@lostgradient/weft 0.3.0 → 0.5.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 (510) hide show
  1. package/README.md +79 -24
  2. package/dist/cli/conformance.js +7 -1
  3. package/dist/cli/generated/operation-client.generated.d.ts +28 -13
  4. package/dist/cli/generated/operation-client.generated.js +1 -0
  5. package/dist/cli/help-text.d.ts +1 -1
  6. package/dist/cli/help-text.js +1 -0
  7. package/dist/cli/operation-catalog-snapshot.d.ts +8 -0
  8. package/dist/cli/operation-catalog-snapshot.js +11 -0
  9. package/dist/cli/parse-schedule-arguments.js +3 -1
  10. package/dist/cli/schedule.js +2 -1
  11. package/dist/cli/types.d.ts +1 -0
  12. package/dist/cli-main.js +79 -78
  13. package/dist/client/handle-delegation.d.ts +3 -2
  14. package/dist/client/handle-delegation.js +3 -1
  15. package/dist/client/http-client-requests.d.ts +2 -1
  16. package/dist/client/http-client-requests.js +7 -0
  17. package/dist/client/http-client.d.ts +9 -6
  18. package/dist/client/http-client.js +10 -1
  19. package/dist/client/http-request.d.ts +11 -1
  20. package/dist/client/http-request.js +17 -7
  21. package/dist/client/index.d.ts +1 -1
  22. package/dist/client/interface.d.ts +61 -5
  23. package/dist/client/local-handles.d.ts +22 -0
  24. package/dist/client/local-handles.js +23 -0
  25. package/dist/client/local.d.ts +6 -3
  26. package/dist/client/local.js +12 -26
  27. package/dist/client/start-body.d.ts +4 -3
  28. package/dist/core/byte-arrays.d.ts +5 -0
  29. package/dist/core/byte-arrays.js +5 -0
  30. package/dist/core/checkpoint/lifecycle.d.ts +3 -0
  31. package/dist/core/checkpoint/lifecycle.js +9 -4
  32. package/dist/core/checkpoint/serialization.js +12 -5
  33. package/dist/core/codec/extension-codec.d.ts +16 -0
  34. package/dist/core/codec/extension-codec.js +100 -6
  35. package/dist/core/context/activity-retry-state.d.ts +38 -0
  36. package/dist/core/context/activity-retry-state.js +89 -0
  37. package/dist/core/context/activity-schedule-to-close.d.ts +159 -0
  38. package/dist/core/context/activity-schedule-to-close.js +69 -0
  39. package/dist/core/context/child-workflow-pipe.d.ts +5 -5
  40. package/dist/core/context/child-workflow-pipe.js +15 -2
  41. package/dist/core/context/context-presence.d.ts +19 -0
  42. package/dist/core/context/context-presence.js +13 -0
  43. package/dist/core/context/durable-operations.d.ts +25 -0
  44. package/dist/core/context/durable-operations.js +64 -0
  45. package/dist/core/context/index.d.ts +9 -5
  46. package/dist/core/context/index.js +17 -12
  47. package/dist/core/context/internals.d.ts +20 -0
  48. package/dist/core/context/internals.js +3 -1
  49. package/dist/core/context/operation-request.d.ts +35 -0
  50. package/dist/core/context/parallel-cache-entry.d.ts +14 -5
  51. package/dist/core/context/run-operation.d.ts +6 -1
  52. package/dist/core/context/run-operation.js +41 -87
  53. package/dist/core/context/session-state.js +7 -8
  54. package/dist/core/context/speculative-child.js +2 -0
  55. package/dist/core/context/types.d.ts +15 -0
  56. package/dist/core/context/version-patching.d.ts +8 -0
  57. package/dist/core/context/version-patching.js +40 -0
  58. package/dist/core/context/workflow-logger.d.ts +98 -0
  59. package/dist/core/context/workflow-logger.js +68 -0
  60. package/dist/core/engine/activity-heartbeat-tracking.d.ts +64 -0
  61. package/dist/core/engine/activity-heartbeat-tracking.js +42 -0
  62. package/dist/core/engine/activity-per-attempt-timeout.d.ts +46 -0
  63. package/dist/core/engine/activity-per-attempt-timeout.js +36 -0
  64. package/dist/core/engine/activity-reconciliation.d.ts +1 -0
  65. package/dist/core/engine/activity-reconciliation.js +12 -1
  66. package/dist/core/engine/activity-resolution.d.ts +23 -0
  67. package/dist/core/engine/activity-resolution.js +37 -0
  68. package/dist/core/engine/aggregate.js +66 -30
  69. package/dist/core/engine/async-activity-completion.d.ts +23 -6
  70. package/dist/core/engine/async-activity-completion.js +53 -12
  71. package/dist/core/engine/attributes-tags.js +9 -4
  72. package/dist/core/engine/bulk-operations-purge.d.ts +26 -0
  73. package/dist/core/engine/bulk-operations-purge.js +38 -3
  74. package/dist/core/engine/bulk-operations-shared.d.ts +2 -0
  75. package/dist/core/engine/bulk-operations-shared.js +8 -2
  76. package/dist/core/engine/bulk-operations.d.ts +4 -1
  77. package/dist/core/engine/bulk-operations.js +235 -24
  78. package/dist/core/engine/callback-creators-bundles.d.ts +9 -0
  79. package/dist/core/engine/callback-creators-bundles.js +30 -2
  80. package/dist/core/engine/callback-creators-core.js +6 -4
  81. package/dist/core/engine/callback-creators-router.js +10 -0
  82. package/dist/core/engine/callback-creators-schedule.d.ts +2 -2
  83. package/dist/core/engine/callback-creators-schedule.js +12 -8
  84. package/dist/core/engine/candidate-read-batching.d.ts +6 -0
  85. package/dist/core/engine/candidate-read-batching.js +1 -0
  86. package/dist/core/engine/checkpoint-io.js +61 -25
  87. package/dist/core/engine/checkpoint-reads.js +3 -2
  88. package/dist/core/engine/checkpoint-replay.d.ts +20 -0
  89. package/dist/core/engine/checkpoint-replay.js +242 -0
  90. package/dist/core/engine/checkpoint-side-effects.d.ts +23 -0
  91. package/dist/core/engine/checkpoint-side-effects.js +35 -0
  92. package/dist/core/engine/child-workflow-cancellation.d.ts +10 -0
  93. package/dist/core/engine/child-workflow-cancellation.js +40 -0
  94. package/dist/core/engine/child-workflow.js +27 -4
  95. package/dist/core/engine/condition-waiters.d.ts +14 -0
  96. package/dist/core/engine/condition-waiters.js +5 -0
  97. package/dist/core/engine/construction.d.ts +3 -0
  98. package/dist/core/engine/construction.js +21 -8
  99. package/dist/core/engine/coordination-branch-executors.d.ts +70 -0
  100. package/dist/core/engine/coordination-branch-executors.js +107 -0
  101. package/dist/core/engine/deferred-consume-envelope.d.ts +59 -0
  102. package/dist/core/engine/deferred-consume-envelope.js +14 -0
  103. package/dist/core/engine/disposal.js +13 -0
  104. package/dist/core/engine/engine-create-types.d.ts +14 -4
  105. package/dist/core/engine/engine-internal-types.d.ts +26 -3
  106. package/dist/core/engine/errors.d.ts +47 -0
  107. package/dist/core/engine/errors.js +20 -0
  108. package/dist/core/engine/event-log-compaction.d.ts +8 -0
  109. package/dist/core/engine/event-log-compaction.js +20 -2
  110. package/dist/core/engine/fenced-write.d.ts +65 -0
  111. package/dist/core/engine/fenced-write.js +71 -0
  112. package/dist/core/engine/finalizer-state.d.ts +28 -0
  113. package/dist/core/engine/finalizer-state.js +16 -0
  114. package/dist/core/engine/handles.d.ts +8 -0
  115. package/dist/core/engine/index.d.ts +34 -16
  116. package/dist/core/engine/index.js +136 -9
  117. package/dist/core/engine/inline-parking.js +3 -2
  118. package/dist/core/engine/internals.d.ts +107 -3
  119. package/dist/core/engine/lease-codec.d.ts +35 -0
  120. package/dist/core/engine/lease-codec.js +32 -0
  121. package/dist/core/engine/lease-deposition.d.ts +66 -0
  122. package/dist/core/engine/lease-deposition.js +10 -0
  123. package/dist/core/engine/lease-errors.d.ts +99 -0
  124. package/dist/core/engine/lease-errors.js +30 -0
  125. package/dist/core/engine/lease-manager.d.ts +114 -0
  126. package/dist/core/engine/lease-manager.js +135 -0
  127. package/dist/core/engine/lifecycle/persist.js +10 -32
  128. package/dist/core/engine/lifecycle/recovered-services.d.ts +8 -6
  129. package/dist/core/engine/lifecycle/recovered-services.js +18 -3
  130. package/dist/core/engine/lifecycle/resume.js +16 -9
  131. package/dist/core/engine/lifecycle/shared.d.ts +8 -1
  132. package/dist/core/engine/lifecycle/start-batch.d.ts +1 -1
  133. package/dist/core/engine/lifecycle/start-batch.js +2 -1
  134. package/dist/core/engine/lifecycle/start-commit.d.ts +9 -0
  135. package/dist/core/engine/lifecycle/start-commit.js +50 -8
  136. package/dist/core/engine/lifecycle/start-or-signal-create.d.ts +58 -0
  137. package/dist/core/engine/lifecycle/start-or-signal-create.js +95 -0
  138. package/dist/core/engine/lifecycle/start-or-signal.d.ts +3 -2
  139. package/dist/core/engine/lifecycle/start-or-signal.js +11 -81
  140. package/dist/core/engine/lifecycle/start-terminal-conflict-purge.d.ts +39 -0
  141. package/dist/core/engine/lifecycle/start-terminal-conflict-purge.js +28 -0
  142. package/dist/core/engine/lifecycle/start.d.ts +4 -4
  143. package/dist/core/engine/lifecycle/start.js +17 -9
  144. package/dist/core/engine/lifecycle/transition.js +17 -5
  145. package/dist/core/engine/lifecycle.d.ts +1 -1
  146. package/dist/core/engine/list-candidate-resolution.js +2 -2
  147. package/dist/core/engine/listing.js +9 -5
  148. package/dist/core/engine/operations-activity.d.ts +6 -13
  149. package/dist/core/engine/operations-activity.js +26 -53
  150. package/dist/core/engine/operations-coordination.d.ts +10 -0
  151. package/dist/core/engine/operations-coordination.js +44 -9
  152. package/dist/core/engine/operations-router.d.ts +6 -0
  153. package/dist/core/engine/operations-router.js +2 -0
  154. package/dist/core/engine/operations-speculate.js +6 -2
  155. package/dist/core/engine/operations-stream.js +12 -2
  156. package/dist/core/engine/operations-time.d.ts +4 -2
  157. package/dist/core/engine/operations-time.js +14 -2
  158. package/dist/core/engine/operations-wait-condition.d.ts +23 -0
  159. package/dist/core/engine/operations-wait-condition.js +62 -0
  160. package/dist/core/engine/ownership-options.d.ts +23 -0
  161. package/dist/core/engine/ownership-options.js +26 -0
  162. package/dist/core/engine/payload-size-policy.d.ts +3 -0
  163. package/dist/core/engine/payload-size-policy.js +4 -0
  164. package/dist/core/engine/pending-updates.d.ts +17 -0
  165. package/dist/core/engine/pending-updates.js +33 -11
  166. package/dist/core/engine/queries.js +1 -1
  167. package/dist/core/engine/registration.d.ts +1 -0
  168. package/dist/core/engine/registration.js +18 -3
  169. package/dist/core/engine/schedule-jitter.d.ts +5 -0
  170. package/dist/core/engine/schedule-jitter.js +10 -0
  171. package/dist/core/engine/schedule-run.d.ts +17 -0
  172. package/dist/core/engine/schedule-run.js +38 -0
  173. package/dist/core/engine/schedule-timer.js +81 -17
  174. package/dist/core/engine/schedules.d.ts +7 -4
  175. package/dist/core/engine/schedules.js +37 -16
  176. package/dist/core/engine/search-attribute-records.d.ts +4 -0
  177. package/dist/core/engine/search-attribute-records.js +17 -0
  178. package/dist/core/engine/signals.d.ts +18 -2
  179. package/dist/core/engine/signals.js +42 -21
  180. package/dist/core/engine/state-utilities.d.ts +49 -2
  181. package/dist/core/engine/state-utilities.js +114 -3
  182. package/dist/core/engine/storage-io.d.ts +16 -2
  183. package/dist/core/engine/storage-io.js +26 -5
  184. package/dist/core/engine/stream-chunk-loading.d.ts +2 -0
  185. package/dist/core/engine/stream-chunk-loading.js +24 -1
  186. package/dist/core/engine/sub-operation.js +25 -6
  187. package/dist/core/engine/termination/cleanup.d.ts +3 -1
  188. package/dist/core/engine/termination/cleanup.js +25 -1
  189. package/dist/core/engine/termination/complete.js +44 -6
  190. package/dist/core/engine/termination/finalizer-activity.d.ts +53 -0
  191. package/dist/core/engine/termination/finalizer-activity.js +30 -0
  192. package/dist/core/engine/termination/finalizer-claim.d.ts +110 -0
  193. package/dist/core/engine/termination/finalizer-claim.js +80 -0
  194. package/dist/core/engine/termination/finalizer.d.ts +48 -0
  195. package/dist/core/engine/termination/finalizer.js +159 -0
  196. package/dist/core/engine/termination/suspend.d.ts +3 -1
  197. package/dist/core/engine/termination.d.ts +1 -0
  198. package/dist/core/engine/termination.js +4 -0
  199. package/dist/core/engine/updates.js +5 -25
  200. package/dist/core/engine/validation/schedule.d.ts +2 -1
  201. package/dist/core/engine/validation/schedule.js +51 -2
  202. package/dist/core/engine/validation.js +32 -5
  203. package/dist/core/engine/waiting-update-response.d.ts +8 -0
  204. package/dist/core/engine/waiting-update-response.js +22 -0
  205. package/dist/core/engine/workflow-concurrency.d.ts +10 -0
  206. package/dist/core/engine/workflow-concurrency.js +136 -0
  207. package/dist/core/engine/workflow-feed.d.ts +4 -5
  208. package/dist/core/engine/workflow-feed.js +4 -1
  209. package/dist/core/engine/workflow-indexes.d.ts +9 -0
  210. package/dist/core/engine/workflow-indexes.js +10 -0
  211. package/dist/core/engine/workflow-state-stream.js +33 -13
  212. package/dist/core/engine/workflow-visibility-queries.d.ts +2 -2
  213. package/dist/core/engine-helpers.js +1 -0
  214. package/dist/core/events/activity-events.d.ts +43 -12
  215. package/dist/core/events/activity-events.js +28 -0
  216. package/dist/core/events/attribute-events.d.ts +2 -3
  217. package/dist/core/events/event-map.d.ts +18 -12
  218. package/dist/core/events/index.d.ts +1 -0
  219. package/dist/core/events/index.js +1 -0
  220. package/dist/core/events/schedule-events.d.ts +71 -0
  221. package/dist/core/events/schedule-events.js +29 -0
  222. package/dist/core/events/signal-events.d.ts +4 -6
  223. package/dist/core/events/system-events.d.ts +29 -19
  224. package/dist/core/events/system-events.js +26 -0
  225. package/dist/core/events/update-events.d.ts +6 -8
  226. package/dist/core/events/workflow-events.d.ts +88 -23
  227. package/dist/core/events/workflow-events.js +26 -0
  228. package/dist/core/failure-categories.js +5 -17
  229. package/dist/core/fault-code.d.ts +9 -3
  230. package/dist/core/fault-code.js +1 -0
  231. package/dist/core/inline-execution-strategy.context-options.d.ts +69 -0
  232. package/dist/core/inline-execution-strategy.context-options.js +56 -0
  233. package/dist/core/inline-execution-strategy.d.ts +31 -36
  234. package/dist/core/inline-execution-strategy.js +16 -27
  235. package/dist/core/list-filter-validation.d.ts +1 -1
  236. package/dist/core/payload-size.d.ts +1 -1
  237. package/dist/core/persisted-data-incompatible-error.d.ts +9 -7
  238. package/dist/core/review/events.d.ts +6 -8
  239. package/dist/core/scheduler/scheduler-class.d.ts +10 -1
  240. package/dist/core/scheduler/scheduler-class.js +38 -11
  241. package/dist/core/scheduler/timer-batch.js +9 -1
  242. package/dist/core/scheduler/timer-sources.d.ts +1 -0
  243. package/dist/core/scheduler/timer-sources.js +11 -5
  244. package/dist/core/session-state.d.ts +0 -1
  245. package/dist/core/session-state.js +2 -2
  246. package/dist/core/start-workflow-validation.d.ts +34 -0
  247. package/dist/core/start-workflow-validation.js +19 -0
  248. package/dist/core/types/activity-verification.d.ts +67 -0
  249. package/dist/core/types/activity-verification.js +0 -0
  250. package/dist/core/types/activity.d.ts +80 -61
  251. package/dist/core/types/bulk.d.ts +50 -9
  252. package/dist/core/types/checkpoint.d.ts +44 -8
  253. package/dist/core/types/list-options.d.ts +146 -0
  254. package/dist/core/types/list-options.js +0 -0
  255. package/dist/core/types/options.d.ts +121 -165
  256. package/dist/core/types/schedules.d.ts +39 -3
  257. package/dist/core/types/services-resolution.d.ts +2 -2
  258. package/dist/core/types/workflow-builder-runtime.d.ts +12 -3
  259. package/dist/core/types/workflow-builder-runtime.js +11 -2
  260. package/dist/core/types/workflow-builder.d.ts +42 -11
  261. package/dist/core/types/workflow-concurrency.d.ts +39 -0
  262. package/dist/core/types/workflow-concurrency.js +0 -0
  263. package/dist/core/types/workflow-context.d.ts +157 -14
  264. package/dist/core/types/workflow-definition.d.ts +53 -10
  265. package/dist/core/types/workflow-function.d.ts +84 -9
  266. package/dist/core/types/workflow-log.d.ts +98 -0
  267. package/dist/core/types/workflow-log.js +0 -0
  268. package/dist/core/types/workflow-registries.d.ts +14 -3
  269. package/dist/core/types/workflow-registry.d.ts +3 -0
  270. package/dist/core/types.d.ts +4 -0
  271. package/dist/core/types.js +4 -0
  272. package/dist/core/versioning.d.ts +9 -39
  273. package/dist/core/versioning.js +2 -12
  274. package/dist/core/weft-error.d.ts +44 -1
  275. package/dist/core/weft-error.js +16 -0
  276. package/dist/core/worker-execution-strategy-options.d.ts +26 -0
  277. package/dist/core/worker-execution-strategy.js +40 -36
  278. package/dist/core/worker-inbound-message.d.ts +38 -0
  279. package/dist/core/worker-inbound-message.js +37 -0
  280. package/dist/core/worker-log-abuse-counter.d.ts +175 -0
  281. package/dist/core/worker-log-abuse-counter.js +107 -0
  282. package/dist/core/worker-message-helpers.d.ts +47 -0
  283. package/dist/core/worker-message-helpers.js +26 -0
  284. package/dist/core/worker-protocol-guard.js +1 -1
  285. package/dist/core/worker-protocol-log.d.ts +56 -0
  286. package/dist/core/worker-protocol-log.js +18 -0
  287. package/dist/core/worker-protocol.d.ts +23 -0
  288. package/dist/core/worker-protocol.js +12 -2
  289. package/dist/core/workflow-version-tuple.d.ts +3 -9
  290. package/dist/core/workflow-version-tuple.js +2 -3
  291. package/dist/diagnostics/format.js +1 -6
  292. package/dist/diagnostics/types.d.ts +4 -5
  293. package/dist/diagnostics/validate.d.ts +0 -1
  294. package/dist/diagnostics/version-check.d.ts +1 -1
  295. package/dist/diagnostics/version-check.js +4 -9
  296. package/dist/index.d.ts +12 -10
  297. package/dist/index.js +29 -3
  298. package/dist/json-schema.js +3 -3
  299. package/dist/mcp/cli.js +19 -19
  300. package/dist/mcp/dispatcher.js +1 -1
  301. package/dist/mcp/http.js +16 -6
  302. package/dist/mcp/protocol.d.ts +2 -0
  303. package/dist/mcp/protocol.js +1 -1
  304. package/dist/mcp/session.d.ts +16 -0
  305. package/dist/mcp/session.js +59 -6
  306. package/dist/mcp/tools.js +73 -6
  307. package/dist/observability/index.js +2 -2
  308. package/dist/server/asyncapi-channels.js +5 -2
  309. package/dist/server/attribute-filters.d.ts +8 -3
  310. package/dist/server/attribute-filters.js +6 -1
  311. package/dist/server/authentication/api-key.d.ts +2 -1
  312. package/dist/server/authentication/api-key.js +5 -2
  313. package/dist/server/authentication/constant-time-api-key.d.ts +15 -0
  314. package/dist/server/authentication/constant-time-api-key.js +24 -0
  315. package/dist/server/authentication/index.d.ts +1 -1
  316. package/dist/server/authentication/index.js +7 -4
  317. package/dist/server/authentication/rotating-api-key-store.d.ts +5 -3
  318. package/dist/server/authentication/rotating-api-key-store.js +19 -11
  319. package/dist/server/engine-event-feed-backend.d.ts +4 -5
  320. package/dist/server/fault-to-http.js +8 -1
  321. package/dist/server/fault-to-json-rpc.js +1 -0
  322. package/dist/server/fleet-event-feed.d.ts +31 -0
  323. package/dist/server/fleet-event-feed.js +157 -0
  324. package/dist/server/handler/index.js +1 -1
  325. package/dist/server/handler/response-helpers.js +2 -1
  326. package/dist/server/handler/route-dispatch.d.ts +6 -3
  327. package/dist/server/handler/route-dispatch.js +2 -2
  328. package/dist/server/handler.js +23 -23
  329. package/dist/server/index.d.ts +32 -2
  330. package/dist/server/index.js +32 -32
  331. package/dist/server/json-rpc-transport-helpers.d.ts +1 -0
  332. package/dist/server/json-rpc-transport-helpers.js +2 -1
  333. package/dist/server/json-rpc-websocket-runtime.d.ts +11 -2
  334. package/dist/server/json-rpc-websocket-runtime.js +1 -0
  335. package/dist/server/json-rpc-websocket-subscriptions.d.ts +10 -0
  336. package/dist/server/json-rpc-websocket-subscriptions.js +29 -0
  337. package/dist/server/json-rpc-websocket-types.d.ts +22 -0
  338. package/dist/server/json-rpc-websocket-types.js +0 -0
  339. package/dist/server/json-rpc-websocket-validation.js +20 -4
  340. package/dist/server/json-rpc-websocket.d.ts +2 -43
  341. package/dist/server/json-rpc-websocket.js +57 -74
  342. package/dist/server/openapi.d.ts +2 -1
  343. package/dist/server/openapi.js +1 -3
  344. package/dist/server/openrpc-document-schema.d.ts +78 -0
  345. package/dist/server/openrpc-document-schema.js +27 -1
  346. package/dist/server/openrpc-errors.d.ts +3 -0
  347. package/dist/server/openrpc-errors.js +2 -1
  348. package/dist/server/openrpc.js +32 -0
  349. package/dist/server/operation-catalog/index.d.ts +1 -1
  350. package/dist/server/operation-catalog/pipeline-helpers.js +1 -0
  351. package/dist/server/operation-catalog/pipeline-stages.js +26 -12
  352. package/dist/server/operation-catalog/pipeline.js +8 -1
  353. package/dist/server/operation-catalog/registry.js +13 -0
  354. package/dist/server/operation-catalog/types.d.ts +20 -9
  355. package/dist/server/operation-fault.d.ts +10 -0
  356. package/dist/server/operation-fault.js +2 -0
  357. package/dist/server/operation-registry.d.ts +12 -11
  358. package/dist/server/operation-registry.js +12 -3
  359. package/dist/server/operations/aggregate-workflows.d.ts +15 -15
  360. package/dist/server/operations/async-activity.d.ts +2 -2
  361. package/dist/server/operations/async-activity.js +12 -7
  362. package/dist/server/operations/bulk-cancel-workflows.d.ts +1 -1
  363. package/dist/server/operations/bulk-cancel-workflows.js +2 -2
  364. package/dist/server/operations/bulk-delete-workflows.d.ts +1 -1
  365. package/dist/server/operations/bulk-delete-workflows.js +2 -2
  366. package/dist/server/operations/bulk-filter-helpers.d.ts +8 -6
  367. package/dist/server/operations/bulk-filter-helpers.js +54 -24
  368. package/dist/server/operations/bulk-mutate-workflow-tags.d.ts +11 -9
  369. package/dist/server/operations/bulk-mutate-workflow-tags.js +2 -2
  370. package/dist/server/operations/bulk-operation-helpers.d.ts +2 -2
  371. package/dist/server/operations/bulk-retry-failed-workflows.d.ts +7 -0
  372. package/dist/server/operations/bulk-retry-failed-workflows.js +64 -0
  373. package/dist/server/operations/bulk-signal-workflows.d.ts +11 -9
  374. package/dist/server/operations/bulk-signal-workflows.js +2 -2
  375. package/dist/server/operations/cancel-schedule.d.ts +1 -1
  376. package/dist/server/operations/create-schedule.d.ts +3 -1
  377. package/dist/server/operations/create-schedule.js +29 -11
  378. package/dist/server/operations/fleet-events-subscription.d.ts +54 -0
  379. package/dist/server/operations/fleet-events-subscription.js +99 -0
  380. package/dist/server/operations/fork-workflow.d.ts +1 -1
  381. package/dist/server/operations/fork-workflow.js +3 -2
  382. package/dist/server/operations/get-checkpoint-at.d.ts +1 -1
  383. package/dist/server/operations/get-registry.d.ts +1 -1
  384. package/dist/server/operations/get-retention-overview.d.ts +1 -1
  385. package/dist/server/operations/get-review.d.ts +1 -1
  386. package/dist/server/operations/get-schedule.d.ts +1 -1
  387. package/dist/server/operations/get-stream-chunks.d.ts +1 -1
  388. package/dist/server/operations/get-system-metrics.d.ts +2 -2
  389. package/dist/server/operations/get-task-diagnostics.d.ts +45 -6
  390. package/dist/server/operations/get-task-diagnostics.js +101 -7
  391. package/dist/server/operations/get-update-result.d.ts +1 -1
  392. package/dist/server/operations/get-workflow-attributes.d.ts +1 -1
  393. package/dist/server/operations/get-workflow-events.d.ts +1 -1
  394. package/dist/server/operations/get-workflow-result.d.ts +1 -1
  395. package/dist/server/operations/get-workflow-timeline.d.ts +1 -1
  396. package/dist/server/operations/get-workflow.d.ts +1 -1
  397. package/dist/server/operations/list-checkpoints.d.ts +1 -1
  398. package/dist/server/operations/list-reviews.d.ts +1 -1
  399. package/dist/server/operations/list-schedules.d.ts +1 -1
  400. package/dist/server/operations/list-task-queues.d.ts +2 -2
  401. package/dist/server/operations/list-workers.d.ts +2 -2
  402. package/dist/server/operations/list-workflows.d.ts +1 -1
  403. package/dist/server/operations/operation-helpers.d.ts +16 -1
  404. package/dist/server/operations/operation-helpers.js +15 -3
  405. package/dist/server/operations/pause-schedule.d.ts +1 -1
  406. package/dist/server/operations/purge-workflows.d.ts +5 -5
  407. package/dist/server/operations/purge-workflows.js +2 -2
  408. package/dist/server/operations/query-workflow.d.ts +1 -1
  409. package/dist/server/operations/query-workflow.js +3 -2
  410. package/dist/server/operations/recover-all.d.ts +1 -1
  411. package/dist/server/operations/replay-workflow.d.ts +1 -1
  412. package/dist/server/operations/resume-schedule.d.ts +1 -1
  413. package/dist/server/operations/set-workflow-attributes.d.ts +1 -1
  414. package/dist/server/operations/set-workflow-attributes.js +6 -3
  415. package/dist/server/operations/signal-workflow.js +8 -3
  416. package/dist/server/operations/single-workflow-tag-mutation.js +13 -3
  417. package/dist/server/operations/start-or-signal-workflow.d.ts +6 -1
  418. package/dist/server/operations/start-or-signal-workflow.js +14 -24
  419. package/dist/server/operations/start-workflow-options.d.ts +6 -0
  420. package/dist/server/operations/start-workflow-rest-input.d.ts +14 -0
  421. package/dist/server/operations/start-workflow-rest-input.js +31 -0
  422. package/dist/server/operations/start-workflow.d.ts +1 -1
  423. package/dist/server/operations/start-workflow.js +8 -23
  424. package/dist/server/operations/storage.d.ts +6 -6
  425. package/dist/server/operations/storage.js +24 -14
  426. package/dist/server/operations/stream-workflow-sse.d.ts +1 -1
  427. package/dist/server/operations/submit-review-decision.d.ts +1 -1
  428. package/dist/server/operations/submit-review-decision.js +6 -3
  429. package/dist/server/operations/update-schedule.d.ts +1 -1
  430. package/dist/server/operations/update-schedule.js +7 -4
  431. package/dist/server/operations/update-workflow.d.ts +1 -1
  432. package/dist/server/operations/update-workflow.js +7 -3
  433. package/dist/server/operations/worker-drain.d.ts +8 -8
  434. package/dist/server/operations/worker-drain.js +11 -8
  435. package/dist/server/operations/workflow-events-subscription.d.ts +7 -8
  436. package/dist/server/operations/workflow-events-subscription.js +43 -8
  437. package/dist/server/rest-binding.d.ts +3 -1
  438. package/dist/server/rest-bindings.js +12 -0
  439. package/dist/server/rest-body.d.ts +10 -0
  440. package/dist/server/rest-body.js +80 -0
  441. package/dist/server/runtime/authentication-bridge.d.ts +1 -0
  442. package/dist/server/runtime/authentication-bridge.js +33 -6
  443. package/dist/server/runtime/client-visible-events.d.ts +3 -0
  444. package/dist/server/runtime/client-visible-events.js +65 -0
  445. package/dist/server/runtime/context.d.ts +7 -0
  446. package/dist/server/runtime/event-broadcasting.d.ts +6 -0
  447. package/dist/server/runtime/event-broadcasting.js +72 -38
  448. package/dist/server/runtime/retry.d.ts +1 -0
  449. package/dist/server/runtime/retry.js +14 -0
  450. package/dist/server/runtime/shutdown.d.ts +7 -6
  451. package/dist/server/runtime/shutdown.js +6 -1
  452. package/dist/server/runtime/task-polling.js +61 -20
  453. package/dist/server/runtime/task-reconciliation.js +9 -1
  454. package/dist/server/runtime/task-result-resolution.d.ts +15 -0
  455. package/dist/server/runtime/task-result-resolution.js +81 -0
  456. package/dist/server/runtime/websocket-stream.d.ts +20 -1
  457. package/dist/server/runtime/websocket-stream.js +173 -7
  458. package/dist/server/runtime/websocket-upgrade.js +22 -3
  459. package/dist/server/runtime/websocket-worker.d.ts +1 -1
  460. package/dist/server/runtime/websocket-worker.js +38 -30
  461. package/dist/server/serve-internals.d.ts +3 -1
  462. package/dist/server/serve-internals.js +18 -2
  463. package/dist/server/task-state.d.ts +30 -0
  464. package/dist/server/task-state.js +28 -0
  465. package/dist/server/workflow-event-feed.d.ts +36 -115
  466. package/dist/server/workflow-event-feed.js +92 -27
  467. package/dist/service-worker/index.js +30 -30
  468. package/dist/storage/auto.js +1 -1
  469. package/dist/storage/bun-sql.js +24 -0
  470. package/dist/storage/compressed-storage.js +1 -1
  471. package/dist/storage/default-scope.d.ts +7 -4
  472. package/dist/storage/http.js +2 -2
  473. package/dist/storage/index.d.ts +76 -4
  474. package/dist/storage/indexeddb.js +1 -1
  475. package/dist/storage/interface.d.ts +163 -0
  476. package/dist/storage/interface.js +1 -1
  477. package/dist/storage/key-prefixes.d.ts +1 -1
  478. package/dist/storage/key-prefixes.js +10 -0
  479. package/dist/storage/lmdb.d.ts +4 -3
  480. package/dist/storage/lmdb.js +1 -1
  481. package/dist/storage/memory.js +1 -1
  482. package/dist/storage/neon-batch.d.ts +30 -0
  483. package/dist/storage/neon-batch.js +30 -0
  484. package/dist/storage/neon-value-mapping.d.ts +30 -3
  485. package/dist/storage/neon-value-mapping.js +12 -0
  486. package/dist/storage/neon.d.ts +16 -0
  487. package/dist/storage/neon.js +9 -4
  488. package/dist/storage/node-sqlite.js +23 -0
  489. package/dist/storage/postgres-key-value-queries.d.ts +69 -44
  490. package/dist/storage/postgres-key-value-queries.js +62 -24
  491. package/dist/storage/resolve.js +1 -1
  492. package/dist/storage/scoped-storage.js +1 -1
  493. package/dist/storage/testing.d.ts +168 -0
  494. package/dist/storage/testing.js +2 -0
  495. package/dist/storage/turso.d.ts +8 -0
  496. package/dist/storage/turso.js +2 -2
  497. package/dist/storage/typed-storage.js +1 -1
  498. package/dist/storage/web-extension.js +1 -1
  499. package/dist/testing/index.js +20 -20
  500. package/dist/version.d.ts +1 -1
  501. package/dist/version.js +1 -1
  502. package/dist/worker/protocol.js +1 -1
  503. package/dist/workers/worker-replay-state.d.ts +32 -0
  504. package/dist/workers/worker-replay-state.js +35 -0
  505. package/dist/workers/worker-state-namespace.d.ts +21 -0
  506. package/dist/workers/worker-state-namespace.js +13 -0
  507. package/dist/workers/workflow-runner.d.ts +19 -15
  508. package/dist/workers/workflow-runner.js +72 -60
  509. package/dist/workers/workflow-worker-entry.js +5 -2
  510. package/package.json +5 -1
@@ -1,12 +1,24 @@
1
+ import { decode } from "../../core/codec.js";
2
+ import { loadStoredStreamTailSequence } from "../../core/engine/stream-chunk-loading.js";
1
3
  import { KEYS } from "../../storage/interface.js";
2
- const TOKEN_EVENT_TYPE = "stream:token";
4
+ const TOKEN_EVENT_TYPE = "stream:token", STREAM_CONNECTION_POLICY_CLOSE_CODE = 1008, MAX_WATCH_REPLAY_EVENTS = 1000, MAX_PENDING_WATCH_REPLAY_MESSAGES = 1000;
5
+ export const DEFAULT_MAX_STREAM_CONNECTIONS_PER_WORKFLOW = 100;
3
6
  export function sendStreamMessage(ws, sequence, message) {
4
- if (sequence <= (ws.data.lastDeliveredSequence ?? -1))
7
+ if (sequence <= (ws.data.streamLastDeliveredSequence ?? -1))
5
8
  return;
6
9
  ws.send(message);
7
- ws.data.lastDeliveredSequence = sequence;
10
+ ws.data.streamLastDeliveredSequence = sequence;
11
+ }
12
+ export function sendWatchMessage(ws, sequence, message) {
13
+ if (sequence <= (ws.data.watchLastDeliveredSequence ?? -1))
14
+ return;
15
+ ws.send(message);
16
+ ws.data.watchLastDeliveredSequence = sequence;
8
17
  }
