@opengeni/codex 0.2.9 → 0.2.11

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
@@ -21,6 +21,10 @@ import {
21
21
  CODEX_ORIGINATOR,
22
22
  CODEX_PROVIDER_BASE_URL,
23
23
  CODEX_PROVIDER_ID,
24
+ CODEX_REALTIME_CALL_TIMEOUT_MS,
25
+ CODEX_REALTIME_DEFAULT_VOICE,
26
+ CODEX_REALTIME_MODEL,
27
+ CODEX_REALTIME_VERSION,
24
28
  CODEX_REFRESH_FALLBACK_MS,
25
29
  CODEX_REFRESH_WINDOW_MS,
26
30
  CODEX_RESPONSES_BASE,
@@ -32,7 +36,19 @@ import {
32
36
  CODEX_RESPONSE_WHOLE_TIMEOUT_MS,
33
37
  CODEX_TOKEN_URL,
34
38
  CODEX_WHAM_BASE
35
- } from "./chunk-YGKQDUY7.js";
39
+ } from "./chunk-HT463QWA.js";
40
+ import {
41
+ CODEX_REALTIME_CONTEXT_APPEND_MAX_BYTES,
42
+ CODEX_REALTIME_INITIAL_ITEMS_MAX_COUNT,
43
+ CODEX_REALTIME_INITIAL_ITEMS_MAX_TOKENS,
44
+ CODEX_REALTIME_V3_MAX_EVENT_BYTES,
45
+ CODEX_REALTIME_V3_MAX_IDENTIFIER_BYTES,
46
+ CODEX_REALTIME_V3_MAX_TEXT_BYTES,
47
+ contextAppendChunks,
48
+ encodeCodexRealtimeV3DelegationContextAppend,
49
+ encodeCodexRealtimeV3SessionContextAppend,
50
+ parseCodexRealtimeV3Event
51
+ } from "./chunk-MFVGCR3N.js";
36
52
 
37
53
  // src/billing.ts
