@elizaos/plugin-edge-tts 2.0.0-alpha.9 → 2.0.0-beta.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/auto-enable.ts ADDED
@@ -0,0 +1,30 @@
1
+ // Auto-enable check for @elizaos/plugin-edge-tts.
2
+ //
3
+ // Plugin manifest entry-point — referenced by package.json's
4
+ // `elizaos.plugin.autoEnableModule`. Keep this module light: env reads only,
5
+ // no service init, no transitive imports of the full plugin runtime. The
6
+ // auto-enable engine loads dozens of these per boot.
7
+ import type { PluginAutoEnableContext } from "@elizaos/core";
8
+
9
+ function isFeatureEnabled(
10
+ config: PluginAutoEnableContext["config"],
11
+ key: string,
12
+ ): boolean {
13
+ const f = (config?.features as Record<string, unknown> | undefined)?.[key];
14
+ if (f === true) return true;
15
+ if (f && typeof f === "object" && f !== null) {
16
+ return (f as Record<string, unknown>).enabled !== false;
17
+ }
18
+ return false;
19
+ }
20
+
21
+ /**
22
+ * Enable when the runtime is provisioned by Eliza Cloud, or when the user has
23
+ * explicitly enabled TTS via `config.features.tts`.
24
+ */
25
+ export function shouldEnable(ctx: PluginAutoEnableContext): boolean {
26
+ return (
27
+ ctx.env.ELIZA_CLOUD_PROVISIONED === "1" ||
28
+ isFeatureEnabled(ctx.config, "tts")
29
+ );
30
+ }
@@ -0,0 +1,316 @@
1
+ var __create = Object.create;
2
+ var __getProtoOf = Object.getPrototypeOf;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ function __accessProp(key) {
8
+ return this[key];
9
+ }
10
+ var __toESMCache_node;
11
+ var __toESMCache_esm;
12
+ var __toESM = (mod, isNodeMode, target) => {
13
+ var canCache = mod != null && typeof mod === "object";
14
+ if (canCache) {
15
+ var cache = isNodeMode
16
+ ? (__toESMCache_node ??= new WeakMap())
17
+ : (__toESMCache_esm ??= new WeakMap());
18
+ var cached = cache.get(mod);
19
+ if (cached) return cached;
20
+ }
21
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
22
+ const to =
23
+ isNodeMode || !mod || !mod.__esModule
24
+ ? __defProp(target, "default", { value: mod, enumerable: true })
25
+ : target;
26
+ for (const key of __getOwnPropNames(mod))
27
+ if (!__hasOwnProp.call(to, key))
28
+ __defProp(to, key, {
29
+ get: __accessProp.bind(mod, key),
30
+ enumerable: true,
31
+ });
32
+ if (canCache) cache.set(mod, to);
33
+ return to;
34
+ };
35
+ var __toCommonJS = (from) => {
36
+ var entry = (__moduleCache ??= new WeakMap()).get(from),
37
+ desc;
38
+ if (entry) return entry;
39
+ entry = __defProp({}, "__esModule", { value: true });
40
+ if ((from && typeof from === "object") || typeof from === "function") {
41
+ for (var key of __getOwnPropNames(from))
42
+ if (!__hasOwnProp.call(entry, key))
43
+ __defProp(entry, key, {
44
+ get: __accessProp.bind(from, key),
45
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable,
46
+ });
47
+ }
48
+ __moduleCache.set(from, entry);
49
+ return entry;
50
+ };
51
+ var __moduleCache;
52
+ var __returnValue = (v) => v;
53
+ function __exportSetter(name, newValue) {
54
+ this[name] = __returnValue.bind(null, newValue);
55
+ }
56
+ var __export = (target, all) => {
57
+ for (var name in all)
58
+ __defProp(target, name, {
59
+ get: all[name],
60
+ enumerable: true,
61
+ configurable: true,
62
+ set: __exportSetter.bind(all, name),
63
+ });
64
+ };
65
+
66
+ // src/index.ts
67
+ var exports_src = {};
68
+ __export(exports_src, {
69
+ edgeTTSPlugin: () => edgeTTSPlugin,
70
+ default: () => src_default,
71
+ _test: () => _test,
72
+ });
73
+ module.exports = __toCommonJS(exports_src);
74
+ var import_node_fs = require("node:fs");
75
+ var import_node_os = require("node:os");
76
+ var import_node_path = __toESM(require("node:path"));
77
+ var import_core = require("@elizaos/core");
78
+ var import_node_edge_tts = require("node-edge-tts");
79
+ var DEFAULT_VOICE = "en-US-MichelleNeural";
80
+ var DEFAULT_LANG = "en-US";
81
+ var DEFAULT_OUTPUT_FORMAT = "audio-24khz-48kbitrate-mono-mp3";
82
+ var DEFAULT_TIMEOUT_MS = 30000;
83
+ var VOICE_PRESETS = {
84
+ alloy: "en-US-GuyNeural",
85
+ echo: "en-US-ChristopherNeural",
86
+ fable: "en-GB-RyanNeural",
87
+ onyx: "en-US-DavisNeural",
88
+ nova: "en-US-JennyNeural",
89
+ shimmer: "en-US-AriaNeural",
90
+ };
91
+ function getSetting(runtime, key, fallback) {
92
+ const envValue =
93
+ typeof process !== "undefined" && process.env
94
+ ? process.env[key]
95
+ : undefined;
96
+ return runtime.getSetting(key) ?? envValue ?? fallback;
97
+ }
98
+ function getEdgeTTSSettings(runtime) {
99
+ const timeoutStr = getSetting(runtime, "EDGE_TTS_TIMEOUT_MS");
100
+ return {
101
+ voice:
102
+ getSetting(runtime, "EDGE_TTS_VOICE", DEFAULT_VOICE) ?? DEFAULT_VOICE,
103
+ lang: getSetting(runtime, "EDGE_TTS_LANG", DEFAULT_LANG) ?? DEFAULT_LANG,
104
+ outputFormat:
105
+ getSetting(runtime, "EDGE_TTS_OUTPUT_FORMAT", DEFAULT_OUTPUT_FORMAT) ??
106
+ DEFAULT_OUTPUT_FORMAT,
107
+ rate: getSetting(runtime, "EDGE_TTS_RATE"),
108
+ pitch: getSetting(runtime, "EDGE_TTS_PITCH"),
109
+ volume: getSetting(runtime, "EDGE_TTS_VOLUME"),
110
+ proxy: getSetting(runtime, "EDGE_TTS_PROXY"),
111
+ timeoutMs: timeoutStr
112
+ ? Number.parseInt(timeoutStr, 10)
113
+ : DEFAULT_TIMEOUT_MS,
114
+ };
115
+ }
116
+ function resolveVoice(voice, defaultVoice) {
117
+ if (!voice) return defaultVoice;
118
+ const preset = VOICE_PRESETS[voice.toLowerCase()];
119
+ if (preset) return preset;
120
+ return voice;
121
+ }
122
+ function speedToRate(speed) {
123
+ if (speed === undefined || speed === 1) return;
124
+ const percentage = Math.round((speed - 1) * 100);
125
+ return percentage >= 0 ? `+${percentage}%` : `${percentage}%`;
126
+ }
127
+ function inferExtension(outputFormat) {
128
+ const normalized = outputFormat.toLowerCase();
129
+ if (normalized.includes("webm")) return ".webm";
130
+ if (normalized.includes("ogg")) return ".ogg";
131
+ if (normalized.includes("opus")) return ".opus";
132
+ if (
133
+ normalized.includes("wav") ||
134
+ normalized.includes("riff") ||
135
+ normalized.includes("pcm")
136
+ ) {
137
+ return ".wav";
138
+ }
139
+ return ".mp3";
140
+ }
141
+ async function generateSpeech(settings, params) {
142
+ const voice = resolveVoice(params.voice, settings.voice);
143
+ const lang = params.lang ?? settings.lang;
144
+ const outputFormat = params.outputFormat ?? settings.outputFormat;
145
+ const rate = params.rate ?? speedToRate(params.speed) ?? settings.rate;
146
+ const pitch = params.pitch ?? settings.pitch;
147
+ const volume = params.volume ?? settings.volume;
148
+ import_core.logger.debug(
149
+ `[EdgeTTS] Generating speech with voice: ${voice}, lang: ${lang}`,
150
+ );
151
+ const tts = new import_node_edge_tts.EdgeTTS({
152
+ voice,
153
+ lang,
154
+ outputFormat,
155
+ saveSubtitles: false,
156
+ proxy: settings.proxy,
157
+ rate,
158
+ pitch,
159
+ volume,
160
+ timeout: settings.timeoutMs,
161
+ });
162
+ const tempDir = import_node_fs.mkdtempSync(
163
+ import_node_path.default.join(import_node_os.tmpdir(), "edge-tts-"),
164
+ );
165
+ const extension = inferExtension(outputFormat);
166
+ const outputPath = import_node_path.default.join(
167
+ tempDir,
168
+ `speech${extension}`,
169
+ );
170
+ try {
171
+ await tts.ttsPromise(params.text, outputPath);
172
+ const audioBuffer = import_node_fs.readFileSync(outputPath);
173
+ return audioBuffer;
174
+ } finally {
175
+ try {
176
+ import_node_fs.rmSync(tempDir, { recursive: true, force: true });
177
+ } catch {}
178
+ }
179
+ }
180
+ var edgeTTSPlugin = {
181
+ name: "edge-tts",
182
+ description:
183
+ "Free text-to-speech synthesis using Microsoft Edge TTS - no API key required, high-quality neural voices",
184
+ models: {
185
+ [import_core.ModelType.TEXT_TO_SPEECH]: async (runtime, input) => {
186
+ const params = typeof input === "string" ? { text: input } : input;
187
+ const settings = getEdgeTTSSettings(runtime);
188
+ import_core.logger.log(
189
+ `[EdgeTTS] Using TEXT_TO_SPEECH with voice: ${settings.voice}`,
190
+ );
191
+ if (!params.text || params.text.trim().length === 0) {
192
+ throw new Error("TEXT_TO_SPEECH requires non-empty text");
193
+ }
194
+ if (params.text.length > 5000) {
195
+ throw new Error("TEXT_TO_SPEECH text exceeds 5000 character limit");
196
+ }
197
+ try {
198
+ const audioBuffer = await generateSpeech(settings, params);
199
+ return audioBuffer;
200
+ } catch (error) {
201
+ const msg = error instanceof Error ? error.message : String(error);
202
+ import_core.logger.error(`EdgeTTS model error: ${msg}`);
203
+ throw error instanceof Error ? error : new Error(msg);
204
+ }
205
+ },
206
+ },
207
+ tests: [
208
+ {
209
+ name: "test edge tts",
210
+ tests: [
211
+ {
212
+ name: "Edge TTS settings validation",
213
+ fn: async (runtime) => {
214
+ const settings = getEdgeTTSSettings(runtime);
215
+ if (!settings.voice) {
216
+ throw new Error("Missing voice configuration");
217
+ }
218
+ if (!settings.lang) {
219
+ throw new Error("Missing language configuration");
220
+ }
221
+ if (!settings.outputFormat) {
222
+ throw new Error("Missing output format configuration");
223
+ }
224
+ import_core.logger.success(
225
+ "Edge TTS settings validated successfully",
226
+ );
227
+ },
228
+ },
229
+ {
230
+ name: "Edge TTS voice preset mapping",
231
+ fn: async (_runtime) => {
232
+ const testCases = [
233
+ { input: "alloy", expected: "en-US-GuyNeural" },
234
+ { input: "nova", expected: "en-US-JennyNeural" },
235
+ { input: "shimmer", expected: "en-US-AriaNeural" },
236
+ {
237
+ input: "en-US-MichelleNeural",
238
+ expected: "en-US-MichelleNeural",
239
+ },
240
+ ];
241
+ for (const tc of testCases) {
242
+ const result = resolveVoice(tc.input, DEFAULT_VOICE);
243
+ if (result !== tc.expected) {
244
+ throw new Error(
245
+ `Voice preset mapping failed: ${tc.input} -> ${result}, expected ${tc.expected}`,
246
+ );
247
+ }
248
+ }
249
+ import_core.logger.success(
250
+ "Voice preset mapping validated successfully",
251
+ );
252
+ },
253
+ },
254
+ {
255
+ name: "Edge TTS speed to rate conversion",
256
+ fn: async (_runtime) => {
257
+ const testCases = [
258
+ { speed: 1, expected: undefined },
259
+ { speed: 1.5, expected: "+50%" },
260
+ { speed: 0.75, expected: "-25%" },
261
+ { speed: 2, expected: "+100%" },
262
+ ];
263
+ for (const tc of testCases) {
264
+ const result = speedToRate(tc.speed);
265
+ if (result !== tc.expected) {
266
+ throw new Error(
267
+ `Speed conversion failed: ${tc.speed} -> ${result}, expected ${tc.expected}`,
268
+ );
269
+ }
270
+ }
271
+ import_core.logger.success(
272
+ "Speed to rate conversion validated successfully",
273
+ );
274
+ },
275
+ },
276
+ {
277
+ name: "Edge TTS generation (live test)",
278
+ fn: async (runtime) => {
279
+ const testText = "Hello, this is a test of Edge TTS.";
280
+ try {
281
+ const audioBuffer = await runtime.useModel(
282
+ import_core.ModelType.TEXT_TO_SPEECH,
283
+ testText,
284
+ );
285
+ if (!audioBuffer || audioBuffer.length === 0) {
286
+ throw new Error("Received empty audio buffer");
287
+ }
288
+ import_core.logger.success(
289
+ `Edge TTS generation successful: ${audioBuffer.length} bytes`,
290
+ );
291
+ } catch (error) {
292
+ const msg =
293
+ error instanceof Error ? error.message : String(error);
294
+ if (msg.includes("ENOTFOUND") || msg.includes("network")) {
295
+ import_core.logger.warn(
296
+ `Edge TTS live test skipped (network unavailable): ${msg}`,
297
+ );
298
+ return;
299
+ }
300
+ throw error;
301
+ }
302
+ },
303
+ },
304
+ ],
305
+ },
306
+ ],
307
+ };
308
+ var src_default = edgeTTSPlugin;
309
+ var _test = {
310
+ resolveVoice,
311
+ speedToRate,
312
+ inferExtension,
313
+ getEdgeTTSSettings,
314
+ };
315
+
316
+ //# debugId=302D9C6A4A9C013564756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/index.ts"],
4
+ "sourcesContent": [
5
+ "import { mkdtempSync, readFileSync, rmSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\nimport { type IAgentRuntime, logger, ModelType, type Plugin } from \"@elizaos/core\";\nimport { EdgeTTS } from \"node-edge-tts\";\n\n/**\n * Edge TTS voice settings configuration\n */\ninterface EdgeTTSSettings {\n voice: string;\n lang: string;\n outputFormat: string;\n rate?: string;\n pitch?: string;\n volume?: string;\n proxy?: string;\n timeoutMs: number;\n}\n\n/**\n * Extended TTS params with Edge-specific options\n */\ninterface EdgeTTSParams {\n text: string;\n voice?: string;\n speed?: number;\n /** Edge TTS specific: language code */\n lang?: string;\n /** Edge TTS specific: output format */\n outputFormat?: string;\n /** Edge TTS specific: rate adjustment (e.g., +10%, -5%) */\n rate?: string;\n /** Edge TTS specific: pitch adjustment (e.g., +5Hz, -10Hz) */\n pitch?: string;\n /** Edge TTS specific: volume adjustment (e.g., +20%, -10%) */\n volume?: string;\n}\n\n// Default voice configurations\nconst DEFAULT_VOICE = \"en-US-MichelleNeural\";\nconst DEFAULT_LANG = \"en-US\";\nconst DEFAULT_OUTPUT_FORMAT = \"audio-24khz-48kbitrate-mono-mp3\";\nconst DEFAULT_TIMEOUT_MS = 30000;\n\n// Voice presets mapping common voice names to Edge TTS voices\nconst VOICE_PRESETS: Record<string, string> = {\n // Generic voices (map to good defaults)\n alloy: \"en-US-GuyNeural\",\n echo: \"en-US-ChristopherNeural\",\n fable: \"en-GB-RyanNeural\",\n onyx: \"en-US-DavisNeural\",\n nova: \"en-US-JennyNeural\",\n shimmer: \"en-US-AriaNeural\",\n // Direct Edge TTS voice names pass through\n};\n\nfunction getSetting(runtime: IAgentRuntime, key: string, fallback?: string): string | undefined {\n const envValue =\n typeof process !== \"undefined\" && (process as { env?: Record<string, string> }).env\n ? (process as { env: Record<string, string> }).env[key]\n : undefined;\n return (runtime.getSetting(key) as string | undefined) ?? envValue ?? fallback;\n}\n\nfunction getEdgeTTSSettings(runtime: IAgentRuntime): EdgeTTSSettings {\n const timeoutStr = getSetting(runtime, \"EDGE_TTS_TIMEOUT_MS\");\n return {\n voice: getSetting(runtime, \"EDGE_TTS_VOICE\", DEFAULT_VOICE) ?? DEFAULT_VOICE,\n lang: getSetting(runtime, \"EDGE_TTS_LANG\", DEFAULT_LANG) ?? DEFAULT_LANG,\n outputFormat:\n getSetting(runtime, \"EDGE_TTS_OUTPUT_FORMAT\", DEFAULT_OUTPUT_FORMAT) ?? DEFAULT_OUTPUT_FORMAT,\n rate: getSetting(runtime, \"EDGE_TTS_RATE\"),\n pitch: getSetting(runtime, \"EDGE_TTS_PITCH\"),\n volume: getSetting(runtime, \"EDGE_TTS_VOLUME\"),\n proxy: getSetting(runtime, \"EDGE_TTS_PROXY\"),\n timeoutMs: timeoutStr ? Number.parseInt(timeoutStr, 10) : DEFAULT_TIMEOUT_MS,\n };\n}\n\n/**\n * Resolve voice name - handles OpenAI-style voice names and Edge TTS voice IDs\n */\nfunction resolveVoice(voice: string | undefined, defaultVoice: string): string {\n if (!voice) return defaultVoice;\n\n // Check if it's a preset name\n const preset = VOICE_PRESETS[voice.toLowerCase()];\n if (preset) return preset;\n\n // Assume it's a direct Edge TTS voice ID\n return voice;\n}\n\n/**\n * Convert speed multiplier to Edge TTS rate string\n * speed: 1.0 = normal, 0.5 = half speed, 2.0 = double speed\n */\nfunction speedToRate(speed: number | undefined): string | undefined {\n if (speed === undefined || speed === 1.0) return undefined;\n const percentage = Math.round((speed - 1) * 100);\n return percentage >= 0 ? `+${percentage}%` : `${percentage}%`;\n}\n\n/**\n * Infer file extension from Edge TTS output format\n */\nfunction inferExtension(outputFormat: string): string {\n const normalized = outputFormat.toLowerCase();\n if (normalized.includes(\"webm\")) return \".webm\";\n if (normalized.includes(\"ogg\")) return \".ogg\";\n if (normalized.includes(\"opus\")) return \".opus\";\n if (normalized.includes(\"wav\") || normalized.includes(\"riff\") || normalized.includes(\"pcm\")) {\n return \".wav\";\n }\n return \".mp3\";\n}\n\n/**\n * Generate speech using Microsoft Edge TTS\n */\nasync function generateSpeech(settings: EdgeTTSSettings, params: EdgeTTSParams): Promise<Buffer> {\n const voice = resolveVoice(params.voice, settings.voice);\n const lang = params.lang ?? settings.lang;\n const outputFormat = params.outputFormat ?? settings.outputFormat;\n const rate = params.rate ?? speedToRate(params.speed) ?? settings.rate;\n const pitch = params.pitch ?? settings.pitch;\n const volume = params.volume ?? settings.volume;\n\n logger.debug(`[EdgeTTS] Generating speech with voice: ${voice}, lang: ${lang}`);\n\n const tts = new EdgeTTS({\n voice,\n lang,\n outputFormat,\n saveSubtitles: false,\n proxy: settings.proxy,\n rate,\n pitch,\n volume,\n timeout: settings.timeoutMs,\n });\n\n // Create temp directory for output\n const tempDir = mkdtempSync(path.join(tmpdir(), \"edge-tts-\"));\n const extension = inferExtension(outputFormat);\n const outputPath = path.join(tempDir, `speech${extension}`);\n\n try {\n await tts.ttsPromise(params.text, outputPath);\n const audioBuffer = readFileSync(outputPath);\n return audioBuffer;\n } finally {\n // Cleanup temp directory\n try {\n rmSync(tempDir, { recursive: true, force: true });\n } catch {\n // Ignore cleanup errors\n }\n }\n}\n\n/**\n * Edge TTS Plugin for ElizaOS\n *\n * Provides free text-to-speech synthesis using Microsoft Edge's TTS service.\n * No API key required - uses the same TTS engine as Microsoft Edge browser.\n *\n * Features:\n * - High-quality neural voices\n * - Multiple languages and locales\n * - Adjustable rate, pitch, and volume\n * - No API key or payment required\n *\n * Optional environment variables:\n * - EDGE_TTS_VOICE: Voice ID (default: en-US-MichelleNeural)\n * - EDGE_TTS_LANG: Language code (default: en-US)\n * - EDGE_TTS_OUTPUT_FORMAT: Output format (default: audio-24khz-48kbitrate-mono-mp3)\n * - EDGE_TTS_RATE: Speech rate adjustment (e.g., +10%, -5%)\n * - EDGE_TTS_PITCH: Pitch adjustment (e.g., +5Hz, -10Hz)\n * - EDGE_TTS_VOLUME: Volume adjustment (e.g., +20%, -10%)\n * - EDGE_TTS_PROXY: HTTP proxy URL\n * - EDGE_TTS_TIMEOUT_MS: Request timeout (default: 30000)\n *\n * Popular voices:\n * - en-US-MichelleNeural (female, US English)\n * - en-US-GuyNeural (male, US English)\n * - en-US-JennyNeural (female, US English)\n * - en-US-AriaNeural (female, US English)\n * - en-GB-SoniaNeural (female, UK English)\n * - en-GB-RyanNeural (male, UK English)\n * - de-DE-KatjaNeural (female, German)\n * - fr-FR-DeniseNeural (female, French)\n * - es-ES-ElviraNeural (female, Spanish)\n * - ja-JP-NanamiNeural (female, Japanese)\n * - zh-CN-XiaoxiaoNeural (female, Chinese)\n */\nexport const edgeTTSPlugin: Plugin = {\n name: \"edge-tts\",\n description:\n \"Free text-to-speech synthesis using Microsoft Edge TTS - no API key required, high-quality neural voices\",\n models: {\n [ModelType.TEXT_TO_SPEECH]: async (\n runtime: IAgentRuntime,\n input: string | EdgeTTSParams\n ): Promise<Buffer | ArrayBuffer | Uint8Array> => {\n const params: EdgeTTSParams = typeof input === \"string\" ? { text: input } : input;\n const settings = getEdgeTTSSettings(runtime);\n\n logger.log(`[EdgeTTS] Using TEXT_TO_SPEECH with voice: ${settings.voice}`);\n\n if (!params.text || params.text.trim().length === 0) {\n throw new Error(\"TEXT_TO_SPEECH requires non-empty text\");\n }\n\n // Edge TTS has a practical limit around 5000 characters\n if (params.text.length > 5000) {\n throw new Error(\"TEXT_TO_SPEECH text exceeds 5000 character limit\");\n }\n\n try {\n const audioBuffer = await generateSpeech(settings, params);\n return audioBuffer;\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n logger.error(`EdgeTTS model error: ${msg}`);\n throw error instanceof Error ? error : new Error(msg);\n }\n },\n },\n tests: [\n {\n name: \"test edge tts\",\n tests: [\n {\n name: \"Edge TTS settings validation\",\n fn: async (runtime: IAgentRuntime) => {\n const settings = getEdgeTTSSettings(runtime);\n\n if (!settings.voice) {\n throw new Error(\"Missing voice configuration\");\n }\n\n if (!settings.lang) {\n throw new Error(\"Missing language configuration\");\n }\n\n if (!settings.outputFormat) {\n throw new Error(\"Missing output format configuration\");\n }\n\n logger.success(\"Edge TTS settings validated successfully\");\n },\n },\n {\n name: \"Edge TTS voice preset mapping\",\n fn: async (_runtime: IAgentRuntime) => {\n // Test that OpenAI-style voice names map correctly\n const testCases = [\n { input: \"alloy\", expected: \"en-US-GuyNeural\" },\n { input: \"nova\", expected: \"en-US-JennyNeural\" },\n { input: \"shimmer\", expected: \"en-US-AriaNeural\" },\n {\n input: \"en-US-MichelleNeural\",\n expected: \"en-US-MichelleNeural\",\n },\n ];\n\n for (const tc of testCases) {\n const result = resolveVoice(tc.input, DEFAULT_VOICE);\n if (result !== tc.expected) {\n throw new Error(\n `Voice preset mapping failed: ${tc.input} -> ${result}, expected ${tc.expected}`\n );\n }\n }\n\n logger.success(\"Voice preset mapping validated successfully\");\n },\n },\n {\n name: \"Edge TTS speed to rate conversion\",\n fn: async (_runtime: IAgentRuntime) => {\n const testCases = [\n { speed: 1.0, expected: undefined },\n { speed: 1.5, expected: \"+50%\" },\n { speed: 0.75, expected: \"-25%\" },\n { speed: 2.0, expected: \"+100%\" },\n ];\n\n for (const tc of testCases) {\n const result = speedToRate(tc.speed);\n if (result !== tc.expected) {\n throw new Error(\n `Speed conversion failed: ${tc.speed} -> ${result}, expected ${tc.expected}`\n );\n }\n }\n\n logger.success(\"Speed to rate conversion validated successfully\");\n },\n },\n {\n name: \"Edge TTS generation (live test)\",\n fn: async (runtime: IAgentRuntime) => {\n const testText = \"Hello, this is a test of Edge TTS.\";\n\n try {\n const audioBuffer = (await runtime.useModel(ModelType.TEXT_TO_SPEECH, testText)) as\n | Buffer\n | Uint8Array;\n\n if (!audioBuffer || audioBuffer.length === 0) {\n throw new Error(\"Received empty audio buffer\");\n }\n\n logger.success(`Edge TTS generation successful: ${audioBuffer.length} bytes`);\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n // Edge TTS might fail in CI environments without network\n if (msg.includes(\"ENOTFOUND\") || msg.includes(\"network\")) {\n logger.warn(`Edge TTS live test skipped (network unavailable): ${msg}`);\n return;\n }\n throw error;\n }\n },\n },\n ],\n },\n ],\n};\n\nexport default edgeTTSPlugin;\n\n// Re-export types\nexport type { EdgeTTSParams, EdgeTTSSettings };\n\n// Export helper functions for testing\nexport const _test = {\n resolveVoice,\n speedToRate,\n inferExtension,\n getEdgeTTSSettings,\n};\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "302D9C6A4A9C013564756E2164756E21",
9
+ "names": []
10
+ }
@@ -4,51 +4,70 @@ var __defProp = Object.defineProperty;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ function __accessProp(key) {
8
+ return this[key];
9
+ }
10
+ var __toESMCache_node;
11
+ var __toESMCache_esm;
7
12
  var __toESM = (mod, isNodeMode, target) => {
13
+ var canCache = mod != null && typeof mod === "object";
14
+ if (canCache) {
15
+ var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
16
+ var cached = cache.get(mod);
17
+ if (cached)
18
+ return cached;
19
+ }
8
20
  target = mod != null ? __create(__getProtoOf(mod)) : {};
9
21
  const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
22
  for (let key of __getOwnPropNames(mod))
11
23
  if (!__hasOwnProp.call(to, key))
12
24
  __defProp(to, key, {
13
- get: () => mod[key],
25
+ get: __accessProp.bind(mod, key),
14
26
  enumerable: true
15
27
  });
28
+ if (canCache)
29
+ cache.set(mod, to);
16
30
  return to;
17
31
  };
