Skip to main content
OrbitPilot

ويدجت محادثة OrbitPilot — تدفق، قابل للتحريك، موبايل وصوتي

ما هو

OrbitPilot الآن هو ويدجت محادثة عائم عالمي للمستخدمين المسجلين: زر يفتح لوحة يمكنك استخدامها من أي صفحة. اللوحة غير معرقلة (استمر في التصفح بينما هي مفتوحة)، قابلة للسحب، قابلة للطي، وتتذكر مكانها ومحادثتك المفتوحة أثناء تنقلك في الموقع.

قدرات جديدة

  • تدفق الإجابات — تظهر الردود كلمة بكلمة بدلاً من الانتظار.
  • إيقاف — توقف الذكاء الاصطناعي في منتصف الإجابة. الإيقاف يحفظ ما تم كتابته حتى الآن ولا يستهلك سؤالاً من رصيدك الشهري.
  • نسخ / تحميل الدردشة كاملة — أزرار في أعلى وأسفل اللوحة (التحميل هو نص .txt).
  • نسخ رسالة واحدة — مرر فوق أي فقاعة للحصول على أيقونة النسخ.
  • تكبير النافذة، تصفح سجل المحادثات، وابدأ محادثة جديدة.
  • إدخال صوتي — اضغط على الميكروفون وتحدث؛ يتم كتابة كلماتك نيابة عنك.

الزوار (غير المسجلين) يحتفظون بنوافذ المحادثة الأصلية في الصفحة الرئيسية.

على هاتفك (جوال)

  • اللوحة تثبت في أسفل الشاشة ولا تتجاوز الحواف، في أي اتجاه — تدوير الهاتف يعيد تشكيلها تلقائيًا.
  • تحترم فتحة الشاشة ومؤشر الصفحة الرئيسية (المناطق الآمنة)، وتستخدم ارتفاع الشاشة المباشر بحيث لا يمكن لشريط العنوان في المتصفح قطع زر الإرسال.
  • بعد أن تتحدث وترسل، تُ emptied الصندوق للسؤال التالي — اضغط على الميكروفون مرة أخرى للتحدث في الدور التالي.

للمطورين

يتطلب التدفق عرضًا غير متزامن تحت ASGI (مولد متزامن يحمل قبل البايت الأول). orbitpilot.views.orbitpilot_ask_stream هو async def ترجع StreamingHttpResponse عبر مولد غير متزامن يبث أحداث سيرفر-تم إرسالها (meta → token… → done). جميع ORM/gating تعمل في مساعدين متزامنين (_prepare_ask_stream / _finalize_ask_stream) عبر sync_to_async(thread_sensitive=True). إيقاف = العميل يبطل جلب البيانات → يتم إلغاء المولد غير المتزامن → يتم حفظ الإجابة الجزئية ولا تُكتب صفحة الحصة. يعيش الواجهة الأمامية في templates/_orbitpilot_widget.html + static/css/orbitpilot-widget.css + static/js/orbitpilot-widget.js، مضمنة فقط للمستخدمين المعتمدين في base.html.

استجابة الهاتف المحمول (Workstream E): الويدجت ككل هو box-sizing: border-box لذا يحتسب حد 1px داخل العرض (كان تدفق iPhone القديم هو width:100vw + border). تُسقط قاعدة @media (max-width:575px) 100vw لـ left/right: env(safe-area-inset-*) + width:auto، وتحجم مع dvh (مع احتياطي vh)، وتجهز المؤلف مع env(safe-area-inset-bottom). في JS، لا يتم تطبيق موضع سحب سطح المكتب المحفوظ على واجهة عرض الهاتف المحمول، ويعيد مستمع resize/orientationchange تثبيت الموضع عبر applyPos(). مسح الصوت: تحافظ وحدة الكلام على buffer النهائي المنفصل عن الإدخال؛ send() تستدعي الآن resetVoice() المشتركة (إيقاف التعرف، مسح مؤقت الصمت، فراغ saved) بالضبط حيث تمسح input.value، لذا تبدأ الدور التالي فارغًا.

