Tools
الفروقات
diffs هي أداة Plugin اختيارية مع إرشادات نظام مدمجة موجزة وSkill مرافقة تحوّل محتوى التغييرات إلى أثر diff للقراءة فقط من أجل الوكلاء.
تقبل إما:
- نصي
beforeوafter patchموحّدًا
يمكنها إرجاع:
- عنوان URL لعارض Gateway من أجل عرض اللوحة
- مسار ملف معروض (PNG أو PDF) من أجل تسليم الرسائل
- كلا المخرجين في استدعاء واحد
عند تمكينها، تضيف Plugin إرشادات استخدام موجزة إلى مساحة موجه النظام، وتعرض أيضًا Skill تفصيلية للحالات التي يحتاج فيها الوكيل إلى تعليمات أوفى.
البدء السريع
ثبّت Plugin
openclaw plugins install diffsفعّل Plugin
{ plugins: { entries: { diffs: { enabled: true, }, }, },}اختر وضعًا
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 بدلًا من ذلك.
سير عمل الوكيل المعتاد
استدعِ diffs
يستدعي الوكيل أداة diffs مع الإدخال.
اقرأ التفاصيل
يقرأ الوكيل حقول details من الاستجابة.
اعرض
يفتح الوكيل إما 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النص الأصلي. مطلوب مع after عند حذف patch.
afterstringالنص المحدّث. مطلوب مع before عند حذف patch.
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"إعداد جودة مسبق لعرض PNG أو PDF.
fileScalenumberتجاوز مقياس الجهاز (1-4).
fileMaxWidthnumberأقصى عرض للعرض بالبكسلات في CSS (640-2400).
ttlSecondsnumberdefault: 1800مدة TTL للأثر بالثواني لمخرجات العارض والملف المستقل. الحد الأقصى 21600.
baseUrlstringتجاوز أصل عنوان URL للعارض. يتجاوز viewerBaseUrl الخاص بـPlugin. يجب أن يكون http أو https، بلا استعلام/تجزئة.
أسماء الإدخال المستعارة القديمة
لا تزال مقبولة للتوافق العكسي:
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.
حقول العارض
حقول مشتركة للأوضاع التي تنشئ عارضًا:
artifactIdviewerUrlviewerPathtitleexpiresAtinputKindfileCountmodecontext(agentId,sessionId,messageChannel,agentAccountIdعند التوفر)
حقول الملف
حقول الملف عند عرض PNG أو PDF:
artifactIdexpiresAtfilePathpath(القيمة نفسها مثلfilePath، للتوافق مع أداة الرسائل)fileBytesfileFormatfileQualityfileScalefileMaxWidth
أسماء التوافق المستعارة
تُعاد أيضًا للمتصلين الحاليين:
format(القيمة نفسها مثلfileFormat)imagePath(القيمة نفسها مثلfilePath)imageBytes(القيمة نفسها مثلfileBytes)imageQuality(القيمة نفسها مثلfileQuality)imageScale(القيمة نفسها مثلfileScale)imageMaxWidth(القيمة نفسها مثلfileMaxWidth)
ملخص سلوك الوضع:
| الوضع | ما يتم إرجاعه |
|---|---|
"view" |
حقول العارض فقط. |
"file" |
حقول الملف فقط، بلا أثر عارض. |
"both" |
حقول العارض إضافة إلى حقول الملف. إذا فشل عرض الملف، يظل العارض يُعاد مع fileError والاسم المستعار imageError. |
الأقسام غير المتغيرة المطوية
- يمكن أن يعرض العارض صفوفًا مثل
N unmodified lines. - عناصر التحكم في التوسيع على تلك الصفوف شرطية وليست مضمونة لكل نوع إدخال.
- تظهر عناصر التحكم في التوسيع عندما يحتوي diff المعروض على بيانات سياق قابلة للتوسيع، وهذا معتاد لإدخال قبل وبعد.
- بالنسبة للعديد من إدخالات Patch الموحّدة، لا تكون أجسام السياق المحذوفة متاحة في أجزاء 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", ttlSeconds: 21600, }, }, }, }, },}القيم الافتراضية المدعومة:
fontFamilyfontSizelineSpacinglayoutshowLineNumbersdiffIndicatorswordWrapbackgroundthemefileFormatfileQualityfileScalefileMaxWidthmodettlSeconds
تتجاوز معاملات الأداة الصريحة هذه القيم الافتراضية.
إعداد عنوان URL عارض دائم
viewerBaseUrlstringبديل احتياطي مملوك لـPlugin لروابط العارض المُعادة عندما لا يمرر استدعاء الأداة baseUrl. يجب أن يكون http أو https، بلا استعلام/تجزئة.
{ plugins: { entries: { diffs: { enabled: true, config: { viewerBaseUrl: "https://gateway.example.com/openclaw", }, }, }, },}إعداد الأمان
security.allowRemoteViewerbooleandefault: falsefalse: تُرفض الطلبات غير المحلية إلى مسارات العارض. true: يُسمح بالعارضين البعيدين إذا كان المسار ذي الرمز صالحًا.
{ plugins: { entries: { diffs: { enabled: true, config: { security: { allowRemoteViewer: false, }, }, }, }, },}دورة حياة الأثر والتخزين
- تُخزن الآثار ضمن المجلد الفرعي المؤقت:
$TMPDIR/openclaw-diffs. - تحتوي البيانات الوصفية لأثر العارض على:
- معرّف أثر عشوائي (20 حرفًا سداسيًا)
- رمز عشوائي (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 الاختيارية لكل طلبي الأصلين.
سلوك إنشاء عنوان URL:
- إذا تم توفير
baseUrlفي استدعاء الأداة، فسيُستخدم بعد تحقق صارم. - وإلا إذا تم إعداد
viewerBaseUrlالخاص بـPlugin، فسيُستخدم. - من دون أي تجاوز، يكون عنوان URL للعارض افتراضيًا local loopback
127.0.0.1. - إذا كان وضع ربط Gateway هو
customوتم ضبطgateway.customBindHost، فسيُستخدم ذلك المضيف.
قواعد baseUrl:
- يجب أن يكون
http://أوhttps://. - تُرفض الاستعلامات والتجزئة.
- يُسمح بالأصل مع مسار أساس اختياري.
نموذج الأمان
تقوية العارض
- يقتصر على Loopback افتراضيا.
- مسارات عارض مرمزة برموز مميزة مع تحقق صارم من المعرف والرمز المميز.
- CSP لاستجابة العارض:
default-src 'none'- النصوص البرمجية والأصول من self فقط
- لا يوجد
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يتضمن loopback لوكيل على المضيف نفسه (على سبيل المثال Tailscale Serve)، فستفشل طلبات عارض 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").