fix(ai): force tool calls so tag generation stops returning prose - #333
Merged
Merged
Conversation
The OpenAI chat-completion provider hard-coded tool_choice: "auto", which lets a model answer a tool-requesting prompt in plain text. deepseek-flash and similar models do exactly that: on the tag-migration prompt the assistant reply is a comma-separated list with no tool_calls, so executeToolCall returns success:false and handleRunTagMigrationBatch silently skips the tag write. The migration then reports success while memories stay untagged and the modal reappears on every load (#303). Default tool_choice to "required" so the model must emit the tool call, with an opt-out (forceToolChoice:false) for providers that reject it. Also align the migration prompt with the tool it is meant to call instead of asking for a comma-separated list.
Make the tool_choice required opt-out reachable from opencode.json and surface a clear config hint when thinking models reject forced tool calls.
EyJunge1
force-pushed
the
fix/tag-choice-required
branch
from
October 1, 2026 19:38
96d5a46 to
48a22aa
Compare
2 of 3 tasks
4 tasks done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Addresses the prose-without-tool-call failure mode from #303 (complementary with #319 for soft-fail accounting).
The OpenAI chat-completion provider hard-coded
tool_choice: "auto", which lets a model answer a tool-requesting prompt in plain text. The tag-migration prompt asked for a tool call (save_tags) but also said "Return ONLY a comma-separated list of tags", so models likedeepseek-flash/deepseek-v4-flashreturn prose with notool_calls.executeToolCallthen returnssuccess: false,handleRunTagMigrationBatchsilently skips the tag write, and the migration reports success while memories stay untagged — so the modal reappears on every page load.Verified directly against
deepseek-flashwith the exact migration prompt:tool_choice: "auto"(previous)"Manim, 数学动画引擎, Python, Manim CE"— no tool_callstool_choice: "required"save_tagscalled with{"tags": [...]}Changes
base-provider.ts— addforceToolChoice?: booleantoProviderConfig.openai-chat-completion.ts— sendtool_choice: "required"unlessforceToolChoice === false.config.ts/provider-config.ts— wireforceToolChoicethrough user config ("forceToolChoice": falseopt-out).openai-chat-completion.ts— 400 hint when thinking mode rejectstool_choice.api-handlers.ts— migration prompt asks for thesave_tagstool call.Relation to #319
#319 fixes soft-fail accounting / UI false success. This PR reduces the prose failure mode. Merge both. Empty
arguments: "{}"remains a separate path.Does not solely close #303. Rebased onto current
main.Test plan
bunx tsc --noEmit— cleanbun test tests/openai-chat-completion-provider.test.ts tests/orcarouter-provider.test.ts tests/ai-provider-config.test.ts— passmainverified clean7 → 0