@illuma-ai/agents 1.1.20 → 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 (246) 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/llm/bedrock/index.cjs +14 -0
  6. package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
  7. package/dist/cjs/run.cjs +20 -9
  8. package/dist/cjs/run.cjs.map +1 -1
  9. package/dist/esm/graphs/Graph.mjs +12 -1
  10. package/dist/esm/graphs/Graph.mjs.map +1 -1
  11. package/dist/esm/graphs/MultiAgentGraph.mjs +85 -1
  12. package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
  13. package/dist/esm/llm/bedrock/index.mjs +14 -0
  14. package/dist/esm/llm/bedrock/index.mjs.map +1 -1
  15. package/dist/esm/run.mjs +20 -9
  16. package/dist/esm/run.mjs.map +1 -1
  17. package/dist/types/graphs/MultiAgentGraph.d.ts +17 -0
  18. package/package.json +1 -1
  19. package/src/graphs/Graph.ts +12 -1
  20. package/src/graphs/MultiAgentGraph.ts +105 -1
  21. package/src/graphs/__tests__/multi-agent-delegate.test.ts +191 -0
  22. package/src/llm/bedrock/index.ts +17 -0
  23. package/src/run.ts +20 -11
  24. package/src/scripts/test-bedrock-handoff-autonomous.ts +231 -0
  25. package/src/agents/AgentContext.js +0 -782
  26. package/src/agents/AgentContext.test.js +0 -421
  27. package/src/agents/__tests__/AgentContext.test.js +0 -678
  28. package/src/agents/__tests__/resolveStructuredOutputMode.test.js +0 -117
  29. package/src/common/enum.js +0 -192
  30. package/src/common/index.js +0 -3
  31. package/src/events.js +0 -166
  32. package/src/graphs/Graph.js +0 -1857
  33. package/src/graphs/MultiAgentGraph.js +0 -1092
  34. package/src/graphs/__tests__/structured-output.integration.test.js +0 -624
  35. package/src/graphs/__tests__/structured-output.test.js +0 -144
  36. package/src/graphs/contextManagement.e2e.test.js +0 -718
  37. package/src/graphs/contextManagement.test.js +0 -485
  38. package/src/graphs/handoffValidation.test.js +0 -276
  39. package/src/graphs/index.js +0 -3
  40. package/src/index.js +0 -28
  41. package/src/instrumentation.js +0 -21
  42. package/src/llm/anthropic/index.js +0 -319
  43. package/src/llm/anthropic/types.js +0 -46
  44. package/src/llm/anthropic/utils/message_inputs.js +0 -627
  45. package/src/llm/anthropic/utils/message_outputs.js +0 -290
  46. package/src/llm/anthropic/utils/output_parsers.js +0 -89
  47. package/src/llm/anthropic/utils/tools.js +0 -25
  48. package/src/llm/bedrock/__tests__/bedrock-caching.test.js +0 -392
  49. package/src/llm/bedrock/index.js +0 -303
  50. package/src/llm/bedrock/types.js +0 -2
  51. package/src/llm/bedrock/utils/index.js +0 -6
  52. package/src/llm/bedrock/utils/message_inputs.js +0 -463
  53. package/src/llm/bedrock/utils/message_outputs.js +0 -269
  54. package/src/llm/fake.js +0 -92
  55. package/src/llm/google/index.js +0 -215
  56. package/src/llm/google/types.js +0 -12
  57. package/src/llm/google/utils/common.js +0 -670
  58. package/src/llm/google/utils/tools.js +0 -111
  59. package/src/llm/google/utils/zod_to_genai_parameters.js +0 -47
  60. package/src/llm/openai/index.js +0 -1033
  61. package/src/llm/openai/types.js +0 -2
  62. package/src/llm/openai/utils/index.js +0 -756
  63. package/src/llm/openai/utils/isReasoningModel.test.js +0 -79
  64. package/src/llm/openrouter/index.js +0 -261
  65. package/src/llm/openrouter/reasoning.test.js +0 -181
  66. package/src/llm/providers.js +0 -36
  67. package/src/llm/text.js +0 -65
  68. package/src/llm/vertexai/index.js +0 -402
  69. package/src/messages/__tests__/tools.test.js +0 -392
  70. package/src/messages/cache.js +0 -404
  71. package/src/messages/cache.test.js +0 -1167
  72. package/src/messages/content.js +0 -48
  73. package/src/messages/content.test.js +0 -314
  74. package/src/messages/core.js +0 -359
  75. package/src/messages/ensureThinkingBlock.test.js +0 -997
  76. package/src/messages/format.js +0 -973
  77. package/src/messages/formatAgentMessages.test.js +0 -2278
  78. package/src/messages/formatAgentMessages.tools.test.js +0 -362
  79. package/src/messages/formatMessage.test.js +0 -608
  80. package/src/messages/ids.js +0 -18
  81. package/src/messages/index.js +0 -9
  82. package/src/messages/labelContentByAgent.test.js +0 -725
  83. package/src/messages/prune.js +0 -438
  84. package/src/messages/reducer.js +0 -60
  85. package/src/messages/shiftIndexTokenCountMap.test.js +0 -63
  86. package/src/messages/summarize.js +0 -146
  87. package/src/messages/summarize.test.js +0 -332
  88. package/src/messages/tools.js +0 -90
  89. package/src/mockStream.js +0 -81
  90. package/src/prompts/collab.js +0 -7
  91. package/src/prompts/index.js +0 -3
  92. package/src/prompts/taskmanager.js +0 -58
  93. package/src/run.js +0 -427
  94. package/src/schemas/index.js +0 -3
  95. package/src/schemas/schema-preparation.test.js +0 -370
  96. package/src/schemas/validate.js +0 -314
  97. package/src/schemas/validate.test.js +0 -264
  98. package/src/scripts/abort.js +0 -127
  99. package/src/scripts/ant_web_search.js +0 -130
  100. package/src/scripts/ant_web_search_edge_case.js +0 -133
  101. package/src/scripts/ant_web_search_error_edge_case.js +0 -119
  102. package/src/scripts/args.js +0 -41
  103. package/src/scripts/bedrock-cache-debug.js +0 -186
  104. package/src/scripts/bedrock-content-aggregation-test.js +0 -195
  105. package/src/scripts/bedrock-merge-test.js +0 -80
  106. package/src/scripts/bedrock-parallel-tools-test.js +0 -150
  107. package/src/scripts/caching.js +0 -106
  108. package/src/scripts/cli.js +0 -152
  109. package/src/scripts/cli2.js +0 -119
  110. package/src/scripts/cli3.js +0 -163
  111. package/src/scripts/cli4.js +0 -165
  112. package/src/scripts/cli5.js +0 -165
  113. package/src/scripts/code_exec.js +0 -171
  114. package/src/scripts/code_exec_files.js +0 -180
  115. package/src/scripts/code_exec_multi_session.js +0 -185
  116. package/src/scripts/code_exec_ptc.js +0 -265
  117. package/src/scripts/code_exec_session.js +0 -217
  118. package/src/scripts/code_exec_simple.js +0 -120
  119. package/src/scripts/content.js +0 -111
  120. package/src/scripts/empty_input.js +0 -125
  121. package/src/scripts/handoff-test.js +0 -96
  122. package/src/scripts/image.js +0 -138
  123. package/src/scripts/memory.js +0 -83
  124. package/src/scripts/multi-agent-chain.js +0 -271
  125. package/src/scripts/multi-agent-conditional.js +0 -185
  126. package/src/scripts/multi-agent-document-review-chain.js +0 -171
  127. package/src/scripts/multi-agent-hybrid-flow.js +0 -264
  128. package/src/scripts/multi-agent-parallel-start.js +0 -214
  129. package/src/scripts/multi-agent-parallel.js +0 -346
  130. package/src/scripts/multi-agent-sequence.js +0 -184
  131. package/src/scripts/multi-agent-supervisor.js +0 -324
  132. package/src/scripts/multi-agent-test.js +0 -147
  133. package/src/scripts/parallel-asymmetric-tools-test.js +0 -202
  134. package/src/scripts/parallel-full-metadata-test.js +0 -176
  135. package/src/scripts/parallel-tools-test.js +0 -256
  136. package/src/scripts/programmatic_exec.js +0 -277
  137. package/src/scripts/programmatic_exec_agent.js +0 -168
  138. package/src/scripts/search.js +0 -118
  139. package/src/scripts/sequential-full-metadata-test.js +0 -143
  140. package/src/scripts/simple.js +0 -174
  141. package/src/scripts/single-agent-metadata-test.js +0 -152
  142. package/src/scripts/stream.js +0 -113
  143. package/src/scripts/test-custom-prompt-key.js +0 -132
  144. package/src/scripts/test-handoff-input.js +0 -143
  145. package/src/scripts/test-handoff-preamble.js +0 -227
  146. package/src/scripts/test-handoff-steering.js +0 -353
  147. package/src/scripts/test-multi-agent-list-handoff.js +0 -318
  148. package/src/scripts/test-parallel-agent-labeling.js +0 -253
  149. package/src/scripts/test-parallel-handoffs.js +0 -229
  150. package/src/scripts/test-thinking-handoff-bedrock.js +0 -132
  151. package/src/scripts/test-thinking-handoff.js +0 -132
  152. package/src/scripts/test-thinking-to-thinking-handoff-bedrock.js +0 -140
  153. package/src/scripts/test-tool-before-handoff-role-order.js +0 -223
  154. package/src/scripts/test-tools-before-handoff.js +0 -187
  155. package/src/scripts/test_code_api.js +0 -263
  156. package/src/scripts/thinking-bedrock.js +0 -128
  157. package/src/scripts/thinking-vertexai.js +0 -130
  158. package/src/scripts/thinking.js +0 -134
  159. package/src/scripts/tool_search.js +0 -114
  160. package/src/scripts/tools.js +0 -125
  161. package/src/specs/agent-handoffs-bedrock.integration.test.js +0 -280
  162. package/src/specs/agent-handoffs.test.js +0 -924
  163. package/src/specs/anthropic.simple.test.js +0 -287
  164. package/src/specs/azure.simple.test.js +0 -381
  165. package/src/specs/cache.simple.test.js +0 -282
  166. package/src/specs/custom-event-await.test.js +0 -148
  167. package/src/specs/deepseek.simple.test.js +0 -189
  168. package/src/specs/emergency-prune.test.js +0 -308
  169. package/src/specs/moonshot.simple.test.js +0 -237
  170. package/src/specs/observability.integration.test.js +0 -1337
  171. package/src/specs/openai.simple.test.js +0 -233
  172. package/src/specs/openrouter.simple.test.js +0 -202
  173. package/src/specs/prune.test.js +0 -733
  174. package/src/specs/reasoning.test.js +0 -144
  175. package/src/specs/spec.utils.js +0 -4
  176. package/src/specs/thinking-handoff.test.js +0 -486
  177. package/src/specs/thinking-prune.test.js +0 -600
  178. package/src/specs/token-distribution-edge-case.test.js +0 -246
  179. package/src/specs/token-memoization.test.js +0 -32
  180. package/src/specs/tokens.test.js +0 -49
  181. package/src/specs/tool-error.test.js +0 -139
  182. package/src/splitStream.js +0 -204
  183. package/src/splitStream.test.js +0 -504
  184. package/src/stream.js +0 -650
  185. package/src/stream.test.js +0 -225
  186. package/src/test/mockTools.js +0 -340
  187. package/src/tools/BrowserTools.js +0 -245
  188. package/src/tools/Calculator.js +0 -38
  189. package/src/tools/Calculator.test.js +0 -225
  190. package/src/tools/CodeExecutor.js +0 -233
  191. package/src/tools/ProgrammaticToolCalling.js +0 -602
  192. package/src/tools/StreamingToolCallBuffer.js +0 -179
  193. package/src/tools/ToolNode.js +0 -930
  194. package/src/tools/ToolSearch.js +0 -904
  195. package/src/tools/__tests__/BrowserTools.test.js +0 -306
  196. package/src/tools/__tests__/ProgrammaticToolCalling.integration.test.js +0 -276
  197. package/src/tools/__tests__/ProgrammaticToolCalling.test.js +0 -807
  198. package/src/tools/__tests__/StreamingToolCallBuffer.test.js +0 -175
  199. package/src/tools/__tests__/ToolApproval.test.js +0 -675
  200. package/src/tools/__tests__/ToolNode.recovery.test.js +0 -200
  201. package/src/tools/__tests__/ToolNode.session.test.js +0 -319
  202. package/src/tools/__tests__/ToolSearch.integration.test.js +0 -125
  203. package/src/tools/__tests__/ToolSearch.test.js +0 -812
  204. package/src/tools/__tests__/handlers.test.js +0 -799
  205. package/src/tools/__tests__/truncation-recovery.integration.test.js +0 -362
  206. package/src/tools/handlers.js +0 -306
  207. package/src/tools/schema.js +0 -25
  208. package/src/tools/search/anthropic.js +0 -34
  209. package/src/tools/search/content.js +0 -116
  210. package/src/tools/search/content.test.js +0 -133
  211. package/src/tools/search/firecrawl.js +0 -173
  212. package/src/tools/search/format.js +0 -198
  213. package/src/tools/search/highlights.js +0 -241
  214. package/src/tools/search/index.js +0 -3
  215. package/src/tools/search/jina-reranker.test.js +0 -106
  216. package/src/tools/search/rerankers.js +0 -165
  217. package/src/tools/search/schema.js +0 -102
  218. package/src/tools/search/search.js +0 -561
  219. package/src/tools/search/serper-scraper.js +0 -126
  220. package/src/tools/search/test.js +0 -129
  221. package/src/tools/search/tool.js +0 -453
  222. package/src/tools/search/types.js +0 -2
  223. package/src/tools/search/utils.js +0 -59
  224. package/src/types/graph.js +0 -24
  225. package/src/types/graph.test.js +0 -192
  226. package/src/types/index.js +0 -7
  227. package/src/types/llm.js +0 -2
  228. package/src/types/messages.js +0 -2
  229. package/src/types/run.js +0 -2
  230. package/src/types/stream.js +0 -2
  231. package/src/types/tools.js +0 -2
  232. package/src/utils/contextAnalytics.js +0 -79
  233. package/src/utils/contextAnalytics.test.js +0 -166
  234. package/src/utils/events.js +0 -26
  235. package/src/utils/graph.js +0 -11
  236. package/src/utils/handlers.js +0 -65
  237. package/src/utils/index.js +0 -10
  238. package/src/utils/llm.js +0 -21
  239. package/src/utils/llmConfig.js +0 -205
  240. package/src/utils/logging.js +0 -37
  241. package/src/utils/misc.js +0 -51
  242. package/src/utils/run.js +0 -69
  243. package/src/utils/schema.js +0 -21
  244. package/src/utils/title.js +0 -119
  245. package/src/utils/tokens.js +0 -92
  246. 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