@mastra/schema-compat 1.0.0-beta.0 → 1.0.0-beta.2

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 CHANGED
@@ -1,5 +1,47 @@
1
1
  # @mastra/schema-compat
2
2
 
3
+ ## 1.0.0-beta.2
4
+
5
+ ### Patch Changes
6
+
7
+ - Fix discriminatedUnion schema information lost when json schema is converted to zod ([#10500](https://github.com/mastra-ai/mastra/pull/10500))
8
+
9
+ ## 1.0.0-beta.1
10
+
11
+ ### Patch Changes
12
+
13
+ - Fixed OpenAI schema compatibility when using `agent.generate()` or `agent.stream()` with `structuredOutput`. ([#10366](https://github.com/mastra-ai/mastra/pull/10366))
14
+
15
+ ## Changes
16
+ - **Automatic transformation**: Zod schemas are now automatically transformed for OpenAI strict mode compatibility when using OpenAI models (including reasoning models like o1, o3, o4)
17
+ - **Optional field handling**: `.optional()` fields are converted to `.nullable()` with a transform that converts `null` → `undefined`, preserving optional semantics while satisfying OpenAI's strict mode requirements
18
+ - **Preserves nullable fields**: Intentionally `.nullable()` fields remain unchanged
19
+ - **Deep transformation**: Handles `.optional()` fields at any nesting level (objects, arrays, unions, etc.)
20
+ - **JSON Schema objects**: Not transformed, only Zod schemas
21
+
22
+ ## Example
23
+
24
+ ```typescript
25
+ const agent = new Agent({
26
+ name: 'data-extractor',
27
+ model: { provider: 'openai', modelId: 'gpt-4o' },
28
+ instructions: 'Extract user information',
29
+ });
30
+
31
+ const schema = z.object({
32
+ name: z.string(),
33
+ age: z.number().optional(),
34
+ deletedAt: z.date().nullable(),
35
+ });
36
+
37
+ // Schema is automatically transformed for OpenAI compatibility
38
+ const result = await agent.generate('Extract: John, deleted yesterday', {
39
+ structuredOutput: { schema },
40
+ });
41
+
42
+ // Result: { name: 'John', age: undefined, deletedAt: null }
43
+ ```
44
+
3
45
  ## 1.0.0-beta.0
4
46
 
5
47
  ### Major Changes
package/dist/index.cjs CHANGED
@@ -3646,7 +3646,8 @@ var SUPPORTED_ZOD_TYPES = [
3646
3646
  "ZodNumber",
3647
3647
  "ZodDate",
3648
3648
  "ZodAny",
3649
- "ZodDefault"
3649
+ "ZodDefault",
3650
+ "ZodNullable"
3650
3651
  ];
3651
3652
  var ALL_ZOD_TYPES = [...SUPPORTED_ZOD_TYPES, ...UNSUPPORTED_ZOD_TYPES];
3652
3653
  var SchemaCompatLayer = class {
@@ -4063,7 +4064,8 @@ var SUPPORTED_ZOD_TYPES2 = [
4063
4064
  "ZodNumber",
4064
4065
  "ZodDate",
4065
4066
  "ZodAny",
4066
- "ZodDefault"
4067
+ "ZodDefault",
4068
+ "ZodNullable"
4067
4069
  ];
4068
4070
  var SchemaCompatLayer2 = class {
4069
4071
  model;
@@ -4106,6 +4108,12 @@ var SchemaCompatLayer2 = class {
4106
4108
  isNull(v) {
4107
4109
  return v instanceof v4.ZodNull;
4108
4110
  }
4111
+ /**
4112
+ * Type guard for nullable Zod types
4113
+ */
4114
+ isNullable(v) {
4115
+ return v instanceof v4.ZodNullable;
4116
+ }
4109
4117
  /**
4110
4118
  * Type guard for array Zod types
4111
4119
  */
@@ -4699,6 +4707,9 @@ function isDate(z11) {
4699
4707
  function isDefault(z11) {
4700
4708
  return (v) => v instanceof z11["ZodDefault"];
4701
4709
  }
4710
+ function isNullable(z11) {
4711
+ return (v) => v instanceof z11["ZodNullable"];
4712
+ }
4702
4713
 
4703
4714
  // src/provider-compats/anthropic.ts
4704
4715
  var AnthropicSchemaCompatLayer = class extends SchemaCompatLayer3 {
@@ -4839,15 +4850,30 @@ var OpenAISchemaCompatLayer = class extends SchemaCompatLayer3 {
4839
4850
  }
4840
4851
  processZodType(value) {
4841
4852
  if (isOptional2(zod.z)(value)) {
4842
- return this.defaultZodOptionalHandler(value, [
4843
- "ZodObject",
4844
- "ZodArray",
4845
- "ZodUnion",
4846
- "ZodString",
4847
- "ZodNever",
4848
- "ZodUndefined",
4849
- "ZodTuple"
4850
- ]);
4853
+ const innerType = "_def" in value ? value._def.innerType : value._zod?.def?.innerType;
4854
+ if (innerType) {
4855
+ if (isNullable(zod.z)(innerType)) {
4856
+ const processed = this.processZodType(innerType);
4857
+ return processed.transform((val) => val === null ? void 0 : val);
4858
+ }
4859
+ const processedInner = this.processZodType(innerType);
4860
+ return processedInner.nullable().transform((val) => val === null ? void 0 : val);
4861
+ }
4862
+ return value;
4863
+ } else if (isNullable(zod.z)(value)) {
4864
+ const innerType = "_def" in value ? value._def.innerType : value._zod?.def?.innerType;
4865
+ if (innerType) {
4866
+ if (isOptional2(zod.z)(innerType)) {
4867
+ const innerInnerType = "_def" in innerType ? innerType._def.innerType : innerType._zod?.def?.innerType;
4868
+ if (innerInnerType) {
4869
+ const processedInnerInner = this.processZodType(innerInnerType);
4870
+ return processedInnerInner.nullable().transform((val) => val === null ? void 0 : val);
4871
+ }
4872
+ }
4873
+ const processedInner = this.processZodType(innerType);
4874
+ return processedInner.nullable();
4875
+ }
4876
+ return value;
4851
4877
  } else if (isObj2(zod.z)(value)) {
4852
4878
  return this.defaultZodObjectHandler(value);
4853
4879
  } else if (isUnion2(zod.z)(value)) {
@@ -4880,15 +4906,37 @@ var OpenAIReasoningSchemaCompatLayer = class extends SchemaCompatLayer3 {
4880
4906
  return this.getModel().modelId.includes(`o3`) || this.getModel().modelId.includes(`o4`) || this.getModel().modelId.includes(`o1`);
4881
4907
  }
4882
4908
  shouldApply() {
4883
- if ((this.getModel().supportsStructuredOutputs || this.isReasoningModel()) && (this.getModel().provider.includes(`openai`) || this.getModel().modelId.includes(`openai`))) {
4909
+ if (this.isReasoningModel() && (this.getModel().provider.includes(`openai`) || this.getModel().modelId.includes(`openai`))) {
4884
4910
  return true;
4885
4911
  }
4886
4912
  return false;
4887
4913
  }
4888
4914
  processZodType(value) {
4889
4915
  if (isOptional2(zod.z)(value)) {
4890
- const innerZodType = this.processZodType(value._def.innerType);
4891
- return innerZodType.nullable();
4916
+ const innerType = "_def" in value ? value._def.innerType : value._zod?.def?.innerType;
4917
+ if (innerType) {
4918
+ if (isNullable(zod.z)(innerType)) {
4919
+ const processed = this.processZodType(innerType);
4920
+ return processed.transform((val) => val === null ? void 0 : val);
4921
+ }
4922
+ const processedInner = this.processZodType(innerType);
4923
+ return processedInner.nullable().transform((val) => val === null ? void 0 : val);
4924
+ }
4925
+ return value;
4926
+ } else if (isNullable(zod.z)(value)) {
4927
+ const innerType = "_def" in value ? value._def.innerType : value._zod?.def?.innerType;
4928
+ if (innerType && isOptional2(zod.z)(innerType)) {
4929
+ const innerInnerType = "_def" in innerType ? innerType._def.innerType : innerType._zod?.def?.innerType;
4930
+ if (innerInnerType) {
4931
+ const processedInnerInner = this.processZodType(innerInnerType);
4932
+ return processedInnerInner.nullable().transform((val) => val === null ? void 0 : val);
4933
+ }
4934
+ }
4935
+ if (innerType) {
4936
+ const processedInner = this.processZodType(innerType);
4937
+ return processedInner.nullable();
4938
+ }
4939
+ return value;
4892
4940
  } else if (isObj2(zod.z)(value)) {
4893
4941
  return this.defaultZodObjectHandler(value, { passthrough: false });
4894
4942
  } else if (isArr2(zod.z)(value)) {