Commit Graph
182 Commits
Author SHA1 Message Date
Armin Ronacher f6f3d55076 Merge remote-tracking branch 'origin/main' into replication
# Conflicts:
#	scripts/check-entry-graphs.mjs
2026-10-24 12:25:43 +02:00
Mario Zechner d8d99950ac feat(chord,durable): PendingOps folds pending ops for slow consumers; Watch delivers one call per busy period
- chord/delta: PendingOps (push, size, take -> PendingTake): raw pending ops, r drops everything
  before it, a leaf index merges appends and primitive sets per path (cleared by any other op),
  past 10,000 ops only "replace with the current value"; one batch is kept by reference and
  received ops are never mutated
- chord: Watch queues frames in PendingOps while its listener is busy or not started and delivers
  one call with the newest value, the folded ops (or [["r", newest]] after an overflow) and the
  newest frame's context; replaces the 100-frame collapse. NativeWatch is unchanged and takes an
  optional replace()
- durable: watchEvents keeps every event batch in order (NativeWatch with a snapshot replace);
  document, view and task-graph watches fold; spec, README, example 04 and tests updated
- tests: fold fuzzers (tracker, appendText, splices/reorders, root arrays, diffRevisions) with
  codec round trips, adversarial cases, cap, ownership, cost and GC guards
2026-10-24 09:37:12 +00:00
Mario Zechner da412b0392 feat(chord,durable): appendText for cheap string appends; Durable partial commits append instead of reassigning
Follow-up to #9265.

- chord: Delta appendText(draft, key, text) / StringKeys<T> record an append op without the
  O(length) prefix compare that a plain `draft[key] += text` costs in prepare()
- durable: partial commits append text and thinking deltas with appendText (assignJson plan,
  checked by length), and apply tool-call argument changes from their own StreamingJsonParser
  of the raw toolcall_delta text instead of reassigning the arguments snapshot
