@openclaw/ai 2026.9.4 → 2026.9.6

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 (101) hide show
  1. package/README.md +1 -1
  2. package/dist/{anthropic-C4Qu4H0Z.mjs → anthropic-DZQ_7gD1.mjs} +37 -38
  3. package/dist/{anthropic-payload-policy-BZ8umAbk.d.mts → anthropic-payload-policy-DyfwikYJ.d.mts} +4 -4
  4. package/dist/{anthropic-stream-reducer-CILWF7JD.mjs → anthropic-stream-reducer-D6ZI1wwj.mjs} +70 -50
  5. package/dist/{api-registry-ByUwIR0e.d.mts → api-registry-C2T3lTV7.d.mts} +2 -2
  6. package/dist/{assistant-output-tLt4H-iQ.mjs → assistant-output-DM1JBNs1.mjs} +1 -1
  7. package/dist/{azure-openai-responses-BAlqlKKc.mjs → azure-openai-responses-DS86GYzq.mjs} +6 -9
  8. package/dist/{base64-D-su8YVo.mjs → base64-CPmadnUf.mjs} +12 -12
  9. package/dist/credential-redaction-BKv49aiv.d.mts +24 -0
  10. package/dist/{diagnostics-QuErwCIl.mjs → diagnostics-CH8j2wIG.mjs} +139 -7
  11. package/dist/{diagnostics-CPeq9F7y.mjs → diagnostics-DzrF1h4J.mjs} +18 -1
  12. package/dist/diagnostics.d.mts +11 -24
  13. package/dist/diagnostics.mjs +4 -4
  14. package/dist/event-stream-C0nsgbj2.d.mts +1 -0
  15. package/dist/{event-stream-Bt5Y4Pav.d.mts → event-stream-CjnIZZst.d.mts} +1 -1
  16. package/dist/event-stream.d.mts +2 -2
  17. package/dist/expect-lbe3Hgrh.mjs +8 -0
  18. package/dist/{google-DPBAOaOW.mjs → google-BZJFjhuC.mjs} +6 -9
  19. package/dist/{google-messages-6JkpHrhJ.mjs → google-messages-DB7GKkDk.mjs} +3 -3
  20. package/dist/{google-shared-BvBeW9aq.mjs → google-shared-Bok4I6zB.mjs} +13 -13
  21. package/dist/{google-vertex-k-TMCAYD.mjs → google-vertex-3eVNR2qW.mjs} +5 -8
  22. package/dist/{host-4atIX-2V.d.mts → host-DH-Z-LDb.d.mts} +5 -3
  23. package/dist/{host-policy-Zcg_cNz8.mjs → host-policy-DZO3oPPk.mjs} +1 -1
  24. package/dist/{host-B8YfDGd4.mjs → host-yTvBrYM2.mjs} +63 -31
  25. package/dist/{index-DdD3qerf.d.mts → index-C25RT6bP.d.mts} +37 -14
  26. package/dist/index.d.mts +7 -8
  27. package/dist/index.mjs +5 -6
  28. package/dist/internal/anthropic.d.mts +13 -10
  29. package/dist/internal/anthropic.mjs +5 -5
  30. package/dist/internal/openai-completions-compat.d.mts +2 -0
  31. package/dist/internal/openai-completions-compat.mjs +2 -0
  32. package/dist/internal/openai-responses-payload-policy.d.mts +2 -2
  33. package/dist/internal/openai-responses-payload-policy.mjs +2 -2
  34. package/dist/internal/openai.d.mts +24 -53
  35. package/dist/internal/openai.mjs +12 -9
  36. package/dist/internal/runtime.d.mts +6 -8
  37. package/dist/internal/runtime.mjs +6 -10
  38. package/dist/internal/shared.d.mts +7 -5
  39. package/dist/internal/shared.mjs +4 -3
  40. package/dist/internal/tool-schema.d.mts +4 -4
  41. package/dist/internal/tool-schema.mjs +2 -2
  42. package/dist/{mistral-CxUZ1jUb.mjs → mistral-C_13dVBn.mjs} +9 -13
  43. package/dist/{model-transport-url-DKocrEsb.d.mts → model-transport-url-C5f59L3Y.d.mts} +1 -1
  44. package/dist/{openai-chatgpt-responses-CgO6kZfo.mjs → openai-chatgpt-responses-sTxPl4zM.mjs} +150 -83
  45. package/dist/{openai-completions-yJuk7eis.mjs → openai-completions-BO6D_hrB.mjs} +11 -12
  46. package/dist/{openai-prompt-cache-Bds-n_9Q.mjs → openai-completions-compat-CUollwl6.mjs} +5 -50
  47. package/dist/{openai-completions-compat-eHgh5UPE.d.mts → openai-completions-compat-DfJG1wSO.d.mts} +4 -4
  48. package/dist/{openai-completions-stream-Da2vvl-S.mjs → openai-completions-stream-BpuJ0ZOA.mjs} +117 -106
  49. package/dist/{openai-prompt-cache-B4eYo2-I.d.mts → openai-prompt-cache-C4RHdN4n.d.mts} +2 -2
  50. package/dist/openai-prompt-cache-CjV_2IRI.mjs +46 -0
  51. package/dist/{openai-provider-client-S2gCrM2Z.mjs → openai-provider-client-BP8J1aeg.mjs} +2 -2
  52. package/dist/openai-reasoning-effort-ash8dPrd.mjs +243 -0
  53. package/dist/{openai-responses-DaYwH05E.mjs → openai-responses-BJ_IEoMU.mjs} +8 -12
  54. package/dist/{openai-responses-compaction-window-CIhBAkkq.mjs → openai-responses-compaction-window-BiNCT0bS.mjs} +20 -62
  55. package/dist/{openai-responses-contracts-BjBAqAg_.d.mts → openai-responses-contracts-B1ENJFpI.d.mts} +9 -5
  56. package/dist/openai-responses-contracts-DWrfMODE.mjs +81 -0
  57. package/dist/{openai-responses-payload-policy-rLRPsSmB.d.mts → openai-responses-payload-policy-C7GsA1y0.d.mts} +5 -3
  58. package/dist/openai-responses-prompt-observer-internal-DPHWgbBH.mjs +198 -0
  59. package/dist/openai-responses-request-lifecycle-DFuyO1pQ.mjs +36 -0
  60. package/dist/{openai-responses-shared-B8RdBPCv.mjs → openai-responses-shared-DvSqtJ6_.mjs} +859 -581
  61. package/dist/openai-responses-terminal-usage-BNFbvY9f.d.mts +47 -0
  62. package/dist/{openai-tool-schema-CzjyYXun.mjs → openai-tool-schema-D4BMcj2D.mjs} +262 -162
  63. package/dist/{openai-transport-params-9aPuV5YY.mjs → openai-transport-params-DZKOTSfH.mjs} +157 -47
  64. package/dist/{positive-integer-41zhOdcV.mjs → positive-integer-BiUxrd71.mjs} +1 -1
  65. package/dist/{provider-error-BA-v_tKd.mjs → provider-error-CRhW7lkJ.mjs} +139 -44
  66. package/dist/{provider-error-CzNw4BWX.d.mts → provider-error-xumb1V3F.d.mts} +3 -1
  67. package/dist/{provider-options-Ceqv1OKk.d.mts → provider-options-DZYq53lj.d.mts} +12 -7
  68. package/dist/{provider-replay-context-CJ_YvcEW.mjs → provider-replay-context-DPr3w20a.mjs} +1 -1
  69. package/dist/{provider-transcript-transform-V5YzU9zh.mjs → provider-transcript-transform-BTocjCRs.mjs} +1 -1
  70. package/dist/{provider-transport-turn-state-D5EXOFL2.mjs → provider-transport-turn-state-lrXEFkYr.mjs} +1 -1
  71. package/dist/{provider-types-CVjKjsuq.d.mts → provider-types-w1rEqrGP.d.mts} +3 -3
  72. package/dist/provider-types.d.mts +6 -7
  73. package/dist/providers.d.mts +2 -2
  74. package/dist/providers.mjs +10 -10
  75. package/dist/{reasoning-tag-text-partitioner-BcR5pztD.mjs → reasoning-tag-text-partitioner-Di38crhI.mjs} +167 -40
  76. package/dist/{simple-options-BQbb4yQL.mjs → simple-options-np1XPuhm.mjs} +5 -3
  77. package/dist/{usage-cost-BNWbbXav.mjs → src-DwGYYyZp.mjs} +18 -11
  78. package/dist/{stream-first-event-timeout-2hfrquuz.mjs → stream-first-event-timeout-BeptfRL6.mjs} +1 -1
  79. package/dist/{string-normalization-CmLIasuf.mjs → string-normalization-J9ZiLfGO.mjs} +13 -1
  80. package/dist/tool-schema-json-projection-CD9c_fK8.mjs +134 -0
  81. package/dist/{transport-stream-shared-zHll9BxO.mjs → transport-stream-shared-B5RioB_Q.mjs} +16 -24
  82. package/dist/{transport-stream-shared-DNvmoWnv.d.mts → transport-stream-shared-B7Z9oCYg.d.mts} +5 -5
  83. package/dist/{transport-utils-zrYjICLZ.mjs → transport-utils-03Qi0CN2.mjs} +3 -3
  84. package/dist/transports.d.mts +27 -13
  85. package/dist/transports.mjs +168 -462
  86. package/dist/types-DTvddOfm.d.mts +1 -0
  87. package/dist/{types-Ntv5z2g2.d.mts → types-qZFbaDbK.d.mts} +49 -3
  88. package/dist/types.d.mts +6 -7
  89. package/dist/types.mjs +4 -5
  90. package/dist/{validation-B0t_G2H6.d.mts → validation-DhQhmt6t.d.mts} +1 -1
  91. package/dist/{validation-BDzVDnTs.mjs → validation-Dw7cb6BV.mjs} +1 -0
  92. package/dist/validation.d.mts +1 -1
  93. package/dist/validation.mjs +1 -1
  94. package/package.json +11 -6
  95. package/dist/diagnostics-DnPnOui6.d.mts +0 -29
  96. package/dist/event-stream-C3WGFsum.d.mts +0 -1
  97. package/dist/openai-responses-contracts-DDOHA62Y.mjs +0 -245
  98. package/dist/openai-responses-prompt-observer-internal-f8J7wpsk.mjs +0 -32
  99. package/dist/src-DDmEryvj.mjs +0 -2
  100. package/dist/tool-schema-json-projection-ClptDdAO.mjs +0 -82
  101. package/dist/types-DlfwzH3T.d.mts +0 -1
