@openclaw/ai 2026.7.2-beta.7 → 2026.8.1-beta.2

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 (91) hide show
  1. package/dist/{anthropic-CH4UUnZr.mjs → anthropic-B6dLpq5L.mjs} +55 -203
  2. package/dist/{src-QkygScBs.mjs → anthropic-JsNA5KCu.mjs} +0 -1
  3. package/dist/anthropic-compaction-replay-8lJNKXOE.mjs +840 -0
  4. package/dist/anthropic-payload-policy-CiEuQS72.d.mts +49 -0
  5. package/dist/{api-registry-DlMgPR39.d.mts → api-registry-k3zTz0cV.d.mts} +1 -1
  6. package/dist/{azure-openai-responses-CImcwB83.mjs → azure-openai-responses-mxIOtUnn.mjs} +23 -29
  7. package/dist/diagnostics.d.mts +24 -1
  8. package/dist/diagnostics.mjs +2 -1
  9. package/dist/{event-stream-YjaPW20U.d.mts → event-stream-BP6AWT8j.d.mts} +4 -1
  10. package/dist/{event-stream-D8n2uFee.mjs → event-stream-uSMZJ3FA.mjs} +26 -5
  11. package/dist/event-stream.d.mts +1 -1
  12. package/dist/event-stream.mjs +1 -1
  13. package/dist/{google-CtSg0iTS.mjs → google-C7h2QzDX.mjs} +5 -5
  14. package/dist/{google-shared-DNBz5rcD.mjs → google-shared-B0Qr9OR7.mjs} +146 -89
  15. package/dist/google-thinking-level-C-V3tecN.mjs +9 -0
  16. package/dist/{google-vertex-31f1uS9L.mjs → google-vertex-Bhc3TjDl.mjs} +11 -7
  17. package/dist/{llm-request-activity-BjtkplhG.mjs → headers-DdOQtGuU.mjs} +9 -1
  18. package/dist/host-DTqNc7ad.mjs +466 -0
  19. package/dist/{host-B9GUmcra.d.mts → host-vWgMMhiJ.d.mts} +9 -4
  20. package/dist/index.d.mts +6 -6
  21. package/dist/index.mjs +7 -5
  22. package/dist/internal/anthropic.d.mts +29 -5
  23. package/dist/internal/anthropic.mjs +5 -5
  24. package/dist/internal/openai-responses-payload-policy.d.mts +3 -0
  25. package/dist/internal/openai-responses-payload-policy.mjs +3 -0
  26. package/dist/internal/openai.d.mts +6 -6
  27. package/dist/internal/openai.mjs +8 -7
  28. package/dist/internal/runtime.d.mts +17 -5
  29. package/dist/internal/runtime.mjs +85 -73
  30. package/dist/internal/shared.d.mts +1 -6
  31. package/dist/internal/shared.mjs +3 -5
  32. package/dist/{json-parse-BvXNt1-7.mjs → json-parse-CDnesDM_.mjs} +4 -6
  33. package/dist/{mistral-CWmpvWYh.mjs → mistral-CEWoQI_g.mjs} +45 -48
  34. package/dist/number-coercion-H9qHik3g.mjs +71 -0
  35. package/dist/openai-chatgpt-jwt-KWcgd0d_.mjs +19 -0
  36. package/dist/{openai-chatgpt-responses-B84Ibtrd.mjs → openai-chatgpt-responses-CrPmqERt.mjs} +284 -240
  37. package/dist/{openai-completions-DsOxhOD1.mjs → openai-completions-BPnt4Sml.mjs} +65 -99
  38. package/dist/{openai-completions-compat-DBWjXoMZ.d.mts → openai-completions-compat-Dt3dcawL.d.mts} +2 -2
  39. package/dist/{openai-responses-BT7A3sLu.mjs → openai-responses-DhIKtOup.mjs} +18 -41
  40. package/dist/openai-responses-contracts-CyfIkQi5.mjs +253 -0
  41. package/dist/openai-responses-contracts-XpZJxrRG.d.mts +68 -0
  42. package/dist/openai-responses-payload-policy-BDxV-W0c.mjs +206 -0
  43. package/dist/openai-responses-payload-policy-BSs371VM.d.mts +40 -0
  44. package/dist/openai-responses-prompt-observer-internal-DgNTYnRY.mjs +46 -0
  45. package/dist/{openai-responses-stream-internal-Cw5txaGW.mjs → openai-responses-shared-DXIt3iY5.mjs} +1406 -940
  46. package/dist/{openai-reasoning-compat-YgeLncHw.mjs → openai-stop-reason-BkFkqqK0.mjs} +204 -37
  47. package/dist/openai-tool-projection-CY04OcvQ.mjs +338 -0
  48. package/dist/provider-error-BUwEnjXq.mjs +429 -0
  49. package/dist/provider-error-CzNw4BWX.d.mts +12 -0
  50. package/dist/{provider-options-D8bB3z9b.d.mts → provider-options-B96RdNpH.d.mts} +9 -3
  51. package/dist/provider-transcript-transform-ePx-Bbfr.mjs +155 -0
  52. package/dist/provider-types.d.mts +31 -0
  53. package/dist/provider-types.mjs +8 -0
  54. package/dist/providers.d.mts +1 -1
  55. package/dist/providers.mjs +17 -19
  56. package/dist/{reasoning-tag-text-partitioner-CGDyLWUR.mjs → reasoning-tag-text-partitioner-rnPwX2pg.mjs} +14 -8
  57. package/dist/record-coerce-DdXsgUd_.mjs +23 -0
  58. package/dist/sanitize-unicode-BYqrYtC_.mjs +90 -0
  59. package/dist/session-resources-CkR4WWy1.mjs +21 -0
  60. package/dist/simple-options-D58D5Kvw.mjs +117 -0
  61. package/dist/src-D2H6yKkH.mjs +2 -0
  62. package/dist/{stream-first-event-timeout-BBys9hSb.mjs → stream-first-event-timeout-MK28puvq.mjs} +2 -2
  63. package/dist/string-coerce-fsri9iCu.mjs +34 -0
  64. package/dist/{tool-schema-json-projection-BwNu3nDi.mjs → tool-schema-json-projection-q5d7QX5c.mjs} +32 -7
  65. package/dist/transport-utils-DJqkxbhC.mjs +138 -0
  66. package/dist/transports.d.mts +166 -241
  67. package/dist/transports.mjs +1979 -1825
  68. package/dist/types-BDdaOVi2.mjs +6 -0
  69. package/dist/{types-bzp5k29J.d.mts → types-BHNrPS1l.d.mts} +23 -1
  70. package/dist/types.d.mts +4 -4
  71. package/dist/types.mjs +6 -4
  72. package/dist/utf16-slice-CvGodqok.mjs +29 -0
  73. package/dist/{validation-DAa_yFOM.mjs → validation-B61OhAio.mjs} +6 -6
  74. package/dist/{validation-B-j7cOYp.d.mts → validation-DT9SrFn3.d.mts} +1 -1
  75. package/dist/validation.d.mts +1 -1
  76. package/dist/validation.mjs +1 -1
  77. package/package.json +15 -1
  78. package/dist/anthropic-usage-DWU-x8MI.mjs +0 -459
  79. package/dist/error-coercion-DgxlWC0n.mjs +0 -15
  80. package/dist/headers-B_e4-1J0.mjs +0 -9
  81. package/dist/host-Dog2WQiR.mjs +0 -369
  82. package/dist/number-coercion-DvG7SNMg.mjs +0 -129
  83. package/dist/openai-chatgpt-jwt-DhAAzLkj.mjs +0 -39
  84. package/dist/openai-responses-shared-pXl6Wd8S.mjs +0 -392
  85. package/dist/openai-tool-projection-OhX64DoP.mjs +0 -215
  86. package/dist/provider-error-CAEvRjry.mjs +0 -47
  87. package/dist/sanitize-unicode-DT5o51ur.mjs +0 -26
  88. package/dist/simple-options-9lhRrN73.mjs +0 -50
  89. package/dist/tool-result-text-CTpIRbYd.mjs +0 -225
  90. package/dist/transform-messages-C8mBqZxF.mjs +0 -2
  91. package/dist/transport-stream-shared-D81p90xq.mjs +0 -297
@@ -1,31 +1,134 @@
1
- import { g as isRecord, m as normalizeOptionalString, n as getAiTransportHost, p as normalizeLowercaseStringOrEmpty } from "./host-Dog2WQiR.mjs";
2
- import { n as clampOpenAIPromptCacheKey } from "./openai-prompt-cache-mZTCdRPo.mjs";
3
- import { a as isImageWithMediaPayload, d as stripSystemPromptCacheBoundary, o as truncateUtf16Safe, r as extractToolResultText, t as describeToolResultMediaPlaceholder } from "./tool-result-text-CTpIRbYd.mjs";
4
- import { u as transformTransportMessages } from "./openai-tool-projection-OhX64DoP.mjs";
5
- import { c as calculateCost } from "./number-coercion-DvG7SNMg.mjs";
6
- import { n as parseStreamingJson } from "./json-parse-BvXNt1-7.mjs";
7
- import { b as redactIdentifier, d as transportAbortError, l as sanitizeNonEmptyTransportPayloadText, u as sanitizeTransportPayloadText, x as redactSensitiveText } from "./transport-stream-shared-D81p90xq.mjs";
8
- import { a as withFirstStreamEventTimeout } from "./stream-first-event-timeout-BBys9hSb.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-BYqrYtC_.mjs";
3
+ import { a as describeToolResultMediaPlaceholder, l as isImageWithMediaPayload, n as getAiTransportHost, s as extractToolResultText } from "./host-DTqNc7ad.mjs";
4
+ import { a as isRecord, n as asNullableRecord } from "./record-coerce-DdXsgUd_.mjs";
5
+ import { t as truncateUtf16Safe } from "./utf16-slice-CvGodqok.mjs";
6
+ import { n as projectProviderError } from "./provider-error-BUwEnjXq.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, 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-CyfIkQi5.mjs";
9
+ import { f as sortPromptCacheToolsByName, l as stripSystemPromptCacheBoundary } from "./simple-options-D58D5Kvw.mjs";
10
+ import { c as transformTransportMessages } from "./tool-schema-json-projection-q5d7QX5c.mjs";
11
+ import { n as parseStreamingJson } from "./json-parse-CDnesDM_.mjs";
12
+ import { n as notifyLlmRequestActivity } from "./headers-DdOQtGuU.mjs";
9
13
  import { t as shortHash } from "./hash-CHgqbJmD.mjs";
