@swirls/looms 0.4.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (243) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/dist/actor/cell.d.ts +21 -2
  3. package/dist/actor/cell.js +15 -3
  4. package/dist/actor/host.d.ts +10 -2
  5. package/dist/actor/host.js +27 -4
  6. package/dist/actor/index.d.ts +2 -1
  7. package/dist/actor/index.js +1 -1
  8. package/dist/actor/routing.d.ts +3 -0
  9. package/dist/actor/routing.js +13 -2
  10. package/dist/agent/definitions-store.d.ts +1 -1
  11. package/dist/agent/definitions-store.js +1 -1
  12. package/dist/agent/definitions.d.ts +48 -0
  13. package/dist/agent/definitions.js +44 -0
  14. package/dist/agent/effects.d.ts +184 -0
  15. package/dist/agent/effects.js +172 -40
  16. package/dist/agent/events.d.ts +89 -0
  17. package/dist/agent/events.js +25 -0
  18. package/dist/agent/module.d.ts +412 -0
  19. package/dist/agent/module.js +5 -1
  20. package/dist/agent/scope.d.ts +88 -0
  21. package/dist/agent/threads.js +39 -3
  22. package/dist/agent/types.d.ts +4 -0
  23. package/dist/approval/effects.d.ts +40 -0
  24. package/dist/approval/module.d.ts +80 -0
  25. package/dist/client/client.d.ts +468 -119
  26. package/dist/client/client.js +214 -21
  27. package/dist/client/index.d.ts +1 -1
  28. package/dist/client/sse.d.ts +1 -1
  29. package/dist/client/sse.js +2 -2
  30. package/dist/cloudflare/durable-object.d.ts +66 -2
  31. package/dist/cloudflare/durable-object.js +96 -1
  32. package/dist/cloudflare/event-store.d.ts +7 -3
  33. package/dist/cloudflare/event-store.js +16 -3
  34. package/dist/cloudflare/index.d.ts +7 -1
  35. package/dist/cloudflare/index.js +7 -1
  36. package/dist/cloudflare/memory-queue.d.ts +18 -0
  37. package/dist/cloudflare/memory-queue.js +53 -0
  38. package/dist/cloudflare/queue-consumer.d.ts +52 -0
  39. package/dist/cloudflare/queue-consumer.js +102 -0
  40. package/dist/cloudflare/queue-message.d.ts +31 -0
  41. package/dist/cloudflare/queue-message.js +33 -0
  42. package/dist/cloudflare/queue-pull.d.ts +62 -0
  43. package/dist/cloudflare/queue-pull.js +130 -0
  44. package/dist/cloudflare/queue-worker.d.ts +39 -0
  45. package/dist/cloudflare/queue-worker.js +62 -0
  46. package/dist/cloudflare/queues.d.ts +10 -0
  47. package/dist/cloudflare/queues.js +10 -0
  48. package/dist/cloudflare/r2-blob-store.d.ts +33 -0
  49. package/dist/cloudflare/r2-blob-store.js +60 -0
  50. package/dist/cloudflare/router.d.ts +4 -1
  51. package/dist/cloudflare/router.js +8 -3
  52. package/dist/cloudflare/websocket.d.ts +27 -0
  53. package/dist/cloudflare/websocket.js +215 -0
  54. package/dist/core/blob-offload.d.ts +21 -0
  55. package/dist/core/blob-offload.js +143 -0
  56. package/dist/core/blob-store.d.ts +45 -0
  57. package/dist/core/blob-store.js +164 -0
  58. package/dist/core/blobs.d.ts +37 -0
  59. package/dist/core/blobs.js +160 -0
  60. package/dist/core/definition-resolver.d.ts +40 -0
  61. package/dist/core/definition-resolver.js +129 -0
  62. package/dist/core/definition-store.d.ts +6 -0
  63. package/dist/core/definition-store.js +37 -1
  64. package/dist/core/effects.d.ts +86 -3
  65. package/dist/core/effects.js +99 -3
  66. package/dist/core/envelope.d.ts +9 -0
  67. package/dist/core/envelope.js +4 -0
  68. package/dist/core/event-codec.js +3 -0
  69. package/dist/core/fold.js +83 -1
  70. package/dist/core/ids.d.ts +2 -0
  71. package/dist/core/ids.js +4 -0
  72. package/dist/core/index.d.ts +8 -0
  73. package/dist/core/index.js +8 -0
  74. package/dist/core/launcher.d.ts +97 -0
  75. package/dist/core/launcher.js +67 -0
  76. package/dist/core/module-scope.d.ts +7 -3
  77. package/dist/core/module-scope.js +3 -0
  78. package/dist/core/module.d.ts +10 -0
  79. package/dist/core/projection.js +4 -0
  80. package/dist/core/protocol.d.ts +36 -1
  81. package/dist/core/protocol.js +35 -0
  82. package/dist/core/published.d.ts +2 -0
  83. package/dist/core/published.js +4 -1
  84. package/dist/core/replay.d.ts +96 -0
  85. package/dist/core/run-context.d.ts +33 -0
  86. package/dist/core/run-context.js +23 -0
  87. package/dist/core/sqlite-store.js +57 -5
  88. package/dist/core/state.d.ts +60 -0
  89. package/dist/core/state.js +19 -0
  90. package/dist/core/store.d.ts +6 -0
  91. package/dist/core/store.js +7 -0
  92. package/dist/core/subscription.d.ts +97 -0
  93. package/dist/core/subscription.js +224 -0
  94. package/dist/core/thread.d.ts +7 -0
  95. package/dist/core/thread.js +1 -0
  96. package/dist/core/trace.d.ts +21 -0
  97. package/dist/core/trace.js +45 -0
  98. package/dist/core/worker-callback.d.ts +25 -1
  99. package/dist/debugger/app/assets/{index-CgDzWJg7.css → index-B7GdT1UA.css} +1 -1
  100. package/dist/debugger/app/assets/index-C31SnCuN.js +22 -0
  101. package/dist/debugger/app/assets/routes-DPA3O5AF.js +47 -0
  102. package/dist/debugger/app/index.html +2 -2
  103. package/dist/debugger/components/event-inspector.d.ts +3 -1
  104. package/dist/debugger/components/event-inspector.js +25 -4
  105. package/dist/debugger/components/event-stream.d.ts +4 -1
  106. package/dist/debugger/components/event-stream.js +2 -2
  107. package/dist/debugger/components/run-tree.d.ts +5 -2
  108. package/dist/debugger/components/run-tree.js +10 -4
  109. package/dist/debugger/context.d.ts +8 -1
  110. package/dist/debugger/context.js +15 -3
  111. package/dist/debugger/events/protocol-summarize.js +18 -3
  112. package/dist/debugger/index.d.ts +1 -1
  113. package/dist/debugger/index.js +1 -1
  114. package/dist/debugger/shell/debugger-shell.js +1 -1
  115. package/dist/debugger/shell/events-pane.js +4 -3
  116. package/dist/debugger/styles.css +1 -0
  117. package/dist/evaluator/definitions-store.d.ts +3 -4
  118. package/dist/evaluator/definitions-store.js +3 -3
  119. package/dist/evaluator/definitions.d.ts +4 -1
  120. package/dist/evaluator/definitions.js +5 -2
  121. package/dist/evaluator/effects.d.ts +41 -0
  122. package/dist/evaluator/effects.js +6 -2
  123. package/dist/evaluator/module.d.ts +84 -0
  124. package/dist/evaluator/module.js +7 -3
  125. package/dist/evaluator/threads.d.ts +2 -0
  126. package/dist/evaluator/threads.js +4 -0
  127. package/dist/projectors/event-log.d.ts +87 -0
  128. package/dist/projectors/event-log.js +396 -0
  129. package/dist/projectors/index-model.d.ts +12 -0
  130. package/dist/projectors/index-model.js +12 -3
  131. package/dist/projectors/memory.js +7 -0
  132. package/dist/projectors/postgres.d.ts +1 -0
  133. package/dist/projectors/postgres.js +32 -15
  134. package/dist/projectors/schema.d.ts +5 -0
  135. package/dist/projectors/schema.js +26 -1
  136. package/dist/projectors/sqlite.js +47 -19
  137. package/dist/projectors/with-projectors.d.ts +7 -1
  138. package/dist/projectors/with-projectors.js +13 -3
  139. package/dist/react/materialize.js +5 -1
  140. package/dist/react/react.d.ts +10 -2
  141. package/dist/react/react.js +43 -19
  142. package/dist/react/store.d.ts +11 -2
  143. package/dist/react/store.js +104 -12
  144. package/dist/react/tables.d.ts +4 -1
  145. package/dist/runtime/cancellation.d.ts +2 -1
  146. package/dist/runtime/cancellation.js +35 -2
  147. package/dist/runtime/child-run.d.ts +10 -0
  148. package/dist/runtime/child-run.js +58 -0
  149. package/dist/runtime/deadline-transition-planner.js +11 -2
  150. package/dist/runtime/dispatch-effect.d.ts +2 -2
  151. package/dist/runtime/dispatch-effect.js +43 -19
  152. package/dist/runtime/errors.d.ts +14 -1
  153. package/dist/runtime/errors.js +10 -0
  154. package/dist/runtime/filesystem-blob-store.d.ts +6 -0
  155. package/dist/runtime/filesystem-blob-store.js +59 -0
  156. package/dist/runtime/helpers.d.ts +15 -6
  157. package/dist/runtime/helpers.js +46 -6
  158. package/dist/runtime/index.d.ts +4 -2
  159. package/dist/runtime/index.js +3 -1
  160. package/dist/runtime/local-effect-executor.d.ts +11 -2
  161. package/dist/runtime/local-effect-executor.js +80 -4
  162. package/dist/runtime/looms.d.ts +38 -4
  163. package/dist/runtime/looms.js +17 -3
  164. package/dist/runtime/repository.d.ts +5 -4
  165. package/dist/runtime/repository.js +5 -2
  166. package/dist/runtime/retry-policy.d.ts +5 -0
  167. package/dist/runtime/retry-policy.js +10 -2
  168. package/dist/runtime/run-start.d.ts +1 -1
  169. package/dist/runtime/run-start.js +10 -0
  170. package/dist/runtime/runtime.d.ts +2 -2
  171. package/dist/runtime/runtime.js +191 -68
  172. package/dist/runtime/server/auth.d.ts +3 -0
  173. package/dist/runtime/server/fetch-handler.d.ts +2 -2
  174. package/dist/runtime/server/fetch-handler.js +35 -4
  175. package/dist/runtime/server/grant.d.ts +49 -0
  176. package/dist/runtime/server/grant.js +177 -0
  177. package/dist/runtime/server/routes/effects.js +47 -5
  178. package/dist/runtime/server/routes/runs.js +6 -1
  179. package/dist/runtime/server/run-route.d.ts +18 -0
  180. package/dist/runtime/server/run-route.js +26 -0
  181. package/dist/runtime/server.d.ts +3 -1
  182. package/dist/runtime/server.js +3 -1
  183. package/dist/runtime/sse.js +26 -4
  184. package/dist/runtime/subscription.d.ts +8 -0
  185. package/dist/runtime/subscription.js +23 -0
  186. package/dist/runtime/types.d.ts +87 -8
  187. package/dist/runtime/wake-engine.d.ts +4 -2
  188. package/dist/runtime/wake-engine.js +57 -6
  189. package/dist/runtime/worker-callbacks.d.ts +12 -2
  190. package/dist/runtime/worker-callbacks.js +102 -72
  191. package/dist/runtime/worker-effect-dispatch.d.ts +14 -5
  192. package/dist/runtime/worker-effect-dispatch.js +84 -18
  193. package/dist/schedule/debugger/index.d.ts +4 -0
  194. package/dist/schedule/debugger/index.js +11 -0
  195. package/dist/schedule/debugger/schedule-view.d.ts +3 -0
  196. package/dist/schedule/debugger/schedule-view.js +68 -0
  197. package/dist/schedule/debugger/summarize.d.ts +2 -0
  198. package/dist/schedule/debugger/summarize.js +43 -0
  199. package/dist/schedule/definitions-store.d.ts +10 -0
  200. package/dist/schedule/definitions-store.js +8 -0
  201. package/dist/schedule/definitions.d.ts +57 -0
  202. package/dist/schedule/definitions.js +30 -0
  203. package/dist/schedule/effects.d.ts +756 -0
  204. package/dist/schedule/effects.js +244 -0
  205. package/dist/schedule/ensure.d.ts +55 -0
  206. package/dist/schedule/ensure.js +109 -0
  207. package/dist/schedule/events.d.ts +116 -0
  208. package/dist/schedule/events.js +49 -0
  209. package/dist/schedule/index.d.ts +11 -0
  210. package/dist/schedule/index.js +11 -0
  211. package/dist/schedule/module.d.ts +1474 -0
  212. package/dist/schedule/module.js +22 -0
  213. package/dist/schedule/projections.d.ts +55 -0
  214. package/dist/schedule/projections.js +88 -0
  215. package/dist/schedule/scope.d.ts +121 -0
  216. package/dist/schedule/scope.js +7 -0
  217. package/dist/schedule/signals.d.ts +25 -0
  218. package/dist/schedule/signals.js +33 -0
  219. package/dist/schedule/specs.d.ts +59 -0
  220. package/dist/schedule/specs.js +231 -0
  221. package/dist/schedule/threads.d.ts +25 -0
  222. package/dist/schedule/threads.js +259 -0
  223. package/dist/testing/corpus-module.d.ts +34 -0
  224. package/dist/testing/corpus-module.js +87 -0
  225. package/dist/testing/index.d.ts +2 -0
  226. package/dist/testing/index.js +5 -6
  227. package/dist/testing/replay-corpus.d.ts +22 -0
  228. package/dist/testing/replay-corpus.js +50 -0
  229. package/dist/workflow/definitions-store.d.ts +1 -1
  230. package/dist/workflow/definitions-store.js +1 -1
  231. package/dist/workflow/definitions.d.ts +14 -0
  232. package/dist/workflow/effects.d.ts +122 -0
  233. package/dist/workflow/effects.js +16 -6
  234. package/dist/workflow/events.d.ts +42 -0
  235. package/dist/workflow/events.js +4 -0
  236. package/dist/workflow/module.d.ts +313 -0
  237. package/dist/workflow/module.js +7 -3
  238. package/dist/workflow/scope.d.ts +42 -0
  239. package/dist/workflow/threads.d.ts +72 -0
  240. package/dist/workflow/threads.js +106 -38
  241. package/package.json +14 -1
  242. package/dist/debugger/app/assets/index-D--9esm9.js +0 -22
  243. package/dist/debugger/app/assets/routes-Dakrdusf.js +0 -47
