Web interfaces

واجهة التحكم

تطبيق Control UI هو تطبيق صفحة واحدة صغير مبني باستخدام Vite + Lit ويقدمه Gateway:

  • الافتراضي: http://<host>:18789/
  • بادئة اختيارية: اضبط gateway.controlUi.basePath (مثلًا /openclaw)

يتواصل مباشرة مع WebSocket الخاص بـ Gateway على المنفذ نفسه.

فتح سريع (محلي)

إذا كان Gateway يعمل على الحاسوب نفسه، فافتح:

إذا فشل تحميل الصفحة، شغّل Gateway أولًا: openclaw gateway.

يُقدَّم التفويض أثناء مصافحة WebSocket عبر:

  • connect.params.auth.token
  • connect.params.auth.password
  • ترويسات هوية Tailscale Serve عندما تكون gateway.auth.allowTailscale: true
  • ترويسات هوية الوكيل الموثوق عندما يكون gateway.auth.mode: "trusted-proxy"

تحتفظ لوحة إعدادات لوحة المعلومات برمز لجلسة تبويب المتصفح الحالية وعنوان gateway المحدد؛ ولا تُحفَظ كلمات المرور. عادةً ما ينشئ الإعداد الأولي رمز gateway لتفويض السر المشترك عند أول اتصال، لكن تفويض كلمة المرور يعمل أيضًا عندما يكون gateway.auth.mode هو "password".

إقران الجهاز (الاتصال الأول)

عند الاتصال بـ Control UI من متصفح أو جهاز جديد، يطلب Gateway عادةً موافقة إقران لمرة واحدة. هذا إجراء أمني لمنع الوصول غير المصرح به.

