@openclaw/ai 2026.9.2 → 2026.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/README.md +3 -2
  2. package/dist/anthropic-CZy5U0NY.mjs +376 -0
  3. package/dist/{anthropic-payload-policy-d46X2pR0.d.mts → anthropic-payload-policy-wuRCb6MH.d.mts} +16 -6
  4. package/dist/{anthropic-compaction-replay-DB2FGLQc.mjs → anthropic-stream-reducer-B_yo_7pf.mjs} +923 -181
  5. package/dist/{api-registry-DWtPjzyn.d.mts → api-registry-CB1-1oQ2.d.mts} +2 -2
  6. package/dist/assistant-output-iqnlJCV2.mjs +16 -0
  7. package/dist/assistant-text-phase-C20rxWwP.mjs +55 -0
  8. package/dist/{azure-openai-responses-C5bZRfAP.mjs → azure-openai-responses-Crpa40QR.mjs} +5 -5
  9. package/dist/{base64-CEFBpSkN.mjs → base64-D-su8YVo.mjs} +1 -27
  10. package/dist/{diagnostics-DfFyKeX_.mjs → diagnostics-dV98PqIy.mjs} +96 -21
  11. package/dist/diagnostics.d.mts +3 -1
  12. package/dist/diagnostics.mjs +3 -3
  13. package/dist/{event-stream-BhT5T1Ay.d.mts → event-stream-C1Z2piyk.d.mts} +11 -3
  14. package/dist/{event-stream-BgDvQeum.mjs → event-stream-D8PARQfL.mjs} +45 -1
  15. package/dist/event-stream-I_GlBsuZ.d.mts +1 -0
  16. package/dist/event-stream.d.mts +2 -2
  17. package/dist/event-stream.mjs +1 -1
  18. package/dist/{github-copilot-headers-NCJtz9i0.mjs → github-copilot-headers-B37TB3rB.mjs} +3 -10
  19. package/dist/github-copilot-request-facts-BTEBMeOv.mjs +16 -0
  20. package/dist/{google-4qeuE8iX.mjs → google-BDPriaVe.mjs} +10 -10
  21. package/dist/google-messages-CVn9eFpF.mjs +449 -0
  22. package/dist/google-shared-BedY23XS.mjs +185 -0
  23. package/dist/{google-vertex-O9BcnB6X.mjs → google-vertex-DMz8XQCn.mjs} +7 -6
  24. package/dist/{host-CEvLw30U.mjs → host-CWuF-sS3.mjs} +44 -39
  25. package/dist/{host-DjzGmdZ2.d.mts → host-DK3wmS3e.d.mts} +3 -3
  26. package/dist/host-policy-CAopLRKA.mjs +37 -0
  27. package/dist/{index-FnHM2FcI.d.mts → index-CQ6LTHw8.d.mts} +3 -3
  28. package/dist/index.d.mts +6 -6
  29. package/dist/index.mjs +4 -4
  30. package/dist/internal/anthropic.d.mts +7 -7
  31. package/dist/internal/anthropic.mjs +4 -4
  32. package/dist/internal/google-model-family.d.mts +5 -0
  33. package/dist/internal/google-model-family.mjs +15 -0
  34. package/dist/internal/openai-responses-payload-policy.d.mts +1 -1
  35. package/dist/internal/openai-responses-payload-policy.mjs +1 -1
  36. package/dist/internal/openai.d.mts +8 -103
  37. package/dist/internal/openai.mjs +10 -10
  38. package/dist/internal/retry-after.d.mts +2 -4
  39. package/dist/internal/retry-after.mjs +57 -8
  40. package/dist/internal/runtime.d.mts +7 -6
  41. package/dist/internal/runtime.mjs +8 -7
  42. package/dist/internal/shared.d.mts +14 -3
  43. package/dist/internal/shared.mjs +6 -4
  44. package/dist/internal/tool-schema.d.mts +63 -0
  45. package/dist/internal/tool-schema.mjs +3 -0
  46. package/dist/{json-parse-BuAJEbdW.mjs → json-parse-Dw_hnxsA.mjs} +1 -1
  47. package/dist/{mistral-Tb6oalqH.mjs → mistral--m-Jm6VZ.mjs} +13 -37
  48. package/dist/model-transport-url-DKocrEsb.d.mts +28 -0
  49. package/dist/{openai-chatgpt-responses-yUXjPNfu.mjs → openai-chatgpt-responses-nDZccFW-.mjs} +48 -38
  50. package/dist/openai-completions-KuoZyx0d.mjs +187 -0
  51. package/dist/{openai-completions-compat-CpjYUArk.d.mts → openai-completions-compat-CXn3T1we.d.mts} +26 -4
  52. package/dist/{openai-completions-stream-BsrBe3Gg.mjs → openai-completions-stream-BQk3SkLD.mjs} +622 -452
  53. package/dist/openai-prompt-cache-BI0rkM-5.mjs +220 -0
  54. package/dist/openai-prompt-cache-rrutvqxq.d.mts +16 -0
  55. package/dist/openai-provider-client-ha_WxTyj.mjs +24 -0
  56. package/dist/openai-reasoning-effort-BK7FbcLT.mjs +167 -0
  57. package/dist/{openai-responses-CCL41ALM.mjs → openai-responses-D99dOzKI.mjs} +14 -29
  58. package/dist/{openai-responses-compaction-window-BMVHFOtq.mjs → openai-responses-compaction-window-D5jbzCi3.mjs} +7 -170
  59. package/dist/{openai-responses-contracts-rF5DDRNS.d.mts → openai-responses-contracts-B55afwRo.d.mts} +3 -3
  60. package/dist/{openai-responses-prompt-observer-internal-D0bhBfgL.mjs → openai-responses-prompt-observer-internal-tApyTLVu.mjs} +3 -3
  61. package/dist/{openai-responses-shared-Bmma_3Qc.mjs → openai-responses-shared-ZyQEzS5i.mjs} +44 -115
  62. package/dist/openai-tool-projection-793cE3QX.d.mts +37 -0
  63. package/dist/{openai-tool-schema-_pTAJqKF.mjs → openai-tool-schema-CzjyYXun.mjs} +38 -556
  64. package/dist/openai-tool-schema-ynZBgqW-.d.mts +38 -0
  65. package/dist/openai-transport-params-DNasp2fU.mjs +674 -0
  66. package/dist/{provider-error-9TraxGvt.mjs → provider-error-C6TbKiey.mjs} +23 -6
  67. package/dist/{provider-options-Bcc_p-TU.d.mts → provider-options-BXr9Ec83.d.mts} +4 -39
  68. package/dist/{provider-transcript-transform-BaMbI1hr.mjs → provider-transcript-transform-pPmUIwKt.mjs} +1 -1
  69. package/dist/provider-types-CAV0Og3m.d.mts +29 -0
  70. package/dist/provider-types.d.mts +6 -31
  71. package/dist/providers.d.mts +2 -2
  72. package/dist/providers.mjs +11 -11
  73. package/dist/{reasoning-tag-text-partitioner-DLCNXki6.mjs → reasoning-tag-text-partitioner-BQBi4B9d.mjs} +19 -12
  74. package/dist/record-coerce-DwRYMj3t.mjs +32 -0
  75. package/dist/retry-after-CdCURCVg.d.mts +15 -0
  76. package/dist/{sanitize-unicode-D6xUvZaS.mjs → sanitize-unicode-Bb-v9meu.mjs} +1 -1
  77. package/dist/session-affinity-CCH7eYdB.mjs +20 -0
  78. package/dist/{simple-options-BjHCCh4v.mjs → simple-options-tcKOqnpF.mjs} +3 -3
  79. package/dist/{src-2qBGKg8O.mjs → src-B2Q_6G8V.mjs} +1 -1
  80. package/dist/{stream-first-event-timeout-DcNjoFQE.mjs → stream-first-event-timeout-2hfrquuz.mjs} +1 -1
  81. package/dist/string-coerce-fsri9iCu.mjs +34 -0
  82. package/dist/{string-normalization--fwJ4S2q.mjs → string-normalization-CmLIasuf.mjs} +1 -1
  83. package/dist/{tool-schema-json-projection-mJhXDcyz.mjs → tool-schema-json-projection-ClptDdAO.mjs} +2 -38
  84. package/dist/{transport-stream-shared-CZqMhfIw.mjs → transport-stream-shared-Cu3ZPhNW.mjs} +5 -5
  85. package/dist/{transport-stream-shared-xnaqxmbP.d.mts → transport-stream-shared-DOxpGJ-H.d.mts} +4 -4
  86. package/dist/transport-utils-CCooe-cr.mjs +121 -0
  87. package/dist/transports.d.mts +113 -41
  88. package/dist/transports.mjs +162 -1276
  89. package/dist/types-BADKjDBI.d.mts +1 -0
  90. package/dist/{types-CJ1-Ht7A.d.mts → types-Dy1q0CSu.d.mts} +72 -57
  91. package/dist/types.d.mts +5 -5
  92. package/dist/types.mjs +3 -3
  93. package/dist/utf16-slice-CvGodqok.mjs +29 -0
  94. package/dist/{validation-CJZtym2g.mjs → validation-BDzVDnTs.mjs} +9 -1
  95. package/dist/{validation-AKZBDGQd.d.mts → validation-CaFUZN9B.d.mts} +1 -1
  96. package/dist/validation.d.mts +1 -1
  97. package/dist/validation.mjs +1 -1
  98. package/package.json +13 -3
  99. package/dist/anthropic-BDdqdVLK.mjs +0 -886
  100. package/dist/event-stream-zctLx0yr.d.mts +0 -1
  101. package/dist/google-shared-CWeG8RIl.mjs +0 -636
  102. package/dist/google-thinking-level-C-V3tecN.mjs +0 -9
  103. package/dist/openai-completions-BIUV3RDT.mjs +0 -403
  104. package/dist/openai-prompt-cache-CGnVB74a.mjs +0 -21
  105. package/dist/openai-prompt-cache-CNoIfHYC.d.mts +0 -16
  106. package/dist/transport-utils-7il795_9.mjs +0 -138
  107. package/dist/types-3Lnm-QSJ.d.mts +0 -1
  108. package/dist/utf16-slice-qz3nsy87.mjs +0 -84
