veryfront 0.1.700 → 0.1.703

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 (37) hide show
  1. package/esm/cli/templates/manifest.d.ts +0 -2
  2. package/esm/cli/templates/manifest.js +1 -3
  3. package/esm/deno.js +1 -1
  4. package/esm/src/agent/streaming/fork-runtime-part-mapper.d.ts +59 -0
  5. package/esm/src/agent/streaming/fork-runtime-part-mapper.d.ts.map +1 -0
  6. package/esm/src/agent/streaming/fork-runtime-part-mapper.js +246 -0
  7. package/esm/src/agent/streaming/fork-runtime-stream.d.ts +2 -50
  8. package/esm/src/agent/streaming/fork-runtime-stream.d.ts.map +1 -1
  9. package/esm/src/agent/streaming/fork-runtime-stream.js +3 -245
  10. package/esm/src/integrations/_data.d.ts.map +1 -1
  11. package/esm/src/integrations/_data.js +1 -42
  12. package/esm/src/oauth/providers/common.d.ts.map +1 -1
  13. package/esm/src/oauth/providers/common.js +6 -1
  14. package/esm/src/utils/version-constant.d.ts +1 -1
  15. package/esm/src/utils/version-constant.js +1 -1
  16. package/esm/src/workflow/claude-code/react/event-state-reducer.d.ts +37 -0
  17. package/esm/src/workflow/claude-code/react/event-state-reducer.d.ts.map +1 -0
  18. package/esm/src/workflow/claude-code/react/event-state-reducer.js +104 -0
  19. package/esm/src/workflow/claude-code/react/use-claude-code-stream.d.ts +3 -35
  20. package/esm/src/workflow/claude-code/react/use-claude-code-stream.d.ts.map +1 -1
  21. package/esm/src/workflow/claude-code/react/use-claude-code-stream.js +9 -78
  22. package/esm/src/workflow/claude-code/react/use-claude-code-websocket.d.ts +2 -27
  23. package/esm/src/workflow/claude-code/react/use-claude-code-websocket.d.ts.map +1 -1
  24. package/esm/src/workflow/claude-code/react/use-claude-code-websocket.js +5 -57
  25. package/esm/src/workflow/executor/dag/index.d.ts +1 -2
  26. package/esm/src/workflow/executor/dag/index.d.ts.map +1 -1
  27. package/esm/src/workflow/executor/dag/index.js +37 -216
  28. package/esm/src/workflow/executor/dag/loop-node-strategy.d.ts +13 -0
  29. package/esm/src/workflow/executor/dag/loop-node-strategy.d.ts.map +1 -0
  30. package/esm/src/workflow/executor/dag/loop-node-strategy.js +134 -0
  31. package/esm/src/workflow/executor/dag/map-node-strategy.d.ts +13 -0
  32. package/esm/src/workflow/executor/dag/map-node-strategy.d.ts.map +1 -0
  33. package/esm/src/workflow/executor/dag/map-node-strategy.js +78 -0
  34. package/esm/src/workflow/executor/dag/node-strategy-types.d.ts +11 -0
  35. package/esm/src/workflow/executor/dag/node-strategy-types.d.ts.map +1 -0
  36. package/esm/src/workflow/executor/dag/node-strategy-types.js +1 -0
  37. package/package.json +1 -1
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import * as dntShim from "../../../../_dnt.shims.js";
7
7
  import { useCallback, useEffect, useRef, useState } from "../../../../react/react.js";
8
+ import { createClaudeCodeEventState, reduceClaudeCodeEventState, } from "./event-state-reducer.js";
8
9
  import { REQUEST_ERROR } from "../../../errors/index.js";
9
10
  /** Default delay before reconnecting after disconnect */
10
11
  const DEFAULT_RECONNECT_DELAY_MS = 1_000;
