跳到內容

使用 OpenClaw Diffs 外掛:快速產出差異比對與檔案交付

每次看 AI 改完程式碼,都要對著終端機裡一堆 + 和 - 看到眼花嗎?要把這些變更清楚地呈現給使用者,或是讓 Agent 自己確認修改是否正確,其實可以更簡單。

diffs 是一個選用的 Plugin 工具,它內建了簡短的系統引導和配套技能,能將變更內容轉換為唯讀的 diff artifact,方便 Agent 處理。

它接受以下任一輸入:

  • before 與 after 文本
  • Unified patch

它可以回傳:

  • 用於 Canvas 呈現的 Gateway Viewer URL
  • 用於訊息傳送的渲染檔案路徑(PNG 或 PDF)
  • 在一次呼叫中同時回傳上述兩者

啟用後,此 Plugin 會在系統提示詞空間(system-prompt space)開頭加入簡潔的使用指南,並在 Agent 需要更完整指令時提供詳細的技能說明。

  1. 啟用 Plugin。
  2. 呼叫 diffs 並設定 mode: "view" 用於 Canvas 優先的流程。
  3. 呼叫 diffs 並設定 mode: "file" 用於聊天檔案傳送流程。
  4. 當你需要兩種成品時,呼叫 diffs 並設定 mode: "both"。
{
plugins: {
entries: {
diffs: {
enabled: true,
},
},
},
}

如果你想保持 diffs 工具啟用,但想停用其內建的系統提示詞引導,請將 plugins.entries.diffs.hooks.allowPromptInjection 設定為 false:

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

這會阻擋 Diffs Plugin 的 before_prompt_build hook,同時保留 Plugin、工具和配套技能供你使用。

如果你想同時停用引導和工具,請直接停用該 Plugin。

  1. Agent 呼叫 diffs。
  2. Agent 讀取 details 欄位。
  3. Agent 執行以下操作之一:
    • 使用 canvas present 開啟 details.viewerUrl
    • 使用 path 或 filePath 透過 message 傳送 details.filePath
    • 兩者皆執行

Before 與 After:

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

Patch:

