Commit graph

40 commits

Author SHA1 Message Date
Armin Ronacher
4a080252f0 Release v1.4.0 2026-10-22 00:29:13 +02:00
Armin Ronacher
ae7b16d43b Add [Unreleased] section for next cycle 2026-10-15 20:57:35 +02:00
Armin Ronacher
71023aec15 Release v1.3.0 2026-10-15 20:57:27 +02:00
Armin Ronacher
3daa20280f fix(coding-agent): keep codemode cancellation prompt and bounded
Refs #10748
2026-10-13 18:17:31 +02:00
Armin Ronacher
d547949184 Add [Unreleased] section for next cycle 2026-10-13 00:47:08 +02:00
Armin Ronacher
06a4669355 Release v1.2.0 2026-10-13 00:46:55 +02:00
Armin Ronacher
b6d505cd1f fix(codemode): reject // @options: lines that are not the first line
A misplaced options line was ignored, so its timeout_ms never applied and
the script ran without a deadline. parseCodemodeSource now throws
CodemodeSourceError before the script runs.

fixes #10631
2026-10-12 17:55:33 +02:00
Armin Ronacher
24382bedd0 refactor(codemode,coding-agent): decouple MCP from codemode
Tools that reach other tools declare it with reachesTools(input); MCP uses it to wait for the servers a call needs and to decide which codemode or tool_search tool to activate, instead of parsing codemode scripts and comparing parameter schemas. Namespaces get aliases, replacing codemode's MCP-specific __ suffix rule.

pi-codemode no longer knows MCP: MCP_TYPESCRIPT_PREAMBLE and mcpStructuredContentSchema() are removed, and the MCP result schema describes itself, with the server's local $refs relocated so they resolve as before.
2026-10-12 09:19:30 +02:00
Mario Zechner
7b597d1481 feat(durable): durable code mode (@earendil-works/pi-durable/codemode)
A codemode tool whose scripts call the conversation's tools as nested calls and
survive a restart. The script runs deterministically (pi-codemode start()); each
result is journaled before it is delivered. A rerun starts the script again from
the stored start data, delivers the journaled results in order (nested calls
reattach by key c<id>), checks every recorded call count, holds calls the
journal lacks until replay ends and checks them against earlier attempts' keys,
then continues live. A call launches only once the count of the drain that made
it is committed, so a rerun can prove which calls are new. Divergence, a changed
module version or sandbox fingerprint, and a passed deadline end the call with a
stored error; a decided outcome is returned without a VM. store()/load() keep
values per conversation, rewindable and forked as of the fork's entry.

pi-codemode: CodemodeRun.finished, set when the outcome is decided.
2026-10-11 21:31:48 +00:00
Armin Ronacher
8a9c051f80 feat(codemode): show schema constraints in tool declarations
Property comments now carry constraints the TypeScript type cannot
express (integer, bounds, lengths, pattern, format, default, ...) as
@ tags, read from nullable anyOf branches too. Types over the size
limit are rendered again without tags before becoming unknown.

