agent-rev 0.1.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.
Files changed (41) hide show
  1. package/dist/api/qwen.d.ts +12 -0
  2. package/dist/api/qwen.js +150 -0
  3. package/dist/commands/auth.d.ts +31 -0
  4. package/dist/commands/auth.js +255 -0
  5. package/dist/commands/config.d.ts +2 -0
  6. package/dist/commands/config.js +42 -0
  7. package/dist/commands/models.d.ts +2 -0
  8. package/dist/commands/models.js +27 -0
  9. package/dist/commands/repl.d.ts +29 -0
  10. package/dist/commands/repl.js +1167 -0
  11. package/dist/commands/run.d.ts +2 -0
  12. package/dist/commands/run.js +52 -0
  13. package/dist/commands/setup.d.ts +2 -0
  14. package/dist/commands/setup.js +353 -0
  15. package/dist/commands/status.d.ts +2 -0
  16. package/dist/commands/status.js +46 -0
  17. package/dist/core/engine.d.ts +36 -0
  18. package/dist/core/engine.js +905 -0
  19. package/dist/core/prompts.d.ts +11 -0
  20. package/dist/core/prompts.js +126 -0
  21. package/dist/index.d.ts +1 -0
  22. package/dist/index.js +171 -0
  23. package/dist/providers/index.d.ts +2 -0
  24. package/dist/providers/index.js +120 -0
  25. package/dist/types.d.ts +73 -0
  26. package/dist/types.js +58 -0
  27. package/dist/ui/input.d.ts +24 -0
  28. package/dist/ui/input.js +244 -0
  29. package/dist/ui/theme.d.ts +99 -0
  30. package/dist/ui/theme.js +307 -0
  31. package/dist/utils/config.d.ts +38 -0
  32. package/dist/utils/config.js +40 -0
  33. package/dist/utils/fs.d.ts +7 -0
  34. package/dist/utils/fs.js +37 -0
  35. package/dist/utils/logger.d.ts +13 -0
  36. package/dist/utils/logger.js +46 -0
  37. package/dist/utils/qwen-auth.d.ts +12 -0
  38. package/dist/utils/qwen-auth.js +250 -0
  39. package/dist/utils/sessions.d.ts +17 -0
  40. package/dist/utils/sessions.js +46 -0
  41. package/package.json +44 -0
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function runCommand(program: Command): void;
@@ -0,0 +1,52 @@
1
+ import * as path from 'path';
2
+ import { loadProjectConfig } from '../utils/config.js';
3
+ import { AgentEngine } from '../core/engine.js';
4
+ import { log } from '../utils/logger.js';
5
+ import { readJson } from '../utils/fs.js';
6
+ export function runCommand(program) {
7
+ const run = program.command('run')
8
+ .description('Run the full agent cycle: orchestrator -> implementor -> reviewer')
9
+ .argument('<task>', 'Task description')
10
+ .action(async (task) => {
11
+ const dir = process.cwd();
12
+ const config = await loadProjectConfig(dir);
13
+ const engine = new AgentEngine(config, dir);
14
+ await engine.runFullCycle(task);
15
+ });
16
+ run.command('orchestrator')
17
+ .alias('orch')
18
+ .description('Run only the orchestrator phase')
19
+ .argument('<task>', 'Task description')
20
+ .action(async (task) => {
21
+ const dir = process.cwd();
22
+ const config = await loadProjectConfig(dir);
23
+ const engine = new AgentEngine(config, dir);
24
+ const result = await engine.runOrchestrator(task);
25
+ log.ok(`Task ID: ${result.taskId}`);
26
+ });
27
+ run.command('implementor')
28
+ .alias('impl')
29
+ .description('Run only the implementor phase')
30
+ .argument('<taskId>', 'Task ID')
31
+ .action(async (taskId) => {
32
+ const dir = process.cwd();
33
+ const config = await loadProjectConfig(dir);
34
+ const engine = new AgentEngine(config, dir);
35
+ const taskDir = path.join(dir, '.agent', 'tasks', taskId);
36
+ const plan = await readJson(path.join(taskDir, 'plan.json'));
37
+ await engine.runImplementor(taskId, plan);
38
+ });
39
+ run.command('reviewer')
40
+ .alias('rev')
41
+ .description('Run only the reviewer phase')
42
+ .argument('<taskId>', 'Task ID')
43
+ .action(async (taskId) => {
44
+ const dir = process.cwd();
45
+ const config = await loadProjectConfig(dir);
46
+ const engine = new AgentEngine(config, dir);
47
+ const taskDir = path.join(dir, '.agent', 'tasks', taskId);
48
+ const plan = await readJson(path.join(taskDir, 'plan.json'));
49
+ const progress = await readJson(path.join(taskDir, 'progress.json'));
50
+ await engine.runReviewer(taskId, plan, progress);
51
+ });
52
+ }
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function setupCommand(program: Command): void;
@@ -0,0 +1,353 @@
1
+ import * as readline from 'readline';
2
+ import * as path from 'path';
3
+ import * as fs from 'fs/promises';
4
+ import chalk from 'chalk';
5
+ import { execSync } from 'child_process';
6
+ import { CLI_REGISTRY } from '../types.js';
7
+ import { writeJson, ensureDir } from '../utils/fs.js';
8
+ import { loadAuth, saveAuth, loadCliConfig, saveCliConfig } from '../utils/config.js';
9
+ import { log } from '../utils/logger.js';
10
+ const CONFIG_DIR = path.join(process.env.HOME || process.env.USERPROFILE || '', '.agent-cli');
11
+ const AUTH_FILE = path.join(CONFIG_DIR, 'auth.json');
12
+ function ask(rl, q) {
13
+ return new Promise((resolve) => rl.question(q, resolve));
14
+ }
15
+ function detectInstalledClis() {
16
+ const installed = [];
17
+ for (const [name, info] of Object.entries(CLI_REGISTRY)) {
18
+ try {
19
+ const p = execSync(`which ${info.command}`, { encoding: 'utf-8' }).trim();
20
+ installed.push({ name, info, path: p });
21
+ }
22
+ catch { /* not installed */ }
23
+ }
24
+ return installed;
25
+ }
26
+ function detectModels(cliName) {
27
+ try {
28
+ switch (cliName) {
29
+ case 'claude': {
30
+ const help = execSync('claude --help 2>/dev/null', { encoding: 'utf-8' });
31
+ const models = help.match(/'([^']+)'/g)?.map((m) => m.replace(/'/g, '')).filter(Boolean);
32
+ if (models?.length)
33
+ return [...new Set(models)];
34
+ return ['opus', 'sonnet', 'haiku'];
35
+ }
36
+ case 'qwen':
37
+ return ['coder-model'];
38
+ case 'gemini': {
39
+ const help = execSync('gemini --help 2>/dev/null', { encoding: 'utf-8' });
40
+ const models = help.match(/'([^']+)'/g)?.map((m) => m.replace(/'/g, '')).filter(Boolean);
41
+ if (models?.length)
42
+ return [...new Set(models)];
43
+ return ['gemini-2.5-pro', 'gemini-2.5-flash'];
44
+ }
45
+ case 'codex': {
46
+ const help = execSync('codex --help 2>/dev/null', { encoding: 'utf-8' });
47
+ const models = help.match(/-m\s+(\S+)/g)?.map((m) => m.split(/\s+/)[1]);
48
+ if (models?.length)
49
+ return [...new Set(models)];
50
+ return ['gpt-4o'];
51
+ }
52
+ case 'cn':
53
+ return ['default (hub)'];
54
+ case 'opencode': {
55
+ const out = execSync('opencode models 2>/dev/null', { encoding: 'utf-8' });
56
+ return out.trim().split('\n').filter(Boolean);
57
+ }
58
+ case 'aider':
59
+ return ['default'];
60
+ default:
61
+ return ['default'];
62
+ }
63
+ }
64
+ catch {
65
+ return ['default'];
66
+ }
67
+ }
68
+ function buildCmd(cliName, model) {
69
+ const info = CLI_REGISTRY[cliName];
70
+ if (!info)
71
+ return `${cliName} -m ${model}`;
72
+ if (cliName === 'codex')
73
+ return `codex exec -m ${model}`;
74
+ if (cliName === 'cn' && model === 'default (hub)')
75
+ return 'cn --auto -p';
76
+ const extra = info.extraFlags ? ` ${info.extraFlags}` : '';
77
+ const promptFlag = info.promptFlag ? ` ${info.promptFlag}` : '';
78
+ return `${info.command} ${info.modelFlag} ${model}${extra}${promptFlag}`.trim();
79
+ }
80
+ function numberedSelect(title, options, maxShow = 20) {
81
+ console.log(chalk.bold(` ${title}`));
82
+ console.log(chalk.dim(' ' + '-'.repeat(36)));
83
+ const show = options.slice(0, maxShow);
84
+ show.forEach((opt, i) => {
85
+ console.log(chalk.dim(` ${i + 1}. ${opt}`));
86
+ });
87
+ if (options.length > maxShow) {
88
+ console.log(chalk.dim(` ... and ${options.length - maxShow} more (type name for unlisted)`));
89
+ }
90
+ return show;
91
+ }
92
+ function resolveChoice(input, options) {
93
+ const trimmed = input.trim();
94
+ const num = parseInt(trimmed);
95
+ if (!isNaN(num) && num >= 1 && num <= options.length) {
96
+ return options[num - 1];
97
+ }
98
+ return trimmed;
99
+ }
100
+ // ─── shared helpers ───────────────────────────────────────────────────────────
101
+ async function configureOneRole(rl, role, installed, cliConfig) {
102
+ const current = cliConfig.roles[role];
103
+ console.log(chalk.yellow(`\n ${role.toUpperCase()}${current ? ` [current: ${current.cli}/${current.model}]` : ''}`));
104
+ const cliOptions = numberedSelect(`CLI for ${role}:`, installed.map((c) => c.name));
105
+ const cliChoice = await ask(rl, ` CLI: `);
106
+ const cliName = resolveChoice(cliChoice, cliOptions);
107
+ if (!CLI_REGISTRY[cliName]) {
108
+ console.log(chalk.red(` Unknown CLI: ${cliName}`));
109
+ return false;
110
+ }
111
+ const models = detectModels(cliName);
112
+ const modelOptions = numberedSelect(`Models for ${cliName}:`, models);
113
+ const modelChoice = await ask(rl, ` Model: `);
114
+ cliConfig.roles[role] = {
115
+ cli: cliName,
116
+ model: resolveChoice(modelChoice, modelOptions),
117
+ };
118
+ return true;
119
+ }
120
+ async function persistConfig(cliConfig) {
121
+ await saveCliConfig(cliConfig);
122
+ const projectDir = process.cwd();
123
+ const projectName = path.basename(projectDir);
124
+ const r = cliConfig.roles;
125
+ const agentConfig = {
126
+ project: projectName,
127
+ description: '',
128
+ stack: 'generic',
129
+ roles: {
130
+ orchestrator: { cli: r.orchestrator?.cli || '', model: r.orchestrator?.model || '', cmd: buildCmd(r.orchestrator?.cli || '', r.orchestrator?.model || '') },
131
+ implementor: { cli: r.implementor?.cli || '', model: r.implementor?.model || '', cmd: buildCmd(r.implementor?.cli || '', r.implementor?.model || '') },
132
+ reviewer: { cli: r.reviewer?.cli || '', model: r.reviewer?.model || '', cmd: buildCmd(r.reviewer?.cli || '', r.reviewer?.model || '') },
133
+ ...(r.explorer ? { explorer: { cli: r.explorer.cli, model: r.explorer.model, cmd: buildCmd(r.explorer.cli, r.explorer.model) } } : {}),
134
+ },
135
+ deliberation: cliConfig.deliberation?.enabled ? {
136
+ proposer: { cli: r.proposer?.cli || '', model: r.proposer?.model || '', cmd: buildCmd(r.proposer?.cli || '', r.proposer?.model || '') },
137
+ critic: { cli: r.critic?.cli || '', model: r.critic?.model || '', cmd: buildCmd(r.critic?.cli || '', r.critic?.model || '') },
138
+ max_rounds: cliConfig.deliberation.max_rounds,
139
+ stop_on: 'ACCEPT',
140
+ output_dir: '.agent/tasks/{ID}/debate/',
141
+ } : undefined,
142
+ structure: { approved_dirs: ['.'], forbidden_dirs: ['node_modules', 'dist', '.git'] },
143
+ };
144
+ await ensureDir(path.join(projectDir, '.agent'));
145
+ await writeJson(path.join(projectDir, '.agent', 'config.json'), agentConfig);
146
+ }
147
+ // ─── single-role command factory ──────────────────────────────────────────────
148
+ function addRoleCommand(setup, cmd, role, description) {
149
+ setup
150
+ .command(cmd)
151
+ .description(description)
152
+ .action(async () => {
153
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
154
+ const installed = detectInstalledClis();
155
+ if (installed.length === 0) {
156
+ console.log(chalk.red(' No CLIs detected.'));
157
+ rl.close();
158
+ return;
159
+ }
160
+ const cliConfig = await loadCliConfig();
161
+ const ok = await configureOneRole(rl, role, installed, cliConfig);
162
+ if (ok) {
163
+ await persistConfig(cliConfig);
164
+ console.log(chalk.green(`\n ✓ ${role} updated`));
165
+ }
166
+ rl.close();
167
+ });
168
+ }
169
+ // ─────────────────────────────────────────────────────────────────────────────
170
+ export function setupCommand(program) {
171
+ const setup = program.command('setup')
172
+ .description('Full interactive setup — login, configure CLIs, initialize project');
173
+ setup
174
+ .command('init')
175
+ .description('Interactive setup wizard')
176
+ .action(async () => {
177
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
178
+ console.log(chalk.bold.cyan('\n Agent CLI — Setup Wizard\n'));
179
+ // Step 1: Show installed CLIs
180
+ const installed = detectInstalledClis();
181
+ if (installed.length === 0) {
182
+ console.log(chalk.red(' No CLIs detected. Install at least one.'));
183
+ rl.close();
184
+ return;
185
+ }
186
+ console.log(chalk.bold(' Detected CLIs:'));
187
+ for (const c of installed) {
188
+ log.cliList(c.name, c.path);
189
+ }
190
+ // Step 2: Login
191
+ console.log(chalk.bold('\n Authentication'));
192
+ console.log(chalk.dim(' ' + '-'.repeat(36)));
193
+ const auth = await loadAuth();
194
+ if (auth.entries.length > 0) {
195
+ console.log(chalk.green(` Already logged in: ${auth.entries.map((e) => e.provider).join(', ')}`));
196
+ }
197
+ else {
198
+ const doLogin = await ask(rl, ' Login now? (y/N): ');
199
+ if (doLogin.toLowerCase() === 'y') {
200
+ const provider = await ask(rl, ' Provider (opencode/google): ');
201
+ const method = await ask(rl, ' Method (oauth/apikey): ');
202
+ if (method === 'apikey') {
203
+ const key = await ask(rl, ' API Key: ');
204
+ auth.entries.push({ provider: provider.trim(), method: 'apikey', apiKey: key.trim() });
205
+ }
206
+ else {
207
+ auth.entries.push({ provider: provider.trim(), method: 'oauth' });
208
+ }
209
+ auth.activeProvider = provider.trim();
210
+ await saveAuth(auth);
211
+ console.log(chalk.green(' ✓ Auth saved'));
212
+ }
213
+ }
214
+ // Step 3: Config multi-CLI
215
+ console.log(chalk.bold('\n Multi-CLI Configuration'));
216
+ console.log(chalk.dim(' ' + '-'.repeat(36)));
217
+ const cliConfig = await loadCliConfig();
218
+ const roles = ['orchestrator', 'implementor', 'reviewer'];
219
+ for (const role of roles) {
220
+ console.log(chalk.yellow(`\n ${role.toUpperCase()}`));
221
+ const cliOptions = numberedSelect(`CLI for ${role}:`, installed.map((c) => c.name));
222
+ const cliChoice = await ask(rl, ` CLI: `);
223
+ const cliName = resolveChoice(cliChoice, cliOptions);
224
+ if (!CLI_REGISTRY[cliName]) {
225
+ console.log(chalk.red(` Unknown CLI: ${cliName}`));
226
+ rl.close();
227
+ return;
228
+ }
229
+ const models = detectModels(cliName);
230
+ const modelOptions = numberedSelect(`Models for ${cliName}:`, models);
231
+ const modelChoice = await ask(rl, ` Model: `);
232
+ const model = resolveChoice(modelChoice, modelOptions);
233
+ cliConfig.roles[role] = { cli: cliName, model };
234
+ }
235
+ // Deliberation
236
+ const delib = await ask(rl, '\n Enable deliberation? (y/N): ');
237
+ if (delib.toLowerCase() === 'y') {
238
+ cliConfig.deliberation.enabled = true;
239
+ const rounds = await ask(rl, ' Max rounds [4]: ');
240
+ cliConfig.deliberation.max_rounds = parseInt(rounds) || 4;
241
+ console.log(chalk.yellow('\n PROPOSER'));
242
+ const pp = await ask(rl, ' CLI: ');
243
+ const pm = await ask(rl, ' Model: ');
244
+ cliConfig.roles.proposer = { cli: pp.trim(), model: pm.trim() };
245
+ console.log(chalk.yellow('\n CRITIC'));
246
+ const cp = await ask(rl, ' CLI: ');
247
+ const cm = await ask(rl, ' Model: ');
248
+ cliConfig.roles.critic = { cli: cp.trim(), model: cm.trim() };
249
+ }
250
+ await saveCliConfig(cliConfig);
251
+ console.log(chalk.green('\n ✓ CLI config saved'));
252
+ // Step 4: Generate .agent/config.json
253
+ const projectDir = process.cwd();
254
+ const projectName = path.basename(projectDir);
255
+ const agentConfig = {
256
+ project: projectName,
257
+ description: '',
258
+ stack: 'generic',
259
+ roles: {
260
+ orchestrator: { cli: cliConfig.roles.orchestrator?.cli || '', model: cliConfig.roles.orchestrator?.model || '', cmd: buildCmd(cliConfig.roles.orchestrator?.cli || '', cliConfig.roles.orchestrator?.model || '') },
261
+ implementor: { cli: cliConfig.roles.implementor?.cli || '', model: cliConfig.roles.implementor?.model || '', cmd: buildCmd(cliConfig.roles.implementor?.cli || '', cliConfig.roles.implementor?.model || '') },
262
+ reviewer: { cli: cliConfig.roles.reviewer?.cli || '', model: cliConfig.roles.reviewer?.model || '', cmd: buildCmd(cliConfig.roles.reviewer?.cli || '', cliConfig.roles.reviewer?.model || '') },
263
+ },
264
+ deliberation: cliConfig.deliberation.enabled ? {
265
+ proposer: { cli: cliConfig.roles.proposer?.cli || '', model: cliConfig.roles.proposer?.model || '', cmd: buildCmd(cliConfig.roles.proposer?.cli || '', cliConfig.roles.proposer?.model || '') },
266
+ critic: { cli: cliConfig.roles.critic?.cli || '', model: cliConfig.roles.critic?.model || '', cmd: buildCmd(cliConfig.roles.critic?.cli || '', cliConfig.roles.critic?.model || '') },
267
+ max_rounds: cliConfig.deliberation.max_rounds,
268
+ stop_on: 'ACCEPT',
269
+ output_dir: '.agent/tasks/{ID}/debate/',
270
+ } : undefined,
271
+ structure: { approved_dirs: ['.'], forbidden_dirs: ['node_modules', 'dist', '.git'] },
272
+ };
273
+ await ensureDir(path.join(projectDir, '.agent'));
274
+ await writeJson(path.join(projectDir, '.agent', 'config.json'), agentConfig);
275
+ console.log(chalk.green(' ✓ .agent/config.json generated'));
276
+ // Generate templates
277
+ const templates = {
278
+ '.agent/INDEX.md': `# ${projectName} — Agent Entry Point\n\n> Leé este archivo antes de cualquier accion.\n\n## Proyecto\n\n## Navegacion por rol\n| Si sos... | Lee primero... |\n|-----------|----------------|\n| ORCHESTRATOR | .agent/rules/workflow.md |\n| IMPLEMENTOR | .agent/tasks/{ID}/plan.json |\n| REVIEWER | .agent/rules/workflow.md |\n`,
279
+ '.agent/rules/workflow.md': '# Agent Workflow Contract\n\n## REGLA #1 — Separacion de roles\nUn rol NUNCA ejecuta acciones de otro rol.\n\n## REGLA #2 — Un CLI NO cambia de rol\n\n## Roles\n- ORCHESTRATOR: planifica, genera plan.json\n- IMPLEMENTOR: ejecuta el plan\n- REVIEWER: valida, genera result.md\n',
280
+ '.agent/rules/structure.md': '# Estructura\n\n## Aprobados\n.\n\n## Prohibidos\nnode_modules, dist, .git\n',
281
+ '.agent/rules/patterns.md': '# Patrones\n\n- kebab-case para archivos\n- PascalCase para clases\n- camelCase para variables\n',
282
+ '.agent/context/architecture.md': '# Arquitectura — NIVEL 0\n\n| Servicio | Stack | Puerto | Detalle |\n|----------|-------|--------|---------|\n| - | - | - | - |\n',
283
+ '.agent/AGENT.md': '# Sub-Agentes\n\n1. Lee .agent/INDEX.md\n2. Lee .agent/rules/workflow.md\n3. Actua SOLO dentro de tu rol\n',
284
+ };
285
+ for (const [fp, content] of Object.entries(templates)) {
286
+ await fs.mkdir(path.join(projectDir, path.dirname(fp)), { recursive: true });
287
+ await fs.writeFile(path.join(projectDir, fp), content, 'utf-8');
288
+ }
289
+ console.log(chalk.green(' ✓ Templates generated'));
290
+ rl.close();
291
+ });
292
+ setup
293
+ .command('config-multi')
294
+ .description('Configure multi-CLI agents (orchestrator, implementor, reviewer)')
295
+ .action(async () => {
296
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
297
+ console.log(chalk.bold.cyan('\n Multi-CLI Configuration\n'));
298
+ const installed = detectInstalledClis();
299
+ if (installed.length === 0) {
300
+ console.log(chalk.red(' No CLIs detected.'));
301
+ rl.close();
302
+ return;
303
+ }
304
+ console.log(chalk.bold(' Detected CLIs:'));
305
+ for (const c of installed)
306
+ log.cliList(c.name, c.path);
307
+ const cliConfig = await loadCliConfig();
308
+ const roles = ['orchestrator', 'implementor', 'reviewer'];
309
+ for (const role of roles) {
310
+ const current = cliConfig.roles[role];
311
+ console.log(chalk.yellow(`\n ${role.toUpperCase()}${current ? ` [current: ${current.cli}/${current.model}]` : ''}`));
312
+ const cliOptions = numberedSelect(`CLI for ${role}:`, installed.map((c) => c.name));
313
+ console.log(chalk.dim(' (Enter to keep current)'));
314
+ const cliChoice = await ask(rl, ` CLI: `);
315
+ if (cliChoice.trim() === '' && current) {
316
+ console.log(chalk.dim(` → keeping ${current.cli}/${current.model}`));
317
+ continue;
318
+ }
319
+ const cliName = resolveChoice(cliChoice, cliOptions);
320
+ const models = detectModels(cliName);
321
+ const modelOptions = numberedSelect(`Models for ${cliName}:`, models);
322
+ const modelChoice = await ask(rl, ` Model: `);
323
+ cliConfig.roles[role] = { cli: cliName, model: resolveChoice(modelChoice, modelOptions) };
324
+ }
325
+ await persistConfig(cliConfig);
326
+ console.log(chalk.green('\n ✓ Config updated'));
327
+ rl.close();
328
+ });
329
+ setup
330
+ .command('status')
331
+ .description('Show current configuration')
332
+ .action(async () => {
333
+ const cliConfig = await loadCliConfig();
334
+ const auth = await loadAuth();
335
+ console.log(chalk.bold.cyan('\n Agent CLI Status\n'));
336
+ console.log(chalk.yellow(' Auth:'), auth.entries.map((e) => `${e.provider} (${e.method})`).join(', ') || 'none');
337
+ console.log(chalk.yellow(' Roles:'));
338
+ for (const [role, r] of Object.entries(cliConfig.roles)) {
339
+ console.log(chalk.dim(` ${role}: ${r.cli}/${r.model}`));
340
+ }
341
+ if (cliConfig.deliberation?.enabled) {
342
+ console.log(chalk.yellow(' Deliberation:'), `enabled (${cliConfig.deliberation.max_rounds} rounds)`);
343
+ }
344
+ console.log('');
345
+ });
346
+ // ── individual role commands ──────────────────────────────────────────────
347
+ addRoleCommand(setup, 'orch', 'orchestrator', 'Configure orchestrator role only');
348
+ addRoleCommand(setup, 'impl', 'implementor', 'Configure implementor role only');
349
+ addRoleCommand(setup, 'rev', 'reviewer', 'Configure reviewer role only');
350
+ addRoleCommand(setup, 'explorer', 'explorer', 'Configure explorer role only');
351
+ addRoleCommand(setup, 'proposer', 'proposer', 'Configure proposer role only (deliberation)');
352
+ addRoleCommand(setup, 'critic', 'critic', 'Configure critic role only (deliberation)');
353
+ }
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function statusCommand(program: Command): void;
@@ -0,0 +1,46 @@
1
+ import chalk from 'chalk';
2
+ import { loadProjectConfig } from '../utils/config.js';
3
+ import { readJson, listDir } from '../utils/fs.js';
4
+ import * as path from 'path';
5
+ export function statusCommand(program) {
6
+ program
7
+ .command('status')
8
+ .description('Show project status and task list')
9
+ .action(async () => {
10
+ const dir = process.cwd();
11
+ try {
12
+ const config = await loadProjectConfig(dir);
13
+ console.log(chalk.bold.cyan(`\n ${config.project}`));
14
+ console.log(chalk.dim(` Stack: ${config.stack}`));
15
+ console.log(chalk.dim(' ' + '-'.repeat(36)));
16
+ console.log(chalk.yellow(' Roles:'));
17
+ for (const [role, r] of Object.entries(config.roles)) {
18
+ if (r)
19
+ console.log(chalk.dim(` ${role}: ${r.cli}/${r.model}`));
20
+ }
21
+ const tasksDir = path.join(dir, '.agent', 'tasks');
22
+ const tasks = await listDir(tasksDir);
23
+ if (tasks.length > 0) {
24
+ console.log(chalk.yellow('\n Tasks:'));
25
+ for (const t of tasks.sort().reverse()) {
26
+ try {
27
+ const progress = await readJson(path.join(tasksDir, t, 'progress.json'));
28
+ const s = progress?.status || 'unknown';
29
+ const icon = s === 'completed' ? chalk.green('v') : s === 'planned' ? chalk.yellow('o') : chalk.red('x');
30
+ console.log(` ${icon} ${t} - ${s}`);
31
+ }
32
+ catch {
33
+ console.log(` ? ${t} - unknown`);
34
+ }
35
+ }
36
+ }
37
+ else {
38
+ console.log(chalk.dim('\n No tasks yet'));
39
+ }
40
+ console.log('');
41
+ }
42
+ catch {
43
+ console.log(chalk.red(' No .agent/config.json found. Run: agent-mp setup init'));
44
+ }
45
+ });
46
+ }
@@ -0,0 +1,36 @@
1
+ import * as readline from 'readline';
2
+ import { AgentConfig, TaskPlan, TaskProgress } from '../types.js';
3
+ import type { FixedInput } from '../ui/input.js';
4
+ export declare class AgentEngine {
5
+ private config;
6
+ private projectDir;
7
+ private coordinatorCmd;
8
+ private rl?;
9
+ private fi?;
10
+ private totalTokens;
11
+ private phaseTokens;
12
+ constructor(config: AgentConfig, projectDir: string, coordinatorCmd?: string, rl?: readline.Interface, fi?: FixedInput);
13
+ /**
14
+ * FASE 0 — Clarificacion con el programador.
15
+ * El coordinador (CLI activo, ej: Qwen) conversa con el usuario
16
+ * hasta tener toda la info necesaria. Retorna la tarea refinada.
17
+ */
18
+ runClarification(initialTask: string): Promise<string>;
19
+ private runWithFallback;
20
+ private buildRolePrompt;
21
+ generateTaskId(task: string): Promise<string>;
22
+ /** Context for the ORCHESTRATOR only — planning-relevant files */
23
+ private buildOrchestratorContext;
24
+ /** Minimal context for COORDINATOR clarification only */
25
+ private buildCoordinatorContext;
26
+ runOrchestrator(task: string): Promise<{
27
+ taskId: string;
28
+ plan: TaskPlan;
29
+ }>;
30
+ runDeliberation(taskId: string, plan: TaskPlan): Promise<void>;
31
+ runImplementor(taskId: string, plan: TaskPlan): Promise<TaskProgress>;
32
+ runReviewer(taskId: string, plan: TaskPlan, progress: TaskProgress): Promise<{
33
+ verdict: string;
34
+ }>;
35
+ runFullCycle(task: string): Promise<void>;
36
+ }