@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 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface GroqSpeechRecognizerProps {
|
|
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 GroqSpeechRecognizer: React.FC<GroqSpeechRecognizerProps>;
|
|
16
|
+
export declare function isGroqSpeechAvailable(): boolean;
|
|
17
|
+
export declare function getGroqSpeechCapabilities(): {
|
|
18
|
+
available: boolean;
|
|
19
|
+
supportedMimeTypes: string[];
|
|
20
|
+
platform: "ios" | "android" | "windows" | "macos" | "web";
|
|
21
|
+
};
|
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.GroqSpeechRecognizer = void 0;
|
|
7
|
+
exports.getGroqSpeechCapabilities = getGroqSpeechCapabilities;
|
|
8
|
+
exports.isGroqSpeechAvailable = isGroqSpeechAvailable;
|
|
9
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
10
|
+
var _reactNative = require("react-native");
|
|
11
|
+
var _logger = require("../logger");
|
|
12
|
+
var _groqTranscription = require("./utils/groq-transcription");
|
|
13
|
+
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); }
|
|
14
|
+
/**
|
|
15
|
+
* Groq-based Speech Recognition using Whisper API
|
|
16
|
+
* Provides real-time streaming transcription with interim results
|
|
17
|
+
* Streams audio chunks to Groq as they accumulate, displaying interim transcripts
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Groq-based speech recognizer using Whisper-large-v3 model
|
|
22
|
+
* Supports real-time streaming and batch transcription
|
|
23
|
+
*/
|
|
24
|
+
const GroqSpeechRecognizer = ({
|
|
25
|
+
shouldListen,
|
|
26
|
+
speechStatusCallback,
|
|
27
|
+
speechResultCallback,
|
|
28
|
+
speechTranslationCallback,
|
|
29
|
+
clientSecret,
|
|
30
|
+
groqApiBaseUrl,
|
|
31
|
+
groqTranscriptionEndpoint,
|
|
32
|
+
stream = true,
|
|
33
|
+
language = 'en',
|
|
34
|
+
onError,
|
|
35
|
+
minAudioSize = 1000
|
|
36
|
+
}) => {
|
|
37
|
+
const [isRecording, setIsRecording] = (0, _react.useState)(false);
|
|
38
|
+
const mediaRecorderRef = (0, _react.useRef)(null);
|
|
39
|
+
const audioChunksRef = (0, _react.useRef)([]);
|
|
40
|
+
const streamRef = (0, _react.useRef)(null);
|
|
41
|
+
const startTimeRef = (0, _react.useRef)(0);
|
|
42
|
+
const lastMimeTypeRef = (0, _react.useRef)('audio/webm');
|
|
43
|
+
|
|
44
|
+
// Real-time streaming state
|
|
45
|
+
const streamAbortRef = (0, _react.useRef)(null);
|
|
46
|
+
const transcriptionStateRef = (0, _react.useRef)({
|
|
47
|
+
isStreaming: false,
|
|
48
|
+
lastSendTime: 0,
|
|
49
|
+
lastInterim: ''
|
|
50
|
+
});
|
|
51
|
+
const finalTranscriptRef = (0, _react.useRef)('');
|
|
52
|
+
const MIN_CHUNK_SIZE = 500; // bytes (before first send)
|
|
53
|
+
const SEND_INTERVAL = 1000; // ms (debounce interval)
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Start audio recording (matching MLX approach)
|
|
57
|
+
*/
|
|
58
|
+
const startRecording = (0, _react.useCallback)(async () => {
|
|
59
|
+
try {
|
|
60
|
+
_logger.logger.debug('Starting Groq recording...');
|
|
61
|
+
|
|
62
|
+
// Browser-specific audio constraints
|
|
63
|
+
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
|
64
|
+
_logger.logger.debug(`Browser detection: Safari = ${isSafari}`);
|
|
65
|
+
const stream = await navigator.mediaDevices.getUserMedia({
|
|
66
|
+
audio: isSafari ? {
|
|
67
|
+
// Safari prefers simpler constraints
|
|
68
|
+
echoCancellation: false,
|
|
69
|
+
noiseSuppression: false,
|
|
70
|
+
autoGainControl: false
|
|
71
|
+
} : {
|
|
72
|
+
echoCancellation: true,
|
|
73
|
+
noiseSuppression: true,
|
|
74
|
+
autoGainControl: true,
|
|
75
|
+
sampleRate: 16000
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
_logger.logger.debug(`Audio stream tracks: ${stream.getAudioTracks().length}`);
|
|
79
|
+
stream.getAudioTracks().forEach((track, index) => {
|
|
80
|
+
_logger.logger.debug(`Track ${index}: ${track.label}, enabled: ${track.enabled}, readyState: ${track.readyState}`);
|
|
81
|
+
});
|
|
82
|
+
streamRef.current = stream;
|
|
83
|
+
audioChunksRef.current = [];
|
|
84
|
+
finalTranscriptRef.current = '';
|
|
85
|
+
|
|
86
|
+
// Create MediaRecorder with supported format
|
|
87
|
+
const mimeType = getSupportedMimeType();
|
|
88
|
+
_logger.logger.debug(`Using MIME type: ${mimeType}`);
|
|
89
|
+
lastMimeTypeRef.current = mimeType;
|
|
90
|
+
|
|
91
|
+
// Try creating MediaRecorder with minimal options first
|
|
92
|
+
let mediaRecorder;
|
|
93
|
+
try {
|
|
94
|
+
mediaRecorder = new MediaRecorder(stream, {
|
|
95
|
+
mimeType
|
|
96
|
+
});
|
|
97
|
+
_logger.logger.debug('MediaRecorder created with minimal options');
|
|
98
|
+
} catch (error) {
|
|
99
|
+
_logger.logger.warn('MediaRecorder constructor failed with minimal options, trying fallback:', error);
|
|
100
|
+
// Fallback without mimeType
|
|
101
|
+
mediaRecorder = new MediaRecorder(stream);
|
|
102
|
+
_logger.logger.debug('MediaRecorder created with fallback options');
|
|
103
|
+
}
|
|
104
|
+
mediaRecorderRef.current = mediaRecorder;
|
|
105
|
+
|
|
106
|
+
// Handle audio data - trigger streaming checks
|
|
107
|
+
mediaRecorder.ondataavailable = event => {
|
|
108
|
+
if (event.data.size > 0) {
|
|
109
|
+
audioChunksRef.current.push(event.data);
|
|
110
|
+
_logger.logger.debug(`Audio chunk: ${event.data.size} bytes (total: ${audioChunksRef.current.length} chunks)`);
|
|
111
|
+
// Check if we should stream
|
|
112
|
+
checkAndStreamAudio();
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// Handle start
|
|
117
|
+
mediaRecorder.onstart = () => {
|
|
118
|
+
_logger.logger.debug('MediaRecorder started, state:', mediaRecorder.state);
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
// Handle recording stop
|
|
122
|
+
mediaRecorder.onstop = async () => {
|
|
123
|
+
_logger.logger.debug('Recording stopped, cleaning up stream...');
|
|
124
|
+
setIsRecording(false);
|
|
125
|
+
|
|
126
|
+
// Cancel active stream
|
|
127
|
+
if (streamAbortRef.current) {
|
|
128
|
+
streamAbortRef.current.abort();
|
|
129
|
+
streamAbortRef.current = null;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Clean up stream (close mic immediately)
|
|
133
|
+
if (streamRef.current) {
|
|
134
|
+
streamRef.current.getTracks().forEach(track => track.stop());
|
|
135
|
+
streamRef.current = null;
|
|
136
|
+
}
|
|
137
|
+
_logger.logger.info('🛑 Groq recording stopped');
|
|
138
|
+
const finalTranscript = (finalTranscriptRef.current || transcriptionStateRef.current.lastInterim || '').trim();
|
|
139
|
+
let parseTranscript = finalTranscript;
|
|
140
|
+
try {
|
|
141
|
+
if (audioChunksRef.current.length > 0 && language && !language.startsWith('en')) {
|
|
142
|
+
const mimeType = lastMimeTypeRef.current || getSupportedMimeType();
|
|
143
|
+
const audioBlob = new Blob(audioChunksRef.current, {
|
|
144
|
+
type: mimeType
|
|
145
|
+
});
|
|
146
|
+
if (audioBlob.size > 0) {
|
|
147
|
+
const translated = await (0, _groqTranscription.translateGroqAudio)({
|
|
148
|
+
apiKey: clientSecret,
|
|
149
|
+
audioBlob,
|
|
150
|
+
mimeType,
|
|
151
|
+
language,
|
|
152
|
+
endpoint: resolveGroqTranslationEndpoint(groqApiBaseUrl, groqTranscriptionEndpoint)
|
|
153
|
+
});
|
|
154
|
+
if (translated) {
|
|
155
|
+
if (speechTranslationCallback) {
|
|
156
|
+
speechTranslationCallback(translated);
|
|
157
|
+
}
|
|
158
|
+
parseTranscript = translated;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
} catch (error) {
|
|
163
|
+
_logger.logger.warn('Groq translation failed:', error);
|
|
164
|
+
} finally {
|
|
165
|
+
audioChunksRef.current = [];
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Stream will naturally end, just signal end of recording
|
|
169
|
+
speechStatusCallback(false, '');
|
|
170
|
+
if (parseTranscript) {
|
|
171
|
+
speechResultCallback(parseTranscript);
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
// Handle errors
|
|
176
|
+
mediaRecorder.onerror = event => {
|
|
177
|
+
_logger.logger.error('MediaRecorder error:', event);
|
|
178
|
+
setIsRecording(false);
|
|
179
|
+
const error = new Error('Recording failed');
|
|
180
|
+
if (onError) onError(error);
|
|
181
|
+
speechStatusCallback(false, '');
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
// Start recording with 100ms timeslice (matching MLX)
|
|
185
|
+
mediaRecorder.start(100);
|
|
186
|
+
_logger.logger.debug('MediaRecorder.start(100) called');
|
|
187
|
+
startTimeRef.current = Date.now();
|
|
188
|
+
setIsRecording(true);
|
|
189
|
+
// Don't send empty interim on start - wait for actual transcripts
|
|
190
|
+
// speechStatusCallback(true, '');
|
|
191
|
+
_logger.logger.info('🎤 Groq recording started');
|
|
192
|
+
} catch (error) {
|
|
193
|
+
_logger.logger.error('Failed to start recording:', error);
|
|
194
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
195
|
+
if (onError) onError(err);
|
|
196
|
+
speechStatusCallback(false, '');
|
|
197
|
+
}
|
|
198
|
+
}, [speechStatusCallback, speechResultCallback, speechTranslationCallback, clientSecret, groqApiBaseUrl, groqTranscriptionEndpoint, language, onError]);
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Stop audio recording
|
|
202
|
+
*/
|
|
203
|
+
const stopRecording = (0, _react.useCallback)(() => {
|
|
204
|
+
_logger.logger.debug('Stop recording called');
|
|
205
|
+
|
|
206
|
+
// Stop all audio tracks immediately
|
|
207
|
+
if (streamRef.current) {
|
|
208
|
+
streamRef.current.getTracks().forEach(track => {
|
|
209
|
+
track.stop();
|
|
210
|
+
});
|
|
211
|
+
streamRef.current = null;
|
|
212
|
+
}
|
|
213
|
+
if (mediaRecorderRef.current && mediaRecorderRef.current.state === 'recording') {
|
|
214
|
+
mediaRecorderRef.current.stop();
|
|
215
|
+
}
|
|
216
|
+
}, []);
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Stream audio to Groq and handle SSE responses
|
|
220
|
+
* Sends accumulated chunks and streams interim transcripts
|
|
221
|
+
*/
|
|
222
|
+
const streamAudio = (0, _react.useCallback)(async audioBlob => {
|
|
223
|
+
if (transcriptionStateRef.current.isStreaming) {
|
|
224
|
+
_logger.logger.warn('Already streaming, skipping');
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
transcriptionStateRef.current.isStreaming = true;
|
|
228
|
+
transcriptionStateRef.current.lastSendTime = Date.now();
|
|
229
|
+
try {
|
|
230
|
+
const mimeType = getSupportedMimeType();
|
|
231
|
+
_logger.logger.info(`📤 Streaming ${audioBlob.size} bytes to Groq (interim mode)...`);
|
|
232
|
+
streamAbortRef.current = new AbortController();
|
|
233
|
+
const state = transcriptionStateRef.current;
|
|
234
|
+
await (0, _groqTranscription.streamGroqTranscription)({
|
|
235
|
+
apiKey: clientSecret,
|
|
236
|
+
audioBlob,
|
|
237
|
+
mimeType,
|
|
238
|
+
language,
|
|
239
|
+
responseFormat: 'verbose_json',
|
|
240
|
+
stream,
|
|
241
|
+
endpoint: resolveGroqTranscriptionEndpoint(groqApiBaseUrl, groqTranscriptionEndpoint),
|
|
242
|
+
signal: streamAbortRef.current.signal,
|
|
243
|
+
onInterim: interimText => {
|
|
244
|
+
if (!interimText || interimText === state.lastInterim) return;
|
|
245
|
+
state.lastInterim = interimText;
|
|
246
|
+
finalTranscriptRef.current = interimText;
|
|
247
|
+
_logger.logger.info(`📝 Interim: "${interimText}"`);
|
|
248
|
+
speechStatusCallback(true, interimText);
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
} catch (error) {
|
|
252
|
+
if (error instanceof Error && error.name !== 'AbortError') {
|
|
253
|
+
_logger.logger.error('❌ Stream error:', error);
|
|
254
|
+
if (onError) onError(error);
|
|
255
|
+
}
|
|
256
|
+
} finally {
|
|
257
|
+
transcriptionStateRef.current.isStreaming = false;
|
|
258
|
+
}
|
|
259
|
+
}, [clientSecret, groqApiBaseUrl, groqTranscriptionEndpoint, language, onError, stream]);
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Check if audio threshold met and stream to Groq
|
|
263
|
+
* Implements debounced streaming with minimum chunk size
|
|
264
|
+
*/
|
|
265
|
+
const checkAndStreamAudio = (0, _react.useCallback)(() => {
|
|
266
|
+
const mimeType = getSupportedMimeType();
|
|
267
|
+
const audioBlob = new Blob(audioChunksRef.current, {
|
|
268
|
+
type: mimeType
|
|
269
|
+
});
|
|
270
|
+
const now = Date.now();
|
|
271
|
+
const state = transcriptionStateRef.current;
|
|
272
|
+
|
|
273
|
+
// Check: minimum chunk size reached?
|
|
274
|
+
if (audioBlob.size < MIN_CHUNK_SIZE) {
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Check: already streaming?
|
|
279
|
+
if (state.isStreaming) {
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Check: debounce interval respected?
|
|
284
|
+
if (now - state.lastSendTime < SEND_INTERVAL) {
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// All checks passed - start streaming
|
|
289
|
+
streamAudio(audioBlob);
|
|
290
|
+
}, [streamAudio]);
|
|
291
|
+
|
|
292
|
+
// SSE handling moved to shared helper (groq-transcription.ts)
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Process collected audio chunks and send to Groq for transcription (matching MLX)
|
|
296
|
+
* CRITICAL: Guard with processingRef to prevent duplicate uploads
|
|
297
|
+
*/
|
|
298
|
+
const processAudioChunks = (0, _react.useCallback)(async () => {
|
|
299
|
+
if (audioChunksRef.current.length === 0) {
|
|
300
|
+
_logger.logger.warn('No audio chunks to process');
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// In streaming mode, audio already processed via stream
|
|
305
|
+
_logger.logger.info('✅ Streaming completed');
|
|
306
|
+
audioChunksRef.current = [];
|
|
307
|
+
}, []);
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Handle shouldListen prop changes
|
|
311
|
+
*/
|
|
312
|
+
(0, _react.useEffect)(() => {
|
|
313
|
+
_logger.logger.debug(`shouldListen changed: ${shouldListen}, isRecording: ${isRecording}`);
|
|
314
|
+
if (shouldListen && !isRecording) {
|
|
315
|
+
_logger.logger.debug('✅ Starting recording');
|
|
316
|
+
startRecording();
|
|
317
|
+
} else if (!shouldListen && isRecording) {
|
|
318
|
+
_logger.logger.debug('❌ Stopping recording');
|
|
319
|
+
stopRecording();
|
|
320
|
+
}
|
|
321
|
+
}, [shouldListen, isRecording, startRecording, stopRecording]);
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Cleanup on unmount
|
|
325
|
+
*/
|
|
326
|
+
(0, _react.useEffect)(() => {
|
|
327
|
+
return () => {
|
|
328
|
+
if (streamAbortRef.current) {
|
|
329
|
+
streamAbortRef.current.abort();
|
|
330
|
+
}
|
|
331
|
+
if (mediaRecorderRef.current && mediaRecorderRef.current.state === 'recording') {
|
|
332
|
+
mediaRecorderRef.current.stop();
|
|
333
|
+
}
|
|
334
|
+
if (streamRef.current) {
|
|
335
|
+
streamRef.current.getTracks().forEach(track => track.stop());
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
}, []);
|
|
339
|
+
return /*#__PURE__*/_react.default.createElement(_reactNative.View, null);
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Get supported MIME type for MediaRecorder
|
|
344
|
+
*/
|
|
345
|
+
exports.GroqSpeechRecognizer = GroqSpeechRecognizer;
|
|
346
|
+
function getSupportedMimeType() {
|
|
347
|
+
const types = ['audio/webm;codecs=opus', 'audio/webm', 'audio/ogg;codecs=opus', 'audio/mp4', 'audio/wav'];
|
|
348
|
+
for (const type of types) {
|
|
349
|
+
if (MediaRecorder.isTypeSupported(type)) {
|
|
350
|
+
return type;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// Fallback
|
|
355
|
+
return 'audio/webm';
|
|
356
|
+
}
|
|
357
|
+
function resolveGroqTranscriptionEndpoint(baseUrl, overrideEndpoint) {
|
|
358
|
+
if (overrideEndpoint) return overrideEndpoint;
|
|
359
|
+
if (!baseUrl) return undefined;
|
|
360
|
+
const trimmed = baseUrl.replace(/\/+$/, '');
|
|
361
|
+
if (trimmed.endsWith('/openai/v1')) {
|
|
362
|
+
return `${trimmed}/audio/transcriptions`;
|
|
363
|
+
}
|
|
364
|
+
return `${trimmed}/openai/v1/audio/transcriptions`;
|
|
365
|
+
}
|
|
366
|
+
function resolveGroqTranslationEndpoint(baseUrl, overrideEndpoint) {
|
|
367
|
+
if (overrideEndpoint) {
|
|
368
|
+
return overrideEndpoint.includes('/audio/transcriptions') ? overrideEndpoint.replace('/audio/transcriptions', '/audio/translations') : overrideEndpoint;
|
|
369
|
+
}
|
|
370
|
+
if (!baseUrl) return undefined;
|
|
371
|
+
const trimmed = baseUrl.replace(/\/+$/, '');
|
|
372
|
+
if (trimmed.endsWith('/openai/v1')) {
|
|
373
|
+
return `${trimmed}/audio/translations`;
|
|
374
|
+
}
|
|
375
|
+
return `${trimmed}/openai/v1/audio/translations`;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Get file extension from MIME type
|
|
380
|
+
*/
|
|
381
|
+
/**
|
|
382
|
+
* Check if Groq speech recognition is available
|
|
383
|
+
*/
|
|
384
|
+
function isGroqSpeechAvailable() {
|
|
385
|
+
// Check if running in browser
|
|
386
|
+
if (typeof window === 'undefined') {
|
|
387
|
+
return false;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// Check for required APIs
|
|
391
|
+
const hasMediaDevices = navigator?.mediaDevices?.getUserMedia !== undefined;
|
|
392
|
+
const hasMediaRecorder = typeof MediaRecorder !== 'undefined';
|
|
393
|
+
return hasMediaDevices && hasMediaRecorder;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Get browser capabilities for Groq speech
|
|
398
|
+
*/
|
|
399
|
+
function getGroqSpeechCapabilities() {
|
|
400
|
+
return {
|
|
401
|
+
available: isGroqSpeechAvailable(),
|
|
402
|
+
supportedMimeTypes: ['audio/webm;codecs=opus', 'audio/webm', 'audio/ogg;codecs=opus', 'audio/mp4', 'audio/wav'].filter(type => {
|
|
403
|
+
if (typeof MediaRecorder === 'undefined') return false;
|
|
404
|
+
return MediaRecorder.isTypeSupported(type);
|
|
405
|
+
}),
|
|
406
|
+
platform: _reactNative.Platform.OS
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZCIsInJlcXVpcmUiLCJfcmVhY3ROYXRpdmUiLCJfbG9nZ2VyIiwiX2dyb3FUcmFuc2NyaXB0aW9uIiwiZSIsInQiLCJXZWFrTWFwIiwiciIsIm4iLCJfX2VzTW9kdWxlIiwibyIsImkiLCJmIiwiX19wcm90b19fIiwiZGVmYXVsdCIsImhhcyIsImdldCIsInNldCIsImhhc093blByb3BlcnR5IiwiY2FsbCIsIk9iamVjdCIsImRlZmluZVByb3BlcnR5IiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yIiwiR3JvcVNwZWVjaFJlY29nbml6ZXIiLCJzaG91bGRMaXN0ZW4iLCJzcGVlY2hTdGF0dXNDYWxsYmFjayIsInNwZWVjaFJlc3VsdENhbGxiYWNrIiwic3BlZWNoVHJhbnNsYXRpb25DYWxsYmFjayIsImNsaWVudFNlY3JldCIsImdyb3FBcGlCYXNlVXJsIiwiZ3JvcVRyYW5zY3JpcHRpb25FbmRwb2ludCIsInN0cmVhbSIsImxhbmd1YWdlIiwib25FcnJvciIsIm1pbkF1ZGlvU2l6ZSIsImlzUmVjb3JkaW5nIiwic2V0SXNSZWNvcmRpbmciLCJ1c2VTdGF0ZSIsIm1lZGlhUmVjb3JkZXJSZWYiLCJ1c2VSZWYiLCJhdWRpb0NodW5rc1JlZiIsInN0cmVhbVJlZiIsInN0YXJ0VGltZVJlZiIsImxhc3RNaW1lVHlwZVJlZiIsInN0cmVhbUFib3J0UmVmIiwidHJhbnNjcmlwdGlvblN0YXRlUmVmIiwiaXNTdHJlYW1pbmciLCJsYXN0U2VuZFRpbWUiLCJsYXN0SW50ZXJpbSIsImZpbmFsVHJhbnNjcmlwdFJlZiIsIk1JTl9DSFVOS19TSVpFIiwiU0VORF9JTlRFUlZBTCIsInN0YXJ0UmVjb3JkaW5nIiwidXNlQ2FsbGJhY2siLCJsb2dnZXIiLCJkZWJ1ZyIsImlzU2FmYXJpIiwidGVzdCIsIm5hdmlnYXRvciIsInVzZXJBZ2VudCIsIm1lZGlhRGV2aWNlcyIsImdldFVzZXJNZWRpYSIsImF1ZGlvIiwiZWNob0NhbmNlbGxhdGlvbiIsIm5vaXNlU3VwcHJlc3Npb24iLCJhdXRvR2FpbkNvbnRyb2wiLCJzYW1wbGVSYXRlIiwiZ2V0QXVkaW9UcmFja3MiLCJsZW5ndGgiLCJmb3JFYWNoIiwidHJhY2siLCJpbmRleCIsImxhYmVsIiwiZW5hYmxlZCIsInJlYWR5U3RhdGUiLCJjdXJyZW50IiwibWltZVR5cGUiLCJnZXRTdXBwb3J0ZWRNaW1lVHlwZSIsIm1lZGlhUmVjb3JkZXIiLCJNZWRpYVJlY29yZGVyIiwiZXJyb3IiLCJ3YXJuIiwib25kYXRhYXZhaWxhYmxlIiwiZXZlbnQiLCJkYXRhIiwic2l6ZSIsInB1c2giLCJjaGVja0FuZFN0cmVhbUF1ZGlvIiwib25zdGFydCIsInN0YXRlIiwib25zdG9wIiwiYWJvcnQiLCJnZXRUcmFja3MiLCJzdG9wIiwiaW5mbyIsImZpbmFsVHJhbnNjcmlwdCIsInRyaW0iLCJwYXJzZVRyYW5zY3JpcHQiLCJzdGFydHNXaXRoIiwiYXVkaW9CbG9iIiwiQmxvYiIsInR5cGUiLCJ0cmFuc2xhdGVkIiwidHJhbnNsYXRlR3JvcUF1ZGlvIiwiYXBpS2V5IiwiZW5kcG9pbnQiLCJyZXNvbHZlR3JvcVRyYW5zbGF0aW9uRW5kcG9pbnQiLCJvbmVycm9yIiwiRXJyb3IiLCJzdGFydCIsIkRhdGUiLCJub3ciLCJlcnIiLCJTdHJpbmciLCJzdG9wUmVjb3JkaW5nIiwic3RyZWFtQXVkaW8iLCJBYm9ydENvbnRyb2xsZXIiLCJzdHJlYW1Hcm9xVHJhbnNjcmlwdGlvbiIsInJlc3BvbnNlRm9ybWF0IiwicmVzb2x2ZUdyb3FUcmFuc2NyaXB0aW9uRW5kcG9pbnQiLCJzaWduYWwiLCJvbkludGVyaW0iLCJpbnRlcmltVGV4dCIsIm5hbWUiLCJwcm9jZXNzQXVkaW9DaHVua3MiLCJ1c2VFZmZlY3QiLCJjcmVhdGVFbGVtZW50IiwiVmlldyIsImV4cG9ydHMiLCJ0eXBlcyIsImlzVHlwZVN1cHBvcnRlZCIsImJhc2VVcmwiLCJvdmVycmlkZUVuZHBvaW50IiwidW5kZWZpbmVkIiwidHJpbW1lZCIsInJlcGxhY2UiLCJlbmRzV2l0aCIsImluY2x1ZGVzIiwiaXNHcm9xU3BlZWNoQXZhaWxhYmxlIiwid2luZG93IiwiaGFzTWVkaWFEZXZpY2VzIiwiaGFzTWVkaWFSZWNvcmRlciIsImdldEdyb3FTcGVlY2hDYXBhYmlsaXRpZXMiLCJhdmFpbGFibGUiLCJzdXBwb3J0ZWRNaW1lVHlwZXMiLCJmaWx0ZXIiLCJwbGF0Zm9ybSIsIlBsYXRmb3JtIiwiT1MiXSwic291cmNlcyI6WyIuLi8uLi9zcmMvc3BlZWNoLXJlY29nbml0aW9uL3NwZWVjaC1yZWNvZ25pdGlvbi1ncm9xLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEdyb3EtYmFzZWQgU3BlZWNoIFJlY29nbml0aW9uIHVzaW5nIFdoaXNwZXIgQVBJXG4gKiBQcm92aWRlcyByZWFsLXRpbWUgc3RyZWFtaW5nIHRyYW5zY3JpcHRpb24gd2l0aCBpbnRlcmltIHJlc3VsdHNcbiAqIFN0cmVhbXMgYXVkaW8gY2h1bmtzIHRvIEdyb3EgYXMgdGhleSBhY2N1bXVsYXRlLCBkaXNwbGF5aW5nIGludGVyaW0gdHJhbnNjcmlwdHNcbiAqL1xuXG5pbXBvcnQgUmVhY3QsIHsgdXNlRWZmZWN0LCB1c2VTdGF0ZSwgdXNlUmVmLCB1c2VDYWxsYmFjayB9IGZyb20gJ3JlYWN0JztcbmltcG9ydCB7IFZpZXcsIFBsYXRmb3JtIH0gZnJvbSAncmVhY3QtbmF0aXZlJztcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gJy4uL2xvZ2dlcic7XG5pbXBvcnQgeyBzdHJlYW1Hcm9xVHJhbnNjcmlwdGlvbiwgdHJhbnNsYXRlR3JvcUF1ZGlvIH0gZnJvbSAnLi91dGlscy9ncm9xLXRyYW5zY3JpcHRpb24nO1xuXG5leHBvcnQgaW50ZXJmYWNlIEdyb3FTcGVlY2hSZWNvZ25pemVyUHJvcHMge1xuICBzaG91bGRMaXN0ZW46IGJvb2xlYW47XG4gIHNwZWVjaFN0YXR1c0NhbGxiYWNrOiAoc3RhdHVzOiBib29sZWFuLCB0cmFuc2NyaXB0OiBzdHJpbmcpID0+IHZvaWQ7XG4gIHNwZWVjaFJlc3VsdENhbGxiYWNrOiAocmVzdWx0OiBzdHJpbmcpID0+IHZvaWQ7XG4gIHNwZWVjaFRyYW5zbGF0aW9uQ2FsbGJhY2s/OiAodHJhbnNsYXRpb246IHN0cmluZykgPT4gdm9pZDtcbiAgY2xpZW50U2VjcmV0OiBzdHJpbmc7XG4gIGdyb3FBcGlCYXNlVXJsPzogc3RyaW5nO1xuICBncm9xVHJhbnNjcmlwdGlvbkVuZHBvaW50Pzogc3RyaW5nO1xuICBzdHJlYW0/OiBib29sZWFuO1xuICBsYW5ndWFnZT86IHN0cmluZztcbiAgb25FcnJvcj86IChlcnJvcjogRXJyb3IpID0+IHZvaWQ7XG4gIG1pbkF1ZGlvU2l6ZT86IG51bWJlcjsgLy8gTWluaW11bSBhdWRpbyBzaXplIGluIGJ5dGVzIChkZWZhdWx0IDEwMDApXG59XG5cbi8qKlxuICogR3JvcS1iYXNlZCBzcGVlY2ggcmVjb2duaXplciB1c2luZyBXaGlzcGVyLWxhcmdlLXYzIG1vZGVsXG4gKiBTdXBwb3J0cyByZWFsLXRpbWUgc3RyZWFtaW5nIGFuZCBiYXRjaCB0cmFuc2NyaXB0aW9uXG4gKi9cbmV4cG9ydCBjb25zdCBHcm9xU3BlZWNoUmVjb2duaXplcjogUmVhY3QuRkM8R3JvcVNwZWVjaFJlY29nbml6ZXJQcm9wcz4gPSAoe1xuICBzaG91bGRMaXN0ZW4sXG4gIHNwZWVjaFN0YXR1c0NhbGxiYWNrLFxuICBzcGVlY2hSZXN1bHRDYWxsYmFjayxcbiAgc3BlZWNoVHJhbnNsYXRpb25DYWxsYmFjayxcbiAgY2xpZW50U2VjcmV0LFxuICBncm9xQXBpQmFzZVVybCxcbiAgZ3JvcVRyYW5zY3JpcHRpb25FbmRwb2ludCxcbiAgc3RyZWFtID0gdHJ1ZSxcbiAgbGFuZ3VhZ2UgPSAnZW4nLFxuICBvbkVycm9yLFxuICBtaW5BdWRpb1NpemUgPSAxMDAwLFxufSkgPT4ge1xuICBjb25zdCBbaXNSZWNvcmRpbmcsIHNldElzUmVjb3JkaW5nXSA9IHVzZVN0YXRlKGZhbHNlKTtcbiAgY29uc3QgbWVkaWFSZWNvcmRlclJlZiA9IHVzZVJlZjxNZWRpYVJlY29yZGVyIHwgbnVsbD4obnVsbCk7XG4gIGNvbnN0IGF1ZGlvQ2h1bmtzUmVmID0gdXNlUmVmPEJsb2JbXT4oW10pO1xuICBjb25zdCBzdHJlYW1SZWYgPSB1c2VSZWY8TWVkaWFTdHJlYW0gfCBudWxsPihudWxsKTtcbiAgY29uc3Qgc3RhcnRUaW1lUmVmID0gdXNlUmVmPG51bWJlcj4oMCk7XG4gIGNvbnN0IGxhc3RNaW1lVHlwZVJlZiA9IHVzZVJlZjxzdHJpbmc+KCdhdWRpby93ZWJtJyk7XG4gIFxuICAvLyBSZWFsLXRpbWUgc3RyZWFtaW5nIHN0YXRlXG4gIGNvbnN0IHN0cmVhbUFib3J0UmVmID0gdXNlUmVmPEFib3J0Q29udHJvbGxlciB8IG51bGw+KG51bGwpO1xuICBjb25zdCB0cmFuc2NyaXB0aW9uU3RhdGVSZWYgPSB1c2VSZWYoe1xuICAgIGlzU3RyZWFtaW5nOiBmYWxzZSxcbiAgICBsYXN0U2VuZFRpbWU6IDAsXG4gICAgbGFzdEludGVyaW06ICcnLFxuICB9KTtcbiAgY29uc3QgZmluYWxUcmFuc2NyaXB0UmVmID0gdXNlUmVmPHN0cmluZz4oJycpO1xuICBjb25zdCBNSU5fQ0hVTktfU0laRSA9IDUwMDsgLy8gYnl0ZXMgKGJlZm9yZSBmaXJzdCBzZW5kKVxuICBjb25zdCBTRU5EX0lOVEVSVkFMID0gMTAwMDsgLy8gbXMgKGRlYm91bmNlIGludGVydmFsKVxuXG4gIC8qKlxuICAgKiBTdGFydCBhdWRpbyByZWNvcmRpbmcgKG1hdGNoaW5nIE1MWCBhcHByb2FjaClcbiAgICovXG4gIGNvbnN0IHN0YXJ0UmVjb3JkaW5nID0gdXNlQ2FsbGJhY2soYXN5bmMgKCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBsb2dnZXIuZGVidWcoJ1N0YXJ0aW5nIEdyb3EgcmVjb3JkaW5nLi4uJyk7XG5cbiAgICAgIC8vIEJyb3dzZXItc3BlY2lmaWMgYXVkaW8gY29uc3RyYWludHNcbiAgICAgIGNvbnN0IGlzU2FmYXJpID0gL14oKD8hY2hyb21lfGFuZHJvaWQpLikqc2FmYXJpL2kudGVzdChuYXZpZ2F0b3IudXNlckFnZW50KTtcbiAgICAgIGxvZ2dlci5kZWJ1ZyhgQnJvd3NlciBkZXRlY3Rpb246IFNhZmFyaSA9ICR7aXNTYWZhcml9YCk7XG5cbiAgICAgIGNvbnN0IHN0cmVhbSA9IGF3YWl0IG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKHtcbiAgICAgICAgYXVkaW86IGlzU2FmYXJpID8ge1xuICAgICAgICAgIC8vIFNhZmFyaSBwcmVmZXJzIHNpbXBsZXIgY29uc3RyYWludHNcbiAgICAgICAgICBlY2hvQ2FuY2VsbGF0aW9uOiBmYWxzZSxcbiAgICAgICAgICBub2lzZVN1cHByZXNzaW9uOiBmYWxzZSxcbiAgICAgICAgICBhdXRvR2FpbkNvbnRyb2w6IGZhbHNlLFxuICAgICAgICB9IDoge1xuICAgICAgICAgIGVjaG9DYW5jZWxsYXRpb246IHRydWUsXG4gICAgICAgICAgbm9pc2VTdXBwcmVzc2lvbjogdHJ1ZSxcbiAgICAgICAgICBhdXRvR2FpbkNvbnRyb2w6IHRydWUsXG4gICAgICAgICAgc2FtcGxlUmF0ZTogMTYwMDAsXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgbG9nZ2VyLmRlYnVnKGBBdWRpbyBzdHJlYW0gdHJhY2tzOiAke3N0cmVhbS5nZXRBdWRpb1RyYWNrcygpLmxlbmd0aH1gKTtcbiAgICAgIHN0cmVhbS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goKHRyYWNrLCBpbmRleCkgPT4ge1xuICAgICAgICBsb2dnZXIuZGVidWcoYFRyYWNrICR7aW5kZXh9OiAke3RyYWNrLmxhYmVsfSwgZW5hYmxlZDogJHt0cmFjay5lbmFibGVkfSwgcmVhZHlTdGF0ZTogJHt0cmFjay5yZWFkeVN0YXRlfWApO1xuICAgICAgfSk7XG5cbiAgICAgIHN0cmVhbVJlZi5jdXJyZW50ID0gc3RyZWFtO1xuICAgICAgYXVkaW9DaHVua3NSZWYuY3VycmVudCA9IFtdO1xuICAgICAgZmluYWxUcmFuc2NyaXB0UmVmLmN1cnJlbnQgPSAnJztcblxuICAgICAgLy8gQ3JlYXRlIE1lZGlhUmVjb3JkZXIgd2l0aCBzdXBwb3J0ZWQgZm9ybWF0XG4gICAgICBjb25zdCBtaW1lVHlwZSA9IGdldFN1cHBvcnRlZE1pbWVUeXBlKCk7XG4gICAgICBsb2dnZXIuZGVidWcoYFVzaW5nIE1JTUUgdHlwZTogJHttaW1lVHlwZX1gKTtcbiAgICAgIGxhc3RNaW1lVHlwZVJlZi5jdXJyZW50ID0gbWltZVR5cGU7XG5cbiAgICAgIC8vIFRyeSBjcmVhdGluZyBNZWRpYVJlY29yZGVyIHdpdGggbWluaW1hbCBvcHRpb25zIGZpcnN0XG4gICAgICBsZXQgbWVkaWFSZWNvcmRlcjogTWVkaWFSZWNvcmRlcjtcbiAgICAgIHRyeSB7XG4gICAgICAgIG1lZGlhUmVjb3JkZXIgPSBuZXcgTWVkaWFSZWNvcmRlcihzdHJlYW0sIHsgbWltZVR5cGUgfSk7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZygnTWVkaWFSZWNvcmRlciBjcmVhdGVkIHdpdGggbWluaW1hbCBvcHRpb25zJyk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBsb2dnZXIud2FybignTWVkaWFSZWNvcmRlciBjb25zdHJ1Y3RvciBmYWlsZWQgd2l0aCBtaW5pbWFsIG9wdGlvbnMsIHRyeWluZyBmYWxsYmFjazonLCBlcnJvcik7XG4gICAgICAgIC8vIEZhbGxiYWNrIHdpdGhvdXQgbWltZVR5cGVcbiAgICAgICAgbWVkaWFSZWNvcmRlciA9IG5ldyBNZWRpYVJlY29yZGVyKHN0cmVhbSk7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZygnTWVkaWFSZWNvcmRlciBjcmVhdGVkIHdpdGggZmFsbGJhY2sgb3B0aW9ucycpO1xuICAgICAgfVxuXG4gICAgICBtZWRpYVJlY29yZGVyUmVmLmN1cnJlbnQgPSBtZWRpYVJlY29yZGVyO1xuXG4gICAgICAvLyBIYW5kbGUgYXVkaW8gZGF0YSAtIHRyaWdnZXIgc3RyZWFtaW5nIGNoZWNrc1xuICAgICAgbWVkaWFSZWNvcmRlci5vbmRhdGFhdmFpbGFibGUgPSAoZXZlbnQ6IEJsb2JFdmVudCkgPT4ge1xuICAgICAgICBpZiAoZXZlbnQuZGF0YS5zaXplID4gMCkge1xuICAgICAgICAgIGF1ZGlvQ2h1bmtzUmVmLmN1cnJlbnQucHVzaChldmVudC5kYXRhKTtcbiAgICAgICAgICBsb2dnZXIuZGVidWcoYEF1ZGlvIGNodW5rOiAke2V2ZW50LmRhdGEuc2l6ZX0gYnl0ZXMgKHRvdGFsOiAke2F1ZGlvQ2h1bmtzUmVmLmN1cnJlbnQubGVuZ3RofSBjaHVua3MpYCk7XG4gICAgICAgICAgLy8gQ2hlY2sgaWYgd2Ugc2hvdWxkIHN0cmVhbVxuICAgICAgICAgIGNoZWNrQW5kU3RyZWFtQXVkaW8oKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgLy8gSGFuZGxlIHN0YXJ0XG4gICAgICBtZWRpYVJlY29yZGVyLm9uc3RhcnQgPSAoKSA9PiB7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZygnTWVkaWFSZWNvcmRlciBzdGFydGVkLCBzdGF0ZTonLCBtZWRpYVJlY29yZGVyLnN0YXRlKTtcbiAgICAgIH07XG5cbiAgICAgIC8vIEhhbmRsZSByZWNvcmRpbmcgc3RvcFxuICAgICAgbWVkaWFSZWNvcmRlci5vbnN0b3AgPSBhc3luYyAoKSA9PiB7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZygnUmVjb3JkaW5nIHN0b3BwZWQsIGNsZWFuaW5nIHVwIHN0cmVhbS4uLicpO1xuICAgICAgICBzZXRJc1JlY29yZGluZyhmYWxzZSk7XG4gICAgICAgIFxuICAgICAgICAvLyBDYW5jZWwgYWN0aXZlIHN0cmVhbVxuICAgICAgICBpZiAoc3RyZWFtQWJvcnRSZWYuY3VycmVudCkge1xuICAgICAgICAgIHN0cmVhbUFib3J0UmVmLmN1cnJlbnQuYWJvcnQoKTtcbiAgICAgICAgICBzdHJlYW1BYm9ydFJlZi5jdXJyZW50ID0gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENsZWFuIHVwIHN0cmVhbSAoY2xvc2UgbWljIGltbWVkaWF0ZWx5KVxuICAgICAgICBpZiAoc3RyZWFtUmVmLmN1cnJlbnQpIHtcbiAgICAgICAgICBzdHJlYW1SZWYuY3VycmVudC5nZXRUcmFja3MoKS5mb3JFYWNoKHRyYWNrID0+IHRyYWNrLnN0b3AoKSk7XG4gICAgICAgICAgc3RyZWFtUmVmLmN1cnJlbnQgPSBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgbG9nZ2VyLmluZm8oJ/Cfm5EgR3JvcSByZWNvcmRpbmcgc3RvcHBlZCcpO1xuXG4gICAgICAgIGNvbnN0IGZpbmFsVHJhbnNjcmlwdCA9IChcbiAgICAgICAgICBmaW5hbFRyYW5zY3JpcHRSZWYuY3VycmVudCB8fFxuICAgICAgICAgIHRyYW5zY3JpcHRpb25TdGF0ZVJlZi5jdXJyZW50Lmxhc3RJbnRlcmltIHx8XG4gICAgICAgICAgJydcbiAgICAgICAgKS50cmltKCk7XG4gICAgICAgIGxldCBwYXJzZVRyYW5zY3JpcHQgPSBmaW5hbFRyYW5zY3JpcHQ7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBhdWRpb0NodW5rc1JlZi5jdXJyZW50Lmxlbmd0aCA+IDAgJiZcbiAgICAgICAgICAgIGxhbmd1YWdlICYmXG4gICAgICAgICAgICAhbGFuZ3VhZ2Uuc3RhcnRzV2l0aCgnZW4nKVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgY29uc3QgbWltZVR5cGUgPSBsYXN0TWltZVR5cGVSZWYuY3VycmVudCB8fCBnZXRTdXBwb3J0ZWRNaW1lVHlwZSgpO1xuICAgICAgICAgICAgY29uc3QgYXVkaW9CbG9iID0gbmV3IEJsb2IoYXVkaW9DaHVua3NSZWYuY3VycmVudCwgeyB0eXBlOiBtaW1lVHlwZSB9KTtcbiAgICAgICAgICAgIGlmIChhdWRpb0Jsb2Iuc2l6ZSA+IDApIHtcbiAgICAgICAgICAgICAgY29uc3QgdHJhbnNsYXRlZCA9IGF3YWl0IHRyYW5zbGF0ZUdyb3FBdWRpbyh7XG4gICAgICAgICAgICAgICAgYXBpS2V5OiBjbGllbnRTZWNyZXQsXG4gICAgICAgICAgICAgICAgYXVkaW9CbG9iLFxuICAgICAgICAgICAgICAgIG1pbWVUeXBlLFxuICAgICAgICAgICAgICAgIGxhbmd1YWdlLFxuICAgICAgICAgICAgICAgIGVuZHBvaW50OiByZXNvbHZlR3JvcVRyYW5zbGF0aW9uRW5kcG9pbnQoXG4gICAgICAgICAgICAgICAgICBncm9xQXBpQmFzZVVybCxcbiAgICAgICAgICAgICAgICAgIGdyb3FUcmFuc2NyaXB0aW9uRW5kcG9pbnQsXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIGlmICh0cmFuc2xhdGVkKSB7XG4gICAgICAgICAgICAgICAgaWYgKHNwZWVjaFRyYW5zbGF0aW9uQ2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICAgIHNwZWVjaFRyYW5zbGF0aW9uQ2FsbGJhY2sodHJhbnNsYXRlZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHBhcnNlVHJhbnNjcmlwdCA9IHRyYW5zbGF0ZWQ7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgbG9nZ2VyLndhcm4oJ0dyb3EgdHJhbnNsYXRpb24gZmFpbGVkOicsIGVycm9yKTtcbiAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICBhdWRpb0NodW5rc1JlZi5jdXJyZW50ID0gW107XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTdHJlYW0gd2lsbCBuYXR1cmFsbHkgZW5kLCBqdXN0IHNpZ25hbCBlbmQgb2YgcmVjb3JkaW5nXG4gICAgICAgIHNwZWVjaFN0YXR1c0NhbGxiYWNrKGZhbHNlLCAnJyk7XG4gICAgICAgIGlmIChwYXJzZVRyYW5zY3JpcHQpIHtcbiAgICAgICAgICBzcGVlY2hSZXN1bHRDYWxsYmFjayhwYXJzZVRyYW5zY3JpcHQpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICAvLyBIYW5kbGUgZXJyb3JzXG4gICAgICBtZWRpYVJlY29yZGVyLm9uZXJyb3IgPSAoZXZlbnQ6IEV2ZW50KSA9PiB7XG4gICAgICAgIGxvZ2dlci5lcnJvcignTWVkaWFSZWNvcmRlciBlcnJvcjonLCBldmVudCk7XG4gICAgICAgIHNldElzUmVjb3JkaW5nKGZhbHNlKTtcbiAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgRXJyb3IoJ1JlY29yZGluZyBmYWlsZWQnKTtcbiAgICAgICAgaWYgKG9uRXJyb3IpIG9uRXJyb3IoZXJyb3IpO1xuICAgICAgICBzcGVlY2hTdGF0dXNDYWxsYmFjayhmYWxzZSwgJycpO1xuICAgICAgfTtcblxuICAgICAgLy8gU3RhcnQgcmVjb3JkaW5nIHdpdGggMTAwbXMgdGltZXNsaWNlIChtYXRjaGluZyBNTFgpXG4gICAgICBtZWRpYVJlY29yZGVyLnN0YXJ0KDEwMCk7XG4gICAgICBsb2dnZXIuZGVidWcoJ01lZGlhUmVjb3JkZXIuc3RhcnQoMTAwKSBjYWxsZWQnKTtcblxuICAgICAgc3RhcnRUaW1lUmVmLmN1cnJlbnQgPSBEYXRlLm5vdygpO1xuICAgICAgc2V0SXNSZWNvcmRpbmcodHJ1ZSk7XG4gICAgICAvLyBEb24ndCBzZW5kIGVtcHR5IGludGVyaW0gb24gc3RhcnQgLSB3YWl0IGZvciBhY3R1YWwgdHJhbnNjcmlwdHNcbiAgICAgIC8vIHNwZWVjaFN0YXR1c0NhbGxiYWNrKHRydWUsICcnKTtcbiAgICAgIGxvZ2dlci5pbmZvKCfwn46kIEdyb3EgcmVjb3JkaW5nIHN0YXJ0ZWQnKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgbG9nZ2VyLmVycm9yKCdGYWlsZWQgdG8gc3RhcnQgcmVjb3JkaW5nOicsIGVycm9yKTtcbiAgICAgIGNvbnN0IGVyciA9IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvciA6IG5ldyBFcnJvcihTdHJpbmcoZXJyb3IpKTtcbiAgICAgIGlmIChvbkVycm9yKSBvbkVycm9yKGVycik7XG4gICAgICBzcGVlY2hTdGF0dXNDYWxsYmFjayhmYWxzZSwgJycpO1xuICAgIH1cbiAgfSwgW1xuICAgIHNwZWVjaFN0YXR1c0NhbGxiYWNrLFxuICAgIHNwZWVjaFJlc3VsdENhbGxiYWNrLFxuICAgIHNwZWVjaFRyYW5zbGF0aW9uQ2FsbGJhY2ssXG4gICAgY2xpZW50U2VjcmV0LFxuICAgIGdyb3FBcGlCYXNlVXJsLFxuICAgIGdyb3FUcmFuc2NyaXB0aW9uRW5kcG9pbnQsXG4gICAgbGFuZ3VhZ2UsXG4gICAgb25FcnJvcixcbiAgXSk7XG5cbiAgLyoqXG4gICAqIFN0b3AgYXVkaW8gcmVjb3JkaW5nXG4gICAqL1xuICBjb25zdCBzdG9wUmVjb3JkaW5nID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgIGxvZ2dlci5kZWJ1ZygnU3RvcCByZWNvcmRpbmcgY2FsbGVkJyk7XG4gICAgXG4gICAgLy8gU3RvcCBhbGwgYXVkaW8gdHJhY2tzIGltbWVkaWF0ZWx5XG4gICAgaWYgKHN0cmVhbVJlZi5jdXJyZW50KSB7XG4gICAgICBzdHJlYW1SZWYuY3VycmVudC5nZXRUcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICB9KTtcbiAgICAgIHN0cmVhbVJlZi5jdXJyZW50ID0gbnVsbDtcbiAgICB9XG4gICAgXG4gICAgaWYgKG1lZGlhUmVjb3JkZXJSZWYuY3VycmVudCAmJiBtZWRpYVJlY29yZGVyUmVmLmN1cnJlbnQuc3RhdGUgPT09ICdyZWNvcmRpbmcnKSB7XG4gICAgICBtZWRpYVJlY29yZGVyUmVmLmN1cnJlbnQuc3RvcCgpO1xuICAgIH1cbiAgfSwgW10pO1xuXG4gIC8qKlxuICAgKiBTdHJlYW0gYXVkaW8gdG8gR3JvcSBhbmQgaGFuZGxlIFNTRSByZXNwb25zZXNcbiAgICogU2VuZHMgYWNjdW11bGF0ZWQgY2h1bmtzIGFuZCBzdHJlYW1zIGludGVyaW0gdHJhbnNjcmlwdHNcbiAgICovXG4gIGNvbnN0IHN0cmVhbUF1ZGlvID0gdXNlQ2FsbGJhY2soYXN5bmMgKGF1ZGlvQmxvYjogQmxvYikgPT4ge1xuICAgIGlmICh0cmFuc2NyaXB0aW9uU3RhdGVSZWYuY3VycmVudC5pc1N0cmVhbWluZykge1xuICAgICAgbG9nZ2VyLndhcm4oJ0FscmVhZHkgc3RyZWFtaW5nLCBza2lwcGluZycpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRyYW5zY3JpcHRpb25TdGF0ZVJlZi5jdXJyZW50LmlzU3RyZWFtaW5nID0gdHJ1ZTtcbiAgICB0cmFuc2NyaXB0aW9uU3RhdGVSZWYuY3VycmVudC5sYXN0U2VuZFRpbWUgPSBEYXRlLm5vdygpO1xuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IG1pbWVUeXBlID0gZ2V0U3VwcG9ydGVkTWltZVR5cGUoKTtcbiAgICAgIGxvZ2dlci5pbmZvKGDwn5OkIFN0cmVhbWluZyAke2F1ZGlvQmxvYi5zaXplfSBieXRlcyB0byBHcm9xIChpbnRlcmltIG1vZGUpLi4uYCk7XG5cbiAgICAgIHN0cmVhbUFib3J0UmVmLmN1cnJlbnQgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG4gICAgICBjb25zdCBzdGF0ZSA9IHRyYW5zY3JpcHRpb25TdGF0ZVJlZi5jdXJyZW50O1xuXG4gICAgICBhd2FpdCBzdHJlYW1Hcm9xVHJhbnNjcmlwdGlvbih7XG4gICAgICAgIGFwaUtleTogY2xpZW50U2VjcmV0LFxuICAgICAgICBhdWRpb0Jsb2IsXG4gICAgICAgIG1pbWVUeXBlLFxuICAgICAgICBsYW5ndWFnZSxcbiAgICAgICAgcmVzcG9uc2VGb3JtYXQ6ICd2ZXJib3NlX2pzb24nLFxuICAgICAgICBzdHJlYW0sXG4gICAgICAgIGVuZHBvaW50OiByZXNvbHZlR3JvcVRyYW5zY3JpcHRpb25FbmRwb2ludChcbiAgICAgICAgICBncm9xQXBpQmFzZVVybCxcbiAgICAgICAgICBncm9xVHJhbnNjcmlwdGlvbkVuZHBvaW50LFxuICAgICAgICApLFxuICAgICAgICBzaWduYWw6IHN0cmVhbUFib3J0UmVmLmN1cnJlbnQuc2lnbmFsLFxuICAgICAgICBvbkludGVyaW06IChpbnRlcmltVGV4dCkgPT4ge1xuICAgICAgICAgIGlmICghaW50ZXJpbVRleHQgfHwgaW50ZXJpbVRleHQgPT09IHN0YXRlLmxhc3RJbnRlcmltKSByZXR1cm47XG4gICAgICAgICAgc3RhdGUubGFzdEludGVyaW0gPSBpbnRlcmltVGV4dDtcbiAgICAgICAgICBmaW5hbFRyYW5zY3JpcHRSZWYuY3VycmVudCA9IGludGVyaW1UZXh0O1xuICAgICAgICAgIGxvZ2dlci5pbmZvKGDwn5OdIEludGVyaW06IFwiJHtpbnRlcmltVGV4dH1cImApO1xuICAgICAgICAgIHNwZWVjaFN0YXR1c0NhbGxiYWNrKHRydWUsIGludGVyaW1UZXh0KTtcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBFcnJvciAmJiBlcnJvci5uYW1lICE9PSAnQWJvcnRFcnJvcicpIHtcbiAgICAgICAgbG9nZ2VyLmVycm9yKCfinYwgU3RyZWFtIGVycm9yOicsIGVycm9yKTtcbiAgICAgICAgaWYgKG9uRXJyb3IpIG9uRXJyb3IoZXJyb3IpO1xuICAgICAgfVxuICAgIH0gZmluYWxseSB7XG4gICAgICB0cmFuc2NyaXB0aW9uU3RhdGVSZWYuY3VycmVudC5pc1N0cmVhbWluZyA9IGZhbHNlO1xuICAgIH1cbiAgfSwgW2NsaWVudFNlY3JldCwgZ3JvcUFwaUJhc2VVcmwsIGdyb3FUcmFuc2NyaXB0aW9uRW5kcG9pbnQsIGxhbmd1YWdlLCBvbkVycm9yLCBzdHJlYW1dKTtcblxuICAvKipcbiAgICogQ2hlY2sgaWYgYXVkaW8gdGhyZXNob2xkIG1ldCBhbmQgc3RyZWFtIHRvIEdyb3FcbiAgICogSW1wbGVtZW50cyBkZWJvdW5jZWQgc3RyZWFtaW5nIHdpdGggbWluaW11bSBjaHVuayBzaXplXG4gICAqL1xuICBjb25zdCBjaGVja0FuZFN0cmVhbUF1ZGlvID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgIGNvbnN0IG1pbWVUeXBlID0gZ2V0U3VwcG9ydGVkTWltZVR5cGUoKTtcbiAgICBjb25zdCBhdWRpb0Jsb2IgPSBuZXcgQmxvYihhdWRpb0NodW5rc1JlZi5jdXJyZW50LCB7IHR5cGU6IG1pbWVUeXBlIH0pO1xuICAgIGNvbnN0IG5vdyA9IERhdGUubm93KCk7XG5cbiAgICBjb25zdCBzdGF0ZSA9IHRyYW5zY3JpcHRpb25TdGF0ZVJlZi5jdXJyZW50O1xuXG4gICAgLy8gQ2hlY2s6IG1pbmltdW0gY2h1bmsgc2l6ZSByZWFjaGVkP1xuICAgIGlmIChhdWRpb0Jsb2Iuc2l6ZSA8IE1JTl9DSFVOS19TSVpFKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gQ2hlY2s6IGFscmVhZHkgc3RyZWFtaW5nP1xuICAgIGlmIChzdGF0ZS5pc1N0cmVhbWluZykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIENoZWNrOiBkZWJvdW5jZSBpbnRlcnZhbCByZXNwZWN0ZWQ/XG4gICAgaWYgKG5vdyAtIHN0YXRlLmxhc3RTZW5kVGltZSA8IFNFTkRfSU5URVJWQUwpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBBbGwgY2hlY2tzIHBhc3NlZCAtIHN0YXJ0IHN0cmVhbWluZ1xuICAgIHN0cmVhbUF1ZGlvKGF1ZGlvQmxvYik7XG4gIH0sIFtzdHJlYW1BdWRpb10pO1xuXG4gIC8vIFNTRSBoYW5kbGluZyBtb3ZlZCB0byBzaGFyZWQgaGVscGVyIChncm9xLXRyYW5zY3JpcHRpb24udHMpXG5cbiAgLyoqXG4gICAqIFByb2Nlc3MgY29sbGVjdGVkIGF1ZGlvIGNodW5rcyBhbmQgc2VuZCB0byBHcm9xIGZvciB0cmFuc2NyaXB0aW9uIChtYXRjaGluZyBNTFgpXG4gICAqIENSSVRJQ0FMOiBHdWFyZCB3aXRoIHByb2Nlc3NpbmdSZWYgdG8gcHJldmVudCBkdXBsaWNhdGUgdXBsb2Fkc1xuICAgKi9cbiAgY29uc3QgcHJvY2Vzc0F1ZGlvQ2h1bmtzID0gdXNlQ2FsbGJhY2soYXN5bmMgKCkgPT4ge1xuICAgIGlmIChhdWRpb0NodW5rc1JlZi5jdXJyZW50Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgbG9nZ2VyLndhcm4oJ05vIGF1ZGlvIGNodW5rcyB0byBwcm9jZXNzJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gSW4gc3RyZWFtaW5nIG1vZGUsIGF1ZGlvIGFscmVhZHkgcHJvY2Vzc2VkIHZpYSBzdHJlYW1cbiAgICBsb2dnZXIuaW5mbygn4pyFIFN0cmVhbWluZyBjb21wbGV0ZWQnKTtcbiAgICBhdWRpb0NodW5rc1JlZi5jdXJyZW50ID0gW107XG4gIH0sIFtdKTtcblxuICAvKipcbiAgICogSGFuZGxlIHNob3VsZExpc3RlbiBwcm9wIGNoYW5nZXNcbiAgICovXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgbG9nZ2VyLmRlYnVnKGBzaG91bGRMaXN0ZW4gY2hhbmdlZDogJHtzaG91bGRMaXN0ZW59LCBpc1JlY29yZGluZzogJHtpc1JlY29yZGluZ31gKTtcblxuICAgIGlmIChzaG91bGRMaXN0ZW4gJiYgIWlzUmVjb3JkaW5nKSB7XG4gICAgICBsb2dnZXIuZGVidWcoJ+KchSBTdGFydGluZyByZWNvcmRpbmcnKTtcbiAgICAgIHN0YXJ0UmVjb3JkaW5nKCk7XG4gICAgfSBlbHNlIGlmICghc2hvdWxkTGlzdGVuICYmIGlzUmVjb3JkaW5nKSB7XG4gICAgICBsb2dnZXIuZGVidWcoJ+KdjCBTdG9wcGluZyByZWNvcmRpbmcnKTtcbiAgICAgIHN0b3BSZWNvcmRpbmcoKTtcbiAgICB9XG4gIH0sIFtzaG91bGRMaXN0ZW4sIGlzUmVjb3JkaW5nLCBzdGFydFJlY29yZGluZywgc3RvcFJlY29yZGluZ10pO1xuXG4gIC8qKlxuICAgKiBDbGVhbnVwIG9uIHVubW91bnRcbiAgICovXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgIGlmIChzdHJlYW1BYm9ydFJlZi5jdXJyZW50KSB7XG4gICAgICAgIHN0cmVhbUFib3J0UmVmLmN1cnJlbnQuYWJvcnQoKTtcbiAgICAgIH1cbiAgICAgIGlmIChtZWRpYVJlY29yZGVyUmVmLmN1cnJlbnQgJiYgbWVkaWFSZWNvcmRlclJlZi5jdXJyZW50LnN0YXRlID09PSAncmVjb3JkaW5nJykge1xuICAgICAgICBtZWRpYVJlY29yZGVyUmVmLmN1cnJlbnQuc3RvcCgpO1xuICAgICAgfVxuICAgICAgaWYgKHN0cmVhbVJlZi5jdXJyZW50KSB7XG4gICAgICAgIHN0cmVhbVJlZi5jdXJyZW50LmdldFRyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB0cmFjay5zdG9wKCkpO1xuICAgICAgfVxuICAgIH07XG4gIH0sIFtdKTtcblxuICByZXR1cm4gPFZpZXcgLz47XG59O1xuXG4vKipcbiAqIEdldCBzdXBwb3J0ZWQgTUlNRSB0eXBlIGZvciBNZWRpYVJlY29yZGVyXG4gKi9cbmZ1bmN0aW9uIGdldFN1cHBvcnRlZE1pbWVUeXBlKCk6IHN0cmluZyB7XG4gIGNvbnN0IHR5cGVzID0gW1xuICAgICdhdWRpby93ZWJtO2NvZGVjcz1vcHVzJyxcbiAgICAnYXVkaW8vd2VibScsXG4gICAgJ2F1ZGlvL29nZztjb2RlY3M9b3B1cycsXG4gICAgJ2F1ZGlvL21wNCcsXG4gICAgJ2F1ZGlvL3dhdicsXG4gIF07XG5cbiAgZm9yIChjb25zdCB0eXBlIG9mIHR5cGVzKSB7XG4gICAgaWYgKE1lZGlhUmVjb3JkZXIuaXNUeXBlU3VwcG9ydGVkKHR5cGUpKSB7XG4gICAgICByZXR1cm4gdHlwZTtcbiAgICB9XG4gIH1cblxuICAvLyBGYWxsYmFja1xuICByZXR1cm4gJ2F1ZGlvL3dlYm0nO1xufVxuXG5mdW5jdGlvbiByZXNvbHZlR3JvcVRyYW5zY3JpcHRpb25FbmRwb2ludChcbiAgYmFzZVVybD86IHN0cmluZyxcbiAgb3ZlcnJpZGVFbmRwb2ludD86IHN0cmluZyxcbik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGlmIChvdmVycmlkZUVuZHBvaW50KSByZXR1cm4gb3ZlcnJpZGVFbmRwb2ludDtcbiAgaWYgKCFiYXNlVXJsKSByZXR1cm4gdW5kZWZpbmVkO1xuICBjb25zdCB0cmltbWVkID0gYmFzZVVybC5yZXBsYWNlKC9cXC8rJC8sICcnKTtcbiAgaWYgKHRyaW1tZWQuZW5kc1dpdGgoJy9vcGVuYWkvdjEnKSkge1xuICAgIHJldHVybiBgJHt0cmltbWVkfS9hdWRpby90cmFuc2NyaXB0aW9uc2A7XG4gIH1cbiAgcmV0dXJuIGAke3RyaW1tZWR9L29wZW5haS92MS9hdWRpby90cmFuc2NyaXB0aW9uc2A7XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVHcm9xVHJhbnNsYXRpb25FbmRwb2ludChcbiAgYmFzZVVybD86IHN0cmluZyxcbiAgb3ZlcnJpZGVFbmRwb2ludD86IHN0cmluZyxcbik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGlmIChvdmVycmlkZUVuZHBvaW50KSB7XG4gICAgcmV0dXJuIG92ZXJyaWRlRW5kcG9pbnQuaW5jbHVkZXMoJy9hdWRpby90cmFuc2NyaXB0aW9ucycpXG4gICAgICA/IG92ZXJyaWRlRW5kcG9pbnQucmVwbGFjZSgnL2F1ZGlvL3RyYW5zY3JpcHRpb25zJywgJy9hdWRpby90cmFuc2xhdGlvbnMnKVxuICAgICAgOiBvdmVycmlkZUVuZHBvaW50O1xuICB9XG4gIGlmICghYmFzZVVybCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgY29uc3QgdHJpbW1lZCA9IGJhc2VVcmwucmVwbGFjZSgvXFwvKyQvLCAnJyk7XG4gIGlmICh0cmltbWVkLmVuZHNXaXRoKCcvb3BlbmFpL3YxJykpIHtcbiAgICByZXR1cm4gYCR7dHJpbW1lZH0vYXVkaW8vdHJhbnNsYXRpb25zYDtcbiAgfVxuICByZXR1cm4gYCR7dHJpbW1lZH0vb3BlbmFpL3YxL2F1ZGlvL3RyYW5zbGF0aW9uc2A7XG59XG5cbi8qKlxuICogR2V0IGZpbGUgZXh0ZW5zaW9uIGZyb20gTUlNRSB0eXBlXG4gKi9cbi8qKlxuICogQ2hlY2sgaWYgR3JvcSBzcGVlY2ggcmVjb2duaXRpb24gaXMgYXZhaWxhYmxlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0dyb3FTcGVlY2hBdmFpbGFibGUoKTogYm9vbGVhbiB7XG4gIC8vIENoZWNrIGlmIHJ1bm5pbmcgaW4gYnJvd3NlclxuICBpZiAodHlwZW9mIHdpbmRvdyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvLyBDaGVjayBmb3IgcmVxdWlyZWQgQVBJc1xuICBjb25zdCBoYXNNZWRpYURldmljZXMgPSBcbiAgICBuYXZpZ2F0b3I/Lm1lZGlhRGV2aWNlcz8uZ2V0VXNlck1lZGlhICE9PSB1bmRlZmluZWQ7XG4gIGNvbnN0IGhhc01lZGlhUmVjb3JkZXIgPSB0eXBlb2YgTWVkaWFSZWNvcmRlciAhPT0gJ3VuZGVmaW5lZCc7XG5cbiAgcmV0dXJuIGhhc01lZGlhRGV2aWNlcyAmJiBoYXNNZWRpYVJlY29yZGVyO1xufVxuXG4vKipcbiAqIEdldCBicm93c2VyIGNhcGFiaWxpdGllcyBmb3IgR3JvcSBzcGVlY2hcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEdyb3FTcGVlY2hDYXBhYmlsaXRpZXMoKSB7XG4gIHJldHVybiB7XG4gICAgYXZhaWxhYmxlOiBpc0dyb3FTcGVlY2hBdmFpbGFibGUoKSxcbiAgICBzdXBwb3J0ZWRNaW1lVHlwZXM6IFtcbiAgICAgICdhdWRpby93ZWJtO2NvZGVjcz1vcHVzJyxcbiAgICAgICdhdWRpby93ZWJtJyxcbiAgICAgICdhdWRpby9vZ2c7Y29kZWNzPW9wdXMnLFxuICAgICAgJ2F1ZGlvL21wNCcsXG4gICAgICAnYXVkaW8vd2F2JyxcbiAgICBdLmZpbHRlcigodHlwZSkgPT4ge1xuICAgICAgaWYgKHR5cGVvZiBNZWRpYVJlY29yZGVyID09PSAndW5kZWZpbmVkJykgcmV0dXJuIGZhbHNlO1xuICAgICAgcmV0dXJuIE1lZGlhUmVjb3JkZXIuaXNUeXBlU3VwcG9ydGVkKHR5cGUpO1xuICAgIH0pLFxuICAgIHBsYXRmb3JtOiBQbGF0Zm9ybS5PUyxcbiAgfTtcbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUFNQSxJQUFBQSxNQUFBLEdBQUFDLHVCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBQyxZQUFBLEdBQUFELE9BQUE7QUFDQSxJQUFBRSxPQUFBLEdBQUFGLE9BQUE7QUFDQSxJQUFBRyxrQkFBQSxHQUFBSCxPQUFBO0FBQXlGLFNBQUFELHdCQUFBSyxDQUFBLEVBQUFDLENBQUEsNkJBQUFDLE9BQUEsTUFBQUMsQ0FBQSxPQUFBRCxPQUFBLElBQUFFLENBQUEsT0FBQUYsT0FBQSxZQUFBUCx1QkFBQSxZQUFBQSxDQUFBSyxDQUFBLEVBQUFDLENBQUEsU0FBQUEsQ0FBQSxJQUFBRCxDQUFBLElBQUFBLENBQUEsQ0FBQUssVUFBQSxTQUFBTCxDQUFBLE1BQUFNLENBQUEsRUFBQUMsQ0FBQSxFQUFBQyxDQUFBLEtBQUFDLFNBQUEsUUFBQUMsT0FBQSxFQUFBVixDQUFBLGlCQUFBQSxDQUFBLHVCQUFBQSxDQUFBLHlCQUFBQSxDQUFBLFNBQUFRLENBQUEsTUFBQUYsQ0FBQSxHQUFBTCxDQUFBLEdBQUFHLENBQUEsR0FBQUQsQ0FBQSxRQUFBRyxDQUFBLENBQUFLLEdBQUEsQ0FBQVgsQ0FBQSxVQUFBTSxDQUFBLENBQUFNLEdBQUEsQ0FBQVosQ0FBQSxHQUFBTSxDQUFBLENBQUFPLEdBQUEsQ0FBQWIsQ0FBQSxFQUFBUSxDQUFBLGdCQUFBUCxDQUFBLElBQUFELENBQUEsZ0JBQUFDLENBQUEsT0FBQWEsY0FBQSxDQUFBQyxJQUFBLENBQUFmLENBQUEsRUFBQUMsQ0FBQSxPQUFBTSxDQUFBLElBQUFELENBQUEsR0FBQVUsTUFBQSxDQUFBQyxjQUFBLEtBQUFELE1BQUEsQ0FBQUUsd0JBQUEsQ0FBQWxCLENBQUEsRUFBQUMsQ0FBQSxPQUFBTSxDQUFBLENBQUFLLEdBQUEsSUFBQUwsQ0FBQSxDQUFBTSxHQUFBLElBQUFQLENBQUEsQ0FBQUUsQ0FBQSxFQUFBUCxDQUFBLEVBQUFNLENBQUEsSUFBQUMsQ0FBQSxDQUFBUCxDQUFBLElBQUFELENBQUEsQ0FBQUMsQ0FBQSxXQUFBTyxDQUFBLEtBQUFSLENBQUEsRUFBQUMsQ0FBQTtBQVR6RjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQXFCQTtBQUNBO0FBQ0E7QUFDQTtBQUNPLE1BQU1rQixvQkFBeUQsR0FBR0EsQ0FBQztFQUN4RUMsWUFBWTtFQUNaQyxvQkFBb0I7RUFDcEJDLG9CQUFvQjtFQUNwQkMseUJBQXlCO0VBQ3pCQyxZQUFZO0VBQ1pDLGNBQWM7RUFDZEMseUJBQXlCO0VBQ3pCQyxNQUFNLEdBQUcsSUFBSTtFQUNiQyxRQUFRLEdBQUcsSUFBSTtFQUNmQyxPQUFPO0VBQ1BDLFlBQVksR0FBRztBQUNqQixDQUFDLEtBQUs7RUFDSixNQUFNLENBQUNDLFdBQVcsRUFBRUMsY0FBYyxDQUFDLEdBQUcsSUFBQUMsZUFBUSxFQUFDLEtBQUssQ0FBQztFQUNyRCxNQUFNQyxnQkFBZ0IsR0FBRyxJQUFBQyxhQUFNLEVBQXVCLElBQUksQ0FBQztFQUMzRCxNQUFNQyxjQUFjLEdBQUcsSUFBQUQsYUFBTSxFQUFTLEVBQUUsQ0FBQztFQUN6QyxNQUFNRSxTQUFTLEdBQUcsSUFBQUYsYUFBTSxFQUFxQixJQUFJLENBQUM7RUFDbEQsTUFBTUcsWUFBWSxHQUFHLElBQUFILGFBQU0sRUFBUyxDQUFDLENBQUM7RUFDdEMsTUFBTUksZUFBZSxHQUFHLElBQUFKLGFBQU0sRUFBUyxZQUFZLENBQUM7O0VBRXBEO0VBQ0EsTUFBTUssY0FBYyxHQUFHLElBQUFMLGFBQU0sRUFBeUIsSUFBSSxDQUFDO0VBQzNELE1BQU1NLHFCQUFxQixHQUFHLElBQUFOLGFBQU0sRUFBQztJQUNuQ08sV0FBVyxFQUFFLEtBQUs7SUFDbEJDLFlBQVksRUFBRSxDQUFDO0lBQ2ZDLFdBQVcsRUFBRTtFQUNmLENBQUMsQ0FBQztFQUNGLE1BQU1DLGtCQUFrQixHQUFHLElBQUFWLGFBQU0sRUFBUyxFQUFFLENBQUM7RUFDN0MsTUFBTVcsY0FBYyxHQUFHLEdBQUcsQ0FBQyxDQUFDO0VBQzVCLE1BQU1DLGFBQWEsR0FBRyxJQUFJLENBQUMsQ0FBQzs7RUFFNUI7QUFDRjtBQUNBO0VBQ0UsTUFBTUMsY0FBYyxHQUFHLElBQUFDLGtCQUFXLEVBQUMsWUFBWTtJQUM3QyxJQUFJO01BQ0ZDLGNBQU0sQ0FBQ0MsS0FBSyxDQUFDLDRCQUE0QixDQUFDOztNQUUxQztNQUNBLE1BQU1DLFFBQVEsR0FBRyxnQ0FBZ0MsQ0FBQ0MsSUFBSSxDQUFDQyxTQUFTLENBQUNDLFNBQVMsQ0FBQztNQUMzRUwsY0FBTSxDQUFDQyxLQUFLLENBQUMsK0JBQStCQyxRQUFRLEVBQUUsQ0FBQztNQUV2RCxNQUFNekIsTUFBTSxHQUFHLE1BQU0yQixTQUFTLENBQUNFLFlBQVksQ0FBQ0MsWUFBWSxDQUFDO1FBQ3ZEQyxLQUFLLEVBQUVOLFFBQVEsR0FBRztVQUNoQjtVQUNBTyxnQkFBZ0IsRUFBRSxLQUFLO1VBQ3ZCQyxnQkFBZ0IsRUFBRSxLQUFLO1VBQ3ZCQyxlQUFlLEVBQUU7UUFDbkIsQ0FBQyxHQUFHO1VBQ0ZGLGdCQUFnQixFQUFFLElBQUk7VUFDdEJDLGdCQUFnQixFQUFFLElBQUk7VUFDdEJDLGVBQWUsRUFBRSxJQUFJO1VBQ3JCQyxVQUFVLEVBQUU7UUFDZDtNQUNGLENBQUMsQ0FBQztNQUVGWixjQUFNLENBQUNDLEtBQUssQ0FBQyx3QkFBd0J4QixNQUFNLENBQUNvQyxjQUFjLENBQUMsQ0FBQyxDQUFDQyxNQUFNLEVBQUUsQ0FBQztNQUN0RXJDLE1BQU0sQ0FBQ29DLGNBQWMsQ0FBQyxDQUFDLENBQUNFLE9BQU8sQ0FBQyxDQUFDQyxLQUFLLEVBQUVDLEtBQUssS0FBSztRQUNoRGpCLGNBQU0sQ0FBQ0MsS0FBSyxDQUFDLFNBQVNnQixLQUFLLEtBQUtELEtBQUssQ0FBQ0UsS0FBSyxjQUFjRixLQUFLLENBQUNHLE9BQU8saUJBQWlCSCxLQUFLLENBQUNJLFVBQVUsRUFBRSxDQUFDO01BQzVHLENBQUMsQ0FBQztNQUVGakMsU0FBUyxDQUFDa0MsT0FBTyxHQUFHNUMsTUFBTTtNQUMxQlMsY0FBYyxDQUFDbUMsT0FBTyxHQUFHLEVBQUU7TUFDM0IxQixrQkFBa0IsQ0FBQzBCLE9BQU8sR0FBRyxFQUFFOztNQUUvQjtNQUNBLE1BQU1DLFFBQVEsR0FBR0Msb0JBQW9CLENBQUMsQ0FBQztNQUN2Q3ZCLGNBQU0sQ0FBQ0MsS0FBSyxDQUFDLG9CQUFvQnFCLFFBQVEsRUFBRSxDQUFDO01BQzVDakMsZUFBZSxDQUFDZ0MsT0FBTyxHQUFHQyxRQUFROztNQUVsQztNQUNBLElBQUlFLGFBQTRCO01BQ2hDLElBQUk7UUFDRkEsYUFBYSxHQUFHLElBQUlDLGFBQWEsQ0FBQ2hELE1BQU0sRUFBRTtVQUFFNkM7UUFBUyxDQUFDLENBQUM7UUFDdkR0QixjQUFNLENBQUNDLEtBQUssQ0FBQyw0Q0FBNEMsQ0FBQztNQUM1RCxDQUFDLENBQUMsT0FBT3lCLEtBQUssRUFBRTtRQUNkMUIsY0FBTSxDQUFDMkIsSUFBSSxDQUFDLHlFQUF5RSxFQUFFRCxLQUFLLENBQUM7UUFDN0Y7UUFDQUYsYUFBYSxHQUFHLElBQUlDLGFBQWEsQ0FBQ2hELE1BQU0sQ0FBQztRQUN6Q3VCLGNBQU0sQ0FBQ0MsS0FBSyxDQUFDLDZDQUE2QyxDQUFDO01BQzdEO01BRUFqQixnQkFBZ0IsQ0FBQ3FDLE9BQU8sR0FBR0csYUFBYTs7TUFFeEM7TUFDQUEsYUFBYSxDQUFDSSxlQUFlLEdBQUlDLEtBQWdCLElBQUs7UUFDcEQsSUFBSUEsS0FBSyxDQUFDQyxJQUFJLENBQUNDLElBQUksR0FBRyxDQUFDLEVBQUU7VUFDdkI3QyxjQUFjLENBQUNtQyxPQUFPLENBQUNXLElBQUksQ0FBQ0gsS0FBSyxDQUFDQyxJQUFJLENBQUM7VUFDdkM5QixjQUFNLENBQUNDLEtBQUssQ0FBQyxnQkFBZ0I0QixLQUFLLENBQUNDLElBQUksQ0FBQ0MsSUFBSSxrQkFBa0I3QyxjQUFjLENBQUNtQyxPQUFPLENBQUNQLE1BQU0sVUFBVSxDQUFDO1VBQ3RHO1VBQ0FtQixtQkFBbUIsQ0FBQyxDQUFDO1FBQ3ZCO01BQ0YsQ0FBQzs7TUFFRDtNQUNBVCxhQUFhLENBQUNVLE9BQU8sR0FBRyxNQUFNO1FBQzVCbEMsY0FBTSxDQUFDQyxLQUFLLENBQUMsK0JBQStCLEVBQUV1QixhQUFhLENBQUNXLEtBQUssQ0FBQztNQUNwRSxDQUFDOztNQUVEO01BQ0FYLGFBQWEsQ0FBQ1ksTUFBTSxHQUFHLFlBQVk7UUFDakNwQyxjQUFNLENBQUNDLEtBQUssQ0FBQywwQ0FBMEMsQ0FBQztRQUN4RG5CLGNBQWMsQ0FBQyxLQUFLLENBQUM7O1FBRXJCO1FBQ0EsSUFBSVEsY0FBYyxDQUFDK0IsT0FBTyxFQUFFO1VBQzFCL0IsY0FBYyxDQUFDK0IsT0FBTyxDQUFDZ0IsS0FBSyxDQUFDLENBQUM7VUFDOUIvQyxjQUFjLENBQUMrQixPQUFPLEdBQUcsSUFBSTtRQUMvQjs7UUFFQTtRQUNBLElBQUlsQyxTQUFTLENBQUNrQyxPQUFPLEVBQUU7VUFDckJsQyxTQUFTLENBQUNrQyxPQUFPLENBQUNpQixTQUFTLENBQUMsQ0FBQyxDQUFDdkIsT0FBTyxDQUFDQyxLQUFLLElBQUlBLEtBQUssQ0FBQ3VCLElBQUksQ0FBQyxDQUFDLENBQUM7VUFDNURwRCxTQUFTLENBQUNrQyxPQUFPLEdBQUcsSUFBSTtRQUMxQjtRQUVBckIsY0FBTSxDQUFDd0MsSUFBSSxDQUFDLDJCQUEyQixDQUFDO1FBRXhDLE1BQU1DLGVBQWUsR0FBRyxDQUN0QjlDLGtCQUFrQixDQUFDMEIsT0FBTyxJQUMxQjlCLHFCQUFxQixDQUFDOEIsT0FBTyxDQUFDM0IsV0FBVyxJQUN6QyxFQUFFLEVBQ0ZnRCxJQUFJLENBQUMsQ0FBQztRQUNSLElBQUlDLGVBQWUsR0FBR0YsZUFBZTtRQUVyQyxJQUFJO1VBQ0YsSUFDRXZELGNBQWMsQ0FBQ21DLE9BQU8sQ0FBQ1AsTUFBTSxHQUFHLENBQUMsSUFDakNwQyxRQUFRLElBQ1IsQ0FBQ0EsUUFBUSxDQUFDa0UsVUFBVSxDQUFDLElBQUksQ0FBQyxFQUMxQjtZQUNBLE1BQU10QixRQUFRLEdBQUdqQyxlQUFlLENBQUNnQyxPQUFPLElBQUlFLG9CQUFvQixDQUFDLENBQUM7WUFDbEUsTUFBTXNCLFNBQVMsR0FBRyxJQUFJQyxJQUFJLENBQUM1RCxjQUFjLENBQUNtQyxPQUFPLEVBQUU7Y0FBRTBCLElBQUksRUFBRXpCO1lBQVMsQ0FBQyxDQUFDO1lBQ3RFLElBQUl1QixTQUFTLENBQUNkLElBQUksR0FBRyxDQUFDLEVBQUU7Y0FDdEIsTUFBTWlCLFVBQVUsR0FBRyxNQUFNLElBQUFDLHFDQUFrQixFQUFDO2dCQUMxQ0MsTUFBTSxFQUFFNUUsWUFBWTtnQkFDcEJ1RSxTQUFTO2dCQUNUdkIsUUFBUTtnQkFDUjVDLFFBQVE7Z0JBQ1J5RSxRQUFRLEVBQUVDLDhCQUE4QixDQUN0QzdFLGNBQWMsRUFDZEMseUJBQ0Y7Y0FDRixDQUFDLENBQUM7Y0FDRixJQUFJd0UsVUFBVSxFQUFFO2dCQUNkLElBQUkzRSx5QkFBeUIsRUFBRTtrQkFDN0JBLHlCQUF5QixDQUFDMkUsVUFBVSxDQUFDO2dCQUN2QztnQkFDQUwsZUFBZSxHQUFHSyxVQUFVO2NBQzlCO1lBQ0Y7VUFDRjtRQUNGLENBQUMsQ0FBQyxPQUFPdEIsS0FBSyxFQUFFO1VBQ2QxQixjQUFNLENBQUMyQixJQUFJLENBQUMsMEJBQTBCLEVBQUVELEtBQUssQ0FBQztRQUNoRCxDQUFDLFNBQVM7VUFDUnhDLGNBQWMsQ0FBQ21DLE9BQU8sR0FBRyxFQUFFO1FBQzdCOztRQUVBO1FBQ0FsRCxvQkFBb0IsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDO1FBQy9CLElBQUl3RSxlQUFlLEVBQUU7VUFDbkJ2RSxvQkFBb0IsQ0FBQ3VFLGVBQWUsQ0FBQztRQUN2QztNQUNGLENBQUM7O01BRUQ7TUFDQW5CLGFBQWEsQ0FBQzZCLE9BQU8sR0FBSXhCLEtBQVksSUFBSztRQUN4QzdCLGNBQU0sQ0FBQzBCLEtBQUssQ0FBQyxzQkFBc0IsRUFBRUcsS0FBSyxDQUFDO1FBQzNDL0MsY0FBYyxDQUFDLEtBQUssQ0FBQztRQUNyQixNQUFNNEMsS0FBSyxHQUFHLElBQUk0QixLQUFLLENBQUMsa0JBQWtCLENBQUM7UUFDM0MsSUFBSTNFLE9BQU8sRUFBRUEsT0FBTyxDQUFDK0MsS0FBSyxDQUFDO1FBQzNCdkQsb0JBQW9CLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQztNQUNqQyxDQUFDOztNQUVEO01BQ0FxRCxhQUFhLENBQUMrQixLQUFLLENBQUMsR0FBRyxDQUFDO01BQ3hCdkQsY0FBTSxDQUFDQyxLQUFLLENBQUMsaUNBQWlDLENBQUM7TUFFL0NiLFlBQVksQ0FBQ2lDLE9BQU8sR0FBR21DLElBQUksQ0FBQ0MsR0FBRyxDQUFDLENBQUM7TUFDakMzRSxjQUFjLENBQUMsSUFBSSxDQUFDO01BQ3BCO01BQ0E7TUFDQWtCLGNBQU0sQ0FBQ3dDLElBQUksQ0FBQywyQkFBMkIsQ0FBQztJQUMxQyxDQUFDLENBQUMsT0FBT2QsS0FBSyxFQUFFO01BQ2QxQixjQUFNLENBQUMwQixLQUFLLENBQUMsNEJBQTRCLEVBQUVBLEtBQUssQ0FBQztNQUNqRCxNQUFNZ0MsR0FBRyxHQUFHaEMsS0FBSyxZQUFZNEIsS0FBSyxHQUFHNUIsS0FBSyxHQUFHLElBQUk0QixLQUFLLENBQUNLLE1BQU0sQ0FBQ2pDLEtBQUssQ0FBQyxDQUFDO01BQ3JFLElBQUkvQyxPQUFPLEVBQUVBLE9BQU8sQ0FBQytFLEdBQUcsQ0FBQztNQUN6QnZGLG9CQUFvQixDQUFDLEtBQUssRUFBRSxFQUFFLENBQUM7SUFDakM7RUFDRixDQUFDLEVBQUUsQ0FDREEsb0JBQW9CLEVBQ3BCQyxvQkFBb0IsRUFDcEJDLHlCQUF5QixFQUN6QkMsWUFBWSxFQUNaQyxjQUFjLEVBQ2RDLHlCQUF5QixFQUN6QkUsUUFBUSxFQUNSQyxPQUFPLENBQ1IsQ0FBQzs7RUFFRjtBQUNGO0FBQ0E7RUFDRSxNQUFNaUYsYUFBYSxHQUFHLElBQUE3RCxrQkFBVyxFQUFDLE1BQU07SUFDdENDLGNBQU0sQ0FBQ0MsS0FBSyxDQUFDLHVCQUF1QixDQUFDOztJQUVyQztJQUNBLElBQUlkLFNBQVMsQ0FBQ2tDLE9BQU8sRUFBRTtNQUNyQmxDLFNBQVMsQ0FBQ2tDLE9BQU8sQ0FBQ2lCLFNBQVMsQ0FBQyxDQUFDLENBQUN2QixPQUFPLENBQUVDLEtBQUssSUFBSztRQUMvQ0EsS0FBSyxDQUFDdUIsSUFBSSxDQUFDLENBQUM7TUFDZCxDQUFDLENBQUM7TUFDRnBELFNBQVMsQ0FBQ2tDLE9BQU8sR0FBRyxJQUFJO0lBQzFCO0lBRUEsSUFBSXJDLGdCQUFnQixDQUFDcUMsT0FBTyxJQUFJckMsZ0JBQWdCLENBQUNxQyxPQUFPLENBQUNjLEtBQUssS0FBSyxXQUFXLEVBQUU7TUFDOUVuRCxnQkFBZ0IsQ0FBQ3FDLE9BQU8sQ0FBQ2tCLElBQUksQ0FBQyxDQUFDO0lBQ2pDO0VBQ0YsQ0FBQyxFQUFFLEVBQUUsQ0FBQzs7RUFFTjtBQUNGO0FBQ0E7QUFDQTtFQUNFLE1BQU1zQixXQUFXLEdBQUcsSUFBQTlELGtCQUFXLEVBQUMsTUFBTzhDLFNBQWUsSUFBSztJQUN6RCxJQUFJdEQscUJBQXFCLENBQUM4QixPQUFPLENBQUM3QixXQUFXLEVBQUU7TUFDN0NRLGNBQU0sQ0FBQzJCLElBQUksQ0FBQyw2QkFBNkIsQ0FBQztNQUMxQztJQUNGO0lBRUFwQyxxQkFBcUIsQ0FBQzhCLE9BQU8sQ0FBQzdCLFdBQVcsR0FBRyxJQUFJO0lBQ2hERCxxQkFBcUIsQ0FBQzhCLE9BQU8sQ0FBQzVCLFlBQVksR0FBRytELElBQUksQ0FBQ0MsR0FBRyxDQUFDLENBQUM7SUFFdkQsSUFBSTtNQUNGLE1BQU1uQyxRQUFRLEdBQUdDLG9CQUFvQixDQUFDLENBQUM7TUFDdkN2QixjQUFNLENBQUN3QyxJQUFJLENBQUMsZ0JBQWdCSyxTQUFTLENBQUNkLElBQUksa0NBQWtDLENBQUM7TUFFN0V6QyxjQUFjLENBQUMrQixPQUFPLEdBQUcsSUFBSXlDLGVBQWUsQ0FBQyxDQUFDO01BQzlDLE1BQU0zQixLQUFLLEdBQUc1QyxxQkFBcUIsQ0FBQzhCLE9BQU87TUFFM0MsTUFBTSxJQUFBMEMsMENBQXVCLEVBQUM7UUFDNUJiLE1BQU0sRUFBRTVFLFlBQVk7UUFDcEJ1RSxTQUFTO1FBQ1R2QixRQUFRO1FBQ1I1QyxRQUFRO1FBQ1JzRixjQUFjLEVBQUUsY0FBYztRQUM5QnZGLE1BQU07UUFDTjBFLFFBQVEsRUFBRWMsZ0NBQWdDLENBQ3hDMUYsY0FBYyxFQUNkQyx5QkFDRixDQUFDO1FBQ0QwRixNQUFNLEVBQUU1RSxjQUFjLENBQUMrQixPQUFPLENBQUM2QyxNQUFNO1FBQ3JDQyxTQUFTLEVBQUdDLFdBQVcsSUFBSztVQUMxQixJQUFJLENBQUNBLFdBQVcsSUFBSUEsV0FBVyxLQUFLakMsS0FBSyxDQUFDekMsV0FBVyxFQUFFO1VBQ3ZEeUMsS0FBSyxDQUFDekMsV0FBVyxHQUFHMEUsV0FBVztVQUMvQnpFLGtCQUFrQixDQUFDMEIsT0FBTyxHQUFHK0MsV0FBVztVQUN4Q3BFLGNBQU0sQ0FBQ3dDLElBQUksQ0FBQyxnQkFBZ0I0QixXQUFXLEdBQUcsQ0FBQztVQUMzQ2pHLG9CQUFvQixDQUFDLElBQUksRUFBRWlHLFdBQVcsQ0FBQztRQUN6QztNQUNGLENBQUMsQ0FBQztJQUNKLENBQUMsQ0FBQyxPQUFPMUMsS0FBSyxFQUFFO01BQ2QsSUFBSUEsS0FBSyxZQUFZNEIsS0FBSyxJQUFJNUIsS0FBSyxDQUFDMkMsSUFBSSxLQUFLLFlBQVksRUFBRTtRQUN6RHJFLGNBQU0sQ0FBQzBCLEtBQUssQ0FBQyxpQkFBaUIsRUFBRUEsS0FBSyxDQUFDO1FBQ3RDLElBQUkvQyxPQUFPLEVBQUVBLE9BQU8sQ0FBQytDLEtBQUssQ0FBQztNQUM3QjtJQUNGLENBQUMsU0FBUztNQUNSbkMscUJBQXFCLENBQUM4QixPQUFPLENBQUM3QixXQUFXLEdBQUcsS0FBSztJQUNuRDtFQUNGLENBQUMsRUFBRSxDQUFDbEIsWUFBWSxFQUFFQyxjQUFjLEVBQUVDLHlCQUF5QixFQUFFRSxRQUFRLEVBQUVDLE9BQU8sRUFBRUYsTUFBTSxDQUFDLENBQUM7O0VBRXhGO0FBQ0Y7QUFDQTtBQUNBO0VBQ0UsTUFBTXdELG1CQUFtQixHQUFHLElBQUFsQyxrQkFBVyxFQUFDLE1BQU07SUFDNUMsTUFBTXVCLFFBQVEsR0FBR0Msb0JBQW9CLENBQUMsQ0FBQztJQUN2QyxNQUFNc0IsU0FBUyxHQUFHLElBQUlDLElBQUksQ0FBQzVELGNBQWMsQ0FBQ21DLE9BQU8sRUFBRTtNQUFFMEIsSUFBSSxFQUFFekI7SUFBUyxDQUFDLENBQUM7SUFDdEUsTUFBTW1DLEdBQUcsR0FBR0QsSUFBSSxDQUFDQyxHQUFHLENBQUMsQ0FBQztJQUV0QixNQUFNdEIsS0FBSyxHQUFHNUMscUJBQXFCLENBQUM4QixPQUFPOztJQUUzQztJQUNBLElBQUl3QixTQUFTLENBQUNkLElBQUksR0FBR25DLGNBQWMsRUFBRTtNQUNuQztJQUNGOztJQUVBO0lBQ0EsSUFBSXVDLEtBQUssQ0FBQzNDLFdBQVcsRUFBRTtNQUNyQjtJQUNGOztJQUVBO0lBQ0EsSUFBSWlFLEdBQUcsR0FBR3RCLEtBQUssQ0FBQzFDLFlBQVksR0FBR0ksYUFBYSxFQUFFO01BQzVDO0lBQ0Y7O0lBRUE7SUFDQWdFLFdBQVcsQ0FBQ2hCLFNBQVMsQ0FBQztFQUN4QixDQUFDLEVBQUUsQ0FBQ2dCLFdBQVcsQ0FBQyxDQUFDOztFQUVqQjs7RUFFQTtBQUNGO0FBQ0E7QUFDQTtFQUNFLE1BQU1TLGtCQUFrQixHQUFHLElBQUF2RSxrQkFBVyxFQUFDLFlBQVk7SUFDakQsSUFBSWIsY0FBYyxDQUFDbUMsT0FBTyxDQUFDUCxNQUFNLEtBQUssQ0FBQyxFQUFFO01BQ3ZDZCxjQUFNLENBQUMyQixJQUFJLENBQUMsNEJBQTRCLENBQUM7TUFDekM7SUFDRjs7SUFFQTtJQUNBM0IsY0FBTSxDQUFDd0MsSUFBSSxDQUFDLHVCQUF1QixDQUFDO0lBQ3BDdEQsY0FBYyxDQUFDbUMsT0FBTyxHQUFHLEVBQUU7RUFDN0IsQ0FBQyxFQUFFLEVBQUUsQ0FBQzs7RUFFTjtBQUNGO0FBQ0E7RUFDRSxJQUFBa0QsZ0JBQVMsRUFBQyxNQUFNO0lBQ2R2RSxjQUFNLENBQUNDLEtBQUssQ0FBQyx5QkFBeUIvQixZQUFZLGtCQUFrQlcsV0FBVyxFQUFFLENBQUM7SUFFbEYsSUFBSVgsWUFBWSxJQUFJLENBQUNXLFdBQVcsRUFBRTtNQUNoQ21CLGNBQU0sQ0FBQ0MsS0FBSyxDQUFDLHNCQUFzQixDQUFDO01BQ3BDSCxjQUFjLENBQUMsQ0FBQztJQUNsQixDQUFDLE1BQU0sSUFBSSxDQUFDNUIsWUFBWSxJQUFJVyxXQUFXLEVBQUU7TUFDdkNtQixjQUFNLENBQUNDLEtBQUssQ0FBQyxzQkFBc0IsQ0FBQztNQUNwQzJELGFBQWEsQ0FBQyxDQUFDO0lBQ2pCO0VBQ0YsQ0FBQyxFQUFFLENBQUMxRixZQUFZLEVBQUVXLFdBQVcsRUFBRWlCLGNBQWMsRUFBRThELGFBQWEsQ0FBQyxDQUFDOztFQUU5RDtBQUNGO0FBQ0E7RUFDRSxJQUFBVyxnQkFBUyxFQUFDLE1BQU07SUFDZCxPQUFPLE1BQU07TUFDWCxJQUFJakYsY0FBYyxDQUFDK0IsT0FBTyxFQUFFO1FBQzFCL0IsY0FBYyxDQUFDK0IsT0FBTyxDQUFDZ0IsS0FBSyxDQUFDLENBQUM7TUFDaEM7TUFDQSxJQUFJckQsZ0JBQWdCLENBQUNxQyxPQUFPLElBQUlyQyxnQkFBZ0IsQ0FBQ3FDLE9BQU8sQ0FBQ2MsS0FBSyxLQUFLLFdBQVcsRUFBRTtRQUM5RW5ELGdCQUFnQixDQUFDcUMsT0FBTyxDQUFDa0IsSUFBSSxDQUFDLENBQUM7TUFDakM7TUFDQSxJQUFJcEQsU0FBUyxDQUFDa0MsT0FBTyxFQUFFO1FBQ3JCbEMsU0FBUyxDQUFDa0MsT0FBTyxDQUFDaUIsU0FBUyxDQUFDLENBQUMsQ0FBQ3ZCLE9BQU8sQ0FBRUMsS0FBSyxJQUFLQSxLQUFLLENBQUN1QixJQUFJLENBQUMsQ0FBQyxDQUFDO01BQ2hFO0lBQ0YsQ0FBQztFQUNILENBQUMsRUFBRSxFQUFFLENBQUM7RUFFTixvQkFBTy9GLE1BQUEsQ0FBQWdCLE9BQUEsQ0FBQWdILGFBQUEsQ0FBQzdILFlBQUEsQ0FBQThILElBQUksTUFBRSxDQUFDO0FBQ2pCLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBRkFDLE9BQUEsQ0FBQXpHLG9CQUFBLEdBQUFBLG9CQUFBO0FBR0EsU0FBU3NELG9CQUFvQkEsQ0FBQSxFQUFXO0VBQ3RDLE1BQU1vRCxLQUFLLEdBQUcsQ0FDWix3QkFBd0IsRUFDeEIsWUFBWSxFQUNaLHVCQUF1QixFQUN2QixXQUFXLEVBQ1gsV0FBVyxDQUNaO0VBRUQsS0FBSyxNQUFNNUIsSUFBSSxJQUFJNEIsS0FBSyxFQUFFO0lBQ3hCLElBQUlsRCxhQUFhLENBQUNtRCxlQUFlLENBQUM3QixJQUFJLENBQUMsRUFBRTtNQUN2QyxPQUFPQSxJQUFJO0lBQ2I7RUFDRjs7RUFFQTtFQUNBLE9BQU8sWUFBWTtBQUNyQjtBQUVBLFNBQVNrQixnQ0FBZ0NBLENBQ3ZDWSxPQUFnQixFQUNoQkMsZ0JBQXlCLEVBQ0w7RUFDcEIsSUFBSUEsZ0JBQWdCLEVBQUUsT0FBT0EsZ0JBQWdCO0VBQzdDLElBQUksQ0FBQ0QsT0FBTyxFQUFFLE9BQU9FLFNBQVM7RUFDOUIsTUFBTUMsT0FBTyxHQUFHSCxPQUFPLENBQUNJLE9BQU8sQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDO0VBQzNDLElBQUlELE9BQU8sQ0FBQ0UsUUFBUSxDQUFDLFlBQVksQ0FBQyxFQUFFO0lBQ2xDLE9BQU8sR0FBR0YsT0FBTyx1QkFBdUI7RUFDMUM7RUFDQSxPQUFPLEdBQUdBLE9BQU8saUNBQWlDO0FBQ3BEO0FBRUEsU0FBUzVCLDhCQUE4QkEsQ0FDckN5QixPQUFnQixFQUNoQkMsZ0JBQXlCLEVBQ0w7RUFDcEIsSUFBSUEsZ0JBQWdCLEVBQUU7SUFDcEIsT0FBT0EsZ0JBQWdCLENBQUNLLFFBQVEsQ0FBQyx1QkFBdUIsQ0FBQyxHQUNyREwsZ0JBQWdCLENBQUNHLE9BQU8sQ0FBQyx1QkFBdUIsRUFBRSxxQkFBcUIsQ0FBQyxHQUN4RUgsZ0JBQWdCO0VBQ3RCO0VBQ0EsSUFBSSxDQUFDRCxPQUFPLEVBQUUsT0FBT0UsU0FBUztFQUM5QixNQUFNQyxPQUFPLEdBQUdILE9BQU8sQ0FBQ0ksT0FBTyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUM7RUFDM0MsSUFBSUQsT0FBTyxDQUFDRSxRQUFRLENBQUMsWUFBWSxDQUFDLEVBQUU7SUFDbEMsT0FBTyxHQUFHRixPQUFPLHFCQUFxQjtFQUN4QztFQUNBLE9BQU8sR0FBR0EsT0FBTywrQkFBK0I7QUFDbEQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ08sU0FBU0kscUJBQXFCQSxDQUFBLEVBQVk7RUFDL0M7RUFDQSxJQUFJLE9BQU9DLE1BQU0sS0FBSyxXQUFXLEVBQUU7SUFDakMsT0FBTyxLQUFLO0VBQ2Q7O0VBRUE7RUFDQSxNQUFNQyxlQUFlLEdBQ25CbEYsU0FBUyxFQUFFRSxZQUFZLEVBQUVDLFlBQVksS0FBS3dFLFNBQVM7RUFDckQsTUFBTVEsZ0JBQWdCLEdBQUcsT0FBTzlELGFBQWEsS0FBSyxXQUFXO0VBRTdELE9BQU82RCxlQUFlLElBQUlDLGdCQUFnQjtBQUM1Qzs7QUFFQTtBQUNBO0FBQ0E7QUFDTyxTQUFTQyx5QkFBeUJBLENBQUEsRUFBRztFQUMxQyxPQUFPO0lBQ0xDLFNBQVMsRUFBRUwscUJBQXFCLENBQUMsQ0FBQztJQUNsQ00sa0JBQWtCLEVBQUUsQ0FDbEIsd0JBQXdCLEVBQ3hCLFlBQVksRUFDWix1QkFBdUIsRUFDdkIsV0FBVyxFQUNYLFdBQVcsQ0FDWixDQUFDQyxNQUFNLENBQUU1QyxJQUFJLElBQUs7TUFDakIsSUFBSSxPQUFPdEIsYUFBYSxLQUFLLFdBQVcsRUFBRSxPQUFPLEtBQUs7TUFDdEQsT0FBT0EsYUFBYSxDQUFDbUQsZUFBZSxDQUFDN0IsSUFBSSxDQUFDO0lBQzVDLENBQUMsQ0FBQztJQUNGNkMsUUFBUSxFQUFFQyxxQkFBUSxDQUFDQztFQUNyQixDQUFDO0FBQ0giLCJpZ25vcmVMaXN0IjpbXX0=
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export type LocalWhisperMode = 'oneshot' | 'sse' | 'realtime';
|
|
3
|
+
export interface MLXSpeechRecognizerProps {
|
|
4
|
+
shouldListen: boolean;
|
|
5
|
+
speechStatusCallback: (status: boolean, transcript: string) => void;
|
|
6
|
+
speechResultCallback: (result: string) => void;
|
|
7
|
+
language?: string;
|
|
8
|
+
onError?: (error: Error) => void;
|
|
9
|
+
baseUrl?: string;
|
|
10
|
+
mode?: LocalWhisperMode;
|
|
11
|
+
modelName?: string;
|
|
12
|
+
minAudioSize?: number;
|
|
13
|
+
}
|
|
14
|
+
export declare const MLXSpeechRecognizer: React.FC<MLXSpeechRecognizerProps>;
|
|
15
|
+
export default MLXSpeechRecognizer;
|