18
- var __moduleCache = /* @__PURE__ */ new WeakMap;
19
32
  var __toCommonJS = (from) => {
20
- var entry = __moduleCache.get(from), desc;
33
+ var entry = (__moduleCache ??= new WeakMap).get(from), desc;
21
34
  if (entry)
22
35
  return entry;
23
36
  entry = __defProp({}, "__esModule", { value: true });
24
- if (from && typeof from === "object" || typeof from === "function")
25
- __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
26
- get: () => from[key],
27
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
28
- }));
37
+ if (from && typeof from === "object" || typeof from === "function") {
38
+ for (var key of __getOwnPropNames(from))
39
+ if (!__hasOwnProp.call(entry, key))
40
+ __defProp(entry, key, {
41
+ get: __accessProp.bind(from, key),
42
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
43
+ });
44
+ }
29
45
  __moduleCache.set(from, entry);
30
46
  return entry;
31
47
  };
48
+ var __moduleCache;
49
+ var __returnValue = (v) => v;
50
+ function __exportSetter(name, newValue) {
51
+ this[name] = __returnValue.bind(null, newValue);
52
+ }
32
53
  var __export = (target, all) => {
33
54
  for (var name in all)
34
55
  __defProp(target, name, {
35
56
  get: all[name],
36
57
  enumerable: true,
37
58
  configurable: true,
38
- set: (newValue) => all[name] = () => newValue
59
+ set: __exportSetter.bind(all, name)
39
60
  });
40
61
  };
41
62
 
