# Diffs

> 面向智能体的只读差异查看器和文件渲染器（可选插件工具）

- 网址：https://funcoding.ai/agents/openclaw/tools/diffs/
- 来源：OpenClaw 官方文档原文（中文），MIT 许可，同步于 2026-10-11
- 官方原文：https://docs.openclaw.ai/zh-CN/tools/diffs

---
`diffs` 是一个可选的内置插件工具，可将修改前/后的文本或统一补丁转换为只读 diff 工件。它还会在系统提示词前添加简短的智能体指导，并随附一项配套 Skills，以提供更完整的说明。

输入：`before` + `after` 文本，或统一 `patch`（互斥）。

输出：用于画布呈现的 Gateway 网关查看器 URL、用于消息传递的已渲染 PNG/PDF 文件路径，或两者。

## 快速开始

**安装插件**

```bash
openclaw plugins install diffs
```

**启用插件**

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

**选择模式**

**view**

画布优先流程：智能体使用 `mode: "view"` 调用 `diffs`，并使用 `canvas present` 打开 `details.viewerUrl`。

**file**

聊天文件传递：智能体使用 `mode: "file"` 调用 `diffs`，并通过 `path` 或 `filePath` 使用 `message` 发送 `details.filePath`。

**both**

组合模式（默认）：智能体使用 `mode: "both"` 调用 `diffs`，通过一次调用获取两种工件。

## 禁用内置系统指导

要保留工具但移除添加到系统提示词前的指导，请将 `plugins.entries.diffs.hooks.allowPromptInjection` 设置为 `false`：

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

这会阻止插件的 `before_prompt_build` 钩子，同时保持工具和 Skills 可用。要同时禁用指导和工具，请改为禁用插件。

## 工具输入参考

除非特别注明，否则所有字段均为可选。

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

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

统一 diff 文本。与 `before` 和 `after` 互斥。

修改前/后模式的显示文件名。

修改前/后模式的语言覆盖提示。未知值和默认查看器集合以外的语言会回退为纯文本，除非安装了
Diff Viewer Language Pack 插件。

查看器标题覆盖值。

输出模式。默认为插件默认值 `defaults.mode`（`both`）。已弃用的别名：`"image"` 的行为与 `"file"` 完全相同。

查看器主题。默认为插件默认值 `defaults.theme`。

Diff 布局。默认为插件默认值 `defaults.layout`。

在完整上下文可用时展开未更改的部分。仅限单次调用的选项（不是插件默认键）。

渲染后的文件格式。默认为插件默认值 `defaults.fileFormat`。

PNG/PDF 渲染的质量预设。

设备缩放覆盖值（`1`-`4`）。

最大渲染宽度，以 CSS 像素为单位（`640`-`2400`）。

查看器和独立文件输出的工件 TTL，以秒为单位。最大值为 `21600`。

查看器 URL 来源覆盖值。覆盖插件的 `viewerBaseUrl`。必须为 `http` 或 `https`，不得包含查询参数/哈希。

<details>
<summary>验证和限制</summary>

