@mastra/schema-compat 1.0.0-beta.6 → 1.0.0-beta.8
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 +20 -0
- package/dist/{chunk-3RG3ZAXL.js → chunk-7UW726BK.js} +52 -3
- package/dist/chunk-7UW726BK.js.map +1 -0
- package/dist/{chunk-MMU7PH2H.cjs → chunk-ZXNJQOPF.cjs} +52 -3
- package/dist/chunk-ZXNJQOPF.cjs.map +1 -0
- package/dist/index.cjs +47 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +45 -1
- package/dist/index.js.map +1 -1
- package/dist/provider-compats/openai.d.ts +15 -0
- package/dist/provider-compats/openai.d.ts.map +1 -1
- package/dist/zod-to-json.cjs +2 -2
- package/dist/zod-to-json.d.ts.map +1 -1
- package/dist/zod-to-json.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-3RG3ZAXL.js.map +0 -1
- package/dist/chunk-MMU7PH2H.cjs.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# @mastra/schema-compat
|
|
2
2
|
|
|
3
|
+
## 1.0.0-beta.8
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Fixed agent network mode failing with "Cannot read properties of undefined" error when tools or workflows don't have an `inputSchema` defined. ([#12063](https://github.com/mastra-ai/mastra/pull/12063))
|
|
8
|
+
- **@mastra/core:** Fixed `getRoutingAgent()` to handle tools and workflows without `inputSchema` by providing a default empty schema fallback.
|
|
9
|
+
- **@mastra/schema-compat:** Fixed Zod v4 optional/nullable fields producing invalid JSON schema for OpenAI structured outputs. OpenAI now correctly receives `type: ["string", "null"]` instead of `anyOf` patterns that were rejected with "must have a 'type' key" error.
|
|
10
|
+
|
|
11
|
+
## 1.0.0-beta.7
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- Fixed OpenAI schema validation error when using passthrough schemas with tools like `vectorQueryTool`. ([#11846](https://github.com/mastra-ai/mastra/pull/11846))
|
|
16
|
+
|
|
17
|
+
**What was happening:** Tools using `.passthrough()` or `z.looseObject()` schemas (like the RAG `vectorQueryTool`) would fail with OpenAI models, returning the error: "Invalid schema for function: In context=('additionalProperties',), schema must have a 'type' key."
|
|
18
|
+
|
|
19
|
+
**What changed:** The OpenAI schema compatibility layer now converts passthrough schemas to strict object schemas, producing valid `additionalProperties: false` instead of the invalid empty object `{}` that Zod v4 generates.
|
|
20
|
+
|
|
21
|
+
Fixes #11823
|
|
22
|
+
|
|
3
23
|
## 1.0.0-beta.6
|
|
4
24
|
|
|
5
25
|
### Patch Changes
|
|
@@ -50,11 +50,59 @@ function patchRecordSchemas(schema) {
|
|
|
50
50
|
}
|
|
51
51
|
return schema;
|
|
52
52
|
}
|
|
53
|
+
function fixAnyOfNullable(schema) {
|
|
54
|
+
if (typeof schema !== "object" || schema === null) {
|
|
55
|
+
return schema;
|
|
56
|
+
}
|
|
57
|
+
const result = { ...schema };
|
|
58
|
+
if (result.anyOf && Array.isArray(result.anyOf) && result.anyOf.length === 2) {
|
|
59
|
+
const nullSchema = result.anyOf.find((s) => typeof s === "object" && s !== null && s.type === "null");
|
|
60
|
+
const otherSchema = result.anyOf.find((s) => typeof s === "object" && s !== null && s.type !== "null");
|
|
61
|
+
if (nullSchema && otherSchema && typeof otherSchema === "object" && otherSchema.type) {
|
|
62
|
+
const { anyOf, ...rest } = result;
|
|
63
|
+
const fixedRest = fixAnyOfNullable(rest);
|
|
64
|
+
const fixedOther = fixAnyOfNullable(otherSchema);
|
|
65
|
+
return {
|
|
66
|
+
...fixedRest,
|
|
67
|
+
...fixedOther,
|
|
68
|
+
type: Array.isArray(fixedOther.type) ? [...fixedOther.type, "null"] : [fixedOther.type, "null"]
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (result.properties && typeof result.properties === "object" && !Array.isArray(result.properties)) {
|
|
73
|
+
result.properties = Object.fromEntries(
|
|
74
|
+
Object.entries(result.properties).map(([key, value]) => {
|
|
75
|
+
const propSchema = value;
|
|
76
|
+
if (typeof propSchema === "object" && propSchema !== null && !Array.isArray(propSchema) && Object.keys(propSchema).length === 0) {
|
|
77
|
+
return [key, { type: ["string", "number", "boolean", "null"] }];
|
|
78
|
+
}
|
|
79
|
+
return [key, fixAnyOfNullable(propSchema)];
|
|
80
|
+
})
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
if (result.items) {
|
|
84
|
+
if (Array.isArray(result.items)) {
|
|
85
|
+
result.items = result.items.map((item) => fixAnyOfNullable(item));
|
|
86
|
+
} else {
|
|
87
|
+
result.items = fixAnyOfNullable(result.items);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (result.anyOf && Array.isArray(result.anyOf)) {
|
|
91
|
+
result.anyOf = result.anyOf.map((s) => fixAnyOfNullable(s));
|
|
92
|
+
}
|
|
93
|
+
if (result.oneOf && Array.isArray(result.oneOf)) {
|
|
94
|
+
result.oneOf = result.oneOf.map((s) => fixAnyOfNullable(s));
|
|
95
|
+
}
|
|
96
|
+
if (result.allOf && Array.isArray(result.allOf)) {
|
|
97
|
+
result.allOf = result.allOf.map((s) => fixAnyOfNullable(s));
|
|
98
|
+
}
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
53
101
|
function zodToJsonSchema(zodSchema, target = "jsonSchema7", strategy = "relative") {
|
|
54
102
|
const fn = "toJSONSchema";
|
|
55
103
|
if (fn in z) {
|
|
56
104
|
patchRecordSchemas(zodSchema);
|
|
57
|
-
|
|
105
|
+
const jsonSchema = z[fn](zodSchema, {
|
|
58
106
|
unrepresentable: "any",
|
|
59
107
|
override: (ctx) => {
|
|
60
108
|
const def = ctx.zodSchema?._def || ctx.zodSchema?._zod?.def;
|
|
@@ -64,6 +112,7 @@ function zodToJsonSchema(zodSchema, target = "jsonSchema7", strategy = "relative
|
|
|
64
112
|
}
|
|
65
113
|
}
|
|
66
114
|
});
|
|
115
|
+
return fixAnyOfNullable(jsonSchema);
|
|
67
116
|
} else {
|
|
68
117
|
return zodToJsonSchemaOriginal(zodSchema, {
|
|
69
118
|
$refStrategy: strategy,
|
|
@@ -73,5 +122,5 @@ function zodToJsonSchema(zodSchema, target = "jsonSchema7", strategy = "relative
|
|
|
73
122
|
}
|
|
74
123
|
|
|
75
124
|
export { zodToJsonSchema };
|
|
76
|
-
//# sourceMappingURL=chunk-
|
|
77
|
-
//# sourceMappingURL=chunk-
|
|
125
|
+
//# sourceMappingURL=chunk-7UW726BK.js.map
|
|
126
|
+
//# sourceMappingURL=chunk-7UW726BK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/zod-to-json.ts"],"names":[],"mappings":"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","file":"chunk-7UW726BK.js","sourcesContent":["import type { JSONSchema7 } from 'json-schema';\nimport { z } from 'zod';\nimport type { ZodSchema as ZodSchemaV3 } from 'zod/v3';\nimport type { ZodType as ZodSchemaV4 } from 'zod/v4';\nimport type { Targets } from 'zod-to-json-schema';\nimport zodToJsonSchemaOriginal from 'zod-to-json-schema';\n\n// Symbol to mark schemas as already patched (for idempotency)\nconst PATCHED = Symbol('__mastra_patched__');\n\n/**\n * Recursively patch Zod v4 record schemas that are missing valueType.\n * This fixes a bug in Zod v4 where z.record(valueSchema) doesn't set def.valueType.\n * The single-arg form should set valueType but instead only sets keyType.\n */\nfunction patchRecordSchemas(schema: any): any {\n if (!schema || typeof schema !== 'object') return schema;\n\n // Skip if already patched (idempotency check)\n if ((schema as any)[PATCHED]) return schema;\n (schema as any)[PATCHED] = true;\n\n // Check the _zod.def location (v4 structure)\n const def = schema._zod?.def;\n\n // Fix record schemas with missing valueType\n if (def?.type === 'record' && def.keyType && !def.valueType) {\n // The bug: z.record(valueSchema) puts the value in keyType instead of valueType\n // Fix: move it to valueType and set keyType to string (the default)\n def.valueType = def.keyType;\n def.keyType = (z as any).string();\n }\n\n // Recursively patch nested schemas\n if (!def) return schema;\n\n if (def.type === 'object' && def.shape) {\n const shape = typeof def.shape === 'function' ? def.shape() : def.shape;\n for (const key of Object.keys(shape)) {\n patchRecordSchemas(shape[key]);\n }\n }\n\n if (def.type === 'array' && def.element) {\n patchRecordSchemas(def.element);\n }\n\n if (def.type === 'union' && def.options) {\n def.options.forEach(patchRecordSchemas);\n }\n\n if (def.type === 'record') {\n if (def.keyType) patchRecordSchemas(def.keyType);\n if (def.valueType) patchRecordSchemas(def.valueType);\n }\n\n // Handle intersection types\n if (def.type === 'intersection') {\n if (def.left) patchRecordSchemas(def.left);\n if (def.right) patchRecordSchemas(def.right);\n }\n\n // Handle lazy types - patch the schema returned by the getter\n if (def.type === 'lazy') {\n // For lazy schemas, we need to patch the schema when it's accessed\n // Store the original getter and wrap it\n if (def.getter && typeof def.getter === 'function') {\n const originalGetter = def.getter;\n def.getter = function () {\n const innerSchema = originalGetter();\n if (innerSchema) {\n patchRecordSchemas(innerSchema);\n }\n return innerSchema;\n };\n }\n }\n\n // Handle wrapper types that have innerType\n // This covers: optional, nullable, default, catch, nullish, and any other wrappers\n if (def.innerType) {\n patchRecordSchemas(def.innerType);\n }\n\n return schema;\n}\n\n/**\n * Recursively fixes anyOf patterns that some providers (like OpenAI) don't accept.\n * Converts anyOf: [{type: X}, {type: \"null\"}] to type: [X, \"null\"]\n * Also fixes empty {} property schemas by converting to a union of primitive types.\n */\nfunction fixAnyOfNullable(schema: JSONSchema7): JSONSchema7 {\n if (typeof schema !== 'object' || schema === null) {\n return schema;\n }\n\n const result = { ...schema };\n\n // Fix anyOf pattern: [{type: X}, {type: \"null\"}] or [{type: \"null\"}, {type: X}]\n if (result.anyOf && Array.isArray(result.anyOf) && result.anyOf.length === 2) {\n const nullSchema = result.anyOf.find((s: any) => typeof s === 'object' && s !== null && s.type === 'null');\n const otherSchema = result.anyOf.find((s: any) => typeof s === 'object' && s !== null && s.type !== 'null');\n\n if (nullSchema && otherSchema && typeof otherSchema === 'object' && otherSchema.type) {\n // Convert anyOf to type array format\n // Normalize sibling fields (like properties/items) before returning\n const { anyOf, ...rest } = result;\n const fixedRest = fixAnyOfNullable(rest as JSONSchema7);\n const fixedOther = fixAnyOfNullable(otherSchema as JSONSchema7);\n return {\n ...fixedRest,\n ...fixedOther,\n type: (Array.isArray(fixedOther.type)\n ? [...fixedOther.type, 'null']\n : [fixedOther.type, 'null']) as JSONSchema7['type'],\n };\n }\n }\n\n // Fix empty property schemas {} - OpenAI requires a type key\n if (result.properties && typeof result.properties === 'object' && !Array.isArray(result.properties)) {\n result.properties = Object.fromEntries(\n Object.entries(result.properties).map(([key, value]) => {\n const propSchema = value as JSONSchema7;\n\n // If property is an empty object {}, convert to allow primitive types\n // Note: We exclude 'object' (requires additionalProperties) and 'array' (requires items) for OpenAI\n if (\n typeof propSchema === 'object' &&\n propSchema !== null &&\n !Array.isArray(propSchema) &&\n Object.keys(propSchema).length === 0\n ) {\n return [key, { type: ['string', 'number', 'boolean', 'null'] as JSONSchema7['type'] }];\n }\n\n // Recursively fix nested schemas\n return [key, fixAnyOfNullable(propSchema)];\n }),\n );\n }\n\n // Recursively fix items in arrays\n if (result.items) {\n if (Array.isArray(result.items)) {\n result.items = result.items.map(item => fixAnyOfNullable(item as JSONSchema7));\n } else {\n result.items = fixAnyOfNullable(result.items as JSONSchema7);\n }\n }\n\n // Recursively fix anyOf/oneOf/allOf schemas\n if (result.anyOf && Array.isArray(result.anyOf)) {\n result.anyOf = result.anyOf.map(s => fixAnyOfNullable(s as JSONSchema7));\n }\n if (result.oneOf && Array.isArray(result.oneOf)) {\n result.oneOf = result.oneOf.map(s => fixAnyOfNullable(s as JSONSchema7));\n }\n if (result.allOf && Array.isArray(result.allOf)) {\n result.allOf = result.allOf.map(s => fixAnyOfNullable(s as JSONSchema7));\n }\n\n return result;\n}\n\nexport function zodToJsonSchema(\n zodSchema: ZodSchemaV3 | ZodSchemaV4,\n target: Targets = 'jsonSchema7',\n strategy: 'none' | 'seen' | 'root' | 'relative' = 'relative',\n): JSONSchema7 {\n const fn = 'toJSONSchema';\n\n if (fn in z) {\n // Zod v4 path - patch record schemas before converting\n patchRecordSchemas(zodSchema);\n\n const jsonSchema = (z as any)[fn](zodSchema, {\n unrepresentable: 'any',\n override: (ctx: any) => {\n // Handle both Zod v4 structures: _def directly or nested in _zod\n const def = ctx.zodSchema?._def || ctx.zodSchema?._zod?.def;\n // Check for date type using both possible property names\n if (def && (def.typeName === 'ZodDate' || def.type === 'date')) {\n ctx.jsonSchema.type = 'string';\n ctx.jsonSchema.format = 'date-time';\n }\n },\n }) satisfies JSONSchema7;\n\n // Fix anyOf patterns for nullable fields - required for OpenAI compatibility\n return fixAnyOfNullable(jsonSchema);\n } else {\n // Zod v3 path - use the original converter\n return zodToJsonSchemaOriginal(zodSchema as ZodSchemaV3, {\n $refStrategy: strategy,\n target,\n }) as JSONSchema7;\n }\n}\n"]}
|
|
@@ -56,11 +56,59 @@ function patchRecordSchemas(schema) {
|
|
|
56
56
|
}
|
|
57
57
|
return schema;
|
|
58
58
|
}
|
|
59
|
+
function fixAnyOfNullable(schema) {
|
|
60
|
+
if (typeof schema !== "object" || schema === null) {
|
|
61
|
+
return schema;
|
|
62
|
+
}
|
|
63
|
+
const result = { ...schema };
|
|
64
|
+
if (result.anyOf && Array.isArray(result.anyOf) && result.anyOf.length === 2) {
|
|
65
|
+
const nullSchema = result.anyOf.find((s) => typeof s === "object" && s !== null && s.type === "null");
|
|
66
|
+
const otherSchema = result.anyOf.find((s) => typeof s === "object" && s !== null && s.type !== "null");
|
|
67
|
+
if (nullSchema && otherSchema && typeof otherSchema === "object" && otherSchema.type) {
|
|
68
|
+
const { anyOf, ...rest } = result;
|
|
69
|
+
const fixedRest = fixAnyOfNullable(rest);
|
|
70
|
+
const fixedOther = fixAnyOfNullable(otherSchema);
|
|
71
|
+
return {
|
|
72
|
+
...fixedRest,
|
|
73
|
+
...fixedOther,
|
|
74
|
+
type: Array.isArray(fixedOther.type) ? [...fixedOther.type, "null"] : [fixedOther.type, "null"]
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (result.properties && typeof result.properties === "object" && !Array.isArray(result.properties)) {
|
|
79
|
+
result.properties = Object.fromEntries(
|
|
80
|
+
Object.entries(result.properties).map(([key, value]) => {
|
|
81
|
+
const propSchema = value;
|
|
82
|
+
if (typeof propSchema === "object" && propSchema !== null && !Array.isArray(propSchema) && Object.keys(propSchema).length === 0) {
|
|
83
|
+
return [key, { type: ["string", "number", "boolean", "null"] }];
|
|
84
|
+
}
|
|
85
|
+
return [key, fixAnyOfNullable(propSchema)];
|
|
86
|
+
})
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
if (result.items) {
|
|
90
|
+
if (Array.isArray(result.items)) {
|
|
91
|
+
result.items = result.items.map((item) => fixAnyOfNullable(item));
|
|
92
|
+
} else {
|
|
93
|
+
result.items = fixAnyOfNullable(result.items);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (result.anyOf && Array.isArray(result.anyOf)) {
|
|
97
|
+
result.anyOf = result.anyOf.map((s) => fixAnyOfNullable(s));
|
|
98
|
+
}
|
|
99
|
+
if (result.oneOf && Array.isArray(result.oneOf)) {
|
|
100
|
+
result.oneOf = result.oneOf.map((s) => fixAnyOfNullable(s));
|
|
101
|
+
}
|
|
102
|
+
if (result.allOf && Array.isArray(result.allOf)) {
|
|
103
|
+
result.allOf = result.allOf.map((s) => fixAnyOfNullable(s));
|
|
104
|
+
}
|
|
105
|
+
return result;
|
|
106
|
+
}
|
|
59
107
|
function zodToJsonSchema(zodSchema, target = "jsonSchema7", strategy = "relative") {
|
|
60
108
|
const fn = "toJSONSchema";
|
|
61
109
|
if (fn in zod.z) {
|
|
62
110
|
patchRecordSchemas(zodSchema);
|
|
63
|
-
|
|
111
|
+
const jsonSchema = zod.z[fn](zodSchema, {
|
|
64
112
|
unrepresentable: "any",
|
|
65
113
|
override: (ctx) => {
|
|
66
114
|
const def = ctx.zodSchema?._def || ctx.zodSchema?._zod?.def;
|
|
@@ -70,6 +118,7 @@ function zodToJsonSchema(zodSchema, target = "jsonSchema7", strategy = "relative
|
|
|
70
118
|
}
|
|
71
119
|
}
|
|
72
120
|
});
|
|
121
|
+
return fixAnyOfNullable(jsonSchema);
|
|
73
122
|
} else {
|
|
74
123
|
return zodToJsonSchemaOriginal__default.default(zodSchema, {
|
|
75
124
|
$refStrategy: strategy,
|
|
@@ -79,5 +128,5 @@ function zodToJsonSchema(zodSchema, target = "jsonSchema7", strategy = "relative
|
|
|
79
128
|
}
|
|
80
129
|
|
|
81
130
|
exports.zodToJsonSchema = zodToJsonSchema;
|
|
82
|
-
//# sourceMappingURL=chunk-
|
|
83
|
-
//# sourceMappingURL=chunk-
|
|
131
|
+
//# sourceMappingURL=chunk-ZXNJQOPF.cjs.map
|
|
132
|
+
//# sourceMappingURL=chunk-ZXNJQOPF.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/zod-to-json.ts"],"names":["z","zodToJsonSchemaOriginal"],"mappings":"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","file":"chunk-ZXNJQOPF.cjs","sourcesContent":["import type { JSONSchema7 } from 'json-schema';\nimport { z } from 'zod';\nimport type { ZodSchema as ZodSchemaV3 } from 'zod/v3';\nimport type { ZodType as ZodSchemaV4 } from 'zod/v4';\nimport type { Targets } from 'zod-to-json-schema';\nimport zodToJsonSchemaOriginal from 'zod-to-json-schema';\n\n// Symbol to mark schemas as already patched (for idempotency)\nconst PATCHED = Symbol('__mastra_patched__');\n\n/**\n * Recursively patch Zod v4 record schemas that are missing valueType.\n * This fixes a bug in Zod v4 where z.record(valueSchema) doesn't set def.valueType.\n * The single-arg form should set valueType but instead only sets keyType.\n */\nfunction patchRecordSchemas(schema: any): any {\n if (!schema || typeof schema !== 'object') return schema;\n\n // Skip if already patched (idempotency check)\n if ((schema as any)[PATCHED]) return schema;\n (schema as any)[PATCHED] = true;\n\n // Check the _zod.def location (v4 structure)\n const def = schema._zod?.def;\n\n // Fix record schemas with missing valueType\n if (def?.type === 'record' && def.keyType && !def.valueType) {\n // The bug: z.record(valueSchema) puts the value in keyType instead of valueType\n // Fix: move it to valueType and set keyType to string (the default)\n def.valueType = def.keyType;\n def.keyType = (z as any).string();\n }\n\n // Recursively patch nested schemas\n if (!def) return schema;\n\n if (def.type === 'object' && def.shape) {\n const shape = typeof def.shape === 'function' ? def.shape() : def.shape;\n for (const key of Object.keys(shape)) {\n patchRecordSchemas(shape[key]);\n }\n }\n\n if (def.type === 'array' && def.element) {\n patchRecordSchemas(def.element);\n }\n\n if (def.type === 'union' && def.options) {\n def.options.forEach(patchRecordSchemas);\n }\n\n if (def.type === 'record') {\n if (def.keyType) patchRecordSchemas(def.keyType);\n if (def.valueType) patchRecordSchemas(def.valueType);\n }\n\n // Handle intersection types\n if (def.type === 'intersection') {\n if (def.left) patchRecordSchemas(def.left);\n if (def.right) patchRecordSchemas(def.right);\n }\n\n // Handle lazy types - patch the schema returned by the getter\n if (def.type === 'lazy') {\n // For lazy schemas, we need to patch the schema when it's accessed\n // Store the original getter and wrap it\n if (def.getter && typeof def.getter === 'function') {\n const originalGetter = def.getter;\n def.getter = function () {\n const innerSchema = originalGetter();\n if (innerSchema) {\n patchRecordSchemas(innerSchema);\n }\n return innerSchema;\n };\n }\n }\n\n // Handle wrapper types that have innerType\n // This covers: optional, nullable, default, catch, nullish, and any other wrappers\n if (def.innerType) {\n patchRecordSchemas(def.innerType);\n }\n\n return schema;\n}\n\n/**\n * Recursively fixes anyOf patterns that some providers (like OpenAI) don't accept.\n * Converts anyOf: [{type: X}, {type: \"null\"}] to type: [X, \"null\"]\n * Also fixes empty {} property schemas by converting to a union of primitive types.\n */\nfunction fixAnyOfNullable(schema: JSONSchema7): JSONSchema7 {\n if (typeof schema !== 'object' || schema === null) {\n return schema;\n }\n\n const result = { ...schema };\n\n // Fix anyOf pattern: [{type: X}, {type: \"null\"}] or [{type: \"null\"}, {type: X}]\n if (result.anyOf && Array.isArray(result.anyOf) && result.anyOf.length === 2) {\n const nullSchema = result.anyOf.find((s: any) => typeof s === 'object' && s !== null && s.type === 'null');\n const otherSchema = result.anyOf.find((s: any) => typeof s === 'object' && s !== null && s.type !== 'null');\n\n if (nullSchema && otherSchema && typeof otherSchema === 'object' && otherSchema.type) {\n // Convert anyOf to type array format\n // Normalize sibling fields (like properties/items) before returning\n const { anyOf, ...rest } = result;\n const fixedRest = fixAnyOfNullable(rest as JSONSchema7);\n const fixedOther = fixAnyOfNullable(otherSchema as JSONSchema7);\n return {\n ...fixedRest,\n ...fixedOther,\n type: (Array.isArray(fixedOther.type)\n ? [...fixedOther.type, 'null']\n : [fixedOther.type, 'null']) as JSONSchema7['type'],\n };\n }\n }\n\n // Fix empty property schemas {} - OpenAI requires a type key\n if (result.properties && typeof result.properties === 'object' && !Array.isArray(result.properties)) {\n result.properties = Object.fromEntries(\n Object.entries(result.properties).map(([key, value]) => {\n const propSchema = value as JSONSchema7;\n\n // If property is an empty object {}, convert to allow primitive types\n // Note: We exclude 'object' (requires additionalProperties) and 'array' (requires items) for OpenAI\n if (\n typeof propSchema === 'object' &&\n propSchema !== null &&\n !Array.isArray(propSchema) &&\n Object.keys(propSchema).length === 0\n ) {\n return [key, { type: ['string', 'number', 'boolean', 'null'] as JSONSchema7['type'] }];\n }\n\n // Recursively fix nested schemas\n return [key, fixAnyOfNullable(propSchema)];\n }),\n );\n }\n\n // Recursively fix items in arrays\n if (result.items) {\n if (Array.isArray(result.items)) {\n result.items = result.items.map(item => fixAnyOfNullable(item as JSONSchema7));\n } else {\n result.items = fixAnyOfNullable(result.items as JSONSchema7);\n }\n }\n\n // Recursively fix anyOf/oneOf/allOf schemas\n if (result.anyOf && Array.isArray(result.anyOf)) {\n result.anyOf = result.anyOf.map(s => fixAnyOfNullable(s as JSONSchema7));\n }\n if (result.oneOf && Array.isArray(result.oneOf)) {\n result.oneOf = result.oneOf.map(s => fixAnyOfNullable(s as JSONSchema7));\n }\n if (result.allOf && Array.isArray(result.allOf)) {\n result.allOf = result.allOf.map(s => fixAnyOfNullable(s as JSONSchema7));\n }\n\n return result;\n}\n\nexport function zodToJsonSchema(\n zodSchema: ZodSchemaV3 | ZodSchemaV4,\n target: Targets = 'jsonSchema7',\n strategy: 'none' | 'seen' | 'root' | 'relative' = 'relative',\n): JSONSchema7 {\n const fn = 'toJSONSchema';\n\n if (fn in z) {\n // Zod v4 path - patch record schemas before converting\n patchRecordSchemas(zodSchema);\n\n const jsonSchema = (z as any)[fn](zodSchema, {\n unrepresentable: 'any',\n override: (ctx: any) => {\n // Handle both Zod v4 structures: _def directly or nested in _zod\n const def = ctx.zodSchema?._def || ctx.zodSchema?._zod?.def;\n // Check for date type using both possible property names\n if (def && (def.typeName === 'ZodDate' || def.type === 'date')) {\n ctx.jsonSchema.type = 'string';\n ctx.jsonSchema.format = 'date-time';\n }\n },\n }) satisfies JSONSchema7;\n\n // Fix anyOf patterns for nullable fields - required for OpenAI compatibility\n return fixAnyOfNullable(jsonSchema);\n } else {\n // Zod v3 path - use the original converter\n return zodToJsonSchemaOriginal(zodSchema as ZodSchemaV3, {\n $refStrategy: strategy,\n target,\n }) as JSONSchema7;\n }\n}\n"]}
|
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkZXNJQOPF_cjs = require('./chunk-ZXNJQOPF.cjs');
|
|
4
4
|
var zod = require('zod');
|
|
5
5
|
var zodFromJsonSchema = require('zod-from-json-schema');
|
|
6
6
|
var zodFromJsonSchemaV3 = require('zod-from-json-schema-v3');
|
|
@@ -3568,7 +3568,7 @@ function trimStartOfStream() {
|
|
|
3568
3568
|
|
|
3569
3569
|
// src/utils.ts
|
|
3570
3570
|
function convertZodSchemaToAISDKSchema(zodSchema2, target = "jsonSchema7") {
|
|
3571
|
-
const jsonSchemaToUse =
|
|
3571
|
+
const jsonSchemaToUse = chunkZXNJQOPF_cjs.zodToJsonSchema(zodSchema2, target);
|
|
3572
3572
|
return jsonSchema(jsonSchemaToUse, {
|
|
3573
3573
|
validate: (value) => {
|
|
3574
3574
|
const result = zodSchema2.safeParse(value);
|
|
@@ -3615,7 +3615,7 @@ function applyCompatLayer({
|
|
|
3615
3615
|
}
|
|
3616
3616
|
}
|
|
3617
3617
|
if (mode === "jsonSchema") {
|
|
3618
|
-
return
|
|
3618
|
+
return chunkZXNJQOPF_cjs.zodToJsonSchema(zodSchema2, "jsonSchema7");
|
|
3619
3619
|
} else {
|
|
3620
3620
|
return convertZodSchemaToAISDKSchema(zodSchema2);
|
|
3621
3621
|
}
|
|
@@ -4907,6 +4907,50 @@ var OpenAISchemaCompatLayer = class extends SchemaCompatLayer3 {
|
|
|
4907
4907
|
"ZodTuple"
|
|
4908
4908
|
]);
|
|
4909
4909
|
}
|
|
4910
|
+
/**
|
|
4911
|
+
* Override to fix additionalProperties: {} which OpenAI doesn't support.
|
|
4912
|
+
* Converts empty object {} to true to preserve passthrough intent.
|
|
4913
|
+
*/
|
|
4914
|
+
processToJSONSchema(zodSchema2) {
|
|
4915
|
+
const jsonSchema2 = super.processToJSONSchema(zodSchema2);
|
|
4916
|
+
return this.fixAdditionalProperties(jsonSchema2);
|
|
4917
|
+
}
|
|
4918
|
+
/**
|
|
4919
|
+
* Recursively fixes additionalProperties: {} to additionalProperties: true.
|
|
4920
|
+
* OpenAI requires additionalProperties to be either:
|
|
4921
|
+
* - false (no additional properties allowed)
|
|
4922
|
+
* - true (any additional properties allowed)
|
|
4923
|
+
* - an object with a "type" key (typed additional properties)
|
|
4924
|
+
* An empty object {} is NOT valid.
|
|
4925
|
+
*/
|
|
4926
|
+
fixAdditionalProperties(schema) {
|
|
4927
|
+
if (typeof schema !== "object" || schema === null) {
|
|
4928
|
+
return schema;
|
|
4929
|
+
}
|
|
4930
|
+
const result = { ...schema };
|
|
4931
|
+
if (result.additionalProperties !== void 0 && typeof result.additionalProperties === "object" && result.additionalProperties !== null && !Array.isArray(result.additionalProperties) && Object.keys(result.additionalProperties).length === 0) {
|
|
4932
|
+
result.additionalProperties = true;
|
|
4933
|
+
}
|
|
4934
|
+
if (result.properties) {
|
|
4935
|
+
result.properties = Object.fromEntries(
|
|
4936
|
+
Object.entries(result.properties).map(([key, value]) => [
|
|
4937
|
+
key,
|
|
4938
|
+
this.fixAdditionalProperties(value)
|
|
4939
|
+
])
|
|
4940
|
+
);
|
|
4941
|
+
}
|
|
4942
|
+
if (result.items) {
|
|
4943
|
+
if (Array.isArray(result.items)) {
|
|
4944
|
+
result.items = result.items.map((item) => this.fixAdditionalProperties(item));
|
|
4945
|
+
} else {
|
|
4946
|
+
result.items = this.fixAdditionalProperties(result.items);
|
|
4947
|
+
}
|
|
4948
|
+
}
|
|
4949
|
+
if (result.additionalProperties && typeof result.additionalProperties === "object" && !Array.isArray(result.additionalProperties) && Object.keys(result.additionalProperties).length > 0) {
|
|
4950
|
+
result.additionalProperties = this.fixAdditionalProperties(result.additionalProperties);
|
|
4951
|
+
}
|
|
4952
|
+
return result;
|
|
4953
|
+
}
|
|
4910
4954
|
};
|
|
4911
4955
|
var OpenAIReasoningSchemaCompatLayer = class extends SchemaCompatLayer3 {
|
|
4912
4956
|
constructor(model) {
|