flowcraft 2.2.0 → 2.3.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 (147) hide show
  1. package/README.md +40 -34
  2. package/dist/analysis.d.ts +3 -1
  3. package/dist/chunk-33NO4PUJ.js +74 -0
  4. package/dist/chunk-33NO4PUJ.js.map +1 -0
  5. package/dist/chunk-5KKSQWSC.js +90 -0
  6. package/dist/chunk-5KKSQWSC.js.map +1 -0
  7. package/dist/{chunk-QLGJUDQF.js → chunk-6INWPSZT.js} +6 -6
  8. package/dist/chunk-6INWPSZT.js.map +1 -0
  9. package/dist/chunk-BC4G7OM6.js +42 -0
  10. package/dist/chunk-BC4G7OM6.js.map +1 -0
  11. package/dist/chunk-BCRWXTWX.js +21 -0
  12. package/dist/chunk-BCRWXTWX.js.map +1 -0
  13. package/dist/{chunk-ZCHFZBGL.js → chunk-C4HYIJI3.js} +120 -5
  14. package/dist/chunk-C4HYIJI3.js.map +1 -0
  15. package/dist/chunk-CD3Q4N6V.js +13 -0
  16. package/dist/chunk-CD3Q4N6V.js.map +1 -0
  17. package/dist/chunk-CD4FUZOJ.js +114 -0
  18. package/dist/chunk-CD4FUZOJ.js.map +1 -0
  19. package/dist/chunk-CY755I7I.js +25 -0
  20. package/dist/chunk-CY755I7I.js.map +1 -0
  21. package/dist/chunk-DL7KVYZF.js +39 -0
  22. package/dist/chunk-DL7KVYZF.js.map +1 -0
  23. package/dist/chunk-FRKO3WX4.js +32 -0
  24. package/dist/chunk-FRKO3WX4.js.map +1 -0
  25. package/dist/chunk-G53CSLBF.js +54 -0
  26. package/dist/chunk-G53CSLBF.js.map +1 -0
  27. package/dist/chunk-G5BGBPFP.js +172 -0
  28. package/dist/chunk-G5BGBPFP.js.map +1 -0
  29. package/dist/chunk-HAZ26F3P.js +98 -0
  30. package/dist/chunk-HAZ26F3P.js.map +1 -0
  31. package/dist/chunk-IB2BISIC.js +446 -0
  32. package/dist/chunk-IB2BISIC.js.map +1 -0
  33. package/dist/{chunk-U5V5O5MN.js → chunk-LNK7LZER.js} +5 -3
  34. package/dist/chunk-LNK7LZER.js.map +1 -0
  35. package/dist/chunk-MCGK3FXQ.js +143 -0
  36. package/dist/chunk-MCGK3FXQ.js.map +1 -0
  37. package/dist/chunk-MUYLRTSR.js +82 -0
  38. package/dist/chunk-MUYLRTSR.js.map +1 -0
  39. package/dist/chunk-NVJ3ZO3P.js +3 -0
  40. package/dist/{chunk-HMR2GEGE.js.map → chunk-NVJ3ZO3P.js.map} +1 -1
  41. package/dist/chunk-NVLZFLYM.js +3 -0
  42. package/dist/chunk-NVLZFLYM.js.map +1 -0
  43. package/dist/chunk-ONH7PIJZ.js +300 -0
  44. package/dist/chunk-ONH7PIJZ.js.map +1 -0
  45. package/dist/chunk-QNYXQKFW.js +25 -0
  46. package/dist/chunk-QNYXQKFW.js.map +1 -0
  47. package/dist/chunk-RM677CNU.js +52 -0
  48. package/dist/chunk-RM677CNU.js.map +1 -0
  49. package/dist/chunk-WWGFIYKW.js +47 -0
  50. package/dist/chunk-WWGFIYKW.js.map +1 -0
  51. package/dist/chunk-XNRIM27H.js +76 -0
  52. package/dist/chunk-XNRIM27H.js.map +1 -0
  53. package/dist/container-factory.d.ts +17 -0
  54. package/dist/container-factory.js +13 -0
  55. package/dist/container-factory.js.map +1 -0
  56. package/dist/container.d.ts +23 -0
  57. package/dist/container.js +3 -0
  58. package/dist/container.js.map +1 -0
  59. package/dist/context.d.ts +3 -1
  60. package/dist/errors.d.ts +18 -17
  61. package/dist/errors.js +1 -1
  62. package/dist/evaluator.d.ts +3 -1
  63. package/dist/flow.d.ts +12 -2
  64. package/dist/flow.js +2 -2
  65. package/dist/index.d.ts +7 -8
  66. package/dist/index.js +26 -14
  67. package/dist/linter.d.ts +3 -1
  68. package/dist/logger.d.ts +3 -1
  69. package/dist/node.d.ts +3 -1
  70. package/dist/node.js +1 -1
  71. package/dist/nodes/batch-gather.d.ts +9 -0
  72. package/dist/nodes/batch-gather.js +4 -0
  73. package/dist/nodes/batch-gather.js.map +1 -0
  74. package/dist/nodes/batch-scatter.d.ts +9 -0
  75. package/dist/nodes/batch-scatter.js +4 -0
  76. package/dist/nodes/batch-scatter.js.map +1 -0
  77. package/dist/nodes/subflow.d.ts +9 -0
  78. package/dist/nodes/subflow.js +10 -0
  79. package/dist/nodes/subflow.js.map +1 -0
  80. package/dist/nodes/wait.d.ts +9 -0
  81. package/dist/nodes/wait.js +4 -0
  82. package/dist/nodes/wait.js.map +1 -0
  83. package/dist/runtime/adapter.d.ts +3 -5
  84. package/dist/runtime/adapter.js +19 -9
  85. package/dist/runtime/execution-context.d.ts +3 -0
  86. package/dist/runtime/execution-context.js +6 -0
  87. package/dist/runtime/execution-context.js.map +1 -0
  88. package/dist/runtime/executors.d.ts +3 -26
  89. package/dist/runtime/executors.js +2 -2
  90. package/dist/runtime/index.d.ts +5 -7
  91. package/dist/runtime/index.js +21 -10
  92. package/dist/runtime/node-executor-factory.d.ts +12 -0
  93. package/dist/runtime/node-executor-factory.js +6 -0
  94. package/dist/runtime/node-executor-factory.js.map +1 -0
  95. package/dist/runtime/orchestrator.d.ts +9 -0
  96. package/dist/runtime/orchestrator.js +8 -0
  97. package/dist/runtime/orchestrator.js.map +1 -0
  98. package/dist/runtime/orchestrators/step-by-step.d.ts +16 -0
  99. package/dist/runtime/orchestrators/step-by-step.js +5 -0
  100. package/dist/runtime/orchestrators/step-by-step.js.map +1 -0
  101. package/dist/runtime/orchestrators/utils.d.ts +35 -0
  102. package/dist/runtime/orchestrators/utils.js +4 -0
  103. package/dist/runtime/orchestrators/utils.js.map +1 -0
  104. package/dist/runtime/runtime.d.ts +3 -41
  105. package/dist/runtime/runtime.js +18 -8
  106. package/dist/runtime/state.d.ts +3 -21
  107. package/dist/runtime/state.js +2 -1
  108. package/dist/runtime/traverser.d.ts +3 -26
  109. package/dist/runtime/traverser.js +1 -2
  110. package/dist/runtime/types.d.ts +3 -16
  111. package/dist/runtime/types.js +1 -1
  112. package/dist/runtime/workflow-logic-handler.d.ts +17 -0
  113. package/dist/runtime/workflow-logic-handler.js +5 -0
  114. package/dist/runtime/workflow-logic-handler.js.map +1 -0
  115. package/dist/sanitizer.d.ts +3 -1
  116. package/dist/serializer.d.ts +3 -1
  117. package/dist/testing/event-logger.d.ts +63 -0
  118. package/dist/testing/event-logger.js +3 -0
  119. package/dist/testing/event-logger.js.map +1 -0
  120. package/dist/testing/index.d.ts +6 -0
  121. package/dist/testing/index.js +31 -0
  122. package/dist/testing/index.js.map +1 -0
  123. package/dist/testing/run-with-trace.d.ts +38 -0
  124. package/dist/testing/run-with-trace.js +29 -0
  125. package/dist/testing/run-with-trace.js.map +1 -0
  126. package/dist/testing/stepper.d.ts +79 -0
  127. package/dist/testing/stepper.js +11 -0
  128. package/dist/testing/stepper.js.map +1 -0
  129. package/dist/types-ezHUBdpL.d.ts +564 -0
  130. package/dist/types.d.ts +3 -1
  131. package/package.json +55 -51
  132. package/LICENSE +0 -21
  133. package/dist/chunk-5ZXV3R5D.js +0 -28
  134. package/dist/chunk-5ZXV3R5D.js.map +0 -1
  135. package/dist/chunk-GEKDR2SS.js +0 -201
  136. package/dist/chunk-GEKDR2SS.js.map +0 -1
  137. package/dist/chunk-HMR2GEGE.js +0 -3
  138. package/dist/chunk-M2FRTT2K.js +0 -144
  139. package/dist/chunk-M2FRTT2K.js.map +0 -1
  140. package/dist/chunk-OTS5YJ3S.js +0 -494
  141. package/dist/chunk-OTS5YJ3S.js.map +0 -1
  142. package/dist/chunk-QLGJUDQF.js.map +0 -1
  143. package/dist/chunk-U5V5O5MN.js.map +0 -1
  144. package/dist/chunk-VSGQDLBF.js +0 -61
  145. package/dist/chunk-VSGQDLBF.js.map +0 -1
  146. package/dist/chunk-ZCHFZBGL.js.map +0 -1
  147. package/dist/types-CsTeXTiA.d.ts +0 -222
