@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,114 +0,0 @@
1
- // src/scripts/tool_search.ts
2
- /**
3
- * Test script for the Tool Search Regex tool.
4
- * Run with: npm run tool_search
5
- *
6
- * Demonstrates runtime registry injection - the tool registry is passed
7
- * at invocation time, not at initialization time.
8
- */
9
- import { config } from 'dotenv';
10
- config();
11
- import { createToolSearch } from '@/tools/ToolSearch';
12
- import { createToolSearchToolRegistry } from '@/test/mockTools';
13
- async function runTest(searchTool, testName, query, options) {
14
- console.log(`\n${'='.repeat(60)}`);
15
- console.log(`TEST: ${testName}`);
16
- console.log(`Query: "${query}"`);
17
- if (options.fields)
18
- console.log(`Fields: ${options.fields.join(', ')}`);
19
- if (options.max_results)
20
- console.log(`Max Results: ${options.max_results}`);
21
- console.log('='.repeat(60));
22
- try {
23
- const startTime = Date.now();
24
- // Manual testing uses schema params directly
25
- // (ToolNode uses different param structure when injecting)
26
- const result = await searchTool.invoke({
27
- query,
28
- fields: options.fields,
29
- max_results: options.max_results,
30
- });
31
- const duration = Date.now() - startTime;
32
- console.log(`\nResult (${duration}ms):`);
33
- if (Array.isArray(result)) {
34
- console.log(result[0]);
35
- if (options.showArtifact) {
36
- console.log('\n--- Artifact ---');
37
- console.dir(result[1], { depth: null });
38
- }
39
- }
40
- else {
41
- console.log(result);
42
- }
43
- }
44
- catch (error) {
45
- console.error('Error:', error instanceof Error ? error.message : error);
46
- }
47
- }
48
- async function main() {
49
- console.log('Tool Search Regex - Test Script');
50
- console.log('================================');
51
- console.log('Demonstrating runtime tool registry injection\n');
52
- const apiKey = process.env.CODE_EXECUTOR_API_KEY;
53
- if (!apiKey) {
54
- console.error('Error: CODE_EXECUTOR_API_KEY environment variable is not set.');
55
- console.log('Please set it in your .env file or environment.');
56
- process.exit(1);
57
- }
58
- console.log('Creating sample tool registry...');
59
- const toolRegistry = createToolSearchToolRegistry();
60
- console.log(`Registry contains ${toolRegistry.size} tools (${Array.from(toolRegistry.values()).filter((t) => t.defer_loading).length} deferred)`);
61
- console.log('\nCreating Tool Search Regex tool WITH registry for testing...');
62
- const searchTool = createToolSearch({ apiKey, toolRegistry });
63
- console.log('Tool created successfully!');
64
- console.log('Note: In production, ToolNode injects toolRegistry via params when invoked through the graph.\n');
65
- const baseOptions = { toolRegistry, onlyDeferred: true };
66
- // Test 1: Simple keyword search (with artifact display)
67
- await runTest(searchTool, 'Simple keyword search', 'expense', {
68
- ...baseOptions,
69
- showArtifact: true,
70
- });
71
- // Test 2: Search for weather-related tools
72
- await runTest(searchTool, 'Weather tools', 'weather|forecast', baseOptions);
73
- // Test 3: Search with case variations
74
- await runTest(searchTool, 'Case insensitive search', 'EMAIL', baseOptions);
75
- // Test 4: Search in description only
76
- await runTest(searchTool, 'Description-only search', 'database', {
77
- ...baseOptions,
78
- fields: ['description'],
79
- });
80
- // Test 5: Search with parameters field
81
- await runTest(searchTool, 'Parameters search', 'query', {
82
- ...baseOptions,
83
- fields: ['parameters'],
84
- });
85
- // Test 6: Limited results
86
- await runTest(searchTool, 'Limited to 2 results', 'get', {
87
- ...baseOptions,
88
- max_results: 2,
89
- });
90
- // Test 7: Pattern that matches nothing
91
- await runTest(searchTool, 'No matches', 'xyznonexistent123', baseOptions);
92
- // Test 8: Regex pattern with character class
93
- await runTest(searchTool, 'Regex with character class', 'get_[a-z]+', baseOptions);
94
- // Test 9: Dangerous pattern (should be sanitized)
95
- await runTest(searchTool, 'Dangerous pattern (sanitized)', '(a+)+', baseOptions);
96
- // Test 10: Search all fields
97
- await runTest(searchTool, 'All fields search', 'text', {
98
- ...baseOptions,
99
- fields: ['name', 'description', 'parameters'],
100
- });
101
- // Test 11: Search ALL tools (not just deferred)
102
- await runTest(searchTool, 'Search ALL tools (incl. non-deferred)', 'calc', {
103
- toolRegistry,
104
- onlyDeferred: false, // Include non-deferred tools
105
- });
106
- console.log('\n' + '='.repeat(60));
107
- console.log('All tests completed!');
108
- console.log('='.repeat(60) + '\n');
109
- }
110
- main().catch((err) => {
111
- console.error('Fatal error:', err);
112
- process.exit(1);
113
- });
114
- //# sourceMappingURL=tool_search.js.map
@@ -1,125 +0,0 @@
1
- /* eslint-disable no-console */
2
- // src/scripts/cli.ts
3
- import { config } from 'dotenv';
4
- config();
5
- import { HumanMessage } from '@langchain/core/messages';
6
- import { ChatModelStreamHandler, createContentAggregator } from '@/stream';
7
- import { ToolEndHandler, ModelEndHandler } from '@/events';
8
- import { GraphEvents, Providers } from '@/common';
9
- import { getLLMConfig } from '@/utils/llmConfig';
10
- import { Calculator } from '@/tools/Calculator';
11
- import { getArgs } from '@/scripts/args';
12
- import { Run } from '@/run';
13
- const conversationHistory = [];
14
- async function testStandardStreaming() {
15
- const { userName, location, provider, currentDate } = await getArgs();
16
- const { contentParts, aggregateContent } = createContentAggregator();
17
- const customHandlers = {
18
- [GraphEvents.TOOL_END]: new ToolEndHandler(),
19
- [GraphEvents.CHAT_MODEL_END]: new ModelEndHandler(),
20
- [GraphEvents.CHAT_MODEL_START]: {
21
- handle: (_event, _data, metadata) => {
22
- console.log('\n====== CHAT_MODEL_START METADATA ======');
23
- console.dir(metadata, { depth: null });
24
- },
25
- },
26
- [GraphEvents.CHAT_MODEL_STREAM]: new ChatModelStreamHandler(),
27
- [GraphEvents.ON_RUN_STEP_COMPLETED]: {
28
- handle: (event, data, metadata) => {
29
- console.log('====== ON_RUN_STEP_COMPLETED ======');
30
- console.log('METADATA:');
31
- console.dir(metadata, { depth: null });
32
- aggregateContent({
33
- event,
34
- data: data,
35
- });
36
- },
37
- },
38
- [GraphEvents.ON_RUN_STEP]: {
39
- handle: (event, data, metadata) => {
40
- console.log('====== ON_RUN_STEP ======');
41
- console.log('DATA:');
42
- console.dir(data, { depth: null });
43
- console.log('METADATA:');
44
- console.dir(metadata, { depth: null });
45
- aggregateContent({ event, data: data });
46
- },
47
- },
48
- [GraphEvents.ON_RUN_STEP_DELTA]: {
49
- handle: (event, data) => {
50
- aggregateContent({ event, data: data });
51
- },
52
- },
53
- [GraphEvents.ON_MESSAGE_DELTA]: {
54
- handle: (event, data) => {
55
- aggregateContent({ event, data: data });
56
- },
57
- },
58
- [GraphEvents.ON_REASONING_DELTA]: {
59
- handle: (event, data) => {
60
- aggregateContent({ event, data: data });
61
- },
62
- },
63
- [GraphEvents.TOOL_START]: {
64
- handle: (_event, data, metadata) => {
65
- console.log('====== TOOL_START ======');
66
- console.log('METADATA:');
67
- console.dir(metadata, { depth: null });
68
- },
69
- },
70
- };
71
- const llmConfig = getLLMConfig(provider);
72
- if (llmConfig.provider === Providers.BEDROCK) {
73
- llmConfig.promptCache = true;
74
- }
75
- const run = await Run.create({
76
- runId: 'test-run-id',
77
- graphConfig: {
78
- type: 'standard',
79
- llmConfig,
80
- tools: [new Calculator()],
81
- instructions: 'You are a friendly AI assistant. Always address the user by their name.',
82
- additional_instructions: `The user's name is ${userName} and they are located in ${location}.`,
83
- maxContextTokens: 89000,
84
- },
85
- indexTokenCountMap: { 0: 35 },
86
- returnContent: true,
87
- skipCleanup: true,
88
- customHandlers,
89
- });
90
- const config = {
91
- configurable: {
92
- provider,
93
- thread_id: 'conversation-num-1',
94
- },
95
- streamMode: 'values',
96
- version: 'v2',
97
- };
98
- console.log('Test 1: Calculation query');
99
- const userMessage = `What is 1123123 + 123123 / 20348? After that, run some interesting calculations based off the result`;
100
- conversationHistory.push(new HumanMessage(userMessage));
101
- const inputs = {
102
- messages: conversationHistory,
103
- };
104
- const finalContentParts = await run.processStream(inputs, config);
105
- const finalMessages = run.getRunMessages();
106
- if (finalMessages) {
107
- conversationHistory.push(...finalMessages);
108
- console.dir(conversationHistory, { depth: null });
109
- }
110
- // console.dir(finalContentParts, { depth: null });
111
- console.log('\n\n====================\n\n');
112
- console.dir(contentParts, { depth: null });
113
- }
114
- process.on('unhandledRejection', (reason, promise) => {
115
- console.error('Unhandled Rejection at:', promise, 'reason:', reason);
116
- console.log('Conversation history:');
117
- process.exit(1);
118
- });
119
- testStandardStreaming().catch((err) => {
120
- console.error(err);
121
- console.log('Conversation history:');
122
- console.dir(conversationHistory, { depth: null });
123
- process.exit(1);
124
- });
125
- //# sourceMappingURL=tools.js.map
@@ -1,280 +0,0 @@
1
- /**
2
- * Integration test: Agent Handoff with Bedrock
3
- *
4
- * Verifies end-to-end that:
5
- * 1. Handoff tool descriptions are enriched with agent name + description
6
- * 2. The LLM (Bedrock Claude) can see and use these descriptions to route correctly
7
- * 3. The handoff actually transfers control to the correct agent
8
- *
9
- * Requires: BEDROCK_AWS_ACCESS_KEY_ID, BEDROCK_AWS_SECRET_ACCESS_KEY, BEDROCK_AWS_REGION
10
- */
11
- import { config } from 'dotenv';
12
- import { resolve } from 'path';
13
- // Load from local .env first, then fall back to ranger's .env for Bedrock credentials
14
- config();
15
- config({
16
- path: resolve(process.cwd(), '..', 'ranger', '.env'),
17
- override: false,
18
- });
19
- import { HumanMessage } from '@langchain/core/messages';
20
- import { Providers, Constants, GraphEvents } from '@/common';
21
- import { ChatModelStreamHandler, createContentAggregator } from '@/stream';
22
- import { ToolEndHandler, ModelEndHandler } from '@/events';
23
- import { Run } from '@/run';
24
- const bedrockRegion = process.env.BEDROCK_AWS_REGION != null &&
25
- process.env.BEDROCK_AWS_REGION !== ''
26
- ? process.env.BEDROCK_AWS_REGION
27
- : process.env.BEDROCK_AWS_DEFAULT_REGION;
28
- const hasBedrock = process.env.BEDROCK_AWS_ACCESS_KEY_ID != null &&
29
- process.env.BEDROCK_AWS_ACCESS_KEY_ID !== '' &&
30
- process.env.BEDROCK_AWS_SECRET_ACCESS_KEY != null &&
31
- process.env.BEDROCK_AWS_SECRET_ACCESS_KEY !== '' &&
32
- bedrockRegion != null &&
33
- bedrockRegion !== '';
34
- const describeIf = hasBedrock ? describe : describe.skip;
35
- /** Helper to safely get tool description from tool object */
36
- const getToolDescription = (tool) => {
37
- return tool.description;
38
- };
39
- /** Helper to safely get tool name from tool object */
40
- const getToolName = (tool) => {
41
- return tool.name;
42
- };
43
- /** Helper to find tool by name */
44
- const findToolByName = (tools, name) => {
45
- return tools?.find((tool) => getToolName(tool) === name);
46
- };
47
- describeIf('Agent Handoff E2E with Bedrock', () => {
48
- jest.setTimeout(120000);
49
- const bedrockOptions = {
50
- model: 'us.anthropic.claude-3-5-haiku-20241022-v1:0',
51
- region: bedrockRegion != null && bedrockRegion !== ''
52
- ? bedrockRegion
53
- : 'us-east-1',
54
- credentials: {
55
- accessKeyId: process.env.BEDROCK_AWS_ACCESS_KEY_ID,
56
- secretAccessKey: process.env.BEDROCK_AWS_SECRET_ACCESS_KEY,
57
- },
58
- };
59
- const createBedrockAgent = (agentId, name, description, instructions) => ({
60
- agentId,
61
- name,
62
- description,
63
- provider: Providers.BEDROCK,
64
- clientOptions: bedrockOptions,
65
- instructions,
66
- maxContextTokens: 28000,
67
- });
68
- describe('Tool Description Enrichment (no edge.description)', () => {
69
- it('should generate tool descriptions from agent name + description when edge has no description', async () => {
70
- const agents = [
71
- createBedrockAgent('supervisor_abc123', 'Supervisor', 'Routes requests to specialists', 'You are a supervisor. Route requests to the appropriate specialist.'),
72
- createBedrockAgent('agent_W47hBnn2RoVZEOy5595GC', 'Sales Expert', 'Handles product pricing, quotes, and purchase orders for enterprise clients', 'You are a sales expert.'),
73
- createBedrockAgent('agent_X92kLmn4TpQR8vw3221HD', 'Technical Support', 'Troubleshoots technical issues, resolves bugs, and handles escalations', 'You are a technical support agent.'),
74
- ];
75
- // Edges WITHOUT explicit descriptions - simulates what happens in production
76
- // when users add handoffs through the UI without typing descriptions
77
- const edges = [
78
- {
79
- from: 'supervisor_abc123',
80
- to: 'agent_W47hBnn2RoVZEOy5595GC',
81
- edgeType: 'handoff',
82
- // No description - should auto-generate from agent name + description
83
- },
84
- {
85
- from: 'supervisor_abc123',
86
- to: 'agent_X92kLmn4TpQR8vw3221HD',
87
- edgeType: 'handoff',
88
- // No description
89
- },
90
- ];
91
- const run = await Run.create({
92
- runId: `bedrock-handoff-desc-${Date.now()}`,
93
- graphConfig: {
94
- type: 'multi-agent',
95
- agents,
96
- edges,
97
- },
98
- returnContent: true,
99
- });
100
- const supervisorContext = run.Graph.agentContexts.get('supervisor_abc123');
101
- // Verify the handoff tools have enriched descriptions
102
- const salesTool = findToolByName(supervisorContext?.tools, `${Constants.LC_TRANSFER_TO_}agent_W47hBnn2RoVZEOy5595GC`);
103
- const supportTool = findToolByName(supervisorContext?.tools, `${Constants.LC_TRANSFER_TO_}agent_X92kLmn4TpQR8vw3221HD`);
104
- expect(salesTool).toBeDefined();
105
- expect(supportTool).toBeDefined();
106
- const salesDesc = getToolDescription(salesTool);
107
- const supportDesc = getToolDescription(supportTool);
108
- // CRITICAL: Descriptions must NOT be just "Transfer control to agent 'agent_W47hBnn...'"
109
- // They must include the human-readable name and description
110
- expect(salesDesc).toContain('Sales Expert');
111
- expect(salesDesc).toContain('pricing');
112
- expect(salesDesc).not.toContain('agent_W47hBnn2RoVZEOy5595GC');
113
- expect(supportDesc).toContain('Technical Support');
114
- expect(supportDesc).toContain('Troubleshoots');
115
- expect(supportDesc).not.toContain('agent_X92kLmn4TpQR8vw3221HD');
116
- /* eslint-disable no-console */
117
- console.log('[PASS] Sales tool description:', salesDesc);
118
- console.log('[PASS] Support tool description:', supportDesc);
119
- /* eslint-enable no-console */
120
- });
121
- });
122
- describe('Live Bedrock Handoff Routing', () => {
123
- it('should route a sales question to the Sales Expert agent', async () => {
124
- const agents = [
125
- createBedrockAgent('router', 'Router', 'Routes user requests to specialists', `You are a request router. You must analyze the user's message and transfer to the appropriate specialist.
126
-
127
- IMPORTANT: Do NOT answer the question yourself. You MUST use one of your transfer tools to hand off to a specialist.
128
- Pick the specialist whose description best matches the user's request.`),
129
- createBedrockAgent('sales_agent', 'Sales Expert', 'Handles product pricing, quotes, and purchase orders', 'You are a sales expert. Answer questions about pricing and products. Be concise.'),
130
- createBedrockAgent('support_agent', 'Technical Support', 'Troubleshoots technical issues and resolves bugs', 'You are technical support. Help with technical problems. Be concise.'),
131
- ];
132
- const edges = [
133
- { from: 'router', to: 'sales_agent', edgeType: 'handoff' },
134
- { from: 'router', to: 'support_agent', edgeType: 'handoff' },
135
- ];
136
- const { contentParts: _contentParts, aggregateContent } = createContentAggregator();
137
- const customHandlers = {
138
- [GraphEvents.TOOL_END]: new ToolEndHandler(),
139
- [GraphEvents.CHAT_MODEL_END]: new ModelEndHandler(),
140
- [GraphEvents.CHAT_MODEL_STREAM]: new ChatModelStreamHandler(),
141
- [GraphEvents.ON_RUN_STEP]: {
142
- handle: (event, data) => {
143
- aggregateContent({
144
- event: event,
145
- data: data,
146
- });
147
- },
148
- },
149
- [GraphEvents.ON_RUN_STEP_COMPLETED]: {
150
- handle: (event, data) => {
151
- aggregateContent({
152
- event: event,
153
- data: data,
154
- });
155
- },
156
- },
157
- [GraphEvents.ON_MESSAGE_DELTA]: {
158
- handle: (event, data) => {
159
- aggregateContent({
160
- event: event,
161
- data: data,
162
- });
163
- },
164
- },
165
- };
166
- const run = await Run.create({
167
- runId: `bedrock-live-handoff-${Date.now()}`,
168
- graphConfig: {
169
- type: 'multi-agent',
170
- agents,
171
- edges,
172
- },
173
- customHandlers,
174
- returnContent: true,
175
- });
176
- const config = {
177
- configurable: { thread_id: 'bedrock-handoff-test' },
178
- streamMode: 'values',
179
- version: 'v2',
180
- };
181
- // Send a sales-related question
182
- const messages = [
183
- new HumanMessage('What is the pricing for your enterprise plan?'),
184
- ];
185
- await run.processStream({ messages }, config);
186
- const finalMessages = run.getRunMessages();
187
- expect(finalMessages).toBeDefined();
188
- expect(finalMessages.length).toBeGreaterThan(1);
189
- // Verify the handoff happened to the sales agent (not support)
190
- const toolMessages = finalMessages.filter((msg) => msg.getType() === 'tool');
191
- const salesHandoff = toolMessages.find((msg) => msg.name === `${Constants.LC_TRANSFER_TO_}sales_agent`);
192
- const supportHandoff = toolMessages.find((msg) => msg.name === `${Constants.LC_TRANSFER_TO_}support_agent`);
193
- expect(salesHandoff).toBeDefined();
194
- expect(supportHandoff).toBeUndefined();
195
- /* eslint-disable no-console */
196
- console.log('[PASS] Router correctly handed off to Sales Expert');
197
- console.log('[PASS] Handoff tool message:', salesHandoff?.content);
198
- /* eslint-enable no-console */
199
- // Verify the sales agent actually responded
200
- const aiMessages = finalMessages.filter((msg) => msg.getType() === 'ai');
201
- expect(aiMessages.length).toBeGreaterThanOrEqual(2); // Router + Sales responses
202
- });
203
- it('should route a technical question to the Support agent', async () => {
204
- const agents = [
205
- createBedrockAgent('router', 'Router', 'Routes user requests to specialists', `You are a request router. You must analyze the user's message and transfer to the appropriate specialist.
206
-
207
- IMPORTANT: Do NOT answer the question yourself. You MUST use one of your transfer tools to hand off to a specialist.
208
- Pick the specialist whose description best matches the user's request.`),
209
- createBedrockAgent('sales_agent', 'Sales Expert', 'Handles product pricing, quotes, and purchase orders', 'You are a sales expert. Answer questions about pricing. Be concise.'),
210
- createBedrockAgent('support_agent', 'Technical Support', 'Troubleshoots technical issues, resolves bugs, and handles error messages', 'You are technical support. Help with technical problems. Be concise.'),
211
- ];
212
- const edges = [
213
- { from: 'router', to: 'sales_agent', edgeType: 'handoff' },
214
- { from: 'router', to: 'support_agent', edgeType: 'handoff' },
215
- ];
216
- const { contentParts: _contentParts, aggregateContent } = createContentAggregator();
217
- const customHandlers = {
218
- [GraphEvents.TOOL_END]: new ToolEndHandler(),
219
- [GraphEvents.CHAT_MODEL_END]: new ModelEndHandler(),
220
- [GraphEvents.CHAT_MODEL_STREAM]: new ChatModelStreamHandler(),
221
- [GraphEvents.ON_RUN_STEP]: {
222
- handle: (event, data) => {
223
- aggregateContent({
224
- event: event,
225
- data: data,
226
- });
227
- },
228
- },
229
- [GraphEvents.ON_RUN_STEP_COMPLETED]: {
230
- handle: (event, data) => {
231
- aggregateContent({
232
- event: event,
233
- data: data,
234
- });
235
- },
236
- },
237
- [GraphEvents.ON_MESSAGE_DELTA]: {
238
- handle: (event, data) => {
239
- aggregateContent({
240
- event: event,
241
- data: data,
242
- });
243
- },
244
- },
245
- };
246
- const run = await Run.create({
247
- runId: `bedrock-live-handoff-support-${Date.now()}`,
248
- graphConfig: {
249
- type: 'multi-agent',
250
- agents,
251
- edges,
252
- },
253
- customHandlers,
254
- returnContent: true,
255
- });
256
- const config = {
257
- configurable: { thread_id: 'bedrock-handoff-support-test' },
258
- streamMode: 'values',
259
- version: 'v2',
260
- };
261
- // Send a technical question
262
- const messages = [
263
- new HumanMessage('I am getting an error 500 when trying to login. The page crashes after entering my password.'),
264
- ];
265
- await run.processStream({ messages }, config);
266
- const finalMessages = run.getRunMessages();
267
- expect(finalMessages).toBeDefined();
268
- const toolMessages = finalMessages.filter((msg) => msg.getType() === 'tool');
269
- const supportHandoff = toolMessages.find((msg) => msg.name === `${Constants.LC_TRANSFER_TO_}support_agent`);
270
- const salesHandoff = toolMessages.find((msg) => msg.name === `${Constants.LC_TRANSFER_TO_}sales_agent`);
271
- expect(supportHandoff).toBeDefined();
272
- expect(salesHandoff).toBeUndefined();
273
- /* eslint-disable no-console */
274
- console.log('[PASS] Router correctly handed off to Technical Support');
275
- console.log('[PASS] Handoff tool message:', supportHandoff?.content);
276
- /* eslint-enable no-console */
277
- });
278
- });
279
- });
280
- //# sourceMappingURL=agent-handoffs-bedrock.integration.test.js.map