@@ -1,13 +1,14 @@
1
- import { defineModule } from '@swirls/looms/core';
1
+ import { defineModule, makeDefinitionStore } from '@swirls/looms/core';
2
2
  import { WorkflowDefinitionsLive } from './definitions-store.js';
3
3
  import { runNodeEffect, scheduleEffect } from './effects.js';
4
4
  import { nodes } from './projections.js';
5
5
  import { workflowModule } from './scope.js';
6
6
  import { workflowThread } from './threads.js';
7
7
  export function workflow(options = {}) {
8
- const definitions = options.definitions ?? [];
8
+ const listed = options.definitions ?? [];
9
+ const definitions = makeDefinitionStore('workflow', listed);
9
10
  return defineModule(workflowModule, () => ({
10
- definitions,
11
+ definitions: listed,
11
12
  threads: { workflow: workflowThread },
12
13
  effects: {
13
14
  schedule: scheduleEffect,
@@ -15,5 +16,8 @@ export function workflow(options = {}) {
15
16
  },
16
17
  projections: { nodes },
17
18
  services: () => WorkflowDefinitionsLive(definitions),
19
+ bindHost(host) {
20
+ definitions.useResolver(host.definitionResolver);
21
+ },
18
22
  }));
19
23
  }
@@ -23,6 +23,8 @@ export declare const workflowModule: import("@swirls/looms/core").ModuleScope<"w
23
23
  readonly definitionVersion: import("effect/Schema").withDecodingDefaultKey<import("effect/Schema").String, never>;
24
24
  readonly input: import("effect/Schema").Codec<import("effect/Schema").Json, import("effect/Schema").Json, never, never>;
25
25
  readonly loopIndex: import("effect/Schema").withDecodingDefaultKey<import("effect/Schema").NullOr<import("effect/Schema").Finite>, never>;
26
+ readonly execution: import("effect/Schema").withDecodingDefaultKey<import("effect/Schema").Union<readonly [import("effect/Schema").Literal<"thread">, import("effect/Schema").Literal<"run">]>, never>;
27
+ readonly close: import("effect/Schema").withDecodingDefaultKey<import("effect/Schema").Union<readonly [import("effect/Schema").Literal<"terminate">, import("effect/Schema").Literal<"wait">]>, never>;
26
28
  }>;
