flowcraft 2.9.3 → 2.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/adapter-DzeZVjSE.d.mts +133 -0
- package/dist/adapters/index.d.mts +2 -0
- package/dist/adapters/index.mjs +3 -0
- package/dist/adapters/persistent-event-bus.d.mts +2 -0
- package/dist/adapters/persistent-event-bus.mjs +59 -0
- package/dist/analysis-B5Twr7sD.d.mts +52 -0
- package/dist/analysis.d.mts +2 -0
- package/dist/analysis.mjs +164 -0
- package/dist/batch-gather-BhF-IzQR.d.mts +8 -0
- package/dist/batch-scatter-DD8TU0Wm.d.mts +8 -0
- package/dist/container-BKdd-9wf.d.mts +24 -0
- package/dist/container-factory-fDY2kkxt.d.mts +17 -0
- package/dist/container-factory.d.mts +2 -0
- package/dist/container-factory.mjs +23 -0
- package/dist/container.d.mts +2 -0
- package/dist/container.mjs +43 -0
- package/dist/context-ZVtzXuZu.d.mts +64 -0
- package/dist/context.d.mts +2 -0
- package/dist/context.mjs +145 -0
- package/dist/error-mapper-BAv_YQMQ.d.mts +14 -0
- package/dist/error-mapper.d.mts +2 -0
- package/dist/error-mapper.mjs +37 -0
- package/dist/errors-CyyIj3OO.d.mts +21 -0
- package/dist/errors.d.mts +2 -0
- package/dist/errors.mjs +24 -0
- package/dist/evaluator-Dnj5qJ92.d.mts +31 -0
- package/dist/evaluator.d.mts +2 -0
- package/dist/evaluator.mjs +80 -0
- package/dist/flow-CZGpYpl-.d.mts +94 -0
- package/dist/flow.d.mts +2 -0
- package/dist/flow.mjs +328 -0
- package/dist/index-9iG2qHLe.d.mts +1 -0
- package/dist/index-Bk0eNZmQ.d.mts +1 -0
- package/dist/index-CNgSR_kt.d.mts +1 -0
- package/dist/index-CW2WHUXP.d.mts +1 -0
- package/dist/index.d.mts +24 -1
- package/dist/index.mjs +31 -746
- package/dist/linter-B8KALEae.d.mts +25 -0
- package/dist/linter.d.mts +2 -0
- package/dist/linter.mjs +74 -0
- package/dist/logger-BvDgvNHQ.d.mts +19 -0
- package/dist/logger.d.mts +2 -0
- package/dist/logger.mjs +26 -0
- package/dist/node.d.mts +2 -0
- package/dist/node.mjs +55 -0
- package/dist/nodes/batch-gather.d.mts +2 -0
- package/dist/nodes/batch-gather.mjs +47 -0
- package/dist/nodes/batch-scatter.d.mts +2 -0
- package/dist/nodes/batch-scatter.mjs +52 -0
- package/dist/nodes/index.d.mts +7 -0
- package/dist/nodes/index.mjs +8 -0
- package/dist/nodes/sleep.d.mts +2 -0
- package/dist/nodes/sleep.mjs +41 -0
- package/dist/nodes/subflow.d.mts +2 -0
- package/dist/nodes/subflow.mjs +64 -0
- package/dist/nodes/wait.d.mts +2 -0
- package/dist/nodes/wait.mjs +12 -0
- package/dist/nodes/webhook.d.mts +2 -0
- package/dist/nodes/webhook.mjs +24 -0
- package/dist/orchestrator-DwMIJRFI.d.mts +8 -0
- package/dist/persistent-event-bus-COiQOpWh.d.mts +68 -0
- package/dist/replay-CVOy6d_L.d.mts +44 -0
- package/dist/runtime/adapter.d.mts +2 -0
- package/dist/runtime/adapter.mjs +349 -0
- package/dist/runtime/builtin-keys.d.mts +37 -0
- package/dist/runtime/builtin-keys.mjs +12 -0
- package/dist/runtime/execution-context.d.mts +2 -0
- package/dist/runtime/execution-context.mjs +26 -0
- package/dist/runtime/executors.d.mts +2 -0
- package/dist/runtime/executors.mjs +259 -0
- package/dist/runtime/index.d.mts +6 -0
- package/dist/runtime/index.mjs +10 -0
- package/dist/runtime/node-executor-factory.d.mts +11 -0
- package/dist/runtime/node-executor-factory.mjs +41 -0
- package/dist/runtime/orchestrator.d.mts +2 -0
- package/dist/runtime/orchestrator.mjs +41 -0
- package/dist/runtime/orchestrators/replay.d.mts +2 -0
- package/dist/{replay-BB11M6K1.mjs → runtime/orchestrators/replay.mjs} +1 -20
- package/dist/runtime/orchestrators/step-by-step.d.mts +15 -0
- package/dist/runtime/orchestrators/step-by-step.mjs +41 -0
- package/dist/runtime/orchestrators/utils.d.mts +2 -0
- package/dist/runtime/orchestrators/utils.mjs +79 -0
- package/dist/runtime/runtime.d.mts +2 -0
- package/dist/runtime/runtime.mjs +425 -0
- package/dist/runtime/scheduler.d.mts +2 -0
- package/dist/runtime/scheduler.mjs +64 -0
- package/dist/runtime/state.d.mts +2 -0
- package/dist/runtime/state.mjs +127 -0
- package/dist/runtime/traverser.d.mts +2 -0
- package/dist/runtime/traverser.mjs +213 -0
- package/dist/runtime/types.d.mts +2 -0
- package/dist/runtime/types.mjs +1 -0
- package/dist/runtime/workflow-logic-handler.d.mts +16 -0
- package/dist/runtime/workflow-logic-handler.mjs +159 -0
- package/dist/sanitizer-Bi00YjvO.d.mts +11 -0
- package/dist/sanitizer.d.mts +2 -0
- package/dist/sanitizer.mjs +37 -0
- package/dist/sdk.d.mts +1 -2
- package/dist/sdk.mjs +1 -2
- package/dist/serializer-BnmJr13R.d.mts +17 -0
- package/dist/serializer.d.mts +2 -0
- package/dist/serializer.mjs +34 -0
- package/dist/sleep-DpwYaY5b.d.mts +8 -0
- package/dist/subflow-n2IMsRe2.d.mts +8 -0
- package/dist/testing/event-logger.d.mts +62 -0
- package/dist/testing/event-logger.mjs +98 -0
- package/dist/testing/index.d.mts +5 -172
- package/dist/testing/index.mjs +6 -276
- package/dist/testing/run-with-trace.d.mts +37 -0
- package/dist/testing/run-with-trace.mjs +49 -0
- package/dist/testing/stepper.d.mts +78 -0
- package/dist/testing/stepper.mjs +100 -0
- package/dist/types-BcrXJEPI.d.mts +687 -0
- package/dist/types.d.mts +2 -0
- package/dist/types.mjs +1 -0
- package/dist/utils-BUEgr9V2.d.mts +34 -0
- package/dist/wait-2Q-LA7V7.d.mts +8 -0
- package/dist/webhook-BiCm-HLx.d.mts +12 -0
- package/package.json +4 -4
- package/dist/index-DUPpyNvU.d.mts +0 -1326
- package/dist/index.mjs.map +0 -1
- package/dist/replay-BB11M6K1.mjs.map +0 -1
- package/dist/runtime-lNm7WbD1.mjs +0 -2250
- package/dist/runtime-lNm7WbD1.mjs.map +0 -1
- package/dist/sdk.mjs.map +0 -1
- package/dist/testing/index.mjs.map +0 -1
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { A as FlowRuntime, B as NodeExecutionResult, F as GraphTraverser, H as NodeExecutorConfig, I as ReadyNode, L as ClassNodeExecutor, M as IOrchestrator, N as IRuntime, P as NodeExecutorFactory, R as ExecutionStrategy, U as WorkflowState, V as NodeExecutor, j as ExecutionServices, z as FunctionNodeExecutor } from "../types-BcrXJEPI.mjs";
|
|
2
|
+
import { i as JobPayload, n as BaseDistributedAdapter, r as ICoordinationStore, t as AdapterOptions } from "../adapter-DzeZVjSE.mjs";
|
|
3
|
+
import { t as DefaultOrchestrator } from "../orchestrator-DwMIJRFI.mjs";
|
|
4
|
+
import { t as ReplayOrchestrator } from "../replay-CVOy6d_L.mjs";
|
|
5
|
+
import { n as processResults, t as executeBatch } from "../utils-BUEgr9V2.mjs";
|
|
6
|
+
export { AdapterOptions, BaseDistributedAdapter, ClassNodeExecutor, DefaultOrchestrator, ExecutionServices, ExecutionStrategy, FlowRuntime, FunctionNodeExecutor, GraphTraverser, ICoordinationStore, IOrchestrator, IRuntime, JobPayload, NodeExecutionResult, NodeExecutor, NodeExecutorConfig, NodeExecutorFactory, ReadyNode, ReplayOrchestrator, WorkflowState, executeBatch, processResults };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { WorkflowState } from "./state.mjs";
|
|
2
|
+
import { executeBatch, processResults } from "./orchestrators/utils.mjs";
|
|
3
|
+
import { DefaultOrchestrator } from "./orchestrator.mjs";
|
|
4
|
+
import { GraphTraverser } from "./traverser.mjs";
|
|
5
|
+
import { ClassNodeExecutor, FunctionNodeExecutor, NodeExecutor } from "./executors.mjs";
|
|
6
|
+
import { FlowRuntime } from "./runtime.mjs";
|
|
7
|
+
import { BaseDistributedAdapter } from "./adapter.mjs";
|
|
8
|
+
import { ReplayOrchestrator } from "./orchestrators/replay.mjs";
|
|
9
|
+
|
|
10
|
+
export { BaseDistributedAdapter, ClassNodeExecutor, DefaultOrchestrator, FlowRuntime, FunctionNodeExecutor, GraphTraverser, NodeExecutor, ReplayOrchestrator, WorkflowState, executeBatch, processResults };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { V as NodeExecutor, k as ExecutionContext, o as IEventBus } from "../types-BcrXJEPI.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/runtime/node-executor-factory.d.ts
|
|
4
|
+
declare class NodeExecutorFactory {
|
|
5
|
+
private readonly eventBus;
|
|
6
|
+
constructor(eventBus: IEventBus);
|
|
7
|
+
createExecutorForNode(nodeId: string, context: ExecutionContext<any, any>): NodeExecutor<any, any>;
|
|
8
|
+
private getExecutionStrategy;
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
export { NodeExecutorFactory };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { FlowcraftError } from "../errors.mjs";
|
|
2
|
+
import { isNodeClass } from "../node.mjs";
|
|
3
|
+
import { ClassNodeExecutor, FunctionNodeExecutor, NodeExecutor } from "./executors.mjs";
|
|
4
|
+
|
|
5
|
+
//#region src/runtime/node-executor-factory.ts
|
|
6
|
+
var NodeExecutorFactory = class {
|
|
7
|
+
constructor(eventBus) {
|
|
8
|
+
this.eventBus = eventBus;
|
|
9
|
+
}
|
|
10
|
+
createExecutorForNode(nodeId, context) {
|
|
11
|
+
const nodeDef = context.blueprint.nodes.find((n) => n.id === nodeId);
|
|
12
|
+
if (!nodeDef) throw new FlowcraftError(`Node '${nodeId}' not found in blueprint.`, {
|
|
13
|
+
nodeId,
|
|
14
|
+
blueprintId: context.blueprint.id,
|
|
15
|
+
executionId: context.executionId,
|
|
16
|
+
isFatal: false
|
|
17
|
+
});
|
|
18
|
+
return new NodeExecutor({
|
|
19
|
+
context,
|
|
20
|
+
nodeDef,
|
|
21
|
+
strategy: this.getExecutionStrategy(nodeDef, context)
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
getExecutionStrategy(nodeDef, context) {
|
|
25
|
+
const implementation = context.nodeRegistry.get(nodeDef.uses);
|
|
26
|
+
if (!implementation) throw new FlowcraftError(`Implementation for '${nodeDef.uses}' not found.`, {
|
|
27
|
+
nodeId: nodeDef.id,
|
|
28
|
+
blueprintId: "",
|
|
29
|
+
isFatal: true
|
|
30
|
+
});
|
|
31
|
+
let maxRetries = nodeDef.config?.maxRetries ?? 1;
|
|
32
|
+
const adapter = context.services.dependencies?.adapter;
|
|
33
|
+
if (adapter && typeof adapter.shouldRetryInProcess === "function") {
|
|
34
|
+
if (!adapter.shouldRetryInProcess(nodeDef)) maxRetries = 1;
|
|
35
|
+
}
|
|
36
|
+
return isNodeClass(implementation) ? new ClassNodeExecutor(implementation, maxRetries, this.eventBus) : new FunctionNodeExecutor(implementation, maxRetries, this.eventBus);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
//#endregion
|
|
41
|
+
export { NodeExecutorFactory };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { FlowcraftError } from "../errors.mjs";
|
|
2
|
+
import { ExecutionContext } from "./execution-context.mjs";
|
|
3
|
+
import { executeBatch, processResults } from "./orchestrators/utils.mjs";
|
|
4
|
+
|
|
5
|
+
//#region src/runtime/orchestrator.ts
|
|
6
|
+
var DefaultOrchestrator = class {
|
|
7
|
+
async run(context, traverser) {
|
|
8
|
+
const hardwareConcurrency = globalThis.navigator?.hardwareConcurrency || 4;
|
|
9
|
+
const maxConcurrency = context.concurrency != null && context.concurrency > 0 ? context.concurrency : Math.min(hardwareConcurrency, 10);
|
|
10
|
+
try {
|
|
11
|
+
context.signal?.throwIfAborted();
|
|
12
|
+
} catch (error) {
|
|
13
|
+
if (error instanceof DOMException && error.name === "AbortError") throw new FlowcraftError("Workflow cancelled", { isFatal: false });
|
|
14
|
+
throw error;
|
|
15
|
+
}
|
|
16
|
+
let iterations = 0;
|
|
17
|
+
const maxIterations = 1e4;
|
|
18
|
+
while (traverser.hasMoreWork()) {
|
|
19
|
+
if (++iterations > maxIterations) throw new Error("Traversal exceeded maximum iterations, possible infinite loop");
|
|
20
|
+
try {
|
|
21
|
+
context.signal?.throwIfAborted();
|
|
22
|
+
} catch (error) {
|
|
23
|
+
if (error instanceof DOMException && error.name === "AbortError") throw new FlowcraftError("Workflow cancelled", { isFatal: false });
|
|
24
|
+
throw error;
|
|
25
|
+
}
|
|
26
|
+
const readyNodes = traverser.getReadyNodes();
|
|
27
|
+
const dynamicBlueprint = traverser.getDynamicBlueprint();
|
|
28
|
+
const updatedContext = new ExecutionContext(dynamicBlueprint, context.state, context.nodeRegistry, context.executionId, context.runtime, context.services, context.signal, context.concurrency);
|
|
29
|
+
await processResults(await executeBatch(readyNodes, dynamicBlueprint, context.state, (nodeId) => context.runtime.getExecutorForNode(nodeId, updatedContext), context.runtime, maxConcurrency), traverser, context.state, context.runtime, context.blueprint, context.executionId);
|
|
30
|
+
if (context.state.isAwaiting()) break;
|
|
31
|
+
}
|
|
32
|
+
const isTraversalComplete = !traverser.hasMoreWork();
|
|
33
|
+
const status = context.state.getStatus(isTraversalComplete);
|
|
34
|
+
const result = await context.state.toResult(context.services.serializer, context.executionId);
|
|
35
|
+
result.status = status;
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
//#endregion
|
|
41
|
+
export { DefaultOrchestrator };
|
|
@@ -1,22 +1,4 @@
|
|
|
1
|
-
//#region \0rolldown/runtime.js
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __exportAll = (all, no_symbols) => {
|
|
4
|
-
let target = {};
|
|
5
|
-
for (var name in all) {
|
|
6
|
-
__defProp(target, name, {
|
|
7
|
-
get: all[name],
|
|
8
|
-
enumerable: true
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
if (!no_symbols) {
|
|
12
|
-
__defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
13
|
-
}
|
|
14
|
-
return target;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
//#endregion
|
|
18
1
|
//#region src/runtime/orchestrators/replay.ts
|
|
19
|
-
var replay_exports = /* @__PURE__ */ __exportAll({ ReplayOrchestrator: () => ReplayOrchestrator });
|
|
20
2
|
/**
|
|
21
3
|
* An orchestrator that replays a pre-recorded sequence of workflow events
|
|
22
4
|
* to reconstruct the workflow state without executing any node logic.
|
|
@@ -103,5 +85,4 @@ var ReplayOrchestrator = class {
|
|
|
103
85
|
};
|
|
104
86
|
|
|
105
87
|
//#endregion
|
|
106
|
-
export {
|
|
107
|
-
//# sourceMappingURL=replay-BB11M6K1.mjs.map
|
|
88
|
+
export { ReplayOrchestrator };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { D as WorkflowResult, F as GraphTraverser, M as IOrchestrator, k as ExecutionContext } from "../../types-BcrXJEPI.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/runtime/orchestrators/step-by-step.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* An orchestrator that executes only one "tick" or "turn" of the workflow.
|
|
6
|
+
* It processes a single batch of ready nodes from the frontier and then returns,
|
|
7
|
+
* allowing the caller to inspect the intermediate state before proceeding.
|
|
8
|
+
*
|
|
9
|
+
* Useful for debugging, testing, or building interactive tools.
|
|
10
|
+
*/
|
|
11
|
+
declare class StepByStepOrchestrator implements IOrchestrator {
|
|
12
|
+
run(context: ExecutionContext<any, any>, traverser: GraphTraverser): Promise<WorkflowResult<any>>;
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { StepByStepOrchestrator };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { FlowcraftError } from "../../errors.mjs";
|
|
2
|
+
import { executeBatch, processResults } from "./utils.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/runtime/orchestrators/step-by-step.ts
|
|
5
|
+
/**
|
|
6
|
+
* An orchestrator that executes only one "tick" or "turn" of the workflow.
|
|
7
|
+
* It processes a single batch of ready nodes from the frontier and then returns,
|
|
8
|
+
* allowing the caller to inspect the intermediate state before proceeding.
|
|
9
|
+
*
|
|
10
|
+
* Useful for debugging, testing, or building interactive tools.
|
|
11
|
+
*/
|
|
12
|
+
var StepByStepOrchestrator = class {
|
|
13
|
+
async run(context, traverser) {
|
|
14
|
+
try {
|
|
15
|
+
context.signal?.throwIfAborted();
|
|
16
|
+
} catch (error) {
|
|
17
|
+
if (error instanceof DOMException && error.name === "AbortError") throw new FlowcraftError("Workflow cancelled", { isFatal: false });
|
|
18
|
+
throw error;
|
|
19
|
+
}
|
|
20
|
+
if (!traverser.hasMoreWork()) {
|
|
21
|
+
const isTraversalComplete = !traverser.hasMoreWork();
|
|
22
|
+
const status = context.state.getStatus(isTraversalComplete);
|
|
23
|
+
const result = await context.state.toResult(context.services.serializer, context.executionId);
|
|
24
|
+
result.status = status;
|
|
25
|
+
return result;
|
|
26
|
+
}
|
|
27
|
+
const allReadyNodes = traverser.getReadyNodes();
|
|
28
|
+
const nodesToExecute = context.concurrency ? allReadyNodes.slice(0, context.concurrency) : allReadyNodes;
|
|
29
|
+
const nodesToSkip = context.concurrency ? allReadyNodes.slice(context.concurrency) : [];
|
|
30
|
+
await processResults(await executeBatch(nodesToExecute, traverser.getDynamicBlueprint(), context.state, (nodeId) => context.runtime.getExecutorForNode(nodeId, context), context.runtime, context.concurrency), traverser, context.state, context.runtime, context.blueprint, context.executionId);
|
|
31
|
+
for (const { nodeId } of nodesToSkip) traverser.addToFrontier(nodeId);
|
|
32
|
+
const isTraversalComplete = !traverser.hasMoreWork();
|
|
33
|
+
const status = context.state.getStatus(isTraversalComplete);
|
|
34
|
+
const result = await context.state.toResult(context.services.serializer, context.executionId);
|
|
35
|
+
result.status = status;
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
//#endregion
|
|
41
|
+
export { StepByStepOrchestrator };
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { FlowcraftError } from "../../errors.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/runtime/orchestrators/utils.ts
|
|
4
|
+
async function executeBatch(readyNodes, blueprint, state, executorFactory, runtime, maxConcurrency) {
|
|
5
|
+
const concurrency = maxConcurrency || readyNodes.length;
|
|
6
|
+
const results = [];
|
|
7
|
+
for (let i = 0; i < readyNodes.length; i += concurrency) {
|
|
8
|
+
const batchPromises = readyNodes.slice(i, i + concurrency).map(async ({ nodeId }) => {
|
|
9
|
+
try {
|
|
10
|
+
const executor = executorFactory(nodeId);
|
|
11
|
+
if (!executor) throw new Error(`No executor for node ${nodeId}`);
|
|
12
|
+
const executionResult = await executor.execute(await runtime.resolveNodeInput(nodeId, blueprint, state.getContext()));
|
|
13
|
+
results.push({
|
|
14
|
+
status: "fulfilled",
|
|
15
|
+
value: {
|
|
16
|
+
nodeId,
|
|
17
|
+
executionResult
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
} catch (error) {
|
|
21
|
+
results.push({
|
|
22
|
+
status: "rejected",
|
|
23
|
+
reason: {
|
|
24
|
+
nodeId,
|
|
25
|
+
error
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
await Promise.all(batchPromises);
|
|
31
|
+
}
|
|
32
|
+
return results;
|
|
33
|
+
}
|
|
34
|
+
async function processResults(settledResults, traverser, state, runtime, _blueprint, executionId) {
|
|
35
|
+
for (const promiseResult of settledResults) {
|
|
36
|
+
if (promiseResult.status === "rejected") {
|
|
37
|
+
const { nodeId, error } = promiseResult.reason;
|
|
38
|
+
if (error instanceof FlowcraftError && error.message.includes("cancelled")) throw error;
|
|
39
|
+
state.addError(nodeId, error);
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
const { nodeId, executionResult } = promiseResult.value;
|
|
43
|
+
if (executionResult.status === "success") {
|
|
44
|
+
const result = executionResult.result;
|
|
45
|
+
if (result) {
|
|
46
|
+
await state.addCompletedNode(nodeId, result.output);
|
|
47
|
+
if (result._fallbackExecuted) state.markFallbackExecuted();
|
|
48
|
+
if (result.dynamicNodes && result.dynamicNodes.length > 0) {
|
|
49
|
+
const gatherNodeId = result.output?.gatherNodeId;
|
|
50
|
+
for (const dynamicNode of result.dynamicNodes) traverser.addDynamicNode(dynamicNode.id, dynamicNode, nodeId, gatherNodeId);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const matched = await runtime.determineNextNodes(traverser.getDynamicBlueprint(), nodeId, result, state.getContext(), executionId);
|
|
54
|
+
for (const { node, edge } of matched) await runtime.applyEdgeTransform(edge, result, node, state.getContext(), traverser.getAllPredecessors(), executionId);
|
|
55
|
+
traverser.markNodeCompleted(nodeId, result, matched.map((m) => m.node));
|
|
56
|
+
} else if (executionResult.status === "failed_with_fallback") {
|
|
57
|
+
const { fallbackNodeId, error } = executionResult;
|
|
58
|
+
const fallbackNodeDef = traverser.getDynamicBlueprint().nodes.find((n) => n.id === fallbackNodeId);
|
|
59
|
+
if (!fallbackNodeDef) {
|
|
60
|
+
const notFoundError = new FlowcraftError(`Fallback node '${fallbackNodeId}' not found in blueprint.`, {
|
|
61
|
+
nodeId,
|
|
62
|
+
cause: error
|
|
63
|
+
});
|
|
64
|
+
state.addError(nodeId, notFoundError);
|
|
65
|
+
} else {
|
|
66
|
+
state.addCompletedNode(nodeId, null);
|
|
67
|
+
state.markFallbackExecuted();
|
|
68
|
+
traverser.markNodeCompleted(nodeId, {
|
|
69
|
+
action: "fallback",
|
|
70
|
+
output: null,
|
|
71
|
+
_fallbackExecuted: true
|
|
72
|
+
}, [fallbackNodeDef]);
|
|
73
|
+
}
|
|
74
|
+
} else state.addError(nodeId, executionResult.error);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
//#endregion
|
|
79
|
+
export { executeBatch, processResults };
|