@elizaos/capacitor-talkmode 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.
@@ -0,0 +1,214 @@
1
+ 'use strict';
2
+
3
+ var core = require('@capacitor/core');
4
+
5
+ const loadWeb = () => Promise.resolve().then(function () { return web; }).then((m) => new m.TalkModeWeb());
6
+ const TalkMode = core.registerPlugin("TalkMode", {
7
+ web: loadWeb,
8
+ });
9
+
10
+ /**
11
+ * Web implementation of TalkMode plugin
12
+ *
13
+ * Uses Web Speech API for TTS with limited functionality compared to native.
14
+ * ElevenLabs streaming is not supported on web due to CORS limitations.
15
+ */
16
+ class TalkModeWeb extends core.WebPlugin {
17
+ constructor() {
18
+ super();
19
+ this.config = {};
20
+ this.state = "idle";
21
+ this.statusText = "Off";
22
+ this.synthesis = null;
23
+ this.currentUtterance = null;
24
+ this.recognition = null;
25
+ this.enabled = false;
26
+ if (typeof window !== "undefined" && window.speechSynthesis) {
27
+ this.synthesis = window.speechSynthesis;
28
+ }
29
+ }
30
+ async start(options) {
31
+ if (options?.config) {
32
+ this.config = { ...this.config, ...options.config };
33
+ }
34
+ // Check for Web Speech API support
35
+ const SpeechRecognitionAPI = window.SpeechRecognition ||
36
+ window.webkitSpeechRecognition;
37
+ if (!SpeechRecognitionAPI) {
38
+ return {
39
+ started: false,
40
+ error: "Speech recognition not supported on this browser",
41
+ };
42
+ }
43
+ if (!this.synthesis) {
44
+ console.warn("[TalkMode] Speech synthesis not available on web");
45
+ }
46
+ this.enabled = true;
47
+ this.setState("listening", "Listening");
48
+ // Initialize speech recognition
49
+ this.recognition = new SpeechRecognitionAPI();
50
+ this.recognition.continuous = true;
51
+ this.recognition.interimResults = true;
52
+ this.recognition.onresult = (event) => {
53
+ const result = event.results[event.results.length - 1];
54
+ const transcript = result[0].transcript;
55
+ const isFinal = result.isFinal;
56
+ this.notifyListeners("transcript", { transcript, isFinal });
57
+ if (isFinal && transcript.trim()) ;
58
+ };
59
+ this.recognition.onerror = (event) => {
60
+ this.notifyListeners("error", {
61
+ code: event.error,
62
+ message: event.message || event.error,
63
+ recoverable: event.error !== "not-allowed",
64
+ });
65
+ };
66
+ this.recognition.onend = () => {
67
+ if (this.enabled && this.state === "listening") {
68
+ // Restart recognition if still enabled
69
+ try {
70
+ this.recognition?.start();
71
+ }
72
+ catch (err) {
73
+ const msg = err instanceof Error ? err.message : String(err);
74
+ if (!msg.includes("already started")) {
75
+ console.warn("[TalkMode] Failed to restart recognition:", msg);
76
+ }
77
+ }
78
+ }
79
+ };
80
+ try {
81
+ this.recognition.start();
82
+ return { started: true };
83
+ }
84
+ catch (error) {
85
+ const message = error instanceof Error ? error.message : "Failed to start";
86
+ return { started: false, error: message };
87
+ }
88
+ }
89
+ async stop() {
90
+ this.enabled = false;
91
+ this.recognition?.stop();
92
+ this.recognition = null;
93
+ this.synthesis?.cancel();
94
+ this.currentUtterance = null;
95
+ this.setState("idle", "Off");
96
+ }
97
+ async isEnabled() {
98
+ return { enabled: this.enabled };
99
+ }
100
+ async getState() {
101
+ return { state: this.state, statusText: this.statusText };
102
+ }
103
+ async updateConfig(options) {
104
+ this.config = { ...this.config, ...options.config };
105
+ }
106
+ async speak(options) {
107
+ if (!this.synthesis) {
108
+ return {
109
+ completed: false,
110
+ interrupted: false,
111
+ usedSystemTts: false,
112
+ error: "Speech synthesis not available",
113
+ };
114
+ }
115
+ // Web can only use system TTS (no ElevenLabs due to CORS)
116
+ const text = options.text.trim();
117
+ if (!text) {
118
+ return { completed: true, interrupted: false, usedSystemTts: true };
119
+ }
120
+ this.setState("speaking", "Speaking");
121
+ this.notifyListeners("speaking", { text, isSystemTts: true });
122
+ return new Promise((resolve) => {
123
+ const utterance = new SpeechSynthesisUtterance(text);
124
+ this.currentUtterance = utterance;
125
+ // Always set language — fallback to en-US if directive doesn't specify.
126
+ // Without this, the browser uses the system locale, which may read
127
+ // numbers in the wrong language (e.g., Chinese on a Chinese-locale system).
128
+ utterance.lang = options.directive?.language || "en-US";
129
+ // Apply directive settings if available
130
+ if (options.directive?.speed) {
131
+ utterance.rate = options.directive.speed;
132
+ }
133
+ utterance.onend = () => {
134
+ this.currentUtterance = null;
135
+ this.notifyListeners("speakComplete", { completed: true });
136
+ this.setState("listening", "Listening");
137
+ resolve({ completed: true, interrupted: false, usedSystemTts: true });
138
+ };
139
+ utterance.onerror = (event) => {
140
+ this.currentUtterance = null;
141
+ this.notifyListeners("speakComplete", { completed: false });
142
+ this.setState("idle", "Speech error");
143
+ resolve({
144
+ completed: false,
145
+ interrupted: event.error === "interrupted",
146
+ usedSystemTts: true,
147
+ error: event.error,
148
+ });
149
+ };
150
+ this.synthesis?.speak(utterance);
151
+ });
152
+ }
153
+ async stopSpeaking() {
154
+ if (this.synthesis && this.currentUtterance) {
155
+ this.synthesis.cancel();
156
+ this.currentUtterance = null;
157
+ return { interruptedAt: undefined };
158
+ }
159
+ return {};
160
+ }
161
+ async isSpeaking() {
162
+ return { speaking: this.synthesis?.speaking ?? false };
163
+ }
164
+ async checkPermissions() {
165
+ // Check microphone permission
166
+ let microphone = "prompt";
167
+ try {
168
+ const result = await navigator.permissions.query({
169
+ name: "microphone",
170
+ });
171
+ microphone = result.state;
172
+ }
173
+ catch {
174
+ // Permissions API may not support microphone query
175
+ }
176
+ // Check if speech recognition is supported
177
+ const SpeechRecognitionAPI = window.SpeechRecognition ||
178
+ window.webkitSpeechRecognition;
179
+ const speechRecognition = SpeechRecognitionAPI ? "prompt" : "not_supported";
180
+ return { microphone, speechRecognition };
181
+ }
182
+ async requestPermissions() {
183
+ // Request microphone permission by attempting to get user media
184
+ try {
185
+ const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
186
+ stream.getTracks().forEach((track) => {
187
+ track.stop();
188
+ });
189
+ }
190
+ catch {
191
+ // Permission denied or error
192
+ }
193
+ return this.checkPermissions();
194
+ }
195
+ setState(state, statusText) {
196
+ const previousState = this.state;
197
+ this.state = state;
198
+ this.statusText = statusText;
199
+ this.notifyListeners("stateChange", {
200
+ state,
201
+ previousState,
202
+ statusText,
203
+ usingSystemTts: true,
204
+ });
205
+ }
206
+ }
207
+
208
+ var web = /*#__PURE__*/Object.freeze({
209
+ __proto__: null,
210
+ TalkModeWeb: TalkModeWeb
211
+ });
212
+
213
+ exports.TalkMode = TalkMode;
214
+ //# sourceMappingURL=plugin.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from \"@capacitor/core\";\nexport * from \"./definitions\";\nconst loadWeb = () => import(\"./web\").then((m) => new m.TalkModeWeb());\nexport const TalkMode = registerPlugin(\"TalkMode\", {\n web: loadWeb,\n});\n","import { WebPlugin } from \"@capacitor/core\";\n/**\n * Web implementation of TalkMode plugin\n *\n * Uses Web Speech API for TTS with limited functionality compared to native.\n * ElevenLabs streaming is not supported on web due to CORS limitations.\n */\nexport class TalkModeWeb extends WebPlugin {\n constructor() {\n super();\n this.config = {};\n this.state = \"idle\";\n this.statusText = \"Off\";\n this.synthesis = null;\n this.currentUtterance = null;\n this.recognition = null;\n this.enabled = false;\n if (typeof window !== \"undefined\" && window.speechSynthesis) {\n this.synthesis = window.speechSynthesis;\n }\n }\n async start(options) {\n if (options?.config) {\n this.config = { ...this.config, ...options.config };\n }\n // Check for Web Speech API support\n const SpeechRecognitionAPI = window.SpeechRecognition ||\n window.webkitSpeechRecognition;\n if (!SpeechRecognitionAPI) {\n return {\n started: false,\n error: \"Speech recognition not supported on this browser\",\n };\n }\n if (!this.synthesis) {\n console.warn(\"[TalkMode] Speech synthesis not available on web\");\n }\n this.enabled = true;\n this.setState(\"listening\", \"Listening\");\n // Initialize speech recognition\n this.recognition = new SpeechRecognitionAPI();\n this.recognition.continuous = true;\n this.recognition.interimResults = true;\n this.recognition.onresult = (event) => {\n const result = event.results[event.results.length - 1];\n const transcript = result[0].transcript;\n const isFinal = result.isFinal;\n this.notifyListeners(\"transcript\", { transcript, isFinal });\n if (isFinal && transcript.trim()) {\n // Note: Full talk mode flow would need Gateway plugin integration\n // For web, we just emit the transcript\n }\n };\n this.recognition.onerror = (event) => {\n this.notifyListeners(\"error\", {\n code: event.error,\n message: event.message || event.error,\n recoverable: event.error !== \"not-allowed\",\n });\n };\n this.recognition.onend = () => {\n if (this.enabled && this.state === \"listening\") {\n // Restart recognition if still enabled\n try {\n this.recognition?.start();\n }\n catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (!msg.includes(\"already started\")) {\n console.warn(\"[TalkMode] Failed to restart recognition:\", msg);\n }\n }\n }\n };\n try {\n this.recognition.start();\n return { started: true };\n }\n catch (error) {\n const message = error instanceof Error ? error.message : \"Failed to start\";\n return { started: false, error: message };\n }\n }\n async stop() {\n this.enabled = false;\n this.recognition?.stop();\n this.recognition = null;\n this.synthesis?.cancel();\n this.currentUtterance = null;\n this.setState(\"idle\", \"Off\");\n }\n async isEnabled() {\n return { enabled: this.enabled };\n }\n async getState() {\n return { state: this.state, statusText: this.statusText };\n }\n async updateConfig(options) {\n this.config = { ...this.config, ...options.config };\n }\n async speak(options) {\n if (!this.synthesis) {\n return {\n completed: false,\n interrupted: false,\n usedSystemTts: false,\n error: \"Speech synthesis not available\",\n };\n }\n // Web can only use system TTS (no ElevenLabs due to CORS)\n const text = options.text.trim();\n if (!text) {\n return { completed: true, interrupted: false, usedSystemTts: true };\n }\n this.setState(\"speaking\", \"Speaking\");\n this.notifyListeners(\"speaking\", { text, isSystemTts: true });\n return new Promise((resolve) => {\n const utterance = new SpeechSynthesisUtterance(text);\n this.currentUtterance = utterance;\n // Always set language — fallback to en-US if directive doesn't specify.\n // Without this, the browser uses the system locale, which may read\n // numbers in the wrong language (e.g., Chinese on a Chinese-locale system).\n utterance.lang = options.directive?.language || \"en-US\";\n // Apply directive settings if available\n if (options.directive?.speed) {\n utterance.rate = options.directive.speed;\n }\n utterance.onend = () => {\n this.currentUtterance = null;\n this.notifyListeners(\"speakComplete\", { completed: true });\n this.setState(\"listening\", \"Listening\");\n resolve({ completed: true, interrupted: false, usedSystemTts: true });\n };\n utterance.onerror = (event) => {\n this.currentUtterance = null;\n this.notifyListeners(\"speakComplete\", { completed: false });\n this.setState(\"idle\", \"Speech error\");\n resolve({\n completed: false,\n interrupted: event.error === \"interrupted\",\n usedSystemTts: true,\n error: event.error,\n });\n };\n this.synthesis?.speak(utterance);\n });\n }\n async stopSpeaking() {\n if (this.synthesis && this.currentUtterance) {\n this.synthesis.cancel();\n this.currentUtterance = null;\n return { interruptedAt: undefined };\n }\n return {};\n }\n async isSpeaking() {\n return { speaking: this.synthesis?.speaking ?? false };\n }\n async checkPermissions() {\n // Check microphone permission\n let microphone = \"prompt\";\n try {\n const result = await navigator.permissions.query({\n name: \"microphone\",\n });\n microphone = result.state;\n }\n catch {\n // Permissions API may not support microphone query\n }\n // Check if speech recognition is supported\n const SpeechRecognitionAPI = window.SpeechRecognition ||\n window.webkitSpeechRecognition;\n const speechRecognition = SpeechRecognitionAPI ? \"prompt\" : \"not_supported\";\n return { microphone, speechRecognition };\n }\n async requestPermissions() {\n // Request microphone permission by attempting to get user media\n try {\n const stream = await navigator.mediaDevices.getUserMedia({ audio: true });\n stream.getTracks().forEach((track) => {\n track.stop();\n });\n }\n catch {\n // Permission denied or error\n }\n return this.checkPermissions();\n }\n setState(state, statusText) {\n const previousState = this.state;\n this.state = state;\n this.statusText = statusText;\n this.notifyListeners(\"stateChange\", {\n state,\n previousState,\n statusText,\n usingSystemTts: true,\n });\n }\n}\n"],"names":["registerPlugin","WebPlugin"],"mappings":";;;;AAEA,MAAM,OAAO,GAAG,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;AAC1D,MAAC,QAAQ,GAAGA,mBAAc,CAAC,UAAU,EAAE;AACnD,IAAI,GAAG,EAAE,OAAO;AAChB,CAAC;;ACJD;AACA;AACA;AACA;AACA;AACA;AACO,MAAM,WAAW,SAASC,cAAS,CAAC;AAC3C,IAAI,WAAW,GAAG;AAClB,QAAQ,KAAK,EAAE;AACf,QAAQ,IAAI,CAAC,MAAM,GAAG,EAAE;AACxB,QAAQ,IAAI,CAAC,KAAK,GAAG,MAAM;AAC3B,QAAQ,IAAI,CAAC,UAAU,GAAG,KAAK;AAC/B,QAAQ,IAAI,CAAC,SAAS,GAAG,IAAI;AAC7B,QAAQ,IAAI,CAAC,gBAAgB,GAAG,IAAI;AACpC,QAAQ,IAAI,CAAC,WAAW,GAAG,IAAI;AAC/B,QAAQ,IAAI,CAAC,OAAO,GAAG,KAAK;AAC5B,QAAQ,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,MAAM,CAAC,eAAe,EAAE;AACrE,YAAY,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,eAAe;AACnD,QAAQ;AACR,IAAI;AACJ,IAAI,MAAM,KAAK,CAAC,OAAO,EAAE;AACzB,QAAQ,IAAI,OAAO,EAAE,MAAM,EAAE;AAC7B,YAAY,IAAI,CAAC,MAAM,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE;AAC/D,QAAQ;AACR;AACA,QAAQ,MAAM,oBAAoB,GAAG,MAAM,CAAC,iBAAiB;AAC7D,YAAY,MAAM,CAAC,uBAAuB;AAC1C,QAAQ,IAAI,CAAC,oBAAoB,EAAE;AACnC,YAAY,OAAO;AACnB,gBAAgB,OAAO,EAAE,KAAK;AAC9B,gBAAgB,KAAK,EAAE,kDAAkD;AACzE,aAAa;AACb,QAAQ;AACR,QAAQ,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;AAC7B,YAAY,OAAO,CAAC,IAAI,CAAC,kDAAkD,CAAC;AAC5E,QAAQ;AACR,QAAQ,IAAI,CAAC,OAAO,GAAG,IAAI;AAC3B,QAAQ,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;AAC/C;AACA,QAAQ,IAAI,CAAC,WAAW,GAAG,IAAI,oBAAoB,EAAE;AACrD,QAAQ,IAAI,CAAC,WAAW,CAAC,UAAU,GAAG,IAAI;AAC1C,QAAQ,IAAI,CAAC,WAAW,CAAC,cAAc,GAAG,IAAI;AAC9C,QAAQ,IAAI,CAAC,WAAW,CAAC,QAAQ,GAAG,CAAC,KAAK,KAAK;AAC/C,YAAY,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;AAClE,YAAY,MAAM,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU;AACnD,YAAY,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO;AAC1C,YAAY,IAAI,CAAC,eAAe,CAAC,YAAY,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;AACvE,YAAY,IAAI,OAAO,IAAI,UAAU,CAAC,IAAI,EAAE,EAAE;AAI9C,QAAQ,CAAC;AACT,QAAQ,IAAI,CAAC,WAAW,CAAC,OAAO,GAAG,CAAC,KAAK,KAAK;AAC9C,YAAY,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE;AAC1C,gBAAgB,IAAI,EAAE,KAAK,CAAC,KAAK;AACjC,gBAAgB,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,KAAK;AACrD,gBAAgB,WAAW,EAAE,KAAK,CAAC,KAAK,KAAK,aAAa;AAC1D,aAAa,CAAC;AACd,QAAQ,CAAC;AACT,QAAQ,IAAI,CAAC,WAAW,CAAC,KAAK,GAAG,MAAM;AACvC,YAAY,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,KAAK,KAAK,WAAW,EAAE;AAC5D;AACA,gBAAgB,IAAI;AACpB,oBAAoB,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE;AAC7C,gBAAgB;AAChB,gBAAgB,OAAO,GAAG,EAAE;AAC5B,oBAAoB,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,GAAG,GAAG,CAAC,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC;AAChF,oBAAoB,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE;AAC1D,wBAAwB,OAAO,CAAC,IAAI,CAAC,2CAA2C,EAAE,GAAG,CAAC;AACtF,oBAAoB;AACpB,gBAAgB;AAChB,YAAY;AACZ,QAAQ,CAAC;AACT,QAAQ,IAAI;AACZ,YAAY,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE;AACpC,YAAY,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE;AACpC,QAAQ;AACR,QAAQ,OAAO,KAAK,EAAE;AACtB,YAAY,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,iBAAiB;AACtF,YAAY,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE;AACrD,QAAQ;AACR,IAAI;AACJ,IAAI,MAAM,IAAI,GAAG;AACjB,QAAQ,IAAI,CAAC,OAAO,GAAG,KAAK;AAC5B,QAAQ,IAAI,CAAC,WAAW,EAAE,IAAI,EAAE;AAChC,QAAQ,IAAI,CAAC,WAAW,GAAG,IAAI;AAC/B,QAAQ,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE;AAChC,QAAQ,IAAI,CAAC,gBAAgB,GAAG,IAAI;AACpC,QAAQ,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC;AACpC,IAAI;AACJ,IAAI,MAAM,SAAS,GAAG;AACtB,QAAQ,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE;AACxC,IAAI;AACJ,IAAI,MAAM,QAAQ,GAAG;AACrB,QAAQ,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE;AACjE,IAAI;AACJ,IAAI,MAAM,YAAY,CAAC,OAAO,EAAE;AAChC,QAAQ,IAAI,CAAC,MAAM,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE;AAC3D,IAAI;AACJ,IAAI,MAAM,KAAK,CAAC,OAAO,EAAE;AACzB,QAAQ,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;AAC7B,YAAY,OAAO;AACnB,gBAAgB,SAAS,EAAE,KAAK;AAChC,gBAAgB,WAAW,EAAE,KAAK;AAClC,gBAAgB,aAAa,EAAE,KAAK;AACpC,gBAAgB,KAAK,EAAE,gCAAgC;AACvD,aAAa;AACb,QAAQ;AACR;AACA,QAAQ,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE;AACxC,QAAQ,IAAI,CAAC,IAAI,EAAE;AACnB,YAAY,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE;AAC/E,QAAQ;AACR,QAAQ,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;AAC7C,QAAQ,IAAI,CAAC,eAAe,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;AACrE,QAAQ,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK;AACxC,YAAY,MAAM,SAAS,GAAG,IAAI,wBAAwB,CAAC,IAAI,CAAC;AAChE,YAAY,IAAI,CAAC,gBAAgB,GAAG,SAAS;AAC7C;AACA;AACA;AACA,YAAY,SAAS,CAAC,IAAI,GAAG,OAAO,CAAC,SAAS,EAAE,QAAQ,IAAI,OAAO;AACnE;AACA,YAAY,IAAI,OAAO,CAAC,SAAS,EAAE,KAAK,EAAE;AAC1C,gBAAgB,SAAS,CAAC,IAAI,GAAG,OAAO,CAAC,SAAS,CAAC,KAAK;AACxD,YAAY;AACZ,YAAY,SAAS,CAAC,KAAK,GAAG,MAAM;AACpC,gBAAgB,IAAI,CAAC,gBAAgB,GAAG,IAAI;AAC5C,gBAAgB,IAAI,CAAC,eAAe,CAAC,eAAe,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AAC1E,gBAAgB,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;AACvD,gBAAgB,OAAO,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;AACrF,YAAY,CAAC;AACb,YAAY,SAAS,CAAC,OAAO,GAAG,CAAC,KAAK,KAAK;AAC3C,gBAAgB,IAAI,CAAC,gBAAgB,GAAG,IAAI;AAC5C,gBAAgB,IAAI,CAAC,eAAe,CAAC,eAAe,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;AAC3E,gBAAgB,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;AACrD,gBAAgB,OAAO,CAAC;AACxB,oBAAoB,SAAS,EAAE,KAAK;AACpC,oBAAoB,WAAW,EAAE,KAAK,CAAC,KAAK,KAAK,aAAa;AAC9D,oBAAoB,aAAa,EAAE,IAAI;AACvC,oBAAoB,KAAK,EAAE,KAAK,CAAC,KAAK;AACtC,iBAAiB,CAAC;AAClB,YAAY,CAAC;AACb,YAAY,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC;AAC5C,QAAQ,CAAC,CAAC;AACV,IAAI;AACJ,IAAI,MAAM,YAAY,GAAG;AACzB,QAAQ,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,gBAAgB,EAAE;AACrD,YAAY,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE;AACnC,YAAY,IAAI,CAAC,gBAAgB,GAAG,IAAI;AACxC,YAAY,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE;AAC/C,QAAQ;AACR,QAAQ,OAAO,EAAE;AACjB,IAAI;AACJ,IAAI,MAAM,UAAU,GAAG;AACvB,QAAQ,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,SAAS,EAAE,QAAQ,IAAI,KAAK,EAAE;AAC9D,IAAI;AACJ,IAAI,MAAM,gBAAgB,GAAG;AAC7B;AACA,QAAQ,IAAI,UAAU,GAAG,QAAQ;AACjC,QAAQ,IAAI;AACZ,YAAY,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,WAAW,CAAC,KAAK,CAAC;AAC7D,gBAAgB,IAAI,EAAE,YAAY;AAClC,aAAa,CAAC;AACd,YAAY,UAAU,GAAG,MAAM,CAAC,KAAK;AACrC,QAAQ;AACR,QAAQ,MAAM;AACd;AACA,QAAQ;AACR;AACA,QAAQ,MAAM,oBAAoB,GAAG,MAAM,CAAC,iBAAiB;AAC7D,YAAY,MAAM,CAAC,uBAAuB;AAC1C,QAAQ,MAAM,iBAAiB,GAAG,oBAAoB,GAAG,QAAQ,GAAG,eAAe;AACnF,QAAQ,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE;AAChD,IAAI;AACJ,IAAI,MAAM,kBAAkB,GAAG;AAC/B;AACA,QAAQ,IAAI;AACZ,YAAY,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,YAAY,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACrF,YAAY,MAAM,CAAC,SAAS,EAAE,CAAC,OAAO,CAAC,CAAC,KAAK,KAAK;AAClD,gBAAgB,KAAK,CAAC,IAAI,EAAE;AAC5B,YAAY,CAAC,CAAC;AACd,QAAQ;AACR,QAAQ,MAAM;AACd;AACA,QAAQ;AACR,QAAQ,OAAO,IAAI,CAAC,gBAAgB,EAAE;AACtC,IAAI;AACJ,IAAI,QAAQ,CAAC,KAAK,EAAE,UAAU,EAAE;AAChC,QAAQ,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK;AACxC,QAAQ,IAAI,CAAC,KAAK,GAAG,KAAK;AAC1B,QAAQ,IAAI,CAAC,UAAU,GAAG,UAAU;AACpC,QAAQ,IAAI,CAAC,eAAe,CAAC,aAAa,EAAE;AAC5C,YAAY,KAAK;AACjB,YAAY,aAAa;AACzB,YAAY,UAAU;AACtB,YAAY,cAAc,EAAE,IAAI;AAChC,SAAS,CAAC;AACV,IAAI;AACJ;;;;;;;;;"}
package/dist/plugin.js ADDED
@@ -0,0 +1,217 @@
1
+ var capacitorTalkMode = (function (exports, core) {
2
+ 'use strict';
3
+
4
+ const loadWeb = () => Promise.resolve().then(function () { return web; }).then((m) => new m.TalkModeWeb());
5
+ const TalkMode = core.registerPlugin("TalkMode", {
6
+ web: loadWeb,
7
+ });
8
+
9
+ /**
10
+ * Web implementation of TalkMode plugin
11
+ *
12
+ * Uses Web Speech API for TTS with limited functionality compared to native.
13
+ * ElevenLabs streaming is not supported on web due to CORS limitations.
14
+ */
15
+ class TalkModeWeb extends core.WebPlugin {
16
+ constructor() {
17
+ super();
18
+ this.config = {};
19
+ this.state = "idle";
20
+ this.statusText = "Off";
21
+ this.synthesis = null;
22
+ this.currentUtterance = null;
23
+ this.recognition = null;
24
+ this.enabled = false;
25
+ if (typeof window !== "undefined" && window.speechSynthesis) {
26
+ this.synthesis = window.speechSynthesis;
27
+ }
28
+ }
29
+ async start(options) {
30
+ if (options?.config) {
31
+ this.config = { ...this.config, ...options.config };
32
+ }
33
+ // Check for Web Speech API support
34
+ const SpeechRecognitionAPI = window.SpeechRecognition ||
35
+ window.webkitSpeechRecognition;
36
+ if (!SpeechRecognitionAPI) {
37
+ return {
38
+ started: false,
39
+ error: "Speech recognition not supported on this browser",
40
+ };
41
+ }
42
+ if (!this.synthesis) {
43
+ console.warn("[TalkMode] Speech synthesis not available on web");
44
+ }
45
+ this.enabled = true;
46
+ this.setState("listening", "Listening");
47
+ // Initialize speech recognition
48
+ this.recognition = new SpeechRecognitionAPI();
49
+ this.recognition.continuous = true;
50
+ this.recognition.interimResults = true;
51
+ this.recognition.onresult = (event) => {
52
+ const result = event.results[event.results.length - 1];
53
+ const transcript = result[0].transcript;
54
+ const isFinal = result.isFinal;
55
+ this.notifyListeners("transcript", { transcript, isFinal });
56
+ if (isFinal && transcript.trim()) ;
57
+ };
58
+ this.recognition.onerror = (event) => {
59
+ this.notifyListeners("error", {
60
+ code: event.error,
61
+ message: event.message || event.error,
62
+ recoverable: event.error !== "not-allowed",
63
+ });
64
+ };
65
+ this.recognition.onend = () => {
66
+ if (this.enabled && this.state === "listening") {
67
+ // Restart recognition if still enabled
68
+ try {
69
+ this.recognition?.start();
70
+ }
71
+ catch (err) {
72
+ const msg = err instanceof Error ? err.message : String(err);
73
+ if (!msg.includes("already started")) {
74
+ console.warn("[TalkMode] Failed to restart recognition:", msg);
75
+ }
76
+ }
77
+ }
78
+ };
79
+ try {
80
+ this.recognition.start();
81
+ return { started: true };
82
+ }
83
+ catch (error) {
84
+ const message = error instanceof Error ? error.message : "Failed to start";
85
+ return { started: false, error: message };
86
+ }
87
+ }
88
+ async stop() {
89
+ this.enabled = false;
90
+ this.recognition?.stop();
91
+ this.recognition = null;
92
+ this.synthesis?.cancel();
93
+ this.currentUtterance = null;
94
+ this.setState("idle", "Off");
95
+ }
96
+ async isEnabled() {
97
+ return { enabled: this.enabled };
98
+ }
99
+ async getState() {
100
+ return { state: this.state, statusText: this.statusText };
101
+ }
102
+ async updateConfig(options) {
103
+ this.config = { ...this.config, ...options.config };
104
+ }
105
+ async speak(options) {
106
+ if (!this.synthesis) {
107
+ return {
108
+ completed: false,
109
+ interrupted: false,
110
+ usedSystemTts: false,
111
+ error: "Speech synthesis not available",
112
+ };
113
+ }
114
+ // Web can only use system TTS (no ElevenLabs due to CORS)
115
+ const text = options.text.trim();
116
+ if (!text) {
117
+ return { completed: true, interrupted: false, usedSystemTts: true };
118
+ }
119
+ this.setState("speaking", "Speaking");
120
+ this.notifyListeners("speaking", { text, isSystemTts: true });
121
+ return new Promise((resolve) => {
122
+ const utterance = new SpeechSynthesisUtterance(text);
123
+ this.currentUtterance = utterance;
124
+ // Always set language — fallback to en-US if directive doesn't specify.
125
+ // Without this, the browser uses the system locale, which may read
126
+ // numbers in the wrong language (e.g., Chinese on a Chinese-locale system).
127
+ utterance.lang = options.directive?.language || "en-US";
128
+ // Apply directive settings if available
129
+ if (options.directive?.speed) {
130
+ utterance.rate = options.directive.speed;
131
+ }
132
+ utterance.onend = () => {
133
+ this.currentUtterance = null;
134
+ this.notifyListeners("speakComplete", { completed: true });
135
+ this.setState("listening", "Listening");
136
+ resolve({ completed: true, interrupted: false, usedSystemTts: true });
137
+ };
138
+ utterance.onerror = (event) => {
139
+ this.currentUtterance = null;
140
+ this.notifyListeners("speakComplete", { completed: false });
141
+ this.setState("idle", "Speech error");
142
+ resolve({
143
+ completed: false,
144
+ interrupted: event.error === "interrupted",
145
+ usedSystemTts: true,
146
+ error: event.error,
147
+ });
148
+ };
149
+ this.synthesis?.speak(utterance);
150
+ });
151
+ }
152
+ async stopSpeaking() {
153
+ if (this.synthesis && this.currentUtterance) {
154
+ this.synthesis.cancel();
155
+ this.currentUtterance = null;
156
+ return { interruptedAt: undefined };
157
+ }
158
+ return {};
159
+ }
160
+ async isSpeaking() {
161
+ return { speaking: this.synthesis?.speaking ?? false };
162
+ }
163
+ async checkPermissions() {
164
+ // Check microphone permission
165
+ let microphone = "prompt";
166
+ try {
167
+ const result = await navigator.permissions.query({
168
+ name: "microphone",
169
+ });
170
+ microphone = result.state;
171
+ }
172
+ catch {
173
+ // Permissions API may not support microphone query
174
+ }
175
+ // Check if speech recognition is supported
176
+ const SpeechRecognitionAPI = window.SpeechRecognition ||
177
+ window.webkitSpeechRecognition;
178
+ const speechRecognition = SpeechRecognitionAPI ? "prompt" : "not_supported";
179
+ return { microphone, speechRecognition };
180
+ }
181
+ async requestPermissions() {
182
+ // Request microphone permission by attempting to get user media
183
+ try {
184
+ const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
185
+ stream.getTracks().forEach((track) => {
186
+ track.stop();
187
+ });
188
+ }
189
+ catch {
190
+ // Permission denied or error
191
+ }
192
+ return this.checkPermissions();
193
+ }
194
+ setState(state, statusText) {
195
+ const previousState = this.state;
196
+ this.state = state;
197
+ this.statusText = statusText;
198
+ this.notifyListeners("stateChange", {
199
+ state,
200
+ previousState,
201
+ statusText,
202
+ usingSystemTts: true,
203
+ });
204
+ }
205
+ }
206
+
207
+ var web = /*#__PURE__*/Object.freeze({
208
+ __proto__: null,
209
+ TalkModeWeb: TalkModeWeb
210
+ });
211
+
212
+ exports.TalkMode = TalkMode;
213
+
214
+ return exports;
215
+
216
+ })({}, capacitorExports);
217
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from \"@capacitor/core\";\nexport * from \"./definitions\";\nconst loadWeb = () => import(\"./web\").then((m) => new m.TalkModeWeb());\nexport const TalkMode = registerPlugin(\"TalkMode\", {\n web: loadWeb,\n});\n","import { WebPlugin } from \"@capacitor/core\";\n/**\n * Web implementation of TalkMode plugin\n *\n * Uses Web Speech API for TTS with limited functionality compared to native.\n * ElevenLabs streaming is not supported on web due to CORS limitations.\n */\nexport class TalkModeWeb extends WebPlugin {\n constructor() {\n super();\n this.config = {};\n this.state = \"idle\";\n this.statusText = \"Off\";\n this.synthesis = null;\n this.currentUtterance = null;\n this.recognition = null;\n this.enabled = false;\n if (typeof window !== \"undefined\" && window.speechSynthesis) {\n this.synthesis = window.speechSynthesis;\n }\n }\n async start(options) {\n if (options?.config) {\n this.config = { ...this.config, ...options.config };\n }\n // Check for Web Speech API support\n const SpeechRecognitionAPI = window.SpeechRecognition ||\n window.webkitSpeechRecognition;\n if (!SpeechRecognitionAPI) {\n return {\n started: false,\n error: \"Speech recognition not supported on this browser\",\n };\n }\n if (!this.synthesis) {\n console.warn(\"[TalkMode] Speech synthesis not available on web\");\n }\n this.enabled = true;\n this.setState(\"listening\", \"Listening\");\n // Initialize speech recognition\n this.recognition = new SpeechRecognitionAPI();\n this.recognition.continuous = true;\n this.recognition.interimResults = true;\n this.recognition.onresult = (event) => {\n const result = event.results[event.results.length - 1];\n const transcript = result[0].transcript;\n const isFinal = result.isFinal;\n this.notifyListeners(\"transcript\", { transcript, isFinal });\n if (isFinal && transcript.trim()) {\n // Note: Full talk mode flow would need Gateway plugin integration\n // For web, we just emit the transcript\n }\n };\n this.recognition.onerror = (event) => {\n this.notifyListeners(\"error\", {\n code: event.error,\n message: event.message || event.error,\n recoverable: event.error !== \"not-allowed\",\n });\n };\n this.recognition.onend = () => {\n if (this.enabled && this.state === \"listening\") {\n // Restart recognition if still enabled\n try {\n this.recognition?.start();\n }\n catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (!msg.includes(\"already started\")) {\n console.warn(\"[TalkMode] Failed to restart recognition:\", msg);\n }\n }\n }\n };\n try {\n this.recognition.start();\n return { started: true };\n }\n catch (error) {\n const message = error instanceof Error ? error.message : \"Failed to start\";\n return { started: false, error: message };\n }\n }\n async stop() {\n this.enabled = false;\n this.recognition?.stop();\n this.recognition = null;\n this.synthesis?.cancel();\n this.currentUtterance = null;\n this.setState(\"idle\", \"Off\");\n }\n async isEnabled() {\n return { enabled: this.enabled };\n }\n async getState() {\n return { state: this.state, statusText: this.statusText };\n }\n async updateConfig(options) {\n this.config = { ...this.config, ...options.config };\n }\n async speak(options) {\n if (!this.synthesis) {\n return {\n completed: false,\n interrupted: false,\n usedSystemTts: false,\n error: \"Speech synthesis not available\",\n };\n }\n // Web can only use system TTS (no ElevenLabs due to CORS)\n const text = options.text.trim();\n if (!text) {\n return { completed: true, interrupted: false, usedSystemTts: true };\n }\n this.setState(\"speaking\", \"Speaking\");\n this.notifyListeners(\"speaking\", { text, isSystemTts: true });\n return new Promise((resolve) => {\n const utterance = new SpeechSynthesisUtterance(text);\n this.currentUtterance = utterance;\n // Always set language — fallback to en-US if directive doesn't specify.\n // Without this, the browser uses the system locale, which may read\n // numbers in the wrong language (e.g., Chinese on a Chinese-locale system).\n utterance.lang = options.directive?.language || \"en-US\";\n // Apply directive settings if available\n if (options.directive?.speed) {\n utterance.rate = options.directive.speed;\n }\n utterance.onend = () => {\n this.currentUtterance = null;\n this.notifyListeners(\"speakComplete\", { completed: true });\n this.setState(\"listening\", \"Listening\");\n resolve({ completed: true, interrupted: false, usedSystemTts: true });\n };\n utterance.onerror = (event) => {\n this.currentUtterance = null;\n this.notifyListeners(\"speakComplete\", { completed: false });\n this.setState(\"idle\", \"Speech error\");\n resolve({\n completed: false,\n interrupted: event.error === \"interrupted\",\n usedSystemTts: true,\n error: event.error,\n });\n };\n this.synthesis?.speak(utterance);\n });\n }\n async stopSpeaking() {\n if (this.synthesis && this.currentUtterance) {\n this.synthesis.cancel();\n this.currentUtterance = null;\n return { interruptedAt: undefined };\n }\n return {};\n }\n async isSpeaking() {\n return { speaking: this.synthesis?.speaking ?? false };\n }\n async checkPermissions() {\n // Check microphone permission\n let microphone = \"prompt\";\n try {\n const result = await navigator.permissions.query({\n name: \"microphone\",\n });\n microphone = result.state;\n }\n catch {\n // Permissions API may not support microphone query\n }\n // Check if speech recognition is supported\n const SpeechRecognitionAPI = window.SpeechRecognition ||\n window.webkitSpeechRecognition;\n const speechRecognition = SpeechRecognitionAPI ? \"prompt\" : \"not_supported\";\n return { microphone, speechRecognition };\n }\n async requestPermissions() {\n // Request microphone permission by attempting to get user media\n try {\n const stream = await navigator.mediaDevices.getUserMedia({ audio: true });\n stream.getTracks().forEach((track) => {\n track.stop();\n });\n }\n catch {\n // Permission denied or error\n }\n return this.checkPermissions();\n }\n setState(state, statusText) {\n const previousState = this.state;\n this.state = state;\n this.statusText = statusText;\n this.notifyListeners(\"stateChange\", {\n state,\n previousState,\n statusText,\n usingSystemTts: true,\n });\n }\n}\n"],"names":["registerPlugin","WebPlugin"],"mappings":"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"}