Repository navigation
Zen gateway does not forward reasoning/thinking stream for Muse Spark 1.2 #43584
Description
Summary
Muse Spark 1.2 (muse-spark-1.2, muse-spark-1.2-contributor) supports reasoning/thinking, but the Zen gateway (https://opencode.ai/zen/go/v1) does not expose the reasoning stream to OpenAI-compatible clients. When streaming via either /v1/chat/completions or /v1/responses, clients receive only the final assistant text; no reasoning_content / reasoning_details / thinking delta is ever emitted, so UIs cannot render a thinking bubble even though the model is reasoning on the server side.
This is distinct from #43379 (missing finish_reason on streaming completions for muse-*). That issue blocks chat/completions entirely. After pinning muse-spark to responses (as done in oh-my-pi #8980), calls succeed but the thinking remains invisible.
Steps to Reproduce
- Subscribe to OpenCode Go and obtain a Zen API key.
- Stream a request for
muse-spark-1.2-contributorvia the Zen gateway:POST https://opencode.ai/zen/go/v1/responseswith"stream": trueandreasoning: { effort: "high" }(Responses API), orPOST https://opencode.ai/zen/go/v1/chat/completionswith"stream": true(OpenAI chat completions)
- Observe the SSE stream.
Expected Behavior
Per OpenAI Responses / chat completions streaming conventions, the gateway should forward reasoning deltas when the upstream model produces them, e.g.:
- Responses API:
response.output_text.deltafor reasoning or a dedicatedreasoningevent - Chat completions:
choices[0].delta.reasoning_content(or equivalentreasoningfield)
Clients that render thinking (Hermes, oh-my-pi, other agent UIs) rely on these deltas to show progress.
Actual Behavior
- Only
output_text/choices[0].delta.contentis streamed. - No reasoning delta is emitted at any point, even with
reasoning.effort = high. - The model does reason server-side (higher latency and token usage vs
effort: none), but the thinking is not observable client-side.
Environment
- Endpoint:
https://opencode.ai/zen/go/v1/{responses,chat/completions} - Models:
muse-spark-1.2,muse-spark-1.2-contributor(alias) - Client: any OpenAI-compatible streaming client (Hermes Agent, oh-my-pi)
- Auth: Zen Go API key
Impact
- Users cannot see or debug the model's reasoning, making long turns appear as hangs.
- Agent UIs that gate on reasoning (e.g., showing a spinner/thinking block) show no progress until the final answer arrives.
Suggested Fix
- For
/v1/responses: forward upstream reasoning events as Responses API reasoning deltas. - For
/v1/chat/completions: map reasoning todelta.reasoning_content(or the gateway's chosen field) when streaming. - If upstream does not provide a structured reasoning stream, consider exposing it once available rather than swallowing it.
Related
- Streaming responses for muse-* models on the Zen gateway never send finish_reason — strict OpenAI-compatible clients enter a retry loop #43379 — missing
finish_reasonfor muse-* onchat/completions(blocking, open) - muse spark 1.2 from opencode go repeatedly throws errors can1357/oh-my-pi#8957 / feat: bind vim-style line-by-line scrolling #8980 — pinned muse-spark to
responsesto work around Streaming responses for muse-* models on the Zen gateway never send finish_reason — strict OpenAI-compatible clients enter a retry loop #43379 (merged) - This issue remains after that workaround: calls succeed, but reasoning is still not forwarded.
Happy to provide additional logs or test against a staging gateway if helpful.
Activity
mysoul12138 commentedon Aug 21, 2026
Update with raw SSE capture data
We ran a detailed packet capture against
POST /zen/go/v1/responseswithmodel: "muse-spark-1.2-contributor"andreasoning: { effort: "high" }.Here are the key findings from the raw SSE events:
Server-side reasoning is confirmed active and counted:
The
response.completedevent usage breakdown explicitly reports reasoning tokens:Reasoning plaintext is omitted / sealed in
encrypted_content:In the
response.output_item.added/doneevents for thereasoningitem:{ "type": "reasoning", "id": "rs_...", "summary": [], "content": null, "encrypted_content": "Q-PaDgGKS2vX5BATTuQ6vWAGET7tc3Jiy8l0B6h_..." // ~11KB opaque encrypted blob }contentisnullsummaryis[]response.reasoning_text.delta(or intermediate text chunk) is ever emitted during the stream.Root Cause:
The gateway only forwards the opaque
encrypted_contentcontainer but does not stream or expose the plaintext reasoning tokens/deltas. As a result, client UIs cannot render the thinking process even though 1,200+ reasoning tokens were generated on the backend.Could the gateway team expose the plaintext reasoning stream (or summary deltas) alongside
encrypted_contentformuse-spark-1.2?hi-one-gg commentedon Aug 24, 2026
Even if the reasoning level is adjusted, I thought there was no reasoning process because the number of generated tokens is small. But does it actually reason on the backend? If not, OpenCode should compensate users for this.
aggieturing-code commentedon Sep 5, 2026
Not forwarding reasoning_content/thinking deltas breaks the client's ability to render thinking, and it's a common gateway regression. GateLLM treats reasoning-token streaming as lossless — reasoning deltas pass through with protocol translation preserved, so downstream UIs see thinking regardless of which upstream served it.