Skip to content

fix(streaming): prevent text truncation before tool calls in think filter and extractors - #256

Merged
ltmoerdani merged 1 commit into
ltmoerdani:mainfrom
NeoMetric:agents/fix-text-truncation-tool-calls
Oct 13, 2026
Merged

ltmoerdani merged 1 commit into
ltmoerdani:mainfrom
NeoMetric:agents/fix-text-truncation-tool-calls

Conversation

@NeoMetric

Copy link
Copy Markdown
Contributor

📝 What does this change?

Prevents text preceding tool calls from being truncated by 8 characters during streaming with reasoning models (e.g. MiniMax Mimo, DeepSeek). ThinkTagFilter now only buffers tail characters if they match an opening or closing think tag prefix, and both OpenAI and Anthropic response extractors flush any pending think filter carry as visible text before emitting tool calls.

🧪 How did you test it?

  • Added unit tests in src/test/thinkTags.test.ts covering ordinary text preservation, partial tag boundary detection, and unclosed tag flushes.
  • Added tests in src/test/extractors.test.ts verifying think tag carry is flushed as visible text prior to tool calls in both OpenAI and Anthropic extractors.
  • Ran npm run lint — all 7 checks passed (Editorconfig, ESLint, Markdown, Prettier, Shellcheck, TypeScript, Tests).

✅ Checklist

  • npm run compile passes
  • npm run lint passes
  • npm test passes
  • npm run package produces a VSIX
  • I tested it works
  • I updated docs/CHANGELOG if needed

@ltmoerdani

Copy link
Copy Markdown
Owner

Hi @NeoMetric, thanks for this. I pulled the branch and ran the full unit test suite locally (512 pass, 0 fail), and I also traced the fix against our past work on think tags and tool call flushing (issues #42, #50, #72 in docs/issues). The root cause analysis checks out: the unconditional 8-char tail buffer in ThinkTagFilter and the missing finish() flush before tool calls were both real, and the fix addresses both without breaking the earlier flush behavior. Test coverage you added is solid too, especially the 5 < 10 comparison case.

Two small things before we can merge:

  1. CHANGELOG conflict: the branch conflicts with main on CHANGELOG.md (we've landed a couple of PRs since, so there's already an [Unreleased] section there). Trivial to resolve, just merge both sets of entries.

  2. Doc numbering: docs/issues/109-20261013-streaming-text-truncation-tool-calls.md collides with the existing 109-20261004-issue252-generic-reasoning-effort.md on main. Could you rename yours to 110-20261013-...? The sequence number needs to stay unique (it's also self-referenced in the CHANGELOG entry and inside the doc itself).

One really minor thing, not blocking: the counts in the ARCHITECTURE-MAP test table ("38 files, 497 cases") are slightly off from what I'm seeing locally, so feel free to bump those while you're in there.

Nice catch on this one by the way, the "exactly 8 characters" symptom was a fun one to trace. Once the two items above are in, this is good to merge.

…lter and extractors

Avoid unconditional 8-character tail buffering in ThinkTagFilter by only buffering when the chunk tail starts with an opening or closing think tag prefix. Flush think filter carry prior to emitting tool calls in both OpenAI and Anthropic extractors so text preceding tool calls is not delayed or split across widget cards.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@NeoMetric
NeoMetric force-pushed the agents/fix-text-truncation-tool-calls branch from dfee685 to fef3a59 Compare October 13, 2026 08:40
@ltmoerdani
ltmoerdani merged commit 278b3df into ltmoerdani:main Oct 13, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants