@mastra/voice-google 0.14.0 → 0.14.1

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/dist/index.cjs CHANGED
@@ -1,544 +1,560 @@
1
- 'use strict';
2
-
3
- var stream = require('stream');
4
- var speech = require('@google-cloud/speech');
5
- var textToSpeech = require('@google-cloud/text-to-speech');
6
-
7
- // src/index.ts
8
-
9
- // ../../packages/_internal-core/dist/chunk-3M4SEWMI.js
10
- var RegisteredLogger = {
11
- LLM: "LLM"};
12
- var LogLevel = {
13
- DEBUG: "debug",
14
- INFO: "info",
15
- WARN: "warn",
16
- ERROR: "error"};
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ let stream = require("stream");
3
+ let _google_cloud_speech = require("@google-cloud/speech");
4
+ let _google_cloud_text_to_speech = require("@google-cloud/text-to-speech");
5
+ //#region ../../packages/_internal-core/dist/logger/index.js
6
+ const RegisteredLogger = {
7
+ AGENT: "AGENT",
8
+ OBSERVABILITY: "OBSERVABILITY",
9
+ AUTH: "AUTH",
10
+ BROWSER: "BROWSER",
11
+ NETWORK: "NETWORK",
12
+ WORKFLOW: "WORKFLOW",
13
+ LLM: "LLM",
14
+ TTS: "TTS",
15
+ VOICE: "VOICE",
16
+ VECTOR: "VECTOR",
17
+ BUNDLER: "BUNDLER",
18
+ DEPLOYER: "DEPLOYER",
19
+ MEMORY: "MEMORY",
20
+ STORAGE: "STORAGE",
21
+ EMBEDDINGS: "EMBEDDINGS",
22
+ MCP_SERVER: "MCP_SERVER",
23
+ SERVER_CACHE: "SERVER_CACHE",
24
+ SERVER: "SERVER",
25
+ WORKSPACE: "WORKSPACE",
26
+ CHANNEL: "CHANNEL"
27
+ };
28
+ const LogLevel = {
29
+ DEBUG: "debug",
30
+ INFO: "info",
31
+ WARN: "warn",
32
+ ERROR: "error",
33
+ NONE: "silent"
34
+ };
17
35
  var MastraLogger = class {
18
- name;
19
- level;
20
- transports;
21
- constructor(options = {}) {
22
- this.name = options.name || "Mastra";
23
- this.level = options.level || LogLevel.ERROR;
24
- this.transports = new Map(Object.entries(options.transports || {}));
25
- }
26
- getTransports() {
27
- return this.transports;
28
- }
29
- trackException(_error, _metadata) {
30
- }
31
- async listLogs(transportId, params) {
32
- if (!transportId || !this.transports.has(transportId)) {
33
- return { logs: [], total: 0, page: params?.page ?? 1, perPage: params?.perPage ?? 100, hasMore: false };
34
- }
35
- return this.transports.get(transportId).listLogs?.(params) ?? {
36
- logs: [],
37
- total: 0,
38
- page: params?.page ?? 1,
39
- perPage: params?.perPage ?? 100,
40
- hasMore: false
41
- };
42
- }
43
- async listLogsByRunId({
44
- transportId,
45
- runId,
46
- fromDate,
47
- toDate,
48
- logLevel,
49
- filters,
50
- page,
51
- perPage
52
- }) {
53
- if (!transportId || !this.transports.has(transportId) || !runId) {
54
- return { logs: [], total: 0, page: page ?? 1, perPage: perPage ?? 100, hasMore: false };
55
- }
56
- return this.transports.get(transportId).listLogsByRunId?.({ runId, fromDate, toDate, logLevel, filters, page, perPage }) ?? {
57
- logs: [],
58
- total: 0,
59
- page: page ?? 1,
60
- perPage: perPage ?? 100,
61
- hasMore: false
62
- };
63
- }
36
+ name;
37
+ level;
38
+ transports;
39
+ constructor(options = {}) {
40
+ this.name = options.name || "Mastra";
41
+ this.level = options.level || LogLevel.ERROR;
42
+ this.transports = new Map(Object.entries(options.transports || {}));
43
+ }
44
+ getTransports() {
45
+ return this.transports;
46
+ }
47
+ trackException(_error, _metadata) {}
48
+ async listLogs(transportId, params) {
49
+ if (!transportId || !this.transports.has(transportId)) return {
50
+ logs: [],
51
+ total: 0,
52
+ page: params?.page ?? 1,
53
+ perPage: params?.perPage ?? 100,
54
+ hasMore: false
55
+ };
56
+ return this.transports.get(transportId).listLogs?.(params) ?? {
57
+ logs: [],
58
+ total: 0,
59
+ page: params?.page ?? 1,
60
+ perPage: params?.perPage ?? 100,
61
+ hasMore: false
62
+ };
63
+ }
64
+ async listLogsByRunId({ transportId, runId, fromDate, toDate, logLevel, filters, page, perPage }) {
65
+ if (!transportId || !this.transports.has(transportId) || !runId) return {
66
+ logs: [],
67
+ total: 0,
68
+ page: page ?? 1,
69
+ perPage: perPage ?? 100,
70
+ hasMore: false
71
+ };
72
+ return this.transports.get(transportId).listLogsByRunId?.({
73
+ runId,
74
+ fromDate,
75
+ toDate,
76
+ logLevel,
77
+ filters,
78
+ page,
79
+ perPage
80
+ }) ?? {
81
+ logs: [],
82
+ total: 0,
83
+ page: page ?? 1,
84
+ perPage: perPage ?? 100,
85
+ hasMore: false
86
+ };
87
+ }
64
88
  };
