Repository navigation
This release is a fidelity pass over the ported runtime: provider adapters, auth flows, session persistence, and agent contracts are realigned with pi as the source of truth.
Tool-call arguments become a parsed JsonObject end to end, pi's upstream contract, instead of a raw JSON string. The ai module ports pi's json-parse (repair, partial-json 0.1.7, re-parse at every streaming delta), every adapter accumulates fragments and finalizes at stop or replay, and the agent fold, JSONL codec, compaction utils, and app UI move to the object shape with it. The adapters are aligned throughout: Anthropic keeps the requested model id, repairs SSE payloads, fails terminally on missing schema-required fields, and throws synchronously on missing auth; OpenAI-completions preserves interleaved text/image order, wires grammar-constrained custom tools, and computes X-Initiator from the transcript; Responses carries supportsStrictMode nullable with per-API defaults (codex/azure true, openai-responses false), while Codex's retry loop, Azure URL rewriting, and header handling follow pi; Google expands systemInstruction, derives x-goog-api-key only when absent, and fails mid-stream on unknown finish reasons; Mistral drops the invented completions bridge and sanitizes streamed text. Models.stream restores pi's lazy-stream contract, where unknown providers, failing auth resolution, and synchronous setup failures surface as a single terminal error event, and the ModelsError taxonomy is back.
The agent and session layers gain pi's steering and follow-up message queues with their drain semantics, poll points, and post-run continuation tail; the composer stays usable while streaming and queued messages render as transient pending rows. AgentSession's event contract is restored — agent_settled, thinking_level_changed, retry-aware AgentEnd.willRetry, and pi's re-emit-before-persist ordering — with run-active state spanning retry backoff and inter-run compaction. Abort semantics follow the abort audit: post-abort threshold compaction really compacts, pre-prompt compaction runs under a tracked child job, a tool-execution abort runs pi's extra turn with the ABORTED finalization, and auth aborts surface as pi's login failures rather than silent cancellation.
Persistence and settings converge on pi's shapes: JSONL uses pi's camelCase stopReason wire values, lenient ECMA-262 timestamps, \n-only splitting, and RawEntry retention for unported entry types; SettingsManager validates compaction budgets lazily at read, persists only modified keys, and models branchSummary; compaction gains pi's compaction-local estimator, where system messages estimate zero and are never cut candidates. Schema-driven validateToolArguments replaces the per-tool hand-rolled checks, and bash timeout validation and enforcement move into the Operations seam like pi's local shell.
Underneath, shared implementations replace the per-site forks: JSON reads and jsonEquals onto one JsonDom surface, WHATWG query parsing and href normalization onto OkHttp's HttpUrl, form encoding onto URLEncoder, Number()/parseFloat semantics onto shared JS-number helpers, retry-after dates onto one lenient parser, and Flow collect-breaks onto truncation operators with both sentinel exceptions deleted. OAuth moves to an OkHttp client with a single whole-exchange deadline, loopback handlers return per-flow error shapes, and the SSE transport takes pi's 300 s idle cap plus full error-body capture so retry classification and error parsing see what pi's adapters see.
On the app side, the transcript becomes an eager Column in a verticalScroll: follow is one snapshotFlow over maxValue, so content growing below the reader can no longer move them, and the LazyList anchoring machinery — TranscriptScrollState, the nested-scroll connection, the sentinel row — is gone.