27
29
  'map.requested': import("effect/Schema").Struct<{
28
30
  readonly nodeId: import("effect/Schema").String;
@@ -33,6 +35,8 @@ export declare const workflowModule: import("@swirls/looms/core").ModuleScope<"w
33
35
  readonly items: import("effect/Schema").$Array<import("effect/Schema").Codec<import("effect/Schema").Json, import("effect/Schema").Json, never, never>>;
34
36
  readonly concurrency: import("effect/Schema").Finite;
35
37
  readonly limitBytes: import("effect/Schema").Finite;
38
+ readonly execution: import("effect/Schema").withDecodingDefaultKey<import("effect/Schema").Union<readonly [import("effect/Schema").Literal<"thread">, import("effect/Schema").Literal<"run">]>, never>;
39
+ readonly close: import("effect/Schema").withDecodingDefaultKey<import("effect/Schema").Union<readonly [import("effect/Schema").Literal<"terminate">, import("effect/Schema").Literal<"wait">]>, never>;
36
40
  }>;
37
41
  'sleep.requested': import("effect/Schema").Struct<{
38
42
  readonly nodeId: import("effect/Schema").String;
@@ -76,6 +80,9 @@ export declare const workflowModule: import("@swirls/looms/core").ModuleScope<"w
76
80
  readonly actorId: import("effect/Schema").optional<import("effect/Schema").String>;
77
81
  }>, import("effect/Schema").Struct<{
78
82
  readonly type: import("effect/Schema").Literal<"system">;
83
+ }>, import("effect/Schema").Struct<{
84
+ readonly type: import("effect/Schema").Literal<"run">;
85
+ readonly runId: import("effect/Schema").String;
79
86
  }>]>>;
80
87
  readonly ephemeral: import("effect/Schema").optional<import("effect/Schema").Boolean>;
81
88
  readonly id: import("effect/Schema").optional<import("effect/Schema").String>;
@@ -93,10 +100,24 @@ export declare const workflowModule: import("@swirls/looms/core").ModuleScope<"w
93
100
  readonly type: import("effect/Schema").Literal<"runtime.cancel">;
94
101
  readonly threadId: import("effect/Schema").String;
95
102
  readonly tag: import("effect/Schema").optional<import("effect/Schema").String>;
103
+ }>, import("effect/Schema").Struct<{
104
+ readonly type: import("effect/Schema").Literal<"runtime.launch">;
105
+ readonly runId: import("effect/Schema").String;
106
+ readonly kind: import("effect/Schema").String;
107
+ readonly definitionName: import("effect/Schema").String;
108
+ readonly definitionVersion: import("effect/Schema").withDecodingDefaultKey<import("effect/Schema").String, never>;
109
+ readonly input: import("effect/Schema").Codec<import("effect/Schema").Json, import("effect/Schema").Json, never, never>;
110
+ readonly close: import("effect/Schema").withDecodingDefaultKey<import("effect/Schema").Union<readonly [import("effect/Schema").Literal<"terminate">, import("effect/Schema").Literal<"wait">]>, never>;
111
+ readonly tag: import("effect/Schema").optional<import("effect/Schema").String>;
112
+ }>, import("effect/Schema").Struct<{
113
+ readonly type: import("effect/Schema").Literal<"runtime.cancelRun">;
114
+ readonly runId: import("effect/Schema").String;
115
+ readonly tag: import("effect/Schema").optional<import("effect/Schema").String>;
96
116
  }>, import("effect/Schema").Struct<{
97
117
  readonly type: import("effect/Schema").String;
98
118
  readonly input: import("effect/Schema").Codec<import("effect/Schema").Json, import("effect/Schema").Json, never, never>;
99
119
  readonly tag: import("effect/Schema").optional<import("effect/Schema").String>;
120
+ readonly at: import("effect/Schema").optional<import("effect/Schema").Finite>;
100
121
  }>]>>;
101
122
  }>;
