跳转至

Diffs

diffs 是一个可选的插件工具,可将 before/after 文本或统一补丁转换为只读的 diff 工件。它还会在系统提示词前插入简短的代理指导,并附带一个配套 skill,以便提供更完整的说明。

输入:before + after 文本,或统一 patch(互斥)。

输出:用于浏览器展示的 Gateway 查看器 URL、用于消息投递的渲染 PNG/PDF 文件路径,或两者兼有。

Control UI 在未安装此插件的情况下已能高亮显示内联工具 diff 和会话 diff。当代理需要独立的查看器链接或用于其他渠道的渲染附件时,请安装 diffs。

快速开始

1. 安装插件

openclaw plugins install clawhub:@openclaw/diffs

安装会自动应用到正在运行的 Gateway;否则将在下次启动时生效。参见 应用更改并检查。

diffs 及其语言包作为独立软件包发布,而非随 OpenClaw 一起提供,因此安装需要使用作用域定位符(scoped locator)。clawhub: 前缀会选择 ClawHub 上的 @openclaw/diffs 副本。如需改从 npm 安装,请使用 npm:@openclaw/diffs。

2. 启用插件

{
  plugins: {
    entries: {
      diffs: {
        enabled: true,
      },
    },
  },
}

3. 选择模式

浏览器流程:代理以 mode: "view" 调用 diffs,并在浏览器中打开 details.viewerUrl。

聊天文件投递:代理以 mode: "file" 调用 diffs,并通过 path 或 filePath 将 details.filePath 随 message 一起发送。

组合(默认):代理以 mode: "both" 调用 diffs,一次调用即可获得两种工件。

禁用内置系统指导

若要保留工具但移除前置的系统提示词指导,请将 plugins.entries.diffs.hooks.allowPromptInjection 设置为 false:

{
  plugins: {
    entries: {
      diffs: {
        enabled: true,
        hooks: {
          allowPromptInjection: false,
        },
      },
    },
  },
}

这会阻止插件的 before_prompt_build 钩子,同时保持工具和 skill 可用。若要同时禁用指导与工具,请改为禁用该插件。

工具输入参考

除非另有说明,所有字段均为可选。

before string (path)
原始文本。当省略 patch 时,需与 after 一起提供。
after string (path)
更新后的文本。当省略 patch 时,需与 before 一起提供。
patch string (path)
统一 diff 文本。与 before 和 after 互斥。
path string (path)
before/after 模式的显示文件名。
lang string (path)
before/after 模式的语言覆盖提示。未知值以及默认查看器集合之外的语言会回退为纯文本,除非已安装 Diffs Language Pack 插件。
title string (path)
查看器标题覆盖。
mode "view" | "file" | "both" (path)
输出模式。默认为插件默认值 defaults.mode(both)。已弃用的别名:"image" 的行为与 "file" 相同。
theme "light" | "dark" (path)
查看器主题。默认为插件默认值 defaults.theme。
layout "unified" | "split" (path)
diff 布局。默认为插件默认值 defaults.layout。
expandUnchanged boolean (path)
当完整上下文可用时展开未更改的部分。仅为每次调用时的选项(不是插件默认键)。
fileFormat "png" | "pdf" (path)
渲染文件格式。默认为插件默认值 defaults.fileFormat。
fileQuality "standard" | "hq" | "print" (path)
PNG/PDF 渲染的质量预设。
fileScale number (path)
设备缩放比例覆盖(1-4)。
fileMaxWidth number (path)
最大渲染宽度(CSS 像素)(640-2400)。
ttlSeconds number (path) 默认值:1800
查看器和独立文件输出的工件 TTL(秒)。最大 21600。
baseUrl string (path)
查看器 URL 来源(origin)覆盖。覆盖插件的 viewerBaseUrl。必须为 http 或 https,且不含查询参数/哈希。
验证与限制
  • before/after:各自最大 512 KiB。
  • patch:最大 2 MiB。
  • path:最大 2048 字节。
  • lang:最大 128 字节。
  • title:最大 1024 字节。
  • 补丁复杂度上限:最多 128 个文件和 120000 总行数。
  • 同时提供 patch 与 before/after 会被拒绝。
  • 渲染文件安全限制(PNG 和 PDF):
  • fileQuality: "standard":最大 8 MP(8,000,000 渲染像素)。
  • fileQuality: "hq":最大 14 MP。
  • fileQuality: "print":最大 24 MP。
  • PDF 还限制为最多 50 页。

语法高亮

内置语言:

javascript、typescript、tsx、jsx、json、markdown、yaml、css、html、sh、python、go、rust、java、c、cpp、csharp、php、sql、docker、ruby、swift、kotlin、r、dart、lua、powershell、xml 和 toml。

