flowcraft 2.6.0 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/dist/adapters/index.d.ts +4 -0
  2. package/dist/adapters/index.js +4 -0
  3. package/dist/adapters/index.js.map +1 -0
  4. package/dist/adapters/persistent-event-bus.d.ts +69 -0
  5. package/dist/adapters/persistent-event-bus.js +3 -0
  6. package/dist/adapters/persistent-event-bus.js.map +1 -0
  7. package/dist/analysis.d.ts +1 -1
  8. package/dist/chunk-3Y5O5EGB.js +3 -0
  9. package/dist/{chunk-NVJ3ZO3P.js.map → chunk-3Y5O5EGB.js.map} +1 -1
  10. package/dist/{chunk-UXIASXSG.js → chunk-4TVWI6Y6.js} +5 -5
  11. package/dist/{chunk-UXIASXSG.js.map → chunk-4TVWI6Y6.js.map} +1 -1
  12. package/dist/{chunk-CYHZ2YVH.js → chunk-6RKHCJUU.js} +8 -3
  13. package/dist/chunk-6RKHCJUU.js.map +1 -0
  14. package/dist/{chunk-MUYLRTSR.js → chunk-7EBKWATZ.js} +9 -5
  15. package/dist/chunk-7EBKWATZ.js.map +1 -0
  16. package/dist/{chunk-7FIOROIR.js → chunk-AKDL2ZX7.js} +2 -2
  17. package/dist/{chunk-7FIOROIR.js.map → chunk-AKDL2ZX7.js.map} +1 -1
  18. package/dist/chunk-ASJYJ3NF.js +46 -0
  19. package/dist/chunk-ASJYJ3NF.js.map +1 -0
  20. package/dist/{chunk-FBPY44WL.js → chunk-H4JTZYIT.js} +3 -3
  21. package/dist/{chunk-FBPY44WL.js.map → chunk-H4JTZYIT.js.map} +1 -1
  22. package/dist/chunk-HFJXYY4E.js +3 -0
  23. package/dist/chunk-HFJXYY4E.js.map +1 -0
  24. package/dist/{chunk-SEI4Z3MO.js → chunk-HXSK5P2X.js} +12 -5
  25. package/dist/chunk-HXSK5P2X.js.map +1 -0
  26. package/dist/{chunk-JLDHCI2O.js → chunk-K6ID3GRG.js} +8 -8
  27. package/dist/chunk-K6ID3GRG.js.map +1 -0
  28. package/dist/{chunk-2ISKDTSN.js → chunk-LU5SLE3P.js} +4 -4
  29. package/dist/{chunk-2ISKDTSN.js.map → chunk-LU5SLE3P.js.map} +1 -1
  30. package/dist/{chunk-N4NLAIEN.js → chunk-LWN7HOD3.js} +4 -3
  31. package/dist/chunk-LWN7HOD3.js.map +1 -0
  32. package/dist/{chunk-HAZ26F3P.js → chunk-N63S5NEG.js} +20 -11
  33. package/dist/chunk-N63S5NEG.js.map +1 -0
  34. package/dist/{chunk-G53CSLBF.js → chunk-RAZWRNAJ.js} +5 -5
  35. package/dist/chunk-RAZWRNAJ.js.map +1 -0
  36. package/dist/{chunk-6MGLU3UU.js → chunk-RF5EYEO6.js} +4 -4
  37. package/dist/{chunk-6MGLU3UU.js.map → chunk-RF5EYEO6.js.map} +1 -1
  38. package/dist/chunk-TKSSRS5U.js +39 -0
  39. package/dist/chunk-TKSSRS5U.js.map +1 -0
  40. package/dist/{chunk-XTW36KQZ.js → chunk-TTOS7NW3.js} +6 -6
  41. package/dist/chunk-TTOS7NW3.js.map +1 -0
  42. package/dist/chunk-UNORA7EM.js +103 -0
  43. package/dist/chunk-UNORA7EM.js.map +1 -0
  44. package/dist/{chunk-OPRR4TAO.js → chunk-VDVUF25G.js} +69 -17
  45. package/dist/chunk-VDVUF25G.js.map +1 -0
  46. package/dist/{chunk-5BOUGXZO.js → chunk-VSKDQVCG.js} +16 -4
  47. package/dist/chunk-VSKDQVCG.js.map +1 -0
  48. package/dist/{chunk-5XPW6YEP.js → chunk-W4IAXDO4.js} +28 -6
  49. package/dist/chunk-W4IAXDO4.js.map +1 -0
  50. package/dist/{chunk-XDI4TJHA.js → chunk-ZETQCNEF.js} +49 -5
  51. package/dist/chunk-ZETQCNEF.js.map +1 -0
  52. package/dist/container-factory.d.ts +1 -1
  53. package/dist/container-factory.js +7 -7
  54. package/dist/context.d.ts +15 -2
  55. package/dist/context.js +1 -1
  56. package/dist/error-mapper.d.ts +1 -1
  57. package/dist/evaluator.d.ts +1 -1
  58. package/dist/flow.d.ts +3 -3
  59. package/dist/flow.js +1 -1
  60. package/dist/index.d.ts +3 -1
  61. package/dist/index.js +21 -18
  62. package/dist/linter.d.ts +1 -1
  63. package/dist/logger.d.ts +1 -1
  64. package/dist/node.d.ts +1 -1
  65. package/dist/nodes/batch-gather.d.ts +1 -1
  66. package/dist/nodes/batch-scatter.d.ts +1 -1
  67. package/dist/nodes/sleep.d.ts +1 -1
  68. package/dist/nodes/subflow.d.ts +1 -1
  69. package/dist/nodes/subflow.js +5 -5
  70. package/dist/nodes/wait.d.ts +1 -1
  71. package/dist/nodes/webhook.d.ts +1 -1
  72. package/dist/runtime/adapter.d.ts +3 -1
  73. package/dist/runtime/adapter.js +15 -15
  74. package/dist/runtime/execution-context.d.ts +1 -1
  75. package/dist/runtime/execution-context.js +3 -3
  76. package/dist/runtime/executors.d.ts +1 -1
  77. package/dist/runtime/index.d.ts +2 -1
  78. package/dist/runtime/index.js +17 -16
  79. package/dist/runtime/node-executor-factory.d.ts +1 -1
  80. package/dist/runtime/orchestrator.d.ts +1 -1
  81. package/dist/runtime/orchestrator.js +5 -5
  82. package/dist/runtime/orchestrators/replay.d.ts +45 -0
  83. package/dist/runtime/orchestrators/replay.js +3 -0
  84. package/dist/runtime/orchestrators/replay.js.map +1 -0
  85. package/dist/runtime/orchestrators/step-by-step.d.ts +1 -1
  86. package/dist/runtime/orchestrators/step-by-step.js +2 -2
  87. package/dist/runtime/orchestrators/utils.d.ts +1 -1
  88. package/dist/runtime/orchestrators/utils.js +1 -1
  89. package/dist/runtime/runtime.d.ts +1 -1
  90. package/dist/runtime/runtime.js +14 -14
  91. package/dist/runtime/scheduler.d.ts +1 -1
  92. package/dist/runtime/state.d.ts +1 -1
  93. package/dist/runtime/state.js +2 -2
  94. package/dist/runtime/traverser.d.ts +1 -1
  95. package/dist/runtime/traverser.js +1 -1
  96. package/dist/runtime/types.d.ts +1 -1
  97. package/dist/runtime/workflow-logic-handler.d.ts +2 -2
  98. package/dist/runtime/workflow-logic-handler.js +2 -2
  99. package/dist/sanitizer.d.ts +1 -1
  100. package/dist/sanitizer.js +1 -1
  101. package/dist/serializer.d.ts +1 -1
  102. package/dist/serializer.js +1 -1
  103. package/dist/testing/event-logger.d.ts +1 -1
  104. package/dist/testing/event-logger.js +1 -1
  105. package/dist/testing/index.d.ts +2 -1
  106. package/dist/testing/index.js +23 -20
  107. package/dist/testing/run-with-trace.d.ts +1 -1
  108. package/dist/testing/run-with-trace.js +19 -18
  109. package/dist/testing/stepper.d.ts +1 -1
  110. package/dist/testing/stepper.js +7 -7
  111. package/dist/{types-B-Drn84R.d.ts → types-D-dVKe4_.d.ts} +49 -6
  112. package/dist/types.d.ts +1 -1
  113. package/package.json +1 -1
  114. package/dist/chunk-5BOUGXZO.js.map +0 -1
  115. package/dist/chunk-5XPW6YEP.js.map +0 -1
  116. package/dist/chunk-CYHZ2YVH.js.map +0 -1
  117. package/dist/chunk-DSYAC4WB.js +0 -27
  118. package/dist/chunk-DSYAC4WB.js.map +0 -1
  119. package/dist/chunk-G53CSLBF.js.map +0 -1
  120. package/dist/chunk-HAZ26F3P.js.map +0 -1
  121. package/dist/chunk-JLDHCI2O.js.map +0 -1
  122. package/dist/chunk-MUYLRTSR.js.map +0 -1
  123. package/dist/chunk-N4NLAIEN.js.map +0 -1
  124. package/dist/chunk-NVJ3ZO3P.js +0 -3
  125. package/dist/chunk-OPRR4TAO.js.map +0 -1
  126. package/dist/chunk-SEI4Z3MO.js.map +0 -1
  127. package/dist/chunk-XDI4TJHA.js.map +0 -1
  128. package/dist/chunk-XTW36KQZ.js.map +0 -1
