flowcraft 2.0.0 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/README.md +51 -5
  2. package/dist/analysis.d.ts +1 -1
  3. package/dist/analysis.js +1 -1
  4. package/dist/{chunk-RYTIQZIB.js → chunk-3XVVR2SR.js} +167 -53
  5. package/dist/chunk-3XVVR2SR.js.map +1 -0
  6. package/dist/{chunk-6DNEDIIT.js → chunk-4A627Q6L.js} +47 -23
  7. package/dist/chunk-4A627Q6L.js.map +1 -0
  8. package/dist/{chunk-VFC342WL.js → chunk-4PELJWF7.js} +6 -6
  9. package/dist/chunk-4PELJWF7.js.map +1 -0
  10. package/dist/{chunk-WXT3YEWU.js → chunk-5ZXV3R5D.js} +2 -2
  11. package/dist/chunk-5ZXV3R5D.js.map +1 -0
  12. package/dist/{chunk-UYPIWXZG.js → chunk-CSZ6EOWG.js} +9 -10
  13. package/dist/chunk-CSZ6EOWG.js.map +1 -0
  14. package/dist/chunk-CYHZ2YVH.js +24 -0
  15. package/dist/chunk-CYHZ2YVH.js.map +1 -0
  16. package/dist/{chunk-J3RNCPED.js → chunk-DSYAC4WB.js} +2 -2
  17. package/dist/chunk-DSYAC4WB.js.map +1 -0
  18. package/dist/{chunk-M23P46ZL.js → chunk-HN72TZY5.js} +10 -5
  19. package/dist/chunk-HN72TZY5.js.map +1 -0
  20. package/dist/{chunk-MICPMOTW.js → chunk-KWQHFT7E.js} +2 -2
  21. package/dist/chunk-KWQHFT7E.js.map +1 -0
  22. package/dist/chunk-M2FRTT2K.js +144 -0
  23. package/dist/chunk-M2FRTT2K.js.map +1 -0
  24. package/dist/{chunk-RW4FH7IL.js → chunk-NBIRTKZ7.js} +89 -32
  25. package/dist/chunk-NBIRTKZ7.js.map +1 -0
  26. package/dist/chunk-O3XD45IL.js +236 -0
  27. package/dist/chunk-O3XD45IL.js.map +1 -0
  28. package/dist/chunk-PH2IYZHV.js +48 -0
  29. package/dist/chunk-PH2IYZHV.js.map +1 -0
  30. package/dist/{chunk-DSZSR7UE.js → chunk-U5V5O5MN.js} +11 -2
  31. package/dist/chunk-U5V5O5MN.js.map +1 -0
  32. package/dist/{chunk-RAZXOMZC.js → chunk-UETC63DP.js} +7 -6
  33. package/dist/chunk-UETC63DP.js.map +1 -0
  34. package/dist/context.d.ts +5 -5
  35. package/dist/context.js +1 -1
  36. package/dist/errors.js +1 -1
  37. package/dist/evaluator.d.ts +21 -13
  38. package/dist/evaluator.js +1 -1
  39. package/dist/flow.d.ts +6 -5
  40. package/dist/flow.js +2 -2
  41. package/dist/index.d.ts +2 -1
  42. package/dist/index.js +15 -15
  43. package/dist/linter.d.ts +1 -1
  44. package/dist/linter.js +2 -2
  45. package/dist/logger.d.ts +5 -5
  46. package/dist/logger.js +1 -1
  47. package/dist/node.d.ts +1 -1
  48. package/dist/node.js +1 -1
  49. package/dist/runtime/adapter.d.ts +24 -4
  50. package/dist/runtime/adapter.js +13 -13
  51. package/dist/runtime/executors.d.ts +7 -7
  52. package/dist/runtime/executors.js +2 -2
  53. package/dist/runtime/index.d.ts +1 -1
  54. package/dist/runtime/index.js +13 -13
  55. package/dist/runtime/runtime.d.ts +9 -7
  56. package/dist/runtime/runtime.js +12 -12
  57. package/dist/runtime/state.d.ts +2 -2
  58. package/dist/runtime/state.js +2 -2
  59. package/dist/runtime/traverser.d.ts +5 -3
  60. package/dist/runtime/traverser.js +3 -3
  61. package/dist/runtime/types.d.ts +2 -1
  62. package/dist/sanitizer.d.ts +1 -1
  63. package/dist/sanitizer.js +1 -1
  64. package/dist/serializer.d.ts +2 -1
  65. package/dist/serializer.js +1 -1
  66. package/dist/{types-CZN_FcB6.d.ts → types-CQCe_nBM.d.ts} +35 -22
  67. package/dist/types.d.ts +1 -1
  68. package/package.json +2 -2
  69. package/dist/chunk-6DNEDIIT.js.map +0 -1
  70. package/dist/chunk-734J4PTM.js +0 -100
  71. package/dist/chunk-734J4PTM.js.map +0 -1
  72. package/dist/chunk-DSZSR7UE.js.map +0 -1
  73. package/dist/chunk-GTZC6PQI.js +0 -22
  74. package/dist/chunk-GTZC6PQI.js.map +0 -1
  75. package/dist/chunk-J3RNCPED.js.map +0 -1
  76. package/dist/chunk-M23P46ZL.js.map +0 -1
  77. package/dist/chunk-MICPMOTW.js.map +0 -1
  78. package/dist/chunk-NPAJNLXQ.js +0 -106
  79. package/dist/chunk-NPAJNLXQ.js.map +0 -1
  80. package/dist/chunk-RAZXOMZC.js.map +0 -1
  81. package/dist/chunk-REH55ZXV.js +0 -13
  82. package/dist/chunk-REH55ZXV.js.map +0 -1
  83. package/dist/chunk-RW4FH7IL.js.map +0 -1
  84. package/dist/chunk-RYTIQZIB.js.map +0 -1
  85. package/dist/chunk-UYPIWXZG.js.map +0 -1
  86. package/dist/chunk-VFC342WL.js.map +0 -1
  87. package/dist/chunk-WXT3YEWU.js.map +0 -1
@@ -1,3 +1,3 @@
1
- export { JsonSerializer } from './chunk-REH55ZXV.js';
1
+ export { JsonSerializer } from './chunk-CYHZ2YVH.js';
2
2
  //# sourceMappingURL=serializer.js.map
3
3
  //# sourceMappingURL=serializer.js.map
@@ -1,5 +1,3 @@
1
- /** eslint-disable unused-imports/no-unused-vars */
2
-
3
1
  /** A type guard to reliably distinguish a NodeClass from a NodeFunction. */
4
2
  declare function isNodeClass(impl: any): impl is NodeClass;
5
3
  /**
@@ -7,36 +5,44 @@ declare function isNodeClass(impl: any): impl is NodeClass;
7
5
  * This class is generic, allowing implementations to specify the exact context
8
6
  * and dependency types they expect.
9
7
  */
