refactor(coding-agent/tools): removed output schema evaluator and simplified validator handling

- Deleted the `ValidationVerdict` type and `evaluateOutputAgainstSchema` API from the output schema validator.
- Updated `yield.ts` to bind `buildOutputValidator`'s error directly to `schemaError` during validator setup.
- Removed the obsolete evaluator tests and adjusted validation success fixture to match the raw summary input shape.
This commit is contained in:
can1357
2026-05-26 07:28:42 +02:00
parent e0eae43fde
commit 3b60edd276
3 changed files with 7 additions and 43 deletions
@@ -15,9 +15,6 @@ import {
} from "@oh-my-pi/pi-ai/utils/schema";
import { jtdToJsonSchema, normalizeSchema } from "./jtd-to-json-schema";
/** Verdict for a successful or failed validation, summarized for callers. */
export type ValidationVerdict = { ok: true } | { ok: false; message: string; missingRequired: string[] };
/** A validator bound to a specific output schema. */
export interface OutputValidator {
/** Run JSON Schema validation; returns the raw `success`/`issues` shape so callers may inspect every failure. */
@@ -45,9 +42,11 @@ export interface BuildOutputValidatorResult {
* Build the canonical validator for a JTD-or-JSON-Schema output declaration.
*
* Returns:
* - `{ validator, jsonSchema }` for constraining schemas — both callers use this path.
* - `{}` for absent or fully-permissive schemas (e.g. `true`, `undefined`) — no validation.
* - `{ error }` when the schema cannot be honored (invalid syntax, `false`, malformed JTD).
* - `{ validator, jsonSchema, normalized }` for constraining schemas — both callers use this path.
* - `{ normalized: true }` for an intentionally unconstrained schema (the JSON Schema literal `true`).
* No validator, but distinguishable from "no schema provided".
* - `{}` for an absent schema (`undefined`).
* - `{ error, normalized? }` when the schema cannot be honored (invalid syntax, `false`, malformed JTD).
*/
export function buildOutputValidator(schema: unknown): BuildOutputValidatorResult {
const { normalized, error: normalizeError } = normalizeSchema(schema);
@@ -89,16 +88,6 @@ export function summarizeValidationFailure(
return { message, missingRequired: missing };
}
/** Reduce a `BuildOutputValidatorResult` + value to the executor's high-level verdict. */
export function evaluateOutputAgainstSchema(schema: unknown, value: unknown): ValidationVerdict | { ok: true } {
const { validator } = buildOutputValidator(schema);
if (!validator) return { ok: true };
const result = validator.validate(value);
if (result.success) return { ok: true };
const { message, missingRequired } = summarizeValidationFailure(result, value, validator.requiredFields);
return { ok: false, message, missingRequired };
}
export function extractRequiredFields(jsonSchema: unknown): string[] {
if (!jsonSchema || typeof jsonSchema !== "object") return [];
const required = (jsonSchema as { required?: unknown }).required;
+1 -2
View File
@@ -121,9 +121,8 @@ export class YieldTool implements AgentTool<TSchema, YieldDetails> {
validator,
jsonSchema: normalizedSchema,
normalized,
error: validatorError,
error: schemaError,
} = buildOutputValidator(session.outputSchema);
const schemaError = validatorError;
if (validator) {
validate = value => validator.validate(value);
}
@@ -2,7 +2,6 @@ import { describe, expect, it } from "bun:test";
import {
buildOutputValidator,
computeMissingRequired,
evaluateOutputAgainstSchema,
extractRequiredFields,
formatAllValidationIssues,
formatValidationIssueHeadline,
@@ -71,32 +70,9 @@ describe("buildOutputValidator", () => {
]);
});
});
describe("evaluateOutputAgainstSchema", () => {
it("returns ok for unconstrained schemas", () => {
expect(evaluateOutputAgainstSchema(undefined, { anything: 1 })).toEqual({ ok: true });
expect(evaluateOutputAgainstSchema(true, { anything: 1 })).toEqual({ ok: true });
});
it("returns ok for conforming payloads", () => {
const schema = { properties: { x: { type: "string" } } };
expect(evaluateOutputAgainstSchema(schema, { x: "hi" })).toEqual({ ok: true });
});
it("returns the executor headline + missingRequired for failures", () => {
const schema = { properties: { x: { type: "string" }, y: { type: "number" } } };
const verdict = evaluateOutputAgainstSchema(schema, { x: "ok" });
expect(verdict).toMatchObject({ ok: false });
if (verdict.ok === false) {
expect(verdict.missingRequired).toContain("y");
expect(verdict.message).toMatch(/y/);
}
});
});
describe("summarizeValidationFailure", () => {
it("returns an empty summary when the result is a success", () => {
const summary = summarizeValidationFailure({ success: true }, {}, []);
const summary = summarizeValidationFailure({ success: true, issues: [] }, {}, []);
expect(summary).toEqual({ message: "", missingRequired: [] });
});