From 9f61a85d73a7ccc570bfd7ce24786d381d456d4f Mon Sep 17 00:00:00 2001 From: can1357 Date: Sun, 26 Apr 2026 03:44:45 +0200 Subject: [PATCH] fix(ai): removed unsupported array item count constraints from Anthropic tool schemas - Added maxItems to the set of unsupported tool schema fields. - Removed minItems constraints that are not 0 or 1, as Anthropic only supports these specific values. - Added test to verify maxItems and non-standard minItems are stripped while minItems: 1 is preserved. --- packages/ai/src/providers/anthropic.ts | 6 ++- packages/ai/test/anthropic-alignment.test.ts | 44 ++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/packages/ai/src/providers/anthropic.ts b/packages/ai/src/providers/anthropic.ts index 0fa86c4e2..753cb7758 100644 --- a/packages/ai/src/providers/anthropic.ts +++ b/packages/ai/src/providers/anthropic.ts @@ -1751,7 +1751,7 @@ export function convertAnthropicMessages( return params; } -const ANTHROPIC_UNSUPPORTED_TOOL_SCHEMA_FIELDS = new Set(["patternProperties"]); +const ANTHROPIC_UNSUPPORTED_TOOL_SCHEMA_FIELDS = new Set(["maxItems", "patternProperties"]); const MAX_ANTHROPIC_STRICT_TOOLS = 20; const MAX_ANTHROPIC_STRICT_OPTIONAL_PARAMETERS = 24; const MAX_ANTHROPIC_STRICT_UNION_PARAMETERS = 16; @@ -1769,6 +1769,10 @@ function normalizeAnthropicToolSchema( Object.entries(schema).filter(([key]) => !ANTHROPIC_UNSUPPORTED_TOOL_SCHEMA_FIELDS.has(key)), ); cache.set(schema, result); + const minItems = result.minItems; + if (typeof minItems === "number" && minItems !== 0 && minItems !== 1) { + delete result.minItems; + } const type = result.type; const canBeObject = diff --git a/packages/ai/test/anthropic-alignment.test.ts b/packages/ai/test/anthropic-alignment.test.ts index 2b7d144c0..90566c3f5 100644 --- a/packages/ai/test/anthropic-alignment.test.ts +++ b/packages/ai/test/anthropic-alignment.test.ts @@ -356,6 +356,50 @@ describe("Anthropic request fingerprint alignment", () => { expect(originalNestedSchema).toHaveProperty("patternProperties"); }); + it("removes Anthropic-unsupported array item count constraints", async () => { + const tools: Tool[] = [ + { + name: "edit_file", + description: "edit files", + parameters: { + type: "object", + properties: { + sub: { + type: "array", + items: { type: "string" }, + minItems: 2, + maxItems: 2, + }, + nonEmpty: { + type: "array", + items: { type: "string" }, + minItems: 1, + }, + }, + required: ["sub"], + } as unknown as TSchema, + }, + ]; + + const payload = (await captureAnthropicPayload(ANTHROPIC_MODEL, { + systemPrompt: "Stay concise.", + messages: [{ role: "user", content: "Hi", timestamp: Date.now() }], + tools, + })) as { + tools?: Array<{ + input_schema?: { + properties?: Record; + }; + }>; + }; + + const properties = payload.tools?.[0]?.input_schema?.properties as Record>; + + expect(properties.sub).not.toHaveProperty("minItems"); + expect(properties.sub).not.toHaveProperty("maxItems"); + expect(properties.nonEmpty.minItems).toBe(1); + }); + it("marks at most twenty Anthropic tools strict", async () => { const tools: Tool[] = Array.from({ length: 25 }, (_, index) => ({ name: `tool_${index}`,