Bug: file_write 内容提取逻辑存在 3 个 Bug + 1 个设计缺陷
背景
file_write 工具通过解析 LLM 回复中的 <file_content> 标签或代码块来获取写入内容。当写入包含代码块的大文件时,内容提取会失败,导致文件写入为空。
Bug 1: 贪婪正则匹配(ga.py)
文件: ga.py — extract_robust_content()
tag = re.search(r"<file_content[^>]*>(.*)</file_content>", text, re.DOTALL)
(.*) 贪婪匹配会匹配到最后一个 </file_content>,如果回复中有多组标签或内容中包含 </file_content> 字面量,会吞掉中间内容。
修复: 改为 (.*?) 非贪婪匹配。
Bug 2: triple-backtick 回退逻辑完全错误(ga.py)
s, e = text.find("```"), text.rfind("```")
if -1 < s < e: return text[text.find("\n", s)+1 : e].strip()
当文章本身包含代码块时(例如技术文章),find("```") 取第一个 ,`rfind("")` 取最后一个 ```,截取的范围是从文章开头的标记到末尾的标记,完全不是期望的文件内容。
Bug 3: _clean_content 静默删除 <file_content> 显示(agent_loop.py)
for p in [r'<file_content>[\s\S]*?</file_content>', ...]:
text = re.sub(p, '', text)
<file_content> 标签在显示时被完全移除,调试时无法确认模型是否写对了内容。
Bug 4: Schema 缺少 content 参数(tools_schema.json)
file_write 的 JSON schema 只有 path 和 mode 两个参数,没有 content。所有写入内容完全依赖 response.content 的文本解析,一旦解析失败就没有任何兜底。
建议修复
ga.py: 重写 extract_robust_content,优先 args.content,其次 <file_content> 非贪婪匹配,最后只取最后一个代码块
tools_schema.json: 给 file_write 增加可选 content 字段
agent_loop.py: _clean_content 改为占位符替代而非完全删除 <file_content>
已在实际环境中复现并验证修复方案(3 文件 12 行修改),可提供补丁。
Bug:
file_write内容提取逻辑存在 3 个 Bug + 1 个设计缺陷背景
file_write工具通过解析 LLM 回复中的<file_content>标签或代码块来获取写入内容。当写入包含代码块的大文件时,内容提取会失败,导致文件写入为空。Bug 1: 贪婪正则匹配(ga.py)
文件:
ga.py—extract_robust_content()(.*)贪婪匹配会匹配到最后一个</file_content>,如果回复中有多组标签或内容中包含</file_content>字面量,会吞掉中间内容。修复: 改为
(.*?)非贪婪匹配。Bug 2: triple-backtick 回退逻辑完全错误(ga.py)
当文章本身包含代码块时(例如技术文章),
find("```")取第一个,`rfind("")` 取最后一个 ```,截取的范围是从文章开头的标记到末尾的标记,完全不是期望的文件内容。Bug 3:
_clean_content静默删除<file_content>显示(agent_loop.py)<file_content>标签在显示时被完全移除,调试时无法确认模型是否写对了内容。Bug 4: Schema 缺少
content参数(tools_schema.json)file_write的 JSON schema 只有path和mode两个参数,没有content。所有写入内容完全依赖response.content的文本解析,一旦解析失败就没有任何兜底。建议修复
ga.py: 重写extract_robust_content,优先args.content,其次<file_content>非贪婪匹配,最后只取最后一个代码块tools_schema.json: 给file_write增加可选content字段agent_loop.py:_clean_content改为占位符替代而非完全删除<file_content>已在实际环境中复现并验证修复方案(3 文件 12 行修改),可提供补丁。