ما ستراه: "disconnected (1008): pairing required"

  • اعرض الطلبات المعلقة

    openclaw devices list
    
  • وافِق حسب معرّف الطلب

    openclaw devices approve <requestId>
    
  • إذا أعاد المتصفح محاولة الإقران مع تغيير تفاصيل التفويض (الدور/النطاقات/المفتاح العام)، فسيحل الطلب المعلق السابق محلّه طلب جديد وسيُنشأ requestId جديد. أعد تشغيل openclaw devices list قبل الموافقة.

    إذا كان المتصفح مقترنًا بالفعل وغيّرته من وصول قراءة إلى وصول كتابة/إدارة، فسيُعامل ذلك كترقية موافقة، وليس إعادة اتصال صامتة. يُبقي OpenClaw الموافقة القديمة نشطة، ويحظر إعادة الاتصال ذات النطاق الأوسع، ويطلب منك الموافقة صراحةً على مجموعة النطاقات الجديدة.

    بعد الموافقة، يُتذكَّر الجهاز ولن يتطلب إعادة الموافقة إلا إذا ألغيتَه باستخدام openclaw devices revoke --device <id> --role <role>. راجع CLI الأجهزة لتدوير الرموز والإلغاء.

    الهوية الشخصية (محلية في المتصفح)

    يدعم Control UI هوية شخصية لكل متصفح (اسم عرض وصورة رمزية) تُرفق بالرسائل الصادرة للإسناد في الجلسات المشتركة. تعيش هذه الهوية في تخزين المتصفح، وتكون محصورة في ملف تعريف المتصفح الحالي، ولا تُزامَن مع أجهزة أخرى أو تُحفَظ من جهة الخادم خارج بيانات وصفية عادية لتأليف النصوص في الرسائل التي ترسلها فعليًا. يؤدي مسح بيانات الموقع أو تبديل المتصفحات إلى إعادة ضبطها لتصبح فارغة.

    ينطبق النمط المحلي نفسه في المتصفح على تجاوز صورة المساعد الرمزية. تضع صور المساعد الرمزية المرفوعة طبقة فوق الهوية التي يحلها gateway في المتصفح المحلي فقط ولا تعود أبدًا عبر config.patch. ما يزال حقل إعدادات ui.assistant.avatar المشترك متاحًا للعملاء غير التابعين لـ UI الذين يكتبون الحقل مباشرةً (مثل gateways المبرمجة أو لوحات المعلومات المخصصة).

    نقطة نهاية إعدادات وقت التشغيل

    يجلب Control UI إعدادات وقت التشغيل الخاصة به من /__openclaw/control-ui-config.json. تخضع نقطة النهاية هذه لتفويض gateway نفسه كبقية سطح HTTP: لا يمكن للمتصفحات غير المصرح لها جلبها، ويتطلب الجلب الناجح إما رمز/كلمة مرور gateway صالحة بالفعل، أو هوية Tailscale Serve، أو هوية وكيل موثوق.

    دعم اللغة

    يمكن لـ Control UI توطين نفسه عند التحميل الأول بناءً على لغة المتصفح لديك. لتجاوزها لاحقًا، افتح نظرة عامة -> وصول Gateway -> اللغة. يوجد منتقي اللغة في بطاقة وصول Gateway، وليس ضمن المظهر.

    • اللغات المدعومة: en, zh-CN, zh-TW, pt-BR, de, es, ja-JP, ko, fr, ar, it, tr, uk, id, pl, th, vi, nl, fa
    • تُحمَّل الترجمات غير الإنجليزية تحميلًا كسولًا في المتصفح.
    • تُحفَظ اللغة المحددة في تخزين المتصفح ويُعاد استخدامها في الزيارات المستقبلية.
    • تعود مفاتيح الترجمة المفقودة إلى الإنجليزية.

    تُنشأ ترجمات الوثائق لمجموعة اللغات غير الإنجليزية نفسها، لكن منتقي اللغة المضمّن في موقع الوثائق من Mintlify يقتصر على رموز اللغات التي تقبلها Mintlify. ما تزال وثائق التايلاندية (th) والفارسية (fa) تُنشأ في مستودع النشر؛ وقد لا تظهر في ذلك المنتقي حتى تدعم Mintlify هذه الرموز.

    سمات المظهر

    تحتفظ لوحة المظهر بسمات Claw وKnot وDash المضمّنة، إضافةً إلى خانة استيراد tweakcn محلية واحدة في المتصفح. لاستيراد سمة، افتح محرر tweakcn، واختر سمة أو أنشئ واحدة، وانقر مشاركة، ثم الصق رابط السمة المنسوخ في المظهر. يقبل المستورد أيضًا عناوين URL للسجل مثل https://tweakcn.com/r/themes/<id>، وعناوين URL للمحرر مثل https://tweakcn.com/editor/theme?theme=amethyst-haze، ومسارات /themes/<id> النسبية، ومعرّفات السمات الخام، وأسماء السمات الافتراضية مثل amethyst-haze.

    تُخزَّن السمات المستوردة فقط في ملف تعريف المتصفح الحالي. ولا تُكتب إلى إعدادات gateway ولا تُزامَن عبر الأجهزة. يؤدي استبدال السمة المستوردة إلى تحديث الخانة المحلية الواحدة؛ ويؤدي مسحها إلى تبديل السمة النشطة مرة أخرى إلى Claw إذا كانت السمة المستوردة محددة.

    ما يمكنه فعله (حاليًا)

    الدردشة والتحدث
    • الدردشة مع النموذج عبر Gateway WS (chat.history, chat.send, chat.abort, chat.inject).
    • تطلب تحديثات سجل الدردشة نافذة حديثة محدودة مع حدود نصية لكل رسالة، بحيث لا تُجبر الجلسات الكبيرة المتصفح على عرض حمولة نص كاملة قبل أن تصبح الدردشة قابلة للاستخدام.
    • التحدث عبر جلسات الوقت الحقيقي في المتصفح. يستخدم OpenAI اتصال WebRTC مباشرًا، ويستخدم Google Live رمز متصفح مقيدًا لمرة واحدة عبر WebSocket، وتستخدم plugins الصوت في الوقت الحقيقي الخلفية فقط نقل ترحيل Gateway. تبدأ جلسات المزوّد المملوكة للعميل بـ talk.client.create؛ وتبدأ جلسات ترحيل Gateway بـ talk.session.create. يُبقي الترحيل بيانات اعتماد المزوّد على Gateway بينما يبث المتصفح PCM الميكروفون عبر talk.session.appendAudio ويمرر استدعاءات أدوات المزوّد openclaw_agent_consult عبر talk.client.toolCall لسياسة Gateway ونموذج OpenClaw الأكبر المُعد.
    • بث استدعاءات الأدوات + بطاقات مخرجات الأدوات الحية في الدردشة (أحداث الوكيل).
    القنوات، والمثيلات، والجلسات، والأحلام
    • القنوات: حالة قنوات plugins المضمّنة والخارجية إضافةً إلى المضمنة، وتسجيل دخول QR، وإعدادات كل قناة (channels.status, web.login.*, config.patch).
    • تُبقي تحديثات فحص القنوات اللقطة السابقة مرئية بينما تنتهي فحوص المزوّد البطيئة، وتُوسَم اللقطات الجزئية عندما يتجاوز فحص أو تدقيق ميزانية UI الخاصة به.
    • المثيلات: قائمة الحضور + التحديث (system-presence).
    • الجلسات: القائمة + تجاوزات النموذج/التفكير/السريع/المطوّل/التتبع/الاستدلال لكل جلسة (sessions.list, sessions.patch).
    • الأحلام: حالة Dreaming، ومفتاح التمكين/التعطيل، وقارئ يوميات الأحلام (doctor.memory.status, doctor.memory.dreamDiary, config.patch).
    Cron، وSkills، والعُقد، وموافقات exec
    • مهام Cron: عرض/إضافة/تحرير/تشغيل/تمكين/تعطيل + سجل التشغيل (cron.*).
    • Skills: الحالة، التمكين/التعطيل، التثبيت، تحديثات مفاتيح API (skills.*).
    • العُقد: القائمة + الحدود القصوى (node.list).
    • موافقات exec: تحرير قوائم السماح الخاصة بـ gateway أو node + سياسة السؤال لـ exec host=gateway/node (exec.approvals.*).
    الإعدادات
    • عرض/تحرير ~/.openclaw/openclaw.json (config.get, config.set).
    • التطبيق + إعادة التشغيل مع التحقق (config.apply) وتنبيه آخر جلسة نشطة.
    • تتضمن عمليات الكتابة حارس تجزئة أساس لمنع طمس التحريرات المتزامنة.
    • تُجري عمليات الكتابة (config.set/config.apply/config.patch) فحصًا مسبقًا لحل SecretRef النشطة للمراجع في حمولة الإعدادات المقدمة؛ وتُرفض المراجع المقدمة النشطة غير المحلولة قبل الكتابة.
    • عرض المخطط + النموذج (config.schema / config.schema.lookup، بما في ذلك حقلا title / description، وتلميحات UI المطابقة، وملخصات الأبناء المباشرين، وبيانات الوثائق الوصفية على عُقد الكائنات/أحرف البدل/المصفوفات/التركيب المتداخلة، إضافةً إلى مخططات plugin + القناة عند توفرها)؛ ولا يتاح محرر Raw JSON إلا عندما تحتوي اللقطة على رحلة ذهاب وعودة خام آمنة.
    • إذا تعذر على لقطة ما إجراء رحلة ذهاب وعودة للنص الخام بأمان، يفرض Control UI وضع النموذج ويعطل وضع Raw لتلك اللقطة.
    • يحافظ محرر Raw JSON، عند اختيار "إعادة الضبط إلى المحفوظ"، على الشكل المؤلَّف خامًا (التنسيق، التعليقات، تخطيط $include) بدلًا من إعادة عرض لقطة مسطحة، بحيث تنجو التحريرات الخارجية من إعادة الضبط عندما تستطيع اللقطة إجراء رحلة ذهاب وعودة بأمان.
    • تُعرض قيم كائنات SecretRef المنظمة للقراءة فقط في حقول إدخال نص النموذج لمنع تلف تحويل الكائن إلى سلسلة نصية بالخطأ.
    التصحيح، والسجلات، والتحديث
    • التصحيح: لقطات الحالة/السلامة/النماذج + سجل الأحداث + استدعاءات RPC يدوية (status, health, models.list).
    • يتضمن سجل الأحداث توقيتات تحديث/RPC الخاصة بـ Control UI، وتوقيتات عرض الدردشة/الإعدادات البطيئة، وإدخالات استجابة المتصفح لإطارات الرسوم المتحركة الطويلة أو المهام الطويلة عندما يكشف المتصفح أنواع إدخالات PerformanceObserver تلك.
    • السجلات: متابعة حية لسجلات ملفات gateway مع التصفية/التصدير (logs.tail).
    • التحديث: تشغيل تحديث حزمة/git + إعادة التشغيل (update.run) مع تقرير إعادة التشغيل، ثم استطلاع update.status بعد إعادة الاتصال للتحقق من إصدار gateway المشغّل.
    ملاحظات لوحة مهام Cron
    • بالنسبة للمهام المعزولة، يكون التسليم افتراضيًا على إعلان ملخص. يمكنك التبديل إلى لا شيء إذا أردت تشغيلات داخلية فقط.
    • تظهر حقول القناة/الهدف عند تحديد الإعلان.
    • يستخدم وضع Webhook القيمة delivery.mode = "webhook" مع ضبط delivery.to على عنوان URL صالح لـ HTTP(S) webhook.
    • بالنسبة لمهام الجلسة الرئيسية، تتوفر أوضاع تسليم webhook ولا شيء.
    • تتضمن عناصر التحكم المتقدمة في التحرير الحذف بعد التشغيل، ومسح تجاوز الوكيل، وخيارات Cron الدقيقة/المتدرجة، وتجاوزات نموذج/تفكير الوكيل، ومفاتيح تسليم أفضل جهد.
    • يكون التحقق من النموذج مضمنًا مع أخطاء على مستوى الحقول؛ وتعطل القيم غير الصالحة زر الحفظ حتى تُصلح.
    • اضبط cron.webhookToken لإرسال رمز bearer مخصص، وإذا أُغفل فسيُرسل webhook دون ترويسة تفويض.
    • بديل مهمل: ما تزال المهام القديمة المخزنة التي تحتوي على notify: true قادرة على استخدام cron.webhook حتى تُرحَّل.

    سلوك الدردشة

    دلالات الإرسال والسجل
    • chat.send غير حاظر: يقر فورا بـ { runId, status: "started" } ويتدفق الرد عبر أحداث chat.
    • تقبل رفع ملفات الدردشة الصور إضافة إلى الملفات غير المرئية. تحتفظ الصور بمسار الصورة الأصلي؛ وتخزن الملفات الأخرى كوسائط مدارة وتظهر في السجل كروابط مرفقات.
    • تعيد إعادة الإرسال باستخدام idempotencyKey نفسه { status: "in_flight" } أثناء التشغيل، و{ status: "ok" } بعد الاكتمال.
    • تكون استجابات chat.history محدودة الحجم حفاظا على سلامة واجهة المستخدم. عندما تكون إدخالات النص كبيرة جدا، قد يقتطع Gateway حقول النص الطويلة، ويحذف كتل البيانات الوصفية الثقيلة، ويستبدل الرسائل كبيرة الحجم بعنصر نائب ([chat.history omitted: message too large]).
    • تستمر الصور التي أنشأها المساعد كإشارات وسائط مدارة وتقدم مرة أخرى عبر عناوين URL لوسائط Gateway المصادق عليها، لذلك لا تعتمد عمليات إعادة التحميل على بقاء حمولات الصور الخام بصيغة base64 في استجابة سجل الدردشة.
    • عند عرض chat.history، تزيل واجهة التحكم وسوم التوجيه المضمنة المخصصة للعرض فقط من نص المساعد المرئي (على سبيل المثال [[reply_to_*]] و[[audio_as_voice]])، وحمولات XML لاستدعاءات الأدوات ذات النص العادي (بما في ذلك <tool_call>...</tool_call>، و<function_call>...</function_call>، و<tool_calls>...</tool_calls>، و<function_calls>...</function_calls>، وكتل استدعاءات الأدوات المقتطعة)، ورموز التحكم في النموذج المسربة بصيغة ASCII/العرض الكامل، وتحذف إدخالات المساعد التي يكون نصها المرئي كله الرمز الصامت الدقيق NO_REPLY / no_reply أو رمز إقرار Heartbeat HEARTBEAT_OK.
    • أثناء إرسال نشط وتحديث السجل النهائي، تبقي طريقة عرض الدردشة رسائل المستخدم/المساعد المحلية المتفائلة مرئية إذا أعاد chat.history مؤقتا لقطة أقدم؛ ويستبدل النص الرسمي تلك الرسائل المحلية بمجرد أن يلحق سجل Gateway.
    • أحداث chat المباشرة هي حالة التسليم، بينما يعاد بناء chat.history من نص الجلسة الدائم. بعد أحداث الأداة النهائية، تعيد واجهة التحكم تحميل السجل وتدمج ذيلا متفائلا صغيرا فقط؛ ويوثق حد النص في دردشة الويب.
    • يضيف chat.inject ملاحظة مساعد إلى نص الجلسة ويبث حدث chat للتحديثات المخصصة لواجهة المستخدم فقط (دون تشغيل وكيل، ودون تسليم قناة).
    • يعرض رأس الدردشة مرشح الوكيل قبل منتقي الجلسة، ويكون منتقي الجلسة محصورا بالوكيل المحدد. يعرض تبديل الوكلاء الجلسات المرتبطة بذلك الوكيل فقط، ويعود إلى الجلسة الرئيسية لذلك الوكيل عندما لا تكون لديه جلسات لوحة معلومات محفوظة بعد.
    • في عروض سطح المكتب، تبقى عناصر تحكم الدردشة في صف مضغوط واحد وتنهار أثناء التمرير إلى أسفل النص؛ ويؤدي التمرير إلى أعلى، أو الرجوع إلى الأعلى، أو الوصول إلى الأسفل إلى استعادة عناصر التحكم.
    • تعرض الرسائل النصية المكررة المتتالية كفقاعة واحدة مع شارة عدد. وتترك الرسائل التي تحمل صورا أو مرفقات أو مخرجات أدوات أو معاينات لوحة دون طي.
    • يطبق منتقيا النموذج والتفكير في رأس الدردشة تحديثا فوريا على الجلسة النشطة عبر sessions.patch؛ وهما تجاوزان دائمان للجلسة، وليسا خيارات إرسال لدورة واحدة فقط.
    • تؤدي كتابة /new في واجهة التحكم إلى إنشاء الجلسة الجديدة نفسها للوحة المعلومات كما في دردشة جديدة والتبديل إليها. وتحافظ كتابة /reset على إعادة التعيين الصريحة في المكان من Gateway للجلسة الحالية.
    • يطلب منتقي نموذج الدردشة عرض النموذج المكون في Gateway. إذا كان agents.defaults.models موجودا، فستقود قائمة السماح هذه المنتقي. وإلا يعرض المنتقي إدخالات models.providers.*.models الصريحة إضافة إلى الموفرين ذوي المصادقة القابلة للاستخدام. ويظل الفهرس الكامل متاحا عبر RPC التصحيح models.list مع view: "all".
    • عندما تظهر تقارير استخدام جلسة Gateway الجديدة ضغط سياق عاليا، تعرض منطقة مؤلف الدردشة إشعار سياق، وعند مستويات Compaction الموصى بها، زرا مضغوطا يشغل مسار Compaction العادي للجلسة. وتخفى لقطات الرموز القديمة حتى يبلغ Gateway عن استخدام جديد مرة أخرى.
    وضع التحدث (الوقت الفعلي في المتصفح)

    يستخدم وضع التحدث موفر صوت وقت فعلي مسجلا. كوّن OpenAI باستخدام talk.realtime.provider: "openai" إضافة إلى talk.realtime.providers.openai.apiKey، أو كوّن Google باستخدام talk.realtime.provider: "google" إضافة إلى talk.realtime.providers.google.apiKey. لا يتلقى المتصفح أبدا مفتاح API قياسيا للموفر. يتلقى OpenAI سرا عابرا لعميل Realtime من أجل WebRTC. ويتلقى Google Live رمز مصادقة API Live مقيدا للاستخدام مرة واحدة لجلسة WebSocket في المتصفح، مع تعليمات وتصريحات أدوات مقفلة داخل الرمز بواسطة Gateway. الموفرون الذين لا يعرضون إلا جسرا خلفيا للوقت الفعلي يعملون عبر نقل ترحيل Gateway، بحيث تبقى بيانات الاعتماد ومآخذ الموردين على جانب الخادم بينما ينتقل صوت المتصفح عبر RPCs Gateway المصادق عليها. يجمع Gateway مطالبة جلسة Realtime؛ ولا يقبل talk.client.create تجاوزات تعليمات يقدمها المستدعي.

    في مؤلف الدردشة، يكون عنصر تحكم التحدث هو زر الموجات بجانب زر الإملاء بالميكروفون. عندما يبدأ التحدث، يعرض صف حالة المؤلف Connecting Talk...، ثم Talk live أثناء اتصال الصوت، أو Asking OpenClaw... أثناء استشارة استدعاء أداة في الوقت الفعلي للنموذج الأكبر المكون عبر talk.client.toolCall.

    اختبار smoke مباشر للمشرفين: يتحقق OPENAI_API_KEY=... GEMINI_API_KEY=... node --import tsx scripts/dev/realtime-talk-live-smoke.ts من تبادل SDP لـ WebRTC في متصفح OpenAI، وإعداد WebSocket المتصفح برمز مقيد في Google Live، ومحول متصفح ترحيل Gateway مع وسائط ميكروفون وهمية. يطبع الأمر حالة الموفر فقط ولا يسجل الأسرار.

    الإيقاف والإجهاض
    • انقر إيقاف (يستدعي chat.abort).
    • أثناء نشاط تشغيل، تصطف المتابعات العادية في طابور. انقر توجيه على رسالة في الطابور لحقن تلك المتابعة في الدور الجاري.
    • اكتب /stop (أو عبارات إجهاض مستقلة مثل stop، وstop action، وstop run، وstop openclaw، وplease stop) للإجهاض خارج النطاق.
    • يدعم chat.abort الصيغة { sessionKey } (دون runId) لإجهاض كل عمليات التشغيل النشطة لتلك الجلسة.
    الاحتفاظ الجزئي عند الإجهاض
    • عند إجهاض تشغيل، يمكن أن يظل نص المساعد الجزئي معروضا في واجهة المستخدم.
    • يستمر Gateway في حفظ نص المساعد الجزئي المجهض في سجل النص عندما توجد مخرجات مخزنة مؤقتا.
    • تتضمن الإدخالات المستمرة بيانات وصفية للإجهاض حتى يتمكن مستهلكو النص من تمييز الأجزاء المجهضة عن مخرجات الاكتمال العادية.

    تثبيت PWA والدفع عبر الويب

    تشحن واجهة التحكم manifest.webmanifest وعامل خدمة، لذلك يمكن للمتصفحات الحديثة تثبيتها كتطبيق PWA مستقل. يتيح Web Push لـ Gateway إيقاظ PWA المثبت بالإشعارات حتى عندما لا تكون علامة التبويب أو نافذة المتصفح مفتوحة.

    السطح ما يفعله
    ui/public/manifest.webmanifest بيان PWA. تعرض المتصفحات "تثبيت التطبيق" بمجرد أن يصبح قابلا للوصول.
    ui/public/sw.js عامل خدمة يتعامل مع أحداث push ونقرات الإشعارات.
    push/vapid-keys.json (تحت دليل حالة OpenClaw) زوج مفاتيح VAPID مولد تلقائيا يستخدم لتوقيع حمولات Web Push.
    push/web-push-subscriptions.json نقاط نهاية اشتراك المتصفح المستمرة.

    تجاوز زوج مفاتيح VAPID عبر متغيرات البيئة في عملية Gateway عندما تريد تثبيت المفاتيح (لعمليات نشر متعددة المضيفين، أو تدوير الأسرار، أو الاختبارات):

    • OPENCLAW_VAPID_PUBLIC_KEY
    • OPENCLAW_VAPID_PRIVATE_KEY
    • OPENCLAW_VAPID_SUBJECT (يكون الافتراضي mailto:openclaw@localhost)

    تستخدم واجهة التحكم طرق Gateway المحكومة بالنطاق هذه لتسجيل اشتراكات المتصفح واختبارها:

    • push.web.vapidPublicKey — يجلب مفتاح VAPID العام النشط.
    • push.web.subscribe — يسجل endpoint إضافة إلى keys.p256dh/keys.auth.
    • push.web.unsubscribe — يزيل نقطة نهاية مسجلة.
    • push.web.test — يرسل إشعار اختبار إلى اشتراك المستدعي.

    التضمينات المستضافة

    يمكن لرسائل المساعد عرض محتوى ويب مستضاف ضمن السطر باستخدام الرمز المختصر [embed ...]. تتحكم gateway.controlUi.embedSandbox في سياسة صندوق حماية iframe:

    صارم

    يعطل تنفيذ النصوص البرمجية داخل التضمينات المستضافة.

    النصوص البرمجية (افتراضي)

    يسمح بالتضمينات التفاعلية مع الحفاظ على عزل الأصل؛ هذا هو الافتراضي وعادة ما يكفي لألعاب/ودجات المتصفح ذاتية الاحتواء.

    موثوق

    يضيف allow-same-origin فوق allow-scripts للمستندات من الموقع نفسه التي تحتاج عمدا إلى امتيازات أقوى.

    مثال:

    {
      gateway: {
        controlUi: {
          embedSandbox: "scripts",
        },
      },
    }
    

    تبقى عناوين URL الخارجية المطلقة http(s) للتضمين محظورة افتراضيا. إذا كنت تريد عمدا تحميل صفحات أطراف ثالثة عبر [embed url="https://..."]، فاضبط gateway.controlUi.allowExternalEmbedUrls: true.

    عرض رسائل الدردشة

    تستخدم رسائل الدردشة المجمعة حدا أقصى افتراضيا مقروءا للعرض. يمكن لعمليات النشر على الشاشات العريضة تجاوزه دون تعديل CSS المضمن عن طريق ضبط gateway.controlUi.chatMessageMaxWidth:

    {
      gateway: {
        controlUi: {
          chatMessageMaxWidth: "min(1280px, 82%)",
        },
      },
    }
    

    تتحقق القيمة قبل وصولها إلى المتصفح. تشمل القيم المدعومة الأطوال والنسب المئوية البسيطة مثل 960px أو 82%، إضافة إلى تعبيرات العرض المقيدة min(...)، وmax(...)، وclamp(...)، وcalc(...)، وfit-content(...).

    الوصول عبر tailnet (موصى به)

    Tailscale Serve مدمج (مفضل)

    أبق Gateway على local loopback ودع Tailscale Serve يوكله عبر HTTPS:

    openclaw gateway --tailscale serve
    

    افتح:

    • https://<magicdns>/ (أو gateway.controlUi.basePath المكون لديك)

    افتراضيا، يمكن لطلبات واجهة التحكم/WebSocket Serve المصادقة عبر رؤوس هوية Tailscale (tailscale-user-login) عندما يكون gateway.auth.allowTailscale هو true. يتحقق OpenClaw من الهوية عبر حل عنوان x-forwarded-for باستخدام tailscale whois ومطابقته مع الرأس، ولا يقبل ذلك إلا عندما يصل الطلب إلى local loopback مع رؤوس x-forwarded-* الخاصة بـ Tailscale. وبالنسبة إلى جلسات مشغل واجهة التحكم ذات هوية جهاز المتصفح، يتخطى مسار Serve المتحقق منه هذا أيضا رحلة إقران الجهاز؛ أما المتصفحات بلا جهاز واتصالات دور العقدة فتظل تتبع فحوصات الجهاز العادية. اضبط gateway.auth.allowTailscale: false إذا كنت تريد طلب بيانات اعتماد سر مشترك صريحة حتى لحركة مرور Serve. ثم استخدم gateway.auth.mode: "token" أو "password".

    بالنسبة إلى مسار هوية Serve غير المتزامن هذا، تسلسل محاولات المصادقة الفاشلة لعنوان IP العميل نفسه ونطاق المصادقة نفسه قبل كتابة حدود المعدل. لذلك يمكن أن تظهر محاولات إعادة المحاولة السيئة المتزامنة من المتصفح نفسه retry later في الطلب الثاني بدلا من تسابق عدم تطابقين عاديين بالتوازي.

    الربط بـ tailnet + الرمز

    openclaw gateway --bind tailnet --token "$(openssl rand -hex 32)"
    

    ثم افتح:

    • http://<tailscale-ip>:18789/ (أو gateway.controlUi.basePath المكون لديك)

    الصق السرّ المشترك المطابق في إعدادات الواجهة (يُرسل كـ connect.params.auth.token أو connect.params.auth.password).

    HTTP غير الآمن

    إذا فتحت لوحة المعلومات عبر HTTP عادي (http://<lan-ip> أو http://<tailscale-ip>)، يعمل المتصفح في سياق غير آمن ويحظر WebCrypto. افتراضيًا، يحظر OpenClaw اتصالات واجهة التحكم من دون هوية جهاز.

    الاستثناءات الموثّقة:

    • توافق HTTP غير الآمن للـ localhost فقط باستخدام gateway.controlUi.allowInsecureAuth=true
    • نجاح مصادقة واجهة التحكم الخاصة بالمشغل عبر gateway.auth.mode: "trusted-proxy"
    • خيار الطوارئ gateway.controlUi.dangerouslyDisableDeviceAuth=true

    الإصلاح الموصى به: استخدم HTTPS (Tailscale Serve) أو افتح الواجهة محليًا:

    • https://<magicdns>/ (Serve)
    • http://127.0.0.1:18789/ (على مضيف Gateway)
    سلوك مفتاح المصادقة غير الآمنة
    {
      gateway: {
        controlUi: { allowInsecureAuth: true },
        bind: "tailnet",
        auth: { mode: "token", token: "replace-me" },
      },
    }
    

    allowInsecureAuth هو مفتاح توافق محلي فقط:

    • يسمح لجلسات واجهة التحكم على localhost بالمتابعة من دون هوية جهاز في سياقات HTTP غير الآمنة.
    • لا يتجاوز فحوصات الإقران.
    • لا يخفف متطلبات هوية الجهاز البعيد (غير localhost).
    للطوارئ فقط
    {
      gateway: {
        controlUi: { dangerouslyDisableDeviceAuth: true },
        bind: "tailnet",
        auth: { mode: "token", token: "replace-me" },
      },
    }
    
    ملاحظة الوكيل الموثوق
    • يمكن أن تسمح مصادقة الوكيل الموثوق الناجحة بجلسات واجهة التحكم الخاصة بالمشغل من دون هوية جهاز.
    • لا يمتد هذا إلى جلسات واجهة التحكم ذات دور العقدة.
    • لا تزال وكلاء العكس عبر local loopback على المضيف نفسه لا تفي بمصادقة الوكيل الموثوق؛ راجع مصادقة الوكيل الموثوق.

    راجع Tailscale للحصول على إرشادات إعداد HTTPS.

    سياسة أمان المحتوى

    تأتي واجهة التحكم مع سياسة img-src صارمة: لا يُسمح إلا بأصول نفس المصدر، وعناوين URL من نوع data:، وعناوين URL من نوع blob: المولّدة محليًا. يرفض المتصفح عناوين URL البعيدة بصيغة http(s) والعناوين النسبية إلى البروتوكول، ولا يصدر طلبات جلب عبر الشبكة.

    ما يعنيه ذلك عمليًا:

    • تظل الصور الرمزية والصور المقدّمة ضمن مسارات نسبية (مثل /avatars/<id>) تُعرض، بما في ذلك مسارات الصور الرمزية المصادَق عليها التي تجلبها الواجهة وتحولها إلى عناوين URL محلية من نوع blob:.
    • تظل عناوين URL المضمّنة data:image/... تُعرض (مفيدة للحمولات داخل البروتوكول).
    • تظل عناوين URL المحلية من نوع blob: التي تنشئها واجهة التحكم تُعرض.
    • تُزال عناوين URL البعيدة للصور الرمزية الصادرة عن بيانات تعريف القنوات في مساعدات الصور الرمزية الخاصة بواجهة التحكم وتُستبدل بالشعار/الشارة المدمجة، لذلك لا تستطيع قناة مخترقة أو خبيثة إجبار متصفح المشغل على جلب صور بعيدة عشوائية.

    لا تحتاج إلى تغيير أي شيء للحصول على هذا السلوك — فهو مفعّل دائمًا وغير قابل للتهيئة.

    مصادقة مسار الصورة الرمزية

    عند تهيئة مصادقة Gateway، تتطلب نقطة نهاية الصورة الرمزية في واجهة التحكم رمز Gateway نفسه المستخدم في بقية API:

    • يعيد GET /avatar/<agentId> صورة الصورة الرمزية للمتصلين المصادَق عليهم فقط. ويعيد GET /avatar/<agentId>?meta=1 بيانات تعريف الصورة الرمزية وفق القاعدة نفسها.
    • تُرفض الطلبات غير المصادَق عليها إلى أي من المسارين (مطابقة لمسار وسائط المساعد الشقيق). يمنع هذا مسار الصورة الرمزية من تسريب هوية الوكيل على المضيفات المحمية بخلاف ذلك.
    • تمرر واجهة التحكم نفسها رمز Gateway كترويسة bearer عند جلب الصور الرمزية، وتستخدم عناوين URL مصادَق عليها من نوع blob بحيث تظل الصورة تُعرض في لوحات المعلومات.

    إذا عطّلت مصادقة Gateway (غير موصى به على المضيفات المشتركة)، يصبح مسار الصورة الرمزية غير مصادَق عليه أيضًا، بما يتماشى مع بقية Gateway.

    مصادقة مسار وسائط المساعد

    عند تهيئة مصادقة Gateway، تستخدم معاينات الوسائط المحلية للمساعد مسارًا من خطوتين:

    • يتطلب GET /__openclaw__/assistant-media?meta=1&source=<path> مصادقة مشغل واجهة التحكم العادية. يرسل المتصفح رمز Gateway كترويسة bearer عند التحقق من التوفر.
    • تتضمن استجابات بيانات التعريف الناجحة mediaTicket قصير العمر ومقيّدًا بمسار المصدر المحدد تمامًا.
    • تستخدم عناوين URL للصور والصوت والفيديو والمستندات المعروضة في المتصفح mediaTicket=<ticket> بدلًا من رمز Gateway النشط أو كلمة المرور. تنتهي صلاحية التذكرة بسرعة ولا يمكنها تفويض مصدر مختلف.

    يحافظ هذا على توافق عرض الوسائط العادي مع عناصر الوسائط الأصلية في المتصفح من دون وضع بيانات اعتماد Gateway قابلة لإعادة الاستخدام في عناوين URL المرئية للوسائط.

    بناء الواجهة

    يقدّم Gateway ملفات ثابتة من dist/control-ui. ابنها باستخدام:

    pnpm ui:build
    

    أساس مطلق اختياري (عندما تريد عناوين URL ثابتة للأصول):

    OPENCLAW_CONTROL_UI_BASE_PATH=/openclaw/ pnpm ui:build
    

    للتطوير المحلي (خادم تطوير منفصل):

    pnpm ui:dev
    

    ثم وجّه الواجهة إلى عنوان URL الخاص بـ WS في Gateway لديك (مثل ws://127.0.0.1:18789).

    التصحيح/الاختبار: خادم التطوير + Gateway بعيد

    واجهة التحكم هي ملفات ثابتة؛ هدف WebSocket قابل للتهيئة ويمكن أن يكون مختلفًا عن أصل HTTP. يكون هذا مفيدًا عندما تريد تشغيل خادم تطوير Vite محليًا بينما يعمل Gateway في مكان آخر.

  • ابدأ خادم تطوير الواجهة

    pnpm ui:dev
    
  • افتح باستخدام gatewayUrl

    http://localhost:5173/?gatewayUrl=ws%3A%2F%2F<gateway-host>%3A18789
    

    مصادقة اختيارية لمرة واحدة (إذا لزم الأمر):

    http://localhost:5173/?gatewayUrl=wss%3A%2F%2F<gateway-host>%3A18789#token=<gateway-token>
    
  • ملاحظات
    • يُخزّن gatewayUrl في localStorage بعد التحميل ويُزال من عنوان URL.
    • إذا مررت نقطة نهاية كاملة ws:// أو wss:// عبر gatewayUrl، فرمز قيمة gatewayUrl في عنوان URL حتى يفسّر المتصفح سلسلة الاستعلام بشكل صحيح.
    • يجب تمرير token عبر جزء عنوان URL (#token=...) كلما أمكن. لا تُرسل الأجزاء إلى الخادم، مما يتجنب تسريب سجلات الطلبات وReferer. لا تزال معاملات الاستعلام القديمة ?token= تُستورد مرة واحدة للتوافق، لكن كخيار احتياطي فقط، وتُزال فورًا بعد التمهيد.
    • تُحفظ password في الذاكرة فقط.
    • عند ضبط gatewayUrl، لا تعود الواجهة إلى بيانات اعتماد التهيئة أو البيئة. قدّم token (أو password) صراحةً. غياب بيانات الاعتماد الصريحة خطأ.
    • استخدم wss:// عندما يكون Gateway خلف TLS (Tailscale Serve، وكيل HTTPS، وما إلى ذلك).
    • لا يُقبل gatewayUrl إلا في نافذة من المستوى الأعلى (غير مضمّنة) لمنع الاختطاف بالنقر.
    • يجب أن تضبط عمليات نشر واجهة التحكم غير local loopback قيمة gateway.controlUi.allowedOrigins صراحةً (الأصول الكاملة). يشمل ذلك إعدادات التطوير البعيدة.
    • قد يزرع بدء تشغيل Gateway أصولًا محلية مثل http://localhost:<port> وhttp://127.0.0.1:<port> من الربط والمنفذ الفعليين وقت التشغيل، لكن أصول المتصفح البعيدة لا تزال تحتاج إلى إدخالات صريحة.
    • لا تستخدم gateway.controlUi.allowedOrigins: ["*"] إلا للاختبارات المحلية الخاضعة لرقابة صارمة. تعني السماح لأي أصل متصفح، وليس "طابق أي مضيف أستخدمه."
    • يفعّل gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true وضع الرجوع إلى أصل ترويسة Host، لكنه وضع أمني خطير.

    مثال:

    {
      gateway: {
        controlUi: {
          allowedOrigins: ["http://localhost:5173"],
        },
      },
    }
    

    تفاصيل إعداد الوصول البعيد: الوصول البعيد.

    ذات صلة