diff --git a/.changeset/responses-tool-strictness.md b/.changeset/responses-tool-strictness.md new file mode 100644 index 00000000000..5828d25de3c --- /dev/null +++ b/.changeset/responses-tool-strictness.md @@ -0,0 +1,5 @@ +--- +"@opencode-ai/core": patch +--- + +Preserve explicit function tool strictness in Copilot Responses requests. diff --git a/packages/core/src/github-copilot/responses/openai-responses-prepare-tools.ts b/packages/core/src/github-copilot/responses/openai-responses-prepare-tools.ts index 2592636dded..f87c53aa1a1 100644 --- a/packages/core/src/github-copilot/responses/openai-responses-prepare-tools.ts +++ b/packages/core/src/github-copilot/responses/openai-responses-prepare-tools.ts @@ -47,7 +47,7 @@ export function prepareResponsesTools({ name: tool.name, description: tool.description, parameters: tool.inputSchema, - strict: strictJsonSchema, + strict: tool.strict ?? strictJsonSchema, }) break case "provider": { diff --git a/packages/core/test/github-copilot/openai-responses-prepare-tools.test.ts b/packages/core/test/github-copilot/openai-responses-prepare-tools.test.ts new file mode 100644 index 00000000000..011a538a0bb --- /dev/null +++ b/packages/core/test/github-copilot/openai-responses-prepare-tools.test.ts @@ -0,0 +1,20 @@ +import { expect, test } from "bun:test" +import type { LanguageModelV3FunctionTool } from "@ai-sdk/provider" +import { prepareResponsesTools } from "@opencode-ai/core/github-copilot/responses/openai-responses-prepare-tools" + +function prepare(strict: boolean | undefined, strictJsonSchema: boolean) { + const tool: LanguageModelV3FunctionTool = { + type: "function", + name: "lookup", + inputSchema: { type: "object", properties: {} }, + strict, + } + return prepareResponsesTools({ tools: [tool], strictJsonSchema }).tools?.[0] +} + +test("function tools prefer explicit strictness over the global fallback", () => { + expect(prepare(true, false)).toMatchObject({ type: "function", strict: true }) + expect(prepare(false, true)).toMatchObject({ type: "function", strict: false }) + expect(prepare(undefined, true)).toMatchObject({ type: "function", strict: true }) + expect(prepare(undefined, false)).toMatchObject({ type: "function", strict: false }) +})