@mastra/voice-google-gemini-live 0.0.0-add-libsql-changeset-20250910154739

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.
@@ -0,0 +1,436 @@
1
+ import type { ToolsInput } from '@mastra/core/agent';
2
+ import { MastraVoice } from '@mastra/core/voice';
3
+ import type { VoiceEventType, VoiceConfig } from '@mastra/core/voice';
4
+ import type { GeminiLiveVoiceConfig, GeminiLiveVoiceOptions, GeminiLiveEventMap, GeminiSessionConfig } from './types';
5
+ /**
6
+ * Helper class for consistent error handling
7
+ */
8
+ /**
9
+ * GeminiLiveVoice provides real-time multimodal voice interactions using Google's Gemini Live API.
10
+ *
11
+ * Features:
12
+ * - Bidirectional audio streaming
13
+ * - Built-in VAD and interrupt handling
14
+ * - Tool calling capabilities
15
+ * - Session management and resumption
16
+ * - Live transcription
17
+ * - Support for both Gemini API and Vertex AI
18
+ *
19
+ * @example Backward compatibility - Direct options (legacy)
20
+ * ```typescript
21
+ * const voice = new GeminiLiveVoice({
22
+ * apiKey: 'your-api-key',
23
+ * model: 'gemini-2.0-flash-live-001',
24
+ * speaker: 'Puck',
25
+ * instructions: 'You are a helpful assistant'
26
+ * });
27
+ * ```
28
+ *
29
+ * @example Mastra VoiceConfig pattern - Recommended
30
+ * ```typescript
31
+ * const voice = new GeminiLiveVoice({
32
+ * speechModel: { name: 'gemini-2.0-flash-live-001', apiKey: 'your-api-key' },
33
+ * speaker: 'Puck',
34
+ * realtimeConfig: {
35
+ * model: 'gemini-2.0-flash-live-001',
36
+ * apiKey: 'your-api-key',
37
+ * options: {
38
+ * instructions: 'You are a helpful assistant',
39
+ * debug: true
40
+ * }
41
+ * }
42
+ * });
43
+ * ```
44
+ *
45
+ * @example Using Vertex AI (with OAuth)
46
+ * ```typescript
47
+ * const voice = new GeminiLiveVoice({
48
+ * realtimeConfig: {
49
+ * model: 'gemini-2.0-flash-live-001',
50
+ * options: {
51
+ * vertexAI: true,
52
+ * project: 'your-gcp-project',
53
+ * location: 'us-central1',
54
+ * serviceAccountKeyFile: '/path/to/service-account.json',
55
+ * }
56
+ * }
57
+ * });
58
+ * ```
59
+ */
60
+ export declare class GeminiLiveVoice extends MastraVoice<GeminiLiveVoiceConfig, GeminiLiveVoiceOptions, GeminiLiveVoiceOptions, ToolsInput, GeminiLiveEventMap> {
61
+ private ws?;
62
+ private eventManager;
63
+ private state;
64
+ private sessionHandle?;
65
+ private readonly debug;
66
+ private readonly audioConfig;
67
+ private queue;
68
+ private connectionManager;
69
+ private contextManager;
70
+ private authManager;
71
+ private audioStreamManager;
72
+ private sessionId?;
73
+ private sessionStartTime?;
74
+ private isResuming;
75
+ private sessionDurationTimeout?;
76
+ private tools?;
77
+ private runtimeContext?;
78
+ private options;
79
+ /**
80
+ * Normalize configuration to ensure proper VoiceConfig format
81
+ * Handles backward compatibility with direct GeminiLiveVoiceConfig
82
+ * @private
83
+ */
84
+ private static normalizeConfig;
85
+ /**
86
+ * Creates a new GeminiLiveVoice instance
87
+ *
88
+ * @param config Configuration options
89
+ */
90
+ constructor(config?: VoiceConfig<GeminiLiveVoiceConfig> | GeminiLiveVoiceConfig);
91
+ /**
92
+ * Register an event listener
93
+ * @param event Event name (e.g., 'speaking', 'writing', 'error', 'speaker')
94
+ * @param callback Callback function that receives event data
95
+ *
96
+ * @example
97
+ * ```typescript
98
+ * // Listen for audio responses
99
+ * voice.on('speaking', ({ audio, audioData, sampleRate }) => {
100
+ * console.log('Received audio chunk:', audioData.length);
101
+ * });
102
+ *
103
+ * // Listen for text responses and transcriptions
104
+ * voice.on('writing', ({ text, role }) => {
105
+ * console.log(`${role}: ${text}`);
106
+ * });
107
+ *
108
+ * // Listen for audio streams (for concatenated playback)
109
+ * voice.on('speaker', (audioStream) => {
110
+ * audioStream.pipe(playbackDevice);
111
+ * });
112
+ *
113
+ * // Handle errors
114
+ * voice.on('error', ({ message, code, details }) => {
115
+ * console.error('Voice error:', message);
116
+ * });
117
+ * ```
118
+ */
119
+ on<E extends VoiceEventType>(event: E, callback: (data: E extends keyof GeminiLiveEventMap ? GeminiLiveEventMap[E] : unknown) => void): void;
120
+ /**
121
+ * Remove an event listener
122
+ * @param event Event name
123
+ * @param callback Callback function to remove
124
+ */
125
+ off<E extends VoiceEventType>(event: E, callback: (data: E extends keyof GeminiLiveEventMap ? GeminiLiveEventMap[E] : unknown) => void): void;
126
+ /**
127
+ * Register a one-time event listener that automatically removes itself after the first emission
128
+ * @param event Event name
129
+ * @param callback Callback function that receives event data
130
+ */
131
+ once<E extends VoiceEventType>(event: E, callback: (data: E extends keyof GeminiLiveEventMap ? GeminiLiveEventMap[E] : unknown) => void): void;
132
+ /**
133
+ * Emit an event to listeners with improved error handling
134
+ * @private
135
+ */
136
+ private emit;
137
+ /**
138
+ * Clean up event listeners to prevent memory leaks
139
+ * @private
140
+ */
141
+ private cleanupEventListeners;
142
+ /**
143
+ * Get current event listener information for debugging
144
+ * @returns Object with event names and listener counts
145
+ */
146
+ getEventListenerInfo(): Record<string, number>;
147
+ /**
148
+ * Create and emit a standardized error
149
+ * @private
150
+ */
151
+ private createAndEmitError;
152
+ /**
153
+ * Handle connection state validation with standardized errors
154
+ * @private
155
+ */
156
+ private validateConnectionState;
157
+ /**
158
+ * Handle WebSocket state validation with standardized errors
159
+ * @private
160
+ */
161
+ private validateWebSocketState;
162
+ /**
163
+ * Establish connection to the Gemini Live API
164
+ */
165
+ connect({ runtimeContext }?: {
166
+ runtimeContext?: any;
167
+ }): Promise<void>;
168
+ /**
169
+ * Disconnect from the Gemini Live API
170
+ */
171
+ disconnect(): Promise<void>;
172
+ /**
173
+ * Send text to be converted to speech
174
+ */
175
+ speak(input: string | NodeJS.ReadableStream, options?: GeminiLiveVoiceOptions): Promise<void>;
176
+ /**
177
+ * Send audio stream for processing
178
+ */
179
+ send(audioData: NodeJS.ReadableStream | Int16Array): Promise<void>;
180
+ /**
181
+ * Process speech from audio stream (traditional STT interface)
182
+ */
183
+ listen(audioStream: NodeJS.ReadableStream, _options?: GeminiLiveVoiceOptions): Promise<string>;
184
+ /**
185
+ * Get available speakers/voices
186
+ */
187
+ getSpeakers(): Promise<Array<{
188
+ voiceId: string;
189
+ description?: string;
190
+ }>>;
191
+ /**
192
+ * Resume a previous session using a session handle
193
+ */
194
+ resumeSession(handle: string, context?: Array<{
195
+ role: string;
196
+ content: string;
197
+ }>): Promise<void>;
198
+ /**
199
+ * Update session configuration during an active session
200
+ * Allows dynamic updates to voice, instructions, tools, and other settings
201
+ *
202
+ * @param config Partial configuration to update
203
+ * @throws Error if not connected or update fails
204
+ *
205
+ * @example
206
+ * ```typescript
207
+ * // Change voice during conversation
208
+ * await voice.updateSessionConfig({
209
+ * speaker: 'Charon'
210
+ * });
211
+ *
212
+ * // Update instructions
213
+ * await voice.updateSessionConfig({
214
+ * instructions: 'You are now a helpful coding assistant'
215
+ * });
216
+ *
217
+ * // Add or update tools
218
+ * await voice.updateSessionConfig({
219
+ * tools: [{ name: 'new_tool', ... }]
220
+ * });
221
+ * ```
222
+ */
223
+ updateSessionConfig(config: Partial<GeminiLiveVoiceConfig>): Promise<void>;
224
+ /**
225
+ * Get current connection state
226
+ */
227
+ getConnectionState(): 'disconnected' | 'connected';
228
+ /**
229
+ * Check if currently connected
230
+ */
231
+ isConnected(): boolean;
232
+ /**
233
+ * Get current speaker stream for audio concatenation
234
+ * This allows external access to the current audio stream being built
235
+ */
236
+ getCurrentSpeakerStream(): NodeJS.ReadableStream | null;
237
+ /**
238
+ * Get session handle for resumption
239
+ */
240
+ getSessionHandle(): string | undefined;
241
+ /**
242
+ * Get comprehensive session information
243
+ */
244
+ getSessionInfo(): {
245
+ id?: string;
246
+ handle?: string;
247
+ startTime?: Date;
248
+ duration?: number;
249
+ state: string;
250
+ config?: GeminiSessionConfig;
251
+ contextSize: number;
252
+ };
253
+ /**
254
+ * Get session context history
255
+ */
256
+ getContextHistory(): Array<{
257
+ role: string;
258
+ content: string;
259
+ timestamp: number;
260
+ }>;
261
+ /**
262
+ * Add to context history for session continuity
263
+ */
264
+ addToContext(role: 'user' | 'assistant', content: string): void;
265
+ /**
266
+ * Clear session context
267
+ */
268
+ clearContext(): void;
269
+ /**
270
+ * Enable or disable automatic reconnection
271
+ */
272
+ setAutoReconnect(enabled: boolean): void;
273
+ /**
274
+ * Send session resumption message
275
+ * @private
276
+ */
277
+ private sendSessionResumption;
278
+ /**
279
+ * Start monitoring session duration
280
+ * @private
281
+ */
282
+ private startSessionDurationMonitor;
283
+ /**
284
+ * Parse duration string to milliseconds
285
+ * @private
286
+ */
287
+ private parseDuration;
288
+ /**
289
+ * Compress context history to manage memory
290
+ * @private
291
+ */
292
+ private compressContext;
293
+ /**
294
+ * Setup WebSocket event listeners for Gemini Live API messages
295
+ * @private
296
+ */
297
+ private setupEventListeners;
298
+ /**
299
+ * Handle different types of messages from Gemini Live API
300
+ * @private
301
+ */
302
+ private handleGeminiMessage;
303
+ /**
304
+ * Handle setup completion message
305
+ * @private
306
+ */
307
+ private handleSetupComplete;
308
+ /**
309
+ * Handle session update confirmation
310
+ * @private
311
+ */
312
+ private handleSessionUpdated;
313
+ /**
314
+ * Handle server content (text/audio responses)
315
+ * @private
316
+ */
317
+ private handleServerContent;
318
+ /**
319
+ * Handle tool call requests from the model
320
+ * @private
321
+ */
322
+ private handleToolCall;
323
+ /**
324
+ * Handle token usage information
325
+ * @private
326
+ */
327
+ private handleUsageUpdate;
328
+ /**
329
+ * Handle session end
330
+ * @private
331
+ */
332
+ private handleSessionEnd;
333
+ /**
334
+ * Handle errors
335
+ * @private
336
+ */
337
+ private handleError;
338
+ /**
339
+ * Determine the modality from message data
340
+ * @private
341
+ */
342
+ private determineModality;
343
+ /**
344
+ * Send initial configuration to Gemini Live API
345
+ * @private
346
+ */
347
+ private sendInitialConfig;
348
+ /**
349
+ * Wait for Gemini Live session to be created and ready
350
+ * @private
351
+ */
352
+ private waitForSessionCreated;
353
+ /**
354
+ * Get OAuth access token for Vertex AI authentication
355
+ * Implements token caching and automatic refresh
356
+ * @private
357
+ */
358
+ private getAccessToken;
359
+ /**
360
+ * Get the current response ID from the server message
361
+ * This is needed to associate audio chunks with their respective responses.
362
+ * @private
363
+ */
364
+ private getCurrentResponseId;
365
+ /**
366
+ * Set the current response ID for the next audio chunk.
367
+ * This is used to track the response ID for the current turn.
368
+ * @private
369
+ */
370
+ private setCurrentResponseId;
371
+ /**
372
+ * Send an event to the Gemini Live API with queueing support
373
+ * @private
374
+ */
375
+ private sendEvent;
376
+ /**
377
+ * Equip the voice provider with tools
378
+ * @param tools Object containing tool definitions that can be called by the voice model
379
+ *
380
+ * @example
381
+ * ```typescript
382
+ * const weatherTool = createTool({
383
+ * id: "getWeather",
384
+ * description: "Get the current weather for a location",
385
+ * inputSchema: z.object({
386
+ * location: z.string().describe("The city and state, e.g. San Francisco, CA"),
387
+ * }),
388
+ * execute: async ({ context }) => {
389
+ * // Fetch weather data from an API
390
+ * const response = await fetch(
391
+ * `https://api.weather.com?location=${encodeURIComponent(context.location)}`,
392
+ * );
393
+ * const data = await response.json();
394
+ * return {
395
+ * message: `The current temperature in ${context.location} is ${data.temperature}°F with ${data.conditions}.`,
396
+ * };
397
+ * },
398
+ * });
399
+ *
400
+ * voice.addTools({
401
+ * getWeather: weatherTool,
402
+ * });
403
+ * ```
404
+ */
405
+ addTools(tools: ToolsInput): void;
406
+ /**
407
+ * Get the current tools configured for this voice instance
408
+ * @returns Object containing the current tools
409
+ */
410
+ getTools(): ToolsInput | undefined;
411
+ private log;
412
+ /**
413
+ * Convert Zod schema to JSON Schema for tool parameters
414
+ * @private
415
+ */
416
+ private convertZodSchemaToJsonSchema;
417
+ /**
418
+ * Convert Zod definition to JSON Schema
419
+ * @private
420
+ */
421
+ private convertZodDefToJsonSchema;
422
+ /**
423
+ * Close the connection (alias for disconnect)
424
+ */
425
+ close(): void;
426
+ /**
427
+ * Trigger voice provider to respond
428
+ */
429
+ answer(_options?: Record<string, unknown>): Promise<void>;
430
+ /**
431
+ * Equip the voice provider with instructions
432
+ * @param instructions Instructions to add
433
+ */
434
+ addInstructions(instructions?: string): void;
435
+ }
436
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}