sandbox-agent/docs/pi-support-plan.md
2026-02-05 17:06:53 -05:00

9.1 KiB

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