ویجت چت OrbitPilot — استریمینگ، قابل جابجایی، موبایلی و صوتی
این چیست
OrbitPilot اکنون یک ویجت چت شناور جهانی برای کاربران وارد شده است: یک دکمه 🛰 در گوشه یک پنل را باز میکند که میتوانید از هر صفحه استفاده کنید. این پنل غیرمسدودکننده است (در حالی که باز است به مرور خود ادامه دهید)، قابل جابجایی قابل جمع شدن است و جای خود را به خاطر میسپارد و گفتگوی باز شما را در حین گشت و گذار در وبسایت به یاد میآورد.
قابلیتهای جدید
- پاسخهای استریم شده — پاسخ کلمه به کلمه ظاهر میشود به جای اینکه بعد از یک زمان انتظار.
- توقف — متوقف کردن AI در وسط پاسخ. متوقف کردن هرچه در حال حاضر نوشته شده را ذخیره میکند و از تعداد درخواستهای مجاز شما کم نمیکند.
- کپی / دانلود کل چت — دکمههایی در بالای پنل و پایین پنل (دانلود به صورت یک متن .txt است).
- کپی یک پیام — بر روی هر حباب بایستید تا آیکن کپی نمایان شود.
- حداکثر کردن پنجره، مرور تاریخچه چت خود و شروع یک گفتگوی جدید.
- ورودی صوتی — بر روی میکروفون ضربه بزنید و صحبت کنید؛ کلمات شما به طور خودکار نوشته میشود.
مهمانها (که وارد نشدهاند) چت پاپ آپ صفحه اصلی را حفظ میکنند.
در تلفن شما (موبایلی)
- پنل به پایین صفحه لنگر میزند و هرگز از لبهها تجاوز نمیکند در هر حالتی — چرخاندن تلفن به طور خودکار آن را تنظیم میکند.
- به برش و نشاندهنده خانه احترام میگذارد (مناطق امن)، و از ارتفاع زنده صفحه استفاده میکند تا نوار آدرس مرورگر نتواند دکمه ارسال را برید.
- پس از اینکه صحبت کردید و ارسال کردید، جعبه خالی میشود برای سؤال بعدی شما — دوباره بر روی میکروفون ضربه بزنید تا برای نوبت بعدی صحبت کنید.
برای توسعهدهندگان
استریمینگ نیاز به یک نمایش غیرهمزمان زیر 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 قرار دارد، فقط برای کاربران احراز هویت شده.
واکنشپذیری موبایل (Workstream E): کل ویجت box-sizing: border-box است
بنابراین حاشیه 1px داخل عرض محاسبه میشود (اوج overflow iPhone قدیمی width:100vw + border بود). قانون @media (max-width:575px)
100vw را برای left/right: env(safe-area-inset-*) + width:auto حذف میکند، اندازهها
با dvh (با یک vh پشتیبان) اندازهگیری میشود و صفحهساز با
env(safe-area-inset-bottom) padding میشود. در JS، یک موقعیت کشیده شده در دسکتاپ در برگه موبایل اعمال نمیشود و یک شنونده resize/orientationchange موقعیت را از طریق applyPos() دوباره تنظیم میکند. پاکسازی صدا: ماژول گفتار یک بافر saved نهایی را جدا از ورودی نگه میدارد؛ 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. دکمهها یک --op-chat-font متغیر CSS را فشار میدهند که توسط
بدنه پیام + ورودی خوانده میشود؛ صفحهساز از min-width:0 در جعبه متن و flex:0 0 auto در
دکمهها استفاده میکند بنابراین ارسال هرگز از صفحه بیرون نمیرود.
منوی همبرگری + حالت صفحه کامل (2026-07-27)
هدر ویجت چت اکنون دارای یک منو و یک دکمه صفحه کامل است:
- دستورالعملهای شما — یادداشتهای دائمی که AI همیشه در نظر میگیرد (مانند دستورالعملهای سفارشی ChatGPT). ذخیره شده در
OrbitPilotSettings.custom_user_promptاز طریقorbitpilot_custom_instructions; برنامه قفلگذاری شده توسط ویژگیcustom_prompt(یک پیام قفل شده + لینک ارتقا در صورتی که طرح اجازه ندهد ظاهر میشود؛ سرور نیز آن را با 403 تحمیل میکند). - بارگذاریها — اکنون به وضوح دو گزینه: “فقط این گفتگو”
(
orbitpilot_conversation_download) در مقابل “تمام تاریخچه چت من” (جدیدorbitpilot_history_download). دکمه نوار ابزار به “ این چت” تغییر نام یافته است. - حافظه → بازسازی حافظه من اکنون — یک بازسازی کامل
(
orbitpilot_rebuild_memory) با یک هشدار هزینه تأیید پشت سر هم (همه چیز را دوباره میخواند و دوباره جاسازی میکند، که از اعتبار AI استفاده میکند)؛ در حالی که یک بازسازی واقعاً در حال حاضر در حال اجرا است، انباشته نخواهد شد. (BL-404، 2026-09-07) اگر آن "ساخت در حال اجرا" واقعاً خراب شده یا توسط یک راهاندازی مجدد سرور متوقف شده باشد — گیر افتاده در برنامهریزی شده یا در حال اجرا بیش از یک پنجره ایمن (10 دقیقه با کارگر زمینه فعال، 3 دقیقه بدون آن) — فشردن دکمه اکنون به طور خودکار آن را پاک میکند و یک بازسازی تازه را آغاز میکند، با استفاده از همان جمعکنندهای که بازرس بروشور همیشه از آن استفاده کرده است (orbitpilot.services.reap_stuck_builds). پاسخ میگوید یک ساخت گیر کرده پاک شده است نه اینکه چیزی نگذشته باشد. قبل از این اصلاح، یک ساخت مرده در آن حالت همواره بارگذاری را مسدود میکرد برای همیشه، بدون راهی برای آزاد کردن آن به جز اداری که بازرس را باز کند.
حالت صفحه کامل () /orbitpilot/chat/ را در یک برگه جدید باز میکند، یک چت مشابه ChatGPT/Gemini که
با همان ویجت (از طریق کلاس بدنه op-fullpage) دوباره استفاده میشود — بنابراین تغییر بین
ویجت کوچک و صفحه کامل همان گفتگو را نگه میدارد (محلی op_widget_conv ذخیره +
یک شنونده رویداد 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 با دیلتا، نه کل متن بالا میرود.
- 🔄 بازسازی کامل (سخت) — همه چیز را از نو دوباره میخواند و جاسازی میکند (از اعتبار AI بیشتری استفاده میکند). فقط در صورتی که چیزی نادرست به نظر برسد از آن استفاده کنید.
برای توسعهدهندگان: 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 چهار رفع مشکل را نمایان کرد:
- پیوندهای خراب AI (
your-app-link): مدل یک دامنه اختراع کرده بود زمانی که مسیرهای نسبی از یک بروشور قدیمی داده میشد. اکنون (الف) یک بررسی سلامت سیستم هشدار میدهد اگرSITE_URLدر تولید localhost باشد، و (ب)orbitpilot.services.heal_links()هر پیوند-placeholder/localhost را به واقعیت در هر پاسخ (استریم/مسدود کننده/مهمان) بازنویسی میکند — بنابراین لینکها حتی قبل از بازسازی کار میکنند. رفع دائمی (تنظیمSITE_URL+ بازسازی) در چک لیست تنظیمات مدیر است. - “لیست بلینکهای من” اکنون کار میکند:
pipeline/retrieve.py add_list_intent_sources()همه قطعات یک منبع را وقتی که پرسش یک درخواست شمارش باشد ("لیست/نمایش/همه بلینکها/وظایف/رویدادهای من")، و نمونههای هشدارهای بلینک را نمونهبرداری میکند — در نتیجه AI اقلام واقعی را لیست میکند، نه فقط تعداد آنها. - اقدامات قابل کلیک: اقدامات اکنون
{label, url}هستند. یک پیوند ناوبری واقعی به عنوان یک دکمه کلیک شدنی نمایش داده میشود (در یک برگه جدید باز میشود)؛ در غیر این صورت یک chip پرکننده است. این در ویجت، مدال خانگی مهمان (که قبلاً اقدامات را حذف میکرد)، و نتیجه صفحه کامل ثابت شده است. لینکهای پاسخ درون خطی نیز اکنون در یک برگه جدید باز میشوند. - صاف کردن پیام: پرسش اصلی پاسخ از تکرار بیش از حد هدف عنوان کاربر متوقف میشود و به طرز دلپذیری "چه چیزی از دیروز تغییر کرده" را مدیریت میکند (این از نمونه فعلی کار میکند، نه تاریخ روز به روز).
برای توسعهدهندگان: orbitpilot/services.py (heal_links, request_base,
split_answer_actions اکنون بازگشت dict است، لایه next_actions مهمان)،
pipeline/retrieve.py (add_list_intent_sources), adminapp/diagnostics.py
(_check_site_url), JS ویجت + home.html (رندر اقدام + DOMPurify target=_blank hook)،
aihub/prompt_registry.py (پیشفرضهای هسته + next_actions؛ با پیشفرضهای بذر未 touched بروزرسانی شده است
aihub/0007).
یک نوار ابزار، نه دو (2026-08-28)
چه چیزی تغییر کرده است. ویجت قبلاً از یک ردیف دکمه مشابه استفاده میکرد - جدید · تاریخ · کپی · این چت - دو بار: یک بار درست در زیر هدر بنفش، و دوباره در زیر جعبه پیام. اکنون یکی وجود دارد، در زیر جعبه پیام.
چرا. گزارش شماره 136، از یک تلفن. دو ردیف نوار ابزار داخل یک پنجره کوچک موجب محدودیت بیشتر در گفتگو میشد. این گزارش به کمی فضای باقی مانده در گفتگو اشاره داشت.
چرا ردیف پایینی باقی مانده است. این ردیفی است که یک انگشت بر روی تلفن به آن دسترسی دارد، در کنار جعبهای که شما در آن تایپ میکنید - که جایی است که "شروع یک چت جدید" و "کپی این چت" متعلق به آن است - و در حال حاضر همه دکمههایی را که ردیف بالایی داشت، حفظ کرده است. ابزارtips ردیف بالایی واژههای مشخصتری بود، بنابراین آنها با آن پایین آمدند.
هیچ چیز قابل دسترسی نیست. هدر دکمه «×» خود را حفظ میکند، بنابراین یک
ویجت جمع شده هنوز بسته میشود؛ و بستن در خارج از دروازه ورود باقی میماند، بنابراین یک مهمان میتواند هنوز
ویجت را ببندد. محافظت شده با 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.