feat(voice): add typed AI chat beside voice

Chat sits next to the mic in the command dock. Replies are silent and never
request the microphone; the first message connects with the selected provider
and runs the same map actions as voice through each provider's text API
(OpenAI OPENAI_CHAT_MODEL, Gemini GEMINI_CHAT_MODEL via generateContent, which
never starts Live). Only one mode runs at a time.

- Chat panel rendered by the voice control presenter: conversation, recent and
  quick-command suggestions, Up/Down history, attachments (map-layer
  references or small UTF-8 text files, sent only with the message)
- Chat and voice panels sit above the dock or dock into the right rail's
  column; minimized bars sit centred above the dock, and height animates on
  swaps
- A centred panel steps down to its bar for the Location and Visual Presets
  trays without moving focus, rests above an open tray, and docks right while
  expanded over one; it returns to the centre once the trays close
- Minimized voice previews the last sentence from each side; the empty Voice
  Preview suggests things to say
- Settings opened from chat keep chat's frame and show the shared AI provider
  and quick commands; voice Settings show Back to voice
- Closing chat ends a typed session; the voice panel's close turns voice off
- The dock widens its voice control for the chat button and restyles its
  wings, which show icons only at 900px and below; assistant panels share the
  left panels' glass, and Cyber keeps its own surfaces
- Server text-chat handlers with body, time and per-IP limits
  (GEV_RATELIMIT_*_CHAT_PER_MIN), documented in SECURITY.md; tests and all
  eleven locales

Co-authored-by: Darren Dignam <[email protected]>
This commit is contained in:
manjunath22466andDarren Dignam committed 2026-11-02 20:56:39 +05:30
1 parent 720260af58
commit af461febae
57 files changed
+6500 -63

No files matched your search

+63 -1
View File
@@ -3218,5 +3218,67 @@
"Load scenes from an exported JSON file": "تحميل المشاهد من ملف JSON مُصدَّر",
"Download the timing log of the last play": "تنزيل سجل توقيت آخر تشغيل",
"Edit anchors, data packs and shot details": "تعديل نقاط الارتكاز وحزم البيانات وتفاصيل اللقطة",
"Download this scene as JSON or an asset bundle": "تنزيل هذا المشهد بصيغة JSON أو حزمة موارد"
"Download this scene as JSON or an asset bundle": "تنزيل هذا المشهد بصيغة JSON أو حزمة موارد",
"Fly to Tokyo": "الانتقال إلى طوكيو",
"Show live flights": "عرض الرحلات المباشرة",
"AI chat": "دردشة الذكاء الاصطناعي",
"GEV CHAT": "دردشة GEV",
"Ask about the map. Tell it where to go.": "اسأل عن الخريطة. أخبرها إلى أين تذهب.",
"Close chat": "إغلاق الدردشة",
"Conversation": "المحادثة",
"Explore with a question": "استكشف بسؤال",
"Find a place, explore live data, or change your view.": "ابحث عن مكان، أو استكشف بيانات مباشرة، أو غيّر العرض.",
"Attachments": "المرفقات",
"Remove attachment": "إزالة المرفق",
"Attach a map layer": "إرفاق طبقة خريطة",
"Choose a layer…": "اختر طبقة…",
"Attach a file": "إرفاق ملف",
"TXT, Markdown, CSV, JSON or GeoJSON · up to 10 KB each. Attachments are sent to your AI provider with your message.": "TXT أو Markdown أو CSV أو JSON أو GeoJSON · حتى 10 كيلوبايت لكل ملف. تُرسل المرفقات إلى مزوّد الذكاء الاصطناعي مع رسالتك.",
"Latest AI response": "أحدث رد من الذكاء الاصطناعي",
"Expand conversation": "توسيع المحادثة",
"Command suggestions": "اقتراحات الأوامر",
"Expand chat": "توسيع الدردشة",
"Add attachment": "إضافة مرفق",
"Message GEV": "رسالة إلى GEV",
"Ask GEV anything about the map…": "اسأل GEV أي شيء عن الخريطة…",
"Stop reply": "إيقاف الرد",
"Send message": "إرسال الرسالة",
"Panel position": "موضع اللوحة",
"Move above the dock": "النقل فوق الشريط",
"Dock to the right": "تثبيت إلى اليمين",
"Expand panel": "توسيع اللوحة",
"Minimize panel": "تصغير اللوحة",
"You can attach up to four items.": "يمكنك إرفاق أربعة عناصر كحد أقصى.",
"Attachments are too large together. Use smaller files.": "المرفقات كبيرة جدًا معًا. استخدم ملفات أصغر.",
"Choose a TXT, Markdown, CSV, JSON or GeoJSON file.": "اختر ملف TXT أو Markdown أو CSV أو JSON أو GeoJSON.",
"Each file must be 10 KB or smaller.": "يجب ألا يتجاوز حجم كل ملف 10 كيلوبايت.",
"Choose a non-empty UTF-8 text file.": "اختر ملفًا نصيًا بترميز UTF-8 غير فارغ.",
"Connecting…": "جارٍ الاتصال…",
"Thinking…": "جارٍ التفكير…",
"Working on the map…": "جارٍ العمل على الخريطة…",
"Silent chat · microphone off": "دردشة صامتة · الميكروفون متوقف",
"Reply interrupted. You can try again.": "توقف الرد. يمكنك المحاولة مرة أخرى.",
"Could not connect. Try again.": "تعذّر الاتصال. حاول مرة أخرى.",
"Session ended. Send a message to start a new conversation.": "انتهت الجلسة. أرسل رسالة لبدء محادثة جديدة.",
"Connection timed out. Try again.": "انتهت مهلة الاتصال. حاول مرة أخرى.",
"Chat closed.": "أُغلقت الدردشة.",
"Connection stopped.": "توقف الاتصال.",
"Message and attachments are too large. Remove an attachment or shorten your message.": "الرسالة والمرفقات كبيرة جدًا. أزل مرفقًا أو اختصر رسالتك.",
"Message was not sent. Try again.": "لم تُرسل الرسالة. حاول مرة أخرى.",
"Reply stopped.": "أُوقف الرد.",
"Suggestions": "اقتراحات",
"Recent": "الأخيرة",
"Quick commands": "أوامر سريعة",
"Open AI chat": "فتح دردشة الذكاء الاصطناعي",
"CHAT": "دردشة",
"Back to chat": "العودة إلى الدردشة",
"Back to voice": "العودة إلى الصوت",
"Latest voice exchange": "آخر تبادل صوتي",
"Try saying": "جرّب أن تقول",
"What am I looking at?": "ما الذي أنظر إليه؟",
"AI Provider": "مزوّد الذكاء الاصطناعي",
"The selected AI provider is shared by voice and chat.": "مزوّد الذكاء الاصطناعي المختار مشترك بين الصوت والدردشة.",
"Show quick commands": "إظهار الأوامر السريعة",
"Chat replies are silent. No microphone access is needed.": "ردود الدردشة صامتة. لا حاجة إلى الوصول إلى الميكروفون.",
"Chat": "الدردشة"
}