102
123
  }>, undefined>, import("@swirls/looms/core").EventCatalog<"workflow", {
@@ -123,6 +144,8 @@ export declare const workflowModule: import("@swirls/looms/core").ModuleScope<"w
123
144
  readonly definitionVersion: import("effect/Schema").withDecodingDefaultKey<import("effect/Schema").String, never>;
124
145
  readonly input: import("effect/Schema").Codec<import("effect/Schema").Json, import("effect/Schema").Json, never, never>;
125
146
  readonly loopIndex: import("effect/Schema").withDecodingDefaultKey<import("effect/Schema").NullOr<import("effect/Schema").Finite>, never>;
147
+ readonly execution: import("effect/Schema").withDecodingDefaultKey<import("effect/Schema").Union<readonly [import("effect/Schema").Literal<"thread">, import("effect/Schema").Literal<"run">]>, never>;
148
+ readonly close: import("effect/Schema").withDecodingDefaultKey<import("effect/Schema").Union<readonly [import("effect/Schema").Literal<"terminate">, import("effect/Schema").Literal<"wait">]>, never>;
126
149
  }>;
127
150
  'map.requested': import("effect/Schema").Struct<{
128
151
  readonly nodeId: import("effect/Schema").String;
@@ -133,6 +156,8 @@ export declare const workflowModule: import("@swirls/looms/core").ModuleScope<"w
133
156
  readonly items: import("effect/Schema").$Array<import("effect/Schema").Codec<import("effect/Schema").Json, import("effect/Schema").Json, never, never>>;
134
157
  readonly concurrency: import("effect/Schema").Finite;
135
158
  readonly limitBytes: import("effect/Schema").Finite;
159
+ readonly execution: import("effect/Schema").withDecodingDefaultKey<import("effect/Schema").Union<readonly [import("effect/Schema").Literal<"thread">, import("effect/Schema").Literal<"run">]>, never>;
160
+ readonly close: import("effect/Schema").withDecodingDefaultKey<import("effect/Schema").Union<readonly [import("effect/Schema").Literal<"terminate">, import("effect/Schema").Literal<"wait">]>, never>;
136
161
  }>;
137
162
  'sleep.requested': import("effect/Schema").Struct<{
138
163
  readonly nodeId: import("effect/Schema").String;
@@ -176,6 +201,9 @@ export declare const workflowModule: import("@swirls/looms/core").ModuleScope<"w
176
201
  readonly actorId: import("effect/Schema").optional<import("effect/Schema").String>;
177
202
  }>, import("effect/Schema").Struct<{
178
203
  readonly type: import("effect/Schema").Literal<"system">;
204
+ }>, import("effect/Schema").Struct<{
205
+ readonly type: import("effect/Schema").Literal<"run">;
206
+ readonly runId: import("effect/Schema").String;
179
207
  }>]>>;
180
208
  readonly ephemeral: import("effect/Schema").optional<import("effect/Schema").Boolean>;
181
209
  readonly id: import("effect/Schema").optional<import("effect/Schema").String>;
@@ -193,10 +221,24 @@ export declare const workflowModule: import("@swirls/looms/core").ModuleScope<"w
193
221
  readonly type: import("effect/Schema").Literal<"runtime.cancel">;
194
222
  readonly threadId: import("effect/Schema").String;
195
223
  readonly tag: import("effect/Schema").optional<import("effect/Schema").String>;
224
+ }>, import("effect/Schema").Struct<{
225
+ readonly type: import("effect/Schema").Literal<"runtime.launch">;
226
+ readonly runId: import("effect/Schema").String;
227
+ readonly kind: import("effect/Schema").String;
228
+ readonly definitionName: import("effect/Schema").String;
229
+ readonly definitionVersion: import("effect/Schema").withDecodingDefaultKey<import("effect/Schema").String, never>;
230
+ readonly input: import("effect/Schema").Codec<import("effect/Schema").Json, import("effect/Schema").Json, never, never>;
231
+ readonly close: import("effect/Schema").withDecodingDefaultKey<import("effect/Schema").Union<readonly [import("effect/Schema").Literal<"terminate">, import("effect/Schema").Literal<"wait">]>, never>;
232
+ readonly tag: import("effect/Schema").optional<import("effect/Schema").String>;
233
+ }>, import("effect/Schema").Struct<{
234
+ readonly type: import("effect/Schema").Literal<"runtime.cancelRun">;
235
+ readonly runId: import("effect/Schema").String;
236
+ readonly tag: import("effect/Schema").optional<import("effect/Schema").String>;
196
237
  }>, import("effect/Schema").Struct<{
197
238
  readonly type: import("effect/Schema").String;
198
239
  readonly input: import("effect/Schema").Codec<import("effect/Schema").Json, import("effect/Schema").Json, never, never>;
199
240
  readonly tag: import("effect/Schema").optional<import("effect/Schema").String>;
241
+ readonly at: import("effect/Schema").optional<import("effect/Schema").Finite>;
200
242
  }>]>>;
201
243
  }>;
202
244
  }>, undefined>;
@@ -9,6 +9,8 @@ export declare const WorkflowPendingSpawnSchema: Schema.Struct<{
9
9
  readonly attempt: Schema.withDecodingDefaultKey<Schema.Finite, never>;
10
10
  readonly input: Schema.Codec<Schema.Json, Schema.Json, never, never>;
11
11
  readonly loopIndex: Schema.withDecodingDefaultKey<Schema.NullOr<Schema.Finite>, never>;
12
+ readonly execution: Schema.withDecodingDefaultKey<Schema.Union<readonly [Schema.Literal<"thread">, Schema.Literal<"run">]>, never>;
13
+ readonly close: Schema.withDecodingDefaultKey<Schema.Union<readonly [Schema.Literal<"terminate">, Schema.Literal<"wait">]>, never>;
12
14
  }>;
13
15
  export type WorkflowPendingSpawn = Schema.Schema.Type<typeof WorkflowPendingSpawnSchema>;
