claude-voice 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +395 -0
  3. package/bin/claude-voice +29 -0
  4. package/config/default.json +109 -0
  5. package/config/voice-prompt.md +27 -0
  6. package/dist/cli.d.ts +8 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +1103 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/config.d.ts +140 -0
  11. package/dist/config.d.ts.map +1 -0
  12. package/dist/config.js +179 -0
  13. package/dist/config.js.map +1 -0
  14. package/dist/env.d.ts +40 -0
  15. package/dist/env.d.ts.map +1 -0
  16. package/dist/env.js +175 -0
  17. package/dist/env.js.map +1 -0
  18. package/dist/index.d.ts +10 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +140 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/platform/index.d.ts +35 -0
  23. package/dist/platform/index.d.ts.map +1 -0
  24. package/dist/platform/index.js +170 -0
  25. package/dist/platform/index.js.map +1 -0
  26. package/dist/server.d.ts +5 -0
  27. package/dist/server.d.ts.map +1 -0
  28. package/dist/server.js +185 -0
  29. package/dist/server.js.map +1 -0
  30. package/dist/stt/index.d.ts +15 -0
  31. package/dist/stt/index.d.ts.map +1 -0
  32. package/dist/stt/index.js +54 -0
  33. package/dist/stt/index.js.map +1 -0
  34. package/dist/stt/providers/openai.d.ts +15 -0
  35. package/dist/stt/providers/openai.d.ts.map +1 -0
  36. package/dist/stt/providers/openai.js +74 -0
  37. package/dist/stt/providers/openai.js.map +1 -0
  38. package/dist/stt/providers/sherpa-onnx.d.ts +50 -0
  39. package/dist/stt/providers/sherpa-onnx.d.ts.map +1 -0
  40. package/dist/stt/providers/sherpa-onnx.js +237 -0
  41. package/dist/stt/providers/sherpa-onnx.js.map +1 -0
  42. package/dist/stt/providers/whisper-local.d.ts +19 -0
  43. package/dist/stt/providers/whisper-local.d.ts.map +1 -0
  44. package/dist/stt/providers/whisper-local.js +141 -0
  45. package/dist/stt/providers/whisper-local.js.map +1 -0
  46. package/dist/terminal/input-injector.d.ts +55 -0
  47. package/dist/terminal/input-injector.d.ts.map +1 -0
  48. package/dist/terminal/input-injector.js +189 -0
  49. package/dist/terminal/input-injector.js.map +1 -0
  50. package/dist/tts/index.d.ts +20 -0
  51. package/dist/tts/index.d.ts.map +1 -0
  52. package/dist/tts/index.js +72 -0
  53. package/dist/tts/index.js.map +1 -0
  54. package/dist/tts/providers/elevenlabs.d.ts +23 -0
  55. package/dist/tts/providers/elevenlabs.d.ts.map +1 -0
  56. package/dist/tts/providers/elevenlabs.js +142 -0
  57. package/dist/tts/providers/elevenlabs.js.map +1 -0
  58. package/dist/tts/providers/macos-say.d.ts +17 -0
  59. package/dist/tts/providers/macos-say.d.ts.map +1 -0
  60. package/dist/tts/providers/macos-say.js +72 -0
  61. package/dist/tts/providers/macos-say.js.map +1 -0
  62. package/dist/tts/providers/openai.d.ts +19 -0
  63. package/dist/tts/providers/openai.d.ts.map +1 -0
  64. package/dist/tts/providers/openai.js +118 -0
  65. package/dist/tts/providers/openai.js.map +1 -0
  66. package/dist/tts/providers/piper.d.ts +48 -0
  67. package/dist/tts/providers/piper.d.ts.map +1 -0
  68. package/dist/tts/providers/piper.js +417 -0
  69. package/dist/tts/providers/piper.js.map +1 -0
  70. package/dist/voice-input.d.ts +9 -0
  71. package/dist/voice-input.d.ts.map +1 -0
  72. package/dist/voice-input.js +137 -0
  73. package/dist/voice-input.js.map +1 -0
  74. package/dist/wake-word/index.d.ts +19 -0
  75. package/dist/wake-word/index.d.ts.map +1 -0
  76. package/dist/wake-word/index.js +200 -0
  77. package/dist/wake-word/index.js.map +1 -0
  78. package/dist/wake-word/recorder.d.ts +19 -0
  79. package/dist/wake-word/recorder.d.ts.map +1 -0
  80. package/dist/wake-word/recorder.js +145 -0
  81. package/dist/wake-word/recorder.js.map +1 -0
  82. package/hooks/notification.js +125 -0
  83. package/hooks/post-tool-use.js +374 -0
  84. package/hooks/session-start.js +212 -0
  85. package/hooks/stop.js +254 -0
  86. package/models/.gitkeep +0 -0
  87. package/package.json +80 -0
  88. package/python/stt_service.py +59 -0
  89. package/python/voice_input.py +154 -0
  90. package/scripts/install.sh +147 -0
  91. package/scripts/listen.py +161 -0
  92. package/scripts/postinstall.js +57 -0
  93. package/scripts/record.sh +79 -0
  94. package/scripts/setup-hooks.sh +22 -0
  95. package/scripts/voice-input.sh +66 -0
