@lostgradient/weft 0.3.0 → 0.4.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 (508) 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 +46 -5
  23. package/dist/client/local.d.ts +4 -1
  24. package/dist/client/local.js +12 -4
  25. package/dist/client/start-body.d.ts +4 -3
  26. package/dist/core/byte-arrays.d.ts +5 -0
  27. package/dist/core/byte-arrays.js +5 -0
  28. package/dist/core/checkpoint/lifecycle.d.ts +3 -0
  29. package/dist/core/checkpoint/lifecycle.js +9 -4
  30. package/dist/core/checkpoint/serialization.js +12 -5
  31. package/dist/core/codec/extension-codec.d.ts +16 -0
  32. package/dist/core/codec/extension-codec.js +100 -6
  33. package/dist/core/context/activity-retry-state.d.ts +38 -0
  34. package/dist/core/context/activity-retry-state.js +89 -0
  35. package/dist/core/context/activity-schedule-to-close.d.ts +159 -0
  36. package/dist/core/context/activity-schedule-to-close.js +69 -0
  37. package/dist/core/context/child-workflow-pipe.d.ts +5 -5
  38. package/dist/core/context/child-workflow-pipe.js +15 -2
  39. package/dist/core/context/context-presence.d.ts +19 -0
  40. package/dist/core/context/context-presence.js +13 -0
  41. package/dist/core/context/durable-operations.d.ts +25 -0
  42. package/dist/core/context/durable-operations.js +64 -0
  43. package/dist/core/context/index.d.ts +9 -5
  44. package/dist/core/context/index.js +17 -12
  45. package/dist/core/context/internals.d.ts +20 -0
  46. package/dist/core/context/internals.js +3 -1
  47. package/dist/core/context/operation-request.d.ts +35 -0
  48. package/dist/core/context/parallel-cache-entry.d.ts +14 -5
  49. package/dist/core/context/run-operation.d.ts +6 -1
  50. package/dist/core/context/run-operation.js +41 -87
  51. package/dist/core/context/session-state.js +7 -8
  52. package/dist/core/context/speculative-child.js +2 -0
  53. package/dist/core/context/types.d.ts +15 -0
  54. package/dist/core/context/version-patching.d.ts +8 -0
  55. package/dist/core/context/version-patching.js +40 -0
  56. package/dist/core/context/workflow-logger.d.ts +98 -0
  57. package/dist/core/context/workflow-logger.js +68 -0
  58. package/dist/core/engine/activity-heartbeat-tracking.d.ts +64 -0
  59. package/dist/core/engine/activity-heartbeat-tracking.js +42 -0
  60. package/dist/core/engine/activity-per-attempt-timeout.d.ts +41 -0
  61. package/dist/core/engine/activity-per-attempt-timeout.js +36 -0
  62. package/dist/core/engine/activity-reconciliation.d.ts +1 -0
  63. package/dist/core/engine/activity-reconciliation.js +12 -1
  64. package/dist/core/engine/activity-resolution.d.ts +23 -0
  65. package/dist/core/engine/activity-resolution.js +37 -0
  66. package/dist/core/engine/aggregate.js +66 -30
  67. package/dist/core/engine/async-activity-completion.d.ts +23 -6
  68. package/dist/core/engine/async-activity-completion.js +53 -12
  69. package/dist/core/engine/attributes-tags.js +9 -4
  70. package/dist/core/engine/bulk-operations-purge.d.ts +26 -0
  71. package/dist/core/engine/bulk-operations-purge.js +38 -3
  72. package/dist/core/engine/bulk-operations-shared.d.ts +2 -0
  73. package/dist/core/engine/bulk-operations-shared.js +8 -2
  74. package/dist/core/engine/bulk-operations.d.ts +4 -1
  75. package/dist/core/engine/bulk-operations.js +235 -24
  76. package/dist/core/engine/callback-creators-bundles.d.ts +9 -0
  77. package/dist/core/engine/callback-creators-bundles.js +30 -2
  78. package/dist/core/engine/callback-creators-core.js +6 -4
  79. package/dist/core/engine/callback-creators-router.js +10 -0
  80. package/dist/core/engine/callback-creators-schedule.d.ts +2 -2
  81. package/dist/core/engine/callback-creators-schedule.js +12 -8
  82. package/dist/core/engine/candidate-read-batching.d.ts +6 -0
  83. package/dist/core/engine/candidate-read-batching.js +1 -0
  84. package/dist/core/engine/checkpoint-io.js +61 -25
  85. package/dist/core/engine/checkpoint-reads.js +3 -2
  86. package/dist/core/engine/checkpoint-replay.d.ts +20 -0
  87. package/dist/core/engine/checkpoint-replay.js +242 -0
  88. package/dist/core/engine/checkpoint-side-effects.d.ts +23 -0
  89. package/dist/core/engine/checkpoint-side-effects.js +35 -0
  90. package/dist/core/engine/child-workflow-cancellation.d.ts +10 -0
  91. package/dist/core/engine/child-workflow-cancellation.js +40 -0
  92. package/dist/core/engine/child-workflow.js +27 -4
  93. package/dist/core/engine/condition-waiters.d.ts +14 -0
  94. package/dist/core/engine/condition-waiters.js +5 -0
  95. package/dist/core/engine/construction.d.ts +3 -0
  96. package/dist/core/engine/construction.js +21 -8
  97. package/dist/core/engine/coordination-branch-executors.d.ts +70 -0
  98. package/dist/core/engine/coordination-branch-executors.js +107 -0
  99. package/dist/core/engine/deferred-consume-envelope.d.ts +59 -0
  100. package/dist/core/engine/deferred-consume-envelope.js +14 -0
  101. package/dist/core/engine/disposal.js +13 -0
  102. package/dist/core/engine/engine-create-types.d.ts +14 -4
  103. package/dist/core/engine/engine-internal-types.d.ts +26 -3
  104. package/dist/core/engine/errors.d.ts +47 -0
  105. package/dist/core/engine/errors.js +20 -0
  106. package/dist/core/engine/event-log-compaction.d.ts +8 -0
  107. package/dist/core/engine/event-log-compaction.js +20 -2
  108. package/dist/core/engine/fenced-write.d.ts +65 -0
  109. package/dist/core/engine/fenced-write.js +71 -0
  110. package/dist/core/engine/finalizer-state.d.ts +28 -0
  111. package/dist/core/engine/finalizer-state.js +16 -0
  112. package/dist/core/engine/handles.d.ts +8 -0
  113. package/dist/core/engine/index.d.ts +34 -16
  114. package/dist/core/engine/index.js +133 -8
  115. package/dist/core/engine/inline-parking.js +3 -2
  116. package/dist/core/engine/internals.d.ts +107 -3
  117. package/dist/core/engine/lease-codec.d.ts +35 -0
  118. package/dist/core/engine/lease-codec.js +32 -0
  119. package/dist/core/engine/lease-deposition.d.ts +66 -0
  120. package/dist/core/engine/lease-deposition.js +10 -0
  121. package/dist/core/engine/lease-errors.d.ts +99 -0
  122. package/dist/core/engine/lease-errors.js +30 -0
  123. package/dist/core/engine/lease-manager.d.ts +114 -0
  124. package/dist/core/engine/lease-manager.js +135 -0
  125. package/dist/core/engine/lifecycle/persist.js +10 -32
  126. package/dist/core/engine/lifecycle/recovered-services.d.ts +8 -6
  127. package/dist/core/engine/lifecycle/recovered-services.js +18 -3
  128. package/dist/core/engine/lifecycle/resume.js +16 -9
  129. package/dist/core/engine/lifecycle/shared.d.ts +8 -1
  130. package/dist/core/engine/lifecycle/start-batch.d.ts +1 -1
  131. package/dist/core/engine/lifecycle/start-batch.js +2 -1
  132. package/dist/core/engine/lifecycle/start-commit.d.ts +9 -0
  133. package/dist/core/engine/lifecycle/start-commit.js +50 -8
  134. package/dist/core/engine/lifecycle/start-or-signal-create.d.ts +58 -0
  135. package/dist/core/engine/lifecycle/start-or-signal-create.js +95 -0
  136. package/dist/core/engine/lifecycle/start-or-signal.d.ts +3 -2
  137. package/dist/core/engine/lifecycle/start-or-signal.js +11 -81
  138. package/dist/core/engine/lifecycle/start-terminal-conflict-purge.d.ts +39 -0
  139. package/dist/core/engine/lifecycle/start-terminal-conflict-purge.js +28 -0
  140. package/dist/core/engine/lifecycle/start.d.ts +4 -4
  141. package/dist/core/engine/lifecycle/start.js +17 -9
  142. package/dist/core/engine/lifecycle/transition.js +17 -5
  143. package/dist/core/engine/lifecycle.d.ts +1 -1
  144. package/dist/core/engine/list-candidate-resolution.js +2 -2
  145. package/dist/core/engine/listing.js +9 -5
  146. package/dist/core/engine/operations-activity.d.ts +4 -11
  147. package/dist/core/engine/operations-activity.js +22 -49
  148. package/dist/core/engine/operations-coordination.d.ts +10 -0
  149. package/dist/core/engine/operations-coordination.js +43 -8
  150. package/dist/core/engine/operations-router.d.ts +6 -0
  151. package/dist/core/engine/operations-router.js +2 -0
  152. package/dist/core/engine/operations-speculate.js +6 -2
  153. package/dist/core/engine/operations-stream.js +12 -2
  154. package/dist/core/engine/operations-time.d.ts +4 -2
  155. package/dist/core/engine/operations-time.js +14 -2
  156. package/dist/core/engine/operations-wait-condition.d.ts +23 -0
  157. package/dist/core/engine/operations-wait-condition.js +62 -0
  158. package/dist/core/engine/ownership-options.d.ts +23 -0
  159. package/dist/core/engine/ownership-options.js +26 -0
  160. package/dist/core/engine/payload-size-policy.d.ts +3 -0
  161. package/dist/core/engine/payload-size-policy.js +4 -0
  162. package/dist/core/engine/pending-updates.d.ts +17 -0
  163. package/dist/core/engine/pending-updates.js +33 -11
  164. package/dist/core/engine/queries.js +1 -1
  165. package/dist/core/engine/registration.d.ts +1 -0
  166. package/dist/core/engine/registration.js +18 -3
  167. package/dist/core/engine/schedule-jitter.d.ts +5 -0
  168. package/dist/core/engine/schedule-jitter.js +10 -0
  169. package/dist/core/engine/schedule-run.d.ts +17 -0
  170. package/dist/core/engine/schedule-run.js +38 -0
  171. package/dist/core/engine/schedule-timer.js +81 -17
  172. package/dist/core/engine/schedules.d.ts +7 -4
  173. package/dist/core/engine/schedules.js +37 -16
  174. package/dist/core/engine/search-attribute-records.d.ts +4 -0
  175. package/dist/core/engine/search-attribute-records.js +17 -0
  176. package/dist/core/engine/signals.d.ts +18 -2
  177. package/dist/core/engine/signals.js +42 -21
  178. package/dist/core/engine/state-utilities.d.ts +49 -2
  179. package/dist/core/engine/state-utilities.js +114 -3
  180. package/dist/core/engine/storage-io.d.ts +16 -2
  181. package/dist/core/engine/storage-io.js +26 -5
  182. package/dist/core/engine/stream-chunk-loading.d.ts +2 -0
  183. package/dist/core/engine/stream-chunk-loading.js +24 -1
  184. package/dist/core/engine/sub-operation.js +22 -3
  185. package/dist/core/engine/termination/cleanup.d.ts +3 -1
  186. package/dist/core/engine/termination/cleanup.js +25 -1
  187. package/dist/core/engine/termination/complete.js +44 -6
  188. package/dist/core/engine/termination/finalizer-activity.d.ts +53 -0
  189. package/dist/core/engine/termination/finalizer-activity.js +30 -0
  190. package/dist/core/engine/termination/finalizer-claim.d.ts +110 -0
  191. package/dist/core/engine/termination/finalizer-claim.js +80 -0
  192. package/dist/core/engine/termination/finalizer.d.ts +48 -0
  193. package/dist/core/engine/termination/finalizer.js +159 -0
  194. package/dist/core/engine/termination/suspend.d.ts +3 -1
  195. package/dist/core/engine/termination.d.ts +1 -0
  196. package/dist/core/engine/termination.js +4 -0
  197. package/dist/core/engine/updates.js +5 -25
  198. package/dist/core/engine/validation/schedule.d.ts +2 -1
  199. package/dist/core/engine/validation/schedule.js +51 -2
  200. package/dist/core/engine/validation.js +32 -5
  201. package/dist/core/engine/waiting-update-response.d.ts +8 -0
  202. package/dist/core/engine/waiting-update-response.js +22 -0
  203. package/dist/core/engine/workflow-concurrency.d.ts +10 -0
  204. package/dist/core/engine/workflow-concurrency.js +136 -0
  205. package/dist/core/engine/workflow-feed.d.ts +4 -5
  206. package/dist/core/engine/workflow-feed.js +4 -1
  207. package/dist/core/engine/workflow-indexes.d.ts +9 -0
  208. package/dist/core/engine/workflow-indexes.js +10 -0
  209. package/dist/core/engine/workflow-state-stream.js +33 -13
  210. package/dist/core/engine/workflow-visibility-queries.d.ts +2 -2
  211. package/dist/core/engine-helpers.js +1 -0
  212. package/dist/core/events/activity-events.d.ts +43 -12
  213. package/dist/core/events/activity-events.js +28 -0
  214. package/dist/core/events/attribute-events.d.ts +2 -3
  215. package/dist/core/events/event-map.d.ts +18 -12
  216. package/dist/core/events/index.d.ts +1 -0
  217. package/dist/core/events/index.js +1 -0
  218. package/dist/core/events/schedule-events.d.ts +71 -0
  219. package/dist/core/events/schedule-events.js +29 -0
  220. package/dist/core/events/signal-events.d.ts +4 -6
  221. package/dist/core/events/system-events.d.ts +29 -19
  222. package/dist/core/events/system-events.js +26 -0
  223. package/dist/core/events/update-events.d.ts +6 -8
  224. package/dist/core/events/workflow-events.d.ts +88 -23
  225. package/dist/core/events/workflow-events.js +26 -0
  226. package/dist/core/failure-categories.js +5 -17
  227. package/dist/core/fault-code.d.ts +9 -3
  228. package/dist/core/fault-code.js +1 -0
  229. package/dist/core/inline-execution-strategy.context-options.d.ts +69 -0
  230. package/dist/core/inline-execution-strategy.context-options.js +56 -0
  231. package/dist/core/inline-execution-strategy.d.ts +31 -36
  232. package/dist/core/inline-execution-strategy.js +16 -27
  233. package/dist/core/list-filter-validation.d.ts +1 -1
  234. package/dist/core/payload-size.d.ts +1 -1
  235. package/dist/core/persisted-data-incompatible-error.d.ts +9 -7
  236. package/dist/core/review/events.d.ts +6 -8
  237. package/dist/core/scheduler/scheduler-class.d.ts +10 -1
  238. package/dist/core/scheduler/scheduler-class.js +38 -11
  239. package/dist/core/scheduler/timer-batch.js +9 -1
  240. package/dist/core/scheduler/timer-sources.d.ts +1 -0
  241. package/dist/core/scheduler/timer-sources.js +11 -5
  242. package/dist/core/session-state.d.ts +0 -1
  243. package/dist/core/session-state.js +2 -2
  244. package/dist/core/start-workflow-validation.d.ts +34 -0
  245. package/dist/core/start-workflow-validation.js +19 -0
  246. package/dist/core/types/activity-verification.d.ts +67 -0
  247. package/dist/core/types/activity-verification.js +0 -0
  248. package/dist/core/types/activity.d.ts +80 -61
  249. package/dist/core/types/bulk.d.ts +50 -9
  250. package/dist/core/types/checkpoint.d.ts +44 -8
  251. package/dist/core/types/list-options.d.ts +146 -0
  252. package/dist/core/types/list-options.js +0 -0
  253. package/dist/core/types/options.d.ts +121 -165
  254. package/dist/core/types/schedules.d.ts +39 -3
  255. package/dist/core/types/services-resolution.d.ts +2 -2
  256. package/dist/core/types/workflow-builder-runtime.d.ts +12 -3
  257. package/dist/core/types/workflow-builder-runtime.js +11 -2
  258. package/dist/core/types/workflow-builder.d.ts +42 -11
  259. package/dist/core/types/workflow-concurrency.d.ts +39 -0
  260. package/dist/core/types/workflow-concurrency.js +0 -0
  261. package/dist/core/types/workflow-context.d.ts +157 -14
  262. package/dist/core/types/workflow-definition.d.ts +53 -10
  263. package/dist/core/types/workflow-function.d.ts +84 -9
  264. package/dist/core/types/workflow-log.d.ts +98 -0
  265. package/dist/core/types/workflow-log.js +0 -0
  266. package/dist/core/types/workflow-registries.d.ts +14 -3
  267. package/dist/core/types/workflow-registry.d.ts +3 -0
  268. package/dist/core/types.d.ts +4 -0
  269. package/dist/core/types.js +4 -0
  270. package/dist/core/versioning.d.ts +9 -39
  271. package/dist/core/versioning.js +2 -12
  272. package/dist/core/weft-error.d.ts +44 -1
  273. package/dist/core/weft-error.js +16 -0
  274. package/dist/core/worker-execution-strategy-options.d.ts +26 -0
  275. package/dist/core/worker-execution-strategy.js +40 -36
  276. package/dist/core/worker-inbound-message.d.ts +38 -0
  277. package/dist/core/worker-inbound-message.js +37 -0
  278. package/dist/core/worker-log-abuse-counter.d.ts +175 -0
  279. package/dist/core/worker-log-abuse-counter.js +107 -0
  280. package/dist/core/worker-message-helpers.d.ts +47 -0
  281. package/dist/core/worker-message-helpers.js +26 -0
  282. package/dist/core/worker-protocol-guard.js +1 -1
  283. package/dist/core/worker-protocol-log.d.ts +56 -0
  284. package/dist/core/worker-protocol-log.js +18 -0
  285. package/dist/core/worker-protocol.d.ts +23 -0
  286. package/dist/core/worker-protocol.js +12 -2
  287. package/dist/core/workflow-version-tuple.d.ts +3 -9
  288. package/dist/core/workflow-version-tuple.js +2 -3
  289. package/dist/diagnostics/format.js +1 -6
  290. package/dist/diagnostics/types.d.ts +4 -5
  291. package/dist/diagnostics/validate.d.ts +0 -1
  292. package/dist/diagnostics/version-check.d.ts +1 -1
  293. package/dist/diagnostics/version-check.js +4 -9
  294. package/dist/index.d.ts +12 -10
  295. package/dist/index.js +29 -3
  296. package/dist/json-schema.js +3 -3
  297. package/dist/mcp/cli.js +27 -27
  298. package/dist/mcp/dispatcher.js +1 -1
  299. package/dist/mcp/http.js +16 -6
  300. package/dist/mcp/protocol.d.ts +2 -0
  301. package/dist/mcp/protocol.js +1 -1
  302. package/dist/mcp/session.d.ts +16 -0
  303. package/dist/mcp/session.js +59 -6
  304. package/dist/mcp/tools.js +73 -6
  305. package/dist/observability/index.js +2 -2
  306. package/dist/server/asyncapi-channels.js +5 -2
  307. package/dist/server/attribute-filters.d.ts +8 -3
  308. package/dist/server/attribute-filters.js +6 -1
  309. package/dist/server/authentication/api-key.d.ts +2 -1
  310. package/dist/server/authentication/api-key.js +5 -2
  311. package/dist/server/authentication/constant-time-api-key.d.ts +15 -0
  312. package/dist/server/authentication/constant-time-api-key.js +24 -0
  313. package/dist/server/authentication/index.d.ts +1 -1
  314. package/dist/server/authentication/index.js +7 -4
  315. package/dist/server/authentication/rotating-api-key-store.d.ts +5 -3
  316. package/dist/server/authentication/rotating-api-key-store.js +19 -11
  317. package/dist/server/engine-event-feed-backend.d.ts +4 -5
  318. package/dist/server/fault-to-http.js +8 -1
  319. package/dist/server/fault-to-json-rpc.js +1 -0
  320. package/dist/server/fleet-event-feed.d.ts +31 -0
  321. package/dist/server/fleet-event-feed.js +157 -0
  322. package/dist/server/handler/index.js +1 -1
  323. package/dist/server/handler/response-helpers.js +2 -1
  324. package/dist/server/handler/route-dispatch.d.ts +6 -3
  325. package/dist/server/handler/route-dispatch.js +2 -2
  326. package/dist/server/handler.js +23 -23
  327. package/dist/server/index.d.ts +32 -2
  328. package/dist/server/index.js +26 -26
  329. package/dist/server/json-rpc-transport-helpers.d.ts +1 -0
  330. package/dist/server/json-rpc-transport-helpers.js +2 -1
  331. package/dist/server/json-rpc-websocket-runtime.d.ts +11 -2
  332. package/dist/server/json-rpc-websocket-runtime.js +1 -0
  333. package/dist/server/json-rpc-websocket-subscriptions.d.ts +10 -0
  334. package/dist/server/json-rpc-websocket-subscriptions.js +29 -0
  335. package/dist/server/json-rpc-websocket-types.d.ts +22 -0
  336. package/dist/server/json-rpc-websocket-types.js +0 -0
  337. package/dist/server/json-rpc-websocket-validation.js +20 -4
  338. package/dist/server/json-rpc-websocket.d.ts +2 -43
  339. package/dist/server/json-rpc-websocket.js +57 -74
  340. package/dist/server/openapi.d.ts +2 -1
  341. package/dist/server/openapi.js +1 -3
  342. package/dist/server/openrpc-document-schema.d.ts +78 -0
  343. package/dist/server/openrpc-document-schema.js +27 -1
  344. package/dist/server/openrpc-errors.d.ts +3 -0
  345. package/dist/server/openrpc-errors.js +2 -1
  346. package/dist/server/openrpc.js +32 -0
  347. package/dist/server/operation-catalog/index.d.ts +1 -1
  348. package/dist/server/operation-catalog/pipeline-helpers.js +1 -0
  349. package/dist/server/operation-catalog/pipeline-stages.js +26 -12
  350. package/dist/server/operation-catalog/pipeline.js +8 -1
  351. package/dist/server/operation-catalog/registry.js +13 -0
  352. package/dist/server/operation-catalog/types.d.ts +20 -9
  353. package/dist/server/operation-fault.d.ts +10 -0
  354. package/dist/server/operation-fault.js +2 -0
  355. package/dist/server/operation-registry.d.ts +12 -11
  356. package/dist/server/operation-registry.js +12 -3
  357. package/dist/server/operations/aggregate-workflows.d.ts +15 -15
  358. package/dist/server/operations/async-activity.d.ts +2 -2
  359. package/dist/server/operations/async-activity.js +12 -7
  360. package/dist/server/operations/bulk-cancel-workflows.d.ts +1 -1
  361. package/dist/server/operations/bulk-cancel-workflows.js +2 -2
  362. package/dist/server/operations/bulk-delete-workflows.d.ts +1 -1
  363. package/dist/server/operations/bulk-delete-workflows.js +2 -2
  364. package/dist/server/operations/bulk-filter-helpers.d.ts +8 -6
  365. package/dist/server/operations/bulk-filter-helpers.js +54 -24
  366. package/dist/server/operations/bulk-mutate-workflow-tags.d.ts +11 -9
  367. package/dist/server/operations/bulk-mutate-workflow-tags.js +2 -2
  368. package/dist/server/operations/bulk-operation-helpers.d.ts +2 -2
  369. package/dist/server/operations/bulk-retry-failed-workflows.d.ts +7 -0
  370. package/dist/server/operations/bulk-retry-failed-workflows.js +64 -0
  371. package/dist/server/operations/bulk-signal-workflows.d.ts +11 -9
  372. package/dist/server/operations/bulk-signal-workflows.js +2 -2
  373. package/dist/server/operations/cancel-schedule.d.ts +1 -1
  374. package/dist/server/operations/create-schedule.d.ts +3 -1
  375. package/dist/server/operations/create-schedule.js +29 -11
  376. package/dist/server/operations/fleet-events-subscription.d.ts +54 -0
  377. package/dist/server/operations/fleet-events-subscription.js +99 -0
  378. package/dist/server/operations/fork-workflow.d.ts +1 -1
  379. package/dist/server/operations/fork-workflow.js +3 -2
  380. package/dist/server/operations/get-checkpoint-at.d.ts +1 -1
  381. package/dist/server/operations/get-registry.d.ts +1 -1
  382. package/dist/server/operations/get-retention-overview.d.ts +1 -1
  383. package/dist/server/operations/get-review.d.ts +1 -1
  384. package/dist/server/operations/get-schedule.d.ts +1 -1
  385. package/dist/server/operations/get-stream-chunks.d.ts +1 -1
  386. package/dist/server/operations/get-system-metrics.d.ts +2 -2
  387. package/dist/server/operations/get-task-diagnostics.d.ts +45 -6
  388. package/dist/server/operations/get-task-diagnostics.js +101 -7
  389. package/dist/server/operations/get-update-result.d.ts +1 -1
  390. package/dist/server/operations/get-workflow-attributes.d.ts +1 -1
  391. package/dist/server/operations/get-workflow-events.d.ts +1 -1
  392. package/dist/server/operations/get-workflow-result.d.ts +1 -1
  393. package/dist/server/operations/get-workflow-timeline.d.ts +1 -1
  394. package/dist/server/operations/get-workflow.d.ts +1 -1
  395. package/dist/server/operations/list-checkpoints.d.ts +1 -1
  396. package/dist/server/operations/list-reviews.d.ts +1 -1
  397. package/dist/server/operations/list-schedules.d.ts +1 -1
  398. package/dist/server/operations/list-task-queues.d.ts +2 -2
  399. package/dist/server/operations/list-workers.d.ts +2 -2
  400. package/dist/server/operations/list-workflows.d.ts +1 -1
  401. package/dist/server/operations/operation-helpers.d.ts +16 -1
  402. package/dist/server/operations/operation-helpers.js +15 -3
  403. package/dist/server/operations/pause-schedule.d.ts +1 -1
  404. package/dist/server/operations/purge-workflows.d.ts +5 -5
  405. package/dist/server/operations/purge-workflows.js +2 -2
  406. package/dist/server/operations/query-workflow.d.ts +1 -1
  407. package/dist/server/operations/query-workflow.js +3 -2
  408. package/dist/server/operations/recover-all.d.ts +1 -1
  409. package/dist/server/operations/replay-workflow.d.ts +1 -1
  410. package/dist/server/operations/resume-schedule.d.ts +1 -1
  411. package/dist/server/operations/set-workflow-attributes.d.ts +1 -1
  412. package/dist/server/operations/set-workflow-attributes.js +6 -3
  413. package/dist/server/operations/signal-workflow.js +8 -3
  414. package/dist/server/operations/single-workflow-tag-mutation.js +13 -3
  415. package/dist/server/operations/start-or-signal-workflow.d.ts +6 -1
  416. package/dist/server/operations/start-or-signal-workflow.js +14 -24
  417. package/dist/server/operations/start-workflow-options.d.ts +6 -0
  418. package/dist/server/operations/start-workflow-rest-input.d.ts +14 -0
  419. package/dist/server/operations/start-workflow-rest-input.js +31 -0
  420. package/dist/server/operations/start-workflow.d.ts +1 -1
  421. package/dist/server/operations/start-workflow.js +8 -23
  422. package/dist/server/operations/storage.d.ts +6 -6
  423. package/dist/server/operations/storage.js +24 -14
  424. package/dist/server/operations/stream-workflow-sse.d.ts +1 -1
  425. package/dist/server/operations/submit-review-decision.d.ts +1 -1
  426. package/dist/server/operations/submit-review-decision.js +6 -3
  427. package/dist/server/operations/update-schedule.d.ts +1 -1
  428. package/dist/server/operations/update-schedule.js +7 -4
  429. package/dist/server/operations/update-workflow.d.ts +1 -1
  430. package/dist/server/operations/update-workflow.js +7 -3
  431. package/dist/server/operations/worker-drain.d.ts +8 -8
  432. package/dist/server/operations/worker-drain.js +11 -8
  433. package/dist/server/operations/workflow-events-subscription.d.ts +7 -8
  434. package/dist/server/operations/workflow-events-subscription.js +43 -8
  435. package/dist/server/rest-binding.d.ts +3 -1
  436. package/dist/server/rest-bindings.js +12 -0
  437. package/dist/server/rest-body.d.ts +10 -0
  438. package/dist/server/rest-body.js +80 -0
  439. package/dist/server/runtime/authentication-bridge.d.ts +1 -0
  440. package/dist/server/runtime/authentication-bridge.js +33 -6
  441. package/dist/server/runtime/client-visible-events.d.ts +3 -0
  442. package/dist/server/runtime/client-visible-events.js +65 -0
  443. package/dist/server/runtime/context.d.ts +7 -0
  444. package/dist/server/runtime/event-broadcasting.d.ts +6 -0
  445. package/dist/server/runtime/event-broadcasting.js +72 -38
  446. package/dist/server/runtime/retry.d.ts +1 -0
  447. package/dist/server/runtime/retry.js +14 -0
  448. package/dist/server/runtime/shutdown.d.ts +7 -6
  449. package/dist/server/runtime/shutdown.js +6 -1
  450. package/dist/server/runtime/task-polling.js +61 -20
  451. package/dist/server/runtime/task-reconciliation.js +9 -1
  452. package/dist/server/runtime/task-result-resolution.d.ts +15 -0
  453. package/dist/server/runtime/task-result-resolution.js +81 -0
  454. package/dist/server/runtime/websocket-stream.d.ts +20 -1
  455. package/dist/server/runtime/websocket-stream.js +173 -7
  456. package/dist/server/runtime/websocket-upgrade.js +22 -3
  457. package/dist/server/runtime/websocket-worker.d.ts +1 -1
  458. package/dist/server/runtime/websocket-worker.js +38 -30
  459. package/dist/server/serve-internals.d.ts +3 -1
  460. package/dist/server/serve-internals.js +18 -2
  461. package/dist/server/task-state.d.ts +30 -0
  462. package/dist/server/task-state.js +28 -0
  463. package/dist/server/workflow-event-feed.d.ts +36 -115
  464. package/dist/server/workflow-event-feed.js +92 -27
  465. package/dist/service-worker/index.js +30 -30
  466. package/dist/storage/auto.js +1 -1
  467. package/dist/storage/bun-sql.js +24 -0
  468. package/dist/storage/compressed-storage.js +1 -1
  469. package/dist/storage/default-scope.d.ts +7 -4
  470. package/dist/storage/http.js +2 -2
  471. package/dist/storage/index.d.ts +76 -4
  472. package/dist/storage/indexeddb.js +1 -1
  473. package/dist/storage/interface.d.ts +163 -0
  474. package/dist/storage/interface.js +1 -1
  475. package/dist/storage/key-prefixes.d.ts +1 -1
  476. package/dist/storage/key-prefixes.js +10 -0
  477. package/dist/storage/lmdb.d.ts +4 -3
  478. package/dist/storage/lmdb.js +1 -1
  479. package/dist/storage/memory.js +1 -1
  480. package/dist/storage/neon-batch.d.ts +30 -0
  481. package/dist/storage/neon-batch.js +30 -0
  482. package/dist/storage/neon-value-mapping.d.ts +30 -3
  483. package/dist/storage/neon-value-mapping.js +12 -0
  484. package/dist/storage/neon.d.ts +16 -0
  485. package/dist/storage/neon.js +9 -4
  486. package/dist/storage/node-sqlite.js +23 -0
  487. package/dist/storage/postgres-key-value-queries.d.ts +69 -44
  488. package/dist/storage/postgres-key-value-queries.js +62 -24
  489. package/dist/storage/resolve.js +1 -1
  490. package/dist/storage/scoped-storage.js +1 -1
  491. package/dist/storage/testing.d.ts +168 -0
  492. package/dist/storage/testing.js +2 -0
  493. package/dist/storage/turso.d.ts +8 -0
  494. package/dist/storage/turso.js +2 -2
  495. package/dist/storage/typed-storage.js +1 -1
  496. package/dist/storage/web-extension.js +1 -1
  497. package/dist/testing/index.js +28 -28
  498. package/dist/version.d.ts +1 -1
  499. package/dist/version.js +1 -1
  500. package/dist/worker/protocol.js +1 -1
  501. package/dist/workers/worker-replay-state.d.ts +32 -0
  502. package/dist/workers/worker-replay-state.js +35 -0
  503. package/dist/workers/worker-state-namespace.d.ts +21 -0
  504. package/dist/workers/worker-state-namespace.js +13 -0
  505. package/dist/workers/workflow-runner.d.ts +19 -15
  506. package/dist/workers/workflow-runner.js +72 -60
  507. package/dist/workers/workflow-worker-entry.js +5 -2
  508. package/package.json +5 -1
