@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
@@ -8,6 +8,10 @@ import {
8
8
  assertChildWorkflowNestingDepth,
9
9
  executeChildWorkflow
10
10
  } from "./child-workflow.js";
11
+ import {
12
+ executeSleepSubOperation,
13
+ executeWaitSignalSubOperation
14
+ } from "./coordination-branch-executors.js";
11
15
  import {
12
16
  executeActivityOperationResult
13
17
  } from "./operations-activity.js";
@@ -32,17 +36,22 @@ export async function executeSubOperation(internals, workflowId, operation, call
32
36
  }, operation);
33
37
  }
34
38
  const subOperationExecutors = {
35
- activity: (context, operation) => executeActivitySubOperation(context.internals, context.workflowId, operation, context.callbacks, context.speculativeState),
39
+ activity: (context, operation) => executeActivitySubOperation(context.internals, context.workflowId, operation, context.callbacks, context.signal, context.speculativeState),
36
40
  "child-workflow": (context, operation) => executeChildWorkflowSubOperation(context.internals, context.workflowId, operation, context.callbacks),
37
41
  memo: (_context, operation) => Promise.resolve(callMemoFunction(operation.fn)),
38
42
  "state-read": (context, operation) => executeStateReadSubOperation(context.internals, operation),
39
43
  "state-commit": (context, operation) => executeStateCommitSubOperation(context.internals, operation, context.callbacks),
40
44
  parallel: (context, operation) => executeParallelSubOperation(context.internals, context.workflowId, operation, context.callbacks, context.signal, context.speculativeState),
41
45
  race: (context, operation) => executeRaceSubOperation(context.internals, context.workflowId, operation, context.callbacks, context.signal, context.speculativeState),
42
- "run-all": (context, operation) => executeRunAllOperationResult(context.internals, context.workflowId, operation, context.callbacks.createCoordinationOperationCallbacks(), context.speculativeState)
46
+ "run-all": (context, operation) => executeRunAllOperationResult(context.internals, context.workflowId, operation, context.callbacks.createCoordinationOperationCallbacks(), context.speculativeState),
47
+ sleep: (context, operation) => executeSleepSubOperation(context.internals, operation, context.signal),
48
+ "wait-signal": (context, operation) => executeWaitSignalSubOperation(context.internals, context.workflowId, operation, context.signal),
49
+ "wait-condition": () => {
50
+ throw Error("ctx.waitUntil() cannot be used as a ctx.race() / ctx.all() / ctx.speculate() branch. Use `yield* ctx.waitUntil(...)` directly, or gate it behind a signal/update the coordinator resolves.");
51
+ }
43
52
  };
