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 +39 -11
- package/dist/main.cjs +39 -11
- package/dist/main.js +39 -11
- package/package.json +1 -1
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.
|
|
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
|
-
|
|
406
|
-
|
|
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(
|
|
411
|
-
|
|
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(
|
|
418
|
-
|
|
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.
|
|
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
|
-
|
|
436
|
-
|
|
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(
|
|
441
|
-
|
|
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(
|
|
448
|
-
|
|
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.
|
|
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
|
-
|
|
396
|
-
|
|
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(
|
|
401
|
-
|
|
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(
|
|
408
|
-
|
|
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
|
}
|