@elizaos/capacitor-talkmode 2.0.0-beta.1 → 2.0.3-beta.3

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.
@@ -57,6 +57,8 @@ export interface SpeakOptions {
57
57
  text: string;
58
58
  /** Optional directive overrides */
59
59
  directive?: TTSDirective;
60
+ /** Route through the on-device local-inference TTS endpoint on native mobile */
61
+ useLocalInferenceTts?: boolean;
60
62
  /** Force use of system TTS */
61
63
  useSystemTts?: boolean;
62
64
  }
@@ -75,19 +77,60 @@ export interface SpeakResult {
75
77
  /** Error message if failed */
76
78
  error?: string;
77
79
  }
80
+ export type TalkModeSessionMode = "idle" | "compose" | "push-to-talk" | "hands-free" | "passive";
81
+ export interface TalkModeSpeakerMetadata {
82
+ /** Stable app/runtime entity id for the speaker when available. */
83
+ entityId?: string;
84
+ /** Connector-native speaker id, such as a Discord user id. */
85
+ sourceId?: string;
86
+ /** Connector/source label, such as "discord", "web", or "native". */
87
+ source?: string;
88
+ /** Human-friendly display name. */
89
+ name?: string;
90
+ /** Connector username or handle. */
91
+ userName?: string;
92
+ /** Room/channel where the turn was captured. */
93
+ channelId?: string;
94
+ roomId?: string;
95
+ metadata?: Record<string, unknown>;
96
+ }
97
+ export interface TalkModeVoiceTurn {
98
+ /** Stable id for this captured speech turn when available. */
99
+ id?: string;
100
+ /** Transcript text for this turn. */
101
+ text: string;
102
+ /** Session mode that produced this turn. */
103
+ mode: TalkModeSessionMode;
104
+ /** Whether this turn is final. */
105
+ isFinal: boolean;
106
+ /** Speaker attribution when provided by the capture backend. */
107
+ speaker?: TalkModeSpeakerMetadata;
108
+ /** Capture backend/source label. */
109
+ source?: string;
110
+ /** Turn start timestamp in epoch milliseconds. */
111
+ startedAtMs?: number;
112
+ /** Turn end timestamp in epoch milliseconds. */
113
+ endedAtMs?: number;
114
+ /** STT confidence where available. */
115
+ confidence?: number;
116
+ /** Backend-specific metadata. */
117
+ metadata?: Record<string, unknown>;
118
+ }
78
119
  /**
79
120
  * Talk mode configuration
80
121
  */
