小翠儿

Develop stage

Trunks

Four processes, two on 192.168.71.9. Loopback only between Active Call and RustPBX. The gateway at 192.168.71.107 peers 192.168.71.9:5060, never localhost. Edit the INVITE table on Routing.

PSTN hop

Trunk provider

Dialog B terminates here. Active Call still INVITEs RustPBX. Loopback is refused.

Gateway panel · 192.168.71.107

Two fields on the device currently kill inbound. Leave a-law. SIP server stays 192.168.71.9:5060.

FieldNowSet to
禁止呼入启用禁用
呼入绑定号码••••••••
首选语音编码a Lawkeep · PCMA first on the PBX

Outbound on the box

Active Call originates to rustpbx on loopback. This preview cannot.

python3 place_call.py <locked>
# ws://127.0.0.1:8081/call/sip?id=out-…
# option.realtime.provider = wss://api.x.ai/v1/realtime?model=grok-voice-latest
# callee sip:••••@192.168.71.9:5060

realtime is a CallOption, not playbook front matter. provider must be the Grok Voice URL — "openai" discards endpoint and dials api.openai.com.

Active Call URL

Dial originates from this browser to that HTTP. This preview cannot reach a private 192.168 address unless you are on the LAN.

Gateway
192.168.71.107:5060
up
udp · pstn-gateway

EDGE. Peers 192.168.71.9:5060, never localhost. DID hidden in UI.

PCMA
PCMU
RustPBX
192.168.71.9:5060
up
udp · pbx

SWITCH. SIP 5060, HTTP 8080, RTP 20000-24999. Never opens 8765.

PCMA
PCMU
Active Call
192.168.71.9:13050
up
udp · agent

ADAPTER. Ext 1001. SIP 13050, HTTP 8081, RTP 25000-29999. Opens Grok Voice.

PCMA
PCMU
Grok Voice
api.x.ai:443
loopback
wss · realtime

BRAIN. wss://api.x.ai/v1/realtime?model=grok-voice-latest — Active Call is the client. Needs XAI_API_KEY.

PCM16

Port map on 192.168.71.9

Gateway is a separate host. speech-to-speech is loopback only.

ProcessSIPHTTPRTPRole
RustPBX5060808020000-24999SIP switch
Active Call13050808125000-29999Grok Voice client · ext 1001
Grok Voice—443—wss://api.x.ai/v1/realtime
Gateway 192.168.71.1075060——Peers 192.168.71.9:5060

Inbound DID

Someone on the mobile network dials the DID.

  1. 01
    PSTN
    GSM/LTE into the gateway
  2. 02
    Gateway
    INVITE 192.168.71.9:5060
  3. 03
    RustPBX
    B2BUA + dialplan → 1001:13050
  4. 04
    Active Call
    Realtime wss://api.x.ai/v1/realtime?model=grok-voice-latest

Outbound · From 1001

The agent dials. From on the trunk is the DID.

  1. 01
    Active Call
    INVITE rustpbx as 1001
  2. 02
    RustPBX
    New Call-ID · From DID (hidden)
  3. 03
    Gateway
    Peers 192.168.71.9:5060, dials GSM
  4. 04
    PSTN
    Callee rings · 200 OK · PCMU

rustpbx config.toml

Drop on 192.168.71.9. HTTP router points at this app.

# Aria × rustpbx — on 192.168.71.9
http_addr = "0.0.0.0:8080"

[proxy]
addr = "0.0.0.0"
udp_port = 5060
external_ip = "192.168.71.9"
media_proxy = "all"
route_originated_calls = true
realms = ["127.0.0.1", "192.168.71.9"]
audio_codecs = ["pcma", "pcmu"]

[media]
rtp_start = 20000
rtp_end = 24999

[[proxy.user_backends]]
type = "memory"
users = [
  { username = "1001", password = "agent1001" },
  { username = "••••", password = "gateway" },
]

[[proxy.routes]]
name = "did-in"
priority = 100
action = "forward"
dest = "sip:[email protected]:13050"

[proxy.routes.match]
"to.user" = "^\\+?(?:86)?••••$"

[[proxy.routes]]
name = "ext-agent"
priority = 99
action = "forward"
dest = "sip:[email protected]:13050"

[proxy.routes.match]
"to.user" = "^1001$"

[[proxy.routes]]
name = "trial-out"
priority = 98
action = "forward"
dest = "pstn"

[proxy.routes.match]
"to.user" = "^\\+?(?:86)?••••$"

[proxy.routes.rewrite]
"from.user" = "••••"
"to.user" = "••••"
"to.host" = "192.168.71.107:5060"

[[proxy.routes]]
name = "pstn-out"
priority = 97
action = "reject"

[proxy.routes.match]
"to.user" = "^\\+?(?:86)?(\\d{5,})$"

[proxy.routes.rewrite]
"from.user" = "••••"

[[trunks]]
name = "pstn"
addr = "192.168.71.107:5060"
transport = "udp"
codecs = ["PCMA", "PCMU"]
direction = "both"

# Gateway peers 192.168.71.9:5060, never localhost.
# DID •••• → sip:[email protected]:13050
# Brain stays loopback: ws://127.0.0.1:8765/v1/realtime

active-call config.toml

Same host. Registers as extension 1001 on SIP 13050.

# Aria × active-call — on 192.168.71.9 next to rustpbx
http_addr = "0.0.0.0:8081"

[ua]
addr = "0.0.0.0"
udp_port = 13050

[media]
rtp_start = 25000
rtp_end = 29999

[[register_users]]
server = "127.0.0.1:5060"
username = "1001"

[register_users.credential]
username = "1001"
password = "agent1001"
realm    = "127.0.0.1"

# Outbound: POST /api/playbook/run then WS /call/sip
#   callee sip:••••@127.0.0.1:5060  codec pcma
# Brain — Grok Voice:
# wss://api.x.ai/v1/realtime?model=grok-voice-latest

# CallOption.realtime (not playbook front matter):
# realtime:
#   provider: "wss://api.x.ai/v1/realtime?model=grok-voice-latest"
#   model: "grok-voice-latest"
#   endpoint: "wss://api.x.ai/v1/realtime?model=grok-voice-latest"
#   secretKey: "$XAI_API_KEY"