65
- var ConsoleLogger = class _ConsoleLogger extends MastraLogger {
66
- component;
67
- filter;
68
- constructor(options = {}) {
69
- super(options);
70
- this.component = options.component;
71
- this.filter = options.filter;
72
- }
73
- child(componentOrBindings) {
74
- const component = typeof componentOrBindings === "string" ? componentOrBindings : componentOrBindings?.component ?? this.component;
75
- return new _ConsoleLogger({
76
- name: this.name,
77
- level: this.level,
78
- component,
79
- filter: this.filter
80
- });
81
- }
82
- shouldLog(level, message, args) {
83
- if (!this.filter) return true;
84
- try {
85
- return this.filter({ component: this.component, level, message, args });
86
- } catch (e) {
87
- console.error(`[Logger] Filter error for component=${this.component} level=${level}:`, e);
88
- return true;
89
- }
90
- }
91
- prefix() {
92
- return this.component ? `[${this.component}] ` : "";
93
- }
94
- debug(message, ...args) {
95
- if (this.level === LogLevel.DEBUG && this.shouldLog(LogLevel.DEBUG, message, args)) {
96
- console.info(`${this.prefix()}${message}`, ...args);
97
- }
98
- }
99
- info(message, ...args) {
100
- if ((this.level === LogLevel.INFO || this.level === LogLevel.DEBUG) && this.shouldLog(LogLevel.INFO, message, args)) {
101
- console.info(`${this.prefix()}${message}`, ...args);
102
- }
103
- }
104
- warn(message, ...args) {
105
- if ((this.level === LogLevel.WARN || this.level === LogLevel.INFO || this.level === LogLevel.DEBUG) && this.shouldLog(LogLevel.WARN, message, args)) {
106
- console.warn(`${this.prefix()}${message}`, ...args);
107
- }
108
- }
109
- error(message, ...args) {
110
- if ((this.level === LogLevel.ERROR || this.level === LogLevel.WARN || this.level === LogLevel.INFO || this.level === LogLevel.DEBUG) && this.shouldLog(LogLevel.ERROR, message, args)) {
111
- console.error(`${this.prefix()}${message}`, ...args);
112
- }
113
- }
114
- async listLogs(_transportId, _params) {
115
- return { logs: [], total: 0, page: _params?.page ?? 1, perPage: _params?.perPage ?? 100, hasMore: false };
116
- }
117
- async listLogsByRunId(_args) {
118
- return { logs: [], total: 0, page: _args.page ?? 1, perPage: _args.perPage ?? 100, hasMore: false };
119
- }
89
+ var ConsoleLogger = class ConsoleLogger extends MastraLogger {
90
+ component;
91
+ filter;
92
+ constructor(options = {}) {
93
+ super(options);
94
+ this.component = options.component;
95
+ this.filter = options.filter;
96
+ }
97
+ child(componentOrBindings) {
98
+ const component = typeof componentOrBindings === "string" ? componentOrBindings : componentOrBindings?.component ?? this.component;
99
+ return new ConsoleLogger({
100
+ name: this.name,
101
+ level: this.level,
102
+ component,
103
+ filter: this.filter
104
+ });
105
+ }
106
+ shouldLog(level, message, args) {
107
+ if (!this.filter) return true;
108
+ try {
109
+ return this.filter({
110
+ component: this.component,
111
+ level,
112
+ message,
113
+ args
114
+ });
115
+ } catch (e) {
116
+ console.error(`[Logger] Filter error for component=${this.component} level=${level}:`, e);
117
+ return true;
118
+ }
119
+ }
120
+ prefix() {
121
+ return this.component ? `[${this.component}] ` : "";
122
+ }
123
+ debug(message, ...args) {
124
+ if (this.level === LogLevel.DEBUG && this.shouldLog(LogLevel.DEBUG, message, args)) console.info(`${this.prefix()}${message}`, ...args);
125
+ }
126
+ info(message, ...args) {
127
+ if ((this.level === LogLevel.INFO || this.level === LogLevel.DEBUG) && this.shouldLog(LogLevel.INFO, message, args)) console.info(`${this.prefix()}${message}`, ...args);
128
+ }
129
+ warn(message, ...args) {
130
+ if ((this.level === LogLevel.WARN || this.level === LogLevel.INFO || this.level === LogLevel.DEBUG) && this.shouldLog(LogLevel.WARN, message, args)) console.warn(`${this.prefix()}${message}`, ...args);
131
+ }
132
+ error(message, ...args) {
133
+ if ((this.level === LogLevel.ERROR || this.level === LogLevel.WARN || this.level === LogLevel.INFO || this.level === LogLevel.DEBUG) && this.shouldLog(LogLevel.ERROR, message, args)) console.error(`${this.prefix()}${message}`, ...args);
134
+ }
135
+ async listLogs(_transportId, _params) {
136
+ return {
137
+ logs: [],
138
+ total: 0,
139
+ page: _params?.page ?? 1,
140
+ perPage: _params?.perPage ?? 100,
141
+ hasMore: false
142
+ };
143
+ }
144
+ async listLogsByRunId(_args) {
145
+ return {
146
+ logs: [],
147
+ total: 0,
148
+ page: _args.page ?? 1,
149
+ perPage: _args.perPage ?? 100,
150
+ hasMore: false
151
+ };
152
+ }
120
153
  };
121
-
122
- // ../../packages/_internal-core/dist/base/index.js
154
+ //#endregion
155
+ //#region ../../packages/_internal-core/dist/base/index.js
123
156
  var MastraBase = class {
124
- component = RegisteredLogger.LLM;
125
- logger;
126
- name;
127
- #rawConfig;
128
- constructor({
129
- component,
130
- name,
131
- rawConfig
132
- }) {
133
- this.component = component || RegisteredLogger.LLM;
134
- this.name = name;
135
- this.#rawConfig = rawConfig;
136
- this.logger = new ConsoleLogger({ name: `${this.component} - ${this.name}` });
137
- }
138
- /**
139
- * Returns the raw storage configuration this primitive was created from,
140
- * or undefined if it was created from code.
141
- */
142
- toRawConfig() {
143
- return this.#rawConfig;
144
- }
145
- /**
146
- * Sets the raw storage configuration for this primitive.
147
- * @internal
148
- */
149
- __setRawConfig(rawConfig) {
150
- this.#rawConfig = rawConfig;
151
- }
152
- /**
153
- * Set the logger for the agent
154
- * @param logger
155
- */
156
- __setLogger(logger) {
157
- this.logger = "child" in logger && typeof logger.child === "function" ? logger.child({ component: this.component }) : logger;
158
- }
157
+ component = RegisteredLogger.LLM;
158
+ logger;
159
+ name;
160
+ #rawConfig;
161
+ constructor({ component, name, rawConfig }) {
162
+ this.component = component || RegisteredLogger.LLM;
163
+ this.name = name;
164
+ this.#rawConfig = rawConfig;
165
+ this.logger = new ConsoleLogger({ name: `${this.component} - ${this.name}` });
166
+ }
167
+ /**
168
+ * Returns the raw storage configuration this primitive was created from,
169
+ * or undefined if it was created from code.
170
+ */
171
+ toRawConfig() {
172
+ return this.#rawConfig;
173
+ }
174
+ /**
175
+ * Sets the raw storage configuration for this primitive.
176
+ * @internal
177
+ */
178
+ __setRawConfig(rawConfig) {
179
+ this.#rawConfig = rawConfig;
180
+ }
181
+ /**
182
+ * Set the logger for the agent
183
+ * @param logger
184
+ */
185
+ __setLogger(logger) {
186
+ this.logger = "child" in logger && typeof logger.child === "function" ? logger.child({ component: this.component }) : logger;
187
+ }
159
188
  };
160
-
161
- // ../../packages/_internals/voice/dist/chunk-NWNKSBZV.js
189
+ //#endregion
190
+ //#region ../../packages/_internals/voice/dist/aisdk-C_K-VCwq.js
162
191
  var MastraVoice = class extends MastraBase {
163
- listeningModel;
164
- speechModel;
165
- speaker;
166
- realtimeConfig;
167
- constructor({ listeningModel, speechModel, speaker, realtimeConfig, name } = {}) {
168
- super({
169
- component: "VOICE",
170
- name
171
- });
172
- this.listeningModel = listeningModel;
173
- this.speechModel = speechModel;
174
- this.speaker = speaker;
175
- this.realtimeConfig = realtimeConfig;
176
- }
177
- /**
178
- * Custom serialization for tracing/observability spans.
179
- * Excludes `apiKey` from listeningModel / speechModel / realtimeConfig
180
- * and any provider-specific state held by subclasses. Subclasses that
181
- * need to expose additional non-sensitive fields can override.
182
- */
183
- serializeForSpan() {
184
- return {
185
- component: "VOICE",
186
- name: this.name,
187
- speaker: this.speaker,
188
- listeningModel: this.listeningModel ? { name: this.listeningModel.name } : void 0,
189
- speechModel: this.speechModel ? { name: this.speechModel.name } : void 0,
190
- realtimeModel: this.realtimeConfig?.model
191
- };
192
- }
193
- updateConfig(_options) {
194
- this.logger.debug("updateConfig not implemented by this voice provider");
195
- }
196
- /**
197
- * Initializes a WebSocket or WebRTC connection for real-time communication
198
- * @returns Promise that resolves when the connection is established
199
- */
200
- async connect(_options) {
201
- this.logger.debug("connect not implemented by this voice provider");
202
- }
203
- /**
204
- * Relay audio data to the voice provider for real-time processing
205
- * @param audioData Audio data to relay
206
- */
207
- async send(_audioData) {
208
- this.logger.debug("relay not implemented by this voice provider");
209
- }
210
- /**
211
- * Trigger voice providers to respond
212
- */
213
- async answer(_options) {
214
- this.logger.debug("answer not implemented by this voice provider");
215
- }
216
- /**
217
- * Equip the voice provider with instructions
218
- * @param instructions Instructions to add
219
- */
220
- addInstructions(_instructions) {
221
- }
222
- /**
223
- * Equip the voice provider with tools
224
- * @param tools Array of tools to add
225
- */
226
- addTools(_tools) {
227
- }
228
- /**
229
- * Disconnect from the WebSocket or WebRTC connection
230
- */
231
- close() {
232
- this.logger.debug("close not implemented by this voice provider");
233
- }
234
- /**
235
- * Register an event listener
236
- * @param event Event name (e.g., 'speaking', 'writing', 'error')
237
- * @param callback Callback function that receives event data
238
- */
239
- on(_event, _callback) {
240
- this.logger.debug("on not implemented by this voice provider");
241
- }
242
- /**
243
- * Remove an event listener
244
- * @param event Event name (e.g., 'speaking', 'writing', 'error')
245
- * @param callback Callback function to remove
246
- */
247
- off(_event, _callback) {
248
- this.logger.debug("off not implemented by this voice provider");
249
- }
250
- /**
251
- * Get available speakers/voices
252
- * @returns Array of available voice IDs and their metadata
253
- */
254
- getSpeakers() {
255
- this.logger.debug("getSpeakers not implemented by this voice provider");
256
- return Promise.resolve([]);
257
- }
258
- /**
259
- * Get available speakers/voices
260
- * @returns Array of available voice IDs and their metadata
261
- */
262
- getListener() {
263
- this.logger.debug("getListener not implemented by this voice provider");
264
- return Promise.resolve({ enabled: false });
265
- }
192
+ listeningModel;
193
+ speechModel;
194
+ speaker;
195
+ realtimeConfig;
196
+ constructor({ listeningModel, speechModel, speaker, realtimeConfig, name } = {}) {
197
+ super({
198
+ component: "VOICE",
199
+ name
200
+ });
201
+ this.listeningModel = listeningModel;
202
+ this.speechModel = speechModel;
203
+ this.speaker = speaker;
204
+ this.realtimeConfig = realtimeConfig;
205
+ }
206
+ /**
207
+ * Custom serialization for tracing/observability spans.
208
+ * Excludes `apiKey` from listeningModel / speechModel / realtimeConfig
209
+ * and any provider-specific state held by subclasses. Subclasses that
210
+ * need to expose additional non-sensitive fields can override.
211
+ */
212
+ serializeForSpan() {
213
+ return {
214
+ component: "VOICE",
215
+ name: this.name,
216
+ speaker: this.speaker,
217
+ listeningModel: this.listeningModel ? { name: this.listeningModel.name } : void 0,
218
+ speechModel: this.speechModel ? { name: this.speechModel.name } : void 0,
219
+ realtimeModel: this.realtimeConfig?.model
220
+ };
221
+ }
222
+ updateConfig(_options) {
223
+ this.logger.debug("updateConfig not implemented by this voice provider");
224
+ }
225
+ /**
226
+ * Initializes a WebSocket or WebRTC connection for real-time communication
227
+ * @returns Promise that resolves when the connection is established
228
+ */
229
+ async connect(_options) {
230
+ this.logger.debug("connect not implemented by this voice provider");
231
+ }
232
+ /**
233
+ * Relay audio data to the voice provider for real-time processing
234
+ * @param audioData Audio data to relay
235
+ */
236
+ async send(_audioData) {
237
+ this.logger.debug("relay not implemented by this voice provider");
238
+ }
239
+ /**
240
+ * Trigger voice providers to respond
241
+ */
242
+ async answer(_options) {
243
+ this.logger.debug("answer not implemented by this voice provider");
244
+ }
245
+ /**
246
+ * Equip the voice provider with instructions
247
+ * @param instructions Instructions to add
248
+ */
249
+ addInstructions(_instructions) {}
250
+ /**
251
+ * Equip the voice provider with tools
252
+ * @param tools Array of tools to add
253
+ */
254
+ addTools(_tools) {}
255
+ /**
256
+ * Disconnect from the WebSocket or WebRTC connection
257
+ */
258
+ close() {
259
+ this.logger.debug("close not implemented by this voice provider");
260
+ }
261
+ /**
262
+ * Register an event listener
263
+ * @param event Event name (e.g., 'speaking', 'writing', 'error')
264
+ * @param callback Callback function that receives event data
265
+ */
266
+ on(_event, _callback) {
267
+ this.logger.debug("on not implemented by this voice provider");
268
+ }
269
+ /**
270
+ * Remove an event listener
271
+ * @param event Event name (e.g., 'speaking', 'writing', 'error')
272
+ * @param callback Callback function to remove
273
+ */
274
+ off(_event, _callback) {
275
+ this.logger.debug("off not implemented by this voice provider");
276
+ }
277
+ /**
278
+ * Get available speakers/voices
279
+ * @returns Array of available voice IDs and their metadata
280
+ */
281
+ getSpeakers() {
282
+ this.logger.debug("getSpeakers not implemented by this voice provider");
283
+ return Promise.resolve([]);
284
+ }
285
+ /**
286
+ * Get available speakers/voices
287
+ * @returns Array of available voice IDs and their metadata
288
+ */
289
+ getListener() {
290
+ this.logger.debug("getListener not implemented by this voice provider");
291
+ return Promise.resolve({ enabled: false });
292
+ }
266
293
  };
267
-
268
- // src/index.ts
269
- var resolveAuthConfig = (modelConfig, fallback, vertexConfig) => {
270
- const resolved = {};
271
- if (vertexConfig?.vertexAI) {
272
- const projectId = vertexConfig.project || process.env.GOOGLE_CLOUD_PROJECT;
273
- if (projectId) {
274
- resolved.projectId = projectId;
275
- }
276
- }
277
- const apiKey = modelConfig?.apiKey ?? fallback.apiKey;
278
- if (apiKey && !vertexConfig?.vertexAI) {
279
- resolved.apiKey = apiKey;
280
- }
281
- const keyFilename = modelConfig?.keyFilename ?? fallback.keyFilename;
282
- if (keyFilename) {
283
- resolved.keyFilename = keyFilename;
284
- }
285
- const credentials = modelConfig?.credentials ?? fallback.credentials;
286
- if (credentials) {
287
- resolved.credentials = credentials;
288
- }
289
- return resolved;
294
+ //#endregion
295
+ //#region src/index.ts
296
+ const resolveAuthConfig = (modelConfig, fallback, vertexConfig) => {
297
+ const resolved = {};
298
+ if (vertexConfig?.vertexAI) {
299
+ const projectId = vertexConfig.project || process.env.GOOGLE_CLOUD_PROJECT;
300
+ if (projectId) resolved.projectId = projectId;
301
+ }
302
+ const apiKey = modelConfig?.apiKey ?? fallback.apiKey;
303
+ if (apiKey && !vertexConfig?.vertexAI) resolved.apiKey = apiKey;
304
+ const keyFilename = modelConfig?.keyFilename ?? fallback.keyFilename;
305
+ if (keyFilename) resolved.keyFilename = keyFilename;
306
+ const credentials = modelConfig?.credentials ?? fallback.credentials;
307
+ if (credentials) resolved.credentials = credentials;
308
+ return resolved;
290
309
  };
291
- var buildAuthOptions = (config, vertexConfig) => {
292
- const options = {};
293
- if (config.credentials) {
294
- options.credentials = config.credentials;
295
- }
296
- if (config.keyFilename) {
297
- options.keyFilename = config.keyFilename;
298
- }
299
- if (config.apiKey && !vertexConfig?.vertexAI) {
300
- options.apiKey = config.apiKey;
301
- }
302
- if (config.projectId) {
303
- options.projectId = config.projectId;
304
- }
305
- return options;
310
+ const buildAuthOptions = (config, vertexConfig) => {
311
+ const options = {};
312
+ if (config.credentials) options.credentials = config.credentials;
313
+ if (config.keyFilename) options.keyFilename = config.keyFilename;
314
+ if (config.apiKey && !vertexConfig?.vertexAI) options.apiKey = config.apiKey;
315
+ if (config.projectId) options.projectId = config.projectId;
316
+ return options;
306
317
  };
307
- var DEFAULT_VOICE = "en-US-Casual-K";
318
+ const DEFAULT_VOICE = "en-US-Casual-K";
319
+ /**
320
+ * GoogleVoice class provides Text-to-Speech and Speech-to-Text capabilities using Google Cloud services.
321
+ * Supports both standard Google Cloud API authentication and Vertex AI mode for enterprise deployments.
322
+ *
323
+ * @class GoogleVoice
324
+ * @extends MastraVoice
325
+ *
326
+ * @example Standard usage with API key
327
+ * ```typescript
328
+ * const voice = new GoogleVoice({
329
+ * speechModel: { apiKey: 'your-api-key' },
330
+ * speaker: 'en-US-Studio-O',
331
+ * });
332
+ * ```
333
+ *
334
+ * @example Vertex AI mode (recommended for production)
335
+ * ```typescript
336
+ * const voice = new GoogleVoice({
337
+ * vertexAI: true,
338
+ * project: 'your-gcp-project',
339
+ * location: 'us-central1',
340
+ * speaker: 'en-US-Studio-O',
341
+ * });
342
+ * ```
343
+ *
344
+ * @example Vertex AI with service account
345
+ * ```typescript
346
+ * const voice = new GoogleVoice({
347
+ * vertexAI: true,
348
+ * project: 'your-gcp-project',
349
+ * speechModel: {
350
+ * keyFilename: '/path/to/service-account.json',
351
+ * },
352
+ * });
353
+ * ```
354
+ */
308
355
  var GoogleVoice = class extends MastraVoice {
309
- ttsClient;
310
- speechClient;
311
- speechClientV2;
312
- speechOptionsV2;
313
- vertexAI;
314
- project;
315
- location;
316
- /**
317
- * Creates an instance of GoogleVoice
318
- * @param {GoogleVoiceConfig} config - Configuration options
319
- * @param {GoogleModelConfig} [config.speechModel] - Configuration for speech synthesis
320
- * @param {GoogleModelConfig} [config.listeningModel] - Configuration for speech recognition
321
- * @param {string} [config.speaker] - Default voice ID to use for speech synthesis
322
- * @param {boolean} [config.vertexAI] - Enable Vertex AI mode
323
- * @param {string} [config.project] - Google Cloud project ID (required for Vertex AI)
324
- * @param {string} [config.location] - Google Cloud region (default: 'us-central1')
325
- */
326
- constructor({ listeningModel, speechModel, speaker, vertexAI = false, project, location } = {}) {
327
- const defaultApiKey = process.env.GOOGLE_API_KEY;
328
- const defaultKeyFilename = process.env.GOOGLE_APPLICATION_CREDENTIALS;
329
- const defaultSpeaker = DEFAULT_VOICE;
330
- const resolvedProject = project || process.env.GOOGLE_CLOUD_PROJECT;
331
- const resolvedLocation = location || process.env.GOOGLE_CLOUD_LOCATION || "us-central1";
332
- if (vertexAI && !resolvedProject) {
333
- throw new Error(
334
- "Google Cloud project ID is required when using Vertex AI. Set GOOGLE_CLOUD_PROJECT environment variable or pass project to constructor."
335
- );
336
- }
337
- const vertexConfig = { vertexAI, project: resolvedProject };
338
- const sharedFallback = {
339
- apiKey: defaultApiKey ?? speechModel?.apiKey ?? listeningModel?.apiKey,
340
- keyFilename: defaultKeyFilename ?? speechModel?.keyFilename ?? listeningModel?.keyFilename,
341
- credentials: speechModel?.credentials ?? listeningModel?.credentials};
342
- const speechAuthConfig = resolveAuthConfig(speechModel, sharedFallback, vertexConfig);
343
- const listeningAuthConfig = resolveAuthConfig(listeningModel, sharedFallback, vertexConfig);
344
- super({
345
- speechModel: {
346
- name: "",
347
- apiKey: speechAuthConfig.apiKey ?? defaultApiKey
348
- },
349
- listeningModel: {
350
- name: "",
351
- apiKey: listeningAuthConfig.apiKey ?? defaultApiKey
352
- },
353
- speaker: speaker ?? defaultSpeaker
354
- });
355
- this.vertexAI = vertexAI;
356
- this.project = resolvedProject;
357
- this.location = resolvedLocation;
358
- const ttsOptions = buildAuthOptions(speechAuthConfig, { vertexAI});
359
- const speechOptions = buildAuthOptions(listeningAuthConfig, { vertexAI});
360
- this.ttsClient = new textToSpeech.TextToSpeechClient(ttsOptions);
361
- this.speechClient = new speech.SpeechClient(speechOptions);
362
- this.speechOptionsV2 = speechOptions;
363
- }
364
- getV2SpeechClient() {
365
- if (!this.speechClientV2) {
366
- this.speechClientV2 = new speech.v2.SpeechClient(this.speechOptionsV2);
367
- }
368
- return this.speechClientV2;
369
- }
370
- /**
371
- * Check if Vertex AI mode is enabled
372
- * @returns {boolean} True if using Vertex AI
373
- */
374
- isUsingVertexAI() {
375
- return this.vertexAI;
376
- }
377
- /**
378
- * Get the configured Google Cloud project ID
379
- * @returns {string | undefined} The project ID or undefined if not set
380
- */
381
- getProject() {
382
- return this.project;
383
- }
384
- /**
385
- * Get the configured Google Cloud location/region
386
- * @returns {string} The location (default: 'us-central1')
387
- */
388
- getLocation() {
389
- return this.location;
390
- }
391
- /**
392
- * Gets a list of available voices
393
- * @returns {Promise<Array<{voiceId: string, languageCodes: string[]}>>} List of available voices and their supported languages. Default language is en-US.
394
- */
395
- async getSpeakers({ languageCode = "en-US" } = {}) {
396
- const [response] = await this.ttsClient.listVoices({ languageCode });
397
- return (response?.voices || []).filter((voice) => voice.name && voice.languageCodes).map((voice) => ({
398
- voiceId: voice.name,
399
- languageCodes: voice.languageCodes
400
- }));
401
- }
402
- async streamToString(stream) {
403
- const chunks = [];
404
- for await (const chunk of stream) {
405
- if (typeof chunk === "string") {
406
- chunks.push(Buffer.from(chunk));
407
- } else {
408
- chunks.push(chunk);
409
- }
410
- }
411
- return Buffer.concat(chunks).toString("utf-8");
412
- }
413
- /**
414
- * Converts text to speech.
415
- *
416
- * When `input` is a string or stream, builds a text-only request (existing behaviour).
417
- * Pass `options.input` to send richer proto fields (ssml, markup, prompt,
418
- * customPronunciations, multiSpeakerMarkup) and `options.voice` for fields
419
- * like modelName or multiSpeakerVoiceConfig.
420
- *
421
- * @param {string | NodeJS.ReadableStream} input - Text or stream to convert to speech
422
- * @param {GoogleSpeakOptions} [options] - Speech synthesis options
423
- * @returns {Promise<NodeJS.ReadableStream>} Stream of synthesised audio. Default encoding is LINEAR16.
424
- */
425
- async speak(input, options) {
426
- const defaultVoiceName = options?.speaker || this.speaker;
427
- const defaultLanguageCode = options?.languageCode || defaultVoiceName?.split("-").slice(0, 2).join("-") || "en-US";
428
- const requestInput = options?.input ? { ...options.input } : { text: typeof input === "string" ? input : await this.streamToString(input) };
429
- if (options?.input && !options.input.text && !options.input.ssml && !options.input.markup && !options.input.multiSpeakerMarkup) {
430
- requestInput.text = typeof input === "string" ? input : await this.streamToString(input);
431
- }
432
- const request = {
433
- input: requestInput,
434
- voice: {
435
- name: defaultVoiceName,
436
- languageCode: defaultLanguageCode,
437
- ...options?.voice
438
- },
439
- audioConfig: options?.audioConfig || { audioEncoding: "LINEAR16" }
440
- };
441
- const [response] = await this.ttsClient.synthesizeSpeech(request);
442
- if (!response.audioContent) {
443
- throw new Error("No audio content returned.");
444
- }
445
- if (typeof response.audioContent === "string") {
446
- throw new Error("Audio content is a string.");
447
- }
448
- const stream$1 = new stream.PassThrough();
449
- stream$1.end(Buffer.from(response.audioContent));
450
- return stream$1;
451
- }
452
- /**
453
- * Checks if listening capabilities are enabled.
454
- *
455
- * @returns {Promise<{ enabled: boolean }>}
456
- */
457
- async getListener() {
458
- return { enabled: true };
459
- }
460
- /**
461
- * Converts speech to text using Cloud Speech-to-Text v1 or v2.
462
- *
463
- * Pass `{ v2: true }` in options to use the v2 API, which supports additional
464
- * audio formats like AAC-in-MP4 (iOS Safari) via `autoDecodingConfig` or
465
- * `explicitDecodingConfig`. The v1 path remains the default.
466
- *
467
- * @param {NodeJS.ReadableStream} audioStream - Audio stream to transcribe. Default encoding is LINEAR16.
468
- * @param {GoogleListenOptions} [options] - Recognition options
469
- * @returns {Promise<string>} Transcribed text
470
- */
471
- async listen(audioStream, options) {
472
- const chunks = [];
473
- for await (const chunk of audioStream) {
474
- if (typeof chunk === "string") {
475
- chunks.push(Buffer.from(chunk));
476
- } else {
477
- chunks.push(chunk);
478
- }
479
- }
480
- const buffer = Buffer.concat(chunks);
481
- if (options && "v2" in options && options.v2) {
482
- return this.recognizeV2(buffer, options);
483
- }
484
- return this.recognizeV1(buffer, options);
485
- }
486
- async recognizeV1(buffer, options) {
487
- const request = {
488
- config: {
489
- encoding: "LINEAR16",
490
- languageCode: "en-US",
491
- ...options?.config
492
- },
493
- audio: {
494
- content: buffer.toString("base64")
495
- }
496
- };
497
- const [response] = await this.speechClient.recognize(request);
498
- return this.extractTranscription(response?.results);
499
- }
500
- async recognizeV2(buffer, options) {
501
- const config = { ...options.config };
502
- if (!config.autoDecodingConfig && !config.explicitDecodingConfig) {
503
- config.autoDecodingConfig = {};
504
- }
505
- if (!config.languageCodes || config.languageCodes.length === 0) {
506
- config.languageCodes = ["en-US"];
507
- }
508
- if (!config.model) {
509
- config.model = "long";
510
- }
511
- let recognizer = options.recognizer;
512
- if (!recognizer) {
513
- const project = this.project || await this.getV2SpeechClient().getProjectId();
514
- recognizer = `projects/${project}/locations/global/recognizers/_`;
515
- }
516
- const request = {
517
- recognizer,
518
- config,
519
- content: buffer
520
- };
521
- const client = this.getV2SpeechClient();
522
- const [response] = await client.recognize(request);
523
- return this.extractTranscription(response?.results);
524
- }
525
- extractTranscription(results) {
526
- if (!results || results.length === 0) {
527
- throw new Error("No transcription results returned");
528
- }
529
- const transcription = results.map((result) => {
530
- if (!result.alternatives || result.alternatives.length === 0) {
531
- return "";
532
- }
533
- return result.alternatives[0].transcript || "";
534
- }).filter((text) => text.length > 0).join(" ");
535
- if (!transcription) {
536
- throw new Error("No valid transcription found in results");
537
- }
538
- return transcription;
539
- }
356
+ ttsClient;
357
+ speechClient;
358
+ speechClientV2;
359
+ speechOptionsV2;
360
+ vertexAI;
361
+ project;
362
+ location;
363
+ /**
364
+ * Creates an instance of GoogleVoice
365
+ * @param {GoogleVoiceConfig} config - Configuration options
366
+ * @param {GoogleModelConfig} [config.speechModel] - Configuration for speech synthesis
367
+ * @param {GoogleModelConfig} [config.listeningModel] - Configuration for speech recognition
368
+ * @param {string} [config.speaker] - Default voice ID to use for speech synthesis
369
+ * @param {boolean} [config.vertexAI] - Enable Vertex AI mode
370
+ * @param {string} [config.project] - Google Cloud project ID (required for Vertex AI)
371
+ * @param {string} [config.location] - Google Cloud region (default: 'us-central1')
372
+ */
373
+ constructor({ listeningModel, speechModel, speaker, vertexAI = false, project, location } = {}) {
374
+ const defaultApiKey = process.env.GOOGLE_API_KEY;
375
+ const defaultKeyFilename = process.env.GOOGLE_APPLICATION_CREDENTIALS;
376
+ const defaultSpeaker = DEFAULT_VOICE;
377
+ const resolvedProject = project || process.env.GOOGLE_CLOUD_PROJECT;
378
+ const resolvedLocation = location || process.env.GOOGLE_CLOUD_LOCATION || "us-central1";
379
+ if (vertexAI && !resolvedProject) throw new Error("Google Cloud project ID is required when using Vertex AI. Set GOOGLE_CLOUD_PROJECT environment variable or pass project to constructor.");
380
+ const vertexConfig = {
381
+ vertexAI,
382
+ project: resolvedProject
383
+ };
384
+ const sharedFallback = {
385
+ apiKey: defaultApiKey ?? speechModel?.apiKey ?? listeningModel?.apiKey,
386
+ keyFilename: defaultKeyFilename ?? speechModel?.keyFilename ?? listeningModel?.keyFilename,
387
+ credentials: speechModel?.credentials ?? listeningModel?.credentials,
388
+ projectId: resolvedProject
389
+ };
390
+ const speechAuthConfig = resolveAuthConfig(speechModel, sharedFallback, vertexConfig);
391
+ const listeningAuthConfig = resolveAuthConfig(listeningModel, sharedFallback, vertexConfig);
392
+ super({
393
+ speechModel: {
394
+ name: "",
395
+ apiKey: speechAuthConfig.apiKey ?? defaultApiKey
396
+ },
397
+ listeningModel: {
398
+ name: "",
399
+ apiKey: listeningAuthConfig.apiKey ?? defaultApiKey
400
+ },
401
+ speaker: speaker ?? defaultSpeaker
402
+ });
403
+ this.vertexAI = vertexAI;
404
+ this.project = resolvedProject;
405
+ this.location = resolvedLocation;
406
+ const ttsOptions = buildAuthOptions(speechAuthConfig, {
407
+ vertexAI,
408
+ location: resolvedLocation
409
+ });
410
+ const speechOptions = buildAuthOptions(listeningAuthConfig, {
411
+ vertexAI,
412
+ location: resolvedLocation
413
+ });
414
+ this.ttsClient = new _google_cloud_text_to_speech.TextToSpeechClient(ttsOptions);
415
+ this.speechClient = new _google_cloud_speech.SpeechClient(speechOptions);
416
+ this.speechOptionsV2 = speechOptions;
417
+ }
418
+ getV2SpeechClient() {
419
+ if (!this.speechClientV2) this.speechClientV2 = new _google_cloud_speech.v2.SpeechClient(this.speechOptionsV2);
420
+ return this.speechClientV2;
421
+ }
422
+ /**
423
+ * Check if Vertex AI mode is enabled
424
+ * @returns {boolean} True if using Vertex AI
425
+ */
426
+ isUsingVertexAI() {
427
+ return this.vertexAI;
428
+ }
429
+ /**
430
+ * Get the configured Google Cloud project ID
431
+ * @returns {string | undefined} The project ID or undefined if not set
432
+ */
433
+ getProject() {
434
+ return this.project;
435
+ }
436
+ /**
437
+ * Get the configured Google Cloud location/region
438
+ * @returns {string} The location (default: 'us-central1')
439
+ */
440
+ getLocation() {
441
+ return this.location;
442
+ }
443
+ /**
444
+ * Gets a list of available voices
445
+ * @returns {Promise<Array<{voiceId: string, languageCodes: string[]}>>} List of available voices and their supported languages. Default language is en-US.
446
+ */
447
+ async getSpeakers({ languageCode = "en-US" } = {}) {
448
+ const [response] = await this.ttsClient.listVoices({ languageCode });
449
+ return (response?.voices || []).filter((voice) => voice.name && voice.languageCodes).map((voice) => ({
450
+ voiceId: voice.name,
451
+ languageCodes: voice.languageCodes
452
+ }));
453
+ }
454
+ async streamToString(stream$1) {
455
+ const chunks = [];
456
+ for await (const chunk of stream$1) if (typeof chunk === "string") chunks.push(Buffer.from(chunk));
457
+ else chunks.push(chunk);
458
+ return Buffer.concat(chunks).toString("utf-8");
459
+ }
460
+ /**
461
+ * Converts text to speech.
462
+ *
463
+ * When `input` is a string or stream, builds a text-only request (existing behaviour).
464
+ * Pass `options.input` to send richer proto fields (ssml, markup, prompt,
465
+ * customPronunciations, multiSpeakerMarkup) and `options.voice` for fields
466
+ * like modelName or multiSpeakerVoiceConfig.
467
+ *
468
+ * @param {string | NodeJS.ReadableStream} input - Text or stream to convert to speech
469
+ * @param {GoogleSpeakOptions} [options] - Speech synthesis options
470
+ * @returns {Promise<NodeJS.ReadableStream>} Stream of synthesised audio. Default encoding is LINEAR16.
471
+ */
472
+ async speak(input, options) {
473
+ const defaultVoiceName = options?.speaker || this.speaker;
474
+ const defaultLanguageCode = options?.languageCode || defaultVoiceName?.split("-").slice(0, 2).join("-") || "en-US";
475
+ const requestInput = options?.input ? { ...options.input } : { text: typeof input === "string" ? input : await this.streamToString(input) };
476
+ if (options?.input && !options.input.text && !options.input.ssml && !options.input.markup && !options.input.multiSpeakerMarkup) requestInput.text = typeof input === "string" ? input : await this.streamToString(input);
477
+ const request = {
478
+ input: requestInput,
479
+ voice: {
480
+ name: defaultVoiceName,
481
+ languageCode: defaultLanguageCode,
482
+ ...options?.voice
483
+ },
484
+ audioConfig: options?.audioConfig || { audioEncoding: "LINEAR16" }
485
+ };
486
+ const [response] = await this.ttsClient.synthesizeSpeech(request);
487
+ if (!response.audioContent) throw new Error("No audio content returned.");
488
+ if (typeof response.audioContent === "string") throw new Error("Audio content is a string.");
489
+ const stream$2 = new stream.PassThrough();
490
+ stream$2.end(Buffer.from(response.audioContent));
491
+ return stream$2;
492
+ }
493
+ /**
494
+ * Checks if listening capabilities are enabled.
495
+ *
496
+ * @returns {Promise<{ enabled: boolean }>}
497
+ */
498
+ async getListener() {
499
+ return { enabled: true };
500
+ }
501
+ /**
502
+ * Converts speech to text using Cloud Speech-to-Text v1 or v2.
503
+ *
504
+ * Pass `{ v2: true }` in options to use the v2 API, which supports additional
505
+ * audio formats like AAC-in-MP4 (iOS Safari) via `autoDecodingConfig` or
506
+ * `explicitDecodingConfig`. The v1 path remains the default.
507
+ *
508
+ * @param {NodeJS.ReadableStream} audioStream - Audio stream to transcribe. Default encoding is LINEAR16.
509
+ * @param {GoogleListenOptions} [options] - Recognition options
510
+ * @returns {Promise<string>} Transcribed text
511
+ */
512
+ async listen(audioStream, options) {
513
+ const chunks = [];
514
+ for await (const chunk of audioStream) if (typeof chunk === "string") chunks.push(Buffer.from(chunk));
515
+ else chunks.push(chunk);
516
+ const buffer = Buffer.concat(chunks);
517
+ if (options && "v2" in options && options.v2) return this.recognizeV2(buffer, options);
518
+ return this.recognizeV1(buffer, options);
519
+ }
520
+ async recognizeV1(buffer, options) {
521
+ const request = {
522
+ config: {
523
+ encoding: "LINEAR16",
524
+ languageCode: "en-US",
525
+ ...options?.config
526
+ },
527
+ audio: { content: buffer.toString("base64") }
528
+ };
529
+ const [response] = await this.speechClient.recognize(request);
530
+ return this.extractTranscription(response?.results);
531
+ }
532
+ async recognizeV2(buffer, options) {
533
+ const config = { ...options.config };
534
+ if (!config.autoDecodingConfig && !config.explicitDecodingConfig) config.autoDecodingConfig = {};
535
+ if (!config.languageCodes || config.languageCodes.length === 0) config.languageCodes = ["en-US"];
536
+ if (!config.model) config.model = "long";
537
+ let recognizer = options.recognizer;
538
+ if (!recognizer) recognizer = `projects/${this.project || await this.getV2SpeechClient().getProjectId()}/locations/global/recognizers/_`;
539
+ const request = {
540
+ recognizer,
541
+ config,
542
+ content: buffer
543
+ };
544
+ const [response] = await this.getV2SpeechClient().recognize(request);
545
+ return this.extractTranscription(response?.results);
546
+ }
547
+ extractTranscription(results) {
548
+ if (!results || results.length === 0) throw new Error("No transcription results returned");
549
+ const transcription = results.map((result) => {
550
+ if (!result.alternatives || result.alternatives.length === 0) return "";
551
+ return result.alternatives[0].transcript || "";
552
+ }).filter((text) => text.length > 0).join(" ");
553
+ if (!transcription) throw new Error("No valid transcription found in results");
554
+ return transcription;
555
+ }
540
556
  };
541
-
557
+ //#endregion
542
558
  exports.GoogleVoice = GoogleVoice;
543
- //# sourceMappingURL=index.cjs.map
559
+
544
560
  //# sourceMappingURL=index.cjs.map