14
16
  export declare const WorkflowPendingMapSchema: Schema.Struct<{
@@ -23,6 +25,8 @@ export declare const WorkflowPendingMapSchema: Schema.Struct<{
23
25
  /** Items before this index have been started; later ones wait for a free slot. */
24
26
  readonly nextIndex: Schema.Finite;
25
27
  readonly outputs: Schema.$Record<Schema.String, Schema.Codec<Schema.Json, Schema.Json, never, never>>;
28
+ readonly execution: Schema.withDecodingDefaultKey<Schema.Union<readonly [Schema.Literal<"thread">, Schema.Literal<"run">]>, never>;
29
+ readonly close: Schema.withDecodingDefaultKey<Schema.Union<readonly [Schema.Literal<"terminate">, Schema.Literal<"wait">]>, never>;
26
30
  }>;
27
31
  export type WorkflowPendingMap = Schema.Schema.Type<typeof WorkflowPendingMapSchema>;
28
32
  export declare const WorkflowPendingSleepSchema: Schema.Struct<{
@@ -68,6 +72,9 @@ export declare const WorkflowPendingEffectsSchema: Schema.Struct<{
68
72
  readonly actorId: Schema.optional<Schema.String>;
69
73
  }>, Schema.Struct<{
70
74
  readonly type: Schema.Literal<"system">;
75
+ }>, Schema.Struct<{
76
+ readonly type: Schema.Literal<"run">;
77
+ readonly runId: Schema.String;
71
78
  }>]>>;
72
79
  readonly ephemeral: Schema.optional<Schema.Boolean>;
73
80
  readonly id: Schema.optional<Schema.String>;
@@ -85,10 +92,24 @@ export declare const WorkflowPendingEffectsSchema: Schema.Struct<{
85
92
  readonly type: Schema.Literal<"runtime.cancel">;
86
93
  readonly threadId: Schema.String;
87
94
  readonly tag: Schema.optional<Schema.String>;
95
+ }>, Schema.Struct<{
96
+ readonly type: Schema.Literal<"runtime.launch">;
97
+ readonly runId: Schema.String;
98
+ readonly kind: Schema.String;
99
+ readonly definitionName: Schema.String;
100
+ readonly definitionVersion: Schema.withDecodingDefaultKey<Schema.String, never>;
101
+ readonly input: Schema.Codec<Schema.Json, Schema.Json, never, never>;
102
+ readonly close: Schema.withDecodingDefaultKey<Schema.Union<readonly [Schema.Literal<"terminate">, Schema.Literal<"wait">]>, never>;
103
+ readonly tag: Schema.optional<Schema.String>;
104
+ }>, Schema.Struct<{
105
+ readonly type: Schema.Literal<"runtime.cancelRun">;
106
+ readonly runId: Schema.String;
107
+ readonly tag: Schema.optional<Schema.String>;
88
108
  }>, Schema.Struct<{
89
109
  readonly type: Schema.String;
90
110
  readonly input: Schema.Codec<Schema.Json, Schema.Json, never, never>;
91
111
  readonly tag: Schema.optional<Schema.String>;
112
+ readonly at: Schema.optional<Schema.Finite>;
92
113
  }>]>>>;
93
114
  }>;
94
115
  export type WorkflowPendingEffects = Schema.Schema.Type<typeof WorkflowPendingEffectsSchema>;
@@ -110,6 +131,9 @@ export declare const WorkflowPendingEmitSchema: Schema.Struct<{
110
131
  readonly actorId: Schema.optional<Schema.String>;
111
132
  }>, Schema.Struct<{
112
133
  readonly type: Schema.Literal<"system">;
134
+ }>, Schema.Struct<{
135
+ readonly type: Schema.Literal<"run">;
136
+ readonly runId: Schema.String;
113
137
  }>]>>;
114
138
  readonly ephemeral: Schema.optional<Schema.Boolean>;
115
139
  readonly id: Schema.optional<Schema.String>;
@@ -147,6 +171,8 @@ export declare const WorkflowStateSchema: Schema.Struct<{
147
171
  readonly attempt: Schema.withDecodingDefaultKey<Schema.Finite, never>;
148
172
  readonly input: Schema.Codec<Schema.Json, Schema.Json, never, never>;
149
173
  readonly loopIndex: Schema.withDecodingDefaultKey<Schema.NullOr<Schema.Finite>, never>;
174
+ readonly execution: Schema.withDecodingDefaultKey<Schema.Union<readonly [Schema.Literal<"thread">, Schema.Literal<"run">]>, never>;
175
+ readonly close: Schema.withDecodingDefaultKey<Schema.Union<readonly [Schema.Literal<"terminate">, Schema.Literal<"wait">]>, never>;
150
176
  }>>>;
151
177
  readonly pendingMaps: Schema.withDecodingDefaultKey<Schema.mutable<Schema.$Array<Schema.Struct<{
152
178
  readonly nodeId: Schema.String;
@@ -160,6 +186,8 @@ export declare const WorkflowStateSchema: Schema.Struct<{
160
186
  /** Items before this index have been started; later ones wait for a free slot. */
161
187
  readonly nextIndex: Schema.Finite;
162
188
  readonly outputs: Schema.$Record<Schema.String, Schema.Codec<Schema.Json, Schema.Json, never, never>>;
189
+ readonly execution: Schema.withDecodingDefaultKey<Schema.Union<readonly [Schema.Literal<"thread">, Schema.Literal<"run">]>, never>;
190
+ readonly close: Schema.withDecodingDefaultKey<Schema.Union<readonly [Schema.Literal<"terminate">, Schema.Literal<"wait">]>, never>;
163
191
  }>>>, never>;
164
192
  readonly pendingSleeps: Schema.mutable<Schema.$Array<Schema.Struct<{
165
193
  readonly waitId: Schema.String;
@@ -203,6 +231,9 @@ export declare const WorkflowStateSchema: Schema.Struct<{
203
231
  readonly actorId: Schema.optional<Schema.String>;
204
232
  }>, Schema.Struct<{
205
233
  readonly type: Schema.Literal<"system">;
234
+ }>, Schema.Struct<{
235
+ readonly type: Schema.Literal<"run">;
236
+ readonly runId: Schema.String;
206
237
  }>]>>;
207
238
  readonly ephemeral: Schema.optional<Schema.Boolean>;
208
239
  readonly id: Schema.optional<Schema.String>;
@@ -220,10 +251,24 @@ export declare const WorkflowStateSchema: Schema.Struct<{
220
251
  readonly type: Schema.Literal<"runtime.cancel">;
221
252
  readonly threadId: Schema.String;
222
253
  readonly tag: Schema.optional<Schema.String>;
254
+ }>, Schema.Struct<{
255
+ readonly type: Schema.Literal<"runtime.launch">;
256
+ readonly runId: Schema.String;
257
+ readonly kind: Schema.String;
258
+ readonly definitionName: Schema.String;
259
+ readonly definitionVersion: Schema.withDecodingDefaultKey<Schema.String, never>;
260
+ readonly input: Schema.Codec<Schema.Json, Schema.Json, never, never>;
261
+ readonly close: Schema.withDecodingDefaultKey<Schema.Union<readonly [Schema.Literal<"terminate">, Schema.Literal<"wait">]>, never>;
262
+ readonly tag: Schema.optional<Schema.String>;
263
+ }>, Schema.Struct<{
264
+ readonly type: Schema.Literal<"runtime.cancelRun">;
265
+ readonly runId: Schema.String;
266
+ readonly tag: Schema.optional<Schema.String>;
223
267
  }>, Schema.Struct<{
224
268
  readonly type: Schema.String;
225
269
  readonly input: Schema.Codec<Schema.Json, Schema.Json, never, never>;
226
270
  readonly tag: Schema.optional<Schema.String>;
271
+ readonly at: Schema.optional<Schema.Finite>;
227
272
  }>]>>>;
228
273
  }>>>;
229
274
  readonly pendingEmits: Schema.mutable<Schema.$Array<Schema.Struct<{
@@ -244,6 +289,9 @@ export declare const WorkflowStateSchema: Schema.Struct<{
244
289
  readonly actorId: Schema.optional<Schema.String>;
245
290
  }>, Schema.Struct<{
246
291
  readonly type: Schema.Literal<"system">;
292
+ }>, Schema.Struct<{
293
+ readonly type: Schema.Literal<"run">;
294
+ readonly runId: Schema.String;
247
295
  }>]>>;
248
296
  readonly ephemeral: Schema.optional<Schema.Boolean>;