حجم خط المحادثة + إصلاح إرسال الهاتف المحمول (2026-07-27)

  • A− / A+ في رأس الويدجت تصغر/تكبر نص المحادثة. يتم تذكر اختيارك (محفوظ في المتصفح عبر localStorage مفتاح op_widget_font) عبر الصفحات والجلسات. الحجم محدود بين 12−22px.
  • زر الإرسال على الهواتف: يحتفظ صف المؤلف الآن بأزرار الإرسال (والميكروفون) مرئية بجانب مربع النص على الشاشات الضيقة — سابقًا كان يمكن لمربع النص دفع زر الإرسال من الحافة اليمنى.

للمطورين: تعليمات templates/_orbitpilot_widget.html، السلوك static/js/orbitpilot-widget.js (applyFont()/bumpFont()، المستعادة عند البدء)، التنسيق static/css/orbitpilot-widget.css. تدفع الأزرار متغير CSS --op-chat-font الذي تقرأه جسم الرسالة + الإدخال؛ يستخدم المؤلف min-width:0 على منطقة النص وflex:0 0 auto على a الأزرار حتى لا يتم دفع زر الإرسال بعيدًا عن الشاشة.

قائمة الطعام + وضع ملء الشاشة (2026-07-27)

رأس ويدجت المحادثة الآن يحتوي على قائمة وزر ملء الشاشة:

  • تعليماتك — ملاحظات قائمة يقيمها الذكاء الاصطناعي دائمًا (مثل تعليمات ChatGPT المخصصة). محفوظة في OrbitPilotSettings.custom_user_prompt عبر orbitpilot_custom_instructions؛ مقيدة بالخطة من خلال ميزة custom_prompt (تظهر رسالة مغلقة + رابط ترقية إذا لم تسمح الخطة بذلك؛ كما يفرض الخادم ذلك برمز 403).
  • التنزيلات — الآن بوضوح خيارين: هذه المحادثة فقط (orbitpilot_conversation_download) مقابل كل سجل المحادثات الخاص بي (جديد orbitpilot_history_download). يتم إعادة تسمية زر شريط الأدوات إلى b هذه المحادثة.
  • الذاكرة → إعادة بناء ذاكرتي الآن — إعادة بناء كاملة (orbitpilot_rebuild_memory) خلف تحذير تكاليف تأكيد (يعيد قراءة كل شيء وإعادة تضمينه، مما يستخدم اعتمادات الذكاء الاصطناعي)؛ لن يتم دمج إعادة بناء طالما أن واحدة حقًا قيد التشغيل. (BL-404، 2026-09-07) إذا كان ذلك "قيد التشغيل بالفعل" قد تعطل بالفعل أو تم إنهاؤه بواسطة إعادة تشغيل الخادم — عالق في المخطط أو قيد التشغيل لفترة طويلة بعد نافذة آمنة (10 دقائق مع العمل الخلفي مع، 3 دقائق بدون ذلك) — الضغط على الزر الآن يمسح ذلك تلقائيًا ويبدأ إعادة بناء جديدة، باستخدام نفس الجني الذي استخدمه دائمًا مدقق الدليل (orbitpilot.services.reap_stuck_builds). تقول الاستجابة إن إعادة البناء العالقة قد تم مسحها بدلاً من التظاهر بأن شيئًا لم يحدث. قبل هذا الإصلاح، كان إعادة البناء المتعطل في هذه الحالة يمنع التحديث إلى الأبد، دون أي طريقة لإزالته باستثناء فتح المدقق بواسطة المسؤول.

وضع ملء الشاشة (زر ملء الشاشة) يفتح /orbitpilot/chat/ في علامة تبويب جديدة، محادثة ملء الشاشة على نمط ChatGPT/Gemini تعيد استخدام نفس الويدجت (عبر فئة الجسم op-fullpage) — لذا الانتقال بين الويدجت الصغيرة وصفحة الملء تحتفظ بنفس المحادثة (مشتركة op_widget_conv في التخزين المحلي + a مستمع storage). أيضًا: A− / A+ يغير خط المحادثة (مُذكر)، وعلى الهاتف يظل زر الإرسال مرئيًا بجانب الميكروفون.

