stitchkit 0.88.0 → 0.90.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +182 -0
- package/dist/agent-runtime/child-blocking.d.ts +17 -0
- package/dist/agent-runtime/child-blocking.d.ts.map +1 -0
- package/dist/agent-runtime/child-budget-policy.d.ts +23 -0
- package/dist/agent-runtime/child-budget-policy.d.ts.map +1 -0
- package/dist/agent-runtime/children-contract.d.ts +155 -0
- package/dist/agent-runtime/children-contract.d.ts.map +1 -0
- package/dist/agent-runtime/children.d.ts +4 -99
- package/dist/agent-runtime/children.d.ts.map +1 -1
- package/dist/agent-runtime/coding-shell-process.d.ts +33 -0
- package/dist/agent-runtime/coding-shell-process.d.ts.map +1 -0
- package/dist/agent-runtime/coding-tool-contract.d.ts +18 -0
- package/dist/agent-runtime/coding-tool-contract.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-files.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-listing.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-search-patch.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-shell.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-utf8.d.ts +28 -0
- package/dist/agent-runtime/coding-tool-utf8.d.ts.map +1 -0
- package/dist/agent-runtime/contained-files.d.ts +20 -0
- package/dist/agent-runtime/contained-files.d.ts.map +1 -1
- package/dist/agent-runtime/durability-contract.d.ts +176 -0
- package/dist/agent-runtime/durability-contract.d.ts.map +1 -0
- package/dist/agent-runtime/durability-json.d.ts +3 -0
- package/dist/agent-runtime/durability-json.d.ts.map +1 -0
- package/dist/agent-runtime/durability-ledger.d.ts +16 -0
- package/dist/agent-runtime/durability-ledger.d.ts.map +1 -0
- package/dist/agent-runtime/durability-scheduler.d.ts +29 -0
- package/dist/agent-runtime/durability-scheduler.d.ts.map +1 -0
- package/dist/agent-runtime/durability.d.ts +14 -0
- package/dist/agent-runtime/durability.d.ts.map +1 -0
- package/dist/agent-runtime/event-search.d.ts.map +1 -1
- package/dist/agent-runtime/harness-contract.d.ts +37 -0
- package/dist/agent-runtime/harness-contract.d.ts.map +1 -1
- package/dist/agent-runtime/harness.d.ts +8 -0
- package/dist/agent-runtime/harness.d.ts.map +1 -1
- package/dist/agent-runtime/prompt.d.ts +23 -0
- package/dist/agent-runtime/prompt.d.ts.map +1 -1
- package/dist/agent-runtime/run-execution.d.ts.map +1 -1
- package/dist/agent-runtime/runtime-internals.d.ts +4 -0
- package/dist/agent-runtime/runtime-internals.d.ts.map +1 -1
- package/dist/agent-runtime/runtime.d.ts +13 -0
- package/dist/agent-runtime/runtime.d.ts.map +1 -1
- package/dist/agent-runtime/sandbox-broker.d.ts +7 -0
- package/dist/agent-runtime/sandbox-broker.d.ts.map +1 -0
- package/dist/agent-runtime/sandbox-bubblewrap-args.d.ts +9 -0
- package/dist/agent-runtime/sandbox-bubblewrap-args.d.ts.map +1 -0
- package/dist/agent-runtime/sandbox-bubblewrap-storage.d.ts +22 -0
- package/dist/agent-runtime/sandbox-bubblewrap-storage.d.ts.map +1 -0
- package/dist/agent-runtime/sandbox-bubblewrap.d.ts +14 -0
- package/dist/agent-runtime/sandbox-bubblewrap.d.ts.map +1 -0
- package/dist/agent-runtime/sandbox-coding-adapter.d.ts +15 -0
- package/dist/agent-runtime/sandbox-coding-adapter.d.ts.map +1 -0
- package/dist/agent-runtime/sandbox-coding.d.ts +15 -0
- package/dist/agent-runtime/sandbox-coding.d.ts.map +1 -0
- package/dist/agent-runtime/sandbox-contract.d.ts +93 -0
- package/dist/agent-runtime/sandbox-contract.d.ts.map +1 -0
- package/dist/agent-runtime/sandbox-process-owner.d.ts +11 -0
- package/dist/agent-runtime/sandbox-process-owner.d.ts.map +1 -0
- package/dist/agent-runtime/sandbox-process.d.ts +8 -0
- package/dist/agent-runtime/sandbox-process.d.ts.map +1 -0
- package/dist/agent-runtime/sandbox-session.d.ts +5 -0
- package/dist/agent-runtime/sandbox-session.d.ts.map +1 -0
- package/dist/agent-runtime/sandbox.d.ts +19 -0
- package/dist/agent-runtime/sandbox.d.ts.map +1 -1
- package/dist/agent-runtime/sqlite-purge.d.ts.map +1 -1
- package/dist/agent-runtime/sqlite.d.ts.map +1 -1
- package/dist/agent-runtime/store-driver.d.ts +127 -0
- package/dist/agent-runtime/store-driver.d.ts.map +1 -1
- package/dist/agent-runtime/store-events.d.ts +104 -0
- package/dist/agent-runtime/store-events.d.ts.map +1 -1
- package/dist/agent-runtime/store-migrations/v2-to-v3.d.ts +14 -0
- package/dist/agent-runtime/store-migrations/v2-to-v3.d.ts.map +1 -0
- package/dist/agent-runtime/store.d.ts +115 -0
- package/dist/agent-runtime/store.d.ts.map +1 -1
- package/dist/agent-runtime-coding-tools.js +11 -1247
- package/dist/agent-runtime-harness.d.ts +1 -1
- package/dist/agent-runtime-harness.d.ts.map +1 -1
- package/dist/agent-runtime-harness.js +65 -15
- package/dist/agent-runtime-openrouter.d.ts +3 -12
- package/dist/agent-runtime-openrouter.d.ts.map +1 -1
- package/dist/agent-runtime-openrouter.js +10 -7
- package/dist/agent-runtime-sandbox.d.ts +5 -0
- package/dist/agent-runtime-sandbox.d.ts.map +1 -0
- package/dist/agent-runtime-sandbox.js +797 -0
- package/dist/agent-runtime-sqlite-bun.js +3 -3
- package/dist/agent-runtime-sqlite-node.js +3 -3
- package/dist/agent-runtime.d.ts +5 -4
- package/dist/agent-runtime.d.ts.map +1 -1
- package/dist/agent-runtime.js +259 -65
- package/dist/application/watch-hub.d.ts +24 -2
- package/dist/application/watch-hub.d.ts.map +1 -1
- package/dist/application.js +127 -37
- package/dist/cli.js +8 -8
- package/dist/index-2na0qrfn.js +214 -0
- package/dist/{index-rcgsnrr6.js → index-31jw8fjq.js} +3 -3
- package/dist/{index-9hw9eq48.js → index-7601qfg1.js} +14 -14
- package/dist/{index-3xnq72rz.js → index-7rkhw9ec.js} +14 -1
- package/dist/{index-0vfdh685.js → index-8c3a7m4g.js} +1 -1
- package/dist/{index-t7gh5w3v.js → index-bn2cjajt.js} +27 -6
- package/dist/index-cp20z0n6.js +1351 -0
- package/dist/{index-qp3vshvc.js → index-fadnxwna.js} +87 -5
- package/dist/{index-v1qk37y9.js → index-hrbajay7.js} +106 -4
- package/dist/{index-p86mxmpp.js → index-hw2chdvy.js} +646 -43
- package/dist/{index-0ydchz76.js → index-mnm4qp0p.js} +5 -5
- package/dist/{index-1szetq6f.js → index-q3ve2d1k.js} +30 -8
- package/dist/{index-6krwcdcf.js → index-zwkgfq1s.js} +95 -85
- package/dist/{index-wn9cb82y.js → index-zyvby92n.js} +12 -9
- package/dist/index.js +13 -13
- package/dist/live/watch-client.d.ts +2 -1
- package/dist/live/watch-client.d.ts.map +1 -1
- package/dist/live/watch-contract.d.ts +70 -4
- package/dist/live/watch-contract.d.ts.map +1 -1
- package/dist/live/watch-delta.d.ts +110 -0
- package/dist/live/watch-delta.d.ts.map +1 -0
- package/dist/live.d.ts +2 -1
- package/dist/live.d.ts.map +1 -1
- package/dist/live.js +56 -4
- package/dist/observability/changes.d.ts +55 -0
- package/dist/observability/changes.d.ts.map +1 -0
- package/dist/observability/index.d.ts +2 -0
- package/dist/observability/index.d.ts.map +1 -1
- package/dist/observability/index.js +127 -0
- package/dist/observability/spool.d.ts +53 -0
- package/dist/observability/spool.d.ts.map +1 -0
- package/dist/server/index.js +9 -9
- package/dist/testing/agent-store-conformance.d.ts.map +1 -1
- package/dist/testing.js +57 -23
- package/dist/tool-invoker.js +6 -6
- package/dist/tools/agent.d.ts +6 -0
- package/dist/tools/agent.d.ts.map +1 -1
- package/dist/tools/connections/define.d.ts +6 -0
- package/dist/tools/connections/define.d.ts.map +1 -0
- package/dist/tools/connections/errors.d.ts +50 -0
- package/dist/tools/connections/errors.d.ts.map +1 -0
- package/dist/tools/connections/http.d.ts +3 -0
- package/dist/tools/connections/http.d.ts.map +1 -0
- package/dist/tools/connections/index.d.ts +19 -0
- package/dist/tools/connections/index.d.ts.map +1 -0
- package/dist/tools/connections/index.js +1047 -0
- package/dist/tools/connections/instance.d.ts +3 -0
- package/dist/tools/connections/instance.d.ts.map +1 -0
- package/dist/tools/connections/json-rpc.d.ts +8 -0
- package/dist/tools/connections/json-rpc.d.ts.map +1 -0
- package/dist/tools/connections/limits.d.ts +36 -0
- package/dist/tools/connections/limits.d.ts.map +1 -0
- package/dist/tools/connections/mcp-client.d.ts +44 -0
- package/dist/tools/connections/mcp-client.d.ts.map +1 -0
- package/dist/tools/connections/mcp.d.ts +5 -0
- package/dist/tools/connections/mcp.d.ts.map +1 -0
- package/dist/tools/connections/mount.d.ts +12 -0
- package/dist/tools/connections/mount.d.ts.map +1 -0
- package/dist/tools/connections/openapi-document.d.ts +4 -0
- package/dist/tools/connections/openapi-document.d.ts.map +1 -0
- package/dist/tools/connections/openapi.d.ts +5 -0
- package/dist/tools/connections/openapi.d.ts.map +1 -0
- package/dist/tools/connections/runtime.d.ts +29 -0
- package/dist/tools/connections/runtime.d.ts.map +1 -0
- package/dist/tools/connections/schema-budget.d.ts +8 -0
- package/dist/tools/connections/schema-budget.d.ts.map +1 -0
- package/dist/tools/connections/sse-frames.d.ts +7 -0
- package/dist/tools/connections/sse-frames.d.ts.map +1 -0
- package/dist/tools/connections/sse-session.d.ts +26 -0
- package/dist/tools/connections/sse-session.d.ts.map +1 -0
- package/dist/tools/connections/ssrf.d.ts +15 -0
- package/dist/tools/connections/ssrf.d.ts.map +1 -0
- package/dist/tools/connections/types.d.ts +60 -0
- package/dist/tools/connections/types.d.ts.map +1 -0
- package/dist/tools/durability-context.d.ts +7 -0
- package/dist/tools/durability-context.d.ts.map +1 -0
- package/dist/tools/execute.d.ts +2 -0
- package/dist/tools/execute.d.ts.map +1 -1
- package/dist/tools/registry.d.ts +38 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/runtime-tool.d.ts +4 -0
- package/dist/tools/runtime-tool.d.ts.map +1 -1
- package/dist/tools.d.ts +1 -0
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +83 -26
- package/llms-full.txt +386 -16
- package/llms.txt +1 -0
- package/package.json +9 -1
- package/dist/index-dre2ywck.js +0 -48
- package/dist/{index-evcnmsc3.js → index-t7fkyxcr.js} +3 -3
package/llms-full.txt
CHANGED
|
@@ -48,13 +48,14 @@ own, recorded as an ADR.
|
|
|
48
48
|
|--------|--------|----------|-------|
|
|
49
49
|
| `stitchkit` | browser **and** server | stable | `defineContract`, `createClient`, `createHttpClient`, `createSocketIOClient`, `parseSSE`, the error model |
|
|
50
50
|
| `stitchkit/contract` | browser **and** server | stable | the contract layer alone — `defineContract`, errors, pagination |
|
|
51
|
-
| `stitchkit/live` | browser **and** server | evolving | `defineEvents` — topic declarations beside the operation contract
|
|
51
|
+
| `stitchkit/live` | browser **and** server | evolving | `defineEvents` — topic declarations beside the operation contract — and watched reads: `createWatchClient`, the value/difference frame and its reassembly |
|
|
52
52
|
| `stitchkit/primitives` | browser **and** server | evolving | generic values and declarations for lifecycle, access, audit, delivery and exports |
|
|
53
53
|
| `stitchkit/server` | server (Bun) | stable | `createServer`, `implement`, hooks, auth, Socket.IO server, server primitives |
|
|
54
54
|
| `stitchkit/node` | server (Node ≥ 22) | stable | `serveNode` + the runtime-agnostic core — the Node mirror of `/server` |
|
|
55
55
|
| `stitchkit/tools` | server | stable | `createMcpHandler`, `mountMcp`, `mountAgent`, the OAuth provider, native tools |
|
|
56
56
|
| `stitchkit/tools/contract` | browser + server | evolving | the shapes a tool surface speaks — async-operation contract, snapshot and cancel schemas, view-file input/output — without the runtime that serves them |
|
|
57
57
|
| `stitchkit/tools/invoker` | server | stable | peer-free `createToolInvoker` over the canonical contract tool runner |
|
|
58
|
+
| `stitchkit/tools/connections` | server (Bun or Node) | evolving | consume external MCP servers and a bounded OpenAPI subset — typed reauthorization, a per-request host fence and per-call credentials |
|
|
58
59
|
| `stitchkit/cli` | server | stable | `createCli` — the CLI transport, light (no MCP SDK / `ai`) |
|
|
59
60
|
| `stitchkit/remote` | browser **and** server | stable | peer-free `implementRemote` for thin HTTP proxy processes |
|
|
60
61
|
| `stitchkit/files` | server (Bun or Node) | stable | peer-free managed local-file boundary |
|
|
@@ -63,11 +64,12 @@ own, recorded as an ADR.
|
|
|
63
64
|
| `stitchkit/tracking/server` | server (Bun or Node) | evolving | the decisions a tracking backend makes — dispositions, visit lease over an application-owned store, active intervals, presence; no database |
|
|
64
65
|
| `stitchkit/release` | browser **and** server | evolving | a page follows the release it was built for — `createReleaseMarker` on the server, `createReleaseWatcher` in the browser, the `X-Build-Id` header and a socket event between them |
|
|
65
66
|
| `stitchkit/geo` | server (Bun or Node) | evolving | managed GeoIP reader generations, last-known-good reload and the optional MaxMind adapter |
|
|
66
|
-
| `stitchkit/observability` | server | stable<br>_redefined in 1 of the
|
|
67
|
+
| `stitchkit/observability` | server | stable<br>_redefined in 1 of the 35 minors since 0.56.2, most recently 0.83.0_ | request/tool event projections — `createObservability`, trace context, sanitisation |
|
|
67
68
|
| `stitchkit/testing` | tests on Bun or Node | stable | in-process generated clients over a real Fetch handler, plus the store and managed-resource conformance kits |
|
|
68
69
|
| `stitchkit/declaration` | browser + build and deployment tooling (Bun or Node) | evolving | `ProjectDeclarationSchema` — the one machine-readable statement a repository makes about itself |
|
|
69
70
|
| `stitchkit/react` | browser + server rendering | stable | `createCursorQuery`, `createCacheBridge`, QueryClient and `ApiError` retry policy |
|
|
70
|
-
| `stitchkit/agent-runtime` | server | evolving<br>_redefined in
|
|
71
|
+
| `stitchkit/agent-runtime` | server | evolving<br>_redefined in 20 of the 35 minors since 0.56.2, most recently 0.89.0_ | optional durable conversation/run loop, history, models, prompts, fencing and events |
|
|
72
|
+
| `stitchkit/agent-runtime/sandbox` | server | evolving | optional Linux Bubblewrap sessions, durable workspaces and a host HTTP credential gateway; see [sandbox guide](sandbox.md) |
|
|
71
73
|
| `stitchkit/agent-runtime/testing` | tests on Bun or Node | evolving | credential-free replay, scripted provider faults and deterministic race controls |
|
|
72
74
|
| `stitchkit/agent-runtime/harness` | server | evolving | resource-aware process-local facade over the canonical Agent runtime; supervision stays outside |
|
|
73
75
|
| `stitchkit/agent-runtime/coding-tools` | server (Bun or Node) | evolving | bounded host-authorized direct file and shell tools; a root boundary, not an OS sandbox |
|
|
@@ -76,7 +78,7 @@ own, recorded as an ADR.
|
|
|
76
78
|
| `stitchkit/agent-runtime/sqlite/bun` | server (Bun) | evolving | durable built-in SQLite store for the agent runtime |
|
|
77
79
|
| `stitchkit/agent-runtime/sqlite/node` | server (Node ≥ 22.5) | evolving | durable built-in SQLite store for the agent runtime |
|
|
78
80
|
| `stitchkit-tui` | terminal (Bun) | evolving | optional official OpenTUI host over a caller-composed headless runtime |
|
|
79
|
-
| `stitchkit/application` | browser + server | evolving<br>_redefined in 7 of the
|
|
81
|
+
| `stitchkit/application` | browser + server | evolving<br>_redefined in 7 of the 35 minors since 0.56.2, most recently 0.83.0_ | managed resource graph, readiness, admission, schedules, subtree restart and bounded shutdown |
|
|
80
82
|
| `stitchkit/application/grammy` | server | evolving | isolated grammY polling and webhook lifecycle adapters |
|
|
81
83
|
| `stitchkit/application/opentelemetry` | server | evolving | maps application snapshots onto an injected OpenTelemetry `Meter` |
|
|
82
84
|
| `stitchkit/application/schemas` | browser + server | evolving | the application's snapshot, health and shutdown schemas alone, without the kernel |
|
|
@@ -5583,9 +5585,11 @@ the product has a narrower definition; it receives the candidate message,
|
|
|
5583
5585
|
terminal reason and optional policy name, and runs before persistence. A false
|
|
5584
5586
|
result fails the candidate instead of rewriting an already committed success.
|
|
5585
5587
|
|
|
5586
|
-
`loop.idleTimeoutMs`
|
|
5587
|
-
|
|
5588
|
-
|
|
5588
|
+
`loop.idleTimeoutMs` measures provider silence. It starts immediately before the
|
|
5589
|
+
provider call, resets on stream activity, and pauses while local tools execute.
|
|
5590
|
+
Resource preparation, child waits and approval waiting do not spend this budget.
|
|
5591
|
+
The host gives tools their own deadlines. A stalled provider still aborts with
|
|
5592
|
+
durable reason `timeout`; caller interruption and shutdown reach tools directly.
|
|
5589
5593
|
|
|
5590
5594
|
Reconnect loads the durable snapshot. Missing transient deltas do not mean the
|
|
5591
5595
|
canonical result was lost. Exactly-once external delivery requires the
|
|
@@ -5593,6 +5597,14 @@ application's transactional outbox or stable-ID deduplication.
|
|
|
5593
5597
|
|
|
5594
5598
|
## Managed tools
|
|
5595
5599
|
|
|
5600
|
+
Durable `step` bodies return lossless JSON: finite numbers (excluding negative zero),
|
|
5601
|
+
strings, booleans, null, dense arrays and plain data objects. Return `null` explicitly
|
|
5602
|
+
for effect-only bodies and convert Date values to strings. Unsupported values are
|
|
5603
|
+
refused after the body, so external effects still require idempotency. First results
|
|
5604
|
+
and replay are detached snapshots; mutating a returned object cannot rewrite a record.
|
|
5605
|
+
The optional [sandbox coding profile](sandbox.md#coding-tool-integration) reuses the
|
|
5606
|
+
same tool mounting, authorization and output handling for namespace-backed commands.
|
|
5607
|
+
|
|
5596
5608
|
Always compose `toolFenceLifecycle` into `mountAgent`. It checks ownership
|
|
5597
5609
|
before a managed side effect and again before accepting its result. Fence loss
|
|
5598
5610
|
uses an internal control signal: it stops the old loop and is not sent to the
|
|
@@ -6690,6 +6702,140 @@ the store's first update. Ledger corruption may be declared reconstructable;
|
|
|
6690
6702
|
an outbox must fail closed rather than silently discard pending delivery.
|
|
6691
6703
|
|
|
6692
6704
|
|
|
6705
|
+
==============================================================================
|
|
6706
|
+
# Guide: Optional process sandbox (docs/guide/sandbox.md)
|
|
6707
|
+
==============================================================================
|
|
6708
|
+
|
|
6709
|
+
---
|
|
6710
|
+
title: Optional process sandbox
|
|
6711
|
+
description: Linux namespace isolation, durable workspaces and a host credential gateway.
|
|
6712
|
+
---
|
|
6713
|
+
|
|
6714
|
+
# Optional process sandbox
|
|
6715
|
+
|
|
6716
|
+
`stitchkit/agent-runtime/sandbox` is a server-only, evolving API. Existing coding
|
|
6717
|
+
tools and agent configuration retain their current behavior. A host explicitly
|
|
6718
|
+
creates a session and opts into `createSandboxCodingTools`; importing this
|
|
6719
|
+
entrypoint does not redirect existing coding tools.
|
|
6720
|
+
|
|
6721
|
+
```ts
|
|
6722
|
+
import { createBubblewrapSandboxBackend } from 'stitchkit/agent-runtime/sandbox';
|
|
6723
|
+
|
|
6724
|
+
const backend = await createBubblewrapSandboxBackend({
|
|
6725
|
+
stateDirectory: '/var/lib/my-app/sandboxes',
|
|
6726
|
+
maxConcurrentCommands: 8,
|
|
6727
|
+
onBrokerError: (cause) => console.error('Internal sandbox gateway error', cause),
|
|
6728
|
+
});
|
|
6729
|
+
const template = await backend.prewarm({
|
|
6730
|
+
template: 'agent-workspace',
|
|
6731
|
+
files: { 'hello.txt': new TextEncoder().encode('hello') },
|
|
6732
|
+
});
|
|
6733
|
+
const handle = await backend.create({ template: template.templateKey, network: 'deny-all' });
|
|
6734
|
+
try {
|
|
6735
|
+
const result = await handle.session.run({ executable: '/usr/bin/cat', args: ['hello.txt'] });
|
|
6736
|
+
console.log(result.stdout);
|
|
6737
|
+
const state = handle.captureState(); // Persist this descriptor in the host's store.
|
|
6738
|
+
await handle.stop();
|
|
6739
|
+
const resumed = await backend.create({ template: template.templateKey, state, network: 'deny-all' });
|
|
6740
|
+
try { console.log(await resumed.session.readTextFile('hello.txt')); }
|
|
6741
|
+
finally { await resumed.delete(); }
|
|
6742
|
+
} finally { await handle.shutdown(); }
|
|
6743
|
+
```
|
|
6744
|
+
|
|
6745
|
+
`prewarm` snapshots the supplied byte files. Its content-addressed key includes
|
|
6746
|
+
the backend name, template name and file contents. It is not a VM image or a
|
|
6747
|
+
package installer. `stop` and `shutdown` kill live commands and retain workspace
|
|
6748
|
+
files; `delete` removes session state and workspace, preserving reusable templates.
|
|
6749
|
+
Reconnect requires the same backend name and template. A live owner holds an
|
|
6750
|
+
exclusive lease: concurrent attach and deletion by an older handle fail with
|
|
6751
|
+
`SANDBOX_BUSY`. After a host crash, an operator must verify that its processes are
|
|
6752
|
+
gone before removing a stale lease; automatic crash recovery is not provided.
|
|
6753
|
+
Storage is process-durable, without a power-loss/fsync guarantee.
|
|
6754
|
+
|
|
6755
|
+
## Coding tool integration
|
|
6756
|
+
|
|
6757
|
+
```ts
|
|
6758
|
+
import { createSandboxCodingTools } from 'stitchkit/agent-runtime/sandbox';
|
|
6759
|
+
import { mountAgent } from 'stitchkit/tools';
|
|
6760
|
+
|
|
6761
|
+
const tools = mountAgent([], {
|
|
6762
|
+
runtimeTools: createSandboxCodingTools(handle, {
|
|
6763
|
+
authorize: (operation) => applicationPolicy(operation),
|
|
6764
|
+
executables: { shell: '/usr/bin/sh' },
|
|
6765
|
+
requiredRestrictions: ['network-denied', 'write-contained', 'process-contained', 'secrets-hidden'],
|
|
6766
|
+
limits: { shellTimeoutMs: 10_000, maxShellOutputBytes: 65_536 },
|
|
6767
|
+
}),
|
|
6768
|
+
});
|
|
6769
|
+
```
|
|
6770
|
+
|
|
6771
|
+
The factory uses the existing coding profile, including its authorization,
|
|
6772
|
+
path containment, UTF-8 handling, output artifacts and command limits. File tools
|
|
6773
|
+
access the same workspace through the host's contained-file implementation;
|
|
6774
|
+
commands run inside the namespace with `/workspace` as their root. The host-only
|
|
6775
|
+
`handle.coding` binding never belongs in model input or persisted state.
|
|
6776
|
+
Unsupported backends omit the binding and the factory refuses explicitly.
|
|
6777
|
+
|
|
6778
|
+
Stop also kills coding commands. Both launch paths share the configured
|
|
6779
|
+
`maxConcurrentCommands` admission limit (default 8); an occupied slot gives
|
|
6780
|
+
`SANDBOX_BUSY` before another process starts. This counts direct commands, not
|
|
6781
|
+
guest descendants. Required restrictions are checked again during preparation;
|
|
6782
|
+
a network-policy change invalidates an outstanding prepared launch. After
|
|
6783
|
+
reconnect, create the coding profile from the new handle; old tools remain stopped.
|
|
6784
|
+
|
|
6785
|
+
## Network gateway
|
|
6786
|
+
|
|
6787
|
+
`deny-all` isolates the network namespace, including DNS and loopback access to
|
|
6788
|
+
host services. `{ allow: [{ origin, headers }] }` retains that isolation and
|
|
6789
|
+
allows HTTP through a Unix-socket gateway only. Origins are exact HTTP(S) origins,
|
|
6790
|
+
including scheme and port; no wildcard, redirect, arbitrary TCP or CONNECT tunnel
|
|
6791
|
+
is allowed. For HTTPS upstreams the **host** establishes TLS. Guests speak HTTP
|
|
6792
|
+
over the socket with the upstream host in `Host`, for example:
|
|
6793
|
+
|
|
6794
|
+
```ts
|
|
6795
|
+
await handle.session.setNetworkPolicy({
|
|
6796
|
+
allow: [{ origin: 'https://api.example.com', headers: { authorization: hostCredential } }],
|
|
6797
|
+
});
|
|
6798
|
+
await handle.session.run({
|
|
6799
|
+
executable: '/usr/bin/curl',
|
|
6800
|
+
args: ['--unix-socket', '/run/stitchkit-network.sock', 'http://api.example.com/resource'],
|
|
6801
|
+
});
|
|
6802
|
+
```
|
|
6803
|
+
|
|
6804
|
+
The host obtains `hostCredential` from its credential store. Headers never enter
|
|
6805
|
+
guest environment, process arguments or persisted reconnect state. Authorized
|
|
6806
|
+
upstreams are trusted: an upstream that reflects its request headers can disclose
|
|
6807
|
+
them in its response. This gateway cannot prevent that. Header values are fixed
|
|
6808
|
+
for the policy; replace the policy to rotate credentials. Policy changes require
|
|
6809
|
+
all commands to finish or stop (`SANDBOX_BUSY` otherwise). `allow-all` explicitly
|
|
6810
|
+
shares host networking and adds no injected headers; use it only when unrestricted
|
|
6811
|
+
egress is intended. Policies are resupplied on every reconnect and are not stored.
|
|
6812
|
+
|
|
6813
|
+
## Runtime boundary
|
|
6814
|
+
|
|
6815
|
+
The reference backend requires Linux, `/usr/bin/bwrap`, usable namespaces and a
|
|
6816
|
+
conventional `/usr`, `/lib`, `/lib64` layout. Failure to establish isolation gives
|
|
6817
|
+
`SANDBOX_UNAVAILABLE`; there is no host-execution fallback. Runtime directories
|
|
6818
|
+
are read-only, the workspace is writable, environment is cleared, and host home,
|
|
6819
|
+
state storage and other host sockets are not mounted. Each command gets ephemeral
|
|
6820
|
+
`/tmp`; only `/workspace` persists. Runtime binaries and the configured state
|
|
6821
|
+
directory belong to the trusted host. See the
|
|
6822
|
+
[Bubblewrap security model](https://github.com/containers/bubblewrap#system-security).
|
|
6823
|
+
|
|
6824
|
+
This is namespace isolation over the host kernel, not a VM. It does not impose
|
|
6825
|
+
memory, CPU, disk or process-count quotas. A host running mutually untrusted workloads
|
|
6826
|
+
must supply those bounds outside the namespace (for example, a delegated cgroup and
|
|
6827
|
+
quota-controlled storage); command admission is not a substitute. Commands default to a 30-second deadline
|
|
6828
|
+
and 1 MiB combined output; callers can configure both. File I/O is bounded to
|
|
6829
|
+
1 MiB. The gateway allows 16 concurrent requests, 1 MiB request/response bodies
|
|
6830
|
+
and a 30-second deadline. Do not treat these bounds as resource containment for
|
|
6831
|
+
arbitrary hostile workloads.
|
|
6832
|
+
|
|
6833
|
+
Custom backends implement `SandboxDriver` byte I/O, `spawn` and policy enforcement;
|
|
6834
|
+
`createSandboxSession` supplies text conversion, paths and `run` once. Paths are
|
|
6835
|
+
workspace-relative or canonical `/workspace/...` paths. Unsupported policies must
|
|
6836
|
+
be refused explicitly by the backend.
|
|
6837
|
+
|
|
6838
|
+
|
|
6693
6839
|
==============================================================================
|
|
6694
6840
|
# Guide: Generic application primitives (docs/guide/primitives.md)
|
|
6695
6841
|
==============================================================================
|
|
@@ -8664,13 +8810,49 @@ Nothing an open can fail with escapes as a rejected promise: a disconnected
|
|
|
8664
8810
|
socket, a timeout, a refusal all arrive as `unavailable` carrying the error's own
|
|
8665
8811
|
code and message, and the next connection retries.
|
|
8666
8812
|
|
|
8813
|
+
The re-open carries what the client still holds, so a reconnection is usually
|
|
8814
|
+
cheap: the hub answers with a difference, or with nothing at all when the answer
|
|
8815
|
+
has not moved. That needs the key to still exist on the server — set `holdMs`
|
|
8816
|
+
past your reconnect delay, or the last detach releases the source and the page
|
|
8817
|
+
pays the whole value once.
|
|
8818
|
+
|
|
8819
|
+
### Large answers cross as differences
|
|
8820
|
+
|
|
8821
|
+
A frame carries the value, a **difference** to a revision this subscriber already
|
|
8822
|
+
holds, or `unchanged`. The hub chooses per subscriber and sends a difference only
|
|
8823
|
+
when it is genuinely smaller; your `value` listener sees the rebuilt value either
|
|
8824
|
+
way and needs no code for this.
|
|
8825
|
+
|
|
8826
|
+
It matters when an answer is large and moves a little: a ~75 KB list in which two
|
|
8827
|
+
timestamps change, republished every fifteen seconds, was a megabyte per
|
|
8828
|
+
subscriber per minute before and is a frame under a kilobyte now.
|
|
8829
|
+
|
|
8830
|
+
```ts
|
|
8831
|
+
createWatchHub({
|
|
8832
|
+
// Superseded values kept per key, so a difference has something to be taken
|
|
8833
|
+
// against. Default 262144. Set 0 to send whole values only.
|
|
8834
|
+
deltaMemoryBytes: 256 * 1024,
|
|
8835
|
+
holdMs: 30_000,
|
|
8836
|
+
// …
|
|
8837
|
+
});
|
|
8838
|
+
```
|
|
8839
|
+
|
|
8840
|
+
Reassembly is checked against the server's fingerprint on every frame. If a
|
|
8841
|
+
difference will not apply — a client that missed a revision, a hub that restarted
|
|
8842
|
+
— that **one key** resynchronises: your `state` listener sees `resync-required`
|
|
8843
|
+
and the whole value follows. Other keys on the same socket are untouched.
|
|
8844
|
+
|
|
8845
|
+
Both ends must come from the same major release: a client older than 0.90 reads a
|
|
8846
|
+
difference frame as a value of `undefined`.
|
|
8847
|
+
|
|
8667
8848
|
### `watch` or `createLiveStateController`?
|
|
8668
8849
|
|
|
8669
8850
|
> **If you would have written `applyEvent` as `(_, next) => next`, you want
|
|
8670
|
-
> `watch`:
|
|
8671
|
-
>
|
|
8672
|
-
>
|
|
8673
|
-
> applying both to one value is always a
|
|
8851
|
+
> `watch`: whatever crosses the wire, what your `value` listener receives is the
|
|
8852
|
+
> whole answer.** `createLiveStateController` is for a server whose *protocol* is
|
|
8853
|
+
> deltas that your code folds. `watch` may send a difference too, but it folds it
|
|
8854
|
+
> for you and hands you the value — so applying both to one value is always a
|
|
8855
|
+
> mistake.
|
|
8674
8856
|
|
|
8675
8857
|
### What it cannot promise
|
|
8676
8858
|
|
|
@@ -9600,9 +9782,10 @@ stitchkit answers this at two levels.
|
|
|
9600
9782
|
sanitisation and `createObservability` with independent request/tool sinks.
|
|
9601
9783
|
[Start here ↓](#the-observability-module)
|
|
9602
9784
|
|
|
9603
|
-
stitchkit still ships no logger and no audit store
|
|
9604
|
-
|
|
9605
|
-
normalised record
|
|
9785
|
+
stitchkit still ships no logger and no audit store, and auditing stays opt-in —
|
|
9786
|
+
those are the app's choice (→ ADR 0012, reaffirmed in ADR 0184). What it ships is
|
|
9787
|
+
the machinery that turns a completed call into a clean, normalised record, keeps
|
|
9788
|
+
the ones worth keeping, and does not lose them when the store is down.
|
|
9606
9789
|
|
|
9607
9790
|
## The observability module
|
|
9608
9791
|
|
|
@@ -9839,6 +10022,69 @@ queryable across all three:
|
|
|
9839
10022
|
| `resultSize` / `responseBytes` | result item count + serialised size |
|
|
9840
10023
|
| `userId` / `ipAddress` / `userAgent` | identity |
|
|
9841
10024
|
|
|
10025
|
+
### Write the calls that changed something
|
|
10026
|
+
|
|
10027
|
+
`auditChanges` is the filter most projects end up writing, shipped so they do not
|
|
10028
|
+
have to write it six ways:
|
|
10029
|
+
|
|
10030
|
+
```ts
|
|
10031
|
+
import { auditChanges, createObservability } from 'stitchkit/observability';
|
|
10032
|
+
|
|
10033
|
+
createObservability({
|
|
10034
|
+
request: { write: saveAuditRow, filter: auditChanges },
|
|
10035
|
+
tools: { write: saveAuditRow, filter: auditChanges },
|
|
10036
|
+
});
|
|
10037
|
+
```
|
|
10038
|
+
|
|
10039
|
+
It drops `GET`, `HEAD` and `OPTIONS`, keeps everything else, and keeps `401` and
|
|
10040
|
+
`403` **whatever the verb was** — a refused read is the row an audit exists to
|
|
10041
|
+
hold, and a filter that drops every `GET` drops exactly that. An unrecognised
|
|
10042
|
+
verb is kept: an extra row costs bytes, a missing one costs the answer to "who
|
|
10043
|
+
changed this", silently and only later.
|
|
10044
|
+
|
|
10045
|
+
One filter across HTTP, MCP and agent calls, because a tool call carries its
|
|
10046
|
+
contract verb in `httpMethod` while its `method` is the literal `TOOL`.
|
|
10047
|
+
|
|
10048
|
+
Narrower policy stays yours — compose it:
|
|
10049
|
+
|
|
10050
|
+
```ts
|
|
10051
|
+
filter: (event) => auditChanges(event) && event.serviceName !== 'health',
|
|
10052
|
+
```
|
|
10053
|
+
|
|
10054
|
+
### Keeping the row when the store is down
|
|
10055
|
+
|
|
10056
|
+
A sink is fire-and-forget, so an unreachable store means the event is simply
|
|
10057
|
+
gone — and a store is most likely to be unreachable during an incident, which is
|
|
10058
|
+
the window whose rows someone will later want most.
|
|
10059
|
+
|
|
10060
|
+
`createSpooledSink` writes the row to a local append-only file first, offers it
|
|
10061
|
+
to the store second, and marks it delivered third. What a previous process left
|
|
10062
|
+
unmarked is replayed:
|
|
10063
|
+
|
|
10064
|
+
```ts
|
|
10065
|
+
import { createSpooledSink } from 'stitchkit/observability';
|
|
10066
|
+
|
|
10067
|
+
const audit = createSpooledSink({
|
|
10068
|
+
path: '/var/lib/app/audit.ndjson',
|
|
10069
|
+
write: saveAuditRow,
|
|
10070
|
+
});
|
|
10071
|
+
|
|
10072
|
+
// Once, at startup, before the sink is wired — and await it.
|
|
10073
|
+
const { replayed, failed } = await audit.recover();
|
|
10074
|
+
|
|
10075
|
+
createObservability({ request: { write: audit.write, filter: auditChanges } });
|
|
10076
|
+
```
|
|
10077
|
+
|
|
10078
|
+
The guarantee is **at least once**. A crash between the store accepting a row and
|
|
10079
|
+
the file recording that it did replays the row, so **the store must be idempotent
|
|
10080
|
+
on the record key** — `event.spanId` by default, unique per call. A unique index
|
|
10081
|
+
on it turns the duplicate into a no-op; without one, replay writes the row twice.
|
|
10082
|
+
Exactly-once would need the file and the database to share a transaction. They do
|
|
10083
|
+
not.
|
|
10084
|
+
|
|
10085
|
+
One process, one path. Two processes pointed at the same file replay each other's
|
|
10086
|
+
records: harmless against an idempotent store, wasteful always.
|
|
10087
|
+
|
|
9842
10088
|
### Request context
|
|
9843
10089
|
|
|
9844
10090
|
When request observability is configured, `createHandler` establishes the
|
|
@@ -11236,6 +11482,65 @@ analytics policy belong to the application.
|
|
|
11236
11482
|
|
|
11237
11483
|
# Upgrading stitchkit
|
|
11238
11484
|
|
|
11485
|
+
## Released migration: 0.90.0
|
|
11486
|
+
|
|
11487
|
+
1. `stitchkit.watch.value` is a discriminated union on `kind` — `full`, `delta`,
|
|
11488
|
+
`unchanged` — and every frame carries `fingerprint`. **Both ends must come from
|
|
11489
|
+
the same major.** A client older than this release reads a `delta` frame as a
|
|
11490
|
+
value of `undefined`, silently; upgrade the hub and the pages that talk to it
|
|
11491
|
+
together, or set `deltaMemoryBytes: 0` on the hub until they are.
|
|
11492
|
+
|
|
11493
|
+
Applications using `createWatchClient` need no code change: it rebuilds the
|
|
11494
|
+
value and hands the listener the whole answer as before. Code that reads
|
|
11495
|
+
`WatchValueFrame.value` directly — a hand-written subscriber, a test double —
|
|
11496
|
+
narrows on `kind` first.
|
|
11497
|
+
|
|
11498
|
+
```ts
|
|
11499
|
+
// before: frame.value
|
|
11500
|
+
// after:
|
|
11501
|
+
if (frame.kind === 'full') hold(frame.value);
|
|
11502
|
+
else if (frame.kind === 'delta') hold(applyWatchDelta(held, frame.delta));
|
|
11503
|
+
// 'unchanged' leaves what you hold standing
|
|
11504
|
+
```
|
|
11505
|
+
|
|
11506
|
+
2. `AttachedWatcher.open` takes an optional third argument, `have`. A custom
|
|
11507
|
+
server binding that forwards `stitchkit.watch.open` should pass the payload's
|
|
11508
|
+
`have` through; omitting it costs a whole value on every reconnection and is
|
|
11509
|
+
otherwise harmless.
|
|
11510
|
+
|
|
11511
|
+
## Released migration: 0.89.0
|
|
11512
|
+
|
|
11513
|
+
1. Custom `AgentRuntimeStore` adapters implement `seedConversationInput`; custom
|
|
11514
|
+
`AgentRuntimeStoreDriver` adapters implement `seeds.load` and `seeds.create` together
|
|
11515
|
+
with atomic, ordered history insertion. Use the maintained Prisma example and run
|
|
11516
|
+
`runAgentStoreConformance` against the adapter. Built-in memory and SQLite
|
|
11517
|
+
stores already implement the contract; SQLite migrates to schema version 3.
|
|
11518
|
+
2. OpenRouter usage normalization consumes each completed SDK step's `usage`, including
|
|
11519
|
+
`raw`, rather than aggregate usage. Missing counters stay `unavailable`.
|
|
11520
|
+
|
|
11521
|
+
```ts
|
|
11522
|
+
// before: normalizeOpenRouterUsage(await result.usage, metadata)
|
|
11523
|
+
// after:
|
|
11524
|
+
for (const step of await result.steps) {
|
|
11525
|
+
const usage = normalizeOpenRouterUsage(step.usage, step.providerMetadata);
|
|
11526
|
+
// Persist the step's measured usage with its provenance.
|
|
11527
|
+
}
|
|
11528
|
+
```
|
|
11529
|
+
|
|
11530
|
+
3. Durable step bodies return lossless JSON. Convert dates explicitly, reject invalid
|
|
11531
|
+
numbers upstream, and return `null` after an effect-only operation.
|
|
11532
|
+
|
|
11533
|
+
```ts
|
|
11534
|
+
await context.step('send', async () => {
|
|
11535
|
+
await sendIdempotently();
|
|
11536
|
+
return null;
|
|
11537
|
+
});
|
|
11538
|
+
```
|
|
11539
|
+
|
|
11540
|
+
First execution, replay and concurrent callers receive detached values. Persistence
|
|
11541
|
+
does not make external effects transactional; the host retains idempotency and recovery.
|
|
11542
|
+
|
|
11543
|
+
|
|
11239
11544
|
How to move a consuming project from one stitchkit version to another — including
|
|
11240
11545
|
across many versions at once (a project frozen on an old version, then jumped
|
|
11241
11546
|
forward). The process is mechanical: stitchkit marks every breaking change in one
|
|
@@ -14942,7 +15247,10 @@ realtime contract from `stitchkit`, and the server halves live in `stitchkit/app
|
|
|
14942
15247
|
| `watchContract` | const | the four-event realtime contract a watched read travels on |
|
|
14943
15248
|
| `WATCH_OPEN` / `WATCH_CLOSE` / `WATCH_VALUE` / `WATCH_STATE` | const | the event names of that contract |
|
|
14944
15249
|
| `WatchKey` / `WatchKeySchema` / `watchKeyString` | type / schema / function | `(service, action, arguments digest)` — the identity both ends compute the same way |
|
|
14945
|
-
| `WatchValueFrame` / `WatchValueSchema` / `WatchStateFrame` / `WatchStateSchema` | _types_ |
|
|
15250
|
+
| `WatchValueFrame` / `WatchValueSchema` / `WatchStateFrame` / `WatchStateSchema` | _types_ | one answer — `full`, `delta` or `unchanged`, with its monotonic revision and fingerprint — and a phase from `LiveStatePhase` with the read's own code and message |
|
|
15251
|
+
| `WatchHave` / `WatchHaveSchema` | type / schema | what a reconnecting subscriber already holds, offered on `open`: a revision and the fingerprint that proves it |
|
|
15252
|
+
| `WatchDelta` / `WatchDeltaSchema` / `WatchArrayOp` / `WatchArrayOpSchema` | _types_ / schemas | a structural difference over parsed JSON — objects by changed and dropped key, arrays by runs copied from the previous value |
|
|
15253
|
+
| `watchDiff` / `applyWatchDelta` / `watchDeltaWins` | functions | build a difference (`undefined` when equal), rebuild the value from one (throws rather than inventing), and whether it is actually smaller than the value |
|
|
14946
15254
|
|
|
14947
15255
|
---
|
|
14948
15256
|
|
|
@@ -15559,6 +15867,12 @@ Server-only optional application runtime. See the
|
|
|
15559
15867
|
| `AgentConversationPageSchema` / `AgentConversationPage` | schema / _type_ | cursor-paged conversation summaries |
|
|
15560
15868
|
| `AgentConversationMessagePageSchema` / `AgentConversationMessagePage` | schema / _type_ | cursor-paged durable message history |
|
|
15561
15869
|
| `composeAgentPrompt` | function | ordered prompt contributions and provenance-aware signed context budget; irreducible reservation deficits are `oversized`, not compactable history |
|
|
15870
|
+
| `SeedConversationInputSchema` / `SeedConversationInput` | schema / _type_ | atomic once-seeding input; partial imported identity sets are refused |
|
|
15871
|
+
| `AgentSeedReceiptSchema` / `AgentSeedReceipt` | schema / _type_ | durable seed receipt retained beyond compaction and implemented by custom store drivers |
|
|
15872
|
+
| `createLocalStepDurability` | function | record JSON step results and park on time/events; a replay returns recorded results, while unrecorded effects require host idempotency |
|
|
15873
|
+
| `StepDurabilityLedger` / `LocalStepDurability` / `LocalStepDurabilityOptions` / `StepRunOptions` | _type_ | the narrow ledger the port needs, the step/read surface, and its construction and per-step options |
|
|
15874
|
+
| `DURABILITY_STEP_EVENT_KIND` | const | the ledger event kind a recorded step is written under |
|
|
15875
|
+
| `StepResultDecodeError` / `StepResultNotSerializableError` / `StepAbortedError` / `ParkRecordDecodeError` / `ParkAbortedError` | class | fail-closed decode of a recorded step or park, a body whose result cannot be serialized, an aborted step, and a park collapsed around an aborted waiter |
|
|
15562
15876
|
| `structuredCompaction` | function | summarize a provider-valid snapshot range and replace it through CAS |
|
|
15563
15877
|
| `selectCompactableHistory` | function | which oldest whole complete turns may be summarised away — the half of compaction that needs no store (→ ADR 0142) |
|
|
15564
15878
|
| `SelectCompactableHistoryOptions` / `CompactableHistory` | _type_ | message list, retained-turn count and evidence policy in; `leadingSummary`, `compactable` and `retained` out |
|
|
@@ -15599,10 +15913,12 @@ Server-only optional application runtime. See the
|
|
|
15599
15913
|
| `agentGoalStateSlot` / `agentTodoStateSlot` / `createAgentStateTools` | constants / function | built-in goal/todo state and bound `goal_*` / `todo_write` Agent tools |
|
|
15600
15914
|
| `AgentSandboxGradeSchema` / `AgentSandboxGrade` / `AgentSandboxRestrictionSchema` / `AgentSandboxRestriction` / `AgentProcessSandbox` | schema / _type_ | host-provided process sandbox capability and explicit restriction vocabulary |
|
|
15601
15915
|
| `probeAgentProcessSandbox` / `missingSandboxRestrictions` / `recordAgentSandboxProbe` | functions | process-cached probe, fail-closed required-gap calculation and durable probe record |
|
|
15916
|
+
| `AgentSandboxProcess` / `AgentSandboxOutputStream` | _types_ | structural child/output interface for optional lifecycle-owned `AgentProcessSandbox.spawn`, without Node ambient type dependencies |
|
|
15602
15917
|
| `AgentEventSearchResultSchema` / `AgentEventSearchResult` / `createSqliteAgentEventSearch` / `createAgentEventSearchTools` | schema / _type_ / functions | authorized FTS5 search with exact event addresses and `session_*` tools |
|
|
15603
15918
|
| `createSqliteAgentSpillStore` | function | durable content-address-checked artifact storage, bounded read/search, retention facts and archive participation |
|
|
15604
15919
|
| `AgentScheduleSchema` / `AgentSchedule` / `AgentScheduleService` / `createAgentScheduleService` / `createAgentScheduleTools` | schema / _types_ / functions | durable `at`/`after`/timezone-explicit `every`, stable dispatch identity and Agent tools |
|
|
15605
15920
|
| `AgentChildBudgetSchema` / `AgentChildBudget` / `AgentChildStateSchema` / `AgentChildState` / `AgentChildRecordSchema` / `AgentChildRecord` | schema / _type_ | durable child graph, bounded seed and measured budget state |
|
|
15921
|
+
| `AgentChildBlockingKindSchema` / `AgentChildBlockingKind` / `AgentChildBlockingSourceSchema` / `AgentChildBlockingSource` / `AgentChildBlockingEventSchema` / `AgentChildBlockingEvent` / `AgentChildBlockingDecision` | schemas / _types_ | parent-owned request identities; responses discriminate approval decisions from JSON input values |
|
|
15606
15922
|
| `AgentChildHandle` / `AgentChildManager` / `createSqliteAgentChildManager` / `createAgentChildTools` / `agentChildBudgetStopPolicy` | _type_ / functions | host execution port, child lifecycle, cascade (given to `createAgentRuntime` as `children`), messaging, Agent tools, and the child runtime's own budget stop policy — `recordStepUsage` at every step boundary, `policy_stop` as `child-budget` when spent |
|
|
15607
15923
|
| `AgentToolDefinition` | _type_ | peer-neutral shape returned by the bound agent-only state, search, schedule and child tool factories |
|
|
15608
15924
|
| `AgentProviderStreamCutError` | class | explicit retryable provider stream truncation evidence |
|
|
@@ -15630,7 +15946,11 @@ recognises a failure carried inside a *successful* tool result, in both the bare
|
|
|
15630
15946
|
|
|
15631
15947
|
`normalizeOpenRouterUsage` is the same normalisation `openRouterProvider`
|
|
15632
15948
|
applies, exported so an application calling the SDK directly gets provenance-correct numbers
|
|
15633
|
-
without adopting the runtime.
|
|
15949
|
+
without adopting the runtime. Pass each completed SDK step's usage, including `raw`.
|
|
15950
|
+
Token provenance comes from the original OpenRouter fields: missing fields remain
|
|
15951
|
+
`unavailable`, even when the SDK substitutes zero. Aggregate usage without `raw` cannot
|
|
15952
|
+
establish reported token counts. Explicit zero remains `provider-reported`; cost is never
|
|
15953
|
+
estimated from token prices.
|
|
15634
15954
|
|
|
15635
15955
|
`AgentContextUsage` reaches every step through `AgentRuntimeRunContext.contextUsage`: how full the
|
|
15636
15956
|
model's context is, as `usedTokens` (an `AgentUsageValue`, so it carries the provenance that says
|
|
@@ -15789,6 +16109,9 @@ and introduces no store, queue or model-provider implementation of its own.
|
|
|
15789
16109
|
| `AgentHarnessControlServer` / `AgentHarnessControlConnection` | _type_ | host server and detachable connection lifecycle; `deliver` is serialized, while required out-of-band `onOverflow` closes/aborts a slow transport before reconnect |
|
|
15790
16110
|
| `AgentHarnessControlServerConfig` | _type_ | explicit per-connection pending-event and server-wide concurrent attachment-snapshot bounds for failure-isolated control delivery |
|
|
15791
16111
|
| `AgentHarnessPendingApproval` / `AgentHarnessApprovalDecision` | _type_ | exact durable pending request and allow/deny successor input |
|
|
16112
|
+
| `AgentHarnessApprovalRequest` | _type_ | the pending request as a response-time policy sees it: approval id, call id, tool name and input |
|
|
16113
|
+
| `AgentHarnessApprovalAuthorization` / `AgentHarnessApprovalAuthorizationResult` | _type_ | response-time policy input (responder, conversation, request, proposed decision) and its `allowed` / `rejected` result |
|
|
16114
|
+
| `AgentHarnessApprovalRejectedError` | class | thrown when the response policy refuses a responder; the pending request is left answerable |
|
|
15792
16115
|
|
|
15793
16116
|
Resources default to at most 64 entries, 1 MiB of total UTF-8 text and 128 diagnostics. Duplicate
|
|
15794
16117
|
names and exceeded bounds fail before the provider step. Recovery remains the underlying runtime's
|
|
@@ -15948,6 +16271,8 @@ audit event. See the [Observability guide](../guide/observability.md).
|
|
|
15948
16271
|
| Export | Kind | Summary |
|
|
15949
16272
|
|--------|------|---------|
|
|
15950
16273
|
| `createObservability` | function | configure framework-owned request completion and canonical tool event sinks — [guide](../guide/observability.md#createobservability) |
|
|
16274
|
+
| `auditChanges` | function | the sink `filter` most projects write themselves — drops `GET`/`HEAD`/`OPTIONS`, keeps `401`/`403` whatever the verb, keeps an unrecognised verb |
|
|
16275
|
+
| `createSpooledSink` / `SpooledSink` / `SpooledSinkConfig` / `SpoolRecovery` | function / _types_ | spool the row to an append-only file before the store and replay what a previous process left undelivered — at least once, keyed on `spanId` |
|
|
15951
16276
|
| `createDimensionsProjector` / `DimensionsProjector` / `DimensionsProjectorConfig` / `ProjectedDimensions` | function / _type_ | typed request/result/error attribution projected into the existing request context |
|
|
15952
16277
|
| `DimensionCollision` / `SetRequestDimensionsOptions` | _type_ | explicit overwrite, preserve or error policy for dimension keys |
|
|
15953
16278
|
| `createBoundedLogger` | function | decorate a `StitchLogger` with request context, shared sanitisation, redaction and total bounds |
|
|
@@ -16105,6 +16430,8 @@ payload.
|
|
|
16105
16430
|
| `RuntimeAgentModelOutput` | _type_ | AI SDK model-facing text/JSON/content output returned by `present.agent` |
|
|
16106
16431
|
| `RuntimeToolTransport` | _type_ | runtime exposure: `'MCP' \| 'AGENT' \| 'CLI'`; omission still means MCP+Agent only |
|
|
16107
16432
|
| `AgentMountConfig` | _type_ | config for `mountAgent` |
|
|
16433
|
+
| `AgentToolRegistry` / `AgentToolRegistryBuilder` / `AgentToolRegistryInput` | _type_ | the composed runtime surface and its builder: declared defaults, `replace`/`disable` by name, and the exact `{ tools, names }` a mount receives |
|
|
16434
|
+
| `defineToolRegistry` | function | compose runtime tools over one declared default set; an unknown `replace`/`disable` name is refused instead of silently leaving the default in place |
|
|
16108
16435
|
| `AgentContext` | _type_ | the context merged into agent tool handlers |
|
|
16109
16436
|
| `CliConfig` | _type_ | config for `createCli`, including program-level `defaultCommand` selection and command-scoped `optionAliases` / `positionals` policy |
|
|
16110
16437
|
| `CliPresentationPolicyConfig` | _type_ | reusable default-command, short-alias and explicit-positional policy inherited by `CliConfig` |
|
|
@@ -16267,6 +16594,36 @@ Advanced building blocks — the shared machinery the mounts are built on.
|
|
|
16267
16594
|
|
|
16268
16595
|
---
|
|
16269
16596
|
|
|
16597
|
+
## `stitchkit/tools/connections`
|
|
16598
|
+
|
|
16599
|
+
Server-only subexport that consumes external MCP servers and OpenAPI specifications
|
|
16600
|
+
as typed tools, without adding a peer dependency to `stitchkit/tools`. Foreign
|
|
16601
|
+
operations mount as the same `RuntimeToolDefinition`s our own produce, so
|
|
16602
|
+
`mountAgent({ runtimeTools })` runs them through the canonical lifecycle, hooks
|
|
16603
|
+
and approval path.
|
|
16604
|
+
|
|
16605
|
+
| Export | Kind | Summary |
|
|
16606
|
+
|--------|------|---------|
|
|
16607
|
+
| `defineMcpClientConnection` | function | declare one external MCP server connection over Streamable HTTP with an optional SSE fallback |
|
|
16608
|
+
| `defineOpenApiConnection` | function | declare one OpenAPI document (object, JSON text or JSON URL) as a tool surface |
|
|
16609
|
+
| `mountConnections` | function | discover every connection and return readonly `RuntimeToolDefinition`s for `mountAgent` |
|
|
16610
|
+
| `ConnectionAuthorizationRequiredError` | class | typed reauthorization signal raised on `401` with credentials resolved again on the next call |
|
|
16611
|
+
| `ConnectionBudgetExceededError` | class | the mount would expose more foreign tools than its declared budget |
|
|
16612
|
+
| `ConnectionRequestError` | class | any non-`2xx` connection response other than the reauthorization signal |
|
|
16613
|
+
| `ConnectionUrlError` | class | a non-http(s) URL or a request host the SSRF fence refused |
|
|
16614
|
+
| `ConnectionTokenProvider` | _type_ | `() => string \| undefined \| Promise<string \| undefined>` — the lazily resolved credential |
|
|
16615
|
+
| `ConnectionBudget` | _type_ | `{ maxTools? }` ceiling on one `mountConnections` call |
|
|
16616
|
+
| `ConnectionDefinition` | _type_ | either a defined MCP client or OpenAPI connection |
|
|
16617
|
+
| `ConnectionMountOptions` | _type_ | shared `{ lifecycle?, budget? }` mount policy |
|
|
16618
|
+
| `McpClientConnection` | _type_ | a defined MCP client connection |
|
|
16619
|
+
| `McpClientConnectionConfig` | _type_ | name, transport, tool filter, token provider, instance key and allowed hosts |
|
|
16620
|
+
| `McpConnectionTransport` | _type_ | `{ url, headers? }` for one MCP endpoint |
|
|
16621
|
+
| `McpToolFilter` | _type_ | `{ allow?, block? }` discovered-tool filter |
|
|
16622
|
+
| `OpenApiConnection` | _type_ | a defined OpenAPI connection |
|
|
16623
|
+
| `OpenApiConnectionConfig` | _type_ | name, spec, base URL, token provider, instance key and allowed hosts |
|
|
16624
|
+
|
|
16625
|
+
---
|
|
16626
|
+
|
|
16270
16627
|
## `stitchkit/testing`
|
|
16271
16628
|
|
|
16272
16629
|
Fetch-only integration helpers that preserve the real generated-client and
|
|
@@ -16639,3 +16996,16 @@ Browser- and server-render-safe React data-layer helpers. Needs the
|
|
|
16639
16996
|
For the rationale behind these APIs — why `Bun.serve` and not a framework, why
|
|
16640
16997
|
two context types, why thin wrappers — see the
|
|
16641
16998
|
[Architecture Decisions](../decisions/).
|
|
16999
|
+
|
|
17000
|
+
## `stitchkit/agent-runtime/sandbox`
|
|
17001
|
+
|
|
17002
|
+
Optional server-only namespace sandbox. Exports:
|
|
17003
|
+
`createSandboxCodingTools` composes the existing coding profile over a handle's
|
|
17004
|
+
host-only `SandboxCodingBinding`, with shared authorization, command collection and lifecycle.
|
|
17005
|
+
`createBubblewrapSandboxBackend`, `createSandboxSession`, `SandboxError`,
|
|
17006
|
+
`SandboxCommandSchema`, `SandboxNetworkPolicySchema`, `SandboxStateSchema`.
|
|
17007
|
+
Its types are `BubblewrapSandboxConfig`, `SandboxBackend`, `SandboxCommand`,
|
|
17008
|
+
`SandboxCreateInput`, `SandboxDriver`, `SandboxHandle`, `SandboxNetworkPolicy`,
|
|
17009
|
+
`SandboxPrewarmInput`, `SandboxProcess`, `SandboxRunOptions`, `SandboxSession`,
|
|
17010
|
+
and `SandboxState`. The [sandbox guide](../guide/sandbox.md) specifies lifecycle,
|
|
17011
|
+
network enforcement, gateway credentials and platform/resource boundaries.
|
package/llms.txt
CHANGED
|
@@ -14,6 +14,7 @@ Build with stitchkit: define a contract once, then `implement` it and serve it (
|
|
|
14
14
|
- [MCP & agents](https://github.com/max-listov/stitchkit/blob/master/docs/guide/mcp-and-agents.md): contracts as MCP tools (createMcpHandler) and AI-agent tools (mountAgent); tool lifecycle, extend, identity
|
|
15
15
|
- [Agent application runtime](https://github.com/max-listov/stitchkit/blob/master/docs/guide/agent-runtime.md): optional durable history, prompt/model composition, stream loop, coordination, fencing and events
|
|
16
16
|
- [Managed application kernel](https://github.com/max-listov/stitchkit/blob/master/docs/guide/application-kernel.md): process-local resources, readiness, admission, schedules, projections and optional provider adapters
|
|
17
|
+
- [Optional process sandbox](https://github.com/max-listov/stitchkit/blob/master/docs/guide/sandbox.md): Linux Bubblewrap sessions, durable workspace reconnect, network policy and host credential brokering
|
|
17
18
|
- [Generic application primitives](https://github.com/max-listov/stitchkit/blob/master/docs/guide/primitives.md): lifecycle transitions, owner scope, permissions, exact money and quantities, deadlines, audit, delivery and exports — declared, not persisted
|
|
18
19
|
- [Application migration recipes](https://github.com/max-listov/stitchkit/blob/master/docs/guide/application-migration-recipes.md): executable database, poller, queue-consumer and operational publishing cutovers
|
|
19
20
|
- [CLI](https://github.com/max-listov/stitchkit/blob/master/docs/guide/cli.md): contracts as a command-line program
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stitchkit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.90.0",
|
|
4
4
|
"description": "Contract-first backend framework — one defineContract() into an HTTP API, MCP tools, AI-agent tools and a typed client. Bun and Node.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bun",
|
|
@@ -73,6 +73,10 @@
|
|
|
73
73
|
"types": "./dist/tool-invoker.d.ts",
|
|
74
74
|
"import": "./dist/tool-invoker.js"
|
|
75
75
|
},
|
|
76
|
+
"./tools/connections": {
|
|
77
|
+
"types": "./dist/tools/connections/index.d.ts",
|
|
78
|
+
"import": "./dist/tools/connections/index.js"
|
|
79
|
+
},
|
|
76
80
|
"./cli": {
|
|
77
81
|
"types": "./dist/cli.d.ts",
|
|
78
82
|
"import": "./dist/cli.js"
|
|
@@ -153,6 +157,10 @@
|
|
|
153
157
|
"types": "./dist/testing.d.ts",
|
|
154
158
|
"import": "./dist/testing.js"
|
|
155
159
|
},
|
|
160
|
+
"./agent-runtime/sandbox": {
|
|
161
|
+
"types": "./dist/agent-runtime-sandbox.d.ts",
|
|
162
|
+
"import": "./dist/agent-runtime-sandbox.js"
|
|
163
|
+
},
|
|
156
164
|
"./files": {
|
|
157
165
|
"types": "./dist/files.d.ts",
|
|
158
166
|
"import": "./dist/files.js"
|
package/dist/index-dre2ywck.js
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
LiveStatePhaseSchema,
|
|
3
|
-
LiveStateStopReasonSchema
|
|
4
|
-
} from "./index-ywd0y6m1.js";
|
|
5
|
-
|
|
6
|
-
// src/live/watch-contract.ts
|
|
7
|
-
import { z } from "zod";
|
|
8
|
-
var WatchKeySchema = z.object({
|
|
9
|
-
service: z.string().min(1),
|
|
10
|
-
action: z.string().min(1),
|
|
11
|
-
digest: z.string().min(1)
|
|
12
|
-
}).strict().readonly();
|
|
13
|
-
var WatchOpenSchema = z.object({ key: WatchKeySchema, args: z.unknown() }).readonly();
|
|
14
|
-
var WatchAcceptedSchema = z.object({
|
|
15
|
-
accepted: z.boolean(),
|
|
16
|
-
reason: z.string().optional()
|
|
17
|
-
}).strict().readonly();
|
|
18
|
-
var WatchValueSchema = z.object({
|
|
19
|
-
key: WatchKeySchema,
|
|
20
|
-
revision: z.number().int().nonnegative(),
|
|
21
|
-
value: z.unknown()
|
|
22
|
-
}).readonly();
|
|
23
|
-
var WatchStateSchema = z.object({
|
|
24
|
-
key: WatchKeySchema,
|
|
25
|
-
phase: LiveStatePhaseSchema,
|
|
26
|
-
reason: LiveStateStopReasonSchema.optional(),
|
|
27
|
-
code: z.string().optional(),
|
|
28
|
-
message: z.string().optional()
|
|
29
|
-
}).readonly();
|
|
30
|
-
var WATCH_OPEN = "stitchkit.watch.open";
|
|
31
|
-
var WATCH_CLOSE = "stitchkit.watch.close";
|
|
32
|
-
var WATCH_VALUE = "stitchkit.watch.value";
|
|
33
|
-
var WATCH_STATE = "stitchkit.watch.state";
|
|
34
|
-
var watchContract = {
|
|
35
|
-
serverToClient: {
|
|
36
|
-
[WATCH_VALUE]: { args: z.tuple([WatchValueSchema]) },
|
|
37
|
-
[WATCH_STATE]: { args: z.tuple([WatchStateSchema]) }
|
|
38
|
-
},
|
|
39
|
-
clientToServer: {
|
|
40
|
-
[WATCH_OPEN]: { args: z.tuple([WatchOpenSchema]), ack: WatchAcceptedSchema },
|
|
41
|
-
[WATCH_CLOSE]: { args: z.tuple([z.object({ key: WatchKeySchema }).readonly()]) }
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
function watchKeyString(key) {
|
|
45
|
-
return `${key.service}/${key.action}/${key.digest}`;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export { WatchKeySchema, WatchValueSchema, WatchStateSchema, WATCH_OPEN, WATCH_CLOSE, WATCH_VALUE, WATCH_STATE, watchContract, watchKeyString };
|