@garrix82/reactgenie-lib 1.3.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.
- package/.env.example +22 -0
- package/.github/workflows/publish.yml +20 -0
- package/LICENSE.txt +201 -0
- package/README.md +621 -0
- package/babel.config.js +29 -0
- package/dist/adapters/__tests__/expo-router-adapter.test.d.ts +1 -0
- package/dist/adapters/expo-router-adapter.d.ts +16 -0
- package/dist/adapters/expo-router-adapter.js +521 -0
- package/dist/adapters/navigation-adapter.d.ts +20 -0
- package/dist/adapters/navigation-adapter.js +137 -0
- package/dist/audio-visualizer.d.ts +14 -0
- package/dist/audio-visualizer.js +123 -0
- package/dist/current-selection.d.ts +27 -0
- package/dist/current-selection.js +94 -0
- package/dist/errors.d.ts +19 -0
- package/dist/errors.js +37 -0
- package/dist/genie/DateTime.d.ts +66 -0
- package/dist/genie/DateTime.js +399 -0
- package/dist/genie/TimeDelta.d.ts +35 -0
- package/dist/genie/TimeDelta.js +169 -0
- package/dist/genie-view-wrapper.d.ts +1 -0
- package/dist/genie-view-wrapper.js +377 -0
- package/dist/hooks/__tests__/useSpeechRecognition.test.d.ts +1 -0
- package/dist/hooks/useSpeechRecognition.d.ts +28 -0
- package/dist/hooks/useSpeechRecognition.js +118 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.js +469 -0
- package/dist/logger.d.ts +23 -0
- package/dist/logger.js +597 -0
- package/dist/logger.remote.test.d.ts +0 -0
- package/dist/modality-provider-v2.d.ts +28 -0
- package/dist/modality-provider-v2.js +1321 -0
- package/dist/modality-provider.d.ts +22 -0
- package/dist/modality-provider.js +373 -0
- package/dist/native-visibility.d.ts +28 -0
- package/dist/native-visibility.js +50 -0
- package/dist/platform/VoiceRecognitionBar.d.ts +17 -0
- package/dist/platform/VoiceRecognitionBar.js +332 -0
- package/dist/platform/components.d.ts +32 -0
- package/dist/platform/components.js +351 -0
- package/dist/platform/events.d.ts +31 -0
- package/dist/platform/events.js +274 -0
- package/dist/platform/index.d.ts +3 -0
- package/dist/platform/index.js +39 -0
- package/dist/platform/types.d.ts +79 -0
- package/dist/platform/types.js +97 -0
- package/dist/react-decorators.d.ts +87 -0
- package/dist/react-decorators.js +368 -0
- package/dist/shared-store.d.ts +74 -0
- package/dist/shared-store.js +589 -0
- package/dist/speech-recognition/__tests__/speech-recognition-groq-transport.test.d.ts +1 -0
- package/dist/speech-recognition/__tests__/speech-recognition-native.test.d.ts +1 -0
- package/dist/speech-recognition/__tests__/speech-recognition-openai-native.test.d.ts +1 -0
- package/dist/speech-recognition/__tests__/speech-recognition-openai.test.d.ts +1 -0
- package/dist/speech-recognition/__tests__/speech-recognition-unified-import.test.d.ts +0 -0
- package/dist/speech-recognition/__tests__/speech-recognition-unified.test.d.ts +1 -0
- package/dist/speech-recognition/speech-recognition-groq.d.ts +21 -0
- package/dist/speech-recognition/speech-recognition-groq.js +409 -0
- package/dist/speech-recognition/speech-recognition-mlx.d.ts +15 -0
- package/dist/speech-recognition/speech-recognition-mlx.js +393 -0
- package/dist/speech-recognition/speech-recognition-native.d.ts +24 -0
- package/dist/speech-recognition/speech-recognition-native.js +632 -0
- package/dist/speech-recognition/speech-recognition-openai-native.d.ts +40 -0
- package/dist/speech-recognition/speech-recognition-openai-native.js +653 -0
- package/dist/speech-recognition/speech-recognition-openai.d.ts +39 -0
- package/dist/speech-recognition/speech-recognition-openai.js +718 -0
- package/dist/speech-recognition/speech-recognition-unified.d.ts +93 -0
- package/dist/speech-recognition/speech-recognition-unified.js +589 -0
- package/dist/speech-recognition/utils/groq-transcription.d.ts +41 -0
- package/dist/speech-recognition/utils/groq-transcription.js +382 -0
- package/dist/speech-recognition.d.ts +7 -0
- package/dist/speech-recognition.js +61 -0
- package/dist/voice-pipeline-telemetry.d.ts +26 -0
- package/dist/voice-pipeline-telemetry.js +15 -0
- package/garrix82-reactgenie-lib-1.3.0.tgz +0 -0
- package/metro/index.js +3 -0
- package/metro/with-genie-registry.js +47 -0
- package/package.json +111 -0
- package/scripts/dry-run.js +23 -0
- package/scripts/generate-genie-registry.js +278 -0
- package/scripts/log-file-test.js +51 -0
- package/scripts/parse.js +26 -0
- package/scripts/prompt.js +19 -0
- package/scripts/set-script.js +200 -0
- package/tsconfig.json +36 -0
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = exports.MLXSpeechRecognizer = void 0;
|
|
7
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
8
|
+
var _reactNative = require("react-native");
|
|
9
|
+
var _logger = _interopRequireDefault(require("../logger"));
|
|
10
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
|
+
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
12
|
+
/**
|
|
13
|
+
* MLX Whisper-based Speech Recognition using a local FastAPI server.
|
|
14
|
+
* Simplified version with manual start/stop control.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const MLXSpeechRecognizer = ({
|
|
18
|
+
shouldListen,
|
|
19
|
+
speechStatusCallback,
|
|
20
|
+
speechResultCallback,
|
|
21
|
+
language = 'en',
|
|
22
|
+
onError,
|
|
23
|
+
baseUrl = 'http://127.0.0.1:8000',
|
|
24
|
+
mode,
|
|
25
|
+
modelName = 'large-v3-turbo',
|
|
26
|
+
minAudioSize = 1000
|
|
27
|
+
}) => {
|
|
28
|
+
const [isRecording, setIsRecording] = (0, _react.useState)(false);
|
|
29
|
+
const mediaRecorderRef = (0, _react.useRef)(null);
|
|
30
|
+
const audioChunksRef = (0, _react.useRef)([]);
|
|
31
|
+
const streamRef = (0, _react.useRef)(null);
|
|
32
|
+
const abortControllerRef = (0, _react.useRef)(null);
|
|
33
|
+
const startTimeRef = (0, _react.useRef)(0);
|
|
34
|
+
// Prevent concurrent uploads / duplicate calls
|
|
35
|
+
const processingRef = (0, _react.useRef)(false);
|
|
36
|
+
// Track last sent transcript for finalization
|
|
37
|
+
const lastSentTranscriptRef = (0, _react.useRef)('');
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Start recording audio from microphone.
|
|
41
|
+
*/
|
|
42
|
+
const startRecording = (0, _react.useCallback)(async () => {
|
|
43
|
+
try {
|
|
44
|
+
_logger.default.debug('Starting MLX Whisper recording...');
|
|
45
|
+
_logger.default.debug(`shouldListen=${shouldListen}, isRecording=${isRecording}, processing=${processingRef.current}`);
|
|
46
|
+
|
|
47
|
+
// Browser-specific audio constraints
|
|
48
|
+
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
|
49
|
+
_logger.default.debug(`Browser detection: Safari = ${isSafari}`);
|
|
50
|
+
const stream = await navigator.mediaDevices.getUserMedia({
|
|
51
|
+
audio: isSafari ? {
|
|
52
|
+
// Safari prefers simpler constraints
|
|
53
|
+
echoCancellation: false,
|
|
54
|
+
noiseSuppression: false,
|
|
55
|
+
autoGainControl: false
|
|
56
|
+
} : {
|
|
57
|
+
echoCancellation: true,
|
|
58
|
+
noiseSuppression: true,
|
|
59
|
+
autoGainControl: true,
|
|
60
|
+
sampleRate: 16000
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
_logger.default.debug(`Audio stream tracks: ${stream.getAudioTracks().length}`);
|
|
64
|
+
stream.getAudioTracks().forEach((track, index) => {
|
|
65
|
+
_logger.default.debug(`Track ${index}: ${track.label}, enabled: ${track.enabled}, readyState: ${track.readyState}`);
|
|
66
|
+
});
|
|
67
|
+
streamRef.current = stream;
|
|
68
|
+
audioChunksRef.current = [];
|
|
69
|
+
|
|
70
|
+
// Create MediaRecorder with supported format
|
|
71
|
+
const mimeType = getSupportedMimeType();
|
|
72
|
+
_logger.default.debug(`Using MIME type: ${mimeType}`);
|
|
73
|
+
|
|
74
|
+
// Try creating MediaRecorder with minimal options first
|
|
75
|
+
let mediaRecorder;
|
|
76
|
+
try {
|
|
77
|
+
mediaRecorder = new MediaRecorder(stream, {
|
|
78
|
+
mimeType
|
|
79
|
+
});
|
|
80
|
+
_logger.default.debug('MediaRecorder created with minimal options');
|
|
81
|
+
} catch (error) {
|
|
82
|
+
_logger.default.warn('MediaRecorder constructor failed with minimal options, trying fallback:', error);
|
|
83
|
+
// Fallback without mimeType
|
|
84
|
+
mediaRecorder = new MediaRecorder(stream);
|
|
85
|
+
_logger.default.debug('MediaRecorder created with fallback options');
|
|
86
|
+
}
|
|
87
|
+
mediaRecorderRef.current = mediaRecorder;
|
|
88
|
+
|
|
89
|
+
// Handle audio data
|
|
90
|
+
mediaRecorder.ondataavailable = event => {
|
|
91
|
+
if (event.data.size > 0) {
|
|
92
|
+
audioChunksRef.current.push(event.data);
|
|
93
|
+
_logger.default.debug(`Audio chunk: ${event.data.size} bytes`);
|
|
94
|
+
} else {
|
|
95
|
+
_logger.default.debug('ondataavailable with empty chunk');
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// Handle start
|
|
100
|
+
mediaRecorder.onstart = () => {
|
|
101
|
+
_logger.default.debug('MediaRecorder started, state:', mediaRecorder.state);
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
// Handle recording stop
|
|
105
|
+
mediaRecorder.onstop = async () => {
|
|
106
|
+
_logger.default.debug('Recording stopped, processing audio...');
|
|
107
|
+
setIsRecording(false);
|
|
108
|
+
|
|
109
|
+
// Clean up stream (close mic immediately)
|
|
110
|
+
if (streamRef.current) {
|
|
111
|
+
streamRef.current.getTracks().forEach(track => track.stop());
|
|
112
|
+
streamRef.current = null;
|
|
113
|
+
}
|
|
114
|
+
_logger.default.info('🛑 MLX Whisper recording stopped');
|
|
115
|
+
_logger.default.debug(`Collected ${audioChunksRef.current.length} audio chunks`);
|
|
116
|
+
await processAudioChunks();
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// Handle errors
|
|
120
|
+
mediaRecorder.onerror = event => {
|
|
121
|
+
_logger.default.error('MediaRecorder error:', event);
|
|
122
|
+
setIsRecording(false);
|
|
123
|
+
const error = new Error('Recording failed');
|
|
124
|
+
if (onError) onError(error);
|
|
125
|
+
speechStatusCallback(false, '');
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
// Start recording with a small timeslice to ensure data collection
|
|
129
|
+
mediaRecorder.start(100); // Collect data every 100ms
|
|
130
|
+
_logger.default.debug('MediaRecorder.start() called');
|
|
131
|
+
startTimeRef.current = Date.now();
|
|
132
|
+
setIsRecording(true);
|
|
133
|
+
speechStatusCallback(true, '');
|
|
134
|
+
_logger.default.info('🎤 MLX Whisper recording started');
|
|
135
|
+
} catch (error) {
|
|
136
|
+
_logger.default.error('Failed to start recording:', error);
|
|
137
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
138
|
+
if (onError) onError(err);
|
|
139
|
+
speechStatusCallback(false, '');
|
|
140
|
+
}
|
|
141
|
+
}, [speechStatusCallback, onError]);
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Stop recording and process audio.
|
|
145
|
+
*/
|
|
146
|
+
const stopRecording = (0, _react.useCallback)(() => {
|
|
147
|
+
const elapsed = Date.now() - startTimeRef.current;
|
|
148
|
+
const minDuration = 1000; // Minimum 1 second recording
|
|
149
|
+
|
|
150
|
+
if (elapsed < minDuration) {
|
|
151
|
+
// Schedule stop after minimum duration
|
|
152
|
+
const delay = minDuration - elapsed;
|
|
153
|
+
setTimeout(() => {
|
|
154
|
+
if (mediaRecorderRef.current && mediaRecorderRef.current.state === 'recording') {
|
|
155
|
+
try {
|
|
156
|
+
// Flush any pending data
|
|
157
|
+
mediaRecorderRef.current.requestData?.();
|
|
158
|
+
} catch (e) {}
|
|
159
|
+
mediaRecorderRef.current.stop();
|
|
160
|
+
}
|
|
161
|
+
}, delay);
|
|
162
|
+
_logger.default.debug(`Recording too short (${elapsed}ms), delaying stop by ${delay}ms`);
|
|
163
|
+
} else {
|
|
164
|
+
// Stop immediately if minimum duration met
|
|
165
|
+
if (mediaRecorderRef.current && mediaRecorderRef.current.state === 'recording') {
|
|
166
|
+
try {
|
|
167
|
+
mediaRecorderRef.current.requestData?.();
|
|
168
|
+
} catch (e) {}
|
|
169
|
+
mediaRecorderRef.current.stop();
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Note: setIsRecording(false) moved to onstop handler
|
|
174
|
+
}, []);
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Process collected audio chunks and send to server.
|
|
178
|
+
*/
|
|
179
|
+
const processAudioChunks = (0, _react.useCallback)(async () => {
|
|
180
|
+
if (audioChunksRef.current.length === 0) {
|
|
181
|
+
_logger.default.warn('No audio chunks to process');
|
|
182
|
+
speechStatusCallback(false, '');
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Prevent duplicate uploads
|
|
187
|
+
if (processingRef.current) {
|
|
188
|
+
_logger.default.warn('Already processing an utterance, skipping duplicate upload');
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
processingRef.current = true;
|
|
192
|
+
// Give feedback to UI that we are uploading/transcribing
|
|
193
|
+
try {
|
|
194
|
+
// indicate remote processing started (no fake interim text)
|
|
195
|
+
speechStatusCallback(true, '');
|
|
196
|
+
// Create audio blob
|
|
197
|
+
const mimeType = getSupportedMimeType();
|
|
198
|
+
const audioBlob = new Blob(audioChunksRef.current, {
|
|
199
|
+
type: mimeType
|
|
200
|
+
});
|
|
201
|
+
_logger.default.debug(`Audio blob size: ${audioBlob.size} bytes`);
|
|
202
|
+
if (audioBlob.size < minAudioSize) {
|
|
203
|
+
_logger.default.warn(`Audio too short (${audioBlob.size} < ${minAudioSize} bytes), skipping`);
|
|
204
|
+
speechStatusCallback(false, '');
|
|
205
|
+
speechResultCallback('');
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Create file for upload
|
|
210
|
+
const extension = getFileExtension(mimeType);
|
|
211
|
+
const audioFile = new File([audioBlob], `audio.${extension}`, {
|
|
212
|
+
type: mimeType
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
// Use single REST endpoint for oneshot and SSE
|
|
216
|
+
const endpoint = `${baseUrl}/v1/audio/transcriptions`;
|
|
217
|
+
|
|
218
|
+
// Prepare request
|
|
219
|
+
abortControllerRef.current = new AbortController();
|
|
220
|
+
const formData = new FormData();
|
|
221
|
+
formData.append('file', audioFile);
|
|
222
|
+
formData.append('model', modelName);
|
|
223
|
+
formData.append('response_format', 'json');
|
|
224
|
+
if (language) formData.append('language', language);
|
|
225
|
+
if (mode === 'oneshot') {
|
|
226
|
+
formData.append('stream', 'false');
|
|
227
|
+
} else {
|
|
228
|
+
formData.append('stream', 'true');
|
|
229
|
+
}
|
|
230
|
+
_logger.default.info(`📤 Sending ${audioBlob.size} bytes to ${endpoint}`);
|
|
231
|
+
_logger.default.info(`🗣️ Mode: ${mode}, Model: ${modelName}, endpoint: ${endpoint}`);
|
|
232
|
+
|
|
233
|
+
// Send to server
|
|
234
|
+
const response = await fetch(endpoint, {
|
|
235
|
+
method: 'POST',
|
|
236
|
+
body: formData,
|
|
237
|
+
signal: abortControllerRef.current.signal
|
|
238
|
+
});
|
|
239
|
+
if (!response.ok) {
|
|
240
|
+
throw new Error(`Server error: ${response.status}`);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Handle response
|
|
244
|
+
if (mode === 'oneshot') {
|
|
245
|
+
const result = await response.json();
|
|
246
|
+
const transcript = result?.text?.trim() || '';
|
|
247
|
+
_logger.default.debug('Received transcription response:', result);
|
|
248
|
+
_logger.default.debug(`Transcription text: "${transcript}"`);
|
|
249
|
+
// Deliver transcript first, then signal end so ModalityProvider processes it once
|
|
250
|
+
lastSentTranscriptRef.current = transcript;
|
|
251
|
+
speechResultCallback(transcript);
|
|
252
|
+
speechStatusCallback(false, '');
|
|
253
|
+
} else {
|
|
254
|
+
// Handle streaming response (SSE)
|
|
255
|
+
await handleStreamingResponse(response);
|
|
256
|
+
}
|
|
257
|
+
} catch (error) {
|
|
258
|
+
_logger.default.error('Transcription error:', error);
|
|
259
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
260
|
+
if (onError) onError(err);
|
|
261
|
+
speechStatusCallback(false, '');
|
|
262
|
+
speechResultCallback('');
|
|
263
|
+
} finally {
|
|
264
|
+
audioChunksRef.current = [];
|
|
265
|
+
if (abortControllerRef.current) {
|
|
266
|
+
abortControllerRef.current = null;
|
|
267
|
+
}
|
|
268
|
+
processingRef.current = false;
|
|
269
|
+
}
|
|
270
|
+
}, [speechStatusCallback, speechResultCallback, baseUrl, mode, modelName, language, minAudioSize, onError]);
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Handle streaming transcription response.
|
|
274
|
+
*/
|
|
275
|
+
const handleStreamingResponse = (0, _react.useCallback)(async response => {
|
|
276
|
+
const reader = response.body?.getReader();
|
|
277
|
+
if (!reader) throw new Error('No response reader');
|
|
278
|
+
const decoder = new TextDecoder();
|
|
279
|
+
let buffer = '';
|
|
280
|
+
let lastTranscript = '';
|
|
281
|
+
let sawDone = false;
|
|
282
|
+
try {
|
|
283
|
+
let done = false;
|
|
284
|
+
while (!done) {
|
|
285
|
+
const result = await reader.read();
|
|
286
|
+
done = result.done;
|
|
287
|
+
if (done) break;
|
|
288
|
+
buffer += decoder.decode(result.value, {
|
|
289
|
+
stream: true
|
|
290
|
+
});
|
|
291
|
+
const lines = buffer.split('\n');
|
|
292
|
+
buffer = lines.pop() || '';
|
|
293
|
+
for (const line of lines) {
|
|
294
|
+
if (line.startsWith('data: ')) {
|
|
295
|
+
const data = line.slice(6).trim();
|
|
296
|
+
if (data === '[DONE]') {
|
|
297
|
+
sawDone = true;
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
300
|
+
try {
|
|
301
|
+
const parsedResult = JSON.parse(data);
|
|
302
|
+
const transcript = parsedResult?.text?.trim();
|
|
303
|
+
if (transcript) {
|
|
304
|
+
_logger.default.info(`📝 Streaming: "${transcript}"`);
|
|
305
|
+
lastTranscript = transcript;
|
|
306
|
+
// deliver partial to UI immediately
|
|
307
|
+
speechResultCallback(transcript);
|
|
308
|
+
}
|
|
309
|
+
} catch (e) {
|
|
310
|
+
// Ignore parse errors
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
if (sawDone) break;
|
|
315
|
+
}
|
|
316
|
+
} finally {
|
|
317
|
+
// Small delay to ensure UI has applied last partial
|
|
318
|
+
try {
|
|
319
|
+
await new Promise(res => setTimeout(res, 60));
|
|
320
|
+
} catch (e) {}
|
|
321
|
+
if (lastTranscript) {
|
|
322
|
+
_logger.default.debug(`Final streaming transcript before end: "${lastTranscript}"`);
|
|
323
|
+
try {
|
|
324
|
+
speechResultCallback(lastTranscript);
|
|
325
|
+
} catch (e) {}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// Signal stream end so ModalityProvider triggers the Genie interpreter once
|
|
329
|
+
try {
|
|
330
|
+
speechStatusCallback(false, '');
|
|
331
|
+
} catch (e) {}
|
|
332
|
+
reader.releaseLock();
|
|
333
|
+
}
|
|
334
|
+
}, [speechStatusCallback, speechResultCallback]);
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* React to shouldListen changes.
|
|
338
|
+
*/
|
|
339
|
+
(0, _react.useEffect)(() => {
|
|
340
|
+
_logger.default.debug(`shouldListen prop changed: ${shouldListen}`);
|
|
341
|
+
// Avoid starting a new recording while previous utterance is processing
|
|
342
|
+
if (shouldListen && !isRecording && !processingRef.current) {
|
|
343
|
+
startRecording();
|
|
344
|
+
} else if (!shouldListen && isRecording) {
|
|
345
|
+
stopRecording();
|
|
346
|
+
}
|
|
347
|
+
}, [shouldListen, isRecording, startRecording, stopRecording]);
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Cleanup on unmount.
|
|
351
|
+
*/
|
|
352
|
+
(0, _react.useEffect)(() => {
|
|
353
|
+
return () => {
|
|
354
|
+
if (mediaRecorderRef.current && mediaRecorderRef.current.state === 'recording') {
|
|
355
|
+
mediaRecorderRef.current.stop();
|
|
356
|
+
}
|
|
357
|
+
if (streamRef.current) {
|
|
358
|
+
streamRef.current.getTracks().forEach(track => track.stop());
|
|
359
|
+
}
|
|
360
|
+
if (abortControllerRef.current) {
|
|
361
|
+
abortControllerRef.current.abort();
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
}, []);
|
|
365
|
+
return /*#__PURE__*/_react.default.createElement(_reactNative.View, null);
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Get supported MIME type for MediaRecorder.
|
|
370
|
+
*/
|
|
371
|
+
exports.MLXSpeechRecognizer = MLXSpeechRecognizer;
|
|
372
|
+
function getSupportedMimeType() {
|
|
373
|
+
const types = ['audio/webm', 'audio/mp4', 'audio/wav', 'audio/ogg'];
|
|
374
|
+
for (const type of types) {
|
|
375
|
+
if (MediaRecorder.isTypeSupported(type)) {
|
|
376
|
+
return type;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
return 'audio/webm';
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Get file extension for MIME type.
|
|
384
|
+
*/
|
|
385
|
+
function getFileExtension(mimeType) {
|
|
386
|
+
if (mimeType.includes('webm')) return 'webm';
|
|
387
|
+
if (mimeType.includes('mp4')) return 'mp4';
|
|
388
|
+
if (mimeType.includes('wav')) return 'wav';
|
|
389
|
+
if (mimeType.includes('ogg')) return 'ogg';
|
|
390
|
+
return 'webm';
|
|
391
|
+
}
|
|
392
|
+
var _default = exports.default = MLXSpeechRecognizer;
|
|
393
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZCIsInJlcXVpcmUiLCJfcmVhY3ROYXRpdmUiLCJfbG9nZ2VyIiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsImUiLCJfX2VzTW9kdWxlIiwiZGVmYXVsdCIsInQiLCJXZWFrTWFwIiwiciIsIm4iLCJvIiwiaSIsImYiLCJfX3Byb3RvX18iLCJoYXMiLCJnZXQiLCJzZXQiLCJoYXNPd25Qcm9wZXJ0eSIsImNhbGwiLCJPYmplY3QiLCJkZWZpbmVQcm9wZXJ0eSIsImdldE93blByb3BlcnR5RGVzY3JpcHRvciIsIk1MWFNwZWVjaFJlY29nbml6ZXIiLCJzaG91bGRMaXN0ZW4iLCJzcGVlY2hTdGF0dXNDYWxsYmFjayIsInNwZWVjaFJlc3VsdENhbGxiYWNrIiwibGFuZ3VhZ2UiLCJvbkVycm9yIiwiYmFzZVVybCIsIm1vZGUiLCJtb2RlbE5hbWUiLCJtaW5BdWRpb1NpemUiLCJpc1JlY29yZGluZyIsInNldElzUmVjb3JkaW5nIiwidXNlU3RhdGUiLCJtZWRpYVJlY29yZGVyUmVmIiwidXNlUmVmIiwiYXVkaW9DaHVua3NSZWYiLCJzdHJlYW1SZWYiLCJhYm9ydENvbnRyb2xsZXJSZWYiLCJzdGFydFRpbWVSZWYiLCJwcm9jZXNzaW5nUmVmIiwibGFzdFNlbnRUcmFuc2NyaXB0UmVmIiwic3RhcnRSZWNvcmRpbmciLCJ1c2VDYWxsYmFjayIsImxvZ2dlciIsImRlYnVnIiwiY3VycmVudCIsImlzU2FmYXJpIiwidGVzdCIsIm5hdmlnYXRvciIsInVzZXJBZ2VudCIsInN0cmVhbSIsIm1lZGlhRGV2aWNlcyIsImdldFVzZXJNZWRpYSIsImF1ZGlvIiwiZWNob0NhbmNlbGxhdGlvbiIsIm5vaXNlU3VwcHJlc3Npb24iLCJhdXRvR2FpbkNvbnRyb2wiLCJzYW1wbGVSYXRlIiwiZ2V0QXVkaW9UcmFja3MiLCJsZW5ndGgiLCJmb3JFYWNoIiwidHJhY2siLCJpbmRleCIsImxhYmVsIiwiZW5hYmxlZCIsInJlYWR5U3RhdGUiLCJtaW1lVHlwZSIsImdldFN1cHBvcnRlZE1pbWVUeXBlIiwibWVkaWFSZWNvcmRlciIsIk1lZGlhUmVjb3JkZXIiLCJlcnJvciIsIndhcm4iLCJvbmRhdGFhdmFpbGFibGUiLCJldmVudCIsImRhdGEiLCJzaXplIiwicHVzaCIsIm9uc3RhcnQiLCJzdGF0ZSIsIm9uc3RvcCIsImdldFRyYWNrcyIsInN0b3AiLCJpbmZvIiwicHJvY2Vzc0F1ZGlvQ2h1bmtzIiwib25lcnJvciIsIkVycm9yIiwic3RhcnQiLCJEYXRlIiwibm93IiwiZXJyIiwiU3RyaW5nIiwic3RvcFJlY29yZGluZyIsImVsYXBzZWQiLCJtaW5EdXJhdGlvbiIsImRlbGF5Iiwic2V0VGltZW91dCIsInJlcXVlc3REYXRhIiwiYXVkaW9CbG9iIiwiQmxvYiIsInR5cGUiLCJleHRlbnNpb24iLCJnZXRGaWxlRXh0ZW5zaW9uIiwiYXVkaW9GaWxlIiwiRmlsZSIsImVuZHBvaW50IiwiQWJvcnRDb250cm9sbGVyIiwiZm9ybURhdGEiLCJGb3JtRGF0YSIsImFwcGVuZCIsInJlc3BvbnNlIiwiZmV0Y2giLCJtZXRob2QiLCJib2R5Iiwic2lnbmFsIiwib2siLCJzdGF0dXMiLCJyZXN1bHQiLCJqc29uIiwidHJhbnNjcmlwdCIsInRleHQiLCJ0cmltIiwiaGFuZGxlU3RyZWFtaW5nUmVzcG9uc2UiLCJyZWFkZXIiLCJnZXRSZWFkZXIiLCJkZWNvZGVyIiwiVGV4dERlY29kZXIiLCJidWZmZXIiLCJsYXN0VHJhbnNjcmlwdCIsInNhd0RvbmUiLCJkb25lIiwicmVhZCIsImRlY29kZSIsInZhbHVlIiwibGluZXMiLCJzcGxpdCIsInBvcCIsImxpbmUiLCJzdGFydHNXaXRoIiwic2xpY2UiLCJwYXJzZWRSZXN1bHQiLCJKU09OIiwicGFyc2UiLCJQcm9taXNlIiwicmVzIiwicmVsZWFzZUxvY2siLCJ1c2VFZmZlY3QiLCJhYm9ydCIsImNyZWF0ZUVsZW1lbnQiLCJWaWV3IiwiZXhwb3J0cyIsInR5cGVzIiwiaXNUeXBlU3VwcG9ydGVkIiwiaW5jbHVkZXMiLCJfZGVmYXVsdCJdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zcGVlY2gtcmVjb2duaXRpb24vc3BlZWNoLXJlY29nbml0aW9uLW1seC50c3giXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBNTFggV2hpc3Blci1iYXNlZCBTcGVlY2ggUmVjb2duaXRpb24gdXNpbmcgYSBsb2NhbCBGYXN0QVBJIHNlcnZlci5cbiAqIFNpbXBsaWZpZWQgdmVyc2lvbiB3aXRoIG1hbnVhbCBzdGFydC9zdG9wIGNvbnRyb2wuXG4gKi9cblxuaW1wb3J0IFJlYWN0LCB7IHVzZVN0YXRlLCB1c2VSZWYsIHVzZUNhbGxiYWNrLCB1c2VFZmZlY3QgfSBmcm9tICdyZWFjdCc7XG5pbXBvcnQgeyBWaWV3IH0gZnJvbSAncmVhY3QtbmF0aXZlJztcbmltcG9ydCBsb2dnZXIgZnJvbSAnLi4vbG9nZ2VyJztcblxuZXhwb3J0IHR5cGUgTG9jYWxXaGlzcGVyTW9kZSA9ICdvbmVzaG90JyB8ICdzc2UnIHwgJ3JlYWx0aW1lJztcblxuZXhwb3J0IGludGVyZmFjZSBNTFhTcGVlY2hSZWNvZ25pemVyUHJvcHMge1xuICBzaG91bGRMaXN0ZW46IGJvb2xlYW47XG4gIHNwZWVjaFN0YXR1c0NhbGxiYWNrOiAoc3RhdHVzOiBib29sZWFuLCB0cmFuc2NyaXB0OiBzdHJpbmcpID0+IHZvaWQ7XG4gIHNwZWVjaFJlc3VsdENhbGxiYWNrOiAocmVzdWx0OiBzdHJpbmcpID0+IHZvaWQ7XG4gIGxhbmd1YWdlPzogc3RyaW5nO1xuICBvbkVycm9yPzogKGVycm9yOiBFcnJvcikgPT4gdm9pZDtcbiAgYmFzZVVybD86IHN0cmluZztcbiAgbW9kZT86IExvY2FsV2hpc3Blck1vZGU7XG4gIG1vZGVsTmFtZT86IHN0cmluZztcbiAgbWluQXVkaW9TaXplPzogbnVtYmVyO1xufVxuXG5leHBvcnQgY29uc3QgTUxYU3BlZWNoUmVjb2duaXplcjogUmVhY3QuRkM8TUxYU3BlZWNoUmVjb2duaXplclByb3BzPiA9ICh7XG4gIHNob3VsZExpc3RlbixcbiAgc3BlZWNoU3RhdHVzQ2FsbGJhY2ssXG4gIHNwZWVjaFJlc3VsdENhbGxiYWNrLFxuICBsYW5ndWFnZSA9ICdlbicsXG4gIG9uRXJyb3IsXG4gIGJhc2VVcmwgPSAnaHR0cDovLzEyNy4wLjAuMTo4MDAwJyxcbiAgbW9kZSxcbiAgbW9kZWxOYW1lID0gJ2xhcmdlLXYzLXR1cmJvJyxcbiAgbWluQXVkaW9TaXplID0gMTAwMCxcbn0pID0+IHtcbiAgY29uc3QgW2lzUmVjb3JkaW5nLCBzZXRJc1JlY29yZGluZ10gPSB1c2VTdGF0ZShmYWxzZSk7XG4gIGNvbnN0IG1lZGlhUmVjb3JkZXJSZWYgPSB1c2VSZWY8TWVkaWFSZWNvcmRlciB8IG51bGw+KG51bGwpO1xuICBjb25zdCBhdWRpb0NodW5rc1JlZiA9IHVzZVJlZjxCbG9iW10+KFtdKTtcbiAgY29uc3Qgc3RyZWFtUmVmID0gdXNlUmVmPE1lZGlhU3RyZWFtIHwgbnVsbD4obnVsbCk7XG4gIGNvbnN0IGFib3J0Q29udHJvbGxlclJlZiA9IHVzZVJlZjxBYm9ydENvbnRyb2xsZXIgfCBudWxsPihudWxsKTtcbiAgY29uc3Qgc3RhcnRUaW1lUmVmID0gdXNlUmVmPG51bWJlcj4oMCk7XG4gIC8vIFByZXZlbnQgY29uY3VycmVudCB1cGxvYWRzIC8gZHVwbGljYXRlIGNhbGxzXG4gIGNvbnN0IHByb2Nlc3NpbmdSZWYgPSB1c2VSZWY8Ym9vbGVhbj4oZmFsc2UpO1xuICAvLyBUcmFjayBsYXN0IHNlbnQgdHJhbnNjcmlwdCBmb3IgZmluYWxpemF0aW9uXG4gIGNvbnN0IGxhc3RTZW50VHJhbnNjcmlwdFJlZiA9IHVzZVJlZjxzdHJpbmc+KCcnKTtcblxuICAvKipcbiAgICogU3RhcnQgcmVjb3JkaW5nIGF1ZGlvIGZyb20gbWljcm9waG9uZS5cbiAgICovXG4gIGNvbnN0IHN0YXJ0UmVjb3JkaW5nID0gdXNlQ2FsbGJhY2soYXN5bmMgKCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBsb2dnZXIuZGVidWcoJ1N0YXJ0aW5nIE1MWCBXaGlzcGVyIHJlY29yZGluZy4uLicpO1xuICAgICAgbG9nZ2VyLmRlYnVnKGBzaG91bGRMaXN0ZW49JHtzaG91bGRMaXN0ZW59LCBpc1JlY29yZGluZz0ke2lzUmVjb3JkaW5nfSwgcHJvY2Vzc2luZz0ke3Byb2Nlc3NpbmdSZWYuY3VycmVudH1gKTtcblxuICAgICAgLy8gQnJvd3Nlci1zcGVjaWZpYyBhdWRpbyBjb25zdHJhaW50c1xuICAgICAgY29uc3QgaXNTYWZhcmkgPSAvXigoPyFjaHJvbWV8YW5kcm9pZCkuKSpzYWZhcmkvaS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpO1xuICAgICAgbG9nZ2VyLmRlYnVnKGBCcm93c2VyIGRldGVjdGlvbjogU2FmYXJpID0gJHtpc1NhZmFyaX1gKTtcblxuICAgICAgY29uc3Qgc3RyZWFtID0gYXdhaXQgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoe1xuICAgICAgICBhdWRpbzogaXNTYWZhcmkgPyB7XG4gICAgICAgICAgLy8gU2FmYXJpIHByZWZlcnMgc2ltcGxlciBjb25zdHJhaW50c1xuICAgICAgICAgIGVjaG9DYW5jZWxsYXRpb246IGZhbHNlLFxuICAgICAgICAgIG5vaXNlU3VwcHJlc3Npb246IGZhbHNlLFxuICAgICAgICAgIGF1dG9HYWluQ29udHJvbDogZmFsc2UsXG4gICAgICAgIH0gOiB7XG4gICAgICAgICAgZWNob0NhbmNlbGxhdGlvbjogdHJ1ZSxcbiAgICAgICAgICBub2lzZVN1cHByZXNzaW9uOiB0cnVlLFxuICAgICAgICAgIGF1dG9HYWluQ29udHJvbDogdHJ1ZSxcbiAgICAgICAgICBzYW1wbGVSYXRlOiAxNjAwMCxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICBsb2dnZXIuZGVidWcoYEF1ZGlvIHN0cmVhbSB0cmFja3M6ICR7c3RyZWFtLmdldEF1ZGlvVHJhY2tzKCkubGVuZ3RofWApO1xuICAgICAgc3RyZWFtLmdldEF1ZGlvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2ssIGluZGV4KSA9PiB7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZyhgVHJhY2sgJHtpbmRleH06ICR7dHJhY2subGFiZWx9LCBlbmFibGVkOiAke3RyYWNrLmVuYWJsZWR9LCByZWFkeVN0YXRlOiAke3RyYWNrLnJlYWR5U3RhdGV9YCk7XG4gICAgICB9KTtcblxuICAgICAgc3RyZWFtUmVmLmN1cnJlbnQgPSBzdHJlYW07XG4gICAgICBhdWRpb0NodW5rc1JlZi5jdXJyZW50ID0gW107XG5cbiAgICAgIC8vIENyZWF0ZSBNZWRpYVJlY29yZGVyIHdpdGggc3VwcG9ydGVkIGZvcm1hdFxuICAgICAgY29uc3QgbWltZVR5cGUgPSBnZXRTdXBwb3J0ZWRNaW1lVHlwZSgpO1xuICAgICAgbG9nZ2VyLmRlYnVnKGBVc2luZyBNSU1FIHR5cGU6ICR7bWltZVR5cGV9YCk7XG5cbiAgICAgIC8vIFRyeSBjcmVhdGluZyBNZWRpYVJlY29yZGVyIHdpdGggbWluaW1hbCBvcHRpb25zIGZpcnN0XG4gICAgICBsZXQgbWVkaWFSZWNvcmRlcjogTWVkaWFSZWNvcmRlcjtcbiAgICAgIHRyeSB7XG4gICAgICAgIG1lZGlhUmVjb3JkZXIgPSBuZXcgTWVkaWFSZWNvcmRlcihzdHJlYW0sIHsgbWltZVR5cGUgfSk7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZygnTWVkaWFSZWNvcmRlciBjcmVhdGVkIHdpdGggbWluaW1hbCBvcHRpb25zJyk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBsb2dnZXIud2FybignTWVkaWFSZWNvcmRlciBjb25zdHJ1Y3RvciBmYWlsZWQgd2l0aCBtaW5pbWFsIG9wdGlvbnMsIHRyeWluZyBmYWxsYmFjazonLCBlcnJvcik7XG4gICAgICAgIC8vIEZhbGxiYWNrIHdpdGhvdXQgbWltZVR5cGVcbiAgICAgICAgbWVkaWFSZWNvcmRlciA9IG5ldyBNZWRpYVJlY29yZGVyKHN0cmVhbSk7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZygnTWVkaWFSZWNvcmRlciBjcmVhdGVkIHdpdGggZmFsbGJhY2sgb3B0aW9ucycpO1xuICAgICAgfVxuXG4gICAgICBtZWRpYVJlY29yZGVyUmVmLmN1cnJlbnQgPSBtZWRpYVJlY29yZGVyO1xuXG4gICAgICAvLyBIYW5kbGUgYXVkaW8gZGF0YVxuICAgICAgbWVkaWFSZWNvcmRlci5vbmRhdGFhdmFpbGFibGUgPSAoZXZlbnQ6IEJsb2JFdmVudCkgPT4ge1xuICAgICAgICBpZiAoZXZlbnQuZGF0YS5zaXplID4gMCkge1xuICAgICAgICAgIGF1ZGlvQ2h1bmtzUmVmLmN1cnJlbnQucHVzaChldmVudC5kYXRhKTtcbiAgICAgICAgICBsb2dnZXIuZGVidWcoYEF1ZGlvIGNodW5rOiAke2V2ZW50LmRhdGEuc2l6ZX0gYnl0ZXNgKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBsb2dnZXIuZGVidWcoJ29uZGF0YWF2YWlsYWJsZSB3aXRoIGVtcHR5IGNodW5rJyk7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIC8vIEhhbmRsZSBzdGFydFxuICAgICAgbWVkaWFSZWNvcmRlci5vbnN0YXJ0ID0gKCkgPT4ge1xuICAgICAgICBsb2dnZXIuZGVidWcoJ01lZGlhUmVjb3JkZXIgc3RhcnRlZCwgc3RhdGU6JywgbWVkaWFSZWNvcmRlci5zdGF0ZSk7XG4gICAgICB9O1xuXG4gICAgICAvLyBIYW5kbGUgcmVjb3JkaW5nIHN0b3BcbiAgICAgIG1lZGlhUmVjb3JkZXIub25zdG9wID0gYXN5bmMgKCkgPT4ge1xuICAgICAgICBsb2dnZXIuZGVidWcoJ1JlY29yZGluZyBzdG9wcGVkLCBwcm9jZXNzaW5nIGF1ZGlvLi4uJyk7XG4gICAgICAgIHNldElzUmVjb3JkaW5nKGZhbHNlKTtcblxuICAgICAgICAvLyBDbGVhbiB1cCBzdHJlYW0gKGNsb3NlIG1pYyBpbW1lZGlhdGVseSlcbiAgICAgICAgaWYgKHN0cmVhbVJlZi5jdXJyZW50KSB7XG4gICAgICAgICAgc3RyZWFtUmVmLmN1cnJlbnQuZ2V0VHJhY2tzKCkuZm9yRWFjaCh0cmFjayA9PiB0cmFjay5zdG9wKCkpO1xuICAgICAgICAgIHN0cmVhbVJlZi5jdXJyZW50ID0gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGxvZ2dlci5pbmZvKCfwn5uRIE1MWCBXaGlzcGVyIHJlY29yZGluZyBzdG9wcGVkJyk7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZyhgQ29sbGVjdGVkICR7YXVkaW9DaHVua3NSZWYuY3VycmVudC5sZW5ndGh9IGF1ZGlvIGNodW5rc2ApO1xuICAgICAgICBhd2FpdCBwcm9jZXNzQXVkaW9DaHVua3MoKTtcbiAgICAgIH07XG5cbiAgICAgIC8vIEhhbmRsZSBlcnJvcnNcbiAgICAgIG1lZGlhUmVjb3JkZXIub25lcnJvciA9IChldmVudDogRXZlbnQpID0+IHtcbiAgICAgICAgbG9nZ2VyLmVycm9yKCdNZWRpYVJlY29yZGVyIGVycm9yOicsIGV2ZW50KTtcbiAgICAgICAgc2V0SXNSZWNvcmRpbmcoZmFsc2UpO1xuICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBFcnJvcignUmVjb3JkaW5nIGZhaWxlZCcpO1xuICAgICAgICBpZiAob25FcnJvcikgb25FcnJvcihlcnJvcik7XG4gICAgICAgIHNwZWVjaFN0YXR1c0NhbGxiYWNrKGZhbHNlLCAnJyk7XG4gICAgICB9O1xuXG4gICAgICAvLyBTdGFydCByZWNvcmRpbmcgd2l0aCBhIHNtYWxsIHRpbWVzbGljZSB0byBlbnN1cmUgZGF0YSBjb2xsZWN0aW9uXG4gICAgICBtZWRpYVJlY29yZGVyLnN0YXJ0KDEwMCk7IC8vIENvbGxlY3QgZGF0YSBldmVyeSAxMDBtc1xuICAgICAgbG9nZ2VyLmRlYnVnKCdNZWRpYVJlY29yZGVyLnN0YXJ0KCkgY2FsbGVkJyk7XG5cbiAgICAgIHN0YXJ0VGltZVJlZi5jdXJyZW50ID0gRGF0ZS5ub3coKTtcbiAgICAgIHNldElzUmVjb3JkaW5nKHRydWUpO1xuICAgICAgc3BlZWNoU3RhdHVzQ2FsbGJhY2sodHJ1ZSwgJycpO1xuICAgICAgbG9nZ2VyLmluZm8oJ/CfjqQgTUxYIFdoaXNwZXIgcmVjb3JkaW5nIHN0YXJ0ZWQnKTtcblxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBsb2dnZXIuZXJyb3IoJ0ZhaWxlZCB0byBzdGFydCByZWNvcmRpbmc6JywgZXJyb3IpO1xuICAgICAgY29uc3QgZXJyID0gZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yIDogbmV3IEVycm9yKFN0cmluZyhlcnJvcikpO1xuICAgICAgaWYgKG9uRXJyb3IpIG9uRXJyb3IoZXJyKTtcbiAgICAgIHNwZWVjaFN0YXR1c0NhbGxiYWNrKGZhbHNlLCAnJyk7XG4gICAgfVxuICB9LCBbc3BlZWNoU3RhdHVzQ2FsbGJhY2ssIG9uRXJyb3JdKTtcblxuICAvKipcbiAgICogU3RvcCByZWNvcmRpbmcgYW5kIHByb2Nlc3MgYXVkaW8uXG4gICAqL1xuICBjb25zdCBzdG9wUmVjb3JkaW5nID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgIGNvbnN0IGVsYXBzZWQgPSBEYXRlLm5vdygpIC0gc3RhcnRUaW1lUmVmLmN1cnJlbnQ7XG4gICAgY29uc3QgbWluRHVyYXRpb24gPSAxMDAwOyAvLyBNaW5pbXVtIDEgc2Vjb25kIHJlY29yZGluZ1xuXG4gICAgaWYgKGVsYXBzZWQgPCBtaW5EdXJhdGlvbikge1xuICAgICAgLy8gU2NoZWR1bGUgc3RvcCBhZnRlciBtaW5pbXVtIGR1cmF0aW9uXG4gICAgICBjb25zdCBkZWxheSA9IG1pbkR1cmF0aW9uIC0gZWxhcHNlZDtcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICBpZiAobWVkaWFSZWNvcmRlclJlZi5jdXJyZW50ICYmIG1lZGlhUmVjb3JkZXJSZWYuY3VycmVudC5zdGF0ZSA9PT0gJ3JlY29yZGluZycpIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgLy8gRmx1c2ggYW55IHBlbmRpbmcgZGF0YVxuICAgICAgICAgICAgKG1lZGlhUmVjb3JkZXJSZWYuY3VycmVudCBhcyBhbnkpLnJlcXVlc3REYXRhPy4oKTtcbiAgICAgICAgICB9IGNhdGNoIChlKSB7fVxuICAgICAgICAgIG1lZGlhUmVjb3JkZXJSZWYuY3VycmVudC5zdG9wKCk7XG4gICAgICAgIH1cbiAgICAgIH0sIGRlbGF5KTtcbiAgICAgIGxvZ2dlci5kZWJ1ZyhgUmVjb3JkaW5nIHRvbyBzaG9ydCAoJHtlbGFwc2VkfW1zKSwgZGVsYXlpbmcgc3RvcCBieSAke2RlbGF5fW1zYCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIFN0b3AgaW1tZWRpYXRlbHkgaWYgbWluaW11bSBkdXJhdGlvbiBtZXRcbiAgICAgIGlmIChtZWRpYVJlY29yZGVyUmVmLmN1cnJlbnQgJiYgbWVkaWFSZWNvcmRlclJlZi5jdXJyZW50LnN0YXRlID09PSAncmVjb3JkaW5nJykge1xuICAgICAgICB0cnkgeyAobWVkaWFSZWNvcmRlclJlZi5jdXJyZW50IGFzIGFueSkucmVxdWVzdERhdGE/LigpOyB9IGNhdGNoIChlKSB7fVxuICAgICAgICBtZWRpYVJlY29yZGVyUmVmLmN1cnJlbnQuc3RvcCgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIE5vdGU6IHNldElzUmVjb3JkaW5nKGZhbHNlKSBtb3ZlZCB0byBvbnN0b3AgaGFuZGxlclxuICB9LCBbXSk7XG5cbiAgLyoqXG4gICAqIFByb2Nlc3MgY29sbGVjdGVkIGF1ZGlvIGNodW5rcyBhbmQgc2VuZCB0byBzZXJ2ZXIuXG4gICAqL1xuICBjb25zdCBwcm9jZXNzQXVkaW9DaHVua3MgPSB1c2VDYWxsYmFjayhhc3luYyAoKSA9PiB7XG4gICAgaWYgKGF1ZGlvQ2h1bmtzUmVmLmN1cnJlbnQubGVuZ3RoID09PSAwKSB7XG4gICAgICBsb2dnZXIud2FybignTm8gYXVkaW8gY2h1bmtzIHRvIHByb2Nlc3MnKTtcbiAgICAgIHNwZWVjaFN0YXR1c0NhbGxiYWNrKGZhbHNlLCAnJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gUHJldmVudCBkdXBsaWNhdGUgdXBsb2Fkc1xuICAgIGlmIChwcm9jZXNzaW5nUmVmLmN1cnJlbnQpIHtcbiAgICAgIGxvZ2dlci53YXJuKCdBbHJlYWR5IHByb2Nlc3NpbmcgYW4gdXR0ZXJhbmNlLCBza2lwcGluZyBkdXBsaWNhdGUgdXBsb2FkJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgcHJvY2Vzc2luZ1JlZi5jdXJyZW50ID0gdHJ1ZTtcbiAgICAvLyBHaXZlIGZlZWRiYWNrIHRvIFVJIHRoYXQgd2UgYXJlIHVwbG9hZGluZy90cmFuc2NyaWJpbmdcbiAgICB0cnkge1xuICAgICAgLy8gaW5kaWNhdGUgcmVtb3RlIHByb2Nlc3Npbmcgc3RhcnRlZCAobm8gZmFrZSBpbnRlcmltIHRleHQpXG4gICAgICBzcGVlY2hTdGF0dXNDYWxsYmFjayh0cnVlLCAnJyk7XG4gICAgICAvLyBDcmVhdGUgYXVkaW8gYmxvYlxuICAgICAgY29uc3QgbWltZVR5cGUgPSBnZXRTdXBwb3J0ZWRNaW1lVHlwZSgpO1xuICAgICAgY29uc3QgYXVkaW9CbG9iID0gbmV3IEJsb2IoYXVkaW9DaHVua3NSZWYuY3VycmVudCwgeyB0eXBlOiBtaW1lVHlwZSB9KTtcblxuICAgICAgbG9nZ2VyLmRlYnVnKGBBdWRpbyBibG9iIHNpemU6ICR7YXVkaW9CbG9iLnNpemV9IGJ5dGVzYCk7XG5cbiAgICAgIGlmIChhdWRpb0Jsb2Iuc2l6ZSA8IG1pbkF1ZGlvU2l6ZSkge1xuICAgICAgICBsb2dnZXIud2FybihgQXVkaW8gdG9vIHNob3J0ICgke2F1ZGlvQmxvYi5zaXplfSA8ICR7bWluQXVkaW9TaXplfSBieXRlcyksIHNraXBwaW5nYCk7XG4gICAgICAgIHNwZWVjaFN0YXR1c0NhbGxiYWNrKGZhbHNlLCAnJyk7XG4gICAgICAgIHNwZWVjaFJlc3VsdENhbGxiYWNrKCcnKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICAvLyBDcmVhdGUgZmlsZSBmb3IgdXBsb2FkXG4gICAgICBjb25zdCBleHRlbnNpb24gPSBnZXRGaWxlRXh0ZW5zaW9uKG1pbWVUeXBlKTtcbiAgICAgIGNvbnN0IGF1ZGlvRmlsZSA9IG5ldyBGaWxlKFthdWRpb0Jsb2JdLCBgYXVkaW8uJHtleHRlbnNpb259YCwgeyB0eXBlOiBtaW1lVHlwZSB9KTtcblxuICAgICAgLy8gVXNlIHNpbmdsZSBSRVNUIGVuZHBvaW50IGZvciBvbmVzaG90IGFuZCBTU0VcbiAgICAgIGNvbnN0IGVuZHBvaW50ID0gYCR7YmFzZVVybH0vdjEvYXVkaW8vdHJhbnNjcmlwdGlvbnNgO1xuXG4gICAgICAvLyBQcmVwYXJlIHJlcXVlc3RcbiAgICAgIGFib3J0Q29udHJvbGxlclJlZi5jdXJyZW50ID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuICAgICAgY29uc3QgZm9ybURhdGEgPSBuZXcgRm9ybURhdGEoKTtcbiAgICAgIGZvcm1EYXRhLmFwcGVuZCgnZmlsZScsIGF1ZGlvRmlsZSk7XG4gICAgICBmb3JtRGF0YS5hcHBlbmQoJ21vZGVsJywgbW9kZWxOYW1lKTtcbiAgICAgIGZvcm1EYXRhLmFwcGVuZCgncmVzcG9uc2VfZm9ybWF0JywgJ2pzb24nKTtcbiAgICAgIGlmIChsYW5ndWFnZSkgZm9ybURhdGEuYXBwZW5kKCdsYW5ndWFnZScsIGxhbmd1YWdlKTtcblxuICAgICAgaWYgKG1vZGUgPT09ICdvbmVzaG90Jykge1xuICAgICAgICBmb3JtRGF0YS5hcHBlbmQoJ3N0cmVhbScsICdmYWxzZScpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZm9ybURhdGEuYXBwZW5kKCdzdHJlYW0nLCAndHJ1ZScpO1xuICAgICAgfVxuXG4gICAgICBsb2dnZXIuaW5mbyhg8J+TpCBTZW5kaW5nICR7YXVkaW9CbG9iLnNpemV9IGJ5dGVzIHRvICR7ZW5kcG9pbnR9YCk7XG4gICAgICBsb2dnZXIuaW5mbyhg8J+Xo++4jyBNb2RlOiAke21vZGV9LCBNb2RlbDogJHttb2RlbE5hbWV9LCBlbmRwb2ludDogJHtlbmRwb2ludH1gKTtcblxuICAgICAgLy8gU2VuZCB0byBzZXJ2ZXJcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goZW5kcG9pbnQsIHtcbiAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICAgIGJvZHk6IGZvcm1EYXRhLFxuICAgICAgICBzaWduYWw6IGFib3J0Q29udHJvbGxlclJlZi5jdXJyZW50LnNpZ25hbCxcbiAgICAgIH0pO1xuXG4gICAgICBpZiAoIXJlc3BvbnNlLm9rKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgU2VydmVyIGVycm9yOiAke3Jlc3BvbnNlLnN0YXR1c31gKTtcbiAgICAgIH1cblxuICAgICAgLy8gSGFuZGxlIHJlc3BvbnNlXG4gICAgICBpZiAobW9kZSA9PT0gJ29uZXNob3QnKSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHJlc3BvbnNlLmpzb24oKTtcbiAgICAgICAgY29uc3QgdHJhbnNjcmlwdCA9IHJlc3VsdD8udGV4dD8udHJpbSgpIHx8ICcnO1xuICAgICAgICBsb2dnZXIuZGVidWcoJ1JlY2VpdmVkIHRyYW5zY3JpcHRpb24gcmVzcG9uc2U6JywgcmVzdWx0KTtcbiAgICAgICAgbG9nZ2VyLmRlYnVnKGBUcmFuc2NyaXB0aW9uIHRleHQ6IFwiJHt0cmFuc2NyaXB0fVwiYCk7XG4gICAgICAgIC8vIERlbGl2ZXIgdHJhbnNjcmlwdCBmaXJzdCwgdGhlbiBzaWduYWwgZW5kIHNvIE1vZGFsaXR5UHJvdmlkZXIgcHJvY2Vzc2VzIGl0IG9uY2VcbiAgICAgICAgbGFzdFNlbnRUcmFuc2NyaXB0UmVmLmN1cnJlbnQgPSB0cmFuc2NyaXB0O1xuICAgICAgICBzcGVlY2hSZXN1bHRDYWxsYmFjayh0cmFuc2NyaXB0KTtcbiAgICAgICAgc3BlZWNoU3RhdHVzQ2FsbGJhY2soZmFsc2UsICcnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIEhhbmRsZSBzdHJlYW1pbmcgcmVzcG9uc2UgKFNTRSlcbiAgICAgICAgYXdhaXQgaGFuZGxlU3RyZWFtaW5nUmVzcG9uc2UocmVzcG9uc2UpO1xuICAgICAgfVxuXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGxvZ2dlci5lcnJvcignVHJhbnNjcmlwdGlvbiBlcnJvcjonLCBlcnJvcik7XG4gICAgICBjb25zdCBlcnIgPSBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IgOiBuZXcgRXJyb3IoU3RyaW5nKGVycm9yKSk7XG4gICAgICBpZiAob25FcnJvcikgb25FcnJvcihlcnIpO1xuICAgICAgc3BlZWNoU3RhdHVzQ2FsbGJhY2soZmFsc2UsICcnKTtcbiAgICAgIHNwZWVjaFJlc3VsdENhbGxiYWNrKCcnKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgYXVkaW9DaHVua3NSZWYuY3VycmVudCA9IFtdO1xuICAgICAgaWYgKGFib3J0Q29udHJvbGxlclJlZi5jdXJyZW50KSB7XG4gICAgICAgIGFib3J0Q29udHJvbGxlclJlZi5jdXJyZW50ID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIHByb2Nlc3NpbmdSZWYuY3VycmVudCA9IGZhbHNlO1xuICAgIH1cbiAgfSwgW3NwZWVjaFN0YXR1c0NhbGxiYWNrLCBzcGVlY2hSZXN1bHRDYWxsYmFjaywgYmFzZVVybCwgbW9kZSwgbW9kZWxOYW1lLCBsYW5ndWFnZSwgbWluQXVkaW9TaXplLCBvbkVycm9yXSk7XG5cbiAgLyoqXG4gICAqIEhhbmRsZSBzdHJlYW1pbmcgdHJhbnNjcmlwdGlvbiByZXNwb25zZS5cbiAgICovXG4gIGNvbnN0IGhhbmRsZVN0cmVhbWluZ1Jlc3BvbnNlID0gdXNlQ2FsbGJhY2soYXN5bmMgKHJlc3BvbnNlOiBSZXNwb25zZSkgPT4ge1xuICAgIGNvbnN0IHJlYWRlciA9IHJlc3BvbnNlLmJvZHk/LmdldFJlYWRlcigpO1xuICAgIGlmICghcmVhZGVyKSB0aHJvdyBuZXcgRXJyb3IoJ05vIHJlc3BvbnNlIHJlYWRlcicpO1xuXG4gICAgY29uc3QgZGVjb2RlciA9IG5ldyBUZXh0RGVjb2RlcigpO1xuICAgIGxldCBidWZmZXIgPSAnJztcbiAgICBsZXQgbGFzdFRyYW5zY3JpcHQgPSAnJztcbiAgICBsZXQgc2F3RG9uZSA9IGZhbHNlO1xuXG4gICAgdHJ5IHtcbiAgICAgIGxldCBkb25lID0gZmFsc2U7XG4gICAgICB3aGlsZSAoIWRvbmUpIHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcmVhZGVyLnJlYWQoKTtcbiAgICAgICAgZG9uZSA9IHJlc3VsdC5kb25lO1xuXG4gICAgICAgIGlmIChkb25lKSBicmVhaztcblxuICAgICAgICBidWZmZXIgKz0gZGVjb2Rlci5kZWNvZGUocmVzdWx0LnZhbHVlLCB7IHN0cmVhbTogdHJ1ZSB9KTtcbiAgICAgICAgY29uc3QgbGluZXMgPSBidWZmZXIuc3BsaXQoJ1xcbicpO1xuICAgICAgICBidWZmZXIgPSBsaW5lcy5wb3AoKSB8fCAnJztcblxuICAgICAgICBmb3IgKGNvbnN0IGxpbmUgb2YgbGluZXMpIHtcbiAgICAgICAgICBpZiAobGluZS5zdGFydHNXaXRoKCdkYXRhOiAnKSkge1xuICAgICAgICAgICAgY29uc3QgZGF0YSA9IGxpbmUuc2xpY2UoNikudHJpbSgpO1xuICAgICAgICAgICAgaWYgKGRhdGEgPT09ICdbRE9ORV0nKSB7XG4gICAgICAgICAgICAgIHNhd0RvbmUgPSB0cnVlO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgY29uc3QgcGFyc2VkUmVzdWx0ID0gSlNPTi5wYXJzZShkYXRhKTtcbiAgICAgICAgICAgICAgY29uc3QgdHJhbnNjcmlwdCA9IHBhcnNlZFJlc3VsdD8udGV4dD8udHJpbSgpO1xuICAgICAgICAgICAgICBpZiAodHJhbnNjcmlwdCkge1xuICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGDwn5OdIFN0cmVhbWluZzogXCIke3RyYW5zY3JpcHR9XCJgKTtcbiAgICAgICAgICAgICAgICBsYXN0VHJhbnNjcmlwdCA9IHRyYW5zY3JpcHQ7XG4gICAgICAgICAgICAgICAgLy8gZGVsaXZlciBwYXJ0aWFsIHRvIFVJIGltbWVkaWF0ZWx5XG4gICAgICAgICAgICAgICAgc3BlZWNoUmVzdWx0Q2FsbGJhY2sodHJhbnNjcmlwdCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgLy8gSWdub3JlIHBhcnNlIGVycm9yc1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzYXdEb25lKSBicmVhaztcbiAgICAgIH1cbiAgICB9IGZpbmFsbHkge1xuICAgICAgLy8gU21hbGwgZGVsYXkgdG8gZW5zdXJlIFVJIGhhcyBhcHBsaWVkIGxhc3QgcGFydGlhbFxuICAgICAgdHJ5IHsgYXdhaXQgbmV3IFByb21pc2UoKHJlcykgPT4gc2V0VGltZW91dChyZXMsIDYwKSk7IH0gY2F0Y2ggKGUpIHt9XG5cbiAgICAgIGlmIChsYXN0VHJhbnNjcmlwdCkge1xuICAgICAgICBsb2dnZXIuZGVidWcoYEZpbmFsIHN0cmVhbWluZyB0cmFuc2NyaXB0IGJlZm9yZSBlbmQ6IFwiJHtsYXN0VHJhbnNjcmlwdH1cImApO1xuICAgICAgICB0cnkgeyBzcGVlY2hSZXN1bHRDYWxsYmFjayhsYXN0VHJhbnNjcmlwdCk7IH0gY2F0Y2ggKGUpIHt9XG4gICAgICB9XG5cbiAgICAgIC8vIFNpZ25hbCBzdHJlYW0gZW5kIHNvIE1vZGFsaXR5UHJvdmlkZXIgdHJpZ2dlcnMgdGhlIEdlbmllIGludGVycHJldGVyIG9uY2VcbiAgICAgIHRyeSB7IHNwZWVjaFN0YXR1c0NhbGxiYWNrKGZhbHNlLCAnJyk7IH0gY2F0Y2ggKGUpIHt9XG5cbiAgICAgIHJlYWRlci5yZWxlYXNlTG9jaygpO1xuICAgIH1cbiAgfSwgW3NwZWVjaFN0YXR1c0NhbGxiYWNrLCBzcGVlY2hSZXN1bHRDYWxsYmFja10pO1xuXG4gIC8qKlxuICAgKiBSZWFjdCB0byBzaG91bGRMaXN0ZW4gY2hhbmdlcy5cbiAgICovXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgbG9nZ2VyLmRlYnVnKGBzaG91bGRMaXN0ZW4gcHJvcCBjaGFuZ2VkOiAke3Nob3VsZExpc3Rlbn1gKTtcbiAgICAvLyBBdm9pZCBzdGFydGluZyBhIG5ldyByZWNvcmRpbmcgd2hpbGUgcHJldmlvdXMgdXR0ZXJhbmNlIGlzIHByb2Nlc3NpbmdcbiAgICBpZiAoc2hvdWxkTGlzdGVuICYmICFpc1JlY29yZGluZyAmJiAhcHJvY2Vzc2luZ1JlZi5jdXJyZW50KSB7XG4gICAgICBzdGFydFJlY29yZGluZygpO1xuICAgIH0gZWxzZSBpZiAoIXNob3VsZExpc3RlbiAmJiBpc1JlY29yZGluZykge1xuICAgICAgc3RvcFJlY29yZGluZygpO1xuICAgIH1cbiAgfSwgW3Nob3VsZExpc3RlbiwgaXNSZWNvcmRpbmcsIHN0YXJ0UmVjb3JkaW5nLCBzdG9wUmVjb3JkaW5nXSk7XG5cbiAgLyoqXG4gICAqIENsZWFudXAgb24gdW5tb3VudC5cbiAgICovXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgIGlmIChtZWRpYVJlY29yZGVyUmVmLmN1cnJlbnQgJiYgbWVkaWFSZWNvcmRlclJlZi5jdXJyZW50LnN0YXRlID09PSAncmVjb3JkaW5nJykge1xuICAgICAgICBtZWRpYVJlY29yZGVyUmVmLmN1cnJlbnQuc3RvcCgpO1xuICAgICAgfVxuICAgICAgaWYgKHN0cmVhbVJlZi5jdXJyZW50KSB7XG4gICAgICAgIHN0cmVhbVJlZi5jdXJyZW50LmdldFRyYWNrcygpLmZvckVhY2godHJhY2sgPT4gdHJhY2suc3RvcCgpKTtcbiAgICAgIH1cbiAgICAgIGlmIChhYm9ydENvbnRyb2xsZXJSZWYuY3VycmVudCkge1xuICAgICAgICBhYm9ydENvbnRyb2xsZXJSZWYuY3VycmVudC5hYm9ydCgpO1xuICAgICAgfVxuICAgIH07XG4gIH0sIFtdKTtcblxuICByZXR1cm4gPFZpZXcgLz47XG59O1xuXG4vKipcbiAqIEdldCBzdXBwb3J0ZWQgTUlNRSB0eXBlIGZvciBNZWRpYVJlY29yZGVyLlxuICovXG5mdW5jdGlvbiBnZXRTdXBwb3J0ZWRNaW1lVHlwZSgpOiBzdHJpbmcge1xuICBjb25zdCB0eXBlcyA9IFsnYXVkaW8vd2VibScsICdhdWRpby9tcDQnLCAnYXVkaW8vd2F2JywgJ2F1ZGlvL29nZyddO1xuXG4gIGZvciAoY29uc3QgdHlwZSBvZiB0eXBlcykge1xuICAgIGlmIChNZWRpYVJlY29yZGVyLmlzVHlwZVN1cHBvcnRlZCh0eXBlKSkge1xuICAgICAgcmV0dXJuIHR5cGU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuICdhdWRpby93ZWJtJztcbn1cblxuLyoqXG4gKiBHZXQgZmlsZSBleHRlbnNpb24gZm9yIE1JTUUgdHlwZS5cbiAqL1xuZnVuY3Rpb24gZ2V0RmlsZUV4dGVuc2lvbihtaW1lVHlwZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgaWYgKG1pbWVUeXBlLmluY2x1ZGVzKCd3ZWJtJykpIHJldHVybiAnd2VibSc7XG4gIGlmIChtaW1lVHlwZS5pbmNsdWRlcygnbXA0JykpIHJldHVybiAnbXA0JztcbiAgaWYgKG1pbWVUeXBlLmluY2x1ZGVzKCd3YXYnKSkgcmV0dXJuICd3YXYnO1xuICBpZiAobWltZVR5cGUuaW5jbHVkZXMoJ29nZycpKSByZXR1cm4gJ29nZyc7XG4gIHJldHVybiAnd2VibSc7XG59XG5cbmV4cG9ydCBkZWZhdWx0IE1MWFNwZWVjaFJlY29nbml6ZXI7XG4iXSwibWFwcGluZ3MiOiI7Ozs7OztBQUtBLElBQUFBLE1BQUEsR0FBQUMsdUJBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFDLFlBQUEsR0FBQUQsT0FBQTtBQUNBLElBQUFFLE9BQUEsR0FBQUMsc0JBQUEsQ0FBQUgsT0FBQTtBQUErQixTQUFBRyx1QkFBQUMsQ0FBQSxXQUFBQSxDQUFBLElBQUFBLENBQUEsQ0FBQUMsVUFBQSxHQUFBRCxDQUFBLEtBQUFFLE9BQUEsRUFBQUYsQ0FBQTtBQUFBLFNBQUFMLHdCQUFBSyxDQUFBLEVBQUFHLENBQUEsNkJBQUFDLE9BQUEsTUFBQUMsQ0FBQSxPQUFBRCxPQUFBLElBQUFFLENBQUEsT0FBQUYsT0FBQSxZQUFBVCx1QkFBQSxZQUFBQSxDQUFBSyxDQUFBLEVBQUFH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
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface NativeSpeechRecognizerProps {
|
|
3
|
+
shouldListen: boolean;
|
|
4
|
+
speechStatusCallback: (status: boolean, transcript: string) => void;
|
|
5
|
+
speechResultCallback: (result: string) => void;
|
|
6
|
+
speechTranslationCallback?: (translation: string) => void;
|
|
7
|
+
clientSecret: string;
|
|
8
|
+
groqApiBaseUrl?: string;
|
|
9
|
+
groqTranscriptionEndpoint?: string;
|
|
10
|
+
stream?: boolean;
|
|
11
|
+
language?: string;
|
|
12
|
+
onError?: (error: Error) => void;
|
|
13
|
+
minAudioSize?: number;
|
|
14
|
+
}
|
|
15
|
+
export declare const NativeSpeechRecognizer: React.FC<NativeSpeechRecognizerProps>;
|
|
16
|
+
export declare function isNativeSpeechAvailable(): boolean;
|
|
17
|
+
export declare function getNativeSpeechCapabilities(): {
|
|
18
|
+
available: boolean;
|
|
19
|
+
platform: "ios" | "android" | "windows" | "macos" | "web";
|
|
20
|
+
supportsVAD: boolean;
|
|
21
|
+
supportsAudioLevels: boolean;
|
|
22
|
+
requiresExpoAudio: boolean;
|
|
23
|
+
backend: string;
|
|
24
|
+
};
|