Skip to content

fix(opencode): Error 400 missing reasoning_content – transform reasoning according to DeepSeek API and aditional test cases - #17529

Closed
dixoxib wants to merge 2 commits into
anomalyco:devfrom
dixoxib:min
Closed

fix(opencode): Error 400 missing reasoning_content – transform reasoning according to DeepSeek API and aditional test cases#17529
dixoxib wants to merge 2 commits into
anomalyco:devfrom
dixoxib:min

Conversation

@dixoxib

@dixoxibdixoxib commented Mar 14, 2026

Copy link
Copy Markdown

Issue for this PR

Closes#17523, #9397, #8934

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

  1. Fixes DeepSeek API thinking mode handling by ensuring assistant messages after the last user message receive an empty reasoning_content field when thinking mode is enabled.
  2. Only current turn's reasoning is provided for the request.

Problem: When using DeepSeek models with thinking mode (via reasoner model IDs or thinking option), assistant messages after the last user message were missing the reasoning_content field. The DeepSeek API expects this field to be present (even if empty) for proper thinking mode operation in multi-turn conversations. The official DeepSeek API only utilizes current turn reasoning, no need for previous reasoning to be provided.

Changes made:

  1. Modified packages/opencode/src/provider/transform.ts to:

    • Detect when thinking mode is enabled for DeepSeek models (checking capabilities.reasoning, model ID containing "deepseek-reasoner", or thinking: { type: "enabled" } option)
    • Find the index of the last user message in the conversation
    • Set empty reasoning_content for all assistant messages after that index when thinking mode is active
    • Preserve existing behavior for actual reasoning content (keeps reasoning text when present)
  2. Added tests in packages/opencode/test/provider/transform.test.ts covering:

    • DeepSeek with empty reasoning_content for assistant messages after last user message
    • DeepSeek with reasoner model ID
    • DeepSeek with thinking option enabled
    • DeepSeek without thinking mode (should NOT set empty reasoning_content)
    • Non-DeepSeek providers unaffected

Why it works: The DeepSeek API documentation indicates that thinking mode requires the reasoning_content field to be present on assistant messages. By setting it to an empty string for assistant messages after the last user message, we comply with API expectations while maintaining backward compatibility for non-thinking mode usage.

How did you verify your code works?

  1. Ran all existing tests: bun test passes
  2. Added and ran new specific tests for DeepSeek thinking mode scenarios
  3. Manual verification with DeepSeek API would show proper thinking mode behavior in multi-turn conversations
  4. Verified non-DeepSeek providers are unaffected by checking test cases for other providers
  5. live test on the official API

Screenshots / recordings

N/A - This is a backend fix with no UI changes.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

If you do not follow this template your PR will be automatically rejected.

@github-actions

Copy link
Copy Markdown
Contributor

Hey! Your PR title transform to DeepSeek API fix and aditional test cases doesn't follow conventional commit format.

Please update it to start with one of:

  • feat: or feat(scope): new feature
  • fix: or fix(scope): bug fix
  • docs: or docs(scope): documentation changes
  • chore: or chore(scope): maintenance tasks
  • refactor: or refactor(scope): code refactoring
  • test: or test(scope): adding or updating tests

Where scope is the package name (e.g., app, desktop, opencode).

See CONTRIBUTING.md for details.

@github-actionsgithub-actionsBot added the needs:compliance This means the issue will auto-close after 2 hours. label Mar 14, 2026
@dixoxibdixoxib changed the title transform to DeepSeek API fix and aditional test casesfix: Error 400 missing reasoning_content – transform reasoning according to DeepSeek API and aditional test casesMar 14, 2026
@github-actionsgithub-actionsBot removed needs:title needs:compliance This means the issue will auto-close after 2 hours. labels Mar 14, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Thanks for updating your PR! It now meets our contributing guidelines. 👍

Comment threadpackages/opencode/src/provider/transform.ts Outdated
Comment threadpackages/opencode/src/provider/transform.ts Outdated
…king: enabled
DeepSeek requires reasoning_content in providerOptions.openaiCompatible for
all assistant messages, even when empty (the API rejects requests without it).
The generic interleaved handling only runs when capabilities.interleaved is
set to an object with a field, which may not always be the case for DeepSeek
models depending on models.dev data.
- Merge the reasoning part padding into a single DeepSeek‑specific block that
extracts reasoning parts to providerOptions.openaiCompatible.reasoning_content
and strips them from content (with return, skipping generic interleaved)
- Add result["thinking"] = { type: "enabled" } in options() so DeepSeek
reasoning models return reasoning_content in the first place
@dixoxib

Copy link
Copy Markdown
Author

PR #24146 fixed empty reasoning_content.
PR #24443, #24218 fix follow up issues, so this PR is no longer be needed.

@dixoxibdixoxib closed this Apr 29, 2026
@dixoxib
dixoxib deleted the min branch June 11, 2026 07:39
Sign up for freeto 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.

Missing reasoning_content field in the assistant message for DeepSeek API implementation

2 participants

@dixoxib@DenisBalan