@ai-sdk/openai 4.0.80 → 4.0.81
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/CHANGELOG.md +6 -0
- package/dist/index.js +42 -4
- package/dist/index.js.map +1 -1
- package/dist/internal/index.js +41 -3
- package/dist/internal/index.js.map +1 -1
- package/package.json +1 -1
- package/src/normalize-openai-json-schema.ts +76 -3
package/package.json
CHANGED
|
@@ -15,6 +15,10 @@ import {
|
|
|
15
15
|
*
|
|
16
16
|
* OpenAI also does not support regex lookaround in JSON Schema `pattern`
|
|
17
17
|
* values. Those patterns are removed and left to client-side validation.
|
|
18
|
+
*
|
|
19
|
+
* Zod 4 represents recursive references as singleton `allOf` schemas. OpenAI
|
|
20
|
+
* does not support `allOf`, but a singleton local reference can be rewritten
|
|
21
|
+
* to a direct reference without changing its validation behavior.
|
|
18
22
|
*/
|
|
19
23
|
export function normalizeOpenAIJsonSchema(schema: JSONSchema7): {
|
|
20
24
|
schema: JSONSchema7;
|
|
@@ -23,7 +27,7 @@ export function normalizeOpenAIJsonSchema(schema: JSONSchema7): {
|
|
|
23
27
|
let removedPropertyNames = false;
|
|
24
28
|
let removedLookaroundPattern = false;
|
|
25
29
|
|
|
26
|
-
const normalizedSchema = normalizeSchema(schema);
|
|
30
|
+
const normalizedSchema = normalizeSchema(schema, true);
|
|
27
31
|
|
|
28
32
|
const warnings: SharedV4Warning[] = [];
|
|
29
33
|
|
|
@@ -50,7 +54,7 @@ export function normalizeOpenAIJsonSchema(schema: JSONSchema7): {
|
|
|
50
54
|
warnings,
|
|
51
55
|
};
|
|
52
56
|
|
|
53
|
-
function normalizeSchema(schema: JSONSchema7): JSONSchema7 {
|
|
57
|
+
function normalizeSchema(schema: JSONSchema7, isRoot = false): JSONSchema7 {
|
|
54
58
|
const propertyNames = schema.propertyNames;
|
|
55
59
|
|
|
56
60
|
if (propertyNames != null) {
|
|
@@ -160,7 +164,76 @@ export function normalizeOpenAIJsonSchema(schema: JSONSchema7): {
|
|
|
160
164
|
}
|
|
161
165
|
}
|
|
162
166
|
|
|
163
|
-
|
|
167
|
+
const reference = getSingletonReference(normalizedSchema);
|
|
168
|
+
|
|
169
|
+
if (reference == null) {
|
|
170
|
+
return normalizedSchema;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const { allOf: _allOf, ...schemaWithoutAllOf } = normalizedSchema;
|
|
174
|
+
|
|
175
|
+
if (!isRoot) {
|
|
176
|
+
// A one-item allOf has the same validation behavior as its reference.
|
|
177
|
+
return {
|
|
178
|
+
...schemaWithoutAllOf,
|
|
179
|
+
$ref: reference,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const referencedSchema = getLocalReferenceSchema(
|
|
184
|
+
reference,
|
|
185
|
+
normalizedSchema,
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
// OpenAI requires an object at the schema root, so a local root reference
|
|
189
|
+
// must be expanded instead of being sent as a direct $ref.
|
|
190
|
+
if (referencedSchema == null) {
|
|
191
|
+
return normalizedSchema;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return {
|
|
195
|
+
...referencedSchema,
|
|
196
|
+
...schemaWithoutAllOf,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function getSingletonReference(schema: JSONSchema7): string | undefined {
|
|
201
|
+
// Do not rewrite intersections: only a single reference is equivalent to
|
|
202
|
+
// a direct $ref.
|
|
203
|
+
if (schema.allOf?.length !== 1) {
|
|
204
|
+
return undefined;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const [allOfSchema] = schema.allOf;
|
|
208
|
+
|
|
209
|
+
return typeof allOfSchema === 'object' &&
|
|
210
|
+
allOfSchema != null &&
|
|
211
|
+
Object.keys(allOfSchema).length === 1 &&
|
|
212
|
+
typeof allOfSchema.$ref === 'string'
|
|
213
|
+
? allOfSchema.$ref
|
|
214
|
+
: undefined;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function getLocalReferenceSchema(
|
|
218
|
+
reference: string,
|
|
219
|
+
schema: JSONSchema7,
|
|
220
|
+
): JSONSchema7 | undefined {
|
|
221
|
+
const match = /^#\/(definitions|\$defs)\/(.+)$/.exec(reference);
|
|
222
|
+
|
|
223
|
+
if (match == null) {
|
|
224
|
+
return undefined;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const [, keyword, encodedName] = match;
|
|
228
|
+
const name = encodedName.replace(/~1/g, '/').replace(/~0/g, '~');
|
|
229
|
+
const definition =
|
|
230
|
+
keyword === 'definitions'
|
|
231
|
+
? schema.definitions?.[name]
|
|
232
|
+
: schema.$defs?.[name];
|
|
233
|
+
|
|
234
|
+
return typeof definition === 'object' && definition != null
|
|
235
|
+
? definition
|
|
236
|
+
: undefined;
|
|
164
237
|
}
|
|
165
238
|
|
|
166
239
|
function normalizeSchemaRecord(
|