veryfront 0.1.699 → 0.1.701

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/esm/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "veryfront",
3
- "version": "0.1.699",
3
+ "version": "0.1.701",
4
4
  "license": "Apache-2.0",
5
5
  "nodeModulesDir": "auto",
6
6
  "minimumDependencyAge": "P2D",
@@ -1,3 +1,3 @@
1
1
  /** Shared version value. */
2
- export declare const VERSION = "0.1.699";
2
+ export declare const VERSION = "0.1.701";
3
3
  //# sourceMappingURL=version-constant.d.ts.map
@@ -1,4 +1,4 @@
1
1
  // Keep in sync with deno.json version.
2
2
  // scripts/release.ts updates this constant during releases.
3
3
  /** Shared version value. */
4
- export const VERSION = "0.1.699";
4
+ export const VERSION = "0.1.701";
@@ -15,11 +15,10 @@ export declare class DAGExecutor {
15
15
  private executeNode;
16
16
  private executeStepNode;
17
17
  private executeParallelNode;
18
- private executeMapNode;
19
18
  private executeBranchNode;
20
19
  private executeWaitNode;
21
20
  private executeSubWorkflowNode;
22
- private executeLoopNode;
23
21
  private checkpoint;
22
+ private executeChildGraph;
24
23
  }
25
24
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/src/workflow/executor/dag/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAYV,YAAY,EAEZ,WAAW,EACZ,MAAM,gBAAgB,CAAC;AAIxB,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAE7F,OAAO,KAAK,EACV,kBAAkB,EAClB,iBAAiB,EAGlB,MAAM,YAAY,CAAC;AAIpB,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAA4B;gBAE9B,MAAM,EAAE,iBAAiB;IAQ/B,OAAO,CACX,KAAK,EAAE,YAAY,EAAE,EACrB,GAAG,EAAE,WAAW,EAChB,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,kBAAkB,CAAC;YAsGhB,WAAW;YA8CX,eAAe;YA0Bf,mBAAmB;YA4CnB,cAAc;YAqGd,iBAAiB;YA+DjB,eAAe;YA8Bf,sBAAsB;YA+DtB,eAAe;YAsKf,UAAU;CAoBzB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/src/workflow/executor/dag/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAQV,YAAY,EAEZ,WAAW,EACZ,MAAM,gBAAgB,CAAC;AAIxB,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAE7F,OAAO,KAAK,EACV,kBAAkB,EAClB,iBAAiB,EAGlB,MAAM,YAAY,CAAC;AAOpB,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAA4B;gBAE9B,MAAM,EAAE,iBAAiB;IAQ/B,OAAO,CACX,KAAK,EAAE,YAAY,EAAE,EACrB,GAAG,EAAE,WAAW,EAChB,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,kBAAkB,CAAC;YAsGhB,WAAW;YAgEX,eAAe;YA0Bf,mBAAmB;YA4CnB,iBAAiB;YA+DjB,eAAe;YA8Bf,sBAAsB;YA+DtB,UAAU;YAqBV,iBAAiB;CAiBhC"}
@@ -5,10 +5,12 @@
5
5
  *
6
6
  * @module ai/workflow/executor/dag
7
7
  */
8
- import { generateId, parseDuration } from "../../types.js";
8
+ import { generateId } from "../../types.js";
9
9
  import { INVALID_ARGUMENT, NOT_SUPPORTED } from "../../../errors/index.js";
10
- import { deriveNodeStatus, shouldCheckpoint, sleep } from "./utils.js";
10
+ import { deriveNodeStatus, shouldCheckpoint } from "./utils.js";
11
11
  import { buildGraph, getReadyNodes, hasCycle, updateInDegreesForCompletedNodes } from "./graph.js";
