anomalyco / anomalyco/opencode

[Zen/GO Gateway] Short reply via Anthropic-compat endpoint missing stop_reason -> client triggers false retry (duplicate output)

Open
#43,617 1 comment 0 reactions 1 assignee View on GitHub

@MrMushrooooom is already working on this.

Since Aug 20, 2026.

Dominant language
TypeScript
Stars
209k
Forks
27.5k
PR merge metrics
PR metrics pending

Description

Summary

When using the Zen/GO gateway (https://opencode.ai/zen/go/v1) via its Anthropic-compatible endpoint, very short completions cause the client to think the stream was truncated and auto-retry with Continue exactly where you left off, producing garbled duplicate output.

Root cause appears to be OpenAI -> Anthropic streaming translation: the final stop_reason / message_stop event is missing or not forwarded for short replies, so Anthropic clients never receive a clean termination.

Repro

  • Gateway: https://opencode.ai/zen/go/v1 (Zen/GO)
  • Client: Hermes Agent Desktop (Anthropic-compatible client)
  • Model: muse-spark-1.2-contributor via opencode-go (DeepSeek channel also affected, but repro here is Muse Spark)
  • Prompt: trivial short prompt, e.g. "测试新模型是否能正常对话,不用过多的回复" / "test if model can talk normally, short reply only"
  • Expected: content_block_stop + message_stop with stop_reason: "end_turn" and stream ends cleanly.
  • Actual: content arrives correctly ("正常,能对话" / single short sentence), but stream ends without proper stop_reason. Client interprets as network truncation.

Observed behavior

Hermes injects system message:

[System: The previous response was cut off by a network error mid-stream. Continue exactly where you left off. Do not restart or repeat prior text. Finish the answer directly.]

Model then emits a duplicate/continuation (e.g. "✓", "正常", then repeated system injections), visible as "乱七八糟东西" to user. Turning off Hermes retry still leaves the stream technically incomplete per Anthropic spec.

Longer replies are less likely to trigger this; short 1-2 token replies reproduce reliably (3/3 in session).

Hypothesis

Zen gateway translates OpenAI streaming (choices[0].finish_reason + data: [DONE]) to Anthropic SSE (message_delta with stop_reason, message_stop). For very short completions the final delta is dropped or stop_reason is null, so message_stop never fires.

Expected fix

Ensure for every OpenAI stream termination (including finish_reason: "stop" on short content), the gateway always emits:

event: message_delta
data: {"delta":{"stop_reason":"end_turn","stop_sequence":null}, ...}
event: message_stop

even when content is 1-2 tokens.

Evidence

  • Gateway base_url: https://opencode.ai/zen/go/v1 with User-Agent: OpenCode/1.0
  • Token: opencode-go subscription ($10/mo, Zen)
  • Client logs show Hermes adding the continuation prompt only after GO stream ends without stop signal (not a client network drop).
  • Same model via native OpenAI endpoint does not exhibit this (only via Anthropic-compat translation).

Impact

Any Anthropic-compat client (Hermes, Claude Code, OpenCode) using Zen/GO will see occasional duplicate/garbled output on short replies. Looks like "GO bug + Hermes over-eager retry" but primary fix is in gateway translation.

Happy to provide a minimal SSE dump if needed.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.