Commit graph

458 commits

Author SHA1 Message Date
Mario Zechner
6536f80129 feat(ai,agent,coding-agent): validate tool arguments with pi-schema, drop TypeBox
pi-schema: opt-in coercion, compile(schema, { coerce: true }) with coerce() and
parse(), the superset of TypeBox's Value.Convert rules and pi-ai's old coercion;
unresolvedRefs option; url and json-pointer-uri-fragment formats.
pi-ai: Tool takes any JSON Schema; validation through pi-schema; Type, Static
and TSchema are no longer exported (breaking). pi-agent-core and pi-durable:
tools on pi-schema, no TypeBox dependency. Coding agent: extensions keep Type,
Static, TSchema and StringEnum through an extension view of pi-ai; built-in
tools stay on TypeBox.
2026-11-01 10:08:42 +00:00
Mario Zechner
f715a15c10 fix(ai,chord,durable,coding-agent): parse streamed tool-call arguments incrementally (fixes #9265)
- ai: StreamingJsonParser / ToolCallArgumentsStream read each argument delta once (tolerant,
  immutable snapshots, linear cost); every provider, pi-messages and the faux provider use it
  and keep stream state (partialJson, partialArgs, index, customInput, streamIndex, Bedrock
  reasoning bytes) off the content blocks; grammar tool input appends per delta
- agent: streamProxy uses the same parser
- chord: Delta append ops own their text (ownedSlice), so ops and replicas no longer keep the
  whole growing string alive
- durable, ai, mcp: bounded error excerpts and summaries own their characters
- coding-agent: tool calls render streamed arguments once per frame, not once per delta
2026-10-24 08:00:07 +00:00
Mario Zechner
04a93bad8f fix(ai,agent,coding-agent,durable): client identity follow-ups
- ClientAttribution is { name, url, categories? } with required name and url, so
  OpenRouter always gets an HTTP-Referer. identity.ts maps the fields to each
  provider's headers; NVIDIA gets the name with its first letter upper-cased.
  attribution: null turns it off. PI_ATTRIBUTION is pi's, including the
  cli-agent category; agent-core, durable, and the coding agent use it.
- Categories are a string array, joined for OpenRouter.
- withClientIdentity() is a typed wrapper instead of a Proxy and keeps a
  MutableModels mutable. Durable no longer caches wrappers in a WeakMap.
- The Codex originator stays pi; login agentName no longer follows attribution.
- Models and the coding agent's ModelRuntime add x-opencode-session for custom
  providers pointing at OpenCode, replacing the coding agent's transformHeaders.
2026-10-21 11:18:16 +00:00
Armin Ronacher
adc5fa9f80 feat(ai,agent,coding-agent): move client identity and provider attribution into pi-ai
pi-ai gets a ClientIdentity request option and createModels() default that choose the User-Agent (detailed with version, short, or custom) and provider attribution headers for OpenRouter, NVIDIA NIM, and OpenCode. Attribution is off by default in pi-ai and on by default in pi-agent-core and pi-durable (HarnessOptions.identity). pi-coding-agent sets its identity from the telemetry setting instead of adding headers itself.
2026-10-21 11:17:02 +00:00
Mario Zechner
f284a2460c fix(ai): time responses with private fields; use the real stream in proxy and test mocks
Replaces the WeakMap workaround. streamProxy and the agent and coding-agent test
mocks reimplemented AssistantMessageEventStream as plain EventStream subclasses;
they now use createAssistantMessageEventStream().
2026-10-06 20:26:27 +02:00
Mario Zechner
36a686ee8d feat: record response, tool execution, and durable task times
pi-ai's AssistantMessageEventStream sets AssistantMessage.durationMs with a
monotonic clock for every API implementation. The agent loop and the durable
tool task set ToolResultMessage.durationMs around execute(). Durable task
records carry startedAt/endedAt stamped by the Session. The coding agent's bash
renderer shows Took from the recorded duration, also after a reload.

closes #10549
2026-10-06 19:28:54 +02:00
Mario Zechner
7fd478a2e8 feat(agent): remove the experimental harness from pi-agent-core
pi-agent-core now contains only Agent, the agent loop, the proxy stream, and
their types. Removed the harness, sessions and session storage, pico3, harness
tools, compaction, skills, prompt templates, telemetry schemas, search types,
and the uuidv7 and pi-telemetry re-exports, plus the ./node, ./harness/* and
./experimental/pico3 subpath exports. Durable sessions live in
@earendil-works/pi-durable.

Also removed packages/session-backends and the experimental mini and micro
coding-agent frontends, with their scripts and build configuration.
2026-10-01 14:45:01 +02:00
Armin Ronacher
8562bcf66a feat(coding-agent): codemode and MCP
This adds codemode and MCP support to pi. Codemode (packages/codemode) runs
model-written JavaScript in a QuickJS wasm VM inside a worker. From there the
script calls pi's tools as async functions, uses a per-session store, and can
read the model catalog and run classifiers. The codemode tool in coding-agent
is compatible with Codex's exec tool, and codemode.mode works like Codex's
tool modes (on or only). Large results are written to a JSON temp file. MCP
(packages/mcp) is a standalone client for stdio and streamable HTTP servers,
with OAuth.

The core only gets general mechanisms; codemode, tool_search and MCP are
built-in extensions that use them. Other extensions can replace these
built-ins. Tools declare an exposure: direct, model-only, codemode, deferred
or hidden. prepareLoadout() lets an orchestrating tool change which tool
declarations the model sees. ctx.executeTool() runs nested calls through
validation and the tool_call/tool_result hooks. Those calls emit events with
parentToolCallId and are recorded as bounded nestedCalls on the parent
result, which compaction and HTML export use. Tools can also return
structuredContent with an outputSchema, and can report errors with isError
instead of throwing. MCP servers come from mcp.json (global, or per project
after the project is trusted) or from pi.registerMcpServer(). They are
managed with /mcp and pi mcp list|login|logout, and their runtimes load on
first use.

Closes #10040
2026-09-29 09:12:50 +02:00
Armin Ronacher
540e174c72
feat(coding-agent): Virtual models (#10035)
This adds experimental support for virtual models. A virtual model is a catalog entry that an extension registers with pi.registerVirtualModel(). It does not talk to a provider itself; for every request it picks a physical model and thinking level. The motivation is to make routing policies pluggable: plan on a strong model and implement on a cheap one, pick a model with a classifier, or move to a larger window when the context grows. Today this needs model switching by hand or hacks in prepareRequest.

The selection stays virtual: model_change records it, resume restores it, and each response records the physical model and thinking level that produced it. Router state can be stored on the session branch, so it follows /tree and forks and survives compaction. Context limits, compaction and image sizing use the physical model a request was routed to. examples/extensions/jev-router.ts shows a full router that uses the Jev classifier to pick Sol or Terra for planning and hands off to Luna after the first edit. docs/virtual-models.md describes the API.
2026-09-28 23:30:45 +02:00
Mario Zechner
d5cba1d97c feat(chord): make immutable delta tracker canonical
Replace the alternate tracker implementations with the optimized immutable overlay, validate draft placements as strict JSON, and document the ownership contract. Consolidate tracker tests and benchmarks around the canonical implementation.
2026-09-24 15:07:12 +02:00
David Brailovsky
002fc83852
feat: expose provider stream events to extensions (#9901)
Add onProviderStreamEvent through pi-ai and agent core, and surface
provider_stream_event to coding-agent extensions.

Closes #9784
2026-09-23 16:03:30 +02:00
Mario Zechner
9a139c62bf feat(chord): consolidate immutable delta tracking 2026-09-23 02:22:52 +02:00
Mario Zechner
466db0fecd feat: add canonical session context boundaries
Make SessionManager projections authoritative for provider requests, add append-only context edits and actionable turn boundaries, and preserve existing queue scheduling during continuation and recovery.
2026-09-21 16:59:20 +02:00
Mario Zechner
10d1ad621f feat: add transactional replicated state 2026-09-21 16:07:59 +02:00
David Brailovsky
47a18e37b1 fix: require complete GIF image signatures
Require GIF87a or GIF89a headers to avoid classifying text files beginning with GIF as images.

Fixes #9755
2026-09-21 10:30:42 +02:00
Mario Zechner
0801601621 feat(durable): move Pico into dedicated package 2026-09-18 13:39:09 +02:00
Mario Zechner
cf8d5fac30 feat(agent): add Pico storage foundation 2026-09-18 12:32:00 +02:00
Mario Zechner
01528e2094 Merge remote-tracking branch 'origin/main' into pico 2026-09-16 17:58:54 +02:00
Armin Ronacher
9e05370b29
Mid conversation system messages (#9548)
This change makes system prompt text and tool changes part of the transcript rather than silently rewriting its starting conditions. This lets Pi record when instructions changed or tools became available, restore that state after resuming or navigating branches, and preserve cached prompt prefixes where the upstream supports it.
2026-09-16 15:54:07 +02:00
Mario Zechner
56cd5989ea docs(agent): replace obsolete Pico prototypes with Pico5 design 2026-09-15 11:27:53 +02:00
Mario Zechner
46b66c59af feat(agent): add hardened pico3 kernel 2026-09-14 11:17:04 +02:00
Mario Zechner
51f3090790 feat(agent): align pico foundation with v2 contract 2026-09-13 04:00:27 +02:00
Mario Zechner
df484f2775 feat(agent): add pico memory storage foundation 2026-09-12 22:31:41 +02:00
Mario Zechner
1915b35a9b feat(agent): refine pico core task capabilities 2026-09-12 22:31:16 +02:00
Mario Zechner
f467cf7068 feat(agent): add pico compile-time foundation 2026-09-12 00:02:58 +02:00
David Brailovsky
c37b0e03b5 fix: cap agent retry backoff
Add a configurable 60-second default cap for assistant and summarization retry delays across coding-agent and the agent harness.

Fixes #8826
2026-09-09 11:54:56 +02:00
David Brailovsky
41218b3940 fix(agent): relax fork lane validation and sequence conformance 2026-09-08 13:34:58 +02:00
David Brailovsky
6dfc66d32a feat(agent): stream legacy JSONL migration and forks
Stream legacy v3 normalization through repeatable file passes, reuse atomic JSONL publication, and preserve stable fork IDs without an intermediate v4 source file.
2026-09-07 12:48:08 +02:00
David Brailovsky
85186f823d fix(agent): expand fork conformance for Memory and JSONL
- Cover application list copying and branch-state exclusion
- Verify sequence preservation and next-write allocation
- Group WP08 cases separately until SQLite is ready
2026-09-04 22:45:31 +02:00
David Brailovsky
9908b2176a feat(agent): fork closed legacy JSONL through format 4
Normalize closed v3 sources into temporary format-4 files and reuse the two-pass fork path without modifying source files.

Remove obsolete JSONL snapshot creation and capture plumbing.
2026-09-04 17:40:30 +02:00
David Brailovsky
e3c966b6ff fix(agent): reject open legacy JSONL forks
Require a non-empty commit to persist normalized format-4 IDs before forking an open v3 session.

Verify rejection leaves the source unchanged and that the same destination ID succeeds after upgrade.
2026-09-04 16:46:14 +02:00
David Brailovsky
89670bc4a6 fix(agent): reduce JSONL fork list index memory
Track only the first surviving append sequence per non-empty list instead of retaining every surviving element sequence.
2026-09-04 16:44:13 +02:00
David Brailovsky
9ee703230f Merge remote-tracking branch 'origin/main' into dev-named-forks-streaming 2026-09-04 16:05:40 +02:00
David Brailovsky
04d17a1080 feat(agent): add two-pass JSONL fork prototype
Stream format-4 sources through current-state indexes, preserve source sequences and high-water marks, and publish destinations atomically.

Capture open-source fork boundaries through the commit queue while retaining snapshot-based legacy-v3 handling.
2026-09-04 16:05:22 +02:00
Qiaochu Hu
c2d3dc55b0
fix(agent): map signal-killed processes to non-zero exit codes (#8994)
waitForChildProcess resolved null for the exit code when a child was killed by a signal (e.g. OOM killer), and exec mapped it with code ?? 0, so the bash tool treated killed commands as successful.

Track the termination signal and fall back to the shell convention of 128 + signal number (137 for SIGKILL) when no exit code is available.

fixes #8992

closes #8882
2026-09-04 00:06:16 +02:00
David Brailovsky
2e2805d92f feat(agent): construct memory forks directly from live state
Stream current values and lists through shared fork policy while preserving sequences and the source high-water mark.
2026-09-03 16:31:29 +02:00
David Brailovsky
8c08d0645a Merge remote-tracking branch 'origin/main' into dev 2026-09-03 07:58:51 +00:00
Mario Zechner
4e69b0c280 feat(ai): preserve Anthropic per-turn thinking effort
Route eligible OpenRouter Claude models through the native Messages API and surface provider thinking-drop diagnostics.
2026-09-02 21:39:29 +02:00
Mario Zechner
e26afb63a4 fix(agent): retain settled tools until placement 2026-09-02 17:53:25 +02:00
David Brailovsky
e583b290a6 fix: remove misleading write byte counts
The write tools reported UTF-16 code units as bytes. Remove the count from success messages instead of scanning content again.

Closes #8979
2026-09-02 15:06:06 +02:00
Qiaochu Hu
ebc3744909
fix(agent): surface proxy stream EOF without terminal event as an error (#8997)
streamProxy dropped a final SSE event that was not newline-terminated
(the residual line buffer was never flushed after the read loop) and
called stream.end() without a result when no done/error event had been
seen, leaving EventStream.result() pending forever. Consumers like
agentLoop awaiting response.result() hung indefinitely when the server
closed the connection mid-response.

Flush the decoder and process the residual buffer after EOF, and push a
synthesized error event when the stream ended without a terminal event.

fixes #8996
2026-09-02 14:16:03 +02:00
Mario Zechner
a84a161c75 Merge remote-tracking branch 'origin/dev' into dev 2026-09-01 18:13:48 +02:00
Mario Zechner
0095bce7db fix(agent): bound shell execution output 2026-09-01 18:12:06 +02:00
David Brailovsky
487af8e168 Merge remote-tracking branch 'origin/main' into dev 2026-09-01 14:48:57 +00:00
David Brailovsky
4e356c0ade feat(agent): centralize scalar fork namespace policy
Add a closed fork classifier, copy application scalars for tree forks, exclude them from branch forks, and reject surviving unknown reserved state.
2026-09-01 15:58:13 +02:00
David Brailovsky
1081eb2126 fix(agent): require configured lanes for branch forks
Reject data-only source branches, preserve tree-scope support for them, and update fork fixtures to provide complete lane configuration and state.
2026-09-01 15:18:05 +02:00
David Brailovsky
f2eae920c6 fix(agent): validate fork entries against named branch ancestry
Reject off-branch and unknown fork points, handle null tips and before-root placement, and make SQLite validate from the named branch tip.
2026-09-01 14:58:49 +02:00
David Brailovsky
f8da63be59 feat(agent): require explicit named branches for session forks
Require fork scope and source branch selection, preserve the branch name in the destination, and cover named-branch behavior across backends.
2026-09-01 12:35:14 +02:00
yaogangqiang
afda4d6202
fix(agent): stop prepared tools after preflight abort (#8936)
fixes #8935

Co-authored-by: yaogangqiang <yaogangqiang@kanyun.com>
2026-09-01 11:00:51 +02:00
Armin Ronacher
86bac52f94 feat: add delta-backed replicated state
Track mutable provider state and publish immutable operation batches. Keep path codecs isolated per client subscription and state member.
2026-08-31 14:04:42 +02:00