@@ -48,16 +49,9 @@ const DEFAULT_MAX_EVENT_HISTORY = 100;
48
49
  export function useClaudeCodeStream(options) {
49
50
  const { url, runId, autoConnect = true, autoReconnect = true, maxReconnectAttempts = 5, reconnectDelay = DEFAULT_RECONNECT_DELAY_MS, keepEventHistory = false, maxEventHistory = DEFAULT_MAX_EVENT_HISTORY, onEvent, onConnect, onDisconnect, onError, onComplete, } = options;
50
51
  const [state, setState] = useState({
52
+ ...createClaudeCodeEventState(),
51
53
  isConnected: false,
52
- isRunning: false,
53
- currentIteration: 0,
54
- maxIterations: 20,
55
- text: "",
56
- currentTool: null,
57
- toolCalls: [],
58
54
  allToolCalls: [],
59
- result: null,
60
- error: null,
61
55
  events: [],
62
56
  });
63
57
  const eventSourceRef = useRef(null);
@@ -67,76 +61,13 @@ export function useClaudeCodeStream(options) {
67
61
  const processEvent = useCallback((event) => {
68
62
  onEvent?.(event);
69
63
  setState((prev) => {
70
- const newState = { ...prev };
71
- // Keep event history if enabled
72
- if (keepEventHistory) {
73
- newState.events = [...prev.events, event].slice(-maxEventHistory);
74
- }
75
- switch (event.type) {
76
- case "iteration_start":
77
- newState.isRunning = true;
78
- newState.currentIteration = event.iteration;
79
- newState.maxIterations = event.maxIterations;
80
- newState.toolCalls = [];
81
- newState.currentTool = null;
82
- break;
83
- case "text_delta":
84
- newState.text = prev.text + event.content;
85
- break;
86
- case "text_complete":
87
- newState.text = event.content;
88
- break;
89
- case "tool_call_start":
90
- newState.currentTool = {
91
- id: event.toolCallId,
92
- name: event.toolName,
93
- input: {},
94
- };
95
- break;
96
- case "tool_call_complete":
97
- newState.currentTool = null;
98
- newState.toolCalls = [
99
- ...prev.toolCalls,
100
- {
101
- id: event.toolCallId,
102
- name: event.toolName,
103
- input: event.input,
104
- },
105
- ];
106
- break;
107
- case "tool_result":
108
- // Update the tool call with its result
109
- newState.toolCalls = prev.toolCalls.map((tc) => tc.id === event.toolCallId
110
- ? { ...tc, output: event.output, isError: event.isError }
111
- : tc);
112
- // Add to all tool calls
113
- newState.allToolCalls = [
114
- ...prev.allToolCalls,
115
- {
116
- iteration: event.iteration || prev.currentIteration,
117
- id: event.toolCallId,
118
- name: event.toolName,
119
- input: prev.toolCalls.find((tc) => tc.id === event.toolCallId)?.input || {},
120
- output: event.output,
121
- isError: event.isError,
122
- },
123
- ];
124
- break;
125
- case "iteration_complete":
126
- newState.currentTool = null;
127
- break;
128
- case "complete":
129
- newState.isRunning = false;
130
- newState.result = event.result;
131
- newState.currentTool = null;
132
- onComplete?.(event.result);
133
- break;
134
- case "error":
135
- newState.error = event.message;
136
- if (!event.recoverable) {
137
- newState.isRunning = false;
138
- }
139
- break;
64
+ const newState = reduceClaudeCodeEventState(prev, event, {
65
+ keepEventHistory,
66
+ maxEventHistory,
67
+ trackAllToolCalls: true,
68
+ });
69
+ if (event.type === "complete") {
70
+ onComplete?.(event.result);
140
71
  }
141
72
  return newState;
142
73
  });
@@ -1,4 +1,5 @@
1
1
  import type { ClaudeCodeEventExtended, ClaudeCodeResult } from "../types.js";
2
+ import { type ClaudeCodeEventState } from "./event-state-reducer.js";
2
3
  /**
3
4
  * Pending approval state
4
5
  */
@@ -22,41 +23,15 @@ export interface PendingInput {
22
23
  /**
23
24
  * State for Claude Code WebSocket
24
25
  */
25
- export interface UseClaudeCodeWebSocketState {
26
+ export interface UseClaudeCodeWebSocketState extends ClaudeCodeEventState {
26
27
  /** Whether currently connected */
27
28
  isConnected: boolean;
28
- /** Whether agent is currently executing */
29
- isRunning: boolean;
30
29
  /** Whether agent was cancelled */
31
30
  isCancelled: boolean;
32
- /** Current iteration number */
33
- currentIteration: number;
34
- /** Maximum iterations allowed */
35
- maxIterations: number;
36
- /** Accumulated text output */
37
- text: string;
38
- /** Current tool being executed (if any) */
39
- currentTool: {
40
- id: string;
41
- name: string;
42
- input: Record<string, unknown>;
43
- } | null;
44
- /** Tool calls in current iteration */
45
- toolCalls: Array<{
46
- id: string;
47
- name: string;
48
- input: Record<string, unknown>;
49
- output?: string;
50
- isError?: boolean;
51
- }>;
52
31
  /** Pending approval requests */
53
32
  pendingApprovals: PendingApproval[];
54
33
  /** Pending input request (if any) */
55
34
  pendingInput: PendingInput | null;
56
- /** Final result (when complete) */
57
- result: ClaudeCodeResult | null;
58
- /** Error message (if any) */
59
- error: string | null;
60
35
  }
61
36
  /**
62
37
  * Options for useClaudeCodeWebSocket hook
@@ -1 +1 @@
1
- {"version":3,"file":"use-claude-code-websocket.d.ts","sourceRoot":"","sources":["../../../../../src/src/workflow/claude-code/react/use-claude-code-websocket.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"use-claude-code-websocket.d.ts","sourceRoot":"","sources":["../../../../../src/src/workflow/claude-code/react/use-claude-code-websocket.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAGV,uBAAuB,EACvB,gBAAgB,EAEjB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,KAAK,oBAAoB,EAI1B,MAAM,0BAA0B,CAAC;AASlC;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,2BAA4B,SAAQ,oBAAoB;IACvE,kCAAkC;IAClC,WAAW,EAAE,OAAO,CAAC;IAErB,kCAAkC;IAClC,WAAW,EAAE,OAAO,CAAC;IAErB,gCAAgC;IAChC,gBAAgB,EAAE,eAAe,EAAE,CAAC;IAEpC,qCAAqC;IACrC,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,6BAA6B;IAC5C,6BAA6B;IAC7B,GAAG,EAAE,MAAM,CAAC;IAEZ,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;IAEd,4BAA4B;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,8BAA8B;IAC9B,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB,6BAA6B;IAC7B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAE9B,2BAA2B;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,yBAAyB;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,gBAAgB;IAChB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,uBAAuB,KAAK,IAAI,CAAC;IACnD,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAChD,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,eAAe,KAAK,IAAI,CAAC;IACxD,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;CAChD;AAED;;GAEG;AACH,MAAM,WAAW,6BAA6B;IAC5C,2BAA2B;IAC3B,OAAO,EAAE,MAAM,IAAI,CAAC;IAEpB,gCAAgC;IAChC,UAAU,EAAE,MAAM,IAAI,CAAC;IAEvB,iCAAiC;IACjC,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAElC,kCAAkC;IAClC,OAAO,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAEtC,iCAAiC;IACjC,MAAM,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAEtD,sBAAsB;IACtB,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,6BAA6B,GACrC,2BAA2B,GAAG,6BAA6B,CAkR7D"}
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import * as dntShim from "../../../../_dnt.shims.js";
7
7
  import { useCallback, useEffect, useRef, useState } from "../../../../react/react.js";
8
+ import { createClaudeCodeEventState, isClaudeCodeCoreEvent, reduceClaudeCodeEventState, } from "./event-state-reducer.js";
8
9
  import { NETWORK_ERROR, REQUEST_ERROR } from "../../../errors/index.js";
9
10
  /** Default delay before reconnecting after disconnect */
10
11
  const DEFAULT_RECONNECT_DELAY_MS = 1_000;
@@ -52,18 +53,11 @@ const DEFAULT_PING_INTERVAL_MS = 30_000;
52
53
  export function useClaudeCodeWebSocket(options) {
53
54
  const { url, runId, autoConnect = true, autoReconnect = true, maxReconnectAttempts = 5, reconnectDelay = DEFAULT_RECONNECT_DELAY_MS, pingInterval = DEFAULT_PING_INTERVAL_MS, onEvent, onConnect, onDisconnect, onError, onComplete, onApprovalRequest, onInputRequest, } = options;
54
55
  const [state, setState] = useState({
56
+ ...createClaudeCodeEventState(),
55
57
  isConnected: false,
56
- isRunning: false,
57
58
  isCancelled: false,
58
- currentIteration: 0,
59
- maxIterations: 20,
60
- text: "",
61
- currentTool: null,
62
- toolCalls: [],
63
59
  pendingApprovals: [],
64
60
  pendingInput: null,
65
- result: null,
66
- error: null,
67
61
  });
68
62
  const socketRef = useRef(null);
69
63
  const reconnectAttemptsRef = useRef(0);
@@ -73,61 +67,15 @@ export function useClaudeCodeWebSocket(options) {
73
67
  const processEvent = useCallback((event) => {
74
68
  onEvent?.(event);
75
69
  setState((prev) => {
76
- const newState = { ...prev };
70
+ const newState = isClaudeCodeCoreEvent(event)
71
+ ? reduceClaudeCodeEventState(prev, event)
72
+ : { ...prev };
77
73
  switch (event.type) {
78
- case "iteration_start":
79
- newState.isRunning = true;
80
- newState.currentIteration = event.iteration;
81
- newState.maxIterations = event.maxIterations;
82
- newState.toolCalls = [];
83
- newState.currentTool = null;
84
- break;
85
- case "text_delta":
86
- newState.text = prev.text + event.content;
87
- break;
88
- case "text_complete":
89
- newState.text = event.content;
90
- break;
91
- case "tool_call_start":
92
- newState.currentTool = {
93
- id: event.toolCallId,
94
- name: event.toolName,
95
- input: {},
96
- };
97
- break;
98
- case "tool_call_complete":
99
- newState.currentTool = null;
100
- newState.toolCalls = [
101
- ...prev.toolCalls,
102
- {
103
- id: event.toolCallId,
104
- name: event.toolName,
105
- input: event.input,
106
- },
107
- ];
108
- break;
109
- case "tool_result":
110
- newState.toolCalls = prev.toolCalls.map((tc) => tc.id === event.toolCallId
111
- ? { ...tc, output: event.output, isError: event.isError }
112
- : tc);
113
- break;
114
- case "iteration_complete":
115
- newState.currentTool = null;
116
- break;
117
74
  case "complete":
118
- newState.isRunning = false;
119
- newState.result = event.result;
120
- newState.currentTool = null;
121
75
  newState.pendingApprovals = [];
122
76
  newState.pendingInput = null;
123
77
  onComplete?.(event.result);
124
78
  break;
125
- case "error":
126
- newState.error = event.message;
127
- if (!event.recoverable) {
128
- newState.isRunning = false;
129
- }
130
- break;
131
79
  case "cancelled":
132
80
  newState.isRunning = false;
133
81
  newState.isCancelled = true;
@@ -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"}