mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-05 23:37:25 +00:00
Fixes #11803. **Problem** `tool_search` builds a tool's search text from its parameter schema but never followed `$ref`. MCP servers (Pydantic, FastMCP) often put nested models in `$defs`: ```json { "properties": { "options": { "$ref": "#/$defs/options" } }, "$defs": { "options": { "properties": { "mode": { "description": "reconciliation" } } } } } ``` Search text was `Inspect records options`, so `tool_search("reconciliation")` found nothing. Durable's copy of `tool_search` had the same gap. The codemode `resolves to` summary had the same blind spot for output schemas: a field behind a `$ref` showed as `structuredContent?` with no field names. **Fix** - pi-codemode exports its existing local JSON Pointer resolver as `resolveSchemaRef(ref, root)`. A malformed percent escape now resolves to nothing instead of throwing `URIError` (this also affected `schemaToType()`). - coding-agent and Durable `schemaText()` follow local `$ref`s. Each referenced subschema is read once, so recursive and shared definitions neither loop nor inflate BM25 term counts. Unreferenced `$defs` and remote refs stay out. - coding-agent `describeFields()`/`describeUnionFields()` resolve `$ref` chains against the output schema root. **Tests** - `packages/codemode/test/declarations.test.ts`: escaped, remote, missing, malformed refs. - `packages/coding-agent/test/tool-search.test.ts`: refs, escaped segments, recursion and shared definitions, unused definitions. - `packages/coding-agent/test/suite/agent-session-codemode.test.ts`: summary through root, field, const, and union refs. - `packages/durable/test/tool-search.test.ts`: end-to-end load via a ref'd description; unused definition does not match. `npm run check` passes.
7 KiB
7 KiB
Changelog
[Unreleased]
Added
- Added
resolveSchemaRef(ref, root), which returns the subschema a local$ref(#,#/$defs/Item) names in a schema, with URI-decoded and JSON Pointer unescaped segments (#11803)
Fixed
- Fixed
schemaToType(),renderDeclarations(),renderToolSignature(), andrenderToolSample()throwingURIErrorfor a local$refwith a malformed percent escape (#/$defs/%E0), so one such tool schema failed every caller that renders all tools. The reference now renders asunknown, like a reference that names nothing (#11803)
[1.5.0] - 2026-11-02
Changed
- README: the codemode tool example builds its parameters with
@earendil-works/pi-schemainstead of TypeBox.
[1.4.0] - 2026-10-21
[1.3.0] - 2026-10-15
Breaking Changes
- Worker-backed results and
close()now settle after requesting shutdown, not after worker exit. Hosts that require actual exit must trackonWorkerStarted(exited)or retain capacity throughacquireWorker()'s release callback
Added
- Added
CodemodeSandbox'sonWorkerStarted(exited)callback so hosts can count a worker against concurrency limits until it actually exits, independently of its script result - Added
CodemodeSandbox'sacquireWorker()hook to reserve shared capacity before starting a worker and release it only on actual exit or constructor failure
Fixed
- Fixed aborts, timeouts, and
close()waiting for worker termination on Bun while a non-interruptible built-in runs; shutdown now requests termination without waiting for exit (#10748)
[1.2.0] - 2026-10-12
Breaking Changes
- Removed
MCP_TYPESCRIPT_PREAMBLEandmcpStructuredContentSchema().renderToolOutputType()and the declarations built on it render every output schema as its own type and no longer turn MCPCallToolResultschemas intoCallToolResult<T>; describe MCP results in the output schema instead
Added
- Added
RemoteCodemodeSandbox, which runs each script's VM in another isolate while tools run in the caller.CodemodeSandboxDurableObjectfrom the new@earendil-works/pi-codemode/cloudflareentry is its remote end, deployed as its own Cloudflare Worker.examples/cloudflareshows the setup - Added
InlineCodemodeSandbox, which runs the VM on the calling thread for runtimes without worker threads. ItsinterruptBudgetlimits scripts that compute without awaiting a tool - Added the
@earendil-works/pi-codemode/portableentry, which has no Node imports, andCodemodeSandboxBase, the API all three sandboxes share - Added
sandbox.start(), a deterministic run whose calls the host answers itself (onCall,run.deliver()), so a host can replay a script after a restart: a virtual clock fromstartedAt, randomness fromseed, UTC, noWeakRef/FinalizationRegistry, results applied in the order the host numbers them, the VM's fingerprint (onStarted), the calls issued after each result (onIdle), and whether the run has its outcome (run.finished). Works with every sandbox;execute()is unchanged
Changed
schemaToType()and the declarations built on it show property constraints the TypeScript type cannot express as tags on the property's comment line, such as// @integer @minimum 0 @maximum 30000 @default 0. Covered keywords:integer, numeric bounds,multipleOf, string length,pattern,format, array length,uniqueItems, non-nulldefault, anddeprecated; constraints of nullableanyOf/oneOffields are read from the non-null branch, and draft-04 booleanexclusiveMinimum/exclusiveMaximumare shown as exclusive bounds. Property descriptions now also split on U+2028/U+2029. A type overmaxCharsis rendered again without tags before it becomesunknown(#10707)image()errors describe the accepted image block as{ type: "image", data, mimeType }instead of an MCP image block- The VM now polls for interrupts while it drains promise jobs, so a script such as
while (true) await nullis stopped at the same points as a synchronous loop
Fixed
- Fixed
parseCodemodeSource()ignoring a// @options:line that is not the first line, so itstimeout_msnever applied; it now throwsCodemodeSourceError(#10631) - Fixed
CodemodeSandboxfailing with a broken bridge error when the host runs undernode --watchon Node 24 or 26, which postswatch:import/watch:requiremessages on the worker channel (#10725)
[1.1.0] - 2026-10-07
Added
- Added
console: trueto text output items produced byconsole.*, so hosts can tell them apart fromtext()output
[1.0.4] - 2026-10-05
Changed
- Built-ins are frozen and built-in globals are read-only before the script runs, so patches such as
Array.prototype.toJSON = ...have no effect. Instances can still overrideconstructor,name,message,toString,toLocaleString,valueOf,toJSON, andObject.prototypemembers (#10444)
Fixed
- Fixed a script that patched built-ins crashing the host process and leaving
execute()unsettled. Malformed payloads from the worker now fail the execution with asandboxerror (#10444)
[1.0.3] - 2026-10-05
[1.0.2] - 2026-10-04
[1.0.1] - 2026-10-03
Fixed
- Fixed scripts that print in a loop growing the host's memory until it crashes: output is limited to
MAX_OUTPUT_CHARS(16 Mi) characters andMAX_OUTPUT_ITEMS(100000) items, and a script past either limit fails with aRangeError(#10283)
[1.0.0] - 2026-10-01
Added
- Added
renderToolOutputType(), the type a tool call resolves to.
Changed
- Reading a member of
toolsor of a global namespace that does not exist now throws an error naming the close matches, instead of returningundefined. Use"name" in toolsto check for a tool.store()size errors explain what the store is for.
[0.99.2] - 2026-09-30
Changed
- Allowed
CodemodeSandbox.workerUrlto be a string, as required for embedded worker entrypoints in Bun compiled executables (#10204).
Fixed
- Fixed
image()accepting malformed base64 data and unsupported image types. It now throws aTypeErrorunless the data is valid base64 of a PNG, JPEG, GIF, or WebP image, derives the MIME type from the image signature instead of the declared type, and strips line breaks from wrapped base64 (#10215).
[0.99.1] - 2026-09-29
[0.99.0] - 2026-09-29
Added
- Initial spike:
CodemodeSandboxruns model-written JavaScript in a worker thread and exposes injected tools astools.<name>(args)async functions.