@@ -0,0 +1,47 @@
1
+ import { K as StopReason, a as AssistantMessage, ot as Usage } from "./types-qZFbaDbK.mjs";
2
+ import "./types-DTvddOfm.mjs";
3
+ import OpenAI from "openai";
4
+ //#region packages/ai/src/providers/openai-responses-terminal-usage.d.ts
5
+ /** A known output ceiling can resume sampling after admitted tools have settled. */
6
+ declare function isResponsesOutputLimitToolCallError(message: Pick<AssistantMessage, "stopReason" | "errorCode" | "diagnostics">): boolean;
7
+ /** Terminal usage payload, modeled structurally so untyped callers can pass raw records. */
8
+ type ResponsesTerminalUsagePayload = {
9
+ input_tokens?: number | null;
10
+ output_tokens?: number | null;
11
+ total_tokens?: number | null;
12
+ input_tokens_details?: {
13
+ cached_tokens?: number | null;
14
+ cache_write_tokens?: number | null;
15
+ } | null;
16
+ output_tokens_details?: {
17
+ reasoning_tokens?: number | null;
18
+ } | null;
19
+ };
20
+ /**
21
+ * Split a terminal usage payload into the priced buckets.
22
+ *
23
+ * OpenAI includes cache reads and writes in `input_tokens`, so both are subtracted out of the
24
+ * billable input bucket. `total_tokens` comes from the payload, but never below the sum of the
25
+ * split buckets: proxies routinely omit it (reporting 0 would understate the turn), and a payload
26
+ * whose `cached_tokens` exceeds `input_tokens` clamps the input bucket, leaving the reported total
27
+ * short of what the buckets actually price.
28
+ */
29
+ declare function mapResponsesTerminalUsage(usage: ResponsesTerminalUsagePayload | undefined | null): Pick<Usage, "input" | "output" | "cacheRead" | "cacheWrite" | "contextUsage" | "totalTokens"> | undefined;
30
+ /** Reasoning tokens are reported by the agent path only; the package path does not track them. */
31
+ declare function readResponsesReasoningTokens(usage: ResponsesTerminalUsagePayload | undefined | null): number | undefined;
32
+ /**
33
+ * Resolve the terminal stop reason, including the two overrides every Responses path shares: a
34
+ * content-filtered turn is a provider error rather than a truncated answer, and a turn that
35
+ * produced tool calls reports `toolUse` instead of a plain stop.
36
+ */
37
+ declare function resolveResponsesTerminalStopReason(params: {
38
+ status: OpenAI.Responses.ResponseStatus | undefined;
39
+ terminalEventType?: "response.completed" | "response.incomplete";
40
+ incompleteReason?: string;
41
+ hasToolCall: boolean;
42
+ }): {
43
+ stopReason: StopReason;
44
+ errorMessage?: string;
45
+ };
46
+ //#endregion
47
+ export { resolveResponsesTerminalStopReason as a, readResponsesReasoningTokens as i, isResponsesOutputLimitToolCallError as n, mapResponsesTerminalUsage as r, ResponsesTerminalUsagePayload as t };
@@ -1,8 +1,35 @@
1
1
  import { n as normalizeLowercaseStringOrEmpty } from "./string-coerce-fsri9iCu.mjs";
