@illuma-ai/agents 1.1.14 → 1.1.16

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 (66) hide show
  1. package/dist/cjs/common/enum.cjs +14 -3
  2. package/dist/cjs/common/enum.cjs.map +1 -1
  3. package/dist/cjs/graphs/MultiAgentGraph.cjs +304 -106
  4. package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
  5. package/dist/cjs/main.cjs +2 -0
  6. package/dist/cjs/main.cjs.map +1 -1
  7. package/dist/cjs/types/graph.cjs.map +1 -1
  8. package/dist/esm/common/enum.mjs +12 -4
  9. package/dist/esm/common/enum.mjs.map +1 -1
  10. package/dist/esm/graphs/MultiAgentGraph.mjs +306 -108
  11. package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
  12. package/dist/esm/main.mjs +1 -1
  13. package/dist/esm/types/graph.mjs.map +1 -1
  14. package/dist/types/common/enum.d.ts +11 -3
  15. package/dist/types/graphs/MultiAgentGraph.d.ts +72 -18
  16. package/dist/types/types/graph.d.ts +17 -5
  17. package/package.json +1 -1
  18. package/src/common/__tests__/enum.test.ts +15 -7
  19. package/src/common/enum.ts +13 -3
  20. package/src/graphs/MultiAgentGraph.ts +385 -107
  21. package/src/graphs/__tests__/multi-agent-delegate.test.ts +208 -0
  22. package/src/graphs/__tests__/multi-agent-edges.test.ts +98 -61
  23. package/src/scripts/multi-agent-chain.js +1 -1
  24. package/src/scripts/multi-agent-chain.ts +1 -1
  25. package/src/scripts/multi-agent-document-review-chain.js +1 -1
  26. package/src/scripts/multi-agent-document-review-chain.ts +1 -1
  27. package/src/scripts/multi-agent-hybrid-flow.js +3 -3
  28. package/src/scripts/multi-agent-hybrid-flow.ts +3 -3
  29. package/src/scripts/multi-agent-parallel.js +2 -2
  30. package/src/scripts/multi-agent-parallel.ts +2 -2
  31. package/src/scripts/multi-agent-sequence.js +2 -2
  32. package/src/scripts/multi-agent-sequence.ts +2 -2
  33. package/src/scripts/multi-agent-supervisor.js +5 -5
  34. package/src/scripts/multi-agent-supervisor.ts +5 -5
  35. package/src/scripts/poc-multi-agent-comprehensive.ts +7 -7
  36. package/src/scripts/sequential-full-metadata-test.js +1 -1
  37. package/src/scripts/sequential-full-metadata-test.ts +1 -1
  38. package/src/scripts/test-custom-prompt-key.js +3 -3
  39. package/src/scripts/test-custom-prompt-key.ts +3 -3
  40. package/src/scripts/test-handoff-input.js +1 -1
  41. package/src/scripts/test-handoff-input.ts +1 -1
  42. package/src/scripts/test-handoff-preamble.js +1 -1
  43. package/src/scripts/test-handoff-preamble.ts +1 -1
  44. package/src/scripts/test-handoff-steering.js +3 -3
  45. package/src/scripts/test-handoff-steering.ts +3 -3
  46. package/src/scripts/test-multi-agent-list-handoff.js +1 -1
  47. package/src/scripts/test-multi-agent-list-handoff.ts +1 -1
  48. package/src/scripts/test-parallel-agent-labeling.js +2 -2
  49. package/src/scripts/test-parallel-agent-labeling.ts +2 -2
  50. package/src/scripts/test-parallel-handoffs.js +2 -2
  51. package/src/scripts/test-parallel-handoffs.ts +2 -2
  52. package/src/scripts/test-thinking-handoff-bedrock.js +1 -1
  53. package/src/scripts/test-thinking-handoff-bedrock.ts +1 -1
  54. package/src/scripts/test-thinking-handoff.js +1 -1
  55. package/src/scripts/test-thinking-handoff.ts +1 -1
  56. package/src/scripts/test-thinking-to-thinking-handoff-bedrock.js +1 -1
  57. package/src/scripts/test-thinking-to-thinking-handoff-bedrock.ts +1 -1
  58. package/src/scripts/test-tool-before-handoff-role-order.js +1 -1
  59. package/src/scripts/test-tool-before-handoff-role-order.ts +1 -1
  60. package/src/scripts/test-tools-before-handoff.js +1 -1
  61. package/src/scripts/test-tools-before-handoff.ts +1 -1
  62. package/src/specs/agent-handoffs-bedrock.integration.test.ts +6 -6
  63. package/src/specs/agent-handoffs.test.ts +35 -35
  64. package/src/specs/thinking-handoff.test.ts +9 -9
  65. package/src/tools/search/search.test.ts +173 -0
  66. package/src/types/graph.ts +17 -5
