Skip to content

fix(chat): preserve text around stray think-close after a complete block - #4191

Open
skyzhao1223 wants to merge 1 commit into
iOfficeAI:mainfrom
skyzhao1223:fix/think-tag-filter-preserve-content
Open

fix(chat): preserve text around stray think-close after a complete block#4191
skyzhao1223 wants to merge 1 commit into
iOfficeAI:mainfrom
skyzhao1223:fix/think-tag-filter-preserve-content

Conversation

@skyzhao1223

Copy link
Copy Markdown

Description

stripThinkTags (used by MessageText, autoTitle, getLastAssistantText and turnCopy to clean AI replies before rendering) had a destructive bug: its MiniMax step deleted everything up to the first orphaned closing think tag, even when the message contained a complete <thinking>…</thinking> block plus a stray trailing close.

Example: START <thinking>secret</thinking> MIDDLE </thinking> END was stripped to " END", silently losing the legitimate START and MIDDLE text from the rendered message. That combination (a balanced block followed by a leftover close tag from concatenated tool-call output) is exactly the case Step 4 was documented to handle by removing "just the tags".

This fix:

  1. Removes complete think/thinking blocks innermost-first in a loop, so nested blocks are fully consumed.
  2. Applies the aggressive MiniMax leading-content strip only when no complete block was present; otherwise the orphaned close is removed by Step 4 while surrounding content is preserved.

Related Issues

No existing issue tracked this; discovered during code review of thinkTagFilter.ts.

Type of Change

  • fix — Bug fix (non-breaking change which fixes an issue)
  • feat — New feature (non-breaking change which adds functionality)
  • perf — Performance improvement
  • refactor — Code restructuring (no behavior change)
  • Breaking change (fix or feature that would break existing functionality)
  • docs — Documentation update

Atomic PR Checklist (Rule 1)

  • This PR contains exactly one feature or bug fix that cannot be further decomposed
  • The PR title follows Conventional Commit format: <type>(<scope>): <subject> (English)

Local Checks (Rule 3)

  • bun run format — formatting passes
  • bun run lint — no lint errors (skip if no .ts/.tsx changed)
  • bunx tsc --noEmit — no type errors (skip if no .ts/.tsx changed)
  • bunx vitest run — tests pass
  • i18n validated (bun run i18n:types + node scripts/check-i18n.js) — only if src/renderer/, locales/, or src/common/config/i18n/ changed; N/A otherwise
  • New/changed user-facing text uses i18n keys (no hardcoded strings)

Runtime Verification

  • Verified on macOS
  • Verified on Windows
  • Verified on Linux
  • I have performed a self-review of my own code

Screenshots

N/A (pure string-processing change, covered by unit tests).

Additional Context

  • Regression tests added in tests/unit/renderer/utils/thinkTagFilter.test.ts for both the "complete block + stray close" and the standalone-orphan-close cases.
  • Verified the bug and the fix directly: the old implementation returned " END" for the input above, the new one returns "START MIDDLE END".
  • Note: bunx tsc --noEmit locally reports one pre-existing error (Cannot find module 'mermaid') that also occurs on a clean checkout of main — it is an environment/dependency issue unrelated to this change.

@skyzhao1223
skyzhao1223 requested a review from IceyLiu as a code owner August 30, 2026 06:15
@codecov

codecov Bot commented Aug 30, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

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.

1 participant