Repository navigation
Conversation
The thought ends at the first </mm:think> and later thinking tags are content, so a reply streams the same whole or split by character. Fixes #1905
… forced-open thought
This was referenced Nov 10, 2026
leehack
added a commit
that referenced
this pull request
Nov 10, 2026
Contributor
|
Chat app preview removed for |
This was referenced Nov 10, 2026
2 of 3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
cd959bae9) does: the thought is the text before the first</mm:think>, kept as generated, and every later<mm:think>or</mm:think>is content. Replaces the generic multi-block extraction inMinimaxM3HandlerwithextractForcedOpenThoughtVerbatimand setskeepsForcedThoughtVerbatimon the format, so the stream ends the thought at its first end tag.</mm:think><mm:think>+ call lost its<mm:think>content in a 2-chunk stream, because the final tool-envelope check read the content's<mm:think>as an unended thought. For verbatim forced-open formats that check now decides from the text after the first end tag.</mm:thinkas content. The two disagreed by chunking and both differed from llama.cpp.Closes #1905.
Production-readiness scope
thinking_mode: enabled) with repeated or stray<mm:think>/</mm:think>parse and stream identically, matching llama.cpp, with any tool choice.Completeness checklist
PR type guidance
Test Plan
dart run tool/prepare_workspace.dartdart format --output=none --set-exit-if-changed .dart analyzedart test -p vm -j 1 --exclude-tags local-only(locally:test/unit/coreand the touched integration test; full suite left to CI at the head)dart test -p chromeontest/unit/core/engineandtest/unit/core/templatecoverage-libmatrix row (not run locally: the change is ~10 lines, all exercised by the new tests;mainenforces the threshold)dart run tool/testing/check_platform_boundaries.dart; mutation check belowMatrix Evidence
test/unit/core, new integration testtest/unit/core/engine,test/unit/core/template, touched stream test@TestOn('vm'); inline oracle shapes run on Chrome inminimax_thinking_stream_test.dartcd959bae9oracle) on the vendoredMiniMax-M3.jinja; no MiniMax M3 weightstest/fixtures/minimax_m3_forced_open_upstream.json(now with end-then-start-then-call rows and partialx<mm:throws)Review Notes
High-risk regression review
structuredOutput)keepsForcedThoughtVerbatimtrait (3 failures), reverting the handler toextractThinking(30 failures), ignoringisPartialin the handler (2 failures), passing the suffix-hiddenthinkingInputto the handler (fails on the new partial rows), ignoringthinkingTagsAreContentin the final envelope check (failsend-then-start-then-callsplit rows). Surviving equivalent variant:lastIndexOfinstead ofindexOffor the end tag passes on the recorded rowscd959bae9probe on the vendored template plus durable fixtures