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.
Files changed (429) hide show
  1. package/CHANGELOG.md +381 -12
  2. package/darwin-native.cjs +4 -2
  3. package/dist/agent-runtime/browser-control-contract.d.ts +32 -2
  4. package/dist/agent-runtime/browser-control-contract.d.ts.map +1 -1
  5. package/dist/agent-runtime/browser-controller.d.ts +21 -3
  6. package/dist/agent-runtime/browser-controller.d.ts.map +1 -1
  7. package/dist/agent-runtime/coding-shell-process.d.ts.map +1 -1
  8. package/dist/agent-runtime/coding-tool-refusals.d.ts +1 -0
  9. package/dist/agent-runtime/coding-tool-refusals.d.ts.map +1 -1
  10. package/dist/agent-runtime/coding-tool-shell.d.ts.map +1 -1
  11. package/dist/agent-runtime/compaction.d.ts.map +1 -1
  12. package/dist/agent-runtime/contained-write.d.ts.map +1 -1
  13. package/dist/agent-runtime/control-schema.d.ts +48 -1
  14. package/dist/agent-runtime/control-schema.d.ts.map +1 -1
  15. package/dist/agent-runtime/deferred-tool-search.d.ts +3 -2
  16. package/dist/agent-runtime/deferred-tool-search.d.ts.map +1 -1
  17. package/dist/agent-runtime/harness-control.d.ts.map +1 -1
  18. package/dist/agent-runtime/harness-realtime.d.ts +34 -4
  19. package/dist/agent-runtime/harness-realtime.d.ts.map +1 -1
  20. package/dist/agent-runtime/runtime-recovery.d.ts.map +1 -1
  21. package/dist/agent-runtime/runtime-state.d.ts.map +1 -1
  22. package/dist/agent-runtime/sandbox-contract.d.ts.map +1 -1
  23. package/dist/agent-runtime/sandbox-process-owner.d.ts +9 -1
  24. package/dist/agent-runtime/sandbox-process-owner.d.ts.map +1 -1
  25. package/dist/agent-runtime/sandbox.d.ts +32 -1
  26. package/dist/agent-runtime/sandbox.d.ts.map +1 -1
  27. package/dist/agent-runtime/schedule-records.d.ts.map +1 -1
  28. package/dist/agent-runtime/schedules.d.ts.map +1 -1
  29. package/dist/agent-runtime/store-events.d.ts +9 -4
  30. package/dist/agent-runtime/store-events.d.ts.map +1 -1
  31. package/dist/agent-runtime/testing.d.ts.map +1 -1
  32. package/dist/application/diagnostic-journal-contract.d.ts +50 -0
  33. package/dist/application/diagnostic-journal-contract.d.ts.map +1 -1
  34. package/dist/application/diagnostic-journal-generations.d.ts +24 -0
  35. package/dist/application/diagnostic-journal-generations.d.ts.map +1 -0
  36. package/dist/application/diagnostic-journal-manager.d.ts.map +1 -1
  37. package/dist/application/diagnostic-journal-open.d.ts +10 -0
  38. package/dist/application/diagnostic-journal-open.d.ts.map +1 -0
  39. package/dist/application/diagnostic-journal-quarantine.d.ts +28 -0
  40. package/dist/application/diagnostic-journal-quarantine.d.ts.map +1 -0
  41. package/dist/application/diagnostic-journal-read-contract.d.ts +73 -3
  42. package/dist/application/diagnostic-journal-read-contract.d.ts.map +1 -1
  43. package/dist/application/diagnostic-journal-reader.d.ts +17 -2
  44. package/dist/application/diagnostic-journal-reader.d.ts.map +1 -1
  45. package/dist/application/diagnostic-journal-recovery.d.ts +18 -2
  46. package/dist/application/diagnostic-journal-recovery.d.ts.map +1 -1
  47. package/dist/application/diagnostic-journal-storage.d.ts +6 -2
  48. package/dist/application/diagnostic-journal-storage.d.ts.map +1 -1
  49. package/dist/application/diagnostic-journal-tail.d.ts +12 -0
  50. package/dist/application/diagnostic-journal-tail.d.ts.map +1 -0
  51. package/dist/application/diagnostic-journal.d.ts +3 -0
  52. package/dist/application/diagnostic-journal.d.ts.map +1 -1
  53. package/dist/application/directory-inbox-accept.d.ts +3 -3
  54. package/dist/application/directory-inbox-accept.d.ts.map +1 -1
  55. package/dist/application/directory-inbox-contract.d.ts +38 -10
  56. package/dist/application/directory-inbox-contract.d.ts.map +1 -1
  57. package/dist/application/directory-inbox-delivery.d.ts +3 -3
  58. package/dist/application/directory-inbox-delivery.d.ts.map +1 -1
  59. package/dist/application/directory-inbox-files.d.ts +17 -2
  60. package/dist/application/directory-inbox-files.d.ts.map +1 -1
  61. package/dist/application/directory-inbox-state.d.ts +1 -1
  62. package/dist/application/directory-inbox-state.d.ts.map +1 -1
  63. package/dist/application/directory-inbox.d.ts +1 -1
  64. package/dist/application/directory-inbox.d.ts.map +1 -1
  65. package/dist/application/file-state-store.d.ts +21 -1
  66. package/dist/application/file-state-store.d.ts.map +1 -1
  67. package/dist/application/grammy.d.ts.map +1 -1
  68. package/dist/application/kernel-contract.d.ts.map +1 -1
  69. package/dist/application/revision-signal.d.ts.map +1 -1
  70. package/dist/application/state-store.d.ts +3 -0
  71. package/dist/application/state-store.d.ts.map +1 -1
  72. package/dist/browser/api-error.d.ts +38 -0
  73. package/dist/browser/api-error.d.ts.map +1 -0
  74. package/dist/browser/chunked-upload.d.ts.map +1 -1
  75. package/dist/browser/client-executors.d.ts.map +1 -1
  76. package/dist/browser/client-url.d.ts.map +1 -1
  77. package/dist/browser/contract-stream.d.ts.map +1 -1
  78. package/dist/browser/http.d.ts +0 -25
  79. package/dist/browser/http.d.ts.map +1 -1
  80. package/dist/browser/resumable.d.ts.map +1 -1
  81. package/dist/contract/define-validation.d.ts +0 -1
  82. package/dist/contract/define-validation.d.ts.map +1 -1
  83. package/dist/contract/define.d.ts.map +1 -1
  84. package/dist/contract/errors-factory.d.ts.map +1 -1
  85. package/dist/contract/errors.d.ts +15 -18
  86. package/dist/contract/errors.d.ts.map +1 -1
  87. package/dist/contract/normalize.d.ts.map +1 -1
  88. package/dist/durability/effect.d.ts.map +1 -1
  89. package/dist/durability/scheduler.d.ts.map +1 -1
  90. package/dist/entrypoints/agent-runtime/browser.js +29 -18
  91. package/dist/entrypoints/agent-runtime/coding-tools.js +8 -7
  92. package/dist/entrypoints/agent-runtime/harness.js +15 -14
  93. package/dist/entrypoints/agent-runtime/realtime.d.ts +1 -1
  94. package/dist/entrypoints/agent-runtime/realtime.d.ts.map +1 -1
  95. package/dist/entrypoints/agent-runtime/realtime.js +119 -54
  96. package/dist/entrypoints/agent-runtime/sandbox.js +23 -17
  97. package/dist/entrypoints/agent-runtime/sqlite/bun.js +4 -3
  98. package/dist/entrypoints/agent-runtime/sqlite/node.js +4 -3
  99. package/dist/entrypoints/agent-runtime/testing.js +8 -6
  100. package/dist/entrypoints/agent-runtime.js +37 -38
  101. package/dist/entrypoints/application/diagnostic-journal.js +305 -111
  102. package/dist/entrypoints/application/directory-inbox.js +174 -77
  103. package/dist/entrypoints/application/grammy.js +5 -2
  104. package/dist/entrypoints/application/opentelemetry.js +2 -2
  105. package/dist/entrypoints/application.d.ts +2 -2
  106. package/dist/entrypoints/application.d.ts.map +1 -1
  107. package/dist/entrypoints/application.js +17 -8
  108. package/dist/entrypoints/cli/publish.d.ts +16 -0
  109. package/dist/entrypoints/cli/publish.d.ts.map +1 -0
  110. package/dist/entrypoints/cli/publish.js +527 -0
  111. package/dist/entrypoints/cli.d.ts +1 -2
  112. package/dist/entrypoints/cli.d.ts.map +1 -1
  113. package/dist/entrypoints/cli.js +59 -966
  114. package/dist/entrypoints/contract.js +3 -3
  115. package/dist/entrypoints/files/packaging.js +196 -56
  116. package/dist/entrypoints/files.d.ts +1 -0
  117. package/dist/entrypoints/files.d.ts.map +1 -1
  118. package/dist/entrypoints/files.js +17 -10
  119. package/dist/entrypoints/index.d.ts +2 -1
  120. package/dist/entrypoints/index.d.ts.map +1 -1
  121. package/dist/entrypoints/index.js +31 -60
  122. package/dist/entrypoints/node.js +8 -8
  123. package/dist/entrypoints/observability.js +3 -3
  124. package/dist/entrypoints/primitives.js +67 -83
  125. package/dist/entrypoints/process.d.ts +1 -1
  126. package/dist/entrypoints/process.d.ts.map +1 -1
  127. package/dist/entrypoints/process.js +2 -2
  128. package/dist/entrypoints/react.js +4 -2
  129. package/dist/entrypoints/remote.js +37 -13
  130. package/dist/entrypoints/server.js +18 -16
  131. package/dist/entrypoints/telegram/screens.js +5 -3
  132. package/dist/entrypoints/telegram.js +31 -46
  133. package/dist/entrypoints/testing.d.ts +1 -1
  134. package/dist/entrypoints/testing.d.ts.map +1 -1
  135. package/dist/entrypoints/testing.js +444 -448
  136. package/dist/entrypoints/tools/connections.js +268 -105
  137. package/dist/entrypoints/tools/contract.js +2 -2
  138. package/dist/entrypoints/tools/invoker.js +8 -7
  139. package/dist/entrypoints/tools/mcp.d.ts +2 -2
  140. package/dist/entrypoints/tools/mcp.d.ts.map +1 -1
  141. package/dist/entrypoints/tools/mcp.js +10 -9
  142. package/dist/entrypoints/tools.d.ts +0 -1
  143. package/dist/entrypoints/tools.d.ts.map +1 -1
  144. package/dist/entrypoints/tools.js +118 -53
  145. package/dist/entrypoints/tracking.js +2 -3
  146. package/dist/files/boundary.d.ts +2 -2
  147. package/dist/files/boundary.d.ts.map +1 -1
  148. package/dist/files/chunk-spool.d.ts.map +1 -1
  149. package/dist/files/file-io.d.ts +2 -2
  150. package/dist/files/file-io.d.ts.map +1 -1
  151. package/dist/files/native-packaging-layout.d.ts +50 -4
  152. package/dist/files/native-packaging-layout.d.ts.map +1 -1
  153. package/dist/files/native-packaging.d.ts +104 -21
  154. package/dist/files/native-packaging.d.ts.map +1 -1
  155. package/dist/{index-r5hsgkz5.js → index-0gs4ymfj.js} +6 -3
  156. package/dist/{index-zax7resm.js → index-0gxvns6s.js} +1 -13
  157. package/dist/index-0s4xebbg.js +8 -0
  158. package/dist/{index-r4r70zmh.js → index-12zsej7b.js} +5 -2
  159. package/dist/{index-kemm0ej5.js → index-1pwwan01.js} +65 -22
  160. package/dist/{index-vgkbcnkc.js → index-299sm5tr.js} +1 -1
  161. package/dist/{index-2vnh05w4.js → index-2k91mewf.js} +31 -74
  162. package/dist/{index-269zqj8m.js → index-2rc6jd9n.js} +28 -12
  163. package/dist/{index-wh0ecvyk.js → index-37asdw3a.js} +1 -1
  164. package/dist/index-3h0ztg0z.js +285 -0
  165. package/dist/{index-g95fk660.js → index-4vsby8n8.js} +8 -15
  166. package/dist/index-556g5hsh.js +17 -0
  167. package/dist/{index-adhgd4pe.js → index-5p55xreg.js} +2 -2
  168. package/dist/index-5w6t91ze.js +47 -0
  169. package/dist/{index-9pw0a51a.js → index-6yxhe58g.js} +40 -7
  170. package/dist/{index-6d9xaxw1.js → index-8ks9b85e.js} +33 -5
  171. package/dist/{index-bhb950qs.js → index-916yh4e2.js} +25 -12
  172. package/dist/index-9tqbxv5p.js +44 -0
  173. package/dist/{index-5csmzesf.js → index-azx12jgv.js} +4 -3
  174. package/dist/{index-mbnnw3f2.js → index-b0kddvzw.js} +15 -5
  175. package/dist/{index-n5yqxd3d.js → index-b0w7rbpt.js} +23 -2
  176. package/dist/index-b56nnscm.js +132 -0
  177. package/dist/{index-0ndk4555.js → index-c0hffcmj.js} +2 -2
  178. package/dist/{index-pptyv13k.js → index-c17xcx4k.js} +42 -6
  179. package/dist/{index-g2j7pnak.js → index-cmzvhhtd.js} +5 -2
  180. package/dist/index-cq59agna.js +51 -0
  181. package/dist/{index-ssmd41kh.js → index-d2h99n7d.js} +1 -1
  182. package/dist/{index-z94wht4y.js → index-dky0dcmf.js} +34 -5
  183. package/dist/{index-za6j7nwy.js → index-dsnjzb62.js} +104 -51
  184. package/dist/index-eemvahkc.js +21 -0
  185. package/dist/index-ef8gdaq0.js +105 -0
  186. package/dist/{index-fa4wg312.js → index-f199nfq5.js} +10 -6
  187. package/dist/{index-ck71tbcf.js → index-fsw1ybf3.js} +11 -15
  188. package/dist/{index-f330qqyg.js → index-g2vfg7ak.js} +217 -63
  189. package/dist/{index-fk18k56k.js → index-gr5g3xfw.js} +11 -18
  190. package/dist/{index-jn9g8xdt.js → index-hjvje0pf.js} +6 -4
  191. package/dist/{index-x928baz2.js → index-j9gxbztg.js} +18 -14
  192. package/dist/index-kfjkb396.js +37 -0
  193. package/dist/{index-6drst9sg.js → index-ksfagmyz.js} +45 -345
  194. package/dist/index-m616f0yz.js +120 -0
  195. package/dist/{index-fm1c1a08.js → index-m6w6jtda.js} +40 -21
  196. package/dist/{index-ptn0g0gj.js → index-ma963wz7.js} +21 -20
  197. package/dist/{index-bakgedh8.js → index-msfpyy2f.js} +2 -4
  198. package/dist/{index-ywppsaby.js → index-n1nszyk0.js} +23 -34
  199. package/dist/{index-v14qqmys.js → index-n4689krb.js} +1 -1
  200. package/dist/{index-a0zzh8ak.js → index-pz3y6b6g.js} +3 -3
  201. package/dist/{index-43p08g7t.js → index-pzb63z66.js} +12 -8
  202. package/dist/{index-h97tqqp1.js → index-qaet40b2.js} +5 -3
  203. package/dist/{index-t1sr4aks.js → index-qaqbdm7s.js} +52 -6
  204. package/dist/{index-77nxk6ay.js → index-r393tnfp.js} +16 -10
  205. package/dist/{index-kb8styz3.js → index-rpzewktb.js} +15 -5
  206. package/dist/{index-27a2pj09.js → index-sj28htvf.js} +1 -1
  207. package/dist/index-szybbezc.js +455 -0
  208. package/dist/{index-2hyavjjj.js → index-wbhdzxar.js} +3 -3
  209. package/dist/{index-4e0ah203.js → index-wdy68sh6.js} +47 -24
  210. package/dist/{index-hbd32c6a.js → index-wqmvtnkp.js} +38 -89
  211. package/dist/{index-hp9d77wk.js → index-x7w1z6pf.js} +15 -4
  212. package/dist/{index-20yvtn9a.js → index-yt7gyg5x.js} +1 -1
  213. package/dist/{index-cvda079a.js → index-yvfk3y36.js} +12 -2
  214. package/dist/{index-5z6jn897.js → index-z23rfxhj.js} +1 -1
  215. package/dist/internal/abort-race.d.ts +8 -2
  216. package/dist/internal/abort-race.d.ts.map +1 -1
  217. package/dist/internal/atomic-file.d.ts +55 -9
  218. package/dist/internal/atomic-file.d.ts.map +1 -1
  219. package/dist/internal/atomic-publication.d.ts +39 -4
  220. package/dist/internal/atomic-publication.d.ts.map +1 -1
  221. package/dist/internal/atomic-staging.d.ts +46 -0
  222. package/dist/internal/atomic-staging.d.ts.map +1 -0
  223. package/dist/internal/bounded-file-read.d.ts +19 -11
  224. package/dist/internal/bounded-file-read.d.ts.map +1 -1
  225. package/dist/internal/bounded-lines.d.ts.map +1 -1
  226. package/dist/internal/close-after.d.ts +11 -0
  227. package/dist/internal/close-after.d.ts.map +1 -0
  228. package/dist/internal/deadline.d.ts +10 -0
  229. package/dist/internal/deadline.d.ts.map +1 -1
  230. package/dist/internal/exclusive-lock-read.d.ts +10 -12
  231. package/dist/internal/exclusive-lock-read.d.ts.map +1 -1
  232. package/dist/internal/exclusive-lock.d.ts +2 -2
  233. package/dist/internal/exclusive-lock.d.ts.map +1 -1
  234. package/dist/internal/file-observation.d.ts +14 -0
  235. package/dist/internal/file-observation.d.ts.map +1 -0
  236. package/dist/internal/json-data.d.ts +22 -5
  237. package/dist/internal/json-data.d.ts.map +1 -1
  238. package/dist/internal/positive-integer.d.ts +9 -0
  239. package/dist/internal/positive-integer.d.ts.map +1 -0
  240. package/dist/internal/process-instance.d.ts +35 -5
  241. package/dist/internal/process-instance.d.ts.map +1 -1
  242. package/dist/internal/secure-fetch.d.ts.map +1 -1
  243. package/dist/internal/timers.d.ts +11 -0
  244. package/dist/internal/timers.d.ts.map +1 -0
  245. package/dist/internal/with-exclusive-lock.d.ts +5 -4
  246. package/dist/internal/with-exclusive-lock.d.ts.map +1 -1
  247. package/dist/observability/bounded-sink.d.ts.map +1 -1
  248. package/dist/primitives/canonical-json.d.ts +23 -2
  249. package/dist/primitives/canonical-json.d.ts.map +1 -1
  250. package/dist/primitives/delivery.d.ts.map +1 -1
  251. package/dist/primitives/index.d.ts +1 -1
  252. package/dist/primitives/index.d.ts.map +1 -1
  253. package/dist/primitives/money.d.ts.map +1 -1
  254. package/dist/process/cleanup.d.ts +6 -1
  255. package/dist/process/cleanup.d.ts.map +1 -1
  256. package/dist/process/command-lifetime.d.ts +4 -0
  257. package/dist/process/command-lifetime.d.ts.map +1 -1
  258. package/dist/process/command-owner.d.ts.map +1 -1
  259. package/dist/process/command.d.ts +4 -0
  260. package/dist/process/command.d.ts.map +1 -1
  261. package/dist/process/contract.d.ts +67 -2
  262. package/dist/process/contract.d.ts.map +1 -1
  263. package/dist/process/group.d.ts +40 -3
  264. package/dist/process/group.d.ts.map +1 -1
  265. package/dist/process/launch.d.ts +12 -1
  266. package/dist/process/launch.d.ts.map +1 -1
  267. package/dist/process/terminate.d.ts +39 -0
  268. package/dist/process/terminate.d.ts.map +1 -0
  269. package/dist/react/query-client.d.ts.map +1 -1
  270. package/dist/realtime/rejection.d.ts.map +1 -1
  271. package/dist/server/contract-stream.d.ts.map +1 -1
  272. package/dist/server/handler-state.d.ts.map +1 -1
  273. package/dist/server/implement.d.ts.map +1 -1
  274. package/dist/server/request-body.d.ts +0 -1
  275. package/dist/server/request-body.d.ts.map +1 -1
  276. package/dist/server/unix-client.d.ts.map +1 -1
  277. package/dist/telegram/broadcast-delivery.d.ts.map +1 -1
  278. package/dist/telegram/broadcast-failure.d.ts +10 -2
  279. package/dist/telegram/broadcast-failure.d.ts.map +1 -1
  280. package/dist/telegram/operator-channel.d.ts.map +1 -1
  281. package/dist/telegram/screens/outcome.d.ts.map +1 -1
  282. package/dist/testing/surface-conformance.d.ts +1 -1
  283. package/dist/testing/surface-conformance.d.ts.map +1 -1
  284. package/dist/testing/surface-manifest.d.ts +0 -6
  285. package/dist/testing/surface-manifest.d.ts.map +1 -1
  286. package/dist/tools/agent.d.ts +1 -1
  287. package/dist/tools/agent.d.ts.map +1 -1
  288. package/dist/tools/cli/args.d.ts +1 -1
  289. package/dist/tools/cli/args.d.ts.map +1 -1
  290. package/dist/tools/cli/help.d.ts.map +1 -1
  291. package/dist/tools/cli/invoke.d.ts +2 -2
  292. package/dist/tools/cli/invoke.d.ts.map +1 -1
  293. package/dist/tools/cli/profile.d.ts.map +1 -1
  294. package/dist/tools/cli/publication-assets.d.ts.map +1 -1
  295. package/dist/tools/cli/publication-contract.d.ts +8 -0
  296. package/dist/tools/cli/publication-contract.d.ts.map +1 -1
  297. package/dist/tools/cli/publication-control.d.ts.map +1 -1
  298. package/dist/tools/cli/publication-storage.d.ts +23 -2
  299. package/dist/tools/cli/publication-storage.d.ts.map +1 -1
  300. package/dist/tools/cli/publication.d.ts +8 -1
  301. package/dist/tools/cli/publication.d.ts.map +1 -1
  302. package/dist/tools/connections/errors.d.ts +18 -6
  303. package/dist/tools/connections/errors.d.ts.map +1 -1
  304. package/dist/tools/connections/limits.d.ts +8 -2
  305. package/dist/tools/connections/limits.d.ts.map +1 -1
  306. package/dist/tools/connections/mcp-client.d.ts.map +1 -1
  307. package/dist/tools/connections/mcp-envelope.d.ts.map +1 -1
  308. package/dist/tools/connections/openapi.d.ts.map +1 -1
  309. package/dist/tools/connections/schema-budget.d.ts +1 -1
  310. package/dist/tools/connections/schema-budget.d.ts.map +1 -1
  311. package/dist/tools/connections/sse-session.d.ts.map +1 -1
  312. package/dist/tools/execute-args.d.ts.map +1 -1
  313. package/dist/tools/execute-result.d.ts.map +1 -1
  314. package/dist/tools/internal/surface-projector.d.ts +17 -3
  315. package/dist/tools/internal/surface-projector.d.ts.map +1 -1
  316. package/dist/tools/internal/tool-error-projection.d.ts +16 -0
  317. package/dist/tools/internal/tool-error-projection.d.ts.map +1 -0
  318. package/dist/tools/internal/tool-view.d.ts.map +1 -1
  319. package/dist/tools/invoker.d.ts.map +1 -1
  320. package/dist/tools/list-names.d.ts +3 -2
  321. package/dist/tools/list-names.d.ts.map +1 -1
  322. package/dist/tools/manifest.d.ts +3 -2
  323. package/dist/tools/manifest.d.ts.map +1 -1
  324. package/dist/tools/mcp/handler.d.ts +7 -0
  325. package/dist/tools/mcp/handler.d.ts.map +1 -1
  326. package/dist/tools/mcp/mount.d.ts +18 -2
  327. package/dist/tools/mcp/mount.d.ts.map +1 -1
  328. package/dist/tools/mcp/prepare.d.ts +3 -3
  329. package/dist/tools/mcp/prepare.d.ts.map +1 -1
  330. package/dist/tools/mcp/register.d.ts.map +1 -1
  331. package/dist/tools/mcp/runtime-tools.d.ts.map +1 -1
  332. package/dist/tools/mcp/stdio-signals.d.ts +14 -0
  333. package/dist/tools/mcp/stdio-signals.d.ts.map +1 -1
  334. package/dist/tools/mcp/stdio.d.ts +7 -0
  335. package/dist/tools/mcp/stdio.d.ts.map +1 -1
  336. package/dist/tools/operations/async-operation-runtime-tools.d.ts.map +1 -1
  337. package/dist/tools/operations/async-operation-runtime-types.d.ts +3 -3
  338. package/dist/tools/operations/async-operation-runtime-types.d.ts.map +1 -1
  339. package/dist/tools/operations/define-wait-tool.d.ts +1 -1
  340. package/dist/tools/operations/define-wait-tool.d.ts.map +1 -1
  341. package/dist/tools/operations/wait-core.d.ts +0 -6
  342. package/dist/tools/operations/wait-core.d.ts.map +1 -1
  343. package/dist/tools/registry.d.ts +1 -1
  344. package/dist/tools/registry.d.ts.map +1 -1
  345. package/dist/tools/remote.d.ts +1 -1
  346. package/dist/tools/remote.d.ts.map +1 -1
  347. package/dist/tools/{runtime-tool-execution.d.ts → runtime-tool-declaration.d.ts} +32 -9
  348. package/dist/tools/runtime-tool-declaration.d.ts.map +1 -0
  349. package/dist/tools/runtime-tool-mcp.d.ts +6 -15
  350. package/dist/tools/runtime-tool-mcp.d.ts.map +1 -1
  351. package/dist/tools/runtime-tool.d.ts +14 -12
  352. package/dist/tools/runtime-tool.d.ts.map +1 -1
  353. package/dist/tools/schema/coerce.d.ts +4 -0
  354. package/dist/tools/schema/coerce.d.ts.map +1 -1
  355. package/dist/tools/schema/flatten-join.d.ts.map +1 -1
  356. package/dist/tools/surface.d.ts +7 -11
  357. package/dist/tools/surface.d.ts.map +1 -1
  358. package/dist/tools/transfer/define-download-tool.d.ts +1 -1
  359. package/dist/tools/transfer/define-download-tool.d.ts.map +1 -1
  360. package/dist/tools/transfer/define-upload-tool.d.ts +1 -1
  361. package/dist/tools/transfer/define-upload-tool.d.ts.map +1 -1
  362. package/dist/tools/transfer/define-view-file-tool.d.ts +1 -1
  363. package/dist/tools/transfer/define-view-file-tool.d.ts.map +1 -1
  364. package/dist/tools/transfer/managed-file-error.d.ts.map +1 -1
  365. package/dist/tools/transfer/view-file-contract.d.ts.map +1 -1
  366. package/dist/tools/transfer/view-file.d.ts +1 -1
  367. package/dist/tools/transfer/view-file.d.ts.map +1 -1
  368. package/dist/tools/transports.d.ts +3 -2
  369. package/dist/tools/transports.d.ts.map +1 -1
  370. package/llms/agent-runtime-browser.txt +10 -4
  371. package/llms/agent-runtime-harness.txt +32 -31
  372. package/llms/agent-runtime-react.txt +1 -1
  373. package/llms/agent-runtime-realtime.txt +14 -5
  374. package/llms/agent-runtime-sandbox.txt +3 -11
  375. package/llms/agent-runtime.3.txt +2 -2
  376. package/llms/agent-runtime.txt +0 -9
  377. package/llms/application.2.txt +3 -12
  378. package/llms/application.3.txt +7 -4
  379. package/llms/application.txt +44 -15
  380. package/llms/cli-publish.txt +29 -0
  381. package/llms/cli.2.txt +9 -11
  382. package/llms/cli.txt +26 -14
  383. package/llms/declaration.txt +0 -9
  384. package/llms/files-packaging.txt +22 -7
  385. package/llms/files.txt +4 -2
  386. package/llms/geo.txt +0 -9
  387. package/llms/live.txt +4 -13
  388. package/llms/observability.txt +31 -5
  389. package/llms/primitives.txt +38 -20
  390. package/llms/process.txt +305 -154
  391. package/llms/react-keyboard.txt +0 -9
  392. package/llms/react.txt +0 -18
  393. package/llms/server.4.txt +1 -1
  394. package/llms/server.5.txt +1 -1
  395. package/llms/server.txt +1 -1
  396. package/llms/stitchkit.txt +6 -7
  397. package/llms/telegram-screens.txt +2 -2
  398. package/llms/testing.txt +0 -1
  399. package/llms/tools-mcp.txt +2 -3
  400. package/llms/tools.2.txt +12 -0
  401. package/llms/tools.3.txt +5 -6
  402. package/llms/tools.txt +6 -4
  403. package/llms/upgrading-0.37.0-0.50.0.txt +947 -0
  404. package/llms/{upgrading-0.44.0-0.61.0.txt → upgrading-0.53.0-0.67.0.txt} +576 -506
  405. package/llms/{upgrading-0.62.0-0.80.0.txt → upgrading-0.68.0-0.94.0.txt} +562 -576
  406. package/llms/{upgrading-0.81.0-0.104.0.txt → upgrading-0.95.0-0.105.0.txt} +452 -567
  407. package/llms/upgrading.txt +4 -4
  408. package/llms-full.txt +1053 -405
  409. package/llms.txt +24 -24
  410. package/native-assets.json +11 -3
  411. package/package.json +6 -6
  412. package/dist/agent-runtime/harness-tools.d.ts +0 -11
  413. package/dist/agent-runtime/harness-tools.d.ts.map +0 -1
  414. package/dist/entrypoints/agent-runtime/harness-tools.d.ts +0 -2
  415. package/dist/entrypoints/agent-runtime/harness-tools.d.ts.map +0 -1
  416. package/dist/entrypoints/agent-runtime/harness-tools.js +0 -32
  417. package/dist/index-1a6jtnd9.js +0 -88
  418. package/dist/index-8a9ksm91.js +0 -95
  419. package/dist/index-a3wma1hk.js +0 -48
  420. package/dist/index-jd470k6q.js +0 -109
  421. package/dist/index-n1dqr7gf.js +0 -20
  422. package/dist/index-nggfa2yn.js +0 -34
  423. package/dist/index-s4evrmp5.js +0 -98
  424. package/dist/index-ze1eph1k.js +0 -20
  425. package/dist/tools/connections/error-projection.d.ts +0 -4
  426. package/dist/tools/connections/error-projection.d.ts.map +0 -1
  427. package/dist/tools/runtime-tool-execution.d.ts.map +0 -1
  428. package/llms/agent-runtime-harness-tools.txt +0 -25
  429. package/llms/upgrading-0.37.0-0.44.0.txt +0 -444
