realtime-voice-agents 2.0.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 +298 -0
- package/assets/elevator-jazz.ulaw +1 -0
- package/assets/keyboard-typing.ulaw +1 -0
- package/assets/lofi.ulaw +1 -0
- package/assets/ringing.ulaw +1 -0
- package/assets/thinking-hum.ulaw +1 -0
- package/dist/BackgroundAudioPlayer-iMcivjis.mjs +282 -0
- package/dist/BackgroundAudioPlayer-jfRULWKC.cjs +313 -0
- package/dist/BaseRealtimeProvider-BQigr5mB.mjs +62 -0
- package/dist/BaseRealtimeProvider-BehPNT1r.d.cts +239 -0
- package/dist/BaseRealtimeProvider-ClP8Wx1X.d.mts +239 -0
- package/dist/BaseRealtimeProvider-DI4pKtOb.cjs +91 -0
- package/dist/GeminiLiveProvider-DvkTgzjG.d.cts +101 -0
- package/dist/GeminiLiveProvider-x2nyx5aO.d.mts +101 -0
- package/dist/InMemorySessionStore-B0_i-DOU.cjs +34 -0
- package/dist/InMemorySessionStore-B5_rq61L.d.cts +83 -0
- package/dist/InMemorySessionStore-B5_rq61L.d.mts +83 -0
- package/dist/InMemorySessionStore-DYParOJO.mjs +29 -0
- package/dist/OpenAICompatibleProvider-Bdtl-UXH.mjs +402 -0
- package/dist/OpenAICompatibleProvider-NS4cKVQj.cjs +409 -0
- package/dist/audio.cjs +21 -0
- package/dist/audio.d.cts +165 -0
- package/dist/audio.d.mts +165 -0
- package/dist/audio.mjs +4 -0
- package/dist/env-DSnGaERV.cjs +19 -0
- package/dist/env-DUwUWTsg.mjs +14 -0
- package/dist/events-BUMYdETO.d.cts +24 -0
- package/dist/events-BUMYdETO.d.mts +24 -0
- package/dist/events-BxDTIKKq.cjs +48 -0
- package/dist/events-BylBSBW-.mjs +43 -0
- package/dist/gemini.cjs +401 -0
- package/dist/gemini.d.cts +41 -0
- package/dist/gemini.d.mts +41 -0
- package/dist/gemini.mjs +395 -0
- package/dist/index.cjs +2142 -0
- package/dist/index.d.cts +920 -0
- package/dist/index.d.mts +920 -0
- package/dist/index.mjs +2113 -0
- package/dist/mulaw--cwU2c9L.mjs +64 -0
- package/dist/mulaw-DLUObjdP.cjs +117 -0
- package/dist/openai.cjs +61 -0
- package/dist/openai.d.cts +121 -0
- package/dist/openai.d.mts +121 -0
- package/dist/openai.mjs +53 -0
- package/dist/presets-Bf75YXs5.d.cts +24 -0
- package/dist/presets-Bf75YXs5.d.mts +24 -0
- package/dist/rest-BYqiVOhe.mjs +265 -0
- package/dist/rest-BvUKut_k.cjs +300 -0
- package/dist/rolldown-runtime-VH7oDXx4.cjs +28 -0
- package/dist/session-config-BVLl7-ha.mjs +74 -0
- package/dist/session-config-c8sOw1XL.cjs +85 -0
- package/dist/store.cjs +3 -0
- package/dist/store.d.cts +2 -0
- package/dist/store.d.mts +2 -0
- package/dist/store.mjs +2 -0
- package/dist/testing.cjs +544 -0
- package/dist/testing.d.cts +191 -0
- package/dist/testing.d.mts +191 -0
- package/dist/testing.mjs +538 -0
- package/dist/transcode-C9aJG7_W.cjs +215 -0
- package/dist/transcode-CsAp97G9.mjs +198 -0
- package/dist/transport-B_PJFIVd.d.cts +155 -0
- package/dist/transport-CEaLFV4E.d.mts +155 -0
- package/dist/twilio.cjs +8 -0
- package/dist/twilio.d.cts +3 -0
- package/dist/twilio.d.mts +3 -0
- package/dist/twilio.mjs +2 -0
- package/dist/twiml-z9LjoF4_.d.cts +67 -0
- package/dist/twiml-z9LjoF4_.d.mts +67 -0
- package/dist/xai.cjs +92 -0
- package/dist/xai.d.cts +35 -0
- package/dist/xai.d.mts +35 -0
- package/dist/xai.mjs +86 -0
- package/package.json +183 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { t as TypedEmitter } from "./events-BUMYdETO.mjs";
|
|
2
|
+
//#region src/twilio/messages.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Twilio Media Streams wire messages.
|
|
5
|
+
* Reference: https://www.twilio.com/docs/voice/media-streams/websocket-messages
|
|
6
|
+
*
|
|
7
|
+
* Inbound (Twilio → server): connected, start, media, stop, mark, dtmf.
|
|
8
|
+
* Outbound (server → Twilio): media, mark, clear.
|
|
9
|
+
* All media payloads are base64 μ-law 8 kHz mono on `<Connect><Stream>` calls.
|
|
10
|
+
*/
|
|
11
|
+
interface TwilioConnectedEvent {
|
|
12
|
+
event: 'connected';
|
|
13
|
+
protocol?: string;
|
|
14
|
+
version?: string;
|
|
15
|
+
}
|
|
16
|
+
interface TwilioStartEvent {
|
|
17
|
+
event: 'start';
|
|
18
|
+
sequenceNumber?: string;
|
|
19
|
+
streamSid: string;
|
|
20
|
+
start: {
|
|
21
|
+
streamSid: string;
|
|
22
|
+
accountSid?: string;
|
|
23
|
+
callSid: string;
|
|
24
|
+
tracks?: string[];
|
|
25
|
+
mediaFormat?: {
|
|
26
|
+
encoding: string;
|
|
27
|
+
sampleRate: number;
|
|
28
|
+
channels: number;
|
|
29
|
+
};
|
|
30
|
+
/** `<Parameter name="…" value="…"/>` pairs from the TwiML `<Stream>`. */
|
|
31
|
+
customParameters?: Record<string, string>;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
interface TwilioMediaEvent {
|
|
35
|
+
event: 'media';
|
|
36
|
+
sequenceNumber?: string;
|
|
37
|
+
streamSid: string;
|
|
38
|
+
media: {
|
|
39
|
+
track?: 'inbound' | 'outbound';
|
|
40
|
+
chunk?: string;
|
|
41
|
+
/** Milliseconds since stream start — the honest wall clock of the call. */
|
|
42
|
+
timestamp?: string;
|
|
43
|
+
/** Base64 μ-law audio. */
|
|
44
|
+
payload: string;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
interface TwilioStopEvent {
|
|
48
|
+
event: 'stop';
|
|
49
|
+
sequenceNumber?: string;
|
|
50
|
+
streamSid: string;
|
|
51
|
+
stop?: {
|
|
52
|
+
accountSid?: string;
|
|
53
|
+
callSid?: string;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
interface TwilioMarkEvent {
|
|
57
|
+
event: 'mark';
|
|
58
|
+
sequenceNumber?: string;
|
|
59
|
+
streamSid: string;
|
|
60
|
+
mark: {
|
|
61
|
+
name: string;
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
interface TwilioDtmfEvent {
|
|
65
|
+
event: 'dtmf';
|
|
66
|
+
streamSid: string;
|
|
67
|
+
sequenceNumber?: string;
|
|
68
|
+
dtmf: {
|
|
69
|
+
track?: string;
|
|
70
|
+
digit: string;
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
type TwilioInboundMessage = TwilioConnectedEvent | TwilioStartEvent | TwilioMediaEvent | TwilioStopEvent | TwilioMarkEvent | TwilioDtmfEvent;
|
|
74
|
+
interface TwilioOutboundMedia {
|
|
75
|
+
event: 'media';
|
|
76
|
+
streamSid: string;
|
|
77
|
+
media: {
|
|
78
|
+
payload: string;
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
interface TwilioOutboundMark {
|
|
82
|
+
event: 'mark';
|
|
83
|
+
streamSid: string;
|
|
84
|
+
mark: {
|
|
85
|
+
name: string;
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
interface TwilioOutboundClear {
|
|
89
|
+
event: 'clear';
|
|
90
|
+
streamSid: string;
|
|
91
|
+
}
|
|
92
|
+
type TwilioOutboundMessage = TwilioOutboundMedia | TwilioOutboundMark | TwilioOutboundClear;
|
|
93
|
+
/**
|
|
94
|
+
* Parse a raw WebSocket frame into a Twilio inbound message.
|
|
95
|
+
* Returns null for non-JSON frames or unknown event types (Twilio may add
|
|
96
|
+
* events; unknown ones must not crash a live call).
|
|
97
|
+
*/
|
|
98
|
+
declare function parseTwilioMessage(raw: string | Buffer): TwilioInboundMessage | null;
|
|
99
|
+
//#endregion
|
|
100
|
+
//#region src/twilio/transport.d.ts
|
|
101
|
+
/** Minimal ws-shaped socket. `ws`-package sockets satisfy this directly. */
|
|
102
|
+
interface WebSocketLike {
|
|
103
|
+
send(data: string): void;
|
|
104
|
+
close(code?: number, reason?: string): void;
|
|
105
|
+
on(event: 'message', listener: (data: unknown, isBinary?: boolean) => void): unknown;
|
|
106
|
+
on(event: 'close', listener: (code?: number, reason?: unknown) => void): unknown;
|
|
107
|
+
on(event: 'error', listener: (error: Error) => void): unknown;
|
|
108
|
+
readyState?: number;
|
|
109
|
+
}
|
|
110
|
+
interface TransportEvents extends Record<string, (...args: any[]) => void> {
|
|
111
|
+
start: (event: TwilioStartEvent) => void;
|
|
112
|
+
media: (event: TwilioMediaEvent) => void;
|
|
113
|
+
stop: (event: TwilioStopEvent) => void;
|
|
114
|
+
mark: (event: TwilioMarkEvent) => void;
|
|
115
|
+
dtmf: (event: TwilioDtmfEvent) => void;
|
|
116
|
+
close: (info: {
|
|
117
|
+
code?: number;
|
|
118
|
+
reason?: string;
|
|
119
|
+
}) => void;
|
|
120
|
+
error: (error: Error) => void;
|
|
121
|
+
}
|
|
122
|
+
interface AwaitStartOptions {
|
|
123
|
+
/** Max time to wait for the `start` frame. Default 5000. */
|
|
124
|
+
timeoutMs?: number;
|
|
125
|
+
/** Max non-start frames tolerated before giving up. Default 8. */
|
|
126
|
+
maxPreStartMessages?: number;
|
|
127
|
+
}
|
|
128
|
+
declare class TwilioMediaTransport extends TypedEmitter<TransportEvents> {
|
|
129
|
+
private readonly ws;
|
|
130
|
+
private streamSidValue;
|
|
131
|
+
private startEvent;
|
|
132
|
+
private closed;
|
|
133
|
+
constructor(ws: WebSocketLike);
|
|
134
|
+
get streamSid(): string | null;
|
|
135
|
+
get start(): TwilioStartEvent | null;
|
|
136
|
+
get isOpen(): boolean;
|
|
137
|
+
/**
|
|
138
|
+
* Resolve with the `start` frame, or reject on timeout / too many pre-start
|
|
139
|
+
* frames / socket close. Media frames arriving before `start` are counted
|
|
140
|
+
* but not delivered (there is no session to deliver them to yet).
|
|
141
|
+
*/
|
|
142
|
+
awaitStart(options?: AwaitStartOptions): Promise<TwilioStartEvent>;
|
|
143
|
+
/** Forward one media payload (base64 μ-law) to the caller. */
|
|
144
|
+
sendMedia(payload: string): void;
|
|
145
|
+
/** Interleave a named mark; Twilio echoes it once playout reaches it. */
|
|
146
|
+
sendMark(name: string): void;
|
|
147
|
+
/** Flush Twilio's playout buffer (barge-in). Pending marks echo back as discarded. */
|
|
148
|
+
sendClear(): void;
|
|
149
|
+
close(code?: number, reason?: string): void;
|
|
150
|
+
private handleMessage;
|
|
151
|
+
private requireStreamSid;
|
|
152
|
+
private sendRaw;
|
|
153
|
+
}
|
|
154
|
+
//#endregion
|
|
155
|
+
export { TwilioConnectedEvent as a, TwilioMarkEvent as c, TwilioOutboundMark as d, TwilioOutboundMedia as f, parseTwilioMessage as g, TwilioStopEvent as h, WebSocketLike as i, TwilioMediaEvent as l, TwilioStartEvent as m, TransportEvents as n, TwilioDtmfEvent as o, TwilioOutboundMessage as p, TwilioMediaTransport as r, TwilioInboundMessage as s, AwaitStartOptions as t, TwilioOutboundClear as u };
|
package/dist/twilio.cjs
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_rest = require("./rest-BvUKut_k.cjs");
|
|
3
|
+
exports.TwilioMediaTransport = require_rest.TwilioMediaTransport;
|
|
4
|
+
exports.TwilioRestClient = require_rest.TwilioRestClient;
|
|
5
|
+
exports.assertValidPhoneNumber = require_rest.assertValidPhoneNumber;
|
|
6
|
+
exports.connectStreamTwiml = require_rest.connectStreamTwiml;
|
|
7
|
+
exports.escapeXml = require_rest.escapeXml;
|
|
8
|
+
exports.parseTwilioMessage = require_rest.parseTwilioMessage;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { a as TwilioConnectedEvent, c as TwilioMarkEvent, d as TwilioOutboundMark, f as TwilioOutboundMedia, g as parseTwilioMessage, h as TwilioStopEvent, i as WebSocketLike, l as TwilioMediaEvent, m as TwilioStartEvent, n as TransportEvents, o as TwilioDtmfEvent, p as TwilioOutboundMessage, r as TwilioMediaTransport, s as TwilioInboundMessage, t as AwaitStartOptions, u as TwilioOutboundClear } from "./transport-B_PJFIVd.cjs";
|
|
2
|
+
import { a as TwilioRestConfig, i as TwilioRestClient, n as connectStreamTwiml, o as assertValidPhoneNumber, r as escapeXml, t as ConnectStreamTwimlOptions } from "./twiml-z9LjoF4_.cjs";
|
|
3
|
+
export { type AwaitStartOptions, type ConnectStreamTwimlOptions, type TransportEvents, type TwilioConnectedEvent, type TwilioDtmfEvent, type TwilioInboundMessage, type TwilioMarkEvent, type TwilioMediaEvent, TwilioMediaTransport, type TwilioOutboundClear, type TwilioOutboundMark, type TwilioOutboundMedia, type TwilioOutboundMessage, TwilioRestClient, type TwilioRestConfig, type TwilioStartEvent, type TwilioStopEvent, type WebSocketLike, assertValidPhoneNumber, connectStreamTwiml, escapeXml, parseTwilioMessage };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { a as TwilioConnectedEvent, c as TwilioMarkEvent, d as TwilioOutboundMark, f as TwilioOutboundMedia, g as parseTwilioMessage, h as TwilioStopEvent, i as WebSocketLike, l as TwilioMediaEvent, m as TwilioStartEvent, n as TransportEvents, o as TwilioDtmfEvent, p as TwilioOutboundMessage, r as TwilioMediaTransport, s as TwilioInboundMessage, t as AwaitStartOptions, u as TwilioOutboundClear } from "./transport-CEaLFV4E.mjs";
|
|
2
|
+
import { a as TwilioRestConfig, i as TwilioRestClient, n as connectStreamTwiml, o as assertValidPhoneNumber, r as escapeXml, t as ConnectStreamTwimlOptions } from "./twiml-z9LjoF4_.mjs";
|
|
3
|
+
export { type AwaitStartOptions, type ConnectStreamTwimlOptions, type TransportEvents, type TwilioConnectedEvent, type TwilioDtmfEvent, type TwilioInboundMessage, type TwilioMarkEvent, type TwilioMediaEvent, TwilioMediaTransport, type TwilioOutboundClear, type TwilioOutboundMark, type TwilioOutboundMedia, type TwilioOutboundMessage, TwilioRestClient, type TwilioRestConfig, type TwilioStartEvent, type TwilioStopEvent, type WebSocketLike, assertValidPhoneNumber, connectStreamTwiml, escapeXml, parseTwilioMessage };
|
package/dist/twilio.mjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as TwilioMediaTransport, i as escapeXml, n as assertValidPhoneNumber, o as parseTwilioMessage, r as connectStreamTwiml, t as TwilioRestClient } from "./rest-BYqiVOhe.mjs";
|
|
2
|
+
export { TwilioMediaTransport, TwilioRestClient, assertValidPhoneNumber, connectStreamTwiml, escapeXml, parseTwilioMessage };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
//#region src/twilio/rest.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Twilio REST control plane: hangup, transfer, SMS/WhatsApp.
|
|
4
|
+
*
|
|
5
|
+
* Media and control are different planes — the WebSocket carries audio, but
|
|
6
|
+
* ending or redirecting the PSTN leg goes through the REST API. The `twilio`
|
|
7
|
+
* SDK is an optional peer dependency, imported lazily so bridges that never
|
|
8
|
+
* use REST features don't need it installed.
|
|
9
|
+
*/
|
|
10
|
+
interface TwilioRestConfig {
|
|
11
|
+
accountSid: string;
|
|
12
|
+
authToken: string;
|
|
13
|
+
callerId?: string;
|
|
14
|
+
}
|
|
15
|
+
declare function assertValidPhoneNumber(phoneNumber: string): void;
|
|
16
|
+
declare class TwilioRestClient {
|
|
17
|
+
private readonly config;
|
|
18
|
+
private clientPromise;
|
|
19
|
+
constructor(config: TwilioRestConfig);
|
|
20
|
+
private client;
|
|
21
|
+
/** End the PSTN leg cleanly (better than just dropping the stream). */
|
|
22
|
+
completeCall(callSid: string): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Blind-transfer the call: replace its TwiML with a `<Dial>`. The number
|
|
25
|
+
* is validated and XML-escaped — never interpolate LLM output raw into
|
|
26
|
+
* markup.
|
|
27
|
+
*/
|
|
28
|
+
transferCall(callSid: string, phoneNumber: string, options?: {
|
|
29
|
+
callerId?: string;
|
|
30
|
+
}): Promise<void>;
|
|
31
|
+
sendSms(options: {
|
|
32
|
+
to: string;
|
|
33
|
+
body: string;
|
|
34
|
+
from: string;
|
|
35
|
+
}): Promise<{
|
|
36
|
+
sid: string;
|
|
37
|
+
}>;
|
|
38
|
+
sendWhatsapp(options: {
|
|
39
|
+
to: string;
|
|
40
|
+
body: string;
|
|
41
|
+
from: string;
|
|
42
|
+
}): Promise<{
|
|
43
|
+
sid: string;
|
|
44
|
+
}>;
|
|
45
|
+
}
|
|
46
|
+
//#endregion
|
|
47
|
+
//#region src/twilio/twiml.d.ts
|
|
48
|
+
/** TwiML helpers for wiring a call into the media-stream bridge. */
|
|
49
|
+
declare function escapeXml(value: string): string;
|
|
50
|
+
interface ConnectStreamTwimlOptions {
|
|
51
|
+
/** wss:// URL of the media-stream WebSocket route. */
|
|
52
|
+
wsUrl: string;
|
|
53
|
+
/**
|
|
54
|
+
* Custom `<Parameter>`s delivered in the start frame's customParameters —
|
|
55
|
+
* the place for auth tokens, tenant ids, or per-call config keys.
|
|
56
|
+
*/
|
|
57
|
+
parameters?: Record<string, string>;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Build the TwiML that connects a call to the bridge.
|
|
61
|
+
*
|
|
62
|
+
* `<Connect><Stream>` is the bidirectional form. `<Start><Stream>` is
|
|
63
|
+
* send-only — the caller would never hear the agent.
|
|
64
|
+
*/
|
|
65
|
+
declare function connectStreamTwiml(options: ConnectStreamTwimlOptions): string;
|
|
66
|
+
//#endregion
|
|
67
|
+
export { TwilioRestConfig as a, TwilioRestClient as i, connectStreamTwiml as n, assertValidPhoneNumber as o, escapeXml as r, ConnectStreamTwimlOptions as t };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
//#region src/twilio/rest.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Twilio REST control plane: hangup, transfer, SMS/WhatsApp.
|
|
4
|
+
*
|
|
5
|
+
* Media and control are different planes — the WebSocket carries audio, but
|
|
6
|
+
* ending or redirecting the PSTN leg goes through the REST API. The `twilio`
|
|
7
|
+
* SDK is an optional peer dependency, imported lazily so bridges that never
|
|
8
|
+
* use REST features don't need it installed.
|
|
9
|
+
*/
|
|
10
|
+
interface TwilioRestConfig {
|
|
11
|
+
accountSid: string;
|
|
12
|
+
authToken: string;
|
|
13
|
+
callerId?: string;
|
|
14
|
+
}
|
|
15
|
+
declare function assertValidPhoneNumber(phoneNumber: string): void;
|
|
16
|
+
declare class TwilioRestClient {
|
|
17
|
+
private readonly config;
|
|
18
|
+
private clientPromise;
|
|
19
|
+
constructor(config: TwilioRestConfig);
|
|
20
|
+
private client;
|
|
21
|
+
/** End the PSTN leg cleanly (better than just dropping the stream). */
|
|
22
|
+
completeCall(callSid: string): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Blind-transfer the call: replace its TwiML with a `<Dial>`. The number
|
|
25
|
+
* is validated and XML-escaped — never interpolate LLM output raw into
|
|
26
|
+
* markup.
|
|
27
|
+
*/
|
|
28
|
+
transferCall(callSid: string, phoneNumber: string, options?: {
|
|
29
|
+
callerId?: string;
|
|
30
|
+
}): Promise<void>;
|
|
31
|
+
sendSms(options: {
|
|
32
|
+
to: string;
|
|
33
|
+
body: string;
|
|
34
|
+
from: string;
|
|
35
|
+
}): Promise<{
|
|
36
|
+
sid: string;
|
|
37
|
+
}>;
|
|
38
|
+
sendWhatsapp(options: {
|
|
39
|
+
to: string;
|
|
40
|
+
body: string;
|
|
41
|
+
from: string;
|
|
42
|
+
}): Promise<{
|
|
43
|
+
sid: string;
|
|
44
|
+
}>;
|
|
45
|
+
}
|
|
46
|
+
//#endregion
|
|
47
|
+
//#region src/twilio/twiml.d.ts
|
|
48
|
+
/** TwiML helpers for wiring a call into the media-stream bridge. */
|
|
49
|
+
declare function escapeXml(value: string): string;
|
|
50
|
+
interface ConnectStreamTwimlOptions {
|
|
51
|
+
/** wss:// URL of the media-stream WebSocket route. */
|
|
52
|
+
wsUrl: string;
|
|
53
|
+
/**
|
|
54
|
+
* Custom `<Parameter>`s delivered in the start frame's customParameters —
|
|
55
|
+
* the place for auth tokens, tenant ids, or per-call config keys.
|
|
56
|
+
*/
|
|
57
|
+
parameters?: Record<string, string>;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Build the TwiML that connects a call to the bridge.
|
|
61
|
+
*
|
|
62
|
+
* `<Connect><Stream>` is the bidirectional form. `<Start><Stream>` is
|
|
63
|
+
* send-only — the caller would never hear the agent.
|
|
64
|
+
*/
|
|
65
|
+
declare function connectStreamTwiml(options: ConnectStreamTwimlOptions): string;
|
|
66
|
+
//#endregion
|
|
67
|
+
export { TwilioRestConfig as a, TwilioRestClient as i, connectStreamTwiml as n, assertValidPhoneNumber as o, escapeXml as r, ConnectStreamTwimlOptions as t };
|
package/dist/xai.cjs
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_BaseRealtimeProvider = require("./BaseRealtimeProvider-DI4pKtOb.cjs");
|
|
3
|
+
const require_session_config = require("./session-config-c8sOw1XL.cjs");
|
|
4
|
+
const require_env = require("./env-DSnGaERV.cjs");
|
|
5
|
+
const require_OpenAICompatibleProvider = require("./OpenAICompatibleProvider-NS4cKVQj.cjs");
|
|
6
|
+
//#region src/xai.ts
|
|
7
|
+
/**
|
|
8
|
+
* xAI Grok Voice Agent provider — `realtime-voice-agents/xai`.
|
|
9
|
+
*
|
|
10
|
+
* The Voice Agent API is OpenAI-Realtime-compatible on the wire (GA event
|
|
11
|
+
* names, `audio/pcmu` at 8 kHz supported → zero transcoding), with a slightly
|
|
12
|
+
* different session shape: `voice` and `turn_detection` live at the session
|
|
13
|
+
* root, audio formats carry an explicit `rate`, and transcription is
|
|
14
|
+
* configured via `language_hint`/`keyterms`.
|
|
15
|
+
* Docs: https://docs.x.ai/developers/model-capabilities/audio/voice-agent
|
|
16
|
+
*/
|
|
17
|
+
const XAI_BASE_URL = "wss://api.x.ai/v1/realtime";
|
|
18
|
+
/** Env vars checked (in order) when no explicit apiKey is passed. */
|
|
19
|
+
const XAI_KEY_ENV_VARS = [
|
|
20
|
+
"XAI_API_KEY",
|
|
21
|
+
"GROK_API_KEY",
|
|
22
|
+
"XAI_KEY"
|
|
23
|
+
];
|
|
24
|
+
/** Alias tracking xAI's flagship voice model. */
|
|
25
|
+
const XAI_DEFAULT_MODEL = "grok-voice-latest";
|
|
26
|
+
const XAI_DEFAULT_VOICE = "eve";
|
|
27
|
+
/** xAI session.update: GA-style nested audio, voice/turn_detection at root. */
|
|
28
|
+
function buildXaiSessionUpdate(init, config = {}) {
|
|
29
|
+
const voice = init.voice ?? config.defaultVoice;
|
|
30
|
+
const transcription = init.transcription === false ? void 0 : init.transcription;
|
|
31
|
+
let session = {
|
|
32
|
+
instructions: init.instructions,
|
|
33
|
+
...voice ? { voice } : {},
|
|
34
|
+
turn_detection: require_session_config.buildTurnDetection(init.vad),
|
|
35
|
+
tools: (init.tools ?? []).map((tool) => ({
|
|
36
|
+
type: "function",
|
|
37
|
+
name: tool.name,
|
|
38
|
+
description: tool.description ?? "",
|
|
39
|
+
parameters: tool.parameters
|
|
40
|
+
})),
|
|
41
|
+
audio: {
|
|
42
|
+
input: {
|
|
43
|
+
format: {
|
|
44
|
+
type: "audio/pcmu",
|
|
45
|
+
rate: 8e3
|
|
46
|
+
},
|
|
47
|
+
...transcription ? { transcription: { ...transcription.language ? { language_hint: transcription.language } : {} } } : {}
|
|
48
|
+
},
|
|
49
|
+
output: { format: {
|
|
50
|
+
type: "audio/pcmu",
|
|
51
|
+
rate: 8e3
|
|
52
|
+
} }
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
session = require_BaseRealtimeProvider.deepMerge(session, init.providerOptions);
|
|
56
|
+
session = require_BaseRealtimeProvider.deepMerge(session, config.extraSessionOptions);
|
|
57
|
+
return {
|
|
58
|
+
type: "session.update",
|
|
59
|
+
session
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/** Create an xAI Grok Voice provider factory for the bridge. */
|
|
63
|
+
function xaiRealtime(options = {}) {
|
|
64
|
+
const apiKey = require_env.resolveApiKey(options.apiKey, XAI_KEY_ENV_VARS);
|
|
65
|
+
if (!apiKey) throw new Error(`xaiRealtime: apiKey missing (pass apiKey or set one of ${XAI_KEY_ENV_VARS.join("/")})`);
|
|
66
|
+
const transcription = options.transcription === false ? false : options.transcription ? { language: options.transcription.languageHint } : void 0;
|
|
67
|
+
const config = {
|
|
68
|
+
apiKey,
|
|
69
|
+
model: options.model ?? "grok-voice-latest",
|
|
70
|
+
voice: options.voice ?? "eve",
|
|
71
|
+
baseUrl: options.baseUrl ?? "wss://api.x.ai/v1/realtime",
|
|
72
|
+
defaultVad: options.vad,
|
|
73
|
+
defaultTranscription: transcription,
|
|
74
|
+
headers: options.headers,
|
|
75
|
+
extraSessionOptions: options.transcription ? require_BaseRealtimeProvider.deepMerge({ audio: { input: { transcription: { ...options.transcription.keyterms ? { keyterms: options.transcription.keyterms } : {} } } } }, options.sessionOptions) : options.sessionOptions,
|
|
76
|
+
connectTimeoutMs: options.connectTimeoutMs,
|
|
77
|
+
providerName: "xai",
|
|
78
|
+
buildSession: buildXaiSessionUpdate,
|
|
79
|
+
capabilityOverrides: {
|
|
80
|
+
truncate: false,
|
|
81
|
+
vadInterruptControl: false
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
return ({ logger }) => new require_OpenAICompatibleProvider.OpenAICompatibleProvider(config, logger);
|
|
85
|
+
}
|
|
86
|
+
//#endregion
|
|
87
|
+
exports.XAI_BASE_URL = XAI_BASE_URL;
|
|
88
|
+
exports.XAI_DEFAULT_MODEL = XAI_DEFAULT_MODEL;
|
|
89
|
+
exports.XAI_DEFAULT_VOICE = XAI_DEFAULT_VOICE;
|
|
90
|
+
exports.XAI_KEY_ENV_VARS = XAI_KEY_ENV_VARS;
|
|
91
|
+
exports.buildXaiSessionUpdate = buildXaiSessionUpdate;
|
|
92
|
+
exports.xaiRealtime = xaiRealtime;
|
package/dist/xai.d.cts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { c as VadConfig, i as ProviderSessionInit, n as ProviderFactory } from "./BaseRealtimeProvider-BehPNT1r.cjs";
|
|
2
|
+
//#region src/xai.d.ts
|
|
3
|
+
declare const XAI_BASE_URL = "wss://api.x.ai/v1/realtime";
|
|
4
|
+
/** Env vars checked (in order) when no explicit apiKey is passed. */
|
|
5
|
+
declare const XAI_KEY_ENV_VARS: readonly ["XAI_API_KEY", "GROK_API_KEY", "XAI_KEY"];
|
|
6
|
+
/** Alias tracking xAI's flagship voice model. */
|
|
7
|
+
declare const XAI_DEFAULT_MODEL = "grok-voice-latest";
|
|
8
|
+
declare const XAI_DEFAULT_VOICE = "eve";
|
|
9
|
+
interface XaiRealtimeOptions {
|
|
10
|
+
/** Defaults to the first of XAI_API_KEY / GROK_API_KEY / XAI_KEY set in the env. */
|
|
11
|
+
apiKey?: string;
|
|
12
|
+
/** `grok-voice-latest` (default), `grok-voice-think-fast-2.0`, … */
|
|
13
|
+
model?: string;
|
|
14
|
+
voice?: string;
|
|
15
|
+
baseUrl?: string;
|
|
16
|
+
vad?: VadConfig | null;
|
|
17
|
+
/** Speech-recognition hints. `false` omits transcription config. */
|
|
18
|
+
transcription?: {
|
|
19
|
+
languageHint?: string;
|
|
20
|
+
keyterms?: string[];
|
|
21
|
+
} | false;
|
|
22
|
+
headers?: Record<string, string>;
|
|
23
|
+
/** Provider-native session fields, deep-merged last (escape hatch). */
|
|
24
|
+
sessionOptions?: Record<string, unknown>;
|
|
25
|
+
connectTimeoutMs?: number;
|
|
26
|
+
}
|
|
27
|
+
/** xAI session.update: GA-style nested audio, voice/turn_detection at root. */
|
|
28
|
+
declare function buildXaiSessionUpdate(init: ProviderSessionInit, config?: {
|
|
29
|
+
defaultVoice?: string;
|
|
30
|
+
extraSessionOptions?: Record<string, unknown>;
|
|
31
|
+
}): Record<string, unknown>;
|
|
32
|
+
/** Create an xAI Grok Voice provider factory for the bridge. */
|
|
33
|
+
declare function xaiRealtime(options?: XaiRealtimeOptions): ProviderFactory;
|
|
34
|
+
//#endregion
|
|
35
|
+
export { XAI_BASE_URL, XAI_DEFAULT_MODEL, XAI_DEFAULT_VOICE, XAI_KEY_ENV_VARS, XaiRealtimeOptions, buildXaiSessionUpdate, xaiRealtime };
|
package/dist/xai.d.mts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { c as VadConfig, i as ProviderSessionInit, n as ProviderFactory } from "./BaseRealtimeProvider-ClP8Wx1X.mjs";
|
|
2
|
+
//#region src/xai.d.ts
|
|
3
|
+
declare const XAI_BASE_URL = "wss://api.x.ai/v1/realtime";
|
|
4
|
+
/** Env vars checked (in order) when no explicit apiKey is passed. */
|
|
5
|
+
declare const XAI_KEY_ENV_VARS: readonly ["XAI_API_KEY", "GROK_API_KEY", "XAI_KEY"];
|
|
6
|
+
/** Alias tracking xAI's flagship voice model. */
|
|
7
|
+
declare const XAI_DEFAULT_MODEL = "grok-voice-latest";
|
|
8
|
+
declare const XAI_DEFAULT_VOICE = "eve";
|
|
9
|
+
interface XaiRealtimeOptions {
|
|
10
|
+
/** Defaults to the first of XAI_API_KEY / GROK_API_KEY / XAI_KEY set in the env. */
|
|
11
|
+
apiKey?: string;
|
|
12
|
+
/** `grok-voice-latest` (default), `grok-voice-think-fast-2.0`, … */
|
|
13
|
+
model?: string;
|
|
14
|
+
voice?: string;
|
|
15
|
+
baseUrl?: string;
|
|
16
|
+
vad?: VadConfig | null;
|
|
17
|
+
/** Speech-recognition hints. `false` omits transcription config. */
|
|
18
|
+
transcription?: {
|
|
19
|
+
languageHint?: string;
|
|
20
|
+
keyterms?: string[];
|
|
21
|
+
} | false;
|
|
22
|
+
headers?: Record<string, string>;
|
|
23
|
+
/** Provider-native session fields, deep-merged last (escape hatch). */
|
|
24
|
+
sessionOptions?: Record<string, unknown>;
|
|
25
|
+
connectTimeoutMs?: number;
|
|
26
|
+
}
|
|
27
|
+
/** xAI session.update: GA-style nested audio, voice/turn_detection at root. */
|
|
28
|
+
declare function buildXaiSessionUpdate(init: ProviderSessionInit, config?: {
|
|
29
|
+
defaultVoice?: string;
|
|
30
|
+
extraSessionOptions?: Record<string, unknown>;
|
|
31
|
+
}): Record<string, unknown>;
|
|
32
|
+
/** Create an xAI Grok Voice provider factory for the bridge. */
|
|
33
|
+
declare function xaiRealtime(options?: XaiRealtimeOptions): ProviderFactory;
|
|
34
|
+
//#endregion
|
|
35
|
+
export { XAI_BASE_URL, XAI_DEFAULT_MODEL, XAI_DEFAULT_VOICE, XAI_KEY_ENV_VARS, XaiRealtimeOptions, buildXaiSessionUpdate, xaiRealtime };
|
package/dist/xai.mjs
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { n as deepMerge } from "./BaseRealtimeProvider-BQigr5mB.mjs";
|
|
2
|
+
import { n as buildTurnDetection } from "./session-config-BVLl7-ha.mjs";
|
|
3
|
+
import { t as resolveApiKey } from "./env-DUwUWTsg.mjs";
|
|
4
|
+
import { t as OpenAICompatibleProvider } from "./OpenAICompatibleProvider-Bdtl-UXH.mjs";
|
|
5
|
+
//#region src/xai.ts
|
|
6
|
+
/**
|
|
7
|
+
* xAI Grok Voice Agent provider — `realtime-voice-agents/xai`.
|
|
8
|
+
*
|
|
9
|
+
* The Voice Agent API is OpenAI-Realtime-compatible on the wire (GA event
|
|
10
|
+
* names, `audio/pcmu` at 8 kHz supported → zero transcoding), with a slightly
|
|
11
|
+
* different session shape: `voice` and `turn_detection` live at the session
|
|
12
|
+
* root, audio formats carry an explicit `rate`, and transcription is
|
|
13
|
+
* configured via `language_hint`/`keyterms`.
|
|
14
|
+
* Docs: https://docs.x.ai/developers/model-capabilities/audio/voice-agent
|
|
15
|
+
*/
|
|
16
|
+
const XAI_BASE_URL = "wss://api.x.ai/v1/realtime";
|
|
17
|
+
/** Env vars checked (in order) when no explicit apiKey is passed. */
|
|
18
|
+
const XAI_KEY_ENV_VARS = [
|
|
19
|
+
"XAI_API_KEY",
|
|
20
|
+
"GROK_API_KEY",
|
|
21
|
+
"XAI_KEY"
|
|
22
|
+
];
|
|
23
|
+
/** Alias tracking xAI's flagship voice model. */
|
|
24
|
+
const XAI_DEFAULT_MODEL = "grok-voice-latest";
|
|
25
|
+
const XAI_DEFAULT_VOICE = "eve";
|
|
26
|
+
/** xAI session.update: GA-style nested audio, voice/turn_detection at root. */
|
|
27
|
+
function buildXaiSessionUpdate(init, config = {}) {
|
|
28
|
+
const voice = init.voice ?? config.defaultVoice;
|
|
29
|
+
const transcription = init.transcription === false ? void 0 : init.transcription;
|
|
30
|
+
let session = {
|
|
31
|
+
instructions: init.instructions,
|
|
32
|
+
...voice ? { voice } : {},
|
|
33
|
+
turn_detection: buildTurnDetection(init.vad),
|
|
34
|
+
tools: (init.tools ?? []).map((tool) => ({
|
|
35
|
+
type: "function",
|
|
36
|
+
name: tool.name,
|
|
37
|
+
description: tool.description ?? "",
|
|
38
|
+
parameters: tool.parameters
|
|
39
|
+
})),
|
|
40
|
+
audio: {
|
|
41
|
+
input: {
|
|
42
|
+
format: {
|
|
43
|
+
type: "audio/pcmu",
|
|
44
|
+
rate: 8e3
|
|
45
|
+
},
|
|
46
|
+
...transcription ? { transcription: { ...transcription.language ? { language_hint: transcription.language } : {} } } : {}
|
|
47
|
+
},
|
|
48
|
+
output: { format: {
|
|
49
|
+
type: "audio/pcmu",
|
|
50
|
+
rate: 8e3
|
|
51
|
+
} }
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
session = deepMerge(session, init.providerOptions);
|
|
55
|
+
session = deepMerge(session, config.extraSessionOptions);
|
|
56
|
+
return {
|
|
57
|
+
type: "session.update",
|
|
58
|
+
session
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/** Create an xAI Grok Voice provider factory for the bridge. */
|
|
62
|
+
function xaiRealtime(options = {}) {
|
|
63
|
+
const apiKey = resolveApiKey(options.apiKey, XAI_KEY_ENV_VARS);
|
|
64
|
+
if (!apiKey) throw new Error(`xaiRealtime: apiKey missing (pass apiKey or set one of ${XAI_KEY_ENV_VARS.join("/")})`);
|
|
65
|
+
const transcription = options.transcription === false ? false : options.transcription ? { language: options.transcription.languageHint } : void 0;
|
|
66
|
+
const config = {
|
|
67
|
+
apiKey,
|
|
68
|
+
model: options.model ?? "grok-voice-latest",
|
|
69
|
+
voice: options.voice ?? "eve",
|
|
70
|
+
baseUrl: options.baseUrl ?? "wss://api.x.ai/v1/realtime",
|
|
71
|
+
defaultVad: options.vad,
|
|
72
|
+
defaultTranscription: transcription,
|
|
73
|
+
headers: options.headers,
|
|
74
|
+
extraSessionOptions: options.transcription ? deepMerge({ audio: { input: { transcription: { ...options.transcription.keyterms ? { keyterms: options.transcription.keyterms } : {} } } } }, options.sessionOptions) : options.sessionOptions,
|
|
75
|
+
connectTimeoutMs: options.connectTimeoutMs,
|
|
76
|
+
providerName: "xai",
|
|
77
|
+
buildSession: buildXaiSessionUpdate,
|
|
78
|
+
capabilityOverrides: {
|
|
79
|
+
truncate: false,
|
|
80
|
+
vadInterruptControl: false
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
return ({ logger }) => new OpenAICompatibleProvider(config, logger);
|
|
84
|
+
}
|
|
85
|
+
//#endregion
|
|
86
|
+
export { XAI_BASE_URL, XAI_DEFAULT_MODEL, XAI_DEFAULT_VOICE, XAI_KEY_ENV_VARS, buildXaiSessionUpdate, xaiRealtime };
|