Files
openclaw/src/agents/openai-tool-schema.test.ts
2026-05-02 09:48:32 +01:00

66 lines
2.2 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
isStrictOpenAIJsonSchemaCompatible,
normalizeStrictOpenAIJsonSchema,
resolveOpenAIStrictToolFlagForInventory,
} from "./openai-tool-schema.js";
describe("OpenAI strict tool schema normalization", () => {
it("repairs top-level object schemas with missing or invalid properties", () => {
const schemas = [
{ type: "object" },
{ type: "object", properties: undefined },
{ type: "object", properties: null },
{ type: "object", properties: [] },
{ type: "object", properties: "invalid" },
];
for (const schema of schemas) {
expect(normalizeStrictOpenAIJsonSchema(schema)).toEqual({
type: "object",
properties: {},
required: [],
additionalProperties: false,
});
expect(isStrictOpenAIJsonSchemaCompatible(schema)).toBe(true);
expect(
resolveOpenAIStrictToolFlagForInventory([{ name: "empty", parameters: schema }], true),
).toBe(true);
}
});
it("does not close permissive nested object schemas implicitly", () => {
const schema = {
type: "object",
properties: {
metadata: {
type: "object",
},
},
required: ["metadata"],
};
const normalized = normalizeStrictOpenAIJsonSchema(schema) as {
additionalProperties?: boolean;
properties?: { metadata?: { additionalProperties?: boolean } };
};
expect(normalized.additionalProperties).toBe(false);
expect(normalized.properties?.metadata).not.toHaveProperty("additionalProperties");
expect(isStrictOpenAIJsonSchemaCompatible(schema)).toBe(false);
expect(
resolveOpenAIStrictToolFlagForInventory([{ name: "write", parameters: schema }], true),
).toBe(false);
});
it("normalizes truly empty MCP tool schema {} for strict mode", () => {
const schema = {};
const normalized = normalizeStrictOpenAIJsonSchema(schema) as Record<string, unknown>;
expect(normalized.type).toBe("object");
expect(normalized.properties).toEqual({});
expect(normalized.required).toEqual([]);
expect(normalized.additionalProperties).toBe(false);
expect(isStrictOpenAIJsonSchemaCompatible(schema)).toBe(true);
});
});