stitchkit 0.104.1 → 0.105.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 +381 -12
- package/darwin-native.cjs +4 -2
- package/dist/agent-runtime/browser-control-contract.d.ts +32 -2
- package/dist/agent-runtime/browser-control-contract.d.ts.map +1 -1
- package/dist/agent-runtime/browser-controller.d.ts +21 -3
- package/dist/agent-runtime/browser-controller.d.ts.map +1 -1
- package/dist/agent-runtime/coding-shell-process.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-refusals.d.ts +1 -0
- package/dist/agent-runtime/coding-tool-refusals.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-shell.d.ts.map +1 -1
- package/dist/agent-runtime/compaction.d.ts.map +1 -1
- package/dist/agent-runtime/contained-write.d.ts.map +1 -1
- package/dist/agent-runtime/control-schema.d.ts +48 -1
- package/dist/agent-runtime/control-schema.d.ts.map +1 -1
- package/dist/agent-runtime/deferred-tool-search.d.ts +3 -2
- package/dist/agent-runtime/deferred-tool-search.d.ts.map +1 -1
- package/dist/agent-runtime/harness-control.d.ts.map +1 -1
- package/dist/agent-runtime/harness-realtime.d.ts +34 -4
- package/dist/agent-runtime/harness-realtime.d.ts.map +1 -1
- package/dist/agent-runtime/runtime-recovery.d.ts.map +1 -1
- package/dist/agent-runtime/runtime-state.d.ts.map +1 -1
- package/dist/agent-runtime/sandbox-contract.d.ts.map +1 -1
- package/dist/agent-runtime/sandbox-process-owner.d.ts +9 -1
- package/dist/agent-runtime/sandbox-process-owner.d.ts.map +1 -1
- package/dist/agent-runtime/sandbox.d.ts +32 -1
- package/dist/agent-runtime/sandbox.d.ts.map +1 -1
- package/dist/agent-runtime/schedule-records.d.ts.map +1 -1
- package/dist/agent-runtime/schedules.d.ts.map +1 -1
- package/dist/agent-runtime/store-events.d.ts +9 -4
- package/dist/agent-runtime/store-events.d.ts.map +1 -1
- package/dist/agent-runtime/testing.d.ts.map +1 -1
- package/dist/application/diagnostic-journal-contract.d.ts +50 -0
- package/dist/application/diagnostic-journal-contract.d.ts.map +1 -1
- package/dist/application/diagnostic-journal-generations.d.ts +24 -0
- package/dist/application/diagnostic-journal-generations.d.ts.map +1 -0
- package/dist/application/diagnostic-journal-manager.d.ts.map +1 -1
- package/dist/application/diagnostic-journal-open.d.ts +10 -0
- package/dist/application/diagnostic-journal-open.d.ts.map +1 -0
- package/dist/application/diagnostic-journal-quarantine.d.ts +28 -0
- package/dist/application/diagnostic-journal-quarantine.d.ts.map +1 -0
- package/dist/application/diagnostic-journal-read-contract.d.ts +73 -3
- package/dist/application/diagnostic-journal-read-contract.d.ts.map +1 -1
- package/dist/application/diagnostic-journal-reader.d.ts +17 -2
- package/dist/application/diagnostic-journal-reader.d.ts.map +1 -1
- package/dist/application/diagnostic-journal-recovery.d.ts +18 -2
- package/dist/application/diagnostic-journal-recovery.d.ts.map +1 -1
- package/dist/application/diagnostic-journal-storage.d.ts +6 -2
- package/dist/application/diagnostic-journal-storage.d.ts.map +1 -1
- package/dist/application/diagnostic-journal-tail.d.ts +12 -0
- package/dist/application/diagnostic-journal-tail.d.ts.map +1 -0
- package/dist/application/diagnostic-journal.d.ts +3 -0
- package/dist/application/diagnostic-journal.d.ts.map +1 -1
- package/dist/application/directory-inbox-accept.d.ts +3 -3
- package/dist/application/directory-inbox-accept.d.ts.map +1 -1
- package/dist/application/directory-inbox-contract.d.ts +38 -10
- package/dist/application/directory-inbox-contract.d.ts.map +1 -1
- package/dist/application/directory-inbox-delivery.d.ts +3 -3
- package/dist/application/directory-inbox-delivery.d.ts.map +1 -1
- package/dist/application/directory-inbox-files.d.ts +17 -2
- package/dist/application/directory-inbox-files.d.ts.map +1 -1
- package/dist/application/directory-inbox-state.d.ts +1 -1
- package/dist/application/directory-inbox-state.d.ts.map +1 -1
- package/dist/application/directory-inbox.d.ts +1 -1
- package/dist/application/directory-inbox.d.ts.map +1 -1
- package/dist/application/file-state-store.d.ts +21 -1
- package/dist/application/file-state-store.d.ts.map +1 -1
- package/dist/application/grammy.d.ts.map +1 -1
- package/dist/application/kernel-contract.d.ts.map +1 -1
- package/dist/application/revision-signal.d.ts.map +1 -1
- package/dist/application/state-store.d.ts +3 -0
- package/dist/application/state-store.d.ts.map +1 -1
- package/dist/browser/api-error.d.ts +38 -0
- package/dist/browser/api-error.d.ts.map +1 -0
- package/dist/browser/chunked-upload.d.ts.map +1 -1
- package/dist/browser/client-executors.d.ts.map +1 -1
- package/dist/browser/client-url.d.ts.map +1 -1
- package/dist/browser/contract-stream.d.ts.map +1 -1
- package/dist/browser/http.d.ts +0 -25
- package/dist/browser/http.d.ts.map +1 -1
- package/dist/browser/resumable.d.ts.map +1 -1
- package/dist/contract/define-validation.d.ts +0 -1
- package/dist/contract/define-validation.d.ts.map +1 -1
- package/dist/contract/define.d.ts.map +1 -1
- package/dist/contract/errors-factory.d.ts.map +1 -1
- package/dist/contract/errors.d.ts +15 -18
- package/dist/contract/errors.d.ts.map +1 -1
- package/dist/contract/normalize.d.ts.map +1 -1
- package/dist/durability/effect.d.ts.map +1 -1
- package/dist/durability/scheduler.d.ts.map +1 -1
- package/dist/entrypoints/agent-runtime/browser.js +29 -18
- package/dist/entrypoints/agent-runtime/coding-tools.js +8 -7
- package/dist/entrypoints/agent-runtime/harness.js +15 -14
- package/dist/entrypoints/agent-runtime/realtime.d.ts +1 -1
- package/dist/entrypoints/agent-runtime/realtime.d.ts.map +1 -1
- package/dist/entrypoints/agent-runtime/realtime.js +119 -54
- package/dist/entrypoints/agent-runtime/sandbox.js +23 -17
- package/dist/entrypoints/agent-runtime/sqlite/bun.js +4 -3
- package/dist/entrypoints/agent-runtime/sqlite/node.js +4 -3
- package/dist/entrypoints/agent-runtime/testing.js +8 -6
- package/dist/entrypoints/agent-runtime.js +37 -38
- package/dist/entrypoints/application/diagnostic-journal.js +305 -111
- package/dist/entrypoints/application/directory-inbox.js +174 -77
- package/dist/entrypoints/application/grammy.js +5 -2
- package/dist/entrypoints/application/opentelemetry.js +2 -2
- package/dist/entrypoints/application.d.ts +2 -2
- package/dist/entrypoints/application.d.ts.map +1 -1
- package/dist/entrypoints/application.js +17 -8
- package/dist/entrypoints/cli/publish.d.ts +16 -0
- package/dist/entrypoints/cli/publish.d.ts.map +1 -0
- package/dist/entrypoints/cli/publish.js +527 -0
- package/dist/entrypoints/cli.d.ts +1 -2
- package/dist/entrypoints/cli.d.ts.map +1 -1
- package/dist/entrypoints/cli.js +59 -966
- package/dist/entrypoints/contract.js +3 -3
- package/dist/entrypoints/files/packaging.js +196 -56
- package/dist/entrypoints/files.d.ts +1 -0
- package/dist/entrypoints/files.d.ts.map +1 -1
- package/dist/entrypoints/files.js +17 -10
- package/dist/entrypoints/index.d.ts +2 -1
- package/dist/entrypoints/index.d.ts.map +1 -1
- package/dist/entrypoints/index.js +31 -60
- package/dist/entrypoints/node.js +8 -8
- package/dist/entrypoints/observability.js +3 -3
- package/dist/entrypoints/primitives.js +67 -83
- package/dist/entrypoints/process.d.ts +1 -1
- package/dist/entrypoints/process.d.ts.map +1 -1
- package/dist/entrypoints/process.js +2 -2
- package/dist/entrypoints/react.js +4 -2
- package/dist/entrypoints/remote.js +37 -13
- package/dist/entrypoints/server.js +18 -16
- package/dist/entrypoints/telegram/screens.js +5 -3
- package/dist/entrypoints/telegram.js +31 -46
- package/dist/entrypoints/testing.d.ts +1 -1
- package/dist/entrypoints/testing.d.ts.map +1 -1
- package/dist/entrypoints/testing.js +444 -448
- package/dist/entrypoints/tools/connections.js +268 -105
- package/dist/entrypoints/tools/contract.js +2 -2
- package/dist/entrypoints/tools/invoker.js +8 -7
- package/dist/entrypoints/tools/mcp.d.ts +2 -2
- package/dist/entrypoints/tools/mcp.d.ts.map +1 -1
- package/dist/entrypoints/tools/mcp.js +10 -9
- package/dist/entrypoints/tools.d.ts +0 -1
- package/dist/entrypoints/tools.d.ts.map +1 -1
- package/dist/entrypoints/tools.js +118 -53
- package/dist/entrypoints/tracking.js +2 -3
- package/dist/files/boundary.d.ts +2 -2
- package/dist/files/boundary.d.ts.map +1 -1
- package/dist/files/chunk-spool.d.ts.map +1 -1
- package/dist/files/file-io.d.ts +2 -2
- package/dist/files/file-io.d.ts.map +1 -1
- package/dist/files/native-packaging-layout.d.ts +50 -4
- package/dist/files/native-packaging-layout.d.ts.map +1 -1
- package/dist/files/native-packaging.d.ts +104 -21
- package/dist/files/native-packaging.d.ts.map +1 -1
- package/dist/{index-r5hsgkz5.js → index-0gs4ymfj.js} +6 -3
- package/dist/{index-zax7resm.js → index-0gxvns6s.js} +1 -13
- package/dist/index-0s4xebbg.js +8 -0
- package/dist/{index-r4r70zmh.js → index-12zsej7b.js} +5 -2
- package/dist/{index-kemm0ej5.js → index-1pwwan01.js} +65 -22
- package/dist/{index-vgkbcnkc.js → index-299sm5tr.js} +1 -1
- package/dist/{index-2vnh05w4.js → index-2k91mewf.js} +31 -74
- package/dist/{index-269zqj8m.js → index-2rc6jd9n.js} +28 -12
- package/dist/{index-wh0ecvyk.js → index-37asdw3a.js} +1 -1
- package/dist/index-3h0ztg0z.js +285 -0
- package/dist/{index-g95fk660.js → index-4vsby8n8.js} +8 -15
- package/dist/index-556g5hsh.js +17 -0
- package/dist/{index-adhgd4pe.js → index-5p55xreg.js} +2 -2
- package/dist/index-5w6t91ze.js +47 -0
- package/dist/{index-9pw0a51a.js → index-6yxhe58g.js} +40 -7
- package/dist/{index-6d9xaxw1.js → index-8ks9b85e.js} +33 -5
- package/dist/{index-bhb950qs.js → index-916yh4e2.js} +25 -12
- package/dist/index-9tqbxv5p.js +44 -0
- package/dist/{index-5csmzesf.js → index-azx12jgv.js} +4 -3
- package/dist/{index-mbnnw3f2.js → index-b0kddvzw.js} +15 -5
- package/dist/{index-n5yqxd3d.js → index-b0w7rbpt.js} +23 -2
- package/dist/index-b56nnscm.js +132 -0
- package/dist/{index-0ndk4555.js → index-c0hffcmj.js} +2 -2
- package/dist/{index-pptyv13k.js → index-c17xcx4k.js} +42 -6
- package/dist/{index-g2j7pnak.js → index-cmzvhhtd.js} +5 -2
- package/dist/index-cq59agna.js +51 -0
- package/dist/{index-ssmd41kh.js → index-d2h99n7d.js} +1 -1
- package/dist/{index-z94wht4y.js → index-dky0dcmf.js} +34 -5
- package/dist/{index-za6j7nwy.js → index-dsnjzb62.js} +104 -51
- package/dist/index-eemvahkc.js +21 -0
- package/dist/index-ef8gdaq0.js +105 -0
- package/dist/{index-fa4wg312.js → index-f199nfq5.js} +10 -6
- package/dist/{index-ck71tbcf.js → index-fsw1ybf3.js} +11 -15
- package/dist/{index-f330qqyg.js → index-g2vfg7ak.js} +217 -63
- package/dist/{index-fk18k56k.js → index-gr5g3xfw.js} +11 -18
- package/dist/{index-jn9g8xdt.js → index-hjvje0pf.js} +6 -4
- package/dist/{index-x928baz2.js → index-j9gxbztg.js} +18 -14
- package/dist/index-kfjkb396.js +37 -0
- package/dist/{index-6drst9sg.js → index-ksfagmyz.js} +45 -345
- package/dist/index-m616f0yz.js +120 -0
- package/dist/{index-fm1c1a08.js → index-m6w6jtda.js} +40 -21
- package/dist/{index-ptn0g0gj.js → index-ma963wz7.js} +21 -20
- package/dist/{index-bakgedh8.js → index-msfpyy2f.js} +2 -4
- package/dist/{index-ywppsaby.js → index-n1nszyk0.js} +23 -34
- package/dist/{index-v14qqmys.js → index-n4689krb.js} +1 -1
- package/dist/{index-a0zzh8ak.js → index-pz3y6b6g.js} +3 -3
- package/dist/{index-43p08g7t.js → index-pzb63z66.js} +12 -8
- package/dist/{index-h97tqqp1.js → index-qaet40b2.js} +5 -3
- package/dist/{index-t1sr4aks.js → index-qaqbdm7s.js} +52 -6
- package/dist/{index-77nxk6ay.js → index-r393tnfp.js} +16 -10
- package/dist/{index-kb8styz3.js → index-rpzewktb.js} +15 -5
- package/dist/{index-27a2pj09.js → index-sj28htvf.js} +1 -1
- package/dist/index-szybbezc.js +455 -0
- package/dist/{index-2hyavjjj.js → index-wbhdzxar.js} +3 -3
- package/dist/{index-4e0ah203.js → index-wdy68sh6.js} +47 -24
- package/dist/{index-hbd32c6a.js → index-wqmvtnkp.js} +38 -89
- package/dist/{index-hp9d77wk.js → index-x7w1z6pf.js} +15 -4
- package/dist/{index-20yvtn9a.js → index-yt7gyg5x.js} +1 -1
- package/dist/{index-cvda079a.js → index-yvfk3y36.js} +12 -2
- package/dist/{index-5z6jn897.js → index-z23rfxhj.js} +1 -1
- package/dist/internal/abort-race.d.ts +8 -2
- package/dist/internal/abort-race.d.ts.map +1 -1
- package/dist/internal/atomic-file.d.ts +55 -9
- package/dist/internal/atomic-file.d.ts.map +1 -1
- package/dist/internal/atomic-publication.d.ts +39 -4
- package/dist/internal/atomic-publication.d.ts.map +1 -1
- package/dist/internal/atomic-staging.d.ts +46 -0
- package/dist/internal/atomic-staging.d.ts.map +1 -0
- package/dist/internal/bounded-file-read.d.ts +19 -11
- package/dist/internal/bounded-file-read.d.ts.map +1 -1
- package/dist/internal/bounded-lines.d.ts.map +1 -1
- package/dist/internal/close-after.d.ts +11 -0
- package/dist/internal/close-after.d.ts.map +1 -0
- package/dist/internal/deadline.d.ts +10 -0
- package/dist/internal/deadline.d.ts.map +1 -1
- package/dist/internal/exclusive-lock-read.d.ts +10 -12
- package/dist/internal/exclusive-lock-read.d.ts.map +1 -1
- package/dist/internal/exclusive-lock.d.ts +2 -2
- package/dist/internal/exclusive-lock.d.ts.map +1 -1
- package/dist/internal/file-observation.d.ts +14 -0
- package/dist/internal/file-observation.d.ts.map +1 -0
- package/dist/internal/json-data.d.ts +22 -5
- package/dist/internal/json-data.d.ts.map +1 -1
- package/dist/internal/positive-integer.d.ts +9 -0
- package/dist/internal/positive-integer.d.ts.map +1 -0
- package/dist/internal/process-instance.d.ts +35 -5
- package/dist/internal/process-instance.d.ts.map +1 -1
- package/dist/internal/secure-fetch.d.ts.map +1 -1
- package/dist/internal/timers.d.ts +11 -0
- package/dist/internal/timers.d.ts.map +1 -0
- package/dist/internal/with-exclusive-lock.d.ts +5 -4
- package/dist/internal/with-exclusive-lock.d.ts.map +1 -1
- package/dist/observability/bounded-sink.d.ts.map +1 -1
- package/dist/primitives/canonical-json.d.ts +23 -2
- package/dist/primitives/canonical-json.d.ts.map +1 -1
- package/dist/primitives/delivery.d.ts.map +1 -1
- package/dist/primitives/index.d.ts +1 -1
- package/dist/primitives/index.d.ts.map +1 -1
- package/dist/primitives/money.d.ts.map +1 -1
- package/dist/process/cleanup.d.ts +6 -1
- package/dist/process/cleanup.d.ts.map +1 -1
- package/dist/process/command-lifetime.d.ts +4 -0
- package/dist/process/command-lifetime.d.ts.map +1 -1
- package/dist/process/command-owner.d.ts.map +1 -1
- package/dist/process/command.d.ts +4 -0
- package/dist/process/command.d.ts.map +1 -1
- package/dist/process/contract.d.ts +67 -2
- package/dist/process/contract.d.ts.map +1 -1
- package/dist/process/group.d.ts +40 -3
- package/dist/process/group.d.ts.map +1 -1
- package/dist/process/launch.d.ts +12 -1
- package/dist/process/launch.d.ts.map +1 -1
- package/dist/process/terminate.d.ts +39 -0
- package/dist/process/terminate.d.ts.map +1 -0
- package/dist/react/query-client.d.ts.map +1 -1
- package/dist/realtime/rejection.d.ts.map +1 -1
- package/dist/server/contract-stream.d.ts.map +1 -1
- package/dist/server/handler-state.d.ts.map +1 -1
- package/dist/server/implement.d.ts.map +1 -1
- package/dist/server/request-body.d.ts +0 -1
- package/dist/server/request-body.d.ts.map +1 -1
- package/dist/server/unix-client.d.ts.map +1 -1
- package/dist/telegram/broadcast-delivery.d.ts.map +1 -1
- package/dist/telegram/broadcast-failure.d.ts +10 -2
- package/dist/telegram/broadcast-failure.d.ts.map +1 -1
- package/dist/telegram/operator-channel.d.ts.map +1 -1
- package/dist/telegram/screens/outcome.d.ts.map +1 -1
- package/dist/testing/surface-conformance.d.ts +1 -1
- package/dist/testing/surface-conformance.d.ts.map +1 -1
- package/dist/testing/surface-manifest.d.ts +0 -6
- package/dist/testing/surface-manifest.d.ts.map +1 -1
- package/dist/tools/agent.d.ts +1 -1
- package/dist/tools/agent.d.ts.map +1 -1
- package/dist/tools/cli/args.d.ts +1 -1
- package/dist/tools/cli/args.d.ts.map +1 -1
- package/dist/tools/cli/help.d.ts.map +1 -1
- package/dist/tools/cli/invoke.d.ts +2 -2
- package/dist/tools/cli/invoke.d.ts.map +1 -1
- package/dist/tools/cli/profile.d.ts.map +1 -1
- package/dist/tools/cli/publication-assets.d.ts.map +1 -1
- package/dist/tools/cli/publication-contract.d.ts +8 -0
- package/dist/tools/cli/publication-contract.d.ts.map +1 -1
- package/dist/tools/cli/publication-control.d.ts.map +1 -1
- package/dist/tools/cli/publication-storage.d.ts +23 -2
- package/dist/tools/cli/publication-storage.d.ts.map +1 -1
- package/dist/tools/cli/publication.d.ts +8 -1
- package/dist/tools/cli/publication.d.ts.map +1 -1
- package/dist/tools/connections/errors.d.ts +18 -6
- package/dist/tools/connections/errors.d.ts.map +1 -1
- package/dist/tools/connections/limits.d.ts +8 -2
- package/dist/tools/connections/limits.d.ts.map +1 -1
- package/dist/tools/connections/mcp-client.d.ts.map +1 -1
- package/dist/tools/connections/mcp-envelope.d.ts.map +1 -1
- package/dist/tools/connections/openapi.d.ts.map +1 -1
- package/dist/tools/connections/schema-budget.d.ts +1 -1
- package/dist/tools/connections/schema-budget.d.ts.map +1 -1
- package/dist/tools/connections/sse-session.d.ts.map +1 -1
- package/dist/tools/execute-args.d.ts.map +1 -1
- package/dist/tools/execute-result.d.ts.map +1 -1
- package/dist/tools/internal/surface-projector.d.ts +17 -3
- package/dist/tools/internal/surface-projector.d.ts.map +1 -1
- package/dist/tools/internal/tool-error-projection.d.ts +16 -0
- package/dist/tools/internal/tool-error-projection.d.ts.map +1 -0
- package/dist/tools/internal/tool-view.d.ts.map +1 -1
- package/dist/tools/invoker.d.ts.map +1 -1
- package/dist/tools/list-names.d.ts +3 -2
- package/dist/tools/list-names.d.ts.map +1 -1
- package/dist/tools/manifest.d.ts +3 -2
- package/dist/tools/manifest.d.ts.map +1 -1
- package/dist/tools/mcp/handler.d.ts +7 -0
- package/dist/tools/mcp/handler.d.ts.map +1 -1
- package/dist/tools/mcp/mount.d.ts +18 -2
- package/dist/tools/mcp/mount.d.ts.map +1 -1
- package/dist/tools/mcp/prepare.d.ts +3 -3
- package/dist/tools/mcp/prepare.d.ts.map +1 -1
- package/dist/tools/mcp/register.d.ts.map +1 -1
- package/dist/tools/mcp/runtime-tools.d.ts.map +1 -1
- package/dist/tools/mcp/stdio-signals.d.ts +14 -0
- package/dist/tools/mcp/stdio-signals.d.ts.map +1 -1
- package/dist/tools/mcp/stdio.d.ts +7 -0
- package/dist/tools/mcp/stdio.d.ts.map +1 -1
- package/dist/tools/operations/async-operation-runtime-tools.d.ts.map +1 -1
- package/dist/tools/operations/async-operation-runtime-types.d.ts +3 -3
- package/dist/tools/operations/async-operation-runtime-types.d.ts.map +1 -1
- package/dist/tools/operations/define-wait-tool.d.ts +1 -1
- package/dist/tools/operations/define-wait-tool.d.ts.map +1 -1
- package/dist/tools/operations/wait-core.d.ts +0 -6
- package/dist/tools/operations/wait-core.d.ts.map +1 -1
- package/dist/tools/registry.d.ts +1 -1
- package/dist/tools/registry.d.ts.map +1 -1
- package/dist/tools/remote.d.ts +1 -1
- package/dist/tools/remote.d.ts.map +1 -1
- package/dist/tools/{runtime-tool-execution.d.ts → runtime-tool-declaration.d.ts} +32 -9
- package/dist/tools/runtime-tool-declaration.d.ts.map +1 -0
- package/dist/tools/runtime-tool-mcp.d.ts +6 -15
- package/dist/tools/runtime-tool-mcp.d.ts.map +1 -1
- package/dist/tools/runtime-tool.d.ts +14 -12
- package/dist/tools/runtime-tool.d.ts.map +1 -1
- package/dist/tools/schema/coerce.d.ts +4 -0
- package/dist/tools/schema/coerce.d.ts.map +1 -1
- package/dist/tools/schema/flatten-join.d.ts.map +1 -1
- package/dist/tools/surface.d.ts +7 -11
- package/dist/tools/surface.d.ts.map +1 -1
- package/dist/tools/transfer/define-download-tool.d.ts +1 -1
- package/dist/tools/transfer/define-download-tool.d.ts.map +1 -1
- package/dist/tools/transfer/define-upload-tool.d.ts +1 -1
- package/dist/tools/transfer/define-upload-tool.d.ts.map +1 -1
- package/dist/tools/transfer/define-view-file-tool.d.ts +1 -1
- package/dist/tools/transfer/define-view-file-tool.d.ts.map +1 -1
- package/dist/tools/transfer/managed-file-error.d.ts.map +1 -1
- package/dist/tools/transfer/view-file-contract.d.ts.map +1 -1
- package/dist/tools/transfer/view-file.d.ts +1 -1
- package/dist/tools/transfer/view-file.d.ts.map +1 -1
- package/dist/tools/transports.d.ts +3 -2
- package/dist/tools/transports.d.ts.map +1 -1
- package/llms/agent-runtime-browser.txt +10 -4
- package/llms/agent-runtime-harness.txt +32 -31
- package/llms/agent-runtime-react.txt +1 -1
- package/llms/agent-runtime-realtime.txt +14 -5
- package/llms/agent-runtime-sandbox.txt +3 -11
- package/llms/agent-runtime.3.txt +2 -2
- package/llms/agent-runtime.txt +0 -9
- package/llms/application.2.txt +3 -12
- package/llms/application.3.txt +7 -4
- package/llms/application.txt +44 -15
- package/llms/cli-publish.txt +29 -0
- package/llms/cli.2.txt +9 -11
- package/llms/cli.txt +26 -14
- package/llms/declaration.txt +0 -9
- package/llms/files-packaging.txt +22 -7
- package/llms/files.txt +4 -2
- package/llms/geo.txt +0 -9
- package/llms/live.txt +4 -13
- package/llms/observability.txt +31 -5
- package/llms/primitives.txt +38 -20
- package/llms/process.txt +305 -154
- package/llms/react-keyboard.txt +0 -9
- package/llms/react.txt +0 -18
- package/llms/server.4.txt +1 -1
- package/llms/server.5.txt +1 -1
- package/llms/server.txt +1 -1
- package/llms/stitchkit.txt +6 -7
- package/llms/telegram-screens.txt +2 -2
- package/llms/testing.txt +0 -1
- package/llms/tools-mcp.txt +2 -3
- package/llms/tools.2.txt +12 -0
- package/llms/tools.3.txt +5 -6
- package/llms/tools.txt +6 -4
- package/llms/upgrading-0.37.0-0.50.0.txt +947 -0
- package/llms/{upgrading-0.44.0-0.61.0.txt → upgrading-0.53.0-0.67.0.txt} +576 -506
- package/llms/{upgrading-0.62.0-0.80.0.txt → upgrading-0.68.0-0.94.0.txt} +562 -576
- package/llms/{upgrading-0.81.0-0.104.0.txt → upgrading-0.95.0-0.105.0.txt} +452 -567
- package/llms/upgrading.txt +4 -4
- package/llms-full.txt +1053 -405
- package/llms.txt +24 -24
- package/native-assets.json +11 -3
- package/package.json +6 -6
- package/dist/agent-runtime/harness-tools.d.ts +0 -11
- package/dist/agent-runtime/harness-tools.d.ts.map +0 -1
- package/dist/entrypoints/agent-runtime/harness-tools.d.ts +0 -2
- package/dist/entrypoints/agent-runtime/harness-tools.d.ts.map +0 -1
- package/dist/entrypoints/agent-runtime/harness-tools.js +0 -32
- package/dist/index-1a6jtnd9.js +0 -88
- package/dist/index-8a9ksm91.js +0 -95
- package/dist/index-a3wma1hk.js +0 -48
- package/dist/index-jd470k6q.js +0 -109
- package/dist/index-n1dqr7gf.js +0 -20
- package/dist/index-nggfa2yn.js +0 -34
- package/dist/index-s4evrmp5.js +0 -98
- package/dist/index-ze1eph1k.js +0 -20
- package/dist/tools/connections/error-projection.d.ts +0 -4
- package/dist/tools/connections/error-projection.d.ts.map +0 -1
- package/dist/tools/runtime-tool-execution.d.ts.map +0 -1
- package/llms/agent-runtime-harness-tools.txt +0 -25
- package/llms/upgrading-0.37.0-0.44.0.txt +0 -444
|
@@ -1,14 +1,421 @@
|
|
|
1
|
-
# Upgrading 0.
|
|
1
|
+
# Upgrading 0.95.0 → 0.105.0 — stitchkit docs slice
|
|
2
2
|
|
|
3
3
|
> Generated from the `docs/` tree by `bun run gen:llms`. The index of all slices is
|
|
4
4
|
> `llms.txt` in this package.
|
|
5
5
|
|
|
6
|
-
Contains: Guide: Upgrading, 0.
|
|
6
|
+
Contains: Guide: Upgrading, 0.95.0 → 0.105.0 (docs/guide/upgrading.md)
|
|
7
7
|
|
|
8
8
|
==============================================================================
|
|
9
|
-
# Guide: Upgrading, 0.
|
|
9
|
+
# Guide: Upgrading, 0.95.0 → 0.105.0 (docs/guide/upgrading.md)
|
|
10
10
|
==============================================================================
|
|
11
11
|
|
|
12
|
+
## Released migration: 0.105.0
|
|
13
|
+
|
|
14
|
+
### CLI publication has its own entrypoint
|
|
15
|
+
|
|
16
|
+
**Who must act:** code that imports `publishCli`, `CliPublicationOptions`, `CliPublicationPhase` or
|
|
17
|
+
`CliPublicationResult` from `stitchkit/cli`. Everything else in `stitchkit/cli` — `createCli`, the
|
|
18
|
+
manifest schemas, signatures, `renderCliInstaller` and the updater — is unchanged.
|
|
19
|
+
|
|
20
|
+
`publishCli` is release infrastructure, so it now ships from the evolving entrypoint
|
|
21
|
+
`stitchkit/cli/publish` instead of the stable `stitchkit/cli`
|
|
22
|
+
([ADR 0245](../decisions/0245-cli-publication-is-an-evolving-leaf.md)). Its options, result and
|
|
23
|
+
behaviour are the same.
|
|
24
|
+
|
|
25
|
+
1. Move the publication names to the new specifier; keep every other CLI import where it is:
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
// before
|
|
29
|
+
import { publishCli, type CliPublicationOptions, verifyCliManifest } from 'stitchkit/cli'
|
|
30
|
+
// after
|
|
31
|
+
import { verifyCliManifest } from 'stitchkit/cli'
|
|
32
|
+
import { publishCli, type CliPublicationOptions } from 'stitchkit/cli/publish'
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Search pattern: `\b(publishCli|CliPublication(Options|Phase|Result))\b` in files that import
|
|
36
|
+
from `'stitchkit/cli'`.
|
|
37
|
+
2. Type-check: an import left on `stitchkit/cli` fails with "has no exported member".
|
|
38
|
+
3. `stitchkit/cli/publish` is evolving: read its breaking entries in each minor you upgrade across.
|
|
39
|
+
|
|
40
|
+
### a command stops by its `stop` policy
|
|
41
|
+
|
|
42
|
+
**Who must act:** callers of `runNativeCommand` (`stitchkit/process`) that pass `killGraceMs`.
|
|
43
|
+
Callers that omit it need no change: the default stop is the same TERM to the group, 100 ms, KILL.
|
|
44
|
+
|
|
45
|
+
1. Replace `killGraceMs: N` with a group stop of the same grace:
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
// before
|
|
49
|
+
await runNativeCommand({ executable, args, signal, killGraceMs: 500 })
|
|
50
|
+
// after
|
|
51
|
+
await runNativeCommand({ executable, args, signal, stop: { target: 'group', graceMs: 500 } })
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Search pattern: `killGraceMs:\s*(\d[\d_]*)` → `stop: { target: 'group', graceMs: $1 }`.
|
|
55
|
+
2. If your own wrapper signals only the leader and waits a long grace (cooperative cancellation),
|
|
56
|
+
replace it with `stop: { target: 'leader', signal: 'SIGINT', graceMs }` (up to one hour). Pass
|
|
57
|
+
`killOn` with your shutdown signal so an application that stops sooner kills the group first.
|
|
58
|
+
3. The result of a stopped command rejects once the group is gone, up to `graceMs` plus
|
|
59
|
+
`cleanupTimeoutMs` after the abort; size your caller deadlines on that sum.
|
|
60
|
+
|
|
61
|
+
### a command stops what its leader left
|
|
62
|
+
|
|
63
|
+
**Who must act:** callers of `runNativeCommand` (`stitchkit/process`) whose command starts a helper
|
|
64
|
+
in its own process group that must keep running after the command returns. A daemon that detaches
|
|
65
|
+
with `setsid` (as `daemon(3)` does) is not in the group and needs
|
|
66
|
+
no change.
|
|
67
|
+
|
|
68
|
+
`descendants` now defaults to `'terminate-after-leader'`
|
|
69
|
+
([ADR 0246](../decisions/0246-a-command-stops-its-descendants-by-default.md)): when the leader
|
|
70
|
+
exits, the members it left in the group are stopped by the command's `stop` policy before the
|
|
71
|
+
pipes drain.
|
|
72
|
+
|
|
73
|
+
1. Find the commands that start a background helper on purpose (a `&` in a shell script, a spawned
|
|
74
|
+
child the leader does not wait for) and declare `'leave'` on them:
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
// before
|
|
78
|
+
await runNativeCommand({ executable, args, timeoutMs })
|
|
79
|
+
// after
|
|
80
|
+
await runNativeCommand({ executable, args, timeoutMs, descendants: 'leave' })
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
2. Remove an explicit `descendants: 'terminate-after-leader'`, or keep it: it is now the default.
|
|
84
|
+
3. A command whose helper inherited stdout or stderr used to wait for that helper until its
|
|
85
|
+
deadline. It now completes when the leader exits; drop a workaround that killed the helper from
|
|
86
|
+
`onLeaderSettled`.
|
|
87
|
+
|
|
88
|
+
### native packaging verifies published digests
|
|
89
|
+
|
|
90
|
+
**Who must act:** build scripts that call `createNativePackaging` (`stitchkit/files/packaging`) and
|
|
91
|
+
read `asset.sourcePath`, hash the addon themselves, switch over the refusal `state`/`code`, pass a
|
|
92
|
+
`platform` other than the literal `'darwin'`, or parse `node_modules/stitchkit/native-assets.json`.
|
|
93
|
+
|
|
94
|
+
The package now publishes the `size` and SHA256 of each Darwin addon, computed when Stitchkit is
|
|
95
|
+
built, in `native-assets.json` at `formatVersion: 2`. `createNativePackaging` reads each selected
|
|
96
|
+
addon once, compares it with that digest and returns the verified bytes. An installed addon that
|
|
97
|
+
differs refuses with `NATIVE_ASSET_DIGEST_MISMATCH`.
|
|
98
|
+
|
|
99
|
+
1. Replace every read of `asset.sourcePath` with `asset.bytes`, and delete your own re-hash of the
|
|
100
|
+
addon: the result's `sha256` is the published digest and `bytes` already match it.
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
// before
|
|
104
|
+
const bytes = readFileSync(asset.sourcePath)
|
|
105
|
+
if (createHash('sha256').update(bytes).digest('hex') !== asset.sha256) throw …
|
|
106
|
+
copyFileSync(asset.sourcePath, destination)
|
|
107
|
+
// after
|
|
108
|
+
writeFileSync(destination, asset.bytes)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
2. Handle the third refusal. A `switch` over `result.state` gains `'mismatch'`
|
|
112
|
+
(`code: 'NATIVE_ASSET_DIGEST_MISMATCH'`); treat it as a failed build, never as a missing addon.
|
|
113
|
+
It carries the differing `architecture` with `expected` (published) and `actual` (installed)
|
|
114
|
+
`{ size, sha256 }`; log both pairs.
|
|
115
|
+
3. Pass the target platform as the literal `'darwin'`. `platform` is a closed enum, so a free
|
|
116
|
+
string (a target name read from configuration, `process.platform`) no longer type-checks, and
|
|
117
|
+
another platform throws instead of returning `unsupported`. Skip packaging for non-Darwin
|
|
118
|
+
targets before the call:
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
// before
|
|
122
|
+
const native = createNativePackaging({ platform: target.platform, architecture, … })
|
|
123
|
+
if (native.state === 'unsupported') return
|
|
124
|
+
// after
|
|
125
|
+
if (target.platform !== 'darwin') return
|
|
126
|
+
const native = createNativePackaging({ platform: target.platform, architecture, … })
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
`unsupported` now means only an architecture the package has no addon for.
|
|
130
|
+
4. Call `createNativePackaging` once per build and pass the result (its `assets` and `plugin`)
|
|
131
|
+
where it is needed. Each call reads and hashes the selected addons again.
|
|
132
|
+
5. If you read `native-assets.json` directly, read `assets.<arch>.path`, `.size` and `.sha256`
|
|
133
|
+
instead of a bare path per architecture; an architecture with no entry is not published.
|
|
134
|
+
|
|
135
|
+
### exclusive locks publish their owner first
|
|
136
|
+
|
|
137
|
+
**Who must act:** callers of `withExclusiveLock` (`stitchkit/files`) that rely on a lock file with no
|
|
138
|
+
readable owner being taken by age, and anything that puts lock files on a filesystem without hard
|
|
139
|
+
links. Every other caller needs no change.
|
|
140
|
+
|
|
141
|
+
A lock is now written to a private `.lock-<id>.tmp` file in the lock's directory, then hard-linked to
|
|
142
|
+
the lock name. The name never exists without a complete owner record, so `ownerlessGraceMs` defaults
|
|
143
|
+
to `null` instead of 5 000 ms: a lock file with no readable owner is never taken because of its age.
|
|
144
|
+
|
|
145
|
+
1. If you depended on age-based reclaim of an empty lock file left by an older writer, opt in:
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
// before: an empty lock older than 5 s was taken by default
|
|
149
|
+
await withExclusiveLock(path, run)
|
|
150
|
+
// after: say so; only legacy empty files need it
|
|
151
|
+
await withExclusiveLock(path, run, { ownerlessGraceMs: 5_000 })
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
2. Keep lock directories on a filesystem that supports hard links (local ext4, xfs, APFS and the
|
|
155
|
+
like). `link` failing with `EPERM` or `ENOTSUP` fails the acquisition.
|
|
156
|
+
3. Expect a `.lock-*.tmp` sibling only after a holder was killed between writing its record and
|
|
157
|
+
publishing it. It is not a lock; the next reclaim in that directory removes the ones whose owner
|
|
158
|
+
is gone on this machine. Exclude the pattern from directory-size caps or backups if you have any.
|
|
159
|
+
|
|
160
|
+
### one runtime-tool declaration
|
|
161
|
+
|
|
162
|
+
**Who must act:** code that names `RuntimeToolExecution`, `RuntimeToolExecutionWithOutput`,
|
|
163
|
+
`RuntimeMcpToolDefinition`, `RuntimeMcpToolDefinitionWithOutput` or `ToolSurfaceDefinition`; code
|
|
164
|
+
that annotates a definition carrying `present` as `RuntimeToolDefinitionWithOutput<I, O>` from
|
|
165
|
+
`stitchkit/tools`; imports of `stitchkit/agent-runtime/harness-tools`; code that compares agent
|
|
166
|
+
control error codes; and callers that send a JSON array as text to a string-or-array tool field.
|
|
167
|
+
Definitions returned by `defineRuntimeTool` / `createRuntimeToolFactory`, native CLI `commands` and
|
|
168
|
+
contract tools need no change.
|
|
169
|
+
|
|
170
|
+
A runtime tool now has one declaration, `RuntimeToolDefinitionWithOutput` /
|
|
171
|
+
`RuntimeToolDefinitionWithoutOutput`, exported with the same name from `stitchkit/cli`,
|
|
172
|
+
`stitchkit/tools` and `stitchkit/tools/mcp`. It carries no SDK type: the presenters are the adapter's
|
|
173
|
+
extension, named as the fourth type argument. `RuntimeToolDefinition` is the one registration type.
|
|
174
|
+
|
|
175
|
+
1. Replace each removed name.
|
|
176
|
+
|
|
177
|
+
| before | after |
|
|
178
|
+
|---|---|
|
|
179
|
+
| `RuntimeToolExecutionWithOutput<I, O>` (`stitchkit/cli`) | `RuntimeToolDefinitionWithOutput<I, O>` |
|
|
180
|
+
| `RuntimeToolExecution` (`stitchkit/cli`) | `RuntimeToolDefinition` |
|
|
181
|
+
| `RuntimeMcpToolDefinitionWithOutput<I, O>` (`stitchkit/tools/mcp`) | `RuntimeToolDefinitionWithOutput<I, O, undefined, RuntimeMcpToolPresenters<z.output<O>>>` |
|
|
182
|
+
| `RuntimeMcpToolDefinition` (`stitchkit/tools/mcp`) | `RuntimeToolDefinition` |
|
|
183
|
+
| `ToolSurfaceDefinition` (`stitchkit/tools`) | `ToolSurfaceProjection<RuntimeToolDefinition>` |
|
|
184
|
+
|
|
185
|
+
2. In `stitchkit/tools`, a type that names a definition with presenters passes the presenter type:
|
|
186
|
+
|
|
187
|
+
```ts
|
|
188
|
+
// before
|
|
189
|
+
const tool: RuntimeToolDefinitionWithOutput<typeof input, typeof output> = defineRuntimeTool({ …, present })
|
|
190
|
+
// after: let defineRuntimeTool infer it, or name the presenters
|
|
191
|
+
const tool = defineRuntimeTool({ …, present })
|
|
192
|
+
const named: RuntimeToolDefinitionWithOutput<typeof input, typeof output, undefined, RuntimeToolPresenters<z.output<typeof output>>> = tool
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
3. An inline handler in `runtimeTools: [...]` needs no wrapper: it is typed by the parsed object.
|
|
196
|
+
To type `input` from the schema, construct with `defineRuntimeTool` (or
|
|
197
|
+
`satisfies RuntimeToolDefinitionWithOutput<typeof input, typeof output>`) before registering.
|
|
198
|
+
|
|
199
|
+
4. Replace `createAgentHarnessTools` (`stitchkit/agent-runtime/harness-tools`) with the call it made:
|
|
200
|
+
|
|
201
|
+
```ts
|
|
202
|
+
// before
|
|
203
|
+
tools: createAgentHarnessTools(({ context }) => ({ services: [svc], context, lifecycle: auth }))
|
|
204
|
+
// after
|
|
205
|
+
import { composeToolLifecycle, mountAgent } from 'stitchkit/tools'
|
|
206
|
+
tools: ({ context, toolFenceLifecycle }) =>
|
|
207
|
+
mountAgent([svc], { context, lifecycle: composeToolLifecycle(auth, toolFenceLifecycle) })
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
5. Agent control codes: `ACCESS_DENIED` is `FORBIDDEN`, and `CONNECTION_CLOSED` is returned for a closed
|
|
211
|
+
connection. `AgentControlErrorCode` lists every code. `authorize` now runs once per request; after you
|
|
212
|
+
withdraw someone's access, call `binding.revoke(conversationId, matches?)` so an open stream is
|
|
213
|
+
re-authorized and ends with an `access-denied` delivery.
|
|
214
|
+
|
|
215
|
+
6. A string-or-array field that receives `'["a","b"]'` now fails with `VALIDATION_ERROR` ("`paths` is a
|
|
216
|
+
list written as text"). Send the array itself. A string that is not a list the array member accepts
|
|
217
|
+
(`[preview].png`) is still one plain string.
|
|
218
|
+
|
|
219
|
+
### flattened unions keep declaration order
|
|
220
|
+
|
|
221
|
+
**Who must act:** consumers that use `flattenUnionInput: true` and keep snapshot tests, golden
|
|
222
|
+
files or provider prompt caches of flattened tool schemas.
|
|
223
|
+
|
|
224
|
+
A flattened union now lists its properties, enum values and branch labels in the order they first
|
|
225
|
+
appear across the variants, not alphabetically. Declaration order often encodes priority, so the
|
|
226
|
+
model now reads the order you wrote. Alternatives of different kinds (`anyOf`) keep their
|
|
227
|
+
canonical order, independent of variant order.
|
|
228
|
+
|
|
229
|
+
1. Regenerate every snapshot or golden file of a flattened tool listing (`buildToolManifest`,
|
|
230
|
+
`listToolNames`, MCP `tools/list`, Agent tool schemas) and review the diff: only ordering moves.
|
|
231
|
+
2. Expect one provider prompt-cache miss per flattened tool after the upgrade.
|
|
232
|
+
3. To keep an order you prefer, declare the variants and fields in that order.
|
|
233
|
+
|
|
234
|
+
### connection limits are validated
|
|
235
|
+
|
|
236
|
+
**Who must act:** callers that pass `timeoutMs` or `maxResponseBytes` to a connection and relied
|
|
237
|
+
on an invalid value silently becoming the default.
|
|
238
|
+
|
|
239
|
+
`stitchkit/tools/connections` throws a `RangeError` when `timeoutMs` is not a positive integer
|
|
240
|
+
within timer range (at most 2 147 483 647) or `maxResponseBytes` is not a positive safe integer.
|
|
241
|
+
Before 0.104.0 a value of 0, a negative number, a fraction or an out-of-range number fell back to
|
|
242
|
+
the default without a message.
|
|
243
|
+
|
|
244
|
+
```ts
|
|
245
|
+
// Before: { timeoutMs: 0 } meant "use the default" by accident.
|
|
246
|
+
// After: omit the option to take the default, or pass a real limit.
|
|
247
|
+
{ timeoutMs: 30_000 }
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### one canonical JSON serializer
|
|
251
|
+
|
|
252
|
+
**Who must act:** tests that call `serializeSurfaceValue` from `stitchkit/testing`, and code that
|
|
253
|
+
puts a value nested deeper than 100 levels into agent store events, archives or projections
|
|
254
|
+
through `canonicalAgentJson`.
|
|
255
|
+
|
|
256
|
+
`canonicalJson` from `stitchkit/primitives` is the package's one canonical serializer. It
|
|
257
|
+
admits dense arrays, plain objects, strings, booleans, `null` and finite numbers; an `undefined`
|
|
258
|
+
object member is omitted. It refuses everything else with a `CanonicalJsonError`, a `TypeError`
|
|
259
|
+
whose `reason` says why: `'depth'`, `'nodes'` and `'bytes'` are the limits you set, while
|
|
260
|
+
`'cycle'`, `'negative-zero'` and `'not-json'` say the value is not JSON data.
|
|
261
|
+
|
|
262
|
+
`serializeSurfaceValue` is removed. It produced the same bytes without limits:
|
|
263
|
+
|
|
264
|
+
```ts
|
|
265
|
+
// Before
|
|
266
|
+
import { serializeSurfaceValue } from 'stitchkit/testing'
|
|
267
|
+
const text = serializeSurfaceValue(manifest)
|
|
268
|
+
// After: the limits default to 100 levels, 100 000 nodes and 1 MiB; raise them for a large manifest
|
|
269
|
+
import { canonicalJson } from 'stitchkit/primitives'
|
|
270
|
+
const text = canonicalJson(manifest, { maxBytes: 16 * 1024 * 1024 })
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
`canonicalAgentJson` in `stitchkit/agent-runtime` is `canonicalJson` with the node and byte
|
|
274
|
+
limits at their maximum. A value both accepted has the same bytes as before, so stored digests
|
|
275
|
+
and archives still match: like `z.json()` before it, the store hashes `-0` as `0` and drops an
|
|
276
|
+
own `__proto__` member (the public `canonicalJson` refuses `-0` and keeps `__proto__`). What
|
|
277
|
+
changed is the refusal table: an `undefined` object member used to fail and is now omitted, and
|
|
278
|
+
a value nested deeper than 100 levels is now refused.
|
|
279
|
+
|
|
280
|
+
```ts
|
|
281
|
+
// Before: canonicalAgentJson({ a: undefined }) threw a ZodError
|
|
282
|
+
// After: canonicalAgentJson({ a: undefined }) === '{}'
|
|
283
|
+
// canonicalAgentJson(nestedBeyond100Levels) throws CanonicalJsonError (reason 'depth')
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### directory inbox entries
|
|
287
|
+
|
|
288
|
+
**Who must act:** producers that drop hard links into an inbox directory, and callers that pass
|
|
289
|
+
`accept` the output of a transforming schema.
|
|
290
|
+
|
|
291
|
+
A file dropped into the inbox directory with more than one link is set aside as `invalid`
|
|
292
|
+
(detail `managed file has multiple links`). Another name can still rewrite such a file after it
|
|
293
|
+
was validated, so it is never trusted. Write each entry as its own regular file: a temporary
|
|
294
|
+
name in the same directory, then a rename onto `<name>.json`.
|
|
295
|
+
|
|
296
|
+
`accept` takes the schema's input type, stores that input as given and parses it with the
|
|
297
|
+
schema on delivery. A schema without a transform has the same input and output type and needs
|
|
298
|
+
no change. With a transform, pass the input:
|
|
299
|
+
|
|
300
|
+
```ts
|
|
301
|
+
const schema = z.object({ amount: z.string().transform(Number) })
|
|
302
|
+
// Before: accept({ source, key, entry: { amount: 42 } }) // typed as the output; `z.string()` refused it
|
|
303
|
+
// After: accept({ source, key, entry: { amount: '42' } }) // delivered as { amount: 42 }
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
A name that is already in `rejected/` no longer stops the pass: identical bytes are the entry
|
|
307
|
+
already set aside, different bytes are kept as `rejected/<name>.<16 hex digits>`.
|
|
308
|
+
|
|
309
|
+
### journal startup scan
|
|
310
|
+
|
|
311
|
+
**Who must act:** operators that read `status.recovery` right after `createDiagnosticJournal` to
|
|
312
|
+
find damaged rows in the middle of a file.
|
|
313
|
+
|
|
314
|
+
Opening a journal reads only the last line of the active file and of every retained
|
|
315
|
+
generation (`startupScan: 'tails'`, the default). A crash tears the end of a file, so a torn tail
|
|
316
|
+
is still reported and still rotated away, and opening no longer parses and validates every
|
|
317
|
+
line of every generation. It still reads each file once in large blocks to count lines, so the time
|
|
318
|
+
grows with the bytes retained, at read speed. Pass `startupScan: 'full'` to read and validate every line as before:
|
|
319
|
+
|
|
320
|
+
```ts
|
|
321
|
+
// Before: every open parsed every line of every generation.
|
|
322
|
+
// After: the same full scan, on request.
|
|
323
|
+
const journal = await createDiagnosticJournal({ path, eventSchema, limits, startupScan: 'full' })
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### journal startup quarantine
|
|
327
|
+
|
|
328
|
+
**Who must act:** operators of a journal that is a source of truth and must not start over
|
|
329
|
+
damaged retained files; code that constructs `DiagnosticJournalRecoveryError` or reads its
|
|
330
|
+
`recovery`; protocols that embed `DiagnosticJournalRecoveryStatusSchema`, and their readers.
|
|
331
|
+
A diagnostic journal needs no change.
|
|
332
|
+
|
|
333
|
+
Opening a journal no longer refuses to start over a torn active file with `maxFiles: 1`, a
|
|
334
|
+
generation name that is not a regular file or a retained file it cannot read. It renames the file
|
|
335
|
+
to `<file>.quarantined-<epoch>` beside the journal, starts, and lists the move in
|
|
336
|
+
`getStatus().recovery.quarantined`. Quarantined files are outside retention and never deleted;
|
|
337
|
+
every later open lists them again, without a `reason`, until you remove them.
|
|
338
|
+
|
|
339
|
+
1. A journal whose damage must stop the process declares the old behaviour:
|
|
340
|
+
|
|
341
|
+
```ts
|
|
342
|
+
// Before: refusing was the only behaviour.
|
|
343
|
+
await createDiagnosticJournal({ path, eventSchema, limits })
|
|
344
|
+
// After:
|
|
345
|
+
await createDiagnosticJournal({ path, eventSchema, limits, onStartupRefusal: 'fail' })
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
2. Branch on the refusal's `reason` instead of its message or error class. Every startup refusal
|
|
349
|
+
about retained evidence is a `DiagnosticJournalRecoveryError`, including the former plain
|
|
350
|
+
`Error` for a non-file generation and the raw `EACCES` for an unreadable one (now in `cause`):
|
|
351
|
+
|
|
352
|
+
```ts
|
|
353
|
+
// Before: catch (error) { if (error instanceof DiagnosticJournalRecoveryError) use(error.recovery) }
|
|
354
|
+
// After:
|
|
355
|
+
catch (error) {
|
|
356
|
+
if (error instanceof DiagnosticJournalRecoveryError && error.reason === 'torn-without-retention-slot') use(error.recovery)
|
|
357
|
+
}
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
`recovery` is present only for `torn-without-retention-slot`. The constructor takes one
|
|
361
|
+
options object: `new DiagnosticJournalRecoveryError({ reason, file, recovery?, cause? })`.
|
|
362
|
+
|
|
363
|
+
3. A protocol that embeds `DiagnosticJournalRecoveryStatusSchema` carries the new optional
|
|
364
|
+
`quarantined` array (at most 32 entries, `reason` optional) and `quarantinedUnlisted` count.
|
|
365
|
+
The schema is `.strict()`: upgrade every reader that parses it with its own copy before a
|
|
366
|
+
writer on this version sends a status with either field, or bump your protocol version.
|
|
367
|
+
|
|
368
|
+
### error constructors take named options
|
|
369
|
+
|
|
370
|
+
**Who must act:** code that constructs an `AppError` or an `ApiError` with anything beyond its
|
|
371
|
+
code, and classes that extend `AppError` and call `super(code, message, status, …)`. Code that
|
|
372
|
+
only throws the `notFound`, `badRequest`, `unauthorized`, `forbidden`, `conflict` and
|
|
373
|
+
`rateLimited` helpers, or only reads `code`, `status`, `details`, `hint`, `traceId`,
|
|
374
|
+
`retryable` and `cause` from a caught error, needs no change.
|
|
375
|
+
|
|
376
|
+
`AppError` (`stitchkit/contract`, `stitchkit/server`, `stitchkit/node`) and `ApiError`
|
|
377
|
+
(`stitchkit`) keep the code as the one positional argument. Every other value is a named
|
|
378
|
+
option, so a call site reads without the signature open. `new AppError(code)` and
|
|
379
|
+
`new ApiError(code)` are unchanged. The compiler finds every old call: a string or number
|
|
380
|
+
in the second position is a type error.
|
|
381
|
+
|
|
382
|
+
1. `AppError`: move `message`, `status`, `details`, `hint`, `traceId` and `retryable` into one
|
|
383
|
+
object after the code. `status` defaults to 500 and `message` to the code.
|
|
384
|
+
|
|
385
|
+
```ts
|
|
386
|
+
// before
|
|
387
|
+
throw new AppError('CONFLICT', 'Selection is stale', 409, { revision: 7 })
|
|
388
|
+
throw new AppError('BUSY', 'Try later', 503, undefined, undefined, undefined, true)
|
|
389
|
+
// after
|
|
390
|
+
throw new AppError('CONFLICT', { message: 'Selection is stale', status: 409, details: { revision: 7 } })
|
|
391
|
+
throw new AppError('BUSY', { message: 'Try later', status: 503, retryable: true })
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
2. A subclass passes the same object to `super`:
|
|
395
|
+
|
|
396
|
+
```ts
|
|
397
|
+
// before
|
|
398
|
+
super('FEATURE_LOCKED', 'locked', 403)
|
|
399
|
+
// after
|
|
400
|
+
super('FEATURE_LOCKED', { message: 'locked', status: 403 })
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
3. `ApiError`: the old order was `code, status, details, message, hint, traceId, errorOptions,
|
|
404
|
+
retryable`. Name each value; `status` defaults to 0 and the former `ErrorOptions` argument
|
|
405
|
+
is now the `cause` option.
|
|
406
|
+
|
|
407
|
+
```ts
|
|
408
|
+
// before
|
|
409
|
+
new ApiError('RATE_LIMITED', 429, undefined, 'slow down', 'wait', 'trace-1', { cause }, true)
|
|
410
|
+
new ApiError('VALIDATION_ERROR', 0, { issues }, 'bad input')
|
|
411
|
+
// after
|
|
412
|
+
new ApiError('RATE_LIMITED', { status: 429, message: 'slow down', hint: 'wait', traceId: 'trace-1', retryable: true, cause })
|
|
413
|
+
new ApiError('VALIDATION_ERROR', { status: 0, details: { issues }, message: 'bad input' })
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
4. Both classes accept the standard `cause`, which `error.cause` returns; omit the option to
|
|
417
|
+
leave the property absent.
|
|
418
|
+
|
|
12
419
|
## Released migration: 0.104.0
|
|
13
420
|
|
|
14
421
|
JS bundles carrying Darwin native capabilities also need the
|
|
@@ -134,10 +541,20 @@ that work actually completes.
|
|
|
134
541
|
|
|
135
542
|
### Darwin native assets in JS distributions
|
|
136
543
|
|
|
137
|
-
**Who must act:** Bun
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
544
|
+
**Who must act:** Bun builds that import `stitchkit/server`, `stitchkit/files` or
|
|
545
|
+
`stitchkit/process` (Linux-only server apps included) and use `--outfile`, copy only
|
|
546
|
+
`outputs[0]`, or package a single file; custom single-file/archive packagers and installers
|
|
547
|
+
delivering native process/files capabilities.
|
|
548
|
+
First affected publication: **0.103.13**, through **0.104.2**. It shipped as a patch; its
|
|
549
|
+
changed delivery graph requires this migration despite unchanged API signatures.
|
|
550
|
+
|
|
551
|
+
In those versions every Bun bundle that reaches the lock or process-identity code,
|
|
552
|
+
`stitchkit/server` included, carries both Darwin `.node` addons as extra outputs on every
|
|
553
|
+
operating system. `bun build --outfile` then fails with
|
|
554
|
+
`cannot write multiple output files without an output directory`, and `--outdir` writes the
|
|
555
|
+
addons next to a Linux artifact. Releases after 0.104.2 resolve the default loader at run time,
|
|
556
|
+
so these bundles are one JS file with no `.node` output again. The static loader exists only
|
|
557
|
+
in a build that uses the `stitchkit/files/packaging` plugin.
|
|
141
558
|
|
|
142
559
|
```sh
|
|
143
560
|
# Before: one JS file was assumed to be the entire distribution.
|
|
@@ -154,12 +571,39 @@ Custom output layout uses the evolving build-only packaging contract in the
|
|
|
154
571
|
|
|
155
572
|
Three deliveries have different rules: an ordinary npm install retains the package's
|
|
156
573
|
native assets; a JS distribution must ship its complete output graph; a Bun compiled
|
|
157
|
-
executable embeds the matching addon and may still use `--outfile`.
|
|
574
|
+
executable embeds the matching addon and may still use `--outfile`. In 0.103.13–0.104.2 a plain
|
|
575
|
+
`bun build` carries the addon without a plugin; later releases carry it only when the build
|
|
576
|
+
uses `createNativePackaging` (`delivery: 'companion'` for JS, `'embedded'` for a compiled
|
|
577
|
+
executable).
|
|
158
578
|
The [native IO guide](native-io.md#libraries-with-a-zod-only-runtime) is the canonical recipe.
|
|
159
579
|
Check the resulting artifact offline outside the build tree and `node_modules`, including
|
|
160
580
|
process identity, live-owner lock refusal, dead-owner recovery and contained IO.
|
|
161
581
|
A missing or corrupt addon remains `unavailable`, never evidence that an owner died.
|
|
162
582
|
|
|
583
|
+
### CLI: repeated options are refused
|
|
584
|
+
|
|
585
|
+
**Who must act:** wrappers, aliases and scripts that append `--json`, `--profile X` or an
|
|
586
|
+
application global to arguments the user may already have given, and anything that passes the
|
|
587
|
+
same global twice.
|
|
588
|
+
First affected publication: **0.103.13**. It shipped as a patch; the change in grammar needs
|
|
589
|
+
this migration.
|
|
590
|
+
|
|
591
|
+
A repeated option that is not an array field is an argument error:
|
|
592
|
+
`--json --json` and `--profile a --profile b` fail with `--json was passed 2 times`. Before
|
|
593
|
+
0.103.13 the last value won, for framework globals, application globals and repeated
|
|
594
|
+
`kind: 'other'` fields alike. Array fields, and untyped passthrough fields that keep their
|
|
595
|
+
raw-list grammar, still repeat.
|
|
596
|
+
|
|
597
|
+
```sh
|
|
598
|
+
# Before: a wrapper appended its default and the last value won.
|
|
599
|
+
mytool deploy --profile staging "$@" --profile production
|
|
600
|
+
# After: build the argument list once, so each option appears once.
|
|
601
|
+
mytool deploy --profile "${PROFILE:-production}" "$@"
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
Dotted leaves such as `--filter.name` follow the same rule as their parent field. Declare a
|
|
605
|
+
field as an array when repetition is meant.
|
|
606
|
+
|
|
163
607
|
## Released migration: 0.103.0
|
|
164
608
|
|
|
165
609
|
### Diagnostic journal startup preserves torn evidence and inspects archives
|
|
@@ -493,562 +937,3 @@ version loads unchanged — the new `unavailableAt` reads as `null`.
|
|
|
493
937
|
drains; without it downtime is counted from the recorded stop. Call
|
|
494
938
|
`recordReady()` when the run serves; a run stopped without it now ends
|
|
495
939
|
`startup-failed`, not `clean`.
|
|
496
|
-
|
|
497
|
-
## Released migration: 0.94.0
|
|
498
|
-
|
|
499
|
-
One breaking minor that consolidates: tool options move into one group, and
|
|
500
|
-
names that were exported from two entrypoints keep only their owner. Every step
|
|
501
|
-
is an edit a type checker or `defineContract` points at; the few behaviour
|
|
502
|
-
changes that need no edit are under Changed and Fixed in the changelog.
|
|
503
|
-
|
|
504
|
-
1. **Move endpoint tool options into `tool`.** **Who must act:** every project
|
|
505
|
-
with an endpoint that sets `toolName`, `ui`, `annotations` or `mcp`. Run the
|
|
506
|
-
codemod from a checkout of this repository, then typecheck:
|
|
507
|
-
|
|
508
|
-
```bash
|
|
509
|
-
bun packages/core/scripts/codemod-tool-group.ts --check path/to/your/src # list
|
|
510
|
-
bun packages/core/scripts/codemod-tool-group.ts path/to/your/src # rewrite
|
|
511
|
-
```
|
|
512
|
-
|
|
513
|
-
```ts
|
|
514
|
-
// before
|
|
515
|
-
{ method: 'GET', path: '/', desc: 'List', toolName: 'user_list', mcp: { inputRequired } }
|
|
516
|
-
// after
|
|
517
|
-
{ method: 'GET', path: '/', desc: 'List', tool: { name: 'user_list', mcp: { inputRequired } } }
|
|
518
|
-
```
|
|
519
|
-
|
|
520
|
-
The codemod leaves two kinds of endpoint for a person and prints where: one
|
|
521
|
-
built with a spread (`{ ...base, toolName }`), and one exposed on HTTP only,
|
|
522
|
-
whose tool options never reached a tool — delete them there. Anything left
|
|
523
|
-
over fails at startup, by name — a key moved into the group under its old
|
|
524
|
-
name (`tool: { toolName }`) included:
|
|
525
|
-
|
|
526
|
-
```text
|
|
527
|
-
Contract "users": endpoint "list" sets `toolName` — tool options live in `tool` since 0.94.0: use tool.name
|
|
528
|
-
```
|
|
529
|
-
|
|
530
|
-
`expose` does not move. `MethodDef` — what hooks and runtime tools see — keeps
|
|
531
|
-
`toolName`, `ui`, `annotations` and `mcp` at the top level, so hook code does
|
|
532
|
-
not change. A tool view is declared only with `withToolView`, which now puts
|
|
533
|
-
it in `tool.view`.
|
|
534
|
-
|
|
535
|
-
2. **Change imports of moved names.** **Who must act:** projects importing any
|
|
536
|
-
of these; the compiler lists every site.
|
|
537
|
-
|
|
538
|
-
| Name | From | To |
|
|
539
|
-
|---|---|---|
|
|
540
|
-
| `RuntimeToolTransport`, `ToolSurfaceTransport`, `ToolInvokerTransport` | `stitchkit/tools`, `stitchkit/tools/invoker`, `stitchkit/tools/connections` | `ToolTransport` from `stitchkit/contract` |
|
|
541
|
-
| `createCli`, `defineCliCommand`, `CliConfig`, `CliSurfaceSource`, `CliPresentationPolicyConfig`, `CliWaitConfig`, `ExitCodeMap`, `CliCommand*` | `stitchkit/tools` | `stitchkit/cli` |
|
|
542
|
-
| `parseSSE`, `ParseSSEOptions` | `stitchkit/server` | `stitchkit` |
|
|
543
|
-
| `runAgentStoreConformance`, `AgentStoreConformance*`, `createAgentRace*`, `AgentRace*` | `stitchkit/testing` | `stitchkit/agent-runtime/testing` |
|
|
544
|
-
| `createLocalStepDurability`, `LocalStepDurability`, `LocalStepDurabilityOptions`, `StepDurabilityLedger` | `stitchkit/agent-runtime` | `stitchkit/tools` |
|
|
545
|
-
|
|
546
|
-
3. **Regenerate a surface snapshot only if it reports drift.** **Who must act:**
|
|
547
|
-
a project whose committed snapshot has an object with integer-like keys
|
|
548
|
-
(`"9"`, `"10"`) — they are now sorted like every other key. Every other
|
|
549
|
-
snapshot, CLI manifest signature and agent-store archive is byte-identical.
|
|
550
|
-
|
|
551
|
-
## Released migration: 0.93.0
|
|
552
|
-
|
|
553
|
-
1. **Regenerate every committed surface snapshot, once.** `manifestVersion` is
|
|
554
|
-
`3` and each operation row gained `mcp` — the rounds it declares before it
|
|
555
|
-
runs. Most rows get `null`, so the first diff is large and mechanical.
|
|
556
|
-
**Who must act:** anyone with a committed snapshot. A snapshot on the older
|
|
557
|
-
version is refused by name rather than failing a schema literal:
|
|
558
|
-
|
|
559
|
-
```text
|
|
560
|
-
Surface snapshot is manifestVersion 2; this build writes 3. Regenerate it
|
|
561
|
-
and review the diff — the format changed, so the first regeneration is
|
|
562
|
-
expected to be large.
|
|
563
|
-
```
|
|
564
|
-
|
|
565
|
-
```ts
|
|
566
|
-
// before — a declared round left no trace, so declaring or removing one
|
|
567
|
-
// passed review invisibly
|
|
568
|
-
manifest.operations[0]
|
|
569
|
-
// after
|
|
570
|
-
manifest.operations[0].mcp
|
|
571
|
-
// null | { inputRequired: [{ key, message, schema }] }
|
|
572
|
-
// | { inputRequired: 'resolved-per-call' }
|
|
573
|
-
```
|
|
574
|
-
|
|
575
|
-
A project that kept its own test for "declared `inputRequired` implies a
|
|
576
|
-
configured state key" can drop it: the snapshot holds that link now.
|
|
577
|
-
|
|
578
|
-
2. **Nothing else to do.** Native commands that declare `output` became
|
|
579
|
-
invokable in process; a name that answered `NOT_FOUND` from
|
|
580
|
-
`createCliInvoker` in 0.92.0 may now resolve. If an application relied on
|
|
581
|
-
native commands being unreachable there, stop passing them to the invoker.
|
|
582
|
-
|
|
583
|
-
## Released migration: 0.92.0
|
|
584
|
-
|
|
585
|
-
1. **`RequestEvent.method`, `path` and `statusCode` are optional.** Work that did
|
|
586
|
-
not arrive over a transport now records their **absence** instead of inventing
|
|
587
|
-
values — a background loop used to write `method: 'AGENT'`, which is not a
|
|
588
|
-
verb. **Who must act:** anyone whose `RequestEventSinkConfig.write` puts these
|
|
589
|
-
into NOT NULL columns, or whose filter reads `event.method`.
|
|
590
|
-
|
|
591
|
-
```ts
|
|
592
|
-
// before
|
|
593
|
-
write: (event) => db.audit.create({ data: { method: event.method, path: event.path, status: event.statusCode } })
|
|
594
|
-
// after — a job has none of the three; `kind` says which kind of row it is
|
|
595
|
-
write: (event) => db.audit.create({ data: {
|
|
596
|
-
kind: event.kind,
|
|
597
|
-
name: event.name ?? null,
|
|
598
|
-
method: event.method ?? null,
|
|
599
|
-
path: event.path ?? null,
|
|
600
|
-
status: event.statusCode ?? null,
|
|
601
|
-
} })
|
|
602
|
-
```
|
|
603
|
-
|
|
604
|
-
A filter written as `event.method !== 'GET'` keeps jobs (`undefined !== 'GET'`),
|
|
605
|
-
which is usually what you want. To exclude them deliberately:
|
|
606
|
-
`event.kind === 'request' && event.method !== 'GET'`.
|
|
607
|
-
|
|
608
|
-
2. **`applyCliUpdate` needs the manifest when given a trust root.** The signature
|
|
609
|
-
covers the manifest and every asset digest together, so an asset alone cannot
|
|
610
|
-
be verified. **Who must act:** only callers adopting signature verification;
|
|
611
|
-
the unsigned call is unchanged.
|
|
612
|
-
|
|
613
|
-
```ts
|
|
614
|
-
// before
|
|
615
|
-
await applyCliUpdate({ asset })
|
|
616
|
-
// after
|
|
617
|
-
await applyCliUpdate({ asset, manifest: check.manifest, trust })
|
|
618
|
-
```
|
|
619
|
-
|
|
620
|
-
3. **An MCP continuation minted before this release is refused once.** The signed
|
|
621
|
-
round state now carries a fingerprint of the question plan, checked on every
|
|
622
|
-
round, so a plan that moved between rounds is a refusal rather than a
|
|
623
|
-
different question asked under the previous one's key. A conversation already
|
|
624
|
-
in flight at deploy time has no fingerprint and gets
|
|
625
|
-
`INVALID_REQUEST_STATE`; the host re-asks and the second attempt succeeds.
|
|
626
|
-
**Who must act:** nobody — but expect a small number of these in the minutes
|
|
627
|
-
after a deploy, and do not read them as tampering.
|
|
628
|
-
|
|
629
|
-
## Released migration: 0.91.0
|
|
630
|
-
|
|
631
|
-
1. `STITCH_ERROR_STATUS` gained `NOT_IMPLEMENTED` (501). An **exhaustive** error
|
|
632
|
-
vocabulary must name it — without the row `defineErrors({ mapping: { exhaustive:
|
|
633
|
-
true } })` stops compiling and then throws at startup. Nothing else in this
|
|
634
|
-
release requires action.
|
|
635
|
-
|
|
636
|
-
```ts
|
|
637
|
-
// before
|
|
638
|
-
map: { …, WAIT_TIMEOUT: 'timeout' }
|
|
639
|
-
// after
|
|
640
|
-
map: { …, NOT_IMPLEMENTED: 'not_implemented', WAIT_TIMEOUT: 'timeout' }
|
|
641
|
-
```
|
|
642
|
-
|
|
643
|
-
The code is thrown only by the new dev-only `onMissingHandler: 'stub'` policy;
|
|
644
|
-
a vocabulary that is not exhaustive is unaffected.
|
|
645
|
-
|
|
646
|
-
## Released migration: 0.90.0
|
|
647
|
-
|
|
648
|
-
1. `stitchkit.watch.value` is a discriminated union on `kind` — `full`, `delta`,
|
|
649
|
-
`unchanged` — and every frame carries `fingerprint`. **Both ends must come from
|
|
650
|
-
the same major.** A client older than this release reads a `delta` frame as a
|
|
651
|
-
value of `undefined`, silently; upgrade the hub and the pages that talk to it
|
|
652
|
-
together, or set `deltaMemoryBytes: 0` on the hub until they are.
|
|
653
|
-
|
|
654
|
-
Applications using `createWatchClient` need no code change: it rebuilds the
|
|
655
|
-
value and hands the listener the whole answer as before. Code that reads
|
|
656
|
-
`WatchValueFrame.value` directly — a hand-written subscriber, a test double —
|
|
657
|
-
narrows on `kind` first.
|
|
658
|
-
|
|
659
|
-
```ts
|
|
660
|
-
// before: frame.value
|
|
661
|
-
// after:
|
|
662
|
-
if (frame.kind === 'full') hold(frame.value);
|
|
663
|
-
else if (frame.kind === 'delta') hold(applyWatchDelta(held, frame.delta));
|
|
664
|
-
// 'unchanged' leaves what you hold standing
|
|
665
|
-
```
|
|
666
|
-
|
|
667
|
-
2. `AttachedWatcher.open` takes an optional third argument, `have`. A custom
|
|
668
|
-
server binding that forwards `stitchkit.watch.open` should pass the payload's
|
|
669
|
-
`have` through; omitting it costs a whole value on every reconnection and is
|
|
670
|
-
otherwise harmless.
|
|
671
|
-
|
|
672
|
-
## Released migration: 0.89.0
|
|
673
|
-
|
|
674
|
-
1. Custom `AgentRuntimeStore` adapters implement `seedConversationInput`; custom
|
|
675
|
-
`AgentRuntimeStoreDriver` adapters implement `seeds.load` and `seeds.create` together
|
|
676
|
-
with atomic, ordered history insertion. Use the maintained Prisma example and run
|
|
677
|
-
`runAgentStoreConformance` against the adapter. Built-in memory and SQLite
|
|
678
|
-
stores already implement the contract; SQLite migrates to schema version 3.
|
|
679
|
-
2. OpenRouter usage normalization consumes each completed SDK step's `usage`, including
|
|
680
|
-
`raw`, rather than aggregate usage. Missing counters stay `unavailable`.
|
|
681
|
-
|
|
682
|
-
```ts
|
|
683
|
-
// before: normalizeOpenRouterUsage(await result.usage, metadata)
|
|
684
|
-
// after:
|
|
685
|
-
for (const step of await result.steps) {
|
|
686
|
-
const usage = normalizeOpenRouterUsage(step.usage, step.providerMetadata);
|
|
687
|
-
// Persist the step's measured usage with its provenance.
|
|
688
|
-
}
|
|
689
|
-
```
|
|
690
|
-
|
|
691
|
-
3. Durable step bodies return lossless JSON. Convert dates explicitly, reject invalid
|
|
692
|
-
numbers upstream, and return `null` after an effect-only operation.
|
|
693
|
-
|
|
694
|
-
```ts
|
|
695
|
-
await context.step('send', async () => {
|
|
696
|
-
await sendIdempotently();
|
|
697
|
-
return null;
|
|
698
|
-
});
|
|
699
|
-
```
|
|
700
|
-
|
|
701
|
-
First execution, replay and concurrent callers receive detached values. Persistence
|
|
702
|
-
does not make external effects transactional; the host retains idempotency and recovery.
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
How to move a consuming project from one stitchkit version to another — including
|
|
706
|
-
across many versions at once (a project frozen on an old version, then jumped
|
|
707
|
-
forward). The process is mechanical: stitchkit marks every breaking change in one
|
|
708
|
-
place and one format, so you can recover the full migration from the version diff.
|
|
709
|
-
|
|
710
|
-
## Released migration: 0.88.0
|
|
711
|
-
|
|
712
|
-
Two mechanical edits, and only if your project builds these values rather than only reading them.
|
|
713
|
-
|
|
714
|
-
A completed step event now carries the provider's response identity, and the field is required:
|
|
715
|
-
|
|
716
|
-
```ts
|
|
717
|
-
// before
|
|
718
|
-
{ type: 'step-finished', step: 0, usage }
|
|
719
|
-
|
|
720
|
-
// after
|
|
721
|
-
{ type: 'step-finished', step: 0, usage, response: { id: generationId } }
|
|
722
|
-
```
|
|
723
|
-
|
|
724
|
-
Every event the runtime emits already has it, so a sink that only reads them needs no change. A
|
|
725
|
-
fixture, a test double or a pipeline that re-validates events persisted by an earlier version does:
|
|
726
|
-
give the older records a response identity, or keep parsing them with the schema they were written
|
|
727
|
-
under.
|
|
728
|
-
|
|
729
|
-
If you implement the whole `AgentRuntime` interface — usually a mock — add the new method:
|
|
730
|
-
|
|
731
|
-
```ts
|
|
732
|
-
// before
|
|
733
|
-
const fake: AgentRuntime = { submit, interrupt, recover, close }
|
|
734
|
-
|
|
735
|
-
// after
|
|
736
|
-
const fake: AgentRuntime = { submit, interrupt, abandon, recover, close }
|
|
737
|
-
```
|
|
738
|
-
|
|
739
|
-
No data migration is involved, and nothing in the store changes shape.
|
|
740
|
-
|
|
741
|
-
## Released migration: 0.87.0
|
|
742
|
-
|
|
743
|
-
Only if your project implements `AgentConversationReader` itself. A message page
|
|
744
|
-
now names which of its messages compaction removed:
|
|
745
|
-
|
|
746
|
-
```ts
|
|
747
|
-
// before
|
|
748
|
-
return { items, ...(nextCursor && { nextCursor }) }
|
|
749
|
-
|
|
750
|
-
// after
|
|
751
|
-
return { items, compacted: [], ...(nextCursor && { nextCursor }) }
|
|
752
|
-
```
|
|
753
|
-
|
|
754
|
-
An empty array is the honest answer for a reader that pages only the active
|
|
755
|
-
history; it is what the SQLite reader returns unless the caller asks for
|
|
756
|
-
`includeCompacted`. Calling the reader needs no change, and no data migration is
|
|
757
|
-
involved.
|
|
758
|
-
|
|
759
|
-
## Released migration: 0.86.0
|
|
760
|
-
|
|
761
|
-
Only if you branch on `AgentTerminalReason` or show it to a person. Three
|
|
762
|
-
failures that used to arrive as `provider_failure` now arrive as themselves:
|
|
763
|
-
|
|
764
|
-
```ts
|
|
765
|
-
// before
|
|
766
|
-
if (run.terminalReason === 'provider_failure') showOutage()
|
|
767
|
-
|
|
768
|
-
// after
|
|
769
|
-
switch (run.terminalReason) {
|
|
770
|
-
case 'provider_failure':
|
|
771
|
-
showOutage()
|
|
772
|
-
break
|
|
773
|
-
case 'storage_conflict':
|
|
774
|
-
// Another writer took this run's revision, or the store refused the write.
|
|
775
|
-
retryOrReport()
|
|
776
|
-
break
|
|
777
|
-
case 'output_rejected':
|
|
778
|
-
// Your own `protocol.acceptTerminal` refused the finished message.
|
|
779
|
-
reportRejectedAnswer()
|
|
780
|
-
break
|
|
781
|
-
case 'runtime_failure':
|
|
782
|
-
// The runtime, or a check the SDK ran on what it was handed, failed
|
|
783
|
-
// before the provider was reached.
|
|
784
|
-
reportInternal()
|
|
785
|
-
break
|
|
786
|
-
}
|
|
787
|
-
```
|
|
788
|
-
|
|
789
|
-
A run that never reached the provider can no longer report `provider_failure`,
|
|
790
|
-
so an alert keyed on that value stops firing for causes that were never the
|
|
791
|
-
provider's.
|
|
792
|
-
|
|
793
|
-
If you implement `AgentRuntimeStore` directly, add the event-ledger surface:
|
|
794
|
-
|
|
795
|
-
```ts
|
|
796
|
-
const store: AgentRuntimeStore = {
|
|
797
|
-
// existing normalized operations
|
|
798
|
-
appendEvent,
|
|
799
|
-
readEvents,
|
|
800
|
-
exportConversation,
|
|
801
|
-
importConversation,
|
|
802
|
-
}
|
|
803
|
-
```
|
|
804
|
-
|
|
805
|
-
If you implement an `AgentRuntimeStoreDriver` (Prisma, Postgres, any external
|
|
806
|
-
database), the ledger is yours to keep: `events` is a required member, and it
|
|
807
|
-
needs a table.
|
|
808
|
-
|
|
809
|
-
```ts
|
|
810
|
-
// before
|
|
811
|
-
const driver: AgentRuntimeStoreDriver<Tx> = { transaction, head, runs, admissions, history, scanRecoverable }
|
|
812
|
-
|
|
813
|
-
// after
|
|
814
|
-
const driver: AgentRuntimeStoreDriver<Tx> = {
|
|
815
|
-
transaction, head, runs, admissions, history, scanRecoverable,
|
|
816
|
-
events: {
|
|
817
|
-
// One row per event; `seq` is per conversation, starts at 1, and is
|
|
818
|
-
// assigned inside the caller's transaction so concurrent appends cannot
|
|
819
|
-
// share or skip a number.
|
|
820
|
-
append: async (tx, draft) => {
|
|
821
|
-
// Two transactions that both read max(seq) and both insert max + 1
|
|
822
|
-
// collide on the primary key; under SERIALIZABLE the snapshot predates
|
|
823
|
-
// any lock you take here. Treat a unique violation on this table as a
|
|
824
|
-
// serialization conflict and re-run the whole transaction — see
|
|
825
|
-
// `runTransaction` in examples/agent-store-prisma/adapter.ts.
|
|
826
|
-
const seq = (await tx.event.aggregate({ _max: { seq: true }, where: { conversationId: draft.conversationId } }))._max.seq ?? 0
|
|
827
|
-
await tx.event.create({ data: { ...draft, seq: seq + 1, payload: JSON.stringify(draft.payload) } })
|
|
828
|
-
return { ...draft, seq: seq + 1 }
|
|
829
|
-
},
|
|
830
|
-
// Ordered by `seq`, bounded by `fromSeq`/`toSeq`/`limit`; `nextSeq` when
|
|
831
|
-
// more remain.
|
|
832
|
-
list: async (tx, input) => { /* see examples/agent-store-prisma/adapter.ts */ },
|
|
833
|
-
},
|
|
834
|
-
}
|
|
835
|
-
```
|
|
836
|
-
|
|
837
|
-
The table carries `eventId` (unique), `conversationId`, `seq`, `schemaVersion`,
|
|
838
|
-
`kind`, `occurredAt`, `ignorable` and `payload`. `runAgentStoreConformance`
|
|
839
|
-
from `stitchkit/testing` now exercises it — contiguous `seq` under twenty
|
|
840
|
-
concurrent appends, bounded reads, the `ignorable` flag, a byte-stable export
|
|
841
|
-
— so run it against your driver before deploying. Expect one more insert per
|
|
842
|
-
run operation (`runtime/transition`) and one per model step
|
|
843
|
-
(`provider/request`) on the hot path; there is no opt-out.
|
|
844
|
-
|
|
845
|
-
If you operate a built-in SQLite store file:
|
|
846
|
-
|
|
847
|
-
1. Back the file up. The first open by 0.86.0 migrates it to schema 2 in one
|
|
848
|
-
transaction and there is no way back: a 0.85.x package refuses a migrated
|
|
849
|
-
file with `Unsupported Stitchkit agent-runtime SQLite schema version 2`.
|
|
850
|
-
2. Check the build for FTS5 before deploying:
|
|
851
|
-
|
|
852
|
-
```sql
|
|
853
|
-
SELECT sqlite_compileoption_used('ENABLE_FTS5');
|
|
854
|
-
```
|
|
855
|
-
|
|
856
|
-
A build without it is refused at open with `requires FTS5 support`. On the
|
|
857
|
-
machine this was verified, Bun 1.3 `bun:sqlite` and Node 24.18 `node:sqlite`
|
|
858
|
-
both carry it; verify your own build rather than assuming — the table of
|
|
859
|
-
supported runtimes says Node ≥ 22.5, and FTS5 there is not verified here.
|
|
860
|
-
3. Know what the migration wrote. Each existing conversation becomes one
|
|
861
|
-
`runtime/baseline` event at `seq 1`, dated when the migration ran, with
|
|
862
|
-
`asOf` inside the payload naming the last message it describes. Event
|
|
863
|
-
search and projections address that conversation's pre-migration history as
|
|
864
|
-
one snapshot at `seq 1`; event-level precision begins with the first event
|
|
865
|
-
after the migration.
|
|
866
|
-
|
|
867
|
-
If you subscribe to `AgentRuntimeEvent` and switch over `event.type`
|
|
868
|
-
exhaustively, add the transient `attempt-reset` case — drop the run's
|
|
869
|
-
transient text — or the reducer stops compiling; a reducer that ignores it
|
|
870
|
-
keeps a failed attempt's partial text on screen.
|
|
871
|
-
|
|
872
|
-
New in this release, not a migration: child runs cascade only when the manager
|
|
873
|
-
is given to the runtime —
|
|
874
|
-
`createAgentRuntime({ ...config, children: createSqliteAgentChildManager({ sqlite, spawn }) })`
|
|
875
|
-
— and the SQLite companions take the store handle (`{ sqlite }`), whose
|
|
876
|
-
`database` and `transaction` they share.
|
|
877
|
-
|
|
878
|
-
## Released migration: 0.85.0
|
|
879
|
-
|
|
880
|
-
Only if you implement `AgentRuntimeStore` directly. Add the new durable
|
|
881
|
-
operation mutation beside the existing run mutations:
|
|
882
|
-
|
|
883
|
-
```ts
|
|
884
|
-
// before
|
|
885
|
-
const store: AgentRuntimeStore = {
|
|
886
|
-
checkpointRunAssistant,
|
|
887
|
-
commitRunTerminal,
|
|
888
|
-
// ...
|
|
889
|
-
}
|
|
890
|
-
|
|
891
|
-
// after
|
|
892
|
-
const store: AgentRuntimeStore = {
|
|
893
|
-
checkpointRunAssistant,
|
|
894
|
-
recordRunOperation,
|
|
895
|
-
commitRunTerminal,
|
|
896
|
-
// ...
|
|
897
|
-
}
|
|
898
|
-
```
|
|
899
|
-
|
|
900
|
-
It must atomically replace `AgentRun.lastOperation`, increment the run revision
|
|
901
|
-
and conversation snapshot version, and enforce the supplied owner, fencing
|
|
902
|
-
token and expected revision. Adapters built with `createAgentRuntimeStore`
|
|
903
|
-
already receive the reference implementation; no driver method is added.
|
|
904
|
-
|
|
905
|
-
## Released migration: 0.84.0
|
|
906
|
-
|
|
907
|
-
Only if you call `createAgentCodingTools`.
|
|
908
|
-
|
|
909
|
-
```bash
|
|
910
|
-
rg -n "createAgentCodingTools"
|
|
911
|
-
```
|
|
912
|
-
|
|
913
|
-
**1. Backslashes are refused.** If anything in your system hands the tools a Windows-style path,
|
|
914
|
-
it now gets `FORBIDDEN`. Convert to `/` at the boundary:
|
|
915
|
-
|
|
916
|
-
```ts
|
|
917
|
-
// before: read_file({ path: 'src\\index.ts' }) // reached openat as two segments
|
|
918
|
-
// after: read_file({ path: 'src/index.ts' })
|
|
919
|
-
```
|
|
920
|
-
|
|
921
|
-
This is the half that matters most: until now a backslash bypassed your **required**
|
|
922
|
-
`authorize({ operation, path })` callback, not just `authorizePath`. A rule denying
|
|
923
|
-
`credentials/token.txt` refused that spelling and served — and overwrote — the same file spelled
|
|
924
|
-
`credentials\token.txt`. If your policy denies specific files, re-read your audit logs for
|
|
925
|
-
backslash spellings.
|
|
926
|
-
|
|
927
|
-
**2. Denying a directory now denies everything under it — and a policy must admit every directory
|
|
928
|
-
on the way to a file**, the way POSIX needs `+x` on each directory in a path.
|
|
929
|
-
|
|
930
|
-
If your policy is a DENY-list, it now does what it read as:
|
|
931
|
-
|
|
932
|
-
```ts
|
|
933
|
-
authorizePath: ({ path }) => path !== 'credentials'
|
|
934
|
-
// before: hid `credentials` from glob, served `credentials/token.txt` to read_file
|
|
935
|
-
// after: refuses `credentials/token.txt`, `credentials/nested/deep.txt` and writes under it
|
|
936
|
-
```
|
|
937
|
-
|
|
938
|
-
If you relied on the old behaviour — a directory hidden from discovery but readable directly — you
|
|
939
|
-
were relying on a defect, and the two halves of one callback disagreeing. Name the paths you
|
|
940
|
-
actually want reachable instead.
|
|
941
|
-
|
|
942
|
-
If your policy is an ALLOW-list, widen it to the directories it leads through, or nothing under
|
|
943
|
-
them is reachable:
|
|
944
|
-
|
|
945
|
-
```ts
|
|
946
|
-
// before: allowed src/index.ts, because only the leaf was ever asked
|
|
947
|
-
authorizePath: ({ path }) => path.startsWith('src/')
|
|
948
|
-
// after: `src` itself is asked first and refused, so the file is refused too
|
|
949
|
-
authorizePath: ({ path }) => path === 'src' || path.startsWith('src/')
|
|
950
|
-
```
|
|
951
|
-
|
|
952
|
-
The workspace root is not asked about — it is the boundary the tools already own.
|
|
953
|
-
|
|
954
|
-
**3. The policy is called more often.** A path of depth N costs N+1 calls (`.`, then each ancestor,
|
|
955
|
-
then the leaf), outermost first, stopping at the first refusal. A policy that logs or meters will
|
|
956
|
-
see a different sequence, and will no longer see the leaf once an ancestor has refused.
|
|
957
|
-
|
|
958
|
-
## Released migration: 0.83.0
|
|
959
|
-
|
|
960
|
-
Two things, both mechanical, and only if you touch an observability sink.
|
|
961
|
-
|
|
962
|
-
```bash
|
|
963
|
-
rg -n "createObservability|createApplicationEventSink|createApplicationSnapshotSink|createAgentRuntimeEventSink|createAgentObservability"
|
|
964
|
-
```
|
|
965
|
-
|
|
966
|
-
**1. `flush()` returns `Promise<boolean>`.** `await sink.flush()` needs no
|
|
967
|
-
change. Only a declared type does:
|
|
968
|
-
|
|
969
|
-
```ts
|
|
970
|
-
// before
|
|
971
|
-
const flushAudit: () => Promise<void> = observability.flush
|
|
972
|
-
// after
|
|
973
|
-
const flushAudit: () => Promise<boolean> = observability.flush
|
|
974
|
-
```
|
|
975
|
-
|
|
976
|
-
**2. `ObservabilityDrainReport` carries `drained`.** The framework builds it, so
|
|
977
|
-
reading code is unchanged. A hand-built report — a test double, or one persisted
|
|
978
|
-
and re-parsed through `ObservabilityDrainReportSchema` — needs the field:
|
|
979
|
-
|
|
980
|
-
```ts
|
|
981
|
-
// before
|
|
982
|
-
{ request, tools, total, durationMs }
|
|
983
|
-
// after
|
|
984
|
-
{ request, tools, total, durationMs, drained: true }
|
|
985
|
-
```
|
|
986
|
-
|
|
987
|
-
Then take the thing this release exists for. Every drain now accepts
|
|
988
|
-
`{ timeoutMs?, signal? }`, so a shutdown can give the audit drain the same
|
|
989
|
-
deadline it gives every other step:
|
|
990
|
-
|
|
991
|
-
```ts
|
|
992
|
-
const report = await observability.close({ timeoutMs: 5_000 })
|
|
993
|
-
if (!report.drained) {
|
|
994
|
-
logger.warn('audit drain incomplete', {
|
|
995
|
-
unwritten: report.total.received - report.total.filtered - report.total.completed,
|
|
996
|
-
})
|
|
997
|
-
}
|
|
998
|
-
```
|
|
999
|
-
|
|
1000
|
-
The bound ends the **waiting**, not the writes: a sink's `write` is handed no
|
|
1001
|
-
cancellation, so an outstanding one keeps running against whatever you close
|
|
1002
|
-
next. Racing `close()` against your own timer looks equivalent and is not — it
|
|
1003
|
-
discards the report along with the wait.
|
|
1004
|
-
|
|
1005
|
-
## Released migration: 0.82.0
|
|
1006
|
-
|
|
1007
|
-
One thing, and only if you mount MCP or agent tools from a `createTrackingContract` contract.
|
|
1008
|
-
|
|
1009
|
-
```bash
|
|
1010
|
-
rg -n "createTrackingContract"
|
|
1011
|
-
```
|
|
1012
|
-
|
|
1013
|
-
The event ingest (`track`, `POST /events`) is now `expose: ['HTTP']`, which is
|
|
1014
|
-
what its sibling `bootstrap` always declared. Before, it declared nothing — and
|
|
1015
|
-
an endpoint with no `expose` is a tool on MCP and AGENT by default, so the
|
|
1016
|
-
mounted surface carried a `track_<prefix>` tool. Since this contract is built
|
|
1017
|
-
inside the framework, an application that had made every tool opt-in for the
|
|
1018
|
-
endpoints *it* authors could not have opted this one out.
|
|
1019
|
-
|
|
1020
|
-
**If you pin a tool-surface digest or count**, it moves by one; re-record it.
|
|
1021
|
-
**If you assert on tool names**, `track_<prefix>` is gone. **If nothing in your
|
|
1022
|
-
project mounts tools from this contract**, there is nothing to do — the HTTP
|
|
1023
|
-
routes, the client and the schemas are unchanged.
|
|
1024
|
-
|
|
1025
|
-
Un-declaring the tool was never the intent, so there is no option to keep it. If
|
|
1026
|
-
an agent in your system genuinely needs to record something, give it your own
|
|
1027
|
-
endpoint with your own schema: the browser ingest trusts a client-minted event
|
|
1028
|
-
id and a visit lease, and an agent holds neither.
|
|
1029
|
-
|
|
1030
|
-
## Released migration: 0.81.0
|
|
1031
|
-
|
|
1032
|
-
**Path literals own string params.**
|
|
1033
|
-
|
|
1034
|
-
An endpoint whose path contains `:id` or a terminal `*rest` no longer needs a
|
|
1035
|
-
duplicate `params: z.object({ …string() })` declaration. Remove schemas that do
|
|
1036
|
-
nothing beyond repeating path names:
|
|
1037
|
-
|
|
1038
|
-
```ts
|
|
1039
|
-
// before
|
|
1040
|
-
{ path: '/projects/:projectId/*filePath',
|
|
1041
|
-
params: z.object({ projectId: z.string(), filePath: z.string() }) }
|
|
1042
|
-
|
|
1043
|
-
// after
|
|
1044
|
-
{ path: '/projects/:projectId/*filePath' }
|
|
1045
|
-
```
|
|
1046
|
-
|
|
1047
|
-
Keep an explicit schema when it validates or coerces. It must cover every name
|
|
1048
|
-
in the path — an explicit schema that misses one now fails at `defineContract`
|
|
1049
|
-
with the path and the missing field named. Client calls and handler contexts
|
|
1050
|
-
infer the string fields from the literal, so a call that omitted one becomes a
|
|
1051
|
-
compile error instead of building a URL with an unresolved segment. Measured
|
|
1052
|
-
across three consuming applications before release (373 endpoints with path
|
|
1053
|
-
segments), no explicit schema missed a field: the migration is deleting
|
|
1054
|
-
schemas that only repeated the path, or nothing.
|