@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.
Files changed (88) hide show
  1. package/dist/{anthropic-CE-7SkF6.mjs → anthropic-B8KwTtlb.mjs} +62 -37
  2. package/dist/{anthropic-SrGtwsJu.d.mts → anthropic-BECQCNdF.d.mts} +0 -2
  3. package/dist/{src-QkygScBs.mjs → anthropic-BQXQudmA.mjs} +0 -2
  4. package/dist/{anthropic-usage-Ma4iX6uG.mjs → anthropic-compaction-replay-4Zx7-aCr.mjs} +225 -103
  5. package/dist/anthropic-payload-policy-CSx7MoKH.d.mts +50 -0
  6. package/dist/{api-registry-EpJoVwM1.d.mts → api-registry-DFxSnFqG.d.mts} +1 -1
  7. package/dist/{azure-openai-responses-Cc_kasye.mjs → azure-openai-responses-Aa4mVcYG.mjs} +23 -29
  8. package/dist/diagnostics.d.mts +24 -1
  9. package/dist/diagnostics.mjs +2 -1
  10. package/dist/event-stream-BVVgDSdq.d.mts +1 -0
  11. package/dist/{event-stream-DRmDMRHH.d.mts → event-stream-D91-ohD_.d.mts} +3 -1
  12. package/dist/{event-stream-CEV9t6da.mjs → event-stream-uSMZJ3FA.mjs} +16 -3
  13. package/dist/event-stream.d.mts +1 -1
  14. package/dist/event-stream.mjs +1 -1
  15. package/dist/{google-shared-Cq2UKx1l.mjs → google-shared-M1dl64nz.mjs} +17 -19
  16. package/dist/google-thinking-level-C-V3tecN.mjs +9 -0
  17. package/dist/{google-vertex-CusxWzvE.mjs → google-vertex-DCJHM_a5.mjs} +5 -4
  18. package/dist/{google-CGQu21aw.mjs → google-yDRnipeq.mjs} +4 -4
  19. package/dist/host-DF_yxOsA.mjs +477 -0
  20. package/dist/{host-Dn4_SZI2.d.mts → host-DJq_FGcz.d.mts} +13 -8
  21. package/dist/index.d.mts +7 -7
  22. package/dist/index.mjs +7 -5
  23. package/dist/internal/anthropic.d.mts +21 -7
  24. package/dist/internal/anthropic.mjs +5 -5
  25. package/dist/internal/openai-responses-payload-policy.d.mts +3 -0
  26. package/dist/internal/openai-responses-payload-policy.mjs +3 -0
  27. package/dist/internal/openai.d.mts +6 -6
  28. package/dist/internal/openai.mjs +9 -7
  29. package/dist/internal/runtime.d.mts +19 -5
  30. package/dist/internal/runtime.mjs +85 -72
  31. package/dist/internal/shared.d.mts +17 -8
  32. package/dist/internal/shared.mjs +4 -5
  33. package/dist/{json-parse-BvXNt1-7.mjs → json-parse-CDnesDM_.mjs} +4 -6
  34. package/dist/{mistral-Dx6VzNjf.mjs → mistral-D6hRXI7A.mjs} +67 -72
  35. package/dist/{number-coercion-1Miyb5MO.mjs → number-coercion-H9qHik3g.mjs} +7 -2
  36. package/dist/openai-chatgpt-jwt-KWcgd0d_.mjs +19 -0
  37. package/dist/{openai-chatgpt-responses-SC9m0FSf.mjs → openai-chatgpt-responses-C339VIfT.mjs} +235 -146
  38. package/dist/{openai-completions-BaIpl93j.mjs → openai-completions-D88orSJ9.mjs} +88 -67
  39. package/dist/openai-completions-compat-B0KTleXp.d.mts +43 -0
  40. package/dist/{openai-responses-Bdx3V_Yu.mjs → openai-responses-BXEcr-Tp.mjs} +17 -24
  41. package/dist/openai-responses-contracts-CD75pQ0m.d.mts +68 -0
  42. package/dist/openai-responses-contracts-DvILoqBk.mjs +247 -0
  43. package/dist/openai-responses-payload-policy-BDo8CQsx.mjs +208 -0
  44. package/dist/openai-responses-payload-policy-CNGFT9zr.d.mts +41 -0
  45. package/dist/{openai-responses-prompt-observer-internal-DDZPxRfr.mjs → openai-responses-prompt-observer-internal-BG-1AsBI.mjs} +2 -3
  46. package/dist/{openai-responses-stream-internal-Bl8YyVtF.mjs → openai-responses-shared-Cvt5MgEm.mjs} +1287 -1039
  47. package/dist/{openai-reasoning-compat-DKebnIBL.mjs → openai-stop-reason-9OONKyAm.mjs} +222 -180
  48. package/dist/{openai-transport-shared-Cipt7egQ.mjs → openai-tool-projection-CHGLt03m.mjs} +239 -128
  49. package/dist/provider-error-C8mBRJDl.mjs +424 -0
  50. package/dist/provider-error-CzNw4BWX.d.mts +12 -0
  51. package/dist/provider-options-AvldWZt8.mjs +21 -0
  52. package/dist/{provider-options-C5kYML7i.d.mts → provider-options-Cc5ZQ6Aa.d.mts} +19 -3
  53. package/dist/provider-transcript-transform--gtf0ZbR.mjs +32 -0
  54. package/dist/provider-types.d.mts +31 -0
  55. package/dist/provider-types.mjs +8 -0
  56. package/dist/providers.d.mts +1 -1
  57. package/dist/providers.mjs +17 -19
  58. package/dist/{reasoning-tag-text-partitioner-CGDyLWUR.mjs → reasoning-tag-text-partitioner-5ygO2rZc.mjs} +17 -8
  59. package/dist/record-coerce-DdXsgUd_.mjs +23 -0
  60. package/dist/{model-utils-Dau5dlgm.mjs → sanitize-unicode-BP7HLLZn.mjs} +28 -2
  61. package/dist/session-resources-CkR4WWy1.mjs +21 -0
  62. package/dist/simple-options-oqsXB6U3.mjs +450 -0
  63. package/dist/src-D2H6yKkH.mjs +2 -0
  64. package/dist/{stream-first-event-timeout-BIBomOGq.mjs → stream-first-event-timeout-MK28puvq.mjs} +2 -2
  65. package/dist/string-coerce-fsri9iCu.mjs +34 -0
  66. package/dist/{tool-schema-json-projection-B1b-XCn5.mjs → tool-schema-json-projection-FEr-jOoZ.mjs} +20 -13
  67. package/dist/transport-utils-Bv0FHkd0.mjs +138 -0
  68. package/dist/transports.d.mts +199 -209
  69. package/dist/transports.mjs +1842 -1364
  70. package/dist/types-BDdaOVi2.mjs +6 -0
  71. package/dist/{types-CH7ReIcU.d.mts → types-DTAP49HF.d.mts} +35 -2
  72. package/dist/types.d.mts +5 -5
  73. package/dist/types.mjs +6 -4
  74. package/dist/utf16-slice-CvGodqok.mjs +29 -0
  75. package/dist/{validation-DAa_yFOM.mjs → validation-B61OhAio.mjs} +6 -6
  76. package/dist/{validation-CcPcuEbR.d.mts → validation-DYNNrU9u.d.mts} +1 -1
  77. package/dist/validation.d.mts +1 -1
  78. package/dist/validation.mjs +1 -1
  79. package/package.json +15 -1
  80. package/dist/host-Bl7Kgddo.mjs +0 -407
  81. package/dist/openai-chatgpt-jwt-DhAAzLkj.mjs +0 -39
  82. package/dist/openai-responses-contracts-BBKBfAqR.d.mts +0 -116
  83. package/dist/openai-responses-shared-CCyMvg7M.mjs +0 -403
  84. package/dist/provider-error-DI0Ts28U.mjs +0 -47
  85. package/dist/sanitize-unicode-DT5o51ur.mjs +0 -26
  86. package/dist/tool-result-text-Dvkp2Dus.mjs +0 -274
  87. package/dist/transform-messages-DfjpNXNQ.mjs +0 -2
  88. package/dist/transport-stream-shared-CPNv7A3r.mjs +0 -297
