diff --git a/src/plugin-sdk/provider-tools.test.ts b/src/plugin-sdk/provider-tools.test.ts index 153713f87ce..a4e5aeea530 100644 --- a/src/plugin-sdk/provider-tools.test.ts +++ b/src/plugin-sdk/provider-tools.test.ts @@ -72,6 +72,35 @@ describe("buildProviderToolCompatFamilyHooks", () => { ).toEqual([]); }); + it("preserves explicit empty properties maps when normalizing strict openai schemas", () => { + const hooks = buildProviderToolCompatFamilyHooks("openai"); + const parameters = { + type: "object", + properties: {}, + }; + const tools = [{ name: "ping", description: "", parameters }] as never; + + const normalized = hooks.normalizeToolSchemas({ + provider: "openai", + modelId: "gpt-5.4", + modelApi: "openai-responses", + model: { + provider: "openai", + api: "openai-responses", + baseUrl: "https://api.openai.com/v1", + id: "gpt-5.4", + } as never, + tools, + }); + + expect(normalized[0]?.parameters).toEqual({ + type: "object", + properties: {}, + required: [], + additionalProperties: false, + }); + }); + it("does not tighten permissive object schemas just to satisfy strict mode", () => { const hooks = buildProviderToolCompatFamilyHooks("openai"); const permissiveParameters = { diff --git a/src/plugin-sdk/provider-tools.ts b/src/plugin-sdk/provider-tools.ts index fec86fca99f..4c8a62a0efd 100644 --- a/src/plugin-sdk/provider-tools.ts +++ b/src/plugin-sdk/provider-tools.ts @@ -229,7 +229,17 @@ function normalizeOpenAIStrictCompatSchemaRecursive(schema: unknown): unknown { let changed = false; const normalized: Record = {}; for (const [key, value] of Object.entries(record)) { - const next = normalizeOpenAIStrictCompatSchemaRecursive(value); + const next = + key === "properties" && value && typeof value === "object" && !Array.isArray(value) + ? Object.fromEntries( + Object.entries(value as Record).map( + ([propertyName, propertyValue]) => [ + propertyName, + normalizeOpenAIStrictCompatSchemaRecursive(propertyValue), + ], + ), + ) + : normalizeOpenAIStrictCompatSchemaRecursive(value); normalized[key] = next; changed ||= next !== value; }