illuma-agents 1.0.26 → 1.0.28

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 (42) hide show
  1. package/dist/cjs/graphs/Graph.cjs +28 -2
  2. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  3. package/dist/cjs/graphs/MultiAgentGraph.cjs +108 -0
  4. package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
  5. package/dist/cjs/messages/format.cjs.map +1 -1
  6. package/dist/cjs/stream.cjs +27 -0
  7. package/dist/cjs/stream.cjs.map +1 -1
  8. package/dist/cjs/tools/BrowserTools.cjs +125 -113
  9. package/dist/cjs/tools/BrowserTools.cjs.map +1 -1
  10. package/dist/esm/graphs/Graph.mjs +28 -2
  11. package/dist/esm/graphs/Graph.mjs.map +1 -1
  12. package/dist/esm/graphs/MultiAgentGraph.mjs +108 -0
  13. package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
  14. package/dist/esm/messages/format.mjs.map +1 -1
  15. package/dist/esm/stream.mjs +27 -0
  16. package/dist/esm/stream.mjs.map +1 -1
  17. package/dist/esm/tools/BrowserTools.mjs +125 -113
  18. package/dist/esm/tools/BrowserTools.mjs.map +1 -1
  19. package/dist/types/graphs/Graph.d.ts +14 -0
  20. package/dist/types/graphs/MultiAgentGraph.d.ts +41 -0
  21. package/dist/types/messages/format.d.ts +1 -1
  22. package/dist/types/tools/BrowserTools.d.ts +45 -5
  23. package/dist/types/types/stream.d.ts +13 -0
  24. package/package.json +4 -2
  25. package/src/graphs/Graph.ts +30 -2
  26. package/src/graphs/MultiAgentGraph.ts +119 -0
  27. package/src/messages/format.ts +2 -2
  28. package/src/scripts/multi-agent-chain.ts +59 -6
  29. package/src/scripts/multi-agent-parallel-start.ts +265 -0
  30. package/src/scripts/multi-agent-parallel.ts +61 -10
  31. package/src/scripts/multi-agent-sequence.ts +6 -1
  32. package/src/scripts/parallel-asymmetric-tools-test.ts +274 -0
  33. package/src/scripts/parallel-full-metadata-test.ts +240 -0
  34. package/src/scripts/parallel-tools-test.ts +340 -0
  35. package/src/scripts/sequential-full-metadata-test.ts +197 -0
  36. package/src/scripts/single-agent-metadata-test.ts +198 -0
  37. package/src/scripts/test-thinking-handoff.ts +8 -0
  38. package/src/scripts/tools.ts +31 -11
  39. package/src/stream.ts +32 -0
  40. package/src/tools/BrowserTools.ts +356 -310
  41. package/src/tools/__tests__/BrowserTools.test.ts +263 -257
  42. package/src/types/stream.ts +15 -0
