agent-mp 0.4.7 → 0.4.9

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.
@@ -521,17 +521,28 @@ INSTRUCCIONES:
521
521
  return null;
522
522
  }
523
523
  const sp = this._startSpinner(`${cliName} ${model}`);
524
+ let lineBuf = '';
525
+ const onChunk = (delta) => {
526
+ lineBuf += delta;
527
+ const lines = lineBuf.split('\n');
528
+ lineBuf = lines.pop() || '';
529
+ for (const l of lines) {
530
+ if (l.trim())
531
+ sp.push(l.trim());
532
+ }
533
+ };
524
534
  try {
525
535
  log.info(`${cliName}: calling Qwen API with own credentials (${model})`);
526
- const result = await callQwenAPIFromCreds(rolePrompt, model, credsPath, (c) => this._parseChunk(c).forEach(l => sp.push(l)));
536
+ const result = await callQwenAPIFromCreds(rolePrompt, model, credsPath, onChunk);
537
+ if (lineBuf.trim())
538
+ sp.push(lineBuf.trim());
527
539
  sp.stop();
528
540
  return result;
529
541
  }
530
542
  catch (err) {
531
543
  sp.stop();
532
544
  if (err.message?.startsWith('QWEN_AUTH_EXPIRED')) {
533
- console.log(chalk.red(`\n ✗ Sesión expirada para ${cliName}.`));
534
- console.log(chalk.yellow(` Ejecutá: ${cliName} --login\n`));
545
+ log.warn(`${cliName} session expired using fallback`);
535
546
  return null;
536
547
  }
537
548
  log.warn(`${cliName} direct API call failed: ${err.message}`);
@@ -572,15 +583,33 @@ INSTRUCCIONES:
572
583
  }
573
584
  }
574
585
  }
575
- // Try global fallback
586
+ // Try global fallback — use callQwenAPI directly for streaming (no subprocess)
576
587
  if (this.config.fallback_global) {
577
588
  const fb = this.config.fallback_global;
578
- log.warn(`Trying global fallback: ${fb.cli} (${fb.model})`);
579
- const globalResult = await tryWithAutoRepair(fb.cli, fb.model, fb.cmd);
580
- if (globalResult !== null) {
589
+ log.warn(`Using global fallback: ${fb.cli} (${fb.model})`);
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
+ };
601
+ try {
602
+ const globalResult = await callQwenAPI(rolePrompt, fb.model, onChunk);
603
+ if (lineBuf.trim())
604
+ sp.push(lineBuf.trim());
605
+ sp.stop();
581
606
  trackTokens(globalResult, fb.cli, fb.model);
582
607
  return globalResult;
583
608
  }
609
+ catch (err) {
610
+ sp.stop();
611
+ log.warn(`Global fallback failed: ${err.message}`);
612
+ }
584
613
  }
585
614
  // All options exhausted
586
615
  throw new Error(`${roleName} failed: primary + individual fallback + global fallback all failed`);
@@ -791,12 +820,16 @@ contenido completo del archivo aqui
791
820
  }
792
821
  const now = new Date().toISOString();
793
822
  if (fileBlocks.length > 0) {
823
+ const sp = this._startSpinner(`Escribiendo ${fileBlocks.length} archivo(s)`);
794
824
  for (const { relPath, content } of fileBlocks) {
825
+ // Strip markdown code fences the LLM may have wrapped around content
826
+ const clean = content.replace(/^```[\w]*\n/, '').replace(/\n```$/, '');
827
+ sp.push(relPath);
795
828
  const absPath = path.join(this.projectDir, relPath);
796
829
  await fs.mkdir(path.dirname(absPath), { recursive: true });
797
- await writeFile(absPath, content);
798
- log.ok(` Creado: ${relPath}`);
830
+ await writeFile(absPath, clean);
799
831
  }
832
+ sp.stop();
800
833
  log.ok(`${fileBlocks.length} archivo(s) implementado(s)`);
801
834
  }
802
835
  else {
@@ -225,6 +225,9 @@ export async function qwenAuthStatus() {
225
225
  const token = await loadToken();
226
226
  if (!token)
227
227
  return { authenticated: false };
228
+ // Verify token is not expired (loadToken already refreshes if close to expiry)
229
+ if (token.expiresAt > 0 && token.expiresAt < Date.now())
230
+ return { authenticated: false };
228
231
  return { authenticated: true };
229
232
  }
230
233
  export async function fetchQwenModels() {
@@ -232,7 +235,8 @@ export async function fetchQwenModels() {
232
235
  if (!token)
233
236
  return [];
234
237
  try {
235
- 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`, {
236
240
  headers: { Authorization: `Bearer ${token.accessToken}` },
237
241
  });
238
242
  if (!res.ok)
@@ -249,7 +253,8 @@ export async function getQwenAccessToken() {
249
253
  return token?.accessToken || null;
250
254
  }
251
255
  async function callQwenAPIWithToken(token, prompt, model, onData) {
252
- const baseUrl = 'https://chat.qwen.ai/api/v1';
256
+ const host = token.resourceUrl ? `https://${token.resourceUrl}` : 'https://chat.qwen.ai';
257
+ const baseUrl = `${host}/api/v1`;
253
258
  const useStream = !!onData;
254
259
  const response = await fetch(`${baseUrl}/chat/completions`, {
255
260
  method: 'POST',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-mp",
3
- "version": "0.4.7",
3
+ "version": "0.4.9",
4
4
  "description": "Deterministic multi-agent CLI orchestrator — plan, code, review",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",