mirror of
https://github.com/dograh-hq/dograh.git
synced 2026-07-22 11:51:04 +02:00
* ViciDial Working * feat(telephony): add FreeSWITCH provider to upstream-PBX seam Generalize the upstream-PBX capture and control paths to dispatch by provider. FreeSWITCH bridges in with X-PBX-* headers and is driven over the Event Socket Library (uuid_kill / uuid_transfer) by the channel UUID, alongside the existing VICIdial ra_call_control path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * add vici specific configs * feat(telephony): env-based VICIdial config + address3 post-call routing Move VICIdial agent/non-agent API and FreeSWITCH ESL connection settings out of hardcoded POC values into environment variables so the same image works against a PBX on another server. Add VICIdial update_lead forwarding: X-VICI-UPDATE-LEAD_* extracted variables are mapped to lead columns and pushed via the non-agent API before a transfer, with reserved API-control params dropped. Add hardcoded address3 disposition routing (Y/N -> in-group transfer, else hang up) and a synchronous final variable extraction so the transfer path sees the freshest conversation state. Skip upstream_pbx capture on non-PJSIP channels to avoid Asterisk 500s. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: run formatter * feat: make vici configurable from UI * chore: clean up PR * fix: incorporate review comments * chore: incorporate review comments * chore: generate client * chore: incporporate review comments * chore: incorporate review comments --------- Co-authored-by: Dograh POC <payment@dograh.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
44 lines
1.3 KiB
Python
44 lines
1.3 KiB
Python
"""Contracts for PBXs that hand a customer leg to Dograh through Asterisk."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from abc import ABC, abstractmethod
|
|
from dataclasses import dataclass
|
|
from typing import Awaitable, Callable, Mapping
|
|
|
|
HeaderReader = Callable[[str], Awaitable[str]]
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ExternalPBXResult:
|
|
ok: bool
|
|
action: str
|
|
message: str
|
|
|
|
|
|
class ExternalPBXAdapter(ABC):
|
|
"""PBX-specific operations; ARI continues to own only Dograh's local leg."""
|
|
|
|
type: str
|
|
|
|
@abstractmethod
|
|
async def capture_call_identity(
|
|
self, read_header: HeaderReader
|
|
) -> dict[str, str] | None:
|
|
"""Read a stable upstream-call identity from inbound SIP headers."""
|
|
|
|
@abstractmethod
|
|
async def hangup(self, identity: Mapping[str, str]) -> ExternalPBXResult:
|
|
"""Hang up the customer leg owned by the external PBX."""
|
|
|
|
@abstractmethod
|
|
async def transfer(
|
|
self, identity: Mapping[str, str], destination: str
|
|
) -> ExternalPBXResult:
|
|
"""Transfer the customer leg to a PBX-native destination."""
|
|
|
|
@abstractmethod
|
|
async def update_fields(
|
|
self, identity: Mapping[str, str], fields: Mapping[str, str]
|
|
) -> ExternalPBXResult:
|
|
"""Update provider-native fields associated with the call."""
|