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.
Files changed (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +298 -0
  3. package/assets/elevator-jazz.ulaw +1 -0
  4. package/assets/keyboard-typing.ulaw +1 -0
  5. package/assets/lofi.ulaw +1 -0
  6. package/assets/ringing.ulaw +1 -0
  7. package/assets/thinking-hum.ulaw +1 -0
  8. package/dist/BackgroundAudioPlayer-iMcivjis.mjs +282 -0
  9. package/dist/BackgroundAudioPlayer-jfRULWKC.cjs +313 -0
  10. package/dist/BaseRealtimeProvider-BQigr5mB.mjs +62 -0
  11. package/dist/BaseRealtimeProvider-BehPNT1r.d.cts +239 -0
  12. package/dist/BaseRealtimeProvider-ClP8Wx1X.d.mts +239 -0
  13. package/dist/BaseRealtimeProvider-DI4pKtOb.cjs +91 -0
  14. package/dist/GeminiLiveProvider-DvkTgzjG.d.cts +101 -0
  15. package/dist/GeminiLiveProvider-x2nyx5aO.d.mts +101 -0
  16. package/dist/InMemorySessionStore-B0_i-DOU.cjs +34 -0
  17. package/dist/InMemorySessionStore-B5_rq61L.d.cts +83 -0
  18. package/dist/InMemorySessionStore-B5_rq61L.d.mts +83 -0
  19. package/dist/InMemorySessionStore-DYParOJO.mjs +29 -0
  20. package/dist/OpenAICompatibleProvider-Bdtl-UXH.mjs +402 -0
  21. package/dist/OpenAICompatibleProvider-NS4cKVQj.cjs +409 -0
  22. package/dist/audio.cjs +21 -0
  23. package/dist/audio.d.cts +165 -0
  24. package/dist/audio.d.mts +165 -0
  25. package/dist/audio.mjs +4 -0
  26. package/dist/env-DSnGaERV.cjs +19 -0
  27. package/dist/env-DUwUWTsg.mjs +14 -0
  28. package/dist/events-BUMYdETO.d.cts +24 -0
  29. package/dist/events-BUMYdETO.d.mts +24 -0
  30. package/dist/events-BxDTIKKq.cjs +48 -0
  31. package/dist/events-BylBSBW-.mjs +43 -0
  32. package/dist/gemini.cjs +401 -0
  33. package/dist/gemini.d.cts +41 -0
  34. package/dist/gemini.d.mts +41 -0
  35. package/dist/gemini.mjs +395 -0
  36. package/dist/index.cjs +2142 -0
  37. package/dist/index.d.cts +920 -0
  38. package/dist/index.d.mts +920 -0
  39. package/dist/index.mjs +2113 -0
  40. package/dist/mulaw--cwU2c9L.mjs +64 -0
  41. package/dist/mulaw-DLUObjdP.cjs +117 -0
  42. package/dist/openai.cjs +61 -0
  43. package/dist/openai.d.cts +121 -0
  44. package/dist/openai.d.mts +121 -0
  45. package/dist/openai.mjs +53 -0
  46. package/dist/presets-Bf75YXs5.d.cts +24 -0
  47. package/dist/presets-Bf75YXs5.d.mts +24 -0
  48. package/dist/rest-BYqiVOhe.mjs +265 -0
  49. package/dist/rest-BvUKut_k.cjs +300 -0
  50. package/dist/rolldown-runtime-VH7oDXx4.cjs +28 -0
  51. package/dist/session-config-BVLl7-ha.mjs +74 -0
  52. package/dist/session-config-c8sOw1XL.cjs +85 -0
  53. package/dist/store.cjs +3 -0
  54. package/dist/store.d.cts +2 -0
  55. package/dist/store.d.mts +2 -0
  56. package/dist/store.mjs +2 -0
  57. package/dist/testing.cjs +544 -0
  58. package/dist/testing.d.cts +191 -0
  59. package/dist/testing.d.mts +191 -0
  60. package/dist/testing.mjs +538 -0
  61. package/dist/transcode-C9aJG7_W.cjs +215 -0
  62. package/dist/transcode-CsAp97G9.mjs +198 -0
  63. package/dist/transport-B_PJFIVd.d.cts +155 -0
  64. package/dist/transport-CEaLFV4E.d.mts +155 -0
  65. package/dist/twilio.cjs +8 -0
  66. package/dist/twilio.d.cts +3 -0
  67. package/dist/twilio.d.mts +3 -0
  68. package/dist/twilio.mjs +2 -0
  69. package/dist/twiml-z9LjoF4_.d.cts +67 -0
  70. package/dist/twiml-z9LjoF4_.d.mts +67 -0
  71. package/dist/xai.cjs +92 -0
  72. package/dist/xai.d.cts +35 -0
  73. package/dist/xai.d.mts +35 -0
  74. package/dist/xai.mjs +86 -0
  75. package/package.json +183 -0
@@ -0,0 +1,191 @@
1
+ import { a as GeminiLiveSessionLike, n as GeminiLiveConnector, t as GeminiConnectParams } from "./GeminiLiveProvider-DvkTgzjG.cjs";
2
+ import { i as WebSocketLike } from "./transport-B_PJFIVd.cjs";
3
+ import { IncomingHttpHeaders } from "node:http";
4
+ import { WebSocket } from "ws";
5
+ //#region src/testing/FakeTwilioMediaStream.d.ts
6
+ type MessageListener = (data: string, isBinary?: boolean) => void;
7
+ type CloseListener = (code?: number, reason?: string) => void;
8
+ type ErrorListener = (error: Error) => void;
9
+ interface FakeConnectOptions {
10
+ callSid?: string;
11
+ streamSid?: string;
12
+ accountSid?: string;
13
+ customParameters?: Record<string, string>;
14
+ /** Send Twilio's `connected` preamble frame before `start`. Default true. */
15
+ sendConnectedFrame?: boolean;
16
+ }
17
+ /** Base64 μ-law silence of the given duration (whole milliseconds at 8 kHz). */
18
+ declare function mulawSilenceBase64(ms: number): string;
19
+ declare class FakeTwilioMediaStream implements WebSocketLike {
20
+ readyState: number;
21
+ readonly callSid: string;
22
+ readonly streamSid: string;
23
+ /** Everything the bridge sent, parsed, in order. */
24
+ readonly outbound: Array<Record<string, any>>;
25
+ /** Base64 payloads of outbound media frames, in order. */
26
+ readonly sentMediaPayloads: string[];
27
+ /** Names of marks echoed back to the bridge (played or discarded). */
28
+ readonly echoedMarks: string[];
29
+ /** Number of `clear` frames received from the bridge. */
30
+ clearCount: number;
31
+ private readonly messageListeners;
32
+ private readonly closeListeners;
33
+ private readonly errorListeners;
34
+ private readonly playoutQueue;
35
+ private playedMsTotal;
36
+ private callerClockMs;
37
+ private mediaSequence;
38
+ private closedByBridge;
39
+ constructor(options?: {
40
+ callSid?: string;
41
+ streamSid?: string;
42
+ });
43
+ send(data: string): void;
44
+ close(code?: number, reason?: string): void;
45
+ on(event: 'message', listener: MessageListener): this;
46
+ on(event: 'close', listener: CloseListener): this;
47
+ on(event: 'error', listener: ErrorListener): this;
48
+ /** Send the `connected` preamble and `start` frame. */
49
+ connect(options?: FakeConnectOptions): void;
50
+ /** Deliver one caller media frame (base64 μ-law) to the bridge. */
51
+ sendMedia(payload: string): void;
52
+ /** Deliver `ms` of caller silence as 20 ms μ-law frames. */
53
+ sendSilence(ms: number): void;
54
+ sendDtmf(digit: string): void;
55
+ /** Deliver the `stop` frame (Twilio ended the stream). */
56
+ stop(): void;
57
+ /** Simulate the socket dropping from Twilio's side. */
58
+ disconnect(code?: number, reason?: string): void;
59
+ /** Total milliseconds of agent audio actually "played" to the caller. */
60
+ get playedMs(): number;
61
+ /** Milliseconds of agent audio still buffered. */
62
+ get queuedMs(): number;
63
+ get wasClosedByBridge(): boolean;
64
+ /**
65
+ * Advance the playout clock: consume buffered media in order and echo each
66
+ * mark as playout reaches it.
67
+ */
68
+ advancePlayback(ms: number): void;
69
+ /** Play out everything currently buffered. */
70
+ playAll(): void;
71
+ private echoMark;
72
+ private deliver;
73
+ }
74
+ //#endregion
75
+ //#region src/testing/FakeOpenAIServer.d.ts
76
+ interface FakeOpenAIServerOptions {
77
+ /** Auto-ack session.update with session.updated. Default true. */
78
+ autoAckSessionUpdate?: boolean;
79
+ }
80
+ interface FakeAudioResponseOptions {
81
+ responseId?: string;
82
+ itemId?: string;
83
+ /** Base64 μ-law chunks to stream as output_audio deltas. */
84
+ chunks: string[];
85
+ transcript?: string;
86
+ usage?: Record<string, unknown>;
87
+ /** Emit response.done after the deltas. Default true. */
88
+ complete?: boolean;
89
+ }
90
+ declare class FakeOpenAIConnection {
91
+ readonly socket: WebSocket;
92
+ /** Every parsed client → server frame, in order. */
93
+ readonly received: Array<Record<string, any>>;
94
+ /** HTTP headers of the client's upgrade request (auth, extensions…). */
95
+ readonly upgradeHeaders: IncomingHttpHeaders;
96
+ private readonly server;
97
+ constructor(server: FakeOpenAIServer, socket: WebSocket, upgradeHeaders?: IncomingHttpHeaders);
98
+ /** Base64 payloads from input_audio_buffer.append frames. */
99
+ get appendedAudio(): string[];
100
+ eventsOfType(type: string): Array<Record<string, any>>;
101
+ waitForEvent(predicate: string | ((frame: Record<string, any>) => boolean), timeoutMs?: number): Promise<Record<string, any>>;
102
+ send(frame: Record<string, unknown>): void;
103
+ /** Script a complete assistant audio response (created → deltas → done). */
104
+ sendAudioResponse(options: FakeAudioResponseOptions): {
105
+ responseId: string;
106
+ itemId: string;
107
+ };
108
+ sendToolCall(options: {
109
+ name: string;
110
+ argumentsJson?: string;
111
+ callId?: string;
112
+ responseId?: string;
113
+ }): string;
114
+ sendSpeechStarted(): void;
115
+ sendSpeechStopped(): void;
116
+ sendUserTranscript(text: string): void;
117
+ sendError(error: Record<string, unknown>): void;
118
+ drop(code?: number, reason?: string): void;
119
+ }
120
+ declare class FakeOpenAIServer {
121
+ readonly connections: FakeOpenAIConnection[];
122
+ private readonly wss;
123
+ private readonly options;
124
+ readonly url: string;
125
+ private constructor();
126
+ static start(options?: FakeOpenAIServerOptions): Promise<FakeOpenAIServer>;
127
+ get latest(): FakeOpenAIConnection;
128
+ waitForConnection(timeoutMs?: number): Promise<FakeOpenAIConnection>;
129
+ close(): Promise<void>;
130
+ }
131
+ //#endregion
132
+ //#region src/testing/FakeGeminiLive.d.ts
133
+ declare class FakeGeminiSession implements GeminiLiveSessionLike {
134
+ readonly params: GeminiConnectParams;
135
+ readonly realtimeInputs: Array<{
136
+ data: string;
137
+ mimeType: string;
138
+ }>;
139
+ readonly clientContents: Array<{
140
+ turns: Array<Record<string, any>>;
141
+ turnComplete?: boolean;
142
+ }>;
143
+ readonly toolResponses: Array<{
144
+ functionResponses: Array<Record<string, any>>;
145
+ }>;
146
+ closed: boolean;
147
+ constructor(params: GeminiConnectParams);
148
+ sendRealtimeInput(input: {
149
+ audio: {
150
+ data: string;
151
+ mimeType: string;
152
+ };
153
+ }): void;
154
+ sendClientContent(content: {
155
+ turns: Array<Record<string, any>>;
156
+ turnComplete?: boolean;
157
+ }): void;
158
+ sendToolResponse(response: {
159
+ functionResponses: Array<Record<string, any>>;
160
+ }): void;
161
+ close(): void;
162
+ serverMessage(message: Record<string, unknown>): void;
163
+ completeSetup(): void;
164
+ /** Stream a model turn: PCM24k audio parts (+ transcript), then turnComplete. */
165
+ sendAudioTurn(options: {
166
+ pcm24kBase64Chunks: string[];
167
+ transcript?: string;
168
+ }): void;
169
+ sendToolCall(options: {
170
+ name: string;
171
+ args?: Record<string, unknown>;
172
+ id?: string;
173
+ }): string;
174
+ sendInterrupted(): void;
175
+ sendInputTranscription(text: string): void;
176
+ sendResumptionUpdate(handle: string): void;
177
+ sendGoAway(timeLeft: string): void;
178
+ sendUsage(usage: Record<string, unknown>): void;
179
+ /** Drop the connection from the server side. */
180
+ drop(code?: number, reason?: string): void;
181
+ }
182
+ declare class FakeGeminiLive {
183
+ readonly sessions: FakeGeminiSession[];
184
+ /** Auto-send setupComplete on connect. Default true. */
185
+ autoCompleteSetup: boolean;
186
+ readonly connector: GeminiLiveConnector;
187
+ get latest(): FakeGeminiSession;
188
+ waitForSessions(count: number, timeoutMs?: number): Promise<FakeGeminiSession>;
189
+ }
190
+ //#endregion
191
+ export { type FakeAudioResponseOptions, type FakeConnectOptions, FakeGeminiLive, FakeGeminiSession, FakeOpenAIConnection, FakeOpenAIServer, type FakeOpenAIServerOptions, FakeTwilioMediaStream, mulawSilenceBase64 };
@@ -0,0 +1,191 @@
1
+ import { a as GeminiLiveSessionLike, n as GeminiLiveConnector, t as GeminiConnectParams } from "./GeminiLiveProvider-x2nyx5aO.mjs";
2
+ import { i as WebSocketLike } from "./transport-CEaLFV4E.mjs";
3
+ import { WebSocket } from "ws";
4
+ import { IncomingHttpHeaders } from "node:http";
5
+ //#region src/testing/FakeTwilioMediaStream.d.ts
6
+ type MessageListener = (data: string, isBinary?: boolean) => void;
7
+ type CloseListener = (code?: number, reason?: string) => void;
8
+ type ErrorListener = (error: Error) => void;
9
+ interface FakeConnectOptions {
10
+ callSid?: string;
11
+ streamSid?: string;
12
+ accountSid?: string;
13
+ customParameters?: Record<string, string>;
14
+ /** Send Twilio's `connected` preamble frame before `start`. Default true. */
15
+ sendConnectedFrame?: boolean;
16
+ }
17
+ /** Base64 μ-law silence of the given duration (whole milliseconds at 8 kHz). */
18
+ declare function mulawSilenceBase64(ms: number): string;
19
+ declare class FakeTwilioMediaStream implements WebSocketLike {
20
+ readyState: number;
21
+ readonly callSid: string;
22
+ readonly streamSid: string;
23
+ /** Everything the bridge sent, parsed, in order. */
24
+ readonly outbound: Array<Record<string, any>>;
25
+ /** Base64 payloads of outbound media frames, in order. */
26
+ readonly sentMediaPayloads: string[];
27
+ /** Names of marks echoed back to the bridge (played or discarded). */
28
+ readonly echoedMarks: string[];
29
+ /** Number of `clear` frames received from the bridge. */
30
+ clearCount: number;
31
+ private readonly messageListeners;
32
+ private readonly closeListeners;
33
+ private readonly errorListeners;
34
+ private readonly playoutQueue;
35
+ private playedMsTotal;
36
+ private callerClockMs;
37
+ private mediaSequence;
38
+ private closedByBridge;
39
+ constructor(options?: {
40
+ callSid?: string;
41
+ streamSid?: string;
42
+ });
43
+ send(data: string): void;
44
+ close(code?: number, reason?: string): void;
45
+ on(event: 'message', listener: MessageListener): this;
46
+ on(event: 'close', listener: CloseListener): this;
47
+ on(event: 'error', listener: ErrorListener): this;
48
+ /** Send the `connected` preamble and `start` frame. */
49
+ connect(options?: FakeConnectOptions): void;
50
+ /** Deliver one caller media frame (base64 μ-law) to the bridge. */
51
+ sendMedia(payload: string): void;
52
+ /** Deliver `ms` of caller silence as 20 ms μ-law frames. */
53
+ sendSilence(ms: number): void;
54
+ sendDtmf(digit: string): void;
55
+ /** Deliver the `stop` frame (Twilio ended the stream). */
56
+ stop(): void;
57
+ /** Simulate the socket dropping from Twilio's side. */
58
+ disconnect(code?: number, reason?: string): void;
59
+ /** Total milliseconds of agent audio actually "played" to the caller. */
60
+ get playedMs(): number;
61
+ /** Milliseconds of agent audio still buffered. */
62
+ get queuedMs(): number;
63
+ get wasClosedByBridge(): boolean;
64
+ /**
65
+ * Advance the playout clock: consume buffered media in order and echo each
66
+ * mark as playout reaches it.
67
+ */
68
+ advancePlayback(ms: number): void;
69
+ /** Play out everything currently buffered. */
70
+ playAll(): void;
71
+ private echoMark;
72
+ private deliver;
73
+ }
74
+ //#endregion
75
+ //#region src/testing/FakeOpenAIServer.d.ts
76
+ interface FakeOpenAIServerOptions {
77
+ /** Auto-ack session.update with session.updated. Default true. */
78
+ autoAckSessionUpdate?: boolean;
79
+ }
80
+ interface FakeAudioResponseOptions {
81
+ responseId?: string;
82
+ itemId?: string;
83
+ /** Base64 μ-law chunks to stream as output_audio deltas. */
84
+ chunks: string[];
85
+ transcript?: string;
86
+ usage?: Record<string, unknown>;
87
+ /** Emit response.done after the deltas. Default true. */
88
+ complete?: boolean;
89
+ }
90
+ declare class FakeOpenAIConnection {
91
+ readonly socket: WebSocket;
92
+ /** Every parsed client → server frame, in order. */
93
+ readonly received: Array<Record<string, any>>;
94
+ /** HTTP headers of the client's upgrade request (auth, extensions…). */
95
+ readonly upgradeHeaders: IncomingHttpHeaders;
96
+ private readonly server;
97
+ constructor(server: FakeOpenAIServer, socket: WebSocket, upgradeHeaders?: IncomingHttpHeaders);
98
+ /** Base64 payloads from input_audio_buffer.append frames. */
99
+ get appendedAudio(): string[];
100
+ eventsOfType(type: string): Array<Record<string, any>>;
101
+ waitForEvent(predicate: string | ((frame: Record<string, any>) => boolean), timeoutMs?: number): Promise<Record<string, any>>;
102
+ send(frame: Record<string, unknown>): void;
103
+ /** Script a complete assistant audio response (created → deltas → done). */
104
+ sendAudioResponse(options: FakeAudioResponseOptions): {
105
+ responseId: string;
106
+ itemId: string;
107
+ };
108
+ sendToolCall(options: {
109
+ name: string;
110
+ argumentsJson?: string;
111
+ callId?: string;
112
+ responseId?: string;
113
+ }): string;
114
+ sendSpeechStarted(): void;
115
+ sendSpeechStopped(): void;
116
+ sendUserTranscript(text: string): void;
117
+ sendError(error: Record<string, unknown>): void;
118
+ drop(code?: number, reason?: string): void;
119
+ }
120
+ declare class FakeOpenAIServer {
121
+ readonly connections: FakeOpenAIConnection[];
122
+ private readonly wss;
123
+ private readonly options;
124
+ readonly url: string;
125
+ private constructor();
126
+ static start(options?: FakeOpenAIServerOptions): Promise<FakeOpenAIServer>;
127
+ get latest(): FakeOpenAIConnection;
128
+ waitForConnection(timeoutMs?: number): Promise<FakeOpenAIConnection>;
129
+ close(): Promise<void>;
130
+ }
131
+ //#endregion
132
+ //#region src/testing/FakeGeminiLive.d.ts
133
+ declare class FakeGeminiSession implements GeminiLiveSessionLike {
134
+ readonly params: GeminiConnectParams;
135
+ readonly realtimeInputs: Array<{
136
+ data: string;
137
+ mimeType: string;
138
+ }>;
139
+ readonly clientContents: Array<{
140
+ turns: Array<Record<string, any>>;
141
+ turnComplete?: boolean;
142
+ }>;
143
+ readonly toolResponses: Array<{
144
+ functionResponses: Array<Record<string, any>>;
145
+ }>;
146
+ closed: boolean;
147
+ constructor(params: GeminiConnectParams);
148
+ sendRealtimeInput(input: {
149
+ audio: {
150
+ data: string;
151
+ mimeType: string;
152
+ };
153
+ }): void;
154
+ sendClientContent(content: {
155
+ turns: Array<Record<string, any>>;
156
+ turnComplete?: boolean;
157
+ }): void;
158
+ sendToolResponse(response: {
159
+ functionResponses: Array<Record<string, any>>;
160
+ }): void;
161
+ close(): void;
162
+ serverMessage(message: Record<string, unknown>): void;
163
+ completeSetup(): void;
164
+ /** Stream a model turn: PCM24k audio parts (+ transcript), then turnComplete. */
165
+ sendAudioTurn(options: {
166
+ pcm24kBase64Chunks: string[];
167
+ transcript?: string;
168
+ }): void;
169
+ sendToolCall(options: {
170
+ name: string;
171
+ args?: Record<string, unknown>;
172
+ id?: string;
173
+ }): string;
174
+ sendInterrupted(): void;
175
+ sendInputTranscription(text: string): void;
176
+ sendResumptionUpdate(handle: string): void;
177
+ sendGoAway(timeLeft: string): void;
178
+ sendUsage(usage: Record<string, unknown>): void;
179
+ /** Drop the connection from the server side. */
180
+ drop(code?: number, reason?: string): void;
181
+ }
182
+ declare class FakeGeminiLive {
183
+ readonly sessions: FakeGeminiSession[];
184
+ /** Auto-send setupComplete on connect. Default true. */
185
+ autoCompleteSetup: boolean;
186
+ readonly connector: GeminiLiveConnector;
187
+ get latest(): FakeGeminiSession;
188
+ waitForSessions(count: number, timeoutMs?: number): Promise<FakeGeminiSession>;
189
+ }
190
+ //#endregion
191
+ export { type FakeAudioResponseOptions, type FakeConnectOptions, FakeGeminiLive, FakeGeminiSession, FakeOpenAIConnection, FakeOpenAIServer, type FakeOpenAIServerOptions, FakeTwilioMediaStream, mulawSilenceBase64 };