codexuse-cli 5.1.5 → 5.1.7
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/index.js +19 -394
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4635,7 +4635,7 @@ var import_node_crypto6 = require("crypto");
|
|
|
4635
4635
|
var import_fs = require("fs");
|
|
4636
4636
|
var import_path = __toESM(require("path"), 1);
|
|
4637
4637
|
var import_path2 = require("path");
|
|
4638
|
-
var
|
|
4638
|
+
var import_toml = __toESM(require_toml(), 1);
|
|
4639
4639
|
|
|
4640
4640
|
// ../../packages/contracts/src/profiles/identity.ts
|
|
4641
4641
|
function normalizeValue(value) {
|
|
@@ -4693,7 +4693,6 @@ var import_node_readline = __toESM(require("readline"), 1);
|
|
|
4693
4693
|
var import_node_fs3 = require("fs");
|
|
4694
4694
|
var import_node_os2 = __toESM(require("os"), 1);
|
|
4695
4695
|
var import_node_path5 = __toESM(require("path"), 1);
|
|
4696
|
-
var import_toml = __toESM(require_toml(), 1);
|
|
4697
4696
|
|
|
4698
4697
|
// ../../packages/runtime-codex/src/codex/cli.ts
|
|
4699
4698
|
var import_node_fs2 = require("fs");
|
|
@@ -4930,12 +4929,6 @@ var ACTIVATION_MODEL = "gpt-5.1-codex-mini";
|
|
|
4930
4929
|
var MAX_STDERR_CAPTURE_CHARS = 32768;
|
|
4931
4930
|
var REFRESH_TOKEN_REDEEMED_SNIPPET = "refresh token was already used";
|
|
4932
4931
|
var authFileCache = /* @__PURE__ */ new Map();
|
|
4933
|
-
var CODEX_OAUTH_REFRESH_URL = "https://auth.openai.com/oauth/token";
|
|
4934
|
-
var CODEX_OAUTH_CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
|
|
4935
|
-
var CODEX_OAUTH_REFRESH_MAX_AGE_MS = 8 * 24 * 60 * 60 * 1e3;
|
|
4936
|
-
var CODEX_OAUTH_ACCESS_TOKEN_REFRESH_SKEW_MS = 2 * 60 * 1e3;
|
|
4937
|
-
var CODEX_USAGE_DEFAULT_BASE_URL = "https://chatgpt.com/backend-api";
|
|
4938
|
-
var CODEX_USAGE_TIMEOUT_MS = 3e4;
|
|
4939
4932
|
function isRecord4(value) {
|
|
4940
4933
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
4941
4934
|
}
|
|
@@ -5159,17 +5152,6 @@ function extractJwtIssuedAtMs(token) {
|
|
|
5159
5152
|
}
|
|
5160
5153
|
return issuedAt * 1e3;
|
|
5161
5154
|
}
|
|
5162
|
-
function extractJwtExpiresAtMs(token) {
|
|
5163
|
-
const payload = decodeJwtPayload(token);
|
|
5164
|
-
if (!payload) {
|
|
5165
|
-
return null;
|
|
5166
|
-
}
|
|
5167
|
-
const expiresAt = payload["exp"];
|
|
5168
|
-
if (typeof expiresAt !== "number" || !Number.isFinite(expiresAt)) {
|
|
5169
|
-
return null;
|
|
5170
|
-
}
|
|
5171
|
-
return expiresAt * 1e3;
|
|
5172
|
-
}
|
|
5173
5155
|
function parseAuthRecord(content) {
|
|
5174
5156
|
try {
|
|
5175
5157
|
const parsed = JSON.parse(content);
|
|
@@ -5258,353 +5240,6 @@ async function writeAuthFileCached(filePath, content) {
|
|
|
5258
5240
|
authFileCache.delete(filePath);
|
|
5259
5241
|
}
|
|
5260
5242
|
}
|
|
5261
|
-
function nonEmptyString(value) {
|
|
5262
|
-
return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
|
|
5263
|
-
}
|
|
5264
|
-
function resolveCodexAuthPathForEnv(envOverride) {
|
|
5265
|
-
return envOverride?.CODEX_HOME ? import_node_path5.default.join(envOverride.CODEX_HOME, "auth.json") : import_node_path5.default.join(
|
|
5266
|
-
envOverride?.HOME ?? process.env.HOME ?? import_node_os2.default.homedir(),
|
|
5267
|
-
".codex",
|
|
5268
|
-
"auth.json"
|
|
5269
|
-
);
|
|
5270
|
-
}
|
|
5271
|
-
function parseCodexOAuthCredentials(content) {
|
|
5272
|
-
const parsed = parseAuthRecord(content);
|
|
5273
|
-
if (!parsed) {
|
|
5274
|
-
return null;
|
|
5275
|
-
}
|
|
5276
|
-
const tokens = isRecord4(parsed.tokens) ? parsed.tokens : {};
|
|
5277
|
-
const accessToken = nonEmptyString(tokens.access_token) ?? nonEmptyString(parsed.access_token);
|
|
5278
|
-
const refreshToken = nonEmptyString(tokens.refresh_token) ?? nonEmptyString(parsed.refresh_token);
|
|
5279
|
-
if (!accessToken && !refreshToken) {
|
|
5280
|
-
return null;
|
|
5281
|
-
}
|
|
5282
|
-
return {
|
|
5283
|
-
accessToken: accessToken ?? "",
|
|
5284
|
-
refreshToken: refreshToken ?? "",
|
|
5285
|
-
idToken: nonEmptyString(tokens.id_token) ?? nonEmptyString(parsed.id_token),
|
|
5286
|
-
accountId: nonEmptyString(tokens.account_id) ?? nonEmptyString(parsed.account_id),
|
|
5287
|
-
lastRefreshMs: parseTimestamp2(tokens.last_refresh) ?? parseTimestamp2(parsed.last_refresh)
|
|
5288
|
-
};
|
|
5289
|
-
}
|
|
5290
|
-
function shouldRefreshCodexOAuthToken(credentials) {
|
|
5291
|
-
if (!credentials.refreshToken) {
|
|
5292
|
-
return false;
|
|
5293
|
-
}
|
|
5294
|
-
const accessExpiresAt = extractJwtExpiresAtMs(credentials.accessToken);
|
|
5295
|
-
if (accessExpiresAt !== null && accessExpiresAt - Date.now() <= CODEX_OAUTH_ACCESS_TOKEN_REFRESH_SKEW_MS) {
|
|
5296
|
-
return true;
|
|
5297
|
-
}
|
|
5298
|
-
if (credentials.lastRefreshMs === null) {
|
|
5299
|
-
return true;
|
|
5300
|
-
}
|
|
5301
|
-
return Date.now() - credentials.lastRefreshMs > CODEX_OAUTH_REFRESH_MAX_AGE_MS;
|
|
5302
|
-
}
|
|
5303
|
-
async function writeCodexOAuthCredentials(authPath, content, credentials) {
|
|
5304
|
-
let json = {};
|
|
5305
|
-
try {
|
|
5306
|
-
const parsed = JSON.parse(content);
|
|
5307
|
-
if (isRecord4(parsed)) {
|
|
5308
|
-
json = { ...parsed };
|
|
5309
|
-
}
|
|
5310
|
-
} catch {
|
|
5311
|
-
json = {};
|
|
5312
|
-
}
|
|
5313
|
-
const existingTokens = isRecord4(json.tokens) ? json.tokens : {};
|
|
5314
|
-
json.tokens = {
|
|
5315
|
-
...existingTokens,
|
|
5316
|
-
access_token: credentials.accessToken,
|
|
5317
|
-
refresh_token: credentials.refreshToken,
|
|
5318
|
-
...credentials.idToken ? { id_token: credentials.idToken } : {},
|
|
5319
|
-
...credentials.accountId ? { account_id: credentials.accountId } : {},
|
|
5320
|
-
last_refresh: (/* @__PURE__ */ new Date()).toISOString()
|
|
5321
|
-
};
|
|
5322
|
-
json.last_refresh = (/* @__PURE__ */ new Date()).toISOString();
|
|
5323
|
-
await writeAuthFileCached(authPath, `${JSON.stringify(json, null, 2)}
|
|
5324
|
-
`);
|
|
5325
|
-
}
|
|
5326
|
-
async function refreshCodexOAuthCredentials(credentials) {
|
|
5327
|
-
if (!credentials.refreshToken) {
|
|
5328
|
-
return credentials;
|
|
5329
|
-
}
|
|
5330
|
-
const response = await fetch(CODEX_OAUTH_REFRESH_URL, {
|
|
5331
|
-
method: "POST",
|
|
5332
|
-
headers: { "Content-Type": "application/json" },
|
|
5333
|
-
signal: AbortSignal.timeout(CODEX_USAGE_TIMEOUT_MS),
|
|
5334
|
-
body: JSON.stringify({
|
|
5335
|
-
client_id: CODEX_OAUTH_CLIENT_ID,
|
|
5336
|
-
grant_type: "refresh_token",
|
|
5337
|
-
refresh_token: credentials.refreshToken,
|
|
5338
|
-
scope: "openid profile email"
|
|
5339
|
-
})
|
|
5340
|
-
});
|
|
5341
|
-
const body = await response.text();
|
|
5342
|
-
if (!response.ok) {
|
|
5343
|
-
let code = "";
|
|
5344
|
-
try {
|
|
5345
|
-
const parsed2 = JSON.parse(body);
|
|
5346
|
-
if (isRecord4(parsed2)) {
|
|
5347
|
-
const error = isRecord4(parsed2.error) ? parsed2.error : {};
|
|
5348
|
-
code = nonEmptyString(error.code) ?? nonEmptyString(parsed2.error) ?? nonEmptyString(parsed2.code) ?? "";
|
|
5349
|
-
}
|
|
5350
|
-
} catch {
|
|
5351
|
-
code = "";
|
|
5352
|
-
}
|
|
5353
|
-
if (code === "refresh_token_reused") {
|
|
5354
|
-
throw new Error("refresh token was already used");
|
|
5355
|
-
}
|
|
5356
|
-
if (code === "refresh_token_expired") {
|
|
5357
|
-
throw new Error("refresh token expired");
|
|
5358
|
-
}
|
|
5359
|
-
if (code === "invalid_grant" || code === "refresh_token_invalidated") {
|
|
5360
|
-
throw new Error("refresh token was revoked");
|
|
5361
|
-
}
|
|
5362
|
-
throw new Error(`Codex OAuth refresh failed HTTP ${response.status}`);
|
|
5363
|
-
}
|
|
5364
|
-
let parsed;
|
|
5365
|
-
try {
|
|
5366
|
-
parsed = JSON.parse(body);
|
|
5367
|
-
} catch {
|
|
5368
|
-
throw new Error("Codex OAuth refresh returned invalid JSON");
|
|
5369
|
-
}
|
|
5370
|
-
if (!isRecord4(parsed)) {
|
|
5371
|
-
throw new Error("Codex OAuth refresh returned invalid data");
|
|
5372
|
-
}
|
|
5373
|
-
return {
|
|
5374
|
-
accessToken: nonEmptyString(parsed.access_token) ?? credentials.accessToken,
|
|
5375
|
-
refreshToken: nonEmptyString(parsed.refresh_token) ?? credentials.refreshToken,
|
|
5376
|
-
idToken: nonEmptyString(parsed.id_token) ?? credentials.idToken,
|
|
5377
|
-
accountId: credentials.accountId,
|
|
5378
|
-
lastRefreshMs: Date.now()
|
|
5379
|
-
};
|
|
5380
|
-
}
|
|
5381
|
-
async function loadCodexConfigContents(envOverride) {
|
|
5382
|
-
const codexHome = envOverride?.CODEX_HOME?.trim();
|
|
5383
|
-
const root = codexHome || import_node_path5.default.join(envOverride?.HOME ?? process.env.HOME ?? import_node_os2.default.homedir(), ".codex");
|
|
5384
|
-
try {
|
|
5385
|
-
return await import_node_fs3.promises.readFile(import_node_path5.default.join(root, "config.toml"), "utf8");
|
|
5386
|
-
} catch {
|
|
5387
|
-
return null;
|
|
5388
|
-
}
|
|
5389
|
-
}
|
|
5390
|
-
function parseChatGPTBaseUrl(contents) {
|
|
5391
|
-
if (!contents) {
|
|
5392
|
-
return CODEX_USAGE_DEFAULT_BASE_URL;
|
|
5393
|
-
}
|
|
5394
|
-
try {
|
|
5395
|
-
const parsed = (0, import_toml.parse)(contents);
|
|
5396
|
-
if (isRecord4(parsed)) {
|
|
5397
|
-
return nonEmptyString(parsed.chatgpt_base_url) ?? CODEX_USAGE_DEFAULT_BASE_URL;
|
|
5398
|
-
}
|
|
5399
|
-
} catch {
|
|
5400
|
-
return CODEX_USAGE_DEFAULT_BASE_URL;
|
|
5401
|
-
}
|
|
5402
|
-
return CODEX_USAGE_DEFAULT_BASE_URL;
|
|
5403
|
-
}
|
|
5404
|
-
async function resolveCodexUsageUrl(envOverride) {
|
|
5405
|
-
let base = parseChatGPTBaseUrl(await loadCodexConfigContents(envOverride));
|
|
5406
|
-
while (base.endsWith("/")) {
|
|
5407
|
-
base = base.slice(0, -1);
|
|
5408
|
-
}
|
|
5409
|
-
if ((base.startsWith("https://chatgpt.com") || base.startsWith("https://chat.openai.com")) && !base.includes("/backend-api")) {
|
|
5410
|
-
base += "/backend-api";
|
|
5411
|
-
}
|
|
5412
|
-
return `${base}${base.includes("/backend-api") ? "/wham/usage" : "/api/codex/usage"}`;
|
|
5413
|
-
}
|
|
5414
|
-
function numberFromUnknown(value) {
|
|
5415
|
-
if (typeof value === "number" && Number.isFinite(value)) {
|
|
5416
|
-
return value;
|
|
5417
|
-
}
|
|
5418
|
-
if (typeof value === "string" && value.trim()) {
|
|
5419
|
-
const parsed = Number(value.trim());
|
|
5420
|
-
return Number.isFinite(parsed) ? parsed : null;
|
|
5421
|
-
}
|
|
5422
|
-
return null;
|
|
5423
|
-
}
|
|
5424
|
-
function toOAuthWindow(window) {
|
|
5425
|
-
if (!window) {
|
|
5426
|
-
return void 0;
|
|
5427
|
-
}
|
|
5428
|
-
const usedPercent = numberFromUnknown(window.used_percent);
|
|
5429
|
-
const resetAt = numberFromUnknown(window.reset_at);
|
|
5430
|
-
const limitWindowSeconds = numberFromUnknown(window.limit_window_seconds);
|
|
5431
|
-
if (usedPercent === null && resetAt === null && limitWindowSeconds === null) {
|
|
5432
|
-
return void 0;
|
|
5433
|
-
}
|
|
5434
|
-
const result = {};
|
|
5435
|
-
if (usedPercent !== null) {
|
|
5436
|
-
result.usedPercent = Math.max(0, Math.min(100, usedPercent));
|
|
5437
|
-
}
|
|
5438
|
-
if (limitWindowSeconds !== null) {
|
|
5439
|
-
result.windowMinutes = Math.round(limitWindowSeconds / 60);
|
|
5440
|
-
}
|
|
5441
|
-
if (resetAt !== null) {
|
|
5442
|
-
const resetMs = resetAt > 1e10 ? resetAt : resetAt * 1e3;
|
|
5443
|
-
result.resetsAt = new Date(resetMs).toISOString();
|
|
5444
|
-
result.resetsInSeconds = Math.max(0, Math.round((resetMs - Date.now()) / 1e3));
|
|
5445
|
-
}
|
|
5446
|
-
return result;
|
|
5447
|
-
}
|
|
5448
|
-
function firstNonEmptyString(...values) {
|
|
5449
|
-
for (const value of values) {
|
|
5450
|
-
const text = nonEmptyString(value);
|
|
5451
|
-
if (text) {
|
|
5452
|
-
return text;
|
|
5453
|
-
}
|
|
5454
|
-
}
|
|
5455
|
-
return null;
|
|
5456
|
-
}
|
|
5457
|
-
function slugForRateLimitId(value) {
|
|
5458
|
-
return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
5459
|
-
}
|
|
5460
|
-
function isSparkRateLimit(limitName, meteredFeature) {
|
|
5461
|
-
return [limitName, meteredFeature].filter((value) => Boolean(value)).some((value) => value.toLowerCase().includes("spark"));
|
|
5462
|
-
}
|
|
5463
|
-
function sparkWindowIdentity(window, fallback) {
|
|
5464
|
-
const limitWindowSeconds = numberFromUnknown(window.limit_window_seconds);
|
|
5465
|
-
const windowMinutes = limitWindowSeconds !== null ? Math.round(limitWindowSeconds / 60) : null;
|
|
5466
|
-
const kind = windowMinutes !== null && windowMinutes > 0 && windowMinutes <= 6 * 60 ? "five-hour" : windowMinutes !== null && windowMinutes >= 6 * 24 * 60 ? "weekly" : fallback;
|
|
5467
|
-
return kind === "weekly" ? { id: "codex-spark-weekly", label: "Codex Spark Weekly" } : { id: "codex-spark", label: "Codex Spark 5-hour" };
|
|
5468
|
-
}
|
|
5469
|
-
function toExtraRateLimitWindow(args) {
|
|
5470
|
-
const window = toOAuthWindow(args.window);
|
|
5471
|
-
if (!window) {
|
|
5472
|
-
return null;
|
|
5473
|
-
}
|
|
5474
|
-
return {
|
|
5475
|
-
id: args.id,
|
|
5476
|
-
label: args.label,
|
|
5477
|
-
...args.meteredFeature ? { meteredFeature: args.meteredFeature } : {},
|
|
5478
|
-
...window
|
|
5479
|
-
};
|
|
5480
|
-
}
|
|
5481
|
-
function parseExtraRateLimitWindows(additionalRateLimits) {
|
|
5482
|
-
if (!Array.isArray(additionalRateLimits)) {
|
|
5483
|
-
return [];
|
|
5484
|
-
}
|
|
5485
|
-
const usedIds = /* @__PURE__ */ new Set();
|
|
5486
|
-
const extraWindows = [];
|
|
5487
|
-
for (const entry of additionalRateLimits) {
|
|
5488
|
-
if (!isRecord4(entry)) {
|
|
5489
|
-
continue;
|
|
5490
|
-
}
|
|
5491
|
-
const limitName = firstNonEmptyString(entry.limit_name);
|
|
5492
|
-
const meteredFeature = firstNonEmptyString(entry.metered_feature);
|
|
5493
|
-
const rateLimit = isRecord4(entry.rate_limit) ? entry.rate_limit : null;
|
|
5494
|
-
if (!rateLimit) {
|
|
5495
|
-
continue;
|
|
5496
|
-
}
|
|
5497
|
-
const primary = isRecord4(rateLimit.primary_window) ? rateLimit.primary_window : null;
|
|
5498
|
-
const secondary = isRecord4(rateLimit.secondary_window) ? rateLimit.secondary_window : null;
|
|
5499
|
-
if (isSparkRateLimit(limitName, meteredFeature)) {
|
|
5500
|
-
const candidates = [
|
|
5501
|
-
{ window: primary, fallback: "five-hour" },
|
|
5502
|
-
{ window: secondary, fallback: "weekly" }
|
|
5503
|
-
];
|
|
5504
|
-
for (const candidate of candidates) {
|
|
5505
|
-
if (!candidate.window) {
|
|
5506
|
-
continue;
|
|
5507
|
-
}
|
|
5508
|
-
const identity = sparkWindowIdentity(candidate.window, candidate.fallback);
|
|
5509
|
-
if (usedIds.has(identity.id)) {
|
|
5510
|
-
continue;
|
|
5511
|
-
}
|
|
5512
|
-
const extraWindow2 = toExtraRateLimitWindow({
|
|
5513
|
-
...identity,
|
|
5514
|
-
meteredFeature,
|
|
5515
|
-
window: candidate.window
|
|
5516
|
-
});
|
|
5517
|
-
if (extraWindow2) {
|
|
5518
|
-
usedIds.add(identity.id);
|
|
5519
|
-
extraWindows.push(extraWindow2);
|
|
5520
|
-
}
|
|
5521
|
-
}
|
|
5522
|
-
continue;
|
|
5523
|
-
}
|
|
5524
|
-
const idSource = firstNonEmptyString(meteredFeature, limitName);
|
|
5525
|
-
const slug = idSource ? slugForRateLimitId(idSource) : "";
|
|
5526
|
-
if (!slug) {
|
|
5527
|
-
continue;
|
|
5528
|
-
}
|
|
5529
|
-
const id = `codex-${slug}`;
|
|
5530
|
-
if (usedIds.has(id)) {
|
|
5531
|
-
continue;
|
|
5532
|
-
}
|
|
5533
|
-
const extraWindow = toExtraRateLimitWindow({
|
|
5534
|
-
id,
|
|
5535
|
-
label: firstNonEmptyString(limitName, meteredFeature) ?? "Codex extra limit",
|
|
5536
|
-
meteredFeature,
|
|
5537
|
-
window: primary ?? secondary
|
|
5538
|
-
});
|
|
5539
|
-
if (extraWindow) {
|
|
5540
|
-
usedIds.add(id);
|
|
5541
|
-
extraWindows.push(extraWindow);
|
|
5542
|
-
}
|
|
5543
|
-
}
|
|
5544
|
-
return extraWindows;
|
|
5545
|
-
}
|
|
5546
|
-
function parseRateLimitSnapshotFromOAuthUsage(value) {
|
|
5547
|
-
if (!isRecord4(value)) {
|
|
5548
|
-
throw new Error("Codex usage API returned invalid data");
|
|
5549
|
-
}
|
|
5550
|
-
const usage = value;
|
|
5551
|
-
const primary = toOAuthWindow(usage.rate_limit?.primary_window ?? null);
|
|
5552
|
-
const secondary = toOAuthWindow(usage.rate_limit?.secondary_window ?? null);
|
|
5553
|
-
const extraWindows = parseExtraRateLimitWindows(usage.additional_rate_limits);
|
|
5554
|
-
if (!primary && !secondary && extraWindows.length === 0) {
|
|
5555
|
-
return null;
|
|
5556
|
-
}
|
|
5557
|
-
return {
|
|
5558
|
-
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5559
|
-
source: "codex-oauth-estimate",
|
|
5560
|
-
...primary ? { primary } : {},
|
|
5561
|
-
...secondary ? { secondary } : {},
|
|
5562
|
-
...extraWindows.length > 0 ? { extraWindows } : {}
|
|
5563
|
-
};
|
|
5564
|
-
}
|
|
5565
|
-
async function fetchRateLimitsViaOAuth(envOverride) {
|
|
5566
|
-
const authPath = resolveCodexAuthPathForEnv(envOverride);
|
|
5567
|
-
const authContent = await readAuthFileCached(authPath);
|
|
5568
|
-
if (!authContent) {
|
|
5569
|
-
return null;
|
|
5570
|
-
}
|
|
5571
|
-
let credentials = parseCodexOAuthCredentials(authContent);
|
|
5572
|
-
if (!credentials) {
|
|
5573
|
-
return null;
|
|
5574
|
-
}
|
|
5575
|
-
if (shouldRefreshCodexOAuthToken(credentials)) {
|
|
5576
|
-
credentials = await refreshCodexOAuthCredentials(credentials);
|
|
5577
|
-
await writeCodexOAuthCredentials(authPath, authContent, credentials);
|
|
5578
|
-
}
|
|
5579
|
-
if (!credentials.accessToken) {
|
|
5580
|
-
return null;
|
|
5581
|
-
}
|
|
5582
|
-
const usageUrl = await resolveCodexUsageUrl(envOverride);
|
|
5583
|
-
const response = await fetch(usageUrl, {
|
|
5584
|
-
method: "GET",
|
|
5585
|
-
headers: {
|
|
5586
|
-
Authorization: `Bearer ${credentials.accessToken}`,
|
|
5587
|
-
Accept: "application/json",
|
|
5588
|
-
"User-Agent": "CodexUse",
|
|
5589
|
-
...credentials.accountId ? { "ChatGPT-Account-Id": credentials.accountId } : {}
|
|
5590
|
-
},
|
|
5591
|
-
signal: AbortSignal.timeout(CODEX_USAGE_TIMEOUT_MS)
|
|
5592
|
-
});
|
|
5593
|
-
const body = await response.text();
|
|
5594
|
-
if (response.status === 401 || response.status === 403) {
|
|
5595
|
-
throw new Error(`Codex OAuth usage failed HTTP ${response.status} (${usageUrl})`);
|
|
5596
|
-
}
|
|
5597
|
-
if (!response.ok) {
|
|
5598
|
-
throw new Error(`Codex usage API failed HTTP ${response.status} (${usageUrl}): ${body.slice(0, 500)}`);
|
|
5599
|
-
}
|
|
5600
|
-
let parsed;
|
|
5601
|
-
try {
|
|
5602
|
-
parsed = JSON.parse(body);
|
|
5603
|
-
} catch {
|
|
5604
|
-
throw new Error("Codex usage API returned invalid JSON");
|
|
5605
|
-
}
|
|
5606
|
-
return parseRateLimitSnapshotFromOAuthUsage(parsed);
|
|
5607
|
-
}
|
|
5608
5243
|
function inferRefreshFailureHint(stderrOutput) {
|
|
5609
5244
|
if (!stderrOutput) {
|
|
5610
5245
|
return null;
|
|
@@ -7357,7 +6992,7 @@ var ProfileManager = class {
|
|
|
7357
6992
|
}
|
|
7358
6993
|
let parsed;
|
|
7359
6994
|
try {
|
|
7360
|
-
parsed = (0,
|
|
6995
|
+
parsed = (0, import_toml.parse)(raw);
|
|
7361
6996
|
} catch (error) {
|
|
7362
6997
|
logWarn(`Failed to parse config.toml for profile home '${profileHome}':`, error);
|
|
7363
6998
|
return;
|
|
@@ -7367,7 +7002,7 @@ var ProfileManager = class {
|
|
|
7367
7002
|
}
|
|
7368
7003
|
delete parsed["model_reasoning_effort"];
|
|
7369
7004
|
const sanitized = this.ensureTrailingNewline(
|
|
7370
|
-
(0,
|
|
7005
|
+
(0, import_toml.stringify)(parsed)
|
|
7371
7006
|
);
|
|
7372
7007
|
try {
|
|
7373
7008
|
await import_fs.promises.writeFile(configPath, sanitized, "utf8");
|
|
@@ -7729,16 +7364,7 @@ var ProfileManager = class {
|
|
|
7729
7364
|
profileName,
|
|
7730
7365
|
() => this.runWithPreparedProfileHome(
|
|
7731
7366
|
profileName,
|
|
7732
|
-
|
|
7733
|
-
try {
|
|
7734
|
-
const rpcSnapshot = await fetchRateLimitsViaRpc(env, { codexPath: options.codexPath });
|
|
7735
|
-
if (rpcSnapshot) {
|
|
7736
|
-
return rpcSnapshot;
|
|
7737
|
-
}
|
|
7738
|
-
} catch {
|
|
7739
|
-
}
|
|
7740
|
-
return fetchRateLimitsViaOAuth(env);
|
|
7741
|
-
},
|
|
7367
|
+
(env) => fetchRateLimitsViaRpc(env, { codexPath: options.codexPath }),
|
|
7742
7368
|
{ syncFromActiveAuthBeforeAction: false }
|
|
7743
7369
|
)
|
|
7744
7370
|
);
|
|
@@ -9369,10 +8995,6 @@ function snapshotResetSeconds(snapshot) {
|
|
|
9369
8995
|
].filter((value) => typeof value === "number" && Number.isFinite(value));
|
|
9370
8996
|
return values.length > 0 ? Math.min(...values) : null;
|
|
9371
8997
|
}
|
|
9372
|
-
function fallbackUsedPercent(profile) {
|
|
9373
|
-
const cached = maxUsedPercent(profile.rateLimit ?? null);
|
|
9374
|
-
return typeof cached === "number" && Number.isFinite(cached) ? cached : null;
|
|
9375
|
-
}
|
|
9376
8998
|
function compareCandidates(left, right) {
|
|
9377
8999
|
const leftUsage = left.usedPercent ?? Number.POSITIVE_INFINITY;
|
|
9378
9000
|
const rightUsage = right.usedPercent ?? Number.POSITIVE_INFINITY;
|
|
@@ -9430,16 +9052,17 @@ async function selectBestProfile(manager, profiles, codexPath) {
|
|
|
9430
9052
|
}
|
|
9431
9053
|
try {
|
|
9432
9054
|
const snapshot = await manager.readLiveRateLimits(profile.name, { codexPath });
|
|
9055
|
+
const usedPercent = maxUsedPercent(snapshot);
|
|
9433
9056
|
candidates.push({
|
|
9434
9057
|
profile,
|
|
9435
|
-
usedPercent: typeof
|
|
9058
|
+
usedPercent: typeof usedPercent === "number" ? usedPercent : null,
|
|
9436
9059
|
resetSeconds: snapshotResetSeconds(snapshot)
|
|
9437
9060
|
});
|
|
9438
9061
|
} catch {
|
|
9439
9062
|
candidates.push({
|
|
9440
9063
|
profile,
|
|
9441
|
-
usedPercent:
|
|
9442
|
-
resetSeconds:
|
|
9064
|
+
usedPercent: null,
|
|
9065
|
+
resetSeconds: null
|
|
9443
9066
|
});
|
|
9444
9067
|
}
|
|
9445
9068
|
}
|
|
@@ -9574,6 +9197,9 @@ Picks the healthiest saved profile, then runs Codex. Auto-run requires Pro or an
|
|
|
9574
9197
|
if (!best) {
|
|
9575
9198
|
throw new Error("No valid saved profiles found. Add one with `codexuse profile add <name>`.");
|
|
9576
9199
|
}
|
|
9200
|
+
if (best.usedPercent === null) {
|
|
9201
|
+
throw new Error("No live rate-limit usage found. Skipping best profile run.");
|
|
9202
|
+
}
|
|
9577
9203
|
const dryRun = hasFlag(flags, "--dry-run");
|
|
9578
9204
|
const summary = `${best.profile.name} (${formatUsagePercent(best.usedPercent)} used)`;
|
|
9579
9205
|
if (dryRun) {
|
|
@@ -15661,7 +15287,7 @@ function summarizeRateLimitSnapshot(snapshot) {
|
|
|
15661
15287
|
return summary;
|
|
15662
15288
|
}
|
|
15663
15289
|
function fallbackUsage(profile) {
|
|
15664
|
-
const usageSummary = summarizeRateLimitSnapshot(
|
|
15290
|
+
const usageSummary = summarizeRateLimitSnapshot(null);
|
|
15665
15291
|
if (!profile.isValid) {
|
|
15666
15292
|
return { summary: "invalid", rows: null, usageSummary };
|
|
15667
15293
|
}
|
|
@@ -15677,8 +15303,7 @@ async function resolveProfileUsage(manager, profile, codexPath) {
|
|
|
15677
15303
|
try {
|
|
15678
15304
|
const snapshot = await manager.readLiveRateLimits(profile.name, { codexPath });
|
|
15679
15305
|
if (!snapshot) {
|
|
15680
|
-
|
|
15681
|
-
return { summary: "n/a", rows: null, usageSummary };
|
|
15306
|
+
return fallbackUsage(profile);
|
|
15682
15307
|
}
|
|
15683
15308
|
const rows = [];
|
|
15684
15309
|
if (snapshot.primary) {
|
|
@@ -15730,7 +15355,7 @@ function computeAutoRollCandidate(profiles, usageMap, currentProfileName, curren
|
|
|
15730
15355
|
(profile) => profile.name !== currentProfileName && !blockedProfileNames.has(profile.name) && profile.isValid && !profile.tokenStatus?.requiresUserAction
|
|
15731
15356
|
).map((profile) => ({
|
|
15732
15357
|
profile,
|
|
15733
|
-
usageSummary: usageMap.get(profile.name)?.usageSummary ?? summarizeRateLimitSnapshot(
|
|
15358
|
+
usageSummary: usageMap.get(profile.name)?.usageSummary ?? summarizeRateLimitSnapshot(null)
|
|
15734
15359
|
}));
|
|
15735
15360
|
if (candidates.length === 0) {
|
|
15736
15361
|
return null;
|
|
@@ -16145,7 +15770,7 @@ async function runAutoRollPass(manager, options) {
|
|
|
16145
15770
|
target: null
|
|
16146
15771
|
};
|
|
16147
15772
|
}
|
|
16148
|
-
const currentUsage = usageMap.get(current.name)?.usageSummary ?? summarizeRateLimitSnapshot(
|
|
15773
|
+
const currentUsage = usageMap.get(current.name)?.usageSummary ?? summarizeRateLimitSnapshot(null);
|
|
16149
15774
|
if (!currentUsage.hasUsage) {
|
|
16150
15775
|
return {
|
|
16151
15776
|
switched: false,
|
|
@@ -16263,7 +15888,7 @@ async function handleProfileCommand(args, version) {
|
|
|
16263
15888
|
usageMap.set(profile.name, {
|
|
16264
15889
|
summary: "codex cli missing",
|
|
16265
15890
|
rows: null,
|
|
16266
|
-
usageSummary: summarizeRateLimitSnapshot(
|
|
15891
|
+
usageSummary: summarizeRateLimitSnapshot(null)
|
|
16267
15892
|
});
|
|
16268
15893
|
}
|
|
16269
15894
|
} else {
|
|
@@ -16634,7 +16259,7 @@ async function pushRemoteSnapshot(access, snapshot, options) {
|
|
|
16634
16259
|
}
|
|
16635
16260
|
|
|
16636
16261
|
// ../../packages/runtime-codex/src/codex/config.ts
|
|
16637
|
-
var
|
|
16262
|
+
var import_toml2 = __toESM(require_toml(), 1);
|
|
16638
16263
|
|
|
16639
16264
|
// ../../packages/runtime-codex/src/codex/config-metadata.ts
|
|
16640
16265
|
var import_node_child_process8 = require("child_process");
|
|
@@ -17273,7 +16898,7 @@ function formatUserFacingError(error, options = {}) {
|
|
|
17273
16898
|
// ../../packages/runtime-codex/src/codex/config.ts
|
|
17274
16899
|
function tryParseToml(content) {
|
|
17275
16900
|
try {
|
|
17276
|
-
const parsed = (0,
|
|
16901
|
+
const parsed = (0, import_toml2.parse)(content);
|
|
17277
16902
|
return { data: parsed ?? {}, error: null };
|
|
17278
16903
|
} catch (error) {
|
|
17279
16904
|
const maybe = error;
|
|
@@ -18312,7 +17937,7 @@ async function ensureCliStorageReady() {
|
|
|
18312
17937
|
}
|
|
18313
17938
|
|
|
18314
17939
|
// src/app/main.ts
|
|
18315
|
-
var VERSION = true ? "5.1.
|
|
17940
|
+
var VERSION = true ? "5.1.7" : "0.0.0";
|
|
18316
17941
|
async function runCli() {
|
|
18317
17942
|
const args = process.argv.slice(2);
|
|
18318
17943
|
if (args.length === 0) {
|