للمطورين: تعليمات templates/_orbitpilot_widget.html، السلوك static/js/orbitpilot-widget.js، التنسيق static/css/orbitpilot-widget.css؛ عرض ملء الصفحة orbitpilot.views.orbitpilot_chat → orbitpilot/templates/orbitpilot/chat_full.html.

تحديث سريع مقابل إعادة بناء كاملة (ذاكرة ناعمة/صلبة، 2026-07-27)

قائمة الويدجت الذاكرة الآن تقدم إعادة بناءين:

  • تحديث سريع (ناعم) — يعيد قراءة وإعادة تضمين فقط العناصر التي قمت بتغييرها منذ آخر بناء؛ العناصر التي لم تتغير تبقى على حالها مع تضمينها، والعناصر المحذوفة يتم إسقاطها. تكلفة أقل بكثير، لأن تكلفة تضمين OpenAI تتزايد مع الدلتا، وليس مع الكل.
  • إعادة بناء كاملة (صلبة) — يعيد قراءة وإعادة تضمين كل شيء من البداية (يستخدم المزيد من اعتمادات الذكاء الاصطناعي). استخدمه فقط إذا كان هناك شيء يبدو خاطئًا.

للمطورين: run_memory_build(user, settings, build, incremental=True) يقارن الكتل الجديدة بضد المخزنة بواسطة (source_key, source_id, chunk_index, content_hash) المفتاح قبل استدعاء embed_chunks، بحيث يتم تضمين الكتل الجديدة/المتغيرة فقط؛ تتم إزالة الأسطر القديمة في نفس الكتلة الذرية؛ تُترك الأسطر غير المتغيرة بدون مساس. يتم تمرير الوضع في OrbitPilotMemoryBuild.incremental (الترحيل orbitpilot/0025) ويتم تعيينه بواسطة orbitpilot_rebuild_memory من mode=soft|hard. إذا تم حذف incremental، run_memory_build يقرأه من سجل البناء. يحتفظ المسار الكامل/الصلب بنفس سلوك الحذف الذري + إعادة التضمين السابق بالضبط.

إصلاحات مدفوعة بالمحادثة (2026-07-28)

تحليل محادثات OrbitPilot الحقيقية (المخففة من PII) أظهر أربع إصلاحات:

  • روابط AI المعطلة (your-app-link): أنشأ النموذج مجالًا عند تسلمه مسارات نسبية من كتيب قديم. الآن (أ) يفحص فحص صحة النظام إذا كان SITE_URL هو localhost في الإنتاج، و(ب) orbitpilot.services.heal_links() يعيد كتابة أي رابط لقطة/localhost إلى المضيف الحقيقي للموقع في كل إجابة (تدفق/محجوز/ضيف) — لذا تعمل الروابط حتى قبل إعادة البناء. الإصلاح الدائم (تعيين SITE_URL + إعادة البناء) موجود في قائمة التحقق من إعدادات الإدارة.
  • تعمل الآن قائمة بلينكس الخاصة بي: pipeline/retrieve.py add_list_intent_sources() تُدخل كل كتل المصدر عند استفسار يكون طلب تعداد ("قائمة/عرض/كل بلينكس/مهام/أحداثي"), ولقطة مساحة العمل ستمثل عناوين Blink — لذا تسرد AI العناصر الفعلية، وليس فقط العدد.
  • أعمال قابلة للنقر: الأعمال الآن {label, url}. رابط التنقل الفعلي يظهر كزر قابل للنقر (يفتح في علامة تبويب جديدة)؛ وإلا فهو شريحة ملء مسبق. تم إصلاحه عبر الويدجت، والنموذج المنزلي للضيف (الذي سقط سابقًا) ونتائج ملء الصفحة. الروابط المتداخلة الآن تفتح أيضًا في علامة تبويب جديدة.
  • تحسين المحفز: يتوقف المحفز الأساسي للإجابة عن تكرار هدف المستخدم بفرط ويتعامل مع "ما الذي تغير منذ البارحة" بمرونة (يعمل من لقطة الحالية، وليس تاريخ يوم بيوم).

