Repository navigation
[BUG] Chat output truncation at 8KB - XML tool calls appear as raw text in chat #707
Description
A Note from the User
This is a message from me, a human user. I asked AI to handle the rest of the issue report.
I tried to patch the problems I encountered while using Zoo Code myself. The patches may be incomplete or may not work correctly. Please, the bug fix team, judge them directly. I hope Zoo Code continues to grow and mature.
Problem
When the model generates a response longer than 8,000 characters, tool call XML tags appear as raw text in the chat output instead of being parsed as tool calls. The 8KB guard in extension.js disables tool-call detection after the buffer exceeds 8,000 characters.
Context
- OS: Windows 11, PowerShell 5.1
- Zoo Code Version: v3.63.100188
- Model: mimo-v2.5-pro
- Trigger: Responses exceeding 8,000 characters
Reproduction Steps
- Ask the model a complex question requiring a long response (8,000+ characters)
- Model generates tool call XML within the response
- XML tags appear as raw text in the chat instead of being parsed as tool calls
Expected Result
Tool call XML should be parsed and executed, with only regular text displayed in chat.
Actual Result
Tool call XML tags appear as raw text in the chat. Here are actual examples from diagnostics:
Example 1: Truncated function tag displayed as text
function>
</invoke>
Example 2: Parameter tags with file paths displayed as text
<parameter=path>c:\\Users\\myuser\Projects\\MyProject
Example 3: Mixed text and XML fragments in a single content block
<parameter=path>C:\Users\developer\projects\\myownsettings
<parameter=timeout>180</parameter>
</function>
</invoke>
Root Cause
The bug is in extension.js line 5369, inside the case"text": branch of the stream consumer switch:
- Buffer accumulation:
D += q.textaccumulates all text chunks into a module-scoped variableDacross the entire stream lifetime. - 8KB hard cutoff:
if (D.length < 8e3 && __detect.test(D))- the XML tool-call detection logic is completely disabled whenDexceeds 8,000 characters. - Raw XML passthrough: Once
Dexceeds 8KB, the__detect.test(D)branch is skipped entirely. Subsequent text chunks containing XML markers are pushed directly intoassistantMessageContentas plain text. - Cross-chunk contamination: File paths like
1yt/Projects/ZooChatare fragments from parameter tags that leaked into chat text rendering.
Impact
| Aspect | Impact |
|---|---|
| User Visibility | Raw XML tags displayed in chat |
| UX Degradation | Sentence breaks, trailing text contamination |
| Reproduction Rate | 100% when model output exceeds 8KB |
| Affected Models | All XML-style tool-call models (mimo-v2.5-pro and others) |
Proposed Fix
Recommended: Remove 8KB guard + add buffer size cap
Remove the D.length < 8e3 guard and replace with a 64KB memory protection cap:
- Remove the 8000-character hard cutoff from the XML detection condition
- Add a 65536-byte (64KB) cap on the accumulation buffer
D - When
Dexceeds 64KB, reset it (existing memory protection behavior) - Keep the existing v7 tool-call extraction logic unchanged
Advantages: Enables tool-call detection at all response lengths. Memory protection handled by separate 64KB cap.
Activity
myk1yt commentedon Jun 24, 2026
[RESOLVED] Chat output truncation at 8KB + XML tool calls appear as raw text
Problem
When the model generates responses longer than 8,000 characters, XML tool call tags appear as raw text in the chat output instead of being parsed as tool calls. Additionally, the XML parser failed when trailing text followed a tool call close tag, causing
attempt_completionto fail silently.Root Cause 1: 8KB Hard Cutoff in XML Detection
In
extension.js, thecase"text":branch of the stream consumer had a hard cutoff that completely disabled XML tool-call detection when the buffer exceeded 8,000 characters.Original code:
When
Dexceeds 8,000 characters,__detect.test(D)is never evaluated. All subsequent XML markers are pushed directly intoassistantMessageContentas plain text.Fixed code:
The 8KB guard is removed. XML detection now runs at all response lengths. A 64KB memory protection cap prevents unbounded buffer growth.
Root Cause 2: Recursive Parser Rejects Trailing Text After Tool Call Close Tag
The XML parser used recursive backtracking to extract nested parameter tags. However, it demanded that the string ended immediately after
</tool_call>with zero trailing text. If the model output even a single newline after</tool_call>, the parser returnednull, causingattempt_completionand other tool calls to fail.Original parser logic (simplified):
Fixed parser logic (simplified):
The
__rem.length === 0constraint is removed. The parser returns success the moment</tool_call>is properly closed, regardless of what follows.Verification
attempt_completionwith trailing text: now works correctlyLimitation
extension.js; will be overwritten on extension updatesmyk1yt commentedon Jun 24, 2026
📍 Supplementary: Patch Location Details
The previous comment was missing the exact location in
extension.js. Here are the precise details for the bug fix team:Patch Location
File:
dist/extension.js(inside the Zoo Code extension directory)Byte offset: ~14,861,064 (inside the
case"text":branch of the streaming consumer)How to Locate Root Cause 1 (8KB Hard Cutoff)
Search for this exact string in
extension.js:This string appears exactly once and uniquely identifies the buggy 8KB guard.
How to Apply Fix 1
Replace the above string with:
What changed:
D.length<8e3guard removed — XML detection now runs at ALL response lengthsif(D.length>65536)D="";added — 64KB memory cap prevents unbounded buffer growthHow to Locate Root Cause 2 (Trailing Text Constraint)
Inside the
__parseRestfunction (also in thecase"text":handler), search for:How to Apply Fix 2
Replace the above block with:
The parser now succeeds the moment
</tool_call>is properly closed, regardless of what follows.