@@ -19,6 +19,17 @@ export declare class MultiAgentGraph extends StandardGraph {
19
19
  private startingNodes;
20
20
  private directEdges;
21
21
  private handoffEdges;
22
+ /**
23
+ * Map of agentId to parallel group info.
24
+ * Contains groupId (incrementing number reflecting execution order) for agents in parallel groups.
25
+ * Sequential agents (not in any parallel group) have undefined entry.
26
+ *
27
+ * Example for: researcher -> [analyst1, analyst2, analyst3] -> summarizer
28
+ * - researcher: undefined (sequential, order 0)
29
+ * - analyst1, analyst2, analyst3: { groupId: 1 } (parallel group, order 1)
30
+ * - summarizer: undefined (sequential, order 2)
31
+ */
32
+ private agentParallelGroups;
22
33
  constructor(input: t.MultiAgentGraphInput);
23
34
  /**
24
35
  * Categorize edges into handoff and direct types
@@ -28,6 +39,36 @@ export declare class MultiAgentGraph extends StandardGraph {
28
39
  * Analyze graph structure to determine starting nodes and connections
29
40
  */
30
41
  private analyzeGraph;
42
+ /**
43
+ * Compute parallel groups by traversing the graph in execution order.
44
+ * Assigns incrementing group IDs that reflect the sequential order of execution.
45
+ *
46
+ * For: researcher -> [analyst1, analyst2, analyst3] -> summarizer
47
+ * - researcher: no group (first sequential node)
48
+ * - analyst1, analyst2, analyst3: groupId 1 (first parallel group)
49
+ * - summarizer: no group (next sequential node)
50
+ *
51
+ * This allows frontend to render in order:
52
+ * Row 0: researcher
53
+ * Row 1: [analyst1, analyst2, analyst3] (grouped)
54
+ * Row 2: summarizer
55
+ */
56
+ private computeParallelCapability;
57
+ /**
58
+ * Get the parallel group ID for an agent, if any.
59
+ * Returns undefined if the agent is not part of a parallel group.
60
+ * Group IDs are incrementing numbers reflecting execution order.
61
+ */
62
+ getParallelGroupId(agentId: string): number | undefined;
63
+ /**
64
+ * Override to indicate this is a multi-agent graph.
65
+ * Enables agentId to be included in RunStep for frontend agent labeling.
66
+ */
67
+ protected isMultiAgentGraph(): boolean;
68
+ /**
69
+ * Override base class method to provide parallel group IDs for run steps.
70
+ */
71
+ protected getParallelGroupIdForAgent(agentId: string): number | undefined;
31
72
  /**
32
73
  * Create handoff tools for agents based on handoff edges only
33
74
  */
@@ -105,7 +105,7 @@ export declare const labelContentByAgent: (contentParts: MessageContentComplex[]
105
105
  * @param tools - Optional set of tool names that are allowed in the request.
106
106
  * @returns - Object containing formatted messages and updated indexTokenCountMap if provided.
107
107
  */
108
- export declare const formatAgentMessages: (payload: TPayload, indexTokenCountMap?: Record<number, number>, tools?: Set<string>) => {
108
+ export declare const formatAgentMessages: (payload: TPayload, indexTokenCountMap?: Record<number, number | undefined>, tools?: Set<string>) => {
109
109
  messages: Array<HumanMessage | AIMessage | SystemMessage | ToolMessage>;
110
110
  indexTokenCountMap?: Record<number, number>;
111
111
  };
@@ -15,7 +15,29 @@ export declare const EBrowserTools: {
15
15
  readonly SCREENSHOT: "browser_screenshot";
16
16
  readonly GET_PAGE_STATE: "browser_get_page_state";
17
17
  };
18
- export type BrowserToolName = typeof EBrowserTools[keyof typeof EBrowserTools];
18
+ export type BrowserToolName = (typeof EBrowserTools)[keyof typeof EBrowserTools];
19
+ /**
20
+ * Callback function type for waiting on browser action results
21
+ * This allows the server (Ranger) to provide a callback that waits for the extension
22
+ * to POST results back to the server before returning to the LLM.
23
+ *
24
+ * @param action - The browser action (click, type, navigate, etc.)
25
+ * @param args - Arguments for the action
26
+ * @param toolCallId - Unique ID for this tool call (from config.toolCall.id)
27
+ * @returns Promise that resolves with the actual browser result (page state, etc.)
28
+ */
29
+ export type BrowserToolCallback = (action: string, args: Record<string, unknown>, toolCallId: string) => Promise<BrowserActionResult>;
30
+ /**
31
+ * Result returned from browser action execution
32
+ */
33
+ export interface BrowserActionResult {
34
+ success: boolean;
35
+ url?: string;
36
+ title?: string;
37
+ elementList?: string;
38
+ error?: string;
39
+ screenshot?: string;
40
+ }
19
41
  /**
20
42
  * Check if browser capability is available based on request headers or context
21
43
  * The browser extension sets these headers when connected:
@@ -33,13 +55,31 @@ export interface BrowserToolResponse {
33
55
  requiresBrowserExecution: true;
34
56
  action: string;
35
57
  args: Record<string, unknown>;
58
+ toolCallId?: string;
36
59
  }
37
60
  /**
38
- * Create placeholder browser tools that signal to the extension to execute locally
39
- * The server creates these tools to give the LLM the schema, but actual execution
40
- * happens in the browser extension which intercepts tool calls
61
+ * Options for creating browser tools
62
+ */
63
+ export interface CreateBrowserToolsOptions {
64
+ /**
65
+ * Optional callback that waits for browser action results.
66
+ * When provided, tools will await this callback to get actual results from the extension.
67
+ * When not provided, tools return markers immediately (for non-server contexts).
68
+ */
69
+ waitForResult?: BrowserToolCallback;
70
+ }
71
+ /**
72
+ * Create browser tools with optional callback for waiting on results
73
+ *
74
+ * When waitForResult callback is provided:
75
+ * 1. Tool returns marker that triggers extension
76
+ * 2. Tool then awaits callback to get actual results
77
+ * 3. Returns real page state to LLM
78
+ *
79
+ * When no callback:
80
+ * 1. Tool returns marker only (for non-server contexts)
41
81
  *
42
82
  * NOTE: These tools use TEXT-BASED element lists, NOT screenshots
43
83
  * Screenshots would be 100K+ tokens each - element lists are ~100 tokens
44
84
  */
45
- export declare function createBrowserTools(): DynamicStructuredTool[];
85
+ export declare function createBrowserTools(options?: CreateBrowserToolsOptions): DynamicStructuredTool[];
@@ -38,6 +38,17 @@ export type RunStep = {
38
38
  id: string;
39
39
  runId?: string;
40
40
  agentId?: string;
41
+ /**
42
+ * Group ID - incrementing number (1, 2, 3...) reflecting execution order.
43
+ * Agents with the same groupId run in parallel and should be rendered together.
44
+ * undefined means the agent runs sequentially (not part of any parallel group).
45
+ *
46
+ * Example for: researcher -> [analyst1, analyst2, analyst3] -> summarizer
47
+ * - researcher: undefined (sequential)
48
+ * - analyst1, analyst2, analyst3: 1 (first parallel group)
49
+ * - summarizer: undefined (sequential)
50
+ */
51
+ groupId?: number;
41
52
  index: number;
42
53
  stepIndex?: number;
43
54
  stepDetails: StepDetails;
@@ -251,6 +262,8 @@ export type MessageContentComplex = (ToolResultContent | ThinkingContentText | A
251
262
  type?: never;
252
263
  })) & {
253
264
  tool_call_ids?: string[];
265
+ agentId?: string;
266
+ groupId?: number;
254
267
  };
255
268
  export interface TMessage {
256
269
  role?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "illuma-agents",
3
- "version": "1.0.26",
3
+ "version": "1.0.28",
4
4
  "main": "./dist/cjs/main.cjs",
5
5
  "module": "./dist/esm/main.mjs",
6
6
  "types": "./dist/types/index.d.ts",
@@ -63,6 +63,8 @@
63
63
  "multi-agent-test": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/multi-agent-test.ts",
64
64
  "test-tools-before-handoff": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/test-tools-before-handoff.ts",
65
65
  "multi-agent-parallel": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/multi-agent-parallel.ts",
66
+ "multi-agent-parallel-start": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/multi-agent-parallel-start.ts",
67
+ "single-agent-metadata-test": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/single-agent-metadata-test.ts",
66
68
  "multi-agent-chain": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/multi-agent-chain.ts",
67
69
  "multi-agent-sequence": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/multi-agent-sequence.ts",
68
70
  "multi-agent-conditional": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/multi-agent-conditional.ts",
@@ -102,7 +104,7 @@
102
104
  "dependencies": {
103
105
  "@langchain/anthropic": "^0.3.26",
104
106
  "@langchain/aws": "^0.1.15",
105
- "@langchain/core": "^0.3.79",
107
+ "@langchain/core": "^0.3.80",
106
108
  "@langchain/deepseek": "^0.0.2",
107
109
  "@langchain/google-genai": "^0.2.18",
108
110
  "@langchain/google-vertexai": "^0.2.18",
@@ -1246,6 +1246,26 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
1246
1246
  return workflow;
1247
1247
  }
1248
1248
 
1249
+ /**
1250
+ * Indicates if this is a multi-agent graph.
1251
+ * Override in MultiAgentGraph to return true.
1252
+ * Used to conditionally include agentId in RunStep for frontend rendering.
1253
+ */
1254
+ protected isMultiAgentGraph(): boolean {
1255
+ return false;
1256
+ }
1257
+
1258
+ /**
1259
+ * Get the parallel group ID for an agent, if any.
1260
+ * Override in MultiAgentGraph to provide actual group IDs.
1261
+ * Group IDs are incrementing numbers (1, 2, 3...) reflecting execution order.
1262
+ * @param _agentId - The agent ID to look up
1263
+ * @returns undefined for StandardGraph (no parallel groups), or group number for MultiAgentGraph
1264
+ */
1265
+ protected getParallelGroupIdForAgent(_agentId: string): number | undefined {
1266
+ return undefined;
1267
+ }
1268
+
1249
1269
  /* Dispatchers */
1250
1270
 
1251
1271
  /**
@@ -1286,13 +1306,21 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
1286
1306
  }
1287
1307
 
1288
1308
  /**
1289
- * Extract and store agentId from metadata
1309
+ * Extract agentId and parallelGroupId from metadata
1310
+ * Only set agentId for MultiAgentGraph (so frontend knows when to show agent labels)
1290
1311
  */
1291
1312
  if (metadata) {
1292
1313
  try {
1293
1314
  const agentContext = this.getAgentContext(metadata);
1294
- if (agentContext.agentId) {
1315
+ if (this.isMultiAgentGraph() && agentContext.agentId) {
1316
+ // Only include agentId for MultiAgentGraph - enables frontend to show agent labels
1295
1317
  runStep.agentId = agentContext.agentId;
1318
+ // Set group ID if this agent is part of a parallel group
1319
+ // Group IDs are incrementing numbers (1, 2, 3...) reflecting execution order
1320
+ const groupId = this.getParallelGroupIdForAgent(agentContext.agentId);
1321
+ if (groupId != null) {
1322
+ runStep.groupId = groupId;
1323
+ }
1296
1324
  }
1297
1325
  } catch (_e) {
1298
1326
  /** If we can't get agent context, that's okay - agentId remains undefined */
@@ -40,6 +40,17 @@ export class MultiAgentGraph extends StandardGraph {
40
40
  private startingNodes: Set<string> = new Set();
41
41
  private directEdges: t.GraphEdge[] = [];
42
42
  private handoffEdges: t.GraphEdge[] = [];
43
+ /**
44
+ * Map of agentId to parallel group info.
45
+ * Contains groupId (incrementing number reflecting execution order) for agents in parallel groups.
46
+ * Sequential agents (not in any parallel group) have undefined entry.
47
+ *
48
+ * Example for: researcher -> [analyst1, analyst2, analyst3] -> summarizer
49
+ * - researcher: undefined (sequential, order 0)
50
+ * - analyst1, analyst2, analyst3: { groupId: 1 } (parallel group, order 1)
51
+ * - summarizer: undefined (sequential, order 2)
52
+ */
53
+ private agentParallelGroups: Map<string, number> = new Map();
43
54
 
44
55
  constructor(input: t.MultiAgentGraphInput) {
45
56
  super(input);
@@ -99,6 +110,114 @@ export class MultiAgentGraph extends StandardGraph {
99
110
  if (this.startingNodes.size === 0 && this.agentContexts.size > 0) {
100
111
  this.startingNodes.add(this.agentContexts.keys().next().value!);
101
112
  }
113
+
114
+ // Determine if graph has parallel execution capability
115
+ this.computeParallelCapability();
116
+ }
117
+
118
+ /**
119
+ * Compute parallel groups by traversing the graph in execution order.
120
+ * Assigns incrementing group IDs that reflect the sequential order of execution.
121
+ *
122
+ * For: researcher -> [analyst1, analyst2, analyst3] -> summarizer
123
+ * - researcher: no group (first sequential node)
124
+ * - analyst1, analyst2, analyst3: groupId 1 (first parallel group)
125
+ * - summarizer: no group (next sequential node)
126
+ *
127
+ * This allows frontend to render in order:
128
+ * Row 0: researcher
129
+ * Row 1: [analyst1, analyst2, analyst3] (grouped)
130
+ * Row 2: summarizer
131
+ */
132
+ private computeParallelCapability(): void {
133
+ let groupCounter = 1; // Start at 1, 0 reserved for "no group"
134
+
135
+ // Check 1: Multiple starting nodes means parallel from the start (group 1)
136
+ if (this.startingNodes.size > 1) {
137
+ for (const agentId of this.startingNodes) {
138
+ this.agentParallelGroups.set(agentId, groupCounter);
139
+ }
140
+ groupCounter++;
141
+ }
142
+
143
+ // Check 2: Traverse direct edges in order to find fan-out patterns
144
+ // Build a simple execution order by following edges from starting nodes
145
+ const visited = new Set<string>();
146
+ const queue: string[] = [...this.startingNodes];
147
+
148
+ while (queue.length > 0) {
149
+ const current = queue.shift()!;
150
+ if (visited.has(current)) continue;
151
+ visited.add(current);
152
+
153
+ // Find direct edges from this node
154
+ for (const edge of this.directEdges) {
155
+ const sources = Array.isArray(edge.from) ? edge.from : [edge.from];
156
+ if (!sources.includes(current)) continue;
157
+
158
+ const destinations = Array.isArray(edge.to) ? edge.to : [edge.to];
159
+
160
+ // Fan-out: multiple destinations = parallel group
161
+ if (destinations.length > 1) {
162
+ for (const dest of destinations) {
163
+ // Only set if not already in a group (first group wins)
164
+ if (!this.agentParallelGroups.has(dest)) {
165
+ this.agentParallelGroups.set(dest, groupCounter);
166
+ }
167
+ if (!visited.has(dest)) {
168
+ queue.push(dest);
169
+ }
170
+ }
171
+ groupCounter++;
172
+ } else {
173
+ // Single destination - add to queue for traversal
174
+ for (const dest of destinations) {
175
+ if (!visited.has(dest)) {
176
+ queue.push(dest);
177
+ }
178
+ }
179
+ }
180
+ }
181
+
182
+ // Also follow handoff edges for traversal (but they don't create parallel groups)
183
+ for (const edge of this.handoffEdges) {
184
+ const sources = Array.isArray(edge.from) ? edge.from : [edge.from];
185
+ if (!sources.includes(current)) continue;
186
+
187
+ const destinations = Array.isArray(edge.to) ? edge.to : [edge.to];
188
+ for (const dest of destinations) {
189
+ if (!visited.has(dest)) {
190
+ queue.push(dest);
191
+ }
192
+ }
193
+ }
194
+ }
195
+ }
196
+
197
+ /**
198
+ * Get the parallel group ID for an agent, if any.
199
+ * Returns undefined if the agent is not part of a parallel group.
200
+ * Group IDs are incrementing numbers reflecting execution order.
201
+ */
202
+ getParallelGroupId(agentId: string): number | undefined {
203
+ return this.agentParallelGroups.get(agentId);
204
+ }
205
+
206
+ /**
207
+ * Override to indicate this is a multi-agent graph.
208
+ * Enables agentId to be included in RunStep for frontend agent labeling.
209
+ */
210
+ protected override isMultiAgentGraph(): boolean {
211
+ return true;
212
+ }
213
+
214
+ /**
215
+ * Override base class method to provide parallel group IDs for run steps.
216
+ */
217
+ protected override getParallelGroupIdForAgent(
218
+ agentId: string
219
+ ): number | undefined {
220
+ return this.agentParallelGroups.get(agentId);
102
221
  }
103
222
 
104
223
  /**
@@ -636,7 +636,7 @@ export const labelContentByAgent = (
636
636
  */
637
637
  export const formatAgentMessages = (
638
638
  payload: TPayload,
639
- indexTokenCountMap?: Record<number, number>,
639
+ indexTokenCountMap?: Record<number, number | undefined>,
640
640
  tools?: Set<string>
641
641
  ): {
642
642
  messages: Array<HumanMessage | AIMessage | SystemMessage | ToolMessage>;
@@ -648,7 +648,7 @@ export const formatAgentMessages = (
648
648
  // If indexTokenCountMap is provided, create a new map to track the updated indices
649
649
  const updatedIndexTokenCountMap: Record<number, number> = {};
650
650
  // Keep track of the mapping from original payload indices to result indices
651
- const indexMapping: Record<number, number[]> = {};
651
+ const indexMapping: Record<number, number[] | undefined> = {};
652
652
 
653
653
  // Process messages with tool conversion if tools set is provided
654
654
  for (let i = 0; i < payload.length; i++) {
@@ -143,18 +143,49 @@ async function testSequentialAgentChain() {
143
143
 
144
144
  // Track agent progression
145
145
  let currentAgent = '';
146
+ const startTime = Date.now();
147
+ let messageCount = 0;
146
148
 
147
- // Create custom handlers
149
+ // Create custom handlers with extensive metadata logging
148
150
  const customHandlers = {
149
151
  [GraphEvents.TOOL_END]: new ToolEndHandler(),
150
- [GraphEvents.CHAT_MODEL_END]: new ModelEndHandler(),
152
+ [GraphEvents.CHAT_MODEL_END]: {
153
+ handle: (
154
+ _event: string,
155
+ _data: t.StreamEventData,
156
+ metadata?: Record<string, unknown>
157
+ ): void => {
158
+ console.log('\n====== CHAT_MODEL_END METADATA ======');
159
+ console.dir(metadata, { depth: null });
160
+ const elapsed = Date.now() - startTime;
161
+ console.log(`⏱️ COMPLETED at ${elapsed}ms`);
162
+ },
163
+ },
164
+ [GraphEvents.CHAT_MODEL_START]: {
165
+ handle: (
166
+ _event: string,
167
+ _data: t.StreamEventData,
168
+ metadata?: Record<string, unknown>
169
+ ): void => {
170
+ console.log('\n====== CHAT_MODEL_START METADATA ======');
171
+ console.dir(metadata, { depth: null });
172
+ const elapsed = Date.now() - startTime;
173
+ console.log(`⏱️ STARTED at ${elapsed}ms`);
174
+ },
175
+ },
151
176
  [GraphEvents.CHAT_MODEL_STREAM]: new ChatModelStreamHandler(),
152
177
  [GraphEvents.ON_RUN_STEP]: {
153
178
  handle: (
154
179
  event: GraphEvents.ON_RUN_STEP,
155
- data: t.StreamEventData
180
+ data: t.StreamEventData,
181
+ metadata?: Record<string, unknown>
156
182
  ): void => {
157
183
  const runStepData = data as any;
184
+ console.log('\n====== ON_RUN_STEP ======');
185
+ console.log('DATA:');
186
+ console.dir(data, { depth: null });
187
+ console.log('METADATA:');
188
+ console.dir(metadata, { depth: null });
158
189
  if (runStepData?.name) {
159
190
  currentAgent = runStepData.name;
160
191
  console.log(`\n→ ${currentAgent} is processing...`);
@@ -165,9 +196,15 @@ async function testSequentialAgentChain() {
165
196
  [GraphEvents.ON_RUN_STEP_COMPLETED]: {
166
197
  handle: (
167
198
  event: GraphEvents.ON_RUN_STEP_COMPLETED,
168
- data: t.StreamEventData
199
+ data: t.StreamEventData,
200
+ metadata?: Record<string, unknown>
169
201
  ): void => {
170
202
  const runStepData = data as any;
203
+ console.log('\n====== ON_RUN_STEP_COMPLETED ======');
204
+ console.log('DATA:');
205
+ console.dir(data, { depth: null });
206
+ console.log('METADATA:');
207
+ console.dir(metadata, { depth: null });
171
208
  if (runStepData?.name) {
172
209
  console.log(`✓ ${runStepData.name} completed`);
173
210
  }
@@ -180,16 +217,32 @@ async function testSequentialAgentChain() {
180
217
  [GraphEvents.ON_RUN_STEP_DELTA]: {
181
218
  handle: (
182
219
  event: GraphEvents.ON_RUN_STEP_DELTA,
183
- data: t.StreamEventData
220
+ data: t.StreamEventData,
221
+ metadata?: Record<string, unknown>
184
222
  ): void => {
223
+ console.log('\n====== ON_RUN_STEP_DELTA ======');
224
+ console.log('DATA:');
225
+ console.dir(data, { depth: null });
226
+ console.log('METADATA:');
227
+ console.dir(metadata, { depth: null });
185
228
  aggregateContent({ event, data: data as t.RunStepDeltaEvent });
186
229
  },
187
230
  },
188
231
  [GraphEvents.ON_MESSAGE_DELTA]: {
189
232
  handle: (
190
233
  event: GraphEvents.ON_MESSAGE_DELTA,
191
- data: t.StreamEventData
234
+ data: t.StreamEventData,
235
+ metadata?: Record<string, unknown>
192
236
  ): void => {
237
+ messageCount++;
238
+ // Only log first few message deltas to avoid spam
239
+ if (messageCount <= 3) {
240
+ console.log('\n====== ON_MESSAGE_DELTA ======');
241
+ console.log('DATA:');
242
+ console.dir(data, { depth: null });
243
+ console.log('METADATA:');
244
+ console.dir(metadata, { depth: null });
245
+ }
193
246
  aggregateContent({ event, data: data as t.MessageDeltaEvent });
194
247
  },
195
248
  },