From 2ace9e44aafca38f485cdc9d028bff6ffd68371f Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 05:43:38 +0000 Subject: [PATCH 1/2] feat: add warning for .optional() usage in OpenAI API schemas This commit adds a warning when .optional() is used in schemas for OpenAI API Structured Outputs, recommending the use of .nullable() instead. - Added warning in optional.ts that triggers when openaiStrictMode is true - Added test to verify warning behavior Fixes openai/openai-node#1180 --- .../zod-to-json-schema/parsers/optional.ts | 9 +++++++++ tests/helpers/zod.test.ts | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/_vendor/zod-to-json-schema/parsers/optional.ts b/src/_vendor/zod-to-json-schema/parsers/optional.ts index 9b3e9731f..9c9fb4d89 100644 --- a/src/_vendor/zod-to-json-schema/parsers/optional.ts +++ b/src/_vendor/zod-to-json-schema/parsers/optional.ts @@ -3,6 +3,15 @@ import { JsonSchema7Type, parseDef } from '../parseDef'; import { Refs } from '../Refs'; export const parseOptionalDef = (def: ZodOptionalDef, refs: Refs): JsonSchema7Type | undefined => { + if (refs.openaiStrictMode) { + const fieldName = refs.propertyPath?.slice(-1)[0] || 'unknown'; + console.warn( + `Warning: Field "${fieldName}" uses .optional() which is not supported by OpenAI API Structured Outputs. ` + + `Please use .nullable() instead. ` + + `See: https://platform.openai.com/docs/guides/structured-outputs#all-fields-must-be-required` + ); + } + if (refs.currentPath.toString() === refs.propertyPath?.toString()) { return parseDef(def.innerType._def, refs); } diff --git a/tests/helpers/zod.test.ts b/tests/helpers/zod.test.ts index 493b4c0c8..e6c366e96 100644 --- a/tests/helpers/zod.test.ts +++ b/tests/helpers/zod.test.ts @@ -88,6 +88,24 @@ describe('zodResponseFormat', () => { `); }); + it('warns when using optional fields with OpenAI API', () => { + const consoleSpy = jest.spyOn(console, 'warn'); + + zodResponseFormat( + z.object({ + required: z.string(), + optional: z.string().optional(), + }), + 'test', + ); + + expect(consoleSpy).toHaveBeenCalledWith( + expect.stringContaining('uses .optional() which is not supported by OpenAI API Structured Outputs') + ); + + consoleSpy.mockRestore(); + }); + it('automatically adds properties with defaults to `required`', () => { expect( zodResponseFormat( From 5fac779a0212efb7a0a5fe5e7ff9df813914bc85 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 07:36:26 +0000 Subject: [PATCH 2/2] formatting --- src/_vendor/zod-to-json-schema/parsers/optional.ts | 4 ++-- tests/helpers/zod.test.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/_vendor/zod-to-json-schema/parsers/optional.ts b/src/_vendor/zod-to-json-schema/parsers/optional.ts index 9c9fb4d89..aee9606e4 100644 --- a/src/_vendor/zod-to-json-schema/parsers/optional.ts +++ b/src/_vendor/zod-to-json-schema/parsers/optional.ts @@ -7,8 +7,8 @@ export const parseOptionalDef = (def: ZodOptionalDef, refs: Refs): JsonSchema7Ty const fieldName = refs.propertyPath?.slice(-1)[0] || 'unknown'; console.warn( `Warning: Field "${fieldName}" uses .optional() which is not supported by OpenAI API Structured Outputs. ` + - `Please use .nullable() instead. ` + - `See: https://platform.openai.com/docs/guides/structured-outputs#all-fields-must-be-required` + `Please use .nullable() instead. ` + + `See: https://platform.openai.com/docs/guides/structured-outputs#all-fields-must-be-required`, ); } diff --git a/tests/helpers/zod.test.ts b/tests/helpers/zod.test.ts index e6c366e96..e35a951ca 100644 --- a/tests/helpers/zod.test.ts +++ b/tests/helpers/zod.test.ts @@ -100,7 +100,7 @@ describe('zodResponseFormat', () => { ); expect(consoleSpy).toHaveBeenCalledWith( - expect.stringContaining('uses .optional() which is not supported by OpenAI API Structured Outputs') + expect.stringContaining('uses .optional() which is not supported by OpenAI API Structured Outputs'), ); consoleSpy.mockRestore();