10
- import { randomUUID } from "node:crypto";
11
- //#region packages/ai/src/transports/model-transport-debug.ts
12
- function normalizeEnv(value) {
13
- return typeof value === "string" ? value.trim().toLowerCase() : "";
14
+ import { d as sanitizeTransportPayloadText, f as transportAbortError, p as withProviderResponseHook, t as transformProviderMessages, u as sanitizeNonEmptyTransportPayloadText } from "./provider-transcript-transform-ePx-Bbfr.mjs";
15
+ import { l as redactIdentifier, u as redactSensitiveText } from "./transport-utils-DJqkxbhC.mjs";
16
+ import { a as createModelStreamCooperativeScheduler, c as log, o as createOpenAIResponseHook, t as projectOpenAITools } from "./openai-tool-projection-CY04OcvQ.mjs";
17
+ import { a as withFirstStreamEventTimeout, i as getFirstStreamEventTimeoutMs, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-MK28puvq.mjs";
18
+ import { createHash, randomUUID } from "node:crypto";
19
+ //#region packages/ai/src/transports/json-unsafe-integers.ts
20
+ /**
21
+ * JSON parsing helpers that preserve integer literals larger than
22
+ * Number.MAX_SAFE_INTEGER as strings before JSON.parse can round them.
23
+ */
24
+ const MAX_SAFE_INTEGER_ABS_STR = String(Number.MAX_SAFE_INTEGER);
25
+ function isAsciiDigit(ch) {
26
+ return ch !== void 0 && ch >= "0" && ch <= "9";
27
+ }
28
+ function parseJsonNumberToken(input, start) {
29
+ let idx = start;
30
+ if (input[idx] === "-") idx += 1;
31
+ if (idx >= input.length) return null;
32
+ if (input[idx] === "0") idx += 1;
33
+ else if (isAsciiDigit(input[idx]) && input[idx] !== "0") while (isAsciiDigit(input[idx])) idx += 1;
34
+ else return null;
35
+ let isInteger = true;
36
+ if (input[idx] === ".") {
37
+ isInteger = false;
38
+ idx += 1;
39
+ if (!isAsciiDigit(input[idx])) return null;
40
+ while (isAsciiDigit(input[idx])) idx += 1;
41
+ }
42
+ if (input[idx] === "e" || input[idx] === "E") {
43
+ isInteger = false;
44
+ idx += 1;
45
+ if (input[idx] === "+" || input[idx] === "-") idx += 1;
46
+ if (!isAsciiDigit(input[idx])) return null;
47
+ while (isAsciiDigit(input[idx])) idx += 1;
48
+ }
49
+ return {
50
+ token: input.slice(start, idx),
51
+ end: idx,
52
+ isInteger
53
+ };
54
+ }
55
+ function isUnsafeIntegerLiteral(token) {
56
+ const digits = token[0] === "-" ? token.slice(1) : token;
57
+ if (digits.length < MAX_SAFE_INTEGER_ABS_STR.length) return false;
58
+ if (digits.length > MAX_SAFE_INTEGER_ABS_STR.length) return true;
59
+ return digits > MAX_SAFE_INTEGER_ABS_STR;
60
+ }
61
+ /** Quotes integer literals above Number.MAX_SAFE_INTEGER before JSON.parse. */
62
+ function quoteUnsafeIntegerLiterals(input) {
63
+ let out = "";
64
+ let inString = false;
65
+ let escaped = false;
66
+ let idx = 0;
67
+ while (idx < input.length) {
68
+ const ch = input[idx] ?? "";
69
+ if (inString) {
70
+ out += ch;
71
+ if (escaped) escaped = false;
72
+ else if (ch === "\\") escaped = true;
73
+ else if (ch === "\"") inString = false;
74
+ idx += 1;
75
+ continue;
76
+ }
77
+ if (ch === "\"") {
78
+ inString = true;
79
+ out += ch;
80
+ idx += 1;
81
+ continue;
82
+ }
83
+ if (ch === "-" || isAsciiDigit(ch)) {
84
+ const parsed = parseJsonNumberToken(input, idx);
85
+ if (parsed) {
86
+ if (parsed.isInteger && isUnsafeIntegerLiteral(parsed.token)) out += `"${parsed.token}"`;
87
+ else out += parsed.token;
88
+ idx = parsed.end;
89
+ continue;
90
+ }
91
+ }
92
+ out += ch;
93
+ idx += 1;
94
+ }
95
+ return out;
14
96
  }
97
+ /** Parses JSON while preserving unsafe integer literals as strings. */
98
+ function parseJsonPreservingUnsafeIntegers(input) {
99
+ return JSON.parse(quoteUnsafeIntegerLiterals(input));
100
+ }
101
+ /** Parses or accepts an object while preserving unsafe integer literals in string input. */
102
+ function parseJsonObjectPreservingUnsafeIntegers(value) {
103
+ if (typeof value === "string") try {
104
+ return asNullableRecord(parseJsonPreservingUnsafeIntegers(value));
105
+ } catch {
106
+ return null;
107
+ }
108
+ return asNullableRecord(value);
109
+ }
110
+ //#endregion
111
+ //#region packages/ai/src/transports/model-transport-debug.ts
112
+ /**
113
+ * Environment-driven debug controls for model transport logging.
114
+ *
115
+ * Model adapters share these helpers so payload, SSE, and transport diagnostics
116
+ * interpret OpenClaw debug environment variables consistently.
117
+ */
15
118
  function isTruthyEnv(value) {
16
- const normalized = normalizeEnv(value);
119
+ const normalized = normalizeLowercaseStringOrEmpty(value);
17
120
  return normalized.length > 0 && normalized !== "0" && normalized !== "false" && normalized !== "off" && normalized !== "no";
18
121
  }
19
122
  /** Resolves model payload debug verbosity from `OPENCLAW_DEBUG_MODEL_PAYLOAD`. */
20
123
  function resolveModelPayloadDebugMode(env = process.env) {
21
- const normalized = normalizeEnv(env.OPENCLAW_DEBUG_MODEL_PAYLOAD);
124
+ const normalized = normalizeLowercaseStringOrEmpty(env.OPENCLAW_DEBUG_MODEL_PAYLOAD);
22
125
  if (normalized === "tools" || normalized === "full-redacted") return normalized;
23
126
  if (normalized === "summary") return "summary";
24
127
  return "off";
25
128
  }
26
129
  /** Resolves SSE stream debug verbosity from `OPENCLAW_DEBUG_SSE`. */
27
130
  function resolveModelSseDebugMode(env = process.env) {
28
- const normalized = normalizeEnv(env.OPENCLAW_DEBUG_SSE);
131
+ const normalized = normalizeLowercaseStringOrEmpty(env.OPENCLAW_DEBUG_SSE);
29
132
  if (normalized === "peek") return "peek";
30
133
  if (normalized === "events" || isTruthyEnv(normalized)) return "events";
31
134
  return "off";
@@ -46,173 +149,6 @@ function emitModelTransportDebug(log, message) {
46
149
  log.debug(message);
47
150
  }
48
151
  //#endregion
49
- //#region packages/normalization-core/src/string-normalization.ts
50
- /** Coerces entries to strings, trims them, and drops empty results. */
51
- function normalizeStringEntries(list) {
52
- return (list ?? []).map((entry) => normalizeOptionalString(String(entry)) ?? "").filter(Boolean);
53
- }
54
- /** Returns first-seen unique values while preserving insertion order. */
55
- function uniqueValues(values) {
56
- return [...new Set(values)];
57
- }
58
- /** Returns first-seen unique strings while preserving insertion order. */
59
- function uniqueStrings(values) {
60
- return uniqueValues(values);
61
- }
62
- //#endregion
63
- //#region packages/ai/src/providers/openai-reasoning-effort.ts
64
- /**
65
- * OpenAI-compatible reasoning-effort normalization. Different GPT families
66
- * expose different accepted effort enums, so callers map requested values here
67
- * before constructing provider payloads.
68
- */
69
- const GPT_5_REASONING_EFFORTS = [
70
- "minimal",
71
- "low",
72
- "medium",
73
- "high"
74
- ];
75
- const GPT_51_REASONING_EFFORTS = [
76
- "none",
77
- "low",
78
- "medium",
79
- "high"
80
- ];
81
- const GPT_52_REASONING_EFFORTS = [
82
- "none",
83
- "low",
84
- "medium",
85
- "high",
86
- "xhigh"
87
- ];
88
- const GPT_56_REASONING_EFFORTS = [
89
- "none",
90
- "low",
91
- "medium",
92
- "high",
93
- "xhigh",
94
- "max"
95
- ];
96
- const GPT_CODEX_REASONING_EFFORTS = [
97
- "low",
98
- "medium",
99
- "high",
100
- "xhigh"
101
- ];
102
- const GPT_PRO_REASONING_EFFORTS = [
103
- "medium",
104
- "high",
105
- "xhigh"
106
- ];
107
- const GPT_5_PRO_REASONING_EFFORTS = ["high"];
108
- const GPT_51_CODEX_MAX_REASONING_EFFORTS = [
109
- "none",
110
- "medium",
111
- "high",
112
- "xhigh"
113
- ];
114
- const GPT_51_CODEX_MINI_REASONING_EFFORTS = ["medium"];
115
- const GENERIC_REASONING_EFFORTS = [
116
- "low",
117
- "medium",
118
- "high"
119
- ];
120
- const CANONICAL_REASONING_EFFORTS = /* @__PURE__ */ new Set([
121
- "none",
122
- "minimal",
123
- "low",
124
- "medium",
125
- "high",
126
- "xhigh",
127
- "max",
128
- "off"
129
- ]);
130
- function normalizeModelId(id) {
131
- return normalizeLowercaseStringOrEmpty(id ?? "").replace(/-\d{4}-\d{2}-\d{2}$/u, "");
132
- }
133
- /** Return whether a model is the GPT-5.4 mini family. */
134
- function isOpenAIGpt54MiniModel(model) {
135
- const id = normalizeModelId(typeof model.id === "string" ? model.id : void 0);
136
- return /^gpt-5\.4-mini(?:-|$)/u.test(id);
137
- }
138
- /** Return whether a model is the GPT-5.5 family. */
139
- function isOpenAIGpt55Model(model) {
140
- const id = normalizeModelId(typeof model.id === "string" ? model.id : void 0);
141
- const name = normalizeModelId(typeof model.name === "string" ? model.name : void 0);
142
- return /^gpt-5\.5(?:-|$)/u.test(id) || /^gpt-5\.5(?:\s|\(|-|$)/u.test(name);
143
- }
144
- /** Return whether a model is the GPT-5.6 family. */
145
- function isOpenAIGpt56Model(model) {
146
- const id = normalizeModelId(typeof model.id === "string" ? model.id : void 0);
147
- const name = normalizeModelId(typeof model.name === "string" ? model.name : void 0);
148
- return /^gpt-5\.6(?:-|$)/u.test(id) || /^gpt-5\.6(?:\s|\(|-|$)/u.test(name);
149
- }
150
- /** Normalize user-facing reasoning effort names to API effort names. */
151
- function normalizeOpenAIReasoningEffort(effort) {
152
- const trimmed = effort.trim();
153
- const folded = trimmed.toLowerCase();
154
- return CANONICAL_REASONING_EFFORTS.has(folded) ? folded : trimmed;
155
- }
156
- function readCompatReasoningEfforts(compat) {
157
- if (!compat || typeof compat !== "object") return;
158
- if (compat.supportsReasoningEffort === false) return [];
159
- const raw = compat.supportedReasoningEfforts;
160
- if (!Array.isArray(raw)) return;
161
- const supported = uniqueStrings(normalizeStringEntries(raw.filter((value) => typeof value === "string")));
162
- return supported.length > 0 ? supported : void 0;
163
- }
164
- function isDisabledReasoningEffort(effort) {
165
- return effort === "none" || effort === "off";
166
- }
167
- /** Resolve the reasoning efforts accepted by a specific OpenAI-compatible model. */
168
- function resolveOpenAISupportedReasoningEfforts(model) {
169
- const compatEfforts = readCompatReasoningEfforts(model.compat);
170
- if (compatEfforts) return compatEfforts;
171
- const id = normalizeModelId(typeof model.id === "string" ? model.id : void 0);
172
- if (/^gpt-5\.6(?:-|$)/u.test(id)) return GPT_56_REASONING_EFFORTS;
173
- if (id === "gpt-5.1-codex-mini") return GPT_51_CODEX_MINI_REASONING_EFFORTS;
174
- if (id === "gpt-5.1-codex-max") return GPT_51_CODEX_MAX_REASONING_EFFORTS;
175
- if (/^gpt-5(?:\.\d+)?-codex(?:-|$)/u.test(id)) return GPT_CODEX_REASONING_EFFORTS;
176
- if (id === "gpt-5-pro") return GPT_5_PRO_REASONING_EFFORTS;
177
- if (/^gpt-5\.[2-9](?:\.\d+)?-pro(?:-|$)/u.test(id)) return GPT_PRO_REASONING_EFFORTS;
178
- if (/^gpt-5\.[2-9](?:\.\d+)?(?:-|$)/u.test(id)) return GPT_52_REASONING_EFFORTS;
179
- if (/^gpt-5\.1(?:-|$)/u.test(id)) return GPT_51_REASONING_EFFORTS;
180
- if (/^gpt-5(?:-|$)/u.test(id)) return GPT_5_REASONING_EFFORTS;
181
- return GENERIC_REASONING_EFFORTS;
182
- }
183
- /**
184
- * Return whether a model accepts the temperature parameter. The GPT-5.6
185
- * family rejects it with a 400; catalog compat can override per model.
186
- */
187
- function supportsOpenAITemperature(model) {
188
- const compat = model.compat;
189
- if (compat && typeof compat === "object") {
190
- const declared = compat.supportsTemperature;
191
- if (typeof declared === "boolean") return declared;
192
- }
193
- const id = normalizeModelId(typeof model.id === "string" ? model.id : void 0);
194
- return !/^gpt-5\.6(?:-|$)/u.test(id);
195
- }
196
- /** Return whether a model accepts a requested reasoning effort. */
197
- function supportsOpenAIReasoningEffort(model, effort) {
198
- return resolveOpenAISupportedReasoningEfforts(model).includes(normalizeOpenAIReasoningEffort(effort));
199
- }
200
- /** Resolve a requested reasoning effort to the closest value supported by the model. */
201
- function resolveOpenAIReasoningEffortForModel(params) {
202
- const requested = normalizeOpenAIReasoningEffort(params.effort);
203
- const mapped = params.fallbackMap?.[requested] ?? (params.fallbackMap && CANONICAL_REASONING_EFFORTS.has(requested) ? Object.entries(params.fallbackMap).find(([effort]) => normalizeOpenAIReasoningEffort(effort) === requested)?.[1] : void 0);
204
- const normalized = mapped === void 0 ? requested : mapped.trim();
205
- const supported = resolveOpenAISupportedReasoningEfforts(params.model);
206
- if (supported.includes(normalized)) return normalized;
207
- if (requested === "off" && supported.includes("none")) return "none";
208
- if (isDisabledReasoningEffort(requested) || isDisabledReasoningEffort(normalized)) return;
209
- if (requested === "minimal" && supported.includes("low")) return "low";
210
- if ((requested === "minimal" || requested === "low") && supported.includes("medium")) return "medium";
211
- if (requested === "xhigh" && supported.includes("high")) return "high";
212
- if (requested === "max" && supported.includes("xhigh")) return "xhigh";
213
- return supported.find((effort) => !isDisabledReasoningEffort(normalizeOpenAIReasoningEffort(effort)));
214
- }
215
- //#endregion
216
152
  //#region packages/ai/src/providers/clean-for-gemini.ts
217
153
  const GEMINI_UNSUPPORTED_SCHEMA_KEYWORDS = /* @__PURE__ */ new Set([
218
154
  "patternProperties",
@@ -511,9 +447,6 @@ const SCHEMA_CHILD_KEYS = /* @__PURE__ */ new Set([
511
447
  "unevaluatedItems",
512
448
  "unevaluatedProperties"
513
449
  ]);
514
- function isSchemaRecord(value) {
515
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
516
- }
517
450
  function cleanSchemaNode(node) {
518
451
  if (Array.isArray(node)) {
519
452
  let changed = false;
@@ -524,7 +457,7 @@ function cleanSchemaNode(node) {
524
457
  });
525
458
  return changed ? entries : node;
526
459
  }
527
- if (!isSchemaRecord(node)) return node;
460
+ if (!isRecord(node)) return node;
528
461
  let changed = false;
529
462
  const cleaned = {};
530
463
  for (const [key, value] of Object.entries(node)) {
@@ -537,7 +470,7 @@ function cleanSchemaNode(node) {
537
470
  continue;
538
471
  }
539
472
  let next = value;
540
- if (SCHEMA_MAP_KEYS$2.has(key) && isSchemaRecord(value)) {
473
+ if (SCHEMA_MAP_KEYS$2.has(key) && isRecord(value)) {
541
474
  let mapChanged = false;
542
475
  next = Object.fromEntries(Object.entries(value).map(([childKey, childValue]) => {
543
476
  const cleanedChild = cleanSchemaNode(childValue);
@@ -556,10 +489,10 @@ function collectSchemaViolations(node, path, violations) {
556
489
  node.forEach((entry, index) => collectSchemaViolations(entry, `${path}[${index}]`, violations));
557
490
  return;
558
491
  }
559
- if (!isSchemaRecord(node)) return;
492
+ if (!isRecord(node)) return;
560
493
  if ("pattern" in node) violations.push(`${path}.pattern`);
561
494
  if (typeof node.maxLength === "number" && node.maxLength >= 2e3) violations.push(`${path}.maxLength`);
562
- 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);
495
+ 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);
563
496
  else if (SCHEMA_CHILD_KEYS.has(key)) collectSchemaViolations(value, `${path}.${key}`, violations);
564
497
  }
565
498
  /** Removes JSON Schema constraints that llama.cpp cannot compile into GBNF. */
@@ -1361,7 +1294,7 @@ function findOpenAIStrictSchemaViolations(schema, path, options) {
1361
1294
  * Caches normalized object inputs by provider compatibility so repeated inventory builds preserve identity.
1362
1295
  */
1363
1296
  const MAX_STRICT_SCHEMA_CACHE_ENTRIES_PER_SCHEMA = 8;
1364
- let strictOpenAISchemaCache = /* @__PURE__ */ new WeakMap();
1297
+ const strictOpenAISchemaCache = /* @__PURE__ */ new WeakMap();
1365
1298
  function resolveToolSchemaModelCompat(compat) {
1366
1299
  if (!compat) return;
1367
1300
  const unsupportedToolSchemaKeywords = Array.isArray(compat.unsupportedToolSchemaKeywords) ? compat.unsupportedToolSchemaKeywords.filter((keyword) => typeof keyword === "string") : [];
@@ -1386,9 +1319,6 @@ function rememberStrictOpenAISchema(schema, key, value) {
1386
1319
  }, ...entries.filter((entry) => entry.key !== key)].slice(0, MAX_STRICT_SCHEMA_CACHE_ENTRIES_PER_SCHEMA));
1387
1320
  return value;
1388
1321
  }
1389
- function clearOpenAIToolSchemaCacheForTest() {
1390
- strictOpenAISchemaCache = /* @__PURE__ */ new WeakMap();
1391
- }
1392
1322
  /** Normalizes a tool parameter schema into the OpenAI strict JSON-schema subset. */
1393
1323
  function normalizeStrictOpenAIJsonSchema(schema, modelCompat) {
1394
1324
  const schemaInput = schema ?? {};
@@ -1480,49 +1410,6 @@ function resolveOpenAIProjectedToolsStrictToolFlag(projection, strict) {
1480
1410
  return projection.tools.every((tool) => isStrictOpenAIJsonSchemaCompatible(tool.parameters));
1481
1411
  }
1482
1412
  //#endregion
1483
- //#region packages/ai/src/transports/openai-transport-shared.ts
1484
- /** Shared options, usage shape, cache identity, ordering, and stream scheduling for OpenAI APIs. */
1485
- const MODEL_STREAM_COOPERATIVE_YIELD_INTERVAL_MS = 12;
1486
- const MODEL_STREAM_COOPERATIVE_YIELD_MAX_EVENTS = 64;
1487
- const GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP = "skip_thought_signature_validator";
1488
- const log = {
1489
- debug(message, data) {
1490
- getAiTransportHost().logDebug("openai-transport", () => ({
1491
- message,
1492
- data
1493
- }));
1494
- },
1495
- info(message, data) {
1496
- getAiTransportHost().logInfo("openai-transport", message, data);
1497
- },
1498
- warn(message, data) {
1499
- getAiTransportHost().logWarn("openai-transport", message, data);
1500
- }
1501
- };
1502
- function throwIfModelStreamAborted(signal) {
1503
- if (signal?.aborted) throw transportAbortError(signal);
1504
- }
1505
- function createModelStreamCooperativeScheduler(signal) {
1506
- let lastYieldedAt = Date.now();
1507
- let eventsSinceYield = 0;
1508
- return { async afterEvent() {
1509
- throwIfModelStreamAborted(signal);
1510
- eventsSinceYield += 1;
1511
- const now = Date.now();
1512
- if (eventsSinceYield < MODEL_STREAM_COOPERATIVE_YIELD_MAX_EVENTS && now - lastYieldedAt < MODEL_STREAM_COOPERATIVE_YIELD_INTERVAL_MS) return;
1513
- eventsSinceYield = 0;
1514
- lastYieldedAt = now;
1515
- await new Promise((resolve) => {
1516
- setTimeout(resolve, 0);
1517
- });
1518
- throwIfModelStreamAborted(signal);
1519
- } };
1520
- }
1521
- function resolvePromptCacheKey(options, cacheRetention) {
1522
- if (cacheRetention === "none") return;
1523
- return clampOpenAIPromptCacheKey(options?.promptCacheKey ?? options?.sessionId);
1524
- }
1525
- //#endregion
1526
1413
  //#region packages/ai/src/transports/openai-responses-replay.ts
1527
1414
  /** Resolves the assistant message id that can be replayed to OpenAI Responses. */
1528
1415
  function resolveReplayableResponsesMessageId(params) {
@@ -1530,324 +1417,182 @@ function resolveReplayableResponsesMessageId(params) {
1530
1417
  if (!params.textSignatureId) return params.fallbackOrdinal === 0 ? params.fallbackId : `${params.fallbackId}_${params.fallbackOrdinal}`;
1531
1418
  return params.previousReplayItemWasReasoning ? params.textSignatureId : void 0;
1532
1419
  }
1533
- const OPENAI_CODEX_RESPONSES_DEFAULT_INSTRUCTIONS = "Follow the user request.";
1534
- const AZURE_RESPONSES_FIRST_EVENT_TIMEOUT_MS = 3e4;
1535
- const RESPONSE_FAILED_NO_DETAILS_MESSAGE = "Unknown error (no error details in response)";
1536
- const OPENAI_RESPONSES_REASONING_REPLAY_META_KEY = "__openclaw_replay";
1537
- const OPENAI_RESPONSES_REASONING_REPLAY_BLOCK_META_KEY = "openclawReasoningReplay";
1538
1420
  //#endregion
1539
- //#region packages/ai/src/transports/openai-responses-debug.ts
1540
- function stringifyUnknown(value, fallback = "") {
1541
- if (typeof value === "string") return value;
1542
- if (typeof value === "number" || typeof value === "boolean") return String(value);
1543
- return fallback;
1544
- }
1545
- function getServiceTierCostMultiplier(serviceTier) {
1546
- switch (serviceTier) {
1547
- case "flex": return .5;
1548
- case "priority": return 2;
1549
- default: return 1;
1550
- }
1421
+ //#region packages/ai/src/transports/openai-responses-compaction-replay.ts
1422
+ const OPENAI_RESPONSES_COMPACTION_SUPPRESSION_TYPE = "openai-responses-compaction-suppression";
1423
+ const OPENAI_RESPONSES_COMPACTION_SUPPRESSION_DATA = "rejected";
1424
+ function hashOptionalReplayContextValue(value) {
1425
+ const normalized = value?.trim();
1426
+ return normalized ? shortHash(normalized) : void 0;
1551
1427
  }
1552
- function applyServiceTierPricing(usage, serviceTier) {
1553
- const multiplier = getServiceTierCostMultiplier(serviceTier);
1554
- if (multiplier === 1) return;
1555
- usage.cost.input *= multiplier;
1556
- usage.cost.output *= multiplier;
1557
- usage.cost.cacheRead *= multiplier;
1558
- usage.cost.cacheWrite *= multiplier;
1559
- usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
1428
+ function buildOpenAIResponsesReplayContext(model, options) {
1429
+ return {
1430
+ provider: model.provider,
1431
+ api: model.api,
1432
+ model: model.id,
1433
+ baseUrlHash: hashOptionalReplayContextValue(model.baseUrl),
1434
+ sessionHash: hashOptionalReplayContextValue(options?.sessionId),
1435
+ authProfileHash: hashOptionalReplayContextValue(options?.authProfileId)
1436
+ };
1560
1437
  }
1561
- function safeDebugValue(value) {
1562
- if (typeof value === "string") return value;
1563
- if (typeof value === "number" || typeof value === "boolean") return String(value);
1564
- if (value === null) return "null";
1565
- if (value === void 0) return "undefined";
1566
- return Array.isArray(value) ? "array" : typeof value;
1438
+ function isOpenAIResponsesReplayContext(value) {
1439
+ if (!isRecord(value)) return false;
1440
+ 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");
1567
1441
  }
1568
- function responseInputTextChars(input) {
1569
- if (typeof input === "string") return input.length;
1570
- if (Array.isArray(input)) return input.reduce((total, item) => total + responseInputTextChars(item), 0);
1571
- if (!input || typeof input !== "object") return 0;
1572
- const record = input;
1573
- let total = 0;
1574
- if (typeof record.text === "string") total += record.text.length;
1575
- if (typeof record.content === "string") total += record.content.length;
1576
- else if (Array.isArray(record.content)) total += responseInputTextChars(record.content);
1577
- return total;
1442
+ function readOpenAIResponsesCompactionReplayState(value) {
1443
+ if (!isOpenAIResponsesReplayContext(value) || typeof value.baseUrlHash !== "string" || value.v !== 1) return;
1444
+ const state = value;
1445
+ if (state.type === OPENAI_RESPONSES_COMPACTION_SUPPRESSION_TYPE) return state.data === OPENAI_RESPONSES_COMPACTION_SUPPRESSION_DATA ? state : void 0;
1446
+ 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 || Number.isSafeInteger(state.replayIndex) && state.replayIndex >= 0) ? state : void 0;
1578
1447
  }
1579
- function responseInputRoles(input) {
1580
- if (!Array.isArray(input)) return "";
1581
- const roles = /* @__PURE__ */ new Set();
1582
- for (const item of input) if (item && typeof item === "object") {
1583
- const role = item.role;
1584
- if (typeof role === "string" && role.trim()) roles.add(role.trim());
1585
- }
1586
- return [...roles].toSorted().join(",");
1448
+ function openAIResponsesReplayContextMatches(state, context) {
1449
+ 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;
1587
1450
  }
1588
- function readToolPayloadField(record, field) {
1589
- try {
1590
- return record[field];
1591
- } catch {
1451
+ function captureOpenAIResponsesCompaction(output, item, replayIndex, model, captureMetadata) {
1452
+ const metadata = captureMetadata ?? buildOpenAIResponsesReasoningReplayMetadata(model);
1453
+ if (!item.encrypted_content) return;
1454
+ if (!metadata?.baseUrlHash) {
1455
+ log.debug("[responses] skipping compaction capture: missing base URL hash");
1592
1456
  return;
1593
1457
  }
1458
+ const currentReplay = readOpenAIResponsesCompactionReplayState(output.providerReplay);
1459
+ if (currentReplay?.type === "openai-responses-compaction" && (currentReplay.replayIndex ?? -1) > (replayIndex ?? Number.MAX_SAFE_INTEGER)) return;
1460
+ output.providerReplay = {
1461
+ v: 1,
1462
+ type: OPENAI_RESPONSES_COMPACTION_REPLAY_TYPE,
1463
+ ...item.id ? { id: item.id } : {},
1464
+ data: item.encrypted_content,
1465
+ ...replayIndex === void 0 ? {} : { replayIndex },
1466
+ provider: metadata.provider,
1467
+ api: metadata.api,
1468
+ model: metadata.model,
1469
+ baseUrlHash: metadata.baseUrlHash,
1470
+ ...metadata.sessionHash ? { sessionHash: metadata.sessionHash } : {},
1471
+ ...metadata.authProfileHash ? { authProfileHash: metadata.authProfileHash } : {}
1472
+ };
1594
1473
  }
1595
- function readResponsesToolDisplayName(tool) {
1596
- if (!tool || typeof tool !== "object") return "";
1597
- const record = tool;
1598
- const name = readToolPayloadField(record, "name");
1599
- if (typeof name === "string") return name;
1600
- const fn = readToolPayloadField(record, "function");
1601
- if (fn && typeof fn === "object") {
1602
- const fnName = readToolPayloadField(fn, "name");
1603
- if (typeof fnName === "string") return fnName;
1604
- }
1605
- const type = readToolPayloadField(record, "type");
1606
- return typeof type === "string" && type !== "function" ? type : "";
1607
- }
1608
- function summarizeResponsesTools(tools) {
1609
- if (!Array.isArray(tools)) return "count=0";
1610
- const names = tools.map(readResponsesToolDisplayName).filter(Boolean);
1611
- const mode = resolveModelPayloadDebugMode();
1612
- const maxNames = mode === "tools" || mode === "full-redacted" ? names.length : 12;
1613
- const label = maxNames >= names.length ? "names" : "sample";
1614
- const shown = names.slice(0, maxNames).join(",");
1615
- return `count=${tools.length}${shown ? ` ${label}=${shown}` : ""}`;
1474
+ function suppressOpenAIResponsesCompaction(output, model, options, rejectedCheckpoint) {
1475
+ const context = buildOpenAIResponsesReplayContext(model, options);
1476
+ if (!context.baseUrlHash) return;
1477
+ output.providerReplay = {
1478
+ v: 1,
1479
+ type: OPENAI_RESPONSES_COMPACTION_SUPPRESSION_TYPE,
1480
+ data: OPENAI_RESPONSES_COMPACTION_SUPPRESSION_DATA,
1481
+ ...context,
1482
+ baseUrlHash: context.baseUrlHash
1483
+ };
1484
+ if (rejectedCheckpoint) options?.onCompactionRejected?.(rejectedCheckpoint);
1616
1485
  }
1617
- function stringifyRedactedPayload(value) {
1618
- try {
1619
- const encoded = JSON.stringify(value);
1620
- if (!encoded) return "<empty>";
1621
- const redacted = redactSensitiveText(encoded, { mode: "tools" });
1622
- return redacted.length > 8e3 ? `${truncateUtf16Safe(redacted, 8e3)}…<truncated>` : redacted;
1623
- } catch {
1624
- return "<unserializable>";
1625
- }
1486
+ function createCompactionTracker(output, model, options) {
1487
+ const replayIndexes = /* @__PURE__ */ new Map();
1488
+ return {
1489
+ added(item, replayIndex) {
1490
+ if (item.type === "compaction" && item.id) replayIndexes.set(item.id, replayIndex);
1491
+ },
1492
+ completed(item, fallbackReplayIndex) {
1493
+ if (item.type !== "compaction" || !item.encrypted_content) return;
1494
+ captureOpenAIResponsesCompaction(output, {
1495
+ type: "compaction",
1496
+ ...item.id ? { id: item.id } : {},
1497
+ encrypted_content: item.encrypted_content
1498
+ }, (item.id ? replayIndexes.get(item.id) : void 0) ?? fallbackReplayIndex, model, options?.reasoningReplayMetadata);
1499
+ if (item.id) replayIndexes.delete(item.id);
1500
+ }
1501
+ };
1626
1502
  }
1627
- function stringifyRedactedEvent(value) {
1628
- const redacted = stringifyRedactedPayload(value);
1629
- return redacted.length > 2e3 ? `${truncateUtf16Safe(redacted, 2e3)}…<truncated>` : redacted;
1503
+ function isSafeResponsesReplayItemId(id) {
1504
+ return typeof id === "string" && id.length > 0 && id.length <= 64;
1630
1505
  }
1631
- const RESPONSE_FAILED_FAILURE_FIELD_KEYS = [
1632
- "error",
1633
- "incomplete_details",
1634
- "status_details",
1635
- "failure_reason",
1636
- "last_error",
1637
- "provider_error",
1638
- "error_details"
1639
- ];
1640
- function readResponseFailedString(record, key) {
1641
- return stringifyUnknown(record?.[key]);
1506
+ function resolveNewestOpenAIResponsesCompactionReplay(messages, model, options) {
1507
+ const context = buildOpenAIResponsesReplayContext(model, options);
1508
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
1509
+ const message = messages[index];
1510
+ if (message?.role !== "assistant") continue;
1511
+ const replay = readOpenAIResponsesCompactionReplayState(message.providerReplay);
1512
+ if (replay?.type === OPENAI_RESPONSES_COMPACTION_SUPPRESSION_TYPE) {
1513
+ if (openAIResponsesReplayContextMatches(replay, context)) return;
1514
+ continue;
1515
+ }
1516
+ if (replay?.type !== "openai-responses-compaction") {
1517
+ if (message.providerReplay?.type === "openai-responses-compaction") return;
1518
+ continue;
1519
+ }
1520
+ if (!openAIResponsesReplayContextMatches(replay, context)) return;
1521
+ return {
1522
+ owner: message,
1523
+ item: {
1524
+ type: "compaction",
1525
+ ...isSafeResponsesReplayItemId(replay.id) ? { id: replay.id } : {},
1526
+ encrypted_content: replay.data
1527
+ },
1528
+ replayIndex: replay.replayIndex ?? 0
1529
+ };
1530
+ }
1642
1531
  }
1643
- function buildResponsesFailedEventSummary(message, responseId, observation) {
1644
- const summary = { message };
1645
- if (responseId) summary.responseId = responseId;
1646
- if (observation) summary.observation = observation;
1647
- return summary;
1532
+ function buildOpenAIResponsesCompactionReplayPlan(messages, model, options) {
1533
+ if (options?.mode === "full-history") return {
1534
+ messages,
1535
+ preserveUnframedToolResults: false
1536
+ };
1537
+ const compaction = resolveNewestOpenAIResponsesCompactionReplay(messages, model, options);
1538
+ if (!compaction) return {
1539
+ messages,
1540
+ preserveUnframedToolResults: false
1541
+ };
1542
+ const ownerIndex = messages.indexOf(compaction.owner);
1543
+ return {
1544
+ messages: [{
1545
+ ...compaction.owner,
1546
+ content: compaction.owner.content.slice(compaction.replayIndex)
1547
+ }, ...messages.slice(ownerIndex + 1)],
1548
+ compaction: compaction.item,
1549
+ preserveUnframedToolResults: true
1550
+ };
1648
1551
  }
1649
- function isResponseFailedIdentifierKey(key) {
1650
- const normalized = key.replace(/[-_\s]/g, "").toLowerCase();
1651
- return normalized === "requestid" || normalized === "xrequestid" || normalized === "providerrequestid" || normalized === "providerresponseid" || normalized === "litellmrequestid" || normalized.includes("request") && normalized.endsWith("id") || normalized.includes("provider") && normalized.endsWith("id");
1552
+ function buildOpenAIResponsesReasoningReplayMetadata(model, options) {
1553
+ return {
1554
+ v: 1,
1555
+ source: "openai-responses",
1556
+ ...buildOpenAIResponsesReplayContext(model, options)
1557
+ };
1652
1558
  }
1653
- function collectResponseFailedIdentifierHashes(value, opts = {}) {
1654
- const path = opts.path ?? "";
1655
- const depth = opts.depth ?? 0;
1656
- const identifierKey = opts.identifierKey ?? "";
1657
- const out = opts.out ?? [];
1658
- const seen = opts.seen ?? /* @__PURE__ */ new WeakSet();
1659
- if (out.length >= 12 || depth > 4 || !value || typeof value !== "object") return out;
1660
- if (seen.has(value)) return out;
1661
- seen.add(value);
1559
+ //#endregion
1560
+ //#region packages/ai/src/transports/openai-responses-replay-messages-internal.ts
1561
+ function stripEncryptedReasoningContentFields(value) {
1562
+ if (!value || typeof value !== "object") return {
1563
+ value,
1564
+ changed: false
1565
+ };
1662
1566
  if (Array.isArray(value)) {
1663
- for (const [index, item] of value.entries()) {
1664
- if (index >= 8 || out.length >= 12) break;
1665
- const itemString = typeof item === "string" || typeof item === "number" ? String(item).trim() : "";
1666
- if (identifierKey && isResponseFailedIdentifierKey(identifierKey) && itemString) {
1667
- out.push(`${path}[${index}]=${redactIdentifier(itemString, { len: 12 })}`);
1668
- continue;
1669
- }
1670
- collectResponseFailedIdentifierHashes(item, {
1671
- path: `${path}[${index}]`,
1672
- depth: depth + 1,
1673
- identifierKey,
1674
- out,
1675
- seen
1676
- });
1677
- }
1678
- return out;
1567
+ let changed = false;
1568
+ const next = value.map((item) => {
1569
+ const stripped = stripEncryptedReasoningContentFields(item);
1570
+ changed ||= stripped.changed;
1571
+ return stripped.value;
1572
+ });
1573
+ return changed ? {
1574
+ value: next,
1575
+ changed: true
1576
+ } : {
1577
+ value,
1578
+ changed: false
1579
+ };
1679
1580
  }
1680
- for (const [key, child] of Object.entries(value)) {
1681
- if (out.length >= 12) break;
1682
- const childPath = path ? `${path}.${key}` : key;
1683
- const childString = typeof child === "string" || typeof child === "number" ? String(child).trim() : "";
1684
- if (isResponseFailedIdentifierKey(key) && childString) {
1685
- out.push(`${childPath}=${redactIdentifier(childString, { len: 12 })}`);
1581
+ const source = value;
1582
+ if (source.type === "compaction") return {
1583
+ value,
1584
+ changed: false
1585
+ };
1586
+ let changed = false;
1587
+ const next = {};
1588
+ for (const [key, child] of Object.entries(source)) {
1589
+ if (key === "encrypted_content") {
1590
+ changed = true;
1686
1591
  continue;
1687
1592
  }
1688
- collectResponseFailedIdentifierHashes(child, {
1689
- path: childPath,
1690
- depth: depth + 1,
1691
- identifierKey: isResponseFailedIdentifierKey(key) ? key : void 0,
1692
- out,
1693
- seen
1694
- });
1695
- }
1696
- return out;
1697
- }
1698
- function redactResponseFailedDiagnosticValue(value, opts = {}) {
1699
- const key = opts.key ?? "";
1700
- const depth = opts.depth ?? 0;
1701
- if (typeof value === "string" || typeof value === "number") return key && isResponseFailedIdentifierKey(key) ? redactIdentifier(String(value), { len: 12 }) : value;
1702
- if (depth > 6 || !value || typeof value !== "object") return value;
1703
- const seen = opts.seen ?? /* @__PURE__ */ new WeakSet();
1704
- if (seen.has(value)) return "<circular>";
1705
- seen.add(value);
1706
- if (Array.isArray(value)) return value.slice(0, 16).map((item) => redactResponseFailedDiagnosticValue(item, {
1707
- key,
1708
- depth: depth + 1,
1709
- seen
1710
- }));
1711
- const out = {};
1712
- for (const [childKey, child] of Object.entries(value)) out[childKey] = redactResponseFailedDiagnosticValue(child, {
1713
- key: childKey,
1714
- depth: depth + 1,
1715
- seen
1716
- });
1717
- return out;
1718
- }
1719
- function buildResponsesFailedFailureFields(response) {
1720
- if (!response) return {};
1721
- const fields = {};
1722
- for (const key of RESPONSE_FAILED_FAILURE_FIELD_KEYS) if (response[key] !== void 0 && response[key] !== null) fields[key] = response[key];
1723
- return fields;
1724
- }
1725
- function buildResponsesFailedNoDetailsObservation(event, model, response = isRecord(event.response) ? event.response : void 0) {
1726
- const failureFields = redactResponseFailedDiagnosticValue(buildResponsesFailedFailureFields(response));
1727
- const metadataKeys = isRecord(response?.metadata) ? Object.keys(response.metadata).toSorted() : [];
1728
- const responsePreview = {
1729
- id: readResponseFailedString(response, "id"),
1730
- status: readResponseFailedString(response, "status"),
1731
- model: readResponseFailedString(response, "model"),
1732
- object: readResponseFailedString(response, "object"),
1733
- failureFields,
1734
- metadataKeys
1735
- };
1736
- return {
1737
- event: "openai_responses_response_failed_without_details",
1738
- provider: model.provider,
1739
- api: model.api,
1740
- transportModel: model.id,
1741
- providerRuntimeFailureKind: "no_error_details",
1742
- responseId: responsePreview.id,
1743
- responseStatus: responsePreview.status,
1744
- responseModel: responsePreview.model,
1745
- responseObject: responsePreview.object,
1746
- metadataKeys,
1747
- requestIdHashes: collectResponseFailedIdentifierHashes(event),
1748
- failureFieldsPreview: stringifyRedactedEvent(failureFields),
1749
- responsePreview: stringifyRedactedEvent(responsePreview)
1750
- };
1751
- }
1752
- function summarizeResponsesFailedNoDetailsObservation(observation) {
1753
- const requestIds = observation.requestIdHashes.join(",");
1754
- const metadataKeys = observation.metadataKeys.join(",");
1755
- 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}`;
1756
- }
1757
- function normalizeResponsesFailedEvent(event, model) {
1758
- const response = isRecord(event.response) ? event.response : void 0;
1759
- const responseId = readResponseFailedString(response, "id") || void 0;
1760
- const error = isRecord(response?.error) ? response.error : void 0;
1761
- if (error) {
1762
- const code = readResponseFailedString(error, "code").trim();
1763
- const message = readResponseFailedString(error, "message").trim();
1764
- if (code || message) return buildResponsesFailedEventSummary(`${code || "unknown"}: ${message || "no message"}`, responseId);
1765
- }
1766
- const incompleteReason = readResponseFailedString(isRecord(response?.incomplete_details) ? response.incomplete_details : void 0, "reason");
1767
- if (incompleteReason) return buildResponsesFailedEventSummary(`incomplete: ${incompleteReason}`, responseId);
1768
- return buildResponsesFailedEventSummary(RESPONSE_FAILED_NO_DETAILS_MESSAGE, responseId, buildResponsesFailedNoDetailsObservation(event, model, response));
1769
- }
1770
- function logResponsesFailedNoDetails(observation) {
1771
- log.warn(`[responses] response.failed missing error details provider=${observation.provider} api=${observation.api} model=${observation.transportModel} ` + summarizeResponsesFailedNoDetailsObservation(observation), observation);
1772
- }
1773
- function summarizeResponsesPayload(params) {
1774
- if (!params || typeof params !== "object") return "payload=non-object";
1775
- const record = params;
1776
- const input = record.input;
1777
- const reasoning = record.reasoning && typeof record.reasoning === "object" ? record.reasoning : void 0;
1778
- const text = record.text && typeof record.text === "object" ? record.text : void 0;
1779
- const parts = [
1780
- `fields=${Object.keys(record).toSorted().join(",")}`,
1781
- `model=${safeDebugValue(record.model)}`,
1782
- `stream=${safeDebugValue(record.stream)}`,
1783
- `inputItems=${Array.isArray(input) ? input.length : typeof input}`,
1784
- `inputRoles=${responseInputRoles(input) || "none"}`,
1785
- `inputTextChars=${responseInputTextChars(input)}`,
1786
- `tools=${summarizeResponsesTools(record.tools)}`,
1787
- `reasoningEffort=${safeDebugValue(reasoning?.effort)}`,
1788
- `reasoningSummary=${safeDebugValue(reasoning?.summary)}`,
1789
- `textVerbosity=${safeDebugValue(text?.verbosity)}`,
1790
- `serviceTier=${safeDebugValue(record.service_tier)}`,
1791
- `store=${safeDebugValue(record.store)}`,
1792
- `promptCacheKey=${record.prompt_cache_key === void 0 ? "absent" : "present"}`,
1793
- `metadataKeys=${record.metadata && typeof record.metadata === "object" ? Object.keys(record.metadata).toSorted().join(",") : "none"}`
1794
- ];
1795
- if (resolveModelPayloadDebugMode() === "full-redacted") parts.push(`payload=${stringifyRedactedPayload(record)}`);
1796
- return parts.join(" ");
1797
- }
1798
- function summarizeOpenAITransportError(error) {
1799
- if (!error || typeof error !== "object") return `type=${typeof error} message=${safeDebugValue(error)}`;
1800
- const record = error;
1801
- const cause = record.cause && typeof record.cause === "object" ? record.cause : void 0;
1802
- return [
1803
- `name=${safeDebugValue(record.name)}`,
1804
- `status=${safeDebugValue(record.status)}`,
1805
- `code=${safeDebugValue(record.code)}`,
1806
- `type=${safeDebugValue(record.type)}`,
1807
- `causeName=${safeDebugValue(cause?.name)}`,
1808
- `causeCode=${safeDebugValue(cause?.code)}`,
1809
- `message=${error instanceof Error ? error.message : safeDebugValue(error)}`
1810
- ].join(" ");
1811
- }
1812
- //#endregion
1813
- //#region packages/ai/src/transports/openai-responses-replay-internal.ts
1814
- function isInvalidEncryptedContentError(error) {
1815
- if (!error || typeof error !== "object") return false;
1816
- const record = error;
1817
- if (record.code === "invalid_encrypted_content" || record.code === "thinking_signature_invalid") return true;
1818
- const message = typeof record.message === "string" ? record.message : "";
1819
- return message.includes("invalid_encrypted_content") || message.includes("thinking_signature_invalid") || record.status === 400 && message.toLowerCase().includes("could not decrypt the provided encrypted_content");
1820
- }
1821
- function stripEncryptedContentFields(value) {
1822
- if (!value || typeof value !== "object") return {
1823
- value,
1824
- changed: false
1825
- };
1826
- if (Array.isArray(value)) {
1827
- let changed = false;
1828
- const next = value.map((item) => {
1829
- const stripped = stripEncryptedContentFields(item);
1830
- changed ||= stripped.changed;
1831
- return stripped.value;
1832
- });
1833
- return changed ? {
1834
- value: next,
1835
- changed: true
1836
- } : {
1837
- value,
1838
- changed: false
1839
- };
1840
- }
1841
- let changed = false;
1842
- const next = {};
1843
- for (const [key, child] of Object.entries(value)) {
1844
- if (key === "encrypted_content") {
1845
- changed = true;
1846
- continue;
1847
- }
1848
- const stripped = stripEncryptedContentFields(child);
1849
- changed ||= stripped.changed;
1850
- next[key] = stripped.value;
1593
+ const stripped = stripEncryptedReasoningContentFields(child);
1594
+ changed ||= stripped.changed;
1595
+ next[key] = stripped.value;
1851
1596
  }
1852
1597
  return changed ? {
1853
1598
  value: next,
@@ -1857,54 +1602,15 @@ function stripEncryptedContentFields(value) {
1857
1602
  changed: false
1858
1603
  };
1859
1604
  }
1860
- function stripResponsesRequestEncryptedContent(params) {
1861
- const stripped = stripEncryptedContentFields(params.input);
1862
- if (!stripped.changed) return params;
1863
- return {
1864
- ...params,
1865
- input: stripped.value
1866
- };
1867
- }
1868
- function hashOptionalReplayContextValue(value) {
1869
- const normalized = value?.trim();
1870
- return normalized ? shortHash(normalized) : void 0;
1871
- }
1872
- function buildOpenAIResponsesReplayContext(model, options) {
1873
- return {
1874
- provider: model.provider,
1875
- api: model.api,
1876
- model: model.id,
1877
- baseUrlHash: hashOptionalReplayContextValue(model.baseUrl),
1878
- sessionHash: hashOptionalReplayContextValue(options?.sessionId),
1879
- authProfileHash: hashOptionalReplayContextValue(options?.authProfileId)
1880
- };
1881
- }
1882
- function buildOpenAIResponsesReasoningReplayMetadata(model, options) {
1883
- return {
1884
- v: 1,
1885
- source: "openai-responses",
1886
- ...buildOpenAIResponsesReplayContext(model, options)
1887
- };
1888
- }
1889
- function tagOpenAIResponsesReasoningReplayItem(item, model, options) {
1890
- if (!("encrypted_content" in item)) return item;
1891
- return {
1892
- ...item,
1893
- [OPENAI_RESPONSES_REASONING_REPLAY_META_KEY]: buildOpenAIResponsesReasoningReplayMetadata(model, options)
1894
- };
1895
- }
1896
1605
  function isOpenAIResponsesReasoningReplayMetadata(value) {
1897
- if (!value || typeof value !== "object") return false;
1606
+ if (!isOpenAIResponsesReplayContext(value)) return false;
1898
1607
  const record = value;
1899
- 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");
1900
- }
1901
- function encryptedReasoningReplayMetadataMatches(metadata, context) {
1902
- if (!metadata) return false;
1903
- 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;
1608
+ return record.v === 1 && record.source === "openai-responses";
1904
1609
  }
1905
1610
  function readOpenAIResponsesReasoningReplayBlockMetadata(block) {
1611
+ if (!Object.hasOwn(block, "openclawReasoningReplay")) return;
1906
1612
  const value = block[OPENAI_RESPONSES_REASONING_REPLAY_BLOCK_META_KEY];
1907
- return isOpenAIResponsesReasoningReplayMetadata(value) ? value : void 0;
1613
+ return isOpenAIResponsesReasoningReplayMetadata(value) ? value : null;
1908
1614
  }
1909
1615
  function normalizeOpenAIResponsesReasoningReplayItem(item) {
1910
1616
  const record = item;
@@ -1914,33 +1620,20 @@ function normalizeOpenAIResponsesReasoningReplayItem(item) {
1914
1620
  summary: []
1915
1621
  };
1916
1622
  }
1917
- function prepareOpenAIResponsesReasoningItemForReplay(item, context, blockMetadata) {
1918
- const { [OPENAI_RESPONSES_REASONING_REPLAY_META_KEY]: rawMetadata, ...rest } = item;
1623
+ function prepareOpenAIResponsesReasoningItemForReplay(item, context, blockMetadata, options) {
1624
+ const record = item;
1625
+ const hasRawMetadata = Object.hasOwn(record, OPENAI_RESPONSES_REASONING_REPLAY_META_KEY);
1626
+ const { [OPENAI_RESPONSES_REASONING_REPLAY_META_KEY]: rawMetadata, ...rest } = record;
1919
1627
  if (!("encrypted_content" in rest)) return normalizeOpenAIResponsesReasoningReplayItem(rest);
1920
- if (encryptedReasoningReplayMetadataMatches(blockMetadata ?? (isOpenAIResponsesReasoningReplayMetadata(rawMetadata) ? rawMetadata : void 0), context)) return normalizeOpenAIResponsesReasoningReplayItem(rest);
1921
- return normalizeOpenAIResponsesReasoningReplayItem(stripEncryptedContentFields(rest).value);
1922
- }
1923
- async function createResponsesStreamWithEncryptedContentRetry(params) {
1924
- try {
1925
- return await params.client.responses.create(params.request, params.requestOptions);
1926
- } catch (error) {
1927
- const retryRequest = stripResponsesRequestEncryptedContent(params.request);
1928
- if (!isInvalidEncryptedContentError(error) || retryRequest === params.request) throw error;
1929
- log.warn(`[responses] retrying without encrypted reasoning content provider=${params.model.provider} api=${params.model.api} model=${params.model.id}`);
1930
- return await params.client.responses.create(retryRequest, params.requestOptions);
1931
- }
1932
- }
1933
- function resolveAzureOpenAIApiVersion(env = process.env) {
1934
- return env.AZURE_OPENAI_API_VERSION?.trim() || "preview";
1628
+ const metadata = blockMetadata !== void 0 ? blockMetadata ?? void 0 : isOpenAIResponsesReasoningReplayMetadata(rawMetadata) ? rawMetadata : void 0;
1629
+ if (blockMetadata === void 0 && !hasRawMetadata && options?.preserveUnattributedEncryptedContent === true || metadata && openAIResponsesReplayContextMatches(metadata, context)) return normalizeOpenAIResponsesReasoningReplayItem(rest);
1630
+ return normalizeOpenAIResponsesReasoningReplayItem(stripEncryptedReasoningContentFields(rest).value);
1935
1631
  }
1936
1632
  function normalizeResponsesReplayItemId(id, prefix) {
1937
1633
  if (!id) return;
1938
1634
  if (id.length <= 64) return id;
1939
1635
  return `${prefix}_${shortHash(id)}`;
1940
1636
  }
1941
- function isSafeResponsesReplayItemId(id) {
1942
- return typeof id === "string" && id.length > 0 && id.length <= 64;
1943
- }
1944
1637
  function encodeTextSignatureV1(id, phase) {
1945
1638
  return JSON.stringify({
1946
1639
  v: 1,
@@ -1948,7 +1641,7 @@ function encodeTextSignatureV1(id, phase) {
1948
1641
  ...phase ? { phase } : {}
1949
1642
  });
1950
1643
  }
1951
- function parseTextSignature(signature) {
1644
+ function parseOpenAIResponsesTextSignature(signature) {
1952
1645
  if (!signature) return;
1953
1646
  if (signature.startsWith("{")) try {
1954
1647
  const parsed = JSON.parse(signature);
@@ -1971,8 +1664,34 @@ function buildResponsesInputMessage(role, content) {
1971
1664
  content
1972
1665
  };
1973
1666
  }
1974
- function convertResponsesMessages(model, context, allowedToolCallProviders, options) {
1667
+ function createOpenAIResponsesAssistantOutput(model, api = model.api) {
1668
+ return {
1669
+ role: "assistant",
1670
+ content: [],
1671
+ api,
1672
+ provider: model.provider,
1673
+ model: model.id,
1674
+ usage: {
1675
+ input: 0,
1676
+ output: 0,
1677
+ cacheRead: 0,
1678
+ cacheWrite: 0,
1679
+ totalTokens: 0,
1680
+ cost: {
1681
+ input: 0,
1682
+ output: 0,
1683
+ cacheRead: 0,
1684
+ cacheWrite: 0,
1685
+ total: 0
1686
+ }
1687
+ },
1688
+ stopReason: "stop",
1689
+ timestamp: Date.now()
1690
+ };
1691
+ }
1692
+ function convertResponsesMessagesWithStyle(model, context, allowedToolCallProviders, options, conversionStyle) {
1975
1693
  const messages = [];
1694
+ const providerStyle = conversionStyle === "provider";
1976
1695
  const shouldReplayReasoningItems = options?.replayReasoningItems ?? true;
1977
1696
  const shouldReplayResponsesItemIds = options?.replayResponsesItemIds ?? true;
1978
1697
  const replayContext = buildOpenAIResponsesReplayContext(model, {
@@ -1980,7 +1699,10 @@ function convertResponsesMessages(model, context, allowedToolCallProviders, opti
1980
1699
  authProfileId: options?.authProfileId
1981
1700
  });
1982
1701
  const shouldNormalizeSameModelToolCallIds = model.provider === "github-copilot";
1983
- const sanitizeIdPart = (part) => part.replace(/[^a-zA-Z0-9_-]/g, "_").replace(/_+$/, "");
1702
+ const sanitizeIdPart = (part) => {
1703
+ const sanitized = part.replace(/[^a-zA-Z0-9_-]/g, "_");
1704
+ return providerStyle ? sanitized : sanitized.replace(/_+$/, "");
1705
+ };
1984
1706
  const normalizeIdPart = (part) => {
1985
1707
  const sanitized = sanitizeIdPart(part);
1986
1708
  return (sanitized.length > 64 ? sanitized.slice(0, 64) : sanitized).replace(/_+$/, "");
@@ -2001,15 +1723,24 @@ function convertResponsesMessages(model, context, allowedToolCallProviders, opti
2001
1723
  const callId = id.slice(0, separatorIndex);
2002
1724
  const itemId = id.slice(separatorIndex + 1);
2003
1725
  const normalizedCallId = normalizeIdPart(callId);
2004
- let normalizedItemId = source.provider !== model.provider || source.api !== model.api ? buildForeignResponsesItemId(itemId) : model.provider === "github-copilot" ? buildSameProviderCopilotResponsesItemId(itemId) : normalizeIdPart(itemId);
1726
+ let normalizedItemId = source.provider !== model.provider || source.api !== model.api ? buildForeignResponsesItemId(itemId) : model.provider === "github-copilot" ? providerStyle ? normalizeIdPart(itemId) : buildSameProviderCopilotResponsesItemId(itemId) : normalizeIdPart(itemId);
2005
1727
  if (!normalizedItemId.startsWith("fc_")) normalizedItemId = normalizeIdPart(`fc_${normalizedItemId}`);
2006
1728
  return `${normalizedCallId}|${normalizedItemId}`;
2007
1729
  };
2008
- const transformedMessages = transformTransportMessages(context.messages, model, normalizeToolCallId, { normalizeSameModelToolCallIds: shouldNormalizeSameModelToolCallIds });
2009
- if ((options?.includeSystemPrompt ?? true) && context.systemPrompt) messages.push(buildResponsesInputMessage(model.reasoning && options?.supportsDeveloperRole !== false ? "developer" : "system", [{
1730
+ const replayPlan = buildOpenAIResponsesCompactionReplayPlan(context.messages, model, {
1731
+ sessionId: options?.sessionId,
1732
+ authProfileId: options?.authProfileId,
1733
+ mode: options?.replayMode
1734
+ });
1735
+ const transformedMessages = providerStyle ? transformProviderMessages(replayPlan.messages, model, normalizeToolCallId) : transformTransportMessages(replayPlan.messages, model, normalizeToolCallId, {
1736
+ normalizeSameModelToolCallIds: shouldNormalizeSameModelToolCallIds,
1737
+ preserveUnframedToolResults: replayPlan.preserveUnframedToolResults
1738
+ });
1739
+ if ((options?.includeSystemPrompt ?? true) && context.systemPrompt) messages.push(buildResponsesInputMessage(model.reasoning && (providerStyle ? model.compat?.supportsDeveloperRole !== false : options?.supportsDeveloperRole !== false) ? "developer" : "system", [{
2010
1740
  type: "input_text",
2011
1741
  text: sanitizeTransportPayloadText(stripSystemPromptCacheBoundary(context.systemPrompt))
2012
1742
  }]));
1743
+ if (replayPlan.compaction) messages.push(replayPlan.compaction);
2013
1744
  let msgIndex = 0;
2014
1745
  for (const msg of transformedMessages) {
2015
1746
  if (msg.role === "user") if (typeof msg.content === "string") messages.push(buildResponsesInputMessage("user", [{
@@ -2024,8 +1755,9 @@ function convertResponsesMessages(model, context, allowedToolCallProviders, opti
2024
1755
  type: "input_image",
2025
1756
  detail: "auto",
2026
1757
  image_url: `data:${item.mimeType};base64,${item.data}`
2027
- }).filter((item) => model.input.includes("image") || item.type !== "input_image");
1758
+ }).filter((item) => providerStyle || model.input.includes("image") || item.type !== "input_image");
2028
1759
  if (content.length > 0) messages.push(buildResponsesInputMessage("user", content));
1760
+ else if (providerStyle) continue;
2029
1761
  }
2030
1762
  else if (msg.role === "assistant") {
2031
1763
  const output = [];
@@ -2033,15 +1765,15 @@ function convertResponsesMessages(model, context, allowedToolCallProviders, opti
2033
1765
  let previousReplayItemWasReasoning = false;
2034
1766
  const isDifferentModel = msg.model !== model.id && msg.provider === model.provider && msg.api === model.api;
2035
1767
  for (const block of msg.content) if (block.type === "thinking") {
2036
- if (shouldReplayReasoningItems && block.thinkingSignature && block.thinkingSignature.startsWith("{")) {
2037
- const replayableReasoningItem = prepareOpenAIResponsesReasoningItemForReplay(JSON.parse(block.thinkingSignature), replayContext, readOpenAIResponsesReasoningReplayBlockMetadata(block));
1768
+ if (shouldReplayReasoningItems && block.thinkingSignature && (providerStyle || block.thinkingSignature.startsWith("{"))) {
1769
+ const replayableReasoningItem = prepareOpenAIResponsesReasoningItemForReplay(JSON.parse(block.thinkingSignature), replayContext, readOpenAIResponsesReasoningReplayBlockMetadata(block), providerStyle ? { preserveUnattributedEncryptedContent: true } : void 0);
2038
1770
  if (!shouldReplayResponsesItemIds) delete replayableReasoningItem.id;
2039
- if (shouldReplayResponsesItemIds && model.provider === "github-copilot" && !isSafeResponsesReplayItemId(replayableReasoningItem.id)) continue;
1771
+ if (shouldReplayResponsesItemIds && !providerStyle && model.provider === "github-copilot" && !isSafeResponsesReplayItemId(replayableReasoningItem.id)) continue;
2040
1772
  output.push(replayableReasoningItem);
2041
1773
  previousReplayItemWasReasoning = true;
2042
1774
  }
2043
1775
  } else if (block.type === "text") {
2044
- const textSignature = parseTextSignature(block.textSignature);
1776
+ const textSignature = parseOpenAIResponsesTextSignature(block.textSignature);
2045
1777
  let msgId = resolveReplayableResponsesMessageId({
2046
1778
  replayResponsesItemIds: shouldReplayResponsesItemIds,
2047
1779
  textSignatureId: textSignature?.id,
@@ -2075,11 +1807,12 @@ function convertResponsesMessages(model, context, allowedToolCallProviders, opti
2075
1807
  ...itemId ? { id: itemId } : {},
2076
1808
  call_id: callId,
2077
1809
  name: block.name,
2078
- arguments: typeof block.arguments === "string" ? block.arguments : JSON.stringify(block.arguments ?? {})
1810
+ arguments: providerStyle ? JSON.stringify(block.arguments) : typeof block.arguments === "string" ? block.arguments : JSON.stringify(block.arguments ?? {})
2079
1811
  });
2080
1812
  previousReplayItemWasReasoning = false;
2081
1813
  }
2082
1814
  if (output.length > 0) messages.push(...output);
1815
+ else if (providerStyle) continue;
2083
1816
  } else if (msg.role === "toolResult") {
2084
1817
  const textResult = extractToolResultText(msg.content);
2085
1818
  const sanitizedTextResult = sanitizeTransportPayloadText(textResult);
@@ -2108,6 +1841,119 @@ function convertResponsesMessages(model, context, allowedToolCallProviders, opti
2108
1841
  }
2109
1842
  return messages;
2110
1843
  }
1844
+ function convertResponsesMessages$1(model, context, allowedToolCallProviders, options) {
1845
+ return convertResponsesMessagesWithStyle(model, context, allowedToolCallProviders, options, "transport");
1846
+ }
1847
+ function convertProviderResponsesMessages(model, context, allowedToolCallProviders, options) {
1848
+ return convertResponsesMessagesWithStyle(model, context, allowedToolCallProviders, options, "provider");
1849
+ }
1850
+ //#endregion
1851
+ //#region packages/ai/src/transports/openai-responses-replay-internal.ts
1852
+ function isInvalidEncryptedContentError(error) {
1853
+ if (!error || typeof error !== "object") return false;
1854
+ const record = error;
1855
+ if (record.code === "invalid_encrypted_content" || record.code === "thinking_signature_invalid") return true;
1856
+ const message = typeof record.message === "string" ? record.message : "";
1857
+ return message.includes("invalid_encrypted_content") || message.includes("thinking_signature_invalid") || record.status === 400 && message.toLowerCase().includes("could not decrypt the provided encrypted_content");
1858
+ }
1859
+ function isOrphanedFunctionCallOutputError(error) {
1860
+ if (!error || typeof error !== "object") return false;
1861
+ const record = error;
1862
+ const message = typeof record.message === "string" ? record.message : "";
1863
+ return /No tool call found for function call output with call_id [A-Za-z0-9_-]+/.test(message);
1864
+ }
1865
+ function commitResponsesEncryptedContentAttempt(attempt, commit) {
1866
+ if (attempt.kind === "compaction-stripped") commit(attempt.rejectedCompaction);
1867
+ }
1868
+ function stripResponsesRequestEncryptedReasoning(request) {
1869
+ const stripped = stripEncryptedReasoningContentFields(request.input);
1870
+ if (!stripped.changed) return request;
1871
+ return {
1872
+ ...request,
1873
+ input: stripped.value
1874
+ };
1875
+ }
1876
+ function stripResponsesRequestCompaction(request) {
1877
+ if (!Array.isArray(request.input)) return request;
1878
+ const input = request.input.filter((item) => !(item !== null && typeof item === "object" && item.type === "compaction"));
1879
+ return input.length === request.input.length ? request : {
1880
+ ...request,
1881
+ input
1882
+ };
1883
+ }
1884
+ function readOpenAIResponsesCompactionRejection(request) {
1885
+ if (!Array.isArray(request.input)) return;
1886
+ const item = request.input.find((candidate) => candidate !== null && typeof candidate === "object" && candidate.type === "compaction" && typeof candidate.encrypted_content === "string");
1887
+ return item ? {
1888
+ data: item.encrypted_content,
1889
+ ...typeof item.id === "string" ? { id: item.id } : {}
1890
+ } : void 0;
1891
+ }
1892
+ async function resolveNextResponsesEncryptedContentAttempt(attempt, error, options) {
1893
+ const orphanedFunctionOutput = isOrphanedFunctionCallOutputError(error);
1894
+ if (!isInvalidEncryptedContentError(error) && !orphanedFunctionOutput || attempt.kind === "compaction-stripped") return;
1895
+ if (!orphanedFunctionOutput && (attempt.kind === "initial" || attempt.kind === "continuation-rejected")) {
1896
+ const reasoningStripped = stripResponsesRequestEncryptedReasoning(attempt.request);
1897
+ if (reasoningStripped !== attempt.request) return {
1898
+ kind: "reasoning-stripped",
1899
+ request: reasoningStripped
1900
+ };
1901
+ }
1902
+ const locallyStripped = stripResponsesRequestCompaction(attempt.request);
1903
+ if (locallyStripped === attempt.request) return;
1904
+ let compactionStripped = options?.buildFullHistoryRequest ? await options.buildFullHistoryRequest() : locallyStripped;
1905
+ compactionStripped = stripResponsesRequestCompaction(compactionStripped);
1906
+ if (attempt.kind === "reasoning-stripped") compactionStripped = stripResponsesRequestEncryptedReasoning(compactionStripped);
1907
+ return {
1908
+ kind: "compaction-stripped",
1909
+ request: compactionStripped,
1910
+ rejectedCompaction: readOpenAIResponsesCompactionRejection(attempt.request)
1911
+ };
1912
+ }
1913
+ async function createResponsesStreamWithEncryptedContentRetry(params) {
1914
+ const sendAttempt = async (attempt) => {
1915
+ const { data, response } = await params.client.responses.create(attempt.request, params.requestOptions).withResponse();
1916
+ commitResponsesEncryptedContentAttempt(attempt, (checkpoint) => {
1917
+ if (checkpoint) params.onCompactionRejected?.(checkpoint);
1918
+ });
1919
+ return {
1920
+ stream: data,
1921
+ response,
1922
+ attempt
1923
+ };
1924
+ };
1925
+ let attempt = {
1926
+ kind: params.initialAttemptKind ?? "initial",
1927
+ request: params.request,
1928
+ ...params.initialRejectedCompaction ? { rejectedCompaction: params.initialRejectedCompaction } : {}
1929
+ };
1930
+ while (true) {
1931
+ params.observePrompt?.(attempt.request, {
1932
+ egress: "responses-sdk",
1933
+ payloadVariant: attempt.kind
1934
+ });
1935
+ try {
1936
+ return await sendAttempt(attempt);
1937
+ } catch (error) {
1938
+ let nextAttempt = await resolveNextResponsesEncryptedContentAttempt(attempt, error, { buildFullHistoryRequest: params.buildFullHistoryRequest });
1939
+ if (!nextAttempt && attempt.request.previous_response_id && error && typeof error === "object" && typeof error.status === "number" && error.code === "previous_response_not_found") {
1940
+ const request = { ...params.buildFullHistoryRequest ? await params.buildFullHistoryRequest() : attempt.request };
1941
+ delete request.previous_response_id;
1942
+ nextAttempt = {
1943
+ kind: "continuation-rejected",
1944
+ request
1945
+ };
1946
+ }
1947
+ if (!nextAttempt) throw error;
1948
+ 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";
1949
+ log.warn(`[responses] retrying ${retryDescription} provider=${params.model.provider} api=${params.model.api} model=${params.model.id}`);
1950
+ attempt = nextAttempt;
1951
+ }
1952
+ }
1953
+ }
1954
+ function resolveAzureOpenAIApiVersion(env = process.env) {
1955
+ return env.AZURE_OPENAI_API_VERSION?.trim() || "preview";
1956
+ }
2111
1957
  //#endregion
2112
1958
  //#region packages/ai/src/providers/openai-responses-stream-compat.ts
2113
1959
  const OPENAI_RESPONSES_OUTPUT_TEXT_CONTENT_PART_TYPE = "output_text";
@@ -2137,19 +1983,16 @@ function resolveResponsesMessageSnapshotCollapse(params) {
2137
1983
  }
2138
1984
  //#endregion
2139
1985
  //#region packages/ai/src/providers/openai-responses-tool-call-tracker.ts
2140
- function readIdentityValue(value) {
2141
- return (typeof value === "string" ? value.trim() : "") || void 0;
2142
- }
2143
1986
  function readOutputIndex(event) {
2144
1987
  return typeof event.output_index === "number" && Number.isInteger(event.output_index) && event.output_index >= 0 ? event.output_index : void 0;
2145
1988
  }
2146
1989
  function readEventIdentity(event) {
2147
- return { itemId: readIdentityValue(event.item_id) };
1990
+ return { itemId: normalizeOptionalString(event.item_id) };
2148
1991
  }
2149
1992
  function readResponsesToolCallItemIdentity(item) {
2150
1993
  return {
2151
- itemId: readIdentityValue(item.id),
2152
- callId: readIdentityValue(item.call_id)
1994
+ itemId: normalizeOptionalString(item.id),
1995
+ callId: normalizeOptionalString(item.call_id)
2153
1996
  };
2154
1997
  }
2155
1998
  function createResponsesToolCallTracker() {
@@ -2212,6 +2055,308 @@ function createResponsesToolCallTracker() {
2212
2055
  };
2213
2056
  }
2214
2057
  //#endregion
2058
+ //#region packages/ai/src/transports/openai-responses-debug.ts
2059
+ function stringifyUnknown(value, fallback = "") {
2060
+ if (typeof value === "string") return value;
2061
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
2062
+ return fallback;
2063
+ }
2064
+ function safeDebugValue(value) {
2065
+ if (typeof value === "string") return value;
2066
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
2067
+ if (value === null) return "null";
2068
+ if (value === void 0) return "undefined";
2069
+ return Array.isArray(value) ? "array" : typeof value;
2070
+ }
2071
+ function responseInputTextChars(input) {
2072
+ if (typeof input === "string") return input.length;
2073
+ if (Array.isArray(input)) return input.reduce((total, item) => total + responseInputTextChars(item), 0);
2074
+ if (!input || typeof input !== "object") return 0;
2075
+ const record = input;
2076
+ let total = 0;
2077
+ if (typeof record.text === "string") total += record.text.length;
2078
+ if (typeof record.content === "string") total += record.content.length;
2079
+ else if (Array.isArray(record.content)) total += responseInputTextChars(record.content);
2080
+ return total;
2081
+ }
2082
+ function responseInputRoles(input) {
2083
+ if (!Array.isArray(input)) return "";
2084
+ const roles = /* @__PURE__ */ new Set();
2085
+ for (const item of input) if (item && typeof item === "object") {
2086
+ const role = item.role;
2087
+ if (typeof role === "string" && role.trim()) roles.add(role.trim());
2088
+ }
2089
+ return [...roles].toSorted().join(",");
2090
+ }
2091
+ function responseInputItemShape(input) {
2092
+ if (!Array.isArray(input)) return "none";
2093
+ return input.map((item) => {
2094
+ if (!isRecord(item) || typeof item.type !== "string") return "unknown";
2095
+ if (item.type === "message" && typeof item.role === "string") return `message:${item.role}`;
2096
+ return item.type;
2097
+ }).join(",") || "none";
2098
+ }
2099
+ function hashOpaqueResponsesValue(value) {
2100
+ return createHash("sha256").update(value).digest("hex");
2101
+ }
2102
+ function summarizeResponsesCompactionItems(input) {
2103
+ if (!Array.isArray(input)) return [
2104
+ "compactionItems=0",
2105
+ "compactionIdHashes=none",
2106
+ "compactionPayloadHashes=none",
2107
+ "compactionInputIndexes=none"
2108
+ ];
2109
+ const compactions = input.flatMap((item, inputIndex) => {
2110
+ if (!isRecord(item) || item.type !== "compaction") return [];
2111
+ return [{
2112
+ idHash: typeof item.id === "string" ? hashOpaqueResponsesValue(item.id) : void 0,
2113
+ inputIndex,
2114
+ payloadHash: typeof item.encrypted_content === "string" ? hashOpaqueResponsesValue(item.encrypted_content) : void 0
2115
+ }];
2116
+ });
2117
+ return [
2118
+ `compactionItems=${compactions.length}`,
2119
+ `compactionIdHashes=${compactions.flatMap((item) => item.idHash ?? []).join(",") || "none"}`,
2120
+ `compactionPayloadHashes=${compactions.flatMap((item) => item.payloadHash ?? []).join(",") || "none"}`,
2121
+ `compactionInputIndexes=${compactions.map((item) => item.inputIndex).join(",") || "none"}`
2122
+ ];
2123
+ }
2124
+ function readToolPayloadField(record, field) {
2125
+ try {
2126
+ return record[field];
2127
+ } catch {
2128
+ return;
2129
+ }
2130
+ }
2131
+ function readResponsesToolDisplayName(tool) {
2132
+ if (!tool || typeof tool !== "object") return "";
2133
+ const record = tool;
2134
+ const name = readToolPayloadField(record, "name");
2135
+ if (typeof name === "string") return name;
2136
+ const fn = readToolPayloadField(record, "function");
2137
+ if (fn && typeof fn === "object") {
2138
+ const fnName = readToolPayloadField(fn, "name");
2139
+ if (typeof fnName === "string") return fnName;
2140
+ }
2141
+ const type = readToolPayloadField(record, "type");
2142
+ return typeof type === "string" && type !== "function" ? type : "";
2143
+ }
2144
+ function summarizeResponsesTools(tools) {
2145
+ if (!Array.isArray(tools)) return "count=0";
2146
+ const names = tools.map(readResponsesToolDisplayName).filter(Boolean);
2147
+ const mode = resolveModelPayloadDebugMode();
2148
+ const maxNames = mode === "tools" || mode === "full-redacted" ? names.length : 12;
2149
+ const label = maxNames >= names.length ? "names" : "sample";
2150
+ const shown = names.slice(0, maxNames).join(",");
2151
+ return `count=${tools.length}${shown ? ` ${label}=${shown}` : ""}`;
2152
+ }
2153
+ function stringifyRedactedPayload(value) {
2154
+ try {
2155
+ const encoded = JSON.stringify(value, (key, child) => key === "encrypted_content" ? "<opaque data omitted>" : child);
2156
+ if (!encoded) return "<empty>";
2157
+ const redacted = redactSensitiveText(encoded, { mode: "tools" });
2158
+ return redacted.length > 8e3 ? `${truncateUtf16Safe(redacted, 8e3)}…<truncated>` : redacted;
2159
+ } catch {
2160
+ return "<unserializable>";
2161
+ }
2162
+ }
2163
+ function stringifyRedactedEvent(value) {
2164
+ const redacted = stringifyRedactedPayload(value);
2165
+ return redacted.length > 2e3 ? `${truncateUtf16Safe(redacted, 2e3)}…<truncated>` : redacted;
2166
+ }
2167
+ const RESPONSE_FAILED_FAILURE_FIELD_KEYS = [
2168
+ "error",
2169
+ "incomplete_details",
2170
+ "status_details",
2171
+ "failure_reason",
2172
+ "last_error",
2173
+ "provider_error",
2174
+ "error_details"
2175
+ ];
2176
+ function readResponseFailedString(record, key) {
2177
+ return stringifyUnknown(record?.[key]);
2178
+ }
2179
+ function buildResponsesFailedEventSummary(message, responseId, observation) {
2180
+ const summary = { message };
2181
+ if (responseId) summary.responseId = responseId;
2182
+ if (observation) summary.observation = observation;
2183
+ return summary;
2184
+ }
2185
+ function isResponseFailedIdentifierKey(key) {
2186
+ const normalized = key.replace(/[-_\s]/g, "").toLowerCase();
2187
+ return normalized === "requestid" || normalized === "xrequestid" || normalized === "providerrequestid" || normalized === "providerresponseid" || normalized === "litellmrequestid" || normalized.includes("request") && normalized.endsWith("id") || normalized.includes("provider") && normalized.endsWith("id");
2188
+ }
2189
+ function collectResponseFailedIdentifierHashes(value, opts = {}) {
2190
+ const path = opts.path ?? "";
2191
+ const depth = opts.depth ?? 0;
2192
+ const identifierKey = opts.identifierKey ?? "";
2193
+ const out = opts.out ?? [];
2194
+ const seen = opts.seen ?? /* @__PURE__ */ new WeakSet();
2195
+ if (out.length >= 12 || depth > 4 || !value || typeof value !== "object") return out;
2196
+ if (seen.has(value)) return out;
2197
+ seen.add(value);
2198
+ if (Array.isArray(value)) {
2199
+ for (const [index, item] of value.entries()) {
2200
+ if (index >= 8 || out.length >= 12) break;
2201
+ const itemString = typeof item === "string" || typeof item === "number" ? String(item).trim() : "";
2202
+ if (identifierKey && isResponseFailedIdentifierKey(identifierKey) && itemString) {
2203
+ out.push(`${path}[${index}]=${redactIdentifier(itemString, { len: 12 })}`);
2204
+ continue;
2205
+ }
2206
+ collectResponseFailedIdentifierHashes(item, {
2207
+ path: `${path}[${index}]`,
2208
+ depth: depth + 1,
2209
+ identifierKey,
2210
+ out,
2211
+ seen
2212
+ });
2213
+ }
2214
+ return out;
2215
+ }
2216
+ for (const [key, child] of Object.entries(value)) {
2217
+ if (out.length >= 12) break;
2218
+ const childPath = path ? `${path}.${key}` : key;
2219
+ const childString = typeof child === "string" || typeof child === "number" ? String(child).trim() : "";
2220
+ if (isResponseFailedIdentifierKey(key) && childString) {
2221
+ out.push(`${childPath}=${redactIdentifier(childString, { len: 12 })}`);
2222
+ continue;
2223
+ }
2224
+ collectResponseFailedIdentifierHashes(child, {
2225
+ path: childPath,
2226
+ depth: depth + 1,
2227
+ identifierKey: isResponseFailedIdentifierKey(key) ? key : void 0,
2228
+ out,
2229
+ seen
2230
+ });
2231
+ }
2232
+ return out;
2233
+ }
2234
+ function redactResponseFailedDiagnosticValue(value, opts = {}) {
2235
+ const key = opts.key ?? "";
2236
+ const depth = opts.depth ?? 0;
2237
+ if (typeof value === "string" || typeof value === "number") return key && isResponseFailedIdentifierKey(key) ? redactIdentifier(String(value), { len: 12 }) : value;
2238
+ if (depth > 6 || !value || typeof value !== "object") return value;
2239
+ const seen = opts.seen ?? /* @__PURE__ */ new WeakSet();
2240
+ if (seen.has(value)) return "<circular>";
2241
+ seen.add(value);
2242
+ if (Array.isArray(value)) return value.slice(0, 16).map((item) => redactResponseFailedDiagnosticValue(item, {
2243
+ key,
2244
+ depth: depth + 1,
2245
+ seen
2246
+ }));
2247
+ const out = {};
2248
+ for (const [childKey, child] of Object.entries(value)) out[childKey] = redactResponseFailedDiagnosticValue(child, {
2249
+ key: childKey,
2250
+ depth: depth + 1,
2251
+ seen
2252
+ });
2253
+ return out;
2254
+ }
2255
+ function buildResponsesFailedFailureFields(response) {
2256
+ if (!response) return {};
2257
+ const fields = {};
2258
+ for (const key of RESPONSE_FAILED_FAILURE_FIELD_KEYS) if (response[key] !== void 0 && response[key] !== null) fields[key] = response[key];
2259
+ return fields;
2260
+ }
2261
+ function buildResponsesFailedNoDetailsObservation(event, model, response = isRecord(event.response) ? event.response : void 0) {
2262
+ const failureFields = redactResponseFailedDiagnosticValue(buildResponsesFailedFailureFields(response));
2263
+ const metadataKeys = isRecord(response?.metadata) ? Object.keys(response.metadata).toSorted() : [];
2264
+ const responsePreview = {
2265
+ id: readResponseFailedString(response, "id"),
2266
+ status: readResponseFailedString(response, "status"),
2267
+ model: readResponseFailedString(response, "model"),
2268
+ object: readResponseFailedString(response, "object"),
2269
+ failureFields,
2270
+ metadataKeys
2271
+ };
2272
+ return {
2273
+ event: "openai_responses_response_failed_without_details",
2274
+ provider: model.provider,
2275
+ api: model.api,
2276
+ transportModel: model.id,
2277
+ providerRuntimeFailureKind: "no_error_details",
2278
+ responseId: responsePreview.id,
2279
+ responseStatus: responsePreview.status,
2280
+ responseModel: responsePreview.model,
2281
+ responseObject: responsePreview.object,
2282
+ metadataKeys,
2283
+ requestIdHashes: collectResponseFailedIdentifierHashes(event),
2284
+ failureFieldsPreview: stringifyRedactedEvent(failureFields),
2285
+ responsePreview: stringifyRedactedEvent(responsePreview)
2286
+ };
2287
+ }
2288
+ function summarizeResponsesFailedNoDetailsObservation(observation) {
2289
+ const requestIds = observation.requestIdHashes.join(",");
2290
+ const metadataKeys = observation.metadataKeys.join(",");
2291
+ 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}`;
2292
+ }
2293
+ function normalizeResponsesFailedEvent(event, model) {
2294
+ const response = isRecord(event.response) ? event.response : void 0;
2295
+ const responseId = readResponseFailedString(response, "id") || void 0;
2296
+ const error = isRecord(response?.error) ? response.error : void 0;
2297
+ if (error) {
2298
+ const code = readResponseFailedString(error, "code").trim();
2299
+ const message = readResponseFailedString(error, "message").trim();
2300
+ if (code || message) return buildResponsesFailedEventSummary(`${code || "unknown"}: ${message || "no message"}`, responseId);
2301
+ }
2302
+ const incompleteReason = readResponseFailedString(isRecord(response?.incomplete_details) ? response.incomplete_details : void 0, "reason");
2303
+ if (incompleteReason) return buildResponsesFailedEventSummary(`incomplete: ${incompleteReason}`, responseId);
2304
+ return buildResponsesFailedEventSummary(RESPONSE_FAILED_NO_DETAILS_MESSAGE, responseId, buildResponsesFailedNoDetailsObservation(event, model, response));
2305
+ }
2306
+ var ResponsesStreamFailure = class extends Error {
2307
+ constructor(failure, response) {
2308
+ super(failure.message);
2309
+ this.name = "ResponsesStreamFailure";
2310
+ this.responseId = failure.responseId;
2311
+ this.response = response;
2312
+ this.observation = failure.observation;
2313
+ }
2314
+ };
2315
+ function logResponsesFailedNoDetails(observation) {
2316
+ log.warn(`[responses] response.failed missing error details provider=${observation.provider} api=${observation.api} model=${observation.transportModel} ` + summarizeResponsesFailedNoDetailsObservation(observation), observation);
2317
+ }
2318
+ function summarizeResponsesPayload(params) {
2319
+ if (!params || typeof params !== "object") return "payload=non-object";
2320
+ const record = params;
2321
+ const input = record.input;
2322
+ const reasoning = record.reasoning && typeof record.reasoning === "object" ? record.reasoning : void 0;
2323
+ const text = record.text && typeof record.text === "object" ? record.text : void 0;
2324
+ const parts = [
2325
+ `fields=${Object.keys(record).toSorted().join(",")}`,
2326
+ `model=${safeDebugValue(record.model)}`,
2327
+ `stream=${safeDebugValue(record.stream)}`,
2328
+ `inputItems=${Array.isArray(input) ? input.length : typeof input}`,
2329
+ `inputItemShape=${responseInputItemShape(input)}`,
2330
+ `inputRoles=${responseInputRoles(input) || "none"}`,
2331
+ `inputTextChars=${responseInputTextChars(input)}`,
2332
+ `tools=${summarizeResponsesTools(record.tools)}`,
2333
+ `reasoningEffort=${safeDebugValue(reasoning?.effort)}`,
2334
+ `reasoningSummary=${safeDebugValue(reasoning?.summary)}`,
2335
+ `textVerbosity=${safeDebugValue(text?.verbosity)}`,
2336
+ `serviceTier=${safeDebugValue(record.service_tier)}`,
2337
+ ...summarizeResponsesCompactionItems(input),
2338
+ `store=${safeDebugValue(record.store)}`,
2339
+ `promptCacheKey=${record.prompt_cache_key === void 0 ? "absent" : "present"}`,
2340
+ `metadataKeys=${record.metadata && typeof record.metadata === "object" ? Object.keys(record.metadata).toSorted().join(",") : "none"}`
2341
+ ];
2342
+ if (resolveModelPayloadDebugMode() === "full-redacted") parts.push(`payload=${stringifyRedactedPayload(record)}`);
2343
+ return parts.join(" ");
2344
+ }
2345
+ function summarizeOpenAITransportError(error) {
2346
+ if (!error || typeof error !== "object") return `type=${typeof error} message=${safeDebugValue(error)}`;
2347
+ const record = error;
2348
+ const cause = record.cause && typeof record.cause === "object" ? record.cause : void 0;
2349
+ return [
2350
+ `name=${safeDebugValue(record.name)}`,
2351
+ `status=${safeDebugValue(record.status)}`,
2352
+ `code=${safeDebugValue(record.code)}`,
2353
+ `type=${safeDebugValue(record.type)}`,
2354
+ `causeName=${safeDebugValue(cause?.name)}`,
2355
+ `causeCode=${safeDebugValue(cause?.code)}`,
2356
+ `message=${error instanceof Error ? error.message : safeDebugValue(error)}`
2357
+ ].join(" ");
2358
+ }
2359
+ //#endregion
2215
2360
  //#region packages/ai/src/transports/openai-responses-stream-observer-internal.ts
2216
2361
  const STRING_DELTA_EVENTS = /* @__PURE__ */ new Set([
2217
2362
  "response.function_call_arguments.delta",
@@ -2233,7 +2378,7 @@ async function* adaptResponsesStream(stream, signal) {
2233
2378
  await scheduler.afterEvent();
2234
2379
  }
2235
2380
  }
2236
- async function* observeResponsesStream(stream, model) {
2381
+ async function* observeResponsesStream(stream, model, requestStartedAt) {
2237
2382
  const startedAt = Date.now();
2238
2383
  const eventTypes = /* @__PURE__ */ new Map();
2239
2384
  const debugMode = resolveModelSseDebugMode();
@@ -2243,7 +2388,7 @@ async function* observeResponsesStream(stream, model) {
2243
2388
  const type = isRecord(event) && typeof event.type === "string" ? event.type : "unknown";
2244
2389
  eventCount += 1;
2245
2390
  eventTypes.set(type, (eventTypes.get(type) ?? 0) + 1);
2246
- if (eventCount === 1) emitModelTransportDebug(log, `[responses] first_event provider=${model.provider} api=${model.api} model=${model.id} elapsedMs=${Date.now() - startedAt} type=${type}`);
2391
+ 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}`);
2247
2392
  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)}`);
2248
2393
  yield event;
2249
2394
  }
@@ -2254,6 +2399,29 @@ async function* observeResponsesStream(stream, model) {
2254
2399
  }
2255
2400
  //#endregion
2256
2401
  //#region packages/ai/src/transports/openai-responses-stream-slots-internal.ts
2402
+ function createResponsesOutputContentIndex() {
2403
+ const indexes = /* @__PURE__ */ new Map();
2404
+ const identity = (item) => {
2405
+ if ((item.type === "reasoning" || item.type === "message") && item.id) return `${item.type}:${item.id}`;
2406
+ return item.type === "function_call" ? `function_call:${item.call_id ?? item.id ?? ""}` : void 0;
2407
+ };
2408
+ return {
2409
+ get(item) {
2410
+ const key = identity(item);
2411
+ return key === void 0 ? void 0 : indexes.get(key);
2412
+ },
2413
+ set(item, contentIndex) {
2414
+ const key = identity(item);
2415
+ if (key !== void 0) indexes.set(key, contentIndex);
2416
+ }
2417
+ };
2418
+ }
2419
+ function appendResponsesPendingTextDelta(slot, delta, materialize) {
2420
+ slot.pendingText = `${slot.pendingText ?? ""}${delta}`;
2421
+ const priorText = slot.collapseCandidate?.block.text ?? "";
2422
+ if (priorText.startsWith(slot.pendingText) || slot.pendingText.startsWith(priorText)) return;
2423
+ materialize(slot);
2424
+ }
2257
2425
  function readResponsesOutputIndex(event) {
2258
2426
  const outputIndex = event.output_index;
2259
2427
  return typeof outputIndex === "number" && Number.isInteger(outputIndex) && outputIndex >= 0 ? outputIndex : void 0;
@@ -2296,6 +2464,14 @@ function createResponsesOutputSlotTracker() {
2296
2464
  }
2297
2465
  //#endregion
2298
2466
  //#region packages/ai/src/providers/openai-responses-terminal-usage.ts
2467
+ /**
2468
+ * Canonical mapping for terminal OpenAI Responses events.
2469
+ *
2470
+ * `response.completed`, `response.incomplete`, and `response.failed` are terminal and can carry
2471
+ * usage, so every Responses path finalizes through the helpers here. Keeping one owner prevents
2472
+ * package and managed transports from drifting on token buckets, service-tier pricing, or future
2473
+ * terminal-event semantics.
2474
+ */
2299
2475
  function readCount(value) {
2300
2476
  return typeof value === "number" && Number.isFinite(value) ? value : 0;
2301
2477
  }
@@ -2325,8 +2501,7 @@ function mapResponsesTerminalUsage(usage) {
2325
2501
  }
2326
2502
  /** Reasoning tokens are reported by the agent path only; the package path does not track them. */
2327
2503
  function readResponsesReasoningTokens(usage) {
2328
- const reasoningTokens = usage?.output_tokens_details?.reasoning_tokens;
2329
- return typeof reasoningTokens === "number" && Number.isFinite(reasoningTokens) ? reasoningTokens : void 0;
2504
+ return asFiniteNumber(usage?.output_tokens_details?.reasoning_tokens);
2330
2505
  }
2331
2506
  function mapResponsesTerminalStopReason(status) {
2332
2507
  if (!status) return "stop";
@@ -2371,13 +2546,19 @@ function resolveResponsesToolCallId(item, fallbackId) {
2371
2546
  const generated = `call_${randomUUID().replaceAll("-", "").slice(0, 24)}`;
2372
2547
  return resolvedItemId ? `${generated}|${resolvedItemId}` : generated;
2373
2548
  }
2374
- function resolveCompletedToolCallName(toolCall, value) {
2375
- const streamedName = toolCall?.block.name.trim() || void 0;
2376
- const completedName = typeof value === "string" ? value.trim() || void 0 : void 0;
2549
+ function resolveCompletedResponsesToolCall(item, streamed) {
2550
+ if (item.status && item.status !== "completed") throw new Error("Responses stream completed with an incomplete terminal tool call");
2551
+ const streamedName = streamed?.name?.trim() || void 0;
2552
+ const completedName = typeof item.name === "string" ? item.name.trim() || void 0 : void 0;
2377
2553
  if (streamedName && completedName && streamedName !== completedName) throw new Error(`Responses stream changed tool-call function name from ${streamedName} to ${completedName}`);
2378
2554
  const name = completedName ?? streamedName;
2379
2555
  if (!name) throw new Error("Responses stream completed tool call without a function name");
2380
- return name;
2556
+ const argumentsValue = parseJsonObjectPreservingUnsafeIntegers(streamed?.arguments ?? item.arguments);
2557
+ if (!argumentsValue) throw new Error("Responses stream completed tool call with invalid JSON arguments");
2558
+ return {
2559
+ name,
2560
+ arguments: argumentsValue
2561
+ };
2381
2562
  }
2382
2563
  function createResponsesTerminalController(params) {
2383
2564
  const { output, stream, model, options } = params;
@@ -2400,8 +2581,35 @@ function createResponsesTerminalController(params) {
2400
2581
  const content = part;
2401
2582
  return content.type === "output_text" || content.type === "text" ? content.text ?? "" : content.refusal ?? "";
2402
2583
  }).join("");
2403
- if (!text) return;
2584
+ const started = params.startedTextBlocksByItemId.get(item.id);
2585
+ if (!text && !started) return;
2404
2586
  const phase = item.phase ?? void 0;
2587
+ if (started) {
2588
+ const previousText = started.block.text;
2589
+ started.block.text = text;
2590
+ started.block.textSignature = encodeTextSignatureV1(item.id, phase);
2591
+ params.setLastTextBlock({
2592
+ block: started.block,
2593
+ index: started.index,
2594
+ phase
2595
+ });
2596
+ params.startedTextBlocksByItemId.delete(item.id);
2597
+ if (text.startsWith(previousText)) {
2598
+ const delta = text.slice(previousText.length);
2599
+ if (delta) stream.push({
2600
+ type: "text_delta",
2601
+ contentIndex: started.index,
2602
+ delta
2603
+ });
2604
+ }
2605
+ stream.push({
2606
+ type: "text_end",
2607
+ contentIndex: started.index,
2608
+ content: text,
2609
+ partial: output
2610
+ });
2611
+ return started.index;
2612
+ }
2405
2613
  const previous = params.getLastTextBlock();
2406
2614
  const collapse = resolveResponsesMessageSnapshotCollapse({
2407
2615
  prior: previous && {
@@ -2420,7 +2628,7 @@ function createResponsesTerminalController(params) {
2420
2628
  content: collapse.text,
2421
2629
  partial: output
2422
2630
  });
2423
- return;
2631
+ return previous.index;
2424
2632
  }
2425
2633
  const block = {
2426
2634
  type: "text",
@@ -2445,13 +2653,15 @@ function createResponsesTerminalController(params) {
2445
2653
  content: text,
2446
2654
  partial: output
2447
2655
  });
2656
+ return index;
2448
2657
  };
2449
2658
  const appendToolCall = (item) => {
2659
+ const validated = resolveCompletedResponsesToolCall(item);
2450
2660
  const toolCall = {
2451
2661
  type: "toolCall",
2452
2662
  id: resolveResponsesToolCallId(item),
2453
- name: resolveCompletedToolCallName(void 0, item.name),
2454
- arguments: parseStreamingJson(item.arguments || "{}")
2663
+ name: validated.name,
2664
+ arguments: validated.arguments
2455
2665
  };
2456
2666
  blocks.push(toolCall);
2457
2667
  const contentIndex = blocks.length - 1;
@@ -2466,19 +2676,50 @@ function createResponsesTerminalController(params) {
2466
2676
  toolCall,
2467
2677
  partial: output
2468
2678
  });
2679
+ return contentIndex;
2469
2680
  };
2470
2681
  const recoverTerminalOutput = (items, includeToolCalls) => {
2471
- if (blocks.some((block) => block.type !== "thinking")) return;
2472
- for (const item of items) if (item.type === "message") appendText(item);
2473
- else {
2682
+ let hasCompletedLaterOutput = false;
2683
+ for (const item of items.toReversed()) {
2684
+ if (item.type === "reasoning") {
2685
+ hasCompletedLaterOutput ||= params.outputItemContentIndexes.get(item) !== void 0;
2686
+ continue;
2687
+ }
2688
+ if (item.type !== "message" && item.type !== "function_call") continue;
2689
+ if (params.outputItemContentIndexes.get(item) !== void 0 || item.type === "message" && params.startedTextBlocksByItemId.has(item.id)) {
2690
+ hasCompletedLaterOutput = true;
2691
+ continue;
2692
+ }
2693
+ if (item.type === "function_call" && !includeToolCalls) continue;
2694
+ if (hasCompletedLaterOutput) throw new Error("Responses stream omitted an output item before completed output");
2695
+ if (item.type === "function_call") resolveCompletedResponsesToolCall(item);
2696
+ }
2697
+ for (const [terminalIndex, item] of items.entries()) if (item.type === "message") {
2698
+ if (params.outputItemContentIndexes.get(item) !== void 0 && !params.startedTextBlocksByItemId.has(item.id)) continue;
2699
+ const appendedIndex = appendText(item);
2700
+ if (appendedIndex !== void 0) params.outputItemContentIndexes.set(item, appendedIndex);
2701
+ } else {
2474
2702
  params.setLastTextBlock(null);
2475
- if (includeToolCalls && item.type === "function_call") appendToolCall(item);
2703
+ const alreadyCapturedCompaction = item.type === "compaction" && output.providerReplay?.type === "openai-responses-compaction" && output.providerReplay.id === item.id && output.providerReplay.data === item.encrypted_content;
2704
+ if (item.type === "compaction" && !alreadyCapturedCompaction) {
2705
+ let replayIndex = blocks.length;
2706
+ for (const laterItem of items.slice(terminalIndex + 1)) {
2707
+ const laterContentIndex = params.outputItemContentIndexes.get(laterItem);
2708
+ if (laterContentIndex !== void 0) {
2709
+ replayIndex = laterContentIndex;
2710
+ break;
2711
+ }
2712
+ }
2713
+ captureOpenAIResponsesCompaction(output, item, replayIndex, model, options?.reasoningReplayMetadata);
2714
+ } else if (includeToolCalls && item.type === "function_call") {
2715
+ if (params.outputItemContentIndexes.get(item) !== void 0) continue;
2716
+ params.outputItemContentIndexes.set(item, appendToolCall(item));
2717
+ }
2476
2718
  }
2477
2719
  };
2478
- const finalizeResponse = (response, terminalEventType) => {
2479
- params.markFinalized();
2480
- backfillReasoning(response.output ?? []);
2481
- output.responseId = response.id || output.responseId;
2720
+ const finalizeTerminalFacts = (response, responseId = response.id) => {
2721
+ output.responseId = responseId || output.responseId;
2722
+ output.responseModel = response.model?.trim() || void 0;
2482
2723
  const usage = mapResponsesTerminalUsage(response.usage);
2483
2724
  const reasoningTokens = readResponsesReasoningTokens(response.usage);
2484
2725
  if (usage) output.usage = {
@@ -2497,6 +2738,11 @@ function createResponsesTerminalController(params) {
2497
2738
  const tier = options.resolveServiceTier ? options.resolveServiceTier(response.service_tier, options.serviceTier) : response.service_tier ?? options.serviceTier;
2498
2739
  options.applyServiceTierPricing(output.usage, tier);
2499
2740
  }
2741
+ };
2742
+ const finalizeResponse = (response, terminalEventType) => {
2743
+ params.markFinalized();
2744
+ backfillReasoning(response.output ?? []);
2745
+ finalizeTerminalFacts(response);
2500
2746
  const terminal = resolveResponsesTerminalStopReason({
2501
2747
  status: response.status,
2502
2748
  terminalEventType,
@@ -2508,28 +2754,22 @@ function createResponsesTerminalController(params) {
2508
2754
  };
2509
2755
  return {
2510
2756
  finalizeResponse,
2757
+ finalizeFailedResponse: finalizeTerminalFacts,
2511
2758
  recoverTerminalOutput
2512
2759
  };
2513
2760
  }
2514
2761
  //#endregion
2515
2762
  //#region packages/ai/src/transports/openai-responses-stream-internal.ts
2516
- var ResponsesStreamFailure = class extends Error {
2517
- constructor(failure, response) {
2518
- super(failure.message);
2519
- this.name = "ResponsesStreamFailure";
2520
- this.responseId = failure.responseId;
2521
- this.response = response;
2522
- this.observation = failure.observation;
2523
- }
2524
- };
2525
2763
  async function processResponsesStream(openaiStream, output, stream, model, options) {
2526
2764
  const streamingToolCalls = createResponsesToolCallTracker();
2527
2765
  const outputSlots = createResponsesOutputSlotTracker();
2528
2766
  const reasoningBlocksById = /* @__PURE__ */ new Map();
2529
- let terminalResponseEvent;
2767
+ const outputItemContentIndexes = createResponsesOutputContentIndex();
2768
+ const startedTextBlocksByItemId = /* @__PURE__ */ new Map();
2769
+ let terminalResponse;
2530
2770
  let lastTextBlock = null;
2531
2771
  const blocks = output.content;
2532
- const blockIndex = () => blocks.length - 1;
2772
+ const compactionTracker = createCompactionTracker(output, model, options);
2533
2773
  const createOutputSlot = (event, item) => {
2534
2774
  if (item.type === "reasoning") {
2535
2775
  const block = {
@@ -2543,6 +2783,8 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
2543
2783
  contentIndex: blocks.length
2544
2784
  };
2545
2785
  blocks.push(block);
2786
+ reasoningBlocksById.set(item.id, block);
2787
+ outputItemContentIndexes.set(item, slot.contentIndex);
2546
2788
  outputSlots.register(event, slot);
2547
2789
  stream.push({
2548
2790
  type: "thinking_start",
@@ -2567,7 +2809,15 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
2567
2809
  pendingText: collapseCandidate ? "" : null,
2568
2810
  collapseCandidate
2569
2811
  };
2570
- if (block) blocks.push(block);
2812
+ if (block) {
2813
+ blocks.push(block);
2814
+ outputItemContentIndexes.set(messageItem, slot.contentIndex ?? blocks.length - 1);
2815
+ startedTextBlocksByItemId.set(messageItem.id, {
2816
+ block,
2817
+ index: slot.contentIndex ?? blocks.length - 1,
2818
+ phase: messageItem.phase ?? void 0
2819
+ });
2820
+ }
2571
2821
  outputSlots.register(event, slot);
2572
2822
  if (slot.contentIndex !== void 0) stream.push({
2573
2823
  type: "text_start",
@@ -2594,7 +2844,13 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
2594
2844
  ...slot.item.phase ? { textSignature: encodeTextSignatureV1(slot.item.id, slot.item.phase) } : {}
2595
2845
  };
2596
2846
  blocks.push(slot.block);
2597
- slot.contentIndex = blockIndex();
2847
+ slot.contentIndex = blocks.length - 1;
2848
+ outputItemContentIndexes.set(slot.item, slot.contentIndex);
2849
+ startedTextBlocksByItemId.set(slot.item.id, {
2850
+ block: slot.block,
2851
+ index: slot.contentIndex,
2852
+ phase: slot.item.phase ?? void 0
2853
+ });
2598
2854
  stream.push({
2599
2855
  type: "text_start",
2600
2856
  contentIndex: slot.contentIndex,
@@ -2612,25 +2868,19 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
2612
2868
  const materializeDeferredTextSlots = (except) => {
2613
2869
  for (const slot of outputSlots.values()) if (slot !== except && slot.type === "text") materializeDeferredTextSlot(slot);
2614
2870
  };
2615
- const appendPendingMessageDelta = (slot, delta) => {
2616
- slot.pendingText = `${slot.pendingText ?? ""}${delta}`;
2617
- const priorText = slot.collapseCandidate?.block.text ?? "";
2618
- if (priorText.startsWith(slot.pendingText) || slot.pendingText.startsWith(priorText)) return;
2619
- materializeDeferredTextSlot(slot);
2620
- };
2621
- const { finalizeResponse, recoverTerminalOutput } = createResponsesTerminalController({
2871
+ const { finalizeResponse, finalizeFailedResponse, recoverTerminalOutput } = createResponsesTerminalController({
2622
2872
  output,
2623
2873
  stream,
2624
2874
  model,
2625
2875
  options,
2626
2876
  reasoningBlocksById,
2877
+ startedTextBlocksByItemId,
2878
+ outputItemContentIndexes,
2627
2879
  getLastTextBlock: () => lastTextBlock,
2628
2880
  setLastTextBlock: (block) => {
2629
2881
  lastTextBlock = block;
2630
2882
  },
2631
- markFinalized: () => {
2632
- terminalResponseEvent = "finalized";
2633
- }
2883
+ markFinalized: () => void 0
2634
2884
  });
2635
2885
  const guardedStream = adaptResponsesStream(withFirstStreamEventTimeout(openaiStream, {
2636
2886
  provider: model.provider,
@@ -2643,322 +2893,538 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
2643
2893
  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."
2644
2894
  }), options?.signal);
2645
2895
  try {
2646
- for await (const event of guardedStream) if (event.type === "response.created") output.responseId = event.response.id;
2647
- else if (event.type === "response.output_item.added") {
2648
- materializeDeferredTextSlots();
2649
- const item = event.item;
2650
- if (item.type !== "message") lastTextBlock = null;
2651
- if (item.type === "reasoning" || item.type === "message") createOutputSlot(event, item);
2652
- else if (item.type === "function_call") {
2653
- const toolCallBlock = {
2654
- type: "toolCall",
2655
- id: resolveResponsesToolCallId(item),
2656
- name: typeof item.name === "string" ? item.name.trim() : "",
2657
- arguments: {},
2658
- partialJson: item.arguments || ""
2659
- };
2660
- const contentIndex = output.content.length;
2661
- const toolCallState = {
2662
- block: toolCallBlock,
2663
- contentIndex,
2664
- argumentStreamReliable: true,
2665
- ...readResponsesToolCallItemIdentity(item)
2666
- };
2667
- streamingToolCalls.register(event, toolCallState);
2668
- if (readResponsesOutputIndex(event) !== void 0) outputSlots.register(event, {
2669
- type: "toolCall",
2670
- toolCall: toolCallState
2671
- });
2672
- output.content.push(toolCallBlock);
2673
- stream.push({
2674
- type: "toolcall_start",
2675
- contentIndex,
2676
- partial: output
2677
- });
2678
- }
2679
- } else if (event.type === "response.reasoning_summary_part.added") {
2680
- const slot = outputSlots.resolve(event, "thinking");
2681
- if (!slot) continue;
2682
- slot.item.summary = slot.item.summary || [];
2683
- slot.item.summary.push(event.part);
2684
- } else if (event.type === "response.reasoning_summary_text.delta") {
2685
- const slot = outputSlots.resolve(event, "thinking");
2686
- if (!slot) continue;
2687
- slot.item.summary = slot.item.summary || [];
2688
- const lastPart = slot.item.summary[slot.item.summary.length - 1];
2689
- if (!lastPart) continue;
2690
- slot.block.thinking += event.delta;
2691
- lastPart.text += event.delta;
2692
- stream.push({
2693
- type: "thinking_delta",
2694
- contentIndex: slot.contentIndex,
2695
- delta: event.delta,
2696
- partial: output
2697
- });
2698
- } else if (event.type === "response.reasoning_summary_part.done") {
2699
- const slot = outputSlots.resolve(event, "thinking");
2700
- if (!slot) continue;
2701
- slot.item.summary = slot.item.summary || [];
2702
- const lastPart = slot.item.summary[slot.item.summary.length - 1];
2703
- if (!lastPart) continue;
2704
- slot.block.thinking += "\n\n";
2705
- lastPart.text += "\n\n";
2706
- stream.push({
2707
- type: "thinking_delta",
2708
- contentIndex: slot.contentIndex,
2709
- delta: "\n\n",
2710
- partial: output
2711
- });
2712
- } else if (event.type === "response.reasoning_text.delta") {
2713
- const slot = outputSlots.resolve(event, "thinking");
2714
- if (!slot) continue;
2715
- slot.block.thinking += event.delta;
2716
- stream.push({
2717
- type: "thinking_delta",
2718
- contentIndex: slot.contentIndex,
2719
- delta: event.delta,
2720
- partial: output
2721
- });
2722
- } else if (event.type === "response.content_part.added") {
2723
- const slot = outputSlots.resolve(event, "text");
2724
- if (!slot) continue;
2725
- slot.item.content = slot.item.content || [];
2726
- if (event.part.type === "output_text" || event.part.type === "text" || event.part.type === "refusal") slot.item.content.push(event.part);
2727
- } else if (event.type === "response.output_text.delta") {
2728
- const slot = outputSlots.resolve(event, "text");
2729
- if (!slot) continue;
2730
- slot.item.content ||= [];
2731
- let lastPart = slot.item.content[slot.item.content.length - 1];
2732
- if (!isResponsesTextContentPartType(lastPart?.type)) {
2733
- lastPart = {
2734
- type: "output_text",
2735
- text: "",
2736
- annotations: []
2737
- };
2738
- slot.item.content.push(lastPart);
2739
- }
2740
- lastPart.text += event.delta;
2741
- if (slot.pendingText !== null) appendPendingMessageDelta(slot, event.delta);
2742
- else if (slot.block && slot.contentIndex !== void 0) {
2743
- slot.block.text += event.delta;
2896
+ for await (const event of guardedStream) {
2897
+ notifyLlmRequestActivity(options?.signal);
2898
+ if (event.type === "response.created") output.responseId = event.response.id;
2899
+ else if (event.type === "response.output_item.added") {
2900
+ materializeDeferredTextSlots();
2901
+ const item = event.item;
2902
+ compactionTracker.added(item, blocks.length);
2903
+ if (item.type !== "message") lastTextBlock = null;
2904
+ if (item.type === "reasoning" || item.type === "message") createOutputSlot(event, item);
2905
+ else if (item.type === "function_call") {
2906
+ const toolCallBlock = {
2907
+ type: "toolCall",
2908
+ id: resolveResponsesToolCallId(item),
2909
+ name: typeof item.name === "string" ? item.name.trim() : "",
2910
+ arguments: {},
2911
+ partialJson: item.arguments || ""
2912
+ };
2913
+ const contentIndex = output.content.length;
2914
+ const toolCallState = {
2915
+ block: toolCallBlock,
2916
+ contentIndex,
2917
+ argumentStreamReliable: true,
2918
+ ...readResponsesToolCallItemIdentity(item)
2919
+ };
2920
+ streamingToolCalls.register(event, toolCallState);
2921
+ if (readResponsesOutputIndex(event) !== void 0) outputSlots.register(event, {
2922
+ type: "toolCall",
2923
+ toolCall: toolCallState
2924
+ });
2925
+ output.content.push(toolCallBlock);
2926
+ outputItemContentIndexes.set(item, contentIndex);
2927
+ stream.push({
2928
+ type: "toolcall_start",
2929
+ contentIndex,
2930
+ partial: output
2931
+ });
2932
+ }
2933
+ } else if (event.type === "response.reasoning_summary_part.added") {
2934
+ const slot = outputSlots.resolve(event, "thinking");
2935
+ if (!slot) continue;
2936
+ slot.item.summary = slot.item.summary || [];
2937
+ slot.item.summary.push(event.part);
2938
+ } else if (event.type === "response.reasoning_summary_text.delta") {
2939
+ const slot = outputSlots.resolve(event, "thinking");
2940
+ if (!slot) continue;
2941
+ slot.item.summary = slot.item.summary || [];
2942
+ const lastPart = slot.item.summary[slot.item.summary.length - 1];
2943
+ if (!lastPart) continue;
2944
+ slot.block.thinking += event.delta;
2945
+ lastPart.text += event.delta;
2744
2946
  stream.push({
2745
- type: "text_delta",
2947
+ type: "thinking_delta",
2746
2948
  contentIndex: slot.contentIndex,
2747
- delta: event.delta
2949
+ delta: event.delta,
2950
+ partial: output
2748
2951
  });
2749
- }
2750
- } else if (isAzureResponsesTextDeltaEvent(event)) {
2751
- const slot = outputSlots.resolve(event, "text");
2752
- if (!slot) continue;
2753
- slot.item.content = slot.item.content || [];
2754
- let lastPart = slot.item.content[slot.item.content.length - 1];
2755
- if (lastPart?.type !== "text") {
2756
- lastPart = {
2757
- type: "text",
2758
- text: ""
2759
- };
2760
- slot.item.content.push(lastPart);
2761
- }
2762
- lastPart.text += event.delta;
2763
- if (slot.pendingText !== null) appendPendingMessageDelta(slot, event.delta);
2764
- else if (slot.block && slot.contentIndex !== void 0) {
2765
- slot.block.text += event.delta;
2952
+ } else if (event.type === "response.reasoning_summary_part.done") {
2953
+ const slot = outputSlots.resolve(event, "thinking");
2954
+ if (!slot) continue;
2955
+ slot.item.summary = slot.item.summary || [];
2956
+ const lastPart = slot.item.summary[slot.item.summary.length - 1];
2957
+ if (!lastPart) continue;
2958
+ slot.block.thinking += "\n\n";
2959
+ lastPart.text += "\n\n";
2766
2960
  stream.push({
2767
- type: "text_delta",
2961
+ type: "thinking_delta",
2768
2962
  contentIndex: slot.contentIndex,
2769
- delta: event.delta
2963
+ delta: "\n\n",
2964
+ partial: output
2770
2965
  });
2771
- }
2772
- } else if (event.type === "response.refusal.delta") {
2773
- const slot = outputSlots.resolve(event, "text");
2774
- if (!slot) continue;
2775
- slot.item.content ||= [];
2776
- let lastPart = slot.item.content[slot.item.content.length - 1];
2777
- if (lastPart?.type !== "refusal") {
2778
- lastPart = {
2779
- type: "refusal",
2780
- refusal: ""
2781
- };
2782
- slot.item.content.push(lastPart);
2783
- }
2784
- lastPart.refusal += event.delta;
2785
- if (slot.pendingText !== null) appendPendingMessageDelta(slot, event.delta);
2786
- else if (slot.block && slot.contentIndex !== void 0) {
2787
- slot.block.text += event.delta;
2966
+ } else if (event.type === "response.reasoning_text.delta") {
2967
+ const slot = outputSlots.resolve(event, "thinking");
2968
+ if (!slot) continue;
2969
+ slot.block.thinking += event.delta;
2788
2970
  stream.push({
2789
- type: "text_delta",
2971
+ type: "thinking_delta",
2790
2972
  contentIndex: slot.contentIndex,
2791
- delta: event.delta
2792
- });
2793
- }
2794
- } else if (event.type === "response.function_call_arguments.delta") {
2795
- const toolCall = streamingToolCalls.resolve(event);
2796
- if (toolCall) {
2797
- toolCall.block.partialJson += event.delta;
2798
- toolCall.block.arguments = parseStreamingJson(toolCall.block.partialJson);
2799
- stream.push({
2800
- type: "toolcall_delta",
2801
- contentIndex: toolCall.contentIndex,
2802
2973
  delta: event.delta,
2803
2974
  partial: output
2804
2975
  });
2805
- } else if (streamingToolCalls.hasActive()) streamingToolCalls.markArgumentsUnreliable();
2806
- } else if (event.type === "response.function_call_arguments.done") {
2807
- const toolCall = streamingToolCalls.resolve(event);
2808
- if (toolCall) {
2809
- const previousPartialJson = toolCall.block.partialJson;
2810
- const doneArguments = typeof event.arguments === "string" ? event.arguments : void 0;
2811
- if (doneArguments !== void 0 && (doneArguments.length > 0 || previousPartialJson === "")) {
2812
- toolCall.block.partialJson = doneArguments;
2813
- toolCall.block.arguments = parseStreamingJson(toolCall.block.partialJson);
2814
- toolCall.argumentStreamReliable = true;
2976
+ } else if (event.type === "response.content_part.added") {
2977
+ const slot = outputSlots.resolve(event, "text");
2978
+ if (!slot) continue;
2979
+ slot.item.content = slot.item.content || [];
2980
+ if (event.part.type === "output_text" || event.part.type === "text" || event.part.type === "refusal") slot.item.content.push(event.part);
2981
+ } else if (event.type === "response.output_text.delta") {
2982
+ const slot = outputSlots.resolve(event, "text");
2983
+ if (!slot) continue;
2984
+ slot.item.content ||= [];
2985
+ let lastPart = slot.item.content[slot.item.content.length - 1];
2986
+ if (!isResponsesTextContentPartType(lastPart?.type)) {
2987
+ lastPart = {
2988
+ type: "output_text",
2989
+ text: "",
2990
+ annotations: []
2991
+ };
2992
+ slot.item.content.push(lastPart);
2993
+ }
2994
+ lastPart.text += event.delta;
2995
+ if (slot.pendingText !== null) appendResponsesPendingTextDelta(slot, event.delta, materializeDeferredTextSlot);
2996
+ else if (slot.block && slot.contentIndex !== void 0) {
2997
+ slot.block.text += event.delta;
2998
+ stream.push({
2999
+ type: "text_delta",
3000
+ contentIndex: slot.contentIndex,
3001
+ delta: event.delta
3002
+ });
3003
+ }
3004
+ } else if (isAzureResponsesTextDeltaEvent(event)) {
3005
+ const slot = outputSlots.resolve(event, "text");
3006
+ if (!slot) continue;
3007
+ slot.item.content = slot.item.content || [];
3008
+ let lastPart = slot.item.content[slot.item.content.length - 1];
3009
+ if (lastPart?.type !== "text") {
3010
+ lastPart = {
3011
+ type: "text",
3012
+ text: ""
3013
+ };
3014
+ slot.item.content.push(lastPart);
3015
+ }
3016
+ lastPart.text += event.delta;
3017
+ if (slot.pendingText !== null) appendResponsesPendingTextDelta(slot, event.delta, materializeDeferredTextSlot);
3018
+ else if (slot.block && slot.contentIndex !== void 0) {
3019
+ slot.block.text += event.delta;
3020
+ stream.push({
3021
+ type: "text_delta",
3022
+ contentIndex: slot.contentIndex,
3023
+ delta: event.delta
3024
+ });
3025
+ }
3026
+ } else if (event.type === "response.refusal.delta") {
3027
+ const slot = outputSlots.resolve(event, "text");
3028
+ if (!slot) continue;
3029
+ slot.item.content ||= [];
3030
+ let lastPart = slot.item.content[slot.item.content.length - 1];
3031
+ if (lastPart?.type !== "refusal") {
3032
+ lastPart = {
3033
+ type: "refusal",
3034
+ refusal: ""
3035
+ };
3036
+ slot.item.content.push(lastPart);
3037
+ }
3038
+ lastPart.refusal += event.delta;
3039
+ if (slot.pendingText !== null) appendResponsesPendingTextDelta(slot, event.delta, materializeDeferredTextSlot);
3040
+ else if (slot.block && slot.contentIndex !== void 0) {
3041
+ slot.block.text += event.delta;
3042
+ stream.push({
3043
+ type: "text_delta",
3044
+ contentIndex: slot.contentIndex,
3045
+ delta: event.delta
3046
+ });
2815
3047
  }
2816
- if (doneArguments?.startsWith(previousPartialJson)) {
2817
- const delta = doneArguments.slice(previousPartialJson.length);
2818
- if (delta.length > 0) stream.push({
3048
+ } else if (event.type === "response.function_call_arguments.delta") {
3049
+ const toolCall = streamingToolCalls.resolve(event);
3050
+ if (toolCall) {
3051
+ toolCall.block.partialJson += event.delta;
3052
+ toolCall.block.arguments = parseStreamingJson(toolCall.block.partialJson);
3053
+ stream.push({
2819
3054
  type: "toolcall_delta",
2820
3055
  contentIndex: toolCall.contentIndex,
2821
- delta,
3056
+ delta: event.delta,
2822
3057
  partial: output
2823
3058
  });
2824
- }
2825
- } else if (streamingToolCalls.hasActive()) streamingToolCalls.markArgumentsUnreliable();
2826
- } else if (event.type === "response.output_item.done") {
2827
- const item = event.item;
2828
- if (item.type !== "message") lastTextBlock = null;
2829
- const existingOutputSlot = resolveOutputItemSlot(event, item);
2830
- materializeDeferredTextSlots(existingOutputSlot);
2831
- const outputSlot = existingOutputSlot ?? getOrCreateOutputSlot(event, item);
2832
- if (item.type === "reasoning" && outputSlot?.type === "thinking") {
2833
- const summaryText = item.summary?.map((s) => s.text).join("\n\n") || "";
2834
- const contentText = item.content?.map((c) => c.text).join("\n\n") || "";
2835
- outputSlot.block.thinking = summaryText || contentText || outputSlot.block.thinking;
2836
- outputSlot.block.thinkingSignature = JSON.stringify(item);
2837
- if (item.encrypted_content && options?.reasoningReplayMetadata) outputSlot.block[OPENAI_RESPONSES_REASONING_REPLAY_BLOCK_META_KEY] = options.reasoningReplayMetadata;
2838
- if (typeof item.id === "string") reasoningBlocksById.set(item.id, outputSlot.block);
2839
- stream.push({
2840
- type: "thinking_end",
2841
- contentIndex: outputSlot.contentIndex,
2842
- content: outputSlot.block.thinking,
2843
- partial: output
2844
- });
2845
- outputSlots.forget(outputSlot);
2846
- } else if (item.type === "message" && outputSlot?.type === "text" && (outputSlot.block || outputSlot.pendingText !== null)) {
2847
- const streamedText = outputSlot.pendingText ?? outputSlot.block?.text ?? "";
2848
- const finalText = item.content == null ? streamedText : item.content.map((c) => c.type === "output_text" || c.type === "text" ? c.text : c.refusal).join("");
2849
- const phase = item.phase ?? void 0;
2850
- const collapse = outputSlot.pendingText !== null ? resolveResponsesMessageSnapshotCollapse({
2851
- prior: outputSlot.collapseCandidate && {
2852
- text: outputSlot.collapseCandidate.block.text,
2853
- phase: outputSlot.collapseCandidate.phase
2854
- },
2855
- nextText: finalText,
2856
- nextPhase: phase
2857
- }) : { kind: "keep" };
2858
- outputSlot.pendingText = null;
2859
- if (collapse.kind === "extend" && outputSlot.collapseCandidate) {
2860
- outputSlot.collapseCandidate.block.text = collapse.text;
2861
- outputSlot.collapseCandidate.block.textSignature = encodeTextSignatureV1(item.id, phase);
3059
+ } else if (streamingToolCalls.hasActive()) streamingToolCalls.markArgumentsUnreliable();
3060
+ } else if (event.type === "response.function_call_arguments.done") {
3061
+ const toolCall = streamingToolCalls.resolve(event);
3062
+ if (toolCall) {
3063
+ const previousPartialJson = toolCall.block.partialJson;
3064
+ const doneArguments = typeof event.arguments === "string" ? event.arguments : void 0;
3065
+ if (doneArguments !== void 0 && (doneArguments.length > 0 || previousPartialJson === "")) {
3066
+ toolCall.block.partialJson = doneArguments;
3067
+ toolCall.block.arguments = parseStreamingJson(toolCall.block.partialJson);
3068
+ toolCall.argumentStreamReliable = true;
3069
+ }
3070
+ if (doneArguments?.startsWith(previousPartialJson)) {
3071
+ const delta = doneArguments.slice(previousPartialJson.length);
3072
+ if (delta.length > 0) stream.push({
3073
+ type: "toolcall_delta",
3074
+ contentIndex: toolCall.contentIndex,
3075
+ delta,
3076
+ partial: output
3077
+ });
3078
+ }
3079
+ } else if (streamingToolCalls.hasActive()) streamingToolCalls.markArgumentsUnreliable();
3080
+ } else if (event.type === "response.output_item.done") {
3081
+ const item = event.item;
3082
+ if (item.type !== "message") lastTextBlock = null;
3083
+ const existingOutputSlot = resolveOutputItemSlot(event, item);
3084
+ materializeDeferredTextSlots(existingOutputSlot);
3085
+ const outputSlot = existingOutputSlot ?? getOrCreateOutputSlot(event, item);
3086
+ compactionTracker.completed(item, blocks.length);
3087
+ if (item.type === "reasoning" && outputSlot?.type === "thinking") {
3088
+ const summaryText = item.summary?.map((s) => s.text).join("\n\n") || "";
3089
+ const contentText = item.content?.map((c) => c.text).join("\n\n") || "";
3090
+ outputSlot.block.thinking = summaryText || contentText || outputSlot.block.thinking;
3091
+ outputSlot.block.thinkingSignature = JSON.stringify(item);
3092
+ if (item.encrypted_content && options?.reasoningReplayMetadata) outputSlot.block[OPENAI_RESPONSES_REASONING_REPLAY_BLOCK_META_KEY] = options.reasoningReplayMetadata;
2862
3093
  stream.push({
2863
- type: "text_end",
2864
- contentIndex: outputSlot.collapseCandidate.index,
2865
- content: collapse.text,
3094
+ type: "thinking_end",
3095
+ contentIndex: outputSlot.contentIndex,
3096
+ content: outputSlot.block.thinking,
2866
3097
  partial: output
2867
3098
  });
2868
- lastTextBlock = outputSlot.collapseCandidate;
2869
- } else {
2870
- if (!outputSlot.block) {
2871
- outputSlot.block = {
2872
- type: "text",
2873
- text: "",
2874
- ...phase ? { textSignature: encodeTextSignatureV1(item.id, phase) } : {}
3099
+ outputSlots.forget(outputSlot);
3100
+ } else if (item.type === "message" && outputSlot?.type === "text" && (outputSlot.block || outputSlot.pendingText !== null)) {
3101
+ const streamedText = outputSlot.pendingText ?? outputSlot.block?.text ?? "";
3102
+ const finalText = item.content == null ? streamedText : item.content.map((c) => c.type === "output_text" || c.type === "text" ? c.text : c.refusal).join("");
3103
+ const phase = item.phase ?? void 0;
3104
+ const collapse = outputSlot.pendingText !== null ? resolveResponsesMessageSnapshotCollapse({
3105
+ prior: outputSlot.collapseCandidate && {
3106
+ text: outputSlot.collapseCandidate.block.text,
3107
+ phase: outputSlot.collapseCandidate.phase
3108
+ },
3109
+ nextText: finalText,
3110
+ nextPhase: phase
3111
+ }) : { kind: "keep" };
3112
+ outputSlot.pendingText = null;
3113
+ if (collapse.kind === "extend" && outputSlot.collapseCandidate) {
3114
+ outputSlot.collapseCandidate.block.text = collapse.text;
3115
+ outputSlot.collapseCandidate.block.textSignature = encodeTextSignatureV1(item.id, phase);
3116
+ stream.push({
3117
+ type: "text_end",
3118
+ contentIndex: outputSlot.collapseCandidate.index,
3119
+ content: collapse.text,
3120
+ partial: output
3121
+ });
3122
+ lastTextBlock = outputSlot.collapseCandidate;
3123
+ outputItemContentIndexes.set(item, outputSlot.collapseCandidate.index);
3124
+ } else {
3125
+ if (!outputSlot.block) {
3126
+ outputSlot.block = {
3127
+ type: "text",
3128
+ text: "",
3129
+ ...phase ? { textSignature: encodeTextSignatureV1(item.id, phase) } : {}
3130
+ };
3131
+ blocks.push(outputSlot.block);
3132
+ outputSlot.contentIndex = blocks.length - 1;
3133
+ stream.push({
3134
+ type: "text_start",
3135
+ contentIndex: outputSlot.contentIndex,
3136
+ partial: output
3137
+ });
3138
+ }
3139
+ outputSlot.block.text = finalText;
3140
+ outputSlot.block.textSignature = encodeTextSignatureV1(item.id, phase);
3141
+ const contentIndex = outputSlot.contentIndex;
3142
+ if (contentIndex === void 0) throw new Error("Responses stream finalized text without a content index");
3143
+ lastTextBlock = {
3144
+ block: outputSlot.block,
3145
+ index: contentIndex,
3146
+ phase
2875
3147
  };
2876
- blocks.push(outputSlot.block);
2877
- outputSlot.contentIndex = blockIndex();
3148
+ outputItemContentIndexes.set(item, contentIndex);
2878
3149
  stream.push({
2879
- type: "text_start",
2880
- contentIndex: outputSlot.contentIndex,
3150
+ type: "text_end",
3151
+ contentIndex,
3152
+ content: outputSlot.block.text,
2881
3153
  partial: output
2882
3154
  });
2883
3155
  }
2884
- outputSlot.block.text = finalText;
2885
- outputSlot.block.textSignature = encodeTextSignatureV1(item.id, phase);
2886
- const contentIndex = outputSlot.contentIndex;
2887
- if (contentIndex === void 0) throw new Error("Responses stream finalized text without a content index");
2888
- lastTextBlock = {
2889
- block: outputSlot.block,
2890
- index: contentIndex,
2891
- phase
2892
- };
2893
- stream.push({
2894
- type: "text_end",
2895
- contentIndex,
2896
- content: outputSlot.block.text,
2897
- partial: output
3156
+ outputSlots.forget(outputSlot);
3157
+ startedTextBlocksByItemId.delete(item.id);
3158
+ } else if (item.type === "function_call") {
3159
+ const streamingToolCall = streamingToolCalls.resolve(event, readResponsesToolCallItemIdentity(item));
3160
+ if (!streamingToolCall && streamingToolCalls.hasActive()) continue;
3161
+ const streamedArguments = streamingToolCall?.block.partialJson ?? "";
3162
+ const completedArguments = typeof item.arguments === "string" ? item.arguments : void 0;
3163
+ if (streamingToolCall && !streamingToolCall.argumentStreamReliable && !completedArguments) continue;
3164
+ const finalArguments = completedArguments !== void 0 && (completedArguments.length > 0 || !streamedArguments) ? completedArguments : streamedArguments;
3165
+ const validated = resolveCompletedResponsesToolCall(item, {
3166
+ name: streamingToolCall?.block.name,
3167
+ arguments: finalArguments
2898
3168
  });
2899
- }
2900
- outputSlots.forget(outputSlot);
2901
- } else if (item.type === "function_call") {
2902
- const streamingToolCall = streamingToolCalls.resolve(event, readResponsesToolCallItemIdentity(item));
2903
- if (!streamingToolCall && streamingToolCalls.hasActive()) continue;
2904
- const completedName = resolveCompletedToolCallName(streamingToolCall, item.name);
2905
- const streamedArguments = streamingToolCall?.block.partialJson ?? "";
2906
- const completedArguments = typeof item.arguments === "string" ? item.arguments : void 0;
2907
- if (streamingToolCall && !streamingToolCall.argumentStreamReliable && !completedArguments) continue;
2908
- const args = parseStreamingJson(completedArguments !== void 0 && (completedArguments.length > 0 || !streamedArguments) ? completedArguments : streamedArguments || "{}");
2909
- let toolCall;
2910
- let contentIndex;
2911
- if (streamingToolCall) {
2912
- const block = streamingToolCall.block;
2913
- block.id = resolveResponsesToolCallId(item, block.id);
2914
- block.name = completedName;
2915
- block.arguments = args;
2916
- delete block.partialJson;
2917
- toolCall = block;
2918
- contentIndex = streamingToolCall.contentIndex;
2919
- } else {
2920
- toolCall = {
2921
- type: "toolCall",
2922
- id: resolveResponsesToolCallId(item),
2923
- name: completedName,
2924
- arguments: args
2925
- };
2926
- blocks.push(toolCall);
2927
- contentIndex = blockIndex();
3169
+ let toolCall;
3170
+ let contentIndex;
3171
+ if (streamingToolCall) {
3172
+ const block = streamingToolCall.block;
3173
+ block.id = resolveResponsesToolCallId(item, block.id);
3174
+ block.name = validated.name;
3175
+ block.arguments = validated.arguments;
3176
+ delete block.partialJson;
3177
+ toolCall = block;
3178
+ contentIndex = streamingToolCall.contentIndex;
3179
+ } else {
3180
+ toolCall = {
3181
+ type: "toolCall",
3182
+ id: resolveResponsesToolCallId(item),
3183
+ name: validated.name,
3184
+ arguments: validated.arguments
3185
+ };
3186
+ blocks.push(toolCall);
3187
+ contentIndex = blocks.length - 1;
3188
+ stream.push({
3189
+ type: "toolcall_start",
3190
+ contentIndex,
3191
+ partial: output
3192
+ });
3193
+ }
3194
+ if (streamingToolCall) {
3195
+ streamingToolCalls.forget(streamingToolCall);
3196
+ for (const slot of outputSlots.values()) if (slot.type === "toolCall" && slot.toolCall === streamingToolCall) outputSlots.forget(slot);
3197
+ }
2928
3198
  stream.push({
2929
- type: "toolcall_start",
3199
+ type: "toolcall_end",
2930
3200
  contentIndex,
3201
+ toolCall,
2931
3202
  partial: output
2932
3203
  });
3204
+ outputItemContentIndexes.set(item, contentIndex);
2933
3205
  }
2934
- if (streamingToolCall) {
2935
- streamingToolCalls.forget(streamingToolCall);
2936
- for (const slot of outputSlots.values()) if (slot.type === "toolCall" && slot.toolCall === streamingToolCall) outputSlots.forget(slot);
2937
- }
2938
- stream.push({
2939
- type: "toolcall_end",
2940
- contentIndex,
2941
- toolCall,
2942
- partial: output
2943
- });
3206
+ } else if (event.type === "response.completed" || event.type === "response.incomplete") {
3207
+ if (streamingToolCalls.hasActive()) throw new Error("Responses stream completed with unresolved tool calls");
3208
+ finalizeResponse(event.response, event.type);
3209
+ if (event.type === "response.completed" || output.stopReason === "length") recoverTerminalOutput(event.response.output ?? [], event.type === "response.completed");
3210
+ terminalResponse = event.type === "response.completed" ? event.response : null;
3211
+ if (output.stopReason === "stop" && output.content.some((block) => block.type === "toolCall")) output.stopReason = "toolUse";
3212
+ break;
3213
+ } else if (event.type === "error") throw new Error(event.message ? `Error Code ${event.code}: ${event.message}` : "Unknown error");
3214
+ else if (event.type === "response.failed") {
3215
+ const failure = normalizeResponsesFailedEvent(event, model);
3216
+ finalizeFailedResponse(event.response, failure.responseId);
3217
+ throw new ResponsesStreamFailure(failure, event.response);
2944
3218
  }
2945
- } else if (event.type === "response.completed" || event.type === "response.incomplete") {
2946
- if (streamingToolCalls.hasActive()) throw new Error("Responses stream completed with unresolved tool calls");
2947
- finalizeResponse(event.response, event.type);
2948
- if (event.type === "response.completed" || output.stopReason === "length") recoverTerminalOutput(event.response.output ?? [], event.type === "response.completed");
2949
- if (output.stopReason === "stop" && output.content.some((block) => block.type === "toolCall")) output.stopReason = "toolUse";
2950
- break;
2951
- } else if (event.type === "error") throw new Error(event.message ? `Error Code ${event.code}: ${event.message}` : "Unknown error");
2952
- else if (event.type === "response.failed") {
2953
- const failure = normalizeResponsesFailedEvent(event, model);
2954
- if (failure.responseId) output.responseId = failure.responseId;
2955
- throw new ResponsesStreamFailure(failure, event.response);
2956
3219
  }
3220
+ if (options?.signal?.aborted) throw transportAbortError(options.signal);
2957
3221
  if (streamingToolCalls.hasActive()) throw new Error("Responses stream ended with unresolved tool calls");
2958
- if (!terminalResponseEvent) throw new Error("OpenAI Responses stream ended before a terminal response event");
3222
+ if (terminalResponse === void 0) throw new Error("OpenAI Responses stream ended before a terminal response event");
3223
+ return terminalResponse ?? void 0;
2959
3224
  } finally {
2960
3225
  for (const block of output.content) delete block.partialJson;
2961
3226
  }
2962
3227
  }
2963
3228
  //#endregion
2964
- export { normalizeOpenAIStrictCompatSchema as $, normalizeResponsesFailedEvent as A, resolveReplayableResponsesMessageId as B, prepareOpenAIResponsesReasoningItemForReplay as C, applyServiceTierPricing as D, tagOpenAIResponsesReasoningReplayItem as E, summarizeResponsesFailedNoDetailsObservation as F, throwIfModelStreamAborted as G, createModelStreamCooperativeScheduler as H, summarizeResponsesPayload as I, isStrictOpenAIJsonSchemaCompatible as J, clearOpenAIToolSchemaCacheForTest as K, summarizeResponsesTools as L, stringifyRedactedEvent as M, stringifyRedactedPayload as N, buildResponsesFailedNoDetailsObservation as O, summarizeOpenAITransportError as P, findOpenAIStrictSchemaViolations as Q, AZURE_RESPONSES_FIRST_EVENT_TIMEOUT_MS as R, isInvalidEncryptedContentError as S, stripResponsesRequestEncryptedContent as T, log as U, GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP as V, resolvePromptCacheKey as W, normalizeStrictOpenAIJsonSchema as X, normalizeOpenAIStrictToolParameters as Y, resolveOpenAIProjectedToolsStrictToolFlag as Z, resolveResponsesMessageSnapshotCollapse as _, supportsOpenAITemperature as _t, resolveResponsesTerminalStopReason as a, LLAMACPP_GBNF_MAX_REPETITION_THRESHOLD as at, convertResponsesMessages as b, resolveModelPayloadDebugMode as bt, readResponsesToolCallItemIdentity as c, GEMINI_UNSUPPORTED_SCHEMA_KEYWORDS as ct, OPENAI_RESPONSES_OUTPUT_TEXT_CONTENT_PART_TYPE as d, isOpenAIGpt55Model as dt, extractToolSchemaModelCompat as et, OPENAI_RESPONSES_OUTPUT_TEXT_DELTA_EVENT_TYPE as f, isOpenAIGpt56Model as ft, isResponsesTextDeltaEventType as g, supportsOpenAIReasoningEffort as gt, isResponsesTextContentPartType as h, resolveOpenAISupportedReasoningEfforts as ht, readResponsesReasoningTokens as i, stripUnsupportedSchemaKeywords as it, safeDebugValue as j, logResponsesFailedNoDetails as k, AZURE_RESPONSES_TEXT_CONTENT_PART_TYPE as l, cleanSchemaForGemini as lt, isAzureResponsesTextDeltaEventType as m, resolveOpenAIReasoningEffortForModel as mt, processResponsesStream as n, resolveUnsupportedToolSchemaKeywords as nt, observeResponsesStream as o, cleanSchemaForLlamacppGbnf as ot, isAzureResponsesTextDeltaEvent as p, normalizeOpenAIReasoningEffort as pt, findOpenAIStrictToolProjectionDiagnostics as q, mapResponsesTerminalUsage as r, shouldOmitEmptyArrayItems as rt, createResponsesToolCallTracker as s, findLlamacppGbnfSchemaViolations as st, ResponsesStreamFailure as t, normalizeToolParameterSchema as tt, AZURE_RESPONSES_TEXT_DELTA_EVENT_TYPE as u, isOpenAIGpt54MiniModel as ut, buildOpenAIResponsesReasoningReplayMetadata as v, uniqueStrings as vt, resolveAzureOpenAIApiVersion as w, createResponsesStreamWithEncryptedContentRetry as x, resolveModelSseDebugMode as xt, buildResponsesInputMessage as y, emitModelTransportDebug as yt, OPENAI_CODEX_RESPONSES_DEFAULT_INSTRUCTIONS as z };
3229
+ //#region packages/ai/src/providers/openai-responses-tools.ts
3230
+ const LOG_SUBSYSTEM = "llm/openai-responses";
3231
+ const MAX_STRICT_TOOL_DOWNGRADE_DIAGNOSTIC_KEYS = 64;
3232
+ const loggedStrictToolDowngradeDiagnosticKeys = /* @__PURE__ */ new Set();
3233
+ /** Converts and returns the projection used to reconcile tool choices. */
3234
+ function convertResponsesToolPayload(tools, options) {
3235
+ const projection = projectOpenAITools(tools);
3236
+ const strict = resolveResponsesStrictToolFlag(projection, resolveResponsesStrictToolSetting(options), options?.model);
3237
+ return {
3238
+ projection,
3239
+ tools: sortPromptCacheToolsByName(projection.tools).map((tool) => {
3240
+ const result = {
3241
+ type: "function",
3242
+ name: tool.name,
3243
+ description: tool.description,
3244
+ parameters: normalizeOpenAIStrictToolParameters(tool.parameters, strict === true, options?.model?.compat)
3245
+ };
3246
+ if (strict !== void 0) result.strict = strict;
3247
+ return result;
3248
+ })
3249
+ };
3250
+ }
3251
+ function resolveResponsesStrictToolSetting(options) {
3252
+ if (options?.strict !== void 0) return options.strict;
3253
+ if (options?.model) return getAiTransportHost().resolveOpenAIStrictToolSetting(options.model, {
3254
+ transport: "stream",
3255
+ supportsStrictMode: options.supportsStrictMode
3256
+ });
3257
+ return false;
3258
+ }
3259
+ function resolveResponsesStrictToolFlag(projection, strictSetting, model) {
3260
+ const strict = resolveOpenAIProjectedToolsStrictToolFlag(projection, strictSetting);
3261
+ if (strictSetting === true && strict === false && model) getAiTransportHost().logDebug(LOG_SUBSYSTEM, () => {
3262
+ const diagnostics = findOpenAIStrictToolProjectionDiagnostics(projection);
3263
+ if (!shouldLogStrictToolDowngradeDiagnostic(diagnostics, model)) return null;
3264
+ const sample = diagnostics.slice(0, 5).map((entry) => ({
3265
+ tool: entry.toolName ?? `tool[${entry.toolIndex}]`,
3266
+ violations: entry.violations.slice(0, 8)
3267
+ }));
3268
+ return {
3269
+ 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`,
3270
+ data: {
3271
+ provider: model.provider,
3272
+ model: model.id,
3273
+ incompatibleToolCount: diagnostics.length,
3274
+ sample
3275
+ }
3276
+ };
3277
+ });
3278
+ return strict;
3279
+ }
3280
+ function shouldLogStrictToolDowngradeDiagnostic(diagnostics, model) {
3281
+ const key = createHash("sha256").update(JSON.stringify({
3282
+ provider: model.provider,
3283
+ model: model.id,
3284
+ diagnostics: diagnostics.map((entry) => ({
3285
+ toolIndex: entry.toolIndex,
3286
+ toolName: entry.toolName ?? null,
3287
+ violations: entry.violations
3288
+ }))
3289
+ })).digest("hex");
3290
+ if (loggedStrictToolDowngradeDiagnosticKeys.has(key)) return false;
3291
+ if (loggedStrictToolDowngradeDiagnosticKeys.size >= MAX_STRICT_TOOL_DOWNGRADE_DIAGNOSTIC_KEYS) loggedStrictToolDowngradeDiagnosticKeys.clear();
3292
+ loggedStrictToolDowngradeDiagnosticKeys.add(key);
3293
+ return true;
3294
+ }
3295
+ //#endregion
3296
+ //#region packages/ai/src/providers/openai-responses-shared.ts
3297
+ function isResponsesReasoningEffort(effort) {
3298
+ return effort === "minimal" || effort === "low" || effort === "medium" || effort === "high" || effort === "xhigh" || effort === "max";
3299
+ }
3300
+ function convertResponsesMessages(model, context, allowedToolCallProviders, options) {
3301
+ return convertProviderResponsesMessages(model, context, allowedToolCallProviders, options);
3302
+ }
3303
+ const createResponsesAssistantOutput = createOpenAIResponsesAssistantOutput;
3304
+ function applyResponsesServiceTierPricing(usage, serviceTier, model) {
3305
+ let multiplier = 1;
3306
+ if (serviceTier === "flex") multiplier = .5;
3307
+ else if (serviceTier === "priority") multiplier = model.id === "gpt-5.5" ? 2.5 : 2;
3308
+ if (multiplier === 1) return;
3309
+ usage.cost.input *= multiplier;
3310
+ usage.cost.output *= multiplier;
3311
+ usage.cost.cacheRead *= multiplier;
3312
+ usage.cost.cacheWrite *= multiplier;
3313
+ usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
3314
+ }
3315
+ function resolveResponsesReasoningEffort(model, reasoning) {
3316
+ const clampedReasoning = reasoning ? clampThinkingLevel(model, reasoning) : void 0;
3317
+ if (!clampedReasoning || clampedReasoning === "off") return;
3318
+ if (clampedReasoning === "max") return supportsOpenAIReasoningEffort(model, "max") ? "max" : "xhigh";
3319
+ if (clampedReasoning === "minimal" && model.provider === "openai" && supportsOpenAIReasoningEffort(model, "max")) {
3320
+ const effort = resolveOpenAIReasoningEffortForModel({
3321
+ model,
3322
+ effort: "minimal"
3323
+ });
3324
+ return isResponsesReasoningEffort(effort) ? effort : void 0;
3325
+ }
3326
+ return clampedReasoning;
3327
+ }
3328
+ function applyCommonResponsesParams(params, model, context, options, config) {
3329
+ if (options?.maxTokens) params.max_output_tokens = Math.max(options.maxTokens, 16);
3330
+ if (options?.temperature !== void 0 && supportsOpenAITemperature(model)) params.temperature = options.temperature;
3331
+ if (context.tools) {
3332
+ const converted = convertResponsesToolPayload(context.tools, { model });
3333
+ if (converted.tools.length > 0) params.tools = converted.tools;
3334
+ }
3335
+ if (!model.reasoning) return;
3336
+ if (options?.reasoningEffort || options?.reasoningSummary) {
3337
+ params.reasoning = {
3338
+ effort: options?.reasoningEffort ? model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort : "medium",
3339
+ summary: options?.reasoningSummary || "auto"
3340
+ };
3341
+ params.include = ["reasoning.encrypted_content"];
3342
+ } else if ((config?.setDefaultReasoningOff ?? true) && model.thinkingLevelMap?.off !== null) params.reasoning = { effort: model.thinkingLevelMap?.off ?? "none" };
3343
+ }
3344
+ function buildResponsesRequestOptions(options) {
3345
+ return {
3346
+ ...options?.signal ? { signal: options.signal } : {},
3347
+ ...options?.timeoutMs !== void 0 ? { timeout: options.timeoutMs } : {},
3348
+ maxRetries: options?.maxRetries ?? 0
3349
+ };
3350
+ }
3351
+ function cleanStreamingScratchBuffers(output) {
3352
+ for (const block of output.content) {
3353
+ delete block.index;
3354
+ delete block.partialJson;
3355
+ }
3356
+ }
3357
+ async function runResponsesStreamLifecycle(params) {
3358
+ const { stream, output, options } = params;
3359
+ let firstEventAbort;
3360
+ try {
3361
+ const model = params.resolveRequestModel?.(params.model) ?? params.model;
3362
+ const client = params.createClient(model);
3363
+ const buildRequest = async (replayMode) => {
3364
+ let request = params.buildParams(model, replayMode);
3365
+ const nextRequest = await options?.onPayload?.(request, model);
3366
+ if (nextRequest !== void 0) request = nextRequest;
3367
+ return request;
3368
+ };
3369
+ const requestParams = await buildRequest("checkpoint");
3370
+ firstEventAbort = createFirstStreamEventAbortController(options?.signal);
3371
+ const { stream: openaiStream, response } = await createResponsesStreamWithEncryptedContentRetry({
3372
+ client,
3373
+ request: requestParams,
3374
+ requestOptions: {
3375
+ ...buildResponsesRequestOptions(options),
3376
+ signal: firstEventAbort.signal
3377
+ },
3378
+ model,
3379
+ buildFullHistoryRequest: () => buildRequest("full-history"),
3380
+ onCompactionRejected: (checkpoint) => suppressOpenAIResponsesCompaction(output, model, options, checkpoint)
3381
+ });
3382
+ const hookedOpenAIStream = withProviderResponseHook({
3383
+ stream: openaiStream,
3384
+ signal: firstEventAbort.signal,
3385
+ abort: firstEventAbort.abort,
3386
+ hook: createOpenAIResponseHook(options?.onResponse, response, model),
3387
+ onReady: () => stream.push({
3388
+ type: "start",
3389
+ partial: output
3390
+ })
3391
+ });
3392
+ const firstEventTimeoutMs = getFirstStreamEventTimeoutMs(options);
3393
+ const onFirstEventTimeout = getFirstStreamEventTimeoutHandler(options);
3394
+ await processResponsesStream(hookedOpenAIStream, output, stream, model, {
3395
+ ...params.processStreamOptions || firstEventTimeoutMs !== void 0 || onFirstEventTimeout !== void 0 ? {
3396
+ ...params.processStreamOptions,
3397
+ firstEventTimeoutMs: params.processStreamOptions?.firstEventTimeoutMs ?? firstEventTimeoutMs,
3398
+ abortFirstEventStream: params.processStreamOptions?.abortFirstEventStream ?? firstEventAbort.abort,
3399
+ onFirstEventTimeout: params.processStreamOptions?.onFirstEventTimeout ?? onFirstEventTimeout,
3400
+ signal: params.processStreamOptions?.signal ?? options?.signal
3401
+ } : void 0,
3402
+ reasoningReplayMetadata: buildOpenAIResponsesReasoningReplayMetadata(model, {
3403
+ sessionId: options?.sessionId,
3404
+ authProfileId: options?.authProfileId
3405
+ })
3406
+ });
3407
+ if (options?.signal?.aborted) throw transportAbortError(options.signal);
3408
+ if (output.stopReason === "aborted" || output.stopReason === "error") throw new Error(output.errorMessage ?? "An unknown error occurred");
3409
+ stream.push({
3410
+ type: "done",
3411
+ reason: output.stopReason,
3412
+ message: output
3413
+ });
3414
+ stream.end();
3415
+ } catch (error) {
3416
+ cleanStreamingScratchBuffers(output);
3417
+ const terminal = projectProviderError(error, options?.signal);
3418
+ Object.assign(output, terminal);
3419
+ stream.push({
3420
+ type: "error",
3421
+ reason: terminal.stopReason,
3422
+ error: output
3423
+ });
3424
+ stream.end();
3425
+ } finally {
3426
+ firstEventAbort?.dispose();
3427
+ }
3428
+ }
3429
+ //#endregion
3430
+ 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, quoteUnsafeIntegerLiterals as ht, 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, parseJsonPreservingUnsafeIntegers as mt, applyResponsesServiceTierPricing as n, resolveUnsupportedToolSchemaKeywords as nt, runResponsesStreamLifecycle as o, cleanSchemaForLlamacppGbnf as ot, ResponsesStreamFailure as p, parseJsonObjectPreservingUnsafeIntegers as pt, 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 };