للمطورين: orbitpilot/services.py (heal_links, request_base, split_answer_actions الآن ترجع قاموس، طبقة next_actions للضيف)، pipeline/retrieve.py (add_list_intent_sources), adminapp/diagnostics.py (_check_site_url)، JS الخاص بالويدجت + home.html (رسم الأعمال + التوصيل DOMPurify target=_blank), aihub/prompt_registry.py (الأساسي + الافتراضيات next_actions؛ تم تحديثها على الافتراضات المدخلة التي لم يتم العبث بها عبر aihub/0007).

شريط أدوات واحد، وليس اثنين (2026-08-28)

ما الذي تغير. كان الويدجت يستخدم رسم نفس صف الأزرار — جديد · تاريخ · نسخ · هذه المحادثة — مرتين: مرة واحدة مباشرة تحت الرأس البنفسجي، ومرة أخرى أسفل مربع الرسالة. الآن هناك واحد، أسفل مربع الرسالة.

لماذا. التقرير رقم #136، من هاتف. صفان من الكروم داخل نافذة قصيرة بالفعل تركت المحادثة بما كان موجودًا. كان التقرير عن مدى قلة المساحة التي كانت لديها المحادثة.

لماذا الصف السفلي هو الذي بقي. هو الذي يصل إليه إبهام على الهاتف، يجلس بجانب المربع الذي تكتب فيه — وهو المكان الذي تنتمي فيه "ابدأ محادثة جديدة" و"انسخ هذه المحادثة" — وكان يحمل بالفعل كل زر كان لدى الآخر. كانت نصوص أدوات الصف العلوي هي الكلمات الأكثر وضوحًا، لذا نزلت معه.

لم يصبح شيء غير متاح. يحتفظ الرأس بخاصية × الخاصة به، لذا لا يزال بإمكان الويدجت المنهارة الإغلاق؛ وتبقى خاصية الغلق خارج بوابة تسجيل الدخول، لذا لا يزال يمكن للضيف إغلاق الويدجت. محمي بواسطة orbitpilot/test_widget_toolbar.py.

الميكروفون: هدف واحد، جلسة واحدة (BL-447، 2026-09-09)

أبلغ المالك عن ميكروفون المحادثة كـ "العمل في المرة الأولى، ثم في المرة الثانية لا يعمل، وأحيانًا يتعطل". كانت الإنتاجية تحمل بالفعل التصحيح السابق عندما قال ذلك، لذا كان ما تبقى تحت ذلك، وليس نشرًا مفقودًا. كانت هناك ثلاثة أشياء خاطئة، وتشرح الأعراض الثلاثة المختلفة.

1. يمكن أن تعني الزر عكس ما يظهره

قرر معالج النقر ما يجب القيام به من خلال قراءة متغير واحد (wantListening، طلب المستخدم) بينما تم رسم الحالة الوردية النبض من متغير مختلف (listening، الحالة الفعلية لمحرك التشغيل). مكالمة stop() في المتصفح غير متزامنة، لذا بعد مهلة الصمت الستة ثوان وبعد كل إرسال هناك نافذة حيث يكون الطلب قد تم إيقافه بينما لا يزال المحرك قيد التشغيل — ويبقى الزر يبدو نشطًا. الضغط الذي يعني الإيقاف تم قراءته بالتالي على أنه البدء، والتصحيح السابق (بشكل صحيح، في حالته الخاصة) ابقى هذا الضغط على قيد الحياة حتى يعيد المحرك التشغيل. الضغط على الإيقاف أعاد تشغيل الميكروفون. لقد جعلت صورة المرآة لنفس الثغرة من الضغط الثاني يلغي الضغط الأول للمستخدم، لذا لم يبدأ الميكروفون على الإطلاق — هذا هو "في المرة الثانية لا يعمل".