@@ -0,0 +1,674 @@
1
+ import { a as normalizeOptionalString, n as normalizeLowercaseStringOrEmpty } from "./string-coerce-fsri9iCu.mjs";
2
+ import { n as applyProviderReportedUsageCost, r as calculateCost } from "./sanitize-unicode-Bb-v9meu.mjs";
3
+ import { n as getAiTransportHost } from "./host-CWuF-sS3.mjs";
4
+ import { o as isRecord, r as asOptionalObjectRecord } from "./record-coerce-DwRYMj3t.mjs";
5
+ import { l as usesNativeOpenAICodexResponsesBackend, n as clampOpenAIPromptCacheKey, s as resolveOpenAICompletionsCompat } from "./openai-prompt-cache-BI0rkM-5.mjs";
6
+ import { i as isCodeModeModelVisibleToolName } from "./transport-utils-CCooe-cr.mjs";
7
+ import { n as resolveModelRequestTimeoutMs, o as resolveProviderRequestPolicyConfig } from "./host-policy-CAopLRKA.mjs";
8
+ import { t as projectRuntimeToolInputSchema } from "./tool-schema-json-projection-ClptDdAO.mjs";
9
+ import { C as headersToRecord, _ as transportAbortError, f as notifyProviderHttpResponse } from "./transport-stream-shared-Cu3ZPhNW.mjs";
10
+ import { t as resolveOpencodeSessionHeaders } from "./session-affinity-CCH7eYdB.mjs";
11
+ import { a as resolveOpenAIProjectedToolsStrictToolFlag, t as findOpenAIStrictToolProjectionDiagnostics } from "./openai-tool-schema-CzjyYXun.mjs";
12
+ import { createHash } from "node:crypto";
13
+ //#region packages/normalization-core/src/node-crypto.ts
14
+ function sha256Hex(input) {
15
+ return createHash("sha256").update(input).digest("hex");
16
+ }
17
+ function sha256HexPrefixCore(input, length) {
18
+ return sha256Hex(input).slice(0, length);
19
+ }
20
+ /** Redacts an identifier to a stable hash label, or "-" for missing values. */
21
+ function redactIdentifier(value, opts) {
22
+ const trimmed = normalizeOptionalString(value);
23
+ if (!trimmed) return "-";
24
+ const len = opts?.len ?? 12;
25
+ return `sha256:${sha256HexPrefixCore(trimmed, Number.isFinite(len) ? Math.max(1, Math.floor(len)) : 12)}`;
26
+ }
27
+ //#endregion
28
+ //#region packages/ai/src/transports/openai-transport-shared.ts
29
+ /** Shared options, usage shape, cache identity, ordering, and stream scheduling for OpenAI APIs. */
30
+ const MODEL_STREAM_COOPERATIVE_YIELD_INTERVAL_MS = 12;
31
+ const MODEL_STREAM_COOPERATIVE_YIELD_MAX_EVENTS = 64;
32
+ const GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP = "skip_thought_signature_validator";
33
+ const log = {
34
+ debug(message, data) {
35
+ getAiTransportHost().logDebug("openai-transport", () => ({
36
+ message,
37
+ data
38
+ }));
39
+ },
40
+ info(message, data) {
41
+ getAiTransportHost().logInfo("openai-transport", message, data);
42
+ },
43
+ warn(message, data) {
44
+ getAiTransportHost().logWarn("openai-transport", message, data);
45
+ }
46
+ };
47
+ function resolveOpenAIClientBaseUrl(model, baseUrl = model.baseUrl) {
48
+ if (baseUrl?.trim()) return baseUrl;
49
+ if (model.provider.trim().toLowerCase() === "openai") return;
50
+ throw new Error(`Provider "${model.provider}" requires an explicit base URL before using an OpenAI-compatible API. Reload provider metadata or configure an endpoint.`);
51
+ }
52
+ const EMPTY_OPENAI_COMPLETIONS_REASONING_BATCH = {
53
+ deltas: [],
54
+ mirroredThinking: [],
55
+ hasThinking: false,
56
+ hasVisibleText: false
57
+ };
58
+ const OPENAI_COMPLETIONS_REASONING_FIELDS = [
59
+ "reasoning_content",
60
+ "reasoning",
61
+ "reasoning_text"
62
+ ];
63
+ function appendOpenAICompletionsReasoningDelta(batch, next) {
64
+ if (next.kind === "thinking") batch.hasThinking = true;
65
+ else batch.hasVisibleText = true;
66
+ const previous = batch.deltas[batch.deltas.length - 1];
67
+ if (!previous || previous.kind !== next.kind) {
68
+ batch.deltas.push(next);
69
+ if (next.kind === "thinking") batch.mirroredThinking.push(next.text);
70
+ return;
71
+ }
72
+ if (next.kind === "thinking" && previous.kind === "thinking") {
73
+ if (previous.signature !== next.signature) {
74
+ batch.deltas.push(next);
75
+ batch.mirroredThinking.push(next.text);
76
+ return;
77
+ }
78
+ previous.text += next.text;
79
+ batch.mirroredThinking[batch.mirroredThinking.length - 1] += next.text;
80
+ return;
81
+ }
82
+ previous.text += next.text;
83
+ }
84
+ function createOpenAICompletionsReasoningBatch() {
85
+ return {
86
+ deltas: [],
87
+ mirroredThinking: [],
88
+ hasThinking: false,
89
+ hasVisibleText: false
90
+ };
91
+ }
92
+ function readOpenAICompletionsReasoningBatch(delta, visibleReasoningDetailTypes) {
93
+ let batch;
94
+ const reasoningDetails = delta.reasoning_details;
95
+ let usedReasoningThinkingDetails = false;
96
+ if (Array.isArray(reasoningDetails)) for (const item of reasoningDetails) {
97
+ if (!isRecord(item)) continue;
98
+ const detail = item;
99
+ if (typeof detail.text !== "string" || !detail.text) continue;
100
+ if (detail.type === "reasoning.text") {
101
+ usedReasoningThinkingDetails = true;
102
+ batch ??= createOpenAICompletionsReasoningBatch();
103
+ appendOpenAICompletionsReasoningDelta(batch, {
104
+ kind: "thinking",
105
+ signature: "reasoning_details",
106
+ text: detail.text
107
+ });
108
+ continue;
109
+ }
110
+ if (typeof detail.type === "string" && visibleReasoningDetailTypes.has(detail.type)) {
111
+ batch ??= createOpenAICompletionsReasoningBatch();
112
+ appendOpenAICompletionsReasoningDelta(batch, {
113
+ kind: "text",
114
+ text: detail.text,
115
+ source: "reasoning_detail"
116
+ });
117
+ }
118
+ }
119
+ if (!usedReasoningThinkingDetails) for (const field of OPENAI_COMPLETIONS_REASONING_FIELDS) {
120
+ const value = delta[field];
121
+ if (typeof value === "string" && value.length > 0) {
122
+ batch ??= createOpenAICompletionsReasoningBatch();
123
+ appendOpenAICompletionsReasoningDelta(batch, {
124
+ kind: "thinking",
125
+ signature: field,
126
+ text: value
127
+ });
128
+ break;
129
+ }
130
+ }
131
+ return batch ?? EMPTY_OPENAI_COMPLETIONS_REASONING_BATCH;
132
+ }
133
+ function parseOpenAICompletionsUsage(rawUsage, model, options) {
134
+ const cacheRead = rawUsage.prompt_tokens_details?.cached_tokens ?? rawUsage.prompt_cache_hit_tokens ?? 0;
135
+ const cacheWrite = rawUsage.prompt_tokens_details?.cache_write_tokens ?? rawUsage.prompt_tokens_details?.cache_creation_input_tokens ?? 0;
136
+ const input = Math.max(0, (rawUsage.prompt_tokens || 0) - cacheRead - cacheWrite);
137
+ const output = rawUsage.completion_tokens || 0;
138
+ const reasoningTokens = rawUsage.completion_tokens_details?.reasoning_tokens;
139
+ const usage = {
140
+ input,
141
+ output,
142
+ cacheRead,
143
+ cacheWrite,
144
+ ...options?.includeReasoningTokens !== false && typeof reasoningTokens === "number" && Number.isFinite(reasoningTokens) ? { reasoningTokens } : {},
145
+ totalTokens: input + output + cacheRead + cacheWrite,
146
+ cost: {
147
+ input: 0,
148
+ output: 0,
149
+ cacheRead: 0,
150
+ cacheWrite: 0,
151
+ total: 0
152
+ }
153
+ };
154
+ calculateCost(model, usage);
155
+ applyProviderReportedUsageCost(usage, rawUsage.cost);
156
+ return usage;
157
+ }
158
+ function createOpenAIResponseHook(onResponse, response, model) {
159
+ return onResponse ? () => onResponse({
160
+ status: response.status,
161
+ headers: headersToRecord(response.headers)
162
+ }, model) : void 0;
163
+ }
164
+ function createOpenAIProviderAcceptanceHook(options, response, model) {
165
+ return () => notifyProviderHttpResponse({
166
+ options,
167
+ response,
168
+ model
169
+ });
170
+ }
171
+ function throwIfModelStreamAborted(signal) {
172
+ if (signal?.aborted) throw transportAbortError(signal);
173
+ }
174
+ /** Measure one UTF-8 append without double-counting a surrogate pair split across chunks. */
175
+ function measureUtf8AppendBytes(bufferEndsWithHighSurrogate, chunk) {
176
+ let bytes = Buffer.byteLength(chunk, "utf8");
177
+ if (!chunk) return {
178
+ bytes,
179
+ endsWithHighSurrogate: bufferEndsWithHighSurrogate
180
+ };
181
+ const nextCodeUnit = chunk.charCodeAt(0);
182
+ if (bufferEndsWithHighSurrogate && nextCodeUnit >= 56320 && nextCodeUnit <= 57343) bytes -= 2;
183
+ const finalCodeUnit = chunk.charCodeAt(chunk.length - 1);
184
+ return {
185
+ bytes,
186
+ endsWithHighSurrogate: finalCodeUnit >= 55296 && finalCodeUnit <= 56319
187
+ };
188
+ }
189
+ function createModelStreamCooperativeScheduler(signal) {
190
+ let lastYieldedAt = Date.now();
191
+ let eventsSinceYield = 0;
192
+ return { async afterEvent() {
193
+ throwIfModelStreamAborted(signal);
194
+ eventsSinceYield += 1;
195
+ const now = Date.now();
196
+ if (eventsSinceYield < MODEL_STREAM_COOPERATIVE_YIELD_MAX_EVENTS && now - lastYieldedAt < MODEL_STREAM_COOPERATIVE_YIELD_INTERVAL_MS) return;
197
+ eventsSinceYield = 0;
198
+ lastYieldedAt = now;
199
+ await new Promise((resolve) => {
200
+ setTimeout(resolve, 0);
201
+ });
202
+ throwIfModelStreamAborted(signal);
203
+ } };
204
+ }
205
+ function resolvePromptCacheKey(options, cacheRetention) {
206
+ if (cacheRetention === "none") return;
207
+ return clampOpenAIPromptCacheKey(options?.promptCacheKey ?? options?.sessionId);
208
+ }
209
+ function isOpenAICompletionsThinkingEnabled(effort) {
210
+ const normalized = effort.trim().toLowerCase();
211
+ return normalized !== "off" && normalized !== "none";
212
+ }
213
+ function readOpenAICompletionsContentDeltas(content, topLevelRefusal, mirroredThinking = []) {
214
+ let deltas = readOpenAICompletionsContentPartDeltas(content);
215
+ if (mirroredThinking.length > 0) {
216
+ const structuredThinking = deltas.filter((delta) => delta.kind === "thinking").map((delta) => delta.text);
217
+ const mirrorsCombinedThinking = structuredThinking.length > 1 && mirroredThinking.includes(structuredThinking.join(""));
218
+ deltas = deltas.filter((delta) => delta.kind !== "thinking" || !mirrorsCombinedThinking && !mirroredThinking.includes(delta.text));
219
+ }
220
+ if (typeof topLevelRefusal !== "string" || !topLevelRefusal) return deltas;
221
+ const structuredRefusals = deltas.filter((delta) => delta.kind === "text" && delta.source === "refusal").map((delta) => delta.text);
222
+ if (structuredRefusals.some((refusal) => refusal === topLevelRefusal) || structuredRefusals.length > 1 && structuredRefusals.join("") === topLevelRefusal) return deltas;
223
+ return [...deltas, {
224
+ kind: "text",
225
+ text: topLevelRefusal,
226
+ source: "refusal"
227
+ }];
228
+ }
229
+ function readOpenAICompletionsContentPartDeltas(content) {
230
+ if (typeof content === "string") return content ? [{
231
+ kind: "text",
232
+ text: content
233
+ }] : [];
234
+ if (Array.isArray(content)) return content.flatMap(readOpenAICompletionsContentPartDeltas);
235
+ if (!content || typeof content !== "object") return [];
236
+ const record = content;
237
+ const type = typeof record.type === "string" ? record.type.toLowerCase() : "";
238
+ const extractText = (value) => {
239
+ if (typeof value === "string") return value;
240
+ if (Array.isArray(value)) return value.map(extractText).join("");
241
+ if (value && typeof value === "object") {
242
+ const nested = value;
243
+ return extractText(nested.text ?? nested.content ?? nested.thinking ?? nested.refusal);
244
+ }
245
+ return "";
246
+ };
247
+ const text = extractText(record.text ?? record.content ?? record.thinking ?? record.refusal);
248
+ if (!text) return [];
249
+ if (type.includes("thinking") || type.includes("reasoning")) return [{
250
+ kind: "thinking",
251
+ text
252
+ }];
253
+ if (type === "refusal") return [{
254
+ kind: "text",
255
+ text,
256
+ source: "refusal"
257
+ }];
258
+ if (["text", "output_text"].includes(type) || type.endsWith(".output_text")) return [{
259
+ kind: "text",
260
+ text
261
+ }];
262
+ return [];
263
+ }
264
+ //#endregion
265
+ //#region packages/ai/src/providers/openai-tool-projection.ts
266
+ function unreadableToolDiagnostic(toolIndex) {
267
+ return {
268
+ toolIndex,
269
+ violations: [`tool[${toolIndex}] is unreadable`]
270
+ };
271
+ }
272
+ /** Snapshots direct/custom tool descriptors before OpenAI payload construction. */
273
+ function projectOpenAITools(tools) {
274
+ let inputToolCount;
275
+ try {
276
+ inputToolCount = tools.length;
277
+ } catch {
278
+ return {
279
+ inputToolCount: 0,
280
+ tools: [],
281
+ diagnostics: [unreadableToolDiagnostic(0)]
282
+ };
283
+ }
284
+ const projectedTools = [];
285
+ const diagnostics = [];
286
+ for (let toolIndex = 0; toolIndex < inputToolCount; toolIndex += 1) {
287
+ let tool;
288
+ try {
289
+ const candidate = tools[toolIndex];
290
+ if (!candidate) {
291
+ diagnostics.push(unreadableToolDiagnostic(toolIndex));
292
+ continue;
293
+ }
294
+ tool = candidate;
295
+ } catch {
296
+ diagnostics.push(unreadableToolDiagnostic(toolIndex));
297
+ continue;
298
+ }
299
+ let name;
300
+ try {
301
+ name = tool.name;
302
+ } catch {
303
+ diagnostics.push({
304
+ toolIndex,
305
+ violations: [`tool[${toolIndex}].name is unreadable`]
306
+ });
307
+ continue;
308
+ }
309
+ if (typeof name !== "string" || !name) {
310
+ diagnostics.push({
311
+ toolIndex,
312
+ violations: [`tool[${toolIndex}].name is empty`]
313
+ });
314
+ continue;
315
+ }
316
+ let parameters;
317
+ try {
318
+ parameters = tool.parameters;
319
+ } catch {
320
+ diagnostics.push({
321
+ toolIndex,
322
+ toolName: name,
323
+ violations: [`${name}.parameters is unreadable`]
324
+ });
325
+ continue;
326
+ }
327
+ const schemaProjection = projectRuntimeToolInputSchema(parameters ?? {}, `${name}.parameters`);
328
+ if (!isRecord(schemaProjection.schema) || schemaProjection.violations.length > 0) {
329
+ diagnostics.push({
330
+ toolIndex,
331
+ toolName: name,
332
+ violations: schemaProjection.violations.length > 0 ? schemaProjection.violations : [`${name}.parameters must be a JSON object schema`]
333
+ });
334
+ continue;
335
+ }
336
+ let descriptionValue;
337
+ try {
338
+ descriptionValue = tool.description;
339
+ } catch {}
340
+ const description = typeof descriptionValue === "string" ? descriptionValue : void 0;
341
+ projectedTools.push({
342
+ toolIndex,
343
+ name,
344
+ ...description !== void 0 ? { description } : {},
345
+ parameters: schemaProjection.schema
346
+ });
347
+ }
348
+ return {
349
+ inputToolCount,
350
+ tools: projectedTools,
351
+ diagnostics
352
+ };
353
+ }
354
+ function requireProjectedFunction(name, projection, choiceLabel) {
355
+ if (!projection.tools.some((tool) => tool.name === name)) throw new Error(`${choiceLabel} requested unavailable tool "${name}" after schema conversion`);
356
+ }
357
+ /** Keeps Responses tool choices aligned with surviving function schemas. */
358
+ function reconcileOpenAIResponsesToolChoice(choice, projection) {
359
+ if (choice === "auto") return projection.tools.length > 0 ? choice : void 0;
360
+ if (choice === "required") {
361
+ if (projection.tools.length === 0) throw new Error("OpenAI Responses tool_choice requires a tool, but no tools survived schema conversion");
362
+ return choice;
363
+ }
364
+ if (choice === "none" || !isRecord(choice)) return choice;
365
+ const choiceType = choice.type;
366
+ if (choiceType === "function") {
367
+ const functionName = choice.name;
368
+ if (typeof functionName !== "string") return choice;
369
+ requireProjectedFunction(functionName, projection, "OpenAI Responses tool_choice");
370
+ return {
371
+ type: "function",
372
+ name: functionName
373
+ };
374
+ }
375
+ if (choiceType !== "allowed_tools") return choice;
376
+ const mode = choice.mode;
377
+ const tools = choice.tools;
378
+ if (mode !== "auto" && mode !== "required" || !Array.isArray(tools)) return choice;
379
+ const normalizedAllowedTools = [];
380
+ for (const tool of tools) {
381
+ if (!isRecord(tool) || tool.type !== "function") {
382
+ normalizedAllowedTools.push(tool);
383
+ continue;
384
+ }
385
+ const functionName = tool.name;
386
+ if (typeof functionName === "string" && projection.tools.some((projectedTool) => projectedTool.name === functionName)) normalizedAllowedTools.push({
387
+ type: "function",
388
+ name: functionName
389
+ });
390
+ }
391
+ if (normalizedAllowedTools.length === 0) {
392
+ if (mode === "auto") return "none";
393
+ throw new Error("OpenAI Responses tool_choice requires a tool, but no allowed tools survived schema conversion");
394
+ }
395
+ return {
396
+ type: "allowed_tools",
397
+ mode,
398
+ tools: normalizedAllowedTools
399
+ };
400
+ }
401
+ /** Keeps Chat Completions tool choices aligned with surviving function schemas. */
402
+ function reconcileOpenAICompletionsToolChoice(choice, projection) {
403
+ if (choice === "auto") return projection.tools.length > 0 ? choice : void 0;
404
+ if (choice === "required") {
405
+ if (projection.tools.length === 0) throw new Error("OpenAI Chat Completions tool_choice requires a tool, but no tools survived schema conversion");
406
+ return choice;
407
+ }
408
+ if (choice === "none" || !isRecord(choice)) return choice;
409
+ const choiceType = choice.type;
410
+ if (choiceType === "custom") throw new Error("OpenAI Chat Completions custom tool_choice is unsupported because this adapter emits function tools only");
411
+ if (choiceType === "function") {
412
+ const functionChoice = choice.function;
413
+ if (!isRecord(functionChoice)) return choice;
414
+ const functionName = functionChoice.name;
415
+ if (typeof functionName !== "string") return choice;
416
+ requireProjectedFunction(functionName, projection, "OpenAI Chat Completions tool_choice");
417
+ return {
418
+ type: "function",
419
+ function: { name: functionName }
420
+ };
421
+ }
422
+ if (choiceType !== "allowed_tools") return choice;
423
+ const allowedConfig = choice.allowed_tools;
424
+ if (!isRecord(allowedConfig)) return choice;
425
+ const mode = allowedConfig.mode;
426
+ const tools = allowedConfig.tools;
427
+ if (mode !== "auto" && mode !== "required" || !Array.isArray(tools)) return choice;
428
+ const normalizedAllowedTools = [];
429
+ for (const tool of tools) {
430
+ if (!isRecord(tool) || tool.type !== "function") continue;
431
+ const functionChoice = tool.function;
432
+ const functionName = isRecord(functionChoice) ? functionChoice.name : void 0;
433
+ if (typeof functionName === "string" && projection.tools.some((projectedTool) => projectedTool.name === functionName)) normalizedAllowedTools.push({
434
+ type: "function",
435
+ function: { name: functionName }
436
+ });
437
+ }
438
+ if (normalizedAllowedTools.length === 0) {
439
+ if (mode === "auto") return "none";
440
+ throw new Error("OpenAI Chat Completions tool_choice requires a tool, but no allowed tools survived schema conversion");
441
+ }
442
+ return {
443
+ type: "allowed_tools",
444
+ allowed_tools: {
445
+ mode,
446
+ tools: normalizedAllowedTools
447
+ }
448
+ };
449
+ }
450
+ //#endregion
451
+ //#region packages/ai/src/transports/openai-reasoning-compat.ts
452
+ /**
453
+ * OpenAI reasoning-effort compatibility helpers.
454
+ *
455
+ * Keeps provider metadata and built-in model exceptions on one path before request payloads are built.
456
+ */
457
+ const OPENAI_MEDIUM_ONLY_REASONING_MODEL_IDS = /* @__PURE__ */ new Set(["gpt-5.1-codex-mini"]);
458
+ function readCompatReasoningEffortMap(compat) {
459
+ const rawMap = asOptionalObjectRecord(asOptionalObjectRecord(compat)?.reasoningEffortMap);
460
+ if (!rawMap) return {};
461
+ return Object.fromEntries(Object.entries(rawMap).filter((entry) => typeof entry[0] === "string" && typeof entry[1] === "string"));
462
+ }
463
+ /** Resolves the reasoning effort remap for an OpenAI-compatible model. */
464
+ function resolveOpenAIReasoningEffortMap(model, fallbackMap = {}) {
465
+ const provider = normalizeLowercaseStringOrEmpty(model.provider ?? "");
466
+ const id = normalizeLowercaseStringOrEmpty(model.id ?? "");
467
+ const builtinMap = provider === "openai" && OPENAI_MEDIUM_ONLY_REASONING_MODEL_IDS.has(id) ? {
468
+ minimal: "medium",
469
+ low: "medium"
470
+ } : {};
471
+ return {
472
+ ...fallbackMap,
473
+ ...builtinMap,
474
+ ...readCompatReasoningEffortMap(model.compat)
475
+ };
476
+ }
477
+ //#endregion
478
+ //#region packages/ai/src/transports/openai-transport-params.ts
479
+ const MAX_OPENAI_STRICT_TOOL_DOWNGRADE_DIAGNOSTIC_KEYS = 256;
480
+ const loggedOpenAIStrictToolDowngradeDiagnosticKeys = /* @__PURE__ */ new Set();
481
+ function readToolPayloadField(record, field) {
482
+ try {
483
+ return Object.hasOwn(record, field) ? record[field] : void 0;
484
+ } catch {
485
+ return;
486
+ }
487
+ }
488
+ function readCodeModePayloadToolName(tool) {
489
+ if (!isRecord(tool)) return;
490
+ const name = readToolPayloadField(tool, "name");
491
+ if (typeof name === "string") return name;
492
+ const fn = readToolPayloadField(tool, "function");
493
+ if (!isRecord(fn)) return;
494
+ const fnName = readToolPayloadField(fn, "name");
495
+ return typeof fnName === "string" ? fnName : void 0;
496
+ }
497
+ function readCodeModePayloadToolIdentity(tool, visibleToolNames, allowedHostedToolTypes) {
498
+ if (!isRecord(tool)) return;
499
+ const type = readToolPayloadField(tool, "type");
500
+ if (typeof type === "string" && allowedHostedToolTypes?.has(type)) {
501
+ try {
502
+ if (Object.hasOwn(tool, "name") || Object.hasOwn(tool, "function") || Object.hasOwn(tool, "functionDeclarations") || Object.hasOwn(tool, "function_declarations")) return false;
503
+ } catch {
504
+ return false;
505
+ }
506
+ return `hosted:${type}`;
507
+ }
508
+ const name = readCodeModePayloadToolName(tool);
509
+ return typeof name === "string" && isCodeModeModelVisibleToolName(name, visibleToolNames) ? `client:${name}` : void 0;
510
+ }
511
+ function readCodeModePayloadToolIdentities(payload) {
512
+ if (!isRecord(payload)) return [];
513
+ const tools = readToolPayloadField(payload, "tools");
514
+ if (!Array.isArray(tools)) return [];
515
+ return tools.flatMap((tool) => {
516
+ if (!isRecord(tool)) return [];
517
+ const identities = [];
518
+ const name = readCodeModePayloadToolName(tool);
519
+ if (name) identities.push(`client:${name}`);
520
+ for (const key of ["functionDeclarations", "function_declarations"]) {
521
+ const declarations = readToolPayloadField(tool, key);
522
+ if (!Array.isArray(declarations)) continue;
523
+ for (const declaration of declarations) {
524
+ const declarationName = readCodeModePayloadToolName(declaration);
525
+ if (declarationName) identities.push(`client:${declarationName}`);
526
+ }
527
+ }
528
+ const type = readToolPayloadField(tool, "type");
529
+ if (typeof type === "string" && type !== "function") identities.push(`hosted:${type}`);
530
+ return identities;
531
+ });
532
+ }
533
+ function filterCodeModePayloadTools(payload, visibleToolNames, allowedHostedToolTypes, observer) {
534
+ if (!isRecord(payload)) return;
535
+ const tools = readToolPayloadField(payload, "tools");
536
+ if (!Array.isArray(tools)) return;
537
+ const beforeToolIdentities = observer ? readCodeModePayloadToolIdentities(payload) : void 0;
538
+ payload.tools = tools.flatMap((tool) => {
539
+ const identity = readCodeModePayloadToolIdentity(tool, visibleToolNames, allowedHostedToolTypes);
540
+ if (identity) return [tool];
541
+ if (identity === false) return [];
542
+ if (!isRecord(tool)) return [];
543
+ const filteredGroups = {};
544
+ for (const key of ["functionDeclarations", "function_declarations"]) {
545
+ const declarations = readToolPayloadField(tool, key);
546
+ if (!Array.isArray(declarations)) continue;
547
+ const filtered = declarations.filter((declaration) => {
548
+ const declarationName = readCodeModePayloadToolName(declaration);
549
+ return typeof declarationName === "string" && isCodeModeModelVisibleToolName(declarationName, visibleToolNames);
550
+ });
551
+ if (filtered.length > 0) filteredGroups[key] = filtered;
552
+ }
553
+ return Object.keys(filteredGroups).length > 0 ? [filteredGroups] : [];
554
+ });
555
+ if (beforeToolIdentities) observer?.({
556
+ beforeToolIdentities,
557
+ afterToolIdentities: readCodeModePayloadToolIdentities(payload)
558
+ });
559
+ }
560
+ function resolveCodeModeResponsesVisibleToolNames(context) {
561
+ return new Set((context.tools ?? []).map(readCodeModePayloadToolName).filter((name) => typeof name === "string"));
562
+ }
563
+ function enforceCodeModeResponsesToolSurface(payload, visibleToolNames, allowedHostedToolTypes, observer) {
564
+ if (!isRecord(payload)) return;
565
+ const tools = readToolPayloadField(payload, "tools");
566
+ if (!Array.isArray(tools)) return;
567
+ const beforeToolIdentities = observer ? readCodeModePayloadToolIdentities(payload) : void 0;
568
+ payload.tools = tools.filter((tool) => Boolean(readCodeModePayloadToolIdentity(tool, visibleToolNames, allowedHostedToolTypes)));
569
+ if (beforeToolIdentities) observer?.({
570
+ beforeToolIdentities,
571
+ afterToolIdentities: readCodeModePayloadToolIdentities(payload)
572
+ });
573
+ }
574
+ function assertCodeModeResponsesToolSurface(payload, visibleToolNames, allowedHostedToolTypes) {
575
+ const tools = isRecord(payload) ? readToolPayloadField(payload, "tools") : void 0;
576
+ if (!Array.isArray(tools)) throw new Error("Code mode payload tool surface violation: expected exec,wait; got no tools");
577
+ const identities = tools.map((tool) => readCodeModePayloadToolIdentity(tool, visibleToolNames, allowedHostedToolTypes));
578
+ const names = identities.flatMap((identity) => typeof identity === "string" && identity.startsWith("client:") ? [identity.slice(7)] : []).toSorted((left, right) => left.localeCompare(right));
579
+ if (names.length >= 2 && identities.every((identity) => typeof identity === "string") && new Set(identities).size === identities.length && names.includes("exec") && names.includes("wait")) return;
580
+ throw new Error(`Code mode payload tool surface violation: expected exec,wait plus direct-only tools; got ${names.length > 0 ? names.join(",") : "none"}`);
581
+ }
582
+ function resolveOpenAIStrictToolFlagWithDiagnostics(projection, strictSetting, context) {
583
+ const strict = resolveOpenAIProjectedToolsStrictToolFlag(projection, strictSetting);
584
+ if (strictSetting === true && strict === false) getAiTransportHost().logDebug("openai-transport", () => {
585
+ const diagnostics = findOpenAIStrictToolProjectionDiagnostics(projection);
586
+ const key = sha256Hex(JSON.stringify({
587
+ transport: context.transport,
588
+ provider: context.model.provider ?? null,
589
+ model: context.model.id ?? null,
590
+ diagnostics: diagnostics.map((entry) => ({
591
+ toolIndex: entry.toolIndex,
592
+ toolName: entry.toolName ?? null,
593
+ violations: entry.violations
594
+ }))
595
+ }));
596
+ if (loggedOpenAIStrictToolDowngradeDiagnosticKeys.has(key)) return null;
597
+ if (loggedOpenAIStrictToolDowngradeDiagnosticKeys.size >= MAX_OPENAI_STRICT_TOOL_DOWNGRADE_DIAGNOSTIC_KEYS) loggedOpenAIStrictToolDowngradeDiagnosticKeys.clear();
598
+ loggedOpenAIStrictToolDowngradeDiagnosticKeys.add(key);
599
+ const sample = diagnostics.slice(0, 5).map((entry) => ({
600
+ tool: entry.toolName ?? `tool[${entry.toolIndex}]`,
601
+ violations: entry.violations.slice(0, 8)
602
+ }));
603
+ return {
604
+ message: `OpenAI ${context.transport} tool schema strict mode downgraded to strict=false for ${context.model.provider ?? "unknown"}/${context.model.id ?? "unknown"} because ${diagnostics.length} tool schema(s) are not strict-compatible`,
605
+ data: {
606
+ transport: context.transport,
607
+ provider: context.model.provider,
608
+ model: context.model.id,
609
+ incompatibleToolCount: diagnostics.length,
610
+ sample
611
+ }
612
+ };
613
+ });
614
+ return strict;
615
+ }
616
+ function buildOpenAIClientHeaders(model, context, optionHeaders, turnHeaders, sessionId) {
617
+ const providerHeaders = { ...model.headers };
618
+ if (model.provider === "github-copilot") Object.assign(providerHeaders, getAiTransportHost().buildCopilotDynamicHeaders(context.messages));
619
+ const callerHeaders = {
620
+ ...optionHeaders,
621
+ ...turnHeaders
622
+ };
623
+ const resolvedHeaders = resolveProviderRequestPolicyConfig(model, {
624
+ provider: model.provider,
625
+ api: model.api,
626
+ baseUrl: model.baseUrl,
627
+ capability: "llm",
628
+ transport: "stream",
629
+ providerHeaders,
630
+ callerHeaders: Object.keys(callerHeaders).length > 0 ? callerHeaders : void 0,
631
+ precedence: "caller-wins"
632
+ }).headers ?? {};
633
+ if (sessionId && !Object.keys(resolvedHeaders).some((key) => normalizeLowercaseStringOrEmpty(key) === "session_id") && usesNativeOpenAICodexResponsesBackend(model)) resolvedHeaders.session_id = clampOpenAIPromptCacheKey(sessionId) ?? sessionId;
634
+ return resolveOpencodeSessionHeaders(model, {
635
+ sessionId,
636
+ headers: resolvedHeaders
637
+ }) ?? resolvedHeaders;
638
+ }
639
+ function resolveOpenAISdkTimeoutMs(model, timeoutMs) {
640
+ return resolveModelRequestTimeoutMs(model, timeoutMs);
641
+ }
642
+ function buildOpenAISdkClientOptions(model) {
643
+ const timeout = resolveOpenAISdkTimeoutMs(model);
644
+ return {
645
+ ...timeout === void 0 ? {} : { timeout },
646
+ maxRetries: 0
647
+ };
648
+ }
649
+ function buildOpenAISdkRequestOptions(model, signal, options) {
650
+ const timeout = resolveOpenAISdkTimeoutMs(model, options?.timeoutMs);
651
+ const headers = options?.stream === true && usesNativeOpenAICodexResponsesBackend(model) ? { Accept: "text/event-stream" } : void 0;
652
+ if (timeout === void 0 && !signal && !headers) return;
653
+ return {
654
+ ...headers ? { headers } : {},
655
+ ...signal ? { signal } : {},
656
+ ...timeout !== void 0 ? { timeout } : {},
657
+ maxRetries: 0
658
+ };
659
+ }
660
+ function getCompat(model) {
661
+ const resolved = resolveOpenAICompletionsCompat(model);
662
+ const compat = model.compat ?? {};
663
+ return {
664
+ ...resolved,
665
+ cacheControlFormat: resolved.cacheControlFormat,
666
+ reasoningEffortMap: resolveOpenAIReasoningEffortMap(model, {}),
667
+ openRouterRouting: resolved.openRouterRouting ?? {},
668
+ vercelGatewayRouting: resolved.vercelGatewayRouting,
669
+ requiresStringContent: compat.requiresStringContent ?? false,
670
+ strictMessageKeys: compat.strictMessageKeys === true
671
+ };
672
+ }
673
+ //#endregion
674
+ export { readOpenAICompletionsContentDeltas as C, throwIfModelStreamAborted as D, resolvePromptCacheKey as E, redactIdentifier as O, parseOpenAICompletionsUsage as S, resolveOpenAIClientBaseUrl as T, createOpenAIProviderAcceptanceHook as _, enforceCodeModeResponsesToolSurface as a, log as b, readCodeModePayloadToolName as c, resolveOpenAIReasoningEffortMap as d, projectOpenAITools as f, createModelStreamCooperativeScheduler as g, GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP as h, buildOpenAISdkRequestOptions as i, sha256Hex as k, resolveCodeModeResponsesVisibleToolNames as l, reconcileOpenAIResponsesToolChoice as m, buildOpenAIClientHeaders as n, filterCodeModePayloadTools as o, reconcileOpenAICompletionsToolChoice as p, buildOpenAISdkClientOptions as r, getCompat as s, assertCodeModeResponsesToolSurface as t, resolveOpenAIStrictToolFlagWithDiagnostics as u, createOpenAIResponseHook as v, readOpenAICompletionsReasoningBatch as w, measureUtf8AppendBytes as x, isOpenAICompletionsThinkingEnabled as y };