@@ -0,0 +1,189 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TerminalInputInjector = void 0;
4
+ exports.sendToClaudeCode = sendToClaudeCode;
5
+ const child_process_1 = require("child_process");
6
+ const util_1 = require("util");
7
+ const execAsync = (0, util_1.promisify)(child_process_1.exec);
8
+ /**
9
+ * Injects text into the terminal using AppleScript on macOS.
10
+ * This allows voice-transcribed text to be sent to Claude Code.
11
+ */
12
+ class TerminalInputInjector {
13
+ terminal;
14
+ constructor(options = {}) {
15
+ if (options.terminal === 'auto' || !options.terminal) {
16
+ // Auto-detect: prefer iTerm if running, otherwise Terminal
17
+ this.terminal = 'Terminal';
18
+ }
19
+ else {
20
+ this.terminal = options.terminal;
21
+ }
22
+ }
23
+ /**
24
+ * Types text into the active terminal window
25
+ */
26
+ async type(text, pressEnter = true) {
27
+ if (process.platform !== 'darwin') {
28
+ throw new Error('Terminal input injection is only supported on macOS');
29
+ }
30
+ // Escape special characters for AppleScript
31
+ const escapedText = this.escapeForAppleScript(text);
32
+ const script = this.generateAppleScript(escapedText, pressEnter);
33
+ try {
34
+ await this.runAppleScript(script);
35
+ }
36
+ catch (error) {
37
+ // Try the other terminal app
38
+ const alternateTerminal = this.terminal === 'Terminal' ? 'iTerm' : 'Terminal';
39
+ const alternateScript = this.generateAppleScript(escapedText, pressEnter, alternateTerminal);
40
+ try {
41
+ await this.runAppleScript(alternateScript);
42
+ }
43
+ catch {
44
+ throw new Error(`Failed to inject text into terminal: ${error}`);
45
+ }
46
+ }
47
+ }
48
+ /**
49
+ * Runs an AppleScript, handling multi-line scripts properly
50
+ */
51
+ async runAppleScript(script) {
52
+ // Split script into lines and use multiple -e arguments
53
+ const lines = script.split('\n').filter(line => line.trim());
54
+ const args = lines.map(line => `-e '${line.replace(/'/g, "'\\''")}'`).join(' ');
55
+ await execAsync(`osascript ${args}`);
56
+ }
57
+ /**
58
+ * Types text character by character with a delay (for visual effect)
59
+ */
60
+ async typeSlowly(text, delayMs = 50, pressEnter = true) {
61
+ for (const char of text) {
62
+ await this.type(char, false);
63
+ await this.delay(delayMs);
64
+ }
65
+ if (pressEnter) {
66
+ await this.pressKey('return');
67
+ }
68
+ }
69
+ /**
70
+ * Simulates pressing a key
71
+ */
72
+ async pressKey(key) {
73
+ if (process.platform !== 'darwin') {
74
+ throw new Error('Key press simulation is only supported on macOS');
75
+ }
76
+ const keyCode = this.getKeyCode(key);
77
+ const script = `
78
+ tell application "System Events"
79
+ key code ${keyCode}
80
+ end tell
81
+ `;
82
+ await execAsync(`osascript -e '${script.replace(/'/g, "'\\''")}'`);
83
+ }
84
+ generateAppleScript(text, pressEnter, terminal) {
85
+ const app = terminal || this.terminal;
86
+ if (app === 'iTerm') {
87
+ return `
88
+ tell application "iTerm"
89
+ tell current session of current window
90
+ write text "${text}"${pressEnter ? '' : ' without newline'}
91
+ end tell
92
+ end tell
93
+ `.replace(/\n/g, ' ');
94
+ }
95
+ // Default: Terminal.app
96
+ // For Terminal, we use System Events to type
97
+ // Note: keystroke and key code must be separate statements
98
+ if (pressEnter) {
99
+ return `tell application "Terminal" to activate
100
+ delay 0.1
101
+ tell application "System Events"
102
+ keystroke "${text}"
103
+ key code 36
104
+ end tell`;
105
+ }
106
+ return `tell application "Terminal" to activate
107
+ delay 0.1
108
+ tell application "System Events"
109
+ keystroke "${text}"
110
+ end tell`;
111
+ }
112
+ escapeForAppleScript(text) {
113
+ return text
114
+ .replace(/\\/g, '\\\\') // Escape backslashes first
115
+ .replace(/"/g, '\\"') // Escape double quotes
116
+ .replace(/\n/g, '\\n') // Escape newlines
117
+ .replace(/\r/g, '\\r') // Escape carriage returns
118
+ .replace(/\t/g, '\\t'); // Escape tabs
119
+ }
120
+ getKeyCode(key) {
121
+ const keyCodes = {
122
+ return: 36,
123
+ enter: 36,
124
+ tab: 48,
125
+ space: 49,
126
+ delete: 51,
127
+ escape: 53,
128
+ command: 55,
129
+ shift: 56,
130
+ capslock: 57,
131
+ option: 58,
132
+ control: 59,
133
+ fn: 63,
134
+ f1: 122,
135
+ f2: 120,
136
+ f3: 99,
137
+ f4: 118,
138
+ f5: 96,
139
+ f6: 97,
140
+ f7: 98,
141
+ f8: 100,
142
+ f9: 101,
143
+ f10: 109,
144
+ f11: 103,
145
+ f12: 111,
146
+ home: 115,
147
+ pageup: 116,
148
+ forwarddelete: 117,
149
+ end: 119,
150
+ pagedown: 121,
151
+ left: 123,
152
+ right: 124,
153
+ down: 125,
154
+ up: 126,
155
+ };
156
+ return keyCodes[key.toLowerCase()] || 0;
157
+ }
158
+ delay(ms) {
159
+ return new Promise((resolve) => setTimeout(resolve, ms));
160
+ }
161
+ /**
162
+ * Check if we're running inside a terminal
163
+ */
164
+ static isInTerminal() {
165
+ return !!(process.stdout.isTTY && (process.env.TERM || process.env.TERM_PROGRAM));
166
+ }
167
+ /**
168
+ * Detect the current terminal application
169
+ */
170
+ static detectTerminal() {
171
+ const termProgram = process.env.TERM_PROGRAM;
172
+ if (termProgram === 'Apple_Terminal') {
173
+ return 'Terminal';
174
+ }
175
+ if (termProgram === 'iTerm.app') {
176
+ return 'iTerm';
177
+ }
178
+ return 'unknown';
179
+ }
180
+ }
181
+ exports.TerminalInputInjector = TerminalInputInjector;
182
+ /**
183
+ * Convenience function to send voice-transcribed text to Claude Code
184
+ */
185
+ async function sendToClaudeCode(text) {
186
+ const injector = new TerminalInputInjector({ terminal: 'auto' });
187
+ await injector.type(text, true);
188
+ }
189
+ //# sourceMappingURL=input-injector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-injector.js","sourceRoot":"","sources":["../../src/terminal/input-injector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { TTSConfig } from '../config';
2
+ export interface TTSProvider {
3
+ name: string;
4
+ speak(text: string): Promise<void>;
5
+ stop(): void;
6
+ isReady(): boolean;
7
+ }
8
+ export declare class TTSManager {
9
+ private provider;
10
+ private queue;
11
+ private isPlaying;
12
+ constructor(config: TTSConfig);
13
+ private createProvider;
14
+ speak(text: string, priority?: boolean): Promise<void>;
15
+ private processQueue;
16
+ stop(): void;
17
+ isReady(): boolean;
18
+ getProviderName(): string;
19
+ }
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tts/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAMtC,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,IAAI,IAAI,IAAI,CAAC;IACb,OAAO,IAAI,OAAO,CAAC;CACpB;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAc;IAC9B,OAAO,CAAC,KAAK,CAA6C;IAC1D,OAAO,CAAC,SAAS,CAAS;gBAEd,MAAM,EAAE,SAAS;IAI7B,OAAO,CAAC,cAAc;IAgBhB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;YAY5C,YAAY;IAqB1B,IAAI,IAAI,IAAI;IAMZ,OAAO,IAAI,OAAO;IAIlB,eAAe,IAAI,MAAM;CAG1B"}
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TTSManager = void 0;
4
+ const macos_say_1 = require("./providers/macos-say");
5
+ const openai_1 = require("./providers/openai");
6
+ const elevenlabs_1 = require("./providers/elevenlabs");
7
+ const piper_1 = require("./providers/piper");
8
+ class TTSManager {
9
+ provider;
10
+ queue = [];
11
+ isPlaying = false;
12
+ constructor(config) {
13
+ this.provider = this.createProvider(config);
14
+ }
15
+ createProvider(config) {
16
+ switch (config.provider) {
17
+ case 'macos-say':
18
+ return new macos_say_1.MacOSSayProvider(config.macos);
19
+ case 'openai':
20
+ return new openai_1.OpenAITTSProvider(config.openai);
21
+ case 'elevenlabs':
22
+ return new elevenlabs_1.ElevenLabsProvider(config.elevenlabs);
23
+ case 'piper':
24
+ return new piper_1.PiperProvider(config.piper);
25
+ default:
26
+ console.warn(`Unknown TTS provider: ${config.provider}, falling back to macos-say`);
27
+ return new macos_say_1.MacOSSayProvider(config.macos);
28
+ }
29
+ }
30
+ async speak(text, priority = false) {
31
+ if (priority) {
32
+ // High priority: stop current playback and insert at front
33
+ this.stop();
34
+ this.queue.unshift({ text, priority });
35
+ }
36
+ else {
37
+ this.queue.push({ text, priority });
38
+ }
39
+ await this.processQueue();
40
+ }
41
+ async processQueue() {
42
+ if (this.isPlaying || this.queue.length === 0) {
43
+ return;
44
+ }
45
+ this.isPlaying = true;
46
+ while (this.queue.length > 0) {
47
+ const item = this.queue.shift();
48
+ if (item) {
49
+ try {
50
+ await this.provider.speak(item.text);
51
+ }
52
+ catch (error) {
53
+ console.error('TTS error:', error);
54
+ }
55
+ }
56
+ }
57
+ this.isPlaying = false;
58
+ }
59
+ stop() {
60
+ this.queue = [];
61
+ this.provider.stop();
62
+ this.isPlaying = false;
63
+ }
64
+ isReady() {
65
+ return this.provider.isReady();
66
+ }
67
+ getProviderName() {
68
+ return this.provider.name;
69
+ }
70
+ }
71
+ exports.TTSManager = TTSManager;
72
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tts/index.ts"],"names":[],"mappings":";;;AACA,qDAAyD;AACzD,+CAAuD;AACvD,uDAA4D;AAC5D,6CAAkD;AASlD,MAAa,UAAU;IACb,QAAQ,CAAc;IACtB,KAAK,GAA0C,EAAE,CAAC;IAClD,SAAS,GAAG,KAAK,CAAC;IAE1B,YAAY,MAAiB;QAC3B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IAC9C,CAAC;IAEO,cAAc,CAAC,MAAiB;QACtC,QAAQ,MAAM,CAAC,QAAQ,EAAE,CAAC;YACxB,KAAK,WAAW;gBACd,OAAO,IAAI,4BAAgB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC5C,KAAK,QAAQ;gBACX,OAAO,IAAI,0BAAiB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC9C,KAAK,YAAY;gBACf,OAAO,IAAI,+BAAkB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YACnD,KAAK,OAAO;gBACV,OAAO,IAAI,qBAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACzC;gBACE,OAAO,CAAC,IAAI,CAAC,yBAAyB,MAAM,CAAC,QAAQ,6BAA6B,CAAC,CAAC;gBACpF,OAAO,IAAI,4BAAgB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,IAAY,EAAE,QAAQ,GAAG,KAAK;QACxC,IAAI,QAAQ,EAAE,CAAC;YACb,2DAA2D;YAC3D,IAAI,CAAC,IAAI,EAAE,CAAC;YACZ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QACtC,CAAC;QAED,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;IAC5B,CAAC;IAEO,KAAK,CAAC,YAAY;QACxB,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9C,OAAO;QACT,CAAC;QAED,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QAEtB,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YAChC,IAAI,IAAI,EAAE,CAAC;gBACT,IAAI,CAAC;oBACH,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACvC,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,OAAO,CAAC,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;gBACrC,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;IACzB,CAAC;IAED,IAAI;QACF,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACrB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;IACzB,CAAC;IAED,OAAO;QACL,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;IACjC,CAAC;IAED,eAAe;QACb,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;IAC5B,CAAC;CACF;AAvED,gCAuEC"}
@@ -0,0 +1,23 @@
1
+ import { TTSProvider } from '../index';
2
+ interface ElevenLabsConfig {
3
+ voiceId: string;
4
+ modelId: string;
5
+ }
6
+ export declare class ElevenLabsProvider implements TTSProvider {
7
+ name: string;
8
+ private config;
9
+ private apiKey;
10
+ private currentProcess;
11
+ private ready;
12
+ constructor(config: ElevenLabsConfig);
13
+ speak(text: string): Promise<void>;
14
+ private playAudio;
15
+ stop(): void;
16
+ isReady(): boolean;
17
+ }
18
+ export declare function listVoices(apiKey: string): Promise<{
19
+ voice_id: string;
20
+ name: string;
21
+ }[]>;
22
+ export {};
23
+ //# sourceMappingURL=elevenlabs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elevenlabs.d.ts","sourceRoot":"","sources":["../../../src/tts/providers/elevenlabs.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAMvC,UAAU,gBAAgB;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAID,qBAAa,kBAAmB,YAAW,WAAW;IACpD,IAAI,SAAgB;IACpB,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,cAAc,CAA6B;IACnD,OAAO,CAAC,KAAK,CAAS;gBAEV,MAAM,EAAE,gBAAgB;IAiB9B,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA0CxC,OAAO,CAAC,SAAS;IAwBjB,IAAI,IAAI,IAAI;IAOZ,OAAO,IAAI,OAAO;CAGnB;AAGD,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CAW9F"}
@@ -0,0 +1,142 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.ElevenLabsProvider = void 0;
40
+ exports.listVoices = listVoices;
41
+ const axios_1 = __importDefault(require("axios"));
42
+ const child_process_1 = require("child_process");
43
+ const fs = __importStar(require("fs"));
44
+ const path = __importStar(require("path"));
45
+ const os = __importStar(require("os"));
46
+ const ELEVENLABS_API_URL = 'https://api.elevenlabs.io/v1';
47
+ class ElevenLabsProvider {
48
+ name = 'elevenlabs';
49
+ config;
50
+ apiKey;
51
+ currentProcess = null;
52
+ ready = false;
53
+ constructor(config) {
54
+ this.config = config;
55
+ this.apiKey = process.env.ELEVENLABS_API_KEY;
56
+ if (!this.apiKey) {
57
+ console.warn('ELEVENLABS_API_KEY not set. ElevenLabs TTS will not work.');
58
+ return;
59
+ }
60
+ if (!config.voiceId) {
61
+ console.warn('ElevenLabs voiceId not configured.');
62
+ return;
63
+ }
64
+ this.ready = true;
65
+ }
66
+ async speak(text) {
67
+ if (!this.apiKey || !this.config.voiceId) {
68
+ throw new Error('ElevenLabs not configured. Set ELEVENLABS_API_KEY and voiceId.');
69
+ }
70
+ const url = `${ELEVENLABS_API_URL}/text-to-speech/${this.config.voiceId}`;
71
+ const response = await axios_1.default.post(url, {
72
+ text,
73
+ model_id: this.config.modelId,
74
+ voice_settings: {
75
+ stability: 0.5,
76
+ similarity_boost: 0.75,
77
+ },
78
+ }, {
79
+ headers: {
80
+ Accept: 'audio/mpeg',
81
+ 'Content-Type': 'application/json',
82
+ 'xi-api-key': this.apiKey,
83
+ },
84
+ responseType: 'arraybuffer',
85
+ });
86
+ // Save to temporary file
87
+ const tempFile = path.join(os.tmpdir(), `tts-${Date.now()}.mp3`);
88
+ fs.writeFileSync(tempFile, Buffer.from(response.data));
89
+ // Play the audio file
90
+ await this.playAudio(tempFile);
91
+ // Cleanup
92
+ try {
93
+ fs.unlinkSync(tempFile);
94
+ }
95
+ catch {
96
+ // Ignore cleanup errors
97
+ }
98
+ }
99
+ playAudio(filePath) {
100
+ return new Promise((resolve, reject) => {
101
+ const player = process.platform === 'darwin' ? 'afplay' : 'ffplay';
102
+ const args = process.platform === 'darwin' ? [filePath] : ['-nodisp', '-autoexit', '-loglevel', 'quiet', filePath];
103
+ this.currentProcess = (0, child_process_1.spawn)(player, args);
104
+ this.currentProcess.on('close', (code) => {
105
+ this.currentProcess = null;
106
+ if (code === 0) {
107
+ resolve();
108
+ }
109
+ else {
110
+ reject(new Error(`Audio player exited with code ${code}`));
111
+ }
112
+ });
113
+ this.currentProcess.on('error', (error) => {
114
+ this.currentProcess = null;
115
+ reject(error);
116
+ });
117
+ });
118
+ }
119
+ stop() {
120
+ if (this.currentProcess) {
121
+ this.currentProcess.kill('SIGTERM');
122
+ this.currentProcess = null;
123
+ }
124
+ }
125
+ isReady() {
126
+ return this.ready;
127
+ }
128
+ }
129
+ exports.ElevenLabsProvider = ElevenLabsProvider;
130
+ // Get available voices from ElevenLabs
131
+ async function listVoices(apiKey) {
132
+ const response = await axios_1.default.get(`${ELEVENLABS_API_URL}/voices`, {
133
+ headers: {
134
+ 'xi-api-key': apiKey,
135
+ },
136
+ });
137
+ return response.data.voices.map((v) => ({
138
+ voice_id: v.voice_id,
139
+ name: v.name,
140
+ }));
141
+ }
142
+ //# sourceMappingURL=elevenlabs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elevenlabs.js","sourceRoot":"","sources":["../../../src/tts/providers/elevenlabs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { TTSProvider } from '../index';
2
+ interface MacOSSayConfig {
3
+ voice: string;
4
+ rate: number;
5
+ }
6
+ export declare class MacOSSayProvider implements TTSProvider {
7
+ name: string;
8
+ private config;
9
+ private currentProcess;
10
+ constructor(config: MacOSSayConfig);
11
+ speak(text: string): Promise<void>;
12
+ stop(): void;
13
+ isReady(): boolean;
14
+ }
15
+ export declare function listVoices(): Promise<string[]>;
16
+ export {};
17
+ //# sourceMappingURL=macos-say.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"macos-say.d.ts","sourceRoot":"","sources":["../../../src/tts/providers/macos-say.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEvC,UAAU,cAAc;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,qBAAa,gBAAiB,YAAW,WAAW;IAClD,IAAI,SAAe;IACnB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,cAAc,CAA6B;gBAEvC,MAAM,EAAE,cAAc;IAI5B,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAyBxC,IAAI,IAAI,IAAI;IAOZ,OAAO,IAAI,OAAO;CAInB;AAGD,wBAAsB,UAAU,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAyBpD"}
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MacOSSayProvider = void 0;
4
+ exports.listVoices = listVoices;
5
+ const child_process_1 = require("child_process");
6
+ class MacOSSayProvider {
7
+ name = 'macos-say';
8
+ config;
9
+ currentProcess = null;
10
+ constructor(config) {
11
+ this.config = config;
12
+ }
13
+ async speak(text) {
14
+ return new Promise((resolve, reject) => {
15
+ // Clean text for shell safety
16
+ const cleanText = text.replace(/"/g, '\\"');
17
+ const args = ['-v', this.config.voice, '-r', String(this.config.rate), cleanText];
18
+ this.currentProcess = (0, child_process_1.spawn)('say', args);
19
+ this.currentProcess.on('close', (code) => {
20
+ this.currentProcess = null;
21
+ if (code === 0) {
22
+ resolve();
23
+ }
24
+ else {
25
+ reject(new Error(`say command exited with code ${code}`));
26
+ }
27
+ });
28
+ this.currentProcess.on('error', (error) => {
29
+ this.currentProcess = null;
30
+ reject(error);
31
+ });
32
+ });
33
+ }
34
+ stop() {
35
+ if (this.currentProcess) {
36
+ this.currentProcess.kill('SIGTERM');
37
+ this.currentProcess = null;
38
+ }
39
+ }
40
+ isReady() {
41
+ // macOS say is always available on macOS
42
+ return process.platform === 'darwin';
43
+ }
44
+ }
45
+ exports.MacOSSayProvider = MacOSSayProvider;
46
+ // List available voices on macOS
47
+ async function listVoices() {
48
+ return new Promise((resolve, reject) => {
49
+ const proc = (0, child_process_1.spawn)('say', ['-v', '?']);
50
+ let output = '';
51
+ proc.stdout.on('data', (data) => {
52
+ output += data.toString();
53
+ });
54
+ proc.on('close', (code) => {
55
+ if (code === 0) {
56
+ const voices = output
57
+ .split('\n')
58
+ .filter((line) => line.trim())
59
+ .map((line) => {
60
+ const match = line.match(/^(\S+)/);
61
+ return match ? match[1] : '';
62
+ })
63
+ .filter((v) => v);
64
+ resolve(voices);
65
+ }
66
+ else {
67
+ reject(new Error('Failed to list voices'));
68
+ }
69
+ });
70
+ });
71
+ }
72
+ //# sourceMappingURL=macos-say.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"macos-say.js","sourceRoot":"","sources":["../../../src/tts/providers/macos-say.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { TTSProvider } from '../index';
2
+ interface OpenAITTSConfig {
3
+ model: 'tts-1' | 'tts-1-hd';
4
+ voice: 'alloy' | 'echo' | 'fable' | 'onyx' | 'nova' | 'shimmer';
5
+ }
6
+ export declare class OpenAITTSProvider implements TTSProvider {
7
+ name: string;
8
+ private config;
9
+ private client;
10
+ private currentProcess;
11
+ private ready;
12
+ constructor(config: OpenAITTSConfig);
13
+ speak(text: string): Promise<void>;
14
+ private playAudio;
15
+ stop(): void;
16
+ isReady(): boolean;
17
+ }
18
+ export {};
19
+ //# sourceMappingURL=openai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../../src/tts/providers/openai.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAMvC,UAAU,eAAe;IACvB,KAAK,EAAE,OAAO,GAAG,UAAU,CAAC;IAC5B,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACjE;AAED,qBAAa,iBAAkB,YAAW,WAAW;IACnD,IAAI,SAAgB;IACpB,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,cAAc,CAA6B;IACnD,OAAO,CAAC,KAAK,CAAS;gBAEV,MAAM,EAAE,eAAe;IAc7B,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BxC,OAAO,CAAC,SAAS;IAyBjB,IAAI,IAAI,IAAI;IAOZ,OAAO,IAAI,OAAO;CAGnB"}