@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
@@ -1,433 +1,6 @@
1
- import { c as normalizeLowercaseStringOrEmpty, o as isRecord } from "./utf16-slice-qz3nsy87.mjs";
2
- import { n as applyProviderReportedUsageCost, r as calculateCost } from "./sanitize-unicode-D6xUvZaS.mjs";
3
- import { n as getAiTransportHost } from "./host-CEvLw30U.mjs";
4
- import { r as uniqueValues, t as normalizeStringEntries } from "./string-normalization--fwJ4S2q.mjs";
5
- import { n as clampOpenAIPromptCacheKey } from "./openai-prompt-cache-CGnVB74a.mjs";
6
- import { t as projectRuntimeToolInputSchema } from "./tool-schema-json-projection-mJhXDcyz.mjs";
7
- import { C as headersToRecord, _ as transportAbortError, f as notifyProviderHttpResponse } from "./transport-stream-shared-CZqMhfIw.mjs";
8
- //#region packages/ai/src/transports/openai-transport-shared.ts
9
- /** Shared options, usage shape, cache identity, ordering, and stream scheduling for OpenAI APIs. */
10
- const MODEL_STREAM_COOPERATIVE_YIELD_INTERVAL_MS = 12;
11
- const MODEL_STREAM_COOPERATIVE_YIELD_MAX_EVENTS = 64;
12
- const GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP = "skip_thought_signature_validator";
13
- const log = {
14
- debug(message, data) {
15
- getAiTransportHost().logDebug("openai-transport", () => ({
16
- message,
17
- data
18
- }));
19
- },
20
- info(message, data) {
21
- getAiTransportHost().logInfo("openai-transport", message, data);
22
- },
23
- warn(message, data) {
24
- getAiTransportHost().logWarn("openai-transport", message, data);
25
- }
26
- };
27
- function resolveOpenAIClientBaseUrl(model, baseUrl = model.baseUrl) {
28
- if (baseUrl?.trim()) return baseUrl;
29
- if (model.provider.trim().toLowerCase() === "openai") return;
30
- throw new Error(`Provider "${model.provider}" requires an explicit base URL before using an OpenAI-compatible API. Reload provider metadata or configure an endpoint.`);
31
- }
32
- const EMPTY_OPENAI_COMPLETIONS_REASONING_BATCH = {
33
- deltas: [],
34
- mirroredThinking: [],
35
- hasThinking: false,
36
- hasVisibleText: false
37
- };
38
- const OPENAI_COMPLETIONS_REASONING_FIELDS = [
39
- "reasoning_content",
40
- "reasoning",
41
- "reasoning_text"
42
- ];
43
- function appendOpenAICompletionsReasoningDelta(batch, next) {
44
- if (next.kind === "thinking") batch.hasThinking = true;
45
- else batch.hasVisibleText = true;
46
- const previous = batch.deltas[batch.deltas.length - 1];
47
- if (!previous || previous.kind !== next.kind) {
48
- batch.deltas.push(next);
49
- if (next.kind === "thinking") batch.mirroredThinking.push(next.text);
50
- return;
51
- }
52
- if (next.kind === "thinking" && previous.kind === "thinking") {
53
- if (previous.signature !== next.signature) {
54
- batch.deltas.push(next);
55
- batch.mirroredThinking.push(next.text);
56
- return;
57
- }
58
- previous.text += next.text;
59
- batch.mirroredThinking[batch.mirroredThinking.length - 1] += next.text;
60
- return;
61
- }
62
- previous.text += next.text;
63
- }
64
- function createOpenAICompletionsReasoningBatch() {
65
- return {
66
- deltas: [],
67
- mirroredThinking: [],
68
- hasThinking: false,
69
- hasVisibleText: false
70
- };
71
- }
72
- function readOpenAICompletionsReasoningBatch(delta, visibleReasoningDetailTypes) {
73
- let batch;
74
- const reasoningDetails = delta.reasoning_details;
75
- let usedReasoningThinkingDetails = false;
76
- if (Array.isArray(reasoningDetails)) for (const item of reasoningDetails) {
77
- if (!isRecord(item)) continue;
78
- const detail = item;
79
- if (typeof detail.text !== "string" || !detail.text) continue;
80
- if (detail.type === "reasoning.text") {
81
- usedReasoningThinkingDetails = true;
82
- batch ??= createOpenAICompletionsReasoningBatch();
83
- appendOpenAICompletionsReasoningDelta(batch, {
84
- kind: "thinking",
85
- signature: "reasoning_details",
86
- text: detail.text
87
- });
88
- continue;
89
- }
90
- if (typeof detail.type === "string" && visibleReasoningDetailTypes.has(detail.type)) {
91
- batch ??= createOpenAICompletionsReasoningBatch();
92
- appendOpenAICompletionsReasoningDelta(batch, {
93
- kind: "text",
94
- text: detail.text,
95
- source: "reasoning_detail"
96
- });
97
- }
98
- }
99
- if (!usedReasoningThinkingDetails) for (const field of OPENAI_COMPLETIONS_REASONING_FIELDS) {
100
- const value = delta[field];
101
- if (typeof value === "string" && value.length > 0) {
102
- batch ??= createOpenAICompletionsReasoningBatch();
103
- appendOpenAICompletionsReasoningDelta(batch, {
104
- kind: "thinking",
105
- signature: field,
106
- text: value
107
- });
108
- break;
109
- }
110
- }
111
- return batch ?? EMPTY_OPENAI_COMPLETIONS_REASONING_BATCH;
112
- }
113
- function parseOpenAICompletionsUsage(rawUsage, model, options) {
114
- const cacheRead = rawUsage.prompt_tokens_details?.cached_tokens ?? rawUsage.prompt_cache_hit_tokens ?? 0;
115
- const cacheWrite = rawUsage.prompt_tokens_details?.cache_write_tokens ?? rawUsage.prompt_tokens_details?.cache_creation_input_tokens ?? 0;
116
- const input = Math.max(0, (rawUsage.prompt_tokens || 0) - cacheRead - cacheWrite);
117
- const output = rawUsage.completion_tokens || 0;
118
- const reasoningTokens = rawUsage.completion_tokens_details?.reasoning_tokens;
119
- const usage = {
120
- input,
121
- output,
122
- cacheRead,
123
- cacheWrite,
124
- ...options?.includeReasoningTokens !== false && typeof reasoningTokens === "number" && Number.isFinite(reasoningTokens) ? { reasoningTokens } : {},
125
- totalTokens: input + output + cacheRead + cacheWrite,
126
- cost: {
127
- input: 0,
128
- output: 0,
129
- cacheRead: 0,
130
- cacheWrite: 0,
131
- total: 0
132
- }
133
- };
134
- calculateCost(model, usage);
135
- applyProviderReportedUsageCost(usage, rawUsage.cost);
136
- return usage;
137
- }
138
- function createOpenAIResponseHook(onResponse, response, model) {
139
- return onResponse ? () => onResponse({
140
- status: response.status,
141
- headers: headersToRecord(response.headers)
142
- }, model) : void 0;
143
- }
144
- function createOpenAIProviderAcceptanceHook(options, response, model) {
145
- return () => notifyProviderHttpResponse({
146
- options,
147
- response,
148
- model
149
- });
150
- }
151
- function throwIfModelStreamAborted(signal) {
152
- if (signal?.aborted) throw transportAbortError(signal);
153
- }
154
- /** Measure one UTF-8 append without double-counting a surrogate pair split across chunks. */
155
- function measureUtf8AppendBytes(bufferEndsWithHighSurrogate, chunk) {
156
- let bytes = Buffer.byteLength(chunk, "utf8");
157
- if (!chunk) return {
158
- bytes,
159
- endsWithHighSurrogate: bufferEndsWithHighSurrogate
160
- };
161
- const nextCodeUnit = chunk.charCodeAt(0);
162
- if (bufferEndsWithHighSurrogate && nextCodeUnit >= 56320 && nextCodeUnit <= 57343) bytes -= 2;
163
- const finalCodeUnit = chunk.charCodeAt(chunk.length - 1);
164
- return {
165
- bytes,
166
- endsWithHighSurrogate: finalCodeUnit >= 55296 && finalCodeUnit <= 56319
167
- };
168
- }
169
- function createModelStreamCooperativeScheduler(signal) {
170
- let lastYieldedAt = Date.now();
171
- let eventsSinceYield = 0;
172
- return { async afterEvent() {
173
- throwIfModelStreamAborted(signal);
174
- eventsSinceYield += 1;
175
- const now = Date.now();
176
- if (eventsSinceYield < MODEL_STREAM_COOPERATIVE_YIELD_MAX_EVENTS && now - lastYieldedAt < MODEL_STREAM_COOPERATIVE_YIELD_INTERVAL_MS) return;
177
- eventsSinceYield = 0;
178
- lastYieldedAt = now;
179
- await new Promise((resolve) => {
180
- setTimeout(resolve, 0);
181
- });
182
- throwIfModelStreamAborted(signal);
183
- } };
184
- }
185
- function resolvePromptCacheKey(options, cacheRetention) {
186
- if (cacheRetention === "none") return;
187
- return clampOpenAIPromptCacheKey(options?.promptCacheKey ?? options?.sessionId);
188
- }
189
- function isOpenAICompletionsThinkingEnabled(effort) {
190
- const normalized = effort.trim().toLowerCase();
191
- return normalized !== "off" && normalized !== "none";
192
- }
193
- function readOpenAICompletionsContentDeltas(content, topLevelRefusal, mirroredThinking = []) {
194
- let deltas = readOpenAICompletionsContentPartDeltas(content);
195
- if (mirroredThinking.length > 0) {
196
- const structuredThinking = deltas.filter((delta) => delta.kind === "thinking").map((delta) => delta.text);
197
- const mirrorsCombinedThinking = structuredThinking.length > 1 && mirroredThinking.includes(structuredThinking.join(""));
198
- deltas = deltas.filter((delta) => delta.kind !== "thinking" || !mirrorsCombinedThinking && !mirroredThinking.includes(delta.text));
199
- }
200
- if (typeof topLevelRefusal !== "string" || !topLevelRefusal) return deltas;
201
- const structuredRefusals = deltas.filter((delta) => delta.kind === "text" && delta.source === "refusal").map((delta) => delta.text);
202
- if (structuredRefusals.some((refusal) => refusal === topLevelRefusal) || structuredRefusals.length > 1 && structuredRefusals.join("") === topLevelRefusal) return deltas;
203
- return [...deltas, {
204
- kind: "text",
205
- text: topLevelRefusal,
206
- source: "refusal"
207
- }];
208
- }
209
- function readOpenAICompletionsContentPartDeltas(content) {
210
- if (typeof content === "string") return content ? [{
211
- kind: "text",
212
- text: content
213
- }] : [];
214
- if (Array.isArray(content)) return content.flatMap(readOpenAICompletionsContentPartDeltas);
215
- if (!content || typeof content !== "object") return [];
216
- const record = content;
217
- const type = typeof record.type === "string" ? record.type.toLowerCase() : "";
218
- const extractText = (value) => {
219
- if (typeof value === "string") return value;
220
- if (Array.isArray(value)) return value.map(extractText).join("");
221
- if (value && typeof value === "object") {
222
- const nested = value;
223
- return extractText(nested.text ?? nested.content ?? nested.thinking ?? nested.refusal);
224
- }
225
- return "";
226
- };
227
- const text = extractText(record.text ?? record.content ?? record.thinking ?? record.refusal);
228
- if (!text) return [];
229
- if (type.includes("thinking") || type.includes("reasoning")) return [{
230
- kind: "thinking",
231
- text
232
- }];
233
- if (type === "refusal") return [{
234
- kind: "text",
235
- text,
236
- source: "refusal"
237
- }];
238
- if (["text", "output_text"].includes(type) || type.endsWith(".output_text")) return [{
239
- kind: "text",
240
- text
241
- }];
242
- return [];
243
- }
244
- //#endregion
245
- //#region packages/ai/src/providers/openai-tool-projection.ts
246
- function unreadableToolDiagnostic(toolIndex) {
247
- return {
248
- toolIndex,
249
- violations: [`tool[${toolIndex}] is unreadable`]
250
- };
251
- }
252
- /** Snapshots direct/custom tool descriptors before OpenAI payload construction. */
253
- function projectOpenAITools(tools) {
254
- let inputToolCount;
255
- try {
256
- inputToolCount = tools.length;
257
- } catch {
258
- return {
259
- inputToolCount: 0,
260
- tools: [],
261
- diagnostics: [unreadableToolDiagnostic(0)]
262
- };
263
- }
264
- const projectedTools = [];
265
- const diagnostics = [];
266
- for (let toolIndex = 0; toolIndex < inputToolCount; toolIndex += 1) {
267
- let tool;
268
- try {
269
- const candidate = tools[toolIndex];
270
- if (!candidate) {
271
- diagnostics.push(unreadableToolDiagnostic(toolIndex));
272
- continue;
273
- }
274
- tool = candidate;
275
- } catch {
276
- diagnostics.push(unreadableToolDiagnostic(toolIndex));
277
- continue;
278
- }
279
- let name;
280
- try {
281
- name = tool.name;
282
- } catch {
283
- diagnostics.push({
284
- toolIndex,
285
- violations: [`tool[${toolIndex}].name is unreadable`]
286
- });
287
- continue;
288
- }
289
- if (typeof name !== "string" || !name) {
290
- diagnostics.push({
291
- toolIndex,
292
- violations: [`tool[${toolIndex}].name is empty`]
293
- });
294
- continue;
295
- }
296
- let parameters;
297
- try {
298
- parameters = tool.parameters;
299
- } catch {
300
- diagnostics.push({
301
- toolIndex,
302
- toolName: name,
303
- violations: [`${name}.parameters is unreadable`]
304
- });
305
- continue;
306
- }
307
- const schemaProjection = projectRuntimeToolInputSchema(parameters ?? {}, `${name}.parameters`);
308
- if (!isRecord(schemaProjection.schema) || schemaProjection.violations.length > 0) {
309
- diagnostics.push({
310
- toolIndex,
311
- toolName: name,
312
- violations: schemaProjection.violations.length > 0 ? schemaProjection.violations : [`${name}.parameters must be a JSON object schema`]
313
- });
314
- continue;
315
- }
316
- let descriptionValue;
317
- try {
318
- descriptionValue = tool.description;
319
- } catch {}
320
- const description = typeof descriptionValue === "string" ? descriptionValue : void 0;
321
- projectedTools.push({
322
- toolIndex,
323
- name,
324
- ...description !== void 0 ? { description } : {},
325
- parameters: schemaProjection.schema
326
- });
327
- }
328
- return {
329
- inputToolCount,
330
- tools: projectedTools,
331
- diagnostics
332
- };
333
- }
334
- function requireProjectedFunction(name, projection, choiceLabel) {
335
- if (!projection.tools.some((tool) => tool.name === name)) throw new Error(`${choiceLabel} requested unavailable tool "${name}" after schema conversion`);
336
- }
337
- /** Keeps Responses tool choices aligned with surviving function schemas. */
338
- function reconcileOpenAIResponsesToolChoice(choice, projection) {
339
- if (choice === "auto") return projection.tools.length > 0 ? choice : void 0;
340
- if (choice === "required") {
341
- if (projection.tools.length === 0) throw new Error("OpenAI Responses tool_choice requires a tool, but no tools survived schema conversion");
342
- return choice;
343
- }
344
- if (choice === "none" || !isRecord(choice)) return choice;
345
- const choiceType = choice.type;
346
- if (choiceType === "function") {
347
- const functionName = choice.name;
348
- if (typeof functionName !== "string") return choice;
349
- requireProjectedFunction(functionName, projection, "OpenAI Responses tool_choice");
350
- return {
351
- type: "function",
352
- name: functionName
353
- };
354
- }
355
- if (choiceType !== "allowed_tools") return choice;
356
- const mode = choice.mode;
357
- const tools = choice.tools;
358
- if (mode !== "auto" && mode !== "required" || !Array.isArray(tools)) return choice;
359
- const normalizedAllowedTools = [];
360
- for (const tool of tools) {
361
- if (!isRecord(tool) || tool.type !== "function") {
362
- normalizedAllowedTools.push(tool);
363
- continue;
364
- }
365
- const functionName = tool.name;
366
- if (typeof functionName === "string" && projection.tools.some((projectedTool) => projectedTool.name === functionName)) normalizedAllowedTools.push({
367
- type: "function",
368
- name: functionName
369
- });
370
- }
371
- if (normalizedAllowedTools.length === 0) {
372
- if (mode === "auto") return "none";
373
- throw new Error("OpenAI Responses tool_choice requires a tool, but no allowed tools survived schema conversion");
374
- }
375
- return {
376
- type: "allowed_tools",
377
- mode,
378
- tools: normalizedAllowedTools
379
- };
380
- }
381
- /** Keeps Chat Completions tool choices aligned with surviving function schemas. */
382
- function reconcileOpenAICompletionsToolChoice(choice, projection) {
383
- if (choice === "auto") return projection.tools.length > 0 ? choice : void 0;
384
- if (choice === "required") {
385
- if (projection.tools.length === 0) throw new Error("OpenAI Chat Completions tool_choice requires a tool, but no tools survived schema conversion");
386
- return choice;
387
- }
388
- if (choice === "none" || !isRecord(choice)) return choice;
389
- const choiceType = choice.type;
390
- if (choiceType === "custom") throw new Error("OpenAI Chat Completions custom tool_choice is unsupported because this adapter emits function tools only");
391
- if (choiceType === "function") {
392
- const functionChoice = choice.function;
393
- if (!isRecord(functionChoice)) return choice;
394
- const functionName = functionChoice.name;
395
- if (typeof functionName !== "string") return choice;
396
- requireProjectedFunction(functionName, projection, "OpenAI Chat Completions tool_choice");
397
- return {
398
- type: "function",
399
- function: { name: functionName }
400
- };
401
- }
402
- if (choiceType !== "allowed_tools") return choice;
403
- const allowedConfig = choice.allowed_tools;
404
- if (!isRecord(allowedConfig)) return choice;
405
- const mode = allowedConfig.mode;
406
- const tools = allowedConfig.tools;
407
- if (mode !== "auto" && mode !== "required" || !Array.isArray(tools)) return choice;
408
- const normalizedAllowedTools = [];
409
- for (const tool of tools) {
410
- if (!isRecord(tool) || tool.type !== "function") continue;
411
- const functionChoice = tool.function;
412
- const functionName = isRecord(functionChoice) ? functionChoice.name : void 0;
413
- if (typeof functionName === "string" && projection.tools.some((projectedTool) => projectedTool.name === functionName)) normalizedAllowedTools.push({
414
- type: "function",
415
- function: { name: functionName }
416
- });
417
- }
418
- if (normalizedAllowedTools.length === 0) {
419
- if (mode === "auto") return "none";
420
- throw new Error("OpenAI Chat Completions tool_choice requires a tool, but no allowed tools survived schema conversion");
421
- }
422
- return {
423
- type: "allowed_tools",
424
- allowed_tools: {
425
- mode,
426
- tools: normalizedAllowedTools
427
- }
428
- };
429
- }
430
- //#endregion
1
+ import { n as normalizeLowercaseStringOrEmpty } from "./string-coerce-fsri9iCu.mjs";
2
+ import { o as isRecord } from "./record-coerce-DwRYMj3t.mjs";
3
+ import { r as uniqueValues, t as normalizeStringEntries } from "./string-normalization-CmLIasuf.mjs";
431
4
  //#region packages/ai/src/providers/clean-for-gemini.ts