@@ -1,14 +1,587 @@
1
- # Upgrading 0.44.0 → 0.61.0 — stitchkit docs slice
1
+ # Upgrading 0.53.0 → 0.67.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.44.0 → 0.61.0 (docs/guide/upgrading.md)
6
+ Contains: Guide: Upgrading, 0.53.0 → 0.67.0 (docs/guide/upgrading.md)
7
7
 
8
8
  ==============================================================================
9
- # Guide: Upgrading, 0.44.0 → 0.61.0 (docs/guide/upgrading.md)
9
+ # Guide: Upgrading, 0.53.0 → 0.67.0 (docs/guide/upgrading.md)
10
10
  ==============================================================================
11
11
 
12
+ ## Released migration: 0.67.0
13
+
14
+ Three application-kernel changes. Two of them fix silent failures, so the most
15
+ important part of this migration is not what the compiler points at — it is the
16
+ two things that change with no compile error at all: **when your server is
17
+ created**, and **which shutdown budget a signal spends**.
18
+
19
+ ### If you gave `managedServerResource` a thunk
20
+
21
+ It is now called during `start`, after the resource's dependencies are ready —
22
+ the reading the type always suggested. Before, it was called on the way *down*,
23
+ so `app.start()` resolved, the snapshot said `healthy` and `ready`, and nothing
24
+ was bound to the port.
25
+
26
+ If your application looked like this, it was never listening:
27
+
28
+ ```ts
29
+ // before — resolves clean, listens on nothing
30
+ managedServerResource({ id: 'http', dependsOn: ['database'], server: () => createServer(config) })
31
+ ```
32
+
33
+ Nothing to change: the same code now binds the port. Check your startup logs for
34
+ a healthy report you never actually verified with a request.
35
+
36
+ If you used the spread workaround — this resource's phases over your own
37
+ `start` — it keeps working, and you can now delete it:
38
+
39
+ ```ts
40
+ // before
41
+ let handle: ManagedServerHandle<T> | null = null
42
+ const shutdown = managedServerResource({ id: 'http', server: () => handle! })
43
+ const http = defineManagedResource({
44
+ ...shutdown,
45
+ dependsOn: ['database', 'socket-io'],
46
+ start: () => { handle = createServer(config) },
47
+ })
48
+
49
+ // after
50
+ const http = managedServerResource({
51
+ id: 'http',
52
+ dependsOn: [database, socketIo],
53
+ server: () => createServer(config),
54
+ })
55
+ ```
56
+
57
+ An already-created handle is adopted exactly as before.
58
+
59
+ ### If you passed `shutdown` to `bindProcessSignals`
60
+
61
+ `bindProcessSignals` used to fill in the schema's defaults for every budget you
62
+ omitted, which made `createApplication({ shutdown })` unreachable on the signal
63
+ path — the one path production stops through. An application declaring five
64
+ seconds took thirty-five.
65
+
66
+ Declare the budget once, on the application, and delete the repetition:
67
+
68
+ ```ts
69
+ // before — the same two numbers in two places, and only one of them applied
70
+ const app = createApplication({ id: 'svc', resources, shutdown: SHUTDOWN_BUDGET })
71
+ bindProcessSignals(app, { shutdown: SHUTDOWN_BUDGET })
72
+
73
+ // after
74
+ const app = createApplication({ id: 'svc', resources, shutdown: SHUTDOWN_BUDGET })
75
+ bindProcessSignals(app)
76
+ ```
77
+
78
+ **Check this even if you change nothing.** If you declared a budget on the
79
+ application and did not repeat it on the binding, your process has been stopping
80
+ on 30 s / 5 s and will now stop on what you declared. Compare it against the
81
+ supervisor timeout that watches it — `kill_timeout`, `TimeoutStopSec` — because
82
+ that number was probably calculated from the declaration.
83
+
84
+ Passing `shutdown` to the binding still works and still wins, key by key: one
85
+ key overrides that key alone and leaves the other at the declaration.
86
+
87
+ ### If you read `resource.dependsOn`
88
+
89
+ Its type widened from `readonly string[]` to `readonly ManagedResourceDependency[]`
90
+ — `string | ManagedResource` — so a dependency can be declared as the resource
91
+ itself. Declaring stays compatible; reading needs one call:
92
+
93
+ ```ts
94
+ // before
95
+ const ids: readonly string[] = resource.dependsOn ?? []
96
+
97
+ // after
98
+ import { managedResourceDependencyId } from 'stitchkit/application'
99
+ const ids = (resource.dependsOn ?? []).map(managedResourceDependencyId)
100
+ ```
101
+
102
+ ### If you thread a handle through a module-local
103
+
104
+ This is the pattern the change exists to remove, and it is opt-in — nothing
105
+ breaks if you keep yours:
106
+
107
+ ```ts
108
+ // before
109
+ let socket: SocketHandle | null = null
110
+ const socketIo = defineManagedResource({
111
+ id: 'socket-io',
112
+ start: async () => { socket = await createSocketServer(config) },
113
+ })
114
+ const http = defineManagedResource({
115
+ id: 'http',
116
+ dependsOn: ['socket-io'],
117
+ start: () => {
118
+ if (!socket) throw new Error('socket is not initialized') // unreachable
119
+ server = createServer({ socket })
120
+ },
121
+ })
122
+
123
+ // after
124
+ const socketIo = defineManagedResource({
125
+ id: 'socket-io',
126
+ start: async () => ({ value: await createSocketServer(config) }),
127
+ })
128
+ const http = defineManagedResource({
129
+ id: 'http',
130
+ dependsOn: [socketIo],
131
+ start: (context) => {
132
+ server = createServer({ socket: context.use(socketIo) }) // SocketHandle
133
+ },
134
+ })
135
+ ```
136
+
137
+ Declare the dependency with the **resource** when you intend to read from it —
138
+ that is the form `use` can type. `use` refuses a resource missing from
139
+ `dependsOn`, and refuses one that published no value; the second refusal is a
140
+ compile error too.
141
+
142
+ ## Released migration: 0.66.0
143
+
144
+ Three changes, and only one of them is a feature. The other two are shapes that
145
+ would have had to break later: a vocabulary that described one fact with two
146
+ words, and a store whose only read was the whole conversation.
147
+
148
+ The compiler points at most of it. Two things change with no compile error —
149
+ what a **total** says about its own provenance, and the fact that token counts
150
+ are now validated where they were not.
151
+
152
+ ### An input that joins a run in flight
153
+
154
+ #### If you matched exhaustively on `AgentTerminalReason`
155
+
156
+ `'absorbed'` is new. A run ends this way when a run already in flight took its
157
+ input on and answered it; its state is `'superseded'`, and `absorbedIntoRunId`
158
+ names the run that has the answer.
159
+
160
+ ```ts
161
+ // after
162
+ switch (run.terminalReason) {
163
+ // …
164
+ case 'absorbed':
165
+ // no assistant message of its own — follow run.absorbedIntoRunId
166
+ break
167
+ }
168
+ ```
169
+
170
+ A run record with `terminalReason: 'absorbed'` and no `absorbedIntoRunId` is
171
+ refused at parse time, and so is `absorbedIntoRunId` on any other reason.
172
+
173
+ #### If you render or export runs
174
+
175
+ An absorbed run has **no assistant message**. Anything that assumes "every
176
+ terminal run has one" needs the `absorbed` case — the answer is on the run
177
+ `absorbedIntoRunId` names, and `store.loadRun` resolves it.
178
+
179
+ #### If you want the policy
180
+
181
+ ```ts
182
+ // after
183
+ runs: { inputPolicy: 'inject' }
184
+ ```
185
+
186
+ It was withdrawn in 0.65.0 and is back with the ordering corrected: the
187
+ absorption commits with the terminal record, not at the step boundary. Read
188
+ *An input that joins a run in flight* in the agent-runtime guide before turning
189
+ it on — in particular what happens when the absorbing run does not complete, and
190
+ how it composes with `coalescePending`.
191
+
192
+ #### If you implement a store driver
193
+
194
+ Nothing to do, but know what changed underneath: one terminal commit can now
195
+ save **two** run records, and they must land in the same transaction. A driver
196
+ that persists one of the pair fails `runAgentStoreConformance`.
197
+
198
+ ### A run read without its conversation
199
+
200
+ #### If you implement `AgentRuntimeStore` by hand
201
+
202
+ Two members to add. **If your adapter is an `AgentRuntimeStoreDriver` passed to
203
+ `createAgentRuntimeStore`, there is nothing to do** — the driver already had
204
+ everything both need.
205
+
206
+ ```ts
207
+ // after
208
+ loadRun(input: { conversationId: string; runId: string }): Promise<AgentRunView | undefined>
209
+ listActiveRuns(conversationId: string): Promise<readonly AgentRun[]>
210
+ ```
211
+
212
+ `AgentRunView` is `{ snapshotVersion, run, assistant? }`. `assistant` is the
213
+ retained terminal answer, so it is present exactly when the run has ended and
214
+ absent while it is live — a store that returns a live run's draft here lets the
215
+ terminal path resolve a run that has not finished. `listActiveRuns` orders by
216
+ `createdAt` then `id`, and must not report a run that has ended.
217
+ `runAgentStoreConformance` covers both, including the boundary cases.
218
+
219
+ #### If you have a store **double** in your tests
220
+
221
+ The runtime now reads `loadRun` where it used to read `loadSnapshot`. A double
222
+ that simulates a condition — a run drifting to another owner, a stale fencing
223
+ token — must apply it to both reads, or the code under test will not see it.
224
+ This is not hypothetical: it turned one of this repository's own fixtures into
225
+ an infinite retry loop, which is how the bounded retry below was found.
226
+
227
+ #### Nothing else changes
228
+
229
+ `loadSnapshot` behaves exactly as before, and still returns the whole
230
+ conversation — as does every mutation result. What it costs, and what bounds it,
231
+ is now written down in *Reading a conversation* in the agent-runtime guide.
232
+
233
+ ### One provenance vocabulary, and integral tokens
234
+
235
+ #### If you match on `'measured'`
236
+
237
+ A **total** now says `computed`, because it is a sum this code performed rather
238
+ than a count it took — the same rule `AgentUsage` has always applied to a run's
239
+ spend. Two values change with no compile error:
240
+
241
+ ```ts
242
+ // before
243
+ if (result.totalTokens.provenance === 'measured') { /* exact */ }
244
+ // after
245
+ if (result.totalTokens.provenance === 'computed') { /* exact, and derived */ }
246
+ ```
247
+
248
+ It affects `AgentHistoryBudgetResult.totalTokens` and
249
+ `ComposedAgentPrompt.instructionTokens`. A per-message or per-section count is
250
+ still `measured` — only the totals moved. When any part was estimated the total
251
+ is still `estimated`: an estimate survives arithmetic, and that is the weaker
252
+ claim, so it wins.
253
+
254
+ #### If you produce token counts
255
+
256
+ They are validated now, in the places they were not. A fractional count throws
257
+ where it used to flow into the context-window arithmetic:
258
+
259
+ ```ts
260
+ // refused from this release on
261
+ estimateTokens: (text) => ({ value: text.length / 4, provenance: 'estimated' })
262
+ // after
263
+ estimateTokens: (text) => ({ value: Math.ceil(text.length / 4), provenance: 'estimated' })
264
+ ```
265
+
266
+ The same applies to `ComposeAgentPromptOptions.estimateFallback` and
267
+ `.historyTokens`, to `AgentPromptBudget.toolSchemas` / `.attachments` /
268
+ `.providerOverhead`, and to `AgentPromptBudget.contextWindow` /
269
+ `.reservedOutput`, which must now be non-negative safe integers.
270
+
271
+ `AgentUsageValue.value` is `z.int()` too, which matters if you build usage
272
+ records by hand or in a store double. A figure arriving from a **provider** is
273
+ not thrown — `normalizeSdkUsage` and the OpenRouter adapter turn a non-integer
274
+ into `{ provenance: 'unavailable' }`, so a run that already answered is not
275
+ failed over its own bookkeeping.
276
+
277
+ #### The new export
278
+
279
+ `AgentProvenanceSchema` / `AgentProvenance` is the whole vocabulary:
280
+ `provider-reported`, `measured`, `computed`, `estimated`, `unavailable`. Each
281
+ surface declares its subset, so nothing widened — `AgentUsageValue` still refuses
282
+ `measured` and `AgentTokenCount` still refuses `provider-reported`. Use it when
283
+ you want one switch over the question instead of two.
284
+
285
+ ## Released migration: 0.65.0
286
+
287
+ The largest migration of the pre-1.0 line, and most of it is the compiler
288
+ pointing at things. One item is a feature withdrawal and two change behaviour
289
+ with no compile error at all.
290
+
291
+ ### A projection a provider accepts, and a policy withdrawn
292
+
293
+ ### If you compact, or use `system-note`, you were broken and now are not
294
+
295
+ No code change to adopt the fix — but **check your own code if you call
296
+ `projectAgentHistory` yourself.** System and summary records no longer appear in
297
+ `messages`; they come back in `system` and belong in the provider's instructions
298
+ channel, which is the only place `ai` accepts them:
299
+
300
+ ```ts
301
+ // before — the provider refuses this outright
302
+ const messages = await projectAgentHistory(snapshot.messages)
303
+ streamText({ model, messages })
304
+
305
+ // after
306
+ const { messages, system } = await projectAgentHistoryDetailed(snapshot.messages)
307
+ streamText({
308
+ model,
309
+ instructions: system.map((content) => ({ role: 'system', content })),
310
+ messages,
311
+ })
312
+ ```
313
+
314
+ If you use `createAgentRuntime`, this is handled for you.
315
+
316
+ ### `inputPolicy: 'inject'` is withdrawn
317
+
318
+ ```ts
319
+ // before
320
+ runs: { inputPolicy: 'inject' }
321
+ // after
322
+ runs: { inputPolicy: 'queue' }
323
+ ```
324
+
325
+ `'absorbed'`, `AgentRun.absorbedIntoRunId` and `AgentRuntimeStore.absorbQueuedRun`
326
+ go with it. A driver built on `AgentRuntimeStoreDriver` needs no change.
327
+
328
+ ### Records must agree with themselves
329
+
330
+ If you construct `AgentRun` values — a store double, a fixture, a migration —
331
+ derive the state instead of setting it:
332
+
333
+ ```ts
334
+ // after
335
+ import { runStateForTerminalReason } from 'stitchkit/agent-runtime'
336
+ AgentRunSchema.parse({ …run, terminalReason: reason, state: runStateForTerminalReason(reason) })
337
+ ```
338
+
339
+ A terminal state with no reason, a queued run carrying one, and `policy_stop`
340
+ without a `terminalPolicyName` are now all refused at parse time.
341
+
342
+ ### Enum and field changes the compiler will point at
343
+
344
+ - `AgentTerminalReason`: `'tool_failure'` removed (never produced),
345
+ `'context_overflow'` added — this runtime's own refusal when the prompt does
346
+ not fit, which used to report `provider_failure`.
347
+ - `AgentRunState`: `'absorbed'` removed.
348
+ - `AgentRunMetrics.usage` is required.
349
+ - `AgentHistoryBudgetDecision['reason']`: `'superseded'` → `'unspeakable'`.
350
+
351
+ ### Two behaviour changes with no compile error
352
+
353
+ - **`loop.idleTimeoutMs` now defaults to 60 000.** A run whose provider stream
354
+ goes quiet for a minute ends as `timeout` instead of holding the lane forever.
355
+ Pass `null` for the old behaviour, and think about why you want it.
356
+ - **`advanceAgentRuntimeEventCursor` stops returning `gap` for durable events.**
357
+ If you reload a conversation on `gap`, you were reloading after essentially
358
+ every run. Transient events still report it, and there it is real.
359
+
360
+ ## Released migration: 0.64.0
361
+
362
+ Two changes, and only one of them can break a build. Nothing was removed.
363
+
364
+ ### An event that says which kind it is
365
+
366
+ ### Narrow `AgentRunEvent` on `type`
367
+
368
+ ```ts
369
+ // before
370
+ for (const event of events) record(event.usage?.cost?.value ?? 0)
371
+
372
+ // after — and the compiler will point at every site
373
+ for (const event of events) {
374
+ if (event.type !== 'run-terminal') continue
375
+ record(event.usage.cost.value ?? null) // `usage` is present; unknown says so
376
+ }
377
+ ```
378
+
379
+ `step` is now required on `step-finished`, `terminalReason` on `run-terminal`,
380
+ and `usage` on both. `queueWaitMs` exists only on `run-started`. Nothing was
381
+ removed — the fields that were optional because a *different* kind of event
382
+ lacked them are now simply on the kinds that have them.
383
+
384
+ Import `AgentRunTerminalEventSchema` (or the sibling schemas) if you construct
385
+ events in tests.
386
+
387
+ ### If you implement `AgentRuntimeStore` directly, move to the driver
388
+
389
+ Not urgent and nothing breaks today — but the aggregate is no longer the
390
+ supported target, so its future growth will not be announced as breaking
391
+ (→ ADR 0111). The supported shape is one line:
392
+
393
+ ```ts
394
+ const driver: AgentRuntimeStoreDriver<TransactionClient> = { /* six primitives */ }
395
+ export const store = createAgentRuntimeStore(driver)
396
+ ```
397
+
398
+ Run `runAgentStoreConformance` against your adapter before and after any bump —
399
+ see *Before you bump, if you implement an agent store* above.
400
+
401
+ ## Released migration: 0.63.0
402
+
403
+ Four changes to what a running system reports and how an input reaches a run
404
+ in flight. Nothing moves an export except one added store member, and only an
405
+ application implementing `AgentRuntimeStore` directly has to touch code.
406
+
407
+ ### A spend figure that survives, and an input that joins
408
+
409
+ ### `AgentRuntimeStore` has a ninth member
410
+
411
+ Only if you implement the aggregate interface directly — an adapter built on
412
+ `AgentRuntimeStoreDriver` needs no change, and the public conformance kit covers
413
+ the new operation.
414
+
415
+ ```ts
416
+ // after
417
+ absorbQueuedRun(input: AbsorbQueuedRun): Promise<AgentStoreMutationResult>
418
+ ```
419
+
420
+ It moves a queued successor's inputs into the run already answering, in one
421
+ mutation, and marks the successor `absorbed`. Two run records change in one
422
+ transaction — if your driver persists them one at a time, persist both.
423
+
424
+ ### A provider failure says so
425
+
426
+ ```ts
427
+ // before — an upstream error arrived as a policy stop with no policy
428
+ if (terminal.reason === 'policy_stop') retryLater()
429
+
430
+ // after
431
+ if (terminal.reason === 'provider_failure') retryLater()
432
+ if (terminal.reason === 'provider_stop') { /* a length cap or content filter */ }
433
+ ```
434
+
435
+ `policy_stop` now always carries the `policyName` that caused it. If you switch
436
+ exhaustively on `AgentTerminalReason` or `AgentRunState`, add `'provider_stop'`
437
+ and `'absorbed'`.
438
+
439
+ ### `partial` changed meaning
440
+
441
+ It used to tell you which event kind you were holding. It now tells you whether
442
+ the figure beside it is a confirmed total:
443
+
444
+ ```ts
445
+ // after — true when the provider never reported the run finished
446
+ if (metrics.partial) treatAsFloor(metrics.usage)
447
+ ```
448
+
449
+ Terminal events for runs that were superseded, interrupted, timed out or failed
450
+ before the provider finished now report `partial: true` where they reported
451
+ `false`.
452
+
453
+ ### Checkpoint metrics are a running total
454
+
455
+ ```ts
456
+ // wrong, and now wrong by more than it used to be
457
+ const spent = checkpoints.reduce((total, c) => total + (c.metrics.usage?.cost?.value ?? 0), 0)
458
+ // right
459
+ const spent = checkpoints.at(-1)?.metrics.usage?.cost?.value
460
+ ```
461
+
462
+ ### You can read a run's spend back from the store
463
+
464
+ `AgentRun.usage` is written at every checkpoint and with the terminal record, so
465
+ a dropped observability event no longer loses the number, and a process that dies
466
+ mid-stream leaves behind what it had already spent.
467
+
468
+ ## Released migration: 0.62.0
469
+
470
+ Two groups of behaviour changes. Nothing moves an export — the surface is
471
+ strictly additive — and every item changes what a running system reports or
472
+ sends, which is what this heading is for. One of them changes a number you may
473
+ already be billing against.
474
+
475
+ ### A run reports what it spent
476
+
477
+ Three changes to what the runtime says about cost and tokens. Nothing moves an
478
+ export; all three change numbers a running system reports, and one of them
479
+ changes a number you may already be billing against.
480
+
481
+ #### Multi-step cost was under-reported and is now summed
482
+
483
+ No code change is needed to get the fix — but check any predicate that reads
484
+ `provenance`:
485
+
486
+ ```ts
487
+ // before — accepted a number that was one step's cost, not the run's
488
+ if (usage.cost?.provenance === 'provider-reported') bill(usage.cost.value)
489
+
490
+ // after — a sum stitchkit performed says so
491
+ if (usage.cost && usage.cost.provenance !== 'unavailable') bill(usage.cost.value)
492
+ ```
493
+
494
+ `'computed'` means stitchkit added up provider-reported parts. It is not a guess
495
+ — `'estimated'` is the word for that — but it is deliberately not
496
+ `'provider-reported'`, because that label is what a caller filters on when it
497
+ wants a figure it can bill against unchanged, and a sum is not one.
498
+
499
+ Token totals moved with it. The AI SDK's `totalUsage` is a sum *it* performed
500
+ over per-step provider figures — not a run total any provider handed over — so
501
+ labelling it `provider-reported` was the same overstatement. **A run total on a
502
+ terminal event is always `computed`.** If you want a figure with the provider's
503
+ own word on it, read `step-finished`: each step carries what that call reported.
504
+
505
+ #### `usage` is always present on a terminal event
506
+
507
+ ```ts
508
+ // before — absent when the run ended before the provider's `finish`
509
+ const spent = event.usage?.cost?.value ?? 0 // silently 0 for a real spend
510
+
511
+ // after — present, and it says what it does not know
512
+ event.usage?.cost?.provenance === 'unavailable' // we spent, and cannot say how much
513
+ ```
514
+
515
+ Keep the optional chaining: one `AgentRunEvent` shape covers `run-started`,
516
+ `step-finished` and `run-terminal`, so `usage` stays optional on the type. The
517
+ guarantee is about terminal events, and a schema shared with `run-started`
518
+ cannot express it.
519
+
520
+ **Do not read `unavailable` as zero.** A run aborted mid-stream has spent real
521
+ money that nobody has counted; a run that never reached the provider has not.
522
+ Both used to look the same and now do not.
523
+
524
+ #### A losing executor reports its own spend
525
+
526
+ An execution that loses the terminal compare-and-swap now emits an operator
527
+ `run-terminal` event, because it ran and it spent. If a sink treated those events
528
+ as "runs this process committed", that is no longer true — `AgentRuntimeResult.metrics`
529
+ is still `undefined` for a losing executor and remains the way to tell.
530
+
531
+ The *delivery* `terminal` event is unchanged and still fires only for the winner,
532
+ so nothing delivers a turn twice.
533
+
534
+ ### An interrupted answer stops passing as a finished one
535
+
536
+ Two behaviour changes, one shared cause: a run ended by a newer input used to
537
+ leave its half-written answer in the conversation with no sign that it was cut
538
+ off, and the next request to the provider carried it as an ordinary assistant
539
+ turn.
540
+
541
+ #### The projection marks an interrupted turn
542
+
543
+ Nothing to change to adopt the fix — the default is the fixed behaviour. What to
544
+ check is whether the marker is the *right* form for your surface, and the
545
+ question that decides it is not "was the run interrupted" but **"did anyone see
546
+ what it produced"**.
547
+
548
+ ```ts
549
+ // after — pick the form; the default is 'assistant-marked'
550
+ createAgentRuntime({ history: { interruptedAssistant: 'system-note' } })
551
+ ```
552
+
553
+ - **The user pressed stop and the text was on their screen** — keep
554
+ `'assistant-marked'`. The assistant turn is the truthful record of what the
555
+ human read, and the model should stay consistent with it.
556
+ - **The partial never reached anyone** — a surface that sends nothing until the
557
+ run is done — prefer `'system-note'`. An assistant turn in provider history is
558
+ a commitment the model stays consistent with; a system line is context.
559
+
560
+ If you pass `history.project` you own the projection outright and none of this
561
+ applies — but the same question does.
562
+
563
+ #### A run ended by a newer input can now say so
564
+
565
+ ```ts
566
+ // before
567
+ runs: { inputPolicy: 'interrupt' } // ends the run, keeps its partial answer
568
+
569
+ // after — for a surface where a follow-up message invalidates the answer
570
+ // in flight rather than merely stopping it
571
+ runs: { inputPolicy: 'supersede' } // ends the run, discards its partial answer
572
+ ```
573
+
574
+ `inputPolicy` also accepts `(input) => policy`, which is how one application
575
+ gives two conversation surfaces different rules without the runtime learning
576
+ which is which.
577
+
578
+ A superseded run terminates with `terminalReason: 'superseded'`, state
579
+ `'superseded'` and an assistant message of status `'superseded'`. **If you switch
580
+ exhaustively on any of those enums, add the arm** — that is the part of this
581
+ release that can break a build rather than a behaviour. The record itself is
582
+ kept: it is excluded from the projection, not deleted, so an operator can still
583
+ see what was thrown away.
584
+
12
585
  ## Released migration: 0.61.0
