@opengeni/codex 0.2.3 → 0.2.5

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
@@ -26,7 +26,7 @@ import {
26
26
  CODEX_RESPONSES_BASE,
27
27
  CODEX_TOKEN_URL,
28
28
  CODEX_WHAM_BASE
29
- } from "./chunk-K47573CJ.js";
29
+ } from "./chunk-AMRVHBCD.js";
30
30
 
31
31
  // src/billing.ts
32
32
  function isCodexBilledModel(model) {
@@ -636,14 +636,18 @@ async function bufferCodexErrorResponse(res) {
636
636
  if (errorType === CODEX_USAGE_LIMIT_ERROR_TYPE) {
637
637
  headers.set("x-should-retry", "false");
638
638
  }
639
- return new Response(bodyText, { status: res.status, statusText: res.statusText, headers });
639
+ return new Response(bodyText, {
640
+ status: res.status,
641
+ statusText: res.statusText,
642
+ headers
643
+ });
640
644
  }
641
645
  async function sseToJsonResponse(res) {
642
646
  const text = await res.text();
643
647
  let final = null;
648
+ let terminalError = null;
644
649
  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");
650
+ for (const data of sseDataPayloads(text)) {
647
651
  if (!data || data === "[DONE]") {
648
652
  continue;
649
653
  }
@@ -651,12 +655,64 @@ async function sseToJsonResponse(res) {
651
655
  const ev = JSON.parse(data);
652
656
  if (ev.type === "response.output_item.done" && ev.item !== void 0) {
653
657
  items.push(ev.item);
654
- } else if (ev.type === "response.completed" || ev.type === "response.done" || ev.type === "response.incomplete") {
658
+ } else if (ev.type === "response.failed") {
659
+ terminalError = codexSseFailureResponse(
660
+ res,
661
+ ev.response?.error,
662
+ "response_failed",
663
+ "The Codex response failed",
664
+ {
665
+ eventType: ev.type,
666
+ responseId: ev.response?.id,
667
+ responseStatus: ev.response?.status
668
+ }
669
+ );
670
+ } else if (ev.type === "error" || ev.type === "response.error") {
671
+ terminalError = codexSseFailureResponse(
672
+ res,
673
+ ev.error ?? ev.response?.error ?? ev,
674
+ "response_error",
675
+ "The Codex response stream reported an error",
676
+ {
677
+ eventType: ev.type,
678
+ responseId: ev.response?.id,
679
+ responseStatus: ev.response?.status
680
+ }
681
+ );
682
+ } else if (ev.type === "response.incomplete") {
683
+ const details = ev.response?.incomplete_details;
684
+ const reason = details && typeof details === "object" ? details.reason : void 0;
685
+ terminalError = codexSseFailureResponse(
686
+ res,
687
+ {
688
+ code: "response_incomplete",
689
+ message: typeof reason === "string" && reason.length > 0 ? `The Codex response was incomplete (${reason})` : "The Codex response was incomplete"
690
+ },
691
+ "response_incomplete",
692
+ "The Codex response was incomplete",
693
+ {
694
+ eventType: ev.type,
695
+ responseId: ev.response?.id,
696
+ responseStatus: ev.response?.status
697
+ }
698
+ );
699
+ } else if (ev.type === "response.completed" || ev.type === "response.done") {
655
700
  final = ev.response ?? null;
656
701
  }
657
702
  } catch {
658
703
  }
659
704
  }
705
+ if (terminalError) {
706
+ return terminalError;
707
+ }
708
+ if (!final) {
709
+ return codexSseFailureResponse(
710
+ res,
711
+ null,
712
+ "invalid_sse_terminal",
713
+ "The Codex response stream ended without a terminal response"
714
+ );
715
+ }
660
716
  if (final && items.length > 0) {
661
717
  final = { ...final, output: items };
662
718
  }
@@ -668,64 +724,331 @@ async function sseToJsonResponse(res) {
668
724
  const headers = new Headers(res.headers);
669
725
  headers.set("content-type", "application/json");
670
726
  headers.delete("content-length");
671
- return new Response(JSON.stringify(final ?? {}), { status: 200, headers });
727
+ return new Response(JSON.stringify(final), { status: 200, headers });
728
+ }
729
+ var NON_RETRYABLE_SSE_ERROR_CODES = /* @__PURE__ */ new Set([
730
+ "bio_policy",
731
+ "context_length_exceeded",
732
+ "cyber_policy",
733
+ "insufficient_quota",
734
+ "invalid_prompt",
735
+ "usage_limit_reached"
736
+ ]);
737
+ function sseDataPayloads(text) {
738
+ const payloads = [];
739
+ let dataLines = [];
740
+ const dispatch = () => {
741
+ if (dataLines.length > 0) payloads.push(dataLines.join("\n"));
742
+ dataLines = [];
743
+ };
744
+ for (const line of text.split(/\r\n|\r|\n/)) {
745
+ if (line === "") {
746
+ dispatch();
747
+ continue;
748
+ }
749
+ if (line === "data") {
750
+ dataLines.push("");
751
+ continue;
752
+ }
753
+ if (!line.startsWith("data:")) continue;
754
+ const value = line.slice(5);
755
+ dataLines.push(value.startsWith(" ") ? value.slice(1) : value);
756
+ }
757
+ dispatch();
758
+ return payloads;
759
+ }
760
+ var CODEX_TERMINAL_ERROR_FIELD_MAX_BYTES = 256;
761
+ var CODEX_TERMINAL_ERROR_MESSAGE_MAX_BYTES = 4 * 1024;
762
+ var CODEX_TERMINAL_ERROR_TRUNCATION_MARKER = "\u2026 [truncated]";
763
+ function boundedTerminalErrorField(value, maxBytes) {
764
+ if (typeof value !== "string") return { truncated: false };
765
+ const encoder = new TextEncoder();
766
+ const encoded = encoder.encode(value);
767
+ if (encoded.byteLength <= maxBytes) return { value, truncated: false };
768
+ const markerBytes = encoder.encode(CODEX_TERMINAL_ERROR_TRUNCATION_MARKER).byteLength;
769
+ let prefixEnd = Math.max(0, maxBytes - markerBytes);
770
+ while (prefixEnd > 0 && (encoded[prefixEnd] & 192) === 128) {
771
+ prefixEnd -= 1;
772
+ }
773
+ return {
774
+ value: `${new TextDecoder().decode(encoded.subarray(0, prefixEnd))}${CODEX_TERMINAL_ERROR_TRUNCATION_MARKER}`,
775
+ truncated: true
776
+ };
777
+ }
778
+ function codexSseFailureResponse(source, rawError, fallbackCode, fallbackMessage, metadata = {}) {
779
+ const projection = codexSseFailureProjection(
780
+ source,
781
+ rawError,
782
+ fallbackCode,
783
+ fallbackMessage,
784
+ metadata
785
+ );
786
+ return new Response(JSON.stringify({ error: projection.error }), {
787
+ status: projection.status,
788
+ headers: projection.headers
789
+ });
790
+ }
791
+ function codexSseFailureProjection(source, rawError, fallbackCode, fallbackMessage, metadata = {}) {
792
+ const record = rawError && typeof rawError === "object" && !Array.isArray(rawError) ? rawError : {};
793
+ const typeField = boundedTerminalErrorField(record.type, CODEX_TERMINAL_ERROR_FIELD_MAX_BYTES);
794
+ const codeField = boundedTerminalErrorField(record.code, CODEX_TERMINAL_ERROR_FIELD_MAX_BYTES);
795
+ const messageField = boundedTerminalErrorField(
796
+ record.message ?? (typeof rawError === "string" ? rawError : void 0),
797
+ CODEX_TERMINAL_ERROR_MESSAGE_MAX_BYTES
798
+ );
799
+ const paramField = boundedTerminalErrorField(record.param, CODEX_TERMINAL_ERROR_FIELD_MAX_BYTES);
800
+ const eventTypeField = boundedTerminalErrorField(
801
+ metadata.eventType,
802
+ CODEX_TERMINAL_ERROR_FIELD_MAX_BYTES
803
+ );
804
+ const responseIdField = boundedTerminalErrorField(
805
+ metadata.responseId,
806
+ CODEX_TERMINAL_ERROR_FIELD_MAX_BYTES
807
+ );
808
+ const responseStatusField = boundedTerminalErrorField(
809
+ metadata.responseStatus,
810
+ CODEX_TERMINAL_ERROR_FIELD_MAX_BYTES
811
+ );
812
+ const providerType = typeField.value === "error" || typeField.value === "response.error" || typeField.value === "response.failed" ? void 0 : typeField.value;
813
+ const code = (codeField.value?.length ? codeField.value : void 0) ?? (providerType?.length ? providerType : void 0) ?? fallbackCode;
814
+ 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));
815
+ const error = {
816
+ type: providerType?.length ? providerType : code,
817
+ code,
818
+ message: messageField.value?.length ? messageField.value : fallbackMessage,
819
+ ...paramField.value?.length ? { param: paramField.value } : {},
820
+ ...eventTypeField.value?.length ? { event_type: eventTypeField.value } : {},
821
+ ...responseIdField.value?.length ? { response_id: responseIdField.value } : {},
822
+ ...responseStatusField.value?.length ? { response_status: responseStatusField.value } : {},
823
+ ...diagnosticTruncated ? { diagnostic_truncated: true } : {}
824
+ };
825
+ const status = code === "rate_limit_exceeded" || code === "usage_limit_reached" || code === "insufficient_quota" ? 429 : NON_RETRYABLE_SSE_ERROR_CODES.has(code) ? 400 : 502;
826
+ const headers = new Headers(source.headers);
827
+ headers.set("content-type", "application/json");
828
+ headers.set(CODEX_TRANSPORT_ERROR_HEADER, "1");
829
+ headers.set("x-should-retry", "false");
830
+ headers.delete("content-length");
831
+ headers.delete("content-encoding");
832
+ return { status, error, headers };
833
+ }
834
+ var CodexStreamingTerminalError = class extends Error {
835
+ status;
836
+ code;
837
+ type;
838
+ eventType;
839
+ responseId;
840
+ responseStatus;
841
+ headers;
842
+ error;
843
+ constructor(projection, publicMessage) {
844
+ super(publicMessage);
845
+ this.name = "CodexStreamingTerminalError";
846
+ this.status = projection.status;
847
+ this.code = projection.error.code;
848
+ this.type = projection.error.type;
849
+ if (projection.error.event_type !== void 0) {
850
+ this.eventType = projection.error.event_type;
851
+ }
852
+ if (projection.error.response_id !== void 0) {
853
+ this.responseId = projection.error.response_id;
854
+ }
855
+ if (projection.error.response_status !== void 0) {
856
+ this.responseStatus = projection.error.response_status;
857
+ }
858
+ this.headers = projection.headers;
859
+ this.error = {
860
+ type: projection.error.type,
861
+ code: projection.error.code,
862
+ ...projection.error.event_type ? { event_type: projection.error.event_type } : {},
863
+ ...projection.error.response_id ? { response_id: projection.error.response_id } : {},
864
+ ...projection.error.response_status ? { response_status: projection.error.response_status } : {},
865
+ ...projection.error.diagnostic_truncated ? { diagnostic_truncated: true } : {}
866
+ };
867
+ }
868
+ };
869
+ function codexSseFailureError(source, rawError, fallbackCode, publicMessage, metadata = {}) {
870
+ return new CodexStreamingTerminalError(
871
+ codexSseFailureProjection(source, rawError, fallbackCode, publicMessage, metadata),
872
+ publicMessage
873
+ );
672
874
  }