{
"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): 在 before/after 模式下的語言覆寫提示。未知值將回退為純文字。
  • title (string): 覆寫 Viewer 標題。
  • mode ("view" | "file" | "both"): 輸出模式。預設為 Plugin 的 defaults.mode。 已棄用的別名:"image" 的行為與 "file" 相同,為了向後相容仍可接受。
  • theme ("light" | "dark"): Viewer 主題。預設為 Plugin 的 defaults.theme。
  • layout ("unified" | "split"): Diff 佈局。預設為 Plugin 的 defaults.layout。
  • expandUnchanged (boolean): 當有完整上下文時,展開未修改的區塊。僅限單次呼叫選項(非 Plugin 預設鍵值)。
  • fileFormat ("png" | "pdf"): 渲染的檔案格式。預設為 Plugin 的 defaults.fileFormat。
  • fileQuality ("standard" | "hq" | "print"): PNG 或 PDF 渲染的品質預設值。
  • fileScale (number): 裝置縮放比例覆寫 (1-4)。
  • fileMaxWidth (number): 以 CSS 像素計的最大渲染寬度 (640-2400)。
  • ttlSeconds (number): Viewer artifact 的存活時間(秒)。預設 1800,最大 21600。
  • baseUrl (string): Viewer URL 的 Origin 覆寫。必須是 http 或 https,不可包含 query 或 hash。

驗證與限制:

  • before 與 after 每個最大 512 KiB。
  • patch 最大 2 MiB。
  • path 最大 2048 bytes。
  • lang 最大 128 bytes。
  • title 最大 1024 bytes。
  • Patch 複雜度上限:最多 128 個檔案和總計 120,000 行。
  • 同時提供 patch 與 before 或 after 會被拒絕。
  • 渲染檔案安全限制(適用於 PNG 和 PDF):
    • fileQuality: "standard": 最大 8 MP (8,000,000 渲染像素)。
    • fileQuality: "hq": 最大 14 MP (14,000,000 渲染像素)。
    • fileQuality: "print": 最大 24 MP (24,000,000 渲染像素)。
    • PDF 另有最大 50 頁的限制。

該工具會在 details 下回傳結構化的元數據。

建立 Viewer 模式的共用欄位:

  • 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

模式行為摘要:

  • mode: "view": 僅包含 Viewer 欄位。
  • mode: "file": 僅包含檔案欄位,不產生 Viewer artifact。
  • mode: "both": 包含 Viewer 欄位與檔案欄位。若檔案渲染失敗,Viewer 仍會回傳並附帶 fileError。
  • Viewer 可以顯示如 N unmodified lines 的行數。
  • 這些行上的展開控制項是根據條件顯示的,並不保證適用於每種輸入類型。
  • 當渲染的 diff 具有可展開的上下文數據時(通常是 before 和 after 輸入),會出現展開控制項。
  • 對於許多 Unified patch 輸入,省略的上下文主體在解析的 patch hunk 中不可用,因此該行可能會在沒有展開控制項的情況下出現。這是預期行為。
  • expandUnchanged 僅在存在可展開上下文時生效。

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

支援的預設值:

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

明確的工具參數會覆寫這些預設值。

  • security.allowRemoteViewer (boolean, 預設為 false)
    • false: 拒絕所有對 Viewer 路由的非 loopback 請求。
    • true: 如果 tokenized 路徑有效,則允許遠端 Viewer。

範例:

{
plugins: {
entries: {
diffs: {
enabled: true,
config: {
security: {
allowRemoteViewer: false,
},
},
},
},
},
}
  • Artifact 儲存在暫存子資料夾下:$TMPDIR/openclaw-diffs。
  • Viewer artifact 元數據包含:
    • 隨機 artifact ID (20 個十六進位字元)
    • 隨機 token (48 個十六進位字元)
    • createdAt 與 expiresAt
    • 儲存的 viewer.html 路徑
  • 未指定時,預設 Viewer TTL 為 30 分鐘。
  • 最大可接受的 Viewer TTL 為 6 小時。
  • 清理工作會在 artifact 建立後伺機執行。
  • 過期的 artifact 會被刪除。
  • 當元數據缺失時,後備清理機制會移除超過 24 小時的過期資料夾。

Viewer 路由:

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

Viewer 資產:

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

Viewer 文件會根據 Viewer URL 相對解析這些資產,因此選填的 baseUrl 路徑前綴也會保留給資產請求。

URL 建構行為:

  • 如果提供了 baseUrl,則在嚴格驗證後使用。
  • 若無 baseUrl,Viewer URL 預設為 loopback 127.0.0.1。
  • 如果 Gateway 綁定模式為 custom 且設定了 gateway.customBindHost,則使用該主機。

baseUrl 規則:

  • 必須是 http:// 或 https://。
  • 拒絕 Query 和 hash。
  • 允許 Origin 加上選填的基礎路徑。

Viewer 防護:

  • 預設僅限 Loopback。
  • 具有嚴格 ID 和 Token 驗證的 Tokenized Viewer 路徑。
  • Viewer 回應的 CSP:
    • default-src 'none'
    • 僅允許來自自身的 script 和資產
    • 無對外 connect-src
  • 啟用遠端存取時的遠端錯誤限流:
    • 每 60 秒 40 次失敗
    • 60 秒鎖定 (429 Too Many Requests)

檔案渲染防護:

  • 截圖瀏覽器的請求路由預設為拒絕。
  • 僅允許來自 http://127.0.0.1/plugins/diffs/assets/* 的本地 Viewer 資產。
  • 阻擋外部網路請求。

mode: "file" 和 mode: "both" 需要 Chromium 相容的瀏覽器。

解析順序:

  1. OpenClaw 配置中的 browser.executablePath。
  2. 環境變數:
    • OPENCLAW_BROWSER_EXECUTABLE_PATH
    • BROWSER_EXECUTABLE_PATH
    • PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH
  3. 平台命令/路徑自動搜尋後備方案。

常見失敗文字:

  • 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 與選填路徑,不要包含 query/hash。
  • {field} exceeds maximum size (...)
    • 減少 payload 大小。
  • Large patch rejection
    • 減少 patch 檔案數量或總行數。

Viewer 存取問題:

  • Viewer URL 預設解析為 127.0.0.1。
  • 對於遠端存取情境,你可以:
    • 在每次工具呼叫時傳遞 baseUrl,或
    • 使用 gateway.bind=custom 並設定 gateway.customBindHost
  • 僅在你打算開放外部 Viewer 存取時才啟用 security.allowRemoteViewer。

未修改行(Unmodified-lines)沒有展開按鈕:

  • 這可能發生在 patch 輸入時,且該 patch 未攜帶可展開的上下文。
  • 這是正常現象,不代表 Viewer 故障。

找不到 Artifact:

  • Artifact 因 TTL 到期。
  • Token 或路徑已變更。
  • 清理機制移除了過期數據。
  • 在 Canvas 中進行本地互動式審查時,優先使用 mode: "view"。
  • 對於需要附件的外部聊天頻道,優先使用 mode: "file"。
  • 除非你的部署環境需要遠端 Viewer URL,否則請保持 allowRemoteViewer 停用。
  • 對於敏感的 diff,請明確設定較短的 ttlSeconds。
  • 除非必要,避免在 diff 輸入中傳送秘密資訊(Secrets)。
  • 如果你的頻道會對圖片進行強力壓縮(例如 Telegram 或 WhatsApp),建議優先選用 PDF 輸出 (fileFormat: "pdf")。

Diff 渲染引擎:

  • 由 Diffs 提供技術支援。

下一步: 想了解如何將這些工具整合到你的工作流中嗎? 你可以參考 Tools 概覽 了解更多可用工具,或是查看 Plugins 學習如何擴充功能。

有任何設定上的問題?歡迎詢問 AI Setup Assistant!

OpenClaw

OpenClaw Expert

還是卡住了?

如果這篇文件沒有解決你的情境,直接問 OpenClaw Expert,拿到可執行步驟。