Bug Description
When using models that do not have web search capability (e.g. glm-think), internal citation markers like 【turn3fetch0】, 【turn3fetch1】 appear literally in the final response text returned to the client.
Root Cause
In src/chat.ts, the citation marker replacement logic has two issues:
Issue 1 — guard condition blocks replacement when no search results exist:
if (searchMap.size > 0) {
txt = txt.replace(/【?(turn\d+[a-zA-Z]+\d+)】?/g, ...)
}
For models without search (no tool_result parts), searchMap is always empty, so this block is never entered and markers are left as-is.
Issue 2 — fallback returns the original marker instead of removing it:
const searchInfo = searchMap.get(key);
if (!searchInfo) return match; // ← returns 【turnXfetchY】 unchanged
Even when the map has entries, if a specific key is missing the marker survives.
This bug exists in both the non-streaming path (around the receiveStream function) and the streaming path.
Expected Behavior
【turnXfetchY】-style markers are internal ChatGLM citation references and should never appear in the output delivered to clients. They should either:
- Be converted to
[N](url) when the corresponding search result is available, or
- Be silently removed when no match is found.
Suggested Fix
// Remove the searchMap.size guard — always run replacement
txt = txt.replace(/【?(turn\d+[a-zA-Z]+\d+)】?/g, (match: string, key: string) => {
const searchInfo = searchMap.get(key);
if (!searchInfo) return ""; // strip unresolved markers instead of keeping them
if (!keyToIdMap.has(key)) keyToIdMap.set(key, counter++);
const newId = keyToIdMap.get(key);
return ` [${newId}](${searchInfo.url})`;
});
This fix needs to be applied in both the streaming and non-streaming paths in src/chat.ts.
Environment
- Affected models:
glm-think (and likely any model without web search)
- Both streaming and non-streaming responses affected
Bug Description
When using models that do not have web search capability (e.g.
glm-think), internal citation markers like【turn3fetch0】,【turn3fetch1】appear literally in the final response text returned to the client.Root Cause
In
src/chat.ts, the citation marker replacement logic has two issues:Issue 1 — guard condition blocks replacement when no search results exist:
For models without search (no
tool_resultparts),searchMapis always empty, so this block is never entered and markers are left as-is.Issue 2 — fallback returns the original marker instead of removing it:
Even when the map has entries, if a specific key is missing the marker survives.
This bug exists in both the non-streaming path (around the
receiveStreamfunction) and the streaming path.Expected Behavior
【turnXfetchY】-style markers are internal ChatGLM citation references and should never appear in the output delivered to clients. They should either:[N](url)when the corresponding search result is available, orSuggested Fix
This fix needs to be applied in both the streaming and non-streaming paths in
src/chat.ts.Environment
glm-think(and likely any model without web search)