ultra-dex 3.2.0 → 3.3.0
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/bin/ultra-dex.js +14 -2
- package/lib/commands/cloud.js +780 -0
- package/lib/commands/exec.js +434 -0
- package/lib/commands/github.js +475 -0
- package/lib/commands/search.js +477 -0
- package/lib/mcp/client.js +502 -0
- package/lib/providers/agent-sdk.js +630 -0
- package/lib/providers/anthropic-agents.js +580 -0
- package/lib/utils/browser.js +373 -0
- package/package.json +10 -4
|
@@ -0,0 +1,630 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anthropic Agent SDK Integration
|
|
3
|
+
* Enables true autonomous agents with tool use, memory, and reasoning
|
|
4
|
+
* This transforms Ultra-Dex swarm from prompt-based to SDK-based agents
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import chalk from 'chalk';
|
|
8
|
+
import fs from 'fs/promises';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// AGENT SDK CONFIGURATION
|
|
13
|
+
// ============================================================================
|
|
14
|
+
|
|
15
|
+
const AGENT_SDK_CONFIG = {
|
|
16
|
+
// Default model for agents
|
|
17
|
+
defaultModel: 'claude-sonnet-4-20250514',
|
|
18
|
+
|
|
19
|
+
// Available models
|
|
20
|
+
models: {
|
|
21
|
+
fast: 'claude-sonnet-4-20250514',
|
|
22
|
+
balanced: 'claude-sonnet-4-20250514',
|
|
23
|
+
powerful: 'claude-opus-4-20250514',
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
// Max tokens for different agent types
|
|
27
|
+
maxTokens: {
|
|
28
|
+
planner: 8000,
|
|
29
|
+
coder: 16000,
|
|
30
|
+
reviewer: 4000,
|
|
31
|
+
default: 8000,
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
// Tool definitions for agents
|
|
35
|
+
tools: {
|
|
36
|
+
read_file: {
|
|
37
|
+
name: 'read_file',
|
|
38
|
+
description: 'Read the contents of a file',
|
|
39
|
+
input_schema: {
|
|
40
|
+
type: 'object',
|
|
41
|
+
properties: {
|
|
42
|
+
path: { type: 'string', description: 'Path to the file' },
|
|
43
|
+
},
|
|
44
|
+
required: ['path'],
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
write_file: {
|
|
48
|
+
name: 'write_file',
|
|
49
|
+
description: 'Write content to a file',
|
|
50
|
+
input_schema: {
|
|
51
|
+
type: 'object',
|
|
52
|
+
properties: {
|
|
53
|
+
path: { type: 'string', description: 'Path to the file' },
|
|
54
|
+
content: { type: 'string', description: 'Content to write' },
|
|
55
|
+
},
|
|
56
|
+
required: ['path', 'content'],
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
search_code: {
|
|
60
|
+
name: 'search_code',
|
|
61
|
+
description: 'Search for code patterns in the codebase',
|
|
62
|
+
input_schema: {
|
|
63
|
+
type: 'object',
|
|
64
|
+
properties: {
|
|
65
|
+
query: { type: 'string', description: 'Search query or regex pattern' },
|
|
66
|
+
file_pattern: { type: 'string', description: 'Glob pattern for files to search' },
|
|
67
|
+
},
|
|
68
|
+
required: ['query'],
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
run_command: {
|
|
72
|
+
name: 'run_command',
|
|
73
|
+
description: 'Run a shell command (sandboxed)',
|
|
74
|
+
input_schema: {
|
|
75
|
+
type: 'object',
|
|
76
|
+
properties: {
|
|
77
|
+
command: { type: 'string', description: 'Command to execute' },
|
|
78
|
+
timeout: { type: 'number', description: 'Timeout in milliseconds' },
|
|
79
|
+
},
|
|
80
|
+
required: ['command'],
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
delegate_task: {
|
|
84
|
+
name: 'delegate_task',
|
|
85
|
+
description: 'Delegate a task to another specialized agent',
|
|
86
|
+
input_schema: {
|
|
87
|
+
type: 'object',
|
|
88
|
+
properties: {
|
|
89
|
+
agent: { type: 'string', description: 'Agent name (backend, frontend, etc.)' },
|
|
90
|
+
task: { type: 'string', description: 'Task description' },
|
|
91
|
+
context: { type: 'string', description: 'Additional context' },
|
|
92
|
+
},
|
|
93
|
+
required: ['agent', 'task'],
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
create_checkpoint: {
|
|
97
|
+
name: 'create_checkpoint',
|
|
98
|
+
description: 'Create a rollback checkpoint before making changes',
|
|
99
|
+
input_schema: {
|
|
100
|
+
type: 'object',
|
|
101
|
+
properties: {
|
|
102
|
+
name: { type: 'string', description: 'Checkpoint name' },
|
|
103
|
+
files: { type: 'array', items: { type: 'string' }, description: 'Files to checkpoint' },
|
|
104
|
+
},
|
|
105
|
+
required: ['name'],
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
browse_web: {
|
|
109
|
+
name: 'browse_web',
|
|
110
|
+
description: 'Browse a webpage and extract information',
|
|
111
|
+
input_schema: {
|
|
112
|
+
type: 'object',
|
|
113
|
+
properties: {
|
|
114
|
+
url: { type: 'string', description: 'URL to browse' },
|
|
115
|
+
action: { type: 'string', description: 'Action: read, screenshot, click, fill' },
|
|
116
|
+
selector: { type: 'string', description: 'CSS selector for action' },
|
|
117
|
+
value: { type: 'string', description: 'Value for fill action' },
|
|
118
|
+
},
|
|
119
|
+
required: ['url'],
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
// ============================================================================
|
|
126
|
+
// AGENT CLASS
|
|
127
|
+
// ============================================================================
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Autonomous Agent powered by Anthropic SDK
|
|
131
|
+
*/
|
|
132
|
+
export class AutonomousAgent {
|
|
133
|
+
constructor(config) {
|
|
134
|
+
this.name = config.name;
|
|
135
|
+
this.role = config.role;
|
|
136
|
+
this.systemPrompt = config.systemPrompt;
|
|
137
|
+
this.tools = config.tools || [];
|
|
138
|
+
this.model = config.model || AGENT_SDK_CONFIG.defaultModel;
|
|
139
|
+
this.maxTokens = config.maxTokens || AGENT_SDK_CONFIG.maxTokens.default;
|
|
140
|
+
this.memory = [];
|
|
141
|
+
this.artifacts = [];
|
|
142
|
+
this.checkpoints = new Map();
|
|
143
|
+
this.provider = config.provider;
|
|
144
|
+
this.workdir = config.workdir || process.cwd();
|
|
145
|
+
this.browser = null;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Execute a tool call
|
|
150
|
+
*/
|
|
151
|
+
async executeTool(toolName, input) {
|
|
152
|
+
switch (toolName) {
|
|
153
|
+
case 'read_file':
|
|
154
|
+
return this._readFile(input.path);
|
|
155
|
+
|
|
156
|
+
case 'write_file':
|
|
157
|
+
return this._writeFile(input.path, input.content);
|
|
158
|
+
|
|
159
|
+
case 'search_code':
|
|
160
|
+
return this._searchCode(input.query, input.file_pattern);
|
|
161
|
+
|
|
162
|
+
case 'run_command':
|
|
163
|
+
return this._runCommand(input.command, input.timeout);
|
|
164
|
+
|
|
165
|
+
case 'delegate_task':
|
|
166
|
+
return this._delegateTask(input.agent, input.task, input.context);
|
|
167
|
+
|
|
168
|
+
case 'create_checkpoint':
|
|
169
|
+
return this._createCheckpoint(input.name, input.files);
|
|
170
|
+
|
|
171
|
+
case 'browse_web':
|
|
172
|
+
return this._browseWeb(input.url, input.action, input.selector, input.value);
|
|
173
|
+
|
|
174
|
+
default:
|
|
175
|
+
return { error: `Unknown tool: ${toolName}` };
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
async _readFile(filepath) {
|
|
180
|
+
try {
|
|
181
|
+
const fullPath = path.resolve(this.workdir, filepath);
|
|
182
|
+
const content = await fs.readFile(fullPath, 'utf8');
|
|
183
|
+
return { success: true, content, path: filepath };
|
|
184
|
+
} catch (err) {
|
|
185
|
+
return { success: false, error: err.message };
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
async _writeFile(filepath, content) {
|
|
190
|
+
try {
|
|
191
|
+
const fullPath = path.resolve(this.workdir, filepath);
|
|
192
|
+
await fs.mkdir(path.dirname(fullPath), { recursive: true });
|
|
193
|
+
await fs.writeFile(fullPath, content, 'utf8');
|
|
194
|
+
this.artifacts.push(filepath);
|
|
195
|
+
return { success: true, path: filepath, bytesWritten: content.length };
|
|
196
|
+
} catch (err) {
|
|
197
|
+
return { success: false, error: err.message };
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
async _searchCode(query, filePattern = '**/*') {
|
|
202
|
+
try {
|
|
203
|
+
const { glob } = await import('glob');
|
|
204
|
+
const files = await glob(filePattern, {
|
|
205
|
+
cwd: this.workdir,
|
|
206
|
+
ignore: ['**/node_modules/**', '**/dist/**', '**/.git/**'],
|
|
207
|
+
nodir: true,
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
const results = [];
|
|
211
|
+
const regex = new RegExp(query, 'gi');
|
|
212
|
+
|
|
213
|
+
for (const file of files.slice(0, 50)) {
|
|
214
|
+
try {
|
|
215
|
+
const content = await fs.readFile(path.join(this.workdir, file), 'utf8');
|
|
216
|
+
const matches = content.match(regex);
|
|
217
|
+
if (matches) {
|
|
218
|
+
results.push({
|
|
219
|
+
file,
|
|
220
|
+
matches: matches.length,
|
|
221
|
+
preview: content.substring(0, 200),
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
} catch {
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return { success: true, results, total: results.length };
|
|
230
|
+
} catch (err) {
|
|
231
|
+
return { success: false, error: err.message };
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
async _runCommand(command, timeout = 30000) {
|
|
236
|
+
try {
|
|
237
|
+
const { exec } = await import('child_process');
|
|
238
|
+
const { promisify } = await import('util');
|
|
239
|
+
const execAsync = promisify(exec);
|
|
240
|
+
|
|
241
|
+
const { stdout, stderr } = await execAsync(command, {
|
|
242
|
+
cwd: this.workdir,
|
|
243
|
+
timeout,
|
|
244
|
+
maxBuffer: 1024 * 1024,
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
return { success: true, stdout, stderr };
|
|
248
|
+
} catch (err) {
|
|
249
|
+
return { success: false, error: err.message, stdout: err.stdout, stderr: err.stderr };
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
async _delegateTask(agentName, task, context) {
|
|
254
|
+
return {
|
|
255
|
+
delegated: true,
|
|
256
|
+
agent: agentName,
|
|
257
|
+
task,
|
|
258
|
+
context,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
async _createCheckpoint(name, files = []) {
|
|
263
|
+
const checkpoint = {
|
|
264
|
+
name,
|
|
265
|
+
timestamp: new Date().toISOString(),
|
|
266
|
+
files: {},
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
const filesToCheckpoint = files.length > 0 ? files : this.artifacts;
|
|
270
|
+
|
|
271
|
+
for (const file of filesToCheckpoint) {
|
|
272
|
+
try {
|
|
273
|
+
const content = await fs.readFile(path.resolve(this.workdir, file), 'utf8');
|
|
274
|
+
checkpoint.files[file] = content;
|
|
275
|
+
} catch {
|
|
276
|
+
// File doesn't exist yet
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
this.checkpoints.set(name, checkpoint);
|
|
281
|
+
return { success: true, name, filesCheckpointed: Object.keys(checkpoint.files).length };
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
async _browseWeb(url, action = 'read', selector, value) {
|
|
285
|
+
try {
|
|
286
|
+
// Dynamic import of browser module
|
|
287
|
+
const { BrowserAutomation } = await import('../utils/browser.js');
|
|
288
|
+
|
|
289
|
+
if (!this.browser) {
|
|
290
|
+
this.browser = new BrowserAutomation();
|
|
291
|
+
await this.browser.launch();
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
let result;
|
|
295
|
+
|
|
296
|
+
switch (action) {
|
|
297
|
+
case 'read':
|
|
298
|
+
result = await this.browser.getPageContent(url);
|
|
299
|
+
break;
|
|
300
|
+
case 'screenshot':
|
|
301
|
+
result = await this.browser.screenshot(url);
|
|
302
|
+
break;
|
|
303
|
+
case 'click':
|
|
304
|
+
await this.browser.navigate(url);
|
|
305
|
+
result = await this.browser.click(selector);
|
|
306
|
+
break;
|
|
307
|
+
case 'fill':
|
|
308
|
+
await this.browser.navigate(url);
|
|
309
|
+
result = await this.browser.fill(selector, value);
|
|
310
|
+
break;
|
|
311
|
+
default:
|
|
312
|
+
result = await this.browser.getPageContent(url);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
return { success: true, ...result };
|
|
316
|
+
} catch (err) {
|
|
317
|
+
return { success: false, error: err.message };
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Rollback to a checkpoint
|
|
323
|
+
*/
|
|
324
|
+
async rollback(checkpointName) {
|
|
325
|
+
const checkpoint = this.checkpoints.get(checkpointName);
|
|
326
|
+
if (!checkpoint) {
|
|
327
|
+
return { success: false, error: `Checkpoint not found: ${checkpointName}` };
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
for (const [file, content] of Object.entries(checkpoint.files)) {
|
|
331
|
+
await fs.writeFile(path.resolve(this.workdir, file), content, 'utf8');
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
return { success: true, restoredFiles: Object.keys(checkpoint.files).length };
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Close browser if open
|
|
339
|
+
*/
|
|
340
|
+
async cleanup() {
|
|
341
|
+
if (this.browser) {
|
|
342
|
+
await this.browser.close();
|
|
343
|
+
this.browser = null;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Run the agent with a task (agentic loop)
|
|
349
|
+
*/
|
|
350
|
+
async run(task, options = {}) {
|
|
351
|
+
const { maxIterations = 10, verbose = false } = options;
|
|
352
|
+
|
|
353
|
+
const messages = [
|
|
354
|
+
{
|
|
355
|
+
role: 'user',
|
|
356
|
+
content: `${task}\n\nYou have access to tools. Use them to complete this task. When done, respond with TASK_COMPLETE.`,
|
|
357
|
+
},
|
|
358
|
+
];
|
|
359
|
+
|
|
360
|
+
if (this.memory.length > 0) {
|
|
361
|
+
const memoryContext = this.memory.slice(-5).map(m => `- ${m}`).join('\n');
|
|
362
|
+
messages[0].content = `Previous context:\n${memoryContext}\n\n${messages[0].content}`;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
let iteration = 0;
|
|
366
|
+
const trace = [];
|
|
367
|
+
|
|
368
|
+
try {
|
|
369
|
+
while (iteration < maxIterations) {
|
|
370
|
+
iteration++;
|
|
371
|
+
|
|
372
|
+
if (verbose) {
|
|
373
|
+
console.log(chalk.gray(` [${this.name}] Iteration ${iteration}...`));
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
const response = await this.provider.generateWithTools(
|
|
377
|
+
this.systemPrompt,
|
|
378
|
+
messages,
|
|
379
|
+
Object.values(AGENT_SDK_CONFIG.tools).filter(t => this.tools.includes(t.name)),
|
|
380
|
+
{ maxTokens: this.maxTokens }
|
|
381
|
+
);
|
|
382
|
+
|
|
383
|
+
if (response.content?.includes('TASK_COMPLETE') || response.stopReason === 'end_turn') {
|
|
384
|
+
trace.push({ iteration, type: 'complete', content: response.content });
|
|
385
|
+
break;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
if (response.toolUse && response.toolUse.length > 0) {
|
|
389
|
+
for (const tool of response.toolUse) {
|
|
390
|
+
if (verbose) {
|
|
391
|
+
console.log(chalk.cyan(` -> ${tool.name}(${JSON.stringify(tool.input).substring(0, 50)}...)`));
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
const result = await this.executeTool(tool.name, tool.input);
|
|
395
|
+
|
|
396
|
+
trace.push({
|
|
397
|
+
iteration,
|
|
398
|
+
type: 'tool',
|
|
399
|
+
tool: tool.name,
|
|
400
|
+
input: tool.input,
|
|
401
|
+
result,
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
if (result.delegated) {
|
|
405
|
+
return {
|
|
406
|
+
status: 'delegated',
|
|
407
|
+
delegateTo: result.agent,
|
|
408
|
+
task: result.task,
|
|
409
|
+
context: result.context,
|
|
410
|
+
trace,
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
messages.push({
|
|
415
|
+
role: 'assistant',
|
|
416
|
+
content: response.content || '',
|
|
417
|
+
tool_use: [tool],
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
messages.push({
|
|
421
|
+
role: 'user',
|
|
422
|
+
content: [{
|
|
423
|
+
type: 'tool_result',
|
|
424
|
+
tool_use_id: tool.id,
|
|
425
|
+
content: JSON.stringify(result),
|
|
426
|
+
}],
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
} else {
|
|
430
|
+
trace.push({ iteration, type: 'response', content: response.content });
|
|
431
|
+
messages.push({ role: 'assistant', content: response.content });
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
} finally {
|
|
435
|
+
await this.cleanup();
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
this.memory.push(`Completed: ${task}`);
|
|
439
|
+
|
|
440
|
+
return {
|
|
441
|
+
status: iteration >= maxIterations ? 'max_iterations' : 'complete',
|
|
442
|
+
artifacts: this.artifacts,
|
|
443
|
+
trace,
|
|
444
|
+
iterations: iteration,
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// ============================================================================
|
|
450
|
+
// AGENT FACTORY
|
|
451
|
+
// ============================================================================
|
|
452
|
+
|
|
453
|
+
export function createAgent(type, provider, options = {}) {
|
|
454
|
+
const agents = {
|
|
455
|
+
planner: {
|
|
456
|
+
name: '@Planner',
|
|
457
|
+
role: 'Task Breakdown Specialist',
|
|
458
|
+
systemPrompt: `You are @Planner, an expert at breaking down features into atomic, implementable tasks.
|
|
459
|
+
You analyze requirements and create clear, sequential task lists.
|
|
460
|
+
Use search_code to understand the existing codebase before planning.
|
|
461
|
+
Output tasks with clear assignments to other agents.`,
|
|
462
|
+
tools: ['search_code', 'read_file', 'delegate_task', 'browse_web'],
|
|
463
|
+
maxTokens: AGENT_SDK_CONFIG.maxTokens.planner,
|
|
464
|
+
},
|
|
465
|
+
|
|
466
|
+
backend: {
|
|
467
|
+
name: '@Backend',
|
|
468
|
+
role: 'API & Server Developer',
|
|
469
|
+
systemPrompt: `You are @Backend, an expert backend developer.
|
|
470
|
+
You write clean, secure API code following best practices.
|
|
471
|
+
Always create checkpoints before making changes.
|
|
472
|
+
Run tests after implementing.`,
|
|
473
|
+
tools: ['read_file', 'write_file', 'search_code', 'run_command', 'create_checkpoint'],
|
|
474
|
+
maxTokens: AGENT_SDK_CONFIG.maxTokens.coder,
|
|
475
|
+
},
|
|
476
|
+
|
|
477
|
+
frontend: {
|
|
478
|
+
name: '@Frontend',
|
|
479
|
+
role: 'UI/UX Developer',
|
|
480
|
+
systemPrompt: `You are @Frontend, an expert React/Next.js developer.
|
|
481
|
+
You build accessible, performant UI components.
|
|
482
|
+
Follow the project's existing patterns and component library.`,
|
|
483
|
+
tools: ['read_file', 'write_file', 'search_code', 'run_command', 'create_checkpoint', 'browse_web'],
|
|
484
|
+
maxTokens: AGENT_SDK_CONFIG.maxTokens.coder,
|
|
485
|
+
},
|
|
486
|
+
|
|
487
|
+
database: {
|
|
488
|
+
name: '@Database',
|
|
489
|
+
role: 'Database Architect',
|
|
490
|
+
systemPrompt: `You are @Database, an expert in database design and optimization.
|
|
491
|
+
You create efficient schemas, migrations, and queries.
|
|
492
|
+
Consider indexing and performance in all decisions.`,
|
|
493
|
+
tools: ['read_file', 'write_file', 'search_code', 'run_command'],
|
|
494
|
+
maxTokens: AGENT_SDK_CONFIG.maxTokens.coder,
|
|
495
|
+
},
|
|
496
|
+
|
|
497
|
+
testing: {
|
|
498
|
+
name: '@Testing',
|
|
499
|
+
role: 'QA Engineer',
|
|
500
|
+
systemPrompt: `You are @Testing, an expert in test automation.
|
|
501
|
+
You write comprehensive unit, integration, and e2e tests.
|
|
502
|
+
Ensure high coverage of edge cases and error paths.`,
|
|
503
|
+
tools: ['read_file', 'write_file', 'search_code', 'run_command', 'browse_web'],
|
|
504
|
+
maxTokens: AGENT_SDK_CONFIG.maxTokens.coder,
|
|
505
|
+
},
|
|
506
|
+
|
|
507
|
+
reviewer: {
|
|
508
|
+
name: '@Reviewer',
|
|
509
|
+
role: 'Code Review Specialist',
|
|
510
|
+
systemPrompt: `You are @Reviewer, an expert code reviewer.
|
|
511
|
+
You identify bugs, security issues, and improvement opportunities.
|
|
512
|
+
Provide actionable feedback with specific line references.`,
|
|
513
|
+
tools: ['read_file', 'search_code'],
|
|
514
|
+
maxTokens: AGENT_SDK_CONFIG.maxTokens.reviewer,
|
|
515
|
+
},
|
|
516
|
+
|
|
517
|
+
research: {
|
|
518
|
+
name: '@Research',
|
|
519
|
+
role: 'Technology Research Specialist',
|
|
520
|
+
systemPrompt: `You are @Research, an expert at technology evaluation.
|
|
521
|
+
You research libraries, frameworks, and best practices.
|
|
522
|
+
Use browse_web to gather information from documentation and articles.`,
|
|
523
|
+
tools: ['browse_web', 'read_file', 'search_code', 'delegate_task'],
|
|
524
|
+
maxTokens: AGENT_SDK_CONFIG.maxTokens.planner,
|
|
525
|
+
},
|
|
526
|
+
|
|
527
|
+
devops: {
|
|
528
|
+
name: '@DevOps',
|
|
529
|
+
role: 'Infrastructure Engineer',
|
|
530
|
+
systemPrompt: `You are @DevOps, an expert in CI/CD and infrastructure.
|
|
531
|
+
You set up deployment pipelines, Docker configs, and cloud infrastructure.
|
|
532
|
+
Prioritize security and reliability.`,
|
|
533
|
+
tools: ['read_file', 'write_file', 'search_code', 'run_command'],
|
|
534
|
+
maxTokens: AGENT_SDK_CONFIG.maxTokens.coder,
|
|
535
|
+
},
|
|
536
|
+
|
|
537
|
+
security: {
|
|
538
|
+
name: '@Security',
|
|
539
|
+
role: 'Security Auditor',
|
|
540
|
+
systemPrompt: `You are @Security, an expert security auditor.
|
|
541
|
+
You identify vulnerabilities (OWASP Top 10, etc.) and recommend fixes.
|
|
542
|
+
Never ignore potential security issues.`,
|
|
543
|
+
tools: ['read_file', 'search_code', 'run_command', 'browse_web'],
|
|
544
|
+
maxTokens: AGENT_SDK_CONFIG.maxTokens.reviewer,
|
|
545
|
+
},
|
|
546
|
+
};
|
|
547
|
+
|
|
548
|
+
const agentConfig = agents[type];
|
|
549
|
+
if (!agentConfig) {
|
|
550
|
+
throw new Error(`Unknown agent type: ${type}`);
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
return new AutonomousAgent({
|
|
554
|
+
...agentConfig,
|
|
555
|
+
...options,
|
|
556
|
+
provider,
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// ============================================================================
|
|
561
|
+
// ORCHESTRATOR
|
|
562
|
+
// ============================================================================
|
|
563
|
+
|
|
564
|
+
export class AgentOrchestrator {
|
|
565
|
+
constructor(provider, options = {}) {
|
|
566
|
+
this.provider = provider;
|
|
567
|
+
this.agents = new Map();
|
|
568
|
+
this.options = options;
|
|
569
|
+
this.history = [];
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
register(type) {
|
|
573
|
+
const agent = createAgent(type, this.provider, this.options);
|
|
574
|
+
this.agents.set(type, agent);
|
|
575
|
+
return agent;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
async runSwarm(task, options = {}) {
|
|
579
|
+
const { startAgent = 'planner', verbose = false } = options;
|
|
580
|
+
|
|
581
|
+
const agentTypes = ['planner', 'backend', 'frontend', 'database', 'testing', 'reviewer', 'research', 'security', 'devops'];
|
|
582
|
+
for (const type of agentTypes) {
|
|
583
|
+
if (!this.agents.has(type)) {
|
|
584
|
+
this.register(type);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
const results = [];
|
|
589
|
+
let currentAgent = startAgent;
|
|
590
|
+
let currentTask = task;
|
|
591
|
+
let maxDelegations = 10;
|
|
592
|
+
|
|
593
|
+
while (maxDelegations > 0) {
|
|
594
|
+
const agent = this.agents.get(currentAgent);
|
|
595
|
+
if (!agent) {
|
|
596
|
+
console.log(chalk.red(`Agent not found: ${currentAgent}`));
|
|
597
|
+
break;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
if (verbose) {
|
|
601
|
+
console.log(chalk.cyan(`\n[${agent.name}] Starting task...`));
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
const result = await agent.run(currentTask, { verbose });
|
|
605
|
+
results.push({ agent: currentAgent, result });
|
|
606
|
+
this.history.push({ agent: currentAgent, task: currentTask, result });
|
|
607
|
+
|
|
608
|
+
if (result.status === 'delegated') {
|
|
609
|
+
currentAgent = result.delegateTo.toLowerCase().replace('@', '');
|
|
610
|
+
currentTask = `${result.task}\n\nContext: ${result.context || ''}`;
|
|
611
|
+
maxDelegations--;
|
|
612
|
+
} else {
|
|
613
|
+
break;
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
return {
|
|
618
|
+
results,
|
|
619
|
+
history: this.history,
|
|
620
|
+
artifacts: results.flatMap(r => r.result.artifacts || []),
|
|
621
|
+
};
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
export default {
|
|
626
|
+
AutonomousAgent,
|
|
627
|
+
AgentOrchestrator,
|
|
628
|
+
createAgent,
|
|
629
|
+
AGENT_SDK_CONFIG,
|
|
630
|
+
};
|