@@ -0,0 +1,40 @@
1
+ export const WORKFLOW_VERSION_LOCAL_PREFIX = "version:";
2
+ export function resolveWorkflowVersionPatch(checkpointLocals, changeId, minSupported, maxSupported) {
3
+ validateWorkflowVersionPatchArguments(changeId, minSupported, maxSupported);
4
+ const localKey = `${WORKFLOW_VERSION_LOCAL_PREFIX}${changeId}`, existing = checkpointLocals[localKey];
5
+ if (existing === void 0)
6
+ return {
7
+ localKey,
8
+ version: maxSupported,
9
+ newlyPinned: !0,
10
+ checkpointLocals: { ...checkpointLocals, [localKey]: maxSupported }
11
+ };
12
+ if (typeof existing !== "number" || !Number.isSafeInteger(existing))
13
+ throw Error(`Invalid checkpointed workflow version patch "${changeId}" value ${JSON.stringify(existing)}`);
14
+ const version = existing;
15
+ assertPinnedVersionSupported(changeId, version, minSupported, maxSupported);
16
+ return {
17
+ localKey,
18
+ version,
19
+ newlyPinned: !1,
20
+ checkpointLocals
21
+ };
22
+ }
23
+ function validateWorkflowVersionPatchArguments(changeId, minSupported, maxSupported) {
24
+ if (typeof changeId !== "string" || changeId.length === 0)
25
+ throw Error("ctx.getVersion() requires a non-empty changeId");
26
+ assertVersionBoundary("minSupported", minSupported);
27
+ assertVersionBoundary("maxSupported", maxSupported);
28
+ if (minSupported > maxSupported)
29
+ throw Error("ctx.getVersion() minSupported must be less than or equal to maxSupported");
30
+ }
31
+ function assertVersionBoundary(name, value) {
32
+ if (!Number.isSafeInteger(value))
33
+ throw Error(`ctx.getVersion() ${name} must be a safe integer`);
34
+ }
35
+ function assertPinnedVersionSupported(changeId, version, minSupported, maxSupported) {
36
+ if (version < minSupported)
37
+ throw Error(`Workflow version patch "${changeId}" is pinned to version ${version}, below the minimum supported version ${minSupported}`);
38
+ if (version > maxSupported)
39
+ throw Error(`Workflow version patch "${changeId}" is pinned to version ${version}, above the maximum supported version ${maxSupported}`);
40
+ }
@@ -0,0 +1,98 @@
1
+ import type { WorkflowLogger, WorkflowLogRecord } from '../types/workflow-log.ts';
2
+ import type { ContextInternals } from './internals.ts';
3
+ /**
4
+ * Dispatch one record to the matching `console` method (`debug`/`info`/`warn`/`error`).
5
+ * The single console-fallback primitive: the logger factory uses it when no sink is
6
+ * installed or a sink throws, and the worker-log host-delivery path (#529) uses it when
7
+ * the host `onLog` sink throws — so console-fallback behavior cannot drift between the
8
+ * inline and worker-forwarded paths.
9
+ */
10
+ export declare function logRecordToConsole(record: WorkflowLogRecord): void;
11
+ /**
12
+ * Inputs the logger needs at construction. The replay/clock probes (`isReplaying`,
13
+ * `now`) are evaluated fresh per emit so they track the live frontier; the identity
14
+ * fields (`workflowId`, `workflowType`) and the `sink` are fixed values.
15
+ */
16
+ export interface WorkflowLoggerBindings {
17
+ readonly workflowId: string;
18
+ readonly workflowType: string;
19
+ /**
20
+ * Whether the current execution position is a replay of an already-committed
21
+ * step. Evaluated lazily at each emit call so it reflects the live frontier.
22
+ */
23
+ isReplaying(): boolean;
24
+ /** Wall-clock millisecond timestamp for the record (never checkpointed). */
25
+ now(): number;
26
+ /**
27
+ * Optional host sink (`EngineOptions.onLog`). When provided, each non-replayed
28
+ * record is routed here INSTEAD of the console — the host owns where logs go
29
+ * (pino / winston / OpenTelemetry / etc.). When absent, records fall back to the
30
+ * matching `console` method, preserving the default behavior. `onLog` is fixed at
31
+ * engine construction (it has no public setter), so this is a captured value, not
32
+ * a per-emit resolver.
33
+ */
34
+ readonly sink?: (record: WorkflowLogRecord) => void;
35
+ }
36
+ /**
37
+ * Create a {@link WorkflowLogger} from the given bindings. Each method suppresses
38
+ * emission when `bindings.isReplaying()` is true (so a recovered run does not
39
+ * re-emit logs from the replayed prefix). A non-replayed record is routed to the
40
+ * host sink (`bindings.sink`) when one is installed, and otherwise to the matching
41
+ * `console` method — so a host that wires `EngineOptions.onLog` takes full control
42
+ * of log routing without duplicate console noise, while the default stays console.
43
+ *
44
+ * A logger must never be able to crash the thing it is logging: if the host sink
45
+ * throws (a serialization error, a transport failure, a bug in the callback — all
46
+ * realistic for the pino / winston / OpenTelemetry integrations this targets), the
47
+ * throw is swallowed and the record falls back to `console` so the workflow run is
48
+ * not marked failed by a logging error.
49
+ */
50
+ export declare function createWorkflowLogger(bindings: WorkflowLoggerBindings): WorkflowLogger;
51
+ /**
52
+ * Build the inline `ctx.log` logger for a {@link Context}. The replay probe reads
53
+ * the RAW nullable `internals.accumulatedResults` field (not the allocating
54
+ * `ctx.accumulatedResults` getter) and the live `internals.stepIndex` without
55
+ * incrementing it — `ctx.log` consumes no durable position, the same step-neutral
56
+ * peek `waitForSignal` makes. `getInternals` is read per emit so the probe tracks
57
+ * the frontier as durable ops advance `stepIndex`. The `sink` is captured by value:
58
+ * `EngineOptions.onLog` is fixed at engine construction, so it never changes for the
59
+ * life of the context.
60
+ */
61
+ export declare function createInlineWorkflowLogger(workflowId: string, workflowType: string, getInternals: () => Pick<ContextInternals, 'accumulatedResults' | 'stepIndex' | 'getNow'>, sink?: (record: WorkflowLogRecord) => void): WorkflowLogger;
62
+ /**
63
+ * The slice of worker replay state the worker logger's replay probe reads. A step
64
+ * being replayed is cached in `accumulatedResults` (it succeeded) OR in
65
+ * `failedOutcomes` (it failed and the failure is replayed) — the logger must check
66
+ * both, mirroring the runner's own `hasCachedWorkerOutcome`, or a log at a
67
+ * replayed *failure* position would re-emit on recovery.
68
+ */
69
+ export interface WorkerLoggerReplayState {
70
+ readonly accumulatedResults: ReadonlyMap<number, unknown>;
71
+ readonly failedOutcomes: ReadonlyMap<number, unknown>;
72
+ readonly nextStepIndex: number;
73
+ }
74
+ /**
75
+ * Build the worker-side `ctx.log` logger. Mirrors {@link createInlineWorkflowLogger}
76
+ * through the shared factory; only the replay probe differs. `nextStepIndex` points
77
+ * at the step the worker generator is about to run, so a cached outcome at that
78
+ * index (success in `accumulatedResults` or failure in `failedOutcomes`) means the
79
+ * step is replaying and its preceding log is suppressed; an uncached index is the
80
+ * live frontier — the same per-position check the inline path makes (and the same
81
+ * union the runner's own replay short-circuit uses). The state is read through
82
+ * `getReplayState` (not captured by value) because the worker registers its replay
83
+ * state *after* the context is built, so the closure must observe the live state at
84
+ * emit time. Worker records use wall-clock `Date.now()` (the worker has no engine
85
+ * clock); the timestamp is observability metadata only, never checkpointed.
86
+ *
87
+ * When the engine host installs an `EngineOptions.onLog` sink, the run/resume message
88
+ * reports `hostHasLogSink: true` and the worker supplies a `forwardToHost` callback
89
+ * here (#529): each non-replayed record is posted back to the host as a `log`
90
+ * protocol message INSTEAD of the worker console, mirroring the inline sink. The
91
+ * callback runs through the shared factory's `sink` slot, so its existing
92
+ * throw-then-console fallback applies — if forwarding is impossible (an oversized or
93
+ * non-cloneable record makes `postMessage` throw), the record falls back to the
94
+ * worker console rather than failing the run. When no host sink exists, `forwardToHost`
95
+ * is omitted and the worker logs to its own console, preserving the default and never
96
+ * losing a log to a no-op host callback.
97
+ */
98
+ export declare function createWorkerWorkflowLogger(workflowId: string, workflowType: string, getReplayState: () => WorkerLoggerReplayState | undefined, forwardToHost?: (record: WorkflowLogRecord) => void): WorkflowLogger;
@@ -0,0 +1,68 @@
1
+ const CONSOLE_METHOD = {
2
+ debug: "debug",
3
+ info: "info",
4
+ warn: "warn",
5
+ error: "error"
6
+ };
7
+ export function logRecordToConsole(record) {
8
+ console[CONSOLE_METHOD[record.level]](record);
9
+ }
10
+ function buildLogRecord(bindings, level, message, attributes) {
11
+ return {
12
+ level,
13
+ message,
14
+ workflowId: bindings.workflowId,
15
+ workflowType: bindings.workflowType,
16
+ timestamp: bindings.now(),
17
+ ...attributes !== void 0 && { attributes }
18
+ };
19
+ }
20
+ export function createWorkflowLogger(bindings) {
21
+ const emit = (level, message, attributes) => {
22
+ if (bindings.isReplaying())
23
+ return;
24
+ const record = buildLogRecord(bindings, level, message, attributes);
25
+ if (bindings.sink !== void 0) {
26
+ try {
27
+ bindings.sink(record);
28
+ } catch {
29
+ logRecordToConsole(record);
30
+ }
31
+ return;
32
+ }
33
+ logRecordToConsole(record);
34
+ };
35
+ return {
36
+ debug: (message, attributes) => emit("debug", message, attributes),
37
+ info: (message, attributes) => emit("info", message, attributes),
38
+ warn: (message, attributes) => emit("warn", message, attributes),
39
+ error: (message, attributes) => emit("error", message, attributes)
40
+ };
41
+ }
42
+ export function createInlineWorkflowLogger(workflowId, workflowType, getInternals, sink) {
43
+ return createWorkflowLogger({
44
+ workflowId,
45
+ workflowType,
46
+ isReplaying: () => {
47
+ const internals = getInternals();
48
+ return internals.accumulatedResults?.has(internals.stepIndex) ?? !1;
49
+ },
50
+ now: () => getInternals().getNow(),
51
+ ...sink !== void 0 && { sink }
52
+ });
53
+ }
54
+ export function createWorkerWorkflowLogger(workflowId, workflowType, getReplayState, forwardToHost) {
55
+ return createWorkflowLogger({
56
+ workflowId,
57
+ workflowType,
58
+ isReplaying: () => {
59
+ const replayState = getReplayState();
60
+ if (replayState === void 0)
61
+ return !1;
62
+ const step = replayState.nextStepIndex;
63
+ return replayState.accumulatedResults.has(step) || replayState.failedOutcomes.has(step);
64
+ },
65
+ now: () => Date.now(),
66
+ ...forwardToHost !== void 0 && { sink: forwardToHost }
67
+ });
68
+ }
@@ -0,0 +1,64 @@
1
+ import type { ActivityContext } from '../types.ts';
2
+ import type { EngineInternals } from './internals.ts';
3
+ /**
4
+ * Per-step heartbeat tracking for {@link ActivityContext.lastHeartbeatDetails}.
5
+ *
6
+ * The store is keyed `workflowId -> step` (not `workflowId` alone) so a retry of
7
+ * an activity step reads the heartbeat ITS prior attempt recorded — and so a
8
+ * later step's first attempt never inherits an earlier step's heartbeat, and
9
+ * concurrent `ctx.all` activities never clobber one another. The step is stable
10
+ * across retry attempts (assigned once at `stepIndex++`). Held only in engine
11
+ * memory and cleared by workflowId (the outer key) on terminal cleanup and purge.
12
+ */
13
+ /** Record the heartbeat the current attempt of a step sent. */
14
+ export declare function recordLastHeartbeatForStep(internals: EngineInternals, workflowId: string, step: number, details: unknown): void;
15
+ /** Read the heartbeat a prior attempt of this step recorded, or `undefined`. */
16
+ export declare function readLastHeartbeatForStep(internals: EngineInternals, workflowId: string, step: number): unknown;
17
+ /**
18
+ * Drop the heartbeat tracked for a single step once that step has completed
19
+ * successfully — after inline verify, and (on the idempotency path) after the
20
+ * reconciliation write, so a verify-rejection retry still reads its prior
21
+ * attempt's heartbeat. The plain path has no reconciliation write; both paths
22
+ * call this only at their successful return. Removes the inner-map entry and
23
+ * drops the outer workflow entry when its last step clears, so a long-lived
24
+ * workflow doesn't accumulate stale per-step heartbeats. Clearing late is
25
+ * harmless (bounded by terminal cleanup); clearing early would strip the
26
+ * resumable-batch heartbeat a retry depends on, so this is only ever called from
27
+ * the non-speculative success path.
28
+ */
29
+ export declare function clearLastHeartbeatForStep(internals: EngineInternals, workflowId: string, step: number): void;
30
+ /**
31
+ * #493: in development mode, emit a COARSE warning when an inline activity RETRY
32
+ * (`attempt > 1`) starts with no `lastHeartbeatDetails` — the closest runtime
33
+ * proxy for the resumable-batch footgun. We cannot distinguish "the prior attempt
34
+ * never heartbeated" (benign) from "the heartbeat was discarded by a process
35
+ * restart" (the dangerous case): the distinguishing fact is the wiped in-memory
36
+ * state, gone by definition. So the message names BOTH possibilities and never
37
+ * claims a restart happened. The gates (development, inline, attempt, missing
38
+ * heartbeat) are read straight off the code below; two facts are NOT derivable
39
+ * from it:
40
+ *
41
+ * - It fires on the speculative path too. A speculative `attempt > 1` that later
42
+ * rolls back still ran twice and still lost any resume payload, so the footgun
43
+ * is real regardless — letting it warn is the deliberate, honest choice.
44
+ * - It pairs with {@link clearLastHeartbeatForStep} without interference: the
45
+ * clear fires only on SUCCESS (a step that never retries) and this reads
46
+ * `undefined` only on a RETRY, and a cleared step is a completed step that by
47
+ * definition will not be retried.
48
+ *
49
+ * The inline gate keys on `!activityWorkerDispatcher` because dispatch is
50
+ * engine-wide today; the heartbeat cache is only ever written on the inline path,
51
+ * so whenever a dispatcher exists the cache is structurally empty and the gate is
52
+ * required to suppress a false warning on every worker retry. A future per-activity
53
+ * routing model would need this gate to key on the resolved per-dispatch mode
54
+ * instead.
55
+ */
56
+ export declare function warnIfRetryMissingHeartbeat(internals: EngineInternals, workflowId: string, step: number, attempt: number): void;
57
+ /**
58
+ * Build the {@link ActivityContext} handed to an inline activity function. The
59
+ * signal comes from the per-workflow AbortController (so workflow cancellation
60
+ * aborts it); `lastHeartbeatDetails` and `heartbeat` are wired to the per-step
61
+ * tracking above; `completeAsync` is supplied by the caller (it owns the
62
+ * async-completion token machinery).
63
+ */
64
+ export declare function buildActivityContext(internals: EngineInternals, workflowId: string, step: number, signal: AbortSignal, completeAsync: () => never): ActivityContext;
@@ -0,0 +1,42 @@
1
+ import { DevelopmentWarningEvent } from "../events.js";
2
+ export function recordLastHeartbeatForStep(internals, workflowId, step, details) {
3
+ let byStep = internals.lastHeartbeatDetailsByStep.get(workflowId);
4
+ if (byStep === void 0) {
5
+ byStep = new Map;
6
+ internals.lastHeartbeatDetailsByStep.set(workflowId, byStep);
7
+ }
8
+ byStep.set(step, details);
9
+ }
10
+ export function readLastHeartbeatForStep(internals, workflowId, step) {
11
+ return internals.lastHeartbeatDetailsByStep.get(workflowId)?.get(step);
12
+ }
13
+ export function clearLastHeartbeatForStep(internals, workflowId, step) {
14
+ const byStep = internals.lastHeartbeatDetailsByStep.get(workflowId);
15
+ if (byStep === void 0)
16
+ return;
17
+ byStep.delete(step);
18
+ if (byStep.size === 0)
19
+ internals.lastHeartbeatDetailsByStep.delete(workflowId);
20
+ }
21
+ export function warnIfRetryMissingHeartbeat(internals, workflowId, step, attempt) {
22
+ if (!internals.options.development)
23
+ return;
24
+ if (internals.activityWorkerDispatcher)
25
+ return;
26
+ if (attempt <= 1)
27
+ return;
28
+ if (readLastHeartbeatForStep(internals, workflowId, step) !== void 0)
29
+ return;
30
+ internals.engine.dispatchEvent(new DevelopmentWarningEvent(workflowId, `Activity retry (attempt ${attempt}) at step ${step} has no lastHeartbeatDetails. Either the previous attempt never recorded heartbeat details (it never called heartbeat(), or called it with no details), or the engine process restarted and discarded the in-memory heartbeat (it is not durable). The resumable-batch pattern only resumes across in-process retries; design the activity to restart cleanly when lastHeartbeatDetails is undefined.`, [`step.${step}.lastHeartbeatDetails`]));
31
+ }
32
+ export function buildActivityContext(internals, workflowId, step, signal, completeAsync) {
33
+ return {
34
+ signal,
35
+ lastHeartbeatDetails: readLastHeartbeatForStep(internals, workflowId, step),
36
+ heartbeat: (details) => {
37
+ internals.heartbeatDetails.set(workflowId, details);
38
+ recordLastHeartbeatForStep(internals, workflowId, step, details);
39
+ },
40
+ completeAsync
41
+ };
42
+ }
@@ -0,0 +1,41 @@
1
+ import type { ContextOperationRequest } from '../context.ts';
2
+ import type { EngineInternals } from './internals.ts';
3
+ type ActivityOperation = Extract<ContextOperationRequest, {
4
+ type: 'activity';
5
+ }>;
6
+ /**
7
+ * Resolve the per-attempt `timeout` setup for an activity attempt (#494).
8
+ *
9
+ * The cap is INLINE-only: worker-mode per-attempt bounds are governed by
10
+ * `visibilityTimeout`, and racing the engine's await against a deadline while a
11
+ * remote worker keeps running would orphan its result and risk double-execution on
12
+ * the next visibility-timeout re-dispatch. When a cap is configured, a fresh
13
+ * per-attempt `AbortController` drives cooperative cancellation; its signal is
14
+ * composited with the workflow-wide signal so the activity's `ctx.signal` aborts on
15
+ * EITHER workflow cancellation OR a per-attempt timeout — without the timeout
16
+ * reaching back to cancel the whole workflow (which would also poison the next
17
+ * retry's signal).
18
+ */
19
+ export declare function resolvePerAttemptTimeout(internals: EngineInternals, workflowId: string, operation: ActivityOperation): {
20
+ perAttemptTimeoutMs: number | undefined;
21
+ attemptAbortController: AbortController | undefined;
22
+ activitySignal: AbortSignal;
23
+ };
24
+ /**
25
+ * Bound a single inline activity attempt by its per-attempt `timeout` (#494).
26
+ *
27
+ * When `timeoutMs` is set and the attempt does not settle first, the returned
28
+ * promise rejects with {@link ActivityPerAttemptTimeoutError} and the per-attempt
29
+ * `AbortController` is aborted with that same error — so the activity's composite
30
+ * `ctx.signal` flips, letting a cooperating activity stop promptly. Weft cannot
31
+ * forcibly preempt the activity function: a non-cooperating activity keeps running
32
+ * in the background until it returns; only the workflow stops awaiting it. The
33
+ * abandoned invocation's eventual settlement is swallowed so it never surfaces as
34
+ * an unhandled rejection after the race has moved on. The timed-out rejection
35
+ * flows through the normal retry path, so a retry policy gets a fresh attempt with
36
+ * a fresh cap (and a fresh per-attempt controller).
37
+ *
38
+ * Returns the invocation unchanged (no timer armed) when no cap is configured.
39
+ */
40
+ export declare function withPerAttemptTimeout(invocation: unknown, timeoutMs: number | undefined, activityName: string, attempt: number, attemptAbortController: AbortController | undefined): Promise<unknown>;
41
+ export {};
@@ -0,0 +1,36 @@
1
+ import {
2
+ ActivityPerAttemptTimeoutError,
3
+ parsePerAttemptTimeoutMs
4
+ } from "../context/activity-schedule-to-close.js";
5
+ export function resolvePerAttemptTimeout(internals, workflowId, operation) {
6
+ const workflowAbortController = internals.inlineStrategy?.getAbortController(workflowId), perAttemptTimeoutMs = internals.activityWorkerDispatcher ? void 0 : parsePerAttemptTimeoutMs(operation.options?.timeout), attemptAbortController = perAttemptTimeoutMs === void 0 ? void 0 : new AbortController, activitySignal = composeActivitySignal(workflowAbortController?.signal, attemptAbortController?.signal);
7
+ return { perAttemptTimeoutMs, attemptAbortController, activitySignal };
8
+ }
9
+ function composeActivitySignal(workflowSignal, attemptSignal) {
10
+ const signals = [workflowSignal, attemptSignal].filter((signal) => signal !== void 0), [first] = signals;
11
+ if (first === void 0)
12
+ return new AbortController().signal;
13
+ if (signals.length === 1)
14
+ return first;
15
+ return AbortSignal.any(signals);
16
+ }
17
+ export async function withPerAttemptTimeout(invocation, timeoutMs, activityName, attempt, attemptAbortController) {
18
+ if (timeoutMs === void 0)
19
+ return invocation;
20
+ const activityPromise = Promise.resolve(invocation);
21
+ activityPromise.catch(() => {});
22
+ let timer;
23
+ const deadline = new Promise((_resolve, reject) => {
24
+ timer = setTimeout(() => {
25
+ const error = new ActivityPerAttemptTimeoutError(activityName, attempt, timeoutMs);
26
+ reject(error);
27
+ attemptAbortController?.abort(error);
28
+ }, timeoutMs);
29
+ });
30
+ try {
31
+ return await Promise.race([activityPromise, deadline]);
32
+ } finally {
33
+ if (timer !== void 0)
34
+ clearTimeout(timer);
35
+ }
36
+ }
@@ -101,6 +101,7 @@ export declare function resolveStartedActivityReconciliationRecord(internals: En
101
101
  completedResult: unknown;
102
102
  }>;
