agent-mp 0.4.10 → 0.4.12

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.
@@ -10,7 +10,7 @@ import { writeJson, ensureDir, readJson, listDir, fileExists } from '../utils/fs
10
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
- import { qwenAuthStatus, QWEN_AGENT_HOME, fetchQwenModels } from '../utils/qwen-auth.js';
13
+ import { qwenLogin, qwenAuthStatus, QWEN_AGENT_HOME, fetchQwenModels } from '../utils/qwen-auth.js';
14
14
  import { renderWelcomePanel, renderHelpHint, renderSectionBox, renderMultiSectionBox } from '../ui/theme.js';
15
15
  import { FixedInput } from '../ui/input.js';
16
16
  import { newSession, saveSession } from '../utils/sessions.js';
@@ -258,42 +258,18 @@ function buildCmd(cliName, model) {
258
258
  }
259
259
  async function cmdLogin(rl) {
260
260
  console.log(chalk.bold.cyan('\n Login\n'));
261
- // If active provider is Qwen, do fresh OAuth for corporate account
261
+ // If active provider is Qwen, use built-in OAuth device flow (no qwen CLI needed)
262
262
  const auth = await loadAuth();
263
263
  if (auth.activeProvider === 'qwen') {
264
- console.log(chalk.dim(' Qwen login for corporate account\n'));
265
- console.log(chalk.dim(' Corporate credentials stored in: ~/.agent-cli/\n'));
266
- console.log(chalk.yellow(' IMPORTANT: Use your CORPORATE account when prompted.\n'));
267
- console.log(chalk.yellow(' The browser will open. If you see your personal account,'));
268
- console.log(chalk.yellow(' log out and sign in with your corporate account.\n'));
264
+ console.log(chalk.dim(` Credentials will be saved to: ${QWEN_AGENT_HOME}/\n`));
269
265
  try {
270
- const { execSync } = await import('child_process');
271
- const personalCreds = path.join(os.homedir(), '.qwen', 'oauth_creds.json');
272
- const corporateCreds = path.join(QWEN_AGENT_HOME, 'oauth_creds.json');
273
- // Backup personal credentials
274
- let personalBackup = null;
275
- if (await fileExists(personalCreds)) {
276
- personalBackup = await fs.readFile(personalCreds, 'utf-8');
277
- await fs.unlink(personalCreds);
278
- }
279
- // Remove corporate creds to force fresh login
280
- await fs.unlink(corporateCreds).catch(() => { });
281
- // Login with Qwen CLI - forces fresh login since personal creds are backed up
282
- execSync('qwen auth qwen-oauth', { stdio: 'inherit' });
283
- // Copy NEW credentials to corporate directory
284
- if (await fileExists(personalCreds)) {
285
- const newCreds = await fs.readFile(personalCreds, 'utf-8');
286
- await fs.writeFile(corporateCreds, newCreds);
287
- }
288
- // Restore personal credentials
289
- if (personalBackup) {
290
- await fs.writeFile(personalCreds, personalBackup);
291
- }
266
+ const success = await qwenLogin();
267
+ if (!success)
268
+ return false;
292
269
  const emailInput = await ask(rl, ' Your email (optional, for display): ');
293
270
  auth.entries = auth.entries.filter((e) => e.provider !== 'qwen');
294
271
  auth.entries.push({ provider: 'qwen', method: 'oauth', ...(emailInput.trim() ? { email: emailInput.trim() } : {}) });
295
272
  await saveAuth(auth);
296
- console.log(chalk.green(' Corporate auth recorded'));
297
273
  return true;
298
274
  }
299
275
  catch (err) {
@@ -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 { callQwenAPI, callQwenAPIFromCreds } from '../utils/qwen-auth.js';
9
+ import { 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 {
@@ -89,12 +89,9 @@ async function ask(prompt, rl, fi) {
89
89
  return new Promise((resolve) => tempRl.question(prompt, (a) => { tempRl.close(); resolve(a); }));
90
90
  }
91
91
  function runCli(cmd, prompt, timeoutMs = 600000, envOverride, onData) {
92
- // Si el comando es "qwen-direct", usar la API directa sin CLI
92
+ // Si el comando es "qwen-direct", redirigir a qwen CLI subprocess
93
93
  if (cmd.startsWith('qwen-direct')) {
94
- const model = cmd.includes('-m') ? cmd.split('-m')[1]?.trim().split(/\s/)[0] : 'coder-model';
95
- return callQwenAPI(prompt, model)
96
- .then(output => ({ output, exitCode: 0 }))
97
- .catch(err => ({ output: `Error: ${err.message}`, exitCode: 1 }));
94
+ return runCli('qwen --yolo', prompt, timeoutMs, envOverride, onData);
98
95
  }
99
96
  return new Promise((resolve, reject) => {
100
97
  const parts = cmd.trim().split(/\s+/);
@@ -300,24 +297,18 @@ INSTRUCCIONES:
300
297
  const envOverride = {};
301
298
  let res;
302
299
  if (this.coordinatorCmd.startsWith('qwen')) {
303
- // Use Qwen API directlyavoids the qwen CLI's own OAuth flow
304
- // which causes mid-session auth popups and breaks display.
305
- const model = this.coordinatorCmd.match(/(?:-m|--model)\s+(\S+)/)?.[1] || 'coder-model';
306
- const sp = this._startSpinner(`coordinador ${model}`);
300
+ // Use qwen CLI subprocessdirect API calls fail with 401 for OAuth tokens
301
+ const coCmd = this.coordinatorCmd.includes('--yolo') ? this.coordinatorCmd : `${this.coordinatorCmd} --yolo`;
302
+ const sp = this._startSpinner(`coordinador`);
307
303
  try {
308
- const result = await callQwenAPI(prompt, model, (c) => this._parseChunk(c).forEach(l => sp.push(l)));
304
+ res = await runCli(coCmd, prompt, 600000, envOverride, (chunk) => {
305
+ this._parseChunk(chunk).forEach(l => sp.push(l));
306
+ });
309
307
  sp.stop();
310
- return result;
311
308
  }
312
309
  catch (err) {
313
310
  sp.stop();
314
- if (err.message?.startsWith('QWEN_AUTH_EXPIRED')) {
315
- console.log(chalk.red('\n ✗ Sesión Qwen expirada.'));
316
- console.log(chalk.yellow(' Ejecutá: /login para re-autenticarte.\n'));
317
- }
318
- else {
319
- console.log(chalk.red(`\n ✗ Error Qwen: ${err.message}`));
320
- }
311
+ console.log(chalk.red(`\n ✗ Error coordinador: ${err.message}`));
321
312
  return '';
322
313
  }
323
314
  }
@@ -583,28 +574,19 @@ INSTRUCCIONES:
583
574
  }
584
575
  }
585
576
  }
586
- // Try global fallback — use callQwenAPI directly for streaming (no subprocess)
577
+ // Try global fallback — use CLI subprocess (direct API calls fail with 401 for OAuth tokens)
587
578
  if (this.config.fallback_global) {
588
579
  const fb = this.config.fallback_global;
589
580
  log.warn(`Using global fallback: ${fb.cli} (${fb.model})`);
590
581
  const sp = this._startSpinner(`${fb.cli} ${fb.model} (fallback)`);
591
- let lineBuf = '';
592
- const onChunk = (delta) => {
593
- lineBuf += delta;
594
- const lines = lineBuf.split('\n');
595
- lineBuf = lines.pop() || '';
596
- for (const l of lines) {
597
- if (l.trim())
598
- sp.push(l.trim());
599
- }
600
- };
601
582
  try {
602
- const globalResult = await callQwenAPI(rolePrompt, fb.model, onChunk);
603
- if (lineBuf.trim())
604
- sp.push(lineBuf.trim());
583
+ const fbCmd = fb.cli.includes('--yolo') ? fb.cli : `${fb.cli} --yolo`;
584
+ const globalResult = await runCli(fbCmd, rolePrompt, 600000, undefined, (chunk) => {
585
+ this._parseChunk(chunk).forEach(l => sp.push(l));
586
+ });
605
587
  sp.stop();
606
- trackTokens(globalResult, fb.cli, fb.model);
607
- return globalResult;
588
+ trackTokens(globalResult.output, fb.cli, fb.model);
589
+ return globalResult.output;
608
590
  }
609
591
  catch (err) {
610
592
  sp.stop();
@@ -1061,17 +1043,17 @@ REGLAS:
1061
1043
  let result;
1062
1044
  const sp = this._startSpinner(`agent-explorer ${role.model}`);
1063
1045
  try {
1064
- result = await callQwenAPI(prompt, role.model, (c) => this._parseChunk(c).forEach(l => sp.push(l)));
1046
+ // Use qwen CLI subprocess direct API calls fail with 401 for OAuth tokens
1047
+ const explorerCliRes = await runCli('qwen --yolo', prompt, 600000, undefined, (chunk) => {
1048
+ this._parseChunk(chunk).forEach(l => sp.push(l));
1049
+ });
1050
+ result = explorerCliRes.output;
1065
1051
  sp.stop();
1066
1052
  }
1067
1053
  catch (err) {
1068
1054
  sp.stop();
1069
- if (err.message?.startsWith('QWEN_AUTH_EXPIRED')) {
1070
- console.log(chalk.red('\n ✗ Sesión Qwen expirada.'));
1071
- console.log(chalk.yellow(' Ejecutá: agent-mp --login (o agent-explorer --login)\n'));
1072
- return '';
1073
- }
1074
- throw err;
1055
+ console.log(chalk.red(`\n ✗ Error explorer: ${err.message}`));
1056
+ return '';
1075
1057
  }
1076
1058
  try {
1077
1059
  await writeFile(path.join(contextDir, 'explorer-last.md'), `# Explorer Report\n\nTask: ${effectiveTask}\nDate: ${new Date().toISOString()}\n\n${result}\n`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-mp",
3
- "version": "0.4.10",
3
+ "version": "0.4.12",
4
4
  "description": "Deterministic multi-agent CLI orchestrator — plan, code, review",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",