42
- // src/index.node.ts
43
- var exports_index_node = {};
44
- __export(exports_index_node, {
63
+ // src/index.ts
64
+ var exports_src = {};
65
+ __export(exports_src, {
45
66
  edgeTTSPlugin: () => edgeTTSPlugin,
46
67
  default: () => src_default,
47
68
  _test: () => _test
48
69
  });
49
- module.exports = __toCommonJS(exports_index_node);
50
-
51
- // src/index.ts
70
+ module.exports = __toCommonJS(exports_src);
52
71
  var import_node_fs = require("node:fs");
53
72
  var import_node_os = require("node:os");
54
73
  var import_node_path = __toESM(require("node:path"));
@@ -145,12 +164,20 @@ async function generateSpeech(settings, params) {
145
164
  var edgeTTSPlugin = {
146
165
  name: "edge-tts",
147
166
  description: "Free text-to-speech synthesis using Microsoft Edge TTS - no API key required, high-quality neural voices",
167
+ autoEnable: {
168
+ shouldEnable: (env, config) => {
169
+ if (env.ELIZA_CLOUD_PROVISIONED === "1")
170
+ return true;
171
+ const f = config?.features?.tts;
172
+ return f === true || typeof f === "object" && f !== null && f.enabled !== false;
173
+ }
174
+ },
148
175
  models: {
149
176
  [import_core.ModelType.TEXT_TO_SPEECH]: async (runtime, input) => {
150
177
  const params = typeof input === "string" ? { text: input } : input;
151
178
  const settings = getEdgeTTSSettings(runtime);
152
179
  import_core.logger.log(`[EdgeTTS] Using TEXT_TO_SPEECH with voice: ${settings.voice}`);
153
- if (!params.text || params.text.trim().length === 0) {
180
+ if (params.text.trim().length === 0) {
154
181
  throw new Error("TEXT_TO_SPEECH requires non-empty text");
155
182
  }
156
183
  if (params.text.length > 5000) {
@@ -257,4 +284,4 @@ var _test = {
257
284
  getEdgeTTSSettings
258
285
  };
259
286
 
260
- //# debugId=44DEBD6EBE84FDA064756E2164756E21
287
+ //# debugId=DC587B57E982FAAA64756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../src/index.ts"],
4
4
  "sourcesContent": [
5
- "import { mkdtempSync, readFileSync, rmSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\nimport { type IAgentRuntime, logger, ModelType, type Plugin } from \"@elizaos/core\";\nimport { EdgeTTS } from \"node-edge-tts\";\n\n/**\n * Edge TTS voice settings configuration\n */\ninterface EdgeTTSSettings {\n voice: string;\n lang: string;\n outputFormat: string;\n rate?: string;\n pitch?: string;\n volume?: string;\n proxy?: string;\n timeoutMs: number;\n}\n\n/**\n * Extended TTS params with Edge-specific options\n */\ninterface EdgeTTSParams {\n text: string;\n voice?: string;\n speed?: number;\n /** Edge TTS specific: language code */\n lang?: string;\n /** Edge TTS specific: output format */\n outputFormat?: string;\n /** Edge TTS specific: rate adjustment (e.g., +10%, -5%) */\n rate?: string;\n /** Edge TTS specific: pitch adjustment (e.g., +5Hz, -10Hz) */\n pitch?: string;\n /** Edge TTS specific: volume adjustment (e.g., +20%, -10%) */\n volume?: string;\n}\n\n// Default voice configurations\nconst DEFAULT_VOICE = \"en-US-MichelleNeural\";\nconst DEFAULT_LANG = \"en-US\";\nconst DEFAULT_OUTPUT_FORMAT = \"audio-24khz-48kbitrate-mono-mp3\";\nconst DEFAULT_TIMEOUT_MS = 30000;\n\n// Voice presets mapping common voice names to Edge TTS voices\nconst VOICE_PRESETS: Record<string, string> = {\n // Generic voices (map to good defaults)\n alloy: \"en-US-GuyNeural\",\n echo: \"en-US-ChristopherNeural\",\n fable: \"en-GB-RyanNeural\",\n onyx: \"en-US-DavisNeural\",\n nova: \"en-US-JennyNeural\",\n shimmer: \"en-US-AriaNeural\",\n // Direct Edge TTS voice names pass through\n};\n\nfunction getSetting(runtime: IAgentRuntime, key: string, fallback?: string): string | undefined {\n const envValue =\n typeof process !== \"undefined\" && (process as { env?: Record<string, string> }).env\n ? (process as { env: Record<string, string> }).env[key]\n : undefined;\n return (runtime.getSetting(key) as string | undefined) ?? envValue ?? fallback;\n}\n\nfunction getEdgeTTSSettings(runtime: IAgentRuntime): EdgeTTSSettings {\n const timeoutStr = getSetting(runtime, \"EDGE_TTS_TIMEOUT_MS\");\n return {\n voice: getSetting(runtime, \"EDGE_TTS_VOICE\", DEFAULT_VOICE) ?? DEFAULT_VOICE,\n lang: getSetting(runtime, \"EDGE_TTS_LANG\", DEFAULT_LANG) ?? DEFAULT_LANG,\n outputFormat:\n getSetting(runtime, \"EDGE_TTS_OUTPUT_FORMAT\", DEFAULT_OUTPUT_FORMAT) ?? DEFAULT_OUTPUT_FORMAT,\n rate: getSetting(runtime, \"EDGE_TTS_RATE\"),\n pitch: getSetting(runtime, \"EDGE_TTS_PITCH\"),\n volume: getSetting(runtime, \"EDGE_TTS_VOLUME\"),\n proxy: getSetting(runtime, \"EDGE_TTS_PROXY\"),\n timeoutMs: timeoutStr ? Number.parseInt(timeoutStr, 10) : DEFAULT_TIMEOUT_MS,\n };\n}\n\n/**\n * Resolve voice name - handles OpenAI-style voice names and Edge TTS voice IDs\n */\nfunction resolveVoice(voice: string | undefined, defaultVoice: string): string {\n if (!voice) return defaultVoice;\n\n // Check if it's a preset name\n const preset = VOICE_PRESETS[voice.toLowerCase()];\n if (preset) return preset;\n\n // Assume it's a direct Edge TTS voice ID\n return voice;\n}\n\n/**\n * Convert speed multiplier to Edge TTS rate string\n * speed: 1.0 = normal, 0.5 = half speed, 2.0 = double speed\n */\nfunction speedToRate(speed: number | undefined): string | undefined {\n if (speed === undefined || speed === 1.0) return undefined;\n const percentage = Math.round((speed - 1) * 100);\n return percentage >= 0 ? `+${percentage}%` : `${percentage}%`;\n}\n\n/**\n * Infer file extension from Edge TTS output format\n */\nfunction inferExtension(outputFormat: string): string {\n const normalized = outputFormat.toLowerCase();\n if (normalized.includes(\"webm\")) return \".webm\";\n if (normalized.includes(\"ogg\")) return \".ogg\";\n if (normalized.includes(\"opus\")) return \".opus\";\n if (normalized.includes(\"wav\") || normalized.includes(\"riff\") || normalized.includes(\"pcm\")) {\n return \".wav\";\n }\n return \".mp3\";\n}\n\n/**\n * Generate speech using Microsoft Edge TTS\n */\nasync function generateSpeech(settings: EdgeTTSSettings, params: EdgeTTSParams): Promise<Buffer> {\n const voice = resolveVoice(params.voice, settings.voice);\n const lang = params.lang ?? settings.lang;\n const outputFormat = params.outputFormat ?? settings.outputFormat;\n const rate = params.rate ?? speedToRate(params.speed) ?? settings.rate;\n const pitch = params.pitch ?? settings.pitch;\n const volume = params.volume ?? settings.volume;\n\n logger.debug(`[EdgeTTS] Generating speech with voice: ${voice}, lang: ${lang}`);\n\n const tts = new EdgeTTS({\n voice,\n lang,\n outputFormat,\n saveSubtitles: false,\n proxy: settings.proxy,\n rate,\n pitch,\n volume,\n timeout: settings.timeoutMs,\n });\n\n // Create temp directory for output\n const tempDir = mkdtempSync(path.join(tmpdir(), \"edge-tts-\"));\n const extension = inferExtension(outputFormat);\n const outputPath = path.join(tempDir, `speech${extension}`);\n\n try {\n await tts.ttsPromise(params.text, outputPath);\n const audioBuffer = readFileSync(outputPath);\n return audioBuffer;\n } finally {\n // Cleanup temp directory\n try {\n rmSync(tempDir, { recursive: true, force: true });\n } catch {\n // Ignore cleanup errors\n }\n }\n}\n\n/**\n * Edge TTS Plugin for ElizaOS\n *\n * Provides free text-to-speech synthesis using Microsoft Edge's TTS service.\n * No API key required - uses the same TTS engine as Microsoft Edge browser.\n *\n * Features:\n * - High-quality neural voices\n * - Multiple languages and locales\n * - Adjustable rate, pitch, and volume\n * - No API key or payment required\n *\n * Optional environment variables:\n * - EDGE_TTS_VOICE: Voice ID (default: en-US-MichelleNeural)\n * - EDGE_TTS_LANG: Language code (default: en-US)\n * - EDGE_TTS_OUTPUT_FORMAT: Output format (default: audio-24khz-48kbitrate-mono-mp3)\n * - EDGE_TTS_RATE: Speech rate adjustment (e.g., +10%, -5%)\n * - EDGE_TTS_PITCH: Pitch adjustment (e.g., +5Hz, -10Hz)\n * - EDGE_TTS_VOLUME: Volume adjustment (e.g., +20%, -10%)\n * - EDGE_TTS_PROXY: HTTP proxy URL\n * - EDGE_TTS_TIMEOUT_MS: Request timeout (default: 30000)\n *\n * Popular voices:\n * - en-US-MichelleNeural (female, US English)\n * - en-US-GuyNeural (male, US English)\n * - en-US-JennyNeural (female, US English)\n * - en-US-AriaNeural (female, US English)\n * - en-GB-SoniaNeural (female, UK English)\n * - en-GB-RyanNeural (male, UK English)\n * - de-DE-KatjaNeural (female, German)\n * - fr-FR-DeniseNeural (female, French)\n * - es-ES-ElviraNeural (female, Spanish)\n * - ja-JP-NanamiNeural (female, Japanese)\n * - zh-CN-XiaoxiaoNeural (female, Chinese)\n */\nexport const edgeTTSPlugin: Plugin = {\n name: \"edge-tts\",\n description:\n \"Free text-to-speech synthesis using Microsoft Edge TTS - no API key required, high-quality neural voices\",\n models: {\n [ModelType.TEXT_TO_SPEECH]: async (\n runtime: IAgentRuntime,\n input: string | EdgeTTSParams\n ): Promise<Buffer | ArrayBuffer | Uint8Array> => {\n const params: EdgeTTSParams = typeof input === \"string\" ? { text: input } : input;\n const settings = getEdgeTTSSettings(runtime);\n\n logger.log(`[EdgeTTS] Using TEXT_TO_SPEECH with voice: ${settings.voice}`);\n\n if (!params.text || params.text.trim().length === 0) {\n throw new Error(\"TEXT_TO_SPEECH requires non-empty text\");\n }\n\n // Edge TTS has a practical limit around 5000 characters\n if (params.text.length > 5000) {\n throw new Error(\"TEXT_TO_SPEECH text exceeds 5000 character limit\");\n }\n\n try {\n const audioBuffer = await generateSpeech(settings, params);\n return audioBuffer;\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n logger.error(`EdgeTTS model error: ${msg}`);\n throw error instanceof Error ? error : new Error(msg);\n }\n },\n },\n tests: [\n {\n name: \"test edge tts\",\n tests: [\n {\n name: \"Edge TTS settings validation\",\n fn: async (runtime: IAgentRuntime) => {\n const settings = getEdgeTTSSettings(runtime);\n\n if (!settings.voice) {\n throw new Error(\"Missing voice configuration\");\n }\n\n if (!settings.lang) {\n throw new Error(\"Missing language configuration\");\n }\n\n if (!settings.outputFormat) {\n throw new Error(\"Missing output format configuration\");\n }\n\n logger.success(\"Edge TTS settings validated successfully\");\n },\n },\n {\n name: \"Edge TTS voice preset mapping\",\n fn: async (_runtime: IAgentRuntime) => {\n // Test that OpenAI-style voice names map correctly\n const testCases = [\n { input: \"alloy\", expected: \"en-US-GuyNeural\" },\n { input: \"nova\", expected: \"en-US-JennyNeural\" },\n { input: \"shimmer\", expected: \"en-US-AriaNeural\" },\n {\n input: \"en-US-MichelleNeural\",\n expected: \"en-US-MichelleNeural\",\n },\n ];\n\n for (const tc of testCases) {\n const result = resolveVoice(tc.input, DEFAULT_VOICE);\n if (result !== tc.expected) {\n throw new Error(\n `Voice preset mapping failed: ${tc.input} -> ${result}, expected ${tc.expected}`\n );\n }\n }\n\n logger.success(\"Voice preset mapping validated successfully\");\n },\n },\n {\n name: \"Edge TTS speed to rate conversion\",\n fn: async (_runtime: IAgentRuntime) => {\n const testCases = [\n { speed: 1.0, expected: undefined },\n { speed: 1.5, expected: \"+50%\" },\n { speed: 0.75, expected: \"-25%\" },\n { speed: 2.0, expected: \"+100%\" },\n ];\n\n for (const tc of testCases) {\n const result = speedToRate(tc.speed);\n if (result !== tc.expected) {\n throw new Error(\n `Speed conversion failed: ${tc.speed} -> ${result}, expected ${tc.expected}`\n );\n }\n }\n\n logger.success(\"Speed to rate conversion validated successfully\");\n },\n },\n {\n name: \"Edge TTS generation (live test)\",\n fn: async (runtime: IAgentRuntime) => {\n const testText = \"Hello, this is a test of Edge TTS.\";\n\n try {\n const audioBuffer = (await runtime.useModel(ModelType.TEXT_TO_SPEECH, testText)) as\n | Buffer\n | Uint8Array;\n\n if (!audioBuffer || audioBuffer.length === 0) {\n throw new Error(\"Received empty audio buffer\");\n }\n\n logger.success(`Edge TTS generation successful: ${audioBuffer.length} bytes`);\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n // Edge TTS might fail in CI environments without network\n if (msg.includes(\"ENOTFOUND\") || msg.includes(\"network\")) {\n logger.warn(`Edge TTS live test skipped (network unavailable): ${msg}`);\n return;\n }\n throw error;\n }\n },\n },\n ],\n },\n ],\n};\n\nexport default edgeTTSPlugin;\n\n// Re-export types\nexport type { EdgeTTSSettings, EdgeTTSParams };\n\n// Export helper functions for testing\nexport const _test = {\n resolveVoice,\n speedToRate,\n inferExtension,\n getEdgeTTSSettings,\n};\n"
5
+ "import { mkdtempSync, readFileSync, rmSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\nimport { type IAgentRuntime, logger, ModelType, type Plugin } from \"@elizaos/core\";\nimport { EdgeTTS } from \"node-edge-tts\";\n\n/**\n * Edge TTS voice settings configuration\n */\ninterface EdgeTTSSettings {\n voice: string;\n lang: string;\n outputFormat: string;\n rate?: string;\n pitch?: string;\n volume?: string;\n proxy?: string;\n timeoutMs: number;\n}\n\n/**\n * Extended TTS params with Edge-specific options\n */\ninterface EdgeTTSParams {\n text: string;\n voice?: string;\n speed?: number;\n /** Edge TTS specific: language code */\n lang?: string;\n /** Edge TTS specific: output format */\n outputFormat?: string;\n /** Edge TTS specific: rate adjustment (e.g., +10%, -5%) */\n rate?: string;\n /** Edge TTS specific: pitch adjustment (e.g., +5Hz, -10Hz) */\n pitch?: string;\n /** Edge TTS specific: volume adjustment (e.g., +20%, -10%) */\n volume?: string;\n}\n\n// Default voice configurations\nconst DEFAULT_VOICE = \"en-US-MichelleNeural\";\nconst DEFAULT_LANG = \"en-US\";\nconst DEFAULT_OUTPUT_FORMAT = \"audio-24khz-48kbitrate-mono-mp3\";\nconst DEFAULT_TIMEOUT_MS = 30000;\n\n// Voice presets mapping common voice names to Edge TTS voices\nconst VOICE_PRESETS: Record<string, string> = {\n // Generic voices (map to good defaults)\n alloy: \"en-US-GuyNeural\",\n echo: \"en-US-ChristopherNeural\",\n fable: \"en-GB-RyanNeural\",\n onyx: \"en-US-DavisNeural\",\n nova: \"en-US-JennyNeural\",\n shimmer: \"en-US-AriaNeural\",\n // Direct Edge TTS voice names pass through\n};\n\nfunction getSetting(runtime: IAgentRuntime, key: string, fallback?: string): string | undefined {\n const envValue =\n typeof process !== \"undefined\" && (process as { env?: Record<string, string> }).env\n ? (process as { env: Record<string, string> }).env[key]\n : undefined;\n return (runtime.getSetting(key) as string | undefined) ?? envValue ?? fallback;\n}\n\nfunction getEdgeTTSSettings(runtime: IAgentRuntime): EdgeTTSSettings {\n const timeoutStr = getSetting(runtime, \"EDGE_TTS_TIMEOUT_MS\");\n return {\n voice: getSetting(runtime, \"EDGE_TTS_VOICE\", DEFAULT_VOICE) ?? DEFAULT_VOICE,\n lang: getSetting(runtime, \"EDGE_TTS_LANG\", DEFAULT_LANG) ?? DEFAULT_LANG,\n outputFormat:\n getSetting(runtime, \"EDGE_TTS_OUTPUT_FORMAT\", DEFAULT_OUTPUT_FORMAT) ?? DEFAULT_OUTPUT_FORMAT,\n rate: getSetting(runtime, \"EDGE_TTS_RATE\"),\n pitch: getSetting(runtime, \"EDGE_TTS_PITCH\"),\n volume: getSetting(runtime, \"EDGE_TTS_VOLUME\"),\n proxy: getSetting(runtime, \"EDGE_TTS_PROXY\"),\n timeoutMs: timeoutStr ? Number.parseInt(timeoutStr, 10) : DEFAULT_TIMEOUT_MS,\n };\n}\n\n/**\n * Resolve voice name - handles OpenAI-style voice names and Edge TTS voice IDs\n */\nfunction resolveVoice(voice: string | undefined, defaultVoice: string): string {\n if (!voice) return defaultVoice;\n\n // Check if it's a preset name\n const preset = VOICE_PRESETS[voice.toLowerCase()];\n if (preset) return preset;\n\n // Assume it's a direct Edge TTS voice ID\n return voice;\n}\n\n/**\n * Convert speed multiplier to Edge TTS rate string\n * speed: 1.0 = normal, 0.5 = half speed, 2.0 = double speed\n */\nfunction speedToRate(speed: number | undefined): string | undefined {\n if (speed === undefined || speed === 1.0) return undefined;\n const percentage = Math.round((speed - 1) * 100);\n return percentage >= 0 ? `+${percentage}%` : `${percentage}%`;\n}\n\n/**\n * Infer file extension from Edge TTS output format\n */\nfunction inferExtension(outputFormat: string): string {\n const normalized = outputFormat.toLowerCase();\n if (normalized.includes(\"webm\")) return \".webm\";\n if (normalized.includes(\"ogg\")) return \".ogg\";\n if (normalized.includes(\"opus\")) return \".opus\";\n if (normalized.includes(\"wav\") || normalized.includes(\"riff\") || normalized.includes(\"pcm\")) {\n return \".wav\";\n }\n return \".mp3\";\n}\n\n/**\n * Generate speech using Microsoft Edge TTS\n */\nasync function generateSpeech(settings: EdgeTTSSettings, params: EdgeTTSParams): Promise<Buffer> {\n const voice = resolveVoice(params.voice, settings.voice);\n const lang = params.lang ?? settings.lang;\n const outputFormat = params.outputFormat ?? settings.outputFormat;\n const rate = params.rate ?? speedToRate(params.speed) ?? settings.rate;\n const pitch = params.pitch ?? settings.pitch;\n const volume = params.volume ?? settings.volume;\n\n logger.debug(`[EdgeTTS] Generating speech with voice: ${voice}, lang: ${lang}`);\n\n const tts = new EdgeTTS({\n voice,\n lang,\n outputFormat,\n saveSubtitles: false,\n proxy: settings.proxy,\n rate,\n pitch,\n volume,\n timeout: settings.timeoutMs,\n });\n\n // Create temp directory for output\n const tempDir = mkdtempSync(path.join(tmpdir(), \"edge-tts-\"));\n const extension = inferExtension(outputFormat);\n const outputPath = path.join(tempDir, `speech${extension}`);\n\n try {\n await tts.ttsPromise(params.text, outputPath);\n const audioBuffer = readFileSync(outputPath);\n return audioBuffer;\n } finally {\n // Cleanup temp directory\n try {\n rmSync(tempDir, { recursive: true, force: true });\n } catch {\n // Ignore cleanup errors\n }\n }\n}\n\n/**\n * Edge TTS Plugin for ElizaOS\n *\n * Provides free text-to-speech synthesis using Microsoft Edge's TTS service.\n * No API key required - uses the same TTS engine as Microsoft Edge browser.\n *\n * Features:\n * - High-quality neural voices\n * - Multiple languages and locales\n * - Adjustable rate, pitch, and volume\n * - No API key or payment required\n *\n * Optional environment variables:\n * - EDGE_TTS_VOICE: Voice ID (default: en-US-MichelleNeural)\n * - EDGE_TTS_LANG: Language code (default: en-US)\n * - EDGE_TTS_OUTPUT_FORMAT: Output format (default: audio-24khz-48kbitrate-mono-mp3)\n * - EDGE_TTS_RATE: Speech rate adjustment (e.g., +10%, -5%)\n * - EDGE_TTS_PITCH: Pitch adjustment (e.g., +5Hz, -10Hz)\n * - EDGE_TTS_VOLUME: Volume adjustment (e.g., +20%, -10%)\n * - EDGE_TTS_PROXY: HTTP proxy URL\n * - EDGE_TTS_TIMEOUT_MS: Request timeout (default: 30000)\n *\n * Popular voices:\n * - en-US-MichelleNeural (female, US English)\n * - en-US-GuyNeural (male, US English)\n * - en-US-JennyNeural (female, US English)\n * - en-US-AriaNeural (female, US English)\n * - en-GB-SoniaNeural (female, UK English)\n * - en-GB-RyanNeural (male, UK English)\n * - de-DE-KatjaNeural (female, German)\n * - fr-FR-DeniseNeural (female, French)\n * - es-ES-ElviraNeural (female, Spanish)\n * - ja-JP-NanamiNeural (female, Japanese)\n * - zh-CN-XiaoxiaoNeural (female, Chinese)\n */\nexport const edgeTTSPlugin: Plugin = {\n name: \"edge-tts\",\n description:\n \"Free text-to-speech synthesis using Microsoft Edge TTS - no API key required, high-quality neural voices\",\n // Self-declared auto-enable: activate when features.tts is enabled OR when\n // running in an Eliza Cloud-provisioned container (cloud voice output).\n autoEnable: {\n shouldEnable: (env, config) => {\n if (env.ELIZA_CLOUD_PROVISIONED === \"1\") return true;\n const f = (config?.features as Record<string, unknown> | undefined)?.tts;\n return (\n f === true ||\n (typeof f === \"object\" && f !== null && (f as { enabled?: unknown }).enabled !== false)\n );\n },\n },\n models: {\n [ModelType.TEXT_TO_SPEECH]: async (\n runtime: IAgentRuntime,\n input: string | EdgeTTSParams\n ): Promise<Buffer | ArrayBuffer | Uint8Array> => {\n const params: EdgeTTSParams = typeof input === \"string\" ? { text: input } : input;\n const settings = getEdgeTTSSettings(runtime);\n\n logger.log(`[EdgeTTS] Using TEXT_TO_SPEECH with voice: ${settings.voice}`);\n\n if (params.text.trim().length === 0) {\n throw new Error(\"TEXT_TO_SPEECH requires non-empty text\");\n }\n\n // Edge TTS has a practical limit around 5000 characters\n if (params.text.length > 5000) {\n throw new Error(\"TEXT_TO_SPEECH text exceeds 5000 character limit\");\n }\n\n try {\n const audioBuffer = await generateSpeech(settings, params);\n return audioBuffer;\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n logger.error(`EdgeTTS model error: ${msg}`);\n throw error instanceof Error ? error : new Error(msg);\n }\n },\n },\n tests: [\n {\n name: \"test edge tts\",\n tests: [\n {\n name: \"Edge TTS settings validation\",\n fn: async (runtime: IAgentRuntime) => {\n const settings = getEdgeTTSSettings(runtime);\n\n if (!settings.voice) {\n throw new Error(\"Missing voice configuration\");\n }\n\n if (!settings.lang) {\n throw new Error(\"Missing language configuration\");\n }\n\n if (!settings.outputFormat) {\n throw new Error(\"Missing output format configuration\");\n }\n\n logger.success(\"Edge TTS settings validated successfully\");\n },\n },\n {\n name: \"Edge TTS voice preset mapping\",\n fn: async (_runtime: IAgentRuntime) => {\n // Test that OpenAI-style voice names map correctly\n const testCases = [\n { input: \"alloy\", expected: \"en-US-GuyNeural\" },\n { input: \"nova\", expected: \"en-US-JennyNeural\" },\n { input: \"shimmer\", expected: \"en-US-AriaNeural\" },\n {\n input: \"en-US-MichelleNeural\",\n expected: \"en-US-MichelleNeural\",\n },\n ];\n\n for (const tc of testCases) {\n const result = resolveVoice(tc.input, DEFAULT_VOICE);\n if (result !== tc.expected) {\n throw new Error(\n `Voice preset mapping failed: ${tc.input} -> ${result}, expected ${tc.expected}`\n );\n }\n }\n\n logger.success(\"Voice preset mapping validated successfully\");\n },\n },\n {\n name: \"Edge TTS speed to rate conversion\",\n fn: async (_runtime: IAgentRuntime) => {\n const testCases = [\n { speed: 1.0, expected: undefined },\n { speed: 1.5, expected: \"+50%\" },\n { speed: 0.75, expected: \"-25%\" },\n { speed: 2.0, expected: \"+100%\" },\n ];\n\n for (const tc of testCases) {\n const result = speedToRate(tc.speed);\n if (result !== tc.expected) {\n throw new Error(\n `Speed conversion failed: ${tc.speed} -> ${result}, expected ${tc.expected}`\n );\n }\n }\n\n logger.success(\"Speed to rate conversion validated successfully\");\n },\n },\n {\n name: \"Edge TTS generation (live test)\",\n fn: async (runtime: IAgentRuntime) => {\n const testText = \"Hello, this is a test of Edge TTS.\";\n\n try {\n const audioBuffer = (await runtime.useModel(ModelType.TEXT_TO_SPEECH, testText)) as\n | Buffer\n | Uint8Array;\n\n if (!audioBuffer || audioBuffer.length === 0) {\n throw new Error(\"Received empty audio buffer\");\n }\n\n logger.success(`Edge TTS generation successful: ${audioBuffer.length} bytes`);\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n // Edge TTS might fail in CI environments without network\n if (msg.includes(\"ENOTFOUND\") || msg.includes(\"network\")) {\n logger.warn(`Edge TTS live test skipped (network unavailable): ${msg}`);\n return;\n }\n throw error;\n }\n },\n },\n ],\n },\n ],\n};\n\nexport default edgeTTSPlugin;\n\n// Re-export types\nexport type { EdgeTTSParams, EdgeTTSSettings };\n\n// Export helper functions for testing\nexport const _test = {\n resolveVoice,\n speedToRate,\n inferExtension,\n getEdgeTTSSettings,\n};\n"
6
6
  ],
7
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAkD,IAAlD;AACuB,IAAvB;AACiB,IAAjB;AACmE,IAAnE;AACwB,IAAxB;AAoCA,IAAM,gBAAgB;AACtB,IAAM,eAAe;AACrB,IAAM,wBAAwB;AAC9B,IAAM,qBAAqB;AAG3B,IAAM,gBAAwC;AAAA,EAE5C,OAAO;AAAA,EACP,MAAM;AAAA,EACN,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,SAAS;AAEX;AAEA,SAAS,UAAU,CAAC,SAAwB,KAAa,UAAuC;AAAA,EAC9F,MAAM,WACJ,OAAO,YAAY,eAAgB,QAA6C,MAC3E,QAA4C,IAAI,OACjD;AAAA,EACN,OAAQ,QAAQ,WAAW,GAAG,KAA4B,YAAY;AAAA;AAGxE,SAAS,kBAAkB,CAAC,SAAyC;AAAA,EACnE,MAAM,aAAa,WAAW,SAAS,qBAAqB;AAAA,EAC5D,OAAO;AAAA,IACL,OAAO,WAAW,SAAS,kBAAkB,aAAa,KAAK;AAAA,IAC/D,MAAM,WAAW,SAAS,iBAAiB,YAAY,KAAK;AAAA,IAC5D,cACE,WAAW,SAAS,0BAA0B,qBAAqB,KAAK;AAAA,IAC1E,MAAM,WAAW,SAAS,eAAe;AAAA,IACzC,OAAO,WAAW,SAAS,gBAAgB;AAAA,IAC3C,QAAQ,WAAW,SAAS,iBAAiB;AAAA,IAC7C,OAAO,WAAW,SAAS,gBAAgB;AAAA,IAC3C,WAAW,aAAa,OAAO,SAAS,YAAY,EAAE,IAAI;AAAA,EAC5D;AAAA;AAMF,SAAS,YAAY,CAAC,OAA2B,cAA8B;AAAA,EAC7E,IAAI,CAAC;AAAA,IAAO,OAAO;AAAA,EAGnB,MAAM,SAAS,cAAc,MAAM,YAAY;AAAA,EAC/C,IAAI;AAAA,IAAQ,OAAO;AAAA,EAGnB,OAAO;AAAA;AAOT,SAAS,WAAW,CAAC,OAA+C;AAAA,EAClE,IAAI,UAAU,aAAa,UAAU;AAAA,IAAK;AAAA,EAC1C,MAAM,aAAa,KAAK,OAAO,QAAQ,KAAK,GAAG;AAAA,EAC/C,OAAO,cAAc,IAAI,IAAI,gBAAgB,GAAG;AAAA;AAMlD,SAAS,cAAc,CAAC,cAA8B;AAAA,EACpD,MAAM,aAAa,aAAa,YAAY;AAAA,EAC5C,IAAI,WAAW,SAAS,MAAM;AAAA,IAAG,OAAO;AAAA,EACxC,IAAI,WAAW,SAAS,KAAK;AAAA,IAAG,OAAO;AAAA,EACvC,IAAI,WAAW,SAAS,MAAM;AAAA,IAAG,OAAO;AAAA,EACxC,IAAI,WAAW,SAAS,KAAK,KAAK,WAAW,SAAS,MAAM,KAAK,WAAW,SAAS,KAAK,GAAG;AAAA,IAC3F,OAAO;AAAA,EACT;AAAA,EACA,OAAO;AAAA;AAMT,eAAe,cAAc,CAAC,UAA2B,QAAwC;AAAA,EAC/F,MAAM,QAAQ,aAAa,OAAO,OAAO,SAAS,KAAK;AAAA,EACvD,MAAM,OAAO,OAAO,QAAQ,SAAS;AAAA,EACrC,MAAM,eAAe,OAAO,gBAAgB,SAAS;AAAA,EACrD,MAAM,OAAO,OAAO,QAAQ,YAAY,OAAO,KAAK,KAAK,SAAS;AAAA,EAClE,MAAM,QAAQ,OAAO,SAAS,SAAS;AAAA,EACvC,MAAM,SAAS,OAAO,UAAU,SAAS;AAAA,EAEzC,mBAAO,MAAM,2CAA2C,gBAAgB,MAAM;AAAA,EAE9E,MAAM,MAAM,IAAI,6BAAQ;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe;AAAA,IACf,OAAO,SAAS;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS,SAAS;AAAA,EACpB,CAAC;AAAA,EAGD,MAAM,UAAU,2BAAY,yBAAK,KAAK,sBAAO,GAAG,WAAW,CAAC;AAAA,EAC5D,MAAM,YAAY,eAAe,YAAY;AAAA,EAC7C,MAAM,aAAa,yBAAK,KAAK,SAAS,SAAS,WAAW;AAAA,EAE1D,IAAI;AAAA,IACF,MAAM,IAAI,WAAW,OAAO,MAAM,UAAU;AAAA,IAC5C,MAAM,cAAc,4BAAa,UAAU;AAAA,IAC3C,OAAO;AAAA,YACP;AAAA,IAEA,IAAI;AAAA,MACF,sBAAO,SAAS,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,MAChD,MAAM;AAAA;AAAA;AAyCL,IAAM,gBAAwB;AAAA,EACnC,MAAM;AAAA,EACN,aACE;AAAA,EACF,QAAQ;AAAA,KACL,sBAAU,iBAAiB,OAC1B,SACA,UAC+C;AAAA,MAC/C,MAAM,SAAwB,OAAO,UAAU,WAAW,EAAE,MAAM,MAAM,IAAI;AAAA,MAC5E,MAAM,WAAW,mBAAmB,OAAO;AAAA,MAE3C,mBAAO,IAAI,8CAA8C,SAAS,OAAO;AAAA,MAEzE,IAAI,CAAC,OAAO,QAAQ,OAAO,KAAK,KAAK,EAAE,WAAW,GAAG;AAAA,QACnD,MAAM,IAAI,MAAM,wCAAwC;AAAA,MAC1D;AAAA,MAGA,IAAI,OAAO,KAAK,SAAS,MAAM;AAAA,QAC7B,MAAM,IAAI,MAAM,kDAAkD;AAAA,MACpE;AAAA,MAEA,IAAI;AAAA,QACF,MAAM,cAAc,MAAM,eAAe,UAAU,MAAM;AAAA,QACzD,OAAO;AAAA,QACP,OAAO,OAAgB;AAAA,QACvB,MAAM,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,QACjE,mBAAO,MAAM,wBAAwB,KAAK;AAAA,QAC1C,MAAM,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,GAAG;AAAA;AAAA;AAAA,EAG1D;AAAA,EACA,OAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,QACL;AAAA,UACE,MAAM;AAAA,UACN,IAAI,OAAO,YAA2B;AAAA,YACpC,MAAM,WAAW,mBAAmB,OAAO;AAAA,YAE3C,IAAI,CAAC,SAAS,OAAO;AAAA,cACnB,MAAM,IAAI,MAAM,6BAA6B;AAAA,YAC/C;AAAA,YAEA,IAAI,CAAC,SAAS,MAAM;AAAA,cAClB,MAAM,IAAI,MAAM,gCAAgC;AAAA,YAClD;AAAA,YAEA,IAAI,CAAC,SAAS,cAAc;AAAA,cAC1B,MAAM,IAAI,MAAM,qCAAqC;AAAA,YACvD;AAAA,YAEA,mBAAO,QAAQ,0CAA0C;AAAA;AAAA,QAE7D;AAAA,QACA;AAAA,UACE,MAAM;AAAA,UACN,IAAI,OAAO,aAA4B;AAAA,YAErC,MAAM,YAAY;AAAA,cAChB,EAAE,OAAO,SAAS,UAAU,kBAAkB;AAAA,cAC9C,EAAE,OAAO,QAAQ,UAAU,oBAAoB;AAAA,cAC/C,EAAE,OAAO,WAAW,UAAU,mBAAmB;AAAA,cACjD;AAAA,gBACE,OAAO;AAAA,gBACP,UAAU;AAAA,cACZ;AAAA,YACF;AAAA,YAEA,WAAW,MAAM,WAAW;AAAA,cAC1B,MAAM,SAAS,aAAa,GAAG,OAAO,aAAa;AAAA,cACnD,IAAI,WAAW,GAAG,UAAU;AAAA,gBAC1B,MAAM,IAAI,MACR,gCAAgC,GAAG,YAAY,oBAAoB,GAAG,UACxE;AAAA,cACF;AAAA,YACF;AAAA,YAEA,mBAAO,QAAQ,6CAA6C;AAAA;AAAA,QAEhE;AAAA,QACA;AAAA,UACE,MAAM;AAAA,UACN,IAAI,OAAO,aAA4B;AAAA,YACrC,MAAM,YAAY;AAAA,cAChB,EAAE,OAAO,GAAK,UAAU,UAAU;AAAA,cAClC,EAAE,OAAO,KAAK,UAAU,OAAO;AAAA,cAC/B,EAAE,OAAO,MAAM,UAAU,OAAO;AAAA,cAChC,EAAE,OAAO,GAAK,UAAU,QAAQ;AAAA,YAClC;AAAA,YAEA,WAAW,MAAM,WAAW;AAAA,cAC1B,MAAM,SAAS,YAAY,GAAG,KAAK;AAAA,cACnC,IAAI,WAAW,GAAG,UAAU;AAAA,gBAC1B,MAAM,IAAI,MACR,4BAA4B,GAAG,YAAY,oBAAoB,GAAG,UACpE;AAAA,cACF;AAAA,YACF;AAAA,YAEA,mBAAO,QAAQ,iDAAiD;AAAA;AAAA,QAEpE;AAAA,QACA;AAAA,UACE,MAAM;AAAA,UACN,IAAI,OAAO,YAA2B;AAAA,YACpC,MAAM,WAAW;AAAA,YAEjB,IAAI;AAAA,cACF,MAAM,cAAe,MAAM,QAAQ,SAAS,sBAAU,gBAAgB,QAAQ;AAAA,cAI9E,IAAI,CAAC,eAAe,YAAY,WAAW,GAAG;AAAA,gBAC5C,MAAM,IAAI,MAAM,6BAA6B;AAAA,cAC/C;AAAA,cAEA,mBAAO,QAAQ,mCAAmC,YAAY,cAAc;AAAA,cAC5E,OAAO,OAAgB;AAAA,cACvB,MAAM,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,cAEjE,IAAI,IAAI,SAAS,WAAW,KAAK,IAAI,SAAS,SAAS,GAAG;AAAA,gBACxD,mBAAO,KAAK,qDAAqD,KAAK;AAAA,gBACtE;AAAA,cACF;AAAA,cACA,MAAM;AAAA;AAAA;AAAA,QAGZ;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAe;AAMR,IAAM,QAAQ;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;",
8
- "debugId": "44DEBD6EBE84FDA064756E2164756E21",
7
+ "mappings": "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",
8
+ "debugId": "DC587B57E982FAAA64756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -0,0 +1,236 @@
1
+ // src/index.ts
2
+ import { mkdtempSync, readFileSync, rmSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import path from "node:path";
5
+ import { logger, ModelType } from "@elizaos/core";
6
+ import { EdgeTTS } from "node-edge-tts";
7
+
8
+ var DEFAULT_VOICE = "en-US-MichelleNeural";
9
+ var DEFAULT_LANG = "en-US";
10
+ var DEFAULT_OUTPUT_FORMAT = "audio-24khz-48kbitrate-mono-mp3";
11
+ var DEFAULT_TIMEOUT_MS = 30000;
12
+ var VOICE_PRESETS = {
13
+ alloy: "en-US-GuyNeural",
14
+ echo: "en-US-ChristopherNeural",
15
+ fable: "en-GB-RyanNeural",
16
+ onyx: "en-US-DavisNeural",
17
+ nova: "en-US-JennyNeural",
18
+ shimmer: "en-US-AriaNeural",
19
+ };
20
+ function getSetting(runtime, key, fallback) {
21
+ const envValue =
22
+ typeof process !== "undefined" && process.env
23
+ ? process.env[key]
24
+ : undefined;
25
+ return runtime.getSetting(key) ?? envValue ?? fallback;
26
+ }
27
+ function getEdgeTTSSettings(runtime) {
28
+ const timeoutStr = getSetting(runtime, "EDGE_TTS_TIMEOUT_MS");
29
+ return {
30
+ voice:
31
+ getSetting(runtime, "EDGE_TTS_VOICE", DEFAULT_VOICE) ?? DEFAULT_VOICE,
32
+ lang: getSetting(runtime, "EDGE_TTS_LANG", DEFAULT_LANG) ?? DEFAULT_LANG,
33
+ outputFormat:
34
+ getSetting(runtime, "EDGE_TTS_OUTPUT_FORMAT", DEFAULT_OUTPUT_FORMAT) ??
35
+ DEFAULT_OUTPUT_FORMAT,
36
+ rate: getSetting(runtime, "EDGE_TTS_RATE"),
37
+ pitch: getSetting(runtime, "EDGE_TTS_PITCH"),
38
+ volume: getSetting(runtime, "EDGE_TTS_VOLUME"),
39
+ proxy: getSetting(runtime, "EDGE_TTS_PROXY"),
40
+ timeoutMs: timeoutStr
41
+ ? Number.parseInt(timeoutStr, 10)
42
+ : DEFAULT_TIMEOUT_MS,
43
+ };
44
+ }
45
+ function resolveVoice(voice, defaultVoice) {
46
+ if (!voice) return defaultVoice;
47
+ const preset = VOICE_PRESETS[voice.toLowerCase()];
48
+ if (preset) return preset;
49
+ return voice;
50
+ }
51
+ function speedToRate(speed) {
52
+ if (speed === undefined || speed === 1) return;
53
+ const percentage = Math.round((speed - 1) * 100);
54
+ return percentage >= 0 ? `+${percentage}%` : `${percentage}%`;
55
+ }
56
+ function inferExtension(outputFormat) {
57
+ const normalized = outputFormat.toLowerCase();
58
+ if (normalized.includes("webm")) return ".webm";
59
+ if (normalized.includes("ogg")) return ".ogg";
60
+ if (normalized.includes("opus")) return ".opus";
61
+ if (
62
+ normalized.includes("wav") ||
63
+ normalized.includes("riff") ||
64
+ normalized.includes("pcm")
65
+ ) {
66
+ return ".wav";
67
+ }
68
+ return ".mp3";
69
+ }
70
+ async function generateSpeech(settings, params) {
71
+ const voice = resolveVoice(params.voice, settings.voice);
72
+ const lang = params.lang ?? settings.lang;
73
+ const outputFormat = params.outputFormat ?? settings.outputFormat;
74
+ const rate = params.rate ?? speedToRate(params.speed) ?? settings.rate;
75
+ const pitch = params.pitch ?? settings.pitch;
76
+ const volume = params.volume ?? settings.volume;
77
+ logger.debug(
78
+ `[EdgeTTS] Generating speech with voice: ${voice}, lang: ${lang}`,
79
+ );
80
+ const tts = new EdgeTTS({
81
+ voice,
82
+ lang,
83
+ outputFormat,
84
+ saveSubtitles: false,
85
+ proxy: settings.proxy,
86
+ rate,
87
+ pitch,
88
+ volume,
89
+ timeout: settings.timeoutMs,
90
+ });
91
+ const tempDir = mkdtempSync(path.join(tmpdir(), "edge-tts-"));
92
+ const extension = inferExtension(outputFormat);
93
+ const outputPath = path.join(tempDir, `speech${extension}`);
94
+ try {
95
+ await tts.ttsPromise(params.text, outputPath);
96
+ const audioBuffer = readFileSync(outputPath);
97
+ return audioBuffer;
98
+ } finally {
99
+ try {
100
+ rmSync(tempDir, { recursive: true, force: true });
101
+ } catch {}
102
+ }
103
+ }
104
+ var edgeTTSPlugin = {
105
+ name: "edge-tts",
106
+ description:
107
+ "Free text-to-speech synthesis using Microsoft Edge TTS - no API key required, high-quality neural voices",
108
+ models: {
109
+ [ModelType.TEXT_TO_SPEECH]: async (runtime, input) => {
110
+ const params = typeof input === "string" ? { text: input } : input;
111
+ const settings = getEdgeTTSSettings(runtime);
112
+ logger.log(
113
+ `[EdgeTTS] Using TEXT_TO_SPEECH with voice: ${settings.voice}`,
114
+ );
115
+ if (!params.text || params.text.trim().length === 0) {
116
+ throw new Error("TEXT_TO_SPEECH requires non-empty text");
117
+ }
118
+ if (params.text.length > 5000) {
119
+ throw new Error("TEXT_TO_SPEECH text exceeds 5000 character limit");
120
+ }
121
+ try {
122
+ const audioBuffer = await generateSpeech(settings, params);
123
+ return audioBuffer;
124
+ } catch (error) {
125
+ const msg = error instanceof Error ? error.message : String(error);
126
+ logger.error(`EdgeTTS model error: ${msg}`);
127
+ throw error instanceof Error ? error : new Error(msg);
128
+ }
129
+ },
130
+ },
131
+ tests: [
132
+ {
133
+ name: "test edge tts",
134
+ tests: [
135
+ {
136
+ name: "Edge TTS settings validation",
137
+ fn: async (runtime) => {
138
+ const settings = getEdgeTTSSettings(runtime);
139
+ if (!settings.voice) {
140
+ throw new Error("Missing voice configuration");
141
+ }
142
+ if (!settings.lang) {
143
+ throw new Error("Missing language configuration");
144
+ }
145
+ if (!settings.outputFormat) {
146
+ throw new Error("Missing output format configuration");
147
+ }
148
+ logger.success("Edge TTS settings validated successfully");
149
+ },
150
+ },
151
+ {
152
+ name: "Edge TTS voice preset mapping",
153
+ fn: async (_runtime) => {
154
+ const testCases = [
155
+ { input: "alloy", expected: "en-US-GuyNeural" },
156
+ { input: "nova", expected: "en-US-JennyNeural" },
157
+ { input: "shimmer", expected: "en-US-AriaNeural" },
158
+ {
159
+ input: "en-US-MichelleNeural",
160
+ expected: "en-US-MichelleNeural",
161
+ },
162
+ ];
163
+ for (const tc of testCases) {
164
+ const result = resolveVoice(tc.input, DEFAULT_VOICE);
165
+ if (result !== tc.expected) {
166
+ throw new Error(
167
+ `Voice preset mapping failed: ${tc.input} -> ${result}, expected ${tc.expected}`,
168
+ );
169
+ }
170
+ }
171
+ logger.success("Voice preset mapping validated successfully");
172
+ },
173
+ },
174
+ {
175
+ name: "Edge TTS speed to rate conversion",
176
+ fn: async (_runtime) => {
177
+ const testCases = [
178
+ { speed: 1, expected: undefined },
179
+ { speed: 1.5, expected: "+50%" },
180
+ { speed: 0.75, expected: "-25%" },
181
+ { speed: 2, expected: "+100%" },
182
+ ];
183
+ for (const tc of testCases) {
184
+ const result = speedToRate(tc.speed);
185
+ if (result !== tc.expected) {
186
+ throw new Error(
187
+ `Speed conversion failed: ${tc.speed} -> ${result}, expected ${tc.expected}`,
188
+ );
189
+ }
190
+ }
191
+ logger.success("Speed to rate conversion validated successfully");
192
+ },
193
+ },
194
+ {
195
+ name: "Edge TTS generation (live test)",
196
+ fn: async (runtime) => {
197
+ const testText = "Hello, this is a test of Edge TTS.";
198
+ try {
199
+ const audioBuffer = await runtime.useModel(
200
+ ModelType.TEXT_TO_SPEECH,
201
+ testText,
202
+ );
203
+ if (!audioBuffer || audioBuffer.length === 0) {
204
+ throw new Error("Received empty audio buffer");
205
+ }
206
+ logger.success(
207
+ `Edge TTS generation successful: ${audioBuffer.length} bytes`,
208
+ );
209
+ } catch (error) {
210
+ const msg =
211
+ error instanceof Error ? error.message : String(error);
212
+ if (msg.includes("ENOTFOUND") || msg.includes("network")) {
213
+ logger.warn(
214
+ `Edge TTS live test skipped (network unavailable): ${msg}`,
215
+ );
216
+ return;
217
+ }
218
+ throw error;
219
+ }
220
+ },
221
+ },
222
+ ],
223
+ },
224
+ ],
225
+ };
226
+ var src_default = edgeTTSPlugin;
227
+ var _test = {
228
+ resolveVoice,
229
+ speedToRate,
230
+ inferExtension,
231
+ getEdgeTTSSettings,
232
+ };
233
+
234
+ export { _test, edgeTTSPlugin, src_default as default };
235
+
236
+ //# debugId=6FEC68331BF4F5C164756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/index.ts"],
4
+ "sourcesContent": [
5
+ "import { mkdtempSync, readFileSync, rmSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\nimport { type IAgentRuntime, logger, ModelType, type Plugin } from \"@elizaos/core\";\nimport { EdgeTTS } from \"node-edge-tts\";\n\n/**\n * Edge TTS voice settings configuration\n */\ninterface EdgeTTSSettings {\n voice: string;\n lang: string;\n outputFormat: string;\n rate?: string;\n pitch?: string;\n volume?: string;\n proxy?: string;\n timeoutMs: number;\n}\n\n/**\n * Extended TTS params with Edge-specific options\n */\ninterface EdgeTTSParams {\n text: string;\n voice?: string;\n speed?: number;\n /** Edge TTS specific: language code */\n lang?: string;\n /** Edge TTS specific: output format */\n outputFormat?: string;\n /** Edge TTS specific: rate adjustment (e.g., +10%, -5%) */\n rate?: string;\n /** Edge TTS specific: pitch adjustment (e.g., +5Hz, -10Hz) */\n pitch?: string;\n /** Edge TTS specific: volume adjustment (e.g., +20%, -10%) */\n volume?: string;\n}\n\n// Default voice configurations\nconst DEFAULT_VOICE = \"en-US-MichelleNeural\";\nconst DEFAULT_LANG = \"en-US\";\nconst DEFAULT_OUTPUT_FORMAT = \"audio-24khz-48kbitrate-mono-mp3\";\nconst DEFAULT_TIMEOUT_MS = 30000;\n\n// Voice presets mapping common voice names to Edge TTS voices\nconst VOICE_PRESETS: Record<string, string> = {\n // Generic voices (map to good defaults)\n alloy: \"en-US-GuyNeural\",\n echo: \"en-US-ChristopherNeural\",\n fable: \"en-GB-RyanNeural\",\n onyx: \"en-US-DavisNeural\",\n nova: \"en-US-JennyNeural\",\n shimmer: \"en-US-AriaNeural\",\n // Direct Edge TTS voice names pass through\n};\n\nfunction getSetting(runtime: IAgentRuntime, key: string, fallback?: string): string | undefined {\n const envValue =\n typeof process !== \"undefined\" && (process as { env?: Record<string, string> }).env\n ? (process as { env: Record<string, string> }).env[key]\n : undefined;\n return (runtime.getSetting(key) as string | undefined) ?? envValue ?? fallback;\n}\n\nfunction getEdgeTTSSettings(runtime: IAgentRuntime): EdgeTTSSettings {\n const timeoutStr = getSetting(runtime, \"EDGE_TTS_TIMEOUT_MS\");\n return {\n voice: getSetting(runtime, \"EDGE_TTS_VOICE\", DEFAULT_VOICE) ?? DEFAULT_VOICE,\n lang: getSetting(runtime, \"EDGE_TTS_LANG\", DEFAULT_LANG) ?? DEFAULT_LANG,\n outputFormat:\n getSetting(runtime, \"EDGE_TTS_OUTPUT_FORMAT\", DEFAULT_OUTPUT_FORMAT) ?? DEFAULT_OUTPUT_FORMAT,\n rate: getSetting(runtime, \"EDGE_TTS_RATE\"),\n pitch: getSetting(runtime, \"EDGE_TTS_PITCH\"),\n volume: getSetting(runtime, \"EDGE_TTS_VOLUME\"),\n proxy: getSetting(runtime, \"EDGE_TTS_PROXY\"),\n timeoutMs: timeoutStr ? Number.parseInt(timeoutStr, 10) : DEFAULT_TIMEOUT_MS,\n };\n}\n\n/**\n * Resolve voice name - handles OpenAI-style voice names and Edge TTS voice IDs\n */\nfunction resolveVoice(voice: string | undefined, defaultVoice: string): string {\n if (!voice) return defaultVoice;\n\n // Check if it's a preset name\n const preset = VOICE_PRESETS[voice.toLowerCase()];\n if (preset) return preset;\n\n // Assume it's a direct Edge TTS voice ID\n return voice;\n}\n\n/**\n * Convert speed multiplier to Edge TTS rate string\n * speed: 1.0 = normal, 0.5 = half speed, 2.0 = double speed\n */\nfunction speedToRate(speed: number | undefined): string | undefined {\n if (speed === undefined || speed === 1.0) return undefined;\n const percentage = Math.round((speed - 1) * 100);\n return percentage >= 0 ? `+${percentage}%` : `${percentage}%`;\n}\n\n/**\n * Infer file extension from Edge TTS output format\n */\nfunction inferExtension(outputFormat: string): string {\n const normalized = outputFormat.toLowerCase();\n if (normalized.includes(\"webm\")) return \".webm\";\n if (normalized.includes(\"ogg\")) return \".ogg\";\n if (normalized.includes(\"opus\")) return \".opus\";\n if (normalized.includes(\"wav\") || normalized.includes(\"riff\") || normalized.includes(\"pcm\")) {\n return \".wav\";\n }\n return \".mp3\";\n}\n\n/**\n * Generate speech using Microsoft Edge TTS\n */\nasync function generateSpeech(settings: EdgeTTSSettings, params: EdgeTTSParams): Promise<Buffer> {\n const voice = resolveVoice(params.voice, settings.voice);\n const lang = params.lang ?? settings.lang;\n const outputFormat = params.outputFormat ?? settings.outputFormat;\n const rate = params.rate ?? speedToRate(params.speed) ?? settings.rate;\n const pitch = params.pitch ?? settings.pitch;\n const volume = params.volume ?? settings.volume;\n\n logger.debug(`[EdgeTTS] Generating speech with voice: ${voice}, lang: ${lang}`);\n\n const tts = new EdgeTTS({\n voice,\n lang,\n outputFormat,\n saveSubtitles: false,\n proxy: settings.proxy,\n rate,\n pitch,\n volume,\n timeout: settings.timeoutMs,\n });\n\n // Create temp directory for output\n const tempDir = mkdtempSync(path.join(tmpdir(), \"edge-tts-\"));\n const extension = inferExtension(outputFormat);\n const outputPath = path.join(tempDir, `speech${extension}`);\n\n try {\n await tts.ttsPromise(params.text, outputPath);\n const audioBuffer = readFileSync(outputPath);\n return audioBuffer;\n } finally {\n // Cleanup temp directory\n try {\n rmSync(tempDir, { recursive: true, force: true });\n } catch {\n // Ignore cleanup errors\n }\n }\n}\n\n/**\n * Edge TTS Plugin for ElizaOS\n *\n * Provides free text-to-speech synthesis using Microsoft Edge's TTS service.\n * No API key required - uses the same TTS engine as Microsoft Edge browser.\n *\n * Features:\n * - High-quality neural voices\n * - Multiple languages and locales\n * - Adjustable rate, pitch, and volume\n * - No API key or payment required\n *\n * Optional environment variables:\n * - EDGE_TTS_VOICE: Voice ID (default: en-US-MichelleNeural)\n * - EDGE_TTS_LANG: Language code (default: en-US)\n * - EDGE_TTS_OUTPUT_FORMAT: Output format (default: audio-24khz-48kbitrate-mono-mp3)\n * - EDGE_TTS_RATE: Speech rate adjustment (e.g., +10%, -5%)\n * - EDGE_TTS_PITCH: Pitch adjustment (e.g., +5Hz, -10Hz)\n * - EDGE_TTS_VOLUME: Volume adjustment (e.g., +20%, -10%)\n * - EDGE_TTS_PROXY: HTTP proxy URL\n * - EDGE_TTS_TIMEOUT_MS: Request timeout (default: 30000)\n *\n * Popular voices:\n * - en-US-MichelleNeural (female, US English)\n * - en-US-GuyNeural (male, US English)\n * - en-US-JennyNeural (female, US English)\n * - en-US-AriaNeural (female, US English)\n * - en-GB-SoniaNeural (female, UK English)\n * - en-GB-RyanNeural (male, UK English)\n * - de-DE-KatjaNeural (female, German)\n * - fr-FR-DeniseNeural (female, French)\n * - es-ES-ElviraNeural (female, Spanish)\n * - ja-JP-NanamiNeural (female, Japanese)\n * - zh-CN-XiaoxiaoNeural (female, Chinese)\n */\nexport const edgeTTSPlugin: Plugin = {\n name: \"edge-tts\",\n description:\n \"Free text-to-speech synthesis using Microsoft Edge TTS - no API key required, high-quality neural voices\",\n models: {\n [ModelType.TEXT_TO_SPEECH]: async (\n runtime: IAgentRuntime,\n input: string | EdgeTTSParams\n ): Promise<Buffer | ArrayBuffer | Uint8Array> => {\n const params: EdgeTTSParams = typeof input === \"string\" ? { text: input } : input;\n const settings = getEdgeTTSSettings(runtime);\n\n logger.log(`[EdgeTTS] Using TEXT_TO_SPEECH with voice: ${settings.voice}`);\n\n if (!params.text || params.text.trim().length === 0) {\n throw new Error(\"TEXT_TO_SPEECH requires non-empty text\");\n }\n\n // Edge TTS has a practical limit around 5000 characters\n if (params.text.length > 5000) {\n throw new Error(\"TEXT_TO_SPEECH text exceeds 5000 character limit\");\n }\n\n try {\n const audioBuffer = await generateSpeech(settings, params);\n return audioBuffer;\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n logger.error(`EdgeTTS model error: ${msg}`);\n throw error instanceof Error ? error : new Error(msg);\n }\n },\n },\n tests: [\n {\n name: \"test edge tts\",\n tests: [\n {\n name: \"Edge TTS settings validation\",\n fn: async (runtime: IAgentRuntime) => {\n const settings = getEdgeTTSSettings(runtime);\n\n if (!settings.voice) {\n throw new Error(\"Missing voice configuration\");\n }\n\n if (!settings.lang) {\n throw new Error(\"Missing language configuration\");\n }\n\n if (!settings.outputFormat) {\n throw new Error(\"Missing output format configuration\");\n }\n\n logger.success(\"Edge TTS settings validated successfully\");\n },\n },\n {\n name: \"Edge TTS voice preset mapping\",\n fn: async (_runtime: IAgentRuntime) => {\n // Test that OpenAI-style voice names map correctly\n const testCases = [\n { input: \"alloy\", expected: \"en-US-GuyNeural\" },\n { input: \"nova\", expected: \"en-US-JennyNeural\" },\n { input: \"shimmer\", expected: \"en-US-AriaNeural\" },\n {\n input: \"en-US-MichelleNeural\",\n expected: \"en-US-MichelleNeural\",\n },\n ];\n\n for (const tc of testCases) {\n const result = resolveVoice(tc.input, DEFAULT_VOICE);\n if (result !== tc.expected) {\n throw new Error(\n `Voice preset mapping failed: ${tc.input} -> ${result}, expected ${tc.expected}`\n );\n }\n }\n\n logger.success(\"Voice preset mapping validated successfully\");\n },\n },\n {\n name: \"Edge TTS speed to rate conversion\",\n fn: async (_runtime: IAgentRuntime) => {\n const testCases = [\n { speed: 1.0, expected: undefined },\n { speed: 1.5, expected: \"+50%\" },\n { speed: 0.75, expected: \"-25%\" },\n { speed: 2.0, expected: \"+100%\" },\n ];\n\n for (const tc of testCases) {\n const result = speedToRate(tc.speed);\n if (result !== tc.expected) {\n throw new Error(\n `Speed conversion failed: ${tc.speed} -> ${result}, expected ${tc.expected}`\n );\n }\n }\n\n logger.success(\"Speed to rate conversion validated successfully\");\n },\n },\n {\n name: \"Edge TTS generation (live test)\",\n fn: async (runtime: IAgentRuntime) => {\n const testText = \"Hello, this is a test of Edge TTS.\";\n\n try {\n const audioBuffer = (await runtime.useModel(ModelType.TEXT_TO_SPEECH, testText)) as\n | Buffer\n | Uint8Array;\n\n if (!audioBuffer || audioBuffer.length === 0) {\n throw new Error(\"Received empty audio buffer\");\n }\n\n logger.success(`Edge TTS generation successful: ${audioBuffer.length} bytes`);\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n // Edge TTS might fail in CI environments without network\n if (msg.includes(\"ENOTFOUND\") || msg.includes(\"network\")) {\n logger.warn(`Edge TTS live test skipped (network unavailable): ${msg}`);\n return;\n }\n throw error;\n }\n },\n },\n ],\n },\n ],\n};\n\nexport default edgeTTSPlugin;\n\n// Re-export types\nexport type { EdgeTTSParams, EdgeTTSSettings };\n\n// Export helper functions for testing\nexport const _test = {\n resolveVoice,\n speedToRate,\n inferExtension,\n getEdgeTTSSettings,\n};\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "6FEC68331BF4F5C164756E2164756E21",
9
+ "names": []
10
+ }
@@ -95,12 +95,20 @@ async function generateSpeech(settings, params) {
95
95
  var edgeTTSPlugin = {
96
96
  name: "edge-tts",
97
97
  description: "Free text-to-speech synthesis using Microsoft Edge TTS - no API key required, high-quality neural voices",
98
+ autoEnable: {
99
+ shouldEnable: (env, config) => {
100
+ if (env.ELIZA_CLOUD_PROVISIONED === "1")
101
+ return true;
102
+ const f = config?.features?.tts;
103
+ return f === true || typeof f === "object" && f !== null && f.enabled !== false;
104
+ }
105
+ },
98
106
  models: {
99
107
  [ModelType.TEXT_TO_SPEECH]: async (runtime, input) => {
100
108
  const params = typeof input === "string" ? { text: input } : input;
101
109
  const settings = getEdgeTTSSettings(runtime);
102
110
  logger.log(`[EdgeTTS] Using TEXT_TO_SPEECH with voice: ${settings.voice}`);
103
- if (!params.text || params.text.trim().length === 0) {
111
+ if (params.text.trim().length === 0) {
104
112
  throw new Error("TEXT_TO_SPEECH requires non-empty text");
105
113
  }
106
114
  if (params.text.length > 5000) {
@@ -212,4 +220,4 @@ export {
212
220
  _test
213
221
  };
214
222
 
215
- //# debugId=72B923D58112D3ED64756E2164756E21
223
+ //# debugId=E6E8C4F38067800864756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../src/index.ts"],
4
4
  "sourcesContent": [
5
- "import { mkdtempSync, readFileSync, rmSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\nimport { type IAgentRuntime, logger, ModelType, type Plugin } from \"@elizaos/core\";\nimport { EdgeTTS } from \"node-edge-tts\";\n\n/**\n * Edge TTS voice settings configuration\n */\ninterface EdgeTTSSettings {\n voice: string;\n lang: string;\n outputFormat: string;\n rate?: string;\n pitch?: string;\n volume?: string;\n proxy?: string;\n timeoutMs: number;\n}\n\n/**\n * Extended TTS params with Edge-specific options\n */\ninterface EdgeTTSParams {\n text: string;\n voice?: string;\n speed?: number;\n /** Edge TTS specific: language code */\n lang?: string;\n /** Edge TTS specific: output format */\n outputFormat?: string;\n /** Edge TTS specific: rate adjustment (e.g., +10%, -5%) */\n rate?: string;\n /** Edge TTS specific: pitch adjustment (e.g., +5Hz, -10Hz) */\n pitch?: string;\n /** Edge TTS specific: volume adjustment (e.g., +20%, -10%) */\n volume?: string;\n}\n\n// Default voice configurations\nconst DEFAULT_VOICE = \"en-US-MichelleNeural\";\nconst DEFAULT_LANG = \"en-US\";\nconst DEFAULT_OUTPUT_FORMAT = \"audio-24khz-48kbitrate-mono-mp3\";\nconst DEFAULT_TIMEOUT_MS = 30000;\n\n// Voice presets mapping common voice names to Edge TTS voices\nconst VOICE_PRESETS: Record<string, string> = {\n // Generic voices (map to good defaults)\n alloy: \"en-US-GuyNeural\",\n echo: \"en-US-ChristopherNeural\",\n fable: \"en-GB-RyanNeural\",\n onyx: \"en-US-DavisNeural\",\n nova: \"en-US-JennyNeural\",\n shimmer: \"en-US-AriaNeural\",\n // Direct Edge TTS voice names pass through\n};\n\nfunction getSetting(runtime: IAgentRuntime, key: string, fallback?: string): string | undefined {\n const envValue =\n typeof process !== \"undefined\" && (process as { env?: Record<string, string> }).env\n ? (process as { env: Record<string, string> }).env[key]\n : undefined;\n return (runtime.getSetting(key) as string | undefined) ?? envValue ?? fallback;\n}\n\nfunction getEdgeTTSSettings(runtime: IAgentRuntime): EdgeTTSSettings {\n const timeoutStr = getSetting(runtime, \"EDGE_TTS_TIMEOUT_MS\");\n return {\n voice: getSetting(runtime, \"EDGE_TTS_VOICE\", DEFAULT_VOICE) ?? DEFAULT_VOICE,\n lang: getSetting(runtime, \"EDGE_TTS_LANG\", DEFAULT_LANG) ?? DEFAULT_LANG,\n outputFormat:\n getSetting(runtime, \"EDGE_TTS_OUTPUT_FORMAT\", DEFAULT_OUTPUT_FORMAT) ?? DEFAULT_OUTPUT_FORMAT,\n rate: getSetting(runtime, \"EDGE_TTS_RATE\"),\n pitch: getSetting(runtime, \"EDGE_TTS_PITCH\"),\n volume: getSetting(runtime, \"EDGE_TTS_VOLUME\"),\n proxy: getSetting(runtime, \"EDGE_TTS_PROXY\"),\n timeoutMs: timeoutStr ? Number.parseInt(timeoutStr, 10) : DEFAULT_TIMEOUT_MS,\n };\n}\n\n/**\n * Resolve voice name - handles OpenAI-style voice names and Edge TTS voice IDs\n */\nfunction resolveVoice(voice: string | undefined, defaultVoice: string): string {\n if (!voice) return defaultVoice;\n\n // Check if it's a preset name\n const preset = VOICE_PRESETS[voice.toLowerCase()];\n if (preset) return preset;\n\n // Assume it's a direct Edge TTS voice ID\n return voice;\n}\n\n/**\n * Convert speed multiplier to Edge TTS rate string\n * speed: 1.0 = normal, 0.5 = half speed, 2.0 = double speed\n */\nfunction speedToRate(speed: number | undefined): string | undefined {\n if (speed === undefined || speed === 1.0) return undefined;\n const percentage = Math.round((speed - 1) * 100);\n return percentage >= 0 ? `+${percentage}%` : `${percentage}%`;\n}\n\n/**\n * Infer file extension from Edge TTS output format\n */\nfunction inferExtension(outputFormat: string): string {\n const normalized = outputFormat.toLowerCase();\n if (normalized.includes(\"webm\")) return \".webm\";\n if (normalized.includes(\"ogg\")) return \".ogg\";\n if (normalized.includes(\"opus\")) return \".opus\";\n if (normalized.includes(\"wav\") || normalized.includes(\"riff\") || normalized.includes(\"pcm\")) {\n return \".wav\";\n }\n return \".mp3\";\n}\n\n/**\n * Generate speech using Microsoft Edge TTS\n */\nasync function generateSpeech(settings: EdgeTTSSettings, params: EdgeTTSParams): Promise<Buffer> {\n const voice = resolveVoice(params.voice, settings.voice);\n const lang = params.lang ?? settings.lang;\n const outputFormat = params.outputFormat ?? settings.outputFormat;\n const rate = params.rate ?? speedToRate(params.speed) ?? settings.rate;\n const pitch = params.pitch ?? settings.pitch;\n const volume = params.volume ?? settings.volume;\n\n logger.debug(`[EdgeTTS] Generating speech with voice: ${voice}, lang: ${lang}`);\n\n const tts = new EdgeTTS({\n voice,\n lang,\n outputFormat,\n saveSubtitles: false,\n proxy: settings.proxy,\n rate,\n pitch,\n volume,\n timeout: settings.timeoutMs,\n });\n\n // Create temp directory for output\n const tempDir = mkdtempSync(path.join(tmpdir(), \"edge-tts-\"));\n const extension = inferExtension(outputFormat);\n const outputPath = path.join(tempDir, `speech${extension}`);\n\n try {\n await tts.ttsPromise(params.text, outputPath);\n const audioBuffer = readFileSync(outputPath);\n return audioBuffer;\n } finally {\n // Cleanup temp directory\n try {\n rmSync(tempDir, { recursive: true, force: true });\n } catch {\n // Ignore cleanup errors\n }\n }\n}\n\n/**\n * Edge TTS Plugin for ElizaOS\n *\n * Provides free text-to-speech synthesis using Microsoft Edge's TTS service.\n * No API key required - uses the same TTS engine as Microsoft Edge browser.\n *\n * Features:\n * - High-quality neural voices\n * - Multiple languages and locales\n * - Adjustable rate, pitch, and volume\n * - No API key or payment required\n *\n * Optional environment variables:\n * - EDGE_TTS_VOICE: Voice ID (default: en-US-MichelleNeural)\n * - EDGE_TTS_LANG: Language code (default: en-US)\n * - EDGE_TTS_OUTPUT_FORMAT: Output format (default: audio-24khz-48kbitrate-mono-mp3)\n * - EDGE_TTS_RATE: Speech rate adjustment (e.g., +10%, -5%)\n * - EDGE_TTS_PITCH: Pitch adjustment (e.g., +5Hz, -10Hz)\n * - EDGE_TTS_VOLUME: Volume adjustment (e.g., +20%, -10%)\n * - EDGE_TTS_PROXY: HTTP proxy URL\n * - EDGE_TTS_TIMEOUT_MS: Request timeout (default: 30000)\n *\n * Popular voices:\n * - en-US-MichelleNeural (female, US English)\n * - en-US-GuyNeural (male, US English)\n * - en-US-JennyNeural (female, US English)\n * - en-US-AriaNeural (female, US English)\n * - en-GB-SoniaNeural (female, UK English)\n * - en-GB-RyanNeural (male, UK English)\n * - de-DE-KatjaNeural (female, German)\n * - fr-FR-DeniseNeural (female, French)\n * - es-ES-ElviraNeural (female, Spanish)\n * - ja-JP-NanamiNeural (female, Japanese)\n * - zh-CN-XiaoxiaoNeural (female, Chinese)\n */\nexport const edgeTTSPlugin: Plugin = {\n name: \"edge-tts\",\n description:\n \"Free text-to-speech synthesis using Microsoft Edge TTS - no API key required, high-quality neural voices\",\n models: {\n [ModelType.TEXT_TO_SPEECH]: async (\n runtime: IAgentRuntime,\n input: string | EdgeTTSParams\n ): Promise<Buffer | ArrayBuffer | Uint8Array> => {\n const params: EdgeTTSParams = typeof input === \"string\" ? { text: input } : input;\n const settings = getEdgeTTSSettings(runtime);\n\n logger.log(`[EdgeTTS] Using TEXT_TO_SPEECH with voice: ${settings.voice}`);\n\n if (!params.text || params.text.trim().length === 0) {\n throw new Error(\"TEXT_TO_SPEECH requires non-empty text\");\n }\n\n // Edge TTS has a practical limit around 5000 characters\n if (params.text.length > 5000) {\n throw new Error(\"TEXT_TO_SPEECH text exceeds 5000 character limit\");\n }\n\n try {\n const audioBuffer = await generateSpeech(settings, params);\n return audioBuffer;\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n logger.error(`EdgeTTS model error: ${msg}`);\n throw error instanceof Error ? error : new Error(msg);\n }\n },\n },\n tests: [\n {\n name: \"test edge tts\",\n tests: [\n {\n name: \"Edge TTS settings validation\",\n fn: async (runtime: IAgentRuntime) => {\n const settings = getEdgeTTSSettings(runtime);\n\n if (!settings.voice) {\n throw new Error(\"Missing voice configuration\");\n }\n\n if (!settings.lang) {\n throw new Error(\"Missing language configuration\");\n }\n\n if (!settings.outputFormat) {\n throw new Error(\"Missing output format configuration\");\n }\n\n logger.success(\"Edge TTS settings validated successfully\");\n },\n },\n {\n name: \"Edge TTS voice preset mapping\",\n fn: async (_runtime: IAgentRuntime) => {\n // Test that OpenAI-style voice names map correctly\n const testCases = [\n { input: \"alloy\", expected: \"en-US-GuyNeural\" },\n { input: \"nova\", expected: \"en-US-JennyNeural\" },\n { input: \"shimmer\", expected: \"en-US-AriaNeural\" },\n {\n input: \"en-US-MichelleNeural\",\n expected: \"en-US-MichelleNeural\",\n },\n ];\n\n for (const tc of testCases) {\n const result = resolveVoice(tc.input, DEFAULT_VOICE);\n if (result !== tc.expected) {\n throw new Error(\n `Voice preset mapping failed: ${tc.input} -> ${result}, expected ${tc.expected}`\n );\n }\n }\n\n logger.success(\"Voice preset mapping validated successfully\");\n },\n },\n {\n name: \"Edge TTS speed to rate conversion\",\n fn: async (_runtime: IAgentRuntime) => {\n const testCases = [\n { speed: 1.0, expected: undefined },\n { speed: 1.5, expected: \"+50%\" },\n { speed: 0.75, expected: \"-25%\" },\n { speed: 2.0, expected: \"+100%\" },\n ];\n\n for (const tc of testCases) {\n const result = speedToRate(tc.speed);\n if (result !== tc.expected) {\n throw new Error(\n `Speed conversion failed: ${tc.speed} -> ${result}, expected ${tc.expected}`\n );\n }\n }\n\n logger.success(\"Speed to rate conversion validated successfully\");\n },\n },\n {\n name: \"Edge TTS generation (live test)\",\n fn: async (runtime: IAgentRuntime) => {\n const testText = \"Hello, this is a test of Edge TTS.\";\n\n try {\n const audioBuffer = (await runtime.useModel(ModelType.TEXT_TO_SPEECH, testText)) as\n | Buffer\n | Uint8Array;\n\n if (!audioBuffer || audioBuffer.length === 0) {\n throw new Error(\"Received empty audio buffer\");\n }\n\n logger.success(`Edge TTS generation successful: ${audioBuffer.length} bytes`);\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n // Edge TTS might fail in CI environments without network\n if (msg.includes(\"ENOTFOUND\") || msg.includes(\"network\")) {\n logger.warn(`Edge TTS live test skipped (network unavailable): ${msg}`);\n return;\n }\n throw error;\n }\n },\n },\n ],\n },\n ],\n};\n\nexport default edgeTTSPlugin;\n\n// Re-export types\nexport type { EdgeTTSSettings, EdgeTTSParams };\n\n// Export helper functions for testing\nexport const _test = {\n resolveVoice,\n speedToRate,\n inferExtension,\n getEdgeTTSSettings,\n};\n"
5
+ "import { mkdtempSync, readFileSync, rmSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\nimport { type IAgentRuntime, logger, ModelType, type Plugin } from \"@elizaos/core\";\nimport { EdgeTTS } from \"node-edge-tts\";\n\n/**\n * Edge TTS voice settings configuration\n */\ninterface EdgeTTSSettings {\n voice: string;\n lang: string;\n outputFormat: string;\n rate?: string;\n pitch?: string;\n volume?: string;\n proxy?: string;\n timeoutMs: number;\n}\n\n/**\n * Extended TTS params with Edge-specific options\n */\ninterface EdgeTTSParams {\n text: string;\n voice?: string;\n speed?: number;\n /** Edge TTS specific: language code */\n lang?: string;\n /** Edge TTS specific: output format */\n outputFormat?: string;\n /** Edge TTS specific: rate adjustment (e.g., +10%, -5%) */\n rate?: string;\n /** Edge TTS specific: pitch adjustment (e.g., +5Hz, -10Hz) */\n pitch?: string;\n /** Edge TTS specific: volume adjustment (e.g., +20%, -10%) */\n volume?: string;\n}\n\n// Default voice configurations\nconst DEFAULT_VOICE = \"en-US-MichelleNeural\";\nconst DEFAULT_LANG = \"en-US\";\nconst DEFAULT_OUTPUT_FORMAT = \"audio-24khz-48kbitrate-mono-mp3\";\nconst DEFAULT_TIMEOUT_MS = 30000;\n\n// Voice presets mapping common voice names to Edge TTS voices\nconst VOICE_PRESETS: Record<string, string> = {\n // Generic voices (map to good defaults)\n alloy: \"en-US-GuyNeural\",\n echo: \"en-US-ChristopherNeural\",\n fable: \"en-GB-RyanNeural\",\n onyx: \"en-US-DavisNeural\",\n nova: \"en-US-JennyNeural\",\n shimmer: \"en-US-AriaNeural\",\n // Direct Edge TTS voice names pass through\n};\n\nfunction getSetting(runtime: IAgentRuntime, key: string, fallback?: string): string | undefined {\n const envValue =\n typeof process !== \"undefined\" && (process as { env?: Record<string, string> }).env\n ? (process as { env: Record<string, string> }).env[key]\n : undefined;\n return (runtime.getSetting(key) as string | undefined) ?? envValue ?? fallback;\n}\n\nfunction getEdgeTTSSettings(runtime: IAgentRuntime): EdgeTTSSettings {\n const timeoutStr = getSetting(runtime, \"EDGE_TTS_TIMEOUT_MS\");\n return {\n voice: getSetting(runtime, \"EDGE_TTS_VOICE\", DEFAULT_VOICE) ?? DEFAULT_VOICE,\n lang: getSetting(runtime, \"EDGE_TTS_LANG\", DEFAULT_LANG) ?? DEFAULT_LANG,\n outputFormat:\n getSetting(runtime, \"EDGE_TTS_OUTPUT_FORMAT\", DEFAULT_OUTPUT_FORMAT) ?? DEFAULT_OUTPUT_FORMAT,\n rate: getSetting(runtime, \"EDGE_TTS_RATE\"),\n pitch: getSetting(runtime, \"EDGE_TTS_PITCH\"),\n volume: getSetting(runtime, \"EDGE_TTS_VOLUME\"),\n proxy: getSetting(runtime, \"EDGE_TTS_PROXY\"),\n timeoutMs: timeoutStr ? Number.parseInt(timeoutStr, 10) : DEFAULT_TIMEOUT_MS,\n };\n}\n\n/**\n * Resolve voice name - handles OpenAI-style voice names and Edge TTS voice IDs\n */\nfunction resolveVoice(voice: string | undefined, defaultVoice: string): string {\n if (!voice) return defaultVoice;\n\n // Check if it's a preset name\n const preset = VOICE_PRESETS[voice.toLowerCase()];\n if (preset) return preset;\n\n // Assume it's a direct Edge TTS voice ID\n return voice;\n}\n\n/**\n * Convert speed multiplier to Edge TTS rate string\n * speed: 1.0 = normal, 0.5 = half speed, 2.0 = double speed\n */\nfunction speedToRate(speed: number | undefined): string | undefined {\n if (speed === undefined || speed === 1.0) return undefined;\n const percentage = Math.round((speed - 1) * 100);\n return percentage >= 0 ? `+${percentage}%` : `${percentage}%`;\n}\n\n/**\n * Infer file extension from Edge TTS output format\n */\nfunction inferExtension(outputFormat: string): string {\n const normalized = outputFormat.toLowerCase();\n if (normalized.includes(\"webm\")) return \".webm\";\n if (normalized.includes(\"ogg\")) return \".ogg\";\n if (normalized.includes(\"opus\")) return \".opus\";\n if (normalized.includes(\"wav\") || normalized.includes(\"riff\") || normalized.includes(\"pcm\")) {\n return \".wav\";\n }\n return \".mp3\";\n}\n\n/**\n * Generate speech using Microsoft Edge TTS\n */\nasync function generateSpeech(settings: EdgeTTSSettings, params: EdgeTTSParams): Promise<Buffer> {\n const voice = resolveVoice(params.voice, settings.voice);\n const lang = params.lang ?? settings.lang;\n const outputFormat = params.outputFormat ?? settings.outputFormat;\n const rate = params.rate ?? speedToRate(params.speed) ?? settings.rate;\n const pitch = params.pitch ?? settings.pitch;\n const volume = params.volume ?? settings.volume;\n\n logger.debug(`[EdgeTTS] Generating speech with voice: ${voice}, lang: ${lang}`);\n\n const tts = new EdgeTTS({\n voice,\n lang,\n outputFormat,\n saveSubtitles: false,\n proxy: settings.proxy,\n rate,\n pitch,\n volume,\n timeout: settings.timeoutMs,\n });\n\n // Create temp directory for output\n const tempDir = mkdtempSync(path.join(tmpdir(), \"edge-tts-\"));\n const extension = inferExtension(outputFormat);\n const outputPath = path.join(tempDir, `speech${extension}`);\n\n try {\n await tts.ttsPromise(params.text, outputPath);\n const audioBuffer = readFileSync(outputPath);\n return audioBuffer;\n } finally {\n // Cleanup temp directory\n try {\n rmSync(tempDir, { recursive: true, force: true });\n } catch {\n // Ignore cleanup errors\n }\n }\n}\n\n/**\n * Edge TTS Plugin for ElizaOS\n *\n * Provides free text-to-speech synthesis using Microsoft Edge's TTS service.\n * No API key required - uses the same TTS engine as Microsoft Edge browser.\n *\n * Features:\n * - High-quality neural voices\n * - Multiple languages and locales\n * - Adjustable rate, pitch, and volume\n * - No API key or payment required\n *\n * Optional environment variables:\n * - EDGE_TTS_VOICE: Voice ID (default: en-US-MichelleNeural)\n * - EDGE_TTS_LANG: Language code (default: en-US)\n * - EDGE_TTS_OUTPUT_FORMAT: Output format (default: audio-24khz-48kbitrate-mono-mp3)\n * - EDGE_TTS_RATE: Speech rate adjustment (e.g., +10%, -5%)\n * - EDGE_TTS_PITCH: Pitch adjustment (e.g., +5Hz, -10Hz)\n * - EDGE_TTS_VOLUME: Volume adjustment (e.g., +20%, -10%)\n * - EDGE_TTS_PROXY: HTTP proxy URL\n * - EDGE_TTS_TIMEOUT_MS: Request timeout (default: 30000)\n *\n * Popular voices:\n * - en-US-MichelleNeural (female, US English)\n * - en-US-GuyNeural (male, US English)\n * - en-US-JennyNeural (female, US English)\n * - en-US-AriaNeural (female, US English)\n * - en-GB-SoniaNeural (female, UK English)\n * - en-GB-RyanNeural (male, UK English)\n * - de-DE-KatjaNeural (female, German)\n * - fr-FR-DeniseNeural (female, French)\n * - es-ES-ElviraNeural (female, Spanish)\n * - ja-JP-NanamiNeural (female, Japanese)\n * - zh-CN-XiaoxiaoNeural (female, Chinese)\n */\nexport const edgeTTSPlugin: Plugin = {\n name: \"edge-tts\",\n description:\n \"Free text-to-speech synthesis using Microsoft Edge TTS - no API key required, high-quality neural voices\",\n // Self-declared auto-enable: activate when features.tts is enabled OR when\n // running in an Eliza Cloud-provisioned container (cloud voice output).\n autoEnable: {\n shouldEnable: (env, config) => {\n if (env.ELIZA_CLOUD_PROVISIONED === \"1\") return true;\n const f = (config?.features as Record<string, unknown> | undefined)?.tts;\n return (\n f === true ||\n (typeof f === \"object\" && f !== null && (f as { enabled?: unknown }).enabled !== false)\n );\n },\n },\n models: {\n [ModelType.TEXT_TO_SPEECH]: async (\n runtime: IAgentRuntime,\n input: string | EdgeTTSParams\n ): Promise<Buffer | ArrayBuffer | Uint8Array> => {\n const params: EdgeTTSParams = typeof input === \"string\" ? { text: input } : input;\n const settings = getEdgeTTSSettings(runtime);\n\n logger.log(`[EdgeTTS] Using TEXT_TO_SPEECH with voice: ${settings.voice}`);\n\n if (params.text.trim().length === 0) {\n throw new Error(\"TEXT_TO_SPEECH requires non-empty text\");\n }\n\n // Edge TTS has a practical limit around 5000 characters\n if (params.text.length > 5000) {\n throw new Error(\"TEXT_TO_SPEECH text exceeds 5000 character limit\");\n }\n\n try {\n const audioBuffer = await generateSpeech(settings, params);\n return audioBuffer;\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n logger.error(`EdgeTTS model error: ${msg}`);\n throw error instanceof Error ? error : new Error(msg);\n }\n },\n },\n tests: [\n {\n name: \"test edge tts\",\n tests: [\n {\n name: \"Edge TTS settings validation\",\n fn: async (runtime: IAgentRuntime) => {\n const settings = getEdgeTTSSettings(runtime);\n\n if (!settings.voice) {\n throw new Error(\"Missing voice configuration\");\n }\n\n if (!settings.lang) {\n throw new Error(\"Missing language configuration\");\n }\n\n if (!settings.outputFormat) {\n throw new Error(\"Missing output format configuration\");\n }\n\n logger.success(\"Edge TTS settings validated successfully\");\n },\n },\n {\n name: \"Edge TTS voice preset mapping\",\n fn: async (_runtime: IAgentRuntime) => {\n // Test that OpenAI-style voice names map correctly\n const testCases = [\n { input: \"alloy\", expected: \"en-US-GuyNeural\" },\n { input: \"nova\", expected: \"en-US-JennyNeural\" },\n { input: \"shimmer\", expected: \"en-US-AriaNeural\" },\n {\n input: \"en-US-MichelleNeural\",\n expected: \"en-US-MichelleNeural\",\n },\n ];\n\n for (const tc of testCases) {\n const result = resolveVoice(tc.input, DEFAULT_VOICE);\n if (result !== tc.expected) {\n throw new Error(\n `Voice preset mapping failed: ${tc.input} -> ${result}, expected ${tc.expected}`\n );\n }\n }\n\n logger.success(\"Voice preset mapping validated successfully\");\n },\n },\n {\n name: \"Edge TTS speed to rate conversion\",\n fn: async (_runtime: IAgentRuntime) => {\n const testCases = [\n { speed: 1.0, expected: undefined },\n { speed: 1.5, expected: \"+50%\" },\n { speed: 0.75, expected: \"-25%\" },\n { speed: 2.0, expected: \"+100%\" },\n ];\n\n for (const tc of testCases) {\n const result = speedToRate(tc.speed);\n if (result !== tc.expected) {\n throw new Error(\n `Speed conversion failed: ${tc.speed} -> ${result}, expected ${tc.expected}`\n );\n }\n }\n\n logger.success(\"Speed to rate conversion validated successfully\");\n },\n },\n {\n name: \"Edge TTS generation (live test)\",\n fn: async (runtime: IAgentRuntime) => {\n const testText = \"Hello, this is a test of Edge TTS.\";\n\n try {\n const audioBuffer = (await runtime.useModel(ModelType.TEXT_TO_SPEECH, testText)) as\n | Buffer\n | Uint8Array;\n\n if (!audioBuffer || audioBuffer.length === 0) {\n throw new Error(\"Received empty audio buffer\");\n }\n\n logger.success(`Edge TTS generation successful: ${audioBuffer.length} bytes`);\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n // Edge TTS might fail in CI environments without network\n if (msg.includes(\"ENOTFOUND\") || msg.includes(\"network\")) {\n logger.warn(`Edge TTS live test skipped (network unavailable): ${msg}`);\n return;\n }\n throw error;\n }\n },\n },\n ],\n },\n ],\n};\n\nexport default edgeTTSPlugin;\n\n// Re-export types\nexport type { EdgeTTSParams, EdgeTTSSettings };\n\n// Export helper functions for testing\nexport const _test = {\n resolveVoice,\n speedToRate,\n inferExtension,\n getEdgeTTSSettings,\n};\n"
6
6
  ],
7
- "mappings": "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",
8
- "debugId": "72B923D58112D3ED64756E2164756E21",
7
+ "mappings": "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",
8
+ "debugId": "E6E8C4F38067800864756E2164756E21",
9
9
  "names": []
10
10
  }
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@elizaos/plugin-edge-tts",
3
- "version": "2.0.0-alpha.9",
3
+ "version": "2.0.0-beta.1",
4
4
  "type": "module",
5
- "main": "dist/cjs/index.node.cjs",
5
+ "main": "dist/node/index.node.js",
6
6
  "module": "dist/node/index.node.js",
7
7
  "types": "dist/index.d.ts",
8
8
  "browser": "dist/browser/index.browser.js",
@@ -24,7 +24,6 @@
24
24
  "node": {
25
25
  "types": "./dist/node/index.d.ts",
26
26
  "import": "./dist/node/index.node.js",
27
- "require": "./dist/cjs/index.node.cjs",
28
27
  "default": "./dist/node/index.node.js"
29
28
  },
30
29
  "default": "./dist/node/index.node.js"
@@ -41,28 +40,39 @@
41
40
  }
42
41
  },
43
42
  "files": [
44
- "dist"
43
+ "dist",
44
+ "auto-enable.ts"
45
45
  ],
46
+ "elizaos": {
47
+ "plugin": {
48
+ "autoEnableModule": "./auto-enable.ts",
49
+ "capabilities": [
50
+ "text-to-speech"
51
+ ]
52
+ }
53
+ },
46
54
  "dependencies": {
47
- "@elizaos/core": "alpha",
55
+ "@elizaos/core": "2.0.0-beta.1",
48
56
  "node-edge-tts": "^1.0.7"
49
57
  },
50
58
  "devDependencies": {
59
+ "@biomejs/biome": "^2.4.14",
51
60
  "@types/bun": "^1.2.22",
52
61
  "@types/node": "^24.5.2",
53
- "typescript": "^5.9.2",
54
- "@biomejs/biome": "^2.3.11"
62
+ "typescript": "^6.0.3"
55
63
  },
56
64
  "scripts": {
57
65
  "build": "bun run build.ts",
58
66
  "dev": "bun --hot build.ts",
59
- "test": "npx -y vitest@4.0.18 run --passWithNoTests",
60
- "clean": "rm -rf dist .turbo node_modules .turbo-tsconfig.json tsconfig.tsbuildinfo",
67
+ "test": "vitest run --config ./vitest.config.ts",
68
+ "clean": "rm -rf dist .turbo .turbo-tsconfig.json tsconfig.tsbuildinfo",
61
69
  "format": "bunx @biomejs/biome format --write .",
62
70
  "format:check": "bunx @biomejs/biome format .",
63
71
  "lint": "bunx @biomejs/biome check --write --unsafe .",
64
72
  "lint:check": "bunx @biomejs/biome check .",
65
- "typecheck": "tsc --noEmit"
73
+ "typecheck": "tsc --noEmit",
74
+ "test:e2e": "node ../../packages/app-core/scripts/run-local-plugin-live-smoke.mjs",
75
+ "test:live": "bun run test:e2e"
66
76
  },
67
77
  "publishConfig": {
68
78
  "access": "public"
@@ -124,7 +134,7 @@
124
134
  }
125
135
  }
126
136
  },
127
- "milady": {
137
+ "eliza": {
128
138
  "platforms": [
129
139
  "browser",
130
140
  "node"