@@ -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-CEV9t6da.mjs";
4
- import { n as getAiTransportHost, r as resolveAiTransportHeaderSentinels } from "./host-Bl7Kgddo.mjs";
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 { c as buildBaseOptions, h as stripSystemPromptCacheBoundary } from "./tool-result-text-Dvkp2Dus.mjs";
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 { a as resolveResponsesReasoningEffort, i as createResponsesAssistantOutput, n as applyResponsesServiceTierPricing, r as convertResponsesMessages, s as convertResponsesToolPayload } from "./openai-responses-shared-CCyMvg7M.mjs";
15
- import { i as registerSessionResourceCleanup, n as resolveOpenAICodexAccountId } from "./openai-chatgpt-jwt-DhAAzLkj.mjs";
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
- let body = buildRequestBody(model, context, options);
127
- const nextBody = await options?.onPayload?.(body, model);
128
- if (nextBody !== void 0) body = nextBody;
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), body, websocketHeaders, output, stream, model, () => {
219
+ await processWebSocketStream(resolveCodexWebSocketUrl(model.baseUrl), activeAttempt.request, websocketHeaders, output, stream, model, () => {
149
220
  websocketStarted = true;
150
- }, requestOptions, firstEventAbort.abort, observePromptEgress);
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(body)).byteLength
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
- for (let attempt = 0; attempt <= maxRetries; attempt++) {
190
- if (activeSignal?.aborted) throw transportAbortError(activeSignal);
191
- let attemptResponse;
192
- let errorText;
193
- try {
194
- observePromptEgress?.(body, {
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: "initial"
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
- errorText = await readChatGptResponsesErrorTextLimited(attemptResponse);
211
- } catch (error) {
212
- if (error instanceof Error) {
213
- if (isRequestTimeoutError(error, options?.signal, requestTimeoutSignal, requestTimeoutMs) && requestTimeoutMs !== void 0) throw formatRequestTimeoutError(requestTimeoutMs, error);
214
- if (error.name === "AbortError" || error.message === "Request was aborted") throw new Error("Request was aborted", { cause: error });
215
- if (error.name === "TimeoutError" && requestTimeoutMs !== void 0) throw new Error(`Request timed out after ${requestTimeoutMs}ms`, { cause: error });
216
- }
217
- const tlsCertificateError = inspectTlsCertificateError(error);
218
- lastError = toErrorObject(error, String(error));
219
- if (attempt < maxRetries && !lastError.message.includes("usage limit") && !tlsCertificateError) {
220
- await sleepWithAbort(BASE_DELAY_MS * 2 ** attempt, activeSignal);
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
- throw lastError;
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 (attempt < maxRetries && isRetryableError(attemptResponse.status, errorText)) {
226
- await sleepWithAbort(resolveHttpRetryDelayMs(attemptResponse, attempt), activeSignal);
227
- continue;
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
- const info = parseErrorResponseText(errorText, attemptResponse.status, attemptResponse.statusText);
230
- throw new Error(info.friendlyMessage || info.message);
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
- if (!response?.ok) throw lastError ?? /* @__PURE__ */ new Error("Failed after retries");
233
- if (!response.body) throw new Error("No response body");
234
- stream.push({
235
- type: "start",
236
- partial: output
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
- output.stopReason = options?.signal?.aborted ? "aborted" : "error";
251
- output.errorMessage = normalizedError instanceof Error ? normalizedError.message : String(normalizedError);
369
+ const terminal = projectProviderError(normalizedError, options?.signal);
370
+ Object.assign(output, terminal);
252
371
  stream.push({
253
372
  type: "error",
254
- reason: output.stopReason,
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: "initial"
901
+ payloadVariant
843
902
  });
844
903
  socket.send(JSON.stringify({
845
904
  type: "response.create",
846
905
  ...requestBody
847
906
  }));
848
- await processResponsesStream(startWebSocketOutputOnFirstEvent(mapCodexEvents(parseWebSocket(socket, options?.signal)), output, stream, onStart), output, stream, model, {
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) break;
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
- if (reachedLimit) await reader.cancel().catch(() => {});
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
- const code = err.code || err.type || "";
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, parseSSEForTest, resetOpenAICodexWebSocketStateForTest, streamOpenAICodexResponses, streamSimpleOpenAICodexResponses };
1067
+ export { closeOpenAICodexWebSocketSessions, extractOpenAICodexAccountId, resetOpenAICodexWebSocketStateForTest, streamOpenAICodexResponses, streamSimpleOpenAICodexResponses };