Repository navigation
fix(schema): preserve const/enum in transformJSONSchema - #1143
edenbuilds wants to merge 2 commits into
Conversation
Dumping leftover const/enum into description strips discriminants from Zod discriminated unions / literal branches, so the model often emits nested union values as JSON strings and tool.parse() fails (anthropics#1116). Keep const and enum on the strict schema before the leftover-keys dump.
|
This fix is right, but I think it lands on a different path than the issue it closes, and that's worth settling before the regression test gets pinned to the wrong helper.
// betaZodTool(...).input_schema -> discriminant intact
"kind": { "type": "string", "const": "set_title" }
// betaZodOutputFormat(...).schema -> discriminant demoted
"kind": { "type": "string", "description": "{const: \"set_title\"}" }So #1116's stated mechanism (" Second, if (Object.keys(jsonSchema).length > 0) {
strictSchema['description'] = ... + '{' + entries.map(...) + '}';
}Every unrecognised key lands in "title": { "type": "string", "description": "{minLength: 3, maxLength: 80}" }
"tags": { "type": "array", "items": {...}, "minItems": 1, "description": "{maxItems: 5}" }Patching Third, two cases in here are worse than demotion, and neither is touched by a Root {"$ref":"#/definitions/Ticket"}Dangling pointer, whole schema gone, nothing thrown. (A non-root Tuples fail two different ways. Array-form Lastly, #1117 was the same fix and was closed unmerged on 2026-07-31 with no comments. Might be worth finding out why before this one waits on a review — if there was a design objection, it probably applies here too. (Context on how I got this: I maintain a small tool that normalises schemas per provider, and I derive its rules by running them through each vendor's own client rather than off the docs — the numbers above are all from |
betaZodTool does not call transformJSONSchema; cover betaZodOutputFormat and clarify comments so the regression matches the real call path.
|
@percymcn thanks — this was exactly the review this PR needed. You’re right that Updated in
On the broader allowlist / root Probe script link is useful — thanks for sharing. |
Summary
constandenumon the strict schema intransformJSONSchemainstead of dumping them intodescription.betaZodOutputFormat,jsonSchemaOutputFormat, and the non-beta equivalents). Discriminants stay machine-readable.betaZodTooldoes not calltransformJSONSchematoday —transformJSONSchemadropsconst/enuminto description text, breaking discriminated unions in tool inputs #1116’s tools-path writeup needs a separate re-check. Related discussion ontransformJSONSchemadropsconst/enuminto description text, breaking discriminated unions in tool inputs #1116; this PR does not claim to close that issue’s tools symptom.Related to #1116
Test plan
yarn jest tests/helpers/transform-json-schema.test.ts tests/helpers/beta/zod.test.tsbetaZodOutputFormat(z.discriminatedUnion(...))keepsconston each branch