@opengeni/codex 0.2.5 → 0.2.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/{chunk-AMRVHBCD.js → chunk-YGKQDUY7.js} +13 -1
- package/dist/{chunk-AMRVHBCD.js.map → chunk-YGKQDUY7.js.map} +1 -1
- package/dist/constants.d.ts +7 -1
- package/dist/constants.js +13 -1
- package/dist/index.d.ts +143 -5
- package/dist/index.js +637 -66
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/api-client.ts +131 -22
- package/src/bounded-operation.ts +43 -0
- package/src/constants.ts +18 -0
- package/src/fetch.ts +351 -11
- package/src/index.ts +2 -0
- package/src/refresh.ts +21 -10
- package/src/request-context.ts +38 -0
- package/src/reset-credits.ts +157 -0
- package/src/response-timeout.ts +159 -0
- package/src/usage-normalize.ts +20 -2
package/dist/index.js
CHANGED
|
@@ -24,9 +24,15 @@ import {
|
|
|
24
24
|
CODEX_REFRESH_FALLBACK_MS,
|
|
25
25
|
CODEX_REFRESH_WINDOW_MS,
|
|
26
26
|
CODEX_RESPONSES_BASE,
|
|
27
|
+
CODEX_RESPONSE_HEADERS_TIMEOUT_MS,
|
|
28
|
+
CODEX_RESPONSE_NO_BYTE_RETRIES,
|
|
29
|
+
CODEX_RESPONSE_RETRY_BACKOFF_MS,
|
|
30
|
+
CODEX_RESPONSE_SDK_OUTER_TIMEOUT_MS,
|
|
31
|
+
CODEX_RESPONSE_STREAM_IDLE_TIMEOUT_MS,
|
|
32
|
+
CODEX_RESPONSE_WHOLE_TIMEOUT_MS,
|
|
27
33
|
CODEX_TOKEN_URL,
|
|
28
34
|
CODEX_WHAM_BASE
|
|
29
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-YGKQDUY7.js";
|
|
30
36
|
|
|
31
37
|
// src/billing.ts
|
|
32
38
|
function isCodexBilledModel(model) {
|
|
@@ -107,7 +113,37 @@ async function exchangeDeviceCode(input, fetchImpl = fetch) {
|
|
|
107
113
|
};
|
|
108
114
|
}
|
|
109
115
|
|
|
116
|
+
// src/bounded-operation.ts
|
|
117
|
+
async function runBoundedCodexOperation(operation, timeoutMs) {
|
|
118
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
119
|
+
throw new Error("Codex operation timeout must be positive");
|
|
120
|
+
}
|
|
121
|
+
const controller = new AbortController();
|
|
122
|
+
let timedOut = false;
|
|
123
|
+
let timeout;
|
|
124
|
+
const work = operation(controller.signal).then(
|
|
125
|
+
(value) => ({ ok: true, value }),
|
|
126
|
+
() => ({
|
|
127
|
+
ok: false,
|
|
128
|
+
reason: timedOut || controller.signal.aborted ? "timeout" : "network_error"
|
|
129
|
+
})
|
|
130
|
+
);
|
|
131
|
+
const deadline = new Promise((resolve) => {
|
|
132
|
+
timeout = setTimeout(() => {
|
|
133
|
+
timedOut = true;
|
|
134
|
+
controller.abort();
|
|
135
|
+
resolve({ ok: false, reason: "timeout" });
|
|
136
|
+
}, timeoutMs);
|
|
137
|
+
});
|
|
138
|
+
try {
|
|
139
|
+
return await Promise.race([work, deadline]);
|
|
140
|
+
} finally {
|
|
141
|
+
if (timeout) clearTimeout(timeout);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
110
145
|
// src/refresh.ts
|
|
146
|
+
var CODEX_REFRESH_TIMEOUT_MS = 5e3;
|
|
111
147
|
var CodexReloginRequired = class extends Error {
|
|
112
148
|
constructor(message) {
|
|
113
149
|
super(message);
|
|
@@ -120,17 +156,24 @@ var CodexRefreshTransient = class extends Error {
|
|
|
120
156
|
this.name = "CodexRefreshTransient";
|
|
121
157
|
}
|
|
122
158
|
};
|
|
123
|
-
async function refreshCodexToken(refreshToken, fetchImpl = fetch) {
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
159
|
+
async function refreshCodexToken(refreshToken, fetchImpl = fetch, timeoutMs = CODEX_REFRESH_TIMEOUT_MS) {
|
|
160
|
+
const fetched = await runBoundedCodexOperation(async (signal) => {
|
|
161
|
+
const res2 = await fetchImpl(CODEX_TOKEN_URL, {
|
|
162
|
+
method: "POST",
|
|
163
|
+
headers: { "Content-Type": "application/json" },
|
|
164
|
+
body: JSON.stringify({
|
|
165
|
+
client_id: CODEX_CLIENT_ID,
|
|
166
|
+
grant_type: "refresh_token",
|
|
167
|
+
refresh_token: refreshToken
|
|
168
|
+
}),
|
|
169
|
+
signal
|
|
170
|
+
});
|
|
171
|
+
return { res: res2, text: await res2.text() };
|
|
172
|
+
}, timeoutMs);
|
|
173
|
+
if (!fetched.ok) {
|
|
174
|
+
throw new CodexRefreshTransient(`Codex token refresh ${fetched.reason}`);
|
|
175
|
+
}
|
|
176
|
+
const { res, text } = fetched.value;
|
|
134
177
|
if (!res.ok) {
|
|
135
178
|
const code = extractRefreshErrorCode(text);
|
|
136
179
|
const msg = code ? PERMANENT_REFRESH_FAILURES[code] : void 0;
|
|
@@ -280,7 +323,89 @@ function buildModelResolver(liveSlugs, fallbackSlug) {
|
|
|
280
323
|
}
|
|
281
324
|
|
|
282
325
|
// src/usage-normalize.ts
|
|
326
|
+
import * as z2 from "zod/v4";
|
|
327
|
+
|
|
328
|
+
// src/reset-credits.ts
|
|
283
329
|
import * as z from "zod/v4";
|
|
330
|
+
var CODEX_RATE_LIMIT_RESET_OUTCOMES = [
|
|
331
|
+
"reset",
|
|
332
|
+
"nothingToReset",
|
|
333
|
+
"noCredit",
|
|
334
|
+
"alreadyRedeemed"
|
|
335
|
+
];
|
|
336
|
+
var nonNegativeInteger = z.number().int().nonnegative();
|
|
337
|
+
var backendTimestamp = z.string().datetime({ offset: true });
|
|
338
|
+
var backendCreditSchema = z.object({
|
|
339
|
+
id: z.string().min(1),
|
|
340
|
+
reset_type: z.string().min(1),
|
|
341
|
+
status: z.string().min(1),
|
|
342
|
+
granted_at: backendTimestamp,
|
|
343
|
+
expires_at: backendTimestamp.nullish(),
|
|
344
|
+
title: z.string().nullish(),
|
|
345
|
+
description: z.string().nullish()
|
|
346
|
+
}).passthrough();
|
|
347
|
+
var backendDetailsSchema = z.object({
|
|
348
|
+
credits: z.array(backendCreditSchema),
|
|
349
|
+
available_count: nonNegativeInteger
|
|
350
|
+
}).passthrough();
|
|
351
|
+
var backendUsageSummarySchema = z.object({
|
|
352
|
+
rate_limit_reset_credits: z.object({ available_count: nonNegativeInteger }).passthrough().nullish()
|
|
353
|
+
}).passthrough();
|
|
354
|
+
var backendConsumeOutcomes = [
|
|
355
|
+
"reset",
|
|
356
|
+
"nothing_to_reset",
|
|
357
|
+
"no_credit",
|
|
358
|
+
"already_redeemed"
|
|
359
|
+
];
|
|
360
|
+
var backendConsumeSchema = z.object({
|
|
361
|
+
code: z.enum(backendConsumeOutcomes),
|
|
362
|
+
// The app-server intentionally discards this field. OpenGeni also refetches
|
|
363
|
+
// rather than inferring post-redemption state from it.
|
|
364
|
+
windows_reset: nonNegativeInteger.default(0)
|
|
365
|
+
}).passthrough();
|
|
366
|
+
function normalizedResetType(value) {
|
|
367
|
+
return value === "codex_rate_limits" ? "codexRateLimits" : "unknown";
|
|
368
|
+
}
|
|
369
|
+
function normalizedCreditStatus(value) {
|
|
370
|
+
if (value === "available" || value === "redeeming" || value === "redeemed") {
|
|
371
|
+
return value;
|
|
372
|
+
}
|
|
373
|
+
return "unknown";
|
|
374
|
+
}
|
|
375
|
+
function parseCodexRateLimitResetCreditsDetails(payload) {
|
|
376
|
+
const parsed = backendDetailsSchema.safeParse(payload);
|
|
377
|
+
if (!parsed.success) return null;
|
|
378
|
+
return {
|
|
379
|
+
availableCount: parsed.data.available_count,
|
|
380
|
+
credits: parsed.data.credits.map((credit) => ({
|
|
381
|
+
id: credit.id,
|
|
382
|
+
resetType: normalizedResetType(credit.reset_type),
|
|
383
|
+
status: normalizedCreditStatus(credit.status),
|
|
384
|
+
grantedAt: Math.floor(Date.parse(credit.granted_at) / 1e3),
|
|
385
|
+
expiresAt: credit.expires_at == null ? null : Math.floor(Date.parse(credit.expires_at) / 1e3),
|
|
386
|
+
title: credit.title ?? null,
|
|
387
|
+
description: credit.description ?? null
|
|
388
|
+
}))
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
function parseCodexRateLimitResetCreditsSummary(payload) {
|
|
392
|
+
const parsed = backendUsageSummarySchema.safeParse(payload);
|
|
393
|
+
const availableCount = parsed.success ? parsed.data.rate_limit_reset_credits?.available_count : void 0;
|
|
394
|
+
return availableCount === void 0 ? null : { availableCount, credits: null };
|
|
395
|
+
}
|
|
396
|
+
function parseCodexRateLimitResetConsumeResponse(payload) {
|
|
397
|
+
const parsed = backendConsumeSchema.safeParse(payload);
|
|
398
|
+
if (!parsed.success) return null;
|
|
399
|
+
const outcomes = {
|
|
400
|
+
reset: "reset",
|
|
401
|
+
nothing_to_reset: "nothingToReset",
|
|
402
|
+
no_credit: "noCredit",
|
|
403
|
+
already_redeemed: "alreadyRedeemed"
|
|
404
|
+
};
|
|
405
|
+
return { outcome: outcomes[parsed.data.code] };
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// src/usage-normalize.ts
|
|
284
409
|
var CODEX_FIVE_HOUR_WINDOW_SECONDS = 18e3;
|
|
285
410
|
var CODEX_WEEKLY_WINDOW_SECONDS = 604800;
|
|
286
411
|
function buildCodexUsageWindowFromCache(usedPercent, resetAt, limitWindowSeconds) {
|
|
@@ -301,34 +426,34 @@ function buildCodexUsageWindowFromCache(usedPercent, resetAt, limitWindowSeconds
|
|
|
301
426
|
limitWindowSeconds
|
|
302
427
|
};
|
|
303
428
|
}
|
|
304
|
-
var windowSchema =
|
|
305
|
-
used_percent:
|
|
306
|
-
reset_after_seconds:
|
|
307
|
-
reset_at:
|
|
308
|
-
limit_window_seconds:
|
|
429
|
+
var windowSchema = z2.object({
|
|
430
|
+
used_percent: z2.number().optional(),
|
|
431
|
+
reset_after_seconds: z2.number().optional(),
|
|
432
|
+
reset_at: z2.number().optional(),
|
|
433
|
+
limit_window_seconds: z2.number().optional()
|
|
309
434
|
}).nullish();
|
|
310
|
-
var rateLimitSchema =
|
|
311
|
-
allowed:
|
|
312
|
-
limit_reached:
|
|
435
|
+
var rateLimitSchema = z2.object({
|
|
436
|
+
allowed: z2.boolean().optional(),
|
|
437
|
+
limit_reached: z2.boolean().optional(),
|
|
313
438
|
primary_window: windowSchema,
|
|
314
439
|
secondary_window: windowSchema
|
|
315
440
|
}).nullish();
|
|
316
|
-
var additionalLimitSchema =
|
|
317
|
-
limit_name:
|
|
318
|
-
metered_feature:
|
|
441
|
+
var additionalLimitSchema = z2.object({
|
|
442
|
+
limit_name: z2.string().optional(),
|
|
443
|
+
metered_feature: z2.string().optional(),
|
|
319
444
|
primary_window: windowSchema,
|
|
320
445
|
secondary_window: windowSchema
|
|
321
446
|
});
|
|
322
|
-
var creditsSchema =
|
|
323
|
-
has_credits:
|
|
324
|
-
unlimited:
|
|
325
|
-
overage_limit_reached:
|
|
326
|
-
balance:
|
|
447
|
+
var creditsSchema = z2.object({
|
|
448
|
+
has_credits: z2.boolean().optional(),
|
|
449
|
+
unlimited: z2.boolean().optional(),
|
|
450
|
+
overage_limit_reached: z2.boolean().optional(),
|
|
451
|
+
balance: z2.union([z2.string(), z2.number()]).optional()
|
|
327
452
|
}).nullish();
|
|
328
|
-
var usageBodySchema =
|
|
329
|
-
plan_type:
|
|
453
|
+
var usageBodySchema = z2.object({
|
|
454
|
+
plan_type: z2.string().nullish(),
|
|
330
455
|
rate_limit: rateLimitSchema,
|
|
331
|
-
additional_limits:
|
|
456
|
+
additional_limits: z2.array(additionalLimitSchema).nullish(),
|
|
332
457
|
credits: creditsSchema
|
|
333
458
|
});
|
|
334
459
|
function clampPercent(value) {
|
|
@@ -391,7 +516,8 @@ function normalizeCodexUsage(httpStatus, rawPayload) {
|
|
|
391
516
|
fiveHour: null,
|
|
392
517
|
weekly: null,
|
|
393
518
|
limitReached: false,
|
|
394
|
-
fetchedAt
|
|
519
|
+
fetchedAt,
|
|
520
|
+
rateLimitResetCredits: parseCodexRateLimitResetCreditsSummary(rawPayload)
|
|
395
521
|
};
|
|
396
522
|
if (httpStatus >= 400 && httpStatus !== 404 || body == null) {
|
|
397
523
|
return { ...base, status: "error" };
|
|
@@ -437,6 +563,9 @@ function normalizeCodexUsage(httpStatus, rawPayload) {
|
|
|
437
563
|
}
|
|
438
564
|
|
|
439
565
|
// src/api-client.ts
|
|
566
|
+
var CODEX_READ_TIMEOUT_MS = 5e3;
|
|
567
|
+
var RESET_CREDIT_DETAILS_TIMEOUT_MS = 5e3;
|
|
568
|
+
var RESET_CREDIT_CONSUME_TIMEOUT_MS = 1e4;
|
|
440
569
|
function subscriptionHeaders(a) {
|
|
441
570
|
return {
|
|
442
571
|
Authorization: `Bearer ${a.accessToken}`,
|
|
@@ -447,35 +576,178 @@ function subscriptionHeaders(a) {
|
|
|
447
576
|
...a.isFedramp ? { "X-OpenAI-Fedramp": "true" } : {}
|
|
448
577
|
};
|
|
449
578
|
}
|
|
450
|
-
async function fetchCodexModels(a, fetchImpl = fetch) {
|
|
451
|
-
const
|
|
452
|
-
|
|
453
|
-
|
|
579
|
+
async function fetchCodexModels(a, fetchImpl = fetch, timeoutMs = CODEX_READ_TIMEOUT_MS) {
|
|
580
|
+
const fetched = await runBoundedCodexOperation(async (signal) => {
|
|
581
|
+
const res = await fetchImpl(
|
|
582
|
+
`${CODEX_RESPONSES_BASE}/models?client_version=${encodeURIComponent(a.clientVersion)}`,
|
|
583
|
+
{ method: "GET", headers: subscriptionHeaders(a), signal }
|
|
584
|
+
);
|
|
585
|
+
if (!res.ok) {
|
|
586
|
+
await res.arrayBuffer().catch(() => void 0);
|
|
587
|
+
return { ok: false, status: res.status, slugs: [] };
|
|
588
|
+
}
|
|
589
|
+
const body = await res.json();
|
|
590
|
+
const slugs = (body.models ?? []).map((model) => model.slug).filter((slug) => typeof slug === "string");
|
|
591
|
+
return { ok: true, status: res.status, slugs };
|
|
592
|
+
}, timeoutMs);
|
|
593
|
+
return fetched.ok ? fetched.value : { ok: false, status: 0, slugs: [] };
|
|
594
|
+
}
|
|
595
|
+
async function fetchCodexUsage(a, fetchImpl = fetch, timeoutMs = CODEX_READ_TIMEOUT_MS) {
|
|
596
|
+
const fetched = await runBoundedCodexOperation(async (signal) => {
|
|
597
|
+
const res = await fetchImpl(`${CODEX_WHAM_BASE}/wham/usage`, {
|
|
454
598
|
method: "GET",
|
|
455
|
-
headers: subscriptionHeaders(a)
|
|
599
|
+
headers: subscriptionHeaders(a),
|
|
600
|
+
signal
|
|
601
|
+
});
|
|
602
|
+
const payload = res.ok || res.status === 404 ? await res.json().catch(() => null) : null;
|
|
603
|
+
if (!res.ok && res.status !== 404) await res.arrayBuffer().catch(() => void 0);
|
|
604
|
+
return { status: res.status, payload };
|
|
605
|
+
}, timeoutMs);
|
|
606
|
+
if (!fetched.ok) throw new Error(`Codex usage request ${fetched.reason}`);
|
|
607
|
+
return fetched.value;
|
|
608
|
+
}
|
|
609
|
+
async function fetchCodexRateLimitResetCredits(a, fetchImpl = fetch, timeoutMs = RESET_CREDIT_DETAILS_TIMEOUT_MS) {
|
|
610
|
+
const fetched = await runBoundedCodexOperation(async (signal) => {
|
|
611
|
+
const res = await fetchImpl(`${CODEX_WHAM_BASE}/wham/rate-limit-reset-credits`, {
|
|
612
|
+
method: "GET",
|
|
613
|
+
headers: subscriptionHeaders(a),
|
|
614
|
+
signal
|
|
615
|
+
});
|
|
616
|
+
if (!res.ok) {
|
|
617
|
+
await res.arrayBuffer().catch(() => void 0);
|
|
618
|
+
return { ok: false, status: res.status, reason: "http_error" };
|
|
456
619
|
}
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
const
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
620
|
+
const details = parseCodexRateLimitResetCreditsDetails(await res.json().catch(() => null));
|
|
621
|
+
return details ? { ok: true, status: res.status, details } : { ok: false, status: res.status, reason: "invalid_response" };
|
|
622
|
+
}, timeoutMs);
|
|
623
|
+
return fetched.ok ? fetched.value : { ok: false, status: 0, reason: fetched.reason };
|
|
624
|
+
}
|
|
625
|
+
async function consumeCodexRateLimitResetCredit(a, input, fetchImpl = fetch, timeoutMs = RESET_CREDIT_CONSUME_TIMEOUT_MS) {
|
|
626
|
+
if (input.idempotencyKey.length === 0 || input.creditId === "") {
|
|
627
|
+
return { ok: false, status: 0, reason: "invalid_request" };
|
|
628
|
+
}
|
|
629
|
+
const fetched = await runBoundedCodexOperation(async (signal) => {
|
|
630
|
+
const res = await fetchImpl(`${CODEX_WHAM_BASE}/wham/rate-limit-reset-credits/consume`, {
|
|
631
|
+
method: "POST",
|
|
632
|
+
headers: {
|
|
633
|
+
...subscriptionHeaders(a),
|
|
634
|
+
"content-type": "application/json"
|
|
635
|
+
},
|
|
636
|
+
body: JSON.stringify({
|
|
637
|
+
redeem_request_id: input.idempotencyKey,
|
|
638
|
+
...input.creditId ? { credit_id: input.creditId } : {}
|
|
639
|
+
}),
|
|
640
|
+
signal
|
|
641
|
+
});
|
|
642
|
+
if (!res.ok) {
|
|
643
|
+
await res.arrayBuffer().catch(() => void 0);
|
|
644
|
+
return { ok: false, status: res.status, reason: "http_error" };
|
|
645
|
+
}
|
|
646
|
+
const result = parseCodexRateLimitResetConsumeResponse(await res.json().catch(() => null));
|
|
647
|
+
return result ? { ok: true, status: res.status, result } : { ok: false, status: res.status, reason: "invalid_response" };
|
|
648
|
+
}, timeoutMs);
|
|
649
|
+
return fetched.ok ? fetched.value : { ok: false, status: 0, reason: fetched.reason };
|
|
472
650
|
}
|
|
473
651
|
|
|
474
652
|
// src/request-context.ts
|
|
475
653
|
import { AsyncLocalStorage } from "async_hooks";
|
|
476
654
|
var codexRequestStorage = new AsyncLocalStorage();
|
|
477
655
|
|
|
656
|
+
// src/response-timeout.ts
|
|
657
|
+
var CODEX_RESPONSE_TIMEOUT_ERROR_TYPE = "opengeni_codex_response_timeout";
|
|
658
|
+
var DEFAULT_CODEX_RESPONSE_TIMEOUT_POLICY = Object.freeze({
|
|
659
|
+
headersTimeoutMs: CODEX_RESPONSE_HEADERS_TIMEOUT_MS,
|
|
660
|
+
streamIdleTimeoutMs: CODEX_RESPONSE_STREAM_IDLE_TIMEOUT_MS,
|
|
661
|
+
wholeRequestTimeoutMs: CODEX_RESPONSE_WHOLE_TIMEOUT_MS,
|
|
662
|
+
noByteRetries: CODEX_RESPONSE_NO_BYTE_RETRIES,
|
|
663
|
+
retryBackoffMs: CODEX_RESPONSE_RETRY_BACKOFF_MS
|
|
664
|
+
});
|
|
665
|
+
function positiveFinite(value, fallback) {
|
|
666
|
+
return value !== void 0 && Number.isFinite(value) && value > 0 ? value : fallback;
|
|
667
|
+
}
|
|
668
|
+
function resolveCodexResponseTimeoutPolicy(override) {
|
|
669
|
+
return {
|
|
670
|
+
headersTimeoutMs: positiveFinite(
|
|
671
|
+
override?.headersTimeoutMs,
|
|
672
|
+
DEFAULT_CODEX_RESPONSE_TIMEOUT_POLICY.headersTimeoutMs
|
|
673
|
+
),
|
|
674
|
+
streamIdleTimeoutMs: positiveFinite(
|
|
675
|
+
override?.streamIdleTimeoutMs,
|
|
676
|
+
DEFAULT_CODEX_RESPONSE_TIMEOUT_POLICY.streamIdleTimeoutMs
|
|
677
|
+
),
|
|
678
|
+
wholeRequestTimeoutMs: positiveFinite(
|
|
679
|
+
override?.wholeRequestTimeoutMs,
|
|
680
|
+
DEFAULT_CODEX_RESPONSE_TIMEOUT_POLICY.wholeRequestTimeoutMs
|
|
681
|
+
),
|
|
682
|
+
// Automatic replay is fail-closed until the provider operation can be
|
|
683
|
+
// durably read/reconciled. Keep the field for policy/event compatibility,
|
|
684
|
+
// but never let a caller opt back into an unproved retry.
|
|
685
|
+
noByteRetries: 0,
|
|
686
|
+
retryBackoffMs: override?.retryBackoffMs !== void 0 && Number.isFinite(override.retryBackoffMs) && override.retryBackoffMs >= 0 ? override.retryBackoffMs : DEFAULT_CODEX_RESPONSE_TIMEOUT_POLICY.retryBackoffMs
|
|
687
|
+
};
|
|
688
|
+
}
|
|
689
|
+
var CodexResponseTimeoutError = class extends Error {
|
|
690
|
+
constructor(timeoutClass, requestId, responseObserved, message = `Codex response ${timeoutClass.replaceAll("_", " ")} timed out`) {
|
|
691
|
+
super(message);
|
|
692
|
+
this.timeoutClass = timeoutClass;
|
|
693
|
+
this.requestId = requestId;
|
|
694
|
+
this.responseObserved = responseObserved;
|
|
695
|
+
this.name = "CodexResponseTimeoutError";
|
|
696
|
+
}
|
|
697
|
+
code = CODEX_RESPONSE_TIMEOUT_ERROR_TYPE;
|
|
698
|
+
type = CODEX_RESPONSE_TIMEOUT_ERROR_TYPE;
|
|
699
|
+
};
|
|
700
|
+
function parseTimeoutClass(value) {
|
|
701
|
+
return value === "connect" || value === "headers" || value === "idle_stream" || value === "whole_request" ? value : null;
|
|
702
|
+
}
|
|
703
|
+
function classifyCodexResponseTimeoutError(error, options = {}) {
|
|
704
|
+
let current = error;
|
|
705
|
+
for (let depth = 0; depth < 8 && current && typeof current === "object"; depth += 1) {
|
|
706
|
+
const value = current;
|
|
707
|
+
const nested = value.error && typeof value.error === "object" ? value.error : void 0;
|
|
708
|
+
const type = (typeof value.type === "string" ? value.type : void 0) ?? (typeof value.code === "string" ? value.code : void 0) ?? (typeof nested?.type === "string" ? nested.type : void 0) ?? (typeof nested?.code === "string" ? nested.code : void 0);
|
|
709
|
+
if (type === CODEX_RESPONSE_TIMEOUT_ERROR_TYPE || value.name === "CodexResponseTimeoutError") {
|
|
710
|
+
const klass = parseTimeoutClass(value.timeoutClass) ?? parseTimeoutClass(nested?.timeout_class) ?? "headers";
|
|
711
|
+
return {
|
|
712
|
+
timeoutClass: klass,
|
|
713
|
+
requestId: (typeof value.requestId === "string" ? value.requestId : void 0) ?? (typeof nested?.request_id === "string" ? nested.request_id : null),
|
|
714
|
+
responseObserved: typeof value.responseObserved === "boolean" ? value.responseObserved : nested?.response_observed === true,
|
|
715
|
+
message: (typeof value.message === "string" ? value.message : void 0) ?? (typeof nested?.message === "string" ? nested.message : "Codex response timed out")
|
|
716
|
+
};
|
|
717
|
+
}
|
|
718
|
+
current = value.cause;
|
|
719
|
+
}
|
|
720
|
+
if (options.allowLegacyRequestTimeout && error && typeof error === "object") {
|
|
721
|
+
const value = error;
|
|
722
|
+
if (value.name === "APIConnectionTimeoutError" || value.message === "Request timed out." && value.name === "Error") {
|
|
723
|
+
return {
|
|
724
|
+
timeoutClass: "headers",
|
|
725
|
+
requestId: null,
|
|
726
|
+
responseObserved: false,
|
|
727
|
+
message: String(value.message ?? "Request timed out.")
|
|
728
|
+
};
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
return null;
|
|
732
|
+
}
|
|
733
|
+
function isPreHeadersTimeoutError(error) {
|
|
734
|
+
const structured = classifyCodexResponseTimeoutError(error);
|
|
735
|
+
if (structured && !structured.responseObserved) {
|
|
736
|
+
return structured.timeoutClass;
|
|
737
|
+
}
|
|
738
|
+
if (!error || typeof error !== "object") return null;
|
|
739
|
+
const value = error;
|
|
740
|
+
const code = typeof value.code === "string" ? value.code : "";
|
|
741
|
+
const name = typeof value.name === "string" ? value.name : "";
|
|
742
|
+
const message = typeof value.message === "string" ? value.message : String(error);
|
|
743
|
+
if (/^(?:ETIMEDOUT|UND_ERR_CONNECT_TIMEOUT)$/i.test(code) || /ConnectTimeout/i.test(name)) {
|
|
744
|
+
return "connect";
|
|
745
|
+
}
|
|
746
|
+
return /connect(?:ion)?[^.]*timed?\s*out/i.test(`${name} ${message}`) ? "connect" : null;
|
|
747
|
+
}
|
|
748
|
+
|
|
478
749
|
// src/fetch.ts
|
|
750
|
+
import { randomUUID } from "crypto";
|
|
479
751
|
var CODEX_TRANSPORT_ERROR_HEADER = "x-opengeni-codex-transport-error";
|
|
480
752
|
function headersCarryCodexTransportMarker(headers) {
|
|
481
753
|
if (!headers || typeof headers !== "object") return false;
|
|
@@ -538,6 +810,210 @@ function parseCodexUsageHeaders(headers) {
|
|
|
538
810
|
checkedAt: new Date(nowMs)
|
|
539
811
|
};
|
|
540
812
|
}
|
|
813
|
+
async function emitRequestEvent(audit, event) {
|
|
814
|
+
await audit.ctx.onModelRequestEvent?.({
|
|
815
|
+
requestId: audit.requestId,
|
|
816
|
+
transportAttempt: audit.transportAttempt,
|
|
817
|
+
...audit.model ? { model: audit.model } : {},
|
|
818
|
+
durationMs: Math.max(0, Date.now() - audit.attemptStartedAt),
|
|
819
|
+
timeoutPolicy: audit.policy,
|
|
820
|
+
...event
|
|
821
|
+
});
|
|
822
|
+
}
|
|
823
|
+
function providerRequestId(headers) {
|
|
824
|
+
return headers.get("x-request-id") ?? headers.get("request-id") ?? void 0;
|
|
825
|
+
}
|
|
826
|
+
async function fetchBeforeHeaders(base, input, init, audit) {
|
|
827
|
+
const elapsed = Date.now() - audit.logicalStartedAt;
|
|
828
|
+
const wholeRemainingMs = audit.policy.wholeRequestTimeoutMs - elapsed;
|
|
829
|
+
const timeoutClass = wholeRemainingMs <= audit.policy.headersTimeoutMs ? "whole_request" : "headers";
|
|
830
|
+
const deadlineMs = Math.max(1, Math.min(audit.policy.headersTimeoutMs, wholeRemainingMs));
|
|
831
|
+
if (wholeRemainingMs <= 0) {
|
|
832
|
+
throw new CodexResponseTimeoutError("whole_request", audit.requestId, false);
|
|
833
|
+
}
|
|
834
|
+
const externalSignal = init.signal;
|
|
835
|
+
if (externalSignal?.aborted) throw externalSignal.reason;
|
|
836
|
+
const controller = new AbortController();
|
|
837
|
+
const forwardAbort = () => controller.abort(externalSignal?.reason);
|
|
838
|
+
externalSignal?.addEventListener("abort", forwardAbort, { once: true });
|
|
839
|
+
const basePromise = base(input, { ...init, signal: controller.signal });
|
|
840
|
+
let deadlineError = null;
|
|
841
|
+
let timer;
|
|
842
|
+
const deadline = new Promise((_resolve, reject) => {
|
|
843
|
+
timer = setTimeout(() => {
|
|
844
|
+
deadlineError = new CodexResponseTimeoutError(timeoutClass, audit.requestId, false);
|
|
845
|
+
reject(deadlineError);
|
|
846
|
+
}, deadlineMs);
|
|
847
|
+
});
|
|
848
|
+
try {
|
|
849
|
+
return await Promise.race([basePromise, deadline]);
|
|
850
|
+
} catch (error) {
|
|
851
|
+
if (deadlineError) {
|
|
852
|
+
controller.abort(deadlineError);
|
|
853
|
+
void basePromise.then((late) => late.body?.cancel(deadlineError ?? void 0)).catch(() => void 0);
|
|
854
|
+
throw deadlineError;
|
|
855
|
+
}
|
|
856
|
+
throw error;
|
|
857
|
+
} finally {
|
|
858
|
+
if (timer) clearTimeout(timer);
|
|
859
|
+
externalSignal?.removeEventListener("abort", forwardAbort);
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
async function observedResponse(res, audit, externalSignal) {
|
|
863
|
+
const requestId = providerRequestId(res.headers);
|
|
864
|
+
if (!res.body) {
|
|
865
|
+
await emitRequestEvent(audit, {
|
|
866
|
+
phase: res.ok ? "completed" : "failed",
|
|
867
|
+
responseObserved: true,
|
|
868
|
+
status: res.status,
|
|
869
|
+
...requestId ? { providerRequestId: requestId } : {}
|
|
870
|
+
});
|
|
871
|
+
return res;
|
|
872
|
+
}
|
|
873
|
+
const reader = res.body.getReader();
|
|
874
|
+
let terminal = false;
|
|
875
|
+
let firstByte = false;
|
|
876
|
+
let idleTimer;
|
|
877
|
+
let wholeTimer;
|
|
878
|
+
let armIdle = () => void 0;
|
|
879
|
+
let abortFromOutside;
|
|
880
|
+
const clearTimers = () => {
|
|
881
|
+
if (idleTimer) clearTimeout(idleTimer);
|
|
882
|
+
if (wholeTimer) clearTimeout(wholeTimer);
|
|
883
|
+
if (abortFromOutside) externalSignal?.removeEventListener("abort", abortFromOutside);
|
|
884
|
+
};
|
|
885
|
+
const body = new ReadableStream({
|
|
886
|
+
start(controller) {
|
|
887
|
+
const timeOut = (klass) => {
|
|
888
|
+
if (terminal) return;
|
|
889
|
+
terminal = true;
|
|
890
|
+
clearTimers();
|
|
891
|
+
const error = new CodexResponseTimeoutError(klass, audit.requestId, true);
|
|
892
|
+
void reader.cancel(error).catch(() => void 0);
|
|
893
|
+
void emitRequestEvent(audit, {
|
|
894
|
+
phase: "timed_out",
|
|
895
|
+
responseObserved: true,
|
|
896
|
+
timeoutClass: klass,
|
|
897
|
+
status: res.status,
|
|
898
|
+
...requestId ? { providerRequestId: requestId } : {}
|
|
899
|
+
}).then(
|
|
900
|
+
() => controller.error(error),
|
|
901
|
+
() => controller.error(error)
|
|
902
|
+
);
|
|
903
|
+
};
|
|
904
|
+
armIdle = () => {
|
|
905
|
+
if (idleTimer) clearTimeout(idleTimer);
|
|
906
|
+
idleTimer = setTimeout(() => timeOut("idle_stream"), audit.policy.streamIdleTimeoutMs);
|
|
907
|
+
};
|
|
908
|
+
armIdle();
|
|
909
|
+
const wholeRemaining = Math.max(
|
|
910
|
+
1,
|
|
911
|
+
audit.policy.wholeRequestTimeoutMs - (Date.now() - audit.logicalStartedAt)
|
|
912
|
+
);
|
|
913
|
+
wholeTimer = setTimeout(() => timeOut("whole_request"), wholeRemaining);
|
|
914
|
+
abortFromOutside = () => {
|
|
915
|
+
if (terminal) return;
|
|
916
|
+
terminal = true;
|
|
917
|
+
clearTimers();
|
|
918
|
+
const reason = externalSignal?.reason ?? new DOMException("Aborted", "AbortError");
|
|
919
|
+
void reader.cancel(reason).catch(() => void 0);
|
|
920
|
+
void emitRequestEvent(audit, {
|
|
921
|
+
phase: "failed",
|
|
922
|
+
responseObserved: true,
|
|
923
|
+
status: res.status,
|
|
924
|
+
...requestId ? { providerRequestId: requestId } : {}
|
|
925
|
+
}).then(
|
|
926
|
+
() => controller.error(reason),
|
|
927
|
+
() => controller.error(reason)
|
|
928
|
+
);
|
|
929
|
+
};
|
|
930
|
+
if (externalSignal?.aborted) {
|
|
931
|
+
abortFromOutside();
|
|
932
|
+
} else {
|
|
933
|
+
externalSignal?.addEventListener("abort", abortFromOutside, { once: true });
|
|
934
|
+
}
|
|
935
|
+
},
|
|
936
|
+
async pull(controller) {
|
|
937
|
+
if (terminal) return;
|
|
938
|
+
try {
|
|
939
|
+
const chunk = await reader.read();
|
|
940
|
+
if (terminal) return;
|
|
941
|
+
if (chunk.done) {
|
|
942
|
+
terminal = true;
|
|
943
|
+
clearTimers();
|
|
944
|
+
await emitRequestEvent(audit, {
|
|
945
|
+
phase: res.ok ? "completed" : "failed",
|
|
946
|
+
responseObserved: true,
|
|
947
|
+
status: res.status,
|
|
948
|
+
...requestId ? { providerRequestId: requestId } : {}
|
|
949
|
+
});
|
|
950
|
+
controller.close();
|
|
951
|
+
return;
|
|
952
|
+
}
|
|
953
|
+
armIdle();
|
|
954
|
+
if (!firstByte) {
|
|
955
|
+
firstByte = true;
|
|
956
|
+
await emitRequestEvent(audit, {
|
|
957
|
+
phase: "first_byte",
|
|
958
|
+
responseObserved: true,
|
|
959
|
+
status: res.status,
|
|
960
|
+
...requestId ? { providerRequestId: requestId } : {}
|
|
961
|
+
});
|
|
962
|
+
}
|
|
963
|
+
controller.enqueue(chunk.value);
|
|
964
|
+
} catch (error) {
|
|
965
|
+
if (terminal) return;
|
|
966
|
+
terminal = true;
|
|
967
|
+
clearTimers();
|
|
968
|
+
await emitRequestEvent(audit, {
|
|
969
|
+
phase: "failed",
|
|
970
|
+
responseObserved: true,
|
|
971
|
+
status: res.status,
|
|
972
|
+
...requestId ? { providerRequestId: requestId } : {}
|
|
973
|
+
});
|
|
974
|
+
controller.error(error);
|
|
975
|
+
}
|
|
976
|
+
},
|
|
977
|
+
async cancel(reason) {
|
|
978
|
+
if (!terminal) {
|
|
979
|
+
terminal = true;
|
|
980
|
+
clearTimers();
|
|
981
|
+
await emitRequestEvent(audit, {
|
|
982
|
+
phase: "failed",
|
|
983
|
+
responseObserved: true,
|
|
984
|
+
status: res.status,
|
|
985
|
+
...requestId ? { providerRequestId: requestId } : {}
|
|
986
|
+
}).catch(() => void 0);
|
|
987
|
+
}
|
|
988
|
+
await reader.cancel(reason).catch(() => void 0);
|
|
989
|
+
}
|
|
990
|
+
});
|
|
991
|
+
const headers = new Headers(res.headers);
|
|
992
|
+
headers.delete("content-length");
|
|
993
|
+
return new Response(body, { status: res.status, statusText: res.statusText, headers });
|
|
994
|
+
}
|
|
995
|
+
function timeoutErrorResponse(info) {
|
|
996
|
+
return new Response(
|
|
997
|
+
JSON.stringify({
|
|
998
|
+
error: {
|
|
999
|
+
type: CODEX_RESPONSE_TIMEOUT_ERROR_TYPE,
|
|
1000
|
+
code: CODEX_RESPONSE_TIMEOUT_ERROR_TYPE,
|
|
1001
|
+
message: info.message,
|
|
1002
|
+
timeout_class: info.timeoutClass,
|
|
1003
|
+
response_observed: info.responseObserved,
|
|
1004
|
+
request_id: info.requestId
|
|
1005
|
+
}
|
|
1006
|
+
}),
|
|
1007
|
+
{
|
|
1008
|
+
status: 504,
|
|
1009
|
+
headers: {
|
|
1010
|
+
"content-type": "application/json",
|
|
1011
|
+
"x-should-retry": "false",
|
|
1012
|
+
[CODEX_TRANSPORT_ERROR_HEADER]: "1"
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
);
|
|
1016
|
+
}
|
|
541
1017
|
function codexSubscriptionFetch(base = globalThis.fetch) {
|
|
542
1018
|
return async (input, init) => {
|
|
543
1019
|
const ctx = codexRequestStorage.getStore();
|
|
@@ -546,7 +1022,11 @@ function codexSubscriptionFetch(base = globalThis.fetch) {
|
|
|
546
1022
|
}
|
|
547
1023
|
const rawUrl = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
|
|
548
1024
|
const rewritten = rawUrl.replace(/(?<!\/codex)\/responses(\b|$)/, "/codex/responses$1");
|
|
549
|
-
const
|
|
1025
|
+
const policy = resolveCodexResponseTimeoutPolicy(ctx.responseTimeoutPolicy);
|
|
1026
|
+
const requestId = ctx.nextRequestId?.() ?? randomUUID();
|
|
1027
|
+
const logicalStartedAt = Date.now();
|
|
1028
|
+
let transportAttempt = 0;
|
|
1029
|
+
const attempt = async (auth, authenticationAttempt) => {
|
|
550
1030
|
const headers = new Headers(init?.headers);
|
|
551
1031
|
headers.set("Authorization", `Bearer ${auth.accessToken}`);
|
|
552
1032
|
if (auth.chatgptAccountId) {
|
|
@@ -566,41 +1046,114 @@ function codexSubscriptionFetch(base = globalThis.fetch) {
|
|
|
566
1046
|
headers.delete("OpenAI-Beta");
|
|
567
1047
|
headers.delete("x-api-key");
|
|
568
1048
|
let callerWantsStream = true;
|
|
1049
|
+
let model;
|
|
569
1050
|
const nextInit = { ...init, headers };
|
|
570
1051
|
if (typeof init?.body === "string") {
|
|
571
1052
|
try {
|
|
572
1053
|
const parsed = JSON.parse(init.body);
|
|
573
1054
|
callerWantsStream = parsed.stream === true;
|
|
574
|
-
|
|
1055
|
+
const normalized = normalizeCodexRequestBody(parsed, ctx.resolveModel);
|
|
1056
|
+
model = typeof normalized.model === "string" ? normalized.model : void 0;
|
|
1057
|
+
nextInit.body = JSON.stringify(normalized);
|
|
575
1058
|
} catch {
|
|
576
1059
|
}
|
|
577
1060
|
}
|
|
1061
|
+
headers.set(
|
|
1062
|
+
"Idempotency-Key",
|
|
1063
|
+
authenticationAttempt === 0 ? requestId : `${requestId}:auth-${authenticationAttempt}`
|
|
1064
|
+
);
|
|
578
1065
|
if (process.env.CODEX_DEBUG) {
|
|
579
|
-
|
|
1066
|
+
let keys = [];
|
|
1067
|
+
if (typeof nextInit.body === "string") {
|
|
1068
|
+
try {
|
|
1069
|
+
keys = Object.keys(JSON.parse(nextInit.body));
|
|
1070
|
+
} catch {
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
580
1073
|
console.error(
|
|
581
1074
|
`[codex-debug] POST ${rewritten} stream=${callerWantsStream} bodyKeys=[${keys.join(",")}]`
|
|
582
1075
|
);
|
|
583
1076
|
}
|
|
584
|
-
|
|
585
|
-
|
|
1077
|
+
let res;
|
|
1078
|
+
transportAttempt += 1;
|
|
1079
|
+
const audit = {
|
|
1080
|
+
ctx,
|
|
1081
|
+
requestId,
|
|
1082
|
+
transportAttempt,
|
|
1083
|
+
...model ? { model } : {},
|
|
1084
|
+
logicalStartedAt,
|
|
1085
|
+
attemptStartedAt: Date.now(),
|
|
1086
|
+
policy
|
|
1087
|
+
};
|
|
1088
|
+
await emitRequestEvent(audit, {
|
|
1089
|
+
phase: "started",
|
|
1090
|
+
responseObserved: false
|
|
1091
|
+
});
|
|
1092
|
+
try {
|
|
1093
|
+
res = await fetchBeforeHeaders(base, rewritten, nextInit, audit);
|
|
1094
|
+
const upstreamRequestId = providerRequestId(res.headers);
|
|
1095
|
+
await emitRequestEvent(audit, {
|
|
1096
|
+
phase: "headers",
|
|
1097
|
+
responseObserved: true,
|
|
1098
|
+
status: res.status,
|
|
1099
|
+
...upstreamRequestId ? { providerRequestId: upstreamRequestId } : {}
|
|
1100
|
+
});
|
|
1101
|
+
const observed = await observedResponse(res, audit, nextInit.signal);
|
|
1102
|
+
res = observed;
|
|
1103
|
+
} catch (error) {
|
|
1104
|
+
if (nextInit.signal?.aborted) {
|
|
1105
|
+
await emitRequestEvent(audit, {
|
|
1106
|
+
phase: "failed",
|
|
1107
|
+
responseObserved: false
|
|
1108
|
+
}).catch(() => void 0);
|
|
1109
|
+
throw error;
|
|
1110
|
+
}
|
|
1111
|
+
const klass = isPreHeadersTimeoutError(error);
|
|
1112
|
+
if (!klass) {
|
|
1113
|
+
await emitRequestEvent(audit, {
|
|
1114
|
+
phase: "failed",
|
|
1115
|
+
responseObserved: false
|
|
1116
|
+
});
|
|
1117
|
+
throw error;
|
|
1118
|
+
}
|
|
1119
|
+
await emitRequestEvent(audit, {
|
|
1120
|
+
phase: "timed_out",
|
|
1121
|
+
responseObserved: false,
|
|
1122
|
+
timeoutClass: klass,
|
|
1123
|
+
willRetry: false
|
|
1124
|
+
}).catch(() => void 0);
|
|
1125
|
+
throw new CodexResponseTimeoutError(klass, requestId, false);
|
|
1126
|
+
}
|
|
1127
|
+
const usage = parseCodexUsageHeaders(res.headers);
|
|
586
1128
|
if (usage) {
|
|
587
1129
|
ctx.onUsageHeaders?.(usage);
|
|
588
1130
|
}
|
|
589
|
-
if (process.env.CODEX_DEBUG && !
|
|
1131
|
+
if (process.env.CODEX_DEBUG && !res.ok) {
|
|
590
1132
|
console.error(
|
|
591
|
-
`[codex-debug] <- ${
|
|
1133
|
+
`[codex-debug] <- ${res.status} requestId=${res.headers.get("x-request-id") ?? "unknown"}`
|
|
592
1134
|
);
|
|
593
1135
|
}
|
|
594
|
-
if (!
|
|
595
|
-
return await bufferCodexErrorResponse(
|
|
1136
|
+
if (!res.ok) {
|
|
1137
|
+
return await bufferCodexErrorResponse(res);
|
|
596
1138
|
}
|
|
597
|
-
return callerWantsStream ? repairCodexStream(
|
|
1139
|
+
return callerWantsStream ? repairCodexStream(res) : await sseToJsonResponse(res);
|
|
598
1140
|
};
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
res
|
|
1141
|
+
try {
|
|
1142
|
+
let res = await attempt(await ctx.getToken(), 0);
|
|
1143
|
+
if (res.status === 401) {
|
|
1144
|
+
res = await attempt(await ctx.refresh(), 1);
|
|
1145
|
+
}
|
|
1146
|
+
return res;
|
|
1147
|
+
} catch (error) {
|
|
1148
|
+
const timeout = classifyCodexResponseTimeoutError(error);
|
|
1149
|
+
if (!timeout) throw error;
|
|
1150
|
+
return timeoutErrorResponse({
|
|
1151
|
+
timeoutClass: timeout.timeoutClass,
|
|
1152
|
+
requestId: timeout.requestId ?? requestId,
|
|
1153
|
+
responseObserved: timeout.responseObserved,
|
|
1154
|
+
message: timeout.message
|
|
1155
|
+
});
|
|
602
1156
|
}
|
|
603
|
-
return res;
|
|
604
1157
|
};
|
|
605
1158
|
}
|
|
606
1159
|
var CODEX_USAGE_LIMIT_ERROR_TYPE = "usage_limit_reached";
|
|
@@ -1648,9 +2201,17 @@ export {
|
|
|
1648
2201
|
CODEX_ORIGINATOR,
|
|
1649
2202
|
CODEX_PROVIDER_BASE_URL,
|
|
1650
2203
|
CODEX_PROVIDER_ID,
|
|
2204
|
+
CODEX_RATE_LIMIT_RESET_OUTCOMES,
|
|
1651
2205
|
CODEX_REFRESH_FALLBACK_MS,
|
|
1652
2206
|
CODEX_REFRESH_WINDOW_MS,
|
|
1653
2207
|
CODEX_RESPONSES_BASE,
|
|
2208
|
+
CODEX_RESPONSE_HEADERS_TIMEOUT_MS,
|
|
2209
|
+
CODEX_RESPONSE_NO_BYTE_RETRIES,
|
|
2210
|
+
CODEX_RESPONSE_RETRY_BACKOFF_MS,
|
|
2211
|
+
CODEX_RESPONSE_SDK_OUTER_TIMEOUT_MS,
|
|
2212
|
+
CODEX_RESPONSE_STREAM_IDLE_TIMEOUT_MS,
|
|
2213
|
+
CODEX_RESPONSE_TIMEOUT_ERROR_TYPE,
|
|
2214
|
+
CODEX_RESPONSE_WHOLE_TIMEOUT_MS,
|
|
1654
2215
|
CODEX_TOKEN_URL,
|
|
1655
2216
|
CODEX_TOOL_OUTPUT_SERIALIZATION_ALLOWANCE,
|
|
1656
2217
|
CODEX_TRANSPORT_ERROR_HEADER,
|
|
@@ -1660,7 +2221,9 @@ export {
|
|
|
1660
2221
|
CodexDeviceError,
|
|
1661
2222
|
CodexRefreshTransient,
|
|
1662
2223
|
CodexReloginRequired,
|
|
2224
|
+
CodexResponseTimeoutError,
|
|
1663
2225
|
CodexStreamingTerminalError,
|
|
2226
|
+
DEFAULT_CODEX_RESPONSE_TIMEOUT_POLICY,
|
|
1664
2227
|
DEFAULT_MODEL_TOOL_OUTPUT_TRUNCATION_TOKENS,
|
|
1665
2228
|
MODEL_TOOL_OUTPUT_OPAQUE_PAYLOAD_MAX_BYTES,
|
|
1666
2229
|
MODEL_TOOL_OUTPUT_OVERSIZED_IMAGE_CARD_DATA_URL,
|
|
@@ -1671,24 +2234,32 @@ export {
|
|
|
1671
2234
|
boundModelToolOutputItems,
|
|
1672
2235
|
buildCodexUsageWindowFromCache,
|
|
1673
2236
|
buildModelResolver,
|
|
2237
|
+
classifyCodexResponseTimeoutError,
|
|
1674
2238
|
classifyCodexUsageLimitError,
|
|
1675
2239
|
codexAppsSanitizingFetch,
|
|
1676
2240
|
codexRequestStorage,
|
|
1677
2241
|
codexSubscriptionFetch,
|
|
2242
|
+
consumeCodexRateLimitResetCredit,
|
|
1678
2243
|
decodeJwtPayload,
|
|
1679
2244
|
exchangeDeviceCode,
|
|
1680
2245
|
fetchCodexModels,
|
|
2246
|
+
fetchCodexRateLimitResetCredits,
|
|
1681
2247
|
fetchCodexUsage,
|
|
1682
2248
|
isCodexBilledModel,
|
|
1683
2249
|
isCodexTransportError,
|
|
2250
|
+
isPreHeadersTimeoutError,
|
|
1684
2251
|
modelToolOutputSerializationBudgetTokens,
|
|
1685
2252
|
normalizeCodexRequestBody,
|
|
1686
2253
|
normalizeCodexUsage,
|
|
2254
|
+
parseCodexRateLimitResetConsumeResponse,
|
|
2255
|
+
parseCodexRateLimitResetCreditsDetails,
|
|
2256
|
+
parseCodexRateLimitResetCreditsSummary,
|
|
1687
2257
|
parseCodexUsageHeaders,
|
|
1688
2258
|
parseIdToken,
|
|
1689
2259
|
pollDeviceCode,
|
|
1690
2260
|
refreshCodexToken,
|
|
1691
2261
|
remapToolCallRequestBody,
|
|
2262
|
+
resolveCodexResponseTimeoutPolicy,
|
|
1692
2263
|
sanitizeMcpJsonBody,
|
|
1693
2264
|
sanitizeMcpSseBody,
|
|
1694
2265
|
startDeviceCode,
|