432
5
  const GEMINI_UNSUPPORTED_SCHEMA_KEYWORDS = /* @__PURE__ */ new Set([
433
6
  "patternProperties",
@@ -969,136 +542,46 @@ function isTypedObjectSchemaMissingValidProperties(schemaRecord, conditionalKey)
969
542
  function isTrulyEmptySchema(schemaRecord) {
970
543
  return Object.keys(schemaRecord).length === 0;
971
544
  }
972
- function normalizeArraySchemasMissingItems(schema) {
973
- if (!isRecord(schema)) return schema;
974
- let changed = false;
975
- const nextSchema = { ...schema };
976
- if (nextSchema.type === "array" && nextSchema.items === void 0) {
977
- nextSchema.items = {};
978
- changed = true;
979
- }
980
- const normalizeSchemaValue = (key) => {
981
- if (!(key in nextSchema)) return;
982
- const value = nextSchema[key];
983
- if (Array.isArray(value)) {
984
- const normalized = value.map(normalizeArraySchemasMissingItems);
985
- if (normalized.some((entry, index) => entry !== value[index])) {
986
- nextSchema[key] = normalized;
987
- changed = true;
988
- }
989
- return;
990
- }
991
- const normalized = normalizeArraySchemasMissingItems(value);
992
- if (normalized !== value) {
993
- nextSchema[key] = normalized;
994
- changed = true;
995
- }
996
- };
997
- for (const key of [
998
- "items",
999
- "contains",
1000
- "additionalProperties",
1001
- "propertyNames",
1002
- "not",
1003
- "if",
1004
- "then",
1005
- "else"
1006
- ]) normalizeSchemaValue(key);
1007
- for (const key of [
1008
- "anyOf",
1009
- "oneOf",
1010
- "allOf",
1011
- "prefixItems"
1012
- ]) normalizeSchemaValue(key);
1013
- for (const key of [
1014
- "properties",
1015
- "patternProperties",
1016
- "dependentSchemas",
1017
- "$defs",
1018
- "definitions"
1019
- ]) {
1020
- const value = nextSchema[key];
1021
- if (!isRecord(value)) continue;
1022
- let entriesChanged = false;
1023
- const normalizedEntries = Object.entries(value).map(([entryKey, entryValue]) => {
1024
- const normalizedEntryValue = normalizeArraySchemasMissingItems(entryValue);
1025
- if (normalizedEntryValue !== entryValue) entriesChanged = true;
1026
- return [entryKey, normalizedEntryValue];
1027
- });
1028
- if (entriesChanged) {
1029
- nextSchema[key] = Object.fromEntries(normalizedEntries);
1030
- changed = true;
1031
- }
1032
- }
1033
- return changed ? nextSchema : schema;
1034
- }
1035
- function schemaAllowsArrayType(schema) {
1036
- const type = schema.type;
1037
- return type === "array" || Array.isArray(type) && type.includes("array");
1038
- }
1039
- const ARRAY_ITEMS_SCHEMA_OBJECT_KEYS = /* @__PURE__ */ new Set([
1040
- "additionalProperties",
1041
- "contains",
1042
- "else",
1043
- "if",
1044
- "items",
1045
- "not",
1046
- "propertyNames",
1047
- "then"
1048
- ]);
1049
- const ARRAY_ITEMS_SCHEMA_ARRAY_KEYS = /* @__PURE__ */ new Set([
1050
- "allOf",
1051
- "anyOf",
1052
- "oneOf",
1053
- "prefixItems"
1054
- ]);
1055
- const ARRAY_ITEMS_SCHEMA_MAP_KEYS = /* @__PURE__ */ new Set([
1056
- "$defs",
1057
- "definitions",
1058
- "dependentSchemas",
1059
- "patternProperties",
1060
- "properties"
1061
- ]);
1062
- function stripEmptyArrayItemsFromArraySchemas(schema) {
545
+ function normalizeArraySchemaItems(schema, mode) {
1063
546
  if (Array.isArray(schema)) {
1064
- let changed = false;
1065
- const entries = schema.map((entry) => {
1066
- const next = stripEmptyArrayItemsFromArraySchemas(entry);
1067
- changed ||= next !== entry;
1068
- return next;
1069
- });
1070
- return changed ? entries : schema;
547
+ if (mode === "add") return schema;
548
+ const entries = schema.map((entry) => normalizeArraySchemaItems(entry, "omit"));
549
+ return entries.some((entry, index) => entry !== schema[index]) ? entries : schema;
1071
550
  }
1072
551
  if (!isRecord(schema)) return schema;
1073
- let changed = false;
1074
- const entries = Object.entries(schema).flatMap(([key, value]) => {
1075
- if (key === "items" && schemaAllowsArrayType(schema) && isRecord(value) && isTrulyEmptySchema(value)) {
552
+ const missingItems = mode !== "omit" && schema.type === "array" && schema.items === void 0;
553
+ let changed = missingItems;
554
+ const normalized = { ...schema };
555
+ if (missingItems) {
556
+ if (mode === "add") normalized.items = {};
557
+ else delete normalized.items;
558
+ }
559
+ const allowsArray = schema.type === "array" || Array.isArray(schema.type) && schema.type.includes("array");
560
+ const normalizeValue = (value, valueMode) => {
561
+ if (!Array.isArray(value)) return normalizeArraySchemaItems(value, valueMode);
562
+ const entries = value.map((entry) => normalizeArraySchemaItems(entry, valueMode));
563
+ return entries.some((entry, index) => entry !== value[index]) ? entries : value;
564
+ };
565
+ for (const [key, value] of Object.entries(normalized)) {
566
+ if (mode !== "add" && key === "items" && allowsArray && isRecord(value) && isTrulyEmptySchema(value)) {
567
+ delete normalized.items;
1076
568
  changed = true;
1077
- return [];
1078
- }
1079
- if (ARRAY_ITEMS_SCHEMA_OBJECT_KEYS.has(key)) {
1080
- const next = stripEmptyArrayItemsFromArraySchemas(value);
1081
- changed ||= next !== value;
1082
- return [[key, next]];
569
+ continue;
1083
570
  }
1084
- if (ARRAY_ITEMS_SCHEMA_ARRAY_KEYS.has(key) && Array.isArray(value)) {
1085
- const next = stripEmptyArrayItemsFromArraySchemas(value);
1086
- changed ||= next !== value;
1087
- return [[key, next]];
571
+ let next = value;
572
+ if (SCHEMA_MAP_KEYS.has(key) && isRecord(value)) {
573
+ const entries = Object.entries(value).map(([entryKey, entry]) => [entryKey, normalizeArraySchemaItems(entry, mode)]);
574
+ if (entries.some(([entryKey, entry]) => entry !== value[entryKey])) next = Object.fromEntries(entries);
575
+ } else if (SCHEMA_OBJECT_KEYS.has(key) || SCHEMA_ARRAY_KEYS.has(key)) {
576
+ const valueMode = SCHEMA_OBJECT_KEYS.has(key) || Array.isArray(value) ? mode : "add";
577
+ if (valueMode === mode || mode !== "omit") next = normalizeValue(value, valueMode);
1088
578
  }
1089
- if (ARRAY_ITEMS_SCHEMA_MAP_KEYS.has(key) && isRecord(value)) {
1090
- let mapChanged = false;
1091
- const next = Object.fromEntries(Object.entries(value).map(([entryKey, entryValue]) => {
1092
- const entryNext = stripEmptyArrayItemsFromArraySchemas(entryValue);
1093
- mapChanged ||= entryNext !== entryValue;
1094
- return [entryKey, entryNext];
1095
- }));
1096
- changed ||= mapChanged;
1097
- return [[key, mapChanged ? next : value]];
579
+ if (next !== value) {
580
+ setOwnSchemaProperty(normalized, key, next);
581
+ changed = true;
1098
582
  }
1099
- return [[key, value]];
1100
- });
1101
- return changed ? Object.fromEntries(entries) : schema;
583
+ }
584
+ return changed ? normalized : schema;
1102
585
  }
1103
586
  function copySchemaMeta(from, to) {
1104
587
  for (const key of [
@@ -1353,8 +836,7 @@ function normalizeToolParameterSchemaUncached(schema, options) {
1353
836
  const omitEmptyArrayItems = shouldOmitEmptyArrayItems(options?.modelCompat);
1354
837
  const isLlamacppGbnfProfile = normalizedToolSchemaProfile === "llamacpp";
1355
838
  function applyProviderCleaning(s) {
1356
- const normalizedSchema = normalizeArraySchemasMissingItems(s);
1357
- let arrayItemsCompatibleSchema = omitEmptyArrayItems ? stripEmptyArrayItemsFromArraySchemas(normalizedSchema) : normalizedSchema;
839
+ let arrayItemsCompatibleSchema = normalizeArraySchemaItems(s, omitEmptyArrayItems ? "normalize" : "add");
1358
840
  if (isLlamacppGbnfProfile) arrayItemsCompatibleSchema = cleanSchemaForLlamacppGbnf(arrayItemsCompatibleSchema);
1359
841
  if (isGeminiProvider && !isAnthropicProvider) {
1360
842
  const geminiCompatibleSchema = cleanSchemaForGemini(arrayItemsCompatibleSchema);
@@ -1682,4 +1164,4 @@ function resolveOpenAIProjectedToolsStrictToolFlag(projection, strict) {
1682
1164
  return projection.tools.every((tool) => isStrictOpenAIJsonSchemaCompatible(tool.parameters));
1683
1165
  }
1684
1166
  //#endregion
1685
- export { readOpenAICompletionsReasoningBatch as A, createOpenAIProviderAcceptanceHook as C, measureUtf8AppendBytes as D, log as E, resolvePromptCacheKey as M, throwIfModelStreamAborted as N, parseOpenAICompletionsUsage as O, createModelStreamCooperativeScheduler as S, isOpenAICompletionsThinkingEnabled as T, cleanSchemaForGemini as _, resolveOpenAIProjectedToolsStrictToolFlag as a, reconcileOpenAIResponsesToolChoice as b, extractToolSchemaModelCompat as c, shouldOmitEmptyArrayItems as d, stripUnsupportedSchemaKeywords as f, GEMINI_UNSUPPORTED_SCHEMA_KEYWORDS as g, findLlamacppGbnfSchemaViolations as h, normalizeStrictOpenAIJsonSchema as i, resolveOpenAIClientBaseUrl as j, readOpenAICompletionsContentDeltas as k, normalizeToolParameterSchema as l, cleanSchemaForLlamacppGbnf as m, isStrictOpenAIJsonSchemaCompatible as n, findOpenAIStrictSchemaViolations as o, LLAMACPP_GBNF_MAX_REPETITION_THRESHOLD as p, normalizeOpenAIStrictToolParameters as r, normalizeOpenAIStrictCompatSchema as s, findOpenAIStrictToolProjectionDiagnostics as t, resolveUnsupportedToolSchemaKeywords as u, projectOpenAITools as v, createOpenAIResponseHook as w, GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP as x, reconcileOpenAICompletionsToolChoice as y };
1167
+ export { cleanSchemaForGemini as _, resolveOpenAIProjectedToolsStrictToolFlag as a, extractToolSchemaModelCompat as c, shouldOmitEmptyArrayItems as d, stripUnsupportedSchemaKeywords as f, GEMINI_UNSUPPORTED_SCHEMA_KEYWORDS as g, findLlamacppGbnfSchemaViolations as h, normalizeStrictOpenAIJsonSchema as i, normalizeToolParameterSchema as l, cleanSchemaForLlamacppGbnf as m, isStrictOpenAIJsonSchemaCompatible as n, findOpenAIStrictSchemaViolations as o, LLAMACPP_GBNF_MAX_REPETITION_THRESHOLD as p, normalizeOpenAIStrictToolParameters as r, normalizeOpenAIStrictCompatSchema as s, findOpenAIStrictToolProjectionDiagnostics as t, resolveUnsupportedToolSchemaKeywords as u };
@@ -0,0 +1,38 @@
1
+ import { n as OpenAIToolProjection } from "./openai-tool-projection-793cE3QX.mjs";
2
+ import { TSchema } from "typebox";
3
+ //#region packages/ai/src/providers/openai-tool-schema-compat.d.ts
4
+ /** Repairs recoverable OpenAI tool-schema shapes before canonical normalization. */
5
+ declare function normalizeOpenAIStrictCompatSchema(schema: unknown): TSchema;
6
+ /** Finds schema paths that violate OpenAI strict tool-schema requirements. */
7
+ declare function findOpenAIStrictSchemaViolations(schema: unknown, path: string, options?: {
8
+ requireObjectRoot?: boolean;
9
+ }): string[];
10
+ //#endregion
11
+ //#region packages/ai/src/providers/openai-tool-schema.d.ts
12
+ /**
13
+ * OpenAI strict-tool-schema normalization and diagnostics.
14
+ *
15
+ * Strict schemas need all object properties required and `additionalProperties: false`; model
16
+ * compatibility settings can also remove unsupported schema constructs before strict checks run.
17
+ */
18
+ type ToolSchemaCompatInput = {
19
+ unsupportedToolSchemaKeywords?: unknown;
20
+ omitEmptyArrayItems?: unknown;
21
+ };
22
+ /** Normalizes a tool parameter schema into the OpenAI strict JSON-schema subset. */
23
+ declare function normalizeStrictOpenAIJsonSchema(schema: unknown, modelCompat?: ToolSchemaCompatInput | null): unknown;
24
+ /** Normalizes tool parameters using strict OpenAI rules only when strict mode is active. */
25
+ declare function normalizeOpenAIStrictToolParameters<T>(schema: T, strict: boolean, modelCompat?: ToolSchemaCompatInput | null): T;
26
+ /** Returns whether a schema already satisfies OpenAI strict tool-schema constraints. */
27
+ declare function isStrictOpenAIJsonSchemaCompatible(schema: unknown): boolean;
28
+ type OpenAIStrictToolSchemaDiagnostic = {
29
+ toolIndex: number;
30
+ toolName?: string;
31
+ violations: string[];
32
+ };
33
+ /** Returns strict-schema diagnostics for an already materialized OpenAI tool projection. */
34
+ declare function findOpenAIStrictToolProjectionDiagnostics(projection: OpenAIToolProjection): OpenAIStrictToolSchemaDiagnostic[];
35
+ /** Resolves strict mode for the projected tools that will be emitted in the request payload. */
36
+ declare function resolveOpenAIProjectedToolsStrictToolFlag(projection: OpenAIToolProjection, strict: boolean | null | undefined): boolean | undefined;
37
+ //#endregion
38
+ export { resolveOpenAIProjectedToolsStrictToolFlag as a, normalizeStrictOpenAIJsonSchema as i, isStrictOpenAIJsonSchemaCompatible as n, findOpenAIStrictSchemaViolations as o, normalizeOpenAIStrictToolParameters as r, normalizeOpenAIStrictCompatSchema as s, findOpenAIStrictToolProjectionDiagnostics as t };