The JTD-to-JSON-Schema converter post-processed convertSchema's
output with normalizeMixedSchemaNode, which walked back into the
emitted JSON Schema looking for nested JTD forms. Inside a
properties block, user-defined property names whose keys happened
to collide with JTD keywords ('ref', 'elements', 'values',
'optionalProperties', 'discriminator') were misclassified as JTD
forms and re-rewritten - corrupting properties like { ref: { type:
'string' } } into { $ref: '#/$defs/[object Object]' } and breaking
the built-in explore agent's output validator with
schema_violation: files.0.ref: must not be present.
convertSchema is already fully recursive and emits pure JSON Schema,
so the post-walk is both unnecessary and unsafe. Drop it.
Fixes #1345
109 lines
2.2 KiB
TypeScript
109 lines
2.2 KiB
TypeScript
import { describe, expect, it } from "bun:test";
|
|
import { jtdToJsonSchema } from "@oh-my-pi/pi-coding-agent/tools/jtd-to-json-schema";
|
|
|
|
describe("jtdToJsonSchema", () => {
|
|
it("converts JTD elements and int32 primitives into JSON Schema", () => {
|
|
const converted = jtdToJsonSchema({
|
|
properties: {
|
|
results: {
|
|
elements: {
|
|
properties: {
|
|
issue: { type: "int32" },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
expect(converted).toEqual({
|
|
type: "object",
|
|
properties: {
|
|
results: {
|
|
type: "array",
|
|
items: {
|
|
type: "object",
|
|
properties: {
|
|
issue: { type: "integer" },
|
|
},
|
|
required: ["issue"],
|
|
additionalProperties: false,
|
|
},
|
|
},
|
|
},
|
|
required: ["results"],
|
|
additionalProperties: false,
|
|
});
|
|
});
|
|
|
|
it("normalizes nested JTD fragments inside JSON Schema nodes", () => {
|
|
const converted = jtdToJsonSchema({
|
|
type: "object",
|
|
properties: {
|
|
results: {
|
|
type: "array",
|
|
elements: {
|
|
properties: {
|
|
issue: { type: "int32" },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
required: ["results"],
|
|
});
|
|
|
|
expect(converted).toEqual({
|
|
type: "object",
|
|
properties: {
|
|
results: {
|
|
type: "array",
|
|
items: {
|
|
type: "object",
|
|
properties: {
|
|
issue: { type: "integer" },
|
|
},
|
|
required: ["issue"],
|
|
additionalProperties: false,
|
|
},
|
|
},
|
|
},
|
|
required: ["results"],
|
|
});
|
|
});
|
|
it("does not misinterpret user-named properties that collide with JTD keywords (#1345)", () => {
|
|
// Mirrors the `files[]` shape declared by the built-in explore agent:
|
|
// a JTD elements form whose item properties include one literally named `ref`.
|
|
const converted = jtdToJsonSchema({
|
|
properties: {
|
|
files: {
|
|
elements: {
|
|
properties: {
|
|
ref: { type: "string" },
|
|
description: { type: "string" },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
expect(converted).toEqual({
|
|
type: "object",
|
|
properties: {
|
|
files: {
|
|
type: "array",
|
|
items: {
|
|
type: "object",
|
|
properties: {
|
|
ref: { type: "string" },
|
|
description: { type: "string" },
|
|
},
|
|
required: ["ref", "description"],
|
|
additionalProperties: false,
|
|
},
|
|
},
|
|
},
|
|
required: ["files"],
|
|
additionalProperties: false,
|
|
});
|
|
});
|
|
});
|