stitchkit 0.94.0 → 0.94.1

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 (346) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/dist/agent-runtime/coding-shell-process.d.ts.map +1 -1
  3. package/dist/agent-runtime/coding-tool-listing.d.ts.map +1 -1
  4. package/dist/agent-runtime/coding-tool-search-patch.d.ts.map +1 -1
  5. package/dist/agent-runtime/contained-darwin.d.ts +38 -0
  6. package/dist/agent-runtime/contained-darwin.d.ts.map +1 -0
  7. package/dist/agent-runtime/contained-files.d.ts +11 -26
  8. package/dist/agent-runtime/contained-files.d.ts.map +1 -1
  9. package/dist/agent-runtime/contained-scan.d.ts +21 -0
  10. package/dist/agent-runtime/contained-scan.d.ts.map +1 -0
  11. package/dist/agent-runtime/contained-write.d.ts +9 -0
  12. package/dist/agent-runtime/contained-write.d.ts.map +1 -0
  13. package/dist/agent-runtime/deferred-tool-types.d.ts +3 -2
  14. package/dist/agent-runtime/deferred-tool-types.d.ts.map +1 -1
  15. package/dist/agent-runtime/harness-control.d.ts +0 -1
  16. package/dist/agent-runtime/harness-control.d.ts.map +1 -1
  17. package/dist/agent-runtime/harness.d.ts +0 -5
  18. package/dist/agent-runtime/harness.d.ts.map +1 -1
  19. package/dist/agent-runtime/managed-tools.d.ts +3 -2
  20. package/dist/agent-runtime/managed-tools.d.ts.map +1 -1
  21. package/dist/agent-runtime/runtime.d.ts +1 -1
  22. package/dist/agent-runtime/runtime.d.ts.map +1 -1
  23. package/dist/agent-runtime/schedule-records.d.ts +34 -0
  24. package/dist/agent-runtime/schedule-records.d.ts.map +1 -0
  25. package/dist/agent-runtime/schedules.d.ts +34 -0
  26. package/dist/agent-runtime/schedules.d.ts.map +1 -1
  27. package/dist/agent-runtime/store-conformance-lifecycle.d.ts +434 -0
  28. package/dist/agent-runtime/store-conformance-lifecycle.d.ts.map +1 -0
  29. package/dist/agent-runtime/store-conformance-ordering.d.ts +18 -0
  30. package/dist/agent-runtime/store-conformance-ordering.d.ts.map +1 -0
  31. package/dist/agent-runtime/store-conformance-support.d.ts +130 -0
  32. package/dist/agent-runtime/store-conformance-support.d.ts.map +1 -0
  33. package/dist/agent-runtime/store-conformance-terminal.d.ts +12 -0
  34. package/dist/agent-runtime/store-conformance-terminal.d.ts.map +1 -0
  35. package/dist/agent-runtime/store-conformance.d.ts.map +1 -1
  36. package/dist/application/admission-rate.d.ts +21 -0
  37. package/dist/application/admission-rate.d.ts.map +1 -0
  38. package/dist/application/admission-run.d.ts +8 -0
  39. package/dist/application/admission-run.d.ts.map +1 -0
  40. package/dist/application/admission.d.ts.map +1 -1
  41. package/dist/application/diagnostic-journal-lock.d.ts +9 -34
  42. package/dist/application/diagnostic-journal-lock.d.ts.map +1 -1
  43. package/dist/application/diagnostic-journal-manager.d.ts.map +1 -1
  44. package/dist/application/diagnostic-journal-storage.d.ts.map +1 -1
  45. package/dist/application/kernel-resource-context.d.ts.map +1 -1
  46. package/dist/application/notification-outbox.d.ts.map +1 -1
  47. package/dist/application/schedule.d.ts +0 -1
  48. package/dist/application/schedule.d.ts.map +1 -1
  49. package/dist/application/watch-hub-core.d.ts +122 -0
  50. package/dist/application/watch-hub-core.d.ts.map +1 -0
  51. package/dist/application/watch-hub.d.ts +2 -2
  52. package/dist/application/watch-hub.d.ts.map +1 -1
  53. package/dist/browser/client-executors.d.ts +14 -0
  54. package/dist/browser/client-executors.d.ts.map +1 -0
  55. package/dist/browser/client-multipart.d.ts +1 -1
  56. package/dist/browser/client-multipart.d.ts.map +1 -1
  57. package/dist/browser/client.d.ts +3 -2
  58. package/dist/browser/client.d.ts.map +1 -1
  59. package/dist/browser/http-fetch.d.ts +22 -0
  60. package/dist/browser/http-fetch.d.ts.map +1 -0
  61. package/dist/browser/http.d.ts +1 -3
  62. package/dist/browser/http.d.ts.map +1 -1
  63. package/dist/browser/live-state-core.d.ts +63 -0
  64. package/dist/browser/live-state-core.d.ts.map +1 -0
  65. package/dist/browser/live-state.d.ts.map +1 -1
  66. package/dist/browser/realtime-client.d.ts +26 -0
  67. package/dist/browser/realtime-client.d.ts.map +1 -0
  68. package/dist/browser/socket-io-connection.d.ts +82 -0
  69. package/dist/browser/socket-io-connection.d.ts.map +1 -0
  70. package/dist/browser/socket-io-peer.d.ts +20 -0
  71. package/dist/browser/socket-io-peer.d.ts.map +1 -0
  72. package/dist/browser/socket-io-trace.d.ts +31 -0
  73. package/dist/browser/socket-io-trace.d.ts.map +1 -0
  74. package/dist/browser/socket-io.d.ts +2 -18
  75. package/dist/browser/socket-io.d.ts.map +1 -1
  76. package/dist/contract/client-types.d.ts +134 -0
  77. package/dist/contract/client-types.d.ts.map +1 -0
  78. package/dist/contract/define-validation.d.ts +30 -0
  79. package/dist/contract/define-validation.d.ts.map +1 -0
  80. package/dist/contract/define.d.ts +3 -357
  81. package/dist/contract/define.d.ts.map +1 -1
  82. package/dist/contract/runtime-context.d.ts +131 -0
  83. package/dist/contract/runtime-context.d.ts.map +1 -0
  84. package/dist/contract/tool-options.d.ts +105 -0
  85. package/dist/contract/tool-options.d.ts.map +1 -0
  86. package/dist/contract/tool-view.d.ts +15 -2
  87. package/dist/contract/tool-view.d.ts.map +1 -1
  88. package/dist/durability/contract.d.ts +83 -0
  89. package/dist/durability/contract.d.ts.map +1 -1
  90. package/dist/durability/effect.d.ts +24 -0
  91. package/dist/durability/effect.d.ts.map +1 -0
  92. package/dist/durability/engine.d.ts +2 -2
  93. package/dist/durability/engine.d.ts.map +1 -1
  94. package/dist/durability/events.d.ts +2 -0
  95. package/dist/durability/events.d.ts.map +1 -1
  96. package/dist/durability/ledger.d.ts +11 -0
  97. package/dist/durability/ledger.d.ts.map +1 -1
  98. package/dist/durability/parks.d.ts +22 -0
  99. package/dist/durability/parks.d.ts.map +1 -0
  100. package/dist/durability/scheduler.d.ts +1 -0
  101. package/dist/durability/scheduler.d.ts.map +1 -1
  102. package/dist/entrypoints/agent-runtime/coding-tools.js +4 -4
  103. package/dist/entrypoints/agent-runtime/harness.js +127 -116
  104. package/dist/entrypoints/agent-runtime/sandbox.js +4 -4
  105. package/dist/entrypoints/agent-runtime/sqlite/bun.js +3 -3
  106. package/dist/entrypoints/agent-runtime/sqlite/node.js +3 -3
  107. package/dist/entrypoints/agent-runtime/testing.js +246 -214
  108. package/dist/entrypoints/agent-runtime.js +224 -203
  109. package/dist/entrypoints/application/diagnostic-journal.js +63 -203
  110. package/dist/entrypoints/application/opentelemetry.js +1 -1
  111. package/dist/entrypoints/application.js +361 -324
  112. package/dist/entrypoints/cli.d.ts +4 -1
  113. package/dist/entrypoints/cli.d.ts.map +1 -1
  114. package/dist/entrypoints/cli.js +57 -35
  115. package/dist/entrypoints/contract.d.ts +5 -2
  116. package/dist/entrypoints/contract.d.ts.map +1 -1
  117. package/dist/entrypoints/contract.js +3 -2
  118. package/dist/entrypoints/files.d.ts +2 -0
  119. package/dist/entrypoints/files.d.ts.map +1 -1
  120. package/dist/entrypoints/files.js +98 -2
  121. package/dist/entrypoints/index.d.ts +4 -2
  122. package/dist/entrypoints/index.d.ts.map +1 -1
  123. package/dist/entrypoints/index.js +348 -282
  124. package/dist/entrypoints/live.js +89 -71
  125. package/dist/entrypoints/node.d.ts +2 -1
  126. package/dist/entrypoints/node.d.ts.map +1 -1
  127. package/dist/entrypoints/node.js +13 -12
  128. package/dist/entrypoints/react.js +1 -1
  129. package/dist/entrypoints/remote.js +4 -4
  130. package/dist/entrypoints/server.d.ts +4 -2
  131. package/dist/entrypoints/server.d.ts.map +1 -1
  132. package/dist/entrypoints/server.js +293 -79
  133. package/dist/entrypoints/testing.d.ts +2 -1
  134. package/dist/entrypoints/testing.d.ts.map +1 -1
  135. package/dist/entrypoints/testing.js +288 -281
  136. package/dist/entrypoints/tools/connections.js +2 -2
  137. package/dist/entrypoints/tools/invoker.js +4 -4
  138. package/dist/entrypoints/tools.d.ts +6 -3
  139. package/dist/entrypoints/tools.d.ts.map +1 -1
  140. package/dist/entrypoints/tools.js +245 -202
  141. package/dist/entrypoints/tracking.js +325 -274
  142. package/dist/files/boundary.d.ts.map +1 -1
  143. package/dist/files/file-io.d.ts +14 -0
  144. package/dist/files/file-io.d.ts.map +1 -0
  145. package/dist/index-1j8pm5t0.js +412 -0
  146. package/dist/{index-kvj7f4hq.js → index-2bxbyab0.js} +10 -2
  147. package/dist/{index-xnj9bgxe.js → index-2gxzjvyr.js} +2 -162
  148. package/dist/index-4gcnakhx.js +82 -0
  149. package/dist/{index-j05z5gn4.js → index-55hkhm67.js} +136 -119
  150. package/dist/{index-cq4qfycf.js → index-79z7m7dt.js} +227 -59
  151. package/dist/{index-97ac4gph.js → index-7f68ghdn.js} +3 -3
  152. package/dist/{index-r7nmqpsg.js → index-7p1f0vp2.js} +1 -1
  153. package/dist/{index-dcpdvjsc.js → index-863ea9jb.js} +4 -4
  154. package/dist/index-8p52kd5p.js +242 -0
  155. package/dist/{index-2qzskm8h.js → index-dce5wxcq.js} +1 -1
  156. package/dist/index-e01r054k.js +105 -0
  157. package/dist/{index-sees8yf8.js → index-ensd0r74.js} +118 -111
  158. package/dist/{index-1nd48tm9.js → index-gxrt5h6v.js} +2 -1
  159. package/dist/{index-e87kakm4.js → index-ham5sz8m.js} +112 -110
  160. package/dist/{index-kj2wbeta.js → index-het2he5g.js} +280 -196
  161. package/dist/{index-vcvkq30w.js → index-hmp4800j.js} +3 -3
  162. package/dist/{index-gyr48nzg.js → index-k30h66yd.js} +71 -151
  163. package/dist/{index-2cr1cqhn.js → index-khtgb21r.js} +2 -2
  164. package/dist/{index-x4799c19.js → index-ndddxtyx.js} +11 -11
  165. package/dist/{index-dydjcp8z.js → index-np4m8hd3.js} +38 -36
  166. package/dist/{index-p81267c2.js → index-p3vsv1fb.js} +621 -357
  167. package/dist/{index-mp5sn43f.js → index-p9e0w8hs.js} +2 -2
  168. package/dist/{index-rewkc2hj.js → index-p9sh0xx4.js} +3 -3
  169. package/dist/{index-70yj2ebz.js → index-paz6sgdp.js} +107 -103
  170. package/dist/{index-bn2cjajt.js → index-px2gm2jp.js} +26 -102
  171. package/dist/index-s812ycat.js +65 -0
  172. package/dist/{index-xsqjkha9.js → index-sp1tzwnb.js} +2 -2
  173. package/dist/{index-n6hxg8as.js → index-t9rhjr9f.js} +615 -566
  174. package/dist/{index-zeemqhqx.js → index-v260df89.js} +88 -80
  175. package/dist/{index-fdp6hdxn.js → index-w906953s.js} +5 -1
  176. package/dist/{index-mdzh02yc.js → index-wdkt63w3.js} +1 -1
  177. package/dist/{index-58k4fp34.js → index-wsm5w4ee.js} +1 -1
  178. package/dist/{index-v38qyerb.js → index-xw3s75nj.js} +1 -1
  179. package/dist/internal/atomic-file.d.ts +23 -2
  180. package/dist/internal/atomic-file.d.ts.map +1 -1
  181. package/dist/internal/exclusive-lock.d.ts +51 -0
  182. package/dist/internal/exclusive-lock.d.ts.map +1 -0
  183. package/dist/internal/process-identity.d.ts +47 -0
  184. package/dist/internal/process-identity.d.ts.map +1 -0
  185. package/dist/internal/with-exclusive-lock.d.ts +67 -0
  186. package/dist/internal/with-exclusive-lock.d.ts.map +1 -0
  187. package/dist/live/watch-client.d.ts.map +1 -1
  188. package/dist/observability/audit.d.ts +2 -2
  189. package/dist/observability/audit.d.ts.map +1 -1
  190. package/dist/observability/event.d.ts +2 -1
  191. package/dist/observability/event.d.ts.map +1 -1
  192. package/dist/primitives/export-operation.d.ts +1 -1
  193. package/dist/primitives/export-operation.d.ts.map +1 -1
  194. package/dist/realtime/registry.d.ts +0 -5
  195. package/dist/realtime/registry.d.ts.map +1 -1
  196. package/dist/server/bun.d.ts +0 -1
  197. package/dist/server/bun.d.ts.map +1 -1
  198. package/dist/server/context-contribution.d.ts +1 -1
  199. package/dist/server/context-contribution.d.ts.map +1 -1
  200. package/dist/server/context.d.ts +1 -1
  201. package/dist/server/context.d.ts.map +1 -1
  202. package/dist/server/endpoint-response.d.ts +2 -1
  203. package/dist/server/endpoint-response.d.ts.map +1 -1
  204. package/dist/server/error-dispatch.d.ts +1 -1
  205. package/dist/server/error-dispatch.d.ts.map +1 -1
  206. package/dist/server/error-hook.d.ts +1 -1
  207. package/dist/server/error-hook.d.ts.map +1 -1
  208. package/dist/server/handler-state.d.ts +1 -1
  209. package/dist/server/handler-state.d.ts.map +1 -1
  210. package/dist/server/implement-registry.d.ts +54 -0
  211. package/dist/server/implement-registry.d.ts.map +1 -0
  212. package/dist/server/implement.d.ts +9 -55
  213. package/dist/server/implement.d.ts.map +1 -1
  214. package/dist/server/middleware/auth.d.ts +1 -31
  215. package/dist/server/middleware/auth.d.ts.map +1 -1
  216. package/dist/server/middleware/jwt.d.ts +31 -0
  217. package/dist/server/middleware/jwt.d.ts.map +1 -0
  218. package/dist/server/multipart-reader.d.ts +22 -0
  219. package/dist/server/multipart-reader.d.ts.map +1 -0
  220. package/dist/server/multipart.d.ts +1 -1
  221. package/dist/server/multipart.d.ts.map +1 -1
  222. package/dist/server/oauth/cimd.d.ts +88 -0
  223. package/dist/server/oauth/cimd.d.ts.map +1 -0
  224. package/dist/server/oauth/endpoints.d.ts +39 -0
  225. package/dist/server/oauth/endpoints.d.ts.map +1 -0
  226. package/dist/server/oauth/provider.d.ts +1 -68
  227. package/dist/server/oauth/provider.d.ts.map +1 -1
  228. package/dist/server/streaming-pump.d.ts +66 -0
  229. package/dist/server/streaming-pump.d.ts.map +1 -0
  230. package/dist/server/streaming-route.d.ts +12 -5
  231. package/dist/server/streaming-route.d.ts.map +1 -1
  232. package/dist/server/types.d.ts +4 -1
  233. package/dist/server/types.d.ts.map +1 -1
  234. package/dist/server/unix-client-bun.d.ts.map +1 -1
  235. package/dist/server/unix-client-http1.d.ts +76 -0
  236. package/dist/server/unix-client-http1.d.ts.map +1 -0
  237. package/dist/server/unix-client.d.ts.map +1 -1
  238. package/dist/testing/handler-clients.d.ts +2 -1
  239. package/dist/testing/handler-clients.d.ts.map +1 -1
  240. package/dist/testing/realtime-probe.d.ts +33 -0
  241. package/dist/testing/realtime-probe.d.ts.map +1 -0
  242. package/dist/testing/surface-conformance.d.ts +0 -31
  243. package/dist/testing/surface-conformance.d.ts.map +1 -1
  244. package/dist/testing/surface-manifest-digest.d.ts +44 -0
  245. package/dist/testing/surface-manifest-digest.d.ts.map +1 -0
  246. package/dist/testing/surface-manifest.d.ts.map +1 -1
  247. package/dist/tools/agent.d.ts +1 -1
  248. package/dist/tools/agent.d.ts.map +1 -1
  249. package/dist/tools/cli/args-fields.d.ts +31 -0
  250. package/dist/tools/cli/args-fields.d.ts.map +1 -0
  251. package/dist/tools/cli/args-route.d.ts +42 -0
  252. package/dist/tools/cli/args-route.d.ts.map +1 -0
  253. package/dist/tools/cli/args-view.d.ts +32 -0
  254. package/dist/tools/cli/args-view.d.ts.map +1 -0
  255. package/dist/tools/cli/args.d.ts +2 -65
  256. package/dist/tools/cli/args.d.ts.map +1 -1
  257. package/dist/tools/cli/argument-error.d.ts +5 -0
  258. package/dist/tools/cli/argument-error.d.ts.map +1 -0
  259. package/dist/tools/cli/checkpoint.d.ts.map +1 -1
  260. package/dist/tools/cli/command.d.ts +1 -1
  261. package/dist/tools/cli/command.d.ts.map +1 -1
  262. package/dist/tools/cli/config.d.ts +1 -1
  263. package/dist/tools/cli/config.d.ts.map +1 -1
  264. package/dist/tools/cli/format.d.ts +2 -1
  265. package/dist/tools/cli/format.d.ts.map +1 -1
  266. package/dist/tools/cli/invoke.d.ts +2 -1
  267. package/dist/tools/cli/invoke.d.ts.map +1 -1
  268. package/dist/tools/cli/managed-surface.d.ts +1 -1
  269. package/dist/tools/cli/managed-surface.d.ts.map +1 -1
  270. package/dist/tools/cli/policy.d.ts +1 -1
  271. package/dist/tools/cli/policy.d.ts.map +1 -1
  272. package/dist/tools/cli/prepare.d.ts.map +1 -1
  273. package/dist/tools/cli/run-managed.d.ts.map +1 -1
  274. package/dist/tools/cli/session.d.ts +1 -1
  275. package/dist/tools/cli/session.d.ts.map +1 -1
  276. package/dist/tools/cli/update.d.ts +19 -0
  277. package/dist/tools/cli/update.d.ts.map +1 -1
  278. package/dist/tools/cli/view.d.ts +1 -1
  279. package/dist/tools/cli/view.d.ts.map +1 -1
  280. package/dist/tools/cli/wait.d.ts +1 -1
  281. package/dist/tools/cli/wait.d.ts.map +1 -1
  282. package/dist/tools/connections/runtime.d.ts +1 -1
  283. package/dist/tools/connections/runtime.d.ts.map +1 -1
  284. package/dist/tools/execute-args.d.ts +23 -0
  285. package/dist/tools/execute-args.d.ts.map +1 -0
  286. package/dist/tools/execute-hooks.d.ts +146 -0
  287. package/dist/tools/execute-hooks.d.ts.map +1 -0
  288. package/dist/tools/execute-result.d.ts +40 -0
  289. package/dist/tools/execute-result.d.ts.map +1 -0
  290. package/dist/tools/execute.d.ts +4 -193
  291. package/dist/tools/execute.d.ts.map +1 -1
  292. package/dist/tools/internal/surface-projector.d.ts +2 -1
  293. package/dist/tools/internal/surface-projector.d.ts.map +1 -1
  294. package/dist/tools/invoker.d.ts +2 -1
  295. package/dist/tools/invoker.d.ts.map +1 -1
  296. package/dist/tools/lifecycle.d.ts +1 -1
  297. package/dist/tools/lifecycle.d.ts.map +1 -1
  298. package/dist/tools/mcp/mount.d.ts +1 -1
  299. package/dist/tools/mcp/mount.d.ts.map +1 -1
  300. package/dist/tools/mcp/prepare.d.ts +2 -1
  301. package/dist/tools/mcp/prepare.d.ts.map +1 -1
  302. package/dist/tools/mcp/progress.d.ts +1 -1
  303. package/dist/tools/mcp/progress.d.ts.map +1 -1
  304. package/dist/tools/mcp/register.d.ts +3 -2
  305. package/dist/tools/mcp/register.d.ts.map +1 -1
  306. package/dist/tools/mcp/round-context.d.ts +38 -0
  307. package/dist/tools/mcp/round-context.d.ts.map +1 -0
  308. package/dist/tools/mcp/round-policy.d.ts +1 -1
  309. package/dist/tools/mcp/round-policy.d.ts.map +1 -1
  310. package/dist/tools/mcp/round.d.ts +3 -11
  311. package/dist/tools/mcp/round.d.ts.map +1 -1
  312. package/dist/tools/mcp/runtime-tools.d.ts +2 -1
  313. package/dist/tools/mcp/runtime-tools.d.ts.map +1 -1
  314. package/dist/tools/mount.d.ts +3 -1
  315. package/dist/tools/mount.d.ts.map +1 -1
  316. package/dist/tools/native-definition.d.ts +2 -1
  317. package/dist/tools/native-definition.d.ts.map +1 -1
  318. package/dist/tools/operations/async-operation-runtime-tools.d.ts +2 -1
  319. package/dist/tools/operations/async-operation-runtime-tools.d.ts.map +1 -1
  320. package/dist/tools/operations/async-operation-runtime-types.d.ts +2 -1
  321. package/dist/tools/operations/async-operation-runtime-types.d.ts.map +1 -1
  322. package/dist/tools/remote.d.ts.map +1 -1
  323. package/dist/tools/runtime-tool.d.ts +3 -1
  324. package/dist/tools/runtime-tool.d.ts.map +1 -1
  325. package/dist/tools/tool-logger.d.ts +1 -1
  326. package/dist/tools/tool-logger.d.ts.map +1 -1
  327. package/dist/tracking/client-listeners.d.ts +30 -0
  328. package/dist/tracking/client-listeners.d.ts.map +1 -0
  329. package/dist/tracking/client-visit.d.ts +61 -0
  330. package/dist/tracking/client-visit.d.ts.map +1 -0
  331. package/dist/tracking/client.d.ts +3 -2
  332. package/dist/tracking/client.d.ts.map +1 -1
  333. package/llms/application.2.txt +266 -2
  334. package/llms/application.txt +8 -266
  335. package/llms/cli.2.txt +80 -0
  336. package/llms/cli.txt +45 -74
  337. package/llms/contract.txt +3 -3
  338. package/llms/files.txt +3 -0
  339. package/llms/tools.2.txt +88 -279
  340. package/llms/tools.3.txt +288 -0
  341. package/llms/tools.txt +27 -65
  342. package/llms-full.txt +108 -12
  343. package/llms.txt +5 -5
  344. package/package.json +1 -1
  345. package/dist/index-e2z3ahw9.js +0 -325
  346. package/dist/index-mkm15s49.js +0 -394