@@ -94,7 +94,7 @@ describe('Agent Handoffs Tests', () => {
94
94
  {
95
95
  from: 'agent_a',
96
96
  to: 'agent_b',
97
- edgeType: EdgeType.HANDOFF,
97
+ edgeType: EdgeType.TRANSFER,
98
98
  description: 'Transfer to agent B',
99
99
  },
100
100
  ];
@@ -128,7 +128,7 @@ describe('Agent Handoffs Tests', () => {
128
128
  {
129
129
  from: 'agent_a',
130
130
  to: 'agent_b',
131
- edgeType: EdgeType.HANDOFF,
131
+ edgeType: EdgeType.TRANSFER,
132
132
  description: 'Transfer to agent B when needed',
133
133
  },
134
134
  ];
@@ -192,7 +192,7 @@ describe('Agent Handoffs Tests', () => {
192
192
  {
193
193
  from: 'agent_a',
194
194
  to: 'agent_b',
195
- edgeType: EdgeType.HANDOFF,
195
+ edgeType: EdgeType.TRANSFER,
196
196
  },
197
197
  ];
198
198
 
@@ -223,13 +223,13 @@ describe('Agent Handoffs Tests', () => {
223
223
  {
224
224
  from: 'agent_a',
225
225
  to: 'agent_b',
226
- edgeType: EdgeType.HANDOFF,
226
+ edgeType: EdgeType.TRANSFER,
227
227
  description: 'Transfer to agent B',
228
228
  },
229
229
  {
230
230
  from: 'agent_b',
231
231
  to: 'agent_a',
232
- edgeType: EdgeType.HANDOFF,
232
+ edgeType: EdgeType.TRANSFER,
233
233
  description: 'Transfer to agent A',
234
234
  },
235
235
  ];
@@ -268,12 +268,12 @@ describe('Agent Handoffs Tests', () => {
268
268
  {
269
269
  from: 'agent_a',
270
270
  to: 'agent_b',
271
- edgeType: EdgeType.HANDOFF,
271
+ edgeType: EdgeType.TRANSFER,
272
272
  },
273
273
  {
274
274
  from: 'agent_b',
275
275
  to: 'agent_a',
276
- edgeType: EdgeType.HANDOFF,
276
+ edgeType: EdgeType.TRANSFER,
277
277
  },
278
278
  ];
279
279
 
@@ -334,13 +334,13 @@ describe('Agent Handoffs Tests', () => {
334
334
  {
335
335
  from: 'agent_a',
336
336
  to: 'agent_b',
337
- edgeType: EdgeType.HANDOFF,
337
+ edgeType: EdgeType.TRANSFER,
338
338
  description: 'Transfer to agent B',
339
339
  },
340
340
  {
341
341
  from: 'agent_b',
342
342
  to: 'agent_c',
343
- edgeType: EdgeType.HANDOFF,
343
+ edgeType: EdgeType.TRANSFER,
344
344
  description: 'Transfer to agent C',
345
345
  },
346
346
  ];
@@ -395,19 +395,19 @@ describe('Agent Handoffs Tests', () => {
395
395
  {
396
396
  from: 'router',
397
397
  to: 'agent_a',
398
- edgeType: EdgeType.HANDOFF,
398
+ edgeType: EdgeType.TRANSFER,
399
399
  description: 'Transfer to agent A for task A',
400
400
  },
401
401
  {
402
402
  from: 'router',
403
403
  to: 'agent_b',
404
- edgeType: EdgeType.HANDOFF,
404
+ edgeType: EdgeType.TRANSFER,
405
405
  description: 'Transfer to agent B for task B',
406
406
  },
407
407
  {
408
408
  from: 'router',
409
409
  to: 'agent_c',
410
- edgeType: EdgeType.HANDOFF,
410
+ edgeType: EdgeType.TRANSFER,
411
411
  description: 'Transfer to agent C for task C',
412
412
  },
413
413
  ];
@@ -449,13 +449,13 @@ describe('Agent Handoffs Tests', () => {
449
449
  {
450
450
  from: 'router',
451
451
  to: 'agent_a',
452
- edgeType: EdgeType.HANDOFF,
452
+ edgeType: EdgeType.TRANSFER,
453
453
  description: 'Transfer to agent A',
454
454
  },
455
455
  {
456
456
  from: 'router',
457
457
  to: 'agent_b',
458
- edgeType: EdgeType.HANDOFF,
458
+ edgeType: EdgeType.TRANSFER,
459
459
  description: 'Transfer to agent B',
460
460
  },
461
461
  ];
@@ -519,7 +519,7 @@ describe('Agent Handoffs Tests', () => {
519
519
  {
520
520
  from: 'agent_a',
521
521
  to: 'agent_b',
522
- edgeType: EdgeType.HANDOFF,
522
+ edgeType: EdgeType.TRANSFER,
523
523
  description: 'Transfer to agent B with instructions',
524
524
  prompt: 'Provide specific instructions for agent B',
525
525
  promptKey: 'instructions',
@@ -551,7 +551,7 @@ describe('Agent Handoffs Tests', () => {
551
551
  {
552
552
  from: 'agent_a',
553
553
  to: 'agent_b',
554
- edgeType: EdgeType.HANDOFF,
554
+ edgeType: EdgeType.TRANSFER,
555
555
  prompt: 'Instructions for handoff',
556
556
  // promptKey not specified, should default to 'instructions'
557
557
  },
@@ -581,7 +581,7 @@ describe('Agent Handoffs Tests', () => {
581
581
  {
582
582
  from: 'agent_a',
583
583
  to: 'agent_b',
584
- edgeType: EdgeType.HANDOFF,
584
+ edgeType: EdgeType.TRANSFER,
585
585
  description: 'Transfer to agent B',
586
586
  prompt: 'Additional context for agent B',
587
587
  promptKey: 'context',
@@ -638,7 +638,7 @@ describe('Agent Handoffs Tests', () => {
638
638
  {
639
639
  from: 'agent_a',
640
640
  to: 'agent_a',
641
- edgeType: EdgeType.HANDOFF,
641
+ edgeType: EdgeType.TRANSFER,
642
642
  description: 'Self-handoff (should be allowed but unusual)',
643
643
  },
644
644
  ];
@@ -724,7 +724,7 @@ describe('Agent Handoffs Tests', () => {
724
724
  {
725
725
  from: 'agent_a',
726
726
  to: 'agent_b',
727
- edgeType: EdgeType.HANDOFF,
727
+ edgeType: EdgeType.TRANSFER,
728
728
  description: 'Transfer to agent B',
729
729
  },
730
730
  ];
@@ -759,12 +759,12 @@ describe('Agent Handoffs Tests', () => {
759
759
  {
760
760
  from: 'agent_a',
761
761
  to: 'agent_b',
762
- edgeType: EdgeType.HANDOFF,
762
+ edgeType: EdgeType.TRANSFER,
763
763
  },
764
764
  {
765
765
  from: 'agent_b',
766
766
  to: 'agent_c',
767
- edgeType: EdgeType.HANDOFF,
767
+ edgeType: EdgeType.TRANSFER,
768
768
  },
769
769
  ];
770
770
 
@@ -806,12 +806,12 @@ describe('Agent Handoffs Tests', () => {
806
806
  {
807
807
  from: 'agent_a',
808
808
  to: 'agent_c',
809
- edgeType: EdgeType.HANDOFF,
809
+ edgeType: EdgeType.TRANSFER,
810
810
  },
811
811
  {
812
812
  from: 'agent_b',
813
813
  to: 'agent_c',
814
- edgeType: EdgeType.HANDOFF,
814
+ edgeType: EdgeType.TRANSFER,
815
815
  },
816
816
  ];
817
817
 
@@ -853,7 +853,7 @@ describe('Agent Handoffs Tests', () => {
853
853
  {
854
854
  from: 'router',
855
855
  to: 'data_analyst',
856
- edgeType: EdgeType.HANDOFF,
856
+ edgeType: EdgeType.TRANSFER,
857
857
  description: 'Transfer to data analyst',
858
858
  prompt: 'Instructions for the analyst about what to analyze',
859
859
  promptKey: 'instructions',
@@ -939,7 +939,7 @@ describe('Agent Handoffs Tests', () => {
939
939
  {
940
940
  from: 'flight_assistant',
941
941
  to: 'hotel_assistant',
942
- edgeType: EdgeType.HANDOFF,
942
+ edgeType: EdgeType.TRANSFER,
943
943
  description: 'Transfer to hotel booking',
944
944
  },
945
945
  ];
@@ -970,7 +970,7 @@ describe('Agent Handoffs Tests', () => {
970
970
  {
971
971
  from: 'agent_with_underscores',
972
972
  to: 'AgentWithCamelCase',
973
- edgeType: EdgeType.HANDOFF,
973
+ edgeType: EdgeType.TRANSFER,
974
974
  },
975
975
  ];
976
976
 
@@ -1007,7 +1007,7 @@ describe('Agent Handoffs Tests', () => {
1007
1007
  {
1008
1008
  from: 'supervisor',
1009
1009
  to: 'data_analyst',
1010
- edgeType: EdgeType.HANDOFF,
1010
+ edgeType: EdgeType.TRANSFER,
1011
1011
  // No description provided - should auto-generate from agent name + description
1012
1012
  },
1013
1013
  ];
@@ -1042,7 +1042,7 @@ describe('Agent Handoffs Tests', () => {
1042
1042
  {
1043
1043
  from: 'supervisor',
1044
1044
  to: 'writer',
1045
- edgeType: EdgeType.HANDOFF,
1045
+ edgeType: EdgeType.TRANSFER,
1046
1046
  },
1047
1047
  ];
1048
1048
 
@@ -1075,7 +1075,7 @@ describe('Agent Handoffs Tests', () => {
1075
1075
  {
1076
1076
  from: 'supervisor',
1077
1077
  to: 'agent_b',
1078
- edgeType: EdgeType.HANDOFF,
1078
+ edgeType: EdgeType.TRANSFER,
1079
1079
  description: 'Custom handoff description that takes priority',
1080
1080
  },
1081
1081
  ];
@@ -1118,9 +1118,9 @@ describe('Agent Handoffs Tests', () => {
1118
1118
  ];
1119
1119
 
1120
1120
  const edges: t.GraphEdge[] = [
1121
- { from: 'router', to: 'sales', edgeType: EdgeType.HANDOFF },
1122
- { from: 'router', to: 'support', edgeType: EdgeType.HANDOFF },
1123
- { from: 'router', to: 'billing', edgeType: EdgeType.HANDOFF },
1121
+ { from: 'router', to: 'sales', edgeType: EdgeType.TRANSFER },
1122
+ { from: 'router', to: 'support', edgeType: EdgeType.TRANSFER },
1123
+ { from: 'router', to: 'billing', edgeType: EdgeType.TRANSFER },
1124
1124
  ];
1125
1125
 
1126
1126
  const run = await Run.create(createTestConfig(agents, edges));
@@ -1176,7 +1176,7 @@ describe('Agent Handoffs Tests', () => {
1176
1176
  ];
1177
1177
 
1178
1178
  const edges: t.GraphEdge[] = [
1179
- { from: 'agent_a', to: 'agent_b', edgeType: EdgeType.HANDOFF },
1179
+ { from: 'agent_a', to: 'agent_b', edgeType: EdgeType.TRANSFER },
1180
1180
  ];
1181
1181
 
1182
1182
  const run = await Run.create(createTestConfig(agents, edges));
@@ -1215,7 +1215,7 @@ describe('Agent Handoffs Tests', () => {
1215
1215
  {
1216
1216
  from: 'agent_a',
1217
1217
  to: 'agent_b',
1218
- edgeType: EdgeType.HANDOFF,
1218
+ edgeType: EdgeType.TRANSFER,
1219
1219
  description: 'Transfer to B',
1220
1220
  },
1221
1221
  ];
@@ -1255,7 +1255,7 @@ describe('Agent Handoffs Tests', () => {
1255
1255
  ];
1256
1256
 
1257
1257
  const edges: t.GraphEdge[] = [
1258
- { from: 'agent_a', to: 'agent_b', edgeType: EdgeType.HANDOFF },
1258
+ { from: 'agent_a', to: 'agent_b', edgeType: EdgeType.TRANSFER },
1259
1259
  ];
1260
1260
 
1261
1261
  const run = await Run.create(createTestConfig(agents, edges));
@@ -77,7 +77,7 @@ describe('Thinking-Enabled Agent Handoff Tests', () => {
77
77
  {
78
78
  from: 'supervisor',
79
79
  to: 'specialist',
80
- edgeType: EdgeType.HANDOFF,
80
+ edgeType: EdgeType.TRANSFER,
81
81
  description: 'Transfer to specialist for detailed analysis',
82
82
  },
83
83
  ];
@@ -166,7 +166,7 @@ describe('Thinking-Enabled Agent Handoff Tests', () => {
166
166
  {
167
167
  from: 'agent_a',
168
168
  to: 'agent_b',
169
- edgeType: EdgeType.HANDOFF,
169
+ edgeType: EdgeType.TRANSFER,
170
170
  },
171
171
  ];
172
172
 
@@ -223,7 +223,7 @@ describe('Thinking-Enabled Agent Handoff Tests', () => {
223
223
  {
224
224
  from: 'coordinator',
225
225
  to: 'analyst',
226
- edgeType: EdgeType.HANDOFF,
226
+ edgeType: EdgeType.TRANSFER,
227
227
  description: 'Transfer to analyst for deep analysis',
228
228
  },
229
229
  ];
@@ -297,7 +297,7 @@ describe('Thinking-Enabled Agent Handoff Tests', () => {
297
297
  {
298
298
  from: 'agent_a',
299
299
  to: 'agent_b',
300
- edgeType: EdgeType.HANDOFF,
300
+ edgeType: EdgeType.TRANSFER,
301
301
  },
302
302
  ];
303
303
 
@@ -360,7 +360,7 @@ describe('Thinking-Enabled Agent Handoff Tests', () => {
360
360
  {
361
361
  from: 'supervisor',
362
362
  to: 'bedrock_specialist',
363
- edgeType: EdgeType.HANDOFF,
363
+ edgeType: EdgeType.TRANSFER,
364
364
  description: 'Transfer to Bedrock specialist',
365
365
  },
366
366
  ];
@@ -450,12 +450,12 @@ describe('Thinking-Enabled Agent Handoff Tests', () => {
450
450
  {
451
451
  from: 'router',
452
452
  to: 'processor',
453
- edgeType: EdgeType.HANDOFF,
453
+ edgeType: EdgeType.TRANSFER,
454
454
  },
455
455
  {
456
456
  from: 'processor',
457
457
  to: 'reviewer',
458
- edgeType: EdgeType.HANDOFF,
458
+ edgeType: EdgeType.TRANSFER,
459
459
  },
460
460
  ];
461
461
 
@@ -538,7 +538,7 @@ describe('Thinking-Enabled Agent Handoff Tests', () => {
538
538
  {
539
539
  from: 'agent_a',
540
540
  to: 'agent_b',
541
- edgeType: EdgeType.HANDOFF,
541
+ edgeType: EdgeType.TRANSFER,
542
542
  },
543
543
  ];
544
544
 
@@ -603,7 +603,7 @@ describe('Thinking-Enabled Agent Handoff Tests', () => {
603
603
  {
604
604
  from: 'agent_a',
605
605
  to: 'agent_b',
606
- edgeType: EdgeType.HANDOFF,
606
+ edgeType: EdgeType.TRANSFER,
607
607
  },
608
608
  ];
609
609
 
@@ -0,0 +1,173 @@
1
+ import axios from 'axios';
2
+ import { createSearchAPI } from './search';
3
+
4
+ jest.mock('axios');
5
+ const mockedAxios = axios as jest.Mocked<typeof axios>;
6
+
7
+ describe('createSearchAPI', () => {
8
+ beforeEach(() => {
9
+ jest.clearAllMocks();
10
+ });
11
+
12
+ const mockSerperResponse = {
13
+ data: {
14
+ organic: [
15
+ { position: 1, title: 'Test', link: 'https://example.com', snippet: 'test' },
16
+ ],
17
+ topStories: [],
18
+ images: [],
19
+ videos: [],
20
+ news: [],
21
+ peopleAlsoAsk: [],
22
+ relatedSearches: [],
23
+ },
24
+ };
25
+
26
+ describe('domainBlocklist', () => {
27
+ it('appends -site: operators to query for blocked domains', async () => {
28
+ mockedAxios.post.mockResolvedValueOnce(mockSerperResponse);
29
+
30
+ const api = createSearchAPI({
31
+ searchProvider: 'serper',
32
+ serperApiKey: 'test-key',
33
+ domainBlocklist: ['reddit.com', 'twitter.com'],
34
+ });
35
+
36
+ await api.getSources({ query: 'test query' });
37
+
38
+ expect(mockedAxios.post).toHaveBeenCalledTimes(1);
39
+ const payload = mockedAxios.post.mock.calls[0][1] as { q: string };
40
+ expect(payload.q).toBe('test query -site:reddit.com -site:twitter.com');
41
+ });
42
+
43
+ it('does not modify query when domainBlocklist is empty', async () => {
44
+ mockedAxios.post.mockResolvedValueOnce(mockSerperResponse);
45
+
46
+ const api = createSearchAPI({
47
+ searchProvider: 'serper',
48
+ serperApiKey: 'test-key',
49
+ domainBlocklist: [],
50
+ });
51
+
52
+ await api.getSources({ query: 'test query' });
53
+
54
+ const payload = mockedAxios.post.mock.calls[0][1] as { q: string };
55
+ expect(payload.q).toBe('test query');
56
+ });
57
+ });
58
+
59
+ describe('countryBlocklist', () => {
60
+ it('appends -site:.XX operators to query for blocked country TLDs', async () => {
61
+ mockedAxios.post.mockResolvedValueOnce(mockSerperResponse);
62
+
63
+ const api = createSearchAPI({
64
+ searchProvider: 'serper',
65
+ serperApiKey: 'test-key',
66
+ countryBlocklist: ['ru', 'ir'],
67
+ });
68
+
69
+ await api.getSources({ query: 'test query' });
70
+
71
+ expect(mockedAxios.post).toHaveBeenCalledTimes(1);
72
+ const payload = mockedAxios.post.mock.calls[0][1] as { q: string };
73
+ expect(payload.q).toBe('test query -site:.ru -site:.ir');
74
+ });
75
+
76
+ it('handles country codes with leading dots', async () => {
77
+ mockedAxios.post.mockResolvedValueOnce(mockSerperResponse);
78
+
79
+ const api = createSearchAPI({
80
+ searchProvider: 'serper',
81
+ serperApiKey: 'test-key',
82
+ countryBlocklist: ['.cn', '.ru'],
83
+ });
84
+
85
+ await api.getSources({ query: 'test query' });
86
+
87
+ const payload = mockedAxios.post.mock.calls[0][1] as { q: string };
88
+ expect(payload.q).toBe('test query -site:.cn -site:.ru');
89
+ });
90
+
91
+ it('lowercases country codes', async () => {
92
+ mockedAxios.post.mockResolvedValueOnce(mockSerperResponse);
93
+
94
+ const api = createSearchAPI({
95
+ searchProvider: 'serper',
96
+ serperApiKey: 'test-key',
97
+ countryBlocklist: ['RU', 'IR'],
98
+ });
99
+
100
+ await api.getSources({ query: 'test query' });
101
+
102
+ const payload = mockedAxios.post.mock.calls[0][1] as { q: string };
103
+ expect(payload.q).toBe('test query -site:.ru -site:.ir');
104
+ });
105
+
106
+ it('does not modify query when countryBlocklist is empty', async () => {
107
+ mockedAxios.post.mockResolvedValueOnce(mockSerperResponse);
108
+
109
+ const api = createSearchAPI({
110
+ searchProvider: 'serper',
111
+ serperApiKey: 'test-key',
112
+ countryBlocklist: [],
113
+ });
114
+
115
+ await api.getSources({ query: 'test query' });
116
+
117
+ const payload = mockedAxios.post.mock.calls[0][1] as { q: string };
118
+ expect(payload.q).toBe('test query');
119
+ });
120
+
121
+ it('does not modify query when countryBlocklist is undefined', async () => {
122
+ mockedAxios.post.mockResolvedValueOnce(mockSerperResponse);
123
+
124
+ const api = createSearchAPI({
125
+ searchProvider: 'serper',
126
+ serperApiKey: 'test-key',
127
+ });
128
+
129
+ await api.getSources({ query: 'test query' });
130
+
131
+ const payload = mockedAxios.post.mock.calls[0][1] as { q: string };
132
+ expect(payload.q).toBe('test query');
133
+ });
134
+ });
135
+
136
+ describe('domainBlocklist + countryBlocklist combined', () => {
137
+ it('appends both domain and country exclusions to query', async () => {
138
+ mockedAxios.post.mockResolvedValueOnce(mockSerperResponse);
139
+
140
+ const api = createSearchAPI({
141
+ searchProvider: 'serper',
142
+ serperApiKey: 'test-key',
143
+ domainBlocklist: ['reddit.com'],
144
+ countryBlocklist: ['ru', 'ir'],
145
+ });
146
+
147
+ await api.getSources({ query: 'test query' });
148
+
149
+ const payload = mockedAxios.post.mock.calls[0][1] as { q: string };
150
+ expect(payload.q).toBe('test query -site:reddit.com -site:.ru -site:.ir');
151
+ });
152
+ });
153
+
154
+ describe('searxng provider', () => {
155
+ it('does not apply countryBlocklist to searxng (only serper)', async () => {
156
+ mockedAxios.get.mockResolvedValueOnce({
157
+ data: { results: [], suggestions: [] },
158
+ });
159
+
160
+ const api = createSearchAPI({
161
+ searchProvider: 'searxng',
162
+ searxngInstanceUrl: 'http://localhost:8080',
163
+ countryBlocklist: ['ru', 'ir'],
164
+ });
165
+
166
+ await api.getSources({ query: 'test query' });
167
+
168
+ expect(mockedAxios.get).toHaveBeenCalledTimes(1);
169
+ const params = mockedAxios.get.mock.calls[0][1]?.params as { q: string };
170
+ expect(params.q).toBe('test query');
171
+ });
172
+ });
173
+ });
@@ -340,14 +340,18 @@ export type GraphEdge = {
340
340
  description?: string;
341
341
  /** Can return boolean or specific destination(s) */
342
342
  condition?: (state: BaseGraphState) => boolean | string | string[];
343
- /** EdgeType.HANDOFF creates tools for dynamic routing, EdgeType.DIRECT creates direct edges with parallel execution */
343
+ /**
344
+ * EdgeType.HANDOFF — true agent handoff, parent calls child inline and gets result back.
345
+ * EdgeType.TRANSFER — one-way transfer, parent exits and child takes over.
346
+ * EdgeType.SEQUENCE — fixed graph edges for sequential/parallel transitions.
347
+ */
344
348
  edgeType?: import('@/common').EdgeType;
345
349
  /**
346
- * For direct edges: Optional prompt to add when transitioning through this edge.
350
+ * For sequence edges: Optional prompt to add when transitioning through this edge.
347
351
  * String prompts can include variables like {results} which will be replaced with
348
352
  * messages from startIndex onwards. When {results} is used, excludeResults defaults to true.
349
353
  *
350
- * For handoff edges: Description for the input parameter that the handoff tool accepts,
354
+ * For transfer edges: Description for the input parameter that the transfer tool accepts,
351
355
  * allowing the supervisor to pass specific instructions/context to the transferred agent.
352
356
  */
353
357
  prompt?:
@@ -362,11 +366,19 @@ export type GraphEdge = {
362
366
  */
363
367
  excludeResults?: boolean;
364
368
  /**
365
- * For handoff edges: Customizes the parameter name for the handoff input.
369
+ * For transfer edges: Customizes the parameter name for the transfer input.
366
370
  * Defaults to "instructions" if not specified.
367
- * Only applies when prompt is provided for handoff edges.
371
+ * Only applies when prompt is provided for transfer edges.
372
+ *
373
+ * For handoff edges: Customizes the parameter name for the handoff instruction input.
368
374
  */
369
375
  promptKey?: string;
376
+ /**
377
+ * For handoff edges: Maximum characters for the result returned to the parent.
378
+ * Uses head/tail truncation (60/40 split) to preserve key findings and conclusions.
379
+ * Defaults to DEFAULT_HANDOFF_MAX_RESULT_CHARS (32768 chars, ~8192 tokens).
380
+ */
381
+ maxResultChars?: number;
370
382
  };
371
383
 
372
384
  export type MultiAgentGraphInput = StandardGraphInput & {