@@ -1,7 +1,7 @@
1
- import { StepByStepOrchestrator } from './chunk-G53CSLBF.js';
2
- import { GraphTraverser } from './chunk-FBPY44WL.js';
3
- import { ExecutionContext } from './chunk-N4NLAIEN.js';
4
- import { WorkflowState } from './chunk-5BOUGXZO.js';
1
+ import { StepByStepOrchestrator } from './chunk-RAZWRNAJ.js';
2
+ import { GraphTraverser } from './chunk-H4JTZYIT.js';
3
+ import { ExecutionContext } from './chunk-LWN7HOD3.js';
4
+ import { WorkflowState } from './chunk-VSKDQVCG.js';
5
5
 
6
6
  // src/testing/stepper.ts
7
7
  async function createStepper(runtime, blueprint, functionRegistry, initialState = {}) {
@@ -40,13 +40,13 @@ async function createStepper(runtime, blueprint, functionRegistry, initialState
40
40
  const previousStateData = runtime.serializer.deserialize(previousStateJson);
41
41
  state = new WorkflowState(previousStateData);
42
42
  traverser = GraphTraverser.fromState(_initialBlueprint, state);
43
- return state.toResult(runtime.serializer);
43
+ return state.toResult(runtime.serializer, void 0);
44
44
  },
45
45
  async next(options = {}) {
46
46
  if (stepper.isDone()) {
47
47
  return null;
48
48
  }
49
- const serializedContext = (await state.toResult(runtime.serializer)).serializedContext;
49
+ const serializedContext = (await state.toResult(runtime.serializer, void 0)).serializedContext;
50
50
  history.push(serializedContext);
51
51
  const executionContext = new ExecutionContext(
52
52
  _initialBlueprint,
@@ -72,5 +72,5 @@ async function createStepper(runtime, blueprint, functionRegistry, initialState
72
72
  }
73
73
 
74
74
  export { createStepper };
75
- //# sourceMappingURL=chunk-JLDHCI2O.js.map
76
- //# sourceMappingURL=chunk-JLDHCI2O.js.map
75
+ //# sourceMappingURL=chunk-K6ID3GRG.js.map
76
+ //# sourceMappingURL=chunk-K6ID3GRG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/testing/stepper.ts"],"names":[],"mappings":"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","file":"chunk-K6ID3GRG.js","sourcesContent":["import type { FlowRuntime } from '../runtime'\nimport { ExecutionContext } from '../runtime/execution-context'\nimport { StepByStepOrchestrator } from '../runtime/orchestrators/step-by-step'\nimport { WorkflowState } from '../runtime/state'\nimport { GraphTraverser } from '../runtime/traverser'\nimport type { NodeClass, NodeFunction, WorkflowBlueprint, WorkflowResult } from '../types'\n\n/**\n * Represents the controlled, step-by-step execution of a workflow.\n * Returned by the `createStepper` utility.\n */\nexport interface IWorkflowStepper<TContext extends Record<string, any>> {\n\t/** The current state of the workflow. Can be inspected after each step. */\n\treadonly state: WorkflowState<TContext>\n\n\t/** The graph traverser instance. Can be used to inspect the frontier or completed nodes. */\n\treadonly traverser: GraphTraverser\n\n\t/**\n\t * Executes the next \"turn\" or batch of ready nodes in the workflow.\n\t * @param options Optional configuration for this specific step, like a cancellation signal.\n\t * @returns A `WorkflowResult` representing the state after the step, or `null` if the workflow has already completed.\n\t */\n\tnext(options?: { signal?: AbortSignal; concurrency?: number }): Promise<WorkflowResult<TContext> | null>\n\n\t/**\n\t * Reverts the workflow to its previous state.\n\t * @returns The `WorkflowResult` of the previous state, or `null` if there is no history to revert to.\n\t */\n\tprev(): Promise<WorkflowResult<TContext> | null>\n\n\t/**\n\t * Resets the stepper to its initial state, clearing all progress and history.\n\t */\n\treset(): void\n\n\t/**\n\t * A convenience method to check if the workflow has any more steps to run.\n\t * @returns `true` if the workflow is complete or stalled, `false` otherwise.\n\t */\n\tisDone(): boolean\n}\n\n/**\n * A test utility that creates a stepper to execute a workflow one \"turn\" at a time.\n * This is invaluable for debugging and writing fine-grained tests where you need to\n * assert the state of the workflow after each logical step.\n *\n * @example\n * // In your test file\n * it('should correctly execute step-by-step', async () => {\n * const runtime = new FlowRuntime({ ... });\n * const flow = createFlow('test')\n * .node('a', async () => ({ output: 10 }))\n * .node('b', async ({ input }) => ({ output: input * 2 }))\n * .edge('a', 'b');\n *\n * const stepper = await createStepper(runtime, flow.toBlueprint(), flow.getFunctionRegistry());\n *\n * // First step (executes node 'a')\n * const result1 = await stepper.next();\n * expect(stepper.isDone()).toBe(false);\n * expect(result1.status).toBe('stalled');\n * expect(result1.context._outputs.a).toBe(10);\n *\n * // Second step (executes node 'b')\n * const result2 = await stepper.next();\n * expect(stepper.isDone()).toBe(true);\n * expect(result2.status).toBe('completed');\n * expect(result2.context._outputs.b).toBe(20);\n *\n * // Final step (no more work)\n * const result3 = await stepper.next();\n * expect(result3).toBeNull();\n * });\n *\n * @param runtime The `FlowRuntime` instance, used for its configuration.\n * @param blueprint The `WorkflowBlueprint` to execute.\n * @param functionRegistry The function registry from createFlow, containing the node implementations.\n * @param initialState The initial state for the workflow run.\n * @returns A Promise that resolves to an `IWorkflowStepper` instance.\n */\nexport async function createStepper<TContext extends Record<string, any>, TDependencies extends Record<string, any>>(\n\truntime: FlowRuntime<TContext, TDependencies>,\n\tblueprint: WorkflowBlueprint,\n\tfunctionRegistry: Map<string, NodeFunction | NodeClass>,\n\tinitialState: Partial<TContext> = {},\n): Promise<IWorkflowStepper<TContext>> {\n\tconst _initialBlueprint = structuredClone(blueprint)\n\tconst _initialState = structuredClone(initialState)\n\n\tlet state: WorkflowState<TContext>\n\tlet traverser: GraphTraverser\n\tconst history: string[] = []\n\n\tconst orchestrator = new StepByStepOrchestrator()\n\tconst executionId = globalThis.crypto?.randomUUID()\n\tconst nodeRegistry = new Map([...runtime.registry, ...functionRegistry])\n\n\tconst initialize = () => {\n\t\tstate = new WorkflowState<TContext>(_initialState)\n\t\ttraverser = new GraphTraverser(_initialBlueprint)\n\t\thistory.length = 0\n\t}\n\n\tinitialize()\n\n\tconst stepper: IWorkflowStepper<TContext> = {\n\t\tget state() {\n\t\t\treturn state\n\t\t},\n\t\tget traverser() {\n\t\t\treturn traverser\n\t\t},\n\t\tisDone() {\n\t\t\treturn !traverser.hasMoreWork() && !state.isAwaiting()\n\t\t},\n\t\treset() {\n\t\t\tinitialize()\n\t\t},\n\t\tasync prev() {\n\t\t\tconst previousStateJson = history.pop()\n\t\t\tif (!previousStateJson) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\tconst previousStateData = runtime.serializer.deserialize(previousStateJson) as Partial<TContext>\n\n\t\t\tstate = new WorkflowState(previousStateData)\n\t\t\ttraverser = GraphTraverser.fromState(_initialBlueprint, state)\n\n\t\t\treturn state.toResult(runtime.serializer, undefined)\n\t\t},\n\t\tasync next(options: { signal?: AbortSignal; concurrency?: number } = {}) {\n\t\t\tif (stepper.isDone()) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\tconst serializedContext = (await state.toResult(runtime.serializer, undefined)).serializedContext\n\t\t\thistory.push(serializedContext)\n\n\t\t\tconst executionContext = new ExecutionContext(\n\t\t\t\t_initialBlueprint,\n\t\t\t\tstate,\n\t\t\t\tnodeRegistry,\n\t\t\t\texecutionId,\n\t\t\t\truntime,\n\t\t\t\t{\n\t\t\t\t\tlogger: runtime.logger,\n\t\t\t\t\teventBus: runtime.eventBus,\n\t\t\t\t\tserializer: runtime.serializer,\n\t\t\t\t\tevaluator: runtime.evaluator,\n\t\t\t\t\tmiddleware: runtime.middleware,\n\t\t\t\t\tdependencies: runtime.dependencies,\n\t\t\t\t},\n\t\t\t\toptions.signal,\n\t\t\t\toptions.concurrency,\n\t\t\t)\n\t\t\treturn orchestrator.run(executionContext, traverser)\n\t\t},\n\t}\n\n\treturn stepper\n}\n"]}
@@ -1,6 +1,6 @@
1
- import { DefaultOrchestrator } from './chunk-XTW36KQZ.js';
1
+ import { DefaultOrchestrator } from './chunk-TTOS7NW3.js';
2
2
  import { NullLogger } from './chunk-4PELJWF7.js';
3
- import { JsonSerializer } from './chunk-CYHZ2YVH.js';
3
+ import { JsonSerializer } from './chunk-6RKHCJUU.js';
4
4
  import { DIContainer, ServiceTokens } from './chunk-WWGFIYKW.js';
5
5
  import { PropertyEvaluator } from './chunk-PH2IYZHV.js';
6
6
 
@@ -21,5 +21,5 @@ function createDefaultContainer(options = {}) {
21
21
  }
22
22
 
23
23
  export { createDefaultContainer };
24
- //# sourceMappingURL=chunk-2ISKDTSN.js.map
25
- //# sourceMappingURL=chunk-2ISKDTSN.js.map
24
+ //# sourceMappingURL=chunk-LU5SLE3P.js.map
25
+ //# sourceMappingURL=chunk-LU5SLE3P.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/container-factory.ts"],"names":[],"mappings":";;;;;;;AA4BO,SAAS,sBAAA,CACf,OAAA,GAA2C,EAAC,EAC9B;AACd,EAAA,MAAM,SAAA,GAAY,IAAI,WAAA,EAAY;AAElC,EAAA,SAAA,CAAU,SAAS,aAAA,CAAc,MAAA,EAAQ,QAAQ,MAAA,IAAU,IAAI,YAAY,CAAA;AAC3E,EAAA,SAAA,CAAU,SAAS,aAAA,CAAc,UAAA,EAAY,QAAQ,UAAA,IAAc,IAAI,gBAAgB,CAAA;AACvF,EAAA,SAAA,CAAU,SAAS,aAAA,CAAc,SAAA,EAAW,QAAQ,SAAA,IAAa,IAAI,mBAAmB,CAAA;AACxF,EAAA,SAAA,CAAU,SAAS,aAAA,CAAc,QAAA,EAAU,QAAQ,QAAA,IAAY,EAAE,MAAM,YAAY;AAAA,EAAC,GAAG,CAAA;AACvF,EAAA,SAAA,CAAU,SAAS,aAAA,CAAc,UAAA,EAAY,OAAA,CAAQ,UAAA,IAAc,EAAE,CAAA;AACrE,EAAA,SAAA,CAAU,SAAS,aAAA,CAAc,YAAA,EAAc,OAAA,CAAQ,QAAA,IAAY,EAAE,CAAA;AACrE,EAAA,SAAA,CAAU,SAAS,aAAA,CAAc,iBAAA,EAAmB,OAAA,CAAQ,UAAA,IAAc,EAAE,CAAA;AAC5E,EAAA,SAAA,CAAU,SAAS,aAAA,CAAc,YAAA,EAAc,OAAA,CAAQ,YAAA,IAAiB,EAAoB,CAAA;AAE5F,EAAA,SAAA,CAAU,gBAAgB,aAAA,CAAc,YAAA,EAAc,MAAM,IAAI,qBAAqB,CAAA;AAErF,EAAA,OAAO,SAAA;AACR","file":"chunk-2ISKDTSN.js","sourcesContent":["import { DIContainer, ServiceTokens } from './container'\nimport { PropertyEvaluator } from './evaluator'\nimport { NullLogger } from './logger'\nimport { DefaultOrchestrator } from './runtime/orchestrator'\nimport { JsonSerializer } from './serializer'\nimport type {\n\tIEvaluator,\n\tIEventBus,\n\tILogger,\n\tISerializer,\n\tMiddleware,\n\tNodeClass,\n\tNodeFunction,\n\tRuntimeDependencies,\n\tWorkflowBlueprint,\n} from './types'\n\nexport interface ContainerOptions<TDependencies extends RuntimeDependencies = RuntimeDependencies> {\n\tlogger?: ILogger\n\tserializer?: ISerializer\n\tevaluator?: IEvaluator\n\teventBus?: IEventBus\n\tmiddleware?: Middleware[]\n\tregistry?: Record<string, NodeFunction | NodeClass>\n\tblueprints?: Record<string, WorkflowBlueprint>\n\tdependencies?: TDependencies\n}\n\nexport function createDefaultContainer<TDependencies extends RuntimeDependencies = RuntimeDependencies>(\n\toptions: ContainerOptions<TDependencies> = {},\n): DIContainer {\n\tconst container = new DIContainer()\n\n\tcontainer.register(ServiceTokens.Logger, options.logger || new NullLogger())\n\tcontainer.register(ServiceTokens.Serializer, options.serializer || new JsonSerializer())\n\tcontainer.register(ServiceTokens.Evaluator, options.evaluator || new PropertyEvaluator())\n\tcontainer.register(ServiceTokens.EventBus, options.eventBus || { emit: async () => {} })\n\tcontainer.register(ServiceTokens.Middleware, options.middleware || [])\n\tcontainer.register(ServiceTokens.NodeRegistry, options.registry || {})\n\tcontainer.register(ServiceTokens.BlueprintRegistry, options.blueprints || {})\n\tcontainer.register(ServiceTokens.Dependencies, options.dependencies || ({} as TDependencies))\n\n\tcontainer.registerFactory(ServiceTokens.Orchestrator, () => new DefaultOrchestrator())\n\n\treturn container\n}\n"]}
1
+ {"version":3,"sources":["../src/container-factory.ts"],"names":[],"mappings":";;;;;;;AA4BO,SAAS,sBAAA,CACf,OAAA,GAA2C,EAAC,EAC9B;AACd,EAAA,MAAM,SAAA,GAAY,IAAI,WAAA,EAAY;AAElC,EAAA,SAAA,CAAU,SAAS,aAAA,CAAc,MAAA,EAAQ,QAAQ,MAAA,IAAU,IAAI,YAAY,CAAA;AAC3E,EAAA,SAAA,CAAU,SAAS,aAAA,CAAc,UAAA,EAAY,QAAQ,UAAA,IAAc,IAAI,gBAAgB,CAAA;AACvF,EAAA,SAAA,CAAU,SAAS,aAAA,CAAc,SAAA,EAAW,QAAQ,SAAA,IAAa,IAAI,mBAAmB,CAAA;AACxF,EAAA,SAAA,CAAU,SAAS,aAAA,CAAc,QAAA,EAAU,QAAQ,QAAA,IAAY,EAAE,MAAM,YAAY;AAAA,EAAC,GAAG,CAAA;AACvF,EAAA,SAAA,CAAU,SAAS,aAAA,CAAc,UAAA,EAAY,OAAA,CAAQ,UAAA,IAAc,EAAE,CAAA;AACrE,EAAA,SAAA,CAAU,SAAS,aAAA,CAAc,YAAA,EAAc,OAAA,CAAQ,QAAA,IAAY,EAAE,CAAA;AACrE,EAAA,SAAA,CAAU,SAAS,aAAA,CAAc,iBAAA,EAAmB,OAAA,CAAQ,UAAA,IAAc,EAAE,CAAA;AAC5E,EAAA,SAAA,CAAU,SAAS,aAAA,CAAc,YAAA,EAAc,OAAA,CAAQ,YAAA,IAAiB,EAAoB,CAAA;AAE5F,EAAA,SAAA,CAAU,gBAAgB,aAAA,CAAc,YAAA,EAAc,MAAM,IAAI,qBAAqB,CAAA;AAErF,EAAA,OAAO,SAAA;AACR","file":"chunk-LU5SLE3P.js","sourcesContent":["import { DIContainer, ServiceTokens } from './container'\nimport { PropertyEvaluator } from './evaluator'\nimport { NullLogger } from './logger'\nimport { DefaultOrchestrator } from './runtime/orchestrator'\nimport { JsonSerializer } from './serializer'\nimport type {\n\tIEvaluator,\n\tIEventBus,\n\tILogger,\n\tISerializer,\n\tMiddleware,\n\tNodeClass,\n\tNodeFunction,\n\tRuntimeDependencies,\n\tWorkflowBlueprint,\n} from './types'\n\nexport interface ContainerOptions<TDependencies extends RuntimeDependencies = RuntimeDependencies> {\n\tlogger?: ILogger\n\tserializer?: ISerializer\n\tevaluator?: IEvaluator\n\teventBus?: IEventBus\n\tmiddleware?: Middleware[]\n\tregistry?: Record<string, NodeFunction | NodeClass>\n\tblueprints?: Record<string, WorkflowBlueprint>\n\tdependencies?: TDependencies\n}\n\nexport function createDefaultContainer<TDependencies extends RuntimeDependencies = RuntimeDependencies>(\n\toptions: ContainerOptions<TDependencies> = {},\n): DIContainer {\n\tconst container = new DIContainer()\n\n\tcontainer.register(ServiceTokens.Logger, options.logger || new NullLogger())\n\tcontainer.register(ServiceTokens.Serializer, options.serializer || new JsonSerializer())\n\tcontainer.register(ServiceTokens.Evaluator, options.evaluator || new PropertyEvaluator())\n\tcontainer.register(ServiceTokens.EventBus, options.eventBus || { emit: async () => {} })\n\tcontainer.register(ServiceTokens.Middleware, options.middleware || [])\n\tcontainer.register(ServiceTokens.NodeRegistry, options.registry || {})\n\tcontainer.register(ServiceTokens.BlueprintRegistry, options.blueprints || {})\n\tcontainer.register(ServiceTokens.Dependencies, options.dependencies || ({} as TDependencies))\n\n\tcontainer.registerFactory(ServiceTokens.Orchestrator, () => new DefaultOrchestrator())\n\n\treturn container\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { WorkflowState } from './chunk-5BOUGXZO.js';
1
+ import { WorkflowState } from './chunk-VSKDQVCG.js';
2
2
 
3
3
  // src/runtime/execution-context.ts
4
4
  var ExecutionContext = class _ExecutionContext {
@@ -11,6 +11,7 @@ var ExecutionContext = class _ExecutionContext {
11
11
  this.services = services;
12
12
  this.signal = signal;
13
13
  this.concurrency = concurrency;
14
+ this.state.setEventEmitter(this.services.eventBus, this.executionId);
14
15
  }
15
16
  createForSubflow(subBlueprint, initialSubState) {
16
17
  const subState = new WorkflowState(initialSubState);
@@ -28,5 +29,5 @@ var ExecutionContext = class _ExecutionContext {
28
29
  };
29
30
 
30
31
  export { ExecutionContext };
31
- //# sourceMappingURL=chunk-N4NLAIEN.js.map
32
- //# sourceMappingURL=chunk-N4NLAIEN.js.map
32
+ //# sourceMappingURL=chunk-LWN7HOD3.js.map
33
+ //# sourceMappingURL=chunk-LWN7HOD3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime/execution-context.ts"],"names":[],"mappings":";;;AAkBO,IAAM,gBAAA,GAAN,MAAM,iBAAA,CAAkG;AAAA,EAC9G,WAAA,CACiB,WACA,KAAA,EACA,YAAA,EACA,aACA,OAAA,EACA,QAAA,EAQA,QACA,WAAA,EACf;AAfe,IAAA,IAAA,CAAA,SAAA,GAAA,SAAA;AACA,IAAA,IAAA,CAAA,KAAA,GAAA,KAAA;AACA,IAAA,IAAA,CAAA,YAAA,GAAA,YAAA;AACA,IAAA,IAAA,CAAA,WAAA,GAAA,WAAA;AACA,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AACA,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AAQA,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,WAAA,GAAA,WAAA;AAEhB,IAAA,IAAA,CAAK,MAAM,eAAA,CAAgB,IAAA,CAAK,QAAA,CAAS,QAAA,EAAU,KAAK,WAAW,CAAA;AAAA,EACpE;AAAA,EAEO,gBAAA,CACN,cACA,eAAA,EAC4C;AAC5C,IAAA,MAAM,QAAA,GAAW,IAAI,aAAA,CAAwB,eAAe,CAAA;AAC5D,IAAA,OAAO,IAAI,iBAAA;AAAA,MACV,YAAA;AAAA,MACA,QAAA;AAAA,MACA,IAAA,CAAK,YAAA;AAAA,MACL,IAAA,CAAK,WAAA;AAAA,MACL,IAAA,CAAK,OAAA;AAAA,MACL,IAAA,CAAK,QAAA;AAAA,MACL,IAAA,CAAK,MAAA;AAAA,MACL,IAAA,CAAK;AAAA,KACN;AAAA,EACD;AACD","file":"chunk-LWN7HOD3.js","sourcesContent":["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<TContext extends Record<string, any>, TDependencies extends RuntimeDependencies> {\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"]}
@@ -41,14 +41,16 @@ async function processResults(settledResults, traverser, state, runtime, _bluepr
41
41
  const { nodeId, executionResult } = promiseResult.value;
42
42
  if (executionResult.status === "success") {
43
43
  const result = executionResult.result;
44
- state.addCompletedNode(nodeId, result.output);
45
- if (result._fallbackExecuted) {
46
- state.markFallbackExecuted();
47
- }
48
- if (result.dynamicNodes && result.dynamicNodes.length > 0) {
49
- const gatherNodeId = result.output?.gatherNodeId;
50
- for (const dynamicNode of result.dynamicNodes) {
51
- traverser.addDynamicNode(dynamicNode.id, dynamicNode, nodeId, gatherNodeId);
44
+ if (result) {
45
+ state.addCompletedNode(nodeId, result.output);
46
+ if (result._fallbackExecuted) {
47
+ state.markFallbackExecuted();
48
+ }
49
+ if (result.dynamicNodes && result.dynamicNodes.length > 0) {
50
+ const gatherNodeId = result.output?.gatherNodeId;
51
+ for (const dynamicNode of result.dynamicNodes) {
52
+ traverser.addDynamicNode(dynamicNode.id, dynamicNode, nodeId, gatherNodeId);
53
+ }
52
54
  }
53
55
  }
54
56
  const matched = await runtime.determineNextNodes(
@@ -63,7 +65,14 @@ async function processResults(settledResults, traverser, state, runtime, _bluepr
63
65
  );
64
66
  const finalMatched = loopControllerMatch ? [loopControllerMatch] : matched;
65
67
  for (const { node, edge } of finalMatched) {
66
- await runtime.applyEdgeTransform(edge, result, node, state.getContext(), traverser.getAllPredecessors());
68
+ await runtime.applyEdgeTransform(
69
+ edge,
70
+ result,
71
+ node,
72
+ state.getContext(),
73
+ traverser.getAllPredecessors(),
74
+ executionId
75
+ );
67
76
  }
68
77
  traverser.markNodeCompleted(
69
78
  nodeId,
@@ -94,5 +103,5 @@ async function processResults(settledResults, traverser, state, runtime, _bluepr
94
103
  }
95
104
 
96
105
  export { executeBatch, processResults };
97
- //# sourceMappingURL=chunk-HAZ26F3P.js.map
98
- //# sourceMappingURL=chunk-HAZ26F3P.js.map
106
+ //# sourceMappingURL=chunk-N63S5NEG.js.map
107
+ //# sourceMappingURL=chunk-N63S5NEG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime/orchestrators/utils.ts"],"names":["nodeId"],"mappings":"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","file":"chunk-N63S5NEG.js","sourcesContent":["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\tstate.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\tconst loopControllerMatch = matched.find(\n\t\t\t\t(m: { node: NodeDefinition; edge: any }) => m.node.uses === 'loop-controller',\n\t\t\t)\n\t\t\tconst finalMatched = loopControllerMatch ? [loopControllerMatch] : matched\n\n\t\t\tfor (const { node, edge } of finalMatched) {\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\tfinalMatched.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(`Fallback node '${fallbackNodeId}' not found in blueprint.`, {\n\t\t\t\t\tnodeId,\n\t\t\t\t\tcause: error,\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(nodeId, { action: 'fallback', output: null, _fallbackExecuted: true }, [\n\t\t\t\t\tfallbackNodeDef,\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"]}
@@ -1,4 +1,4 @@
1
- import { executeBatch, processResults } from './chunk-HAZ26F3P.js';
1
+ import { executeBatch, processResults } from './chunk-N63S5NEG.js';
2
2
  import { FlowcraftError } from './chunk-BCRWXTWX.js';
3
3
 
4
4
  // src/runtime/orchestrators/step-by-step.ts
@@ -15,7 +15,7 @@ var StepByStepOrchestrator = class {
15
15
  if (!traverser.hasMoreWork()) {
16
16
  const isTraversalComplete2 = !traverser.hasMoreWork();
17
17
  const status2 = context.state.getStatus(isTraversalComplete2);
18
- const result2 = await context.state.toResult(context.services.serializer);
18
+ const result2 = await context.state.toResult(context.services.serializer, context.executionId);
19
19
  result2.status = status2;
20
20
  return result2;
21
21
  }
@@ -43,12 +43,12 @@ var StepByStepOrchestrator = class {
43
43
  }
44
44
  const isTraversalComplete = !traverser.hasMoreWork();
45
45
  const status = context.state.getStatus(isTraversalComplete);
46
- const result = await context.state.toResult(context.services.serializer);
46
+ const result = await context.state.toResult(context.services.serializer, context.executionId);
47
47
  result.status = status;
48
48
  return result;
49
49
  }
50
50
  };
51
51
 
52
52
  export { StepByStepOrchestrator };
53
- //# sourceMappingURL=chunk-G53CSLBF.js.map
54
- //# sourceMappingURL=chunk-G53CSLBF.js.map
53
+ //# sourceMappingURL=chunk-RAZWRNAJ.js.map
54
+ //# sourceMappingURL=chunk-RAZWRNAJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime/orchestrators/step-by-step.ts"],"names":["isTraversalComplete","status","result"],"mappings":";;;;AAeO,IAAM,yBAAN,MAAsD;AAAA,EAC5D,MAAa,GAAA,CAAI,OAAA,EAAqC,SAAA,EAAyD;AAC9G,IAAA,IAAI;AACH,MAAA,OAAA,CAAQ,QAAQ,cAAA,EAAe;AAAA,IAChC,SAAS,KAAA,EAAO;AACf,MAAA,IAAI,KAAA,YAAiB,YAAA,IAAgB,KAAA,CAAM,IAAA,KAAS,YAAA,EAAc;AACjE,QAAA,MAAM,IAAI,cAAA,CAAe,oBAAA,EAAsB,EAAE,OAAA,EAAS,OAAO,CAAA;AAAA,MAClE;AACA,MAAA,MAAM,KAAA;AAAA,IACP;AAEA,IAAA,IAAI,CAAC,SAAA,CAAU,WAAA,EAAY,EAAG;AAC7B,MAAA,MAAMA,oBAAAA,GAAsB,CAAC,SAAA,CAAU,WAAA,EAAY;AACnD,MAAA,MAAMC,OAAAA,GAAS,OAAA,CAAQ,KAAA,CAAM,SAAA,CAAUD,oBAAmB,CAAA;AAC1D,MAAA,MAAME,OAAAA,GAAS,MAAM,OAAA,CAAQ,KAAA,CAAM,SAAS,OAAA,CAAQ,QAAA,CAAS,UAAA,EAAY,OAAA,CAAQ,WAAW,CAAA;AAC5F,MAAAA,QAAO,MAAA,GAASD,OAAAA;AAChB,MAAA,OAAOC,OAAAA;AAAA,IACR;AAEA,IAAA,MAAM,aAAA,GAAgB,UAAU,aAAA,EAAc;AAC9C,IAAA,MAAM,cAAA,GAAiB,QAAQ,WAAA,GAAc,aAAA,CAAc,MAAM,CAAA,EAAG,OAAA,CAAQ,WAAW,CAAA,GAAI,aAAA;AAC3F,IAAA,MAAM,WAAA,GAAc,QAAQ,WAAA,GAAc,aAAA,CAAc,MAAM,OAAA,CAAQ,WAAW,IAAI,EAAC;AAEtF,IAAA,MAAM,iBAAiB,MAAM,YAAA;AAAA,MAC5B,cAAA;AAAA,MACA,UAAU,mBAAA,EAAoB;AAAA,MAC9B,OAAA,CAAQ,KAAA;AAAA,MACR,CAAC,MAAA,KAAmB,OAAA,CAAQ,OAAA,CAAQ,kBAAA,CAAmB,QAAQ,OAAO,CAAA;AAAA,MACtE,OAAA,CAAQ,OAAA;AAAA,MACR,OAAA,CAAQ;AAAA,KACT;AAEA,IAAA,MAAM,cAAA;AAAA,MACL,cAAA;AAAA,MACA,SAAA;AAAA,MACA,OAAA,CAAQ,KAAA;AAAA,MACR,OAAA,CAAQ,OAAA;AAAA,MACR,OAAA,CAAQ,SAAA;AAAA,MACR,OAAA,CAAQ;AAAA,KACT;AAEA,IAAA,KAAA,MAAW,EAAE,MAAA,EAAO,IAAK,WAAA,EAAa;AACrC,MAAA,SAAA,CAAU,cAAc,MAAM,CAAA;AAAA,IAC/B;AAEA,IAAA,MAAM,mBAAA,GAAsB,CAAC,SAAA,CAAU,WAAA,EAAY;AACnD,IAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,KAAA,CAAM,SAAA,CAAU,mBAAmB,CAAA;AAC1D,IAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,KAAA,CAAM,SAAS,OAAA,CAAQ,QAAA,CAAS,UAAA,EAAY,OAAA,CAAQ,WAAW,CAAA;AAC5F,IAAA,MAAA,CAAO,MAAA,GAAS,MAAA;AAChB,IAAA,OAAO,MAAA;AAAA,EACR;AACD","file":"chunk-RAZWRNAJ.js","sourcesContent":["import { FlowcraftError } from '../../errors'\n\nimport type { WorkflowResult } from '../../types'\nimport type { ExecutionContext } from '../execution-context'\nimport type { GraphTraverser } from '../traverser'\nimport type { IOrchestrator } from '../types'\nimport { executeBatch, processResults } from './utils'\n\n/**\n * An orchestrator that executes only one \"tick\" or \"turn\" of the workflow.\n * It processes a single batch of ready nodes from the frontier and then returns,\n * allowing the caller to inspect the intermediate state before proceeding.\n *\n * Useful for debugging, testing, or building interactive tools.\n */\nexport class StepByStepOrchestrator implements IOrchestrator {\n\tpublic async run(context: ExecutionContext<any, any>, traverser: GraphTraverser): Promise<WorkflowResult<any>> {\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\tif (!traverser.hasMoreWork()) {\n\t\t\tconst isTraversalComplete = !traverser.hasMoreWork()\n\t\t\tconst status = context.state.getStatus(isTraversalComplete)\n\t\t\tconst result = await context.state.toResult(context.services.serializer, context.executionId)\n\t\t\tresult.status = status\n\t\t\treturn result\n\t\t}\n\n\t\tconst allReadyNodes = traverser.getReadyNodes()\n\t\tconst nodesToExecute = context.concurrency ? allReadyNodes.slice(0, context.concurrency) : allReadyNodes\n\t\tconst nodesToSkip = context.concurrency ? allReadyNodes.slice(context.concurrency) : []\n\n\t\tconst settledResults = await executeBatch(\n\t\t\tnodesToExecute,\n\t\t\ttraverser.getDynamicBlueprint(),\n\t\t\tcontext.state,\n\t\t\t(nodeId: string) => context.runtime.getExecutorForNode(nodeId, context),\n\t\t\tcontext.runtime,\n\t\t\tcontext.concurrency,\n\t\t)\n\n\t\tawait processResults(\n\t\t\tsettledResults,\n\t\t\ttraverser,\n\t\t\tcontext.state,\n\t\t\tcontext.runtime,\n\t\t\tcontext.blueprint,\n\t\t\tcontext.executionId,\n\t\t)\n\n\t\tfor (const { nodeId } of nodesToSkip) {\n\t\t\ttraverser.addToFrontier(nodeId)\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(context.services.serializer, context.executionId)\n\t\tresult.status = status\n\t\treturn result\n\t}\n}\n"]}
@@ -1,5 +1,5 @@
1
- import { InMemoryEventLogger } from './chunk-MUYLRTSR.js';
2
- import { FlowRuntime } from './chunk-OPRR4TAO.js';
1
+ import { InMemoryEventLogger } from './chunk-7EBKWATZ.js';
2
+ import { FlowRuntime } from './chunk-VDVUF25G.js';
3
3
 
4
4
  // src/testing/run-with-trace.ts
5
5
  async function runWithTrace(runtime, blueprint, initialState = {}, options = {}) {
@@ -21,5 +21,5 @@ async function runWithTrace(runtime, blueprint, initialState = {}, options = {})
21
21
  }
22
22
 
23
23
  export { runWithTrace };
24
- //# sourceMappingURL=chunk-6MGLU3UU.js.map
25
- //# sourceMappingURL=chunk-6MGLU3UU.js.map
24
+ //# sourceMappingURL=chunk-RF5EYEO6.js.map
25
+ //# sourceMappingURL=chunk-RF5EYEO6.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/testing/run-with-trace.ts"],"names":[],"mappings":";;;;AA+BA,eAAsB,YAAA,CACrB,SACA,SAAA,EACA,YAAA,GAA2C,EAAC,EAC5C,OAAA,GAII,EAAC,EACJ;AACD,EAAA,MAAM,WAAA,GAAc,IAAI,mBAAA,EAAoB;AAC5C,EAAA,MAAM,WAAA,GAAc,IAAI,WAAA,CAAY;AAAA,IACnC,GAAG,OAAA,CAAQ,OAAA;AAAA,IACX,QAAA,EAAU;AAAA,GACV,CAAA;AAED,EAAA,IAAI;AACH,IAAA,MAAM,SAAS,MAAM,WAAA,CAAY,GAAA,CAAI,SAAA,EAAW,cAAc,OAAO,CAAA;AACrE,IAAA,IAAI,OAAA,CAAQ,IAAI,KAAA,EAAO;AACtB,MAAA,WAAA,CAAY,QAAA,CAAS,CAAA,kBAAA,EAAqB,SAAA,CAAU,EAAE,CAAA,CAAE,CAAA;AAAA,IACzD;AACA,IAAA,OAAO,MAAA;AAAA,EACR,SAAS,KAAA,EAAO;AACf,IAAA,WAAA,CAAY,QAAA,CAAS,CAAA,oBAAA,EAAuB,SAAA,CAAU,EAAE,CAAA,CAAE,CAAA;AAC1D,IAAA,MAAM,KAAA;AAAA,EACP;AACD","file":"chunk-6MGLU3UU.js","sourcesContent":["import { FlowRuntime } from '../runtime'\nimport type { WorkflowBlueprint } from '../types'\nimport { InMemoryEventLogger } from './event-logger'\n\n/**\n * A test helper that executes a workflow and automatically prints a detailed\n * execution trace to the console if the workflow fails.\n *\n * @example\n * // In your test file (e.g., my-workflow.test.ts)\n * it('should process data correctly', async () => {\n * const flow = createFlow('my-flow')\n * .node('a', async () => ({ output: 1 }))\n * .node('b', async ({ input }) => ({ output: input + 1 })) // Bug: returns { output: 3 }\n * .edge('a', 'b')\n *\n * const runtime = new FlowRuntime({})\n *\n * // If this test fails, a full, human-readable trace of the execution\n * // (inputs, outputs, context changes) is printed to the console.\n * const result = await runWithTrace(runtime, flow.toBlueprint())\n *\n * expect(result.context.b).toBe(2)\n * })\n *\n * @param runtime The original FlowRuntime instance (its options will be used).\n * @param blueprint The WorkflowBlueprint to execute.\n * @param initialState The initial state for the workflow run.\n * @param options Additional options for the run.\n * @returns The WorkflowResult if successful.\n */\nexport async function runWithTrace<TContext extends Record<string, any>>(\n\truntime: FlowRuntime<TContext, any>,\n\tblueprint: WorkflowBlueprint,\n\tinitialState: Partial<TContext> | string = {},\n\toptions: {\n\t\tfunctionRegistry?: Map<string, any>\n\t\tstrict?: boolean\n\t\tsignal?: AbortSignal\n\t} = {},\n) {\n\tconst eventLogger = new InMemoryEventLogger()\n\tconst testRuntime = new FlowRuntime({\n\t\t...runtime.options,\n\t\teventBus: eventLogger,\n\t})\n\n\ttry {\n\t\tconst result = await testRuntime.run(blueprint, initialState, options)\n\t\tif (process.env.DEBUG) {\n\t\t\teventLogger.printLog(`Successful Trace: ${blueprint.id}`)\n\t\t}\n\t\treturn result\n\t} catch (error) {\n\t\teventLogger.printLog(`Failing Test Trace: ${blueprint.id}`)\n\t\tthrow error\n\t}\n}\n"]}
1
+ {"version":3,"sources":["../src/testing/run-with-trace.ts"],"names":[],"mappings":";;;;AA+BA,eAAsB,YAAA,CACrB,SACA,SAAA,EACA,YAAA,GAA2C,EAAC,EAC5C,OAAA,GAII,EAAC,EACJ;AACD,EAAA,MAAM,WAAA,GAAc,IAAI,mBAAA,EAAoB;AAC5C,EAAA,MAAM,WAAA,GAAc,IAAI,WAAA,CAAY;AAAA,IACnC,GAAG,OAAA,CAAQ,OAAA;AAAA,IACX,QAAA,EAAU;AAAA,GACV,CAAA;AAED,EAAA,IAAI;AACH,IAAA,MAAM,SAAS,MAAM,WAAA,CAAY,GAAA,CAAI,SAAA,EAAW,cAAc,OAAO,CAAA;AACrE,IAAA,IAAI,OAAA,CAAQ,IAAI,KAAA,EAAO;AACtB,MAAA,WAAA,CAAY,QAAA,CAAS,CAAA,kBAAA,EAAqB,SAAA,CAAU,EAAE,CAAA,CAAE,CAAA;AAAA,IACzD;AACA,IAAA,OAAO,MAAA;AAAA,EACR,SAAS,KAAA,EAAO;AACf,IAAA,WAAA,CAAY,QAAA,CAAS,CAAA,oBAAA,EAAuB,SAAA,CAAU,EAAE,CAAA,CAAE,CAAA;AAC1D,IAAA,MAAM,KAAA;AAAA,EACP;AACD","file":"chunk-RF5EYEO6.js","sourcesContent":["import { FlowRuntime } from '../runtime'\nimport type { WorkflowBlueprint } from '../types'\nimport { InMemoryEventLogger } from './event-logger'\n\n/**\n * A test helper that executes a workflow and automatically prints a detailed\n * execution trace to the console if the workflow fails.\n *\n * @example\n * // In your test file (e.g., my-workflow.test.ts)\n * it('should process data correctly', async () => {\n * const flow = createFlow('my-flow')\n * .node('a', async () => ({ output: 1 }))\n * .node('b', async ({ input }) => ({ output: input + 1 })) // Bug: returns { output: 3 }\n * .edge('a', 'b')\n *\n * const runtime = new FlowRuntime({})\n *\n * // If this test fails, a full, human-readable trace of the execution\n * // (inputs, outputs, context changes) is printed to the console.\n * const result = await runWithTrace(runtime, flow.toBlueprint())\n *\n * expect(result.context.b).toBe(2)\n * })\n *\n * @param runtime The original FlowRuntime instance (its options will be used).\n * @param blueprint The WorkflowBlueprint to execute.\n * @param initialState The initial state for the workflow run.\n * @param options Additional options for the run.\n * @returns The WorkflowResult if successful.\n */\nexport async function runWithTrace<TContext extends Record<string, any>>(\n\truntime: FlowRuntime<TContext, any>,\n\tblueprint: WorkflowBlueprint,\n\tinitialState: Partial<TContext> | string = {},\n\toptions: {\n\t\tfunctionRegistry?: Map<string, any>\n\t\tstrict?: boolean\n\t\tsignal?: AbortSignal\n\t} = {},\n) {\n\tconst eventLogger = new InMemoryEventLogger()\n\tconst testRuntime = new FlowRuntime({\n\t\t...runtime.options,\n\t\teventBus: eventLogger,\n\t})\n\n\ttry {\n\t\tconst result = await testRuntime.run(blueprint, initialState, options)\n\t\tif (process.env.DEBUG) {\n\t\t\teventLogger.printLog(`Successful Trace: ${blueprint.id}`)\n\t\t}\n\t\treturn result\n\t} catch (error) {\n\t\teventLogger.printLog(`Failing Test Trace: ${blueprint.id}`)\n\t\tthrow error\n\t}\n}\n"]}
@@ -0,0 +1,39 @@
1
+ // src/sanitizer.ts
2
+ function sanitizeBlueprint(raw) {
3
+ let nodesArray = [];
4
+ if (Array.isArray(raw.nodes)) {
5
+ nodesArray = raw.nodes;
6
+ } else if (typeof raw.nodes === "object" && raw.nodes !== null) {
7
+ nodesArray = Object.values(raw.nodes);
8
+ }
9
+ const nodes = nodesArray.map((node) => ({
10
+ id: node.id,
11
+ uses: node.uses,
12
+ params: node.params,
13
+ inputs: node.inputs,
14
+ config: node.config
15
+ }));
16
+ let edgesArray = [];
17
+ if (Array.isArray(raw.edges)) {
18
+ edgesArray = raw.edges;
19
+ } else if (typeof raw.edges === "object" && raw.edges !== null) {
20
+ edgesArray = Object.values(raw.edges);
21
+ }
22
+ const edges = edgesArray.map((edge) => ({
23
+ source: edge.source,
24
+ target: edge.target,
25
+ action: edge.action,
26
+ condition: edge.condition,
27
+ transform: edge.transform
28
+ }));
29
+ return {
30
+ id: raw.id,
31
+ nodes,
32
+ edges,
33
+ metadata: raw.metadata
34
+ };
35
+ }
36
+
37
+ export { sanitizeBlueprint };
38
+ //# sourceMappingURL=chunk-TKSSRS5U.js.map
39
+ //# sourceMappingURL=chunk-TKSSRS5U.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/sanitizer.ts"],"names":[],"mappings":";AAOO,SAAS,kBAAkB,GAAA,EAA6B;AAC9D,EAAA,IAAI,aAAoB,EAAC;AACzB,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,GAAA,CAAI,KAAK,CAAA,EAAG;AAC7B,IAAA,UAAA,GAAa,GAAA,CAAI,KAAA;AAAA,EAClB,WAAW,OAAO,GAAA,CAAI,UAAU,QAAA,IAAY,GAAA,CAAI,UAAU,IAAA,EAAM;AAC/D,IAAA,UAAA,GAAa,MAAA,CAAO,MAAA,CAAO,GAAA,CAAI,KAAK,CAAA;AAAA,EACrC;AAEA,EAAA,MAAM,KAAA,GAA0B,UAAA,CAAW,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,CAAA;AAEF,EAAA,IAAI,aAAoB,EAAC;AACzB,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,GAAA,CAAI,KAAK,CAAA,EAAG;AAC7B,IAAA,UAAA,GAAa,GAAA,CAAI,KAAA;AAAA,EAClB,WAAW,OAAO,GAAA,CAAI,UAAU,QAAA,IAAY,GAAA,CAAI,UAAU,IAAA,EAAM;AAC/D,IAAA,UAAA,GAAa,MAAA,CAAO,MAAA,CAAO,GAAA,CAAI,KAAK,CAAA;AAAA,EACrC;AAEA,EAAA,MAAM,KAAA,GAA0B,UAAA,CAAW,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,CAAA;AAEF,EAAA,OAAO;AAAA,IACN,IAAI,GAAA,CAAI,EAAA;AAAA,IACR,KAAA;AAAA,IACA,KAAA;AAAA,IACA,UAAU,GAAA,CAAI;AAAA,GACf;AACD","file":"chunk-TKSSRS5U.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\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"]}
@@ -1,12 +1,12 @@
1
- import { executeBatch, processResults } from './chunk-HAZ26F3P.js';
2
- import { ExecutionContext } from './chunk-N4NLAIEN.js';
1
+ import { executeBatch, processResults } from './chunk-N63S5NEG.js';
2
+ import { ExecutionContext } from './chunk-LWN7HOD3.js';
3
3
  import { FlowcraftError } from './chunk-BCRWXTWX.js';
4
4
 
5
5
  // src/runtime/orchestrator.ts
6
6
  var DefaultOrchestrator = class {
7
7
  async run(context, traverser) {
8
8
  const hardwareConcurrency = globalThis.navigator?.hardwareConcurrency || 4;
9
- const maxConcurrency = context.concurrency ?? Math.min(hardwareConcurrency, 10);
9
+ const maxConcurrency = context.concurrency != null && context.concurrency > 0 ? context.concurrency : Math.min(hardwareConcurrency, 10);
10
10
  try {
11
11
  context.signal?.throwIfAborted();
12
12
  } catch (error) {
@@ -63,12 +63,12 @@ var DefaultOrchestrator = class {
63
63
  }
64
64
  const isTraversalComplete = !traverser.hasMoreWork();
65
65
  const status = context.state.getStatus(isTraversalComplete);
66
- const result = await context.state.toResult(context.services.serializer);
66
+ const result = await context.state.toResult(context.services.serializer, context.executionId);
67
67
  result.status = status;
68
68
  return result;
69
69
  }
70
70
  };
71
71
 
72
72
  export { DefaultOrchestrator };
73
- //# sourceMappingURL=chunk-XTW36KQZ.js.map
74
- //# sourceMappingURL=chunk-XTW36KQZ.js.map
73
+ //# sourceMappingURL=chunk-TTOS7NW3.js.map
74
+ //# sourceMappingURL=chunk-TTOS7NW3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime/orchestrator.ts"],"names":[],"mappings":";;;;;AAOO,IAAM,sBAAN,MAAmD;AAAA,EACzD,MAAM,GAAA,CAAI,OAAA,EAAqC,SAAA,EAAyD;AACvG,IAAA,MAAM,mBAAA,GAAsB,UAAA,CAAW,SAAA,EAAW,mBAAA,IAAuB,CAAA;AACzE,IAAA,MAAM,cAAA,GACL,OAAA,CAAQ,WAAA,IAAe,IAAA,IAAQ,OAAA,CAAQ,WAAA,GAAc,CAAA,GAAI,OAAA,CAAQ,WAAA,GAAc,IAAA,CAAK,GAAA,CAAI,mBAAA,EAAqB,EAAE,CAAA;AAEhH,IAAA,IAAI;AACH,MAAA,OAAA,CAAQ,QAAQ,cAAA,EAAe;AAAA,IAChC,SAAS,KAAA,EAAO;AACf,MAAA,IAAI,KAAA,YAAiB,YAAA,IAAgB,KAAA,CAAM,IAAA,KAAS,YAAA,EAAc;AACjE,QAAA,MAAM,IAAI,cAAA,CAAe,oBAAA,EAAsB,EAAE,OAAA,EAAS,OAAO,CAAA;AAAA,MAClE;AACA,MAAA,MAAM,KAAA;AAAA,IACP;AAEA,IAAA,IAAI,UAAA,GAAa,CAAA;AACjB,IAAA,MAAM,aAAA,GAAgB,GAAA;AAEtB,IAAA,OAAO,SAAA,CAAU,aAAY,EAAG;AAC/B,MAAA,IAAI,EAAE,aAAa,aAAA,EAAe;AACjC,QAAA,MAAM,IAAI,MAAM,+DAA+D,CAAA;AAAA,MAChF;AAEA,MAAA,IAAI;AACH,QAAA,OAAA,CAAQ,QAAQ,cAAA,EAAe;AAAA,MAChC,SAAS,KAAA,EAAO;AACf,QAAA,IAAI,KAAA,YAAiB,YAAA,IAAgB,KAAA,CAAM,IAAA,KAAS,YAAA,EAAc;AACjE,UAAA,MAAM,IAAI,cAAA,CAAe,oBAAA,EAAsB,EAAE,OAAA,EAAS,OAAO,CAAA;AAAA,QAClE;AACA,QAAA,MAAM,KAAA;AAAA,MACP;AAEA,MAAA,MAAM,UAAA,GAAa,UAAU,aAAA,EAAc;AAC3C,MAAA,MAAM,gBAAA,GAAmB,UAAU,mBAAA,EAAoB;AACvD,MAAA,MAAM,iBAAiB,IAAI,gBAAA;AAAA,QAC1B,gBAAA;AAAA,QACA,OAAA,CAAQ,KAAA;AAAA,QACR,OAAA,CAAQ,YAAA;AAAA,QACR,OAAA,CAAQ,WAAA;AAAA,QACR,OAAA,CAAQ,OAAA;AAAA,QACR,OAAA,CAAQ,QAAA;AAAA,QACR,OAAA,CAAQ,MAAA;AAAA,QACR,OAAA,CAAQ;AAAA,OACT;AACA,MAAA,MAAM,iBAAiB,MAAM,YAAA;AAAA,QAC5B,UAAA;AAAA,QACA,gBAAA;AAAA,QACA,OAAA,CAAQ,KAAA;AAAA,QACR,CAAC,MAAA,KAAmB,OAAA,CAAQ,OAAA,CAAQ,kBAAA,CAAmB,QAAQ,cAAc,CAAA;AAAA,QAC7E,OAAA,CAAQ,OAAA;AAAA,QACR;AAAA,OACD;AAEA,MAAA,MAAM,cAAA;AAAA,QACL,cAAA;AAAA,QACA,SAAA;AAAA,QACA,OAAA,CAAQ,KAAA;AAAA,QACR,OAAA,CAAQ,OAAA;AAAA,QACR,OAAA,CAAQ,SAAA;AAAA,QACR,OAAA,CAAQ;AAAA,OACT;AAEA,MAAA,IAAI,OAAA,CAAQ,KAAA,CAAM,UAAA,EAAW,EAAG;AAC/B,QAAA;AAAA,MACD;AAAA,IACD;AAEA,IAAA,MAAM,mBAAA,GAAsB,CAAC,SAAA,CAAU,WAAA,EAAY;AACnD,IAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,KAAA,CAAM,SAAA,CAAU,mBAAmB,CAAA;AAC1D,IAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,KAAA,CAAM,SAAS,OAAA,CAAQ,QAAA,CAAS,UAAA,EAAY,OAAA,CAAQ,WAAW,CAAA;AAC5F,IAAA,MAAA,CAAO,MAAA,GAAS,MAAA;AAChB,IAAA,OAAO,MAAA;AAAA,EACR;AACD","file":"chunk-TTOS7NW3.js","sourcesContent":["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(context: ExecutionContext<any, any>, traverser: GraphTraverser): Promise<WorkflowResult<any>> {\n\t\tconst hardwareConcurrency = globalThis.navigator?.hardwareConcurrency || 4\n\t\tconst maxConcurrency =\n\t\t\tcontext.concurrency != null && context.concurrency > 0 ? context.concurrency : 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(context.services.serializer, context.executionId)\n\t\tresult.status = status\n\t\treturn result\n\t}\n}\n"]}
@@ -0,0 +1,103 @@
1
+ // src/runtime/orchestrators/replay.ts
2
+ var ReplayOrchestrator = class {
3
+ /**
4
+ * Creates a new ReplayOrchestrator with a sequence of recorded workflow events.
5
+ *
6
+ * @param events - Array of FlowcraftEvent objects representing the recorded workflow execution
7
+ */
8
+ constructor(events) {
9
+ this.events = events;
10
+ }
11
+ /**
12
+ * Replays the recorded workflow events to reconstruct the workflow state.
13
+ *
14
+ * This method filters events for the specific execution, applies each event in sequence
15
+ * to rebuild the context state, and returns the final reconstructed workflow result.
16
+ * Replayed executions always have a "completed" status since they reconstruct the final state.
17
+ *
18
+ * @param context - The execution context containing state and services
19
+ * @param _traverser - Graph traverser (unused in replay mode)
20
+ * @returns Promise resolving to the reconstructed workflow result
21
+ */
22
+ async run(context, _traverser) {
23
+ const executionEvents = this.events.filter((event) => {
24
+ if ("executionId" in event.payload) {
25
+ return event.payload.executionId === context.executionId;
26
+ }
27
+ return false;
28
+ });
29
+ const fallbackMap = /* @__PURE__ */ new Map();
30
+ for (const event of executionEvents) {
31
+ await this.applyEvent(event, context, fallbackMap);
32
+ }
33
+ const includeExecutionId = executionEvents.length > 0;
34
+ const result = await context.state.toResult(
35
+ context.services.serializer,
36
+ includeExecutionId ? context.executionId : void 0
37
+ );
38
+ result.status = "completed";
39
+ return result;
40
+ }
41
+ /**
42
+ * Applies a single workflow event to reconstruct the execution state.
43
+ *
44
+ * This method handles different event types by updating the workflow state accordingly,
45
+ * including node completions, context changes, errors, fallbacks, and workflow control events.
46
+ *
47
+ * @param event - The workflow event to apply
48
+ * @param context - The execution context to update
49
+ * @param fallbackMap - Map tracking fallback node relationships (fallbackNodeId -> originalNodeId)
50
+ */
51
+ async applyEvent(event, context, fallbackMap) {
52
+ const { type, payload } = event;
53
+ switch (type) {
54
+ case "node:start":
55
+ break;
56
+ case "node:finish": {
57
+ const originalNodeId = fallbackMap.get(payload.nodeId);
58
+ if (originalNodeId) {
59
+ await context.state.addCompletedNode(originalNodeId, payload.result.output);
60
+ } else {
61
+ await context.state.addCompletedNode(payload.nodeId, payload.result.output);
62
+ }
63
+ break;
64
+ }
65
+ case "context:change":
66
+ if (payload.op === "set") {
67
+ await context.state.getContext().set(payload.key, payload.value);
68
+ } else if (payload.op === "delete") {
69
+ await context.state.getContext().delete(payload.key);
70
+ }
71
+ break;
72
+ case "node:error":
73
+ context.state.addError(payload.nodeId, payload.error);
74
+ break;
75
+ case "node:fallback":
76
+ fallbackMap.set(payload.fallback, payload.nodeId);
77
+ context.state.markFallbackExecuted();
78
+ break;
79
+ case "node:retry":
80
+ break;
81
+ case "edge:evaluate":
82
+ break;
83
+ case "workflow:stall":
84
+ case "workflow:pause":
85
+ if ("remainingNodes" in payload) {
86
+ for (let i = 0; i < payload.remainingNodes; i++) {
87
+ await context.state.markAsAwaiting(`node-${i}`);
88
+ }
89
+ }
90
+ break;
91
+ case "batch:start":
92
+ break;
93
+ case "batch:finish":
94
+ for (const _result of payload.results) {
95
+ }
96
+ break;
97
+ }
98
+ }
99
+ };
100
+
101
+ export { ReplayOrchestrator };
102
+ //# sourceMappingURL=chunk-UNORA7EM.js.map
103
+ //# sourceMappingURL=chunk-UNORA7EM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime/orchestrators/replay.ts"],"names":[],"mappings":"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","file":"chunk-UNORA7EM.js","sourcesContent":["import type { FlowcraftEvent, WorkflowResult } from '../../types'\nimport type { ExecutionContext } from '../execution-context'\nimport type { GraphTraverser } from '../traverser'\nimport type { IOrchestrator } from '../types'\n\n/**\n * An orchestrator that replays a pre-recorded sequence of workflow events\n * to reconstruct the workflow state without executing any node logic.\n *\n * This enables time-travel debugging by allowing developers to inspect\n * the exact state of a workflow at any point in its execution history.\n */\nexport class ReplayOrchestrator implements IOrchestrator {\n\t/**\n\t * Creates a new ReplayOrchestrator with a sequence of recorded workflow events.\n\t *\n\t * @param events - Array of FlowcraftEvent objects representing the recorded workflow execution\n\t */\n\tconstructor(private events: FlowcraftEvent[]) {}\n\n\t/**\n\t * Replays the recorded workflow events to reconstruct the workflow state.\n\t *\n\t * This method filters events for the specific execution, applies each event in sequence\n\t * to rebuild the context state, and returns the final reconstructed workflow result.\n\t * Replayed executions always have a \"completed\" status since they reconstruct the final state.\n\t *\n\t * @param context - The execution context containing state and services\n\t * @param _traverser - Graph traverser (unused in replay mode)\n\t * @returns Promise resolving to the reconstructed workflow result\n\t */\n\tasync run(context: ExecutionContext<any, any>, _traverser: GraphTraverser): Promise<WorkflowResult<any>> {\n\t\tconst executionEvents = this.events.filter((event) => {\n\t\t\tif ('executionId' in event.payload) {\n\t\t\t\treturn event.payload.executionId === context.executionId\n\t\t\t}\n\t\t\treturn false\n\t\t})\n\n\t\tconst fallbackMap = new Map<string, string>()\n\n\t\tfor (const event of executionEvents) {\n\t\t\tawait this.applyEvent(event, context, fallbackMap)\n\t\t}\n\n\t\tconst includeExecutionId = executionEvents.length > 0\n\t\tconst result = await context.state.toResult(\n\t\t\tcontext.services.serializer,\n\t\t\tincludeExecutionId ? context.executionId : undefined,\n\t\t)\n\t\tresult.status = 'completed'\n\t\treturn result\n\t}\n\n\t/**\n\t * Applies a single workflow event to reconstruct the execution state.\n\t *\n\t * This method handles different event types by updating the workflow state accordingly,\n\t * including node completions, context changes, errors, fallbacks, and workflow control events.\n\t *\n\t * @param event - The workflow event to apply\n\t * @param context - The execution context to update\n\t * @param fallbackMap - Map tracking fallback node relationships (fallbackNodeId -> originalNodeId)\n\t */\n\tprivate async applyEvent(\n\t\tevent: FlowcraftEvent,\n\t\tcontext: ExecutionContext<any, any>,\n\t\tfallbackMap: Map<string, string>,\n\t): Promise<void> {\n\t\tconst { type, payload } = event\n\n\t\tswitch (type) {\n\t\t\tcase 'node:start':\n\t\t\t\tbreak\n\n\t\t\tcase 'node:finish': {\n\t\t\t\tconst originalNodeId = fallbackMap.get(payload.nodeId)\n\t\t\t\tif (originalNodeId) {\n\t\t\t\t\tawait context.state.addCompletedNode(originalNodeId, payload.result.output)\n\t\t\t\t} else {\n\t\t\t\t\tawait context.state.addCompletedNode(payload.nodeId, payload.result.output)\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tcase 'context:change':\n\t\t\t\tif (payload.op === 'set') {\n\t\t\t\t\tawait context.state.getContext().set(payload.key, payload.value)\n\t\t\t\t} else if (payload.op === 'delete') {\n\t\t\t\t\tawait context.state.getContext().delete(payload.key)\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tcase 'node:error':\n\t\t\t\tcontext.state.addError(payload.nodeId, payload.error)\n\t\t\t\tbreak\n\n\t\t\tcase 'node:fallback':\n\t\t\t\tfallbackMap.set(payload.fallback, payload.nodeId)\n\t\t\t\tcontext.state.markFallbackExecuted()\n\t\t\t\tbreak\n\n\t\t\tcase 'node:retry':\n\t\t\t\tbreak\n\n\t\t\tcase 'edge:evaluate':\n\t\t\t\tbreak\n\n\t\t\tcase 'workflow:stall':\n\t\t\tcase 'workflow:pause':\n\t\t\t\tif ('remainingNodes' in payload) {\n\t\t\t\t\tfor (let i = 0; i < payload.remainingNodes; i++) {\n\t\t\t\t\t\tawait context.state.markAsAwaiting(`node-${i}`)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tcase 'batch:start':\n\t\t\t\tbreak\n\n\t\t\tcase 'batch:finish':\n\t\t\t\tfor (const _result of payload.results) {\n\t\t\t\t\t// TODO?\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tdefault:\n\t\t\t\tbreak\n\t\t}\n\t}\n}\n"]}
@@ -1,20 +1,20 @@
1
- import { WorkflowLogicHandler } from './chunk-SEI4Z3MO.js';
1
+ import { WorkflowLogicHandler } from './chunk-HXSK5P2X.js';
2
2
  import { NodeExecutorFactory } from './chunk-DL7KVYZF.js';
3
3
  import { WorkflowScheduler } from './chunk-LM4ACVHL.js';
4
- import { BatchGatherNode } from './chunk-BC4G7OM6.js';
5
- import { BatchScatterNode } from './chunk-RM677CNU.js';
6
4
  import { SleepNode } from './chunk-HNHM3FDK.js';
7
- import { SubflowNode } from './chunk-UXIASXSG.js';
8
- import { GraphTraverser } from './chunk-FBPY44WL.js';
5
+ import { SubflowNode } from './chunk-4TVWI6Y6.js';
9
6
  import { WaitNode } from './chunk-IDTYHLDQ.js';
10
7
  import { WebhookNode } from './chunk-I53JB2KW.js';
11
- import { sanitizeBlueprint } from './chunk-DSYAC4WB.js';
8
+ import { GraphTraverser } from './chunk-H4JTZYIT.js';
9
+ import { BatchGatherNode } from './chunk-BC4G7OM6.js';
10
+ import { BatchScatterNode } from './chunk-RM677CNU.js';
11
+ import { sanitizeBlueprint } from './chunk-TKSSRS5U.js';
12
12
  import { analyzeBlueprint } from './chunk-ZLW4QOTS.js';
13
- import { DefaultOrchestrator } from './chunk-XTW36KQZ.js';
14
- import { ExecutionContext } from './chunk-N4NLAIEN.js';
15
- import { WorkflowState } from './chunk-5BOUGXZO.js';
13
+ import { DefaultOrchestrator } from './chunk-TTOS7NW3.js';
14
+ import { ExecutionContext } from './chunk-LWN7HOD3.js';
15
+ import { WorkflowState } from './chunk-VSKDQVCG.js';
16
16
  import { NullLogger } from './chunk-4PELJWF7.js';
17
- import { JsonSerializer } from './chunk-CYHZ2YVH.js';
17
+ import { JsonSerializer } from './chunk-6RKHCJUU.js';
18
18
  import { DIContainer, ServiceTokens } from './chunk-WWGFIYKW.js';
19
19
  import { FlowcraftError } from './chunk-BCRWXTWX.js';
20
20
  import { PropertyEvaluator } from './chunk-PH2IYZHV.js';
@@ -246,7 +246,10 @@ var FlowRuntime = class {
246
246
  throw error;
247
247
  }
248
248
  }
249
- startScheduler() {
249
+ startScheduler(checkIntervalMs) {
250
+ if (checkIntervalMs !== void 0) {
251
+ this.scheduler = new WorkflowScheduler(this, checkIntervalMs);
252
+ }
250
253
  this.scheduler.start();
251
254
  }
252
255
  stopScheduler() {
@@ -358,14 +361,14 @@ var FlowRuntime = class {
358
361
  const nextSteps = await this.determineNextNodes(blueprint, awaitingNodeId, resumeData, contextImpl, executionId);
359
362
  if (nextSteps.length === 0) {
360
363
  workflowState.clearAwaiting(awaitingNodeId);
361
- const result = await workflowState.toResult(this.serializer);
364
+ const result = await workflowState.toResult(this.serializer, executionId);
362
365
  result.status = "completed";
363
366
  return result;
364
367
  }
365
368
  const traverserForResume = new GraphTraverser(blueprint);
366
369
  const allPredecessors = traverserForResume.getAllPredecessors();
367
370
  for (const { node, edge } of nextSteps) {
368
- await this.applyEdgeTransform(edge, resumeData, node, contextImpl, allPredecessors);
371
+ await this.applyEdgeTransform(edge, resumeData, node, contextImpl, allPredecessors, executionId);
369
372
  }
370
373
  const traverser = GraphTraverser.fromState(blueprint, workflowState);
371
374
  const nextNodeDefs = nextSteps.map((s) => s.node);
@@ -465,14 +468,63 @@ var FlowRuntime = class {
465
468
  async determineNextNodes(blueprint, nodeId, result, context, executionId) {
466
469
  return this.logicHandler.determineNextNodes(blueprint, nodeId, result, context, executionId);
467
470
  }
468
- async applyEdgeTransform(edge, sourceResult, targetNode, context, allPredecessors) {
469
- return this.logicHandler.applyEdgeTransform(edge, sourceResult, targetNode, context, allPredecessors);
471
+ async applyEdgeTransform(edge, sourceResult, targetNode, context, allPredecessors, executionId) {
472
+ return this.logicHandler.applyEdgeTransform(edge, sourceResult, targetNode, context, allPredecessors, executionId);
470
473
  }
471
474
  async resolveNodeInput(nodeId, blueprint, context) {
472
475
  return this.logicHandler.resolveNodeInput(nodeId, blueprint, context);
473
476
  }
477
+ /**
478
+ * Replay a workflow execution from a pre-recorded event history.
479
+ * This reconstructs the final workflow state without executing any node logic,
480
+ * enabling time-travel debugging and post-mortem analysis.
481
+ *
482
+ * @param blueprint The workflow blueprint
483
+ * @param events The recorded event history for the execution
484
+ * @param executionId Optional execution ID to filter events (if events contain multiple executions)
485
+ * @returns The reconstructed workflow result
486
+ */
487
+ async replay(blueprint, events, executionId) {
488
+ let filteredEvents = events;
489
+ if (executionId) {
490
+ filteredEvents = events.filter((event) => {
491
+ if ("executionId" in event.payload) {
492
+ return event.payload.executionId === executionId;
493
+ }
494
+ return false;
495
+ });
496
+ }
497
+ if (!executionId) {
498
+ const workflowStartEvent = filteredEvents.find((e) => e.type === "workflow:start");
499
+ if (workflowStartEvent && "executionId" in workflowStartEvent.payload) {
500
+ executionId = workflowStartEvent.payload.executionId;
501
+ } else {
502
+ throw new FlowcraftError("Cannot determine execution ID from events", { isFatal: true });
503
+ }
504
+ }
505
+ const tempContext = this._setupExecutionContext(
506
+ blueprint,
507
+ {},
508
+ { strict: false }
509
+ // allow cycles in replay
510
+ );
511
+ const executionContext = new ExecutionContext(
512
+ blueprint,
513
+ tempContext.state,
514
+ tempContext.nodeRegistry,
515
+ executionId,
516
+ this,
517
+ tempContext.services,
518
+ tempContext.signal,
519
+ tempContext.concurrency
520
+ );
521
+ const { ReplayOrchestrator } = await import('./runtime/orchestrators/replay.js');
522
+ const replayOrchestrator = new ReplayOrchestrator(filteredEvents);
523
+ const traverser = new GraphTraverser(blueprint);
524
+ return await replayOrchestrator.run(executionContext, traverser);
525
+ }
474
526
  };
475
527
 
476
528
  export { FlowRuntime };
477
- //# sourceMappingURL=chunk-OPRR4TAO.js.map
478
- //# sourceMappingURL=chunk-OPRR4TAO.js.map
529
+ //# sourceMappingURL=chunk-VDVUF25G.js.map
530
+ //# sourceMappingURL=chunk-VDVUF25G.js.map