249
297
  readonly id: Schema.optional<Schema.String>;
@@ -288,6 +336,8 @@ export declare const workflowThread: import("@swirls/looms/core").ThreadDefiniti
288
336
  readonly attempt: number;
289
337
  readonly input: Schema.Json;
290
338
  readonly loopIndex: number | null;
339
+ readonly execution: "run" | "thread";
340
+ readonly close: "terminate" | "wait";
291
341
  }[];
292
342
  readonly pendingMaps: {
293
343
  readonly nodeId: string;
@@ -302,6 +352,8 @@ export declare const workflowThread: import("@swirls/looms/core").ThreadDefiniti
302
352
  readonly outputs: {
303
353
  readonly [x: string]: Schema.Json;
304
354
  };
355
+ readonly execution: "run" | "thread";
356
+ readonly close: "terminate" | "wait";
305
357
  }[];
306
358
  readonly pendingSleeps: {
307
359
  readonly waitId: string;
@@ -345,6 +397,9 @@ export declare const workflowThread: import("@swirls/looms/core").ThreadDefiniti
345
397
  readonly actorId?: string | undefined;
346
398
  } | {
347
399
  readonly type: "system";
400
+ } | {
401
+ readonly type: "run";
402
+ readonly runId: string;
348
403
  } | undefined;
349
404
  readonly ephemeral?: boolean | undefined;
350
405
  readonly id?: string | undefined;
@@ -362,10 +417,24 @@ export declare const workflowThread: import("@swirls/looms/core").ThreadDefiniti
362
417
  readonly type: "runtime.cancel";
363
418
  readonly threadId: string;
364
419
  readonly tag?: string | undefined;
420
+ } | {
421
+ readonly type: "runtime.launch";
422
+ readonly runId: string;
423
+ readonly kind: string;
424
+ readonly definitionName: string;
425
+ readonly definitionVersion: string;
426
+ readonly input: Schema.Json;
427
+ readonly close: "terminate" | "wait";
428
+ readonly tag?: string | undefined;
429
+ } | {
430
+ readonly type: "runtime.cancelRun";
431
+ readonly runId: string;
432
+ readonly tag?: string | undefined;
365
433
  } | {
366
434
  readonly type: string;
367
435
  readonly input: Schema.Json;
368
436
  readonly tag?: string | undefined;
437
+ readonly at?: number | undefined;
369
438
  })[];
370
439
  }[];
371
440
  readonly pendingEmits: {
@@ -386,6 +455,9 @@ export declare const workflowThread: import("@swirls/looms/core").ThreadDefiniti
386
455
  readonly actorId?: string | undefined;
387
456
  } | {
388
457
  readonly type: "system";
458
+ } | {
459
+ readonly type: "run";
460
+ readonly runId: string;
389
461
  } | undefined;
390
462
  readonly ephemeral?: boolean | undefined;
391
463
  readonly id?: string | undefined;
@@ -1,5 +1,5 @@
1
1
  import { Effect, Predicate, Schema } from 'effect';
2
- import { cancel, createWaitId, DEFAULT_DEFINITION_VERSION, EventInputSchema, emit, fail, invoke, isJsonObject, isWithdrawnError, RuntimeEffectSchema, spawn, stableEffectId, wait, utf8JsonBytes, waitOutcome, } from '@swirls/looms/core';
2
+ import { cancel, cancelRun, createWaitId, DEFAULT_DEFINITION_VERSION, deterministicRunId, EventInputSchema, emit, fail, invoke, isJsonObject, isWithdrawnError, launch, RuntimeEffectSchema, spawn, stableEffectId, wait, utf8JsonBytes, waitOutcome, } from '@swirls/looms/core';
3
3
  import { NodeStateSchema } from './definitions.js';
4
4
  import { runNodeEffect, scheduleEffect } from './effects.js';
5
5
  import { iterationChildWorkflowId, nodeRunKey, WorkflowValueTooLargeError } from './graph.js';
@@ -15,6 +15,8 @@ export const WorkflowPendingSpawnSchema = Schema.Struct({
15
15
  attempt: attemptNumber,
16
16
  input: Schema.Json,
17
17
  loopIndex: Schema.NullOr(Schema.Finite).pipe(Schema.withDecodingDefaultKey(Effect.succeed(null))),
18
+ execution: Schema.Union([Schema.Literal('thread'), Schema.Literal('run')]).pipe(Schema.withDecodingDefaultKey(Effect.succeed('thread'))),
19
+ close: Schema.Union([Schema.Literal('terminate'), Schema.Literal('wait')]).pipe(Schema.withDecodingDefaultKey(Effect.succeed('terminate'))),
18
20
  });
