Files
reverse-engineering-anything/src/contracts/compactInputSchema.test.ts
T

563 lines
18 KiB
TypeScript

import { Ajv } from "ajv";
import { Ajv2020 } from "ajv/dist/2020.js";
import { describe, expect, it } from "vitest";
import { compactAdvertisedInputSchema } from "./compactInputSchema.js";
const serializedBytes = (value: unknown): number =>
Buffer.byteLength(JSON.stringify(value), "utf8");
const repeatedObservation = {
type: "object",
properties: {
captured_url: { type: "string", minLength: 1 },
captured_at: { type: "string", minLength: 1 },
status_code: { type: "integer", minimum: 100, maximum: 599 },
headers: {
type: "object",
additionalProperties: { type: "string" },
minProperties: 1,
},
body_digest: { type: "string", minLength: 64, maxLength: 64 },
},
required: ["captured_url", "captured_at", "status_code"],
additionalProperties: false,
} as const;
const annotatedSchema = {
type: "object",
description: "Root group guidance stays.",
properties: {
query: {
type: "string",
description: "Field guidance leaves.",
examples: ["seed"],
default: "seed",
title: "Query",
minLength: 1,
},
limits: {
type: "object",
description: "Nested guidance leaves.",
properties: {
max_results: {
type: "integer",
description: "Leaves.",
minimum: 1,
maximum: 500,
default: 50,
},
},
required: ["max_results"],
additionalProperties: false,
},
},
required: ["query"],
dependentRequired: { limits: ["query"] },
additionalProperties: false,
} as const;
const oversizedPairSchema = (): Record<string, unknown> => {
const deepStructure = {
type: "object",
description: "Nested guidance that leaves.",
properties: Object.fromEntries(
Array.from({ length: 40 }, (_, index) => [
`field_${index}`,
{ type: "string", minLength: 1, description: `Field ${index}` },
]),
),
required: Array.from({ length: 40 }, (_, index) => `field_${index}`),
additionalProperties: false,
};
return {
type: "object",
description: "Provide a complete capture pair.",
properties: {
before: structuredClone(deepStructure),
after: structuredClone(deepStructure),
},
required: ["before", "after"],
additionalProperties: false,
};
};
describe("compact advertised input schema", () => {
it("drops nested annotation prose while keeping validation keywords", () => {
const { schema, presentation } = compactAdvertisedInputSchema(
structuredClone(annotatedSchema),
13 * 1024,
);
expect(presentation).toBe("inline");
expect(schema.description).toBe("Root group guidance stays.");
const query = (schema.properties as Record<string, unknown>)
.query as Record<string, unknown>;
expect(query).toEqual({ type: "string", minLength: 1 });
const limits = (schema.properties as Record<string, unknown>)
.limits as Record<string, unknown>;
expect(limits.description).toBeUndefined();
expect(limits.required).toEqual(["max_results"]);
expect(schema.dependentRequired).toEqual({ limits: ["query"] });
expect(schema.required).toEqual(["query"]);
});
it("keeps annotation-shaped keys inside literal const and enum data", () => {
const literalMode = {
description: "saved data",
default: { keep: "me" },
};
const { schema } = compactAdvertisedInputSchema(
{
type: "object",
properties: {
mode: { enum: [literalMode] },
pinned: { const: { description: "literal" } },
},
},
13 * 1024,
);
const properties = schema.properties as Record<string, unknown>;
expect((properties.mode as Record<string, unknown>).enum).toEqual([
literalMode,
]);
expect((properties.pinned as Record<string, unknown>).const).toEqual({
description: "literal",
});
});
it("inlines local references without changing validation or literal data", () => {
const original = {
type: "object",
$defs: { "observation/~": structuredClone(repeatedObservation) },
properties: {
before: { $ref: "#/$defs/observation~1~0" },
after: { $ref: "#/$defs/observation~1~0" },
literal: { const: { $ref: "saved data", $defs: { keep: true } } },
},
required: ["before", "after"],
additionalProperties: false,
};
const { schema, presentation } = compactAdvertisedInputSchema(
original,
13312,
);
expect(presentation).toBe("inline");
expect(schema.$defs).toBeUndefined();
const ajv = new Ajv2020({ strict: false });
const canonical = ajv.compile(original);
const compact = ajv.compile(schema);
const observation = {
captured_url: "https://example.com",
captured_at: "now",
status_code: 200,
};
for (const input of [
{ before: observation, after: observation },
{ before: observation, after: { ...observation, status_code: 99 } },
{
before: observation,
after: observation,
literal: original.properties.literal.const,
},
])
expect(compact(input)).toBe(canonical(input));
});
it("does not reintroduce unsupported dialect keywords in reduced schemas", () => {
let nested: Record<string, unknown> = { type: "string" };
for (let level = 0; level < 12; level += 1)
nested = { type: "object", properties: { child: nested } };
const { schema, presentation } = compactAdvertisedInputSchema(
{
$schema: "https://json-schema.org/draft/2020-12/schema",
type: "object",
properties: { deep: nested },
dependentRequired: { detail: ["target"] },
},
1_500,
);
expect(presentation).toBe("reduced");
expect(schema.$schema).toBe("https://json-schema.org/draft/2020-12/schema");
expect(schema).not.toHaveProperty("dependentRequired");
});
it("keeps unconstrained JSON values explicit for client type inference", () => {
const { schema } = compactAdvertisedInputSchema(
{
type: "object",
properties: { normalized_result: {}, literal: { const: {} } },
},
13312,
);
const properties = schema.properties as Record<string, unknown>;
expect(properties.normalized_result).toEqual({
type: ["null", "boolean", "object", "array", "number", "string"],
items: {},
});
expect(properties.literal).toEqual({ const: {} });
const validate = new Ajv2020({ strict: false }).compile(schema);
for (const normalized_result of [
null,
true,
{},
[],
42,
"result",
[[null, true, 42, "nested"], { values: [[], [false]] }],
])
expect(validate({ normalized_result })).toBe(true);
});
it("preserves independent validation constraints on reference siblings", () => {
const original = {
type: "object",
$defs: { text: { type: "string", minLength: 3 } },
properties: {
query: { $ref: "#/$defs/text", minLength: 1, maxLength: 5 },
},
};
const { schema } = compactAdvertisedInputSchema(original, 13312);
const validate = new Ajv2020({ strict: false }).compile(schema);
expect(validate({ query: "a" })).toBe(false);
expect(validate({ query: "abc" })).toBe(true);
expect(validate({ query: "abcdef" })).toBe(false);
});
});
describe("compact input schema budget and reduction", () => {
it("budgets repeated-reference expansion before materializing it", () => {
const definitions: Record<string, unknown> = {
leaf: structuredClone(repeatedObservation),
};
for (let index = 0; index < 30; index++) {
const $ref = `#/$defs/${index === 0 ? "leaf" : `level${index - 1}`}`;
definitions[`level${index}`] = {
type: "object",
properties: { left: { $ref }, right: { $ref } },
};
}
const { schema, presentation } = compactAdvertisedInputSchema(
{
type: "object",
$defs: definitions,
properties: { tree: { $ref: "#/$defs/level29" } },
},
1024,
);
expect(presentation).toBe("reduced");
expect(serializedBytes(schema)).toBeLessThanOrEqual(1024);
expect(schema.properties).toEqual({ tree: { type: "object" } });
});
it("retains referenced object, array and nullable types in reduced inputs", () => {
const original = {
type: "object",
$defs: {
pair: oversizedPairSchema(),
observations: {
type: "array",
items: structuredClone(repeatedObservation),
},
nullable: { anyOf: [{ type: "string" }, { type: "null" }] },
},
properties: {
capture: { $ref: "#/$defs/pair", description: "Complete capture." },
observations: { $ref: "#/$defs/observations" },
label: { $ref: "#/$defs/nullable" },
},
};
const { schema, presentation } = compactAdvertisedInputSchema(
original,
1024,
);
expect(presentation).toBe("reduced");
expect(schema.properties).toEqual({
capture: { type: "object", description: "Complete capture." },
observations: {
type: "array",
items: {
type: ["null", "boolean", "object", "array", "number", "string"],
items: {},
},
},
label: { type: ["string", "null"] },
});
const validate = new Ajv2020({ strict: false }).compile(schema);
expect(validate({ capture: {}, observations: [], label: null })).toBe(true);
expect(
validate({
capture: {},
observations: [[[null, true, 42, "nested"], { values: [[], [false]] }]],
label: null,
}),
).toBe(true);
expect(validate({ capture: {}, observations: [], label: "capture" })).toBe(
true,
);
expect(validate({ capture: "{}", observations: [], label: null })).toBe(
false,
);
});
it("reduces structurally oversized schemas to the shallow property presentation", () => {
const compacted = compactAdvertisedInputSchema(oversizedPairSchema(), 1024);
expect(compacted.presentation).toBe("reduced");
expect(serializedBytes(compacted.schema)).toBeLessThanOrEqual(1024);
expect(compacted.schema.type).toBe("object");
expect(compacted.schema.description).toContain(
"Provide a complete capture pair.",
);
expect(compacted.schema.description).toContain(
"compact input schema profile",
);
const properties = compacted.schema.properties as Record<string, unknown>;
expect(properties.before).toEqual({
type: "object",
description: "Nested guidance that leaves.",
});
expect(properties.after).toEqual(properties.before);
expect(compacted.schema.required).toEqual(["before", "after"]);
});
it("produces deterministic output for equal input", () => {
const schema = {
type: "object",
properties: {
before: structuredClone(repeatedObservation),
after: structuredClone(repeatedObservation),
},
};
expect(compactAdvertisedInputSchema(schema, 13 * 1024)).toEqual(
compactAdvertisedInputSchema(structuredClone(schema), 13 * 1024),
);
});
it("keeps inline presentations under the measured provider budget", () => {
const { schema, presentation } = compactAdvertisedInputSchema(
{
type: "object",
description: "Group guidance.",
properties: {
before: structuredClone(repeatedObservation),
after: structuredClone(repeatedObservation),
normalization: {
type: "object",
description: "Rules.",
properties: { rules: { type: "array", items: { type: "string" } } },
},
},
},
13312,
);
expect(presentation).toBe("inline");
expect(serializedBytes(schema)).toBeLessThanOrEqual(13312);
});
});
it.each([
["draft-2020-12", "https://example.test/nested"],
["draft-2020-12", "nested.json"],
["draft-07", "https://example.test/nested"],
["draft-07", "nested.json"],
] as const)(
"keeps embedded resource references scoped when inlining twice in %s with %s",
(dialect, id) => {
const source = {
$schema:
dialect === "draft-07"
? "http://json-schema.org/draft-07/schema#"
: "https://json-schema.org/draft/2020-12/schema",
$id: "https://example.test/root.json",
type: "object",
definitions: {
target: { type: "string" },
nested: {
$id: id,
type: "object",
definitions: { target: { type: "number" } },
properties: { value: { $ref: "#/definitions/target" } },
required: ["value"],
},
},
properties: {
before: { $ref: "#/definitions/nested" },
after: { $ref: "#/definitions/nested" },
},
required: ["before", "after"],
};
const compact = compactAdvertisedInputSchema(source, 13312);
expect(compact.presentation).toBe("inline");
expect(JSON.stringify(compact.schema)).not.toContain('"$ref":');
const createAjv = () =>
dialect === "draft-07"
? new Ajv({ strict: false })
: new Ajv2020({ strict: false });
const canonical = createAjv().compile(source);
const advertised = createAjv().compile(compact.schema);
for (const value of [7, "seven", null]) {
const input = { before: { value }, after: { value } };
expect(advertised(input)).toBe(canonical(input));
}
},
);
it("decodes URI fragments and JSON Pointer escapes through schema arrays", () => {
const source = {
type: "object",
definitions: { "a/b~": { prefixItems: [{ type: "number" }] } },
properties: { value: { $ref: "#/definitions/a%7E1b%7E0/prefixItems/0" } },
};
const result = compactAdvertisedInputSchema(source, 13312);
expect(result.presentation).toBe("inline");
const canonical = new Ajv2020({ strict: false }).compile(source);
const advertised = new Ajv2020({ strict: false }).compile(result.schema);
for (const value of [7, "seven", null])
expect(advertised({ value })).toBe(canonical({ value }));
});
it.each(["$dynamicRef", "$recursiveRef"])(
"does not strip resource identities from a partially expanded %s closure",
(keyword) => {
const result = compactAdvertisedInputSchema(
{
type: "object",
definitions: {
nested: {
$id: "https://example.test/nested",
type: "object",
properties: { next: { [keyword]: "#" } },
},
},
properties: { child: { $ref: "#/definitions/nested" } },
},
13312,
);
expect(result.presentation).toBe("reduced");
expect(JSON.stringify(result.schema)).not.toContain('"$ref":');
expect(result.schema.description).toContain("canonical");
},
);
it.each(["", "#legacy", "https://example.test/root.json"])(
"does not invent a pointer resource for an aliased or ambiguous nested ID %j",
(id) => {
const result = compactAdvertisedInputSchema(
{
$id: "https://example.test/root.json",
type: "object",
definitions: {
target: { type: "string" },
nested: {
$id: id,
type: "object",
definitions: { target: { type: "number" } },
properties: { value: { $ref: "#/definitions/target" } },
},
},
properties: { child: { $ref: "#/definitions/nested" } },
},
13312,
);
expect(result.presentation).toBe("reduced");
expect(result.schema.properties).toEqual({ child: {} });
},
);
it("uses explicit reduction for Draft 7 reference siblings with conflicting client semantics", () => {
const result = compactAdvertisedInputSchema(
{
$schema: "http://json-schema.org/draft-07/schema#",
type: "object",
definitions: { value: { type: "number" } },
properties: { value: { $ref: "#/definitions/value", maximum: 5 } },
},
13312,
);
expect(result.presentation).toBe("reduced");
expect(result.schema.properties).toEqual({ value: { type: "number" } });
});
it.each(["draft-2020-12", "draft-07"] as const)(
"removes embedded dialect declarations only after static expansion in %s",
(dialect) => {
const $schema =
dialect === "draft-07"
? "http://json-schema.org/draft-07/schema#"
: "https://json-schema.org/draft/2020-12/schema";
const shared = { $ref: "#/definitions/value" };
const source = {
$schema,
$id: "https://example.test/root",
type: "object",
properties: Object.fromEntries(
["string", "number"].map((type) => [
type,
{
$schema,
$id: `${type}.json#`,
type: "object",
definitions: { value: { type } },
properties: { value: shared },
required: ["value"],
},
]),
),
required: ["string", "number"],
};
const result = compactAdvertisedInputSchema(source, 13312);
expect(result.presentation).toBe("inline");
expect(result.schema.$schema).toBe($schema);
expect(JSON.stringify(result.schema).match(/"\$schema"/gu)).toHaveLength(1);
const createAjv = () =>
dialect === "draft-07"
? new Ajv({ strict: false })
: new Ajv2020({ strict: false });
const canonical = createAjv().compile(source);
const advertised = createAjv().compile(result.schema);
for (const value of [
{ string: { value: "a" }, number: { value: 7 } },
{ string: { value: 7 }, number: { value: "a" } },
])
expect(advertised(value)).toBe(canonical(value));
},
);
it.each(["child.json", "https://example.test/child.json"])(
"does not expand ambiguous sibling resources with ID %s",
($id) => {
const result = compactAdvertisedInputSchema(
{
type: "object",
properties: Object.fromEntries(
["string", "number"].map((type) => [
type,
{
$id,
type: "object",
definitions: { value: { type } },
properties: { value: { $ref: "#/definitions/value" } },
},
]),
),
},
13312,
);
expect(result.presentation).toBe("reduced");
expect(result.schema.properties).toEqual({ string: {}, number: {} });
},
);
it("includes restored root identity in the compact byte budget", () => {
const result = compactAdvertisedInputSchema(
{
$id: `https://example.test/${"a".repeat(1024)}`,
type: "object",
properties: { value: { type: "number" } },
},
512,
);
expect(result.presentation).toBe("reduced");
expect(serializedBytes(result.schema)).toBeLessThanOrEqual(512);
expect(result.schema.properties).toEqual({ value: { type: "number" } });
});