macOS companion app
تراكب صوتي
دورة حياة تراكب الصوت (macOS)
الجمهور: مساهمو تطبيق macOS. الهدف: الحفاظ على قابلية توقع تراكب الصوت عندما تتداخل كلمة التنبيه مع اضغط للتحدث.
النية الحالية
- إذا كان التراكب ظاهرًا بالفعل بسبب كلمة التنبيه وضغط المستخدم مفتاح الاختصار، فإن جلسة مفتاح الاختصار تتبنى النص الموجود بدلًا من إعادة تعيينه. يبقى التراكب ظاهرًا أثناء الضغط على مفتاح الاختصار. عند إفلات المستخدم: يتم الإرسال إذا وُجد نص بعد إزالة المسافات الطرفية، وإلا يتم الإخفاء.
- كلمة التنبيه وحدها لا تزال ترسل تلقائيًا عند الصمت؛ أما اضغط للتحدث فيرسل فورًا عند الإفلات.
تم التنفيذ (9 ديسمبر 2025)
- تحمل جلسات التراكب الآن رمزًا مميزًا لكل التقاط (كلمة تنبيه أو اضغط للتحدث). يتم إسقاط تحديثات الجزئي/النهائي/الإرسال/الإخفاء/المستوى عندما لا يطابق الرمز المميز، مما يتجنب ردود النداء القديمة.
- يتبنى اضغط للتحدث أي نص تراكب ظاهر كبادئة (لذلك فإن الضغط على مفتاح الاختصار أثناء ظهور تراكب التنبيه يُبقي النص ويضيف الكلام الجديد). ينتظر حتى 1.5 ثانية للحصول على نسخة نهائية قبل الرجوع إلى النص الحالي.
- يتم إصدار سجلات الرنين/التراكب عند
infoفي الفئاتvoicewake.overlayوvoicewake.pttوvoicewake.chime(بدء الجلسة، جزئي، نهائي، إرسال، إخفاء، سبب الرنين).
الخطوات التالية
VoiceSessionCoordinator(ممثل)- يمتلك
VoiceSessionواحدة بالضبط في كل مرة. - API (مستند إلى الرمز المميز):
beginWakeCaptureوbeginPushToTalkوupdatePartialوendCaptureوcancelوapplyCooldown. - يسقط ردود النداء التي تحمل رموزًا مميزة قديمة (يمنع أدوات التعرف القديمة من إعادة فتح التراكب).
- يمتلك
VoiceSession(نموذج)- الحقول:
tokenوsource(wakeWord|pushToTalk) والنص المثبت/المتقلب، وأعلام الرنين، والمؤقتات (الإرسال التلقائي، الخمول)، وoverlayMode(display|editing|sending) وموعد انتهاء فترة التهدئة.
- الحقول:
- ربط التراكب
- يعكس
VoiceSessionPublisher(ObservableObject) الجلسة النشطة إلى SwiftUI. - يعرض
VoiceWakeOverlayViewعبر الناشر فقط؛ ولا يغيّر الكائنات المفردة العامة مباشرة أبدًا. - تستدعي إجراءات مستخدم التراكب (
sendNowوdismissوedit) المنسق مع الرمز المميز للجلسة.
- يعكس
- مسار إرسال موحد
- عند
endCapture: إذا كان النص بعد إزالة المسافات الطرفية فارغًا ← إخفاء؛ وإلاperformSend(session:)(يشغل رنين الإرسال مرة واحدة، ويمرر، ثم يخفي). - اضغط للتحدث: بلا تأخير؛ كلمة التنبيه: تأخير اختياري للإرسال التلقائي.
- طبّق فترة تهدئة قصيرة على وقت تشغيل التنبيه بعد انتهاء اضغط للتحدث حتى لا تعيد كلمة التنبيه التشغيل فورًا.
- عند
- التسجيل
- يصدر المنسق سجلات
.infoفي النظام الفرعيai.openclaw، ضمن الفئتينvoicewake.overlayوvoicewake.chime. - الأحداث الرئيسية:
session_startedوadopted_by_push_to_talkوpartialوfinalizedوsendوdismissوcancelوcooldown.
- يصدر المنسق سجلات
قائمة التحقق للتصحيح
-
دفق السجلات أثناء إعادة إنتاج تراكب عالق:
sudo log stream --predicate 'subsystem == "ai.openclaw" AND category CONTAINS "voicewake"' --level info --style compact -
تحقق من وجود رمز مميز واحد فقط لجلسة نشطة؛ يجب أن يسقط المنسق ردود النداء القديمة.
-
تأكد من أن إفلات اضغط للتحدث يستدعي دائمًا
endCaptureمع الرمز المميز النشط؛ إذا كان النص فارغًا، فتوقعdismissبدون رنين أو إرسال.
خطوات الترحيل (مقترحة)
- أضف
VoiceSessionCoordinatorوVoiceSessionوVoiceSessionPublisher. - أعد هيكلة
VoiceWakeRuntimeلإنشاء الجلسات/تحديثها/إنهائها بدلًا من لمسVoiceWakeOverlayControllerمباشرة. - أعد هيكلة
VoicePushToTalkلتبني الجلسات الموجودة واستدعاءendCaptureعند الإفلات؛ وطبّق فترة تهدئة وقت التشغيل. - اربط
VoiceWakeOverlayControllerبالناشر؛ وأزل الاستدعاءات المباشرة من وقت التشغيل/اضغط للتحدث. - أضف اختبارات تكامل لتبني الجلسات، وفترة التهدئة، وإخفاء النص الفارغ.