19
21
  export const WorkflowPendingMapSchema = Schema.Struct({
20
22
  nodeId: Schema.String,
@@ -28,6 +30,8 @@ export const WorkflowPendingMapSchema = Schema.Struct({
28
30
  /** Items before this index have been started; later ones wait for a free slot. */
29
31
  nextIndex: Schema.Finite,
30
32
  outputs: Schema.Record(Schema.String, Schema.Json),
33
+ execution: Schema.Union([Schema.Literal('thread'), Schema.Literal('run')]).pipe(Schema.withDecodingDefaultKey(Effect.succeed('thread'))),
34
+ close: Schema.Union([Schema.Literal('terminate'), Schema.Literal('wait')]).pipe(Schema.withDecodingDefaultKey(Effect.succeed('terminate'))),
31
35
  });
32
36
  export const WorkflowPendingSleepSchema = Schema.Struct({
33
37
  waitId: Schema.String,
@@ -87,7 +91,26 @@ function runNodeInvocation(state, nodeId) {
87
91
  nodes: state.nodes,
88
92
  }, `runNode_${nodeRunKey(nodeId, attempts, node?.iteration?.index)}`);
89
93
  }
90
- function spawnAndWait(threadId, child, childThreadId, input, tag) {
94
+ function spawnAndWait(runId, threadId, child, childThreadId, input, tag) {
95
+ if (child.execution === 'run') {
96
+ const childRunId = deterministicRunId(runId, childThreadId);
97
+ return [
98
+ launch({
99
+ runId: childRunId,
100
+ kind: child.kind,
101
+ definitionName: child.definitionName,
102
+ definitionVersion: child.definitionVersion,
103
+ input,
104
+ close: child.close,
105
+ tag: `launch_${childRunId}`,
106
+ }),
107
+ wait({
108
+ waitId: createWaitId(threadId, `spawn_${childRunId}`),
109
+ on: { type: 'runtime.child.settled', match: { runId: childRunId } },
110
+ tag,
111
+ }),
112
+ ];
113
+ }
91
114
  return [
92
115
  spawn({
93
116
  childThreadId,
@@ -106,11 +129,17 @@ function spawnAndWait(threadId, child, childThreadId, input, tag) {
106
129
  }),
107
130
  ];
108
131
  }
132
+ function childMode(execution, close) {
133
+ return {
134
+ execution: execution === 'run' ? 'run' : 'thread',
135
+ close: close === 'wait' ? 'wait' : 'terminate',
136
+ };
137
+ }
109
138
  function mapChildThreadId(threadId, map, index) {
110
139
  return iterationChildWorkflowId(threadId, map.nodeId, 'map', map.attempt, index);
111
140
  }
112
141
  /** Every effect a node currently needs, attributed to that node. */
113
- function nodeEffects(state, threadId) {
142
+ function nodeEffects(state, threadId, runId) {
114
143
  const effects = [];
115
144
  const add = (nodeId, items) => {
116
145
  for (const effect of items) {
@@ -122,7 +151,7 @@ function nodeEffects(state, threadId) {
122
151
  }
123
152
  for (const item of state.pendingSpawns) {
124
153
  const tag = { nodeId: item.nodeId, attempt: item.attempt };
125
- add(item.nodeId, spawnAndWait(threadId, item, item.childThreadId, item.input, {
154
+ add(item.nodeId, spawnAndWait(runId, threadId, item, item.childThreadId, item.input, {
126
155
  ...tag,
127
156
  loopIndex: item.loopIndex,
128
157
  }));
@@ -130,7 +159,7 @@ function nodeEffects(state, threadId) {
130
159
  for (const map of state.pendingMaps) {
131
160
  for (let index = 0; index < map.nextIndex; index++) {
132
161
  if (!(String(index) in map.outputs)) {
133
- add(map.nodeId, spawnAndWait(threadId, map, mapChildThreadId(threadId, map, index), map.items[index] ?? null, { nodeId: map.nodeId, attempt: map.attempt, index }));
162
+ add(map.nodeId, spawnAndWait(runId, threadId, map, mapChildThreadId(threadId, map, index), map.items[index] ?? null, { nodeId: map.nodeId, attempt: map.attempt, index }));
134
163
  }
135
164
  }
136
165
  }
@@ -144,50 +173,80 @@ function nodeEffects(state, threadId) {
144
173
  }
145
174
  return effects;
146
175
  }
147
- function nodeIdForEffect(state, threadId, effectId) {
148
- const match = nodeEffects(state, threadId).find((item) => stableEffectId(threadId, item.effect) === effectId);
176
+ function nodeIdForEffect(state, threadId, runId, effectId) {
177
+ const match = nodeEffects(state, threadId, runId).find((item) => stableEffectId(threadId, item.effect) === effectId);
149
178
  return match?.nodeId ?? null;
150
179
  }
180
+ function childTarget(runId, childThreadId, execution) {
181
+ return execution === 'run' ? deterministicRunId(runId, childThreadId) : childThreadId;
182
+ }
151
183
  /** Children a node started that have not reported back yet. */
152
- function unsettledChildren(state, nodeId, threadId) {
153
- const children = state.pendingSpawns
154
- .filter((item) => item.nodeId === nodeId)
155
- .map((item) => item.childThreadId);
184
+ function unsettledChildren(state, nodeId, threadId, runId) {
185
+ const children = [];
186
+ for (const item of state.pendingSpawns) {
187
+ if (item.nodeId !== nodeId) {
188
+ continue;
189
+ }
190
+ const execution = item.execution === 'run' ? 'run' : 'thread';
191
+ children.push({
192
+ key: item.childThreadId,
193
+ target: childTarget(runId, item.childThreadId, execution),
194
+ execution,
195
+ close: item.close === 'wait' ? 'wait' : 'terminate',
196
+ });
197
+ }
156
198
  for (const map of state.pendingMaps) {
157
199
  if (map.nodeId !== nodeId) {
158
200
  continue;
159
201
  }
202
+ const execution = map.execution === 'run' ? 'run' : 'thread';
203
+ const close = map.close === 'wait' ? 'wait' : 'terminate';
160
204
  for (let index = 0; index < map.nextIndex; index++) {
161
- if (!(String(index) in map.outputs)) {
162
- children.push(mapChildThreadId(threadId, map, index));
205
+ if (String(index) in map.outputs) {
206
+ continue;
163
207
  }
208
+ const key = mapChildThreadId(threadId, map, index);
209
+ children.push({
210
+ key,
211
+ target: childTarget(runId, key, execution),
212
+ execution,
213
+ close,
214
+ });
164
215
  }
165
216
  }
166
217
  return children;
167
218
  }
168
219
  /**
169
220
  * Drops a node's pending work and cancels the children it leaves running. `settled` is the child
170
- * whose result is finishing the node, which must not be cancelled.
221
+ * whose result is finishing the node, which must not be cancelled. A `wait` child run stays
222
+ * pending until it settles, so the node does not finish ahead of that cancellation.
171
223
  */
172
- function withoutPendingWork(state, nodeId, threadId, settled = null) {
173
- const cancels = unsettledChildren(state, nodeId, threadId).filter((childThreadId) => childThreadId !== settled && !state.pendingCancels.includes(childThreadId));
224
+ function withoutPendingWork(state, nodeId, threadId, runId, settled = null) {
225
+ const children = unsettledChildren(state, nodeId, threadId, runId);
226
+ const cancels = children
227
+ .map((child) => child.target)
228
+ .filter((target) => target !== settled && !state.pendingCancels.includes(target));
229
+ const keptSpawns = new Set(children
230
+ .filter((child) => child.execution === 'run' && child.close === 'wait' && child.target !== settled)
231
+ .map((child) => child.key));
232
+ const keepMap = children.some((child) => child.execution === 'run' && child.close === 'wait' && child.target !== settled);
174
233
  return {
175
234
  ...state,
176
235
  pendingCancels: cancels.length === 0 ? state.pendingCancels : [...state.pendingCancels, ...cancels],
177
- pendingSpawns: state.pendingSpawns.filter((item) => item.nodeId !== nodeId),
178
- pendingMaps: state.pendingMaps.filter((item) => item.nodeId !== nodeId),
236
+ pendingSpawns: state.pendingSpawns.filter((item) => item.nodeId !== nodeId || keptSpawns.has(item.childThreadId)),
237
+ pendingMaps: state.pendingMaps.filter((item) => item.nodeId !== nodeId || keepMap),
179
238
  pendingSleeps: state.pendingSleeps.filter((item) => item.nodeId !== nodeId),
180
239
  pendingEffects: state.pendingEffects.filter((item) => item.nodeId !== nodeId),
181
240
  };
182
241
  }
183
- function stopNode(state, nodeId, threadId) {
242
+ function stopNode(state, nodeId, threadId, runId) {
184
243
  return {
185
- ...withoutPendingWork(state, nodeId, threadId),
244
+ ...withoutPendingWork(state, nodeId, threadId, runId),
186
245
  runningNodes: state.runningNodes.filter((id) => id !== nodeId),
187
246
  };
188
247
  }
189
248
  /** Drops a node's pending work and emits the event that durably finishes it. */
190
- function finishNode(state, nodeId, result, error, threadId, settled = null) {
249
+ function finishNode(state, nodeId, result, error, threadId, runId, settled = null) {
191
250
  const id = `finished_${nodeId}`;
192
251
  const event = {
193
252
  type: 'workflow.node.finished',
@@ -195,24 +254,25 @@ function finishNode(state, nodeId, result, error, threadId, settled = null) {
195
254
  threadId,
196
255
  };
197
256
  return {
198
- ...withoutPendingWork(state, nodeId, threadId, settled),
257
+ ...withoutPendingWork(state, nodeId, threadId, runId, settled),
199
258
  pendingEmits: [...state.pendingEmits.filter((item) => item.id !== id), { id, event }],
200
259
  };
201
260
  }
202
- function recordMapOutput(state, map, index, output, threadId) {
261
+ function recordMapOutput(state, map, index, output, threadId, runId) {
203
262
  if (String(index) in map.outputs) {
204
263
  return state;
205
264
  }
206
- const settled = mapChildThreadId(threadId, map, index);
265
+ const childThreadId = mapChildThreadId(threadId, map, index);
266
+ const settled = childTarget(runId, childThreadId, map.execution === 'run' ? 'run' : 'thread');
207
267
  const outputs = { ...map.outputs, [String(index)]: output };
208
268
  const size = utf8JsonBytes(outputs);
209
269
  if (size > map.limitBytes) {
210
270
  const error = new WorkflowValueTooLargeError(`Node ${map.nodeId} outputs`, size, map.limitBytes);
211
- return finishNode(state, map.nodeId, null, error.message, threadId, settled);
271
+ return finishNode(state, map.nodeId, null, error.message, threadId, runId, settled);
212
272
  }
213
273
  if (Object.keys(outputs).length === map.items.length) {
214
274
  const ordered = map.items.map((_, i) => outputs[String(i)] ?? null);
215
- return finishNode(state, map.nodeId, ordered, null, threadId, settled);
275
+ return finishNode(state, map.nodeId, ordered, null, threadId, runId, settled);
216
276
  }
217
277
  const nextIndex = Math.min(map.items.length, map.nextIndex + 1);
218
278
  return {
@@ -298,7 +358,7 @@ export const workflowThread = workflowModule.thread({
298
358
  }
299
359
  const failed = Predicate.isString(error) && error.length > 0;
300
360
  return {
301
- ...stopNode(state, nodeId, ctx.threadId),
361
+ ...stopNode(state, nodeId, ctx.threadId, ctx.runId),
302
362
  nodes: {
303
363
  ...state.nodes,
304
364
  [nodeId]: {
@@ -317,7 +377,7 @@ export const workflowThread = workflowModule.thread({
317
377
  case 'workflow.node.skipped': {
318
378
  const { nodeId, reason, cause } = event.payload;
319
379
  return {
320
- ...stopNode(state, nodeId, ctx.threadId),
380
+ ...stopNode(state, nodeId, ctx.threadId, ctx.runId),
321
381
  nodes: {
322
382
  ...state.nodes,
323
383
  [nodeId]: {
@@ -340,7 +400,10 @@ export const workflowThread = workflowModule.thread({
340
400
  ...state,
341
401
  pendingSpawns: [
342
402
  ...state.pendingSpawns.filter((item) => item.nodeId !== nodeId),
343
- event.payload,
403
+ {
404
+ ...event.payload,
405
+ ...childMode(event.payload.execution, event.payload.close),
406
+ },
344
407
  ],
345
408
  };
346
409
  }
@@ -355,6 +418,7 @@ export const workflowThread = workflowModule.thread({
355
418
  ...state.pendingMaps.filter((item) => item.nodeId !== nodeId),
356
419
  {
357
420
  ...event.payload,
421
+ ...childMode(event.payload.execution, event.payload.close),
358
422
  nextIndex: Math.min(event.payload.concurrency, event.payload.items.length),
359
423
  outputs: {},
360
424
  },
@@ -408,14 +472,14 @@ export const workflowThread = workflowModule.thread({
408
472
  }
409
473
  const effectId = event.payload.effectId;
410
474
  const nodeId = Predicate.isString(effectId)
411
- ? nodeIdForEffect(state, ctx.threadId, effectId)
475
+ ? nodeIdForEffect(state, ctx.threadId, ctx.runId, effectId)
412
476
  : null;
413
477
  if (!nodeId) {
414
478
  return state;
415
479
  }
416
480
  const message = `Node ${nodeId} failed: ${error}`;
417
481
  return {
418
- ...finishNode(stopNode(state, nodeId, ctx.threadId), nodeId, null, message, ctx.threadId),
482
+ ...finishNode(stopNode(state, nodeId, ctx.threadId, ctx.runId), nodeId, null, message, ctx.threadId, ctx.runId),
419
483
  nodes: {
420
484
  ...state.nodes,
421
485
  [nodeId]: {
@@ -439,7 +503,7 @@ export const workflowThread = workflowModule.thread({
439
503
  const { result, error } = waitOutcome(event.payload.event, tag, { waited: true });
440
504
  const map = state.pendingMaps.find((item) => item.nodeId === nodeId);
441
505
  if (error === null && map && Predicate.isNumber(tag.index)) {
442
- return recordMapOutput(state, map, tag.index, result, ctx.threadId);
506
+ return recordMapOutput(state, map, tag.index, result, ctx.threadId, ctx.runId);
443
507
  }
444
508
  const node = state.nodes[nodeId];
445
509
  if (error === null && node && Predicate.isNumber(tag.loopIndex)) {
@@ -454,10 +518,14 @@ export const workflowThread = workflowModule.thread({
454
518
  }
455
519
  const satisfied = event.payload.event;
456
520
  const satisfiedPayload = Predicate.isObject(satisfied) ? satisfied.payload : undefined;
457
- const settled = Predicate.isObject(satisfiedPayload) && Predicate.isString(satisfiedPayload.threadId)
458
- ? satisfiedPayload.threadId
521
+ const settled = Predicate.isObject(satisfiedPayload)
522
+ ? Predicate.isString(satisfiedPayload.runId)
523
+ ? satisfiedPayload.runId
524
+ : Predicate.isString(satisfiedPayload.threadId)
525
+ ? satisfiedPayload.threadId
526
+ : null
459
527
  : null;
460
- return finishNode(state, nodeId, result, error, ctx.threadId, settled);
528
+ return finishNode(state, nodeId, result, error, ctx.threadId, ctx.runId, settled);
461
529
  }
462
530
  default:
463
531
  return state;
@@ -468,14 +536,14 @@ export const workflowThread = workflowModule.thread({
468
536
  if (state.needsSchedule) {
469
537
  effects.push(scheduleInvocation(state));
470
538
  }
471
- for (const item of nodeEffects(state, ctx.threadId)) {
539
+ for (const item of nodeEffects(state, ctx.threadId, ctx.runId)) {
472
540
  effects.push(item.effect);
473
541
  }
474
542
  for (const emitReq of state.pendingEmits) {
475
543
  effects.push(emit(emitReq.event));
476
544
  }
477
- for (const childThreadId of state.pendingCancels) {
478
- effects.push(cancel(childThreadId));
545
+ for (const childId of state.pendingCancels) {
546
+ effects.push(childId.startsWith('run_') ? cancelRun(childId, `cancel_${childId}`) : cancel(childId));
479
547
  }
480
548
  if (state.status === 'failed') {
481
549
  effects.push(fail(state.error ?? 'Workflow execution failed'));