diff --git a/src/_vendor/zod-to-json-schema/parseDef.ts b/src/_vendor/zod-to-json-schema/parseDef.ts index f4dd747ca..bbdbb3d42 100644 --- a/src/_vendor/zod-to-json-schema/parseDef.ts +++ b/src/_vendor/zod-to-json-schema/parseDef.ts @@ -230,7 +230,7 @@ const selectParser = ( case ZodFirstPartyTypeKind.ZodDefault: return parseDefaultDef(def, refs); case ZodFirstPartyTypeKind.ZodBranded: - return parseBrandedDef(def, refs); + return parseBrandedDef(def, refs, forceResolution); case ZodFirstPartyTypeKind.ZodReadonly: return parseReadonlyDef(def, refs); case ZodFirstPartyTypeKind.ZodCatch: diff --git a/src/_vendor/zod-to-json-schema/parsers/branded.ts b/src/_vendor/zod-to-json-schema/parsers/branded.ts index c585f2d93..ad1f9028c 100644 --- a/src/_vendor/zod-to-json-schema/parsers/branded.ts +++ b/src/_vendor/zod-to-json-schema/parsers/branded.ts @@ -2,6 +2,6 @@ import { ZodBrandedDef } from 'zod/v3'; import { parseDef } from '../parseDef'; import { Refs } from '../Refs'; -export function parseBrandedDef(_def: ZodBrandedDef, refs: Refs) { - return parseDef(_def.type._def, refs); +export function parseBrandedDef(_def: ZodBrandedDef, refs: Refs, forceResolution = false) { + return parseDef(_def.type._def, refs, forceResolution); } diff --git a/tests/helpers/zod.test.ts b/tests/helpers/zod.test.ts index 1bc766376..baa92db4d 100644 --- a/tests/helpers/zod.test.ts +++ b/tests/helpers/zod.test.ts @@ -1,4 +1,4 @@ -import { zodResponseFormat } from 'openai/helpers/zod'; +import { zodResponseFormat, zodTextFormat } from 'openai/helpers/zod'; import { z as zv3 } from 'zod/v3'; import { z as zv4 } from 'zod/v4'; @@ -359,4 +359,30 @@ describe.each([ expect(consoleSpy).toHaveBeenCalledTimes(0); }); + + it('does not emit circular refs for branded zodTextFormat array items', () => { + if (version !== 'v3') { + return; + } + + const BlockIdSchema = z.string().brand<'SlideId'>(); + const SlidePlanSchema = z.object({ + slides: z.array( + z.object({ + subtitle: z.array(BlockIdSchema).nullable(), + content: z.array(BlockIdSchema).min(1), + }), + ), + }); + + const jsonSchema = zodTextFormat(SlidePlanSchema, 'slidePlan').schema as { + definitions?: Record; + }; + + expect( + jsonSchema.definitions?.['slidePlan_properties_slides_items_properties_subtitle_anyOf_0_items'], + ).toEqual({ + type: 'string', + }); + }); });