feat: suppress output of partial XML tool tag fragments in stream processing

This commit is contained in:
CJACK
2026-03-29 14:59:30 +08:00
parent 4b42fe9086
commit 3ab9d44f60
4 changed files with 51 additions and 4 deletions

View File

@@ -79,8 +79,22 @@ function findPartialXMLToolTagStart(s) {
return -1;
}
function looksLikeXMLToolTagFragment(s) {
const trimmed = (s || '').trim();
if (!trimmed) return false;
const lower = trimmed.toLowerCase();
const fragments = [
'tool_calls>', 'tool_call>', '/tool_calls>', '/tool_call>',
'function_calls>', 'function_call>', '/function_calls>', '/function_call>',
'invoke>', '/invoke>', 'tool_use>', '/tool_use>',
'tool_name>', '/tool_name>', 'parameters>', '/parameters>',
];
return fragments.some(f => lower.includes(f));
}
module.exports = {
consumeXMLToolCapture,
hasOpenXMLToolTag,
findPartialXMLToolTagStart,
looksLikeXMLToolTagFragment,
};

View File

@@ -15,6 +15,7 @@ const {
consumeXMLToolCapture: consumeXMLToolCaptureImpl,
hasOpenXMLToolTag,
findPartialXMLToolTagStart,
looksLikeXMLToolTagFragment,
} = require('./sieve-xml');
function processToolSieveChunk(state, chunk, toolNames) {
if (!state) {
@@ -123,8 +124,10 @@ function flushToolSieve(state, toolNames) {
resetIncrementalToolState(state);
}
if (state.pending) {
noteText(state, state.pending);
events.push({ type: 'text', text: state.pending });
if (!hasOpenXMLToolTag(state.pending) && !looksLikeXMLToolTagFragment(state.pending)) {
noteText(state, state.pending);
events.push({ type: 'text', text: state.pending });
}
state.pending = '';
}
return events;