Skip to content

fix: render think tags as reasoning blocks + fix MCP MaxListeners overflow#21873

Closed
saurav-shakya wants to merge 1 commit intoanomalyco:devfrom
saurav-shakya:fix/issue-16903-glm5-temperature
Closed

fix: render think tags as reasoning blocks + fix MCP MaxListeners overflow#21873
saurav-shakya wants to merge 1 commit intoanomalyco:devfrom
saurav-shakya:fix/issue-16903-glm5-temperature

Conversation

@saurav-shakya
Copy link
Copy Markdown

@saurav-shakya saurav-shakya commented Apr 10, 2026

Issue for this PR

Closes #16903

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

GLM-5 model pollutes context window with broken thinking output. Raw <think> tags leak into the UI as garbled ? characters, breaking TUI layout and status indicators.

Think-tag fix:

  • Added splitThinkBlocks() / stripThinkTags() utilities in packages/util/src/think.ts and packages/opencode/src/util/format.ts
  • TUI TextPart now extracts reasoning and renders it as a dimmed/bordered block (only when thinking display is enabled)
  • Web UI TextPartDisplay renders extracted reasoning in a reasoning-part div
  • CLI run.ts strips think tags from output; shows reasoning with --thinking flag
  • GLM-5 temperature set to 1.0 for stability

MCP MaxListeners fix (related):

  • With 7+ local MCP servers, the default EventEmitter limit of 10 is easily exceeded
  • Dynamically calculates the needed limit from the local MCP server count and raises EventEmitter.defaultMaxListeners + per-stream limits before connecting

How did you verify your code works?

Tested locally with GLM-5 model. Verified <think> tags no longer leak into TUI/web rendered output and reasoning blocks display correctly. MCP fix verified with multiple local MCP servers — no more MaxListeners warnings.

Screenshots / recordings

N/A — TUI text rendering change; reasoning blocks render with dim/italic styling behind a left border.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

…rflow

Two fixes in this commit:

### 1. Render <think> tags as reasoning blocks at display layer

Models like GLM-5 embed reasoning in raw <think>...</think> tags within text parts.
Previously these were displayed as raw HTML to the user.

**Approach:** Parse and render <think> / <thinking> tags at the display layer (TUI, Web UI, CLI)
rather than stripping them from the message storage. This preserves the full model output for
multi-turn context while giving users clean, styled reasoning blocks.

**Changes:**
- packages/util/src/think.ts -- Shared utility: stripThinkTags(), splitThinkBlocks() with regex matching both <think> and <thinking> variants
- packages/opencode/src/util/format.ts -- Same utilities for the core package
- packages/opencode/src/cli/cmd/tui/routes/session/index.tsx -- TextPart renders think blocks with dim/italic/bordered styling matching ReasoningPart
- packages/ui/src/components/message-part.tsx -- TextPartDisplay renders think blocks in <div data-component="reasoning-part">
- packages/opencode/src/cli/cmd/run.ts -- CLI strips think tags from output, shows reasoning with --thinking flag

### 2. Fix MCP MaxListeners overflow with many servers

When 7+ stdio-based MCP servers are configured, the default Node.js EventEmitter limit of ~10 is exceeded.
Each StdioClientTransport spawns a child process and adds listeners to its stdin/stdout/stderr pipes.
The MCP protocol layer also sends many concurrent requests (getPrompt, listTools, etc.) that each add a 'drain' listener.

**Fix:** Dynamically calculate the needed listener limit based on the number of configured local MCP servers
and increase both EventEmitter.defaultMaxListeners and process stream limits before connecting.

**Changes:**
- packages/opencode/src/mcp/index.ts -- Count local MCP servers, set EventEmitter.defaultMaxListeners and process stream limits proportionally

## Related Issues
- Fixes anomalyco#16903 (GLM-5 thinking output pollution)
- Fixes anomalyco#11439 (think tag rendering regression from removal of extractReasoningMiddleware)
- Related: anomalyco#4033, anomalyco#7779
@github-actions github-actions bot added the needs:compliance This means the issue will auto-close after 2 hours. label Apr 10, 2026
@github-actions
Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

Potential duplicate found:

This PR appears to address the same two fixes: rendering <think> tags as reasoning blocks and handling MCP MaxListeners issues. The title and scope match PR #21873 closely. You should check whether #15389 is still open and if it has already been merged or if these represent duplicate efforts.

@github-actions github-actions bot removed the needs:compliance This means the issue will auto-close after 2 hours. label Apr 10, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Thanks for updating your PR! It now meets our contributing guidelines. 👍

Copy link
Copy Markdown
Author

Closing as duplicate of #15389 which implements the same think tag rendering and MCP MaxListeners fixes. Please update #15389 to also close #16903 (GLM-5 issue).

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.

[BUG] GLM-5 model pollutes context window with broken thinking output

1 participant