getpatter 0.3.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/README.md +720 -0
- package/dist/chunk-KB57IV4K.mjs +410 -0
- package/dist/index.d.mts +866 -0
- package/dist/index.d.ts +866 -0
- package/dist/index.js +4287 -0
- package/dist/index.mjs +3773 -0
- package/dist/test-mode-RTQAK5CP.mjs +6 -0
- package/package.json +68 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,866 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import { Request, Response, NextFunction, Express } from 'express';
|
|
3
|
+
|
|
4
|
+
interface IncomingMessage {
|
|
5
|
+
readonly text: string;
|
|
6
|
+
readonly callId: string;
|
|
7
|
+
readonly caller: string;
|
|
8
|
+
}
|
|
9
|
+
interface STTConfig {
|
|
10
|
+
readonly provider: string;
|
|
11
|
+
readonly apiKey: string;
|
|
12
|
+
readonly language: string;
|
|
13
|
+
toDict(): Record<string, string>;
|
|
14
|
+
}
|
|
15
|
+
interface TTSConfig {
|
|
16
|
+
readonly provider: string;
|
|
17
|
+
readonly apiKey: string;
|
|
18
|
+
readonly voice: string;
|
|
19
|
+
toDict(): Record<string, string>;
|
|
20
|
+
}
|
|
21
|
+
type MessageHandler = (msg: IncomingMessage) => Promise<string>;
|
|
22
|
+
type CallEventHandler = (data: Record<string, unknown>) => Promise<void>;
|
|
23
|
+
interface PatterOptions {
|
|
24
|
+
apiKey: string;
|
|
25
|
+
backendUrl?: string;
|
|
26
|
+
restUrl?: string;
|
|
27
|
+
}
|
|
28
|
+
interface ConnectOptions {
|
|
29
|
+
onMessage: MessageHandler;
|
|
30
|
+
onCallStart?: CallEventHandler;
|
|
31
|
+
onCallEnd?: CallEventHandler;
|
|
32
|
+
provider?: string;
|
|
33
|
+
providerKey?: string;
|
|
34
|
+
providerSecret?: string;
|
|
35
|
+
number?: string;
|
|
36
|
+
country?: string;
|
|
37
|
+
stt?: STTConfig;
|
|
38
|
+
tts?: TTSConfig;
|
|
39
|
+
}
|
|
40
|
+
interface CallOptions {
|
|
41
|
+
to: string;
|
|
42
|
+
onMessage?: MessageHandler;
|
|
43
|
+
firstMessage?: string;
|
|
44
|
+
fromNumber?: string;
|
|
45
|
+
agentId?: string;
|
|
46
|
+
machineDetection?: boolean;
|
|
47
|
+
}
|
|
48
|
+
interface ToolDefinition {
|
|
49
|
+
name: string;
|
|
50
|
+
description: string;
|
|
51
|
+
parameters: Record<string, unknown>;
|
|
52
|
+
/** Webhook URL — called when the LLM invokes this tool. Mutually exclusive with handler. */
|
|
53
|
+
webhookUrl?: string;
|
|
54
|
+
/** Local handler function — when provided, called instead of webhookUrl. */
|
|
55
|
+
handler?: (args: Record<string, unknown>, context: Record<string, unknown>) => Promise<string>;
|
|
56
|
+
}
|
|
57
|
+
interface CreateAgentOptions {
|
|
58
|
+
name: string;
|
|
59
|
+
systemPrompt: string;
|
|
60
|
+
model?: string;
|
|
61
|
+
voice?: string;
|
|
62
|
+
voiceProvider?: string;
|
|
63
|
+
language?: string;
|
|
64
|
+
firstMessage?: string;
|
|
65
|
+
tools?: ToolDefinition[];
|
|
66
|
+
}
|
|
67
|
+
interface Agent {
|
|
68
|
+
id: string;
|
|
69
|
+
name: string;
|
|
70
|
+
systemPrompt: string;
|
|
71
|
+
model: string;
|
|
72
|
+
voice: string;
|
|
73
|
+
voiceProvider: string;
|
|
74
|
+
language: string;
|
|
75
|
+
firstMessage: string | null;
|
|
76
|
+
tools: ToolDefinition[] | null;
|
|
77
|
+
}
|
|
78
|
+
interface PhoneNumber {
|
|
79
|
+
id: string;
|
|
80
|
+
number: string;
|
|
81
|
+
provider: string;
|
|
82
|
+
country: string;
|
|
83
|
+
status: string;
|
|
84
|
+
agentId: string | null;
|
|
85
|
+
}
|
|
86
|
+
interface Call {
|
|
87
|
+
id: string;
|
|
88
|
+
direction: string;
|
|
89
|
+
caller: string;
|
|
90
|
+
callee: string;
|
|
91
|
+
startedAt: string;
|
|
92
|
+
endedAt: string | null;
|
|
93
|
+
durationSeconds: number | null;
|
|
94
|
+
status: string;
|
|
95
|
+
transcript: Array<{
|
|
96
|
+
role: string;
|
|
97
|
+
text: string;
|
|
98
|
+
timestamp: string;
|
|
99
|
+
}> | null;
|
|
100
|
+
}
|
|
101
|
+
interface LocalOptions {
|
|
102
|
+
mode: 'local';
|
|
103
|
+
twilioSid?: string;
|
|
104
|
+
twilioToken?: string;
|
|
105
|
+
openaiKey?: string;
|
|
106
|
+
phoneNumber: string;
|
|
107
|
+
webhookUrl: string;
|
|
108
|
+
telephonyProvider?: 'twilio' | 'telnyx';
|
|
109
|
+
telnyxKey?: string;
|
|
110
|
+
telnyxConnectionId?: string;
|
|
111
|
+
/**
|
|
112
|
+
* Telnyx Ed25519 public key (base64-encoded, DER/SPKI format) for webhook
|
|
113
|
+
* signature verification. When provided, unauthenticated requests are rejected.
|
|
114
|
+
*/
|
|
115
|
+
telnyxPublicKey?: string;
|
|
116
|
+
}
|
|
117
|
+
interface Guardrail {
|
|
118
|
+
/** Name for logging when triggered */
|
|
119
|
+
name: string;
|
|
120
|
+
/** List of terms that trigger the guardrail (case-insensitive) */
|
|
121
|
+
blockedTerms?: string[];
|
|
122
|
+
/** Custom check function — return true to block the response */
|
|
123
|
+
check?: (text: string) => boolean;
|
|
124
|
+
/** Replacement text spoken when guardrail triggers */
|
|
125
|
+
replacement?: string;
|
|
126
|
+
}
|
|
127
|
+
interface AgentOptions {
|
|
128
|
+
systemPrompt: string;
|
|
129
|
+
voice?: string;
|
|
130
|
+
model?: string;
|
|
131
|
+
language?: string;
|
|
132
|
+
firstMessage?: string;
|
|
133
|
+
tools?: ToolDefinition[];
|
|
134
|
+
provider?: 'openai_realtime' | 'elevenlabs_convai' | 'pipeline';
|
|
135
|
+
elevenlabsKey?: string;
|
|
136
|
+
elevenlabsAgentId?: string;
|
|
137
|
+
deepgramKey?: string;
|
|
138
|
+
/** STT provider config for pipeline mode. Use ``Patter.deepgram()`` or ``Patter.whisper()``. */
|
|
139
|
+
stt?: STTConfig;
|
|
140
|
+
/** TTS provider config for pipeline mode. Use ``Patter.elevenlabs()`` or ``Patter.openaiTts()``. */
|
|
141
|
+
tts?: TTSConfig;
|
|
142
|
+
/** Dynamic variables for ``{placeholder}`` substitution in systemPrompt at call time. */
|
|
143
|
+
variables?: Record<string, string>;
|
|
144
|
+
/** Output guardrails — filter AI responses before TTS */
|
|
145
|
+
guardrails?: Guardrail[];
|
|
146
|
+
}
|
|
147
|
+
type PipelineMessageHandler = (data: Record<string, unknown>) => Promise<string>;
|
|
148
|
+
interface ServeOptions {
|
|
149
|
+
agent: AgentOptions;
|
|
150
|
+
port?: number;
|
|
151
|
+
onCallStart?: (data: Record<string, unknown>) => Promise<void>;
|
|
152
|
+
onCallEnd?: (data: Record<string, unknown>) => Promise<void>;
|
|
153
|
+
onTranscript?: (data: Record<string, unknown>) => Promise<void>;
|
|
154
|
+
/** Pipeline mode only — called with the user's transcript; return value is spoken.
|
|
155
|
+
* Can also be a URL string for remote webhook/WebSocket integration. */
|
|
156
|
+
onMessage?: PipelineMessageHandler | string;
|
|
157
|
+
/** Called after each turn with per-turn metrics. */
|
|
158
|
+
onMetrics?: (data: Record<string, unknown>) => Promise<void>;
|
|
159
|
+
/** When true, record calls via the Twilio Recordings API. */
|
|
160
|
+
recording?: boolean;
|
|
161
|
+
/** If set, spoken as a voicemail message when AMD detects a machine. */
|
|
162
|
+
voicemailMessage?: string;
|
|
163
|
+
/** Custom pricing overrides for cost calculation. */
|
|
164
|
+
pricing?: Record<string, Record<string, unknown>>;
|
|
165
|
+
/** When true (default), serve a dashboard UI at /dashboard. */
|
|
166
|
+
dashboard?: boolean;
|
|
167
|
+
/** Bearer token for dashboard/API authentication. */
|
|
168
|
+
dashboardToken?: string;
|
|
169
|
+
/** Path to SQLite database for dashboard persistence (not used in TS yet). */
|
|
170
|
+
dashboardDb?: string;
|
|
171
|
+
/** When true (default), persist dashboard data. */
|
|
172
|
+
dashboardPersist?: boolean;
|
|
173
|
+
}
|
|
174
|
+
interface LocalCallOptions {
|
|
175
|
+
to: string;
|
|
176
|
+
agent: AgentOptions;
|
|
177
|
+
machineDetection?: boolean;
|
|
178
|
+
/** If set, spoken as a voicemail message when AMD detects a machine. Requires machineDetection=true. */
|
|
179
|
+
voicemailMessage?: string;
|
|
180
|
+
/** Dynamic variables merged into agent.variables before call. Override agent-level variables. */
|
|
181
|
+
variables?: Record<string, string>;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
declare function deepgram(opts: {
|
|
185
|
+
apiKey: string;
|
|
186
|
+
language?: string;
|
|
187
|
+
}): STTConfig;
|
|
188
|
+
declare function whisper(opts: {
|
|
189
|
+
apiKey: string;
|
|
190
|
+
language?: string;
|
|
191
|
+
}): STTConfig;
|
|
192
|
+
declare function elevenlabs(opts: {
|
|
193
|
+
apiKey: string;
|
|
194
|
+
voice?: string;
|
|
195
|
+
}): TTSConfig;
|
|
196
|
+
declare function openaiTts(opts: {
|
|
197
|
+
apiKey: string;
|
|
198
|
+
voice?: string;
|
|
199
|
+
}): TTSConfig;
|
|
200
|
+
|
|
201
|
+
declare class Patter {
|
|
202
|
+
readonly apiKey: string;
|
|
203
|
+
private readonly backendUrl;
|
|
204
|
+
private readonly restUrl;
|
|
205
|
+
private readonly connection;
|
|
206
|
+
private readonly mode;
|
|
207
|
+
private readonly localConfig;
|
|
208
|
+
private embeddedServer;
|
|
209
|
+
constructor(options: PatterOptions | LocalOptions);
|
|
210
|
+
agent(opts: AgentOptions): AgentOptions;
|
|
211
|
+
serve(opts: ServeOptions): Promise<void>;
|
|
212
|
+
test(opts: ServeOptions): Promise<void>;
|
|
213
|
+
connect(options: ConnectOptions): Promise<void>;
|
|
214
|
+
call(options: CallOptions | LocalCallOptions): Promise<void>;
|
|
215
|
+
disconnect(): Promise<void>;
|
|
216
|
+
createAgent(opts: CreateAgentOptions): Promise<Agent>;
|
|
217
|
+
listAgents(): Promise<Agent[]>;
|
|
218
|
+
buyNumber(opts?: {
|
|
219
|
+
country?: string;
|
|
220
|
+
provider?: string;
|
|
221
|
+
}): Promise<PhoneNumber>;
|
|
222
|
+
assignAgent(numberId: string, agentId: string): Promise<void>;
|
|
223
|
+
listCalls(limit?: number): Promise<Call[]>;
|
|
224
|
+
static deepgram: typeof deepgram;
|
|
225
|
+
static whisper: typeof whisper;
|
|
226
|
+
static elevenlabs: typeof elevenlabs;
|
|
227
|
+
static openaiTts: typeof openaiTts;
|
|
228
|
+
static guardrail(opts: {
|
|
229
|
+
name: string;
|
|
230
|
+
blockedTerms?: string[];
|
|
231
|
+
check?: (text: string) => boolean;
|
|
232
|
+
replacement?: string;
|
|
233
|
+
}): Guardrail;
|
|
234
|
+
/**
|
|
235
|
+
* Create a tool definition for use with `agent({ tools: [...] })`.
|
|
236
|
+
*
|
|
237
|
+
* Either `handler` (a function) or `webhookUrl` must be provided.
|
|
238
|
+
*
|
|
239
|
+
* @param opts.name - Tool name (visible to the LLM).
|
|
240
|
+
* @param opts.description - What the tool does (visible to the LLM).
|
|
241
|
+
* @param opts.parameters - JSON Schema for tool arguments.
|
|
242
|
+
* @param opts.handler - Async function called in-process when the LLM invokes the tool.
|
|
243
|
+
* @param opts.webhookUrl - URL to POST to when the LLM invokes the tool.
|
|
244
|
+
*
|
|
245
|
+
* @example
|
|
246
|
+
* ```ts
|
|
247
|
+
* phone.agent({
|
|
248
|
+
* systemPrompt: 'You are a pizza bot.',
|
|
249
|
+
* tools: [
|
|
250
|
+
* Patter.tool({
|
|
251
|
+
* name: 'check_menu',
|
|
252
|
+
* description: 'Check available menu items',
|
|
253
|
+
* handler: async (args) => JSON.stringify({ items: ['margherita'] }),
|
|
254
|
+
* }),
|
|
255
|
+
* ],
|
|
256
|
+
* });
|
|
257
|
+
* ```
|
|
258
|
+
*/
|
|
259
|
+
static tool(opts: {
|
|
260
|
+
name: string;
|
|
261
|
+
description?: string;
|
|
262
|
+
parameters?: Record<string, unknown>;
|
|
263
|
+
handler?: (args: Record<string, unknown>, context: Record<string, unknown>) => Promise<string>;
|
|
264
|
+
webhookUrl?: string;
|
|
265
|
+
}): ToolDefinition;
|
|
266
|
+
private registerNumber;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
interface Logger {
|
|
270
|
+
info(message: string, ...args: unknown[]): void;
|
|
271
|
+
warn(message: string, ...args: unknown[]): void;
|
|
272
|
+
error(message: string, ...args: unknown[]): void;
|
|
273
|
+
debug(message: string, ...args: unknown[]): void;
|
|
274
|
+
}
|
|
275
|
+
declare function getLogger(): Logger;
|
|
276
|
+
declare function setLogger(logger: Logger): void;
|
|
277
|
+
|
|
278
|
+
declare class PatterError extends Error {
|
|
279
|
+
constructor(message: string);
|
|
280
|
+
}
|
|
281
|
+
declare class PatterConnectionError extends PatterError {
|
|
282
|
+
constructor(message: string);
|
|
283
|
+
}
|
|
284
|
+
declare class AuthenticationError extends PatterError {
|
|
285
|
+
constructor(message: string);
|
|
286
|
+
}
|
|
287
|
+
declare class ProvisionError extends PatterError {
|
|
288
|
+
constructor(message: string);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Default provider pricing and merge utilities.
|
|
293
|
+
*
|
|
294
|
+
* Pricing is based on public provider rates (as of early 2025).
|
|
295
|
+
* Developers can override any provider's pricing.
|
|
296
|
+
*/
|
|
297
|
+
interface ProviderPricing {
|
|
298
|
+
unit: string;
|
|
299
|
+
price?: number;
|
|
300
|
+
audio_input_per_token?: number;
|
|
301
|
+
audio_output_per_token?: number;
|
|
302
|
+
text_input_per_token?: number;
|
|
303
|
+
text_output_per_token?: number;
|
|
304
|
+
}
|
|
305
|
+
declare const DEFAULT_PRICING: Record<string, ProviderPricing>;
|
|
306
|
+
/**
|
|
307
|
+
* Merge user overrides into a copy of DEFAULT_PRICING.
|
|
308
|
+
* Performs a shallow per-provider merge.
|
|
309
|
+
*/
|
|
310
|
+
declare function mergePricing(overrides?: Record<string, Partial<ProviderPricing>> | null): Record<string, ProviderPricing>;
|
|
311
|
+
/** Calculate STT cost from audio duration. */
|
|
312
|
+
declare function calculateSttCost(provider: string, audioSeconds: number, pricing: Record<string, ProviderPricing>): number;
|
|
313
|
+
/** Calculate TTS cost from character count. */
|
|
314
|
+
declare function calculateTtsCost(provider: string, characterCount: number, pricing: Record<string, ProviderPricing>): number;
|
|
315
|
+
/** Calculate OpenAI Realtime cost from token usage. */
|
|
316
|
+
declare function calculateRealtimeCost(usage: {
|
|
317
|
+
input_token_details?: {
|
|
318
|
+
audio_tokens?: number;
|
|
319
|
+
text_tokens?: number;
|
|
320
|
+
};
|
|
321
|
+
output_token_details?: {
|
|
322
|
+
audio_tokens?: number;
|
|
323
|
+
text_tokens?: number;
|
|
324
|
+
};
|
|
325
|
+
}, pricing: Record<string, ProviderPricing>): number;
|
|
326
|
+
/** Calculate telephony cost from call duration. */
|
|
327
|
+
declare function calculateTelephonyCost(provider: string, durationSeconds: number, pricing: Record<string, ProviderPricing>): number;
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Call metrics accumulator — tracks cost and latency during a call.
|
|
331
|
+
*
|
|
332
|
+
* Port of the Python `CallMetricsAccumulator` from `sdk/patter/services/metrics.py`.
|
|
333
|
+
*/
|
|
334
|
+
|
|
335
|
+
interface LatencyBreakdown {
|
|
336
|
+
stt_ms: number;
|
|
337
|
+
llm_ms: number;
|
|
338
|
+
tts_ms: number;
|
|
339
|
+
total_ms: number;
|
|
340
|
+
}
|
|
341
|
+
interface CostBreakdown {
|
|
342
|
+
stt: number;
|
|
343
|
+
tts: number;
|
|
344
|
+
llm: number;
|
|
345
|
+
telephony: number;
|
|
346
|
+
total: number;
|
|
347
|
+
}
|
|
348
|
+
interface TurnMetrics {
|
|
349
|
+
turn_index: number;
|
|
350
|
+
user_text: string;
|
|
351
|
+
agent_text: string;
|
|
352
|
+
latency: LatencyBreakdown;
|
|
353
|
+
stt_audio_seconds: number;
|
|
354
|
+
tts_characters: number;
|
|
355
|
+
timestamp: number;
|
|
356
|
+
}
|
|
357
|
+
interface CallMetrics {
|
|
358
|
+
call_id: string;
|
|
359
|
+
duration_seconds: number;
|
|
360
|
+
turns: TurnMetrics[];
|
|
361
|
+
cost: CostBreakdown;
|
|
362
|
+
latency_avg: LatencyBreakdown;
|
|
363
|
+
latency_p95: LatencyBreakdown;
|
|
364
|
+
provider_mode: string;
|
|
365
|
+
stt_provider: string;
|
|
366
|
+
tts_provider: string;
|
|
367
|
+
llm_provider: string;
|
|
368
|
+
telephony_provider: string;
|
|
369
|
+
}
|
|
370
|
+
interface CallControl {
|
|
371
|
+
/** Transfer the call to a different number. */
|
|
372
|
+
transfer(number: string): Promise<void>;
|
|
373
|
+
/** Hang up the call. */
|
|
374
|
+
hangup(): Promise<void>;
|
|
375
|
+
/** Current call ID. */
|
|
376
|
+
readonly callId: string;
|
|
377
|
+
/** Caller number. */
|
|
378
|
+
readonly caller: string;
|
|
379
|
+
/** Callee number. */
|
|
380
|
+
readonly callee: string;
|
|
381
|
+
}
|
|
382
|
+
declare class CallMetricsAccumulator {
|
|
383
|
+
callId: string;
|
|
384
|
+
readonly providerMode: string;
|
|
385
|
+
readonly telephonyProvider: string;
|
|
386
|
+
readonly sttProvider: string;
|
|
387
|
+
readonly ttsProvider: string;
|
|
388
|
+
readonly llmProvider: string;
|
|
389
|
+
private readonly _pricing;
|
|
390
|
+
private readonly _callStart;
|
|
391
|
+
private readonly _turns;
|
|
392
|
+
private _turnStart;
|
|
393
|
+
private _sttComplete;
|
|
394
|
+
private _llmComplete;
|
|
395
|
+
private _ttsFirstByte;
|
|
396
|
+
private _turnUserText;
|
|
397
|
+
private _turnSttAudioSeconds;
|
|
398
|
+
private _totalSttAudioSeconds;
|
|
399
|
+
private _totalTtsCharacters;
|
|
400
|
+
private _totalRealtimeCost;
|
|
401
|
+
private _sttByteCount;
|
|
402
|
+
private _sttSampleRate;
|
|
403
|
+
private _sttBytesPerSample;
|
|
404
|
+
private _actualTelephonyCost;
|
|
405
|
+
private _actualSttCost;
|
|
406
|
+
constructor(opts: {
|
|
407
|
+
callId: string;
|
|
408
|
+
providerMode: string;
|
|
409
|
+
telephonyProvider: string;
|
|
410
|
+
sttProvider?: string;
|
|
411
|
+
ttsProvider?: string;
|
|
412
|
+
llmProvider?: string;
|
|
413
|
+
pricing?: Record<string, Partial<ProviderPricing>> | null;
|
|
414
|
+
});
|
|
415
|
+
/** Configure audio format for STT byte-to-seconds conversion. */
|
|
416
|
+
configureSttFormat(sampleRate?: number, bytesPerSample?: number): void;
|
|
417
|
+
startTurn(): void;
|
|
418
|
+
recordSttComplete(text: string, audioSeconds?: number): void;
|
|
419
|
+
recordLlmComplete(): void;
|
|
420
|
+
recordTtsFirstByte(): void;
|
|
421
|
+
recordTtsComplete(text: string): void;
|
|
422
|
+
recordTurnComplete(agentText: string): TurnMetrics;
|
|
423
|
+
recordTurnInterrupted(): TurnMetrics | null;
|
|
424
|
+
addSttAudioBytes(byteCount: number): void;
|
|
425
|
+
recordRealtimeUsage(usage: {
|
|
426
|
+
input_token_details?: {
|
|
427
|
+
audio_tokens?: number;
|
|
428
|
+
text_tokens?: number;
|
|
429
|
+
};
|
|
430
|
+
output_token_details?: {
|
|
431
|
+
audio_tokens?: number;
|
|
432
|
+
text_tokens?: number;
|
|
433
|
+
};
|
|
434
|
+
}): void;
|
|
435
|
+
setActualTelephonyCost(cost: number): void;
|
|
436
|
+
setActualSttCost(cost: number): void;
|
|
437
|
+
endCall(): CallMetrics;
|
|
438
|
+
getCostSoFar(): CostBreakdown;
|
|
439
|
+
private _resetTurnState;
|
|
440
|
+
private _computeTurnLatency;
|
|
441
|
+
private _computeCost;
|
|
442
|
+
private _computeAverageLatency;
|
|
443
|
+
private _computeP95Latency;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
declare class OpenAIRealtimeAdapter {
|
|
447
|
+
private readonly apiKey;
|
|
448
|
+
private readonly model;
|
|
449
|
+
private readonly voice;
|
|
450
|
+
private readonly instructions;
|
|
451
|
+
private readonly tools?;
|
|
452
|
+
private ws;
|
|
453
|
+
constructor(apiKey: string, model?: string, voice?: string, instructions?: string, tools?: Array<{
|
|
454
|
+
name: string;
|
|
455
|
+
description: string;
|
|
456
|
+
parameters: Record<string, unknown>;
|
|
457
|
+
}> | undefined);
|
|
458
|
+
connect(): Promise<void>;
|
|
459
|
+
sendAudio(mulawAudio: Buffer): void;
|
|
460
|
+
onEvent(callback: (type: string, data: unknown) => void): void;
|
|
461
|
+
cancelResponse(): void;
|
|
462
|
+
sendText(text: string): Promise<void>;
|
|
463
|
+
sendFunctionResult(callId: string, result: string): Promise<void>;
|
|
464
|
+
close(): void;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
declare class ElevenLabsConvAIAdapter {
|
|
468
|
+
private readonly apiKey;
|
|
469
|
+
private readonly agentId;
|
|
470
|
+
private readonly voiceId;
|
|
471
|
+
private readonly firstMessage;
|
|
472
|
+
private ws;
|
|
473
|
+
private eventCallback;
|
|
474
|
+
constructor(apiKey: string, agentId?: string, voiceId?: string, _modelId?: string, _language?: string, firstMessage?: string);
|
|
475
|
+
connect(): Promise<void>;
|
|
476
|
+
sendAudio(audioBytes: Buffer): void;
|
|
477
|
+
onEvent(callback: (type: string, data: unknown) => void): void;
|
|
478
|
+
close(): void;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
interface LocalConfig {
|
|
482
|
+
twilioSid?: string;
|
|
483
|
+
twilioToken?: string;
|
|
484
|
+
openaiKey?: string;
|
|
485
|
+
phoneNumber: string;
|
|
486
|
+
webhookUrl: string;
|
|
487
|
+
telephonyProvider?: 'twilio' | 'telnyx';
|
|
488
|
+
telnyxKey?: string;
|
|
489
|
+
telnyxConnectionId?: string;
|
|
490
|
+
/**
|
|
491
|
+
* Telnyx Ed25519 public key (base64-encoded, DER/SPKI format) used to verify
|
|
492
|
+
* incoming webhook signatures. Obtain from the Telnyx portal under
|
|
493
|
+
* API Keys → Webhook Keys. When provided, unauthenticated webhook requests
|
|
494
|
+
* are rejected with HTTP 403.
|
|
495
|
+
*/
|
|
496
|
+
telnyxPublicKey?: string;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* In-memory metrics store for the local dashboard.
|
|
501
|
+
*
|
|
502
|
+
* Keeps the last `maxCalls` completed calls and tracks active calls.
|
|
503
|
+
* Supports SSE event subscribers for real-time updates.
|
|
504
|
+
*/
|
|
505
|
+
|
|
506
|
+
interface CallRecord {
|
|
507
|
+
call_id: string;
|
|
508
|
+
caller: string;
|
|
509
|
+
callee: string;
|
|
510
|
+
direction: string;
|
|
511
|
+
started_at: number;
|
|
512
|
+
ended_at?: number;
|
|
513
|
+
transcript?: Array<{
|
|
514
|
+
role: string;
|
|
515
|
+
text: string;
|
|
516
|
+
timestamp: number;
|
|
517
|
+
}>;
|
|
518
|
+
turns?: unknown[];
|
|
519
|
+
metrics?: Record<string, unknown> | null;
|
|
520
|
+
[key: string]: unknown;
|
|
521
|
+
}
|
|
522
|
+
interface SSEEvent {
|
|
523
|
+
type: string;
|
|
524
|
+
data: Record<string, unknown>;
|
|
525
|
+
}
|
|
526
|
+
declare class MetricsStore extends EventEmitter {
|
|
527
|
+
private readonly maxCalls;
|
|
528
|
+
private calls;
|
|
529
|
+
private activeCalls;
|
|
530
|
+
constructor(maxCalls?: number);
|
|
531
|
+
private publish;
|
|
532
|
+
recordCallStart(data: Record<string, unknown>): void;
|
|
533
|
+
recordTurn(data: Record<string, unknown>): void;
|
|
534
|
+
recordCallEnd(data: Record<string, unknown>, metrics?: Record<string, unknown> | null): void;
|
|
535
|
+
getCalls(limit?: number, offset?: number): CallRecord[];
|
|
536
|
+
getCall(callId: string): CallRecord | null;
|
|
537
|
+
getActiveCalls(): CallRecord[];
|
|
538
|
+
getAggregates(): Record<string, unknown>;
|
|
539
|
+
getCallsInRange(fromTs?: number, toTs?: number): CallRecord[];
|
|
540
|
+
get callCount(): number;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* Dashboard authentication middleware for Express.
|
|
545
|
+
*
|
|
546
|
+
* When a token is configured, requests must include either:
|
|
547
|
+
* - Authorization: Bearer <token> header
|
|
548
|
+
* - ?token=<token> query parameter
|
|
549
|
+
*/
|
|
550
|
+
|
|
551
|
+
declare function makeAuthMiddleware(token?: string): (req: Request, res: Response, next: NextFunction) => void;
|
|
552
|
+
|
|
553
|
+
/**
|
|
554
|
+
* Data export utilities for the dashboard.
|
|
555
|
+
*/
|
|
556
|
+
|
|
557
|
+
/**
|
|
558
|
+
* Convert call list to CSV string.
|
|
559
|
+
*
|
|
560
|
+
* Columns: call_id, caller, callee, direction, started_at, ended_at,
|
|
561
|
+
* duration_s, cost_total, cost_stt, cost_tts, cost_llm, cost_telephony,
|
|
562
|
+
* avg_latency_ms, turns_count, provider_mode
|
|
563
|
+
*/
|
|
564
|
+
declare function callsToCsv(calls: CallRecord[]): string;
|
|
565
|
+
/**
|
|
566
|
+
* Convert call list to JSON string.
|
|
567
|
+
*/
|
|
568
|
+
declare function callsToJson(calls: CallRecord[]): string;
|
|
569
|
+
|
|
570
|
+
/**
|
|
571
|
+
* Dashboard and B2B API routes for the EmbeddedServer (Express).
|
|
572
|
+
*
|
|
573
|
+
* Mounts:
|
|
574
|
+
* GET / - HTML UI
|
|
575
|
+
* GET /api/dashboard/calls - call list JSON
|
|
576
|
+
* GET /api/dashboard/calls/:callId - single call JSON
|
|
577
|
+
* GET /api/dashboard/active - active calls JSON
|
|
578
|
+
* GET /api/dashboard/aggregates - aggregate stats JSON
|
|
579
|
+
* GET /api/dashboard/events - SSE event stream
|
|
580
|
+
* GET /api/dashboard/export/calls - CSV/JSON export
|
|
581
|
+
*
|
|
582
|
+
* GET /api/v1/calls - B2B paginated call history
|
|
583
|
+
* GET /api/v1/calls/active - B2B active calls
|
|
584
|
+
* GET /api/v1/calls/:callId - B2B single call detail
|
|
585
|
+
* GET /api/v1/analytics/overview - B2B aggregate stats
|
|
586
|
+
* GET /api/v1/analytics/costs - B2B cost breakdown
|
|
587
|
+
*/
|
|
588
|
+
|
|
589
|
+
declare function mountDashboard(app: Express, store: MetricsStore, token?: string): void;
|
|
590
|
+
declare function mountApi(app: Express, store: MetricsStore, token?: string): void;
|
|
591
|
+
|
|
592
|
+
/**
|
|
593
|
+
* Built-in LLM loop for pipeline mode when no onMessage handler is provided.
|
|
594
|
+
*
|
|
595
|
+
* Uses a pluggable ``LLMProvider`` interface so callers can supply OpenAI,
|
|
596
|
+
* Anthropic, Gemini, or any custom provider. The default provider is
|
|
597
|
+
* ``OpenAILLMProvider`` which preserves full backward compatibility.
|
|
598
|
+
*/
|
|
599
|
+
|
|
600
|
+
/** A single streaming chunk yielded by an LLM provider. */
|
|
601
|
+
interface LLMChunk {
|
|
602
|
+
type: 'text' | 'tool_call' | 'done';
|
|
603
|
+
content?: string;
|
|
604
|
+
index?: number;
|
|
605
|
+
id?: string;
|
|
606
|
+
name?: string;
|
|
607
|
+
arguments?: string;
|
|
608
|
+
}
|
|
609
|
+
/**
|
|
610
|
+
* Interface that any LLM provider must satisfy.
|
|
611
|
+
*
|
|
612
|
+
* Implementors yield streaming ``LLMChunk`` objects:
|
|
613
|
+
* - ``{ type: "text", content: "..." }`` — a text token.
|
|
614
|
+
* - ``{ type: "tool_call", index, id?, name?, arguments? }`` — a (partial) tool
|
|
615
|
+
* invocation. Chunks with the same ``index`` are concatenated.
|
|
616
|
+
* - ``{ type: "done" }`` — signals the end of the stream (optional).
|
|
617
|
+
*/
|
|
618
|
+
interface LLMProvider {
|
|
619
|
+
stream(messages: Array<Record<string, unknown>>, tools?: Array<Record<string, unknown>> | null): AsyncGenerator<LLMChunk, void, unknown>;
|
|
620
|
+
}
|
|
621
|
+
/** LLM provider backed by OpenAI Chat Completions (streaming). */
|
|
622
|
+
declare class OpenAILLMProvider implements LLMProvider {
|
|
623
|
+
private readonly apiKey;
|
|
624
|
+
private readonly model;
|
|
625
|
+
constructor(apiKey: string, model: string);
|
|
626
|
+
stream(messages: Array<Record<string, unknown>>, tools?: Array<Record<string, unknown>> | null): AsyncGenerator<LLMChunk, void, unknown>;
|
|
627
|
+
}
|
|
628
|
+
declare class LLMLoop {
|
|
629
|
+
private readonly provider;
|
|
630
|
+
private readonly systemPrompt;
|
|
631
|
+
private readonly tools;
|
|
632
|
+
private readonly openaiTools;
|
|
633
|
+
private readonly toolMap;
|
|
634
|
+
constructor(apiKey: string, model: string, systemPrompt: string, tools?: ToolDefinition[] | null, llmProvider?: LLMProvider);
|
|
635
|
+
/**
|
|
636
|
+
* Stream LLM response tokens, handling tool calls automatically.
|
|
637
|
+
* Yields text tokens as they arrive from the LLM.
|
|
638
|
+
*/
|
|
639
|
+
run(userText: string, history: Array<{
|
|
640
|
+
role: string;
|
|
641
|
+
text: string;
|
|
642
|
+
}>, callContext: Record<string, unknown>): AsyncGenerator<string, void, unknown>;
|
|
643
|
+
private executeTool;
|
|
644
|
+
private buildMessages;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
/**
|
|
648
|
+
* Remote message handler for B2B webhook and WebSocket integration.
|
|
649
|
+
*
|
|
650
|
+
* Allows onMessage to be a URL string instead of a callable:
|
|
651
|
+
* - HTTP webhook: onMessage="https://api.customer.com/patter/message"
|
|
652
|
+
* - WebSocket: onMessage="ws://localhost:9000/stream"
|
|
653
|
+
*/
|
|
654
|
+
declare class RemoteMessageHandler {
|
|
655
|
+
private readonly webhookSecret;
|
|
656
|
+
/**
|
|
657
|
+
* @param webhookSecret Optional HMAC secret. When provided, outgoing webhook
|
|
658
|
+
* requests include an `X-Patter-Signature` header so the receiver can
|
|
659
|
+
* verify the payload originated from Patter.
|
|
660
|
+
*/
|
|
661
|
+
constructor(webhookSecret?: string);
|
|
662
|
+
/**
|
|
663
|
+
* Compute HMAC-SHA256 hex digest for the given body.
|
|
664
|
+
*/
|
|
665
|
+
private signPayload;
|
|
666
|
+
/**
|
|
667
|
+
* Release resources held by this handler.
|
|
668
|
+
*/
|
|
669
|
+
close(): void;
|
|
670
|
+
/**
|
|
671
|
+
* POST transcript to HTTP webhook, return response text.
|
|
672
|
+
*
|
|
673
|
+
* The webhook receives a JSON payload:
|
|
674
|
+
* { text, call_id, caller, callee, history }
|
|
675
|
+
*
|
|
676
|
+
* The response can be plain text or JSON { text: "..." }.
|
|
677
|
+
*
|
|
678
|
+
* When `webhookSecret` was provided at construction time, the request
|
|
679
|
+
* includes an `X-Patter-Signature` header with the HMAC-SHA256 hex
|
|
680
|
+
* digest of the JSON body.
|
|
681
|
+
*/
|
|
682
|
+
callWebhook(url: string, data: Record<string, unknown>): Promise<string>;
|
|
683
|
+
/**
|
|
684
|
+
* Send transcript via WebSocket, yield response chunks.
|
|
685
|
+
*
|
|
686
|
+
* Sends the message data as JSON. Receives one or more JSON frames
|
|
687
|
+
* with { text: "..." } - multiple frames enable streaming.
|
|
688
|
+
* A frame with { done: true } signals end of response.
|
|
689
|
+
*/
|
|
690
|
+
callWebSocket(url: string, data: Record<string, unknown>): AsyncGenerator<string, void, unknown>;
|
|
691
|
+
}
|
|
692
|
+
/** Check if onMessage is a remote URL string. */
|
|
693
|
+
declare function isRemoteUrl(onMessage: unknown): onMessage is string;
|
|
694
|
+
/** Check if a URL is a WebSocket URL. */
|
|
695
|
+
declare function isWebSocketUrl(url: string): boolean;
|
|
696
|
+
|
|
697
|
+
/**
|
|
698
|
+
* Interactive terminal test mode for voice agents.
|
|
699
|
+
*
|
|
700
|
+
* Simulates a phone call without telephony, STT, or TTS - pure text
|
|
701
|
+
* input/output in the terminal. Useful for rapid agent development.
|
|
702
|
+
*/
|
|
703
|
+
|
|
704
|
+
declare class TestSession {
|
|
705
|
+
run(opts: {
|
|
706
|
+
agent: AgentOptions;
|
|
707
|
+
openaiKey?: string;
|
|
708
|
+
onMessage?: PipelineMessageHandler;
|
|
709
|
+
onCallStart?: (data: Record<string, unknown>) => Promise<void>;
|
|
710
|
+
onCallEnd?: (data: Record<string, unknown>) => Promise<void>;
|
|
711
|
+
}): Promise<void>;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
interface Transcript$1 {
|
|
715
|
+
readonly text: string;
|
|
716
|
+
readonly isFinal: boolean;
|
|
717
|
+
readonly confidence: number;
|
|
718
|
+
}
|
|
719
|
+
type TranscriptCallback$1 = (transcript: Transcript$1) => void;
|
|
720
|
+
declare class DeepgramSTT {
|
|
721
|
+
private readonly apiKey;
|
|
722
|
+
private readonly language;
|
|
723
|
+
private readonly model;
|
|
724
|
+
private readonly encoding;
|
|
725
|
+
private readonly sampleRate;
|
|
726
|
+
private ws;
|
|
727
|
+
private callbacks;
|
|
728
|
+
/** Request ID from Deepgram — used to query actual cost post-call. */
|
|
729
|
+
requestId: string;
|
|
730
|
+
constructor(apiKey: string, language?: string, model?: string, encoding?: string, sampleRate?: number);
|
|
731
|
+
/** Factory for Twilio calls — mulaw 8 kHz. */
|
|
732
|
+
static forTwilio(apiKey: string, language?: string, model?: string): DeepgramSTT;
|
|
733
|
+
connect(): Promise<void>;
|
|
734
|
+
sendAudio(audio: Buffer): void;
|
|
735
|
+
onTranscript(callback: TranscriptCallback$1): void;
|
|
736
|
+
close(): void;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
/**
|
|
740
|
+
* OpenAI Whisper STT adapter for the Patter SDK pipeline mode.
|
|
741
|
+
*
|
|
742
|
+
* Buffers incoming PCM16 audio and periodically sends it to the
|
|
743
|
+
* OpenAI Whisper transcription API as a WAV file.
|
|
744
|
+
*/
|
|
745
|
+
interface Transcript {
|
|
746
|
+
readonly text: string;
|
|
747
|
+
readonly isFinal: boolean;
|
|
748
|
+
readonly confidence: number;
|
|
749
|
+
}
|
|
750
|
+
type TranscriptCallback = (transcript: Transcript) => void;
|
|
751
|
+
declare class WhisperSTT {
|
|
752
|
+
private readonly apiKey;
|
|
753
|
+
private readonly model;
|
|
754
|
+
private readonly language;
|
|
755
|
+
private readonly bufferSize;
|
|
756
|
+
private buffer;
|
|
757
|
+
private callbacks;
|
|
758
|
+
private running;
|
|
759
|
+
constructor(apiKey: string, model?: string, language?: string, bufferSize?: number);
|
|
760
|
+
/** Factory for Twilio calls — mulaw 8 kHz is transcoded upstream, so we still receive PCM 16-bit. */
|
|
761
|
+
static forTwilio(apiKey: string, language?: string, model?: string): WhisperSTT;
|
|
762
|
+
connect(): Promise<void>;
|
|
763
|
+
sendAudio(audio: Buffer): void;
|
|
764
|
+
onTranscript(callback: TranscriptCallback): void;
|
|
765
|
+
close(): void;
|
|
766
|
+
private transcribeBuffer;
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
declare class ElevenLabsTTS {
|
|
770
|
+
private readonly apiKey;
|
|
771
|
+
private readonly voiceId;
|
|
772
|
+
private readonly modelId;
|
|
773
|
+
private readonly outputFormat;
|
|
774
|
+
constructor(apiKey: string, voiceId?: string, modelId?: string, outputFormat?: string);
|
|
775
|
+
/**
|
|
776
|
+
* Synthesise text to speech and return the full audio as a single Buffer.
|
|
777
|
+
*
|
|
778
|
+
* For large chunks (or when latency matters) call `synthesizeStream` instead.
|
|
779
|
+
*/
|
|
780
|
+
synthesize(text: string): Promise<Buffer>;
|
|
781
|
+
/**
|
|
782
|
+
* Synthesise text and yield audio chunks as they arrive (streaming).
|
|
783
|
+
*
|
|
784
|
+
* The yielded buffers are raw PCM at 16 kHz (or whatever `outputFormat` is
|
|
785
|
+
* configured to).
|
|
786
|
+
*/
|
|
787
|
+
synthesizeStream(text: string): AsyncGenerator<Buffer>;
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
declare class OpenAITTS {
|
|
791
|
+
private readonly apiKey;
|
|
792
|
+
private readonly voice;
|
|
793
|
+
private readonly model;
|
|
794
|
+
constructor(apiKey: string, voice?: string, model?: string);
|
|
795
|
+
/**
|
|
796
|
+
* Synthesise text to speech and return the full audio as a single Buffer.
|
|
797
|
+
*
|
|
798
|
+
* For large chunks (or when latency matters) call `synthesizeStream` instead.
|
|
799
|
+
*/
|
|
800
|
+
synthesize(text: string): Promise<Buffer>;
|
|
801
|
+
/**
|
|
802
|
+
* Synthesise text and yield audio chunks as they arrive (streaming).
|
|
803
|
+
*
|
|
804
|
+
* OpenAI returns 24 kHz PCM16; each chunk is resampled to 16 kHz before
|
|
805
|
+
* yielding so the output is ready for telephony pipelines.
|
|
806
|
+
*/
|
|
807
|
+
synthesizeStream(text: string): AsyncGenerator<Buffer>;
|
|
808
|
+
/**
|
|
809
|
+
* Resample 24 kHz PCM16-LE to 16 kHz by taking 2 out of every 3 samples.
|
|
810
|
+
*
|
|
811
|
+
* For each group of 3 input samples the first is kept as-is and the second
|
|
812
|
+
* output sample is the average of input samples 2 and 3. This matches the
|
|
813
|
+
* Python SDK implementation.
|
|
814
|
+
*/
|
|
815
|
+
static resample24kTo16k(audio: Buffer): Buffer;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
/**
|
|
819
|
+
* Audio transcoding utilities for Patter TypeScript SDK.
|
|
820
|
+
*
|
|
821
|
+
* Pure TypeScript implementation — no native dependencies required.
|
|
822
|
+
* Handles mulaw (G.711) encoding/decoding and PCM16 resampling for
|
|
823
|
+
* telephony audio pipelines (Twilio mulaw 8kHz, Telnyx 16kHz PCM,
|
|
824
|
+
* OpenAI TTS 24kHz PCM).
|
|
825
|
+
*/
|
|
826
|
+
/**
|
|
827
|
+
* Decode mu-law 8-bit audio to signed 16-bit little-endian PCM.
|
|
828
|
+
*
|
|
829
|
+
* Each input byte produces one 16-bit sample (2 bytes), so the output
|
|
830
|
+
* buffer is exactly twice the length of the input.
|
|
831
|
+
*/
|
|
832
|
+
declare function mulawToPcm16(mulawData: Buffer): Buffer;
|
|
833
|
+
/**
|
|
834
|
+
* Encode signed 16-bit little-endian PCM to mu-law 8-bit audio.
|
|
835
|
+
*
|
|
836
|
+
* Each pair of input bytes (one 16-bit sample) produces one output byte.
|
|
837
|
+
* If the input length is odd, the trailing byte is ignored.
|
|
838
|
+
*/
|
|
839
|
+
declare function pcm16ToMulaw(pcmData: Buffer): Buffer;
|
|
840
|
+
/**
|
|
841
|
+
* Upsample 8 kHz PCM16 to 16 kHz using linear interpolation.
|
|
842
|
+
*
|
|
843
|
+
* For each pair of consecutive samples (s[n], s[n+1]) the output
|
|
844
|
+
* contains s[n] followed by (s[n] + s[n+1]) / 2. The last sample
|
|
845
|
+
* is duplicated to fill the final position.
|
|
846
|
+
*
|
|
847
|
+
* Output length = input length * 2.
|
|
848
|
+
*/
|
|
849
|
+
declare function resample8kTo16k(pcm8k: Buffer): Buffer;
|
|
850
|
+
/**
|
|
851
|
+
* Downsample 16 kHz PCM16 to 8 kHz by taking every 2nd sample.
|
|
852
|
+
*
|
|
853
|
+
* Output length = input length / 2.
|
|
854
|
+
*/
|
|
855
|
+
declare function resample16kTo8k(pcm16k: Buffer): Buffer;
|
|
856
|
+
/**
|
|
857
|
+
* Downsample 24 kHz PCM16 to 16 kHz by taking 2 of every 3 samples.
|
|
858
|
+
*
|
|
859
|
+
* Matches the Python backend approach: for every group of 3 input samples,
|
|
860
|
+
* output the 1st and 2nd, skip the 3rd.
|
|
861
|
+
*
|
|
862
|
+
* Output length = floor(inputSamples * 2 / 3) * 2 bytes.
|
|
863
|
+
*/
|
|
864
|
+
declare function resample24kTo16k(pcm24k: Buffer): Buffer;
|
|
865
|
+
|
|
866
|
+
export { type Agent, type AgentOptions, AuthenticationError, type Call, type CallControl, type CallEventHandler, type CallMetrics, CallMetricsAccumulator, type CallOptions, type CallRecord, type ConnectOptions, type CostBreakdown, type CreateAgentOptions, DEFAULT_PRICING, DeepgramSTT, ElevenLabsConvAIAdapter, ElevenLabsTTS, type Guardrail, type IncomingMessage, type LLMChunk, LLMLoop, type LLMProvider, type LatencyBreakdown, type LocalCallOptions, type LocalConfig, type LocalOptions, type Logger, type MessageHandler, MetricsStore, OpenAILLMProvider, OpenAIRealtimeAdapter, OpenAITTS, Patter, PatterConnectionError, PatterError, type PatterOptions, type PhoneNumber, type PipelineMessageHandler, type ProviderPricing, ProvisionError, RemoteMessageHandler, type SSEEvent, type STTConfig, type ServeOptions, type TTSConfig, TestSession, type ToolDefinition, type TurnMetrics, WhisperSTT, calculateRealtimeCost, calculateSttCost, calculateTelephonyCost, calculateTtsCost, callsToCsv, callsToJson, deepgram, elevenlabs, getLogger, isRemoteUrl, isWebSocketUrl, makeAuthMiddleware, mergePricing, mountApi, mountDashboard, mulawToPcm16, openaiTts, pcm16ToMulaw, resample16kTo8k, resample24kTo16k, resample8kTo16k, setLogger, whisper };
|