Skip to content

OpenClaw Diffs 插件为 agent 提供只读代码差异查看能力:接受 before/after 文本或 unified patch 输入,输出画布查看器 URL(mode: "view")或 PNG/PDF 文件(mode: "file"),也可同时返回两者。默认制品 TTL 30 分钟,最大 6 小时。文件模式需要 Chromium 兼容浏览器,查看器默认仅限本地环回地址,远程访问需额外配置 viewerBaseUrl 并启用 allowRemoteViewer

OpenClaw Diffs 插件:代码差异可视化工具配置与故障排查

diffs 是可选插件工具,带有简短内置系统提示引导和配套技能,用于将变更内容转化为 agent 可呈现的只读差异制品。

接受以下输入之一:

  • beforeafter 文本
  • unified patch

可返回:

  • 用于画布展示的网关查看器 URL
  • 用于消息投递的渲染文件路径(PNG 或 PDF)
  • 一次调用同时返回两者

快速开始

安装插件

```bash
openclaw plugins install diffs
```

启用插件

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

选择输出模式

view

    画布优先流程:agent 调用 `diffs` 并设置 `mode: "view"`,然后用 `canvas present` 打开 `details.viewerUrl`。

file

    聊天文件投递:agent 调用 `diffs` 并设置 `mode: "file"`,然后用 `message` 工具通过 `path` 或 `filePath` 发送 `details.filePath`。

both

    组合模式:agent 调用 `diffs` 并设置 `mode: "both"`,一次调用同时获得查看器和文件。

怎么禁用内置系统提示引导

如果想保留 diffs 工具但去掉其自动注入的系统提示,设置 plugins.entries.diffs.hooks.allowPromptInjectionfalse

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

这会屏蔽 diffs 插件的 before_prompt_build 钩子,同时保持插件、工具和配套技能可用。如果想完全禁用引导和工具,直接禁用插件本身。

典型 agent 工作流

调用 diffs

Agent 调用 `diffs` 工具并传入输入。

读取 details

Agent 从响应中读取 `details` 字段。

展示制品

Agent 选择:
- 用 `canvas present` 打开 `details.viewerUrl`
- 用 `message` 工具通过 `path` 或 `filePath` 发送 `details.filePath`
- 两者都做

输入示例

Before and after

```json
{
  "before": "# Hello\n\nOne",
  "after": "# Hello\n\nTwo",
  "path": "docs/example.md",
  "mode": "view"
}
```

Patch

```json
{
  "patch": "diff --git a/src/example.ts b/src/example.ts\n--- a/src/example.ts\n+++ b/src/example.ts\n@@ -1 +1 @@\n-const x = 1;\n+const x = 2;\n",
  "mode": "both"
}
```

工具输入参数参考

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

before string

原始文本。省略 patch 时,必须与 after 一起提供。

after string

更新后文本。省略 patch 时,必须与 before 一起提供。

patch string

Unified diff 文本。与 before/after 互斥。

path string

Before/after 模式下显示的文件名。

lang string

语言覆盖提示;未知值回退为纯文本。

title string

查看器标题覆盖。

mode

输出模式,默认值为插件配置中的 defaults.mode。已废弃别名 "image" 行为同 "file",仍向后兼容。

theme

查看器主题,默认值来自 defaults.theme

layout

差异布局,默认值来自 defaults.layout

expandUnchanged boolean

当存在可展开上下文时,展开未改动部分。仅作为每次调用的选项,无插件级默认值。

fileFormat

渲染文件格式,默认值来自 defaults.fileFormat

fileQuality

PNG 或 PDF 渲染质量预设。

fileScale number

设备缩放倍率覆盖,范围 1-4

fileMaxWidth number

最大渲染宽度(CSS 像素),范围 640-2400

ttlSeconds number

制品 TTL(秒),适用于查看器和文件输出。最大 21600(6 小时)。

baseUrl string

查看器 URL 的 origin 覆盖。必须为 httphttps,不含查询参数和 hash。覆盖插件 viewerBaseUrl

已废弃的输入别名

以下旧字段仍向后兼容:
- `format` -> `fileFormat`
- `imageFormat` -> `fileFormat`
- `imageQuality` -> `fileQuality`
- `imageScale` -> `fileScale`
- `imageMaxWidth` -> `fileMaxWidth`

输入验证与大小限制