12
+ import { executeLoopNodeStrategy } from "./loop-node-strategy.js";
13
+ import { executeMapNodeStrategy } from "./map-node-strategy.js";
12
14
  export class DAGExecutor {
13
15
  config;
14
16
  constructor(config) {
@@ -118,7 +120,16 @@ export class DAGExecutor {
118
120
  case "parallel":
119
121
  return this.executeParallelNode(node, config, context, nodeStates);
120
122
  case "map":
121
- return this.executeMapNode(node, config, context, nodeStates);
123
+ return executeMapNodeStrategy({
124
+ node,
125
+ config,
126
+ context,
127
+ nodeStates,
128
+ runtime: {
129
+ executeChildGraph: (nodes, run, options) => this.executeChildGraph(nodes, run, options),
130
+ onNodeComplete: this.config.onNodeComplete,
131
+ },
132
+ });
122
133
  case "branch":
123
134
  return this.executeBranchNode(node, config, context, nodeStates);
124
135
  case "wait":
@@ -126,7 +137,16 @@ export class DAGExecutor {
126
137
  case "subWorkflow":
127
138
  return this.executeSubWorkflowNode(node, config, context);
128
139
  case "loop":
129
- return this.executeLoopNode(node, config, context, nodeStates);
140
+ return executeLoopNodeStrategy({
141
+ node,
142
+ config,
143
+ context,
144
+ nodeStates,
145
+ runtime: {
146
+ executeChildGraph: (nodes, run) => this.executeChildGraph(nodes, run),
147
+ onNodeComplete: this.config.onNodeComplete,
148
+ },
149
+ });
130
150
  default:
131
151
  throw INVALID_ARGUMENT.create({
132
152
  detail: `Unknown node type "${config.type}" for node "${node.id}". ` +
@@ -186,85 +206,6 @@ export class DAGExecutor {
186
206
  waiting: result.waiting,
187
207
  };
188
208
  }
189
- async executeMapNode(node, config, context, nodeStates) {
190
- const startTime = Date.now();
191
- const items = typeof config.items === "function" ? await config.items(context) : config.items;
192
- if (!Array.isArray(items)) {
193
- throw INVALID_ARGUMENT.create({ detail: `Map node "${node.id}" items must be an array` });
194
- }
195
- if (items.length === 0) {
196
- const state = {
197
- nodeId: node.id,
198
- status: "completed",
199
- output: [],
200
- attempt: 1,
201
- startedAt: new Date(startTime),
202
- completedAt: new Date(),
203
- };
204
- return { state, contextUpdates: { [node.id]: [] }, waiting: false };
205
- }
206
- const isWorkflowDef = (p) => typeof p === "object" && p !== null && "steps" in p;
207
- const childNodes = items.map((item, i) => {
208
- const childId = `${node.id}_${i}`;
209
- if (isWorkflowDef(config.processor)) {
210
- return {
211
- id: childId,
212
- config: {
213
- type: "subWorkflow",
214
- workflow: config.processor,
215
- input: item,
216
- retry: config.retry,
217
- checkpoint: false,
218
- },
219
- };
220
- }
221
- const processorConfig = { ...config.processor.config };
222
- if (processorConfig.type === "step") {
223
- processorConfig.input = item;
224
- }
225
- return { id: childId, config: processorConfig };
226
- });
227
- const originalConcurrency = this.config.maxConcurrency;
228
- if (config.concurrency) {
229
- this.config.maxConcurrency = config.concurrency;
230
- }
231
- try {
232
- const result = await this.execute(childNodes, {
233
- id: `${node.id}_map`,
234
- workflowId: "",
235
- status: "running",
236
- input: context.input,
237
- // Carry already-accumulated child states so completed children are
238
- // skipped on resume instead of re-executing (H8).
239
- nodeStates,
240
- currentNodes: [],
241
- context: { ...context },
242
- checkpoints: [],
243
- pendingApprovals: [],
244
- createdAt: new Date(),
245
- });
246
- Object.assign(nodeStates, result.nodeStates);
247
- const outputs = childNodes.map((child) => result.nodeStates[child.id]?.output);
248
- const state = {
249
- nodeId: node.id,
250
- status: deriveNodeStatus(result.completed, result.waiting),
251
- output: outputs,
252
- error: result.error,
253
- attempt: 1,
254
- startedAt: new Date(startTime),
255
- completedAt: result.completed ? new Date() : undefined,
256
- };
257
- this.config.onNodeComplete?.(node.id, state);
258
- return {
259
- state,
260
- contextUpdates: result.completed ? { [node.id]: outputs } : {},
261
- waiting: result.waiting,
262
- };
263
- }
264
- finally {
265
- this.config.maxConcurrency = originalConcurrency;
266
- }
267
- }
268
209
  async executeBranchNode(node, config, context, nodeStates) {
269
210
  const startTime = Date.now();
270
211
  const conditionResult = await config.condition(context);
@@ -383,139 +324,6 @@ export class DAGExecutor {
383
324
  waiting: result.waiting,
384
325
  };
385
326
  }
386
- async executeLoopNode(node, config, context, nodeStates) {
387
- const startTime = Date.now();
388
- const previousResults = [];
389
- let iteration = 0;
390
- let exitReason = "condition";
391
- let lastError;
392
- const existingLoopState = context[`${node.id}_loop_state`];
393
- // Child node states for the in-flight (resumed) iteration, so its already
394
- // completed steps are not re-executed on resume (H9).
395
- let resumeIterationNodeStates;
396
- let resumeIteration;
397
- if (existingLoopState) {
398
- iteration = existingLoopState.iteration;
399
- previousResults.push(...existingLoopState.previousResults);
400
- resumeIterationNodeStates = existingLoopState.iterationNodeStates;
401
- resumeIteration = existingLoopState.iteration;
402
- }
403
- while (iteration < config.maxIterations) {
404
- const loopContext = {
405
- iteration,
406
- totalIterations: iteration,
407
- previousResults: [...previousResults],
408
- isFirstIteration: iteration === 0,
409
- isLastAllowedIteration: iteration === config.maxIterations - 1,
410
- };
411
- if (!(await config.while(context, loopContext))) {
412
- exitReason = "condition";
413
- break;
414
- }
415
- const steps = typeof config.steps === "function"
416
- ? config.steps(context, loopContext)
417
- : config.steps;
418
- // On resume, rehydrate the in-flight iteration's child node states so its
419
- // already-completed steps are skipped instead of re-executed (H9).
420
- const iterationNodeStates = resumeIteration === iteration && resumeIterationNodeStates
421
- ? { ...resumeIterationNodeStates }
422
- : {};
423
- // Only rehydrate once; subsequent iterations start fresh.
424
- resumeIterationNodeStates = undefined;
425
- const result = await this.execute(steps, {
426
- id: `${node.id}_iter_${iteration}`,
427
- workflowId: "",
428
- status: "running",
429
- input: context.input,
430
- nodeStates: iterationNodeStates,
431
- currentNodes: [],
432
- context: { ...context, _loop: loopContext },
433
- checkpoints: [],
434
- pendingApprovals: [],
435
- createdAt: new Date(),
436
- });
437
- if (result.waiting) {
438
- Object.assign(nodeStates, result.nodeStates);
439
- const state = {
440
- nodeId: node.id,
441
- status: "running",
442
- output: { iteration, waiting: true, previousResults },
443
- attempt: 1,
444
- startedAt: new Date(startTime),
445
- };
446
- return {
447
- state,
448
- contextUpdates: {
449
- ...result.context,
450
- [`${node.id}_loop_state`]: {
451
- iteration,
452
- previousResults,
453
- // Persist the in-flight iteration's child states so completed
454
- // steps are not re-executed when this iteration resumes (H9).
455
- iterationNodeStates: result.nodeStates,
456
- },
457
- },
458
- waiting: true,
459
- };
460
- }
461
- if (result.error) {
462
- lastError = result.error;
463
- exitReason = "error";
464
- break;
465
- }
466
- previousResults.push(result.context);
467
- Object.assign(context, result.context);
468
- Object.assign(nodeStates, result.nodeStates);
469
- if (config.delay && iteration < config.maxIterations - 1) {
470
- const delayMs = typeof config.delay === "number"
471
- ? config.delay
472
- : parseDuration(config.delay);
473
- await sleep(delayMs);
474
- }
475
- iteration++;
476
- }
477
- if (iteration >= config.maxIterations && exitReason !== "condition") {
478
- exitReason = "maxIterations";
479
- }
480
- const finalLoopContext = {
481
- iteration,
482
- totalIterations: iteration,
483
- previousResults,
484
- isFirstIteration: false,
485
- isLastAllowedIteration: true,
486
- };
487
- let completionUpdates = {};
488
- if (exitReason === "maxIterations" && config.onMaxIterations) {
489
- completionUpdates = await config.onMaxIterations(context, finalLoopContext);
490
- }
491
- else if (exitReason === "condition" && config.onComplete) {
492
- completionUpdates = await config.onComplete(context, finalLoopContext);
493
- }
494
- const output = {
495
- exitReason,
496
- iterations: iteration,
497
- previousResults,
498
- ...completionUpdates,
499
- };
500
- const state = {
501
- nodeId: node.id,
502
- status: exitReason === "error" ? "failed" : "completed",
503
- output,
504
- error: lastError,
505
- attempt: 1,
506
- startedAt: new Date(startTime),
507
- completedAt: new Date(),
508
- };
509
- this.config.onNodeComplete?.(node.id, state);
510
- return {
511
- state,
512
- contextUpdates: {
513
- [node.id]: output,
514
- ...completionUpdates,
515
- },
516
- waiting: false,
517
- };
518
- }
519
327
  async checkpoint(runId, nodeId, context, nodeStates) {
520
328
  if (!this.config.checkpointManager) {
521
329
  return;
@@ -529,4 +337,17 @@ export class DAGExecutor {
529
337
  };
530
338
  await this.config.checkpointManager.save(runId, checkpoint);
531
339
  }
340
+ async executeChildGraph(nodes, run, options) {
341
+ if (!options?.maxConcurrency) {
342
+ return await this.execute(nodes, run);
343
+ }
344
+ const originalConcurrency = this.config.maxConcurrency;
345
+ this.config.maxConcurrency = options.maxConcurrency;
346
+ try {
347
+ return await this.execute(nodes, run);
348
+ }
349
+ finally {
350
+ this.config.maxConcurrency = originalConcurrency;
351
+ }
352
+ }
532
353
  }
@@ -0,0 +1,13 @@
1
+ import type { LoopNodeConfig, NodeState, WorkflowContext, WorkflowNode } from "../../types.js";
2
+ import type { NodeExecutionResult } from "./types.js";
3
+ import type { NodeStrategyRuntime } from "./node-strategy-types.js";
4
+ interface ExecuteLoopNodeStrategyInput {
5
+ node: WorkflowNode;
6
+ config: LoopNodeConfig;
7
+ context: WorkflowContext;
8
+ nodeStates: Record<string, NodeState>;
9
+ runtime: NodeStrategyRuntime;
10
+ }
11
+ export declare function executeLoopNodeStrategy(input: ExecuteLoopNodeStrategyInput): Promise<NodeExecutionResult>;
12
+ export {};
13
+ //# sourceMappingURL=loop-node-strategy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop-node-strategy.d.ts","sourceRoot":"","sources":["../../../../../src/src/workflow/executor/dag/loop-node-strategy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,cAAc,EACd,SAAS,EACT,eAAe,EACf,YAAY,EACb,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEpE,UAAU,4BAA4B;IACpC,IAAI,EAAE,YAAY,CAAC;IACnB,MAAM,EAAE,cAAc,CAAC;IACvB,OAAO,EAAE,eAAe,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACtC,OAAO,EAAE,mBAAmB,CAAC;CAC9B;AAQD,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,4BAA4B,GAClC,OAAO,CAAC,mBAAmB,CAAC,CAwJ9B"}
@@ -0,0 +1,134 @@
1
+ import { parseDuration } from "../../types.js";
2
+ import { sleep } from "./utils.js";
3
+ export async function executeLoopNodeStrategy(input) {
4
+ const { node, config, context, nodeStates, runtime } = input;
5
+ const startTime = Date.now();
6
+ const previousResults = [];
7
+ let iteration = 0;
8
+ let exitReason = "condition";
9
+ let lastError;
10
+ const existingLoopState = context[`${node.id}_loop_state`];
11
+ // Child node states for the in-flight (resumed) iteration, so its already
12
+ // completed steps are not re-executed on resume (H9).
13
+ let resumeIterationNodeStates;
14
+ let resumeIteration;
15
+ if (existingLoopState) {
16
+ iteration = existingLoopState.iteration;
17
+ previousResults.push(...existingLoopState.previousResults);
18
+ resumeIterationNodeStates = existingLoopState.iterationNodeStates;
19
+ resumeIteration = existingLoopState.iteration;
20
+ }
21
+ while (iteration < config.maxIterations) {
22
+ const loopContext = {
23
+ iteration,
24
+ totalIterations: iteration,
25
+ previousResults: [...previousResults],
26
+ isFirstIteration: iteration === 0,
27
+ isLastAllowedIteration: iteration === config.maxIterations - 1,
28
+ };
29
+ if (!(await config.while(context, loopContext))) {
30
+ exitReason = "condition";
31
+ break;
32
+ }
33
+ const steps = typeof config.steps === "function"
34
+ ? config.steps(context, loopContext)
35
+ : config.steps;
36
+ // On resume, rehydrate the in-flight iteration's child node states so its
37
+ // already-completed steps are skipped instead of re-executed (H9).
38
+ const iterationNodeStates = resumeIteration === iteration && resumeIterationNodeStates
39
+ ? { ...resumeIterationNodeStates }
40
+ : {};
41
+ // Only rehydrate once; subsequent iterations start fresh.
42
+ resumeIterationNodeStates = undefined;
43
+ const result = await runtime.executeChildGraph(steps, {
44
+ id: `${node.id}_iter_${iteration}`,
45
+ workflowId: "",
46
+ status: "running",
47
+ input: context.input,
48
+ nodeStates: iterationNodeStates,
49
+ currentNodes: [],
50
+ context: { ...context, _loop: loopContext },
51
+ checkpoints: [],
52
+ pendingApprovals: [],
53
+ createdAt: new Date(),
54
+ });
55
+ if (result.waiting) {
56
+ Object.assign(nodeStates, result.nodeStates);
57
+ const state = {
58
+ nodeId: node.id,
59
+ status: "running",
60
+ output: { iteration, waiting: true, previousResults },
61
+ attempt: 1,
62
+ startedAt: new Date(startTime),
63
+ };
64
+ return {
65
+ state,
66
+ contextUpdates: {
67
+ ...result.context,
68
+ [`${node.id}_loop_state`]: {
69
+ iteration,
70
+ previousResults,
71
+ // Persist the in-flight iteration's child states so completed
72
+ // steps are not re-executed when this iteration resumes (H9).
73
+ iterationNodeStates: result.nodeStates,
74
+ },
75
+ },
76
+ waiting: true,
77
+ };
78
+ }
79
+ if (result.error) {
80
+ lastError = result.error;
81
+ exitReason = "error";
82
+ break;
83
+ }
84
+ previousResults.push(result.context);
85
+ Object.assign(context, result.context);
86
+ Object.assign(nodeStates, result.nodeStates);
87
+ if (config.delay && iteration < config.maxIterations - 1) {
88
+ const delayMs = typeof config.delay === "number" ? config.delay : parseDuration(config.delay);
89
+ await sleep(delayMs);
90
+ }
91
+ iteration++;
92
+ }
93
+ if (iteration >= config.maxIterations && exitReason !== "condition") {
94
+ exitReason = "maxIterations";
95
+ }
96
+ const finalLoopContext = {
97
+ iteration,
98
+ totalIterations: iteration,
99
+ previousResults,
100
+ isFirstIteration: false,
101
+ isLastAllowedIteration: true,
102
+ };
103
+ let completionUpdates = {};
104
+ if (exitReason === "maxIterations" && config.onMaxIterations) {
105
+ completionUpdates = await config.onMaxIterations(context, finalLoopContext);
106
+ }
107
+ else if (exitReason === "condition" && config.onComplete) {
108
+ completionUpdates = await config.onComplete(context, finalLoopContext);
109
+ }
110
+ const output = {
111
+ exitReason,
112
+ iterations: iteration,
113
+ previousResults,
114
+ ...completionUpdates,
115
+ };
116
+ const state = {
117
+ nodeId: node.id,
118
+ status: exitReason === "error" ? "failed" : "completed",
119
+ output,
120
+ error: lastError,
121
+ attempt: 1,
122
+ startedAt: new Date(startTime),
123
+ completedAt: new Date(),
124
+ };
125
+ runtime.onNodeComplete?.(node.id, state);
126
+ return {
127
+ state,
128
+ contextUpdates: {
129
+ [node.id]: output,
130
+ ...completionUpdates,
131
+ },
132
+ waiting: false,
133
+ };
134
+ }
@@ -0,0 +1,13 @@
1
+ import type { MapNodeConfig, NodeState, WorkflowContext, WorkflowNode } from "../../types.js";
2
+ import type { NodeExecutionResult } from "./types.js";
3
+ import type { NodeStrategyRuntime } from "./node-strategy-types.js";
4
+ interface ExecuteMapNodeStrategyInput {
5
+ node: WorkflowNode;
6
+ config: MapNodeConfig;
7
+ context: WorkflowContext;
8
+ nodeStates: Record<string, NodeState>;
9
+ runtime: NodeStrategyRuntime;
10
+ }
11
+ export declare function executeMapNodeStrategy(input: ExecuteMapNodeStrategyInput): Promise<NodeExecutionResult>;
12
+ export {};
13
+ //# sourceMappingURL=map-node-strategy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"map-node-strategy.d.ts","sourceRoot":"","sources":["../../../../../src/src/workflow/executor/dag/map-node-strategy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,SAAS,EACT,eAAe,EAEf,YAAY,EAEb,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEpE,UAAU,2BAA2B;IACnC,IAAI,EAAE,YAAY,CAAC;IACnB,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,eAAe,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACtC,OAAO,EAAE,mBAAmB,CAAC;CAC9B;AAqCD,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,2BAA2B,GACjC,OAAO,CAAC,mBAAmB,CAAC,CAgE9B"}
@@ -0,0 +1,78 @@
1
+ import { INVALID_ARGUMENT } from "../../../errors/index.js";
2
+ import { deriveNodeStatus } from "./utils.js";
3
+ function isWorkflowDefinition(processor) {
4
+ return typeof processor === "object" && processor !== null && "steps" in processor;
5
+ }
6
+ function createMapChildNodes(node, config, items) {
7
+ return items.map((item, i) => {
8
+ const childId = `${node.id}_${i}`;
9
+ if (isWorkflowDefinition(config.processor)) {
10
+ return {
11
+ id: childId,
12
+ config: {
13
+ type: "subWorkflow",
14
+ workflow: config.processor,
15
+ input: item,
16
+ retry: config.retry,
17
+ checkpoint: false,
18
+ },
19
+ };
20
+ }
21
+ const processorConfig = { ...config.processor.config };
22
+ if (processorConfig.type === "step") {
23
+ processorConfig.input = item;
24
+ }
25
+ return { id: childId, config: processorConfig };
26
+ });
27
+ }
28
+ export async function executeMapNodeStrategy(input) {
29
+ const { node, config, context, nodeStates, runtime } = input;
30
+ const startTime = Date.now();
31
+ const items = typeof config.items === "function" ? await config.items(context) : config.items;
32
+ if (!Array.isArray(items)) {
33
+ throw INVALID_ARGUMENT.create({ detail: `Map node "${node.id}" items must be an array` });
34
+ }
35
+ if (items.length === 0) {
36
+ const state = {
37
+ nodeId: node.id,
38
+ status: "completed",
39
+ output: [],
40
+ attempt: 1,
41
+ startedAt: new Date(startTime),
42
+ completedAt: new Date(),
43
+ };
44
+ return { state, contextUpdates: { [node.id]: [] }, waiting: false };
45
+ }
46
+ const childNodes = createMapChildNodes(node, config, items);
47
+ const result = await runtime.executeChildGraph(childNodes, {
48
+ id: `${node.id}_map`,
49
+ workflowId: "",
50
+ status: "running",
51
+ input: context.input,
52
+ // Carry already-accumulated child states so completed children are
53
+ // skipped on resume instead of re-executing (H8).
54
+ nodeStates,
55
+ currentNodes: [],
56
+ context: { ...context },
57
+ checkpoints: [],
58
+ pendingApprovals: [],
59
+ createdAt: new Date(),
60
+ }, config.concurrency ? { maxConcurrency: config.concurrency } : undefined);
61
+ Object.assign(nodeStates, result.nodeStates);
62
+ const outputs = childNodes.map((child) => result.nodeStates[child.id]?.output);
63
+ const state = {
64
+ nodeId: node.id,
65
+ status: deriveNodeStatus(result.completed, result.waiting),
66
+ output: outputs,
67
+ error: result.error,
68
+ attempt: 1,
69
+ startedAt: new Date(startTime),
70
+ completedAt: result.completed ? new Date() : undefined,
71
+ };
72
+ runtime.onNodeComplete?.(node.id, state);
73
+ return {
74
+ state,
75
+ contextUpdates: result.completed ? { [node.id]: outputs } : {},
76
+ waiting: result.waiting,
77
+ };
78
+ }
@@ -0,0 +1,11 @@
1
+ import type { NodeState, WorkflowNode, WorkflowRun } from "../../types.js";
2
+ import type { DAGExecutionResult } from "./types.js";
3
+ export interface ChildGraphExecutionOptions {
4
+ maxConcurrency?: number;
5
+ }
6
+ export type ExecuteChildGraph = (nodes: WorkflowNode[], run: WorkflowRun, options?: ChildGraphExecutionOptions) => Promise<DAGExecutionResult>;
7
+ export interface NodeStrategyRuntime {
8
+ executeChildGraph: ExecuteChildGraph;
9
+ onNodeComplete?: (nodeId: string, state: NodeState) => void;
10
+ }
11
+ //# sourceMappingURL=node-strategy-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-strategy-types.d.ts","sourceRoot":"","sources":["../../../../../src/src/workflow/executor/dag/node-strategy-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,MAAM,WAAW,0BAA0B;IACzC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,iBAAiB,GAAG,CAC9B,KAAK,EAAE,YAAY,EAAE,EACrB,GAAG,EAAE,WAAW,EAChB,OAAO,CAAC,EAAE,0BAA0B,KACjC,OAAO,CAAC,kBAAkB,CAAC,CAAC;AAEjC,MAAM,WAAW,mBAAmB;IAClC,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;CAC7D"}
@@ -1 +1 @@
1
- {"version":3,"file":"run-manager.d.ts","sourceRoot":"","sources":["../../../../src/src/workflow/worker/run-manager.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAoC,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAG9F,OAAO,KAAK,EAAsB,kBAAkB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAehG,YAAY,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAE9F;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,uCAAuC;IACvC,OAAO,EAAE,eAAe,CAAC;IAEzB,6DAA6D;IAC7D,QAAQ,EAAE,WAAW,CAAC;IAEtB,0DAA0D;IAC1D,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE7B,wDAAwD;IACxD,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,wCAAwC;IACxC,uBAAuB,CAAC,EAAE,MAAM,CAAC;IAEjC,4DAA4D;IAC5D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,2BAA2B;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;AAExE;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,aAAa,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,IAAI,CAAC;IAClB,WAAW,CAAC,EAAE,IAAI,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,UAAU,gBAAgB;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,kBAAkB,CAAC;IAC3B,SAAS,EAAE,IAAI,CAAC;CACjB;AAOD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,WAAW,CAAC,CAAwC;IAC5D,OAAO,CAAC,gBAAgB,CAAuC;IAC/D,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,SAAS,CAAS;gBAEd,MAAM,EAAE,wBAAwB;IAuB5C;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAsB5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA+B3B;;OAEG;IACH,QAAQ,IAAI,YAAY;IAIxB;;OAEG;IACH,mBAAmB,IAAI,gBAAgB,EAAE;IAIzC;;OAEG;IACH,YAAY,IAAI,MAAM;IAItB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAWxB;;OAEG;YACW,IAAI;IAyGlB;;OAEG;YACW,wBAAwB;IAuCtC;;OAEG;YACW,0BAA0B;IAoDxC;;OAEG;IACH,OAAO,CAAC,WAAW;CAIpB;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,wBAAwB,GAC/B,kBAAkB,CAEpB"}
1
+ {"version":3,"file":"run-manager.d.ts","sourceRoot":"","sources":["../../../../src/src/workflow/worker/run-manager.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAoC,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAG9F,OAAO,KAAK,EAAsB,kBAAkB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAehG,YAAY,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAE9F;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,uCAAuC;IACvC,OAAO,EAAE,eAAe,CAAC;IAEzB,6DAA6D;IAC7D,QAAQ,EAAE,WAAW,CAAC;IAEtB,0DAA0D;IAC1D,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE7B,wDAAwD;IACxD,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,wCAAwC;IACxC,uBAAuB,CAAC,EAAE,MAAM,CAAC;IAEjC,4DAA4D;IAC5D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,2BAA2B;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;AAExE;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,aAAa,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,IAAI,CAAC;IAClB,WAAW,CAAC,EAAE,IAAI,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,UAAU,gBAAgB;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,kBAAkB,CAAC;IAC3B,SAAS,EAAE,IAAI,CAAC;CACjB;AAOD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,WAAW,CAAC,CAAwC;IAC5D,OAAO,CAAC,gBAAgB,CAAuC;IAC/D,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,SAAS,CAAS;gBAEd,MAAM,EAAE,wBAAwB;IAuB5C;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAsB5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA+B3B;;OAEG;IACH,QAAQ,IAAI,YAAY;IAIxB;;OAEG;IACH,mBAAmB,IAAI,gBAAgB,EAAE;IAIzC;;OAEG;IACH,YAAY,IAAI,MAAM;IAItB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAWxB;;OAEG;YACW,IAAI;IAyGlB;;OAEG;YACW,wBAAwB;IAuCtC;;OAEG;YACW,0BAA0B;IAqDxC;;OAEG;IACH,OAAO,CAAC,WAAW;CAIpB;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,wBAAwB,GAC/B,kBAAkB,CAEpB"}
@@ -303,6 +303,7 @@ export class WorkflowRunManager {
303
303
  }
304
304
  catch (error) {
305
305
  logger.error(`Failed to create run execution for ${run.id}:`, error);
306
+ this.stats.executionsFailed++;
306
307
  // Mark workflow as failed
307
308
  await this.config.backend.updateRun(run.id, {
308
309
  status: "failed",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "veryfront",
3
- "version": "0.1.699",
3
+ "version": "0.1.701",
4
4
  "description": "The simplest way to build AI-powered apps",
5
5
  "keywords": [
6
6
  "react",