@illuma-ai/agents 1.1.21 → 1.1.22

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 (241) hide show
  1. package/dist/cjs/graphs/Graph.cjs +12 -1
  2. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  3. package/dist/cjs/graphs/MultiAgentGraph.cjs +85 -1
  4. package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
  5. package/dist/cjs/run.cjs +20 -9
  6. package/dist/cjs/run.cjs.map +1 -1
  7. package/dist/esm/graphs/Graph.mjs +12 -1
  8. package/dist/esm/graphs/Graph.mjs.map +1 -1
  9. package/dist/esm/graphs/MultiAgentGraph.mjs +85 -1
  10. package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
  11. package/dist/esm/run.mjs +20 -9
  12. package/dist/esm/run.mjs.map +1 -1
  13. package/dist/types/graphs/MultiAgentGraph.d.ts +17 -0
  14. package/package.json +1 -1
  15. package/src/graphs/Graph.ts +12 -1
  16. package/src/graphs/MultiAgentGraph.ts +105 -1
  17. package/src/graphs/__tests__/multi-agent-delegate.test.ts +191 -0
  18. package/src/run.ts +20 -11
  19. package/src/scripts/test-bedrock-handoff-autonomous.ts +231 -0
  20. package/src/agents/AgentContext.js +0 -782
  21. package/src/agents/AgentContext.test.js +0 -421
  22. package/src/agents/__tests__/AgentContext.test.js +0 -678
  23. package/src/agents/__tests__/resolveStructuredOutputMode.test.js +0 -117
  24. package/src/common/enum.js +0 -192
  25. package/src/common/index.js +0 -3
  26. package/src/events.js +0 -166
  27. package/src/graphs/Graph.js +0 -1857
  28. package/src/graphs/MultiAgentGraph.js +0 -1092
  29. package/src/graphs/__tests__/structured-output.integration.test.js +0 -624
  30. package/src/graphs/__tests__/structured-output.test.js +0 -144
  31. package/src/graphs/contextManagement.e2e.test.js +0 -718
  32. package/src/graphs/contextManagement.test.js +0 -485
  33. package/src/graphs/handoffValidation.test.js +0 -276
  34. package/src/graphs/index.js +0 -3
  35. package/src/index.js +0 -28
  36. package/src/instrumentation.js +0 -21
  37. package/src/llm/anthropic/index.js +0 -319
  38. package/src/llm/anthropic/types.js +0 -46
  39. package/src/llm/anthropic/utils/message_inputs.js +0 -627
  40. package/src/llm/anthropic/utils/message_outputs.js +0 -290
  41. package/src/llm/anthropic/utils/output_parsers.js +0 -89
  42. package/src/llm/anthropic/utils/tools.js +0 -25
  43. package/src/llm/bedrock/__tests__/bedrock-caching.test.js +0 -392
  44. package/src/llm/bedrock/index.js +0 -303
  45. package/src/llm/bedrock/types.js +0 -2
  46. package/src/llm/bedrock/utils/index.js +0 -6
  47. package/src/llm/bedrock/utils/message_inputs.js +0 -463
  48. package/src/llm/bedrock/utils/message_outputs.js +0 -269
  49. package/src/llm/fake.js +0 -92
  50. package/src/llm/google/index.js +0 -215
  51. package/src/llm/google/types.js +0 -12
  52. package/src/llm/google/utils/common.js +0 -670
  53. package/src/llm/google/utils/tools.js +0 -111
  54. package/src/llm/google/utils/zod_to_genai_parameters.js +0 -47
  55. package/src/llm/openai/index.js +0 -1033
  56. package/src/llm/openai/types.js +0 -2
  57. package/src/llm/openai/utils/index.js +0 -756
  58. package/src/llm/openai/utils/isReasoningModel.test.js +0 -79
  59. package/src/llm/openrouter/index.js +0 -261
  60. package/src/llm/openrouter/reasoning.test.js +0 -181
  61. package/src/llm/providers.js +0 -36
  62. package/src/llm/text.js +0 -65
  63. package/src/llm/vertexai/index.js +0 -402
  64. package/src/messages/__tests__/tools.test.js +0 -392
  65. package/src/messages/cache.js +0 -404
  66. package/src/messages/cache.test.js +0 -1167
  67. package/src/messages/content.js +0 -48
  68. package/src/messages/content.test.js +0 -314
  69. package/src/messages/core.js +0 -359
  70. package/src/messages/ensureThinkingBlock.test.js +0 -997
  71. package/src/messages/format.js +0 -973
  72. package/src/messages/formatAgentMessages.test.js +0 -2278
  73. package/src/messages/formatAgentMessages.tools.test.js +0 -362
  74. package/src/messages/formatMessage.test.js +0 -608
  75. package/src/messages/ids.js +0 -18
  76. package/src/messages/index.js +0 -9
  77. package/src/messages/labelContentByAgent.test.js +0 -725
  78. package/src/messages/prune.js +0 -438
  79. package/src/messages/reducer.js +0 -60
  80. package/src/messages/shiftIndexTokenCountMap.test.js +0 -63
  81. package/src/messages/summarize.js +0 -146
  82. package/src/messages/summarize.test.js +0 -332
  83. package/src/messages/tools.js +0 -90
  84. package/src/mockStream.js +0 -81
  85. package/src/prompts/collab.js +0 -7
  86. package/src/prompts/index.js +0 -3
  87. package/src/prompts/taskmanager.js +0 -58
  88. package/src/run.js +0 -427
  89. package/src/schemas/index.js +0 -3
  90. package/src/schemas/schema-preparation.test.js +0 -370
  91. package/src/schemas/validate.js +0 -314
  92. package/src/schemas/validate.test.js +0 -264
  93. package/src/scripts/abort.js +0 -127
  94. package/src/scripts/ant_web_search.js +0 -130
  95. package/src/scripts/ant_web_search_edge_case.js +0 -133
  96. package/src/scripts/ant_web_search_error_edge_case.js +0 -119
  97. package/src/scripts/args.js +0 -41
  98. package/src/scripts/bedrock-cache-debug.js +0 -186
  99. package/src/scripts/bedrock-content-aggregation-test.js +0 -195
  100. package/src/scripts/bedrock-merge-test.js +0 -80
  101. package/src/scripts/bedrock-parallel-tools-test.js +0 -150
  102. package/src/scripts/caching.js +0 -106
  103. package/src/scripts/cli.js +0 -152
  104. package/src/scripts/cli2.js +0 -119
  105. package/src/scripts/cli3.js +0 -163
  106. package/src/scripts/cli4.js +0 -165
  107. package/src/scripts/cli5.js +0 -165
  108. package/src/scripts/code_exec.js +0 -171
  109. package/src/scripts/code_exec_files.js +0 -180
  110. package/src/scripts/code_exec_multi_session.js +0 -185
  111. package/src/scripts/code_exec_ptc.js +0 -265
  112. package/src/scripts/code_exec_session.js +0 -217
  113. package/src/scripts/code_exec_simple.js +0 -120
  114. package/src/scripts/content.js +0 -111
  115. package/src/scripts/empty_input.js +0 -125
  116. package/src/scripts/handoff-test.js +0 -96
  117. package/src/scripts/image.js +0 -138
  118. package/src/scripts/memory.js +0 -83
  119. package/src/scripts/multi-agent-chain.js +0 -271
  120. package/src/scripts/multi-agent-conditional.js +0 -185
  121. package/src/scripts/multi-agent-document-review-chain.js +0 -171
  122. package/src/scripts/multi-agent-hybrid-flow.js +0 -264
  123. package/src/scripts/multi-agent-parallel-start.js +0 -214
  124. package/src/scripts/multi-agent-parallel.js +0 -346
  125. package/src/scripts/multi-agent-sequence.js +0 -184
  126. package/src/scripts/multi-agent-supervisor.js +0 -324
  127. package/src/scripts/multi-agent-test.js +0 -147
  128. package/src/scripts/parallel-asymmetric-tools-test.js +0 -202
  129. package/src/scripts/parallel-full-metadata-test.js +0 -176
  130. package/src/scripts/parallel-tools-test.js +0 -256
  131. package/src/scripts/programmatic_exec.js +0 -277
  132. package/src/scripts/programmatic_exec_agent.js +0 -168
  133. package/src/scripts/search.js +0 -118
  134. package/src/scripts/sequential-full-metadata-test.js +0 -143
  135. package/src/scripts/simple.js +0 -174
  136. package/src/scripts/single-agent-metadata-test.js +0 -152
  137. package/src/scripts/stream.js +0 -113
  138. package/src/scripts/test-custom-prompt-key.js +0 -132
  139. package/src/scripts/test-handoff-input.js +0 -143
  140. package/src/scripts/test-handoff-preamble.js +0 -227
  141. package/src/scripts/test-handoff-steering.js +0 -353
  142. package/src/scripts/test-multi-agent-list-handoff.js +0 -318
  143. package/src/scripts/test-parallel-agent-labeling.js +0 -253
  144. package/src/scripts/test-parallel-handoffs.js +0 -229
  145. package/src/scripts/test-thinking-handoff-bedrock.js +0 -132
  146. package/src/scripts/test-thinking-handoff.js +0 -132
  147. package/src/scripts/test-thinking-to-thinking-handoff-bedrock.js +0 -140
  148. package/src/scripts/test-tool-before-handoff-role-order.js +0 -223
  149. package/src/scripts/test-tools-before-handoff.js +0 -187
  150. package/src/scripts/test_code_api.js +0 -263
  151. package/src/scripts/thinking-bedrock.js +0 -128
  152. package/src/scripts/thinking-vertexai.js +0 -130
  153. package/src/scripts/thinking.js +0 -134
  154. package/src/scripts/tool_search.js +0 -114
  155. package/src/scripts/tools.js +0 -125
  156. package/src/specs/agent-handoffs-bedrock.integration.test.js +0 -280
  157. package/src/specs/agent-handoffs.test.js +0 -924
  158. package/src/specs/anthropic.simple.test.js +0 -287
  159. package/src/specs/azure.simple.test.js +0 -381
  160. package/src/specs/cache.simple.test.js +0 -282
  161. package/src/specs/custom-event-await.test.js +0 -148
  162. package/src/specs/deepseek.simple.test.js +0 -189
  163. package/src/specs/emergency-prune.test.js +0 -308
  164. package/src/specs/moonshot.simple.test.js +0 -237
  165. package/src/specs/observability.integration.test.js +0 -1337
  166. package/src/specs/openai.simple.test.js +0 -233
  167. package/src/specs/openrouter.simple.test.js +0 -202
  168. package/src/specs/prune.test.js +0 -733
  169. package/src/specs/reasoning.test.js +0 -144
  170. package/src/specs/spec.utils.js +0 -4
  171. package/src/specs/thinking-handoff.test.js +0 -486
  172. package/src/specs/thinking-prune.test.js +0 -600
  173. package/src/specs/token-distribution-edge-case.test.js +0 -246
  174. package/src/specs/token-memoization.test.js +0 -32
  175. package/src/specs/tokens.test.js +0 -49
  176. package/src/specs/tool-error.test.js +0 -139
  177. package/src/splitStream.js +0 -204
  178. package/src/splitStream.test.js +0 -504
  179. package/src/stream.js +0 -650
  180. package/src/stream.test.js +0 -225
  181. package/src/test/mockTools.js +0 -340
  182. package/src/tools/BrowserTools.js +0 -245
  183. package/src/tools/Calculator.js +0 -38
  184. package/src/tools/Calculator.test.js +0 -225
  185. package/src/tools/CodeExecutor.js +0 -233
  186. package/src/tools/ProgrammaticToolCalling.js +0 -602
  187. package/src/tools/StreamingToolCallBuffer.js +0 -179
  188. package/src/tools/ToolNode.js +0 -930
  189. package/src/tools/ToolSearch.js +0 -904
  190. package/src/tools/__tests__/BrowserTools.test.js +0 -306
  191. package/src/tools/__tests__/ProgrammaticToolCalling.integration.test.js +0 -276
  192. package/src/tools/__tests__/ProgrammaticToolCalling.test.js +0 -807
  193. package/src/tools/__tests__/StreamingToolCallBuffer.test.js +0 -175
  194. package/src/tools/__tests__/ToolApproval.test.js +0 -675
  195. package/src/tools/__tests__/ToolNode.recovery.test.js +0 -200
  196. package/src/tools/__tests__/ToolNode.session.test.js +0 -319
  197. package/src/tools/__tests__/ToolSearch.integration.test.js +0 -125
  198. package/src/tools/__tests__/ToolSearch.test.js +0 -812
  199. package/src/tools/__tests__/handlers.test.js +0 -799
  200. package/src/tools/__tests__/truncation-recovery.integration.test.js +0 -362
  201. package/src/tools/handlers.js +0 -306
  202. package/src/tools/schema.js +0 -25
  203. package/src/tools/search/anthropic.js +0 -34
  204. package/src/tools/search/content.js +0 -116
  205. package/src/tools/search/content.test.js +0 -133
  206. package/src/tools/search/firecrawl.js +0 -173
  207. package/src/tools/search/format.js +0 -198
  208. package/src/tools/search/highlights.js +0 -241
  209. package/src/tools/search/index.js +0 -3
  210. package/src/tools/search/jina-reranker.test.js +0 -106
  211. package/src/tools/search/rerankers.js +0 -165
  212. package/src/tools/search/schema.js +0 -102
  213. package/src/tools/search/search.js +0 -561
  214. package/src/tools/search/serper-scraper.js +0 -126
  215. package/src/tools/search/test.js +0 -129
  216. package/src/tools/search/tool.js +0 -453
  217. package/src/tools/search/types.js +0 -2
  218. package/src/tools/search/utils.js +0 -59
  219. package/src/types/graph.js +0 -24
  220. package/src/types/graph.test.js +0 -192
  221. package/src/types/index.js +0 -7
  222. package/src/types/llm.js +0 -2
  223. package/src/types/messages.js +0 -2
  224. package/src/types/run.js +0 -2
  225. package/src/types/stream.js +0 -2
  226. package/src/types/tools.js +0 -2
  227. package/src/utils/contextAnalytics.js +0 -79
  228. package/src/utils/contextAnalytics.test.js +0 -166
  229. package/src/utils/events.js +0 -26
  230. package/src/utils/graph.js +0 -11
  231. package/src/utils/handlers.js +0 -65
  232. package/src/utils/index.js +0 -10
  233. package/src/utils/llm.js +0 -21
  234. package/src/utils/llmConfig.js +0 -205
  235. package/src/utils/logging.js +0 -37
  236. package/src/utils/misc.js +0 -51
  237. package/src/utils/run.js +0 -69
  238. package/src/utils/schema.js +0 -21
  239. package/src/utils/title.js +0 -119
  240. package/src/utils/tokens.js +0 -92
  241. package/src/utils/toonFormat.js +0 -379
