Repository navigation
Description
Summary
With the built-in opencode/big-pickle model, reasoning is intermittently persisted as an
ordinary text part instead of a reasoning part, and the literal closing thinking marker
</think> leaks into the visible assistant text. In 2.0.29/2.0.30 the marker appeared at
the start of the reply (</think>Готово…); 2.0.31 reduces that shape roughly 16x, but a
rarer variant remains where the whole thinking trace is stored as text ending in the marker.
Environment
- opencode version: 2.0.31 (the issue also reproduced on 2.0.29 and 2.0.30)
- OS: Windows 10 19045.6456 (10.0.19045)
- Terminal: VS Code integrated terminal (TERM_PROGRAM=vscode, TERM=xterm-256color, COLORTERM=truecolor)
- Shell: cmd.exe (C:\Windows\system32\cmd.exe)
- Install/channel: npm global
@opencode/cli, prefixD:\Programs\0.IA\npm-global - Active plugins: none found in config
Reproduction
- Select model
opencode/big-pickle. - Send a prompt that makes the model think and then call a tool, e.g.
вызови инструмент glob 12 раз последовательно, по одному вызову за шаг. - Inspect the stored assistant parts (
session_messageinopencode.db) or watch the
rendered reply.
The marker sometimes shows up as a separate leading text part and sometimes as part of the
assistant's final message, so the visible symptom is a stray </think> before the answer.
Expected Behavior
Reasoning should be stored in a reasoning part, and the thinking / </think> markers
should never appear in visible assistant text nor be replayed to the model as assistant
content.
Actual Behavior
A text part starts with, or contains, the literal marker </think>, and because it is
persisted as an ordinary text part it is also replayed into the next request as assistant
content.
Raw stored examples from 2.0.29 / 2.0.30 (marker at the start, immediately before the answer):
"</think>Готово.\n\n- `churnCount`: ..."
" responseГотово, можно проверять.\n\n- ..."
" responseГотово.\n\n- ..."
In that session 32 assistant messages were affected. Across the whole database: 191 of
12059 assistant messages, always with the same model (opencode/big-pickle), never with
other providers configured on the machine.
Additional Context
Measured on one machine with the same model, reading the session DB and counting assistant
messages that contain a tool call:
| opencode | assistant msgs with tool call | msgs whose text part starts with </think> |
|---|---|---|
| 2.0.29 | 661 | 105 (15.9%) |
| 2.0.30 | 165 | 29 (17.6%) |
| 2.0.31 | 88 | 1 (1.1%) |
So 2.0.31 largely removes the highly visible "marker before the answer" shape, but the
underlying "reasoning stored as text" problem is not fully gone. Residual 2.0.31 examples
(raw stored text parts):
"The glob tool isn't in the Code Mode catalog - only opencode tools are. ..."
"Try search({query:...}) or search({pattern:...}).</think>"
"</think>" (lone text part immediately before a tool call)
The leak is frequency-based, not deterministic: the same model and the same prompt produce
it only in a subset of tool-call turns (~18% before the upgrade, ~1% after).
Related: #34126 (standalone </think> before tool_calls persisted as assistant text) and
its fix PR #34698, which was closed without being merged; #43770 (reasoning inlined in
content leaks into text); #11439.
Note: in the v2.0.31 binary the literal marker strings are not present, while
reasoning_content / reasoningField / reasoningEnd are. Worth verifying that the
reasoning-to-tool boundary suppression actually ships in v2 builds (the v1 fix lived in
packages/llm/src/protocols/openai-chat.ts).
Workarounds tried
Upgrading 2.0.29 -> 2.0.31 reduces the visible marker-before-the-answer shape from ~16% to
~1% of tool-call messages, but does not eliminate the leak entirely. No configuration
workaround found.
Activity
opencode-agent commentedon Oct 16, 2026
Thanks for the detailed report and the per-version measurements, @glucmastersten-cpu.
I think this is a duplicate of #54599. In both,
opencode/big-picklesends its reasoning inline in the reply, ending in a literal</think>with no opening tag, and OpenCode saves it as a normaltextpart instead of areasoningpart. That issue has already been reproduced on v2, and #54612 proposes a fix. The fix splits the inline reasoning out where the stream is parsed (packages/ai/src/protocols/openai-chat.ts), turned on foropencode/big-pickle, and has not been merged yet. That fits what you saw: there are no marker strings in the 2.0.31 binary.Possible duplicates and related issues, ordered by likelihood:
</think>stored and shown as text. Already reproduced, with fix proposed in fix(core): split inline chain-of-thought into a reasoning part #54612.</think>or inline reasoning ending up in assistant text.Your numbers for 2.0.29 → 2.0.31 and the remaining 2.0.31 examples would be useful as a comment on #54599.
The bot will close this issue as a duplicate in 1 day unless you reply explaining how your problem is different.
opencode-agent commentedon Oct 17, 2026
Closing as a duplicate of #54599, since there was no reply saying how this differs. Both are about
opencode/big-picklesending its reasoning inline with a literal</think>, which OpenCode then saves as visible text. Please follow #54599 and the proposed fix in #54612. Your numbers for 2.0.29 → 2.0.31 and the remaining 2.0.31 examples would help there, so please add them as a comment on #54599. If your problem turns out to be different, reply here and we can reopen. Thanks, @glucmastersten-cpu!