- `before` 和 `after` 各自最大 512 KiB。
- `patch` 最大 2 MiB。
- `path` 最大 2048 字节。
- `lang` 最大 128 字节。
- `title` 最大 1024 字节。
- Patch 复杂度上限:最多 128 个文件,120000 总行数。
- `patch` 与 `before`/`after` 同时提供会被拒绝。
- 渲染文件安全限制(同时作用于 PNG 和 PDF):
  - `fileQuality: "standard"`:最大 8 MP(800 万渲染像素)
  - `fileQuality: "hq"`:最大 14 MP(1400 万渲染像素)
  - `fileQuality: "print"`:最大 24 MP(2400 万渲染像素)
  - PDF 额外限制:最多 50 页

输出 details 契约

工具在 details 下返回结构化元数据。

查看器模式字段

适用于所有创建查看器的模式:
- `artifactId`
- `viewerUrl`
- `viewerPath`
- `title`
- `expiresAt`
- `inputKind`
- `fileCount`
- `mode`
- `context`(包含 `agentId`、`sessionId`、`messageChannel`、`agentAccountId`,视情况)

文件模式字段

当渲染 PNG 或 PDF 时返回:
- `artifactId`
- `expiresAt`
- `filePath`
- `path`(与 `filePath` 相同,用于消息工具兼容)
- `fileBytes`
- `fileFormat`
- `fileQuality`
- `fileScale`
- `fileMaxWidth`

向后兼容别名

为旧客户端同时返回:
- `format`(同 `fileFormat`)
- `imagePath`(同 `filePath`)
- `imageBytes`(同 `fileBytes`)
- `imageQuality`(同 `fileQuality`)
- `imageScale`(同 `fileScale`)
- `imageMaxWidth`(同 `fileMaxWidth`)

模式行为汇总:

模式返回内容
"view"仅查看器字段
"file"仅文件字段,不创建查看器制品
"both"查看器字段 + 文件字段。若文件渲染失败,查看器仍正常返回,并额外附带 fileError(别名 imageError

未改动行的折叠显示

  • 查看器可以显示如 N unmodified lines 的行。
  • 这些行上的展开控件并非对所有输入类型都保证出现。
  • 当渲染的差异包含可展开上下文数据时,才会出现展开控制;对于 before/after 输入这是典型的。
  • 对于许多 unified patch 输入,解析的 hunk 中缺少省略的上下文,因此未改动行可能不带展开控件——这是预期行为。
  • expandUnchanged 仅当存在可展开上下文时生效。

插件默认值配置

~/.openclaw/openclaw.json 中设置:

json5
{
  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,
          },
        },
      },
    },
  },
}

支持的默认字段:

  • fontFamily
  • fontSize
  • lineSpacing
  • layout
  • showLineNumbers
  • diffIndicators
  • wordWrap
  • background
  • theme
  • fileFormat
  • fileQuality
  • fileScale
  • fileMaxWidth
  • mode
  • ttlSeconds

工具调用中的显式参数会覆盖这些默认值。

查看器 URL 持久化配置

viewerBaseUrl string

插件级别的查看器 URL 回退。当工具调用未传 baseUrl 时使用。必须为 httphttps,不含查询参数和 hash。

json5
{
  plugins: {
    entries: {
      diffs: {
        enabled: true,
        config: {
          viewerBaseUrl: "https://gateway.example.com/openclaw",
        },
      },
    },
  },
}

安全配置

security.allowRemoteViewer boolean

false:非 loopback 的查看器请求被拒绝。true:允许远程查看器(若 token 化路径有效)。

json5
{
  plugins: {
    entries: {
      diffs: {
        enabled: true,
        config: {
          security: {
            allowRemoteViewer: false,
          },
        },
      },
    },
  },
}

制品生命周期与存储

  • 制品存储在临时子目录:$TMPDIR/openclaw-diffs
  • 查看器制品元数据包含:
    • 随机 artifact ID(20 位十六进制)
    • 随机 token(48 位十六进制)
    • createdAtexpiresAt
    • 存储的 viewer.html 路径
  • 默认查看器 TTL:30 分钟(1800 秒)。
  • 最大接受查看器 TTL:6 小时(21600 秒)。
  • 清理在制品创建后机会性地运行。
  • 过期制品会被删除。
  • 元数据缺失时,回退清理删除超过 24 小时的过期文件夹。

查看器 URL 与网络行为

查看器路由:

  • /plugins/diffs/view/{artifactId}/{token}

查看器静态资源:

  • /plugins/diffs/assets/viewer.js
  • /plugins/diffs/assets/viewer-runtime.js

查看器文档相对于 URL 解析这些资源,因此可选的 baseUrl 路径前缀也会保留给资产请求。

