agent-rev 0.3.5 → 0.3.6

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,6 +10,17 @@ export declare function qwenAuthStatus(): Promise<{
10
10
  }>;
11
11
  export declare function fetchQwenModels(): Promise<string[]>;
12
12
  export declare function getQwenAccessToken(): Promise<string | null>;
13
+ /**
14
+ * Call Qwen by spawning the `qwen` CLI with piped stdin.
15
+ * The qwen CLI manages its own token refresh and uses the correct API format.
16
+ * Falls back to direct HTTP call if the qwen CLI is not available.
17
+ */
13
18
  export declare function callQwenAPI(prompt: string, model?: string): Promise<string>;
14
- /** Call Qwen API using credentials from a specific file path (for role binaries) */
19
+ /**
20
+ * Call Qwen API using credentials from a specific file path (for role binaries).
21
+ * The role binary CLI (e.g. agent-explorer) manages its own qwen auth via the
22
+ * shared ~/.qwen/oauth_creds.json — we spawn it with piped stdin so it runs
23
+ * in non-interactive mode without TTY issues.
24
+ * Falls back to direct HTTP if the role binary is not found.
25
+ */
15
26
  export declare function callQwenAPIFromCreds(prompt: string, model: string, credsPath: string): Promise<string>;
@@ -1,6 +1,7 @@
1
1
  import * as fs from 'fs/promises';
2
2
  import * as path from 'path';
3
3
  import * as crypto from 'crypto';
4
+ import { spawnSync } from 'child_process';
4
5
  import open from 'open';
5
6
  import { AGENT_HOME } from './config.js';
6
7
  const QWEN_OAUTH_BASE_URL = 'https://chat.qwen.ai';
@@ -273,7 +274,30 @@ async function callQwenAPIWithToken(token, prompt, model) {
273
274
  const data = await response.json();
274
275
  return data.choices?.[0]?.message?.content || '';
275
276
  }
277
+ /**
278
+ * Call Qwen by spawning the `qwen` CLI with piped stdin.
279
+ * The qwen CLI manages its own token refresh and uses the correct API format.
280
+ * Falls back to direct HTTP call if the qwen CLI is not available.
281
+ */
276
282
  export async function callQwenAPI(prompt, model = 'coder-model') {
283
+ // Try using the qwen CLI subprocess first — it handles auth/refresh/format automatically
284
+ const qwenBin = process.env.QWEN_BIN || 'qwen';
285
+ try {
286
+ const result = spawnSync(qwenBin, [], {
287
+ input: prompt,
288
+ encoding: 'utf-8',
289
+ timeout: 300000, // 5 minutes
290
+ maxBuffer: 10 * 1024 * 1024,
291
+ });
292
+ if (result.status === 0 && result.stdout?.trim()) {
293
+ return result.stdout.trim();
294
+ }
295
+ // qwen not available or failed — fall through to direct API
296
+ }
297
+ catch {
298
+ // qwen not installed — fall through
299
+ }
300
+ // Fallback: direct API call (requires valid token in AGENT_HOME)
277
301
  let token = await loadToken();
278
302
  if (!token) {
279
303
  throw new Error('QWEN_AUTH_EXPIRED: No hay token de Qwen. Ejecutá --login primero.');
@@ -284,7 +308,6 @@ export async function callQwenAPI(prompt, model = 'coder-model') {
284
308
  catch (err) {
285
309
  if (!err.message?.startsWith('QWEN_AUTH_EXPIRED'))
286
310
  throw err;
287
- // 401 — intentar refresh antes de rendirse
288
311
  if (token.refreshToken) {
289
312
  const refreshed = await doRefreshToken(token.refreshToken);
290
313
  if (refreshed) {
@@ -295,14 +318,39 @@ export async function callQwenAPI(prompt, model = 'coder-model') {
295
318
  throw new Error('QWEN_AUTH_EXPIRED: Sesión expirada. Ejecutá: agent-mp --login');
296
319
  }
297
320
  }
298
- /** Call Qwen API using credentials from a specific file path (for role binaries) */
321
+ /**
322
+ * Call Qwen API using credentials from a specific file path (for role binaries).
323
+ * The role binary CLI (e.g. agent-explorer) manages its own qwen auth via the
324
+ * shared ~/.qwen/oauth_creds.json — we spawn it with piped stdin so it runs
325
+ * in non-interactive mode without TTY issues.
326
+ * Falls back to direct HTTP if the role binary is not found.
327
+ */
299
328
  export async function callQwenAPIFromCreds(prompt, model, credsPath) {
329
+ // Derive the role binary name from the creds path (e.g. ~/.agent-explorer/ → agent-explorer)
330
+ const cliName = path.basename(path.dirname(credsPath)).replace(/^\./, '');
331
+ // Try spawning the role binary with piped stdin (non-interactive mode)
332
+ const qwenBin = process.env.QWEN_BIN || 'qwen';
333
+ try {
334
+ const result = spawnSync(qwenBin, [], {
335
+ input: prompt,
336
+ encoding: 'utf-8',
337
+ timeout: 300000,
338
+ maxBuffer: 10 * 1024 * 1024,
339
+ });
340
+ if (result.status === 0 && result.stdout?.trim()) {
341
+ return result.stdout.trim();
342
+ }
343
+ }
344
+ catch {
345
+ // qwen not available
346
+ }
347
+ // Fallback: direct HTTP with stored creds
300
348
  let raw;
301
349
  try {
302
350
  raw = JSON.parse(await fs.readFile(credsPath, 'utf-8'));
303
351
  }
304
352
  catch {
305
- throw new Error(`No credentials found at ${credsPath}. Run the role binary with --login first.`);
353
+ throw new Error(`No credentials found at ${credsPath}. Run: ${cliName} --login`);
306
354
  }
307
355
  let token = {
308
356
  accessToken: raw.accessToken || raw.access_token || '',
@@ -312,7 +360,7 @@ export async function callQwenAPIFromCreds(prompt, model, credsPath) {
312
360
  resourceUrl: raw.resourceUrl || raw.resource_url,
313
361
  };
314
362
  if (!token.accessToken) {
315
- throw new Error(`Invalid credentials at ${credsPath}. Run the role binary with --login first.`);
363
+ throw new Error(`Invalid credentials at ${credsPath}. Run: ${cliName} --login`);
316
364
  }
317
365
  // Refresh proactivo: si vence en menos de 2 minutos (o ya venció)
318
366
  const TWO_MIN = 2 * 60 * 1000;
@@ -337,7 +385,6 @@ export async function callQwenAPIFromCreds(prompt, model, credsPath) {
337
385
  return callQwenAPIWithToken(refreshed, prompt, model);
338
386
  }
339
387
  }
340
- const cliName = path.basename(path.dirname(credsPath)).replace(/^\./, '');
341
388
  throw new Error(`QWEN_AUTH_EXPIRED: Sesión expirada. Ejecutá: ${cliName} --login`);
342
389
  }
343
390
  }
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"agent-rev","version":"0.3.5","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"}}
1
+ {"name":"agent-rev","version":"0.3.6","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"}}