support pi

This commit is contained in:
Franklin 2026-02-05 17:06:53 -05:00
parent cc5a9e0d73
commit 843498e9db
41 changed files with 2654 additions and 102 deletions

200
docs/pi-support-plan.md Normal file
View file

@ -0,0 +1,200 @@
# Pi Agent Support Plan (pi-mono)
## Investigation Summary
### Pi CLI modes and RPC protocol
- Pi supports multiple modes including interactive, print/JSON output, RPC, and SDK usage. JSON mode outputs a stream of JSON events suitable for parsing, and RPC mode is intended for programmatic control over stdin/stdout.
- RPC mode is started with `pi --mode rpc` and supports options like `--provider`, `--model`, `--no-session`, and `--session-dir`.
- The RPC protocol is newline-delimited JSON over stdin/stdout:
- Commands are JSON objects written to stdin.
- Responses are JSON objects with `type: "response"` and optional `id`.
- Events are JSON objects without `id`.
- `prompt` can include images using `ImageContent` (base64 or URL) alongside text.
- JSON/print mode (`pi -p` or `pi --print --mode json`) produces JSONL for non-interactive parsing and can resume sessions with a token.
### RPC commands
RPC commands listed in `rpc.md` include:
- `new_session`, `get_state`, `list_sessions`, `delete_session`, `rename_session`, `clear_session`
- `prompt`, `queue_message`, `abort`, `get_queued_messages`
### RPC event types
RPC events listed in `rpc.md` include:
- `agent_start`, `agent_end`
- `turn_start`, `turn_end`
- `message_start`, `message_update`, `message_end`
- `tool_execution_start`, `tool_execution_update`, `tool_execution_end`
- `auto_compaction`, `auto_retry`, `hook_error`
`message_update` uses `assistantMessageEvent` deltas such as:
- `start`, `text_start`, `text_delta`, `text_end`
- `thinking_start`, `thinking_delta`, `thinking_end`
- `toolcall_start`, `toolcall_delta`, `toolcall_end`
- `toolcall_args_start`, `toolcall_args_delta`, `toolcall_args_end`
- `done`, `error`
`tool_execution_update` includes `partialResult`, which is described as accumulated output so far.
### Schema source locations (pi-mono)
RPC types are documented as living in:
- `packages/ai/src/types.ts` (Model types)
- `packages/agent/src/types.ts` (AgentResponse types)
- `packages/coding-agent/src/core/messages.ts` (message types)
- `packages/coding-agent/src/modes/rpc/rpc-types.ts` (RPC protocol types)
### Distribution assets
Pi releases provide platform-specific binaries such as:
- `pi-darwin-arm64`, `pi-darwin-x64`
- `pi-linux-arm64`, `pi-linux-x64`
- `pi-win-x64.zip`
## Integration Decisions
- Follow the OpenCode pattern: a shared long-running process (stdio RPC) with session multiplexing.
- Primary integration path is RPC streaming (`pi --mode rpc`).
- JSON/print mode is a fallback only (diagnostics or non-interactive runs).
- Create sessions via `new_session`; store the returned `sessionId` as `native_session_id`.
- Use `get_state` as a re-sync path after server restarts.
- Use `prompt` for send-message, with optional image content.
- Convert Pi events into universal events; emit daemon synthetic `session.started` on session creation and `session.ended` only on errors/termination.
## Implementation Plan
### 1) Agent Identity + Capabilities
Files:
- `server/packages/agent-management/src/agents.rs`
- `server/packages/sandbox-agent/src/router.rs`
- `docs/cli.mdx`, `docs/conversion.mdx`, `docs/session-transcript-schema.mdx`
- `README.md`, `frontend/packages/website/src/components/FAQ.tsx`
Tasks:
- Add `AgentId::Pi` with string/binary name `"pi"` and parsing rules.
- Add Pi to `all_agents()` and agent lists.
- Define `AgentCapabilities` for Pi:
- `tool_calls=true`, `tool_results=true`
- `text_messages=true`, `streaming_deltas=true`, `item_started=true`
- `reasoning=true` (from `thinking_*` deltas)
- `images=true` (ImageContent in `prompt`)
- `permissions=false`, `questions=false`, `mcp_tools=false`
- `shared_process=true`, `session_lifecycle=false` (no native session events)
- `error_events=true` (hook_error)
- `command_execution=false`, `file_changes=false`, `file_attachments=false`
### 2) Installer and Binary Resolution
Files:
- `server/packages/agent-management/src/agents.rs`
Tasks:
- Add `install_pi()` that:
- Downloads the correct release asset per platform (`pi-<platform>`).
- Handles `.zip` on Windows and raw binaries elsewhere.
- Marks binary executable.
- Add Pi to `AgentManager::install`, `is_installed`, `version`.
- Version detection: try `--version`, `version`, `-V`.
### 3) Schema Extraction for Pi
Files:
- `resources/agent-schemas/src/pi.ts` (new)
- `resources/agent-schemas/src/index.ts`
- `resources/agent-schemas/artifacts/json-schema/pi.json`
- `server/packages/extracted-agent-schemas/build.rs`
- `server/packages/extracted-agent-schemas/src/lib.rs`
Tasks:
- Implement `extractPiSchema()`:
- Download pi-mono sources (zip/tarball) into a temp dir.
- Use `ts-json-schema-generator` against `packages/coding-agent/src/modes/rpc/rpc-types.ts`.
- Include dependent files per `rpc.md` (ai/types, agent/types, core/messages).
- Extract `RpcEvent`, `RpcResponse`, `RpcCommand` unions (exact type names from source).
- Add fallback schema if remote fetch fails (minimal union with event/response fields).
- Wire pi into extractor index and artifact generation.
### 4) Universal Schema Conversion (Pi -> Universal)
Files:
- `server/packages/universal-agent-schema/src/agents/pi.rs` (new)
- `server/packages/universal-agent-schema/src/agents/mod.rs`
- `server/packages/universal-agent-schema/src/lib.rs`
- `server/packages/sandbox-agent/src/router.rs`
Mapping rules:
- `message_start` -> `item.started` (kind=message, role=assistant, native_item_id=messageId)
- `message_update`:
- `text_*` -> `item.delta` (assistant text delta)
- `thinking_*` -> `item.delta` with `ContentPart::Reasoning` (visibility=Private)
- `toolcall_*` and `toolcall_args_*` -> ignore for now (tool_execution_* is authoritative)
- `error` -> `item.completed` with `ItemStatus::Failed` (if no later message_end)
- `message_end` -> `item.completed` (finalize assistant message)
- `tool_execution_start` -> `item.started` (kind=tool_call, ContentPart::ToolCall)
- `tool_execution_update` -> `item.delta` for a synthetic tool_result item:
- Maintain a per-toolCallId buffer to compute delta from accumulated `partialResult`.
- `tool_execution_end` -> `item.completed` (kind=tool_result, output from `result.content`)
- If `isError=true`, set item status to failed.
- `agent_start`, `turn_start`, `turn_end`, `agent_end`, `auto_compaction`, `auto_retry`, `hook_error`:
- Map to `ItemKind::Status` with a label like `pi.agent_start`, `pi.auto_retry`, etc.
- Do not emit `session.ended` for these events.
- If event parsing fails, emit `agent.unparsed` (source=daemon, synthetic=true) and fail tests.
### 5) Shared RPC Server Integration
Files:
- `server/packages/sandbox-agent/src/router.rs`
Tasks:
- Add a new managed stdio server type for Pi, similar to Codex:
- Create `PiServer` struct with:
- stdin sender
- pending request map keyed by request id
- per-session native session id mapping
- Extend `ManagedServerKind` to include Pi.
- Add `ensure_pi_server()` and `spawn_pi_server()` using `pi --mode rpc`.
- Add a `handle_pi_server_output()` loop to parse stdout lines into events/responses.
- Session creation:
- On `create_session`, ensure Pi server is running, send `new_session`, store sessionId.
- Register session with `server_manager.register_session` for native mapping.
- Sending messages:
- Use `prompt` command; include sessionId and optional images.
- Emit synthetic `item.started` only if Pi does not emit `message_start`.
### 6) Router + Streaming Path Changes
Files:
- `server/packages/sandbox-agent/src/router.rs`
Tasks:
- Add Pi handling to:
- `create_session` (new_session)
- `send_message` (prompt)
- `parse_agent_line` (Pi event conversion)
- `agent_modes` (default to `default` unless Pi exposes a mode list)
- `agent_supports_resume` (true if Pi supports session resume)
### 7) Tests
Files:
- `server/packages/sandbox-agent/tests/...`
- `server/packages/universal-agent-schema/tests/...` (if present)
Tasks:
- Unit tests for conversion:
- `message_start/update/end` -> item.started/delta/completed
- `tool_execution_*` -> tool call/result mapping with partialResult delta
- failure -> agent.unparsed
- Integration tests:
- Start Pi RPC server, create session, send prompt, stream events.
- Validate `native_session_id` mapping and event ordering.
- Update HTTP/SSE test coverage to include Pi agent if relevant.
## Risk Areas / Edge Cases
- `tool_execution_update.partialResult` is cumulative; must compute deltas.
- `message_update` may emit `done`/`error` without `message_end`; handle both paths.
- No native session lifecycle events; rely on daemon synthetic events.
- Session recovery after RPC server restart requires `get_state` + re-register sessions.
## Acceptance Criteria
- Pi appears in `/v1/agents`, CLI list, and docs.
- `create_session` returns `native_session_id` from Pi `new_session`.
- Streaming prompt yields universal events with proper ordering:
- message -> item.started/delta/completed
- tool execution -> tool call + tool result
- Tests pass and no synthetic data is used in test fixtures.
## Sources
- https://upd.dev/badlogic/pi-mono/src/commit/d36e0ea07303d8a76d51b4a7bd5f0d6d3c490860/packages/coding-agent/docs/rpc.md
- https://buildwithpi.ai/pi-cli
- https://takopi.dev/docs/pi-cli/
- https://upd.dev/badlogic/pi-mono/releases