常用别名(js、ts、bash、md、yml、c++、dockerfile、rb、kt、ps1 等)会规范化为上述语言。

安装 Diffs Language Pack 插件以支持更多语言(Astro、Vue、Svelte、MDX、GraphQL、Terraform/HCL、Nix、Clojure、Elixir、Haskell、OCaml、Scala、Zig、Solidity、Verilog/VHDL、Fortran、MATLAB、LaTeX、Mermaid、Sass/Less/SCSS、Nginx、Apache、CSV、dotenv、INI、diff 等):

openclaw plugins install clawhub:@openclaw/diffs-language-pack

未安装该语言包时,不支持的语言仍会以可读的纯文本形式渲染。上游目录请参见 Diffs Language Pack 插件 和 Shiki 语言。

输出详情约定

所有成功结果均包含 changed:当 before/after 输入完全相同时返回 false,且不会创建工件;渲染结果返回 true。

查看器字段(view 和 both 模式)
  • changed
  • artifactId
  • viewerUrl
  • viewerPath
  • title
  • expiresAt
  • inputKind
  • fileCount
  • mode
  • context(可用时的 agentId、sessionId、messageChannel、agentAccountId)
文件字段(file 和 both 模式)
  • changed
  • artifactId
  • expiresAt
  • filePath
  • path(与 filePath 相同,用于消息工具兼容性)
  • fileBytes
  • fileFormat
  • fileQuality
  • fileScale
  • fileMaxWidth
模式 返回内容
"view" 仅查看器字段。
"file" 仅文件字段,无查看器工件。
"both" 查看器字段以及文件字段。如果文件渲染失败,查看器仍会返回结果,并带有 fileError。

折叠的未更改部分

查看器显示类似 N unmodified lines 的行。展开控件只有在渲染的差异包含可展开的上下文数据时才会出现(通常出现在 before/after 输入中)。许多 unified 补丁在其 hunk 中省略了上下文主体。此时该行可能没有展开控件。这是预期行为,不是 bug。expandUnchanged 仅在存在可展开的上下文时生效。

多文件导航

涉及多个文件的补丁会以已更改文件摘要卡片开头。该卡片显示:

  • 总计 +N / -N 计数
  • 每个文件的计数
  • 新增、删除和重命名的徽标
  • 跳转到每个文件的锚点链接

渲染后的 PNG/PDF 文件会保留每个文件的头部计数。它们会去掉交互式视图切换开关,因为在静态文件中这些控件是失效的。

插件默认值

在 ~/.openclaw/openclaw.json 中设置插件级默认值:

{
  plugins: {
    entries: {
      diffs: {
        enabled: true,
        config: {
          defaults: {
            fontFamily: "Fira Code",
            fontSize: 15,
            lineSpacing: 1.6,
            layout: "unified",
            showLineNumbers: true,
            diffIndicators: "bars",
            wordWrap: true,
            background: true,
            theme: "dark",
            fileFormat: "png",
            fileQuality: "standard",
            fileScale: 2,
            fileMaxWidth: 960,
            mode: "both",
            ttlSeconds: 21600,
          },
        },
      },
    },
  },
}

支持的 defaults 键:fontFamily、fontSize、lineSpacing、layout、showLineNumbers、diffIndicators、wordWrap、background、theme、fileFormat、fileQuality、fileScale、fileMaxWidth、mode、ttlSeconds。显式的工具调用参数会覆盖这些默认值。

持久化查看器 URL 配置

viewerBaseUrl string (path)
当工具调用未传入 baseUrl 时,用于返回查看器链接的插件自有回退地址。必须是 http 或 https,且不含查询字符串或哈希。
{
  plugins: {
    entries: {
      diffs: {
        enabled: true,
        config: {
          viewerBaseUrl: "https://gateway.example.com/openclaw",
        },
      },
    },
  },
}

安全配置

security.allowRemoteViewer boolean (path) default: false
false:拒绝指向查看器路由的非回环请求。true:如果令牌化路径有效,则允许远程查看器。
{
  plugins: {
    entries: {
      diffs: {
        enabled: true,
        config: {
          security: {
            allowRemoteViewer: false,
          },
        },
      },
    },
  },
}

工件生命周期与存储

  • 查看器 HTML 和元数据存储在共享的 state/openclaw.sqlite 数据库中,位于 Diffs 插件的 blob 命名空间下。HTML 经过 gzip 压缩。SQLite 仅存储随机 URL 令牌的 SHA-256 哈希,而非令牌本身。
  • 由于频道投递需要文件路径,渲染后的 PNG/PDF 文件会以临时物化文件的形式保留在 $TMPDIR/openclaw-diffs 下。SQLite 持有其过期元数据。OpenClaw 不写入 JSON sidecar 文件。
  • 默认工件 TTL:30 分钟。最大可接受 TTL:6 小时。
  • 每次工件创建调用后,清理会择机运行。首先删除过期的 SQLite 行,然后删除任何相应的 PNG/PDF 目录。
  • 后备扫描会移除超过 24 小时且无对应 SQLite 行的临时文件夹。遗留的 meta.json、file-meta.json 和 viewer.html 缓存不会被导入或读取。

