@talkif/webrtc 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/index.cjs +943 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +494 -0
- package/dist/index.d.ts +494 -0
- package/dist/index.js +908 -0
- package/dist/index.js.map +1 -0
- package/package.json +37 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,494 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire types for the Talkif WebRTC signaling API and the pipecat SmallWebRTC
|
|
3
|
+
* data-channel protocol spoken by Talkif voice bots.
|
|
4
|
+
*
|
|
5
|
+
* These shapes are the public contract. Field casing matches the backend JSON
|
|
6
|
+
* exactly (camelCase over HTTP).
|
|
7
|
+
*/
|
|
8
|
+
interface IceServer {
|
|
9
|
+
urls: string;
|
|
10
|
+
username?: string;
|
|
11
|
+
credential?: string;
|
|
12
|
+
}
|
|
13
|
+
interface IceServersResponse {
|
|
14
|
+
iceServers: IceServer[];
|
|
15
|
+
/** Seconds remaining on the underlying TURN credential. */
|
|
16
|
+
ttl: number;
|
|
17
|
+
}
|
|
18
|
+
interface CreateCallRequest {
|
|
19
|
+
flowId: string;
|
|
20
|
+
metadata?: Record<string, unknown>;
|
|
21
|
+
}
|
|
22
|
+
interface CreateTestCallRequest {
|
|
23
|
+
flowId: string;
|
|
24
|
+
/**
|
|
25
|
+
* Draft flow definition (frontend `FlowDefinition` shape). The library does
|
|
26
|
+
* not interpret it — it is passed through to the backend, which validates
|
|
27
|
+
* and compiles it for the bot.
|
|
28
|
+
*/
|
|
29
|
+
definition: Record<string, unknown>;
|
|
30
|
+
metadata?: Record<string, unknown>;
|
|
31
|
+
}
|
|
32
|
+
type CallStatus = 'CREATED' | 'BOT_ASSIGNED' | 'QUEUED' | 'RINGING' | 'IN_PROGRESS' | 'COMPLETED' | 'FAILED' | 'NO_ANSWER' | 'BUSY' | 'CANCELED';
|
|
33
|
+
/** REST statuses that mean the call is genuinely over. */
|
|
34
|
+
declare const TERMINAL_CALL_STATUSES: ReadonlySet<CallStatus>;
|
|
35
|
+
interface CreateCallResponse {
|
|
36
|
+
callId: string;
|
|
37
|
+
flowId: string;
|
|
38
|
+
status: CallStatus;
|
|
39
|
+
botId?: string | null;
|
|
40
|
+
}
|
|
41
|
+
interface WebRTCCall {
|
|
42
|
+
callId: string;
|
|
43
|
+
status: CallStatus;
|
|
44
|
+
}
|
|
45
|
+
interface OfferRequest {
|
|
46
|
+
sdp: string;
|
|
47
|
+
iceServers?: IceServer[];
|
|
48
|
+
}
|
|
49
|
+
/** Public surface: token-exchange response (`POST /public/calls/session`). */
|
|
50
|
+
interface PublicSessionResponse {
|
|
51
|
+
/** Signed session token — sent as `Authorization: Bearer <token>`. */
|
|
52
|
+
token: string;
|
|
53
|
+
/** Seconds until the token expires (~15 min). */
|
|
54
|
+
expiresIn: number;
|
|
55
|
+
/** The flow this session may call (bound to the publishable key). */
|
|
56
|
+
flowId: string;
|
|
57
|
+
}
|
|
58
|
+
interface OfferResponse {
|
|
59
|
+
sdp: string;
|
|
60
|
+
sdpType: string;
|
|
61
|
+
botId?: string | null;
|
|
62
|
+
}
|
|
63
|
+
/** Bot → client: bot requests a new offer/answer cycle. */
|
|
64
|
+
interface RenegotiateMessage {
|
|
65
|
+
type: 'renegotiate';
|
|
66
|
+
}
|
|
67
|
+
/** Bot → client: bot is closing the connection. */
|
|
68
|
+
interface PeerLeftMessage {
|
|
69
|
+
type: 'peerLeft';
|
|
70
|
+
}
|
|
71
|
+
/** Client → bot: enable/disable a media receiver. 0=audio, 1=video, 2=screen. */
|
|
72
|
+
interface TrackStatusMessage {
|
|
73
|
+
type: 'trackStatus';
|
|
74
|
+
receiver_index: 0 | 1 | 2;
|
|
75
|
+
enabled: boolean;
|
|
76
|
+
}
|
|
77
|
+
type SignallingPayload = RenegotiateMessage | PeerLeftMessage | TrackStatusMessage;
|
|
78
|
+
interface SignallingEnvelope {
|
|
79
|
+
type: 'signalling';
|
|
80
|
+
message: SignallingPayload;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Anything on the data channel that is not the signalling envelope (and not a
|
|
84
|
+
* `"ping"` keepalive string) is an app message: arbitrary JSON exchanged with
|
|
85
|
+
* the bot pipeline.
|
|
86
|
+
*/
|
|
87
|
+
type AppMessage = Record<string, unknown>;
|
|
88
|
+
/**
|
|
89
|
+
* Server envelope on the realtime events WebSocket. `seq` is per-connection
|
|
90
|
+
* and monotonic — a gap means THIS connection dropped frames under
|
|
91
|
+
* backpressure, not that the call missed anything.
|
|
92
|
+
*/
|
|
93
|
+
interface CallEventEnvelope {
|
|
94
|
+
v: number;
|
|
95
|
+
type: string;
|
|
96
|
+
call_id?: string;
|
|
97
|
+
seq: number;
|
|
98
|
+
ts: number;
|
|
99
|
+
data: Record<string, unknown>;
|
|
100
|
+
}
|
|
101
|
+
/** Event types the public WS delivers for the session's call. */
|
|
102
|
+
type CallEventType = 'transcript' | 'interim' | 'status' | 'tts' | 'tts_word' | 'speech' | 'turn' | 'node_transition' | 'error';
|
|
103
|
+
type CallState = 'idle' | 'requesting' | 'connecting' | 'connected' | 'ended' | 'error';
|
|
104
|
+
interface TalkifCallEventMap {
|
|
105
|
+
/** State machine transition. */
|
|
106
|
+
statechange: {
|
|
107
|
+
state: CallState;
|
|
108
|
+
previous: CallState;
|
|
109
|
+
};
|
|
110
|
+
/** Media is flowing and the SDP answer is applied. */
|
|
111
|
+
connected: {
|
|
112
|
+
callId: string;
|
|
113
|
+
botId: string | null;
|
|
114
|
+
};
|
|
115
|
+
/** Remote (bot) audio track arrived. */
|
|
116
|
+
track: {
|
|
117
|
+
stream: MediaStream;
|
|
118
|
+
};
|
|
119
|
+
/** Call finished normally (user hangup, bot peerLeft, terminal status). */
|
|
120
|
+
ended: {
|
|
121
|
+
reason: CallEndReason;
|
|
122
|
+
};
|
|
123
|
+
/** Fatal failure. The call is torn down; state is 'error'. */
|
|
124
|
+
error: {
|
|
125
|
+
error: TalkifCallError;
|
|
126
|
+
};
|
|
127
|
+
/** One-second duration tick while connected. */
|
|
128
|
+
tick: {
|
|
129
|
+
durationSecs: number;
|
|
130
|
+
};
|
|
131
|
+
/** JSON app message from the bot over the data channel. */
|
|
132
|
+
appmessage: {
|
|
133
|
+
message: AppMessage;
|
|
134
|
+
};
|
|
135
|
+
/** Bot asked for renegotiation. Emitted after the re-offer is attempted. */
|
|
136
|
+
renegotiated: {
|
|
137
|
+
ok: boolean;
|
|
138
|
+
};
|
|
139
|
+
/** Mute toggled. */
|
|
140
|
+
mutechange: {
|
|
141
|
+
muted: boolean;
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* Any realtime event for this call from the events WebSocket (public mode).
|
|
145
|
+
* Fires for every delivered envelope, including those with dedicated
|
|
146
|
+
* events below.
|
|
147
|
+
*/
|
|
148
|
+
callevent: {
|
|
149
|
+
event: CallEventEnvelope;
|
|
150
|
+
};
|
|
151
|
+
/** Final transcript line (public mode, via the events WebSocket). */
|
|
152
|
+
transcript: {
|
|
153
|
+
role: string;
|
|
154
|
+
content: string;
|
|
155
|
+
data: Record<string, unknown>;
|
|
156
|
+
};
|
|
157
|
+
/** Interim (in-progress) transcription (public mode). May be dropped under backpressure. */
|
|
158
|
+
interim: {
|
|
159
|
+
data: Record<string, unknown>;
|
|
160
|
+
};
|
|
161
|
+
/**
|
|
162
|
+
* Word-level TTS timing (public mode). Drives karaoke-style caption
|
|
163
|
+
* highlighting; only words actually spoken are delivered. May be dropped
|
|
164
|
+
* under backpressure.
|
|
165
|
+
*/
|
|
166
|
+
ttsword: TtsWordEvent;
|
|
167
|
+
/**
|
|
168
|
+
* Sentence-level chunk of the agent's reply (public mode), emitted when the
|
|
169
|
+
* LLM output is handed to TTS synthesis — ahead of audio playback. Use for
|
|
170
|
+
* chat-style streaming of the reply; reconcile with the final `transcript`
|
|
171
|
+
* (on interruption the tail may never be spoken). May be dropped under
|
|
172
|
+
* backpressure.
|
|
173
|
+
*/
|
|
174
|
+
ttschunk: TtsChunkEvent;
|
|
175
|
+
}
|
|
176
|
+
/** Payload of a `tts` realtime event. */
|
|
177
|
+
interface TtsChunkEvent {
|
|
178
|
+
/** Sentence-level text chunk of the agent's reply. */
|
|
179
|
+
text: string;
|
|
180
|
+
/** Unix timestamp from the bot (seconds, fractional). */
|
|
181
|
+
timestamp: number;
|
|
182
|
+
/** Full raw event payload (character counts, TTS timing metrics…). */
|
|
183
|
+
data: Record<string, unknown>;
|
|
184
|
+
}
|
|
185
|
+
/** Payload of a `tts_word` realtime event. */
|
|
186
|
+
interface TtsWordEvent {
|
|
187
|
+
/** The spoken word. */
|
|
188
|
+
word: string;
|
|
189
|
+
/** Presentation timestamp — when the word is spoken in the audio (ms), if known. */
|
|
190
|
+
ptsMs: number | null;
|
|
191
|
+
/** Unix timestamp from the bot (seconds, fractional). */
|
|
192
|
+
timestamp: number;
|
|
193
|
+
/** Full raw event payload. */
|
|
194
|
+
data: Record<string, unknown>;
|
|
195
|
+
}
|
|
196
|
+
type CallEndReason = 'local-hangup' | 'peer-left' | 'terminal-status' | 'external';
|
|
197
|
+
type TalkifCallErrorCode = 'media-unavailable' | 'signaling-failed' | 'connection-failed' | 'pipeline-dead' | 'renegotiation-failed'
|
|
198
|
+
/** Publishable key rejected, origin not allowed, or session expired. */
|
|
199
|
+
| 'session-rejected'
|
|
200
|
+
/** This session already has an active call (multi-tab). */
|
|
201
|
+
| 'call-active'
|
|
202
|
+
/** Rate/concurrency limit hit — retry later. */
|
|
203
|
+
| 'rate-limited'
|
|
204
|
+
/** No bot available right now — retry shortly. */
|
|
205
|
+
| 'no-agent';
|
|
206
|
+
declare class TalkifCallError extends Error {
|
|
207
|
+
readonly code: TalkifCallErrorCode;
|
|
208
|
+
readonly cause?: unknown;
|
|
209
|
+
constructor(code: TalkifCallErrorCode, message: string, cause?: unknown);
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Supplies the Authorization header value for signaling requests.
|
|
213
|
+
* Called per request so short-lived tokens (JWT refresh, widget session
|
|
214
|
+
* tokens) stay current. Return e.g. `"Bearer <token>"`.
|
|
215
|
+
*/
|
|
216
|
+
type AuthProvider = () => string | Promise<string>;
|
|
217
|
+
interface TalkifClientConfig {
|
|
218
|
+
/** API origin, e.g. `https://api.talkif.ai`. No trailing slash. */
|
|
219
|
+
baseUrl: string;
|
|
220
|
+
accountId: string;
|
|
221
|
+
auth: AuthProvider;
|
|
222
|
+
/** Override fetch (tests, SSR polyfills). Defaults to global fetch. */
|
|
223
|
+
fetch?: typeof fetch;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Public (embeddable) configuration: the browser-safe publishable key from the
|
|
227
|
+
* flow's public-access settings. The library exchanges it for a short-lived
|
|
228
|
+
* session token itself — no bearer token, no account id. The page's Origin
|
|
229
|
+
* must be on the key's allowlist.
|
|
230
|
+
*/
|
|
231
|
+
interface TalkifPublicClientConfig {
|
|
232
|
+
/** API origin, e.g. `https://api.talkif.ai`. No trailing slash. */
|
|
233
|
+
baseUrl: string;
|
|
234
|
+
/** Publishable key (`pk_live_...`) — safe to ship in page source. */
|
|
235
|
+
publishableKey: string;
|
|
236
|
+
/**
|
|
237
|
+
* Cloudflare Turnstile sitekey (Talkif's — public, safe to ship). When set,
|
|
238
|
+
* the library renders an invisible Turnstile challenge and produces a token
|
|
239
|
+
* for each session exchange automatically. Leave unset to disable the gate
|
|
240
|
+
* (dev/local, or before Turnstile is provisioned).
|
|
241
|
+
*/
|
|
242
|
+
turnstileSiteKey?: string;
|
|
243
|
+
/**
|
|
244
|
+
* Manual Turnstile token supplier. Overrides `turnstileSiteKey` — supply
|
|
245
|
+
* this only if you render Turnstile yourself. Called at each exchange.
|
|
246
|
+
*/
|
|
247
|
+
turnstileToken?: () => string | Promise<string>;
|
|
248
|
+
/** Override fetch (tests, SSR polyfills). Defaults to global fetch. */
|
|
249
|
+
fetch?: typeof fetch;
|
|
250
|
+
}
|
|
251
|
+
type TalkifConfig = TalkifClientConfig | TalkifPublicClientConfig;
|
|
252
|
+
declare function isPublicConfig(config: TalkifConfig): config is TalkifPublicClientConfig;
|
|
253
|
+
interface StartCallOptions {
|
|
254
|
+
/**
|
|
255
|
+
* Start a call against a published flow. Required in authenticated mode.
|
|
256
|
+
* Ignored in public mode — the flow is bound to the publishable key.
|
|
257
|
+
*/
|
|
258
|
+
flowId?: string;
|
|
259
|
+
/**
|
|
260
|
+
* When set, uses the draft test-call endpoint with this definition instead
|
|
261
|
+
* of the published flow.
|
|
262
|
+
*/
|
|
263
|
+
draftDefinition?: Record<string, unknown>;
|
|
264
|
+
metadata?: Record<string, unknown>;
|
|
265
|
+
/** Constraints for getUserMedia. Defaults to `{ audio: true }`. */
|
|
266
|
+
audio?: MediaTrackConstraints | boolean;
|
|
267
|
+
/**
|
|
268
|
+
* Attach remote audio to this element instead of an internally created
|
|
269
|
+
* autoplay `Audio()`. Pass `null` to disable playback entirely (consumer
|
|
270
|
+
* handles the `track` event itself).
|
|
271
|
+
*/
|
|
272
|
+
audioElement?: HTMLAudioElement | null;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* One WebRTC voice session with a Talkif agent.
|
|
277
|
+
*
|
|
278
|
+
* Lifecycle: `idle → requesting → connecting → connected → ended | error`.
|
|
279
|
+
* A TalkifCall instance is single-use: create a new one per call.
|
|
280
|
+
*/
|
|
281
|
+
declare class TalkifCall {
|
|
282
|
+
private readonly signaling;
|
|
283
|
+
private readonly config;
|
|
284
|
+
private readonly emitter;
|
|
285
|
+
private events;
|
|
286
|
+
private pc;
|
|
287
|
+
private localStream;
|
|
288
|
+
private remoteAudio;
|
|
289
|
+
private ownsAudioElement;
|
|
290
|
+
private dataChannel;
|
|
291
|
+
private iceServers;
|
|
292
|
+
private durationTimer;
|
|
293
|
+
private healthTimer;
|
|
294
|
+
private pipelineConfirmed;
|
|
295
|
+
private renegotiating;
|
|
296
|
+
private _state;
|
|
297
|
+
private _callId;
|
|
298
|
+
private _botId;
|
|
299
|
+
private _muted;
|
|
300
|
+
private _durationSecs;
|
|
301
|
+
constructor(config: TalkifConfig);
|
|
302
|
+
get state(): CallState;
|
|
303
|
+
get callId(): string | null;
|
|
304
|
+
get botId(): string | null;
|
|
305
|
+
get muted(): boolean;
|
|
306
|
+
get durationSecs(): number;
|
|
307
|
+
on<K extends keyof TalkifCallEventMap>(event: K, listener: (payload: TalkifCallEventMap[K]) => void): () => void;
|
|
308
|
+
off<K extends keyof TalkifCallEventMap>(event: K, listener: (payload: TalkifCallEventMap[K]) => void): void;
|
|
309
|
+
/**
|
|
310
|
+
* External health signal (e.g. the dashboard's SSE layer saw a
|
|
311
|
+
* RUNNING/CONNECTED status). Cancels the REST health watchdog.
|
|
312
|
+
*/
|
|
313
|
+
confirmPipelineHealthy(): void;
|
|
314
|
+
/**
|
|
315
|
+
* External terminal signal (e.g. SSE reported COMPLETED). Tears down and
|
|
316
|
+
* transitions to 'ended'.
|
|
317
|
+
*/
|
|
318
|
+
endedExternally(): void;
|
|
319
|
+
/** Send an arbitrary JSON app message to the bot over the data channel. */
|
|
320
|
+
sendAppMessage(message: AppMessage): boolean;
|
|
321
|
+
setMuted(muted: boolean): void;
|
|
322
|
+
/** User-initiated hangup. */
|
|
323
|
+
hangup(): void;
|
|
324
|
+
/** Full teardown regardless of state — safe to call multiple times. */
|
|
325
|
+
dispose(): void;
|
|
326
|
+
start(options: StartCallOptions): Promise<void>;
|
|
327
|
+
private prepareLocal;
|
|
328
|
+
private waitForFirstRelayCandidate;
|
|
329
|
+
private attachRemoteAudio;
|
|
330
|
+
private handleSignalling;
|
|
331
|
+
/**
|
|
332
|
+
* Bot asked for a new offer/answer cycle. Re-offer through the same relay
|
|
333
|
+
* endpoint. If the backend rejects re-offers (older deployments), the call
|
|
334
|
+
* keeps running on the existing session — surfaced via `renegotiated`.
|
|
335
|
+
*/
|
|
336
|
+
private renegotiate;
|
|
337
|
+
/**
|
|
338
|
+
* Public mode only: open the realtime events WebSocket for this call.
|
|
339
|
+
* Events double as the pipeline-health signal, and a terminal `status`
|
|
340
|
+
* event ends the call from the server side (e.g. max-duration reached).
|
|
341
|
+
*/
|
|
342
|
+
private connectEvents;
|
|
343
|
+
private handleCallEvent;
|
|
344
|
+
private armHealthWatchdog;
|
|
345
|
+
private verifyPipelineHealth;
|
|
346
|
+
private mustLocalSdp;
|
|
347
|
+
private startDurationTimer;
|
|
348
|
+
private fail;
|
|
349
|
+
private setState;
|
|
350
|
+
private teardown;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
interface CallEventsOptions {
|
|
354
|
+
/** API origin, e.g. `https://api.talkif.ai`. */
|
|
355
|
+
baseUrl: string;
|
|
356
|
+
/** Fresh session token per (re)connect — first-message auth. */
|
|
357
|
+
getToken: () => Promise<string>;
|
|
358
|
+
/** Every delivered envelope for the session's call. */
|
|
359
|
+
onEvent: (event: CallEventEnvelope) => void;
|
|
360
|
+
/**
|
|
361
|
+
* A `seq` gap was observed: this connection shed frames under backpressure.
|
|
362
|
+
* The client auto-requests a server-side replay on reconnect; consumers that
|
|
363
|
+
* render transcripts incrementally may want to clear-and-rebuild on replay.
|
|
364
|
+
*/
|
|
365
|
+
onGap?: (expected: number, received: number) => void;
|
|
366
|
+
/** Optional WebSocket constructor override (tests, Node). */
|
|
367
|
+
webSocket?: typeof WebSocket;
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Client for the public realtime events WebSocket
|
|
371
|
+
* (`/api/v1/public/ws/events`).
|
|
372
|
+
*
|
|
373
|
+
* Protocol: connect → send `{"type":"auth","token":...}` within 5s → send
|
|
374
|
+
* `{"type":"subscribe"}` (the session is auto-bound to its one call) →
|
|
375
|
+
* receive `{v, type, call_id?, seq, ts, data}` envelopes. Reconnects with
|
|
376
|
+
* backoff; after the first successful connection, reconnect subscribes with
|
|
377
|
+
* `replay: true` to recover anything missed during the gap.
|
|
378
|
+
*/
|
|
379
|
+
declare class CallEventsClient {
|
|
380
|
+
private readonly options;
|
|
381
|
+
private ws;
|
|
382
|
+
private closed;
|
|
383
|
+
private attempts;
|
|
384
|
+
private everConnected;
|
|
385
|
+
private lastSeq;
|
|
386
|
+
private reconnectTimer;
|
|
387
|
+
constructor(options: CallEventsOptions);
|
|
388
|
+
connect(): void;
|
|
389
|
+
close(): void;
|
|
390
|
+
private wsUrl;
|
|
391
|
+
private open;
|
|
392
|
+
private scheduleReconnect;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
declare class SignalingError extends Error {
|
|
396
|
+
readonly status: number;
|
|
397
|
+
readonly body: unknown;
|
|
398
|
+
constructor(status: number, message: string, body: unknown);
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Holds the short-lived session token for the public surface: exchanges the
|
|
402
|
+
* publishable key on first use, re-exchanges near expiry, and can be
|
|
403
|
+
* invalidated on a 401 so the next request retries with a fresh token.
|
|
404
|
+
*/
|
|
405
|
+
declare class PublicSession {
|
|
406
|
+
private readonly config;
|
|
407
|
+
private token;
|
|
408
|
+
private expiresAt;
|
|
409
|
+
private flowIdValue;
|
|
410
|
+
private inflight;
|
|
411
|
+
private turnstile;
|
|
412
|
+
constructor(config: TalkifPublicClientConfig);
|
|
413
|
+
/** A fresh Turnstile token, from the manual supplier or the built-in
|
|
414
|
+
* manager; undefined when no gate is configured (dev/local). */
|
|
415
|
+
private turnstileToken;
|
|
416
|
+
/** Tear down the Turnstile widget (call when the client is disposed). */
|
|
417
|
+
dispose(): void;
|
|
418
|
+
/** Flow bound to the publishable key (known after the first exchange). */
|
|
419
|
+
get flowId(): string | null;
|
|
420
|
+
getToken(): Promise<string>;
|
|
421
|
+
invalidate(): void;
|
|
422
|
+
private exchange;
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Thin HTTP client for the Talkif WebRTC signaling routes. Two modes:
|
|
426
|
+
* - authenticated (dashboard/API): `/api/v1/accounts/{accountId}/calls/webrtc`
|
|
427
|
+
* - public (embed): `/api/v1/public/calls`, session token minted from the
|
|
428
|
+
* publishable key and refreshed transparently.
|
|
429
|
+
*/
|
|
430
|
+
declare class SignalingClient {
|
|
431
|
+
private readonly config;
|
|
432
|
+
readonly session: PublicSession | null;
|
|
433
|
+
constructor(config: TalkifConfig);
|
|
434
|
+
get isPublic(): boolean;
|
|
435
|
+
private get base();
|
|
436
|
+
private authorization;
|
|
437
|
+
private request;
|
|
438
|
+
createCall(body: CreateCallRequest): Promise<CreateCallResponse>;
|
|
439
|
+
createTestCall(body: CreateTestCallRequest): Promise<CreateCallResponse>;
|
|
440
|
+
getIceServers(): Promise<IceServersResponse>;
|
|
441
|
+
sendOffer(callId: string, body: OfferRequest): Promise<OfferResponse>;
|
|
442
|
+
getCall(callId: string): Promise<WebRTCCall>;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* Cloudflare Turnstile integration — the "prove you're a real browser" gate
|
|
447
|
+
* that stops scripted abuse of the public call surface.
|
|
448
|
+
*
|
|
449
|
+
* The customer does nothing: the widget self-injects Cloudflare's script,
|
|
450
|
+
* renders an invisible Turnstile widget with Talkif's sitekey, and produces a
|
|
451
|
+
* fresh token for each session exchange. The sitekey is public and safe to
|
|
452
|
+
* ship; the matching secret lives only in the backend.
|
|
453
|
+
*/
|
|
454
|
+
/** Minimal shape of the global `turnstile` object we use. */
|
|
455
|
+
interface TurnstileApi {
|
|
456
|
+
render(container: HTMLElement, options: {
|
|
457
|
+
sitekey: string;
|
|
458
|
+
callback?: (token: string) => void;
|
|
459
|
+
'error-callback'?: (code?: string) => void;
|
|
460
|
+
'expired-callback'?: () => void;
|
|
461
|
+
size?: 'invisible' | 'normal' | 'compact' | 'flexible';
|
|
462
|
+
execution?: 'render' | 'execute';
|
|
463
|
+
retry?: 'auto' | 'never';
|
|
464
|
+
}): string;
|
|
465
|
+
execute(widgetId: string, options?: {
|
|
466
|
+
sitekey?: string;
|
|
467
|
+
}): void;
|
|
468
|
+
reset(widgetId: string): void;
|
|
469
|
+
remove(widgetId: string): void;
|
|
470
|
+
}
|
|
471
|
+
declare global {
|
|
472
|
+
interface Window {
|
|
473
|
+
turnstile?: TurnstileApi;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* Manages one invisible Turnstile widget and hands out fresh tokens.
|
|
478
|
+
*
|
|
479
|
+
* Turnstile tokens are single-use and short-lived, so we `execute()` a fresh
|
|
480
|
+
* challenge for each call to `getToken()` (i.e. each session exchange). The
|
|
481
|
+
* widget is rendered lazily on first use and torn down with `dispose()`.
|
|
482
|
+
*/
|
|
483
|
+
declare class TurnstileManager {
|
|
484
|
+
private readonly siteKey;
|
|
485
|
+
private container;
|
|
486
|
+
private widgetId;
|
|
487
|
+
private pending;
|
|
488
|
+
constructor(siteKey: string);
|
|
489
|
+
/** Obtain a fresh Turnstile token. Rejects if the challenge fails. */
|
|
490
|
+
getToken(): Promise<string>;
|
|
491
|
+
dispose(): void;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
export { type AppMessage, type AuthProvider, type CallEndReason, type CallEventEnvelope, type CallEventType, CallEventsClient, type CallState, type CallStatus, type CreateCallRequest, type CreateCallResponse, type CreateTestCallRequest, type IceServer, type IceServersResponse, type OfferRequest, type OfferResponse, type PeerLeftMessage, PublicSession, type PublicSessionResponse, type RenegotiateMessage, SignalingClient, SignalingError, type SignallingEnvelope, type SignallingPayload, type StartCallOptions, TERMINAL_CALL_STATUSES, TalkifCall, TalkifCallError, type TalkifCallErrorCode, type TalkifCallEventMap, type TalkifClientConfig, type TalkifConfig, type TalkifPublicClientConfig, type TrackStatusMessage, type TtsChunkEvent, type TtsWordEvent, TurnstileManager, type WebRTCCall, isPublicConfig };
|