stitchkit 0.104.2 → 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 +372 -13
- 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 +153 -64
- 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 +78 -17
- 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 +16 -8
- 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 +287 -157
- 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 +1029 -409
- 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
|
@@ -0,0 +1,947 @@
|
|
|
1
|
+
# Upgrading 0.37.0 → 0.50.0 — stitchkit docs slice
|
|
2
|
+
|
|
3
|
+
> Generated from the `docs/` tree by `bun run gen:llms`. The index of all slices is
|
|
4
|
+
> `llms.txt` in this package.
|
|
5
|
+
|
|
6
|
+
Contains: Guide: Upgrading, 0.37.0 → 0.50.0 (docs/guide/upgrading.md)
|
|
7
|
+
|
|
8
|
+
==============================================================================
|
|
9
|
+
# Guide: Upgrading, 0.37.0 → 0.50.0 (docs/guide/upgrading.md)
|
|
10
|
+
==============================================================================
|
|
11
|
+
|
|
12
|
+
## Released migration: 0.50.0
|
|
13
|
+
|
|
14
|
+
### The factory's scope union now covers per-endpoint overrides
|
|
15
|
+
|
|
16
|
+
`createContractFactory<Scope>()` already required a typed `scope` on the
|
|
17
|
+
contract. It now holds a per-endpoint `scope` override to the same union. Nothing
|
|
18
|
+
to migrate unless an override is outside the union — which was always a bug: the
|
|
19
|
+
scope reached no auth rule, and `createAuthHook` threw
|
|
20
|
+
`[stitchkit] auth: no rule for scope "…"` on the first request to it.
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
const { defineContract } = createContractFactory<'public' | 'user' | 'admin'>()
|
|
24
|
+
|
|
25
|
+
defineContract({ prefix: 'posts', scope: 'user' }, {
|
|
26
|
+
// before: compiled; failed at request time
|
|
27
|
+
// after: compile error naming the scope (TypeScript even suggests 'admin')
|
|
28
|
+
purge: { method: 'DELETE', path: '/all', desc: 'Purge', scope: 'admn', output },
|
|
29
|
+
})
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Fix the typo, or widen the factory union if the scope is real. Contracts built
|
|
33
|
+
with plain `defineContract` are unaffected.
|
|
34
|
+
|
|
35
|
+
### A declared `defineErrors` message is now used
|
|
36
|
+
|
|
37
|
+
`ErrorDefinition` accepts `message`. Nothing to migrate unless a registry already
|
|
38
|
+
wrote that key: it type-checked before (excess-property checking does not fire
|
|
39
|
+
through a `const` generic) and was ignored, so the code itself went on the wire.
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
const { errors } = defineErrors({ GONE: { status: 410, message: 'Long gone' } })
|
|
43
|
+
// before: errors.GONE().message === 'GONE'
|
|
44
|
+
// after: errors.GONE().message === 'Long gone'
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
If a registry carried `message` as a note to the reader rather than as
|
|
48
|
+
user-facing text, either fix the text or drop the key. A code with no `details`
|
|
49
|
+
schema also shows that text to a model (its tool `details` is `{ message }`).
|
|
50
|
+
|
|
51
|
+
### Optional: adopt `createScopedImplement`
|
|
52
|
+
|
|
53
|
+
If the app declares one superset handler context because different scopes inject
|
|
54
|
+
different fields, replace it with a scope map. This is additive — `createImplement`
|
|
55
|
+
still works.
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
// before — one context for every scope; `ctx.userId` is typed even in a
|
|
59
|
+
// `public` handler, where the runtime never injects it
|
|
60
|
+
interface AppContext extends RuntimeContext { userId: string; isAdmin: boolean }
|
|
61
|
+
export const implement = createImplement<AppContext>()
|
|
62
|
+
|
|
63
|
+
// after — each handler typed by its endpoint's effective scope
|
|
64
|
+
export const implementFor = createScopedImplement<{
|
|
65
|
+
public: object
|
|
66
|
+
user: { userId: string }
|
|
67
|
+
admin: { userId: string; isAdmin: boolean }
|
|
68
|
+
}>()
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
`'public'` must be a key (a contract with no `scope` is `'public'`). Write
|
|
72
|
+
endpoints inline in the contract literal: an endpoint hoisted into a variable
|
|
73
|
+
widens its `scope` to `string` and is reported as undeclared.
|
|
74
|
+
|
|
75
|
+
## Released migration: 0.49.0
|
|
76
|
+
|
|
77
|
+
### The server handle became managed
|
|
78
|
+
|
|
79
|
+
`createServer()` and `serveNode()` return a handle that owns admission, HTTP
|
|
80
|
+
drain, realtime closure and one deadline-bounded runtime stop:
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
// before
|
|
84
|
+
server.stop()
|
|
85
|
+
await socket.io.close()
|
|
86
|
+
// after
|
|
87
|
+
await server.shutdown({ gracePeriodMs: 30_000 })
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
The runtime-specific instance stays reachable at `.runtime`, so an escape hatch
|
|
91
|
+
you already rely on does not disappear — but code that closed transports itself,
|
|
92
|
+
in its own order, is now racing the handle. Delete the manual closes rather than
|
|
93
|
+
keeping both; the handle's result tells you what it drained and what it forced.
|
|
94
|
+
|
|
95
|
+
### Socket.IO mounts through the whole handle
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
// before
|
|
99
|
+
createServer({ websocket: socket.websocket, rawRoutes: [socket.route] })
|
|
100
|
+
// after
|
|
101
|
+
createServer({ socket })
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
One owner for the route, the WebSocket attachment and the closure. For a raw Bun
|
|
105
|
+
lane, keep the composed `websocket` handler and pass `socket` beside it.
|
|
106
|
+
|
|
107
|
+
### Bun native `routes` are gone
|
|
108
|
+
|
|
109
|
+
Native routes run before the Fetch handler, so they bypassed managed admission —
|
|
110
|
+
which means they also bypassed shutdown, logging and observability, and that is
|
|
111
|
+
why they had to go rather than be wired up:
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
// before
|
|
115
|
+
createServer({ routes: { '/health': () => Response.json({ ok: true }) } })
|
|
116
|
+
// after
|
|
117
|
+
createServer({ rawRoutes: [{ method: 'GET', path: '/health', handler: () => Response.json({ ok: true }) }] })
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### The handshake policy takes a Web `Request`
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
// before
|
|
124
|
+
createSocketIOServer({ serverOptions: { allowRequest: (req, done) => done(null, allowed(req)) } })
|
|
125
|
+
// after
|
|
126
|
+
createSocketIOServer({ allowRequest: (request) => allowed(request) })
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
The Node-shaped callback is gone, and the policy is now composed with shutdown
|
|
130
|
+
admission on both runtimes: a handshake arriving during drain is refused for
|
|
131
|
+
you.
|
|
132
|
+
|
|
133
|
+
## Released migration: 0.48.0
|
|
134
|
+
|
|
135
|
+
### Typed-client request options move to `.withOptions`
|
|
136
|
+
|
|
137
|
+
Generated endpoint methods reserve their ordinary call signature for contract
|
|
138
|
+
variables. This keeps them directly assignable to callback APIs whose runtime
|
|
139
|
+
supplies its own second context argument, including `react-query-kit` and
|
|
140
|
+
TanStack Query. Move imperative cancellation to the callable's explicit method:
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
// before — endpoint with arguments
|
|
144
|
+
await api.create({ name: 'Max' }, { signal })
|
|
145
|
+
|
|
146
|
+
// after
|
|
147
|
+
await api.create.withOptions({ name: 'Max' }, { signal })
|
|
148
|
+
|
|
149
|
+
// before — endpoint without arguments
|
|
150
|
+
await api.health({ signal })
|
|
151
|
+
|
|
152
|
+
// after
|
|
153
|
+
await api.health.withOptions({ signal })
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Direct query and mutation composition remains unchanged:
|
|
157
|
+
|
|
158
|
+
```ts
|
|
159
|
+
createMutation({ mutationFn: api.create })
|
|
160
|
+
createQuery({ queryKey: ['search'], fetcher: api.search })
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
There is no positional-options alias. Ordinary generated methods ignore extra
|
|
164
|
+
runtime callback arguments; only `.withOptions` reads `ClientRequestOptions`.
|
|
165
|
+
|
|
166
|
+
## Released migration: 0.47.0
|
|
167
|
+
|
|
168
|
+
### HTTP auth moves to the pre-body `authorize` phase
|
|
169
|
+
|
|
170
|
+
Move the HTTP wiring of `createAuthHook` from `beforeHandle` to `authorize`.
|
|
171
|
+
This lets Stitchkit reject an unauthorized JSON or multipart request after path
|
|
172
|
+
parameter validation but before reading a body chunk. Keep application
|
|
173
|
+
preconditions that depend on validated input in `beforeHandle`.
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
const auth = createAuthHook({ authenticate, authorize })
|
|
177
|
+
|
|
178
|
+
// before
|
|
179
|
+
createServer({ services, hooks: { beforeHandle: auth } })
|
|
180
|
+
|
|
181
|
+
// after
|
|
182
|
+
createServer({ services, hooks: { authorize: auth } })
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Tool transports already receive parsed input, so their wiring does not move:
|
|
186
|
+
|
|
187
|
+
```ts
|
|
188
|
+
createMcpHandler({ services, lifecycle: { beforeHandle: auth } })
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
If a custom HTTP authorization hook read `ctx.input`, `ctx.files` or raw body
|
|
192
|
+
state, split it: identity/scope checks belong in `authorize`; validated payload
|
|
193
|
+
preconditions belong in `beforeHandle` or the domain service.
|
|
194
|
+
|
|
195
|
+
### Multipart uses a typed descriptor and `ctx.files`
|
|
196
|
+
|
|
197
|
+
Replace every string multipart declaration, top-level `maxUploadBytes` and
|
|
198
|
+
`ctx.file`. The descriptor is now the only source of request, per-file,
|
|
199
|
+
cardinality and declared media-type policy.
|
|
200
|
+
|
|
201
|
+
```ts
|
|
202
|
+
// before
|
|
203
|
+
upload: {
|
|
204
|
+
method: 'POST',
|
|
205
|
+
path: '/',
|
|
206
|
+
multipart: 'file',
|
|
207
|
+
maxUploadBytes: 25 * 1024 * 1024,
|
|
208
|
+
}
|
|
209
|
+
upload: ({ file, input }) => store(file, input)
|
|
210
|
+
|
|
211
|
+
// after
|
|
212
|
+
upload: {
|
|
213
|
+
method: 'POST',
|
|
214
|
+
path: '/',
|
|
215
|
+
multipart: {
|
|
216
|
+
maxRequestBytes: 25 * 1024 * 1024,
|
|
217
|
+
files: {
|
|
218
|
+
file: {
|
|
219
|
+
maxBytes: 20 * 1024 * 1024,
|
|
220
|
+
contentTypes: ['image/*', 'application/pdf'],
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
}
|
|
225
|
+
upload: ({ files, input }) => store(files.file, input)
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Multiple files are repeated under one multipart field name and arrive in the
|
|
229
|
+
same order:
|
|
230
|
+
|
|
231
|
+
```ts
|
|
232
|
+
files: {
|
|
233
|
+
attachments: { multiple: true, maxFiles: 8 },
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
await api.upload({ attachments: [firstFile, secondFile] })
|
|
237
|
+
// handler: files.attachments is File[]
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
For direct-to-storage delivery, set `delivery: 'stream'` and implement the
|
|
241
|
+
endpoint with `defineMultipartStream`. A receiver must consume its Web Stream
|
|
242
|
+
and return `{ value, cleanup }`; the final handler sees only receiver values.
|
|
243
|
+
There is no deprecated overload or buffered compatibility path under the old
|
|
244
|
+
contract shape.
|
|
245
|
+
|
|
246
|
+
## Released migration: 0.46.0
|
|
247
|
+
|
|
248
|
+
### `REALTIME_CONTRACT_VIOLATION` joined the error registry
|
|
249
|
+
|
|
250
|
+
Realtime contract failures use the framework error model instead of a bare
|
|
251
|
+
`ZodError`, so an exhaustive map stops compiling until the code is added:
|
|
252
|
+
|
|
253
|
+
```ts
|
|
254
|
+
// before
|
|
255
|
+
{ …, INTERNAL_SERVER_ERROR: 'internal' } satisfies Record<StitchErrorCode, string>
|
|
256
|
+
// after
|
|
257
|
+
{ …, INTERNAL_SERVER_ERROR: 'internal', REALTIME_CONTRACT_VIOLATION: 'internal' } satisfies Record<StitchErrorCode, string>
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Only an exhaustive map breaks. Since 0.56.1 `codeMap` itself is partial, so a
|
|
261
|
+
map without the `satisfies` keeps compiling and lets the code travel as itself.
|
|
262
|
+
|
|
263
|
+
### `RealtimeRejectedEvent.error` is an `AppError`
|
|
264
|
+
|
|
265
|
+
```ts
|
|
266
|
+
// before
|
|
267
|
+
onRejected: ({ error }) => error.issues
|
|
268
|
+
// after
|
|
269
|
+
onRejected: ({ error }) => error.details?.issues // the ZodError moves to error.cause
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
The envelope gained `reason` and `fault`. The consequence worth checking: code
|
|
273
|
+
reading `.issues` directly does not fail to compile if the handler is loosely
|
|
274
|
+
typed — it silently reads `undefined`. Grep for `.issues` on rejection handlers.
|
|
275
|
+
|
|
276
|
+
### CLI construction refuses reserved names
|
|
277
|
+
|
|
278
|
+
A contract field or tool named `json`, `wait`, `quiet`, `dry-run`, `help`,
|
|
279
|
+
`version`, `wait-timeout` or `output-dir` now **throws while the CLI is built**,
|
|
280
|
+
instead of being silently shadowed:
|
|
281
|
+
|
|
282
|
+
```ts
|
|
283
|
+
// before: app schedule_job --wait 2h → {"path":"2h"}, exit 0
|
|
284
|
+
// after: building a CLI over a contract with a "wait" field throws
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
This one fires at startup, not at call time, so an application shipping such a
|
|
288
|
+
field crashes on boot after the upgrade. That is deliberate — the old behaviour
|
|
289
|
+
corrupted arguments silently — but it means the upgrade is not safe to deploy
|
|
290
|
+
without building the CLI once locally.
|
|
291
|
+
|
|
292
|
+
### `createToolLogger` writes to stderr
|
|
293
|
+
|
|
294
|
+
stdout is the JSON-RPC channel of a stdio MCP server, and the previous
|
|
295
|
+
`console.info` default corrupted it. Pass `log` to redirect if your process
|
|
296
|
+
collected tool logs from stdout.
|
|
297
|
+
|
|
298
|
+
## Released migration: 0.44.0
|
|
299
|
+
|
|
300
|
+
### MCP TypeScript SDK v2 and protocol `2026-07-28`
|
|
301
|
+
|
|
302
|
+
This is a hard cut: there is one Stitchkit API and no v1 aliases. Applications
|
|
303
|
+
that expose MCP install the split server package; applications that implement an
|
|
304
|
+
MCP host or run client E2E install the split client package.
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
bun remove @modelcontextprotocol/sdk
|
|
308
|
+
bun add @modelcontextprotocol/server@^2 ai@^7
|
|
309
|
+
# MCP hosts and client-side E2E only:
|
|
310
|
+
bun add -d @modelcontextprotocol/client@^2
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
Direct SDK imports move to the split packages too:
|
|
314
|
+
|
|
315
|
+
```ts
|
|
316
|
+
// before
|
|
317
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
|
|
318
|
+
|
|
319
|
+
// after
|
|
320
|
+
import { McpServer } from '@modelcontextprotocol/server'
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
MCP Apps additionally install `@modelcontextprotocol/ext-apps`. That adapter may
|
|
324
|
+
carry its own isolated v1-era transitive/peer relationship while the ecosystem
|
|
325
|
+
finishes its cutover; it does not permit application code to import the removed
|
|
326
|
+
monolithic SDK. Application-owned MCP server and client code uses the v2 split
|
|
327
|
+
packages exclusively.
|
|
328
|
+
|
|
329
|
+
```ts
|
|
330
|
+
// before
|
|
331
|
+
import { Client } from '@modelcontextprotocol/sdk/client/index.js'
|
|
332
|
+
import { createMcpHandler } from 'stitchkit/tools'
|
|
333
|
+
|
|
334
|
+
const handleMcp = createMcpHandler({
|
|
335
|
+
serverInfo,
|
|
336
|
+
auth,
|
|
337
|
+
services,
|
|
338
|
+
sessionMode: 'stateless',
|
|
339
|
+
})
|
|
340
|
+
rawRoutes: [{ method: 'ALL', path: '/mcp', handler: handleMcp }]
|
|
341
|
+
|
|
342
|
+
// after
|
|
343
|
+
import { Client } from '@modelcontextprotocol/client'
|
|
344
|
+
import { createMcpHandler, createMcpHttpRoute } from 'stitchkit/tools'
|
|
345
|
+
|
|
346
|
+
const mcp = createMcpHandler({
|
|
347
|
+
serverInfo,
|
|
348
|
+
auth,
|
|
349
|
+
services,
|
|
350
|
+
legacy: 'serve',
|
|
351
|
+
})
|
|
352
|
+
rawRoutes: [createMcpHttpRoute({ path: '/mcp', handler: mcp })]
|
|
353
|
+
// graceful shutdown: await mcp.close()
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
Keep the owned handle and close it from the same shutdown path as the HTTP
|
|
357
|
+
server. A minimal runtime smoke should list tools before shutdown and prove the
|
|
358
|
+
closed handler no longer serves requests:
|
|
359
|
+
|
|
360
|
+
```ts
|
|
361
|
+
const mcp = createMcpHandler(config)
|
|
362
|
+
const route = createMcpHttpRoute({ path: '/mcp', handler: mcp })
|
|
363
|
+
|
|
364
|
+
const beforeClose = await route.handler(listToolsRequest)
|
|
365
|
+
if (!beforeClose.ok) throw new Error('MCP list-tools smoke failed')
|
|
366
|
+
|
|
367
|
+
await mcp.close()
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
Remove `@modelcontextprotocol/sdk`, `sessionMode`, `McpSessionMode`, session
|
|
371
|
+
stores and all `Mcp-Session-Id` handling. HTTP is always request-isolated and
|
|
372
|
+
stateless. `legacy: 'serve'` (default) lets the official SDK negotiate supported
|
|
373
|
+
pre-2026 stateless clients on the same endpoint; `legacy: 'reject'` makes it
|
|
374
|
+
modern-only. This is not a stateful compatibility transport.
|
|
375
|
+
|
|
376
|
+
#### Output shape depends on the negotiated protocol era
|
|
377
|
+
|
|
378
|
+
Stitchkit always validates the handler result against the declared output
|
|
379
|
+
schema. The negotiated MCP era determines only its wire representation:
|
|
380
|
+
|
|
381
|
+
| Negotiated era | Non-object `structuredContent` |
|
|
382
|
+
|---|---|
|
|
383
|
+
| MCP `2026-07-28` | the exact schema-valid JSON root: array, scalar or `null` |
|
|
384
|
+
| supported legacy era | the official SDK codec adapts it to `{ result: value }` |
|
|
385
|
+
|
|
386
|
+
Object roots keep their object shape in both eras. Do not change every consumer
|
|
387
|
+
expectation to the modern shape while `legacy: 'serve'` remains enabled. Pin
|
|
388
|
+
both protocol versions in the consumer's transport E2E and assert the boundary
|
|
389
|
+
explicitly:
|
|
390
|
+
|
|
391
|
+
```ts
|
|
392
|
+
await expectToolOutputForProtocol('2026-07-28', ['a', 'b'])
|
|
393
|
+
await expectToolOutputForProtocol('2025-11-25', { result: ['a', 'b'] })
|
|
394
|
+
|
|
395
|
+
async function expectToolOutputForProtocol(
|
|
396
|
+
protocolVersion: '2026-07-28' | '2025-11-25',
|
|
397
|
+
expected: unknown,
|
|
398
|
+
) {
|
|
399
|
+
const client = await connectConsumerMcpClient({ protocolVersion })
|
|
400
|
+
const result = await client.callTool({ name: 'list_notes', arguments: {} })
|
|
401
|
+
expect(result.structuredContent).toEqual(expected)
|
|
402
|
+
await client.close()
|
|
403
|
+
}
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
`connectConsumerMcpClient` represents the consumer's real HTTP or stdio setup;
|
|
407
|
+
configure its official client with `versionNegotiation.mode.pin` so the test
|
|
408
|
+
cannot silently negotiate a different era.
|
|
409
|
+
|
|
410
|
+
The stdio helper now returns an owned lifecycle handle:
|
|
411
|
+
|
|
412
|
+
```ts
|
|
413
|
+
// before
|
|
414
|
+
await createStdioMcpServer(config)
|
|
415
|
+
|
|
416
|
+
// after
|
|
417
|
+
const stdio = await createStdioMcpServer({ ...config, legacy: 'serve' })
|
|
418
|
+
await stdio.close()
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
OAuth client registration is now one explicit policy object. CIMD is secure and
|
|
422
|
+
enabled by default; DCR is disabled unless supplied:
|
|
423
|
+
|
|
424
|
+
```ts
|
|
425
|
+
// before
|
|
426
|
+
mountOAuthProvider({ ...oauth, clients, codes, refreshTokens })
|
|
427
|
+
|
|
428
|
+
// after
|
|
429
|
+
mountOAuthProvider({
|
|
430
|
+
...oauth,
|
|
431
|
+
clientRegistration: {
|
|
432
|
+
preRegistered: { get: clients.get },
|
|
433
|
+
// optional: dcr: { register: clients.register, get: clients.get }
|
|
434
|
+
},
|
|
435
|
+
codes,
|
|
436
|
+
refreshTokens,
|
|
437
|
+
})
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
A URL client id must be HTTPS and serve a document whose `client_id` exactly
|
|
441
|
+
matches that URL, with explicit `redirect_uris` and
|
|
442
|
+
`token_endpoint_auth_method: 'none'`. Do not keep a consumer-side metadata
|
|
443
|
+
fetcher or DCR fallback; Stitchkit owns SSRF-safe resolution and caching.
|
|
444
|
+
|
|
445
|
+
Multi-round input is opt-in on the operation and does not change Agent, CLI or
|
|
446
|
+
ordinary HTTP handlers:
|
|
447
|
+
|
|
448
|
+
```ts
|
|
449
|
+
const ConfirmationSchema = z.object({ confirmed: z.boolean() })
|
|
450
|
+
|
|
451
|
+
mcp: {
|
|
452
|
+
inputRequired: [{
|
|
453
|
+
key: 'confirmation',
|
|
454
|
+
message: 'Confirm this action',
|
|
455
|
+
schema: ConfirmationSchema,
|
|
456
|
+
}],
|
|
457
|
+
}
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
Configure `multiRound.state` on the MCP server with a key of at least 32 bytes
|
|
461
|
+
and a stable authenticated `principal`. Read accepted typed content from
|
|
462
|
+
`ctx.mcpInput.confirmation`. Multiple declarations run in array order, the
|
|
463
|
+
aggregate remains exactly typed by key, keys must be unique, and declarations
|
|
464
|
+
must fit `multiRound.serving.maxRounds` (default `10`). Do not execute a
|
|
465
|
+
destructive side effect before the complete aggregate is accepted. A modern
|
|
466
|
+
request missing the declared elicitation capability receives JSON-RPC error
|
|
467
|
+
code `-32021`. The official per-request legacy HTTP bridge cannot issue
|
|
468
|
+
server-to-client elicitation, so it returns a deterministic failed tool result;
|
|
469
|
+
multi-round input is never silently treated as complete.
|
|
470
|
+
|
|
471
|
+
#### Compatibility matrix
|
|
472
|
+
|
|
473
|
+
| Host / transport | Tools and Apps | Multi-round input | Continuity |
|
|
474
|
+
|---|---|---|---|
|
|
475
|
+
| `2026-07-28` HTTP | yes | yes | request-isolated |
|
|
476
|
+
| supported legacy stateless HTTP | yes | unsupported result | request-isolated |
|
|
477
|
+
| `2026-07-28` stdio | yes | yes | one process connection |
|
|
478
|
+
| supported legacy stdio | yes | official SDK bridge | one process connection |
|
|
479
|
+
| Agent / CLI / ordinary HTTP | unchanged | not exposed | unchanged |
|
|
480
|
+
|
|
481
|
+
Subscriptions, cross-request progress and resumable stateful SSE are not
|
|
482
|
+
implemented or advertised.
|
|
483
|
+
|
|
484
|
+
#### Consumer checklist
|
|
485
|
+
|
|
486
|
+
1. Replace the monolithic SDK with `@modelcontextprotocol/server@^2` and, only
|
|
487
|
+
for hosts/tests, `@modelcontextprotocol/client@^2`.
|
|
488
|
+
2. Replace raw MCP route wiring with `createMcpHttpRoute`; retain and close the
|
|
489
|
+
returned handler/stdio handle during shutdown.
|
|
490
|
+
3. Delete all session mode, event-store and session-id code.
|
|
491
|
+
4. Move OAuth client policy under `clientRegistration`; publish CIMD or enable
|
|
492
|
+
DCR explicitly.
|
|
493
|
+
5. Make `authorizeUser` return the exact consented scope subset. The framework
|
|
494
|
+
validates that it is a subset of the request before saving the authorization
|
|
495
|
+
code:
|
|
496
|
+
|
|
497
|
+
```ts
|
|
498
|
+
// before
|
|
499
|
+
authorizeUser: async () => ({ userId })
|
|
500
|
+
|
|
501
|
+
// after
|
|
502
|
+
authorizeUser: async (_req, request) => ({
|
|
503
|
+
userId,
|
|
504
|
+
approvedScopes: request.scope?.split(' ') ?? [],
|
|
505
|
+
})
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
6. Snapshot `listToolNames`, run one contract tool, one runtime tool, any raw
|
|
509
|
+
multimodal tool and every MCP App resource you use.
|
|
510
|
+
7. Exercise modern HTTP and stdio with protocol `2026-07-28`; exercise legacy
|
|
511
|
+
only if `legacy: 'serve'` is part of your support policy.
|
|
512
|
+
8. Run the consumer's typecheck and runtime gates. A browser/HTTP-only consumer
|
|
513
|
+
must continue to work without either MCP package.
|
|
514
|
+
|
|
515
|
+
## Historical breaking migrations through 0.44.0
|
|
516
|
+
|
|
517
|
+
HTTP observability now completes inside the framework handler instead of a
|
|
518
|
+
nested fetch wrapper. Configure request and tool sinks explicitly:
|
|
519
|
+
|
|
520
|
+
```ts
|
|
521
|
+
// before
|
|
522
|
+
const audit = createAuditHook({ write })
|
|
523
|
+
createServer({
|
|
524
|
+
services,
|
|
525
|
+
wrapFetch: (handler) => wrapInRequestContext(audit.http(handler)),
|
|
526
|
+
})
|
|
527
|
+
mountAgent(services, { hooks: audit.toolCall })
|
|
528
|
+
|
|
529
|
+
// after
|
|
530
|
+
const observability = createObservability({
|
|
531
|
+
request: { write, includePayload: true },
|
|
532
|
+
tools: { write },
|
|
533
|
+
})
|
|
534
|
+
createServer({ services, observability: observability.request })
|
|
535
|
+
mountAgent(services, { hooks: observability.toolCall })
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
Body capture changed from always-on for body methods to opt-in. Set
|
|
539
|
+
`includePayload: true` only when the request sink needs the sanitized JSON body.
|
|
540
|
+
There is no `createAuditHook` or `audit.http` compatibility path;
|
|
541
|
+
`wrapInRequestContext` remains only for custom fetch pipelines.
|
|
542
|
+
|
|
543
|
+
Tool introspection now accepts one object-shaped contract/runtime surface. Stop
|
|
544
|
+
calling the internal contract collector or merging a locally converted runtime
|
|
545
|
+
manifest:
|
|
546
|
+
|
|
547
|
+
```ts
|
|
548
|
+
// before
|
|
549
|
+
buildToolManifest(services.flatMap((service) => collectTools(service, 'AGENT')))
|
|
550
|
+
listToolNames(services)
|
|
551
|
+
summarizeTransports(services)
|
|
552
|
+
|
|
553
|
+
// after
|
|
554
|
+
const surface = { services, runtimeTools }
|
|
555
|
+
buildToolManifest({ ...surface, transport: 'AGENT' })
|
|
556
|
+
listToolNames(surface)
|
|
557
|
+
summarizeTransports(surface)
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
`ToolNameEntry` adds `kind: 'contract' | 'runtime'`. `TransportSummary` is now
|
|
561
|
+
`{ contractServices, runtimeTools, totals, sources }`; replace `services` and
|
|
562
|
+
`perService` reads with the explicit counts and mixed-source breakdown. There
|
|
563
|
+
is no positional overload and no `buildRuntimeToolManifest`: Stitchkit owns the
|
|
564
|
+
combined order, transport filtering, canonical presentation schema and
|
|
565
|
+
cross-origin collision checks.
|
|
566
|
+
|
|
567
|
+
`defineErrors` now uses one Zod-first definition object and returns constructors
|
|
568
|
+
instead of positional throwers. Add explicit `throw`, move message/details/hint
|
|
569
|
+
into one options object, and declare a details schema when that code carries
|
|
570
|
+
structured context:
|
|
571
|
+
|
|
572
|
+
```ts
|
|
573
|
+
// before
|
|
574
|
+
const { errors } = defineErrors({ QUOTA_EXCEEDED: 429 })
|
|
575
|
+
errors.QUOTA_EXCEEDED('Try later', { retryAfterSeconds: 30 }, 'Wait')
|
|
576
|
+
|
|
577
|
+
// after
|
|
578
|
+
const { errors, definitions } = defineErrors({
|
|
579
|
+
QUOTA_EXCEEDED: {
|
|
580
|
+
status: 429,
|
|
581
|
+
details: z.object({ retryAfterSeconds: z.number().positive() }),
|
|
582
|
+
},
|
|
583
|
+
})
|
|
584
|
+
throw errors.QUOTA_EXCEEDED({
|
|
585
|
+
message: 'Try later',
|
|
586
|
+
details: { retryAfterSeconds: 30 },
|
|
587
|
+
hint: 'Wait',
|
|
588
|
+
})
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
There is no positional overload. A code without `details` forbids them; use an
|
|
592
|
+
optional object schema when the details object itself is optional. Read status
|
|
593
|
+
and schemas from the frozen `definitions` registry instead of maintaining a
|
|
594
|
+
parallel map.
|
|
595
|
+
|
|
596
|
+
Managed MCP runtime tools are now declared as immutable data. Move protected
|
|
597
|
+
registrar calls to `runtimeTools`; rename deliberate raw SDK registration to
|
|
598
|
+
`rawTools`. There is no registrar alias:
|
|
599
|
+
|
|
600
|
+
```ts
|
|
601
|
+
// before — protected
|
|
602
|
+
createMcpHandler({
|
|
603
|
+
services,
|
|
604
|
+
nativeTools: ({ registerTool }) => registerTool(preview),
|
|
605
|
+
})
|
|
606
|
+
|
|
607
|
+
// after — protected and prepared with the rest of the surface
|
|
608
|
+
createMcpHandler({ services, runtimeTools: [preview] })
|
|
609
|
+
|
|
610
|
+
// before — deliberate raw SDK opt-out
|
|
611
|
+
nativeTools: ({ rawServer }, auth) => mountRaw(rawServer, auth)
|
|
612
|
+
|
|
613
|
+
// after — still a deliberate raw SDK opt-out
|
|
614
|
+
rawTools: (server, auth) => mountRaw(server, auth)
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
When identity selects from a bounded set, replace a repeatedly prepared
|
|
618
|
+
`services(auth)` factory with a finite registry:
|
|
619
|
+
|
|
620
|
+
```ts
|
|
621
|
+
createMcpHandler({
|
|
622
|
+
surfaces: {
|
|
623
|
+
admin: { services: allServices, runtimeTools: [preview] },
|
|
624
|
+
member: { services: memberServices, runtimeTools: [preview] },
|
|
625
|
+
},
|
|
626
|
+
selectSurface: (auth) => auth.isAdmin ? 'admin' : 'member',
|
|
627
|
+
})
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
Keep direct `services(auth)` / `runtimeTools(auth)` only for genuinely
|
|
631
|
+
unbounded definitions; Stitchkit intentionally does not cache arbitrary auth
|
|
632
|
+
values.
|
|
633
|
+
|
|
634
|
+
Contract success bodies are now determined by the presence of `output`, not by
|
|
635
|
+
the handler's runtime value. A nullable output returns JSON `null` with status
|
|
636
|
+
`200`; `undefined` with a declared output and non-null data without an output
|
|
637
|
+
schema are contract violations:
|
|
638
|
+
|
|
639
|
+
```ts
|
|
640
|
+
// nullable JSON data: 200 with body `null`
|
|
641
|
+
session: {
|
|
642
|
+
method: 'GET', path: '/session', desc: 'Current session',
|
|
643
|
+
output: SessionSchema.nullable(),
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
// bodyless operation: 204 with no body
|
|
647
|
+
logout: {
|
|
648
|
+
method: 'POST', path: '/logout', desc: 'End the session',
|
|
649
|
+
}
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
Add an output schema to every handler that returns data. Omit `output` and
|
|
653
|
+
return nothing for bodyless operations; runtime tools follow the same rule and
|
|
654
|
+
type no-output handlers as `void`.
|
|
655
|
+
|
|
656
|
+
`createToolInvoker` now separates immutable registry preparation from per-call
|
|
657
|
+
runtime state. Move source/context/lifecycle/hooks/output-strip reporting from
|
|
658
|
+
the factory config to the third invocation argument. Use `invokeOrThrow` when a
|
|
659
|
+
nested operation should preserve the normalized `AppError` instead of returning
|
|
660
|
+
a model-facing failure envelope:
|
|
661
|
+
|
|
662
|
+
```ts
|
|
663
|
+
// before
|
|
664
|
+
const invoker = createToolInvoker(services, {
|
|
665
|
+
transport: 'AGENT', context: { identity }, lifecycle, hooks,
|
|
666
|
+
})
|
|
667
|
+
const result = await invoker.invoke(name, args)
|
|
668
|
+
|
|
669
|
+
// after
|
|
670
|
+
const invoker = createToolInvoker(services, { transport: 'AGENT' })
|
|
671
|
+
const result = await invoker.invoke(name, args, {
|
|
672
|
+
context: { identity }, lifecycle, hooks,
|
|
673
|
+
})
|
|
674
|
+
const data = await invoker.invokeOrThrow(name, args, {
|
|
675
|
+
context: { identity }, lifecycle, hooks,
|
|
676
|
+
})
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
There is no static runtime-config overload: request identity must not be retained
|
|
680
|
+
by a reusable compiled registry.
|
|
681
|
+
|
|
682
|
+
Entity cache handlers now require the cached list shape and CRUD policies. Move
|
|
683
|
+
`listKey` under `list`, make detail keys event-aware, and state the list-item
|
|
684
|
+
identity/projection explicitly:
|
|
685
|
+
|
|
686
|
+
```ts
|
|
687
|
+
// before
|
|
688
|
+
createEntityCacheHandlers<Entity>({
|
|
689
|
+
getId,
|
|
690
|
+
listKey: ['entities'],
|
|
691
|
+
detailKey: (id) => ['entities', id],
|
|
692
|
+
})
|
|
693
|
+
|
|
694
|
+
// after
|
|
695
|
+
createEntityCacheHandlers<Entity, EntityListItem>({
|
|
696
|
+
getId,
|
|
697
|
+
getListItemId: (item) => item.id,
|
|
698
|
+
toListItem: (entity) => ({ id: entity.id, name: entity.name }),
|
|
699
|
+
list: {
|
|
700
|
+
key: ['entities'],
|
|
701
|
+
shape: 'paginated',
|
|
702
|
+
createAt: 'start',
|
|
703
|
+
updateMissing: 'skip',
|
|
704
|
+
},
|
|
705
|
+
detailKey: (event) => ['entities', event.id],
|
|
706
|
+
})
|
|
707
|
+
```
|
|
708
|
+
|
|
709
|
+
Choose `array`, `paginated`, `infinite-array` or `infinite-paginated` to match
|
|
710
|
+
the actual cached data. A dynamic `list.key` / `detailKey` receives a
|
|
711
|
+
discriminated event and can derive scoped keys from the created/updated entity
|
|
712
|
+
or deleted payload. Add `compare` only when the backend has a canonical order;
|
|
713
|
+
the framework does not guess it or mutate pagination metadata.
|
|
714
|
+
|
|
715
|
+
Protected native MCP operations now use the transport-neutral runtime tool
|
|
716
|
+
definition. Return the schema-owned value from the handler and move MCP content
|
|
717
|
+
or metadata into `present.mcp`; `structuredContent` and `isError` are
|
|
718
|
+
framework-owned:
|
|
719
|
+
|
|
720
|
+
```ts
|
|
721
|
+
// before
|
|
722
|
+
registerTool({ input, output, handler: async () => ({
|
|
723
|
+
content: [{ type: 'image', data, mimeType: 'image/png' }],
|
|
724
|
+
structuredContent: { assetId },
|
|
725
|
+
}) })
|
|
726
|
+
|
|
727
|
+
// after
|
|
728
|
+
const preview = defineRuntimeTool({
|
|
729
|
+
name: 'render_preview', description, identity, input, output,
|
|
730
|
+
handler: async () => ({ assetId, data }),
|
|
731
|
+
present: {
|
|
732
|
+
mcp: (result) => ({
|
|
733
|
+
content: [{ type: 'image', data: result.data, mimeType: 'image/png' }],
|
|
734
|
+
}),
|
|
735
|
+
},
|
|
736
|
+
})
|
|
737
|
+
runtimeTools: [preview]
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
The removed `NativeMcp*` types have no aliases. Use `RuntimeToolDefinition`,
|
|
741
|
+
`RuntimeToolIdentity`, `RuntimeToolHandlerContext` and
|
|
742
|
+
`RuntimeMcpPresentation`. The same definition can now be passed to
|
|
743
|
+
`mountAgent(services, { runtimeTools: [preview] })`; add `present.agent` only
|
|
744
|
+
when the model needs rich text/file content instead of the neutral JSON result.
|
|
745
|
+
|
|
746
|
+
Trailing wildcards must be named consistently across the path and params schema:
|
|
747
|
+
|
|
748
|
+
```ts
|
|
749
|
+
// before
|
|
750
|
+
path: '/app/:slug/*'
|
|
751
|
+
params: z.object({ slug: z.string(), '*': z.string() })
|
|
752
|
+
ctx.params['*']
|
|
753
|
+
api.app({ slug: 'foo', '*': 'a/b' })
|
|
754
|
+
|
|
755
|
+
// after
|
|
756
|
+
path: '/app/:slug/*filePath'
|
|
757
|
+
params: z.object({ slug: z.string(), filePath: z.string() })
|
|
758
|
+
ctx.params.filePath
|
|
759
|
+
api.app({ slug: 'foo', filePath: 'a/b' })
|
|
760
|
+
```
|
|
761
|
+
|
|
762
|
+
Bare wildcards have no compatibility alias; raw routes use the same named form.
|
|
763
|
+
|
|
764
|
+
### Expected-401 matchers
|
|
765
|
+
|
|
766
|
+
`HttpClientConfig.authEndpoints` is removed. Replace manual path prefixes with
|
|
767
|
+
the operations whose 401 response is expected:
|
|
768
|
+
|
|
769
|
+
```ts
|
|
770
|
+
// before
|
|
771
|
+
createHttpClient({ baseUrl, authEndpoints: ['/api/auth/'] })
|
|
772
|
+
|
|
773
|
+
// after
|
|
774
|
+
createHttpClient({
|
|
775
|
+
baseUrl,
|
|
776
|
+
suppressUnauthorizedFor: contractEndpointMatchers(authContract, ['login', 'verify']),
|
|
777
|
+
})
|
|
778
|
+
```
|
|
779
|
+
|
|
780
|
+
There is no implicit `/auth/` suppression. Omit `suppressUnauthorizedFor` when
|
|
781
|
+
every 401 should emit the global `unauthorized` event.
|
|
782
|
+
|
|
783
|
+
## The 0.37 migration
|
|
784
|
+
|
|
785
|
+
Tool presentation is no longer an executable Zod parser. Replace the removed
|
|
786
|
+
flatten helpers with the JSON Schema compiler, and choose the explicit
|
|
787
|
+
`MountableTool` surface when using the advanced collection API:
|
|
788
|
+
|
|
789
|
+
```ts
|
|
790
|
+
// before
|
|
791
|
+
const flat = flattenUnionsDeep(zodSchema)
|
|
792
|
+
mountable.schema
|
|
793
|
+
|
|
794
|
+
// after
|
|
795
|
+
const flat = flattenToolJsonSchema(
|
|
796
|
+
z.toJSONSchema(zodSchema, { target: 'draft-07', io: 'input' }),
|
|
797
|
+
)
|
|
798
|
+
mountable.presentationSchema // model/MCP/manifest JSON Schema
|
|
799
|
+
mountable.argumentSchema // executable CLI argument adapter only
|
|
800
|
+
```
|
|
801
|
+
|
|
802
|
+
Contract and native handlers keep their original Zod schemas; MCP and agent SDK
|
|
803
|
+
adapters now forward raw arguments so defaults, coercions, refinements and
|
|
804
|
+
transforms execute exactly once inside Stitchkit. There are no compatibility
|
|
805
|
+
exports for `flattenDiscriminatedUnion`, `flattenUnionsDeep` or
|
|
806
|
+
`MountableTool.schema`. → ADR 0050
|
|
807
|
+
|
|
808
|
+
Tool-call hooks now take one options object. Migrate all three callbacks; there
|
|
809
|
+
are no positional overloads:
|
|
810
|
+
|
|
811
|
+
```ts
|
|
812
|
+
// before
|
|
813
|
+
beforeToolCall: (toolName, args, context, endpoint) => {}
|
|
814
|
+
afterToolCall: (toolName, args, result, durationMs, context, endpoint, error) => {}
|
|
815
|
+
onToolError: (toolName, error, context, endpoint) => {}
|
|
816
|
+
|
|
817
|
+
// after
|
|
818
|
+
beforeToolCall: ({ toolName, args, context, endpoint }) => {}
|
|
819
|
+
afterToolCall: ({ toolName, args, result, durationMs, context, endpoint, error }) => {}
|
|
820
|
+
onToolError: ({ toolName, error, context, endpoint }) => {}
|
|
821
|
+
```
|
|
822
|
+
|
|
823
|
+
### MCP schema validation
|
|
824
|
+
|
|
825
|
+
The standalone validator now takes one object and live MCP configs carry the
|
|
826
|
+
same rules under `schemaValidation`. Migrate every positional call and every
|
|
827
|
+
`onIncompatibleSchema` field; there is no old-shape overload:
|
|
828
|
+
|
|
829
|
+
```ts
|
|
830
|
+
// before
|
|
831
|
+
validateMcpSchemas(services, 'throw', logger, { requireTypedProperties: true })
|
|
832
|
+
createMcpHandler({ services, onIncompatibleSchema: 'throw' })
|
|
833
|
+
|
|
834
|
+
// after
|
|
835
|
+
validateMcpSchemas({ services, policy: 'throw', logger, requireTypedProperties: true })
|
|
836
|
+
createMcpHandler({ services, schemaValidation: { policy: 'throw' } })
|
|
837
|
+
```
|
|
838
|
+
|
|
839
|
+
Put `extend` and `flattenUnionInput` beside `services`, not inside
|
|
840
|
+
`schemaValidation`. The handler applies the profile to the exact prepared schema
|
|
841
|
+
it advertises. Add `requirePortableFormats: true` when every custom JSON Schema
|
|
842
|
+
format must be rejected before a client sees it.
|
|
843
|
+
|
|
844
|
+
Native MCP registration also changed shape in 0.37. Move protected tools to the
|
|
845
|
+
framework registrar; keep an SDK-raw tool only by naming the opt-out:
|
|
846
|
+
|
|
847
|
+
```ts
|
|
848
|
+
// before
|
|
849
|
+
nativeTools: (server, auth) => server.registerTool(name, config, handler)
|
|
850
|
+
|
|
851
|
+
// after — lifecycle, hooks and schema policy apply
|
|
852
|
+
nativeTools: ({ registerTool }, auth) => registerTool({
|
|
853
|
+
name, description, identity, input, output, handler,
|
|
854
|
+
})
|
|
855
|
+
|
|
856
|
+
// after — intentionally raw
|
|
857
|
+
nativeTools: ({ rawServer }, auth) => rawServer.registerTool(name, config, handler)
|
|
858
|
+
```
|
|
859
|
+
|
|
860
|
+
If a tool hook annotated `endpoint` as `MethodDef`, remove that annotation or
|
|
861
|
+
use `OperationIdentity`: native operations have service/action/scope/method but
|
|
862
|
+
no HTTP path.
|
|
863
|
+
|
|
864
|
+
### Node-facing server types
|
|
865
|
+
|
|
866
|
+
`stitchkit/server` remains Bun-concrete: an explicitly annotated `RawRoute`
|
|
867
|
+
still receives `BunServer`. `stitchkit/node` no longer drags Bun declarations
|
|
868
|
+
into a Node project. Its raw routes default the host server to `unknown`, and
|
|
869
|
+
its Socket.IO handle exposes only Node capabilities:
|
|
870
|
+
|
|
871
|
+
```ts
|
|
872
|
+
// before — Node entry still leaked Bun-only fields and ambient types
|
|
873
|
+
const route: RawRoute = { handler: (_req, ctx) => ctx.server?.upgrade(...) }
|
|
874
|
+
const socket = await createSocketIOServer(config)
|
|
875
|
+
socket.websocket
|
|
876
|
+
|
|
877
|
+
// after — name a custom embedding host only when one exists
|
|
878
|
+
const route: RawRoute<MyHostServer> = {
|
|
879
|
+
handler: (_req, ctx) => useHost(ctx.server),
|
|
880
|
+
}
|
|
881
|
+
const socket = await createSocketIOServer(config)
|
|
882
|
+
socket.io
|
|
883
|
+
socket.attach(nodeHttpServer)
|
|
884
|
+
```
|
|
885
|
+
|
|
886
|
+
Node consumers can remove `@types/bun` unless another dependency independently
|
|
887
|
+
requires it.
|
|
888
|
+
|
|
889
|
+
### Managed server shutdown
|
|
890
|
+
|
|
891
|
+
`createServer()` and `serveNode()` now return the same structural managed
|
|
892
|
+
lifecycle. Replace every direct runtime stop and parallel Socket.IO close:
|
|
893
|
+
|
|
894
|
+
```ts
|
|
895
|
+
// before — split ownership
|
|
896
|
+
const socket = await createSocketIOServer(config)
|
|
897
|
+
const server = createServer({
|
|
898
|
+
services,
|
|
899
|
+
websocket: socket.websocket,
|
|
900
|
+
rawRoutes: [socket.route],
|
|
901
|
+
})
|
|
902
|
+
server.stop()
|
|
903
|
+
await socket.io.close()
|
|
904
|
+
|
|
905
|
+
// after — one owner and one total deadline
|
|
906
|
+
const socket = await createSocketIOServer(config)
|
|
907
|
+
const server = createServer({ services, socket })
|
|
908
|
+
const result = await server.shutdown({ gracePeriodMs: 30_000 })
|
|
909
|
+
```
|
|
910
|
+
|
|
911
|
+
On Node, keep the same `socket` field and replace `handle.close()` with
|
|
912
|
+
`handle.shutdown()`. Runtime-specific diagnostics move under `handle.runtime`;
|
|
913
|
+
do not use it as a second shutdown path. Standalone CLI/tools that create a
|
|
914
|
+
Socket.IO handle without an HTTP server call `await socket.close()`.
|
|
915
|
+
|
|
916
|
+
If Bun Socket.IO shares the port with a raw lane, keep the explicit composition
|
|
917
|
+
but let the server mount the Socket.IO route:
|
|
918
|
+
|
|
919
|
+
```ts
|
|
920
|
+
createServer({
|
|
921
|
+
services,
|
|
922
|
+
socket,
|
|
923
|
+
websocket: composeWebSocketHandlers([
|
|
924
|
+
webSocketLane({ match: isRaw, handlers: rawHandlers }),
|
|
925
|
+
socketIoLane(socket.websocket),
|
|
926
|
+
]),
|
|
927
|
+
rawRoutes: [rawUpgradeRoute],
|
|
928
|
+
})
|
|
929
|
+
```
|
|
930
|
+
|
|
931
|
+
Move native Bun `routes` entries to `rawRoutes`. Native routes run before the
|
|
932
|
+
Fetch handler and therefore cannot participate in admission or drain. Wire
|
|
933
|
+
`SIGTERM`/`SIGINT` in the application; the first signal starts `shutdown()`, and
|
|
934
|
+
a later signal may abort the same controller. Close MCP, databases and queues
|
|
935
|
+
after the server result—those resources remain application-owned.
|
|
936
|
+
|
|
937
|
+
Move a handshake policy from the Node-only callback shape inside
|
|
938
|
+
`serverOptions` to the runtime-neutral top-level policy. It receives a Web
|
|
939
|
+
`Request`, may be async, and returns whether to admit the handshake:
|
|
940
|
+
|
|
941
|
+
```ts
|
|
942
|
+
// before
|
|
943
|
+
serverOptions: { allowRequest: (request, done) => done(null, allowed(request)) }
|
|
944
|
+
|
|
945
|
+
// after
|
|
946
|
+
allowRequest: (request) => allowed(request)
|
|
947
|
+
```
|