From 6e2ec390524d0aacefd48d552788892ccbf98726 Mon Sep 17 00:00:00 2001 From: Liang Jiaqing Date: Wed, 6 May 2026 10:30:08 +0800 Subject: [PATCH] file_write: support content arg in native mode, strip it in text-emulated mode --- assets/tools_schema.json | 3 ++- assets/tools_schema_cn.json | 3 ++- ga.py | 11 ++++++----- llmcore.py | 9 +++++++++ 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/assets/tools_schema.json b/assets/tools_schema.json index 7df7bec3..0ba8b0ef 100644 --- a/assets/tools_schema.json +++ b/assets/tools_schema.json @@ -29,9 +29,10 @@ }}, {"type": "function", "function": { "name": "file_write", - "description": "Create/overwrite/append files. HUGE edits ONLY. Content must in ... in reply body BEFORE the file_write call (not args). Supports {{file:path:startLine:endLine}}, auto-expanded", + "description": "Create/overwrite/append files. HUGE edits ONLY. Supports {{file:path:startLine:endLine}}, auto-expanded", "parameters": {"type": "object", "properties": { "path": {"type": "string", "description": "File path"}, + "content": {"type": "string"}, "mode": {"type": "string", "enum": ["overwrite", "append", "prepend"], "description": "Write mode", "default": "overwrite"}}} }}, {"type": "function", "function": { diff --git a/assets/tools_schema_cn.json b/assets/tools_schema_cn.json index 77e5eae6..17f14c3a 100644 --- a/assets/tools_schema_cn.json +++ b/assets/tools_schema_cn.json @@ -29,9 +29,10 @@ }}, {"type": "function", "function": { "name": "file_write", - "description": "用于文件的新建、全量覆盖或追加写入。对于精细的代码修改,应优先使用 file_patch。注意:要写入的内容必须放在回复正文的 标签或代码块中。写入内容支持 {{file:路径:起始行:结束行}} 语法引用文件片段,写入前自动展开", + "description": "用于文件的新建、全量覆盖或追加写入。对于精细的代码修改,应优先使用 file_patch。写入内容支持 {{file:路径:起始行:结束行}} 语法引用文件片段,写入前自动展开", "parameters": {"type": "object", "properties": { "path": {"type": "string", "description": "文件路径"}, + "content": {"type": "string"}, "mode": {"type": "string", "enum": ["overwrite", "append", "prepend"], "description": "写入模式覆盖、追加或在开头追加", "default": "overwrite"}}} }}, {"type": "function", "function": { diff --git a/ga.py b/ga.py index ca55ae66..124fb1bd 100644 --- a/ga.py +++ b/ga.py @@ -284,7 +284,8 @@ class GenericAgentHandler(BaseHandler): if not code: code = self._extract_code_block(response, code_type) if not code: return StepOutcome("[Error] Code missing. Must use reply code block or 'script' arg.", next_prompt="\n") - timeout = args.get("timeout", 60) + try: timeout = int(args.get("timeout", 60)) + except: timeout = 60 raw_path = os.path.join(self.cwd, args.get("cwd", './')) cwd = os.path.normpath(os.path.abspath(raw_path)) code_cwd = os.path.normpath(self.cwd) @@ -380,12 +381,12 @@ class GenericAgentHandler(BaseHandler): if blocks: return blocks[-1].strip() return None - blocks = extract_robust_content(response.content) - if not blocks: + content = args.get('content') or extract_robust_content(response.content) + if not content: yield f"[Status] ❌ 失败: 未在回复中找到代码块内容\n" - return StepOutcome({"status": "error", "msg": "No content found. Put content inside ... tags in your reply body before call file_write."}, next_prompt="\n") + return StepOutcome({"status": "error", "msg": "No content found. Blank is not supported. Put content inside ... tags in your reply body before call file_write."}, next_prompt="\n") try: - new_content = expand_file_refs(blocks, base_dir=self.cwd) + new_content = expand_file_refs(content, base_dir=self.cwd) if mode == "prepend": old = open(path, 'r', encoding="utf-8").read() if os.path.exists(path) else "" open(path, 'w', encoding="utf-8").write(new_content + old) diff --git a/llmcore.py b/llmcore.py index 8696c7b6..2952541c 100644 --- a/llmcore.py +++ b/llmcore.py @@ -736,6 +736,15 @@ class ToolClient: self.total_cd_tokens = 0 def chat(self, messages, tools=None): + tools = json.loads(json.dumps(tools, ensure_ascii=False)) if tools else tools + for t in tools or []: + f = t.get('function', {}) + if f.get('name') == 'file_write': + props = f.get('parameters', {}).get('properties', {}) + props.pop('content', None) + extra = '. Content must be placed in tags in reply body, not in args' + if extra not in f.get('description', ''): f['description'] = f.get('description', '') + extra + break full_prompt = self._build_protocol_prompt(messages, tools) print("Full prompt length:", len(full_prompt), 'chars') gen = self.backend.ask(full_prompt)