103
103
  export declare function writeActivityReconciliationTransition(storage: Storage, reference: ActivityReconciliationReference, expectedRecord: ActivityReconciliationRecord, nextRecord: ActivityReconciliationRecord): Promise<void>;
104
+ export declare function stageActivityReconciliationTransitionWithAtomicWorkflowCommit(internals: EngineInternals, workflowId: string, reference: ActivityReconciliationReference, expectedRecord: ActivityReconciliationRecord, nextRecord: ActivityReconciliationRecord): void;
104
105
  export declare function normalizePreDispatchVerificationResult(result: ActivityVerificationResult): 'not-completed' | 'completed-result-unavailable' | 'indeterminate' | {
105
106
  result: unknown;
106
107
  };
@@ -6,6 +6,7 @@ import {
6
6
  import { decode, encode } from "../codec.js";
7
7
  import { assertPayloadWithinLimit } from "../payload-size.js";
8
8
  import { WeftError } from "../weft-error.js";
9
+ import { stageAtomicWorkflowCommitSideEffects } from "./checkpoint-side-effects.js";
9
10
 
10
11
  export class ActivityReconciliationCapabilityError extends WeftError {
11
12
  constructor() {
@@ -95,9 +96,19 @@ export async function resolveStartedActivityReconciliationRecord(internals, work
95
96
  return { completedResult: normalized.result };
96
97
  }
97
98
  export async function writeActivityReconciliationTransition(storage, reference, expectedRecord, nextRecord) {
98
- if (!await storageConditionalBatch(storage, [{ key: reference.key, expectedValue: encode(expectedRecord) }], [{ type: "put", key: reference.key, value: encode(nextRecord) }]))
99
+ const sideEffects = buildActivityReconciliationTransitionSideEffects(reference, expectedRecord, nextRecord);
100
+ if (!await storageConditionalBatch(storage, sideEffects.conditions, sideEffects.operations))
99
101
  throw new ActivityReconciliationConflictError("Activity reconciliation completion lost compare-and-set ownership.");
100
102
  }
103
+ export function stageActivityReconciliationTransitionWithAtomicWorkflowCommit(internals, workflowId, reference, expectedRecord, nextRecord) {
104
+ stageAtomicWorkflowCommitSideEffects(internals, workflowId, buildActivityReconciliationTransitionSideEffects(reference, expectedRecord, nextRecord));
105
+ }
106
+ function buildActivityReconciliationTransitionSideEffects(reference, expectedRecord, nextRecord) {
107
+ return {
108
+ conditions: [{ key: reference.key, expectedValue: encode(expectedRecord) }],
109
+ operations: [{ type: "put", key: reference.key, value: encode(nextRecord) }]
110
+ };
111
+ }
101
112
  export function normalizePreDispatchVerificationResult(result) {
102
113
  if (result === "not-completed")
103
114
  return "not-completed";
@@ -0,0 +1,23 @@
1
+ import type { ContextOperationRequest } from '../context.ts';
2
+ import type { EngineInternals } from './internals.ts';
3
+ import type { ActivityFunctionWithMetadata } from './operations-activity.ts';
4
+ type ActivityOperation = Extract<ContextOperationRequest, {
5
+ type: 'activity';
6
+ }>;
7
+ /**
8
+ * Resolve the activity callable along with its attached metadata (compensation,
9
+ * verification). Returns `undefined` when no registry and no `operation.fn`
10
+ * resolve the name — the metadata path treats a miss as advisory rather than
11
+ * fatal.
12
+ */
13
+ export declare function getActivityFunctionWithMetadata(internals: EngineInternals, workflowId: string, operation: ActivityOperation): ActivityFunctionWithMetadata | undefined;
14
+ /**
15
+ * Resolve the activity function for a given operation. Uses the same
16
+ * per-workflow-first-then-global ordering as `getActivityFunctionWithMetadata`.
17
+ * For inline-mode callers that pass an `operation.fn` directly, the registries
18
+ * are still consulted first so a workflow's locally-scoped activity wins over
19
+ * the bare callable. Throws `ActivityResolutionError` when neither path
20
+ * resolves.
21
+ */
22
+ export declare function resolveActivityFunction(internals: EngineInternals, workflowId: string, operation: ActivityOperation): (...arguments_: unknown[]) => unknown;
23
+ export {};
@@ -0,0 +1,37 @@
1
+ import { ActivityResolutionError } from "./errors.js";
2
+ function resolveActivityViaRegistries(internals, workflowId, activityName) {
3
+ const workflowType = internals.workflowTypeByWorkflowId.get(workflowId);
4
+ if (workflowType !== void 0) {
5
+ const perWorkflow = internals.activityRegistriesByWorkflow.get(workflowType);
6
+ if (perWorkflow !== void 0) {
7
+ const perWorkflowFn = perWorkflow.resolve(activityName);
8
+ if (perWorkflowFn)
9
+ return { fn: perWorkflowFn, workflowType };
10
+ }
11
+ const globalFn = internals.activityRegistry.resolve(activityName);
12
+ if (globalFn)
13
+ return { fn: globalFn, workflowType };
14
+ return;
15
+ }
16
+ const globalFn = internals.activityRegistry.resolve(activityName);
17
+ if (globalFn)
18
+ return { fn: globalFn, workflowType: "<unknown>" };
19
+ return;
20
+ }
21
+ export function getActivityFunctionWithMetadata(internals, workflowId, operation) {
22
+ const resolved = resolveActivityViaRegistries(internals, workflowId, operation.activityName);
23
+ if (resolved)
24
+ return resolved.fn;
25
+ if (typeof operation.fn === "function")
26
+ return operation.fn;
27
+ return;
28
+ }
29
+ export function resolveActivityFunction(internals, workflowId, operation) {
30
+ const resolved = resolveActivityViaRegistries(internals, workflowId, operation.activityName);
31
+ if (resolved)
32
+ return resolved.fn;
33
+ if (operation.fn)
34
+ return operation.fn;
35
+ const workflowType = internals.workflowTypeByWorkflowId.get(workflowId) ?? "<unknown>";
36
+ throw new ActivityResolutionError(workflowType, operation.activityName);
37
+ }
@@ -5,12 +5,16 @@ import {
5
5
  MAX_AGGREGATE_DISTINCT_KEYS,
6
6
  normalizeAggregateOptions
7
7
  } from "../aggregate-validation.js";
8
- import { decode } from "../codec.js";
9
8
  import { normalizeListFilter } from "../list-filter-validation.js";
10
9
  import { WeftError } from "../weft-error.js";
11
10
  import { normalizeWorkflowTags } from "../workflow-tags.js";
11
+ import { CONSTRAINED_ID_CHUNK_SIZE } from "./candidate-read-batching.js";
12
12
  import { resolveListCandidateIds } from "./list-candidate-resolution.js";
13
- import { matchesListFilter } from "./state-utilities.js";
13
+ import {
14
+ readSearchAttributesForFilter,
15
+ readSearchAttributesForStates
16
+ } from "./search-attribute-records.js";
17
+ import { decodeSearchAttributeRecord, matchesListFilter } from "./state-utilities.js";
14
18
  import { decodeWorkflowState } from "./validation.js";
15
19
  import { MAX_LIST_SCAN_ROWS, WorkflowListScanCapExceededError } from "./workflow-indexes.js";
16
20
  import { isTopLevelWorkflowStateKey } from "./workflow-state-stream.js";
@@ -27,19 +31,6 @@ const ATTRIBUTE_VALUE_TO_KEY = (value) => {
27
31
  return value.join(",");
28
32
  return String(value);
29
33
  };
30
- async function resolveDimensionKey(internals, state, groupBy) {
31
- if (groupBy === "status")
32
- return state.status;
33
- if (groupBy === "type")
34
- return state.type;
35
- if (groupBy === "failureCategory")
36
- return state.failureCategory ?? null;
37
- const attributeBytes = await internals.storage.get(KEYS.attribute(state.id));
38
- if (!attributeBytes)
39
- return null;
40
- const attributes = decode(attributeBytes);
41
- return ATTRIBUTE_VALUE_TO_KEY(attributes[groupBy.attribute]);
42
- }
43
34
 
44
35
  export class UnknownAggregateAttributeError extends WeftError {
45
36
  attribute;
@@ -72,8 +63,8 @@ function validateAggregateInputs(internals, filter, options, executionOptions) {
72
63
  distinctKeyCap: executionOptions.distinctKeyCap ?? MAX_AGGREGATE_DISTINCT_KEYS
73
64
  };
74
65
  }
75
- async function accumulateAggregateState(internals, state, groupBy, distinctKeyCap, accumulator) {
76
- const key = await resolveDimensionKey(internals, state, groupBy), current = accumulator.counts.get(key);
66
+ function accumulateAggregateKey(key, distinctKeyCap, accumulator) {
67
+ const current = accumulator.counts.get(key);
77
68
  if (current === void 0) {
78
69
  if (accumulator.counts.size >= distinctKeyCap)
79
70
  throw new AggregateDistinctKeyCapExceededError(distinctKeyCap);
@@ -82,32 +73,77 @@ async function accumulateAggregateState(internals, state, groupBy, distinctKeyCa
82
73
  accumulator.counts.set(key, current + 1);
83
74
  accumulator.total += 1;
84
75
  }
76
+ async function resolveDimensionKeys(internals, states, groupBy, searchAttributesByWorkflowId = new Map) {
77
+ if (groupBy === "status")
78
+ return states.map((state) => state.status);
79
+ if (groupBy === "type")
80
+ return states.map((state) => state.type);
81
+ if (groupBy === "failureCategory")
82
+ return states.map((state) => state.failureCategory ?? null);
83
+ return resolveAttributeDimensionKeys(internals, states, groupBy, searchAttributesByWorkflowId);
84
+ }
85
+ async function resolveAttributeDimensionKeys(internals, states, groupBy, searchAttributesByWorkflowId) {
86
+ const keys = [];
87
+ for (let start = 0;start < states.length; start += CONSTRAINED_ID_CHUNK_SIZE) {
88
+ const stateChunk = states.slice(start, start + CONSTRAINED_ID_CHUNK_SIZE), statesNeedingReads = stateChunk.filter((state) => !searchAttributesByWorkflowId.has(state.id)), attributeBytesByWorkflowId = new Map;
89
+ await Promise.all(statesNeedingReads.map(async (state) => {
90
+ attributeBytesByWorkflowId.set(state.id, await internals.storage.get(KEYS.attribute(state.id)));
91
+ }));
92
+ for (const state of stateChunk) {
93
+ const attributes = searchAttributesByWorkflowId.has(state.id) ? searchAttributesByWorkflowId.get(state.id) ?? null : decodeSearchAttributeRecord(attributeBytesByWorkflowId.get(state.id) ?? null);
94
+ if (attributes === null) {
95
+ keys.push(null);
96
+ continue;
97
+ }
98
+ keys.push(ATTRIBUTE_VALUE_TO_KEY(attributes[groupBy.attribute]));
99
+ }
100
+ }
101
+ return keys;
102
+ }
103
+ async function accumulateAggregateStates(internals, states, groupBy, distinctKeyCap, accumulator, searchAttributesByWorkflowId) {
104
+ const dimensionKeys = await resolveDimensionKeys(internals, states, groupBy, searchAttributesByWorkflowId);
105
+ for (const key of dimensionKeys)
106
+ accumulateAggregateKey(key, distinctKeyCap, accumulator);
107
+ }
85
108
  async function accumulateFromConstrainedIds(internals, constrainedIds, normalizedFilter, normalizedTagFilters, groupBy, distinctKeyCap, accumulator) {
86
- if (constrainedIds.size > MAX_LIST_SCAN_ROWS)
109
+ const orderedIds = [...constrainedIds];
110
+ if (orderedIds.length > MAX_LIST_SCAN_ROWS)
87
111
  throw new WorkflowListScanCapExceededError(MAX_LIST_SCAN_ROWS);
88
- for (const workflowId of constrainedIds) {
89
- const stateBytes = await internals.storage.get(KEYS.workflow(workflowId));
90
- if (!stateBytes)
91
- continue;
92
- const state = decodeWorkflowState(stateBytes);
93
- if (!matchesListFilter(state, normalizedFilter, constrainedIds, normalizedTagFilters))
94
- continue;
95
- await accumulateAggregateState(internals, state, groupBy, distinctKeyCap, accumulator);
112
+ for (let start = 0;start < orderedIds.length; start += CONSTRAINED_ID_CHUNK_SIZE) {
113
+ const idChunk = orderedIds.slice(start, start + CONSTRAINED_ID_CHUNK_SIZE), stateBytesChunk = await Promise.all(idChunk.map((workflowId) => internals.storage.get(KEYS.workflow(workflowId)))), searchAttributesByWorkflowId = await readSearchAttributesForStates(internals, stateBytesChunk, normalizedFilter), matchingStates = [];
114
+ for (const stateBytes of stateBytesChunk) {
115
+ if (!stateBytes)
116
+ continue;
117
+ const state = decodeWorkflowState(stateBytes);
118
+ if (!matchesListFilter(state, normalizedFilter, constrainedIds, normalizedTagFilters, searchAttributesByWorkflowId.get(state.id) ?? null))
119
+ continue;
120
+ matchingStates.push(state);
121
+ }
122
+ await accumulateAggregateStates(internals, matchingStates, groupBy, distinctKeyCap, accumulator, searchAttributesByWorkflowId);
96
123
  }
97
124
  }
98
125
  async function accumulateFromFullScan(internals, normalizedFilter, normalizedTagFilters, groupBy, distinctKeyCap, accumulator) {
99
- let scanned = 0;
126
+ let scanned = 0, matchingStates = [], matchingSearchAttributesByWorkflowId = new Map;
100
127
  for await (const [storageKey, value] of internals.storage.scan("wf:")) {
101
128
  if (!isTopLevelWorkflowStateKey(storageKey))
102
129
  continue;
103
130
  scanned += 1;
104
131
  if (scanned > MAX_LIST_SCAN_ROWS)
105
132
  throw new WorkflowListScanCapExceededError(MAX_LIST_SCAN_ROWS);
106
- const state = decodeWorkflowState(value);
107
- if (!matchesListFilter(state, normalizedFilter, null, normalizedTagFilters))
133
+ const state = decodeWorkflowState(value), searchAttributes = await readSearchAttributesForFilter(internals, state.id, normalizedFilter);
134
+ if (!matchesListFilter(state, normalizedFilter, null, normalizedTagFilters, searchAttributes))
108
135
  continue;
109
- await accumulateAggregateState(internals, state, groupBy, distinctKeyCap, accumulator);
136
+ matchingStates.push(state);
137
+ if (searchAttributes !== null)
138
+ matchingSearchAttributesByWorkflowId.set(state.id, searchAttributes);
139
+ if (matchingStates.length === CONSTRAINED_ID_CHUNK_SIZE) {
140
+ await accumulateAggregateStates(internals, matchingStates, groupBy, distinctKeyCap, accumulator, matchingSearchAttributesByWorkflowId);
141
+ matchingStates = [];
142
+ matchingSearchAttributesByWorkflowId = new Map;
143
+ }
110
144
  }
145
+ if (matchingStates.length > 0)
146
+ await accumulateAggregateStates(internals, matchingStates, groupBy, distinctKeyCap, accumulator, matchingSearchAttributesByWorkflowId);
111
147
  }
112
148
  function finalizeAggregateResult(accumulator, requestedLimit) {
113
149
  const sortedGroups = [...accumulator.counts.entries()].map(([groupKey, count]) => ({ key: groupKey, count })).toSorted((left, right) => {