From dcca3f76b411d3cc11df28b84f926e8464dde1f5 Mon Sep 17 00:00:00 2001 From: starptech Date: Thu, 21 May 2026 12:37:09 +0200 Subject: [PATCH] Enable required tool choice for structured output tests --- .../opencode/test/provider/provider.test.ts | 16 ++++++++++ packages/opencode/test/session/prompt.test.ts | 32 +++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/packages/opencode/test/provider/provider.test.ts b/packages/opencode/test/provider/provider.test.ts index 1185863bcd..982ffd3de6 100644 --- a/packages/opencode/test/provider/provider.test.ts +++ b/packages/opencode/test/provider/provider.test.ts @@ -2048,16 +2048,32 @@ test("models.dev normalization fills required response fields", () => { output: 128_000, }, }, + "deepseek-reasoner": { + id: "deepseek-reasoner", + name: "DeepSeek Reasoner", + family: "deepseek", + tool_choice_required: false, + cost: { + input: 0.5, + output: 2, + }, + limit: { + context: 64_000, + output: 8_000, + }, + }, }, } as unknown as ModelsDev.Provider const model = Provider.fromModelsDevProvider(provider).models["gpt-5.4"] + const reasoner = Provider.fromModelsDevProvider(provider).models["deepseek-reasoner"] expect(model.api.url).toBe("") expect(model.capabilities.temperature).toBe(false) expect(model.capabilities.reasoning).toBe(false) expect(model.capabilities.attachment).toBe(false) expect(model.capabilities.toolcall).toBe(true) expect(model.capabilities.toolChoiceRequired).toBe(true) + expect(reasoner.capabilities.toolChoiceRequired).toBe(false) expect(model.release_date).toBe("") }) diff --git a/packages/opencode/test/session/prompt.test.ts b/packages/opencode/test/session/prompt.test.ts index a106d5080a..2d8e4b59a6 100644 --- a/packages/opencode/test/session/prompt.test.ts +++ b/packages/opencode/test/session/prompt.test.ts @@ -548,6 +548,38 @@ it.instance("structured output uses auto tool choice and errors when the model i }), ) +it.instance("structured output uses required tool choice by default", () => + Effect.gen(function* () { + const { llm } = yield* useServerConfig(providerCfg) + const prompt = yield* SessionPrompt.Service + const sessions = yield* Session.Service + const chat = yield* sessions.create({ + title: "Pinned", + permission: [{ permission: "*", pattern: "*", action: "allow" }], + }) + yield* llm.text("plain text") + + yield* prompt.prompt({ + sessionID: chat.id, + agent: "build", + model: { providerID: ProviderID.make("test"), modelID: ModelID.make("test-model") }, + parts: [{ type: "text", text: "say hello" }], + format: { + type: "json_schema", + schema: { + type: "object", + properties: { answer: { type: "string" } }, + required: ["answer"], + }, + }, + }) + + const inputs = yield* llm.inputs + expect(inputs).toHaveLength(1) + expect(inputs[0].tool_choice).toBe("required") + }), +) + noLLMServer.instance( "prompt emits v2 prompted and synthetic events", () =>