Agent Zero host-file-editing 技能指南:通过 text_editor_remote 安全读写 CLI 主机文件
【免费下载链接】agent-zeroAgent Zero AI framework项目地址: https://gitcode.com/GitHub_Trending/ag/agent-zero
Agent Zero 通过 A0 Connector 插件(plugin.yaml)把 Agent 的能力延伸到用户本机:当用户在 WebUI 中连接 A0 CLI 后,Agent 可以使用text_editor_remote工具直接读取、写入、修补运行 A0 CLI 的那台机器上的文件。本文基于 plugins/_a0_connector/skills/host-file-editing/SKILL.md 展开,系统梳理该技能的边界约束、读写访问模式、编辑流程、上下文补丁(patch_text)语法与失败处理策略,并结合工具源码与辅助模块说明其底层实现原理。读完本文,你将掌握如何在 Agent Zero 中安全、精准、可回退地完成"用户本机文件"的远程编辑,并理解为什么必须区分 CLI 主机文件与服务端(Docker)文件。
边界:哪些文件属于 CLI 主机
text_editor_remote只能用于A0 CLI 运行所在机器上的文件操作。Skill 文档明确指出:
Use
text_editor_remoteonly for file work on the machine where A0 CLI is running. These paths and files belong to the CLI host, not the Agent Zero server or Docker container.
也就是说,该工具面向的是"用户计算机 / 本地文件 / CLI 主机文件 / 明确不属于 Docker 或服务端的文件"。如果任务目标位于 Agent Zero 自身运行时(服务端工作目录或 Docker 容器)内部,则应改用常规的服务端文件工具,例如 helpers/files.py 提供的文件操作能力。
这一边界在工具提示词 agent.system.tool.text_editor_remote.md 中被进一步强调:
- 当用户请求的是"已连接本地机器 / A0 CLI 主机"上的文件,或明确表示不使用 Docker/服务端文件时,必须使用本工具,而不是服务端文件工具;
- 相对路径相对于 CLI 主机文件系统解析,不要将其改写为
/a0/usr/workdir—— 该路径属于 Agent Zero 服务端/Docker 侧。
在实现层面,工具通过 WebSocket 把操作指令转发给已连接的 CLI 客户端。从源码 tools/text_editor_remote.py 可以看到,每次操作都会生成唯一op_id,通过connector_file_op事件(FILE_OP_EVENT)投递给选中的 CLI socket,再以asyncio.wait_for等待FILE_OP_TIMEOUT = 30.0秒内的响应。换言之,文件本身始终留在 CLI 主机上,Agent Zero 服务端只负责"下发指令、回收结果",这正是边界约束的工程基础。
访问模式:Read&Write 与 Read only
Skill 定义了两种访问模式:
| 模式 | 能力 | 说明 |
|---|---|---|
| Read&Write | 读取、写入、修补 | 可以修改 CLI 主机文件,要求改动窄而刻意(narrow and intentional) |
| Read only | 仅检查 | 只允许读取;若写入被阻止,应告知用户按F3将本地文件访问切换为 Read&Write |
这两种模式在服务端有对应的元数据模型。查看 helpers/ws_runtime.py 中的RemoteFileMetadata:
enabled:该 CLI 是否开启远程文件访问;write_enabled:是否允许写入;mode:归一化为read_only或read_write。
而select_remote_file_target_sid(context_id, require_writes=...)在选择目标 CLI 时,会先过滤掉enabled=False的客户端;当require_writes=True(即write/patch操作)时,还会要求write_enabled=True。对应的错误提示也写死在工具源码 tools/text_editor_remote.py 中:
- 没有任何连接的 CLI 时:提示连接 A0 CLI 到当前 Agent Zero 实例;
- 有 CLI 但远程文件写入被阻止:提示"按 F3 将 CLI 切换为 Read&Write";
- 有 CLI 但未宣告远程文件访问能力:提示"当前没有 CLI 宣告远程文件访问"。
值得注意的错误消息原文是Press F3 to switch the CLI to Read&Write.,与 Skill 文档保持一致,说明F3是 CLI 侧切换访问模式的快捷键,服务端只负责按元数据放行。
编辑流程:read → patch → write 的优先级
Skill 对编辑流程给出明确的操作顺序建议:
- 先用
read检查文件:无论是查看内容,还是为基于行号的编辑做准备,都从read开始; write只在真正需要整文件替换或新建时使用;- 简单精确替换优先用
patch+old_text/new_text; - 上下文锚定编辑优先用
patch_text,尤其适合插入/删除之后行号可能漂移的场景; patch+edits仅用于基于最近一次远程读取的小范围行编辑;- 若基于新鲜度的行修补被判定为过期(stale)而拒绝,应重新读取文件并用更新后的行范围重试。
工具入口 tools/text_editor_remote.py 正是按这个优先级实现的:
action归一化为小写并允许连字符(replace("-", "_")),仅接受read、write、patch三种取值;read支持可选的line_from、line_to行号区间参数;write必须携带content;patch必须提供且只能提供三种补丁形式之一:edits、patch_text或old_text+new_text。
三种补丁形式在 plugins/_text_editor/helpers/patch_request.py 的parse_patch_request中被强制互斥校验:同时给出多于一种形式会返回both_error("provide exactly one patch form: edits, patch_text, or old_text/new_text");old_text为空会报 "old_text is required for exact replace";patch_text为空会报 "patch_text must not be empty"。
工具提示词中还给出一个read的完整调用示例(JSON):
{ "thoughts": [ "The user asked for a file on the connected local machine, so I should read it through the A0 CLI host." ], "headline": "Reading file on connected local machine", "tool_name": "text_editor_remote", "tool_args": { "action": "read", "path": "README.md", "line_from": 1, "line_to": 80 } }read的返回格式在 tools/text_editor_remote.py 中定义为:
{path} {total_lines} lines >>> {content} <<<即先输出路径与总行数,再以>>>与<<<包裹文件内容,便于模型在后续 patch 时精确定位上下文。
Patch Text 语法规则
patch_text是上下文锚定的补丁格式(实现参考 plugins/_text_editor/helpers/context_patch.py,采用 PseudoPatch 风格)。Skill 文档给出以下硬性规则,缺一不可:
- 精确替换:
old_text必须恰好匹配当前文件中的一处原文;若匹配到多处,应使用更长的文本片段使其唯一; - 单文件:
patch_text支持一次只更新一个文件的多个 hunk(*** Update File:只能出现一次,见 context_patch.py); - 插入:使用一个
@@ existing line锚点,随后逐行+new line表示新增; - 替换:使用
@@ before target锚点,随后-old++new;或使用@@ old target锚点,后接同样的替换对; - 禁止:在同一 hunk 中,同一旧行既作为上下文又作为删除行出现;
- 前缀:每个非头部内容行必须以且仅以一个前缀开头——空格表示上下文、
+表示新增、-表示删除; - 禁止:一次插入不得堆叠多个
@@锚点。
从 context_patch.py 的解析逻辑可以看到,合法的补丁以*** Begin Patch开头、以*** End Patch结尾,文件头必须是*** Update File: {path};*** Move to:、*** Add File:、*** Delete File:均不被支持(分别报 "does not support file moves" 与 "supports update hunks only")。解析器会校验必须包含至少一个更新 hunk("patch_text must contain at least one update hunk")。
一个标准替换补丁示例:
*** Begin Patch *** Update File: /home/user/project/config.py @@ def load_config(): - timeout = 30 + timeout = 60 *** End Patch当使用old_text/new_text精确替换时,工具会在内部调用 exact_replace_to_patch_text,把精确替换自动转换成上述上下文补丁格式再下发,因此两条路径共享同一套 CLI 侧应用逻辑。
新鲜度感知:为什么行号编辑会被拒绝
Skill 反复强调"基于最近一次远程读取"与"过期重试",其背后是 Agent Zero 的新鲜度(freshness)检查机制,实现在 plugins/_text_editor/helpers/patch_state.py 中(远程侧经 text_editor_freshness.py 复用同一套逻辑,使用独立的REMOTE_FRESHNESS_KEY = "_a0_connector_text_editor_remote_mtimes"存储)。
工作流程如下(对应 tools/text_editor_remote.py 的_execute_patch):
- 执行
patch(基于行号edits)前,先向 CLI 发一次stat操作取回文件元数据(realpath、mtime、total_lines,结构见FileMetadata); - 调用
check_patch_freshness(agent, stat_file)比对服务端记录的该文件 mtime 与当前 mtime; - 若返回
patch_need_read(从未读过或记录缺失)或patch_stale_read(mtime 不一致),则拒绝本次 patch; - 拒绝后,工具会通过
fw.text_editor.patch_need_read.md/fw.text_editor.patch_stale_read.md提示 Agent 先重新读取文件(见 tools/text_editor_remote.py); - 若 CLI 太老、不认识
stat操作(错误信息含unknown op: stat),则返回unsupported_cli_freshness,提示升级 CLI 后再试。
patch 成功后,服务端会根据结果更新状态:若 mtime/行数变化符合预期(替换行数守恒)则记录新状态,否则标记为 stale(mtime: 0, total_lines: 0),强制下一次编辑前重新读取。这正是"行号可能因外部修改而失效"这一工程问题在 Agent 侧的自动化防线。
失败处理:断连、超时与权限
Skill 文档在失败处理一节定义了三条准则,源码均有对应实现:
| 场景 | 处理方式 | 源码依据 |
|---|---|---|
| 没有连接的 CLI | 告知用户将 A0 CLI 连接到当前 Agent Zero 实例 | tools/text_editor_remote.py |
| 写入被阻止 | 告知用户按F3将本地文件访问切换为 Read&Write | tools/text_editor_remote.py |
| 请求超时或 CLI 断开 | 汇总失败原因,等待重连后重试 | FILE_OP_TIMEOUT = 30.0,超时与ConnectionNotFoundError分支(tools/text_editor_remote.py) |
超时错误消息形如text_editor_remote: timed out waiting for CLI to respond to {op} on {path!r};CLI 在投递前断开则报the selected CLI client disconnected before the file operation could be delivered。无论哪种情况,工具都会清理挂起的操作记录(clear_pending_file_op)并以ok: False返回,不会静默吞掉失败。
此外,ws_runtime.py 还支持大文件分块回传:CLI 可以以json+base64编码的分片帧(chunk_index/chunk_count)返回超大文件内容,服务端按序组装并校验后再解析(ws_runtime.py),从而让大文件的远程读取也能可靠完成。
能力发现与可见性
text_editor_remote工具并非总是可见,它由 A0 Connector 的能力协商机制控制。在 api/v1/capabilities.py 的_BASE_FEATURES列表中,text_editor_remote是基础特性之一;而在工具侧,提示词 agent.system.tool.text_editor_remote.md 的显示条件是"已连接的 A0 CLI 宣告了远程文件访问能力"。插件 AGENTS.md(plugins/_a0_connector/AGENTS.md)中的契约进一步说明:
remote file metadata enables
text_editor_remote
即:只有 CLI 通过连接握手上报RemoteFileMetadata(enabled)之后,该工具提示词才会注入 Agent 的上下文;没有连接任何 CLI 时,远程工具提示词整体隐藏,Agent 也就不会尝试调用。这种"按需可见"设计避免了模型在无 CLI 环境下误用远端工具。
总结
host-file-editing技能为 Agent Zero 的远程文件操作划定了清晰的行为准则:边界上只处理 CLI 主机文件,服务端/Docker 文件走常规工具;模式上区分 Read&Write 与 Read only,写入权限由 CLI 侧 F3 控制;流程上坚持 read 优先、patch 次之、write 兜底;语法上通过严格的patch_text上下文锚定规则保证补丁的确定性;可靠性上以 mtime 新鲜度检查杜绝过期行号编辑,并对无连接、无权限、超时、断连给出显式失败提示。这套设计与 tools/text_editor_remote.py、helpers/ws_runtime.py、helpers/text_editor_freshness.py 等实现一一对应,任何想要为 Agent Zero 接入"本机文件编辑"能力、或扩展远程工具生态的开发者,都可以把这条技能链路作为参考范式。
【免费下载链接】agent-zeroAgent Zero AI framework项目地址: https://gitcode.com/GitHub_Trending/ag/agent-zero
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考