673
875
  function repairCodexStream(res) {
674
876
  if (!res.body) {
675
- return res;
877
+ const error = codexSseFailureError(
878
+ res,
879
+ null,
880
+ "invalid_sse_terminal",
881
+ "The Codex response stream ended without a terminal response"
882
+ );
883
+ const body = new ReadableStream({
884
+ start(controller) {
885
+ controller.error(error);
886
+ }
887
+ });
888
+ const headers2 = new Headers(res.headers);
889
+ headers2.delete("content-length");
890
+ return new Response(body, {
891
+ status: res.status,
892
+ statusText: res.statusText,
893
+ headers: headers2
894
+ });
676
895
  }
677
896
  const items = [];
678
897
  const decoder = new TextDecoder();
679
898
  const encoder = new TextEncoder();
680
899
  let buffer = "";
900
+ let successfulTerminalSeen = false;
901
+ const emitCompleteBlocks = (controller, final) => {
902
+ let boundary = findSseBlockBoundary(buffer, final);
903
+ while (boundary) {
904
+ const block = buffer.slice(0, boundary.start);
905
+ const separator = buffer.slice(boundary.start, boundary.end);
906
+ buffer = buffer.slice(boundary.end);
907
+ const patched = patchSseBlock(block, items, res);
908
+ successfulTerminalSeen ||= patched.successfulTerminal;
909
+ controller.enqueue(encoder.encode(`${patched.block}${separator}`));
910
+ boundary = findSseBlockBoundary(buffer, final);
911
+ }
912
+ };
681
913
  const transform = new TransformStream({
682
914
  transform(chunk, controller) {
683
915
  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
- }
916
+ emitCompleteBlocks(controller, false);
693
917
  },
694
918
  flush(controller) {
919
+ buffer += decoder.decode();
920
+ emitCompleteBlocks(controller, true);
695
921
  if (buffer.length > 0) {
696
- controller.enqueue(encoder.encode(patchSseBlock(buffer, items)));
922
+ const patched = patchSseBlock(buffer, items, res);
923
+ successfulTerminalSeen ||= patched.successfulTerminal;
924
+ controller.enqueue(encoder.encode(patched.block));
925
+ buffer = "";
926
+ }
927
+ if (!successfulTerminalSeen) {
928
+ throw codexSseFailureError(
929
+ res,
930
+ null,
931
+ "invalid_sse_terminal",
932
+ "The Codex response stream ended without a terminal response"
933
+ );
697
934
  }
698
935
  }
699
936
  });
