From 4e158e87831aa43a881dada8f2dee8ca2b37300e Mon Sep 17 00:00:00 2001 From: thzxx Date: Sat, 18 Apr 2026 08:21:08 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=96=87=E6=9C=AC?= =?UTF-8?q?=E8=A7=A3=E6=9E=90=E5=85=9C=E5=BA=95=E6=AD=A3=E5=88=99=E4=B8=8D?= =?UTF-8?q?=E5=8C=B9=E9=85=8D=E6=A8=A1=E5=9E=8B=E5=AE=9E=E9=99=85=E8=BE=93?= =?UTF-8?q?=E5=87=BA=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 模型实际输出格式: Action: write_file Action Input: {"path": "测试.md", "content": ""} 原正则用 [\r\n]+ 强制要求换行,且 Action: 后的冒号和 Action Input: 的冒号处理冲突导致匹配失败。 改为 [\r\n\s]* 灵活匹配空白/换行。 --- src/renderer/services/agent-engine.ts | 29 +++++++-------------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/src/renderer/services/agent-engine.ts b/src/renderer/services/agent-engine.ts index 4cfdb33..c37102f 100644 --- a/src/renderer/services/agent-engine.ts +++ b/src/renderer/services/agent-engine.ts @@ -104,10 +104,13 @@ const VALID_TOOL_NAMES = new Set([ function parseToolCallsFromText(content: string): ToolCall[] { const calls: ToolCall[] = []; - // 匹配模式1: **Action:** tool_name **Action Input:** {json} - // 匹配模式2: Action: tool_name Action Input: {json} - // 同时支持 Action 和 Action Input 写在同一段或多行 - const actionRegex = /\*?\*?Action:?\*?\*?\s*([\w]+)\s*[\r\n]+\s*\*?\*?Action\s*Input:?\*?\*?\s*(\{[\s\S]*?\})/gi; + // 匹配:Action: tool_name(可选加粗标记) + // 然后紧跟 Action Input: {json} + // 支持格式: + // Action: write_file Action: write_file + // Action Input: {...} **Action Input:** {...} + // 也支持写在同一段落的情况 + const actionRegex = /\*{0,2}Action:?\*{0,2}\s*(\w+)\s+[\r\n\s]*\*{0,2}Action\s*Input:?\*{0,2}\s*(\{[\s\S]*?\})/gi; let match; while ((match = actionRegex.exec(content)) !== null) { @@ -127,7 +130,6 @@ function parseToolCallsFromText(content: string): ToolCall[] { } catch { // JSON 解析失败,尝试修复常见问题 try { - // 处理单引号、尾逗号等 let fixed = argsStr .replace(/'/g, '"') .replace(/,\s*}/g, '}') @@ -146,23 +148,6 @@ function parseToolCallsFromText(content: string): ToolCall[] { } } - // 备选模式:Action 和 Action Input 写在一行或用不同分隔 - if (calls.length === 0) { - const singleLineRegex = /Action:\s*(\w+)\s*.*?Action\s*Input:\s*(\{[^}]+\})/gi; - while ((match = singleLineRegex.exec(content)) !== null) { - const toolName = match[1].trim(); - const argsStr = match[2].trim(); - if (!VALID_TOOL_NAMES.has(toolName)) continue; - try { - const args = JSON.parse(argsStr); - calls.push({ - type: 'function', - function: { name: toolName, arguments: args } - }); - } catch { /* skip */ } - } - } - if (calls.length > 0) { logInfo(`文本解析兜底: 从回复中提取到 ${calls.length} 个工具调用`, calls.map(c => c.function.name).join(', ')); }