@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,128 +1,42 @@
1
- import { _ as normalizeLowercaseStringOrEmpty, b as isRecord, v as normalizeOptionalString } from "./host-Bl7Kgddo.mjs";
2
- import { n as calculateCost } from "./model-utils-Dau5dlgm.mjs";
3
- import { a as isImageWithMediaPayload, h as stripSystemPromptCacheBoundary, o as truncateUtf16Safe, r as extractToolResultText, t as describeToolResultMediaPlaceholder } from "./tool-result-text-Dvkp2Dus.mjs";
4
- import { c as transformTransportMessages } from "./tool-schema-json-projection-B1b-XCn5.mjs";
5
- import { n as parseStreamingJson } from "./json-parse-BvXNt1-7.mjs";
6
- import { b as redactIdentifier, d as transportAbortError, l as sanitizeNonEmptyTransportPayloadText, u as sanitizeTransportPayloadText, x as redactSensitiveText } from "./transport-stream-shared-CPNv7A3r.mjs";
7
- import { i as log, n as createModelStreamCooperativeScheduler } from "./openai-transport-shared-Cipt7egQ.mjs";
8
- import { a as withFirstStreamEventTimeout } from "./stream-first-event-timeout-BIBomOGq.mjs";
1
+ import { a as normalizeOptionalString, n as normalizeLowercaseStringOrEmpty } from "./string-coerce-fsri9iCu.mjs";
2
+ import { i as clampThinkingLevel, r as calculateCost } from "./sanitize-unicode-BP7HLLZn.mjs";
3
+ import { a as describeToolResultMediaPlaceholder, c as extractToolResultText, d as isImageWithMediaPayload, n as getAiTransportHost } from "./host-DF_yxOsA.mjs";
4
+ import { a as isRecord } from "./record-coerce-DdXsgUd_.mjs";
5
+ import { t as truncateUtf16Safe } from "./utf16-slice-CvGodqok.mjs";
6
+ import { n as projectProviderError } from "./provider-error-C8mBRJDl.mjs";
7
+ import { t as asFiniteNumber } from "./number-coercion-H9qHik3g.mjs";
8
+ import { C as normalizeStringEntries, S as supportsOpenAITemperature, T as uniqueValues, a as OPENAI_RESPONSES_COMPACTION_REPLAY_TYPE, c as OPENAI_RESPONSES_RETAINED_COMPACTION_REPLAY_TYPE, f as RESPONSE_FAILED_NO_DETAILS_MESSAGE, o as OPENAI_RESPONSES_REASONING_REPLAY_BLOCK_META_KEY, s as OPENAI_RESPONSES_REASONING_REPLAY_META_KEY, x as supportsOpenAIReasoningEffort, y as resolveOpenAIReasoningEffortForModel } from "./openai-responses-contracts-DvILoqBk.mjs";
9
+ import { C as withProviderResponseHook, P as sortPromptCacheToolsByName, b as sanitizeTransportPayloadText, j as stripSystemPromptCacheBoundary, v as parseTerminalToolCallArguments, x as transportAbortError, y as sanitizeNonEmptyTransportPayloadText } from "./simple-options-oqsXB6U3.mjs";
10
+ import { c as transformTransportMessages } from "./tool-schema-json-projection-FEr-jOoZ.mjs";
11
+ import { n as parseStreamingJson } from "./json-parse-CDnesDM_.mjs";
12
+ import { t as notifyLlmRequestActivity } from "./llm-request-activity-BjtkplhG.mjs";
9
13
  import { t as shortHash } from "./hash-CHgqbJmD.mjs";
10
- import { randomUUID } from "node:crypto";
11
- //#region packages/ai/src/transports/json-unsafe-integers.ts
14
+ import { l as redactIdentifier, u as redactSensitiveText } from "./transport-utils-Bv0FHkd0.mjs";
15
+ import { a as createModelStreamCooperativeScheduler, l as log, o as createOpenAIProviderAcceptanceHook, t as projectOpenAITools } 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 { t as transformProviderMessages } from "./provider-transcript-transform--gtf0ZbR.mjs";
18
+ import { createHash, randomUUID } from "node:crypto";
19
+ //#region packages/ai/src/transports/model-transport-debug.ts
12
20
  /**
13
- * JSON parsing helpers that preserve integer literals larger than
14
- * Number.MAX_SAFE_INTEGER as strings before JSON.parse can round them.
21
+ * Environment-driven debug controls for model transport logging.
22
+ *
23
+ * Model adapters share these helpers so payload, SSE, and transport diagnostics
24
+ * interpret OpenClaw debug environment variables consistently.
15
25
  */
16
- const MAX_SAFE_INTEGER_ABS_STR = String(Number.MAX_SAFE_INTEGER);
17
- function isAsciiDigit(ch) {
18
- return ch !== void 0 && ch >= "0" && ch <= "9";
19
- }
20
- function parseJsonNumberToken(input, start) {
21
- let idx = start;
22
- if (input[idx] === "-") idx += 1;
23
- if (idx >= input.length) return null;
24
- if (input[idx] === "0") idx += 1;
25
- else if (isAsciiDigit(input[idx]) && input[idx] !== "0") while (isAsciiDigit(input[idx])) idx += 1;
26
- else return null;
27
- let isInteger = true;
28
- if (input[idx] === ".") {
29
- isInteger = false;
30
- idx += 1;
31
- if (!isAsciiDigit(input[idx])) return null;
32
- while (isAsciiDigit(input[idx])) idx += 1;
33
- }
34
- if (input[idx] === "e" || input[idx] === "E") {
35
- isInteger = false;
36
- idx += 1;
37
- if (input[idx] === "+" || input[idx] === "-") idx += 1;
38
- if (!isAsciiDigit(input[idx])) return null;
39
- while (isAsciiDigit(input[idx])) idx += 1;
40
- }
41
- return {
42
- token: input.slice(start, idx),
43
- end: idx,
44
- isInteger
45
- };
46
- }
47
- function isUnsafeIntegerLiteral(token) {
48
- const digits = token[0] === "-" ? token.slice(1) : token;
49
- if (digits.length < MAX_SAFE_INTEGER_ABS_STR.length) return false;
50
- if (digits.length > MAX_SAFE_INTEGER_ABS_STR.length) return true;
51
- return digits > MAX_SAFE_INTEGER_ABS_STR;
52
- }
53
- /** Quotes integer literals above Number.MAX_SAFE_INTEGER before JSON.parse. */
54
- function quoteUnsafeIntegerLiterals(input) {
55
- let out = "";
56
- let inString = false;
57
- let escaped = false;
58
- let idx = 0;
59
- while (idx < input.length) {
60
- const ch = input[idx] ?? "";
61
- if (inString) {
62
- out += ch;
63
- if (escaped) escaped = false;
64
- else if (ch === "\\") escaped = true;
65
- else if (ch === "\"") inString = false;
66
- idx += 1;
67
- continue;
68
- }
69
- if (ch === "\"") {
70
- inString = true;
71
- out += ch;
72
- idx += 1;
73
- continue;
74
- }
75
- if (ch === "-" || isAsciiDigit(ch)) {
76
- const parsed = parseJsonNumberToken(input, idx);
77
- if (parsed) {
78
- if (parsed.isInteger && isUnsafeIntegerLiteral(parsed.token)) out += `"${parsed.token}"`;
79
- else out += parsed.token;
80
- idx = parsed.end;
81
- continue;
82
- }
83
- }
84
- out += ch;
85
- idx += 1;
86
- }
87
- return out;
88
- }
89
- /** Parses JSON while preserving unsafe integer literals as strings. */
90
- function parseJsonPreservingUnsafeIntegers(input) {
91
- return JSON.parse(quoteUnsafeIntegerLiterals(input));
92
- }
93
- /** Parses or accepts an object while preserving unsafe integer literals in string input. */
94
- function parseJsonObjectPreservingUnsafeIntegers(value) {
95
- if (typeof value === "string") {
96
- try {
97
- const parsed = parseJsonPreservingUnsafeIntegers(value);
98
- if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) return parsed;
99
- } catch {
100
- return null;
101
- }
102
- return null;
103
- }
104
- if (value && typeof value === "object" && !Array.isArray(value)) return value;
105
- return null;
106
- }
107
- //#endregion
108
- //#region packages/ai/src/transports/model-transport-debug.ts
109
- function normalizeEnv(value) {
110
- return typeof value === "string" ? value.trim().toLowerCase() : "";
111
- }
112
26
  function isTruthyEnv(value) {
113
- const normalized = normalizeEnv(value);
27
+ const normalized = normalizeLowercaseStringOrEmpty(value);
114
28
  return normalized.length > 0 && normalized !== "0" && normalized !== "false" && normalized !== "off" && normalized !== "no";
115
29
  }
116
30
  /** Resolves model payload debug verbosity from `OPENCLAW_DEBUG_MODEL_PAYLOAD`. */
117
31
  function resolveModelPayloadDebugMode(env = process.env) {
118
- const normalized = normalizeEnv(env.OPENCLAW_DEBUG_MODEL_PAYLOAD);
32
+ const normalized = normalizeLowercaseStringOrEmpty(env.OPENCLAW_DEBUG_MODEL_PAYLOAD);
119
33
  if (normalized === "tools" || normalized === "full-redacted") return normalized;
120
34
  if (normalized === "summary") return "summary";
121
35
  return "off";
122
36
  }
123
37
  /** Resolves SSE stream debug verbosity from `OPENCLAW_DEBUG_SSE`. */
