packages/agent
August 31, 2026 ยท View on GitHub
@earendil-works/pi-agent-core provides the stateful agent loop and a publicly exported optional harness for compaction, sessions, skills, prompts, and execution environments.
STRUCTURE
src/agent.ts Agent state, prompt queue, subscriptions, abort
src/agent-loop.ts Provider/tool loop, scheduling, cursor-exec bridging
src/assistant-terminal-state.ts Terminal-state classification for assistant turns
src/empty-assistant-recovery.ts Recovery for empty assistant responses
src/stream-fn.ts Injectable stream function abstraction
src/types.ts App messages, events, state, conversion boundary
src/proxy.ts Remote stream proxy
src/index.ts Browser-safe public exports
src/node.ts Node harness public exports
src/search/ Scanning session search over readable storage
src/harness/ AgentHarness: lanes, sessions (own AGENTS.md),
tools (own AGENTS.md), compaction, skills, prompt
templates, env adapters
src/harness/reducer.ts Record-log validation and lane state reduction
src/harness/telemetry.ts Schema-first AI/harness telemetry spans
src/harness/messages.ts Harness message helpers
src/harness/prompt-templates.ts Prompt template expansion
src/harness/system-prompt.ts System prompt assembly
src/harness/skills.ts Skill discovery and loading
src/changes.md Fork-specific behavior record
scripts/generate-telemetry-docs.ts Regenerates docs/telemetry-schema.md
WHERE TO LOOK
| Task | File |
|---|---|
| Tool scheduling or terminal states | src/agent-loop.ts |
| Agent lifecycle or abort | src/agent.ts |
| Public message/event contract | src/types.ts |
| Harness orchestration | src/harness/agent-harness.ts |
| Node process and filesystem behavior | src/harness/env/nodejs.ts |
| Session persistence | src/harness/session/ (session.ts, state.ts, context.ts, types.ts, jsonl/, memory.ts; own AGENTS.md) |
| Session search | src/search/scanning.ts, contracts in src/search/index.ts; see docs/search.md |
| Built-in tool behavior | src/harness/tools/ (own AGENTS.md) |
| SQLite session storage | packages/session-backends/sqlite-node (@earendil-works/pi-storage-sqlite-node) |
| Compaction | src/harness/compaction/ |
INVARIANTS
- Keep
AgentMessageas app state and convert to the AI packageMessageonly throughconvertToLlm. - Core files
agent.ts,agent-loop.ts, andtypes.tsremain browser-safe; Node filesystem/process behavior belongs behindsrc/node.tsandsrc/harness/env/. - Tool preparation/finalization may complete concurrently, but returned
toolResultsremain in assistant source order. - The active run owns idle-timeout and abort cleanup. Abort produces terminal behavior once; do not emit or settle a run twice.
- Subscribers receive events; messages remain state. Preserve discriminated streaming event shapes.
- Keep harness interfaces injectable so tests can use memory storage and fake execution environments.
ANTI-PATTERNS
- Sequentializing independent tool calls.
- Importing Node-only modules into browser-safe entry points.
- Storing provider-shaped messages directly as app state.
- Adding harness behavior without exporting and documenting the matching public surface.
VALIDATION
- Run
bun run testfrom this package for agent-loop coverage. - Run
bun run test:harnessfor harness/session/env changes. - Telemetry schema changes:
bun run generate-telemetry-docsto rewritedocs/telemetry-schema.md, thenbun run check:telemetry-docs; the generated file must never be edited by hand. - Runtime changes also require root
bun run checkand the root QA evidence gate. - Keep
README.md,docs/harness.md,docs/search.md, andsrc/changes.mdaligned with public or fork-specific changes.
NOTES
- Session storage:
SessionStorageimplementations (jsonl/JsonlSessionStorage/JsonlSessionRepo,memory.tsInMemorySessionStorage/InMemorySessionRepo) behindSessiontree semantics insession.ts; SQLite backend inpackages/session-backends/sqlite-node. New backends must passcreateSessionBackendConformance, published as the@earendil-works/pi-agent-core/session/testingsubpath. - Cursor exec bridging:
execHandlers/onToolResultare installed only whenconfig.cursorExecHandlersis set. AssistanttoolCallblocks stampedkCursorExecResolved(packages/ai/src/utils/block-symbols.ts) were executed server-side and are never re-run locally; their bufferedtoolResults are appended right after the assistant message, including on error/abort paths. Local exec work re-arms the idle watchdog viaAssistantMessageEventStream.trackLocalWork.
Generated: 2026-08-24 | Commit baf15a54d