Diffs
diffs は任意の plugin ツールで、短い組み込みのシステムガイダンスと、変更内容をエージェント向けの読み取り専用 diff アーティファクトに変換する companion skill を備えています。
受け付ける入力は次のいずれかです。
beforeとafterのテキスト- unified
patch
- canvas 表示用の Gateway ビューアー URL
- メッセージ配信用のレンダリング済みファイルパス(PNG または PDF)
- 1回の呼び出しで両方の出力
クイックスタート
- plugin を有効化します。
- canvas 優先のフローでは
mode: "view"でdiffsを呼び出します。 - チャットへのファイル配信フローでは
mode: "file"でdiffsを呼び出します。 - 両方のアーティファクトが必要な場合は
mode: "both"でdiffsを呼び出します。
plugin を有効化する
組み込みのシステムガイダンスを無効化する
diffs ツールは有効のまま、組み込みの system-prompt ガイダンスだけを無効にしたい場合は、plugins.entries.diffs.hooks.allowPromptInjection を false に設定してください。
before_prompt_build hook がブロックされます。
ガイダンスとツールの両方を無効にしたい場合は、代わりに plugin を無効化してください。
一般的なエージェントのワークフロー
- エージェントが
diffsを呼び出す。 - エージェントが
detailsフィールドを読む。 - エージェントは次のいずれかを行う。
canvas presentでdetails.viewerUrlを開くpathまたはfilePathを使ってmessageでdetails.filePathを送る- 両方を行う
入力例
Before と after:ツール入力リファレンス
特記がない限り、すべてのフィールドは任意です。before(string): 元のテキスト。patchを省略する場合、afterと組で必須です。after(string): 更新後のテキスト。patchを省略する場合、beforeと組で必須です。patch(string): unified diff テキスト。beforeおよびafterとは排他的です。path(string): before/after モード向けの表示用ファイル名。lang(string): before/after モード向けの言語上書きヒント。不明な値は plain text にフォールバックします。title(string): ビューアーのタイトル上書き。mode("view" | "file" | "both"): 出力モード。デフォルトは plugin 既定値defaults.mode。 非推奨エイリアス:"image"は"file"と同様に動作し、後方互換性のため引き続き受け付けられます。theme("light" | "dark"): ビューアーテーマ。デフォルトは 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): ビューアーおよび単独ファイル出力のアーティファクト TTL(秒)。デフォルトは 1800、最大は 21600。baseUrl(string): ビューアー URL origin の上書き。plugin のviewerBaseUrlを上書きします。httpまたはhttpsでなければならず、query/hash は不可です。
format->fileFormatimageFormat->fileFormatimageQuality->fileQualityimageScale->fileScaleimageMaxWidth->fileMaxWidth
beforeとafterはそれぞれ最大 512 KiB。patchは最大 2 MiB。pathは最大 2048 バイト。langは最大 128 バイト。titleは最大 1024 バイト。- 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 の下に返します。
ビューアーを作成するモードで共通のフィールド:
artifactIdviewerUrlviewerPathtitleexpiresAtinputKindfileCountmodecontext(利用可能な場合はagentId、sessionId、messageChannel、agentAccountId)
artifactIdexpiresAtfilePathpath(filePathと同じ値。message ツール互換用)fileBytesfileFormatfileQualityfileScalefileMaxWidth
format(fileFormatと同じ値)imagePath(filePathと同じ値)imageBytes(fileBytesと同じ値)imageQuality(fileQualityと同じ値)imageScale(fileScaleと同じ値)imageMaxWidth(fileMaxWidthと同じ値)
mode: "view": ビューアーフィールドのみ。mode: "file": ファイルフィールドのみ。ビューアーアーティファクトなし。mode: "both": ビューアーフィールドに加えてファイルフィールドも返します。ファイルレンダリングに失敗しても、fileErrorと互換エイリアスimageErrorを付けてビューアーは返されます。
折りたたまれた未変更セクション
- ビューアーには
N unmodified linesのような行が表示される場合があります。 - それらの行の展開コントロールは条件付きであり、すべての入力種別で保証されるわけではありません。
- 展開コントロールは、レンダリングされた diff に展開可能な文脈データがある場合に表示されます。これは before/after 入力で一般的です。
- 多くの unified patch 入力では、省略された文脈本文は解析済み patch hunk に存在しないため、その行は展開コントロールなしで表示されることがあります。これは想定された動作です。
expandUnchangedは、展開可能な文脈が存在する場合にのみ適用されます。
plugin の既定値
plugin 全体の既定値は~/.openclaw/openclaw.json で設定します。
fontFamilyfontSizelineSpacinglayoutshowLineNumbersdiffIndicatorswordWrapbackgroundthemefileFormatfileQualityfileScalefileMaxWidthmode
viewerBaseUrl(string, optional)- ツール呼び出しで
baseUrlが渡されなかった場合に、返却されるビューアーリンクに使われる plugin 所有のフォールバック。 httpまたはhttpsでなければならず、query/hash は不可です。
- ツール呼び出しで
セキュリティ設定
security.allowRemoteViewer(boolean, デフォルトfalse)false: ビューアールートへの non-loopback リクエストは拒否されます。true: トークン付きパスが有効であれば、リモートビューアーが許可されます。
アーティファクトのライフサイクルと保存先
- アーティファクトは temp のサブフォルダ
$TMPDIR/openclaw-diffsに保存されます。 - ビューアーアーティファクトのメタデータには次が含まれます。
- ランダムなアーティファクト ID(20 hex chars)
- ランダムなトークン(48 hex chars)
createdAtとexpiresAt- 保存された
viewer.htmlパス
- アーティファクト TTL は、指定されない場合デフォルトで 30 分です。
- 受け付けるビューアー TTL の最大値は 6 時間です。
- クリーンアップはアーティファクト作成後に日和見的に実行されます。
- 期限切れアーティファクトは削除されます。
- メタデータがない場合、フォールバックのクリーンアップにより 24 時間より古い stale フォルダが削除されます。
ビューアー URL とネットワーク動作
ビューアールート:/plugins/diffs/view/{artifactId}/{token}
/plugins/diffs/assets/viewer.js/plugins/diffs/assets/viewer-runtime.js
baseUrl パス接頭辞はアセットリクエストでも保持されます。
URL 構築動作:
- ツール呼び出しの
baseUrlが指定されている場合、厳格な検証のうえでそれが使われます。 - そうでなければ、plugin の
viewerBaseUrlが設定されていればそれが使われます。 - どちらの上書きもない場合、ビューアー URL のデフォルトは loopback
127.0.0.1です。 - Gateway の bind mode が
customで、gateway.customBindHostが設定されている場合は、その host が使われます。
baseUrl のルール:
http://またはhttps://でなければなりません。- Query と hash は拒否されます。
- Origin と任意の base path は許可されます。
セキュリティモデル
ビューアーの強化:- デフォルトで loopback のみ。
- 厳格な ID および token 検証を伴うトークン化ビューアーパス。
- ビューアー応答の CSP:
default-src 'none'- scripts と assets は self のみ
- 外向きの
connect-srcなし
- リモートアクセスが有効な場合のリモート miss スロットリング:
- 60 秒あたり 40 回の失敗
- 60 秒のロックアウト(
429 Too Many Requests)
- スクリーンショットブラウザーのリクエストルーティングは deny-by-default です。
http://127.0.0.1/plugins/diffs/assets/*からのローカルビューアーアセットのみ許可されます。- 外部ネットワークリクエストはブロックされます。
file モードのブラウザー要件
mode: "file" と mode: "both" には Chromium 互換ブラウザーが必要です。
解決順序:
- OpenClaw config の
browser.executablePath。 - 環境変数:
OPENCLAW_BROWSER_EXECUTABLE_PATHBROWSER_EXECUTABLE_PATHPLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH
- プラットフォームごとのコマンド/パス探索フォールバック。
Diff PNG/PDF rendering requires a Chromium-compatible browser...
トラブルシューティング
入力検証エラー:Provide patch or both before and after text.beforeとafterの両方を含めるか、patchを指定してください。
Provide either patch or before/after input, not both.- 入力モードを混在させないでください。
Invalid baseUrl: ...- query/hash のない、任意パス付き
http(s)origin を使ってください。
- query/hash のない、任意パス付き
{field} exceeds maximum size (...)- ペイロードサイズを減らしてください。
- 大きな patch の拒否
- patch のファイル数または合計行数を減らしてください。
- ビューアー URL はデフォルトで
127.0.0.1に解決されます。 - リモートアクセスのシナリオでは、次のいずれかを行ってください。
- plugin の
viewerBaseUrlを設定する - ツール呼び出しごとに
baseUrlを渡す gateway.bind=customとgateway.customBindHostを使う
- plugin の
gateway.trustedProxiesに、同一ホスト proxy(たとえば Tailscale Serve)向けの loopback が含まれている場合、forwarded client-IP headers のない生の loopback ビューアーリクエストは、設計上 fail closed になります。- その proxy トポロジでは:
- 添付ファイルだけが必要なら
mode: "file"またはmode: "both"を優先する、または - 共有可能なビューアー URL が必要なら、意図的に
security.allowRemoteViewerを有効にし、plugin のviewerBaseUrlを設定するか、proxy/public なbaseUrlを渡してください
- 添付ファイルだけが必要なら
security.allowRemoteViewerは、外部ビューアーアクセスを意図している場合にのみ有効にしてください。
- patch 入力で、patch が展開可能な文脈を含んでいない場合に発生することがあります。
- これは想定された動作であり、ビューアー障害を示すものではありません。
- TTL によりアーティファクトが期限切れになった。
- token または path が変更された。
- クリーンアップで stale データが削除された。
運用ガイダンス
- canvas でのローカル対話レビューには
mode: "view"を優先してください。 - 添付ファイルが必要な外向きチャットチャネルには
mode: "file"を優先してください。 - デプロイでリモートビューアー URL が必要でない限り、
allowRemoteViewerは無効のままにしてください。 - 機微な diff には明示的に短い
ttlSecondsを設定してください。 - 必要ない場合は diff 入力に秘密情報を含めないでください。
- あなたのチャネルが画像を強く圧縮する場合(たとえば Telegram や WhatsApp)は、PDF 出力(
fileFormat: "pdf")を優先してください。
- Diffs を使用しています。