38
54
  function isCodexBilledModel(model) {
@@ -567,7 +583,7 @@ function normalizeCodexUsage(httpStatus, rawPayload) {
567
583
  var CODEX_READ_TIMEOUT_MS = 5e3;
568
584
  var RESET_CREDIT_DETAILS_TIMEOUT_MS = 5e3;
569
585
  var RESET_CREDIT_CONSUME_TIMEOUT_MS = 1e4;
570
- function subscriptionHeaders(a) {
586
+ function codexSubscriptionHeaders(a) {
571
587
  return {
572
588
  Authorization: `Bearer ${a.accessToken}`,
573
589
  ...a.chatgptAccountId ? { "ChatGPT-Account-ID": a.chatgptAccountId } : {},
@@ -581,7 +597,7 @@ async function fetchCodexModels(a, fetchImpl = fetch, timeoutMs = CODEX_READ_TIM
581
597
  const fetched = await runBoundedCodexOperation(async (signal) => {
582
598
  const res = await fetchImpl(
583
599
  `${CODEX_RESPONSES_BASE}/models?client_version=${encodeURIComponent(a.clientVersion)}`,
584
- { method: "GET", headers: subscriptionHeaders(a), signal }
600
+ { method: "GET", headers: codexSubscriptionHeaders(a), signal }
585
601
  );
586
602
  if (!res.ok) {
587
603
  await res.arrayBuffer().catch(() => void 0);
@@ -597,7 +613,7 @@ async function fetchCodexUsage(a, fetchImpl = fetch, timeoutMs = CODEX_READ_TIME
597
613
  const fetched = await runBoundedCodexOperation(async (signal) => {
598
614
  const res = await fetchImpl(`${CODEX_WHAM_BASE}/wham/usage`, {
599
615
  method: "GET",
600
- headers: subscriptionHeaders(a),
616
+ headers: codexSubscriptionHeaders(a),
601
617
  signal
602
618
  });
603
619
  const payload = res.ok || res.status === 404 ? await res.json().catch(() => null) : null;
@@ -611,15 +627,23 @@ async function fetchCodexRateLimitResetCredits(a, fetchImpl = fetch, timeoutMs =
611
627
  const fetched = await runBoundedCodexOperation(async (signal) => {
612
628
  const res = await fetchImpl(`${CODEX_WHAM_BASE}/wham/rate-limit-reset-credits`, {
613
629
  method: "GET",
614
- headers: subscriptionHeaders(a),
630
+ headers: codexSubscriptionHeaders(a),
615
631
  signal
616
632
  });
617
633
  if (!res.ok) {
618
634
  await res.arrayBuffer().catch(() => void 0);
619
- return { ok: false, status: res.status, reason: "http_error" };
635
+ return {
636
+ ok: false,
637
+ status: res.status,
638
+ reason: "http_error"
639
+ };
620
640
  }
621
641
  const details = parseCodexRateLimitResetCreditsDetails(await res.json().catch(() => null));
622
- return details ? { ok: true, status: res.status, details } : { ok: false, status: res.status, reason: "invalid_response" };
642
+ return details ? { ok: true, status: res.status, details } : {
643
+ ok: false,
644
+ status: res.status,
645
+ reason: "invalid_response"
646
+ };
623
647
  }, timeoutMs);
624
648
  return fetched.ok ? fetched.value : { ok: false, status: 0, reason: fetched.reason };
625
649
  }
@@ -631,7 +655,7 @@ async function consumeCodexRateLimitResetCredit(a, input, fetchImpl = fetch, tim
631
655
  const res = await fetchImpl(`${CODEX_WHAM_BASE}/wham/rate-limit-reset-credits/consume`, {
632
656
  method: "POST",
633
657
  headers: {
634
- ...subscriptionHeaders(a),
658
+ ...codexSubscriptionHeaders(a),
635
659
  "content-type": "application/json"
636
660
  },
637
661
  body: JSON.stringify({
@@ -642,10 +666,18 @@ async function consumeCodexRateLimitResetCredit(a, input, fetchImpl = fetch, tim
642
666
  });
643
667
  if (!res.ok) {
644
668
  await res.arrayBuffer().catch(() => void 0);
645
- return { ok: false, status: res.status, reason: "http_error" };
669
+ return {
670
+ ok: false,
671
+ status: res.status,
672
+ reason: "http_error"
673
+ };
646
674
  }
647
675
  const result = parseCodexRateLimitResetConsumeResponse(await res.json().catch(() => null));
648
- return result ? { ok: true, status: res.status, result } : { ok: false, status: res.status, reason: "invalid_response" };
676
+ return result ? { ok: true, status: res.status, result } : {
677
+ ok: false,
678
+ status: res.status,
679
+ reason: "invalid_response"
680
+ };
649
681
  }, timeoutMs);
650
682
  return fetched.ok ? fetched.value : { ok: false, status: 0, reason: fetched.reason };
651
683
  }
@@ -754,6 +786,27 @@ function isPreHeadersTimeoutError(error) {
754
786
 
755
787
  // src/fetch.ts
756
788
  import { randomUUID } from "crypto";
789
+
790
+ // src/opaque-artifact.ts
791
+ import { createHash } from "crypto";
792
+ function opaqueProviderArtifactFingerprint(item) {
793
+ if (!item || typeof item !== "object") return null;
794
+ const record = item;
795
+ if (record.type !== "reasoning" && record.type !== "compaction") return null;
796
+ const providerData = record.providerData && typeof record.providerData === "object" ? record.providerData : null;
797
+ const ciphertext = typeof record.encrypted_content === "string" && record.encrypted_content || typeof record.encryptedContent === "string" && record.encryptedContent || typeof providerData?.encrypted_content === "string" && providerData.encrypted_content || typeof providerData?.encryptedContent === "string" && providerData.encryptedContent || null;
798
+ if (!ciphertext) return null;
799
+ return `${record.type}:${createHash("sha256").update(ciphertext).digest("hex")}`;
800
+ }
801
+ function opaqueProviderArtifactFingerprints(input) {
802
+ if (!Array.isArray(input)) return [];
803
+ return input.flatMap((item) => {
804
+ const fingerprint = opaqueProviderArtifactFingerprint(item);
805
+ return fingerprint ? [fingerprint] : [];
806
+ });
807
+ }
808
+
809
+ // src/fetch.ts
757
810
  var CODEX_TRANSPORT_ERROR_HEADER = "x-opengeni-codex-transport-error";
758
811
  function headersCarryCodexTransportMarker(headers) {
759
812
  if (!headers || typeof headers !== "object") return false;
@@ -1090,6 +1143,7 @@ function codexSubscriptionFetch(base = globalThis.fetch) {
1090
1143
  }
1091
1144
  let callerWantsStream = true;
1092
1145
  let model;
1146
+ let requestOpaqueArtifacts = [];
1093
1147
  const nextInit = { ...init, headers };
1094
1148
  if (typeof init?.body === "string") {
1095
1149
  try {
@@ -1098,9 +1152,11 @@ function codexSubscriptionFetch(base = globalThis.fetch) {
1098
1152
  const normalized = normalizeCodexRequestBody(parsed, ctx.resolveModel);
1099
1153
  model = typeof normalized.model === "string" ? normalized.model : void 0;
1100
1154
  nextInit.body = JSON.stringify(normalized);
1155
+ requestOpaqueArtifacts = opaqueProviderArtifactFingerprints(normalized.input);
1101
1156
  } catch {
1102
1157
  }
1103
1158
  }
1159
+ ctx.onRequestOpaqueArtifacts?.({ requestId, fingerprints: requestOpaqueArtifacts });
1104
1160
  headers.set(
1105
1161
  "Idempotency-Key",
1106
1162
  authenticationAttempt === 0 ? requestId : `${requestId}:auth-${authenticationAttempt}`
@@ -2219,6 +2275,269 @@ function isResponsesProtocolContentPrefix(output) {
2219
2275
  function isImageDataUrl(value) {
2220
2276
  return /^data:image\/[a-z0-9.+-]+;base64,/i.test(value);
2221
2277
  }
2278
+
2279
+ // src/realtime.ts
2280
+ var CODEX_REALTIME_CALL_URL = `${CODEX_RESPONSES_BASE}/realtime/calls?intent=quicksilver&architecture=avas`;
2281
+ var MAX_REALTIME_SDP_BYTES = 1024 * 1024;
2282
+ var REALTIME_CALL_ID = /^(?:rtc_.+|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/i;
2283
+ var CODEX_REALTIME_VOICES = [
2284
+ "juniper",
2285
+ "maple",
2286
+ "spruce",
2287
+ "ember",
2288
+ "vale",
2289
+ "breeze",
2290
+ "arbor",
2291
+ "sol",
2292
+ "cove"
2293
+ ];
2294
+ var CodexRealtimeError = class extends Error {
2295
+ constructor(code, message, providerStatus = null) {
2296
+ super(message);
2297
+ this.code = code;
2298
+ this.providerStatus = providerStatus;
2299
+ this.name = "CodexRealtimeError";
2300
+ }
2301
+ };
2302
+ async function createCodexRealtimeCall(auth, input, fetchImpl = fetch, options = {}) {
2303
+ validateRealtimeInput(input);
2304
+ const timeoutMs = options.timeoutMs ?? CODEX_REALTIME_CALL_TIMEOUT_MS;
2305
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
2306
+ throw new CodexRealtimeError("invalid_request", "Codex realtime timeout must be positive");
2307
+ }
2308
+ if (options.signal?.aborted) {
2309
+ throw new CodexRealtimeError("cancelled", "Codex realtime request cancelled");
2310
+ }
2311
+ const controller = new AbortController();
2312
+ let timedOut = false;
2313
+ let timeout;
2314
+ let rejectCancellation;
2315
+ const cancellation = new Promise((_resolve, reject) => {
2316
+ rejectCancellation = reject;
2317
+ });
2318
+ const onAbort = () => {
2319
+ controller.abort(options.signal?.reason);
2320
+ rejectCancellation?.(new CodexRealtimeError("cancelled", "Codex realtime request cancelled"));
2321
+ };
2322
+ options.signal?.addEventListener("abort", onAbort, { once: true });
2323
+ const deadline = new Promise((_resolve, reject) => {
2324
+ timeout = setTimeout(() => {
2325
+ timedOut = true;
2326
+ controller.abort();
2327
+ reject(new CodexRealtimeError("timeout", "Codex realtime request timed out"));
2328
+ }, timeoutMs);
2329
+ });
2330
+ const request = (async () => {
2331
+ const response = await fetchImpl(CODEX_REALTIME_CALL_URL, {
2332
+ method: "POST",
2333
+ headers: {
2334
+ ...codexSubscriptionHeaders(auth),
2335
+ "content-type": "application/json",
2336
+ "openai-alpha": "quicksilver=v2",
2337
+ "session-id": input.sessionId,
2338
+ "thread-id": input.sessionId
2339
+ },
2340
+ body: JSON.stringify({
2341
+ sdp: input.sdp,
2342
+ session: {
2343
+ instructions: input.instructions ?? "",
2344
+ audio: {
2345
+ output: { voice: input.voice ?? CODEX_REALTIME_DEFAULT_VOICE }
2346
+ },
2347
+ delegation: { type: "client" },
2348
+ model: CODEX_REALTIME_MODEL,
2349
+ ...input.initialItems?.length ? {
2350
+ initial_items: input.initialItems.map((item) => ({
2351
+ type: "message",
2352
+ role: item.role,
2353
+ content: [
2354
+ {
2355
+ type: item.role === "assistant" ? "output_text" : "input_text",
2356
+ text: item.text
2357
+ }
2358
+ ]
2359
+ }))
2360
+ } : {}
2361
+ }
2362
+ }),
2363
+ signal: controller.signal
2364
+ });
2365
+ if (!response.ok) {
2366
+ await response.body?.cancel().catch(() => void 0);
2367
+ throw providerHttpError(response.status);
2368
+ }
2369
+ const location = response.headers.get("location");
2370
+ if (!location || !validRealtimeLocation(location)) {
2371
+ await response.body?.cancel().catch(() => void 0);
2372
+ throw new CodexRealtimeError(
2373
+ "invalid_response",
2374
+ "Codex realtime response did not identify a compatible call",
2375
+ response.status
2376
+ );
2377
+ }
2378
+ const sdp = await readBoundedSdp(response);
2379
+ if (!isAudioSdp(sdp)) {
2380
+ throw new CodexRealtimeError(
2381
+ "invalid_response",
2382
+ "Codex realtime response was not an audio SDP answer",
2383
+ response.status
2384
+ );
2385
+ }
2386
+ return {
2387
+ sdp,
2388
+ version: CODEX_REALTIME_VERSION,
2389
+ model: CODEX_REALTIME_MODEL
2390
+ };
2391
+ })();
2392
+ try {
2393
+ return await Promise.race([request, cancellation, deadline]);
2394
+ } catch (error) {
2395
+ if (error instanceof CodexRealtimeError) throw error;
2396
+ if (options.signal?.aborted) {
2397
+ throw new CodexRealtimeError("cancelled", "Codex realtime request cancelled");
2398
+ }
2399
+ if (timedOut || controller.signal.aborted) {
2400
+ throw new CodexRealtimeError("timeout", "Codex realtime request timed out");
2401
+ }
2402
+ throw new CodexRealtimeError("network", "Codex realtime provider request failed");
2403
+ } finally {
2404
+ if (timeout) clearTimeout(timeout);
2405
+ options.signal?.removeEventListener("abort", onAbort);
2406
+ }
2407
+ }
2408
+ function selectCodexCredentialId(args) {
2409
+ if (args.sessionPinnedCredentialId && args.connectedIds.has(args.sessionPinnedCredentialId)) {
2410
+ return args.sessionPinnedCredentialId;
2411
+ }
2412
+ if (args.activeCredentialId && args.connectedIds.has(args.activeCredentialId)) {
2413
+ return args.activeCredentialId;
2414
+ }
2415
+ return null;
2416
+ }
2417
+ function validateRealtimeInput(input) {
2418
+ if (input.version !== CODEX_REALTIME_VERSION) {
2419
+ throw new CodexRealtimeError(
2420
+ "incompatible",
2421
+ `Codex realtime requires ${CODEX_REALTIME_VERSION}`
2422
+ );
2423
+ }
2424
+ if (!input.sessionId || input.sessionId.length > 128) {
2425
+ throw new CodexRealtimeError("invalid_request", "Codex realtime session id is invalid");
2426
+ }
2427
+ if (new TextEncoder().encode(input.sdp).byteLength > MAX_REALTIME_SDP_BYTES) {
2428
+ throw new CodexRealtimeError("invalid_request", "Codex realtime SDP offer is too large");
2429
+ }
2430
+ if (!isAudioSdp(input.sdp)) {
2431
+ throw new CodexRealtimeError("invalid_request", "Codex realtime requires an audio SDP offer");
2432
+ }
2433
+ if (input.voice !== void 0 && !CODEX_REALTIME_VOICES.includes(input.voice)) {
2434
+ throw new CodexRealtimeError("invalid_request", "Codex realtime voice is unsupported");
2435
+ }
2436
+ const initialItems = input.initialItems ?? [];
2437
+ if (initialItems.length > CODEX_REALTIME_INITIAL_ITEMS_MAX_COUNT) {
2438
+ throw new CodexRealtimeError(
2439
+ "invalid_request",
2440
+ `Codex realtime history exceeds ${CODEX_REALTIME_INITIAL_ITEMS_MAX_COUNT} items`
2441
+ );
2442
+ }
2443
+ let estimatedTokens = 0;
2444
+ for (const item of initialItems) {
2445
+ if (item.role !== "user" && item.role !== "developer" && item.role !== "assistant" || typeof item.text !== "string") {
2446
+ throw new CodexRealtimeError("invalid_request", "Codex realtime history item is invalid");
2447
+ }
2448
+ const itemTokens = Math.ceil(new TextEncoder().encode(item.text).byteLength / 4);
2449
+ if (itemTokens > CODEX_REALTIME_INITIAL_ITEMS_MAX_TOKENS) {
2450
+ throw new CodexRealtimeError("invalid_request", "Codex realtime history item is too large");
2451
+ }
2452
+ estimatedTokens += itemTokens;
2453
+ }
2454
+ if (estimatedTokens > CODEX_REALTIME_INITIAL_ITEMS_MAX_TOKENS) {
2455
+ throw new CodexRealtimeError("invalid_request", "Codex realtime history is too large");
2456
+ }
2457
+ }
2458
+ function providerHttpError(status) {
2459
+ if (status === 401) {
2460
+ return new CodexRealtimeError(
2461
+ "authentication",
2462
+ "Codex subscription rejected authentication",
2463
+ status
2464
+ );
2465
+ }
2466
+ if (status === 403) {
2467
+ return new CodexRealtimeError(
2468
+ "entitlement",
2469
+ "Codex subscription lacks realtime entitlement",
2470
+ status
2471
+ );
2472
+ }
2473
+ if (status === 404) {
2474
+ return new CodexRealtimeError(
2475
+ "incompatible",
2476
+ "Codex subscription realtime is unavailable",
2477
+ status
2478
+ );
2479
+ }
2480
+ if (status === 429) {
2481
+ return new CodexRealtimeError("rate_limited", "Codex realtime is rate limited", status);
2482
+ }
2483
+ return new CodexRealtimeError("provider", "Codex realtime provider request failed", status);
2484
+ }
2485
+ function validRealtimeLocation(location) {
2486
+ const path = location.split("?", 1)[0] ?? "";
2487
+ const segment = path.split("/").filter(Boolean).at(-1) ?? "";
2488
+ return REALTIME_CALL_ID.test(segment);
2489
+ }
2490
+ function isAudioSdp(sdp) {
2491
+ return /^v=0(?:\r?\n)/.test(sdp) && /(?:^|\r?\n)m=audio\s/m.test(sdp);
2492
+ }
2493
+ async function readBoundedSdp(response) {
2494
+ const declared = Number(response.headers.get("content-length"));
2495
+ if (Number.isFinite(declared) && declared > MAX_REALTIME_SDP_BYTES) {
2496
+ await response.body?.cancel().catch(() => void 0);
2497
+ throw new CodexRealtimeError(
2498
+ "invalid_response",
2499
+ "Codex realtime SDP answer is too large",
2500
+ response.status
2501
+ );
2502
+ }
2503
+ if (!response.body) return "";
2504
+ const reader = response.body.getReader();
2505
+ const chunks = [];
2506
+ let total = 0;
2507
+ try {
2508
+ while (true) {
2509
+ const next = await reader.read();
2510
+ if (next.done) break;
2511
+ total += next.value.byteLength;
2512
+ if (total > MAX_REALTIME_SDP_BYTES) {
2513
+ await reader.cancel();
2514
+ throw new CodexRealtimeError(
2515
+ "invalid_response",
2516
+ "Codex realtime SDP answer is too large",
2517
+ response.status
2518
+ );
2519
+ }
2520
+ chunks.push(next.value);
2521
+ }
2522
+ } finally {
2523
+ reader.releaseLock();
2524
+ }
2525
+ const bytes = new Uint8Array(total);
2526
+ let offset = 0;
2527
+ for (const chunk of chunks) {
2528
+ bytes.set(chunk, offset);
2529
+ offset += chunk.byteLength;
2530
+ }
2531
+ try {
2532
+ return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
2533
+ } catch {
2534
+ throw new CodexRealtimeError(
2535
+ "invalid_response",
2536
+ "Codex realtime SDP answer was not valid UTF-8",
2537
+ response.status
2538
+ );
2539
+ }
2540
+ }
2222
2541
  export {
2223
2542
  CODEX_APPS_MCP_SERVER_ID,
2224
2543
  CODEX_APPS_MCP_SERVER_NAME,
@@ -2245,6 +2564,17 @@ export {
2245
2564
  CODEX_PROVIDER_BASE_URL,
2246
2565
  CODEX_PROVIDER_ID,
2247
2566
  CODEX_RATE_LIMIT_RESET_OUTCOMES,
2567
+ CODEX_REALTIME_CALL_TIMEOUT_MS,
2568
+ CODEX_REALTIME_CONTEXT_APPEND_MAX_BYTES,
2569
+ CODEX_REALTIME_DEFAULT_VOICE,
2570
+ CODEX_REALTIME_INITIAL_ITEMS_MAX_COUNT,
2571
+ CODEX_REALTIME_INITIAL_ITEMS_MAX_TOKENS,
2572
+ CODEX_REALTIME_MODEL,
2573
+ CODEX_REALTIME_V3_MAX_EVENT_BYTES,
2574
+ CODEX_REALTIME_V3_MAX_IDENTIFIER_BYTES,
2575
+ CODEX_REALTIME_V3_MAX_TEXT_BYTES,
2576
+ CODEX_REALTIME_VERSION,
2577
+ CODEX_REALTIME_VOICES,
2248
2578
  CODEX_REFRESH_FALLBACK_MS,
2249
2579
  CODEX_REFRESH_WINDOW_MS,
2250
2580
  CODEX_RESPONSES_BASE,
@@ -2262,6 +2592,7 @@ export {
2262
2592
  CODEX_WEEKLY_WINDOW_SECONDS,
2263
2593
  CODEX_WHAM_BASE,
2264
2594
  CodexDeviceError,
2595
+ CodexRealtimeError,
2265
2596
  CodexRefreshTransient,
2266
2597
  CodexReloginRequired,
2267
2598
  CodexResponseTimeoutError,
@@ -2283,8 +2614,13 @@ export {
2283
2614
  codexAppsSanitizingFetch,
2284
2615
  codexRequestStorage,
2285
2616
  codexSubscriptionFetch,
2617
+ codexSubscriptionHeaders,
2286
2618
  consumeCodexRateLimitResetCredit,
2619
+ contextAppendChunks,
2620
+ createCodexRealtimeCall,
2287
2621
  decodeJwtPayload,
2622
+ encodeCodexRealtimeV3DelegationContextAppend,
2623
+ encodeCodexRealtimeV3SessionContextAppend,
2288
2624
  exchangeDeviceCode,
2289
2625
  fetchCodexModels,
2290
2626
  fetchCodexRateLimitResetCredits,
@@ -2295,9 +2631,12 @@ export {
2295
2631
  modelToolOutputSerializationBudgetTokens,
2296
2632
  normalizeCodexRequestBody,
2297
2633
  normalizeCodexUsage,
2634
+ opaqueProviderArtifactFingerprint,
2635
+ opaqueProviderArtifactFingerprints,
2298
2636
  parseCodexRateLimitResetConsumeResponse,
2299
2637
  parseCodexRateLimitResetCreditsDetails,
2300
2638
  parseCodexRateLimitResetCreditsSummary,
2639
+ parseCodexRealtimeV3Event,
2301
2640
  parseCodexUsageHeaders,
2302
2641
  parseIdToken,
2303
2642
  pollDeviceCode,
@@ -2306,6 +2645,7 @@ export {
2306
2645
  resolveCodexResponseTimeoutPolicy,
2307
2646
  sanitizeMcpJsonBody,
2308
2647
  sanitizeMcpSseBody,
2648
+ selectCodexCredentialId,
2309
2649
  startDeviceCode,
2310
2650
  truncateMiddleWithTokenBudget,
2311
2651
  withCodexRequestOverrides