700
937
  const headers = new Headers(res.headers);
701
938
  headers.delete("content-length");
702
- return new Response(res.body.pipeThrough(transform), { status: res.status, headers });
939
+ return new Response(res.body.pipeThrough(transform), {
940
+ status: res.status,
941
+ headers
942
+ });
943
+ }
944
+ function findSseBlockBoundary(value, final) {
945
+ for (let index = 0; index < value.length; index += 1) {
946
+ const firstEnd = sseLineEndingEnd(value, index, final);
947
+ if (firstEnd === null) continue;
948
+ const secondEnd = sseLineEndingEnd(value, firstEnd, final);
949
+ if (secondEnd !== null) {
950
+ return { start: index, end: secondEnd };
951
+ }
952
+ index = firstEnd - 1;
953
+ }
954
+ return null;
955
+ }
956
+ function sseLineEndingEnd(value, index, final) {
957
+ const current = value[index];
958
+ if (current === "\n") return index + 1;
959
+ if (current !== "\r") return null;
960
+ if (index + 1 < value.length) {
961
+ return value[index + 1] === "\n" ? index + 2 : index + 1;
962
+ }
963
+ return final ? index + 1 : null;
703
964
  }
704
- function patchSseBlock(block, items) {
705
- const lines = block.split("\n");
965
+ function patchSseBlock(block, items, source) {
966
+ const lines = block.split(/\r\n|\r|\n/);
706
967
  const dataStr = lines.filter((l) => l.startsWith("data:")).map((l) => l.slice(5).trim()).join("\n");
707
968
  if (!dataStr || dataStr === "[DONE]") {
708
- return block;
969
+ return { block, successfulTerminal: false };
709
970
  }
710
971
  let ev;
711
972
  try {
712
973
  ev = JSON.parse(dataStr);
713
974
  } catch {
714
- return block;
975
+ return { block, successfulTerminal: false };
715
976
  }
716
977
  if (ev.type === "response.output_item.done" && ev.item !== void 0) {
717
978
  items.push(ev.item);
718
- return block;
979
+ return { block, successfulTerminal: false };
719
980
  }
720
- if ((ev.type === "response.completed" || ev.type === "response.done" || ev.type === "response.incomplete") && ev.response) {
981
+ if (ev.type === "response.failed") {
982
+ throw codexSseFailureError(
983
+ source,
984
+ ev.response?.error,
985
+ "response_failed",
986
+ "The Codex response failed",
987
+ {
988
+ eventType: ev.type,
989
+ responseId: ev.response?.id,
990
+ responseStatus: ev.response?.status
991
+ }
992
+ );
993
+ }
994
+ if (ev.type === "error" || ev.type === "response.error") {
995
+ throw codexSseFailureError(
996
+ source,
997
+ ev.error ?? ev.response?.error ?? ev,
998
+ "response_error",
999
+ "The Codex response stream reported an error",
1000
+ {
1001
+ eventType: ev.type,
1002
+ responseId: ev.response?.id,
1003
+ responseStatus: ev.response?.status
1004
+ }
1005
+ );
1006
+ }
1007
+ if (ev.type === "response.incomplete") {
1008
+ const details = ev.response?.incomplete_details;
1009
+ const reason = details && typeof details === "object" ? details.reason : void 0;
1010
+ throw codexSseFailureError(
1011
+ source,
1012
+ {
1013
+ code: "response_incomplete",
1014
+ message: typeof reason === "string" && reason.length > 0 ? `The Codex response was incomplete (${reason})` : "The Codex response was incomplete"
1015
+ },
1016
+ "response_incomplete",
1017
+ "The Codex response was incomplete",
1018
+ {
1019
+ eventType: ev.type,
1020
+ responseId: ev.response?.id,
1021
+ responseStatus: ev.response?.status
1022
+ }
1023
+ );
1024
+ }
1025
+ if ((ev.type === "response.completed" || ev.type === "response.done") && ev.response) {
1026
+ if (ev.response.status === "failed" || ev.response.status === "incomplete" || ev.response.error !== null && ev.response.error !== void 0) {
1027
+ throw codexSseFailureError(
1028
+ source,
1029
+ ev.response.error,
1030
+ ev.response.status === "incomplete" ? "response_incomplete" : "response_failed",
1031
+ ev.response.status === "incomplete" ? "The Codex response was incomplete" : "The Codex response failed",
1032
+ {
1033
+ eventType: ev.type,
1034
+ responseId: ev.response.id,
1035
+ responseStatus: ev.response.status
1036
+ }
1037
+ );
1038
+ }
721
1039
  const out = ev.response.output;
722
1040
  if ((!Array.isArray(out) || out.length === 0) && items.length > 0) {
723
1041
  ev.response = { ...ev.response, output: items };
724
1042
  const nonData = lines.filter((l) => !l.startsWith("data:"));
725
- return [...nonData, `data: ${JSON.stringify(ev)}`].join("\n");
1043
+ const lineEnding = block.match(/\r\n|\r|\n/)?.[0] ?? "\n";
1044
+ return {
1045
+ block: [...nonData, `data: ${JSON.stringify(ev)}`].join(lineEnding),
1046
+ successfulTerminal: true
1047
+ };
726
1048
  }
1049
+ return { block, successfulTerminal: true };
727
1050
  }
728
- return block;
1051
+ return { block, successfulTerminal: false };
729
1052
  }
730
1053
 
731
1054
  // src/mcp-sanitize.ts
@@ -894,6 +1217,412 @@ function codexAppsSanitizingFetch(base = globalThis.fetch, namespaceSink) {
894
1217
  return new Response(sanitized, { status: res.status, statusText: res.statusText, headers });
895
1218
  };
896
1219
  }
1220
+
1221
+ // src/oversized-image-card.ts
1222
+ var MODEL_TOOL_OUTPUT_OVERSIZED_IMAGE_CARD_DATA_URL = "data:image/png;base64,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";
1223
+
1224
+ // src/model-output-truncation.ts
1225
+ var CODEX_MODEL_TOOL_OUTPUT_TRUNCATION_TOKENS = 1e4;
1226
+ var CODEX_TOOL_OUTPUT_SERIALIZATION_ALLOWANCE = 1.2;
1227
+ var DEFAULT_MODEL_TOOL_OUTPUT_TRUNCATION_TOKENS = CODEX_MODEL_TOOL_OUTPUT_TRUNCATION_TOKENS;
1228
+ var APPROX_BYTES_PER_TOKEN = 4;
1229
+ var TOKEN_TRUNCATION_MARKER = /…\d{1,12} tokens truncated…/u;
1230
+ var TOOL_RESULT_TYPES = /* @__PURE__ */ new Set([
1231
+ "function_call_result",
1232
+ "function_call_output",
1233
+ "computer_call_result",
1234
+ "custom_tool_call_output",
1235
+ "shell_call_output",
1236
+ "apply_patch_call_output"
1237
+ ]);
1238
+ var STRUCTURAL_STRING_KEYS = /* @__PURE__ */ new Set([
1239
+ "type",
1240
+ "role",
1241
+ "status",
1242
+ "name",
1243
+ "id",
1244
+ "callId",
1245
+ "call_id",
1246
+ "namespace",
1247
+ "detail",
1248
+ "mimeType",
1249
+ "media_type"
1250
+ ]);
1251
+ var MODEL_TOOL_OUTPUT_MAX_DEPTH = 12;
1252
+ var MODEL_TOOL_OUTPUT_MAX_CONTAINER_ENTRIES = 255;
1253
+ var MODEL_TOOL_OUTPUT_MAX_TOTAL_ENTRIES = 2048;
1254
+ var MODEL_TOOL_OUTPUT_MAX_PROPERTY_KEY_BYTES = 256;
1255
+ var MODEL_TOOL_OUTPUT_MAX_STRUCTURAL_STRING_TOKENS = 64;
1256
+ var MODEL_TOOL_OUTPUT_STRUCTURAL_STRING_BUDGET_TOKENS = 1024;
1257
+ var MODEL_TOOL_OUTPUT_OPAQUE_PAYLOAD_MAX_BYTES = 8 * 1024 * 1024;
1258
+ var DEPTH_OMISSION_MARKER = "[OpenGeni omitted subtree: maximum structured tool-output depth exceeded]";
1259
+ var CYCLE_OMISSION_MARKER = "[OpenGeni omitted subtree: cyclic tool output]";
1260
+ var STRUCTURAL_STRING_OMISSION_MARKER = "[OpenGeni omitted structural string: structural budget exhausted]";
1261
+ var TEXT_FIELD_OMISSION_MARKER = /^\[omitted text field \d+ \.\.\.\]$/u;
1262
+ var TEXT_ITEMS_OMISSION_MARKER = /^\[omitted \d+ text items \.\.\.\]$/u;
1263
+ var STRUCTURAL_ENTRIES_OMISSION_MARKER = /^\[OpenGeni omitted \d+ structured (?:array items|object properties)\]$/u;
1264
+ var OPAQUE_PAYLOAD_OMISSION_MARKER = /^\[OpenGeni omitted (?:image|file|encrypted) payload: \d+ bytes exceeded the bounded model-input allowance\]$/u;
1265
+ var STRUCTURAL_PROPERTIES_MARKER_KEY = "__opengeni_omitted_properties__";
1266
+ function modelToolOutputSerializationBudgetTokens(policyTokens = DEFAULT_MODEL_TOOL_OUTPUT_TRUNCATION_TOKENS) {
1267
+ return Math.ceil(Math.max(0, policyTokens) * CODEX_TOOL_OUTPUT_SERIALIZATION_ALLOWANCE);
1268
+ }
1269
+ function approximateTokenCount(value) {
1270
+ return Math.ceil(Buffer.byteLength(value, "utf8") / APPROX_BYTES_PER_TOKEN);
1271
+ }
1272
+ function truncateMiddleWithTokenBudget(value, maxTokens) {
1273
+ if (value.length === 0) return value;
1274
+ const maxBytes = Math.max(0, maxTokens) * APPROX_BYTES_PER_TOKEN;
1275
+ const valueBytes = Buffer.byteLength(value, "utf8");
1276
+ if (maxTokens > 0 && valueBytes <= maxBytes) return value;
1277
+ const existingMarker = value.match(TOKEN_TRUNCATION_MARKER)?.[0];
1278
+ if (existingMarker && valueBytes <= maxBytes + Buffer.byteLength(existingMarker, "utf8")) {
1279
+ return value;
1280
+ }
1281
+ if (maxBytes === 0) {
1282
+ return `\u2026${approximateTokenCount(value)} tokens truncated\u2026`;
1283
+ }
1284
+ const leftBudget = Math.floor(maxBytes / 2);
1285
+ const rightBudget = maxBytes - leftBudget;
1286
+ const bytes = Buffer.from(value, "utf8");
1287
+ let leftEnd = Math.min(leftBudget, bytes.length);
1288
+ while (leftEnd > 0 && leftEnd < bytes.length && isUtf8ContinuationByte(bytes[leftEnd])) {
1289
+ leftEnd -= 1;
1290
+ }
1291
+ let rightStart = Math.max(0, bytes.length - rightBudget);
1292
+ while (rightStart < bytes.length && isUtf8ContinuationByte(bytes[rightStart])) {
1293
+ rightStart += 1;
1294
+ }
1295
+ const left = bytes.subarray(0, leftEnd).toString("utf8");
1296
+ const right = bytes.subarray(rightStart).toString("utf8");
1297
+ const removedBytes = Math.max(0, valueBytes - maxBytes);
1298
+ const removedTokens = Math.ceil(removedBytes / APPROX_BYTES_PER_TOKEN);
1299
+ return `${left}\u2026${removedTokens} tokens truncated\u2026${right}`;
1300
+ }
1301
+ function isUtf8ContinuationByte(value) {
1302
+ return (value & 192) === 128;
1303
+ }
1304
+ function boundModelToolOutputItem(item, policyTokens = DEFAULT_MODEL_TOOL_OUTPUT_TRUNCATION_TOKENS) {
1305
+ const type = typeof item.type === "string" ? item.type : "";
1306
+ if (!TOOL_RESULT_TYPES.has(type)) return item;
1307
+ const budget = modelToolOutputSerializationBudgetTokens(policyTokens);
1308
+ const boundedOutput = boundToolOutputValue(item.output, budget);
1309
+ return boundedOutput === item.output ? item : { ...item, output: boundedOutput };
1310
+ }
1311
+ function boundModelToolOutputItems(items, policyTokens = DEFAULT_MODEL_TOOL_OUTPUT_TRUNCATION_TOKENS) {
1312
+ return items.map((item) => boundModelToolOutputItem(item, policyTokens));
1313
+ }
1314
+ function boundToolOutputValue(output, budgetTokens) {
1315
+ const state = modelOutputBoundState(budgetTokens);
1316
+ if (typeof output === "string") {
1317
+ if (isGeneratedModelOutputMarker(output)) {
1318
+ observeGeneratedMarkerBudget(output, state);
1319
+ return output;
1320
+ }
1321
+ if (isImageDataUrl(output)) return boundOpaqueProtocolString(output, state, "image");
1322
+ return truncateMiddleWithTokenBudget(output, budgetTokens);
1323
+ }
1324
+ if (Array.isArray(output)) {
1325
+ const isProtocolContent = isResponsesProtocolContentPrefix(output);
1326
+ return isProtocolContent ? boundStructuredOutputItems(output, state) : boundTextLeaves(output, state);
1327
+ }
1328
+ if (!output || typeof output !== "object") return output;
1329
+ const record = output;
1330
+ return boundTextLeaves(record, state);
1331
+ }
1332
+ function modelOutputBoundState(budgetTokens) {
1333
+ return {
1334
+ remaining: Math.max(0, budgetTokens),
1335
+ remainingStructural: MODEL_TOOL_OUTPUT_STRUCTURAL_STRING_BUDGET_TOKENS,
1336
+ remainingEntries: MODEL_TOOL_OUTPUT_MAX_TOTAL_ENTRIES,
1337
+ remainingOpaqueBytes: MODEL_TOOL_OUTPUT_OPAQUE_PAYLOAD_MAX_BYTES,
1338
+ opaqueOmissions: 0,
1339
+ lastOpaqueOmissionMarker: null,
1340
+ omitted: 0,
1341
+ seen: /* @__PURE__ */ new WeakSet()
1342
+ };
1343
+ }
1344
+ function boundStructuredOutputItems(items, state) {
1345
+ let omitted = 0;
1346
+ let changed = false;
1347
+ const out = [];
1348
+ let processed = 0;
1349
+ const terminalStructuralMarker = items.length <= MODEL_TOOL_OUTPUT_MAX_CONTAINER_ENTRIES + 1 && isTypedStructuralArrayOmissionMarker(items.at(-1)) ? items.at(-1) : null;
1350
+ let preservedTerminalStructuralMarker = false;
1351
+ for (let index = 0; index < items.length; index += 1) {
1352
+ const item = items[index];
1353
+ if (processed >= MODEL_TOOL_OUTPUT_MAX_CONTAINER_ENTRIES || state.remainingEntries <= 0) {
1354
+ if (terminalStructuralMarker && index <= items.length - 1) {
1355
+ out.push(terminalStructuralMarker);
1356
+ preservedTerminalStructuralMarker = true;
1357
+ }
1358
+ break;
1359
+ }
1360
+ processed += 1;
1361
+ state.remainingEntries -= 1;
1362
+ const record = item;
1363
+ if (record.type === "input_text" && isGeneratedModelOutputMarker(record.text)) {
1364
+ const bounded2 = boundTextLeaves(item, state, 1);
1365
+ out.push(bounded2);
1366
+ if (item === terminalStructuralMarker) preservedTerminalStructuralMarker = true;
1367
+ if (bounded2 !== item) changed = true;
1368
+ continue;
1369
+ }
1370
+ if (record.type === "input_text" && state.remaining === 0) {
1371
+ omitted += 1;
1372
+ changed = true;
1373
+ continue;
1374
+ }
1375
+ const bounded = boundResponsesProtocolContentItem(record, state);
1376
+ out.push(bounded);
1377
+ if (item === terminalStructuralMarker) preservedTerminalStructuralMarker = true;
1378
+ if (bounded !== item) changed = true;
1379
+ }
1380
+ if (omitted > 0) {
1381
+ out.push({
1382
+ type: "input_text",
1383
+ text: `[omitted ${omitted} text items ...]`
1384
+ });
1385
+ }
1386
+ const structurallyOmitted = preservedTerminalStructuralMarker ? 0 : items.length - processed;
1387
+ if (structurallyOmitted > 0) {
1388
+ out.push(typedStructuredArrayOmissionMarker(structurallyOmitted));
1389
+ changed = true;
1390
+ }
1391
+ return changed ? out : items;
1392
+ }
1393
+ function boundResponsesProtocolContentItem(item, state) {
1394
+ const opaqueOmissionsBefore = state.opaqueOmissions;
1395
+ const bounded = boundTextLeaves(item, state, 1);
1396
+ if (item.type === "input_image" && state.opaqueOmissions > opaqueOmissionsBefore) {
1397
+ return {
1398
+ type: "input_image",
1399
+ imageUrl: MODEL_TOOL_OUTPUT_OVERSIZED_IMAGE_CARD_DATA_URL
1400
+ };
1401
+ }
1402
+ if (item.type === "input_file" && state.opaqueOmissions > opaqueOmissionsBefore) {
1403
+ return typedProtocolTextMarker(
1404
+ state.lastOpaqueOmissionMarker ?? "[OpenGeni omitted file payload: 0 bytes exceeded the bounded model-input allowance]"
1405
+ );
1406
+ }
1407
+ return bounded;
1408
+ }
1409
+ function boundTextLeaves(value, state, depth = 0, opaqueKind = null) {
1410
+ if (typeof value === "string") {
1411
+ if (isGeneratedModelOutputMarker(value)) {
1412
+ observeGeneratedMarkerBudget(value, state);
1413
+ return value;
1414
+ }
1415
+ if (opaqueKind || isImageDataUrl(value)) {
1416
+ return boundOpaqueProtocolString(value, state, opaqueKind ?? "image");
1417
+ }
1418
+ if (state.remaining === 0) {
1419
+ state.omitted += 1;
1420
+ return `[omitted text field ${state.omitted} ...]`;
1421
+ }
1422
+ const cost = approximateTokenCount(value);
1423
+ if (cost <= state.remaining) {
1424
+ state.remaining -= cost;
1425
+ return value;
1426
+ }
1427
+ const bounded = truncateMiddleWithTokenBudget(value, state.remaining);
1428
+ state.remaining = 0;
1429
+ return bounded;
1430
+ }
1431
+ if (!value || typeof value !== "object") return value;
1432
+ if (depth >= MODEL_TOOL_OUTPUT_MAX_DEPTH) return DEPTH_OMISSION_MARKER;
1433
+ if (state.seen.has(value)) return CYCLE_OMISSION_MARKER;
1434
+ state.seen.add(value);
1435
+ if (Array.isArray(value)) {
1436
+ const out2 = [];
1437
+ let processed2 = 0;
1438
+ let changed2 = false;
1439
+ for (let index = 0; index < value.length; index += 1) {
1440
+ const entry = value[index];
1441
+ if (processed2 >= MODEL_TOOL_OUTPUT_MAX_CONTAINER_ENTRIES || state.remainingEntries <= 0) {
1442
+ if (index === value.length - 1 && typeof entry === "string" && STRUCTURAL_ENTRIES_OMISSION_MARKER.test(entry)) {
1443
+ out2.push(entry);
1444
+ }
1445
+ break;
1446
+ }
1447
+ processed2 += 1;
1448
+ state.remainingEntries -= 1;
1449
+ const bounded = boundTextLeaves(entry, state, depth + 1, opaqueKind);
1450
+ out2.push(bounded);
1451
+ if (bounded !== entry) changed2 = true;
1452
+ }
1453
+ const omitted2 = value.length - out2.length;
1454
+ if (omitted2 > 0) {
1455
+ out2.push(structuredEntriesOmissionMarker(omitted2, "array"));
1456
+ changed2 = true;
1457
+ }
1458
+ state.seen.delete(value);
1459
+ return changed2 ? out2 : value;
1460
+ }
1461
+ const record = value;
1462
+ const recordOpaqueKind = nonTextProtocolKind(record.type) ?? opaqueKind;
1463
+ const entries = Object.entries(record);
1464
+ const out = {};
1465
+ let processed = 0;
1466
+ let omitted = 0;
1467
+ let changed = false;
1468
+ for (let index = 0; index < entries.length; index += 1) {
1469
+ const [key, entry] = entries[index];
1470
+ if (processed >= MODEL_TOOL_OUTPUT_MAX_CONTAINER_ENTRIES || state.remainingEntries <= 0) {
1471
+ if (index === entries.length - 1 && isGeneratedStructuralMarkerProperty(key, entry)) {
1472
+ out[key] = entry;
1473
+ break;
1474
+ }
1475
+ omitted += entries.length - index;
1476
+ break;
1477
+ }
1478
+ processed += 1;
1479
+ state.remainingEntries -= 1;
1480
+ if (Buffer.byteLength(key, "utf8") > MODEL_TOOL_OUTPUT_MAX_PROPERTY_KEY_BYTES) {
1481
+ omitted += 1;
1482
+ changed = true;
1483
+ continue;
1484
+ }
1485
+ const childOpaqueKind = opaqueKindForChild(recordOpaqueKind, key);
1486
+ if (typeof entry === "string" && childOpaqueKind) {
1487
+ const bounded2 = boundTextLeaves(entry, state, depth + 1, childOpaqueKind);
1488
+ out[key] = bounded2;
1489
+ if (bounded2 !== entry) changed = true;
1490
+ continue;
1491
+ }
1492
+ if (typeof entry === "string" && STRUCTURAL_STRING_KEYS.has(key)) {
1493
+ const bounded2 = boundStructuralString(entry, state);
1494
+ out[key] = bounded2;
1495
+ if (bounded2 !== entry) changed = true;
1496
+ continue;
1497
+ }
1498
+ const bounded = boundTextLeaves(entry, state, depth + 1, childOpaqueKind);
1499
+ out[key] = bounded;
1500
+ if (bounded !== entry) changed = true;
1501
+ }
1502
+ if (omitted > 0) {
1503
+ out[uniqueStructuralMarkerKey(out)] = structuredEntriesOmissionMarker(omitted, "object");
1504
+ changed = true;
1505
+ }
1506
+ state.seen.delete(value);
1507
+ return changed ? out : value;
1508
+ }
1509
+ function boundStructuralString(value, state) {
1510
+ if (isGeneratedModelOutputMarker(value)) {
1511
+ observeGeneratedMarkerBudget(value, state);
1512
+ return value;
1513
+ }
1514
+ if (state.remainingStructural === 0) return STRUCTURAL_STRING_OMISSION_MARKER;
1515
+ const cost = approximateTokenCount(value);
1516
+ const allowance = Math.min(
1517
+ MODEL_TOOL_OUTPUT_MAX_STRUCTURAL_STRING_TOKENS,
1518
+ state.remainingStructural
1519
+ );
1520
+ if (cost <= allowance) {
1521
+ state.remainingStructural -= cost;
1522
+ return value;
1523
+ }
1524
+ state.remainingStructural -= allowance;
1525
+ return truncateMiddleWithTokenBudget(value, allowance);
1526
+ }
1527
+ function boundOpaqueProtocolString(value, state, kind) {
1528
+ if (kind === "image" && value === MODEL_TOOL_OUTPUT_OVERSIZED_IMAGE_CARD_DATA_URL) {
1529
+ state.remainingOpaqueBytes = 0;
1530
+ return value;
1531
+ }
1532
+ const bytes = Buffer.byteLength(value, "utf8");
1533
+ if (bytes <= state.remainingOpaqueBytes) {
1534
+ state.remainingOpaqueBytes -= bytes;
1535
+ return value;
1536
+ }
1537
+ state.remainingOpaqueBytes = 0;
1538
+ if (kind === "image") {
1539
+ state.opaqueOmissions += 1;
1540
+ return MODEL_TOOL_OUTPUT_OVERSIZED_IMAGE_CARD_DATA_URL;
1541
+ }
1542
+ const marker = `[OpenGeni omitted ${kind} payload: ${bytes} bytes exceeded the bounded model-input allowance]`;
1543
+ state.opaqueOmissions += 1;
1544
+ state.lastOpaqueOmissionMarker = marker;
1545
+ return marker;
1546
+ }
1547
+ function nonTextProtocolKind(value) {
1548
+ if (value === "image" || value === "input_image" || value === "computer_screenshot") {
1549
+ return "image";
1550
+ }
1551
+ if (value === "file" || value === "input_file") return "file";
1552
+ if (value === "encrypted_content") return "encrypted";
1553
+ return null;
1554
+ }
1555
+ function opaqueKindForChild(kind, key) {
1556
+ if (!kind) return null;
1557
+ const opaqueKeys = kind === "image" ? ["image", "image_url", "imageUrl", "file_id", "fileId", "id", "data", "url", "source"] : kind === "file" ? [
1558
+ "file",
1559
+ "file_data",
1560
+ "fileData",
1561
+ "file_url",
1562
+ "fileUrl",
1563
+ "file_id",
1564
+ "fileId",
1565
+ "id",
1566
+ "data",
1567
+ "url",
1568
+ "content",
1569
+ "source"
1570
+ ] : ["encrypted_content", "content", "data"];
1571
+ return opaqueKeys.includes(key) ? kind : null;
1572
+ }
1573
+ function structuredEntriesOmissionMarker(count, container) {
1574
+ return `[OpenGeni omitted ${count} structured ${container === "array" ? "array items" : "object properties"}]`;
1575
+ }
1576
+ function typedProtocolTextMarker(text) {
1577
+ return { type: "input_text", text };
1578
+ }
1579
+ function typedStructuredArrayOmissionMarker(count) {
1580
+ return typedProtocolTextMarker(structuredEntriesOmissionMarker(count, "array"));
1581
+ }
1582
+ function isTypedStructuralArrayOmissionMarker(value) {
1583
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
1584
+ const record = value;
1585
+ return record.type === "input_text" && typeof record.text === "string" && STRUCTURAL_ENTRIES_OMISSION_MARKER.test(record.text) && record.text.includes("structured array items");
1586
+ }
1587
+ function isGeneratedModelOutputMarker(value) {
1588
+ 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));
1589
+ }
1590
+ function observeGeneratedMarkerBudget(value, state) {
1591
+ if (TEXT_FIELD_OMISSION_MARKER.test(value) || TEXT_ITEMS_OMISSION_MARKER.test(value)) {
1592
+ state.remaining = 0;
1593
+ }
1594
+ if (value === STRUCTURAL_STRING_OMISSION_MARKER) state.remainingStructural = 0;
1595
+ if (OPAQUE_PAYLOAD_OMISSION_MARKER.test(value)) state.remainingOpaqueBytes = 0;
1596
+ }
1597
+ function isGeneratedStructuralMarkerProperty(key, value) {
1598
+ return key.startsWith(STRUCTURAL_PROPERTIES_MARKER_KEY) && typeof value === "string" && STRUCTURAL_ENTRIES_OMISSION_MARKER.test(value);
1599
+ }
1600
+ function uniqueStructuralMarkerKey(record) {
1601
+ let key = STRUCTURAL_PROPERTIES_MARKER_KEY;
1602
+ let suffix = 1;
1603
+ while (Object.hasOwn(record, key)) {
1604
+ key = `${STRUCTURAL_PROPERTIES_MARKER_KEY}_${suffix}`;
1605
+ suffix += 1;
1606
+ }
1607
+ return key;
1608
+ }
1609
+ function isResponsesProtocolContentPrefix(output) {
1610
+ if (output.length === 0) return false;
1611
+ const retainedPrefixLength = Math.min(output.length, MODEL_TOOL_OUTPUT_MAX_CONTAINER_ENTRIES);
1612
+ for (let index = 0; index < retainedPrefixLength; index += 1) {
1613
+ const item = output[index];
1614
+ if (!item || typeof item !== "object" || Array.isArray(item)) return false;
1615
+ const record = item;
1616
+ if (record.type === "input_text" && typeof record.text === "string") continue;
1617
+ if (record.type === "input_image") continue;
1618
+ if (record.type === "input_file") continue;
1619
+ return false;
1620
+ }
1621
+ return true;
1622
+ }
1623
+ function isImageDataUrl(value) {
1624
+ return /^data:image\/[a-z0-9.+-]+;base64,/i.test(value);
1625
+ }
897
1626
  export {
898
1627
  CODEX_APPS_MCP_SERVER_ID,
899
1628
  CODEX_APPS_MCP_SERVER_NAME,
@@ -915,6 +1644,7 @@ export {
915
1644
  CODEX_MODEL_CONTEXT_WINDOW_TOKENS,
916
1645
  CODEX_MODEL_EFFECTIVE_CONTEXT_WINDOW_TOKENS,
917
1646
  CODEX_MODEL_ID_PREFIX,
1647
+ CODEX_MODEL_TOOL_OUTPUT_TRUNCATION_TOKENS,
918
1648
  CODEX_ORIGINATOR,
919
1649
  CODEX_PROVIDER_BASE_URL,
920
1650
  CODEX_PROVIDER_ID,
@@ -922,6 +1652,7 @@ export {
922
1652
  CODEX_REFRESH_WINDOW_MS,
923
1653
  CODEX_RESPONSES_BASE,
924
1654
  CODEX_TOKEN_URL,
1655
+ CODEX_TOOL_OUTPUT_SERIALIZATION_ALLOWANCE,
925
1656
  CODEX_TRANSPORT_ERROR_HEADER,
926
1657
  CODEX_USAGE_LIMIT_ERROR_TYPE,
927
1658
  CODEX_WEEKLY_WINDOW_SECONDS,
@@ -929,8 +1660,15 @@ export {
929
1660
  CodexDeviceError,
930
1661
  CodexRefreshTransient,
931
1662
  CodexReloginRequired,
1663
+ CodexStreamingTerminalError,
1664
+ DEFAULT_MODEL_TOOL_OUTPUT_TRUNCATION_TOKENS,
1665
+ MODEL_TOOL_OUTPUT_OPAQUE_PAYLOAD_MAX_BYTES,
1666
+ MODEL_TOOL_OUTPUT_OVERSIZED_IMAGE_CARD_DATA_URL,
932
1667
  ToolNameMapper,
933
1668
  accessTokenExpiry,
1669
+ approximateTokenCount,
1670
+ boundModelToolOutputItem,
1671
+ boundModelToolOutputItems,
934
1672
  buildCodexUsageWindowFromCache,
935
1673
  buildModelResolver,
936
1674
  classifyCodexUsageLimitError,
@@ -943,6 +1681,7 @@ export {
943
1681
  fetchCodexUsage,
944
1682
  isCodexBilledModel,
945
1683
  isCodexTransportError,
1684
+ modelToolOutputSerializationBudgetTokens,
946
1685
  normalizeCodexRequestBody,
947
1686
  normalizeCodexUsage,
948
1687
  parseCodexUsageHeaders,
@@ -952,6 +1691,7 @@ export {
952
1691
  remapToolCallRequestBody,
953
1692
  sanitizeMcpJsonBody,
954
1693
  sanitizeMcpSseBody,
955
- startDeviceCode
1694
+ startDeviceCode,
1695
+ truncateMiddleWithTokenBudget
956
1696
  };
957
1697
  //# sourceMappingURL=index.js.map