124
38
  function resolveModelSseDebugMode(env = process.env) {
125
- const normalized = normalizeEnv(env.OPENCLAW_DEBUG_SSE);
39
+ const normalized = normalizeLowercaseStringOrEmpty(env.OPENCLAW_DEBUG_SSE);
126
40
  if (normalized === "peek") return "peek";
127
41
  if (normalized === "events" || isTruthyEnv(normalized)) return "events";
128
42
  return "off";
@@ -143,173 +57,6 @@ function emitModelTransportDebug(log, message) {
143
57
  log.debug(message);
144
58
  }
145
59
  //#endregion
146
- //#region packages/normalization-core/src/string-normalization.ts
147
- /** Coerces entries to strings, trims them, and drops empty results. */
148
- function normalizeStringEntries(list) {
149
- return (list ?? []).map((entry) => normalizeOptionalString(String(entry)) ?? "").filter(Boolean);
150
- }
151
- /** Returns first-seen unique values while preserving insertion order. */
152
- function uniqueValues(values) {
153
- return [...new Set(values)];
154
- }
155
- /** Returns first-seen unique strings while preserving insertion order. */
156
- function uniqueStrings(values) {
157
- return uniqueValues(values);
158
- }
159
- //#endregion
160
- //#region packages/ai/src/providers/openai-reasoning-effort.ts
161
- /**
162
- * OpenAI-compatible reasoning-effort normalization. Different GPT families
163
- * expose different accepted effort enums, so callers map requested values here
164
- * before constructing provider payloads.
165
- */
166
- const GPT_5_REASONING_EFFORTS = [
167
- "minimal",
168
- "low",
169
- "medium",
170
- "high"
171
- ];
172
- const GPT_51_REASONING_EFFORTS = [
173
- "none",
174
- "low",
175
- "medium",
176
- "high"
177
- ];
178
- const GPT_52_REASONING_EFFORTS = [
179
- "none",
180
- "low",
181
- "medium",
182
- "high",
183
- "xhigh"
184
- ];
185
- const GPT_56_REASONING_EFFORTS = [
186
- "none",
187
- "low",
188
- "medium",
189
- "high",
190
- "xhigh",
191
- "max"
192
- ];
193
- const GPT_CODEX_REASONING_EFFORTS = [
194
- "low",
195
- "medium",
196
- "high",
197
- "xhigh"
198
- ];
199
- const GPT_PRO_REASONING_EFFORTS = [
200
- "medium",
201
- "high",
202
- "xhigh"
203
- ];
204
- const GPT_5_PRO_REASONING_EFFORTS = ["high"];
205
- const GPT_51_CODEX_MAX_REASONING_EFFORTS = [
206
- "none",
207
- "medium",
208
- "high",
209
- "xhigh"
210
- ];
211
- const GPT_51_CODEX_MINI_REASONING_EFFORTS = ["medium"];
212
- const GENERIC_REASONING_EFFORTS = [
213
- "low",
214
- "medium",
215
- "high"
216
- ];
217
- const CANONICAL_REASONING_EFFORTS = /* @__PURE__ */ new Set([
218
- "none",
219
- "minimal",
220
- "low",
221
- "medium",
222
- "high",
223
- "xhigh",
224
- "max",
225
- "off"
226
- ]);
227
- function normalizeModelId(id) {
228
- return normalizeLowercaseStringOrEmpty(id ?? "").replace(/-\d{4}-\d{2}-\d{2}$/u, "");
229
- }
230
- /** Return whether a model is the GPT-5.4 mini family. */
231
- function isOpenAIGpt54MiniModel(model) {
232
- const id = normalizeModelId(typeof model.id === "string" ? model.id : void 0);
233
- return /^gpt-5\.4-mini(?:-|$)/u.test(id);
234
- }
235
- /** Return whether a model is the GPT-5.5 family. */
236
- function isOpenAIGpt55Model(model) {
237
- const id = normalizeModelId(typeof model.id === "string" ? model.id : void 0);
238
- const name = normalizeModelId(typeof model.name === "string" ? model.name : void 0);
239
- return /^gpt-5\.5(?:-|$)/u.test(id) || /^gpt-5\.5(?:\s|\(|-|$)/u.test(name);
240
- }
241
- /** Return whether a model is the GPT-5.6 family. */
242
- function isOpenAIGpt56Model(model) {
243
- const id = normalizeModelId(typeof model.id === "string" ? model.id : void 0);
244
- const name = normalizeModelId(typeof model.name === "string" ? model.name : void 0);
245
- return /^gpt-5\.6(?:-|$)/u.test(id) || /^gpt-5\.6(?:\s|\(|-|$)/u.test(name);
246
- }
247
- /** Normalize user-facing reasoning effort names to API effort names. */
248
- function normalizeOpenAIReasoningEffort(effort) {
249
- const trimmed = effort.trim();
250
- const folded = trimmed.toLowerCase();
251
- return CANONICAL_REASONING_EFFORTS.has(folded) ? folded : trimmed;
252
- }
253
- function readCompatReasoningEfforts(compat) {
254
- if (!compat || typeof compat !== "object") return;
255
- if (compat.supportsReasoningEffort === false) return [];
256
- const raw = compat.supportedReasoningEfforts;
257
- if (!Array.isArray(raw)) return;
258
- const supported = uniqueStrings(normalizeStringEntries(raw.filter((value) => typeof value === "string")));
259
- return supported.length > 0 ? supported : void 0;
260
- }
261
- function isDisabledReasoningEffort(effort) {
262
- return effort === "none" || effort === "off";
263
- }
264
- /** Resolve the reasoning efforts accepted by a specific OpenAI-compatible model. */
265
- function resolveOpenAISupportedReasoningEfforts(model) {
266
- const compatEfforts = readCompatReasoningEfforts(model.compat);
267
- if (compatEfforts) return compatEfforts;
268
- const id = normalizeModelId(typeof model.id === "string" ? model.id : void 0);
269
- if (/^gpt-5\.6(?:-|$)/u.test(id)) return GPT_56_REASONING_EFFORTS;
270
- if (id === "gpt-5.1-codex-mini") return GPT_51_CODEX_MINI_REASONING_EFFORTS;
271
- if (id === "gpt-5.1-codex-max") return GPT_51_CODEX_MAX_REASONING_EFFORTS;
272
- if (/^gpt-5(?:\.\d+)?-codex(?:-|$)/u.test(id)) return GPT_CODEX_REASONING_EFFORTS;
273
- if (id === "gpt-5-pro") return GPT_5_PRO_REASONING_EFFORTS;
274
- if (/^gpt-5\.[2-9](?:\.\d+)?-pro(?:-|$)/u.test(id)) return GPT_PRO_REASONING_EFFORTS;
275
- if (/^gpt-5\.[2-9](?:\.\d+)?(?:-|$)/u.test(id)) return GPT_52_REASONING_EFFORTS;
276
- if (/^gpt-5\.1(?:-|$)/u.test(id)) return GPT_51_REASONING_EFFORTS;
277
- if (/^gpt-5(?:-|$)/u.test(id)) return GPT_5_REASONING_EFFORTS;
278
- return GENERIC_REASONING_EFFORTS;
279
- }
280
- /**
281
- * Return whether a model accepts the temperature parameter. The GPT-5.6
282
- * family rejects it with a 400; catalog compat can override per model.
283
- */
284
- function supportsOpenAITemperature(model) {
285
- const compat = model.compat;
286
- if (compat && typeof compat === "object") {
287
- const declared = compat.supportsTemperature;
288
- if (typeof declared === "boolean") return declared;
289
- }
290
- const id = normalizeModelId(typeof model.id === "string" ? model.id : void 0);
291
- return !/^gpt-5\.6(?:-|$)/u.test(id);
292
- }
293
- /** Return whether a model accepts a requested reasoning effort. */
294
- function supportsOpenAIReasoningEffort(model, effort) {
295
- return resolveOpenAISupportedReasoningEfforts(model).includes(normalizeOpenAIReasoningEffort(effort));
296
- }
297
- /** Resolve a requested reasoning effort to the closest value supported by the model. */
298
- function resolveOpenAIReasoningEffortForModel(params) {
299
- const requested = normalizeOpenAIReasoningEffort(params.effort);
300
- const mapped = params.fallbackMap?.[requested] ?? (params.fallbackMap && CANONICAL_REASONING_EFFORTS.has(requested) ? Object.entries(params.fallbackMap).find(([effort]) => normalizeOpenAIReasoningEffort(effort) === requested)?.[1] : void 0);
301
- const normalized = mapped === void 0 ? requested : mapped.trim();
302
- const supported = resolveOpenAISupportedReasoningEfforts(params.model);
303
- if (supported.includes(normalized)) return normalized;
304
- if (requested === "off" && supported.includes("none")) return "none";
305
- if (isDisabledReasoningEffort(requested) || isDisabledReasoningEffort(normalized)) return;
306
- if (requested === "minimal" && supported.includes("low")) return "low";
307
- if ((requested === "minimal" || requested === "low") && supported.includes("medium")) return "medium";
308
- if (requested === "xhigh" && supported.includes("high")) return "high";
309
- if (requested === "max" && supported.includes("xhigh")) return "xhigh";
310
- return supported.find((effort) => !isDisabledReasoningEffort(normalizeOpenAIReasoningEffort(effort)));
311
- }
312
- //#endregion
313
60
  //#region packages/ai/src/providers/clean-for-gemini.ts
314
61
  const GEMINI_UNSUPPORTED_SCHEMA_KEYWORDS = /* @__PURE__ */ new Set([
315
62
  "patternProperties",
@@ -431,8 +178,8 @@ function simplifyUnionVariants(params) {
431
178
  };
432
179
  copySchemaMeta$1(obj, result);
433
180
  return {
434
- variants: nonNullVariants,
435
- simplified: result
181
+ kind: "simplified",
182
+ value: result
436
183
  };
437
184
  }
438
185
  if (stripped && nonNullVariants.length === 1) {
@@ -441,16 +188,19 @@ function simplifyUnionVariants(params) {
441
188
  const result = { ...lone };
442
189
  copySchemaMeta$1(obj, result);
443
190
  return {
444
- variants: nonNullVariants,
445
- simplified: result
191
+ kind: "simplified",
192
+ value: result
446
193
  };
447
194
  }
448
195
  return {
449
- variants: nonNullVariants,
450
- simplified: lone
196
+ kind: "simplified",
197
+ value: lone
451
198
  };
452
199
  }
453
- return { variants: stripped ? nonNullVariants : variants };
200
+ return {
201
+ kind: "variants",
202
+ value: stripped ? nonNullVariants : variants
203
+ };
454
204
  }
455
205
  function sanitizeRequiredFields(schema) {
456
206
  if (!Array.isArray(schema.required)) return schema;
@@ -495,16 +245,16 @@ function cleanSchemaForGeminiWithDefs(schema, defs, refStack) {
495
245
  obj,
496
246
  variants: cleanedAnyOf ?? []
497
247
  });
498
- cleanedAnyOf = simplified.variants;
499
- if ("simplified" in simplified) return simplified.simplified;
248
+ if (simplified.kind === "simplified") return simplified.value;
249
+ cleanedAnyOf = simplified.value;
500
250
  }
501
251
  if (hasOneOf) {
502
252
  const simplified = simplifyUnionVariants({
503
253
  obj,
504
254
  variants: cleanedOneOf ?? []
505
255
  });
506
- cleanedOneOf = simplified.variants;
507
- if ("simplified" in simplified) return simplified.simplified;
256
+ if (simplified.kind === "simplified") return simplified.value;
257
+ cleanedOneOf = simplified.value;
508
258
  }
509
259
  const cleaned = {};
510
260
  for (const [key, value] of Object.entries(obj)) {
@@ -608,9 +358,6 @@ const SCHEMA_CHILD_KEYS = /* @__PURE__ */ new Set([
608
358
  "unevaluatedItems",
609
359
  "unevaluatedProperties"
610
360
  ]);
611
- function isSchemaRecord(value) {
612
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
613
- }
614
361
  function cleanSchemaNode(node) {
615
362
  if (Array.isArray(node)) {
616
363
  let changed = false;
@@ -621,7 +368,7 @@ function cleanSchemaNode(node) {
621
368
  });
622
369
  return changed ? entries : node;
623
370
  }
624
- if (!isSchemaRecord(node)) return node;
371
+ if (!isRecord(node)) return node;
625
372
  let changed = false;
626
373
  const cleaned = {};
627
374
  for (const [key, value] of Object.entries(node)) {
@@ -634,7 +381,7 @@ function cleanSchemaNode(node) {
634
381
  continue;
635
382
  }
636
383
  let next = value;
637
- if (SCHEMA_MAP_KEYS$2.has(key) && isSchemaRecord(value)) {
384
+ if (SCHEMA_MAP_KEYS$2.has(key) && isRecord(value)) {
638
385
  let mapChanged = false;
639
386
  next = Object.fromEntries(Object.entries(value).map(([childKey, childValue]) => {
640
387
  const cleanedChild = cleanSchemaNode(childValue);
@@ -653,10 +400,10 @@ function collectSchemaViolations(node, path, violations) {
653
400
  node.forEach((entry, index) => collectSchemaViolations(entry, `${path}[${index}]`, violations));
654
401
  return;
655
402
  }
656
- if (!isSchemaRecord(node)) return;
403
+ if (!isRecord(node)) return;
657
404
  if ("pattern" in node) violations.push(`${path}.pattern`);
658
405
  if (typeof node.maxLength === "number" && node.maxLength >= 2e3) violations.push(`${path}.maxLength`);
659
- for (const [key, value] of Object.entries(node)) if (SCHEMA_MAP_KEYS$2.has(key) && isSchemaRecord(value)) for (const [childKey, childValue] of Object.entries(value)) collectSchemaViolations(childValue, `${path}.${key}.${childKey}`, violations);
406
+ for (const [key, value] of Object.entries(node)) if (SCHEMA_MAP_KEYS$2.has(key) && isRecord(value)) for (const [childKey, childValue] of Object.entries(value)) collectSchemaViolations(childValue, `${path}.${key}.${childKey}`, violations);
660
407
  else if (SCHEMA_CHILD_KEYS.has(key)) collectSchemaViolations(value, `${path}.${key}`, violations);
661
408
  }
662
409
  /** Removes JSON Schema constraints that llama.cpp cannot compile into GBNF. */
@@ -1458,7 +1205,7 @@ function findOpenAIStrictSchemaViolations(schema, path, options) {
1458
1205
  * Caches normalized object inputs by provider compatibility so repeated inventory builds preserve identity.
1459
1206
  */
1460
1207
  const MAX_STRICT_SCHEMA_CACHE_ENTRIES_PER_SCHEMA = 8;
1461
- let strictOpenAISchemaCache = /* @__PURE__ */ new WeakMap();
1208
+ const strictOpenAISchemaCache = /* @__PURE__ */ new WeakMap();
1462
1209
  function resolveToolSchemaModelCompat(compat) {
1463
1210
  if (!compat) return;
1464
1211
  const unsupportedToolSchemaKeywords = Array.isArray(compat.unsupportedToolSchemaKeywords) ? compat.unsupportedToolSchemaKeywords.filter((keyword) => typeof keyword === "string") : [];
@@ -1483,9 +1230,6 @@ function rememberStrictOpenAISchema(schema, key, value) {
1483
1230
  }, ...entries.filter((entry) => entry.key !== key)].slice(0, MAX_STRICT_SCHEMA_CACHE_ENTRIES_PER_SCHEMA));
1484
1231
  return value;
1485
1232
  }
1486
- function clearOpenAIToolSchemaCacheForTest() {
1487
- strictOpenAISchemaCache = /* @__PURE__ */ new WeakMap();
1488
- }
1489
1233
  /** Normalizes a tool parameter schema into the OpenAI strict JSON-schema subset. */
1490
1234
  function normalizeStrictOpenAIJsonSchema(schema, modelCompat) {
1491
1235
  const schemaInput = schema ?? {};
@@ -1584,337 +1328,197 @@ function resolveReplayableResponsesMessageId(params) {
1584
1328
  if (!params.textSignatureId) return params.fallbackOrdinal === 0 ? params.fallbackId : `${params.fallbackId}_${params.fallbackOrdinal}`;
1585
1329
  return params.previousReplayItemWasReasoning ? params.textSignatureId : void 0;
1586
1330
  }
1587
- const OPENAI_CODEX_RESPONSES_DEFAULT_INSTRUCTIONS = "Follow the user request.";
1588
- const AZURE_RESPONSES_FIRST_EVENT_TIMEOUT_MS = 3e4;
1589
- const RESPONSE_FAILED_NO_DETAILS_MESSAGE = "Unknown error (no error details in response)";
1590
- const OPENAI_RESPONSES_REASONING_REPLAY_META_KEY = "__openclaw_replay";
1591
- const OPENAI_RESPONSES_REASONING_REPLAY_BLOCK_META_KEY = "openclawReasoningReplay";
1592
- const PROMPT_OBSERVER = Symbol("openaiResponsesPromptObserver");
1593
- const responsesPromptObserver = {
1594
- set(options, observer) {
1595
- Reflect.set(options, PROMPT_OBSERVER, observer);
1596
- },
1597
- get(options) {
1598
- return Reflect.get(options, PROMPT_OBSERVER);
1599
- },
1600
- copy(source, target) {
1601
- const observer = source && responsesPromptObserver.get(source);
1602
- if (observer) responsesPromptObserver.set(target, observer);
1603
- }
1604
- };
1605
1331
  //#endregion
1606
- //#region packages/ai/src/transports/openai-responses-debug.ts
1607
- function stringifyUnknown(value, fallback = "") {
1608
- if (typeof value === "string") return value;
1609
- if (typeof value === "number" || typeof value === "boolean") return String(value);
1610
- return fallback;
1332
+ //#region packages/ai/src/transports/openai-responses-compaction-replay.ts
1333
+ const OPENAI_RESPONSES_COMPACTION_SUPPRESSION_TYPE = "openai-responses-compaction-suppression";
1334
+ const OPENAI_RESPONSES_COMPACTION_SUPPRESSION_DATA = "rejected";
1335
+ function hashOptionalReplayContextValue(value) {
1336
+ const normalized = value?.trim();
1337
+ return normalized ? shortHash(normalized) : void 0;
1611
1338
  }
1612
- function getServiceTierCostMultiplier(serviceTier) {
1613
- switch (serviceTier) {
1614
- case "flex": return .5;
1615
- case "priority": return 2;
1616
- default: return 1;
1617
- }
1339
+ function buildOpenAIResponsesReplayContext(model, options) {
1340
+ return {
1341
+ provider: model.provider,
1342
+ api: model.api,
1343
+ model: model.id,
1344
+ baseUrlHash: hashOptionalReplayContextValue(model.baseUrl),
1345
+ sessionHash: hashOptionalReplayContextValue(options?.sessionId),
1346
+ authProfileHash: hashOptionalReplayContextValue(options?.authProfileId)
1347
+ };
1618
1348
  }
1619
- function applyServiceTierPricing(usage, serviceTier) {
1620
- const multiplier = getServiceTierCostMultiplier(serviceTier);
1621
- if (multiplier === 1) return;
1622
- usage.cost.input *= multiplier;
1623
- usage.cost.output *= multiplier;
1624
- usage.cost.cacheRead *= multiplier;
1625
- usage.cost.cacheWrite *= multiplier;
1626
- usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
1349
+ function isOpenAIResponsesReplayContext(value) {
1350
+ if (!isRecord(value)) return false;
1351
+ return typeof value.provider === "string" && typeof value.api === "string" && typeof value.model === "string" && (value.baseUrlHash === void 0 || typeof value.baseUrlHash === "string") && (value.sessionHash === void 0 || typeof value.sessionHash === "string") && (value.authProfileHash === void 0 || typeof value.authProfileHash === "string");
1627
1352
  }
1628
- function safeDebugValue(value) {
1629
- if (typeof value === "string") return value;
1630
- if (typeof value === "number" || typeof value === "boolean") return String(value);
1631
- if (value === null) return "null";
1632
- if (value === void 0) return "undefined";
1633
- return Array.isArray(value) ? "array" : typeof value;
1353
+ function isOpenAIResponsesCompactionState(state) {
1354
+ if (typeof state.baseUrlHash !== "string" || state.v !== 1) return false;
1355
+ if (state.type === OPENAI_RESPONSES_COMPACTION_SUPPRESSION_TYPE) return state.data === OPENAI_RESPONSES_COMPACTION_SUPPRESSION_DATA;
1356
+ if (state.type === "openai-responses-retained-compaction") return typeof state.data === "string" && state.data.length > 0 && (state.id === void 0 || typeof state.id === "string") && state.replayIndex === void 0;
1357
+ return state.type === "openai-responses-compaction" && typeof state.data === "string" && state.data.length > 0 && (state.id === void 0 || typeof state.id === "string") && (state.replayIndex === void 0 || typeof state.replayIndex === "number" && Number.isSafeInteger(state.replayIndex) && state.replayIndex >= 0);
1634
1358
  }
1635
- function responseInputTextChars(input) {
1636
- if (typeof input === "string") return input.length;
1637
- if (Array.isArray(input)) return input.reduce((total, item) => total + responseInputTextChars(item), 0);
1638
- if (!input || typeof input !== "object") return 0;
1639
- const record = input;
1640
- let total = 0;
1641
- if (typeof record.text === "string") total += record.text.length;
1642
- if (typeof record.content === "string") total += record.content.length;
1643
- else if (Array.isArray(record.content)) total += responseInputTextChars(record.content);
1644
- return total;
1359
+ function readOpenAIResponsesCompactionReplayState(value) {
1360
+ return isRecord(value) && isOpenAIResponsesReplayContext(value) && isOpenAIResponsesCompactionState(value) ? value : void 0;
1645
1361
  }
1646
- function responseInputRoles(input) {
1647
- if (!Array.isArray(input)) return "";
1648
- const roles = /* @__PURE__ */ new Set();
1649
- for (const item of input) if (item && typeof item === "object") {
1650
- const role = item.role;
1651
- if (typeof role === "string" && role.trim()) roles.add(role.trim());
1652
- }
1653
- return [...roles].toSorted().join(",");
1362
+ function openAIResponsesReplayContextMatches(state, context) {
1363
+ return state.provider === context.provider && state.api === context.api && state.model === context.model && state.baseUrlHash === context.baseUrlHash && state.sessionHash === context.sessionHash && state.authProfileHash === context.authProfileHash;
1654
1364
  }
1655
- function readToolPayloadField(record, field) {
1656
- try {
1657
- return record[field];
1658
- } catch {
1365
+ function captureOpenAIResponsesCompaction(output, item, boundary, model, captureMetadata) {
1366
+ const metadata = captureMetadata ?? buildOpenAIResponsesReasoningReplayMetadata(model);
1367
+ if (!item.encrypted_content) return;
1368
+ if (!metadata?.baseUrlHash) {
1369
+ log.debug("[responses] skipping compaction capture: missing base URL hash");
1659
1370
  return;
1660
1371
  }
1372
+ const currentReplay = readOpenAIResponsesCompactionReplayState(output.providerReplay);
1373
+ if (typeof boundary === "number" && currentReplay?.type === "openai-responses-compaction" && (currentReplay.replayIndex ?? -1) > boundary) return;
1374
+ output.providerReplay = {
1375
+ v: 1,
1376
+ type: boundary === "retained-users" ? OPENAI_RESPONSES_RETAINED_COMPACTION_REPLAY_TYPE : OPENAI_RESPONSES_COMPACTION_REPLAY_TYPE,
1377
+ ...item.id ? { id: item.id } : {},
1378
+ data: item.encrypted_content,
1379
+ ...typeof boundary === "number" ? { replayIndex: boundary } : {},
1380
+ provider: metadata.provider,
1381
+ api: metadata.api,
1382
+ model: metadata.model,
1383
+ baseUrlHash: metadata.baseUrlHash,
1384
+ ...metadata.sessionHash ? { sessionHash: metadata.sessionHash } : {},
1385
+ ...metadata.authProfileHash ? { authProfileHash: metadata.authProfileHash } : {}
1386
+ };
1661
1387
  }
1662
- function readResponsesToolDisplayName(tool) {
1663
- if (!tool || typeof tool !== "object") return "";
1664
- const record = tool;
1665
- const name = readToolPayloadField(record, "name");
1666
- if (typeof name === "string") return name;
1667
- const fn = readToolPayloadField(record, "function");
1668
- if (fn && typeof fn === "object") {
1669
- const fnName = readToolPayloadField(fn, "name");
1670
- if (typeof fnName === "string") return fnName;
1671
- }
1672
- const type = readToolPayloadField(record, "type");
1673
- return typeof type === "string" && type !== "function" ? type : "";
1674
- }
1675
- function summarizeResponsesTools(tools) {
1676
- if (!Array.isArray(tools)) return "count=0";
1677
- const names = tools.map(readResponsesToolDisplayName).filter(Boolean);
1678
- const mode = resolveModelPayloadDebugMode();
1679
- const maxNames = mode === "tools" || mode === "full-redacted" ? names.length : 12;
1680
- const label = maxNames >= names.length ? "names" : "sample";
1681
- const shown = names.slice(0, maxNames).join(",");
1682
- return `count=${tools.length}${shown ? ` ${label}=${shown}` : ""}`;
1388
+ function suppressOpenAIResponsesCompaction(output, model, options, rejectedCheckpoint) {
1389
+ const context = buildOpenAIResponsesReplayContext(model, options);
1390
+ if (!context.baseUrlHash) return;
1391
+ output.providerReplay = {
1392
+ v: 1,
1393
+ type: OPENAI_RESPONSES_COMPACTION_SUPPRESSION_TYPE,
1394
+ data: OPENAI_RESPONSES_COMPACTION_SUPPRESSION_DATA,
1395
+ ...context,
1396
+ baseUrlHash: context.baseUrlHash
1397
+ };
1398
+ if (rejectedCheckpoint) options?.onCompactionRejected?.(rejectedCheckpoint);
1683
1399
  }
1684
- function stringifyRedactedPayload(value) {
1685
- try {
1686
- const encoded = JSON.stringify(value);
1687
- if (!encoded) return "<empty>";
1688
- const redacted = redactSensitiveText(encoded, { mode: "tools" });
1689
- return redacted.length > 8e3 ? `${truncateUtf16Safe(redacted, 8e3)}…<truncated>` : redacted;
1690
- } catch {
1691
- return "<unserializable>";
1692
- }
1400
+ function createCompactionTracker(output, model, options) {
1401
+ const replayIndexes = /* @__PURE__ */ new Map();
1402
+ return {
1403
+ added(item, replayIndex) {
1404
+ if (item.type === "compaction" && item.id) replayIndexes.set(item.id, replayIndex);
1405
+ },
1406
+ completed(item, fallbackReplayIndex) {
1407
+ if (item.type !== "compaction" || !item.encrypted_content) return;
1408
+ captureOpenAIResponsesCompaction(output, {
1409
+ type: "compaction",
1410
+ ...item.id ? { id: item.id } : {},
1411
+ encrypted_content: item.encrypted_content
1412
+ }, (item.id ? replayIndexes.get(item.id) : void 0) ?? fallbackReplayIndex, model, options?.reasoningReplayMetadata);
1413
+ if (item.id) replayIndexes.delete(item.id);
1414
+ }
1415
+ };
1693
1416
  }
1694
- function stringifyRedactedEvent(value) {
1695
- const redacted = stringifyRedactedPayload(value);
1696
- return redacted.length > 2e3 ? `${truncateUtf16Safe(redacted, 2e3)}…<truncated>` : redacted;
1417
+ function isSafeResponsesReplayItemId(id) {
1418
+ return typeof id === "string" && id.length > 0 && id.length <= 64;
1697
1419
  }
1698
- const RESPONSE_FAILED_FAILURE_FIELD_KEYS = [
1699
- "error",
1700
- "incomplete_details",
1701
- "status_details",
1702
- "failure_reason",
1703
- "last_error",
1704
- "provider_error",
1705
- "error_details"
1706
- ];
1707
- function readResponseFailedString(record, key) {
1708
- return stringifyUnknown(record?.[key]);
1420
+ function resolveNewestOpenAIResponsesCompactionReplay(messages, model, options) {
1421
+ const context = buildOpenAIResponsesReplayContext(model, options);
1422
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
1423
+ const message = messages[index];
1424
+ if (message?.role !== "assistant") continue;
1425
+ const replay = readOpenAIResponsesCompactionReplayState(message.providerReplay);
1426
+ if (replay?.type === OPENAI_RESPONSES_COMPACTION_SUPPRESSION_TYPE) {
1427
+ if (openAIResponsesReplayContextMatches(replay, context)) return;
1428
+ continue;
1429
+ }
1430
+ if (replay?.type !== "openai-responses-compaction" && replay?.type !== "openai-responses-retained-compaction") {
1431
+ if (message.providerReplay?.type === "openai-responses-compaction" || message.providerReplay?.type === "openai-responses-retained-compaction") return;
1432
+ continue;
1433
+ }
1434
+ if (!openAIResponsesReplayContextMatches(replay, context)) return;
1435
+ return {
1436
+ owner: message,
1437
+ item: {
1438
+ type: "compaction",
1439
+ ...isSafeResponsesReplayItemId(replay.id) ? { id: replay.id } : {},
1440
+ encrypted_content: replay.data
1441
+ },
1442
+ ...replay.type === "openai-responses-retained-compaction" ? { mode: "retained-users" } : {
1443
+ mode: "compacted-prefix",
1444
+ replayIndex: replay.replayIndex ?? 0
1445
+ }
1446
+ };
1447
+ }
1709
1448
  }
1710
- function buildResponsesFailedEventSummary(message, responseId, observation) {
1711
- const summary = { message };
1712
- if (responseId) summary.responseId = responseId;
1713
- if (observation) summary.observation = observation;
1714
- return summary;
1449
+ function buildOpenAIResponsesCompactionReplayPlan(messages, model, options) {
1450
+ if (options?.mode === "full-history") return {
1451
+ messages,
1452
+ preserveUnframedToolResults: false
1453
+ };
1454
+ const compaction = resolveNewestOpenAIResponsesCompactionReplay(messages, model, options);
1455
+ if (!compaction) return {
1456
+ messages,
1457
+ preserveUnframedToolResults: false
1458
+ };
1459
+ const ownerIndex = messages.indexOf(compaction.owner);
1460
+ const collectRetainedUserMessages = (prefix) => {
1461
+ const previous = resolveNewestOpenAIResponsesCompactionReplay(prefix, model, options);
1462
+ if (!previous) return prefix.filter((message) => message.role === "user");
1463
+ const previousOwnerIndex = prefix.indexOf(previous.owner);
1464
+ const laterUsers = prefix.slice(previousOwnerIndex + 1).filter((message) => message.role === "user");
1465
+ return previous.mode === "retained-users" ? [...collectRetainedUserMessages(prefix.slice(0, previousOwnerIndex)), ...laterUsers] : laterUsers;
1466
+ };
1467
+ const retainedMessages = compaction.mode === "retained-users" ? collectRetainedUserMessages(messages.slice(0, ownerIndex)) : void 0;
1468
+ return {
1469
+ messages: [{
1470
+ ...compaction.owner,
1471
+ content: compaction.mode === "retained-users" ? [] : compaction.owner.content.slice(compaction.replayIndex)
1472
+ }, ...messages.slice(ownerIndex + 1)],
1473
+ ...retainedMessages?.length ? { retainedMessages } : {},
1474
+ compaction: compaction.item,
1475
+ preserveUnframedToolResults: true
1476
+ };
1715
1477
  }
1716
- function isResponseFailedIdentifierKey(key) {
1717
- const normalized = key.replace(/[-_\s]/g, "").toLowerCase();
1718
- return normalized === "requestid" || normalized === "xrequestid" || normalized === "providerrequestid" || normalized === "providerresponseid" || normalized === "litellmrequestid" || normalized.includes("request") && normalized.endsWith("id") || normalized.includes("provider") && normalized.endsWith("id");
1478
+ function buildOpenAIResponsesReasoningReplayMetadata(model, options) {
1479
+ return {
1480
+ v: 1,
1481
+ source: "openai-responses",
1482
+ ...buildOpenAIResponsesReplayContext(model, options)
1483
+ };
1719
1484
  }
1720
- function collectResponseFailedIdentifierHashes(value, opts = {}) {
1721
- const path = opts.path ?? "";
1722
- const depth = opts.depth ?? 0;
1723
- const identifierKey = opts.identifierKey ?? "";
1724
- const out = opts.out ?? [];
1725
- const seen = opts.seen ?? /* @__PURE__ */ new WeakSet();
1726
- if (out.length >= 12 || depth > 4 || !value || typeof value !== "object") return out;
1727
- if (seen.has(value)) return out;
1728
- seen.add(value);
1485
+ //#endregion
1486
+ //#region packages/ai/src/transports/openai-responses-replay-messages-internal.ts
1487
+ function stripEncryptedReasoningContentFields(value) {
1488
+ if (!value || typeof value !== "object") return {
1489
+ value,
1490
+ changed: false
1491
+ };
1729
1492
  if (Array.isArray(value)) {
1730
- for (const [index, item] of value.entries()) {
1731
- if (index >= 8 || out.length >= 12) break;
1732
- const itemString = typeof item === "string" || typeof item === "number" ? String(item).trim() : "";
1733
- if (identifierKey && isResponseFailedIdentifierKey(identifierKey) && itemString) {
1734
- out.push(`${path}[${index}]=${redactIdentifier(itemString, { len: 12 })}`);
1735
- continue;
1736
- }
1737
- collectResponseFailedIdentifierHashes(item, {
1738
- path: `${path}[${index}]`,
1739
- depth: depth + 1,
1740
- identifierKey,
1741
- out,
1742
- seen
1743
- });
1744
- }
1745
- return out;
1493
+ let changed = false;
1494
+ const next = value.map((item) => {
1495
+ const stripped = stripEncryptedReasoningContentFields(item);
1496
+ changed ||= stripped.changed;
1497
+ return stripped.value;
1498
+ });
1499
+ return changed ? {
1500
+ value: next,
1501
+ changed: true
1502
+ } : {
1503
+ value,
1504
+ changed: false
1505
+ };
1746
1506
  }
1747
- for (const [key, child] of Object.entries(value)) {
1748
- if (out.length >= 12) break;
1749
- const childPath = path ? `${path}.${key}` : key;
1750
- const childString = typeof child === "string" || typeof child === "number" ? String(child).trim() : "";
1751
- if (isResponseFailedIdentifierKey(key) && childString) {
1752
- out.push(`${childPath}=${redactIdentifier(childString, { len: 12 })}`);
1507
+ const source = value;
1508
+ if (source.type === "compaction") return {
1509
+ value,
1510
+ changed: false
1511
+ };
1512
+ let changed = false;
1513
+ const next = {};
1514
+ for (const [key, child] of Object.entries(source)) {
1515
+ if (key === "encrypted_content") {
1516
+ changed = true;
1753
1517
  continue;
1754
1518
  }
1755
- collectResponseFailedIdentifierHashes(child, {
1756
- path: childPath,
1757
- depth: depth + 1,
1758
- identifierKey: isResponseFailedIdentifierKey(key) ? key : void 0,
1759
- out,
1760
- seen
1761
- });
1762
- }
1763
- return out;
1764
- }
1765
- function redactResponseFailedDiagnosticValue(value, opts = {}) {
1766
- const key = opts.key ?? "";
1767
- const depth = opts.depth ?? 0;
1768
- if (typeof value === "string" || typeof value === "number") return key && isResponseFailedIdentifierKey(key) ? redactIdentifier(String(value), { len: 12 }) : value;
1769
- if (depth > 6 || !value || typeof value !== "object") return value;
1770
- const seen = opts.seen ?? /* @__PURE__ */ new WeakSet();
1771
- if (seen.has(value)) return "<circular>";
1772
- seen.add(value);
1773
- if (Array.isArray(value)) return value.slice(0, 16).map((item) => redactResponseFailedDiagnosticValue(item, {
1774
- key,
1775
- depth: depth + 1,
1776
- seen
1777
- }));
1778
- const out = {};
1779
- for (const [childKey, child] of Object.entries(value)) out[childKey] = redactResponseFailedDiagnosticValue(child, {
1780
- key: childKey,
1781
- depth: depth + 1,
1782
- seen
1783
- });
1784
- return out;
1785
- }
1786
- function buildResponsesFailedFailureFields(response) {
1787
- if (!response) return {};
1788
- const fields = {};
1789
- for (const key of RESPONSE_FAILED_FAILURE_FIELD_KEYS) if (response[key] !== void 0 && response[key] !== null) fields[key] = response[key];
1790
- return fields;
1791
- }
1792
- function buildResponsesFailedNoDetailsObservation(event, model, response = isRecord(event.response) ? event.response : void 0) {
1793
- const failureFields = redactResponseFailedDiagnosticValue(buildResponsesFailedFailureFields(response));
1794
- const metadataKeys = isRecord(response?.metadata) ? Object.keys(response.metadata).toSorted() : [];
1795
- const responsePreview = {
1796
- id: readResponseFailedString(response, "id"),
1797
- status: readResponseFailedString(response, "status"),
1798
- model: readResponseFailedString(response, "model"),
1799
- object: readResponseFailedString(response, "object"),
1800
- failureFields,
1801
- metadataKeys
1802
- };
1803
- return {
1804
- event: "openai_responses_response_failed_without_details",
1805
- provider: model.provider,
1806
- api: model.api,
1807
- transportModel: model.id,
1808
- providerRuntimeFailureKind: "no_error_details",
1809
- responseId: responsePreview.id,
1810
- responseStatus: responsePreview.status,
1811
- responseModel: responsePreview.model,
1812
- responseObject: responsePreview.object,
1813
- metadataKeys,
1814
- requestIdHashes: collectResponseFailedIdentifierHashes(event),
1815
- failureFieldsPreview: stringifyRedactedEvent(failureFields),
1816
- responsePreview: stringifyRedactedEvent(responsePreview)
1817
- };
1818
- }
1819
- function summarizeResponsesFailedNoDetailsObservation(observation) {
1820
- const requestIds = observation.requestIdHashes.join(",");
1821
- const metadataKeys = observation.metadataKeys.join(",");
1822
- return `responseId=${safeDebugValue(observation.responseId || void 0)} responseStatus=${safeDebugValue(observation.responseStatus || void 0)} responseModel=${safeDebugValue(observation.responseModel || void 0)} requestIds=${requestIds || "none"} metadataKeys=${metadataKeys || "none"} failureFields=${observation.failureFieldsPreview}`;
1823
- }
1824
- function normalizeResponsesFailedEvent(event, model) {
1825
- const response = isRecord(event.response) ? event.response : void 0;
1826
- const responseId = readResponseFailedString(response, "id") || void 0;
1827
- const error = isRecord(response?.error) ? response.error : void 0;
1828
- if (error) {
1829
- const code = readResponseFailedString(error, "code").trim();
1830
- const message = readResponseFailedString(error, "message").trim();
1831
- if (code || message) return buildResponsesFailedEventSummary(`${code || "unknown"}: ${message || "no message"}`, responseId);
1832
- }
1833
- const incompleteReason = readResponseFailedString(isRecord(response?.incomplete_details) ? response.incomplete_details : void 0, "reason");
1834
- if (incompleteReason) return buildResponsesFailedEventSummary(`incomplete: ${incompleteReason}`, responseId);
1835
- return buildResponsesFailedEventSummary(RESPONSE_FAILED_NO_DETAILS_MESSAGE, responseId, buildResponsesFailedNoDetailsObservation(event, model, response));
1836
- }
1837
- function logResponsesFailedNoDetails(observation) {
1838
- log.warn(`[responses] response.failed missing error details provider=${observation.provider} api=${observation.api} model=${observation.transportModel} ` + summarizeResponsesFailedNoDetailsObservation(observation), observation);
1839
- }
1840
- function summarizeResponsesPayload(params) {
1841
- if (!params || typeof params !== "object") return "payload=non-object";
1842
- const record = params;
1843
- const input = record.input;
1844
- const reasoning = record.reasoning && typeof record.reasoning === "object" ? record.reasoning : void 0;
1845
- const text = record.text && typeof record.text === "object" ? record.text : void 0;
1846
- const parts = [
1847
- `fields=${Object.keys(record).toSorted().join(",")}`,
1848
- `model=${safeDebugValue(record.model)}`,
1849
- `stream=${safeDebugValue(record.stream)}`,
1850
- `inputItems=${Array.isArray(input) ? input.length : typeof input}`,
1851
- `inputRoles=${responseInputRoles(input) || "none"}`,
1852
- `inputTextChars=${responseInputTextChars(input)}`,
1853
- `tools=${summarizeResponsesTools(record.tools)}`,
1854
- `reasoningEffort=${safeDebugValue(reasoning?.effort)}`,
1855
- `reasoningSummary=${safeDebugValue(reasoning?.summary)}`,
1856
- `textVerbosity=${safeDebugValue(text?.verbosity)}`,
1857
- `serviceTier=${safeDebugValue(record.service_tier)}`,
1858
- `store=${safeDebugValue(record.store)}`,
1859
- `promptCacheKey=${record.prompt_cache_key === void 0 ? "absent" : "present"}`,
1860
- `metadataKeys=${record.metadata && typeof record.metadata === "object" ? Object.keys(record.metadata).toSorted().join(",") : "none"}`
1861
- ];
1862
- if (resolveModelPayloadDebugMode() === "full-redacted") parts.push(`payload=${stringifyRedactedPayload(record)}`);
1863
- return parts.join(" ");
1864
- }
1865
- function summarizeOpenAITransportError(error) {
1866
- if (!error || typeof error !== "object") return `type=${typeof error} message=${safeDebugValue(error)}`;
1867
- const record = error;
1868
- const cause = record.cause && typeof record.cause === "object" ? record.cause : void 0;
1869
- return [
1870
- `name=${safeDebugValue(record.name)}`,
1871
- `status=${safeDebugValue(record.status)}`,
1872
- `code=${safeDebugValue(record.code)}`,
1873
- `type=${safeDebugValue(record.type)}`,
1874
- `causeName=${safeDebugValue(cause?.name)}`,
1875
- `causeCode=${safeDebugValue(cause?.code)}`,
1876
- `message=${error instanceof Error ? error.message : safeDebugValue(error)}`
1877
- ].join(" ");
1878
- }
1879
- //#endregion
1880
- //#region packages/ai/src/transports/openai-responses-replay-internal.ts
1881
- function isInvalidEncryptedContentError(error) {
1882
- if (!error || typeof error !== "object") return false;
1883
- const record = error;
1884
- if (record.code === "invalid_encrypted_content" || record.code === "thinking_signature_invalid") return true;
1885
- const message = typeof record.message === "string" ? record.message : "";
1886
- return message.includes("invalid_encrypted_content") || message.includes("thinking_signature_invalid") || record.status === 400 && message.toLowerCase().includes("could not decrypt the provided encrypted_content");
1887
- }
1888
- function stripEncryptedContentFields(value) {
1889
- if (!value || typeof value !== "object") return {
1890
- value,
1891
- changed: false
1892
- };
1893
- if (Array.isArray(value)) {
1894
- let changed = false;
1895
- const next = value.map((item) => {
1896
- const stripped = stripEncryptedContentFields(item);
1897
- changed ||= stripped.changed;
1898
- return stripped.value;
1899
- });
1900
- return changed ? {
1901
- value: next,
1902
- changed: true
1903
- } : {
1904
- value,
1905
- changed: false
1906
- };
1907
- }
1908
- let changed = false;
1909
- const next = {};
1910
- for (const [key, child] of Object.entries(value)) {
1911
- if (key === "encrypted_content") {
1912
- changed = true;
1913
- continue;
1914
- }
1915
- const stripped = stripEncryptedContentFields(child);
1916
- changed ||= stripped.changed;
1917
- next[key] = stripped.value;
1519
+ const stripped = stripEncryptedReasoningContentFields(child);
1520
+ changed ||= stripped.changed;
1521
+ next[key] = stripped.value;
1918
1522
  }
1919
1523
  return changed ? {
1920
1524
  value: next,
@@ -1924,54 +1528,15 @@ function stripEncryptedContentFields(value) {
1924
1528
  changed: false
1925
1529
  };
1926
1530
  }
1927
- function stripResponsesRequestEncryptedContent(params) {
1928
- const stripped = stripEncryptedContentFields(params.input);
1929
- if (!stripped.changed) return params;
1930
- return {
1931
- ...params,
1932
- input: stripped.value
1933
- };
1934
- }
1935
- function hashOptionalReplayContextValue(value) {
1936
- const normalized = value?.trim();
1937
- return normalized ? shortHash(normalized) : void 0;
1938
- }
1939
- function buildOpenAIResponsesReplayContext(model, options) {
1940
- return {
1941
- provider: model.provider,
1942
- api: model.api,
1943
- model: model.id,
1944
- baseUrlHash: hashOptionalReplayContextValue(model.baseUrl),
1945
- sessionHash: hashOptionalReplayContextValue(options?.sessionId),
1946
- authProfileHash: hashOptionalReplayContextValue(options?.authProfileId)
1947
- };
1948
- }
1949
- function buildOpenAIResponsesReasoningReplayMetadata(model, options) {
1950
- return {
1951
- v: 1,
1952
- source: "openai-responses",
1953
- ...buildOpenAIResponsesReplayContext(model, options)
1954
- };
1955
- }
1956
- function tagOpenAIResponsesReasoningReplayItem(item, model, options) {
1957
- if (!("encrypted_content" in item)) return item;
1958
- return {
1959
- ...item,
1960
- [OPENAI_RESPONSES_REASONING_REPLAY_META_KEY]: buildOpenAIResponsesReasoningReplayMetadata(model, options)
1961
- };
1962
- }
1963
1531
  function isOpenAIResponsesReasoningReplayMetadata(value) {
1964
- if (!value || typeof value !== "object") return false;
1532
+ if (!isOpenAIResponsesReplayContext(value)) return false;
1965
1533
  const record = value;
1966
- return record.v === 1 && record.source === "openai-responses" && typeof record.provider === "string" && typeof record.api === "string" && typeof record.model === "string" && (record.baseUrlHash === void 0 || typeof record.baseUrlHash === "string") && (record.sessionHash === void 0 || typeof record.sessionHash === "string") && (record.authProfileHash === void 0 || typeof record.authProfileHash === "string");
1967
- }
1968
- function encryptedReasoningReplayMetadataMatches(metadata, context) {
1969
- if (!metadata) return false;
1970
- return metadata.provider === context.provider && metadata.api === context.api && metadata.model === context.model && metadata.baseUrlHash === context.baseUrlHash && metadata.sessionHash === context.sessionHash && metadata.authProfileHash === context.authProfileHash;
1534
+ return record.v === 1 && record.source === "openai-responses";
1971
1535
  }
1972
1536
  function readOpenAIResponsesReasoningReplayBlockMetadata(block) {
1537
+ if (!Object.hasOwn(block, "openclawReasoningReplay")) return;
1973
1538
  const value = block[OPENAI_RESPONSES_REASONING_REPLAY_BLOCK_META_KEY];
1974
- return isOpenAIResponsesReasoningReplayMetadata(value) ? value : void 0;
1539
+ return isOpenAIResponsesReasoningReplayMetadata(value) ? value : null;
1975
1540
  }
1976
1541
  function normalizeOpenAIResponsesReasoningReplayItem(item) {
1977
1542
  const record = item;
@@ -1981,49 +1546,20 @@ function normalizeOpenAIResponsesReasoningReplayItem(item) {
1981
1546
  summary: []
1982
1547
  };
1983
1548
  }
1984
- function prepareOpenAIResponsesReasoningItemForReplay(item, context, blockMetadata) {
1985
- const { [OPENAI_RESPONSES_REASONING_REPLAY_META_KEY]: rawMetadata, ...rest } = item;
1549
+ function prepareOpenAIResponsesReasoningItemForReplay(item, context, blockMetadata, options) {
1550
+ const record = item;
1551
+ const hasRawMetadata = Object.hasOwn(record, OPENAI_RESPONSES_REASONING_REPLAY_META_KEY);
1552
+ const { [OPENAI_RESPONSES_REASONING_REPLAY_META_KEY]: rawMetadata, ...rest } = record;
1986
1553
  if (!("encrypted_content" in rest)) return normalizeOpenAIResponsesReasoningReplayItem(rest);
1987
- if (encryptedReasoningReplayMetadataMatches(blockMetadata ?? (isOpenAIResponsesReasoningReplayMetadata(rawMetadata) ? rawMetadata : void 0), context)) return normalizeOpenAIResponsesReasoningReplayItem(rest);
1988
- return normalizeOpenAIResponsesReasoningReplayItem(stripEncryptedContentFields(rest).value);
1989
- }
1990
- async function createResponsesStreamWithEncryptedContentRetry(params) {
1991
- try {
1992
- params.observePrompt?.(params.request, {
1993
- egress: "responses-sdk",
1994
- payloadVariant: "initial"
1995
- });
1996
- const { data, response } = await params.client.responses.create(params.request, params.requestOptions).withResponse();
1997
- return {
1998
- stream: data,
1999
- response
2000
- };
2001
- } catch (error) {
2002
- const retryRequest = stripResponsesRequestEncryptedContent(params.request);
2003
- if (!isInvalidEncryptedContentError(error) || retryRequest === params.request) throw error;
2004
- log.warn(`[responses] retrying without encrypted reasoning content provider=${params.model.provider} api=${params.model.api} model=${params.model.id}`);
2005
- params.observePrompt?.(retryRequest, {
2006
- egress: "responses-sdk",
2007
- payloadVariant: "encrypted-content-retry"
2008
- });
2009
- const { data, response } = await params.client.responses.create(retryRequest, params.requestOptions).withResponse();
2010
- return {
2011
- stream: data,
2012
- response
2013
- };
2014
- }
2015
- }
2016
- function resolveAzureOpenAIApiVersion(env = process.env) {
2017
- return env.AZURE_OPENAI_API_VERSION?.trim() || "preview";
1554
+ const metadata = blockMetadata !== void 0 ? blockMetadata ?? void 0 : isOpenAIResponsesReasoningReplayMetadata(rawMetadata) ? rawMetadata : void 0;
1555
+ if (blockMetadata === void 0 && !hasRawMetadata && options?.preserveUnattributedEncryptedContent === true || metadata && openAIResponsesReplayContextMatches(metadata, context)) return normalizeOpenAIResponsesReasoningReplayItem(rest);
1556
+ return normalizeOpenAIResponsesReasoningReplayItem(stripEncryptedReasoningContentFields(rest).value);
2018
1557
  }
2019
1558
  function normalizeResponsesReplayItemId(id, prefix) {
2020
1559
  if (!id) return;
2021
1560
  if (id.length <= 64) return id;
2022
1561
  return `${prefix}_${shortHash(id)}`;
2023
1562
  }
2024
- function isSafeResponsesReplayItemId(id) {
2025
- return typeof id === "string" && id.length > 0 && id.length <= 64;
2026
- }
2027
1563
  function encodeTextSignatureV1(id, phase) {
2028
1564
  return JSON.stringify({
2029
1565
  v: 1,
@@ -2031,7 +1567,7 @@ function encodeTextSignatureV1(id, phase) {
2031
1567
  ...phase ? { phase } : {}
2032
1568
  });
2033
1569
  }
2034
- function parseTextSignature(signature) {
1570
+ function parseOpenAIResponsesTextSignature(signature) {
2035
1571
  if (!signature) return;
2036
1572
  if (signature.startsWith("{")) try {
2037
1573
  const parsed = JSON.parse(signature);
@@ -2054,8 +1590,34 @@ function buildResponsesInputMessage(role, content) {
2054
1590
  content
2055
1591
  };
2056
1592
  }
2057
- function convertResponsesMessages(model, context, allowedToolCallProviders, options) {
1593
+ function createOpenAIResponsesAssistantOutput(model, api = model.api) {
1594
+ return {
1595
+ role: "assistant",
1596
+ content: [],
1597
+ api,
1598
+ provider: model.provider,
1599
+ model: model.id,
1600
+ usage: {
1601
+ input: 0,
1602
+ output: 0,
1603
+ cacheRead: 0,
1604
+ cacheWrite: 0,
1605
+ totalTokens: 0,
1606
+ cost: {
1607
+ input: 0,
1608
+ output: 0,
1609
+ cacheRead: 0,
1610
+ cacheWrite: 0,
1611
+ total: 0
1612
+ }
1613
+ },
1614
+ stopReason: "stop",
1615
+ timestamp: Date.now()
1616
+ };
1617
+ }
1618
+ function convertResponsesMessagesWithStyle(model, context, allowedToolCallProviders, options, conversionStyle) {
2058
1619
  const messages = [];
1620
+ const providerStyle = conversionStyle === "provider";
2059
1621
  const shouldReplayReasoningItems = options?.replayReasoningItems ?? true;
2060
1622
  const shouldReplayResponsesItemIds = options?.replayResponsesItemIds ?? true;
2061
1623
  const replayContext = buildOpenAIResponsesReplayContext(model, {
@@ -2063,7 +1625,10 @@ function convertResponsesMessages(model, context, allowedToolCallProviders, opti
2063
1625
  authProfileId: options?.authProfileId
2064
1626
  });
2065
1627
  const shouldNormalizeSameModelToolCallIds = model.provider === "github-copilot";
2066
- const sanitizeIdPart = (part) => part.replace(/[^a-zA-Z0-9_-]/g, "_").replace(/_+$/, "");
1628
+ const sanitizeIdPart = (part) => {
1629
+ const sanitized = part.replace(/[^a-zA-Z0-9_-]/g, "_");
1630
+ return providerStyle ? sanitized : sanitized.replace(/_+$/, "");
1631
+ };
2067
1632
  const normalizeIdPart = (part) => {
2068
1633
  const sanitized = sanitizeIdPart(part);
2069
1634
  return (sanitized.length > 64 ? sanitized.slice(0, 64) : sanitized).replace(/_+$/, "");
@@ -2084,17 +1649,36 @@ function convertResponsesMessages(model, context, allowedToolCallProviders, opti
2084
1649
  const callId = id.slice(0, separatorIndex);
2085
1650
  const itemId = id.slice(separatorIndex + 1);
2086
1651
  const normalizedCallId = normalizeIdPart(callId);
2087
- let normalizedItemId = source.provider !== model.provider || source.api !== model.api ? buildForeignResponsesItemId(itemId) : model.provider === "github-copilot" ? buildSameProviderCopilotResponsesItemId(itemId) : normalizeIdPart(itemId);
1652
+ let normalizedItemId = source.provider !== model.provider || source.api !== model.api ? buildForeignResponsesItemId(itemId) : model.provider === "github-copilot" ? providerStyle ? normalizeIdPart(itemId) : buildSameProviderCopilotResponsesItemId(itemId) : normalizeIdPart(itemId);
2088
1653
  if (!normalizedItemId.startsWith("fc_")) normalizedItemId = normalizeIdPart(`fc_${normalizedItemId}`);
2089
1654
  return `${normalizedCallId}|${normalizedItemId}`;
2090
1655
  };
2091
- const transformedMessages = transformTransportMessages(context.messages, model, normalizeToolCallId, { normalizeSameModelToolCallIds: shouldNormalizeSameModelToolCallIds });
2092
- if ((options?.includeSystemPrompt ?? true) && context.systemPrompt) messages.push(buildResponsesInputMessage(model.reasoning && options?.supportsDeveloperRole !== false ? "developer" : "system", [{
1656
+ const replayPlan = buildOpenAIResponsesCompactionReplayPlan(context.messages, model, {
1657
+ sessionId: options?.sessionId,
1658
+ authProfileId: options?.authProfileId,
1659
+ mode: options?.replayMode
1660
+ });
1661
+ const transformMessages = (source) => providerStyle ? transformProviderMessages(source, model, normalizeToolCallId) : transformTransportMessages(source, model, normalizeToolCallId, {
1662
+ normalizeSameModelToolCallIds: shouldNormalizeSameModelToolCallIds,
1663
+ preserveUnframedToolResults: replayPlan.preserveUnframedToolResults
1664
+ });
1665
+ const transformedMessages = transformMessages(replayPlan.messages);
1666
+ const transformedRetainedMessages = replayPlan.retainedMessages ? transformMessages(replayPlan.retainedMessages) : [];
1667
+ if ((options?.includeSystemPrompt ?? true) && context.systemPrompt) messages.push(buildResponsesInputMessage(model.reasoning && (providerStyle ? model.compat?.supportsDeveloperRole !== false : options?.supportsDeveloperRole !== false) ? "developer" : "system", [{
2093
1668
  type: "input_text",
2094
1669
  text: sanitizeTransportPayloadText(stripSystemPromptCacheBoundary(context.systemPrompt))
2095
1670
  }]));
1671
+ const replayMessages = replayPlan.compaction ? [
1672
+ ...transformedRetainedMessages,
1673
+ replayPlan.compaction,
1674
+ ...transformedMessages
1675
+ ] : transformedMessages;
2096
1676
  let msgIndex = 0;
2097
- for (const msg of transformedMessages) {
1677
+ for (const msg of replayMessages) {
1678
+ if (!("role" in msg)) {
1679
+ messages.push(msg);
1680
+ continue;
1681
+ }
2098
1682
  if (msg.role === "user") if (typeof msg.content === "string") messages.push(buildResponsesInputMessage("user", [{
2099
1683
  type: "input_text",
2100
1684
  text: sanitizeTransportPayloadText(msg.content)
@@ -2107,8 +1691,9 @@ function convertResponsesMessages(model, context, allowedToolCallProviders, opti
2107
1691
  type: "input_image",
2108
1692
  detail: "auto",
2109
1693
  image_url: `data:${item.mimeType};base64,${item.data}`
2110
- }).filter((item) => model.input.includes("image") || item.type !== "input_image");
1694
+ }).filter((item) => providerStyle || model.input.includes("image") || item.type !== "input_image");
2111
1695
  if (content.length > 0) messages.push(buildResponsesInputMessage("user", content));
1696
+ else if (providerStyle) continue;
2112
1697
  }
2113
1698
  else if (msg.role === "assistant") {
2114
1699
  const output = [];
@@ -2116,15 +1701,22 @@ function convertResponsesMessages(model, context, allowedToolCallProviders, opti
2116
1701
  let previousReplayItemWasReasoning = false;
2117
1702
  const isDifferentModel = msg.model !== model.id && msg.provider === model.provider && msg.api === model.api;
2118
1703
  for (const block of msg.content) if (block.type === "thinking") {
2119
- if (shouldReplayReasoningItems && block.thinkingSignature && block.thinkingSignature.startsWith("{")) {
2120
- const replayableReasoningItem = prepareOpenAIResponsesReasoningItemForReplay(JSON.parse(block.thinkingSignature), replayContext, readOpenAIResponsesReasoningReplayBlockMetadata(block));
1704
+ if (shouldReplayReasoningItems && block.thinkingSignature && (providerStyle || block.thinkingSignature.startsWith("{"))) {
1705
+ let reasoningItem;
1706
+ try {
1707
+ reasoningItem = JSON.parse(block.thinkingSignature);
1708
+ } catch {
1709
+ continue;
1710
+ }
1711
+ if (!isRecord(reasoningItem) || reasoningItem.type !== "reasoning") continue;
1712
+ const replayableReasoningItem = prepareOpenAIResponsesReasoningItemForReplay(reasoningItem, replayContext, readOpenAIResponsesReasoningReplayBlockMetadata(isRecord(block) ? block : {}), providerStyle ? { preserveUnattributedEncryptedContent: true } : void 0);
2121
1713
  if (!shouldReplayResponsesItemIds) delete replayableReasoningItem.id;
2122
- if (shouldReplayResponsesItemIds && model.provider === "github-copilot" && !isSafeResponsesReplayItemId(replayableReasoningItem.id)) continue;
1714
+ if (shouldReplayResponsesItemIds && !providerStyle && model.provider === "github-copilot" && !isSafeResponsesReplayItemId(replayableReasoningItem.id)) continue;
2123
1715
  output.push(replayableReasoningItem);
2124
1716
  previousReplayItemWasReasoning = true;
2125
1717
  }
2126
1718
  } else if (block.type === "text") {
2127
- const textSignature = parseTextSignature(block.textSignature);
1719
+ const textSignature = parseOpenAIResponsesTextSignature(block.textSignature);
2128
1720
  let msgId = resolveReplayableResponsesMessageId({
2129
1721
  replayResponsesItemIds: shouldReplayResponsesItemIds,
2130
1722
  textSignatureId: textSignature?.id,
@@ -2158,11 +1750,12 @@ function convertResponsesMessages(model, context, allowedToolCallProviders, opti
2158
1750
  ...itemId ? { id: itemId } : {},
2159
1751
  call_id: callId,
2160
1752
  name: block.name,
2161
- arguments: typeof block.arguments === "string" ? block.arguments : JSON.stringify(block.arguments ?? {})
1753
+ arguments: providerStyle ? JSON.stringify(block.arguments) : typeof block.arguments === "string" ? block.arguments : JSON.stringify(block.arguments ?? {})
2162
1754
  });
2163
1755
  previousReplayItemWasReasoning = false;
2164
1756
  }
2165
1757
  if (output.length > 0) messages.push(...output);
1758
+ else if (providerStyle) continue;
2166
1759
  } else if (msg.role === "toolResult") {
2167
1760
  const textResult = extractToolResultText(msg.content);
2168
1761
  const sanitizedTextResult = sanitizeTransportPayloadText(textResult);
@@ -2191,6 +1784,123 @@ function convertResponsesMessages(model, context, allowedToolCallProviders, opti
2191
1784
  }
2192
1785
  return messages;
2193
1786
  }
1787
+ function convertResponsesMessages$1(model, context, allowedToolCallProviders, options) {
1788
+ return convertResponsesMessagesWithStyle(model, context, allowedToolCallProviders, options, "transport");
1789
+ }
1790
+ function convertProviderResponsesMessages(model, context, allowedToolCallProviders, options) {
1791
+ return convertResponsesMessagesWithStyle(model, context, allowedToolCallProviders, options, "provider");
1792
+ }
1793
+ //#endregion
1794
+ //#region packages/ai/src/transports/openai-responses-replay-internal.ts
1795
+ function isAsyncIterable(value) {
1796
+ return (typeof value === "object" && value !== null || typeof value === "function") && Symbol.asyncIterator in value;
1797
+ }
1798
+ function isInvalidEncryptedContentError(error) {
1799
+ if (!error || typeof error !== "object") return false;
1800
+ const record = error;
1801
+ if (record.code === "invalid_encrypted_content" || record.code === "thinking_signature_invalid") return true;
1802
+ const message = typeof record.message === "string" ? record.message : "";
1803
+ return message.includes("invalid_encrypted_content") || message.includes("thinking_signature_invalid") || record.status === 400 && message.toLowerCase().includes("could not decrypt the provided encrypted_content");
1804
+ }
1805
+ function isOrphanedFunctionCallOutputError(error) {
1806
+ if (!error || typeof error !== "object") return false;
1807
+ const record = error;
1808
+ const message = typeof record.message === "string" ? record.message : "";
1809
+ return /No tool call found for function call output with call_id [A-Za-z0-9_-]+/.test(message);
1810
+ }
1811
+ function commitResponsesEncryptedContentAttempt(attempt, commit) {
1812
+ if (attempt.kind === "compaction-stripped") commit(attempt.rejectedCompaction);
1813
+ }
1814
+ function stripResponsesRequestEncryptedReasoning(request) {
1815
+ const stripped = stripEncryptedReasoningContentFields(request.input);
1816
+ if (!stripped.changed) return request;
1817
+ return {
1818
+ ...request,
1819
+ input: stripped.value
1820
+ };
1821
+ }
1822
+ function stripResponsesRequestCompaction(request) {
1823
+ if (!Array.isArray(request.input)) return request;
1824
+ const input = request.input.filter((item) => !(item !== null && typeof item === "object" && item.type === "compaction"));
1825
+ return input.length === request.input.length ? request : {
1826
+ ...request,
1827
+ input
1828
+ };
1829
+ }
1830
+ function readOpenAIResponsesCompactionRejection(request) {
1831
+ if (!Array.isArray(request.input)) return;
1832
+ const item = request.input.find((candidate) => candidate !== null && typeof candidate === "object" && candidate.type === "compaction" && typeof candidate.encrypted_content === "string");
1833
+ return item ? {
1834
+ data: item.encrypted_content,
1835
+ ...typeof item.id === "string" ? { id: item.id } : {}
1836
+ } : void 0;
1837
+ }
1838
+ async function resolveNextResponsesEncryptedContentAttempt(attempt, error, options) {
1839
+ const orphanedFunctionOutput = isOrphanedFunctionCallOutputError(error);
1840
+ if (!isInvalidEncryptedContentError(error) && !orphanedFunctionOutput || attempt.kind === "compaction-stripped") return;
1841
+ if (!orphanedFunctionOutput && (attempt.kind === "initial" || attempt.kind === "continuation-rejected")) {
1842
+ const reasoningStripped = stripResponsesRequestEncryptedReasoning(attempt.request);
1843
+ if (reasoningStripped !== attempt.request) return {
1844
+ kind: "reasoning-stripped",
1845
+ request: reasoningStripped
1846
+ };
1847
+ }
1848
+ const locallyStripped = stripResponsesRequestCompaction(attempt.request);
1849
+ if (locallyStripped === attempt.request) return;
1850
+ let compactionStripped = options?.buildFullHistoryRequest ? await options.buildFullHistoryRequest() : locallyStripped;
1851
+ compactionStripped = stripResponsesRequestCompaction(compactionStripped);
1852
+ if (attempt.kind === "reasoning-stripped") compactionStripped = stripResponsesRequestEncryptedReasoning(compactionStripped);
1853
+ return {
1854
+ kind: "compaction-stripped",
1855
+ request: compactionStripped,
1856
+ rejectedCompaction: readOpenAIResponsesCompactionRejection(attempt.request)
1857
+ };
1858
+ }
1859
+ async function createResponsesStreamWithEncryptedContentRetry(params) {
1860
+ const sendAttempt = async (attempt) => {
1861
+ const { data, response } = await params.client.responses.create(attempt.request, params.requestOptions).withResponse();
1862
+ commitResponsesEncryptedContentAttempt(attempt, (checkpoint) => {
1863
+ if (checkpoint) params.onCompactionRejected?.(checkpoint);
1864
+ });
1865
+ if (!isAsyncIterable(data)) throw new Error("OpenAI Responses streaming request returned a non-stream response");
1866
+ return {
1867
+ stream: data,
1868
+ response,
1869
+ attempt
1870
+ };
1871
+ };
1872
+ let attempt = {
1873
+ kind: params.initialAttemptKind ?? "initial",
1874
+ request: params.request,
1875
+ ...params.initialRejectedCompaction ? { rejectedCompaction: params.initialRejectedCompaction } : {}
1876
+ };
1877
+ while (true) {
1878
+ params.observePrompt?.(attempt.request, {
1879
+ egress: "responses-sdk",
1880
+ payloadVariant: attempt.kind
1881
+ });
1882
+ try {
1883
+ return await sendAttempt(attempt);
1884
+ } catch (error) {
1885
+ let nextAttempt = await resolveNextResponsesEncryptedContentAttempt(attempt, error, { buildFullHistoryRequest: params.buildFullHistoryRequest });
1886
+ if (!nextAttempt && attempt.request.previous_response_id && error && typeof error === "object" && typeof error.status === "number" && error.code === "previous_response_not_found") {
1887
+ const request = { ...params.buildFullHistoryRequest ? await params.buildFullHistoryRequest() : attempt.request };
1888
+ delete request.previous_response_id;
1889
+ nextAttempt = {
1890
+ kind: "continuation-rejected",
1891
+ request
1892
+ };
1893
+ }
1894
+ if (!nextAttempt) throw error;
1895
+ const retryDescription = nextAttempt.kind === "reasoning-stripped" ? "without encrypted reasoning content" : nextAttempt.kind === "compaction-stripped" ? "without encrypted compaction content" : "full history after rejected previous_response_id";
1896
+ log.warn(`[responses] retrying ${retryDescription} provider=${params.model.provider} api=${params.model.api} model=${params.model.id}`);
1897
+ attempt = nextAttempt;
1898
+ }
1899
+ }
1900
+ }
1901
+ function resolveAzureOpenAIApiVersion(env = process.env) {
1902
+ return env.AZURE_OPENAI_API_VERSION?.trim() || "preview";
1903
+ }
2194
1904
  //#endregion
2195
1905
  //#region packages/ai/src/providers/openai-responses-stream-compat.ts
2196
1906
  const OPENAI_RESPONSES_OUTPUT_TEXT_CONTENT_PART_TYPE = "output_text";
@@ -2220,19 +1930,16 @@ function resolveResponsesMessageSnapshotCollapse(params) {
2220
1930
  }
2221
1931
  //#endregion
2222
1932
  //#region packages/ai/src/providers/openai-responses-tool-call-tracker.ts
2223
- function readIdentityValue(value) {
2224
- return (typeof value === "string" ? value.trim() : "") || void 0;
2225
- }
2226
1933
  function readOutputIndex(event) {
2227
1934
  return typeof event.output_index === "number" && Number.isInteger(event.output_index) && event.output_index >= 0 ? event.output_index : void 0;
2228
1935
  }
2229
1936
  function readEventIdentity(event) {
2230
- return { itemId: readIdentityValue(event.item_id) };
1937
+ return { itemId: normalizeOptionalString(event.item_id) };
2231
1938
  }
2232
1939
  function readResponsesToolCallItemIdentity(item) {
2233
1940
  return {
2234
- itemId: readIdentityValue(item.id),
2235
- callId: readIdentityValue(item.call_id)
1941
+ itemId: normalizeOptionalString(item.id),
1942
+ callId: normalizeOptionalString(item.call_id)
2236
1943
  };
2237
1944
  }
2238
1945
  function createResponsesToolCallTracker() {
@@ -2295,6 +2002,308 @@ function createResponsesToolCallTracker() {
2295
2002
  };
2296
2003
  }
2297
2004
  //#endregion
2005
+ //#region packages/ai/src/transports/openai-responses-debug.ts
2006
+ function stringifyUnknown(value, fallback = "") {
2007
+ if (typeof value === "string") return value;
2008
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
2009
+ return fallback;
2010
+ }
2011
+ function safeDebugValue(value) {
2012
+ if (typeof value === "string") return value;
2013
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
2014
+ if (value === null) return "null";
2015
+ if (value === void 0) return "undefined";
2016
+ return Array.isArray(value) ? "array" : typeof value;
2017
+ }
2018
+ function responseInputTextChars(input) {
2019
+ if (typeof input === "string") return input.length;
2020
+ if (Array.isArray(input)) return input.reduce((total, item) => total + responseInputTextChars(item), 0);
2021
+ if (!input || typeof input !== "object") return 0;
2022
+ const record = input;
2023
+ let total = 0;
2024
+ if (typeof record.text === "string") total += record.text.length;
2025
+ if (typeof record.content === "string") total += record.content.length;
2026
+ else if (Array.isArray(record.content)) total += responseInputTextChars(record.content);
2027
+ return total;
2028
+ }
2029
+ function responseInputRoles(input) {
2030
+ if (!Array.isArray(input)) return "";
2031
+ const roles = /* @__PURE__ */ new Set();
2032
+ for (const item of input) if (item && typeof item === "object") {
2033
+ const role = item.role;
2034
+ if (typeof role === "string" && role.trim()) roles.add(role.trim());
2035
+ }
2036
+ return [...roles].toSorted().join(",");
2037
+ }
2038
+ function responseInputItemShape(input) {
2039
+ if (!Array.isArray(input)) return "none";
2040
+ return input.map((item) => {
2041
+ if (!isRecord(item) || typeof item.type !== "string") return "unknown";
2042
+ if (item.type === "message" && typeof item.role === "string") return `message:${item.role}`;
2043
+ return item.type;
2044
+ }).join(",") || "none";
2045
+ }
2046
+ function hashOpaqueResponsesValue(value) {
2047
+ return createHash("sha256").update(value).digest("hex");
2048
+ }
2049
+ function summarizeResponsesCompactionItems(input) {
2050
+ if (!Array.isArray(input)) return [
2051
+ "compactionItems=0",
2052
+ "compactionIdHashes=none",
2053
+ "compactionPayloadHashes=none",
2054
+ "compactionInputIndexes=none"
2055
+ ];
2056
+ const compactions = input.flatMap((item, inputIndex) => {
2057
+ if (!isRecord(item) || item.type !== "compaction") return [];
2058
+ return [{
2059
+ idHash: typeof item.id === "string" ? hashOpaqueResponsesValue(item.id) : void 0,
2060
+ inputIndex,
2061
+ payloadHash: typeof item.encrypted_content === "string" ? hashOpaqueResponsesValue(item.encrypted_content) : void 0
2062
+ }];
2063
+ });
2064
+ return [
2065
+ `compactionItems=${compactions.length}`,
2066
+ `compactionIdHashes=${compactions.flatMap((item) => item.idHash ?? []).join(",") || "none"}`,
2067
+ `compactionPayloadHashes=${compactions.flatMap((item) => item.payloadHash ?? []).join(",") || "none"}`,
2068
+ `compactionInputIndexes=${compactions.map((item) => item.inputIndex).join(",") || "none"}`
2069
+ ];
2070
+ }
2071
+ function readToolPayloadField(record, field) {
2072
+ try {
2073
+ return record[field];
2074
+ } catch {
2075
+ return;
2076
+ }
2077
+ }
2078
+ function readResponsesToolDisplayName(tool) {
2079
+ if (!tool || typeof tool !== "object") return "";
2080
+ const record = tool;
2081
+ const name = readToolPayloadField(record, "name");
2082
+ if (typeof name === "string") return name;
2083
+ const fn = readToolPayloadField(record, "function");
2084
+ if (fn && typeof fn === "object") {
2085
+ const fnName = readToolPayloadField(fn, "name");
2086
+ if (typeof fnName === "string") return fnName;
2087
+ }
2088
+ const type = readToolPayloadField(record, "type");
2089
+ return typeof type === "string" && type !== "function" ? type : "";
2090
+ }
2091
+ function summarizeResponsesTools(tools) {
2092
+ if (!Array.isArray(tools)) return "count=0";
2093
+ const names = tools.map(readResponsesToolDisplayName).filter(Boolean);
2094
+ const mode = resolveModelPayloadDebugMode();
2095
+ const maxNames = mode === "tools" || mode === "full-redacted" ? names.length : 12;
2096
+ const label = maxNames >= names.length ? "names" : "sample";
2097
+ const shown = names.slice(0, maxNames).join(",");
2098
+ return `count=${tools.length}${shown ? ` ${label}=${shown}` : ""}`;
2099
+ }
2100
+ function stringifyRedactedPayload(value) {
2101
+ try {
2102
+ const encoded = JSON.stringify(value, (key, child) => key === "encrypted_content" ? "<opaque data omitted>" : child);
2103
+ if (!encoded) return "<empty>";
2104
+ const redacted = redactSensitiveText(encoded, { mode: "tools" });
2105
+ return redacted.length > 8e3 ? `${truncateUtf16Safe(redacted, 8e3)}…<truncated>` : redacted;
2106
+ } catch {
2107
+ return "<unserializable>";
2108
+ }
2109
+ }
2110
+ function stringifyRedactedEvent(value) {
2111
+ const redacted = stringifyRedactedPayload(value);
2112
+ return redacted.length > 2e3 ? `${truncateUtf16Safe(redacted, 2e3)}…<truncated>` : redacted;
2113
+ }
2114
+ const RESPONSE_FAILED_FAILURE_FIELD_KEYS = [
2115
+ "error",
2116
+ "incomplete_details",
2117
+ "status_details",
2118
+ "failure_reason",
2119
+ "last_error",
2120
+ "provider_error",
2121
+ "error_details"
2122
+ ];
2123
+ function readResponseFailedString(record, key) {
2124
+ return stringifyUnknown(record?.[key]);
2125
+ }
2126
+ function buildResponsesFailedEventSummary(message, responseId, observation) {
2127
+ const summary = { message };
2128
+ if (responseId) summary.responseId = responseId;
2129
+ if (observation) summary.observation = observation;
2130
+ return summary;
2131
+ }
2132
+ function isResponseFailedIdentifierKey(key) {
2133
+ const normalized = key.replace(/[-_\s]/g, "").toLowerCase();
2134
+ return normalized === "requestid" || normalized === "xrequestid" || normalized === "providerrequestid" || normalized === "providerresponseid" || normalized === "litellmrequestid" || normalized.includes("request") && normalized.endsWith("id") || normalized.includes("provider") && normalized.endsWith("id");
2135
+ }
2136
+ function collectResponseFailedIdentifierHashes(value, opts = {}) {
2137
+ const path = opts.path ?? "";
2138
+ const depth = opts.depth ?? 0;
2139
+ const identifierKey = opts.identifierKey ?? "";
2140
+ const out = opts.out ?? [];
2141
+ const seen = opts.seen ?? /* @__PURE__ */ new WeakSet();
2142
+ if (out.length >= 12 || depth > 4 || !value || typeof value !== "object") return out;
2143
+ if (seen.has(value)) return out;
2144
+ seen.add(value);
2145
+ if (Array.isArray(value)) {
2146
+ for (const [index, item] of value.entries()) {
2147
+ if (index >= 8 || out.length >= 12) break;
2148
+ const itemString = typeof item === "string" || typeof item === "number" ? String(item).trim() : "";
2149
+ if (identifierKey && isResponseFailedIdentifierKey(identifierKey) && itemString) {
2150
+ out.push(`${path}[${index}]=${redactIdentifier(itemString, { len: 12 })}`);
2151
+ continue;
2152
+ }
2153
+ collectResponseFailedIdentifierHashes(item, {
2154
+ path: `${path}[${index}]`,
2155
+ depth: depth + 1,
2156
+ identifierKey,
2157
+ out,
2158
+ seen
2159
+ });
2160
+ }
2161
+ return out;
2162
+ }
2163
+ for (const [key, child] of Object.entries(value)) {
2164
+ if (out.length >= 12) break;
2165
+ const childPath = path ? `${path}.${key}` : key;
2166
+ const childString = typeof child === "string" || typeof child === "number" ? String(child).trim() : "";
2167
+ if (isResponseFailedIdentifierKey(key) && childString) {
2168
+ out.push(`${childPath}=${redactIdentifier(childString, { len: 12 })}`);
2169
+ continue;
2170
+ }
2171
+ collectResponseFailedIdentifierHashes(child, {
2172
+ path: childPath,
2173
+ depth: depth + 1,
2174
+ identifierKey: isResponseFailedIdentifierKey(key) ? key : void 0,
2175
+ out,
2176
+ seen
2177
+ });
2178
+ }
2179
+ return out;
2180
+ }
2181
+ function redactResponseFailedDiagnosticValue(value, opts = {}) {
2182
+ const key = opts.key ?? "";
2183
+ const depth = opts.depth ?? 0;
2184
+ if (typeof value === "string" || typeof value === "number") return key && isResponseFailedIdentifierKey(key) ? redactIdentifier(String(value), { len: 12 }) : value;
2185
+ if (depth > 6 || !value || typeof value !== "object") return value;
2186
+ const seen = opts.seen ?? /* @__PURE__ */ new WeakSet();
2187
+ if (seen.has(value)) return "<circular>";
2188
+ seen.add(value);
2189
+ if (Array.isArray(value)) return value.slice(0, 16).map((item) => redactResponseFailedDiagnosticValue(item, {
2190
+ key,
2191
+ depth: depth + 1,
2192
+ seen
2193
+ }));
2194
+ const out = {};
2195
+ for (const [childKey, child] of Object.entries(value)) out[childKey] = redactResponseFailedDiagnosticValue(child, {
2196
+ key: childKey,
2197
+ depth: depth + 1,
2198
+ seen
2199
+ });
2200
+ return out;
2201
+ }
2202
+ function buildResponsesFailedFailureFields(response) {
2203
+ if (!response) return {};
2204
+ const fields = {};
2205
+ for (const key of RESPONSE_FAILED_FAILURE_FIELD_KEYS) if (response[key] !== void 0 && response[key] !== null) fields[key] = response[key];
2206
+ return fields;
2207
+ }
2208
+ function buildResponsesFailedNoDetailsObservation(event, model, response = isRecord(event.response) ? event.response : void 0) {
2209
+ const failureFields = redactResponseFailedDiagnosticValue(buildResponsesFailedFailureFields(response));
2210
+ const metadataKeys = isRecord(response?.metadata) ? Object.keys(response.metadata).toSorted() : [];
2211
+ const responsePreview = {
2212
+ id: readResponseFailedString(response, "id"),
2213
+ status: readResponseFailedString(response, "status"),
2214
+ model: readResponseFailedString(response, "model"),
2215
+ object: readResponseFailedString(response, "object"),
2216
+ failureFields,
2217
+ metadataKeys
2218
+ };
2219
+ return {
2220
+ event: "openai_responses_response_failed_without_details",
2221
+ provider: model.provider,
2222
+ api: model.api,
2223
+ transportModel: model.id,
2224
+ providerRuntimeFailureKind: "no_error_details",
2225
+ responseId: responsePreview.id,
2226
+ responseStatus: responsePreview.status,
2227
+ responseModel: responsePreview.model,
2228
+ responseObject: responsePreview.object,
2229
+ metadataKeys,
2230
+ requestIdHashes: collectResponseFailedIdentifierHashes(event),
2231
+ failureFieldsPreview: stringifyRedactedEvent(failureFields),
2232
+ responsePreview: stringifyRedactedEvent(responsePreview)
2233
+ };
2234
+ }
2235
+ function summarizeResponsesFailedNoDetailsObservation(observation) {
2236
+ const requestIds = observation.requestIdHashes.join(",");
2237
+ const metadataKeys = observation.metadataKeys.join(",");
2238
+ return `responseId=${safeDebugValue(observation.responseId || void 0)} responseStatus=${safeDebugValue(observation.responseStatus || void 0)} responseModel=${safeDebugValue(observation.responseModel || void 0)} requestIds=${requestIds || "none"} metadataKeys=${metadataKeys || "none"} failureFields=${observation.failureFieldsPreview}`;
2239
+ }
2240
+ function normalizeResponsesFailedEvent(event, model) {
2241
+ const response = isRecord(event.response) ? event.response : void 0;
2242
+ const responseId = readResponseFailedString(response, "id") || void 0;
2243
+ const error = isRecord(response?.error) ? response.error : void 0;
2244
+ if (error) {
2245
+ const code = readResponseFailedString(error, "code").trim();
2246
+ const message = readResponseFailedString(error, "message").trim();
2247
+ if (code || message) return buildResponsesFailedEventSummary(`${code || "unknown"}: ${message || "no message"}`, responseId);
2248
+ }
2249
+ const incompleteReason = readResponseFailedString(isRecord(response?.incomplete_details) ? response.incomplete_details : void 0, "reason");
2250
+ if (incompleteReason) return buildResponsesFailedEventSummary(`incomplete: ${incompleteReason}`, responseId);
2251
+ return buildResponsesFailedEventSummary(RESPONSE_FAILED_NO_DETAILS_MESSAGE, responseId, buildResponsesFailedNoDetailsObservation(event, model, response));
2252
+ }
2253
+ var ResponsesStreamFailure = class extends Error {
2254
+ constructor(failure, response) {
2255
+ super(failure.message);
2256
+ this.name = "ResponsesStreamFailure";
2257
+ this.responseId = failure.responseId;
2258
+ this.response = response;
2259
+ this.observation = failure.observation;
2260
+ }
2261
+ };
2262
+ function logResponsesFailedNoDetails(observation) {
2263
+ log.warn(`[responses] response.failed missing error details provider=${observation.provider} api=${observation.api} model=${observation.transportModel} ` + summarizeResponsesFailedNoDetailsObservation(observation), observation);
2264
+ }
2265
+ function summarizeResponsesPayload(params) {
2266
+ if (!params || typeof params !== "object") return "payload=non-object";
2267
+ const record = params;
2268
+ const input = record.input;
2269
+ const reasoning = record.reasoning && typeof record.reasoning === "object" ? record.reasoning : void 0;
2270
+ const text = record.text && typeof record.text === "object" ? record.text : void 0;
2271
+ const parts = [
2272
+ `fields=${Object.keys(record).toSorted().join(",")}`,
2273
+ `model=${safeDebugValue(record.model)}`,
2274
+ `stream=${safeDebugValue(record.stream)}`,
2275
+ `inputItems=${Array.isArray(input) ? input.length : typeof input}`,
2276
+ `inputItemShape=${responseInputItemShape(input)}`,
2277
+ `inputRoles=${responseInputRoles(input) || "none"}`,
2278
+ `inputTextChars=${responseInputTextChars(input)}`,
2279
+ `tools=${summarizeResponsesTools(record.tools)}`,
2280
+ `reasoningEffort=${safeDebugValue(reasoning?.effort)}`,
2281
+ `reasoningSummary=${safeDebugValue(reasoning?.summary)}`,
2282
+ `textVerbosity=${safeDebugValue(text?.verbosity)}`,
2283
+ `serviceTier=${safeDebugValue(record.service_tier)}`,
2284
+ ...summarizeResponsesCompactionItems(input),
2285
+ `store=${safeDebugValue(record.store)}`,
2286
+ `promptCacheKey=${record.prompt_cache_key === void 0 ? "absent" : "present"}`,
2287
+ `metadataKeys=${record.metadata && typeof record.metadata === "object" ? Object.keys(record.metadata).toSorted().join(",") : "none"}`
2288
+ ];
2289
+ if (resolveModelPayloadDebugMode() === "full-redacted") parts.push(`payload=${stringifyRedactedPayload(record)}`);
2290
+ return parts.join(" ");
2291
+ }
2292
+ function summarizeOpenAITransportError(error) {
2293
+ if (!error || typeof error !== "object") return `type=${typeof error} message=${safeDebugValue(error)}`;
2294
+ const record = error;
2295
+ const cause = record.cause && typeof record.cause === "object" ? record.cause : void 0;
2296
+ return [
2297
+ `name=${safeDebugValue(record.name)}`,
2298
+ `status=${safeDebugValue(record.status)}`,
2299
+ `code=${safeDebugValue(record.code)}`,
2300
+ `type=${safeDebugValue(record.type)}`,
2301
+ `causeName=${safeDebugValue(cause?.name)}`,
2302
+ `causeCode=${safeDebugValue(cause?.code)}`,
2303
+ `message=${error instanceof Error ? error.message : safeDebugValue(error)}`
2304
+ ].join(" ");
2305
+ }
2306
+ //#endregion
2298
2307
  //#region packages/ai/src/transports/openai-responses-stream-observer-internal.ts
2299
2308
  const STRING_DELTA_EVENTS = /* @__PURE__ */ new Set([
2300
2309
  "response.function_call_arguments.delta",
@@ -2316,7 +2325,7 @@ async function* adaptResponsesStream(stream, signal) {
2316
2325
  await scheduler.afterEvent();
2317
2326
  }
2318
2327
  }
2319
- async function* observeResponsesStream(stream, model) {
2328
+ async function* observeResponsesStream(stream, model, requestStartedAt) {
2320
2329
  const startedAt = Date.now();
2321
2330
  const eventTypes = /* @__PURE__ */ new Map();
2322
2331
  const debugMode = resolveModelSseDebugMode();
@@ -2326,7 +2335,7 @@ async function* observeResponsesStream(stream, model) {
2326
2335
  const type = isRecord(event) && typeof event.type === "string" ? event.type : "unknown";
2327
2336
  eventCount += 1;
2328
2337
  eventTypes.set(type, (eventTypes.get(type) ?? 0) + 1);
2329
- if (eventCount === 1) emitModelTransportDebug(log, `[responses] first_event provider=${model.provider} api=${model.api} model=${model.id} elapsedMs=${Date.now() - startedAt} type=${type}`);
2338
+ if (eventCount === 1) emitModelTransportDebug(log, `[responses] first_event provider=${model.provider} api=${model.api} model=${model.id} elapsedMs=${Date.now() - (requestStartedAt ?? startedAt)} headersToEventMs=${Date.now() - startedAt} type=${type}`);
2330
2339
  if (debugMode === "peek" && eventCount <= 5) emitModelTransportDebug(log, `[responses] event_peek provider=${model.provider} api=${model.api} model=${model.id} index=${eventCount} type=${type} event=${stringifyRedactedEvent(event)}`);
2331
2340
  yield event;
2332
2341
  }
@@ -2337,6 +2346,23 @@ async function* observeResponsesStream(stream, model) {
2337
2346
  }
2338
2347
  //#endregion
2339
2348
  //#region packages/ai/src/transports/openai-responses-stream-slots-internal.ts
2349
+ function createResponsesOutputContentIndex() {
2350
+ const indexes = /* @__PURE__ */ new Map();
2351
+ const identity = (item) => {
2352
+ if ((item.type === "reasoning" || item.type === "message") && item.id) return `${item.type}:${item.id}`;
2353
+ return item.type === "function_call" ? `function_call:${item.call_id ?? item.id ?? ""}` : void 0;
2354
+ };
2355
+ return {
2356
+ get(item) {
2357
+ const key = identity(item);
2358
+ return key === void 0 ? void 0 : indexes.get(key);
2359
+ },
2360
+ set(item, contentIndex) {
2361
+ const key = identity(item);
2362
+ if (key !== void 0) indexes.set(key, contentIndex);
2363
+ }
2364
+ };
2365
+ }
2340
2366
  function appendResponsesPendingTextDelta(slot, delta, materialize) {
2341
2367
  slot.pendingText = `${slot.pendingText ?? ""}${delta}`;
2342
2368
  const priorText = slot.collapseCandidate?.block.text ?? "";
@@ -2385,6 +2411,14 @@ function createResponsesOutputSlotTracker() {
2385
2411
  }
2386
2412
  //#endregion
2387
2413
  //#region packages/ai/src/providers/openai-responses-terminal-usage.ts
2414
+ /**
2415
+ * Canonical mapping for terminal OpenAI Responses events.
2416
+ *
2417
+ * `response.completed`, `response.incomplete`, and `response.failed` are terminal and can carry
2418
+ * usage, so every Responses path finalizes through the helpers here. Keeping one owner prevents
2419
+ * package and managed transports from drifting on token buckets, service-tier pricing, or future
2420
+ * terminal-event semantics.
2421
+ */
2388
2422
  function readCount(value) {
2389
2423
  return typeof value === "number" && Number.isFinite(value) ? value : 0;
2390
2424
  }
@@ -2414,8 +2448,7 @@ function mapResponsesTerminalUsage(usage) {
2414
2448
  }
2415
2449
  /** Reasoning tokens are reported by the agent path only; the package path does not track them. */
2416
2450
  function readResponsesReasoningTokens(usage) {
2417
- const reasoningTokens = usage?.output_tokens_details?.reasoning_tokens;
2418
- return typeof reasoningTokens === "number" && Number.isFinite(reasoningTokens) ? reasoningTokens : void 0;
2451
+ return asFiniteNumber(usage?.output_tokens_details?.reasoning_tokens);
2419
2452
  }
2420
2453
  function mapResponsesTerminalStopReason(status) {
2421
2454
  if (!status) return "stop";
@@ -2467,11 +2500,9 @@ function resolveCompletedResponsesToolCall(item, streamed) {
2467
2500
  if (streamedName && completedName && streamedName !== completedName) throw new Error(`Responses stream changed tool-call function name from ${streamedName} to ${completedName}`);
2468
2501
  const name = completedName ?? streamedName;
2469
2502
  if (!name) throw new Error("Responses stream completed tool call without a function name");
2470
- const argumentsValue = parseJsonObjectPreservingUnsafeIntegers(streamed?.arguments ?? item.arguments);
2471
- if (!argumentsValue) throw new Error("Responses stream completed tool call with invalid JSON arguments");
2472
2503
  return {
2473
2504
  name,
2474
- arguments: argumentsValue
2505
+ arguments: parseTerminalToolCallArguments(streamed?.arguments ?? item.arguments, "Responses stream completed tool call with invalid JSON arguments")
2475
2506
  };
2476
2507
  }
2477
2508
  function createResponsesTerminalController(params) {
@@ -2522,7 +2553,7 @@ function createResponsesTerminalController(params) {
2522
2553
  content: text,
2523
2554
  partial: output
2524
2555
  });
2525
- return;
2556
+ return started.index;
2526
2557
  }
2527
2558
  const previous = params.getLastTextBlock();
2528
2559
  const collapse = resolveResponsesMessageSnapshotCollapse({
@@ -2542,7 +2573,7 @@ function createResponsesTerminalController(params) {
2542
2573
  content: collapse.text,
2543
2574
  partial: output
2544
2575
  });
2545
- return;
2576
+ return previous.index;
2546
2577
  }
2547
2578
  const block = {
2548
2579
  type: "text",
@@ -2567,6 +2598,7 @@ function createResponsesTerminalController(params) {
2567
2598
  content: text,
2568
2599
  partial: output
2569
2600
  });
2601
+ return index;
2570
2602
  };
2571
2603
  const appendToolCall = (item) => {
2572
2604
  const validated = resolveCompletedResponsesToolCall(item);
@@ -2589,17 +2621,17 @@ function createResponsesTerminalController(params) {
2589
2621
  toolCall,
2590
2622
  partial: output
2591
2623
  });
2624
+ return contentIndex;
2592
2625
  };
2593
2626
  const recoverTerminalOutput = (items, includeToolCalls) => {
2594
2627
  let hasCompletedLaterOutput = false;
2595
2628
  for (const item of items.toReversed()) {
2596
2629
  if (item.type === "reasoning") {
2597
- hasCompletedLaterOutput ||= params.reasoningBlocksById.has(item.id);
2630
+ hasCompletedLaterOutput ||= params.outputItemContentIndexes.get(item) !== void 0;
2598
2631
  continue;
2599
2632
  }
2600
2633
  if (item.type !== "message" && item.type !== "function_call") continue;
2601
- const identity = item.type === "message" ? `message:${item.id}` : `function_call:${item.call_id}`;
2602
- if (params.completedOutputItemIdentities.has(identity) || item.type === "message" && params.startedTextBlocksByItemId.has(item.id)) {
2634
+ if (params.outputItemContentIndexes.get(item) !== void 0 || item.type === "message" && params.startedTextBlocksByItemId.has(item.id)) {
2603
2635
  hasCompletedLaterOutput = true;
2604
2636
  continue;
2605
2637
  }
@@ -2607,25 +2639,32 @@ function createResponsesTerminalController(params) {
2607
2639
  if (hasCompletedLaterOutput) throw new Error("Responses stream omitted an output item before completed output");
2608
2640
  if (item.type === "function_call") resolveCompletedResponsesToolCall(item);
2609
2641
  }
2610
- for (const item of items) if (item.type === "message") {
2611
- const identity = `message:${item.id}`;
2612
- if (params.completedOutputItemIdentities.has(identity)) continue;
2613
- appendText(item);
2614
- params.completedOutputItemIdentities.add(identity);
2642
+ for (const [terminalIndex, item] of items.entries()) if (item.type === "message") {
2643
+ if (params.outputItemContentIndexes.get(item) !== void 0 && !params.startedTextBlocksByItemId.has(item.id)) continue;
2644
+ const appendedIndex = appendText(item);
2645
+ if (appendedIndex !== void 0) params.outputItemContentIndexes.set(item, appendedIndex);
2615
2646
  } else {
2616
2647
  params.setLastTextBlock(null);
2617
- if (includeToolCalls && item.type === "function_call") {
2618
- const identity = `function_call:${item.call_id}`;
2619
- if (params.completedOutputItemIdentities.has(identity)) continue;
2620
- appendToolCall(item);
2621
- params.completedOutputItemIdentities.add(identity);
2648
+ const alreadyCapturedCompaction = item.type === "compaction" && output.providerReplay?.type === "openai-responses-compaction" && output.providerReplay.id === item.id && output.providerReplay.data === item.encrypted_content;
2649
+ if (item.type === "compaction" && !alreadyCapturedCompaction) {
2650
+ let replayIndex = blocks.length;
2651
+ for (const laterItem of items.slice(terminalIndex + 1)) {
2652
+ const laterContentIndex = params.outputItemContentIndexes.get(laterItem);
2653
+ if (laterContentIndex !== void 0) {
2654
+ replayIndex = laterContentIndex;
2655
+ break;
2656
+ }
2657
+ }
2658
+ captureOpenAIResponsesCompaction(output, item, replayIndex, model, options?.reasoningReplayMetadata);
2659
+ } else if (includeToolCalls && item.type === "function_call") {
2660
+ if (params.outputItemContentIndexes.get(item) !== void 0) continue;
2661
+ params.outputItemContentIndexes.set(item, appendToolCall(item));
2622
2662
  }
2623
2663
  }
2624
2664
  };
2625
- const finalizeResponse = (response, terminalEventType) => {
2626
- params.markFinalized();
2627
- backfillReasoning(response.output ?? []);
2628
- output.responseId = response.id || output.responseId;
2665
+ const finalizeTerminalFacts = (response, responseId = response.id) => {
2666
+ output.responseId = responseId || output.responseId;
2667
+ output.responseModel = response.model?.trim() || void 0;
2629
2668
  const usage = mapResponsesTerminalUsage(response.usage);
2630
2669
  const reasoningTokens = readResponsesReasoningTokens(response.usage);
2631
2670
  if (usage) output.usage = {
@@ -2644,6 +2683,11 @@ function createResponsesTerminalController(params) {
2644
2683
  const tier = options.resolveServiceTier ? options.resolveServiceTier(response.service_tier, options.serviceTier) : response.service_tier ?? options.serviceTier;
2645
2684
  options.applyServiceTierPricing(output.usage, tier);
2646
2685
  }
2686
+ };
2687
+ const finalizeResponse = (response, terminalEventType) => {
2688
+ params.markFinalized();
2689
+ backfillReasoning(response.output ?? []);
2690
+ finalizeTerminalFacts(response);
2647
2691
  const terminal = resolveResponsesTerminalStopReason({
2648
2692
  status: response.status,
2649
2693
  terminalEventType,
@@ -2655,30 +2699,22 @@ function createResponsesTerminalController(params) {
2655
2699
  };
2656
2700
  return {
2657
2701
  finalizeResponse,
2702
+ finalizeFailedResponse: finalizeTerminalFacts,
2658
2703
  recoverTerminalOutput
2659
2704
  };
2660
2705
  }
2661
2706
  //#endregion
2662
2707
  //#region packages/ai/src/transports/openai-responses-stream-internal.ts
2663
- var ResponsesStreamFailure = class extends Error {
2664
- constructor(failure, response) {
2665
- super(failure.message);
2666
- this.name = "ResponsesStreamFailure";
2667
- this.responseId = failure.responseId;
2668
- this.response = response;
2669
- this.observation = failure.observation;
2670
- }
2671
- };
2672
2708
  async function processResponsesStream(openaiStream, output, stream, model, options) {
2673
2709
  const streamingToolCalls = createResponsesToolCallTracker();
2674
2710
  const outputSlots = createResponsesOutputSlotTracker();
2675
2711
  const reasoningBlocksById = /* @__PURE__ */ new Map();
2676
- const completedOutputItemIdentities = /* @__PURE__ */ new Set();
2712
+ const outputItemContentIndexes = createResponsesOutputContentIndex();
2677
2713
  const startedTextBlocksByItemId = /* @__PURE__ */ new Map();
2678
- let terminalResponseEvent;
2714
+ let terminalResponse;
2679
2715
  let lastTextBlock = null;
2680
2716
  const blocks = output.content;
2681
- const blockIndex = () => blocks.length - 1;
2717
+ const compactionTracker = createCompactionTracker(output, model, options);
2682
2718
  const createOutputSlot = (event, item) => {
2683
2719
  if (item.type === "reasoning") {
2684
2720
  const block = {
@@ -2693,6 +2729,7 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
2693
2729
  };
2694
2730
  blocks.push(block);
2695
2731
  reasoningBlocksById.set(item.id, block);
2732
+ outputItemContentIndexes.set(item, slot.contentIndex);
2696
2733
  outputSlots.register(event, slot);
2697
2734
  stream.push({
2698
2735
  type: "thinking_start",
@@ -2719,6 +2756,7 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
2719
2756
  };
2720
2757
  if (block) {
2721
2758
  blocks.push(block);
2759
+ outputItemContentIndexes.set(messageItem, slot.contentIndex ?? blocks.length - 1);
2722
2760
  startedTextBlocksByItemId.set(messageItem.id, {
2723
2761
  block,
2724
2762
  index: slot.contentIndex ?? blocks.length - 1,
@@ -2751,7 +2789,8 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
2751
2789
  ...slot.item.phase ? { textSignature: encodeTextSignatureV1(slot.item.id, slot.item.phase) } : {}
2752
2790
  };
2753
2791
  blocks.push(slot.block);
2754
- slot.contentIndex = blockIndex();
2792
+ slot.contentIndex = blocks.length - 1;
2793
+ outputItemContentIndexes.set(slot.item, slot.contentIndex);
2755
2794
  startedTextBlocksByItemId.set(slot.item.id, {
2756
2795
  block: slot.block,
2757
2796
  index: slot.contentIndex,
@@ -2774,21 +2813,19 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
2774
2813
  const materializeDeferredTextSlots = (except) => {
2775
2814
  for (const slot of outputSlots.values()) if (slot !== except && slot.type === "text") materializeDeferredTextSlot(slot);
2776
2815
  };
2777
- const { finalizeResponse, recoverTerminalOutput } = createResponsesTerminalController({
2816
+ const { finalizeResponse, finalizeFailedResponse, recoverTerminalOutput } = createResponsesTerminalController({
2778
2817
  output,
2779
2818
  stream,
2780
2819
  model,
2781
2820
  options,
2782
2821
  reasoningBlocksById,
2783
- completedOutputItemIdentities,
2784
2822
  startedTextBlocksByItemId,
2823
+ outputItemContentIndexes,
2785
2824
  getLastTextBlock: () => lastTextBlock,
2786
2825
  setLastTextBlock: (block) => {
2787
2826
  lastTextBlock = block;
2788
2827
  },
2789
- markFinalized: () => {
2790
- terminalResponseEvent = "finalized";
2791
- }
2828
+ markFinalized: () => void 0
2792
2829
  });
2793
2830
  const guardedStream = adaptResponsesStream(withFirstStreamEventTimeout(openaiStream, {
2794
2831
  provider: model.provider,
@@ -2801,327 +2838,538 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
2801
2838
  hint: "The provider may be stalled while parsing the tool payload; retry with a smaller tool surface or enable OPENCLAW_DEBUG_MODEL_PAYLOAD=tools to inspect exposed tools."
2802
2839
  }), options?.signal);
2803
2840
  try {
2804
- for await (const event of guardedStream) if (event.type === "response.created") output.responseId = event.response.id;
2805
- else if (event.type === "response.output_item.added") {
2806
- materializeDeferredTextSlots();
2807
- const item = event.item;
2808
- if (item.type !== "message") lastTextBlock = null;
2809
- if (item.type === "reasoning" || item.type === "message") createOutputSlot(event, item);
2810
- else if (item.type === "function_call") {
2811
- const toolCallBlock = {
2812
- type: "toolCall",
2813
- id: resolveResponsesToolCallId(item),
2814
- name: typeof item.name === "string" ? item.name.trim() : "",
2815
- arguments: {},
2816
- partialJson: item.arguments || ""
2817
- };
2818
- const contentIndex = output.content.length;
2819
- const toolCallState = {
2820
- block: toolCallBlock,
2821
- contentIndex,
2822
- argumentStreamReliable: true,
2823
- ...readResponsesToolCallItemIdentity(item)
2824
- };
2825
- streamingToolCalls.register(event, toolCallState);
2826
- if (readResponsesOutputIndex(event) !== void 0) outputSlots.register(event, {
2827
- type: "toolCall",
2828
- toolCall: toolCallState
2829
- });
2830
- output.content.push(toolCallBlock);
2831
- stream.push({
2832
- type: "toolcall_start",
2833
- contentIndex,
2834
- partial: output
2835
- });
2836
- }
2837
- } else if (event.type === "response.reasoning_summary_part.added") {
2838
- const slot = outputSlots.resolve(event, "thinking");
2839
- if (!slot) continue;
2840
- slot.item.summary = slot.item.summary || [];
2841
- slot.item.summary.push(event.part);
2842
- } else if (event.type === "response.reasoning_summary_text.delta") {
2843
- const slot = outputSlots.resolve(event, "thinking");
2844
- if (!slot) continue;
2845
- slot.item.summary = slot.item.summary || [];
2846
- const lastPart = slot.item.summary[slot.item.summary.length - 1];
2847
- if (!lastPart) continue;
2848
- slot.block.thinking += event.delta;
2849
- lastPart.text += event.delta;
2850
- stream.push({
2851
- type: "thinking_delta",
2852
- contentIndex: slot.contentIndex,
2853
- delta: event.delta,
2854
- partial: output
2855
- });
2856
- } else if (event.type === "response.reasoning_summary_part.done") {
2857
- const slot = outputSlots.resolve(event, "thinking");
2858
- if (!slot) continue;
2859
- slot.item.summary = slot.item.summary || [];
2860
- const lastPart = slot.item.summary[slot.item.summary.length - 1];
2861
- if (!lastPart) continue;
2862
- slot.block.thinking += "\n\n";
2863
- lastPart.text += "\n\n";
2864
- stream.push({
2865
- type: "thinking_delta",
2866
- contentIndex: slot.contentIndex,
2867
- delta: "\n\n",
2868
- partial: output
2869
- });
2870
- } else if (event.type === "response.reasoning_text.delta") {
2871
- const slot = outputSlots.resolve(event, "thinking");
2872
- if (!slot) continue;
2873
- slot.block.thinking += event.delta;
2874
- stream.push({
2875
- type: "thinking_delta",
2876
- contentIndex: slot.contentIndex,
2877
- delta: event.delta,
2878
- partial: output
2879
- });
2880
- } else if (event.type === "response.content_part.added") {
2881
- const slot = outputSlots.resolve(event, "text");
2882
- if (!slot) continue;
2883
- slot.item.content = slot.item.content || [];
2884
- if (event.part.type === "output_text" || event.part.type === "text" || event.part.type === "refusal") slot.item.content.push(event.part);
2885
- } else if (event.type === "response.output_text.delta") {
2886
- const slot = outputSlots.resolve(event, "text");
2887
- if (!slot) continue;
2888
- slot.item.content ||= [];
2889
- let lastPart = slot.item.content[slot.item.content.length - 1];
2890
- if (!isResponsesTextContentPartType(lastPart?.type)) {
2891
- lastPart = {
2892
- type: "output_text",
2893
- text: "",
2894
- annotations: []
2895
- };
2896
- slot.item.content.push(lastPart);
2897
- }
2898
- lastPart.text += event.delta;
2899
- if (slot.pendingText !== null) appendResponsesPendingTextDelta(slot, event.delta, materializeDeferredTextSlot);
2900
- else if (slot.block && slot.contentIndex !== void 0) {
2901
- slot.block.text += event.delta;
2841
+ for await (const event of guardedStream) {
2842
+ notifyLlmRequestActivity(options?.signal);
2843
+ if (event.type === "response.created") output.responseId = event.response.id;
2844
+ else if (event.type === "response.output_item.added") {
2845
+ materializeDeferredTextSlots();
2846
+ const item = event.item;
2847
+ compactionTracker.added(item, blocks.length);
2848
+ if (item.type !== "message") lastTextBlock = null;
2849
+ if (item.type === "reasoning" || item.type === "message") createOutputSlot(event, item);
2850
+ else if (item.type === "function_call") {
2851
+ const toolCallBlock = {
2852
+ type: "toolCall",
2853
+ id: resolveResponsesToolCallId(item),
2854
+ name: typeof item.name === "string" ? item.name.trim() : "",
2855
+ arguments: {},
2856
+ partialJson: item.arguments || ""
2857
+ };
2858
+ const contentIndex = output.content.length;
2859
+ const toolCallState = {
2860
+ block: toolCallBlock,
2861
+ contentIndex,
2862
+ argumentStreamReliable: true,
2863
+ ...readResponsesToolCallItemIdentity(item)
2864
+ };
2865
+ streamingToolCalls.register(event, toolCallState);
2866
+ if (readResponsesOutputIndex(event) !== void 0) outputSlots.register(event, {
2867
+ type: "toolCall",
2868
+ toolCall: toolCallState
2869
+ });
2870
+ output.content.push(toolCallBlock);
2871
+ outputItemContentIndexes.set(item, contentIndex);
2872
+ stream.push({
2873
+ type: "toolcall_start",
2874
+ contentIndex,
2875
+ partial: output
2876
+ });
2877
+ }
2878
+ } else if (event.type === "response.reasoning_summary_part.added") {
2879
+ const slot = outputSlots.resolve(event, "thinking");
2880
+ if (!slot) continue;
2881
+ slot.item.summary = slot.item.summary || [];
2882
+ slot.item.summary.push(event.part);
2883
+ } else if (event.type === "response.reasoning_summary_text.delta") {
2884
+ const slot = outputSlots.resolve(event, "thinking");
2885
+ if (!slot) continue;
2886
+ slot.item.summary = slot.item.summary || [];
2887
+ const lastPart = slot.item.summary[slot.item.summary.length - 1];
2888
+ if (!lastPart) continue;
2889
+ slot.block.thinking += event.delta;
2890
+ lastPart.text += event.delta;
2902
2891
  stream.push({
2903
- type: "text_delta",
2892
+ type: "thinking_delta",
2904
2893
  contentIndex: slot.contentIndex,
2905
- delta: event.delta
2894
+ delta: event.delta,
2895
+ partial: output
2906
2896
  });
2907
- }
2908
- } else if (isAzureResponsesTextDeltaEvent(event)) {
2909
- const slot = outputSlots.resolve(event, "text");
2910
- if (!slot) continue;
2911
- slot.item.content = slot.item.content || [];
2912
- let lastPart = slot.item.content[slot.item.content.length - 1];
2913
- if (lastPart?.type !== "text") {
2914
- lastPart = {
2915
- type: "text",
2916
- text: ""
2917
- };
2918
- slot.item.content.push(lastPart);
2919
- }
2920
- lastPart.text += event.delta;
2921
- if (slot.pendingText !== null) appendResponsesPendingTextDelta(slot, event.delta, materializeDeferredTextSlot);
2922
- else if (slot.block && slot.contentIndex !== void 0) {
2923
- slot.block.text += event.delta;
2897
+ } else if (event.type === "response.reasoning_summary_part.done") {
2898
+ const slot = outputSlots.resolve(event, "thinking");
2899
+ if (!slot) continue;
2900
+ slot.item.summary = slot.item.summary || [];
2901
+ const lastPart = slot.item.summary[slot.item.summary.length - 1];
2902
+ if (!lastPart) continue;
2903
+ slot.block.thinking += "\n\n";
2904
+ lastPart.text += "\n\n";
2924
2905
  stream.push({
2925
- type: "text_delta",
2906
+ type: "thinking_delta",
2926
2907
  contentIndex: slot.contentIndex,
2927
- delta: event.delta
2908
+ delta: "\n\n",
2909
+ partial: output
2928
2910
  });
2929
- }
2930
- } else if (event.type === "response.refusal.delta") {
2931
- const slot = outputSlots.resolve(event, "text");
2932
- if (!slot) continue;
2933
- slot.item.content ||= [];
2934
- let lastPart = slot.item.content[slot.item.content.length - 1];
2935
- if (lastPart?.type !== "refusal") {
2936
- lastPart = {
2937
- type: "refusal",
2938
- refusal: ""
2939
- };
2940
- slot.item.content.push(lastPart);
2941
- }
2942
- lastPart.refusal += event.delta;
2943
- if (slot.pendingText !== null) appendResponsesPendingTextDelta(slot, event.delta, materializeDeferredTextSlot);
2944
- else if (slot.block && slot.contentIndex !== void 0) {
2945
- slot.block.text += event.delta;
2911
+ } else if (event.type === "response.reasoning_text.delta") {
2912
+ const slot = outputSlots.resolve(event, "thinking");
2913
+ if (!slot) continue;
2914
+ slot.block.thinking += event.delta;
2946
2915
  stream.push({
2947
- type: "text_delta",
2916
+ type: "thinking_delta",
2948
2917
  contentIndex: slot.contentIndex,
2949
- delta: event.delta
2950
- });
2951
- }
2952
- } else if (event.type === "response.function_call_arguments.delta") {
2953
- const toolCall = streamingToolCalls.resolve(event);
2954
- if (toolCall) {
2955
- toolCall.block.partialJson += event.delta;
2956
- toolCall.block.arguments = parseStreamingJson(toolCall.block.partialJson);
2957
- stream.push({
2958
- type: "toolcall_delta",
2959
- contentIndex: toolCall.contentIndex,
2960
2918
  delta: event.delta,
2961
2919
  partial: output
2962
2920
  });
2963
- } else if (streamingToolCalls.hasActive()) streamingToolCalls.markArgumentsUnreliable();
2964
- } else if (event.type === "response.function_call_arguments.done") {
2965
- const toolCall = streamingToolCalls.resolve(event);
2966
- if (toolCall) {
2967
- const previousPartialJson = toolCall.block.partialJson;
2968
- const doneArguments = typeof event.arguments === "string" ? event.arguments : void 0;
2969
- if (doneArguments !== void 0 && (doneArguments.length > 0 || previousPartialJson === "")) {
2970
- toolCall.block.partialJson = doneArguments;
2971
- toolCall.block.arguments = parseStreamingJson(toolCall.block.partialJson);
2972
- toolCall.argumentStreamReliable = true;
2921
+ } else if (event.type === "response.content_part.added") {
2922
+ const slot = outputSlots.resolve(event, "text");
2923
+ if (!slot) continue;
2924
+ slot.item.content = slot.item.content || [];
2925
+ if (event.part.type === "output_text" || event.part.type === "text" || event.part.type === "refusal") slot.item.content.push(event.part);
2926
+ } else if (event.type === "response.output_text.delta") {
2927
+ const slot = outputSlots.resolve(event, "text");
2928
+ if (!slot) continue;
2929
+ slot.item.content ||= [];
2930
+ let lastPart = slot.item.content[slot.item.content.length - 1];
2931
+ if (!isResponsesTextContentPartType(lastPart?.type)) {
2932
+ lastPart = {
2933
+ type: "output_text",
2934
+ text: "",
2935
+ annotations: []
2936
+ };
2937
+ slot.item.content.push(lastPart);
2938
+ }
2939
+ lastPart.text += event.delta;
2940
+ if (slot.pendingText !== null) appendResponsesPendingTextDelta(slot, event.delta, materializeDeferredTextSlot);
2941
+ else if (slot.block && slot.contentIndex !== void 0) {
2942
+ slot.block.text += event.delta;
2943
+ stream.push({
2944
+ type: "text_delta",
2945
+ contentIndex: slot.contentIndex,
2946
+ delta: event.delta
2947
+ });
2948
+ }
2949
+ } else if (isAzureResponsesTextDeltaEvent(event)) {
2950
+ const slot = outputSlots.resolve(event, "text");
2951
+ if (!slot) continue;
2952
+ slot.item.content = slot.item.content || [];
2953
+ let lastPart = slot.item.content[slot.item.content.length - 1];
2954
+ if (lastPart?.type !== "text") {
2955
+ lastPart = {
2956
+ type: "text",
2957
+ text: ""
2958
+ };
2959
+ slot.item.content.push(lastPart);
2960
+ }
2961
+ lastPart.text += event.delta;
2962
+ if (slot.pendingText !== null) appendResponsesPendingTextDelta(slot, event.delta, materializeDeferredTextSlot);
2963
+ else if (slot.block && slot.contentIndex !== void 0) {
2964
+ slot.block.text += event.delta;
2965
+ stream.push({
2966
+ type: "text_delta",
2967
+ contentIndex: slot.contentIndex,
2968
+ delta: event.delta
2969
+ });
2970
+ }
2971
+ } else if (event.type === "response.refusal.delta") {
2972
+ const slot = outputSlots.resolve(event, "text");
2973
+ if (!slot) continue;
2974
+ slot.item.content ||= [];
2975
+ let lastPart = slot.item.content[slot.item.content.length - 1];
2976
+ if (lastPart?.type !== "refusal") {
2977
+ lastPart = {
2978
+ type: "refusal",
2979
+ refusal: ""
2980
+ };
2981
+ slot.item.content.push(lastPart);
2982
+ }
2983
+ lastPart.refusal += event.delta;
2984
+ if (slot.pendingText !== null) appendResponsesPendingTextDelta(slot, event.delta, materializeDeferredTextSlot);
2985
+ else if (slot.block && slot.contentIndex !== void 0) {
2986
+ slot.block.text += event.delta;
2987
+ stream.push({
2988
+ type: "text_delta",
2989
+ contentIndex: slot.contentIndex,
2990
+ delta: event.delta
2991
+ });
2973
2992
  }
2974
- if (doneArguments?.startsWith(previousPartialJson)) {
2975
- const delta = doneArguments.slice(previousPartialJson.length);
2976
- if (delta.length > 0) stream.push({
2993
+ } else if (event.type === "response.function_call_arguments.delta") {
2994
+ const toolCall = streamingToolCalls.resolve(event);
2995
+ if (toolCall) {
2996
+ toolCall.block.partialJson += event.delta;
2997
+ toolCall.block.arguments = parseStreamingJson(toolCall.block.partialJson);
2998
+ stream.push({
2977
2999
  type: "toolcall_delta",
2978
3000
  contentIndex: toolCall.contentIndex,
2979
- delta,
3001
+ delta: event.delta,
2980
3002
  partial: output
2981
3003
  });
2982
- }
2983
- } else if (streamingToolCalls.hasActive()) streamingToolCalls.markArgumentsUnreliable();
2984
- } else if (event.type === "response.output_item.done") {
2985
- const item = event.item;
2986
- if (item.type !== "message") lastTextBlock = null;
2987
- const existingOutputSlot = resolveOutputItemSlot(event, item);
2988
- materializeDeferredTextSlots(existingOutputSlot);
2989
- const outputSlot = existingOutputSlot ?? getOrCreateOutputSlot(event, item);
2990
- if (item.type === "reasoning" && outputSlot?.type === "thinking") {
2991
- const summaryText = item.summary?.map((s) => s.text).join("\n\n") || "";
2992
- const contentText = item.content?.map((c) => c.text).join("\n\n") || "";
2993
- outputSlot.block.thinking = summaryText || contentText || outputSlot.block.thinking;
2994
- outputSlot.block.thinkingSignature = JSON.stringify(item);
2995
- if (item.encrypted_content && options?.reasoningReplayMetadata) outputSlot.block[OPENAI_RESPONSES_REASONING_REPLAY_BLOCK_META_KEY] = options.reasoningReplayMetadata;
2996
- stream.push({
2997
- type: "thinking_end",
2998
- contentIndex: outputSlot.contentIndex,
2999
- content: outputSlot.block.thinking,
3000
- partial: output
3001
- });
3002
- outputSlots.forget(outputSlot);
3003
- } else if (item.type === "message" && outputSlot?.type === "text" && (outputSlot.block || outputSlot.pendingText !== null)) {
3004
- const streamedText = outputSlot.pendingText ?? outputSlot.block?.text ?? "";
3005
- const finalText = item.content == null ? streamedText : item.content.map((c) => c.type === "output_text" || c.type === "text" ? c.text : c.refusal).join("");
3006
- const phase = item.phase ?? void 0;
3007
- const collapse = outputSlot.pendingText !== null ? resolveResponsesMessageSnapshotCollapse({
3008
- prior: outputSlot.collapseCandidate && {
3009
- text: outputSlot.collapseCandidate.block.text,
3010
- phase: outputSlot.collapseCandidate.phase
3011
- },
3012
- nextText: finalText,
3013
- nextPhase: phase
3014
- }) : { kind: "keep" };
3015
- outputSlot.pendingText = null;
3016
- if (collapse.kind === "extend" && outputSlot.collapseCandidate) {
3017
- outputSlot.collapseCandidate.block.text = collapse.text;
3018
- outputSlot.collapseCandidate.block.textSignature = encodeTextSignatureV1(item.id, phase);
3004
+ } else if (streamingToolCalls.hasActive()) streamingToolCalls.markArgumentsUnreliable();
3005
+ } else if (event.type === "response.function_call_arguments.done") {
3006
+ const toolCall = streamingToolCalls.resolve(event);
3007
+ if (toolCall) {
3008
+ const previousPartialJson = toolCall.block.partialJson;
3009
+ const doneArguments = typeof event.arguments === "string" ? event.arguments : void 0;
3010
+ if (doneArguments !== void 0 && (doneArguments.length > 0 || previousPartialJson === "")) {
3011
+ toolCall.block.partialJson = doneArguments;
3012
+ toolCall.block.arguments = parseStreamingJson(toolCall.block.partialJson);
3013
+ toolCall.argumentStreamReliable = true;
3014
+ }
3015
+ if (doneArguments?.startsWith(previousPartialJson)) {
3016
+ const delta = doneArguments.slice(previousPartialJson.length);
3017
+ if (delta.length > 0) stream.push({
3018
+ type: "toolcall_delta",
3019
+ contentIndex: toolCall.contentIndex,
3020
+ delta,
3021
+ partial: output
3022
+ });
3023
+ }
3024
+ } else if (streamingToolCalls.hasActive()) streamingToolCalls.markArgumentsUnreliable();
3025
+ } else if (event.type === "response.output_item.done") {
3026
+ const item = event.item;
3027
+ if (item.type !== "message") lastTextBlock = null;
3028
+ const existingOutputSlot = resolveOutputItemSlot(event, item);
3029
+ materializeDeferredTextSlots(existingOutputSlot);
3030
+ const outputSlot = existingOutputSlot ?? getOrCreateOutputSlot(event, item);
3031
+ compactionTracker.completed(item, blocks.length);
3032
+ if (item.type === "reasoning" && outputSlot?.type === "thinking") {
3033
+ const summaryText = item.summary?.map((s) => s.text).join("\n\n") || "";
3034
+ const contentText = item.content?.map((c) => c.text).join("\n\n") || "";
3035
+ outputSlot.block.thinking = summaryText || contentText || outputSlot.block.thinking;
3036
+ outputSlot.block.thinkingSignature = JSON.stringify(item);
3037
+ if (item.encrypted_content && options?.reasoningReplayMetadata) outputSlot.block[OPENAI_RESPONSES_REASONING_REPLAY_BLOCK_META_KEY] = options.reasoningReplayMetadata;
3019
3038
  stream.push({
3020
- type: "text_end",
3021
- contentIndex: outputSlot.collapseCandidate.index,
3022
- content: collapse.text,
3039
+ type: "thinking_end",
3040
+ contentIndex: outputSlot.contentIndex,
3041
+ content: outputSlot.block.thinking,
3023
3042
  partial: output
3024
3043
  });
3025
- lastTextBlock = outputSlot.collapseCandidate;
3026
- } else {
3027
- if (!outputSlot.block) {
3028
- outputSlot.block = {
3029
- type: "text",
3030
- text: "",
3031
- ...phase ? { textSignature: encodeTextSignatureV1(item.id, phase) } : {}
3044
+ outputSlots.forget(outputSlot);
3045
+ } else if (item.type === "message" && outputSlot?.type === "text" && (outputSlot.block || outputSlot.pendingText !== null)) {
3046
+ const streamedText = outputSlot.pendingText ?? outputSlot.block?.text ?? "";
3047
+ const finalText = item.content == null ? streamedText : item.content.map((c) => c.type === "output_text" || c.type === "text" ? c.text : c.refusal).join("");
3048
+ const phase = item.phase ?? void 0;
3049
+ const collapse = outputSlot.pendingText !== null ? resolveResponsesMessageSnapshotCollapse({
3050
+ prior: outputSlot.collapseCandidate && {
3051
+ text: outputSlot.collapseCandidate.block.text,
3052
+ phase: outputSlot.collapseCandidate.phase
3053
+ },
3054
+ nextText: finalText,
3055
+ nextPhase: phase
3056
+ }) : { kind: "keep" };
3057
+ outputSlot.pendingText = null;
3058
+ if (collapse.kind === "extend" && outputSlot.collapseCandidate) {
3059
+ outputSlot.collapseCandidate.block.text = collapse.text;
3060
+ outputSlot.collapseCandidate.block.textSignature = encodeTextSignatureV1(item.id, phase);
3061
+ stream.push({
3062
+ type: "text_end",
3063
+ contentIndex: outputSlot.collapseCandidate.index,
3064
+ content: collapse.text,
3065
+ partial: output
3066
+ });
3067
+ lastTextBlock = outputSlot.collapseCandidate;
3068
+ outputItemContentIndexes.set(item, outputSlot.collapseCandidate.index);
3069
+ } else {
3070
+ if (!outputSlot.block) {
3071
+ outputSlot.block = {
3072
+ type: "text",
3073
+ text: "",
3074
+ ...phase ? { textSignature: encodeTextSignatureV1(item.id, phase) } : {}
3075
+ };
3076
+ blocks.push(outputSlot.block);
3077
+ outputSlot.contentIndex = blocks.length - 1;
3078
+ stream.push({
3079
+ type: "text_start",
3080
+ contentIndex: outputSlot.contentIndex,
3081
+ partial: output
3082
+ });
3083
+ }
3084
+ outputSlot.block.text = finalText;
3085
+ outputSlot.block.textSignature = encodeTextSignatureV1(item.id, phase);
3086
+ const contentIndex = outputSlot.contentIndex;
3087
+ if (contentIndex === void 0) throw new Error("Responses stream finalized text without a content index");
3088
+ lastTextBlock = {
3089
+ block: outputSlot.block,
3090
+ index: contentIndex,
3091
+ phase
3032
3092
  };
3033
- blocks.push(outputSlot.block);
3034
- outputSlot.contentIndex = blockIndex();
3093
+ outputItemContentIndexes.set(item, contentIndex);
3035
3094
  stream.push({
3036
- type: "text_start",
3037
- contentIndex: outputSlot.contentIndex,
3095
+ type: "text_end",
3096
+ contentIndex,
3097
+ content: outputSlot.block.text,
3038
3098
  partial: output
3039
3099
  });
3040
3100
  }
3041
- outputSlot.block.text = finalText;
3042
- outputSlot.block.textSignature = encodeTextSignatureV1(item.id, phase);
3043
- const contentIndex = outputSlot.contentIndex;
3044
- if (contentIndex === void 0) throw new Error("Responses stream finalized text without a content index");
3045
- lastTextBlock = {
3046
- block: outputSlot.block,
3047
- index: contentIndex,
3048
- phase
3049
- };
3050
- stream.push({
3051
- type: "text_end",
3052
- contentIndex,
3053
- content: outputSlot.block.text,
3054
- partial: output
3101
+ outputSlots.forget(outputSlot);
3102
+ startedTextBlocksByItemId.delete(item.id);
3103
+ } else if (item.type === "function_call") {
3104
+ const streamingToolCall = streamingToolCalls.resolve(event, readResponsesToolCallItemIdentity(item));
3105
+ if (!streamingToolCall && streamingToolCalls.hasActive()) continue;
3106
+ const streamedArguments = streamingToolCall?.block.partialJson ?? "";
3107
+ const completedArguments = typeof item.arguments === "string" ? item.arguments : void 0;
3108
+ if (streamingToolCall && !streamingToolCall.argumentStreamReliable && !completedArguments) continue;
3109
+ const finalArguments = completedArguments !== void 0 && (completedArguments.length > 0 || !streamedArguments) ? completedArguments : streamedArguments;
3110
+ const validated = resolveCompletedResponsesToolCall(item, {
3111
+ name: streamingToolCall?.block.name,
3112
+ arguments: finalArguments
3055
3113
  });
3056
- }
3057
- outputSlots.forget(outputSlot);
3058
- startedTextBlocksByItemId.delete(item.id);
3059
- completedOutputItemIdentities.add(`message:${item.id}`);
3060
- } else if (item.type === "function_call") {
3061
- const streamingToolCall = streamingToolCalls.resolve(event, readResponsesToolCallItemIdentity(item));
3062
- if (!streamingToolCall && streamingToolCalls.hasActive()) continue;
3063
- const streamedArguments = streamingToolCall?.block.partialJson ?? "";
3064
- const completedArguments = typeof item.arguments === "string" ? item.arguments : void 0;
3065
- if (streamingToolCall && !streamingToolCall.argumentStreamReliable && !completedArguments) continue;
3066
- const finalArguments = completedArguments !== void 0 && (completedArguments.length > 0 || !streamedArguments) ? completedArguments : streamedArguments;
3067
- const validated = resolveCompletedResponsesToolCall(item, {
3068
- name: streamingToolCall?.block.name,
3069
- arguments: finalArguments
3070
- });
3071
- let toolCall;
3072
- let contentIndex;
3073
- if (streamingToolCall) {
3074
- const block = streamingToolCall.block;
3075
- block.id = resolveResponsesToolCallId(item, block.id);
3076
- block.name = validated.name;
3077
- block.arguments = validated.arguments;
3078
- delete block.partialJson;
3079
- toolCall = block;
3080
- contentIndex = streamingToolCall.contentIndex;
3081
- } else {
3082
- toolCall = {
3083
- type: "toolCall",
3084
- id: resolveResponsesToolCallId(item),
3085
- name: validated.name,
3086
- arguments: validated.arguments
3087
- };
3088
- blocks.push(toolCall);
3089
- contentIndex = blockIndex();
3114
+ let toolCall;
3115
+ let contentIndex;
3116
+ if (streamingToolCall) {
3117
+ const block = streamingToolCall.block;
3118
+ block.id = resolveResponsesToolCallId(item, block.id);
3119
+ block.name = validated.name;
3120
+ block.arguments = validated.arguments;
3121
+ delete block.partialJson;
3122
+ toolCall = block;
3123
+ contentIndex = streamingToolCall.contentIndex;
3124
+ } else {
3125
+ toolCall = {
3126
+ type: "toolCall",
3127
+ id: resolveResponsesToolCallId(item),
3128
+ name: validated.name,
3129
+ arguments: validated.arguments
3130
+ };
3131
+ blocks.push(toolCall);
3132
+ contentIndex = blocks.length - 1;
3133
+ stream.push({
3134
+ type: "toolcall_start",
3135
+ contentIndex,
3136
+ partial: output
3137
+ });
3138
+ }
3139
+ if (streamingToolCall) {
3140
+ streamingToolCalls.forget(streamingToolCall);
3141
+ for (const slot of outputSlots.values()) if (slot.type === "toolCall" && slot.toolCall === streamingToolCall) outputSlots.forget(slot);
3142
+ }
3090
3143
  stream.push({
3091
- type: "toolcall_start",
3144
+ type: "toolcall_end",
3092
3145
  contentIndex,
3146
+ toolCall,
3093
3147
  partial: output
3094
3148
  });
3149
+ outputItemContentIndexes.set(item, contentIndex);
3095
3150
  }
3096
- if (streamingToolCall) {
3097
- streamingToolCalls.forget(streamingToolCall);
3098
- for (const slot of outputSlots.values()) if (slot.type === "toolCall" && slot.toolCall === streamingToolCall) outputSlots.forget(slot);
3099
- }
3100
- stream.push({
3101
- type: "toolcall_end",
3102
- contentIndex,
3103
- toolCall,
3104
- partial: output
3105
- });
3106
- completedOutputItemIdentities.add(`function_call:${item.call_id}`);
3151
+ } else if (event.type === "response.completed" || event.type === "response.incomplete") {
3152
+ if (streamingToolCalls.hasActive()) throw new Error("Responses stream completed with unresolved tool calls");
3153
+ finalizeResponse(event.response, event.type);
3154
+ if (event.type === "response.completed" || output.stopReason === "length") recoverTerminalOutput(event.response.output ?? [], event.type === "response.completed");
3155
+ terminalResponse = event.type === "response.completed" ? event.response : null;
3156
+ if (output.stopReason === "stop" && output.content.some((block) => block.type === "toolCall")) output.stopReason = "toolUse";
3157
+ break;
3158
+ } else if (event.type === "error") throw new Error(event.message ? `Error Code ${event.code}: ${event.message}` : "Unknown error");
3159
+ else if (event.type === "response.failed") {
3160
+ const failure = normalizeResponsesFailedEvent(isRecord(event) ? event : {}, model);
3161
+ finalizeFailedResponse(event.response, failure.responseId);
3162
+ throw new ResponsesStreamFailure(failure, event.response);
3107
3163
  }
3108
- } else if (event.type === "response.completed" || event.type === "response.incomplete") {
3109
- if (streamingToolCalls.hasActive()) throw new Error("Responses stream completed with unresolved tool calls");
3110
- finalizeResponse(event.response, event.type);
3111
- if (event.type === "response.completed" || output.stopReason === "length") recoverTerminalOutput(event.response.output ?? [], event.type === "response.completed");
3112
- if (output.stopReason === "stop" && output.content.some((block) => block.type === "toolCall")) output.stopReason = "toolUse";
3113
- break;
3114
- } else if (event.type === "error") throw new Error(event.message ? `Error Code ${event.code}: ${event.message}` : "Unknown error");
3115
- else if (event.type === "response.failed") {
3116
- const failure = normalizeResponsesFailedEvent(event, model);
3117
- if (failure.responseId) output.responseId = failure.responseId;
3118
- throw new ResponsesStreamFailure(failure, event.response);
3119
3164
  }
3165
+ if (options?.signal?.aborted) throw transportAbortError(options.signal);
3120
3166
  if (streamingToolCalls.hasActive()) throw new Error("Responses stream ended with unresolved tool calls");
3121
- if (!terminalResponseEvent) throw new Error("OpenAI Responses stream ended before a terminal response event");
3167
+ if (terminalResponse === void 0) throw new Error("OpenAI Responses stream ended before a terminal response event");
3168
+ return terminalResponse ?? void 0;
3122
3169
  } finally {
3123
3170
  for (const block of output.content) delete block.partialJson;
3124
3171
  }
3125
3172
  }
3126
3173
  //#endregion
3127
- export { shouldOmitEmptyArrayItems as $, normalizeResponsesFailedEvent as A, responsesPromptObserver as B, prepareOpenAIResponsesReasoningItemForReplay as C, applyServiceTierPricing as D, tagOpenAIResponsesReasoningReplayItem as E, summarizeResponsesFailedNoDetailsObservation as F, normalizeOpenAIStrictToolParameters as G, clearOpenAIToolSchemaCacheForTest as H, summarizeResponsesPayload as I, findOpenAIStrictSchemaViolations as J, normalizeStrictOpenAIJsonSchema as K, summarizeResponsesTools as L, stringifyRedactedEvent as M, stringifyRedactedPayload as N, buildResponsesFailedNoDetailsObservation as O, summarizeOpenAITransportError as P, resolveUnsupportedToolSchemaKeywords as Q, AZURE_RESPONSES_FIRST_EVENT_TIMEOUT_MS as R, isInvalidEncryptedContentError as S, stripResponsesRequestEncryptedContent as T, findOpenAIStrictToolProjectionDiagnostics as U, resolveReplayableResponsesMessageId as V, isStrictOpenAIJsonSchemaCompatible as W, extractToolSchemaModelCompat as X, normalizeOpenAIStrictCompatSchema as Y, normalizeToolParameterSchema as Z, resolveResponsesMessageSnapshotCollapse as _, resolveModelSseDebugMode as _t, resolveResponsesTerminalStopReason as a, cleanSchemaForGemini as at, convertResponsesMessages as b, quoteUnsafeIntegerLiterals as bt, readResponsesToolCallItemIdentity as c, isOpenAIGpt56Model as ct, OPENAI_RESPONSES_OUTPUT_TEXT_CONTENT_PART_TYPE as d, resolveOpenAISupportedReasoningEfforts as dt, stripUnsupportedSchemaKeywords as et, OPENAI_RESPONSES_OUTPUT_TEXT_DELTA_EVENT_TYPE as f, supportsOpenAIReasoningEffort as ft, isResponsesTextDeltaEventType as g, resolveModelPayloadDebugMode as gt, isResponsesTextContentPartType as h, emitModelTransportDebug as ht, readResponsesReasoningTokens as i, GEMINI_UNSUPPORTED_SCHEMA_KEYWORDS as it, safeDebugValue as j, logResponsesFailedNoDetails as k, AZURE_RESPONSES_TEXT_CONTENT_PART_TYPE as l, normalizeOpenAIReasoningEffort as lt, isAzureResponsesTextDeltaEventType as m, uniqueStrings as mt, processResponsesStream as n, cleanSchemaForLlamacppGbnf as nt, observeResponsesStream as o, isOpenAIGpt54MiniModel as ot, isAzureResponsesTextDeltaEvent as p, supportsOpenAITemperature as pt, resolveOpenAIProjectedToolsStrictToolFlag as q, mapResponsesTerminalUsage as r, findLlamacppGbnfSchemaViolations as rt, createResponsesToolCallTracker as s, isOpenAIGpt55Model as st, ResponsesStreamFailure as t, LLAMACPP_GBNF_MAX_REPETITION_THRESHOLD as tt, AZURE_RESPONSES_TEXT_DELTA_EVENT_TYPE as u, resolveOpenAIReasoningEffortForModel as ut, buildOpenAIResponsesReasoningReplayMetadata as v, parseJsonObjectPreservingUnsafeIntegers as vt, resolveAzureOpenAIApiVersion as w, createResponsesStreamWithEncryptedContentRetry as x, buildResponsesInputMessage as y, parseJsonPreservingUnsafeIntegers as yt, OPENAI_CODEX_RESPONSES_DEFAULT_INSTRUCTIONS as z };
3174
+ //#region packages/ai/src/providers/openai-responses-tools.ts
3175
+ const LOG_SUBSYSTEM = "llm/openai-responses";
3176
+ const MAX_STRICT_TOOL_DOWNGRADE_DIAGNOSTIC_KEYS = 64;
3177
+ const loggedStrictToolDowngradeDiagnosticKeys = /* @__PURE__ */ new Set();
3178
+ /** Converts and returns the projection used to reconcile tool choices. */
3179
+ function convertResponsesToolPayload(tools, options) {
3180
+ const projection = projectOpenAITools(tools);
3181
+ const strict = resolveResponsesStrictToolFlag(projection, resolveResponsesStrictToolSetting(options), options?.model);
3182
+ return {
3183
+ projection,
3184
+ tools: sortPromptCacheToolsByName(projection.tools).map((tool) => {
3185
+ const result = {
3186
+ type: "function",
3187
+ name: tool.name,
3188
+ description: tool.description,
3189
+ parameters: normalizeOpenAIStrictToolParameters(tool.parameters, strict === true, options?.model?.compat)
3190
+ };
3191
+ if (strict !== void 0) result.strict = strict;
3192
+ return result;
3193
+ })
3194
+ };
3195
+ }
3196
+ function resolveResponsesStrictToolSetting(options) {
3197
+ if (options?.strict !== void 0) return options.strict;
3198
+ if (options?.model) return getAiTransportHost().resolveOpenAIStrictToolSetting(options.model, {
3199
+ transport: "stream",
3200
+ supportsStrictMode: options.supportsStrictMode
3201
+ });
3202
+ return false;
3203
+ }
3204
+ function resolveResponsesStrictToolFlag(projection, strictSetting, model) {
3205
+ const strict = resolveOpenAIProjectedToolsStrictToolFlag(projection, strictSetting);
3206
+ if (strictSetting === true && strict === false && model) getAiTransportHost().logDebug(LOG_SUBSYSTEM, () => {
3207
+ const diagnostics = findOpenAIStrictToolProjectionDiagnostics(projection);
3208
+ if (!shouldLogStrictToolDowngradeDiagnostic(diagnostics, model)) return null;
3209
+ const sample = diagnostics.slice(0, 5).map((entry) => ({
3210
+ tool: entry.toolName ?? `tool[${entry.toolIndex}]`,
3211
+ violations: entry.violations.slice(0, 8)
3212
+ }));
3213
+ return {
3214
+ message: `OpenAI responses tool schema strict mode downgraded to strict=false for ${model.provider ?? "unknown"}/${model.id ?? "unknown"} because ${diagnostics.length} tool schema(s) are not strict-compatible`,
3215
+ data: {
3216
+ provider: model.provider,
3217
+ model: model.id,
3218
+ incompatibleToolCount: diagnostics.length,
3219
+ sample
3220
+ }
3221
+ };
3222
+ });
3223
+ return strict;
3224
+ }
3225
+ function shouldLogStrictToolDowngradeDiagnostic(diagnostics, model) {
3226
+ const key = createHash("sha256").update(JSON.stringify({
3227
+ provider: model.provider,
3228
+ model: model.id,
3229
+ diagnostics: diagnostics.map((entry) => ({
3230
+ toolIndex: entry.toolIndex,
3231
+ toolName: entry.toolName ?? null,
3232
+ violations: entry.violations
3233
+ }))
3234
+ })).digest("hex");
3235
+ if (loggedStrictToolDowngradeDiagnosticKeys.has(key)) return false;
3236
+ if (loggedStrictToolDowngradeDiagnosticKeys.size >= MAX_STRICT_TOOL_DOWNGRADE_DIAGNOSTIC_KEYS) loggedStrictToolDowngradeDiagnosticKeys.clear();
3237
+ loggedStrictToolDowngradeDiagnosticKeys.add(key);
3238
+ return true;
3239
+ }
3240
+ //#endregion
3241
+ //#region packages/ai/src/providers/openai-responses-shared.ts
3242
+ function isResponsesReasoningEffort(effort) {
3243
+ return effort === "minimal" || effort === "low" || effort === "medium" || effort === "high" || effort === "xhigh" || effort === "max";
3244
+ }
3245
+ function convertResponsesMessages(model, context, allowedToolCallProviders, options) {
3246
+ return convertProviderResponsesMessages(model, context, allowedToolCallProviders, options);
3247
+ }
3248
+ const createResponsesAssistantOutput = createOpenAIResponsesAssistantOutput;
3249
+ function applyResponsesServiceTierPricing(usage, serviceTier, model) {
3250
+ let multiplier = 1;
3251
+ if (serviceTier === "flex") multiplier = .5;
3252
+ else if (serviceTier === "priority") multiplier = model.id === "gpt-5.5" ? 2.5 : 2;
3253
+ if (multiplier === 1) return;
3254
+ usage.cost.input *= multiplier;
3255
+ usage.cost.output *= multiplier;
3256
+ usage.cost.cacheRead *= multiplier;
3257
+ usage.cost.cacheWrite *= multiplier;
3258
+ usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
3259
+ }
3260
+ function resolveResponsesReasoningEffort(model, reasoning) {
3261
+ const clampedReasoning = reasoning ? clampThinkingLevel(model, reasoning) : void 0;
3262
+ if (!clampedReasoning || clampedReasoning === "off") return;
3263
+ if (clampedReasoning === "max") return supportsOpenAIReasoningEffort(model, "max") ? "max" : "xhigh";
3264
+ if (clampedReasoning === "minimal" && model.provider === "openai" && supportsOpenAIReasoningEffort(model, "max")) {
3265
+ const effort = resolveOpenAIReasoningEffortForModel({
3266
+ model,
3267
+ effort: "minimal"
3268
+ });
3269
+ return isResponsesReasoningEffort(effort) ? effort : void 0;
3270
+ }
3271
+ return clampedReasoning;
3272
+ }
3273
+ function applyCommonResponsesParams(params, model, context, options, config) {
3274
+ if (options?.maxTokens) params.max_output_tokens = Math.max(options.maxTokens, 16);
3275
+ if (options?.temperature !== void 0 && supportsOpenAITemperature(model)) params.temperature = options.temperature;
3276
+ if (context.tools) {
3277
+ const converted = convertResponsesToolPayload(context.tools, { model });
3278
+ if (converted.tools.length > 0) params.tools = converted.tools;
3279
+ }
3280
+ if (!model.reasoning) return;
3281
+ if (options?.reasoningEffort || options?.reasoningSummary) {
3282
+ params.reasoning = {
3283
+ effort: options?.reasoningEffort ? model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort : "medium",
3284
+ summary: options?.reasoningSummary || "auto"
3285
+ };
3286
+ params.include = ["reasoning.encrypted_content"];
3287
+ } else if ((config?.setDefaultReasoningOff ?? true) && model.thinkingLevelMap?.off !== null) params.reasoning = { effort: model.thinkingLevelMap?.off ?? "none" };
3288
+ }
3289
+ function buildResponsesRequestOptions(options) {
3290
+ return {
3291
+ ...options?.signal ? { signal: options.signal } : {},
3292
+ ...options?.timeoutMs !== void 0 ? { timeout: options.timeoutMs } : {},
3293
+ maxRetries: options?.maxRetries ?? 0
3294
+ };
3295
+ }
3296
+ function cleanStreamingScratchBuffers(output) {
3297
+ for (const block of output.content) {
3298
+ delete block.index;
3299
+ delete block.partialJson;
3300
+ }
3301
+ }
3302
+ async function runResponsesStreamLifecycle(params) {
3303
+ const { stream, output, options } = params;
3304
+ let firstEventAbort;
3305
+ try {
3306
+ const model = params.resolveRequestModel?.(params.model) ?? params.model;
3307
+ const client = params.createClient(model);
3308
+ const buildRequest = async (replayMode) => {
3309
+ let request = params.buildParams(model, replayMode);
3310
+ const nextRequest = await options?.onPayload?.(request, model);
3311
+ if (nextRequest !== void 0) request = nextRequest;
3312
+ return request;
3313
+ };
3314
+ const requestParams = await buildRequest("checkpoint");
3315
+ firstEventAbort = createFirstStreamEventAbortController(options?.signal);
3316
+ const { stream: openaiStream, response } = await createResponsesStreamWithEncryptedContentRetry({
3317
+ client,
3318
+ request: requestParams,
3319
+ requestOptions: {
3320
+ ...buildResponsesRequestOptions(options),
3321
+ signal: firstEventAbort.signal
3322
+ },
3323
+ model,
3324
+ buildFullHistoryRequest: () => buildRequest("full-history"),
3325
+ onCompactionRejected: (checkpoint) => suppressOpenAIResponsesCompaction(output, model, options, checkpoint)
3326
+ });
3327
+ const hookedOpenAIStream = withProviderResponseHook({
3328
+ stream: openaiStream,
3329
+ signal: firstEventAbort.signal,
3330
+ abort: firstEventAbort.abort,
3331
+ hook: createOpenAIProviderAcceptanceHook(options, response, model),
3332
+ onReady: () => stream.push({
3333
+ type: "start",
3334
+ partial: output
3335
+ })
3336
+ });
3337
+ const firstEventTimeoutMs = getFirstStreamEventTimeoutMs(options);
3338
+ const onFirstEventTimeout = getFirstStreamEventTimeoutHandler(options);
3339
+ await processResponsesStream(hookedOpenAIStream, output, stream, model, {
3340
+ ...params.processStreamOptions || firstEventTimeoutMs !== void 0 || onFirstEventTimeout !== void 0 ? {
3341
+ ...params.processStreamOptions,
3342
+ firstEventTimeoutMs: params.processStreamOptions?.firstEventTimeoutMs ?? firstEventTimeoutMs,
3343
+ abortFirstEventStream: params.processStreamOptions?.abortFirstEventStream ?? firstEventAbort.abort,
3344
+ onFirstEventTimeout: params.processStreamOptions?.onFirstEventTimeout ?? onFirstEventTimeout,
3345
+ signal: params.processStreamOptions?.signal ?? options?.signal
3346
+ } : void 0,
3347
+ reasoningReplayMetadata: buildOpenAIResponsesReasoningReplayMetadata(model, {
3348
+ sessionId: options?.sessionId,
3349
+ authProfileId: options?.authProfileId
3350
+ })
3351
+ });
3352
+ if (options?.signal?.aborted) throw transportAbortError(options.signal);
3353
+ if (output.stopReason === "aborted" || output.stopReason === "error") throw new Error(output.errorMessage ?? "An unknown error occurred");
3354
+ stream.push({
3355
+ type: "done",
3356
+ reason: output.stopReason,
3357
+ message: output
3358
+ });
3359
+ stream.end();
3360
+ } catch (error) {
3361
+ cleanStreamingScratchBuffers(output);
3362
+ const terminal = projectProviderError(error, options?.signal);
3363
+ Object.assign(output, terminal);
3364
+ stream.push({
3365
+ type: "error",
3366
+ reason: terminal.stopReason,
3367
+ error: output
3368
+ });
3369
+ stream.end();
3370
+ } finally {
3371
+ firstEventAbort?.dispose();
3372
+ }
3373
+ }
3374
+ //#endregion
3375
+ export { normalizeOpenAIStrictCompatSchema as $, isAzureResponsesTextDeltaEvent as A, buildResponsesInputMessage as B, summarizeResponsesTools as C, AZURE_RESPONSES_TEXT_DELTA_EVENT_TYPE as D, AZURE_RESPONSES_TEXT_CONTENT_PART_TYPE as E, commitResponsesEncryptedContentAttempt as F, suppressOpenAIResponsesCompaction as G, createOpenAIResponsesAssistantOutput as H, createResponsesStreamWithEncryptedContentRetry as I, isStrictOpenAIJsonSchemaCompatible as J, resolveReplayableResponsesMessageId as K, isInvalidEncryptedContentError as L, isResponsesTextContentPartType as M, isResponsesTextDeltaEventType as N, OPENAI_RESPONSES_OUTPUT_TEXT_CONTENT_PART_TYPE as O, resolveResponsesMessageSnapshotCollapse as P, findOpenAIStrictSchemaViolations as Q, resolveAzureOpenAIApiVersion as R, summarizeResponsesPayload as S, readResponsesToolCallItemIdentity as T, buildOpenAIResponsesReasoningReplayMetadata as U, convertResponsesMessages$1 as V, captureOpenAIResponsesCompaction as W, normalizeStrictOpenAIJsonSchema as X, normalizeOpenAIStrictToolParameters as Y, resolveOpenAIProjectedToolsStrictToolFlag as Z, safeDebugValue as _, resolveResponsesReasoningEffort as a, LLAMACPP_GBNF_MAX_REPETITION_THRESHOLD as at, summarizeOpenAITransportError as b, processResponsesStream as c, GEMINI_UNSUPPORTED_SCHEMA_KEYWORDS as ct, resolveResponsesTerminalStopReason as d, resolveModelPayloadDebugMode as dt, extractToolSchemaModelCompat as et, observeResponsesStream as f, resolveModelSseDebugMode as ft, normalizeResponsesFailedEvent as g, logResponsesFailedNoDetails as h, createResponsesAssistantOutput as i, stripUnsupportedSchemaKeywords as it, isAzureResponsesTextDeltaEventType as j, OPENAI_RESPONSES_OUTPUT_TEXT_DELTA_EVENT_TYPE as k, mapResponsesTerminalUsage as l, cleanSchemaForGemini as lt, buildResponsesFailedNoDetailsObservation as m, applyResponsesServiceTierPricing as n, resolveUnsupportedToolSchemaKeywords as nt, runResponsesStreamLifecycle as o, cleanSchemaForLlamacppGbnf as ot, ResponsesStreamFailure as p, findOpenAIStrictToolProjectionDiagnostics as q, convertResponsesMessages as r, shouldOmitEmptyArrayItems as rt, convertResponsesToolPayload as s, findLlamacppGbnfSchemaViolations as st, applyCommonResponsesParams as t, normalizeToolParameterSchema as tt, readResponsesReasoningTokens as u, emitModelTransportDebug as ut, stringifyRedactedEvent as v, createResponsesToolCallTracker as w, summarizeResponsesFailedNoDetailsObservation as x, stringifyRedactedPayload as y, resolveNextResponsesEncryptedContentAttempt as z };