Skip to content

fix(llm): clear ReasoningEffort when DeepSeek thinking is disabled#1663

Merged
looplj merged 1 commit into
looplj:unstablefrom
Lucent-Snow:fix/deepseek-reasoning-effort-none
May 14, 2026
Merged

fix(llm): clear ReasoningEffort when DeepSeek thinking is disabled#1663
looplj merged 1 commit into
looplj:unstablefrom
Lucent-Snow:fix/deepseek-reasoning-effort-none

Conversation

@Lucent-Snow

Copy link
Copy Markdown
Contributor

Summary

When reasoning_effort: "none" is sent to disable thinking mode for DeepSeek channels, the outbound transformer correctly sets thinking: {type: "disabled"} but fails to clear the ReasoningEffort field from the underlying OpenAI Request struct. This causes the JSON body sent to DeepSeek API to contain both:

{
    "reasoning_effort": "none",
    "thinking": {"type": "disabled"}
}

DeepSeek API rejects reasoning_effort: "none" as unknown (only accepts high/low/medium/max/xhigh), returning HTTP 400.

Fix

Clear Request.ReasoningEffort to empty string when thinking is disabled, so it is omitted from JSON via omitempty. The DeepSeek API receives only thinking: {type: "disabled"} which correctly disables thinking.

Changes

  • llm/transformer/deepseek/outbound.go: Clear ReasonableEffort when thinkingDisabled is true

Note: The Anthropic-format DeepSeek path (llm/transformer/anthropic/outbound_convert.go) was already fixed in #1552 (commit 78ab459).

Closes #1662

Test plan

  • Send reasoning_effort: "none" to a DeepSeek channel via /v1/chat/completions — should return normal response without 400 error
  • Send reasoning_effort: "high" — should still enable thinking with high effort

🤖 Generated with Claude Code

When reasoning_effort="none" is sent to disable thinking, the DeepSeek
outbound transformer correctly sets thinking.type="disabled" but fails
to clear the ReasoningEffort field from the underlying OpenAI request.
This causes DeepSeek API to reject the request with:
  reasoning_effort: unknown variant `none`

Clear ReasoningEffort to empty string so it is omitted from the JSON
via omitempty, leaving only thinking.type="disabled".

Closes looplj#1662

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented May 14, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a bug where sending reasoning_effort: "none" to a DeepSeek channel would result in both "reasoning_effort":"none" and "thinking":{"type":"disabled"} being forwarded to the DeepSeek API simultaneously, causing an HTTP 400 because DeepSeek does not accept "none" as a valid reasoning effort value.

  • Clears dsReq.Request.ReasoningEffort to "" in outbound.go when thinkingDisabled is true, so the omitempty JSON tag suppresses the field from the serialized body.
  • The parallel Anthropic-format path (llm/transformer/anthropic/outbound_convert.go) was already fixed in fix(llm): missing anthropic thinking disabled transform #1552; this closes the same gap in the direct OpenAI-format DeepSeek path.

Confidence Score: 4/5

The change is a minimal, targeted one-liner that correctly exploits the existing omitempty tag to suppress the rejected field. Safe to merge.

The fix is correct and well-scoped. The only gap is that the existing test for the 'none' reasoning effort case doesn't assert that ReasoningEffort is absent from the serialized JSON, so a regression could slip through unnoticed in the future.

llm/transformer/deepseek/outbound_test.go — the test covering this path should assert that ReasoningEffort is empty in the output body.

Important Files Changed

Filename Overview
llm/transformer/deepseek/outbound.go Adds a single line to clear ReasoningEffort when thinking is disabled, preventing "reasoning_effort":"none" from being sent to the DeepSeek API which rejects it with HTTP 400.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Incoming llm.Request\nReasoningEffort = 'none'] --> B[Build dsReq from oaiReq\nReasoningEffort = 'none' copied in]
    B --> C{thinkingDisabled?\nReasoningEffort == 'none'}
    C -- Yes --> D[Set Thinking.Type = 'disabled']
    D --> E[Clear ReasoningEffort = ''\nomitempty omits from JSON]
    E --> F[JSON body sent to DeepSeek\nthinking: disabled ONLY]
    C -- No --> G[Set Thinking.Type = 'enabled'\nKeep ReasoningEffort as-is]
    G --> H[Fill empty reasoning_content\nin assistant messages]
    H --> I[JSON body sent to DeepSeek\nthinking: enabled + reasoning_effort]
    F --> J[DeepSeek API accepts]
    I --> J
Loading

Comments Outside Diff (1)

  1. llm/transformer/deepseek/outbound.go, line 142-145 (link)

    P2 Test doesn't assert ReasoningEffort is cleared

    The existing "reasoning effort none disables thinking" test case only asserts dsReq.Thinking.Type == "disabled" — it never checks that dsReq.ReasoningEffort is empty in the serialized JSON body. Without that assertion the test would have passed even before this fix, so a future regression that re-introduces "reasoning_effort":"none" in the payload would go undetected. Adding assert.Equal(t, "", dsReq.ReasoningEffort) (or inspecting the raw got.Body for the absence of "reasoning_effort") would lock in the bug fix.

Reviews (1): Last reviewed commit: "fix(llm): clear ReasoningEffort when Dee..." | Re-trigger Greptile

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the DeepSeek outbound transformer to clear the ReasoningEffort field when thinking is disabled, ensuring compatibility with the DeepSeek API by omitting unsupported values. I have no further feedback to provide.

@looplj looplj merged commit 473cc90 into looplj:unstable May 14, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug/错误]: DeepSeek 通道 reasoning_effort="none" 关闭思考时报 400 错误

2 participants