@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,4 +1,5 @@
1
1
  import type { Engine } from '../../core/engine.ts';
2
+ import type { FleetEventFeed } from '../fleet-event-feed.ts';
2
3
  import type { ServerContext } from './context.ts';
3
4
  /**
4
5
  * Result of wiring up engine-to-WebSocket event broadcasting.
@@ -46,6 +47,9 @@ export declare function registerWorkflowEventLifecycle(engine: Engine, context:
46
47
  * token messages, enabling per-workflow stream sockets to be used in
47
48
  * place of the default pub/sub channel. Leave unset unless you manage stream
48
49
  * sockets separately (as `serve()` does internally).
50
+ * @param options.publishWatchMessage - Optional override for watch-event delivery.
51
+ * When provided, this callback is called instead of `server.publish()` for
52
+ * watch messages, enabling per-socket replay buffering during catch-up.
49
53
  *
50
54
  * @example
51
55
  * ```ts
@@ -68,4 +72,6 @@ export declare function registerWorkflowEventLifecycle(engine: Engine, context:
68
72
  */
69
73
  export declare function wireEventBroadcasting(engine: Engine, server: ReturnType<typeof Bun.serve>, options?: {
70
74
  publishTokenMessage?: (workflowId: string, sequence: number, message: string) => void;
75
+ publishWatchMessage?: (workflowId: string, sequence: number, message: string) => void;
76
+ fleetEventFeed?: FleetEventFeed;
71
77
  }): EventBroadcastingHandle;
@@ -1,24 +1,19 @@
1
1
  import { encode } from "../../core/codec.js";
2
2
  import {
3
- ActivityCompletedEvent,
4
- ActivityFailedEvent,
5
- ActivityStartedEvent,
6
- AttributesChangedEvent,
7
- SignalDeliveredEvent,
8
- SignalReceivedEvent,
9
- UpdateCompletedEvent,
10
- UpdateReceivedEvent,
3
+ encodeStoredStreamTailSequence,
4
+ loadStoredStreamTailSequence
5
+ } from "../../core/engine/stream-chunk-loading.js";
6
+ import {
11
7
  WorkflowCancelledEvent,
12
8
  WorkflowCompletedEvent,
13
9
  WorkflowFailedEvent,
14
- WorkflowStartedEvent,
15
10
  WorkflowTimedOutEvent
16
11
  } from "../../core/events.js";
17
12
  import { KEYS } from "../../storage/interface.js";
18
13
  import { claimNextSequence } from "../runtime-helpers.js";
14
+ import { CLIENT_VISIBLE_EVENT_TYPES, TOKEN_EVENT_TYPE } from "./client-visible-events.js";
19
15
  import { cancelTask } from "./task-dispatch.js";
20
16
  import { withRetry } from "./websocket-worker.js";
21
- const TOKEN_EVENT_TYPE = "stream:token";
22
17
  function workflowChannelPath(workflowId, connectionType) {
23
18
  return `/v1/workflows/${encodeURIComponent(workflowId)}/${connectionType}`;
24
19
  }
