agent-rev 0.3.3 → 0.3.4

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.
@@ -59,7 +59,8 @@ async function saveToken(token) {
59
59
  const tokenPath = await getTokenPath();
60
60
  await fs.writeFile(tokenPath, JSON.stringify(token, null, 2), 'utf-8');
61
61
  }
62
- async function refreshAccessToken(refreshToken) {
62
+ /** Calls the refresh endpoint and returns the new token (does NOT save). */
63
+ async function doRefreshToken(refreshToken) {
63
64
  try {
64
65
  const response = await fetch(QWEN_OAUTH_TOKEN_ENDPOINT, {
65
66
  method: 'POST',
@@ -70,25 +71,29 @@ async function refreshAccessToken(refreshToken) {
70
71
  client_id: QWEN_OAUTH_CLIENT_ID,
71
72
  }),
72
73
  });
73
- if (!response.ok) {
74
- throw new Error(`Token refresh failed: ${response.status}`);
75
- }
74
+ if (!response.ok)
75
+ return null;
76
76
  const data = await response.json();
77
- const token = {
77
+ if (!data.access_token)
78
+ return null;
79
+ return {
78
80
  accessToken: data.access_token,
79
81
  refreshToken: data.refresh_token || refreshToken,
80
82
  expiresAt: Date.now() + (data.expires_in || 3600) * 1000,
81
83
  idToken: data.id_token,
82
84
  resourceUrl: data.resource_url,
83
85
  };
84
- await saveToken(token);
85
- return token;
86
86
  }
87
- catch (error) {
88
- console.error('Error refreshing token:', error);
87
+ catch {
89
88
  return null;
90
89
  }
91
90
  }
91
+ async function refreshAccessToken(refreshToken) {
92
+ const token = await doRefreshToken(refreshToken);
93
+ if (token)
94
+ await saveToken(token);
95
+ return token;
96
+ }
92
97
  // Generate PKCE code verifier and challenge
93
98
  function generatePKCE() {
94
99
  const codeVerifier = crypto.randomBytes(32).toString('base64url');
@@ -263,7 +268,7 @@ async function callQwenAPIWithToken(token, prompt, model) {
263
268
  return data.choices?.[0]?.message?.content || '';
264
269
  }
265
270
  export async function callQwenAPI(prompt, model = 'coder-model') {
266
- const token = await loadToken();
271
+ let token = await loadToken();
267
272
  if (!token) {
268
273
  throw new Error('QWEN_AUTH_EXPIRED: No hay token de Qwen. Ejecutá --login primero.');
269
274
  }
@@ -271,10 +276,17 @@ export async function callQwenAPI(prompt, model = 'coder-model') {
271
276
  return await callQwenAPIWithToken(token, prompt, model);
272
277
  }
273
278
  catch (err) {
274
- if (err.message?.startsWith('QWEN_AUTH_EXPIRED')) {
275
- throw new Error('QWEN_AUTH_EXPIRED: Sesión expirada. Ejecutá: agent-mp --login');
279
+ if (!err.message?.startsWith('QWEN_AUTH_EXPIRED'))
280
+ throw err;
281
+ // 401 — intentar refresh antes de rendirse
282
+ if (token.refreshToken) {
283
+ const refreshed = await doRefreshToken(token.refreshToken);
284
+ if (refreshed) {
285
+ await saveToken(refreshed);
286
+ return callQwenAPIWithToken(refreshed, prompt, model);
287
+ }
276
288
  }
277
- throw err;
289
+ throw new Error('QWEN_AUTH_EXPIRED: Sesión expirada. Ejecutá: agent-mp --login');
278
290
  }
279
291
  }
280
292
  /** Call Qwen API using credentials from a specific file path (for role binaries) */
@@ -296,9 +308,9 @@ export async function callQwenAPIFromCreds(prompt, model, credsPath) {
296
308
  if (!token.accessToken) {
297
309
  throw new Error(`Invalid credentials at ${credsPath}. Run the role binary with --login first.`);
298
310
  }
299
- // Refresh if expired
311
+ // Refresh if expired by timestamp
300
312
  if (token.expiresAt <= Date.now() && token.refreshToken) {
301
- const refreshed = await refreshAccessToken(token.refreshToken);
313
+ const refreshed = await doRefreshToken(token.refreshToken);
302
314
  if (refreshed) {
303
315
  token = refreshed;
304
316
  await fs.writeFile(credsPath, JSON.stringify(token, null, 2), 'utf-8');
@@ -308,10 +320,17 @@ export async function callQwenAPIFromCreds(prompt, model, credsPath) {
308
320
  return await callQwenAPIWithToken(token, prompt, model);
309
321
  }
310
322
  catch (err) {
311
- if (err.message?.startsWith('QWEN_AUTH_EXPIRED')) {
312
- const cliName = path.basename(path.dirname(credsPath)).replace(/^\./, '');
313
- throw new Error(`QWEN_AUTH_EXPIRED: Sesión expirada. Ejecutá: ${cliName} --login`);
323
+ if (!err.message?.startsWith('QWEN_AUTH_EXPIRED'))
324
+ throw err;
325
+ // 401 server-side intentar refresh aunque expiresAt no haya vencido
326
+ if (token.refreshToken) {
327
+ const refreshed = await doRefreshToken(token.refreshToken);
328
+ if (refreshed) {
329
+ await fs.writeFile(credsPath, JSON.stringify(refreshed, null, 2), 'utf-8');
330
+ return callQwenAPIWithToken(refreshed, prompt, model);
331
+ }
314
332
  }
315
- throw err;
333
+ const cliName = path.basename(path.dirname(credsPath)).replace(/^\./, '');
334
+ throw new Error(`QWEN_AUTH_EXPIRED: Sesión expirada. Ejecutá: ${cliName} --login`);
316
335
  }
317
336
  }
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"agent-rev","version":"0.3.3","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.4","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"}}