Web interfaces

دردشة الويب

الحالة: تتحدث واجهة دردشة SwiftUI على macOS/iOS مباشرة إلى WebSocket الخاص بـ Gateway.

ما هي

  • واجهة دردشة أصلية للـ Gateway (بلا متصفح مضمّن وبلا خادم ثابت محلي).
  • تستخدم الجلسات وقواعد التوجيه نفسها مثل القنوات الأخرى.
  • توجيه حتمي: تعود الردود دائمًا إلى WebChat.

البدء السريع

  1. ابدأ تشغيل الـ Gateway.
  2. افتح واجهة WebChat (تطبيق macOS/iOS) أو تبويب الدردشة في واجهة التحكم.
  3. تأكد من تكوين مسار مصادقة Gateway صالح (سر مشترك افتراضيًا، حتى على local loopback).

كيف يعمل (السلوك)

  • تتصل الواجهة بـ WebSocket الخاص بـ Gateway وتستخدم chat.history وchat.send وchat.inject.
  • يكون chat.history محدودًا لضمان الاستقرار: قد يقتطع Gateway حقول النص الطويلة، ويحذف البيانات الوصفية الثقيلة، ويستبدل الإدخالات كبيرة الحجم بـ [chat.history omitted: message too large].
  • يتبع chat.history فرع النص الحالي النشط لملفات الجلسات الحديثة ذات الإلحاق فقط، لذلك لا تُعرض فروع إعادة الكتابة المتروكة ونسخ المطالبات المستبدلة في WebChat.
  • تُعرض إدخالات Compaction كفاصل واضح للتاريخ المضغوط. يوضح الفاصل أن الأدوار السابقة محفوظة في نقطة تحقق ويربط بعناصر التحكم في نقاط تحقق الجلسات، حيث يستطيع المشغلون إنشاء فرع أو استعادة عرض ما قبل Compaction عندما تسمح أذوناتهم بذلك.
  • تتذكر واجهة التحكم sessionId الخاص بـ Gateway الذي يعيده chat.history وتضمّنه في استدعاءات chat.send اللاحقة، لذلك تواصل عمليات إعادة الاتصال وتحديث الصفحة المحادثة المخزنة نفسها ما لم يبدأ المستخدم جلسة أو يعيد ضبطها.
  • تدمج واجهة التحكم عمليات الإرسال المتطابقة قيد التنفيذ للجلسة والرسالة والمرفقات نفسها قبل إنشاء معرّف تشغيل chat.send جديد؛ ولا يزال Gateway يزيل تكرار الطلبات المعادة التي تعيد استخدام مفتاح idempotency نفسه.
  • تُمرَّر ملفات بدء تشغيل مساحة العمل وتعليمات BOOTSTRAP.md المعلقة عبر سياق المشروع في مطالبة نظام الوكيل، ولا تُنسخ إلى رسالة مستخدم WebChat. لا يضيف اقتطاع bootstrap إلا إشعار استرداد موجزًا في مطالبة النظام؛ وتبقى العدادات التفصيلية ومفاتيح التكوين في أسطح التشخيص.
  • يجري أيضًا تطبيع عرض chat.history: سياق OpenClaw الخاص بوقت التشغيل فقط، وأغلفة المغلفات الواردة، ووسوم توجيهات التسليم المضمّنة مثل [[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 فقط.
  • تُستبعد حمولات الرد الموسومة كاستدلال (isReasoning: true) من محتوى مساعد WebChat، ونص إعادة تشغيل السجل، وكتل المحتوى الصوتي، بحيث لا تظهر حمولات التفكير فقط كرسائل مساعد مرئية أو صوت قابل للتشغيل.
  • يضيف chat.inject ملاحظة مساعد مباشرة إلى النص وينشرها إلى الواجهة (بلا تشغيل وكيل).
  • يمكن أن تبقي عمليات التشغيل المُجهَضة إخراج المساعد الجزئي مرئيًا في الواجهة.
  • يحفظ Gateway نص المساعد الجزئي المُجهَض في تاريخ النص عندما يوجد إخراج مخزن مؤقتًا، ويعلّم تلك الإدخالات ببيانات وصفية للإجهاض.
  • يُجلب التاريخ دائمًا من الـ Gateway (بلا مراقبة ملفات محلية).
  • إذا تعذر الوصول إلى الـ Gateway، يكون WebChat للقراءة فقط.

نموذج النص والتسليم

يمتلك WebChat مساري بيانات منفصلين:

  • ملف JSONL للجلسة هو نص النموذج/وقت التشغيل الدائم. بالنسبة إلى عمليات تشغيل الوكيل العادية، يحفظ Pi رسائل user وassistant وtoolResult المرئية للنموذج عبر مدير الجلسات الخاص به. لا يكتب WebChat نصوص تسليم أو حالة أو مساعدة عشوائية في ذلك النص.
  • أحداث ReplyPayload الخاصة بـ Gateway هي إسقاط التسليم الحي. يمكن تطبيعها لعرض WebChat/القناة، وبث الكتل، ووسوم التوجيهات، وتضمين الوسائط، وأعلام TTS/الصوت، وسلوك الرجوع في الواجهة. وهي ليست بحد ذاتها سجل الجلسة القانوني.
  • يحقن WebChat إدخالات نص المساعد فقط عندما يملك Gateway رسالة معروضة خارج دور مساعد Pi عادي: chat.inject، وردود الأوامر غير الوكيلة، والإخراج الجزئي المُجهَض، ومكمّلات نص الوسائط التي يديرها WebChat.
  • يقرأ chat.history نص الجلسة المخزن ويطبق إسقاط عرض WebChat. إذا ظهر نص مساعد حي أثناء التشغيل ثم اختفى بعد إعادة تحميل التاريخ، فتحقق أولًا مما إذا كان JSONL الخام يحتوي على نص المساعد، ثم مما إذا كان إسقاط chat.history قد أزاله، ثم مما إذا كان دمج الذيل المتفائل في واجهة التحكم قد استبدل حالة التسليم المحلية باللقطة الدائمة.

ينبغي أن تكون الإجابات النهائية لتشغيل الوكيل العادي دائمة لأن Pi يكتب message_end الخاص بالمساعد. أي رجوع يعكس حمولة نهائية مسلّمة إلى النص يجب أن يتجنب أولًا تكرار دور مساعد كتبه Pi بالفعل.

لوحة أدوات الوكلاء في واجهة التحكم

  • تحتوي لوحة الأدوات /agents في واجهة التحكم على عرضين منفصلين:
    • تستخدم متاح الآن tools.effective(sessionKey=...) وتعرض ما تستطيع الجلسة الحالية استخدامه فعليًا وقت التشغيل، بما في ذلك الأدوات الأساسية وأدوات Plugin والأدوات المملوكة للقنوات.
    • تستخدم تكوين الأدوات tools.catalog وتظل مركزة على الملفات الشخصية والتجاوزات ودلالات الفهرس.
  • الإتاحة وقت التشغيل محددة بنطاق الجلسة. يمكن أن يغيّر تبديل الجلسات على الوكيل نفسه قائمة متاح الآن.
  • لا يعني محرر التكوين الإتاحة وقت التشغيل؛ فلا يزال الوصول الفعّال يتبع أسبقية السياسة (allow/deny، والتجاوزات حسب الوكيل والمزوّد/القناة).

الاستخدام البعيد

  • يمرر الوضع البعيد WebSocket الخاص بالـ Gateway عبر SSH/Tailscale.
  • لا تحتاج إلى تشغيل خادم WebChat منفصل.

مرجع التكوين (WebChat)

التكوين الكامل: التكوين

خيارات WebChat:

  • gateway.webchat.chatHistoryMaxChars: الحد الأقصى لعدد الأحرف لحقول النص في استجابات chat.history. عندما يتجاوز إدخال نص هذا الحد، يقتطع Gateway حقول النص الطويلة وقد يستبدل الرسائل كبيرة الحجم بعنصر نائب. يمكن للعميل أيضًا إرسال maxChars لكل طلب لتجاوز هذا الافتراضي لاستدعاء chat.history واحد.

الخيارات العامة ذات الصلة:

  • gateway.port, gateway.bind: مضيف/منفذ WebSocket.
  • gateway.auth.mode, gateway.auth.token, gateway.auth.password: مصادقة WebSocket بالسر المشترك.
  • gateway.auth.allowTailscale: يمكن أن يستخدم تبويب دردشة واجهة التحكم في المتصفح رؤوس هوية Tailscale Serve عند تفعيلها.
  • gateway.auth.mode: "trusted-proxy": مصادقة وكيل عكسي لعملاء المتصفح خلف مصدر وكيل غير loopback واعٍ بالهوية (راجع مصادقة الوكيل الموثوق).
  • gateway.remote.url, gateway.remote.token, gateway.remote.password: هدف Gateway البعيد.
  • session.*: تخزين الجلسات وافتراضيات المفتاح الرئيسي.

ذو صلة