81
122
  export interface TalkModeConfig {
123
+ /** Session mode requested by the UI/connector. */
124
+ mode?: Exclude<TalkModeSessionMode, "idle">;
82
125
  /** Session key for chat */
83
126
  sessionKey?: string;
84
127
  /** TTS configuration */
85
128
  tts?: TTSConfig;
86
- /** STT configuration (desktop whisper/web) */
129
+ /** STT configuration (platform recognizer/Web Speech) */
87
130
  stt?: {
88
131
  /** STT engine preference */
89
- engine?: "whisper" | "web";
90
- /** Whisper model size */
132
+ engine?: "native" | "web";
133
+ /** Legacy compatibility field; ignored by current recognizers */
91
134
  modelSize?: "tiny" | "base" | "small" | "medium" | "large";
92
135
  /** Language code (e.g., "en", "es") */
93
136
  language?: string;
@@ -111,6 +154,8 @@ export interface TalkModeStateEvent {
111
154
  state: TalkModeState;
112
155
  /** Previous state */
113
156
  previousState: TalkModeState;
157
+ /** Current session mode */
158
+ mode?: TalkModeSessionMode;
114
159
  /** Status message */
115
160
  statusText: string;
116
161
  /** Whether system TTS is being used */
@@ -124,6 +169,16 @@ export interface TalkModeTranscriptEvent {
124
169
  transcript: string;
125
170
  /** Whether this is final */
126
171
  isFinal: boolean;
172
+ /** Session mode that produced this transcript */
173
+ mode?: Exclude<TalkModeSessionMode, "idle">;
174
+ /** Speaker attribution when provided by the capture backend */
175
+ speaker?: TalkModeSpeakerMetadata;
176
+ /** Full turn metadata for speaker-aware clients */
177
+ turn?: TalkModeVoiceTurn;
178
+ /** Capture backend/source label */
179
+ source?: string;
180
+ /** STT confidence where available */
181
+ confidence?: number;
127
182
  }
128
183
  /**
129
184
  * TTS start event
@@ -154,6 +209,68 @@ export interface TalkModeErrorEvent {
154
209
  /** Whether recoverable */
155
210
  recoverable: boolean;
156
211
  }
212
+ /**
213
+ * Native playback has started.
214
+ */
215
+ export interface TalkModePlaybackStartEvent {
216
+ /** Playback provider that produced the audio */
217
+ provider: "elevenlabs" | "local-inference" | "system";
218
+ /** PCM sample rate when known */
219
+ sampleRate?: number;
220
+ /** PCM channel count when known */
221
+ channels?: number;
222
+ }
223
+ /**
224
+ * One frame of raw PCM captured by the native AudioRecord diarization path.
225
+ *
226
+ * Emitted continuously while {@link TalkModePlugin.startAudioFrames} is active.
227
+ * `pcm16` is little-endian signed 16-bit mono PCM, base64-encoded — feed it to a
228
+ * JS/bun VAD / diarizer / wake-word consumer. The native STT (SpeechRecognizer /
229
+ * SODA) path does NOT produce these; only the explicit audio-frame mode does.
230
+ */
231
+ export interface TalkModeAudioFrameEvent {
232
+ /** Base64-encoded little-endian signed 16-bit mono PCM for this frame. */
233
+ pcm16: string;
234
+ /** Sample rate of the captured PCM in Hz (e.g. 16000). */
235
+ sampleRate: number;
236
+ /** Channel count of the captured PCM (always 1 — mono). */
237
+ channels: 1;
238
+ /** Number of PCM samples in this frame (`pcm16` byte length / 2). */
239
+ samples: number;
240
+ /** Root-mean-square amplitude of this frame, normalized 0..1. */
241
+ rms: number;
242
+ /** Monotonic capture timestamp for this frame, ms (SystemClock.elapsedRealtime). */
243
+ timestamp: number;
244
+ /** Running index of this frame since capture started (0-based). */
245
+ frameIndex: number;
246
+ }
247
+ /** Options for {@link TalkModePlugin.startAudioFrames}. */
248
+ export interface AudioFrameOptions {
249
+ /**
250
+ * Target capture sample rate in Hz. Default 16000 (16 kHz mono — the rate
251
+ * VAD/diarizer/wake-word models expect). The device may not support every
252
+ * rate; the result reports the rate actually opened.
253
+ */
254
+ sampleRate?: number;
255
+ /**
256
+ * Frames per `audioFrame` event, in milliseconds of audio. Default 20 ms
257
+ * (320 samples @ 16 kHz) — the standard VAD frame size.
258
+ */
259
+ frameMs?: number;
260
+ }
261
+ /** Result of {@link TalkModePlugin.startAudioFrames}. */
262
+ export interface AudioFrameResult {
263
+ /** True when the AudioRecord capture started and frames will stream. */
264
+ started: boolean;
265
+ /** The sample rate the native AudioRecord was actually opened at, in Hz. */
266
+ sampleRate?: number;
267
+ /** Samples per emitted frame. */
268
+ frameSamples?: number;
269
+ /** True when SpeechRecognizer STT was suspended to free the mic for capture. */
270
+ suspendedStt?: boolean;
271
+ /** Populated when `started` is false. */
272
+ error?: string;
273
+ }
157
274
  /**
158
275
  * Permission status for talk mode
159
276
  */
@@ -249,6 +366,30 @@ export interface TalkModePlugin {
249
366
  * @returns Promise resolving to permission status after request
250
367
  */
251
368
  requestPermissions(): Promise<TalkModePermissionStatus>;
369
+ /**
370
+ * Start raw 16 kHz mono PCM frame capture (the diarization / VAD / wake-word
371
+ * source). Opt-in and independent of the default {@link start} STT flow.
372
+ *
373
+ * Android cannot run a parallel `AudioRecord` while `SpeechRecognizer` (SODA)
374
+ * holds the mic, so this SUSPENDS any active SpeechRecognizer for the duration
375
+ * of capture, then runs an `AudioRecord` and streams `audioFrame` events.
376
+ * Calling {@link stopAudioFrames} releases the `AudioRecord` and resumes STT
377
+ * if it was running. Native-only (no-op error on web/desktop).
378
+ *
379
+ * @returns Promise resolving to the capture result.
380
+ */
381
+ startAudioFrames(options?: AudioFrameOptions): Promise<AudioFrameResult>;
382
+ /**
383
+ * Stop raw PCM frame capture and resume SpeechRecognizer STT if it was
384
+ * suspended by {@link startAudioFrames}.
385
+ */
386
+ stopAudioFrames(): Promise<void>;
387
+ /**
388
+ * Query whether raw PCM frame capture is currently active.
389
+ */
390
+ isCapturingAudioFrames(): Promise<{
391
+ capturing: boolean;
392
+ }>;
252
393
  /**
253
394
  * Add listener for state changes
254
395
  */
@@ -269,6 +410,11 @@ export interface TalkModePlugin {
269
410
  * Add listener for errors
270
411
  */
271
412
  addListener(eventName: "error", listenerFunc: (event: TalkModeErrorEvent) => void): Promise<PluginListenerHandle>;
413
+ addListener(eventName: "playbackStart", listenerFunc: (event: TalkModePlaybackStartEvent) => void): Promise<PluginListenerHandle>;
414
+ /**
415
+ * Add listener for raw PCM audio frames (only while startAudioFrames is active)
416
+ */
417
+ addListener(eventName: "audioFrame", listenerFunc: (event: TalkModeAudioFrameEvent) => void): Promise<PluginListenerHandle>;
272
418
  /**
273
419
  * Remove all listeners
274
420
  */
@@ -1 +1 @@
1
- {"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAE5D;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8BAA8B;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4BAA4B;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2BAA2B;IAC3B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,mCAAmC;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,uCAAuC;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mCAAmC;IACnC,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,kCAAkC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kCAAkC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4BAA4B;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yBAAyB;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,qDAAqD;IACrD,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,mCAAmC;IACnC,SAAS,CAAC,EAAE,YAAY,CAAC;IACzB,gFAAgF;IAChF,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,8BAA8B;IAC9B,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,4CAA4C;IAC5C,SAAS,EAAE,OAAO,CAAC;IACnB,uCAAuC;IACvC,WAAW,EAAE,OAAO,CAAC;IACrB,kEAAkE;IAClE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8CAA8C;IAC9C,aAAa,EAAE,OAAO,CAAC;IACvB,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,mBAAmB,GAC3B,MAAM,GACN,SAAS,GACT,cAAc,GACd,YAAY,GACZ,SAAS,CAAC;AAEd,MAAM,WAAW,uBAAuB;IACtC,mEAAmE;IACnE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mCAAmC;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oCAAoC;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,iBAAiB;IAChC,8DAA8D;IAC9D,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,IAAI,EAAE,mBAAmB,CAAC;IAC1B,kCAAkC;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,gEAAgE;IAChE,OAAO,CAAC,EAAE,uBAAuB,CAAC;IAClC,oCAAoC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sCAAsC;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iCAAiC;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,kDAAkD;IAClD,IAAI,CAAC,EAAE,OAAO,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC;IAC5C,2BAA2B;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wBAAwB;IACxB,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,yDAAyD;IACzD,GAAG,CAAC,EAAE;QACJ,4BAA4B;QAC5B,MAAM,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;QAC1B,iEAAiE;QACjE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;QAC3D,uCAAuC;QACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,+CAA+C;QAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,uDAAuD;IACvD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,yCAAyC;IACzC,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,GACrB,MAAM,GACN,WAAW,GACX,YAAY,GACZ,UAAU,GACV,OAAO,CAAC;AAEZ;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,oBAAoB;IACpB,KAAK,EAAE,aAAa,CAAC;IACrB,qBAAqB;IACrB,aAAa,EAAE,aAAa,CAAC;IAC7B,2BAA2B;IAC3B,IAAI,CAAC,EAAE,mBAAmB,CAAC;IAC3B,qBAAqB;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,sBAAsB;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,4BAA4B;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,iDAAiD;IACjD,IAAI,CAAC,EAAE,OAAO,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC;IAC5C,+DAA+D;IAC/D,OAAO,CAAC,EAAE,uBAAuB,CAAC;IAClC,mDAAmD;IACnD,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,mCAAmC;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qCAAqC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,wBAAwB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,WAAW,EAAE,OAAO,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,6CAA6C;IAC7C,SAAS,EAAE,OAAO,CAAC;IACnB,mDAAmD;IACnD,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,oBAAoB;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,0BAA0B;IAC1B,WAAW,EAAE,OAAO,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,gDAAgD;IAChD,QAAQ,EAAE,YAAY,GAAG,iBAAiB,GAAG,QAAQ,CAAC;IACtD,iCAAiC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mCAAmC;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,uBAAuB;IACtC,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,UAAU,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,QAAQ,EAAE,CAAC,CAAC;IACZ,qEAAqE;IACrE,OAAO,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,GAAG,EAAE,MAAM,CAAC;IACZ,oFAAoF;IACpF,SAAS,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,2DAA2D;AAC3D,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,yDAAyD;AACzD,MAAM,WAAW,gBAAgB;IAC/B,wEAAwE;IACxE,OAAO,EAAE,OAAO,CAAC;IACjB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iCAAiC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gFAAgF;IAChF,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,4BAA4B;IAC5B,UAAU,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC5C,oCAAoC;IACpC,iBAAiB,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,eAAe,CAAC;CACtE;AAED;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;;OAKG;IACH,KAAK,CAAC,OAAO,CAAC,EAAE;QACd,MAAM,CAAC,EAAE,cAAc,CAAC;KACzB,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAElD;;;;OAIG;IACH,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtB;;;;OAIG;IACH,SAAS,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAE3C;;;;OAIG;IACH,QAAQ,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,aAAa,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAElE;;;;;OAKG;IACH,YAAY,CAAC,OAAO,EAAE;QAAE,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1E;;;;;OAKG;IACH,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAEnD;;;;OAIG;IACH,YAAY,IAAI,OAAO,CAAC;QAAE,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAEpD;;;;OAIG;IACH,UAAU,IAAI,OAAO,CAAC;QAAE,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAE7C;;;;OAIG;IACH,gBAAgB,IAAI,OAAO,CAAC,wBAAwB,CAAC,CAAC;IAEtD;;;;OAIG;IACH,kBAAkB,IAAI,OAAO,CAAC,wBAAwB,CAAC,CAAC;IAExD;;;;;;;;;;;OAWG;IACH,gBAAgB,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAEzE;;;OAGG;IACH,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjC;;OAEG;IACH,sBAAsB,IAAI,OAAO,CAAC;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAE1D;;OAEG;IACH,WAAW,CACT,SAAS,EAAE,aAAa,EACxB,YAAY,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,GAChD,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAEjC;;OAEG;IACH,WAAW,CACT,SAAS,EAAE,YAAY,EACvB,YAAY,EAAE,CAAC,KAAK,EAAE,uBAAuB,KAAK,IAAI,GACrD,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAEjC;;OAEG;IACH,WAAW,CACT,SAAS,EAAE,UAAU,EACrB,YAAY,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,GAC9C,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAEjC;;OAEG;IACH,WAAW,CACT,SAAS,EAAE,eAAe,EAC1B,YAAY,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,GAC9C,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAEjC;;OAEG;IACH,WAAW,CACT,SAAS,EAAE,OAAO,EAClB,YAAY,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,GAChD,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAEjC,WAAW,CACT,SAAS,EAAE,eAAe,EAC1B,YAAY,EAAE,CAAC,KAAK,EAAE,0BAA0B,KAAK,IAAI,GACxD,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAEjC;;OAEG;IACH,WAAW,CACT,SAAS,EAAE,YAAY,EACvB,YAAY,EAAE,CAAC,KAAK,EAAE,uBAAuB,KAAK,IAAI,GACrD,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAEjC;;OAEG;IACH,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACrC"}
package/dist/esm/web.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { WebPlugin } from "@capacitor/core";
2
- import type { SpeakOptions, SpeakResult, TalkModeConfig, TalkModePermissionStatus, TalkModeState } from "./definitions";
2
+ import type { AudioFrameOptions, AudioFrameResult, SpeakOptions, SpeakResult, TalkModeConfig, TalkModePermissionStatus, TalkModeState } from "./definitions";
3
3
  /**
4
4
  * Web implementation of TalkMode plugin
5
5
  *
@@ -39,6 +39,11 @@ export declare class TalkModeWeb extends WebPlugin {
39
39
  isSpeaking(): Promise<{
40
40
  speaking: boolean;
41
41
  }>;
42
+ startAudioFrames(_options?: AudioFrameOptions): Promise<AudioFrameResult>;
43
+ stopAudioFrames(): Promise<void>;
44
+ isCapturingAudioFrames(): Promise<{
45
+ capturing: boolean;
46
+ }>;
42
47
  checkPermissions(): Promise<TalkModePermissionStatus>;
43
48
  requestPermissions(): Promise<TalkModePermissionStatus>;
44
49
  private setState;
@@ -1 +1 @@
1
- {"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,KAAK,EACV,YAAY,EACZ,WAAW,EACX,cAAc,EACd,wBAAwB,EACxB,aAAa,EACd,MAAM,eAAe,CAAC;AA8CvB;;;;;GAKG;AACH,qBAAa,WAAY,SAAQ,SAAS;IACxC,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,KAAK,CAAyB;IACtC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAAgC;IACjD,OAAO,CAAC,gBAAgB,CAAyC;IACjE,OAAO,CAAC,WAAW,CAA0C;IAC7D,OAAO,CAAC,OAAO,CAAS;;IASlB,KAAK,CAAC,OAAO,CAAC,EAAE;QACpB,MAAM,CAAC,EAAE,cAAc,CAAC;KACzB,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IA8E3C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IASrB,SAAS,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAI1C,QAAQ,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,aAAa,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IAIjE,YAAY,CAAC,OAAO,EAAE;QAC1B,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;KACjC,GAAG,OAAO,CAAC,IAAI,CAAC;IAIX,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;IAwDlD,YAAY,IAAI,OAAO,CAAC;QAAE,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IASnD,UAAU,IAAI,OAAO,CAAC;QAAE,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC;IAI5C,gBAAgB,IAAI,OAAO,CAAC,wBAAwB,CAAC;IA2BrD,kBAAkB,IAAI,OAAO,CAAC,wBAAwB,CAAC;IAc7D,OAAO,CAAC,QAAQ;CAWjB"}
1
+ {"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAO5C,OAAO,KAAK,EACV,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,cAAc,EACd,wBAAwB,EACxB,aAAa,EACd,MAAM,eAAe,CAAC;AAEvB;;;;;GAKG;AACH,qBAAa,WAAY,SAAQ,SAAS;IACxC,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,KAAK,CAAyB;IACtC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAAgC;IACjD,OAAO,CAAC,gBAAgB,CAAyC;IACjE,OAAO,CAAC,WAAW,CAA0C;IAC7D,OAAO,CAAC,OAAO,CAAS;;IASlB,KAAK,CAAC,OAAO,CAAC,EAAE;QACpB,MAAM,CAAC,EAAE,cAAc,CAAC;KACzB,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAiF3C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IASrB,SAAS,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAI1C,QAAQ,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,aAAa,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IAIjE,YAAY,CAAC,OAAO,EAAE;QAC1B,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;KACjC,GAAG,OAAO,CAAC,IAAI,CAAC;IAIX,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;IA4DlD,YAAY,IAAI,OAAO,CAAC;QAAE,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IASnD,UAAU,IAAI,OAAO,CAAC;QAAE,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC;IAI5C,gBAAgB,CACpB,QAAQ,CAAC,EAAE,iBAAiB,GAC3B,OAAO,CAAC,gBAAgB,CAAC;IAStB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAIhC,sBAAsB,IAAI,OAAO,CAAC;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC;IAIzD,gBAAgB,IAAI,OAAO,CAAC,wBAAwB,CAAC;IAiCrD,kBAAkB,IAAI,OAAO,CAAC,wBAAwB,CAAC;IAiB7D,OAAO,CAAC,QAAQ;CAWjB"}
package/dist/esm/web.js CHANGED
@@ -43,8 +43,13 @@ export class TalkModeWeb extends WebPlugin {
43
43
  this.recognition.interimResults = true;
44
44
  this.recognition.onresult = (event) => {
45
45
  const result = event.results[event.results.length - 1];
46
- const transcript = result[0].transcript;
46
+ const first = result?.[0];
47
+ if (!first || typeof first.transcript !== "string")
48
+ return;
49
+ const transcript = first.transcript;
47
50
  const isFinal = result.isFinal;
51
+ if (!transcript.trim())
52
+ return;
48
53
  this.notifyListeners("transcript", { transcript, isFinal });
49
54
  if (isFinal && transcript.trim()) {
50
55
  // Note: Full talk mode flow would need Gateway plugin integration
@@ -122,7 +127,9 @@ export class TalkModeWeb extends WebPlugin {
122
127
  // numbers in the wrong language (e.g., Chinese on a Chinese-locale system).
123
128
  utterance.lang = options.directive?.language || "en-US";
124
129
  // Apply directive settings if available
125
- if (options.directive?.speed) {
130
+ if (typeof options.directive?.speed === "number" &&
131
+ Number.isFinite(options.directive.speed) &&
132
+ options.directive.speed > 0) {
126
133
  utterance.rate = options.directive.speed;
127
134
  }
128
135
  utterance.onend = () => {
@@ -156,14 +163,32 @@ export class TalkModeWeb extends WebPlugin {
156
163
  async isSpeaking() {
157
164
  return { speaking: this.synthesis?.speaking ?? false };
158
165
  }
166
+ async startAudioFrames(_options) {
167
+ // Raw PCM frame capture is a native-only diarization path; on web the Web
168
+ // Speech API gives transcripts only, with no raw-PCM hook.
169
+ return {
170
+ started: false,
171
+ error: "audioFrame capture is not supported on web",
172
+ };
173
+ }
174
+ async stopAudioFrames() {
175
+ // no-op on web
176
+ }
177
+ async isCapturingAudioFrames() {
178
+ return { capturing: false };
179
+ }
159
180
  async checkPermissions() {
160
181
  // Check microphone permission
161
182
  let microphone = "prompt";
162
183
  try {
163
- const result = await navigator.permissions.query({
184
+ const result = await navigator.permissions?.query?.({
164
185
  name: "microphone",
165
186
  });
166
- microphone = result.state;
187
+ if (result?.state === "granted" ||
188
+ result?.state === "denied" ||
189
+ result?.state === "prompt") {
190
+ microphone = result.state;
191
+ }
167
192
  }
168
193
  catch {
169
194
  // Permissions API may not support microphone query
@@ -177,7 +202,11 @@ export class TalkModeWeb extends WebPlugin {
177
202
  async requestPermissions() {
178
203
  // Request microphone permission by attempting to get user media
179
204
  try {
180
- const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
205
+ const stream = await navigator.mediaDevices?.getUserMedia?.({
206
+ audio: true,
207
+ });
208
+ if (!stream)
209
+ throw new Error("mediaDevices.getUserMedia unavailable");
181
210
  stream.getTracks().forEach((track) => {
182
211
  track.stop();
183
212
  });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=web.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.test.d.ts","sourceRoot":"","sources":["../../src/web.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,137 @@
1
+ import { afterEach, describe, expect, it, vi } from "vitest";
2
+ import { TalkModeWeb } from "./web";
3
+ class FakeRecognition extends EventTarget {
4
+ constructor() {
5
+ super();
6
+ this.continuous = false;
7
+ this.interimResults = false;
8
+ this.onresult = null;
9
+ this.onerror = null;
10
+ this.onend = null;
11
+ this.start = vi.fn();
12
+ this.stop = vi.fn(() => {
13
+ this.onend?.();
14
+ });
15
+ this.abort = vi.fn();
16
+ FakeRecognition.latest = this;
17
+ }
18
+ }
19
+ FakeRecognition.latest = null;
20
+ class FakeUtterance {
21
+ constructor(text) {
22
+ this.text = text;
23
+ this.lang = "";
24
+ this.rate = 1;
25
+ this.onend = null;
26
+ this.onerror = null;
27
+ }
28
+ }
29
+ function setWindow(value) {
30
+ Object.defineProperty(globalThis, "window", {
31
+ configurable: true,
32
+ value,
33
+ });
34
+ }
35
+ function setNavigator(value) {
36
+ Object.defineProperty(globalThis, "navigator", {
37
+ configurable: true,
38
+ value,
39
+ });
40
+ }
41
+ describe("TalkModeWeb fallback", () => {
42
+ afterEach(() => {
43
+ vi.restoreAllMocks();
44
+ vi.unstubAllGlobals();
45
+ FakeRecognition.latest = null;
46
+ });
47
+ it("reports unsupported recognition and denied permission requests without media APIs", async () => {
48
+ setWindow({});
49
+ setNavigator({});
50
+ await expect(new TalkModeWeb().start()).resolves.toEqual({
51
+ started: false,
52
+ error: "Speech recognition not supported on this browser",
53
+ });
54
+ await expect(new TalkModeWeb().checkPermissions()).resolves.toEqual({
55
+ microphone: "prompt",
56
+ speechRecognition: "not_supported",
57
+ });
58
+ await expect(new TalkModeWeb().requestPermissions()).resolves.toEqual({
59
+ microphone: "prompt",
60
+ speechRecognition: "not_supported",
61
+ });
62
+ });
63
+ it("emits transcript events for valid recognition results and ignores malformed ones", async () => {
64
+ const synthesis = { cancel: vi.fn(), speak: vi.fn(), speaking: false };
65
+ setWindow({
66
+ SpeechRecognition: FakeRecognition,
67
+ speechSynthesis: synthesis,
68
+ });
69
+ setNavigator({});
70
+ const plugin = new TalkModeWeb();
71
+ const transcripts = vi.fn();
72
+ await plugin.addListener("transcript", transcripts);
73
+ await expect(plugin.start()).resolves.toEqual({ started: true });
74
+ FakeRecognition.latest?.onresult?.({
75
+ results: [{ isFinal: true, 0: { transcript: 42 } }],
76
+ });
77
+ expect(transcripts).not.toHaveBeenCalled();
78
+ FakeRecognition.latest?.onresult?.({
79
+ results: [{ isFinal: true, 0: { transcript: " hello " } }],
80
+ });
81
+ expect(transcripts).toHaveBeenCalledWith({
82
+ transcript: " hello ",
83
+ isFinal: true,
84
+ });
85
+ });
86
+ it("speaks with sanitized directive values and resolves completion", async () => {
87
+ const utterances = [];
88
+ const synthesis = {
89
+ cancel: vi.fn(),
90
+ speaking: false,
91
+ speak: vi.fn((value) => {
92
+ utterances.push(value);
93
+ queueMicrotask(() => value.onend?.());
94
+ }),
95
+ };
96
+ setWindow({ speechSynthesis: synthesis });
97
+ vi.stubGlobal("SpeechSynthesisUtterance", FakeUtterance);
98
+ const plugin = new TalkModeWeb();
99
+ const speaking = vi.fn();
100
+ const complete = vi.fn();
101
+ await plugin.addListener("speaking", speaking);
102
+ await plugin.addListener("speakComplete", complete);
103
+ await expect(plugin.speak({
104
+ text: "Hello",
105
+ directive: { language: "es", speed: Number.NaN },
106
+ })).resolves.toEqual({
107
+ completed: true,
108
+ interrupted: false,
109
+ usedSystemTts: true,
110
+ });
111
+ expect(synthesis.speak).toHaveBeenCalled();
112
+ expect(utterances[0]?.lang).toBe("es");
113
+ expect(utterances[0]?.rate).toBe(1);
114
+ expect(speaking).toHaveBeenCalledWith({
115
+ text: "Hello",
116
+ isSystemTts: true,
117
+ });
118
+ expect(complete).toHaveBeenCalledWith({ completed: true });
119
+ });
120
+ it("maps speech synthesis errors without throwing", async () => {
121
+ const synthesis = {
122
+ cancel: vi.fn(),
123
+ speaking: false,
124
+ speak: vi.fn((value) => {
125
+ queueMicrotask(() => value.onerror?.({ error: "interrupted" }));
126
+ }),
127
+ };
128
+ setWindow({ speechSynthesis: synthesis });
129
+ vi.stubGlobal("SpeechSynthesisUtterance", FakeUtterance);
130
+ await expect(new TalkModeWeb().speak({ text: "Stop" })).resolves.toEqual({
131
+ completed: false,
132
+ interrupted: true,
133
+ usedSystemTts: true,
134
+ error: "interrupted",
135
+ });
136
+ });
137
+ });
@@ -51,8 +51,13 @@ class TalkModeWeb extends core.WebPlugin {
51
51
  this.recognition.interimResults = true;
52
52
  this.recognition.onresult = (event) => {
53
53
  const result = event.results[event.results.length - 1];
54
- const transcript = result[0].transcript;
54
+ const first = result?.[0];
55
+ if (!first || typeof first.transcript !== "string")
56
+ return;
57
+ const transcript = first.transcript;
55
58
  const isFinal = result.isFinal;
59
+ if (!transcript.trim())
60
+ return;
56
61
  this.notifyListeners("transcript", { transcript, isFinal });
57
62
  if (isFinal && transcript.trim()) ;
58
63
  };
@@ -127,7 +132,9 @@ class TalkModeWeb extends core.WebPlugin {
127
132
  // numbers in the wrong language (e.g., Chinese on a Chinese-locale system).
128
133
  utterance.lang = options.directive?.language || "en-US";
129
134
  // Apply directive settings if available
130
- if (options.directive?.speed) {
135
+ if (typeof options.directive?.speed === "number" &&
136
+ Number.isFinite(options.directive.speed) &&
137
+ options.directive.speed > 0) {
131
138
  utterance.rate = options.directive.speed;
132
139
  }
133
140
  utterance.onend = () => {
@@ -161,14 +168,32 @@ class TalkModeWeb extends core.WebPlugin {
161
168
  async isSpeaking() {
162
169
  return { speaking: this.synthesis?.speaking ?? false };
163
170
  }
171
+ async startAudioFrames(_options) {
172
+ // Raw PCM frame capture is a native-only diarization path; on web the Web
173
+ // Speech API gives transcripts only, with no raw-PCM hook.
174
+ return {
175
+ started: false,
176
+ error: "audioFrame capture is not supported on web",
177
+ };
178
+ }
179
+ async stopAudioFrames() {
180
+ // no-op on web
181
+ }
182
+ async isCapturingAudioFrames() {
183
+ return { capturing: false };
184
+ }
164
185
  async checkPermissions() {
165
186
  // Check microphone permission
166
187
  let microphone = "prompt";
167
188
  try {
168
- const result = await navigator.permissions.query({
189
+ const result = await navigator.permissions?.query?.({
169
190
  name: "microphone",
170
191
  });
171
- microphone = result.state;
192
+ if (result?.state === "granted" ||
193
+ result?.state === "denied" ||
194
+ result?.state === "prompt") {
195
+ microphone = result.state;
196
+ }
172
197
  }
173
198
  catch {
174
199
  // Permissions API may not support microphone query
@@ -182,7 +207,11 @@ class TalkModeWeb extends core.WebPlugin {
182
207
  async requestPermissions() {
183
208
  // Request microphone permission by attempting to get user media
184
209
  try {
185
- const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
210
+ const stream = await navigator.mediaDevices?.getUserMedia?.({
211
+ audio: true,
212
+ });
213
+ if (!stream)
214
+ throw new Error("mediaDevices.getUserMedia unavailable");
186
215
  stream.getTracks().forEach((track) => {
187
216
  track.stop();
188
217
  });
@@ -1 +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":"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"}
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 first = result?.[0];\n if (!first || typeof first.transcript !== \"string\")\n return;\n const transcript = first.transcript;\n const isFinal = result.isFinal;\n if (!transcript.trim())\n return;\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 (typeof options.directive?.speed === \"number\" &&\n Number.isFinite(options.directive.speed) &&\n options.directive.speed > 0) {\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 startAudioFrames(_options) {\n // Raw PCM frame capture is a native-only diarization path; on web the Web\n // Speech API gives transcripts only, with no raw-PCM hook.\n return {\n started: false,\n error: \"audioFrame capture is not supported on web\",\n };\n }\n async stopAudioFrames() {\n // no-op on web\n }\n async isCapturingAudioFrames() {\n return { capturing: 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 if (result?.state === \"granted\" ||\n result?.state === \"denied\" ||\n result?.state === \"prompt\") {\n microphone = result.state;\n }\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?.({\n audio: true,\n });\n if (!stream)\n throw new Error(\"mediaDevices.getUserMedia unavailable\");\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,KAAK,GAAG,MAAM,GAAG,CAAC,CAAC;AACrC,YAAY,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ;AAC9D,gBAAgB;AAChB,YAAY,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU;AAC/C,YAAY,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO;AAC1C,YAAY,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE;AAClC,gBAAgB;AAChB,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,OAAO,CAAC,SAAS,EAAE,KAAK,KAAK,QAAQ;AAC5D,gBAAgB,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC;AACxD,gBAAgB,OAAO,CAAC,SAAS,CAAC,KAAK,GAAG,CAAC,EAAE;AAC7C,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,CAAC,QAAQ,EAAE;AACrC;AACA;AACA,QAAQ,OAAO;AACf,YAAY,OAAO,EAAE,KAAK;AAC1B,YAAY,KAAK,EAAE,4CAA4C;AAC/D,SAAS;AACT,IAAI;AACJ,IAAI,MAAM,eAAe,GAAG;AAC5B;AACA,IAAI;AACJ,IAAI,MAAM,sBAAsB,GAAG;AACnC,QAAQ,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE;AACnC,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,EAAE,KAAK,GAAG;AAChE,gBAAgB,IAAI,EAAE,YAAY;AAClC,aAAa,CAAC;AACd,YAAY,IAAI,MAAM,EAAE,KAAK,KAAK,SAAS;AAC3C,gBAAgB,MAAM,EAAE,KAAK,KAAK,QAAQ;AAC1C,gBAAgB,MAAM,EAAE,KAAK,KAAK,QAAQ,EAAE;AAC5C,gBAAgB,UAAU,GAAG,MAAM,CAAC,KAAK;AACzC,YAAY;AACZ,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,EAAE,YAAY,GAAG;AACxE,gBAAgB,KAAK,EAAE,IAAI;AAC3B,aAAa,CAAC;AACd,YAAY,IAAI,CAAC,MAAM;AACvB,gBAAgB,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC;AACxE,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;;;;;;;;;"}