Skip to content

Commit b18ff1c

Browse files
committed
更新 parse-xml-tool-calls.js 和 streaming.js 文件
1 parent 49621d4 commit b18ff1c

3 files changed

Lines changed: 44 additions & 4 deletions

File tree

src/parse-xml-tool-calls.js

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,35 @@ function hasFunctionCallOpenTag(text) {
3030
if (typeof text !== 'string') return false;
3131
return /<function_calls\s*>/i.test(text)
3232
|| /\[function_calls\]/i.test(text)
33-
|| /\[tool_calls\]\s*$/m.test(text);
33+
|| /\[tool_calls\]\s*$/m.test(text)
34+
|| /<([a-z_][a-z0-9_-]*)\b[^<>]*question\s*=/i.test(text);
35+
}
36+
37+
function hasStandaloneToolCallTags(text) {
38+
if (typeof text !== 'string') return false;
39+
return /<([a-z_][a-z0-9_-]*)\b[^<>]*\/>\s*$/i.test(text)
40+
|| /<([a-z_][a-z0-9_-]*)\b[^<>]*>[^<]*<\/\1>/i.test(text);
41+
}
42+
43+
function extractStandaloneToolCallTags(text) {
44+
if (typeof text !== 'string') return [];
45+
46+
const toolCalls = [];
47+
const selfClosingRegex = /<([a-z_][a-z0-9_-]*)\b([^>]*)\/>/gi;
48+
let match;
49+
50+
while ((match = selfClosingRegex.exec(text)) !== null) {
51+
const tagName = match[1].trim();
52+
const attrsText = match[2] || '';
53+
54+
if (shouldSkipContainerTag(tagName)) continue;
55+
if (!/(?:question|command|path|file_path|content|url|query|text|follow_up)\s*=/i.test(attrsText)) continue;
56+
57+
const argumentsParsed = parseXmlAttributes(attrsText);
58+
toolCalls.push(buildToolCall(toolCalls.length, tagName, argumentsParsed));
59+
}
60+
61+
return toolCalls;
3462
}
3563

3664
// 从文本中提取所有 function_calls / tool_calls 块
@@ -506,6 +534,8 @@ function extractTextToolCallField(block, fieldName) {
506534
module.exports = {
507535
hasFunctionCalls,
508536
hasFunctionCallOpenTag,
537+
hasStandaloneToolCallTags,
538+
extractStandaloneToolCallTags,
509539
extractFunctionCallsBlocks,
510540
parseFunctionCallsBlock,
511541
parseXmlToolCallsFromText,

src/streaming.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const crypto = require('crypto');
22
const { normalizeError, createHttpError } = require('./errors');
33
const { normalizeUsage, sanitizeAssistantContent } = require('./helpers');
4-
const { hasFunctionCallOpenTag, stripXmlToolCalls } = require('./parse-xml-tool-calls');
4+
const { hasFunctionCallOpenTag, hasStandaloneToolCallTags, stripXmlToolCalls } = require('./parse-xml-tool-calls');
55

66
function writeSseEvent(response, payload) {
77
response.write(`data: ${payload}\n\n`);
@@ -60,7 +60,7 @@ function emitContentDelta(response, streamState, delta) {
6060
streamState.accumulatedContent += delta;
6161
streamState.contentBuffer += delta;
6262

63-
if (!streamState.inToolCallMode && hasFunctionCallOpenTag(streamState.accumulatedContent)) {
63+
if (!streamState.inToolCallMode && (hasFunctionCallOpenTag(streamState.accumulatedContent) || hasStandaloneToolCallTags(streamState.accumulatedContent))) {
6464
streamState.inToolCallMode = true;
6565
streamState.contentBuffer = '';
6666
return;

src/tool-calls.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ const {
55
stripXmlToolCalls,
66
hasJsonToolCall,
77
parseJsonToolCallsFromText,
8-
parseTextToolCalls
8+
parseTextToolCalls,
9+
hasStandaloneToolCallTags,
10+
extractStandaloneToolCallTags
911
} = require('./parse-xml-tool-calls');
1012
const { normalizeUsage } = require('./helpers');
1113

@@ -22,6 +24,10 @@ function buildOpenAiResponse(model, content, events) {
2224
toolCalls = parseTextToolCalls(content);
2325
}
2426

27+
if (toolCalls.length === 0 && hasStandaloneToolCallTags(content)) {
28+
toolCalls = extractStandaloneToolCallTags(content);
29+
}
30+
2531
const cleanContent = stripXmlToolCalls(content);
2632

2733
const message = { role: 'assistant', content: cleanContent || '' };
@@ -64,6 +70,10 @@ function detectToolCalls(content) {
6470
toolCalls = parseTextToolCalls(content);
6571
}
6672

73+
if (toolCalls.length === 0 && hasStandaloneToolCallTags(content)) {
74+
toolCalls = extractStandaloneToolCallTags(content);
75+
}
76+
6777
if (!toolCalls.length) return null;
6878
return buildOpenAiToolCalls(toolCalls);
6979
}

0 commit comments

Comments
 (0)