agent-mp 0.5.33 → 0.5.35
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 +56 -0
- package/dist/core/engine.js +76 -47
- package/package.json +1 -1
package/dist/commands/repl.js
CHANGED
|
@@ -855,6 +855,9 @@ function cmdHelp(fi) {
|
|
|
855
855
|
{ key: '/run rev <id>', value: 'Run only reviewer' },
|
|
856
856
|
{ key: '/run explorer [task]', value: 'Run only explorer' },
|
|
857
857
|
{ key: '/explorer [task]', value: 'Run explorer (shortcut)' },
|
|
858
|
+
{ key: '/orch <feature-id>', value: 'Lanza SOLO orchestrator — genera plan.json' },
|
|
859
|
+
{ key: '/impl <task-id>', value: 'Lanza SOLO implementor — ejecuta plan existente' },
|
|
860
|
+
{ key: '/rev <task-id>', value: 'Lanza SOLO reviewer — valida implementación' },
|
|
858
861
|
{ key: '/model', value: 'Cambiar modelo del coordinador' },
|
|
859
862
|
{ key: '/provider', value: 'Cambiar proveedor activo (Gemini / Qwen)' },
|
|
860
863
|
{ key: '/login', value: 'Configurar API key (Qwen o Gemini)' },
|
|
@@ -1196,6 +1199,59 @@ export async function runRepl(resumeSession) {
|
|
|
1196
1199
|
});
|
|
1197
1200
|
break;
|
|
1198
1201
|
}
|
|
1202
|
+
// Comandos cortos para lanzar roles directamente
|
|
1203
|
+
case 'orch': {
|
|
1204
|
+
// /orch <feature-id> — lanza solo orchestrator sin preguntas
|
|
1205
|
+
const featureId = args.join(' ').trim();
|
|
1206
|
+
if (!featureId) {
|
|
1207
|
+
fi.println(chalk.red(' Uso: /orch <feature-id>'));
|
|
1208
|
+
break;
|
|
1209
|
+
}
|
|
1210
|
+
await withEngine(async (engine) => {
|
|
1211
|
+
const result = await engine.runOrchestrator(`.agent/docs/${featureId}`, undefined, featureId);
|
|
1212
|
+
fi.println(chalk.green(` ✓ Task ID: ${result.taskId}`));
|
|
1213
|
+
fi.println(chalk.green(` ✓ Plan: .agent/tasks/${result.taskId}/plan.json`));
|
|
1214
|
+
});
|
|
1215
|
+
break;
|
|
1216
|
+
}
|
|
1217
|
+
case 'impl': {
|
|
1218
|
+
// /impl <task-id> — lanza solo implementor con plan existente
|
|
1219
|
+
const taskId = args.join(' ').trim();
|
|
1220
|
+
if (!taskId) {
|
|
1221
|
+
fi.println(chalk.red(' Uso: /impl <task-id>'));
|
|
1222
|
+
break;
|
|
1223
|
+
}
|
|
1224
|
+
await withEngine(async (engine) => {
|
|
1225
|
+
const taskDir = path.join(engine['projectDir'], '.agent', 'tasks', taskId);
|
|
1226
|
+
if (!await fileExists(taskDir)) {
|
|
1227
|
+
fi.println(chalk.red(` ✗ Task "${taskId}" no existe`));
|
|
1228
|
+
return;
|
|
1229
|
+
}
|
|
1230
|
+
const plan = await readJson(path.join(taskDir, 'plan.json'));
|
|
1231
|
+
await engine.runImplementor(taskId, plan);
|
|
1232
|
+
fi.println(chalk.green(` ✓ Implementación completada`));
|
|
1233
|
+
});
|
|
1234
|
+
break;
|
|
1235
|
+
}
|
|
1236
|
+
case 'rev': {
|
|
1237
|
+
// /rev <task-id> — lanza solo reviewer
|
|
1238
|
+
const taskId = args.join(' ').trim();
|
|
1239
|
+
if (!taskId) {
|
|
1240
|
+
fi.println(chalk.red(' Uso: /rev <task-id>'));
|
|
1241
|
+
break;
|
|
1242
|
+
}
|
|
1243
|
+
await withEngine(async (engine) => {
|
|
1244
|
+
const taskDir = path.join(engine['projectDir'], '.agent', 'tasks', taskId);
|
|
1245
|
+
if (!await fileExists(taskDir)) {
|
|
1246
|
+
fi.println(chalk.red(` ✗ Task "${taskId}" no existe`));
|
|
1247
|
+
return;
|
|
1248
|
+
}
|
|
1249
|
+
const plan = await readJson(path.join(taskDir, 'plan.json'));
|
|
1250
|
+
const progress = await readJson(path.join(taskDir, 'progress.json'));
|
|
1251
|
+
await engine.runReviewer(taskId, plan, progress);
|
|
1252
|
+
});
|
|
1253
|
+
break;
|
|
1254
|
+
}
|
|
1199
1255
|
case 'models':
|
|
1200
1256
|
case 'model':
|
|
1201
1257
|
await withRl((rl) => cmdModels(args[0], fi, rl));
|
package/dist/core/engine.js
CHANGED
|
@@ -414,19 +414,46 @@ export class AgentEngine {
|
|
|
414
414
|
MODO SPEC — Feature cargada: "${activeFeatureId}"
|
|
415
415
|
Los archivos raw YA ESTÁN en el CONTEXTO DEL PROYECTO arriba.
|
|
416
416
|
|
|
417
|
+
TU ÚNICO TRABAJO: Construir colaborativamente un **SPEC.MD FUNCIONAL** con el programador.
|
|
418
|
+
|
|
417
419
|
REGLAS CRÍTICAS:
|
|
418
|
-
1. ANTES DE ESCRIBIR CUALQUIER COSA: leé completo el CONTEXTO DEL PROYECTO, incluyendo
|
|
420
|
+
1. ANTES DE ESCRIBIR CUALQUIER COSA: leé completo el CONTEXTO DEL PROYECTO, incluyendo "TAREA EXISTENTE" si está presente.
|
|
419
421
|
2. SI EXISTE SPEC.MD en el contexto (bajo "SPEC.MD EXISTENTE"):
|
|
420
422
|
- **NO lo regeneres desde cero** — ese documento es VIVO y lo edita el humano.
|
|
421
|
-
- Identificá qué secciones ya están completas
|
|
423
|
+
- Identificá qué secciones ya están completas.
|
|
422
424
|
- Identificá qué información FALTA o está incompleta.
|
|
423
425
|
- Hacé SOLO las preguntas necesarias para completar lo que falta.
|
|
424
|
-
- Si el spec.md ya está completo, NO hagas preguntas —
|
|
425
|
-
3.
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
426
|
+
- Si el spec.md ya está completo, NO hagas preguntas — decí "El spec está listo. Usá /orch para lanzar la planificación".
|
|
427
|
+
3. EL SPEC.MD DEBE SER FUNCIONAL — describí QUÉ se va a construir, no CÓMO:
|
|
428
|
+
|
|
429
|
+
**Para endpoints/nuevas features:**
|
|
430
|
+
- Endpoint: método y ruta (ej: POST /users)
|
|
431
|
+
- Request: datos de entrada (body, params, query) con tipos y validaciones
|
|
432
|
+
- Response: datos de salida con estructura y códigos HTTP
|
|
433
|
+
- Proceso por capas: Controller → Service → Repository (qué pasa en cada una)
|
|
434
|
+
- Reglas de negocio: validaciones, condiciones, excepciones
|
|
435
|
+
|
|
436
|
+
**Para fixes/correcciones:**
|
|
437
|
+
- Comportamiento actual: cómo funciona ahora (el problema)
|
|
438
|
+
- Comportamiento esperado: cómo debe funcionar después
|
|
439
|
+
- Casos afectados: qué funcionalidades existentes pueden impactarse
|
|
440
|
+
- Criterios de aceptación: cómo se verifica que está fixeado
|
|
441
|
+
|
|
442
|
+
**Para scripts/utilidades:**
|
|
443
|
+
- Entrada: qué recibe (parámetros, archivos, input de usuario)
|
|
444
|
+
- Salida: qué produce (archivo, output en consola, resultado)
|
|
445
|
+
- Proceso: pasos que ejecuta (sin detalles de implementación)
|
|
446
|
+
- Manejo de errores: qué pasa si falla
|
|
447
|
+
|
|
448
|
+
4. NUNCA incluyas en el spec:
|
|
449
|
+
- Nombres de archivos específicos (eso lo define el orchestrator)
|
|
450
|
+
- Pasos de implementación (eso lo define el plan.json)
|
|
451
|
+
- Tecnologías específicas a menos que el programador las mencione
|
|
452
|
+
|
|
453
|
+
5. Cuando el spec.md esté completo (o si ya existe y está completo):
|
|
454
|
+
- Confirmá con el programador que está listo
|
|
455
|
+
- Indicá que puede usar **/orch <feature-id>** para lanzar la planificación
|
|
456
|
+
- Escribí EXACTAMENTE al final: ${READY_SENTINEL}` : `
|
|
430
457
|
MODO TAREA LIBRE — No se especificó feature todavía.
|
|
431
458
|
${featureListBlock}
|
|
432
459
|
REGLAS:
|
|
@@ -437,7 +464,7 @@ REGLAS:
|
|
|
437
464
|
- Cuando el objetivo esté claro, escribí EXACTAMENTE al final: ${READY_SENTINEL}
|
|
438
465
|
- NUNCA escribas ${READY_SENTINEL} si solo recibiste un saludo o falta información concreta.`;
|
|
439
466
|
const prompt = `Sos el COORDINADOR de un equipo de desarrollo de software.
|
|
440
|
-
Tu
|
|
467
|
+
Tu ÚNICO TRABAJO es construir colaborativamente un **SPEC.MD FUNCIONAL** con el programador.
|
|
441
468
|
|
|
442
469
|
REGLA DE ORO: ANTES de escribir cualquier respuesta, LEÉ COMPLETO el CONTEXTO DEL PROYECTO que está arriba. Toda la información que necesitás para no hacer preguntas obvias está ahí.
|
|
443
470
|
|
|
@@ -451,12 +478,14 @@ INSTRUCCIONES GENERALES:
|
|
|
451
478
|
- Hablá en forma NATURAL, como un compañero de equipo experimentado.
|
|
452
479
|
- ANTES DE RESPONDER: leé todo el CONTEXTO DEL PROYECTO, incluyendo "TAREA EXISTENTE" si está presente.
|
|
453
480
|
- **SPEC.MD ES DOCUMENTO VIVO**: Si ya existe spec.md, NO lo regeneres — es un documento que el humano va construyendo y editando. Solo identificá qué falta y preguntá para completar.
|
|
481
|
+
- Tu rol es **SOLO clarificación funcional** — NO lanzás el orchestrator, implementador, ni reviewer. Eso lo hace el programador manualmente con /orch, /impl, /rev.
|
|
454
482
|
- Si hay una TAREA EXISTENTE con RESULTADO PREVIO: FAIL, informá al usuario qué falló y preguntá si quiere corregir eso específico.
|
|
455
483
|
- Si ya hay SPEC.MD o plan.json para la tarea, NO los regeneres — usá los existentes.
|
|
456
484
|
- NO preguntés cosas que ya están respondidas en los archivos raw, TAREA EXISTENTE, SPEC.MD o la conversación.
|
|
457
485
|
- Hacé como máximo UNA pregunta por turno.
|
|
458
486
|
- NO uses JSON, hablá normalmente.
|
|
459
|
-
- Sé directo y eficiente — respetá el tiempo del programador
|
|
487
|
+
- Sé directo y eficiente — respetá el tiempo del programador.
|
|
488
|
+
- **Cuando el spec esté listo**: Confirmá que el programador puede usar **/orch <feature-id>** para lanzar la planificación.${specInstructions}`;
|
|
460
489
|
log.info('Coordinador analizando...');
|
|
461
490
|
const envOverride = {};
|
|
462
491
|
let res;
|
|
@@ -601,48 +630,48 @@ INSTRUCCIONES GENERALES:
|
|
|
601
630
|
}
|
|
602
631
|
// Sentinel-based detection — coordinator explicitly signals readiness
|
|
603
632
|
if (responseText.includes('[LISTO_PARA_LANZAR]')) {
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
log.ok(`spec.md existente mantenido`);
|
|
628
|
-
}
|
|
633
|
+
// El spec está listo — guardar y retornar SIN preguntar si lanzar orchestrator
|
|
634
|
+
let specPath;
|
|
635
|
+
if (activeFeatureId) {
|
|
636
|
+
const specDir = path.join(this.projectDir, '.agent', 'docs', activeFeatureId);
|
|
637
|
+
const specFile = path.join(specDir, 'spec.md');
|
|
638
|
+
// Si ya existe spec.md y hay contenido nuevo, ACTUALIZAR incrementalmente
|
|
639
|
+
if (await fileExists(specFile) && pendingSpecContent) {
|
|
640
|
+
const existingSpec = await readFile(specFile);
|
|
641
|
+
// Si el contenido es sustancialmente diferente, preguntar al usuario
|
|
642
|
+
if (existingSpec.trim() !== pendingSpecContent.trim()) {
|
|
643
|
+
console.log(chalk.yellow('\n ⚠️ Ya existe un spec.md con este contenido:'));
|
|
644
|
+
console.log(chalk.dim(' ' + existingSpec.split('\n').slice(0, 10).join('\n ')));
|
|
645
|
+
const action = await ask('\n ¿Qué querés hacer? (r=reemplazar / m=mantener el existente / e=editar): ', this.rl);
|
|
646
|
+
if (action.toLowerCase() === 'r') {
|
|
647
|
+
await writeFile(specFile, pendingSpecContent);
|
|
648
|
+
log.ok(`spec.md reemplazado`);
|
|
649
|
+
}
|
|
650
|
+
else if (action.toLowerCase() === 'e') {
|
|
651
|
+
console.log(chalk.dim(' Editá el archivo spec.md manualmente y luego volvé a ejecutar.'));
|
|
652
|
+
return { task: conversationHistory, specPath: undefined, featureId: activeFeatureId };
|
|
653
|
+
}
|
|
654
|
+
else {
|
|
655
|
+
log.ok(`spec.md existente mantenido`);
|
|
629
656
|
}
|
|
630
657
|
}
|
|
631
|
-
else
|
|
632
|
-
|
|
633
|
-
await writeFile(specFile, pendingSpecContent);
|
|
634
|
-
log.ok(`spec.md guardado en ${path.relative(this.projectDir, specFile)}`);
|
|
635
|
-
}
|
|
636
|
-
if (await fileExists(specFile)) {
|
|
637
|
-
specPath = specFile;
|
|
658
|
+
else {
|
|
659
|
+
log.ok(`spec.md ya está actualizado`);
|
|
638
660
|
}
|
|
639
661
|
}
|
|
640
|
-
|
|
662
|
+
else if (pendingSpecContent) {
|
|
663
|
+
// No existe spec.md — crearlo
|
|
664
|
+
await writeFile(specFile, pendingSpecContent);
|
|
665
|
+
log.ok(`spec.md guardado en ${path.relative(this.projectDir, specFile)}`);
|
|
666
|
+
}
|
|
667
|
+
if (await fileExists(specFile)) {
|
|
668
|
+
specPath = specFile;
|
|
669
|
+
}
|
|
641
670
|
}
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
671
|
+
console.log(chalk.green('\n ✓ Spec.md listo. Para continuar usá:'));
|
|
672
|
+
console.log(chalk.dim(` /orch ${activeFeatureId || '<feature-id>'}`));
|
|
673
|
+
console.log(chalk.dim(' Esto generará el plan.json de implementación.\n'));
|
|
674
|
+
return { task: conversationHistory, specPath, featureId: activeFeatureId };
|
|
646
675
|
}
|
|
647
676
|
}
|
|
648
677
|
// Ask user — slash commands are handled here without calling coordinator again
|