@@ -1,253 +0,0 @@
1
- #!/usr/bin/env bun
2
- import { config } from 'dotenv';
3
- config();
4
- import { HumanMessage } from '@langchain/core/messages';
5
- import { labelContentByAgent, formatAgentMessages } from '@/messages/format';
6
- import { ChatModelStreamHandler, createContentAggregator } from '@/stream';
7
- import { Providers, GraphEvents } from '@/common';
8
- import { ToolEndHandler, ModelEndHandler } from '@/events';
9
- import { Run } from '@/run';
10
- const conversationHistory = [];
11
- /**
12
- * Test parallel multi-agent system with agent labeling on subsequent runs
13
- *
14
- * Graph structure:
15
- * START -> researcher
16
- * researcher -> [analyst1, analyst2, analyst3] (fan-out)
17
- * [analyst1, analyst2, analyst3] -> summarizer (fan-in)
18
- * summarizer -> END
19
- */
20
- async function testParallelWithAgentLabeling() {
21
- console.log('Testing Parallel Multi-Agent with Agent Labeling...\n');
22
- // Set up content aggregator
23
- const { contentParts, aggregateContent } = createContentAggregator();
24
- // Define specialized agents
25
- const agents = [
26
- {
27
- agentId: 'researcher',
28
- provider: Providers.ANTHROPIC,
29
- clientOptions: {
30
- modelName: 'claude-haiku-4-5',
31
- apiKey: process.env.ANTHROPIC_API_KEY,
32
- },
33
- instructions: `You are a research coordinator. Analyze the request and provide 2-3 sentence coordination brief.`,
34
- },
35
- {
36
- agentId: 'analyst1',
37
- provider: Providers.ANTHROPIC,
38
- clientOptions: {
39
- modelName: 'claude-haiku-4-5',
40
- apiKey: process.env.ANTHROPIC_API_KEY,
41
- },
42
- instructions: `You are FINANCIAL ANALYST. Provide 2-3 sentence financial analysis. Start with "FINANCIAL ANALYSIS:"`,
43
- },
44
- {
45
- agentId: 'analyst2',
46
- provider: Providers.ANTHROPIC,
47
- clientOptions: {
48
- modelName: 'claude-haiku-4-5',
49
- apiKey: process.env.ANTHROPIC_API_KEY,
50
- },
51
- instructions: `You are TECHNICAL ANALYST. Provide 2-3 sentence technical analysis. Start with "TECHNICAL ANALYSIS:"`,
52
- },
53
- {
54
- agentId: 'analyst3',
55
- provider: Providers.ANTHROPIC,
56
- clientOptions: {
57
- modelName: 'claude-haiku-4-5',
58
- apiKey: process.env.ANTHROPIC_API_KEY,
59
- },
60
- instructions: `You are MARKET ANALYST. Provide 2-3 sentence market analysis. Start with "MARKET ANALYSIS:"`,
61
- },
62
- {
63
- agentId: 'summarizer',
64
- provider: Providers.ANTHROPIC,
65
- clientOptions: {
66
- modelName: 'claude-haiku-4-5',
67
- apiKey: process.env.ANTHROPIC_API_KEY,
68
- },
69
- instructions: `You are SYNTHESIS EXPERT. Review all analyses and provide 2-3 sentence integrated summary.`,
70
- },
71
- ];
72
- // Define direct edges (fan-out and fan-in)
73
- const edges = [
74
- {
75
- from: 'researcher',
76
- to: ['analyst1', 'analyst2', 'analyst3'],
77
- description: 'Distribute research to specialist analysts',
78
- edgeType: 'sequence',
79
- },
80
- {
81
- from: ['analyst1', 'analyst2', 'analyst3'],
82
- to: 'summarizer',
83
- description: 'Aggregate analysis results',
84
- edgeType: 'sequence',
85
- prompt: 'Based on the analyses below, provide an integrated summary:\n\n{results}',
86
- },
87
- ];
88
- // Create custom handlers
89
- const customHandlers = {
90
- [GraphEvents.TOOL_END]: new ToolEndHandler(),
91
- [GraphEvents.CHAT_MODEL_END]: new ModelEndHandler(),
92
- [GraphEvents.CHAT_MODEL_STREAM]: new ChatModelStreamHandler(),
93
- [GraphEvents.ON_RUN_STEP_COMPLETED]: {
94
- handle: (event, data) => {
95
- aggregateContent({
96
- event,
97
- data: data,
98
- });
99
- },
100
- },
101
- [GraphEvents.ON_RUN_STEP]: {
102
- handle: (event, data) => {
103
- aggregateContent({ event, data: data });
104
- },
105
- },
106
- [GraphEvents.ON_MESSAGE_DELTA]: {
107
- handle: (event, data) => {
108
- aggregateContent({ event, data: data });
109
- },
110
- },
111
- };
112
- try {
113
- const query = 'What are the implications of widespread AI adoption?';
114
- console.log(`${'='.repeat(80)}`);
115
- console.log(`FIRST RUN - USER QUERY: "${query}"`);
116
- console.log('='.repeat(80));
117
- // Reset conversation
118
- conversationHistory.length = 0;
119
- conversationHistory.push(new HumanMessage(query));
120
- // Create graph
121
- const runConfig = {
122
- runId: `parallel-test-${Date.now()}`,
123
- graphConfig: {
124
- type: 'multi-agent',
125
- agents,
126
- edges,
127
- },
128
- customHandlers,
129
- returnContent: true,
130
- skipCleanup: true,
131
- };
132
- const run = await Run.create(runConfig);
133
- console.log('\nProcessing first run with parallel agents...\n');
134
- const config = {
135
- configurable: {
136
- thread_id: 'parallel-agent-labeling-1',
137
- },
138
- streamMode: 'values',
139
- version: 'v2',
140
- };
141
- const inputs = {
142
- messages: conversationHistory,
143
- };
144
- await run.processStream(inputs, config);
145
- const finalMessages = run.getRunMessages();
146
- if (finalMessages) {
147
- conversationHistory.push(...finalMessages);
148
- }
149
- // Show agent participation
150
- console.log(`\n${'─'.repeat(80)}`);
151
- console.log('FIRST RUN - AGENT PARTICIPATION:');
152
- console.log('─'.repeat(80));
153
- if (run.Graph) {
154
- const activeAgents = run.Graph.getActiveAgentIds();
155
- console.log(`\nActive agents (${activeAgents.length}):`, activeAgents);
156
- const stepsByAgent = run.Graph.getRunStepsByAgent();
157
- stepsByAgent.forEach((steps, agentId) => {
158
- console.log(` ${agentId}: ${steps.length} steps`);
159
- });
160
- console.log(`\nTotal content parts: ${contentParts.length}`);
161
- }
162
- // =============================================================
163
- // SECOND RUN: Test with agent-labeled history
164
- // =============================================================
165
- console.log(`\n${'='.repeat(80)}`);
166
- console.log(`SECOND RUN - Simulating DB Load with Parallel Agent Labeling`);
167
- console.log('='.repeat(80));
168
- // Simulate DB storage
169
- const dbStoredContentParts = [...contentParts];
170
- const dbStoredAgentIdMap = Object.fromEntries(run.Graph.getContentPartAgentMap());
171
- console.log('\nšŸ“¦ Simulating DB storage:');
172
- console.log(` - Stored ${dbStoredContentParts.length} content parts`);
173
- console.log(` - Stored agent mappings for ${Object.keys(dbStoredAgentIdMap).length} parts`);
174
- // Load and label by agent with labelNonTransferContent option
175
- console.log('\nšŸ“„ Loading from DB and labeling ALL agent content...');
176
- const agentNames = {
177
- researcher: 'Researcher',
178
- analyst1: 'Financial Analyst',
179
- analyst2: 'Technical Analyst',
180
- analyst3: 'Market Analyst',
181
- summarizer: 'Synthesizer',
182
- };
183
- const labeledContentParts = labelContentByAgent(dbStoredContentParts.filter((p) => p != null), dbStoredAgentIdMap, agentNames, { labelNonTransferContent: true } // NEW: Label all content
184
- );
185
- console.log(` - Labeled ${labeledContentParts.length} content groups by agent`);
186
- // Convert to payload
187
- const payload = [
188
- {
189
- role: 'user',
190
- content: query,
191
- },
192
- {
193
- role: 'assistant',
194
- content: labeledContentParts,
195
- },
196
- ];
197
- // Format using formatAgentMessages
198
- console.log('\nšŸ”§ Calling formatAgentMessages...');
199
- const { messages: formattedMessages } = formatAgentMessages(payload);
200
- console.log(` - Formatted into ${formattedMessages.length} BaseMessages`);
201
- // Show preview
202
- console.log('\nšŸ‘ļø Preview of formatted history:');
203
- console.log('─'.repeat(80));
204
- for (let i = 0; i < formattedMessages.length; i++) {
205
- const msg = formattedMessages[i];
206
- const role = msg._getType();
207
- const preview = typeof msg.content === 'string'
208
- ? msg.content.slice(0, 300)
209
- : JSON.stringify(msg.content).slice(0, 300);
210
- console.log(`[${i}] ${role}: ${preview}${preview.length >= 300 ? '...' : ''}`);
211
- console.log('');
212
- }
213
- console.log('─'.repeat(80));
214
- // Create a second run with labeled history
215
- console.log('\nšŸš€ Starting second run with agent-labeled parallel history...');
216
- const followupQuery = 'Which analyst identified the most significant risk?';
217
- console.log(` Followup: "${followupQuery}"`);
218
- const secondRunHistory = [
219
- ...formattedMessages,
220
- new HumanMessage(followupQuery),
221
- ];
222
- const runConfig2 = {
223
- runId: `parallel-test-2-${Date.now()}`,
224
- graphConfig: {
225
- type: 'multi-agent',
226
- agents,
227
- edges,
228
- },
229
- customHandlers,
230
- returnContent: true,
231
- skipCleanup: true,
232
- };
233
- const run2 = await Run.create(runConfig2);
234
- const inputs2 = {
235
- messages: secondRunHistory,
236
- };
237
- await run2.processStream(inputs2, config);
238
- console.log('\nāœ… Second run completed successfully!');
239
- console.log(' The researcher correctly understood that parallel analysts handled');
240
- console.log(' the previous analysis, with clear attribution per agent.');
241
- console.log(`\n${'='.repeat(80)}`);
242
- console.log('TEST COMPLETE');
243
- console.log('='.repeat(80));
244
- console.log('\nThis demonstrates that parallel multi-agent patterns work correctly');
245
- console.log('with agent labeling, preventing confusion about who said what.');
246
- }
247
- catch (error) {
248
- console.error('Error in parallel agent labeling test:', error);
249
- }
250
- }
251
- // Run the test
252
- testParallelWithAgentLabeling();
253
- //# sourceMappingURL=test-parallel-agent-labeling.js.map
@@ -1,229 +0,0 @@
1
- import { config } from 'dotenv';
2
- config();
3
- import { HumanMessage } from '@langchain/core/messages';
4
- import { ChatModelStreamHandler, createContentAggregator } from '@/stream';
5
- import { ToolEndHandler } from '@/events';
6
- import { Providers, GraphEvents } from '@/common';
7
- import { sleep } from '@/utils/run';
8
- import { Run } from '@/run';
9
- const conversationHistory = [];
10
- /**
11
- * Test parallel handoffs - where an LLM calls multiple transfer tools simultaneously
12
- *
13
- * Graph structure:
14
- * coordinator -> [researcher, writer] (via parallel handoff tools)
15
- *
16
- * The coordinator agent has two transfer tools:
17
- * - transfer_to_researcher
18
- * - transfer_to_writer
19
- *
20
- * When given a task that needs both, it should call both tools in parallel.
21
- */
22
- async function testParallelHandoffs() {
23
- console.log('Testing Parallel Handoffs (LLM calling multiple transfers)...\n');
24
- const { contentParts, aggregateContent } = createContentAggregator();
25
- const agents = [
26
- {
27
- agentId: 'coordinator',
28
- provider: Providers.OPENAI,
29
- clientOptions: {
30
- modelName: 'gpt-4o-mini',
31
- apiKey: process.env.OPENAI_API_KEY,
32
- },
33
- instructions: `You are a COORDINATOR agent. Your job is to delegate tasks to specialized agents.
34
-
35
- You have access to two transfer tools:
36
- - transfer_to_researcher: For research and fact-finding tasks
37
- - transfer_to_writer: For content creation and writing tasks
38
-
39
- IMPORTANT: When a task requires BOTH research AND writing, you MUST call BOTH transfer tools SIMULTANEOUSLY in the same response. Do not call them sequentially.
40
-
41
- For example, if asked to "research and write about X", call both transfers at once to enable parallel work.
42
-
43
- When delegating, provide clear instructions to each agent about what they should do.`,
44
- },
45
- {
46
- agentId: 'researcher',
47
- provider: Providers.ANTHROPIC,
48
- clientOptions: {
49
- modelName: 'claude-haiku-4-5',
50
- apiKey: process.env.ANTHROPIC_API_KEY,
51
- },
52
- instructions: `You are a RESEARCHER. When you receive a task:
53
- 1. Provide concise research findings (100-150 words)
54
- 2. Start your response with "šŸ“š RESEARCH FINDINGS:"`,
55
- },
56
- {
57
- agentId: 'writer',
58
- provider: Providers.ANTHROPIC,
59
- clientOptions: {
60
- modelName: 'claude-haiku-4-5',
61
- apiKey: process.env.ANTHROPIC_API_KEY,
62
- },
63
- instructions: `You are a WRITER. When you receive a task:
64
- 1. Provide creative content (100-150 words)
65
- 2. Start your response with "āœļø WRITTEN CONTENT:"`,
66
- },
67
- ];
68
- /**
69
- * Create handoff edges from coordinator to both researcher and writer.
70
- * These are separate edges so the LLM sees both transfer tools.
71
- */
72
- const edges = [
73
- {
74
- from: 'coordinator',
75
- to: 'researcher',
76
- edgeType: 'transfer',
77
- description: 'Transfer to researcher for research and fact-finding tasks',
78
- prompt: 'Research task instructions',
79
- },
80
- {
81
- from: 'coordinator',
82
- to: 'writer',
83
- edgeType: 'transfer',
84
- description: 'Transfer to writer for content creation and writing tasks',
85
- prompt: 'Writing task instructions',
86
- },
87
- ];
88
- /** Track which agents are active and their timing */
89
- const activeAgents = new Set();
90
- const agentTimings = {};
91
- const startTime = Date.now();
92
- const customHandlers = {
93
- [GraphEvents.TOOL_END]: new ToolEndHandler(),
94
- [GraphEvents.CHAT_MODEL_END]: {
95
- handle: (_event, _data, metadata) => {
96
- const nodeName = metadata?.langgraph_node;
97
- if (nodeName) {
98
- const elapsed = Date.now() - startTime;
99
- agentTimings[nodeName] = agentTimings[nodeName] || {};
100
- agentTimings[nodeName].end = elapsed;
101
- activeAgents.delete(nodeName);
102
- console.log(`\nā±ļø [${nodeName}] COMPLETED at ${elapsed}ms`);
103
- }
104
- },
105
- },
106
- [GraphEvents.CHAT_MODEL_START]: {
107
- handle: (_event, _data, metadata) => {
108
- const nodeName = metadata?.langgraph_node;
109
- if (nodeName) {
110
- const elapsed = Date.now() - startTime;
111
- /** Store first start time for parallel overlap calculation */
112
- if (!agentTimings[nodeName]?.start) {
113
- agentTimings[nodeName] = agentTimings[nodeName] || {};
114
- agentTimings[nodeName].start = elapsed;
115
- }
116
- activeAgents.add(nodeName);
117
- console.log(`\nā±ļø [${nodeName}] STARTED at ${elapsed}ms`);
118
- console.log(` Active agents: ${Array.from(activeAgents).join(', ')}`);
119
- }
120
- },
121
- },
122
- [GraphEvents.CHAT_MODEL_STREAM]: new ChatModelStreamHandler(),
123
- [GraphEvents.ON_RUN_STEP_COMPLETED]: {
124
- handle: (event, data) => {
125
- aggregateContent({
126
- event,
127
- data: data,
128
- });
129
- },
130
- },
131
- [GraphEvents.ON_RUN_STEP]: {
132
- handle: (event, data) => {
133
- aggregateContent({ event, data: data });
134
- },
135
- },
136
- [GraphEvents.ON_RUN_STEP_DELTA]: {
137
- handle: (event, data) => {
138
- aggregateContent({ event, data: data });
139
- },
140
- },
141
- [GraphEvents.ON_MESSAGE_DELTA]: {
142
- handle: (event, data) => {
143
- aggregateContent({ event, data: data });
144
- },
145
- },
146
- };
147
- const runConfig = {
148
- runId: `parallel-handoffs-${Date.now()}`,
149
- graphConfig: {
150
- type: 'multi-agent',
151
- agents,
152
- edges,
153
- },
154
- customHandlers,
155
- returnContent: true,
156
- skipCleanup: true,
157
- };
158
- try {
159
- const run = await Run.create(runConfig);
160
- /** Prompt designed to trigger parallel handoffs without confusing language */
161
- const userMessage = `Help me with two topics:
162
- 1. The history of the internet
163
- 2. A short poem about technology
164
-
165
- I need information on both topics.`;
166
- conversationHistory.push(new HumanMessage(userMessage));
167
- console.log('User message:', userMessage);
168
- console.log('\nInvoking multi-agent graph with parallel handoff request...\n');
169
- const config = {
170
- configurable: {
171
- thread_id: 'parallel-handoffs-test-1',
172
- },
173
- streamMode: 'values',
174
- version: 'v2',
175
- };
176
- const inputs = {
177
- messages: conversationHistory,
178
- };
179
- await run.processStream(inputs, config);
180
- const finalMessages = run.getRunMessages();
181
- if (finalMessages) {
182
- conversationHistory.push(...finalMessages);
183
- }
184
- /** Analyze parallel execution */
185
- console.log('\n\n========== TIMING SUMMARY ==========');
186
- console.log('Available timing keys:', Object.keys(agentTimings));
187
- for (const [agent, timing] of Object.entries(agentTimings)) {
188
- const duration = timing.end && timing.start ? timing.end - timing.start : 'N/A';
189
- console.log(`${agent}: started=${timing.start}ms, ended=${timing.end}ms, duration=${duration}ms`);
190
- }
191
- /** Check if researcher and writer ran in parallel (handle key variations) */
192
- const researcherKey = Object.keys(agentTimings).find((k) => k.includes('researcher'));
193
- const writerKey = Object.keys(agentTimings).find((k) => k.includes('writer'));
194
- const researcherTiming = researcherKey
195
- ? agentTimings[researcherKey]
196
- : undefined;
197
- const writerTiming = writerKey ? agentTimings[writerKey] : undefined;
198
- if (researcherTiming && writerTiming) {
199
- const bothStarted = researcherTiming.start && writerTiming.start;
200
- const bothEnded = researcherTiming.end && writerTiming.end;
201
- if (bothStarted && bothEnded) {
202
- const overlap = Math.min(researcherTiming.end, writerTiming.end) -
203
- Math.max(researcherTiming.start, writerTiming.start);
204
- if (overlap > 0) {
205
- console.log(`\nāœ… PARALLEL HANDOFFS SUCCESSFUL: ${overlap}ms overlap between researcher and writer`);
206
- }
207
- else {
208
- console.log(`\nāš ļø SEQUENTIAL EXECUTION: researcher and writer did not overlap`);
209
- console.log(` This may indicate the LLM called transfers sequentially, not in parallel`);
210
- }
211
- }
212
- }
213
- else {
214
- console.log('\nāš ļø Not all agents were invoked. Check if handoffs occurred.');
215
- console.log(' researcher timing:', researcherTiming);
216
- console.log(' writer timing:', writerTiming);
217
- }
218
- console.log('====================================\n');
219
- console.log('Final content parts:', contentParts.length, 'parts');
220
- console.dir(contentParts, { depth: null });
221
- await sleep(3000);
222
- }
223
- catch (error) {
224
- console.error('Error in parallel handoffs test:', error);
225
- throw error;
226
- }
227
- }
228
- testParallelHandoffs();
229
- //# sourceMappingURL=test-parallel-handoffs.js.map
@@ -1,132 +0,0 @@
1
- #!/usr/bin/env bun
2
- import { config } from 'dotenv';
3
- config();
4
- import { HumanMessage } from '@langchain/core/messages';
5
- import { Run } from '@/run';
6
- import { ChatModelStreamHandler } from '@/stream';
7
- import { Providers, GraphEvents } from '@/common';
8
- import { ToolEndHandler, ModelEndHandler } from '@/events';
9
- const conversationHistory = [];
10
- /**
11
- * Test edge case: switching from OpenAI supervisor (no thinking) to Bedrock specialist (with thinking enabled)
12
- * This should not throw an error about missing thinking blocks
13
- */
14
- async function testBedrockThinkingHandoff() {
15
- console.log('Testing OpenAI → Bedrock (with thinking) handoff...\n');
16
- // Create custom handlers
17
- const customHandlers = {
18
- [GraphEvents.TOOL_END]: new ToolEndHandler(),
19
- [GraphEvents.CHAT_MODEL_END]: new ModelEndHandler(),
20
- [GraphEvents.CHAT_MODEL_STREAM]: new ChatModelStreamHandler(),
21
- [GraphEvents.TOOL_START]: {
22
- handle: (_event, data) => {
23
- const toolData = data;
24
- if (toolData?.name) {
25
- console.log(`\nšŸ”§ Tool called: ${toolData.name}`);
26
- }
27
- },
28
- },
29
- };
30
- // Create the graph configuration
31
- function createGraphConfig() {
32
- console.log('Creating graph with OpenAI supervisor and Bedrock specialist with thinking enabled.\n');
33
- const agents = [
34
- {
35
- agentId: 'supervisor',
36
- provider: Providers.OPENAI,
37
- clientOptions: {
38
- modelName: 'gpt-4o-mini',
39
- apiKey: process.env.OPENAI_API_KEY,
40
- },
41
- instructions: `You are a task supervisor. When the user asks about code review, use transfer_to_code_reviewer to hand off to the specialist.`,
42
- maxContextTokens: 8000,
43
- },
44
- {
45
- agentId: 'code_reviewer',
46
- provider: Providers.BEDROCK,
47
- clientOptions: {
48
- region: process.env.BEDROCK_AWS_REGION || 'us-east-1',
49
- model: 'us.anthropic.claude-3-7-sonnet-20250219-v1:0',
50
- credentials: {
51
- accessKeyId: process.env.BEDROCK_AWS_ACCESS_KEY_ID,
52
- secretAccessKey: process.env.BEDROCK_AWS_SECRET_ACCESS_KEY,
53
- },
54
- additionalModelRequestFields: {
55
- thinking: {
56
- type: 'enabled',
57
- budget_tokens: 2000,
58
- },
59
- },
60
- },
61
- instructions: `You are a code review specialist using Bedrock with extended thinking. Think carefully about the code quality, best practices, and potential issues. Provide thoughtful feedback.`,
62
- maxContextTokens: 8000,
63
- },
64
- ];
65
- const edges = [
66
- {
67
- from: 'supervisor',
68
- to: ['code_reviewer'],
69
- description: 'Transfer to code review specialist',
70
- edgeType: 'transfer',
71
- },
72
- ];
73
- return {
74
- runId: `bedrock-thinking-handoff-test-${Date.now()}`,
75
- graphConfig: {
76
- type: 'multi-agent',
77
- agents,
78
- edges,
79
- },
80
- customHandlers,
81
- returnContent: true,
82
- skipCleanup: true,
83
- };
84
- }
85
- try {
86
- // Test query that should trigger a handoff
87
- const query = 'Can you review this function and tell me if there are any issues?\n\nfunction add(a, b) { return a + b; }';
88
- console.log(`${'='.repeat(60)}`);
89
- console.log(`USER QUERY: "${query}"`);
90
- console.log('='.repeat(60));
91
- // Initialize conversation
92
- conversationHistory.push(new HumanMessage(query));
93
- // Create and run the graph
94
- const runConfig = createGraphConfig();
95
- const run = await Run.create(runConfig);
96
- const config = {
97
- configurable: {
98
- thread_id: 'bedrock-thinking-handoff-test-1',
99
- },
100
- streamMode: 'values',
101
- version: 'v2',
102
- };
103
- console.log('\nProcessing request...\n');
104
- // Process with streaming
105
- const inputs = {
106
- messages: conversationHistory,
107
- };
108
- await run.processStream(inputs, config);
109
- const finalMessages = run.getRunMessages();
110
- if (finalMessages) {
111
- conversationHistory.push(...finalMessages);
112
- }
113
- // Success!
114
- console.log(`\n${'='.repeat(60)}`);
115
- console.log('āœ… TEST PASSED');
116
- console.log('='.repeat(60));
117
- console.log('\nSuccessfully handed off from OpenAI (no thinking) to');
118
- console.log('Bedrock with thinking enabled without errors!');
119
- console.log('\nThe ensureThinkingBlockInMessages() function correctly');
120
- console.log('handled the transition by converting tool sequences to');
121
- console.log('HumanMessages before calling the Bedrock API.');
122
- }
123
- catch (error) {
124
- console.error('\nāŒ TEST FAILED');
125
- console.error('='.repeat(60));
126
- console.error('Error:', error);
127
- process.exit(1);
128
- }
129
- }
130
- // Run the test
131
- testBedrockThinkingHandoff();
132
- //# sourceMappingURL=test-thinking-handoff-bedrock.js.map