2
2
  import { o as isRecord } from "./record-coerce-DwRYMj3t.mjs";
3
- import { r as uniqueValues, t as normalizeStringEntries } from "./string-normalization-CmLIasuf.mjs";
3
+ import { i as uniqueValues, t as normalizeStringEntries } from "./string-normalization-J9ZiLfGO.mjs";
4
+ //#region packages/ai/src/providers/schema-walk.ts
5
+ /** Resume child schema walks on a heap stack, never through recursive yield delegation. */
6
+ function evaluateSchemaWalk(walk) {
7
+ const parents = [];
8
+ let current = walk;
9
+ let value;
10
+ try {
11
+ while (true) {
12
+ const step = current.next(value);
13
+ if (!step.done) {
14
+ parents.push(current);
15
+ current = step.value;
16
+ value = void 0;
17
+ continue;
18
+ }
19
+ value = step.value;
20
+ const parent = parents.pop();
21
+ if (!parent) return value;
22
+ current = parent;
23
+ }
24
+ } finally {
25
+ let parent;
26
+ while (parent = parents.pop()) parent.return(void 0);
27
+ }
28
+ }
29
+ //#endregion
4
30
  //#region packages/ai/src/providers/clean-for-gemini.ts
5
31
  const GEMINI_UNSUPPORTED_SCHEMA_KEYWORDS = /* @__PURE__ */ new Set([
32
+ "~optional",
6
33
  "patternProperties",
7
34
  "additionalProperties",
8
35
  "$schema",
@@ -158,89 +185,123 @@ function sanitizeRequiredFields(schema) {
158
185
  else delete schema.required;
159
186
  return schema;
160
187
  }
161
- function cleanSchemaForGeminiWithDefs(schema, defs, refStack) {
188
+ function* cleanSchemaArray(schemas, defs, refStack, ancestors, result) {
189
+ result.length = schemas.length;
190
+ for (let index = 0; index < result.length; index += 1) if (index in schemas) result[index] = yield cleanSchemaForGeminiWithDefs(schemas[index], defs, refStack, ancestors);
191
+ return result;
192
+ }
193
+ function* cleanSchemaForGeminiWithDefs(schema, defs, refStack, ancestors) {
162
194
  if (!schema || typeof schema !== "object") return schema;
163
- if (Array.isArray(schema)) return schema.map((item) => cleanSchemaForGeminiWithDefs(item, defs, refStack));
164
- const obj = schema;
165
- const nextDefs = extendSchemaDefs$1(defs, obj);
166
- const refValue = typeof obj.$ref === "string" ? obj.$ref : void 0;
167
- if (refValue) {
168
- if (refStack?.has(refValue)) return {};
169
- const resolved = tryResolveLocalRef$1(refValue, nextDefs);
170
- if (resolved) {
171
- const nextRefStack = refStack ? new Set(refStack) : /* @__PURE__ */ new Set();
172
- nextRefStack.add(refValue);
173
- const cleaned = cleanSchemaForGeminiWithDefs(resolved, nextDefs, nextRefStack);
174
- if (!cleaned || typeof cleaned !== "object" || Array.isArray(cleaned)) return cleaned;
175
- const result = { ...cleaned };
195
+ if (ancestors.has(schema)) throw new TypeError("Tool schema contains a circular reference.");
196
+ ancestors.add(schema);
197
+ try {
198
+ if (Array.isArray(schema)) {
199
+ const result = [];
200
+ yield cleanSchemaArray(schema, defs, refStack, ancestors, result);
201
+ return result;
202
+ }
203
+ const obj = schema;
204
+ const nextDefs = extendSchemaDefs$1(defs, obj);
205
+ const refValue = typeof obj.$ref === "string" ? obj.$ref : void 0;
206
+ if (refValue) {
207
+ if (refStack?.has(refValue)) return {};
208
+ const resolved = tryResolveLocalRef$1(refValue, nextDefs);
209
+ if (resolved) {
210
+ const nextRefStack = refStack ? new Set(refStack) : /* @__PURE__ */ new Set();
211
+ nextRefStack.add(refValue);
212
+ const cleaned = yield cleanSchemaForGeminiWithDefs(resolved, nextDefs, nextRefStack, /* @__PURE__ */ new Set());
213
+ if (!cleaned || typeof cleaned !== "object" || Array.isArray(cleaned)) return cleaned;
214
+ const result = { ...cleaned };
215
+ copySchemaMeta$1(obj, result);
216
+ return result;
217
+ }
218
+ const result = {};
176
219
  copySchemaMeta$1(obj, result);
177
220
  return result;
178
221
  }
179
- const result = {};
180
- copySchemaMeta$1(obj, result);
181
- return result;
182
- }
183
- const hasAnyOf = "anyOf" in obj && Array.isArray(obj.anyOf);
184
- const hasOneOf = "oneOf" in obj && Array.isArray(obj.oneOf);
185
- let cleanedAnyOf = hasAnyOf ? obj.anyOf.map((variant) => cleanSchemaForGeminiWithDefs(variant, nextDefs, refStack)) : void 0;
186
- let cleanedOneOf = hasOneOf ? obj.oneOf.map((variant) => cleanSchemaForGeminiWithDefs(variant, nextDefs, refStack)) : void 0;
187
- if (hasAnyOf) {
188
- const simplified = simplifyUnionVariants({
189
- obj,
190
- variants: cleanedAnyOf ?? []
191
- });
192
- if (simplified.kind === "simplified") return simplified.value;
193
- cleanedAnyOf = simplified.value;
194
- }
195
- if (hasOneOf) {
196
- const simplified = simplifyUnionVariants({
197
- obj,
198
- variants: cleanedOneOf ?? []
199
- });
200
- if (simplified.kind === "simplified") return simplified.value;
201
- cleanedOneOf = simplified.value;
202
- }
203
- const cleaned = {};
204
- for (const [key, value] of Object.entries(obj)) {
205
- if (GEMINI_UNSUPPORTED_SCHEMA_KEYWORDS.has(key)) continue;
206
- if (key === "const") {
207
- const enumValues = cleanGeminiEnumValues([value]);
208
- if (enumValues) cleaned.enum = enumValues;
209
- continue;
222
+ const hasAnyOf = "anyOf" in obj && Array.isArray(obj.anyOf);
223
+ const hasOneOf = "oneOf" in obj && Array.isArray(obj.oneOf);
224
+ let cleanedAnyOf;
225
+ if (hasAnyOf) {
226
+ const variants = obj.anyOf;
227
+ cleanedAnyOf = [];
228
+ yield cleanSchemaArray(variants, nextDefs, refStack, ancestors, cleanedAnyOf);
210
229
  }
211
- if (key === "enum") {
212
- const enumValues = cleanGeminiEnumValues(value);
213
- if (enumValues) cleaned.enum = enumValues;
214
- continue;
230
+ let cleanedOneOf;
231
+ if (hasOneOf) {
232
+ const variants = obj.oneOf;
233
+ cleanedOneOf = [];
234
+ yield cleanSchemaArray(variants, nextDefs, refStack, ancestors, cleanedOneOf);
215
235
  }
216
- if (key === "required" && Array.isArray(value) && value.length === 0) continue;
217
- if (key === "type" && (hasAnyOf || hasOneOf)) continue;
218
- if (key === "type" && Array.isArray(value) && value.every((entry) => typeof entry === "string")) {
219
- const types = value.filter((entry) => entry !== "null");
220
- cleaned.type = types.length === 1 ? types[0] : types;
221
- continue;
236
+ if (hasAnyOf) {
237
+ const simplified = simplifyUnionVariants({
238
+ obj,
239
+ variants: cleanedAnyOf ?? []
240
+ });
241
+ if (simplified.kind === "simplified") return simplified.value;
242
+ cleanedAnyOf = simplified.value;
222
243
  }
223
- if (key === "properties") {
224
- if (value && typeof value === "object" && !Array.isArray(value)) cleaned[key] = Object.fromEntries(Object.entries(value).map(([k, v]) => [k, cleanSchemaForGeminiWithDefs(v, nextDefs, refStack)]));
225
- else cleaned[key] = {};
226
- } else if (key === "items" && value) {
227
- if (Array.isArray(value)) cleaned[key] = value.map((entry) => cleanSchemaForGeminiWithDefs(entry, nextDefs, refStack));
228
- else if (typeof value === "object") cleaned[key] = cleanSchemaForGeminiWithDefs(value, nextDefs, refStack);
229
- else cleaned[key] = value;
230
- } else if (key === "anyOf" && Array.isArray(value)) cleaned[key] = cleanedAnyOf ?? value.map((variant) => cleanSchemaForGeminiWithDefs(variant, nextDefs, refStack));
231
- else if (key === "oneOf" && Array.isArray(value)) cleaned[key] = cleanedOneOf ?? value.map((variant) => cleanSchemaForGeminiWithDefs(variant, nextDefs, refStack));
232
- else if (key === "allOf" && Array.isArray(value)) cleaned[key] = value.map((variant) => cleanSchemaForGeminiWithDefs(variant, nextDefs, refStack));
233
- else cleaned[key] = value;
234
- }
235
- if (cleaned.anyOf && Array.isArray(cleaned.anyOf)) {
236
- const flattened = flattenUnionFallback(cleaned, cleaned.anyOf);
237
- if (flattened) return sanitizeRequiredFields(flattened);
238
- }
239
- if (cleaned.oneOf && Array.isArray(cleaned.oneOf)) {
240
- const flattened = flattenUnionFallback(cleaned, cleaned.oneOf);
241
- if (flattened) return sanitizeRequiredFields(flattened);
244
+ if (hasOneOf) {
245
+ const simplified = simplifyUnionVariants({
246
+ obj,
247
+ variants: cleanedOneOf ?? []
248
+ });
249
+ if (simplified.kind === "simplified") return simplified.value;
250
+ cleanedOneOf = simplified.value;
251
+ }
252
+ const cleaned = {};
253
+ for (const [key, value] of Object.entries(obj)) {
254
+ if (GEMINI_UNSUPPORTED_SCHEMA_KEYWORDS.has(key)) continue;
255
+ if (key === "const") {
256
+ const enumValues = cleanGeminiEnumValues([value]);
257
+ if (enumValues) cleaned.enum = enumValues;
258
+ continue;
259
+ }
260
+ if (key === "enum") {
261
+ const enumValues = cleanGeminiEnumValues(value);
262
+ if (enumValues) cleaned.enum = enumValues;
263
+ continue;
264
+ }
265
+ if (key === "required" && Array.isArray(value) && value.length === 0) continue;
266
+ if (key === "type" && (hasAnyOf || hasOneOf)) continue;
267
+ if (key === "type" && Array.isArray(value) && value.every((entry) => typeof entry === "string")) {
268
+ const types = value.filter((entry) => entry !== "null");
269
+ cleaned.type = types.length === 1 ? types[0] : types;
270
+ continue;
271
+ }
272
+ if (key === "properties") {
273
+ if (value && typeof value === "object" && !Array.isArray(value)) {
274
+ const entries = Object.entries(value);
275
+ for (const entry of entries) entry[1] = yield cleanSchemaForGeminiWithDefs(entry[1], nextDefs, refStack, ancestors);
276
+ cleaned[key] = Object.fromEntries(entries);
277
+ } else cleaned[key] = {};
278
+ } else if (key === "items" && value) {
279
+ if (Array.isArray(value)) {
280
+ const result = [];
281
+ yield cleanSchemaArray(value, nextDefs, refStack, ancestors, result);
282
+ cleaned[key] = result;
283
+ } else if (typeof value === "object") cleaned[key] = yield cleanSchemaForGeminiWithDefs(value, nextDefs, refStack, ancestors);
284
+ else cleaned[key] = value;
285
+ } else if (key === "anyOf" && Array.isArray(value)) cleaned[key] = cleanedAnyOf;
286
+ else if (key === "oneOf" && Array.isArray(value)) cleaned[key] = cleanedOneOf;
287
+ else if (key === "allOf" && Array.isArray(value)) {
288
+ const result = [];
289
+ yield cleanSchemaArray(value, nextDefs, refStack, ancestors, result);
290
+ cleaned[key] = result;
291
+ } else cleaned[key] = value;
292
+ }
293
+ if (cleaned.anyOf && Array.isArray(cleaned.anyOf)) {
294
+ const flattened = flattenUnionFallback(cleaned, cleaned.anyOf);
295
+ if (flattened) return sanitizeRequiredFields(flattened);
296
+ }
297
+ if (cleaned.oneOf && Array.isArray(cleaned.oneOf)) {
298
+ const flattened = flattenUnionFallback(cleaned, cleaned.oneOf);
299
+ if (flattened) return sanitizeRequiredFields(flattened);
300
+ }
301
+ return sanitizeRequiredFields(cleaned);
302
+ } finally {
303
+ ancestors.delete(schema);
242
304
  }
243
- return sanitizeRequiredFields(cleaned);
244
305
  }
245
306
  /**
246
307
  * Last-resort flattening for anyOf/oneOf arrays that could not be simplified
@@ -272,9 +333,7 @@ function flattenUnionFallback(obj, variants) {
272
333
  return merged;
273
334
  }
274
335
  function cleanSchemaForGemini(schema) {
275
- if (!schema || typeof schema !== "object") return schema;
276
- if (Array.isArray(schema)) return schema.map(cleanSchemaForGemini);
277
- return cleanSchemaForGeminiWithDefs(schema, extendSchemaDefs$1(void 0, schema), void 0);
336
+ return evaluateSchemaWalk(cleanSchemaForGeminiWithDefs(schema, void 0, void 0, /* @__PURE__ */ new Set()));
278
337
  }
279
338
  //#endregion
280
339
  //#region packages/ai/src/providers/clean-for-llamacpp-gbnf.ts
@@ -395,29 +454,96 @@ const SCHEMA_ARRAY_KEYS$1 = /* @__PURE__ */ new Set([
395
454
  "oneOf",
396
455
  "prefixItems"
397
456
  ]);
398
- /** Recursively remove schema keywords unsupported by a target provider/tool surface. */
399
- function stripUnsupportedSchemaKeywords(schema, unsupportedKeywords) {
457
+ function* stripSchemaArray(schemas, unsupportedKeywords, ancestors, result) {
458
+ result.length = schemas.length;
459
+ for (let index = 0; index < result.length; index += 1) if (index in schemas) result[index] = yield stripSchemaKeywords(schemas[index], unsupportedKeywords, ancestors);
460
+ return result;
461
+ }
462
+ function* stripSchemaKeywords(schema, unsupportedKeywords, ancestors) {
400
463
  if (!schema || typeof schema !== "object") return schema;
401
- if (Array.isArray(schema)) return schema.map((entry) => stripUnsupportedSchemaKeywords(entry, unsupportedKeywords));
402
- const obj = schema;
403
- const cleaned = {};
404
- for (const [key, value] of Object.entries(obj)) {
405
- if (unsupportedKeywords.has(key)) continue;
406
- if (SCHEMA_MAP_KEYS$1.has(key) && value && typeof value === "object" && !Array.isArray(value)) {
407
- cleaned[key] = Object.fromEntries(Object.entries(value).map(([childKey, childValue]) => [childKey, stripUnsupportedSchemaKeywords(childValue, unsupportedKeywords)]));
408
- continue;
409
- }
410
- if (SCHEMA_ARRAY_KEYS$1.has(key) && Array.isArray(value)) {
411
- cleaned[key] = value.map((entry) => stripUnsupportedSchemaKeywords(entry, unsupportedKeywords));
412
- continue;
464
+ if (ancestors.has(schema)) throw new TypeError("Tool schema contains a circular reference.");
465
+ ancestors.add(schema);
466
+ try {
467
+ if (Array.isArray(schema)) {
468
+ const result = [];
469
+ yield stripSchemaArray(schema, unsupportedKeywords, ancestors, result);
470
+ return result;
413
471
  }
414
- if (SCHEMA_OBJECT_KEYS$1.has(key) && value && typeof value === "object") {
415
- cleaned[key] = stripUnsupportedSchemaKeywords(value, unsupportedKeywords);
416
- continue;
472
+ const obj = schema;
473
+ const cleaned = {};
474
+ for (const [key, value] of Object.entries(obj)) {
475
+ if (unsupportedKeywords.has(key)) continue;
476
+ if (SCHEMA_MAP_KEYS$1.has(key) && value && typeof value === "object" && !Array.isArray(value)) {
477
+ const entries = Object.entries(value);
478
+ for (const entry of entries) entry[1] = yield stripSchemaKeywords(entry[1], unsupportedKeywords, ancestors);
479
+ cleaned[key] = Object.fromEntries(entries);
480
+ } else if (SCHEMA_ARRAY_KEYS$1.has(key) && Array.isArray(value)) {
481
+ const result = [];
482
+ yield stripSchemaArray(value, unsupportedKeywords, ancestors, result);
483
+ cleaned[key] = result;
484
+ } else if (SCHEMA_OBJECT_KEYS$1.has(key) && value && typeof value === "object") cleaned[key] = yield stripSchemaKeywords(value, unsupportedKeywords, ancestors);
485
+ else cleaned[key] = value;
417
486
  }
418
- cleaned[key] = value;
487
+ return cleaned;
488
+ } finally {
489
+ ancestors.delete(schema);
419
490
  }
420
- return cleaned;
491
+ }
492
+ /** Remove schema keywords unsupported by a target provider/tool surface. */
493
+ function stripUnsupportedSchemaKeywords(schema, unsupportedKeywords) {
494
+ return evaluateSchemaWalk(stripSchemaKeywords(schema, unsupportedKeywords, /* @__PURE__ */ new Set()));
495
+ }
496
+ //#endregion
497
+ //#region packages/ai/src/providers/tool-schema-normalization-cache.ts
498
+ let preparedSchemas;
499
+ /** Only synchronous conversion owns these fresh projections; no facts survive its return. */
500
+ function withPreparedToolSchemaNormalization(schemas, convert) {
501
+ const previous = preparedSchemas;
502
+ preparedSchemas = schemas;
503
+ try {
504
+ return convert();
505
+ } finally {
506
+ preparedSchemas = previous;
507
+ }
508
+ }
509
+ function createBoundedSchemaCache(maxEntries) {
510
+ const schemas = /* @__PURE__ */ new WeakMap();
511
+ return {
512
+ get(source, key) {
513
+ return schemas.get(source)?.find((entry) => entry.key === key)?.value;
514
+ },
515
+ remember(source, key, value) {
516
+ const entries = schemas.get(source) ?? [];
517
+ schemas.set(source, [{
518
+ key,
519
+ value
520
+ }, ...entries.filter((entry) => entry.key !== key)].slice(0, maxEntries));
521
+ return value;
522
+ }
523
+ };
524
+ }
525
+ /** Prepared variants cannot evict direct callers' identity-preserving cache entries. */
526
+ function createToolSchemaNormalizationCache(maxEntries) {
527
+ const directCache = createBoundedSchemaCache(maxEntries);
528
+ const preparedCache = createBoundedSchemaCache(maxEntries);
529
+ return {
530
+ get(source, key) {
531
+ const prepared = preparedSchemas?.get(source);
532
+ if (!prepared) return directCache.get(source, key);
533
+ const entry = preparedCache.get(prepared.source, key);
534
+ return entry?.inputJson === prepared.inputJson ? JSON.parse(entry.outputJson) : void 0;
535
+ },
536
+ remember(source, key, value) {
537
+ const prepared = preparedSchemas?.get(source);
538
+ if (!prepared) return directCache.remember(source, key, value);
539
+ const outputJson = JSON.stringify(value);
540
+ if (outputJson !== void 0) preparedCache.remember(prepared.source, key, {
541
+ inputJson: prepared.inputJson,
542
+ outputJson
543
+ });
544
+ return value;
545
+ }
546
+ };
421
547
  }
422
548
  //#endregion
423
549
  //#region packages/ai/src/providers/agent-tools-parameter-schema.ts
@@ -444,8 +570,7 @@ function resolveUnsupportedToolSchemaKeywords(modelOrCompat) {
444
570
  function shouldOmitEmptyArrayItems(modelOrCompat) {
445
571
  return extractToolSchemaModelCompat(modelOrCompat)?.omitEmptyArrayItems === true;
446
572
  }
447
- const MAX_TOOL_PARAMETER_SCHEMA_CACHE_ENTRIES_PER_SCHEMA = 8;
448
- const toolParameterSchemaCache = /* @__PURE__ */ new WeakMap();
573
+ const toolParameterSchemaCache = createToolSchemaNormalizationCache(8);
449
574
  function resolveToolParameterSchemaCacheKey(options) {
450
575
  const normalizedProvider = normalizeLowercaseStringOrEmpty(options?.modelProvider);
451
576
  const normalizedModelId = normalizeLowercaseStringOrEmpty(options?.modelId);
@@ -460,17 +585,6 @@ function resolveToolParameterSchemaCacheKey(options) {
460
585
  omitEmptyArrayItems
461
586
  ]);
462
587
  }
463
- function getCachedToolParameterSchema(schema, key) {
464
- return toolParameterSchemaCache.get(schema)?.find((entry) => entry.key === key)?.value;
465
- }
466
- function rememberCachedToolParameterSchema(schema, key, value) {
467
- const entries = toolParameterSchemaCache.get(schema) ?? [];
468
- toolParameterSchemaCache.set(schema, [{
469
- key,
470
- value
471
- }, ...entries.filter((entry) => entry.key !== key)].slice(0, MAX_TOOL_PARAMETER_SCHEMA_CACHE_ENTRIES_PER_SCHEMA));
472
- return value;
473
- }
474
588
  function isGeminiModelId(modelId) {
475
589
  return /(?:^|[/:])gemini(?:$|[-/:.])/.test(modelId);
476
590
  }
@@ -570,7 +684,8 @@ function normalizeArraySchemaItems(schema, mode) {
570
684
  }
571
685
  let next = value;
572
686
  if (SCHEMA_MAP_KEYS.has(key) && isRecord(value)) {
573
- const entries = Object.entries(value).map(([entryKey, entry]) => [entryKey, normalizeArraySchemaItems(entry, mode)]);
687
+ const entries = Object.entries(value);
688
+ for (const entry of entries) entry[1] = normalizeArraySchemaItems(entry[1], mode);
574
689
  if (entries.some(([entryKey, entry]) => entry !== value[entryKey])) next = Object.fromEntries(entries);
575
690
  } else if (SCHEMA_OBJECT_KEYS.has(key) || SCHEMA_ARRAY_KEYS.has(key)) {
576
691
  const valueMode = SCHEMA_OBJECT_KEYS.has(key) || Array.isArray(value) ? mode : "add";
@@ -699,7 +814,9 @@ function inlineLocalSchemaRefsWithDefs(schema, defs, refStack, state, rootDocume
699
814
  continue;
700
815
  }
701
816
  if (SCHEMA_MAP_KEYS.has(key) && isRecord(value)) {
702
- setOwnSchemaProperty(result, key, Object.fromEntries(Object.entries(value).map(([entryKey, entryValue]) => [entryKey, inlineLocalSchemaRefsWithDefs(entryValue, nextDefs, refStack, state, rootDocument)])));
817
+ const entries = Object.entries(value);
818
+ for (const entry of entries) entry[1] = inlineLocalSchemaRefsWithDefs(entry[1], nextDefs, refStack, state, rootDocument);
819
+ setOwnSchemaProperty(result, key, Object.fromEntries(entries));
703
820
  continue;
704
821
  }
705
822
  if (SCHEMA_OBJECT_KEYS.has(key) && isRecord(value)) {
@@ -722,7 +839,8 @@ function inlineLocalSchemaRefsWithDefs(schema, defs, refStack, state, rootDocume
722
839
  /** Inline local $ref pointers so providers receive self-contained tool schemas. */
723
840
  function inlineLocalToolSchemaRefs(schema) {
724
841
  if (!schema || typeof schema !== "object") return schema;
725
- return inlineLocalSchemaRefsWithDefs(schema, extendSchemaDefs(void 0, schema), void 0, { unresolvedLocalRefs: false }, schema);
842
+ const schemaRecord = schema;
843
+ return inlineLocalSchemaRefsWithDefs(schema, Array.isArray(schema) ? extendSchemaDefs(void 0, schemaRecord) : void 0, void 0, { unresolvedLocalRefs: false }, schema);
726
844
  }
727
845
  const OPENAPI_SCHEMA_ANNOTATION_KEYS = /* @__PURE__ */ new Set([
728
846
  "discriminator",
@@ -774,46 +892,40 @@ function normalizeOpenApiSchemaKeywords(schema) {
774
892
  if (!isRecord(schema)) return schema;
775
893
  let changed = false;
776
894
  const nullable = schema.nullable === true;
777
- const normalized = {};
778
- for (const [key, value] of Object.entries(schema)) {
895
+ const entries = Object.entries(schema);
896
+ let normalized;
897
+ for (const [key, value] of entries) {
779
898
  if (key === "nullable" || OPENAPI_SCHEMA_ANNOTATION_KEYS.has(key)) {
899
+ normalized ??= Object.fromEntries(entries);
900
+ delete normalized[key];
780
901
  changed = true;
781
902
  continue;
782
903
  }
783
- if (SCHEMA_LITERAL_KEYS.has(key)) {
784
- normalized[key] = value;
785
- continue;
786
- }
904
+ if (SCHEMA_LITERAL_KEYS.has(key) || key === "components") continue;
905
+ let next = value;
787
906
  if (SCHEMA_MAP_KEYS.has(key) && isRecord(value)) {
788
907
  let mapChanged = false;
789
- const next = Object.fromEntries(Object.entries(value).map(([entryKey, entryValue]) => {
790
- const nextEntry = normalizeOpenApiSchemaKeywords(entryValue);
791
- mapChanged ||= nextEntry !== entryValue;
792
- return [entryKey, nextEntry];
793
- }));
794
- normalized[key] = mapChanged ? next : value;
795
- changed ||= mapChanged;
796
- continue;
797
- }
798
- if (key === "components") {
799
- normalized[key] = value;
908
+ const mapEntries = Object.entries(value);
909
+ for (const entry of mapEntries) {
910
+ const nextEntry = normalizeOpenApiSchemaKeywords(entry[1]);
911
+ mapChanged ||= nextEntry !== entry[1];
912
+ entry[1] = nextEntry;
913
+ }
914
+ next = mapChanged ? Object.fromEntries(mapEntries) : value;
915
+ } else if (SCHEMA_OBJECT_KEYS.has(key) && isRecord(value)) next = normalizeOpenApiSchemaKeywords(value);
916
+ else if (SCHEMA_ARRAY_KEYS.has(key) && Array.isArray(value)) {
917
+ const nextEntries = value.map(normalizeOpenApiSchemaKeywords);
918
+ (normalized ??= Object.fromEntries(entries))[key] = nextEntries;
919
+ changed ||= nextEntries.some((entry, index) => entry !== value[index]);
800
920
  continue;
801
921
  }
802
- if (SCHEMA_OBJECT_KEYS.has(key) && isRecord(value)) {
803
- const next = normalizeOpenApiSchemaKeywords(value);
804
- normalized[key] = next;
805
- changed ||= next !== value;
806
- continue;
807
- }
808
- if (SCHEMA_ARRAY_KEYS.has(key) && Array.isArray(value)) {
809
- const next = value.map(normalizeOpenApiSchemaKeywords);
810
- normalized[key] = next;
811
- changed ||= next.some((entry, index) => entry !== value[index]);
812
- continue;
922
+ if (next !== value) {
923
+ (normalized ??= Object.fromEntries(entries))[key] = next;
924
+ changed = true;
813
925
  }
814
- setOwnSchemaProperty(normalized, key, value);
815
926
  }
816
927
  if (nullable) {
928
+ normalized ??= Object.fromEntries(entries);
817
929
  if (hasOpenApiComposition(normalized)) return wrapNullableComposedSchema(normalized);
818
930
  if ("type" in normalized) {
819
931
  const nextType = appendNullSchemaType(normalized.type);
@@ -821,7 +933,7 @@ function normalizeOpenApiSchemaKeywords(schema) {
821
933
  }
822
934
  if (Array.isArray(normalized.enum) && !normalized.enum.includes(null)) normalized.enum = [...normalized.enum, null];
823
935
  }
824
- return changed || nullable ? normalized : schema;
936
+ return changed || nullable ? normalized ?? schema : schema;
825
937
  }
826
938
  function normalizeToolParameterSchemaUncached(schema, options) {
827
939
  const inlinedSchema = normalizeOpenApiSchemaKeywords(inlineLocalToolSchemaRefs(schema));
@@ -897,9 +1009,9 @@ function normalizeToolParameterSchemaUncached(schema, options) {
897
1009
  function normalizeToolParameterSchema(schema, options) {
898
1010
  if (!schema || typeof schema !== "object") return normalizeToolParameterSchemaUncached(schema, options);
899
1011
  const cacheKey = resolveToolParameterSchemaCacheKey(options);
900
- const cached = getCachedToolParameterSchema(schema, cacheKey);
1012
+ const cached = toolParameterSchemaCache.get(schema, cacheKey);
901
1013
  if (cached) return cached;
902
- return rememberCachedToolParameterSchema(schema, cacheKey, normalizeToolParameterSchemaUncached(schema, options));
1014
+ return toolParameterSchemaCache.remember(schema, cacheKey, normalizeToolParameterSchemaUncached(schema, options));
903
1015
  }
904
1016
  //#endregion
905
1017
  //#region packages/ai/src/providers/openai-tool-schema-compat.ts
@@ -1048,8 +1160,7 @@ function findOpenAIStrictSchemaViolations(schema, path, options) {
1048
1160
  *
1049
1161
  * Caches normalized object inputs by provider compatibility so repeated inventory builds preserve identity.
1050
1162
  */
1051
- const MAX_STRICT_SCHEMA_CACHE_ENTRIES_PER_SCHEMA = 8;
1052
- const strictOpenAISchemaCache = /* @__PURE__ */ new WeakMap();
1163
+ const strictOpenAISchemaCache = createToolSchemaNormalizationCache(8);
1053
1164
  function resolveToolSchemaModelCompat(compat) {
1054
1165
  if (!compat) return;
1055
1166
  const unsupportedToolSchemaKeywords = Array.isArray(compat.unsupportedToolSchemaKeywords) ? compat.unsupportedToolSchemaKeywords.filter((keyword) => typeof keyword === "string") : [];
@@ -1063,25 +1174,14 @@ function resolveStrictOpenAISchemaCacheKey(modelCompat) {
1063
1174
  const compat = resolveToolSchemaModelCompat(modelCompat);
1064
1175
  return JSON.stringify([[...compat?.unsupportedToolSchemaKeywords ?? []].toSorted(), shouldOmitEmptyArrayItems(compat)]);
1065
1176
  }
1066
- function readCachedStrictOpenAISchema(schema, key) {
1067
- return strictOpenAISchemaCache.get(schema)?.find((entry) => entry.key === key)?.value;
1068
- }
1069
- function rememberStrictOpenAISchema(schema, key, value) {
1070
- const entries = strictOpenAISchemaCache.get(schema) ?? [];
1071
- strictOpenAISchemaCache.set(schema, [{
1072
- key,
1073
- value
1074
- }, ...entries.filter((entry) => entry.key !== key)].slice(0, MAX_STRICT_SCHEMA_CACHE_ENTRIES_PER_SCHEMA));
1075
- return value;
1076
- }
1077
1177
  /** Normalizes a tool parameter schema into the OpenAI strict JSON-schema subset. */
1078
1178
  function normalizeStrictOpenAIJsonSchema(schema, modelCompat) {
1079
1179
  const schemaInput = schema ?? {};
1080
1180
  if (!schemaInput || typeof schemaInput !== "object") return normalizeStrictOpenAIJsonSchemaRecursive(normalizeToolParameterSchema(schemaInput, { modelCompat: resolveToolSchemaModelCompat(modelCompat) }), 0);
1081
1181
  const cacheKey = resolveStrictOpenAISchemaCacheKey(modelCompat);
1082
- const cached = readCachedStrictOpenAISchema(schemaInput, cacheKey);
1182
+ const cached = strictOpenAISchemaCache.get(schemaInput, cacheKey);
1083
1183
  if (cached !== void 0) return cached;
1084
- return rememberStrictOpenAISchema(schemaInput, cacheKey, normalizeStrictOpenAIJsonSchemaRecursive(normalizeToolParameterSchema(schemaInput, { modelCompat: resolveToolSchemaModelCompat(modelCompat) }), 0));
1184
+ return strictOpenAISchemaCache.remember(schemaInput, cacheKey, normalizeStrictOpenAIJsonSchemaRecursive(normalizeToolParameterSchema(schemaInput, { modelCompat: resolveToolSchemaModelCompat(modelCompat) }), 0));
1085
1185
  }
1086
1186
  function normalizeStrictOpenAIJsonSchemaRecursive(schema, depth) {
1087
1187
  if (Array.isArray(schema)) {
@@ -1164,4 +1264,4 @@ function resolveOpenAIProjectedToolsStrictToolFlag(projection, strict) {
1164
1264
  return projection.tools.every((tool) => isStrictOpenAIJsonSchemaCompatible(tool.parameters));
1165
1265
  }
1166
1266
  //#endregion
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 };
1267
+ export { GEMINI_UNSUPPORTED_SCHEMA_KEYWORDS as _, resolveOpenAIProjectedToolsStrictToolFlag as a, extractToolSchemaModelCompat as c, shouldOmitEmptyArrayItems as d, withPreparedToolSchemaNormalization as f, findLlamacppGbnfSchemaViolations as g, cleanSchemaForLlamacppGbnf as h, normalizeStrictOpenAIJsonSchema as i, normalizeToolParameterSchema as l, LLAMACPP_GBNF_MAX_REPETITION_THRESHOLD as m, isStrictOpenAIJsonSchemaCompatible as n, findOpenAIStrictSchemaViolations as o, stripUnsupportedSchemaKeywords as p, normalizeOpenAIStrictToolParameters as r, normalizeOpenAIStrictCompatSchema as s, findOpenAIStrictToolProjectionDiagnostics as t, resolveUnsupportedToolSchemaKeywords as u, cleanSchemaForGemini as v };