mirror of
https://github.com/CJackHwang/ds2api.git
synced 2026-05-15 21:55:09 +08:00
feat: implement code fence awareness in tool sieve to prevent false-positive XML tool detection inside code blocks and refine prompt instructions.
This commit is contained in:
@@ -42,8 +42,8 @@ function consumeXMLToolCapture(captured, toolNames, trimWrappingJSONFence) {
|
||||
suffix: trimmedFence.suffix,
|
||||
};
|
||||
}
|
||||
// XML tool syntax but failed to parse — consume to avoid leak.
|
||||
return { ready: true, prefix: prefixPart, calls: [], suffix: suffixPart };
|
||||
// If this block failed to become a tool call, pass it through as text.
|
||||
return { ready: true, prefix: prefixPart + xmlBlock, calls: [], suffix: suffixPart };
|
||||
}
|
||||
return { ready: false, prefix: '', calls: [], suffix: '' };
|
||||
}
|
||||
@@ -79,22 +79,8 @@ 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,
|
||||
};
|
||||
|
||||
@@ -12,7 +12,6 @@ const {
|
||||
consumeXMLToolCapture: consumeXMLToolCaptureImpl,
|
||||
hasOpenXMLToolTag,
|
||||
findPartialXMLToolTagStart,
|
||||
looksLikeXMLToolTagFragment,
|
||||
} = require('./sieve-xml');
|
||||
function processToolSieveChunk(state, chunk, toolNames) {
|
||||
if (!state) {
|
||||
@@ -77,7 +76,7 @@ function processToolSieveChunk(state, chunk, toolNames) {
|
||||
resetIncrementalToolState(state);
|
||||
continue;
|
||||
}
|
||||
const [safe, hold] = splitSafeContentForToolDetection(pending);
|
||||
const [safe, hold] = splitSafeContentForToolDetection(state, pending);
|
||||
if (!safe) {
|
||||
break;
|
||||
}
|
||||
@@ -114,26 +113,22 @@ function flushToolSieve(state, toolNames) {
|
||||
}
|
||||
} else if (state.capture) {
|
||||
const content = state.capture;
|
||||
if (!hasOpenXMLToolTag(content) && !looksLikeXMLToolTagFragment(content)) {
|
||||
noteText(state, content);
|
||||
events.push({ type: 'text', text: content });
|
||||
}
|
||||
noteText(state, content);
|
||||
events.push({ type: 'text', text: content });
|
||||
}
|
||||
state.capture = '';
|
||||
state.capturing = false;
|
||||
resetIncrementalToolState(state);
|
||||
}
|
||||
if (state.pending) {
|
||||
if (!hasOpenXMLToolTag(state.pending) && !looksLikeXMLToolTagFragment(state.pending)) {
|
||||
noteText(state, state.pending);
|
||||
events.push({ type: 'text', text: state.pending });
|
||||
}
|
||||
noteText(state, state.pending);
|
||||
events.push({ type: 'text', text: state.pending });
|
||||
state.pending = '';
|
||||
}
|
||||
return events;
|
||||
}
|
||||
|
||||
function splitSafeContentForToolDetection(s) {
|
||||
function splitSafeContentForToolDetection(state, s) {
|
||||
const text = s || '';
|
||||
if (!text) {
|
||||
return ['', ''];
|
||||
@@ -141,6 +136,9 @@ function splitSafeContentForToolDetection(s) {
|
||||
// Only hold back partial XML tool tags.
|
||||
const xmlIdx = findPartialXMLToolTagStart(text);
|
||||
if (xmlIdx >= 0) {
|
||||
if (insideCodeFenceWithState(state, text.slice(0, xmlIdx))) {
|
||||
return [text, ''];
|
||||
}
|
||||
if (xmlIdx > 0) {
|
||||
return [text.slice(0, xmlIdx), text.slice(xmlIdx)];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user