@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/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-K47573CJ.js";
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 res = await fetchImpl(CODEX_TOKEN_URL, {
125
- method: "POST",
126
- headers: { "Content-Type": "application/json" },
127
- body: JSON.stringify({
128
- client_id: CODEX_CLIENT_ID,
129
- grant_type: "refresh_token",
130
- refresh_token: refreshToken
131
- })
132
- });
133
- const text = await res.text();
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 = z.object({
305
- used_percent: z.number().optional(),
306
- reset_after_seconds: z.number().optional(),
307
- reset_at: z.number().optional(),
308
- limit_window_seconds: z.number().optional()
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 = z.object({
311
- allowed: z.boolean().optional(),
312
- limit_reached: z.boolean().optional(),
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 = z.object({
317
- limit_name: z.string().optional(),
318
- metered_feature: z.string().optional(),
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 = z.object({
323
- has_credits: z.boolean().optional(),
324
- unlimited: z.boolean().optional(),
325
- overage_limit_reached: z.boolean().optional(),
326
- balance: z.union([z.string(), z.number()]).optional()
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 = z.object({
329
- plan_type: z.string().nullish(),
453
+ var usageBodySchema = z2.object({
454
+ plan_type: z2.string().nullish(),
330
455
  rate_limit: rateLimitSchema,
331
- additional_limits: z.array(additionalLimitSchema).nullish(),
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 res = await fetchImpl(
452
- `${CODEX_RESPONSES_BASE}/models?client_version=${encodeURIComponent(a.clientVersion)}`,
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
- if (!res.ok) {
459
- return { ok: false, status: res.status, slugs: [] };
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 fetchCodexUsage(a, fetchImpl = fetch) {
466
- const res = await fetchImpl(`${CODEX_WHAM_BASE}/wham/usage`, {
467
- method: "GET",
468
- headers: subscriptionHeaders(a)
469
- });
470
- const payload = res.ok || res.status === 404 ? await res.json().catch(() => null) : null;
471
- return { status: res.status, payload };
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 attempt = async (auth) => {
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
- nextInit.body = JSON.stringify(normalizeCodexRequestBody(parsed, ctx.resolveModel));
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
- const keys = typeof nextInit.body === "string" ? Object.keys(JSON.parse(nextInit.body)) : [];
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
- const res2 = await base(rewritten, nextInit);
585
- const usage = parseCodexUsageHeaders(res2.headers);
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 && !res2.ok) {
1131
+ if (process.env.CODEX_DEBUG && !res.ok) {
590
1132
  console.error(
591
- `[codex-debug] <- ${res2.status} requestId=${res2.headers.get("x-request-id") ?? "unknown"}`
1133
+ `[codex-debug] <- ${res.status} requestId=${res.headers.get("x-request-id") ?? "unknown"}`
592
1134
  );
593
1135
  }
594
- if (!res2.ok) {
595
- return await bufferCodexErrorResponse(res2);
1136
+ if (!res.ok) {
1137
+ return await bufferCodexErrorResponse(res);
596
1138
  }
597
- return callerWantsStream ? repairCodexStream(res2) : await sseToJsonResponse(res2);
1139
+ return callerWantsStream ? repairCodexStream(res) : await sseToJsonResponse(res);
598
1140
  };
599
- let res = await attempt(await ctx.getToken());
600
- if (res.status === 401) {
601
- res = await attempt(await ctx.refresh());
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, { status: res.status, statusText: res.statusText, headers });
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 block of text.split("\n\n")) {
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.completed" || ev.type === "response.done" || ev.type === "response.incomplete") {
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 ?? {}), { status: 200, headers });
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
- return res;
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
- let idx = buffer.indexOf("\n\n");
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
- controller.enqueue(encoder.encode(patchSseBlock(buffer, items)));
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), { status: res.status, headers });
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("\n");
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 ((ev.type === "response.completed" || ev.type === "response.done" || ev.type === "response.incomplete") && ev.response) {
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
- return [...nonData, `data: ${JSON.stringify(ev)}`].join("\n");
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