URL 构建顺序:

  1. 若工具调用提供了 baseUrl,经严格验证后使用。
  2. 否则若插件配置了 viewerBaseUrl,使用它。
  3. 无覆盖时,查看器 URL 默认为 loopback 127.0.0.1
  4. 若网关绑定模式为 custom 且设置了 gateway.customBindHost,则使用该 host。

baseUrl 规则:

  • 必须以 http://https:// 开头。
  • 拒绝包含查询参数或 hash。
  • 允许 origin 加可选基础路径。

安全模型

查看器加固

- 默认仅限 loopback 地址。
- Token 化的查看器路径,严格校验 ID 和 token。
- 查看器响应 CSP:
  - `default-src 'none'`
  - 脚本和资源仅来自 self
  - 无出站 `connect-src`
- 启用远程访问时的限流:每 60 秒 40 次失败,60 秒锁定(`429 Too Many Requests`)

文件渲染加固

- 截屏浏览器的请求路由默认拒绝一切。
- 仅允许访问本地的查看器资产:`http://127.0.0.1/plugins/diffs/assets/*`
- 外部网络请求被阻断。

file 模式的浏览器要求

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

浏览器解析顺序:

配置文件

OpenClaw 配置中的 `browser.executablePath`

环境变量

- `OPENCLAW_BROWSER_EXECUTABLE_PATH`
- `BROWSER_EXECUTABLE_PATH`
- `PLAYWRIGHT_CHROMIUM_EXECUTABLE_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)` origin,不含查询参数和 hash。
- `{field} exceeds maximum size (...) ` — 减小 payload 大小。
- 大型 patch 被拒 — 减少 patch 文件数或总行数。

查看器无法访问(远程)

- 查看器 URL 默认解析为 `127.0.0.1`。
- 对于远程场景,请:
  - 设置插件 `viewerBaseUrl`,或
  - 每次调用传入 `baseUrl`,或
  - 使用 `gateway.bind=custom` 和 `gateway.customBindHost`
- 如果 `gateway.trustedProxies` 包含 loopback(例如 Tailscale Serve),裸 loopback 查看器请求因缺少转发客户端 IP 头会被拒绝——这是预期设计。
- 对于那种代理拓扑:
  - 如果只需附件,优先用 `mode: "file"` 或 `mode: "both"`
  - 如果需要可分享的查看器 URL,主动启用 `security.allowRemoteViewer` 并设置插件 `viewerBaseUrl` 或传入代理 / 公开 `baseUrl`
- 仅在打算开放外部查看器访问时才启用 `security.allowRemoteViewer`。

未改动行没有展开按钮

对于 patch 输入,当 patch 不包含可展开上下文时可能出现。这是预期行为,不表示查看器故障。

制品未找到

- 制品因 TTL 过期。
- Token 或路径已变更。
- 清理进程删除了过期数据。

运维建议

  • 本地交互式审查时,优先使用 mode: "view"
  • 需要作为附件发送到外部聊天渠道时,优先使用 mode: "file"
  • 保持 allowRemoteViewer 禁用,除非你的部署确实需要远程查看器 URL。
  • 对敏感差异设置较短的显式 ttlSeconds
  • 避免在差异输入中包含不应传输的密钥。
  • 如果聊天渠道会大幅压缩图片(如 Telegram、WhatsApp),优先使用 PDF 输出(fileFormat: "pdf")。

INFO

差异渲染引擎由 Diffs 提供支持。

相关文档

常见问题

如何让外部用户访问 Diffs 查看器?

查看器默认仅允许本地环回地址(127.0.0.1)。要让外部访问,需要在插件配置中设置 viewerBaseUrl(例如 https://your-gateway.com/openclaw)并将 security.allowRemoteViewer 设为 true。注意:远程查看器路径带 token,但一旦暴露链接即可分享。启用限流:每 60 秒 40 次失败后锁定 60 秒。

为什么 mode: "file"mode: "both" 报错要求 Chromium 浏览器?

文件模式需要 Chromium 兼容浏览器来渲染 PNG/PDF。OpenClaw 会依次检查配置 browser.executablePath、环境变量(OPENCLAW_BROWSER_EXECUTABLE_PATH 等)和平台路径。如果都没有找到,就会报错 Diff PNG/PDF rendering requires a Chromium-compatible browser。安装 Chrome/Chromium/Edge/Brave 或设置上述环境变量即可解决。

制品默认有效期多久?能延长吗?

默认有效期 30 分钟(1800 秒),可通过工具调用的 ttlSeconds 参数延长,最大 21600 秒(6 小时)。过期后制品会被自动清理,无法恢复,需要重新调用 diffs 生成。