agent-mp 0.4.12 → 0.4.13

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.
@@ -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 { callQwenAPIFromCreds } from '../utils/qwen-auth.js';
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 {
@@ -89,9 +89,12 @@ 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", redirigir a qwen CLI subprocess
92
+ // Si el comando es "qwen-direct", usar la API directa sin CLI
93
93
  if (cmd.startsWith('qwen-direct')) {
94
- return runCli('qwen --yolo', prompt, timeoutMs, envOverride, onData);
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 }));
95
98
  }
96
99
  return new Promise((resolve, reject) => {
97
100
  const parts = cmd.trim().split(/\s+/);
@@ -297,18 +300,24 @@ INSTRUCCIONES:
297
300
  const envOverride = {};
298
301
  let res;
299
302
  if (this.coordinatorCmd.startsWith('qwen')) {
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`);
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}`);
303
307
  try {
304
- res = await runCli(coCmd, prompt, 600000, envOverride, (chunk) => {
305
- this._parseChunk(chunk).forEach(l => sp.push(l));
306
- });
308
+ const result = await callQwenAPI(prompt, model, (c) => this._parseChunk(c).forEach(l => sp.push(l)));
307
309
  sp.stop();
310
+ return result;
308
311
  }
309
312
  catch (err) {
310
313
  sp.stop();
311
- console.log(chalk.red(`\n ✗ Error coordinador: ${err.message}`));
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
+ }
312
321
  return '';
313
322
  }
314
323
  }
@@ -574,19 +583,28 @@ INSTRUCCIONES:
574
583
  }
575
584
  }
576
585
  }
577
- // Try global fallback — use CLI subprocess (direct API calls fail with 401 for OAuth tokens)
586
+ // Try global fallback — use callQwenAPI directly for streaming (no subprocess)
578
587
  if (this.config.fallback_global) {
579
588
  const fb = this.config.fallback_global;
580
589
  log.warn(`Using global fallback: ${fb.cli} (${fb.model})`);
581
590
  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
+ };
582
601
  try {
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
- });
602
+ const globalResult = await callQwenAPI(rolePrompt, fb.model, onChunk);
603
+ if (lineBuf.trim())
604
+ sp.push(lineBuf.trim());
587
605
  sp.stop();
588
- trackTokens(globalResult.output, fb.cli, fb.model);
589
- return globalResult.output;
606
+ trackTokens(globalResult, fb.cli, fb.model);
607
+ return globalResult;
590
608
  }
591
609
  catch (err) {
592
610
  sp.stop();
@@ -1043,17 +1061,17 @@ REGLAS:
1043
1061
  let result;
1044
1062
  const sp = this._startSpinner(`agent-explorer ${role.model}`);
1045
1063
  try {
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;
1064
+ result = await callQwenAPI(prompt, role.model, (c) => this._parseChunk(c).forEach(l => sp.push(l)));
1051
1065
  sp.stop();
1052
1066
  }
1053
1067
  catch (err) {
1054
1068
  sp.stop();
1055
- console.log(chalk.red(`\n ✗ Error explorer: ${err.message}`));
1056
- return '';
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;
1057
1075
  }
1058
1076
  try {
1059
1077
  await writeFile(path.join(contextDir, 'explorer-last.md'), `# Explorer Report\n\nTask: ${effectiveTask}\nDate: ${new Date().toISOString()}\n\n${result}\n`);
@@ -235,7 +235,8 @@ export async function fetchQwenModels() {
235
235
  if (!token)
236
236
  return [];
237
237
  try {
238
- const res = await fetch('https://chat.qwen.ai/api/models', {
238
+ const host = token.resourceUrl ? `https://${token.resourceUrl}` : 'https://chat.qwen.ai';
239
+ const res = await fetch(`${host}/api/models`, {
239
240
  headers: { Authorization: `Bearer ${token.accessToken}` },
240
241
  });
241
242
  if (!res.ok)
@@ -252,17 +253,35 @@ export async function getQwenAccessToken() {
252
253
  return token?.accessToken || null;
253
254
  }
254
255
  async function callQwenAPIWithToken(token, prompt, model, onData) {
255
- const baseUrl = 'https://chat.qwen.ai/api/v1';
256
+ // Use resource_url from token (e.g. "portal.qwen.ai"), fallback to DashScope
257
+ const rawHost = token.resourceUrl || 'dashscope.aliyuncs.com/compatible-mode';
258
+ const host = rawHost.startsWith('http') ? rawHost : `https://${rawHost}`;
259
+ const baseUrl = host.endsWith('/v1') ? host : `${host}/v1`;
256
260
  const useStream = !!onData;
261
+ const userAgent = `QwenCode/0.14.2 (${process.platform}; ${process.arch})`;
262
+ // portal.qwen.ai requires content parts format (plain strings return 400)
263
+ const toContentParts = (text) => [{ type: 'text', text }];
257
264
  const response = await fetch(`${baseUrl}/chat/completions`, {
258
265
  method: 'POST',
259
266
  headers: {
260
267
  'Authorization': `Bearer ${token.accessToken}`,
261
268
  'Content-Type': 'application/json',
269
+ 'Accept': 'application/json',
270
+ 'User-Agent': userAgent,
271
+ 'x-dashscope-authtype': 'qwen-oauth',
272
+ 'x-dashscope-cachecontrol': 'enable',
273
+ 'x-dashscope-useragent': userAgent,
274
+ 'x-stainless-lang': 'js',
275
+ 'x-stainless-package-version': '5.11.0',
276
+ 'x-stainless-os': process.platform,
277
+ 'x-stainless-arch': process.arch,
278
+ 'x-stainless-runtime': 'node',
279
+ 'x-stainless-runtime-version': process.version,
280
+ 'x-stainless-retry-count': '0',
262
281
  },
263
282
  body: JSON.stringify({
264
283
  model: model || 'coder-model',
265
- messages: [{ role: 'user', content: prompt }],
284
+ messages: [{ role: 'user', content: toContentParts(prompt) }],
266
285
  stream: useStream,
267
286
  }),
268
287
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-mp",
3
- "version": "0.4.12",
3
+ "version": "0.4.13",
4
4
  "description": "Deterministic multi-agent CLI orchestrator — plan, code, review",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",