@@ -13,7 +13,7 @@ import {
13
13
  createActivityProjection,
14
14
  createApplicationSnapshotSink,
15
15
  createManagedSchedule
16
- } from "../index-sees8yf8.js";
16
+ } from "../index-ensd0r74.js";
17
17
  import {
18
18
  DiagnosticJournalCloseResultSchema,
19
19
  DiagnosticJournalFailurePhaseSchema,
@@ -36,7 +36,7 @@ import {
36
36
  ApplicationShutdownBudgetSchema,
37
37
  ApplicationShutdownOptionsSchema,
38
38
  createApplication
39
- } from "../index-fdp6hdxn.js";
39
+ } from "../index-w906953s.js";
40
40
  import {
41
41
  ApplicationAdmissionSnapshotSchema,
42
42
  ApplicationHealthSchema,
@@ -69,8 +69,8 @@ import {
69
69
  deltaWins,
70
70
  diff,
71
71
  watchKeyString
72
- } from "../index-mdzh02yc.js";
73
- import"../index-mkm15s49.js";
72
+ } from "../index-wdkt63w3.js";
73
+ import"../index-1j8pm5t0.js";
74
74
  import {
75
75
  BoundedChannelPolicySchema,
76
76
  BoundedChannelReaderError,
@@ -94,6 +94,85 @@ import"../index-kzfs85xp.js";
94
94
  import"../index-hffjpmq9.js";
95
95
  // src/application/admission.ts
96
96
  import { z } from "zod";
97
+
98
+ // src/application/admission-rate.ts
99
+ function pruneRate(samples, intervalMs, at) {
100
+ let expired = 0;
101
+ while (expired < samples.length && at - (samples[expired]?.at ?? at) >= intervalMs) {
102
+ expired += 1;
103
+ }
104
+ if (expired > 0)
105
+ samples.splice(0, expired);
106
+ }
107
+ function pruneExpired(policy, globalRate, keys, at) {
108
+ if (policy.global.rate)
109
+ pruneRate(globalRate, policy.global.rate.intervalMs, at);
110
+ for (const [key, record] of keys) {
111
+ if (record.limits?.rate)
112
+ pruneRate(record.rate, record.limits.rate.intervalMs, at);
113
+ if (record.active === 0 && record.rate.length === 0)
114
+ keys.delete(key);
115
+ }
116
+ }
117
+ function retryAfter(samples, budget, at) {
118
+ return Math.max(1, Math.ceil(budget.intervalMs - (at - (samples[0]?.at ?? at))));
119
+ }
120
+ function removeSample(samples, sample) {
121
+ if (!sample)
122
+ return;
123
+ const index = samples.indexOf(sample);
124
+ if (index >= 0)
125
+ samples.splice(index, 1);
126
+ }
127
+
128
+ // src/application/admission-run.ts
129
+ async function runAdmitted(acquire, key, work, options) {
130
+ if (options.timeoutMs !== undefined) {
131
+ if (!Number.isSafeInteger(options.timeoutMs) || options.timeoutMs < 0) {
132
+ throw new TypeError("run timeoutMs must be a non-negative safe integer");
133
+ }
134
+ }
135
+ if (options.signal?.aborted)
136
+ throw new BoundedOperationWaitError("cancelled");
137
+ const admission = acquire(key);
138
+ if (admission.outcome === "refused") {
139
+ throw new BoundedAdmissionRefusalError(admission.reason, admission.retryAfterMs);
140
+ }
141
+ const workAbort = new AbortController;
142
+ const abortWork = () => workAbort.abort(options.signal?.reason);
143
+ options.signal?.addEventListener("abort", abortWork, { once: true });
144
+ let timer;
145
+ let timedOut = false;
146
+ if (options.timeoutMs !== undefined) {
147
+ timer = setTimeout(() => {
148
+ timedOut = true;
149
+ workAbort.abort(new DOMException("Operation wait timed out", "TimeoutError"));
150
+ }, options.timeoutMs);
151
+ }
152
+ const outcome = Promise.resolve().then(() => work({ signal: workAbort.signal })).then((value) => ({ kind: "value", value }), (error) => ({ kind: "error", error })).finally(() => admission.lease.release());
153
+ const callerDone = new Promise((resolve) => {
154
+ const settle = () => resolve({ kind: "caller" });
155
+ if (workAbort.signal.aborted)
156
+ settle();
157
+ else
158
+ workAbort.signal.addEventListener("abort", settle, { once: true });
159
+ });
160
+ try {
161
+ const settled = await Promise.race([outcome, callerDone]);
162
+ if (settled.kind === "caller") {
163
+ throw new BoundedOperationWaitError(timedOut ? "timed-out" : "cancelled");
164
+ }
165
+ if (settled.kind === "error")
166
+ throw settled.error;
167
+ return settled.value;
168
+ } finally {
169
+ if (timer !== undefined)
170
+ clearTimeout(timer);
171
+ options.signal?.removeEventListener("abort", abortWork);
172
+ }
173
+ }
174
+
175
+ // src/application/admission.ts
97
176
  var PositiveSafeIntegerSchema = z.number().int().positive().safe();
98
177
  var BoundedRateBudgetSchema = z.object({
99
178
  limit: PositiveSafeIntegerSchema,
@@ -176,22 +255,59 @@ class BoundedOperationWaitError extends Error {
176
255
  this.name = "BoundedOperationWaitError";
177
256
  }
178
257
  }
258
+ var NO_REFUSALS = {
259
+ "not-accepting": 0,
260
+ "global-concurrency": 0,
261
+ "key-required": 0,
262
+ "key-capacity": 0,
263
+ "key-concurrency": 0,
264
+ "global-rate": 0,
265
+ "key-rate": 0,
266
+ upstream: 0
267
+ };
268
+ async function waitForDrain(drainWaiters, options) {
269
+ const controller = new AbortController;
270
+ let timer;
271
+ const abort = () => controller.abort();
272
+ if (options.signal?.aborted)
273
+ abort();
274
+ else
275
+ options.signal?.addEventListener("abort", abort, { once: true });
276
+ if (options.timeoutMs !== undefined) {
277
+ if (!Number.isSafeInteger(options.timeoutMs) || options.timeoutMs < 0) {
278
+ throw new TypeError("drain timeoutMs must be a non-negative safe integer");
279
+ }
280
+ timer = setTimeout(abort, options.timeoutMs);
281
+ }
282
+ let resolveDrained;
283
+ try {
284
+ await Promise.race([
285
+ new Promise((resolve) => {
286
+ resolveDrained = resolve;
287
+ drainWaiters.add(resolve);
288
+ }),
289
+ new Promise((resolve) => {
290
+ if (controller.signal.aborted)
291
+ resolve();
292
+ else
293
+ controller.signal.addEventListener("abort", () => resolve(), { once: true });
294
+ })
295
+ ]);
296
+ } finally {
297
+ if (timer !== undefined)
298
+ clearTimeout(timer);
299
+ options.signal?.removeEventListener("abort", abort);
300
+ if (resolveDrained)
301
+ drainWaiters.delete(resolveDrained);
302
+ }
303
+ }
179
304
  function createBoundedAdmission(config) {
180
305
  const policy = BoundedAdmissionPolicySchema.parse(config.policy);
181
306
  const clock = config.clock ?? { now: () => performance.now() };
182
307
  const keys = new Map;
183
308
  const globalRate = [];
184
309
  const drainWaiters = new Set;
185
- const refusals = {
186
- "not-accepting": 0,
187
- "global-concurrency": 0,
188
- "key-required": 0,
189
- "key-capacity": 0,
190
- "key-concurrency": 0,
191
- "global-rate": 0,
192
- "key-rate": 0,
193
- upstream: 0
194
- };
310
+ const refusals = { ...NO_REFUSALS };
195
311
  let state = "accepting";
196
312
  let active = 0;
197
313
  let accepted = 0;
@@ -219,26 +335,7 @@ function createBoundedAdmission(config) {
219
335
  ...perKey.rate && { rate: perKey.rate }
220
336
  });
221
337
  };
222
- const pruneRate = (samples, intervalMs, at) => {
223
- let expired = 0;
224
- while (expired < samples.length && at - (samples[expired]?.at ?? at) >= intervalMs) {
225
- expired += 1;
226
- }
227
- if (expired > 0)
228
- samples.splice(0, expired);
229
- };
230
- const prune = (at) => {
231
- if (policy.global.rate)
232
- pruneRate(globalRate, policy.global.rate.intervalMs, at);
233
- for (const [key, record] of keys) {
234
- if (record.limits?.rate) {
235
- pruneRate(record.rate, record.limits.rate.intervalMs, at);
236
- }
237
- if (record.active === 0 && record.rate.length === 0)
238
- keys.delete(key);
239
- }
240
- };
241
- const retryAfter = (samples, budget, at) => Math.max(1, Math.ceil(budget.intervalMs - (at - (samples[0]?.at ?? at))));
338
+ const prune = (at) => pruneExpired(policy, globalRate, keys, at);
242
339
  const refuse = (reason, retryAfterMs) => {
243
340
  refused += 1;
244
341
  refusals[reason] += 1;
@@ -260,16 +357,9 @@ function createBoundedAdmission(config) {
260
357
  active -= 1;
261
358
  if (keyRecord)
262
359
  keyRecord.active -= 1;
263
- if (globalSample) {
264
- const index = globalRate.indexOf(globalSample);
265
- if (index >= 0)
266
- globalRate.splice(index, 1);
267
- }
268
- if (keySample && keyRecord) {
269
- const index = keyRecord.rate.indexOf(keySample);
270
- if (index >= 0)
271
- keyRecord.rate.splice(index, 1);
272
- }
360
+ removeSample(globalRate, globalSample);
361
+ if (keyRecord)
362
+ removeSample(keyRecord.rate, keySample);
273
363
  if (key !== undefined && keyRecord?.active === 0 && keyRecord.rate.length === 0) {
274
364
  keys.delete(key);
275
365
  }
@@ -368,87 +458,10 @@ function createBoundedAdmission(config) {
368
458
  stopAdmission();
369
459
  if (active === 0)
370
460
  return { drained: true, remaining: 0 };
371
- const controller = new AbortController;
372
- let timer;
373
- const abort = () => controller.abort();
374
- if (options.signal?.aborted)
375
- abort();
376
- else
377
- options.signal?.addEventListener("abort", abort, { once: true });
378
- if (options.timeoutMs !== undefined) {
379
- if (!Number.isSafeInteger(options.timeoutMs) || options.timeoutMs < 0) {
380
- throw new TypeError("drain timeoutMs must be a non-negative safe integer");
381
- }
382
- timer = setTimeout(abort, options.timeoutMs);
383
- }
384
- let resolveDrained;
385
- try {
386
- await Promise.race([
387
- new Promise((resolve) => {
388
- resolveDrained = resolve;
389
- drainWaiters.add(resolve);
390
- }),
391
- new Promise((resolve) => {
392
- if (controller.signal.aborted)
393
- resolve();
394
- else
395
- controller.signal.addEventListener("abort", () => resolve(), { once: true });
396
- })
397
- ]);
398
- } finally {
399
- if (timer !== undefined)
400
- clearTimeout(timer);
401
- options.signal?.removeEventListener("abort", abort);
402
- if (resolveDrained)
403
- drainWaiters.delete(resolveDrained);
404
- }
461
+ await waitForDrain(drainWaiters, options);
405
462
  return { drained: active === 0, remaining: active };
406
463
  };
407
- const run = async (key, work, options = {}) => {
408
- if (options.timeoutMs !== undefined) {
409
- if (!Number.isSafeInteger(options.timeoutMs) || options.timeoutMs < 0) {
410
- throw new TypeError("run timeoutMs must be a non-negative safe integer");
411
- }
412
- }
413
- if (options.signal?.aborted)
414
- throw new BoundedOperationWaitError("cancelled");
415
- const admission = acquire(key);
416
- if (admission.outcome === "refused") {
417
- throw new BoundedAdmissionRefusalError(admission.reason, admission.retryAfterMs);
418
- }
419
- const workAbort = new AbortController;
420
- const abortWork = () => workAbort.abort(options.signal?.reason);
421
- options.signal?.addEventListener("abort", abortWork, { once: true });
422
- let timer;
423
- let timedOut = false;
424
- if (options.timeoutMs !== undefined) {
425
- timer = setTimeout(() => {
426
- timedOut = true;
427
- workAbort.abort(new DOMException("Operation wait timed out", "TimeoutError"));
428
- }, options.timeoutMs);
429
- }
430
- const outcome = Promise.resolve().then(() => work({ signal: workAbort.signal })).then((value) => ({ kind: "value", value }), (error) => ({ kind: "error", error })).finally(() => admission.lease.release());
431
- const callerDone = new Promise((resolve) => {
432
- const settle = () => resolve({ kind: "caller" });
433
- if (workAbort.signal.aborted)
434
- settle();
435
- else
436
- workAbort.signal.addEventListener("abort", settle, { once: true });
437
- });
438
- try {
439
- const settled = await Promise.race([outcome, callerDone]);
440
- if (settled.kind === "caller") {
441
- throw new BoundedOperationWaitError(timedOut ? "timed-out" : "cancelled");
442
- }
443
- if (settled.kind === "error")
444
- throw settled.error;
445
- return settled.value;
446
- } finally {
447
- if (timer !== undefined)
448
- clearTimeout(timer);
449
- options.signal?.removeEventListener("abort", abortWork);
450
- }
451
- };
464
+ const run = (key, work, options = {}) => runAdmitted(acquire, key, work, options);
452
465
  return {
453
466
  acquire,
454
467
  run,
@@ -815,37 +828,67 @@ var emptyOutboxState = () => ({
815
828
  });
816
829
  var sizeOf = (value) => measureSize(value).responseBytes;
817
830
  var DEFAULT_OUTBOX_BACKOFF = { minDelayMs: 1000, maxDelayMs: 60000, jitter: 0 };
818
- function createNotificationOutbox(config) {
819
- const schema = notificationOutboxStateSchema(config.payloadSchema);
820
- const clock = config.clock ?? (() => new Date);
821
- const ownerId = config.ownerId ?? crypto.randomUUID();
831
+ function resolveOutboxLimits(config) {
822
832
  const pollIntervalMs = z5.number().int().min(10).parse(config.pollIntervalMs ?? 1000);
823
833
  const leaseMs = z5.number().int().min(100).parse(config.leaseMs ?? 30000);
824
834
  const maxAttempts = z5.number().int().min(1).max(1e4).parse(config.maxAttempts ?? 100);
825
835
  const maxQueue = z5.number().int().min(1).max(1e5).parse(config.maxQueue ?? 1000);
826
836
  const maxStateBytes = z5.number().int().min(1024).parse(config.maxStateBytes ?? 1024 * 1024);
827
837
  const retainReceipts = z5.number().int().min(0).max(1e5).parse(config.retainReceipts ?? 1000);
838
+ return { pollIntervalMs, leaseMs, maxAttempts, maxQueue, maxStateBytes, retainReceipts };
839
+ }
840
+ function boundedOutboxState(parsed, maxQueue, retainReceipts, maxStateBytes) {
841
+ if (parsed.queue.length > maxQueue) {
842
+ throw new Error(`[stitchkit] notification outbox queue limit (${maxQueue}) exceeded`);
843
+ }
844
+ let receipts = parsed.receipts.slice(0, retainReceipts);
845
+ let next = { ...parsed, receipts };
846
+ while (sizeOf(next) > maxStateBytes && receipts.length > 0) {
847
+ receipts = receipts.slice(0, -1);
848
+ next = { ...parsed, receipts };
849
+ }
850
+ if (sizeOf(next) > maxStateBytes) {
851
+ throw new Error(`[stitchkit] notification outbox state limit (${maxStateBytes} bytes) exceeded`);
852
+ }
853
+ return next;
854
+ }
855
+ function dropReason(classification, attempts, maxAttempts) {
856
+ if (classification.recipientUnreachable === true)
857
+ return "recipient-unreachable";
858
+ if (!classification.retryable)
859
+ return "terminal";
860
+ return attempts >= maxAttempts ? "attempt-limit" : null;
861
+ }
862
+ var RetryDelaySchema = z5.number().nonnegative().max(24 * 60 * 60 * 1000);
863
+ var NO_LEASE = { leaseOwner: null, leaseId: null, leaseUntil: null };
864
+ function claimDue(queue, now, ownerId, leaseMs) {
865
+ const candidate = [...queue].sort((left, right) => Date.parse(left.createdAt) - Date.parse(right.createdAt)).find((item) => Date.parse(item.nextAttemptAt) <= now.getTime() && (item.leaseUntil === null || Date.parse(item.leaseUntil) <= now.getTime()));
866
+ if (!candidate)
867
+ return null;
868
+ return {
869
+ ...candidate,
870
+ attempts: candidate.attempts + 1,
871
+ leaseOwner: ownerId,
872
+ leaseId: crypto.randomUUID(),
873
+ leaseUntil: new Date(now.getTime() + leaseMs).toISOString()
874
+ };
875
+ }
876
+ async function reportOutboxError(config, error) {
877
+ try {
878
+ await config.onError?.(error);
879
+ } catch {}
880
+ }
881
+ function createNotificationOutbox(config) {
882
+ const schema = notificationOutboxStateSchema(config.payloadSchema);
883
+ const clock = config.clock ?? (() => new Date);
884
+ const ownerId = config.ownerId ?? crypto.randomUUID();
885
+ const { pollIntervalMs, leaseMs, maxAttempts, maxQueue, maxStateBytes, retainReceipts } = resolveOutboxLimits(config);
828
886
  const backoffMs = config.backoffMs ?? ((attempt) => backoffDelay(DEFAULT_OUTBOX_BACKOFF, attempt));
829
887
  let timer;
830
888
  let running = false;
831
889
  let interrupted = false;
832
890
  let flushTail = Promise.resolve();
833
- const bounded = (input) => {
834
- const parsed = schema.parse(input);
835
- if (parsed.queue.length > maxQueue) {
836
- throw new Error(`[stitchkit] notification outbox queue limit (${maxQueue}) exceeded`);
837
- }
838
- let receipts = parsed.receipts.slice(0, retainReceipts);
839
- let next = { ...parsed, receipts };
840
- while (sizeOf(next) > maxStateBytes && receipts.length > 0) {
841
- receipts = receipts.slice(0, -1);
842
- next = { ...parsed, receipts };
843
- }
844
- if (sizeOf(next) > maxStateBytes) {
845
- throw new Error(`[stitchkit] notification outbox state limit (${maxStateBytes} bytes) exceeded`);
846
- }
847
- return next;
848
- };
891
+ const bounded = (input) => boundedOutboxState(schema.parse(input), maxQueue, retainReceipts, maxStateBytes);
849
892
  const parse = (state) => schema.parse(state ?? emptyOutboxState());
850
893
  const enqueue = async (input) => {
851
894
  const key = z5.string().min(1).max(512).parse(input.key);
@@ -857,18 +900,10 @@ function createNotificationOutbox(config) {
857
900
  return { state, result: false };
858
901
  }
859
902
  const now = clock().toISOString();
903
+ const fresh = { key, payload, createdAt: now, attempts: 0, nextAttemptAt: now };
860
904
  const queue = [
861
905
  ...state.queue.filter((item) => !supersedes.has(item.key)),
862
- {
863
- key,
864
- payload,
865
- createdAt: now,
866
- attempts: 0,
867
- nextAttemptAt: now,
868
- leaseOwner: null,
869
- leaseId: null,
870
- leaseUntil: null
871
- }
906
+ { ...fresh, ...NO_LEASE }
872
907
  ];
873
908
  const next = bounded({ ...state, queue });
874
909
  return { state: next, result: true };
@@ -878,21 +913,13 @@ function createNotificationOutbox(config) {
878
913
  const now = clock();
879
914
  return config.store.update((current) => {
880
915
  const state = parse(current);
881
- const candidate = [...state.queue].sort((left, right) => Date.parse(left.createdAt) - Date.parse(right.createdAt)).find((item) => Date.parse(item.nextAttemptAt) <= now.getTime() && (item.leaseUntil === null || Date.parse(item.leaseUntil) <= now.getTime()));
882
- if (!candidate)
916
+ const claimed = claimDue(state.queue, now, ownerId, leaseMs);
917
+ if (!claimed)
883
918
  return { state, result: null };
884
- const leaseId = crypto.randomUUID();
885
- const claimed = {
886
- ...candidate,
887
- attempts: candidate.attempts + 1,
888
- leaseOwner: ownerId,
889
- leaseId,
890
- leaseUntil: new Date(now.getTime() + leaseMs).toISOString()
891
- };
892
919
  return {
893
920
  state: bounded({
894
921
  ...state,
895
- queue: state.queue.map((item) => item.key === candidate.key ? claimed : item)
922
+ queue: state.queue.map((item) => item.key === claimed.key ? claimed : item)
896
923
  }),
897
924
  result: claimed
898
925
  };
@@ -926,7 +953,7 @@ function createNotificationOutbox(config) {
926
953
  if (!live)
927
954
  return { state, result: null };
928
955
  const attempts = live.attempts;
929
- const reason = classification.recipientUnreachable === true ? "recipient-unreachable" : !classification.retryable ? "terminal" : attempts >= maxAttempts ? "attempt-limit" : null;
956
+ const reason = dropReason(classification, attempts, maxAttempts);
930
957
  if (reason) {
931
958
  return {
932
959
  state: bounded({
@@ -936,15 +963,11 @@ function createNotificationOutbox(config) {
936
963
  result: { item: { ...live, attempts }, error, reason }
937
964
  };
938
965
  }
939
- const rawDelay = backoffMs(attempts);
940
- const wait = z5.number().finite().nonnegative().max(24 * 60 * 60 * 1000).parse(rawDelay);
966
+ const wait = RetryDelaySchema.parse(backoffMs(attempts));
941
967
  const retry = {
942
968
  ...live,
943
- attempts,
944
969
  nextAttemptAt: new Date(clock().getTime() + wait).toISOString(),
945
- leaseOwner: null,
946
- leaseId: null,
947
- leaseUntil: null
970
+ ...NO_LEASE
948
971
  };
949
972
  return {
950
973
  state: bounded({
@@ -990,9 +1013,7 @@ function createNotificationOutbox(config) {
990
1013
  try {
991
1014
  await flush();
992
1015
  } catch (error) {
993
- try {
994
- await config.onError?.(error);
995
- } catch {}
1016
+ await reportOutboxError(config, error);
996
1017
  } finally {
997
1018
  schedule();
998
1019
  }
@@ -1552,59 +1573,60 @@ function managedServerResource(config) {
1552
1573
  }
1553
1574
  });
1554
1575
  }
1555
- // src/application/watch-hub.ts
1576
+ // src/application/watch-hub-core.ts
1556
1577
  var DEFAULT_BACKOFF = { minDelayMs: 250, maxDelayMs: 30000, jitter: 0.2 };
1557
- function watchKey(operation, args) {
1558
- const record = typeof args === "object" && args !== null && !Array.isArray(args) ? args : { value: args };
1559
- return {
1560
- service: operation.service,
1561
- action: operation.action,
1562
- digest: argumentsDigest(record)
1563
- };
1564
- }
1565
- function createWatchHub(config) {
1566
- const sources = new Map;
1567
- const held = new Map;
1568
- const maxWatches = config.maxWatchesPerSubscriber ?? 64;
1569
- const holdMs = config.holdMs ?? 0;
1570
- const deltaMemoryBytes = config.deltaMemoryBytes ?? 262144;
1571
- const same = config.same ?? ((previous, next) => serializeCanonicalJson(previous) === serializeCanonicalJson(next));
1572
- let reads = 0;
1573
- let closed = false;
1574
- function tell(key, deliver2) {
1578
+
1579
+ class WatchHubCore {
1580
+ config;
1581
+ sources = new Map;
1582
+ held = new Map;
1583
+ maxWatches;
1584
+ holdMs;
1585
+ deltaMemoryBytes;
1586
+ same;
1587
+ reads = 0;
1588
+ closed = false;
1589
+ constructor(config) {
1590
+ this.config = config;
1591
+ this.maxWatches = config.maxWatchesPerSubscriber ?? 64;
1592
+ this.holdMs = config.holdMs ?? 0;
1593
+ this.deltaMemoryBytes = config.deltaMemoryBytes ?? 262144;
1594
+ this.same = config.same ?? ((previous, next) => serializeCanonicalJson(previous) === serializeCanonicalJson(next));
1595
+ }
1596
+ tell(key, send) {
1575
1597
  try {
1576
- deliver2();
1598
+ send();
1577
1599
  return true;
1578
1600
  } catch (error) {
1579
- config.logger?.warn?.("[stitchkit] watch subscriber threw", {
1601
+ this.config.logger?.warn?.("[stitchkit] watch subscriber threw", {
1580
1602
  key: watchKeyString(key),
1581
1603
  error: error instanceof Error ? error.message : String(error)
1582
1604
  });
1583
1605
  return false;
1584
1606
  }
1585
1607
  }
1586
- function announceState(source, state) {
1608
+ announceState(source, state) {
1587
1609
  source.state = state;
1588
1610
  for (const subscriber of source.subscribers) {
1589
- tell(source.key, () => subscriber.state(state));
1611
+ this.tell(source.key, () => subscriber.state(state));
1590
1612
  }
1591
1613
  }
1592
- function remember(source, revision, value, fingerprint) {
1593
- if (deltaMemoryBytes === 0)
1614
+ remember(source, revision, value, fingerprint) {
1615
+ if (this.deltaMemoryBytes === 0)
1594
1616
  return;
1595
1617
  const bytes = (JSON.stringify(value) ?? "null").length;
1596
- if (bytes > deltaMemoryBytes)
1618
+ if (bytes > this.deltaMemoryBytes)
1597
1619
  return;
1598
1620
  source.history.set(revision, { value, fingerprint, bytes });
1599
1621
  source.historyBytes += bytes;
1600
1622
  for (const [oldest, entry] of source.history) {
1601
- if (source.historyBytes <= deltaMemoryBytes)
1623
+ if (source.historyBytes <= this.deltaMemoryBytes)
1602
1624
  break;
1603
1625
  source.history.delete(oldest);
1604
1626
  source.historyBytes -= entry.bytes;
1605
1627
  }
1606
1628
  }
1607
- function frameFor(source, subscriber) {
1629
+ frameFor(source, subscriber) {
1608
1630
  const value = source.value;
1609
1631
  const fingerprint = source.fingerprint ?? valueFingerprint(value);
1610
1632
  const full = {
@@ -1620,10 +1642,10 @@ function createWatchHub(config) {
1620
1642
  if (base === source.revision) {
1621
1643
  return { kind: "unchanged", key: source.key, revision: source.revision, fingerprint };
1622
1644
  }
1623
- const held2 = source.history.get(base);
1624
- if (!held2)
1645
+ const held = source.history.get(base);
1646
+ if (!held)
1625
1647
  return full;
1626
- const delta = diff(held2.value, value);
1648
+ const delta = diff(held.value, value);
1627
1649
  if (delta === undefined || !deltaWins(delta, value))
1628
1650
  return full;
1629
1651
  return {
@@ -1635,7 +1657,7 @@ function createWatchHub(config) {
1635
1657
  delta
1636
1658
  };
1637
1659
  }
1638
- function adoptBaseline(source, subscriber, have) {
1660
+ adoptBaseline(source, subscriber, have) {
1639
1661
  if (source.fingerprint === have.fingerprint) {
1640
1662
  source.baselines.set(subscriber, source.revision);
1641
1663
  return;
@@ -1652,56 +1674,56 @@ function createWatchHub(config) {
1652
1674
  return;
1653
1675
  }
1654
1676
  }
1655
- function deliver(source, subscriber) {
1656
- const frame = frameFor(source, subscriber);
1657
- const delivered = tell(source.key, () => subscriber.value(frame));
1677
+ deliver(source, subscriber) {
1678
+ const frame = this.frameFor(source, subscriber);
1679
+ const delivered = this.tell(source.key, () => subscriber.value(frame));
1658
1680
  if (delivered)
1659
1681
  source.baselines.set(subscriber, source.revision);
1660
1682
  return delivered;
1661
1683
  }
1662
- function publish(source, value, fingerprint) {
1684
+ publish(source, value, fingerprint) {
1663
1685
  if (source.fingerprint !== undefined) {
1664
- remember(source, source.revision, source.value, source.fingerprint);
1686
+ this.remember(source, source.revision, source.value, source.fingerprint);
1665
1687
  }
1666
1688
  source.revision += 1;
1667
1689
  source.value = value;
1668
1690
  source.fingerprint = fingerprint;
1669
1691
  for (const subscriber of source.subscribers)
1670
- deliver(source, subscriber);
1692
+ this.deliver(source, subscriber);
1671
1693
  }
1672
- async function pump(source) {
1673
- if (source.reading || closed)
1694
+ async pump(source) {
1695
+ if (source.reading || this.closed)
1674
1696
  return;
1675
1697
  source.reading = true;
1676
1698
  try {
1677
- while (source.dirty && !closed) {
1699
+ while (source.dirty && !this.closed) {
1678
1700
  source.dirty = false;
1679
- reads += 1;
1701
+ this.reads += 1;
1680
1702
  try {
1681
- const value = await config.read(source.operation, source.args);
1703
+ const value = await this.config.read(source.operation, source.args);
1682
1704
  source.backoff.reset();
1683
1705
  const signature = serializeCanonicalJson(value);
1684
- const unchanged = source.signature !== undefined && same(source.value, value);
1706
+ const unchanged = source.signature !== undefined && this.same(source.value, value);
1685
1707
  source.signature = signature;
1686
1708
  if (!unchanged)
1687
- publish(source, value, valueFingerprint(value));
1709
+ this.publish(source, value, valueFingerprint(value));
1688
1710
  if (source.state.phase !== "live") {
1689
- announceState(source, { key: source.key, phase: "live" });
1711
+ this.announceState(source, { key: source.key, phase: "live" });
1690
1712
  }
1691
1713
  } catch (error) {
1692
1714
  const code = readErrorCode(error);
1693
- announceState(source, {
1715
+ this.announceState(source, {
1694
1716
  key: source.key,
1695
1717
  phase: "unavailable",
1696
1718
  reason: "source-error",
1697
1719
  ...code !== undefined && { code },
1698
1720
  message: error instanceof Error ? error.message : String(error)
1699
1721
  });
1700
- config.logger?.warn?.("[stitchkit] watched read failed", {
1722
+ this.config.logger?.warn?.("[stitchkit] watched read failed", {
1701
1723
  key: watchKeyString(source.key),
1702
1724
  error
1703
1725
  });
1704
- scheduleRetry(source);
1726
+ this.scheduleRetry(source);
1705
1727
  return;
1706
1728
  }
1707
1729
  }
@@ -1709,19 +1731,19 @@ function createWatchHub(config) {
1709
1731
  source.reading = false;
1710
1732
  }
1711
1733
  }
1712
- function scheduleRetry(source) {
1713
- if (closed || source.subscribers.size === 0)
1734
+ scheduleRetry(source) {
1735
+ if (this.closed || source.subscribers.size === 0)
1714
1736
  return;
1715
1737
  clearTimeout(source.retry);
1716
1738
  source.retry = setTimeout(() => {
1717
1739
  source.dirty = true;
1718
- pump(source);
1740
+ this.pump(source);
1719
1741
  }, source.backoff.next());
1720
1742
  source.retry.unref?.();
1721
1743
  }
1722
- function acquire(operation, key, args) {
1744
+ acquire(operation, key, args) {
1723
1745
  const id = watchKeyString(key);
1724
- const existing = sources.get(id);
1746
+ const existing = this.sources.get(id);
1725
1747
  if (existing) {
1726
1748
  clearTimeout(existing.release);
1727
1749
  existing.release = undefined;
@@ -1740,18 +1762,18 @@ function createWatchHub(config) {
1740
1762
  reading: false,
1741
1763
  dirty: true,
1742
1764
  state: { key, phase: "opening" },
1743
- backoff: createBackoff(config.backoff ?? DEFAULT_BACKOFF)
1765
+ backoff: createBackoff(this.config.backoff ?? DEFAULT_BACKOFF)
1744
1766
  };
1745
- for (const topic of config.invalidatedBy(operation, args)) {
1746
- source.unsubscribes.push(config.subscribe(topic, () => {
1767
+ for (const topic of this.config.invalidatedBy(operation, args)) {
1768
+ source.unsubscribes.push(this.config.subscribe(topic, () => {
1747
1769
  source.dirty = true;
1748
- pump(source);
1770
+ this.pump(source);
1749
1771
  }));
1750
1772
  }
1751
- sources.set(id, source);
1773
+ this.sources.set(id, source);
1752
1774
  return source;
1753
1775
  }
1754
- function release(source) {
1776
+ release(source) {
1755
1777
  if (source.subscribers.size > 0)
1756
1778
  return;
1757
1779
  clearTimeout(source.retry);
@@ -1764,109 +1786,105 @@ function createWatchHub(config) {
1764
1786
  }
1765
1787
  for (const unsubscribe of source.unsubscribes)
1766
1788
  unsubscribe();
1767
- sources.delete(watchKeyString(source.key));
1789
+ this.sources.delete(watchKeyString(source.key));
1768
1790
  };
1769
- if (holdMs === 0) {
1791
+ if (this.holdMs === 0) {
1770
1792
  drop();
1771
1793
  return;
1772
1794
  }
1773
- source.release = setTimeout(drop, holdMs);
1795
+ source.release = setTimeout(drop, this.holdMs);
1774
1796
  source.release.unref?.();
1775
1797
  }
1776
- return {
1777
- attach(subscriber) {
1778
- const keys = new Set;
1779
- held.set(subscriber, keys);
1780
- return {
1781
- open(key, args, have) {
1782
- if (closed)
1783
- return { accepted: false, reason: "the watch hub is closed" };
1784
- const operation = { service: key.service, action: key.action };
1785
- if (!config.watchable(operation)) {
1786
- return {
1787
- accepted: false,
1788
- reason: `${key.service}.${key.action} is not watchable`
1789
- };
1790
- }
1791
- const id = watchKeyString(key);
1792
- if (keys.has(id))
1793
- return { accepted: true };
1794
- if (keys.size >= maxWatches) {
1795
- return {
1796
- accepted: false,
1797
- reason: `this connection is already watching ${keys.size} reads (limit ${maxWatches})`
1798
- };
1799
- }
1800
- const source = acquire(operation, key, args);
1801
- source.subscribers.add(subscriber);
1802
- keys.add(id);
1803
- if (have)
1804
- adoptBaseline(source, subscriber, have);
1805
- try {
1806
- if (source.signature !== undefined) {
1807
- const frame = frameFor(source, subscriber);
1808
- subscriber.value(frame);
1809
- source.baselines.set(subscriber, source.revision);
1810
- }
1811
- subscriber.state(source.state);
1812
- } catch (error) {
1813
- source.subscribers.delete(subscriber);
1814
- source.baselines.delete(subscriber);
1815
- keys.delete(id);
1816
- release(source);
1817
- return {
1818
- accepted: false,
1819
- reason: error instanceof Error ? error.message : String(error)
1820
- };
1821
- }
1822
- pump(source);
1798
+ attach(subscriber) {
1799
+ const keys = new Set;
1800
+ this.held.set(subscriber, keys);
1801
+ return {
1802
+ open: (key, args, have) => {
1803
+ if (this.closed)
1804
+ return { accepted: false, reason: "the watch hub is closed" };
1805
+ const operation = { service: key.service, action: key.action };
1806
+ if (!this.config.watchable(operation)) {
1807
+ return {
1808
+ accepted: false,
1809
+ reason: `${key.service}.${key.action} is not watchable`
1810
+ };
1811
+ }
1812
+ const id = watchKeyString(key);
1813
+ if (keys.has(id))
1823
1814
  return { accepted: true };
1824
- },
1825
- close(key) {
1826
- const id = watchKeyString(key);
1827
- if (!keys.delete(id))
1828
- return;
1829
- const source = sources.get(id);
1815
+ if (keys.size >= this.maxWatches) {
1816
+ return {
1817
+ accepted: false,
1818
+ reason: `this connection is already watching ${keys.size} reads (limit ${this.maxWatches})`
1819
+ };
1820
+ }
1821
+ const source = this.acquire(operation, key, args);
1822
+ source.subscribers.add(subscriber);
1823
+ keys.add(id);
1824
+ if (have)
1825
+ this.adoptBaseline(source, subscriber, have);
1826
+ try {
1827
+ if (source.signature !== undefined) {
1828
+ const frame = this.frameFor(source, subscriber);
1829
+ subscriber.value(frame);
1830
+ source.baselines.set(subscriber, source.revision);
1831
+ }
1832
+ subscriber.state(source.state);
1833
+ } catch (error) {
1834
+ source.subscribers.delete(subscriber);
1835
+ source.baselines.delete(subscriber);
1836
+ keys.delete(id);
1837
+ this.release(source);
1838
+ return {
1839
+ accepted: false,
1840
+ reason: error instanceof Error ? error.message : String(error)
1841
+ };
1842
+ }
1843
+ this.pump(source);
1844
+ return { accepted: true };
1845
+ },
1846
+ close: (key) => {
1847
+ const id = watchKeyString(key);
1848
+ if (!keys.delete(id))
1849
+ return;
1850
+ const source = this.sources.get(id);
1851
+ if (!source)
1852
+ return;
1853
+ source.subscribers.delete(subscriber);
1854
+ source.baselines.delete(subscriber);
1855
+ this.release(source);
1856
+ },
1857
+ detach: () => {
1858
+ for (const id of keys) {
1859
+ const source = this.sources.get(id);
1830
1860
  if (!source)
1831
- return;
1861
+ continue;
1832
1862
  source.subscribers.delete(subscriber);
1833
1863
  source.baselines.delete(subscriber);
1834
- release(source);
1835
- },
1836
- detach() {
1837
- for (const id of keys) {
1838
- const source = sources.get(id);
1839
- if (!source)
1840
- continue;
1841
- source.subscribers.delete(subscriber);
1842
- source.baselines.delete(subscriber);
1843
- release(source);
1844
- }
1845
- keys.clear();
1846
- held.delete(subscriber);
1864
+ this.release(source);
1847
1865
  }
1848
- };
1849
- },
1850
- readCount: () => reads,
1851
- size: () => sources.size,
1852
- close() {
1853
- closed = true;
1854
- const teardown = [...sources.values()];
1855
- sources.clear();
1856
- held.clear();
1857
- for (const source of teardown) {
1858
- clearTimeout(source.retry);
1859
- clearTimeout(source.release);
1860
- announceState(source, {
1861
- key: source.key,
1862
- phase: "unavailable",
1863
- reason: "source-unavailable"
1864
- });
1865
- for (const unsubscribe of source.unsubscribes)
1866
- unsubscribe();
1866
+ keys.clear();
1867
+ this.held.delete(subscriber);
1867
1868
  }
1869
+ };
1870
+ }
1871
+ close() {
1872
+ this.closed = true;
1873
+ const teardown = [...this.sources.values()];
1874
+ this.sources.clear();
1875
+ this.held.clear();
1876
+ for (const source of teardown) {
1877
+ clearTimeout(source.retry);
1878
+ clearTimeout(source.release);
1879
+ this.announceState(source, {
1880
+ key: source.key,
1881
+ phase: "unavailable",
1882
+ reason: "source-unavailable"
1883
+ });
1884
+ for (const unsubscribe of source.unsubscribes)
1885
+ unsubscribe();
1868
1886
  }
1869
- };
1887
+ }
1870
1888
  }
1871
1889
  function valueFingerprint(value) {
1872
1890
  return argumentsDigest({ value });
@@ -1877,6 +1895,25 @@ function readErrorCode(error) {
1877
1895
  const code = Reflect.get(error, "code");
1878
1896
  return typeof code === "string" ? code : undefined;
1879
1897
  }
1898
+
1899
+ // src/application/watch-hub.ts
1900
+ function watchKey(operation, args) {
1901
+ const record = typeof args === "object" && args !== null && !Array.isArray(args) ? args : { value: args };
1902
+ return {
1903
+ service: operation.service,
1904
+ action: operation.action,
1905
+ digest: argumentsDigest(record)
1906
+ };
1907
+ }
1908
+ function createWatchHub(config) {
1909
+ const hub = new WatchHubCore(config);
1910
+ return {
1911
+ attach: (subscriber) => hub.attach(subscriber),
1912
+ readCount: () => hub.reads,
1913
+ size: () => hub.sources.size,
1914
+ close: () => hub.close()
1915
+ };
1916
+ }
1880
1917
  export {
1881
1918
  watchKey,
1882
1919
  transitionProcessStart,