Skip to content

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

Description

@ch405canova-sudo

Describe the bug
When connecting Zoo Code to a local OpenAI-compatible chat model that emits a reasoning_content field (llama.cpp, Ollama's OpenAI endpoint, LM Studio), the reasoning is silently discarded from the assistant messages. The model therefore cannot see its own reasoning chain, which reduces output quality and inflates token usage on follow-up turns.

To Reproduce

  1. Run a local OpenAI-compatible server that streams reasoning_content alongside content, e.g. llama.cpp llama-server (any reasoning model such as Qwen3.6/QwQ/DeepSeek-R1).
  2. In Zoo Code, add it as an OpenAI-compatible provider with the local base URL.
  3. Run any task and observe the messages sent back to the provider on the next turn.
  4. The assistant message contains only content, the reasoning_content is dropped.

Expected behavior
reasoning_content should be preserved and fed back so the local model sees its own reasoning, OR there should be an official setting to enable R1-format handling for OpenAI-compatible providers.

What version of zoo are you running
3.74.0 (also affects current main)

Root cause
src/api/providers/openai.ts:88-90:

const enabledR1Format = this.options.openAiR1FormatEnabled ?? false
const deepseekReasoner = modelId.includes("deepseek-reasoner") || enabledR1Format

openAiR1FormatEnabled exists only on the provider's options object but is never set anywhere in the codebase — no UI setting, no package.json configuration, no provider-creation code touches it. So the R1 format path (which parses and preserves reasoning_content) is effectively dead for every model whose id doesn't literally contain deepseek-reasoner.

The deepseekReasoner flag then gates convertToR1Format(...) (line 106) and the reasoning parse/save logic further down in the streaming path. Local models are left with reasoning stripped.

Workaround (current)
Patch the bundled dist/extension.js to force the R1 flag (d=!0 for the OpenAI stream) and hard-enable preserveReasoning. Details and the exact search/replace strings are documented. A source-level equivalent of the same change is what this issue asks to be fixed in-tree.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions