Improve Pi import follow-ups and add /tree branch navigation#1136
Open
kj1534 wants to merge 8 commits into
Open
Improve Pi import follow-ups and add /tree branch navigation#1136kj1534 wants to merge 8 commits into
kj1534 wants to merge 8 commits into
Conversation
Add process.platform === 'win32' checks for Windows import session path matching
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
This PR adds Pi session import + tree navigation support (including /tree out-of-band navigation), updates command schemas/UI autocomplete to support command argument options, and improves cross-platform path/agent persistence handling.
Changes:
- Add Pi tree navigation (
/tree) via a temporary Pi RPC extension bridge, plus UI autocomplete for selecting tree entries. - Improve agent import/resume logic (reuse stored agent IDs, force timeline hydration) and refresh command lists on timeline epoch resets.
- Harden persistence operations (Windows path comparisons, atomic rename retry, pending-write recovery) and enrich Pi resume metadata (model/thinking).
Reviewed changes
Copilot reviewed 40 out of 40 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| public-docs/supported-providers.md | Documents Pi session import + /tree semantics and /treed exclusion. |
| public-docs/security.md | Adds Pi authentication note. |
| public-docs/cli.md | Documents paseo import usage including Pi JSONL path support. |
| packages/server/src/utils/path.ts | Treats path comparisons as Windows on win32 and for definite Windows paths. |
| packages/server/src/shared/messages.ts | Extends slash command schema with argument options for UI autocomplete. |
| packages/server/src/server/agent/providers/pi/tree-navigation.ts | Implements Pi JSONL parsing and tree-entry listing/feedback formatting. |
| packages/server/src/server/agent/providers/pi/tree-navigation.test.ts | Adds tests for Pi tree listing, labels, parsing, and feedback behavior. |
| packages/server/src/server/agent/providers/pi/test-utils/fake-pi.ts | Adds fake Pi support for tree-nav bridge results and injected prompt failures. |
| packages/server/src/server/agent/providers/pi/session-descriptor.ts | Captures Pi model/thinking metadata from JSONL head/tail for resume/import UI. |
| packages/server/src/server/agent/providers/pi/session-descriptor.test.ts | Tests model/thinking metadata extraction. |
| packages/server/src/server/agent/providers/pi/runtime.ts | Adds --extension support for Pi launches. |
| packages/server/src/server/agent/providers/pi/cli-runtime.test.ts | Tests passing extension paths through the CLI runtime. |
| packages/server/src/server/agent/providers/pi/agent.ts | Loads a temporary Pi extension, adds /tree command options, and out-of-band handling. |
| packages/server/src/server/agent/providers/pi/agent.test.ts | Tests extension injection, persistence metadata, deferred prompt startup, and /tree behavior. |
| packages/server/src/server/agent/provider-registry.ts | Wraps tryHandleOutOfBand so provider events are mapped correctly. |
| packages/server/src/server/agent/import-sessions.ts | Reuses stored agent IDs on re-import, unarchives correctly, forces timeline hydration, applies better titles. |
| packages/server/src/server/agent/import-sessions.test.ts | Tests re-import of closed/archived sessions and forced hydration. |
| packages/server/src/server/agent/agent-storage.ts | Prevents failed writes from poisoning later writes; adds rename retry for transient FS errors. |
| packages/server/src/server/agent/agent-storage.test.ts | Tests recovery after a failed atomic write. |
| packages/server/src/server/agent/agent-sdk-types.ts | Adds command argument options + out-of-band run result type with timeline rehydration support. |
| packages/server/src/server/agent/agent-prompt.ts | Waits for pending out-of-band runs before recording/sending new prompts. |
| packages/server/src/server/agent/agent-manager.ts | Serializes out-of-band runs, supports forced timeline rehydration, keeps persistence/runtime info in sync. |
| packages/server/src/server/agent/agent-manager.test.ts | Adds tests for out-of-band rehydration and foreground/out-of-band ordering. |
| packages/app/src/timeline/session-stream-reducers.ts | Resets timeline on epoch changes and triggers command invalidation side effects. |
| packages/app/src/timeline/session-stream-reducers.test.ts | Tests epoch reset behavior and command invalidation forwarding. |
| packages/app/src/hooks/use-archive-agent.ts | Invalidates recent-provider-sessions cache on archive/close. |
| packages/app/src/hooks/use-archive-agent.test.ts | Tests query invalidation changes. |
| packages/app/src/hooks/use-agent-commands-query.ts | Adds argumentOptions, supports invalidation by root key, configurable staleness. |
| packages/app/src/hooks/use-agent-commands-query.test.ts | Tests invalidating root key refreshes active command queries. |
| packages/app/src/hooks/use-agent-autocomplete.ts | Adds argument autocomplete for slash commands (e.g., /tree <entryId>). |
| packages/app/src/hooks/use-agent-autocomplete.test.ts | Tests /tree argument filtering, ordering preservation, and selection behavior. |
| packages/app/src/contexts/session-context.tsx | Hooks epoch resets to invalidate agent command queries. |
| packages/app/src/components/ui/autocomplete.tsx | Adds stacked layout for non-file options and expands description display. |
| packages/app/src/components/import-session-sheet.tsx | Improves import UI to hide newly imported sessions immediately and update session store. |
| packages/app/src/components/import-session-sheet.test.tsx | Tests Pi provider inclusion and post-import row removal. |
| docs/providers.md | Documents Pi /tree handling via extension bridge and /treed rationale. |
| docs/development.md | Adds Pi session JSONL location/scanning details. |
| docs/architecture.md | Explains Pi out-of-band tree navigation in the architecture docs. |
| .oxfmtrc.json | Extends formatter ignore patterns for AGENTS.md files. |
| .gitattributes | Adds consistent EOL settings and marks AGENTS.md as non-text. |
Comments suppressed due to low confidence (2)
packages/server/src/server/agent/providers/pi/agent.ts:1
- The Pi extension command (
/paseo_tree) accepts a base64 JSON payload that includesresultPath, and it writes to that path without validation. Even though the command is hidden fromlistCommands, a user can still manually invoke/paseo_tree ...and cause arbitrary file writes in their user context. Consider hardening by (mandatory): (1) generating a per-session random command name or including a per-session secret token in the payload and validating it inside the extension, and (2) restrictingresultPathto a Paseo-created temp directory (e.g., reject absolute paths or paths outside the temp dir). Also wrapdecodePayloadin a try/catch so malformed args produce a controlled{ ok: false, error: ... }response rather than throwing before writing a result.
import { randomUUID } from "node:crypto";
packages/server/src/server/agent/providers/pi/tree-navigation.ts:1
readPiTreeEntriesuses synchronous I/O and parses the entire JSONL file, and it’s called by/treelisting and bybuildPiTreeSlashCommand(which is included on everylistCommands()call in the Pi session). For large Pi sessions, this can block the server event loop and make command refresh sluggish. Consider caching parsed results keyed by(sessionFile, mtime)or switching to async streaming reads; additionally, consider early-exiting once enough selectable entries are collected (since the UI caps to 500 options and listing caps to 80).
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| this.pendingWrites.set(agentId, tracked); | ||
| return tracked; | ||
| return next; |
Comment on lines
+356
to
+365
| function hasPersistenceHandleChanged( | ||
| previous: AgentPersistenceHandle | null | undefined, | ||
| next: AgentPersistenceHandle, | ||
| ): boolean { | ||
| return ( | ||
| next.sessionId !== previous?.sessionId || | ||
| next.nativeHandle !== previous?.nativeHandle || | ||
| JSON.stringify(next.metadata ?? {}) !== JSON.stringify(previous?.metadata ?? {}) | ||
| ); | ||
| } |
| } | ||
|
|
||
| if (selected.type === "command_argument") { | ||
| setUserInput(`/${selected.commandName} ${selected.argumentValue}`); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Linked issue
Closes #819
Type of change
What does this PR do
This PR builds on the Pi session import/RPC provider work from #1097. It adds follow-up fixes around that implementation, adds Pi
/treebranch navigation in Paseo, and includes a few shared import/OOB improvements that also benefit other providers.Shared Paseo improvements
Several changes in this PR are implemented in shared Paseo code and are not Pi-only:
sessionIdandnativeHandlein the shared import path.tryHandleOutOfBanda shared ordering guarantee between side-effect commands and normal user turns.tryHandleOutOfBand, so wrapped/custom providers keep OOB command support.Pi import follow-ups
persistence.nativeHandle, so resume/import can reopen the exact native Pi session file./treefeedback/reload behavior.Pi
/treenavigationAdds provider slash-command support for Pi
/tree:/treelists selectable Pi JSONL entries./tree <entryId>runs out-of-band through a temporary internal Paseo Pi extension.ctx.navigateTree(..., { summarize: false }).The user-facing semantics are:
The notice is local to Paseo and is not written into the Pi session JSONL. The selected tree point is pending until the next normal message creates a new Pi JSONL entry; if the user reloads the agent before sending that message, Paseo may resume Pi's persisted leaf and clear the pending selection.
/treeautocomplete UX•current branch,●current leaf,↳non-current branch entry,○non-current branch body, and capped┊depth tracks./treetimeline rehydrate/new epoch so the current marker updates after navigation./treed/treedis intentionally not exposed as a Paseo app command./treedis a third-party Pi tree-delete extension whose useful actions depend on highlighted-entry keyboard shortcuts in Pi's terminal UI. Paseo cannot pass those interactive delete actions as command arguments, so users are directed to usepi resumein a terminal when they need/treed.Docs
Adds and updates docs for:
/treebranch navigation behavior./treeguidance./treedlimitations.Additional commits included
This PR also includes two small supporting commits:
fbcbdaband4bfa399supplements the previous Windows session import path fix. It tightens path equivalence behavior for Windows import/session matching edge cases that were missed when the earlier PR was conflict-resolved.1cd0b53adds repository line-ending normalization:.gitattributesHow did you verify it
Automated validation run locally after rebasing onto latest
upstream/main:Result:
Also run:
Manual validation:
/treeto select user entries and create sibling branches./treeto select assistant entries and continue from that assistant response./treecurrent marker refresh behavior after command-cache invalidation changes.Checklist
npm run typecheckpassesnpm run lintpassesnpm run formatran (Biome)