stitchkit 0.92.0 → 0.94.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 (793) hide show
  1. package/CHANGELOG.md +191 -0
  2. package/README.md +5 -2
  3. package/dist/agent-runtime/children-control.d.ts +6 -0
  4. package/dist/agent-runtime/children-control.d.ts.map +1 -0
  5. package/dist/agent-runtime/children-spawn.d.ts +6 -0
  6. package/dist/agent-runtime/children-spawn.d.ts.map +1 -0
  7. package/dist/agent-runtime/children-state.d.ts +46 -0
  8. package/dist/agent-runtime/children-state.d.ts.map +1 -0
  9. package/dist/agent-runtime/children-usage.d.ts +8 -0
  10. package/dist/agent-runtime/children-usage.d.ts.map +1 -0
  11. package/dist/agent-runtime/children.d.ts +11 -14
  12. package/dist/agent-runtime/children.d.ts.map +1 -1
  13. package/dist/agent-runtime/coding-tool-contract.d.ts +2 -1
  14. package/dist/agent-runtime/coding-tool-contract.d.ts.map +1 -1
  15. package/dist/agent-runtime/deferred-tool-types.d.ts +2 -2
  16. package/dist/agent-runtime/deferred-tool-types.d.ts.map +1 -1
  17. package/dist/agent-runtime/events.d.ts +1 -1
  18. package/dist/agent-runtime/events.d.ts.map +1 -1
  19. package/dist/agent-runtime/managed-tools.d.ts +1 -1
  20. package/dist/agent-runtime/managed-tools.d.ts.map +1 -1
  21. package/dist/agent-runtime/observability.d.ts +1 -1
  22. package/dist/agent-runtime/observability.d.ts.map +1 -1
  23. package/dist/{agent-runtime-openrouter.d.ts → agent-runtime/openrouter.d.ts} +3 -3
  24. package/dist/agent-runtime/openrouter.d.ts.map +1 -0
  25. package/dist/agent-runtime/projections.d.ts +1 -1
  26. package/dist/agent-runtime/projections.d.ts.map +1 -1
  27. package/dist/agent-runtime/run-acquisition.d.ts +17 -0
  28. package/dist/agent-runtime/run-acquisition.d.ts.map +1 -0
  29. package/dist/agent-runtime/run-execution-state.d.ts +133 -0
  30. package/dist/agent-runtime/run-execution-state.d.ts.map +1 -0
  31. package/dist/agent-runtime/run-execution.d.ts +17 -33
  32. package/dist/agent-runtime/run-execution.d.ts.map +1 -1
  33. package/dist/agent-runtime/run-failure.d.ts +18 -0
  34. package/dist/agent-runtime/run-failure.d.ts.map +1 -0
  35. package/dist/agent-runtime/run-model-attempts.d.ts +6 -0
  36. package/dist/agent-runtime/run-model-attempts.d.ts.map +1 -0
  37. package/dist/agent-runtime/run-prompt-history.d.ts +58 -0
  38. package/dist/agent-runtime/run-prompt-history.d.ts.map +1 -0
  39. package/dist/agent-runtime/run-provider-ledger.d.ts +26 -0
  40. package/dist/agent-runtime/run-provider-ledger.d.ts.map +1 -0
  41. package/dist/agent-runtime/run-stream-parts.d.ts +17 -0
  42. package/dist/agent-runtime/run-stream-parts.d.ts.map +1 -0
  43. package/dist/agent-runtime/run-terminal.d.ts +11 -0
  44. package/dist/agent-runtime/run-terminal.d.ts.map +1 -0
  45. package/dist/agent-runtime/run-turn-preparation.d.ts +22 -0
  46. package/dist/agent-runtime/run-turn-preparation.d.ts.map +1 -0
  47. package/dist/agent-runtime/runtime-admission-gate.d.ts +29 -0
  48. package/dist/agent-runtime/runtime-admission-gate.d.ts.map +1 -0
  49. package/dist/agent-runtime/runtime-control.d.ts +9 -0
  50. package/dist/agent-runtime/runtime-control.d.ts.map +1 -0
  51. package/dist/agent-runtime/runtime-recovery.d.ts +10 -0
  52. package/dist/agent-runtime/runtime-recovery.d.ts.map +1 -0
  53. package/dist/agent-runtime/runtime-state.d.ts +36 -0
  54. package/dist/agent-runtime/runtime-state.d.ts.map +1 -0
  55. package/dist/agent-runtime/runtime-submit.d.ts +5 -0
  56. package/dist/agent-runtime/runtime-submit.d.ts.map +1 -0
  57. package/dist/agent-runtime/runtime.d.ts +9 -4
  58. package/dist/agent-runtime/runtime.d.ts.map +1 -1
  59. package/dist/{agent-runtime-sqlite-bun.d.ts → agent-runtime/sqlite-bun.d.ts} +5 -4
  60. package/dist/agent-runtime/sqlite-bun.d.ts.map +1 -0
  61. package/dist/agent-runtime/sqlite-events.d.ts +5 -0
  62. package/dist/agent-runtime/sqlite-events.d.ts.map +1 -0
  63. package/dist/agent-runtime/sqlite-history.d.ts +7 -0
  64. package/dist/agent-runtime/sqlite-history.d.ts.map +1 -0
  65. package/dist/agent-runtime/sqlite-ledger.d.ts +7 -0
  66. package/dist/agent-runtime/sqlite-ledger.d.ts.map +1 -0
  67. package/dist/{agent-runtime-sqlite-node.d.ts → agent-runtime/sqlite-node.d.ts} +5 -4
  68. package/dist/agent-runtime/sqlite-node.d.ts.map +1 -0
  69. package/dist/agent-runtime/sqlite-reads.d.ts +14 -0
  70. package/dist/agent-runtime/sqlite-reads.d.ts.map +1 -0
  71. package/dist/agent-runtime/sqlite-rows.d.ts +178 -0
  72. package/dist/agent-runtime/sqlite-rows.d.ts.map +1 -0
  73. package/dist/agent-runtime/sqlite-schema.d.ts +7 -0
  74. package/dist/agent-runtime/sqlite-schema.d.ts.map +1 -0
  75. package/dist/agent-runtime/sqlite-transactions.d.ts +25 -0
  76. package/dist/agent-runtime/sqlite-transactions.d.ts.map +1 -0
  77. package/dist/agent-runtime/sqlite.d.ts +10 -6
  78. package/dist/agent-runtime/sqlite.d.ts.map +1 -1
  79. package/dist/agent-runtime/store-archive.d.ts +16 -0
  80. package/dist/agent-runtime/store-archive.d.ts.map +1 -0
  81. package/dist/{testing/agent-store-conformance.d.ts → agent-runtime/store-conformance.d.ts} +2 -2
  82. package/dist/agent-runtime/store-conformance.d.ts.map +1 -0
  83. package/dist/agent-runtime/store-create.d.ts +11 -0
  84. package/dist/agent-runtime/store-create.d.ts.map +1 -0
  85. package/dist/agent-runtime/{store-driver.d.ts → store-driver-contract.d.ts} +7 -7
  86. package/dist/agent-runtime/store-driver-contract.d.ts.map +1 -0
  87. package/dist/agent-runtime/store-events.d.ts +7 -89
  88. package/dist/agent-runtime/store-events.d.ts.map +1 -1
  89. package/dist/agent-runtime/store-memory.d.ts +4 -0
  90. package/dist/agent-runtime/store-memory.d.ts.map +1 -0
  91. package/dist/agent-runtime/store-mutate.d.ts +13 -0
  92. package/dist/agent-runtime/store-mutate.d.ts.map +1 -0
  93. package/dist/agent-runtime/store-purge.d.ts +1 -1
  94. package/dist/agent-runtime/store-purge.d.ts.map +1 -1
  95. package/dist/agent-runtime/store-reads.d.ts +29 -0
  96. package/dist/agent-runtime/store-reads.d.ts.map +1 -0
  97. package/dist/agent-runtime/store-reduce-history.d.ts +10 -0
  98. package/dist/agent-runtime/store-reduce-history.d.ts.map +1 -0
  99. package/dist/agent-runtime/store-reduce-run.d.ts +14 -0
  100. package/dist/agent-runtime/store-reduce-run.d.ts.map +1 -0
  101. package/dist/agent-runtime/store-reduce-shared.d.ts +76 -0
  102. package/dist/agent-runtime/store-reduce-shared.d.ts.map +1 -0
  103. package/dist/agent-runtime/store-reduce-terminal.d.ts +6 -0
  104. package/dist/agent-runtime/store-reduce-terminal.d.ts.map +1 -0
  105. package/dist/agent-runtime/store-reducer.d.ts +24 -0
  106. package/dist/agent-runtime/store-reducer.d.ts.map +1 -0
  107. package/dist/agent-runtime/store-snapshot.d.ts +19 -0
  108. package/dist/agent-runtime/store-snapshot.d.ts.map +1 -0
  109. package/dist/agent-runtime/store.d.ts +1 -1
  110. package/dist/agent-runtime/store.d.ts.map +1 -1
  111. package/dist/application/admission.d.ts +1 -1
  112. package/dist/application/admission.d.ts.map +1 -1
  113. package/dist/application/events.d.ts +1 -1
  114. package/dist/application/events.d.ts.map +1 -1
  115. package/dist/{server → application}/file-state-store.d.ts +1 -1
  116. package/dist/application/file-state-store.d.ts.map +1 -0
  117. package/dist/application/health.d.ts +1 -1
  118. package/dist/application/health.d.ts.map +1 -1
  119. package/dist/application/kernel-admission.d.ts +8 -0
  120. package/dist/application/kernel-admission.d.ts.map +1 -0
  121. package/dist/application/kernel-contract.d.ts +142 -0
  122. package/dist/application/kernel-contract.d.ts.map +1 -0
  123. package/dist/application/kernel-resource-context.d.ts +24 -0
  124. package/dist/application/kernel-resource-context.d.ts.map +1 -0
  125. package/dist/application/kernel-restart.d.ts +5 -0
  126. package/dist/application/kernel-restart.d.ts.map +1 -0
  127. package/dist/application/kernel-rollback.d.ts +4 -0
  128. package/dist/application/kernel-rollback.d.ts.map +1 -0
  129. package/dist/application/kernel-shutdown.d.ts +6 -0
  130. package/dist/application/kernel-shutdown.d.ts.map +1 -0
  131. package/dist/application/kernel-start.d.ts +20 -0
  132. package/dist/application/kernel-start.d.ts.map +1 -0
  133. package/dist/application/kernel-state.d.ts +116 -0
  134. package/dist/application/kernel-state.d.ts.map +1 -0
  135. package/dist/application/kernel.d.ts +9 -140
  136. package/dist/application/kernel.d.ts.map +1 -1
  137. package/dist/application/latest-sink.d.ts +1 -1
  138. package/dist/application/latest-sink.d.ts.map +1 -1
  139. package/dist/application/opentelemetry.d.ts +1 -1
  140. package/dist/application/opentelemetry.d.ts.map +1 -1
  141. package/dist/application/watch-hub.d.ts +2 -2
  142. package/dist/application/watch-hub.d.ts.map +1 -1
  143. package/dist/browser/client-multipart.d.ts +1 -1
  144. package/dist/browser/client-multipart.d.ts.map +1 -1
  145. package/dist/browser/client-url.d.ts +1 -1
  146. package/dist/browser/client-url.d.ts.map +1 -1
  147. package/dist/browser/client.d.ts +1 -1
  148. package/dist/browser/client.d.ts.map +1 -1
  149. package/dist/browser/contract-stream.d.ts +1 -1
  150. package/dist/browser/contract-stream.d.ts.map +1 -1
  151. package/dist/browser/http.d.ts +1 -1
  152. package/dist/browser/http.d.ts.map +1 -1
  153. package/dist/browser/resumable.d.ts +1 -28
  154. package/dist/browser/resumable.d.ts.map +1 -1
  155. package/dist/browser/retained.d.ts.map +1 -0
  156. package/dist/browser/socket-io.d.ts +23 -1
  157. package/dist/browser/socket-io.d.ts.map +1 -1
  158. package/dist/browser/stream.d.ts +14 -2
  159. package/dist/browser/stream.d.ts.map +1 -1
  160. package/dist/contract/define.d.ts +72 -65
  161. package/dist/contract/define.d.ts.map +1 -1
  162. package/dist/{internal/errors.d.ts → contract/normalize.d.ts} +3 -39
  163. package/dist/contract/normalize.d.ts.map +1 -0
  164. package/dist/contract/tool-view.d.ts +135 -0
  165. package/dist/contract/tool-view.d.ts.map +1 -0
  166. package/dist/declaration/declaration.d.ts.map +1 -0
  167. package/dist/{agent-runtime/durability-contract.d.ts → durability/contract.d.ts} +2 -2
  168. package/dist/durability/contract.d.ts.map +1 -0
  169. package/dist/{agent-runtime/durability.d.ts → durability/engine.d.ts} +4 -4
  170. package/dist/durability/engine.d.ts.map +1 -0
  171. package/dist/durability/events.d.ts +101 -0
  172. package/dist/durability/events.d.ts.map +1 -0
  173. package/dist/{agent-runtime/durability-json.d.ts → durability/json.d.ts} +1 -1
  174. package/dist/durability/json.d.ts.map +1 -0
  175. package/dist/{agent-runtime/durability-ledger.d.ts → durability/ledger.d.ts} +2 -2
  176. package/dist/durability/ledger.d.ts.map +1 -0
  177. package/dist/{agent-runtime/durability-scheduler.d.ts → durability/scheduler.d.ts} +2 -2
  178. package/dist/durability/scheduler.d.ts.map +1 -0
  179. package/dist/entrypoints/agent-runtime/browser.d.ts +5 -0
  180. package/dist/entrypoints/agent-runtime/browser.d.ts.map +1 -0
  181. package/dist/{agent-runtime-browser.js → entrypoints/agent-runtime/browser.js} +3 -3
  182. package/dist/{agent-runtime-coding-tools.d.ts → entrypoints/agent-runtime/coding-tools.d.ts} +2 -2
  183. package/dist/entrypoints/agent-runtime/coding-tools.d.ts.map +1 -0
  184. package/dist/entrypoints/agent-runtime/coding-tools.js +22 -0
  185. package/dist/{agent-runtime-harness.d.ts → entrypoints/agent-runtime/harness.d.ts} +2 -2
  186. package/dist/entrypoints/agent-runtime/harness.d.ts.map +1 -0
  187. package/dist/{agent-runtime-harness.js → entrypoints/agent-runtime/harness.js} +24 -25
  188. package/dist/entrypoints/agent-runtime/openrouter.d.ts +2 -0
  189. package/dist/entrypoints/agent-runtime/openrouter.d.ts.map +1 -0
  190. package/dist/{agent-runtime-openrouter.js → entrypoints/agent-runtime/openrouter.js} +3 -3
  191. package/dist/{agent-runtime-sandbox.d.ts → entrypoints/agent-runtime/sandbox.d.ts} +5 -5
  192. package/dist/entrypoints/agent-runtime/sandbox.d.ts.map +1 -0
  193. package/dist/{agent-runtime-sandbox.js → entrypoints/agent-runtime/sandbox.js} +11 -12
  194. package/dist/entrypoints/agent-runtime/sqlite/bun.d.ts +2 -0
  195. package/dist/entrypoints/agent-runtime/sqlite/bun.d.ts.map +1 -0
  196. package/dist/{agent-runtime-sqlite-bun.js → entrypoints/agent-runtime/sqlite/bun.js} +8 -6
  197. package/dist/entrypoints/agent-runtime/sqlite/node.d.ts +2 -0
  198. package/dist/entrypoints/agent-runtime/sqlite/node.d.ts.map +1 -0
  199. package/dist/{agent-runtime-sqlite-node.js → entrypoints/agent-runtime/sqlite/node.js} +8 -6
  200. package/dist/entrypoints/agent-runtime/testing.d.ts +4 -0
  201. package/dist/entrypoints/agent-runtime/testing.d.ts.map +1 -0
  202. package/dist/entrypoints/agent-runtime/testing.js +1084 -0
  203. package/dist/{agent-runtime.d.ts → entrypoints/agent-runtime.d.ts} +41 -37
  204. package/dist/entrypoints/agent-runtime.d.ts.map +1 -0
  205. package/dist/{agent-runtime.js → entrypoints/agent-runtime.js} +408 -366
  206. package/dist/{application-diagnostic-journal.d.ts → entrypoints/application/diagnostic-journal.d.ts} +2 -2
  207. package/dist/entrypoints/application/diagnostic-journal.d.ts.map +1 -0
  208. package/dist/{application-diagnostic-journal.js → entrypoints/application/diagnostic-journal.js} +3 -3
  209. package/dist/{application-grammy.d.ts → entrypoints/application/grammy.d.ts} +2 -2
  210. package/dist/entrypoints/application/grammy.d.ts.map +1 -0
  211. package/dist/{application-grammy.js → entrypoints/application/grammy.js} +2 -2
  212. package/dist/{application-opentelemetry.d.ts → entrypoints/application/opentelemetry.d.ts} +2 -2
  213. package/dist/entrypoints/application/opentelemetry.d.ts.map +1 -0
  214. package/dist/{application-opentelemetry.js → entrypoints/application/opentelemetry.js} +4 -4
  215. package/dist/{application-schemas.d.ts → entrypoints/application/schemas.d.ts} +2 -2
  216. package/dist/entrypoints/application/schemas.d.ts.map +1 -0
  217. package/dist/{application-schemas.js → entrypoints/application/schemas.js} +2 -2
  218. package/dist/{application.d.ts → entrypoints/application.d.ts} +22 -21
  219. package/dist/entrypoints/application.d.ts.map +1 -0
  220. package/dist/{application.js → entrypoints/application.js} +24 -22
  221. package/dist/entrypoints/bin/upgrade-cli.d.ts.map +1 -0
  222. package/dist/{upgrade-cli.js → entrypoints/bin/upgrade-cli.js} +3 -3
  223. package/dist/{cli.d.ts → entrypoints/cli.d.ts} +15 -15
  224. package/dist/entrypoints/cli.d.ts.map +1 -0
  225. package/dist/{cli.js → entrypoints/cli.js} +37 -32
  226. package/dist/entrypoints/contract.d.ts +9 -0
  227. package/dist/entrypoints/contract.d.ts.map +1 -0
  228. package/dist/{contract/index.js → entrypoints/contract.js} +14 -6
  229. package/dist/entrypoints/declaration.d.ts +2 -0
  230. package/dist/entrypoints/declaration.d.ts.map +1 -0
  231. package/dist/{declaration.js → entrypoints/declaration.js} +1 -1
  232. package/dist/{files.d.ts → entrypoints/files.d.ts} +2 -2
  233. package/dist/entrypoints/files.d.ts.map +1 -0
  234. package/dist/{files.js → entrypoints/files.js} +3 -3
  235. package/dist/{geo.d.ts → entrypoints/geo.d.ts} +1 -1
  236. package/dist/entrypoints/geo.d.ts.map +1 -0
  237. package/dist/{geo.js → entrypoints/geo.js} +4 -4
  238. package/dist/entrypoints/google.d.ts +2 -0
  239. package/dist/entrypoints/google.d.ts.map +1 -0
  240. package/dist/{google.js → entrypoints/google.js} +1 -1
  241. package/dist/{index.d.ts → entrypoints/index.d.ts} +14 -13
  242. package/dist/entrypoints/index.d.ts.map +1 -0
  243. package/dist/{index.js → entrypoints/index.js} +99 -33
  244. package/dist/{live.d.ts → entrypoints/live.d.ts} +4 -4
  245. package/dist/entrypoints/live.d.ts.map +1 -0
  246. package/dist/{live.js → entrypoints/live.js} +6 -4
  247. package/dist/{node.d.ts → entrypoints/node.d.ts} +11 -11
  248. package/dist/entrypoints/node.d.ts.map +1 -0
  249. package/dist/{node.js → entrypoints/node.js} +20 -16
  250. package/dist/entrypoints/oauth.d.ts +2 -0
  251. package/dist/entrypoints/oauth.d.ts.map +1 -0
  252. package/dist/{oauth.js → entrypoints/oauth.js} +3 -3
  253. package/dist/{observability/index.d.ts → entrypoints/observability.d.ts} +11 -11
  254. package/dist/entrypoints/observability.d.ts.map +1 -0
  255. package/dist/{observability/index.js → entrypoints/observability.js} +9 -11
  256. package/dist/entrypoints/primitives.d.ts +3 -0
  257. package/dist/entrypoints/primitives.d.ts.map +1 -0
  258. package/dist/{primitives.js → entrypoints/primitives.js} +1 -6
  259. package/dist/{react.d.ts → entrypoints/react.d.ts} +4 -4
  260. package/dist/entrypoints/react.d.ts.map +1 -0
  261. package/dist/{react.js → entrypoints/react.js} +3 -3
  262. package/dist/{release.d.ts → entrypoints/release.d.ts} +4 -4
  263. package/dist/entrypoints/release.d.ts.map +1 -0
  264. package/dist/{release.js → entrypoints/release.js} +1 -1
  265. package/dist/{remote.d.ts → entrypoints/remote.d.ts} +1 -1
  266. package/dist/entrypoints/remote.d.ts.map +1 -0
  267. package/dist/entrypoints/remote.js +66 -0
  268. package/dist/{server/index.d.ts → entrypoints/server.d.ts} +35 -34
  269. package/dist/entrypoints/server.d.ts.map +1 -0
  270. package/dist/{server/index.js → entrypoints/server.js} +294 -244
  271. package/dist/{telegram.d.ts → entrypoints/telegram.d.ts} +2 -2
  272. package/dist/entrypoints/telegram.d.ts.map +1 -0
  273. package/dist/{telegram.js → entrypoints/telegram.js} +1 -1
  274. package/dist/entrypoints/testing.d.ts +9 -0
  275. package/dist/entrypoints/testing.d.ts.map +1 -0
  276. package/dist/{testing.js → entrypoints/testing.js} +107 -926
  277. package/dist/{tools/connections/index.d.ts → entrypoints/tools/connections.d.ts} +6 -7
  278. package/dist/entrypoints/tools/connections.d.ts.map +1 -0
  279. package/dist/{tools/connections/index.js → entrypoints/tools/connections.js} +7 -4
  280. package/dist/{tools-contract.d.ts → entrypoints/tools/contract.d.ts} +5 -5
  281. package/dist/entrypoints/tools/contract.d.ts.map +1 -0
  282. package/dist/{tools-contract.js → entrypoints/tools/contract.js} +4 -4
  283. package/dist/{tool-invoker.d.ts → entrypoints/tools/invoker.d.ts} +2 -2
  284. package/dist/entrypoints/tools/invoker.d.ts.map +1 -0
  285. package/dist/entrypoints/tools/invoker.js +20 -0
  286. package/dist/entrypoints/tools.d.ts +51 -0
  287. package/dist/entrypoints/tools.d.ts.map +1 -0
  288. package/dist/{tools.js → entrypoints/tools.js} +1787 -1751
  289. package/dist/{tracking-server.d.ts → entrypoints/tracking/server.d.ts} +8 -8
  290. package/dist/entrypoints/tracking/server.d.ts.map +1 -0
  291. package/dist/{tracking.d.ts → entrypoints/tracking.d.ts} +15 -15
  292. package/dist/entrypoints/tracking.d.ts.map +1 -0
  293. package/dist/{tracking.js → entrypoints/tracking.js} +5 -8
  294. package/dist/google/google.d.ts.map +1 -0
  295. package/dist/{index-a916km3r.js → index-0b1ess5e.js} +6 -13
  296. package/dist/{index-zwkgfq1s.js → index-1nd48tm9.js} +113 -118
  297. package/dist/{index-7zbps32p.js → index-1zbbzgfh.js} +2 -2
  298. package/dist/{index-mzvgxp0n.js → index-2cr1cqhn.js} +16 -4
  299. package/dist/{index-f9mb610r.js → index-35mh5bhj.js} +2 -2
  300. package/dist/index-48ffdxgk.js +6 -0
  301. package/dist/index-58k4fp34.js +1023 -0
  302. package/dist/{index-p13mwz16.js → index-83bdg97s.js} +1 -1
  303. package/dist/index-97ac4gph.js +3618 -0
  304. package/dist/{index-kw9t5ayn.js → index-cq4qfycf.js} +5 -5
  305. package/dist/{index-7gnkny4z.js → index-d9pk3td4.js} +1 -1
  306. package/dist/{index-e42wzzz5.js → index-dcpdvjsc.js} +7 -7
  307. package/dist/{index-h9etkkyk.js → index-dydjcp8z.js} +102 -25
  308. package/dist/{index-sr93cwf9.js → index-e2z3ahw9.js} +2 -2
  309. package/dist/{index-yewwh1w4.js → index-e87kakm4.js} +96 -11
  310. package/dist/{index-cby4ar3v.js → index-eqqvgdb3.js} +1 -1
  311. package/dist/index-fdp6hdxn.js +942 -0
  312. package/dist/{index-0a349c33.js → index-gyr48nzg.js} +125 -198
  313. package/dist/{index-wnfk50r0.js → index-h6eeys1v.js} +1 -1
  314. package/dist/{index-77fekveh.js → index-hffjpmq9.js} +1 -15
  315. package/dist/{index-yn8remb1.js → index-j05z5gn4.js} +50 -14
  316. package/dist/index-k5hsfc3j.js +31 -0
  317. package/dist/{index-fq77yfzc.js → index-kj2wbeta.js} +1 -1
  318. package/dist/index-kvj7f4hq.js +39 -0
  319. package/dist/{index-4fpa9dy2.js → index-m9zn6cpq.js} +2 -2
  320. package/dist/{index-2na0qrfn.js → index-mdzh02yc.js} +7 -7
  321. package/dist/{index-ywd0y6m1.js → index-mkm15s49.js} +1 -1
  322. package/dist/index-mp5sn43f.js +1084 -0
  323. package/dist/{index-7n145nbe.js → index-n6hxg8as.js} +530 -387
  324. package/dist/index-ngfhvfpd.js +30 -0
  325. package/dist/{index-e0znv5gn.js → index-p5r7qpdd.js} +2 -93
  326. package/dist/{index-n0f51dfn.js → index-p81267c2.js} +608 -549
  327. package/dist/{index-wc4x00bn.js → index-qwhynv6x.js} +1 -1
  328. package/dist/index-r7nmqpsg.js +154 -0
  329. package/dist/{index-bx75zwt7.js → index-rewkc2hj.js} +5 -4
  330. package/dist/{index-9f8ztey6.js → index-sees8yf8.js} +2 -2
  331. package/dist/{index-vjpvjqpn.js → index-v38qyerb.js} +16 -2
  332. package/dist/{index-2c2bjw3s.js → index-vcvkq30w.js} +3 -3
  333. package/dist/index-wqgjfstn.js +18 -0
  334. package/dist/{index-f477k430.js → index-x4799c19.js} +1 -1
  335. package/dist/{index-cxqhvq21.js → index-xnj9bgxe.js} +142 -129
  336. package/dist/index-xsqjkha9.js +281 -0
  337. package/dist/{index-6kyksz9y.js → index-yw4fzmdz.js} +1 -1
  338. package/dist/{index-3xwxfj4z.js → index-zeemqhqx.js} +1 -1
  339. package/dist/{index-tmwcrptx.js → index-zfrhfn82.js} +1 -1
  340. package/dist/index-znfs20ss.js +98 -0
  341. package/dist/internal/backoff.d.ts +29 -0
  342. package/dist/internal/backoff.d.ts.map +1 -0
  343. package/dist/internal/canonical-json.d.ts +21 -11
  344. package/dist/internal/canonical-json.d.ts.map +1 -1
  345. package/dist/internal/channel.d.ts.map +1 -0
  346. package/dist/internal/logger.d.ts.map +1 -0
  347. package/dist/internal/request.d.ts.map +1 -0
  348. package/dist/internal/secure-fetch.d.ts +12 -0
  349. package/dist/internal/secure-fetch.d.ts.map +1 -1
  350. package/dist/internal/stable-digest.d.ts +0 -43
  351. package/dist/internal/stable-digest.d.ts.map +1 -1
  352. package/dist/internal/typed.d.ts +0 -8
  353. package/dist/internal/typed.d.ts.map +1 -1
  354. package/dist/internal/zod-issues.d.ts +38 -0
  355. package/dist/internal/zod-issues.d.ts.map +1 -0
  356. package/dist/{tools/json-schema-dialect.d.ts → json-schema/dialect.d.ts} +1 -1
  357. package/dist/json-schema/dialect.d.ts.map +1 -0
  358. package/dist/json-schema/json-schema.d.ts.map +1 -0
  359. package/dist/live/watch-delta.d.ts.map +1 -1
  360. package/dist/{oauth.d.ts → oauth/authorization-code.d.ts} +1 -1
  361. package/dist/oauth/authorization-code.d.ts.map +1 -0
  362. package/dist/observability/audit.d.ts +2 -2
  363. package/dist/observability/audit.d.ts.map +1 -1
  364. package/dist/observability/bounded-logger.d.ts +1 -1
  365. package/dist/observability/bounded-logger.d.ts.map +1 -1
  366. package/dist/{internal/observability-sink.d.ts → observability/bounded-sink.d.ts} +2 -2
  367. package/dist/observability/bounded-sink.d.ts.map +1 -0
  368. package/dist/observability/context.d.ts +1 -1
  369. package/dist/observability/context.d.ts.map +1 -1
  370. package/dist/observability/event.d.ts +1 -1
  371. package/dist/observability/event.d.ts.map +1 -1
  372. package/dist/observability/work.d.ts +1 -1
  373. package/dist/observability/work.d.ts.map +1 -1
  374. package/dist/primitives/audit.d.ts +1 -1
  375. package/dist/primitives/audit.d.ts.map +1 -1
  376. package/dist/primitives/export-operation.d.ts +4 -2
  377. package/dist/primitives/export-operation.d.ts.map +1 -1
  378. package/dist/realtime/socket.d.ts +1 -1
  379. package/dist/realtime/socket.d.ts.map +1 -1
  380. package/dist/server/context-contribution.d.ts +1 -1
  381. package/dist/server/context-contribution.d.ts.map +1 -1
  382. package/dist/server/context.d.ts +2 -2
  383. package/dist/server/context.d.ts.map +1 -1
  384. package/dist/server/contract-method.d.ts +15 -0
  385. package/dist/server/contract-method.d.ts.map +1 -0
  386. package/dist/server/contract-stream.d.ts +1 -1
  387. package/dist/server/contract-stream.d.ts.map +1 -1
  388. package/dist/server/create.d.ts +8 -0
  389. package/dist/server/create.d.ts.map +1 -1
  390. package/dist/server/endpoint-dispatch.d.ts +10 -0
  391. package/dist/server/endpoint-dispatch.d.ts.map +1 -0
  392. package/dist/server/endpoint-response.d.ts +18 -0
  393. package/dist/server/endpoint-response.d.ts.map +1 -0
  394. package/dist/server/error-dispatch.d.ts +17 -1
  395. package/dist/server/error-dispatch.d.ts.map +1 -1
  396. package/dist/server/error-hook.d.ts +2 -2
  397. package/dist/server/error-hook.d.ts.map +1 -1
  398. package/dist/server/handler-state.d.ts +44 -0
  399. package/dist/server/handler-state.d.ts.map +1 -0
  400. package/dist/server/implement.d.ts +1 -1
  401. package/dist/server/implement.d.ts.map +1 -1
  402. package/dist/server/middleware/auth.d.ts +1 -1
  403. package/dist/server/middleware/auth.d.ts.map +1 -1
  404. package/dist/server/middleware/cors.d.ts +17 -0
  405. package/dist/server/middleware/cors.d.ts.map +1 -1
  406. package/dist/server/middleware/trust-fence.d.ts +1 -1
  407. package/dist/server/middleware/trust-fence.d.ts.map +1 -1
  408. package/dist/server/multipart.d.ts +1 -1
  409. package/dist/server/multipart.d.ts.map +1 -1
  410. package/dist/{tools/oauth-metadata.d.ts → server/oauth/metadata.d.ts} +2 -2
  411. package/dist/server/oauth/metadata.d.ts.map +1 -0
  412. package/dist/{tools/oauth-provider.d.ts → server/oauth/provider.d.ts} +2 -2
  413. package/dist/server/oauth/provider.d.ts.map +1 -0
  414. package/dist/server/realtime.d.ts +1 -1
  415. package/dist/server/realtime.d.ts.map +1 -1
  416. package/dist/server/request-completion.d.ts +16 -0
  417. package/dist/server/request-completion.d.ts.map +1 -0
  418. package/dist/server/response-metadata.d.ts +1 -1
  419. package/dist/server/response-metadata.d.ts.map +1 -1
  420. package/dist/server/route-table.d.ts +9 -0
  421. package/dist/server/route-table.d.ts.map +1 -0
  422. package/dist/server/stream.d.ts +0 -13
  423. package/dist/server/stream.d.ts.map +1 -1
  424. package/dist/server/types.d.ts +7 -4
  425. package/dist/server/types.d.ts.map +1 -1
  426. package/dist/testing/handler-clients.d.ts +31 -0
  427. package/dist/testing/handler-clients.d.ts.map +1 -0
  428. package/dist/testing/managed-resource-conformance-scenarios.d.ts.map +1 -1
  429. package/dist/testing/surface-conformance.d.ts +2 -1
  430. package/dist/testing/surface-conformance.d.ts.map +1 -1
  431. package/dist/testing/surface-manifest.d.ts +64 -5
  432. package/dist/testing/surface-manifest.d.ts.map +1 -1
  433. package/dist/tools/{cli-args.d.ts → cli/args.d.ts} +1 -1
  434. package/dist/tools/cli/args.d.ts.map +1 -0
  435. package/dist/tools/{cli-checkpoint.d.ts → cli/checkpoint.d.ts} +1 -1
  436. package/dist/tools/cli/checkpoint.d.ts.map +1 -0
  437. package/dist/tools/{cli-command.d.ts → cli/command.d.ts} +22 -4
  438. package/dist/tools/cli/command.d.ts.map +1 -0
  439. package/dist/tools/{cli.d.ts → cli/config.d.ts} +5 -12
  440. package/dist/tools/cli/config.d.ts.map +1 -0
  441. package/dist/tools/cli/create-cli.d.ts +36 -0
  442. package/dist/tools/cli/create-cli.d.ts.map +1 -0
  443. package/dist/tools/cli/download.d.ts +8 -0
  444. package/dist/tools/cli/download.d.ts.map +1 -0
  445. package/dist/tools/{cli-format.d.ts → cli/format.d.ts} +2 -2
  446. package/dist/tools/cli/format.d.ts.map +1 -0
  447. package/dist/tools/cli/help.d.ts +24 -0
  448. package/dist/tools/cli/help.d.ts.map +1 -0
  449. package/dist/tools/{cli-installer.d.ts → cli/installer.d.ts} +2 -2
  450. package/dist/tools/cli/installer.d.ts.map +1 -0
  451. package/dist/tools/{cli-invoke.d.ts → cli/invoke.d.ts} +35 -10
  452. package/dist/tools/cli/invoke.d.ts.map +1 -0
  453. package/dist/tools/cli/io.d.ts +10 -0
  454. package/dist/tools/cli/io.d.ts.map +1 -0
  455. package/dist/tools/cli/managed-surface.d.ts +30 -0
  456. package/dist/tools/cli/managed-surface.d.ts.map +1 -0
  457. package/dist/tools/{cli-manifest.d.ts → cli/manifest.d.ts} +1 -1
  458. package/dist/tools/cli/manifest.d.ts.map +1 -0
  459. package/dist/tools/{cli-policy.d.ts → cli/policy.d.ts} +2 -2
  460. package/dist/tools/cli/policy.d.ts.map +1 -0
  461. package/dist/tools/cli/prepare.d.ts +14 -0
  462. package/dist/tools/cli/prepare.d.ts.map +1 -0
  463. package/dist/tools/{cli-profile.d.ts → cli/profile.d.ts} +2 -2
  464. package/dist/tools/cli/profile.d.ts.map +1 -0
  465. package/dist/tools/cli/run-managed.d.ts +5 -0
  466. package/dist/tools/cli/run-managed.d.ts.map +1 -0
  467. package/dist/tools/cli/run-native.d.ts +9 -0
  468. package/dist/tools/cli/run-native.d.ts.map +1 -0
  469. package/dist/tools/cli/session.d.ts +40 -0
  470. package/dist/tools/cli/session.d.ts.map +1 -0
  471. package/dist/tools/{cli-signature.d.ts → cli/signature.d.ts} +2 -2
  472. package/dist/tools/cli/signature.d.ts.map +1 -0
  473. package/dist/tools/{cli-stream.d.ts → cli/stream.d.ts} +4 -4
  474. package/dist/tools/cli/stream.d.ts.map +1 -0
  475. package/dist/tools/{cli-update.d.ts → cli/update.d.ts} +3 -3
  476. package/dist/tools/cli/update.d.ts.map +1 -0
  477. package/dist/tools/{cli-view.d.ts → cli/view.d.ts} +2 -2
  478. package/dist/tools/cli/view.d.ts.map +1 -0
  479. package/dist/tools/{cli-wait.d.ts → cli/wait.d.ts} +2 -2
  480. package/dist/tools/cli/wait.d.ts.map +1 -0
  481. package/dist/tools/connections/runtime.d.ts +1 -1
  482. package/dist/tools/connections/runtime.d.ts.map +1 -1
  483. package/dist/tools/connections/types.d.ts +3 -3
  484. package/dist/tools/connections/types.d.ts.map +1 -1
  485. package/dist/tools/durability-context.d.ts +1 -1
  486. package/dist/tools/durability-context.d.ts.map +1 -1
  487. package/dist/tools/execute.d.ts +30 -3
  488. package/dist/tools/execute.d.ts.map +1 -1
  489. package/dist/tools/internal/surface-projector.d.ts +8 -6
  490. package/dist/tools/internal/surface-projector.d.ts.map +1 -1
  491. package/dist/tools/internal/tool-view.d.ts +41 -0
  492. package/dist/tools/internal/tool-view.d.ts.map +1 -0
  493. package/dist/tools/invoker.d.ts +11 -3
  494. package/dist/tools/invoker.d.ts.map +1 -1
  495. package/dist/tools/list-names.d.ts +3 -3
  496. package/dist/tools/list-names.d.ts.map +1 -1
  497. package/dist/tools/manifest.d.ts +2 -2
  498. package/dist/tools/manifest.d.ts.map +1 -1
  499. package/dist/tools/{mcp-app.d.ts → mcp/app.d.ts} +1 -1
  500. package/dist/tools/mcp/app.d.ts.map +1 -0
  501. package/dist/tools/{mcp-catalog.d.ts → mcp/catalog.d.ts} +2 -2
  502. package/dist/tools/mcp/catalog.d.ts.map +1 -0
  503. package/dist/tools/{mcp-handler.d.ts → mcp/handler.d.ts} +5 -5
  504. package/dist/tools/mcp/handler.d.ts.map +1 -0
  505. package/dist/tools/{mcp.d.ts → mcp/mount.d.ts} +9 -9
  506. package/dist/tools/mcp/mount.d.ts.map +1 -0
  507. package/dist/tools/{mcp-prepare.d.ts → mcp/prepare.d.ts} +9 -9
  508. package/dist/tools/mcp/prepare.d.ts.map +1 -0
  509. package/dist/tools/{mcp-progress.d.ts → mcp/progress.d.ts} +2 -2
  510. package/dist/tools/mcp/progress.d.ts.map +1 -0
  511. package/dist/tools/mcp/register.d.ts +35 -0
  512. package/dist/tools/mcp/register.d.ts.map +1 -0
  513. package/dist/tools/{mcp-round-policy.d.ts → mcp/round-policy.d.ts} +2 -2
  514. package/dist/tools/mcp/round-policy.d.ts.map +1 -0
  515. package/dist/tools/{mcp-round.d.ts → mcp/round.d.ts} +4 -4
  516. package/dist/tools/mcp/round.d.ts.map +1 -0
  517. package/dist/tools/mcp/runtime-tools.d.ts +24 -0
  518. package/dist/tools/mcp/runtime-tools.d.ts.map +1 -0
  519. package/dist/tools/{mcp-stdio-signals.d.ts → mcp/stdio-signals.d.ts} +3 -3
  520. package/dist/tools/mcp/stdio-signals.d.ts.map +1 -0
  521. package/dist/tools/{mcp-stdio.d.ts → mcp/stdio.d.ts} +4 -4
  522. package/dist/tools/mcp/stdio.d.ts.map +1 -0
  523. package/dist/tools/{mcp-trace.d.ts → mcp/trace.d.ts} +1 -1
  524. package/dist/tools/mcp/trace.d.ts.map +1 -0
  525. package/dist/tools/mount.d.ts +12 -7
  526. package/dist/tools/mount.d.ts.map +1 -1
  527. package/dist/tools/native-definition.d.ts +3 -3
  528. package/dist/tools/native-definition.d.ts.map +1 -1
  529. package/dist/tools/operations/async-operation-binding-types.d.ts +127 -0
  530. package/dist/tools/operations/async-operation-binding-types.d.ts.map +1 -0
  531. package/dist/tools/operations/async-operation-binding.d.ts +28 -0
  532. package/dist/tools/operations/async-operation-binding.d.ts.map +1 -0
  533. package/dist/tools/operations/async-operation-canonical-types.d.ts +110 -0
  534. package/dist/tools/operations/async-operation-canonical-types.d.ts.map +1 -0
  535. package/dist/tools/operations/async-operation-canonical.d.ts +7 -0
  536. package/dist/tools/operations/async-operation-canonical.d.ts.map +1 -0
  537. package/dist/tools/operations/async-operation-contract.d.ts.map +1 -0
  538. package/dist/tools/operations/async-operation-id.d.ts +23 -0
  539. package/dist/tools/operations/async-operation-id.d.ts.map +1 -0
  540. package/dist/tools/operations/async-operation-runtime-tools.d.ts +40 -0
  541. package/dist/tools/operations/async-operation-runtime-tools.d.ts.map +1 -0
  542. package/dist/tools/operations/async-operation-runtime-types.d.ts +68 -0
  543. package/dist/tools/operations/async-operation-runtime-types.d.ts.map +1 -0
  544. package/dist/tools/operations/async-operation-runtime.d.ts +5 -0
  545. package/dist/tools/operations/async-operation-runtime.d.ts.map +1 -0
  546. package/dist/tools/{define-wait-tool.d.ts → operations/define-wait-tool.d.ts} +2 -2
  547. package/dist/tools/operations/define-wait-tool.d.ts.map +1 -0
  548. package/dist/tools/operations/mount-wait.d.ts.map +1 -0
  549. package/dist/tools/operations/wait-core.d.ts.map +1 -0
  550. package/dist/tools/remote.d.ts +1 -1
  551. package/dist/tools/remote.d.ts.map +1 -1
  552. package/dist/tools/runtime-tool.d.ts +11 -4
  553. package/dist/tools/runtime-tool.d.ts.map +1 -1
  554. package/dist/tools/schema/coerce.d.ts.map +1 -0
  555. package/dist/tools/schema/flatten-join.d.ts.map +1 -0
  556. package/dist/tools/schema/flatten.d.ts.map +1 -0
  557. package/dist/tools/schema/portable-formats.d.ts.map +1 -0
  558. package/dist/tools/{presentation.d.ts → schema/presentation.d.ts} +2 -0
  559. package/dist/tools/schema/presentation.d.ts.map +1 -0
  560. package/dist/tools/schema/schema.d.ts.map +1 -0
  561. package/dist/tools/schema/untyped-properties.d.ts.map +1 -0
  562. package/dist/tools/surface.d.ts +2 -3
  563. package/dist/tools/surface.d.ts.map +1 -1
  564. package/dist/tools/toolkit.d.ts +4 -4
  565. package/dist/tools/toolkit.d.ts.map +1 -1
  566. package/dist/tools/{define-download-tool.d.ts → transfer/define-download-tool.d.ts} +4 -4
  567. package/dist/tools/transfer/define-download-tool.d.ts.map +1 -0
  568. package/dist/tools/{define-upload-tool.d.ts → transfer/define-upload-tool.d.ts} +3 -3
  569. package/dist/tools/transfer/define-upload-tool.d.ts.map +1 -0
  570. package/dist/tools/{define-view-file-tool.d.ts → transfer/define-view-file-tool.d.ts} +2 -2
  571. package/dist/tools/transfer/define-view-file-tool.d.ts.map +1 -0
  572. package/dist/tools/{download-core.d.ts → transfer/download-core.d.ts} +2 -2
  573. package/dist/tools/transfer/download-core.d.ts.map +1 -0
  574. package/dist/tools/{managed-file-error.d.ts → transfer/managed-file-error.d.ts} +1 -1
  575. package/dist/tools/transfer/managed-file-error.d.ts.map +1 -0
  576. package/dist/tools/{mount-download.d.ts → transfer/mount-download.d.ts} +1 -1
  577. package/dist/tools/transfer/mount-download.d.ts.map +1 -0
  578. package/dist/tools/{mount-upload.d.ts → transfer/mount-upload.d.ts} +1 -1
  579. package/dist/tools/transfer/mount-upload.d.ts.map +1 -0
  580. package/dist/tools/transfer/native-result.d.ts.map +1 -0
  581. package/dist/tools/{upload-core.d.ts → transfer/upload-core.d.ts} +1 -1
  582. package/dist/tools/transfer/upload-core.d.ts.map +1 -0
  583. package/dist/tools/transfer/view-file-contract.d.ts.map +1 -0
  584. package/dist/tools/{view-file.d.ts → transfer/view-file.d.ts} +1 -1
  585. package/dist/tools/transfer/view-file.d.ts.map +1 -0
  586. package/dist/tools/transports.d.ts +1 -1
  587. package/dist/tools/transports.d.ts.map +1 -1
  588. package/dist/tracking/contract.d.ts +1 -1
  589. package/dist/tracking/contract.d.ts.map +1 -1
  590. package/llms/agent-runtime-browser.txt +33 -0
  591. package/llms/agent-runtime-coding-tools.txt +58 -0
  592. package/llms/agent-runtime-harness.txt +45 -0
  593. package/llms/agent-runtime-openrouter.txt +22 -0
  594. package/llms/agent-runtime-sandbox.txt +159 -0
  595. package/llms/agent-runtime-sqlite-bun.txt +29 -0
  596. package/llms/agent-runtime-sqlite-node.txt +26 -0
  597. package/llms/agent-runtime-testing.txt +30 -0
  598. package/llms/agent-runtime.2.txt +550 -0
  599. package/llms/agent-runtime.3.txt +311 -0
  600. package/llms/agent-runtime.txt +893 -0
  601. package/llms/application-diagnostic-journal.txt +30 -0
  602. package/llms/application-grammy.txt +27 -0
  603. package/llms/application-opentelemetry.txt +27 -0
  604. package/llms/application-schemas.txt +42 -0
  605. package/llms/application.2.txt +223 -0
  606. package/llms/application.txt +1144 -0
  607. package/llms/cli.txt +977 -0
  608. package/llms/contract.txt +606 -0
  609. package/llms/declaration.txt +286 -0
  610. package/llms/files.txt +30 -0
  611. package/llms/geo.txt +114 -0
  612. package/llms/google.txt +27 -0
  613. package/llms/live.txt +471 -0
  614. package/llms/node.txt +43 -0
  615. package/llms/oauth.txt +136 -0
  616. package/llms/observability.txt +893 -0
  617. package/llms/primitives.txt +158 -0
  618. package/llms/react.txt +184 -0
  619. package/llms/release.txt +176 -0
  620. package/llms/remote.txt +25 -0
  621. package/llms/server.2.txt +361 -0
  622. package/llms/server.3.txt +1031 -0
  623. package/llms/server.4.txt +905 -0
  624. package/llms/server.5.txt +250 -0
  625. package/llms/server.txt +996 -0
  626. package/llms/stitchkit.2.txt +836 -0
  627. package/llms/stitchkit.3.txt +147 -0
  628. package/llms/stitchkit.txt +260 -0
  629. package/llms/telegram.txt +30 -0
  630. package/llms/testing.txt +676 -0
  631. package/llms/tools-connections.txt +45 -0
  632. package/llms/tools-contract.txt +9 -0
  633. package/llms/tools-invoker.txt +9 -0
  634. package/llms/tools.2.txt +838 -0
  635. package/llms/tools.txt +1004 -0
  636. package/llms/tracking-server.txt +32 -0
  637. package/llms/tracking.txt +263 -0
  638. package/llms/upgrading-0.37.0-0.50.0.txt +947 -0
  639. package/llms/upgrading-0.53.0-0.67.0.txt +1174 -0
  640. package/llms/upgrading-0.68.0-0.94.0.txt +1159 -0
  641. package/llms/upgrading.txt +215 -0
  642. package/llms-full.txt +305 -75
  643. package/llms.txt +54 -5
  644. package/package.json +84 -83
  645. package/dist/agent-runtime/durability-contract.d.ts.map +0 -1
  646. package/dist/agent-runtime/durability-json.d.ts.map +0 -1
  647. package/dist/agent-runtime/durability-ledger.d.ts.map +0 -1
  648. package/dist/agent-runtime/durability-scheduler.d.ts.map +0 -1
  649. package/dist/agent-runtime/durability.d.ts.map +0 -1
  650. package/dist/agent-runtime/store-driver.d.ts.map +0 -1
  651. package/dist/agent-runtime-browser.d.ts +0 -5
  652. package/dist/agent-runtime-browser.d.ts.map +0 -1
  653. package/dist/agent-runtime-coding-tools.d.ts.map +0 -1
  654. package/dist/agent-runtime-coding-tools.js +0 -23
  655. package/dist/agent-runtime-harness.d.ts.map +0 -1
  656. package/dist/agent-runtime-openrouter.d.ts.map +0 -1
  657. package/dist/agent-runtime-sandbox.d.ts.map +0 -1
  658. package/dist/agent-runtime-sqlite-bun.d.ts.map +0 -1
  659. package/dist/agent-runtime-sqlite-node.d.ts.map +0 -1
  660. package/dist/agent-runtime-testing.d.ts +0 -3
  661. package/dist/agent-runtime-testing.d.ts.map +0 -1
  662. package/dist/agent-runtime-testing.js +0 -156
  663. package/dist/agent-runtime.d.ts.map +0 -1
  664. package/dist/application/channel.d.ts.map +0 -1
  665. package/dist/application-diagnostic-journal.d.ts.map +0 -1
  666. package/dist/application-grammy.d.ts.map +0 -1
  667. package/dist/application-opentelemetry.d.ts.map +0 -1
  668. package/dist/application-schemas.d.ts.map +0 -1
  669. package/dist/application.d.ts.map +0 -1
  670. package/dist/cli.d.ts.map +0 -1
  671. package/dist/contract/index.d.ts +0 -8
  672. package/dist/contract/index.d.ts.map +0 -1
  673. package/dist/declaration.d.ts.map +0 -1
  674. package/dist/files.d.ts.map +0 -1
  675. package/dist/geo.d.ts.map +0 -1
  676. package/dist/google.d.ts.map +0 -1
  677. package/dist/index-0j3vcp5m.js +0 -28
  678. package/dist/index-a11g2kry.js +0 -866
  679. package/dist/index-cnyk6te3.js +0 -77
  680. package/dist/index-fadnxwna.js +0 -1046
  681. package/dist/index-hrbajay7.js +0 -1196
  682. package/dist/index-s8cnx02s.js +0 -90
  683. package/dist/index-v5573g1k.js +0 -142
  684. package/dist/index-vk3kq9sb.js +0 -3344
  685. package/dist/index.d.ts.map +0 -1
  686. package/dist/internal/errors.d.ts.map +0 -1
  687. package/dist/internal/observability-sink.d.ts.map +0 -1
  688. package/dist/live.d.ts.map +0 -1
  689. package/dist/logger.d.ts.map +0 -1
  690. package/dist/node.d.ts.map +0 -1
  691. package/dist/oauth.d.ts.map +0 -1
  692. package/dist/observability/index.d.ts.map +0 -1
  693. package/dist/primitives.d.ts +0 -3
  694. package/dist/primitives.d.ts.map +0 -1
  695. package/dist/react.d.ts.map +0 -1
  696. package/dist/release.d.ts.map +0 -1
  697. package/dist/remote.d.ts.map +0 -1
  698. package/dist/remote.js +0 -88
  699. package/dist/retained.d.ts.map +0 -1
  700. package/dist/server/file-state-store.d.ts.map +0 -1
  701. package/dist/server/index.d.ts.map +0 -1
  702. package/dist/server/request.d.ts.map +0 -1
  703. package/dist/telegram.d.ts.map +0 -1
  704. package/dist/testing/agent-store-conformance.d.ts.map +0 -1
  705. package/dist/testing.d.ts +0 -39
  706. package/dist/testing.d.ts.map +0 -1
  707. package/dist/tool-invoker.d.ts.map +0 -1
  708. package/dist/tool-invoker.js +0 -21
  709. package/dist/tools/async-operation-contract.d.ts.map +0 -1
  710. package/dist/tools/async-operation.d.ts +0 -332
  711. package/dist/tools/async-operation.d.ts.map +0 -1
  712. package/dist/tools/cli-args.d.ts.map +0 -1
  713. package/dist/tools/cli-checkpoint.d.ts.map +0 -1
  714. package/dist/tools/cli-command.d.ts.map +0 -1
  715. package/dist/tools/cli-format.d.ts.map +0 -1
  716. package/dist/tools/cli-installer.d.ts.map +0 -1
  717. package/dist/tools/cli-invoke.d.ts.map +0 -1
  718. package/dist/tools/cli-manifest.d.ts.map +0 -1
  719. package/dist/tools/cli-policy.d.ts.map +0 -1
  720. package/dist/tools/cli-profile.d.ts.map +0 -1
  721. package/dist/tools/cli-signature.d.ts.map +0 -1
  722. package/dist/tools/cli-stream.d.ts.map +0 -1
  723. package/dist/tools/cli-update.d.ts.map +0 -1
  724. package/dist/tools/cli-view.d.ts.map +0 -1
  725. package/dist/tools/cli-wait.d.ts.map +0 -1
  726. package/dist/tools/cli.d.ts.map +0 -1
  727. package/dist/tools/coerce.d.ts.map +0 -1
  728. package/dist/tools/connections/index.d.ts.map +0 -1
  729. package/dist/tools/define-download-tool.d.ts.map +0 -1
  730. package/dist/tools/define-upload-tool.d.ts.map +0 -1
  731. package/dist/tools/define-view-file-tool.d.ts.map +0 -1
  732. package/dist/tools/define-wait-tool.d.ts.map +0 -1
  733. package/dist/tools/download-core.d.ts.map +0 -1
  734. package/dist/tools/flatten-join.d.ts.map +0 -1
  735. package/dist/tools/flatten.d.ts.map +0 -1
  736. package/dist/tools/json-schema-dialect.d.ts.map +0 -1
  737. package/dist/tools/json-schema.d.ts.map +0 -1
  738. package/dist/tools/managed-file-error.d.ts.map +0 -1
  739. package/dist/tools/mcp-app.d.ts.map +0 -1
  740. package/dist/tools/mcp-catalog.d.ts.map +0 -1
  741. package/dist/tools/mcp-handler.d.ts.map +0 -1
  742. package/dist/tools/mcp-prepare.d.ts.map +0 -1
  743. package/dist/tools/mcp-progress.d.ts.map +0 -1
  744. package/dist/tools/mcp-round-policy.d.ts.map +0 -1
  745. package/dist/tools/mcp-round.d.ts.map +0 -1
  746. package/dist/tools/mcp-stdio-signals.d.ts.map +0 -1
  747. package/dist/tools/mcp-stdio.d.ts.map +0 -1
  748. package/dist/tools/mcp-trace.d.ts.map +0 -1
  749. package/dist/tools/mcp.d.ts.map +0 -1
  750. package/dist/tools/mount-download.d.ts.map +0 -1
  751. package/dist/tools/mount-upload.d.ts.map +0 -1
  752. package/dist/tools/mount-wait.d.ts.map +0 -1
  753. package/dist/tools/native-mcp.d.ts +0 -20
  754. package/dist/tools/native-mcp.d.ts.map +0 -1
  755. package/dist/tools/native-result.d.ts.map +0 -1
  756. package/dist/tools/oauth-metadata.d.ts.map +0 -1
  757. package/dist/tools/oauth-provider.d.ts.map +0 -1
  758. package/dist/tools/portable-formats.d.ts.map +0 -1
  759. package/dist/tools/presentation.d.ts.map +0 -1
  760. package/dist/tools/schema.d.ts.map +0 -1
  761. package/dist/tools/untyped-properties.d.ts.map +0 -1
  762. package/dist/tools/upload-core.d.ts.map +0 -1
  763. package/dist/tools/view-file-contract.d.ts.map +0 -1
  764. package/dist/tools/view-file.d.ts.map +0 -1
  765. package/dist/tools/wait-core.d.ts.map +0 -1
  766. package/dist/tools-contract.d.ts.map +0 -1
  767. package/dist/tools.d.ts +0 -50
  768. package/dist/tools.d.ts.map +0 -1
  769. package/dist/tracking-server.d.ts.map +0 -1
  770. package/dist/tracking.d.ts.map +0 -1
  771. package/dist/upgrade-cli.d.ts.map +0 -1
  772. package/dist/{retained.d.ts → browser/retained.d.ts} +0 -0
  773. package/dist/{declaration.d.ts → declaration/declaration.d.ts} +0 -0
  774. package/dist/{upgrade-cli.d.ts → entrypoints/bin/upgrade-cli.d.ts} +0 -0
  775. package/dist/{tracking-server.js → entrypoints/tracking/server.js} +0 -0
  776. package/dist/{google.d.ts → google/google.d.ts} +0 -0
  777. package/dist/{index-pq95qkbf.js → index-5jm36zv1.js} +0 -0
  778. package/dist/{index-actkayzn.js → index-70yj2ebz.js} +3 -3
  779. /package/dist/{application → internal}/channel.d.ts +0 -0
  780. /package/dist/{logger.d.ts → internal/logger.d.ts} +0 -0
  781. /package/dist/{server → internal}/request.d.ts +0 -0
  782. /package/dist/{tools → json-schema}/json-schema.d.ts +0 -0
  783. /package/dist/tools/{async-operation-contract.d.ts → operations/async-operation-contract.d.ts} +0 -0
  784. /package/dist/tools/{mount-wait.d.ts → operations/mount-wait.d.ts} +0 -0
  785. /package/dist/tools/{wait-core.d.ts → operations/wait-core.d.ts} +0 -0
  786. /package/dist/tools/{coerce.d.ts → schema/coerce.d.ts} +0 -0
  787. /package/dist/tools/{flatten-join.d.ts → schema/flatten-join.d.ts} +0 -0
  788. /package/dist/tools/{flatten.d.ts → schema/flatten.d.ts} +0 -0
  789. /package/dist/tools/{portable-formats.d.ts → schema/portable-formats.d.ts} +0 -0
  790. /package/dist/tools/{schema.d.ts → schema/schema.d.ts} +0 -0
  791. /package/dist/tools/{untyped-properties.d.ts → schema/untyped-properties.d.ts} +0 -0
  792. /package/dist/tools/{native-result.d.ts → transfer/native-result.d.ts} +0 -0
  793. /package/dist/tools/{view-file-contract.d.ts → transfer/view-file-contract.d.ts} +0 -0