44
- async function executeActivitySubOperation(internals, workflowId, operation, callbacks, speculativeState) {
45
- return executeActivityOperationResult(internals, workflowId, operation, callbacks.createActivityOperationCallbacks(), speculativeState);
53
+ async function executeActivitySubOperation(internals, workflowId, operation, callbacks, signal, speculativeState) {
54
+ return executeActivityOperationResult(internals, workflowId, operation, callbacks.createActivityOperationCallbacks(), signal, speculativeState);
46
55
  }
47
56
  async function executeChildWorkflowSubOperation(internals, workflowId, operation, callbacks) {
48
57
  return executeChildWorkflow(internals, workflowId, operation, assertChildWorkflowNestingDepth(internals, workflowId), callbacks.createChildWorkflowOperationCallbacks());
@@ -58,8 +67,18 @@ async function executeStateCommitSubOperation(internals, operation, callbacks) {
58
67
  }
59
68
  async function executeParallelSubOperation(internals, workflowId, operation, callbacks, signal, speculativeState) {
60
69
  signal?.throwIfAborted();
61
- const subOperationPromises = operation.operations.map((subOperation) => executeSubOperation(internals, workflowId, subOperation, callbacks, signal, speculativeState));
62
- return Promise.all(subOperationPromises);
70
+ const controller = new AbortController, abortNestedAll = () => {
71
+ controller.abort(signal?.reason);
72
+ };
73
+ signal?.addEventListener("abort", abortNestedAll, { once: !0 });
74
+ const subOperationPromises = operation.operations.map((subOperation) => executeSubOperation(internals, workflowId, subOperation, callbacks, controller.signal, speculativeState));
75
+ Promise.allSettled(subOperationPromises);
76
+ try {
77
+ return await Promise.all(subOperationPromises);
78
+ } finally {
79
+ signal?.removeEventListener("abort", abortNestedAll);
80
+ controller.abort();
81
+ }
63
82
  }
64
83
  async function executeRaceSubOperation(internals, workflowId, operation, callbacks, signal, speculativeState) {
65
84
  signal?.throwIfAborted();
@@ -13,7 +13,9 @@ export type TerminationCallbacks = {
13
13
  handleScheduledWorkflowTerminal: (workflowId: string) => Promise<void>;
14
14
  loadWorkflowState: (workflowId: string) => Promise<WorkflowState | null>;
15
15
  runSerializedWorkflowStateWrite: <Result>(workflowId: string, writeOperation: () => Promise<Result>) => Promise<Result>;
16
- commitWorkflowStateOperations: (state: WorkflowState, operations: BatchOperation[]) => Promise<void>;
16
+ commitWorkflowStateOperations: (state: WorkflowState, operations: BatchOperation[], options?: {
17
+ includePendingAtomicSideEffects?: boolean;
18
+ }) => Promise<void>;
17
19
  cleanupReviews: (workflowId: string) => Promise<void>;
18
20
  };
19
21
  export declare const TERMINAL_WORKFLOW_STATUSES: ReadonlySet<WorkflowStatus>;
@@ -1,8 +1,9 @@
1
- import { KEYS, encodeStorageKeyComponent } from "../../../storage/interface.js";
1
+ import { KEYS, encodeStorageKeyComponent, storageHas } from "../../../storage/interface.js";
2
2
  import { CleanupWarningEvent } from "../../events.js";
3
3
  import { asyncActivityWorkflowPrefix } from "../async-activity-completion.js";
4
4
  import { forgetCommittedCheckpointBytes } from "../checkpoint-commit-snapshots.js";
5
5
  import { parseTerminalCleanupTimerId, workflowFeedListenerKey } from "../state-utilities.js";
6
+ import { releaseWorkflowConcurrencySlot } from "../workflow-concurrency.js";
6
7
  export const TERMINAL_WORKFLOW_STATUSES = new Set([
7
8
  "completed",
8
9
  "failed",
@@ -60,6 +61,16 @@ function evictSleepResolversWithoutResolving(internals, workflowId) {
60
61
  internals.sleepResolvers.delete(`${workflowId}:${operationId}`);
61
62
  internals.sleepResolversByWorkflow.delete(workflowId);
62
63
  }
64
+ function cleanupConditionWaiters(internals, workflowId) {
65
+ const resolver = internals.conditionWaiters.get(workflowId);
66
+ if (!resolver)
67
+ return;
68
+ resolver();
69
+ internals.conditionWaiters.delete(workflowId);
70
+ }
71
+ function evictConditionWaitersWithoutResolving(internals, workflowId) {
72
+ internals.conditionWaiters.delete(workflowId);
73
+ }
63
74
  function cleanupReviewEscalations(internals, workflowId, callbacks) {
64
75
  const reviewIds = internals.workflowReviewIds.get(workflowId);
65
76
  if (!reviewIds)
@@ -80,7 +91,9 @@ export function cleanupWaiters(internals, workflowId, callbacks) {
80
91
  for (const kind of TRACKED_WAITER_KINDS)
81
92
  cleanupTrackedWaiter(internals, workflowId, kind);
82
93
  cleanupSleepResolvers(internals, workflowId);
94
+ cleanupConditionWaiters(internals, workflowId);
83
95
  cleanupReviewEscalations(internals, workflowId, callbacks);
96
+ internals.deliveredPendingUpdateIds.delete(workflowId);
84
97
  internals.workflowNestingDepths.delete(workflowId);
85
98
  internals.workflowHeaders.delete(workflowId);
86
99
  internals.workflowServices.delete(workflowId);
@@ -90,11 +103,13 @@ export function evictSuspendedWorkflowWaiters(internals, workflowId, callbacks)
90
103
  for (const kind of TRACKED_WAITER_KINDS)
91
104
  cleanupTrackedWaiter(internals, workflowId, kind);
92
105
  evictSleepResolversWithoutResolving(internals, workflowId);
106
+ evictConditionWaitersWithoutResolving(internals, workflowId);
93
107
  cleanupReviewEscalations(internals, workflowId, callbacks);
94
108
  }
95
109
  export async function cleanupWorkflowStorage(internals, workflowId, includeOutputArtifacts) {
96
110
  const encodedWorkflowId = encodeStorageKeyComponent(workflowId), prefixes = [
97
111
  KEYS.activityReconciliationPrefix(workflowId),
112
+ KEYS.childCancellationPrefix(workflowId),
98
113
  asyncActivityWorkflowPrefix(workflowId),
99
114
  KEYS.signalAcceptedResponsePrefix(workflowId),
100
115
  `sig:${encodedWorkflowId}:`,
@@ -105,7 +120,10 @@ export async function cleanupWorkflowStorage(internals, workflowId, includeOutpu
105
120
  prefixes.push(`offload:${encodedWorkflowId}:`, `blob:${encodedWorkflowId}:`);
106
121
  await internals.storage.delete(KEYS.workflowHeaders(workflowId));
107
122
  await internals.storage.delete(KEYS.signalSequence(workflowId));
123
+ await releaseWorkflowConcurrencySlot(internals, workflowId);
108
124
  await internals.storage.delete(KEYS.workflowHasServices(workflowId));
125
+ if (!await storageHas(internals.storage, KEYS.teardownOwed(workflowId)))
126
+ await internals.storage.delete(KEYS.finalizerState(workflowId));
109
127
  if (internals.storage.deletePrefix) {
110
128
  for (const prefix of prefixes)
111
129
  await internals.storage.deletePrefix(prefix);
@@ -132,12 +150,18 @@ export function cleanupTerminalWorkflowMemory(internals, workflowId, callbacks)
132
150
  forgetCommittedCheckpointBytes(internals, workflowId);
133
151
  internals.checkpoints.delete(workflowId);
134
152
  internals.heartbeatDetails.delete(workflowId);
153
+ internals.lastHeartbeatDetailsByStep.delete(workflowId);
135
154
  for (const [token, pending] of internals.pendingAsyncActivities)
136
155
  if (pending.workflowId === workflowId)
137
156
  internals.pendingAsyncActivities.delete(token);
138
157
  internals.eventLogHeads.delete(workflowId);
139
158
  internals.pendingTimelineEntries.delete(workflowId);
159
+ internals.pendingAsyncActivityResolutions ??= new Map;
160
+ internals.pendingAsyncActivityResolutions.delete(workflowId);
161
+ internals.pendingAtomicWorkflowCommitSideEffects ??= new Map;
162
+ internals.pendingAtomicWorkflowCommitSideEffects.delete(workflowId);
140
163
  internals.parkedInlineWorkflows.delete(workflowId);
164
+ internals.inlineStrategy?.clearParkedContext(workflowId);
141
165
  internals.workflowVersionTuples.delete(workflowId);
142
166
  internals.cancelHandlersByWorkflow.delete(workflowId);
143
167
  internals.workflowFeedListeners.delete(workflowFeedListenerKey(workflowId, "events"));
@@ -18,10 +18,16 @@ import {
18
18
  } from "../attributes-tags.js";
19
19
  import { TERMINAL_CLEANUP_DELAY_MS } from "../bulk-operations.js";
20
20
  import { takeCancelHandlers } from "../cancel-handlers.js";
21
+ import { pendingAtomicWorkflowCommitSideEffectsStagePut } from "../checkpoint-side-effects.js";
21
22
  import { getWorkflowExecutionStartedAt } from "../handles.js";
22
23
  import { dropQueuedInlineWorkflowStart } from "../inline-launch-queue.js";
23
24
  import { EMPTY_STORAGE_VALUE } from "../lifecycle.js";
24
- import { createTerminalCleanupTimerId, summarizeTimelineValue } from "../state-utilities.js";
25
+ import {
26
+ createTeardownTimerId,
27
+ createTerminalCleanupTimerId,
28
+ summarizeTimelineValue
29
+ } from "../state-utilities.js";
30
+ import { releaseWorkflowConcurrencySlot } from "../workflow-concurrency.js";
25
31
  import { buildWorkflowVisibilityIndexTransition } from "../workflow-indexes.js";
26
32
  import {
27
33
  cleanupTerminalWorkflowImmediately,
@@ -54,17 +60,26 @@ export async function terminateWorkflow(internals, workflowId, status, callbacks
54
60
  dropQueuedInlineWorkflowStart(internals, workflowId);
55
61
  internals.strategy.cancelWorkflow(workflowId);
56
62
  try {
57
- const attributeBytes = await internals.storage.get(KEYS.attribute(workflowId)), attributes = attributeBytes ? decode(attributeBytes) : {}, retainedAttributes = buildRetainedTerminalSearchAttributes(attributes), terminationMessage = status === "timed-out" ? "Workflow timed out" : "Workflow cancelled", terminationResult = await updateWorkflowState(internals, workflowId, { status, ...reason !== void 0 ? { terminationReason: reason } : {} }, {
63
+ const terminalCleanupToken = internals.workflowsNeedingTerminalCleanup.has(workflowId) ? crypto.randomUUID() : void 0, attributeBytes = await internals.storage.get(KEYS.attribute(workflowId)), attributes = attributeBytes ? decode(attributeBytes) : {}, finalizerStatePresent = await internals.storage.get(KEYS.finalizerState(workflowId)) !== null || pendingAtomicWorkflowCommitSideEffectsStagePut(internals, workflowId, KEYS.finalizerState(workflowId)), retainedAttributes = buildRetainedTerminalSearchAttributes(attributes), terminationMessage = status === "timed-out" ? "Workflow timed out" : "Workflow cancelled", terminationResult = await updateWorkflowState(internals, workflowId, {
64
+ status,
65
+ ...reason !== void 0 ? { terminationReason: reason } : {},
66
+ ...terminalCleanupToken !== void 0 ? { terminalCleanupToken } : {}
67
+ }, {
58
68
  allowedStatuses: FORCIBLY_TERMINABLE_STATUSES,
59
69
  buildAdditionalOperations: (_previousState, updatedAt) => {
60
70
  finalizePendingTimelineEntry(internals, workflowId, status, terminationMessage, updatedAt);
61
71
  const pendingTimelineOperation = buildPendingTimelineOperation(internals, workflowId);
62
- return pendingTimelineOperation ? [pendingTimelineOperation] : [];
72
+ return [
73
+ ...pendingTimelineOperation ? [pendingTimelineOperation] : [],
74
+ ...terminalCleanupToken !== void 0 ? buildTerminalCleanupTimerOperations(internals, workflowId, !0, updatedAt, terminalCleanupToken) : [],
75
+ ...buildTeardownOperations(workflowId, finalizerStatePresent, updatedAt)
76
+ ];
63
77
  }
64
78
  });
65
79
  if (!terminationResult)
66
80
  return;
67
81
  await runCancellationHandlersForStatus(internals, workflowId, status, callbacks);
82
+ await releaseWorkflowConcurrencySlot(internals, workflowId);
68
83
  const { previousState, updatedAt } = terminationResult, elapsed = updatedAt - getWorkflowExecutionStartedAt(previousState);
69
84
  await cleanupAttributeIndex(internals, workflowId, attributes);
70
85
  await writeRetainedTerminalSearchAttributes(internals, workflowId, retainedAttributes);
@@ -165,11 +180,14 @@ export async function completeWorkflow(internals, workflowId, result, callbacks)
165
180
  appendSearchAttributeOperations(completionOperations, workflowId, currentAttributes);
166
181
  if (terminalCleanupToken !== void 0)
167
182
  completionOperations.push(...buildTerminalCleanupTimerOperations(internals, workflowId, !1, now, terminalCleanupToken));
168
- await callbacks.commitWorkflowStateOperations(state, completionOperations);
183
+ await callbacks.commitWorkflowStateOperations(state, completionOperations, {
184
+ includePendingAtomicSideEffects: !0
185
+ });
169
186
  return { duration };
170
187
  });
171
188
  if (!completionMetadata)
172
189
  return;
190
+ await releaseWorkflowConcurrencySlot(internals, workflowId);
173
191
  notifyCompletionWaiters(internals, workflowId, result, completionMetadata.duration, callbacks);
174
192
  }
175
193
  export async function failWorkflow(internals, workflowId, error, callbacks, failureCategory = "system") {
@@ -179,18 +197,24 @@ export async function failWorkflow(internals, workflowId, error, callbacks, fail
179
197
  status: "failed",
180
198
  error: error.message,
181
199
  failureCategory
182
- };
200
+ }, terminalCleanupToken = internals.workflowsNeedingTerminalCleanup.has(workflowId) ? crypto.randomUUID() : void 0;
183
201
  if (error.stack !== void 0)
184
202
  stateUpdate.errorStack = error.stack;
203
+ if (terminalCleanupToken !== void 0)
204
+ stateUpdate.terminalCleanupToken = terminalCleanupToken;
185
205
  if (!await updateWorkflowState(internals, workflowId, stateUpdate, {
186
206
  allowedStatuses: FORCIBLY_TERMINABLE_STATUSES,
187
207
  buildAdditionalOperations: (_previousState, updatedAt) => {
188
208
  finalizePendingTimelineEntry(internals, workflowId, "failed", error.message, updatedAt);
189
209
  const pendingTimelineOperation = buildPendingTimelineOperation(internals, workflowId);
190
- return pendingTimelineOperation ? [pendingTimelineOperation] : [];
210
+ return [
211
+ ...pendingTimelineOperation ? [pendingTimelineOperation] : [],
212
+ ...terminalCleanupToken !== void 0 ? buildTerminalCleanupTimerOperations(internals, workflowId, !1, updatedAt, terminalCleanupToken) : []
213
+ ];
191
214
  }
192
215
  }))
193
216
  return;
217
+ await releaseWorkflowConcurrencySlot(internals, workflowId);
194
218
  await cleanupAttributeIndex(internals, workflowId, attributes);
195
219
  callbacks.swallowPromiseRejection(internals.scheduler.cancel(`deadline:${workflowId}`, workflowId));
196
220
  await writeRetainedTerminalSearchAttributes(internals, workflowId, retainedAttributes);
@@ -219,6 +243,20 @@ export function buildTerminalCleanupTimerOperations(_internals, workflowId, incl
219
243
  kind: "terminal-cleanup"
220
244
  });
221
245
  }
246
+ function buildTeardownOperations(workflowId, finalizerStatePresent, terminalizedAt) {
247
+ if (!finalizerStatePresent)
248
+ return [];
249
+ const token = crypto.randomUUID(), claim = { status: "owed", attempts: 0, token };
250
+ return [
251
+ { type: "put", key: KEYS.teardownOwed(workflowId), value: encode(claim) },
252
+ ...buildTimerBatchOperations({
253
+ id: createTeardownTimerId(token),
254
+ workflowId,
255
+ fireAt: terminalizedAt,
256
+ kind: "teardown"
257
+ })
258
+ ];
259
+ }
222
260
  export async function ensureTerminalCleanupTracked(internals, workflowId) {
223
261
  if (internals.workflowsNeedingTerminalCleanup.has(workflowId))
224
262
  return;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * The `runFinalizerActivity` primitive (#446 Phase 2). A workflow's definition-level
3
+ * `finalizer` is an ordinary activity, but it runs POST-terminal — after the engine
4
+ * has evicted the workflow's generator and abort controller — so it cannot go through
5
+ * the live-workflow `executeActivity` path: that path reads
6
+ * `inlineStrategy.getAbortController(workflowId)` (gone after cancel) and the
7
+ * per-workflow type/heartbeat bookkeeping (swept by terminal cleanup). This primitive
8
+ * therefore owns its OWN `AbortController`, resolves the implementation from the
9
+ * engine-lifetime registration entry, and never touches the operation-result feedback
10
+ * channel.
11
+ *
12
+ * Outer retry/backoff is the teardown timer reschedule in `runWorkflowFinalizer`, NOT
13
+ * the activity's own `retry` policy — so this primitive runs exactly one attempt and
14
+ * surfaces success or a thrown error to the caller. The activity's `timeout` is honored
15
+ * as a per-attempt cap.
16
+ *
17
+ * @module core/engine/termination/finalizer-activity
18
+ */
19
+ import type { ActivityContext, Duration } from '../../types.ts';
20
+ /**
21
+ * The minimal finalizer shape this primitive uses. A registered finalizer is stored
22
+ * as `AnyActivityDefinition`, whose `execute` is typed `ActivityFunction<never>` (the
23
+ * input is contravariantly `never`) and which erases `timeout` at the type level —
24
+ * neither shape is directly invokable with `unknown` input. The drive narrows the
25
+ * registry entry to this structural type, which is what the engine actually relies on
26
+ * at teardown: a named, callable activity with an optional per-attempt `timeout`.
27
+ */
28
+ export interface RunnableFinalizer {
29
+ readonly name: string;
30
+ readonly timeout?: Duration;
31
+ execute(input: unknown, context?: ActivityContext): unknown;
32
+ }
33
+ /** Outcome of a single finalizer attempt. */
34
+ export type FinalizerAttemptResult = {
35
+ ok: true;
36
+ } | {
37
+ ok: false;
38
+ error: unknown;
39
+ abortedByShutdown: boolean;
40
+ };
41
+ /**
42
+ * Run one attempt of a workflow's finalizer activity against the recorded finalizer
43
+ * state, under a caller-supplied abort signal (the engine shutdown signal) composed
44
+ * with the activity's own per-attempt timeout. Resolves to a structured result rather
45
+ * than throwing, so the drive can branch on success / retryable-failure / dead-letter
46
+ * without a try/catch around it.
47
+ *
48
+ * @param finalizer - the resolved finalizer activity definition (from the engine-lifetime registry)
49
+ * @param input - the decoded `ctx.setFinalizerState` payload passed as the activity input
50
+ * @param attempt - 1-based attempt number, for the per-attempt timeout error message
51
+ * @param shutdownSignal - the engine's dispose/shutdown abort signal; aborting it stops a cooperating finalizer
52
+ */
53
+ export declare function runFinalizerActivity(finalizer: RunnableFinalizer, input: unknown, attempt: number, shutdownSignal: AbortSignal): Promise<FinalizerAttemptResult>;
@@ -0,0 +1,30 @@
1
+ import { parseDuration } from "../../scheduler.js";
2
+ import { withPerAttemptTimeout } from "../activity-per-attempt-timeout.js";
3
+ export async function runFinalizerActivity(finalizer, input, attempt, shutdownSignal) {
4
+ const perAttemptTimeoutMs = finalizer.timeout === void 0 ? void 0 : parseDuration(finalizer.timeout), attemptController = new AbortController, relayShutdownAbort = () => attemptController.abort(shutdownSignal.reason);
5
+ if (shutdownSignal.aborted)
6
+ attemptController.abort(shutdownSignal.reason);
7
+ else
8
+ shutdownSignal.addEventListener("abort", relayShutdownAbort, { once: !0 });
9
+ const activityContext = {
10
+ signal: attemptController.signal,
11
+ heartbeat: () => {},
12
+ completeAsync: () => {
13
+ throw Error(`Finalizer "${finalizer.name}" called ctx.completeAsync(), which is not supported in a workflow finalizer: the finalizer runs after the workflow is already terminal, so there is no durable step to complete out of band. Run the teardown synchronously instead.`);
14
+ }
15
+ };
16
+ try {
17
+ await withPerAttemptTimeout(finalizer.execute(input, activityContext), perAttemptTimeoutMs, finalizer.name, attempt, attemptController);
18
+ if (shutdownSignal.aborted)
19
+ return {
20
+ ok: !1,
21
+ error: Error(`Finalizer "${finalizer.name}" resolved while the engine was shutting down; treating attempt ${attempt} as shutdown-aborted so the teardown re-runs after restart.`, { cause: shutdownSignal.reason }),
22
+ abortedByShutdown: !0
23
+ };
24
+ return { ok: !0 };
25
+ } catch (error) {
26
+ return { ok: !1, error, abortedByShutdown: shutdownSignal.aborted };
27
+ } finally {
28
+ shutdownSignal.removeEventListener("abort", relayShutdownAbort);
29
+ }
30
+ }
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Durable-claim mechanics for the workflow finalizer drive (issue #446 Phase 2).
3
+ * This module owns the `teardownOwed` marker's lifecycle — the stale-claim reclaim
4
+ * horizon, the retry backoff schedule, the dead-letter record shape, and every fenced
5
+ * write that mutates the marker (claim CAS, settle CAS, re-arm, clear, dead-letter). The
6
+ * orchestration that decides WHEN to call these lives in `./finalizer.ts`; keeping the
7
+ * byte-level claim transitions here keeps each module under the size budget and isolates
8
+ * the part where CAS correctness matters most.
9
+ *
10
+ * Concurrency contract (see `./finalizer.ts` for the full model): a holder fenced-CAS's
11
+ * `owed → running` (stamping `claimedAt`) before running the finalizer, then settle-CAS's
12
+ * the EXACT `running` bytes it wrote when clearing, rescheduling, or dead-lettering — so a
13
+ * concurrent reclaimer can never clobber a fresher claim. Liveness is decided purely by
14
+ * the clock via {@link teardownStaleThresholdMs}.
15
+ *
16
+ * @module core/engine/termination/finalizer-claim
17
+ */
18
+ import type { BatchOperation } from '../../../storage/interface.ts';
19
+ import type { EngineInternals } from '../internals.ts';
20
+ import { type TeardownClaim } from '../state-utilities.ts';
21
+ import type { RunnableFinalizer } from './finalizer-activity.ts';
22
+ /** Maximum finalizer attempts before the teardown is dead-lettered (the leak horizon). */
23
+ export declare const MAX_TEARDOWN_ATTEMPTS = 8;
24
+ /** Short re-arm delay for the self-heal timer written on a non-settling drive exit. */
25
+ export declare const TEARDOWN_SELF_HEAL_DELAY_MS = 30000;
26
+ /** Backoff for the timer rescheduled after a failed finalizer attempt (1-based attempt). */
27
+ export declare function teardownBackoffMs(failedAttempt: number): number;
28
+ /**
29
+ * The reclaim horizon for a `running` claim: a holder that has not settled within this
30
+ * window of `claimedAt` is presumed crashed/deposed and its claim is reclaimable. Equal
31
+ * to the finalizer's per-attempt budget (its declared `timeout`, or
32
+ * {@link DEFAULT_FINALIZER_STALE_BUDGET_MS}) plus {@link TEARDOWN_STALE_MARGIN_MS}.
33
+ */
34
+ export declare function teardownStaleThresholdMs(finalizer: RunnableFinalizer): number;
35
+ /** Whether a `running` claim is reclaimable: its holder has not settled within the stale window. */
36
+ export declare function runningClaimIsStale(internals: EngineInternals, claim: TeardownClaim, finalizer: RunnableFinalizer): boolean;
37
+ /**
38
+ * Durable audit record written to {@link KEYS.teardownDeadLetter} when a workflow's
39
+ * finalizer permanently fails — the retry horizon was reached, or the recorded resource
40
+ * state vanished so the finalizer can never run. It is the supported operator surface
41
+ * for a leaked external resource: raw storage inspection of the `wf-teardown-deadletter:`
42
+ * key is the contract (in-process teardown events are best-effort and not durable, and
43
+ * the record is excluded from the workflow purge delete-set so it survives after the
44
+ * workflow record is gone).
45
+ */
46
+ export interface TeardownDeadLetterRecord {
47
+ /** The workflow type whose finalizer leaked. */
48
+ type: string;
49
+ /** The last finalizer error message (or the reason teardown was abandoned). */
50
+ lastError: string;
51
+ /** The attempt count reached before dead-lettering. */
52
+ attempts: number;
53
+ /** Engine clock when the record was written. */
54
+ deadLetteredAt: number;
55
+ /** The decoded `ctx.setFinalizerState` payload, when it was still recoverable. */
56
+ finalizerInput?: unknown;
57
+ }
58
+ /** Build the operations that arm a fresh `wf-teardown:` timer at `fireAt` (same token). */
59
+ export declare function teardownTimerOperations(token: string, workflowId: string, fireAt: number): BatchOperation[];
60
+ /** Encode an `owed` claim (attempts as given, no `claimedAt` while owed). */
61
+ export declare function encodeOwedClaim(attempts: number, token: string): Uint8Array;
62
+ /** Encode the `running` claim a holder writes to atomically claim the marker. */
63
+ export declare function encodeRunningClaim(attempts: number, token: string, claimedAt: number): Uint8Array;
64
+ /**
65
+ * Re-arm a future `wf-teardown:` timer for a non-settling drive exit (lost CAS, a
66
+ * presumed-live `running` claim, a shutdown abort, or a leave-the-marker case), so the
67
+ * claim is not stranded after the scheduler deletes the fired timer. The marker bytes
68
+ * are left untouched — only the timer is (re)written. Fenced, best-effort: a deposed
69
+ * engine that loses the fence simply yields to the new owner, whose own timer drives it.
70
+ */
71
+ export declare function rearmTeardownTimer(internals: EngineInternals, workflowId: string, token: string, delayMs: number): Promise<void>;
72
+ /**
73
+ * Clear the teardown marker for a workflow that turned out not to owe a finalizer run
74
+ * after all — a stale timer or a vanished/ineligible workflow. Conditioned on the marker
75
+ * still being byte-for-byte `expectedBytes` (the bytes this drive read), so a concurrent
76
+ * drive that already re-claimed or re-armed the marker — e.g. a same-id rerun whose fresh
77
+ * cancellation wrote a NEW claim — is never clobbered. A lost CAS (someone changed it
78
+ * first) is a benign no-op. Swallows a lost-fence error: a deposed engine simply leaves
79
+ * the marker for the new owner. No timer is re-armed: clearing the marker IS the settle.
80
+ */
81
+ export declare function clearTeardownMarker(internals: EngineInternals, workflowId: string, expectedBytes: Uint8Array): Promise<boolean>;
82
+ /**
83
+ * Atomically claim the marker: CAS `owed → running` only if it is byte-for-byte the
84
+ * `expectedBytes` we read (so concurrent reclaimers can't both win), fenced on the lease
85
+ * epoch. Returns the `running` bytes we wrote on success (needed as the settle CAS
86
+ * precondition), or `null` on a lost CAS.
87
+ */
88
+ export declare function claimTeardownMarker(internals: EngineInternals, workflowId: string, expectedBytes: Uint8Array, attempts: number, token: string): Promise<Uint8Array | null>;
89
+ /**
90
+ * Commit a settle batch conditioned on the `teardownOwed` marker still equalling the
91
+ * exact `running` bytes this drive wrote (Codex MF2). If a reclaimer overwrote the
92
+ * marker first, the CAS fails and this returns `false` WITHOUT committing — the caller
93
+ * must then skip dispatching any teardown event. A deposition still hard-halts (the
94
+ * fenced helper throws), which the drive's outer try/catch routes to a cleanup error.
95
+ */
96
+ export declare function settleOnRunningClaim(internals: EngineInternals, workflowId: string, runningBytes: Uint8Array, operations: BatchOperation[]): Promise<boolean>;
97
+ /**
98
+ * Write the durable dead-letter record and clear the teardown + finalizer-state keys,
99
+ * conditioned on the marker still being byte-for-byte `expectedBytes`. Used both at the
100
+ * retry horizon (`expectedBytes` = the `running` bytes this drive wrote) and when the
101
+ * recorded resource state vanished before any claim (`expectedBytes` = the `owed` bytes
102
+ * this drive read). Conditioning on `expectedBytes` in BOTH cases prevents a stale drive
103
+ * from dead-lettering after a concurrent drive already settled the marker — which would
104
+ * falsely report a leak after a successful teardown. Returns whether the durable write
105
+ * committed; the caller dispatches the dead-lettered event only when it did.
106
+ */
107
+ export declare function deadLetterTeardown(internals: EngineInternals, workflowId: string, workflowType: string, attempts: number, expectedBytes: Uint8Array, details: {
108
+ lastError: string;
109
+ finalizerInput: unknown;
110
+ }): Promise<boolean>;
@@ -0,0 +1,80 @@
1
+ import { KEYS } from "../../../storage/interface.js";
2
+ import { encode } from "../../codec.js";
3
+ import { buildTimerBatchOperations, parseDuration } from "../../scheduler.js";
4
+ import {
5
+ commitFencedEngineWrite,
6
+ commitFencedEngineWriteAllowingPreconditionFailure
7
+ } from "../fenced-write.js";
8
+ import { createTeardownTimerId } from "../state-utilities.js";
9
+ export const MAX_TEARDOWN_ATTEMPTS = 8;
10
+ const TEARDOWN_BACKOFF_SCHEDULE_MS = [
11
+ 60000,
12
+ 300000,
13
+ 900000,
14
+ 3600000
15
+ ], DEFAULT_FINALIZER_STALE_BUDGET_MS = 300000, TEARDOWN_STALE_MARGIN_MS = 30000;
16
+ export const TEARDOWN_SELF_HEAL_DELAY_MS = 30000;
17
+ export function teardownBackoffMs(failedAttempt) {
18
+ const index = failedAttempt - 1;
19
+ return TEARDOWN_BACKOFF_SCHEDULE_MS[index] ?? TEARDOWN_BACKOFF_SCHEDULE_MS[TEARDOWN_BACKOFF_SCHEDULE_MS.length - 1];
20
+ }
21
+ export function teardownStaleThresholdMs(finalizer) {
22
+ return (finalizer.timeout === void 0 ? DEFAULT_FINALIZER_STALE_BUDGET_MS : parseDuration(finalizer.timeout)) + TEARDOWN_STALE_MARGIN_MS;
23
+ }
24
+ export function runningClaimIsStale(internals, claim, finalizer) {
25
+ if (claim.status !== "running")
26
+ return !0;
27
+ if (claim.claimedAt === void 0)
28
+ return !0;
29
+ return internals.options.getNow() - claim.claimedAt >= teardownStaleThresholdMs(finalizer);
30
+ }
31
+ export function teardownTimerOperations(token, workflowId, fireAt) {
32
+ return buildTimerBatchOperations({
33
+ id: createTeardownTimerId(token),
34
+ workflowId,
35
+ fireAt,
36
+ kind: "teardown"
37
+ });
38
+ }
39
+ export function encodeOwedClaim(attempts, token) {
40
+ return encode({ status: "owed", attempts, token });
41
+ }
42
+ export function encodeRunningClaim(attempts, token, claimedAt) {
43
+ return encode({ status: "running", attempts, token, claimedAt });
44
+ }
45
+ export async function rearmTeardownTimer(internals, workflowId, token, delayMs) {
46
+ const fireAt = internals.options.getNow() + delayMs;
47
+ try {
48
+ await commitFencedEngineWrite(internals, teardownTimerOperations(token, workflowId, fireAt), [], () => Error("teardown self-heal re-arm lost the lease fence"));
49
+ } catch {}
50
+ }
51
+ export async function clearTeardownMarker(internals, workflowId, expectedBytes) {
52
+ try {
53
+ return await commitFencedEngineWriteAllowingPreconditionFailure(internals, [{ type: "delete", key: KEYS.teardownOwed(workflowId) }], [{ key: KEYS.teardownOwed(workflowId), expectedValue: expectedBytes }]);
54
+ } catch {
55
+ return !1;
56
+ }
57
+ }
58
+ export async function claimTeardownMarker(internals, workflowId, expectedBytes, attempts, token) {
59
+ const runningBytes = encodeRunningClaim(attempts, token, internals.options.getNow());
60
+ return await commitFencedEngineWriteAllowingPreconditionFailure(internals, [{ type: "put", key: KEYS.teardownOwed(workflowId), value: runningBytes }], [{ key: KEYS.teardownOwed(workflowId), expectedValue: expectedBytes }]) ? runningBytes : null;
61
+ }
62
+ export async function settleOnRunningClaim(internals, workflowId, runningBytes, operations) {
63
+ return commitFencedEngineWriteAllowingPreconditionFailure(internals, operations, [
64
+ { key: KEYS.teardownOwed(workflowId), expectedValue: runningBytes }
65
+ ]);
66
+ }
67
+ export async function deadLetterTeardown(internals, workflowId, workflowType, attempts, expectedBytes, details) {
68
+ const deadLetter = {
69
+ type: workflowType,
70
+ lastError: details.lastError,
71
+ attempts,
72
+ deadLetteredAt: internals.options.getNow(),
73
+ ...details.finalizerInput === void 0 ? {} : { finalizerInput: details.finalizerInput }
74
+ };
75
+ return settleOnRunningClaim(internals, workflowId, expectedBytes, [
76
+ { type: "delete", key: KEYS.teardownOwed(workflowId) },
77
+ { type: "delete", key: KEYS.finalizerState(workflowId) },
78
+ { type: "put", key: KEYS.teardownDeadLetter(workflowId), value: encode(deadLetter) }
79
+ ]);
80
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * The engine-side finalizer drive (`runWorkflowFinalizer`) for issue #446 Phase 2.
3
+ * Dispatched by the scheduler when a `wf-teardown:` timer fires, it drives a
4
+ * workflow's definition-level `finalizer` to durable completion after a
5
+ * `cancelled`/`timed-out` terminal — claiming the durable teardown marker, running
6
+ * the finalizer activity (via {@link runFinalizerActivity}), and then clearing,
7
+ * backing off, or dead-lettering based on the outcome. The byte-level claim mechanics
8
+ * (CAS, settle, re-arm, dead-letter, the stale horizon and backoff) live in
9
+ * `./finalizer-claim.ts`; this module is the orchestration that decides which to call.
10
+ *
11
+ * Concurrency model — a single durable, TIME-based claim:
12
+ * the durable `teardownOwed` marker carries a `{ status, attempts, token, claimedAt }`
13
+ * claim ({@link TeardownClaim}). A holder fenced-CAS's `owed → running` (stamping
14
+ * `claimedAt`) before running, and settle-CAS's the exact `running` bytes it wrote when
15
+ * clearing or rescheduling — so a concurrent reclaimer can never clobber a fresher
16
+ * claim. Liveness is decided purely by the clock: a `running` claim is reclaimable once
17
+ * `claimedAt` is older than {@link teardownStaleThresholdMs} (the finalizer's per-attempt
18
+ * timeout plus a margin). There is NO in-memory liveness set and NO epoch in the record;
19
+ * crash recovery is an ordinary stale-claim retry driven by the timer that survived the
20
+ * terminal batch. The tradeoff is that a finalizer running past the stale threshold may
21
+ * be re-driven concurrently, which is why workflow finalizers must be idempotent (a
22
+ * contract of the #446 design).
23
+ *
24
+ * Self-heal invariant: every exit that does NOT settle the claim (a lost claim CAS, a
25
+ * presumed-live `running` claim, a shutdown-aborted attempt, or a missing registration)
26
+ * re-arms a future `wf-teardown:` timer before returning, because the scheduler deletes
27
+ * the fired timer once this returns without throwing. A non-settling exit that forgot to
28
+ * re-arm would strand the marker with no timer to re-drive it.
29
+ *
30
+ * @module core/engine/termination/finalizer
31
+ */
32
+ import type { WorkflowState } from '../../types.ts';
33
+ import type { EngineInternals } from '../internals.ts';
34
+ export { teardownStaleThresholdMs, type TeardownDeadLetterRecord } from './finalizer-claim.ts';
35
+ /** The subset of termination callbacks the finalizer drive needs. */
36
+ export interface FinalizerDriveCallbacks {
37
+ loadWorkflowState: (workflowId: string) => Promise<WorkflowState | null>;
38
+ dispatchEvent: (event: Event) => void;
39
+ handleCleanupError: (source: string, error: unknown, workflowId?: string) => void;
40
+ }
41
+ /**
42
+ * Drive one teardown attempt for a workflow whose `wf-teardown:` timer just fired.
43
+ * Never throws: the scheduler treats a thrown timer callback as "retry on the next
44
+ * tick", which would defeat the backoff schedule, so every failure path is handled
45
+ * internally and the function returns normally (letting the scheduler delete the
46
+ * fired timer; a backoff/self-heal reschedule writes a fresh timer entry).
47
+ */
48
+ export declare function runWorkflowFinalizer(internals: EngineInternals, workflowId: string, timerId: string, callbacks: FinalizerDriveCallbacks): Promise<void>;