# خطة: DTMF والهاتفة محليًا (On-Premise) بدون مقدّم خدمة خارجي — مع مسار مزدوج

> المشكلة: بعض العملاء (بنك مثلاً) لا يقبلون مرور الصوت/البيانات عبر مزوّد خارجي (Twilio/Plivo/OpenAI/ElevenLabs). وعملاء آخرون لا يمانعون. المطلوب حلّان يعملان من نفس المنصة، والاختيار لكل عميل.
>
> نتاج بحث معمق (يوليو 2026): Asterisk **AudioSocket**، FreeSWITCH، بروتوكولات DTMF المحلية (RFC 4733 / SIP INFO / in-band)، ومكوّنات AI المحلية (Whisper.cpp, Vosk, Piper, Kokoro, SILMA) — مبنية على ما أنجزناه فعلاً في المنصة.

---

## الفكرة المعمارية: "محرك هاتفة" قابل للتبديل لكل عميل

المنصة أصلاً متعددة المحرّكات (ElevenLabs / Twilio+OpenAI / Plivo / SIP). نضيف **محرّكًا رابعًا: On-Premise** ونجعل اختيار المحرك خاصية لكل عميل/وكيل. النتيجة مساران:

| | **المسار A: سحابي** (العميل العادي) | **المسار B: محلي بالكامل** (البنك) |
|---|---|---|
| الهاتفة | Twilio / Plivo / SIP trunk | **Asterisk أو FreeSWITCH** في مقر العميل |
| نقل الصوت | Media Streams (WebSocket) | **AudioSocket** (TCP، PCM خام) داخل شبكة العميل |
| DTMF | حدث `dtmf` من Twilio (مبني ✅) | **إطار DTMF 0x03** من AudioSocket (محلي 100%) |
| التعرف على الكلام (STT) | OpenAI Realtime (سحابي) | **Whisper.cpp / Vosk** محلي على GPU |
| النموذج اللغوي (LLM) | OpenAI / Groq | **Custom LLM محلي** (مبني ✅ — LM Studio/vLLM) |
| توليد الصوت (TTS) | ElevenLabs / OpenAI | **Piper / Kokoro / SILMA** محلي (RunPod/GPU مبني ✅) |
| قراءة بيانات ERP | Data Views (مبني ✅) | نفس Data Views لكن القاعدة داخل شبكة البنك |
| خروج أي بيانات للإنترنت | نعم (طبيعي) | **صفر — لا شيء يغادر مقر العميل** |

**النقطة الجوهرية:** المسار B يعيد استخدام **كل ما بنيناه** (Custom LLM، TTS محلي، Data Views، منطق التقاط DTMF). القطعة الناقصة الوحيدة هي **جسر AudioSocket + STT محلي**.

---

## لماذا AudioSocket هو الحل الأمثل للمسار المحلي (من البحث)

بروتوكول AudioSocket من Asterisk هو أبسط بروتوكول بث صوتي ممكن — اتصال TCP مباشر، رأس 3 بايت + حمولة:
- **UUID (0x01)**: معرّف الجلسة (16 بايت).
- **AUDIO (0x10)**: 320 بايت PCM (16-bit، 8kHz، mono = 20 مللي ثانية).
- **DTMF (0x03)**: بايت واحد = الرقم المضغوط. **DTMF يصل جاهزًا في نفس الاتصال — لا حاجة لأي معالجة نغمات.**

هذا يعني أن التقاط DTMF محليًا **أبسط** من السحابي: Asterisk يكشف النغمة (RFC 4733) ويرسلها كإطار 0x03، ونحن نقرأه مباشرة. لا مقدّم خدمة، لا إنترنت، لا خوارزميات كشف.

البدائل المدروسة:
- **ARI externalMedia**: أقوى لكن يتطلب خبرة RTP/WebRTC — أعقد بلا داعٍ لحالتنا.
- **FreeSWITCH + mod_audio_stream/GStreamer**: بديل ممتاز لمن يفضّل FreeSWITCH؛ نفس المبدأ (بث PCM + DTMF عبر الأحداث).
- **بوابة FXO/ATA** (Grandstream/Patton/Yeastar): لربط خطوط الهاتف التناظرية بـAsterisk إن كان البنك يستخدم خطوطًا أرضية.

---

## المسار A: العميل العادي (سحابي) — ✅ جاهز الآن

لا عمل جديد. الموجود يغطيه بالكامل:
- محركات Twilio+OpenAI / Plivo / ElevenLabs SIP.
- **DTMF مبني** في جسر Twilio (إطار العمل السابق).
- Data Views للحقن قبل المكالمة وأثناءها.