@@ -0,0 +1,996 @@
1
+ # stitchkit/server — stitchkit docs slice, part 1 of 5
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
+ > Continues in `llms/server.2.txt`.
6
+
7
+ Parts of this slice:
8
+ - `llms/server.txt`: Guide: HTTP server (docs/guide/server.md)
9
+ - `llms/server.2.txt`: Guide: HTTP server (docs/guide/server.md)
10
+ - `llms/server.3.txt`: Guide: Realtime (docs/guide/realtime.md)
11
+ - `llms/server.4.txt`: Guide: Auth & errors (docs/guide/auth-and-errors.md) · Guide: Multi-tenant (docs/guide/multi-tenant.md)
12
+ - `llms/server.5.txt`: API reference: `stitchkit/server` (docs/api/reference.md)
13
+
14
+ Also read:
15
+ - see `llms/testing.txt` for the Testing & deployment guide
16
+
17
+ ==============================================================================
18
+ # Guide: HTTP server (docs/guide/server.md)
19
+ ==============================================================================
20
+
21
+ # HTTP server
22
+
23
+ stitchkit serves contracts on `Bun.serve()` directly — no Hono, no Elysia, no
24
+ Express. You bind a contract to handlers with `implement()`, then mount the
25
+ result on `createServer()`.
26
+
27
+ ## `implement`
28
+
29
+ `implement(contract, handlers)` type-checks each handler against its endpoint's
30
+ schemas and returns a `ServiceDef` to mount.
31
+
32
+ ```ts
33
+ import { implement } from 'stitchkit/server'
34
+ import { users } from '../shared/contracts'
35
+
36
+ const usersService = implement(users, {
37
+ list: () => db.users.findMany(),
38
+ create: (ctx) => db.users.create(ctx.input), // ctx.input: typed
39
+ get: (ctx) => db.users.findById(ctx.params.id), // ctx.params: typed
40
+ delete: (ctx) => db.users.delete(ctx.params.id),
41
+ })
42
+ ```
43
+
44
+ A handler may be sync or async. Its return value is checked against the
45
+ endpoint's `output` schema; an endpoint without `output` returns nothing.
46
+
47
+ ### The handler context
48
+
49
+ Every handler receives one `ctx` argument:
50
+
51
+ | `ctx` field | Type | Source |
52
+ |-------------|------|--------|
53
+ | `params` | inferred from `params` schema | parsed path params |
54
+ | `input` | inferred from `input` schema | parsed body / query |
55
+ | `files` | inferred `File` map or receiver values | the endpoint's typed multipart fields |
56
+ | `source` | `'http' \| 'mcp' \| 'agent'` | the transport that invoked the handler |
57
+ | `traceId` | `string` | per-request trace id |
58
+ | `ipAddress` | `string` | caller IP |
59
+ | `userAgent` | `string` | caller user-agent |
60
+
61
+ The same handler runs for HTTP, MCP and agent calls — `ctx.source` tells you
62
+ which. Anything an auth hook attaches (e.g. the resolved user) is also on `ctx`.
63
+
64
+ ### `createImplement` — a fixed context type
65
+
66
+ To type `ctx` with your app's extras (the user an auth hook injects), fix the
67
+ context type once:
68
+
69
+ ```ts
70
+ import { createImplement } from 'stitchkit/server'
71
+
72
+ interface AppContext extends RuntimeContext { user: User | null }
73
+
74
+ export const implement = createImplement<AppContext>()
75
+ // every implement() call now has ctx.user typed
76
+ ```
77
+
78
+ ### Per-scope handler context — `createScopedImplement`
79
+
80
+ `createImplement<Ctx>()` gives every handler the **same** context type. In an app
81
+ where each scope guarantees different injected fields, that single type is a
82
+ superset: a `public` handler is told it has a `userId` the runtime never injects
83
+ there. `createScopedImplement` types each handler by its endpoint's **effective**
84
+ scope instead — the endpoint's own `scope`, else the contract's:
85
+
86
+ ```ts
87
+ import { createScopedImplement } from 'stitchkit/server'
88
+
89
+ export const implementFor = createScopedImplement<{
90
+ public: object // no extra fields
91
+ user: { userId: string }
92
+ admin: { userId: string; isAdmin: boolean }
93
+ }>()
94
+
95
+ implementFor(postsContract, {
96
+ list: (ctx) => listPosts(ctx.userId), // contract scope 'user'
97
+ purge: (ctx) => (ctx.isAdmin ? purge() : []), // endpoint scope 'admin'
98
+ ping: () => ({ ok: true }), // endpoint scope 'public'
99
+ })
100
+ ```
101
+
102
+ The map is **type-only** — scope fields are types, so there is no runtime
103
+ argument and no `{} as UserFields` at the call site. `'public'` must be a key:
104
+ a contract without a `scope` is `'public'`. A scope outside the map is a compile
105
+ error on that endpoint, naming the scope.
106
+
107
+ Three boundaries worth knowing:
108
+
109
+ - A field of another scope is not a compile error on access — `RuntimeContext`
110
+ keeps its `[key: string]: unknown` index signature (transports write through
111
+ it). It degrades to `unknown`, so it can no longer pose as a `string`; using it
112
+ in a typed position fails.
113
+ - The map states what **your** `beforeHandle` / `createAuthHook.inject` puts on
114
+ the context. The framework does not verify a hand-written claim (→ ADR 0075) —
115
+ so prefer not to write one: scoped auth rules declare their contribution by
116
+ performing it, and `createScopedImplement<AuthScopes<typeof hook>>()` derives
117
+ the map from the hook
118
+ ([details](./auth-and-errors.md#scoped-rules--the-map-createscopedimplement-consumes),
119
+ → ADR 0078).
120
+ - An endpoint hoisted out of the contract literal widens its `scope` to `string`,
121
+ which is no key of any map, and lands in the error branch. An endpoint whose
122
+ `scope` is added by a conditional spread is optional, so it resolves to **both**
123
+ scopes and is typed against what they guarantee in common. Write endpoints
124
+ inline for the precise type.
125
+ - Scope keys are string literals. A map declared as an index signature
126
+ (`Record<string, …>`) makes every scope valid and disables the check.
127
+
128
+ The same map has a registry form and a streaming form:
129
+
130
+ ```ts
131
+ // one contract registry, handlers still typed per endpoint scope
132
+ const implementAll = createScopedImplementRegistry<Scopes>()
133
+ export const services = implementAll(apiContractRegistry, { posts, users })
134
+
135
+ // a service FILE declares its handlers typed but unbound — binding happens
136
+ // once, in the registry. Curried out of necessity: one call cannot both take
137
+ // the contract and contextually infer the handlers from it.
138
+ export const posts = implementFor.declare(postsContract)({
139
+ list: (ctx) => listPosts(ctx.userId), // ctx typed per endpoint scope
140
+ purge: (ctx) => (ctx.isAdmin ? purge() : []),
141
+ })
142
+
143
+ // a streaming multipart handler that reads its scope's fields. The endpoint
144
+ // must declare its own `scope`, and only that literal is accepted: an endpoint
145
+ // inheriting the contract's scope cannot be verified from here, and guessing it
146
+ // would rebuild the superset this factory removes.
147
+ implementFor(mediaContract, {
148
+ upload: implementFor.stream('admin', mediaContract.endpoints.upload, {
149
+ files: { file: receiveFile },
150
+ handler: ({ files, userId }) => store(files.file, userId),
151
+ }),
152
+ })
153
+ ```
154
+
155
+ Outside a scoped app, `createMultipartStream<Ctx>()` does for streaming handlers
156
+ what `createImplement<Ctx>()` does for ordinary ones. Plain
157
+ `defineMultipartStream` still gives the loose `RuntimeContext`.
158
+
159
+ ### `implementRegistry` — one backend registry
160
+
161
+ When contracts already live in one literal registry, bind the backend from that
162
+ same source instead of maintaining a parallel `services` list:
163
+
164
+ ```ts
165
+ import { implementRegistry } from 'stitchkit/server'
166
+
167
+ export const apiServices = implementRegistry(apiContractRegistry, {
168
+ users: usersHandlers,
169
+ posts: postsHandlers,
170
+ })
171
+ ```
172
+
173
+ Every registry key is required, extra keys fail, and each handler map is checked
174
+ against its own contract. The returned service order follows the contract
175
+ registry order — and the same services ride along under `.byKey`, so a consumer
176
+ whose registry keys are load-bearing (filtering a tool surface per caller) never
177
+ rebuilds a prefix lookup by hand:
178
+
179
+ ```ts
180
+ const services = implementRegistry(apiContractRegistry, handlers)
181
+ createServer({ services }) // the array, as before
182
+ const visible = [services.byKey.users] // the same objects, by key
183
+ ```
184
+
185
+ `createImplementRegistry<AppContext>()` fixes the application
186
+ context once, like `createImplement` does for a single contract. Runtime callers
187
+ also fail first on missing/extra keys and on a duplicate prefix **within one
188
+ scope** — the same prefix under two different group scopes is legal (their URLs
189
+ are separated by `scopePrefixes`, and a genuine path clash is the router's own
190
+ construction error).
191
+
192
+ #### A dev stand that survives half a feature — `onMissingHandler`
193
+
194
+ Adding an endpoint is two edits by construction: the contract, then the handler.
195
+ An editor saves one file at a time and a watcher restarts on the first save, so
196
+ between the two the application refuses to start — and on a shared dev stand that
197
+ is everyone's stand, not just yours. A project rule ("make both edits at once")
198
+ cannot outrun the filesystem.
199
+
200
+ ```ts
201
+ implementRegistry(apiContractRegistry, handlers, {
202
+ onMissingHandler: process.env.NODE_ENV === 'production' ? 'throw' : 'stub',
203
+ })
204
+ ```
205
+
206
+ With `'stub'` the application starts, the unimplemented endpoint answers `501` and
207
+ names itself in the log at every mount, so it cannot be forgotten. Both save
208
+ orders are covered: a contract ahead of its handler, and a handler ahead of its
209
+ contract. The option is accepted by `implement`, `implementRegistry`,
210
+ `createImplement`, `createScopedImplement`, `createImplementRegistry` and
211
+ `createScopedImplementRegistry`.
212
+
213
+ Three things it deliberately does not do. It stays `'throw'` by default, and
214
+ `'throw'` is the only right answer in production: a release is atomic, so there is
215
+ no window to protect, and a surface with a hole must not ship. It does not relax
216
+ the **compile-time** exactness check — that lives in the generic constraint, your
217
+ editor still shows the missing handler, and a watcher that only transpiles is
218
+ precisely why the runtime refusal was the one that bit. And it does not stub a
219
+ streaming multipart endpoint, which needs `defineMultipartStream()` receivers; the
220
+ stand still stops on one of those.
221
+
222
+ The stub answers `NOT_IMPLEMENTED` with status `501` everywhere — over HTTP and on
223
+ a tool call that crosses a process boundary alike, because the code is registered
224
+ in `STITCH_ERROR_STATUS`. One consequence follows from that and is worth knowing:
225
+ a stubbed endpoint keeps its `expose`, so on a dev stand it is advertised to a
226
+ model as a real tool that always refuses. The refusal is not retryable, so a model
227
+ stops rather than loops; it still costs one turn to find out.
228
+
229
+ The registry is intentionally flat: every key must point to one concrete
230
+ `defineContract()` result. Composed namespace arrays are mounted explicitly with
231
+ `implement()` because they do not have a one-key-to-one-handler-map boundary.
232
+
233
+ ## `createServer`
234
+
235
+ `createServer(config)` builds the router and starts `Bun.serve()`. It returns a
236
+ managed handle with `url`, `port`, the concrete server under `runtime`, live
237
+ `status`, and one idempotent `shutdown()` lifecycle.
238
+
239
+ ```ts
240
+ import { createServer } from 'stitchkit/server'
241
+
242
+ createServer({
243
+ services: [usersService, postsService],
244
+ port: 3000,
245
+ cors: { origin: 'https://app.example.com' },
246
+ hooks: { /* … */ },
247
+ logging: true,
248
+ })
249
+ ```
250
+
251
+ `createHandler(config)` is the same router as a bare `(req) => Promise<Response>`
252
+ function — no `Bun.serve`. Use it in tests, or to embed stitchkit in another
253
+ server. See [Testing & deployment](./testing-and-deployment.md).
254
+
255
+ ### `ServerConfig`
256
+
257
+ | Field | Purpose |
258
+ |-------|---------|
259
+ | `services` | `ServiceDef[]` mounted at the root |
260
+ | `groups` | route groups — a shared path prefix and hooks (see below) |
261
+ | `scopePrefixes` | `scope → path prefix` map — mount `services` by `service.scope` (see below) |
262
+ | `rawRoutes` | non-contract routes (see below) |
263
+ | `maxJsonBodyBytes` | optional JSON body cap (bytes); per-route value overrides; unset preserves existing behaviour |
264
+ | `port` / `hostname` | listen address — port defaults to `3000` |
265
+ | `unix` | listen on a unix domain socket instead of TCP — `'/run/app.sock'` or `{ path, mode }` (see below) |
266
+ | `cors` | CORS policy — `{ origin, credentials, methods, headers, exposeHeaders }`. `origin` is **required** when `cors` is present: pass an explicit origin (or list), or `'*'` to deliberately allow every origin — an origin-less config is a construction error, never a silent wildcard. Omit `cors` entirely to emit no CORS headers. |
267
+ | `hooks` | lifecycle hooks (see below) |
268
+ | `logging` | `true` for built-in request logs, or a `LoggingConfig` (see below) |
269
+ | `traceId` | override per-request trace-id resolution — may return `undefined` to fall back |
270
+ | `wrapFetch` | compose wrappers around the finished handler (request context, audit) |
271
+ | `socket` | full Stitchkit Socket.IO handle; route, default WebSocket handler and shutdown are mounted once |
272
+ | `websocket` | custom Bun WebSocket handler; with `socket`, this is the explicit composed handler |
273
+ | `development` / `bun` | passthrough to `Bun.serve` |
274
+
275
+ Native Bun `routes` are intentionally not accepted: Bun matches them before
276
+ `fetch`, so they could bypass shutdown admission. Use `rawRoutes`; they retain
277
+ the Fetch `Request → Response` model and participate in lifecycle tracking.
278
+
279
+ ### Local daemon over a unix socket
280
+
281
+ A local daemon whose door is a socket file needs no TCP port at all:
282
+
283
+ ```ts
284
+ const server = createServer({
285
+ services,
286
+ unix: { path: '/run/my-daemon.sock', mode: 0o600 },
287
+ })
288
+ ```
289
+
290
+ `unix` is mutually exclusive with `port`/`hostname` (construction error). The
291
+ handle stays honest: `server.url` is `unix:///run/my-daemon.sock` — an
292
+ identifier, **not** a fetchable address (dial the path with
293
+ `createHttpClient({ unix })`, [client guide](client.md#unix-domain-sockets)) —
294
+ and `server.port` is `0`.
295
+
296
+ Socket-file hygiene is built in. A stale file left by a killed process is
297
+ reclaimed automatically: the path is probed, and only a socket that is owned by
298
+ the current user **and** answers no live listener is removed before binding
299
+ (best-effort — two processes racing the same path resolve through the loud
300
+ bind error of the loser). A regular file at the path, another user's socket, or
301
+ a live listener each fail with a specific error instead of being unlinked. A
302
+ clean `server.shutdown()` removes the file.
303
+
304
+ `mode` tightens the socket file permissions after listen. Bun creates the file
305
+ `0755` under a normal umask — since `connect(2)` requires *write* permission
306
+ that is already owner-only in practice — but when access to the socket **is**
307
+ the credential, set `mode: 0o600` explicitly and let the filesystem be the
308
+ policy. The Socket.IO lifecycle (`socket`) cannot mount on a unix listener
309
+ (socket.io clients dial TCP only — construction error); Bun's own WebSocket
310
+ client cannot dial a unix path either. Unix listeners are Bun-only: `srvx`
311
+ resolves a numeric port unconditionally, so `stitchkit/node` does not offer
312
+ `unix` (no half-support).
313
+
314
+ ### Managed shutdown
315
+
316
+ ```ts
317
+ const server = createServer({ services, socket })
318
+
319
+ const result = await server.shutdown({
320
+ gracePeriodMs: 30_000,
321
+ realtimeCloseTimeoutMs: 1_000,
322
+ forceTimeoutMs: 5_000,
323
+ retryAfterSeconds: 5,
324
+ signal: shutdownController.signal,
325
+ })
326
+ ```
327
+
328
+ The first call closes HTTP and Socket.IO admission and cancels owned contract streams and
329
+ `streamingRoute` / `ndjsonRoute` / `sseRoute` sources. Their supplied `signal` is the lifetime:
330
+ waiting producers must honour it, and their iterator cleanup must finish. No separate application
331
+ abort controller or copied shutdown loop is required. Admitted finite HTTP/application work and
332
+ stream cleanup share the full `gracePeriodMs` budget. Once that work drains, `realtimeCloseTimeoutMs` (default `1_000`)
333
+ bounds WebSocket close handshakes inside the same outer deadline. Any upgraded sockets still open
334
+ at that boundary are terminated without shortening HTTP grace, and graceful runtime shutdown
335
+ continues. If the outer grace budget or external signal forces destructive teardown,
336
+ `forceTimeoutMs` bounds physical completion separately. Repeated calls return the same Promise;
337
+ the first options win. New
338
+ ordinary HTTP work receives `503`, `Retry-After` and `Connection: close` outside
339
+ `wrapFetch`. `result.outcome` is `clean` or `forced`; a forced result preserves
340
+ the pending snapshot and reason while final pending counters describe the
341
+ post-close transport state and any still-owned stream cleanup. A streaming request increments
342
+ `completedRequests` only after its source cleanup settles, not when its `Response` is returned.
343
+ `abortedRequests` counts requests pending at outer force, not subscriptions closed cooperatively
344
+ during grace. `forcedWebSockets` counts both sockets terminated at the dedicated
345
+ realtime bound and sockets terminated by outer force; `pendingWebSocketsAtForce` is only the latter
346
+ snapshot, so a clean result can truthfully report a bounded realtime termination. A graceful phase error still runs forced cleanup and
347
+ then rejects with the original error; a forced transport that cannot confirm
348
+ completion before `forceTimeoutMs` rejects instead of reporting a false zero. An uncooperative
349
+ stream stays pending even if its connection is gone; a cleanup error rejects shutdown.
350
+ Standalone `createHandler` and arbitrary raw `Response` bodies have no managed source ownership:
351
+ their embedding host/producer owns cancellation. Request identity must be retained by `wrapFetch`
352
+ when forwarding to owned streaming routes; it is also required by native timeout/upgrade APIs.
353
+ `runtime` is a diagnostics escape hatch, not a second canonical stop path.
354
+
355
+ ### Trusted HTTPS in development
356
+
357
+ Stitchkit does not own local certificate generation or a frontend development
358
+ server. When a device or browser feature requires a secure context, generate a
359
+ trusted certificate outside the application (for example with `mkcert`) and pass
360
+ its files through the Bun server boundary:
361
+
362
+ ```ts
363
+ import { readFileSync } from 'node:fs'
364
+ import { createServer } from 'stitchkit/server'
365
+
366
+ createServer({
367
+ services,
368
+ hostname: '0.0.0.0',
369
+ bun: {
370
+ tls: {
371
+ cert: readFileSync('./certs/dev.pem'),
372
+ key: readFileSync('./certs/dev-key.pem'),
373
+ },
374
+ },
375
+ })
376
+ ```
377
+
378
+ Trust the certificate authority on each test device and configure the frontend's
379
+ HTTPS mode in that frontend project. Certificate renewal, interface discovery
380
+ and device onboarding remain application infrastructure rather than framework
381
+ or starter behavior.
382
+
383
+ ### Request logging
384
+
385
+ `logging: true` is shorthand for `logging: {}` — **any object turns logging
386
+ on**, and the fields tune it:
387
+
388
+ ```ts
389
+ createServer({
390
+ services,
391
+ logging: {
392
+ // What the built-in formatter writes. Omit it and it follows NODE_ENV.
393
+ format: 'json',
394
+ // Route lines into your stack instead of the built-in formatter.
395
+ logger: myLogger,
396
+ // Silence noise. Runs after the built-in filter (framework assets,
397
+ // favicon, preflights), so it can only quieten more.
398
+ skip: (_req, url) => url.pathname === '/health' || url.pathname.startsWith('/socket.io/'),
399
+ // Extra fields on the completion line.
400
+ enrich: (req, _url, { status }) => ({
401
+ userAgent: req.headers.get('user-agent') ?? undefined,
402
+ cacheable: status === 200,
403
+ }),
404
+ },
405
+ })
406
+ ```
407
+
408
+ ### Two formats, and who chooses
409
+
410
+ | `format` | What it writes | Carries `enrich` / context identity |
411
+ |---|---|---|
412
+ | `'pretty'` | two coloured lines per request — `→` on arrival, `←` on completion | no — a line sized for a terminal is not a record |
413
+ | `'json'` | one structured line per completed request | yes |
414
+
415
+ Status `499` has one framework-wide meaning: the client closed the request. It
416
+ is logged at `info`, not under the ordinary `4xx → warn` rule. A confirmed
417
+ disconnect is not sent through project `onError`, `normalizeError` or the
418
+ request-error recorder; an `AbortError` while the request signal is still active
419
+ remains an internal failure. A runtime abort reason may be preserved by identity
420
+ through at most eight cycle-safe standard `cause` links; error messages and codes
421
+ are never classifiers. The same rule applies when the disconnect happens while
422
+ Stitchkit is reading a JSON upload body: bounded reads race every pending stream
423
+ read against the request signal and never parse a cancelled partial body. `499`
424
+ is transport telemetry, not a response declared in the contract or generated
425
+ OpenAPI document.
426
+
427
+ Unset, `format` follows `NODE_ENV`: `json` under `production`, `pretty`
428
+ otherwise. That default is read **per request** — not at import, not when this
429
+ package was built — so it reflects the environment your app actually runs in.
430
+ Set `format` and the environment stops being consulted at all.
431
+
432
+ **If your project validates its environment through a single door** — a Zod
433
+ schema, `@t3-oss/env-core`, anything of that shape — set `format` explicitly
434
+ from *your* value rather than leaning on the default. The library reads raw
435
+ `process.env`, which is a second source of truth: let the two disagree on one
436
+ deployment and production writes `pretty` without a word.
437
+
438
+ ```ts
439
+ import { env } from '@/config'
440
+ createServer({ services, logging: { format: env.NODE_ENV === 'production' ? 'json' : 'pretty' } })
441
+ ```
442
+
443
+ `format` applies to the **built-in** formatter only. With `logger` set, your
444
+ sink always receives the structured object, in every environment — the format
445
+ is not involved.
446
+
447
+ **Want the structured line in development?** Set `format: 'json'`. That is the
448
+ way to see what `enrich` and the request context actually put on the record;
449
+ changing `NODE_ENV` is not needed, and neither is deploying.
450
+
451
+ Three more things about `enrich`:
452
+
453
+ - It runs at close, when the request body is already consumed.
454
+ - The framework owns `traceId`, `method`, `path`, `status`, `durationMs`,
455
+ `errorCode` and `ip` in both structured sinks; the built-in JSON line also
456
+ owns `ts`, `level` and `msg`. Its value wins a collision, and a discarded key
457
+ warns once per handler rather than disappearing silently.
458
+ - `errorCode` has one outcome-aware exception: enrichment may supply it for a
459
+ `4xx`/`5xx` response when the framework derived no code, such as an error
460
+ `Response` returned by a raw route. It cannot add one to a `2xx`/`3xx` or
461
+ replace a framework-derived code.
462
+ - A throw in `skip` or `enrich` is swallowed; neither can fail a request.
463
+
464
+ With an observability context active, the structured line also carries `userId`,
465
+ `serviceName`, `action` and `dimensions` for free. See
466
+ [Observability](./observability.md).
467
+
468
+ ## Route groups
469
+
470
+ A group gives a set of services a shared path prefix and its own hooks:
471
+
472
+ ```ts
473
+ createServer({
474
+ groups: [
475
+ { pathPrefix: '/api', services: [usersService, postsService] },
476
+ { pathPrefix: '/api/admin', services: [adminService], hooks: { authorize: adminAuth } },
477
+ ],
478
+ })
479
+ ```
480
+
481
+ Each service's own `prefix` is appended to the group prefix — `usersService`
482
+ above is served at `/api/users`.
483
+
484
+ ### Param prefixes (resource-scoped paths)
485
+
486
+ A group `pathPrefix` may contain `:param` segments — the spine of a multi-tenant
487
+ or resource-scoped API:
488
+
489
+ ```ts
490
+ createServer({
491
+ groups: [
492
+ { pathPrefix: '/tenants/:tenantId', services: [widgetsService], hooks: { authorize: auth } },
493
+ ],
494
+ })
495
+ // widgetsService (prefix 'widgets') → /tenants/:tenantId/widgets/...
496
+ ```
497
+
498
+ **Where the prefix param lands.** The router matches the *full* path (group
499
+ prefix + service prefix + endpoint path) and collects every `:param` — from the
500
+ prefix and from the endpoint alike — into one set. Each is spread onto the
501
+ context root, so it is available as **`ctx.tenantId`** (a raw `string`) in the
502
+ `authorize` hook, handler and later lifecycle hooks:
503
+
504
+ ```ts
505
+ beforeHandle: (ctx) => {
506
+ const tenantId = ctx.tenantId // string — from the group prefix
507
+ }
508
+ ```
509
+
510
+ `ctx.tenantId` is typed `unknown` (it rides the context index signature) — narrow
511
+ it (`String(ctx.tenantId)` / a guard) at the read site.
512
+
513
+ **Relation to the endpoint `params` schema.** `ctx.params` is the endpoint's
514
+ `params` schema **parsed against all collected path params** (prefix + endpoint).
515
+ So to get the prefix param *inside* typed `ctx.params`, add it to that schema:
516
+
517
+ ```ts
518
+ // endpoint under /tenants/:tenantId
519
+ { method: 'GET', path: '/:widgetId', desc: 'Get a widget',
520
+ params: z.object({ tenantId: z.string(), widgetId: z.string() }) }
521
+ // → ctx.params.tenantId and ctx.params.widgetId both typed
522
+ ```
523
+
524
+ ⚠️ A **`z.strictObject`** params schema that omits the prefix param **rejects the
525
+ request** (the extra `tenantId` key fails the strict parse). Either include every
526
+ prefix param in the schema, use a non-strict `z.object` (extra keys are dropped
527
+ from `ctx.params`, but `ctx.tenantId` still works), or read the param off the
528
+ context root.
529
+
530
+ **Trailing wildcard.** A contract path may end in a named wildcard.
531
+ `/app/:slug/*filePath` matches
532
+ both `/app/foo` and nested paths such as `/app/foo/a/b`; the collected params are
533
+ `{ slug: 'foo', filePath: '' }` and `{ slug: 'foo', filePath: 'a/b' }`
534
+ respectively. Put `filePath` in the endpoint's `params` schema to keep it in
535
+ typed `ctx.params`. Each captured segment is URL-decoded before the remainder is
536
+ joined, so encoded spaces and reserved characters reach the handler as their
537
+ semantic values while `/` remains the segment boundary. Static and named-param
538
+ routes are matched before a catch-all, so a
539
+ more specific endpoint wins regardless of declaration order. The same matcher
540
+ drives `405 Allow` resolution.
541
+
542
+ ### Scope-driven mounting (`scopePrefixes`)
543
+
544
+ With several scopes, hand-partitioning services into `groups` duplicates the
545
+ scope↔prefix mapping. Instead, map `scope → prefix` once and pass the flat
546
+ `services` list — each entry mounts under `scopePrefixes[service.scope]`:
547
+
548
+ ```ts
549
+ createServer({
550
+ services, // mixed scopes, listed once
551
+ scopePrefixes: { tenant: 'tenants/:tenantId', project: 'projects/:projectId' },
552
+ })
553
+ // scope 'tenant' → /tenants/:tenantId/<prefix>/...
554
+ // scope 'project' → /projects/:projectId/<prefix>/...
555
+ // unmapped scope → mounted flat
556
+ ```
557
+
558
+ A prefix may carry `:param` segments (they land on the context exactly as above).
559
+ Services listed under explicit `groups` are unaffected — the group prefix wins.
560
+ Scope stays a free string (unless the contract is authored through
561
+ `createContractFactory<Scope>()`); the core attaches no meaning beyond this lookup
562
+ (→ ADR 0024). When each scope needs a different handler-context shape, use
563
+ [`createScopedImplement`](#per-scope-handler-context--createscopedimplement)
564
+ rather than a single superset context.
565
+
566
+ ## Lifecycle hooks
567
+
568
+ Five hooks wrap every contract request. Route matching and path-param
569
+ validation happen before authorization; body/query parsing happens only after
570
+ authorization succeeds:
571
+
572
+ ```ts
573
+ createServer({
574
+ services,
575
+ hooks: {
576
+ onRequest(req) { /* logging, global rate limit — may return a Response to short-circuit */ },
577
+ authorize(ctx, endpoint) { /* identity + scope, before body reads — throw to reject */ },
578
+ beforeHandle(ctx, endpoint) { /* validated-input preconditions */ },
579
+ afterHandle(ctx, result, ep) { /* transform the result data */ },
580
+ onError(ctx, error, ep) { /* custom error response — return a Response */ },
581
+ },
582
+ })
583
+ ```
584
+
585
+ - **`onRequest`** — runs first, with the raw `Request`. Return a `Response` to
586
+ short-circuit (a rate-limit 429, a redirect); return nothing to continue.
587
+ - **`authorize`** — runs after route matching and validated path params, but
588
+ before query, JSON or multipart parsing. It receives request metadata and
589
+ params, with `input: undefined` and no files. This is the HTTP home of
590
+ [`createAuthHook`](./auth-and-errors.md#createauthhook).
591
+ - **`beforeHandle`** — runs after the complete context has been parsed and
592
+ validated, immediately before the handler. Put input-dependent application
593
+ preconditions here, not authentication.
594
+ - **`afterHandle`** — receives the handler result; return a replacement to
595
+ transform it.
596
+ - **`onError`** — for a matched contract route, the group's hook runs first,
597
+ then the global hook, then the standard error envelope. The first returned
598
+ `Response` wins (including its status and headers); an absent hook, `undefined`
599
+ return or thrown/rejected hook continues to the next level with the **original
600
+ error** and the same context and endpoint. A failing hook is diagnosed through
601
+ `logging.logger.error` (or the internal console fallback), never substituted
602
+ into the client response. This covers path/body validation, authorization,
603
+ before/after hooks and handler errors, including raw-response contract handlers.
604
+ Global `onRequest` failures, `rawRoutes` and unmatched 404/405 have no matched
605
+ contract group and use only the global hook. A confirmed client disconnect
606
+ deliberately bypasses both hooks; errors after streaming headers have been
607
+ sent keep their existing stream-error path.
608
+
609
+ Hooks see `RuntimeContext` (loose types); handlers see `HandlerContext` (typed).
610
+ That split is deliberate — see [ADR 0003](../decisions/0003-two-context-types.md).
611
+
612
+ ## Signed JSON webhooks
613
+
614
+ A provider signs the original JSON text, not `JSON.stringify(ctx.input)`.
615
+ Declare `rawBody: true` to retain the same decoded text the router reads while
616
+ keeping normal Zod validation:
617
+
618
+ ```ts
619
+ const webhooks = defineContract(
620
+ { prefix: 'webhooks' },
621
+ {
622
+ receive: {
623
+ method: 'POST', path: '/provider', desc: 'Receive a signed event',
624
+ rawBody: true,
625
+ maxJsonBodyBytes: 256 * 1024,
626
+ input: ProviderEventSchema,
627
+ output: z.object({ accepted: z.boolean() }),
628
+ },
629
+ },
630
+ )
631
+
632
+ receive: async (ctx) => {
633
+ const signature = ctx.req.headers.get('x-signature')
634
+ await verifyWebhookHmac(ctx.rawBody, signature) // guaranteed string
635
+ return { accepted: true }
636
+ }
637
+ ```
638
+
639
+ This endpoint is HTTP-only and cannot be multipart or exposed as a tool. The
640
+ router sets `ctx.rawBody` before JSON/Zod validation, so `onError` can inspect it
641
+ after malformed JSON or a schema failure. Endpoints without `rawBody: true` do
642
+ not retain the text. `maxJsonBodyBytes` may also be set once on `createServer` /
643
+ `createHandler`; a route value wins. Both limits are opt-in and abort an
644
+ oversized stream before it is fully buffered. → ADR 0051
645
+
646
+ ## Safelisted request bodies (beacons)
647
+
648
+ A body the router reads is `application/json`, and a non-empty body with any
649
+ other `Content-Type` is a `400`. That is deliberate: a `text/plain` body is a
650
+ CORS *simple* request, sent with cookies from any site before the browser asks
651
+ whether the page may read the reply — so requiring JSON forces a preflight, and
652
+ the preflight is where a foreign form is stopped.
653
+
654
+ A page that is being unloaded does not get a preflight. `navigator.sendBeacon`
655
+ with an `application/json` blob and `fetch({ keepalive: true })` with a JSON
656
+ `Content-Type` both report success and both die before the server sees them
657
+ when the API is on another origin. A beacon with a **string** body is
658
+ `text/plain` and arrives. Declare the endpoint that receives it:
659
+
660
+ ```ts
661
+ const tracking = defineContract(
662
+ { prefix: 'tracking', scope: 'public' },
663
+ {
664
+ track: {
665
+ method: 'POST', path: '/events', desc: 'Batch track browser events',
666
+ safelistedBody: true,
667
+ maxJsonBodyBytes: 256 * 1024,
668
+ input: TrackEventsRequestSchema,
669
+ output: TrackEventsResponseSchema,
670
+ },
671
+ },
672
+ )
673
+
674
+ // browser, on `pagehide`
675
+ navigator.sendBeacon(urls.tracking.track(), JSON.stringify(batch)) // text/plain;charset=UTF-8
676
+ ```
677
+
678
+ The body is parsed by the same JSON parser, validated against the same `input`
679
+ and bounded by the same `maxJsonBodyBytes`; `application/json` keeps working.
680
+ What changes is one rule, and it is the rule that keeps the door from being a
681
+ hole: a `text/plain` body is accepted **only from an `Origin` on the server's
682
+ explicit `cors.origin` allow-list**. Everything else is a `403` before the text
683
+ is read:
684
+
685
+ | Request | Outcome |
686
+ |---------|---------|
687
+ | `Origin` on the allow-list (string or list, case-insensitive) | parsed |
688
+ | `Content-Type: text/plain; charset=application/json` from a foreign origin | `403` — the media type is compared whole, never as a substring |
689
+ | `Origin` of a site the server never named | `403` |
690
+ | `Origin: null` — sandboxed iframe, cross-origin redirect, `file://` | `403` |
691
+ | no `Origin` header | `403` |
692
+ | server `cors.origin: '*'` | `403` — a wildcard is not an allow-list |
693
+ | server without `cors` | `403` — there is no allow-list |
694
+ | `application/json` from any origin | unchanged — never subject to the check |
695
+
696
+ The check is a browser invariant, not authentication: a `curl` with a stolen
697
+ cookie and a forged `Origin` passes, and that is an authenticated call, not a
698
+ cross-site one. Two things follow for the application:
699
+
700
+ - **`sendBeacon` sends no headers.** A bearer-authenticated client has to put
701
+ its token in the body — and the body is read *after* `authorize`, so that
702
+ token is available in `beforeHandle` or the handler, never in an auth hook.
703
+ Cookie-authenticated apps are unaffected.
704
+ - **`POST` only.** `defineContract` refuses the flag on `GET`, `HEAD`, `PUT`,
705
+ `PATCH`, `DELETE`, multipart, streaming and input-less endpoints: none of them
706
+ is a simple request with a JSON body, so the flag would only widen the surface.
707
+
708
+ Unlike `rawBody`, the flag does not force `expose: ['HTTP']` — a beacon endpoint
709
+ may still be a tool; only HTTP body parsing changes. OpenAPI lists both media
710
+ types with one schema. → ADR 0165
711
+
712
+ A [raw route](#raw-routes) has none of this: `parseBody` reads any
713
+ `Content-Type`, so a raw beacon route is reachable from any site with the
714
+ user's cookies unless the route checks `Origin` itself. Prefer the flag.
715
+
716
+ ### Choosing an HTTP boundary
717
+
718
+ | Need | Contract declaration | What remains framework-owned |
719
+ |------|----------------------|------------------------------|
720
+ | Typed JSON request/response | ordinary `input` / `output` | routing, auth, schemas, hooks, client, OpenAPI |
721
+ | HMAC-signed JSON | `rawBody: true` + `input` / `output` | the same pipeline plus the exact decoded request text |
722
+ | Page-unload beacon from another origin | `safelistedBody: true` + `input` / `output` | the same pipeline; a `text/plain` body is admitted only from an allow-listed `Origin` |
723
+ | File upload | typed `multipart` descriptor | file cardinality/limits, text input validation and client form encoding |
724
+ | File, stream or redirect response behind contract auth | `rawResponse: true` | request parsing, route identity, auth and typed URL/client surface |
725
+ | Transport that cannot be expressed as the contract pipeline | `RawRoute` | only raw routing, CORS, request hook and error normalisation |
726
+
727
+ `rawBody` is for JSON signatures: verify `ctx.rawBody` against the signature
728
+ header, then use the already validated `ctx.input`. A provider-specific binary
729
+ signature protocol, OAuth callback or WebSocket upgrade can be a real raw route,
730
+ but it must own its validation and authorization explicitly.
731
+
732
+ ## Typed JSON response metadata
733
+
734
+ A JSON endpoint that must attach dynamic HTTP headers while preserving typed
735
+ output declares `responseMeta`. The handler still returns ordinary data:
736
+
737
+ ```ts
738
+ const auth = defineContract({ prefix: 'auth' }, {
739
+ complete: {
740
+ method: 'POST', path: '/complete', desc: 'Complete authentication',
741
+ input: CompleteAuthSchema,
742
+ output: AuthUserSchema,
743
+ responseMeta: { status: 200 },
744
+ },
745
+ })
746
+
747
+ complete: async ({ input, response }) => {
748
+ const result = await authenticate(input.token)
749
+ response.headers.append('Set-Cookie', session.set(result.sessionId))
750
+ response.headers.append('Set-Cookie', preferences.set(result.preferencesId))
751
+ return result.user
752
+ }
753
+ ```
754
+
755
+ `ctx.response.headers` is a fresh Web Fetch `Headers` bag per request. `append`
756
+ preserves repeated `Set-Cookie` values on Bun and Node. The endpoint is
757
+ HTTP-only, but its typed client method still resolves to `AuthUser` — not
758
+ `Response` — and the final data still passes group/global `afterHandle` and the
759
+ declared `output` schema exactly once.
760
+
761
+ `responseMeta.status` is static contract metadata and OpenAPI publishes the same
762
+ 2xx code. Without it, an endpoint with `output` uses `200`; an endpoint without
763
+ `output` uses `204`. A nullable output returns JSON `null` with status `200` —
764
+ the runtime value never turns a declared response body into no content.
765
+ `undefined` violates a declared output, while returning non-null data without an
766
+ output schema is also a server fault. Bodyless `204`/`205` cannot be combined
767
+ with `output`. Redirects, streams, files and handler-owned status/body logic
768
+ remain [`rawResponse: true`](#raw-response-endpoints).
769
+
770
+ Collected headers are merged only after the complete success pipeline. A
771
+ handler, hook or output-validation failure discards them. `Content-Type`,
772
+ `Content-Length`, `x-request-id` and every `Access-Control-*` header remain
773
+ framework-owned; trying to set one fails loudly with the endpoint identity.
774
+ → [ADR 0052](../decisions/0052-typed-json-response-metadata.md)
775
+
776
+ ## Raw-response endpoints
777
+
778
+ An endpoint that answers with **bytes rather than data** — a PDF download, a
779
+ file, an SSE stream — declares `rawResponse: true` and returns the `Response` itself:
780
+
781
+ ```ts
782
+ // contract
783
+ export const documents = defineContract(
784
+ { prefix: 'documents', scope: 'admin' },
785
+ {
786
+ download: {
787
+ method: 'GET', path: '/:id/pdf', desc: 'Download a document as a PDF',
788
+ params: z.object({ id: z.uuid() }),
789
+ rawResponse: true, contentType: 'application/pdf',
790
+ },
791
+ },
792
+ )
793
+
794
+ // handler — no guard on the first line; `beforeHandle` already ran
795
+ download: (ctx) => serveFile(ctx.req, { path: pathFor(ctx.params.id),
796
+ filename: 'offer.pdf' }),
797
+ ```
798
+
799
+ The request half is untouched: `params`, `input` and `multipart` parse and
800
+ validate exactly as elsewhere, and the endpoint goes through `beforeHandle` — so
801
+ the **auth gate applies without a guard in the handler**. Only the response is
802
+ handed over, so there is no `output` schema, `afterHandle` is skipped (it
803
+ transforms data; there is none) and the endpoint is HTTP-only: never an MCP
804
+ tool, an agent tool or a CLI command. Declaring `output`, `tool` or a non-HTTP
805
+ `expose` alongside `rawResponse` is a type error, and throws
806
+ at definition time for a contract assembled at runtime.
807
+
808
+ On the typed client the method resolves to the untouched `Response` — the
809
+ filename lives in `Content-Disposition`, so a `Blob` alone would lose it:
810
+
811
+ ```ts
812
+ const client = createClient(documents, http)
813
+ const res = await client.download({ id }) // Response
814
+ const name = res.headers.get('Content-Disposition')
815
+ const blob = await res.blob()
816
+ ```
817
+
818
+ When the browser should navigate or assign the endpoint directly to `src`, use
819
+ [`createUrlBuilder`](./client.md#contract-url-builders). Raw-response GET methods
820
+ are included, while mutation and multipart methods are intentionally absent.
821
+
822
+ Cross-origin, remember that those headers are readable only because CORS exposes
823
+ them — see [`cors.exposeHeaders`](#serving-files--range-requests).
824
+
825
+ **Raw response or [raw route](#raw-routes)?** Both hand the `Response` to your
826
+ code. A raw-response *endpoint* stays in the contract: only its response is
827
+ raw — it is still routed, gated, typed and documented like every other endpoint.
828
+ A raw *route* is outside the contract entirely — no schemas, no auth gate, no
829
+ client — which is what you want for an OAuth redirect or a non-JSON webhook. A
830
+ signed JSON webhook can stay validated through
831
+ [`rawBody: true`](#signed-json-webhooks).
832
+
833
+ If an endpoint returns typed JSON and only needs an additional status/header,
834
+ use [`responseMeta`](#typed-json-response-metadata), not `rawResponse`: the raw
835
+ variant deliberately transfers response ownership and changes the client result
836
+ to `Response`.
837
+
838
+ ⚠️ **Delete the old raw route when you move an endpoint into the contract.** Raw
839
+ routes are matched **first**, so a leftover one keeps serving the bytes and the
840
+ contract endpoint — with its auth gate — never runs. stitchkit warns at startup
841
+ when a raw route shadows a contract route, naming both and the scope being
842
+ bypassed; treat that warning as a bug.
843
+
844
+ ⚠️ **A path built from user input needs a containment check.** `staticRoute`
845
+ enforces it; `serveFile` deliberately leaves it to the caller, so an endpoint
846
+ serving `/:filename` must not pass it through:
847
+
848
+ ```ts
849
+ import { isWithinDir, serveFile } from 'stitchkit/server'
850
+ import { resolve } from 'node:path'
851
+
852
+ const ROOT = resolve('./uploads')
853
+
854
+ file: (ctx) => {
855
+ const target = resolve(ROOT, ctx.params.filename)
856
+ // `../../etc/passwd` resolves outside ROOT — reject before touching disk.
857
+ if (!isWithinDir(ROOT, target)) throw notFound('File not found')
858
+ return serveFile(ctx.req, { path: target })
859
+ },
860
+ ```
861
+
862
+ `implementRemote` proxies a raw-response endpoint like any other — the remote
863
+ `Response` is forwarded verbatim. Request headers are not relayed, so a `Range`
864
+ sent to the proxy does not reach the origin and the full body comes back.
865
+ → ADR 0038.
866
+
867
+ ## Raw routes
868
+
869
+ Some routes cannot be a clean JSON contract — an OAuth redirect, a webhook with
870
+ signature verification, static files, the Socket.IO endpoint. `rawRoutes` are
871
+ plain `Request → Response` handlers, matched by the same router (shared CORS and
872
+ `onRequest`) but with no schema parsing and no `beforeHandle` gate — a raw route
873
+ authorises itself.
874
+
875
+ ```ts
876
+ createServer({
877
+ services,
878
+ rawRoutes: [
879
+ {
880
+ method: 'GET',
881
+ path: '/health',
882
+ handler: () => Response.json({ status: 'ok' }),
883
+ },
884
+ {
885
+ method: 'POST',
886
+ path: '/webhooks/:provider',
887
+ serviceName: 'webhooks',
888
+ action: 'receive',
889
+ handler: (req, ctx) => handleWebhook(ctx.params.provider, req),
890
+ },
891
+ ],
892
+ })
893
+ ```
894
+
895
+ `serviceName` and `action` are optional observability identity. Declare
896
+ `serviceName` when audit, logging, sampling or another cross-cutting policy
897
+ groups this raw route with a service; add `action` when the policy needs an
898
+ operation within that service. Stitchkit never derives either from `path`.
899
+ `action` without `serviceName`, and empty identity strings, fail at startup.
900
+
901
+ A path may be exact, carry `:param` segments, or end in `/*filePath` for a prefix
902
+ wildcard — and the two combine: `/app/:slug/*filePath` matches `/app/x/a/b` with
903
+ `ctx.params.slug === 'x'` and the remainder in `ctx.params.filePath` (a SPA
904
+ deep-link fallback). List more specific routes before the wildcard — the first
905
+ match wins. `staticRoute()` builds a raw route that serves a directory.
906
+
907
+ At startup Stitchkit rejects exact duplicates, equivalent parameter shapes
908
+ (`/users/:id` vs `/users/:userId`) and any later raw route completely hidden by
909
+ an earlier raw route. Partial overlap stays legal, including the recommended
910
+ specific-before-wildcard order. `GET` and `HEAD` remain independent because that
911
+ is how the actual raw matcher dispatches them. Raw-vs-contract overlap remains a
912
+ startup diagnostic naming the bypassed contract identity and scope.
913
+
914
+ ### Raw-route helpers
915
+
916
+ A raw route gives up the contract pipeline, so three things get re-implemented in
917
+ every one. `stitchkit/server` ships them — conveniences, not a second pipeline
918
+ (no auth, no schema gate beyond `parseBody`):
919
+
920
+ ```ts
921
+ import { respondJson, errorResponse, parseBody, badRequest } from 'stitchkit/server'
922
+
923
+ handler: async (req) => {
924
+ try {
925
+ const body = await parseBody(req, MySchema) // typed value, or null (no throw)
926
+ if (!body) throw badRequest('invalid body') // helpers THROW an AppError
927
+ return respondJson(await myService(body)) // JSON; 204 when null/undefined
928
+ } catch (err) {
929
+ return errorResponse(err) // same envelope as a contract route
930
+ }
931
+ }
932
+ ```
933
+
934
+ The error helpers (`badRequest`, `notFound`, …) **throw** an `AppError`, so raise
935
+ them inside the `try` and let `errorResponse(err)` render it — that runs any
936
+ thrown value through the framework's `normalizeError`, so a raw route returns the
937
+ **identical** `{ error: { code, message, … } }` shape (and `x-request-id`) a
938
+ contract route does.
939
+
940
+ ### Serving files & Range requests
941
+
942
+ `staticRoute` is basic on purpose — it reads the whole file into memory and has
943
+ no `Range` or conditional support; put a CDN in front, or use it for small web
944
+ assets. To serve **media** (video / audio / large downloads) that a browser must
945
+ seek and cache, use **`serveFile`** (Bun) — it streams the requested byte range
946
+ and speaks the conditional-request half of RFC 7233 / 9110:
947
+
948
+ ```ts
949
+ import { defineContract } from 'stitchkit/contract'
950
+ import { implement, serveFile } from 'stitchkit/server'
951
+ import { z } from 'zod'
952
+
953
+ const MediaParams = z.object({ id: z.string() })
954
+ const media = defineContract({ prefix: 'media' }, {
955
+ download: {
956
+ method: 'GET', path: '/:id', desc: 'Download media',
957
+ params: MediaParams, rawResponse: true, contentType: 'video/mp4',
958
+ },
959
+ inspect: {
960
+ method: 'HEAD', path: '/:id', desc: 'Inspect media',
961
+ params: MediaParams, rawResponse: true, contentType: 'video/mp4',
962
+ },
963
+ })
964
+
965
+ const mediaService = implement(media, {
966
+ download: ({ req, params }) =>
967
+ serveFile(req, { path: pathForId(params.id), filename: 'clip.mp4' }),
968
+ inspect: ({ req, params }) =>
969
+ serveFile(req, { path: pathForId(params.id), filename: 'clip.mp4' }),
970
+ })
971
+ ```
972
+
973
+ GET and HEAD are separate operations deliberately: declaring GET never creates
974
+ a hidden HEAD alias. Both travel through the normal contract router, params,
975
+ lifecycle/RBAC and request logging. A HEAD handler may inspect the raw query via
976
+ `ctx.req.url`, but cannot declare a request input schema or body.
977
+
978
+ `serveFile` returns `206` (range, with `Content-Range` + `Content-Length`), `200`
979
+ (full), `416` (unsatisfiable, `Content-Range: bytes */size`), `304`
980
+ (`If-None-Match` / `If-Modified-Since`), `404` (missing) or `405` (non GET/HEAD).
981
+ It always sets `Accept-Ranges: bytes`, a weak `ETag` and `Last-Modified` (so
982
+ `If-Range` keeps a changing file from being stitched from stale + fresh bytes),
983
+ and `nosniff`. `Content-Type` is auto-detected from the path — override it, or
984
+ pass `disposition` / `cacheControl` / `etag: false`, via the options.
985
+
986
+ Cross-origin, the browser lets JavaScript read only the CORS-safelisted response
987
+ headers. stitchkit therefore exposes the download-relevant ones by default
988
+ (`Content-Disposition`, `Content-Range`, `ETag`, …) — without that a `fetch`-based
989
+ download cannot recover the file's name. Override with `cors.exposeHeaders`
990
+ (extend `DEFAULT_CORS_EXPOSE_HEADERS` rather than replacing it), or pass `[]` to
991
+ emit none.
992
+
993
+ `serveFile` takes an explicit `path` and trusts it — **the caller owns
994
+ containment**. For a URL-derived path use `staticRoute` (which enforces it) or
995
+ `isWithinDir` first. The byte-range parser is exported on its own as
996
+ `parseByteRange(header, size)` for direct use and testing. → ADR 0023.