Describe the bug
Some models (e.g., zhipu/glm via OpenAI-compatible API) emit a separate reasoning-start → reasoning-delta → reasoning-end cycle for every single token during thinking/reasoning output. This causes the TUI to render each token as an independent Thinking: line:
Thinking: The
Thinking: user
Thinking: said
Thinking: hello
Instead of the expected continuous paragraph:
Thinking: The user said hello
Root cause
In processor.ts, each reasoning-start event creates a new reasoning Part with a unique partID. Models like DeepSeek emit one start, many deltas, and one end — so one part is created. But models like zhipu/glm wrap each token in its own start/delta/end cycle, creating a new part per token.
The TUI's <code streaming={true}> component appends new content as a new line on each reactive update. Since each token creates a separate part (and thus a separate ReasoningPart component instance), each token renders on its own line.
Steps to reproduce
- Configure an OpenAI-compatible provider with a model that has per-token reasoning events (e.g., zhipu/glm-5 via gateway)
- Send any message that triggers thinking/reasoning
- Observe each thinking token displayed on a separate line with
Thinking: prefix
Expected behavior
Thinking content should render as a continuous paragraph, regardless of how the model streams reasoning events.
Environment
- OS: Windows 11
- OpenCode: dev branch
- Model: zhipu/glm-5 via Mify gateway (OpenAI-compatible format)
Describe the bug
Some models (e.g., zhipu/glm via OpenAI-compatible API) emit a separate
reasoning-start→reasoning-delta→reasoning-endcycle for every single token during thinking/reasoning output. This causes the TUI to render each token as an independentThinking:line:Instead of the expected continuous paragraph:
Root cause
In
processor.ts, eachreasoning-startevent creates a new reasoningPartwith a uniquepartID. Models like DeepSeek emit one start, many deltas, and one end — so one part is created. But models like zhipu/glm wrap each token in its own start/delta/end cycle, creating a new part per token.The TUI's
<code streaming={true}>component appends new content as a new line on each reactive update. Since each token creates a separate part (and thus a separateReasoningPartcomponent instance), each token renders on its own line.Steps to reproduce
Thinking:prefixExpected behavior
Thinking content should render as a continuous paragraph, regardless of how the model streams reasoning events.
Environment