فقط نضيف في واجهة الوكيل خيار **"وضع الخصوصية: سحابي (افتراضي)"**.

---

## المسار B: البنك (محلي بالكامل) — خطة التنفيذ

### المكوّنات على خادم/أجهزة العميل (داخل شبكته)
```
┌─────────────────────────────────────────────────────────────┐
│  مقر العميل (البنك) — لا شيء يغادر هذه الحدود                 │
│                                                              │
│  خطوط الهاتف ──► [Asterisk/FreeSWITCH] ──AudioSocket TCP──►  │
│   (SIP trunk محلي                          │                 │
│    أو بوابة FXO)                           ▼                 │
│                            ┌──────────────────────────────┐  │
│                            │  HalaVoice On-Prem Agent      │  │
│                            │  (حاوية Docker على GPU)       │  │
│                            │  • جسر AudioSocket            │  │
│                            │  • STT: Whisper.cpp / Vosk    │  │
│                            │  • LLM: LM Studio / vLLM      │  │
│                            │  • TTS: Piper / SILMA         │  │
│                            │  • DTMF: إطار 0x03 مباشرة     │  │
│                            └──────────────┬───────────────┘  │
│                                           ▼                  │
│                            [قاعدة بيانات البنك — Data View]   │
└─────────────────────────────────────────────────────────────┘
         │ (اختياري) فقط بيانات التحكم/التقارير المجهّلة
         ▼
   منصة HalaVoice (SaaS) — لإدارة الوكلاء والحملات فقط
```

### الأجزاء المطلوب بناؤها

**1) محرك On-Premise جديد** `server/engines/onprem/` (يحاكي بنية محرك Twilio+OpenAI):
- **خادم AudioSocket (TCP)**: يستقبل اتصال Asterisk، يفك إطارات UUID/AUDIO/DTMF.
- **حلقة الصوت**: PCM 8kHz → STT محلي → نص → Custom LLM (مبني) → رد → TTS محلي (مبني) → PCM → يُرسل عبر AudioSocket.
- **DTMF**: إطار 0x03 → نفس منطق المجمّع والبحث في Data Views الذي بنيناه (نعيد استخدام `finalizeDtmf` بعد تعميمه).
- **VAD/مقاطعة**: كشف نشاط صوتي محلي (webrtcvad/silero) لإدارة الأدوار.

**2) STT محلي** (القطعة الجديدة الوحيدة فعليًا):
- **Whisper.cpp** (large-v3-turbo) على GPU — عربي ممتاز، ~200-400ms، أو
- **Vosk** (أخف، CPU، جودة أقل) للأجهزة بلا GPU.
- خدمة `server/services/stt-local.ts` بواجهة موحّدة (streaming partial + final).

**3) تعميم منطق DTMF**: نقل `finalizeDtmf` + البحث في Data Views من جسر Twilio إلى وحدة مشتركة `server/services/dtmf-handler.ts` يستخدمها المحركان.

**4) حزمة النشر للعميل** `onprem-agent/`:
- `Dockerfile` (يحزم الجسر + Whisper.cpp + Piper + يتصل بـLM Studio محلي).
- `extensions.conf` جاهز لـAsterisk (dialplan يوجّه المكالمة إلى `AudioSocket(uuid,host:port)`).
- دليل تركيب عربي: Asterisk + بوابة FXO (إن لزم) + الحاوية على GPU.
- خيار all-in-one: جهاز واحد بـGPU يشغّل Asterisk + الوكيل + STT/LLM/TTS.

**5) إعدادات المنصة**:
- خيار في الوكيل: **"وضع الخصوصية: محلي بالكامل (On-Premise)"** + عنوان الوكيل المحلي (IP:port لجسر AudioSocket) — بنفس فكرة كتابة IP الخاصة بـLM Studio التي طلبتها سابقًا.
- المنصة السحابية تدير التهيئة والحملات فقط؛ **الصوت والبيانات الحساسة لا تصلها إطلاقًا**.

### الأمان والامتثال (نقطة البيع للبنوك)
- **عزل شبكي كامل**: الصوت والـSTT والـLLM والـTTS وقاعدة البيانات كلها داخل شبكة البنك.
- ما يصل المنصة السحابية (اختياري): بيانات تحكم فقط (حالة الوكيل، إحصاءات مجهّلة) — يمكن قطعه كليًا (وضع air-gapped بترخيص محلي).
- يحقق متطلبات ساما/PDPL لإقامة البيانات (data residency) بأقوى صورة: لا مغادرة أصلاً.
- تكامل مباشر مع إضافة sama-call-enforcement (تسجيل، تحقق هوية، حد المحاولات) — كلها محلية.

