fix: strip all reasoning blocks in removeReasoningContent, not just the first - #243
fix: strip all reasoning blocks in removeReasoningContent, not just the first#243Ayush7614 wants to merge 1 commit into
Conversation
…he first removeReasoningContent only removed the first complete thinking… response block and ignored unterminated blocks. A model can emit several reasoning spans across one turn, and a stream cut off mid-reasoning leaves an unterminated block — both cases leaked reasoning into the token count and, potentially, the prompt sent to the model. Now: - strips every complete thinking… response block (global replace) - strips a trailing unterminated thinking block - applies the same treatment to the DeepSeek <|channel|>analysis…final format Adds a test suite covering single/multiple/unterminated blocks for both formats, plus extractReasoningFromMessage edge cases.
|
Thanks @Ayush7614 — the core observation is correct, and the regex-with- Verified on your branch merged onto current
Three things, none of them large. 1. The framing needs correcting — and it's good news
It feeds the token-count estimate behind the context-usage indicator. It is not on the path that builds the outbound request. So the PR description ("doesn't leak into the prompt") and the function's own comment ("Reasoning content should not be sent to the model") both overstate what this code does — the comment has been stale for a while, and your PR is a good moment to fix it. That's worth getting right in the description because it also lowers the stakes on point 3 below: the worst case is a slightly-off token estimate, not lost or leaked content. 2. An undocumented improvement worth claimingThe old code did Your 3. The catch-all is greedyresult = result.replace(/<think>[\s\S]*$/, '')If a user pastes a snippet that contains a literal Nits
Fix the description and the stale comment, run Prettier, and this is ready. Thanks for the tests — the unterminated-block cases are the ones I'd have forgotten 🧠 Generated by Claude Code |
What
removeReasoningContent(used byuseTokensCountto compute what gets sent to the model) only removed the first completethinking… responseblock and completely ignored unterminated blocks:thinking…block with no closing tag — it was never removed at all.Both cases meant reasoning content leaked into the token count and, potentially, into the prompt sent to the model.
Fix
thinking… responseblock (global replace) instead of the first match.thinking…block.<|channel|>analysis<|message|>…<|start|>assistant<|channel|>final<|message|>format.Verification
web-app/src/utils/__tests__/reasoning.test.ts, 12 tests) covering single / multiple / unterminated blocks for both formats plusextractReasoningFromMessageedge cases.tsc -bclean,eslint0 errors, fullutilssuite 67/67 pass.