9
18
  export async function getHighestStoredStreamSequence(engine, workflowId, key) {
19
+ const tailSequence = await loadStoredStreamTailSequence(engine.storage, workflowId, key);
20
+ if (tailSequence !== null)
21
+ return tailSequence;
10
22
  const prefix = KEYS.streamChunkPrefix(workflowId, key);
11
23
  for await (const [storageKey] of engine.storage.scan(prefix, { reverse: !0, limit: 1 })) {
12
24
  const sequenceText = storageKey.slice(prefix.length), sequence = Number.parseInt(sequenceText, 10);
@@ -15,13 +27,37 @@ export async function getHighestStoredStreamSequence(engine, workflowId, key) {
15
27
  }
16
28
  return -1;
17
29
  }
30
+ export async function getHighestStoredWatchSequence(engine, workflowId) {
31
+ const prefix = KEYS.eventPrefix(workflowId);
32
+ for await (const [storageKey] of engine.storage.scan(prefix, { reverse: !0, limit: 50 })) {
33
+ const sequence = parseSequenceFromEventKey(prefix, storageKey);
34
+ if (sequence === null)
35
+ continue;
36
+ return sequence;
37
+ }
38
+ return -1;
39
+ }
18
40
  export function addStreamSocket(context, workflowId, ws) {
41
+ if (!addWorkflowStreamConnection(context, workflowId, ws))
42
+ return !1;
19
43
  let sockets = context.streamSockets.get(workflowId);
20
44
  if (!sockets) {
21
45
  sockets = new Set;
22
46
  context.streamSockets.set(workflowId, sockets);
23
47
  }
24
48
  sockets.add(ws);
49
+ return !0;
50
+ }
51
+ export function addWatchSocket(context, workflowId, ws) {
52
+ if (!addWorkflowStreamConnection(context, workflowId, ws))
53
+ return !1;
54
+ let sockets = context.watchSockets.get(workflowId);
55
+ if (!sockets) {
56
+ sockets = new Set;
57
+ context.watchSockets.set(workflowId, sockets);
58
+ }
59
+ sockets.add(ws);
60
+ return !0;
25
61
  }
26
62
  export function removeStreamSocket(context, ws) {
27
63
  const workflowId = ws.data.workflowId;
@@ -34,6 +70,39 @@ export function removeStreamSocket(context, ws) {
34
70
  if (sockets.size === 0)
35
71
  context.streamSockets.delete(workflowId);
36
72
  }
73
+ export function removeWatchSocket(context, ws) {
74
+ const workflowId = ws.data.workflowId;
75
+ if (!workflowId)
76
+ return;
77
+ const sockets = context.watchSockets.get(workflowId);
78
+ if (!sockets)
79
+ return;
80
+ sockets.delete(ws);
81
+ if (sockets.size === 0)
82
+ context.watchSockets.delete(workflowId);
83
+ }
84
+ export function removeWorkflowStreamConnection(context, ws) {
85
+ const workflowId = ws.data.workflowId;
86
+ if (!workflowId || !ws.data.workflowStreamConnectionAccepted)
87
+ return;
88
+ ws.data.workflowStreamConnectionAccepted = !1;
89
+ const currentCount = context.workflowStreamConnectionCounts.get(workflowId);
90
+ if (currentCount === void 0 || currentCount <= 1) {
91
+ context.workflowStreamConnectionCounts.delete(workflowId);
92
+ return;
93
+ }
94
+ context.workflowStreamConnectionCounts.set(workflowId, currentCount - 1);
95
+ }
96
+ function addWorkflowStreamConnection(context, workflowId, ws) {
97
+ const currentCount = context.workflowStreamConnectionCounts.get(workflowId) ?? 0, maxConnections = context.maxStreamConnectionsPerWorkflow;
98
+ if (currentCount >= maxConnections) {
99
+ ws.close(STREAM_CONNECTION_POLICY_CLOSE_CODE, `maximum stream connections per workflow (${maxConnections}) exceeded`);
100
+ return !1;
101
+ }
102
+ context.workflowStreamConnectionCounts.set(workflowId, currentCount + 1);
103
+ ws.data.workflowStreamConnectionAccepted = !0;
104
+ return !0;
105
+ }
37
106
  export function flushPendingStreamMessages(_context, ws) {
38
107
  const pendingMessages = ws.data.pendingStreamMessages ?? [];
39
108
  pendingMessages.sort((left, right) => left.sequence - right.sequence);
@@ -41,12 +110,19 @@ export function flushPendingStreamMessages(_context, ws) {
41
110
  sendStreamMessage(ws, pending.sequence, pending.message);
42
111
  ws.data.pendingStreamMessages = [];
43
112
  }
113
+ export function flushPendingWatchMessages(_context, ws) {
114
+ const pendingMessages = ws.data.pendingWatchMessages ?? [];
115
+ pendingMessages.sort((left, right) => left.sequence - right.sequence);
116
+ for (const pending of pendingMessages)
117
+ sendWatchMessage(ws, pending.sequence, pending.message);
118
+ ws.data.pendingWatchMessages = [];
119
+ }
44
120
  export function publishTokenMessage(context, workflowId, sequence, message) {
45
121
  const sockets = context.streamSockets.get(workflowId);
46
122
  if (!sockets)
47
123
  return;
48
124
  for (const ws of sockets) {
49
- if (ws.data.replayInProgress) {
125
+ if (ws.data.streamReplayInProgress) {
50
126
  ws.data.pendingStreamMessages ??= [];
51
127
  ws.data.pendingStreamMessages.push({ sequence, message });
52
128
  continue;
@@ -54,11 +130,29 @@ export function publishTokenMessage(context, workflowId, sequence, message) {
54
130
  sendStreamMessage(ws, sequence, message);
55
131
  }
56
132
  }
133
+ export function publishWatchMessage(context, workflowId, sequence, message) {
134
+ const sockets = context.watchSockets.get(workflowId);
135
+ if (!sockets)
136
+ return;
137
+ for (const ws of sockets) {
138
+ if (ws.data.watchReplayInProgress) {
139
+ const pendingMessages = ws.data.pendingWatchMessages ?? [];
140
+ if (pendingMessages.length >= MAX_PENDING_WATCH_REPLAY_MESSAGES) {
141
+ closeWatchSocketForReplayLimit(context, ws, `watch replay buffer exceeded ${MAX_PENDING_WATCH_REPLAY_MESSAGES} pending messages`);
142
+ continue;
143
+ }
144
+ pendingMessages.push({ sequence, message });
145
+ ws.data.pendingWatchMessages = pendingMessages;
146
+ continue;
147
+ }
148
+ sendWatchMessage(ws, sequence, message);
149
+ }
150
+ }
57
151
  export async function replayTokenStream(context, engine, ws, workflowId) {
58
- ws.data.lastDeliveredSequence = -1;
152
+ ws.data.streamLastDeliveredSequence = -1;
59
153
  try {
60
154
  const requestedResumeFrom = ws.data.resumeFrom, after = requestedResumeFrom === void 0 ? -1 : Math.min(requestedResumeFrom, await getHighestStoredStreamSequence(engine, workflowId, "tokens"));
61
- ws.data.lastDeliveredSequence = after;
155
+ ws.data.streamLastDeliveredSequence = after;
62
156
  const chunks = after >= 0 ? await engine.getStreamChunks(workflowId, "tokens", { after }) : await engine.getStreamChunks(workflowId, "tokens");
63
157
  for (const chunk of chunks) {
64
158
  if (typeof chunk.value !== "object" || chunk.value === null)
@@ -73,7 +167,79 @@ export async function replayTokenStream(context, engine, ws, workflowId) {
73
167
  } catch (error) {
74
168
  console.error(`[weft] Failed to replay token stream for workflow "${workflowId}":`, error);
75
169
  } finally {
76
- ws.data.replayInProgress = !1;
170
+ ws.data.streamReplayInProgress = !1;
77
171
  flushPendingStreamMessages(context, ws);
78
172
  }
79
173
  }
174
+ export async function replayWatchEvents(context, engine, ws, workflowId) {
175
+ ws.data.watchLastDeliveredSequence = -1;
176
+ let shouldFlushPending = !0, replayedEvents = 0;
177
+ try {
178
+ const requestedResumeFrom = ws.data.resumeFrom, after = requestedResumeFrom === void 0 ? -1 : Math.min(requestedResumeFrom, await getHighestStoredWatchSequence(engine, workflowId));
179
+ ws.data.watchLastDeliveredSequence = after;
180
+ const prefix = KEYS.eventPrefix(workflowId), scanOptions = after >= 0 ? { gt: KEYS.event(workflowId, after) } : void 0;
181
+ for await (const [storageKey, value] of engine.storage.scan(prefix, scanOptions)) {
182
+ const sequence = parseSequenceFromEventKey(prefix, storageKey);
183
+ if (sequence === null || sequence <= after)
184
+ continue;
185
+ const decoded = decodeStoredWatchEvent(value);
186
+ if (!isStoredWatchEvent(decoded))
187
+ continue;
188
+ if (replayedEvents >= MAX_WATCH_REPLAY_EVENTS) {
189
+ shouldFlushPending = !1;
190
+ closeWatchSocketForReplayLimit(context, ws, `watch replay window exceeds ${MAX_WATCH_REPLAY_EVENTS} events; reconnect with a newer resumeFrom`);
191
+ return;
192
+ }
193
+ sendWatchMessage(ws, sequence, JSON.stringify({
194
+ type: decoded.type,
195
+ timestamp: decoded.timestamp,
196
+ data: decoded.data,
197
+ sequence,
198
+ cursor: String(sequence)
199
+ }));
200
+ replayedEvents += 1;
201
+ }
202
+ } catch (error) {
203
+ console.error(`[weft] Failed to replay watch events for workflow "${workflowId}":`, error);
204
+ shouldFlushPending = !1;
205
+ closeWatchSocketForReplayLimit(context, ws, "watch replay failed before catch-up completed; reconnect with a newer resumeFrom");
206
+ } finally {
207
+ ws.data.watchReplayInProgress = !1;
208
+ if (shouldFlushPending)
209
+ flushPendingWatchMessages(context, ws);
210
+ else
211
+ ws.data.pendingWatchMessages = [];
212
+ }
213
+ }
214
+ function closeWatchSocketForReplayLimit(context, ws, reason) {
215
+ ws.data.pendingWatchMessages = [];
216
+ ws.data.watchReplayInProgress = !1;
217
+ ws.close(STREAM_CONNECTION_POLICY_CLOSE_CODE, reason);
218
+ removeWatchSocket(context, ws);
219
+ removeWorkflowStreamConnection(context, ws);
220
+ }
221
+ function decodeStoredWatchEvent(value) {
222
+ try {
223
+ return decode(value);
224
+ } catch {
225
+ return null;
226
+ }
227
+ }
228
+ function parseSequenceFromEventKey(prefix, storageKey) {
229
+ if (!storageKey.startsWith(prefix))
230
+ return null;
231
+ const rawSequence = storageKey.slice(prefix.length);
232
+ if (!/^\d+$/.test(rawSequence))
233
+ return null;
234
+ const sequence = Number.parseInt(rawSequence, 10);
235
+ return Number.isSafeInteger(sequence) ? sequence : null;
236
+ }
237
+ function isStoredWatchEvent(value) {
238
+ if (typeof value !== "object" || value === null)
239
+ return !1;
240
+ const record = value;
241
+ return typeof record.type === "string" && typeof record.timestamp === "number" && Number.isFinite(record.timestamp) && isPlainRecord(record.data);
242
+ }
243
+ function isPlainRecord(value) {
244
+ return typeof value === "object" && value !== null && !Array.isArray(value);
245
+ }
@@ -37,7 +37,7 @@ function rejectsCrossOriginUpgrade(context, request) {
37
37
  return context.corsPolicy !== null && origin !== null && !isOriginAllowed(context.corsPolicy, origin);
38
38
  }
39
39
  function resolvePrincipalForUpgrade(connectionType, authContext) {
40
- if (connectionType !== "jsonrpc" && connectionType !== "worker")
40
+ if (connectionType !== "jsonrpc" && connectionType !== "worker" && connectionType !== "watch" && connectionType !== "stream")
41
41
  return { ok: !0, principal: void 0 };
42
42
  if (authContext === void 0)
43
43
  return { ok: !0, principal: void 0 };
@@ -48,10 +48,29 @@ function resolvePrincipalForUpgrade(connectionType, authContext) {
48
48
  console.error("[weft] WebSocket upgrade principal resolution failed", error);
49
49
  return { ok: !1, response: new Response("Authentication context invalid", { status: 401 }) };
50
50
  }
51
- if (connectionType === "worker" && isAuthenticated(principal) && !principal.hasScope("workers:write"))
52
- return { ok: !1, response: new Response("Insufficient scope", { status: 403 }) };
51
+ const requiredScope = upgradeScope(connectionType);
52
+ if (requiredScope !== null) {
53
+ if (!isAuthenticated(principal))
54
+ return { ok: !1, response: new Response("Authentication required", { status: 401 }) };
55
+ if (!principal.hasScope(requiredScope))
56
+ return { ok: !1, response: new Response("Insufficient scope", { status: 403 }) };
57
+ }
53
58
  return { ok: !0, principal };
54
59
  }
60
+ function upgradeScope(connectionType) {
61
+ switch (connectionType) {
62
+ case "worker":
63
+ return "workers:write";
64
+ case "watch":
65
+ return "events:read";
66
+ case "stream":
67
+ return "streams:read";
68
+ case "jsonrpc":
69
+ case "generic":
70
+ case void 0:
71
+ return null;
72
+ }
73
+ }
55
74
  export function handleWebSocketUpgrade(server, context, options, request, url, authContext) {
56
75
  if (request.headers.get("upgrade") !== "websocket")
57
76
  return null;
@@ -3,5 +3,5 @@ import type { ServeOptions } from '../index.ts';
3
3
  import type { WebSocketData } from '../json-rpc-websocket-runtime.ts';
4
4
  import type { ServerContext } from './context.ts';
5
5
  export { isInflightRecord } from '../task-state.ts';
6
- export declare function withRetry<T>(operation: () => Promise<T>, label: string, maxAttempts?: number): Promise<T>;
6
+ export { withRetry } from './retry.ts';
7
7
  export declare function handleWorkerWebSocketMessage(context: ServerContext, options: ServeOptions, ws: ServerWebSocket<WebSocketData>, rawMessage: string | Buffer, cleanupWorkflowIndex: (operationId: string) => void): void;
@@ -1,4 +1,5 @@
1
1
  import { decode, encode } from "../../core/codec.js";
2
+ import { WorkerConnectedEvent } from "../../core/events.js";
2
3
  import { KEYS } from "../../storage/interface.js";
3
4
  import {
4
5
  REMOTE_WORKER_PROTOCOL_VERSION,
@@ -7,35 +8,20 @@ import {
7
8
  } from "../../worker/protocol.js";
8
9
  import { workerProtocolIncompatibleMessage } from "../../worker/worker-protocol-incompatible-error.js";
9
10
  import { isAuthenticated } from "../principal.js";
11
+ import { isInflightRecord, readInflightRecord } from "../task-state.js";
12
+ import { withRetry } from "./retry.js";
13
+ import { recordWorkerCapacitySaturationMetric } from "./task-metrics.js";
10
14
  import {
11
- isInflightRecord,
12
- readInflightRecord,
13
- transitionInflightToResolved
14
- } from "../task-state.js";
15
- import {
16
- recordTaskExecutionLatencyMetric,
17
- recordWorkerCapacitySaturationMetric
18
- } from "./task-metrics.js";
15
+ taskResultPayloadSizeError,
16
+ transitionTaskResultToResolvedWithRetry
17
+ } from "./task-result-resolution.js";
19
18
  import { WORKER_STREAM_RE } from "./websocket-upgrade.js";
20
19
  const MAX_WORKER_CONCURRENCY = 1000, DEFAULT_WORKER_CONCURRENCY = 10, WORKER_PROTOCOL_CLOSE_CODE = 1002, WORKER_REGISTRATION_CLOSE_CODE = 1008;
21
20
  function isWorkerConnection(pathname) {
22
21
  return WORKER_STREAM_RE.test(pathname);
23
22
  }
24
23
  export { isInflightRecord } from "../task-state.js";
25
- export async function withRetry(operation, label, maxAttempts = 2) {
26
- let lastError;
27
- for (let attempt = 1;attempt <= maxAttempts; attempt++)
28
- try {
29
- return await operation();
30
- } catch (error) {
31
- lastError = error;
32
- if (attempt < maxAttempts) {
33
- console.warn(`[weft] Retrying "${label}" (attempt ${attempt + 1}/${maxAttempts})`);
34
- await Bun.sleep(100 * attempt);
35
- }
36
- }
37
- throw lastError;
38
- }
24
+ export { withRetry } from "./retry.js";
39
25
  function sendWorkerProtocolMessage(ws, message) {
40
26
  ws.send(JSON.stringify(message));
41
27
  }
@@ -83,7 +69,7 @@ function buildWorkerRegistrationInfo(message, queue, concurrency) {
83
69
  ...message.capabilities !== void 0 ? { capabilities: message.capabilities } : {}
84
70
  };
85
71
  }
86
- function registerWorker(context, ws, message) {
72
+ function registerWorker(context, options, ws, message) {
87
73
  if (!principalMayRegisterWorker(ws.data.principal)) {
88
74
  rejectRegistration(ws, "invalid_registration", "Worker registration requires the workers:write scope", message.protocolVersion);
89
75
  return;
@@ -106,6 +92,7 @@ function registerWorker(context, ws, message) {
106
92
  activities: [...message.activities],
107
93
  concurrency: clampedConcurrency
108
94
  });
95
+ options.engine.dispatchEvent(new WorkerConnectedEvent(message.workerId, queue, [...message.activities], clampedConcurrency));
109
96
  }
110
97
  function resolveTaskResultStatus(message) {
111
98
  return message.status === "completed" ? "completed" : "failed";
@@ -128,20 +115,41 @@ function onTaskResultMessage(context, options, ws, message, cleanupWorkflowIndex
128
115
  });
129
116
  return;
130
117
  }
118
+ const resolvedStatus = resolveTaskResultStatus(message), payloadError = taskResultPayloadSizeError({
119
+ operationId,
120
+ status: resolvedStatus,
121
+ resolutionReason: resolvedStatus,
122
+ ...message.status === "completed" ? { value: message.value } : { error: message.error }
123
+ }, context.payloadSizeMaxBytes);
131
124
  context.registry.completeTask(operationId);
132
125
  context.deadlineTracker.remove(operationId);
133
126
  cleanupWorkflowIndex(operationId);
134
127
  recordWorkerCapacitySaturationMetric(context.metricsCollector, context.registry);
135
128
  (async () => {
136
- const inflightRecord = await readInflightRecord(options.engine.storage, operationId), resolvedAt = Date.now(), resolvedStatus = resolveTaskResultStatus(message);
137
- await transitionInflightToResolved(options.engine.storage, operationId, resolvedStatus, {
138
- ...inflightRecord === null ? {} : { record: inflightRecord },
139
- resolvedAt,
129
+ const inflightRecord = await readInflightRecord(options.engine.storage, operationId);
130
+ if (payloadError !== null) {
131
+ sendWorkerProtocolMessage(ws, {
132
+ type: "protocolError",
133
+ code: "invalid_message",
134
+ message: payloadError.message
135
+ });
136
+ await transitionTaskResultToResolvedWithRetry(context, options, {
137
+ operationId,
138
+ status: "failed",
139
+ resolutionReason: "failed",
140
+ inflightRecord,
141
+ error: payloadError.message,
142
+ skipPayloadSizeCheck: !0
143
+ });
144
+ return;
145
+ }
146
+ await transitionTaskResultToResolvedWithRetry(context, options, {
147
+ operationId,
148
+ status: resolvedStatus,
140
149
  resolutionReason: resolvedStatus,
150
+ inflightRecord,
141
151
  ...message.status === "completed" ? { value: message.value } : { error: message.error }
142
152
  });
143
- if (inflightRecord !== null)
144
- recordTaskExecutionLatencyMetric(context.metricsCollector, inflightRecord, resolvedAt);
145
153
  })().catch((error) => {
146
154
  console.error(`[weft] Failed to transition task "${operationId}" to resolved \u2014 inflight record may leak:`, error);
147
155
  });
@@ -215,7 +223,7 @@ export function handleWorkerWebSocketMessage(context, options, ws, rawMessage, c
215
223
  }
216
224
  switch (message.type) {
217
225
  case "register": {
218
- registerWorker(context, ws, message);
226
+ registerWorker(context, options, ws, message);
219
227
  break;
220
228
  }
221
229
  case "taskResult": {
@@ -19,12 +19,14 @@ import { type EventBroadcastingHandle } from './runtime/event-broadcasting.ts';
19
19
  * `tests/auth-warning-filter.test.ts`) and not part of the public API surface.
20
20
  */
21
21
  export declare const NO_AUTHENTICATION_WARNING = "[weft] WARNING: server started with NO authentication; all non-public operations are publicly accessible. Configure serve({ auth }) to lock down, or set unauthenticatedAccess: \"reject\" in production to fail closed.";
22
+ export declare const MCP_ORIGIN_CONFIGURATION_WARNING = "[weft] WARNING: MCP HTTP transport is enabled without publicOrigin or trustedHosts. Cross-origin /mcp requests are rejected, and discovery routes that emit absolute URLs return 503. Configure serve({ publicOrigin: \"https://api.example.com\" }) or serve({ trustedHosts: [\"api.example.com\"] }) before exposing the server through a browser or reverse proxy.";
22
23
  /**
23
24
  * Clamp a user-supplied `workerReconnectGracePeriodMs` into `[0, 5_000]`.
24
- * Returns the default when undefined or non-finite.
25
+ * Returns the 2000ms default when undefined or non-finite.
25
26
  */
26
27
  export declare function clampWorkerReconnectGracePeriod(value: number | undefined): number;
27
28
  export declare function assertAuthenticationPosture(options: ServeOptions, environmentRequirement?: string | undefined): void;
29
+ export declare function warnIfMcpOriginConfigurationMissing(options: ServeOptions): void;
28
30
  /**
29
31
  * A mutable holder for the Bun server instance. The `fetch` handler needs to
30
32
  * call back into the server (for WebSocket upgrades) but the server isn't
@@ -1,4 +1,5 @@
1
1
  import { decode } from "../core/codec.js";
2
+ import { getEnginePayloadSizeMaxBytes } from "../core/engine/payload-size-policy.js";
2
3
  import { createMcpSessionManager } from "../mcp/session.js";
3
4
  import { createMetricsCollectorExporter, MetricsCollector } from "../observability/metrics.js";
4
5
  import { WorkerRegistry } from "../worker/registry.js";
@@ -11,6 +12,7 @@ import {
11
12
  } from "./authentication.js";
12
13
  import { DeadlineTracker } from "./deadline-tracker.js";
13
14
  import { createEngineEventFeedBackend } from "./engine-event-feed-backend.js";
15
+ import { createFleetEventFeed } from "./fleet-event-feed.js";
14
16
  import { closeJsonRpcSessionsForShutdown } from "./json-rpc-websocket-runtime.js";
15
17
  import { createLiveOperationRegistry, createLiveRestBindings } from "./rest-bindings.js";
16
18
  import {
@@ -22,12 +24,14 @@ import { resolveCorsPolicy, validateCorsOptions } from "./runtime/cors.js";
22
24
  import {
23
25
  registerWorkflowEventLifecycle
24
26
  } from "./runtime/event-broadcasting.js";
27
+ import { shutdownAllWorkers } from "./runtime/shutdown.js";
25
28
  import { reconcileOrphanedRecords, scanExpiredTasks } from "./runtime/task-reconciliation.js";
29
+ import { DEFAULT_MAX_STREAM_CONNECTIONS_PER_WORKFLOW } from "./runtime/websocket-stream.js";
26
30
  import { isInflightRecord, withRetry } from "./runtime/websocket-worker.js";
27
31
  import { TaskQueue } from "./task-queue.js";
28
32
  import { createWorkflowEventFeed } from "./workflow-event-feed.js";
29
- const RECONCILIATION_MULTIPLIER = 12, DEFAULT_WORKER_RECONNECT_GRACE_PERIOD_MS = 100, MAX_WORKER_RECONNECT_GRACE_PERIOD_MS = 5000, AUTHENTICATION_REQUIRED_ENVIRONMENT_VARIABLE = "WEFT_SERVER_AUTHENTICATION_REQUIRED";
30
- export const NO_AUTHENTICATION_WARNING = '[weft] WARNING: server started with NO authentication; all non-public operations are publicly accessible. Configure serve({ auth }) to lock down, or set unauthenticatedAccess: "reject" in production to fail closed.';
33
+ const RECONCILIATION_MULTIPLIER = 12, DEFAULT_WORKER_RECONNECT_GRACE_PERIOD_MS = 2000, MAX_WORKER_RECONNECT_GRACE_PERIOD_MS = 5000, AUTHENTICATION_REQUIRED_ENVIRONMENT_VARIABLE = "WEFT_SERVER_AUTHENTICATION_REQUIRED";
34
+ export const NO_AUTHENTICATION_WARNING = '[weft] WARNING: server started with NO authentication; all non-public operations are publicly accessible. Configure serve({ auth }) to lock down, or set unauthenticatedAccess: "reject" in production to fail closed.', MCP_ORIGIN_CONFIGURATION_WARNING = '[weft] WARNING: MCP HTTP transport is enabled without publicOrigin or trustedHosts. Cross-origin /mcp requests are rejected, and discovery routes that emit absolute URLs return 503. Configure serve({ publicOrigin: "https://api.example.com" }) or serve({ trustedHosts: ["api.example.com"] }) before exposing the server through a browser or reverse proxy.';
31
35
  const NO_AUTHENTICATION_REJECT_ERROR = '[weft] Refusing to start server with no authentication. Configure serve({ auth }) or set unauthenticatedAccess: "allow" only for trusted local development.', NO_AUTHENTICATION_ENVIRONMENT_ERROR = "[weft] Refusing to start server with no authentication because WEFT_SERVER_AUTHENTICATION_REQUIRED requires authentication. Configure serve({ auth }) or unset WEFT_SERVER_AUTHENTICATION_REQUIRED only for trusted local development.", TRUTHY_AUTHENTICATION_REQUIREMENT_VALUES = new Set(["1", "true", "yes", "on"]), FALSY_AUTHENTICATION_REQUIREMENT_VALUES = new Set(["0", "false", "no", "off"]);
32
36
  export function clampWorkerReconnectGracePeriod(value) {
33
37
  if (value === void 0 || !Number.isFinite(value))
@@ -61,6 +65,11 @@ export function assertAuthenticationPosture(options, environmentRequirement = Bu
61
65
  return;
62
66
  console.warn(NO_AUTHENTICATION_WARNING);
63
67
  }
68
+ export function warnIfMcpOriginConfigurationMissing(options) {
69
+ if (options.publicOrigin !== void 0 || options.trustedHosts !== void 0)
70
+ return;
71
+ console.warn(MCP_ORIGIN_CONFIGURATION_WARNING);
72
+ }
64
73
  export function resolveNetworkConfig(options) {
65
74
  if (options.auth)
66
75
  validateAuthConfig(options.auth);
@@ -69,6 +78,7 @@ export function resolveNetworkConfig(options) {
69
78
  if (options.cors)
70
79
  validateCorsOptions(options.cors, options.auth !== void 0);
71
80
  assertAuthenticationPosture(options);
81
+ warnIfMcpOriginConfigurationMissing(options);
72
82
  const port = options.port ?? 7233, hostname = options.hostname ?? "0.0.0.0", development = options.development ?? !1, serverMetricsCollector = new MetricsCollector, prometheusExporter = options.prometheusExporter ?? createMetricsCollectorExporter(serverMetricsCollector), serverOptions = { ...options, prometheusExporter }, tlsOptions = buildTLSOptions(options.auth);
73
83
  return { port, hostname, development, tlsOptions, serverOptions, serverMetricsCollector };
74
84
  }
@@ -79,6 +89,9 @@ export function buildServerContext(options, serverMetricsCollector) {
79
89
  taskQueue,
80
90
  workerSockets: new Map,
81
91
  streamSockets: new Map,
92
+ watchSockets: new Map,
93
+ workflowStreamConnectionCounts: new Map,
94
+ maxStreamConnectionsPerWorkflow: options.maxStreamConnectionsPerWorkflow ?? DEFAULT_MAX_STREAM_CONNECTIONS_PER_WORKFLOW,
82
95
  workerAffinity: new Map,
83
96
  workflowOperations: new Map,
84
97
  operationToWorkflow: new Map,
@@ -95,12 +108,14 @@ export function buildServerContext(options, serverMetricsCollector) {
95
108
  metricsCollector: serverMetricsCollector,
96
109
  eventFeedBackend,
97
110
  workflowEventFeed: createWorkflowEventFeed(eventFeedBackend),
111
+ fleetEventFeed: createFleetEventFeed(options.engine.storage),
98
112
  activeJsonRpcSessions: new Set,
99
113
  mcpSessionManager: createMcpSessionManager(options.engine),
100
114
  authenticatorPromise: options.auth ? createAuthenticator(options.auth) : null,
101
115
  rateLimiter: options.rateLimit ? createRateLimiter(options.rateLimit) : null,
102
116
  visibilityPollMs: options.visibilityPollIntervalMs ?? 5000,
103
117
  workerReconnectGracePeriodMs: clampWorkerReconnectGracePeriod(options.workerReconnectGracePeriodMs),
118
+ payloadSizeMaxBytes: getEnginePayloadSizeMaxBytes(options.engine),
104
119
  pendingWorkerRequeues: new Map,
105
120
  scanRunning: !1,
106
121
  processingOperations: new Set,
@@ -148,6 +163,7 @@ export function registerStackDisposers(stack, context, options, broadcastingHand
148
163
  });
149
164
  stack.defer(() => context.mcpSessionManager[Symbol.asyncDispose]());
150
165
  stack.defer(registerWorkflowEventLifecycle(options.engine, context, broadcastingHandle));
166
+ stack.defer(() => shutdownAllWorkers(context, options.workerShutdownTimeoutMs === void 0 ? void 0 : { timeoutMs: options.workerShutdownTimeoutMs, stopWaitingWhenIdle: !0 }));
151
167
  const visibilityPollHandle = setInterval(() => {
152
168
  scanExpiredTasks(context, options, onOperationCleanup);
153
169
  }, context.visibilityPollMs), reconciliationIntervalMs = context.visibilityPollMs * RECONCILIATION_MULTIPLIER, reconciliationHandle = setInterval(() => {
@@ -20,6 +20,8 @@ export type TaskState = 'queued' | 'inflight' | 'resolved';
20
20
  export type TaskRequeueReason = 'visibility-timeout' | 'worker-disconnect';
21
21
  /** Final reason captured when a task reaches the resolved state. */
22
22
  export type TaskResolutionReason = 'completed' | 'failed' | 'cancelled' | 'max-attempts-exceeded';
23
+ /** Why a task-result transition was moved to the operator dead-letter guard. */
24
+ export type TaskDeadLetterReason = 'result-resolution-storage-exhausted';
23
25
  /** Lifecycle evidence persisted with task records for diagnostics. */
24
26
  export interface TaskLifecycleFields {
25
27
  /** First time this operation entered a task queue. */
@@ -103,6 +105,24 @@ export interface ResolvedRecord {
103
105
  queueLatencyMs?: number | undefined;
104
106
  executionLatencyMs?: number | undefined;
105
107
  }
108
+ /** Durable operator guard for a task result whose resolved write exhausted retries. */
109
+ export interface DeadLetteredTaskRecord {
110
+ operationId: string;
111
+ reason: TaskDeadLetterReason;
112
+ deadLetteredAt: number;
113
+ errorMessage: string;
114
+ retryAttempts: number;
115
+ status: 'completed' | 'failed';
116
+ activityName?: string | undefined;
117
+ queue?: string | undefined;
118
+ workerId?: string | undefined;
119
+ attempt?: number | undefined;
120
+ visibilityTimeout?: number | undefined;
121
+ workflowId?: string | undefined;
122
+ retryCount?: number | undefined;
123
+ requeueCount?: number | undefined;
124
+ lastRequeueReason?: TaskRequeueReason | undefined;
125
+ }
106
126
  export interface TransitionInflightToResolvedOptions {
107
127
  resolutionReason?: TaskResolutionReason;
108
128
  resolvedAt?: number;
@@ -131,10 +151,20 @@ export declare function isQueuedRecord(value: unknown): value is QueuedRecord;
131
151
  export declare function isInflightRecord(value: unknown): value is InflightRecord;
132
152
  /** Type guard for decoded storage records in the resolved state. */
133
153
  export declare function isResolvedRecord(value: unknown): value is ResolvedRecord;
154
+ /** Type guard for decoded task-result dead-letter records. */
155
+ export declare function isDeadLetteredTaskRecord(value: unknown): value is DeadLetteredTaskRecord;
134
156
  /** Decode the queued record for an operation, returning null when absent or malformed. */
135
157
  export declare function readQueuedRecord(storage: Storage, operationId: string): Promise<QueuedRecord | null>;
136
158
  /** Decode the inflight record for an operation, returning null when absent or malformed. */
137
159
  export declare function readInflightRecord(storage: Storage, operationId: string): Promise<InflightRecord | null>;
160
+ /** Decode the task-result dead-letter record for an operation. */
161
+ export declare function readDeadLetteredTaskRecord(storage: Storage, operationId: string): Promise<DeadLetteredTaskRecord | null>;
162
+ /** True when reconciliation should not re-dispatch the operation. */
163
+ export declare function isTaskDeadLettered(storage: Storage, operationId: string): Promise<boolean>;
164
+ /** Persist a task-result dead-letter guard. */
165
+ export declare function writeDeadLetteredTaskRecord(storage: Storage, record: DeadLetteredTaskRecord): Promise<void>;
166
+ /** Clear a task-result dead-letter guard so reconciliation may handle the inflight record again. */
167
+ export declare function clearDeadLetteredTaskRecord(storage: Storage, operationId: string): Promise<void>;
138
168
  export declare function calculateQueueLatencyMs(record: TaskLifecycleFields): number | undefined;
139
169
  export declare function calculateExecutionLatencyMs(record: TaskLifecycleFields, completedAt: number): number | undefined;
140
170
  export declare function calculateHeartbeatAgeMs(record: TaskLifecycleFields & {
@@ -49,6 +49,12 @@ export function isResolvedRecord(value) {
49
49
  const record = value;
50
50
  return typeof record.operationId === "string" && (record.status === "completed" || record.status === "failed") && typeof record.resolvedAt === "number";
51
51
  }
52
+ export function isDeadLetteredTaskRecord(value) {
53
+ if (value === null || typeof value !== "object")
54
+ return !1;
55
+ const record = value;
56
+ return typeof record.operationId === "string" && record.reason === "result-resolution-storage-exhausted" && typeof record.deadLetteredAt === "number" && typeof record.errorMessage === "string" && typeof record.retryAttempts === "number" && (record.status === "completed" || record.status === "failed");
57
+ }
52
58
  export async function readQueuedRecord(storage, operationId) {
53
59
  const value = await storage.get(KEYS.operationQueued(operationId));
54
60
  if (value === null)
@@ -63,6 +69,28 @@ export async function readInflightRecord(storage, operationId) {
63
69
  const decoded = decode(value);
64
70
  return isInflightRecord(decoded) ? decoded : null;
65
71
  }
72
+ export async function readDeadLetteredTaskRecord(storage, operationId) {
73
+ const value = await storage.get(KEYS.operationDeadLetter(operationId));
74
+ if (value === null)
75
+ return null;
76
+ const decoded = decode(value);
77
+ return isDeadLetteredTaskRecord(decoded) ? decoded : null;
78
+ }
79
+ export async function isTaskDeadLettered(storage, operationId) {
80
+ return await readDeadLetteredTaskRecord(storage, operationId) !== null;
81
+ }
82
+ export async function writeDeadLetteredTaskRecord(storage, record) {
83
+ await storage.batch([
84
+ {
85
+ type: "put",
86
+ key: KEYS.operationDeadLetter(record.operationId),
87
+ value: encode(record)
88
+ }
89
+ ]);
90
+ }
91
+ export async function clearDeadLetteredTaskRecord(storage, operationId) {
92
+ await storage.delete(KEYS.operationDeadLetter(operationId));
93
+ }
66
94
  function normalizeQueuedRecordLifecycle(record, previous) {
67
95
  const normalized = {
68
96
  ...record,