ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

ClawX 文件活动机制深度解析:基于 ACP 时间线的 OpenClaw 文件变更投影与工作区安全边界

ClawX 文件活动机制深度解析:基于 ACP 时间线的 OpenClaw 文件变更投影与工作区安全边界 人工智能AI 应用桌面应用交互助手【免费下载链接】ClawXClawX is a desktop app that provides a graphical interface for OpenClaw AI agents. It turns CLI-based AI orchestration into a desktop experience without using the terminal. China website is https://clawx.com.cn.项目地址https://gitcode.com/gh_mirrors/cl/ClawX点击查看免费下载导读本文以 openclaw-file-activity.md 为技术主线剖析 ClawX 桌面端如何在不扫描磁盘、不维护持久账本的前提下把 OpenClaw Agent 在 ACP 会话中声明的write、edit、apply_patch三类文件工具调用投影为聊天时间线中的文件活动卡片与Changes差异视图。你将掌握文件活动记录的语义边界与工具解析规则、AcpFileActivity数据模型与聚合算法、POSIX/Windows 双路径族下的工作区包含校验Workspace containment、工具派生路径与用户附件两条安全边界的隔离以及 Main 进程对每次读取、打开、reveal 操作的独立重校验机制。文末给出对应的单元测试与 E2E 测试锚点便于你在仓库中继续深入验证。该特性对应的核心实现位于 src/lib/acp/openclaw-file-activities.tsUI 呈现位于 src/pages/Chat/AcpFileCard.tsx 与 src/pages/Chat/AcpTurnFileActivity.tsx权威规则约束见 tool-derived-file-safety.md。一、语义与归属文件活动是什么、不是什么1.1 定义边界文件活动File Activity是纯 Renderer渲染进程对活跃 ACP 时间线的投影它记录的是 OpenClaw 文件编辑类工具调用所声明的文件变更而不是真实的磁盘差异。参考文档给出了三条明确的否定式定义它不是 Git diff它不是经过磁盘校验的 diff它不是会话开始时的基线快照。1.2 不做清单从参考文档与 tool-derived-file-safety.md 的规则表述可以归纳出 ClawX 明确不做的事不扫描或监听工作区no workspace scan/watch不创建快照不推断 shell/脚本的副作用例如工具调用中出现的路径不会成为凭据不解析任意散文内容不调用sessions.files.list去伪造差异不持久化一份独立的文件活动账本。因此文件活动本质上是会话时间线的可丢弃派生视图——切换会话时投影随活跃时间线一起清除见第五节体验与回放。1.3 Main 进程的职责边界与 Renderer 的投影职责对应Main主进程不解释工具语义它只执行两类操作工作区范围内的read/stat显式的原生文件动作打开应用、reveal。这一职责划分在源码中有清晰体现Renderer 侧的投影逻辑完全由 src/lib/acp/openclaw-file-activities.ts 承担而 Main 侧的工作区文件服务由 electron/services/files-api.ts 承担两者通过 Host API 的WorkspaceFileRef契约衔接见第四节。1.4 支持的工具有且只有三种文件活动只认三个工具write、edit、apply_patch。工具身份的判定规则是取 OpenClaw ACP 标题中第一个冒号之前的小写 trim 段parseToolName工具调用状态必须为completed。其余情况——不支持的工具、格式异常、pending、running、failed、cancelled——一律保持普通工具卡片形态不产生任何文件活动。对应的单元测试在 tests/unit/openclaw-file-activities.test.ts 中验证了WriteFile: x、rewrite: x、read: x、exec: x、write file: x、write x等近似标题全部被拒而write: a、EdIt : b、APPLY_PATCH: c这类大小写与空格差异的标题会被规范化后接受。二、规范输入Canonical Inputs三种工具的解析规则2.1 路径字段优先级对write与edit路径字段按以下优先级取值readPath的实现顺序path → file_path → filePath → file取到第一个非空字符串即停止。单元测试验证了同时给出四个字段时只有path生效tests/unit/openclaw-file-activities.test.ts中uses canonical path alias precedence用例。2.2 write空到新的 fragmentwrite的输入解析规则接受字符串content若存在字符串 content产生一个oldText: → newText: content的 fragment空到新片段动作标记为created。关键语义created描述的是工具意图并不断言该文件此前不存在。此外若路径合法但没有字符串 content则可能产生一个仅含路径的记录path-only record此时行数统计不可用added/removed 为null而非 0——对应测试uses canonical path alias precedence and retains path-only Writes。2.3 edit两种兼容形态edit接受两种输入形态规范数组形态edits: Array{ oldText, newText }官方顶层兼容形态顶层直接给出oldText/newText。解析规则数组形态中每个元素必须是同时含字符串oldText与newText的记录否则该条目被跳过例如缺少newText、或oldText/newText均为空字符串的条目会被忽略顶层兼容形态的 fragment 会追加到数组形态之后故意不支持宽泛别名如old_string/new_string——单元测试accepts only canonical array and top-level Edit pairs and skips invalid entries专门验证了带old_string的调用不产生任何 fragment。2.4 apply_patchOpenClaw 补丁封套语法apply_patch的解析是三者中最复杂的参考文档逐条给出了语法契约实现位于parsePatch/parsePatchHunk/parseUpdateChunksrc/lib/acp/openclaw-file-activities.ts。信封与包裹envelope wrapper必须包裹在*** Begin Patch/*** End Patch之间可选支持三种 heredoc 包裹EOF、EOF、EOF结束行以EOF收尾单元测试逐一验证了三种包裹形式it.each([EOF, EOF])。支持的区块sections区块行标记说明Add*** Add File: path内容行以开头产生created动作Update*** Update File: path内容行用空格上下文、-删除、新增Delete*** Delete File: path产生deleted动作fragments 为空Move-toUpdate 区块后紧跟*** Move to: path见下方移动语义Update 块的规则细节第一个 Update chunk 可以省略上下文标记后续 chunk 必须带allowMissingContext仅对首个 chunk 为真*** End of File是语法标记而非文件内容用于标识 chunk 结束空行同时计入旧/新两侧。原子失败语义语法失败会整体拒绝整个工具载荷不产生部分活动。单元测试atomically discards malformed apply-patch payloads验证了即使某个 Add 块单独看是合法的只要后续 Update 块出现非法行整个载荷的活动结果为空投影EMPTY_PROJECTION。独立路径过滤语法解析通过后若某些路径独立地不安全超出工作区这些路径会被剔除而工作区内合法的记录仍然保留——即安全的记录不被连坐。2.5 移动Move的折叠语义一个 Move 通常产生两条记录源路径deleted 目标路径created更新 fragment 挂在目标上。但若规范化后的源路径与目标路径相同例如./same.txt→nested/../same.txt则折叠为一次modified。单元测试collapses a same-normalized-path Move and splits a real Move精确验证了这一行为。三、数据模型与聚合Data Model And Aggregation3.1 核心类型参考文档给出了概念模型实现中的权威类型定义在 src/lib/acp/openclaw-file-activities.ts第 7-49 行type AcpFileChangeFragment { oldText: string; newText: string; sequence: number; }; type AcpFileActivity { turnId: string; toolCallId: string; toolName: write | edit | apply_patch; relativePath: string; action: created | modified | deleted; fragments: AcpFileChangeFragment[]; sequence: number; }; type AcpFileActivityProjection { activities: AcpFileActivity[]; turnSummariesByTurnId: Recordstring, AcpTurnFileSummary[]; fileGroups: AcpSessionFileGroup[]; uniqueFileCount: number; };要点sequence是派生的显示顺序号不是持久化身份turn 关联复用 ACP 显示分组算法groupAcpTimelineItems来自 src/lib/acp/timeline-groups.ts包括仅含工具的 turntool-only turns。单元测试验证了工具调用之间的用户消息不产生新的 turn 分组纯工具 turn 也能获得assistant-turn:tool:id形式的 turnId。3.2 投影入口projectOpenClawFileActivities是唯一入口输入为{ timeline, workspaceRoot, executionCwd }输出AcpFileActivityProjection。其内部流程createPathContext校验根与 cwd见第四节遍历按 turn 分组后的时间线只处理assistant-turn分组只处理kind tool-call、status completed且toolCallId未被处理过的条目reducer 级别的工具身份去重防止同一工具的流式更新产生重复活动按工具类型解析输入产出活动记录。3.3 聚合规则Turn 内每个路径只有一个按钮与一个摘要buildSummaries但保留按时间顺序的完整活动与 fragments跨会话Changes 视图buildFileGroups按相对路径分组组内活动按时间顺序排列组本身按首次活动出现顺序排列去重完全相同的(oldText, newText)片段对被剔除mergeActivityFragments中的seen集合安全链式合并当前一活动的newText等于后一活动的oldText时两个 fragment 可以串接合并例如A→B后接B→C合并为A→C单元测试验证了diff: { oldText: A, newText: C }独立 fragment互不相关的片段共享同一个展示 diff但不宣称是累积补丁cumulative patch——合并逻辑对无法串联的片段保留其独立性例如one→two与three→four生成oldText: one\n\nthree、newText: two\n\nfour。3.4 行数统计统计前先规范化 CRLFnormalizeEol\r\n→\n使用diffLines来自diff包逐 fragment 统计新增/删除行数缺失可计数 fragment 时added/removed 为null不展示绝不伪造 0。对应测试matches diffLines semantics for empty text, CRLF, trailing newlines, and context-only hunks验证了空 content0/-0、CRLF 变化0/-0、上下文-only chunk0/-0等边界。3.5 动作折叠同一 turn 内同一路径的多个动作按foldAction折叠一旦出现deleted则终态为deletedcreated优先于modified先 create 后 edit 显示created。测试folds same-turn same-path actions, sums counts, and preserves chronological file groups验证了create→edit→delete→recreate序列最终摘要动作仍为created且计数跨多个活动累加4 增 1 删。四、路径安全工作区包含边界4.1 信任模型工具路径是不可信的输入。两个权威上下文workspaceRoot包含边界containment boundaryexecutionCwdACP 工作目录会话绑定时由 Main 权威解析并注册见 session-workspace-authority.md。规则相对路径基于 execution cwd 解析相对与绝对候选路径都必须词法上lexically位于 workspace root 之内且必须属于同一路径族posix 或 windows。若没有权威的 root 与 cwd如非绝对路径、混合路径族、或 cwd 逃出 root则整个投影不产生。单元测试rejects non-absolute, mixed-family, or out-of-root context before projection用五组非法上下文逐一验证。4.2 双路径族解析createPathContext与resolveToolPath实现了完整的 POSIX / Windows 双语义跨平台可用不依赖 Node 的path模块——测试甚至断言投影源码不 importnode:内建模块以保证 Renderer 沙箱兼容POSIX..归一化、反斜杠\被转换为/、Windows 绝对路径C:\...、UNC被拒绝、/workspace-collision/...这类根前缀碰撞root-prefix collision被正确排除Windows盘符C:与 UNC\\server\share语义完整C:workspace\x.txt这类盘符相对路径被拒绝大小写不敏感比较。测试uses win32 drive and UNC semantics cross-platform验证了C:\work根下c:/work/project/b.txt归一化为project/b.txt、D:\其他盘被拒、UNC 根下..\shared.txt解析为shared.txt。4.3 WorkspaceFileRef 契约预览与显式原生动作全程只使用相对引用type WorkspaceFileRef { workspaceRoot: string; relativePath: string; };该类型定义在 src/lib/file-preview-client.tsHost API 契约在 src/lib/host-api.ts 中对应files.readWorkspaceText、readWorkspaceBinary、statWorkspaceFile、listWorkspaceOpenHandlers、openWorkspaceWith、revealWorkspaceFile等操作全部接收WorkspaceFileRef。4.4 Main 的独立规范化与二次校验Renderer 的词法校验只是第一道防线对明显越界的路径直接拒绝 UI 呈现。Main 对每一次read/stat/原生动作请求都独立执行规范化canonicalize路径检查真实路径与最近的已存在父目录拒绝路径穿越traversal、非文件non-file、符号链接逃逸symlink escape避免跟随不安全的最终链接。实现位于 electron/services/files-api.ts对应测试 tests/unit/files-api-workspace.test.ts 中覆盖了rejects non-files, traversal, and symlink escapes for every workspace native action、rejects root-prefix collisions on POSIX and case-insensitive Windows paths、rejects existing targets and parent symlinks that escape the root、以及验证之后、打开之前父目录被换出的 TOCTOU 竞态用例rejects a parent swapped outside after validation but before file open。此外handler 发现、选中 handler 打开、reveal 每一步都重新解析WorkspaceFileRef选中 handler 打开前Main 在调用原生动作的前一刻执行一次额外的回调重校验callback revalidation如果 Renderer 层词法校验未拦截而 Main 层拒绝则历史活动仍保留但请求的文件操作被拒绝——UI 呈现Load failed而活动记录不消失。E2E 测试shows scoped read rejection without invoking unscoped file or shell actions验证了被拒后不产生任何非readWorkspaceText的 files 调用、也不产生任何 shell 调用。4.5 原生动作的边界工具派生的目标在应用内只读预览绝不使用裸路径 shell APInaked-path shell APIcreated/modified活动可暴露独立的Open with菜单其原生动作只由工作区范围的 Host API 操作支撑listWorkspaceOpenHandlers→openWorkspaceWith→revealWorkspaceFiledeleted活动不暴露任何原生动作对 HTML 文件菜单首先提供浏览器导航从有效的 workspace root 与包含的相对路径构造 file URLlocalHtmlBrowserUrl见 src/lib/local-html-browser.ts。E2E 测试验证了 HTML 活动点击主按钮后走 Preview 标签、导航到file:///workspace/site/demo.html且不出现 web-browser 标签原生适配器只接收Main 拥有的规范化路径与不透明 handler idMain 在调用前重新校验工作区引用Linux 平台上在浏览器动作之后若符合条件只提供工作区范围的 revealAcpFileOpenWith组件中platform linux时跳过 handler 发现。4.6 呈现壳src/pages/Chat/AcpFileCard.tsx 提供共享的附件/文件活动呈现壳与目标感知菜单不共享授权sharing grants。限制大小内的 DOCX/PPTX 活动通过其WorkspaceFileRef进入 Office 查看器解析与单查看器约束详见 office-document-preview.md。五、与附件的隔离Separation From Attachments文件活动与用户可见附件是两条独立的投影与安全边界工具输入/输出中的附带路径incidental paths始终是工具派生的证据它们不能变成附件卡片、不能在工作区外解析、不能使用附件范围的授权附件证据必须来自标准 ACP 资源内容、Main 拥有的用户 staging 记录、或有界的显式助手MEDIA:例外见 acp-generated-media-and-diagnostics.mdMain 只在 ACP 会话加载/创建成功后建立附件会话与相对路径上下文每次附件 resolve、预览读取、系统或外部打开都按精确的会话 key generation 引用 规范化目标重新校验与工具派生文件活动不同显式附件证据可以在工作区外解析文件活动永远不进入附件管线其显式原生动作通过WorkspaceFileRef被限制在规范化工作区内。完整的附件边界文档见 acp-attachment-access-control.md规则见 attachment-access-safety.md。这条隔离在代码中体现在AcpFileTarget联合类型上kind: workspace带WorkspaceFileRef与kind: attachment带 sessionKey/generation/uri/stagingId 等走完全不同的 Host API 分支。六、用户体验与回放User Experience And Replay6.1 单 turn 呈现每个助手 turn 对每个符合条件的路径显示一个文件按钮 一个摘要AcpTurnFileActivity组件渲染在 src/pages/Chat/AcpTurnFileActivity.tsxcreated/modified按钮主操作打开当前文件 Preview并带Open with菜单含浏览器动作、应用选择、revealdeleted按钮主操作直接打开 Changes无 Open with摘要区显示N/-M行数徽标added/removed 不可用时隐藏。E2E 测试renders a live completed Write with counts, scoped Preview, and a session record验证了按钮可访问名Created src/live.ts、摘要2-0、Open with 菜单、reveal 到revealWorkspaceFile、Preview 读取readWorkspaceText、以及 Changes 标签中的文件组与活动记录。6.2 Changes 视图Changes 按会话作用域分组按文件分组每个 turn、每个路径最多显示一个 diff 编辑器Monaco diff viewer空会话明确显示该会话没有文件变更E2E 断言This session has no file changes yet.多轮编辑同一路径时不同 turn 的 fragment 区块分别保留E2Epreserves both fragment sections when two live turns edit one path断言两个Change 1/Change 2与两个 diff viewer。6.3 多视图预览与 HTML当预览支持多个视图时分段切换器segmented switcher共享文件名字/路径头的尾部空间不额外占用一行HTML 文件暴露Preview与Source两个视图默认沙箱渲染预览切换视图时保留同一次作用域读取结果同一readWorkspaceText结果复用。6.4 回放与投影生命周期完整的 ACP 结构化回放historical replay通过同一条投影路径恢复可用活动单元测试projects historical items identically断言 historical 条目与实时条目产出完全一致仅转录transcript-only或不完整的回放不推断缺失记录——E2Edoes not invent file activity when replay omits raw input验证了缺 rawInput 的历史 Write 只显示普通工具卡片、不产生任何文件活动会话切换时投影随活跃时间线清除E2Erestores the full ledger after switching away and replaying the session验证了切走再切回后活动完整恢复、且新会话的延迟写入不会污染旧会话的 generation。6.5 排版一致性E2Ekeeps tool cards and file activity aligned with assistant prose in a wide transcript还验证了助手正文、工具卡片、文件活动卡片三者在宽视口下保持对齐宽度600px 且彼此宽度差 ≤2px保证长会话中排版稳定。七、验证锚点Validation Anchors参考文档与仓库给出了可复现的测试矩阵验证层文件覆盖内容单元测试tests/unit/openclaw-file-activities.test.ts工具名规范化、状态过滤、路径别名优先级、三种工具解析、补丁语法、双路径族、聚合/折叠/合并、空投影形态单元测试tests/unit/files-api-workspace.test.tsMain 侧工作区作用域文件服务staging 目录、遍历/符号链接逃逸、根前缀碰撞、TOCTOU 竞态E2E 测试tests/e2e/chat-file-changes.spec.tsHTML 预览导航、实时 Write/Edit/apply_patch 渲染、失败/不支持工具无活动、deleted 打开 Changes、多轮编辑、会话切换回放、作用域读取被拒、排版对齐组件测试tests/unit 下 file-preview 相关套件如file-preview-body.test.tsx、office-file-viewers.test.tsx预览壳与 Office 查看器的WorkspaceFileRef传递八、小结一次理解三个关键原则声明即记录文件活动忠于工具输入所声明的内容不做磁盘校验、不扫描、不推断因此它永远不失真也永远不会超过声明的范围双层防线Renderer 词法包含校验保证 UI 层不出界Main 规范化 实时路径校验 调用前重校验保证每一次文件操作都锚定在规范化工作区内符号链接与 TOCTOU 竞态被显式测试覆盖隔离优于复用工具派生文件活动与用户附件使用两套独立的安全边界与授权语义前者被牢牢锁在工作区WorkspaceFileRef内杜绝了附带路径升级为附件授权的路径混淆。这套设计把展示 Agent 改了什么文件与实际放行哪些文件操作彻底分离既保证了聊天体验的信息密度又把攻击面收敛到 Main 可审计的 Host API 边界之内——这也是 tool-derived-file-safety.md 规则把工具路径不可信作为第一原则的根本原因。赞分享人工智能AI 应用桌面应用交互助手【免费下载链接】ClawXClawX is a desktop app that provides a graphical interface for OpenClaw AI agents. It turns CLI-based AI orchestration into a desktop experience without using the terminal. China website is https://clawx.com.cn.项目地址https://gitcode.com/gh_mirrors/cl/ClawX点击查看免费下载相关推荐ClawX 工具派生文件安全从 ACP 文件活动到本地系统操作的双端信任边界ClawX 工具派生文件安全从 ACP 文件活动到本地系统操作的双端信任边界 ClawX 通过 ACPAgent Client Protocol会话把 O人工智能AI 应用桌面应用交互助手OpenClaw Logbook 插件完全指南把屏幕活动自动变成工作日志时间线OpenClaw Logbook 插件完全指南把屏幕活动自动变成工作日志时间线 Logbook 是 OpenClaw 内置但默认关闭的一个可选插件它以固定的AI 应用AI Agent交互助手后端即时通讯网关ClawX OpenClaw 配置投递机制深度解析单一协调器、Mutator 事务与安全提交ClawX OpenClaw 配置投递机制深度解析单一协调器、Mutator 事务与安全提交 导读 本文围绕 ClawX 的 OpenClaw 配置投递Co人工智能AI 应用桌面应用交互助手创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表