flowcraft 2.3.1 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analysis.d.ts +1 -1
- package/dist/{chunk-C4HYIJI3.js → chunk-7PBANEG3.js} +16 -2
- package/dist/chunk-7PBANEG3.js.map +1 -0
- package/dist/{chunk-HKX7WQLS.js → chunk-CHG6O6JX.js} +38 -8
- package/dist/chunk-CHG6O6JX.js.map +1 -0
- package/dist/{chunk-XNRIM27H.js → chunk-GIJOZ3AN.js} +4 -4
- package/dist/{chunk-XNRIM27H.js.map → chunk-GIJOZ3AN.js.map} +1 -1
- package/dist/{chunk-CD3Q4N6V.js → chunk-GVF7GQXQ.js} +6 -3
- package/dist/chunk-GVF7GQXQ.js.map +1 -0
- package/dist/{chunk-ZNL7ZXPR.js → chunk-J3HZD5ES.js} +26 -21
- package/dist/chunk-J3HZD5ES.js.map +1 -0
- package/dist/{chunk-MKNZBKSR.js → chunk-K6LPGUPR.js} +4 -4
- package/dist/{chunk-MKNZBKSR.js.map → chunk-K6LPGUPR.js.map} +1 -1
- package/dist/{chunk-FRKO3WX4.js → chunk-KXXEA5VE.js} +3 -3
- package/dist/{chunk-FRKO3WX4.js.map → chunk-KXXEA5VE.js.map} +1 -1
- package/dist/chunk-LJ4COM7S.js +20 -0
- package/dist/chunk-LJ4COM7S.js.map +1 -0
- package/dist/chunk-LM4ACVHL.js +73 -0
- package/dist/chunk-LM4ACVHL.js.map +1 -0
- package/dist/{chunk-33NO4PUJ.js → chunk-NDWVLU7J.js} +3 -3
- package/dist/{chunk-33NO4PUJ.js.map → chunk-NDWVLU7J.js.map} +1 -1
- package/dist/{chunk-CD4FUZOJ.js → chunk-OO3FF3DF.js} +22 -8
- package/dist/chunk-OO3FF3DF.js.map +1 -0
- package/dist/{chunk-QNYXQKFW.js → chunk-OZZP5YI6.js} +3 -3
- package/dist/{chunk-QNYXQKFW.js.map → chunk-OZZP5YI6.js.map} +1 -1
- package/dist/{chunk-BN4MV36K.js → chunk-VN2JKKAE.js} +3 -3
- package/dist/{chunk-BN4MV36K.js.map → chunk-VN2JKKAE.js.map} +1 -1
- package/dist/container-factory.d.ts +1 -1
- package/dist/container-factory.js +4 -4
- package/dist/context.d.ts +1 -1
- package/dist/evaluator.d.ts +1 -1
- package/dist/flow.d.ts +10 -1
- package/dist/flow.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +12 -10
- package/dist/linter.d.ts +1 -1
- package/dist/logger.d.ts +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/nodes/batch-gather.d.ts +1 -1
- package/dist/nodes/batch-scatter.d.ts +1 -1
- package/dist/nodes/sleep.d.ts +9 -0
- package/dist/nodes/sleep.js +4 -0
- package/dist/nodes/sleep.js.map +1 -0
- package/dist/nodes/subflow.d.ts +1 -1
- package/dist/nodes/subflow.js +3 -3
- package/dist/nodes/wait.d.ts +1 -1
- package/dist/nodes/wait.js +1 -1
- package/dist/runtime/adapter.d.ts +2 -1
- package/dist/runtime/adapter.js +10 -8
- package/dist/runtime/execution-context.d.ts +1 -1
- package/dist/runtime/execution-context.js +2 -2
- package/dist/runtime/executors.d.ts +1 -1
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.js +10 -8
- package/dist/runtime/node-executor-factory.d.ts +1 -1
- package/dist/runtime/orchestrator.d.ts +1 -1
- package/dist/runtime/orchestrator.js +3 -3
- package/dist/runtime/orchestrators/step-by-step.d.ts +1 -1
- package/dist/runtime/orchestrators/utils.d.ts +1 -1
- package/dist/runtime/runtime.d.ts +1 -1
- package/dist/runtime/runtime.js +9 -7
- package/dist/runtime/scheduler.d.ts +3 -0
- package/dist/runtime/scheduler.js +3 -0
- package/dist/runtime/scheduler.js.map +1 -0
- package/dist/runtime/state.d.ts +1 -1
- package/dist/runtime/state.js +1 -1
- package/dist/runtime/traverser.d.ts +1 -1
- package/dist/runtime/types.d.ts +1 -1
- package/dist/runtime/workflow-logic-handler.d.ts +1 -1
- package/dist/sanitizer.d.ts +1 -1
- package/dist/serializer.d.ts +1 -1
- package/dist/testing/event-logger.d.ts +1 -1
- package/dist/testing/index.d.ts +1 -1
- package/dist/testing/index.js +13 -11
- package/dist/testing/run-with-trace.d.ts +1 -1
- package/dist/testing/run-with-trace.js +11 -9
- package/dist/testing/stepper.d.ts +1 -1
- package/dist/testing/stepper.js +3 -3
- package/dist/{types-ezHUBdpL.d.ts → types-DWCZW68f.d.ts} +29 -2
- package/dist/types.d.ts +1 -1
- package/package.json +1 -1
- package/dist/chunk-C4HYIJI3.js.map +0 -1
- package/dist/chunk-CD3Q4N6V.js.map +0 -1
- package/dist/chunk-CD4FUZOJ.js.map +0 -1
- package/dist/chunk-HKX7WQLS.js.map +0 -1
- package/dist/chunk-ZNL7ZXPR.js.map +0 -1
package/dist/analysis.d.ts
CHANGED
|
@@ -86,6 +86,20 @@ var Flow = class {
|
|
|
86
86
|
this.edge(scatterId, gatherId);
|
|
87
87
|
return this;
|
|
88
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Creates a sleep node that pauses workflow execution for a specified duration.
|
|
91
|
+
* @param id A unique identifier for the sleep node.
|
|
92
|
+
* @param options Configuration for the sleep duration.
|
|
93
|
+
*/
|
|
94
|
+
sleep(id, options) {
|
|
95
|
+
const nodeDef = {
|
|
96
|
+
id,
|
|
97
|
+
uses: "sleep",
|
|
98
|
+
params: { duration: options.duration }
|
|
99
|
+
};
|
|
100
|
+
this.blueprint.nodes?.push(nodeDef);
|
|
101
|
+
return this;
|
|
102
|
+
}
|
|
89
103
|
/**
|
|
90
104
|
* Creates a wait node that pauses workflow execution for external input.
|
|
91
105
|
* @param id A unique identifier for the wait node.
|
|
@@ -275,5 +289,5 @@ function createFlow(id) {
|
|
|
275
289
|
}
|
|
276
290
|
|
|
277
291
|
export { Flow, createFlow };
|
|
278
|
-
//# sourceMappingURL=chunk-
|
|
279
|
-
//# sourceMappingURL=chunk-
|
|
292
|
+
//# sourceMappingURL=chunk-7PBANEG3.js.map
|
|
293
|
+
//# sourceMappingURL=chunk-7PBANEG3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/flow.ts"],"names":[],"mappings":"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","file":"chunk-7PBANEG3.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 sleep node that pauses workflow execution for a specified duration.\n\t * @param id A unique identifier for the sleep node.\n\t * @param options Configuration for the sleep duration.\n\t */\n\tsleep(\n\t\tid: string,\n\t\toptions: {\n\t\t\t/** The duration to sleep in milliseconds. */\n\t\t\tduration: number\n\t\t},\n\t): this {\n\t\tconst nodeDef: NodeDefinition = {\n\t\t\tid,\n\t\t\tuses: 'sleep',\n\t\t\tparams: { duration: options.duration },\n\t\t}\n\t\tthis.blueprint.nodes?.push(nodeDef)\n\t\treturn this\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"]}
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
+
import { NodeExecutorFactory } from './chunk-DL7KVYZF.js';
|
|
2
|
+
import { WorkflowScheduler } from './chunk-LM4ACVHL.js';
|
|
1
3
|
import { WorkflowLogicHandler } from './chunk-MCGK3FXQ.js';
|
|
2
|
-
import {
|
|
4
|
+
import { SleepNode } from './chunk-LJ4COM7S.js';
|
|
5
|
+
import { SubflowNode } from './chunk-K6LPGUPR.js';
|
|
3
6
|
import { GraphTraverser } from './chunk-G5BGBPFP.js';
|
|
4
|
-
import { WaitNode } from './chunk-
|
|
5
|
-
import { NodeExecutorFactory } from './chunk-DL7KVYZF.js';
|
|
7
|
+
import { WaitNode } from './chunk-GVF7GQXQ.js';
|
|
6
8
|
import { sanitizeBlueprint } from './chunk-DSYAC4WB.js';
|
|
7
9
|
import { BatchGatherNode } from './chunk-BC4G7OM6.js';
|
|
8
10
|
import { BatchScatterNode } from './chunk-RM677CNU.js';
|
|
9
11
|
import { analyzeBlueprint } from './chunk-233SESC2.js';
|
|
10
|
-
import { DefaultOrchestrator } from './chunk-
|
|
11
|
-
import { ExecutionContext } from './chunk-
|
|
12
|
-
import { WorkflowState } from './chunk-
|
|
12
|
+
import { DefaultOrchestrator } from './chunk-NDWVLU7J.js';
|
|
13
|
+
import { ExecutionContext } from './chunk-KXXEA5VE.js';
|
|
14
|
+
import { WorkflowState } from './chunk-OO3FF3DF.js';
|
|
13
15
|
import { NullLogger } from './chunk-4PELJWF7.js';
|
|
14
16
|
import { JsonSerializer } from './chunk-CYHZ2YVH.js';
|
|
15
17
|
import { DIContainer, ServiceTokens } from './chunk-WWGFIYKW.js';
|
|
@@ -32,6 +34,10 @@ var FlowRuntime = class {
|
|
|
32
34
|
options;
|
|
33
35
|
logicHandler;
|
|
34
36
|
executorFactory;
|
|
37
|
+
scheduler;
|
|
38
|
+
getBlueprint(id) {
|
|
39
|
+
return this.blueprints[id];
|
|
40
|
+
}
|
|
35
41
|
constructor(containerOrOptions, legacyOptions) {
|
|
36
42
|
if (containerOrOptions instanceof DIContainer) {
|
|
37
43
|
this.container = containerOrOptions;
|
|
@@ -46,6 +52,7 @@ var FlowRuntime = class {
|
|
|
46
52
|
this.dependencies = this.container.resolve(ServiceTokens.Dependencies);
|
|
47
53
|
this.options = legacyOptions || {};
|
|
48
54
|
this.orchestrator = this.container.resolve(ServiceTokens.Orchestrator);
|
|
55
|
+
this.scheduler = new WorkflowScheduler(this);
|
|
49
56
|
} else {
|
|
50
57
|
const options = containerOrOptions;
|
|
51
58
|
this.logger = options.logger || new NullLogger();
|
|
@@ -66,6 +73,7 @@ var FlowRuntime = class {
|
|
|
66
73
|
};
|
|
67
74
|
const builtInNodes = {
|
|
68
75
|
wait: WaitNode,
|
|
76
|
+
sleep: SleepNode,
|
|
69
77
|
subflow: SubflowNode,
|
|
70
78
|
"batch-scatter": BatchScatterNode,
|
|
71
79
|
"batch-gather": BatchGatherNode,
|
|
@@ -73,6 +81,7 @@ var FlowRuntime = class {
|
|
|
73
81
|
};
|
|
74
82
|
this.registry = new Map(Object.entries({ ...builtInNodes, ...options.registry || {} }));
|
|
75
83
|
this.blueprints = options.blueprints || {};
|
|
84
|
+
this.scheduler = new WorkflowScheduler(this);
|
|
76
85
|
this.dependencies = options.dependencies || {};
|
|
77
86
|
this.options = options;
|
|
78
87
|
this.container = null;
|
|
@@ -168,6 +177,21 @@ var FlowRuntime = class {
|
|
|
168
177
|
errors: result.errors
|
|
169
178
|
}
|
|
170
179
|
});
|
|
180
|
+
if (result.status === "awaiting") {
|
|
181
|
+
const awaitingNodeIds = executionContext.state.getAwaitingNodeIds();
|
|
182
|
+
for (const nodeId of awaitingNodeIds) {
|
|
183
|
+
const details = executionContext.state.getAwaitingDetails(nodeId);
|
|
184
|
+
if (details?.reason === "timer") {
|
|
185
|
+
this.scheduler.registerAwaitingWorkflow(
|
|
186
|
+
executionContext.executionId,
|
|
187
|
+
executionContext.blueprint.id,
|
|
188
|
+
result.serializedContext,
|
|
189
|
+
nodeId,
|
|
190
|
+
details.wakeUpAt
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
171
195
|
return result;
|
|
172
196
|
} catch (error) {
|
|
173
197
|
const duration = Date.now() - startTime;
|
|
@@ -220,6 +244,12 @@ var FlowRuntime = class {
|
|
|
220
244
|
throw error;
|
|
221
245
|
}
|
|
222
246
|
}
|
|
247
|
+
startScheduler() {
|
|
248
|
+
this.scheduler.start();
|
|
249
|
+
}
|
|
250
|
+
stopScheduler() {
|
|
251
|
+
this.scheduler.stop();
|
|
252
|
+
}
|
|
223
253
|
_setupResumedExecutionContext(blueprint, workflowState, options) {
|
|
224
254
|
const executionId = globalThis.crypto?.randomUUID();
|
|
225
255
|
const nodeRegistry = this._createExecutionRegistry(options?.functionRegistry);
|
|
@@ -442,5 +472,5 @@ var FlowRuntime = class {
|
|
|
442
472
|
};
|
|
443
473
|
|
|
444
474
|
export { FlowRuntime };
|
|
445
|
-
//# sourceMappingURL=chunk-
|
|
446
|
-
//# sourceMappingURL=chunk-
|
|
475
|
+
//# sourceMappingURL=chunk-CHG6O6JX.js.map
|
|
476
|
+
//# sourceMappingURL=chunk-CHG6O6JX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/runtime/runtime.ts"],"names":[],"mappings":"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","file":"chunk-CHG6O6JX.js","sourcesContent":["import type { BlueprintAnalysis } from '../analysis'\nimport { analyzeBlueprint } from '../analysis'\nimport { DIContainer, ServiceTokens } from '../container'\nimport { FlowcraftError } from '../errors'\nimport { PropertyEvaluator } from '../evaluator'\nimport { NullLogger } from '../logger'\nimport { BatchGatherNode } from '../nodes/batch-gather'\nimport { BatchScatterNode } from '../nodes/batch-scatter'\nimport { SleepNode } from '../nodes/sleep'\nimport { SubflowNode } from '../nodes/subflow'\nimport { WaitNode } from '../nodes/wait'\nimport { sanitizeBlueprint } from '../sanitizer'\nimport { JsonSerializer } from '../serializer'\nimport type {\n\tContextImplementation,\n\tEdgeDefinition,\n\tIEvaluator,\n\tIEventBus,\n\tILogger,\n\tISerializer,\n\tMiddleware,\n\tNodeClass,\n\tNodeDefinition,\n\tNodeFunction,\n\tNodeResult,\n\tRuntimeOptions,\n\tWorkflowBlueprint,\n\tWorkflowError,\n\tWorkflowResult,\n} from '../types'\nimport { ExecutionContext } from './execution-context'\nimport { NodeExecutorFactory } from './node-executor-factory'\nimport { DefaultOrchestrator } from './orchestrator'\nimport { WorkflowScheduler } from './scheduler'\nimport { WorkflowState } from './state'\nimport { GraphTraverser } from './traverser'\nimport type { IOrchestrator, IRuntime } from './types'\nimport { WorkflowLogicHandler } from './workflow-logic-handler'\n\nexport class FlowRuntime<TContext extends Record<string, any>, TDependencies extends Record<string, any>>\n\timplements IRuntime<TContext, TDependencies>\n{\n\tprivate container: DIContainer\n\tpublic registry: Map<string, NodeFunction | NodeClass>\n\tprivate blueprints: Record<string, WorkflowBlueprint>\n\tpublic dependencies: TDependencies\n\tpublic logger: ILogger\n\tpublic eventBus: IEventBus\n\tpublic serializer: ISerializer\n\tpublic middleware: Middleware[]\n\tpublic evaluator: IEvaluator\n\tprivate analysisCache: WeakMap<WorkflowBlueprint, BlueprintAnalysis>\n\tpublic orchestrator: IOrchestrator\n\tpublic options: RuntimeOptions<TDependencies>\n\tprivate readonly logicHandler: WorkflowLogicHandler\n\tprivate readonly executorFactory: NodeExecutorFactory\n\tpublic scheduler: WorkflowScheduler\n\n\tgetBlueprint(id: string): WorkflowBlueprint | undefined {\n\t\treturn this.blueprints[id]\n\t}\n\n\tconstructor(container: DIContainer, options?: RuntimeOptions<TDependencies>)\n\tconstructor(options: RuntimeOptions<TDependencies>)\n\tconstructor(\n\t\tcontainerOrOptions: DIContainer | RuntimeOptions<TDependencies>,\n\t\tlegacyOptions?: RuntimeOptions<TDependencies>,\n\t) {\n\t\tif (containerOrOptions instanceof DIContainer) {\n\t\t\tthis.container = containerOrOptions\n\t\t\tthis.logger = this.container.resolve<ILogger>(ServiceTokens.Logger)\n\t\t\tthis.serializer = this.container.resolve<ISerializer>(ServiceTokens.Serializer)\n\t\t\tthis.evaluator = this.container.resolve<IEvaluator>(ServiceTokens.Evaluator)\n\t\t\tthis.eventBus = this.container.resolve<IEventBus>(ServiceTokens.EventBus) || { emit: async () => {} }\n\t\t\tthis.middleware = this.container.resolve<Middleware[]>(ServiceTokens.Middleware) || []\n\t\t\tthis.registry = this.container.resolve<Map<string, NodeFunction | NodeClass>>(ServiceTokens.NodeRegistry)\n\t\t\tthis.blueprints = this.container.resolve<Record<string, WorkflowBlueprint>>(ServiceTokens.BlueprintRegistry)\n\t\t\tthis.dependencies = this.container.resolve<TDependencies>(ServiceTokens.Dependencies)\n\t\t\tthis.options = legacyOptions || ({} as RuntimeOptions<TDependencies>)\n\t\t\tthis.orchestrator = this.container.resolve<IOrchestrator>(ServiceTokens.Orchestrator)\n\t\t\tthis.scheduler = new WorkflowScheduler(this)\n\t\t} else {\n\t\t\tconst options = containerOrOptions\n\t\t\tthis.logger = options.logger || new NullLogger()\n\t\t\tthis.serializer = options.serializer || new JsonSerializer()\n\t\t\tthis.evaluator = options.evaluator || new PropertyEvaluator()\n\t\t\tthis.eventBus = options.eventBus || { emit: async () => {} }\n\t\t\tthis.middleware = options.middleware || []\n\t\t\tconst loopControllerFunction: NodeFunction = async (context) => {\n\t\t\t\tconst condition = context.params.condition\n\t\t\t\tconst contextData = await context.context.toJSON()\n\t\t\t\tconst result = this.evaluator.evaluate(condition, contextData)\n\t\t\t\tif (result) {\n\t\t\t\t\treturn { action: 'continue' }\n\t\t\t\t} else {\n\t\t\t\t\treturn { action: 'break', output: null }\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst builtInNodes = {\n\t\t\t\twait: WaitNode,\n\t\t\t\tsleep: SleepNode,\n\t\t\t\tsubflow: SubflowNode,\n\t\t\t\t'batch-scatter': BatchScatterNode,\n\t\t\t\t'batch-gather': BatchGatherNode,\n\t\t\t\t'loop-controller': loopControllerFunction,\n\t\t\t}\n\t\t\tthis.registry = new Map(Object.entries({ ...builtInNodes, ...(options.registry || {}) }))\n\t\t\tthis.blueprints = options.blueprints || {}\n\t\t\tthis.scheduler = new WorkflowScheduler(this)\n\t\t\tthis.dependencies = options.dependencies || ({} as TDependencies)\n\t\t\tthis.options = options\n\t\t\tthis.container = null as any\n\t\t}\n\t\tthis.orchestrator = this.container?.has(ServiceTokens.Orchestrator)\n\t\t\t? this.container.resolve<IOrchestrator>(ServiceTokens.Orchestrator)\n\t\t\t: new DefaultOrchestrator()\n\t\tthis.analysisCache = new WeakMap()\n\t\tthis.logicHandler = new WorkflowLogicHandler(this.evaluator, this.eventBus)\n\t\tthis.executorFactory = new NodeExecutorFactory(this.eventBus)\n\t}\n\n\tprivate _setupExecutionContext(\n\t\tblueprint: WorkflowBlueprint,\n\t\tinitialState: Partial<TContext> | string,\n\t\toptions?: {\n\t\t\tfunctionRegistry?: Map<string, any>\n\t\t\tstrict?: boolean\n\t\t\tsignal?: AbortSignal\n\t\t\tconcurrency?: number\n\t\t},\n\t): ExecutionContext<TContext, TDependencies> {\n\t\tconst executionId = globalThis.crypto?.randomUUID()\n\t\tconst contextData =\n\t\t\ttypeof initialState === 'string' ? (this.serializer.deserialize(initialState) as Partial<TContext>) : initialState\n\t\tblueprint = sanitizeBlueprint(blueprint)\n\t\tconst state = new WorkflowState<TContext>(contextData)\n\t\tconst nodeRegistry = this._createExecutionRegistry(options?.functionRegistry)\n\t\treturn new ExecutionContext(\n\t\t\tblueprint,\n\t\t\tstate,\n\t\t\tnodeRegistry,\n\t\t\texecutionId,\n\t\t\tthis,\n\t\t\t{\n\t\t\t\tlogger: this.logger,\n\t\t\t\teventBus: this.eventBus,\n\t\t\t\tserializer: this.serializer,\n\t\t\t\tevaluator: this.evaluator,\n\t\t\t\tmiddleware: this.middleware,\n\t\t\t\tdependencies: this.dependencies,\n\t\t\t},\n\t\t\toptions?.signal,\n\t\t\toptions?.concurrency,\n\t\t)\n\t}\n\n\tasync run(\n\t\tblueprint: WorkflowBlueprint,\n\t\tinitialState: Partial<TContext> | string = {},\n\t\toptions?: {\n\t\t\tfunctionRegistry?: Map<string, any>\n\t\t\tstrict?: boolean\n\t\t\tsignal?: AbortSignal\n\t\t\tconcurrency?: number\n\t\t},\n\t): Promise<WorkflowResult<TContext>> {\n\t\tconst startTime = Date.now()\n\t\tconst executionContext = this._setupExecutionContext(blueprint, initialState, options)\n\n\t\tthis.logger.info(`Starting workflow execution`, {\n\t\t\tblueprintId: executionContext.blueprint.id,\n\t\t\texecutionId: executionContext.executionId,\n\t\t})\n\n\t\ttry {\n\t\t\tawait this.eventBus.emit({\n\t\t\t\ttype: 'workflow:start',\n\t\t\t\tpayload: { blueprintId: executionContext.blueprint.id, executionId: executionContext.executionId },\n\t\t\t})\n\t\t\tawait this.eventBus.emit({\n\t\t\t\ttype: 'workflow:resume',\n\t\t\t\tpayload: { blueprintId: executionContext.blueprint.id, executionId: executionContext.executionId },\n\t\t\t})\n\t\t\tconst analysis =\n\t\t\t\tthis.analysisCache.get(executionContext.blueprint) ??\n\t\t\t\t(() => {\n\t\t\t\t\tconst computed = analyzeBlueprint(executionContext.blueprint)\n\t\t\t\t\tthis.analysisCache.set(executionContext.blueprint, computed)\n\t\t\t\t\treturn computed\n\t\t\t\t})()\n\t\t\tif (options?.strict && !analysis.isDag) {\n\t\t\t\tthrow new Error(`Workflow '${executionContext.blueprint.id}' failed strictness check: Cycles are not allowed.`)\n\t\t\t}\n\t\t\tif (!analysis.isDag) {\n\t\t\t\tthis.logger.warn(`Workflow contains cycles`, {\n\t\t\t\t\tblueprintId: executionContext.blueprint.id,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tconst traverser = new GraphTraverser(executionContext.blueprint, options?.strict === true)\n\t\t\tconst result = await this.orchestrator.run(executionContext, traverser)\n\n\t\t\tconst duration = Date.now() - startTime\n\t\t\tif (result.status === 'stalled') {\n\t\t\t\tawait this.eventBus.emit({\n\t\t\t\t\ttype: 'workflow:stall',\n\t\t\t\t\tpayload: {\n\t\t\t\t\t\tblueprintId: executionContext.blueprint.id,\n\t\t\t\t\t\texecutionId: executionContext.executionId,\n\t\t\t\t\t\tremainingNodes: traverser.getAllNodeIds().size - executionContext.state.getCompletedNodes().size,\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t\tawait this.eventBus.emit({\n\t\t\t\t\ttype: 'workflow:pause',\n\t\t\t\t\tpayload: { blueprintId: executionContext.blueprint.id, executionId: executionContext.executionId },\n\t\t\t\t})\n\t\t\t}\n\t\t\tthis.logger.info(`Workflow execution completed`, {\n\t\t\t\tblueprintId: executionContext.blueprint.id,\n\t\t\t\texecutionId: executionContext.executionId,\n\t\t\t\tstatus: result.status,\n\t\t\t\tduration,\n\t\t\t\terrors: result.errors?.length || 0,\n\t\t\t})\n\t\t\tawait this.eventBus.emit({\n\t\t\t\ttype: 'workflow:finish',\n\t\t\t\tpayload: {\n\t\t\t\t\tblueprintId: executionContext.blueprint.id,\n\t\t\t\t\texecutionId: executionContext.executionId,\n\t\t\t\t\tstatus: result.status,\n\t\t\t\t\terrors: result.errors,\n\t\t\t\t},\n\t\t\t})\n\n\t\t\tif (result.status === 'awaiting') {\n\t\t\t\tconst awaitingNodeIds = executionContext.state.getAwaitingNodeIds()\n\t\t\t\tfor (const nodeId of awaitingNodeIds) {\n\t\t\t\t\tconst details = executionContext.state.getAwaitingDetails(nodeId)\n\t\t\t\t\tif (details?.reason === 'timer') {\n\t\t\t\t\t\tthis.scheduler.registerAwaitingWorkflow(\n\t\t\t\t\t\t\texecutionContext.executionId,\n\t\t\t\t\t\t\texecutionContext.blueprint.id,\n\t\t\t\t\t\t\tresult.serializedContext,\n\t\t\t\t\t\t\tnodeId,\n\t\t\t\t\t\t\tdetails.wakeUpAt,\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn result\n\t\t} catch (error) {\n\t\t\tconst duration = Date.now() - startTime\n\t\t\tconst workflowError: WorkflowError = {\n\t\t\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t\tisFatal: false,\n\t\t\t\tname: 'WorkflowError',\n\t\t\t}\n\t\t\tawait this.eventBus.emit({\n\t\t\t\ttype: 'workflow:finish',\n\t\t\t\tpayload: {\n\t\t\t\t\tblueprintId: executionContext.blueprint.id,\n\t\t\t\t\texecutionId: executionContext.executionId,\n\t\t\t\t\tstatus: 'cancelled',\n\t\t\t\t\terrors: [workflowError],\n\t\t\t\t},\n\t\t\t})\n\t\t\tif (\n\t\t\t\terror instanceof DOMException\n\t\t\t\t\t? error.name === 'AbortError'\n\t\t\t\t\t: error instanceof FlowcraftError && error.message.includes('cancelled')\n\t\t\t) {\n\t\t\t\tthis.logger.info(`Workflow execution cancelled`, {\n\t\t\t\t\tblueprintId: executionContext.blueprint.id,\n\t\t\t\t\texecutionId: executionContext.executionId,\n\t\t\t\t\tduration,\n\t\t\t\t})\n\t\t\t\tawait this.eventBus.emit({\n\t\t\t\t\ttype: 'workflow:pause',\n\t\t\t\t\tpayload: { blueprintId: executionContext.blueprint.id, executionId: executionContext.executionId },\n\t\t\t\t})\n\t\t\t\tawait this.eventBus.emit({\n\t\t\t\t\ttype: 'workflow:finish',\n\t\t\t\t\tpayload: {\n\t\t\t\t\t\tblueprintId: executionContext.blueprint.id,\n\t\t\t\t\t\texecutionId: executionContext.executionId,\n\t\t\t\t\t\tstatus: 'cancelled',\n\t\t\t\t\t\terrors: [workflowError],\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t\treturn {\n\t\t\t\t\tcontext: {} as TContext,\n\t\t\t\t\tserializedContext: '{}',\n\t\t\t\t\tstatus: 'cancelled',\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.logger.error(`Workflow execution failed`, {\n\t\t\t\tblueprintId: executionContext.blueprint.id,\n\t\t\t\texecutionId: executionContext.executionId,\n\t\t\t\tduration,\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t})\n\t\t\tthrow error\n\t\t}\n\t}\n\n\tstartScheduler(): void {\n\t\tthis.scheduler.start()\n\t}\n\n\tstopScheduler(): void {\n\t\tthis.scheduler.stop()\n\t}\n\n\tprivate _setupResumedExecutionContext(\n\t\tblueprint: WorkflowBlueprint,\n\t\tworkflowState: WorkflowState<TContext>,\n\t\toptions?: {\n\t\t\tfunctionRegistry?: Map<string, any>\n\t\t\tstrict?: boolean\n\t\t\tsignal?: AbortSignal\n\t\t\tconcurrency?: number\n\t\t},\n\t): ExecutionContext<TContext, TDependencies> {\n\t\tconst executionId = globalThis.crypto?.randomUUID()\n\t\tconst nodeRegistry = this._createExecutionRegistry(options?.functionRegistry)\n\t\treturn new ExecutionContext(\n\t\t\tblueprint,\n\t\t\tworkflowState,\n\t\t\tnodeRegistry,\n\t\t\texecutionId,\n\t\t\tthis,\n\t\t\t{\n\t\t\t\tlogger: this.logger,\n\t\t\t\teventBus: this.eventBus,\n\t\t\t\tserializer: this.serializer,\n\t\t\t\tevaluator: this.evaluator,\n\t\t\t\tmiddleware: this.middleware,\n\t\t\t\tdependencies: this.dependencies,\n\t\t\t},\n\t\t\toptions?.signal,\n\t\t)\n\t}\n\n\tasync resume(\n\t\tblueprint: WorkflowBlueprint,\n\t\tserializedContext: string,\n\t\tresumeData: { output?: any; action?: string },\n\t\tnodeId?: string,\n\t\toptions?: {\n\t\t\tfunctionRegistry?: Map<string, any>\n\t\t\tstrict?: boolean\n\t\t\tsignal?: AbortSignal\n\t\t\tconcurrency?: number\n\t\t},\n\t): Promise<WorkflowResult<TContext>> {\n\t\tconst executionId = globalThis.crypto?.randomUUID()\n\t\tconst workflowState = new WorkflowState<TContext>(\n\t\t\tthis.serializer.deserialize(serializedContext) as Partial<TContext>,\n\t\t)\n\n\t\tconst awaitingNodeIds = workflowState.getAwaitingNodeIds()\n\t\tif (awaitingNodeIds.length === 0) {\n\t\t\tthrow new FlowcraftError('Cannot resume: The provided context is not in an awaiting state.', {\n\t\t\t\tisFatal: true,\n\t\t\t})\n\t\t}\n\n\t\tconst awaitingNodeId = nodeId || awaitingNodeIds[0]\n\t\tif (!awaitingNodeIds.includes(awaitingNodeId)) {\n\t\t\tthrow new FlowcraftError(`Cannot resume: Node '${awaitingNodeId}' is not in an awaiting state.`, {\n\t\t\t\tisFatal: true,\n\t\t\t})\n\t\t}\n\n\t\tconst awaitingNodeDef = blueprint.nodes.find((n) => n.id === awaitingNodeId)\n\t\tif (!awaitingNodeDef) {\n\t\t\tthrow new FlowcraftError(`Awaiting node '${awaitingNodeId}' not found in blueprint.`, {\n\t\t\t\tnodeId: awaitingNodeId,\n\t\t\t\tblueprintId: blueprint.id,\n\t\t\t\tisFatal: true,\n\t\t\t})\n\t\t}\n\n\t\tconst contextImpl = workflowState.getContext()\n\n\t\tif (awaitingNodeDef.uses === 'SubflowNode') {\n\t\t\tconst subflowStateKey = `_subflowState.${awaitingNodeId}`\n\t\t\tconst asyncContext = contextImpl\n\t\t\tconst subflowContext = (await asyncContext.get(subflowStateKey as any)) as string\n\n\t\t\tif (!subflowContext) {\n\t\t\t\tthrow new FlowcraftError(`Cannot resume: Subflow state for node '${awaitingNodeId}' not found.`, {\n\t\t\t\t\tnodeId: awaitingNodeId,\n\t\t\t\t\tblueprintId: blueprint.id,\n\t\t\t\t\tisFatal: true,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tconst blueprintId = awaitingNodeDef.params?.blueprintId\n\t\t\tif (!blueprintId) {\n\t\t\t\tthrow new FlowcraftError(`Subflow node '${awaitingNodeId}' is missing the 'blueprintId' parameter.`, {\n\t\t\t\t\tnodeId: awaitingNodeId,\n\t\t\t\t\tblueprintId: blueprint.id,\n\t\t\t\t\tisFatal: true,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tconst subBlueprint = this.blueprints[blueprintId]\n\t\t\tif (!subBlueprint) {\n\t\t\t\tthrow new FlowcraftError(`Sub-blueprint with ID '${blueprintId}' not found in runtime registry.`, {\n\t\t\t\t\tnodeId: awaitingNodeId,\n\t\t\t\t\tblueprintId: blueprint.id,\n\t\t\t\t\tisFatal: true,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tconst subflowResumeResult = await this.resume(subBlueprint, subflowContext, resumeData, undefined, options)\n\n\t\t\tif (subflowResumeResult.status !== 'completed') {\n\t\t\t\tthrow new FlowcraftError(\n\t\t\t\t\t`Resumed subflow '${subBlueprint.id}' did not complete. Status: ${subflowResumeResult.status}`,\n\t\t\t\t\t{\n\t\t\t\t\t\tnodeId: awaitingNodeId,\n\t\t\t\t\t\tblueprintId: blueprint.id,\n\t\t\t\t\t\tisFatal: false,\n\t\t\t\t\t},\n\t\t\t\t)\n\t\t\t}\n\n\t\t\t// mirror the output extraction logic from SubflowNode.exec\n\t\t\tconst subflowFinalContext = subflowResumeResult.context as Record<string, any>\n\t\t\tlet finalSubflowOutput: any\n\t\t\tconst subAnalysis = analyzeBlueprint(subBlueprint)\n\n\t\t\tif (awaitingNodeDef.params?.outputs) {\n\t\t\t\tfinalSubflowOutput = subflowFinalContext\n\t\t\t} else if (subAnalysis.terminalNodeIds.length === 1) {\n\t\t\t\tconst terminalId = subAnalysis.terminalNodeIds[0]\n\t\t\t\tfinalSubflowOutput = subflowFinalContext[`_outputs.${terminalId}`]\n\t\t\t} else {\n\t\t\t\tconst terminalOutputs: Record<string, any> = {}\n\t\t\t\tfor (const terminalId of subAnalysis.terminalNodeIds) {\n\t\t\t\t\tterminalOutputs[terminalId] = subflowFinalContext[`_outputs.${terminalId}`]\n\t\t\t\t}\n\t\t\t\tfinalSubflowOutput = terminalOutputs\n\t\t\t}\n\n\t\t\tresumeData = { output: finalSubflowOutput }\n\n\t\t\tawait contextImpl.delete(subflowStateKey as any)\n\t\t}\n\n\t\tworkflowState.addCompletedNode(awaitingNodeId, resumeData.output)\n\n\t\tconst nextSteps = await this.determineNextNodes(blueprint, awaitingNodeId, resumeData, contextImpl, executionId)\n\n\t\tif (nextSteps.length === 0) {\n\t\t\tworkflowState.clearAwaiting(awaitingNodeId)\n\t\t\tconst result = await workflowState.toResult(this.serializer)\n\t\t\tresult.status = 'completed'\n\t\t\treturn result\n\t\t}\n\n\t\tconst traverserForResume = new GraphTraverser(blueprint)\n\t\tconst allPredecessors = traverserForResume.getAllPredecessors()\n\n\t\tfor (const { node, edge } of nextSteps) {\n\t\t\tawait this.applyEdgeTransform(edge, resumeData, node, contextImpl, allPredecessors)\n\t\t}\n\n\t\tconst traverser = GraphTraverser.fromState(blueprint, workflowState)\n\n\t\tconst nextNodeDefs = nextSteps.map((s) => s.node)\n\t\tfor (const nodeDef of nextNodeDefs) {\n\t\t\ttraverser.addToFrontier(nodeDef.id)\n\t\t}\n\n\t\tworkflowState.clearAwaiting(awaitingNodeId)\n\n\t\tconst executionContext = this._setupResumedExecutionContext(blueprint, workflowState, options)\n\n\t\treturn await this.orchestrator.run(executionContext, traverser)\n\t}\n\n\tpublic _createExecutionRegistry(dynamicRegistry?: Map<string, any>): Map<string, NodeFunction | NodeClass> {\n\t\tconst executionRegistry = new Map(this.registry)\n\t\tif (dynamicRegistry) {\n\t\t\tfor (const [key, func] of dynamicRegistry.entries()) {\n\t\t\t\texecutionRegistry.set(key, func)\n\t\t\t}\n\t\t}\n\t\treturn executionRegistry\n\t}\n\n\tasync executeNode(\n\t\tblueprint: WorkflowBlueprint,\n\t\tnodeId: string,\n\t\tstate: WorkflowState<TContext>,\n\t\t_allPredecessors?: Map<string, Set<string>>,\n\t\tfunctionRegistry?: Map<string, any>,\n\t\texecutionId?: string,\n\t\tsignal?: AbortSignal,\n\t): Promise<NodeResult<any, 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\texecutionId,\n\t\t\t\tisFatal: false,\n\t\t\t})\n\t\t}\n\n\t\tconst contextImpl = state.getContext()\n\t\tconst asyncContext = contextImpl\n\n\t\tconst input = await this.resolveNodeInput(nodeDef.id, blueprint, asyncContext)\n\t\tconst nodeRegistry = new Map([...this.registry, ...(functionRegistry || new Map())])\n\n\t\tconst services = {\n\t\t\tlogger: this.logger,\n\t\t\teventBus: this.eventBus,\n\t\t\tserializer: this.serializer,\n\t\t\tevaluator: this.evaluator,\n\t\t\tmiddleware: this.middleware,\n\t\t\tdependencies: this.dependencies,\n\t\t}\n\t\tconst context = new ExecutionContext(blueprint, state, nodeRegistry, executionId || '', this, services, signal)\n\n\t\tconst executor = this.executorFactory.createExecutorForNode(nodeId, context)\n\n\t\tconst executionResult = await executor.execute(input)\n\n\t\tif (executionResult.status === 'success') {\n\t\t\treturn executionResult.result\n\t\t}\n\n\t\tif (executionResult.status === 'failed_with_fallback') {\n\t\t\tconst fallbackNode = blueprint.nodes.find((n: NodeDefinition) => n.id === executionResult.fallbackNodeId)\n\t\t\tif (!fallbackNode) {\n\t\t\t\tthrow new FlowcraftError(`Fallback node '${executionResult.fallbackNodeId}' not found in blueprint.`, {\n\t\t\t\t\tnodeId: nodeDef.id,\n\t\t\t\t\tblueprintId: blueprint.id,\n\t\t\t\t\texecutionId,\n\t\t\t\t\tisFatal: false,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tconst fallbackInput = await this.resolveNodeInput(fallbackNode.id, blueprint, asyncContext)\n\t\t\tconst fallbackExecutor = this.executorFactory.createExecutorForNode(fallbackNode.id, context)\n\n\t\t\tconst fallbackResult = await fallbackExecutor.execute(fallbackInput)\n\t\t\tif (fallbackResult.status === 'success') {\n\t\t\t\tstate.markFallbackExecuted()\n\t\t\t\tstate.addCompletedNode(executionResult.fallbackNodeId, fallbackResult.result.output)\n\t\t\t\tthis.logger.info(`Fallback execution completed`, {\n\t\t\t\t\tnodeId: nodeDef.id,\n\t\t\t\t\tfallbackNodeId: executionResult.fallbackNodeId,\n\t\t\t\t\texecutionId,\n\t\t\t\t})\n\t\t\t\treturn { ...fallbackResult.result, _fallbackExecuted: true }\n\t\t\t}\n\n\t\t\tthrow fallbackResult.error\n\t\t}\n\n\t\tthrow executionResult.error\n\t}\n\n\tpublic getExecutorForNode(nodeId: string, context: ExecutionContext<TContext, TDependencies>): any {\n\t\treturn this.executorFactory.createExecutorForNode(nodeId, context)\n\t}\n\n\tpublic createForSubflow(\n\t\tsubBlueprint: WorkflowBlueprint,\n\t\tinitialSubState: Partial<TContext>,\n\t\texecutionId: string,\n\t\tsignal?: AbortSignal,\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.registry,\n\t\t\texecutionId,\n\t\t\tthis,\n\t\t\t{\n\t\t\t\tlogger: this.logger,\n\t\t\t\teventBus: this.eventBus,\n\t\t\t\tserializer: this.serializer,\n\t\t\t\tevaluator: this.evaluator,\n\t\t\t\tmiddleware: this.middleware,\n\t\t\t\tdependencies: this.dependencies,\n\t\t\t},\n\t\t\tsignal,\n\t\t)\n\t}\n\n\tasync determineNextNodes(\n\t\tblueprint: WorkflowBlueprint,\n\t\tnodeId: string,\n\t\tresult: NodeResult<any, any>,\n\t\tcontext: ContextImplementation<TContext>,\n\t\texecutionId?: string,\n\t): Promise<{ node: NodeDefinition; edge: EdgeDefinition }[]> {\n\t\treturn this.logicHandler.determineNextNodes(blueprint, nodeId, result, context, executionId)\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<TContext>,\n\t\tallPredecessors?: Map<string, Set<string>>,\n\t): Promise<void> {\n\t\treturn this.logicHandler.applyEdgeTransform(edge, sourceResult, targetNode, context, allPredecessors)\n\t}\n\n\tpublic async resolveNodeInput(\n\t\tnodeId: string,\n\t\tblueprint: WorkflowBlueprint,\n\t\tcontext: ContextImplementation<TContext>,\n\t): Promise<any> {\n\t\treturn this.logicHandler.resolveNodeInput(nodeId, blueprint, context)\n\t}\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { StepByStepOrchestrator } from './chunk-G53CSLBF.js';
|
|
2
2
|
import { GraphTraverser } from './chunk-G5BGBPFP.js';
|
|
3
|
-
import { ExecutionContext } from './chunk-
|
|
4
|
-
import { WorkflowState } from './chunk-
|
|
3
|
+
import { ExecutionContext } from './chunk-KXXEA5VE.js';
|
|
4
|
+
import { WorkflowState } from './chunk-OO3FF3DF.js';
|
|
5
5
|
|
|
6
6
|
// src/testing/stepper.ts
|
|
7
7
|
async function createStepper(runtime, blueprint, functionRegistry, initialState = {}) {
|
|
@@ -72,5 +72,5 @@ async function createStepper(runtime, blueprint, functionRegistry, initialState
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
export { createStepper };
|
|
75
|
-
//# sourceMappingURL=chunk-
|
|
76
|
-
//# sourceMappingURL=chunk-
|
|
75
|
+
//# sourceMappingURL=chunk-GIJOZ3AN.js.map
|
|
76
|
+
//# sourceMappingURL=chunk-GIJOZ3AN.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/testing/stepper.ts"],"names":[],"mappings":";;;;;;AAkFA,eAAsB,cACrB,OAAA,EACA,SAAA,EACA,gBAAA,EACA,YAAA,GAAkC,EAAC,EACG;AACtC,EAAA,MAAM,iBAAA,GAAoB,gBAAgB,SAAS,CAAA;AACnD,EAAA,MAAM,aAAA,GAAgB,gBAAgB,YAAY,CAAA;AAElD,EAAA,IAAI,KAAA;AACJ,EAAA,IAAI,SAAA;AACJ,EAAA,MAAM,UAAoB,EAAC;AAE3B,EAAA,MAAM,YAAA,GAAe,IAAI,sBAAA,EAAuB;AAChD,EAAA,MAAM,WAAA,GAAc,UAAA,CAAW,MAAA,EAAQ,UAAA,EAAW;AAClD,EAAA,MAAM,YAAA,GAAe,IAAI,GAAA,CAAI,CAAC,GAAG,OAAA,CAAQ,QAAA,EAAU,GAAG,gBAAgB,CAAC,CAAA;AAEvE,EAAA,MAAM,aAAa,MAAM;AACxB,IAAA,KAAA,GAAQ,IAAI,cAAwB,aAAa,CAAA;AACjD,IAAA,SAAA,GAAY,IAAI,eAAe,iBAAiB,CAAA;AAChD,IAAA,OAAA,CAAQ,MAAA,GAAS,CAAA;AAAA,EAClB,CAAA;AAEA,EAAA,UAAA,EAAW;AAEX,EAAA,MAAM,OAAA,GAAsC;AAAA,IAC3C,IAAI,KAAA,GAAQ;AACX,MAAA,OAAO,KAAA;AAAA,IACR,CAAA;AAAA,IACA,IAAI,SAAA,GAAY;AACf,MAAA,OAAO,SAAA;AAAA,IACR,CAAA;AAAA,IACA,MAAA,GAAS;AACR,MAAA,OAAO,CAAC,SAAA,CAAU,WAAA,EAAY,IAAK,CAAC,MAAM,UAAA,EAAW;AAAA,IACtD,CAAA;AAAA,IACA,KAAA,GAAQ;AACP,MAAA,UAAA,EAAW;AAAA,IACZ,CAAA;AAAA,IACA,MAAM,IAAA,GAAO;AACZ,MAAA,MAAM,iBAAA,GAAoB,QAAQ,GAAA,EAAI;AACtC,MAAA,IAAI,CAAC,iBAAA,EAAmB;AACvB,QAAA,OAAO,IAAA;AAAA,MACR;AAEA,MAAA,MAAM,iBAAA,GAAoB,OAAA,CAAQ,UAAA,CAAW,WAAA,CAAY,iBAAiB,CAAA;AAE1E,MAAA,KAAA,GAAQ,IAAI,cAAc,iBAAiB,CAAA;AAC3C,MAAA,SAAA,GAAY,cAAA,CAAe,SAAA,CAAU,iBAAA,EAAmB,KAAK,CAAA;AAE7D,MAAA,OAAO,KAAA,CAAM,QAAA,CAAS,OAAA,CAAQ,UAAU,CAAA;AAAA,IACzC,CAAA;AAAA,IACA,MAAM,IAAA,CAAK,OAAA,GAA0D,EAAC,EAAG;AACxE,MAAA,IAAI,OAAA,CAAQ,QAAO,EAAG;AACrB,QAAA,OAAO,IAAA;AAAA,MACR;AAEA,MAAA,MAAM,qBAAqB,MAAM,KAAA,CAAM,QAAA,CAAS,OAAA,CAAQ,UAAU,CAAA,EAAG,iBAAA;AACrE,MAAA,OAAA,CAAQ,KAAK,iBAAiB,CAAA;AAE9B,MAAA,MAAM,mBAAmB,IAAI,gBAAA;AAAA,QAC5B,iBAAA;AAAA,QACA,KAAA;AAAA,QACA,YAAA;AAAA,QACA,WAAA;AAAA,QACA,OAAA;AAAA,QACA;AAAA,UACC,QAAQ,OAAA,CAAQ,MAAA;AAAA,UAChB,UAAU,OAAA,CAAQ,QAAA;AAAA,UAClB,YAAY,OAAA,CAAQ,UAAA;AAAA,UACpB,WAAW,OAAA,CAAQ,SAAA;AAAA,UACnB,YAAY,OAAA,CAAQ,UAAA;AAAA,UACpB,cAAc,OAAA,CAAQ;AAAA,SACvB;AAAA,QACA,OAAA,CAAQ,MAAA;AAAA,QACR,OAAA,CAAQ;AAAA,OACT;AACA,MAAA,OAAO,YAAA,CAAa,GAAA,CAAI,gBAAA,EAAkB,SAAS,CAAA;AAAA,IACpD;AAAA,GACD;AAEA,EAAA,OAAO,OAAA;AACR","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/testing/stepper.ts"],"names":[],"mappings":";;;;;;AAkFA,eAAsB,cACrB,OAAA,EACA,SAAA,EACA,gBAAA,EACA,YAAA,GAAkC,EAAC,EACG;AACtC,EAAA,MAAM,iBAAA,GAAoB,gBAAgB,SAAS,CAAA;AACnD,EAAA,MAAM,aAAA,GAAgB,gBAAgB,YAAY,CAAA;AAElD,EAAA,IAAI,KAAA;AACJ,EAAA,IAAI,SAAA;AACJ,EAAA,MAAM,UAAoB,EAAC;AAE3B,EAAA,MAAM,YAAA,GAAe,IAAI,sBAAA,EAAuB;AAChD,EAAA,MAAM,WAAA,GAAc,UAAA,CAAW,MAAA,EAAQ,UAAA,EAAW;AAClD,EAAA,MAAM,YAAA,GAAe,IAAI,GAAA,CAAI,CAAC,GAAG,OAAA,CAAQ,QAAA,EAAU,GAAG,gBAAgB,CAAC,CAAA;AAEvE,EAAA,MAAM,aAAa,MAAM;AACxB,IAAA,KAAA,GAAQ,IAAI,cAAwB,aAAa,CAAA;AACjD,IAAA,SAAA,GAAY,IAAI,eAAe,iBAAiB,CAAA;AAChD,IAAA,OAAA,CAAQ,MAAA,GAAS,CAAA;AAAA,EAClB,CAAA;AAEA,EAAA,UAAA,EAAW;AAEX,EAAA,MAAM,OAAA,GAAsC;AAAA,IAC3C,IAAI,KAAA,GAAQ;AACX,MAAA,OAAO,KAAA;AAAA,IACR,CAAA;AAAA,IACA,IAAI,SAAA,GAAY;AACf,MAAA,OAAO,SAAA;AAAA,IACR,CAAA;AAAA,IACA,MAAA,GAAS;AACR,MAAA,OAAO,CAAC,SAAA,CAAU,WAAA,EAAY,IAAK,CAAC,MAAM,UAAA,EAAW;AAAA,IACtD,CAAA;AAAA,IACA,KAAA,GAAQ;AACP,MAAA,UAAA,EAAW;AAAA,IACZ,CAAA;AAAA,IACA,MAAM,IAAA,GAAO;AACZ,MAAA,MAAM,iBAAA,GAAoB,QAAQ,GAAA,EAAI;AACtC,MAAA,IAAI,CAAC,iBAAA,EAAmB;AACvB,QAAA,OAAO,IAAA;AAAA,MACR;AAEA,MAAA,MAAM,iBAAA,GAAoB,OAAA,CAAQ,UAAA,CAAW,WAAA,CAAY,iBAAiB,CAAA;AAE1E,MAAA,KAAA,GAAQ,IAAI,cAAc,iBAAiB,CAAA;AAC3C,MAAA,SAAA,GAAY,cAAA,CAAe,SAAA,CAAU,iBAAA,EAAmB,KAAK,CAAA;AAE7D,MAAA,OAAO,KAAA,CAAM,QAAA,CAAS,OAAA,CAAQ,UAAU,CAAA;AAAA,IACzC,CAAA;AAAA,IACA,MAAM,IAAA,CAAK,OAAA,GAA0D,EAAC,EAAG;AACxE,MAAA,IAAI,OAAA,CAAQ,QAAO,EAAG;AACrB,QAAA,OAAO,IAAA;AAAA,MACR;AAEA,MAAA,MAAM,qBAAqB,MAAM,KAAA,CAAM,QAAA,CAAS,OAAA,CAAQ,UAAU,CAAA,EAAG,iBAAA;AACrE,MAAA,OAAA,CAAQ,KAAK,iBAAiB,CAAA;AAE9B,MAAA,MAAM,mBAAmB,IAAI,gBAAA;AAAA,QAC5B,iBAAA;AAAA,QACA,KAAA;AAAA,QACA,YAAA;AAAA,QACA,WAAA;AAAA,QACA,OAAA;AAAA,QACA;AAAA,UACC,QAAQ,OAAA,CAAQ,MAAA;AAAA,UAChB,UAAU,OAAA,CAAQ,QAAA;AAAA,UAClB,YAAY,OAAA,CAAQ,UAAA;AAAA,UACpB,WAAW,OAAA,CAAQ,SAAA;AAAA,UACnB,YAAY,OAAA,CAAQ,UAAA;AAAA,UACpB,cAAc,OAAA,CAAQ;AAAA,SACvB;AAAA,QACA,OAAA,CAAQ,MAAA;AAAA,QACR,OAAA,CAAQ;AAAA,OACT;AACA,MAAA,OAAO,YAAA,CAAa,GAAA,CAAI,gBAAA,EAAkB,SAAS,CAAA;AAAA,IACpD;AAAA,GACD;AAEA,EAAA,OAAO,OAAA;AACR","file":"chunk-GIJOZ3AN.js","sourcesContent":["import type { FlowRuntime } from '../runtime'\nimport { ExecutionContext } from '../runtime/execution-context'\nimport { StepByStepOrchestrator } from '../runtime/orchestrators/step-by-step'\nimport { WorkflowState } from '../runtime/state'\nimport { GraphTraverser } from '../runtime/traverser'\nimport type { NodeClass, NodeFunction, WorkflowBlueprint, WorkflowResult } from '../types'\n\n/**\n * Represents the controlled, step-by-step execution of a workflow.\n * Returned by the `createStepper` utility.\n */\nexport interface IWorkflowStepper<TContext extends Record<string, any>> {\n\t/** The current state of the workflow. Can be inspected after each step. */\n\treadonly state: WorkflowState<TContext>\n\n\t/** The graph traverser instance. Can be used to inspect the frontier or completed nodes. */\n\treadonly traverser: GraphTraverser\n\n\t/**\n\t * Executes the next \"turn\" or batch of ready nodes in the workflow.\n\t * @param options Optional configuration for this specific step, like a cancellation signal.\n\t * @returns A `WorkflowResult` representing the state after the step, or `null` if the workflow has already completed.\n\t */\n\tnext(options?: { signal?: AbortSignal; concurrency?: number }): Promise<WorkflowResult<TContext> | null>\n\n\t/**\n\t * Reverts the workflow to its previous state.\n\t * @returns The `WorkflowResult` of the previous state, or `null` if there is no history to revert to.\n\t */\n\tprev(): Promise<WorkflowResult<TContext> | null>\n\n\t/**\n\t * Resets the stepper to its initial state, clearing all progress and history.\n\t */\n\treset(): void\n\n\t/**\n\t * A convenience method to check if the workflow has any more steps to run.\n\t * @returns `true` if the workflow is complete or stalled, `false` otherwise.\n\t */\n\tisDone(): boolean\n}\n\n/**\n * A test utility that creates a stepper to execute a workflow one \"turn\" at a time.\n * This is invaluable for debugging and writing fine-grained tests where you need to\n * assert the state of the workflow after each logical step.\n *\n * @example\n * // In your test file\n * it('should correctly execute step-by-step', async () => {\n * const runtime = new FlowRuntime({ ... });\n * const flow = createFlow('test')\n * .node('a', async () => ({ output: 10 }))\n * .node('b', async ({ input }) => ({ output: input * 2 }))\n * .edge('a', 'b');\n *\n * const stepper = await createStepper(runtime, flow.toBlueprint(), flow.getFunctionRegistry());\n *\n * // First step (executes node 'a')\n * const result1 = await stepper.next();\n * expect(stepper.isDone()).toBe(false);\n * expect(result1.status).toBe('stalled');\n * expect(result1.context._outputs.a).toBe(10);\n *\n * // Second step (executes node 'b')\n * const result2 = await stepper.next();\n * expect(stepper.isDone()).toBe(true);\n * expect(result2.status).toBe('completed');\n * expect(result2.context._outputs.b).toBe(20);\n *\n * // Final step (no more work)\n * const result3 = await stepper.next();\n * expect(result3).toBeNull();\n * });\n *\n * @param runtime The `FlowRuntime` instance, used for its configuration.\n * @param blueprint The `WorkflowBlueprint` to execute.\n * @param functionRegistry The function registry from createFlow, containing the node implementations.\n * @param initialState The initial state for the workflow run.\n * @returns A Promise that resolves to an `IWorkflowStepper` instance.\n */\nexport async function createStepper<TContext extends Record<string, any>, TDependencies extends Record<string, any>>(\n\truntime: FlowRuntime<TContext, TDependencies>,\n\tblueprint: WorkflowBlueprint,\n\tfunctionRegistry: Map<string, NodeFunction | NodeClass>,\n\tinitialState: Partial<TContext> = {},\n): Promise<IWorkflowStepper<TContext>> {\n\tconst _initialBlueprint = structuredClone(blueprint)\n\tconst _initialState = structuredClone(initialState)\n\n\tlet state: WorkflowState<TContext>\n\tlet traverser: GraphTraverser\n\tconst history: string[] = []\n\n\tconst orchestrator = new StepByStepOrchestrator()\n\tconst executionId = globalThis.crypto?.randomUUID()\n\tconst nodeRegistry = new Map([...runtime.registry, ...functionRegistry])\n\n\tconst initialize = () => {\n\t\tstate = new WorkflowState<TContext>(_initialState)\n\t\ttraverser = new GraphTraverser(_initialBlueprint)\n\t\thistory.length = 0\n\t}\n\n\tinitialize()\n\n\tconst stepper: IWorkflowStepper<TContext> = {\n\t\tget state() {\n\t\t\treturn state\n\t\t},\n\t\tget traverser() {\n\t\t\treturn traverser\n\t\t},\n\t\tisDone() {\n\t\t\treturn !traverser.hasMoreWork() && !state.isAwaiting()\n\t\t},\n\t\treset() {\n\t\t\tinitialize()\n\t\t},\n\t\tasync prev() {\n\t\t\tconst previousStateJson = history.pop()\n\t\t\tif (!previousStateJson) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\tconst previousStateData = runtime.serializer.deserialize(previousStateJson) as Partial<TContext>\n\n\t\t\tstate = new WorkflowState(previousStateData)\n\t\t\ttraverser = GraphTraverser.fromState(_initialBlueprint, state)\n\n\t\t\treturn state.toResult(runtime.serializer)\n\t\t},\n\t\tasync next(options: { signal?: AbortSignal; concurrency?: number } = {}) {\n\t\t\tif (stepper.isDone()) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\tconst serializedContext = (await state.toResult(runtime.serializer)).serializedContext\n\t\t\thistory.push(serializedContext)\n\n\t\t\tconst executionContext = new ExecutionContext(\n\t\t\t\t_initialBlueprint,\n\t\t\t\tstate,\n\t\t\t\tnodeRegistry,\n\t\t\t\texecutionId,\n\t\t\t\truntime,\n\t\t\t\t{\n\t\t\t\t\tlogger: runtime.logger,\n\t\t\t\t\teventBus: runtime.eventBus,\n\t\t\t\t\tserializer: runtime.serializer,\n\t\t\t\t\tevaluator: runtime.evaluator,\n\t\t\t\t\tmiddleware: runtime.middleware,\n\t\t\t\t\tdependencies: runtime.dependencies,\n\t\t\t\t},\n\t\t\t\toptions.signal,\n\t\t\t\toptions.concurrency,\n\t\t\t)\n\t\t\treturn orchestrator.run(executionContext, traverser)\n\t\t},\n\t}\n\n\treturn stepper\n}\n"]}
|
|
@@ -3,11 +3,14 @@ import { BaseNode } from './chunk-LNK7LZER.js';
|
|
|
3
3
|
// src/nodes/wait.ts
|
|
4
4
|
var WaitNode = class extends BaseNode {
|
|
5
5
|
async exec(_prepResult, context) {
|
|
6
|
-
context.dependencies.workflowState.markAsAwaiting(this.nodeId ?? ""
|
|
6
|
+
context.dependencies.workflowState.markAsAwaiting(this.nodeId ?? "", {
|
|
7
|
+
reason: "external_event"
|
|
8
|
+
// params: this.params // NOTE: can add more details if needed in the future
|
|
9
|
+
});
|
|
7
10
|
return { output: void 0 };
|
|
8
11
|
}
|
|
9
12
|
};
|
|
10
13
|
|
|
11
14
|
export { WaitNode };
|
|
12
|
-
//# sourceMappingURL=chunk-
|
|
13
|
-
//# sourceMappingURL=chunk-
|
|
15
|
+
//# sourceMappingURL=chunk-GVF7GQXQ.js.map
|
|
16
|
+
//# sourceMappingURL=chunk-GVF7GQXQ.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,EAAA,EAAI;AAAA,MACpE,MAAA,EAAQ;AAAA;AAAA,KAER,CAAA;AACD,IAAA,OAAO,EAAE,QAAQ,MAAA,EAAU;AAAA,EAC5B;AACD","file":"chunk-GVF7GQXQ.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\t\treason: 'external_event',\n\t\t\t// params: this.params // NOTE: can add more details if needed in the future\n\t\t})\n\t\treturn { output: undefined }\n\t}\n}\n"]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { FlowRuntime } from './chunk-
|
|
1
|
+
import { FlowRuntime } from './chunk-CHG6O6JX.js';
|
|
2
2
|
import { analyzeBlueprint } from './chunk-233SESC2.js';
|
|
3
|
+
import { ConsoleLogger } from './chunk-4PELJWF7.js';
|
|
3
4
|
import { JsonSerializer } from './chunk-CYHZ2YVH.js';
|
|
4
5
|
|
|
5
6
|
// src/runtime/adapter.ts
|
|
@@ -7,17 +8,19 @@ var BaseDistributedAdapter = class {
|
|
|
7
8
|
runtime;
|
|
8
9
|
store;
|
|
9
10
|
serializer;
|
|
11
|
+
logger;
|
|
10
12
|
constructor(options) {
|
|
11
13
|
this.runtime = new FlowRuntime(options.runtimeOptions);
|
|
12
14
|
this.store = options.coordinationStore;
|
|
13
15
|
this.serializer = options.runtimeOptions.serializer || new JsonSerializer();
|
|
14
|
-
|
|
16
|
+
this.logger = options.runtimeOptions.logger || new ConsoleLogger();
|
|
17
|
+
this.logger.info("[Adapter] BaseDistributedAdapter initialized.");
|
|
15
18
|
}
|
|
16
19
|
/**
|
|
17
20
|
* Starts the worker, which begins listening for and processing jobs from the queue.
|
|
18
21
|
*/
|
|
19
22
|
start() {
|
|
20
|
-
|
|
23
|
+
this.logger.info("[Adapter] Starting worker...");
|
|
21
24
|
this.processJobs(this.handleJob.bind(this));
|
|
22
25
|
}
|
|
23
26
|
/**
|
|
@@ -35,7 +38,7 @@ var BaseDistributedAdapter = class {
|
|
|
35
38
|
const blueprint = this.runtime.options.blueprints?.[blueprintId];
|
|
36
39
|
if (!blueprint) {
|
|
37
40
|
const reason = `Blueprint with ID '${blueprintId}' not found in the worker's runtime registry.`;
|
|
38
|
-
|
|
41
|
+
this.logger.error(`[Adapter] FATAL: ${reason}`);
|
|
39
42
|
await this.publishFinalResult(runId, { status: "failed", reason });
|
|
40
43
|
return;
|
|
41
44
|
}
|
|
@@ -51,7 +54,7 @@ var BaseDistributedAdapter = class {
|
|
|
51
54
|
markFallbackExecuted: () => {
|
|
52
55
|
},
|
|
53
56
|
addError: (nodeId2, error) => {
|
|
54
|
-
|
|
57
|
+
this.logger.error(`[Adapter] Error in node ${nodeId2}:`, error);
|
|
55
58
|
}
|
|
56
59
|
};
|
|
57
60
|
try {
|
|
@@ -69,7 +72,7 @@ var BaseDistributedAdapter = class {
|
|
|
69
72
|
}
|
|
70
73
|
const allTerminalNodesCompleted = analysis.terminalNodeIds.every((terminalId) => completedNodes.has(terminalId));
|
|
71
74
|
if (allTerminalNodesCompleted) {
|
|
72
|
-
|
|
75
|
+
this.logger.info(`[Adapter] All terminal nodes completed for Run ID: ${runId}. Declaring workflow complete.`);
|
|
73
76
|
const finalContext = await context.toJSON();
|
|
74
77
|
const finalResult = {
|
|
75
78
|
context: finalContext,
|
|
@@ -82,14 +85,14 @@ var BaseDistributedAdapter = class {
|
|
|
82
85
|
});
|
|
83
86
|
return;
|
|
84
87
|
} else {
|
|
85
|
-
|
|
88
|
+
this.logger.info(
|
|
86
89
|
`[Adapter] Terminal node '${nodeId}' completed for Run ID '${runId}', but other terminal nodes are still running.`
|
|
87
90
|
);
|
|
88
91
|
}
|
|
89
92
|
}
|
|
90
93
|
const nextNodes = await this.runtime.determineNextNodes(blueprint, nodeId, result, context, runId);
|
|
91
94
|
if (nextNodes.length === 0 && !isTerminalNode) {
|
|
92
|
-
|
|
95
|
+
this.logger.info(
|
|
93
96
|
`[Adapter] Non-terminal node '${nodeId}' reached end of branch for Run ID '${runId}'. This branch will now terminate.`
|
|
94
97
|
);
|
|
95
98
|
return;
|
|
@@ -98,15 +101,15 @@ var BaseDistributedAdapter = class {
|
|
|
98
101
|
await this.runtime.applyEdgeTransform(edge, result, nextNodeDef, context);
|
|
99
102
|
const isReady = await this.isReadyForFanIn(runId, blueprint, nextNodeDef.id);
|
|
100
103
|
if (isReady) {
|
|
101
|
-
|
|
104
|
+
this.logger.info(`[Adapter] Node '${nextNodeDef.id}' is ready. Enqueuing job.`);
|
|
102
105
|
await this.enqueueJob({ runId, blueprintId, nodeId: nextNodeDef.id });
|
|
103
106
|
} else {
|
|
104
|
-
|
|
107
|
+
this.logger.info(`[Adapter] Node '${nextNodeDef.id}' is waiting for other predecessors to complete.`);
|
|
105
108
|
}
|
|
106
109
|
}
|
|
107
110
|
} catch (error) {
|
|
108
111
|
const reason = error.message || "Unknown execution error";
|
|
109
|
-
|
|
112
|
+
this.logger.error(`[Adapter] FATAL: Job for node '${nodeId}' failed for Run ID '${runId}': ${reason}`);
|
|
110
113
|
await this.publishFinalResult(runId, { status: "failed", reason });
|
|
111
114
|
await this.writePoisonPillForSuccessors(runId, blueprint, nodeId);
|
|
112
115
|
}
|
|
@@ -127,7 +130,7 @@ var BaseDistributedAdapter = class {
|
|
|
127
130
|
const poisonKey = `flowcraft:fanin:poison:${runId}:${targetNodeId}`;
|
|
128
131
|
const isPoisoned = await this.store.get(poisonKey);
|
|
129
132
|
if (isPoisoned) {
|
|
130
|
-
|
|
133
|
+
this.logger.info(`[Adapter] Node '${targetNodeId}' is poisoned due to failed predecessor. Failing immediately.`);
|
|
131
134
|
throw new Error(`Node '${targetNodeId}' failed due to poisoned predecessor in run '${runId}'`);
|
|
132
135
|
}
|
|
133
136
|
if (joinStrategy === "any") {
|
|
@@ -137,7 +140,9 @@ var BaseDistributedAdapter = class {
|
|
|
137
140
|
const cancelKey = `flowcraft:fanin:cancel:${runId}:${targetNodeId}`;
|
|
138
141
|
const isCancelled = !await this.store.setIfNotExist(cancelKey, "cancelled", 3600);
|
|
139
142
|
if (isCancelled) {
|
|
140
|
-
|
|
143
|
+
this.logger.info(
|
|
144
|
+
`[Adapter] Node '${targetNodeId}' is cancelled due to failed predecessor. Failing immediately.`
|
|
145
|
+
);
|
|
141
146
|
throw new Error(`Node '${targetNodeId}' failed due to cancelled predecessor in run '${runId}'`);
|
|
142
147
|
}
|
|
143
148
|
return false;
|
|
@@ -193,7 +198,7 @@ var BaseDistributedAdapter = class {
|
|
|
193
198
|
const poisonKey = `flowcraft:fanin:poison:${runId}:${nodeId}`;
|
|
194
199
|
const isPoisoned = await this.store.get(poisonKey);
|
|
195
200
|
if (isPoisoned) {
|
|
196
|
-
|
|
201
|
+
this.logger.info(`[Adapter] Reconciling: Node '${nodeId}' is poisoned, skipping.`, { runId });
|
|
197
202
|
continue;
|
|
198
203
|
}
|
|
199
204
|
let shouldEnqueue = false;
|
|
@@ -202,18 +207,18 @@ var BaseDistributedAdapter = class {
|
|
|
202
207
|
if (await this.store.setIfNotExist(lockKey, "locked-by-reconcile", 3600)) {
|
|
203
208
|
shouldEnqueue = true;
|
|
204
209
|
} else {
|
|
205
|
-
|
|
210
|
+
this.logger.info(`[Adapter] Reconciling: Node '${nodeId}' is an 'any' join and is already locked.`, { runId });
|
|
206
211
|
}
|
|
207
212
|
} else {
|
|
208
213
|
const lockKey = `flowcraft:nodelock:${runId}:${nodeId}`;
|
|
209
214
|
if (await this.store.setIfNotExist(lockKey, "locked", 120)) {
|
|
210
215
|
shouldEnqueue = true;
|
|
211
216
|
} else {
|
|
212
|
-
|
|
217
|
+
this.logger.info(`[Adapter] Reconciling: Node '${nodeId}' is already locked.`, { runId });
|
|
213
218
|
}
|
|
214
219
|
}
|
|
215
220
|
if (shouldEnqueue) {
|
|
216
|
-
|
|
221
|
+
this.logger.info(`[Adapter] Reconciling: Enqueuing ready job for node '${nodeId}'`, { runId });
|
|
217
222
|
await this.enqueueJob({ runId, blueprintId: blueprint.id, nodeId });
|
|
218
223
|
enqueuedNodes.add(nodeId);
|
|
219
224
|
}
|
|
@@ -258,13 +263,13 @@ var BaseDistributedAdapter = class {
|
|
|
258
263
|
if (joinStrategy === "all") {
|
|
259
264
|
const poisonKey = `flowcraft:fanin:poison:${runId}:${successor.id}`;
|
|
260
265
|
await this.store.setIfNotExist(poisonKey, "poisoned", 3600);
|
|
261
|
-
|
|
266
|
+
this.logger.info(
|
|
262
267
|
`[Adapter] Wrote poison pill for 'all' join node '${successor.id}' due to failed predecessor '${failedNodeId}'`
|
|
263
268
|
);
|
|
264
269
|
} else if (joinStrategy === "any") {
|
|
265
270
|
const cancelKey = `flowcraft:fanin:cancel:${runId}:${successor.id}`;
|
|
266
271
|
await this.store.setIfNotExist(cancelKey, "cancelled", 3600);
|
|
267
|
-
|
|
272
|
+
this.logger.info(
|
|
268
273
|
`[Adapter] Wrote cancellation pill for 'any' join node '${successor.id}' due to failed predecessor '${failedNodeId}'`
|
|
269
274
|
);
|
|
270
275
|
}
|
|
@@ -274,5 +279,5 @@ var BaseDistributedAdapter = class {
|
|
|
274
279
|
};
|
|
275
280
|
|
|
276
281
|
export { BaseDistributedAdapter };
|
|
277
|
-
//# sourceMappingURL=chunk-
|
|
278
|
-
//# sourceMappingURL=chunk-
|
|
282
|
+
//# sourceMappingURL=chunk-J3HZD5ES.js.map
|
|
283
|
+
//# sourceMappingURL=chunk-J3HZD5ES.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/runtime/adapter.ts"],"names":["nodeId"],"mappings":"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","file":"chunk-J3HZD5ES.js","sourcesContent":["import { analyzeBlueprint } from '../analysis'\nimport { ConsoleLogger } from '../logger'\nimport { JsonSerializer } from '../serializer'\nimport type {\n\tIAsyncContext,\n\tILogger,\n\tISerializer,\n\tNodeResult,\n\tRuntimeOptions,\n\tWorkflowBlueprint,\n\tWorkflowResult,\n} from '../types'\nimport { FlowRuntime } from './runtime'\n\n/**\n * Defines the contract for an atomic, distributed key-value store required by\n * the adapter for coordination tasks like fan-in joins and locking.\n */\nexport interface ICoordinationStore {\n\t/** Atomically increments a key and returns the new value. Ideal for 'all' joins. */\n\tincrement: (key: string, ttlSeconds: number) => Promise<number>\n\t/** Sets a key only if it does not already exist. Ideal for 'any' joins (locking). */\n\tsetIfNotExist: (key: string, value: string, ttlSeconds: number) => Promise<boolean>\n\t/** Deletes a key. Used for cleanup. */\n\tdelete: (key: string) => Promise<void>\n\t/** Gets the value of a key. */\n\tget: (key: string) => Promise<string | undefined>\n}\n\n/** Configuration options for constructing a BaseDistributedAdapter. */\nexport interface AdapterOptions {\n\truntimeOptions: RuntimeOptions<any>\n\tcoordinationStore: ICoordinationStore\n}\n\n/** The data payload expected for a job in the queue. */\nexport interface JobPayload {\n\trunId: string\n\tblueprintId: string\n\tnodeId: string\n}\n\n/**\n * The base class for all distributed adapters. It handles the technology-agnostic\n * orchestration logic and leaves queue-specific implementation to subclasses.\n */\nexport abstract class BaseDistributedAdapter {\n\tprotected readonly runtime: FlowRuntime<any, any>\n\tprotected readonly store: ICoordinationStore\n\tprotected readonly serializer: ISerializer\n\tprotected readonly logger: ILogger\n\n\tconstructor(options: AdapterOptions) {\n\t\tthis.runtime = new FlowRuntime(options.runtimeOptions)\n\t\tthis.store = options.coordinationStore\n\t\tthis.serializer = options.runtimeOptions.serializer || new JsonSerializer()\n\t\tthis.logger = options.runtimeOptions.logger || new ConsoleLogger()\n\t\tthis.logger.info('[Adapter] BaseDistributedAdapter initialized.')\n\t}\n\n\t/**\n\t * Starts the worker, which begins listening for and processing jobs from the queue.\n\t */\n\tpublic start(): void {\n\t\tthis.logger.info('[Adapter] Starting worker...')\n\t\tthis.processJobs(this.handleJob.bind(this))\n\t}\n\n\t/**\n\t * Creates a technology-specific distributed context for a given workflow run.\n\t * @param runId The unique ID for the workflow execution.\n\t */\n\tprotected abstract createContext(runId: string): IAsyncContext<Record<string, any>>\n\t/**\n\t * Sets up the listener for the message queue. The implementation should call the\n\t * provided `handler` function for each new job received.\n\t * @param handler The core logic to execute for each job.\n\t */\n\tprotected abstract processJobs(handler: (job: JobPayload) => Promise<void>): void\n\n\t/**\n\t * Enqueues a new job onto the message queue.\n\t * @param job The payload for the job to be enqueued.\n\t */\n\tprotected abstract enqueueJob(job: JobPayload): Promise<void>\n\n\t/**\n\t * Publishes the final result of a completed or failed workflow run.\n\t * @param runId The unique ID of the workflow run.\n\t * @param result The final status and payload of the workflow.\n\t */\n\tprotected abstract publishFinalResult(\n\t\trunId: string,\n\t\tresult: {\n\t\t\tstatus: 'completed' | 'failed'\n\t\t\tpayload?: WorkflowResult\n\t\t\treason?: string\n\t\t},\n\t): Promise<void>\n\n\t/**\n\t * Hook called at the start of job processing. Subclasses can override this\n\t * to perform additional setup (e.g., timestamp tracking for reconciliation).\n\t */\n\tprotected async onJobStart(_runId: string, _blueprintId: string, _nodeId: string): Promise<void> {\n\t\t// default implementation does nothing\n\t}\n\n\t/**\n\t * The main handler for processing a single job from the queue.\n\t */\n\tprotected async handleJob(job: JobPayload): Promise<void> {\n\t\tconst { runId, blueprintId, nodeId } = job\n\n\t\tawait this.onJobStart(runId, blueprintId, nodeId)\n\n\t\tconst blueprint = this.runtime.options.blueprints?.[blueprintId]\n\t\tif (!blueprint) {\n\t\t\tconst reason = `Blueprint with ID '${blueprintId}' not found in the worker's runtime registry.`\n\t\t\tthis.logger.error(`[Adapter] FATAL: ${reason}`)\n\t\t\tawait this.publishFinalResult(runId, { status: 'failed', reason })\n\t\t\treturn\n\t\t}\n\n\t\tconst context = this.createContext(runId)\n\n\t\t// persist the blueprintId for the reconcile method to find later\n\t\tconst hasBlueprintId = await context.has('blueprintId' as any)\n\t\tif (!hasBlueprintId) {\n\t\t\tawait context.set('blueprintId' as any, blueprintId)\n\t\t\t// also store in coordination store as fallback\n\t\t\tconst blueprintKey = `flowcraft:blueprint:${runId}`\n\t\t\tawait this.store.setIfNotExist(blueprintKey, blueprintId, 3600)\n\t\t}\n\t\tconst workerState = {\n\t\t\tgetContext: () => context,\n\t\t\tmarkFallbackExecuted: () => {},\n\t\t\taddError: (nodeId: string, error: Error) => {\n\t\t\t\tthis.logger.error(`[Adapter] Error in node ${nodeId}:`, error)\n\t\t\t},\n\t\t} as any\n\n\t\ttry {\n\t\t\tconst result: NodeResult<any, any> = await this.runtime.executeNode(blueprint, nodeId, workerState)\n\t\t\tawait context.set(`_outputs.${nodeId}` as any, result.output)\n\n\t\t\tconst analysis = analyzeBlueprint(blueprint)\n\t\t\tconst isTerminalNode = analysis.terminalNodeIds.includes(nodeId)\n\n\t\t\tif (isTerminalNode) {\n\t\t\t\tconst allContextKeys = Object.keys(await context.toJSON())\n\t\t\t\tconst completedNodes = new Set<string>()\n\t\t\t\tfor (const key of allContextKeys) {\n\t\t\t\t\tif (key.startsWith('_outputs.')) {\n\t\t\t\t\t\tcompletedNodes.add(key.substring('_outputs.'.length))\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst allTerminalNodesCompleted = analysis.terminalNodeIds.every((terminalId) => completedNodes.has(terminalId))\n\n\t\t\t\tif (allTerminalNodesCompleted) {\n\t\t\t\t\tthis.logger.info(`[Adapter] All terminal nodes completed for Run ID: ${runId}. Declaring workflow complete.`)\n\t\t\t\t\tconst finalContext = await context.toJSON()\n\t\t\t\t\tconst finalResult: WorkflowResult = {\n\t\t\t\t\t\tcontext: finalContext,\n\t\t\t\t\t\tserializedContext: this.serializer.serialize(finalContext),\n\t\t\t\t\t\tstatus: 'completed',\n\t\t\t\t\t}\n\t\t\t\t\tawait this.publishFinalResult(runId, {\n\t\t\t\t\t\tstatus: 'completed',\n\t\t\t\t\t\tpayload: finalResult,\n\t\t\t\t\t})\n\t\t\t\t\treturn\n\t\t\t\t} else {\n\t\t\t\t\tthis.logger.info(\n\t\t\t\t\t\t`[Adapter] Terminal node '${nodeId}' completed for Run ID '${runId}', but other terminal nodes are still running.`,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst nextNodes = await this.runtime.determineNextNodes(blueprint, nodeId, result, context, runId)\n\n\t\t\t// stop if a branch terminates but it wasn't a terminal node\n\t\t\tif (nextNodes.length === 0 && !isTerminalNode) {\n\t\t\t\tthis.logger.info(\n\t\t\t\t\t`[Adapter] Non-terminal node '${nodeId}' reached end of branch for Run ID '${runId}'. This branch will now terminate.`,\n\t\t\t\t)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tfor (const { node: nextNodeDef, edge } of nextNodes) {\n\t\t\t\tawait this.runtime.applyEdgeTransform(edge, result, nextNodeDef, context)\n\t\t\t\tconst isReady = await this.isReadyForFanIn(runId, blueprint, nextNodeDef.id)\n\t\t\t\tif (isReady) {\n\t\t\t\t\tthis.logger.info(`[Adapter] Node '${nextNodeDef.id}' is ready. Enqueuing job.`)\n\t\t\t\t\tawait this.enqueueJob({ runId, blueprintId, nodeId: nextNodeDef.id })\n\t\t\t\t} else {\n\t\t\t\t\tthis.logger.info(`[Adapter] Node '${nextNodeDef.id}' is waiting for other predecessors to complete.`)\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error: any) {\n\t\t\tconst reason = error.message || 'Unknown execution error'\n\t\t\tthis.logger.error(`[Adapter] FATAL: Job for node '${nodeId}' failed for Run ID '${runId}': ${reason}`)\n\t\t\tawait this.publishFinalResult(runId, { status: 'failed', reason })\n\t\t\tawait this.writePoisonPillForSuccessors(runId, blueprint, nodeId)\n\t\t}\n\t}\n\n\t/**\n\t * Encapsulates the fan-in join logic using the coordination store.\n\t */\n\tprotected async isReadyForFanIn(runId: string, blueprint: WorkflowBlueprint, targetNodeId: string): Promise<boolean> {\n\t\tconst targetNode = blueprint.nodes.find((n) => n.id === targetNodeId)\n\t\tif (!targetNode) {\n\t\t\tthrow new Error(`Node '${targetNodeId}' not found in blueprint`)\n\t\t}\n\t\tconst joinStrategy = targetNode.config?.joinStrategy || 'all'\n\t\tconst predecessors = blueprint.edges.filter((e) => e.target === targetNodeId)\n\n\t\tif (predecessors.length <= 1) {\n\t\t\treturn true\n\t\t}\n\n\t\tconst poisonKey = `flowcraft:fanin:poison:${runId}:${targetNodeId}`\n\t\tconst isPoisoned = await this.store.get(poisonKey)\n\t\tif (isPoisoned) {\n\t\t\tthis.logger.info(`[Adapter] Node '${targetNodeId}' is poisoned due to failed predecessor. Failing immediately.`)\n\t\t\tthrow new Error(`Node '${targetNodeId}' failed due to poisoned predecessor in run '${runId}'`)\n\t\t}\n\n\t\tif (joinStrategy === 'any') {\n\t\t\tconst lockKey = `flowcraft:joinlock:${runId}:${targetNodeId}`\n\t\t\tconst isLocked = await this.store.setIfNotExist(lockKey, 'locked', 3600)\n\t\t\tif (!isLocked) {\n\t\t\t\t// Check if it's cancelled\n\t\t\t\tconst cancelKey = `flowcraft:fanin:cancel:${runId}:${targetNodeId}`\n\t\t\t\tconst isCancelled = !(await this.store.setIfNotExist(cancelKey, 'cancelled', 3600))\n\t\t\t\tif (isCancelled) {\n\t\t\t\t\tthis.logger.info(\n\t\t\t\t\t\t`[Adapter] Node '${targetNodeId}' is cancelled due to failed predecessor. Failing immediately.`,\n\t\t\t\t\t)\n\t\t\t\t\tthrow new Error(`Node '${targetNodeId}' failed due to cancelled predecessor in run '${runId}'`)\n\t\t\t\t}\n\t\t\t\treturn false // Already locked by another predecessor\n\t\t\t}\n\t\t\treturn true\n\t\t} else {\n\t\t\tconst fanInKey = `flowcraft:fanin:${runId}:${targetNodeId}`\n\t\t\tconst readyCount = await this.store.increment(fanInKey, 3600)\n\t\t\tif (readyCount >= predecessors.length) {\n\t\t\t\tawait this.store.delete(fanInKey)\n\t\t\t\treturn true\n\t\t\t}\n\t\t\treturn false\n\t\t}\n\t}\n\n\t/**\n\t * Reconciles the state of a workflow run. It inspects the persisted\n\t * context to find completed nodes, determines the next set of executable\n\t * nodes (the frontier), and enqueues jobs for them if they aren't\n\t * already running. This is the core of the resume functionality.\n\t *\n\t * @param runId The unique ID of the workflow execution to reconcile.\n\t * @returns The set of node IDs that were enqueued for execution.\n\t */\n\tpublic async reconcile(runId: string): Promise<Set<string>> {\n\t\tconst context = this.createContext(runId)\n\t\tlet blueprintId = (await context.get('blueprintId' as any)) as string | undefined\n\n\t\tif (!blueprintId) {\n\t\t\t// fallback to coordination store\n\t\t\tconst blueprintKey = `flowcraft:blueprint:${runId}`\n\t\t\tblueprintId = await this.store.get(blueprintKey)\n\t\t\tif (blueprintId) {\n\t\t\t\t// set it back in context for future use\n\t\t\t\tawait context.set('blueprintId' as any, blueprintId)\n\t\t\t} else {\n\t\t\t\tthrow new Error(`Cannot reconcile runId '${runId}': blueprintId not found in context or coordination store.`)\n\t\t\t}\n\t\t}\n\t\tconst blueprint = this.runtime.options.blueprints?.[blueprintId]\n\t\tif (!blueprint) {\n\t\t\tthrow new Error(`Cannot reconcile runId '${runId}': Blueprint with ID '${blueprintId}' not found.`)\n\t\t}\n\n\t\tconst state = await context.toJSON()\n\t\t// filter out internal keys\n\t\tconst completedNodes = new Set<string>()\n\t\tfor (const key of Object.keys(state)) {\n\t\t\tif (key.startsWith('_outputs.')) {\n\t\t\t\tcompletedNodes.add(key.substring('_outputs.'.length))\n\t\t\t}\n\t\t}\n\n\t\tconst frontier = this.calculateResumedFrontier(blueprint, completedNodes)\n\n\t\tconst enqueuedNodes = new Set<string>()\n\t\tfor (const nodeId of frontier) {\n\t\t\tconst nodeDef = blueprint.nodes.find((n) => n.id === nodeId)\n\t\t\tconst joinStrategy = nodeDef?.config?.joinStrategy || 'all'\n\n\t\t\tconst poisonKey = `flowcraft:fanin:poison:${runId}:${nodeId}`\n\t\t\tconst isPoisoned = await this.store.get(poisonKey)\n\t\t\tif (isPoisoned) {\n\t\t\t\tthis.logger.info(`[Adapter] Reconciling: Node '${nodeId}' is poisoned, skipping.`, { runId })\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tlet shouldEnqueue = false\n\n\t\t\tif (joinStrategy === 'any') {\n\t\t\t\t// acquire the permanent join lock\n\t\t\t\tconst lockKey = `flowcraft:joinlock:${runId}:${nodeId}`\n\t\t\t\tif (await this.store.setIfNotExist(lockKey, 'locked-by-reconcile', 3600)) {\n\t\t\t\t\tshouldEnqueue = true\n\t\t\t\t} else {\n\t\t\t\t\tthis.logger.info(`[Adapter] Reconciling: Node '${nodeId}' is an 'any' join and is already locked.`, { runId })\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// 'all' joins and single-predecessor nodes use a temporary lock\n\t\t\t\tconst lockKey = `flowcraft:nodelock:${runId}:${nodeId}`\n\t\t\t\tif (await this.store.setIfNotExist(lockKey, 'locked', 120)) {\n\t\t\t\t\tshouldEnqueue = true\n\t\t\t\t} else {\n\t\t\t\t\tthis.logger.info(`[Adapter] Reconciling: Node '${nodeId}' is already locked.`, { runId })\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (shouldEnqueue) {\n\t\t\t\tthis.logger.info(`[Adapter] Reconciling: Enqueuing ready job for node '${nodeId}'`, { runId })\n\t\t\t\tawait this.enqueueJob({ runId, blueprintId: blueprint.id, nodeId })\n\t\t\t\tenqueuedNodes.add(nodeId)\n\t\t\t}\n\t\t}\n\n\t\treturn enqueuedNodes\n\t}\n\n\tprivate calculateResumedFrontier(blueprint: WorkflowBlueprint, completedNodes: Set<string>): Set<string> {\n\t\tconst newFrontier = new Set<string>()\n\t\tconst allPredecessors = new Map<string, Set<string>>()\n\t\t// (logic extracted from the GraphTraverser)\n\t\tfor (const node of blueprint.nodes) {\n\t\t\tallPredecessors.set(node.id, new Set())\n\t\t}\n\t\tfor (const edge of blueprint.edges) {\n\t\t\tallPredecessors.get(edge.target)?.add(edge.source)\n\t\t}\n\n\t\tfor (const node of blueprint.nodes) {\n\t\t\tif (completedNodes.has(node.id)) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tconst predecessors = allPredecessors.get(node.id) ?? new Set()\n\t\t\tif (predecessors.size === 0 && !completedNodes.has(node.id)) {\n\t\t\t\tnewFrontier.add(node.id)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tconst joinStrategy = node.config?.joinStrategy || 'all'\n\t\t\tconst completedPredecessors = [...predecessors].filter((p) => completedNodes.has(p))\n\n\t\t\tconst isReady =\n\t\t\t\tjoinStrategy === 'any' ? completedPredecessors.length > 0 : completedPredecessors.length === predecessors.size\n\n\t\t\tif (isReady) {\n\t\t\t\tnewFrontier.add(node.id)\n\t\t\t}\n\t\t}\n\t\treturn newFrontier\n\t}\n\n\t/**\n\t * Writes a poison pill for 'all' join successors and a cancellation pill for 'any' join successors of a failed node to prevent stalling or ambiguous states.\n\t */\n\tprivate async writePoisonPillForSuccessors(\n\t\trunId: string,\n\t\tblueprint: WorkflowBlueprint,\n\t\tfailedNodeId: string,\n\t): Promise<void> {\n\t\tconst successors = blueprint.edges\n\t\t\t.filter((edge) => edge.source === failedNodeId)\n\t\t\t.map((edge) => edge.target)\n\t\t\t.map((targetId) => blueprint.nodes.find((node) => node.id === targetId))\n\t\t\t.filter((node) => node)\n\n\t\tfor (const successor of successors) {\n\t\t\tif (successor) {\n\t\t\t\tconst joinStrategy = successor.config?.joinStrategy || 'all'\n\t\t\t\tif (joinStrategy === 'all') {\n\t\t\t\t\tconst poisonKey = `flowcraft:fanin:poison:${runId}:${successor.id}`\n\t\t\t\t\tawait this.store.setIfNotExist(poisonKey, 'poisoned', 3600)\n\t\t\t\t\tthis.logger.info(\n\t\t\t\t\t\t`[Adapter] Wrote poison pill for 'all' join node '${successor.id}' due to failed predecessor '${failedNodeId}'`,\n\t\t\t\t\t)\n\t\t\t\t} else if (joinStrategy === 'any') {\n\t\t\t\t\tconst cancelKey = `flowcraft:fanin:cancel:${runId}:${successor.id}`\n\t\t\t\t\tawait this.store.setIfNotExist(cancelKey, 'cancelled', 3600)\n\t\t\t\t\tthis.logger.info(\n\t\t\t\t\t\t`[Adapter] Wrote cancellation pill for 'any' join node '${successor.id}' due to failed predecessor '${failedNodeId}'`,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
|