13
586
 
14
587
  Three behaviour changes between versions. None moves an export — the surface is
@@ -599,506 +1172,3 @@ const mock: Pick<RealtimeClient<S, C>, 'emit'> = { emit: () => true }
599
1172
  While migrating, consider replacing hand-rolled `if (client.connected)` guards
600
1173
  with the new honest surface: check `client.emit(...) === false`, or observe
601
1174
  drops centrally with `onDroppedEmit`.
602
-
603
- ## Released migration: 0.50.0
604
-
605
- ### The factory's scope union now covers per-endpoint overrides
606
-
607
- `createContractFactory<Scope>()` already required a typed `scope` on the
608
- contract. It now holds a per-endpoint `scope` override to the same union. Nothing
609
- to migrate unless an override is outside the union — which was always a bug: the
610
- scope reached no auth rule, and `createAuthHook` threw
611
- `[stitchkit] auth: no rule for scope "…"` on the first request to it.
612
-
613
- ```ts
614
- const { defineContract } = createContractFactory<'public' | 'user' | 'admin'>()
615
-
616
- defineContract({ prefix: 'posts', scope: 'user' }, {
617
- // before: compiled; failed at request time
618
- // after: compile error naming the scope (TypeScript even suggests 'admin')
619
- purge: { method: 'DELETE', path: '/all', desc: 'Purge', scope: 'admn', output },
620
- })
621
- ```
622
-
623
- Fix the typo, or widen the factory union if the scope is real. Contracts built
624
- with plain `defineContract` are unaffected.
625
-
626
- ### A declared `defineErrors` message is now used
627
-
628
- `ErrorDefinition` accepts `message`. Nothing to migrate unless a registry already
629
- wrote that key: it type-checked before (excess-property checking does not fire
630
- through a `const` generic) and was ignored, so the code itself went on the wire.
631
-
632
- ```ts
633
- const { errors } = defineErrors({ GONE: { status: 410, message: 'Long gone' } })
634
- // before: errors.GONE().message === 'GONE'
635
- // after: errors.GONE().message === 'Long gone'
636
- ```
637
-
638
- If a registry carried `message` as a note to the reader rather than as
639
- user-facing text, either fix the text or drop the key. A code with no `details`
640
- schema also shows that text to a model (its tool `details` is `{ message }`).
641
-
642
- ### Optional: adopt `createScopedImplement`
643
-
644
- If the app declares one superset handler context because different scopes inject
645
- different fields, replace it with a scope map. This is additive — `createImplement`
646
- still works.
647
-
648
- ```ts
649
- // before — one context for every scope; `ctx.userId` is typed even in a
650
- // `public` handler, where the runtime never injects it
651
- interface AppContext extends RuntimeContext { userId: string; isAdmin: boolean }
652
- export const implement = createImplement<AppContext>()
653
-
654
- // after — each handler typed by its endpoint's effective scope
655
- export const implementFor = createScopedImplement<{
656
- public: object
657
- user: { userId: string }
658
- admin: { userId: string; isAdmin: boolean }
659
- }>()
660
- ```
661
-
662
- `'public'` must be a key (a contract with no `scope` is `'public'`). Write
663
- endpoints inline in the contract literal: an endpoint hoisted into a variable
664
- widens its `scope` to `string` and is reported as undeclared.
665
-
666
- ## Released migration: 0.49.0
667
-
668
- ### The server handle became managed
669
-
670
- `createServer()` and `serveNode()` return a handle that owns admission, HTTP
671
- drain, realtime closure and one deadline-bounded runtime stop:
672
-
673
- ```ts
674
- // before
675
- server.stop()
676
- await socket.io.close()
677
- // after
678
- await server.shutdown({ gracePeriodMs: 30_000 })
679
- ```
680
-
681
- The runtime-specific instance stays reachable at `.runtime`, so an escape hatch
682
- you already rely on does not disappear — but code that closed transports itself,
683
- in its own order, is now racing the handle. Delete the manual closes rather than
684
- keeping both; the handle's result tells you what it drained and what it forced.
685
-
686
- ### Socket.IO mounts through the whole handle
687
-
688
- ```ts
689
- // before
690
- createServer({ websocket: socket.websocket, rawRoutes: [socket.route] })
691
- // after
692
- createServer({ socket })
693
- ```
694
-
695
- One owner for the route, the WebSocket attachment and the closure. For a raw Bun
696
- lane, keep the composed `websocket` handler and pass `socket` beside it.
697
-
698
- ### Bun native `routes` are gone
699
-
700
- Native routes run before the Fetch handler, so they bypassed managed admission —
701
- which means they also bypassed shutdown, logging and observability, and that is
702
- why they had to go rather than be wired up:
703
-
704
- ```ts
705
- // before
706
- createServer({ routes: { '/health': () => Response.json({ ok: true }) } })
707
- // after
708
- createServer({ rawRoutes: [{ method: 'GET', path: '/health', handler: () => Response.json({ ok: true }) }] })
709
- ```
710
-
711
- ### The handshake policy takes a Web `Request`
712
-
713
- ```ts
714
- // before
715
- createSocketIOServer({ serverOptions: { allowRequest: (req, done) => done(null, allowed(req)) } })
716
- // after
717
- createSocketIOServer({ allowRequest: (request) => allowed(request) })
718
- ```
719
-
720
- The Node-shaped callback is gone, and the policy is now composed with shutdown
721
- admission on both runtimes: a handshake arriving during drain is refused for
722
- you.
723
-
724
- ## Released migration: 0.48.0
725
-
726
- ### Typed-client request options move to `.withOptions`
727
-
728
- Generated endpoint methods reserve their ordinary call signature for contract
729
- variables. This keeps them directly assignable to callback APIs whose runtime
730
- supplies its own second context argument, including `react-query-kit` and
731
- TanStack Query. Move imperative cancellation to the callable's explicit method:
732
-
733
- ```ts
734
- // before — endpoint with arguments
735
- await api.create({ name: 'Max' }, { signal })
736
-
737
- // after
738
- await api.create.withOptions({ name: 'Max' }, { signal })
739
-
740
- // before — endpoint without arguments
741
- await api.health({ signal })
742
-
743
- // after
744
- await api.health.withOptions({ signal })
745
- ```
746
-
747
- Direct query and mutation composition remains unchanged:
748
-
749
- ```ts
750
- createMutation({ mutationFn: api.create })
751
- createQuery({ queryKey: ['search'], fetcher: api.search })
752
- ```
753
-
754
- There is no positional-options alias. Ordinary generated methods ignore extra
755
- runtime callback arguments; only `.withOptions` reads `ClientRequestOptions`.
756
-
757
- ## Released migration: 0.47.0
758
-
759
- ### HTTP auth moves to the pre-body `authorize` phase
760
-
761
- Move the HTTP wiring of `createAuthHook` from `beforeHandle` to `authorize`.
762
- This lets Stitchkit reject an unauthorized JSON or multipart request after path
763
- parameter validation but before reading a body chunk. Keep application
764
- preconditions that depend on validated input in `beforeHandle`.
765
-
766
- ```ts
767
- const auth = createAuthHook({ authenticate, authorize })
768
-
769
- // before
770
- createServer({ services, hooks: { beforeHandle: auth } })
771
-
772
- // after
773
- createServer({ services, hooks: { authorize: auth } })
774
- ```
775
-
776
- Tool transports already receive parsed input, so their wiring does not move:
777
-
778
- ```ts
779
- createMcpHandler({ services, lifecycle: { beforeHandle: auth } })
780
- ```
781
-
782
- If a custom HTTP authorization hook read `ctx.input`, `ctx.files` or raw body
783
- state, split it: identity/scope checks belong in `authorize`; validated payload
784
- preconditions belong in `beforeHandle` or the domain service.
785
-
786
- ### Multipart uses a typed descriptor and `ctx.files`
787
-
788
- Replace every string multipart declaration, top-level `maxUploadBytes` and
789
- `ctx.file`. The descriptor is now the only source of request, per-file,
790
- cardinality and declared media-type policy.
791
-
792
- ```ts
793
- // before
794
- upload: {
795
- method: 'POST',
796
- path: '/',
797
- multipart: 'file',
798
- maxUploadBytes: 25 * 1024 * 1024,
799
- }
800
- upload: ({ file, input }) => store(file, input)
801
-
802
- // after
803
- upload: {
804
- method: 'POST',
805
- path: '/',
806
- multipart: {
807
- maxRequestBytes: 25 * 1024 * 1024,
808
- files: {
809
- file: {
810
- maxBytes: 20 * 1024 * 1024,
811
- contentTypes: ['image/*', 'application/pdf'],
812
- },
813
- },
814
- },
815
- }
816
- upload: ({ files, input }) => store(files.file, input)
817
- ```
818
-
819
- Multiple files are repeated under one multipart field name and arrive in the
820
- same order:
821
-
822
- ```ts
823
- files: {
824
- attachments: { multiple: true, maxFiles: 8 },
825
- }
826
-
827
- await api.upload({ attachments: [firstFile, secondFile] })
828
- // handler: files.attachments is File[]
829
- ```
830
-
831
- For direct-to-storage delivery, set `delivery: 'stream'` and implement the
832
- endpoint with `defineMultipartStream`. A receiver must consume its Web Stream
833
- and return `{ value, cleanup }`; the final handler sees only receiver values.
834
- There is no deprecated overload or buffered compatibility path under the old
835
- contract shape.
836
-
837
- ## Released migration: 0.46.0
838
-
839
- ### `REALTIME_CONTRACT_VIOLATION` joined the error registry
840
-
841
- Realtime contract failures use the framework error model instead of a bare
842
- `ZodError`, so an exhaustive map stops compiling until the code is added:
843
-
844
- ```ts
845
- // before
846
- { …, INTERNAL_SERVER_ERROR: 'internal' } satisfies Record<StitchErrorCode, string>
847
- // after
848
- { …, INTERNAL_SERVER_ERROR: 'internal', REALTIME_CONTRACT_VIOLATION: 'internal' } satisfies Record<StitchErrorCode, string>
849
- ```
850
-
851
- Only an exhaustive map breaks. Since 0.56.1 `codeMap` itself is partial, so a
852
- map without the `satisfies` keeps compiling and lets the code travel as itself.
853
-
854
- ### `RealtimeRejectedEvent.error` is an `AppError`
855
-
856
- ```ts
857
- // before
858
- onRejected: ({ error }) => error.issues
859
- // after
860
- onRejected: ({ error }) => error.details?.issues // the ZodError moves to error.cause
861
- ```
862
-
863
- The envelope gained `reason` and `fault`. The consequence worth checking: code
864
- reading `.issues` directly does not fail to compile if the handler is loosely
865
- typed — it silently reads `undefined`. Grep for `.issues` on rejection handlers.
866
-
867
- ### CLI construction refuses reserved names
868
-
869
- A contract field or tool named `json`, `wait`, `quiet`, `dry-run`, `help`,
870
- `version`, `wait-timeout` or `output-dir` now **throws while the CLI is built**,
871
- instead of being silently shadowed:
872
-
873
- ```ts
874
- // before: app schedule_job --wait 2h → {"path":"2h"}, exit 0
875
- // after: building a CLI over a contract with a "wait" field throws
876
- ```
877
-
878
- This one fires at startup, not at call time, so an application shipping such a
879
- field crashes on boot after the upgrade. That is deliberate — the old behaviour
880
- corrupted arguments silently — but it means the upgrade is not safe to deploy
881
- without building the CLI once locally.
882
-
883
- ### `createToolLogger` writes to stderr
884
-
885
- stdout is the JSON-RPC channel of a stdio MCP server, and the previous
886
- `console.info` default corrupted it. Pass `log` to redirect if your process
887
- collected tool logs from stdout.
888
-
889
- ## Released migration: 0.44.0
890
-
891
- ### MCP TypeScript SDK v2 and protocol `2026-07-28`
892
-
893
- This is a hard cut: there is one Stitchkit API and no v1 aliases. Applications
894
- that expose MCP install the split server package; applications that implement an
895
- MCP host or run client E2E install the split client package.
896
-
897
- ```bash
898
- bun remove @modelcontextprotocol/sdk
899
- bun add @modelcontextprotocol/server@^2 ai@^7
900
- # MCP hosts and client-side E2E only:
901
- bun add -d @modelcontextprotocol/client@^2
902
- ```
903
-
904
- Direct SDK imports move to the split packages too:
905
-
906
- ```ts
907
- // before
908
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
909
-
910
- // after
911
- import { McpServer } from '@modelcontextprotocol/server'
912
- ```
913
-
914
- MCP Apps additionally install `@modelcontextprotocol/ext-apps`. That adapter may
915
- carry its own isolated v1-era transitive/peer relationship while the ecosystem
916
- finishes its cutover; it does not permit application code to import the removed
917
- monolithic SDK. Application-owned MCP server and client code uses the v2 split
918
- packages exclusively.
919
-
920
- ```ts
921
- // before
922
- import { Client } from '@modelcontextprotocol/sdk/client/index.js'
923
- import { createMcpHandler } from 'stitchkit/tools'
924
-
925
- const handleMcp = createMcpHandler({
926
- serverInfo,
927
- auth,
928
- services,
929
- sessionMode: 'stateless',
930
- })
931
- rawRoutes: [{ method: 'ALL', path: '/mcp', handler: handleMcp }]
932
-
933
- // after
934
- import { Client } from '@modelcontextprotocol/client'
935
- import { createMcpHandler, createMcpHttpRoute } from 'stitchkit/tools'
936
-
937
- const mcp = createMcpHandler({
938
- serverInfo,
939
- auth,
940
- services,
941
- legacy: 'serve',
942
- })
943
- rawRoutes: [createMcpHttpRoute({ path: '/mcp', handler: mcp })]
944
- // graceful shutdown: await mcp.close()
945
- ```
946
-
947
- Keep the owned handle and close it from the same shutdown path as the HTTP
948
- server. A minimal runtime smoke should list tools before shutdown and prove the
949
- closed handler no longer serves requests:
950
-
951
- ```ts
952
- const mcp = createMcpHandler(config)
953
- const route = createMcpHttpRoute({ path: '/mcp', handler: mcp })
954
-
955
- const beforeClose = await route.handler(listToolsRequest)
956
- if (!beforeClose.ok) throw new Error('MCP list-tools smoke failed')
957
-
958
- await mcp.close()
959
- ```
960
-
961
- Remove `@modelcontextprotocol/sdk`, `sessionMode`, `McpSessionMode`, session
962
- stores and all `Mcp-Session-Id` handling. HTTP is always request-isolated and
963
- stateless. `legacy: 'serve'` (default) lets the official SDK negotiate supported
964
- pre-2026 stateless clients on the same endpoint; `legacy: 'reject'` makes it
965
- modern-only. This is not a stateful compatibility transport.
966
-
967
- #### Output shape depends on the negotiated protocol era
968
-
969
- Stitchkit always validates the handler result against the declared output
970
- schema. The negotiated MCP era determines only its wire representation:
971
-
972
- | Negotiated era | Non-object `structuredContent` |
973
- |---|---|
974
- | MCP `2026-07-28` | the exact schema-valid JSON root: array, scalar or `null` |
975
- | supported legacy era | the official SDK codec adapts it to `{ result: value }` |
976
-
977
- Object roots keep their object shape in both eras. Do not change every consumer
978
- expectation to the modern shape while `legacy: 'serve'` remains enabled. Pin
979
- both protocol versions in the consumer's transport E2E and assert the boundary
980
- explicitly:
981
-
982
- ```ts
983
- await expectToolOutputForProtocol('2026-07-28', ['a', 'b'])
984
- await expectToolOutputForProtocol('2025-11-25', { result: ['a', 'b'] })
985
-
986
- async function expectToolOutputForProtocol(
987
- protocolVersion: '2026-07-28' | '2025-11-25',
988
- expected: unknown,
989
- ) {
990
- const client = await connectConsumerMcpClient({ protocolVersion })
991
- const result = await client.callTool({ name: 'list_notes', arguments: {} })
992
- expect(result.structuredContent).toEqual(expected)
993
- await client.close()
994
- }
995
- ```
996
-
997
- `connectConsumerMcpClient` represents the consumer's real HTTP or stdio setup;
998
- configure its official client with `versionNegotiation.mode.pin` so the test
999
- cannot silently negotiate a different era.
1000
-
1001
- The stdio helper now returns an owned lifecycle handle:
1002
-
1003
- ```ts
1004
- // before
1005
- await createStdioMcpServer(config)
1006
-
1007
- // after
1008
- const stdio = await createStdioMcpServer({ ...config, legacy: 'serve' })
1009
- await stdio.close()
1010
- ```
1011
-
1012
- OAuth client registration is now one explicit policy object. CIMD is secure and
1013
- enabled by default; DCR is disabled unless supplied:
1014
-
1015
- ```ts
1016
- // before
1017
- mountOAuthProvider({ ...oauth, clients, codes, refreshTokens })
1018
-
1019
- // after
1020
- mountOAuthProvider({
1021
- ...oauth,
1022
- clientRegistration: {
1023
- preRegistered: { get: clients.get },
1024
- // optional: dcr: { register: clients.register, get: clients.get }
1025
- },
1026
- codes,
1027
- refreshTokens,
1028
- })
1029
- ```
1030
-
1031
- A URL client id must be HTTPS and serve a document whose `client_id` exactly
1032
- matches that URL, with explicit `redirect_uris` and
1033
- `token_endpoint_auth_method: 'none'`. Do not keep a consumer-side metadata
1034
- fetcher or DCR fallback; Stitchkit owns SSRF-safe resolution and caching.
1035
-
1036
- Multi-round input is opt-in on the operation and does not change Agent, CLI or
1037
- ordinary HTTP handlers:
1038
-
1039
- ```ts
1040
- const ConfirmationSchema = z.object({ confirmed: z.boolean() })
1041
-
1042
- mcp: {
1043
- inputRequired: [{
1044
- key: 'confirmation',
1045
- message: 'Confirm this action',
1046
- schema: ConfirmationSchema,
1047
- }],
1048
- }
1049
- ```
1050
-
1051
- Configure `multiRound.state` on the MCP server with a key of at least 32 bytes
1052
- and a stable authenticated `principal`. Read accepted typed content from
1053
- `ctx.mcpInput.confirmation`. Multiple declarations run in array order, the
1054
- aggregate remains exactly typed by key, keys must be unique, and declarations
1055
- must fit `multiRound.serving.maxRounds` (default `10`). Do not execute a
1056
- destructive side effect before the complete aggregate is accepted. A modern
1057
- request missing the declared elicitation capability receives JSON-RPC error
1058
- code `-32021`. The official per-request legacy HTTP bridge cannot issue
1059
- server-to-client elicitation, so it returns a deterministic failed tool result;
1060
- multi-round input is never silently treated as complete.
1061
-
1062
- #### Compatibility matrix
1063
-
1064
- | Host / transport | Tools and Apps | Multi-round input | Continuity |
1065
- |---|---|---|---|
1066
- | `2026-07-28` HTTP | yes | yes | request-isolated |
1067
- | supported legacy stateless HTTP | yes | unsupported result | request-isolated |
1068
- | `2026-07-28` stdio | yes | yes | one process connection |
1069
- | supported legacy stdio | yes | official SDK bridge | one process connection |
1070
- | Agent / CLI / ordinary HTTP | unchanged | not exposed | unchanged |
1071
-
1072
- Subscriptions, cross-request progress and resumable stateful SSE are not
1073
- implemented or advertised.
1074
-
1075
- #### Consumer checklist
1076
-
1077
- 1. Replace the monolithic SDK with `@modelcontextprotocol/server@^2` and, only
1078
- for hosts/tests, `@modelcontextprotocol/client@^2`.
1079
- 2. Replace raw MCP route wiring with `createMcpHttpRoute`; retain and close the
1080
- returned handler/stdio handle during shutdown.
1081
- 3. Delete all session mode, event-store and session-id code.
1082
- 4. Move OAuth client policy under `clientRegistration`; publish CIMD or enable
1083
- DCR explicitly.
1084
- 5. Make `authorizeUser` return the exact consented scope subset. The framework
1085
- validates that it is a subset of the request before saving the authorization
1086
- code:
1087
-
1088
- ```ts
1089
- // before
1090
- authorizeUser: async () => ({ userId })
1091
-
1092
- // after
1093
- authorizeUser: async (_req, request) => ({
1094
- userId,
1095
- approvedScopes: request.scope?.split(' ') ?? [],
1096
- })
1097
- ```
1098
-
1099
- 6. Snapshot `listToolNames`, run one contract tool, one runtime tool, any raw
1100
- multimodal tool and every MCP App resource you use.
1101
- 7. Exercise modern HTTP and stdio with protocol `2026-07-28`; exercise legacy
1102
- only if `legacy: 'serve'` is part of your support policy.
1103
- 8. Run the consumer's typecheck and runtime gates. A browser/HTTP-only consumer
1104
- must continue to work without either MCP package.