Files
diegosouzapw--omniroute/tests/unit/translator-gemini-schema-pattern-property.test.ts
2026-07-13 13:39:12 +08:00

67 lines
2.7 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
// Regression for port-from-9router#1368: the Gemini/Antigravity schema sanitizer
// strips JSON-Schema *constraint* keywords (pattern, minLength, ...) that Gemini
// rejects. But it must NOT strip a tool property that is merely *named* like one of
// those keywords. glob/grep tools declare a property literally called `pattern`;
// deleting it (and then dropping it from `required`) made those tools unusable on
// `ag/*` (Antigravity) backends.
const { cleanJSONSchemaForAntigravity } = await import(
"../../open-sse/translator/helpers/geminiHelper.ts"
);
test("#1368: a property named 'pattern' survives Gemini schema sanitization", () => {
// Mirrors the grep tool's input schema (property name === constraint keyword).
const grepParams = {
type: "object",
properties: {
pattern: { type: "string", description: "The regex pattern to search for" },
path: { type: "string", description: "Directory to search in" },
},
required: ["pattern", "path"],
};
const cleaned = cleanJSONSchemaForAntigravity(grepParams) as {
properties: Record<string, unknown>;
required?: string[];
};
// The `pattern` *property* must be preserved (it is a tool argument, not a
// string-validation constraint on the object schema itself).
assert.ok(
cleaned.properties && Object.prototype.hasOwnProperty.call(cleaned.properties, "pattern"),
"expected `properties.pattern` to be preserved"
);
assert.equal((cleaned.properties.pattern as { type?: string }).type, "string");
// And it must remain in `required` (cleanupRequired drops names with no property).
assert.ok(
Array.isArray(cleaned.required) && cleaned.required.includes("pattern"),
"expected `required` to still include `pattern`"
);
});
test("#1368: a string-level `pattern` CONSTRAINT is preserved for antigravity", () => {
// Antigravity (Gemini-derived) DOES accept `pattern` on string constraints.
// Stripping it broke glob/grep/file-search tools that express their argument
// regex via `pattern`. The sanitizer must keep it. (Ported from 9router @ f6c2f7ca.)
const schema = {
type: "object",
properties: {
code: { type: "string", pattern: "^[A-Z]{3}$", description: "country code" },
},
required: ["code"],
};
const cleaned = cleanJSONSchemaForAntigravity(schema) as {
properties: { code: Record<string, unknown> };
};
assert.ok(cleaned.properties.code, "the `code` property itself survives");
assert.equal(
(cleaned.properties.code as { pattern?: string }).pattern,
"^[A-Z]{3}$",
"the string `pattern` constraint must be preserved for antigravity"
);
});