الآن هناك متغير واحد. micOn هو ما طلبه المستخدم؛ يتم رسم الزر منه ويتم قراءة النقر منه، لذا لا يمكن أن تتعارض.

2. كائن التعرف الواحد خدم الصفحة بأكملها

تم بناء SpeechRecognition واحدة عند تحميل الصفحة وأعيد استخدامها إلى الأبد. هذا هو السبب الوحيد الذي جعل البداية قد تفشل بخطأ "حالة غير صالحة" على الإطلاق، وكائن مجبوس بواسطة انقطاع الشبكة أو ميكروفون ممسك بواسطة تطبيق آخر يبقى محشورًا حتى يتم إعادة تحميل الصفحة — "يعمل مرة واحدة، ثم مرة أخرى". كل ميكروفون آخر على الموقع (صندوق التقاط الصفحة الرئيسية، موثق الأخطاء، الإملاء الإداري) يبني بالفعل واحدًا جديدًا عند كل ضغط. الويدجت الخاصة بالمحادثة الآن تفعل الشيء نفسه، لذا يتم الحصول على محرك جديد مع كل ضغط.

3. غلق النافذة لم يحرر الميكروفون

close() لم يتوقف أبدًا عن التعرف ولم يتوقف شيئًا عند مغادرة الصفحة، لذا ترك غلق المحادثة منتصف الإملاء المحرك قيد التشغيل خلف لوحة مخفية: ظل مؤشر تسجيل المتصفح مُضاءً، واستمر دورة إعادة التشغيل إحتياطياً، وهبطت الكلمات في صندوق لم يكن بإمكان أحد رؤيته. هذا هو "التعطل". غلق النافذة ومغادرة الصفحة كلاهما الآن يحرر الميكروفون.

ما الذي تغير أيضًا الذي يمكنك رؤيته

  • الفشل يقول ما حدث. التمويل المحجوز، لم يتم العثور على ميكروفون، و "تلك الضغط لم تبدأ أي شيء" كانت تبدو واحدة — زر رمادي والموضوعة العادية. كل واحد يكتب الآن رسالته القصيرة الخاصة في صندوق الرسالة.
  • محرك معطل يستسلم بدلاً من الدوران. الإملاء لا يزال يبدأ نفسه من خلال فترة تفكير، وهذا هو السلوك المستخدم في كل ميكروفون هنا، ولكن جلسة تستمر في الانخفاض دون سماع الكلام على الإطلاق تتوقف بعد عدة محاولات وتقول ذلك. الكلام الحقيقي يعيد ملء ذلك الميزانية، لذا لا ينفد الإملاء العادي أبدًا.
  • صندوق المحادثة يأخذ لوحة المفاتيح فقط عندما يكون على الشاشة. إنهاء الإملاء كان يستهدف إدخال البيانات بشكل غير مشروط، مما قد يسحب لوحة المفاتيح إلى نافذة تم غلقها للتو.

للمطورين. الجلسة المحتضرة هي يتيمة — مرجع الجلسة الحالية يتم تعيينه إلى null وكل معالج يتحقق من هويته الخاصة قبل لمس أي شيء — لذا نتيجة نهائية متأخرة بعد الإرسال تُهمل لأنها تنتمي إلى جلسة لا يملكها أحد بعد الآن. هذا يحافظ على الضمان الذي كان يصل إليه الإصلاحين السابقين دون وجود علامة يمكن تركها مسلحة. تعيش المنطق في static/js/orbitpilot-widget.js (كتلة initVoice) ويضغط الشكل بواسطة adminapp/test_widget_mic.py و adminapp/test_voice_parity.py. لا يمكن تشغيل كلام المتصفح في مجموعة الاختبارات؛ اختبار دخان كروم حقيقي هو عنصر منفصل مقترح.

This guide was translated automatically. Read the English original.

🪐 OrbitPilot

Create a free account and I'll remember your conversations — sign up

🧠 Memory status