---

## المكوّنات المحلية الموصى بها (من البحث)

| المكوّن | الخيار الموصى به | البديل الأخف |
|---------|------------------|--------------|
| الهاتفة | **Asterisk 20+ / AudioSocket** | FreeSWITCH + mod_audio_stream |
| STT | **Whisper.cpp large-v3-turbo** (GPU) | Vosk (CPU) |
| LLM | **Qwen3-14B / SILMA-9B عبر vLLM أو LM Studio** (مبني ✅) | نموذج أصغر على CPU |
| TTS | **Piper (سريع CPU) أو SILMA (GPU، جودة أعلى)** (مبني ✅) | — |
| الأجهزة | جهاز GPU واحد (RTX 4090 24GB) يشغّل كل شيء | H200 للأحمال الكبيرة |
| بوابة الخطوط | Grandstream/Patton FXO عند وجود خطوط تناظرية | SIP trunk محلي مباشر |

**التكلفة للبنك**: جهاز GPU واحد (~$2,500) + Asterisk (مجاني) + كل المكوّنات مفتوحة المصدر = بلا رسوم شهرية لكل دقيقة، وبيانات لا تغادر أبدًا.

---

## مراحل التنفيذ

| المرحلة | المحتوى | التقدير |
|---------|---------|---------|
| 1 | تعميم منطق DTMF لوحدة مشتركة + خيار "وضع الخصوصية" في الوكيل | 2-3 أيام |
| 2 | جسر AudioSocket (TCP، فك UUID/AUDIO/DTMF) + حلقة صوت أساسية | أسبوع |
| 3 | تكامل STT محلي (Whisper.cpp) + ربط Custom LLM + TTS المحلي في الحلقة | أسبوع |
| 4 | VAD/مقاطعة + جودة الأدوار + إخفاء أرقام DTMF + سجل ساما محلي | أسبوع |
| 5 | حزمة النشر (Docker + extensions.conf + دليل عربي) + اختبار مع Asterisk حقيقي | أسبوع |
| 6 | (اختياري) موصل FreeSWITCH + وضع air-gapped بترخيص محلي | أسبوع |

**الإجمالي:** ~5-6 أسابيع لمحرك محلي كامل، معظم مكوّناته (LLM، TTS، DTMF، Data Views) **مبنية بالفعل** — الجديد أساسًا هو جسر AudioSocket وSTT المحلي.

---

## الخلاصة
- **المسار A (سحابي)**: جاهز — يضاف فقط خيار الوضع في الواجهة.
- **المسار B (محلي للبنوك)**: محرك On-Premise عبر Asterisk AudioSocket — DTMF يصل جاهزًا كإطار 0x03، والذكاء (STT/LLM/TTS) محلي بالكامل على GPU واحد، **وصفر بيانات تغادر مقر العميل**. يعيد استخدام Custom LLM وTTS المحلي وData Views ومنطق DTMF المبنية سابقًا.
- الاختيار خاصية لكل عميل/وكيل — نفس المنصة تخدم البنك المتشدّد والعميل العادي.

## مصادر البحث
- Asterisk AudioSocket (بروتوكول + إطار DTMF 0x03): docs.asterisk.org/Configuration/Channel-Drivers/AudioSocket • medium.com/@anilmathewm/real-time-ai-voice-agents-with-asterisk-audiosocket-2026-guide
- مشروع مفتوح مرجعي: github.com/hkjarral/AVA-AI-Voice-Agent-for-Asterisk (Asterisk/FreePBX + AudioSocket، سحابي/محلي/هجين)
- Pipecat AudioSocket transport (PCM + DTMF ثنائي الاتجاه): github.com/pipecat-ai/pipecat/issues/2702
- DTMF المحلي (RFC 4733 الموصى به): voip-info.org/asterisk-dtmf • developer.signalwire.com/freeswitch (DTMF)
- مكوّنات محلية: Whisper.cpp، Vosk، Piper، Kokoro (Apache-2.0) — inworld.ai/resources/best-self-hosted-tts • LiveKit self-host: github.com/livekit/agents
- أجهزة: NVIDIA H200 للأحمال الكبيرة، بوابات FXO (Grandstream/Patton/Yeastar) — vaxvoip.com/voipblog/speech-to-speech-ai-engine
- ElevenLabs أضافت نشرًا on-premise (أبريل 2026) وInworld TTS محلي <200ms — كبدائل TTS تجارية محلية
