@dialstack/sdk-dev / native/src / NativeCallBridge
Class: NativeCallBridge
Defined in: sdk/native/src/bridge/NativeCallBridge.ts:187
The bidirectional bridge between the OS call surface and the SDK (OS↔SDK answer/end/mute/hold/DTMF and lifecycle), and the only thing that subscribes to either. Works with no renderer: a push-woken headless runtime starts it like the app window does.
Pairing a session with a call
A call has one call_id everywhere: on the socket, in the wake webhook and on
the INVITE a wake resumes. The OS mints its own session id at setup, and the
bridge links it to that call_id (ids) the moment it knows both: when it
reports a call itself, when an outbound call is placed, and when the OS
reports a wake push's session (incomingReported, carrying the call_id the
push delivered). Every lookup goes through that link; none guesses by
position. A second session for a call_id already linked is the same call
shown twice, and is ended.
The contract this puts on the integrator: the wake push carries the
webhook's call_id, and the OS adapter reports it on incomingReported.
Constructors
Constructor
new NativeCallBridge(options): NativeCallBridge;
Defined in: sdk/native/src/bridge/NativeCallBridge.ts:261
Parameters
options
Returns
NativeCallBridge
Properties
hold
readonly hold: RuntimeHold;
Defined in: sdk/native/src/bridge/NativeCallBridge.ts:188
Methods
answer()
answer(callId): void;
Defined in: sdk/native/src/bridge/NativeCallBridge.ts:314
In-app Answer, routed through the OS so it converges on the one answer path.
Parameters
callId
string
Returns
void
call()
call(destination, displayName?): Promise<BridgeCall>;
Defined in: sdk/native/src/bridge/NativeCallBridge.ts:364
Place an outbound call, reported to the OS FIRST so on Android the foreground
service starts and the call survives backgrounding mid-dial (otherwise the OS
reaps the process and drops the call). If placement fails we end the session
we opened; from then on it rides the same watchCall lifecycle.
An OS-initiated dial (callIntent) comes through here too, so both
directions converge on one path.
Parameters
destination
string
displayName?
string | null
Returns
Promise<BridgeCall>
end()
end(callId): void;
Defined in: sdk/native/src/bridge/NativeCallBridge.ts:334
In-app End/Decline, via the same convergence.
Parameters
callId
string
Returns
void
ensureConnected()
ensureConnected(forWake?): Promise<void>;
Defined in: sdk/native/src/bridge/NativeCallBridge.ts:300
Resolving means the SIP AOR is REGISTERed, so a parked INVITE can reach us.
The phone joins a connect already in flight, so this never starts a second
one. Never reconnect() here — that disposes live calls.
forWake is the corpse-proofing path: when the OS freezes a backgrounded app
it can kill the WebSocket with no close frame reaching JS, so no disconnected
fires and isConnected still reads "connected" over a dead socket. Trusting them never re-REGISTERs the AOR and the parked call is never
re-forked. So a wake with NO live call sheds whatever socket state we hold and
reconnects for real. A wake WITH a live call skips this: that call proves the
socket and a teardown would drop it. A connect still in flight is joined, not
shed: it has no stale socket to distrust, and its own timeouts bound it.
Parameters
forWake?
boolean = false
Returns
Promise<void>
getTrace()
getTrace(): readonly string[];
Defined in: sdk/native/src/bridge/NativeCallBridge.ts:392
Ring buffer for a debug view; one-way, useSyncExternalStore-shaped.
Returns
readonly string[]
start()
start(): void;
Defined in: sdk/native/src/bridge/NativeCallBridge.ts:278
Idempotent. Call from the app entry on every path (window and headless).
Returns
void
subscribeTrace()
subscribeTrace(listener): () => void;
Defined in: sdk/native/src/bridge/NativeCallBridge.ts:396
Parameters
listener
() => void
Returns
() => void