@openclaw/ai 2026.9.5 → 2026.9.7
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.
- package/dist/{anthropic-COtDvgtt.mjs → anthropic-Cw2pgccz.mjs} +59 -88
- package/dist/{anthropic-payload-policy-5Erq1Nzy.d.mts → anthropic-payload-policy-NIPVYXPq.d.mts} +8 -6
- package/dist/{anthropic-stream-reducer-BvdYYWL8.mjs → anthropic-stream-reducer-D9MCkl8Z.mjs} +194 -247
- package/dist/{api-registry-Ba2Cv-ut.d.mts → api-registry-D-nbmSqr.d.mts} +2 -2
- package/dist/{azure-openai-responses-YrgnD583.mjs → azure-openai-responses-BwT3-X8P.mjs} +22 -33
- package/dist/{base64-BQOzsvUH.mjs → base64-C1PsYcRQ.mjs} +22 -16
- package/dist/{diagnostics-Dm4bisWG.mjs → diagnostics-CJaB6g8J.mjs} +55 -10
- package/dist/{diagnostics-CPeq9F7y.mjs → diagnostics-DzrF1h4J.mjs} +18 -1
- package/dist/diagnostics.d.mts +11 -5
- package/dist/diagnostics.mjs +4 -4
- package/dist/{env-api-keys-bktO00EJ.mjs → env-api-keys-CyX4VKGO.mjs} +7 -5
- package/dist/event-stream-CMQfX_yr.d.mts +1 -0
- package/dist/{event-stream-CCoa-qSI.d.mts → event-stream-DOPFYVqs.d.mts} +2 -2
- package/dist/{event-stream-D8PARQfL.mjs → event-stream-vd9UnCAU.mjs} +10 -0
- package/dist/event-stream.d.mts +2 -2
- package/dist/event-stream.mjs +1 -1
- package/dist/{google-BuhpRO9r.mjs → google-BfapkS_K.mjs} +8 -11
- package/dist/google-interactions-DW3iXzjc.mjs +574 -0
- package/dist/{google-messages-CyWnYlh0.mjs → google-messages-CtjVtVot.mjs} +35 -71
- package/dist/{google-shared-BT5ZeNer.mjs → google-shared-Y2YfotEu.mjs} +43 -47
- package/dist/{google-vertex-C7EplRvt.mjs → google-vertex-Dov4kBWu.mjs} +16 -30
- package/dist/{host-B4MeUNBc.mjs → host-CHi3X87F.mjs} +64 -189
- package/dist/{host-policy-DUnXSx0I.mjs → host-policy-BOAwRg_M.mjs} +2 -14
- package/dist/{host-FZ1RA_qD.d.mts → host-rxlNaBwm.d.mts} +9 -3
- package/dist/{index-DaF2QbwS.d.mts → index-D6KsSE74.d.mts} +57 -9
- package/dist/index.d.mts +7 -7
- package/dist/index.mjs +7 -7
- package/dist/internal/anthropic.d.mts +13 -8
- package/dist/internal/anthropic.mjs +5 -5
- package/dist/internal/openai-completions-compat.d.mts +1 -1
- package/dist/internal/openai-completions-compat.mjs +1 -1
- package/dist/internal/openai-responses-payload-policy.d.mts +1 -1
- package/dist/internal/openai-responses-payload-policy.mjs +2 -2
- package/dist/internal/openai.d.mts +46 -9
- package/dist/internal/openai.mjs +13 -12
- package/dist/internal/runtime.d.mts +31 -70
- package/dist/internal/runtime.mjs +11 -66
- package/dist/internal/shared.d.mts +16 -13
- package/dist/internal/shared.mjs +6 -5
- package/dist/internal/tool-schema.d.mts +2 -2
- package/dist/internal/tool-schema.mjs +2 -2
- package/dist/{mistral-moA-mbwl.mjs → mistral-RS6mboC-.mjs} +46 -93
- package/dist/{model-transport-url-DKocrEsb.d.mts → model-transport-url-C5f59L3Y.d.mts} +1 -1
- package/dist/{openai-chatgpt-responses-DWID3EFO.mjs → openai-chatgpt-responses-CYbidtrn.mjs} +118 -99
- package/dist/{openai-completions-DJ1Vm-CD.mjs → openai-completions-D14ihPYk.mjs} +14 -12
- package/dist/{openai-completions-compat-CkwdxTZx.mjs → openai-completions-compat-BOVWBZDn.mjs} +3 -5
- package/dist/{openai-completions-compat-JE7gqxb9.d.mts → openai-completions-compat-qJjmqQ71.d.mts} +3 -3
- package/dist/{openai-completions-stream-Bu98b0Hv.mjs → openai-completions-stream-CDCuw3DP.mjs} +124 -183
- package/dist/{openai-prompt-cache-CJ_xEevu.d.mts → openai-prompt-cache-CouErLh7.d.mts} +2 -2
- package/dist/{openai-prompt-cache-1wfaIszn.mjs → openai-prompt-cache-D2V7MqR7.mjs} +1 -1
- package/dist/{openai-provider-client-DPo0Hmak.mjs → openai-provider-client-CwfsGBbA.mjs} +2 -2
- package/dist/{openai-reasoning-effort-NlFZmfEu.mjs → openai-reasoning-effort-ConhwkeX.mjs} +14 -5
- package/dist/{openai-responses-BejZzQCP.mjs → openai-responses-CKCBEc2W.mjs} +12 -11
- package/dist/openai-responses-compaction-replay-DiYn-gFM.d.mts +12 -0
- package/dist/{openai-responses-compaction-window-D6P5oZP5.mjs → openai-responses-compaction-window-UNK1GDpy.mjs} +5 -5
- package/dist/{openai-responses-contracts-DWrfMODE.mjs → openai-responses-contracts-CLxnqS9p.mjs} +1 -1
- package/dist/{openai-responses-contracts-Dflvrfa8.d.mts → openai-responses-contracts-D1iZ0njF.d.mts} +4 -4
- package/dist/{openai-responses-prompt-observer-internal-C15_-OwV.mjs → openai-responses-prompt-observer-internal-iAqLb4tk.mjs} +16 -13
- package/dist/openai-responses-request-lifecycle-Fsag-IGZ.mjs +36 -0
- package/dist/{openai-responses-shared-CwsziD_m.mjs → openai-responses-shared-DL4ulQn7.mjs} +838 -577
- package/dist/{openai-responses-terminal-usage-Dl3J6zrf.d.mts → openai-responses-terminal-usage-BE7lf7nW.d.mts} +2 -2
- package/dist/{openai-stop-reason-Drnn_6Qj.mjs → openai-stop-reason-8s70vDXj.mjs} +2 -12
- package/dist/{openai-tool-schema-ynZBgqW-.d.mts → openai-tool-schema-a5ysBBga.d.mts} +0 -6
- package/dist/{openai-tool-schema-BO8rwyAD.mjs → openai-tool-schema-vsl-cE-n.mjs} +365 -429
- package/dist/{openai-transport-params-DQeuAvBl.mjs → openai-transport-params-BwlpzX-2.mjs} +61 -106
- package/dist/{positive-integer-DtjCkbue.mjs → positive-integer-CjN5OJbH.mjs} +1 -1
- package/dist/{provider-error-DDqw9Qda.mjs → provider-error-CwT_j2v0.mjs} +82 -10
- package/dist/{provider-error-CzNw4BWX.d.mts → provider-error-xumb1V3F.d.mts} +3 -1
- package/dist/{provider-options-DprLsWh9.d.mts → provider-options-Df7ov0K1.d.mts} +6 -4
- package/dist/{provider-replay-context-CnUSOwhr.mjs → provider-replay-context-DsyI5jOP.mjs} +1 -1
- package/dist/{provider-transcript-transform-BsRAhuWJ.mjs → provider-transcript-transform-JbFbHV8h.mjs} +17 -2
- package/dist/{provider-transport-turn-state-CkGToCD2.mjs → provider-transport-turn-state-BheUi_hl.mjs} +1 -1
- package/dist/{provider-types-CAKRC7N5.d.mts → provider-types-d4XnoZMd.d.mts} +3 -3
- package/dist/provider-types.d.mts +6 -6
- package/dist/providers.d.mts +2 -2
- package/dist/providers.mjs +15 -11
- package/dist/{reasoning-tag-text-partitioner-Dy9IO8Dc.mjs → reasoning-tag-text-partitioner-B6FIIBt6.mjs} +193 -98
- package/dist/{record-coerce-DwRYMj3t.mjs → record-coerce-CNDovvft.mjs} +1 -1
- package/dist/simple-options-CGAkCwtM.mjs +349 -0
- package/dist/{src-DeKjbE8I.mjs → src-H4aXcFuX.mjs} +53 -26
- package/dist/{stream-CREqxHgU.mjs → stream-DDsCBgd-.mjs} +1 -7
- package/dist/{stream-first-event-timeout-C9ZadkJW.mjs → stream-first-event-timeout-B9o0S4SZ.mjs} +1 -1
- package/dist/{tool-schema-json-projection-CD9c_fK8.mjs → tool-schema-json-projection-Ct8SeBeJ.mjs} +63 -23
- package/dist/{transport-stream-shared-D-6FQSHm.mjs → transport-stream-shared-Dh5qKJ8e.mjs} +63 -37
- package/dist/{transport-stream-shared-BbUkFaHi.d.mts → transport-stream-shared-yYhXa4kX.d.mts} +13 -7
- package/dist/{transport-utils-1cyq5Y7x.mjs → transport-utils-C-4bf2Ok.mjs} +3 -4
- package/dist/transports.d.mts +37 -33
- package/dist/transports.mjs +208 -239
- package/dist/types-CB-_vNyI.d.mts +1 -0
- package/dist/{types-4_uVs5WH.d.mts → types-CLLR3eB4.d.mts} +5 -1
- package/dist/types.d.mts +6 -6
- package/dist/types.mjs +5 -5
- package/dist/{validation-Dw7cb6BV.mjs → validation-BFZc40Ig.mjs} +80 -54
- package/dist/{validation-Ctzu2DhF.d.mts → validation-Cat2wQsc.d.mts} +1 -1
- package/dist/validation.d.mts +1 -1
- package/dist/validation.mjs +1 -1
- package/package.json +6 -6
- package/dist/assistant-output-BsEkB-vU.mjs +0 -16
- package/dist/event-stream-DmSCpi1T.d.mts +0 -1
- package/dist/simple-options-C6cFWj_f.mjs +0 -175
- package/dist/types-DkJfb4W3.d.mts +0 -1
- package/dist/utf16-slice-CvGodqok.mjs +0 -29
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { o as isRecord } from "./record-coerce-CNDovvft.mjs";
|
|
1
2
|
import { n as normalizeLowercaseStringOrEmpty } from "./string-coerce-fsri9iCu.mjs";
|
|
2
|
-
import { o as isRecord } from "./record-coerce-DwRYMj3t.mjs";
|
|
3
3
|
import { i as uniqueValues, t as normalizeStringEntries } from "./string-normalization-J9ZiLfGO.mjs";
|
|
4
|
+
import { a as SCHEMA_OBJECT_KEYS$1, i as SCHEMA_MAP_KEYS$1, o as evaluateSchemaWalk, r as SCHEMA_ARRAY_KEYS$1 } from "./tool-schema-json-projection-Ct8SeBeJ.mjs";
|
|
4
5
|
//#region packages/ai/src/providers/clean-for-gemini.ts
|
|
5
6
|
const GEMINI_UNSUPPORTED_SCHEMA_KEYWORDS = /* @__PURE__ */ new Set([
|
|
7
|
+
"~optional",
|
|
6
8
|
"patternProperties",
|
|
7
9
|
"additionalProperties",
|
|
8
10
|
"$schema",
|
|
@@ -71,7 +73,7 @@ function tryFlattenLiteralAnyOf(variants) {
|
|
|
71
73
|
return null;
|
|
72
74
|
}
|
|
73
75
|
function isNullSchema(variant) {
|
|
74
|
-
if (!
|
|
76
|
+
if (!isRecord(variant)) return false;
|
|
75
77
|
const record = variant;
|
|
76
78
|
if ("const" in record && record.const === null) return true;
|
|
77
79
|
if (Array.isArray(record.enum) && record.enum.length === 1) return record.enum[0] === null;
|
|
@@ -80,20 +82,9 @@ function isNullSchema(variant) {
|
|
|
80
82
|
if (Array.isArray(typeValue) && typeValue.length === 1 && typeValue[0] === "null") return true;
|
|
81
83
|
return false;
|
|
82
84
|
}
|
|
83
|
-
function stripNullVariants(variants) {
|
|
84
|
-
if (variants.length === 0) return {
|
|
85
|
-
variants,
|
|
86
|
-
stripped: false
|
|
87
|
-
};
|
|
88
|
-
const nonNull = variants.filter((variant) => !isNullSchema(variant));
|
|
89
|
-
return {
|
|
90
|
-
variants: nonNull,
|
|
91
|
-
stripped: nonNull.length !== variants.length
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
85
|
function extendSchemaDefs$1(defs, schema) {
|
|
95
|
-
const defsEntry =
|
|
96
|
-
const legacyDefsEntry =
|
|
86
|
+
const defsEntry = isRecord(schema.$defs) ? schema.$defs : void 0;
|
|
87
|
+
const legacyDefsEntry = isRecord(schema.definitions) ? schema.definitions : void 0;
|
|
97
88
|
if (!defsEntry && !legacyDefsEntry) return defs;
|
|
98
89
|
const next = defs ? new Map(defs) : /* @__PURE__ */ new Map();
|
|
99
90
|
if (defsEntry) for (const [key, value] of Object.entries(defsEntry)) next.set(key, value);
|
|
@@ -113,7 +104,8 @@ function tryResolveLocalRef$1(ref, defs) {
|
|
|
113
104
|
}
|
|
114
105
|
function simplifyUnionVariants(params) {
|
|
115
106
|
const { obj, variants } = params;
|
|
116
|
-
const
|
|
107
|
+
const nonNullVariants = variants.filter((variant) => !isNullSchema(variant));
|
|
108
|
+
const stripped = nonNullVariants.length !== variants.length;
|
|
117
109
|
const flattened = tryFlattenLiteralAnyOf(nonNullVariants);
|
|
118
110
|
if (flattened) {
|
|
119
111
|
const result = {
|
|
@@ -148,7 +140,7 @@ function simplifyUnionVariants(params) {
|
|
|
148
140
|
}
|
|
149
141
|
function sanitizeRequiredFields(schema) {
|
|
150
142
|
if (!Array.isArray(schema.required)) return schema;
|
|
151
|
-
if (!
|
|
143
|
+
if (!isRecord(schema.properties)) {
|
|
152
144
|
if (schema.type === "object") delete schema.required;
|
|
153
145
|
return schema;
|
|
154
146
|
}
|
|
@@ -158,89 +150,114 @@ function sanitizeRequiredFields(schema) {
|
|
|
158
150
|
else delete schema.required;
|
|
159
151
|
return schema;
|
|
160
152
|
}
|
|
161
|
-
function
|
|
153
|
+
function* cleanSchemaArray(schemas, defs, refStack, ancestors, result) {
|
|
154
|
+
result.length = schemas.length;
|
|
155
|
+
for (let index = 0; index < result.length; index += 1) if (index in schemas) result[index] = yield cleanSchemaForGeminiWithDefs(schemas[index], defs, refStack, ancestors);
|
|
156
|
+
return result;
|
|
157
|
+
}
|
|
158
|
+
function* cleanSchemaForGeminiWithDefs(schema, defs, refStack, ancestors) {
|
|
162
159
|
if (!schema || typeof schema !== "object") return schema;
|
|
163
|
-
if (
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
160
|
+
if (ancestors.has(schema)) throw new TypeError("Tool schema contains a circular reference.");
|
|
161
|
+
ancestors.add(schema);
|
|
162
|
+
try {
|
|
163
|
+
if (Array.isArray(schema)) {
|
|
164
|
+
const result = [];
|
|
165
|
+
yield cleanSchemaArray(schema, defs, refStack, ancestors, result);
|
|
166
|
+
return result;
|
|
167
|
+
}
|
|
168
|
+
const obj = schema;
|
|
169
|
+
const nextDefs = extendSchemaDefs$1(defs, obj);
|
|
170
|
+
const refValue = typeof obj.$ref === "string" ? obj.$ref : void 0;
|
|
171
|
+
if (refValue) {
|
|
172
|
+
if (refStack?.has(refValue)) return {};
|
|
173
|
+
const resolved = tryResolveLocalRef$1(refValue, nextDefs);
|
|
174
|
+
if (resolved) {
|
|
175
|
+
const nextRefStack = refStack ? new Set(refStack) : /* @__PURE__ */ new Set();
|
|
176
|
+
nextRefStack.add(refValue);
|
|
177
|
+
const cleaned = yield cleanSchemaForGeminiWithDefs(resolved, nextDefs, nextRefStack, /* @__PURE__ */ new Set());
|
|
178
|
+
if (!cleaned || typeof cleaned !== "object" || Array.isArray(cleaned)) return cleaned;
|
|
179
|
+
const result = { ...cleaned };
|
|
180
|
+
copySchemaMeta$1(obj, result);
|
|
181
|
+
return result;
|
|
182
|
+
}
|
|
183
|
+
const result = {};
|
|
176
184
|
copySchemaMeta$1(obj, result);
|
|
177
185
|
return result;
|
|
178
186
|
}
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
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;
|
|
187
|
+
const hasAnyOf = "anyOf" in obj && Array.isArray(obj.anyOf);
|
|
188
|
+
const hasOneOf = "oneOf" in obj && Array.isArray(obj.oneOf);
|
|
189
|
+
let cleanedAnyOf;
|
|
190
|
+
if (hasAnyOf) {
|
|
191
|
+
const variants = obj.anyOf;
|
|
192
|
+
cleanedAnyOf = [];
|
|
193
|
+
yield cleanSchemaArray(variants, nextDefs, refStack, ancestors, cleanedAnyOf);
|
|
210
194
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
195
|
+
let cleanedOneOf;
|
|
196
|
+
if (hasOneOf) {
|
|
197
|
+
const variants = obj.oneOf;
|
|
198
|
+
cleanedOneOf = [];
|
|
199
|
+
yield cleanSchemaArray(variants, nextDefs, refStack, ancestors, cleanedOneOf);
|
|
215
200
|
}
|
|
216
|
-
if (
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
201
|
+
if (hasAnyOf) {
|
|
202
|
+
const simplified = simplifyUnionVariants({
|
|
203
|
+
obj,
|
|
204
|
+
variants: cleanedAnyOf ?? []
|
|
205
|
+
});
|
|
206
|
+
if (simplified.kind === "simplified") return simplified.value;
|
|
207
|
+
cleanedAnyOf = simplified.value;
|
|
222
208
|
}
|
|
223
|
-
if (
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
209
|
+
if (hasOneOf) {
|
|
210
|
+
const simplified = simplifyUnionVariants({
|
|
211
|
+
obj,
|
|
212
|
+
variants: cleanedOneOf ?? []
|
|
213
|
+
});
|
|
214
|
+
if (simplified.kind === "simplified") return simplified.value;
|
|
215
|
+
cleanedOneOf = simplified.value;
|
|
216
|
+
}
|
|
217
|
+
const cleaned = {};
|
|
218
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
219
|
+
if (GEMINI_UNSUPPORTED_SCHEMA_KEYWORDS.has(key)) continue;
|
|
220
|
+
if (key === "const" || key === "enum") {
|
|
221
|
+
const enumValues = cleanGeminiEnumValues(key === "const" ? [value] : value);
|
|
222
|
+
if (enumValues) cleaned.enum = enumValues;
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
if (key === "required" && Array.isArray(value) && value.length === 0) continue;
|
|
226
|
+
if (key === "type" && (hasAnyOf || hasOneOf)) continue;
|
|
227
|
+
if (key === "type" && Array.isArray(value) && value.every((entry) => typeof entry === "string")) {
|
|
228
|
+
const types = value.filter((entry) => entry !== "null");
|
|
229
|
+
cleaned.type = types.length === 1 ? types[0] : types;
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
if (key === "properties") {
|
|
233
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
234
|
+
const entries = Object.entries(value);
|
|
235
|
+
for (const entry of entries) entry[1] = yield cleanSchemaForGeminiWithDefs(entry[1], nextDefs, refStack, ancestors);
|
|
236
|
+
cleaned[key] = Object.fromEntries(entries);
|
|
237
|
+
} else cleaned[key] = {};
|
|
238
|
+
} else if (key === "items" && value) {
|
|
239
|
+
if (Array.isArray(value)) {
|
|
240
|
+
const result = [];
|
|
241
|
+
yield cleanSchemaArray(value, nextDefs, refStack, ancestors, result);
|
|
242
|
+
cleaned[key] = result;
|
|
243
|
+
} else if (typeof value === "object") cleaned[key] = yield cleanSchemaForGeminiWithDefs(value, nextDefs, refStack, ancestors);
|
|
244
|
+
else cleaned[key] = value;
|
|
245
|
+
} else if (key === "anyOf" && Array.isArray(value)) cleaned[key] = cleanedAnyOf;
|
|
246
|
+
else if (key === "oneOf" && Array.isArray(value)) cleaned[key] = cleanedOneOf;
|
|
247
|
+
else if (key === "allOf" && Array.isArray(value)) {
|
|
248
|
+
const result = [];
|
|
249
|
+
yield cleanSchemaArray(value, nextDefs, refStack, ancestors, result);
|
|
250
|
+
cleaned[key] = result;
|
|
251
|
+
} else cleaned[key] = value;
|
|
252
|
+
}
|
|
253
|
+
for (const variants of [cleaned.anyOf, cleaned.oneOf]) if (Array.isArray(variants)) {
|
|
254
|
+
const flattened = flattenUnionFallback(cleaned, variants);
|
|
255
|
+
if (flattened) return sanitizeRequiredFields(flattened);
|
|
256
|
+
}
|
|
257
|
+
return sanitizeRequiredFields(cleaned);
|
|
258
|
+
} finally {
|
|
259
|
+
ancestors.delete(schema);
|
|
242
260
|
}
|
|
243
|
-
return sanitizeRequiredFields(cleaned);
|
|
244
261
|
}
|
|
245
262
|
/**
|
|
246
263
|
* Last-resort flattening for anyOf/oneOf arrays that could not be simplified
|
|
@@ -251,40 +268,192 @@ function flattenUnionFallback(obj, variants) {
|
|
|
251
268
|
const objects = variants.filter((v) => Boolean(v) && typeof v === "object");
|
|
252
269
|
if (objects.length === 0) return;
|
|
253
270
|
const types = new Set(objects.map((v) => v.type).filter(Boolean));
|
|
254
|
-
if (objects.length === 1) {
|
|
255
|
-
const merged = { ...objects[0] };
|
|
256
|
-
copySchemaMeta$1(obj, merged);
|
|
257
|
-
return merged;
|
|
258
|
-
}
|
|
259
|
-
if (types.size === 1) {
|
|
260
|
-
const merged = { type: Array.from(types)[0] };
|
|
261
|
-
copySchemaMeta$1(obj, merged);
|
|
262
|
-
return merged;
|
|
263
|
-
}
|
|
264
271
|
const first = objects[0];
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
copySchemaMeta$1(obj, merged);
|
|
268
|
-
return merged;
|
|
269
|
-
}
|
|
270
|
-
const merged = {};
|
|
272
|
+
const type = types.size === 1 ? Array.from(types)[0] : first?.type;
|
|
273
|
+
const merged = objects.length === 1 ? { ...first } : type ? { type } : {};
|
|
271
274
|
copySchemaMeta$1(obj, merged);
|
|
272
275
|
return merged;
|
|
273
276
|
}
|
|
274
277
|
function cleanSchemaForGemini(schema) {
|
|
275
|
-
return cleanSchemaForGeminiWithDefs(schema, void 0, void 0);
|
|
278
|
+
return evaluateSchemaWalk(cleanSchemaForGeminiWithDefs(schema, void 0, void 0, /* @__PURE__ */ new Set()));
|
|
276
279
|
}
|
|
277
280
|
//#endregion
|
|
278
|
-
//#region packages/ai/src/providers/
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
281
|
+
//#region packages/ai/src/providers/tool-schema-refs.ts
|
|
282
|
+
function setOwnSchemaProperty(target, key, value) {
|
|
283
|
+
Object.defineProperty(target, key, {
|
|
284
|
+
value,
|
|
285
|
+
enumerable: true,
|
|
286
|
+
configurable: true,
|
|
287
|
+
writable: true
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
function copySchemaMeta(from, to) {
|
|
291
|
+
for (const key of [
|
|
292
|
+
"title",
|
|
293
|
+
"description",
|
|
294
|
+
"default"
|
|
295
|
+
]) if (key in from && from[key] !== void 0) to[key] = from[key];
|
|
296
|
+
}
|
|
297
|
+
function extendSchemaDefs(defs, schema) {
|
|
298
|
+
const defsEntry = isRecord(schema.$defs) ? schema.$defs : void 0;
|
|
299
|
+
const legacyDefsEntry = isRecord(schema.definitions) ? schema.definitions : void 0;
|
|
300
|
+
if (!defsEntry && !legacyDefsEntry) return defs;
|
|
301
|
+
const next = defs ? {
|
|
302
|
+
$defs: new Map(defs.$defs),
|
|
303
|
+
definitions: new Map(defs.definitions)
|
|
304
|
+
} : {
|
|
305
|
+
$defs: /* @__PURE__ */ new Map(),
|
|
306
|
+
definitions: /* @__PURE__ */ new Map()
|
|
307
|
+
};
|
|
308
|
+
if (defsEntry) for (const [key, value] of Object.entries(defsEntry)) next.$defs.set(key, value);
|
|
309
|
+
if (legacyDefsEntry) for (const [key, value] of Object.entries(legacyDefsEntry)) next.definitions.set(key, value);
|
|
310
|
+
return next;
|
|
311
|
+
}
|
|
312
|
+
function decodeJsonPointerSegment(segment) {
|
|
313
|
+
return segment.replaceAll("~1", "/").replaceAll("~0", "~");
|
|
314
|
+
}
|
|
315
|
+
function resolveJsonPointerPath(value, segments) {
|
|
316
|
+
let current = value;
|
|
317
|
+
for (const segment of segments) {
|
|
318
|
+
if (!current || typeof current !== "object") return;
|
|
319
|
+
const key = decodeJsonPointerSegment(segment);
|
|
320
|
+
if (Array.isArray(current)) {
|
|
321
|
+
const index = /^(?:0|[1-9]\d*)$/.test(key) ? Number(key) : -1;
|
|
322
|
+
if (index < 0 || index >= current.length) return;
|
|
323
|
+
current = current[index];
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
if (!isRecord(current) || !Object.hasOwn(current, key)) return;
|
|
327
|
+
current = current[key];
|
|
328
|
+
}
|
|
329
|
+
return current;
|
|
330
|
+
}
|
|
331
|
+
function resolveLocalJsonPointer(rootDocument, ref) {
|
|
332
|
+
if (!ref.startsWith("#/")) return;
|
|
333
|
+
return resolveJsonPointerPath(rootDocument, ref.slice(2).split("/"));
|
|
334
|
+
}
|
|
335
|
+
const SCHEMA_MAP_KEYS = /* @__PURE__ */ new Set([
|
|
282
336
|
"$defs",
|
|
283
337
|
"definitions",
|
|
284
338
|
"dependentSchemas",
|
|
285
339
|
"patternProperties",
|
|
286
340
|
"properties"
|
|
287
341
|
]);
|
|
342
|
+
const SCHEMA_OBJECT_KEYS = /* @__PURE__ */ new Set([
|
|
343
|
+
"additionalProperties",
|
|
344
|
+
"contains",
|
|
345
|
+
"else",
|
|
346
|
+
"if",
|
|
347
|
+
"items",
|
|
348
|
+
"not",
|
|
349
|
+
"propertyNames",
|
|
350
|
+
"then"
|
|
351
|
+
]);
|
|
352
|
+
const SCHEMA_ARRAY_KEYS = /* @__PURE__ */ new Set([
|
|
353
|
+
"allOf",
|
|
354
|
+
"anyOf",
|
|
355
|
+
"items",
|
|
356
|
+
"oneOf",
|
|
357
|
+
"prefixItems"
|
|
358
|
+
]);
|
|
359
|
+
const SCHEMA_LITERAL_KEYS = /* @__PURE__ */ new Set([
|
|
360
|
+
"const",
|
|
361
|
+
"default",
|
|
362
|
+
"enum",
|
|
363
|
+
"examples"
|
|
364
|
+
]);
|
|
365
|
+
function tryResolveLocalRef(ref, defs, rootDocument) {
|
|
366
|
+
const match = ref.match(/^#\/(\$defs|definitions)\/([^/]+)(?:\/(.*))?$/);
|
|
367
|
+
if (match && defs) {
|
|
368
|
+
const namespace = match[1] === "$defs" ? defs.$defs : defs.definitions;
|
|
369
|
+
const name = decodeJsonPointerSegment(match[2] ?? "");
|
|
370
|
+
const resolved = name ? namespace.get(name) : void 0;
|
|
371
|
+
if (resolved !== void 0) return resolveJsonPointerPath(resolved, match[3] ? match[3].split("/") : []);
|
|
372
|
+
}
|
|
373
|
+
return resolveLocalJsonPointer(rootDocument, ref);
|
|
374
|
+
}
|
|
375
|
+
function inlineLocalSchemaRefsWithDefs(schema, defs, refStack, state, rootDocument) {
|
|
376
|
+
if (Array.isArray(schema)) return schema.map((entry) => inlineLocalSchemaRefsWithDefs(entry, defs, refStack, state, rootDocument));
|
|
377
|
+
if (!isRecord(schema)) return schema;
|
|
378
|
+
const obj = schema;
|
|
379
|
+
const nextDefs = extendSchemaDefs(defs, obj);
|
|
380
|
+
const refValue = typeof obj.$ref === "string" ? obj.$ref : void 0;
|
|
381
|
+
if (refValue) {
|
|
382
|
+
if (refStack?.has(refValue)) return {};
|
|
383
|
+
const resolved = tryResolveLocalRef(refValue, nextDefs, rootDocument);
|
|
384
|
+
if (resolved === void 0) {
|
|
385
|
+
if (refValue.startsWith("#/")) state.unresolvedLocalRefs = true;
|
|
386
|
+
return { ...obj };
|
|
387
|
+
}
|
|
388
|
+
const nextRefStack = refStack ? new Set(refStack) : /* @__PURE__ */ new Set();
|
|
389
|
+
nextRefStack.add(refValue);
|
|
390
|
+
const inlined = inlineLocalSchemaRefsWithDefs(resolved, nextDefs, nextRefStack, state, rootDocument);
|
|
391
|
+
if (!isRecord(inlined)) return inlined;
|
|
392
|
+
const result = { ...inlined };
|
|
393
|
+
copySchemaMeta(obj, result);
|
|
394
|
+
if (obj.nullable === true) result.nullable = true;
|
|
395
|
+
return result;
|
|
396
|
+
}
|
|
397
|
+
const result = {};
|
|
398
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
399
|
+
if (key === "$defs" || key === "definitions" || key === "components") continue;
|
|
400
|
+
let next = value;
|
|
401
|
+
if (SCHEMA_MAP_KEYS.has(key) && isRecord(value)) {
|
|
402
|
+
const entries = Object.entries(value);
|
|
403
|
+
for (const entry of entries) entry[1] = inlineLocalSchemaRefsWithDefs(entry[1], nextDefs, refStack, state, rootDocument);
|
|
404
|
+
next = Object.fromEntries(entries);
|
|
405
|
+
} else if (SCHEMA_OBJECT_KEYS.has(key) && isRecord(value)) next = inlineLocalSchemaRefsWithDefs(value, nextDefs, refStack, state, rootDocument);
|
|
406
|
+
else if (SCHEMA_ARRAY_KEYS.has(key) && Array.isArray(value)) next = value.map((entry) => inlineLocalSchemaRefsWithDefs(entry, nextDefs, refStack, state, rootDocument));
|
|
407
|
+
setOwnSchemaProperty(result, key, next);
|
|
408
|
+
}
|
|
409
|
+
if (state.unresolvedLocalRefs) {
|
|
410
|
+
if ("$defs" in obj) result.$defs = obj.$defs;
|
|
411
|
+
if ("definitions" in obj) result.definitions = obj.definitions;
|
|
412
|
+
if ("components" in obj) result.components = obj.components;
|
|
413
|
+
}
|
|
414
|
+
return result;
|
|
415
|
+
}
|
|
416
|
+
/** Inline local $ref pointers so providers receive self-contained tool schemas. */
|
|
417
|
+
function inlineLocalToolSchemaRefs(schema) {
|
|
418
|
+
if (!schema || typeof schema !== "object") return schema;
|
|
419
|
+
const schemaRecord = schema;
|
|
420
|
+
return inlineLocalSchemaRefsWithDefs(schema, Array.isArray(schema) ? extendSchemaDefs(void 0, schemaRecord) : void 0, void 0, { unresolvedLocalRefs: false }, schema);
|
|
421
|
+
}
|
|
422
|
+
/** Keep compact root definitions. Fall back for scopes or refs we must rewrite. */
|
|
423
|
+
function canPreserveRootSchemaRefs(schema) {
|
|
424
|
+
if (!isRecord(schema) || schema.type !== "object" || !isRecord(schema.properties) || ["$defs", "definitions"].some((key) => key in schema && !isRecord(schema[key])) || [
|
|
425
|
+
"anyOf",
|
|
426
|
+
"oneOf",
|
|
427
|
+
"allOf"
|
|
428
|
+
].some((key) => Array.isArray(schema[key])) || "$ref" in schema) return false;
|
|
429
|
+
let hasRefs = false;
|
|
430
|
+
const ancestors = /* @__PURE__ */ new Set();
|
|
431
|
+
function visit(node, inDefinitions = false) {
|
|
432
|
+
if (!isRecord(node)) return true;
|
|
433
|
+
if (ancestors.has(node) || "$id" in node || "id" in node || "components" in node || node !== schema && ("$defs" in node || "definitions" in node)) return false;
|
|
434
|
+
if ("$ref" in node) {
|
|
435
|
+
if (typeof node.$ref !== "string" || !/^#\/(\$defs|definitions)\/[^/]+$/.test(node.$ref) || node.nullable === true || resolveLocalJsonPointer(schema, node.$ref) === void 0) return false;
|
|
436
|
+
hasRefs ||= !inDefinitions;
|
|
437
|
+
}
|
|
438
|
+
ancestors.add(node);
|
|
439
|
+
try {
|
|
440
|
+
for (const [key, value] of Object.entries(node)) if (SCHEMA_MAP_KEYS.has(key) && isRecord(value)) {
|
|
441
|
+
const childInDefinitions = inDefinitions || key === "$defs" || key === "definitions";
|
|
442
|
+
if (!Object.values(value).every((entry) => visit(entry, childInDefinitions))) return false;
|
|
443
|
+
} else if (SCHEMA_ARRAY_KEYS.has(key) && Array.isArray(value)) {
|
|
444
|
+
if (!value.every((entry) => visit(entry, inDefinitions))) return false;
|
|
445
|
+
} else if (SCHEMA_OBJECT_KEYS.has(key) && !visit(value, inDefinitions)) return false;
|
|
446
|
+
return true;
|
|
447
|
+
} finally {
|
|
448
|
+
ancestors.delete(node);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
return visit(schema) && hasRefs;
|
|
452
|
+
}
|
|
453
|
+
//#endregion
|
|
454
|
+
//#region packages/ai/src/providers/clean-for-llamacpp-gbnf.ts
|
|
455
|
+
/** llama.cpp rejects grammar repetitions whose expanded rule count reaches 2000. */
|
|
456
|
+
const LLAMACPP_GBNF_MAX_REPETITION_THRESHOLD = 2e3;
|
|
288
457
|
const SCHEMA_CHILD_KEYS = /* @__PURE__ */ new Set([
|
|
289
458
|
"additionalItems",
|
|
290
459
|
"additionalProperties",
|
|
@@ -302,20 +471,21 @@ const SCHEMA_CHILD_KEYS = /* @__PURE__ */ new Set([
|
|
|
302
471
|
"unevaluatedItems",
|
|
303
472
|
"unevaluatedProperties"
|
|
304
473
|
]);
|
|
305
|
-
|
|
306
|
-
|
|
474
|
+
/** Removes JSON Schema constraints that llama.cpp cannot compile into GBNF. */
|
|
475
|
+
function cleanSchemaForLlamacppGbnf(schema) {
|
|
476
|
+
if (Array.isArray(schema)) {
|
|
307
477
|
let changed = false;
|
|
308
|
-
const entries =
|
|
309
|
-
const next =
|
|
478
|
+
const entries = schema.map((entry) => {
|
|
479
|
+
const next = cleanSchemaForLlamacppGbnf(entry);
|
|
310
480
|
changed ||= next !== entry;
|
|
311
481
|
return next;
|
|
312
482
|
});
|
|
313
|
-
return changed ? entries :
|
|
483
|
+
return changed ? entries : schema;
|
|
314
484
|
}
|
|
315
|
-
if (!isRecord(
|
|
485
|
+
if (!isRecord(schema)) return schema;
|
|
316
486
|
let changed = false;
|
|
317
487
|
const cleaned = {};
|
|
318
|
-
for (const [key, value] of Object.entries(
|
|
488
|
+
for (const [key, value] of Object.entries(schema)) {
|
|
319
489
|
if (key === "pattern") {
|
|
320
490
|
changed = true;
|
|
321
491
|
continue;
|
|
@@ -325,19 +495,19 @@ function cleanSchemaNode(node) {
|
|
|
325
495
|
continue;
|
|
326
496
|
}
|
|
327
497
|
let next = value;
|
|
328
|
-
if (SCHEMA_MAP_KEYS
|
|
498
|
+
if (SCHEMA_MAP_KEYS.has(key) && isRecord(value)) {
|
|
329
499
|
let mapChanged = false;
|
|
330
500
|
next = Object.fromEntries(Object.entries(value).map(([childKey, childValue]) => {
|
|
331
|
-
const cleanedChild =
|
|
501
|
+
const cleanedChild = cleanSchemaForLlamacppGbnf(childValue);
|
|
332
502
|
mapChanged ||= cleanedChild !== childValue;
|
|
333
503
|
return [childKey, cleanedChild];
|
|
334
504
|
}));
|
|
335
505
|
if (!mapChanged) next = value;
|
|
336
|
-
} else if (SCHEMA_CHILD_KEYS.has(key)) next =
|
|
506
|
+
} else if (SCHEMA_CHILD_KEYS.has(key)) next = cleanSchemaForLlamacppGbnf(value);
|
|
337
507
|
cleaned[key] = next;
|
|
338
508
|
changed ||= next !== value;
|
|
339
509
|
}
|
|
340
|
-
return changed ? cleaned :
|
|
510
|
+
return changed ? cleaned : schema;
|
|
341
511
|
}
|
|
342
512
|
function collectSchemaViolations(node, path, violations) {
|
|
343
513
|
if (Array.isArray(node)) {
|
|
@@ -347,13 +517,9 @@ function collectSchemaViolations(node, path, violations) {
|
|
|
347
517
|
if (!isRecord(node)) return;
|
|
348
518
|
if ("pattern" in node) violations.push(`${path}.pattern`);
|
|
349
519
|
if (typeof node.maxLength === "number" && node.maxLength >= 2e3) violations.push(`${path}.maxLength`);
|
|
350
|
-
for (const [key, value] of Object.entries(node)) if (SCHEMA_MAP_KEYS
|
|
520
|
+
for (const [key, value] of Object.entries(node)) if (SCHEMA_MAP_KEYS.has(key) && isRecord(value)) for (const [childKey, childValue] of Object.entries(value)) collectSchemaViolations(childValue, `${path}.${key}.${childKey}`, violations);
|
|
351
521
|
else if (SCHEMA_CHILD_KEYS.has(key)) collectSchemaViolations(value, `${path}.${key}`, violations);
|
|
352
522
|
}
|
|
353
|
-
/** Removes JSON Schema constraints that llama.cpp cannot compile into GBNF. */
|
|
354
|
-
function cleanSchemaForLlamacppGbnf(schema) {
|
|
355
|
-
return cleanSchemaNode(schema);
|
|
356
|
-
}
|
|
357
523
|
/** Reports schema paths that llama.cpp cannot compile into GBNF. */
|
|
358
524
|
function findLlamacppGbnfSchemaViolations(schema, path) {
|
|
359
525
|
const violations = [];
|
|
@@ -362,60 +528,38 @@ function findLlamacppGbnfSchemaViolations(schema, path) {
|
|
|
362
528
|
}
|
|
363
529
|
//#endregion
|
|
364
530
|
//#region packages/ai/src/providers/schema-keyword-strip.ts
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
]);
|
|
373
|
-
/** Containers whose value is a single nested schema. */
|
|
374
|
-
const SCHEMA_OBJECT_KEYS$1 = /* @__PURE__ */ new Set([
|
|
375
|
-
"additionalItems",
|
|
376
|
-
"additionalProperties",
|
|
377
|
-
"contains",
|
|
378
|
-
"contentSchema",
|
|
379
|
-
"else",
|
|
380
|
-
"if",
|
|
381
|
-
"items",
|
|
382
|
-
"not",
|
|
383
|
-
"propertyNames",
|
|
384
|
-
"then",
|
|
385
|
-
"unevaluatedItems",
|
|
386
|
-
"unevaluatedProperties"
|
|
387
|
-
]);
|
|
388
|
-
/** Containers whose value is a list of nested schemas. */
|
|
389
|
-
const SCHEMA_ARRAY_KEYS$1 = /* @__PURE__ */ new Set([
|
|
390
|
-
"allOf",
|
|
391
|
-
"anyOf",
|
|
392
|
-
"items",
|
|
393
|
-
"oneOf",
|
|
394
|
-
"prefixItems"
|
|
395
|
-
]);
|
|
396
|
-
/** Recursively remove schema keywords unsupported by a target provider/tool surface. */
|
|
397
|
-
function stripUnsupportedSchemaKeywords(schema, unsupportedKeywords) {
|
|
531
|
+
function* stripSchemaArray(schemas, unsupportedKeywords, ancestors) {
|
|
532
|
+
const result = [];
|
|
533
|
+
result.length = schemas.length;
|
|
534
|
+
for (let index = 0; index < result.length; index += 1) if (index in schemas) result[index] = yield stripSchemaKeywords(schemas[index], unsupportedKeywords, ancestors);
|
|
535
|
+
return result;
|
|
536
|
+
}
|
|
537
|
+
function* stripSchemaKeywords(schema, unsupportedKeywords, ancestors) {
|
|
398
538
|
if (!schema || typeof schema !== "object") return schema;
|
|
399
|
-
if (
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
continue;
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
cleaned[key] =
|
|
414
|
-
continue;
|
|
539
|
+
if (ancestors.has(schema)) throw new TypeError("Tool schema contains a circular reference.");
|
|
540
|
+
ancestors.add(schema);
|
|
541
|
+
try {
|
|
542
|
+
if (Array.isArray(schema)) return yield stripSchemaArray(schema, unsupportedKeywords, ancestors);
|
|
543
|
+
const obj = schema;
|
|
544
|
+
const cleaned = {};
|
|
545
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
546
|
+
if (unsupportedKeywords.has(key)) continue;
|
|
547
|
+
if (SCHEMA_MAP_KEYS$1.has(key) && value && typeof value === "object" && !Array.isArray(value)) {
|
|
548
|
+
const entries = Object.entries(value);
|
|
549
|
+
for (const entry of entries) entry[1] = yield stripSchemaKeywords(entry[1], unsupportedKeywords, ancestors);
|
|
550
|
+
cleaned[key] = Object.fromEntries(entries);
|
|
551
|
+
} else if (SCHEMA_ARRAY_KEYS$1.has(key) && Array.isArray(value)) cleaned[key] = yield stripSchemaArray(value, unsupportedKeywords, ancestors);
|
|
552
|
+
else if (SCHEMA_OBJECT_KEYS$1.has(key) && value && typeof value === "object") cleaned[key] = yield stripSchemaKeywords(value, unsupportedKeywords, ancestors);
|
|
553
|
+
else cleaned[key] = value;
|
|
415
554
|
}
|
|
416
|
-
cleaned
|
|
555
|
+
return cleaned;
|
|
556
|
+
} finally {
|
|
557
|
+
ancestors.delete(schema);
|
|
417
558
|
}
|
|
418
|
-
|
|
559
|
+
}
|
|
560
|
+
/** Remove schema keywords unsupported by a target provider/tool surface. */
|
|
561
|
+
function stripUnsupportedSchemaKeywords(schema, unsupportedKeywords) {
|
|
562
|
+
return evaluateSchemaWalk(stripSchemaKeywords(schema, unsupportedKeywords, /* @__PURE__ */ new Set()));
|
|
419
563
|
}
|
|
420
564
|
//#endregion
|
|
421
565
|
//#region packages/ai/src/providers/tool-schema-normalization-cache.ts
|
|
@@ -549,37 +693,6 @@ function mergePropertySchemas(existing, incoming) {
|
|
|
549
693
|
}
|
|
550
694
|
return existing;
|
|
551
695
|
}
|
|
552
|
-
function setOwnSchemaProperty(target, key, value) {
|
|
553
|
-
Object.defineProperty(target, key, {
|
|
554
|
-
value,
|
|
555
|
-
enumerable: true,
|
|
556
|
-
configurable: true,
|
|
557
|
-
writable: true
|
|
558
|
-
});
|
|
559
|
-
}
|
|
560
|
-
function hasTopLevelArrayKeyword(schemaRecord, key) {
|
|
561
|
-
return Array.isArray(schemaRecord[key]);
|
|
562
|
-
}
|
|
563
|
-
function getFlattenableVariantKey(schemaRecord) {
|
|
564
|
-
if (hasTopLevelArrayKeyword(schemaRecord, "anyOf")) return "anyOf";
|
|
565
|
-
if (hasTopLevelArrayKeyword(schemaRecord, "oneOf")) return "oneOf";
|
|
566
|
-
return null;
|
|
567
|
-
}
|
|
568
|
-
function getTopLevelConditionalKey(schemaRecord) {
|
|
569
|
-
return getFlattenableVariantKey(schemaRecord) ?? (hasTopLevelArrayKeyword(schemaRecord, "allOf") ? "allOf" : null);
|
|
570
|
-
}
|
|
571
|
-
function hasTopLevelObjectSchema(schemaRecord, conditionalKey) {
|
|
572
|
-
return schemaRecord.type === "object" && isRecord(schemaRecord.properties) && conditionalKey === null;
|
|
573
|
-
}
|
|
574
|
-
function isObjectLikeSchemaMissingType(schemaRecord, conditionalKey) {
|
|
575
|
-
return !("type" in schemaRecord) && (isRecord(schemaRecord.properties) || Array.isArray(schemaRecord.required)) && conditionalKey === null;
|
|
576
|
-
}
|
|
577
|
-
function isTypedObjectSchemaMissingValidProperties(schemaRecord, conditionalKey) {
|
|
578
|
-
return schemaRecord.type === "object" && !isRecord(schemaRecord.properties) && conditionalKey === null;
|
|
579
|
-
}
|
|
580
|
-
function isTrulyEmptySchema(schemaRecord) {
|
|
581
|
-
return Object.keys(schemaRecord).length === 0;
|
|
582
|
-
}
|
|
583
696
|
function normalizeArraySchemaItems(schema, mode) {
|
|
584
697
|
if (Array.isArray(schema)) {
|
|
585
698
|
if (mode === "add") return schema;
|
|
@@ -601,7 +714,7 @@ function normalizeArraySchemaItems(schema, mode) {
|
|
|
601
714
|
return entries.some((entry, index) => entry !== value[index]) ? entries : value;
|
|
602
715
|
};
|
|
603
716
|
for (const [key, value] of Object.entries(normalized)) {
|
|
604
|
-
if (mode !== "add" && key === "items" && allowsArray && isRecord(value) &&
|
|
717
|
+
if (mode !== "add" && key === "items" && allowsArray && isRecord(value) && Object.keys(value).length === 0) {
|
|
605
718
|
delete normalized.items;
|
|
606
719
|
changed = true;
|
|
607
720
|
continue;
|
|
@@ -622,150 +735,6 @@ function normalizeArraySchemaItems(schema, mode) {
|
|
|
622
735
|
}
|
|
623
736
|
return changed ? normalized : schema;
|
|
624
737
|
}
|
|
625
|
-
function copySchemaMeta(from, to) {
|
|
626
|
-
for (const key of [
|
|
627
|
-
"title",
|
|
628
|
-
"description",
|
|
629
|
-
"default"
|
|
630
|
-
]) if (key in from && from[key] !== void 0) to[key] = from[key];
|
|
631
|
-
}
|
|
632
|
-
function extendSchemaDefs(defs, schema) {
|
|
633
|
-
const defsEntry = schema.$defs && typeof schema.$defs === "object" && !Array.isArray(schema.$defs) ? schema.$defs : void 0;
|
|
634
|
-
const legacyDefsEntry = schema.definitions && typeof schema.definitions === "object" && !Array.isArray(schema.definitions) ? schema.definitions : void 0;
|
|
635
|
-
if (!defsEntry && !legacyDefsEntry) return defs;
|
|
636
|
-
const next = defs ? {
|
|
637
|
-
$defs: new Map(defs.$defs),
|
|
638
|
-
definitions: new Map(defs.definitions)
|
|
639
|
-
} : {
|
|
640
|
-
$defs: /* @__PURE__ */ new Map(),
|
|
641
|
-
definitions: /* @__PURE__ */ new Map()
|
|
642
|
-
};
|
|
643
|
-
if (defsEntry) for (const [key, value] of Object.entries(defsEntry)) next.$defs.set(key, value);
|
|
644
|
-
if (legacyDefsEntry) for (const [key, value] of Object.entries(legacyDefsEntry)) next.definitions.set(key, value);
|
|
645
|
-
return next;
|
|
646
|
-
}
|
|
647
|
-
function decodeJsonPointerSegment(segment) {
|
|
648
|
-
return segment.replaceAll("~1", "/").replaceAll("~0", "~");
|
|
649
|
-
}
|
|
650
|
-
function resolveJsonPointerPath(value, segments) {
|
|
651
|
-
let current = value;
|
|
652
|
-
for (const segment of segments) {
|
|
653
|
-
if (!current || typeof current !== "object") return;
|
|
654
|
-
const key = decodeJsonPointerSegment(segment);
|
|
655
|
-
if (Array.isArray(current)) {
|
|
656
|
-
const index = /^(?:0|[1-9]\d*)$/.test(key) ? Number(key) : -1;
|
|
657
|
-
if (index < 0 || index >= current.length) return;
|
|
658
|
-
current = current[index];
|
|
659
|
-
continue;
|
|
660
|
-
}
|
|
661
|
-
const record = current;
|
|
662
|
-
if (!Object.hasOwn(record, key)) return;
|
|
663
|
-
current = record[key];
|
|
664
|
-
}
|
|
665
|
-
return current;
|
|
666
|
-
}
|
|
667
|
-
function resolveLocalJsonPointer(rootDocument, ref) {
|
|
668
|
-
if (!ref.startsWith("#/")) return;
|
|
669
|
-
return resolveJsonPointerPath(rootDocument, ref.slice(2).split("/"));
|
|
670
|
-
}
|
|
671
|
-
const SCHEMA_MAP_KEYS = /* @__PURE__ */ new Set([
|
|
672
|
-
"$defs",
|
|
673
|
-
"definitions",
|
|
674
|
-
"dependentSchemas",
|
|
675
|
-
"patternProperties",
|
|
676
|
-
"properties"
|
|
677
|
-
]);
|
|
678
|
-
const SCHEMA_OBJECT_KEYS = /* @__PURE__ */ new Set([
|
|
679
|
-
"additionalProperties",
|
|
680
|
-
"contains",
|
|
681
|
-
"else",
|
|
682
|
-
"if",
|
|
683
|
-
"items",
|
|
684
|
-
"not",
|
|
685
|
-
"propertyNames",
|
|
686
|
-
"then"
|
|
687
|
-
]);
|
|
688
|
-
const SCHEMA_ARRAY_KEYS = /* @__PURE__ */ new Set([
|
|
689
|
-
"allOf",
|
|
690
|
-
"anyOf",
|
|
691
|
-
"items",
|
|
692
|
-
"oneOf",
|
|
693
|
-
"prefixItems"
|
|
694
|
-
]);
|
|
695
|
-
const SCHEMA_LITERAL_KEYS = /* @__PURE__ */ new Set([
|
|
696
|
-
"const",
|
|
697
|
-
"default",
|
|
698
|
-
"enum",
|
|
699
|
-
"examples"
|
|
700
|
-
]);
|
|
701
|
-
function tryResolveLocalRef(ref, defs, rootDocument) {
|
|
702
|
-
const match = ref.match(/^#\/(\$defs|definitions)\/([^/]+)(?:\/(.*))?$/);
|
|
703
|
-
if (match && defs) {
|
|
704
|
-
const namespace = match[1] === "$defs" ? defs.$defs : defs.definitions;
|
|
705
|
-
const name = decodeJsonPointerSegment(match[2] ?? "");
|
|
706
|
-
const resolved = name ? namespace.get(name) : void 0;
|
|
707
|
-
if (resolved !== void 0) return resolveJsonPointerPath(resolved, match[3] ? match[3].split("/") : []);
|
|
708
|
-
}
|
|
709
|
-
return resolveLocalJsonPointer(rootDocument, ref);
|
|
710
|
-
}
|
|
711
|
-
function inlineLocalSchemaRefsWithDefs(schema, defs, refStack, state, rootDocument) {
|
|
712
|
-
if (!schema || typeof schema !== "object") return schema;
|
|
713
|
-
if (Array.isArray(schema)) return schema.map((entry) => inlineLocalSchemaRefsWithDefs(entry, defs, refStack, state, rootDocument));
|
|
714
|
-
const obj = schema;
|
|
715
|
-
const nextDefs = extendSchemaDefs(defs, obj);
|
|
716
|
-
const refValue = typeof obj.$ref === "string" ? obj.$ref : void 0;
|
|
717
|
-
if (refValue) {
|
|
718
|
-
if (refStack?.has(refValue)) return {};
|
|
719
|
-
const resolved = tryResolveLocalRef(refValue, nextDefs, rootDocument);
|
|
720
|
-
if (resolved === void 0) {
|
|
721
|
-
if (refValue.startsWith("#/")) state.unresolvedLocalRefs = true;
|
|
722
|
-
return { ...obj };
|
|
723
|
-
}
|
|
724
|
-
const nextRefStack = refStack ? new Set(refStack) : /* @__PURE__ */ new Set();
|
|
725
|
-
nextRefStack.add(refValue);
|
|
726
|
-
const inlined = inlineLocalSchemaRefsWithDefs(resolved, nextDefs, nextRefStack, state, rootDocument);
|
|
727
|
-
if (!inlined || typeof inlined !== "object" || Array.isArray(inlined)) return inlined;
|
|
728
|
-
const result = { ...inlined };
|
|
729
|
-
copySchemaMeta(obj, result);
|
|
730
|
-
if (obj.nullable === true) result.nullable = true;
|
|
731
|
-
return result;
|
|
732
|
-
}
|
|
733
|
-
const result = {};
|
|
734
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
735
|
-
if (key === "$defs" || key === "definitions" || key === "components") continue;
|
|
736
|
-
if (SCHEMA_LITERAL_KEYS.has(key)) {
|
|
737
|
-
setOwnSchemaProperty(result, key, value);
|
|
738
|
-
continue;
|
|
739
|
-
}
|
|
740
|
-
if (SCHEMA_MAP_KEYS.has(key) && isRecord(value)) {
|
|
741
|
-
const entries = Object.entries(value);
|
|
742
|
-
for (const entry of entries) entry[1] = inlineLocalSchemaRefsWithDefs(entry[1], nextDefs, refStack, state, rootDocument);
|
|
743
|
-
setOwnSchemaProperty(result, key, Object.fromEntries(entries));
|
|
744
|
-
continue;
|
|
745
|
-
}
|
|
746
|
-
if (SCHEMA_OBJECT_KEYS.has(key) && isRecord(value)) {
|
|
747
|
-
setOwnSchemaProperty(result, key, inlineLocalSchemaRefsWithDefs(value, nextDefs, refStack, state, rootDocument));
|
|
748
|
-
continue;
|
|
749
|
-
}
|
|
750
|
-
if (SCHEMA_ARRAY_KEYS.has(key) && Array.isArray(value)) {
|
|
751
|
-
setOwnSchemaProperty(result, key, value.map((entry) => inlineLocalSchemaRefsWithDefs(entry, nextDefs, refStack, state, rootDocument)));
|
|
752
|
-
continue;
|
|
753
|
-
}
|
|
754
|
-
setOwnSchemaProperty(result, key, value);
|
|
755
|
-
}
|
|
756
|
-
if (state.unresolvedLocalRefs) {
|
|
757
|
-
if ("$defs" in obj) result.$defs = obj.$defs;
|
|
758
|
-
if ("definitions" in obj) result.definitions = obj.definitions;
|
|
759
|
-
if ("components" in obj) result.components = obj.components;
|
|
760
|
-
}
|
|
761
|
-
return result;
|
|
762
|
-
}
|
|
763
|
-
/** Inline local $ref pointers so providers receive self-contained tool schemas. */
|
|
764
|
-
function inlineLocalToolSchemaRefs(schema) {
|
|
765
|
-
if (!schema || typeof schema !== "object") return schema;
|
|
766
|
-
const schemaRecord = schema;
|
|
767
|
-
return inlineLocalSchemaRefsWithDefs(schema, Array.isArray(schema) ? extendSchemaDefs(void 0, schemaRecord) : void 0, void 0, { unresolvedLocalRefs: false }, schema);
|
|
768
|
-
}
|
|
769
738
|
const OPENAPI_SCHEMA_ANNOTATION_KEYS = /* @__PURE__ */ new Set([
|
|
770
739
|
"discriminator",
|
|
771
740
|
"externalDocs",
|
|
@@ -860,9 +829,6 @@ function normalizeOpenApiSchemaKeywords(schema) {
|
|
|
860
829
|
return changed || nullable ? normalized ?? schema : schema;
|
|
861
830
|
}
|
|
862
831
|
function normalizeToolParameterSchemaUncached(schema, options) {
|
|
863
|
-
const inlinedSchema = normalizeOpenApiSchemaKeywords(inlineLocalToolSchemaRefs(schema));
|
|
864
|
-
const schemaRecord = inlinedSchema && typeof inlinedSchema === "object" ? inlinedSchema : void 0;
|
|
865
|
-
if (!schemaRecord) return inlinedSchema;
|
|
866
832
|
const normalizedProvider = normalizeLowercaseStringOrEmpty(options?.modelProvider);
|
|
867
833
|
const normalizedModelId = normalizeLowercaseStringOrEmpty(options?.modelId);
|
|
868
834
|
const normalizedToolSchemaProfile = normalizeLowercaseStringOrEmpty(options?.modelCompat?.toolSchemaProfile);
|
|
@@ -871,36 +837,37 @@ function normalizeToolParameterSchemaUncached(schema, options) {
|
|
|
871
837
|
const unsupportedToolSchemaKeywords = resolveUnsupportedToolSchemaKeywords(options?.modelCompat);
|
|
872
838
|
const omitEmptyArrayItems = shouldOmitEmptyArrayItems(options?.modelCompat);
|
|
873
839
|
const isLlamacppGbnfProfile = normalizedToolSchemaProfile === "llamacpp";
|
|
840
|
+
const inlinedSchema = normalizeOpenApiSchemaKeywords(normalizedProvider === "openai" && !isGeminiProvider && !isLlamacppGbnfProfile && ![
|
|
841
|
+
"$ref",
|
|
842
|
+
"$defs",
|
|
843
|
+
"definitions"
|
|
844
|
+
].some((key) => unsupportedToolSchemaKeywords.has(key)) && canPreserveRootSchemaRefs(schema) ? schema : inlineLocalToolSchemaRefs(schema));
|
|
845
|
+
const schemaRecord = inlinedSchema && typeof inlinedSchema === "object" ? inlinedSchema : void 0;
|
|
846
|
+
if (!schemaRecord) return inlinedSchema;
|
|
874
847
|
function applyProviderCleaning(s) {
|
|
875
848
|
let arrayItemsCompatibleSchema = normalizeArraySchemaItems(s, omitEmptyArrayItems ? "normalize" : "add");
|
|
876
849
|
if (isLlamacppGbnfProfile) arrayItemsCompatibleSchema = cleanSchemaForLlamacppGbnf(arrayItemsCompatibleSchema);
|
|
877
|
-
if (isGeminiProvider && !isAnthropicProvider)
|
|
878
|
-
|
|
879
|
-
return unsupportedToolSchemaKeywords.size > 0 ? stripUnsupportedSchemaKeywords(geminiCompatibleSchema, unsupportedToolSchemaKeywords) : geminiCompatibleSchema;
|
|
880
|
-
}
|
|
881
|
-
if (unsupportedToolSchemaKeywords.size > 0) return stripUnsupportedSchemaKeywords(arrayItemsCompatibleSchema, unsupportedToolSchemaKeywords);
|
|
850
|
+
if (isGeminiProvider && !isAnthropicProvider) arrayItemsCompatibleSchema = cleanSchemaForGemini(arrayItemsCompatibleSchema);
|
|
851
|
+
if (unsupportedToolSchemaKeywords.size > 0) arrayItemsCompatibleSchema = stripUnsupportedSchemaKeywords(arrayItemsCompatibleSchema, unsupportedToolSchemaKeywords);
|
|
882
852
|
return arrayItemsCompatibleSchema;
|
|
883
853
|
}
|
|
884
|
-
const
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
type: "object",
|
|
890
|
-
properties: isRecord(schemaRecord.properties) ? schemaRecord.properties : {}
|
|
891
|
-
});
|
|
892
|
-
if (isTypedObjectSchemaMissingValidProperties(schemaRecord, conditionalKey)) return applyProviderCleaning({
|
|
893
|
-
...schemaRecord,
|
|
894
|
-
properties: {}
|
|
895
|
-
});
|
|
896
|
-
if (!flattenableVariantKey) {
|
|
897
|
-
if (isTrulyEmptySchema(schemaRecord)) return applyProviderCleaning({
|
|
898
|
-
type: "object",
|
|
854
|
+
const flattenableVariantKey = Array.isArray(schemaRecord.anyOf) ? "anyOf" : Array.isArray(schemaRecord.oneOf) ? "oneOf" : void 0;
|
|
855
|
+
if (!flattenableVariantKey && !Array.isArray(schemaRecord.allOf)) {
|
|
856
|
+
const hasProperties = isRecord(schemaRecord.properties);
|
|
857
|
+
if (schemaRecord.type === "object") return applyProviderCleaning(hasProperties ? schemaRecord : {
|
|
858
|
+
...schemaRecord,
|
|
899
859
|
properties: {}
|
|
900
860
|
});
|
|
901
|
-
if (
|
|
902
|
-
|
|
861
|
+
if (!("type" in schemaRecord) && (hasProperties || Array.isArray(schemaRecord.required))) return applyProviderCleaning({
|
|
862
|
+
...schemaRecord,
|
|
863
|
+
type: "object",
|
|
864
|
+
properties: hasProperties ? schemaRecord.properties : {}
|
|
865
|
+
});
|
|
903
866
|
}
|
|
867
|
+
if (!flattenableVariantKey) return applyProviderCleaning(Object.keys(schemaRecord).length === 0 ? {
|
|
868
|
+
type: "object",
|
|
869
|
+
properties: {}
|
|
870
|
+
} : inlinedSchema);
|
|
904
871
|
const variants = schemaRecord[flattenableVariantKey];
|
|
905
872
|
const mergedProperties = isRecord(schemaRecord.properties) ? { ...schemaRecord.properties } : {};
|
|
906
873
|
const requiredCounts = /* @__PURE__ */ new Map();
|
|
@@ -919,11 +886,10 @@ function normalizeToolParameterSchemaUncached(schema, options) {
|
|
|
919
886
|
}
|
|
920
887
|
const baseRequired = Array.isArray(schemaRecord.required) ? schemaRecord.required.filter((key) => typeof key === "string") : void 0;
|
|
921
888
|
const mergedRequired = baseRequired && baseRequired.length > 0 ? baseRequired : objectVariants > 0 ? Array.from(requiredCounts.entries()).filter(([, count]) => count === objectVariants).map(([key]) => key) : void 0;
|
|
922
|
-
const nextSchema = { ...schemaRecord };
|
|
923
889
|
return applyProviderCleaning({
|
|
924
890
|
type: "object",
|
|
925
|
-
...typeof
|
|
926
|
-
...typeof
|
|
891
|
+
...typeof schemaRecord.title === "string" ? { title: schemaRecord.title } : {},
|
|
892
|
+
...typeof schemaRecord.description === "string" ? { description: schemaRecord.description } : {},
|
|
927
893
|
properties: Object.keys(mergedProperties).length > 0 ? mergedProperties : schemaRecord.properties ?? {},
|
|
928
894
|
...mergedRequired && mergedRequired.length > 0 ? { required: mergedRequired } : {},
|
|
929
895
|
additionalProperties: "additionalProperties" in schemaRecord ? schemaRecord.additionalProperties : true
|
|
@@ -939,14 +905,6 @@ function normalizeToolParameterSchema(schema, options) {
|
|
|
939
905
|
}
|
|
940
906
|
//#endregion
|
|
941
907
|
//#region packages/ai/src/providers/openai-tool-schema-compat.ts
|
|
942
|
-
const OPENAI_STRICT_COMPAT_SCHEMA_MAP_KEYS = /* @__PURE__ */ new Set([
|
|
943
|
-
"$defs",
|
|
944
|
-
"definitions",
|
|
945
|
-
"dependentSchemas",
|
|
946
|
-
"dependencies",
|
|
947
|
-
"patternProperties",
|
|
948
|
-
"properties"
|
|
949
|
-
]);
|
|
950
908
|
const OPENAI_NULLABLE_ANNOTATION_KEYS = /* @__PURE__ */ new Set([
|
|
951
909
|
"default",
|
|
952
910
|
"description",
|
|
@@ -954,39 +912,22 @@ const OPENAI_NULLABLE_ANNOTATION_KEYS = /* @__PURE__ */ new Set([
|
|
|
954
912
|
"format",
|
|
955
913
|
"title"
|
|
956
914
|
]);
|
|
957
|
-
const OPENAI_STRICT_COMPAT_SCHEMA_NESTED_KEYS =
|
|
958
|
-
"additionalItems",
|
|
959
|
-
"additionalProperties",
|
|
960
|
-
"allOf",
|
|
961
|
-
"anyOf",
|
|
962
|
-
"contains",
|
|
963
|
-
"contentSchema",
|
|
964
|
-
"else",
|
|
965
|
-
"if",
|
|
966
|
-
"items",
|
|
967
|
-
"not",
|
|
968
|
-
"oneOf",
|
|
969
|
-
"prefixItems",
|
|
970
|
-
"propertyNames",
|
|
971
|
-
"then",
|
|
972
|
-
"unevaluatedItems",
|
|
973
|
-
"unevaluatedProperties"
|
|
974
|
-
]);
|
|
915
|
+
const OPENAI_STRICT_COMPAT_SCHEMA_NESTED_KEYS = new Set([...SCHEMA_OBJECT_KEYS$1, ...SCHEMA_ARRAY_KEYS$1].toSorted());
|
|
975
916
|
function normalizeOpenAIStrictCompatSchemaMap(schema) {
|
|
976
|
-
if (!
|
|
917
|
+
if (!isRecord(schema)) return schema;
|
|
977
918
|
let changed = false;
|
|
978
919
|
const normalized = Object.fromEntries(Object.entries(schema).map(([key, value]) => {
|
|
979
|
-
const next = normalizeOpenAIStrictCompatSchemaRecursive(value
|
|
920
|
+
const next = normalizeOpenAIStrictCompatSchemaRecursive(value);
|
|
980
921
|
changed ||= next !== value;
|
|
981
922
|
return [key, next];
|
|
982
923
|
}));
|
|
983
924
|
return changed ? normalized : schema;
|
|
984
925
|
}
|
|
985
|
-
function normalizeOpenAIStrictCompatSchemaRecursive(schema,
|
|
926
|
+
function normalizeOpenAIStrictCompatSchemaRecursive(schema, promoteEmptyObject = false) {
|
|
986
927
|
if (Array.isArray(schema)) {
|
|
987
928
|
let changed = false;
|
|
988
929
|
const normalized = schema.map((entry) => {
|
|
989
|
-
const next = normalizeOpenAIStrictCompatSchemaRecursive(entry
|
|
930
|
+
const next = normalizeOpenAIStrictCompatSchemaRecursive(entry);
|
|
990
931
|
changed ||= next !== entry;
|
|
991
932
|
return next;
|
|
992
933
|
});
|
|
@@ -1002,13 +943,13 @@ function normalizeOpenAIStrictCompatSchemaRecursive(schema, options) {
|
|
|
1002
943
|
changed = true;
|
|
1003
944
|
return [];
|
|
1004
945
|
}
|
|
1005
|
-
const next =
|
|
946
|
+
const next = SCHEMA_MAP_KEYS$1.has(key) ? normalizeOpenAIStrictCompatSchemaMap(value) : OPENAI_STRICT_COMPAT_SCHEMA_NESTED_KEYS.has(key) ? normalizeOpenAIStrictCompatSchemaRecursive(value) : value;
|
|
1006
947
|
changed ||= next !== value;
|
|
1007
948
|
return [[key, next]];
|
|
1008
949
|
});
|
|
1009
950
|
const normalized = Object.fromEntries(entries);
|
|
1010
951
|
if (Object.keys(normalized).length === 0) {
|
|
1011
|
-
if (!
|
|
952
|
+
if (!promoteEmptyObject) return schema;
|
|
1012
953
|
return {
|
|
1013
954
|
type: "object",
|
|
1014
955
|
properties: {},
|
|
@@ -1026,7 +967,7 @@ function normalizeOpenAIStrictCompatSchemaRecursive(schema, options) {
|
|
|
1026
967
|
normalized.properties = {};
|
|
1027
968
|
changed = true;
|
|
1028
969
|
}
|
|
1029
|
-
const hasEmptyProperties =
|
|
970
|
+
const hasEmptyProperties = isRecord(normalized.properties) && Object.keys(normalized.properties).length === 0;
|
|
1030
971
|
if (normalized.type === "object" && !Array.isArray(normalized.required) && hasEmptyProperties) {
|
|
1031
972
|
normalized.required = [];
|
|
1032
973
|
changed = true;
|
|
@@ -1039,7 +980,7 @@ function normalizeOpenAIStrictCompatSchemaRecursive(schema, options) {
|
|
|
1039
980
|
}
|
|
1040
981
|
/** Repairs recoverable OpenAI tool-schema shapes before canonical normalization. */
|
|
1041
982
|
function normalizeOpenAIStrictCompatSchema(schema) {
|
|
1042
|
-
return normalizeOpenAIStrictCompatSchemaRecursive(schema,
|
|
983
|
+
return normalizeOpenAIStrictCompatSchemaRecursive(schema, true);
|
|
1043
984
|
}
|
|
1044
985
|
/** Finds schema paths that violate OpenAI strict tool-schema requirements. */
|
|
1045
986
|
function findOpenAIStrictSchemaViolations(schema, path, options) {
|
|
@@ -1056,7 +997,7 @@ function findOpenAIStrictSchemaViolations(schema, path, options) {
|
|
|
1056
997
|
"allOf"
|
|
1057
998
|
]) if (key in record) violations.push(`${path}.${key}`);
|
|
1058
999
|
if (Array.isArray(record.type)) violations.push(`${path}.type`);
|
|
1059
|
-
const properties =
|
|
1000
|
+
const properties = isRecord(record.properties) ? record.properties : void 0;
|
|
1060
1001
|
if (record.type === "object") {
|
|
1061
1002
|
if (record.additionalProperties !== false) violations.push(`${path}.additionalProperties`);
|
|
1062
1003
|
const required = Array.isArray(record.required) ? record.required.filter((entry) => typeof entry === "string") : void 0;
|
|
@@ -1066,9 +1007,9 @@ function findOpenAIStrictSchemaViolations(schema, path, options) {
|
|
|
1066
1007
|
for (const key of Object.keys(properties)) if (!requiredSet.has(key)) violations.push(`${path}.required.${key}`);
|
|
1067
1008
|
}
|
|
1068
1009
|
}
|
|
1069
|
-
for (const key of
|
|
1010
|
+
for (const key of SCHEMA_MAP_KEYS$1) {
|
|
1070
1011
|
const schemaMap = record[key];
|
|
1071
|
-
if (!
|
|
1012
|
+
if (!isRecord(schemaMap)) continue;
|
|
1072
1013
|
for (const [entryKey, value] of Object.entries(schemaMap)) violations.push(...findOpenAIStrictSchemaViolations(value, `${path}.${key}.${entryKey}`));
|
|
1073
1014
|
}
|
|
1074
1015
|
for (const key of OPENAI_STRICT_COMPAT_SCHEMA_NESTED_KEYS) {
|
|
@@ -1079,11 +1020,6 @@ function findOpenAIStrictSchemaViolations(schema, path, options) {
|
|
|
1079
1020
|
}
|
|
1080
1021
|
//#endregion
|
|
1081
1022
|
//#region packages/ai/src/providers/openai-tool-schema.ts
|
|
1082
|
-
/**
|
|
1083
|
-
* OpenAI strict JSON-schema normalization for tool inventories and request payloads.
|
|
1084
|
-
*
|
|
1085
|
-
* Caches normalized object inputs by provider compatibility so repeated inventory builds preserve identity.
|
|
1086
|
-
*/
|
|
1087
1023
|
const strictOpenAISchemaCache = createToolSchemaNormalizationCache(8);
|
|
1088
1024
|
function resolveToolSchemaModelCompat(compat) {
|
|
1089
1025
|
if (!compat) return;
|
|
@@ -1126,7 +1062,7 @@ function normalizeStrictOpenAIJsonSchemaRecursive(schema, depth) {
|
|
|
1126
1062
|
return [key, next];
|
|
1127
1063
|
}));
|
|
1128
1064
|
if (normalized.type === "object") {
|
|
1129
|
-
const properties =
|
|
1065
|
+
const properties = isRecord(normalized.properties) ? normalized.properties : void 0;
|
|
1130
1066
|
if (properties && Object.keys(properties).length === 0 && !Array.isArray(normalized.required)) {
|
|
1131
1067
|
normalized.required = [];
|
|
1132
1068
|
changed = true;
|
|
@@ -1171,14 +1107,14 @@ function isStrictOpenAIJsonSchemaCompatibleRecursive(schema) {
|
|
|
1171
1107
|
if (Array.isArray(record.type)) return false;
|
|
1172
1108
|
if (record.type === "object" && record.additionalProperties !== false) return false;
|
|
1173
1109
|
if (record.type === "object") {
|
|
1174
|
-
const properties =
|
|
1110
|
+
const properties = isRecord(record.properties) ? record.properties : {};
|
|
1175
1111
|
const required = Array.isArray(record.required) ? record.required.filter((entry) => typeof entry === "string") : void 0;
|
|
1176
1112
|
if (!required) return false;
|
|
1177
1113
|
const requiredSet = new Set(required);
|
|
1178
1114
|
if (Object.keys(properties).some((key) => !requiredSet.has(key))) return false;
|
|
1179
1115
|
}
|
|
1180
1116
|
return Object.entries(record).every(([key, entry]) => {
|
|
1181
|
-
if (key === "properties" &&
|
|
1117
|
+
if (key === "properties" && isRecord(entry)) return Object.values(entry).every(isStrictOpenAIJsonSchemaCompatibleRecursive);
|
|
1182
1118
|
return isStrictOpenAIJsonSchemaCompatibleRecursive(entry);
|
|
1183
1119
|
});
|
|
1184
1120
|
}
|