Tools
تفاوتها
diffs یک ابزار اختیاری Plugin با راهنمایی کوتاه داخلی در system و یک skill همراه است که محتوای تغییرات را به یک artifact فقطخواندنی diff برای agentها تبدیل میکند.
این ابزار یکی از این موارد را میپذیرد:
- متن
beforeوafter - یک
patchیکپارچه
میتواند این موارد را برگرداند:
- یک URL نمایشگر Gateway برای ارائه در canvas
- یک مسیر فایل رندرشده (PNG یا PDF) برای تحویل پیام
- هر دو خروجی در یک فراخوانی
وقتی فعال باشد، Plugin راهنمایی کاربردی مختصر را به فضای system-prompt اضافه میکند و همچنین برای مواردی که agent به دستورالعملهای کاملتر نیاز دارد، یک skill تفصیلی ارائه میدهد.
شروع سریع
نصب Plugin
openclaw plugins install diffs
فعالسازی Plugin
{
plugins: {
entries: {
diffs: {
enabled: true,
},
},
},
}
انتخاب یک حالت
view
جریانهای canvas-first: agentها diffs را با mode: "view" فراخوانی میکنند و details.viewerUrl را با canvas present باز میکنند.
file
تحویل فایل در گفتگو: agentها diffs را با mode: "file" فراخوانی میکنند و details.filePath را با message و با استفاده از path یا filePath ارسال میکنند.
both
ترکیبی: agentها diffs را با mode: "both" فراخوانی میکنند تا هر دو artifact را در یک فراخوانی دریافت کنند.
غیرفعالسازی راهنمایی داخلی system
اگر میخواهید ابزار diffs فعال بماند اما راهنمایی داخلی system-prompt آن غیرفعال شود، plugins.entries.diffs.hooks.allowPromptInjection را روی false تنظیم کنید:
{
plugins: {
entries: {
diffs: {
enabled: true,
hooks: {
allowPromptInjection: false,
},
},
},
},
}
این کار hook با نام before_prompt_build در Pluginِ diffs را مسدود میکند، در حالی که Plugin، ابزار و skill همراه همچنان در دسترس میمانند.
اگر میخواهید هم راهنمایی و هم ابزار را غیرفعال کنید، خود Plugin را غیرفعال کنید.
گردشکار معمول agent
فراخوانی diffs
agent ابزار diffs را با ورودی فراخوانی میکند.
خواندن details
agent فیلدهای details را از پاسخ میخواند.
ارائه
agent یا details.viewerUrl را با canvas present باز میکند، یا details.filePath را با message و با استفاده از path یا filePath ارسال میکند، یا هر دو کار را انجام میدهد.
نمونههای ورودی
قبل و بعد
{
"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"
}
مرجع ورودی ابزار
همه فیلدها اختیاری هستند، مگر اینکه ذکر شده باشد.
beforestringمتن اصلی. وقتی patch حذف شده باشد، همراه با after الزامی است.
afterstringمتن بهروزشده. وقتی patch حذف شده باشد، همراه با before الزامی است.
patchstringمتن diff یکپارچه. با before و after ناسازگار و متقابلاً انحصاری است.
pathstringنام فایل نمایشی برای حالت قبل و بعد.
langstringراهنمای بازنویسی زبان برای حالت قبل و بعد. مقدارهای ناشناخته به متن ساده برمیگردند.
titlestringبازنویسی عنوان نمایشگر.
mode"view" | "file" | "both"حالت خروجی. مقدار پیشفرض برابر با پیشفرض Plugin یعنی defaults.mode است. نام مستعار منسوخ: "image" مانند "file" رفتار میکند و همچنان برای سازگاری با نسخههای قبلی پذیرفته میشود.
theme"light" | "dark"پوسته نمایشگر. مقدار پیشفرض برابر با پیشفرض Plugin یعنی defaults.theme است.
layout"unified" | "split"چیدمان diff. مقدار پیشفرض برابر با پیشفرض Plugin یعنی defaults.layout است.
expandUnchangedbooleanوقتی زمینه کامل در دسترس باشد، بخشهای بدون تغییر را باز میکند. فقط گزینهای برای هر فراخوانی است (کلید پیشفرض Plugin نیست).
fileFormat"png" | "pdf"قالب فایل رندرشده. مقدار پیشفرض برابر با پیشفرض Plugin یعنی defaults.fileFormat است.
fileQuality"standard" | "hq" | "print"preset کیفیت برای رندر PNG یا PDF.
fileScalenumberبازنویسی مقیاس دستگاه (1-4).
fileMaxWidthnumberبیشینه عرض رندر بر حسب پیکسل CSS (640-2400).
ttlSecondsnumberTTL artifact بر حسب ثانیه برای خروجیهای نمایشگر و فایل مستقل. حداکثر 21600.
baseUrlstringبازنویسی origin برای URL نمایشگر. مقدار viewerBaseUrl در Plugin را بازنویسی میکند. باید 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 صفحه دارد.
قرارداد جزئیات خروجی
ابزار metadata ساختیافته را زیر details برمیگرداند.
فیلدهای نمایشگر
فیلدهای مشترک برای حالتهایی که نمایشگر میسازند:
artifactIdviewerUrlviewerPathtitleexpiresAtinputKindfileCountmodecontext(agentId،sessionId،messageChannel،agentAccountIdوقتی در دسترس باشد)
فیلدهای فایل
فیلدهای فایل وقتی PNG یا PDF رندر میشود:
artifactIdexpiresAtfilePathpath(همان مقدارfilePath، برای سازگاری با ابزار message)fileBytesfileFormatfileQualityfileScalefileMaxWidth
نامهای مستعار سازگاری
برای فراخوانهای موجود نیز برگردانده میشود:
format(همان مقدارfileFormat)imagePath(همان مقدارfilePath)imageBytes(همان مقدارfileBytes)imageQuality(همان مقدارfileQuality)imageScale(همان مقدارfileScale)imageMaxWidth(همان مقدارfileMaxWidth)
خلاصه رفتار حالتها:
| حالت | آنچه برگردانده میشود |
|---|---|
"view" |
فقط فیلدهای نمایشگر. |
"file" |
فقط فیلدهای فایل، بدون artifact نمایشگر. |
"both" |
فیلدهای نمایشگر بههمراه فیلدهای فایل. اگر رندر فایل شکست بخورد، نمایشگر همچنان با fileError و نام مستعار imageError برمیگردد. |
بخشهای بدون تغییر جمعشده
- نمایشگر میتواند ردیفهایی مانند
N unmodified linesنشان دهد. - کنترلهای باز کردن روی آن ردیفها شرطی هستند و برای هر نوع ورودی تضمین نمیشوند.
- کنترلهای باز کردن زمانی ظاهر میشوند که diff رندرشده داده زمینه قابل باز شدن داشته باشد، که برای ورودی قبل و بعد معمول است.
- برای بسیاری از ورودیهای patch یکپارچه، بدنههای زمینه حذفشده در hunkهای patch تجزیهشده در دسترس نیستند، بنابراین ردیف میتواند بدون کنترلهای باز کردن ظاهر شود. این رفتار مورد انتظار است.
expandUnchangedفقط وقتی اعمال میشود که زمینه قابل باز شدن وجود داشته باشد.
پیشفرضهای Plugin
پیشفرضهای سراسری Plugin را در ~/.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
پارامترهای صریح ابزار این پیشفرضها را بازنویسی میکنند.
پیکربندی URL نمایشگر پایدار
viewerBaseUrlstringfallback متعلق به Plugin برای لینکهای نمایشگر برگشتی وقتی فراخوانی ابزار baseUrl را پاس نمیدهد. باید http یا https باشد، بدون query/hash.
{
plugins: {
entries: {
diffs: {
enabled: true,
config: {
viewerBaseUrl: "https://gateway.example.com/openclaw",
},
},
},
},
}
پیکربندی امنیت
security.allowRemoteViewerbooleanfalse: درخواستهای غیر loopback به routeهای نمایشگر رد میشوند. true: اگر مسیر tokenized معتبر باشد، نمایشگرهای remote مجاز هستند.
{
plugins: {
entries: {
diffs: {
enabled: true,
config: {
security: {
allowRemoteViewer: false,
},
},
},
},
},
}
چرخه عمر و ذخیرهسازی artifact
- artifactها زیر زیرپوشه موقت ذخیره میشوند:
$TMPDIR/openclaw-diffs. - metadata مربوط به artifact نمایشگر شامل این موارد است:
- شناسه artifact تصادفی (20 کاراکتر hex)
- token تصادفی (48 کاراکتر hex)
createdAtوexpiresAt- مسیر ذخیرهشده
viewer.html
- وقتی مشخص نشده باشد، TTL پیشفرض artifact برابر با 30 دقیقه است.
- بیشینه TTL پذیرفتهشده برای نمایشگر 6 ساعت است.
- پاکسازی پس از ایجاد artifact بهصورت فرصتطلبانه اجرا میشود.
- artifactهای منقضیشده حذف میشوند.
- پاکسازی fallback وقتی metadata موجود نباشد، پوشههای کهنهتر از 24 ساعت را حذف میکند.
URL نمایشگر و رفتار شبکه
route نمایشگر:
/plugins/diffs/view/{artifactId}/{token}
assetهای نمایشگر:
/plugins/diffs/assets/viewer.js/plugins/diffs/assets/viewer-runtime.js
سند نمایشگر این assetها را نسبت به URL نمایشگر resolve میکند، بنابراین پیشوند مسیر اختیاری baseUrl برای درخواستهای asset نیز حفظ میشود.
رفتار ساخت URL:
- اگر
baseUrlدر فراخوانی ابزار ارائه شده باشد، پس از اعتبارسنجی سختگیرانه استفاده میشود. - در غیر این صورت، اگر
viewerBaseUrlدر Plugin پیکربندی شده باشد، از آن استفاده میشود. - بدون هیچیک از بازنویسیها، URL نمایشگر بهصورت پیشفرض به loopback
127.0.0.1تنظیم میشود. - اگر حالت bind در Gateway برابر
customباشد وgateway.customBindHostتنظیم شده باشد، از آن host استفاده میشود.
قواعد baseUrl:
- باید
http://یاhttps://باشد. - query و hash رد میشوند.
- origin بههمراه مسیر پایه اختیاری مجاز است.
مدل امنیتی
سختسازی نمایشگر
- بهطور پیشفرض فقط local loopback.
- مسیرهای نمایشگر دارای توکن، با اعتبارسنجی سختگیرانه شناسه و توکن.
- CSP پاسخ نمایشگر:
default-src 'none'- اسکریپتها و داراییها فقط از خود منبع
- بدون
connect-srcخروجی
- محدودسازی خطاهای راه دور هنگام فعال بودن دسترسی راه دور:
- 40 خطا در هر 60 ثانیه
- قفلشدن 60 ثانیهای (
429 Too Many Requests)
سختسازی رندر فایل
- مسیریابی درخواستهای مرورگر اسکرینشات بهصورت پیشفرض deny-by-default است.
- فقط داراییهای نمایشگر محلی از
http://127.0.0.1/plugins/diffs/assets/*مجاز هستند. - درخواستهای شبکه خارجی مسدود میشوند.
نیازمندیهای مرورگر برای حالت فایل
mode: "file" و mode: "both" به مرورگر سازگار با Chromium نیاز دارند.
ترتیب حلوفصل:
پیکربندی
browser.executablePath در پیکربندی OpenClaw.
متغیرهای محیطی
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)با مسیر اختیاری استفاده کنید، بدون query/hash.{field} exceeds maximum size (...)— اندازه payload را کاهش دهید.- رد شدن patch بزرگ — تعداد فایلهای patch یا مجموع خطوط را کاهش دهید.
دسترسپذیری نمایشگر
- URL نمایشگر بهطور پیشفرض به
127.0.0.1resolve میشود. - برای سناریوهای دسترسی راه دور، یکی از این کارها را انجام دهید:
viewerBaseUrlمربوط به Plugin را تنظیم کنید، یا- در هر فراخوانی ابزار
baseUrlرا ارسال کنید، یا - از
gateway.bind=customوgateway.customBindHostاستفاده کنید
- اگر
gateway.trustedProxiesشامل loopback برای یک پروکسی همان میزبان باشد (برای مثال Tailscale Serve)، درخواستهای خام نمایشگر از loopback بدون هدرهای client-IP فورواردشده، طبق طراحی fail closed میشوند. - برای آن توپولوژی پروکسی:
- وقتی فقط به یک پیوست نیاز دارید،
mode: "file"یاmode: "both"را ترجیح دهید، یا - وقتی به URL نمایشگر قابل اشتراکگذاری نیاز دارید، عمداً
security.allowRemoteViewerرا فعال کنید وviewerBaseUrlمربوط به Plugin را تنظیم کنید یا یکbaseUrlپروکسی/عمومی ارسال کنید
- وقتی فقط به یک پیوست نیاز دارید،
security.allowRemoteViewerرا فقط زمانی فعال کنید که قصد دسترسی خارجی به نمایشگر را دارید.
ردیف خطوط تغییرنکرده دکمه باز کردن ندارد
این وضعیت میتواند برای ورودی patch رخ دهد، وقتی patch زمینه قابل گسترش همراه ندارد. این مورد مورد انتظار است و نشاندهنده خرابی نمایشگر نیست.
Artifact پیدا نشد
- Artifact به دلیل TTL منقضی شده است.
- توکن یا مسیر تغییر کرده است.
- پاکسازی دادههای کهنه را حذف کرده است.
راهنمای عملیاتی
- برای بازبینیهای تعاملی محلی در canvas،
mode: "view"را ترجیح دهید. - برای کانالهای گفتوگوی خروجی که به پیوست نیاز دارند،
mode: "file"را ترجیح دهید. allowRemoteViewerرا غیرفعال نگه دارید، مگر اینکه deployment شما به URLهای نمایشگر راه دور نیاز داشته باشد.- برای diffهای حساس،
ttlSecondsکوتاه و صریح تنظیم کنید. - وقتی لازم نیست، از ارسال اسرار در ورودی diff خودداری کنید.
- اگر کانال شما تصاویر را شدیداً فشرده میکند (برای مثال Telegram یا WhatsApp)، خروجی PDF (
fileFormat: "pdf") را ترجیح دهید.