fix(openai): preserve reasoning for local OpenAI-compatible models via R1 toggle - #1119
Conversation
…a R1 toggle The openAiR1FormatEnabled toggle (UI + provider-settings) only forced the R1 request format, but getModel() never set info.preserveReasoning. As a result Task.ts (shouldPreserveForApi = info.preserveReasoning === true) stripped reasoning_content from follow-up context for every local OpenAI-compatible reasoning model (llama.cpp, LM Studio, Ollama) — there was no way to feed the chain back. Enable the toggle and getModel() now sets preserveReasoning: true so the reasoning chain is preserved in the next-turn context. Default behaviour unchanged.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthrough
ChangesOpenAI reasoning configuration
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related issues
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
src/api/providers/__tests__/openai.spec.tsESLint skipped: missing config or dependency (missing-dependency). The ESLint configuration references a package that is not available in the sandbox. src/api/providers/openai.tsESLint skipped: the ESLint configuration for this file references a package that is not available in the sandbox. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
This work is a joint effort by chaos (@ch405canova-sudo) and opencode — the bug was found and the fix developed together on a local llama.cpp stack (August 2026). |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
This PR addresses the same root cause as #1096 (local OpenAI-compatible reasoning is discarded because Note on approach: #1096 proposes a separate |
Summary
Local OpenAI-compatible reasoning models (llama.cpp
llama-server, LM Studio, Ollama's OpenAI endpoint, vLLM, etc.) stream areasoning_contentfield, but Zoo Code strips it from the follow-up context for these providers — so the model can never see its own reasoning chain on the next turn.Root cause
openAiR1FormatEnabled(exposed as a UI checkbox viaR1FormatSettingand declared inprovider-settings.ts) only forces the R1 request format inopenai.ts. It never propagates toinfo.preserveReasoning, which is what gates reasoning retention inTask.ts:OpenAiHandler.getModel()builds itsModelInfofromopenAiCustomModelInfo ?? openAiModelInfoSaneDefaults— neither setspreserveReasoning. For the built-in OpenAI-compatible provider the value is therefore alwaysundefined, and reasoning is stripped from messages sent back to the API.Fix
When the user enables the R1 format toggle,
getModel()now setspreserveReasoning: trueon the returned model info:This preserves
reasoning_contentin the assistant history sent to the model on follow-up turns. Default behaviour (toggle off) is unchanged.Tests
Added two
getModelcases tosrc/api/providers/__tests__/openai.spec.ts:preserveReasoningistruewhenopenAiR1FormatEnabledis onpreserveReasoningstaysundefinedby defaultRelated
Fixes #1118
Summary by CodeRabbit
New Features
Bug Fixes