查看器 URL 与网络行为

查看器路由:/plugins/diffs/view/{artifactId}/{token}

查看器资源:

  • /plugins/diffs/assets/viewer.js
  • /plugins/diffs/assets/viewer-runtime.js
  • /plugins/diffs-language-pack/assets/viewer.js(仅当差异使用语言包语言时)

查看器文档会相对于查看器 URL 解析这些资源。因此,可选的 baseUrl 路径前缀也会同样应用到资源请求中。

URL 解析顺序:工具调用的 baseUrl(经过严格验证后)-> 插件 viewerBaseUrl -> gateway.publicOrigin -> 现有的绑定感知 Gateway 回退。

baseUrl 规则:

  • 协议必须是 http:// 或 https://。
  • 带有查询字符串或哈希的 baseUrl 会被拒绝。
  • 允许源(origin)加可选的基础路径。

安全模型

查看器加固
  • 默认仅限回环(loopback)。
  • 令牌化查看器路径,具有严格的 ID 和令牌模式验证。
  • 查看器响应 CSP:default-src 'none'。脚本和资源仅从自身(self)加载。查看器不发出任何出站 connect-src 请求。
  • 启用远程访问时的远程未命中限流:每 60 秒 40 次失败会触发 60 秒锁定(429 Too Many Requests)。
文件渲染加固
  • 截图浏览器请求路由默认拒绝。
  • 仅允许来自 http://127.0.0.1/plugins/diffs/assets/* 的本地查看器资源。
  • 外部网络请求会被阻止。

文件模式的浏览器要求

mode: "file" 和 mode: "both" 需要兼容 Chromium 的浏览器。

解析顺序:

1. 配置

OpenClaw 配置中的 browser.executablePath。

2. 环境变量

  • OPENCLAW_BROWSER_EXECUTABLE_PATH
  • BROWSER_EXECUTABLE_PATH
  • PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH

3. 平台回退

Chrome、Chromium、Edge 和 Brave 的常见安装路径和 PATH 查找。

常见失败文本:Diff PNG/PDF rendering requires a Chromium-compatible browser...。通过安装 Chrome、Chromium、Edge 或 Brave,或设置上述任一可执行文件路径选项来修复。

故障排查

输入验证错误
  • Provide patch or both before and after text. -- 同时包含 before 和 after,或提供 patch。
  • Provide either patch or before/after input, not both. -- 不要混用输入模式。
  • Invalid baseUrl: ... -- 使用带可选路径的 http(s) 源,不包含查询参数/哈希。
  • {field} exceeds maximum size (...) -- 减小负载大小。
  • 大型 patch 被拒绝 -- 减少 patch 文件数量或总行数。
查看器可访问性
  • 查看器 URL 默认解析为 127.0.0.1。
  • 对于远程访问,设置 gateway.publicOrigin,设置插件 viewerBaseUrl,或按调用传递 baseUrl。
  • gateway.trustedProxies 可以包含回环地址,用于同一主机代理,例如 Tailscale Serve。此时,未携带转发客户端 IP 头的原始回环查看器请求会按设计失败关闭。
  • 对于该代理拓扑,附件优先使用 mode: "file"/"both"。对于可共享的查看器链接,请有意启用 security.allowRemoteViewer 以及插件 viewerBaseUrl/代理 baseUrl。
  • 仅在打算允许外部查看器访问时启用 security.allowRemoteViewer。
未修改行没有展开按钮

对于缺少可展开上下文的 patch 输入,这是预期行为。这不是查看器故障。

未找到工件
  • 工件因 TTL 过期。
  • Token 或路径已更改。
  • 清理移除了过期数据。

操作指南

  • 对于浏览器中的本地交互式审查,优先使用 mode: "view"。
  • 对于需要附件的外发聊天渠道,优先使用 mode: "file"。
  • 除非部署需要远程查看器 URL,否则保持 allowRemoteViewer 禁用。
  • 为敏感 diff 设置明确的短 ttlSeconds。
  • 除非必要,避免在 diff 输入中发送机密信息。
  • 如果渠道会强力压缩图像(例如 Telegram 或 WhatsApp),优先使用 PDF 输出(fileFormat: "pdf")。

Note

Diff 渲染引擎由 Diffs 提供支持。

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/openclaw