agent-rev 0.2.8 → 0.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/dist/commands/repl.js +29 -1
- package/dist/core/engine.d.ts +1 -0
- package/dist/core/engine.js +73 -5
- package/dist/index.js +14 -0
- package/package.json +23 -1
package/dist/commands/repl.js
CHANGED
|
@@ -716,10 +716,12 @@ function cmdHelp(fi) {
|
|
|
716
716
|
{ key: '/setup explorer', value: 'Reconfigure explorer only' },
|
|
717
717
|
{ key: '/config-multi', value: 'Reconfigure all agents at once' },
|
|
718
718
|
{ key: '/status', value: 'Show current configuration and tasks' },
|
|
719
|
+
{ key: '/explorer <task>', value: 'Run explorer agent on a task/question' },
|
|
719
720
|
{ key: '/run <task>', value: 'Full cycle: orchestrator → implementor → reviewer' },
|
|
720
721
|
{ key: '/run orch <task>', value: 'Run only orchestrator' },
|
|
721
722
|
{ key: '/run impl <id>', value: 'Run only implementor' },
|
|
722
723
|
{ key: '/run rev <id>', value: 'Run only reviewer' },
|
|
724
|
+
{ key: '/run explorer <task>', value: 'Run only explorer' },
|
|
723
725
|
{ key: '/models', value: 'List models for all installed CLIs' },
|
|
724
726
|
{ key: '/models <cli>', value: 'List models for a specific CLI' },
|
|
725
727
|
{ key: '/login', value: 'Login (Qwen OAuth or CLI auth)' },
|
|
@@ -1035,6 +1037,12 @@ export async function runRepl(resumeSession) {
|
|
|
1035
1037
|
const progress = await readJson(path.join(taskDir, 'progress.json'));
|
|
1036
1038
|
await engine.runReviewer(taskId, plan, progress);
|
|
1037
1039
|
}
|
|
1040
|
+
else if (args[0] === 'explorer' || args[0] === 'exp') {
|
|
1041
|
+
const task = args.slice(1).join(' ') || undefined;
|
|
1042
|
+
const engine = new AgentEngine(config, dir, gCoordinatorCmd, rl, fi, handleCmd);
|
|
1043
|
+
const result = await engine.runExplorer(task);
|
|
1044
|
+
fi.println(result);
|
|
1045
|
+
}
|
|
1038
1046
|
else {
|
|
1039
1047
|
const task = args.join(' ');
|
|
1040
1048
|
const engine = new AgentEngine(config, dir, gCoordinatorCmd, rl, fi, handleCmd);
|
|
@@ -1042,6 +1050,20 @@ export async function runRepl(resumeSession) {
|
|
|
1042
1050
|
}
|
|
1043
1051
|
break;
|
|
1044
1052
|
}
|
|
1053
|
+
case 'explorer': {
|
|
1054
|
+
const task = args.join(' ') || undefined;
|
|
1055
|
+
try {
|
|
1056
|
+
const dir = process.cwd();
|
|
1057
|
+
const config = await loadProjectConfig(dir);
|
|
1058
|
+
const engine = new AgentEngine(config, dir, gCoordinatorCmd, rl, fi, handleCmd);
|
|
1059
|
+
const result = await engine.runExplorer(task);
|
|
1060
|
+
fi.println(result);
|
|
1061
|
+
}
|
|
1062
|
+
catch (err) {
|
|
1063
|
+
fi.println(chalk.red(` Explorer error: ${err.message}`));
|
|
1064
|
+
}
|
|
1065
|
+
break;
|
|
1066
|
+
}
|
|
1045
1067
|
case 'models':
|
|
1046
1068
|
case 'model':
|
|
1047
1069
|
await withRl((rl) => cmdModels(args[0], fi, rl));
|
|
@@ -1203,6 +1225,12 @@ export async function runRole(role, arg, model) {
|
|
|
1203
1225
|
await engine.runReviewer(arg, plan, progress);
|
|
1204
1226
|
break;
|
|
1205
1227
|
}
|
|
1228
|
+
case 'explorer':
|
|
1229
|
+
case 'exp': {
|
|
1230
|
+
const result = await engine.runExplorer(arg || undefined);
|
|
1231
|
+
console.log(result);
|
|
1232
|
+
break;
|
|
1233
|
+
}
|
|
1206
1234
|
case 'coordinator':
|
|
1207
1235
|
case 'coord': {
|
|
1208
1236
|
console.log(chalk.yellow(' Coordinator mode requires interactive REPL.'));
|
|
@@ -1210,7 +1238,7 @@ export async function runRole(role, arg, model) {
|
|
|
1210
1238
|
process.exit(1);
|
|
1211
1239
|
}
|
|
1212
1240
|
default:
|
|
1213
|
-
console.log(chalk.red(` Unknown role: ${role}. Use: orchestrator, implementor, reviewer`));
|
|
1241
|
+
console.log(chalk.red(` Unknown role: ${role}. Use: orchestrator, implementor, reviewer, explorer`));
|
|
1214
1242
|
process.exit(1);
|
|
1215
1243
|
}
|
|
1216
1244
|
}
|
package/dist/core/engine.d.ts
CHANGED
package/dist/core/engine.js
CHANGED
|
@@ -346,6 +346,7 @@ INSTRUCCIONES:
|
|
|
346
346
|
orchestrator: 'orchestrator',
|
|
347
347
|
implementor: 'implementor',
|
|
348
348
|
reviewer: 'reviewer',
|
|
349
|
+
explorer: 'explorer',
|
|
349
350
|
};
|
|
350
351
|
const key = roleMap[roleName];
|
|
351
352
|
const role = this.config.roles[key];
|
|
@@ -446,15 +447,23 @@ INSTRUCCIONES:
|
|
|
446
447
|
}
|
|
447
448
|
}
|
|
448
449
|
};
|
|
450
|
+
// Role binaries (agent-orch, agent-impl, etc.) are wrappers, not AI CLIs.
|
|
451
|
+
// Calling them with a full prompt causes recursion or ENAMETOOLONG errors.
|
|
452
|
+
const ROLE_BINARIES = new Set(['agent-orch', 'agent-impl', 'agent-rev', 'agent-explorer']);
|
|
449
453
|
// Try primary
|
|
450
454
|
log.info(`Launching ${roleName}: ${role.cli} (${role.model})`);
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
+
if (ROLE_BINARIES.has(role.cli)) {
|
|
456
|
+
log.warn(`${role.cli} is a role binary — skipping to fallback to avoid recursion`);
|
|
457
|
+
}
|
|
458
|
+
else {
|
|
459
|
+
const primaryResult = await tryWithAutoRepair(role.cli, role.model, role.cmd);
|
|
460
|
+
if (primaryResult !== null) {
|
|
461
|
+
trackTokens(primaryResult, role.cli, role.model);
|
|
462
|
+
return primaryResult;
|
|
463
|
+
}
|
|
455
464
|
}
|
|
456
465
|
// Try individual fallback
|
|
457
|
-
if (role.fallback) {
|
|
466
|
+
if (role.fallback && !ROLE_BINARIES.has(role.fallback.cli)) {
|
|
458
467
|
log.warn(`Trying individual fallback for ${roleName}: ${role.fallback.cli} (${role.fallback.model})`);
|
|
459
468
|
const fallbackResult = await tryWithAutoRepair(role.fallback.cli, role.fallback.model, role.fallback.cmd);
|
|
460
469
|
if (fallbackResult !== null) {
|
|
@@ -489,6 +498,10 @@ REGLA: Al terminar, responde SOLO con el JSON de progreso indicado.`,
|
|
|
489
498
|
REGLA: Usa tus herramientas (read_file, grep_search, etc.) para leer los archivos y verificar criterios.
|
|
490
499
|
REGLA: NO modifiques archivos. NO implementes correcciones.
|
|
491
500
|
REGLA: Al terminar, responde SOLO con el JSON de resultado indicado.`,
|
|
501
|
+
explorer: `ROL: EXPLORER — solo explora y reporta, nunca modifica archivos.
|
|
502
|
+
REGLA: Usa tus herramientas (read_file, grep_search, list_directory, etc.) para explorar el proyecto.
|
|
503
|
+
REGLA: NO modifiques archivos. NO ejecutes comandos que cambien estado.
|
|
504
|
+
REGLA: Al terminar, reporta todo lo que encontraste de forma clara y estructurada.`,
|
|
492
505
|
};
|
|
493
506
|
const preamble = preambles[roleName] || '';
|
|
494
507
|
return preamble ? `${preamble}\n\n${taskPrompt}` : taskPrompt;
|
|
@@ -726,6 +739,61 @@ INSTRUCCIONES:
|
|
|
726
739
|
log.verdict(verdict);
|
|
727
740
|
return { verdict };
|
|
728
741
|
}
|
|
742
|
+
async runExplorer(task) {
|
|
743
|
+
if (!this.config.roles.explorer) {
|
|
744
|
+
if (!this.config.fallback_global) {
|
|
745
|
+
throw new Error('Explorer not configured and no fallback available. Run /setup explorer first.');
|
|
746
|
+
}
|
|
747
|
+
log.warn(`Explorer role not configured — using fallback: ${this.config.fallback_global.cli} (${this.config.fallback_global.model})`);
|
|
748
|
+
this.config.roles.explorer = { ...this.config.fallback_global };
|
|
749
|
+
}
|
|
750
|
+
log.phase(0, 'Exploracion', this.config.roles.explorer.cli, this.config.roles.explorer.model);
|
|
751
|
+
// Ensure .agent/ structure exists
|
|
752
|
+
const agentDir = path.join(this.projectDir, '.agent');
|
|
753
|
+
const contextDir = path.join(agentDir, 'context');
|
|
754
|
+
await fs.mkdir(contextDir, { recursive: true });
|
|
755
|
+
await fs.mkdir(path.join(agentDir, 'rules'), { recursive: true });
|
|
756
|
+
// Read existing architecture doc if any
|
|
757
|
+
const archPath = path.join(contextDir, 'architecture.md');
|
|
758
|
+
let existingArch = '';
|
|
759
|
+
try {
|
|
760
|
+
existingArch = await readFile(archPath);
|
|
761
|
+
}
|
|
762
|
+
catch { /* new project */ }
|
|
763
|
+
const effectiveTask = task || 'Explorar y documentar todas las aplicaciones y servicios del proyecto';
|
|
764
|
+
const prompt = `TAREA DE EXPLORACION: ${effectiveTask}
|
|
765
|
+
DIRECTORIO_TRABAJO: ${this.projectDir}
|
|
766
|
+
PROYECTO: ${this.config.project}
|
|
767
|
+
STACK: ${this.config.stack}
|
|
768
|
+
|
|
769
|
+
${existingArch ? `DOCUMENTACION EXISTENTE (actualizar si hay cambios):\n${existingArch.slice(0, 3000)}\n` : 'DOCUMENTACION EXISTENTE: ninguna — crear desde cero.\n'}
|
|
770
|
+
INSTRUCCIONES:
|
|
771
|
+
1. Lista el directorio raiz para identificar todos los servicios/aplicaciones.
|
|
772
|
+
2. Para cada servicio/app: lee su package.json / requirements.txt / pyproject.toml para obtener nombre, stack y dependencias clave.
|
|
773
|
+
3. Explora src/ o app/ de cada servicio: identifica entry point, modulos principales, rutas/endpoints expuestos, puerto configurado.
|
|
774
|
+
4. Identifica dependencias ENTRE servicios (llamadas HTTP, variables de entorno compartidas, bases de datos comunes).
|
|
775
|
+
5. Crea o actualiza el archivo ${archPath} con:
|
|
776
|
+
- Tabla resumen: | Servicio | Stack | Puerto | Proposito | Entry Point |
|
|
777
|
+
- Por cada servicio: modulos principales, rutas API clave, dependencias externas
|
|
778
|
+
- Mapa de dependencias entre servicios
|
|
779
|
+
6. Crea o actualiza archivos individuales en ${contextDir}/<servicio>/architecture.md para cada servicio.
|
|
780
|
+
7. Al terminar lista todos los archivos creados/actualizados.
|
|
781
|
+
|
|
782
|
+
REGLAS:
|
|
783
|
+
- NO modifiques archivos de aplicacion (solo .agent/context/)
|
|
784
|
+
- NO ejecutes comandos que cambien estado (npm install, migraciones, etc.)
|
|
785
|
+
- Si un directorio esta en node_modules, dist, .git: ignoralo`;
|
|
786
|
+
const res = await this.runWithFallback('explorer', prompt, 'Exploracion');
|
|
787
|
+
const text = extractCliText(res);
|
|
788
|
+
// Always save a timestamped explorer report
|
|
789
|
+
try {
|
|
790
|
+
const ts = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
|
|
791
|
+
await writeFile(path.join(contextDir, `explorer-${ts}.md`), `# Explorer Report\n\nTask: ${effectiveTask}\nDate: ${new Date().toISOString()}\n\n${text}\n`);
|
|
792
|
+
log.ok(`Saved to .agent/context/explorer-${ts}.md`);
|
|
793
|
+
}
|
|
794
|
+
catch { /* don't fail if save fails */ }
|
|
795
|
+
return text;
|
|
796
|
+
}
|
|
729
797
|
async runFullCycle(task) {
|
|
730
798
|
// Header is now shown by the REPL before the first user message
|
|
731
799
|
// ══════════════════════════════════════════════════
|
package/dist/index.js
CHANGED
|
@@ -85,6 +85,20 @@ const ROLE_BINS = {
|
|
|
85
85
|
const nativeRole = ROLE_BINS[PKG_NAME];
|
|
86
86
|
if (nativeRole) {
|
|
87
87
|
const args = process.argv.slice(2);
|
|
88
|
+
// --version / -V
|
|
89
|
+
if (args.includes('--version') || args.includes('-V')) {
|
|
90
|
+
console.log(readVersion());
|
|
91
|
+
process.exit(0);
|
|
92
|
+
}
|
|
93
|
+
// --help / -h
|
|
94
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
95
|
+
console.log(chalk.bold.cyan(`\n ${PKG_NAME} v${readVersion()} — ${nativeRole} agent\n`));
|
|
96
|
+
console.log(chalk.dim(` Usage: ${PKG_NAME} [--model <model>] "<task>"`));
|
|
97
|
+
console.log(chalk.dim(` Login: ${PKG_NAME} --login`));
|
|
98
|
+
console.log(chalk.dim(` Status: ${PKG_NAME} --status`));
|
|
99
|
+
console.log(chalk.dim(` Version: ${PKG_NAME} --version\n`));
|
|
100
|
+
process.exit(0);
|
|
101
|
+
}
|
|
88
102
|
// --login: OAuth login for this role's account
|
|
89
103
|
if (args.includes('--login') || args.includes('login')) {
|
|
90
104
|
const { qwenLogin, fetchQwenModels } = await import('./utils/qwen-auth.js');
|
package/package.json
CHANGED
|
@@ -1 +1,23 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"name": "agent-rev",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "agent-rev agent",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"files": ["dist/"],
|
|
8
|
+
"bin": { "agent-rev": "dist/index.js" },
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc && echo '#!/usr/bin/env node' | cat - dist/index.js > dist/index.tmp && mv dist/index.tmp dist/index.js && chmod +x dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"keywords": ["ai", "agent", "cli"],
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"@anthropic-ai/sdk": "^0.39.0",
|
|
16
|
+
"@google/generative-ai": "^0.24.0",
|
|
17
|
+
"chalk": "^5.4.1",
|
|
18
|
+
"commander": "^13.1.0",
|
|
19
|
+
"open": "^11.0.0",
|
|
20
|
+
"openai": "^4.91.0"
|
|
21
|
+
},
|
|
22
|
+
"engines": { "node": ">=18.0.0" }
|
|
23
|
+
}
|