flowcraft 2.0.0 → 2.1.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.
- package/README.md +51 -5
- package/dist/analysis.d.ts +1 -1
- package/dist/analysis.js +1 -1
- package/dist/{chunk-RYTIQZIB.js → chunk-3XVVR2SR.js} +167 -53
- package/dist/chunk-3XVVR2SR.js.map +1 -0
- package/dist/{chunk-6DNEDIIT.js → chunk-4A627Q6L.js} +47 -23
- package/dist/chunk-4A627Q6L.js.map +1 -0
- package/dist/{chunk-VFC342WL.js → chunk-4PELJWF7.js} +6 -6
- package/dist/chunk-4PELJWF7.js.map +1 -0
- package/dist/{chunk-WXT3YEWU.js → chunk-5ZXV3R5D.js} +2 -2
- package/dist/chunk-5ZXV3R5D.js.map +1 -0
- package/dist/{chunk-UYPIWXZG.js → chunk-CSZ6EOWG.js} +9 -10
- package/dist/chunk-CSZ6EOWG.js.map +1 -0
- package/dist/chunk-CYHZ2YVH.js +24 -0
- package/dist/chunk-CYHZ2YVH.js.map +1 -0
- package/dist/{chunk-J3RNCPED.js → chunk-DSYAC4WB.js} +2 -2
- package/dist/chunk-DSYAC4WB.js.map +1 -0
- package/dist/{chunk-M23P46ZL.js → chunk-HN72TZY5.js} +10 -5
- package/dist/chunk-HN72TZY5.js.map +1 -0
- package/dist/{chunk-MICPMOTW.js → chunk-KWQHFT7E.js} +2 -2
- package/dist/chunk-KWQHFT7E.js.map +1 -0
- package/dist/chunk-M2FRTT2K.js +144 -0
- package/dist/chunk-M2FRTT2K.js.map +1 -0
- package/dist/{chunk-RW4FH7IL.js → chunk-NBIRTKZ7.js} +89 -32
- package/dist/chunk-NBIRTKZ7.js.map +1 -0
- package/dist/chunk-O3XD45IL.js +236 -0
- package/dist/chunk-O3XD45IL.js.map +1 -0
- package/dist/chunk-PH2IYZHV.js +48 -0
- package/dist/chunk-PH2IYZHV.js.map +1 -0
- package/dist/{chunk-DSZSR7UE.js → chunk-U5V5O5MN.js} +11 -2
- package/dist/chunk-U5V5O5MN.js.map +1 -0
- package/dist/{chunk-RAZXOMZC.js → chunk-UETC63DP.js} +7 -6
- package/dist/chunk-UETC63DP.js.map +1 -0
- package/dist/context.d.ts +5 -5
- package/dist/context.js +1 -1
- package/dist/errors.js +1 -1
- package/dist/evaluator.d.ts +21 -13
- package/dist/evaluator.js +1 -1
- package/dist/flow.d.ts +6 -5
- package/dist/flow.js +2 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +15 -15
- package/dist/linter.d.ts +1 -1
- package/dist/linter.js +2 -2
- package/dist/logger.d.ts +5 -5
- package/dist/logger.js +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/node.js +1 -1
- package/dist/runtime/adapter.d.ts +24 -4
- package/dist/runtime/adapter.js +13 -13
- package/dist/runtime/executors.d.ts +7 -7
- package/dist/runtime/executors.js +2 -2
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.js +13 -13
- package/dist/runtime/runtime.d.ts +9 -7
- package/dist/runtime/runtime.js +12 -12
- package/dist/runtime/state.d.ts +2 -2
- package/dist/runtime/state.js +2 -2
- package/dist/runtime/traverser.d.ts +5 -3
- package/dist/runtime/traverser.js +3 -3
- package/dist/runtime/types.d.ts +2 -1
- package/dist/sanitizer.d.ts +1 -1
- package/dist/sanitizer.js +1 -1
- package/dist/serializer.d.ts +2 -1
- package/dist/serializer.js +1 -1
- package/dist/{types-CZN_FcB6.d.ts → types-CQCe_nBM.d.ts} +35 -22
- package/dist/types.d.ts +1 -1
- package/package.json +2 -2
- package/dist/chunk-6DNEDIIT.js.map +0 -1
- package/dist/chunk-734J4PTM.js +0 -100
- package/dist/chunk-734J4PTM.js.map +0 -1
- package/dist/chunk-DSZSR7UE.js.map +0 -1
- package/dist/chunk-GTZC6PQI.js +0 -22
- package/dist/chunk-GTZC6PQI.js.map +0 -1
- package/dist/chunk-J3RNCPED.js.map +0 -1
- package/dist/chunk-M23P46ZL.js.map +0 -1
- package/dist/chunk-MICPMOTW.js.map +0 -1
- package/dist/chunk-NPAJNLXQ.js +0 -106
- package/dist/chunk-NPAJNLXQ.js.map +0 -1
- package/dist/chunk-RAZXOMZC.js.map +0 -1
- package/dist/chunk-REH55ZXV.js +0 -13
- package/dist/chunk-REH55ZXV.js.map +0 -1
- package/dist/chunk-RW4FH7IL.js.map +0 -1
- package/dist/chunk-RYTIQZIB.js.map +0 -1
- package/dist/chunk-UYPIWXZG.js.map +0 -1
- package/dist/chunk-VFC342WL.js.map +0 -1
- package/dist/chunk-WXT3YEWU.js.map +0 -1
|
@@ -1,31 +1,43 @@
|
|
|
1
|
-
import { isNodeClass } from './chunk-
|
|
1
|
+
import { isNodeClass } from './chunk-U5V5O5MN.js';
|
|
2
2
|
|
|
3
3
|
// src/flow.ts
|
|
4
|
+
function _hashFunction(fn) {
|
|
5
|
+
const source = fn.toString();
|
|
6
|
+
let hash = 0;
|
|
7
|
+
for (let i = 0; i < source.length; i++) {
|
|
8
|
+
const char = source.charCodeAt(i);
|
|
9
|
+
hash = (hash << 5) - hash + char;
|
|
10
|
+
hash = hash & hash;
|
|
11
|
+
}
|
|
12
|
+
return Math.abs(hash).toString(16);
|
|
13
|
+
}
|
|
4
14
|
var Flow = class {
|
|
5
15
|
blueprint;
|
|
6
16
|
functionRegistry;
|
|
7
17
|
loopControllerIds;
|
|
18
|
+
loopDefinitions;
|
|
8
19
|
constructor(id) {
|
|
9
20
|
this.blueprint = { id, nodes: [], edges: [] };
|
|
10
21
|
this.functionRegistry = /* @__PURE__ */ new Map();
|
|
11
22
|
this.loopControllerIds = /* @__PURE__ */ new Map();
|
|
23
|
+
this.loopDefinitions = [];
|
|
12
24
|
}
|
|
13
25
|
node(id, implementation, options) {
|
|
14
26
|
let usesKey;
|
|
15
27
|
if (isNodeClass(implementation)) {
|
|
16
|
-
usesKey = implementation.name && implementation.name !== "BaseNode" ? implementation.name : `class_${
|
|
28
|
+
usesKey = implementation.name && implementation.name !== "BaseNode" ? implementation.name : `class_${_hashFunction(implementation)}`;
|
|
17
29
|
this.functionRegistry.set(usesKey, implementation);
|
|
18
30
|
} else {
|
|
19
|
-
usesKey = `fn_${
|
|
31
|
+
usesKey = `fn_${_hashFunction(implementation)}`;
|
|
20
32
|
this.functionRegistry.set(usesKey, implementation);
|
|
21
33
|
}
|
|
22
34
|
const nodeDef = { id, uses: usesKey, ...options };
|
|
23
|
-
this.blueprint.nodes
|
|
35
|
+
this.blueprint.nodes?.push(nodeDef);
|
|
24
36
|
return this;
|
|
25
37
|
}
|
|
26
38
|
edge(source, target, options) {
|
|
27
39
|
const edgeDef = { source, target, ...options };
|
|
28
|
-
this.blueprint.edges
|
|
40
|
+
this.blueprint.edges?.push(edgeDef);
|
|
29
41
|
return this;
|
|
30
42
|
}
|
|
31
43
|
/**
|
|
@@ -44,26 +56,26 @@ var Flow = class {
|
|
|
44
56
|
const gatherId = `${id}_gather`;
|
|
45
57
|
let workerUsesKey;
|
|
46
58
|
if (isNodeClass(worker)) {
|
|
47
|
-
workerUsesKey = worker.name && worker.name !== "BaseNode" ? worker.name : `class_batch_worker_${
|
|
59
|
+
workerUsesKey = worker.name && worker.name !== "BaseNode" ? worker.name : `class_batch_worker_${_hashFunction(worker)}`;
|
|
48
60
|
this.functionRegistry.set(workerUsesKey, worker);
|
|
49
61
|
} else {
|
|
50
|
-
workerUsesKey = `fn_batch_worker_${
|
|
62
|
+
workerUsesKey = `fn_batch_worker_${_hashFunction(worker)}`;
|
|
51
63
|
this.functionRegistry.set(workerUsesKey, worker);
|
|
52
64
|
}
|
|
53
|
-
this.blueprint.nodes
|
|
65
|
+
this.blueprint.nodes?.push({
|
|
54
66
|
id: scatterId,
|
|
55
67
|
uses: "batch-scatter",
|
|
56
|
-
//
|
|
68
|
+
// built-in
|
|
57
69
|
inputs: inputKey,
|
|
58
70
|
params: { workerUsesKey, outputKey, gatherNodeId: gatherId }
|
|
59
71
|
});
|
|
60
|
-
this.blueprint.nodes
|
|
72
|
+
this.blueprint.nodes?.push({
|
|
61
73
|
id: gatherId,
|
|
62
74
|
uses: "batch-gather",
|
|
63
|
-
// built-in
|
|
75
|
+
// built-in
|
|
64
76
|
params: { outputKey },
|
|
65
77
|
config: { joinStrategy: "all" }
|
|
66
|
-
//
|
|
78
|
+
// important: must wait for all scattered jobs
|
|
67
79
|
});
|
|
68
80
|
this.edge(scatterId, gatherId);
|
|
69
81
|
return this;
|
|
@@ -80,21 +92,21 @@ var Flow = class {
|
|
|
80
92
|
const { startNodeId, endNodeId, condition } = options;
|
|
81
93
|
const controllerId = `${id}-loop`;
|
|
82
94
|
this.loopControllerIds.set(id, controllerId);
|
|
83
|
-
this.
|
|
95
|
+
this.loopDefinitions.push({ id, startNodeId, endNodeId });
|
|
96
|
+
this.blueprint.nodes?.push({
|
|
84
97
|
id: controllerId,
|
|
85
98
|
uses: "loop-controller",
|
|
86
|
-
//
|
|
99
|
+
// built-in
|
|
87
100
|
params: { condition },
|
|
88
101
|
config: { joinStrategy: "any" }
|
|
102
|
+
// to allow re-execution on each loop iteration
|
|
89
103
|
});
|
|
90
104
|
this.edge(endNodeId, controllerId);
|
|
91
|
-
this.edge(controllerId, startNodeId, {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if (endNode)
|
|
97
|
-
endNode.config = { ...endNode.config, joinStrategy: "any" };
|
|
105
|
+
this.edge(controllerId, startNodeId, {
|
|
106
|
+
action: "continue",
|
|
107
|
+
transform: `context.${endNodeId}`
|
|
108
|
+
// pass the end node's value to the start node
|
|
109
|
+
});
|
|
98
110
|
return this;
|
|
99
111
|
}
|
|
100
112
|
getLoopControllerId(id) {
|
|
@@ -108,6 +120,18 @@ var Flow = class {
|
|
|
108
120
|
if (!this.blueprint.nodes || this.blueprint.nodes.length === 0) {
|
|
109
121
|
throw new Error("Cannot build a blueprint with no nodes.");
|
|
110
122
|
}
|
|
123
|
+
for (const loopDef of this.loopDefinitions) {
|
|
124
|
+
const startNode = this.blueprint.nodes?.find((n) => n.id === loopDef.startNodeId);
|
|
125
|
+
const endNode = this.blueprint.nodes?.find((n) => n.id === loopDef.endNodeId);
|
|
126
|
+
if (!startNode) {
|
|
127
|
+
throw new Error(`Loop '${loopDef.id}' references non-existent start node '${loopDef.startNodeId}'.`);
|
|
128
|
+
}
|
|
129
|
+
if (!endNode) {
|
|
130
|
+
throw new Error(`Loop '${loopDef.id}' references non-existent end node '${loopDef.endNodeId}'.`);
|
|
131
|
+
}
|
|
132
|
+
startNode.config = { ...startNode.config, joinStrategy: "any" };
|
|
133
|
+
endNode.config = { ...endNode.config, joinStrategy: "any" };
|
|
134
|
+
}
|
|
111
135
|
return this.blueprint;
|
|
112
136
|
}
|
|
113
137
|
getFunctionRegistry() {
|
|
@@ -119,5 +143,5 @@ function createFlow(id) {
|
|
|
119
143
|
}
|
|
120
144
|
|
|
121
145
|
export { Flow, createFlow };
|
|
122
|
-
//# sourceMappingURL=chunk-
|
|
123
|
-
//# sourceMappingURL=chunk-
|
|
146
|
+
//# sourceMappingURL=chunk-4A627Q6L.js.map
|
|
147
|
+
//# sourceMappingURL=chunk-4A627Q6L.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/flow.ts"],"names":[],"mappings":"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","file":"chunk-4A627Q6L.js","sourcesContent":["import { isNodeClass } from './node'\nimport type { EdgeDefinition, NodeClass, NodeDefinition, NodeFunction, WorkflowBlueprint } from './types'\n\n/**\n * Generates a deterministic hash for a function based on its source code.\n */\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\treturn Math.abs(hash).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}>\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}\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 * @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 * @param options.inputKey The key in the context that holds the input array for the batch.\n\t * @param options.outputKey The key in the context where the array of results will be stored.\n\t * @returns The Flow instance for chaining.\n\t */\n\tbatch<TInput = any, TOutput = any, TAction extends string = string>(\n\t\tid: string,\n\t\tworker:\n\t\t\t| NodeFunction<TContext, TDependencies, TInput, TOutput, TAction>\n\t\t\t| NodeClass<TContext, TDependencies, TInput, TOutput, TAction>,\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: keyof TContext\n\t\t},\n\t): this {\n\t\tconst { inputKey, outputKey } = options\n\t\tconst scatterId = `${id}_scatter`\n\t\tconst gatherId = `${id}_gather`\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 },\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 },\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\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 })\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\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\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\treturn this.blueprint as WorkflowBlueprint\n\t}\n\n\tgetFunctionRegistry() {\n\t\treturn this.functionRegistry\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"]}
|
|
@@ -14,16 +14,16 @@ var ConsoleLogger = class {
|
|
|
14
14
|
}
|
|
15
15
|
};
|
|
16
16
|
var NullLogger = class {
|
|
17
|
-
debug() {
|
|
17
|
+
debug(_message, _meta) {
|
|
18
18
|
}
|
|
19
|
-
info() {
|
|
19
|
+
info(_message, _meta) {
|
|
20
20
|
}
|
|
21
|
-
warn() {
|
|
21
|
+
warn(_message, _meta) {
|
|
22
22
|
}
|
|
23
|
-
error() {
|
|
23
|
+
error(_message, _meta) {
|
|
24
24
|
}
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
export { ConsoleLogger, NullLogger };
|
|
28
|
-
//# sourceMappingURL=chunk-
|
|
29
|
-
//# sourceMappingURL=chunk-
|
|
28
|
+
//# sourceMappingURL=chunk-4PELJWF7.js.map
|
|
29
|
+
//# sourceMappingURL=chunk-4PELJWF7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/logger.ts"],"names":[],"mappings":";AAGO,IAAM,gBAAN,MAAuC;AAAA,EAC7C,KAAA,CAAM,SAAiB,IAAA,EAAkC;AACxD,IAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,QAAA,EAAW,OAAO,CAAA,CAAA,EAAI,QAAQ,EAAE,CAAA;AAAA,EAC/C;AAAA,EAEA,IAAA,CAAK,SAAiB,IAAA,EAAkC;AACvD,IAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,OAAA,EAAU,OAAO,CAAA,CAAA,EAAI,QAAQ,EAAE,CAAA;AAAA,EAC7C;AAAA,EAEA,IAAA,CAAK,SAAiB,IAAA,EAAkC;AACvD,IAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,OAAA,EAAU,OAAO,CAAA,CAAA,EAAI,QAAQ,EAAE,CAAA;AAAA,EAC7C;AAAA,EAEA,KAAA,CAAM,SAAiB,IAAA,EAAkC;AACxD,IAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,QAAA,EAAW,OAAO,CAAA,CAAA,EAAI,QAAQ,EAAE,CAAA;AAAA,EAC/C;AACD;AAGO,IAAM,aAAN,MAAoC;AAAA,EAC1C,KAAA,CAAM,UAAkB,KAAA,EAAmC;AAAA,EAAC;AAAA,EAC5D,IAAA,CAAK,UAAkB,KAAA,EAAmC;AAAA,EAAC;AAAA,EAC3D,IAAA,CAAK,UAAkB,KAAA,EAAmC;AAAA,EAAC;AAAA,EAC3D,KAAA,CAAM,UAAkB,KAAA,EAAmC;AAAA,EAAC;AAC7D","file":"chunk-4PELJWF7.js","sourcesContent":["import type { ILogger } from './types'\n\n/** A logger implementation that outputs to the console. */\nexport class ConsoleLogger implements ILogger {\n\tdebug(message: string, meta?: Record<string, any>): void {\n\t\tconsole.debug(`[DEBUG] ${message}`, meta || '')\n\t}\n\n\tinfo(message: string, meta?: Record<string, any>): void {\n\t\tconsole.info(`[INFO] ${message}`, meta || '')\n\t}\n\n\twarn(message: string, meta?: Record<string, any>): void {\n\t\tconsole.warn(`[WARN] ${message}`, meta || '')\n\t}\n\n\terror(message: string, meta?: Record<string, any>): void {\n\t\tconsole.error(`[ERROR] ${message}`, meta || '')\n\t}\n}\n\n/** A logger implementation that does nothing (no-op). */\nexport class NullLogger implements ILogger {\n\tdebug(_message: string, _meta?: Record<string, any>): void {}\n\tinfo(_message: string, _meta?: Record<string, any>): void {}\n\twarn(_message: string, _meta?: Record<string, any>): void {}\n\terror(_message: string, _meta?: Record<string, any>): void {}\n}\n"]}
|
|
@@ -24,5 +24,5 @@ var FatalNodeExecutionError = class extends NodeExecutionError {
|
|
|
24
24
|
};
|
|
25
25
|
|
|
26
26
|
export { CancelledWorkflowError, FatalNodeExecutionError, NodeExecutionError };
|
|
27
|
-
//# sourceMappingURL=chunk-
|
|
28
|
-
//# sourceMappingURL=chunk-
|
|
27
|
+
//# sourceMappingURL=chunk-5ZXV3R5D.js.map
|
|
28
|
+
//# sourceMappingURL=chunk-5ZXV3R5D.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts"],"names":[],"mappings":";AACO,IAAM,kBAAA,GAAN,cAAiC,KAAA,CAAM;AAAA,EAC7C,WAAA,CACC,OAAA,EACgB,MAAA,EACA,WAAA,EACA,eACA,WAAA,EACf;AACD,IAAA,KAAA,CAAM,OAAO,CAAA;AALG,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,WAAA,GAAA,WAAA;AACA,IAAA,IAAA,CAAA,aAAA,GAAA,aAAA;AACA,IAAA,IAAA,CAAA,WAAA,GAAA,WAAA;AAGhB,IAAA,IAAA,CAAK,IAAA,GAAO,oBAAA;AAAA,EACb;AACD;AAGO,IAAM,sBAAA,GAAN,cAAqC,KAAA,CAAM;AAAA,EACjD,WAAA,CACC,OAAA,GAAU,mCAAA,EACM,WAAA,EACf;AACD,IAAA,KAAA,CAAM,OAAO,CAAA;AAFG,IAAA,IAAA,CAAA,WAAA,GAAA,WAAA;AAGhB,IAAA,IAAA,CAAK,IAAA,GAAO,wBAAA;AAAA,EACb;AACD;AAGO,IAAM,uBAAA,GAAN,cAAsC,kBAAA,CAAmB;AAAA,EAC/D,WAAA,CAAY,OAAA,EAAiB,MAAA,EAAgB,WAAA,EAAqB,eAAuB,WAAA,EAAsB;AAC9G,IAAA,KAAA,CAAM,OAAA,EAAS,MAAA,EAAQ,WAAA,EAAa,aAAA,EAAe,WAAW,CAAA;AAC9D,IAAA,IAAA,CAAK,IAAA,GAAO,yBAAA;AAAA,EACb;AACD","file":"chunk-5ZXV3R5D.js","sourcesContent":["/** Error thrown when a node fails during execution. */\nexport class NodeExecutionError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly nodeId: string,\n\t\tpublic readonly blueprintId: string,\n\t\tpublic readonly originalError?: Error,\n\t\tpublic readonly executionId?: string,\n\t) {\n\t\tsuper(message)\n\t\tthis.name = 'NodeExecutionError'\n\t}\n}\n\n/** Error thrown when a workflow is gracefully aborted. */\nexport class CancelledWorkflowError extends Error {\n\tconstructor(\n\t\tmessage = 'Workflow execution was cancelled.',\n\t\tpublic readonly executionId?: string,\n\t) {\n\t\tsuper(message)\n\t\tthis.name = 'CancelledWorkflowError'\n\t}\n}\n\n/** Error thrown for a non-recoverable failure that should halt the workflow immediately. */\nexport class FatalNodeExecutionError extends NodeExecutionError {\n\tconstructor(message: string, nodeId: string, blueprintId: string, originalError?: Error, executionId?: string) {\n\t\tsuper(message, nodeId, blueprintId, originalError, executionId)\n\t\tthis.name = 'FatalNodeExecutionError'\n\t}\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Context } from './chunk-
|
|
1
|
+
import { Context } from './chunk-KWQHFT7E.js';
|
|
2
2
|
|
|
3
3
|
// src/runtime/state.ts
|
|
4
4
|
var WorkflowState = class {
|
|
@@ -17,7 +17,9 @@ var WorkflowState = class {
|
|
|
17
17
|
this.errors.push({
|
|
18
18
|
nodeId,
|
|
19
19
|
message: error.message,
|
|
20
|
-
originalError: error
|
|
20
|
+
originalError: error,
|
|
21
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
22
|
+
stack: error.stack
|
|
21
23
|
});
|
|
22
24
|
}
|
|
23
25
|
clearError(nodeId) {
|
|
@@ -38,12 +40,9 @@ var WorkflowState = class {
|
|
|
38
40
|
getAnyFallbackExecuted() {
|
|
39
41
|
return this.anyFallbackExecuted;
|
|
40
42
|
}
|
|
41
|
-
getStatus(allNodeIds,
|
|
42
|
-
if (this.anyFallbackExecuted)
|
|
43
|
-
|
|
44
|
-
if (this.errors.length > 0)
|
|
45
|
-
return "failed";
|
|
46
|
-
[...allNodeIds].filter((id) => !this._completedNodes.has(id) && !fallbackNodeIds.has(id));
|
|
43
|
+
getStatus(allNodeIds, _fallbackNodeIds) {
|
|
44
|
+
if (this.anyFallbackExecuted) return "completed";
|
|
45
|
+
if (this.errors.length > 0) return "failed";
|
|
47
46
|
return this._completedNodes.size < allNodeIds.size ? "stalled" : "completed";
|
|
48
47
|
}
|
|
49
48
|
toResult(serializer) {
|
|
@@ -58,5 +57,5 @@ var WorkflowState = class {
|
|
|
58
57
|
};
|
|
59
58
|
|
|
60
59
|
export { WorkflowState };
|
|
61
|
-
//# sourceMappingURL=chunk-
|
|
62
|
-
//# sourceMappingURL=chunk-
|
|
60
|
+
//# sourceMappingURL=chunk-CSZ6EOWG.js.map
|
|
61
|
+
//# sourceMappingURL=chunk-CSZ6EOWG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/runtime/state.ts"],"names":[],"mappings":";;;AAGO,IAAM,gBAAN,MAA0D;AAAA,EACxD,eAAA,uBAAsB,GAAA,EAAY;AAAA,EAClC,SAA0B,EAAC;AAAA,EAC3B,mBAAA,GAAsB,KAAA;AAAA,EACtB,OAAA;AAAA,EAER,YAAY,WAAA,EAAgC;AAC3C,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,OAAA,CAAkB,WAAW,CAAA;AAAA,EACjD;AAAA,EAEA,gBAAA,CAAiB,QAAgB,MAAA,EAAa;AAC7C,IAAA,IAAA,CAAK,eAAA,CAAgB,IAAI,MAAM,CAAA;AAC/B,IAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,MAAA,EAA0B,MAAM,CAAA;AAAA,EAClD;AAAA,EAEA,QAAA,CAAS,QAAgB,KAAA,EAAc;AACtC,IAAA,IAAA,CAAK,OAAO,IAAA,CAAK;AAAA,MAChB,MAAA;AAAA,MACA,SAAS,KAAA,CAAM,OAAA;AAAA,MACf,aAAA,EAAe,KAAA;AAAA,MACf,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,MAClC,OAAO,KAAA,CAAM;AAAA,KACb,CAAA;AAAA,EACF;AAAA,EAEA,WAAW,MAAA,EAAgB;AAC1B,IAAA,IAAA,CAAK,MAAA,GAAS,KAAK,MAAA,CAAO,MAAA,CAAO,CAAC,GAAA,KAAQ,GAAA,CAAI,WAAW,MAAM,CAAA;AAAA,EAChE;AAAA,EAEA,oBAAA,GAAuB;AACtB,IAAA,IAAA,CAAK,mBAAA,GAAsB,IAAA;AAAA,EAC5B;AAAA,EAEA,UAAA,GAA8C;AAC7C,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EACb;AAAA,EAEA,iBAAA,GAAiC;AAChC,IAAA,OAAO,IAAI,GAAA,CAAI,IAAA,CAAK,eAAe,CAAA;AAAA,EACpC;AAAA,EAEA,SAAA,GAA6B;AAC5B,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACb;AAAA,EAEA,sBAAA,GAAkC;AACjC,IAAA,OAAO,IAAA,CAAK,mBAAA;AAAA,EACb;AAAA,EAEA,SAAA,CAAU,YAAyB,gBAAA,EAAyD;AAC3F,IAAA,IAAI,IAAA,CAAK,qBAAqB,OAAO,WAAA;AACrC,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,MAAA,GAAS,CAAA,EAAG,OAAO,QAAA;AAEnC,IAAA,OAAO,IAAA,CAAK,eAAA,CAAgB,IAAA,GAAO,UAAA,CAAW,OAAO,SAAA,GAAY,WAAA;AAAA,EAClE;AAAA,EAEA,SAAS,UAAA,EAAmD;AAC3D,IAAA,MAAM,WAAA,GAAc,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAO;AACxC,IAAA,OAAO;AAAA,MACN,OAAA,EAAS,WAAA;AAAA,MACT,iBAAA,EAAmB,UAAA,CAAW,SAAA,CAAU,WAAW,CAAA;AAAA,MACnD,MAAA,EAAQ,KAAK,SAAA,iBAAU,IAAI,KAAI,kBAAG,IAAI,KAAK,CAAA;AAAA,MAC3C,QAAQ,IAAA,CAAK,MAAA,CAAO,MAAA,GAAS,CAAA,GAAI,KAAK,MAAA,GAAS;AAAA,KAChD;AAAA,EACD;AACD","file":"chunk-CSZ6EOWG.js","sourcesContent":["import { Context } from '../context'\nimport type { ContextImplementation, 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: ContextImplementation<TContext>\n\n\tconstructor(initialData: Partial<TContext>) {\n\t\tthis.context = new Context<TContext>(initialData)\n\t}\n\n\taddCompletedNode(nodeId: string, output: any) {\n\t\tthis._completedNodes.add(nodeId)\n\t\tthis.context.set(nodeId as keyof TContext, output)\n\t}\n\n\taddError(nodeId: string, error: Error) {\n\t\tthis.errors.push({\n\t\t\tnodeId,\n\t\t\tmessage: error.message,\n\t\t\toriginalError: error,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tstack: error.stack,\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(): ContextImplementation<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\tgetStatus(allNodeIds: Set<string>, _fallbackNodeIds: Set<string>): WorkflowResult['status'] {\n\t\tif (this.anyFallbackExecuted) return 'completed'\n\t\tif (this.errors.length > 0) return 'failed'\n\t\t// const _remainingNodes = [...allNodeIds].filter((id) => !this._completedNodes.has(id) && !fallbackNodeIds.has(id))\n\t\treturn this._completedNodes.size < allNodeIds.size ? 'stalled' : 'completed'\n\t}\n\n\ttoResult(serializer: ISerializer): WorkflowResult<TContext> {\n\t\tconst contextJSON = this.context.toJSON() as TContext\n\t\treturn {\n\t\t\tcontext: contextJSON,\n\t\t\tserializedContext: serializer.serialize(contextJSON),\n\t\t\tstatus: this.getStatus(new Set(), new Set()),\n\t\t\terrors: this.errors.length > 0 ? this.errors : undefined,\n\t\t}\n\t}\n}\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// src/serializer.ts
|
|
2
|
+
var JsonSerializer = class {
|
|
3
|
+
hasWarned = false;
|
|
4
|
+
serialize(data) {
|
|
5
|
+
for (const value of Object.values(data)) {
|
|
6
|
+
if (value instanceof Map || value instanceof Set || value instanceof Date) {
|
|
7
|
+
if (!this.hasWarned) {
|
|
8
|
+
console.warn(
|
|
9
|
+
"[Flowcraft] Warning: Default JsonSerializer does not support Map, Set, or Date types. Data may be lost. Consider providing a custom ISerializer (e.g., using superjson)."
|
|
10
|
+
);
|
|
11
|
+
this.hasWarned = true;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return JSON.stringify(data);
|
|
16
|
+
}
|
|
17
|
+
deserialize(text) {
|
|
18
|
+
return JSON.parse(text);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export { JsonSerializer };
|
|
23
|
+
//# sourceMappingURL=chunk-CYHZ2YVH.js.map
|
|
24
|
+
//# sourceMappingURL=chunk-CYHZ2YVH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/serializer.ts"],"names":[],"mappings":";AASO,IAAM,iBAAN,MAA4C;AAAA,EAC1C,SAAA,GAAY,KAAA;AAAA,EAEpB,UAAU,IAAA,EAAmC;AAC5C,IAAA,KAAA,MAAW,KAAA,IAAS,MAAA,CAAO,MAAA,CAAO,IAAI,CAAA,EAAG;AACxC,MAAA,IAAI,KAAA,YAAiB,GAAA,IAAO,KAAA,YAAiB,GAAA,IAAO,iBAAiB,IAAA,EAAM;AAC1E,QAAA,IAAI,CAAC,KAAK,SAAA,EAAW;AACpB,UAAA,OAAA,CAAQ,IAAA;AAAA,YACP;AAAA,WACD;AACA,UAAA,IAAA,CAAK,SAAA,GAAY,IAAA;AAAA,QAClB;AAAA,MACD;AAAA,IACD;AACA,IAAA,OAAO,IAAA,CAAK,UAAU,IAAI,CAAA;AAAA,EAC3B;AAAA,EAEA,YAAY,IAAA,EAAmC;AAC9C,IAAA,OAAO,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,EACvB;AACD","file":"chunk-CYHZ2YVH.js","sourcesContent":["import type { ISerializer } from './types'\n\n/**\n * A default serializer using standard JSON.\n *\n * @warning This implementation is lossy and does not handle complex data types\n * like `Date`, `Map`, `Set`, `undefined`, etc. It is recommended to provide a robust\n * serializer like `superjson` if working with complex data types.\n */\nexport class JsonSerializer implements ISerializer {\n\tprivate hasWarned = false\n\n\tserialize(data: Record<string, any>): string {\n\t\tfor (const value of Object.values(data)) {\n\t\t\tif (value instanceof Map || value instanceof Set || value instanceof Date) {\n\t\t\t\tif (!this.hasWarned) {\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t'[Flowcraft] Warning: Default JsonSerializer does not support Map, Set, or Date types. Data may be lost. Consider providing a custom ISerializer (e.g., using superjson).',\n\t\t\t\t\t)\n\t\t\t\t\tthis.hasWarned = true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn JSON.stringify(data)\n\t}\n\n\tdeserialize(text: string): Record<string, any> {\n\t\treturn JSON.parse(text)\n\t}\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/sanitizer.ts"],"names":[],"mappings":";AAOO,SAAS,kBAAkB,GAAA,EAA6B;AAC9D,EAAA,MAAM,KAAA,GACL,GAAA,CAAI,KAAA,EAAO,GAAA,CAAI,CAAC,IAAA,MAAe;AAAA,IAC9B,IAAI,IAAA,CAAK,EAAA;AAAA,IACT,MAAM,IAAA,CAAK,IAAA;AAAA,IACX,QAAQ,IAAA,CAAK,MAAA;AAAA,IACb,QAAQ,IAAA,CAAK,MAAA;AAAA,IACb,QAAQ,IAAA,CAAK;AAAA,GACd,CAAE,KAAK,EAAC;AAET,EAAA,MAAM,KAAA,GACL,GAAA,CAAI,KAAA,EAAO,GAAA,CAAI,CAAC,IAAA,MAAe;AAAA,IAC9B,QAAQ,IAAA,CAAK,MAAA;AAAA,IACb,QAAQ,IAAA,CAAK,MAAA;AAAA,IACb,QAAQ,IAAA,CAAK,MAAA;AAAA,IACb,WAAW,IAAA,CAAK,SAAA;AAAA,IAChB,WAAW,IAAA,CAAK;AAAA,GACjB,CAAE,KAAK,EAAC;AAET,EAAA,OAAO;AAAA,IACN,IAAI,GAAA,CAAI,EAAA;AAAA,IACR,KAAA;AAAA,IACA,KAAA;AAAA,IACA,UAAU,GAAA,CAAI;AAAA,GACf;AACD","file":"chunk-DSYAC4WB.js","sourcesContent":["import type { EdgeDefinition, NodeDefinition, WorkflowBlueprint } from './types'\n\n/**\n * Sanitizes a raw workflow blueprint by removing extra properties\n * added by UI tools (e.g., position, style) and keeping only the\n * properties defined in NodeDefinition and EdgeDefinition.\n */\nexport function sanitizeBlueprint(raw: any): WorkflowBlueprint {\n\tconst nodes: NodeDefinition[] =\n\t\traw.nodes?.map((node: any) => ({\n\t\t\tid: node.id,\n\t\t\tuses: node.uses,\n\t\t\tparams: node.params,\n\t\t\tinputs: node.inputs,\n\t\t\tconfig: node.config,\n\t\t})) || []\n\n\tconst edges: EdgeDefinition[] =\n\t\traw.edges?.map((edge: any) => ({\n\t\t\tsource: edge.source,\n\t\t\ttarget: edge.target,\n\t\t\taction: edge.action,\n\t\t\tcondition: edge.condition,\n\t\t\ttransform: edge.transform,\n\t\t})) || []\n\n\treturn {\n\t\tid: raw.id,\n\t\tnodes,\n\t\tedges,\n\t\tmetadata: raw.metadata,\n\t}\n}\n"]}
|
|
@@ -6,8 +6,12 @@ function checkForCycles(blueprint) {
|
|
|
6
6
|
}
|
|
7
7
|
const allNodeIds = blueprint.nodes.map((node) => node.id);
|
|
8
8
|
const adj = /* @__PURE__ */ new Map();
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
for (const id of allNodeIds) {
|
|
10
|
+
adj.set(id, []);
|
|
11
|
+
}
|
|
12
|
+
for (const edge of blueprint.edges) {
|
|
13
|
+
adj.get(edge.source)?.push(edge.target);
|
|
14
|
+
}
|
|
11
15
|
const visited = /* @__PURE__ */ new Set();
|
|
12
16
|
const recursionStack = /* @__PURE__ */ new Set();
|
|
13
17
|
function detectCycleUtil(nodeId, path) {
|
|
@@ -40,7 +44,8 @@ function generateMermaid(blueprint) {
|
|
|
40
44
|
}
|
|
41
45
|
let mermaid = "flowchart TD\n";
|
|
42
46
|
for (const node of blueprint.nodes) {
|
|
43
|
-
const
|
|
47
|
+
const paramsString = node.params ? `<br/>params: ${JSON.stringify(node.params)}` : "";
|
|
48
|
+
const nodeLabel = `${node.id}${paramsString}`;
|
|
44
49
|
mermaid += ` ${node.id}["${nodeLabel}"]
|
|
45
50
|
`;
|
|
46
51
|
}
|
|
@@ -101,5 +106,5 @@ function analyzeBlueprint(blueprint) {
|
|
|
101
106
|
}
|
|
102
107
|
|
|
103
108
|
export { analyzeBlueprint, checkForCycles, generateMermaid };
|
|
104
|
-
//# sourceMappingURL=chunk-
|
|
105
|
-
//# sourceMappingURL=chunk-
|
|
109
|
+
//# sourceMappingURL=chunk-HN72TZY5.js.map
|
|
110
|
+
//# sourceMappingURL=chunk-HN72TZY5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/analysis.ts"],"names":[],"mappings":"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","file":"chunk-HN72TZY5.js","sourcesContent":["import type { WorkflowBlueprint } from './types'\n\n/**\n * A list of cycles found in the graph. Each cycle is an array of node IDs.\n */\nexport type Cycles = string[][]\n\n/**\n * Analysis result for a workflow blueprint\n */\nexport interface BlueprintAnalysis {\n\t/** Cycles found in the graph */\n\tcycles: Cycles\n\t/** Node IDs that have no incoming edges (start nodes) */\n\tstartNodeIds: string[]\n\t/** Node IDs that have no outgoing edges (terminal nodes) */\n\tterminalNodeIds: string[]\n\t/** Total number of nodes */\n\tnodeCount: number\n\t/** Total number of edges */\n\tedgeCount: number\n\t/** Whether the graph is a valid DAG (no cycles) */\n\tisDag: boolean\n}\n\n/**\n * Analyzes a workflow blueprint to detect cycles.\n * @param blueprint The WorkflowBlueprint object containing nodes and edges.\n * @returns An array of cycles found. Each cycle is represented as an array of node IDs.\n */\nexport function checkForCycles(blueprint: WorkflowBlueprint): Cycles {\n\tconst cycles: Cycles = []\n\tif (!blueprint || !blueprint.nodes || blueprint.nodes.length === 0) {\n\t\treturn cycles\n\t}\n\n\tconst allNodeIds = blueprint.nodes.map((node) => node.id)\n\tconst adj = new Map<string, string[]>()\n\tfor (const id of allNodeIds) {\n\t\tadj.set(id, [])\n\t}\n\tfor (const edge of blueprint.edges) {\n\t\tadj.get(edge.source)?.push(edge.target)\n\t}\n\n\tconst visited = new Set<string>()\n\tconst recursionStack = new Set<string>()\n\n\tfunction detectCycleUtil(nodeId: string, path: string[]) {\n\t\tvisited.add(nodeId)\n\t\trecursionStack.add(nodeId)\n\t\tpath.push(nodeId)\n\n\t\tconst neighbors = adj.get(nodeId) || []\n\t\tfor (const neighbor of neighbors) {\n\t\t\tif (recursionStack.has(neighbor)) {\n\t\t\t\tconst cycleStartIndex = path.indexOf(neighbor)\n\t\t\t\tconst cycle = path.slice(cycleStartIndex)\n\t\t\t\tcycles.push([...cycle, neighbor])\n\t\t\t} else if (!visited.has(neighbor)) {\n\t\t\t\tdetectCycleUtil(neighbor, path)\n\t\t\t}\n\t\t}\n\n\t\trecursionStack.delete(nodeId)\n\t\tpath.pop()\n\t}\n\n\tfor (const nodeId of allNodeIds) {\n\t\tif (!visited.has(nodeId)) {\n\t\t\tdetectCycleUtil(nodeId, [])\n\t\t}\n\t}\n\n\treturn cycles\n}\n\n/**\n * Generates Mermaid diagram syntax from a WorkflowBlueprint\n * @param blueprint The WorkflowBlueprint object containing nodes and edges\n * @returns Mermaid syntax string for the flowchart\n */\nexport function generateMermaid(blueprint: WorkflowBlueprint): string {\n\tif (!blueprint || !blueprint.nodes || blueprint.nodes.length === 0) {\n\t\treturn 'flowchart TD\\n empty[Empty Blueprint]'\n\t}\n\n\tlet mermaid = 'flowchart TD\\n'\n\n\tfor (const node of blueprint.nodes) {\n\t\t// Using backticks and characters like <br/> for newlines in Mermaid labels\n\t\tconst paramsString = node.params ? `<br/>params: ${JSON.stringify(node.params)}` : ''\n\t\tconst nodeLabel = `${node.id}${paramsString}`\n\t\tmermaid += ` ${node.id}[\"${nodeLabel}\"]\\n`\n\t}\n\n\tfor (const edge of blueprint.edges || []) {\n\t\tconst labelParts: string[] = []\n\n\t\tif (edge.action) {\n\t\t\tlabelParts.push(edge.action)\n\t\t}\n\t\tif (edge.condition) {\n\t\t\tlabelParts.push(edge.condition)\n\t\t}\n\t\tif (edge.transform) {\n\t\t\tlabelParts.push(edge.transform)\n\t\t}\n\n\t\tif (labelParts.length > 0) {\n\t\t\tconst edgeLabel = labelParts.join(' | ')\n\t\t\tmermaid += ` ${edge.source} -- \"${edgeLabel}\" --> ${edge.target}\\n`\n\t\t} else {\n\t\t\tmermaid += ` ${edge.source} --> ${edge.target}\\n`\n\t\t}\n\t}\n\n\treturn mermaid\n}\n\n/**\n * Analyzes a workflow blueprint and returns comprehensive analysis\n * @param blueprint The WorkflowBlueprint object containing nodes and edges\n * @returns Analysis result with cycles, start nodes, terminal nodes, and other metrics\n */\nexport function analyzeBlueprint(blueprint: WorkflowBlueprint): BlueprintAnalysis {\n\tif (!blueprint || !blueprint.nodes || blueprint.nodes.length === 0) {\n\t\treturn {\n\t\t\tcycles: [],\n\t\t\tstartNodeIds: [],\n\t\t\tterminalNodeIds: [],\n\t\t\tnodeCount: 0,\n\t\t\tedgeCount: 0,\n\t\t\tisDag: true,\n\t\t}\n\t}\n\n\tconst cycles = checkForCycles(blueprint)\n\tconst nodeCount = blueprint.nodes.length\n\tconst edgeCount = blueprint.edges?.length || 0\n\n\tconst nodesWithIncoming = new Set<string>()\n\tfor (const edge of blueprint.edges || []) {\n\t\tnodesWithIncoming.add(edge.target)\n\t}\n\n\tconst startNodeIds = blueprint.nodes.map((node) => node.id).filter((nodeId) => !nodesWithIncoming.has(nodeId))\n\n\tconst nodesWithOutgoing = new Set<string>()\n\tfor (const edge of blueprint.edges || []) {\n\t\tnodesWithOutgoing.add(edge.source)\n\t}\n\n\tconst terminalNodeIds = blueprint.nodes.map((node) => node.id).filter((nodeId) => !nodesWithOutgoing.has(nodeId))\n\n\treturn {\n\t\tcycles,\n\t\tstartNodeIds,\n\t\tterminalNodeIds,\n\t\tnodeCount,\n\t\tedgeCount,\n\t\tisDag: cycles.length === 0,\n\t}\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/context.ts"],"names":[],"mappings":";AAKO,IAAM,UAAN,MAAsF;AAAA,EAC5E,IAAA,GAAO,MAAA;AAAA,EACf,IAAA;AAAA,EAER,WAAA,CAAY,WAAA,GAAiC,EAAC,EAAG;AAChD,IAAA,IAAA,CAAK,OAAO,IAAI,GAAA,CAAI,MAAA,CAAO,OAAA,CAAQ,WAAW,CAAC,CAAA;AAAA,EAChD;AAAA,EAEA,IAA8B,GAAA,EAAiC;AAC9D,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,EACjC;AAAA,EAEA,GAAA,CAA8B,KAAQ,KAAA,EAA0B;AAC/D,IAAA,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,GAAG,GAAG,KAAK,CAAA;AAAA,EACjC;AAAA,EAEA,IAA8B,GAAA,EAAiB;AAC9C,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,EACjC;AAAA,EAEA,OAAiC,GAAA,EAAiB;AACjD,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,EACpC;AAAA,EAEA,MAAA,GAA8B;AAC7B,IAAA,OAAO,MAAA,CAAO,WAAA,CAAY,IAAA,CAAK,IAAI,CAAA;AAAA,EACpC;AACD;AAMO,IAAM,mBAAN,MAAgG;AAAA,EAGtG,YAAoB,WAAA,EAAqC;AAArC,IAAA,IAAA,CAAA,WAAA,GAAA,WAAA;AAAA,EAAsC;AAAA,EAF1C,IAAA,GAAO,OAAA;AAAA,EAIvB,IAA8B,GAAA,EAA0C;AACvE,IAAA,OAAO,QAAQ,OAAA,CAAQ,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,GAAG,CAAC,CAAA;AAAA,EACjD;AAAA,EAEA,GAAA,CAA8B,KAAQ,KAAA,EAAmC;AACxE,IAAA,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,GAAA,EAAK,KAAK,CAAA;AAC/B,IAAA,OAAO,QAAQ,OAAA,EAAQ;AAAA,EACxB;AAAA,EAEA,IAA8B,GAAA,EAA0B;AACvD,IAAA,OAAO,QAAQ,OAAA,CAAQ,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,GAAG,CAAC,CAAA;AAAA,EACjD;AAAA,EAEA,OAAiC,GAAA,EAA0B;AAC1D,IAAA,OAAO,QAAQ,OAAA,CAAQ,IAAA,CAAK,WAAA,CAAY,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,EACpD;AAAA,EAEA,MAAA,GAAuC;AACtC,IAAA,OAAO,OAAA,CAAQ,OAAA,CAAQ,IAAA,CAAK,WAAA,CAAY,QAAQ,CAAA;AAAA,EACjD;AACD","file":"chunk-KWQHFT7E.js","sourcesContent":["import type { IAsyncContext, ISyncContext } from './types'\n\n/**\n * A default, high-performance, in-memory implementation of ISyncContext using a Map.\n */\nexport class Context<TContext extends Record<string, any>> implements ISyncContext<TContext> {\n\tpublic readonly type = 'sync' as const\n\tprivate data: Map<string, any>\n\n\tconstructor(initialData: Partial<TContext> = {}) {\n\t\tthis.data = new Map(Object.entries(initialData))\n\t}\n\n\tget<K extends keyof TContext>(key: K): TContext[K] | undefined {\n\t\treturn this.data.get(String(key))\n\t}\n\n\tset<K extends keyof TContext>(key: K, value: TContext[K]): void {\n\t\tthis.data.set(String(key), value)\n\t}\n\n\thas<K extends keyof TContext>(key: K): boolean {\n\t\treturn this.data.has(String(key))\n\t}\n\n\tdelete<K extends keyof TContext>(key: K): boolean {\n\t\treturn this.data.delete(String(key))\n\t}\n\n\ttoJSON(): Record<string, any> {\n\t\treturn Object.fromEntries(this.data)\n\t}\n}\n\n/**\n * An adapter that provides a consistent, Promise-based view of a synchronous context.\n * This is created by the runtime and is transparent to the node author.\n */\nexport class AsyncContextView<TContext extends Record<string, any>> implements IAsyncContext<TContext> {\n\tpublic readonly type = 'async' as const\n\n\tconstructor(private syncContext: ISyncContext<TContext>) {}\n\n\tget<K extends keyof TContext>(key: K): Promise<TContext[K] | undefined> {\n\t\treturn Promise.resolve(this.syncContext.get(key))\n\t}\n\n\tset<K extends keyof TContext>(key: K, value: TContext[K]): Promise<void> {\n\t\tthis.syncContext.set(key, value)\n\t\treturn Promise.resolve()\n\t}\n\n\thas<K extends keyof TContext>(key: K): Promise<boolean> {\n\t\treturn Promise.resolve(this.syncContext.has(key))\n\t}\n\n\tdelete<K extends keyof TContext>(key: K): Promise<boolean> {\n\t\treturn Promise.resolve(this.syncContext.delete(key))\n\t}\n\n\ttoJSON(): Promise<Record<string, any>> {\n\t\treturn Promise.resolve(this.syncContext.toJSON())\n\t}\n}\n"]}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { CancelledWorkflowError, FatalNodeExecutionError } from './chunk-5ZXV3R5D.js';
|
|
2
|
+
|
|
3
|
+
// src/runtime/executors.ts
|
|
4
|
+
async function withRetries(executor, maxRetries, nodeDef, context, executionId, signal, eventBus) {
|
|
5
|
+
let lastError;
|
|
6
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
7
|
+
try {
|
|
8
|
+
signal?.throwIfAborted();
|
|
9
|
+
const result = await executor();
|
|
10
|
+
if (attempt > 1) {
|
|
11
|
+
context.dependencies.logger.info(`Node execution succeeded after retry`, {
|
|
12
|
+
nodeId: nodeDef.id,
|
|
13
|
+
attempt,
|
|
14
|
+
executionId
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
return result;
|
|
18
|
+
} catch (error) {
|
|
19
|
+
lastError = error;
|
|
20
|
+
if (error instanceof DOMException && error.name === "AbortError") {
|
|
21
|
+
throw new CancelledWorkflowError("Workflow cancelled");
|
|
22
|
+
}
|
|
23
|
+
if (error instanceof FatalNodeExecutionError) break;
|
|
24
|
+
if (attempt < maxRetries) {
|
|
25
|
+
context.dependencies.logger.warn(`Node execution failed, retrying`, {
|
|
26
|
+
nodeId: nodeDef.id,
|
|
27
|
+
attempt,
|
|
28
|
+
maxRetries,
|
|
29
|
+
error: error instanceof Error ? error.message : String(error),
|
|
30
|
+
executionId
|
|
31
|
+
});
|
|
32
|
+
if (eventBus) {
|
|
33
|
+
await eventBus.emit("node:retry", {
|
|
34
|
+
blueprintId: context.dependencies.blueprint?.id || "",
|
|
35
|
+
nodeId: nodeDef.id,
|
|
36
|
+
attempt,
|
|
37
|
+
executionId
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
} else {
|
|
41
|
+
context.dependencies.logger.error(`Node execution failed after all retries`, {
|
|
42
|
+
nodeId: nodeDef.id,
|
|
43
|
+
attempts: maxRetries,
|
|
44
|
+
error: error instanceof Error ? error.message : String(error),
|
|
45
|
+
executionId
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
throw lastError;
|
|
51
|
+
}
|
|
52
|
+
var FunctionNodeExecutor = class {
|
|
53
|
+
constructor(implementation, maxRetries, eventBus) {
|
|
54
|
+
this.implementation = implementation;
|
|
55
|
+
this.maxRetries = maxRetries;
|
|
56
|
+
this.eventBus = eventBus;
|
|
57
|
+
}
|
|
58
|
+
async execute(nodeDef, context, executionId, signal) {
|
|
59
|
+
return withRetries(
|
|
60
|
+
() => this.implementation(context),
|
|
61
|
+
this.maxRetries,
|
|
62
|
+
nodeDef,
|
|
63
|
+
context,
|
|
64
|
+
executionId,
|
|
65
|
+
signal,
|
|
66
|
+
this.eventBus
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
var ClassNodeExecutor = class {
|
|
71
|
+
constructor(implementation, maxRetries, eventBus) {
|
|
72
|
+
this.implementation = implementation;
|
|
73
|
+
this.maxRetries = maxRetries;
|
|
74
|
+
this.eventBus = eventBus;
|
|
75
|
+
}
|
|
76
|
+
async execute(nodeDef, context, executionId, signal) {
|
|
77
|
+
const instance = new this.implementation(nodeDef.params || {});
|
|
78
|
+
let lastError;
|
|
79
|
+
try {
|
|
80
|
+
signal?.throwIfAborted();
|
|
81
|
+
const prepResult = await instance.prep(context);
|
|
82
|
+
let execResult;
|
|
83
|
+
try {
|
|
84
|
+
execResult = await withRetries(
|
|
85
|
+
() => instance.exec(prepResult, context),
|
|
86
|
+
this.maxRetries,
|
|
87
|
+
nodeDef,
|
|
88
|
+
context,
|
|
89
|
+
executionId,
|
|
90
|
+
signal,
|
|
91
|
+
this.eventBus
|
|
92
|
+
);
|
|
93
|
+
} catch (error) {
|
|
94
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
95
|
+
if (error instanceof DOMException && error.name === "AbortError") {
|
|
96
|
+
throw new CancelledWorkflowError("Workflow cancelled");
|
|
97
|
+
}
|
|
98
|
+
if (error instanceof FatalNodeExecutionError) {
|
|
99
|
+
throw error;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (lastError) {
|
|
103
|
+
signal?.throwIfAborted();
|
|
104
|
+
execResult = await instance.fallback(lastError, context);
|
|
105
|
+
}
|
|
106
|
+
signal?.throwIfAborted();
|
|
107
|
+
if (!execResult) {
|
|
108
|
+
throw new Error("Execution failed after all retries");
|
|
109
|
+
}
|
|
110
|
+
return await instance.post(execResult, context);
|
|
111
|
+
} catch (error) {
|
|
112
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
113
|
+
if (error instanceof DOMException && error.name === "AbortError") {
|
|
114
|
+
throw new CancelledWorkflowError("Workflow cancelled");
|
|
115
|
+
}
|
|
116
|
+
throw error;
|
|
117
|
+
} finally {
|
|
118
|
+
if (lastError) {
|
|
119
|
+
try {
|
|
120
|
+
await instance.recover(lastError, context);
|
|
121
|
+
} catch (recoverError) {
|
|
122
|
+
context.dependencies.logger.warn(`Recover phase failed`, {
|
|
123
|
+
nodeId: nodeDef.id,
|
|
124
|
+
originalError: lastError.message,
|
|
125
|
+
recoverError: recoverError instanceof Error ? recoverError.message : String(recoverError),
|
|
126
|
+
executionId
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
var BuiltInNodeExecutor = class {
|
|
134
|
+
constructor(executeBuiltIn) {
|
|
135
|
+
this.executeBuiltIn = executeBuiltIn;
|
|
136
|
+
}
|
|
137
|
+
async execute(nodeDef, context) {
|
|
138
|
+
return this.executeBuiltIn(nodeDef, context.context);
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
export { BuiltInNodeExecutor, ClassNodeExecutor, FunctionNodeExecutor };
|
|
143
|
+
//# sourceMappingURL=chunk-M2FRTT2K.js.map
|
|
144
|
+
//# sourceMappingURL=chunk-M2FRTT2K.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/runtime/executors.ts"],"names":[],"mappings":"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","file":"chunk-M2FRTT2K.js","sourcesContent":["import { CancelledWorkflowError, FatalNodeExecutionError } from '../errors'\nimport type {\n\tContextImplementation,\n\tIEventBus,\n\tNodeClass,\n\tNodeContext,\n\tNodeDefinition,\n\tNodeFunction,\n\tNodeResult,\n} from '../types'\n\nasync function withRetries<T>(\n\texecutor: () => Promise<T>,\n\tmaxRetries: number,\n\tnodeDef: NodeDefinition,\n\tcontext: NodeContext<any, any, any>,\n\texecutionId?: string,\n\tsignal?: AbortSignal,\n\teventBus?: IEventBus,\n): Promise<T> {\n\tlet lastError: any\n\tfor (let attempt = 1; attempt <= maxRetries; attempt++) {\n\t\ttry {\n\t\t\tsignal?.throwIfAborted()\n\t\t\tconst result = await executor()\n\t\t\tif (attempt > 1) {\n\t\t\t\tcontext.dependencies.logger.info(`Node execution succeeded after retry`, {\n\t\t\t\t\tnodeId: nodeDef.id,\n\t\t\t\t\tattempt,\n\t\t\t\t\texecutionId,\n\t\t\t\t})\n\t\t\t}\n\t\t\treturn result\n\t\t} catch (error) {\n\t\t\tlastError = error\n\t\t\tif (error instanceof DOMException && error.name === 'AbortError') {\n\t\t\t\tthrow new CancelledWorkflowError('Workflow cancelled')\n\t\t\t}\n\t\t\tif (error instanceof FatalNodeExecutionError) break\n\t\t\tif (attempt < maxRetries) {\n\t\t\t\tcontext.dependencies.logger.warn(`Node execution failed, retrying`, {\n\t\t\t\t\tnodeId: nodeDef.id,\n\t\t\t\t\tattempt,\n\t\t\t\t\tmaxRetries,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\texecutionId,\n\t\t\t\t})\n\t\t\t\tif (eventBus) {\n\t\t\t\t\tawait eventBus.emit('node:retry', {\n\t\t\t\t\t\tblueprintId: context.dependencies.blueprint?.id || '',\n\t\t\t\t\t\tnodeId: nodeDef.id,\n\t\t\t\t\t\tattempt,\n\t\t\t\t\t\texecutionId,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcontext.dependencies.logger.error(`Node execution failed after all retries`, {\n\t\t\t\t\tnodeId: nodeDef.id,\n\t\t\t\t\tattempts: maxRetries,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\texecutionId,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\tthrow lastError\n}\n\nexport interface ExecutionStrategy {\n\texecute: (\n\t\tnodeDef: NodeDefinition,\n\t\tcontext: NodeContext<any, any, any>,\n\t\texecutionId?: string,\n\t\tsignal?: AbortSignal,\n\t) => Promise<NodeResult<any, any>>\n}\n\nexport class FunctionNodeExecutor implements ExecutionStrategy {\n\tconstructor(\n\t\tprivate implementation: NodeFunction,\n\t\tprivate maxRetries: number,\n\t\tprivate eventBus: IEventBus,\n\t) {}\n\n\tasync execute(\n\t\tnodeDef: NodeDefinition,\n\t\tcontext: NodeContext<any, any, any>,\n\t\texecutionId?: string,\n\t\tsignal?: AbortSignal,\n\t): Promise<NodeResult<any, any>> {\n\t\treturn withRetries(\n\t\t\t() => this.implementation(context),\n\t\t\tthis.maxRetries,\n\t\t\tnodeDef,\n\t\t\tcontext,\n\t\t\texecutionId,\n\t\t\tsignal,\n\t\t\tthis.eventBus,\n\t\t)\n\t}\n}\n\nexport class ClassNodeExecutor implements ExecutionStrategy {\n\tconstructor(\n\t\tprivate implementation: NodeClass,\n\t\tprivate maxRetries: number,\n\t\tprivate eventBus: IEventBus,\n\t) {}\n\n\tasync execute(\n\t\tnodeDef: NodeDefinition,\n\t\tcontext: NodeContext<any, any, any>,\n\t\texecutionId?: string,\n\t\tsignal?: AbortSignal,\n\t): Promise<NodeResult<any, any>> {\n\t\tconst instance = new this.implementation(nodeDef.params || {})\n\t\tlet lastError: Error | undefined\n\t\ttry {\n\t\t\tsignal?.throwIfAborted()\n\t\t\tconst prepResult = await instance.prep(context)\n\t\t\tlet execResult: Omit<NodeResult, 'error'> | undefined\n\t\t\ttry {\n\t\t\t\texecResult = await withRetries(\n\t\t\t\t\t() => instance.exec(prepResult, context),\n\t\t\t\t\tthis.maxRetries,\n\t\t\t\t\tnodeDef,\n\t\t\t\t\tcontext,\n\t\t\t\t\texecutionId,\n\t\t\t\t\tsignal,\n\t\t\t\t\tthis.eventBus,\n\t\t\t\t)\n\t\t\t} catch (error) {\n\t\t\t\tlastError = error instanceof Error ? error : new Error(String(error))\n\t\t\t\tif (error instanceof DOMException && error.name === 'AbortError') {\n\t\t\t\t\tthrow new CancelledWorkflowError('Workflow cancelled')\n\t\t\t\t}\n\t\t\t\tif (error instanceof FatalNodeExecutionError) {\n\t\t\t\t\tthrow error\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (lastError) {\n\t\t\t\tsignal?.throwIfAborted()\n\t\t\t\texecResult = await instance.fallback(lastError, context)\n\t\t\t}\n\t\t\tsignal?.throwIfAborted()\n\t\t\tif (!execResult) {\n\t\t\t\tthrow new Error('Execution failed after all retries')\n\t\t\t}\n\t\t\treturn await instance.post(execResult, context)\n\t\t} catch (error) {\n\t\t\tlastError = error instanceof Error ? error : new Error(String(error))\n\t\t\tif (error instanceof DOMException && error.name === 'AbortError') {\n\t\t\t\tthrow new CancelledWorkflowError('Workflow cancelled')\n\t\t\t}\n\t\t\tthrow error\n\t\t} finally {\n\t\t\tif (lastError) {\n\t\t\t\ttry {\n\t\t\t\t\tawait instance.recover(lastError, context)\n\t\t\t\t} catch (recoverError) {\n\t\t\t\t\tcontext.dependencies.logger.warn(`Recover phase failed`, {\n\t\t\t\t\t\tnodeId: nodeDef.id,\n\t\t\t\t\t\toriginalError: lastError.message,\n\t\t\t\t\t\trecoverError: recoverError instanceof Error ? recoverError.message : String(recoverError),\n\t\t\t\t\t\texecutionId,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport class BuiltInNodeExecutor implements ExecutionStrategy {\n\tconstructor(\n\t\tprivate executeBuiltIn: (\n\t\t\tnodeDef: NodeDefinition,\n\t\t\tcontext: ContextImplementation<any>,\n\t\t) => Promise<NodeResult<any, any>>,\n\t) {}\n\n\tasync execute(\n\t\tnodeDef: NodeDefinition,\n\t\tcontext: NodeContext<Record<string, unknown>, Record<string, unknown>, any>,\n\t): Promise<NodeResult<any, any>> {\n\t\treturn this.executeBuiltIn(nodeDef, context.context as ContextImplementation<any>)\n\t}\n}\n"]}
|