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.
112 lines
7 KiB
Markdown
112 lines
7 KiB
Markdown
# 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](https://github.com/earendil-works/pi/issues/11803))
|
|
|
|
### Fixed
|
|
|
|
- Fixed `schemaToType()`, `renderDeclarations()`, `renderToolSignature()`, and `renderToolSample()` throwing `URIError` for a local `$ref` with a malformed percent escape (`#/$defs/%E0`), so one such tool schema failed every caller that renders all tools. The reference now renders as `unknown`, like a reference that names nothing ([#11803](https://github.com/earendil-works/pi/issues/11803))
|
|
|
|
## [1.5.0] - 2026-11-02
|
|
|
|
### Changed
|
|
|
|
- README: the codemode tool example builds its parameters with `@earendil-works/pi-schema` instead 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 track `onWorkerStarted(exited)` or retain capacity through `acquireWorker()`'s release callback
|
|
|
|
### Added
|
|
|
|
- Added `CodemodeSandbox`'s `onWorkerStarted(exited)` callback so hosts can count a worker against concurrency limits until it actually exits, independently of its script result
|
|
- Added `CodemodeSandbox`'s `acquireWorker()` 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](https://github.com/earendil-works/pi/issues/10748))
|
|
|
|
## [1.2.0] - 2026-10-12
|
|
|
|
### Breaking Changes
|
|
|
|
- Removed `MCP_TYPESCRIPT_PREAMBLE` and `mcpStructuredContentSchema()`. `renderToolOutputType()` and the declarations built on it render every output schema as its own type and no longer turn MCP `CallToolResult` schemas into `CallToolResult<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. `CodemodeSandboxDurableObject` from the new `@earendil-works/pi-codemode/cloudflare` entry is its remote end, deployed as its own Cloudflare Worker. `examples/cloudflare` shows the setup
|
|
- Added `InlineCodemodeSandbox`, which runs the VM on the calling thread for runtimes without worker threads. Its `interruptBudget` limits scripts that compute without awaiting a tool
|
|
- Added the `@earendil-works/pi-codemode/portable` entry, which has no Node imports, and `CodemodeSandboxBase`, 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 from `startedAt`, randomness from `seed`, UTC, no `WeakRef`/`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-null `default`, and `deprecated`; constraints of nullable `anyOf`/`oneOf` fields are read from the non-null branch, and draft-04 boolean `exclusiveMinimum`/`exclusiveMaximum` are shown as exclusive bounds. Property descriptions now also split on U+2028/U+2029. A type over `maxChars` is rendered again without tags before it becomes `unknown` ([#10707](https://github.com/earendil-works/pi/issues/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 null` is stopped at the same points as a synchronous loop
|
|
|
|
### Fixed
|
|
|
|
- Fixed `parseCodemodeSource()` ignoring a `// @options:` line that is not the first line, so its `timeout_ms` never applied; it now throws `CodemodeSourceError` ([#10631](https://github.com/earendil-works/pi/issues/10631))
|
|
- Fixed `CodemodeSandbox` failing with a broken bridge error when the host runs under `node --watch` on Node 24 or 26, which posts `watch:import`/`watch:require` messages on the worker channel ([#10725](https://github.com/earendil-works/pi/issues/10725))
|
|
|
|
## [1.1.0] - 2026-10-07
|
|
|
|
### Added
|
|
|
|
- Added `console: true` to text output items produced by `console.*`, so hosts can tell them apart from `text()` 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 override `constructor`, `name`, `message`, `toString`, `toLocaleString`, `valueOf`, `toJSON`, and `Object.prototype` members ([#10444](https://github.com/earendil-works/pi/issues/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 a `sandbox` error ([#10444](https://github.com/earendil-works/pi/issues/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 and `MAX_OUTPUT_ITEMS` (100000) items, and a script past either limit fails with a `RangeError` ([#10283](https://github.com/earendil-works/pi/issues/10283))
|
|
|
|
## [1.0.0] - 2026-10-01
|
|
|
|
### Added
|
|
|
|
- Added `renderToolOutputType()`, the type a tool call resolves to.
|
|
|
|
### Changed
|
|
|
|
- Reading a member of `tools` or of a global namespace that does not exist now throws an error naming the close matches, instead of returning `undefined`. Use `"name" in tools` to check for a tool. `store()` size errors explain what the store is for.
|
|
|
|
## [0.99.2] - 2026-09-30
|
|
|
|
### Changed
|
|
|
|
- Allowed `CodemodeSandbox.workerUrl` to be a string, as required for embedded worker entrypoints in Bun compiled executables ([#10204](https://github.com/earendil-works/pi/issues/10204)).
|
|
|
|
### Fixed
|
|
|
|
- Fixed `image()` accepting malformed base64 data and unsupported image types. It now throws a `TypeError` unless 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](https://github.com/earendil-works/pi/issues/10215)).
|
|
|
|
## [0.99.1] - 2026-09-29
|
|
|
|
## [0.99.0] - 2026-09-29
|
|
|
|
### Added
|
|
|
|
- Initial spike: `CodemodeSandbox` runs model-written JavaScript in a worker thread and exposes injected tools as `tools.<name>(args)` async functions.
|