flowcraft 2.2.0 → 2.3.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 (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-BC4G7OM6.js +42 -0
  6. package/dist/chunk-BC4G7OM6.js.map +1 -0
  7. package/dist/chunk-BCRWXTWX.js +21 -0
  8. package/dist/chunk-BCRWXTWX.js.map +1 -0
  9. package/dist/chunk-BN4MV36K.js +25 -0
  10. package/dist/chunk-BN4MV36K.js.map +1 -0
  11. package/dist/{chunk-ZCHFZBGL.js → chunk-C4HYIJI3.js} +120 -5
  12. package/dist/chunk-C4HYIJI3.js.map +1 -0
  13. package/dist/chunk-CD3Q4N6V.js +13 -0
  14. package/dist/chunk-CD3Q4N6V.js.map +1 -0
  15. package/dist/chunk-CD4FUZOJ.js +114 -0
  16. package/dist/chunk-CD4FUZOJ.js.map +1 -0
  17. package/dist/chunk-DL7KVYZF.js +39 -0
  18. package/dist/chunk-DL7KVYZF.js.map +1 -0
  19. package/dist/chunk-FRKO3WX4.js +32 -0
  20. package/dist/chunk-FRKO3WX4.js.map +1 -0
  21. package/dist/chunk-G53CSLBF.js +54 -0
  22. package/dist/chunk-G53CSLBF.js.map +1 -0
  23. package/dist/chunk-G5BGBPFP.js +172 -0
  24. package/dist/chunk-G5BGBPFP.js.map +1 -0
  25. package/dist/chunk-HAZ26F3P.js +98 -0
  26. package/dist/chunk-HAZ26F3P.js.map +1 -0
  27. package/dist/chunk-HKX7WQLS.js +446 -0
  28. package/dist/chunk-HKX7WQLS.js.map +1 -0
  29. package/dist/{chunk-U5V5O5MN.js → chunk-LNK7LZER.js} +5 -3
  30. package/dist/chunk-LNK7LZER.js.map +1 -0
  31. package/dist/chunk-MCGK3FXQ.js +143 -0
  32. package/dist/chunk-MCGK3FXQ.js.map +1 -0
  33. package/dist/chunk-MKNZBKSR.js +90 -0
  34. package/dist/chunk-MKNZBKSR.js.map +1 -0
  35. package/dist/chunk-MUYLRTSR.js +82 -0
  36. package/dist/chunk-MUYLRTSR.js.map +1 -0
  37. package/dist/chunk-NVJ3ZO3P.js +3 -0
  38. package/dist/{chunk-HMR2GEGE.js.map → chunk-NVJ3ZO3P.js.map} +1 -1
  39. package/dist/chunk-NVLZFLYM.js +3 -0
  40. package/dist/chunk-NVLZFLYM.js.map +1 -0
  41. package/dist/chunk-ONH7PIJZ.js +300 -0
  42. package/dist/chunk-ONH7PIJZ.js.map +1 -0
  43. package/dist/chunk-QNYXQKFW.js +25 -0
  44. package/dist/chunk-QNYXQKFW.js.map +1 -0
  45. package/dist/chunk-RM677CNU.js +52 -0
  46. package/dist/chunk-RM677CNU.js.map +1 -0
  47. package/dist/chunk-WWGFIYKW.js +47 -0
  48. package/dist/chunk-WWGFIYKW.js.map +1 -0
  49. package/dist/chunk-XNRIM27H.js +76 -0
  50. package/dist/chunk-XNRIM27H.js.map +1 -0
  51. package/dist/{chunk-QLGJUDQF.js → chunk-ZNL7ZXPR.js} +26 -11
  52. package/dist/chunk-ZNL7ZXPR.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
@@ -0,0 +1,143 @@
1
+ import { AsyncContextView } from './chunk-R3HQXIEL.js';
2
+ import { FlowcraftError } from './chunk-BCRWXTWX.js';
3
+
4
+ // src/runtime/workflow-logic-handler.ts
5
+ var WorkflowLogicHandler = class {
6
+ constructor(evaluator, eventBus) {
7
+ this.evaluator = evaluator;
8
+ this.eventBus = eventBus;
9
+ }
10
+ async determineNextNodes(blueprint, completedNodeId, result, context, executionId) {
11
+ let effectiveSourceNodeId = completedNodeId;
12
+ const completedNodeDef = blueprint.nodes.find((n) => n.id === completedNodeId);
13
+ if (completedNodeDef?.uses === "loop-controller" && result.action !== "continue")
14
+ effectiveSourceNodeId = completedNodeDef.params?.endNodeId;
15
+ let directOutgoingEdges = blueprint.edges.filter((edge) => edge.source === effectiveSourceNodeId);
16
+ if (effectiveSourceNodeId !== completedNodeId)
17
+ directOutgoingEdges = directOutgoingEdges.filter((edge) => edge.target !== completedNodeId);
18
+ const nodesThisIsAFallbackFor = blueprint.nodes.filter((n) => n.config?.fallback === completedNodeId);
19
+ const inheritedOutgoingEdges = nodesThisIsAFallbackFor.flatMap(
20
+ (originalNode) => blueprint.edges.filter((edge) => edge.source === originalNode.id)
21
+ );
22
+ const allPossibleEdges = [...directOutgoingEdges, ...inheritedOutgoingEdges];
23
+ const outgoingEdges = [
24
+ ...new Map(
25
+ allPossibleEdges.map((edge) => [
26
+ `${edge.source}-${edge.target}-${edge.action || ""}-${edge.condition || ""}`,
27
+ edge
28
+ ])
29
+ ).values()
30
+ ];
31
+ const matched = [];
32
+ const evaluateEdge = async (edge) => {
33
+ if (!edge.condition) return true;
34
+ const contextData = context.type === "sync" ? context.toJSON() : await context.toJSON();
35
+ const evaluationResult = !!this.evaluator.evaluate(edge.condition, {
36
+ ...contextData,
37
+ result
38
+ });
39
+ await this.eventBus.emit({
40
+ type: "edge:evaluate",
41
+ payload: { source: edge.source, target: edge.target, condition: edge.condition, result: evaluationResult }
42
+ });
43
+ return evaluationResult;
44
+ };
45
+ if (result.action) {
46
+ const actionEdges = outgoingEdges.filter((edge) => edge.action === result.action);
47
+ for (const edge of actionEdges) {
48
+ if (await evaluateEdge(edge)) {
49
+ const targetNode = blueprint.nodes.find((n) => n.id === edge.target);
50
+ if (targetNode) matched.push({ node: targetNode, edge });
51
+ } else {
52
+ await this.eventBus.emit({
53
+ type: "node:skipped",
54
+ payload: { nodeId: completedNodeId, edge, executionId: executionId || "", blueprintId: blueprint.id }
55
+ });
56
+ }
57
+ }
58
+ }
59
+ if (matched.length === 0) {
60
+ const defaultEdges = outgoingEdges.filter((edge) => !edge.action);
61
+ for (const edge of defaultEdges) {
62
+ if (await evaluateEdge(edge)) {
63
+ const targetNode = blueprint.nodes.find((n) => n.id === edge.target);
64
+ if (targetNode) matched.push({ node: targetNode, edge });
65
+ } else {
66
+ await this.eventBus.emit({
67
+ type: "node:skipped",
68
+ payload: { nodeId: completedNodeId, edge, executionId: executionId || "", blueprintId: blueprint.id }
69
+ });
70
+ }
71
+ }
72
+ }
73
+ return matched;
74
+ }
75
+ async applyEdgeTransform(edge, sourceResult, targetNode, context, allPredecessors) {
76
+ const asyncContext = context.type === "sync" ? new AsyncContextView(context) : context;
77
+ const predecessors = allPredecessors?.get(targetNode.id);
78
+ const hasSinglePredecessor = predecessors && predecessors.size === 1;
79
+ const hasExplicitInputs = targetNode.inputs !== void 0;
80
+ const hasEdgeTransform = edge.transform !== void 0;
81
+ if (!hasExplicitInputs && !hasSinglePredecessor && !hasEdgeTransform) {
82
+ return;
83
+ }
84
+ const finalInput = edge.transform ? this.evaluator.evaluate(edge.transform, {
85
+ input: sourceResult.output,
86
+ context: await asyncContext.toJSON()
87
+ }) : sourceResult.output;
88
+ const inputKey = `_inputs.${targetNode.id}`;
89
+ await asyncContext.set(inputKey, finalInput);
90
+ await this.eventBus.emit({
91
+ type: "context:change",
92
+ payload: { sourceNode: edge.source, key: inputKey, value: finalInput }
93
+ });
94
+ if (!hasExplicitInputs) {
95
+ targetNode.inputs = inputKey;
96
+ }
97
+ }
98
+ async resolveNodeInput(nodeId, blueprint, context) {
99
+ const nodeDef = blueprint.nodes.find((n) => n.id === nodeId);
100
+ if (!nodeDef) {
101
+ throw new FlowcraftError(`Node '${nodeId}' not found in blueprint.`, {
102
+ nodeId,
103
+ blueprintId: blueprint.id,
104
+ isFatal: false
105
+ });
106
+ }
107
+ const asyncContext = context.type === "sync" ? new AsyncContextView(context) : context;
108
+ if (nodeDef.inputs) {
109
+ if (typeof nodeDef.inputs === "string") {
110
+ const key = nodeDef.inputs;
111
+ if (key.startsWith("_")) return await asyncContext.get(key);
112
+ const outputKey = `_outputs.${key}`;
113
+ if (await asyncContext.has(outputKey)) {
114
+ return await asyncContext.get(outputKey);
115
+ }
116
+ return await asyncContext.get(key);
117
+ }
118
+ if (typeof nodeDef.inputs === "object") {
119
+ const input = {};
120
+ for (const key in nodeDef.inputs) {
121
+ const contextKey = nodeDef.inputs[key];
122
+ if (contextKey.startsWith("_")) {
123
+ input[key] = await asyncContext.get(contextKey);
124
+ } else {
125
+ const outputKey = `_outputs.${contextKey}`;
126
+ if (await asyncContext.has(outputKey)) {
127
+ input[key] = await asyncContext.get(outputKey);
128
+ } else {
129
+ input[key] = await asyncContext.get(contextKey);
130
+ }
131
+ }
132
+ }
133
+ return input;
134
+ }
135
+ }
136
+ const inputKey = `_inputs.${nodeDef.id}`;
137
+ return await asyncContext.get(inputKey);
138
+ }
139
+ };
140
+
141
+ export { WorkflowLogicHandler };
142
+ //# sourceMappingURL=chunk-MCGK3FXQ.js.map
143
+ //# sourceMappingURL=chunk-MCGK3FXQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime/workflow-logic-handler.ts"],"names":[],"mappings":"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","file":"chunk-MCGK3FXQ.js","sourcesContent":["import { AsyncContextView } from '../context'\nimport { FlowcraftError } from '../errors'\nimport type {\n\tContextImplementation,\n\tEdgeDefinition,\n\tIEvaluator,\n\tIEventBus,\n\tNodeDefinition,\n\tNodeResult,\n\tWorkflowBlueprint,\n} from '../types'\n\nexport class WorkflowLogicHandler {\n\tconstructor(\n\t\tprivate readonly evaluator: IEvaluator,\n\t\tprivate readonly eventBus: IEventBus,\n\t) {}\n\n\tpublic async determineNextNodes(\n\t\tblueprint: WorkflowBlueprint,\n\t\tcompletedNodeId: string,\n\t\tresult: NodeResult<any, any>,\n\t\tcontext: ContextImplementation<any>,\n\t\texecutionId?: string,\n\t): Promise<{ node: NodeDefinition; edge: EdgeDefinition }[]> {\n\t\tlet effectiveSourceNodeId = completedNodeId\n\t\tconst completedNodeDef = blueprint.nodes.find((n) => n.id === completedNodeId)\n\t\tif (completedNodeDef?.uses === 'loop-controller' && result.action !== 'continue')\n\t\t\t// act as if the loop's end node just finished\n\t\t\teffectiveSourceNodeId = completedNodeDef.params?.endNodeId\n\n\t\tlet directOutgoingEdges = blueprint.edges.filter((edge) => edge.source === effectiveSourceNodeId)\n\t\tif (effectiveSourceNodeId !== completedNodeId)\n\t\t\t// breaking from a loop, ignore the edge that leads back to the controller\n\t\t\tdirectOutgoingEdges = directOutgoingEdges.filter((edge) => edge.target !== completedNodeId)\n\n\t\tconst nodesThisIsAFallbackFor = blueprint.nodes.filter((n) => n.config?.fallback === completedNodeId)\n\t\tconst inheritedOutgoingEdges = nodesThisIsAFallbackFor.flatMap((originalNode) =>\n\t\t\tblueprint.edges.filter((edge) => edge.source === originalNode.id),\n\t\t)\n\t\tconst allPossibleEdges = [...directOutgoingEdges, ...inheritedOutgoingEdges]\n\t\tconst outgoingEdges = [\n\t\t\t...new Map(\n\t\t\t\tallPossibleEdges.map((edge) => [\n\t\t\t\t\t`${edge.source}-${edge.target}-${edge.action || ''}-${edge.condition || ''}`,\n\t\t\t\t\tedge,\n\t\t\t\t]),\n\t\t\t).values(),\n\t\t]\n\n\t\tconst matched: { node: NodeDefinition; edge: EdgeDefinition }[] = []\n\t\tconst evaluateEdge = async (edge: EdgeDefinition): Promise<boolean> => {\n\t\t\tif (!edge.condition) return true\n\t\t\tconst contextData = context.type === 'sync' ? context.toJSON() : await context.toJSON()\n\t\t\tconst evaluationResult = !!this.evaluator.evaluate(edge.condition, {\n\t\t\t\t...contextData,\n\t\t\t\tresult,\n\t\t\t})\n\t\t\tawait this.eventBus.emit({\n\t\t\t\ttype: 'edge:evaluate',\n\t\t\t\tpayload: { source: edge.source, target: edge.target, condition: edge.condition, result: evaluationResult },\n\t\t\t})\n\t\t\treturn evaluationResult\n\t\t}\n\n\t\tif (result.action) {\n\t\t\tconst actionEdges = outgoingEdges.filter((edge) => edge.action === result.action)\n\t\t\tfor (const edge of actionEdges) {\n\t\t\t\tif (await evaluateEdge(edge)) {\n\t\t\t\t\tconst targetNode = blueprint.nodes.find((n) => n.id === edge.target)\n\t\t\t\t\tif (targetNode) matched.push({ node: targetNode, edge })\n\t\t\t\t} else {\n\t\t\t\t\tawait this.eventBus.emit({\n\t\t\t\t\t\ttype: 'node:skipped',\n\t\t\t\t\t\tpayload: { nodeId: completedNodeId, edge, executionId: executionId || '', blueprintId: blueprint.id },\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (matched.length === 0) {\n\t\t\tconst defaultEdges = outgoingEdges.filter((edge) => !edge.action)\n\t\t\tfor (const edge of defaultEdges) {\n\t\t\t\tif (await evaluateEdge(edge)) {\n\t\t\t\t\tconst targetNode = blueprint.nodes.find((n) => n.id === edge.target)\n\t\t\t\t\tif (targetNode) matched.push({ node: targetNode, edge })\n\t\t\t\t} else {\n\t\t\t\t\tawait this.eventBus.emit({\n\t\t\t\t\t\ttype: 'node:skipped',\n\t\t\t\t\t\tpayload: { nodeId: completedNodeId, edge, executionId: executionId || '', blueprintId: blueprint.id },\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn matched\n\t}\n\n\tpublic async applyEdgeTransform(\n\t\tedge: EdgeDefinition,\n\t\tsourceResult: NodeResult<any, any>,\n\t\ttargetNode: NodeDefinition,\n\t\tcontext: ContextImplementation<any>,\n\t\tallPredecessors?: Map<string, Set<string>>,\n\t): Promise<void> {\n\t\tconst asyncContext = context.type === 'sync' ? new AsyncContextView(context) : context\n\t\tconst predecessors = allPredecessors?.get(targetNode.id)\n\t\tconst hasSinglePredecessor = predecessors && predecessors.size === 1\n\t\tconst hasExplicitInputs = targetNode.inputs !== undefined\n\t\tconst hasEdgeTransform = edge.transform !== undefined\n\n\t\tif (!hasExplicitInputs && !hasSinglePredecessor && !hasEdgeTransform) {\n\t\t\treturn\n\t\t}\n\n\t\tconst finalInput = edge.transform\n\t\t\t? this.evaluator.evaluate(edge.transform, {\n\t\t\t\t\tinput: sourceResult.output,\n\t\t\t\t\tcontext: await asyncContext.toJSON(),\n\t\t\t\t})\n\t\t\t: sourceResult.output\n\t\tconst inputKey = `_inputs.${targetNode.id}`\n\t\tawait asyncContext.set(inputKey as any, finalInput)\n\t\tawait this.eventBus.emit({\n\t\t\ttype: 'context:change',\n\t\t\tpayload: { sourceNode: edge.source, key: inputKey, value: finalInput },\n\t\t})\n\t\tif (!hasExplicitInputs) {\n\t\t\ttargetNode.inputs = inputKey\n\t\t}\n\t}\n\n\tpublic async resolveNodeInput(\n\t\tnodeId: string,\n\t\tblueprint: WorkflowBlueprint,\n\t\tcontext: ContextImplementation<any>,\n\t): Promise<any> {\n\t\tconst nodeDef = 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: blueprint.id,\n\t\t\t\tisFatal: false,\n\t\t\t})\n\t\t}\n\t\tconst asyncContext = context.type === 'sync' ? new AsyncContextView(context) : context\n\t\tif (nodeDef.inputs) {\n\t\t\tif (typeof nodeDef.inputs === 'string') {\n\t\t\t\tconst key = nodeDef.inputs\n\t\t\t\tif (key.startsWith('_')) return await asyncContext.get(key as any)\n\t\t\t\tconst outputKey = `_outputs.${key}`\n\t\t\t\tif (await asyncContext.has(outputKey as any)) {\n\t\t\t\t\treturn await asyncContext.get(outputKey as any)\n\t\t\t\t}\n\t\t\t\treturn await asyncContext.get(key as any)\n\t\t\t}\n\t\t\tif (typeof nodeDef.inputs === 'object') {\n\t\t\t\tconst input: Record<string, any> = {}\n\t\t\t\tfor (const key in nodeDef.inputs) {\n\t\t\t\t\tconst contextKey = nodeDef.inputs[key]\n\t\t\t\t\tif (contextKey.startsWith('_')) {\n\t\t\t\t\t\tinput[key] = await asyncContext.get(contextKey as any)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst outputKey = `_outputs.${contextKey}`\n\t\t\t\t\t\tif (await asyncContext.has(outputKey as any)) {\n\t\t\t\t\t\t\tinput[key] = await asyncContext.get(outputKey as any)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tinput[key] = await asyncContext.get(contextKey as any)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn input\n\t\t\t}\n\t\t}\n\t\t// Default to standardized input key\n\t\tconst inputKey = `_inputs.${nodeDef.id}`\n\t\treturn await asyncContext.get(inputKey as any)\n\t}\n}\n"]}
@@ -0,0 +1,90 @@
1
+ import { GraphTraverser } from './chunk-G5BGBPFP.js';
2
+ import { analyzeBlueprint } from './chunk-233SESC2.js';
3
+ import { ExecutionContext } from './chunk-FRKO3WX4.js';
4
+ import { WorkflowState } from './chunk-CD4FUZOJ.js';
5
+ import { FlowcraftError } from './chunk-BCRWXTWX.js';
6
+ import { BaseNode } from './chunk-LNK7LZER.js';
7
+
8
+ // src/nodes/subflow.ts
9
+ var SubflowNode = class extends BaseNode {
10
+ async exec(_prepResult, context) {
11
+ const { blueprintId, inputs, outputs } = this.params ?? {};
12
+ const { runtime, workflowState } = context.dependencies;
13
+ if (!blueprintId) {
14
+ throw new FlowcraftError(`Subflow node '${this.nodeId}' is missing 'blueprintId' parameter.`, { isFatal: true });
15
+ }
16
+ const subBlueprint = runtime.blueprints?.[blueprintId] || runtime.runtime?.blueprints?.[blueprintId];
17
+ if (!subBlueprint) {
18
+ throw new FlowcraftError(`Sub-blueprint '${blueprintId}' not found in runtime registry.`, { isFatal: true });
19
+ }
20
+ const subflowInitialContext = {};
21
+ if (inputs) {
22
+ for (const [targetKey, sourceKey] of Object.entries(inputs)) {
23
+ let value = await context.context.get(sourceKey);
24
+ if (value === void 0) {
25
+ value = await context.context.get(`_outputs.${sourceKey}`);
26
+ }
27
+ subflowInitialContext[targetKey] = value;
28
+ }
29
+ } else if (context.input !== void 0) {
30
+ const subAnalysis2 = analyzeBlueprint(subBlueprint);
31
+ for (const startNodeId of subAnalysis2.startNodeIds) {
32
+ const inputKey = `_inputs.${startNodeId}`;
33
+ subflowInitialContext[inputKey] = context.input;
34
+ }
35
+ }
36
+ const subflowState = new WorkflowState(subflowInitialContext);
37
+ const subflowExecContext = new ExecutionContext(
38
+ subBlueprint,
39
+ subflowState,
40
+ runtime.nodeRegistry,
41
+ runtime.executionId,
42
+ runtime.runtime,
43
+ runtime.services,
44
+ runtime.signal,
45
+ runtime.concurrency
46
+ );
47
+ const subflowTraverser = new GraphTraverser(subBlueprint);
48
+ const subflowResult = await runtime.runtime.orchestrator.run(subflowExecContext, subflowTraverser);
49
+ if (subflowResult.status === "awaiting") {
50
+ workflowState.markAsAwaiting(this.nodeId ?? "");
51
+ const subflowStateKey = `_subflowState.${this.nodeId}`;
52
+ await context.context.set(subflowStateKey, subflowResult.serializedContext);
53
+ return { output: void 0 };
54
+ }
55
+ if (subflowResult.status !== "completed") {
56
+ const firstError = subflowResult.errors?.[0];
57
+ const errorMessage = firstError?.message || "Unknown error";
58
+ throw new FlowcraftError(
59
+ `Sub-workflow '${blueprintId}' did not complete successfully. Status: ${subflowResult.status}. Error: ${errorMessage}`,
60
+ {
61
+ cause: firstError,
62
+ nodeId: this.nodeId,
63
+ blueprintId
64
+ }
65
+ );
66
+ }
67
+ const subflowFinalContext = subflowResult.context;
68
+ if (outputs) {
69
+ for (const [parentKey, subKey] of Object.entries(outputs)) {
70
+ const value = subflowFinalContext[`_outputs.${subKey}`] ?? subflowFinalContext[subKey];
71
+ await context.context.set(parentKey, value);
72
+ }
73
+ return { output: subflowFinalContext };
74
+ }
75
+ const subAnalysis = analyzeBlueprint(subBlueprint);
76
+ if (subAnalysis.terminalNodeIds.length === 1) {
77
+ const terminalId = subAnalysis.terminalNodeIds[0];
78
+ return { output: subflowFinalContext[`_outputs.${terminalId}`] };
79
+ }
80
+ const terminalOutputs = {};
81
+ for (const terminalId of subAnalysis.terminalNodeIds) {
82
+ terminalOutputs[terminalId] = subflowFinalContext[`_outputs.${terminalId}`];
83
+ }
84
+ return { output: terminalOutputs };
85
+ }
86
+ };
87
+
88
+ export { SubflowNode };
89
+ //# sourceMappingURL=chunk-MKNZBKSR.js.map
90
+ //# sourceMappingURL=chunk-MKNZBKSR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/nodes/subflow.ts"],"names":["subAnalysis"],"mappings":"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","file":"chunk-MKNZBKSR.js","sourcesContent":["import { analyzeBlueprint } from '../analysis'\nimport { FlowcraftError } from '../errors'\nimport { BaseNode } from '../node'\nimport { ExecutionContext } from '../runtime/execution-context'\nimport { WorkflowState } from '../runtime/state'\nimport { GraphTraverser } from '../runtime/traverser'\nimport type { NodeContext, NodeResult } from '../types'\n\nexport class SubflowNode 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\tconst { blueprintId, inputs, outputs } = this.params ?? {}\n\t\tconst { runtime, workflowState } = context.dependencies\n\n\t\tif (!blueprintId) {\n\t\t\tthrow new FlowcraftError(`Subflow node '${this.nodeId}' is missing 'blueprintId' parameter.`, { isFatal: true })\n\t\t}\n\n\t\tconst subBlueprint =\n\t\t\t(runtime as any).blueprints?.[blueprintId] || (runtime as any).runtime?.blueprints?.[blueprintId]\n\t\tif (!subBlueprint) {\n\t\t\tthrow new FlowcraftError(`Sub-blueprint '${blueprintId}' not found in runtime registry.`, { isFatal: true })\n\t\t}\n\n\t\tconst subflowInitialContext: Record<string, any> = {}\n\n\t\tif (inputs) {\n\t\t\t// explicit inputs\n\t\t\tfor (const [targetKey, sourceKey] of Object.entries(inputs as Record<string, string>)) {\n\t\t\t\tlet value = await context.context.get(sourceKey as any)\n\t\t\t\tif (value === undefined) {\n\t\t\t\t\tvalue = await context.context.get(`_outputs.${sourceKey}` as any)\n\t\t\t\t}\n\t\t\t\tsubflowInitialContext[targetKey] = value\n\t\t\t}\n\t\t} else if (context.input !== undefined) {\n\t\t\t// pass the parent node's input to the subflow's start nodes\n\t\t\tconst subAnalysis = analyzeBlueprint(subBlueprint)\n\t\t\tfor (const startNodeId of subAnalysis.startNodeIds) {\n\t\t\t\tconst inputKey = `_inputs.${startNodeId}`\n\t\t\t\tsubflowInitialContext[inputKey] = context.input\n\t\t\t}\n\t\t}\n\n\t\tconst subflowState = new WorkflowState(subflowInitialContext)\n\t\tconst subflowExecContext = new ExecutionContext(\n\t\t\tsubBlueprint,\n\t\t\tsubflowState,\n\t\t\truntime.nodeRegistry,\n\t\t\truntime.executionId,\n\t\t\truntime.runtime,\n\t\t\truntime.services,\n\t\t\truntime.signal,\n\t\t\truntime.concurrency,\n\t\t)\n\t\tconst subflowTraverser = new GraphTraverser(subBlueprint)\n\n\t\tconst subflowResult = await runtime.runtime.orchestrator.run(subflowExecContext, subflowTraverser)\n\n\t\tif (subflowResult.status === 'awaiting') {\n\t\t\tworkflowState.markAsAwaiting(this.nodeId ?? '')\n\t\t\tconst subflowStateKey = `_subflowState.${this.nodeId}`\n\t\t\tawait context.context.set(subflowStateKey as any, subflowResult.serializedContext)\n\t\t\treturn { output: undefined }\n\t\t}\n\n\t\tif (subflowResult.status !== 'completed') {\n\t\t\tconst firstError = subflowResult.errors?.[0]\n\t\t\tconst errorMessage = firstError?.message || 'Unknown error'\n\t\t\tthrow new FlowcraftError(\n\t\t\t\t`Sub-workflow '${blueprintId}' did not complete successfully. Status: ${subflowResult.status}. Error: ${errorMessage}`,\n\t\t\t\t{\n\t\t\t\t\tcause: firstError,\n\t\t\t\t\tnodeId: this.nodeId,\n\t\t\t\t\tblueprintId,\n\t\t\t\t},\n\t\t\t)\n\t\t}\n\n\t\tconst subflowFinalContext = subflowResult.context as Record<string, any>\n\n\t\tif (outputs) {\n\t\t\tfor (const [parentKey, subKey] of Object.entries(outputs as Record<string, string>)) {\n\t\t\t\tconst value = subflowFinalContext[`_outputs.${subKey}`] ?? subflowFinalContext[subKey]\n\t\t\t\tawait context.context.set(parentKey as any, value)\n\t\t\t}\n\t\t\treturn { output: subflowFinalContext } // Return the whole context if mapping is used\n\t\t}\n\n\t\tconst subAnalysis = analyzeBlueprint(subBlueprint)\n\t\tif (subAnalysis.terminalNodeIds.length === 1) {\n\t\t\tconst terminalId = subAnalysis.terminalNodeIds[0]\n\t\t\treturn { output: subflowFinalContext[`_outputs.${terminalId}`] }\n\t\t}\n\n\t\tconst terminalOutputs: Record<string, any> = {}\n\t\tfor (const terminalId of subAnalysis.terminalNodeIds) {\n\t\t\tterminalOutputs[terminalId] = subflowFinalContext[`_outputs.${terminalId}`]\n\t\t}\n\t\treturn { output: terminalOutputs }\n\t}\n}\n"]}
@@ -0,0 +1,82 @@
1
+ // src/testing/event-logger.ts
2
+ var InMemoryEventLogger = class {
3
+ events = [];
4
+ /**
5
+ * Clears all captured events.
6
+ */
7
+ clear() {
8
+ this.events.length = 0;
9
+ }
10
+ /**
11
+ * The `emit` method required by the IEventBus interface.
12
+ * It simply pushes the received event into the internal events array.
13
+ * @param event The FlowcraftEvent to record.
14
+ */
15
+ async emit(event) {
16
+ this.events.push(event);
17
+ }
18
+ /**
19
+ * Finds the first event of a specific type.
20
+ * @param type The event type to find (e.g., 'node:error').
21
+ * @returns The first matching event, or undefined if not found.
22
+ */
23
+ find(type) {
24
+ return this.events.find((e) => e.type === type);
25
+ }
26
+ /**
27
+ * Filters events to find all occurrences of a specific type.
28
+ * @param type The event type to filter by.
29
+ * @returns An array of matching events.
30
+ */
31
+ filter(type) {
32
+ return this.events.filter((e) => e.type === type);
33
+ }
34
+ /**
35
+ * Prints a formatted log of all captured events to the console.
36
+ * Ideal for debugging failing tests.
37
+ * @param title A title for the log output.
38
+ */
39
+ printLog(title = "Workflow Execution Trace") {
40
+ console.log(`
41
+ --- ${title} ---`);
42
+ if (this.events.length === 0) {
43
+ console.log("No events were captured.");
44
+ console.log("----------------------------------\n");
45
+ return;
46
+ }
47
+ this.events.forEach((event, index) => {
48
+ const { type, payload } = event;
49
+ console.log(`
50
+ [${index + 1}] ${type}`);
51
+ switch (type) {
52
+ case "node:start":
53
+ console.log(` - Node: "${payload.nodeId}" | Input: ${JSON.stringify(payload.input)}`);
54
+ break;
55
+ case "edge:evaluate":
56
+ console.log(` - Edge: "${payload.source}" -> "${payload.target}"`);
57
+ console.log(` - Condition: ${payload.condition || "N/A"} | Result: ${payload.result}`);
58
+ break;
59
+ case "context:change":
60
+ console.log(
61
+ ` - Node "${payload.sourceNode}" wrote to context -> Key: "${payload.key}" | Value: ${JSON.stringify(payload.value)}`
62
+ );
63
+ break;
64
+ case "node:finish":
65
+ console.log(` - Node: "${payload.nodeId}" | Result: ${JSON.stringify(payload.result)}`);
66
+ break;
67
+ case "node:error":
68
+ console.log(` - Node: "${payload.nodeId}"`);
69
+ console.error(" - Error:", payload.error);
70
+ break;
71
+ default:
72
+ console.log(` - Payload: ${JSON.stringify(payload, null, 2)}`);
73
+ }
74
+ });
75
+ console.log(`
76
+ --- End of Trace ---`);
77
+ }
78
+ };
79
+
80
+ export { InMemoryEventLogger };
81
+ //# sourceMappingURL=chunk-MUYLRTSR.js.map
82
+ //# sourceMappingURL=chunk-MUYLRTSR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/testing/event-logger.ts"],"names":[],"mappings":"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","file":"chunk-MUYLRTSR.js","sourcesContent":["import type { FlowcraftEvent, IEventBus } from '../types'\n\n/**\n * A test utility that implements IEventBus to capture all workflow events\n * in memory, acting as a \"flight recorder\" for behavioral testing.\n *\n * @example\n * // In your test file (e.g., resiliency.test.ts)\n * it('should retry a node on failure', async () => {\n * const eventLogger = new InMemoryEventLogger();\n * const runtime = new FlowRuntime({ eventBus: eventLogger });\n *\n * const flow = createFlow('retry-flow')\n * .node('api-call', vi.fn().mockRejectedValueOnce(new Error('fail')), {\n * config: { maxRetries: 2 },\n * });\n *\n * await runtime.run(flow.toBlueprint());\n *\n * // Assert against the captured event history to prove behavior.\n * const retryEvents = eventLogger.filter('node:retry');\n * expect(retryEvents).toHaveLength(1); // The first attempt is not a \"retry\"\n * });\n */\nexport class InMemoryEventLogger implements IEventBus {\n\tpublic readonly events: FlowcraftEvent[] = []\n\n\t/**\n\t * Clears all captured events.\n\t */\n\tpublic clear(): void {\n\t\tthis.events.length = 0\n\t}\n\n\t/**\n\t * The `emit` method required by the IEventBus interface.\n\t * It simply pushes the received event into the internal events array.\n\t * @param event The FlowcraftEvent to record.\n\t */\n\tpublic async emit(event: FlowcraftEvent): Promise<void> {\n\t\tthis.events.push(event)\n\t}\n\n\t/**\n\t * Finds the first event of a specific type.\n\t * @param type The event type to find (e.g., 'node:error').\n\t * @returns The first matching event, or undefined if not found.\n\t */\n\tpublic find<T extends FlowcraftEvent['type']>(type: T): Extract<FlowcraftEvent, { type: T }> | undefined {\n\t\treturn this.events.find((e) => e.type === type) as Extract<FlowcraftEvent, { type: T }> | undefined\n\t}\n\n\t/**\n\t * Filters events to find all occurrences of a specific type.\n\t * @param type The event type to filter by.\n\t * @returns An array of matching events.\n\t */\n\tpublic filter<T extends FlowcraftEvent['type']>(type: T): Extract<FlowcraftEvent, { type: T }>[] {\n\t\treturn this.events.filter((e) => e.type === type) as Extract<FlowcraftEvent, { type: T }>[]\n\t}\n\n\t/**\n\t * Prints a formatted log of all captured events to the console.\n\t * Ideal for debugging failing tests.\n\t * @param title A title for the log output.\n\t */\n\tpublic printLog(title = 'Workflow Execution Trace'): void {\n\t\tconsole.log(`\\n--- ${title} ---`)\n\t\tif (this.events.length === 0) {\n\t\t\tconsole.log('No events were captured.')\n\t\t\tconsole.log('----------------------------------\\n')\n\t\t\treturn\n\t\t}\n\n\t\tthis.events.forEach((event, index) => {\n\t\t\tconst { type, payload } = event\n\t\t\tconsole.log(`\\n[${index + 1}] ${type}`)\n\n\t\t\t// Custom formatting for a more intuitive trace\n\t\t\tswitch (type) {\n\t\t\t\tcase 'node:start':\n\t\t\t\t\tconsole.log(` - Node: \"${payload.nodeId}\" | Input: ${JSON.stringify(payload.input)}`)\n\t\t\t\t\tbreak\n\t\t\t\tcase 'edge:evaluate':\n\t\t\t\t\tconsole.log(` - Edge: \"${payload.source}\" -> \"${payload.target}\"`)\n\t\t\t\t\tconsole.log(` - Condition: ${payload.condition || 'N/A'} | Result: ${payload.result}`)\n\t\t\t\t\tbreak\n\t\t\t\tcase 'context:change':\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t` - Node \"${payload.sourceNode}\" wrote to context -> Key: \"${payload.key}\" | Value: ${JSON.stringify(payload.value)}`,\n\t\t\t\t\t)\n\t\t\t\t\tbreak\n\t\t\t\tcase 'node:finish':\n\t\t\t\t\tconsole.log(` - Node: \"${payload.nodeId}\" | Result: ${JSON.stringify(payload.result)}`)\n\t\t\t\t\tbreak\n\t\t\t\tcase 'node:error':\n\t\t\t\t\tconsole.log(` - Node: \"${payload.nodeId}\"`)\n\t\t\t\t\tconsole.error(' - Error:', payload.error)\n\t\t\t\t\tbreak\n\t\t\t\tdefault:\n\t\t\t\t\tconsole.log(` - Payload: ${JSON.stringify(payload, null, 2)}`)\n\t\t\t}\n\t\t})\n\t\tconsole.log(`\\n--- End of Trace ---`)\n\t}\n}\n"]}
@@ -0,0 +1,3 @@
1
+
2
+ //# sourceMappingURL=chunk-NVJ3ZO3P.js.map
3
+ //# sourceMappingURL=chunk-NVJ3ZO3P.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-HMR2GEGE.js"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-NVJ3ZO3P.js"}
@@ -0,0 +1,3 @@
1
+
2
+ //# sourceMappingURL=chunk-NVLZFLYM.js.map
3
+ //# sourceMappingURL=chunk-NVLZFLYM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-NVLZFLYM.js"}