@opengeni/codex 0.2.3 → 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-K47573CJ.js → chunk-YGKQDUY7.js} +14 -2
- package/dist/{chunk-K47573CJ.js.map → chunk-YGKQDUY7.js.map} +1 -1
- package/dist/constants.d.ts +8 -2
- package/dist/constants.js +13 -1
- package/dist/index.d.ts +231 -5
- package/dist/index.js +1402 -91
- 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 +20 -2
- package/src/fetch.ts +866 -49
- package/src/index.ts +3 -0
- package/src/model-output-truncation.ts +590 -0
- package/src/oversized-image-card.ts +18 -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`, {
|
|
598
|
+
method: "GET",
|
|
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`, {
|
|
454
612
|
method: "GET",
|
|
455
|
-
headers: subscriptionHeaders(a)
|
|
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
|
-
const body = await res.json();
|
|
462
|
-
const slugs = (body.models ?? []).map((m) => m.slug).filter((s) => typeof s === "string");
|
|
463
|
-
return { ok: true, status: res.status, slugs };
|
|
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 };
|
|
464
624
|
}
|
|
465
|
-
async function
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
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";
|
|
@@ -636,14 +1189,18 @@ async function bufferCodexErrorResponse(res) {
|
|
|
636
1189
|
if (errorType === CODEX_USAGE_LIMIT_ERROR_TYPE) {
|
|
637
1190
|
headers.set("x-should-retry", "false");
|
|
638
1191
|
}
|
|
639
|
-
return new Response(bodyText, {
|
|
1192
|
+
return new Response(bodyText, {
|
|
1193
|
+
status: res.status,
|
|
1194
|
+
statusText: res.statusText,
|
|
1195
|
+
headers
|
|
1196
|
+
});
|
|
640
1197
|
}
|
|
641
1198
|
async function sseToJsonResponse(res) {
|
|
642
1199
|
const text = await res.text();
|
|
643
1200
|
let final = null;
|
|
1201
|
+
let terminalError = null;
|
|
644
1202
|
const items = [];
|
|
645
|
-
for (const
|
|
646
|
-
const data = block.split("\n").filter((l) => l.startsWith("data:")).map((l) => l.slice(5).trim()).join("\n");
|
|
1203
|
+
for (const data of sseDataPayloads(text)) {
|
|
647
1204
|
if (!data || data === "[DONE]") {
|
|
648
1205
|
continue;
|
|
649
1206
|
}
|
|
@@ -651,12 +1208,64 @@ async function sseToJsonResponse(res) {
|
|
|
651
1208
|
const ev = JSON.parse(data);
|
|
652
1209
|
if (ev.type === "response.output_item.done" && ev.item !== void 0) {
|
|
653
1210
|
items.push(ev.item);
|
|
654
|
-
} else if (ev.type === "response.
|
|
1211
|
+
} else if (ev.type === "response.failed") {
|
|
1212
|
+
terminalError = codexSseFailureResponse(
|
|
1213
|
+
res,
|
|
1214
|
+
ev.response?.error,
|
|
1215
|
+
"response_failed",
|
|
1216
|
+
"The Codex response failed",
|
|
1217
|
+
{
|
|
1218
|
+
eventType: ev.type,
|
|
1219
|
+
responseId: ev.response?.id,
|
|
1220
|
+
responseStatus: ev.response?.status
|
|
1221
|
+
}
|
|
1222
|
+
);
|
|
1223
|
+
} else if (ev.type === "error" || ev.type === "response.error") {
|
|
1224
|
+
terminalError = codexSseFailureResponse(
|
|
1225
|
+
res,
|
|
1226
|
+
ev.error ?? ev.response?.error ?? ev,
|
|
1227
|
+
"response_error",
|
|
1228
|
+
"The Codex response stream reported an error",
|
|
1229
|
+
{
|
|
1230
|
+
eventType: ev.type,
|
|
1231
|
+
responseId: ev.response?.id,
|
|
1232
|
+
responseStatus: ev.response?.status
|
|
1233
|
+
}
|
|
1234
|
+
);
|
|
1235
|
+
} else if (ev.type === "response.incomplete") {
|
|
1236
|
+
const details = ev.response?.incomplete_details;
|
|
1237
|
+
const reason = details && typeof details === "object" ? details.reason : void 0;
|
|
1238
|
+
terminalError = codexSseFailureResponse(
|
|
1239
|
+
res,
|
|
1240
|
+
{
|
|
1241
|
+
code: "response_incomplete",
|
|
1242
|
+
message: typeof reason === "string" && reason.length > 0 ? `The Codex response was incomplete (${reason})` : "The Codex response was incomplete"
|
|
1243
|
+
},
|
|
1244
|
+
"response_incomplete",
|
|
1245
|
+
"The Codex response was incomplete",
|
|
1246
|
+
{
|
|
1247
|
+
eventType: ev.type,
|
|
1248
|
+
responseId: ev.response?.id,
|
|
1249
|
+
responseStatus: ev.response?.status
|
|
1250
|
+
}
|
|
1251
|
+
);
|
|
1252
|
+
} else if (ev.type === "response.completed" || ev.type === "response.done") {
|
|
655
1253
|
final = ev.response ?? null;
|
|
656
1254
|
}
|
|
657
1255
|
} catch {
|
|
658
1256
|
}
|
|
659
1257
|
}
|
|
1258
|
+
if (terminalError) {
|
|
1259
|
+
return terminalError;
|
|
1260
|
+
}
|
|
1261
|
+
if (!final) {
|
|
1262
|
+
return codexSseFailureResponse(
|
|
1263
|
+
res,
|
|
1264
|
+
null,
|
|
1265
|
+
"invalid_sse_terminal",
|
|
1266
|
+
"The Codex response stream ended without a terminal response"
|
|
1267
|
+
);
|
|
1268
|
+
}
|
|
660
1269
|
if (final && items.length > 0) {
|
|
661
1270
|
final = { ...final, output: items };
|
|
662
1271
|
}
|
|
@@ -668,64 +1277,331 @@ async function sseToJsonResponse(res) {
|
|
|
668
1277
|
const headers = new Headers(res.headers);
|
|
669
1278
|
headers.set("content-type", "application/json");
|
|
670
1279
|
headers.delete("content-length");
|
|
671
|
-
return new Response(JSON.stringify(final
|
|
1280
|
+
return new Response(JSON.stringify(final), { status: 200, headers });
|
|
1281
|
+
}
|
|
1282
|
+
var NON_RETRYABLE_SSE_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
1283
|
+
"bio_policy",
|
|
1284
|
+
"context_length_exceeded",
|
|
1285
|
+
"cyber_policy",
|
|
1286
|
+
"insufficient_quota",
|
|
1287
|
+
"invalid_prompt",
|
|
1288
|
+
"usage_limit_reached"
|
|
1289
|
+
]);
|
|
1290
|
+
function sseDataPayloads(text) {
|
|
1291
|
+
const payloads = [];
|
|
1292
|
+
let dataLines = [];
|
|
1293
|
+
const dispatch = () => {
|
|
1294
|
+
if (dataLines.length > 0) payloads.push(dataLines.join("\n"));
|
|
1295
|
+
dataLines = [];
|
|
1296
|
+
};
|
|
1297
|
+
for (const line of text.split(/\r\n|\r|\n/)) {
|
|
1298
|
+
if (line === "") {
|
|
1299
|
+
dispatch();
|
|
1300
|
+
continue;
|
|
1301
|
+
}
|
|
1302
|
+
if (line === "data") {
|
|
1303
|
+
dataLines.push("");
|
|
1304
|
+
continue;
|
|
1305
|
+
}
|
|
1306
|
+
if (!line.startsWith("data:")) continue;
|
|
1307
|
+
const value = line.slice(5);
|
|
1308
|
+
dataLines.push(value.startsWith(" ") ? value.slice(1) : value);
|
|
1309
|
+
}
|
|
1310
|
+
dispatch();
|
|
1311
|
+
return payloads;
|
|
1312
|
+
}
|
|
1313
|
+
var CODEX_TERMINAL_ERROR_FIELD_MAX_BYTES = 256;
|
|
1314
|
+
var CODEX_TERMINAL_ERROR_MESSAGE_MAX_BYTES = 4 * 1024;
|
|
1315
|
+
var CODEX_TERMINAL_ERROR_TRUNCATION_MARKER = "\u2026 [truncated]";
|
|
1316
|
+
function boundedTerminalErrorField(value, maxBytes) {
|
|
1317
|
+
if (typeof value !== "string") return { truncated: false };
|
|
1318
|
+
const encoder = new TextEncoder();
|
|
1319
|
+
const encoded = encoder.encode(value);
|
|
1320
|
+
if (encoded.byteLength <= maxBytes) return { value, truncated: false };
|
|
1321
|
+
const markerBytes = encoder.encode(CODEX_TERMINAL_ERROR_TRUNCATION_MARKER).byteLength;
|
|
1322
|
+
let prefixEnd = Math.max(0, maxBytes - markerBytes);
|
|
1323
|
+
while (prefixEnd > 0 && (encoded[prefixEnd] & 192) === 128) {
|
|
1324
|
+
prefixEnd -= 1;
|
|
1325
|
+
}
|
|
1326
|
+
return {
|
|
1327
|
+
value: `${new TextDecoder().decode(encoded.subarray(0, prefixEnd))}${CODEX_TERMINAL_ERROR_TRUNCATION_MARKER}`,
|
|
1328
|
+
truncated: true
|
|
1329
|
+
};
|
|
1330
|
+
}
|
|
1331
|
+
function codexSseFailureResponse(source, rawError, fallbackCode, fallbackMessage, metadata = {}) {
|
|
1332
|
+
const projection = codexSseFailureProjection(
|
|
1333
|
+
source,
|
|
1334
|
+
rawError,
|
|
1335
|
+
fallbackCode,
|
|
1336
|
+
fallbackMessage,
|
|
1337
|
+
metadata
|
|
1338
|
+
);
|
|
1339
|
+
return new Response(JSON.stringify({ error: projection.error }), {
|
|
1340
|
+
status: projection.status,
|
|
1341
|
+
headers: projection.headers
|
|
1342
|
+
});
|
|
1343
|
+
}
|
|
1344
|
+
function codexSseFailureProjection(source, rawError, fallbackCode, fallbackMessage, metadata = {}) {
|
|
1345
|
+
const record = rawError && typeof rawError === "object" && !Array.isArray(rawError) ? rawError : {};
|
|
1346
|
+
const typeField = boundedTerminalErrorField(record.type, CODEX_TERMINAL_ERROR_FIELD_MAX_BYTES);
|
|
1347
|
+
const codeField = boundedTerminalErrorField(record.code, CODEX_TERMINAL_ERROR_FIELD_MAX_BYTES);
|
|
1348
|
+
const messageField = boundedTerminalErrorField(
|
|
1349
|
+
record.message ?? (typeof rawError === "string" ? rawError : void 0),
|
|
1350
|
+
CODEX_TERMINAL_ERROR_MESSAGE_MAX_BYTES
|
|
1351
|
+
);
|
|
1352
|
+
const paramField = boundedTerminalErrorField(record.param, CODEX_TERMINAL_ERROR_FIELD_MAX_BYTES);
|
|
1353
|
+
const eventTypeField = boundedTerminalErrorField(
|
|
1354
|
+
metadata.eventType,
|
|
1355
|
+
CODEX_TERMINAL_ERROR_FIELD_MAX_BYTES
|
|
1356
|
+
);
|
|
1357
|
+
const responseIdField = boundedTerminalErrorField(
|
|
1358
|
+
metadata.responseId,
|
|
1359
|
+
CODEX_TERMINAL_ERROR_FIELD_MAX_BYTES
|
|
1360
|
+
);
|
|
1361
|
+
const responseStatusField = boundedTerminalErrorField(
|
|
1362
|
+
metadata.responseStatus,
|
|
1363
|
+
CODEX_TERMINAL_ERROR_FIELD_MAX_BYTES
|
|
1364
|
+
);
|
|
1365
|
+
const providerType = typeField.value === "error" || typeField.value === "response.error" || typeField.value === "response.failed" ? void 0 : typeField.value;
|
|
1366
|
+
const code = (codeField.value?.length ? codeField.value : void 0) ?? (providerType?.length ? providerType : void 0) ?? fallbackCode;
|
|
1367
|
+
const diagnosticTruncated = typeField.truncated || codeField.truncated || messageField.truncated || paramField.truncated || eventTypeField.truncated || responseIdField.truncated || responseStatusField.truncated || Object.keys(record).some((key) => !["type", "code", "message", "param"].includes(key)) || rawError !== null && rawError !== void 0 && typeof rawError !== "string" && (typeof rawError !== "object" || Array.isArray(rawError));
|
|
1368
|
+
const error = {
|
|
1369
|
+
type: providerType?.length ? providerType : code,
|
|
1370
|
+
code,
|
|
1371
|
+
message: messageField.value?.length ? messageField.value : fallbackMessage,
|
|
1372
|
+
...paramField.value?.length ? { param: paramField.value } : {},
|
|
1373
|
+
...eventTypeField.value?.length ? { event_type: eventTypeField.value } : {},
|
|
1374
|
+
...responseIdField.value?.length ? { response_id: responseIdField.value } : {},
|
|
1375
|
+
...responseStatusField.value?.length ? { response_status: responseStatusField.value } : {},
|
|
1376
|
+
...diagnosticTruncated ? { diagnostic_truncated: true } : {}
|
|
1377
|
+
};
|
|
1378
|
+
const status = code === "rate_limit_exceeded" || code === "usage_limit_reached" || code === "insufficient_quota" ? 429 : NON_RETRYABLE_SSE_ERROR_CODES.has(code) ? 400 : 502;
|
|
1379
|
+
const headers = new Headers(source.headers);
|
|
1380
|
+
headers.set("content-type", "application/json");
|
|
1381
|
+
headers.set(CODEX_TRANSPORT_ERROR_HEADER, "1");
|
|
1382
|
+
headers.set("x-should-retry", "false");
|
|
1383
|
+
headers.delete("content-length");
|
|
1384
|
+
headers.delete("content-encoding");
|
|
1385
|
+
return { status, error, headers };
|
|
1386
|
+
}
|
|
1387
|
+
var CodexStreamingTerminalError = class extends Error {
|
|
1388
|
+
status;
|
|
1389
|
+
code;
|
|
1390
|
+
type;
|
|
1391
|
+
eventType;
|
|
1392
|
+
responseId;
|
|
1393
|
+
responseStatus;
|
|
1394
|
+
headers;
|
|
1395
|
+
error;
|
|
1396
|
+
constructor(projection, publicMessage) {
|
|
1397
|
+
super(publicMessage);
|
|
1398
|
+
this.name = "CodexStreamingTerminalError";
|
|
1399
|
+
this.status = projection.status;
|
|
1400
|
+
this.code = projection.error.code;
|
|
1401
|
+
this.type = projection.error.type;
|
|
1402
|
+
if (projection.error.event_type !== void 0) {
|
|
1403
|
+
this.eventType = projection.error.event_type;
|
|
1404
|
+
}
|
|
1405
|
+
if (projection.error.response_id !== void 0) {
|
|
1406
|
+
this.responseId = projection.error.response_id;
|
|
1407
|
+
}
|
|
1408
|
+
if (projection.error.response_status !== void 0) {
|
|
1409
|
+
this.responseStatus = projection.error.response_status;
|
|
1410
|
+
}
|
|
1411
|
+
this.headers = projection.headers;
|
|
1412
|
+
this.error = {
|
|
1413
|
+
type: projection.error.type,
|
|
1414
|
+
code: projection.error.code,
|
|
1415
|
+
...projection.error.event_type ? { event_type: projection.error.event_type } : {},
|
|
1416
|
+
...projection.error.response_id ? { response_id: projection.error.response_id } : {},
|
|
1417
|
+
...projection.error.response_status ? { response_status: projection.error.response_status } : {},
|
|
1418
|
+
...projection.error.diagnostic_truncated ? { diagnostic_truncated: true } : {}
|
|
1419
|
+
};
|
|
1420
|
+
}
|
|
1421
|
+
};
|
|
1422
|
+
function codexSseFailureError(source, rawError, fallbackCode, publicMessage, metadata = {}) {
|
|
1423
|
+
return new CodexStreamingTerminalError(
|
|
1424
|
+
codexSseFailureProjection(source, rawError, fallbackCode, publicMessage, metadata),
|
|
1425
|
+
publicMessage
|
|
1426
|
+
);
|
|
672
1427
|
}
|
|
673
1428
|
function repairCodexStream(res) {
|
|
674
1429
|
if (!res.body) {
|
|
675
|
-
|
|
1430
|
+
const error = codexSseFailureError(
|
|
1431
|
+
res,
|
|
1432
|
+
null,
|
|
1433
|
+
"invalid_sse_terminal",
|
|
1434
|
+
"The Codex response stream ended without a terminal response"
|
|
1435
|
+
);
|
|
1436
|
+
const body = new ReadableStream({
|
|
1437
|
+
start(controller) {
|
|
1438
|
+
controller.error(error);
|
|
1439
|
+
}
|
|
1440
|
+
});
|
|
1441
|
+
const headers2 = new Headers(res.headers);
|
|
1442
|
+
headers2.delete("content-length");
|
|
1443
|
+
return new Response(body, {
|
|
1444
|
+
status: res.status,
|
|
1445
|
+
statusText: res.statusText,
|
|
1446
|
+
headers: headers2
|
|
1447
|
+
});
|
|
676
1448
|
}
|
|
677
1449
|
const items = [];
|
|
678
1450
|
const decoder = new TextDecoder();
|
|
679
1451
|
const encoder = new TextEncoder();
|
|
680
1452
|
let buffer = "";
|
|
1453
|
+
let successfulTerminalSeen = false;
|
|
1454
|
+
const emitCompleteBlocks = (controller, final) => {
|
|
1455
|
+
let boundary = findSseBlockBoundary(buffer, final);
|
|
1456
|
+
while (boundary) {
|
|
1457
|
+
const block = buffer.slice(0, boundary.start);
|
|
1458
|
+
const separator = buffer.slice(boundary.start, boundary.end);
|
|
1459
|
+
buffer = buffer.slice(boundary.end);
|
|
1460
|
+
const patched = patchSseBlock(block, items, res);
|
|
1461
|
+
successfulTerminalSeen ||= patched.successfulTerminal;
|
|
1462
|
+
controller.enqueue(encoder.encode(`${patched.block}${separator}`));
|
|
1463
|
+
boundary = findSseBlockBoundary(buffer, final);
|
|
1464
|
+
}
|
|
1465
|
+
};
|
|
681
1466
|
const transform = new TransformStream({
|
|
682
1467
|
transform(chunk, controller) {
|
|
683
1468
|
buffer += decoder.decode(chunk, { stream: true });
|
|
684
|
-
|
|
685
|
-
while (idx !== -1) {
|
|
686
|
-
const block = buffer.slice(0, idx);
|
|
687
|
-
buffer = buffer.slice(idx + 2);
|
|
688
|
-
controller.enqueue(encoder.encode(`${patchSseBlock(block, items)}
|
|
689
|
-
|
|
690
|
-
`));
|
|
691
|
-
idx = buffer.indexOf("\n\n");
|
|
692
|
-
}
|
|
1469
|
+
emitCompleteBlocks(controller, false);
|
|
693
1470
|
},
|
|
694
1471
|
flush(controller) {
|
|
1472
|
+
buffer += decoder.decode();
|
|
1473
|
+
emitCompleteBlocks(controller, true);
|
|
695
1474
|
if (buffer.length > 0) {
|
|
696
|
-
|
|
1475
|
+
const patched = patchSseBlock(buffer, items, res);
|
|
1476
|
+
successfulTerminalSeen ||= patched.successfulTerminal;
|
|
1477
|
+
controller.enqueue(encoder.encode(patched.block));
|
|
1478
|
+
buffer = "";
|
|
1479
|
+
}
|
|
1480
|
+
if (!successfulTerminalSeen) {
|
|
1481
|
+
throw codexSseFailureError(
|
|
1482
|
+
res,
|
|
1483
|
+
null,
|
|
1484
|
+
"invalid_sse_terminal",
|
|
1485
|
+
"The Codex response stream ended without a terminal response"
|
|
1486
|
+
);
|
|
697
1487
|
}
|
|
698
1488
|
}
|
|
699
1489
|
});
|
|
700
1490
|
const headers = new Headers(res.headers);
|
|
701
1491
|
headers.delete("content-length");
|
|
702
|
-
return new Response(res.body.pipeThrough(transform), {
|
|
1492
|
+
return new Response(res.body.pipeThrough(transform), {
|
|
1493
|
+
status: res.status,
|
|
1494
|
+
headers
|
|
1495
|
+
});
|
|
1496
|
+
}
|
|
1497
|
+
function findSseBlockBoundary(value, final) {
|
|
1498
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
1499
|
+
const firstEnd = sseLineEndingEnd(value, index, final);
|
|
1500
|
+
if (firstEnd === null) continue;
|
|
1501
|
+
const secondEnd = sseLineEndingEnd(value, firstEnd, final);
|
|
1502
|
+
if (secondEnd !== null) {
|
|
1503
|
+
return { start: index, end: secondEnd };
|
|
1504
|
+
}
|
|
1505
|
+
index = firstEnd - 1;
|
|
1506
|
+
}
|
|
1507
|
+
return null;
|
|
1508
|
+
}
|
|
1509
|
+
function sseLineEndingEnd(value, index, final) {
|
|
1510
|
+
const current = value[index];
|
|
1511
|
+
if (current === "\n") return index + 1;
|
|
1512
|
+
if (current !== "\r") return null;
|
|
1513
|
+
if (index + 1 < value.length) {
|
|
1514
|
+
return value[index + 1] === "\n" ? index + 2 : index + 1;
|
|
1515
|
+
}
|
|
1516
|
+
return final ? index + 1 : null;
|
|
703
1517
|
}
|
|
704
|
-
function patchSseBlock(block, items) {
|
|
705
|
-
const lines = block.split(
|
|
1518
|
+
function patchSseBlock(block, items, source) {
|
|
1519
|
+
const lines = block.split(/\r\n|\r|\n/);
|
|
706
1520
|
const dataStr = lines.filter((l) => l.startsWith("data:")).map((l) => l.slice(5).trim()).join("\n");
|
|
707
1521
|
if (!dataStr || dataStr === "[DONE]") {
|
|
708
|
-
return block;
|
|
1522
|
+
return { block, successfulTerminal: false };
|
|
709
1523
|
}
|
|
710
1524
|
let ev;
|
|
711
1525
|
try {
|
|
712
1526
|
ev = JSON.parse(dataStr);
|
|
713
1527
|
} catch {
|
|
714
|
-
return block;
|
|
1528
|
+
return { block, successfulTerminal: false };
|
|
715
1529
|
}
|
|
716
1530
|
if (ev.type === "response.output_item.done" && ev.item !== void 0) {
|
|
717
1531
|
items.push(ev.item);
|
|
718
|
-
return block;
|
|
1532
|
+
return { block, successfulTerminal: false };
|
|
1533
|
+
}
|
|
1534
|
+
if (ev.type === "response.failed") {
|
|
1535
|
+
throw codexSseFailureError(
|
|
1536
|
+
source,
|
|
1537
|
+
ev.response?.error,
|
|
1538
|
+
"response_failed",
|
|
1539
|
+
"The Codex response failed",
|
|
1540
|
+
{
|
|
1541
|
+
eventType: ev.type,
|
|
1542
|
+
responseId: ev.response?.id,
|
|
1543
|
+
responseStatus: ev.response?.status
|
|
1544
|
+
}
|
|
1545
|
+
);
|
|
1546
|
+
}
|
|
1547
|
+
if (ev.type === "error" || ev.type === "response.error") {
|
|
1548
|
+
throw codexSseFailureError(
|
|
1549
|
+
source,
|
|
1550
|
+
ev.error ?? ev.response?.error ?? ev,
|
|
1551
|
+
"response_error",
|
|
1552
|
+
"The Codex response stream reported an error",
|
|
1553
|
+
{
|
|
1554
|
+
eventType: ev.type,
|
|
1555
|
+
responseId: ev.response?.id,
|
|
1556
|
+
responseStatus: ev.response?.status
|
|
1557
|
+
}
|
|
1558
|
+
);
|
|
719
1559
|
}
|
|
720
|
-
if (
|
|
1560
|
+
if (ev.type === "response.incomplete") {
|
|
1561
|
+
const details = ev.response?.incomplete_details;
|
|
1562
|
+
const reason = details && typeof details === "object" ? details.reason : void 0;
|
|
1563
|
+
throw codexSseFailureError(
|
|
1564
|
+
source,
|
|
1565
|
+
{
|
|
1566
|
+
code: "response_incomplete",
|
|
1567
|
+
message: typeof reason === "string" && reason.length > 0 ? `The Codex response was incomplete (${reason})` : "The Codex response was incomplete"
|
|
1568
|
+
},
|
|
1569
|
+
"response_incomplete",
|
|
1570
|
+
"The Codex response was incomplete",
|
|
1571
|
+
{
|
|
1572
|
+
eventType: ev.type,
|
|
1573
|
+
responseId: ev.response?.id,
|
|
1574
|
+
responseStatus: ev.response?.status
|
|
1575
|
+
}
|
|
1576
|
+
);
|
|
1577
|
+
}
|
|
1578
|
+
if ((ev.type === "response.completed" || ev.type === "response.done") && ev.response) {
|
|
1579
|
+
if (ev.response.status === "failed" || ev.response.status === "incomplete" || ev.response.error !== null && ev.response.error !== void 0) {
|
|
1580
|
+
throw codexSseFailureError(
|
|
1581
|
+
source,
|
|
1582
|
+
ev.response.error,
|
|
1583
|
+
ev.response.status === "incomplete" ? "response_incomplete" : "response_failed",
|
|
1584
|
+
ev.response.status === "incomplete" ? "The Codex response was incomplete" : "The Codex response failed",
|
|
1585
|
+
{
|
|
1586
|
+
eventType: ev.type,
|
|
1587
|
+
responseId: ev.response.id,
|
|
1588
|
+
responseStatus: ev.response.status
|
|
1589
|
+
}
|
|
1590
|
+
);
|
|
1591
|
+
}
|
|
721
1592
|
const out = ev.response.output;
|
|
722
1593
|
if ((!Array.isArray(out) || out.length === 0) && items.length > 0) {
|
|
723
1594
|
ev.response = { ...ev.response, output: items };
|
|
724
1595
|
const nonData = lines.filter((l) => !l.startsWith("data:"));
|
|
725
|
-
|
|
1596
|
+
const lineEnding = block.match(/\r\n|\r|\n/)?.[0] ?? "\n";
|
|
1597
|
+
return {
|
|
1598
|
+
block: [...nonData, `data: ${JSON.stringify(ev)}`].join(lineEnding),
|
|
1599
|
+
successfulTerminal: true
|
|
1600
|
+
};
|
|
726
1601
|
}
|
|
1602
|
+
return { block, successfulTerminal: true };
|
|
727
1603
|
}
|
|
728
|
-
return block;
|
|
1604
|
+
return { block, successfulTerminal: false };
|
|
729
1605
|
}
|
|
730
1606
|
|
|
731
1607
|
// src/mcp-sanitize.ts
|
|
@@ -894,6 +1770,412 @@ function codexAppsSanitizingFetch(base = globalThis.fetch, namespaceSink) {
|
|
|
894
1770
|
return new Response(sanitized, { status: res.status, statusText: res.statusText, headers });
|
|
895
1771
|
};
|
|
896
1772
|
}
|
|
1773
|
+
|
|
1774
|
+
// src/oversized-image-card.ts
|
|
1775
|
+
var MODEL_TOOL_OUTPUT_OVERSIZED_IMAGE_CARD_DATA_URL = "data:image/png;base64,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";
|
|
1776
|
+
|
|
1777
|
+
// src/model-output-truncation.ts
|
|
1778
|
+
var CODEX_MODEL_TOOL_OUTPUT_TRUNCATION_TOKENS = 1e4;
|
|
1779
|
+
var CODEX_TOOL_OUTPUT_SERIALIZATION_ALLOWANCE = 1.2;
|
|
1780
|
+
var DEFAULT_MODEL_TOOL_OUTPUT_TRUNCATION_TOKENS = CODEX_MODEL_TOOL_OUTPUT_TRUNCATION_TOKENS;
|
|
1781
|
+
var APPROX_BYTES_PER_TOKEN = 4;
|
|
1782
|
+
var TOKEN_TRUNCATION_MARKER = /…\d{1,12} tokens truncated…/u;
|
|
1783
|
+
var TOOL_RESULT_TYPES = /* @__PURE__ */ new Set([
|
|
1784
|
+
"function_call_result",
|
|
1785
|
+
"function_call_output",
|
|
1786
|
+
"computer_call_result",
|
|
1787
|
+
"custom_tool_call_output",
|
|
1788
|
+
"shell_call_output",
|
|
1789
|
+
"apply_patch_call_output"
|
|
1790
|
+
]);
|
|
1791
|
+
var STRUCTURAL_STRING_KEYS = /* @__PURE__ */ new Set([
|
|
1792
|
+
"type",
|
|
1793
|
+
"role",
|
|
1794
|
+
"status",
|
|
1795
|
+
"name",
|
|
1796
|
+
"id",
|
|
1797
|
+
"callId",
|
|
1798
|
+
"call_id",
|
|
1799
|
+
"namespace",
|
|
1800
|
+
"detail",
|
|
1801
|
+
"mimeType",
|
|
1802
|
+
"media_type"
|
|
1803
|
+
]);
|
|
1804
|
+
var MODEL_TOOL_OUTPUT_MAX_DEPTH = 12;
|
|
1805
|
+
var MODEL_TOOL_OUTPUT_MAX_CONTAINER_ENTRIES = 255;
|
|
1806
|
+
var MODEL_TOOL_OUTPUT_MAX_TOTAL_ENTRIES = 2048;
|
|
1807
|
+
var MODEL_TOOL_OUTPUT_MAX_PROPERTY_KEY_BYTES = 256;
|
|
1808
|
+
var MODEL_TOOL_OUTPUT_MAX_STRUCTURAL_STRING_TOKENS = 64;
|
|
1809
|
+
var MODEL_TOOL_OUTPUT_STRUCTURAL_STRING_BUDGET_TOKENS = 1024;
|
|
1810
|
+
var MODEL_TOOL_OUTPUT_OPAQUE_PAYLOAD_MAX_BYTES = 8 * 1024 * 1024;
|
|
1811
|
+
var DEPTH_OMISSION_MARKER = "[OpenGeni omitted subtree: maximum structured tool-output depth exceeded]";
|
|
1812
|
+
var CYCLE_OMISSION_MARKER = "[OpenGeni omitted subtree: cyclic tool output]";
|
|
1813
|
+
var STRUCTURAL_STRING_OMISSION_MARKER = "[OpenGeni omitted structural string: structural budget exhausted]";
|
|
1814
|
+
var TEXT_FIELD_OMISSION_MARKER = /^\[omitted text field \d+ \.\.\.\]$/u;
|
|
1815
|
+
var TEXT_ITEMS_OMISSION_MARKER = /^\[omitted \d+ text items \.\.\.\]$/u;
|
|
1816
|
+
var STRUCTURAL_ENTRIES_OMISSION_MARKER = /^\[OpenGeni omitted \d+ structured (?:array items|object properties)\]$/u;
|
|
1817
|
+
var OPAQUE_PAYLOAD_OMISSION_MARKER = /^\[OpenGeni omitted (?:image|file|encrypted) payload: \d+ bytes exceeded the bounded model-input allowance\]$/u;
|
|
1818
|
+
var STRUCTURAL_PROPERTIES_MARKER_KEY = "__opengeni_omitted_properties__";
|
|
1819
|
+
function modelToolOutputSerializationBudgetTokens(policyTokens = DEFAULT_MODEL_TOOL_OUTPUT_TRUNCATION_TOKENS) {
|
|
1820
|
+
return Math.ceil(Math.max(0, policyTokens) * CODEX_TOOL_OUTPUT_SERIALIZATION_ALLOWANCE);
|
|
1821
|
+
}
|
|
1822
|
+
function approximateTokenCount(value) {
|
|
1823
|
+
return Math.ceil(Buffer.byteLength(value, "utf8") / APPROX_BYTES_PER_TOKEN);
|
|
1824
|
+
}
|
|
1825
|
+
function truncateMiddleWithTokenBudget(value, maxTokens) {
|
|
1826
|
+
if (value.length === 0) return value;
|
|
1827
|
+
const maxBytes = Math.max(0, maxTokens) * APPROX_BYTES_PER_TOKEN;
|
|
1828
|
+
const valueBytes = Buffer.byteLength(value, "utf8");
|
|
1829
|
+
if (maxTokens > 0 && valueBytes <= maxBytes) return value;
|
|
1830
|
+
const existingMarker = value.match(TOKEN_TRUNCATION_MARKER)?.[0];
|
|
1831
|
+
if (existingMarker && valueBytes <= maxBytes + Buffer.byteLength(existingMarker, "utf8")) {
|
|
1832
|
+
return value;
|
|
1833
|
+
}
|
|
1834
|
+
if (maxBytes === 0) {
|
|
1835
|
+
return `\u2026${approximateTokenCount(value)} tokens truncated\u2026`;
|
|
1836
|
+
}
|
|
1837
|
+
const leftBudget = Math.floor(maxBytes / 2);
|
|
1838
|
+
const rightBudget = maxBytes - leftBudget;
|
|
1839
|
+
const bytes = Buffer.from(value, "utf8");
|
|
1840
|
+
let leftEnd = Math.min(leftBudget, bytes.length);
|
|
1841
|
+
while (leftEnd > 0 && leftEnd < bytes.length && isUtf8ContinuationByte(bytes[leftEnd])) {
|
|
1842
|
+
leftEnd -= 1;
|
|
1843
|
+
}
|
|
1844
|
+
let rightStart = Math.max(0, bytes.length - rightBudget);
|
|
1845
|
+
while (rightStart < bytes.length && isUtf8ContinuationByte(bytes[rightStart])) {
|
|
1846
|
+
rightStart += 1;
|
|
1847
|
+
}
|
|
1848
|
+
const left = bytes.subarray(0, leftEnd).toString("utf8");
|
|
1849
|
+
const right = bytes.subarray(rightStart).toString("utf8");
|
|
1850
|
+
const removedBytes = Math.max(0, valueBytes - maxBytes);
|
|
1851
|
+
const removedTokens = Math.ceil(removedBytes / APPROX_BYTES_PER_TOKEN);
|
|
1852
|
+
return `${left}\u2026${removedTokens} tokens truncated\u2026${right}`;
|
|
1853
|
+
}
|
|
1854
|
+
function isUtf8ContinuationByte(value) {
|
|
1855
|
+
return (value & 192) === 128;
|
|
1856
|
+
}
|
|
1857
|
+
function boundModelToolOutputItem(item, policyTokens = DEFAULT_MODEL_TOOL_OUTPUT_TRUNCATION_TOKENS) {
|
|
1858
|
+
const type = typeof item.type === "string" ? item.type : "";
|
|
1859
|
+
if (!TOOL_RESULT_TYPES.has(type)) return item;
|
|
1860
|
+
const budget = modelToolOutputSerializationBudgetTokens(policyTokens);
|
|
1861
|
+
const boundedOutput = boundToolOutputValue(item.output, budget);
|
|
1862
|
+
return boundedOutput === item.output ? item : { ...item, output: boundedOutput };
|
|
1863
|
+
}
|
|
1864
|
+
function boundModelToolOutputItems(items, policyTokens = DEFAULT_MODEL_TOOL_OUTPUT_TRUNCATION_TOKENS) {
|
|
1865
|
+
return items.map((item) => boundModelToolOutputItem(item, policyTokens));
|
|
1866
|
+
}
|
|
1867
|
+
function boundToolOutputValue(output, budgetTokens) {
|
|
1868
|
+
const state = modelOutputBoundState(budgetTokens);
|
|
1869
|
+
if (typeof output === "string") {
|
|
1870
|
+
if (isGeneratedModelOutputMarker(output)) {
|
|
1871
|
+
observeGeneratedMarkerBudget(output, state);
|
|
1872
|
+
return output;
|
|
1873
|
+
}
|
|
1874
|
+
if (isImageDataUrl(output)) return boundOpaqueProtocolString(output, state, "image");
|
|
1875
|
+
return truncateMiddleWithTokenBudget(output, budgetTokens);
|
|
1876
|
+
}
|
|
1877
|
+
if (Array.isArray(output)) {
|
|
1878
|
+
const isProtocolContent = isResponsesProtocolContentPrefix(output);
|
|
1879
|
+
return isProtocolContent ? boundStructuredOutputItems(output, state) : boundTextLeaves(output, state);
|
|
1880
|
+
}
|
|
1881
|
+
if (!output || typeof output !== "object") return output;
|
|
1882
|
+
const record = output;
|
|
1883
|
+
return boundTextLeaves(record, state);
|
|
1884
|
+
}
|
|
1885
|
+
function modelOutputBoundState(budgetTokens) {
|
|
1886
|
+
return {
|
|
1887
|
+
remaining: Math.max(0, budgetTokens),
|
|
1888
|
+
remainingStructural: MODEL_TOOL_OUTPUT_STRUCTURAL_STRING_BUDGET_TOKENS,
|
|
1889
|
+
remainingEntries: MODEL_TOOL_OUTPUT_MAX_TOTAL_ENTRIES,
|
|
1890
|
+
remainingOpaqueBytes: MODEL_TOOL_OUTPUT_OPAQUE_PAYLOAD_MAX_BYTES,
|
|
1891
|
+
opaqueOmissions: 0,
|
|
1892
|
+
lastOpaqueOmissionMarker: null,
|
|
1893
|
+
omitted: 0,
|
|
1894
|
+
seen: /* @__PURE__ */ new WeakSet()
|
|
1895
|
+
};
|
|
1896
|
+
}
|
|
1897
|
+
function boundStructuredOutputItems(items, state) {
|
|
1898
|
+
let omitted = 0;
|
|
1899
|
+
let changed = false;
|
|
1900
|
+
const out = [];
|
|
1901
|
+
let processed = 0;
|
|
1902
|
+
const terminalStructuralMarker = items.length <= MODEL_TOOL_OUTPUT_MAX_CONTAINER_ENTRIES + 1 && isTypedStructuralArrayOmissionMarker(items.at(-1)) ? items.at(-1) : null;
|
|
1903
|
+
let preservedTerminalStructuralMarker = false;
|
|
1904
|
+
for (let index = 0; index < items.length; index += 1) {
|
|
1905
|
+
const item = items[index];
|
|
1906
|
+
if (processed >= MODEL_TOOL_OUTPUT_MAX_CONTAINER_ENTRIES || state.remainingEntries <= 0) {
|
|
1907
|
+
if (terminalStructuralMarker && index <= items.length - 1) {
|
|
1908
|
+
out.push(terminalStructuralMarker);
|
|
1909
|
+
preservedTerminalStructuralMarker = true;
|
|
1910
|
+
}
|
|
1911
|
+
break;
|
|
1912
|
+
}
|
|
1913
|
+
processed += 1;
|
|
1914
|
+
state.remainingEntries -= 1;
|
|
1915
|
+
const record = item;
|
|
1916
|
+
if (record.type === "input_text" && isGeneratedModelOutputMarker(record.text)) {
|
|
1917
|
+
const bounded2 = boundTextLeaves(item, state, 1);
|
|
1918
|
+
out.push(bounded2);
|
|
1919
|
+
if (item === terminalStructuralMarker) preservedTerminalStructuralMarker = true;
|
|
1920
|
+
if (bounded2 !== item) changed = true;
|
|
1921
|
+
continue;
|
|
1922
|
+
}
|
|
1923
|
+
if (record.type === "input_text" && state.remaining === 0) {
|
|
1924
|
+
omitted += 1;
|
|
1925
|
+
changed = true;
|
|
1926
|
+
continue;
|
|
1927
|
+
}
|
|
1928
|
+
const bounded = boundResponsesProtocolContentItem(record, state);
|
|
1929
|
+
out.push(bounded);
|
|
1930
|
+
if (item === terminalStructuralMarker) preservedTerminalStructuralMarker = true;
|
|
1931
|
+
if (bounded !== item) changed = true;
|
|
1932
|
+
}
|
|
1933
|
+
if (omitted > 0) {
|
|
1934
|
+
out.push({
|
|
1935
|
+
type: "input_text",
|
|
1936
|
+
text: `[omitted ${omitted} text items ...]`
|
|
1937
|
+
});
|
|
1938
|
+
}
|
|
1939
|
+
const structurallyOmitted = preservedTerminalStructuralMarker ? 0 : items.length - processed;
|
|
1940
|
+
if (structurallyOmitted > 0) {
|
|
1941
|
+
out.push(typedStructuredArrayOmissionMarker(structurallyOmitted));
|
|
1942
|
+
changed = true;
|
|
1943
|
+
}
|
|
1944
|
+
return changed ? out : items;
|
|
1945
|
+
}
|
|
1946
|
+
function boundResponsesProtocolContentItem(item, state) {
|
|
1947
|
+
const opaqueOmissionsBefore = state.opaqueOmissions;
|
|
1948
|
+
const bounded = boundTextLeaves(item, state, 1);
|
|
1949
|
+
if (item.type === "input_image" && state.opaqueOmissions > opaqueOmissionsBefore) {
|
|
1950
|
+
return {
|
|
1951
|
+
type: "input_image",
|
|
1952
|
+
imageUrl: MODEL_TOOL_OUTPUT_OVERSIZED_IMAGE_CARD_DATA_URL
|
|
1953
|
+
};
|
|
1954
|
+
}
|
|
1955
|
+
if (item.type === "input_file" && state.opaqueOmissions > opaqueOmissionsBefore) {
|
|
1956
|
+
return typedProtocolTextMarker(
|
|
1957
|
+
state.lastOpaqueOmissionMarker ?? "[OpenGeni omitted file payload: 0 bytes exceeded the bounded model-input allowance]"
|
|
1958
|
+
);
|
|
1959
|
+
}
|
|
1960
|
+
return bounded;
|
|
1961
|
+
}
|
|
1962
|
+
function boundTextLeaves(value, state, depth = 0, opaqueKind = null) {
|
|
1963
|
+
if (typeof value === "string") {
|
|
1964
|
+
if (isGeneratedModelOutputMarker(value)) {
|
|
1965
|
+
observeGeneratedMarkerBudget(value, state);
|
|
1966
|
+
return value;
|
|
1967
|
+
}
|
|
1968
|
+
if (opaqueKind || isImageDataUrl(value)) {
|
|
1969
|
+
return boundOpaqueProtocolString(value, state, opaqueKind ?? "image");
|
|
1970
|
+
}
|
|
1971
|
+
if (state.remaining === 0) {
|
|
1972
|
+
state.omitted += 1;
|
|
1973
|
+
return `[omitted text field ${state.omitted} ...]`;
|
|
1974
|
+
}
|
|
1975
|
+
const cost = approximateTokenCount(value);
|
|
1976
|
+
if (cost <= state.remaining) {
|
|
1977
|
+
state.remaining -= cost;
|
|
1978
|
+
return value;
|
|
1979
|
+
}
|
|
1980
|
+
const bounded = truncateMiddleWithTokenBudget(value, state.remaining);
|
|
1981
|
+
state.remaining = 0;
|
|
1982
|
+
return bounded;
|
|
1983
|
+
}
|
|
1984
|
+
if (!value || typeof value !== "object") return value;
|
|
1985
|
+
if (depth >= MODEL_TOOL_OUTPUT_MAX_DEPTH) return DEPTH_OMISSION_MARKER;
|
|
1986
|
+
if (state.seen.has(value)) return CYCLE_OMISSION_MARKER;
|
|
1987
|
+
state.seen.add(value);
|
|
1988
|
+
if (Array.isArray(value)) {
|
|
1989
|
+
const out2 = [];
|
|
1990
|
+
let processed2 = 0;
|
|
1991
|
+
let changed2 = false;
|
|
1992
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
1993
|
+
const entry = value[index];
|
|
1994
|
+
if (processed2 >= MODEL_TOOL_OUTPUT_MAX_CONTAINER_ENTRIES || state.remainingEntries <= 0) {
|
|
1995
|
+
if (index === value.length - 1 && typeof entry === "string" && STRUCTURAL_ENTRIES_OMISSION_MARKER.test(entry)) {
|
|
1996
|
+
out2.push(entry);
|
|
1997
|
+
}
|
|
1998
|
+
break;
|
|
1999
|
+
}
|
|
2000
|
+
processed2 += 1;
|
|
2001
|
+
state.remainingEntries -= 1;
|
|
2002
|
+
const bounded = boundTextLeaves(entry, state, depth + 1, opaqueKind);
|
|
2003
|
+
out2.push(bounded);
|
|
2004
|
+
if (bounded !== entry) changed2 = true;
|
|
2005
|
+
}
|
|
2006
|
+
const omitted2 = value.length - out2.length;
|
|
2007
|
+
if (omitted2 > 0) {
|
|
2008
|
+
out2.push(structuredEntriesOmissionMarker(omitted2, "array"));
|
|
2009
|
+
changed2 = true;
|
|
2010
|
+
}
|
|
2011
|
+
state.seen.delete(value);
|
|
2012
|
+
return changed2 ? out2 : value;
|
|
2013
|
+
}
|
|
2014
|
+
const record = value;
|
|
2015
|
+
const recordOpaqueKind = nonTextProtocolKind(record.type) ?? opaqueKind;
|
|
2016
|
+
const entries = Object.entries(record);
|
|
2017
|
+
const out = {};
|
|
2018
|
+
let processed = 0;
|
|
2019
|
+
let omitted = 0;
|
|
2020
|
+
let changed = false;
|
|
2021
|
+
for (let index = 0; index < entries.length; index += 1) {
|
|
2022
|
+
const [key, entry] = entries[index];
|
|
2023
|
+
if (processed >= MODEL_TOOL_OUTPUT_MAX_CONTAINER_ENTRIES || state.remainingEntries <= 0) {
|
|
2024
|
+
if (index === entries.length - 1 && isGeneratedStructuralMarkerProperty(key, entry)) {
|
|
2025
|
+
out[key] = entry;
|
|
2026
|
+
break;
|
|
2027
|
+
}
|
|
2028
|
+
omitted += entries.length - index;
|
|
2029
|
+
break;
|
|
2030
|
+
}
|
|
2031
|
+
processed += 1;
|
|
2032
|
+
state.remainingEntries -= 1;
|
|
2033
|
+
if (Buffer.byteLength(key, "utf8") > MODEL_TOOL_OUTPUT_MAX_PROPERTY_KEY_BYTES) {
|
|
2034
|
+
omitted += 1;
|
|
2035
|
+
changed = true;
|
|
2036
|
+
continue;
|
|
2037
|
+
}
|
|
2038
|
+
const childOpaqueKind = opaqueKindForChild(recordOpaqueKind, key);
|
|
2039
|
+
if (typeof entry === "string" && childOpaqueKind) {
|
|
2040
|
+
const bounded2 = boundTextLeaves(entry, state, depth + 1, childOpaqueKind);
|
|
2041
|
+
out[key] = bounded2;
|
|
2042
|
+
if (bounded2 !== entry) changed = true;
|
|
2043
|
+
continue;
|
|
2044
|
+
}
|
|
2045
|
+
if (typeof entry === "string" && STRUCTURAL_STRING_KEYS.has(key)) {
|
|
2046
|
+
const bounded2 = boundStructuralString(entry, state);
|
|
2047
|
+
out[key] = bounded2;
|
|
2048
|
+
if (bounded2 !== entry) changed = true;
|
|
2049
|
+
continue;
|
|
2050
|
+
}
|
|
2051
|
+
const bounded = boundTextLeaves(entry, state, depth + 1, childOpaqueKind);
|
|
2052
|
+
out[key] = bounded;
|
|
2053
|
+
if (bounded !== entry) changed = true;
|
|
2054
|
+
}
|
|
2055
|
+
if (omitted > 0) {
|
|
2056
|
+
out[uniqueStructuralMarkerKey(out)] = structuredEntriesOmissionMarker(omitted, "object");
|
|
2057
|
+
changed = true;
|
|
2058
|
+
}
|
|
2059
|
+
state.seen.delete(value);
|
|
2060
|
+
return changed ? out : value;
|
|
2061
|
+
}
|
|
2062
|
+
function boundStructuralString(value, state) {
|
|
2063
|
+
if (isGeneratedModelOutputMarker(value)) {
|
|
2064
|
+
observeGeneratedMarkerBudget(value, state);
|
|
2065
|
+
return value;
|
|
2066
|
+
}
|
|
2067
|
+
if (state.remainingStructural === 0) return STRUCTURAL_STRING_OMISSION_MARKER;
|
|
2068
|
+
const cost = approximateTokenCount(value);
|
|
2069
|
+
const allowance = Math.min(
|
|
2070
|
+
MODEL_TOOL_OUTPUT_MAX_STRUCTURAL_STRING_TOKENS,
|
|
2071
|
+
state.remainingStructural
|
|
2072
|
+
);
|
|
2073
|
+
if (cost <= allowance) {
|
|
2074
|
+
state.remainingStructural -= cost;
|
|
2075
|
+
return value;
|
|
2076
|
+
}
|
|
2077
|
+
state.remainingStructural -= allowance;
|
|
2078
|
+
return truncateMiddleWithTokenBudget(value, allowance);
|
|
2079
|
+
}
|
|
2080
|
+
function boundOpaqueProtocolString(value, state, kind) {
|
|
2081
|
+
if (kind === "image" && value === MODEL_TOOL_OUTPUT_OVERSIZED_IMAGE_CARD_DATA_URL) {
|
|
2082
|
+
state.remainingOpaqueBytes = 0;
|
|
2083
|
+
return value;
|
|
2084
|
+
}
|
|
2085
|
+
const bytes = Buffer.byteLength(value, "utf8");
|
|
2086
|
+
if (bytes <= state.remainingOpaqueBytes) {
|
|
2087
|
+
state.remainingOpaqueBytes -= bytes;
|
|
2088
|
+
return value;
|
|
2089
|
+
}
|
|
2090
|
+
state.remainingOpaqueBytes = 0;
|
|
2091
|
+
if (kind === "image") {
|
|
2092
|
+
state.opaqueOmissions += 1;
|
|
2093
|
+
return MODEL_TOOL_OUTPUT_OVERSIZED_IMAGE_CARD_DATA_URL;
|
|
2094
|
+
}
|
|
2095
|
+
const marker = `[OpenGeni omitted ${kind} payload: ${bytes} bytes exceeded the bounded model-input allowance]`;
|
|
2096
|
+
state.opaqueOmissions += 1;
|
|
2097
|
+
state.lastOpaqueOmissionMarker = marker;
|
|
2098
|
+
return marker;
|
|
2099
|
+
}
|
|
2100
|
+
function nonTextProtocolKind(value) {
|
|
2101
|
+
if (value === "image" || value === "input_image" || value === "computer_screenshot") {
|
|
2102
|
+
return "image";
|
|
2103
|
+
}
|
|
2104
|
+
if (value === "file" || value === "input_file") return "file";
|
|
2105
|
+
if (value === "encrypted_content") return "encrypted";
|
|
2106
|
+
return null;
|
|
2107
|
+
}
|
|
2108
|
+
function opaqueKindForChild(kind, key) {
|
|
2109
|
+
if (!kind) return null;
|
|
2110
|
+
const opaqueKeys = kind === "image" ? ["image", "image_url", "imageUrl", "file_id", "fileId", "id", "data", "url", "source"] : kind === "file" ? [
|
|
2111
|
+
"file",
|
|
2112
|
+
"file_data",
|
|
2113
|
+
"fileData",
|
|
2114
|
+
"file_url",
|
|
2115
|
+
"fileUrl",
|
|
2116
|
+
"file_id",
|
|
2117
|
+
"fileId",
|
|
2118
|
+
"id",
|
|
2119
|
+
"data",
|
|
2120
|
+
"url",
|
|
2121
|
+
"content",
|
|
2122
|
+
"source"
|
|
2123
|
+
] : ["encrypted_content", "content", "data"];
|
|
2124
|
+
return opaqueKeys.includes(key) ? kind : null;
|
|
2125
|
+
}
|
|
2126
|
+
function structuredEntriesOmissionMarker(count, container) {
|
|
2127
|
+
return `[OpenGeni omitted ${count} structured ${container === "array" ? "array items" : "object properties"}]`;
|
|
2128
|
+
}
|
|
2129
|
+
function typedProtocolTextMarker(text) {
|
|
2130
|
+
return { type: "input_text", text };
|
|
2131
|
+
}
|
|
2132
|
+
function typedStructuredArrayOmissionMarker(count) {
|
|
2133
|
+
return typedProtocolTextMarker(structuredEntriesOmissionMarker(count, "array"));
|
|
2134
|
+
}
|
|
2135
|
+
function isTypedStructuralArrayOmissionMarker(value) {
|
|
2136
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
2137
|
+
const record = value;
|
|
2138
|
+
return record.type === "input_text" && typeof record.text === "string" && STRUCTURAL_ENTRIES_OMISSION_MARKER.test(record.text) && record.text.includes("structured array items");
|
|
2139
|
+
}
|
|
2140
|
+
function isGeneratedModelOutputMarker(value) {
|
|
2141
|
+
return typeof value === "string" && (value === DEPTH_OMISSION_MARKER || value === CYCLE_OMISSION_MARKER || value === STRUCTURAL_STRING_OMISSION_MARKER || TEXT_FIELD_OMISSION_MARKER.test(value) || TEXT_ITEMS_OMISSION_MARKER.test(value) || STRUCTURAL_ENTRIES_OMISSION_MARKER.test(value) || OPAQUE_PAYLOAD_OMISSION_MARKER.test(value));
|
|
2142
|
+
}
|
|
2143
|
+
function observeGeneratedMarkerBudget(value, state) {
|
|
2144
|
+
if (TEXT_FIELD_OMISSION_MARKER.test(value) || TEXT_ITEMS_OMISSION_MARKER.test(value)) {
|
|
2145
|
+
state.remaining = 0;
|
|
2146
|
+
}
|
|
2147
|
+
if (value === STRUCTURAL_STRING_OMISSION_MARKER) state.remainingStructural = 0;
|
|
2148
|
+
if (OPAQUE_PAYLOAD_OMISSION_MARKER.test(value)) state.remainingOpaqueBytes = 0;
|
|
2149
|
+
}
|
|
2150
|
+
function isGeneratedStructuralMarkerProperty(key, value) {
|
|
2151
|
+
return key.startsWith(STRUCTURAL_PROPERTIES_MARKER_KEY) && typeof value === "string" && STRUCTURAL_ENTRIES_OMISSION_MARKER.test(value);
|
|
2152
|
+
}
|
|
2153
|
+
function uniqueStructuralMarkerKey(record) {
|
|
2154
|
+
let key = STRUCTURAL_PROPERTIES_MARKER_KEY;
|
|
2155
|
+
let suffix = 1;
|
|
2156
|
+
while (Object.hasOwn(record, key)) {
|
|
2157
|
+
key = `${STRUCTURAL_PROPERTIES_MARKER_KEY}_${suffix}`;
|
|
2158
|
+
suffix += 1;
|
|
2159
|
+
}
|
|
2160
|
+
return key;
|
|
2161
|
+
}
|
|
2162
|
+
function isResponsesProtocolContentPrefix(output) {
|
|
2163
|
+
if (output.length === 0) return false;
|
|
2164
|
+
const retainedPrefixLength = Math.min(output.length, MODEL_TOOL_OUTPUT_MAX_CONTAINER_ENTRIES);
|
|
2165
|
+
for (let index = 0; index < retainedPrefixLength; index += 1) {
|
|
2166
|
+
const item = output[index];
|
|
2167
|
+
if (!item || typeof item !== "object" || Array.isArray(item)) return false;
|
|
2168
|
+
const record = item;
|
|
2169
|
+
if (record.type === "input_text" && typeof record.text === "string") continue;
|
|
2170
|
+
if (record.type === "input_image") continue;
|
|
2171
|
+
if (record.type === "input_file") continue;
|
|
2172
|
+
return false;
|
|
2173
|
+
}
|
|
2174
|
+
return true;
|
|
2175
|
+
}
|
|
2176
|
+
function isImageDataUrl(value) {
|
|
2177
|
+
return /^data:image\/[a-z0-9.+-]+;base64,/i.test(value);
|
|
2178
|
+
}
|
|
897
2179
|
export {
|
|
898
2180
|
CODEX_APPS_MCP_SERVER_ID,
|
|
899
2181
|
CODEX_APPS_MCP_SERVER_NAME,
|
|
@@ -915,13 +2197,23 @@ export {
|
|
|
915
2197
|
CODEX_MODEL_CONTEXT_WINDOW_TOKENS,
|
|
916
2198
|
CODEX_MODEL_EFFECTIVE_CONTEXT_WINDOW_TOKENS,
|
|
917
2199
|
CODEX_MODEL_ID_PREFIX,
|
|
2200
|
+
CODEX_MODEL_TOOL_OUTPUT_TRUNCATION_TOKENS,
|
|
918
2201
|
CODEX_ORIGINATOR,
|
|
919
2202
|
CODEX_PROVIDER_BASE_URL,
|
|
920
2203
|
CODEX_PROVIDER_ID,
|
|
2204
|
+
CODEX_RATE_LIMIT_RESET_OUTCOMES,
|
|
921
2205
|
CODEX_REFRESH_FALLBACK_MS,
|
|
922
2206
|
CODEX_REFRESH_WINDOW_MS,
|
|
923
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,
|
|
924
2215
|
CODEX_TOKEN_URL,
|
|
2216
|
+
CODEX_TOOL_OUTPUT_SERIALIZATION_ALLOWANCE,
|
|
925
2217
|
CODEX_TRANSPORT_ERROR_HEADER,
|
|
926
2218
|
CODEX_USAGE_LIMIT_ERROR_TYPE,
|
|
927
2219
|
CODEX_WEEKLY_WINDOW_SECONDS,
|
|
@@ -929,29 +2221,48 @@ export {
|
|
|
929
2221
|
CodexDeviceError,
|
|
930
2222
|
CodexRefreshTransient,
|
|
931
2223
|
CodexReloginRequired,
|
|
2224
|
+
CodexResponseTimeoutError,
|
|
2225
|
+
CodexStreamingTerminalError,
|
|
2226
|
+
DEFAULT_CODEX_RESPONSE_TIMEOUT_POLICY,
|
|
2227
|
+
DEFAULT_MODEL_TOOL_OUTPUT_TRUNCATION_TOKENS,
|
|
2228
|
+
MODEL_TOOL_OUTPUT_OPAQUE_PAYLOAD_MAX_BYTES,
|
|
2229
|
+
MODEL_TOOL_OUTPUT_OVERSIZED_IMAGE_CARD_DATA_URL,
|
|
932
2230
|
ToolNameMapper,
|
|
933
2231
|
accessTokenExpiry,
|
|
2232
|
+
approximateTokenCount,
|
|
2233
|
+
boundModelToolOutputItem,
|
|
2234
|
+
boundModelToolOutputItems,
|
|
934
2235
|
buildCodexUsageWindowFromCache,
|
|
935
2236
|
buildModelResolver,
|
|
2237
|
+
classifyCodexResponseTimeoutError,
|
|
936
2238
|
classifyCodexUsageLimitError,
|
|
937
2239
|
codexAppsSanitizingFetch,
|
|
938
2240
|
codexRequestStorage,
|
|
939
2241
|
codexSubscriptionFetch,
|
|
2242
|
+
consumeCodexRateLimitResetCredit,
|
|
940
2243
|
decodeJwtPayload,
|
|
941
2244
|
exchangeDeviceCode,
|
|
942
2245
|
fetchCodexModels,
|
|
2246
|
+
fetchCodexRateLimitResetCredits,
|
|
943
2247
|
fetchCodexUsage,
|
|
944
2248
|
isCodexBilledModel,
|
|
945
2249
|
isCodexTransportError,
|
|
2250
|
+
isPreHeadersTimeoutError,
|
|
2251
|
+
modelToolOutputSerializationBudgetTokens,
|
|
946
2252
|
normalizeCodexRequestBody,
|
|
947
2253
|
normalizeCodexUsage,
|
|
2254
|
+
parseCodexRateLimitResetConsumeResponse,
|
|
2255
|
+
parseCodexRateLimitResetCreditsDetails,
|
|
2256
|
+
parseCodexRateLimitResetCreditsSummary,
|
|
948
2257
|
parseCodexUsageHeaders,
|
|
949
2258
|
parseIdToken,
|
|
950
2259
|
pollDeviceCode,
|
|
951
2260
|
refreshCodexToken,
|
|
952
2261
|
remapToolCallRequestBody,
|
|
2262
|
+
resolveCodexResponseTimeoutPolicy,
|
|
953
2263
|
sanitizeMcpJsonBody,
|
|
954
2264
|
sanitizeMcpSseBody,
|
|
955
|
-
startDeviceCode
|
|
2265
|
+
startDeviceCode,
|
|
2266
|
+
truncateMiddleWithTokenBudget
|
|
956
2267
|
};
|
|
957
2268
|
//# sourceMappingURL=index.js.map
|