illuma-agents 1.0.26 → 1.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/graphs/Graph.cjs +28 -2
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/graphs/MultiAgentGraph.cjs +108 -0
- package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
- package/dist/cjs/messages/format.cjs.map +1 -1
- package/dist/cjs/stream.cjs +27 -0
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/tools/BrowserTools.cjs +125 -113
- package/dist/cjs/tools/BrowserTools.cjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +28 -2
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/graphs/MultiAgentGraph.mjs +108 -0
- package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
- package/dist/esm/messages/format.mjs.map +1 -1
- package/dist/esm/stream.mjs +27 -0
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/tools/BrowserTools.mjs +125 -113
- package/dist/esm/tools/BrowserTools.mjs.map +1 -1
- package/dist/types/graphs/Graph.d.ts +14 -0
- package/dist/types/graphs/MultiAgentGraph.d.ts +41 -0
- package/dist/types/messages/format.d.ts +1 -1
- package/dist/types/tools/BrowserTools.d.ts +45 -5
- package/dist/types/types/stream.d.ts +13 -0
- package/package.json +4 -2
- package/src/graphs/Graph.ts +30 -2
- package/src/graphs/MultiAgentGraph.ts +119 -0
- package/src/messages/format.ts +2 -2
- package/src/scripts/multi-agent-chain.ts +59 -6
- package/src/scripts/multi-agent-parallel-start.ts +265 -0
- package/src/scripts/multi-agent-parallel.ts +61 -10
- package/src/scripts/multi-agent-sequence.ts +6 -1
- package/src/scripts/parallel-asymmetric-tools-test.ts +274 -0
- package/src/scripts/parallel-full-metadata-test.ts +240 -0
- package/src/scripts/parallel-tools-test.ts +340 -0
- package/src/scripts/sequential-full-metadata-test.ts +197 -0
- package/src/scripts/single-agent-metadata-test.ts +198 -0
- package/src/scripts/test-thinking-handoff.ts +8 -0
- package/src/scripts/tools.ts +31 -11
- package/src/stream.ts +32 -0
- package/src/tools/BrowserTools.ts +356 -310
- package/src/tools/__tests__/BrowserTools.test.ts +263 -257
- package/src/types/stream.ts +15 -0
|
@@ -1,257 +1,263 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, jest } from '@jest/globals';
|
|
2
|
-
import {
|
|
3
|
-
createBrowserTools,
|
|
4
|
-
hasBrowserCapability,
|
|
5
|
-
EBrowserTools,
|
|
6
|
-
type BrowserToolResponse,
|
|
7
|
-
} from '../BrowserTools';
|
|
8
|
-
|
|
9
|
-
describe('BrowserTools', () => {
|
|
10
|
-
describe('EBrowserTools enum', () => {
|
|
11
|
-
it('should have all expected browser tool names', () => {
|
|
12
|
-
expect(EBrowserTools.CLICK).toBe('browser_click');
|
|
13
|
-
expect(EBrowserTools.TYPE).toBe('browser_type');
|
|
14
|
-
expect(EBrowserTools.NAVIGATE).toBe('browser_navigate');
|
|
15
|
-
expect(EBrowserTools.SCROLL).toBe('browser_scroll');
|
|
16
|
-
expect(EBrowserTools.EXTRACT).toBe('browser_extract');
|
|
17
|
-
expect(EBrowserTools.HOVER).toBe('browser_hover');
|
|
18
|
-
expect(EBrowserTools.WAIT).toBe('browser_wait');
|
|
19
|
-
expect(EBrowserTools.BACK).toBe('browser_back');
|
|
20
|
-
expect(EBrowserTools.SCREENSHOT).toBe('browser_screenshot');
|
|
21
|
-
expect(EBrowserTools.GET_PAGE_STATE).toBe('browser_get_page_state');
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it('should have exactly 10 browser tools', () => {
|
|
25
|
-
expect(Object.keys(EBrowserTools).length).toBe(10);
|
|
26
|
-
});
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
describe('hasBrowserCapability', () => {
|
|
30
|
-
it('should return false when no request is provided', () => {
|
|
31
|
-
expect(hasBrowserCapability()).toBe(false);
|
|
32
|
-
expect(hasBrowserCapability(undefined)).toBe(false);
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it('should return false when request has no headers', () => {
|
|
36
|
-
expect(hasBrowserCapability({})).toBe(false);
|
|
37
|
-
expect(hasBrowserCapability({ headers: undefined })).toBe(false);
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it('should return true when X-Ranger-Browser-Extension header is true', () => {
|
|
41
|
-
const req = {
|
|
42
|
-
headers: {
|
|
43
|
-
'x-ranger-browser-extension': 'true',
|
|
44
|
-
},
|
|
45
|
-
};
|
|
46
|
-
expect(hasBrowserCapability(req)).toBe(true);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('should return true when X-Ranger-Browser-Capable header is true', () => {
|
|
50
|
-
const req = {
|
|
51
|
-
headers: {
|
|
52
|
-
'x-ranger-browser-capable': 'true',
|
|
53
|
-
},
|
|
54
|
-
};
|
|
55
|
-
expect(hasBrowserCapability(req)).toBe(true);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it('should return false when browser headers are not true', () => {
|
|
59
|
-
const req = {
|
|
60
|
-
headers: {
|
|
61
|
-
'x-ranger-browser-extension': 'false',
|
|
62
|
-
'x-ranger-browser-capable': 'false',
|
|
63
|
-
},
|
|
64
|
-
};
|
|
65
|
-
expect(hasBrowserCapability(req)).toBe(false);
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it('should return false when browser headers are missing', () => {
|
|
69
|
-
const req = {
|
|
70
|
-
headers: {
|
|
71
|
-
'content-type': 'application/json',
|
|
72
|
-
},
|
|
73
|
-
};
|
|
74
|
-
expect(hasBrowserCapability(req)).toBe(false);
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
describe('createBrowserTools', () => {
|
|
79
|
-
let tools: ReturnType<typeof createBrowserTools>;
|
|
80
|
-
|
|
81
|
-
beforeEach(() => {
|
|
82
|
-
tools = createBrowserTools();
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
it('should create exactly 10 browser tools', () => {
|
|
86
|
-
expect(tools.length).toBe(10);
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
it('should create tools with correct names', () => {
|
|
90
|
-
const toolNames = tools.map(t => t.name);
|
|
91
|
-
expect(toolNames).toContain('browser_click');
|
|
92
|
-
expect(toolNames).toContain('browser_type');
|
|
93
|
-
expect(toolNames).toContain('browser_navigate');
|
|
94
|
-
expect(toolNames).toContain('browser_scroll');
|
|
95
|
-
expect(toolNames).toContain('browser_extract');
|
|
96
|
-
expect(toolNames).toContain('browser_hover');
|
|
97
|
-
expect(toolNames).toContain('browser_wait');
|
|
98
|
-
expect(toolNames).toContain('browser_back');
|
|
99
|
-
expect(toolNames).toContain('browser_screenshot');
|
|
100
|
-
expect(toolNames).toContain('browser_get_page_state');
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
it('should have descriptions for all tools', () => {
|
|
104
|
-
for (const tool of tools) {
|
|
105
|
-
expect(tool.description).toBeDefined();
|
|
106
|
-
expect(tool.description.length).toBeGreaterThan(0);
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
describe('browser_click tool', () => {
|
|
111
|
-
it('should return requiresBrowserExecution marker', async () => {
|
|
112
|
-
const clickTool = tools.find(t => t.name === 'browser_click');
|
|
113
|
-
expect(clickTool).toBeDefined();
|
|
114
|
-
|
|
115
|
-
const result = await clickTool!.invoke({ index: 5 });
|
|
116
|
-
const parsed: BrowserToolResponse = JSON.parse(result);
|
|
117
|
-
|
|
118
|
-
expect(parsed.requiresBrowserExecution).toBe(true);
|
|
119
|
-
expect(parsed.action).toBe('click');
|
|
120
|
-
expect(parsed.args).toEqual({ index: 5 });
|
|
121
|
-
});
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
describe('browser_type tool', () => {
|
|
125
|
-
it('should return requiresBrowserExecution marker with all args', async () => {
|
|
126
|
-
const typeTool = tools.find(t => t.name === 'browser_type');
|
|
127
|
-
expect(typeTool).toBeDefined();
|
|
128
|
-
|
|
129
|
-
const result = await typeTool!.invoke({
|
|
130
|
-
index: 3,
|
|
131
|
-
text: 'Hello World',
|
|
132
|
-
pressEnter: true
|
|
133
|
-
});
|
|
134
|
-
const parsed: BrowserToolResponse = JSON.parse(result);
|
|
135
|
-
|
|
136
|
-
expect(parsed.requiresBrowserExecution).toBe(true);
|
|
137
|
-
expect(parsed.action).toBe('type');
|
|
138
|
-
expect(parsed.args.index).toBe(3);
|
|
139
|
-
expect(parsed.args.text).toBe('Hello World');
|
|
140
|
-
expect(parsed.args.pressEnter).toBe(true);
|
|
141
|
-
});
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
describe('browser_navigate tool', () => {
|
|
145
|
-
it('should return requiresBrowserExecution marker with URL', async () => {
|
|
146
|
-
const navigateTool = tools.find(t => t.name === 'browser_navigate');
|
|
147
|
-
expect(navigateTool).toBeDefined();
|
|
148
|
-
|
|
149
|
-
const result = await navigateTool!.invoke({
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
expect(parsed.
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
expect(parsed.
|
|
172
|
-
expect(parsed.
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
expect(parsed.
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
expect(parsed.
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
expect(
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
expect(
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
1
|
+
import { describe, it, expect, beforeEach, jest as _jest } from '@jest/globals';
|
|
2
|
+
import {
|
|
3
|
+
createBrowserTools,
|
|
4
|
+
hasBrowserCapability,
|
|
5
|
+
EBrowserTools,
|
|
6
|
+
type BrowserToolResponse,
|
|
7
|
+
} from '../BrowserTools';
|
|
8
|
+
|
|
9
|
+
describe('BrowserTools', () => {
|
|
10
|
+
describe('EBrowserTools enum', () => {
|
|
11
|
+
it('should have all expected browser tool names', () => {
|
|
12
|
+
expect(EBrowserTools.CLICK).toBe('browser_click');
|
|
13
|
+
expect(EBrowserTools.TYPE).toBe('browser_type');
|
|
14
|
+
expect(EBrowserTools.NAVIGATE).toBe('browser_navigate');
|
|
15
|
+
expect(EBrowserTools.SCROLL).toBe('browser_scroll');
|
|
16
|
+
expect(EBrowserTools.EXTRACT).toBe('browser_extract');
|
|
17
|
+
expect(EBrowserTools.HOVER).toBe('browser_hover');
|
|
18
|
+
expect(EBrowserTools.WAIT).toBe('browser_wait');
|
|
19
|
+
expect(EBrowserTools.BACK).toBe('browser_back');
|
|
20
|
+
expect(EBrowserTools.SCREENSHOT).toBe('browser_screenshot');
|
|
21
|
+
expect(EBrowserTools.GET_PAGE_STATE).toBe('browser_get_page_state');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('should have exactly 10 browser tools', () => {
|
|
25
|
+
expect(Object.keys(EBrowserTools).length).toBe(10);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
describe('hasBrowserCapability', () => {
|
|
30
|
+
it('should return false when no request is provided', () => {
|
|
31
|
+
expect(hasBrowserCapability()).toBe(false);
|
|
32
|
+
expect(hasBrowserCapability(undefined)).toBe(false);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should return false when request has no headers', () => {
|
|
36
|
+
expect(hasBrowserCapability({})).toBe(false);
|
|
37
|
+
expect(hasBrowserCapability({ headers: undefined })).toBe(false);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should return true when X-Ranger-Browser-Extension header is true', () => {
|
|
41
|
+
const req = {
|
|
42
|
+
headers: {
|
|
43
|
+
'x-ranger-browser-extension': 'true',
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
expect(hasBrowserCapability(req)).toBe(true);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('should return true when X-Ranger-Browser-Capable header is true', () => {
|
|
50
|
+
const req = {
|
|
51
|
+
headers: {
|
|
52
|
+
'x-ranger-browser-capable': 'true',
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
expect(hasBrowserCapability(req)).toBe(true);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('should return false when browser headers are not true', () => {
|
|
59
|
+
const req = {
|
|
60
|
+
headers: {
|
|
61
|
+
'x-ranger-browser-extension': 'false',
|
|
62
|
+
'x-ranger-browser-capable': 'false',
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
expect(hasBrowserCapability(req)).toBe(false);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('should return false when browser headers are missing', () => {
|
|
69
|
+
const req = {
|
|
70
|
+
headers: {
|
|
71
|
+
'content-type': 'application/json',
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
expect(hasBrowserCapability(req)).toBe(false);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
describe('createBrowserTools', () => {
|
|
79
|
+
let tools: ReturnType<typeof createBrowserTools>;
|
|
80
|
+
|
|
81
|
+
beforeEach(() => {
|
|
82
|
+
tools = createBrowserTools();
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('should create exactly 10 browser tools', () => {
|
|
86
|
+
expect(tools.length).toBe(10);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('should create tools with correct names', () => {
|
|
90
|
+
const toolNames = tools.map((t) => t.name);
|
|
91
|
+
expect(toolNames).toContain('browser_click');
|
|
92
|
+
expect(toolNames).toContain('browser_type');
|
|
93
|
+
expect(toolNames).toContain('browser_navigate');
|
|
94
|
+
expect(toolNames).toContain('browser_scroll');
|
|
95
|
+
expect(toolNames).toContain('browser_extract');
|
|
96
|
+
expect(toolNames).toContain('browser_hover');
|
|
97
|
+
expect(toolNames).toContain('browser_wait');
|
|
98
|
+
expect(toolNames).toContain('browser_back');
|
|
99
|
+
expect(toolNames).toContain('browser_screenshot');
|
|
100
|
+
expect(toolNames).toContain('browser_get_page_state');
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('should have descriptions for all tools', () => {
|
|
104
|
+
for (const tool of tools) {
|
|
105
|
+
expect(tool.description).toBeDefined();
|
|
106
|
+
expect(tool.description.length).toBeGreaterThan(0);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
describe('browser_click tool', () => {
|
|
111
|
+
it('should return requiresBrowserExecution marker', async () => {
|
|
112
|
+
const clickTool = tools.find((t) => t.name === 'browser_click');
|
|
113
|
+
expect(clickTool).toBeDefined();
|
|
114
|
+
|
|
115
|
+
const result = await clickTool!.invoke({ index: 5 });
|
|
116
|
+
const parsed: BrowserToolResponse = JSON.parse(result);
|
|
117
|
+
|
|
118
|
+
expect(parsed.requiresBrowserExecution).toBe(true);
|
|
119
|
+
expect(parsed.action).toBe('click');
|
|
120
|
+
expect(parsed.args).toEqual({ index: 5 });
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
describe('browser_type tool', () => {
|
|
125
|
+
it('should return requiresBrowserExecution marker with all args', async () => {
|
|
126
|
+
const typeTool = tools.find((t) => t.name === 'browser_type');
|
|
127
|
+
expect(typeTool).toBeDefined();
|
|
128
|
+
|
|
129
|
+
const result = await typeTool!.invoke({
|
|
130
|
+
index: 3,
|
|
131
|
+
text: 'Hello World',
|
|
132
|
+
pressEnter: true,
|
|
133
|
+
});
|
|
134
|
+
const parsed: BrowserToolResponse = JSON.parse(result);
|
|
135
|
+
|
|
136
|
+
expect(parsed.requiresBrowserExecution).toBe(true);
|
|
137
|
+
expect(parsed.action).toBe('type');
|
|
138
|
+
expect(parsed.args.index).toBe(3);
|
|
139
|
+
expect(parsed.args.text).toBe('Hello World');
|
|
140
|
+
expect(parsed.args.pressEnter).toBe(true);
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
describe('browser_navigate tool', () => {
|
|
145
|
+
it('should return requiresBrowserExecution marker with URL', async () => {
|
|
146
|
+
const navigateTool = tools.find((t) => t.name === 'browser_navigate');
|
|
147
|
+
expect(navigateTool).toBeDefined();
|
|
148
|
+
|
|
149
|
+
const result = await navigateTool!.invoke({
|
|
150
|
+
url: 'https://example.com',
|
|
151
|
+
});
|
|
152
|
+
const parsed: BrowserToolResponse = JSON.parse(result);
|
|
153
|
+
|
|
154
|
+
expect(parsed.requiresBrowserExecution).toBe(true);
|
|
155
|
+
expect(parsed.action).toBe('navigate');
|
|
156
|
+
expect(parsed.args.url).toBe('https://example.com');
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
describe('browser_scroll tool', () => {
|
|
161
|
+
it('should return requiresBrowserExecution marker with direction', async () => {
|
|
162
|
+
const scrollTool = tools.find((t) => t.name === 'browser_scroll');
|
|
163
|
+
expect(scrollTool).toBeDefined();
|
|
164
|
+
|
|
165
|
+
const result = await scrollTool!.invoke({
|
|
166
|
+
direction: 'down',
|
|
167
|
+
amount: 500,
|
|
168
|
+
});
|
|
169
|
+
const parsed: BrowserToolResponse = JSON.parse(result);
|
|
170
|
+
|
|
171
|
+
expect(parsed.requiresBrowserExecution).toBe(true);
|
|
172
|
+
expect(parsed.action).toBe('scroll');
|
|
173
|
+
expect(parsed.args.direction).toBe('down');
|
|
174
|
+
expect(parsed.args.amount).toBe(500);
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
describe('browser_hover tool', () => {
|
|
179
|
+
it('should return requiresBrowserExecution marker with index', async () => {
|
|
180
|
+
const hoverTool = tools.find((t) => t.name === 'browser_hover');
|
|
181
|
+
expect(hoverTool).toBeDefined();
|
|
182
|
+
|
|
183
|
+
const result = await hoverTool!.invoke({ index: 2 });
|
|
184
|
+
const parsed: BrowserToolResponse = JSON.parse(result);
|
|
185
|
+
|
|
186
|
+
expect(parsed.requiresBrowserExecution).toBe(true);
|
|
187
|
+
expect(parsed.action).toBe('hover');
|
|
188
|
+
expect(parsed.args.index).toBe(2);
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
describe('browser_wait tool', () => {
|
|
193
|
+
it('should return requiresBrowserExecution marker with duration', async () => {
|
|
194
|
+
const waitTool = tools.find((t) => t.name === 'browser_wait');
|
|
195
|
+
expect(waitTool).toBeDefined();
|
|
196
|
+
|
|
197
|
+
const result = await waitTool!.invoke({ duration: 2000 });
|
|
198
|
+
const parsed: BrowserToolResponse = JSON.parse(result);
|
|
199
|
+
|
|
200
|
+
expect(parsed.requiresBrowserExecution).toBe(true);
|
|
201
|
+
expect(parsed.action).toBe('wait');
|
|
202
|
+
expect(parsed.args.duration).toBe(2000);
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
describe('browser_back tool', () => {
|
|
207
|
+
it('should return requiresBrowserExecution marker', async () => {
|
|
208
|
+
const backTool = tools.find((t) => t.name === 'browser_back');
|
|
209
|
+
expect(backTool).toBeDefined();
|
|
210
|
+
|
|
211
|
+
const result = await backTool!.invoke({});
|
|
212
|
+
const parsed: BrowserToolResponse = JSON.parse(result);
|
|
213
|
+
|
|
214
|
+
expect(parsed.requiresBrowserExecution).toBe(true);
|
|
215
|
+
expect(parsed.action).toBe('back');
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
describe('browser_screenshot tool', () => {
|
|
220
|
+
it('should return requiresBrowserExecution marker', async () => {
|
|
221
|
+
const screenshotTool = tools.find(
|
|
222
|
+
(t) => t.name === 'browser_screenshot'
|
|
223
|
+
);
|
|
224
|
+
expect(screenshotTool).toBeDefined();
|
|
225
|
+
|
|
226
|
+
const result = await screenshotTool!.invoke({});
|
|
227
|
+
const parsed: BrowserToolResponse = JSON.parse(result);
|
|
228
|
+
|
|
229
|
+
expect(parsed.requiresBrowserExecution).toBe(true);
|
|
230
|
+
expect(parsed.action).toBe('screenshot');
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
describe('browser_get_page_state tool', () => {
|
|
235
|
+
it('should return requiresBrowserExecution marker', async () => {
|
|
236
|
+
const pageStateTool = tools.find(
|
|
237
|
+
(t) => t.name === 'browser_get_page_state'
|
|
238
|
+
);
|
|
239
|
+
expect(pageStateTool).toBeDefined();
|
|
240
|
+
|
|
241
|
+
const result = await pageStateTool!.invoke({});
|
|
242
|
+
const parsed: BrowserToolResponse = JSON.parse(result);
|
|
243
|
+
|
|
244
|
+
expect(parsed.requiresBrowserExecution).toBe(true);
|
|
245
|
+
expect(parsed.action).toBe('get_page_state');
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
describe('browser_extract tool', () => {
|
|
250
|
+
it('should return requiresBrowserExecution marker', async () => {
|
|
251
|
+
const extractTool = tools.find((t) => t.name === 'browser_extract');
|
|
252
|
+
expect(extractTool).toBeDefined();
|
|
253
|
+
|
|
254
|
+
const result = await extractTool!.invoke({ query: 'main content' });
|
|
255
|
+
const parsed: BrowserToolResponse = JSON.parse(result);
|
|
256
|
+
|
|
257
|
+
expect(parsed.requiresBrowserExecution).toBe(true);
|
|
258
|
+
expect(parsed.action).toBe('extract');
|
|
259
|
+
expect(parsed.args.query).toBe('main content');
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
});
|
|
263
|
+
});
|
package/src/types/stream.ts
CHANGED
|
@@ -66,6 +66,17 @@ export type RunStep = {
|
|
|
66
66
|
id: string; // #new
|
|
67
67
|
runId?: string; // #new
|
|
68
68
|
agentId?: string; // #new - tracks which agent this step belongs to
|
|
69
|
+
/**
|
|
70
|
+
* Group ID - incrementing number (1, 2, 3...) reflecting execution order.
|
|
71
|
+
* Agents with the same groupId run in parallel and should be rendered together.
|
|
72
|
+
* undefined means the agent runs sequentially (not part of any parallel group).
|
|
73
|
+
*
|
|
74
|
+
* Example for: researcher -> [analyst1, analyst2, analyst3] -> summarizer
|
|
75
|
+
* - researcher: undefined (sequential)
|
|
76
|
+
* - analyst1, analyst2, analyst3: 1 (first parallel group)
|
|
77
|
+
* - summarizer: undefined (sequential)
|
|
78
|
+
*/
|
|
79
|
+
groupId?: number; // #new
|
|
69
80
|
index: number; // #new
|
|
70
81
|
stepIndex?: number; // #new
|
|
71
82
|
stepDetails: StepDetails;
|
|
@@ -332,6 +343,10 @@ export type MessageContentComplex = (
|
|
|
332
343
|
})
|
|
333
344
|
) & {
|
|
334
345
|
tool_call_ids?: string[];
|
|
346
|
+
// Optional agentId for parallel execution attribution
|
|
347
|
+
agentId?: string;
|
|
348
|
+
// Optional groupId for parallel group attribution
|
|
349
|
+
groupId?: number;
|
|
335
350
|
};
|
|
336
351
|
|
|
337
352
|
export interface TMessage {
|