agent-rev 0.3.1 → 0.3.2
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 +3 -12
- package/dist/core/engine.js +63 -63
- package/package.json +1 -1
package/dist/commands/repl.js
CHANGED
|
@@ -7,7 +7,7 @@ import chalk from 'chalk';
|
|
|
7
7
|
import { execSync } from 'child_process';
|
|
8
8
|
import { CLI_REGISTRY } from '../types.js';
|
|
9
9
|
import { writeJson, ensureDir, readJson, listDir, fileExists } from '../utils/fs.js';
|
|
10
|
-
import { loadAuth, saveAuth, loadCliConfig, saveCliConfig, loadProjectConfig
|
|
10
|
+
import { loadAuth, saveAuth, loadCliConfig, saveCliConfig, loadProjectConfig } from '../utils/config.js';
|
|
11
11
|
import { log } from '../utils/logger.js';
|
|
12
12
|
import { AgentEngine, ExitError } from '../core/engine.js';
|
|
13
13
|
import { qwenAuthStatus, QWEN_AGENT_HOME, fetchQwenModels } from '../utils/qwen-auth.js';
|
|
@@ -1227,17 +1227,8 @@ export async function runRole(role, arg, model) {
|
|
|
1227
1227
|
}
|
|
1228
1228
|
case 'explorer':
|
|
1229
1229
|
case 'exp': {
|
|
1230
|
-
const
|
|
1231
|
-
|
|
1232
|
-
// This binary IS the configured explorer CLI — avoid recursion.
|
|
1233
|
-
// Call Qwen API directly using own credentials.
|
|
1234
|
-
const result = await engine.runExplorerDirect(arg || undefined);
|
|
1235
|
-
console.log(result);
|
|
1236
|
-
}
|
|
1237
|
-
else {
|
|
1238
|
-
const result = await engine.runExplorer(arg || undefined);
|
|
1239
|
-
console.log(result);
|
|
1240
|
-
}
|
|
1230
|
+
const result = await engine.runExplorer(arg || undefined);
|
|
1231
|
+
console.log(result);
|
|
1241
1232
|
break;
|
|
1242
1233
|
}
|
|
1243
1234
|
case 'coordinator':
|
package/dist/core/engine.js
CHANGED
|
@@ -6,7 +6,7 @@ import { CLI_REGISTRY } from '../types.js';
|
|
|
6
6
|
import { writeJson, readJson, fileExists, writeFile, readFile } from '../utils/fs.js';
|
|
7
7
|
import { log } from '../utils/logger.js';
|
|
8
8
|
import chalk from 'chalk';
|
|
9
|
-
import {
|
|
9
|
+
import { callQwenAPI, callQwenAPIFromCreds } from '../utils/qwen-auth.js';
|
|
10
10
|
import * as fs from 'fs/promises';
|
|
11
11
|
/** Thrown when a slash command inside a conversation requests exit */
|
|
12
12
|
export class ExitError extends Error {
|
|
@@ -251,55 +251,45 @@ INSTRUCCIONES:
|
|
|
251
251
|
const envOverride = {};
|
|
252
252
|
let res;
|
|
253
253
|
if (this.coordinatorCmd.startsWith('qwen')) {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
let corporateCredsContent = null;
|
|
254
|
+
// Use Qwen API directly — avoids the qwen CLI's own OAuth flow
|
|
255
|
+
// which causes mid-session auth popups and breaks display.
|
|
257
256
|
try {
|
|
258
|
-
|
|
257
|
+
const model = this.coordinatorCmd.match(/(?:-m|--model)\s+(\S+)/)?.[1] || 'coder-model';
|
|
258
|
+
return await callQwenAPI(prompt, model);
|
|
259
259
|
}
|
|
260
|
-
catch {
|
|
261
|
-
console.log(chalk.red(
|
|
260
|
+
catch (err) {
|
|
261
|
+
console.log(chalk.red(`\n ✗ Error de autenticación Qwen: ${err.message}`));
|
|
262
262
|
console.log(chalk.yellow(' Ejecutá /login para autenticarte.\n'));
|
|
263
263
|
return '';
|
|
264
264
|
}
|
|
265
|
-
let personalBackup = null;
|
|
266
|
-
try {
|
|
267
|
-
personalBackup = await fs.readFile(personalCreds, 'utf-8');
|
|
268
|
-
}
|
|
269
|
-
catch { }
|
|
270
|
-
await fs.writeFile(personalCreds, corporateCredsContent);
|
|
271
|
-
res = await runCli(this.coordinatorCmd, prompt, 600000, envOverride);
|
|
272
|
-
if (personalBackup) {
|
|
273
|
-
await fs.writeFile(personalCreds, personalBackup);
|
|
274
|
-
}
|
|
275
|
-
else {
|
|
276
|
-
await fs.unlink(personalCreds).catch(() => { });
|
|
277
|
-
}
|
|
278
265
|
}
|
|
279
266
|
else {
|
|
280
267
|
res = await runCli(this.coordinatorCmd, prompt, 600000, envOverride);
|
|
281
268
|
}
|
|
282
|
-
// Extract readable text
|
|
269
|
+
// Extract readable text — search for JSON array even if there's prefix text
|
|
283
270
|
let responseText = res.output.trim();
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
if (item.type === 'assistant' && item.message?.content?.length > 0) {
|
|
293
|
-
const t = item.message.content.find((c) => c.type === 'text');
|
|
294
|
-
if (t?.text) {
|
|
295
|
-
responseText = t.text;
|
|
271
|
+
const arrayStart = res.output.indexOf('[{');
|
|
272
|
+
if (arrayStart !== -1) {
|
|
273
|
+
try {
|
|
274
|
+
const json = JSON.parse(res.output.slice(arrayStart));
|
|
275
|
+
if (Array.isArray(json)) {
|
|
276
|
+
for (const item of json) {
|
|
277
|
+
if (item.type === 'result' && typeof item.result === 'string') {
|
|
278
|
+
responseText = item.result;
|
|
296
279
|
break;
|
|
297
280
|
}
|
|
281
|
+
if (item.type === 'assistant' && item.message?.content?.length > 0) {
|
|
282
|
+
const t = item.message.content.find((c) => c.type === 'text');
|
|
283
|
+
if (t?.text) {
|
|
284
|
+
responseText = t.text;
|
|
285
|
+
break;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
298
288
|
}
|
|
299
289
|
}
|
|
300
290
|
}
|
|
291
|
+
catch { }
|
|
301
292
|
}
|
|
302
|
-
catch { }
|
|
303
293
|
return responseText;
|
|
304
294
|
};
|
|
305
295
|
// Clarification loop — coordinator is only called when there is new user input
|
|
@@ -446,14 +436,34 @@ INSTRUCCIONES:
|
|
|
446
436
|
}
|
|
447
437
|
}
|
|
448
438
|
};
|
|
449
|
-
// Role binaries (agent-orch, agent-impl, etc.)
|
|
450
|
-
//
|
|
451
|
-
//
|
|
439
|
+
// Role binaries (agent-orch, agent-impl, etc.) require an interactive TTY and can't
|
|
440
|
+
// be spawned as subprocesses. Instead, if they have their own Qwen credentials
|
|
441
|
+
// (~/.agent-<name>/oauth_creds.json from running `agent-<name> --login`), call
|
|
442
|
+
// the Qwen API directly with those creds. Otherwise skip to fallback.
|
|
452
443
|
const ROLE_BINARIES = new Set(['agent-orch', 'agent-impl', 'agent-rev', 'agent-explorer']);
|
|
444
|
+
const tryRoleBinaryCreds = async (cliName, model) => {
|
|
445
|
+
const credsPath = path.join(os.homedir(), `.${cliName}`, 'oauth_creds.json');
|
|
446
|
+
if (!(await fileExists(credsPath))) {
|
|
447
|
+
log.warn(`${cliName} has no credentials — run: ${cliName} --login`);
|
|
448
|
+
return null;
|
|
449
|
+
}
|
|
450
|
+
try {
|
|
451
|
+
log.info(`${cliName}: calling Qwen API with own credentials (${model})`);
|
|
452
|
+
return await callQwenAPIFromCreds(rolePrompt, model, credsPath);
|
|
453
|
+
}
|
|
454
|
+
catch (err) {
|
|
455
|
+
log.warn(`${cliName} direct API call failed: ${err.message}`);
|
|
456
|
+
return null;
|
|
457
|
+
}
|
|
458
|
+
};
|
|
453
459
|
// Try primary
|
|
454
460
|
log.info(`Launching ${roleName}: ${role.cli} (${role.model})`);
|
|
455
461
|
if (ROLE_BINARIES.has(role.cli)) {
|
|
456
|
-
|
|
462
|
+
const directResult = await tryRoleBinaryCreds(role.cli, role.model);
|
|
463
|
+
if (directResult !== null) {
|
|
464
|
+
trackTokens(directResult, role.cli, role.model);
|
|
465
|
+
return directResult;
|
|
466
|
+
}
|
|
457
467
|
}
|
|
458
468
|
else {
|
|
459
469
|
const primaryResult = await tryWithAutoRepair(role.cli, role.model, role.cmd);
|
|
@@ -463,12 +473,21 @@ INSTRUCCIONES:
|
|
|
463
473
|
}
|
|
464
474
|
}
|
|
465
475
|
// Try individual fallback
|
|
466
|
-
if (role.fallback
|
|
476
|
+
if (role.fallback) {
|
|
467
477
|
log.warn(`Trying individual fallback for ${roleName}: ${role.fallback.cli} (${role.fallback.model})`);
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
478
|
+
if (ROLE_BINARIES.has(role.fallback.cli)) {
|
|
479
|
+
const directResult = await tryRoleBinaryCreds(role.fallback.cli, role.fallback.model);
|
|
480
|
+
if (directResult !== null) {
|
|
481
|
+
trackTokens(directResult, role.fallback.cli, role.fallback.model);
|
|
482
|
+
return directResult;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
else {
|
|
486
|
+
const fallbackResult = await tryWithAutoRepair(role.fallback.cli, role.fallback.model, role.fallback.cmd);
|
|
487
|
+
if (fallbackResult !== null) {
|
|
488
|
+
trackTokens(fallbackResult, role.fallback.cli, role.fallback.model);
|
|
489
|
+
return fallbackResult;
|
|
490
|
+
}
|
|
472
491
|
}
|
|
473
492
|
}
|
|
474
493
|
// Try global fallback
|
|
@@ -783,26 +802,7 @@ REGLAS:
|
|
|
783
802
|
- NO modifiques archivos de aplicacion (solo .agent/context/)
|
|
784
803
|
- NO ejecutes comandos que cambien estado (npm install, migraciones, etc.)
|
|
785
804
|
- Si un directorio esta en node_modules, dist, .git: ignoralo`;
|
|
786
|
-
const
|
|
787
|
-
let res;
|
|
788
|
-
if (ROLE_BINS.has(this.config.roles.explorer.cli)) {
|
|
789
|
-
// Spawn the role binary as a separate process with its own credentials.
|
|
790
|
-
// Pass only the short task — the binary builds its own full prompt internally.
|
|
791
|
-
const explorerRole = this.config.roles.explorer;
|
|
792
|
-
const spawnCmd = `${explorerRole.cli} --model ${explorerRole.model}`;
|
|
793
|
-
log.info(`Spawning ${explorerRole.cli} (${explorerRole.model}) as separate process`);
|
|
794
|
-
const result = await runCli(spawnCmd, effectiveTask);
|
|
795
|
-
if (result.exitCode !== 0) {
|
|
796
|
-
log.warn(`${explorerRole.cli} exited with code ${result.exitCode} — trying fallback`);
|
|
797
|
-
res = await this.runWithFallback('explorer', prompt, 'Exploracion');
|
|
798
|
-
}
|
|
799
|
-
else {
|
|
800
|
-
res = result.output;
|
|
801
|
-
}
|
|
802
|
-
}
|
|
803
|
-
else {
|
|
804
|
-
res = await this.runWithFallback('explorer', prompt, 'Exploracion');
|
|
805
|
-
}
|
|
805
|
+
const res = await this.runWithFallback('explorer', prompt, 'Exploracion');
|
|
806
806
|
const text = extractCliText(res);
|
|
807
807
|
// Always save a timestamped explorer report
|
|
808
808
|
try {
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"agent-rev","version":"0.3.
|
|
1
|
+
{"name":"agent-rev","version":"0.3.2","description":"agent-rev agent","type":"module","main":"./dist/index.js","files":["dist/"],"bin":{"agent-rev":"dist/index.js"},"scripts":{"build":"tsc"},"keywords":["ai","agent","cli"],"license":"MIT","dependencies":{"@anthropic-ai/sdk":"^0.39.0","@google/generative-ai":"^0.24.0","chalk":"^5.4.1","commander":"^13.1.0","open":"^11.0.0","openai":"^4.91.0"},"engines":{"node":">=18.0.0"}}
|