Diffs
diffs 是一個選用的外掛工具,內建簡短的系統引導說明,並附帶一個輔助技能,可將變更內容轉換為代理的唯讀 diff 成品。
它接受:
before和after文字- 統一格式的
patch
它可以回傳:
- Gateway 檢視器 URL,供 canvas 呈現
- 渲染後的檔案路徑(PNG 或 PDF),供訊息投遞
- 單次呼叫同時產生兩種輸出
啟用後,外掛會將簡潔的使用引導注入系統提示空間,同時公開一個詳細的技能,供代理需要更完整指示時使用。
快速上手
- 啟用外掛。
- 以
mode: "view"呼叫diffs,適用於以 canvas 為主的流程。 - 以
mode: "file"呼叫diffs,適用於聊天檔案投遞流程。 - 以
mode: "both"呼叫diffs,同時需要兩種成品時使用。
啟用外掛
{
plugins: {
entries: {
diffs: {
enabled: true,
},
},
},
}
停用內建系統引導
如果你想保留 diffs 工具但停用其內建的系統提示引導,將 plugins.entries.diffs.hooks.allowPromptInjection 設為 false:
{
plugins: {
entries: {
diffs: {
enabled: true,
hooks: {
allowPromptInjection: false,
},
},
},
},
}
這會阻擋 diffs 外掛的 before_prompt_build 鉤子,同時保留外掛、工具和輔助技能可用。
如果你想同時停用引導和工具,請直接停用外掛。
典型的代理工作流程
- 代理呼叫
diffs。 - 代理讀取
details欄位。 - 代理選擇:
- 以
canvas present開啟details.viewerUrl - 以
message透過path或filePath傳送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):統一格式的 diff 文字。與before和after互斥。path(string):before 和 after 模式的顯示檔名。lang(string):before 和 after 模式的語言覆寫提示。title(string):檢視器標題覆寫。mode("view" | "file" | "both"):輸出模式。預設為外掛的defaults.mode。theme("light" | "dark"):檢視器主題。預設為外掛的defaults.theme。layout("unified" | "split"):diff 版面。預設為外掛的defaults.layout。expandUnchanged(boolean):在有完整上下文時展開未變更的區段。僅限單次呼叫選項(不是外掛預設 key)。fileFormat("png" | "pdf"):渲染的檔案格式。預設為外掛的defaults.fileFormat。fileQuality("standard" | "hq" | "print"):PNG 或 PDF 渲染的品質預設。fileScale(number):裝置縮放覆寫(1-4)。fileMaxWidth(number):最大渲染寬度,CSS 像素(640-2400)。ttlSeconds(number):檢視器成品的 TTL 秒數。預設 1800,最大 21600。baseUrl(string):檢視器 URL 來源覆寫。必須是http或https,不可有查詢字串 / hash。
驗證和限制:
before和after各自最大 512 KiB。patch最大 2 MiB。path最大 2048 bytes。lang最大 128 bytes。title最大 1024 bytes。- Patch 複雜度上限:最多 128 個檔案和 120000 總行數。
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 合約
工具在 details 底下回傳結構化的元資料。
建立檢視器的模式共用欄位:
artifactIdviewerUrlviewerPathtitleexpiresAtinputKindfileCountmode
渲染 PNG 或 PDF 時的檔案欄位:
filePathpath(與filePath相同,供 message 工具相容)fileBytesfileFormatfileQualityfileScalefileMaxWidth
模式行為摘要:
mode: "view":僅檢視器欄位。mode: "file":僅檔案欄位,不建立檢視器成品。mode: "both":檢視器欄位加檔案欄位。如果檔案渲染失敗,檢視器仍會回傳並附帶fileError。
折疊的未變更區段
- 檢視器可能顯示
N unmodified lines之類的行。 - 這些行上的展開控制項是有條件的,不保證每種輸入都有。
- 當渲染的 diff 有可展開的上下文資料時才會出現展開控制項,通常在 before 和 after 輸入時出現。
- 對於許多統一 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",
},
},
},
},
},
}
支援的預設值:
fontFamilyfontSizelineSpacinglayoutshowLineNumbersdiffIndicatorswordWrapbackgroundthemefileFormatfileQualityfileScalefileMaxWidthmode
明確的工具參數會覆寫這些預設值。
安全性設定
security.allowRemoteViewer(boolean,預設false)false:拒絕非回環的檢視器路由請求。true:如果 token 化路徑有效則允許遠端檢視器。
範例:
{
plugins: {
entries: {
diffs: {
enabled: true,
config: {
security: {
allowRemoteViewer: false,
},
},
},
},
},
}
成品生命週期和儲存
- 成品儲存在暫存子資料夾:
$TMPDIR/openclaw-diffs。 - 檢視器成品的元資料包含:
- 隨機成品 ID(20 個十六進位字元)
- 隨機 token(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
URL 建構行為:
- 如果提供了
baseUrl,經過嚴格驗證後使用。 - 未提供
baseUrl時,檢視器 URL 預設為回環127.0.0.1。 - 如果 Gateway 繫結模式為
custom且設定了gateway.customBindHost,則使用該主機。
baseUrl 規則:
- 必須是
http://或https://。 - 查詢字串和 hash 會被拒絕。
- 允許 origin 加上選用的基底路徑。
安全模型
檢視器加固:
- 預設僅限回環。
- token 化的檢視器路徑,嚴格驗證 ID 和 token。
- 檢視器回應 CSP:
default-src 'none'- scripts 和 assets 僅從 self
- 無對外
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_PATHBROWSER_EXECUTABLE_PATHPLAYWRIGHT_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。 - 遠端存取情境:
- 每次工具呼叫傳入
baseUrl,或 - 使用
gateway.bind=custom和gateway.customBindHost
- 每次工具呼叫傳入
- 僅在需要外部檢視器存取時才啟用
security.allowRemoteViewer。
未變更行沒有展開按鈕:
- patch 輸入不帶可展開上下文時可能發生。
- 這是預期行為,不表示檢視器故障。
成品找不到:
- 成品因 TTL 過期。
- Token 或路徑已變更。
- 清理機制移除了過期資料。
操作建議
- 本地互動式審閱建議使用
mode: "view",在 canvas 中檢視。 - 需要附件的外部聊天頻道建議使用
mode: "file"。 - 除非部署環境需要遠端檢視器 URL,否則保持
allowRemoteViewer停用。 - 敏感的 diff 設定較短的明確
ttlSeconds。 - 非必要時避免在 diff 輸入中傳送機密資料。
- 如果你的頻道會積極壓縮圖片(例如 Telegram 或 WhatsApp),建議使用 PDF 輸出(
fileFormat: "pdf")。
Diff 渲染引擎:
- 由 Diffs 驅動。