codex-team 0.0.9 → 0.0.10

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.
package/dist/cli.cjs CHANGED
@@ -13,7 +13,7 @@ var __webpack_modules__ = {
13
13
  const utc_js_namespaceObject = require("dayjs/plugin/utc.js");
14
14
  var utc_js_default = /*#__PURE__*/ __webpack_require__.n(utc_js_namespaceObject);
15
15
  var package_namespaceObject = {
16
- rE: "0.0.9"
16
+ rE: "0.0.10"
17
17
  };
18
18
  const external_node_crypto_namespaceObject = require("node:crypto");
19
19
  const promises_namespaceObject = require("node:fs/promises");
@@ -226,6 +226,9 @@ var __webpack_modules__ = {
226
226
  const external_node_util_namespaceObject = require("node:util");
227
227
  const DEFAULT_CHATGPT_BASE_URL = "https://chatgpt.com";
228
228
  const USER_AGENT = "codexm/0.1";
229
+ const USAGE_FETCH_ATTEMPTS = 3;
230
+ const USAGE_FETCH_RETRY_DELAY_MS = 250;
231
+ const USAGE_FETCH_TIMEOUT_MS = 15000;
229
232
  function quota_client_isRecord(value) {
230
233
  return "object" == typeof value && null !== value && !Array.isArray(value);
231
234
  }
@@ -323,8 +326,6 @@ var __webpack_modules__ = {
323
326
  const normalizedBaseUrl = baseUrl.replace(/\/+$/u, "");
324
327
  const candidates = [
325
328
  `${normalizedBaseUrl}/backend-api/wham/usage`,
326
- `${normalizedBaseUrl}/wham/usage`,
327
- `${normalizedBaseUrl}/api/codex/usage`,
328
329
  "https://chatgpt.com/backend-api/wham/usage"
329
330
  ];
330
331
  return [
@@ -334,6 +335,19 @@ var __webpack_modules__ = {
334
335
  function normalizeFetchError(error) {
335
336
  return error instanceof Error ? error.message : String(error);
336
337
  }
338
+ async function delay(milliseconds) {
339
+ await new Promise((resolve)=>setTimeout(resolve, milliseconds));
340
+ }
341
+ function isTransientUsageStatus(status) {
342
+ return 408 === status || 429 === status || status >= 500 && status <= 599;
343
+ }
344
+ function isLastAttempt(attempt) {
345
+ return attempt >= USAGE_FETCH_ATTEMPTS;
346
+ }
347
+ function formatUsageAttemptError(url, attempt, message) {
348
+ const retryContext = USAGE_FETCH_ATTEMPTS > 1 ? ` attempt ${attempt}/${USAGE_FETCH_ATTEMPTS}` : "";
349
+ return `${url}${retryContext} -> ${message}`;
350
+ }
337
351
  function shouldRetryWithTokenRefresh(message) {
338
352
  const normalized = message.toLowerCase();
339
353
  return normalized.includes("401") || normalized.includes("403") || normalized.includes("unauthorized") || normalized.includes("invalid_token") || normalized.includes("deactivated_workspace");
@@ -389,7 +403,9 @@ var __webpack_modules__ = {
389
403
  const urls = await resolveUsageUrls(options.homeDir);
390
404
  const now = (options.now ?? new Date()).toISOString();
391
405
  const errors = [];
392
- for (const url of urls){
406
+ for (const url of urls)for(let attempt = 1; attempt <= USAGE_FETCH_ATTEMPTS; attempt += 1){
407
+ const abortController = new AbortController();
408
+ const timeout = setTimeout(()=>abortController.abort(), USAGE_FETCH_TIMEOUT_MS);
393
409
  let response;
394
410
  try {
395
411
  response = await fetchImpl(url, {
@@ -399,23 +415,35 @@ var __webpack_modules__ = {
399
415
  "ChatGPT-Account-Id": extracted.accountId,
400
416
  Accept: "application/json",
401
417
  "User-Agent": USER_AGENT
402
- }
418
+ },
419
+ signal: abortController.signal
403
420
  });
404
421
  } catch (error) {
405
- errors.push(`${url} -> ${normalizeFetchError(error)}`);
406
- continue;
422
+ clearTimeout(timeout);
423
+ const message = abortController.signal.aborted ? `timed out after ${USAGE_FETCH_TIMEOUT_MS}ms` : normalizeFetchError(error);
424
+ errors.push(formatUsageAttemptError(url, attempt, message));
425
+ if (!isLastAttempt(attempt)) {
426
+ await delay(USAGE_FETCH_RETRY_DELAY_MS * attempt);
427
+ continue;
428
+ }
429
+ break;
407
430
  }
431
+ clearTimeout(timeout);
408
432
  if (!response.ok) {
409
433
  const body = await response.text();
410
- errors.push(`${url} -> ${response.status}: ${body.slice(0, 140).replace(/\s+/gu, " ").trim()}`);
411
- continue;
434
+ errors.push(formatUsageAttemptError(url, attempt, `${response.status}: ${body.slice(0, 140).replace(/\s+/gu, " ").trim()}`));
435
+ if (isTransientUsageStatus(response.status) && !isLastAttempt(attempt)) {
436
+ await delay(USAGE_FETCH_RETRY_DELAY_MS * attempt);
437
+ continue;
438
+ }
439
+ break;
412
440
  }
413
441
  let payload;
414
442
  try {
415
443
  payload = await response.json();
416
444
  } catch (error) {
417
- errors.push(`${url} -> failed to parse JSON: ${normalizeFetchError(error)}`);
418
- continue;
445
+ errors.push(formatUsageAttemptError(url, attempt, `failed to parse JSON: ${normalizeFetchError(error)}`));
446
+ break;
419
447
  }
420
448
  return mapUsagePayload(payload, extracted.planType, now);
421
449
  }
package/dist/main.cjs CHANGED
@@ -43,7 +43,7 @@ var timezone_js_default = /*#__PURE__*/ __webpack_require__.n(timezone_js_namesp
43
43
  const utc_js_namespaceObject = require("dayjs/plugin/utc.js");
44
44
  var utc_js_default = /*#__PURE__*/ __webpack_require__.n(utc_js_namespaceObject);
45
45
  var package_namespaceObject = {
46
- rE: "0.0.9"
46
+ rE: "0.0.10"
47
47
  };
48
48
  const external_node_crypto_namespaceObject = require("node:crypto");
49
49
  const promises_namespaceObject = require("node:fs/promises");
@@ -256,6 +256,9 @@ const external_node_child_process_namespaceObject = require("node:child_process"
256
256
  const external_node_util_namespaceObject = require("node:util");
257
257
  const DEFAULT_CHATGPT_BASE_URL = "https://chatgpt.com";
258
258
  const USER_AGENT = "codexm/0.1";
259
+ const USAGE_FETCH_ATTEMPTS = 3;
260
+ const USAGE_FETCH_RETRY_DELAY_MS = 250;
261
+ const USAGE_FETCH_TIMEOUT_MS = 15000;
259
262
  function quota_client_isRecord(value) {
260
263
  return "object" == typeof value && null !== value && !Array.isArray(value);
261
264
  }
@@ -353,8 +356,6 @@ async function resolveUsageUrls(homeDir) {
353
356
  const normalizedBaseUrl = baseUrl.replace(/\/+$/u, "");
354
357
  const candidates = [
355
358
  `${normalizedBaseUrl}/backend-api/wham/usage`,
356
- `${normalizedBaseUrl}/wham/usage`,
357
- `${normalizedBaseUrl}/api/codex/usage`,
358
359
  "https://chatgpt.com/backend-api/wham/usage"
359
360
  ];
360
361
  return [
@@ -364,6 +365,19 @@ async function resolveUsageUrls(homeDir) {
364
365
  function normalizeFetchError(error) {
365
366
  return error instanceof Error ? error.message : String(error);
366
367
  }
368
+ async function delay(milliseconds) {
369
+ await new Promise((resolve)=>setTimeout(resolve, milliseconds));
370
+ }
371
+ function isTransientUsageStatus(status) {
372
+ return 408 === status || 429 === status || status >= 500 && status <= 599;
373
+ }
374
+ function isLastAttempt(attempt) {
375
+ return attempt >= USAGE_FETCH_ATTEMPTS;
376
+ }
377
+ function formatUsageAttemptError(url, attempt, message) {
378
+ const retryContext = USAGE_FETCH_ATTEMPTS > 1 ? ` attempt ${attempt}/${USAGE_FETCH_ATTEMPTS}` : "";
379
+ return `${url}${retryContext} -> ${message}`;
380
+ }
367
381
  function shouldRetryWithTokenRefresh(message) {
368
382
  const normalized = message.toLowerCase();
369
383
  return normalized.includes("401") || normalized.includes("403") || normalized.includes("unauthorized") || normalized.includes("invalid_token") || normalized.includes("deactivated_workspace");
@@ -419,7 +433,9 @@ async function requestUsage(snapshot, options) {
419
433
  const urls = await resolveUsageUrls(options.homeDir);
420
434
  const now = (options.now ?? new Date()).toISOString();
421
435
  const errors = [];
422
- for (const url of urls){
436
+ for (const url of urls)for(let attempt = 1; attempt <= USAGE_FETCH_ATTEMPTS; attempt += 1){
437
+ const abortController = new AbortController();
438
+ const timeout = setTimeout(()=>abortController.abort(), USAGE_FETCH_TIMEOUT_MS);
423
439
  let response;
424
440
  try {
425
441
  response = await fetchImpl(url, {
@@ -429,23 +445,35 @@ async function requestUsage(snapshot, options) {
429
445
  "ChatGPT-Account-Id": extracted.accountId,
430
446
  Accept: "application/json",
431
447
  "User-Agent": USER_AGENT
432
- }
448
+ },
449
+ signal: abortController.signal
433
450
  });
434
451
  } catch (error) {
435
- errors.push(`${url} -> ${normalizeFetchError(error)}`);
436
- continue;
452
+ clearTimeout(timeout);
453
+ const message = abortController.signal.aborted ? `timed out after ${USAGE_FETCH_TIMEOUT_MS}ms` : normalizeFetchError(error);
454
+ errors.push(formatUsageAttemptError(url, attempt, message));
455
+ if (!isLastAttempt(attempt)) {
456
+ await delay(USAGE_FETCH_RETRY_DELAY_MS * attempt);
457
+ continue;
458
+ }
459
+ break;
437
460
  }
461
+ clearTimeout(timeout);
438
462
  if (!response.ok) {
439
463
  const body = await response.text();
440
- errors.push(`${url} -> ${response.status}: ${body.slice(0, 140).replace(/\s+/gu, " ").trim()}`);
441
- continue;
464
+ errors.push(formatUsageAttemptError(url, attempt, `${response.status}: ${body.slice(0, 140).replace(/\s+/gu, " ").trim()}`));
465
+ if (isTransientUsageStatus(response.status) && !isLastAttempt(attempt)) {
466
+ await delay(USAGE_FETCH_RETRY_DELAY_MS * attempt);
467
+ continue;
468
+ }
469
+ break;
442
470
  }
443
471
  let payload;
444
472
  try {
445
473
  payload = await response.json();
446
474
  } catch (error) {
447
- errors.push(`${url} -> failed to parse JSON: ${normalizeFetchError(error)}`);
448
- continue;
475
+ errors.push(formatUsageAttemptError(url, attempt, `failed to parse JSON: ${normalizeFetchError(error)}`));
476
+ break;
449
477
  }
450
478
  return mapUsagePayload(payload, extracted.planType, now);
451
479
  }
package/dist/main.js CHANGED
@@ -9,7 +9,7 @@ import { basename, dirname, join } from "node:path";
9
9
  import { execFile } from "node:child_process";
10
10
  import { promisify } from "node:util";
11
11
  var package_namespaceObject = {
12
- rE: "0.0.9"
12
+ rE: "0.0.10"
13
13
  };
14
14
  function isRecord(value) {
15
15
  return "object" == typeof value && null !== value && !Array.isArray(value);
@@ -216,6 +216,9 @@ function decodeJwtPayload(token) {
216
216
  }
217
217
  const DEFAULT_CHATGPT_BASE_URL = "https://chatgpt.com";
218
218
  const USER_AGENT = "codexm/0.1";
219
+ const USAGE_FETCH_ATTEMPTS = 3;
220
+ const USAGE_FETCH_RETRY_DELAY_MS = 250;
221
+ const USAGE_FETCH_TIMEOUT_MS = 15000;
219
222
  function quota_client_isRecord(value) {
220
223
  return "object" == typeof value && null !== value && !Array.isArray(value);
221
224
  }
@@ -313,8 +316,6 @@ async function resolveUsageUrls(homeDir) {
313
316
  const normalizedBaseUrl = baseUrl.replace(/\/+$/u, "");
314
317
  const candidates = [
315
318
  `${normalizedBaseUrl}/backend-api/wham/usage`,
316
- `${normalizedBaseUrl}/wham/usage`,
317
- `${normalizedBaseUrl}/api/codex/usage`,
318
319
  "https://chatgpt.com/backend-api/wham/usage"
319
320
  ];
320
321
  return [
@@ -324,6 +325,19 @@ async function resolveUsageUrls(homeDir) {
324
325
  function normalizeFetchError(error) {
325
326
  return error instanceof Error ? error.message : String(error);
326
327
  }
328
+ async function delay(milliseconds) {
329
+ await new Promise((resolve)=>setTimeout(resolve, milliseconds));
330
+ }
331
+ function isTransientUsageStatus(status) {
332
+ return 408 === status || 429 === status || status >= 500 && status <= 599;
333
+ }
334
+ function isLastAttempt(attempt) {
335
+ return attempt >= USAGE_FETCH_ATTEMPTS;
336
+ }
337
+ function formatUsageAttemptError(url, attempt, message) {
338
+ const retryContext = USAGE_FETCH_ATTEMPTS > 1 ? ` attempt ${attempt}/${USAGE_FETCH_ATTEMPTS}` : "";
339
+ return `${url}${retryContext} -> ${message}`;
340
+ }
327
341
  function shouldRetryWithTokenRefresh(message) {
328
342
  const normalized = message.toLowerCase();
329
343
  return normalized.includes("401") || normalized.includes("403") || normalized.includes("unauthorized") || normalized.includes("invalid_token") || normalized.includes("deactivated_workspace");
@@ -379,7 +393,9 @@ async function requestUsage(snapshot, options) {
379
393
  const urls = await resolveUsageUrls(options.homeDir);
380
394
  const now = (options.now ?? new Date()).toISOString();
381
395
  const errors = [];
382
- for (const url of urls){
396
+ for (const url of urls)for(let attempt = 1; attempt <= USAGE_FETCH_ATTEMPTS; attempt += 1){
397
+ const abortController = new AbortController();
398
+ const timeout = setTimeout(()=>abortController.abort(), USAGE_FETCH_TIMEOUT_MS);
383
399
  let response;
384
400
  try {
385
401
  response = await fetchImpl(url, {
@@ -389,23 +405,35 @@ async function requestUsage(snapshot, options) {
389
405
  "ChatGPT-Account-Id": extracted.accountId,
390
406
  Accept: "application/json",
391
407
  "User-Agent": USER_AGENT
392
- }
408
+ },
409
+ signal: abortController.signal
393
410
  });
394
411
  } catch (error) {
395
- errors.push(`${url} -> ${normalizeFetchError(error)}`);
396
- continue;
412
+ clearTimeout(timeout);
413
+ const message = abortController.signal.aborted ? `timed out after ${USAGE_FETCH_TIMEOUT_MS}ms` : normalizeFetchError(error);
414
+ errors.push(formatUsageAttemptError(url, attempt, message));
415
+ if (!isLastAttempt(attempt)) {
416
+ await delay(USAGE_FETCH_RETRY_DELAY_MS * attempt);
417
+ continue;
418
+ }
419
+ break;
397
420
  }
421
+ clearTimeout(timeout);
398
422
  if (!response.ok) {
399
423
  const body = await response.text();
400
- errors.push(`${url} -> ${response.status}: ${body.slice(0, 140).replace(/\s+/gu, " ").trim()}`);
401
- continue;
424
+ errors.push(formatUsageAttemptError(url, attempt, `${response.status}: ${body.slice(0, 140).replace(/\s+/gu, " ").trim()}`));
425
+ if (isTransientUsageStatus(response.status) && !isLastAttempt(attempt)) {
426
+ await delay(USAGE_FETCH_RETRY_DELAY_MS * attempt);
427
+ continue;
428
+ }
429
+ break;
402
430
  }
403
431
  let payload;
404
432
  try {
405
433
  payload = await response.json();
406
434
  } catch (error) {
407
- errors.push(`${url} -> failed to parse JSON: ${normalizeFetchError(error)}`);
408
- continue;
435
+ errors.push(formatUsageAttemptError(url, attempt, `failed to parse JSON: ${normalizeFetchError(error)}`));
436
+ break;
409
437
  }
410
438
  return mapUsagePayload(payload, extracted.planType, now);
411
439
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codex-team",
3
- "version": "0.0.9",
3
+ "version": "0.0.10",
4
4
  "description": "Manage multiple Codex ChatGPT auth snapshots and quota usage from the command line.",
5
5
  "license": "MIT",
6
6
  "type": "module",