10
- declare abstract class BaseNode<TContext extends Record<string, any> = Record<string, any>, TDependencies extends RuntimeDependencies = RuntimeDependencies> {
11
- protected params: Record<string, any>;
8
+ declare abstract class BaseNode<TContext extends Record<string, any> = Record<string, any>, TDependencies extends RuntimeDependencies = RuntimeDependencies, TInput = any, TOutput = any, TAction extends string = string> {
9
+ protected params?: Record<string, any> | undefined;
12
10
  /**
13
11
  * @param params Static parameters for this node instance, passed from the blueprint.
14
12
  */
15
- constructor(params: Record<string, any>);
13
+ constructor(params?: Record<string, any> | undefined);
16
14
  /**
17
15
  * Phase 1: Gathers and prepares data for execution. This phase is NOT retried on failure.
18
16
  * @param context The node's execution context.
19
17
  * @returns The data needed for the `exec` phase.
20
18
  */
21
- prep(context: NodeContext<TContext, TDependencies>): Promise<any>;
19
+ prep(context: NodeContext<TContext, TDependencies, TInput>): Promise<any>;
22
20
  /**
23
21
  * Phase 2: Performs the core, isolated logic. This is the ONLY phase that is retried.
24
22
  * @param prepResult The data returned from the `prep` phase.
25
23
  * @param context The node's execution context.
26
24
  */
27
- abstract exec(prepResult: any, context: NodeContext<TContext, TDependencies>): Promise<Omit<NodeResult, 'error'>>;
25
+ abstract exec(prepResult: any, context: NodeContext<TContext, TDependencies, TInput>): Promise<Omit<NodeResult<TOutput, TAction>, 'error'>>;
28
26
  /**
29
27
  * Phase 3: Processes the result and saves state. This phase is NOT retried.
30
28
  * @param execResult The successful result from the `exec` or `fallback` phase.
31
29
  * @param _context The node's execution context.
32
30
  */
33
- post(execResult: Omit<NodeResult, 'error'>, _context: NodeContext<TContext, TDependencies>): Promise<NodeResult>;
31
+ post(execResult: Omit<NodeResult<TOutput, TAction>, 'error'>, _context: NodeContext<TContext, TDependencies, TInput>): Promise<NodeResult<TOutput, TAction>>;
34
32
  /**
35
33
  * An optional safety net that runs if all `exec` retries fail.
36
34
  * @param error The final error from the last `exec` attempt.
37
35
  * @param _context The node's execution context.
38
36
  */
39
- fallback(error: Error, _context: NodeContext<TContext, TDependencies>): Promise<Omit<NodeResult, 'error'>>;
37
+ fallback(error: Error, _context: NodeContext<TContext, TDependencies, TInput>): Promise<Omit<NodeResult<TOutput, TAction>, 'error'>>;
38
+ /**
39
+ * An optional cleanup phase for non-retriable errors that occur outside the main `exec` method.
40
+ * This method is invoked in a `finally` block or equivalent construct if a fatal, unhandled exception occurs in the `prep`, `exec`, or `post` phases.
41
+ * Allows nodes to perform crucial cleanup, such as closing database connections or releasing locks.
42
+ * @param _error The error that caused the failure.
43
+ * @param _context The node's execution context.
44
+ */
45
+ recover(_error: Error, _context: NodeContext<TContext, TDependencies, TInput>): Promise<void>;
40
46
  }
41
47
 
42
48
  /** The central, serializable representation of a workflow. */
@@ -80,9 +86,9 @@ interface NodeConfig {
80
86
  joinStrategy?: 'all' | 'any';
81
87
  }
82
88
  /** The required return type for any node implementation. */
83
- interface NodeResult<TOutput = any> {
89
+ interface NodeResult<TOutput = any, TAction extends string = string> {
84
90
  output?: TOutput;
85
- action?: string;
91
+ action?: TAction;
86
92
  error?: {
87
93
  message: string;
88
94
  [key: string]: any;
@@ -93,11 +99,11 @@ interface NodeResult<TOutput = any> {
93
99
  _fallbackExecuted?: boolean;
94
100
  }
95
101
  /** The context object passed to every node's execution logic. */
96
- interface NodeContext<TContext extends Record<string, any> = Record<string, any>, TDependencies extends RuntimeDependencies = RuntimeDependencies> {
102
+ interface NodeContext<TContext extends Record<string, any> = Record<string, any>, TDependencies extends RuntimeDependencies = RuntimeDependencies, TInput = any> {
97
103
  /** The async-only interface for interacting with the workflow's state. */
98
104
  context: IAsyncContext<TContext>;
99
105
  /** The primary input data for this node, typically from its predecessor. */
100
- input?: any;
106
+ input?: TInput;
101
107
  /** Static parameters defined in the blueprint. */
102
108
  params: Record<string, any>;
103
109
  /** Shared, runtime-level dependencies (e.g., database clients, loggers). */
@@ -106,9 +112,9 @@ interface NodeContext<TContext extends Record<string, any> = Record<string, any>
106
112
  signal?: AbortSignal;
107
113
  }
108
114
  /** A simple function-based node implementation. */
109
- type NodeFunction<TContext extends Record<string, any> = Record<string, any>, TDependencies extends RuntimeDependencies = RuntimeDependencies> = (context: NodeContext<TContext, TDependencies>) => Promise<NodeResult>;
115
+ type NodeFunction<TContext extends Record<string, any> = Record<string, any>, TDependencies extends RuntimeDependencies = RuntimeDependencies, TInput = any, TOutput = any, TAction extends string = string> = (context: NodeContext<TContext, TDependencies, TInput>) => Promise<NodeResult<TOutput, TAction>>;
110
116
  /** Represents a constructor for any concrete class that extends the abstract BaseNode. */
111
- type NodeClass = new (params?: any) => BaseNode<any, any>;
117
+ type NodeClass<TContext extends Record<string, any> = Record<string, any>, TDependencies extends RuntimeDependencies = RuntimeDependencies, TInput = any, TOutput = any, TAction extends string = string> = new (params?: Record<string, any>) => BaseNode<TContext, TDependencies, TInput, TOutput, TAction>;
112
118
  /** A union of all possible node implementation types. */
113
119
  type NodeImplementation = NodeFunction | NodeClass;
114
120
  /** A registry mapping node types to their implementations. */
@@ -120,8 +126,8 @@ interface ISyncContext<TContext extends Record<string, any> = Record<string, any
120
126
  readonly type: 'sync';
121
127
  get: <K extends keyof TContext>(key: K) => TContext[K] | undefined;
122
128
  set: <K extends keyof TContext>(key: K, value: TContext[K]) => void;
123
- has: (key: keyof TContext) => boolean;
124
- delete: (key: keyof TContext) => boolean;
129
+ has: <K extends keyof TContext>(key: K) => boolean;
130
+ delete: <K extends keyof TContext>(key: K) => boolean;
125
131
  toJSON: () => Record<string, any>;
126
132
  }
127
133
  /** The asynchronous context interface for remote or distributed state. */
@@ -129,8 +135,8 @@ interface IAsyncContext<TContext extends Record<string, any> = Record<string, an
129
135
  readonly type: 'async';
130
136
  get: <K extends keyof TContext>(key: K) => Promise<TContext[K] | undefined>;
131
137
  set: <K extends keyof TContext>(key: K, value: TContext[K]) => Promise<void>;
132
- has: (key: keyof TContext) => Promise<boolean>;
133
- delete: (key: keyof TContext) => Promise<boolean>;
138
+ has: <K extends keyof TContext>(key: K) => Promise<boolean>;
139
+ delete: <K extends keyof TContext>(key: K) => Promise<boolean>;
134
140
  toJSON: () => Promise<Record<string, any>>;
135
141
  }
136
142
  /** Generic for any set of dependencies. */
@@ -140,7 +146,7 @@ interface RuntimeDependencies {
140
146
  /** Configuration options for the FlowRuntime. */
141
147
  interface RuntimeOptions<TDependencies extends RuntimeDependencies = RuntimeDependencies> {
142
148
  /** A registry of globally available node implementations. */
143
- registry?: Record<string, NodeFunction | NodeClass>;
149
+ registry?: Record<string, NodeFunction | NodeClass | typeof BaseNode>;
144
150
  /** A registry of all available workflow blueprints for subflow execution. */
145
151
  blueprints?: Record<string, WorkflowBlueprint>;
146
152
  /** Shared dependencies to be injected into every node. */
@@ -149,7 +155,12 @@ interface RuntimeOptions<TDependencies extends RuntimeDependencies = RuntimeDepe
149
155
  logger?: ILogger;
150
156
  /** A pluggable event bus for observability. */
151
157
  eventBus?: IEventBus;
152
- /** A pluggable evaluator for edge conditions and transforms. */
158
+ /**
159
+ * A pluggable evaluator for edge conditions and transforms.
160
+ * @default new PropertyEvaluator() - A safe evaluator for simple property access.
161
+ * For complex logic, provide a custom implementation or use the `UnsafeEvaluator`
162
+ * (not recommended for production).
163
+ */
153
164
  evaluator?: IEvaluator;
154
165
  /** An array of middleware to wrap node execution. */
155
166
  middleware?: Middleware[];
@@ -189,9 +200,11 @@ interface WorkflowError {
189
200
  nodeId: string;
190
201
  message: string;
191
202
  originalError?: any;
203
+ timestamp: string;
204
+ stack?: string;
192
205
  }
193
206
  /** The final result of a workflow execution. */
194
- interface WorkflowResult<TContext = any> {
207
+ interface WorkflowResult<TContext = Record<string, any>> {
195
208
  context: TContext;
196
209
  serializedContext: string;
197
210
  status: 'completed' | 'failed' | 'stalled' | 'cancelled';
package/dist/types.d.ts CHANGED
@@ -1 +1 @@
1
- export { C as ContextImplementation, E as EdgeDefinition, h as IAsyncContext, k as IEvaluator, m as IEventBus, l as ILogger, n as ISerializer, I as ISyncContext, M as Middleware, e as NodeClass, a as NodeConfig, c as NodeContext, N as NodeDefinition, d as NodeFunction, f as NodeImplementation, g as NodeRegistry, b as NodeResult, R as RuntimeDependencies, j as RuntimeOptions, W as WorkflowBlueprint, o as WorkflowError, p as WorkflowResult } from './types-CZN_FcB6.js';
1
+ export { C as ContextImplementation, E as EdgeDefinition, h as IAsyncContext, k as IEvaluator, m as IEventBus, l as ILogger, n as ISerializer, I as ISyncContext, M as Middleware, e as NodeClass, a as NodeConfig, c as NodeContext, N as NodeDefinition, d as NodeFunction, f as NodeImplementation, g as NodeRegistry, b as NodeResult, R as RuntimeDependencies, j as RuntimeOptions, W as WorkflowBlueprint, o as WorkflowError, p as WorkflowResult } from './types-CQCe_nBM.js';
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "flowcraft",
3
3
  "type": "module",
4
- "version": "2.0.0",
4
+ "version": "2.1.1",
5
5
  "description": "A lightweight workflow framework",
6
6
  "license": "MIT",
7
- "homepage": "https://github.com/gorango/flowcraft",
7
+ "homepage": "https://flowcraft.js.org",
8
8
  "repository": {
9
9
  "type": "git",
10
10
  "url": "https://github.com/gorango/flowcraft.git"
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/flow.ts"],"names":[],"mappings":"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","file":"chunk-6DNEDIIT.js","sourcesContent":["import type { EdgeDefinition, NodeClass, NodeDefinition, NodeFunction, WorkflowBlueprint } from './types'\nimport { isNodeClass } from './node'\n\n/**\n * A fluent API for programmatically constructing a WorkflowBlueprint.\n */\nexport class Flow<\n\tTContext extends Record<string, any> = Record<string, any>,\n\tTDependencies extends Record<string, any> = Record<string, any>,\n> {\n\tprivate blueprint: Partial<WorkflowBlueprint>\n\tprivate functionRegistry: Map<string, NodeFunction | NodeClass>\n\tprivate loopControllerIds: Map<string, string>\n\n\tconstructor(id: string) {\n\t\tthis.blueprint = { id, nodes: [], edges: [] }\n\t\tthis.functionRegistry = new Map()\n\t\tthis.loopControllerIds = new Map()\n\t}\n\n\tnode(\n\t\tid: string,\n\t\timplementation: NodeFunction<TContext, TDependencies> | NodeClass,\n\t\toptions?: Omit<NodeDefinition, 'id' | 'uses'>,\n\t): this {\n\t\tlet usesKey: string\n\n\t\tif (isNodeClass(implementation)) {\n\t\t\tusesKey = (implementation.name && implementation.name !== 'BaseNode')\n\t\t\t\t? implementation.name\n\t\t\t\t: `class_${globalThis.crypto.randomUUID()}`\n\t\t\tthis.functionRegistry.set(usesKey, implementation)\n\t\t}\n\t\telse {\n\t\t\tusesKey = `fn_${globalThis.crypto.randomUUID()}`\n\t\t\tthis.functionRegistry.set(usesKey, implementation as NodeFunction)\n\t\t}\n\n\t\tconst nodeDef: NodeDefinition = { id, uses: usesKey, ...options }\n\t\tthis.blueprint.nodes!.push(nodeDef)\n\t\treturn this\n\t}\n\n\tedge(source: string, target: string, options?: Omit<EdgeDefinition, 'source' | 'target'>): this {\n\t\tconst edgeDef: EdgeDefinition = { source, target, ...options }\n\t\tthis.blueprint.edges!.push(edgeDef)\n\t\treturn this\n\t}\n\n\t/**\n\t * Creates a batch processing pattern.\n\t * It takes an input array, runs a worker node on each item in parallel, and gathers the results.\n\t * @param id The base ID for this batch operation.\n\t * @param worker The node implementation to run on each item.\n\t * @param options Configuration for the batch operation.\n\t * @param options.inputKey The key in the context that holds the input array for the batch.\n\t * @param options.outputKey The key in the context where the array of results will be stored.\n\t * @returns The Flow instance for chaining.\n\t */\n\tbatch(id: string, worker: NodeFunction<TContext, TDependencies> | NodeClass, options: {\n\t\t/** The key in the context that holds the input array for the batch. */\n\t\tinputKey: string\n\t\t/** The key in the context where the array of results will be stored. */\n\t\toutputKey: string\n\t}): this {\n\t\tconst { inputKey, outputKey } = options\n\t\tconst scatterId = `${id}_scatter`\n\t\tconst gatherId = `${id}_gather`\n\n\t\t// Register the user's worker implementation under a unique key.\n\t\tlet workerUsesKey: string\n\t\tif (isNodeClass(worker)) {\n\t\t\tworkerUsesKey = (worker.name && worker.name !== 'BaseNode') ? worker.name : `class_batch_worker_${globalThis.crypto.randomUUID()}`\n\t\t\tthis.functionRegistry.set(workerUsesKey, worker)\n\t\t}\n\t\telse {\n\t\t\tworkerUsesKey = `fn_batch_worker_${globalThis.crypto.randomUUID()}`\n\t\t\tthis.functionRegistry.set(workerUsesKey, worker as NodeFunction)\n\t\t}\n\n\t\t// Scatter Node: A built-in node that takes an array and dynamically schedules worker nodes.\n\t\tthis.blueprint.nodes!.push({\n\t\t\tid: scatterId,\n\t\t\tuses: 'batch-scatter', // This is a special, built-in node type\n\t\t\tinputs: inputKey,\n\t\t\tparams: { workerUsesKey, outputKey, gatherNodeId: gatherId },\n\t\t})\n\n\t\t// Gather Node: A built-in node that waits for all workers to finish and collects the results.\n\t\tthis.blueprint.nodes!.push({\n\t\t\tid: gatherId,\n\t\t\tuses: 'batch-gather', // built-in node type\n\t\t\tparams: { outputKey },\n\t\t\tconfig: { joinStrategy: 'all' }, // Important: Must wait for all scattered jobs\n\t\t})\n\n\t\t// Edge to connect the scatter and gather nodes. The orchestrator will manage the dynamic workers.\n\t\tthis.edge(scatterId, gatherId)\n\n\t\treturn this\n\t}\n\n\t/**\n\t * Creates a loop pattern in the workflow graph.\n\t * @param id A unique identifier for the loop construct.\n\t * @param options Defines the start, end, and continuation condition of the loop.\n\t * @param options.startNodeId The ID of the first node inside the loop body.\n\t * @param options.endNodeId The ID of the last node inside the loop body.\n\t * @param options.condition An expression that, if true, causes the loop to run again.\n\t */\n\tloop(id: string, options: {\n\t\t/** The ID of the first node inside the loop body. */\n\t\tstartNodeId: string\n\t\t/** The ID of the last node inside the loop body. */\n\t\tendNodeId: string\n\t\t/** An expression that, if true, causes the loop to run again. */\n\t\tcondition: string\n\t}): this {\n\t\tconst { startNodeId, endNodeId, condition } = options\n\t\tconst controllerId = `${id}-loop`\n\n\t\t// Store the generated ID against the user-provided loop ID\n\t\tthis.loopControllerIds.set(id, controllerId)\n\n\t\t// Add the controller node, which evaluates the loop condition.\n\t\t// Set joinStrategy='any' to allow re-execution on each loop iteration\n\t\tthis.blueprint.nodes!.push({\n\t\t\tid: controllerId,\n\t\t\tuses: 'loop-controller', // Special built-in node type\n\t\t\tparams: { condition },\n\t\t\tconfig: { joinStrategy: 'any' },\n\t\t})\n\n\t\t// Connect the end of the loop body to the controller.\n\t\tthis.edge(endNodeId, controllerId)\n\n\t\t// Connect the controller back to the start of the loop if the condition is met.\n\t\t// Use a transform to pass the end node's value to the start node for the next iteration.\n\t\tthis.edge(controllerId, startNodeId, { action: 'continue', transform: `context.${endNodeId}` })\n\n\t\t// Set the start and end nodes to use 'any' join strategy so they can re-execute\n\t\t// Start node: executes when either its initial predecessor OR the loop controller completes\n\t\t// End node: needs to re-execute on each loop iteration\n\t\tconst startNode = this.blueprint.nodes!.find(n => n.id === startNodeId)\n\t\tif (startNode)\n\t\t\tstartNode.config = { ...startNode.config, joinStrategy: 'any' }\n\n\t\tconst endNode = this.blueprint.nodes!.find(n => n.id === endNodeId)\n\t\tif (endNode)\n\t\t\tendNode.config = { ...endNode.config, joinStrategy: 'any' }\n\n\t\treturn this\n\t}\n\n\tgetLoopControllerId(id: string): string {\n\t\tconst controllerId = this.loopControllerIds.get(id)\n\t\tif (!controllerId) {\n\t\t\tthrow new Error(`Loop with id '${id}' not found. Ensure you have defined it using the .loop() method.`)\n\t\t}\n\t\treturn controllerId\n\t}\n\n\ttoBlueprint(): WorkflowBlueprint {\n\t\tif (!this.blueprint.nodes || this.blueprint.nodes.length === 0) {\n\t\t\tthrow new Error('Cannot build a blueprint with no nodes.')\n\t\t}\n\t\treturn this.blueprint as WorkflowBlueprint\n\t}\n\n\tgetFunctionRegistry() {\n\t\treturn this.functionRegistry\n\t}\n}\n\n/**\n * Helper function to create a new Flow builder instance.\n */\nexport function createFlow<\n\tTContext extends Record<string, any> = Record<string, any>,\n\tTDependencies extends Record<string, any> = Record<string, any>,\n>(id: string): Flow<TContext, TDependencies> {\n\treturn new Flow(id)\n}\n"]}
@@ -1,100 +0,0 @@
1
- import { CancelledWorkflowError, FatalNodeExecutionError } from './chunk-WXT3YEWU.js';
2
-
3
- // src/runtime/executors.ts
4
- var FunctionNodeExecutor = class {
5
- constructor(implementation, maxRetries, eventBus) {
6
- this.implementation = implementation;
7
- this.maxRetries = maxRetries;
8
- this.eventBus = eventBus;
9
- }
10
- async execute(nodeDef, context, executionId, signal) {
11
- let lastError;
12
- for (let attempt = 1; attempt <= this.maxRetries; attempt++) {
13
- try {
14
- signal?.throwIfAborted();
15
- const result = await this.implementation(context);
16
- if (attempt > 1) {
17
- context.dependencies.logger.info(`Node execution succeeded after retry`, { nodeId: nodeDef.id, attempt, executionId });
18
- }
19
- return result;
20
- } catch (error) {
21
- lastError = error;
22
- if (error instanceof DOMException && error.name === "AbortError") {
23
- throw new CancelledWorkflowError("Workflow cancelled");
24
- }
25
- if (error instanceof FatalNodeExecutionError)
26
- break;
27
- if (attempt < this.maxRetries) {
28
- context.dependencies.logger.warn(`Node execution failed, retrying`, { nodeId: nodeDef.id, attempt, maxRetries: this.maxRetries, error: error instanceof Error ? error.message : String(error), executionId });
29
- await this.eventBus.emit("node:retry", { blueprintId: context.dependencies.blueprint?.id || "", nodeId: nodeDef.id, attempt, executionId });
30
- } else {
31
- context.dependencies.logger.error(`Node execution failed after all retries`, { nodeId: nodeDef.id, attempts: this.maxRetries, error: error instanceof Error ? error.message : String(error), executionId });
32
- }
33
- }
34
- }
35
- throw lastError;
36
- }
37
- };
38
- var ClassNodeExecutor = class {
39
- constructor(implementation, maxRetries, eventBus) {
40
- this.implementation = implementation;
41
- this.maxRetries = maxRetries;
42
- this.eventBus = eventBus;
43
- }
44
- async execute(nodeDef, context, executionId, signal) {
45
- const instance = new this.implementation(nodeDef.params || {});
46
- try {
47
- signal?.throwIfAborted();
48
- const prepResult = await instance.prep(context);
49
- let execResult;
50
- let lastError;
51
- for (let attempt = 1; attempt <= this.maxRetries; attempt++) {
52
- try {
53
- signal?.throwIfAborted();
54
- execResult = await instance.exec(prepResult, context);
55
- lastError = void 0;
56
- if (attempt > 1) {
57
- context.dependencies.logger.info(`Node execution succeeded after retry`, { nodeId: nodeDef.id, attempt, executionId });
58
- }
59
- break;
60
- } catch (error) {
61
- lastError = error;
62
- if (error instanceof DOMException && error.name === "AbortError") {
63
- throw new CancelledWorkflowError("Workflow cancelled");
64
- }
65
- if (error instanceof FatalNodeExecutionError)
66
- break;
67
- if (attempt < this.maxRetries) {
68
- context.dependencies.logger.warn(`Node execution failed, retrying`, { nodeId: nodeDef.id, attempt, maxRetries: this.maxRetries, error: error instanceof Error ? error.message : String(error), executionId });
69
- await this.eventBus.emit("node:retry", { blueprintId: context.dependencies.blueprint?.id || "", nodeId: nodeDef.id, attempt, executionId });
70
- } else {
71
- context.dependencies.logger.error(`Node execution failed after all retries`, { nodeId: nodeDef.id, attempts: this.maxRetries, error: error instanceof Error ? error.message : String(error), executionId });
72
- }
73
- }
74
- }
75
- if (lastError) {
76
- signal?.throwIfAborted();
77
- execResult = await instance.fallback(lastError, context);
78
- }
79
- signal?.throwIfAborted();
80
- return await instance.post(execResult, context);
81
- } catch (error) {
82
- if (error instanceof DOMException && error.name === "AbortError") {
83
- throw new CancelledWorkflowError("Workflow cancelled");
84
- }
85
- throw error;
86
- }
87
- }
88
- };
89
- var BuiltInNodeExecutor = class {
90
- constructor(executeBuiltIn) {
91
- this.executeBuiltIn = executeBuiltIn;
92
- }
93
- async execute(nodeDef, context) {
94
- return this.executeBuiltIn(nodeDef, context.context);
95
- }
96
- };
97
-
98
- export { BuiltInNodeExecutor, ClassNodeExecutor, FunctionNodeExecutor };
99
- //# sourceMappingURL=chunk-734J4PTM.js.map
100
- //# sourceMappingURL=chunk-734J4PTM.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/runtime/executors.ts"],"names":[],"mappings":"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","file":"chunk-734J4PTM.js","sourcesContent":["import type { BaseNode } from '../node'\nimport type { ContextImplementation, IEventBus, NodeContext, NodeDefinition, NodeFunction, NodeResult } from '../types'\nimport { CancelledWorkflowError, FatalNodeExecutionError } from '../errors'\n\nexport interface ExecutionStrategy {\n\texecute: (\n\t\tnodeDef: NodeDefinition,\n\t\tcontext: NodeContext<any, any>,\n\t\texecutionId?: string,\n\t\tsignal?: AbortSignal,\n\t) => Promise<NodeResult>\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>,\n\t\texecutionId?: string,\n\t\tsignal?: AbortSignal,\n\t): Promise<NodeResult> {\n\t\tlet lastError: any\n\t\tfor (let attempt = 1; attempt <= this.maxRetries; attempt++) {\n\t\t\ttry {\n\t\t\t\tsignal?.throwIfAborted()\n\t\t\t\tconst result = await this.implementation(context)\n\t\t\t\tif (attempt > 1) {\n\t\t\t\t\tcontext.dependencies.logger.info(`Node execution succeeded after retry`, { nodeId: nodeDef.id, attempt, executionId })\n\t\t\t\t}\n\t\t\t\treturn result\n\t\t\t}\n\t\t\tcatch (error) {\n\t\t\t\tlastError = error\n\t\t\t\tif (error instanceof DOMException && error.name === 'AbortError') {\n\t\t\t\t\tthrow new CancelledWorkflowError('Workflow cancelled')\n\t\t\t\t}\n\t\t\t\tif (error instanceof FatalNodeExecutionError)\n\t\t\t\t\tbreak\n\t\t\t\tif (attempt < this.maxRetries) {\n\t\t\t\t\tcontext.dependencies.logger.warn(`Node execution failed, retrying`, { nodeId: nodeDef.id, attempt, maxRetries: this.maxRetries, error: error instanceof Error ? error.message : String(error), executionId })\n\t\t\t\t\tawait this.eventBus.emit('node:retry', { blueprintId: context.dependencies.blueprint?.id || '', nodeId: nodeDef.id, attempt, executionId })\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tcontext.dependencies.logger.error(`Node execution failed after all retries`, { nodeId: nodeDef.id, attempts: this.maxRetries, error: error instanceof Error ? error.message : String(error), executionId })\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthrow lastError\n\t}\n}\n\nexport class ClassNodeExecutor implements ExecutionStrategy {\n\tconstructor(\n\t\tprivate implementation: typeof BaseNode,\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>,\n\t\texecutionId?: string,\n\t\tsignal?: AbortSignal,\n\t): Promise<NodeResult> {\n\t\tconst instance = new (this.implementation as new (params: Record<string, any>) => BaseNode)(nodeDef.params || {})\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'>\n\t\t\tlet lastError: any\n\t\t\tfor (let attempt = 1; attempt <= this.maxRetries; attempt++) {\n\t\t\t\ttry {\n\t\t\t\t\tsignal?.throwIfAborted()\n\t\t\t\t\texecResult = await instance.exec(prepResult, context)\n\t\t\t\t\tlastError = undefined\n\t\t\t\t\tif (attempt > 1) {\n\t\t\t\t\t\tcontext.dependencies.logger.info(`Node execution succeeded after retry`, { nodeId: nodeDef.id, attempt, executionId })\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcatch (error) {\n\t\t\t\t\tlastError = error\n\t\t\t\t\tif (error instanceof DOMException && error.name === 'AbortError') {\n\t\t\t\t\t\tthrow new CancelledWorkflowError('Workflow cancelled')\n\t\t\t\t\t}\n\t\t\t\t\tif (error instanceof FatalNodeExecutionError)\n\t\t\t\t\t\tbreak\n\t\t\t\t\tif (attempt < this.maxRetries) {\n\t\t\t\t\t\tcontext.dependencies.logger.warn(`Node execution failed, retrying`, { nodeId: nodeDef.id, attempt, maxRetries: this.maxRetries, error: error instanceof Error ? error.message : String(error), executionId })\n\t\t\t\t\t\tawait this.eventBus.emit('node:retry', { blueprintId: context.dependencies.blueprint?.id || '', nodeId: nodeDef.id, attempt, executionId })\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tcontext.dependencies.logger.error(`Node execution failed after all retries`, { nodeId: nodeDef.id, attempts: this.maxRetries, error: error instanceof Error ? error.message : String(error), executionId })\n\t\t\t\t\t}\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\treturn await instance.post(execResult!, context)\n\t\t}\n\t\tcatch (error) {\n\t\t\tif (error instanceof DOMException && error.name === 'AbortError') {\n\t\t\t\tthrow new CancelledWorkflowError('Workflow cancelled')\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\t}\n}\n\nexport class BuiltInNodeExecutor implements ExecutionStrategy {\n\tconstructor(\n\t\tprivate executeBuiltIn: (nodeDef: NodeDefinition, context: ContextImplementation<any>) => Promise<NodeResult>,\n\t) { }\n\n\tasync execute(\n\t\tnodeDef: NodeDefinition,\n\t\tcontext: NodeContext<any, any>,\n\t): Promise<NodeResult> {\n\t\treturn this.executeBuiltIn(nodeDef, context.context as ContextImplementation<any>)\n\t}\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/node.ts"],"names":[],"mappings":";AAKO,SAAS,YAAY,IAAA,EAA8B;AACzD,EAAA,OAAO,OAAO,IAAA,KAAS,UAAA,IAAc,CAAC,CAAC,KAAK,SAAA,EAAW,IAAA;AACxD;AAOO,IAAe,WAAf,MAGL;AAAA;AAAA;AAAA;AAAA,EAID,YAAsB,MAAA,EAA6B;AAA7B,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAA+B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOrD,MAAM,KAAK,OAAA,EAA6D;AACvE,IAAA,OAAO,OAAA,CAAQ,KAAA;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,IAAA,CAAK,UAAA,EAAuC,QAAA,EAAqE;AACtH,IAAA,OAAO,UAAA;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,QAAA,CAAS,KAAA,EAAc,QAAA,EAAoF;AAEhH,IAAA,MAAM,KAAA;AAAA,EACP;AACD","file":"chunk-DSZSR7UE.js","sourcesContent":["/** eslint-disable unused-imports/no-unused-vars */\n\nimport 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> {\n\t/**\n\t * @param params Static parameters for this node instance, passed from the blueprint.\n\t */\n\tconstructor(protected params: Record<string, any>) { }\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>): 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(prepResult: any, context: NodeContext<TContext, TDependencies>): Promise<Omit<NodeResult, '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(execResult: Omit<NodeResult, 'error'>, _context: NodeContext<TContext, TDependencies>): Promise<NodeResult> {\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(error: Error, _context: NodeContext<TContext, TDependencies>): Promise<Omit<NodeResult, 'error'>> {\n\t\t// By default, re-throw the error, failing the node.\n\t\tthrow error\n\t}\n}\n"]}
@@ -1,22 +0,0 @@
1
- // src/evaluator.ts
2
- var SimpleEvaluator = class {
3
- evaluate(expression, context) {
4
- try {
5
- const validIdentifierRegex = /^[a-z_$][\w$]*$/i;
6
- const validKeys = Object.keys(context).filter((key) => validIdentifierRegex.test(key));
7
- const validContext = {};
8
- for (const key of validKeys) {
9
- validContext[key] = context[key];
10
- }
11
- const sandbox = new Function(...validKeys, `return ${expression}`);
12
- return sandbox(...validKeys.map((k) => validContext[k]));
13
- } catch (error) {
14
- console.error(`Error evaluating expression "${expression}":`, error);
15
- return void 0;
16
- }
17
- }
18
- };
19
-
20
- export { SimpleEvaluator };
21
- //# sourceMappingURL=chunk-GTZC6PQI.js.map
22
- //# sourceMappingURL=chunk-GTZC6PQI.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/evaluator.ts"],"names":[],"mappings":";AAiBO,IAAM,kBAAN,MAA4C;AAAA,EAClD,QAAA,CAAS,YAAoB,OAAA,EAAmC;AAC/D,IAAA,IAAI;AAEH,MAAA,MAAM,oBAAA,GAAuB,kBAAA;AAC7B,MAAA,MAAM,SAAA,GAAY,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,CAAE,OAAO,CAAA,GAAA,KAAO,oBAAA,CAAqB,IAAA,CAAK,GAAG,CAAC,CAAA;AACnF,MAAA,MAAM,eAAoC,EAAC;AAC3C,MAAA,KAAA,MAAW,OAAO,SAAA,EAAW;AAC5B,QAAA,YAAA,CAAa,GAAG,CAAA,GAAI,OAAA,CAAQ,GAAG,CAAA;AAAA,MAChC;AAIA,MAAA,MAAM,UAAU,IAAI,QAAA,CAAS,GAAG,SAAA,EAAW,CAAA,OAAA,EAAU,UAAU,CAAA,CAAE,CAAA;AACjE,MAAA,OAAO,OAAA,CAAQ,GAAG,SAAA,CAAU,GAAA,CAAI,OAAK,YAAA,CAAa,CAAC,CAAC,CAAC,CAAA;AAAA,IACtD,SACO,KAAA,EAAO;AACb,MAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,6BAAA,EAAgC,UAAU,CAAA,EAAA,CAAA,EAAM,KAAK,CAAA;AAEnE,MAAA,OAAO,MAAA;AAAA,IACR;AAAA,EACD;AACD","file":"chunk-GTZC6PQI.js","sourcesContent":["import type { IEvaluator } from './types'\n\n/**\n * A simple, safe, placeholder expression evaluator.\n * It provides a sandboxed environment for evaluating edge conditions and transforms.\n *\n * @warning This implementation uses `new Function()` which, while sandboxed from the global\n * scope, can be a security risk if expressions are provided by end-users. It is NOT\n * recommended for production systems. Please replace this with a more robust and secure\n * library like `jsep` by providing your own implementation in the runtime options.\n *\n * This implementation can only access properties on a single context object.\n * Example expressions:\n * - \"result.output.status === 'SUCCESS'\"\n * - \"context.user.isAdmin\"\n * - \"input.value * 100\"\n */\nexport class SimpleEvaluator 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 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\n\t\t\t// Creates a function that is sandboxed to only the keys of the `context` object.\n\t\t\t// It prevents access to global scope (e.g., `window`, `process`).\n\t\t\tconst sandbox = new Function(...validKeys, `return ${expression}`) // eslint-disable-line no-new-func\n\t\t\treturn sandbox(...validKeys.map(k => validContext[k]))\n\t\t}\n\t\tcatch (error) {\n\t\t\tconsole.error(`Error evaluating expression \"${expression}\":`, error)\n\t\t\t// In case of a syntax error or other issue, default to a \"falsy\" value.\n\t\t\treturn undefined\n\t\t}\n\t}\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/sanitizer.ts"],"names":[],"mappings":";AAOO,SAAS,kBAAkB,GAAA,EAA6B;AAC9D,EAAA,MAAM,KAAA,GAA0B,GAAA,CAAI,KAAA,EAAO,GAAA,CAAI,CAAC,IAAA,MAAe;AAAA,IAC9D,IAAI,IAAA,CAAK,EAAA;AAAA,IACT,MAAM,IAAA,CAAK,IAAA;AAAA,IACX,QAAQ,IAAA,CAAK,MAAA;AAAA,IACb,QAAQ,IAAA,CAAK,MAAA;AAAA,IACb,QAAQ,IAAA,CAAK;AAAA,GACd,CAAE,KAAK,EAAC;AAER,EAAA,MAAM,KAAA,GAA0B,GAAA,CAAI,KAAA,EAAO,GAAA,CAAI,CAAC,IAAA,MAAe;AAAA,IAC9D,QAAQ,IAAA,CAAK,MAAA;AAAA,IACb,QAAQ,IAAA,CAAK,MAAA;AAAA,IACb,QAAQ,IAAA,CAAK,MAAA;AAAA,IACb,WAAW,IAAA,CAAK,SAAA;AAAA,IAChB,WAAW,IAAA,CAAK;AAAA,GACjB,CAAE,KAAK,EAAC;AAER,EAAA,OAAO;AAAA,IACN,IAAI,GAAA,CAAI,EAAA;AAAA,IACR,KAAA;AAAA,IACA,KAAA;AAAA,IACA,UAAU,GAAA,CAAI;AAAA,GACf;AACD","file":"chunk-J3RNCPED.js","sourcesContent":["import type { EdgeDefinition, NodeDefinition, WorkflowBlueprint } from './types'\n\n/**\n * Sanitizes a raw workflow blueprint by removing extra properties\n * added by UI tools (e.g., position, style) and keeping only the\n * properties defined in NodeDefinition and EdgeDefinition.\n */\nexport function sanitizeBlueprint(raw: any): WorkflowBlueprint {\n\tconst nodes: NodeDefinition[] = raw.nodes?.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\tconst edges: EdgeDefinition[] = raw.edges?.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"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/analysis.ts"],"names":[],"mappings":"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","file":"chunk-M23P46ZL.js","sourcesContent":["import type { WorkflowBlueprint } from './types'\n\n/**\n * A list of cycles found in the graph. Each cycle is an array of node IDs.\n */\nexport type Cycles = string[][]\n\n/**\n * Analysis result for a workflow blueprint\n */\nexport interface BlueprintAnalysis {\n\t/** Cycles found in the graph */\n\tcycles: Cycles\n\t/** Node IDs that have no incoming edges (start nodes) */\n\tstartNodeIds: string[]\n\t/** Node IDs that have no outgoing edges (terminal nodes) */\n\tterminalNodeIds: string[]\n\t/** Total number of nodes */\n\tnodeCount: number\n\t/** Total number of edges */\n\tedgeCount: number\n\t/** Whether the graph is a valid DAG (no cycles) */\n\tisDag: boolean\n}\n\n/**\n * Analyzes a workflow blueprint to detect cycles.\n * @param blueprint The WorkflowBlueprint object containing nodes and edges.\n * @returns An array of cycles found. Each cycle is represented as an array of node IDs.\n */\nexport function checkForCycles(blueprint: WorkflowBlueprint): Cycles {\n\tconst cycles: Cycles = []\n\tif (!blueprint || !blueprint.nodes || blueprint.nodes.length === 0) {\n\t\treturn cycles\n\t}\n\n\tconst allNodeIds = blueprint.nodes.map(node => node.id)\n\tconst adj = new Map<string, string[]>()\n\tallNodeIds.forEach(id => adj.set(id, []))\n\tblueprint.edges.forEach(edge => adj.get(edge.source)?.push(edge.target))\n\n\tconst visited = new Set<string>()\n\tconst recursionStack = new Set<string>()\n\n\tfunction detectCycleUtil(nodeId: string, path: string[]) {\n\t\tvisited.add(nodeId)\n\t\trecursionStack.add(nodeId)\n\t\tpath.push(nodeId)\n\n\t\tconst neighbors = adj.get(nodeId) || []\n\t\tfor (const neighbor of neighbors) {\n\t\t\tif (recursionStack.has(neighbor)) {\n\t\t\t\tconst cycleStartIndex = path.indexOf(neighbor)\n\t\t\t\tconst cycle = path.slice(cycleStartIndex)\n\t\t\t\tcycles.push([...cycle, neighbor])\n\t\t\t}\n\t\t\telse if (!visited.has(neighbor)) {\n\t\t\t\tdetectCycleUtil(neighbor, path)\n\t\t\t}\n\t\t}\n\n\t\trecursionStack.delete(nodeId)\n\t\tpath.pop()\n\t}\n\n\tfor (const nodeId of allNodeIds) {\n\t\tif (!visited.has(nodeId)) {\n\t\t\tdetectCycleUtil(nodeId, [])\n\t\t}\n\t}\n\n\treturn cycles\n}\n\n/**\n * Generates Mermaid diagram syntax from a WorkflowBlueprint\n * @param blueprint The WorkflowBlueprint object containing nodes and edges\n * @returns Mermaid syntax string for the flowchart\n */\nexport function generateMermaid(blueprint: WorkflowBlueprint): string {\n\tif (!blueprint || !blueprint.nodes || blueprint.nodes.length === 0) {\n\t\treturn 'flowchart TD\\n empty[Empty Blueprint]'\n\t}\n\n\tlet mermaid = 'flowchart TD\\n'\n\n\t// Add nodes\n\tfor (const node of blueprint.nodes) {\n\t\tconst nodeLabel = node.id\n\t\tmermaid += ` ${node.id}[\"${nodeLabel}\"]\\n`\n\t}\n\n\t// Add edges\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}\n\t\telse {\n\t\t\tmermaid += ` ${edge.source} --> ${edge.target}\\n`\n\t\t}\n\t}\n\n\treturn mermaid\n}\n\n/**\n * Analyzes a workflow blueprint and returns comprehensive analysis\n * @param blueprint The WorkflowBlueprint object containing nodes and edges\n * @returns Analysis result with cycles, start nodes, terminal nodes, and other metrics\n */\nexport function analyzeBlueprint(blueprint: WorkflowBlueprint): BlueprintAnalysis {\n\tif (!blueprint || !blueprint.nodes || blueprint.nodes.length === 0) {\n\t\treturn {\n\t\t\tcycles: [],\n\t\t\tstartNodeIds: [],\n\t\t\tterminalNodeIds: [],\n\t\t\tnodeCount: 0,\n\t\t\tedgeCount: 0,\n\t\t\tisDag: true,\n\t\t}\n\t}\n\n\tconst cycles = checkForCycles(blueprint)\n\tconst nodeCount = blueprint.nodes.length\n\tconst edgeCount = blueprint.edges?.length || 0\n\n\t// Find nodes with no incoming edges (start nodes)\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\t// Find nodes with no outgoing edges (terminal nodes)\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"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/context.ts"],"names":[],"mappings":";AAKO,IAAM,UAAN,MAAsF;AAAA,EAC5E,IAAA,GAAO,MAAA;AAAA,EACf,IAAA;AAAA,EAER,WAAA,CAAY,WAAA,GAAiC,EAAC,EAAG;AAChD,IAAA,IAAA,CAAK,OAAO,IAAI,GAAA,CAAI,MAAA,CAAO,OAAA,CAAQ,WAAW,CAAC,CAAA;AAAA,EAChD;AAAA,EAEA,IAA8B,GAAA,EAAiC;AAC9D,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,EACjC;AAAA,EAEA,GAAA,CAA8B,KAAQ,KAAA,EAA0B;AAC/D,IAAA,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,GAAG,GAAG,KAAK,CAAA;AAAA,EACjC;AAAA,EAEA,IAAI,GAAA,EAA8B;AACjC,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,EACjC;AAAA,EAEA,OAAO,GAAA,EAA8B;AACpC,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,EACpC;AAAA,EAEA,MAAA,GAA8B;AAC7B,IAAA,OAAO,MAAA,CAAO,WAAA,CAAY,IAAA,CAAK,IAAI,CAAA;AAAA,EACpC;AACD;AAMO,IAAM,mBAAN,MAAgG;AAAA,EAGtG,YAAoB,WAAA,EAAqC;AAArC,IAAA,IAAA,CAAA,WAAA,GAAA,WAAA;AAAA,EAAuC;AAAA,EAF3C,IAAA,GAAO,OAAA;AAAA,EAIvB,IAA8B,GAAA,EAA0C;AACvE,IAAA,OAAO,QAAQ,OAAA,CAAQ,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,GAAG,CAAC,CAAA;AAAA,EACjD;AAAA,EAEA,GAAA,CAA8B,KAAQ,KAAA,EAAmC;AACxE,IAAA,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,GAAA,EAAK,KAAK,CAAA;AAC/B,IAAA,OAAO,QAAQ,OAAA,EAAQ;AAAA,EACxB;AAAA,EAEA,IAAI,GAAA,EAAuC;AAC1C,IAAA,OAAO,QAAQ,OAAA,CAAQ,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,GAAG,CAAC,CAAA;AAAA,EACjD;AAAA,EAEA,OAAO,GAAA,EAAuC;AAC7C,IAAA,OAAO,QAAQ,OAAA,CAAQ,IAAA,CAAK,WAAA,CAAY,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,EACpD;AAAA,EAEA,MAAA,GAAuC;AACtC,IAAA,OAAO,OAAA,CAAQ,OAAA,CAAQ,IAAA,CAAK,WAAA,CAAY,QAAQ,CAAA;AAAA,EACjD;AACD","file":"chunk-MICPMOTW.js","sourcesContent":["import type { IAsyncContext, ISyncContext } from './types'\n\n/**\n * A default, high-performance, in-memory implementation of ISyncContext using a Map.\n */\nexport class Context<TContext extends Record<string, any>> implements ISyncContext<TContext> {\n\tpublic readonly type = 'sync' as const\n\tprivate data: Map<string, any>\n\n\tconstructor(initialData: Partial<TContext> = {}) {\n\t\tthis.data = new Map(Object.entries(initialData))\n\t}\n\n\tget<K extends keyof TContext>(key: K): TContext[K] | undefined {\n\t\treturn this.data.get(String(key))\n\t}\n\n\tset<K extends keyof TContext>(key: K, value: TContext[K]): void {\n\t\tthis.data.set(String(key), value)\n\t}\n\n\thas(key: keyof TContext): boolean {\n\t\treturn this.data.has(String(key))\n\t}\n\n\tdelete(key: keyof TContext): boolean {\n\t\treturn this.data.delete(String(key))\n\t}\n\n\ttoJSON(): Record<string, any> {\n\t\treturn Object.fromEntries(this.data)\n\t}\n}\n\n/**\n * An adapter that provides a consistent, Promise-based view of a synchronous context.\n * This is created by the runtime and is transparent to the node author.\n */\nexport class AsyncContextView<TContext extends Record<string, any>> implements IAsyncContext<TContext> {\n\tpublic readonly type = 'async' as const\n\n\tconstructor(private syncContext: ISyncContext<TContext>) { }\n\n\tget<K extends keyof TContext>(key: K): Promise<TContext[K] | undefined> {\n\t\treturn Promise.resolve(this.syncContext.get(key))\n\t}\n\n\tset<K extends keyof TContext>(key: K, value: TContext[K]): Promise<void> {\n\t\tthis.syncContext.set(key, value)\n\t\treturn Promise.resolve()\n\t}\n\n\thas(key: keyof TContext): Promise<boolean> {\n\t\treturn Promise.resolve(this.syncContext.has(key))\n\t}\n\n\tdelete(key: keyof TContext): 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"]}
@@ -1,106 +0,0 @@
1
- import { FlowRuntime } from './chunk-RYTIQZIB.js';
2
- import { JsonSerializer } from './chunk-REH55ZXV.js';
3
-
4
- // src/runtime/adapter.ts
5
- var BaseDistributedAdapter = class {
6
- runtime;
7
- store;
8
- serializer;
9
- constructor(options) {
10
- this.runtime = new FlowRuntime(options.runtimeOptions);
11
- this.store = options.coordinationStore;
12
- this.serializer = options.runtimeOptions.serializer || new JsonSerializer();
13
- console.log("[Adapter] BaseDistributedAdapter initialized.");
14
- }
15
- /**
16
- * Starts the worker, which begins listening for and processing jobs from the queue.
17
- */
18
- start() {
19
- console.log("[Adapter] Starting worker...");
20
- this.processJobs(this.handleJob.bind(this));
21
- }
22
- /**
23
- * The main handler for processing a single job from the queue.
24
- */
25
- async handleJob(job) {
26
- const { runId, blueprintId, nodeId } = job;
27
- const blueprint = (this.runtime.options.blueprints || {})[blueprintId];
28
- if (!blueprint) {
29
- const reason = `Blueprint with ID '${blueprintId}' not found in the worker's runtime registry.`;
30
- console.error(`[Adapter] FATAL: ${reason}`);
31
- await this.publishFinalResult(runId, { status: "failed", reason });
32
- return;
33
- }
34
- const context = this.createContext(runId);
35
- const mockState = {
36
- getContext: () => context,
37
- markFallbackExecuted: () => {
38
- },
39
- addError: (nodeId2, error) => {
40
- console.error(`[Adapter] Error in node ${nodeId2}:`, error);
41
- }
42
- };
43
- try {
44
- const result = await this.runtime.executeNode(blueprint, nodeId, mockState);
45
- await context.set(nodeId, result.output);
46
- const nodeDef = blueprint.nodes.find((n) => n.id === nodeId);
47
- if (nodeDef?.uses === "output") {
48
- console.log(`[Adapter] \u2705 Output node '${nodeId}' finished. Declaring workflow complete for Run ID: ${runId}`);
49
- const finalContext = await context.toJSON();
50
- const finalResult = {
51
- context: finalContext,
52
- serializedContext: this.serializer.serialize(finalContext),
53
- status: "completed"
54
- };
55
- await this.publishFinalResult(runId, { status: "completed", payload: finalResult });
56
- return;
57
- }
58
- const nextNodes = await this.runtime.determineNextNodes(blueprint, nodeId, result, context);
59
- if (nextNodes.length === 0) {
60
- console.log(`[Adapter] Terminal node '${nodeId}' reached for Run ID '${runId}', but it was not an 'output' node. This branch will now terminate.`);
61
- return;
62
- }
63
- for (const { node: nextNodeDef, edge } of nextNodes) {
64
- await this.runtime.applyEdgeTransform(edge, result, nextNodeDef, context);
65
- const isReady = await this.isReadyForFanIn(runId, blueprint, nextNodeDef.id);
66
- if (isReady) {
67
- console.log(`[Adapter] Node '${nextNodeDef.id}' is ready. Enqueuing job.`);
68
- await this.enqueueJob({ runId, blueprintId, nodeId: nextNodeDef.id });
69
- } else {
70
- console.log(`[Adapter] Node '${nextNodeDef.id}' is waiting for other predecessors to complete.`);
71
- }
72
- }
73
- } catch (error) {
74
- const reason = error.message || "Unknown execution error";
75
- console.error(`[Adapter] FATAL: Job for node '${nodeId}' failed for Run ID '${runId}': ${reason}`);
76
- await this.publishFinalResult(runId, { status: "failed", reason });
77
- }
78
- }
79
- /**
80
- * Encapsulates the fan-in join logic using the coordination store.
81
- */
82
- async isReadyForFanIn(runId, blueprint, targetNodeId) {
83
- const targetNode = blueprint.nodes.find((n) => n.id === targetNodeId);
84
- const joinStrategy = targetNode.config?.joinStrategy || "all";
85
- const predecessors = blueprint.edges.filter((e) => e.target === targetNodeId);
86
- if (predecessors.length <= 1) {
87
- return true;
88
- }
89
- if (joinStrategy === "any") {
90
- const lockKey = `flowcraft:joinlock:${runId}:${targetNodeId}`;
91
- return await this.store.setIfNotExist(lockKey, "locked", 3600);
92
- } else {
93
- const fanInKey = `flowcraft:fanin:${runId}:${targetNodeId}`;
94
- const readyCount = await this.store.increment(fanInKey, 3600);
95
- if (readyCount >= predecessors.length) {
96
- await this.store.delete(fanInKey);
97
- return true;
98
- }
99
- return false;
100
- }
101
- }
102
- };
103
-
104
- export { BaseDistributedAdapter };
105
- //# sourceMappingURL=chunk-NPAJNLXQ.js.map
106
- //# sourceMappingURL=chunk-NPAJNLXQ.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/runtime/adapter.ts"],"names":["nodeId"],"mappings":"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","file":"chunk-NPAJNLXQ.js","sourcesContent":["import type { IAsyncContext, ISerializer, RuntimeOptions, WorkflowBlueprint, WorkflowResult } from '../types'\nimport { JsonSerializer } from '../serializer'\nimport { FlowRuntime } from './runtime'\n\n/**\n * Defines the contract for an atomic, distributed key-value store required by\n * the adapter for coordination tasks like fan-in joins and locking.\n */\nexport interface ICoordinationStore {\n\t/** Atomically increments a key and returns the new value. Ideal for 'all' joins. */\n\tincrement: (key: string, ttlSeconds: number) => Promise<number>\n\t/** Sets a key only if it does not already exist. Ideal for 'any' joins (locking). */\n\tsetIfNotExist: (key: string, value: string, ttlSeconds: number) => Promise<boolean>\n\t/** Deletes a key. Used for cleanup. */\n\tdelete: (key: string) => Promise<void>\n}\n\n/** Configuration options for constructing a BaseDistributedAdapter. */\nexport interface AdapterOptions {\n\truntimeOptions: RuntimeOptions<any>\n\tcoordinationStore: ICoordinationStore\n}\n\n/** The data payload expected for a job in the queue. */\nexport interface JobPayload {\n\trunId: string\n\tblueprintId: string\n\tnodeId: string\n}\n\n/**\n * The base class for all distributed adapters. It handles the technology-agnostic\n * orchestration logic and leaves queue-specific implementation to subclasses.\n */\nexport abstract class BaseDistributedAdapter {\n\tprotected readonly runtime: FlowRuntime<any, any>\n\tprotected readonly store: ICoordinationStore\n\tprotected readonly serializer: ISerializer\n\n\tconstructor(options: AdapterOptions) {\n\t\tthis.runtime = new FlowRuntime(options.runtimeOptions)\n\t\tthis.store = options.coordinationStore\n\t\tthis.serializer = options.runtimeOptions.serializer || new JsonSerializer()\n\t\tconsole.log('[Adapter] BaseDistributedAdapter initialized.')\n\t}\n\n\t/**\n\t * Starts the worker, which begins listening for and processing jobs from the queue.\n\t */\n\tpublic start(): void {\n\t\tconsole.log('[Adapter] Starting worker...')\n\t\tthis.processJobs(this.handleJob.bind(this))\n\t}\n\n\t/**\n\t * Creates a technology-specific distributed context for a given workflow run.\n\t * @param runId The unique ID for the workflow execution.\n\t */\n\tprotected abstract createContext(runId: string): IAsyncContext<Record<string, any>>\n\t/**\n\t * Sets up the listener for the message queue. The implementation should call the\n\t * provided `handler` function for each new job received.\n\t * @param handler The core logic to execute for each job.\n\t */\n\tprotected abstract processJobs(handler: (job: JobPayload) => Promise<void>): void\n\n\t/**\n\t * Enqueues a new job onto the message queue.\n\t * @param job The payload for the job to be enqueued.\n\t */\n\tprotected abstract enqueueJob(job: JobPayload): Promise<void>\n\n\t/**\n\t * Publishes the final result of a completed or failed workflow run.\n\t * @param runId The unique ID of the workflow run.\n\t * @param result The final status and payload of the workflow.\n\t */\n\tprotected abstract publishFinalResult(runId: string, result: { status: 'completed' | 'failed', payload?: WorkflowResult, reason?: string }): Promise<void>\n\n\t/**\n\t * The main handler for processing a single job from the queue.\n\t */\n\tprivate async handleJob(job: JobPayload): Promise<void> {\n\t\tconst { runId, blueprintId, nodeId } = job\n\n\t\tconst blueprint = (this.runtime.options.blueprints || {})[blueprintId]\n\t\tif (!blueprint) {\n\t\t\tconst reason = `Blueprint with ID '${blueprintId}' not found in the worker's runtime registry.`\n\t\t\tconsole.error(`[Adapter] FATAL: ${reason}`)\n\t\t\tawait this.publishFinalResult(runId, { status: 'failed', reason })\n\t\t\treturn\n\t\t}\n\n\t\tconst context = this.createContext(runId)\n\t\tconst mockState = {\n\t\t\tgetContext: () => context,\n\t\t\tmarkFallbackExecuted: () => { },\n\t\t\taddError: (nodeId: string, error: Error) => {\n\t\t\t\tconsole.error(`[Adapter] Error in node ${nodeId}:`, error)\n\t\t\t},\n\t\t} as any\n\n\t\ttry {\n\t\t\tconst result = await this.runtime.executeNode(blueprint, nodeId, mockState)\n\t\t\tawait context.set(nodeId as any, result.output)\n\n\t\t\tconst nodeDef = blueprint.nodes.find(n => n.id === nodeId)\n\t\t\t// Convention: The workflow is considered complete when the first 'output' node finishes.\n\t\t\tif (nodeDef?.uses === 'output') {\n\t\t\t\tconsole.log(`[Adapter] ✅ Output node '${nodeId}' finished. Declaring workflow complete for Run ID: ${runId}`)\n\t\t\t\tconst finalContext = await context.toJSON()\n\t\t\t\tconst finalResult: WorkflowResult = {\n\t\t\t\t\tcontext: finalContext,\n\t\t\t\t\tserializedContext: this.serializer.serialize(finalContext),\n\t\t\t\t\tstatus: 'completed',\n\t\t\t\t}\n\t\t\t\tawait this.publishFinalResult(runId, { status: 'completed', payload: finalResult })\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst nextNodes = await this.runtime.determineNextNodes(blueprint, nodeId, result, context)\n\n\t\t\t// If a branch terminates but it wasn't an 'output' node, just stop.\n\t\t\tif (nextNodes.length === 0) {\n\t\t\t\tconsole.log(`[Adapter] Terminal node '${nodeId}' reached for Run ID '${runId}', but it was not an 'output' node. This branch will now terminate.`)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tfor (const { node: nextNodeDef, edge } of nextNodes) {\n\t\t\t\tawait this.runtime.applyEdgeTransform(edge, result, nextNodeDef, context)\n\t\t\t\tconst isReady = await this.isReadyForFanIn(runId, blueprint, nextNodeDef.id)\n\t\t\t\tif (isReady) {\n\t\t\t\t\tconsole.log(`[Adapter] Node '${nextNodeDef.id}' is ready. Enqueuing job.`)\n\t\t\t\t\tawait this.enqueueJob({ runId, blueprintId, nodeId: nextNodeDef.id })\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tconsole.log(`[Adapter] Node '${nextNodeDef.id}' is waiting for other predecessors to complete.`)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcatch (error: any) {\n\t\t\tconst reason = error.message || 'Unknown execution error'\n\t\t\tconsole.error(`[Adapter] FATAL: Job for node '${nodeId}' failed for Run ID '${runId}': ${reason}`)\n\t\t\tawait this.publishFinalResult(runId, { status: 'failed', reason })\n\t\t}\n\t}\n\n\t/**\n\t * Encapsulates the fan-in join logic using the coordination store.\n\t */\n\tprivate async isReadyForFanIn(runId: string, blueprint: WorkflowBlueprint, targetNodeId: string): Promise<boolean> {\n\t\tconst targetNode = blueprint.nodes.find(n => n.id === targetNodeId)!\n\t\tconst joinStrategy = targetNode.config?.joinStrategy || 'all'\n\t\tconst predecessors = blueprint.edges.filter(e => e.target === targetNodeId)\n\n\t\tif (predecessors.length <= 1) {\n\t\t\treturn true\n\t\t}\n\n\t\tif (joinStrategy === 'any') {\n\t\t\tconst lockKey = `flowcraft:joinlock:${runId}:${targetNodeId}`\n\t\t\treturn await this.store.setIfNotExist(lockKey, 'locked', 3600)\n\t\t}\n\t\telse {\n\t\t\tconst fanInKey = `flowcraft:fanin:${runId}:${targetNodeId}`\n\t\t\tconst readyCount = await this.store.increment(fanInKey, 3600)\n\t\t\tif (readyCount >= predecessors.length) {\n\t\t\t\tawait this.store.delete(fanInKey)\n\t\t\t\treturn true\n\t\t\t}\n\t\t\treturn false\n\t\t}\n\t}\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/linter.ts"],"names":[],"mappings":"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","file":"chunk-RAZXOMZC.js","sourcesContent":["import type { NodeClass, NodeFunction, WorkflowBlueprint } from './types'\nimport { analyzeBlueprint } from './analysis'\n\nexport type LinterIssueCode = | 'INVALID_EDGE_SOURCE'\n\t| 'INVALID_EDGE_TARGET'\n\t| 'MISSING_NODE_IMPLEMENTATION'\n\t| 'ORPHAN_NODE'\n\nexport interface LinterIssue {\n\tcode: LinterIssueCode\n\tmessage: string\n\tnodeId?: string\n\trelatedId?: string\n}\n\nexport interface LinterResult {\n\tisValid: boolean\n\tissues: LinterIssue[]\n}\n\n/**\n * Statically analyzes a workflow blueprint against a registry of implementations\n * to find common errors before runtime.\n *\n * @param blueprint The WorkflowBlueprint to analyze.\n * @param registry A map of node implementations (functions or classes) to check against.\n * @returns A LinterResult object containing any issues found.\n */\nexport function lintBlueprint(\n\tblueprint: WorkflowBlueprint,\n\tregistry: Map<string, NodeFunction | NodeClass> | Record<string, NodeFunction | NodeClass>,\n): LinterResult {\n\tconst issues: LinterIssue[] = []\n\tconst nodeIds = new Set(blueprint.nodes.map(n => n.id))\n\tconst registryKeys = registry instanceof Map ? new Set(registry.keys()) : new Set(Object.keys(registry))\n\n\t// 1. Check for missing node implementations\n\tfor (const node of blueprint.nodes) {\n\t\tif (!node.uses.startsWith('batch-') && !node.uses.startsWith('loop-') && !registryKeys.has(node.uses)) {\n\t\t\tissues.push({\n\t\t\t\tcode: 'MISSING_NODE_IMPLEMENTATION',\n\t\t\t\tmessage: `Node implementation key '${node.uses}' is not found in the provided registry.`,\n\t\t\t\tnodeId: node.id,\n\t\t\t})\n\t\t}\n\t}\n\n\t// 2. Check for graph integrity (edges must point to valid nodes)\n\tfor (const edge of blueprint.edges || []) {\n\t\tif (!nodeIds.has(edge.source)) {\n\t\t\tissues.push({\n\t\t\t\tcode: 'INVALID_EDGE_SOURCE',\n\t\t\t\tmessage: `Edge source '${edge.source}' does not correspond to a valid node ID.`,\n\t\t\t\trelatedId: edge.target,\n\t\t\t})\n\t\t}\n\t\tif (!nodeIds.has(edge.target)) {\n\t\t\tissues.push({\n\t\t\t\tcode: 'INVALID_EDGE_TARGET',\n\t\t\t\tmessage: `Edge target '${edge.target}' does not correspond to a valid node ID.`,\n\t\t\t\trelatedId: edge.source,\n\t\t\t})\n\t\t}\n\t}\n\n\t// 3. Check for orphan nodes (not connected to the main graph)\n\tif (blueprint.nodes.length > 1) {\n\t\tconst analysis = analyzeBlueprint(blueprint)\n\t\tconst connectedNodes = new Set<string>()\n\t\tconst nodesToVisit = [...analysis.startNodeIds]\n\t\tconst visited = new Set<string>()\n\n\t\twhile (nodesToVisit.length > 0) {\n\t\t\tconst currentId = nodesToVisit.pop()!\n\t\t\tif (visited.has(currentId))\n\t\t\t\tcontinue\n\n\t\t\tvisited.add(currentId)\n\t\t\tconnectedNodes.add(currentId)\n\n\t\t\tblueprint.edges\n\t\t\t\t.filter(e => e.source === currentId)\n\t\t\t\t.forEach(e => nodesToVisit.push(e.target))\n\t\t}\n\n\t\tfor (const nodeId of nodeIds) {\n\t\t\tif (!connectedNodes.has(nodeId)) {\n\t\t\t\tissues.push({\n\t\t\t\t\tcode: 'ORPHAN_NODE',\n\t\t\t\t\tmessage: `Node '${nodeId}' is not reachable from any start node.`,\n\t\t\t\t\tnodeId,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\tisValid: issues.length === 0,\n\t\tissues,\n\t}\n}\n"]}
@@ -1,13 +0,0 @@
1
- // src/serializer.ts
2
- var JsonSerializer = class {
3
- serialize(data) {
4
- return JSON.stringify(data);
5
- }
6
- deserialize(text) {
7
- return JSON.parse(text);
8
- }
9
- };
10
-
11
- export { JsonSerializer };
12
- //# sourceMappingURL=chunk-REH55ZXV.js.map
13
- //# sourceMappingURL=chunk-REH55ZXV.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/serializer.ts"],"names":[],"mappings":";AASO,IAAM,iBAAN,MAA4C;AAAA,EAClD,UAAU,IAAA,EAAmC;AAC5C,IAAA,OAAO,IAAA,CAAK,UAAU,IAAI,CAAA;AAAA,EAC3B;AAAA,EAEA,YAAY,IAAA,EAAmC;AAC9C,IAAA,OAAO,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,EACvB;AACD","file":"chunk-REH55ZXV.js","sourcesContent":["import type { ISerializer } from './types'\n\n/**\n * A default serializer using standard JSON.\n *\n * @warning This implementation is lossy and does not handle complex data types\n * like `Date`, `Map`, `Set`, `undefined`, etc. It is recommended to provide a robust\n * serializer like `superjson` if working with complex data types.\n */\nexport class JsonSerializer implements ISerializer {\n\tserialize(data: Record<string, any>): string {\n\t\treturn JSON.stringify(data)\n\t}\n\n\tdeserialize(text: string): Record<string, any> {\n\t\treturn JSON.parse(text)\n\t}\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/runtime/traverser.ts"],"names":["nodeId"],"mappings":"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","file":"chunk-RW4FH7IL.js","sourcesContent":["import type { NodeResult, WorkflowBlueprint } from '../types'\nimport type { WorkflowState } from './state'\nimport type { IRuntime } from './types'\nimport { analyzeBlueprint } from '../analysis'\nimport { CancelledWorkflowError } from '../errors'\n\nexport class GraphTraverser<TContext extends Record<string, any>, TDependencies extends Record<string, any>> {\n\tprivate frontier = new Set<string>()\n\tprivate allPredecessors: Map<string, Set<string>>\n\tprivate dynamicBlueprint: WorkflowBlueprint\n\n\tconstructor(\n\t\tprivate blueprint: WorkflowBlueprint,\n\t\tprivate runtime: IRuntime<TContext, TDependencies>,\n\t\tprivate state: WorkflowState<TContext>,\n\t\tprivate functionRegistry: Map<string, any> | undefined,\n\t\tprivate executionId: string,\n\t\tprivate signal?: AbortSignal,\n\t) {\n\t\tthis.dynamicBlueprint = JSON.parse(JSON.stringify(blueprint)) as WorkflowBlueprint\n\t\tthis.allPredecessors = new Map<string, Set<string>>()\n\t\tthis.dynamicBlueprint.nodes.forEach(node => this.allPredecessors.set(node.id, new Set()))\n\t\tthis.dynamicBlueprint.edges.forEach(edge => this.allPredecessors.get(edge.target)?.add(edge.source))\n\t\tconst analysis = analyzeBlueprint(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 && this.runtime.options.strict !== true) {\n\t\t\tconst uniqueStartNodes = new Set<string>()\n\t\t\tfor (const cycle of analysis.cycles) {\n\t\t\t\tif (cycle.length > 0)\n\t\t\t\t\tuniqueStartNodes.add(cycle[0])\n\t\t\t}\n\t\t\tthis.frontier = new Set(uniqueStartNodes)\n\t\t}\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\tasync traverse(): Promise<void> {\n\t\ttry {\n\t\t\tthis.signal?.throwIfAborted()\n\t\t}\n\t\tcatch (error) {\n\t\t\tif (error instanceof DOMException && error.name === 'AbortError')\n\t\t\t\tthrow new CancelledWorkflowError('Workflow cancelled')\n\t\t\tthrow error\n\t\t}\n\t\tlet iterations = 0\n\t\tconst maxIterations = 10000\n\t\twhile (this.frontier.size > 0) {\n\t\t\tif (++iterations > maxIterations)\n\t\t\t\tthrow new Error('Traversal exceeded maximum iterations, possible infinite loop')\n\n\t\t\ttry {\n\t\t\t\tthis.signal?.throwIfAborted()\n\t\t\t\tconst currentJobs = Array.from(this.frontier)\n\t\t\t\tthis.frontier.clear()\n\t\t\t\tconst promises = currentJobs.map(nodeId =>\n\t\t\t\t\tthis.runtime\n\t\t\t\t\t\t.executeNode(this.dynamicBlueprint, nodeId, this.state, this.allPredecessors, this.functionRegistry, this.executionId, this.signal)\n\t\t\t\t\t\t.then((result: NodeResult) => ({ status: 'fulfilled' as const, value: { nodeId, result } }))\n\t\t\t\t\t\t.catch((error: unknown) => ({ status: 'rejected' as const, reason: { nodeId, error } })),\n\t\t\t\t)\n\t\t\t\tconst settledResults = await Promise.all(promises)\n\t\t\t\tconst completedThisTurn = new Set<string>()\n\t\t\t\tfor (const promiseResult of settledResults) {\n\t\t\t\t\tif (promiseResult.status === 'rejected') {\n\t\t\t\t\t\tconst { nodeId, error } = promiseResult.reason\n\t\t\t\t\t\tif (error instanceof CancelledWorkflowError)\n\t\t\t\t\t\t\tthrow error\n\t\t\t\t\t\tthis.state.addError(nodeId, error as Error)\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tconst { nodeId, result } = promiseResult.value\n\t\t\t\t\tthis.state.addCompletedNode(nodeId, result.output)\n\t\t\t\t\tcompletedThisTurn.add(nodeId)\n\t\t\t\t\tif (result._fallbackExecuted)\n\t\t\t\t\t\tthis.state.markFallbackExecuted()\n\t\t\t\t\tawait this.handleDynamicNodes(nodeId, result)\n\t\t\t\t\tif (!result._fallbackExecuted) {\n\t\t\t\t\t\tconst matched = await this.runtime.determineNextNodes(this.dynamicBlueprint, nodeId, result, this.state.getContext())\n\n\t\t\t\t\t\t// If one of the next nodes is a loop controller, prioritize it to avoid ambiguity from manual cycle edges.\n\t\t\t\t\t\tconst loopControllerMatch = matched.find(m => m.node.uses === 'loop-controller')\n\t\t\t\t\t\tconst finalMatched = loopControllerMatch ? [loopControllerMatch] : matched\n\n\t\t\t\t\t\tfor (const { node, edge } of finalMatched) {\n\t\t\t\t\t\t\tconst joinStrategy = node.config?.joinStrategy || 'all'\n\t\t\t\t\t\t\tif (joinStrategy !== 'any' && this.state.getCompletedNodes().has(node.id))\n\t\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t\tawait this.runtime.applyEdgeTransform(edge, result, node, this.state.getContext(), this.allPredecessors)\n\t\t\t\t\t\t\tconst requiredPredecessors = this.allPredecessors.get(node.id)!\n\t\t\t\t\t\t\tconst isReady = joinStrategy === 'any'\n\t\t\t\t\t\t\t\t? [...requiredPredecessors].some(p => completedThisTurn.has(p))\n\t\t\t\t\t\t\t\t: [...requiredPredecessors].every(p => this.state.getCompletedNodes().has(p))\n\t\t\t\t\t\t\tif (isReady)\n\t\t\t\t\t\t\t\tthis.frontier.add(node.id)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (matched.length === 0) {\n\t\t\t\t\t\t\tfor (const [potentialNextId, predecessors] of this.allPredecessors) {\n\t\t\t\t\t\t\t\tif (predecessors.has(nodeId) && !this.state.getCompletedNodes().has(potentialNextId)) {\n\t\t\t\t\t\t\t\t\tconst joinStrategy = this.dynamicBlueprint.nodes.find(n => n.id === potentialNextId)?.config?.joinStrategy || 'all'\n\t\t\t\t\t\t\t\t\tconst isReady = joinStrategy === 'any'\n\t\t\t\t\t\t\t\t\t\t? [...predecessors].some(p => completedThisTurn.has(p))\n\t\t\t\t\t\t\t\t\t\t: [...predecessors].every(p => this.state.getCompletedNodes().has(p))\n\t\t\t\t\t\t\t\t\tif (isReady)\n\t\t\t\t\t\t\t\t\t\tthis.frontier.add(potentialNextId)\n\t\t\t\t\t\t\t\t}\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\tcatch (error) {\n\t\t\t\tif (error instanceof DOMException && error.name === 'AbortError') {\n\t\t\t\t\tthrow new CancelledWorkflowError('Workflow cancelled')\n\t\t\t\t}\n\t\t\t\tthrow error\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async handleDynamicNodes(nodeId: string, result: NodeResult) {\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.allPredecessors.get(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\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)\n\t\t\t\tfallbackNodeIds.add(node.config.fallback)\n\t\t}\n\t\treturn fallbackNodeIds\n\t}\n\n\tgetDynamicBlueprint(): WorkflowBlueprint {\n\t\treturn this.dynamicBlueprint\n\t}\n}\n"]}