You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Build order reminder: docs/agents/implementation-handoff.md
Problem Statement
Developers want a daily-driver interactive coding agent in Python that matches the semantics and extension model of earendil-works/pi, without depending on the TypeScript runtime or chasing full API/session-file parity. Today this repo has settled decisions and research notes but no runnable packages: no thin LLM adapter, no agent runtime, no TUI, and no piy CLI.
Solution
Ship a uv monorepo with four installable packages — pi_llm, pi_agent, pi_tui, pi_coding_agent — that together deliver:
A thin LiteLLM-backed LLM adapter (OpenAI Chat Completions contract only).
An agent runtime with a public loop + stateful Agent SDK surface.
Own-format session persistence with resume/branch/fork and compaction.
A Textual interactive CLI (piy) wired from runtime events to widgets.
Behavior aligns with upstream where decisions say so; public APIs are idiomatic Python. Orchestrator/chat, themes/packages marketplace, print/JSON/RPC modes, OAuth, and built-in sandbox stay out of v1.
User Stories
As a Python developer, I want a uv workspace with four packages and CI (ruff + typecheck + pytest), so that I can develop and merge package work safely.
As an embedder, I want pi_llm to call models via LiteLLM acompletion with modern tools / tool_choice, so that I do not maintain a provider matrix.
As a TUI user, I want streamed assistant tokens for UI updates, so that responses feel live.
As the agent runtime, I want tool calls assembled fully before execution, so that tools run against complete arguments.
As an operator, I want capability probes and OpenAI-mapped errors from pi_llm, so that unsupported features and auth failures are actionable.
As a user, I want credentials resolved env-first then optional ~/.pi/agent/auth.json, so that CI and local setups both work.
As an interactive piy user, I want a prompt-and-save path for missing keys, so that first-run setup does not require editing files by hand.
As an SDK user, I want a pure agent loop I can drive myself, so that I can embed turn mechanics without the stateful facade.
As an SDK user, I want a stateful Agent with prompt / continue / steer / follow_up, so that I can run multi-turn sessions from Python.
As an SDK user, I want awaited subscribe as the event settlement barrier, so that my handler finishes before the runtime advances.
As a subscriber, I want the full agent/turn/message/tool event set in a fixed order, so that UIs can update incrementally and deterministically.
As an SDK user, I want AgentMessage in the transcript and LLM Message only at stream time, so that UI/custom roles never leak unprojected into the model.
As an SDK user, I want transform_context / convert_to_llm hooks, so that I can reshape context before the model call.
As an SDK user, I want to inject the stream function from pi_llm, so that the runtime stays provider-agnostic.
As a tool author, I want before/after tool hooks under parallel or sequential batching, so that I can gate or observe tool execution.
As a coding-agent user, I want built-in read with line windowing and truncation, so that large files do not blow the context.
As a coding-agent user, I want built-in write for whole-file writes, so that create/overwrite is simple and reliable.
As a coding-agent user, I want built-in edit with exact multi-replace edits[] and optional per-edit replace_all, so that surgical edits are deterministic.
As a coding-agent user, I want edit to be all-or-nothing with uniqueness/non-overlap checks against the original file, so that partial/ambiguous edits fail closed.
As a coding-agent user, I want edit and write to share a per-realpath queue, so that concurrent file mutations serialize safely.
As a coding-agent user, I want soft guidance that the model read before edit, so that edits are grounded without hard-enforcing a protocol.
As a coding-agent user, I want built-in bash with session cwd, optional timeout, and output truncation, so that shell work stays usable and bounded.
As a coding-agent user, I want tool errors that are actionable for the model/UI without Python tracebacks, so that the agent can recover.
As a coding-agent user, I want host process permissions (no built-in sandbox), so that v1 matches the upstream security stance.
As a user, I want Skills discovered from ~/.pi/agent, trusted .pi, ~/.agents/skills, and ancestor .agents/skills, so that shared and project skills both appear.
As a user, I want Skills as SKILL.md + YAML frontmatter directories listed in a catalog and readable on demand, so that prompts stay small until needed.
As a user, I want Prompt Templates as non-recursive prompts/*.md expanded via /name with upstream-style placeholders, so that slash commands work familiarly.
As a user, I want settings nested-merge from ~/.pi/agent/settings.json and .pi/settings.json, so that project overrides are predictable.
As a user, I want v1 settings keys skills / prompts / defaultProjectTrust / enableSkillCommands (plus compaction reserve/keepRecent as decided), so that discovery and compaction are configurable.
As a user, I want project trust gated via ~/.pi/agent/trust.json, so that untrusted project resources are not loaded silently.
As an interactive user, I want to be asked about trust; as a non-interactive user, I want project resources skipped unless already trusted or --approve, so that automation stays safe by default.
As a user, I want AGENTS.md / CLAUDE.md (and peers) walked from ancestors into <project_context>, so that the model sees repo guidance.
As a user, I want sessions stored as own JSONL (header version + message tree) under ~/.pi/agent/sessions/<cwd-encoded>/, so that work is resumable per project.
As a user, I want Session to own the file/branch pointer and Agent to own the live transcript, so that persistence and runtime stay cleanly separated.
As a user, I want resume / list / branch / fork, so that I can continue or diverge conversations.
As a user, I want auto compaction near the context window and manual /compact [instructions], so that long sessions keep working.
As a user, I want compaction written as a JSONL compaction entry without rewriting away history, so that the file tree remains auditable.
As a model consumer after compaction, I want summary + recent tail only, so that the prompt fits the window.
As a TUI user, I want a scrollable transcript, streaming assistant text, tool-call display, and a multiline editor, so that interactive coding feels complete for v1.
As a TUI user, I want widgets updated from agent runtime events (not raw LiteLLM streams), so that UI stays consistent with SDK semantics.
As a package consumer, I want reusable Textual widgets/layouts in pi_tui and wiring/piy in pi_coding_agent, so that UI pieces stay reusable.
As a CI maintainer, I want pytest with recorded LLM chunk fixtures and no required live LLM, so that merges do not depend on external APIs.
As a CI maintainer, I want light Textual pilot tests, so that basic UI wiring regresses loudly without pixel goldens.
As a developer, I want design alignment with upstream semantics without TypeScript API or session interchange, so that the Python API can stay idiomatic.
Implementation Decisions
Packages / layout: packages/pi_llm, packages/pi_agent, packages/pi_tui, packages/pi_coding_agent (src layout) in a uv workspace; CLI entrypoint piy from pi_coding_agent.
pi_llm: Depend only on LiteLLM’s OpenAI Chat Completions path (acompletion, modern tools/tool_choice). Stream for UI; assemble-then-execute for tools; capability probes; map errors to an OpenAI-shaped surface. No Proxy/Router/functions=/add_function_to_prompt. Credentials: env first, then optional ~/.pi/agent/auth.json. Resolution lives in pi_llm; interactive prompt-and-save UX lives in piy (not inside pi_llm).
pi_agent public surface: Dual export — pure agent loop + stateful Agent. Agent owns transcript/tools/queues; methods prompt / continue / steer / follow_up; no concurrent prompt. Awaited ordered subscribe is the settlement barrier. Full agent/turn/message/tool event sequence as researched upstream. AgentMessage vs LLM Message with projection only at stream time via transform_context → convert_to_llm. Tool contract includes before/after hooks and parallel|sequential batching. Stream function injected from pi_llm.
Built-in tools (implemented in coding-agent, registered on Agent):
read: line window + truncation.
write: whole-file write.
edit: exact multi-replace edits[], optional per-edit replace_all; relative to original file; unique/non-overlapping; all-or-nothing; shares per-realpath queue with write; soft read-before-edit guidance; diff/patch may appear in details, not as the primary edit API.
Settings: nested merge of ~/.pi/agent/settings.json overlaid by .pi/settings.json. v1 recognized keys include skills, prompts, defaultProjectTrust, enableSkillCommands, plus compaction-related reserve/keepRecent overrides as decided.
Project trust: decisions in ~/.pi/agent/trust.json; interactive prompt; non-interactive default deny unless trusted or --approve.
Context files: per-directory prefer AGENTS.md else CLAUDE.md (and settled peers); ancestor walk → <project_context> in system prompt.
Session: own JSONL (version header + message tree) under ~/.pi/agent/sessions/<cwd-encoded>/. Session owns file + branch pointer; Agent owns transcript; coding-agent wires persistence. Capabilities: resume/list/branch/fork. No upstream session interchange.
Compaction: auto when approximate contextTokens > contextWindow - reserveTokens; keepRecentTokens for retained tail; manual /compact [instructions]; append compaction entry (do not rewrite away history); model context = summary + kept recent messages; branch summarization deferred.
pi_tui: Textual widgets/layouts for transcript, streaming assistant, tool display, editor. Event-driven incremental updates. No custom differential rendering engine; no themes in v1.
piy wiring: in pi_coding_agent; maps runtime events → widgets; owns auth prompt-and-save and trust prompts.
Research anchors: docs/research/upstream-agent-core.md, docs/research/upstream-coding-agent-extensibility.md, docs/research/litellm-streaming-tools.md, docs/research/edit-tool-designs.md.
Testing Decisions
What makes a good test: assert external behavior at package seams; do not lock internal file layout or private helpers. Prefer fakes/fixtures over live network.
Primary seams (approved):
pi_llm stream boundary with recorded/handwritten chunks (no live API in CI).
Agent / loop public surface with injected fake StreamFn — the thickest seam.
Built-in tools against temporary directories.
Resource discovery + settings/trust against fake HOME + project roots.
Session + compaction against a temporary session tree.
Built-in permission/sandbox system (host permissions; external containerization if needed)
Branch summarization on tree navigation (deferred past compaction v1)
Pixel-perfect upstream TUI parity or custom differential renderer
Further Notes
Domain vocabulary must follow CONTEXT.md; do not re-litigate closed map tickets unless the destination changes.
Issue Handoff: implement v1 Python pi harness #17 remains the implementation handoff umbrella; this spec is the buildable collapse of map decisions for /to-tickets and /implement.
Tracer-bullet tickets should stay vertical and session-sized; work the frontier (unblocked tickets) one fresh context at a time via /implement.
Parent
CONTEXT.mddocs/agents/implementation-handoff.mdProblem Statement
Developers want a daily-driver interactive coding agent in Python that matches the semantics and extension model of earendil-works/pi, without depending on the TypeScript runtime or chasing full API/session-file parity. Today this repo has settled decisions and research notes but no runnable packages: no thin LLM adapter, no agent runtime, no TUI, and no
piyCLI.Solution
Ship a
uvmonorepo with four installable packages —pi_llm,pi_agent,pi_tui,pi_coding_agent— that together deliver:AgentSDK surface.read/write/edit/bash) and v1 extension discovery (skills, prompt templates, settings, trust, context files).piy) wired from runtime events to widgets.Behavior aligns with upstream where decisions say so; public APIs are idiomatic Python. Orchestrator/chat, themes/packages marketplace, print/JSON/RPC modes, OAuth, and built-in sandbox stay out of v1.
User Stories
uvworkspace with four packages and CI (ruff + typecheck + pytest), so that I can develop and merge package work safely.pi_llmto call models via LiteLLMacompletionwith moderntools/tool_choice, so that I do not maintain a provider matrix.pi_llm, so that unsupported features and auth failures are actionable.~/.pi/agent/auth.json, so that CI and local setups both work.piyuser, I want a prompt-and-save path for missing keys, so that first-run setup does not require editing files by hand.Agentwithprompt/continue/steer/follow_up, so that I can run multi-turn sessions from Python.subscribeas the event settlement barrier, so that my handler finishes before the runtime advances.transform_context/convert_to_llmhooks, so that I can reshape context before the model call.pi_llm, so that the runtime stays provider-agnostic.readwith line windowing and truncation, so that large files do not blow the context.writefor whole-file writes, so that create/overwrite is simple and reliable.editwith exact multi-replaceedits[]and optional per-editreplace_all, so that surgical edits are deterministic.editto be all-or-nothing with uniqueness/non-overlap checks against the original file, so that partial/ambiguous edits fail closed.editandwriteto share a per-realpath queue, so that concurrent file mutations serialize safely.readbeforeedit, so that edits are grounded without hard-enforcing a protocol.bashwith session cwd, optional timeout, and output truncation, so that shell work stays usable and bounded.~/.pi/agent, trusted.pi,~/.agents/skills, and ancestor.agents/skills, so that shared and project skills both appear.SKILL.md+ YAML frontmatter directories listed in a catalog and readable on demand, so that prompts stay small until needed.prompts/*.mdexpanded via/namewith upstream-style placeholders, so that slash commands work familiarly.~/.pi/agent/settings.jsonand.pi/settings.json, so that project overrides are predictable.skills/prompts/defaultProjectTrust/enableSkillCommands(plus compaction reserve/keepRecent as decided), so that discovery and compaction are configurable.~/.pi/agent/trust.json, so that untrusted project resources are not loaded silently.--approve, so that automation stays safe by default.<project_context>, so that the model sees repo guidance.version+ message tree) under~/.pi/agent/sessions/<cwd-encoded>/, so that work is resumable per project./compact [instructions], so that long sessions keep working.compactionentry without rewriting away history, so that the file tree remains auditable.pi_tuiand wiring/piyinpi_coding_agent, so that UI pieces stay reusable.Implementation Decisions
packages/pi_llm,packages/pi_agent,packages/pi_tui,packages/pi_coding_agent(src layout) in auvworkspace; CLI entrypointpiyfrompi_coding_agent.pi_llm: Depend only on LiteLLM’s OpenAI Chat Completions path (acompletion, moderntools/tool_choice). Stream for UI; assemble-then-execute for tools; capability probes; map errors to an OpenAI-shaped surface. No Proxy/Router/functions=/add_function_to_prompt. Credentials: env first, then optional~/.pi/agent/auth.json. Resolution lives inpi_llm; interactive prompt-and-save UX lives inpiy(not insidepi_llm).pi_agentpublic surface: Dual export — pure agent loop + statefulAgent.Agentowns transcript/tools/queues; methodsprompt/continue/steer/follow_up; no concurrentprompt. Awaited orderedsubscribeis the settlement barrier. Full agent/turn/message/tool event sequence as researched upstream. AgentMessage vs LLM Message with projection only at stream time viatransform_context→convert_to_llm. Tool contract includes before/after hooks and parallel|sequential batching. Stream function injected frompi_llm.Agent):read: line window + truncation.write: whole-file write.edit: exact multi-replaceedits[], optional per-editreplace_all; relative to original file; unique/non-overlapping; all-or-nothing; shares per-realpath queue withwrite; soft read-before-edit guidance; diff/patch may appear in details, not as the primary edit API.bash: session cwd, optional timeout, output truncation, no sandbox; host permissions.~/.pi/agent/and project.pi/(project side behind trust); Skills also~/.agents/skills/and ancestor.agents/skills/; settings path arrays + CLI add/disable.SKILL.md+ YAML frontmatter); prompts non-recursive*.md, filename =/name, upstream-style placeholders.~/.pi/agent/settings.jsonoverlaid by.pi/settings.json. v1 recognized keys includeskills,prompts,defaultProjectTrust,enableSkillCommands, plus compaction-related reserve/keepRecent overrides as decided.~/.pi/agent/trust.json; interactive prompt; non-interactive default deny unless trusted or--approve.AGENTS.mdelseCLAUDE.md(and settled peers); ancestor walk →<project_context>in system prompt.versionheader + message tree) under~/.pi/agent/sessions/<cwd-encoded>/. Session owns file + branch pointer; Agent owns transcript; coding-agent wires persistence. Capabilities: resume/list/branch/fork. No upstream session interchange.contextTokens > contextWindow - reserveTokens;keepRecentTokensfor retained tail; manual/compact [instructions]; appendcompactionentry (do not rewrite away history); model context = summary + kept recent messages; branch summarization deferred.pi_tui: Textual widgets/layouts for transcript, streaming assistant, tool display, editor. Event-driven incremental updates. No custom differential rendering engine; no themes in v1.piywiring: inpi_coding_agent; maps runtime events → widgets; owns auth prompt-and-save and trust prompts.pi_llm→pi_agent→ built-in tools → resources/settings/trust/context → session/compaction →pi_tui+piywiring.docs/research/upstream-agent-core.md,docs/research/upstream-coding-agent-extensibility.md,docs/research/litellm-streaming-tools.md,docs/research/edit-tool-designs.md.Testing Decisions
pi_llmstream boundary with recorded/handwritten chunks (no live API in CI).Agent/ loop public surface with injected fake StreamFn — the thickest seam.piyintegration (optional, few): fake LLM + temp dirs proving the interactive main path wires together.piywiring tests;pi_tuiowns widget pilots.uvinstall/sync, ruff, typecheck, pytest. Live LLM not required to merge.Out of Scope
orchestratorandpi-chatpi-ai(aggregation library only)Further Notes
CONTEXT.md; do not re-litigate closed map tickets unless the destination changes./to-ticketsand/implement./implement.