Complete project scaffolding and core implementation of an AI-powered telephony system that calls companies, navigates IVR menus, waits on hold, and transfers to the user when a human answers. Key components: - FastAPI server with REST API, WebSocket, and MCP (SSE) interfaces - SIP/VoIP call management via PJSUA2 with RTP audio streaming - LLM-powered IVR navigation using OpenAI/Anthropic with tool calling - Hold detection service combining audio analysis and silence detection - Real-time STT (Whisper/Deepgram) and TTS (OpenAI/Piper) pipelines - Call recording with per-channel and mixed audio capture - Event bus (asyncio pub/sub) for real-time client updates - Web dashboard with live call monitoring - SQLite persistence via SQLAlchemy with call history and analytics - Notification support (email, SMS, webhook, desktop) - Docker Compose deployment with Opal VoIP and Opal Media containers - Comprehensive test suite with unit, integration, and E2E tests - Simplified .gitignore and full project documentation in README
105 lines
4.0 KiB
Markdown
105 lines
4.0 KiB
Markdown
# Hold Slayer Gateway — Dial Plan
|
||
|
||
## Overview
|
||
|
||
The gateway accepts calls from registered SIP endpoints and routes them
|
||
based on the dialled digits. No trunk-access prefix (no "9") is needed.
|
||
All routing is pattern-matched in order; the first match wins.
|
||
|
||
---
|
||
|
||
## ⚠️ Emergency Services — 911
|
||
|
||
> **911 and 9911 are always routed directly to the PSTN trunk.**
|
||
> No gateway logic intercepts, records, or delays these calls.
|
||
> `9911` is accepted in addition to `911` to catch the common
|
||
> mis-dial habit of dialling `9` for an outside line.
|
||
>
|
||
> **Your SIP trunk provider must support emergency calling on your DID.**
|
||
> Verify this with your provider before putting this system in service.
|
||
> VoIP emergency calling has location limitations — ensure your
|
||
> registered location is correct with your provider.
|
||
|
||
---
|
||
|
||
## Extension Ranges
|
||
|
||
| Range | Purpose |
|
||
|-------|--------------------------------|
|
||
| 2XX | SIP endpoints (phones/softphones) |
|
||
| 5XX | System services |
|
||
|
||
---
|
||
|
||
## 2XX — Endpoint Extensions
|
||
|
||
Extensions are auto-assigned from **221** upward when a SIP device
|
||
registers (`SIP REGISTER`) with the gateway or via `POST /api/devices`.
|
||
|
||
| Extension | Format | Example |
|
||
|-----------|---------------------------------|--------------------------------|
|
||
| 221–299 | Auto-assigned to registered devices | `sip:221@gateway.helu.ca` |
|
||
|
||
### Assignment policy
|
||
|
||
- First device to register gets **221**, next **222**, and so on.
|
||
- Extensions are persisted in the database and survive restarts.
|
||
- If a device is removed its extension is freed and may be reassigned.
|
||
- `GATEWAY_SIP_DOMAIN` in `.env` sets the domain part of the URI.
|
||
|
||
---
|
||
|
||
## 5XX — System Services
|
||
|
||
| Extension | Service | Notes |
|
||
|-----------|----------------------|-----------------------------------------|
|
||
| 500 | Auto-attendant | Reserved — not yet implemented |
|
||
| 510 | Gateway status | Plays a status announcement |
|
||
| 511 | Echo test | Returns audio back to caller |
|
||
| 520 | Hold Slayer launch | Prompts for a number to hold-slay |
|
||
| 599 | Operator fallback | Transfers to preferred device |
|
||
|
||
---
|
||
|
||
## Outbound PSTN
|
||
|
||
All outbound patterns are routed via the configured SIP trunk
|
||
(`SIP_TRUNK_HOST`). No access code prefix is needed.
|
||
|
||
### Pattern table
|
||
|
||
| Pattern | Example input | Normalised to | Notes |
|
||
|----------------------|--------------------|---------------------|------------------------------------|
|
||
| `+1NPANXXXXXX` | `+16135550100` | `+16135550100` | E.164 — pass through as-is |
|
||
| `1NPANXXXXXX` | `16135550100` | `+16135550100` | NANP with country code |
|
||
| `NPANXXXXXX` | `6135550100` | `+16135550100` | 10-digit NANP — prepend `+1` |
|
||
| `011CC…` | `01144201234567` | `+44201234567` | International — strip `011` |
|
||
| `00CC…` | `004420…` | `+4420…` | International alt prefix |
|
||
| `+CC…` | `+44201234567` | `+44201234567` | E.164 international — pass through |
|
||
|
||
### Rules
|
||
|
||
1. E.164 (`+` prefix) is always passed to the trunk unchanged.
|
||
2. NANP 11-digit (`1` + 10 digits) is normalised to E.164 by prepending `+`.
|
||
3. NANP 10-digit is normalised to E.164 by prepending `+1`.
|
||
4. International via `011` or `00` strips the IDD prefix and prepends `+`.
|
||
5. 7-digit local dialling is **not supported** — always dial the area code.
|
||
|
||
---
|
||
|
||
## Inbound PSTN
|
||
|
||
Calls arriving from the trunk on the DID (`SIP_TRUNK_DID`) are routed
|
||
to the highest-priority online device. If no device is online the call
|
||
is queued or dropped (configurable via `MAX_HOLD_TIME`).
|
||
|
||
---
|
||
|
||
## Future
|
||
|
||
- Named regions / area-code routing
|
||
- Least-cost routing across multiple trunks
|
||
- Time-of-day routing (business hours vs. after-hours)
|
||
- Ring groups across multiple 2XX extensions
|
||
- Voicemail (extension 500)
|