@@ -106,6 +101,11 @@ export function wireEventBroadcasting(engine, server, options) {
106
101
  if (existing)
107
102
  return existing;
108
103
  const promise = (async () => {
104
+ const storedTailSequence = await loadStoredStreamTailSequence(engine.storage, workflowId, "tokens");
105
+ if (storedTailSequence !== null) {
106
+ tokenSequenceCounters.set(workflowId, storedTailSequence + 1);
107
+ return;
108
+ }
109
109
  const prefix = KEYS.streamChunkPrefix(workflowId, "tokens");
110
110
  let highestSequence = -1;
111
111
  for await (const [key] of engine.storage.scan(prefix, { reverse: !0, limit: 1 })) {
@@ -122,11 +122,7 @@ export function wireEventBroadcasting(engine, server, options) {
122
122
  return promise;
123
123
  }
124
124
  async function persistAndPublishEvent(workflowId, eventType, message) {
125
- await ensureSequenceInitialized(workflowId);
126
- const parsed = JSON.parse(message), sequence = claimNextSequence(sequenceCounters, workflowId), storageKey = KEYS.event(workflowId, sequence), encoded = encode(parsed);
127
- await withRetry(async () => engine.storage.put(storageKey, encoded), `persist event "${eventType}" for workflow "${workflowId}"`);
128
- const watchChannel = workflowChannelPath(workflowId, "watch");
129
- server.publish(watchChannel, message);
125
+ const parsed = JSON.parse(message);
130
126
  if (eventType === TOKEN_EVENT_TYPE) {
131
127
  const tokenPayload = {
132
128
  workflowId: typeof parsed.data.workflowId === "string" ? parsed.data.workflowId : workflowId,
@@ -135,10 +131,23 @@ export function wireEventBroadcasting(engine, server, options) {
135
131
  };
136
132
  await ensureTokenSequenceInitialized(workflowId);
137
133
  const tokenSequence = claimNextSequence(tokenSequenceCounters, workflowId);
138
- await withRetry(async () => engine.storage.put(KEYS.streamChunk(workflowId, "tokens", tokenSequence), encode(tokenPayload)), `persist token stream chunk for workflow "${workflowId}"`);
134
+ await withRetry(async () => engine.storage.batch([
135
+ {
136
+ type: "put",
137
+ key: KEYS.streamChunk(workflowId, "tokens", tokenSequence),
138
+ value: encode(tokenPayload)
139
+ },
140
+ {
141
+ type: "put",
142
+ key: KEYS.streamTail(workflowId, "tokens"),
143
+ value: encodeStoredStreamTailSequence(tokenSequence)
144
+ }
145
+ ]), `persist token stream chunk for workflow "${workflowId}"`);
139
146
  const streamMessage = JSON.stringify({
140
- ...parsed,
147
+ type: parsed.type,
148
+ timestamp: parsed.timestamp,
141
149
  sequence: tokenSequence,
150
+ cursor: String(tokenSequence),
142
151
  data: tokenPayload
143
152
  });
144
153
  if (options?.publishTokenMessage)
@@ -147,32 +156,34 @@ export function wireEventBroadcasting(engine, server, options) {
147
156
  const streamChannel = workflowChannelPath(workflowId, "stream");
148
157
  server.publish(streamChannel, streamMessage);
149
158
  }
159
+ return;
160
+ }
161
+ await ensureSequenceInitialized(workflowId);
162
+ const sequence = claimNextSequence(sequenceCounters, workflowId), watchMessage = JSON.stringify({
163
+ type: parsed.type,
164
+ timestamp: parsed.timestamp,
165
+ data: parsed.data,
166
+ sequence,
167
+ cursor: String(sequence)
168
+ }), storageKey = KEYS.event(workflowId, sequence), encoded = encode(JSON.parse(watchMessage));
169
+ await withRetry(async () => engine.storage.put(storageKey, encoded), `persist event "${eventType}" for workflow "${workflowId}"`);
170
+ await appendFleetEvent(options?.fleetEventFeed, eventType, workflowId, message);
171
+ if (options?.publishWatchMessage)
172
+ options.publishWatchMessage(workflowId, sequence, watchMessage);
173
+ else {
174
+ const watchChannel = workflowChannelPath(workflowId, "watch");
175
+ server.publish(watchChannel, watchMessage);
150
176
  }
151
177
  }
152
- const eventTypes = [
153
- WorkflowStartedEvent.type,
154
- WorkflowCompletedEvent.type,
155
- WorkflowFailedEvent.type,
156
- WorkflowCancelledEvent.type,
157
- WorkflowTimedOutEvent.type,
158
- ActivityStartedEvent.type,
159
- ActivityCompletedEvent.type,
160
- ActivityFailedEvent.type,
161
- TOKEN_EVENT_TYPE,
162
- SignalReceivedEvent.type,
163
- SignalDeliveredEvent.type,
164
- AttributesChangedEvent.type,
165
- UpdateReceivedEvent.type,
166
- UpdateCompletedEvent.type
167
- ];
168
- for (const eventType of eventTypes)
178
+ for (const eventType of CLIENT_VISIBLE_EVENT_TYPES)
169
179
  engine.addEventListener(eventType, (event) => {
170
- const workflowId = getWorkflowIdFromEvent(event);
171
- if (workflowId === void 0)
172
- return;
173
- const message = serializeEvent(event);
180
+ const workflowId = getWorkflowIdFromEvent(event), message = serializeEvent(event);
174
181
  if (message === null)
175
182
  return;
183
+ if (workflowId === void 0) {
184
+ appendFleetEvent(options?.fleetEventFeed, eventType, void 0, message);
185
+ return;
186
+ }
176
187
  const nextChain = (sequenceChains.get(workflowId) ?? Promise.resolve()).then(() => persistAndPublishEvent(workflowId, eventType, message)).catch((error) => {
177
188
  console.error(`[weft] Failed to persist event "${eventType}" for workflow "${workflowId}":`, error);
178
189
  });
@@ -203,3 +214,26 @@ export function wireEventBroadcasting(engine, server, options) {
203
214
  cleanupWorkflow
204
215
  };
205
216
  }
217
+ async function appendFleetEvent(fleetEventFeed, eventType, workflowId, message) {
218
+ if (eventType === TOKEN_EVENT_TYPE)
219
+ return;
220
+ if (fleetEventFeed === void 0)
221
+ return;
222
+ try {
223
+ const parsed = JSON.parse(message), event = {
224
+ kind: eventType,
225
+ emittedAtMs: parsed.timestamp,
226
+ payload: parsed.data
227
+ };
228
+ if (workflowId === void 0) {
229
+ await fleetEventFeed.append(event);
230
+ return;
231
+ }
232
+ await fleetEventFeed.appendWorkflowEventIfPresent({
233
+ ...event,
234
+ workflowId
235
+ });
236
+ } catch (error) {
237
+ console.error(`[weft] Failed to append fleet event "${eventType}":`, error);
238
+ }
239
+ }
@@ -0,0 +1 @@
1
+ export declare function withRetry<T>(operation: () => Promise<T>, label: string, maxAttempts?: number): Promise<T>;
@@ -0,0 +1,14 @@
1
+ export async function withRetry(operation, label, maxAttempts = 2) {
2
+ let lastError;
3
+ for (let attempt = 1;attempt <= maxAttempts; attempt++)
4
+ try {
5
+ return await operation();
6
+ } catch (error) {
7
+ lastError = error;
8
+ if (attempt < maxAttempts) {
9
+ console.warn(`[weft] Retrying "${label}" (attempt ${attempt + 1}/${maxAttempts})`);
10
+ await Bun.sleep(100 * attempt);
11
+ }
12
+ }
13
+ throw lastError;
14
+ }
@@ -1,10 +1,11 @@
1
1
  import type { ServerContext } from './context.ts';
2
2
  export declare const DEFAULT_SHUTDOWN_TIMEOUT_MS = 30000;
3
+ type WorkerShutdownOptions = {
4
+ timeoutMs?: number | undefined;
5
+ stopWaitingWhenIdle?: boolean | undefined;
6
+ };
3
7
  /** Send a shutdown message to a specific worker and wait for it to disconnect. */
4
- export declare function shutdownWorker(context: ServerContext, workerId: string, shutdownOptions?: {
5
- timeoutMs?: number;
6
- }): Promise<boolean>;
8
+ export declare function shutdownWorker(context: ServerContext, workerId: string, shutdownOptions?: WorkerShutdownOptions): Promise<boolean>;
7
9
  /** Send a shutdown message to all connected workers and wait for them to disconnect. */
8
- export declare function shutdownAllWorkers(context: ServerContext, shutdownOptions?: {
9
- timeoutMs?: number;
10
- }): Promise<void>;
10
+ export declare function shutdownAllWorkers(context: ServerContext, shutdownOptions?: WorkerShutdownOptions): Promise<void>;
11
+ export {};
@@ -1,11 +1,16 @@
1
1
  export const DEFAULT_SHUTDOWN_TIMEOUT_MS = 30000;
2
+ function workerShutdownFinished(context, workerId, options) {
3
+ if (!context.workerSockets.has(workerId))
4
+ return !0;
5
+ return options?.stopWaitingWhenIdle === !0 && context.registry.getWorkerTasks(workerId).length === 0;
6
+ }
2
7
  export async function shutdownWorker(context, workerId, shutdownOptions) {
3
8
  const ws = context.workerSockets.get(workerId);
4
9
  if (!ws)
5
10
  return !1;
6
11
  ws.send(JSON.stringify({ type: "shutdown" }));
7
12
  const timeout = shutdownOptions?.timeoutMs ?? DEFAULT_SHUTDOWN_TIMEOUT_MS, deadline = Date.now() + timeout;
8
- while (context.workerSockets.has(workerId)) {
13
+ while (!workerShutdownFinished(context, workerId, shutdownOptions)) {
9
14
  if (Date.now() >= deadline)
10
15
  return !0;
11
16
  await Bun.sleep(50);
@@ -1,22 +1,24 @@
1
1
  import { isAuthenticated } from "../principal.js";
2
+ import { readRestJsonBody } from "../rest-body.js";
3
+ import { readInflightRecord, transitionQueuedToInflight } from "../task-state.js";
4
+ import { recordTaskBacklogMetric, recordTaskQueueLatencyMetric } from "./task-metrics.js";
2
5
  import {
3
- readInflightRecord,
4
- transitionInflightToResolved,
5
- transitionQueuedToInflight
6
- } from "../task-state.js";
7
- import {
8
- recordTaskBacklogMetric,
9
- recordTaskExecutionLatencyMetric,
10
- recordTaskQueueLatencyMetric
11
- } from "./task-metrics.js";
6
+ taskResultPayloadSizeError,
7
+ transitionTaskResultToResolvedWithRetry
8
+ } from "./task-result-resolution.js";
12
9
  const TASK_POLL_RE = /^\/v1\/tasks\/([\w-]+)$/, TASK_RESULT_RE = /^\/v1\/tasks\/([\w-]+)\/result$/, TASK_DIAGNOSTICS_PATH = "/v1/tasks/diagnostics", MAX_POLL_TIMEOUT = 60000, DEFAULT_POLL_TIMEOUT = 30000, DEFAULT_VISIBILITY_TIMEOUT = 30000;
13
- async function parseTaskResultBody(request) {
10
+ async function parseTaskResultBody(request, options) {
14
11
  try {
15
- return await request.json();
16
- } catch {
12
+ return await readRestJsonBody(request, options);
13
+ } catch (error) {
14
+ if (isPayloadTooLargeFault(error))
15
+ return Response.json({ error: error.message }, { status: 413 });
17
16
  return null;
18
17
  }
19
18
  }
19
+ function isPayloadTooLargeFault(value) {
20
+ return typeof value === "object" && value !== null && value.code === "PayloadTooLarge" && typeof value.message === "string";
21
+ }
20
22
  function authorizeWorkerPrincipal(principal) {
21
23
  if (principal === void 0)
22
24
  return null;
@@ -47,19 +49,42 @@ async function applyTaskResult(context, options, result, inflightRecord) {
47
49
  try {
48
50
  context.taskQueue.complete({ operationId, status, value, error });
49
51
  context.deadlineTracker.remove(operationId);
50
- const resolvedAt = Date.now();
51
- await transitionInflightToResolved(options.engine.storage, operationId, resolvedStatus, {
52
- ...inflightRecord === null ? {} : { record: inflightRecord },
53
- resolvedAt,
52
+ await transitionTaskResultToResolvedWithRetry(context, options, {
53
+ operationId,
54
+ status: resolvedStatus,
54
55
  resolutionReason: resolvedStatus,
56
+ inflightRecord,
55
57
  ...status === "completed" ? { value } : { error }
56
58
  });
57
- if (inflightRecord !== null)
58
- recordTaskExecutionLatencyMetric(context.metricsCollector, inflightRecord, resolvedAt);
59
59
  } catch (storageError) {
60
60
  console.error(`[weft] Failed to transition task "${operationId}" to resolved \u2014 inflight record may leak:`, storageError);
61
61
  }
62
62
  }
63
+ async function applyPayloadRejectedTaskResult(context, options, result, inflightRecord, error) {
64
+ context.taskQueue.complete({
65
+ operationId: result.operationId,
66
+ status: "failed",
67
+ error: error.message
68
+ });
69
+ context.deadlineTracker.remove(result.operationId);
70
+ await transitionTaskResultToResolvedWithRetry(context, options, {
71
+ operationId: result.operationId,
72
+ status: "failed",
73
+ resolutionReason: "failed",
74
+ inflightRecord,
75
+ error: error.message,
76
+ skipPayloadSizeCheck: !0
77
+ });
78
+ }
79
+ function payloadSizeExceededResponse(error) {
80
+ return Response.json({
81
+ error: error.message,
82
+ code: error.code,
83
+ maxBytes: error.maxBytes,
84
+ serializedBytes: error.serializedBytes,
85
+ payloadKind: error.payloadKind
86
+ }, { status: 413 });
87
+ }
63
88
  export function createLongPollInflightRecord(queue, task) {
64
89
  const now = Date.now(), visibilityTimeout = task.visibilityTimeout ?? DEFAULT_VISIBILITY_TIMEOUT, deadline = now + visibilityTimeout;
65
90
  return {
@@ -126,7 +151,9 @@ export async function handleTaskResultRequest(context, options, request, url, pr
126
151
  const authorizationResponse = authorizeWorkerPrincipal(principal);
127
152
  if (authorizationResponse !== null)
128
153
  return authorizationResponse;
129
- const body = await parseTaskResultBody(request);
154
+ const body = await parseTaskResultBody(request, options.maxRequestBodyBytes !== void 0 ? { maxBodyBytes: options.maxRequestBodyBytes } : {});
155
+ if (body instanceof Response)
156
+ return body;
130
157
  if (body === null)
131
158
  return Response.json({ error: "Invalid JSON body" }, { status: 400 });
132
159
  const validated = validateTaskResultBody(body);
@@ -135,13 +162,27 @@ export async function handleTaskResultRequest(context, options, request, url, pr
135
162
  const inflightRecord = await readInflightRecord(options.engine.storage, validated.operationId);
136
163
  if (inflightRecord !== null && !isLongPollCompletionAuthorized(inflightRecord, validated))
137
164
  return Response.json({ error: "Forbidden" }, { status: 403 });
165
+ const payloadError = taskResultPayloadSizeError({
166
+ operationId: validated.operationId,
167
+ status: validated.status,
168
+ resolutionReason: validated.status,
169
+ ...validated.status === "completed" ? { value: validated.value } : { error: validated.error }
170
+ }, context.payloadSizeMaxBytes);
171
+ if (payloadError !== null) {
172
+ try {
173
+ await applyPayloadRejectedTaskResult(context, options, validated, inflightRecord, payloadError);
174
+ } catch (error) {
175
+ console.error(`[weft] Failed to persist oversized task result rejection for task "${validated.operationId}":`, error);
176
+ }
177
+ return payloadSizeExceededResponse(payloadError);
178
+ }
138
179
  await applyTaskResult(context, options, validated, inflightRecord);
139
180
  return Response.json({ ok: !0 });
140
181
  }
141
182
  function isLongPollCompletionAuthorized(inflightRecord, validated) {
142
183
  if (validated.workerId === void 0 || inflightRecord.workerId !== validated.workerId)
143
184
  return !1;
144
- if (inflightRecord.attemptToken !== void 0 && validated.attemptToken !== void 0 && validated.attemptToken !== inflightRecord.attemptToken)
185
+ if (inflightRecord.attemptToken !== void 0 && validated.attemptToken !== inflightRecord.attemptToken)
145
186
  return !1;
146
187
  return !0;
147
188
  }
@@ -3,7 +3,11 @@ import { ActivityFailedEvent } from "../../core/events.js";
3
3
  import { calculateBackoff } from "../../core/scheduler.js";
4
4
  import { KEYS } from "../../storage/interface.js";
5
5
  import { restoreExtendedDeadlineIfStillActive } from "../runtime-helpers.js";
6
- import { transitionInflightToQueued, transitionInflightToResolved } from "../task-state.js";
6
+ import {
7
+ isTaskDeadLettered,
8
+ transitionInflightToQueued,
9
+ transitionInflightToResolved
10
+ } from "../task-state.js";
7
11
  import { dispatchTaskImpl, scheduleDelayedDispatch } from "./task-dispatch.js";
8
12
  import {
9
13
  isTaskHeartbeatStaleForMetrics,
@@ -98,6 +102,8 @@ export async function scanExpiredTasks(context, options, cleanupWorkflowIndex) {
98
102
  console.error(`[weft] Corrupt inflight record for task "${operationId}" \u2014 skipping`);
99
103
  continue;
100
104
  }
105
+ if (await isTaskDeadLettered(options.engine.storage, operationId))
106
+ continue;
101
107
  if (restoreExtendedDeadlineIfStillActive(context.deadlineTracker, operationId, decoded.deadline, now))
102
108
  continue;
103
109
  context.registry.completeTask(decoded.operationId);
@@ -130,6 +136,8 @@ export async function reconcileOrphanedRecords(context, options, cleanupWorkflow
130
136
  continue;
131
137
  if (isTaskHeartbeatStaleForMetrics(decoded, now))
132
138
  staleHeartbeatCount += 1;
139
+ if (await isTaskDeadLettered(options.engine.storage, decoded.operationId))
140
+ continue;
133
141
  if (decoded.deadline > now) {
134
142
  if (context.processingOperations.has(decoded.operationId))
135
143
  continue;
@@ -0,0 +1,15 @@
1
+ import { PayloadSizeExceededError } from '../../core/payload-size.ts';
2
+ import type { ServeOptions } from '../index.ts';
3
+ import { type InflightRecord, type TaskResolutionReason } from '../task-state.ts';
4
+ import type { ServerContext } from './context.ts';
5
+ export type TaskResultResolutionInput = {
6
+ readonly operationId: string;
7
+ readonly status: 'completed' | 'failed';
8
+ readonly resolutionReason: TaskResolutionReason;
9
+ readonly value?: unknown;
10
+ readonly error?: string | undefined;
11
+ readonly inflightRecord?: InflightRecord | null | undefined;
12
+ readonly skipPayloadSizeCheck?: boolean | undefined;
13
+ };
14
+ export declare function taskResultPayloadSizeError(input: TaskResultResolutionInput, maxBytes: number | null): PayloadSizeExceededError | null;
15
+ export declare function transitionTaskResultToResolvedWithRetry(context: ServerContext, options: ServeOptions, input: TaskResultResolutionInput): Promise<void>;
@@ -0,0 +1,81 @@
1
+ import { TaskResultDeadLetteredEvent } from "../../core/events.js";
2
+ import { PayloadSizeExceededError, assertPayloadWithinLimit } from "../../core/payload-size.js";
3
+ import {
4
+ readInflightRecord,
5
+ transitionInflightToResolved,
6
+ writeDeadLetteredTaskRecord
7
+ } from "../task-state.js";
8
+ import { withRetry } from "./retry.js";
9
+ import { recordTaskExecutionLatencyMetric } from "./task-metrics.js";
10
+ const TASK_RESULT_RESOLUTION_RETRY_ATTEMPTS = 2;
11
+ function taskResultPayloadForSizeCheck(input) {
12
+ return input.status === "completed" ? input.value : input.error ?? "";
13
+ }
14
+ export function taskResultPayloadSizeError(input, maxBytes) {
15
+ try {
16
+ assertPayloadWithinLimit(taskResultPayloadForSizeCheck(input), maxBytes, "activity result");
17
+ return null;
18
+ } catch (error) {
19
+ if (error instanceof PayloadSizeExceededError)
20
+ return error;
21
+ throw error;
22
+ }
23
+ }
24
+ export async function transitionTaskResultToResolvedWithRetry(context, options, input) {
25
+ if (input.skipPayloadSizeCheck !== !0) {
26
+ const payloadError = taskResultPayloadSizeError(input, context.payloadSizeMaxBytes);
27
+ if (payloadError !== null)
28
+ throw payloadError;
29
+ }
30
+ const storage = options.engine.storage, resolvedAt = Date.now();
31
+ let latestInflightRecord = input.inflightRecord;
32
+ try {
33
+ await withRetry(async () => {
34
+ if (latestInflightRecord === void 0)
35
+ latestInflightRecord = await readInflightRecord(storage, input.operationId);
36
+ await transitionInflightToResolved(storage, input.operationId, input.status, {
37
+ ...latestInflightRecord === null ? {} : { record: latestInflightRecord },
38
+ resolvedAt,
39
+ resolutionReason: input.resolutionReason,
40
+ ...input.status === "completed" ? { value: input.value } : { error: input.error }
41
+ });
42
+ }, `transition task "${input.operationId}" to resolved`, TASK_RESULT_RESOLUTION_RETRY_ATTEMPTS);
43
+ } catch (error) {
44
+ const fallbackInflightRecord = latestInflightRecord ?? await readInflightRecord(storage, input.operationId).catch(() => null);
45
+ await withRetry(async () => {
46
+ await writeTaskResultDeadLetter(options, input, fallbackInflightRecord);
47
+ }, `dead-letter task "${input.operationId}" after result-resolution retries`, TASK_RESULT_RESOLUTION_RETRY_ATTEMPTS);
48
+ console.error(`[weft] Failed to transition task "${input.operationId}" to resolved after retries \u2014 dead-lettered:`, error);
49
+ return;
50
+ }
51
+ if (latestInflightRecord !== null && latestInflightRecord !== void 0)
52
+ recordTaskExecutionLatencyMetric(context.metricsCollector, latestInflightRecord, resolvedAt);
53
+ }
54
+ async function writeTaskResultDeadLetter(options, input, inflightRecord) {
55
+ const storageErrorCode = "result-resolution-storage-exhausted", record = {
56
+ operationId: input.operationId,
57
+ reason: storageErrorCode,
58
+ deadLetteredAt: Date.now(),
59
+ errorMessage: storageErrorCode,
60
+ retryAttempts: TASK_RESULT_RESOLUTION_RETRY_ATTEMPTS,
61
+ status: input.status,
62
+ ...inflightRecord?.activityName === void 0 ? {} : { activityName: inflightRecord.activityName },
63
+ ...inflightRecord?.queue === void 0 ? {} : { queue: inflightRecord.queue },
64
+ ...inflightRecord?.workerId === void 0 ? {} : { workerId: inflightRecord.workerId },
65
+ ...inflightRecord?.attempt === void 0 ? {} : { attempt: inflightRecord.attempt },
66
+ ...inflightRecord?.visibilityTimeout === void 0 ? {} : { visibilityTimeout: inflightRecord.visibilityTimeout },
67
+ ...inflightRecord?.workflowId === void 0 ? {} : { workflowId: inflightRecord.workflowId },
68
+ ...inflightRecord?.retryCount === void 0 ? {} : { retryCount: inflightRecord.retryCount },
69
+ ...inflightRecord?.requeueCount === void 0 ? {} : { requeueCount: inflightRecord.requeueCount },
70
+ ...inflightRecord?.lastRequeueReason === void 0 ? {} : { lastRequeueReason: inflightRecord.lastRequeueReason }
71
+ };
72
+ await writeDeadLetteredTaskRecord(options.engine.storage, record);
73
+ options.engine.dispatchEvent(new TaskResultDeadLetteredEvent({
74
+ operationId: record.operationId,
75
+ workflowId: record.workflowId,
76
+ activityName: record.activityName,
77
+ queue: record.queue,
78
+ workerId: record.workerId,
79
+ errorMessage: record.errorMessage
80
+ }));
81
+ }
@@ -2,14 +2,33 @@ import type { ServerWebSocket } from 'bun';
2
2
  import type { Engine } from '../../core/engine.ts';
3
3
  import type { WebSocketData } from '../json-rpc-websocket-runtime.ts';
4
4
  import type { ServerContext } from './context.ts';
5
+ /**
6
+ * Default per-workflow cap for one-way workflow WebSocket connections
7
+ * (`/stream` and `/watch`). Mirrors the JSON-RPC subscription default so one
8
+ * workflow cannot consume unbounded server sockets.
9
+ */
10
+ export declare const DEFAULT_MAX_STREAM_CONNECTIONS_PER_WORKFLOW = 100;
5
11
  export declare function sendStreamMessage(ws: ServerWebSocket<WebSocketData>, sequence: number, message: string): void;
12
+ export declare function sendWatchMessage(ws: ServerWebSocket<WebSocketData>, sequence: number, message: string): void;
6
13
  export declare function getHighestStoredStreamSequence(engine: Engine, workflowId: string, key: string): Promise<number>;
7
- export declare function addStreamSocket(context: ServerContext, workflowId: string, ws: ServerWebSocket<WebSocketData>): void;
14
+ export declare function getHighestStoredWatchSequence(engine: Engine, workflowId: string): Promise<number>;
15
+ export declare function addStreamSocket(context: ServerContext, workflowId: string, ws: ServerWebSocket<WebSocketData>): boolean;
16
+ export declare function addWatchSocket(context: ServerContext, workflowId: string, ws: ServerWebSocket<WebSocketData>): boolean;
8
17
  export declare function removeStreamSocket(context: ServerContext, ws: ServerWebSocket<WebSocketData>): void;
18
+ export declare function removeWatchSocket(context: ServerContext, ws: ServerWebSocket<WebSocketData>): void;
19
+ export declare function removeWorkflowStreamConnection(context: ServerContext, ws: ServerWebSocket<WebSocketData>): void;
9
20
  export declare function flushPendingStreamMessages(_context: ServerContext, ws: ServerWebSocket<WebSocketData>): void;
21
+ export declare function flushPendingWatchMessages(_context: ServerContext, ws: ServerWebSocket<WebSocketData>): void;
10
22
  export declare function publishTokenMessage(context: ServerContext, workflowId: string, sequence: number, message: string): void;
23
+ export declare function publishWatchMessage(context: ServerContext, workflowId: string, sequence: number, message: string): void;
11
24
  /**
12
25
  * Send existing token chunks from storage to a newly connected stream client,
13
26
  * so it can catch up on tokens emitted before the connection was established.
14
27
  */
15
28
  export declare function replayTokenStream(context: ServerContext, engine: Engine, ws: ServerWebSocket<WebSocketData>, workflowId: string): Promise<void>;
29
+ /**
30
+ * Send stored raw watch events to a newly connected watch client. The raw
31
+ * watch transport keeps its historical frame shape but now honors the same
32
+ * `resumeFrom` cursor query parameter used by token streams.
33
+ */
34
+ export declare function replayWatchEvents(context: ServerContext, engine: Engine, ws: ServerWebSocket<WebSocketData>, workflowId: string): Promise<void>;