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:
@@ -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;
|
||||
|
||||
@@ -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: [] });
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user