feat: add pi as a direct-session provider - #233
Draft
Kunde21 wants to merge 6 commits into
Draft
Conversation
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Register `pi` in `AgentProviderIdV1` and add a `piAgentDir` source variant to `DirectSessionsSource`, then implement the full direct-session provider under `apps/cli/src/backends/pi/directSessions/` and wire it through the backend catalog (`getDirectSessionProviderOps`). Pi sessions are tree-structured JSONL keyed by `id`/`parentId`, so the active branch is resolved by porting pi's own `buildContextEntries`/ `buildSessionPath`/`_buildIndex` tree walk into `piEntryContext.ts` (faithful to the installed binary's `firstKeptEntryId` compaction fold). Paging slices the projected active-branch item list (index cursors) rather than raw bytes, since the tree walk needs the whole file; `older` pages return chronological intra-page order so the shared import orchestrator's page-reversal reconstructs full chronological order. Takeover resumes in place via `pi --session <uuid>` launched from the session's header `cwd` (authoritative; the `--<cwd>--` directory name is not decoded because its encoding collapses both separators and drive colons), with `PI_CODING_AGENT_DIR` pointing at the scanned agent dir. Layer 4 linking (`ensureDirectSessionLink` pi arms) is not yet included; linking works generically today but pi-specific source-key discrimination and the `piSessionId` metadata field remain to be added.
…tity Add pi arms to the four provider-discrimination sites in ensureDirectSessionLink so pi direct sessions link with correct identity: resolveSourceKey produces `piAgentDir:<agentDir>` (was falling to 'unknown', which collided across different PI_CODING_AGENT_DIR scopes), buildDirectSessionMetadata writes `piSessionId`, resolveMetadataRemoteSessionId reads it back, and resolveMarkerProviderId recognizes pi-flavored daemon markers (flavor + backendTarget agentId). The identity-merge path intentionally mirrors Claude (no provider-specific re-sync block); the generic directSessionV1 update handles refresh. With this, pi reaches full direct-session parity with Claude/Codex/OpenCode across discovery, import, follow, takeover spawn, and linking.
…es truncates The backward pager's cursor tracked a `consumed` item count and derived the next page window as `total - consumed - maxItems`. When maxBytes truncated a page below maxItems, the next window overlapped the just-delivered region, producing duplicated/gapped items and out-of-order reconstruction — corrupting imports of any substantial pi session. Fixtures used a large maxBytes so never triggered it. Switch to an `endExclusive` cursor: each page collects newest-first within [endExclusive-maxItems, endExclusive), byte-limit truncates the older end, and the next page window begins exactly where this one stopped. Pages stay gap-free, overlap-free, and reconstruct into full chronological order regardless of truncation. Adds a regression test (maxBytes: 512) that failed before the fix.
validateDirectMachineSource had a closed switch over the provider enum with only codex/claude/opencode arms and a default rejection. Once 'pi' joined AgentProviderIdV1, TypeScript compiled but every pi direct-session RPC request failed at runtime with 'unsupported direct session provider' — a silent daemon->pi wiring break the integration test was written to surface (and did). Add the pi arm mirroring the claude security model: the configured agent dir is daemon-controlled (env PI_CODING_AGENT_DIR or default ~/.pi/agent, resolved via resolvePiAgentDir), a client may omit agentDir, and a supplied agentDir must match the configured dir as a path-traversal guard. Adds owner-level unit coverage for the arm and a new RPC-handler integration test exercising list/page/readAfter through the real catalog + real pi providerOps against a fixture pi session (with an abandoned sibling branch so active-branch selection comes through the RPC stack too).
…daemon RPC Extend the existing auth-gated RPC integration coverage to the pi provider: - link.ensure integration: add a pi case to the mock-server harness, asserting created=true and that the persisted (encrypted) metadata carries providerId='pi', piSessionId, and a piAgentDir source. Adds PI_CODING_AGENT_DIR to the test env scope. - takeover: add a pi case (real catalog + fixture pi session + spawn capture) asserting the spawn options carry the header cwd as directory, resume=<pi session uuid>, builtInAgent pi, transcriptStorage='direct', and PI_CODING_AGENT_DIR env. No production code changed; closes the last unverified RPC wiring paths (link.ensure, takeover) for pi with mocked auth.
Register pi so the UI's direct-session browse picker offers it as a discoverable provider, completing the UI side of the pi direct-session support. - packages/agents manifest: flip pi sessionStorage.direct to true. This is the gate that listDirectBrowseProviderIds (and the new-session / handoff direct-storage flows) check. It is an accurate capability declaration: the daemon already supports pi direct (in-place) session storage via the provider added in the CLI work. - apps/ui: add a pi directSessions.browse capability (order 40) with a resolvePiBrowseSourceOptions resolver returning the piAgentDir source, mirroring the claude/codex/opencode providers. Add the browseSourcePiDefault translation across all locales. - Tests: update resolveDirectBrowseSourceOptions to expect pi in the provider list, and vendorHandoffPolicy to reflect pi's now-true direct storage (swapping the "unsupported direct storage" example to gemini). Broader (intended) effect: pi is now also selectable for direct transcript storage when starting a new session and for direct-storage handoff, matching claude/codex/opencode.
Kunde21
force-pushed
the
pi-direct-sessions
branch
from
August 11, 2026 01:36
3ed24b1 to
c6b1f8a
Compare
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.
Summary
Adds
pi(the@earendil-works/pi-coding-agentharness) as a fourth direct-session provider alongside Claude, Codex, and OpenCode. Pi sessions are tree-structured JSONL on disk, so this mirrors the Claude filesystem model while porting pi's own active-branch resolution so imported transcripts match what a resumed pi session actually sees.Discovery, transcript import/follow, linking, and takeover all resolve through the existing shared seam (
getDirectSessionProviderOps('pi')via the backend catalog), keeping shared orchestration provider-agnostic.Changes
packages/protocol): add'pi'toAgentProviderIdV1and apiAgentDirsource variant toDirectSessionsSource.apps/cli/src/backends/pi/directSessions/): fullDirectSessionProviderOpsimplementation — discovery (cwd-encoded directory scan), paging (whole-file tree-walk → active-branch item-list paging), readAfter/follow, activity, working-directory (from authoritative headercwd), and takeover spawn options (pi --session <uuid>from the session's cwd,PI_CODING_AGENT_DIRenv).backends/pi/index.ts): wiregetDirectSessionProviderOps.ensureDirectSessionLink): pi arms for source-keyed identity (piAgentDir:<agentDir>),piSessionIdmetadata, and pi marker recognition.validateDirectMachineSource): pi arm mirroring Claude's model (daemon-controlled agent dir, client override must match — path-traversal guard).Key implementation notes
buildContextEntries/buildSessionPath/_buildIndex(last-in-file leaf derivation,firstKeptEntryIdcompaction fold) so imports never include abandoned sibling branches or duplicate history. Faithful to the installed binary.endExclusivecursor (collect newest-first, byte-limit truncates the older end) so pages stay gap-free and overlap-free even whenmaxBytestruncates belowmaxItems— reconstructable into full chronological order.pi --session <uuid>(not--fork), launched from the headercwd(authoritative; the--<cwd>--directory name is not decoded since its encoding collapses separators and drive colons).Two bugs found and fixed via testing
consumedcursor caused overlapping windows whenmaxBytestruncated pages → duplicated/gapped, out-of-order imports of any substantial session. Caught by live validation against a real 700-item pi session.validateDirectMachineSourcehad a closedswitchover the provider enum with nopiarm → every pi RPC request rejected at runtime withunsupported direct session provider, despite TypeScript compiling. Caught by an RPC-handler integration test.Testing
~/.pi/agent— discovered 119 sessions, paged a 700-item session across 7 pages (chronological, gap-free, duplicate-free).Out of scope / residual
pi --session <uuid>process spawn was not run against a live daemon+server (needs a running daemon build + server auth). The spawn options are proven correct and match pi's verified resume semantics.Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.Note
Add pi as a direct-session provider with transcript paging, candidate listing, and takeover support
pias a validAgentProviderIdV1and extendsDirectSessionsSourceSchemawith a newpiAgentDirsource kind.piDirectSessionProviderOpsimplementing the fullDirectSessionProviderOpsinterface: listing session candidates, paging transcripts (backward with byte/item limits), tail-reading via polling forward cursor, retrieving activity from file mtime, and resolving spawn options to resume pi in-place.<agentDir>/sessionssubdirectories, extracting UUIDs from JSONL filenames, and sorting by mtime. Candidate listing supports pagination via base64url index cursors and optional title/metadata search.parentIdlinks, handles compaction (firstKeptEntryId), and normalizes entries toDirectTranscriptRawMessageV1with stablepi:<relPath>:<id>identifiers.validateDirectMachineSourceenforces that client-suppliedagentDirmatches the daemon-configured path, mirroring the existing claude policy.Macroscope summarized db3805b. (Automatic summaries will resume when PR exits draft mode or review begins).