Files
oh-my-pi/packages/coding-agent/test/tools/jtd-to-json-schema.test.ts
T
roboomp ef68db17f5 fix(coding-agent/tools): stopped re-walking JTD-converted JSON Schema for nested JTD detection
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
2026-05-25 17:21:53 +00:00

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,
});
});
});