closes #10707
2026-10-11 22:19:06 +02:00
Mario Zechner
0fb1aee749 feat(codemode): deterministic runs that the host answers (sandbox.start)
For durable code mode: a host can rerun a script after a restart and get the
same calls with the same arguments. start() runs the script with a virtual
clock (startedAt, then each result's time, never backwards), randomness from a
seed, UTC, no WeakRef/FinalizationRegistry, and the run's own tools and
globals; every call goes to onCall with the VM's call id, and the host answers
with run.deliver(seq, now, id, outcome). The VM applies results strictly in
seq order whatever the transport does, reports its fingerprint (engine
versions, prelude hash, limits) before the script runs, the calls issued after
each result (onIdle), and the result it was processing when the script ended
(result.during). Rejections can carry properties for the script's Error.
execute() is unchanged.
2026-10-11 19:50:26 +00:00
Armin Ronacher
4130bd5b32 fix(codemode): ignore Node --watch notifications from the worker
Node 24/26 --watch posts watch:import/watch:require messages on the
worker channel (nodejs/node#65044), which failed the run as a broken
bridge.

closes #10725
2026-10-10 19:13:19 +02:00
Armin Ronacher
748b351fe2 feat(codemode): run sandboxes on Cloudflare Workers via a remote Durable Object
Split the host into transport-independent execution logic and a VM driver, so the VM can run in a worker thread (CodemodeSandbox, unchanged), on the calling thread (InlineCodemodeSandbox), or in another isolate over RPC (RemoteCodemodeSandbox).

Add the /portable entry without Node imports and the /cloudflare entry with CodemodeSandboxDurableObject, meant to be deployed as its own Worker so scripts never block the caller's thread. Scripts that compute without awaiting a tool are bounded by an interrupt budget, now also polled while draining promise jobs. examples/cloudflare shows the setup.
2026-10-10 14:41:36 +02:00
Armin Ronacher
75a99721d1 Add [Unreleased] section for next cycle 2026-10-07 23:33:49 +02:00
Armin Ronacher
abe508e1b8 Release v1.1.0 2026-10-07 23:33:33 +02:00
Mario Zechner
70759f48be fix: address actionable npm audit findings 2026-10-07 23:00:59 +02:00
Armin Ronacher
eb326d265a fix(codemode,coding-agent): separate codemode output items
Text items get ==> text N/M <== headers when there are several, and
console output is grouped into one <console_output> block. Console text
items are marked with console: true.
2026-10-06 23:51:09 +02:00
Armin Ronacher
28dcce2ba4 Add [Unreleased] section for next cycle 2026-10-05 21:23:02 +02:00
Armin Ronacher
7c10bd4337 Release v1.0.4 2026-10-05 21:22:49 +02:00
Armin Ronacher
b223082bb2 fix(codemode): survive scripts that patch built-ins
Freeze built-ins and make built-in globals read-only before the script
runs, keeping instance overrides working via accessors. Validate all
worker payloads on the host and fail malformed ones as sandbox errors
instead of crashing the host process.

closes #10444
2026-10-05 17:29:19 +02:00
Armin Ronacher
997d31f286 Add [Unreleased] section for next cycle 2026-10-05 10:21:24 +02:00
Armin Ronacher
d78dc83d63 Release v1.0.3 2026-10-05 10:21:10 +02:00
Armin Ronacher
200387122c Add [Unreleased] section for next cycle 2026-10-04 02:41:25 +02:00
Armin Ronacher
cd32f7725f Release v1.0.2 2026-10-04 02:41:16 +02:00
Armin Ronacher
4c6fb7cfe8 Add [Unreleased] section for next cycle 2026-10-03 14:21:11 +02:00
Armin Ronacher
a7229ddc21 Release v1.0.1 2026-10-03 14:20:57 +02:00
Armin Ronacher
319fecb89b fix(codemode): cap script output so print loops cannot exhaust host memory
text(), image(), and console.* fail the script with a RangeError past
MAX_OUTPUT_CHARS (16 Mi) characters or MAX_OUTPUT_ITEMS (100000) items.

closes #10283
2026-10-02 17:54:35 +02:00
Armin Ronacher
86dfceec40 Add [Unreleased] section for next cycle 2026-10-01 20:52:38 +02:00
Armin Ronacher
a13d35a742 Release v1.0.0 2026-10-01 20:52:21 +02:00
Armin Ronacher
6f1072cc08 feat(coding-agent): shrink codemode prompt and guide scripts back from errors
Move the codemode script reference, including the models API, into
docs/codemode.md and keep only one line per global in the tool
description. Declared tools get a one-line note on how scripts call them,
and the codemode system prompt guidance and MCP server section are shorter.
With the default tools a GPT-5.6 request drops from about 5,300 to 3,300
tokens.

Errors now point the way back: unknown tools and models members name close
matches, models.classify() and models.generateImages() validate their
arguments, unknown or mistyped models point to getAvailableOfType(),
store() overflow explains the store, and unshown generated images get a note.
2026-10-01 18:27:23 +02:00
Armin Ronacher
955cc6665e Add [Unreleased] section for next cycle 2026-09-30 21:12:42 +02:00
Armin Ronacher
005af57d88 Release v0.99.2 2026-09-30 21:12:28 +02:00
Armin Ronacher
4a42f8fafa fix(coding-agent): load codemode worker in Windows binary
closes #10204
2026-09-30 13:48:04 +02:00
Armin Ronacher
d2931ad3d5 fix(coding-agent): validate codemode image() base64 and detect image type
image() now rejects malformed base64 and data without a PNG, JPEG, GIF,
or WebP signature, and derives the MIME type from the signature. Invalid
image blocks were persisted and made every later provider request fail.

closes #10215
2026-09-30 12:10:30 +02:00
Armin Ronacher
6a4af07d61 Add [Unreleased] section for next cycle 2026-09-29 20:07:07 +02:00
Armin Ronacher
d86654abb8 Release v0.99.1 2026-09-29 20:06:55 +02:00
Armin Ronacher
312184edb6 Add [Unreleased] section for next cycle 2026-09-29 19:04:43 +02:00
Armin Ronacher
4b060d3a98 Release v0.99.0 2026-09-29 19:04:28 +02:00
Armin Ronacher
8eb2bccf26 fix: bump vitest to 4.1.11 and gondolin's undici to 6.29.0
Addresses GHSA-82fw-gwwq-j7x9 (vitest mocker path traversal) and
GHSA-3wwx-pv8p-q78v (undici 6.x permessage-deflate DoS). Both are
dev/example-only; the shipped coding-agent shrinkwrap is unchanged.
2026-09-29 18:38:07 +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