快速开始

Diffs

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

输入: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,并通过 message 使用 pathfilePath 发送 details.filePath

    both

    组合模式(默认):智能体使用 mode: "both" 调用 diffs,在一次调用中获取两种工件。

  • 禁用内置系统指导

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

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

    这会阻止插件的 before_prompt_build 钩子,同时仍保留工具和 Skill。若要同时禁用指导和工具,请改为禁用插件。

    工具输入参考

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

    beforestring

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

    afterstring

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

    patchstring

    统一 diff 文本。与 beforeafter 互斥。

    pathstring

    前后对比模式下显示的文件名。

    langstring

    前后对比模式下的语言覆盖提示。未知值和默认查看器集合之外的语言会回退为纯文本,除非已安装 Diff Viewer Language Pack 插件。

    titlestring

    覆盖查看器标题。

    mode"view" | "file" | "both"

    输出模式。默认为插件默认值 defaults.modeboth)。已弃用的别名:"image" 的行为与 "file" 完全相同。

    theme"light" | "dark"

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

    layout"unified" | "split"

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

    expandUnchangedboolean

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

    fileFormat"png" | "pdf"

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

    fileQuality"standard" | "hq" | "print"

    PNG/PDF 渲染的质量预设。

    fileScalenumber

    设备缩放比例覆盖值(1-4)。

    fileMaxWidthnumber

    以 CSS 像素为单位的最大渲染宽度(640-2400)。

    ttlSecondsnumberdefault: 1800

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

    baseUrlstring

    查看器 URL 来源覆盖值。覆盖插件的 viewerBaseUrl。必须为 httphttps,且不得包含查询参数或哈希。

    验证和限制
    • before/after:每个最大 512 KiB。
    • patch:最大 2 MiB。
    • path:最大 2048 字节。
    • lang:最大 128 字节。
    • title:最大 1024 字节。
    • 补丁复杂度上限:最多 128 个文件,总行数最多 120000 行。
    • 同时提供 patchbefore/after 会被拒绝。
    • 渲染文件的安全限制(PNG 和 PDF):
      • fileQuality: "standard":最大 8 MP(8,000,000 个渲染像素)。
      • fileQuality: "hq":最大 14 MP。
      • fileQuality: "print":最大 24 MP。
      • PDF 还限制为最多 50 页。

    语法高亮

    内置语言:

    javascripttypescripttsxjsxjsonmarkdownyamlcsshtmlshpythongorustjavaccppcsharpphpsqldockerrubyswiftkotlinrdartluapowershellxmltoml

    常见别名(jstsbashmdymlc++dockerfilerbktps1 等)会规范化为这些语言。

    安装 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 插件Shiki 语言

    输出详情契约

    所有成功结果都包含 changed:如果前后输入相同,则返回 false 且不创建工件;渲染后的结果返回 true

    查看器字段(view 和 both 模式)
    • changed
    • artifactId
    • viewerUrl
    • viewerPath
    • title
    • expiresAt
    • inputKind
    • fileCount
    • mode
    • context(可用时包含 agentIdsessionIdmessageChannelagentAccountId
    文件字段(file 和 both 模式)
    • changed
    • artifactId
    • expiresAt
    • filePath
    • path(与 filePath 的值相同,用于兼容消息工具)
    • fileBytes
    • fileFormat
    • fileQuality
    • fileScale
    • fileMaxWidth
    模式 返回内容
    "view" 仅查看器字段。
    "file" 仅文件字段,不创建查看器工件。
    "both" 查看器字段加文件字段。如果文件渲染失败,查看器仍会返回,并包含 fileError

    折叠的未更改部分

    查看器会显示类似 N unmodified lines 的行。仅当渲染后的差异包含可展开的上下文数据时(通常见于 before/after 输入),才会出现展开控件。许多统一格式补丁的区块中不包含上下文正文,因此可能会出现该行但没有展开控件——这是预期行为,并非错误。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 键:fontFamilyfontSizelineSpacinglayoutshowLineNumbersdiffIndicatorswordWrapbackgroundthemefileFormatfileQualityfileScalefileMaxWidthmodettlSeconds。显式的工具调用参数会覆盖这些默认值。

    持久化查看器 URL 配置

    viewerBaseUrlstring

    当工具调用未传入 baseUrl 时,用于返回查看器链接的插件自有回退值。必须使用 httphttps,且不得包含查询字符串或哈希片段。

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

    安全配置

    security.allowRemoteViewerbooleandefault: false

    false:拒绝对查看器路由的非回环请求。true:如果带令牌的路径有效,则允许远程查看器访问。

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

    工件生命周期和存储

    • 工件位于 $TMPDIR/openclaw-diffs 下。
    • 查看器元数据存储一个随机的 20 位十六进制字符工件 ID、一个随机的 48 位十六进制字符令牌、createdAt/expiresAt,以及已存储的 viewer.html 路径。
    • 默认工件 TTL:30 分钟。可接受的最大 TTL:6 小时。
    • 每次创建工件调用后都会择机运行清理;过期工件将被删除。
    • 元数据缺失时,后备清理会移除早于 24 小时的陈旧文件夹。

    查看器 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://;不允许查询字符串和哈希;允许使用源站加可选的基础路径。

    安全模型

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

    文件模式的浏览器要求

    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,或者设置上述任一可执行文件路径选项,即可修复。

    故障排查

    输入验证错误
    • Provide patch or both before and after text.——同时提供 beforeafter,或者提供 patch
    • Provide either patch or before/after input, not both.——不要混用输入模式。
    • Invalid baseUrl: ...——使用可带路径但不含查询参数或哈希的 http(s) 源。
    • {field} exceeds maximum size (...)——减小负载大小。
    • 大型补丁被拒绝——减少补丁文件数量或总行数。
    查看器可访问性
    • 默认情况下,查看器 URL 解析为 127.0.0.1
    • 如需远程访问,可以设置插件的 viewerBaseUrl、在每次调用中传入 baseUrl,或将 gateway.bind=customgateway.customBindHost 搭配使用。
    • 如果 gateway.trustedProxies 针对同一主机上的代理(例如 Tailscale Serve)包含环回地址,则不带转发客户端 IP 标头的原始环回查看器请求会按设计以失败关闭方式处理。
    • 对于这种代理拓扑,优先使用 mode: "file"/"both" 来提供附件;或者有意启用 security.allowRemoteViewer,并配合插件的 viewerBaseUrl/代理的 baseUrl 来生成可共享的查看器链接。
    • 仅在确实需要外部查看器访问时启用 security.allowRemoteViewer
    未修改行所在行没有展开按钮

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

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

    运维指导

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

    相关内容

    Was this useful?
    On this page

    On this page