@@ -1,6 +1,7 @@
1
- import { isNodeClass } from './chunk-U5V5O5MN.js';
1
+ import { isNodeClass } from './chunk-LNK7LZER.js';
2
2
 
3
3
  // src/flow.ts
4
+ var hashCounter = 0;
4
5
  function _hashFunction(fn) {
5
6
  const source = fn.toString();
6
7
  let hash = 0;
@@ -9,19 +10,21 @@ function _hashFunction(fn) {
9
10
  hash = (hash << 5) - hash + char;
10
11
  hash = hash & hash;
11
12
  }
12
- return Math.abs(hash).toString(16);
13
+ return (Math.abs(hash) + hashCounter++).toString(16);
13
14
  }
14
15
  var Flow = class {
15
16
  blueprint;
16
17
  functionRegistry;
17
18
  loopControllerIds;
18
19
  loopDefinitions;
20
+ batchDefinitions;
19
21
  cycleEntryPoints;
20
22
  constructor(id) {
21
23
  this.blueprint = { id, nodes: [], edges: [] };
22
24
  this.functionRegistry = /* @__PURE__ */ new Map();
23
25
  this.loopControllerIds = /* @__PURE__ */ new Map();
24
26
  this.loopDefinitions = [];
27
+ this.batchDefinitions = [];
25
28
  this.cycleEntryPoints = /* @__PURE__ */ new Map();
26
29
  }
27
30
  node(id, implementation, options) {
@@ -56,6 +59,7 @@ var Flow = class {
56
59
  const { inputKey, outputKey } = options;
57
60
  const scatterId = `${id}_scatter`;
58
61
  const gatherId = `${id}_gather`;
62
+ this.batchDefinitions.push({ id, scatterId, gatherId });
59
63
  let workerUsesKey;
60
64
  if (isNodeClass(worker)) {
61
65
  workerUsesKey = worker.name && worker.name !== "BaseNode" ? worker.name : `class_batch_worker_${_hashFunction(worker)}`;
@@ -82,6 +86,16 @@ var Flow = class {
82
86
  this.edge(scatterId, gatherId);
83
87
  return this;
84
88
  }
89
+ /**
90
+ * Creates a wait node that pauses workflow execution for external input.
91
+ * @param id A unique identifier for the wait node.
92
+ * @param options Optional configuration for the wait node.
93
+ */
94
+ wait(id, options) {
95
+ const nodeDef = { id, uses: "wait", ...options };
96
+ this.blueprint.nodes?.push(nodeDef);
97
+ return this;
98
+ }
85
99
  /**
86
100
  * Creates a loop pattern in the workflow graph.
87
101
  * @param id A unique identifier for the loop construct.
@@ -94,7 +108,7 @@ var Flow = class {
94
108
  const { startNodeId, endNodeId, condition } = options;
95
109
  const controllerId = `${id}-loop`;
96
110
  this.loopControllerIds.set(id, controllerId);
97
- this.loopDefinitions.push({ id, startNodeId, endNodeId });
111
+ this.loopDefinitions.push({ id, startNodeId, endNodeId, condition });
98
112
  this.blueprint.nodes?.push({
99
113
  id: controllerId,
100
114
  uses: "loop-controller",
@@ -131,6 +145,35 @@ var Flow = class {
131
145
  if (!this.blueprint.nodes || this.blueprint.nodes.length === 0) {
132
146
  throw new Error("Cannot build a blueprint with no nodes.");
133
147
  }
148
+ const finalEdges = [];
149
+ const processedOriginalEdges = /* @__PURE__ */ new Set();
150
+ const allOriginalEdges = this.blueprint.edges || [];
151
+ for (const loopDef of this.loopDefinitions) {
152
+ const controllerId = this.getLoopControllerId(loopDef.id);
153
+ const edgesToRewire = allOriginalEdges.filter((e) => e.source === loopDef.endNodeId && e.target !== controllerId);
154
+ for (const edge of edgesToRewire) {
155
+ finalEdges.push({ ...edge, source: controllerId, action: edge.action || "break" });
156
+ processedOriginalEdges.add(edge);
157
+ }
158
+ }
159
+ for (const batchDef of this.batchDefinitions) {
160
+ const incomingEdges = allOriginalEdges.filter((e) => e.target === batchDef.id);
161
+ for (const edge of incomingEdges) {
162
+ finalEdges.push({ ...edge, target: batchDef.scatterId });
163
+ processedOriginalEdges.add(edge);
164
+ }
165
+ const outgoingEdges = allOriginalEdges.filter((e) => e.source === batchDef.id);
166
+ for (const edge of outgoingEdges) {
167
+ finalEdges.push({ ...edge, source: batchDef.gatherId });
168
+ processedOriginalEdges.add(edge);
169
+ }
170
+ }
171
+ for (const edge of allOriginalEdges) {
172
+ if (!processedOriginalEdges.has(edge)) {
173
+ finalEdges.push(edge);
174
+ }
175
+ }
176
+ this.blueprint.edges = finalEdges;
134
177
  for (const loopDef of this.loopDefinitions) {
135
178
  const startNode = this.blueprint.nodes?.find((n) => n.id === loopDef.startNodeId);
136
179
  const endNode = this.blueprint.nodes?.find((n) => n.id === loopDef.endNodeId);
@@ -154,11 +197,83 @@ var Flow = class {
154
197
  getFunctionRegistry() {
155
198
  return this.functionRegistry;
156
199
  }
200
+ toGraphRepresentation() {
201
+ const blueprint = this.toBlueprint();
202
+ const uiNodes = [];
203
+ const uiEdges = [];
204
+ const ignoredNodeIds = /* @__PURE__ */ new Set();
205
+ for (const loopDef of this.loopDefinitions) {
206
+ const controllerId = this.loopControllerIds.get(loopDef.id);
207
+ if (!controllerId) continue;
208
+ ignoredNodeIds.add(controllerId);
209
+ uiEdges.push({
210
+ source: loopDef.endNodeId,
211
+ target: loopDef.startNodeId,
212
+ data: {
213
+ isLoopback: true,
214
+ condition: loopDef.condition,
215
+ label: `continue if: ${loopDef.condition}`
216
+ }
217
+ });
218
+ const breakEdges = blueprint.edges.filter((edge) => edge.source === controllerId && edge.action === "break");
219
+ for (const breakEdge of breakEdges) {
220
+ uiEdges.push({
221
+ ...breakEdge,
222
+ source: loopDef.endNodeId
223
+ });
224
+ }
225
+ }
226
+ const scatterNodes = blueprint.nodes.filter((n) => n.uses === "batch-scatter");
227
+ for (const scatterNode of scatterNodes) {
228
+ const gatherNodeId = scatterNode.params?.gatherNodeId;
229
+ if (!gatherNodeId) continue;
230
+ ignoredNodeIds.add(scatterNode.id);
231
+ ignoredNodeIds.add(gatherNodeId);
232
+ const batchId = scatterNode.id.replace("_scatter", "");
233
+ const gatherNode = blueprint.nodes.find((n) => n.id === gatherNodeId);
234
+ uiNodes.push({
235
+ id: batchId,
236
+ uses: scatterNode.params?.workerUsesKey,
237
+ type: "batch-worker",
238
+ data: {
239
+ label: `Batch: ${batchId}`,
240
+ isBatchPlaceholder: true,
241
+ workerUsesKey: scatterNode.params?.workerUsesKey,
242
+ inputKey: scatterNode.inputs,
243
+ outputKey: gatherNode?.params?.outputKey
244
+ }
245
+ });
246
+ const incomingEdges = blueprint.edges.filter((e) => e.target === scatterNode.id);
247
+ for (const edge of incomingEdges) {
248
+ uiEdges.push({ ...edge, target: batchId });
249
+ }
250
+ const outgoingEdges = blueprint.edges.filter((e) => e.source === gatherNodeId);
251
+ for (const edge of outgoingEdges) {
252
+ uiEdges.push({ ...edge, source: batchId });
253
+ }
254
+ }
255
+ for (const node of blueprint.nodes) {
256
+ if (!ignoredNodeIds.has(node.id)) {
257
+ uiNodes.push(node);
258
+ }
259
+ }
260
+ for (const edge of blueprint.edges) {
261
+ if (!ignoredNodeIds.has(edge.source) && !ignoredNodeIds.has(edge.target)) {
262
+ const alreadyAdded = uiEdges.some(
263
+ (e) => e.source === edge.source && e.target === edge.target && e.action === edge.action
264
+ );
265
+ if (!alreadyAdded) {
266
+ uiEdges.push(edge);
267
+ }
268
+ }
269
+ }
270
+ return { nodes: uiNodes, edges: uiEdges };
271
+ }
157
272
  };
158
273
  function createFlow(id) {
159
274
  return new Flow(id);
160
275
  }
161
276
 
162
277
  export { Flow, createFlow };
163
- //# sourceMappingURL=chunk-ZCHFZBGL.js.map
164
- //# sourceMappingURL=chunk-ZCHFZBGL.js.map
278
+ //# sourceMappingURL=chunk-C4HYIJI3.js.map
279
+ //# sourceMappingURL=chunk-C4HYIJI3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/flow.ts"],"names":[],"mappings":"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","file":"chunk-C4HYIJI3.js","sourcesContent":["import { isNodeClass } from './node'\nimport type { EdgeDefinition, NodeClass, NodeDefinition, NodeFunction, UIGraph, WorkflowBlueprint } from './types'\n\n/**\n * Generates a deterministic hash for a function based on its source code and a unique counter.\n */\nlet hashCounter = 0\nfunction _hashFunction(fn: NodeFunction<any, any, any, any, any> | NodeClass<any, any, any, any, any>): string {\n\tconst source = fn.toString()\n\tlet hash = 0\n\tfor (let i = 0; i < source.length; i++) {\n\t\tconst char = source.charCodeAt(i)\n\t\thash = (hash << 5) - hash + char\n\t\thash = hash & hash // Convert to 32-bit integer\n\t}\n\t// Add counter to ensure uniqueness even for identical functions\n\treturn (Math.abs(hash) + hashCounter++).toString(16)\n}\n\n/**\n * A fluent API for programmatically constructing a WorkflowBlueprint.\n */\nexport class Flow<\n\tTContext extends Record<string, any> = Record<string, any>,\n\tTDependencies extends Record<string, any> = Record<string, any>,\n> {\n\tprivate blueprint: Partial<WorkflowBlueprint>\n\tprivate functionRegistry: Map<string, NodeFunction | NodeClass>\n\tprivate loopControllerIds: Map<string, string>\n\tprivate loopDefinitions: Array<{\n\t\tid: string\n\t\tstartNodeId: string\n\t\tendNodeId: string\n\t\tcondition: string\n\t}>\n\tprivate batchDefinitions: Array<{\n\t\tid: string\n\t\tscatterId: string\n\t\tgatherId: string\n\t}>\n\tprivate cycleEntryPoints: Map<string, string>\n\n\tconstructor(id: string) {\n\t\tthis.blueprint = { id, nodes: [], edges: [] }\n\t\tthis.functionRegistry = new Map()\n\t\tthis.loopControllerIds = new Map()\n\t\tthis.loopDefinitions = []\n\t\tthis.batchDefinitions = []\n\t\tthis.cycleEntryPoints = new Map()\n\t}\n\n\tnode<TInput = any, TOutput = any, TAction extends string = string>(\n\t\tid: string,\n\t\timplementation:\n\t\t\t| NodeFunction<TContext, TDependencies, TInput, TOutput, TAction>\n\t\t\t| NodeClass<TContext, TDependencies, TInput, TOutput, TAction>,\n\t\toptions?: Omit<NodeDefinition, 'id' | 'uses'>,\n\t): this {\n\t\tlet usesKey: string\n\n\t\tif (isNodeClass(implementation)) {\n\t\t\tusesKey =\n\t\t\t\timplementation.name && implementation.name !== 'BaseNode'\n\t\t\t\t\t? implementation.name\n\t\t\t\t\t: `class_${_hashFunction(implementation)}`\n\t\t\tthis.functionRegistry.set(usesKey, implementation)\n\t\t} else {\n\t\t\tusesKey = `fn_${_hashFunction(implementation)}`\n\t\t\tthis.functionRegistry.set(usesKey, implementation as unknown as NodeFunction)\n\t\t}\n\n\t\tconst nodeDef: NodeDefinition = { id, uses: usesKey, ...options }\n\t\tthis.blueprint.nodes?.push(nodeDef)\n\t\treturn this\n\t}\n\n\tedge(source: string, target: string, options?: Omit<EdgeDefinition, 'source' | 'target'>): this {\n\t\tconst edgeDef: EdgeDefinition = { source, target, ...options }\n\t\tthis.blueprint.edges?.push(edgeDef)\n\t\treturn this\n\t}\n\n\t/**\n\t * Creates a batch processing pattern.\n\t * It takes an input array, runs a worker node on each item in parallel, and gathers the results.\n\t * This method augments the Flow's TContext with a new key for the output array.\n\t *\n\t * @param id The base ID for this batch operation.\n\t * @param worker The node implementation to run on each item.\n\t * @param options Configuration for the batch operation.\n\t * @returns The Flow instance with an updated context type for chaining.\n\t */\n\tbatch<TWorkerInput, TWorkerOutput, TWorkerAction extends string, TOutputKey extends string>(\n\t\tid: string,\n\t\tworker:\n\t\t\t| NodeFunction<TContext, TDependencies, TWorkerInput, TWorkerOutput, TWorkerAction>\n\t\t\t| NodeClass<TContext, TDependencies, TWorkerInput, TWorkerOutput, TWorkerAction>,\n\t\toptions: {\n\t\t\t/** The key in the context that holds the input array for the batch. */\n\t\t\tinputKey: keyof TContext\n\t\t\t/** The key in the context where the array of results will be stored. */\n\t\t\toutputKey: TOutputKey\n\t\t\t/** The number of items to process in each chunk to limit memory usage. */\n\t\t\tchunkSize?: number\n\t\t},\n\t): Flow<TContext & { [K in TOutputKey]: TWorkerOutput[] }, TDependencies> {\n\t\tconst { inputKey, outputKey } = options\n\t\tconst scatterId = `${id}_scatter`\n\t\tconst gatherId = `${id}_gather`\n\n\t\tthis.batchDefinitions.push({ id, scatterId, gatherId })\n\n\t\t// register worker implementation under a unique key.\n\t\tlet workerUsesKey: string\n\t\tif (isNodeClass(worker)) {\n\t\t\tworkerUsesKey =\n\t\t\t\tworker.name && worker.name !== 'BaseNode' ? worker.name : `class_batch_worker_${_hashFunction(worker)}`\n\t\t\tthis.functionRegistry.set(workerUsesKey, worker)\n\t\t} else {\n\t\t\tworkerUsesKey = `fn_batch_worker_${_hashFunction(worker)}`\n\t\t\tthis.functionRegistry.set(workerUsesKey, worker as unknown as NodeFunction)\n\t\t}\n\n\t\t// scatter node: takes an array and dynamically schedules worker nodes\n\t\tthis.blueprint.nodes?.push({\n\t\t\tid: scatterId,\n\t\t\tuses: 'batch-scatter', // built-in\n\t\t\tinputs: inputKey as string,\n\t\t\tparams: { workerUsesKey, outputKey: outputKey as string, gatherNodeId: gatherId, chunkSize: options.chunkSize },\n\t\t})\n\n\t\t// gather node: waits for all workers to finish and collects the results\n\t\tthis.blueprint.nodes?.push({\n\t\t\tid: gatherId,\n\t\t\tuses: 'batch-gather', // built-in\n\t\t\tparams: { outputKey, gatherNodeId: gatherId },\n\t\t\tconfig: { joinStrategy: 'all' }, // important: must wait for all scattered jobs\n\t\t})\n\n\t\t// edge to connect scatter and gather nodes, orchestrator will manage dynamic workers\n\t\tthis.edge(scatterId, gatherId)\n\n\t\treturn this as unknown as Flow<TContext & { [K in TOutputKey]: TWorkerOutput[] }, TDependencies>\n\t}\n\n\t/**\n\t * Creates a wait node that pauses workflow execution for external input.\n\t * @param id A unique identifier for the wait node.\n\t * @param options Optional configuration for the wait node.\n\t */\n\twait(id: string, options?: Omit<NodeDefinition, 'id' | 'uses'>): this {\n\t\tconst nodeDef: NodeDefinition = { id, uses: 'wait', ...options }\n\t\tthis.blueprint.nodes?.push(nodeDef)\n\t\treturn this\n\t}\n\n\t/**\n\t * Creates a loop pattern in the workflow graph.\n\t * @param id A unique identifier for the loop construct.\n\t * @param options Defines the start, end, and continuation condition of the loop.\n\t * @param options.startNodeId The ID of the first node inside the loop body.\n\t * @param options.endNodeId The ID of the last node inside the loop body.\n\t * @param options.condition An expression that, if true, causes the loop to run again.\n\t */\n\tloop(\n\t\tid: string,\n\t\toptions: {\n\t\t\t/** The ID of the first node inside the loop body. */\n\t\t\tstartNodeId: string\n\t\t\t/** The ID of the last node inside the loop body. */\n\t\t\tendNodeId: string\n\t\t\t/** An expression that, if true, causes the loop to run again. */\n\t\t\tcondition: string\n\t\t},\n\t): this {\n\t\tconst { startNodeId, endNodeId, condition } = options\n\t\tconst controllerId = `${id}-loop`\n\n\t\tthis.loopControllerIds.set(id, controllerId)\n\n\t\tthis.loopDefinitions.push({ id, startNodeId, endNodeId, condition })\n\n\t\t// controller node: evaluates the loop condition\n\t\tthis.blueprint.nodes?.push({\n\t\t\tid: controllerId,\n\t\t\tuses: 'loop-controller', // built-in\n\t\t\tparams: { condition },\n\t\t\tconfig: { joinStrategy: 'any' }, // to allow re-execution on each loop iteration\n\t\t})\n\n\t\tthis.edge(endNodeId, controllerId)\n\n\t\tthis.edge(controllerId, startNodeId, {\n\t\t\taction: 'continue',\n\t\t\ttransform: `context.${endNodeId}`, // pass the end node's value to the start node\n\t\t})\n\n\t\treturn this\n\t}\n\n\tgetLoopControllerId(id: string): string {\n\t\tconst controllerId = this.loopControllerIds.get(id)\n\t\tif (!controllerId) {\n\t\t\tthrow new Error(`Loop with id '${id}' not found. Ensure you have defined it using the .loop() method.`)\n\t\t}\n\t\treturn controllerId\n\t}\n\n\t/**\n\t * Sets the preferred entry point for a cycle in non-DAG workflows.\n\t * This helps remove ambiguity when the runtime needs to choose a starting node for cycles.\n\t * @param nodeId The ID of the node to use as the entry point for cycles containing this node.\n\t */\n\tsetCycleEntryPoint(nodeId: string): this {\n\t\tthis.cycleEntryPoints.set(nodeId, nodeId)\n\t\treturn this\n\t}\n\n\ttoBlueprint(): WorkflowBlueprint {\n\t\tif (!this.blueprint.nodes || this.blueprint.nodes.length === 0) {\n\t\t\tthrow new Error('Cannot build a blueprint with no nodes.')\n\t\t}\n\n\t\tconst finalEdges: EdgeDefinition[] = []\n\t\tconst processedOriginalEdges = new Set<EdgeDefinition>()\n\t\tconst allOriginalEdges = this.blueprint.edges || []\n\n\t\t// loop edge re-wiring\n\t\tfor (const loopDef of this.loopDefinitions) {\n\t\t\tconst controllerId = this.getLoopControllerId(loopDef.id)\n\t\t\tconst edgesToRewire = allOriginalEdges.filter((e) => e.source === loopDef.endNodeId && e.target !== controllerId)\n\t\t\tfor (const edge of edgesToRewire) {\n\t\t\t\tfinalEdges.push({ ...edge, source: controllerId, action: edge.action || 'break' })\n\t\t\t\tprocessedOriginalEdges.add(edge)\n\t\t\t}\n\t\t}\n\n\t\t// batch edge re-wiring\n\t\tfor (const batchDef of this.batchDefinitions) {\n\t\t\tconst incomingEdges = allOriginalEdges.filter((e) => e.target === batchDef.id)\n\t\t\tfor (const edge of incomingEdges) {\n\t\t\t\tfinalEdges.push({ ...edge, target: batchDef.scatterId })\n\t\t\t\tprocessedOriginalEdges.add(edge)\n\t\t\t}\n\n\t\t\tconst outgoingEdges = allOriginalEdges.filter((e) => e.source === batchDef.id)\n\t\t\tfor (const edge of outgoingEdges) {\n\t\t\t\tfinalEdges.push({ ...edge, source: batchDef.gatherId })\n\t\t\t\tprocessedOriginalEdges.add(edge)\n\t\t\t}\n\t\t}\n\n\t\t// all remaining edges\n\t\tfor (const edge of allOriginalEdges) {\n\t\t\tif (!processedOriginalEdges.has(edge)) {\n\t\t\t\tfinalEdges.push(edge)\n\t\t\t}\n\t\t}\n\t\tthis.blueprint.edges = finalEdges\n\n\t\tfor (const loopDef of this.loopDefinitions) {\n\t\t\tconst startNode = this.blueprint.nodes?.find((n) => n.id === loopDef.startNodeId)\n\t\t\tconst endNode = this.blueprint.nodes?.find((n) => n.id === loopDef.endNodeId)\n\n\t\t\tif (!startNode) {\n\t\t\t\tthrow new Error(`Loop '${loopDef.id}' references non-existent start node '${loopDef.startNodeId}'.`)\n\t\t\t}\n\t\t\tif (!endNode) {\n\t\t\t\tthrow new Error(`Loop '${loopDef.id}' references non-existent end node '${loopDef.endNodeId}'.`)\n\t\t\t}\n\n\t\t\tstartNode.config = { ...startNode.config, joinStrategy: 'any' }\n\t\t\tendNode.config = { ...endNode.config, joinStrategy: 'any' }\n\t\t}\n\n\t\tif (this.cycleEntryPoints.size > 0) {\n\t\t\tthis.blueprint.metadata = {\n\t\t\t\t...this.blueprint.metadata,\n\t\t\t\tcycleEntryPoints: Array.from(this.cycleEntryPoints.keys()),\n\t\t\t}\n\t\t}\n\n\t\treturn this.blueprint as WorkflowBlueprint\n\t}\n\n\tgetFunctionRegistry() {\n\t\treturn this.functionRegistry\n\t}\n\n\ttoGraphRepresentation(): UIGraph {\n\t\tconst blueprint = this.toBlueprint()\n\t\tconst uiNodes: UIGraph['nodes'] = []\n\t\tconst uiEdges: UIGraph['edges'] = []\n\n\t\tconst ignoredNodeIds = new Set<string>()\n\n\t\t// replace loop-controllers with direct, cyclical edges\n\t\tfor (const loopDef of this.loopDefinitions) {\n\t\t\tconst controllerId = this.loopControllerIds.get(loopDef.id)\n\t\t\tif (!controllerId) continue\n\n\t\t\tignoredNodeIds.add(controllerId)\n\n\t\t\t// direct edge from the end of loop to start\n\t\t\tuiEdges.push({\n\t\t\t\tsource: loopDef.endNodeId,\n\t\t\t\ttarget: loopDef.startNodeId,\n\t\t\t\tdata: {\n\t\t\t\t\tisLoopback: true,\n\t\t\t\t\tcondition: loopDef.condition,\n\t\t\t\t\tlabel: `continue if: ${loopDef.condition}`,\n\t\t\t\t},\n\t\t\t})\n\n\t\t\t// re-wire any 'break' edges\n\t\t\tconst breakEdges = blueprint.edges.filter((edge) => edge.source === controllerId && edge.action === 'break')\n\t\t\tfor (const breakEdge of breakEdges) {\n\t\t\t\tuiEdges.push({\n\t\t\t\t\t...breakEdge,\n\t\t\t\t\tsource: loopDef.endNodeId,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\t// replace scatter/gather pairs with a single representative \"worker\" node\n\t\tconst scatterNodes = blueprint.nodes.filter((n) => n.uses === 'batch-scatter')\n\t\tfor (const scatterNode of scatterNodes) {\n\t\t\tconst gatherNodeId = scatterNode.params?.gatherNodeId\n\t\t\tif (!gatherNodeId) continue\n\n\t\t\tignoredNodeIds.add(scatterNode.id)\n\t\t\tignoredNodeIds.add(gatherNodeId)\n\n\t\t\t// single node to represent parallel work\n\t\t\tconst batchId = scatterNode.id.replace('_scatter', '')\n\t\t\tconst gatherNode = blueprint.nodes.find((n) => n.id === gatherNodeId)\n\n\t\t\tuiNodes.push({\n\t\t\t\tid: batchId,\n\t\t\t\tuses: scatterNode.params?.workerUsesKey,\n\t\t\t\ttype: 'batch-worker',\n\t\t\t\tdata: {\n\t\t\t\t\tlabel: `Batch: ${batchId}`,\n\t\t\t\t\tisBatchPlaceholder: true,\n\t\t\t\t\tworkerUsesKey: scatterNode.params?.workerUsesKey,\n\t\t\t\t\tinputKey: scatterNode.inputs,\n\t\t\t\t\toutputKey: gatherNode?.params?.outputKey,\n\t\t\t\t},\n\t\t\t})\n\n\t\t\t// re-wire incoming edges\n\t\t\tconst incomingEdges = blueprint.edges.filter((e) => e.target === scatterNode.id)\n\t\t\tfor (const edge of incomingEdges) {\n\t\t\t\tuiEdges.push({ ...edge, target: batchId })\n\t\t\t}\n\n\t\t\t// re-wire outgoing edges\n\t\t\tconst outgoingEdges = blueprint.edges.filter((e) => e.source === gatherNodeId)\n\t\t\tfor (const edge of outgoingEdges) {\n\t\t\t\tuiEdges.push({ ...edge, source: batchId })\n\t\t\t}\n\t\t}\n\n\t\tfor (const node of blueprint.nodes) {\n\t\t\tif (!ignoredNodeIds.has(node.id)) {\n\t\t\t\tuiNodes.push(node)\n\t\t\t}\n\t\t}\n\n\t\tfor (const edge of blueprint.edges) {\n\t\t\tif (!ignoredNodeIds.has(edge.source) && !ignoredNodeIds.has(edge.target)) {\n\t\t\t\tconst alreadyAdded = uiEdges.some(\n\t\t\t\t\t(e) => e.source === edge.source && e.target === edge.target && e.action === edge.action,\n\t\t\t\t)\n\t\t\t\tif (!alreadyAdded) {\n\t\t\t\t\tuiEdges.push(edge)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn { nodes: uiNodes, edges: uiEdges }\n\t}\n}\n\n/**\n * Helper function to create a new Flow builder instance.\n */\nexport function createFlow<\n\tTContext extends Record<string, any> = Record<string, any>,\n\tTDependencies extends Record<string, any> = Record<string, any>,\n>(id: string): Flow<TContext, TDependencies> {\n\treturn new Flow(id)\n}\n"]}
@@ -0,0 +1,13 @@
1
+ import { BaseNode } from './chunk-LNK7LZER.js';
2
+
3
+ // src/nodes/wait.ts
4
+ var WaitNode = class extends BaseNode {
5
+ async exec(_prepResult, context) {
6
+ context.dependencies.workflowState.markAsAwaiting(this.nodeId ?? "");
7
+ return { output: void 0 };
8
+ }
9
+ };
10
+
11
+ export { WaitNode };
12
+ //# sourceMappingURL=chunk-CD3Q4N6V.js.map
13
+ //# sourceMappingURL=chunk-CD3Q4N6V.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/nodes/wait.ts"],"names":[],"mappings":";;;AAGO,IAAM,QAAA,GAAN,cAAuB,QAAA,CAAS;AAAA,EACtC,MAAM,IAAA,CACL,WAAA,EACA,OAAA,EACqC;AACrC,IAAA,OAAA,CAAQ,YAAA,CAAa,aAAA,CAAc,cAAA,CAAe,IAAA,CAAK,UAAU,EAAE,CAAA;AACnE,IAAA,OAAO,EAAE,QAAQ,MAAA,EAAU;AAAA,EAC5B;AACD","file":"chunk-CD3Q4N6V.js","sourcesContent":["import { BaseNode } from '../node'\nimport type { NodeContext, NodeResult } from '../types'\n\nexport class WaitNode extends BaseNode {\n\tasync exec(\n\t\t_prepResult: any,\n\t\tcontext: NodeContext<Record<string, any>, any, any>,\n\t): Promise<Omit<NodeResult, 'error'>> {\n\t\tcontext.dependencies.workflowState.markAsAwaiting(this.nodeId ?? '')\n\t\treturn { output: undefined }\n\t}\n}\n"]}
@@ -0,0 +1,114 @@
1
+ import { AsyncContextView, Context } from './chunk-R3HQXIEL.js';
2
+ import { FlowcraftError } from './chunk-BCRWXTWX.js';
3
+
4
+ // src/runtime/state.ts
5
+ var WorkflowState = class {
6
+ _completedNodes = /* @__PURE__ */ new Set();
7
+ errors = [];
8
+ anyFallbackExecuted = false;
9
+ context;
10
+ _isAwaiting = false;
11
+ _awaitingNodeIds = /* @__PURE__ */ new Set();
12
+ constructor(initialData) {
13
+ this.context = new AsyncContextView(new Context(initialData));
14
+ if (initialData._awaitingNodeIds) {
15
+ this._isAwaiting = true;
16
+ const awaitingIds = initialData._awaitingNodeIds;
17
+ if (Array.isArray(awaitingIds)) {
18
+ for (const id of awaitingIds) {
19
+ this._awaitingNodeIds.add(id);
20
+ }
21
+ }
22
+ }
23
+ for (const key of Object.keys(initialData)) {
24
+ if (key.startsWith("_outputs.")) {
25
+ const nodeId = key.substring("_outputs.".length);
26
+ this._completedNodes.add(nodeId);
27
+ }
28
+ }
29
+ }
30
+ async addCompletedNode(nodeId, output) {
31
+ this._completedNodes.add(nodeId);
32
+ await this.context.set(`_outputs.${nodeId}`, output);
33
+ }
34
+ addError(nodeId, error) {
35
+ const flowcraftError = new FlowcraftError(error.message, {
36
+ cause: error,
37
+ nodeId,
38
+ isFatal: false
39
+ });
40
+ this.errors.push({
41
+ ...flowcraftError,
42
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
43
+ originalError: error
44
+ // Legacy compatibility
45
+ });
46
+ }
47
+ clearError(nodeId) {
48
+ this.errors = this.errors.filter((err) => err.nodeId !== nodeId);
49
+ }
50
+ markFallbackExecuted() {
51
+ this.anyFallbackExecuted = true;
52
+ }
53
+ getContext() {
54
+ return this.context;
55
+ }
56
+ getCompletedNodes() {
57
+ return new Set(this._completedNodes);
58
+ }
59
+ getErrors() {
60
+ return this.errors;
61
+ }
62
+ getAnyFallbackExecuted() {
63
+ return this.anyFallbackExecuted;
64
+ }
65
+ markAsAwaiting(nodeId) {
66
+ this._isAwaiting = true;
67
+ this._awaitingNodeIds.add(nodeId);
68
+ const awaitingArray = Array.from(this._awaitingNodeIds);
69
+ this.context.set("_awaitingNodeIds", awaitingArray);
70
+ }
71
+ isAwaiting() {
72
+ return this._isAwaiting && this._awaitingNodeIds.size > 0;
73
+ }
74
+ getAwaitingNodeIds() {
75
+ return Array.from(this._awaitingNodeIds);
76
+ }
77
+ clearAwaiting(nodeId) {
78
+ if (nodeId) {
79
+ this._awaitingNodeIds.delete(nodeId);
80
+ } else {
81
+ this._awaitingNodeIds.clear();
82
+ }
83
+ this._isAwaiting = this._awaitingNodeIds.size > 0;
84
+ const awaitingArray = Array.from(this._awaitingNodeIds);
85
+ if (awaitingArray.length > 0) {
86
+ this.context.set("_awaitingNodeIds", awaitingArray);
87
+ } else {
88
+ this.context.delete("_awaitingNodeIds");
89
+ }
90
+ }
91
+ getStatus(isTraversalComplete = false) {
92
+ if (this._isAwaiting) return "awaiting";
93
+ if (this.anyFallbackExecuted) return "completed";
94
+ if (this.errors.length > 0) return "failed";
95
+ if (isTraversalComplete) return "completed";
96
+ return "stalled";
97
+ }
98
+ async toResult(serializer) {
99
+ const contextJSON = await this.context.toJSON();
100
+ if (!this._isAwaiting && contextJSON._awaitingNodeIds) {
101
+ delete contextJSON._awaitingNodeIds;
102
+ }
103
+ return {
104
+ context: contextJSON,
105
+ serializedContext: serializer.serialize(contextJSON),
106
+ status: this.getStatus(),
107
+ errors: this.errors.length > 0 ? this.errors : void 0
108
+ };
109
+ }
110
+ };
111
+
112
+ export { WorkflowState };
113
+ //# sourceMappingURL=chunk-CD4FUZOJ.js.map
114
+ //# sourceMappingURL=chunk-CD4FUZOJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime/state.ts"],"names":[],"mappings":"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","file":"chunk-CD4FUZOJ.js","sourcesContent":["import { AsyncContextView, Context as SyncContext } from '../context'\nimport { FlowcraftError } from '../errors'\nimport type { IAsyncContext, ISerializer, WorkflowError, WorkflowResult } from '../types'\n\nexport class WorkflowState<TContext extends Record<string, any>> {\n\tprivate _completedNodes = new Set<string>()\n\tprivate errors: WorkflowError[] = []\n\tprivate anyFallbackExecuted = false\n\tprivate context: IAsyncContext<TContext>\n\tprivate _isAwaiting = false\n\tprivate _awaitingNodeIds = new Set<string>()\n\n\tconstructor(initialData: Partial<TContext>) {\n\t\tthis.context = new AsyncContextView(new SyncContext<TContext>(initialData))\n\t\tif ((initialData as any)._awaitingNodeIds) {\n\t\t\tthis._isAwaiting = true\n\t\t\tconst awaitingIds = (initialData as any)._awaitingNodeIds\n\t\t\tif (Array.isArray(awaitingIds)) {\n\t\t\t\tfor (const id of awaitingIds) {\n\t\t\t\t\tthis._awaitingNodeIds.add(id)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (const key of Object.keys(initialData)) {\n\t\t\tif (key.startsWith('_outputs.')) {\n\t\t\t\tconst nodeId = key.substring('_outputs.'.length)\n\t\t\t\tthis._completedNodes.add(nodeId)\n\t\t\t}\n\t\t}\n\t}\n\n\tasync addCompletedNode(nodeId: string, output: any) {\n\t\tthis._completedNodes.add(nodeId)\n\t\tawait this.context.set(`_outputs.${nodeId}` as any, output)\n\t}\n\n\taddError(nodeId: string, error: Error) {\n\t\tconst flowcraftError = new FlowcraftError(error.message, {\n\t\t\tcause: error,\n\t\t\tnodeId,\n\t\t\tisFatal: false,\n\t\t})\n\t\tthis.errors.push({\n\t\t\t...flowcraftError,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\toriginalError: error, // Legacy compatibility\n\t\t})\n\t}\n\n\tclearError(nodeId: string) {\n\t\tthis.errors = this.errors.filter((err) => err.nodeId !== nodeId)\n\t}\n\n\tmarkFallbackExecuted() {\n\t\tthis.anyFallbackExecuted = true\n\t}\n\n\tgetContext(): IAsyncContext<TContext> {\n\t\treturn this.context\n\t}\n\n\tgetCompletedNodes(): Set<string> {\n\t\treturn new Set(this._completedNodes)\n\t}\n\n\tgetErrors(): WorkflowError[] {\n\t\treturn this.errors\n\t}\n\n\tgetAnyFallbackExecuted(): boolean {\n\t\treturn this.anyFallbackExecuted\n\t}\n\n\tmarkAsAwaiting(nodeId: string): void {\n\t\tthis._isAwaiting = true\n\t\tthis._awaitingNodeIds.add(nodeId)\n\t\tconst awaitingArray = Array.from(this._awaitingNodeIds)\n\t\tthis.context.set('_awaitingNodeIds' as any, awaitingArray)\n\t}\n\n\tisAwaiting(): boolean {\n\t\treturn this._isAwaiting && this._awaitingNodeIds.size > 0\n\t}\n\n\tgetAwaitingNodeIds(): string[] {\n\t\treturn Array.from(this._awaitingNodeIds)\n\t}\n\n\tclearAwaiting(nodeId?: string): void {\n\t\tif (nodeId) {\n\t\t\tthis._awaitingNodeIds.delete(nodeId)\n\t\t} else {\n\t\t\tthis._awaitingNodeIds.clear()\n\t\t}\n\t\tthis._isAwaiting = this._awaitingNodeIds.size > 0\n\t\tconst awaitingArray = Array.from(this._awaitingNodeIds)\n\t\tif (awaitingArray.length > 0) {\n\t\t\tthis.context.set('_awaitingNodeIds' as any, awaitingArray)\n\t\t} else {\n\t\t\tthis.context.delete('_awaitingNodeIds' as any)\n\t\t}\n\t}\n\n\tgetStatus(isTraversalComplete = false): WorkflowResult['status'] {\n\t\tif (this._isAwaiting) return 'awaiting'\n\t\tif (this.anyFallbackExecuted) return 'completed'\n\t\tif (this.errors.length > 0) return 'failed'\n\t\tif (isTraversalComplete) return 'completed'\n\t\treturn 'stalled'\n\t}\n\n\tasync toResult(serializer: ISerializer): Promise<WorkflowResult<TContext>> {\n\t\tconst contextJSON = (await this.context.toJSON()) as TContext\n\t\tif (!this._isAwaiting && (contextJSON as any)._awaitingNodeIds) {\n\t\t\tdelete (contextJSON as any)._awaitingNodeIds\n\t\t}\n\t\treturn {\n\t\t\tcontext: contextJSON,\n\t\t\tserializedContext: serializer.serialize(contextJSON),\n\t\t\tstatus: this.getStatus(),\n\t\t\terrors: this.errors.length > 0 ? this.errors : undefined,\n\t\t}\n\t}\n}\n"]}
@@ -0,0 +1,25 @@
1
+ import { InMemoryEventLogger } from './chunk-MUYLRTSR.js';
2
+ import { FlowRuntime } from './chunk-IB2BISIC.js';
3
+
4
+ // src/testing/run-with-trace.ts
5
+ async function runWithTrace(runtime, blueprint, initialState = {}, options = {}) {
6
+ const eventLogger = new InMemoryEventLogger();
7
+ const testRuntime = new FlowRuntime({
8
+ ...runtime.options,
9
+ eventBus: eventLogger
10
+ });
11
+ try {
12
+ const result = await testRuntime.run(blueprint, initialState, options);
13
+ if (process.env.DEBUG) {
14
+ eventLogger.printLog(`Successful Trace: ${blueprint.id}`);
15
+ }
16
+ return result;
17
+ } catch (error) {
18
+ eventLogger.printLog(`Failing Test Trace: ${blueprint.id}`);
19
+ throw error;
20
+ }
21
+ }
22
+
23
+ export { runWithTrace };
24
+ //# sourceMappingURL=chunk-CY755I7I.js.map
25
+ //# sourceMappingURL=chunk-CY755I7I.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/testing/run-with-trace.ts"],"names":[],"mappings":";;;;AA+BA,eAAsB,YAAA,CACrB,SACA,SAAA,EACA,YAAA,GAA2C,EAAC,EAC5C,OAAA,GAII,EAAC,EACJ;AACD,EAAA,MAAM,WAAA,GAAc,IAAI,mBAAA,EAAoB;AAC5C,EAAA,MAAM,WAAA,GAAc,IAAI,WAAA,CAAY;AAAA,IACnC,GAAG,OAAA,CAAQ,OAAA;AAAA,IACX,QAAA,EAAU;AAAA,GACV,CAAA;AAED,EAAA,IAAI;AACH,IAAA,MAAM,SAAS,MAAM,WAAA,CAAY,GAAA,CAAI,SAAA,EAAW,cAAc,OAAO,CAAA;AACrE,IAAA,IAAI,OAAA,CAAQ,IAAI,KAAA,EAAO;AACtB,MAAA,WAAA,CAAY,QAAA,CAAS,CAAA,kBAAA,EAAqB,SAAA,CAAU,EAAE,CAAA,CAAE,CAAA;AAAA,IACzD;AACA,IAAA,OAAO,MAAA;AAAA,EACR,SAAS,KAAA,EAAO;AACf,IAAA,WAAA,CAAY,QAAA,CAAS,CAAA,oBAAA,EAAuB,SAAA,CAAU,EAAE,CAAA,CAAE,CAAA;AAC1D,IAAA,MAAM,KAAA;AAAA,EACP;AACD","file":"chunk-CY755I7I.js","sourcesContent":["import { FlowRuntime } from '../runtime'\nimport type { WorkflowBlueprint } from '../types'\nimport { InMemoryEventLogger } from './event-logger'\n\n/**\n * A test helper that executes a workflow and automatically prints a detailed\n * execution trace to the console if the workflow fails.\n *\n * @example\n * // In your test file (e.g., my-workflow.test.ts)\n * it('should process data correctly', async () => {\n * const flow = createFlow('my-flow')\n * .node('a', async () => ({ output: 1 }))\n * .node('b', async ({ input }) => ({ output: input + 1 })) // Bug: returns { output: 3 }\n * .edge('a', 'b')\n *\n * const runtime = new FlowRuntime({})\n *\n * // If this test fails, a full, human-readable trace of the execution\n * // (inputs, outputs, context changes) is printed to the console.\n * const result = await runWithTrace(runtime, flow.toBlueprint())\n *\n * expect(result.context.b).toBe(2)\n * })\n *\n * @param runtime The original FlowRuntime instance (its options will be used).\n * @param blueprint The WorkflowBlueprint to execute.\n * @param initialState The initial state for the workflow run.\n * @param options Additional options for the run.\n * @returns The WorkflowResult if successful.\n */\nexport async function runWithTrace<TContext extends Record<string, any>>(\n\truntime: FlowRuntime<TContext, any>,\n\tblueprint: WorkflowBlueprint,\n\tinitialState: Partial<TContext> | string = {},\n\toptions: {\n\t\tfunctionRegistry?: Map<string, any>\n\t\tstrict?: boolean\n\t\tsignal?: AbortSignal\n\t} = {},\n) {\n\tconst eventLogger = new InMemoryEventLogger()\n\tconst testRuntime = new FlowRuntime({\n\t\t...runtime.options,\n\t\teventBus: eventLogger,\n\t})\n\n\ttry {\n\t\tconst result = await testRuntime.run(blueprint, initialState, options)\n\t\tif (process.env.DEBUG) {\n\t\t\teventLogger.printLog(`Successful Trace: ${blueprint.id}`)\n\t\t}\n\t\treturn result\n\t} catch (error) {\n\t\teventLogger.printLog(`Failing Test Trace: ${blueprint.id}`)\n\t\tthrow error\n\t}\n}\n"]}
@@ -0,0 +1,39 @@
1
+ import { NodeExecutor, ClassNodeExecutor, FunctionNodeExecutor } from './chunk-ONH7PIJZ.js';
2
+ import { FlowcraftError } from './chunk-BCRWXTWX.js';
3
+ import { isNodeClass } from './chunk-LNK7LZER.js';
4
+
5
+ // src/runtime/node-executor-factory.ts
6
+ var NodeExecutorFactory = class {
7
+ constructor(eventBus) {
8
+ this.eventBus = eventBus;
9
+ }
10
+ createExecutorForNode(nodeId, context) {
11
+ const nodeDef = context.blueprint.nodes.find((n) => n.id === nodeId);
12
+ if (!nodeDef) {
13
+ throw new FlowcraftError(`Node '${nodeId}' not found in blueprint.`, {
14
+ nodeId,
15
+ blueprintId: context.blueprint.id,
16
+ executionId: context.executionId,
17
+ isFatal: false
18
+ });
19
+ }
20
+ const strategy = this.getExecutionStrategy(nodeDef, context.nodeRegistry);
21
+ return new NodeExecutor({ context, nodeDef, strategy });
22
+ }
23
+ getExecutionStrategy(nodeDef, nodeRegistry) {
24
+ const implementation = nodeRegistry.get(nodeDef.uses);
25
+ if (!implementation) {
26
+ throw new FlowcraftError(`Implementation for '${nodeDef.uses}' not found.`, {
27
+ nodeId: nodeDef.id,
28
+ blueprintId: "",
29
+ isFatal: true
30
+ });
31
+ }
32
+ const maxRetries = nodeDef.config?.maxRetries ?? 1;
33
+ return isNodeClass(implementation) ? new ClassNodeExecutor(implementation, maxRetries, this.eventBus) : new FunctionNodeExecutor(implementation, maxRetries, this.eventBus);
34
+ }
35
+ };
36
+
37
+ export { NodeExecutorFactory };
38
+ //# sourceMappingURL=chunk-DL7KVYZF.js.map
39
+ //# sourceMappingURL=chunk-DL7KVYZF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime/node-executor-factory.ts"],"names":[],"mappings":";;;;;AAOO,IAAM,sBAAN,MAA0B;AAAA,EAChC,YAA6B,QAAA,EAAqB;AAArB,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AAAA,EAAsB;AAAA,EAE5C,qBAAA,CAAsB,QAAgB,OAAA,EAA6D;AACzG,IAAA,MAAM,OAAA,GAAU,QAAQ,SAAA,CAAU,KAAA,CAAM,KAAK,CAAC,CAAA,KAAM,CAAA,CAAE,EAAA,KAAO,MAAM,CAAA;AACnE,IAAA,IAAI,CAAC,OAAA,EAAS;AACb,MAAA,MAAM,IAAI,cAAA,CAAe,CAAA,MAAA,EAAS,MAAM,CAAA,yBAAA,CAAA,EAA6B;AAAA,QACpE,MAAA;AAAA,QACA,WAAA,EAAa,QAAQ,SAAA,CAAU,EAAA;AAAA,QAC/B,aAAa,OAAA,CAAQ,WAAA;AAAA,QACrB,OAAA,EAAS;AAAA,OACT,CAAA;AAAA,IACF;AAEA,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,oBAAA,CAAqB,OAAA,EAAS,QAAQ,YAAY,CAAA;AAExE,IAAA,OAAO,IAAI,YAAA,CAAa,EAAE,OAAA,EAAS,OAAA,EAAS,UAAU,CAAA;AAAA,EACvD;AAAA,EAEQ,oBAAA,CACP,SACA,YAAA,EACoB;AACpB,IAAA,MAAM,cAAA,GAAiB,YAAA,CAAa,GAAA,CAAI,OAAA,CAAQ,IAAI,CAAA;AACpD,IAAA,IAAI,CAAC,cAAA,EAAgB;AACpB,MAAA,MAAM,IAAI,cAAA,CAAe,CAAA,oBAAA,EAAuB,OAAA,CAAQ,IAAI,CAAA,YAAA,CAAA,EAAgB;AAAA,QAC3E,QAAQ,OAAA,CAAQ,EAAA;AAAA,QAChB,WAAA,EAAa,EAAA;AAAA,QACb,OAAA,EAAS;AAAA,OACT,CAAA;AAAA,IACF;AAEA,IAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,MAAA,EAAQ,UAAA,IAAc,CAAA;AACjD,IAAA,OAAO,WAAA,CAAY,cAAc,CAAA,GAC9B,IAAI,kBAAkB,cAAA,EAAgB,UAAA,EAAY,IAAA,CAAK,QAAQ,IAC/D,IAAI,oBAAA,CAAqB,cAAA,EAAgB,UAAA,EAAY,KAAK,QAAQ,CAAA;AAAA,EACtE;AACD","file":"chunk-DL7KVYZF.js","sourcesContent":["import { FlowcraftError } from '../errors'\nimport { isNodeClass } from '../node'\nimport type { IEventBus, NodeClass, NodeDefinition, NodeFunction } from '../types'\nimport type { ExecutionContext } from './execution-context'\nimport type { ExecutionStrategy } from './executors'\nimport { ClassNodeExecutor, FunctionNodeExecutor, NodeExecutor } from './executors'\n\nexport class NodeExecutorFactory {\n\tconstructor(private readonly eventBus: IEventBus) {}\n\n\tpublic createExecutorForNode(nodeId: string, context: ExecutionContext<any, any>): NodeExecutor<any, any> {\n\t\tconst nodeDef = context.blueprint.nodes.find((n) => n.id === nodeId)\n\t\tif (!nodeDef) {\n\t\t\tthrow new FlowcraftError(`Node '${nodeId}' not found in blueprint.`, {\n\t\t\t\tnodeId,\n\t\t\t\tblueprintId: context.blueprint.id,\n\t\t\t\texecutionId: context.executionId,\n\t\t\t\tisFatal: false,\n\t\t\t})\n\t\t}\n\n\t\tconst strategy = this.getExecutionStrategy(nodeDef, context.nodeRegistry)\n\n\t\treturn new NodeExecutor({ context, nodeDef, strategy })\n\t}\n\n\tprivate getExecutionStrategy(\n\t\tnodeDef: NodeDefinition,\n\t\tnodeRegistry: Map<string, NodeFunction | NodeClass>,\n\t): ExecutionStrategy {\n\t\tconst implementation = nodeRegistry.get(nodeDef.uses)\n\t\tif (!implementation) {\n\t\t\tthrow new FlowcraftError(`Implementation for '${nodeDef.uses}' not found.`, {\n\t\t\t\tnodeId: nodeDef.id,\n\t\t\t\tblueprintId: '',\n\t\t\t\tisFatal: true,\n\t\t\t})\n\t\t}\n\n\t\tconst maxRetries = nodeDef.config?.maxRetries ?? 1\n\t\treturn isNodeClass(implementation)\n\t\t\t? new ClassNodeExecutor(implementation, maxRetries, this.eventBus)\n\t\t\t: new FunctionNodeExecutor(implementation, maxRetries, this.eventBus)\n\t}\n}\n"]}
@@ -0,0 +1,32 @@
1
+ import { WorkflowState } from './chunk-CD4FUZOJ.js';
2
+
3
+ // src/runtime/execution-context.ts
4
+ var ExecutionContext = class _ExecutionContext {
5
+ constructor(blueprint, state, nodeRegistry, executionId, runtime, services, signal, concurrency) {
6
+ this.blueprint = blueprint;
7
+ this.state = state;
8
+ this.nodeRegistry = nodeRegistry;
9
+ this.executionId = executionId;
10
+ this.runtime = runtime;
11
+ this.services = services;
12
+ this.signal = signal;
13
+ this.concurrency = concurrency;
14
+ }
15
+ createForSubflow(subBlueprint, initialSubState) {
16
+ const subState = new WorkflowState(initialSubState);
17
+ return new _ExecutionContext(
18
+ subBlueprint,
19
+ subState,
20
+ this.nodeRegistry,
21
+ this.executionId,
22
+ this.runtime,
23
+ this.services,
24
+ this.signal,
25
+ this.concurrency
26
+ );
27
+ }
28
+ };
29
+
30
+ export { ExecutionContext };
31
+ //# sourceMappingURL=chunk-FRKO3WX4.js.map
32
+ //# sourceMappingURL=chunk-FRKO3WX4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime/execution-context.ts"],"names":[],"mappings":";;;AAkBO,IAAM,gBAAA,GAAN,MAAM,iBAAA,CAAkG;AAAA,EAC9G,WAAA,CACiB,WACA,KAAA,EACA,YAAA,EACA,aACA,OAAA,EACA,QAAA,EAQA,QACA,WAAA,EACf;AAfe,IAAA,IAAA,CAAA,SAAA,GAAA,SAAA;AACA,IAAA,IAAA,CAAA,KAAA,GAAA,KAAA;AACA,IAAA,IAAA,CAAA,YAAA,GAAA,YAAA;AACA,IAAA,IAAA,CAAA,WAAA,GAAA,WAAA;AACA,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AACA,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AAQA,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,WAAA,GAAA,WAAA;AAAA,EACd;AAAA,EAEI,gBAAA,CACN,cACA,eAAA,EAC4C;AAC5C,IAAA,MAAM,QAAA,GAAW,IAAI,aAAA,CAAwB,eAAe,CAAA;AAC5D,IAAA,OAAO,IAAI,iBAAA;AAAA,MACV,YAAA;AAAA,MACA,QAAA;AAAA,MACA,IAAA,CAAK,YAAA;AAAA,MACL,IAAA,CAAK,WAAA;AAAA,MACL,IAAA,CAAK,OAAA;AAAA,MACL,IAAA,CAAK,QAAA;AAAA,MACL,IAAA,CAAK,MAAA;AAAA,MACL,IAAA,CAAK;AAAA,KACN;AAAA,EACD;AACD","file":"chunk-FRKO3WX4.js","sourcesContent":["import type {\n\tIEvaluator,\n\tIEventBus,\n\tILogger,\n\tISerializer,\n\tMiddleware,\n\tNodeClass,\n\tNodeFunction,\n\tRuntimeDependencies,\n\tWorkflowBlueprint,\n} from '../types'\nimport type { FlowRuntime } from './runtime'\nimport { WorkflowState } from './state'\n\n/**\n * A container for all state and dependencies of a single workflow execution.\n * This object is created once per `run` and passed through the execution stack.\n */\nexport class ExecutionContext<TContext extends Record<string, any>, TDependencies extends RuntimeDependencies> {\n\tconstructor(\n\t\tpublic readonly blueprint: WorkflowBlueprint,\n\t\tpublic readonly state: WorkflowState<TContext>,\n\t\tpublic readonly nodeRegistry: Map<string, NodeFunction | NodeClass>,\n\t\tpublic readonly executionId: string,\n\t\tpublic readonly runtime: FlowRuntime<TContext, TDependencies>, // A reference back to the runtime for orchestrating subflows\n\t\tpublic readonly services: {\n\t\t\tlogger: ILogger\n\t\t\teventBus: IEventBus\n\t\t\tserializer: ISerializer\n\t\t\tevaluator: IEvaluator\n\t\t\tmiddleware: Middleware[]\n\t\t\tdependencies: TDependencies\n\t\t},\n\t\tpublic readonly signal?: AbortSignal,\n\t\tpublic readonly concurrency?: number,\n\t) {}\n\n\tpublic createForSubflow(\n\t\tsubBlueprint: WorkflowBlueprint,\n\t\tinitialSubState: Partial<TContext>,\n\t): ExecutionContext<TContext, TDependencies> {\n\t\tconst subState = new WorkflowState<TContext>(initialSubState)\n\t\treturn new ExecutionContext(\n\t\t\tsubBlueprint,\n\t\t\tsubState,\n\t\t\tthis.nodeRegistry,\n\t\t\tthis.executionId,\n\t\t\tthis.runtime,\n\t\t\tthis.services,\n\t\t\tthis.signal,\n\t\t\tthis.concurrency,\n\t\t)\n\t}\n}\n"]}
@@ -0,0 +1,54 @@
1
+ import { executeBatch, processResults } from './chunk-HAZ26F3P.js';
2
+ import { FlowcraftError } from './chunk-BCRWXTWX.js';
3
+
4
+ // src/runtime/orchestrators/step-by-step.ts
5
+ var StepByStepOrchestrator = class {
6
+ async run(context, traverser) {
7
+ try {
8
+ context.signal?.throwIfAborted();
9
+ } catch (error) {
10
+ if (error instanceof DOMException && error.name === "AbortError") {
11
+ throw new FlowcraftError("Workflow cancelled", { isFatal: false });
12
+ }
13
+ throw error;
14
+ }
15
+ if (!traverser.hasMoreWork()) {
16
+ const isTraversalComplete2 = !traverser.hasMoreWork();
17
+ const status2 = context.state.getStatus(isTraversalComplete2);
18
+ const result2 = await context.state.toResult(context.services.serializer);
19
+ result2.status = status2;
20
+ return result2;
21
+ }
22
+ const allReadyNodes = traverser.getReadyNodes();
23
+ const nodesToExecute = context.concurrency ? allReadyNodes.slice(0, context.concurrency) : allReadyNodes;
24
+ const nodesToSkip = context.concurrency ? allReadyNodes.slice(context.concurrency) : [];
25
+ const settledResults = await executeBatch(
26
+ nodesToExecute,
27
+ traverser.getDynamicBlueprint(),
28
+ context.state,
29
+ (nodeId) => context.runtime.getExecutorForNode(nodeId, context),
30
+ context.runtime,
31
+ context.concurrency
32
+ );
33
+ await processResults(
34
+ settledResults,
35
+ traverser,
36
+ context.state,
37
+ context.runtime,
38
+ context.blueprint,
39
+ context.executionId
40
+ );
41
+ for (const { nodeId } of nodesToSkip) {
42
+ traverser.addToFrontier(nodeId);
43
+ }
44
+ const isTraversalComplete = !traverser.hasMoreWork();
45
+ const status = context.state.getStatus(isTraversalComplete);
46
+ const result = await context.state.toResult(context.services.serializer);
47
+ result.status = status;
48
+ return result;
49
+ }
50
+ };
51
+
52
+ export { StepByStepOrchestrator };
53
+ //# sourceMappingURL=chunk-G53CSLBF.js.map
54
+ //# sourceMappingURL=chunk-G53CSLBF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime/orchestrators/step-by-step.ts"],"names":["isTraversalComplete","status","result"],"mappings":";;;;AAeO,IAAM,yBAAN,MAAsD;AAAA,EAC5D,MAAa,GAAA,CAAI,OAAA,EAAqC,SAAA,EAAyD;AAC9G,IAAA,IAAI;AACH,MAAA,OAAA,CAAQ,QAAQ,cAAA,EAAe;AAAA,IAChC,SAAS,KAAA,EAAO;AACf,MAAA,IAAI,KAAA,YAAiB,YAAA,IAAgB,KAAA,CAAM,IAAA,KAAS,YAAA,EAAc;AACjE,QAAA,MAAM,IAAI,cAAA,CAAe,oBAAA,EAAsB,EAAE,OAAA,EAAS,OAAO,CAAA;AAAA,MAClE;AACA,MAAA,MAAM,KAAA;AAAA,IACP;AAEA,IAAA,IAAI,CAAC,SAAA,CAAU,WAAA,EAAY,EAAG;AAC7B,MAAA,MAAMA,oBAAAA,GAAsB,CAAC,SAAA,CAAU,WAAA,EAAY;AACnD,MAAA,MAAMC,OAAAA,GAAS,OAAA,CAAQ,KAAA,CAAM,SAAA,CAAUD,oBAAmB,CAAA;AAC1D,MAAA,MAAME,UAAS,MAAM,OAAA,CAAQ,MAAM,QAAA,CAAS,OAAA,CAAQ,SAAS,UAAU,CAAA;AACvE,MAAAA,QAAO,MAAA,GAASD,OAAAA;AAChB,MAAA,OAAOC,OAAAA;AAAA,IACR;AAEA,IAAA,MAAM,aAAA,GAAgB,UAAU,aAAA,EAAc;AAC9C,IAAA,MAAM,cAAA,GAAiB,QAAQ,WAAA,GAAc,aAAA,CAAc,MAAM,CAAA,EAAG,OAAA,CAAQ,WAAW,CAAA,GAAI,aAAA;AAC3F,IAAA,MAAM,WAAA,GAAc,QAAQ,WAAA,GAAc,aAAA,CAAc,MAAM,OAAA,CAAQ,WAAW,IAAI,EAAC;AAEtF,IAAA,MAAM,iBAAiB,MAAM,YAAA;AAAA,MAC5B,cAAA;AAAA,MACA,UAAU,mBAAA,EAAoB;AAAA,MAC9B,OAAA,CAAQ,KAAA;AAAA,MACR,CAAC,MAAA,KAAmB,OAAA,CAAQ,OAAA,CAAQ,kBAAA,CAAmB,QAAQ,OAAO,CAAA;AAAA,MACtE,OAAA,CAAQ,OAAA;AAAA,MACR,OAAA,CAAQ;AAAA,KACT;AAEA,IAAA,MAAM,cAAA;AAAA,MACL,cAAA;AAAA,MACA,SAAA;AAAA,MACA,OAAA,CAAQ,KAAA;AAAA,MACR,OAAA,CAAQ,OAAA;AAAA,MACR,OAAA,CAAQ,SAAA;AAAA,MACR,OAAA,CAAQ;AAAA,KACT;AAEA,IAAA,KAAA,MAAW,EAAE,MAAA,EAAO,IAAK,WAAA,EAAa;AACrC,MAAA,SAAA,CAAU,cAAc,MAAM,CAAA;AAAA,IAC/B;AAEA,IAAA,MAAM,mBAAA,GAAsB,CAAC,SAAA,CAAU,WAAA,EAAY;AACnD,IAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,KAAA,CAAM,SAAA,CAAU,mBAAmB,CAAA;AAC1D,IAAA,MAAM,SAAS,MAAM,OAAA,CAAQ,MAAM,QAAA,CAAS,OAAA,CAAQ,SAAS,UAAU,CAAA;AACvE,IAAA,MAAA,CAAO,MAAA,GAAS,MAAA;AAChB,IAAA,OAAO,MAAA;AAAA,EACR;AACD","file":"chunk-G53CSLBF.js","sourcesContent":["import { FlowcraftError } from '../../errors'\n\nimport type { WorkflowResult } from '../../types'\nimport type { ExecutionContext } from '../execution-context'\nimport type { GraphTraverser } from '../traverser'\nimport type { IOrchestrator } from '../types'\nimport { executeBatch, processResults } from './utils'\n\n/**\n * An orchestrator that executes only one \"tick\" or \"turn\" of the workflow.\n * It processes a single batch of ready nodes from the frontier and then returns,\n * allowing the caller to inspect the intermediate state before proceeding.\n *\n * Useful for debugging, testing, or building interactive tools.\n */\nexport class StepByStepOrchestrator implements IOrchestrator {\n\tpublic async run(context: ExecutionContext<any, any>, traverser: GraphTraverser): Promise<WorkflowResult<any>> {\n\t\ttry {\n\t\t\tcontext.signal?.throwIfAborted()\n\t\t} catch (error) {\n\t\t\tif (error instanceof DOMException && error.name === 'AbortError') {\n\t\t\t\tthrow new FlowcraftError('Workflow cancelled', { isFatal: false })\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\n\t\tif (!traverser.hasMoreWork()) {\n\t\t\tconst isTraversalComplete = !traverser.hasMoreWork()\n\t\t\tconst status = context.state.getStatus(isTraversalComplete)\n\t\t\tconst result = await context.state.toResult(context.services.serializer)\n\t\t\tresult.status = status\n\t\t\treturn result\n\t\t}\n\n\t\tconst allReadyNodes = traverser.getReadyNodes()\n\t\tconst nodesToExecute = context.concurrency ? allReadyNodes.slice(0, context.concurrency) : allReadyNodes\n\t\tconst nodesToSkip = context.concurrency ? allReadyNodes.slice(context.concurrency) : []\n\n\t\tconst settledResults = await executeBatch(\n\t\t\tnodesToExecute,\n\t\t\ttraverser.getDynamicBlueprint(),\n\t\t\tcontext.state,\n\t\t\t(nodeId: string) => context.runtime.getExecutorForNode(nodeId, context),\n\t\t\tcontext.runtime,\n\t\t\tcontext.concurrency,\n\t\t)\n\n\t\tawait processResults(\n\t\t\tsettledResults,\n\t\t\ttraverser,\n\t\t\tcontext.state,\n\t\t\tcontext.runtime,\n\t\t\tcontext.blueprint,\n\t\t\tcontext.executionId,\n\t\t)\n\n\t\tfor (const { nodeId } of nodesToSkip) {\n\t\t\ttraverser.addToFrontier(nodeId)\n\t\t}\n\n\t\tconst isTraversalComplete = !traverser.hasMoreWork()\n\t\tconst status = context.state.getStatus(isTraversalComplete)\n\t\tconst result = await context.state.toResult(context.services.serializer)\n\t\tresult.status = status\n\t\treturn result\n\t}\n}\n"]}