- `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 页。

</details>

## 语法高亮

内置语言：

`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` 等）会规范化为这些语言。

安装 Diff Viewer 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 等）：

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

未安装该语言包时，不支持的语言仍会以易读的纯文本呈现。有关上游目录，请参阅 [Diffs Language Pack 插件](https://docs.openclaw.ai/zh-CN/plugins/reference/diffs-language-pack)和 [Shiki 语言](https://shiki.style/languages)。

## 输出详情契约

所有成功结果都包含 `changed`：修改前/后输入相同时返回 `false`，且不会创建工件；已渲染的结果返回 `true`。

<details>
<summary>查看器字段（view 和 both 模式）</summary>

- `changed`
- `artifactId`
- `viewerUrl`
- `viewerPath`
- `title`
- `expiresAt`
- `inputKind`
- `fileCount`
- `mode`
- `context`（可用时为 `agentId`、`sessionId`、`messageChannel`、`agentAccountId`）

</details>

<details>
<summary>文件字段（file 和 both 模式）</summary>

- `changed`
- `artifactId`
- `expiresAt`
- `filePath`
- `path`（与 `filePath` 的值相同，用于消息工具兼容性）
- `fileBytes`
- `fileFormat`
- `fileQuality`
- `fileScale`
- `fileMaxWidth`

</details>

| 模式     | 返回内容                                                                                         |
| -------- | ----------------------------------------------------------------------------------------------- |
| `"view"` | 仅查看器字段。                                                                             |
| `"file"` | 仅文件字段，不含查看器工件。                                                           |
| `"both"` | 查看器字段加文件字段。如果文件渲染失败，查看器仍会随 `fileError` 返回。 |

### 折叠的未更改部分

查看器会显示类似 `N unmodified lines` 的行。仅当渲染后的 diff 包含可展开的上下文数据时，才会显示展开控件（修改前/后输入通常如此）。许多统一补丁会在其区块中省略上下文正文，因此该行可能出现但没有展开控件——这是预期行为，并非错误。`expandUnchanged` 仅在存在可展开上下文时适用。

### 多文件导航

涉及多个文件的补丁以已更改文件摘要卡片开头：`+N` / `-N` 总数、各文件计数、新增/删除/重命名徽章，以及跳转到各文件的锚点链接。渲染后的 PNG/PDF 文件会保留各文件的标题计数，但会移除交互式视图切换控件，因为这些控件在静态文件中无法使用。

## 插件默认值

在 `~/.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,
          },
        },
      },
    },
  },
}
```

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

### 持久化查看器 URL 配置

当工具调用未传递 `baseUrl` 时，由插件管理的返回查看器链接回退值。必须为 `http` 或 `https`，不得包含查询参数/哈希。

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

## 安全配置

`false`：拒绝向查看器路由发出的非 local loopback 请求。`true`：如果令牌化路径有效，则允许远程查看器。

```json5
{
  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 管理其过期元数据；不会写入 JSON 辅助文件。
- 默认工件 TTL：30 分钟。可接受的最大 TTL：6 小时。
- 每次创建工件调用后都会择机运行清理。首先删除已过期的 SQLite 行，随后删除任何对应的 PNG/PDF 目录。
- 兜底扫描会移除超过 24 小时且没有对应行的临时文件夹。不会导入或读取旧版 `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`（仅当 diff 使用语言包所支持的语言时）

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

URL 解析顺序：工具调用的 `baseUrl`（经过严格验证后）-> 插件的 `viewerBaseUrl` -> local loopback 的 `127.0.0.1` 默认值。如果 Gateway 网关绑定模式为 `custom`，且已设置 `gateway.customBindHost`，则使用该主机而非 local loopback。

`baseUrl` 规则：必须为 `http://` 或 `https://`；拒绝查询参数和哈希；允许使用源站以及可选的基础路径。

## 安全模型

<details>
<summary>查看器加固</summary>

- 默认仅限 local loopback。
- 使用令牌化查看器路径，并严格验证 ID 和令牌格式。
- 查看器响应 CSP：`default-src 'none'`；脚本/资源只能来自自身；不允许出站 `connect-src`。
- 启用远程访问时会对远程访问失败进行限流：60 秒内失败 40 次将触发 60 秒锁定（`429 Too Many Requests`）。

</details>

<details>
<summary>文件渲染加固</summary>

- 屏幕截图浏览器请求路由默认拒绝。
- 仅允许来自 `http://127.0.0.1/plugins/diffs/assets/*` 的本地查看器资源。
- 阻止外部网络请求。

</details>

## 文件模式的浏览器要求

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

解析顺序：

**配置**

OpenClaw 配置中的 `browser.executablePath`。

**环境变量**

- `OPENCLAW_BROWSER_EXECUTABLE_PATH`
- `BROWSER_EXECUTABLE_PATH`
- `PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH`

**平台回退**

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

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

## 故障排查

<details>
<summary>输入验证错误</summary>

- `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 (...)` —— 减小有效载荷大小。
- 大型补丁被拒绝 —— 减少补丁文件数量或总行数。

</details>

<details>
<summary>查看器可访问性</summary>

- 查看器 URL 默认解析为 `127.0.0.1`。
- 如需远程访问，可设置插件的 `viewerBaseUrl`、在每次调用时传入 `baseUrl`，或将 `gateway.bind=custom` 与 `gateway.customBindHost` 配合使用。
- 如果 `gateway.trustedProxies` 包含用于同主机代理的 local loopback（例如 Tailscale Serve），则根据设计，不带转发客户端 IP 标头的原始 local loopback 查看器请求会以失败关闭。
- 对于该代理拓扑，优先使用 `mode: "file"`/`"both"` 作为附件；或者有意启用 `security.allowRemoteViewer`，并配合插件的 `viewerBaseUrl`/代理的 `baseUrl`，以提供可共享的查看器链接。
- 仅当确实需要外部查看器访问时，才启用 `security.allowRemoteViewer`。

</details>

<details>
<summary>未修改行没有展开按钮</summary>

如果补丁输入缺少可展开的上下文，这是预期行为，并非查看器故障。

</details>

<details>
<summary>找不到工件</summary>

- 工件因 TTL 到期。
- 令牌或路径已更改。
- 清理操作移除了陈旧数据。

</details>

## 操作指南

- 在画布中进行本地交互式审查时，优先使用 `mode: "view"`。
- 对于需要附件的出站聊天渠道，优先使用 `mode: "file"`。
- 除非部署需要远程查看器 URL，否则请保持 `allowRemoteViewer` 禁用。
- 对于敏感 diff，请显式设置较短的 `ttlSeconds`。
- 非必要时，避免在 diff 输入中发送机密信息。
- 如果你的渠道会大幅压缩图像（例如 Telegram 或 WhatsApp），请优先使用 PDF 输出（`fileFormat: "pdf"`）。

<div class="callout callout-note">

Diff 渲染引擎由 [Diffs](https://diffs.com) 提供支持。

</div>

## 相关内容

- [浏览器](https://funcoding.ai/agents/openclaw/tools/browser/)
- [插件](https://funcoding.ai/agents/openclaw/tools/plugin/)
- [工具概览](https://funcoding.ai/agents/openclaw/tools/)
