@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 +197 -125
- package/dist/index.js.map +1 -1
- package/dist/request-context.d.ts +6 -0
- package/package.json +1 -1
- package/src/fetch.ts +270 -160
- package/src/request-context.ts +6 -0
package/dist/index.js
CHANGED
|
@@ -914,15 +914,90 @@ function parseCodexUsageHeaders(headers) {
|
|
|
914
914
|
checkedAt: new Date(nowMs)
|
|
915
915
|
};
|
|
916
916
|
}
|
|
917
|
-
|
|
918
|
-
|
|
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,
|
|
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
|
|
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
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
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
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
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
|
-
|
|
1759
|
-
|
|
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 (
|
|
1771
|
-
|
|
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;
|