@opengeni/codex 0.2.15 → 0.2.16

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
@@ -914,15 +914,90 @@ function parseCodexUsageHeaders(headers) {
914
914
  checkedAt: new Date(nowMs)
915
915
  };
916
916
  }
917
- async function emitRequestEvent(audit, event) {
918
- await audit.ctx.onModelRequestEvent?.({
917
+ function classifyCodexSseTerminal(ev) {
918
+ if (ev.type === "response.failed") {
919
+ return {
920
+ phase: "failed",
921
+ rawError: ev.response?.error,
922
+ fallbackCode: "response_failed",
923
+ fallbackMessage: "The Codex response failed"
924
+ };
925
+ }
926
+ if (ev.type === "error" || ev.type === "response.error") {
927
+ return {
928
+ phase: "failed",
929
+ rawError: ev.error ?? ev.response?.error ?? ev,
930
+ fallbackCode: "response_error",
931
+ fallbackMessage: "The Codex response stream reported an error"
932
+ };
933
+ }
934
+ if (ev.type === "response.incomplete") {
935
+ const details = ev.response?.incomplete_details;
936
+ const reason = details && typeof details === "object" ? details.reason : void 0;
937
+ return {
938
+ phase: "failed",
939
+ rawError: {
940
+ code: "response_incomplete",
941
+ message: typeof reason === "string" && reason.length > 0 ? `The Codex response was incomplete (${reason})` : "The Codex response was incomplete"
942
+ },
943
+ fallbackCode: "response_incomplete",
944
+ fallbackMessage: "The Codex response was incomplete"
945
+ };
946
+ }
947
+ if (ev.type !== "response.completed" && ev.type !== "response.done") {
948
+ return null;
949
+ }
950
+ if (!ev.response) {
951
+ return null;
952
+ }
953
+ const responseStatus = ev.response.status;
954
+ if (responseStatus !== void 0 && responseStatus !== "completed" || ev.response.error !== null && ev.response.error !== void 0) {
955
+ const incomplete = responseStatus === "incomplete";
956
+ return {
957
+ phase: "failed",
958
+ rawError: ev.response.error,
959
+ fallbackCode: incomplete ? "response_incomplete" : "response_failed",
960
+ fallbackMessage: incomplete ? "The Codex response was incomplete" : "The Codex response failed"
961
+ };
962
+ }
963
+ return { phase: "completed" };
964
+ }
965
+ function markSemanticTerminal(state, phase) {
966
+ if (state.phase === null) {
967
+ state.phase = phase;
968
+ }
969
+ }
970
+ function terminalOutcomeForPhase(phase) {
971
+ if (phase === "completed" || phase === "failed" || phase === "timed_out") {
972
+ return phase;
973
+ }
974
+ return null;
975
+ }
976
+ function requestEventFor(audit, event) {
977
+ return {
919
978
  requestId: audit.requestId,
920
979
  transportAttempt: audit.transportAttempt,
921
980
  ...audit.model ? { model: audit.model } : {},
922
- durationMs: Math.max(0, Date.now() - audit.attemptStartedAt),
981
+ durationMs: Math.max(0, performance.now() - audit.attemptStartedAtMonotonic),
923
982
  timeoutPolicy: audit.policy,
924
983
  ...event
925
- });
984
+ };
985
+ }
986
+ async function emitRequestEvent(audit, event) {
987
+ const terminalOutcome = terminalOutcomeForPhase(event.phase);
988
+ if (terminalOutcome !== null) {
989
+ if (audit.terminalOutcome !== null) {
990
+ return false;
991
+ }
992
+ audit.terminalOutcome = terminalOutcome;
993
+ }
994
+ const observed = requestEventFor(audit, event);
995
+ try {
996
+ audit.ctx.onModelRequestDiagnostic?.(observed);
997
+ } catch {
998
+ }
999
+ await audit.ctx.onModelRequestEvent?.(observed);
1000
+ return true;
926
1001
  }
927
1002
  function providerRequestId(headers) {
928
1003
  return headers.get("x-request-id") ?? headers.get("request-id") ?? void 0;
@@ -963,11 +1038,12 @@ async function fetchBeforeHeaders(base, input, init, audit) {
963
1038
  externalSignal?.removeEventListener("abort", forwardAbort);
964
1039
  }
965
1040
  }
966
- async function observedResponse(res, audit, externalSignal) {
1041
+ async function observedResponse(res, audit, externalSignal, semanticTerminal) {
967
1042
  const requestId = providerRequestId(res.headers);
968
1043
  if (!res.body) {
1044
+ if (semanticTerminal) markSemanticTerminal(semanticTerminal, "failed");
969
1045
  await emitRequestEvent(audit, {
970
- phase: res.ok ? "completed" : "failed",
1046
+ phase: semanticTerminal?.phase ?? (res.ok ? "completed" : "failed"),
971
1047
  responseObserved: true,
972
1048
  status: res.status,
973
1049
  ...requestId ? { providerRequestId: requestId } : {}
@@ -992,17 +1068,19 @@ async function observedResponse(res, audit, externalSignal) {
992
1068
  if (terminal) return;
993
1069
  terminal = true;
994
1070
  clearTimers();
1071
+ const semanticPhase = semanticTerminal?.phase;
1072
+ const phase = semanticPhase ?? "timed_out";
995
1073
  const error = new CodexResponseTimeoutError(klass, audit.requestId, true);
996
1074
  void reader.cancel(error).catch(() => void 0);
997
1075
  void emitRequestEvent(audit, {
998
- phase: "timed_out",
1076
+ phase,
999
1077
  responseObserved: true,
1000
- timeoutClass: klass,
1078
+ ...phase === "timed_out" ? { timeoutClass: klass } : {},
1001
1079
  status: res.status,
1002
1080
  ...requestId ? { providerRequestId: requestId } : {}
1003
1081
  }).then(
1004
- () => controller.error(error),
1005
- () => controller.error(error)
1082
+ () => phase === "completed" ? controller.close() : controller.error(error),
1083
+ () => phase === "completed" ? controller.close() : controller.error(error)
1006
1084
  );
1007
1085
  };
1008
1086
  armIdle = () => {
@@ -1022,13 +1100,13 @@ async function observedResponse(res, audit, externalSignal) {
1022
1100
  const reason = externalSignal?.reason ?? new DOMException("Aborted", "AbortError");
1023
1101
  void reader.cancel(reason).catch(() => void 0);
1024
1102
  void emitRequestEvent(audit, {
1025
- phase: "failed",
1103
+ phase: semanticTerminal?.phase ?? "failed",
1026
1104
  responseObserved: true,
1027
1105
  status: res.status,
1028
1106
  ...requestId ? { providerRequestId: requestId } : {}
1029
1107
  }).then(
1030
- () => controller.error(reason),
1031
- () => controller.error(reason)
1108
+ () => semanticTerminal?.phase === "completed" ? controller.close() : controller.error(reason),
1109
+ () => semanticTerminal?.phase === "completed" ? controller.close() : controller.error(reason)
1032
1110
  );
1033
1111
  };
1034
1112
  if (externalSignal?.aborted) {
@@ -1047,12 +1125,19 @@ async function observedResponse(res, audit, externalSignal) {
1047
1125
  if (chunk.done) {
1048
1126
  terminal = true;
1049
1127
  clearTimers();
1050
- await emitRequestEvent(audit, {
1051
- phase: res.ok ? "completed" : "failed",
1052
- responseObserved: true,
1053
- status: res.status,
1054
- ...requestId ? { providerRequestId: requestId } : {}
1055
- });
1128
+ if (semanticTerminal && semanticTerminal.phase === null) {
1129
+ if (!semanticTerminal.deferTransportTerminal) {
1130
+ markSemanticTerminal(semanticTerminal, "failed");
1131
+ }
1132
+ }
1133
+ if (!semanticTerminal?.deferTransportTerminal || semanticTerminal.phase !== null) {
1134
+ await emitRequestEvent(audit, {
1135
+ phase: semanticTerminal?.phase ?? (res.ok ? "completed" : "failed"),
1136
+ responseObserved: true,
1137
+ status: res.status,
1138
+ ...requestId ? { providerRequestId: requestId } : {}
1139
+ });
1140
+ }
1056
1141
  controller.close();
1057
1142
  return;
1058
1143
  }
@@ -1075,21 +1160,32 @@ async function observedResponse(res, audit, externalSignal) {
1075
1160
  if (terminal) return;
1076
1161
  terminal = true;
1077
1162
  clearTimers();
1163
+ const semanticPhase = semanticTerminal?.phase;
1164
+ if (semanticTerminal && semanticPhase === null) {
1165
+ markSemanticTerminal(semanticTerminal, "failed");
1166
+ }
1078
1167
  await emitRequestEvent(audit, {
1079
- phase: "failed",
1168
+ phase: semanticPhase ?? "failed",
1080
1169
  responseObserved: true,
1081
1170
  status: res.status,
1082
1171
  ...requestId ? { providerRequestId: requestId } : {}
1083
1172
  });
1084
- controller.error(error);
1173
+ if (semanticPhase === "completed") {
1174
+ controller.close();
1175
+ } else {
1176
+ controller.error(error);
1177
+ }
1085
1178
  }
1086
1179
  },
1087
1180
  async cancel(reason) {
1088
1181
  if (!terminal) {
1089
1182
  terminal = true;
1090
1183
  clearTimers();
1184
+ if (semanticTerminal && semanticTerminal.phase === null) {
1185
+ markSemanticTerminal(semanticTerminal, "failed");
1186
+ }
1091
1187
  await emitRequestEvent(audit, {
1092
- phase: "failed",
1188
+ phase: semanticTerminal?.phase ?? "failed",
1093
1189
  responseObserved: true,
1094
1190
  status: res.status,
1095
1191
  ...requestId ? { providerRequestId: requestId } : {}
@@ -1219,13 +1315,18 @@ function codexSubscriptionFetch(base = globalThis.fetch) {
1219
1315
  transportAttempt,
1220
1316
  ...model ? { model } : {},
1221
1317
  logicalStartedAt,
1222
- attemptStartedAt: Date.now(),
1223
- policy
1318
+ attemptStartedAtMonotonic: performance.now(),
1319
+ policy,
1320
+ terminalOutcome: null
1224
1321
  };
1225
1322
  await emitRequestEvent(audit, {
1226
1323
  phase: "started",
1227
1324
  responseObserved: false
1228
1325
  });
1326
+ const semanticTerminal = {
1327
+ phase: null,
1328
+ deferTransportTerminal: !callerWantsStream
1329
+ };
1229
1330
  try {
1230
1331
  res = await fetchBeforeHeaders(base, rewritten, nextInit, audit);
1231
1332
  const upstreamRequestId = providerRequestId(res.headers);
@@ -1235,8 +1336,7 @@ function codexSubscriptionFetch(base = globalThis.fetch) {
1235
1336
  status: res.status,
1236
1337
  ...upstreamRequestId ? { providerRequestId: upstreamRequestId } : {}
1237
1338
  });
1238
- const observed = await observedResponse(res, audit, nextInit.signal);
1239
- res = observed;
1339
+ res = await observedResponse(res, audit, nextInit.signal, semanticTerminal);
1240
1340
  } catch (error) {
1241
1341
  if (nextInit.signal?.aborted) {
1242
1342
  await emitRequestEvent(audit, {
@@ -1273,9 +1373,25 @@ function codexSubscriptionFetch(base = globalThis.fetch) {
1273
1373
  });
1274
1374
  }
1275
1375
  if (!res.ok) {
1276
- return await bufferCodexErrorResponse(res);
1376
+ const buffered = await bufferCodexErrorResponse(res);
1377
+ const upstreamRequestId = providerRequestId(res.headers);
1378
+ markSemanticTerminal(semanticTerminal, "failed");
1379
+ await emitRequestEvent(audit, {
1380
+ phase: "failed",
1381
+ responseObserved: true,
1382
+ status: res.status,
1383
+ ...upstreamRequestId ? { providerRequestId: upstreamRequestId } : {}
1384
+ }).catch(() => void 0);
1385
+ return buffered;
1386
+ }
1387
+ if (callerWantsStream) {
1388
+ res = validateCodexStream(res, (phase) => {
1389
+ markSemanticTerminal(semanticTerminal, phase);
1390
+ });
1391
+ } else {
1392
+ res = await sseToJsonResponse(res, audit, semanticTerminal);
1277
1393
  }
1278
- return callerWantsStream ? validateCodexStream(res) : await sseToJsonResponse(res);
1394
+ return res;
1279
1395
  };
1280
1396
  try {
1281
1397
  let res = await attempt(await ctx.getToken(), 0);
@@ -1382,7 +1498,8 @@ async function readBoundedResponseText(response, maxBytes) {
1382
1498
  }
1383
1499
  return { text: parts.join(""), truncated };
1384
1500
  }
1385
- async function sseToJsonResponse(res) {
1501
+ async function sseToJsonResponse(res, audit, semanticTerminal) {
1502
+ const upstreamRequestId = providerRequestId(res.headers);
1386
1503
  const text = await res.text();
1387
1504
  let final = null;
1388
1505
  let terminalError = null;
@@ -1395,57 +1512,45 @@ async function sseToJsonResponse(res) {
1395
1512
  const ev = JSON.parse(data);
1396
1513
  if (ev.type === "response.output_item.done" && ev.item !== void 0) {
1397
1514
  items.push(ev.item);
1398
- } else if (ev.type === "response.failed") {
1399
- terminalError = codexSseFailureResponse(
1400
- res,
1401
- ev.response?.error,
1402
- "response_failed",
1403
- "The Codex response failed",
1404
- {
1405
- eventType: ev.type,
1406
- responseId: ev.response?.id,
1407
- responseStatus: ev.response?.status
1408
- }
1409
- );
1410
- } else if (ev.type === "error" || ev.type === "response.error") {
1411
- terminalError = codexSseFailureResponse(
1412
- res,
1413
- ev.error ?? ev.response?.error ?? ev,
1414
- "response_error",
1415
- "The Codex response stream reported an error",
1416
- {
1417
- eventType: ev.type,
1418
- responseId: ev.response?.id,
1419
- responseStatus: ev.response?.status
1420
- }
1421
- );
1422
- } else if (ev.type === "response.incomplete") {
1423
- const details = ev.response?.incomplete_details;
1424
- const reason = details && typeof details === "object" ? details.reason : void 0;
1425
- terminalError = codexSseFailureResponse(
1426
- res,
1427
- {
1428
- code: "response_incomplete",
1429
- message: typeof reason === "string" && reason.length > 0 ? `The Codex response was incomplete (${reason})` : "The Codex response was incomplete"
1430
- },
1431
- "response_incomplete",
1432
- "The Codex response was incomplete",
1433
- {
1434
- eventType: ev.type,
1435
- responseId: ev.response?.id,
1436
- responseStatus: ev.response?.status
1437
- }
1438
- );
1439
- } else if (ev.type === "response.completed" || ev.type === "response.done") {
1440
- final = ev.response ?? null;
1515
+ } else {
1516
+ const terminal = classifyCodexSseTerminal(ev);
1517
+ if (terminal?.phase === "failed") {
1518
+ terminalError = codexSseFailureResponse(
1519
+ res,
1520
+ terminal.rawError,
1521
+ terminal.fallbackCode,
1522
+ terminal.fallbackMessage,
1523
+ {
1524
+ eventType: ev.type,
1525
+ responseId: ev.response?.id,
1526
+ responseStatus: ev.response?.status
1527
+ }
1528
+ );
1529
+ } else if (terminal?.phase === "completed") {
1530
+ final = ev.response ?? null;
1531
+ }
1441
1532
  }
1442
1533
  } catch {
1443
1534
  }
1444
1535
  }
1445
1536
  if (terminalError) {
1537
+ markSemanticTerminal(semanticTerminal, "failed");
1538
+ await emitRequestEvent(audit, {
1539
+ phase: "failed",
1540
+ responseObserved: true,
1541
+ status: res.status,
1542
+ ...upstreamRequestId ? { providerRequestId: upstreamRequestId } : {}
1543
+ });
1446
1544
  return terminalError;
1447
1545
  }
1448
1546
  if (!final) {
1547
+ markSemanticTerminal(semanticTerminal, "failed");
1548
+ await emitRequestEvent(audit, {
1549
+ phase: "failed",
1550
+ responseObserved: true,
1551
+ status: res.status,
1552
+ ...upstreamRequestId ? { providerRequestId: upstreamRequestId } : {}
1553
+ });
1449
1554
  return codexSseFailureResponse(
1450
1555
  res,
1451
1556
  null,
@@ -1461,6 +1566,13 @@ async function sseToJsonResponse(res) {
1461
1566
  `[codex-debug] sse->json items=${items.length} outputLen=${Array.isArray(final?.output) ? final.output.length : "?"}`
1462
1567
  );
1463
1568
  }
1569
+ markSemanticTerminal(semanticTerminal, "completed");
1570
+ await emitRequestEvent(audit, {
1571
+ phase: "completed",
1572
+ responseObserved: true,
1573
+ status: res.status,
1574
+ ...upstreamRequestId ? { providerRequestId: upstreamRequestId } : {}
1575
+ });
1464
1576
  const headers = new Headers(res.headers);
1465
1577
  headers.set("content-type", "application/json");
1466
1578
  headers.delete("content-length");
@@ -1613,8 +1725,9 @@ function codexSseFailureError(source, rawError, fallbackCode, publicMessage, met
1613
1725
  codexSseFailureProjection(source, rawError, fallbackCode, publicMessage, metadata)
1614
1726
  );
1615
1727
  }
1616
- function validateCodexStream(res) {
1728
+ function validateCodexStream(res, onSemanticTerminal) {
1617
1729
  if (!res.body) {
1730
+ onSemanticTerminal?.("failed");
1618
1731
  const error = codexSseFailureError(
1619
1732
  res,
1620
1733
  null,
@@ -1644,7 +1757,7 @@ function validateCodexStream(res) {
1644
1757
  const block = buffer.slice(0, boundary.start);
1645
1758
  const separator = buffer.slice(boundary.start, boundary.end);
1646
1759
  buffer = buffer.slice(boundary.end);
1647
- successfulTerminalSeen ||= inspectCodexSseBlock(block, res);
1760
+ successfulTerminalSeen ||= inspectCodexSseBlock(block, res, onSemanticTerminal);
1648
1761
  controller.enqueue(encoder.encode(`${block}${separator}`));
1649
1762
  boundary = findSseBlockBoundary(buffer, final);
1650
1763
  }
@@ -1658,7 +1771,7 @@ function validateCodexStream(res) {
1658
1771
  buffer += decoder.decode();
1659
1772
  emitCompleteBlocks(controller, true);
1660
1773
  if (buffer.length > 0) {
1661
- successfulTerminalSeen ||= inspectCodexSseBlock(buffer, res);
1774
+ successfulTerminalSeen ||= inspectCodexSseBlock(buffer, res, onSemanticTerminal);
1662
1775
  controller.enqueue(encoder.encode(buffer));
1663
1776
  buffer = "";
1664
1777
  }
@@ -1708,7 +1821,7 @@ var CODEX_TERMINAL_TYPE_HINTS = [
1708
1821
  '"response.error"',
1709
1822
  '"error"'
1710
1823
  ];
1711
- function inspectCodexSseBlock(block, source) {
1824
+ function inspectCodexSseBlock(block, source, onSemanticTerminal) {
1712
1825
  const lines = block.split(/\r\n|\r|\n/);
1713
1826
  const dataStr = lines.filter((l) => l.startsWith("data:")).map((l) => l.slice(5).trim()).join("\n");
1714
1827
  if (!dataStr || dataStr === "[DONE]") {
@@ -1723,43 +1836,14 @@ function inspectCodexSseBlock(block, source) {
1723
1836
  } catch {
1724
1837
  return false;
1725
1838
  }
1726
- if (ev.type === "response.failed") {
1727
- throw codexSseFailureError(
1728
- source,
1729
- ev.response?.error,
1730
- "response_failed",
1731
- "The Codex response failed",
1732
- {
1733
- eventType: ev.type,
1734
- responseId: ev.response?.id,
1735
- responseStatus: ev.response?.status
1736
- }
1737
- );
1738
- }
1739
- if (ev.type === "error" || ev.type === "response.error") {
1740
- throw codexSseFailureError(
1741
- source,
1742
- ev.error ?? ev.response?.error ?? ev,
1743
- "response_error",
1744
- "The Codex response stream reported an error",
1745
- {
1746
- eventType: ev.type,
1747
- responseId: ev.response?.id,
1748
- responseStatus: ev.response?.status
1749
- }
1750
- );
1751
- }
1752
- if (ev.type === "response.incomplete") {
1753
- const details = ev.response?.incomplete_details;
1754
- const reason = details && typeof details === "object" ? details.reason : void 0;
1839
+ const terminal = classifyCodexSseTerminal(ev);
1840
+ if (terminal?.phase === "failed") {
1841
+ onSemanticTerminal?.("failed");
1755
1842
  throw codexSseFailureError(
1756
1843
  source,
1757
- {
1758
- code: "response_incomplete",
1759
- message: typeof reason === "string" && reason.length > 0 ? `The Codex response was incomplete (${reason})` : "The Codex response was incomplete"
1760
- },
1761
- "response_incomplete",
1762
- "The Codex response was incomplete",
1844
+ terminal.rawError,
1845
+ terminal.fallbackCode,
1846
+ terminal.fallbackMessage,
1763
1847
  {
1764
1848
  eventType: ev.type,
1765
1849
  responseId: ev.response?.id,
@@ -1767,20 +1851,8 @@ function inspectCodexSseBlock(block, source) {
1767
1851
  }
1768
1852
  );
1769
1853
  }
1770
- if ((ev.type === "response.completed" || ev.type === "response.done") && ev.response) {
1771
- if (ev.response.status !== void 0 && ev.response.status !== "completed" || ev.response.error !== null && ev.response.error !== void 0) {
1772
- throw codexSseFailureError(
1773
- source,
1774
- ev.response.error,
1775
- ev.response.status === "incomplete" ? "response_incomplete" : "response_failed",
1776
- ev.response.status === "incomplete" ? "The Codex response was incomplete" : "The Codex response failed",
1777
- {
1778
- eventType: ev.type,
1779
- responseId: ev.response.id,
1780
- responseStatus: ev.response.status
1781
- }
1782
- );
1783
- }
1854
+ if (terminal?.phase === "completed") {
1855
+ onSemanticTerminal?.("completed");
1784
1856
  return true;
1785
1857
  }
1786
1858
  return false;