@mastra/voice-google 0.0.0-toolOptionTypes-20250917085558 → 0.0.0-top-level-fix-20251211111608

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
@@ -6,61 +6,129 @@ var textToSpeech = require('@google-cloud/text-to-speech');
6
6
  var voice = require('@mastra/core/voice');
7
7
 
8
8
  // src/index.ts
9
+ var resolveAuthConfig = (modelConfig, fallback, vertexConfig) => {
10
+ const resolved = {};
11
+ if (vertexConfig?.vertexAI) {
12
+ const projectId = vertexConfig.project || process.env.GOOGLE_CLOUD_PROJECT;
13
+ if (projectId) {
14
+ resolved.projectId = projectId;
15
+ }
16
+ }
17
+ const apiKey = modelConfig?.apiKey ?? fallback.apiKey;
18
+ if (apiKey && !vertexConfig?.vertexAI) {
19
+ resolved.apiKey = apiKey;
20
+ }
21
+ const keyFilename = modelConfig?.keyFilename ?? fallback.keyFilename;
22
+ if (keyFilename) {
23
+ resolved.keyFilename = keyFilename;
24
+ }
25
+ const credentials = modelConfig?.credentials ?? fallback.credentials;
26
+ if (credentials) {
27
+ resolved.credentials = credentials;
28
+ }
29
+ return resolved;
30
+ };
31
+ var buildAuthOptions = (config, vertexConfig) => {
32
+ const options = {};
33
+ if (config.credentials) {
34
+ options.credentials = config.credentials;
35
+ }
36
+ if (config.keyFilename) {
37
+ options.keyFilename = config.keyFilename;
38
+ }
39
+ if (config.apiKey && !vertexConfig?.vertexAI) {
40
+ options.apiKey = config.apiKey;
41
+ }
42
+ if (config.projectId) {
43
+ options.projectId = config.projectId;
44
+ }
45
+ return options;
46
+ };
9
47
  var DEFAULT_VOICE = "en-US-Casual-K";
