@openclaw/ai 2026.8.1-beta.1 → 2026.8.1-beta.3
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/{anthropic-CE-7SkF6.mjs → anthropic-B8KwTtlb.mjs} +62 -37
- package/dist/{anthropic-SrGtwsJu.d.mts → anthropic-BECQCNdF.d.mts} +0 -2
- package/dist/{src-QkygScBs.mjs → anthropic-BQXQudmA.mjs} +0 -2
- package/dist/{anthropic-usage-Ma4iX6uG.mjs → anthropic-compaction-replay-4Zx7-aCr.mjs} +225 -103
- package/dist/anthropic-payload-policy-CSx7MoKH.d.mts +50 -0
- package/dist/{api-registry-EpJoVwM1.d.mts → api-registry-DFxSnFqG.d.mts} +1 -1
- package/dist/{azure-openai-responses-Cc_kasye.mjs → azure-openai-responses-Aa4mVcYG.mjs} +23 -29
- package/dist/diagnostics.d.mts +24 -1
- package/dist/diagnostics.mjs +2 -1
- package/dist/event-stream-BVVgDSdq.d.mts +1 -0
- package/dist/{event-stream-DRmDMRHH.d.mts → event-stream-D91-ohD_.d.mts} +3 -1
- package/dist/{event-stream-CEV9t6da.mjs → event-stream-uSMZJ3FA.mjs} +16 -3
- package/dist/event-stream.d.mts +1 -1
- package/dist/event-stream.mjs +1 -1
- package/dist/{google-shared-Cq2UKx1l.mjs → google-shared-M1dl64nz.mjs} +17 -19
- package/dist/google-thinking-level-C-V3tecN.mjs +9 -0
- package/dist/{google-vertex-CusxWzvE.mjs → google-vertex-DCJHM_a5.mjs} +5 -4
- package/dist/{google-CGQu21aw.mjs → google-yDRnipeq.mjs} +4 -4
- package/dist/host-DF_yxOsA.mjs +477 -0
- package/dist/{host-Dn4_SZI2.d.mts → host-DJq_FGcz.d.mts} +13 -8
- package/dist/index.d.mts +7 -7
- package/dist/index.mjs +7 -5
- package/dist/internal/anthropic.d.mts +21 -7
- package/dist/internal/anthropic.mjs +5 -5
- package/dist/internal/openai-responses-payload-policy.d.mts +3 -0
- package/dist/internal/openai-responses-payload-policy.mjs +3 -0
- package/dist/internal/openai.d.mts +6 -6
- package/dist/internal/openai.mjs +9 -7
- package/dist/internal/runtime.d.mts +19 -5
- package/dist/internal/runtime.mjs +85 -72
- package/dist/internal/shared.d.mts +17 -8
- package/dist/internal/shared.mjs +4 -5
- package/dist/{json-parse-BvXNt1-7.mjs → json-parse-CDnesDM_.mjs} +4 -6
- package/dist/{mistral-Dx6VzNjf.mjs → mistral-D6hRXI7A.mjs} +67 -72
- package/dist/{number-coercion-1Miyb5MO.mjs → number-coercion-H9qHik3g.mjs} +7 -2
- package/dist/openai-chatgpt-jwt-KWcgd0d_.mjs +19 -0
- package/dist/{openai-chatgpt-responses-SC9m0FSf.mjs → openai-chatgpt-responses-C339VIfT.mjs} +235 -146
- package/dist/{openai-completions-BaIpl93j.mjs → openai-completions-D88orSJ9.mjs} +88 -67
- package/dist/openai-completions-compat-B0KTleXp.d.mts +43 -0
- package/dist/{openai-responses-Bdx3V_Yu.mjs → openai-responses-BXEcr-Tp.mjs} +17 -24
- package/dist/openai-responses-contracts-CD75pQ0m.d.mts +68 -0
- package/dist/openai-responses-contracts-DvILoqBk.mjs +247 -0
- package/dist/openai-responses-payload-policy-BDo8CQsx.mjs +208 -0
- package/dist/openai-responses-payload-policy-CNGFT9zr.d.mts +41 -0
- package/dist/{openai-responses-prompt-observer-internal-DDZPxRfr.mjs → openai-responses-prompt-observer-internal-BG-1AsBI.mjs} +2 -3
- package/dist/{openai-responses-stream-internal-Bl8YyVtF.mjs → openai-responses-shared-Cvt5MgEm.mjs} +1287 -1039
- package/dist/{openai-reasoning-compat-DKebnIBL.mjs → openai-stop-reason-9OONKyAm.mjs} +222 -180
- package/dist/{openai-transport-shared-Cipt7egQ.mjs → openai-tool-projection-CHGLt03m.mjs} +239 -128
- package/dist/provider-error-C8mBRJDl.mjs +424 -0
- package/dist/provider-error-CzNw4BWX.d.mts +12 -0
- package/dist/provider-options-AvldWZt8.mjs +21 -0
- package/dist/{provider-options-C5kYML7i.d.mts → provider-options-Cc5ZQ6Aa.d.mts} +19 -3
- package/dist/provider-transcript-transform--gtf0ZbR.mjs +32 -0
- package/dist/provider-types.d.mts +31 -0
- package/dist/provider-types.mjs +8 -0
- package/dist/providers.d.mts +1 -1
- package/dist/providers.mjs +17 -19
- package/dist/{reasoning-tag-text-partitioner-CGDyLWUR.mjs → reasoning-tag-text-partitioner-5ygO2rZc.mjs} +17 -8
- package/dist/record-coerce-DdXsgUd_.mjs +23 -0
- package/dist/{model-utils-Dau5dlgm.mjs → sanitize-unicode-BP7HLLZn.mjs} +28 -2
- package/dist/session-resources-CkR4WWy1.mjs +21 -0
- package/dist/simple-options-oqsXB6U3.mjs +450 -0
- package/dist/src-D2H6yKkH.mjs +2 -0
- package/dist/{stream-first-event-timeout-BIBomOGq.mjs → stream-first-event-timeout-MK28puvq.mjs} +2 -2
- package/dist/string-coerce-fsri9iCu.mjs +34 -0
- package/dist/{tool-schema-json-projection-B1b-XCn5.mjs → tool-schema-json-projection-FEr-jOoZ.mjs} +20 -13
- package/dist/transport-utils-Bv0FHkd0.mjs +138 -0
- package/dist/transports.d.mts +199 -209
- package/dist/transports.mjs +1842 -1364
- package/dist/types-BDdaOVi2.mjs +6 -0
- package/dist/{types-CH7ReIcU.d.mts → types-DTAP49HF.d.mts} +35 -2
- package/dist/types.d.mts +5 -5
- package/dist/types.mjs +6 -4
- package/dist/utf16-slice-CvGodqok.mjs +29 -0
- package/dist/{validation-DAa_yFOM.mjs → validation-B61OhAio.mjs} +6 -6
- package/dist/{validation-CcPcuEbR.d.mts → validation-DYNNrU9u.d.mts} +1 -1
- package/dist/validation.d.mts +1 -1
- package/dist/validation.mjs +1 -1
- package/package.json +15 -1
- package/dist/host-Bl7Kgddo.mjs +0 -407
- package/dist/openai-chatgpt-jwt-DhAAzLkj.mjs +0 -39
- package/dist/openai-responses-contracts-BBKBfAqR.d.mts +0 -116
- package/dist/openai-responses-shared-CCyMvg7M.mjs +0 -403
- package/dist/provider-error-DI0Ts28U.mjs +0 -47
- package/dist/sanitize-unicode-DT5o51ur.mjs +0 -26
- package/dist/tool-result-text-Dvkp2Dus.mjs +0 -274
- package/dist/transform-messages-DfjpNXNQ.mjs +0 -2
- package/dist/transport-stream-shared-CPNv7A3r.mjs +0 -297
package/dist/{openai-chatgpt-responses-SC9m0FSf.mjs → openai-chatgpt-responses-C339VIfT.mjs}
RENAMED
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
import { n as getEnvApiKey } from "./env-api-keys-DrgeBuva.mjs";
|
|
2
2
|
import { i as formatThrownValue, n as createAssistantMessageDiagnostic, t as appendAssistantMessageDiagnostic } from "./diagnostics-COpOtRwq.mjs";
|
|
3
|
-
import { t as AssistantMessageEventStream } from "./event-stream-
|
|
4
|
-
import { n as getAiTransportHost, r as resolveAiTransportHeaderSentinels } from "./host-
|
|
3
|
+
import { t as AssistantMessageEventStream } from "./event-stream-uSMZJ3FA.mjs";
|
|
4
|
+
import { n as getAiTransportHost, r as resolveAiTransportHeaderSentinels } from "./host-DF_yxOsA.mjs";
|
|
5
|
+
import { n as projectProviderError } from "./provider-error-C8mBRJDl.mjs";
|
|
6
|
+
import { n as toErrorObject, t as createResponsesPromptEgressObserver } from "./openai-responses-prompt-observer-internal-BG-1AsBI.mjs";
|
|
7
|
+
import { c as resolveTimerTimeoutMs, i as clampTimerTimeoutMs } from "./number-coercion-H9qHik3g.mjs";
|
|
8
|
+
import { S as supportsOpenAITemperature, m as responsesPromptObserver } from "./openai-responses-contracts-DvILoqBk.mjs";
|
|
5
9
|
import { n as clampOpenAIPromptCacheKey } from "./openai-prompt-cache-mZTCdRPo.mjs";
|
|
6
|
-
import {
|
|
7
|
-
import { n as toErrorObject, t as createResponsesPromptEgressObserver } from "./openai-responses-prompt-observer-internal-DDZPxRfr.mjs";
|
|
8
|
-
import { B as responsesPromptObserver, n as processResponsesStream, pt as supportsOpenAITemperature, t as ResponsesStreamFailure } from "./openai-responses-stream-internal-Bl8YyVtF.mjs";
|
|
9
|
-
import { n as clampTimerTimeoutMs, o as resolveTimerTimeoutMs } from "./number-coercion-1Miyb5MO.mjs";
|
|
10
|
-
import { parseRetryAfterHttpDateMs } from "./internal/retry-after.mjs";
|
|
11
|
-
import { d as transportAbortError, f as MALFORMED_STREAMING_FRAGMENT_ERROR_MESSAGE } from "./transport-stream-shared-CPNv7A3r.mjs";
|
|
12
|
-
import { i as getFirstStreamEventTimeoutMs, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-BIBomOGq.mjs";
|
|
10
|
+
import { C as withProviderResponseHook, _ as notifyProviderStreamOpened, j as stripSystemPromptCacheBoundary, n as buildBaseOptions, x as transportAbortError } from "./simple-options-oqsXB6U3.mjs";
|
|
13
11
|
import { t as headersToRecord } from "./headers-B_e4-1J0.mjs";
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
12
|
+
import { parseRetryAfterHttpDateMs } from "./internal/retry-after.mjs";
|
|
13
|
+
import { t as MALFORMED_STREAMING_FRAGMENT_ERROR_MESSAGE } from "./transport-utils-Bv0FHkd0.mjs";
|
|
14
|
+
import { F as commitResponsesEncryptedContentAttempt, G as suppressOpenAIResponsesCompaction, L as isInvalidEncryptedContentError, U as buildOpenAIResponsesReasoningReplayMetadata, a as resolveResponsesReasoningEffort, c as processResponsesStream, i as createResponsesAssistantOutput, n as applyResponsesServiceTierPricing, p as ResponsesStreamFailure, r as convertResponsesMessages, s as convertResponsesToolPayload, z as resolveNextResponsesEncryptedContentAttempt } from "./openai-responses-shared-Cvt5MgEm.mjs";
|
|
15
|
+
import { o as createOpenAIProviderAcceptanceHook, s as createOpenAIResponseHook } from "./openai-tool-projection-CHGLt03m.mjs";
|
|
16
|
+
import { a as withFirstStreamEventTimeout, i as getFirstStreamEventTimeoutMs, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-MK28puvq.mjs";
|
|
17
|
+
import { n as registerSessionResourceCleanup } from "./session-resources-CkR4WWy1.mjs";
|
|
18
|
+
import "./diagnostics.mjs";
|
|
19
|
+
import { n as resolveOpenAICodexAccountId } from "./openai-chatgpt-jwt-KWcgd0d_.mjs";
|
|
16
20
|
import { t as createSseByteGuard } from "./streaming-byte-guard-BrbkbwUu.mjs";
|
|
17
21
|
import { t as inspectTlsCertificateError } from "./tls-certificate-errors-DXSpluKI.mjs";
|
|
18
22
|
//#region packages/ai/src/internal/retry-sleep.ts
|
|
@@ -35,6 +39,63 @@ function sleepWithAbort(ms, signal) {
|
|
|
35
39
|
});
|
|
36
40
|
}
|
|
37
41
|
//#endregion
|
|
42
|
+
//#region packages/ai/src/providers/openai-chatgpt-responses-protocol.ts
|
|
43
|
+
const OPENAI_CHATGPT_RESPONSES_SUCCESS_BODY_MAX_BYTES = 16 * 1024 * 1024;
|
|
44
|
+
var CodexProtocolError = class extends Error {
|
|
45
|
+
constructor(message, options) {
|
|
46
|
+
super(message);
|
|
47
|
+
this.name = "CodexProtocolError";
|
|
48
|
+
this.payload = options?.payload;
|
|
49
|
+
this.cause = options?.cause;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
async function* parseOpenAIChatGptResponsesSse(response) {
|
|
53
|
+
if (!response.body) return;
|
|
54
|
+
const reader = response.body.getReader();
|
|
55
|
+
const guard = createSseByteGuard(reader, {
|
|
56
|
+
maxBytes: OPENAI_CHATGPT_RESPONSES_SUCCESS_BODY_MAX_BYTES,
|
|
57
|
+
onOverflow: ({ size, maxBytes }) => /* @__PURE__ */ new Error(`OpenAI ChatGPT Responses success body exceeded ${maxBytes} bytes (received ${size})`)
|
|
58
|
+
});
|
|
59
|
+
const decoder = new TextDecoder();
|
|
60
|
+
let buffer = "";
|
|
61
|
+
try {
|
|
62
|
+
while (true) {
|
|
63
|
+
const { done, value } = await guard.read();
|
|
64
|
+
if (value) buffer += decoder.decode(value, { stream: true });
|
|
65
|
+
if (done) buffer += decoder.decode();
|
|
66
|
+
while (true) {
|
|
67
|
+
const searchable = !done && buffer.endsWith("\r") && !buffer.endsWith("\r\r") && !buffer.endsWith("\n\r") ? buffer.slice(0, -1) : buffer;
|
|
68
|
+
const boundary = /(?:\r\n|\r(?!\n)|\n)(?:\r\n|\r(?!\n)|\n)/.exec(searchable);
|
|
69
|
+
if (!boundary) break;
|
|
70
|
+
const chunk = buffer.slice(0, boundary.index);
|
|
71
|
+
buffer = buffer.slice(boundary.index + boundary[0].length);
|
|
72
|
+
const dataLines = chunk.split(/\r\n|\r|\n/).filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trim());
|
|
73
|
+
if (dataLines.length > 0) {
|
|
74
|
+
const data = dataLines.join("\n").trim();
|
|
75
|
+
if (data && data !== "[DONE]") {
|
|
76
|
+
let event;
|
|
77
|
+
try {
|
|
78
|
+
event = JSON.parse(data);
|
|
79
|
+
} catch (cause) {
|
|
80
|
+
if (!(cause instanceof SyntaxError)) throw cause;
|
|
81
|
+
throw new CodexProtocolError(MALFORMED_STREAMING_FRAGMENT_ERROR_MESSAGE, { cause });
|
|
82
|
+
}
|
|
83
|
+
yield event;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (done) break;
|
|
88
|
+
}
|
|
89
|
+
} finally {
|
|
90
|
+
try {
|
|
91
|
+
await guard.cancel();
|
|
92
|
+
} catch {}
|
|
93
|
+
try {
|
|
94
|
+
reader.releaseLock();
|
|
95
|
+
} catch {}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
//#endregion
|
|
38
99
|
//#region packages/ai/src/providers/openai-chatgpt-responses.ts
|
|
39
100
|
const dynamicImport = (specifier) => import(specifier);
|
|
40
101
|
function loadNodeOs() {
|
|
@@ -50,7 +111,6 @@ const CODEX_TOOL_CALL_PROVIDERS = /* @__PURE__ */ new Set(["openai", "opencode"]
|
|
|
50
111
|
const WEBSOCKET_MESSAGE_TOO_BIG_CLOSE_CODE = 1009;
|
|
51
112
|
const WEBSOCKET_CONNECTION_LIMIT_REACHED_CODE = "websocket_connection_limit_reached";
|
|
52
113
|
const OPENAI_CHATGPT_RESPONSES_ERROR_BODY_MAX_BYTES = 16 * 1024;
|
|
53
|
-
const OPENAI_CHATGPT_RESPONSES_SUCCESS_BODY_MAX_BYTES = 16 * 1024 * 1024;
|
|
54
114
|
const CODEX_RESPONSE_STATUSES = /* @__PURE__ */ new Set([
|
|
55
115
|
"completed",
|
|
56
116
|
"incomplete",
|
|
@@ -123,9 +183,17 @@ const streamOpenAICodexResponses = (model, context, options) => {
|
|
|
123
183
|
const modelHeaders = resolveAiTransportHeaderSentinels(model.headers);
|
|
124
184
|
const optionHeaders = resolveAiTransportHeaderSentinels(options?.headers);
|
|
125
185
|
const accountId = extractOpenAICodexAccountId(apiKey);
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
186
|
+
const buildBody = async (replayMode) => {
|
|
187
|
+
let body = buildRequestBody(model, context, options, replayMode);
|
|
188
|
+
const nextBody = await options?.onPayload?.(body, model);
|
|
189
|
+
if (nextBody !== void 0) body = nextBody;
|
|
190
|
+
return body;
|
|
191
|
+
};
|
|
192
|
+
let semanticAttempt = {
|
|
193
|
+
kind: "initial",
|
|
194
|
+
request: await buildBody("checkpoint")
|
|
195
|
+
};
|
|
196
|
+
const commitSemanticAttempt = (attempt) => commitResponsesEncryptedContentAttempt(attempt, (checkpoint) => suppressOpenAIResponsesCompaction(output, model, options, checkpoint));
|
|
129
197
|
const observePromptEgress = createResponsesPromptEgressObserver(options, context.systemPrompt);
|
|
130
198
|
const sessionId = clampOpenAIPromptCacheKey(options?.sessionId);
|
|
131
199
|
requestTimeoutMs = resolveRequestTimeoutMs(options);
|
|
@@ -141,13 +209,20 @@ const streamOpenAICodexResponses = (model, context, options) => {
|
|
|
141
209
|
if (transport !== "sse" && !websocketDisabledForSession) {
|
|
142
210
|
const websocketHeaders = buildWebSocketHeaders(modelHeaders, optionHeaders, accountId, apiKey, sessionId || createCodexRequestId());
|
|
143
211
|
let websocketStarted = false;
|
|
212
|
+
let websocketRequestSent = false;
|
|
144
213
|
let retriedWebSocketConnectionLimit = false;
|
|
145
214
|
while (true) {
|
|
215
|
+
const activeAttempt = semanticAttempt;
|
|
146
216
|
websocketStarted = false;
|
|
217
|
+
websocketRequestSent = false;
|
|
147
218
|
try {
|
|
148
|
-
await processWebSocketStream(resolveCodexWebSocketUrl(model.baseUrl),
|
|
219
|
+
await processWebSocketStream(resolveCodexWebSocketUrl(model.baseUrl), activeAttempt.request, websocketHeaders, output, stream, model, () => {
|
|
149
220
|
websocketStarted = true;
|
|
150
|
-
},
|
|
221
|
+
}, () => {
|
|
222
|
+
commitSemanticAttempt(activeAttempt);
|
|
223
|
+
}, requestOptions, firstEventAbort.abort, observePromptEgress, activeAttempt.kind, () => {
|
|
224
|
+
websocketRequestSent = true;
|
|
225
|
+
});
|
|
151
226
|
if (activeSignal?.aborted) throw transportAbortError(activeSignal);
|
|
152
227
|
if (output.stopReason === "aborted" || output.stopReason === "error") throw new CodexApiError(output.errorMessage ?? "An unknown error occurred");
|
|
153
228
|
stream.push({
|
|
@@ -159,6 +234,12 @@ const streamOpenAICodexResponses = (model, context, options) => {
|
|
|
159
234
|
return;
|
|
160
235
|
} catch (error) {
|
|
161
236
|
const aborted = activeSignal?.aborted;
|
|
237
|
+
const nextSemanticAttempt = !aborted && websocketRequestSent && !websocketStarted && error instanceof CodexApiError && isInvalidEncryptedContentError(error) ? await resolveNextResponsesEncryptedContentAttempt(activeAttempt, error, { buildFullHistoryRequest: () => buildBody("full-history") }) : void 0;
|
|
238
|
+
if (nextSemanticAttempt) {
|
|
239
|
+
semanticAttempt = nextSemanticAttempt;
|
|
240
|
+
retriedWebSocketConnectionLimit = false;
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
162
243
|
const connectionLimitBeforeStart = !websocketStarted && isWebSocketConnectionLimitReachedError(error);
|
|
163
244
|
if (!aborted && connectionLimitBeforeStart && !retriedWebSocketConnectionLimit) {
|
|
164
245
|
retriedWebSocketConnectionLimit = true;
|
|
@@ -170,7 +251,7 @@ const streamOpenAICodexResponses = (model, context, options) => {
|
|
|
170
251
|
fallbackTransport: transport === "auto" && !websocketStarted ? "sse" : void 0,
|
|
171
252
|
eventsEmitted: websocketStarted,
|
|
172
253
|
phase: websocketStarted ? "after_message_stream_start" : "before_message_stream_start",
|
|
173
|
-
requestBytes: new TextEncoder().encode(JSON.stringify(
|
|
254
|
+
requestBytes: new TextEncoder().encode(JSON.stringify(activeAttempt.request)).byteLength
|
|
174
255
|
}));
|
|
175
256
|
if (transport === "auto" && options?.sessionId) websocketSseFallbackSessions.add(options.sessionId);
|
|
176
257
|
if (websocketStarted || transport !== "auto") throw error;
|
|
@@ -178,64 +259,102 @@ const streamOpenAICodexResponses = (model, context, options) => {
|
|
|
178
259
|
}
|
|
179
260
|
}
|
|
180
261
|
}
|
|
181
|
-
const sseHeaders = buildSSEHeaders(modelHeaders, optionHeaders, accountId, apiKey, sessionId);
|
|
182
|
-
const bodyJson = JSON.stringify(body);
|
|
183
|
-
const compressedBody = model.provider === "openai" && !sseHeaders.has("content-encoding") ? compressRequestBodyZstd(bodyJson) : null;
|
|
184
|
-
if (compressedBody) sseHeaders.set("content-encoding", "zstd");
|
|
185
|
-
const sseBody = compressedBody ?? bodyJson;
|
|
186
262
|
let response;
|
|
187
|
-
let lastError;
|
|
188
263
|
const maxRetries = options?.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
264
|
+
while (true) {
|
|
265
|
+
const activeAttempt = semanticAttempt;
|
|
266
|
+
response = void 0;
|
|
267
|
+
const sseHeaders = buildSSEHeaders(modelHeaders, optionHeaders, accountId, apiKey, sessionId);
|
|
268
|
+
const bodyJson = JSON.stringify(activeAttempt.request);
|
|
269
|
+
const compressedBody = model.provider === "openai" && !sseHeaders.has("content-encoding") ? compressRequestBodyZstd(bodyJson) : null;
|
|
270
|
+
if (compressedBody) sseHeaders.set("content-encoding", "zstd");
|
|
271
|
+
const sseBody = compressedBody ?? bodyJson;
|
|
272
|
+
let terminalResponseError;
|
|
273
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
274
|
+
if (activeSignal?.aborted) throw transportAbortError(activeSignal);
|
|
275
|
+
observePromptEgress?.(activeAttempt.request, {
|
|
195
276
|
egress: "native-codex-sse",
|
|
196
|
-
payloadVariant:
|
|
197
|
-
});
|
|
198
|
-
attemptResponse = await fetch(resolveCodexUrl(model.baseUrl), {
|
|
199
|
-
method: "POST",
|
|
200
|
-
headers: sseHeaders,
|
|
201
|
-
body: sseBody,
|
|
202
|
-
signal: activeSignal
|
|
277
|
+
payloadVariant: activeAttempt.kind
|
|
203
278
|
});
|
|
279
|
+
let attemptResponse;
|
|
280
|
+
try {
|
|
281
|
+
attemptResponse = await fetch(resolveCodexUrl(model.baseUrl), {
|
|
282
|
+
method: "POST",
|
|
283
|
+
headers: sseHeaders,
|
|
284
|
+
body: sseBody,
|
|
285
|
+
signal: activeSignal
|
|
286
|
+
});
|
|
287
|
+
} catch (error) {
|
|
288
|
+
if (error instanceof Error) {
|
|
289
|
+
if (isRequestTimeoutError(error, options?.signal, requestTimeoutSignal, requestTimeoutMs) && requestTimeoutMs !== void 0) throw formatRequestTimeoutError(requestTimeoutMs, error);
|
|
290
|
+
if (error.name === "AbortError" || error.message === "Request was aborted") throw new Error("Request was aborted", { cause: error });
|
|
291
|
+
if (error.name === "TimeoutError" && requestTimeoutMs !== void 0) throw new Error(`Request timed out after ${requestTimeoutMs}ms`, { cause: error });
|
|
292
|
+
}
|
|
293
|
+
const tlsCertificateError = inspectTlsCertificateError(error);
|
|
294
|
+
const lastError = toErrorObject(error, String(error));
|
|
295
|
+
if (attempt < maxRetries && !lastError.message.includes("usage limit") && !tlsCertificateError) {
|
|
296
|
+
await sleepWithAbort(BASE_DELAY_MS * 2 ** attempt, activeSignal);
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
throw lastError;
|
|
300
|
+
}
|
|
204
301
|
response = attemptResponse;
|
|
205
|
-
await options?.onResponse?.({
|
|
206
|
-
status: attemptResponse.status,
|
|
207
|
-
headers: headersToRecord(attemptResponse.headers)
|
|
208
|
-
}, model);
|
|
209
302
|
if (attemptResponse.ok) break;
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
303
|
+
const hookStream = withFirstStreamEventTimeout(withProviderResponseHook({
|
|
304
|
+
signal: firstEventAbort.signal,
|
|
305
|
+
abort: firstEventAbort.abort,
|
|
306
|
+
hook: createOpenAIResponseHook(options?.onResponse, attemptResponse, model)
|
|
307
|
+
}), {
|
|
308
|
+
provider: model.provider,
|
|
309
|
+
api: model.api,
|
|
310
|
+
model: model.id,
|
|
311
|
+
timeoutMs: getFirstStreamEventTimeoutMs(options) ?? 0,
|
|
312
|
+
stage: "responses",
|
|
313
|
+
abort: firstEventAbort.abort,
|
|
314
|
+
onTimeout: getFirstStreamEventTimeoutHandler(options)
|
|
315
|
+
});
|
|
316
|
+
const [errorText] = await Promise.all([readChatGptResponsesErrorTextLimited(attemptResponse, activeSignal), hookStream[Symbol.asyncIterator]().next()]);
|
|
317
|
+
if (attempt < maxRetries && isRetryableError(attemptResponse.status, errorText)) {
|
|
318
|
+
await sleepWithAbort(resolveHttpRetryDelayMs(attemptResponse, attempt), activeSignal);
|
|
221
319
|
continue;
|
|
222
320
|
}
|
|
223
|
-
|
|
321
|
+
const info = parseErrorResponseText(errorText, attemptResponse.status, attemptResponse.statusText);
|
|
322
|
+
terminalResponseError = new CodexApiError(info.friendlyMessage || info.message, { code: info.code });
|
|
323
|
+
break;
|
|
224
324
|
}
|
|
225
|
-
if (
|
|
226
|
-
|
|
227
|
-
|
|
325
|
+
if (response?.ok) {
|
|
326
|
+
if (!response.body) throw new Error("No response body");
|
|
327
|
+
if (activeSignal?.aborted) throw transportAbortError(activeSignal);
|
|
328
|
+
commitSemanticAttempt(activeAttempt);
|
|
329
|
+
break;
|
|
228
330
|
}
|
|
229
|
-
|
|
230
|
-
|
|
331
|
+
if (activeSignal?.aborted) throw transportAbortError(activeSignal);
|
|
332
|
+
const nextSemanticAttempt = terminalResponseError ? await resolveNextResponsesEncryptedContentAttempt(activeAttempt, terminalResponseError, { buildFullHistoryRequest: () => buildBody("full-history") }) : void 0;
|
|
333
|
+
if (!nextSemanticAttempt) throw terminalResponseError ?? /* @__PURE__ */ new Error("Failed after retries");
|
|
334
|
+
semanticAttempt = nextSemanticAttempt;
|
|
231
335
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
336
|
+
await processResponsesStream(withProviderResponseHook({
|
|
337
|
+
stream: mapCodexEvents(parseOpenAIChatGptResponsesSse(response)),
|
|
338
|
+
signal: firstEventAbort.signal,
|
|
339
|
+
abort: firstEventAbort.abort,
|
|
340
|
+
hook: createOpenAIProviderAcceptanceHook(options, response, model),
|
|
341
|
+
onReady: () => stream.push({
|
|
342
|
+
type: "start",
|
|
343
|
+
partial: output
|
|
344
|
+
})
|
|
345
|
+
}), output, stream, model, {
|
|
346
|
+
serviceTier: options?.serviceTier,
|
|
347
|
+
firstEventTimeoutMs: getFirstStreamEventTimeoutMs(options),
|
|
348
|
+
abortFirstEventStream: firstEventAbort.abort,
|
|
349
|
+
onFirstEventTimeout: getFirstStreamEventTimeoutHandler(options),
|
|
350
|
+
signal: options?.signal,
|
|
351
|
+
reasoningReplayMetadata: buildOpenAIResponsesReasoningReplayMetadata(model, {
|
|
352
|
+
sessionId: options?.sessionId,
|
|
353
|
+
authProfileId: options?.authProfileId
|
|
354
|
+
}),
|
|
355
|
+
resolveServiceTier: resolveCodexServiceTier,
|
|
356
|
+
applyServiceTierPricing: (usage, serviceTier) => applyResponsesServiceTierPricing(usage, serviceTier, model)
|
|
237
357
|
});
|
|
238
|
-
await processStream(response, output, stream, model, options, firstEventAbort.abort);
|
|
239
358
|
if (activeSignal?.aborted) throw transportAbortError(activeSignal);
|
|
240
359
|
if (output.stopReason === "aborted" || output.stopReason === "error") throw new Error(output.errorMessage ?? "An unknown error occurred");
|
|
241
360
|
stream.push({
|
|
@@ -247,11 +366,11 @@ const streamOpenAICodexResponses = (model, context, options) => {
|
|
|
247
366
|
} catch (error) {
|
|
248
367
|
const normalizedError = isRequestTimeoutError(error, options?.signal, requestTimeoutSignal, requestTimeoutMs) && requestTimeoutMs !== void 0 ? formatRequestTimeoutError(requestTimeoutMs, error) : error;
|
|
249
368
|
for (const block of output.content) delete block.partialJson;
|
|
250
|
-
|
|
251
|
-
output
|
|
369
|
+
const terminal = projectProviderError(normalizedError, options?.signal);
|
|
370
|
+
Object.assign(output, terminal);
|
|
252
371
|
stream.push({
|
|
253
372
|
type: "error",
|
|
254
|
-
reason:
|
|
373
|
+
reason: terminal.stopReason,
|
|
255
374
|
error: output
|
|
256
375
|
});
|
|
257
376
|
stream.end();
|
|
@@ -266,15 +385,19 @@ const streamSimpleOpenAICodexResponses = (model, context, options) => {
|
|
|
266
385
|
if (!apiKey) throw new Error(`No API key for provider: ${model.provider}`);
|
|
267
386
|
const resolvedOptions = {
|
|
268
387
|
...buildBaseOptions(model, options, apiKey),
|
|
388
|
+
authProfileId: options?.authProfileId,
|
|
269
389
|
reasoningEffort: resolveResponsesReasoningEffort(model, options?.reasoning)
|
|
270
390
|
};
|
|
271
391
|
responsesPromptObserver.copy(options, resolvedOptions);
|
|
272
392
|
return streamOpenAICodexResponses(model, context, resolvedOptions);
|
|
273
393
|
};
|
|
274
|
-
function buildRequestBody(model, context, options) {
|
|
394
|
+
function buildRequestBody(model, context, options, replayMode = "checkpoint") {
|
|
275
395
|
const messages = convertResponsesMessages(model, context, CODEX_TOOL_CALL_PROVIDERS, {
|
|
276
396
|
includeSystemPrompt: false,
|
|
277
|
-
replayResponsesItemIds: false
|
|
397
|
+
replayResponsesItemIds: false,
|
|
398
|
+
sessionId: options?.sessionId,
|
|
399
|
+
authProfileId: options?.authProfileId,
|
|
400
|
+
replayMode
|
|
278
401
|
});
|
|
279
402
|
const body = {
|
|
280
403
|
model: model.id,
|
|
@@ -321,17 +444,6 @@ function resolveCodexWebSocketUrl(baseUrl) {
|
|
|
321
444
|
if (url.protocol === "http:") url.protocol = "ws:";
|
|
322
445
|
return url.toString();
|
|
323
446
|
}
|
|
324
|
-
async function processStream(response, output, stream, model, options, abortFirstEventStream) {
|
|
325
|
-
await processResponsesStream(mapCodexEvents(parseSSE(response)), output, stream, model, {
|
|
326
|
-
serviceTier: options?.serviceTier,
|
|
327
|
-
firstEventTimeoutMs: getFirstStreamEventTimeoutMs(options),
|
|
328
|
-
abortFirstEventStream,
|
|
329
|
-
onFirstEventTimeout: getFirstStreamEventTimeoutHandler(options),
|
|
330
|
-
signal: options?.signal,
|
|
331
|
-
resolveServiceTier: resolveCodexServiceTier,
|
|
332
|
-
applyServiceTierPricing: (usage, serviceTier) => applyResponsesServiceTierPricing(usage, serviceTier, model)
|
|
333
|
-
});
|
|
334
|
-
}
|
|
335
447
|
var CodexApiError = class extends Error {
|
|
336
448
|
constructor(message, options) {
|
|
337
449
|
super(message);
|
|
@@ -341,14 +453,6 @@ var CodexApiError = class extends Error {
|
|
|
341
453
|
this.cause = options?.cause;
|
|
342
454
|
}
|
|
343
455
|
};
|
|
344
|
-
var CodexProtocolError = class extends Error {
|
|
345
|
-
constructor(message, options) {
|
|
346
|
-
super(message);
|
|
347
|
-
this.name = "CodexProtocolError";
|
|
348
|
-
this.payload = options?.payload;
|
|
349
|
-
this.cause = options?.cause;
|
|
350
|
-
}
|
|
351
|
-
};
|
|
352
456
|
function isCodexNonTransportError(error) {
|
|
353
457
|
return error instanceof CodexApiError || error instanceof CodexProtocolError || error instanceof ResponsesStreamFailure;
|
|
354
458
|
}
|
|
@@ -393,53 +497,6 @@ function normalizeCodexStatus(status) {
|
|
|
393
497
|
if (typeof status !== "string") return;
|
|
394
498
|
return CODEX_RESPONSE_STATUSES.has(status) ? status : void 0;
|
|
395
499
|
}
|
|
396
|
-
async function* parseSSE(response) {
|
|
397
|
-
if (!response.body) return;
|
|
398
|
-
const reader = response.body.getReader();
|
|
399
|
-
const guard = createSseByteGuard(reader, {
|
|
400
|
-
maxBytes: OPENAI_CHATGPT_RESPONSES_SUCCESS_BODY_MAX_BYTES,
|
|
401
|
-
onOverflow: ({ size, maxBytes }) => /* @__PURE__ */ new Error(`OpenAI ChatGPT Responses success body exceeded ${maxBytes} bytes (received ${size})`)
|
|
402
|
-
});
|
|
403
|
-
const decoder = new TextDecoder();
|
|
404
|
-
let buffer = "";
|
|
405
|
-
try {
|
|
406
|
-
while (true) {
|
|
407
|
-
const { done, value } = await guard.read();
|
|
408
|
-
if (value) buffer += decoder.decode(value, { stream: true });
|
|
409
|
-
if (done) buffer += decoder.decode();
|
|
410
|
-
while (true) {
|
|
411
|
-
const searchable = !done && buffer.endsWith("\r") && !buffer.endsWith("\r\r") && !buffer.endsWith("\n\r") ? buffer.slice(0, -1) : buffer;
|
|
412
|
-
const boundary = /(?:\r\n|\r(?!\n)|\n)(?:\r\n|\r(?!\n)|\n)/.exec(searchable);
|
|
413
|
-
if (!boundary) break;
|
|
414
|
-
const chunk = buffer.slice(0, boundary.index);
|
|
415
|
-
buffer = buffer.slice(boundary.index + boundary[0].length);
|
|
416
|
-
const dataLines = chunk.split(/\r\n|\r|\n/).filter((l) => l.startsWith("data:")).map((l) => l.slice(5).trim());
|
|
417
|
-
if (dataLines.length > 0) {
|
|
418
|
-
const data = dataLines.join("\n").trim();
|
|
419
|
-
if (data && data !== "[DONE]") {
|
|
420
|
-
let event;
|
|
421
|
-
try {
|
|
422
|
-
event = JSON.parse(data);
|
|
423
|
-
} catch (cause) {
|
|
424
|
-
if (!(cause instanceof SyntaxError)) throw cause;
|
|
425
|
-
throw new CodexProtocolError(MALFORMED_STREAMING_FRAGMENT_ERROR_MESSAGE, { cause });
|
|
426
|
-
}
|
|
427
|
-
yield event;
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
if (done) break;
|
|
432
|
-
}
|
|
433
|
-
} finally {
|
|
434
|
-
try {
|
|
435
|
-
await guard.cancel();
|
|
436
|
-
} catch {}
|
|
437
|
-
try {
|
|
438
|
-
reader.releaseLock();
|
|
439
|
-
} catch {}
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
const parseSSEForTest = parseSSE;
|
|
443
500
|
const OPENAI_BETA_RESPONSES_WEBSOCKETS = "responses_websockets=2026-02-06";
|
|
444
501
|
const SESSION_WEBSOCKET_CACHE_TTL_MS = 300 * 1e3;
|
|
445
502
|
const SESSION_WEBSOCKET_MAX_AGE_MS = 3300 * 1e3;
|
|
@@ -815,12 +872,14 @@ function buildCachedWebSocketRequestBody(entry, body) {
|
|
|
815
872
|
input: delta
|
|
816
873
|
};
|
|
817
874
|
}
|
|
818
|
-
async function* startWebSocketOutputOnFirstEvent(events, output, stream, onStart) {
|
|
875
|
+
async function* startWebSocketOutputOnFirstEvent(events, output, stream, onFirstProviderEvent, reportStreamOpened, onStart) {
|
|
819
876
|
let started = false;
|
|
820
877
|
for await (const event of events) {
|
|
821
878
|
if (!started) {
|
|
822
879
|
started = true;
|
|
880
|
+
onFirstProviderEvent();
|
|
823
881
|
onStart();
|
|
882
|
+
await reportStreamOpened();
|
|
824
883
|
stream.push({
|
|
825
884
|
type: "start",
|
|
826
885
|
partial: output
|
|
@@ -829,7 +888,7 @@ async function* startWebSocketOutputOnFirstEvent(events, output, stream, onStart
|
|
|
829
888
|
yield event;
|
|
830
889
|
}
|
|
831
890
|
}
|
|
832
|
-
async function processWebSocketStream(url, body, headers, output, stream, model, onStart, options, abortFirstEventStream, observePromptEgress) {
|
|
891
|
+
async function processWebSocketStream(url, body, headers, output, stream, model, onFirstProviderEvent, onStart, options, abortFirstEventStream, observePromptEgress, payloadVariant = "initial", onRequestSent) {
|
|
833
892
|
const { socket, entry, release } = await acquireWebSocket(url, headers, options?.sessionId, options?.signal);
|
|
834
893
|
let keepConnection = true;
|
|
835
894
|
const useCachedContext = options?.transport === "websocket-cached" || options?.transport === "auto";
|
|
@@ -839,18 +898,29 @@ async function processWebSocketStream(url, body, headers, output, stream, model,
|
|
|
839
898
|
if (options?.signal?.aborted) throw transportAbortError(options.signal);
|
|
840
899
|
observePromptEgress?.(requestBody, {
|
|
841
900
|
egress: "native-codex-websocket",
|
|
842
|
-
payloadVariant
|
|
901
|
+
payloadVariant
|
|
843
902
|
});
|
|
844
903
|
socket.send(JSON.stringify({
|
|
845
904
|
type: "response.create",
|
|
846
905
|
...requestBody
|
|
847
906
|
}));
|
|
848
|
-
|
|
907
|
+
onRequestSent?.();
|
|
908
|
+
await processResponsesStream(startWebSocketOutputOnFirstEvent(mapCodexEvents(parseWebSocket(socket, options?.signal)), output, stream, onFirstProviderEvent, () => notifyProviderStreamOpened({
|
|
909
|
+
options,
|
|
910
|
+
cancelStream: () => {
|
|
911
|
+
keepConnection = false;
|
|
912
|
+
closeWebSocketSilently(socket);
|
|
913
|
+
}
|
|
914
|
+
}), onStart), output, stream, model, {
|
|
849
915
|
serviceTier: options?.serviceTier,
|
|
850
916
|
firstEventTimeoutMs: getFirstStreamEventTimeoutMs(options),
|
|
851
917
|
abortFirstEventStream,
|
|
852
918
|
onFirstEventTimeout: getFirstStreamEventTimeoutHandler(options),
|
|
853
919
|
signal: options?.signal,
|
|
920
|
+
reasoningReplayMetadata: buildOpenAIResponsesReasoningReplayMetadata(model, {
|
|
921
|
+
sessionId: options?.sessionId,
|
|
922
|
+
authProfileId: options?.authProfileId
|
|
923
|
+
}),
|
|
854
924
|
resolveServiceTier: resolveCodexServiceTier,
|
|
855
925
|
applyServiceTierPricing: (usage, serviceTier) => applyResponsesServiceTierPricing(usage, serviceTier, model)
|
|
856
926
|
});
|
|
@@ -858,7 +928,9 @@ async function processWebSocketStream(url, body, headers, output, stream, model,
|
|
|
858
928
|
else if (useCachedContext && entry && output.responseId) {
|
|
859
929
|
const responseItems = convertResponsesMessages(model, { messages: [output] }, CODEX_TOOL_CALL_PROVIDERS, {
|
|
860
930
|
includeSystemPrompt: false,
|
|
861
|
-
replayResponsesItemIds: false
|
|
931
|
+
replayResponsesItemIds: false,
|
|
932
|
+
sessionId: options?.sessionId,
|
|
933
|
+
authProfileId: options?.authProfileId
|
|
862
934
|
}).filter((item) => item.type !== "function_call_output");
|
|
863
935
|
entry.continuation = {
|
|
864
936
|
lastRequestBody: fullBody,
|
|
@@ -874,17 +946,31 @@ async function processWebSocketStream(url, body, headers, output, stream, model,
|
|
|
874
946
|
release({ keep: keepConnection });
|
|
875
947
|
}
|
|
876
948
|
}
|
|
877
|
-
async function readChatGptResponsesErrorTextLimited(response) {
|
|
949
|
+
async function readChatGptResponsesErrorTextLimited(response, signal) {
|
|
878
950
|
const reader = response.body?.getReader();
|
|
879
951
|
if (!reader) return "";
|
|
880
952
|
const decoder = new TextDecoder();
|
|
881
953
|
let total = 0;
|
|
882
954
|
let text = "";
|
|
883
955
|
let reachedLimit = false;
|
|
956
|
+
let completed = false;
|
|
957
|
+
let cancelPromise;
|
|
958
|
+
const cancel = () => {
|
|
959
|
+
cancelPromise ??= reader.cancel(signal?.reason).catch(() => {});
|
|
960
|
+
return cancelPromise;
|
|
961
|
+
};
|
|
962
|
+
const onAbort = () => {
|
|
963
|
+
cancel();
|
|
964
|
+
};
|
|
965
|
+
if (signal?.aborted) onAbort();
|
|
966
|
+
else signal?.addEventListener("abort", onAbort, { once: true });
|
|
884
967
|
try {
|
|
885
968
|
while (true) {
|
|
886
969
|
const { value, done } = await reader.read();
|
|
887
|
-
if (done)
|
|
970
|
+
if (done) {
|
|
971
|
+
completed = true;
|
|
972
|
+
break;
|
|
973
|
+
}
|
|
888
974
|
if (!value || value.byteLength === 0) continue;
|
|
889
975
|
const remaining = OPENAI_CHATGPT_RESPONSES_ERROR_BODY_MAX_BYTES - total;
|
|
890
976
|
if (remaining <= 0) {
|
|
@@ -901,7 +987,8 @@ async function readChatGptResponsesErrorTextLimited(response) {
|
|
|
901
987
|
}
|
|
902
988
|
if (!reachedLimit) text += decoder.decode();
|
|
903
989
|
} finally {
|
|
904
|
-
|
|
990
|
+
signal?.removeEventListener("abort", onAbort);
|
|
991
|
+
if (!completed) await cancel();
|
|
905
992
|
try {
|
|
906
993
|
reader.releaseLock();
|
|
907
994
|
} catch {}
|
|
@@ -911,11 +998,12 @@ async function readChatGptResponsesErrorTextLimited(response) {
|
|
|
911
998
|
function parseErrorResponseText(raw, status, statusText) {
|
|
912
999
|
let message = raw || statusText || "Request failed";
|
|
913
1000
|
let friendlyMessage;
|
|
1001
|
+
let code;
|
|
914
1002
|
try {
|
|
915
1003
|
const err = JSON.parse(raw)?.error;
|
|
916
1004
|
if (err) {
|
|
917
|
-
|
|
918
|
-
if (/usage_limit_reached|usage_not_included|rate_limit_exceeded/i.test(code) || status === 429) {
|
|
1005
|
+
code = err.code || err.type || void 0;
|
|
1006
|
+
if (/usage_limit_reached|usage_not_included|rate_limit_exceeded/i.test(code ?? "") || status === 429) {
|
|
919
1007
|
const plan = err.plan_type ? ` (${err.plan_type.toLowerCase()} plan)` : "";
|
|
920
1008
|
const mins = err.resets_at ? Math.max(0, Math.round((err.resets_at * 1e3 - Date.now()) / 6e4)) : void 0;
|
|
921
1009
|
friendlyMessage = `You have hit your ChatGPT usage limit${plan}.${mins !== void 0 ? ` Try again in ~${mins} min.` : ""}`.trim();
|
|
@@ -924,6 +1012,7 @@ function parseErrorResponseText(raw, status, statusText) {
|
|
|
924
1012
|
}
|
|
925
1013
|
} catch {}
|
|
926
1014
|
return {
|
|
1015
|
+
...code ? { code } : {},
|
|
927
1016
|
message,
|
|
928
1017
|
friendlyMessage
|
|
929
1018
|
};
|
|
@@ -975,4 +1064,4 @@ function buildWebSocketHeaders(initHeaders, additionalHeaders, accountId, token,
|
|
|
975
1064
|
return headers;
|
|
976
1065
|
}
|
|
977
1066
|
//#endregion
|
|
978
|
-
export { closeOpenAICodexWebSocketSessions, extractOpenAICodexAccountId,
|
|
1067
|
+
export { closeOpenAICodexWebSocketSessions, extractOpenAICodexAccountId, resetOpenAICodexWebSocketStateForTest, streamOpenAICodexResponses, streamSimpleOpenAICodexResponses };
|