Skip to content

fix(openai): preserve reasoning for local OpenAI-compatible models via R1 toggle - #1119

Open
ch405canova-sudo wants to merge 1 commit into
Zoo-Code-Org:mainfrom
ch405canova-sudo:fix/preserve-reasoning-openai-compatible
Open

fix(openai): preserve reasoning for local OpenAI-compatible models via R1 toggle#1119
ch405canova-sudo wants to merge 1 commit into
Zoo-Code-Org:mainfrom
ch405canova-sudo:fix/preserve-reasoning-openai-compatible

Conversation

@ch405canova-sudo

@ch405canova-sudo ch405canova-sudo commented Aug 4, 2026

Copy link
Copy Markdown

Summary

Local OpenAI-compatible reasoning models (llama.cpp llama-server, LM Studio, Ollama's OpenAI endpoint, vLLM, etc.) stream a reasoning_content field, 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 via R1FormatSetting and declared in provider-settings.ts) only forces the R1 request format in openai.ts. It never propagates to info.preserveReasoning, which is what gates reasoning retention in Task.ts:

// src/core/task/Task.ts
const shouldPreserveForApi = this.api.getModel().info.preserveReasoning === true

OpenAiHandler.getModel() builds its ModelInfo from openAiCustomModelInfo ?? openAiModelInfoSaneDefaults — neither sets preserveReasoning. For the built-in OpenAI-compatible provider the value is therefore always undefined, and reasoning is stripped from messages sent back to the API.

Fix

When the user enables the R1 format toggle, getModel() now sets preserveReasoning: true on the returned model info:

return {
    id,
    info: this.options.openAiR1FormatEnabled ? { ...info, preserveReasoning: true } : info,
    ...params,
}

This preserves reasoning_content in the assistant history sent to the model on follow-up turns. Default behaviour (toggle off) is unchanged.

Tests

Added two getModel cases to src/api/providers/__tests__/openai.spec.ts:

  • preserveReasoning is true when openAiR1FormatEnabled is on
  • preserveReasoning stays undefined by default

Related

Fixes #1118

Summary by CodeRabbit

  • New Features

    • Added support for preserving reasoning information when the OpenAI R1 format option is enabled.
  • Bug Fixes

    • Ensured model configuration remains unchanged when the option is disabled.

…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.
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: bec01852-0b5b-4180-9661-4c1494390c37

📥 Commits

Reviewing files that changed from the base of the PR and between 7918f6b and beef72e.

📒 Files selected for processing (2)
  • src/api/providers/__tests__/openai.spec.ts
  • src/api/providers/openai.ts

📝 Walkthrough

Walkthrough

OpenAiHandler.getModel now adds preserveReasoning: true when openAiR1FormatEnabled is enabled. Tests verify the enabled state and confirm that the property remains undefined by default.

Changes

OpenAI reasoning configuration

Layer / File(s) Summary
Conditional model configuration
src/api/providers/openai.ts, src/api/providers/__tests__/openai.spec.ts
getModel adds preserveReasoning: true when the R1 format setting is enabled. Tests cover enabled and default behavior.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related issues

Possibly related PRs

Suggested labels: awaiting-review

Suggested reviewers: edelauna, taltas

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the OpenAI fix and the R1 toggle behavior.
Description check ✅ Passed The description explains the root cause, implementation, tests, and linked issue, but does not follow every template heading.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

src/api/providers/__tests__/openai.spec.ts

ESLint skipped: missing config or dependency (missing-dependency). The ESLint configuration references a package that is not available in the sandbox.

src/api/providers/openai.ts

ESLint 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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@ch405canova-sudo

Copy link
Copy Markdown
Author

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

codecov Bot commented Aug 4, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@ch405canova-sudo

Copy link
Copy Markdown
Author

This PR addresses the same root cause as #1096 (local OpenAI-compatible reasoning is discarded because preserveReasoning is never enabled for the built-in OpenAI-compatible provider).

Note on approach: #1096 proposes a separate preserveReasoning checkbox, while this PR couples it to the existing R1-format toggle. Both solve the underlying issue — happy to align with whichever approach the maintainers prefer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting-review PR changes are ready and waiting for maintainer re-review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Reasoning from local OpenAI-compatible models (llama.cpp/Ollama/LM Studio) is discarded — no official toggle

1 participant