10
48
  var GoogleVoice = class extends voice.MastraVoice {
11
49
  ttsClient;
12
50
  speechClient;
51
+ vertexAI;
52
+ project;
53
+ location;
13
54
  /**
14
55
  * Creates an instance of GoogleVoice
15
- * @param {Object} config - Configuration options
56
+ * @param {GoogleVoiceConfig} config - Configuration options
16
57
  * @param {GoogleModelConfig} [config.speechModel] - Configuration for speech synthesis
17
58
  * @param {GoogleModelConfig} [config.listeningModel] - Configuration for speech recognition
18
59
  * @param {string} [config.speaker] - Default voice ID to use for speech synthesis
19
- * @throws {Error} If no API key is provided via config or environment variable
60
+ * @param {boolean} [config.vertexAI] - Enable Vertex AI mode
61
+ * @param {string} [config.project] - Google Cloud project ID (required for Vertex AI)
62
+ * @param {string} [config.location] - Google Cloud region (default: 'us-central1')
20
63
  */
21
- constructor({
22
- listeningModel,
23
- speechModel,
24
- speaker
25
- } = {}) {
64
+ constructor({ listeningModel, speechModel, speaker, vertexAI = false, project, location } = {}) {
26
65
  const defaultApiKey = process.env.GOOGLE_API_KEY;
66
+ const defaultKeyFilename = process.env.GOOGLE_APPLICATION_CREDENTIALS;
27
67
  const defaultSpeaker = DEFAULT_VOICE;
68
+ const resolvedProject = project || process.env.GOOGLE_CLOUD_PROJECT;
69
+ const resolvedLocation = location || process.env.GOOGLE_CLOUD_LOCATION || "us-central1";
70
+ if (vertexAI && !resolvedProject) {
71
+ throw new Error(
72
+ "Google Cloud project ID is required when using Vertex AI. Set GOOGLE_CLOUD_PROJECT environment variable or pass project to constructor."
73
+ );
74
+ }
75
+ const vertexConfig = { vertexAI, project: resolvedProject };
76
+ const sharedFallback = {
77
+ apiKey: defaultApiKey ?? speechModel?.apiKey ?? listeningModel?.apiKey,
78
+ keyFilename: defaultKeyFilename ?? speechModel?.keyFilename ?? listeningModel?.keyFilename,
79
+ credentials: speechModel?.credentials ?? listeningModel?.credentials};
80
+ const speechAuthConfig = resolveAuthConfig(speechModel, sharedFallback, vertexConfig);
81
+ const listeningAuthConfig = resolveAuthConfig(listeningModel, sharedFallback, vertexConfig);
28
82
  super({
29
83
  speechModel: {
30
84
  name: "",
31
- apiKey: speechModel?.apiKey ?? defaultApiKey
85
+ apiKey: speechAuthConfig.apiKey ?? defaultApiKey
32
86
  },
33
87
  listeningModel: {
34
88
  name: "",
35
- apiKey: listeningModel?.apiKey ?? defaultApiKey
89
+ apiKey: listeningAuthConfig.apiKey ?? defaultApiKey
36
90
  },
37
91
  speaker: speaker ?? defaultSpeaker
38
92
  });
39
- const apiKey = defaultApiKey || speechModel?.apiKey || listeningModel?.apiKey;
40
- if (!apiKey) {
41
- throw new Error(
42
- "Google API key is not set, set GOOGLE_API_KEY environment variable or pass apiKey to constructor"
43
- );
44
- }
45
- this.ttsClient = new textToSpeech.TextToSpeechClient({
46
- apiKey: this.speechModel?.apiKey || defaultApiKey
47
- });
48
- this.speechClient = new speech.SpeechClient({
49
- apiKey: this.listeningModel?.apiKey || defaultApiKey
50
- });
93
+ this.vertexAI = vertexAI;
94
+ this.project = resolvedProject;
95
+ this.location = resolvedLocation;
96
+ const ttsOptions = buildAuthOptions(speechAuthConfig, { vertexAI});
97
+ const speechOptions = buildAuthOptions(listeningAuthConfig, { vertexAI});
98
+ this.ttsClient = new textToSpeech.TextToSpeechClient(ttsOptions);
99
+ this.speechClient = new speech.SpeechClient(speechOptions);
100
+ }
101
+ /**
102
+ * Check if Vertex AI mode is enabled
103
+ * @returns {boolean} True if using Vertex AI
104
+ */
105
+ isUsingVertexAI() {
106
+ return this.vertexAI;
107
+ }
108
+ /**
109
+ * Get the configured Google Cloud project ID
110
+ * @returns {string | undefined} The project ID or undefined if not set
111
+ */
112
+ getProject() {
113
+ return this.project;
114
+ }
115
+ /**
116
+ * Get the configured Google Cloud location/region
117
+ * @returns {string} The location (default: 'us-central1')
118
+ */
119
+ getLocation() {
120
+ return this.location;
51
121
  }
52
122
  /**
53
123
  * Gets a list of available voices
54
124
  * @returns {Promise<Array<{voiceId: string, languageCodes: string[]}>>} List of available voices and their supported languages. Default language is en-US.
55
125
  */
56
126
  async getSpeakers({ languageCode = "en-US" } = {}) {
57
- return this.traced(async () => {
58
- const [response] = await this.ttsClient.listVoices({ languageCode });
59
- return (response?.voices || []).filter((voice) => voice.name && voice.languageCodes).map((voice) => ({
60
- voiceId: voice.name,
61
- languageCodes: voice.languageCodes
62
- }));
63
- }, "voice.google.getSpeakers")();
127
+ const [response] = await this.ttsClient.listVoices({ languageCode });
128
+ return (response?.voices || []).filter((voice) => voice.name && voice.languageCodes).map((voice) => ({
129
+ voiceId: voice.name,
130
+ languageCodes: voice.languageCodes
131
+ }));
64
132
  }
65
133
  async streamToString(stream) {
66
134
  const chunks = [];
@@ -83,27 +151,25 @@ var GoogleVoice = class extends voice.MastraVoice {
83
151
  * @returns {Promise<NodeJS.ReadableStream>} Stream of synthesized audio. Default encoding is LINEAR16.
84
152
  */
85
153
  async speak(input, options) {
86
- return this.traced(async () => {
87
- const text = typeof input === "string" ? input : await this.streamToString(input);
88
- const request = {
89
- input: { text },
90
- voice: {
91
- name: options?.speaker || this.speaker,
92
- languageCode: options?.languageCode || options?.speaker?.split("-").slice(0, 2).join("-") || "en-US"
93
- },
94
- audioConfig: options?.audioConfig || { audioEncoding: "LINEAR16" }
95
- };
96
- const [response] = await this.ttsClient.synthesizeSpeech(request);
97
- if (!response.audioContent) {
98
- throw new Error("No audio content returned.");
99
- }
100
- if (typeof response.audioContent === "string") {
101
- throw new Error("Audio content is a string.");
102
- }
103
- const stream$1 = new stream.PassThrough();
104
- stream$1.end(Buffer.from(response.audioContent));
105
- return stream$1;
106
- }, "voice.google.speak")();
154
+ const text = typeof input === "string" ? input : await this.streamToString(input);
155
+ const request = {
156
+ input: { text },
157
+ voice: {
158
+ name: options?.speaker || this.speaker,
159
+ languageCode: options?.languageCode || options?.speaker?.split("-").slice(0, 2).join("-") || "en-US"
160
+ },
161
+ audioConfig: options?.audioConfig || { audioEncoding: "LINEAR16" }
162
+ };
163
+ const [response] = await this.ttsClient.synthesizeSpeech(request);
164
+ if (!response.audioContent) {
165
+ throw new Error("No audio content returned.");
166
+ }
167
+ if (typeof response.audioContent === "string") {
168
+ throw new Error("Audio content is a string.");
169
+ }
170
+ const stream$1 = new stream.PassThrough();
171
+ stream$1.end(Buffer.from(response.audioContent));
172
+ return stream$1;
107
173
  }
108
174
  /**
109
175
  * Checks if listening capabilities are enabled.
@@ -121,43 +187,39 @@ var GoogleVoice = class extends voice.MastraVoice {
121
187
  * @returns {Promise<string>} Transcribed text
122
188
  */
123
189
  async listen(audioStream, options) {
124
- return this.traced(async () => {
125
- const chunks = [];
126
- for await (const chunk of audioStream) {
127
- if (typeof chunk === "string") {
128
- chunks.push(Buffer.from(chunk));
129
- } else {
130
- chunks.push(chunk);
131
- }
190
+ const chunks = [];
191
+ for await (const chunk of audioStream) {
192
+ if (typeof chunk === "string") {
193
+ chunks.push(Buffer.from(chunk));
194
+ } else {
195
+ chunks.push(chunk);
132
196
  }
133
- const buffer = Buffer.concat(chunks);
134
- let request = {
135
- config: {
136
- encoding: "LINEAR16",
137
- languageCode: "en-US",
138
- ...options?.config
139
- },
140
- audio: {
141
- content: buffer.toString("base64")
142
- }
143
- };
144
- console.log(`BEFORE REQUEST`);
145
- const [response] = await this.speechClient.recognize(request);
146
- console.log(`AFTER REQUEST`);
147
- if (!response.results || response.results.length === 0) {
148
- throw new Error("No transcription results returned");
197
+ }
198
+ const buffer = Buffer.concat(chunks);
199
+ let request = {
200
+ config: {
201
+ encoding: "LINEAR16",
202
+ languageCode: "en-US",
203
+ ...options?.config
204
+ },
205
+ audio: {
206
+ content: buffer.toString("base64")
149
207
  }
150
- const transcription = response.results.map((result) => {
151
- if (!result.alternatives || result.alternatives.length === 0) {
152
- return "";
153
- }
154
- return result.alternatives[0].transcript || "";
155
- }).filter((text) => text.length > 0).join(" ");
156
- if (!transcription) {
157
- throw new Error("No valid transcription found in results");
208
+ };
209
+ const [response] = await this.speechClient.recognize(request);
210
+ if (!response.results || response.results.length === 0) {
211
+ throw new Error("No transcription results returned");
212
+ }
213
+ const transcription = response.results.map((result) => {
214
+ if (!result.alternatives || result.alternatives.length === 0) {
215
+ return "";
158
216
  }
159
- return transcription;
160
- }, "voice.google.listen")();
217
+ return result.alternatives[0].transcript || "";
218
+ }).filter((text) => text.length > 0).join(" ");
219
+ if (!transcription) {
220
+ throw new Error("No valid transcription found in results");
221
+ }
222
+ return transcription;
161
223
  }
162
224
  };
163
225
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":["MastraVoice","TextToSpeechClient","SpeechClient","stream","PassThrough"],"mappings":"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","file":"index.cjs","sourcesContent":["import { PassThrough } from 'stream';\n\nimport { SpeechClient } from '@google-cloud/speech';\nimport type { google as SpeechTypes } from '@google-cloud/speech/build/protos/protos';\nimport { TextToSpeechClient } from '@google-cloud/text-to-speech';\nimport type { google as TextToSpeechTypes } from '@google-cloud/text-to-speech/build/protos/protos';\nimport { MastraVoice } from '@mastra/core/voice';\n\n/**\n * Configuration for Google Cloud Voice models\n * @interface GoogleModelConfig\n * @property {string} [apiKey] - Optional Google Cloud API key. If not provided, will use GOOGLE_API_KEY environment variable\n */\nexport interface GoogleModelConfig {\n apiKey?: string;\n}\n\nconst DEFAULT_VOICE = 'en-US-Casual-K';\n\n/**\n * GoogleVoice class provides Text-to-Speech and Speech-to-Text capabilities using Google Cloud services\n * @class GoogleVoice\n * @extends MastraVoice\n */\nexport class GoogleVoice extends MastraVoice {\n private ttsClient: TextToSpeechClient;\n private speechClient: SpeechClient;\n\n /**\n * Creates an instance of GoogleVoice\n * @param {Object} config - Configuration options\n * @param {GoogleModelConfig} [config.speechModel] - Configuration for speech synthesis\n * @param {GoogleModelConfig} [config.listeningModel] - Configuration for speech recognition\n * @param {string} [config.speaker] - Default voice ID to use for speech synthesis\n * @throws {Error} If no API key is provided via config or environment variable\n */\n constructor({\n listeningModel,\n speechModel,\n speaker,\n }: {\n listeningModel?: GoogleModelConfig;\n speechModel?: GoogleModelConfig;\n speaker?: string;\n } = {}) {\n const defaultApiKey = process.env.GOOGLE_API_KEY;\n const defaultSpeaker = DEFAULT_VOICE;\n\n super({\n speechModel: {\n name: '',\n apiKey: speechModel?.apiKey ?? defaultApiKey,\n },\n listeningModel: {\n name: '',\n apiKey: listeningModel?.apiKey ?? defaultApiKey,\n },\n speaker: speaker ?? defaultSpeaker,\n });\n\n const apiKey = defaultApiKey || speechModel?.apiKey || listeningModel?.apiKey;\n if (!apiKey) {\n throw new Error(\n 'Google API key is not set, set GOOGLE_API_KEY environment variable or pass apiKey to constructor',\n );\n }\n\n this.ttsClient = new TextToSpeechClient({\n apiKey: this.speechModel?.apiKey || defaultApiKey,\n });\n\n this.speechClient = new SpeechClient({\n apiKey: this.listeningModel?.apiKey || defaultApiKey,\n });\n }\n\n /**\n * Gets a list of available voices\n * @returns {Promise<Array<{voiceId: string, languageCodes: string[]}>>} List of available voices and their supported languages. Default language is en-US.\n */\n async getSpeakers({ languageCode = 'en-US' }: { languageCode?: string } = {}) {\n return this.traced(async () => {\n const [response] = await this.ttsClient.listVoices({ languageCode: languageCode });\n return (response?.voices || [])\n .filter(voice => voice.name && voice.languageCodes)\n .map(voice => ({\n voiceId: voice.name!,\n languageCodes: voice.languageCodes!,\n }));\n }, 'voice.google.getSpeakers')();\n }\n\n private async streamToString(stream: NodeJS.ReadableStream): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of stream) {\n if (typeof chunk === 'string') {\n chunks.push(Buffer.from(chunk));\n } else {\n chunks.push(chunk);\n }\n }\n return Buffer.concat(chunks).toString('utf-8');\n }\n\n /**\n * Converts text to speech\n * @param {string | NodeJS.ReadableStream} input - Text or stream to convert to speech\n * @param {Object} [options] - Speech synthesis options\n * @param {string} [options.speaker] - Voice ID to use\n * @param {string} [options.languageCode] - Language code for the voice\n * @param {TextToSpeechTypes.cloud.texttospeech.v1.ISynthesizeSpeechRequest['audioConfig']} [options.audioConfig] - Audio configuration options\n * @returns {Promise<NodeJS.ReadableStream>} Stream of synthesized audio. Default encoding is LINEAR16.\n */\n async speak(\n input: string | NodeJS.ReadableStream,\n options?: {\n speaker?: string;\n languageCode?: string;\n audioConfig?: TextToSpeechTypes.cloud.texttospeech.v1.ISynthesizeSpeechRequest['audioConfig'];\n },\n ): Promise<NodeJS.ReadableStream> {\n return this.traced(async () => {\n const text = typeof input === 'string' ? input : await this.streamToString(input);\n\n const request: TextToSpeechTypes.cloud.texttospeech.v1.ISynthesizeSpeechRequest = {\n input: { text },\n voice: {\n name: options?.speaker || this.speaker,\n languageCode: options?.languageCode || options?.speaker?.split('-').slice(0, 2).join('-') || 'en-US',\n },\n audioConfig: options?.audioConfig || { audioEncoding: 'LINEAR16' },\n };\n\n const [response] = await this.ttsClient.synthesizeSpeech(request);\n\n if (!response.audioContent) {\n throw new Error('No audio content returned.');\n }\n\n if (typeof response.audioContent === 'string') {\n throw new Error('Audio content is a string.');\n }\n\n const stream = new PassThrough();\n stream.end(Buffer.from(response.audioContent));\n return stream;\n }, 'voice.google.speak')();\n }\n\n /**\n * Checks if listening capabilities are enabled.\n *\n * @returns {Promise<{ enabled: boolean }>}\n */\n async getListener() {\n return { enabled: true };\n }\n\n /**\n * Converts speech to text\n * @param {NodeJS.ReadableStream} audioStream - Audio stream to transcribe. Default encoding is LINEAR16.\n * @param {Object} [options] - Recognition options\n * @param {SpeechTypes.cloud.speech.v1.IRecognitionConfig} [options.config] - Recognition configuration\n * @returns {Promise<string>} Transcribed text\n */\n async listen(\n audioStream: NodeJS.ReadableStream,\n options?: { stream?: boolean; config?: SpeechTypes.cloud.speech.v1.IRecognitionConfig },\n ): Promise<string> {\n return this.traced(async () => {\n const chunks: Buffer[] = [];\n for await (const chunk of audioStream) {\n if (typeof chunk === 'string') {\n chunks.push(Buffer.from(chunk));\n } else {\n chunks.push(chunk);\n }\n }\n const buffer = Buffer.concat(chunks);\n\n let request = {\n config: {\n encoding: 'LINEAR16',\n languageCode: 'en-US',\n ...options?.config,\n },\n audio: {\n content: buffer.toString('base64'),\n },\n };\n console.log(`BEFORE REQUEST`);\n const [response] = await this.speechClient.recognize(request as SpeechTypes.cloud.speech.v1.IRecognizeRequest);\n console.log(`AFTER REQUEST`);\n\n if (!response.results || response.results.length === 0) {\n throw new Error('No transcription results returned');\n }\n\n const transcription = response.results\n .map((result: any) => {\n if (!result.alternatives || result.alternatives.length === 0) {\n return '';\n }\n return result.alternatives[0].transcript || '';\n })\n .filter((text: string) => text.length > 0)\n .join(' ');\n\n if (!transcription) {\n throw new Error('No valid transcription found in results');\n }\n\n return transcription;\n }, 'voice.google.listen')();\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":["MastraVoice","TextToSpeechClient","SpeechClient","stream","PassThrough"],"mappings":"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","file":"index.cjs","sourcesContent":["import { PassThrough } from 'node:stream';\n\nimport { SpeechClient } from '@google-cloud/speech';\nimport type { google as SpeechTypes } from '@google-cloud/speech/build/protos/protos';\nimport { TextToSpeechClient } from '@google-cloud/text-to-speech';\nimport type { google as TextToSpeechTypes } from '@google-cloud/text-to-speech/build/protos/protos';\nimport { MastraVoice } from '@mastra/core/voice';\n\n/**\n * Configuration for Google Cloud Voice models\n * @interface GoogleModelConfig\n * @property {string} [apiKey] - Optional Google Cloud API key. If not provided, will use GOOGLE_API_KEY environment variable\n * @property {string} [keyFilename] - Optional path to a service account key file. If not provided, will use GOOGLE_APPLICATION_CREDENTIALS environment variable\n * @property {{ client_email?: string; private_key?: string }} [credentials] - Optional in-memory service account credentials\n */\nexport interface GoogleModelConfig {\n apiKey?: string;\n keyFilename?: string;\n credentials?: {\n client_email?: string;\n private_key?: string;\n [key: string]: unknown;\n };\n}\n\n/**\n * Configuration options for GoogleVoice\n * @interface GoogleVoiceConfig\n */\nexport interface GoogleVoiceConfig {\n /** Configuration for speech synthesis (TTS) */\n speechModel?: GoogleModelConfig;\n /** Configuration for speech recognition (STT) */\n listeningModel?: GoogleModelConfig;\n /** Default voice ID to use for speech synthesis */\n speaker?: string;\n /**\n * Enable Vertex AI mode for enterprise deployments.\n * When true, uses Google Cloud project-based authentication instead of API keys.\n * Requires `project` to be set or GOOGLE_CLOUD_PROJECT environment variable.\n */\n vertexAI?: boolean;\n /**\n * Google Cloud project ID (required when vertexAI is true).\n * Falls back to GOOGLE_CLOUD_PROJECT environment variable.\n */\n project?: string;\n /**\n * Google Cloud region for Vertex AI endpoints.\n * Falls back to GOOGLE_CLOUD_LOCATION environment variable.\n * @default 'us-central1'\n */\n location?: string;\n}\n\ntype AuthConfig = Pick<GoogleModelConfig, 'apiKey' | 'keyFilename' | 'credentials'> & {\n projectId?: string;\n};\n\ntype GoogleClientOptions = AuthConfig;\n\nconst resolveAuthConfig = (\n modelConfig: GoogleModelConfig | undefined,\n fallback: AuthConfig,\n vertexConfig?: { vertexAI?: boolean; project?: string },\n): AuthConfig => {\n const resolved: AuthConfig = {};\n\n // For Vertex AI, prioritize project-based auth over API keys\n if (vertexConfig?.vertexAI) {\n const projectId = vertexConfig.project || process.env.GOOGLE_CLOUD_PROJECT;\n if (projectId) {\n resolved.projectId = projectId;\n }\n }\n\n const apiKey = modelConfig?.apiKey ?? fallback.apiKey;\n // Only use API key if not in Vertex AI mode\n if (apiKey && !vertexConfig?.vertexAI) {\n resolved.apiKey = apiKey;\n }\n\n const keyFilename = modelConfig?.keyFilename ?? fallback.keyFilename;\n if (keyFilename) {\n resolved.keyFilename = keyFilename;\n }\n\n const credentials = modelConfig?.credentials ?? fallback.credentials;\n if (credentials) {\n resolved.credentials = credentials;\n }\n\n return resolved;\n};\n\nconst buildAuthOptions = (\n config: AuthConfig,\n vertexConfig?: { vertexAI?: boolean; location?: string },\n): GoogleClientOptions => {\n const options: GoogleClientOptions = {};\n\n if (config.credentials) {\n options.credentials = config.credentials;\n }\n\n if (config.keyFilename) {\n options.keyFilename = config.keyFilename;\n }\n\n // Only use API key if not using Vertex AI\n if (config.apiKey && !vertexConfig?.vertexAI) {\n options.apiKey = config.apiKey;\n }\n\n // For Vertex AI, set the project ID\n if (config.projectId) {\n options.projectId = config.projectId;\n }\n\n return options;\n};\n\nconst DEFAULT_VOICE = 'en-US-Casual-K';\n\n/**\n * GoogleVoice class provides Text-to-Speech and Speech-to-Text capabilities using Google Cloud services.\n * Supports both standard Google Cloud API authentication and Vertex AI mode for enterprise deployments.\n *\n * @class GoogleVoice\n * @extends MastraVoice\n *\n * @example Standard usage with API key\n * ```typescript\n * const voice = new GoogleVoice({\n * speechModel: { apiKey: 'your-api-key' },\n * speaker: 'en-US-Studio-O',\n * });\n * ```\n *\n * @example Vertex AI mode (recommended for production)\n * ```typescript\n * const voice = new GoogleVoice({\n * vertexAI: true,\n * project: 'your-gcp-project',\n * location: 'us-central1',\n * speaker: 'en-US-Studio-O',\n * });\n * ```\n *\n * @example Vertex AI with service account\n * ```typescript\n * const voice = new GoogleVoice({\n * vertexAI: true,\n * project: 'your-gcp-project',\n * speechModel: {\n * keyFilename: '/path/to/service-account.json',\n * },\n * });\n * ```\n */\nexport class GoogleVoice extends MastraVoice {\n private ttsClient: TextToSpeechClient;\n private speechClient: SpeechClient;\n private readonly vertexAI: boolean;\n private readonly project?: string;\n private readonly location: string;\n\n /**\n * Creates an instance of GoogleVoice\n * @param {GoogleVoiceConfig} config - Configuration options\n * @param {GoogleModelConfig} [config.speechModel] - Configuration for speech synthesis\n * @param {GoogleModelConfig} [config.listeningModel] - Configuration for speech recognition\n * @param {string} [config.speaker] - Default voice ID to use for speech synthesis\n * @param {boolean} [config.vertexAI] - Enable Vertex AI mode\n * @param {string} [config.project] - Google Cloud project ID (required for Vertex AI)\n * @param {string} [config.location] - Google Cloud region (default: 'us-central1')\n */\n constructor({ listeningModel, speechModel, speaker, vertexAI = false, project, location }: GoogleVoiceConfig = {}) {\n const defaultApiKey = process.env.GOOGLE_API_KEY;\n const defaultKeyFilename = process.env.GOOGLE_APPLICATION_CREDENTIALS;\n const defaultSpeaker = DEFAULT_VOICE;\n\n // Resolve Vertex AI configuration\n const resolvedProject = project || process.env.GOOGLE_CLOUD_PROJECT;\n const resolvedLocation = location || process.env.GOOGLE_CLOUD_LOCATION || 'us-central1';\n\n // Validate Vertex AI configuration\n if (vertexAI && !resolvedProject) {\n throw new Error(\n 'Google Cloud project ID is required when using Vertex AI. ' +\n 'Set GOOGLE_CLOUD_PROJECT environment variable or pass project to constructor.',\n );\n }\n\n const vertexConfig = { vertexAI, project: resolvedProject };\n\n const sharedFallback: AuthConfig = {\n apiKey: defaultApiKey ?? speechModel?.apiKey ?? listeningModel?.apiKey,\n keyFilename: defaultKeyFilename ?? speechModel?.keyFilename ?? listeningModel?.keyFilename,\n credentials: speechModel?.credentials ?? listeningModel?.credentials,\n projectId: resolvedProject,\n };\n\n const speechAuthConfig = resolveAuthConfig(speechModel, sharedFallback, vertexConfig);\n const listeningAuthConfig = resolveAuthConfig(listeningModel, sharedFallback, vertexConfig);\n\n super({\n speechModel: {\n name: '',\n apiKey: speechAuthConfig.apiKey ?? defaultApiKey,\n },\n listeningModel: {\n name: '',\n apiKey: listeningAuthConfig.apiKey ?? defaultApiKey,\n },\n speaker: speaker ?? defaultSpeaker,\n });\n\n this.vertexAI = vertexAI;\n this.project = resolvedProject;\n this.location = resolvedLocation;\n\n const ttsOptions = buildAuthOptions(speechAuthConfig, { vertexAI, location: resolvedLocation });\n const speechOptions = buildAuthOptions(listeningAuthConfig, { vertexAI, location: resolvedLocation });\n\n this.ttsClient = new TextToSpeechClient(ttsOptions);\n this.speechClient = new SpeechClient(speechOptions);\n }\n\n /**\n * Check if Vertex AI mode is enabled\n * @returns {boolean} True if using Vertex AI\n */\n isUsingVertexAI(): boolean {\n return this.vertexAI;\n }\n\n /**\n * Get the configured Google Cloud project ID\n * @returns {string | undefined} The project ID or undefined if not set\n */\n getProject(): string | undefined {\n return this.project;\n }\n\n /**\n * Get the configured Google Cloud location/region\n * @returns {string} The location (default: 'us-central1')\n */\n getLocation(): string {\n return this.location;\n }\n\n /**\n * Gets a list of available voices\n * @returns {Promise<Array<{voiceId: string, languageCodes: string[]}>>} List of available voices and their supported languages. Default language is en-US.\n */\n async getSpeakers({ languageCode = 'en-US' }: { languageCode?: string } = {}) {\n const [response] = await this.ttsClient.listVoices({ languageCode: languageCode });\n return (response?.voices || [])\n .filter(voice => voice.name && voice.languageCodes)\n .map(voice => ({\n voiceId: voice.name!,\n languageCodes: voice.languageCodes!,\n }));\n }\n\n private async streamToString(stream: NodeJS.ReadableStream): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of stream) {\n if (typeof chunk === 'string') {\n chunks.push(Buffer.from(chunk));\n } else {\n chunks.push(chunk);\n }\n }\n return Buffer.concat(chunks).toString('utf-8');\n }\n\n /**\n * Converts text to speech\n * @param {string | NodeJS.ReadableStream} input - Text or stream to convert to speech\n * @param {Object} [options] - Speech synthesis options\n * @param {string} [options.speaker] - Voice ID to use\n * @param {string} [options.languageCode] - Language code for the voice\n * @param {TextToSpeechTypes.cloud.texttospeech.v1.ISynthesizeSpeechRequest['audioConfig']} [options.audioConfig] - Audio configuration options\n * @returns {Promise<NodeJS.ReadableStream>} Stream of synthesized audio. Default encoding is LINEAR16.\n */\n async speak(\n input: string | NodeJS.ReadableStream,\n options?: {\n speaker?: string;\n languageCode?: string;\n audioConfig?: TextToSpeechTypes.cloud.texttospeech.v1.ISynthesizeSpeechRequest['audioConfig'];\n },\n ): Promise<NodeJS.ReadableStream> {\n const text = typeof input === 'string' ? input : await this.streamToString(input);\n\n const request: TextToSpeechTypes.cloud.texttospeech.v1.ISynthesizeSpeechRequest = {\n input: { text },\n voice: {\n name: options?.speaker || this.speaker,\n languageCode: options?.languageCode || options?.speaker?.split('-').slice(0, 2).join('-') || 'en-US',\n },\n audioConfig: options?.audioConfig || { audioEncoding: 'LINEAR16' },\n };\n\n const [response] = await this.ttsClient.synthesizeSpeech(request);\n\n if (!response.audioContent) {\n throw new Error('No audio content returned.');\n }\n\n if (typeof response.audioContent === 'string') {\n throw new Error('Audio content is a string.');\n }\n\n const stream = new PassThrough();\n stream.end(Buffer.from(response.audioContent));\n return stream;\n }\n\n /**\n * Checks if listening capabilities are enabled.\n *\n * @returns {Promise<{ enabled: boolean }>}\n */\n async getListener() {\n return { enabled: true };\n }\n\n /**\n * Converts speech to text\n * @param {NodeJS.ReadableStream} audioStream - Audio stream to transcribe. Default encoding is LINEAR16.\n * @param {Object} [options] - Recognition options\n * @param {SpeechTypes.cloud.speech.v1.IRecognitionConfig} [options.config] - Recognition configuration\n * @returns {Promise<string>} Transcribed text\n */\n async listen(\n audioStream: NodeJS.ReadableStream,\n options?: { stream?: boolean; config?: SpeechTypes.cloud.speech.v1.IRecognitionConfig },\n ): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of audioStream) {\n if (typeof chunk === 'string') {\n chunks.push(Buffer.from(chunk));\n } else {\n chunks.push(chunk);\n }\n }\n const buffer = Buffer.concat(chunks);\n\n let request = {\n config: {\n encoding: 'LINEAR16',\n languageCode: 'en-US',\n ...options?.config,\n },\n audio: {\n content: buffer.toString('base64'),\n },\n };\n const [response] = await this.speechClient.recognize(request as SpeechTypes.cloud.speech.v1.IRecognizeRequest);\n\n if (!response.results || response.results.length === 0) {\n throw new Error('No transcription results returned');\n }\n\n const transcription = response.results\n .map((result: any) => {\n if (!result.alternatives || result.alternatives.length === 0) {\n return '';\n }\n return result.alternatives[0].transcript || '';\n })\n .filter((text: string) => text.length > 0)\n .join(' ');\n\n if (!transcription) {\n throw new Error('No valid transcription found in results');\n }\n\n return transcription;\n }\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -5,31 +5,115 @@ import { MastraVoice } from '@mastra/core/voice';
5
5
  * Configuration for Google Cloud Voice models
6
6
  * @interface GoogleModelConfig
7
7
  * @property {string} [apiKey] - Optional Google Cloud API key. If not provided, will use GOOGLE_API_KEY environment variable
8
+ * @property {string} [keyFilename] - Optional path to a service account key file. If not provided, will use GOOGLE_APPLICATION_CREDENTIALS environment variable
9
+ * @property {{ client_email?: string; private_key?: string }} [credentials] - Optional in-memory service account credentials
8
10
  */
9
11
  export interface GoogleModelConfig {
10
12
  apiKey?: string;
13
+ keyFilename?: string;
14
+ credentials?: {
15
+ client_email?: string;
16
+ private_key?: string;
17
+ [key: string]: unknown;
18
+ };
11
19
  }
12
20
  /**
13
- * GoogleVoice class provides Text-to-Speech and Speech-to-Text capabilities using Google Cloud services
21
+ * Configuration options for GoogleVoice
22
+ * @interface GoogleVoiceConfig
23
+ */
24
+ export interface GoogleVoiceConfig {
25
+ /** Configuration for speech synthesis (TTS) */
26
+ speechModel?: GoogleModelConfig;
27
+ /** Configuration for speech recognition (STT) */
28
+ listeningModel?: GoogleModelConfig;
29
+ /** Default voice ID to use for speech synthesis */
30
+ speaker?: string;
31
+ /**
32
+ * Enable Vertex AI mode for enterprise deployments.
33
+ * When true, uses Google Cloud project-based authentication instead of API keys.
34
+ * Requires `project` to be set or GOOGLE_CLOUD_PROJECT environment variable.
35
+ */
36
+ vertexAI?: boolean;
37
+ /**
38
+ * Google Cloud project ID (required when vertexAI is true).
39
+ * Falls back to GOOGLE_CLOUD_PROJECT environment variable.
40
+ */
41
+ project?: string;
42
+ /**
43
+ * Google Cloud region for Vertex AI endpoints.
44
+ * Falls back to GOOGLE_CLOUD_LOCATION environment variable.
45
+ * @default 'us-central1'
46
+ */
47
+ location?: string;
48
+ }
49
+ /**
50
+ * GoogleVoice class provides Text-to-Speech and Speech-to-Text capabilities using Google Cloud services.
51
+ * Supports both standard Google Cloud API authentication and Vertex AI mode for enterprise deployments.
52
+ *
14
53
  * @class GoogleVoice
15
54
  * @extends MastraVoice
55
+ *
56
+ * @example Standard usage with API key
57
+ * ```typescript
58
+ * const voice = new GoogleVoice({
59
+ * speechModel: { apiKey: 'your-api-key' },
60
+ * speaker: 'en-US-Studio-O',
61
+ * });
62
+ * ```
63
+ *
64
+ * @example Vertex AI mode (recommended for production)
65
+ * ```typescript
66
+ * const voice = new GoogleVoice({
67
+ * vertexAI: true,
68
+ * project: 'your-gcp-project',
69
+ * location: 'us-central1',
70
+ * speaker: 'en-US-Studio-O',
71
+ * });
72
+ * ```
73
+ *
74
+ * @example Vertex AI with service account
75
+ * ```typescript
76
+ * const voice = new GoogleVoice({
77
+ * vertexAI: true,
78
+ * project: 'your-gcp-project',
79
+ * speechModel: {
80
+ * keyFilename: '/path/to/service-account.json',
81
+ * },
82
+ * });
83
+ * ```
16
84
  */
17
85
  export declare class GoogleVoice extends MastraVoice {
18
86
  private ttsClient;
19
87
  private speechClient;
88
+ private readonly vertexAI;
89
+ private readonly project?;
90
+ private readonly location;
20
91
  /**
21
92
  * Creates an instance of GoogleVoice
22
- * @param {Object} config - Configuration options
93
+ * @param {GoogleVoiceConfig} config - Configuration options
23
94
  * @param {GoogleModelConfig} [config.speechModel] - Configuration for speech synthesis
24
95
  * @param {GoogleModelConfig} [config.listeningModel] - Configuration for speech recognition
25
96
  * @param {string} [config.speaker] - Default voice ID to use for speech synthesis
26
- * @throws {Error} If no API key is provided via config or environment variable
97
+ * @param {boolean} [config.vertexAI] - Enable Vertex AI mode
98
+ * @param {string} [config.project] - Google Cloud project ID (required for Vertex AI)
99
+ * @param {string} [config.location] - Google Cloud region (default: 'us-central1')
27
100
  */
28
- constructor({ listeningModel, speechModel, speaker, }?: {
29
- listeningModel?: GoogleModelConfig;
30
- speechModel?: GoogleModelConfig;
31
- speaker?: string;
32
- });
101
+ constructor({ listeningModel, speechModel, speaker, vertexAI, project, location }?: GoogleVoiceConfig);
102
+ /**
103
+ * Check if Vertex AI mode is enabled
104
+ * @returns {boolean} True if using Vertex AI
105
+ */
106
+ isUsingVertexAI(): boolean;
107
+ /**
108
+ * Get the configured Google Cloud project ID
109
+ * @returns {string | undefined} The project ID or undefined if not set
110
+ */
111
+ getProject(): string | undefined;
112
+ /**
113
+ * Get the configured Google Cloud location/region
114
+ * @returns {string} The location (default: 'us-central1')
115
+ */
116
+ getLocation(): string;
33
117
  /**
34
118
  * Gets a list of available voices
35
119
  * @returns {Promise<Array<{voiceId: string, languageCodes: string[]}>>} List of available voices and their supported languages. Default language is en-US.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,IAAI,WAAW,EAAE,MAAM,0CAA0C,CAAC;AAEtF,OAAO,KAAK,EAAE,MAAM,IAAI,iBAAiB,EAAE,MAAM,kDAAkD,CAAC;AACpG,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAID;;;;GAIG;AACH,qBAAa,WAAY,SAAQ,WAAW;IAC1C,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,YAAY,CAAe;IAEnC;;;;;;;OAOG;gBACS,EACV,cAAc,EACd,WAAW,EACX,OAAO,GACR,GAAE;QACD,cAAc,CAAC,EAAE,iBAAiB,CAAC;QACnC,WAAW,CAAC,EAAE,iBAAiB,CAAC;QAChC,OAAO,CAAC,EAAE,MAAM,CAAC;KACb;IAgCN;;;OAGG;IACG,WAAW,CAAC,EAAE,YAAsB,EAAE,GAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAA;KAAO;;;;YAY9D,cAAc;IAY5B;;;;;;;;OAQG;IACG,KAAK,CACT,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,cAAc,EACrC,OAAO,CAAC,EAAE;QACR,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,WAAW,CAAC,EAAE,iBAAiB,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC,wBAAwB,CAAC,aAAa,CAAC,CAAC;KAC/F,GACA,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC;IA6BjC;;;;OAIG;IACG,WAAW;;;IAIjB;;;;;;OAMG;IACG,MAAM,CACV,WAAW,EAAE,MAAM,CAAC,cAAc,EAClC,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,kBAAkB,CAAA;KAAE,GACtF,OAAO,CAAC,MAAM,CAAC;CA+CnB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,IAAI,WAAW,EAAE,MAAM,0CAA0C,CAAC;AAEtF,OAAO,KAAK,EAAE,MAAM,IAAI,iBAAiB,EAAE,MAAM,kDAAkD,CAAC;AACpG,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE;QACZ,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,CAAC;CACH;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,+CAA+C;IAC/C,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,iDAAiD;IACjD,cAAc,CAAC,EAAE,iBAAiB,CAAC;IACnC,mDAAmD;IACnD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAuED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,qBAAa,WAAY,SAAQ,WAAW;IAC1C,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAU;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAElC;;;;;;;;;OASG;gBACS,EAAE,cAAc,EAAE,WAAW,EAAE,OAAO,EAAE,QAAgB,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAE,iBAAsB;IAoDjH;;;OAGG;IACH,eAAe,IAAI,OAAO;IAI1B;;;OAGG;IACH,UAAU,IAAI,MAAM,GAAG,SAAS;IAIhC;;;OAGG;IACH,WAAW,IAAI,MAAM;IAIrB;;;OAGG;IACG,WAAW,CAAC,EAAE,YAAsB,EAAE,GAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAA;KAAO;;;;YAU9D,cAAc;IAY5B;;;;;;;;OAQG;IACG,KAAK,CACT,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,cAAc,EACrC,OAAO,CAAC,EAAE;QACR,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,WAAW,CAAC,EAAE,iBAAiB,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC,wBAAwB,CAAC,aAAa,CAAC,CAAC;KAC/F,GACA,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC;IA2BjC;;;;OAIG;IACG,WAAW;;;IAIjB;;;;;;OAMG;IACG,MAAM,CACV,WAAW,EAAE,MAAM,CAAC,cAAc,EAClC,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,kBAAkB,CAAA;KAAE,GACtF,OAAO,CAAC,MAAM,CAAC;CA2CnB"}