flowcraft 2.9.2 → 2.9.3
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 +1 -1
- package/dist/index.mjs +4 -4
- package/dist/index.mjs.map +1 -1
- package/dist/{runtime-CRwlRW2p.mjs → runtime-lNm7WbD1.mjs} +35 -6
- package/dist/runtime-lNm7WbD1.mjs.map +1 -0
- package/dist/testing/index.mjs +1 -1
- package/package.json +1 -1
- package/dist/runtime-CRwlRW2p.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-lNm7WbD1.mjs","names":["SyncContext"],"sources":["../src/adapters/persistent-event-bus.ts","../src/analysis.ts","../src/container.ts","../src/evaluator.ts","../src/logger.ts","../src/errors.ts","../src/context.ts","../src/runtime/state.ts","../src/runtime/execution-context.ts","../src/runtime/orchestrators/utils.ts","../src/runtime/orchestrator.ts","../src/serializer.ts","../src/node.ts","../src/nodes/batch-gather.ts","../src/nodes/batch-scatter.ts","../src/nodes/sleep.ts","../src/runtime/traverser.ts","../src/nodes/subflow.ts","../src/nodes/wait.ts","../src/nodes/webhook.ts","../src/sanitizer.ts","../src/runtime/executors.ts","../src/runtime/node-executor-factory.ts","../src/runtime/scheduler.ts","../src/runtime/workflow-logic-handler.ts","../src/runtime/runtime.ts"],"sourcesContent":["import type { FlowcraftEvent, IEventBus } from '../types'\n\n/**\n * Interface for a persistent storage mechanism for events.\n * Implementations can store events in databases, log streams, files, etc.\n */\nexport interface IEventStore {\n\t/**\n\t * Store an event persistently.\n\t * @param event The event to store\n\t * @param executionId The execution ID for grouping events\n\t */\n\tstore(event: FlowcraftEvent, executionId: string): Promise<void>\n\n\t/**\n\t * Retrieve all events for a specific execution.\n\t * @param executionId The execution ID\n\t * @returns Array of events in chronological order\n\t */\n\tretrieve(executionId: string): Promise<FlowcraftEvent[]>\n\n\t/**\n\t * Retrieve events for multiple executions.\n\t * @param executionIds Array of execution IDs\n\t * @returns Map of execution ID to array of events\n\t */\n\tretrieveMultiple(executionIds: string[]): Promise<Map<string, FlowcraftEvent[]>>\n}\n\n/**\n * A pluggable event bus adapter that persists all workflow events\n * to a configurable storage backend, enabling time-travel debugging and replay.\n *\n * @example\n * ```typescript\n * // Using a database-backed store\n * const eventStore = new DatabaseEventStore(dbConnection)\n * const eventBus = new PersistentEventBusAdapter(eventStore)\n * const runtime = new FlowRuntime({ eventBus })\n *\n * // Later, replay the execution\n * const events = await eventStore.retrieve(executionId)\n * const finalState = await runtime.replay(blueprint, events)\n * ```\n */\nexport class PersistentEventBusAdapter implements IEventBus {\n\tconstructor(private store: IEventStore) {}\n\n\t/**\n\t * Emit an event by storing it persistently.\n\t * Also emits to console for debugging (can be made configurable).\n\t */\n\tasync emit(event: FlowcraftEvent): Promise<void> {\n\t\tlet executionId = 'unknown'\n\t\tif ('executionId' in event.payload) {\n\t\t\texecutionId = event.payload.executionId as string\n\t\t}\n\t\tawait this.store.store(event, executionId)\n\t}\n}\n\n/**\n * Simple in-memory event store for testing and development.\n * Not suitable for production use.\n */\nexport class InMemoryEventStore implements IEventStore {\n\tprivate events = new Map<string, FlowcraftEvent[]>()\n\n\tasync store(event: FlowcraftEvent, executionId: string): Promise<void> {\n\t\tif (!this.events.has(executionId)) {\n\t\t\tthis.events.set(executionId, [])\n\t\t}\n\t\tthis.events.get(executionId)?.push(event)\n\t}\n\n\tasync retrieve(executionId: string): Promise<FlowcraftEvent[]> {\n\t\treturn this.events.get(executionId) || []\n\t}\n\n\tasync retrieveMultiple(executionIds: string[]): Promise<Map<string, FlowcraftEvent[]>> {\n\t\tconst result = new Map<string, FlowcraftEvent[]>()\n\t\tfor (const id of executionIds) {\n\t\t\tresult.set(id, await this.retrieve(id))\n\t\t}\n\t\treturn result\n\t}\n\n\t/**\n\t * Clear all stored events (useful for testing).\n\t */\n\tclear(): void {\n\t\tthis.events.clear()\n\t}\n}\n","import type { FlowcraftEvent, 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 using an iterative DFS algorithm.\n * This avoids stack overflow issues for deep graphs compared to the recursive version.\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?.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\t// 0 = not visited, 1 = visiting, 2 = visited\n\tconst state = new Map<string, number>()\n\tfor (const id of allNodeIds) {\n\t\tstate.set(id, 0)\n\t}\n\n\tfor (const startNode of allNodeIds) {\n\t\tif (state.get(startNode) !== 0) continue\n\n\t\tconst stack: { node: string; path: string[] }[] = [{ node: startNode, path: [] }]\n\t\tconst pathSet = new Set<string>()\n\n\t\twhile (stack.length > 0) {\n\t\t\tconst { node, path } = stack[stack.length - 1]\n\n\t\t\tif (state.get(node) === 0) {\n\t\t\t\t// first visit\n\t\t\t\tstate.set(node, 1) // visiting\n\t\t\t\tpathSet.add(node)\n\t\t\t\tpath.push(node)\n\t\t\t}\n\n\t\t\tconst neighbors = adj.get(node) || []\n\t\t\tlet foundUnvisited = false\n\n\t\t\tfor (const neighbor of neighbors) {\n\t\t\t\tif (state.get(neighbor) === 1) {\n\t\t\t\t\t// back edge, cycle found\n\t\t\t\t\tconst cycleStartIndex = path.indexOf(neighbor)\n\t\t\t\t\tconst cycle = path.slice(cycleStartIndex)\n\t\t\t\t\tcycles.push([...cycle, neighbor])\n\t\t\t\t} else if (state.get(neighbor) === 0) {\n\t\t\t\t\t// unvisited neighbor\n\t\t\t\t\tstack.push({ node: neighbor, path: [...path] })\n\t\t\t\t\tfoundUnvisited = true\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!foundUnvisited) {\n\t\t\t\t// all neighbors visited\n\t\t\t\tstate.set(node, 2) // visited\n\t\t\t\tstack.pop()\n\t\t\t\tpathSet.delete(node)\n\t\t\t}\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?.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\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 * Generates Mermaid diagram syntax from a WorkflowBlueprint with execution history styling\n * @param blueprint The WorkflowBlueprint object containing nodes and edges\n * @param events Array of FlowcraftEvent objects from the workflow execution\n * @returns Mermaid syntax string for the flowchart with execution path highlighting\n */\nexport function generateMermaidForRun(\n\tblueprint: WorkflowBlueprint,\n\tevents: FlowcraftEvent[],\n): string {\n\tif (!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\tconst successfulNodes = new Set<string>()\n\tconst failedNodes = new Set<string>()\n\tconst takenEdges = new Set<string>()\n\n\tfor (const event of events) {\n\t\tswitch (event.type) {\n\t\t\tcase 'node:finish':\n\t\t\t\tsuccessfulNodes.add(event.payload.nodeId)\n\t\t\t\tbreak\n\t\t\tcase 'node:error':\n\t\t\t\tfailedNodes.add(event.payload.nodeId)\n\t\t\t\tbreak\n\t\t\tcase 'edge:evaluate':\n\t\t\t\tif (event.payload.result) {\n\t\t\t\t\tconst edgeKey = `${event.payload.source}->${event.payload.target}`\n\t\t\t\t\ttakenEdges.add(edgeKey)\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t}\n\t}\n\n\tfor (const node of blueprint.nodes) {\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 node of blueprint.nodes) {\n\t\tif (successfulNodes.has(node.id)) {\n\t\t\tmermaid += ` style ${node.id} fill:#d4edda,stroke:#c3e6cb\\n`\n\t\t} else if (failedNodes.has(node.id)) {\n\t\t\tmermaid += ` style ${node.id} fill:#f8d7da,stroke:#f5c6cb\\n`\n\t\t}\n\t}\n\n\tlet edgeIndex = 0\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\tconst edgeKey = `${edge.source}->${edge.target}`\n\t\tconst isTaken = takenEdges.has(edgeKey)\n\n\t\tlet edgeLine: string\n\t\tif (labelParts.length > 0) {\n\t\t\tconst edgeLabel = labelParts.join(' | ')\n\t\t\tedgeLine = ` ${edge.source} -- \"${edgeLabel}\" --> ${edge.target}\\n`\n\t\t} else {\n\t\t\tedgeLine = ` ${edge.source} --> ${edge.target}\\n`\n\t\t}\n\n\t\tmermaid += edgeLine\n\n\t\tif (isTaken) {\n\t\t\tmermaid += ` linkStyle ${edgeIndex} stroke:#007bff,stroke-width:3px\\n`\n\t\t}\n\n\t\tedgeIndex++\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?.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\n\t\t.map((node) => node.id)\n\t\t.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\n\t\t.map((node) => node.id)\n\t\t.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","export type ServiceToken<_T = any> = string | symbol\n\nexport class DIContainer {\n\tprivate services: Map<ServiceToken, any> = new Map()\n\tprivate factories: Map<ServiceToken, (container: DIContainer) => any> = new Map()\n\n\tregister<T>(token: ServiceToken<T>, implementation: T): void {\n\t\tthis.services.set(token, implementation)\n\t}\n\n\tregisterFactory<T>(token: ServiceToken<T>, factory: (container: DIContainer) => T): void {\n\t\tthis.factories.set(token, factory)\n\t}\n\n\tresolve<T>(token: ServiceToken<T>): T {\n\t\tif (this.services.has(token)) {\n\t\t\treturn this.services.get(token)\n\t\t}\n\n\t\tif (this.factories.has(token)) {\n\t\t\tconst factory = this.factories.get(token)\n\t\t\tconst instance = factory?.(this)\n\t\t\tthis.services.set(token, instance)\n\t\t\treturn instance\n\t\t}\n\n\t\tthrow new Error(`Service not found for token: ${String(token)}`)\n\t}\n\n\thas(token: ServiceToken): boolean {\n\t\treturn this.services.has(token) || this.factories.has(token)\n\t}\n\n\tcreateChild(): DIContainer {\n\t\tconst child = new DIContainer()\n\t\tchild.services = new Map(this.services)\n\t\tchild.factories = new Map(this.factories)\n\t\treturn child\n\t}\n}\n\nexport const ServiceTokens = {\n\tLogger: Symbol.for('flowcraft:logger'),\n\tSerializer: Symbol.for('flowcraft:serializer'),\n\tEvaluator: Symbol.for('flowcraft:evaluator'),\n\tEventBus: Symbol.for('flowcraft:eventBus'),\n\tOrchestrator: Symbol.for('flowcraft:orchestrator'),\n\tMiddleware: Symbol.for('flowcraft:middleware'),\n\tNodeRegistry: Symbol.for('flowcraft:nodeRegistry'),\n\tBlueprintRegistry: Symbol.for('flowcraft:blueprintRegistry'),\n\tDependencies: Symbol.for('flowcraft:dependencies'),\n} as const\n","import type { IEvaluator } from './types'\n\n/**\n * A safe evaluator that only allows simple property access.\n * It cannot execute arbitrary code and is secure for untrusted inputs.\n *\n * Example expressions:\n * - \"result.output.status\"\n * - \"context.user.isAdmin\"\n * - \"input.value\"\n */\nexport class PropertyEvaluator implements IEvaluator {\n\tevaluate(expression: string, context: Record<string, any>): any {\n\t\ttry {\n\t\t\t// Basic validation to ensure it's a simple path\n\t\t\tif (!/^[a-zA-Z0-9_$.]+$/.test(expression)) {\n\t\t\t\tconsole.error(\n\t\t\t\t\t`Error evaluating expression: \"${expression}\" contains invalid characters.`,\n\t\t\t\t)\n\t\t\t\treturn undefined\n\t\t\t}\n\n\t\t\tconst parts = expression.split('.')\n\t\t\tconst startKey = parts[0]\n\n\t\t\tif (!Object.hasOwn(context, startKey)) {\n\t\t\t\treturn undefined\n\t\t\t}\n\n\t\t\tlet current = context[startKey]\n\t\t\tfor (let i = 1; i < parts.length; i++) {\n\t\t\t\tif (current === null || current === undefined) {\n\t\t\t\t\treturn undefined\n\t\t\t\t}\n\t\t\t\tcurrent = current[parts[i]]\n\t\t\t}\n\t\t\treturn current\n\t\t} catch (error) {\n\t\t\tconsole.error(`Error evaluating property expression \"${expression}\":`, error)\n\t\t\treturn undefined\n\t\t}\n\t}\n}\n\n/**\n * Rewrites an expression so that hyphenated identifiers use bracket notation.\n * E.g. \"foo-bar.total\" → 'context[\"foo-bar\"].total'\n */\nfunction rewriteHyphenatedIdentifiers(expression: string, hyphenatedKeys: string[]): string {\n\tlet result = expression\n\t// sort by len desc to avoid partial replacements\n\tconst sortedKeys = [...hyphenatedKeys].toSorted((a, b) => b.length - a.length)\n\tfor (const key of sortedKeys) {\n\t\tif (!key.includes('-')) continue\n\t\tconst regex = new RegExp(`(?<![\\\\w$])${escapeRegex(key)}(?![\\\\w$-])`, 'g')\n\t\tresult = result.replace(regex, `context[\"${key}\"]`)\n\t}\n\treturn result\n}\n\nfunction escapeRegex(str: string): string {\n\treturn str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\n/**\n * @warning This evaluator uses `new Function()` and can execute arbitrary\n * JavaScript code. It poses a significant security risk if the expressions\n * are not from a trusted source (e.g., user input).\n *\n * It should only be used in controlled environments where all workflow\n * definitions are static and authored by trusted developers.\n *\n * For safer evaluation, use the default `PropertyEvaluator` or install a\n * sandboxed library like `jsep` to create a custom, secure evaluator.\n */\nexport class UnsafeEvaluator implements IEvaluator {\n\tevaluate(expression: string, context: Record<string, any>): any {\n\t\ttry {\n\t\t\t// filter out keys that aren't valid JavaScript identifiers\n\t\t\tconst validIdentifierRegex = /^[a-z_$][\\w$]*$/i\n\t\t\tconst validKeys = Object.keys(context).filter((key) => validIdentifierRegex.test(key))\n\t\t\tconst hyphenatedKeys = Object.keys(context).filter(\n\t\t\t\t(key) => !validIdentifierRegex.test(key) && /^[a-zA-Z0-9_$-]+$/.test(key),\n\t\t\t)\n\t\t\tconst validContext: Record<string, any> = {}\n\t\t\tfor (const key of validKeys) {\n\t\t\t\tvalidContext[key] = context[key]\n\t\t\t}\n\t\t\tfor (const key of hyphenatedKeys) {\n\t\t\t\tvalidContext[key] = context[key]\n\t\t\t}\n\n\t\t\tlet rewrittenExpression = rewriteHyphenatedIdentifiers(expression, hyphenatedKeys)\n\n\t\t\t// sandboxed function prevents access to global scope (e.g., `window`, `process`).\n\t\t\tconst sandbox = new Function('context', ...validKeys, `return ${rewrittenExpression}`)\n\t\t\treturn sandbox(validContext, ...validKeys.map((k) => validContext[k]))\n\t\t} catch (error) {\n\t\t\tconsole.error(`Error evaluating expression \"${expression}\":`, error)\n\t\t\t// default to a \"falsy\" value.\n\t\t\treturn undefined\n\t\t}\n\t}\n}\n","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","/**\n * A single, comprehensive error class for the framework.\n * Use this for all errors to ensure consistent structure and easy debugging.\n */\nexport class FlowcraftError extends Error {\n\tpublic readonly message: string\n\tpublic readonly nodeId?: string\n\tpublic readonly blueprintId?: string\n\tpublic readonly executionId?: string\n\tpublic readonly isFatal: boolean\n\n\tconstructor(\n\t\tmessage: string,\n\t\toptions: {\n\t\t\tcause?: Error\n\t\t\tnodeId?: string\n\t\t\tblueprintId?: string\n\t\t\texecutionId?: string\n\t\t\tisFatal?: boolean\n\t\t} = {},\n\t) {\n\t\t// Pass the cause to the parent Error constructor for proper chaining\n\t\tsuper(message, { cause: options.cause })\n\t\tthis.name = 'FlowcraftError'\n\t\tthis.message = message\n\n\t\tthis.nodeId = options.nodeId\n\t\tthis.blueprintId = options.blueprintId\n\t\tthis.executionId = options.executionId\n\t\tthis.isFatal = options.isFatal ?? false\n\t}\n}\n","import type { IAsyncContext, ISyncContext, PatchOperation } 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\tget(key: string): any | undefined {\n\t\treturn this.data.get(key)\n\t}\n\n\tset<K extends keyof TContext>(key: K, value: TContext[K]): void\n\tset(key: string, value: any): void {\n\t\tthis.data.set(key, value)\n\t}\n\n\thas<K extends keyof TContext>(key: K): boolean\n\thas(key: string): boolean {\n\t\treturn this.data.has(key)\n\t}\n\n\tdelete<K extends keyof TContext>(key: K): boolean\n\tdelete(key: string): boolean {\n\t\treturn this.data.delete(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<\n\tTContext extends Record<string, any>,\n> 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\tget(key: string): Promise<any | 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\tset(key: string, value: any): 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\thas(key: string): 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\tdelete(key: string): 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\tasync patch(_operations: PatchOperation[]): Promise<void> {\n\t\tthrow new Error('Patch operations not supported by AsyncContextView')\n\t}\n}\n\n/**\n * A proxy wrapper that tracks changes to an async context for delta-based persistence.\n * Records all mutations (set/delete operations) to enable efficient partial updates.\n */\nexport class TrackedAsyncContext<\n\tTContext extends Record<string, any>,\n> implements IAsyncContext<TContext> {\n\tpublic readonly type = 'async' as const\n\tprivate deltas: PatchOperation[] = []\n\tprivate innerContext: IAsyncContext<TContext>\n\tprivate eventBus?: any\n\tprivate executionId?: string\n\tprivate sourceNode?: string\n\n\tconstructor(\n\t\tinnerContext: IAsyncContext<TContext>,\n\t\teventBus?: any,\n\t\texecutionId?: string,\n\t\tsourceNode?: string,\n\t) {\n\t\tthis.innerContext = innerContext\n\t\tthis.eventBus = eventBus\n\t\tthis.executionId = executionId\n\t\tthis.sourceNode = sourceNode\n\t}\n\n\tasync get<K extends keyof TContext>(key: K): Promise<TContext[K] | undefined>\n\tasync get(key: string): Promise<any | undefined> {\n\t\treturn this.innerContext.get(key)\n\t}\n\n\tasync set<K extends keyof TContext>(key: K, value: TContext[K]): Promise<void>\n\tasync set(key: string, value: any): Promise<void> {\n\t\tthis.deltas.push({ op: 'set', key, value })\n\t\tawait this.innerContext.set(key, value)\n\t\tif (this.eventBus && this.executionId) {\n\t\t\tawait this.eventBus.emit({\n\t\t\t\ttype: 'context:change',\n\t\t\t\tpayload: {\n\t\t\t\t\tsourceNode: this.sourceNode || 'unknown',\n\t\t\t\t\tkey,\n\t\t\t\t\top: 'set',\n\t\t\t\t\tvalue,\n\t\t\t\t\texecutionId: this.executionId,\n\t\t\t\t},\n\t\t\t})\n\t\t}\n\t}\n\n\tasync has<K extends keyof TContext>(key: K): Promise<boolean>\n\tasync has(key: string): Promise<boolean> {\n\t\treturn this.innerContext.has(key)\n\t}\n\n\tasync delete<K extends keyof TContext>(key: K): Promise<boolean>\n\tasync delete(key: string): Promise<boolean> {\n\t\tthis.deltas.push({ op: 'delete', key })\n\t\tconst result = await this.innerContext.delete(key)\n\t\tif (this.eventBus && this.executionId && result) {\n\t\t\tawait this.eventBus.emit({\n\t\t\t\ttype: 'context:change',\n\t\t\t\tpayload: {\n\t\t\t\t\tsourceNode: this.sourceNode || 'unknown',\n\t\t\t\t\tkey,\n\t\t\t\t\top: 'delete',\n\t\t\t\t\texecutionId: this.executionId,\n\t\t\t\t},\n\t\t\t})\n\t\t}\n\t\treturn result\n\t}\n\n\ttoJSON(): Promise<Record<string, any>> {\n\t\treturn this.innerContext.toJSON()\n\t}\n\n\tasync patch(operations: PatchOperation[]): Promise<void> {\n\t\tif (this.innerContext.patch) {\n\t\t\treturn this.innerContext.patch(operations)\n\t\t}\n\n\t\tfor (const op of operations) {\n\t\t\tif (op.op === 'set') {\n\t\t\t\tawait this.innerContext.set(op.key, op.value)\n\t\t\t} else if (op.op === 'delete') {\n\t\t\t\tawait this.innerContext.delete(op.key)\n\t\t\t}\n\t\t}\n\t}\n\n\tgetDeltas(): PatchOperation[] {\n\t\treturn [...this.deltas]\n\t}\n\n\tclearDeltas(): void {\n\t\tthis.deltas = []\n\t}\n\n\t/**\n\t * Configures the event emitter for tracking context changes.\n\t * This enables the context to emit events when set/delete operations occur,\n\t * allowing for external monitoring and persistence of context mutations.\n\t *\n\t * @param eventBus - The event bus instance to emit context change events\n\t * @param executionId - The unique identifier for the current workflow execution\n\t * @param sourceNode - Optional identifier for the node that triggered the context change\n\t */\n\tconfigureEventEmitter(eventBus: any, executionId: string, sourceNode?: string): void {\n\t\tthis.eventBus = eventBus\n\t\tthis.executionId = executionId\n\t\tthis.sourceNode = sourceNode\n\t}\n}\n","import { AsyncContextView, Context as SyncContext, TrackedAsyncContext } from '../context'\nimport { FlowcraftError } from '../errors'\nimport type { IAsyncContext, ISerializer, WorkflowError, WorkflowResult } from '../types'\n\nexport class WorkflowState<TContext extends Record<string, any>> {\n\tprivate _completedNodes = new Set<string>()\n\tprivate errors: WorkflowError[] = []\n\tprivate anyFallbackExecuted = false\n\tprivate context: IAsyncContext<TContext>\n\tprivate _isAwaiting = false\n\tprivate _awaitingNodeIds = new Set<string>()\n\tprivate _awaitingDetails = new Map<string, any>()\n\n\tconstructor(initialData: Partial<TContext>, context?: IAsyncContext<TContext>) {\n\t\tif (context) {\n\t\t\tthis.context =\n\t\t\t\tcontext instanceof TrackedAsyncContext ? context : new TrackedAsyncContext(context)\n\t\t} else {\n\t\t\tthis.context = new TrackedAsyncContext(\n\t\t\t\tnew AsyncContextView(new SyncContext<TContext>(initialData)),\n\t\t\t)\n\t\t}\n\t\tif ((initialData as any)._awaitingNodeIds) {\n\t\t\tthis._isAwaiting = true\n\t\t\tconst awaitingIds = (initialData as any)._awaitingNodeIds\n\t\t\tif (Array.isArray(awaitingIds)) {\n\t\t\t\tfor (const id of awaitingIds) {\n\t\t\t\t\tthis._awaitingNodeIds.add(id)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif ((initialData as any)._awaitingDetails) {\n\t\t\tthis._awaitingDetails = new Map(Object.entries((initialData as any)._awaitingDetails))\n\t\t}\n\t\tfor (const key of Object.keys(initialData)) {\n\t\t\tif (key.startsWith('_outputs.')) {\n\t\t\t\tconst nodeId = key.substring('_outputs.'.length)\n\t\t\t\tthis._completedNodes.add(nodeId)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Configure the context to emit events when modified.\n\t * This is called after the ExecutionContext is created.\n\t */\n\tsetEventEmitter(eventBus: any, executionId: string, sourceNode?: string): void {\n\t\tif (this.context instanceof TrackedAsyncContext) {\n\t\t\tthis.context.configureEventEmitter(eventBus, executionId, sourceNode)\n\t\t}\n\t}\n\n\tasync addCompletedNode(nodeId: string, output: any) {\n\t\tthis._completedNodes.add(nodeId)\n\t\tawait this.context.set(`_outputs.${nodeId}` as any, output)\n\t\tawait this.context.set(nodeId as any, output)\n\t}\n\n\taddError(nodeId: string, error: Error) {\n\t\tconst flowcraftError = new FlowcraftError(error.message, {\n\t\t\tcause: error,\n\t\t\tnodeId,\n\t\t\tisFatal: false,\n\t\t})\n\t\tthis.errors.push({\n\t\t\t...flowcraftError,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\toriginalError: error, // legacy compatibility\n\t\t})\n\t}\n\n\tclearError(nodeId: string) {\n\t\tthis.errors = this.errors.filter((err) => err.nodeId !== nodeId)\n\t}\n\n\tmarkFallbackExecuted() {\n\t\tthis.anyFallbackExecuted = true\n\t}\n\n\tgetContext(): IAsyncContext<TContext> {\n\t\treturn this.context\n\t}\n\n\tgetCompletedNodes(): Set<string> {\n\t\treturn new Set(this._completedNodes)\n\t}\n\n\tgetErrors(): WorkflowError[] {\n\t\treturn this.errors\n\t}\n\n\tgetAnyFallbackExecuted(): boolean {\n\t\treturn this.anyFallbackExecuted\n\t}\n\n\tasync markAsAwaiting(nodeId: string, details?: any): Promise<void> {\n\t\tthis._isAwaiting = true\n\t\tthis._awaitingNodeIds.add(nodeId)\n\t\tif (details) {\n\t\t\tthis._awaitingDetails.set(nodeId, details)\n\t\t}\n\t\tawait this.context.set('_awaitingNodeIds' as any, Array.from(this._awaitingNodeIds))\n\t\tawait this.context.set('_awaitingDetails' as any, Object.fromEntries(this._awaitingDetails))\n\t}\n\n\tisAwaiting(): boolean {\n\t\treturn this._isAwaiting && this._awaitingNodeIds.size > 0\n\t}\n\n\tgetAwaitingNodeIds(): string[] {\n\t\treturn Array.from(this._awaitingNodeIds)\n\t}\n\n\tgetAwaitingDetails(nodeId: string): any {\n\t\treturn this._awaitingDetails.get(nodeId)\n\t}\n\n\tclearAwaiting(nodeId?: string): void {\n\t\tif (nodeId) {\n\t\t\tthis._awaitingNodeIds.delete(nodeId)\n\t\t\tthis._awaitingDetails.delete(nodeId)\n\t\t} else {\n\t\t\tthis._awaitingNodeIds.clear()\n\t\t\tthis._awaitingDetails.clear()\n\t\t}\n\t\tthis._isAwaiting = this._awaitingNodeIds.size > 0\n\n\t\tif (this._awaitingNodeIds.size > 0) {\n\t\t\tthis.context.set('_awaitingNodeIds' as any, Array.from(this._awaitingNodeIds))\n\t\t\tthis.context.set('_awaitingDetails' as any, Object.fromEntries(this._awaitingDetails))\n\t\t} else {\n\t\t\tthis.context.delete('_awaitingNodeIds' as any)\n\t\t\tthis.context.delete('_awaitingDetails' as any)\n\t\t}\n\t}\n\n\tgetStatus(isTraversalComplete = false): WorkflowResult['status'] {\n\t\tif (this._isAwaiting) return 'awaiting'\n\t\tif (this.anyFallbackExecuted) return 'completed'\n\t\tif (this.errors.length > 0) return 'failed'\n\t\tif (isTraversalComplete) return 'completed'\n\t\treturn 'stalled'\n\t}\n\n\tasync toResult(\n\t\tserializer: ISerializer,\n\t\texecutionId?: string,\n\t): Promise<WorkflowResult<TContext>> {\n\t\tconst contextJSON = (await this.context.toJSON()) as TContext\n\t\tif (!this._isAwaiting && (contextJSON as any)._awaitingNodeIds) {\n\t\t\tdelete (contextJSON as any)._awaitingNodeIds\n\t\t\tdelete (contextJSON as any)._awaitingDetails\n\t\t}\n\t\tif (executionId) {\n\t\t\t;(contextJSON as any)._executionId = executionId\n\t\t}\n\t\treturn {\n\t\t\tcontext: contextJSON,\n\t\t\tserializedContext: serializer.serialize(contextJSON),\n\t\t\tstatus: this.getStatus(),\n\t\t\terrors: this.errors.length > 0 ? this.errors : undefined,\n\t\t}\n\t}\n}\n","import type {\n\tIEvaluator,\n\tIEventBus,\n\tILogger,\n\tISerializer,\n\tMiddleware,\n\tNodeClass,\n\tNodeFunction,\n\tRuntimeDependencies,\n\tWorkflowBlueprint,\n} from '../types'\nimport type { FlowRuntime } from './runtime'\nimport { WorkflowState } from './state'\n\n/**\n * A container for all state and dependencies of a single workflow execution.\n * This object is created once per `run` and passed through the execution stack.\n */\nexport class ExecutionContext<\n\tTContext extends Record<string, any>,\n\tTDependencies extends RuntimeDependencies,\n> {\n\tconstructor(\n\t\tpublic readonly blueprint: WorkflowBlueprint,\n\t\tpublic readonly state: WorkflowState<TContext>,\n\t\tpublic readonly nodeRegistry: Map<string, NodeFunction | NodeClass>,\n\t\tpublic readonly executionId: string,\n\t\tpublic readonly runtime: FlowRuntime<TContext, TDependencies>, // A reference back to the runtime for orchestrating subflows\n\t\tpublic readonly services: {\n\t\t\tlogger: ILogger\n\t\t\teventBus: IEventBus\n\t\t\tserializer: ISerializer\n\t\t\tevaluator: IEvaluator\n\t\t\tmiddleware: Middleware[]\n\t\t\tdependencies: TDependencies\n\t\t},\n\t\tpublic readonly signal?: AbortSignal,\n\t\tpublic readonly concurrency?: number,\n\t) {\n\t\tthis.state.setEventEmitter(this.services.eventBus, this.executionId)\n\t}\n\n\tpublic createForSubflow(\n\t\tsubBlueprint: WorkflowBlueprint,\n\t\tinitialSubState: Partial<TContext>,\n\t): ExecutionContext<TContext, TDependencies> {\n\t\tconst subState = new WorkflowState<TContext>(initialSubState)\n\t\treturn new ExecutionContext(\n\t\t\tsubBlueprint,\n\t\t\tsubState,\n\t\t\tthis.nodeRegistry,\n\t\t\tthis.executionId,\n\t\t\tthis.runtime,\n\t\t\tthis.services,\n\t\t\tthis.signal,\n\t\t\tthis.concurrency,\n\t\t)\n\t}\n}\n","import { FlowcraftError } from '../../errors'\nimport type { NodeDefinition, WorkflowBlueprint } from '../../types'\nimport type { NodeExecutionResult } from '../executors'\nimport type { WorkflowState } from '../state'\nimport type { GraphTraverser } from '../traverser'\n\nexport async function executeBatch(\n\treadyNodes: Array<{ nodeId: string; nodeDef: any }>,\n\tblueprint: WorkflowBlueprint,\n\tstate: WorkflowState<any>,\n\texecutorFactory: (nodeId: string) => any,\n\truntime: any,\n\tmaxConcurrency?: number,\n): Promise<\n\tArray<\n\t\t| { status: 'fulfilled'; value: { nodeId: string; executionResult: NodeExecutionResult } }\n\t\t| { status: 'rejected'; reason: { nodeId: string; error: unknown } }\n\t>\n> {\n\tconst concurrency = maxConcurrency || readyNodes.length\n\tconst results: Array<\n\t\t| { status: 'fulfilled'; value: { nodeId: string; executionResult: NodeExecutionResult } }\n\t\t| { status: 'rejected'; reason: { nodeId: string; error: unknown } }\n\t> = []\n\n\tfor (let i = 0; i < readyNodes.length; i += concurrency) {\n\t\tconst batch = readyNodes.slice(i, i + concurrency)\n\t\tconst batchPromises = batch.map(async ({ nodeId }) => {\n\t\t\ttry {\n\t\t\t\tconst executor = executorFactory(nodeId)\n\t\t\t\tif (!executor) throw new Error(`No executor for node ${nodeId}`)\n\t\t\t\tconst executionResult = await executor.execute(\n\t\t\t\t\tawait runtime.resolveNodeInput(nodeId, blueprint, state.getContext()),\n\t\t\t\t)\n\t\t\t\tresults.push({\n\t\t\t\t\tstatus: 'fulfilled' as const,\n\t\t\t\t\tvalue: { nodeId, executionResult },\n\t\t\t\t})\n\t\t\t} catch (error) {\n\t\t\t\tresults.push({\n\t\t\t\t\tstatus: 'rejected' as const,\n\t\t\t\t\treason: { nodeId, error },\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\n\t\tawait Promise.all(batchPromises)\n\t}\n\n\treturn results\n}\n\nexport async function processResults(\n\tsettledResults: Array<\n\t\t| { status: 'fulfilled'; value: { nodeId: string; executionResult: NodeExecutionResult } }\n\t\t| { status: 'rejected'; reason: { nodeId: string; error: unknown } }\n\t>,\n\ttraverser: GraphTraverser,\n\tstate: WorkflowState<any>,\n\truntime: any,\n\t_blueprint: WorkflowBlueprint,\n\texecutionId?: string,\n): Promise<void> {\n\tfor (const promiseResult of settledResults) {\n\t\tif (promiseResult.status === 'rejected') {\n\t\t\tconst { nodeId, error } = promiseResult.reason\n\t\t\tif (error instanceof FlowcraftError && error.message.includes('cancelled')) {\n\t\t\t\tthrow error\n\t\t\t}\n\t\t\tstate.addError(nodeId, error as Error)\n\t\t\tcontinue\n\t\t}\n\n\t\tconst { nodeId, executionResult } = promiseResult.value\n\n\t\tif (executionResult.status === 'success') {\n\t\t\tconst result = executionResult.result\n\t\t\tif (result) {\n\t\t\t\tawait state.addCompletedNode(nodeId, result.output)\n\t\t\t\tif (result._fallbackExecuted) {\n\t\t\t\t\tstate.markFallbackExecuted()\n\t\t\t\t}\n\n\t\t\t\tif (result.dynamicNodes && result.dynamicNodes.length > 0) {\n\t\t\t\t\tconst gatherNodeId = result.output?.gatherNodeId\n\t\t\t\t\tfor (const dynamicNode of result.dynamicNodes) {\n\t\t\t\t\t\ttraverser.addDynamicNode(dynamicNode.id, dynamicNode, nodeId, gatherNodeId)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst matched = await runtime.determineNextNodes(\n\t\t\t\ttraverser.getDynamicBlueprint(),\n\t\t\t\tnodeId,\n\t\t\t\tresult,\n\t\t\t\tstate.getContext(),\n\t\t\t\texecutionId,\n\t\t\t)\n\n\t\t\tfor (const { node, edge } of matched) {\n\t\t\t\tawait runtime.applyEdgeTransform(\n\t\t\t\t\tedge,\n\t\t\t\t\tresult,\n\t\t\t\t\tnode,\n\t\t\t\t\tstate.getContext(),\n\t\t\t\t\ttraverser.getAllPredecessors(),\n\t\t\t\t\texecutionId,\n\t\t\t\t)\n\t\t\t}\n\n\t\t\ttraverser.markNodeCompleted(\n\t\t\t\tnodeId,\n\t\t\t\tresult,\n\t\t\t\tmatched.map((m: { node: NodeDefinition; edge: any }) => m.node),\n\t\t\t)\n\t\t} else if (executionResult.status === 'failed_with_fallback') {\n\t\t\tconst { fallbackNodeId, error } = executionResult\n\t\t\tconst blueprint = traverser.getDynamicBlueprint()\n\t\t\tconst fallbackNodeDef = blueprint.nodes.find((n) => n.id === fallbackNodeId)\n\n\t\t\tif (!fallbackNodeDef) {\n\t\t\t\tconst notFoundError = new FlowcraftError(\n\t\t\t\t\t`Fallback node '${fallbackNodeId}' not found in blueprint.`,\n\t\t\t\t\t{\n\t\t\t\t\t\tnodeId,\n\t\t\t\t\t\tcause: error,\n\t\t\t\t\t},\n\t\t\t\t)\n\t\t\t\tstate.addError(nodeId, notFoundError)\n\t\t\t} else {\n\t\t\t\tstate.addCompletedNode(nodeId, null)\n\t\t\t\tstate.markFallbackExecuted()\n\n\t\t\t\ttraverser.markNodeCompleted(\n\t\t\t\t\tnodeId,\n\t\t\t\t\t{ action: 'fallback', output: null, _fallbackExecuted: true },\n\t\t\t\t\t[fallbackNodeDef],\n\t\t\t\t)\n\t\t\t}\n\t\t} else {\n\t\t\tstate.addError(nodeId, executionResult.error)\n\t\t}\n\t}\n}\n","import { FlowcraftError } from '../errors'\nimport type { WorkflowResult } from '../types'\nimport { ExecutionContext } from './execution-context'\nimport { executeBatch, processResults } from './orchestrators/utils'\nimport type { GraphTraverser } from './traverser'\nimport type { IOrchestrator } from './types'\n\nexport class DefaultOrchestrator implements IOrchestrator {\n\tasync run(\n\t\tcontext: ExecutionContext<any, any>,\n\t\ttraverser: GraphTraverser,\n\t): Promise<WorkflowResult<any>> {\n\t\tconst hardwareConcurrency = globalThis.navigator?.hardwareConcurrency || 4\n\t\tconst maxConcurrency =\n\t\t\tcontext.concurrency != null && context.concurrency > 0\n\t\t\t\t? context.concurrency\n\t\t\t\t: Math.min(hardwareConcurrency, 10)\n\n\t\ttry {\n\t\t\tcontext.signal?.throwIfAborted()\n\t\t} catch (error) {\n\t\t\tif (error instanceof DOMException && error.name === 'AbortError') {\n\t\t\t\tthrow new FlowcraftError('Workflow cancelled', { isFatal: false })\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\n\t\tlet iterations = 0\n\t\tconst maxIterations = 10000\n\n\t\twhile (traverser.hasMoreWork()) {\n\t\t\tif (++iterations > maxIterations) {\n\t\t\t\tthrow new Error('Traversal exceeded maximum iterations, possible infinite loop')\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tcontext.signal?.throwIfAborted()\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof DOMException && error.name === 'AbortError') {\n\t\t\t\t\tthrow new FlowcraftError('Workflow cancelled', { isFatal: false })\n\t\t\t\t}\n\t\t\t\tthrow error\n\t\t\t}\n\n\t\t\tconst readyNodes = traverser.getReadyNodes()\n\t\t\tconst dynamicBlueprint = traverser.getDynamicBlueprint()\n\t\t\tconst updatedContext = new ExecutionContext(\n\t\t\t\tdynamicBlueprint,\n\t\t\t\tcontext.state,\n\t\t\t\tcontext.nodeRegistry,\n\t\t\t\tcontext.executionId,\n\t\t\t\tcontext.runtime,\n\t\t\t\tcontext.services,\n\t\t\t\tcontext.signal,\n\t\t\t\tcontext.concurrency,\n\t\t\t)\n\t\t\tconst settledResults = await executeBatch(\n\t\t\t\treadyNodes,\n\t\t\t\tdynamicBlueprint,\n\t\t\t\tcontext.state,\n\t\t\t\t(nodeId: string) => context.runtime.getExecutorForNode(nodeId, updatedContext),\n\t\t\t\tcontext.runtime,\n\t\t\t\tmaxConcurrency,\n\t\t\t)\n\n\t\t\tawait processResults(\n\t\t\t\tsettledResults,\n\t\t\t\ttraverser,\n\t\t\t\tcontext.state,\n\t\t\t\tcontext.runtime,\n\t\t\t\tcontext.blueprint,\n\t\t\t\tcontext.executionId,\n\t\t\t)\n\n\t\t\tif (context.state.isAwaiting()) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tconst isTraversalComplete = !traverser.hasMoreWork()\n\t\tconst status = context.state.getStatus(isTraversalComplete)\n\t\tconst result = await context.state.toResult(\n\t\t\tcontext.services.serializer,\n\t\t\tcontext.executionId,\n\t\t)\n\t\tresult.status = status\n\t\treturn result\n\t}\n}\n","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\ttry {\n\t\t\treturn JSON.stringify(data)\n\t\t} catch {\n\t\t\tconsole.warn(\n\t\t\t\t'[Flowcraft] Warning: Circular reference detected in context. Using safe serialization.',\n\t\t\t)\n\t\t\treturn JSON.stringify({\n\t\t\t\t_circularReference: true,\n\t\t\t\tmessage: 'Context contains circular references',\n\t\t\t})\n\t\t}\n\t}\n\n\tdeserialize(text: string): Record<string, any> {\n\t\treturn JSON.parse(text)\n\t}\n}\n","import type { NodeClass, NodeContext, NodeResult, RuntimeDependencies } from './types'\n\n/** A type guard to reliably distinguish a NodeClass from a NodeFunction. */\nexport function isNodeClass(impl: any): impl is NodeClass {\n\treturn typeof impl === 'function' && !!impl.prototype?.exec\n}\n\n/**\n * A structured, class-based node for complex logic with a safe, granular lifecycle.\n * This class is generic, allowing implementations to specify the exact context\n * and dependency types they expect.\n */\nexport abstract class BaseNode<\n\tTContext extends Record<string, any> = Record<string, any>,\n\tTDependencies extends RuntimeDependencies = RuntimeDependencies,\n\tTInput = any,\n\tTOutput = any,\n\tTAction extends string = string,\n> {\n\t/**\n\t * @param params Static parameters for this node instance, passed from the blueprint.\n\t * @param nodeId The ID of the node in the blueprint.\n\t */\n\tconstructor(\n\t\tprotected params?: Record<string, any>,\n\t\tprotected nodeId?: string,\n\t) {}\n\n\t/**\n\t * Phase 1: Gathers and prepares data for execution. This phase is NOT retried on failure.\n\t * @param context The node's execution context.\n\t * @returns The data needed for the `exec` phase.\n\t */\n\tasync prep(context: NodeContext<TContext, TDependencies, TInput>): Promise<any> {\n\t\treturn context.input\n\t}\n\n\t/**\n\t * Phase 2: Performs the core, isolated logic. This is the ONLY phase that is retried.\n\t * @param prepResult The data returned from the `prep` phase.\n\t * @param context The node's execution context.\n\t */\n\tabstract exec(\n\t\tprepResult: any,\n\t\tcontext: NodeContext<TContext, TDependencies, TInput>,\n\t): Promise<Omit<NodeResult<TOutput, TAction>, 'error'>>\n\n\t/**\n\t * Phase 3: Processes the result and saves state. This phase is NOT retried.\n\t * @param execResult The successful result from the `exec` or `fallback` phase.\n\t * @param _context The node's execution context.\n\t */\n\tasync post(\n\t\texecResult: Omit<NodeResult<TOutput, TAction>, 'error'>,\n\t\t_context: NodeContext<TContext, TDependencies, TInput>,\n\t): Promise<NodeResult<TOutput, TAction>> {\n\t\treturn execResult\n\t}\n\n\t/**\n\t * An optional safety net that runs if all `exec` retries fail.\n\t * @param error The final error from the last `exec` attempt.\n\t * @param _context The node's execution context.\n\t */\n\tasync fallback(\n\t\terror: Error,\n\t\t_context: NodeContext<TContext, TDependencies, TInput>,\n\t): Promise<Omit<NodeResult<TOutput, TAction>, 'error'>> {\n\t\t// By default, re-throw the error, failing the node.\n\t\tthrow error\n\t}\n\n\t/**\n\t * An optional cleanup phase for non-retriable errors that occur outside the main `exec` method.\n\t * This method is invoked in a `finally` block or equivalent construct if a fatal, unhandled exception occurs in the `prep`, `exec`, or `post` phases.\n\t * Allows nodes to perform crucial cleanup, such as closing database connections or releasing locks.\n\t * @param _error The error that caused the failure.\n\t * @param _context The node's execution context.\n\t */\n\tasync recover(\n\t\t_error: Error,\n\t\t_context: NodeContext<TContext, TDependencies, TInput>,\n\t): Promise<void> {\n\t\t// Default no-op implementation. Subclasses can override for cleanup.\n\t}\n}\n","import { BaseNode } from '../node'\nimport type { NodeContext, NodeResult } from '../types'\n\nexport class BatchGatherNode extends BaseNode {\n\tasync exec(\n\t\t_prepResult: any,\n\t\tcontext: NodeContext<any, any, any>,\n\t): Promise<Omit<NodeResult, 'error'>> {\n\t\tconst { gatherNodeId, outputKey } = (this.params as any) || {}\n\t\tconst hasMore = (await context.context.get(`${gatherNodeId}_hasMore`)) || false\n\t\tconst dynamicNodes: any[] = []\n\t\tlet results: any[] = []\n\t\tif (hasMore) {\n\t\t\t// create a new scatter node for the next chunk\n\t\t\tconst newScatterId = `${gatherNodeId}_scatter_next`\n\t\t\tdynamicNodes.push({\n\t\t\t\tid: newScatterId,\n\t\t\t\tuses: 'batch-scatter',\n\t\t\t\tinputs: context.input,\n\t\t\t\tparams: { ...this.params, gatherNodeId },\n\t\t\t})\n\t\t} else {\n\t\t\t// collect results from all chunks into outputKey\n\t\t\tconst allWorkerIds =\n\t\t\t\t((await context.context.get(`${gatherNodeId}_allWorkerIds`)) as string[]) || []\n\t\t\tresults = []\n\t\t\tfor (const workerId of allWorkerIds) {\n\t\t\t\tconst result = await context.context.get(`_outputs.${workerId}` as any)\n\t\t\t\tif (result !== undefined) results.push(result)\n\t\t\t}\n\t\t\tawait context.context.set(outputKey as any, results)\n\n\t\t\tconst parentBatchId = gatherNodeId.replace('_gather', '')\n\t\t\tawait context.dependencies.runtime.services.eventBus.emit({\n\t\t\t\ttype: 'batch:finish',\n\t\t\t\tpayload: {\n\t\t\t\t\tbatchId: parentBatchId,\n\t\t\t\t\tgatherNodeId,\n\t\t\t\t\tresults,\n\t\t\t\t},\n\t\t\t})\n\t\t}\n\t\treturn { dynamicNodes, output: results }\n\t}\n}\n","import { BaseNode } from '../node'\nimport type { NodeContext, NodeResult } from '../types'\n\nexport class BatchScatterNode extends BaseNode {\n\tasync exec(\n\t\t_prepResult: any,\n\t\tcontext: NodeContext<any, any, any>,\n\t): Promise<Omit<NodeResult, 'error'>> {\n\t\tconst inputArray = context.input || []\n\t\tif (!Array.isArray(inputArray)) {\n\t\t\tthrow new Error(`Input for batch-scatter node '${this.nodeId}' must be an array.`)\n\t\t}\n\t\tconst {\n\t\t\tchunkSize = inputArray.length,\n\t\t\tworkerUsesKey,\n\t\t\tgatherNodeId,\n\t\t} = (this.params as any) || {}\n\t\tif (!workerUsesKey || !gatherNodeId) {\n\t\t\tthrow new Error(\n\t\t\t\t`BatchScatterNode requires 'workerUsesKey' and 'gatherNodeId' parameters.`,\n\t\t\t)\n\t\t}\n\t\tconst batchId = globalThis.crypto.randomUUID()\n\t\tconst currentIndex = (await context.context.get(`${this.nodeId}_currentIndex`)) || 0\n\t\tconst endIndex = Math.min(currentIndex + chunkSize, inputArray.length)\n\t\tconst dynamicNodes: any[] = []\n\t\tconst workerIds = []\n\t\tfor (let i = currentIndex; i < endIndex; i++) {\n\t\t\tconst item = inputArray[i]\n\t\t\tconst itemInputKey = `_batch.${this.nodeId}_${batchId}_item_${i}`\n\t\t\tawait context.context.set(itemInputKey as any, item)\n\t\t\tconst workerId = `${workerUsesKey}_${batchId}_${i}`\n\t\t\tworkerIds.push(workerId)\n\t\t\tdynamicNodes.push({\n\t\t\t\tid: workerId,\n\t\t\t\tuses: workerUsesKey,\n\t\t\t\tinputs: itemInputKey,\n\t\t\t})\n\t\t}\n\n\t\tconst parentBatchId = this.nodeId?.replace('_scatter', '') || ''\n\t\tawait context.dependencies.runtime.services.eventBus.emit({\n\t\t\ttype: 'batch:start',\n\t\t\tpayload: {\n\t\t\t\tbatchId: parentBatchId,\n\t\t\t\tscatterNodeId: this.nodeId,\n\t\t\t\tworkerNodeIds: workerIds,\n\t\t\t},\n\t\t})\n\n\t\tawait context.context.set(`${this.nodeId}_currentIndex`, endIndex)\n\t\tconst hasMore = endIndex < inputArray.length\n\t\tawait context.context.set(`${gatherNodeId}_hasMore`, hasMore)\n\t\tconst existingWorkerIds = (await context.context.get(`${gatherNodeId}_allWorkerIds`)) || []\n\t\tconst allWorkerIds = [...existingWorkerIds, ...workerIds]\n\t\tawait context.context.set(`${gatherNodeId}_allWorkerIds`, allWorkerIds)\n\t\treturn { dynamicNodes, output: { gatherNodeId, hasMore } }\n\t}\n}\n","import { BaseNode } from '../node'\nimport type { NodeContext, NodeResult } from '../types'\n\nexport class SleepNode extends BaseNode {\n\tasync exec(\n\t\tprepResult: any,\n\t\tcontext: NodeContext<Record<string, any>, any, any>,\n\t): Promise<Omit<NodeResult, 'error'>> {\n\t\tconst durationParam = this.params?.duration as string | number\n\n\t\tlet durationMs: number\n\t\tif (typeof durationParam === 'string') {\n\t\t\tconst match = durationParam.match(/^(\\d+)([smhd])$/)\n\t\t\tif (!match) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`SleepNode '${this.nodeId}' received an invalid duration string: '${durationParam}'. Expected format: '5m', '10s', '1h', '2d'`,\n\t\t\t\t)\n\t\t\t}\n\t\t\tconst [, numStr, unit] = match\n\t\t\tconst num = parseInt(numStr, 10)\n\t\t\tswitch (unit) {\n\t\t\t\tcase 's':\n\t\t\t\t\tdurationMs = num * 1000\n\t\t\t\t\tbreak\n\t\t\t\tcase 'm':\n\t\t\t\t\tdurationMs = num * 60 * 1000\n\t\t\t\t\tbreak\n\t\t\t\tcase 'h':\n\t\t\t\t\tdurationMs = num * 60 * 60 * 1000\n\t\t\t\t\tbreak\n\t\t\t\tcase 'd':\n\t\t\t\t\tdurationMs = num * 24 * 60 * 60 * 1000\n\t\t\t\t\tbreak\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new Error(`Invalid duration unit: ${unit}`)\n\t\t\t}\n\t\t} else if (typeof durationParam === 'number') {\n\t\t\tdurationMs = durationParam\n\t\t} else {\n\t\t\tthrow new Error(\n\t\t\t\t`SleepNode '${this.nodeId}' received an invalid duration type: ${typeof durationParam}`,\n\t\t\t)\n\t\t}\n\n\t\tif (durationMs < 0) {\n\t\t\tthrow new Error(`SleepNode '${this.nodeId}' received a negative duration.`)\n\t\t}\n\n\t\tconst wakeUpAt = new Date(Date.now() + durationMs).toISOString()\n\n\t\tawait context.dependencies.workflowState.markAsAwaiting(this.nodeId ?? '', {\n\t\t\treason: 'timer',\n\t\t\twakeUpAt,\n\t\t})\n\n\t\treturn { output: prepResult }\n\t}\n}\n","import { analyzeBlueprint } from '../analysis'\nimport { FlowcraftError } from '../errors'\nimport type { NodeDefinition, NodeResult, WorkflowBlueprint } from '../types'\nimport type { WorkflowState } from './state'\n\nexport interface ReadyNode {\n\tnodeId: string\n\tnodeDef: NodeDefinition\n}\n\nexport class GraphTraverser {\n\tprivate frontier = new Set<string>()\n\tprivate allPredecessors: Map<string, Set<string>>\n\tprivate allSuccessors: Map<string, Set<string>>\n\tprivate dynamicBlueprint: WorkflowBlueprint\n\tprivate completedNodes = new Set<string>()\n\tprivate nodesInLoops: Map<string, Set<string>>\n\n\tconstructor(blueprint: WorkflowBlueprint, isStrictMode: boolean = false) {\n\t\tthis.dynamicBlueprint = structuredClone(blueprint) as WorkflowBlueprint\n\t\tthis.allPredecessors = new Map<string, Set<string>>()\n\t\tthis.allSuccessors = new Map<string, Set<string>>()\n\t\tthis.nodesInLoops = new Map<string, Set<string>>()\n\t\tfor (const node of this.dynamicBlueprint.nodes) {\n\t\t\tthis.allPredecessors.set(node.id, new Set())\n\t\t\tthis.allSuccessors.set(node.id, new Set())\n\t\t}\n\t\tfor (const edge of this.dynamicBlueprint.edges) {\n\t\t\tthis.getPredecessors(edge.target).add(edge.source)\n\t\t}\n\t\tfor (const edge of this.dynamicBlueprint.edges) {\n\t\t\tthis.getSuccessors(edge.source).add(edge.target)\n\t\t}\n\t\tconst analysis = analyzeBlueprint(blueprint)\n\t\tthis.filterNodesInLoops(blueprint)\n\t\tthis.frontier = new Set(analysis.startNodeIds.filter((id) => !this.isFallbackNode(id)))\n\t\tif (this.frontier.size === 0 && analysis.cycles.length > 0 && !isStrictMode) {\n\t\t\tconst uniqueStartNodes = new Set<string>()\n\t\t\tconst cycleEntryPoints = new Set(blueprint.metadata?.cycleEntryPoints || [])\n\t\t\tfor (const cycle of analysis.cycles) {\n\t\t\t\tif (cycle.length > 0) {\n\t\t\t\t\tconst entryPoint = cycle.find((node) => cycleEntryPoints.has(node))\n\t\t\t\t\tuniqueStartNodes.add(entryPoint || cycle[0])\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.frontier = new Set(uniqueStartNodes)\n\t\t}\n\t}\n\n\t/**\n\t * Clears all nodes from the execution frontier.\n\t */\n\tpublic clearFrontier(): void {\n\t\tthis.frontier.clear()\n\t}\n\n\t/**\n\t * Creates and initializes a GraphTraverser from a saved workflow state.\n\t * This is the correct way to prepare a traverser for a `resume` operation.\n\t * @param blueprint The workflow blueprint.\n\t * @param state The workflow state being resumed.\n\t * @returns A configured GraphTraverser instance.\n\t */\n\tpublic static fromState(\n\t\tblueprint: WorkflowBlueprint,\n\t\tstate: WorkflowState<any>,\n\t): GraphTraverser {\n\t\tconst traverser = new GraphTraverser(blueprint)\n\n\t\t// clear auto-populated frontier from constructor\n\t\ttraverser.clearFrontier()\n\n\t\t// re-hydrate the set of completed nodes\n\t\tconst completedNodes = state.getCompletedNodes()\n\t\ttraverser.completedNodes = new Set(completedNodes)\n\n\t\t// Identify nodes whose conditional edges were already evaluated during a prior run.\n\t\t// If ALL incoming edges from completed predecessors have conditions, the routing\n\t\t// decision was already made — don't re-add them to the frontier.\n\t\t// nodes whose conditional edges were already evaluated during a prior run\n\t\tconst hasOnlyConditionalIncomingEdges = (nodeId: string): boolean => {\n\t\t\tconst incomingEdges = blueprint.edges.filter((e) => e.target === nodeId)\n\t\t\tif (incomingEdges.length === 0) return false\n\t\t\tconst fromCompletedPredecessors = incomingEdges.filter((e) =>\n\t\t\t\tcompletedNodes.has(e.source),\n\t\t\t)\n\t\t\tif (fromCompletedPredecessors.length === 0) return false\n\t\t\treturn fromCompletedPredecessors.every((e) => e.condition !== undefined)\n\t\t}\n\n\t\tfor (const node of traverser.dynamicBlueprint.nodes) {\n\t\t\tif (traverser.completedNodes.has(node.id)) continue\n\n\t\t\tif (hasOnlyConditionalIncomingEdges(node.id)) continue\n\n\t\t\tconst requiredPredecessors = traverser.allPredecessors.get(node.id)\n\t\t\tconst joinStrategy = traverser.getJoinStrategy(node.id)\n\n\t\t\t// if no predecessors and not completed, it's a start node and should be in the frontier\n\t\t\tif (!requiredPredecessors || requiredPredecessors.size === 0) {\n\t\t\t\ttraverser.frontier.add(node.id)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tconst completedPredecessors = [...requiredPredecessors].filter((p) =>\n\t\t\t\ttraverser.completedNodes.has(p),\n\t\t\t)\n\t\t\tconst isReady =\n\t\t\t\tjoinStrategy === 'any'\n\t\t\t\t\t? completedPredecessors.length > 0\n\t\t\t\t\t: completedPredecessors.length === requiredPredecessors.size\n\n\t\t\tif (isReady) traverser.frontier.add(node.id)\n\t\t}\n\n\t\treturn traverser\n\t}\n\n\tprivate isFallbackNode(nodeId: string): boolean {\n\t\treturn this.dynamicBlueprint.nodes.some((n) => n.config?.fallback === nodeId)\n\t}\n\n\tprivate getJoinStrategy(nodeId: string): 'any' | 'all' {\n\t\tconst node = this.dynamicBlueprint.nodes.find((n) => n.id === nodeId)\n\t\tconst baseJoinStrategy = node?.config?.joinStrategy || 'all'\n\t\treturn baseJoinStrategy\n\t}\n\n\tprivate filterNodesInLoops(blueprint: WorkflowBlueprint): void {\n\t\tblueprint.nodes.forEach((node) => {\n\t\t\tif (node.uses !== 'loop-controller') return\n\n\t\t\tconst nextInLoopId = blueprint.edges.find(\n\t\t\t\t(e) => e.source === node.id && e.action === 'continue',\n\t\t\t)?.target\n\t\t\tif (!nextInLoopId) {\n\t\t\t\tthrow new FlowcraftError(\n\t\t\t\t\t`Loop '${node.id}' has no continue edge to start node. ` +\n\t\t\t\t\t\t`Ensure edges are wired inside the loop and incoming/breaking edges point to the loop controller.`,\n\t\t\t\t\t{ nodeId: node.id, blueprintId: blueprint.id },\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tconst set: Set<string> = new Set()\n\t\t\tset.add(nextInLoopId)\n\t\t\tthis.nodesInLoops.set(node.id, this.getAllLoopSuccessors(nextInLoopId, blueprint, set))\n\t\t})\n\t}\n\n\tprivate getAllLoopSuccessors(\n\t\tnodeId: string,\n\t\tblueprint: WorkflowBlueprint,\n\t\tset: Set<string>,\n\t): Set<string> {\n\t\tthis.getSuccessors(nodeId).forEach((successor) => {\n\t\t\tif (set.has(successor)) return\n\t\t\tconst node = this.getNode(successor, blueprint)\n\t\t\tif (!node || node.uses === 'loop-controller') return\n\t\t\tset.add(successor)\n\t\t\tthis.getAllLoopSuccessors(successor, blueprint, set)\n\t\t})\n\t\treturn set\n\t}\n\n\tgetReadyNodes(): ReadyNode[] {\n\t\tconst readyNodes: ReadyNode[] = []\n\t\tfor (const nodeId of this.frontier) {\n\t\t\tconst nodeDef = this.dynamicBlueprint.nodes.find((n) => n.id === nodeId)\n\t\t\tif (nodeDef) {\n\t\t\t\treadyNodes.push({ nodeId, nodeDef })\n\t\t\t}\n\t\t}\n\t\tthis.frontier.clear()\n\t\treturn readyNodes\n\t}\n\n\thasMoreWork(): boolean {\n\t\treturn this.frontier.size > 0\n\t}\n\n\tmarkNodeCompleted(\n\t\tnodeId: string,\n\t\tresult: NodeResult<any, any>,\n\t\tnextNodes: NodeDefinition[],\n\t): void {\n\t\tthis.completedNodes.add(nodeId)\n\n\t\tif (result?.dynamicNodes && result.dynamicNodes.length > 0) {\n\t\t\tconst gatherNodeId = result.output?.gatherNodeId\n\t\t\tfor (const dynamicNode of result.dynamicNodes) {\n\t\t\t\tthis.dynamicBlueprint.nodes.push(dynamicNode)\n\t\t\t\tthis.allPredecessors.set(dynamicNode.id, new Set([nodeId]))\n\t\t\t\tif (gatherNodeId) {\n\t\t\t\t\tthis.getPredecessors(gatherNodeId).add(dynamicNode.id)\n\t\t\t\t}\n\t\t\t\tthis.frontier.add(dynamicNode.id)\n\t\t\t}\n\t\t}\n\n\t\tfor (const node of nextNodes) {\n\t\t\tconst joinStrategy = this.getJoinStrategy(node.id)\n\t\t\tif (joinStrategy !== 'any' && this.completedNodes.has(node.id)) continue\n\n\t\t\tconst requiredPredecessors = this.getPredecessors(node.id)\n\n\t\t\tconst isReady =\n\t\t\t\tjoinStrategy === 'any'\n\t\t\t\t\t? requiredPredecessors.has(nodeId)\n\t\t\t\t\t: [...requiredPredecessors].every((p) => this.completedNodes.has(p))\n\n\t\t\tif (isReady) {\n\t\t\t\tthis.frontier.add(node.id)\n\t\t\t\t// reset to uncompleted for all nodes in a loop\n\t\t\t\tif (node.uses === 'loop-controller') {\n\t\t\t\t\tthis.getNodesInLoop(node.id).forEach((id) => {\n\t\t\t\t\t\tthis.resetNodeCompletion(id)\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (nextNodes.length === 0) {\n\t\t\tfor (const [potentialNextId, predecessors] of this.allPredecessors) {\n\t\t\t\tif (predecessors.has(nodeId) && !this.completedNodes.has(potentialNextId)) {\n\t\t\t\t\tconst hasConditionalIncomingEdge = this.dynamicBlueprint.edges.some(\n\t\t\t\t\t\t(e) => e.target === potentialNextId && e.condition,\n\t\t\t\t\t)\n\t\t\t\t\tif (hasConditionalIncomingEdge) continue\n\n\t\t\t\t\tconst joinStrategy = this.getJoinStrategy(potentialNextId)\n\t\t\t\t\tconst isReady =\n\t\t\t\t\t\tjoinStrategy === 'any'\n\t\t\t\t\t\t\t? predecessors.has(nodeId)\n\t\t\t\t\t\t\t: [...predecessors].every((p) => this.completedNodes.has(p))\n\t\t\t\t\tif (isReady) {\n\t\t\t\t\t\tthis.frontier.add(potentialNextId)\n\t\t\t\t\t\tconst node = this.getNode(potentialNextId, this.dynamicBlueprint)\n\t\t\t\t\t\tif (!node) continue\n\t\t\t\t\t\t// reset to uncompleted for all nodes in a loop\n\t\t\t\t\t\tif (node.uses === 'loop-controller') {\n\t\t\t\t\t\t\tthis.getNodesInLoop(node.id).forEach((id) => {\n\t\t\t\t\t\t\t\tthis.resetNodeCompletion(id)\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tgetAllNodeIds(): Set<string> {\n\t\treturn new Set(this.dynamicBlueprint.nodes.map((n) => n.id))\n\t}\n\n\tgetFallbackNodeIds(): Set<string> {\n\t\tconst fallbackNodeIds = new Set<string>()\n\t\tfor (const node of this.dynamicBlueprint.nodes) {\n\t\t\tif (node.config?.fallback) fallbackNodeIds.add(node.config.fallback)\n\t\t}\n\t\treturn fallbackNodeIds\n\t}\n\n\tgetCompletedNodes(): Set<string> {\n\t\treturn new Set(this.completedNodes)\n\t}\n\n\tgetDynamicBlueprint(): WorkflowBlueprint {\n\t\treturn this.dynamicBlueprint\n\t}\n\n\tgetAllPredecessors(): Map<string, Set<string>> {\n\t\treturn this.allPredecessors\n\t}\n\n\tgetAllSuccessors(): Map<string, Set<string>> {\n\t\treturn this.allSuccessors\n\t}\n\n\tgetPredecessors(nodeId: string): Set<string> {\n\t\tconst predecessors = this.allPredecessors.get(nodeId)\n\t\tif (!predecessors) return new Set()\n\t\treturn predecessors\n\t}\n\n\tgetSuccessors(nodeId: string): Set<string> {\n\t\tconst successors = this.allSuccessors.get(nodeId)\n\t\tif (!successors) return new Set()\n\t\treturn successors\n\t}\n\n\tgetNodesInLoop(id: string): Set<string> {\n\t\tconst loopNodes = this.nodesInLoops.get(id)\n\t\tif (!loopNodes) return new Set()\n\t\treturn loopNodes\n\t}\n\n\tresetNodeCompletion(nodeId: string): void {\n\t\tthis.completedNodes.delete(nodeId)\n\t}\n\n\tgetNode(nodeId: string, blueprint: WorkflowBlueprint): NodeDefinition | undefined {\n\t\treturn blueprint.nodes.find((n) => n.id === nodeId)\n\t}\n\n\taddDynamicNode(\n\t\t_nodeId: string,\n\t\tdynamicNode: NodeDefinition,\n\t\tpredecessorId: string,\n\t\tgatherNodeId?: string,\n\t): void {\n\t\tthis.dynamicBlueprint.nodes.push(dynamicNode)\n\t\tthis.allPredecessors.set(dynamicNode.id, new Set([predecessorId]))\n\t\tif (gatherNodeId) {\n\t\t\tthis.allPredecessors.get(gatherNodeId)?.add(dynamicNode.id)\n\t\t}\n\t\tthis.frontier.add(dynamicNode.id)\n\t}\n\n\t/**\n\t * Manually adds a node ID back to the execution frontier.\n\t * Used by orchestrators that need fine-grained control over steps.\n\t * @param nodeId The ID of the node to add to the frontier.\n\t */\n\tpublic addToFrontier(nodeId: string): void {\n\t\tthis.frontier.add(nodeId)\n\t}\n}\n","import { analyzeBlueprint } from '../analysis'\nimport { FlowcraftError } from '../errors'\nimport { BaseNode } from '../node'\nimport { ExecutionContext } from '../runtime/execution-context'\nimport { WorkflowState } from '../runtime/state'\nimport { GraphTraverser } from '../runtime/traverser'\nimport type { NodeContext, NodeResult } from '../types'\n\nexport class SubflowNode extends BaseNode {\n\tasync exec(\n\t\t_prepResult: any,\n\t\tcontext: NodeContext<Record<string, any>, any, any>,\n\t): Promise<Omit<NodeResult, 'error'>> {\n\t\tconst { blueprintId, inputs, outputs } = this.params ?? {}\n\t\tconst { runtime, workflowState } = context.dependencies\n\n\t\tif (!blueprintId) {\n\t\t\tthrow new FlowcraftError(\n\t\t\t\t`Subflow node '${this.nodeId}' is missing 'blueprintId' parameter.`,\n\t\t\t\t{ isFatal: true },\n\t\t\t)\n\t\t}\n\n\t\tconst subBlueprint =\n\t\t\t(runtime as any).blueprints?.[blueprintId] ||\n\t\t\t(runtime as any).runtime?.blueprints?.[blueprintId]\n\t\tif (!subBlueprint) {\n\t\t\tthrow new FlowcraftError(\n\t\t\t\t`Sub-blueprint '${blueprintId}' not found in runtime registry.`,\n\t\t\t\t{ isFatal: true },\n\t\t\t)\n\t\t}\n\n\t\tconst subflowInitialContext: Record<string, any> = {}\n\n\t\tif (inputs) {\n\t\t\t// explicit inputs\n\t\t\tfor (const [targetKey, sourceKey] of Object.entries(inputs as Record<string, string>)) {\n\t\t\t\tlet value = await context.context.get(sourceKey as any)\n\t\t\t\tif (value === undefined) {\n\t\t\t\t\tvalue = await context.context.get(`_outputs.${sourceKey}` as any)\n\t\t\t\t}\n\t\t\t\tsubflowInitialContext[targetKey] = value\n\t\t\t}\n\t\t} else if (context.input !== undefined) {\n\t\t\t// pass the parent node's input to the subflow's start nodes\n\t\t\tconst subAnalysis = analyzeBlueprint(subBlueprint)\n\t\t\tfor (const startNodeId of subAnalysis.startNodeIds) {\n\t\t\t\tconst inputKey = `_inputs.${startNodeId}`\n\t\t\t\tsubflowInitialContext[inputKey] = context.input\n\t\t\t}\n\t\t}\n\n\t\tconst subflowState = new WorkflowState(subflowInitialContext)\n\t\tconst subflowExecContext = new ExecutionContext(\n\t\t\tsubBlueprint,\n\t\t\tsubflowState,\n\t\t\truntime.nodeRegistry,\n\t\t\truntime.executionId,\n\t\t\truntime.runtime,\n\t\t\truntime.services,\n\t\t\truntime.signal,\n\t\t\truntime.concurrency,\n\t\t)\n\t\tconst subflowTraverser = new GraphTraverser(subBlueprint)\n\n\t\tconst subflowResult = await runtime.runtime.orchestrator.run(\n\t\t\tsubflowExecContext,\n\t\t\tsubflowTraverser,\n\t\t)\n\n\t\tif (subflowResult.status === 'awaiting') {\n\t\t\tawait workflowState.markAsAwaiting(this.nodeId ?? '')\n\t\t\tconst subflowStateKey = `_subflowState.${this.nodeId}`\n\t\t\tawait context.context.set(subflowStateKey as any, subflowResult.serializedContext)\n\t\t\treturn { output: undefined }\n\t\t}\n\n\t\tif (subflowResult.status !== 'completed') {\n\t\t\tconst firstError = subflowResult.errors?.[0]\n\t\t\tconst errorMessage = firstError?.message || 'Unknown error'\n\t\t\tthrow new FlowcraftError(\n\t\t\t\t`Sub-workflow '${blueprintId}' did not complete successfully. Status: ${subflowResult.status}. Error: ${errorMessage}`,\n\t\t\t\t{\n\t\t\t\t\tcause: firstError,\n\t\t\t\t\tnodeId: this.nodeId,\n\t\t\t\t\tblueprintId,\n\t\t\t\t},\n\t\t\t)\n\t\t}\n\n\t\tconst subflowFinalContext = subflowResult.context as Record<string, any>\n\n\t\tif (outputs) {\n\t\t\tfor (const [parentKey, subKey] of Object.entries(outputs as Record<string, string>)) {\n\t\t\t\tconst value =\n\t\t\t\t\tsubflowFinalContext[`_outputs.${subKey}`] ?? subflowFinalContext[subKey]\n\t\t\t\tawait context.context.set(parentKey as any, value)\n\t\t\t}\n\t\t\treturn { output: subflowFinalContext }\n\t\t}\n\n\t\tconst subAnalysis = analyzeBlueprint(subBlueprint)\n\t\tif (subAnalysis.terminalNodeIds.length === 1) {\n\t\t\tconst terminalId = subAnalysis.terminalNodeIds[0]\n\t\t\treturn { output: subflowFinalContext[`_outputs.${terminalId}`] }\n\t\t}\n\n\t\tconst terminalOutputs: Record<string, any> = {}\n\t\tfor (const terminalId of subAnalysis.terminalNodeIds) {\n\t\t\tterminalOutputs[terminalId] = subflowFinalContext[`_outputs.${terminalId}`]\n\t\t}\n\t\treturn { output: terminalOutputs }\n\t}\n}\n","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\tawait context.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","import { BaseNode } from '../node'\nimport type { Webhook } from '../sdk'\nimport type { NodeContext, NodeResult } from '../types'\n\nexport class WebhookNode extends BaseNode {\n\tasync prep(context: NodeContext<Record<string, any>, any, any>): Promise<any> {\n\t\tconst runId = context.dependencies.runtime.executionId\n\t\tconst nodeId = this.nodeId ?? ''\n\t\tconst adapter = (context.dependencies as any).adapter\n\t\tconst { url, event } = await adapter.registerWebhookEndpoint(runId, nodeId)\n\t\treturn { url, event }\n\t}\n\n\tasync exec(\n\t\tprepResult: { url: string; event: string },\n\t\t_context: NodeContext<Record<string, any>, any, any>,\n\t): Promise<Omit<NodeResult, 'error'>> {\n\t\tconst webhook: Webhook = {\n\t\t\turl: prepResult.url,\n\t\t\tevent: prepResult.event,\n\t\t\trequest: new Promise(() => {}), // will be resolved by the wait node\n\t\t}\n\n\t\treturn { output: webhook }\n\t}\n}\n","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\tlet nodesArray: any[] = []\n\tif (Array.isArray(raw.nodes)) {\n\t\tnodesArray = raw.nodes\n\t} else if (typeof raw.nodes === 'object' && raw.nodes !== null) {\n\t\tnodesArray = Object.values(raw.nodes)\n\t}\n\n\tconst nodes: NodeDefinition[] = nodesArray.map((node: any) => ({\n\t\tid: node.id,\n\t\tuses: node.uses,\n\t\tparams: node.params,\n\t\tinputs: node.inputs,\n\t\tconfig: node.config,\n\t}))\n\n\tlet edgesArray: any[] = []\n\tif (Array.isArray(raw.edges)) {\n\t\tedgesArray = raw.edges\n\t} else if (typeof raw.edges === 'object' && raw.edges !== null) {\n\t\tedgesArray = Object.values(raw.edges)\n\t}\n\n\tconst edges: EdgeDefinition[] = edgesArray.map((edge: any) => ({\n\t\tsource: edge.source,\n\t\ttarget: edge.target,\n\t\taction: edge.action,\n\t\tcondition: edge.condition,\n\t\ttransform: edge.transform,\n\t}))\n\n\treturn {\n\t\tid: raw.id,\n\t\tnodes,\n\t\tedges,\n\t\tmetadata: raw.metadata,\n\t}\n}\n","import { FlowcraftError } from '../errors'\nimport type {\n\tIEventBus,\n\tMiddleware,\n\tNodeClass,\n\tNodeContext,\n\tNodeDefinition,\n\tNodeFunction,\n\tNodeResult,\n} from '../types'\nimport type { ExecutionContext } from './execution-context'\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 FlowcraftError('Workflow cancelled', {\n\t\t\t\t\tisFatal: false,\n\t\t\t\t})\n\t\t\t}\n\t\t\tif (error instanceof FlowcraftError && error.isFatal) 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({\n\t\t\t\t\t\ttype: 'node:retry',\n\t\t\t\t\t\tpayload: {\n\t\t\t\t\t\t\tnodeId: nodeDef.id,\n\t\t\t\t\t\t\tattempt,\n\t\t\t\t\t\t\texecutionId: executionId || '',\n\t\t\t\t\t\t\tblueprintId: context.dependencies.blueprint?.id || '',\n\t\t\t\t\t\t},\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 || {}, nodeDef.id)\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 FlowcraftError('Workflow cancelled', {\n\t\t\t\t\t\tisFatal: false,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tif (error instanceof FlowcraftError && error.isFatal) {\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 FlowcraftError('Workflow cancelled', {\n\t\t\t\t\tisFatal: false,\n\t\t\t\t})\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:\n\t\t\t\t\t\t\trecoverError instanceof Error\n\t\t\t\t\t\t\t\t? recoverError.message\n\t\t\t\t\t\t\t\t: 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 type NodeExecutionResult =\n\t| { status: 'success'; result: NodeResult<any, any> }\n\t| { status: 'failed_with_fallback'; fallbackNodeId: string; error: FlowcraftError }\n\t| { status: 'failed'; error: FlowcraftError }\n\nexport interface NodeExecutorConfig<\n\tTContext extends Record<string, any>,\n\tTDependencies extends Record<string, any>,\n> {\n\tcontext: ExecutionContext<TContext, TDependencies>\n\tnodeDef: NodeDefinition\n\tstrategy: ExecutionStrategy\n}\n\nexport class NodeExecutor<\n\tTContext extends Record<string, any>,\n\tTDependencies extends Record<string, any>,\n> {\n\tprivate context: ExecutionContext<TContext, TDependencies>\n\tprivate nodeDef: NodeDefinition\n\tprivate strategy: ExecutionStrategy\n\n\tconstructor(config: NodeExecutorConfig<TContext, TDependencies>) {\n\t\tthis.context = config.context\n\t\tthis.nodeDef = config.nodeDef\n\t\tthis.strategy = config.strategy\n\t}\n\n\tasync execute(input: any): Promise<NodeExecutionResult> {\n\t\tconst asyncContext = this.context.state.getContext()\n\n\t\tconst nodeContext: NodeContext<TContext, TDependencies, any> = {\n\t\t\tcontext: asyncContext,\n\t\t\tinput,\n\t\t\tparams: this.nodeDef.params || {},\n\t\t\tdependencies: {\n\t\t\t\t...this.context.services.dependencies,\n\t\t\t\tlogger: this.context.services.logger,\n\t\t\t\truntime: this.context,\n\t\t\t\tworkflowState: this.context.state,\n\t\t\t},\n\t\t\tsignal: this.context.signal,\n\t\t}\n\n\t\tconst beforeHooks = this.context.services.middleware\n\t\t\t.map((m) => m.beforeNode)\n\t\t\t.filter((hook): hook is NonNullable<Middleware['beforeNode']> => !!hook)\n\t\tconst afterHooks = this.context.services.middleware\n\t\t\t.map((m) => m.afterNode)\n\t\t\t.filter((hook): hook is NonNullable<Middleware['afterNode']> => !!hook)\n\t\tconst aroundHooks = this.context.services.middleware\n\t\t\t.map((m) => m.aroundNode)\n\t\t\t.filter((hook): hook is NonNullable<Middleware['aroundNode']> => !!hook)\n\n\t\tconst coreExecution = async (): Promise<NodeExecutionResult> => {\n\t\t\tlet result: NodeResult | undefined\n\t\t\tlet error: Error | undefined\n\t\t\ttry {\n\t\t\t\tfor (const hook of beforeHooks) await hook(nodeContext.context, this.nodeDef.id)\n\t\t\t\tresult = await this.strategy.execute(\n\t\t\t\t\tthis.nodeDef,\n\t\t\t\t\tnodeContext,\n\t\t\t\t\tthis.context.executionId,\n\t\t\t\t\tthis.context.signal,\n\t\t\t\t)\n\t\t\t\treturn { status: 'success', result }\n\t\t\t} catch (e: any) {\n\t\t\t\terror = e instanceof Error ? e : new Error(String(e))\n\t\t\t\tconst flowcraftError =\n\t\t\t\t\terror instanceof FlowcraftError\n\t\t\t\t\t\t? error\n\t\t\t\t\t\t: new FlowcraftError(`Node '${this.nodeDef.id}' execution failed`, {\n\t\t\t\t\t\t\t\tcause: error,\n\t\t\t\t\t\t\t\tnodeId: this.nodeDef.id,\n\t\t\t\t\t\t\t\tblueprintId: this.context.blueprint.id,\n\t\t\t\t\t\t\t\texecutionId: this.context.executionId,\n\t\t\t\t\t\t\t\tisFatal: false,\n\t\t\t\t\t\t\t})\n\n\t\t\t\tconst fallbackNodeId = this.nodeDef.config?.fallback\n\t\t\t\tif (fallbackNodeId && !flowcraftError.isFatal) {\n\t\t\t\t\tthis.context.services.logger.warn(`Node failed, fallback required`, {\n\t\t\t\t\t\tnodeId: this.nodeDef.id,\n\t\t\t\t\t\tfallbackNodeId,\n\t\t\t\t\t\terror: error.message,\n\t\t\t\t\t\texecutionId: this.context.executionId,\n\t\t\t\t\t})\n\t\t\t\t\tawait this.context.services.eventBus.emit({\n\t\t\t\t\t\ttype: 'node:fallback',\n\t\t\t\t\t\tpayload: {\n\t\t\t\t\t\t\tnodeId: this.nodeDef.id,\n\t\t\t\t\t\t\texecutionId: this.context.executionId || '',\n\t\t\t\t\t\t\tfallback: fallbackNodeId,\n\t\t\t\t\t\t\tblueprintId: this.context.blueprint.id,\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 'failed_with_fallback',\n\t\t\t\t\t\tfallbackNodeId,\n\t\t\t\t\t\terror: flowcraftError,\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn { status: 'failed', error: flowcraftError }\n\t\t\t} finally {\n\t\t\t\tfor (const hook of afterHooks)\n\t\t\t\t\tawait hook(nodeContext.context, this.nodeDef.id, result, error)\n\t\t\t}\n\t\t}\n\n\t\tlet executionChain: () => Promise<NodeExecutionResult> = coreExecution\n\t\tfor (let i = aroundHooks.length - 1; i >= 0; i--) {\n\t\t\tconst hook = aroundHooks[i]\n\t\t\tconst next = executionChain\n\t\t\texecutionChain = async () => {\n\t\t\t\tlet capturedResult: NodeExecutionResult | undefined\n\t\t\t\tconst middlewareResult = await hook(\n\t\t\t\t\tnodeContext.context,\n\t\t\t\t\tthis.nodeDef.id,\n\t\t\t\t\tasync () => {\n\t\t\t\t\t\tcapturedResult = await next()\n\t\t\t\t\t\tif (capturedResult.status === 'success') {\n\t\t\t\t\t\t\treturn capturedResult.result\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow capturedResult.error\n\t\t\t\t\t},\n\t\t\t\t)\n\t\t\t\tif (!capturedResult && middlewareResult) {\n\t\t\t\t\treturn { status: 'success', result: middlewareResult }\n\t\t\t\t}\n\t\t\t\tif (!capturedResult) {\n\t\t\t\t\tthrow new Error('Middleware did not call next() and did not return a result')\n\t\t\t\t}\n\t\t\t\treturn capturedResult\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\tawait this.context.services.eventBus.emit({\n\t\t\t\ttype: 'node:start',\n\t\t\t\tpayload: {\n\t\t\t\t\tnodeId: this.nodeDef.id,\n\t\t\t\t\texecutionId: this.context.executionId || '',\n\t\t\t\t\tinput: nodeContext.input,\n\t\t\t\t\tblueprintId: this.context.blueprint.id,\n\t\t\t\t},\n\t\t\t})\n\t\t\tconst executionResult = await executionChain()\n\t\t\tif (executionResult.status === 'success') {\n\t\t\t\tawait this.context.services.eventBus.emit({\n\t\t\t\t\ttype: 'node:finish',\n\t\t\t\t\tpayload: {\n\t\t\t\t\t\tnodeId: this.nodeDef.id,\n\t\t\t\t\t\tresult: executionResult.result,\n\t\t\t\t\t\texecutionId: this.context.executionId || '',\n\t\t\t\t\t\tblueprintId: this.context.blueprint.id,\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\tawait this.context.services.eventBus.emit({\n\t\t\t\t\ttype: 'node:error',\n\t\t\t\t\tpayload: {\n\t\t\t\t\t\tnodeId: this.nodeDef.id,\n\t\t\t\t\t\terror: executionResult.error,\n\t\t\t\t\t\texecutionId: this.context.executionId || '',\n\t\t\t\t\t\tblueprintId: this.context.blueprint.id,\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t}\n\t\t\treturn executionResult\n\t\t} catch (error: any) {\n\t\t\tconst err = error instanceof Error ? error : new Error(String(error))\n\t\t\tconst flowcraftError =\n\t\t\t\terr instanceof FlowcraftError\n\t\t\t\t\t? err\n\t\t\t\t\t: new FlowcraftError(`Node '${this.nodeDef.id}' failed execution.`, {\n\t\t\t\t\t\t\tcause: err,\n\t\t\t\t\t\t\tnodeId: this.nodeDef.id,\n\t\t\t\t\t\t\tblueprintId: this.context.blueprint.id,\n\t\t\t\t\t\t\texecutionId: this.context.executionId,\n\t\t\t\t\t\t\tisFatal: false,\n\t\t\t\t\t\t})\n\t\t\tawait this.context.services.eventBus.emit({\n\t\t\t\ttype: 'node:error',\n\t\t\t\tpayload: {\n\t\t\t\t\tnodeId: this.nodeDef.id,\n\t\t\t\t\terror: flowcraftError,\n\t\t\t\t\texecutionId: this.context.executionId || '',\n\t\t\t\t\tblueprintId: this.context.blueprint.id,\n\t\t\t\t},\n\t\t\t})\n\t\t\tif (error instanceof DOMException && error.name === 'AbortError') {\n\t\t\t\tthrow new FlowcraftError('Workflow cancelled', {\n\t\t\t\t\texecutionId: this.context.executionId,\n\t\t\t\t\tisFatal: false,\n\t\t\t\t})\n\t\t\t}\n\t\t\tthrow error instanceof FlowcraftError && !error.isFatal\n\t\t\t\t? error\n\t\t\t\t: new FlowcraftError(`Node '${this.nodeDef.id}' failed execution.`, {\n\t\t\t\t\t\tcause: error,\n\t\t\t\t\t\tnodeId: this.nodeDef.id,\n\t\t\t\t\t\tblueprintId: this.context.blueprint.id,\n\t\t\t\t\t\texecutionId: this.context.executionId,\n\t\t\t\t\t\tisFatal: false,\n\t\t\t\t\t})\n\t\t}\n\t}\n}\n","import { FlowcraftError } from '../errors'\nimport { isNodeClass } from '../node'\nimport type { IEventBus, NodeClass, NodeDefinition, NodeFunction } from '../types'\nimport type { ExecutionContext } from './execution-context'\nimport type { ExecutionStrategy } from './executors'\nimport { ClassNodeExecutor, FunctionNodeExecutor, NodeExecutor } from './executors'\n\nexport class NodeExecutorFactory {\n\tconstructor(private readonly eventBus: IEventBus) {}\n\n\tpublic createExecutorForNode(\n\t\tnodeId: string,\n\t\tcontext: ExecutionContext<any, any>,\n\t): NodeExecutor<any, any> {\n\t\tconst nodeDef = context.blueprint.nodes.find((n) => n.id === nodeId)\n\t\tif (!nodeDef) {\n\t\t\tthrow new FlowcraftError(`Node '${nodeId}' not found in blueprint.`, {\n\t\t\t\tnodeId,\n\t\t\t\tblueprintId: context.blueprint.id,\n\t\t\t\texecutionId: context.executionId,\n\t\t\t\tisFatal: false,\n\t\t\t})\n\t\t}\n\n\t\tconst strategy = this.getExecutionStrategy(nodeDef, context.nodeRegistry)\n\n\t\treturn new NodeExecutor({ context, nodeDef, strategy })\n\t}\n\n\tprivate getExecutionStrategy(\n\t\tnodeDef: NodeDefinition,\n\t\tnodeRegistry: Map<string, NodeFunction | NodeClass>,\n\t): ExecutionStrategy {\n\t\tconst implementation = nodeRegistry.get(nodeDef.uses)\n\t\tif (!implementation) {\n\t\t\tthrow new FlowcraftError(`Implementation for '${nodeDef.uses}' not found.`, {\n\t\t\t\tnodeId: nodeDef.id,\n\t\t\t\tblueprintId: '',\n\t\t\t\tisFatal: true,\n\t\t\t})\n\t\t}\n\n\t\tconst maxRetries = nodeDef.config?.maxRetries ?? 1\n\t\treturn isNodeClass(implementation)\n\t\t\t? new ClassNodeExecutor(implementation, maxRetries, this.eventBus)\n\t\t\t: new FunctionNodeExecutor(implementation, maxRetries, this.eventBus)\n\t}\n}\n","import type { WorkflowResult } from '../types'\nimport type { FlowRuntime } from './runtime'\n\nexport interface AwaitingWorkflow {\n\texecutionId: string\n\tblueprintId: string\n\tserializedContext: string\n\tawaitingNodeId: string\n\twakeUpAt: string\n\tfunctionRegistry?: Map<string, any>\n}\n\nexport class WorkflowScheduler {\n\tprivate runtime: FlowRuntime<any, any>\n\tprivate activeWorkflows: Map<string, AwaitingWorkflow> = new Map()\n\tprivate resumeResults: Map<string, WorkflowResult> = new Map()\n\tprivate intervalId?: NodeJS.Timeout\n\tprivate checkIntervalMs: number\n\n\tconstructor(runtime: FlowRuntime<any, any>, checkIntervalMs: number = 1000) {\n\t\tthis.runtime = runtime\n\t\tthis.checkIntervalMs = checkIntervalMs\n\t}\n\n\tstart(): void {\n\t\tif (this.intervalId) return\n\n\t\tthis.intervalId = setInterval(() => {\n\t\t\tthis.checkAndResumeWorkflows()\n\t\t}, this.checkIntervalMs)\n\t}\n\n\tstop(): void {\n\t\tif (this.intervalId) {\n\t\t\tclearInterval(this.intervalId)\n\t\t\tthis.intervalId = undefined\n\t\t}\n\t}\n\n\tregisterAwaitingWorkflow(\n\t\texecutionId: string,\n\t\tblueprintId: string,\n\t\tserializedContext: string,\n\t\tawaitingNodeId: string,\n\t\twakeUpAt: string,\n\t\tfunctionRegistry?: Map<string, any>,\n\t): void {\n\t\tthis.activeWorkflows.set(executionId, {\n\t\t\texecutionId,\n\t\t\tblueprintId,\n\t\t\tserializedContext,\n\t\t\tawaitingNodeId,\n\t\t\twakeUpAt,\n\t\t\tfunctionRegistry,\n\t\t})\n\t}\n\n\tunregisterWorkflow(executionId: string): void {\n\t\tthis.activeWorkflows.delete(executionId)\n\t}\n\n\tprivate async checkAndResumeWorkflows(): Promise<void> {\n\t\tconst now = new Date()\n\t\tconst toResume: AwaitingWorkflow[] = []\n\n\t\tfor (const [_executionId, workflow] of this.activeWorkflows) {\n\t\t\tconst wakeUpTime = new Date(workflow.wakeUpAt)\n\t\t\tif (wakeUpTime <= now) {\n\t\t\t\ttoResume.push(workflow)\n\t\t\t}\n\t\t}\n\n\t\tfor (const workflow of toResume) {\n\t\t\ttry {\n\t\t\t\tconst blueprint = this.runtime.getBlueprint(workflow.blueprintId)\n\t\t\t\tif (!blueprint) {\n\t\t\t\t\tconsole.warn(`Blueprint ${workflow.blueprintId} not found, skipping resumption`)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tconst result = await this.runtime.resume(\n\t\t\t\t\tblueprint,\n\t\t\t\t\tworkflow.serializedContext,\n\t\t\t\t\t{ output: undefined },\n\t\t\t\t\tworkflow.awaitingNodeId,\n\t\t\t\t\t{ functionRegistry: workflow.functionRegistry },\n\t\t\t\t)\n\n\t\t\t\tthis.resumeResults.set(workflow.executionId, result)\n\n\t\t\t\tif (result.status === 'completed' || result.status === 'failed') {\n\t\t\t\t\tthis.unregisterWorkflow(workflow.executionId)\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(`Failed to resume workflow ${workflow.executionId}:`, error)\n\t\t\t\tthis.unregisterWorkflow(workflow.executionId)\n\t\t\t}\n\t\t}\n\t}\n\n\tgetActiveWorkflows(): AwaitingWorkflow[] {\n\t\treturn Array.from(this.activeWorkflows.values())\n\t}\n\n\tgetResumeResult(executionId: string): WorkflowResult | undefined {\n\t\treturn this.resumeResults.get(executionId)\n\t}\n}\n","import { AsyncContextView } from '../context'\nimport { FlowcraftError } from '../errors'\nimport type {\n\tContextImplementation,\n\tEdgeDefinition,\n\tIEvaluator,\n\tIEventBus,\n\tNodeDefinition,\n\tNodeResult,\n\tWorkflowBlueprint,\n} from '../types'\n\nexport class WorkflowLogicHandler {\n\tconstructor(\n\t\tprivate readonly evaluator: IEvaluator,\n\t\tprivate readonly eventBus: IEventBus,\n\t) {}\n\n\tpublic async determineNextNodes(\n\t\tblueprint: WorkflowBlueprint,\n\t\tcompletedNodeId: string,\n\t\tresult: NodeResult<any, any>,\n\t\tcontext: ContextImplementation<any>,\n\t\texecutionId?: string,\n\t): Promise<{ node: NodeDefinition; edge: EdgeDefinition }[]> {\n\t\tif (!result) return []\n\n\t\tconst effectiveSourceNodeId = completedNodeId\n\n\t\tconst directOutgoingEdges = blueprint.edges.filter(\n\t\t\t(edge) => edge.source === effectiveSourceNodeId,\n\t\t)\n\n\t\tconst nodesThisIsAFallbackFor = blueprint.nodes.filter(\n\t\t\t(n) => n.config?.fallback === completedNodeId,\n\t\t)\n\t\tconst inheritedOutgoingEdges = nodesThisIsAFallbackFor.flatMap((originalNode) =>\n\t\t\tblueprint.edges.filter((edge) => edge.source === originalNode.id),\n\t\t)\n\t\tconst allPossibleEdges = [...directOutgoingEdges, ...inheritedOutgoingEdges]\n\t\tconst outgoingEdges = [\n\t\t\t...new Map(\n\t\t\t\tallPossibleEdges.map((edge) => [\n\t\t\t\t\t`${edge.source}-${edge.target}-${edge.action || ''}-${edge.condition || ''}`,\n\t\t\t\t\tedge,\n\t\t\t\t]),\n\t\t\t).values(),\n\t\t]\n\n\t\tconst matched: { node: NodeDefinition; edge: EdgeDefinition }[] = []\n\t\tconst evaluateEdge = async (edge: EdgeDefinition): Promise<boolean> => {\n\t\t\tif (!edge.condition) return true\n\t\t\tconst contextData = context.type === 'sync' ? context.toJSON() : await context.toJSON()\n\t\t\tconst evaluationResult = !!this.evaluator.evaluate(edge.condition, {\n\t\t\t\t...contextData,\n\t\t\t\tresult,\n\t\t\t})\n\t\t\tawait this.eventBus.emit({\n\t\t\t\ttype: 'edge:evaluate',\n\t\t\t\tpayload: {\n\t\t\t\t\tsource: edge.source,\n\t\t\t\t\ttarget: edge.target,\n\t\t\t\t\tcondition: edge.condition,\n\t\t\t\t\tresult: evaluationResult,\n\t\t\t\t},\n\t\t\t})\n\t\t\treturn evaluationResult\n\t\t}\n\n\t\tconst completedNode = blueprint.nodes.find((n) => n.id === completedNodeId)\n\t\tconst isLoopController = completedNode?.uses === 'loop-controller'\n\n\t\tif (isLoopController) {\n\t\t\tconst conditionalEdges = outgoingEdges.filter((edge) => edge.condition)\n\t\t\tfor (const edge of conditionalEdges) {\n\t\t\t\tif (await evaluateEdge(edge)) {\n\t\t\t\t\tconst targetNode = blueprint.nodes.find((n) => n.id === edge.target)\n\t\t\t\t\tif (targetNode) matched.push({ node: targetNode, edge })\n\t\t\t\t} else {\n\t\t\t\t\tawait this.eventBus.emit({\n\t\t\t\t\t\ttype: 'node:skipped',\n\t\t\t\t\t\tpayload: {\n\t\t\t\t\t\t\tnodeId: completedNodeId,\n\t\t\t\t\t\t\tedge,\n\t\t\t\t\t\t\texecutionId: executionId || '',\n\t\t\t\t\t\t\tblueprintId: blueprint.id,\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (matched.length > 0) {\n\t\t\t\treturn matched\n\t\t\t}\n\t\t}\n\n\t\tif (result.action) {\n\t\t\tconst actionEdges = outgoingEdges.filter((edge) => edge.action === result.action)\n\t\t\tfor (const edge of actionEdges) {\n\t\t\t\tif (await evaluateEdge(edge)) {\n\t\t\t\t\tconst targetNode = blueprint.nodes.find((n) => n.id === edge.target)\n\t\t\t\t\tif (targetNode) matched.push({ node: targetNode, edge })\n\t\t\t\t} else {\n\t\t\t\t\tawait this.eventBus.emit({\n\t\t\t\t\t\ttype: 'node:skipped',\n\t\t\t\t\t\tpayload: {\n\t\t\t\t\t\t\tnodeId: completedNodeId,\n\t\t\t\t\t\t\tedge,\n\t\t\t\t\t\t\texecutionId: executionId || '',\n\t\t\t\t\t\t\tblueprintId: blueprint.id,\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (matched.length === 0) {\n\t\t\tconst defaultEdges = outgoingEdges.filter((edge) => !edge.action)\n\t\t\tfor (const edge of defaultEdges) {\n\t\t\t\tif (await evaluateEdge(edge)) {\n\t\t\t\t\tconst targetNode = blueprint.nodes.find((n) => n.id === edge.target)\n\t\t\t\t\tif (targetNode) matched.push({ node: targetNode, edge })\n\t\t\t\t} else {\n\t\t\t\t\tawait this.eventBus.emit({\n\t\t\t\t\t\ttype: 'node:skipped',\n\t\t\t\t\t\tpayload: {\n\t\t\t\t\t\t\tnodeId: completedNodeId,\n\t\t\t\t\t\t\tedge,\n\t\t\t\t\t\t\texecutionId: executionId || '',\n\t\t\t\t\t\t\tblueprintId: blueprint.id,\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn matched\n\t}\n\n\tpublic async applyEdgeTransform(\n\t\tedge: EdgeDefinition,\n\t\tsourceResult: NodeResult<any, any>,\n\t\ttargetNode: NodeDefinition,\n\t\tcontext: ContextImplementation<any>,\n\t\tallPredecessors?: Map<string, Set<string>>,\n\t\texecutionId?: string,\n\t): Promise<void> {\n\t\tconst asyncContext = context.type === 'sync' ? new AsyncContextView(context) : context\n\t\tconst predecessors = allPredecessors?.get(targetNode.id)\n\t\tconst _hasSinglePredecessor = predecessors && predecessors.size === 1\n\t\tconst hasExplicitInputs = targetNode.inputs !== undefined\n\t\tconst hasEdgeTransform = edge.transform !== undefined\n\n\t\tlet sourceOutput = sourceResult.output\n\n\t\t// When the target node has an explicit `inputs` map, resolve that node's output\n\t\tif (hasEdgeTransform && hasExplicitInputs && typeof targetNode.inputs === 'string') {\n\t\t\tconst inputsKey = targetNode.inputs\n\t\t\tconst resolvedKey = inputsKey.startsWith('_') ? inputsKey : `_outputs.${inputsKey}`\n\t\t\tif ((await asyncContext.has(resolvedKey as any)) && inputsKey !== edge.source) {\n\t\t\t\tsourceOutput = await asyncContext.get(resolvedKey as any)\n\t\t\t}\n\t\t}\n\n\t\tconst finalInput = hasEdgeTransform\n\t\t\t? this.evaluator.evaluate(edge.transform!, {\n\t\t\t\t\tinput: sourceOutput,\n\t\t\t\t\tcontext: await asyncContext.toJSON(),\n\t\t\t\t})\n\t\t\t: sourceOutput\n\t\tconst inputKey = `_inputs.${targetNode.id}`\n\t\tawait asyncContext.set(inputKey as any, finalInput)\n\t\tawait this.eventBus.emit({\n\t\t\ttype: 'context:change',\n\t\t\tpayload: {\n\t\t\t\tsourceNode: edge.source,\n\t\t\t\tkey: inputKey,\n\t\t\t\top: 'set',\n\t\t\t\tvalue: finalInput,\n\t\t\t\texecutionId: executionId || 'unknown',\n\t\t\t},\n\t\t})\n\t\tif (!hasExplicitInputs || hasEdgeTransform) {\n\t\t\ttargetNode.inputs = inputKey\n\t\t}\n\t}\n\n\tpublic async resolveNodeInput(\n\t\tnodeId: string,\n\t\tblueprint: WorkflowBlueprint,\n\t\tcontext: ContextImplementation<any>,\n\t): Promise<any> {\n\t\tconst nodeDef = blueprint.nodes.find((n) => n.id === nodeId)\n\t\tif (!nodeDef) {\n\t\t\tthrow new FlowcraftError(`Node '${nodeId}' not found in blueprint.`, {\n\t\t\t\tnodeId,\n\t\t\t\tblueprintId: blueprint.id,\n\t\t\t\tisFatal: false,\n\t\t\t})\n\t\t}\n\t\tconst asyncContext = context.type === 'sync' ? new AsyncContextView(context) : context\n\t\tif (nodeDef.inputs) {\n\t\t\tif (typeof nodeDef.inputs === 'string') {\n\t\t\t\tconst key = nodeDef.inputs\n\t\t\t\tif (key.startsWith('_')) return await asyncContext.get(key as any)\n\t\t\t\tconst outputKey = `_outputs.${key}`\n\t\t\t\tif (await asyncContext.has(outputKey as any)) {\n\t\t\t\t\treturn await asyncContext.get(outputKey as any)\n\t\t\t\t}\n\t\t\t\treturn await asyncContext.get(key as any)\n\t\t\t}\n\t\t\tif (typeof nodeDef.inputs === 'object') {\n\t\t\t\tconst input: Record<string, any> = {}\n\t\t\t\tfor (const key in nodeDef.inputs) {\n\t\t\t\t\tconst contextKey = nodeDef.inputs[key]\n\t\t\t\t\tif (contextKey.startsWith('_')) {\n\t\t\t\t\t\tinput[key] = await asyncContext.get(contextKey as any)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst outputKey = `_outputs.${contextKey}`\n\t\t\t\t\t\tif (await asyncContext.has(outputKey as any)) {\n\t\t\t\t\t\t\tinput[key] = await asyncContext.get(outputKey as any)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tinput[key] = await asyncContext.get(contextKey as any)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn input\n\t\t\t}\n\t\t}\n\t\t// Default to standardized input key\n\t\tconst inputKey = `_inputs.${nodeDef.id}`\n\t\treturn await asyncContext.get(inputKey as any)\n\t}\n}\n","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 {\n\tBatchGatherNode,\n\tBatchScatterNode,\n\tSleepNode,\n\tSubflowNode,\n\tWaitNode,\n\tWebhookNode,\n} from '../nodes'\nimport { sanitizeBlueprint } from '../sanitizer'\nimport { JsonSerializer } from '../serializer'\nimport type {\n\tContextImplementation,\n\tEdgeDefinition,\n\tFlowcraftEvent,\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<\n\tTContext extends Record<string, any>,\n\tTDependencies extends Record<string, any>,\n> implements IRuntime<TContext, TDependencies> {\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()\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\tlet userRegistry: any\n\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) || {\n\t\t\t\temit: async () => {},\n\t\t\t}\n\t\t\tthis.middleware = this.container.resolve<Middleware[]>(ServiceTokens.Middleware) || []\n\t\t\tuserRegistry = this.container.resolve(ServiceTokens.NodeRegistry)\n\t\t\tthis.blueprints = this.container.resolve<Record<string, WorkflowBlueprint>>(\n\t\t\t\tServiceTokens.BlueprintRegistry,\n\t\t\t)\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\tuserRegistry = 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\n\t\tconst loopControllerFunction: NodeFunction = async (context) => {\n\t\t\tconst condition = context.params.condition\n\t\t\tconst contextData = await context.context.toJSON()\n\t\t\tconst result = this.evaluator.evaluate(condition, contextData)\n\t\t\tif (result) {\n\t\t\t\treturn { action: 'continue' }\n\t\t\t} else {\n\t\t\t\treturn { action: 'break', output: null }\n\t\t\t}\n\t\t}\n\t\tconst builtInNodes = {\n\t\t\twait: WaitNode,\n\t\t\tsleep: SleepNode,\n\t\t\twebhook: WebhookNode,\n\t\t\tsubflow: SubflowNode,\n\t\t\t'batch-scatter': BatchScatterNode,\n\t\t\t'batch-gather': BatchGatherNode,\n\t\t\t'loop-controller': loopControllerFunction,\n\t\t}\n\t\tthis.registry = new Map(Object.entries({ ...builtInNodes, ...userRegistry }))\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'\n\t\t\t\t? (this.serializer.deserialize(initialState) as Partial<TContext>)\n\t\t\t\t: 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: {\n\t\t\t\t\tblueprintId: executionContext.blueprint.id,\n\t\t\t\t\texecutionId: executionContext.executionId,\n\t\t\t\t},\n\t\t\t})\n\t\t\tawait this.eventBus.emit({\n\t\t\t\ttype: 'workflow:resume',\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},\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(\n\t\t\t\t\t`Workflow '${executionContext.blueprint.id}' failed strictness check: Cycles are not allowed.`,\n\t\t\t\t)\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(\n\t\t\t\texecutionContext.blueprint,\n\t\t\t\toptions?.strict === true,\n\t\t\t)\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:\n\t\t\t\t\t\t\ttraverser.getAllNodeIds().size -\n\t\t\t\t\t\t\texecutionContext.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: {\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},\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\toptions?.functionRegistry,\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: {\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},\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(checkIntervalMs?: number): void {\n\t\tif (checkIntervalMs !== undefined) {\n\t\t\tthis.scheduler = new WorkflowScheduler(this, checkIntervalMs)\n\t\t}\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(\n\t\t\t\t'Cannot resume: The provided context is not in an awaiting state.',\n\t\t\t\t{\n\t\t\t\t\tisFatal: true,\n\t\t\t\t},\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(\n\t\t\t\t`Cannot resume: Node '${awaitingNodeId}' is not in an awaiting state.`,\n\t\t\t\t{\n\t\t\t\t\tisFatal: true,\n\t\t\t\t},\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(\n\t\t\t\t\t`Cannot resume: Subflow state for node '${awaitingNodeId}' not found.`,\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: true,\n\t\t\t\t\t},\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(\n\t\t\t\t\t`Subflow node '${awaitingNodeId}' is missing the 'blueprintId' parameter.`,\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: true,\n\t\t\t\t\t},\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(\n\t\t\t\t\t`Sub-blueprint with ID '${blueprintId}' not found in runtime registry.`,\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: true,\n\t\t\t\t\t},\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tconst subflowResumeResult = await this.resume(\n\t\t\t\tsubBlueprint,\n\t\t\t\tsubflowContext,\n\t\t\t\tresumeData,\n\t\t\t\tundefined,\n\t\t\t\toptions,\n\t\t\t)\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\tconst existingOutput = (await workflowState\n\t\t\t.getContext()\n\t\t\t.get(`_outputs.${awaitingNodeId}`)) as any\n\t\tconst nodeOutput = resumeData.output !== undefined ? resumeData.output : existingOutput\n\t\tworkflowState.addCompletedNode(awaitingNodeId, nodeOutput)\n\n\t\tconst nodeResult = { output: nodeOutput }\n\t\tconst nextSteps = await this.determineNextNodes(\n\t\t\tblueprint,\n\t\t\tawaitingNodeId,\n\t\t\tnodeResult,\n\t\t\tcontextImpl,\n\t\t\texecutionId,\n\t\t)\n\n\t\tif (nextSteps.length === 0) {\n\t\t\tworkflowState.clearAwaiting(awaitingNodeId)\n\t\t\tconst result = await workflowState.toResult(this.serializer, executionId)\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(\n\t\t\t\tedge,\n\t\t\t\tnodeResult,\n\t\t\t\tnode,\n\t\t\t\tcontextImpl,\n\t\t\t\tallPredecessors,\n\t\t\t\texecutionId,\n\t\t\t)\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(\n\t\t\tblueprint,\n\t\t\tworkflowState,\n\t\t\toptions,\n\t\t)\n\n\t\treturn await this.orchestrator.run(executionContext, traverser)\n\t}\n\n\tpublic _createExecutionRegistry(\n\t\tdynamicRegistry?: Map<string, any>,\n\t): 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(\n\t\t\tblueprint,\n\t\t\tstate,\n\t\t\tnodeRegistry,\n\t\t\texecutionId || '',\n\t\t\tthis,\n\t\t\tservices,\n\t\t\tsignal,\n\t\t)\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\t\t\t\t(n: NodeDefinition) => n.id === executionResult.fallbackNodeId,\n\t\t\t)\n\t\t\tif (!fallbackNode) {\n\t\t\t\tthrow new FlowcraftError(\n\t\t\t\t\t`Fallback node '${executionResult.fallbackNodeId}' not found in blueprint.`,\n\t\t\t\t\t{\n\t\t\t\t\t\tnodeId: nodeDef.id,\n\t\t\t\t\t\tblueprintId: blueprint.id,\n\t\t\t\t\t\texecutionId,\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\tconst fallbackInput = await this.resolveNodeInput(\n\t\t\t\tfallbackNode.id,\n\t\t\t\tblueprint,\n\t\t\t\tasyncContext,\n\t\t\t)\n\t\t\tconst fallbackExecutor = this.executorFactory.createExecutorForNode(\n\t\t\t\tfallbackNode.id,\n\t\t\t\tcontext,\n\t\t\t)\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(\n\t\tnodeId: string,\n\t\tcontext: ExecutionContext<TContext, TDependencies>,\n\t): any {\n\t\treturn this.executorFactory.createExecutorForNode(nodeId, context)\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\texecutionId?: string,\n\t): Promise<void> {\n\t\treturn this.logicHandler.applyEdgeTransform(\n\t\t\tedge,\n\t\t\tsourceResult,\n\t\t\ttargetNode,\n\t\t\tcontext,\n\t\t\tallPredecessors,\n\t\t\texecutionId,\n\t\t)\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\t/**\n\t * Replay a workflow execution from a pre-recorded event history.\n\t * This reconstructs the final workflow state without executing any node logic,\n\t * enabling time-travel debugging and post-mortem analysis.\n\t *\n\t * @param blueprint The workflow blueprint\n\t * @param events The recorded event history for the execution\n\t * @param executionId Optional execution ID to filter events (if events contain multiple executions)\n\t * @returns The reconstructed workflow result\n\t */\n\tasync replay(\n\t\tblueprint: WorkflowBlueprint,\n\t\tevents: FlowcraftEvent[],\n\t\texecutionId?: string,\n\t): Promise<WorkflowResult<TContext>> {\n\t\tlet filteredEvents = events\n\t\tif (executionId) {\n\t\t\tfilteredEvents = events.filter((event) => {\n\t\t\t\tif ('executionId' in event.payload) {\n\t\t\t\t\treturn event.payload.executionId === executionId\n\t\t\t\t}\n\t\t\t\treturn false\n\t\t\t})\n\t\t}\n\n\t\tif (!executionId) {\n\t\t\tconst workflowStartEvent = filteredEvents.find((e) => e.type === 'workflow:start')\n\t\t\tif (workflowStartEvent && 'executionId' in workflowStartEvent.payload) {\n\t\t\t\texecutionId = workflowStartEvent.payload.executionId\n\t\t\t} else {\n\t\t\t\tthrow new FlowcraftError('Cannot determine execution ID from events', {\n\t\t\t\t\tisFatal: true,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\tconst tempContext = this._setupExecutionContext(\n\t\t\tblueprint,\n\t\t\t{},\n\t\t\t{ strict: false }, // allow cycles in replay\n\t\t)\n\n\t\tconst executionContext = new ExecutionContext(\n\t\t\tblueprint,\n\t\t\ttempContext.state,\n\t\t\ttempContext.nodeRegistry,\n\t\t\texecutionId,\n\t\t\tthis,\n\t\t\ttempContext.services,\n\t\t\ttempContext.signal,\n\t\t\ttempContext.concurrency,\n\t\t)\n\n\t\tconst { ReplayOrchestrator } = await import('./orchestrators/replay')\n\t\tconst replayOrchestrator = new ReplayOrchestrator(filteredEvents)\n\n\t\tconst traverser = new GraphTraverser(blueprint)\n\n\t\treturn await replayOrchestrator.run(executionContext, traverser)\n\t}\n}\n"],"mappings":"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"}
|
package/dist/testing/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { F as InMemoryEventStore, I as PersistentEventBusAdapter, _ as executeBatch, b as WorkflowState, l as GraphTraverser, t as FlowRuntime, v as processResults, w as FlowcraftError, y as ExecutionContext } from "../runtime-
|
|
1
|
+
import { F as InMemoryEventStore, I as PersistentEventBusAdapter, _ as executeBatch, b as WorkflowState, l as GraphTraverser, t as FlowRuntime, v as processResults, w as FlowcraftError, y as ExecutionContext } from "../runtime-lNm7WbD1.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/testing/event-logger.ts
|
|
4
4
|
/**
|