- durable "." entry-graph budget 73 -> 76 for the parser it now imports
2026-10-24 08:21:41 +00:00
David Brailovsky a1836b06c3 fix: handle npm 12 pack --json output in preview-packages 2026-10-23 11:20:01 +02:00
Armin Ronacher 0a2a3cbce5 Merge remote-tracking branch 'origin/main' into replication
# Conflicts:
#	packages/durable/README.md
#	packages/durable/src/index.ts
#	packages/durable/src/storage/indexeddb.ts
#	packages/durable/src/storage/sqlite/storage.ts
2026-10-23 09:11:32 +02:00
Christian Klotz db774055e3 Set up preview packages (#11260)
* feat: publish preview packages to pkg.earendil.com

CI packs every public package after the build, with internal dependencies
pointing at the same commit's builds. A workflow_run job publishes them to
the earendil-pkg worker with the job's GitHub OIDC token, moves main or
pr-<n>, and comments install commands on the PR. Closing a PR deletes its
ref. pi-env is left out because its daemons are only built for releases.

* feat: publish preview packages only for main and same-repo PRs

pkg.earendil.com requires a consumer token, so fork authors could not
install their previews anyway. Fork PRs are no longer packed or
published, which keeps fork code out of the registry and removes the PR
lookup: the PR number now comes from the workflow_run event. The PR
comment is dropped; the job summary lists the install commands.

* fix: pick the PR into main and describe only the workflow in preview-packages.yml

- Read the PR number from the workflow_run pull request list with jq,
  selecting the PR into main; a branch can also have PRs into other
  branches, and the index expression tripped workflow linters.
- Comments describe what the workflow does and what it needs from
  pkg.earendil.com, not how the service works.

* fix: gate preview publishing to main pushes and open PRs into main

- Publish only CI runs for pushes to main and for pull requests. A branch
  can make its own copy of CI run on push; those runs are unreviewed and
  were uploaded as push builds.
- Move pr-<number> only while the PR is open into main with this commit
  as its head, checked live, so a late publish cannot recreate the ref of
  a closed PR; otherwise publish without a ref and print a notice.
- Set concurrency per job, so skipped fork runs never wait in a group.

* docs: drop the service rule from the preview-packages.yml header

* docs: name the earendil-works/pkg worker in the preview script
2026-10-22 11:43:08 +02:00
Armin Ronacher d1de53475d feat(durable): rebuild the commit log from stored state
ReplayableStorage.log(after) reads the changes committed after a sequence from what the storage keeps, replacing export() and the outbox. Schema version 3 stamps conversations, tasks, and submissions with a commit sequence and indexes every stamp, so the log is read in ranges. ReplicatingStorage and the outbox are removed; the sync module keeps compactRecords() and the log lines.
2026-10-21 18:06:40 +02:00
Armin Ronacher e8d6d0fb98 feat(durable): replicate storages as a commit log
Every built-in storage implements ReplayableStorage: head(), replay() at an explicit sequence, and export() of the current state as a log that replays to the same reads. SQLite schema version 3 adds sequence indexes so export streams. @earendil-works/pi-durable/sync adds ReplicatingStorage, which appends each committed batch to an outbox with fork copies resolved, compactRecords(), and versioned JSON log lines.
2026-10-21 14:39:36 +02:00
Armin Ronacher cae9fd28a2 Revert "feat(durable): replicate storages as a commit log"
This reverts commit 4c25119f54. The work continues on the replication branch.
2026-10-21 14:39:26 +02:00
Armin Ronacher 4c25119f54 feat(durable): replicate storages as a commit log
Every built-in storage implements ReplayableStorage: head(), replay() at an explicit sequence, and export() of the current state as a log that replays to the same reads. SQLite schema version 3 adds sequence indexes so export streams. @earendil-works/pi-durable/sync adds ReplicatingStorage, which appends each committed batch to an outbox with fork copies resolved, compactRecords(), and versioned JSON log lines.
2026-10-21 14:26:19 +02: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 5c1736f82d feat: checkpointWhen is required on Durable document definitions
Breaking change: defineDoc and defineDocFamily now require an explicit checkpointWhen predicate; no default is supplied. Set policies on built-in documents, examples, tests, and triage state, and document the required API.
2026-10-19 18:17:42 +00:00
Mario Zechner 2ec55d808d feat: Durable and pi-ai telemetry; Context.telemetry is always a span
- pi-ai: AI_TELEMETRY_SCHEMA; pi.ai.request and pi.ai.poll spans around Models requests via a lazyStream observer
  (no provider changes), first_chunk and block events (never per delta), usage/cost end attributes, provider_error
  status with a bounded message, aborted stays ok; duration, first-chunk, token and cost metrics; option renamed
  telemetryContext -> telemetry (a parent span)
- pi-telemetry: TelemetryContext carries readonly metrics and propagation capabilities on every span
- chord/context: Context.telemetry is always a TelemetrySpan (NOOP default); withTelemetry takes spans
- durable: DURABLE_TELEMETRY_SCHEMA; pi.durable.submit (inputs start their own trace linked to the caller) and
  pi.durable.phase spans for every task phase; stored carriers on submissions and tasks (TaskOptions.trace, links);
  entry, submission, checkpoint, replay and report events after commit; resumed tasks stay in their trace; phase
  duration, active task and report metrics; failed phases carry fixed categories with bounded messages
2026-10-19 06:26:02 +00:00
Mario Zechner 48909d987a feat: telemetry propagation, span links and metrics; telemetry member in chord/context
- pi-telemetry: TelemetryPropagation (inject/extract, opaque carriers), span links (SpanOptions.links, addLink),
  TelemetryMetrics (counter, up-down counter, histogram), typed metric schemas (createTypedMetrics), in-memory
  measurement log, conformance tests for propagation and metrics
- chord/context: fixed Context.telemetry member (NOOP default), withTelemetry, traceIn
- durable: HarnessOptions.telemetry option type (no instrumentation yet)
2026-10-18 20:36:08 +00:00
David Brailovsky 4954d76050 feat: check the model catalog against the latest release before publishing (#11007)
pi.dev serves each published catalog to released pi >= MINIMUM_PI_VERSION.
Compile the latest release's pi-ai against its built-in models overlaid by
the new catalog, so a catalog it cannot handle (e.g. kimi-coding moving to
openai-completions) fails in CI instead of breaking released clients.
MINIMUM_PI_VERSION moves to scripts/model-catalog-minimum-version.mjs.
2026-10-15 21:21:57 +02:00
Armin Ronacher d05a73fb31 fix: keep the Nix model catalog pin buildable
The pin script discovered the catalog with the checkout's version, which on
main is the last release, so pi.dev answered with the catalog for released
clients after MINIMUM_PI_VERSION was raised. It now pins the newest
published catalog and treats the pin as stale when its provider/type/API
model groups differ. The release script pins the newest catalog and runs
the Nix build steps before tagging.

closes #10985
2026-10-15 20:16:03 +02:00
David Brailovsky a3f265b1c6 feat(ai): use Chat Completions for the kimi-coding provider
Switch kimi-coding to OpenAI Chat Completions at api.kimi.com/coding/v1,
the protocol the official Kimi Code client uses. K3, K3-256K, and Kimi For
Coding accept tools declared in later system messages, so tools loaded
mid-conversation (e.g. by tool_search) keep the prompt cache. Highspeed
rejects tool-bearing system messages and keeps added tools top-level.

Re-lands b06c1f2 (reverted in 6a1f799b6) with MINIMUM_PI_VERSION bumped
to 1.2.1. Released clients implement only Anthropic Messages for
kimi-coding and ignore a model's api, so they must keep receiving the
last catalog published under 0.80.7.

closes #10720
2026-10-15 15:29:11 +02:00
Armin Ronacher f13c00fb3a fix: pin internal dependencies to exact versions
Update release synchronization and dependency checks to enforce exact versions. Refresh both lockfiles and add regression coverage.

closes #10865
2026-10-13 14:28:15 +02:00
Mario Zechner 6db4070f17 docs: describe only the current Chord, Durable, and coding-agent code
Chord: README rewritten for the new runtime; notes.md and requests.md removed, their open limits and
decisions folded into spec.md section 12; guide and spec status lines updated. Durable: drops the
pico-v5 handoff and delta findings, renames the Pico spec, and uses current Chord terms. Delta README,
issue categories, and PI_RADIUS_GATEWAY updated.
2026-10-12 10:47:09 +00:00
Mario Zechner 0104fef1e9 feat(chord): replace the facet and service runtime with the chord2 host runtime
Moves chord2 (contracts, objects, cells, roots, plugins, hot reload, memory/IPC/WebSocket links)
from p2 into packages/chord, with its tests (now on vitest) and docs. The root export is the new
runtime plus the shared base (Context, JsonValue, JsonRepresentation, Draft, copyJson, isJsonValue,
replicatedState and its types). ./node now holds the host manager, child control, process locks,
and nodeLoader. ./context and ./delta are unchanged; ./bundler is removed.

replicatedState stays a standalone module with the same exports. It no longer exposes the exact-op
subscription the removed service provider used, so listener failures of mutable states are always
reported asynchronously. The package depends on typebox instead of esbuild. The wire format stays JSON.
2026-10-12 10:41:59 +00:00
Mario Zechner 7472cda0d6 feat(coding-agent): remove the experimental server stack and the client, protocol, and server packages
Deletes packages/client, packages/protocol (CBOR codec), packages/server, coding-agent's
src/experimental (except source-resolver.ts, which source runs still preload), src/cli/experimental,
src/client, the example plugin, and their tests. coding-agent no longer depends on @earendil-works/chord.
The installer lock drops esbuild, so its platform-package sanity check goes too.
2026-10-12 10:41:59 +00:00
Mario Zechner 97195ec3c4 build: share root config with pi-private
Everything outside apps/ is the same in pi and pi-private; apps/ exists only
in pi-private, and these files now tolerate its absence:
- workspaces include apps/*
- biome.json leaves apps/ to its own config
- the pre-commit hook runs the apps/mobile check only when it exists
- the Android APK workflow runs only in earendil-works/pi-private
- scripts/biome-check.mjs runs native Biome, or Biome WASM on Android
  (@biomejs/wasm-nodejs 2.3.5), for npm run check
From pi-private bac58de97, c2a8629da, 106714ebc.
2026-10-11 16:36:26 +00: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
Mario Zechner 42a3497d03 feat(durable): read returns images, optional Photon image processor
read returns an image file as one image block (programs get an ImageContent) plus an info diagnostic,
instead of an unsupported_image error. Limits are the conversation model's inputLimits.images.resize,
by default 2000x2000 pixels and 4.5 MB of base64.

- Without a processor: PNG, JPEG, GIF, and WebP within the limits pass through undecoded; the byte limit
  is checked before reading the file, dimensions from the header. Larger images and BMP are error results.
- With createCodingTools({ images }): the processor orients by EXIF, converts BMP to PNG, and shrinks to
  fit. ImageProcessor.prepare is async.
- @earendil-works/pi-durable/images: createPhotonImages(wasm) on @silvia-odwyer/photon 0.3.3 (web build);
  /images/node and /images/cloudflare load the wasm. The root and ./tools entries never reach it (enforced
  in check-entry-graphs).
- An image must be read whole: one that changes while read is read again, unlike a growing text file.
- A model without image input gets a diagnostic that it sees a placeholder.
2026-10-09 19:38:02 +00:00
Mario Zechner eba8497395 feat(durable): nested tool calls, structured output, callers; storage errors end the Session
Nested tool calls: ToolExecutionApi.executeTool() runs another tool as its own pi.tool task owned by the caller,
keyed for replay-safe reattachment. Results for programs live in the caller's NestedResultDoc until it settles;
pi.live.nestedTools shows each call with the arguments it runs with and a summary. TaskOptions.abandonOnRestart
aborts work its creator awaited only in memory before it runs again after a restart.

Structured output: structuredOutputSchema and structuredOutput, validated; a tool without a schema gives programs its
bounded output (one text as a string, one image as itself, else the list). ToolExecutionResult.content is now output.
callers and modelTools decide who may call a tool.

Storage errors: any error a Storage method throws fails the Session, which closes itself; later calls and waits reject
with SessionFailed, watches end with session_failed, and Session.closed settles. Nothing retries in the Harness.
StorageRejected is removed; StorageRequestError marks invalid reads that fail only their call. Listener and onReport
errors are contained and reported.

Also updates scripts/issues/triage.ts and the vacation experiment for the content -> output rename.
2026-10-09 17:13:34 +00:00
Mario Zechner 5a10492690 feat: add local issue triage tool in scripts/issues
Syncs issues with gh, triages new ones with a pi-durable agent (category, duplicates, summary, p0/p1/none suggestion), and serves a web UI for decisions.
2026-10-09 17:12:26 +00:00
Christian Klotz 6fb2e78151 fix: support npm 12 pack JSON output (#10680)
fixes #10633
2026-10-08 17:26:34 +02:00
Armin Ronacher bf8d9c659f chore: allow skipping tests in the release script
PI_RELEASE_SKIP_TESTS=1 skips ./test.sh when the suite already passed in release:local and the machine is too loaded for timing-sensitive tests.
2026-10-07 23:32:05 +02:00
Mario Zechner 4c28a6865c fix(durable): raise the root entry budget for the shared storage scan module 2026-10-06 20:57:14 +02:00
Christian Klotz 23cf2b948d feat: unify package artifact validation (#10197)
* feat: unify package artifact validation

* fix: restrict local artifact output paths

* fix: clarify package artifact module names

* feat: support pnpm package artifact consumers

* fix: preserve local release package installs

Keep npm and Bun consumer installs as runnable release artifacts while retaining isolated validation for other packages. Simplify smoke fixtures and avoid redundant release work.
2026-10-06 13:30:02 +02:00
Armin Ronacher 1ffb6bd621 fix(coding-agent): disable .env autoload in standalone binary
Bun compiled executables load cwd .env files into process.env by default.
closes #10473
2026-10-06 09:57:14 +02:00
Mario Zechner ba03e03f2d feat(env): add @earendil-works/pi-env, remote execution environments over SSH
- RemoteExecutionEnv: a Durable ExecutionEnv on another machine whose
  results match NodeExecutionEnv there; Connection to the pi-env daemon
- packages/env/daemon: the Rust daemon for Linux, macOS, Android and
  Windows, following Node and libuv semantics
- env.yml runs Durable's env tests, the daemon's checks and pi-env's
  conformance and differential tests on Linux, macOS and Windows
2026-10-05 12:50:48 +02:00
Armin Ronacher 1b094148b9 fix(coding-agent): keep codemode working after the install is updated or removed
Resolve the QuickJS wasm path once and spawn the bundled codemode worker
from an in-memory data: URL. Show a restart hint when errors occur after
the install changed on disk.

closes #10439
2026-10-04 22:49:20 +02:00
Mario Zechner 70eceaade6 fix(durable): persist provider session identities
Assign each conversation its own UUIDv7 and forward it to model requests for prompt-cache affinity. Lazily backfill legacy conversations and cover real Codex cache reuse.

Closes #10424
2026-10-04 00:59:08 +02:00
Armin Ronacher 9fba660cf1 chore: accept unfixable node-forge advisory in npm audit
The scheduled npm audit failed on GHSA-86w9-cpqp-85rv, which has no fixed node-forge release. node-forge is only reachable through gondolin in the private gondolin example extension, and gondolin only verifies certificates from its own CA with exponent 65537, so the low-exponent forgery does not apply. The audit now runs through scripts/npm-audit.mjs, which fails on any other advisory at or above moderate.
2026-10-02 18:49:34 +02:00
Armin Ronacher c71a496ff9 feat(coding-agent): add Nix flake (#9137)
Add a Nix flake that builds Pi from the checkout on aarch64/x86_64 Linux
and macOS. The build is offline: provider model data is hydrated from a
pi.dev model catalog revision pinned in nix/model-catalog.json, and the
runtime dependency tree comes from packages/coding-agent/install-lock with
internal packages built from source.

The Nix workflow keeps the catalog pin current on main, builds release
tags on all systems, and fast-forwards the stable branch to each release
that builds. The release script refreshes the pin before tagging.
2026-10-02 18:30:51 +02:00
Armin Ronacher 581e7ba781 feat(coding-agent): remove npm shrinkwrap and recommend the managed installer
npm installs no longer pin transitive dependencies. Pinned installs come
from the pi.dev installer lockfile. pi update on global npm installs now
recommends migrating with the installer.

closes #5653
2026-10-02 17:16:56 +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
Mario Zechner 49683a3647 feat(durable): lifecycle conformance and task graph view (Packages 22, 23)
Package 22: runtime.now() and report() throw after the invocation ended; a
migration-only commit is published; a failed Harness.open closes without the
caller's context and rethrows the open error; ConversationWatch alias. Tests
for close joining non-cooperative code, cancelled close, queued operations at
the seal, progress calls and viewers on a paused Harness, the Chord guide, and
the spec's usage examples.

Package 23: Harness.taskGraph() and watchTaskGraph() mount every live task with
its owner edge, committed status, flags, and owned conversations, advanced from
commit publications. Example 24 prints the checkout's tree.
2026-10-01 09:53:21 +02:00
Mario Zechner b56702ad34 feat(durable): extensions and per-conversation agents (Package 21)
- Registry of named extensions (tools, sections, hooks, wraps, tasks) with install/uninstall;
  defineExtension, defineTool, section, hook, wrapTool, wrapSection
- pi.agent document (model, thinking level, extensions, tools filter, instructions, cwd),
  configure(), Conversation.agent()/configure(), agent option on root/createConversation/fork,
  task-owned conversations copy their owner's agent
- Harness-wide HarnessSettings read at every use; env function built per use
- Hooks and the agent resolved per task phase; tool calls resolved with the tools filter applied
- ToolRegistration<TParameters, TDetails> types execute() args from parameters
- HarnessOptions.conversationCreated; Tx.submissionByRequest() and Tx.createSubmission()
- FileSystem.id; edit/write serialize per file system id and canonical path
- CodingTools extension (read, write, edit, bash)
- Examples 06-31 on the new API, README and CHANGELOG
2026-10-01 01:28:22 +02:00
Mario Zechner ed0d6b91b6 feat(durable): compaction and overflow (Package 20)
Manual compact(), background and blocking threshold compaction, and overflow
compaction with one retry. Summaries are headed pi.compaction entries placed
through the inbox, or appended by a compaction the generation waits on; the
stale rule decides between concurrent summaries.
2026-09-30 18:23:25 +02:00
Armin Ronacher 4a42f8fafa fix(coding-agent): load codemode worker in Windows binary
closes #10204
2026-09-30 13:48:04 +02:00
Mario Zechner 47f65f1a3a feat(durable): inbox, reset, usage, conversation view, and experimental events (Package 17) 2026-09-29 21:24:32 +02:00
Mario Zechner 445770e032 feat(durable): first coding-agent tool turn (Package 16)
Generation offers active registered tools through positional system entries and
hands a tool-calling answer to parallel or sequential pi.tool tasks and a
pi.post-tools task that applies addTools/terminate and continues the run. Tool
tasks validate, run beforeTool/afterTool, record intent with the replay policy,
publish bounded, sanitized, adaptively throttled progress in pi.live.tools, and
write results with a rendered diagnostics block. Hook dispatch with conversation
and subtree scopes, prepareArguments, HarnessOptions.env, and read/bash/edit/write
tools in pi-durable/tools. The env shell now streams raw output and spills past
thresholds; its bounded capture and publisher are removed.
2026-09-29 21:24:32 +02:00
Mario Zechner ba7d5fbedb feat(ai,durable): add lightweight pi-ai/models entry and avoid TypeBox in durable
Durable generation imports retry helpers from pi-ai/utils/retry; examples use
pi-ai/models and pi-ai/providers/faux. Entry graph budgets and an import
footprint test guard the models entry.
2026-09-29 21:24:17 +02:00
Armin Ronacher 72abf01ba9 fix(coding-agent): bundle openai-chatgpt OAuth flow
The lazy OAuth entry list in the bundle build was missing openai-chatgpt,
so /login with OpenAI failed with a missing module error. Also fail the
build if any importOAuthModule() target in load.ts has no lazy entry.
2026-09-29 20:00:11 +02:00
Armin Ronacher dfbb4a21ed fix: include codemode and mcp in local release packages 2026-09-29 19:01:55 +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 ca7460d16b feat: build with TypeScript 7 and run sources with plain node
Replace the tsgo native preview with typescript@7.0.2 and port the check scripts to the TS 7 API. Target ES2024, drop useDefineForClassFields: false and unused decorator options, and enable verbatimModuleSyntax. Replace tsx with node plus the source resolver hook, passed to --import as a file URL.

closes #9965
2026-09-25 13:14:33 +02:00
Armin Ronacher 7fd564cbb7 feat: share model catalog protocol with pi.dev (#9763)
Move catalog layout, index validation, version selection, and request
negotiation into scripts/model-catalog-protocol.ts. pi.dev keeps an
identical copy, so the publisher and a test running the current client
exercise the same selection pi.dev performs. Replaces the cross-repository
compatibility dispatch.

Related to #9099.
2026-09-23 20:08:05 +02:00