Tools
الفروقات
diffs هي أداة Plugin اختيارية تتضمن إرشادات نظام مدمجة موجزة وSkill مصاحبة تحول محتوى التغييرات إلى أثر فرق للقراءة فقط للوكلاء.
تقبل إما:
- نصي
beforeوafter patchموحدًا
يمكنها إرجاع:
- عنوان URL لعارض Gateway للعرض على اللوحة
- مسار ملف مُصيّر (PNG أو PDF) للتسليم عبر الرسائل
- كلا المخرجين في استدعاء واحد
عند تمكينها، تضيف Plugin إرشادات استخدام موجزة إلى مساحة موجه النظام، وتعرض أيضًا Skill مفصلة للحالات التي يحتاج فيها الوكيل إلى تعليمات أوفى.
البدء السريع
Install the plugin
openclaw plugins install diffs
Enable the plugin
{
plugins: {
entries: {
diffs: {
enabled: true,
},
},
},
}
Pick a mode
view
تدفقات تركّز على اللوحة أولًا: يستدعي الوكلاء diffs مع mode: "view" ويفتحون details.viewerUrl باستخدام canvas present.
file
تسليم ملفات الدردشة: يستدعي الوكلاء diffs مع mode: "file" ويرسلون details.filePath باستخدام message عبر path أو filePath.
both
مدمج: يستدعي الوكلاء diffs مع mode: "both" للحصول على الأثرين في استدعاء واحد.
تعطيل إرشادات النظام المدمجة
إذا أردت إبقاء أداة diffs مُمكّنة مع تعطيل إرشادات موجه النظام المدمجة الخاصة بها، فاضبط plugins.entries.diffs.hooks.allowPromptInjection على false:
{
plugins: {
entries: {
diffs: {
enabled: true,
hooks: {
allowPromptInjection: false,
},
},
},
},
}
يحظر هذا خطاف before_prompt_build الخاص بـ Plugin diffs مع إبقاء Plugin والأداة وSkill المصاحبة متاحة.
إذا أردت تعطيل كل من الإرشادات والأداة، فعطّل Plugin بدلًا من ذلك.
سير عمل الوكيل المعتاد
Call diffs
يستدعي الوكيل أداة diffs مع الإدخال.
Read details
يقرأ الوكيل حقول details من الاستجابة.
Present
إما أن يفتح الوكيل details.viewerUrl باستخدام canvas present، أو يرسل details.filePath باستخدام message عبر path أو filePath، أو يفعل الأمرين معًا.
أمثلة الإدخال
Before and 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"
}
مرجع إدخال الأداة
كل الحقول اختيارية ما لم يُذكر خلاف ذلك.
beforestringالنص الأصلي. مطلوب مع after عند حذف patch.
afterstringالنص المحدّث. مطلوب مع before عند حذف patch.
patchstringنص فرق موحد. لا يمكن استخدامه مع before وafter.
pathstringاسم الملف المعروض لوضع قبل وبعد.
langstringتلميح لتجاوز اللغة في وضع قبل وبعد. القيم غير المعروفة تعود إلى نص عادي.
titlestringتجاوز عنوان العارض.
mode"view" | "file" | "both"وضع الإخراج. القيمة الافتراضية هي إعداد Plugin الافتراضي defaults.mode. الاسم المستعار المهمل: "image" يتصرف مثل "file" وما زال مقبولًا للتوافق العكسي.
theme"light" | "dark"سمة العارض. القيمة الافتراضية هي إعداد Plugin الافتراضي defaults.theme.
layout"unified" | "split"تخطيط الفرق. القيمة الافتراضية هي إعداد Plugin الافتراضي defaults.layout.
expandUnchangedbooleanتوسيع الأقسام غير المتغيرة عندما يكون السياق الكامل متاحًا. خيار لكل استدعاء فقط (وليس مفتاحًا افتراضيًا في Plugin).
fileFormat"png" | "pdf"تنسيق الملف المُصيّر. القيمة الافتراضية هي إعداد Plugin الافتراضي defaults.fileFormat.
fileQuality"standard" | "hq" | "print"إعداد جودة مسبق لتصيير PNG أو PDF.
fileScalenumberتجاوز مقياس الجهاز (1-4).
fileMaxWidthnumberأقصى عرض للتصيير بوحدات بكسل CSS (640-2400).
ttlSecondsnumberمدة بقاء الأثر بالثواني لمخرجات العارض والملف المستقل. الحد الأقصى 21600.
baseUrlstringتجاوز أصل عنوان URL للعارض. يتجاوز viewerBaseUrl الخاص بـ Plugin. يجب أن يكون http أو https، بلا استعلام/تجزئة.
Legacy input aliases
لا تزال مقبولة للتوافق العكسي:
format->fileFormatimageFormat->fileFormatimageQuality->fileQualityimageScale->fileScaleimageMaxWidth->fileMaxWidth
Validation and limits
- الحد الأقصى لكل من
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.
Viewer fields
الحقول المشتركة للأوضاع التي تنشئ عارضًا:
artifactIdviewerUrlviewerPathtitleexpiresAtinputKindfileCountmodecontext(agentId,sessionId,messageChannel,agentAccountIdعند توفرها)
File fields
حقول الملف عند تصيير PNG أو PDF:
artifactIdexpiresAtfilePathpath(نفس قيمةfilePath، للتوافق مع أداة الرسائل)fileBytesfileFormatfileQualityfileScalefileMaxWidth
Compatibility aliases
تُعاد أيضًا للمتصلين الحاليين:
format(نفس قيمةfileFormat)imagePath(نفس قيمةfilePath)imageBytes(نفس قيمةfileBytes)imageQuality(نفس قيمةfileQuality)imageScale(نفس قيمةfileScale)imageMaxWidth(نفس قيمةfileMaxWidth)
ملخص سلوك الوضع:
| الوضع | ما يتم إرجاعه |
|---|---|
"view" |
حقول العارض فقط. |
"file" |
حقول الملف فقط، بلا أثر عارض. |
"both" |
حقول العارض بالإضافة إلى حقول الملف. إذا فشل تصيير الملف، يظل العارض يُعاد مع fileError والاسم المستعار imageError. |
الأقسام غير المتغيرة المطوية
- يمكن للعارض إظهار صفوف مثل
N unmodified lines. - عناصر التحكم في التوسيع على تلك الصفوف مشروطة وليست مضمونة لكل نوع إدخال.
- تظهر عناصر التحكم في التوسيع عندما يحتوي الفرق المُصيّر على بيانات سياق قابلة للتوسيع، وهذا معتاد لإدخال قبل وبعد.
- في كثير من مدخلات الرقع الموحدة، لا تكون أجسام السياق المحذوفة متاحة في كتل الرقعة المحللة، لذلك قد يظهر الصف دون عناصر تحكم للتوسيع. هذا سلوك متوقع.
- لا ينطبق
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 دائم للعارض
viewerBaseUrlstringبديل احتياطي مملوك لـ Plugin لروابط العارض المُعادة عندما لا يمرر استدعاء الأداة baseUrl. يجب أن يكون http أو https، بلا استعلام/تجزئة.
{
plugins: {
entries: {
diffs: {
enabled: true,
config: {
viewerBaseUrl: "https://gateway.example.com/openclaw",
},
},
},
},
}
إعداد الأمان
security.allowRemoteViewerbooleanfalse: تُرفض الطلبات غير local loopback إلى مسارات العارض. true: يُسمح بالعارضين البعيدين إذا كان المسار المرمّز صالحًا.
{
plugins: {
entries: {
diffs: {
enabled: true,
config: {
security: {
allowRemoteViewer: false,
},
},
},
},
},
}
دورة حياة الأثر والتخزين
- تُخزّن الآثار ضمن المجلد الفرعي المؤقت:
$TMPDIR/openclaw-diffs. - تحتوي بيانات وصف أثر العارض على:
- معرّف أثر عشوائي (20 حرفًا سداسيًا)
- رمز عشوائي (48 حرفًا سداسيًا)
createdAtوexpiresAt- مسار
viewer.htmlالمخزّن
- مدة بقاء الأثر الافتراضية هي 30 دقيقة عند عدم تحديدها.
- أقصى مدة بقاء عارض مقبولة هي 6 ساعات.
- يعمل التنظيف انتهازيًا بعد إنشاء الأثر.
- تُحذف الآثار منتهية الصلاحية.
- يزيل التنظيف الاحتياطي المجلدات القديمة التي يزيد عمرها عن 24 ساعة عند فقدان البيانات الوصفية.
عنوان URL للعارض وسلوك الشبكة
مسار العارض:
/plugins/diffs/view/{artifactId}/{token}
أصول العارض:
/plugins/diffs/assets/viewer.js/plugins/diffs/assets/viewer-runtime.js
يحل مستند العارض تلك الأصول نسبةً إلى عنوان URL للعارض، لذلك يُحافظ أيضًا على بادئة مسار baseUrl الاختيارية لكلا طلبي الأصول.
سلوك إنشاء عنوان URL:
- إذا قُدّم
baseUrlفي استدعاء الأداة، فيُستخدم بعد تحقق صارم. - وإلا إذا كان
viewerBaseUrlالخاص بـ Plugin مهيأً، فيُستخدم. - دون أي من التجاوزين، يكون عنوان URL للعارض افتراضيًا هو local loopback
127.0.0.1. - إذا كان وضع ربط Gateway هو
customوكانgateway.customBindHostمضبوطًا، فيُستخدم ذلك المضيف.
قواعد baseUrl:
- يجب أن يكون
http://أوhttps://. - تُرفض الاستعلامات والتجزئات.
- يُسمح بالأصل بالإضافة إلى مسار أساسي اختياري.
نموذج الأمان
تقوية العارض
- local loopback فقط افتراضيًا.
- مسارات عارض مزودة برموز مع تحقق صارم من المعرّف والرمز.
- سياسة CSP لاستجابة العارض:
default-src 'none'- السكربتات والأصول من الذات فقط
- لا يوجد
connect-srcصادر
- تقييد الإخفاقات البعيدة عند تمكين الوصول البعيد:
- 40 إخفاقًا لكل 60 ثانية
- قفل لمدة 60 ثانية (
429 Too Many Requests)
تقوية عرض الملفات
- توجيه طلبات متصفح لقطات الشاشة يرفض افتراضيًا.
- يُسمح فقط بأصول العارض المحلية من
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)مع مسار اختياري، بلا استعلام/هاش.{field} exceeds maximum size (...)— قلّل حجم الحمولة.- رفض الرقعة الكبيرة — قلّل عدد ملفات الرقعة أو إجمالي الأسطر.
إمكانية الوصول إلى العارض
- يُحل عنوان URL للعارض إلى
127.0.0.1افتراضيًا. - لسيناريوهات الوصول البعيد، إمّا:
- عيّن
viewerBaseUrlفي Plugin، أو - مرّر
baseUrlلكل استدعاء أداة، أو - استخدم
gateway.bind=customوgateway.customBindHost
- عيّن
- إذا كان
gateway.trustedProxiesيتضمن local loopback لوكيل على المضيف نفسه (مثل Tailscale Serve)، فإن طلبات عارض local loopback الخام من دون ترويسات عنوان IP للعميل المُمرَّرة تفشل مغلقةً حسب التصميم. - لطوبولوجيا الوكيل تلك:
- فضّل
mode: "file"أوmode: "both"عندما تحتاج إلى مرفق فقط، أو - مكّن
security.allowRemoteViewerعمدًا وعيّنviewerBaseUrlفي Plugin أو مرّرbaseUrlلوكيل/عام عندما تحتاج إلى عنوان URL عارض قابل للمشاركة
- فضّل
- مكّن
security.allowRemoteViewerفقط عندما تقصد إتاحة وصول خارجي إلى العارض.
صف الأسطر غير المعدّلة لا يحتوي على زر توسيع
يمكن أن يحدث هذا لإدخال الرقعة عندما لا تحمل الرقعة سياقًا قابلًا للتوسيع. هذا متوقع ولا يشير إلى فشل في العارض.
لم يُعثر على الأثر
- انتهت صلاحية الأثر بسبب TTL.
- تغيّر الرمز أو المسار.
- أزالت عملية التنظيف بيانات قديمة.
إرشادات تشغيلية
- فضّل
mode: "view"للمراجعات التفاعلية المحلية في اللوحة. - فضّل
mode: "file"لقنوات الدردشة الصادرة التي تحتاج إلى مرفق. - أبقِ
allowRemoteViewerمعطلًا ما لم يتطلب نشرُك عناوين URL بعيدة للعارض. - عيّن
ttlSecondsقصيرة وصريحة للفروقات الحساسة. - تجنب إرسال الأسرار في إدخال الفرق عندما لا تكون مطلوبة.
- إذا كانت قناتك تضغط الصور بقوة (مثل Telegram أو WhatsApp)، ففضّل إخراج PDF (
fileFormat: "pdf").