@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.
Files changed (85) hide show
  1. package/.env.example +22 -0
  2. package/.github/workflows/publish.yml +20 -0
  3. package/LICENSE.txt +201 -0
  4. package/README.md +621 -0
  5. package/babel.config.js +29 -0
  6. package/dist/adapters/__tests__/expo-router-adapter.test.d.ts +1 -0
  7. package/dist/adapters/expo-router-adapter.d.ts +16 -0
  8. package/dist/adapters/expo-router-adapter.js +521 -0
  9. package/dist/adapters/navigation-adapter.d.ts +20 -0
  10. package/dist/adapters/navigation-adapter.js +137 -0
  11. package/dist/audio-visualizer.d.ts +14 -0
  12. package/dist/audio-visualizer.js +123 -0
  13. package/dist/current-selection.d.ts +27 -0
  14. package/dist/current-selection.js +94 -0
  15. package/dist/errors.d.ts +19 -0
  16. package/dist/errors.js +37 -0
  17. package/dist/genie/DateTime.d.ts +66 -0
  18. package/dist/genie/DateTime.js +399 -0
  19. package/dist/genie/TimeDelta.d.ts +35 -0
  20. package/dist/genie/TimeDelta.js +169 -0
  21. package/dist/genie-view-wrapper.d.ts +1 -0
  22. package/dist/genie-view-wrapper.js +377 -0
  23. package/dist/hooks/__tests__/useSpeechRecognition.test.d.ts +1 -0
  24. package/dist/hooks/useSpeechRecognition.d.ts +28 -0
  25. package/dist/hooks/useSpeechRecognition.js +118 -0
  26. package/dist/index.d.ts +30 -0
  27. package/dist/index.js +469 -0
  28. package/dist/logger.d.ts +23 -0
  29. package/dist/logger.js +597 -0
  30. package/dist/logger.remote.test.d.ts +0 -0
  31. package/dist/modality-provider-v2.d.ts +28 -0
  32. package/dist/modality-provider-v2.js +1321 -0
  33. package/dist/modality-provider.d.ts +22 -0
  34. package/dist/modality-provider.js +373 -0
  35. package/dist/native-visibility.d.ts +28 -0
  36. package/dist/native-visibility.js +50 -0
  37. package/dist/platform/VoiceRecognitionBar.d.ts +17 -0
  38. package/dist/platform/VoiceRecognitionBar.js +332 -0
  39. package/dist/platform/components.d.ts +32 -0
  40. package/dist/platform/components.js +351 -0
  41. package/dist/platform/events.d.ts +31 -0
  42. package/dist/platform/events.js +274 -0
  43. package/dist/platform/index.d.ts +3 -0
  44. package/dist/platform/index.js +39 -0
  45. package/dist/platform/types.d.ts +79 -0
  46. package/dist/platform/types.js +97 -0
  47. package/dist/react-decorators.d.ts +87 -0
  48. package/dist/react-decorators.js +368 -0
  49. package/dist/shared-store.d.ts +74 -0
  50. package/dist/shared-store.js +589 -0
  51. package/dist/speech-recognition/__tests__/speech-recognition-groq-transport.test.d.ts +1 -0
  52. package/dist/speech-recognition/__tests__/speech-recognition-native.test.d.ts +1 -0
  53. package/dist/speech-recognition/__tests__/speech-recognition-openai-native.test.d.ts +1 -0
  54. package/dist/speech-recognition/__tests__/speech-recognition-openai.test.d.ts +1 -0
  55. package/dist/speech-recognition/__tests__/speech-recognition-unified-import.test.d.ts +0 -0
  56. package/dist/speech-recognition/__tests__/speech-recognition-unified.test.d.ts +1 -0
  57. package/dist/speech-recognition/speech-recognition-groq.d.ts +21 -0
  58. package/dist/speech-recognition/speech-recognition-groq.js +409 -0
  59. package/dist/speech-recognition/speech-recognition-mlx.d.ts +15 -0
  60. package/dist/speech-recognition/speech-recognition-mlx.js +393 -0
  61. package/dist/speech-recognition/speech-recognition-native.d.ts +24 -0
  62. package/dist/speech-recognition/speech-recognition-native.js +632 -0
  63. package/dist/speech-recognition/speech-recognition-openai-native.d.ts +40 -0
  64. package/dist/speech-recognition/speech-recognition-openai-native.js +653 -0
  65. package/dist/speech-recognition/speech-recognition-openai.d.ts +39 -0
  66. package/dist/speech-recognition/speech-recognition-openai.js +718 -0
  67. package/dist/speech-recognition/speech-recognition-unified.d.ts +93 -0
  68. package/dist/speech-recognition/speech-recognition-unified.js +589 -0
  69. package/dist/speech-recognition/utils/groq-transcription.d.ts +41 -0
  70. package/dist/speech-recognition/utils/groq-transcription.js +382 -0
  71. package/dist/speech-recognition.d.ts +7 -0
  72. package/dist/speech-recognition.js +61 -0
  73. package/dist/voice-pipeline-telemetry.d.ts +26 -0
  74. package/dist/voice-pipeline-telemetry.js +15 -0
  75. package/garrix82-reactgenie-lib-1.3.0.tgz +0 -0
  76. package/metro/index.js +3 -0
  77. package/metro/with-genie-registry.js +47 -0
  78. package/package.json +111 -0
  79. package/scripts/dry-run.js +23 -0
  80. package/scripts/generate-genie-registry.js +278 -0
  81. package/scripts/log-file-test.js +51 -0
  82. package/scripts/parse.js +26 -0
  83. package/scripts/prompt.js +19 -0
  84. package/scripts/set-script.js +200 -0
  85. 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
+ };