Skip to content

[Bug] Zen Go /v1/chat/completions strips usage.completion_tokens_details for deepseek-v4-flash - official DeepSeek API sends it #45606

Closed as not planned

Description

@shashwatx

Description

The Zen Go OpenAI-compatible endpoint (https://opencode.ai/zen/go/v1/chat/completions) strips usage.completion_tokens_details.reasoning_tokens from responses for deepseek-v4-flash, while the official DeepSeek API (https://api.deepseek.com/chat/completions) reports it for the same model id, same prompt, same request shape.

The thinking text itself is forwarded (choices[0].message.reasoning_content is populated), so the model clearly engages reasoning through the gateway — only the token accounting for it disappears. Two additional DeepSeek-native usage fields (prompt_cache_hit_tokens, prompt_cache_miss_tokens) are likewise absent, and usage. prompt_tokens_details arrives hollowed ({} even when populated upstream).

This is a provider-specific gap in the gateway's normalization layer rather than a model-behavior difference: on this exact endpoint/harness/prompt combination, a kimi-k2.6 request returns a fully-populated details block minutes apart from a deepseek-v4-flash request that returns none.

Expected Behavior

Per the official DeepSeek API docs, the response usage should include:

"usage": {
   "completion_tokens": 0,
   "prompt_tokens": 0,
   "prompt_cache_hit_tokens": 0,
   "prompt_cache_miss_tokens": 0,
   "total_tokens": 0,
   "completion_tokens_details": {
     "reasoning_tokens": 0
}

and per the OpenAI chat-completions convention that Zen's own normalization code follows (see PR #24441), completion_tokens_details.reasoning_tokens is part of the standard
usage shape the gateway is expected to forward.

Actual Behavior

"usage": {
  "prompt_tokens": 124,
  "completion_tokens": 198,
  "total_tokens": 322,
  "prompt_tokens_details": {}
}
  • usage.completion_tokens_details is absent entirely on every Zen Go response for deepseek-v4-flash (12+ attempts over two days, at different hours, trivial and reasoning-
    forcing prompts), while message.reasoning_content is delivered.
  • usage.prompt_tokens_details arrives as {} (hollowed) instead of the populated shape the official API sends.
  • prompt_cache_hit_tokens / prompt_cache_miss_tokens are dropped, masking whether DeepSeek prefix caching engaged per request.
  • The same harness seconds apart returns a fully-populated details block for kimi-k2.6 — so the gateway is capable of forwarding it; the gap is specific to the DeepSeek path.

Plugins

No response

OpenCode version

1.18.23

Steps to reproduce

The strip is deterministic across 12+ requests spanning two days, trivial and forcing
prompts, stream=false, at different hours.

  1. Send the identical request body to both endpoints (fixed combinatorial prompt that forces reasoning):
FIXED='Solve step by step internally, then respond ONLY with valid JSON {"count": <int>}. How many distinct arrangements of the letters in "MISSISSIPPI" have no two S characters   adjacent?'

BODY='{"model":"deepseek-v4-flash","messages":[{"role":"user","content":"'"$FIXED"'"}],"max_tokens":8000,"response_format":{"type":"json_object"},"stream":false}'

# Zen Go — completion_tokens_details MISSING
curl -s https://opencode.ai/zen/go/v1/chat/completions \
  -H "Authorization: Bearer $OPENCODE_GO_API_KEY" \
  -H "Content-Type: application/json" -d "$BODY" | jq '.usage'

# Official DeepSeek — completion_tokens_details.reasoning_tokens present
curl -s https://api.deepseek.com/chat/completions \
  -H "Authorization: Bearer $DEEPSEEK_API_KEY" \
  -H "Content-Type: application/json" -d "$BODY" | jq '.usage'
  1. Zen Go result (capture F1, cf-ray a31b27150f0aa330-SEA, 2026-08-27 12:41:52 GMT):
{"prompt_tokens": 124, "completion_tokens": 198, "total_tokens": 322,
 "prompt_tokens_details": {}}

choices[0].message.reasoning_content is populated (~500 chars of thinking) — the model reasoned; only the accounting vanished.

  1. Official result minutes later (capture D2, 2026-08-27 11:33:14 GMT), same model id + prompt:
{"prompt_tokens": 144, "completion_tokens": 221, "total_tokens": 365,
 "prompt_tokens_details": {"cached_tokens": 0},
 "completion_tokens_details": {"reasoning_tokens": 214},
 "prompt_cache_hit_tokens": 0, "prompt_cache_miss_tokens": 144}
  1. Positive control through the same gateway, same harness/prompt, minutes apart (capture F2, cf-ray a31b2b91ef3390db-SEA, 2026-08-27 12:45:43 GMT) — kimi-k2.6 returns
    the full OpenAI details shape:
"prompt_tokens_details": {"audio_tokens": 0, "cached_tokens": 47, "cache_write_tokens": 0},
"completion_tokens_details": {"audio_tokens": 0, "reasoning_tokens": 1757}

Captures were made with plain httpx/curl POSTs (no SDK, no OpenCode client parsing) — this rules out client-side field stripping

Screenshot and/or share link

No response

Operating System

macOS 14.5.0, arm64

Terminal

Ghostty

Activity

  1. github-actions commented on Aug 27, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    If your issue is specifically about the completion_tokens_details.reasoning_tokens being stripped (rather than caching behavior), it may still be a distinct problem worth tracking separately.

  2. changed the title [-]Zen Go /v1/chat/completions strips usage.completion_tokens_details for deepseek-v4-flash - official DeepSeek API sends it[/-] [+][Bug] Zen Go /v1/chat/completions strips usage.completion_tokens_details for deepseek-v4-flash - official DeepSeek API sends it[/+] on Aug 28, 2026
  3. shashwatx commented on Aug 28, 2026

    @shashwatx
    Author

    Thanks for the triaging.
    The issues highlighted in the comment above are related but different.

    One data point that may help triage all three: a positive control through the same endpoint, harness, and fixed prompt shows the gateway does forward the complete completion_tokens_details + a populated prompt_tokens_details for kimi-k2.6 (reasoning_tokens: 1757), minutes apart from a deepseek-v4-flash response where the block is absent entirely. So this looks like a per-provider gap in the gateway's usage normalization (cf. the oaCompatHelper.normalizeUsage surface in #24441) rather than a gateway-wide or model-behavior issue — plausibly one root cause feeding all three threads.

  4. thdxr commented on Oct 11, 2026

    @thdxr
    Member

    Thanks for the report! OpenCode 2.0 is now out and development is focused on V2, so we're closing issues filed against OpenCode 1. Please upgrade (opencode upgrade --major, details: https://anoma.ly/notes/opencode-2-0), and if this is still relevant on 2.0, reopen this issue or open a new one with your 2.0 version.

    — from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊

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

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