Diffs
diffs は、簡潔な組み込みシステムガイダンスとコンパニオンスキルを備えたオプションのプラグインツールで、変更内容を読み取り専用の diff アーティファクトとしてエージェントに提供します。
入力として以下のいずれかを受け付けます:
beforeとafterテキスト- 統一形式の
patch
出力として以下を返せます:
- キャンバス表示用の Gateway ビューア URL
- メッセージ配信用のレンダリングファイルパス(PNG または PDF)
- 1 回の呼び出しで両方の出力
有効にすると、プラグインはシステムプロンプトに簡潔な使い方のガイダンスを追加し、エージェントがより詳細な指示を必要とする場合のために詳細なスキルも公開します。
クイックスタート
- プラグインを有効にする。
- キャンバス優先のフローには
diffsをmode: "view"で呼び出す。 - チャットファイル配信フローには
diffsをmode: "file"で呼び出す。 - 両方のアーティファクトが必要な場合は
diffsをmode: "both"で呼び出す。
プラグインを有効にする
{
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フィールドを読み取る。 - エージェントが以下のいずれかを実行:
details.viewerUrlをcanvas presentで開くdetails.filePathをmessageのpathまたはfilePathで送信- 両方を実行
入力例
before と after:
{
"before": "# Hello\n\nOne",
"after": "# Hello\n\nTwo",
"path": "docs/example.md",
"mode": "view"
}
パッチ:
{
"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): 完全なコンテキストが利用可能な場合に未変更セクションを展開。呼び出しごとのオプションのみ(プラグインデフォルトキーではない)。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でなければならず、クエリ/ハッシュは不可。
バリデーションと制限:
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(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 入力では一般的)。
- 多くの統一パッチ入力では、省略されたコンテキスト本体がパースされたパッチハンクに含まれないため、展開コントロールなしで行が表示されることがある。これは期待通りの動作。
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: トークン付きパスが有効であればリモートビューアを許可。
例:
{
plugins: {
entries: {
diffs: {
enabled: true,
config: {
security: {
allowRemoteViewer: false,
},
},
},
},
},
}
アーティファクトのライフサイクルとストレージ
- アーティファクトは一時サブフォルダ
$TMPDIR/openclaw-diffsに保存。 - ビューアアーティファクトのメタデータには以下を含む:
- ランダムなアーティファクト ID(16 進数 20 文字)
- ランダムなトークン(16 進数 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://でなければならない。- クエリとハッシュは拒否される。
- オリジン+任意のベースパスが許可される。
セキュリティモデル
ビューアの堅牢化:
- デフォルトでループバック専用。
- 厳密な ID とトークンバリデーション付きのトークン化ビューアパス。
- ビューアレスポンス CSP:
default-src 'none'- スクリプトとアセットは 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)オリジン+任意のパスを使用、クエリ/ハッシュは不可。
{field} exceeds maximum size (...)- ペイロードサイズを削減。
- 大きなパッチの拒否
- パッチのファイル数または合計行数を削減。
ビューアのアクセス問題:
- ビューア URL はデフォルトで
127.0.0.1に解決。 - リモートアクセスが必要な場合:
- ツール呼び出しごとに
baseUrlを指定するか、 gateway.bind=customとgateway.customBindHostを使用
- ツール呼び出しごとに
- 外部ビューアアクセスを意図する場合のみ
security.allowRemoteViewerを有効化。
未変更行に展開ボタンがない:
- パッチ入力にて展開可能なコンテキストがない場合に発生する可能性がある。
- これは期待通りの動作であり、ビューアの障害ではない。
アーティファクトが見つからない:
- TTL により期限切れ。
- トークンまたはパスが変更された。
- クリーンアップにより古いデータが削除された。
運用ガイダンス
- キャンバスでのローカル対話レビューには
mode: "view"を推奨。 - 添付ファイルが必要なアウトバウンドチャットチャンネルには
mode: "file"を推奨。 - デプロイメントがリモートビューア URL を必要とする場合を除き、
allowRemoteViewerは無効のまま。 - 機密性の高い diff には短い
ttlSecondsを明示的に設定。 - 不要な場合は diff 入力にシークレットを含めない。
- チャンネルが画像を強く圧縮する場合(例: Telegram や WhatsApp)、PDF 出力(
fileFormat: "pdf")を推奨。
diff レンダリングエンジン:
- Diffs により提供。