@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,653 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = exports.OpenAINativeSpeechRecognizer = void 0;
7
+ exports.getOpenAINativeSpeechCapabilities = getOpenAINativeSpeechCapabilities;
8
+ exports.isOpenAINativeSpeechAvailable = isOpenAINativeSpeechAvailable;
9
+ var _react = _interopRequireWildcard(require("react"));
10
+ var _reactNative = require("react-native");
11
+ var _logger = _interopRequireDefault(require("../logger"));
12
+ var _groqTranscription = require("./utils/groq-transcription");
13
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
14
+ 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); }
15
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
16
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
17
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
18
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
19
+ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
20
+ function loadReactNativeWebRTC() {
21
+ try {
22
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
23
+ const module = require("react-native-webrtc");
24
+ const resolved = module?.default || module;
25
+ if (resolved?.RTCPeerConnection && resolved?.mediaDevices?.getUserMedia) {
26
+ return resolved;
27
+ }
28
+ return null;
29
+ } catch {
30
+ return null;
31
+ }
32
+ }
33
+ const nativeWebRTC = loadReactNativeWebRTC();
34
+ const DEFAULT_REALTIME_MODEL = "gpt-4o-transcribe";
35
+ const DEFAULT_REALTIME_WEBRTC_URL = "https://api.openai.com/v1/realtime?intent=transcription";
36
+ const DATA_CHANNEL_OPEN_TIMEOUT_MS = 6000;
37
+ const OpenAINativeSpeechRecognizer = ({
38
+ shouldListen,
39
+ speechStatusCallback,
40
+ speechResultCallback,
41
+ speechTranslationCallback,
42
+ speechReadyCallback,
43
+ clientSecret,
44
+ openaiTranscriptionSessionEndpoint,
45
+ openaiTranslationEndpoint,
46
+ openaiRealtimeWebRtcUrl = DEFAULT_REALTIME_WEBRTC_URL,
47
+ openaiRealtimeModel = DEFAULT_REALTIME_MODEL,
48
+ openaiTranslationModel = "gpt-4.1-mini",
49
+ openaiVadEnabled = true,
50
+ openaiAutoStopOnVadSilence = false,
51
+ openaiVadThreshold = 0.7,
52
+ openaiVadPrefixPaddingMs = 400,
53
+ openaiVadSilenceDurationMs = 1000,
54
+ openaiVadIdleTimeoutMs = 6000,
55
+ openaiPrewarmOnMount = false,
56
+ language = "en",
57
+ requestContextProvider,
58
+ onError
59
+ }) => {
60
+ const proxyAuthToken = clientSecret;
61
+ const [isRecording, setIsRecording] = (0, _react.useState)(false);
62
+ const [sessionRecoveryToken, setSessionRecoveryToken] = (0, _react.useState)(0);
63
+ const pcRef = (0, _react.useRef)(null);
64
+ const dataChannelRef = (0, _react.useRef)(null);
65
+ const streamRef = (0, _react.useRef)(null);
66
+ const sessionInitRef = (0, _react.useRef)(null);
67
+ const finalTranscriptRef = (0, _react.useRef)("");
68
+ const interimTranscriptRef = (0, _react.useRef)("");
69
+ const stopInFlightRef = (0, _react.useRef)(false);
70
+ const finalizedRef = (0, _react.useRef)(false);
71
+ const awaitingCommitFinalRef = (0, _react.useRef)(false);
72
+ const commitFinalTimeoutRef = (0, _react.useRef)(null);
73
+ const didPrewarmRef = (0, _react.useRef)(false);
74
+ const isRecordingRef = (0, _react.useRef)(false);
75
+ const shouldListenRef = (0, _react.useRef)(shouldListen);
76
+ const openaiPrewarmOnMountRef = (0, _react.useRef)(openaiPrewarmOnMount);
77
+ const sessionRecoveryModeRef = (0, _react.useRef)(null);
78
+ const sessionRecoveryInFlightRef = (0, _react.useRef)(false);
79
+ const suppressedChannelErrorRef = (0, _react.useRef)(null);
80
+ const emitError = (0, _react.useCallback)(error => {
81
+ const err = error instanceof Error ? error : new Error(String(error));
82
+ _logger.default.error("[OpenAI Native SR] error:", err);
83
+ onError?.(err);
84
+ }, [onError]);
85
+ const buildTurnDetection = (0, _react.useCallback)(() => {
86
+ if (!openaiVadEnabled) return null;
87
+ return {
88
+ type: "server_vad",
89
+ threshold: openaiVadThreshold,
90
+ prefix_padding_ms: openaiVadPrefixPaddingMs,
91
+ silence_duration_ms: openaiVadSilenceDurationMs
92
+ };
93
+ }, [openaiVadEnabled, openaiVadThreshold, openaiVadPrefixPaddingMs, openaiVadSilenceDurationMs]);
94
+ const waitForDataChannelOpen = (0, _react.useCallback)(async channel => {
95
+ if (channel?.readyState === "open") {
96
+ return;
97
+ }
98
+ const start = Date.now();
99
+ while (Date.now() - start < DATA_CHANNEL_OPEN_TIMEOUT_MS) {
100
+ if (channel?.readyState === "open") {
101
+ return;
102
+ }
103
+ await new Promise(resolve => setTimeout(resolve, 50));
104
+ }
105
+ throw new Error(`OpenAI native realtime data channel did not open within ${DATA_CHANNEL_OPEN_TIMEOUT_MS}ms (state=${String(channel?.readyState ?? "unknown")})`);
106
+ }, []);
107
+ const resetTranscriptRefs = (0, _react.useCallback)(() => {
108
+ finalTranscriptRef.current = "";
109
+ interimTranscriptRef.current = "";
110
+ finalizedRef.current = false;
111
+ }, []);
112
+ const getBufferedTranscript = (0, _react.useCallback)(() => {
113
+ return (finalTranscriptRef.current || interimTranscriptRef.current).trim();
114
+ }, []);
115
+ const clearCommitFinalWait = (0, _react.useCallback)(() => {
116
+ awaitingCommitFinalRef.current = false;
117
+ if (commitFinalTimeoutRef.current) {
118
+ clearTimeout(commitFinalTimeoutRef.current);
119
+ commitFinalTimeoutRef.current = null;
120
+ }
121
+ }, []);
122
+ const notifyReady = (0, _react.useCallback)(ready => {
123
+ speechReadyCallback?.(ready);
124
+ }, [speechReadyCallback]);
125
+ (0, _react.useEffect)(() => {
126
+ isRecordingRef.current = isRecording;
127
+ }, [isRecording]);
128
+ (0, _react.useEffect)(() => {
129
+ shouldListenRef.current = shouldListen;
130
+ }, [shouldListen]);
131
+ (0, _react.useEffect)(() => {
132
+ openaiPrewarmOnMountRef.current = openaiPrewarmOnMount;
133
+ }, [openaiPrewarmOnMount]);
134
+ const setAudioCaptureEnabled = (0, _react.useCallback)(enabled => {
135
+ const stream = streamRef.current;
136
+ if (!stream || typeof stream.getTracks !== "function") {
137
+ return;
138
+ }
139
+ try {
140
+ const tracks = stream.getTracks().filter(track => track?.kind === "audio");
141
+ tracks.forEach(track => {
142
+ try {
143
+ track.enabled = enabled;
144
+ } catch (error) {
145
+ _logger.default.warn("[OpenAI Native SR] toggle audio track warning:", error);
146
+ }
147
+ });
148
+ } catch (error) {
149
+ _logger.default.warn("[OpenAI Native SR] enumerate audio tracks warning:", error);
150
+ }
151
+ }, []);
152
+ const handleExpiredSession = (0, _react.useCallback)((channel, pc) => {
153
+ if (sessionRecoveryInFlightRef.current) {
154
+ return;
155
+ }
156
+ if (dataChannelRef.current !== channel) {
157
+ return;
158
+ }
159
+ sessionRecoveryInFlightRef.current = true;
160
+ suppressedChannelErrorRef.current = channel;
161
+ sessionRecoveryModeRef.current = shouldListenRef.current ? "listen" : openaiPrewarmOnMountRef.current ? "prewarm" : null;
162
+ clearCommitFinalWait();
163
+ resetTranscriptRefs();
164
+ setAudioCaptureEnabled(false);
165
+ sessionInitRef.current = null;
166
+ try {
167
+ channel?.close?.();
168
+ } catch (error) {
169
+ _logger.default.warn("[OpenAI Native SR] close data channel warning:", error);
170
+ }
171
+ try {
172
+ pc?.close?.();
173
+ } catch (error) {
174
+ _logger.default.warn("[OpenAI Native SR] close peer warning:", error);
175
+ }
176
+ try {
177
+ streamRef.current?.getTracks?.().forEach(track => track.stop?.());
178
+ } catch (error) {
179
+ _logger.default.warn("[OpenAI Native SR] stop stream warning:", error);
180
+ }
181
+ if (dataChannelRef.current === channel) {
182
+ dataChannelRef.current = null;
183
+ }
184
+ if (pcRef.current === pc) {
185
+ pcRef.current = null;
186
+ }
187
+ streamRef.current = null;
188
+ setIsRecording(false);
189
+ notifyReady(false);
190
+ speechStatusCallback(false, "");
191
+ if (sessionRecoveryModeRef.current) {
192
+ setSessionRecoveryToken(value => value + 1);
193
+ } else {
194
+ sessionRecoveryInFlightRef.current = false;
195
+ suppressedChannelErrorRef.current = null;
196
+ }
197
+ }, [clearCommitFinalWait, notifyReady, resetTranscriptRefs, setAudioCaptureEnabled, speechStatusCallback]);
198
+ const clearRealtimeInputBuffer = (0, _react.useCallback)(reason => {
199
+ if (dataChannelRef.current?.readyState !== "open") {
200
+ return;
201
+ }
202
+ try {
203
+ dataChannelRef.current.send(JSON.stringify({
204
+ type: "input_audio_buffer.clear"
205
+ }));
206
+ _logger.default.debug(`[OpenAI Native SR] cleared input buffer (${reason})`);
207
+ } catch (error) {
208
+ _logger.default.warn("[OpenAI Native SR] clear input buffer warning:", error);
209
+ }
210
+ }, []);
211
+ const getRequestContextHeaders = (0, _react.useCallback)(() => {
212
+ const context = requestContextProvider?.();
213
+ if (!context) return {};
214
+ const headers = {};
215
+ if (context.threadId) {
216
+ headers["x-thread-id"] = String(context.threadId);
217
+ }
218
+ if (context.turnId) {
219
+ headers["x-turn-id"] = String(context.turnId);
220
+ }
221
+ if (context.sessionId !== undefined && context.sessionId !== null) {
222
+ headers["x-voice-session-id"] = String(context.sessionId);
223
+ }
224
+ if (context.sentryTrace) {
225
+ headers["sentry-trace"] = String(context.sentryTrace);
226
+ }
227
+ if (context.baggage) {
228
+ headers.baggage = String(context.baggage);
229
+ }
230
+ return headers;
231
+ }, [requestContextProvider]);
232
+ const translateToEnglish = (0, _react.useCallback)(async text => {
233
+ const input = text.trim();
234
+ if (!input || !openaiTranslationEndpoint) return "";
235
+ if (language.toLowerCase().startsWith("en")) return "";
236
+ const headers = _objectSpread({
237
+ "content-type": "application/json"
238
+ }, getRequestContextHeaders());
239
+ if (proxyAuthToken) {
240
+ headers.Authorization = `Bearer ${proxyAuthToken}`;
241
+ }
242
+ const response = await fetch(openaiTranslationEndpoint, {
243
+ method: "POST",
244
+ headers,
245
+ body: JSON.stringify({
246
+ text: input,
247
+ sourceLanguage: language,
248
+ model: openaiTranslationModel
249
+ })
250
+ });
251
+ if (!response.ok) {
252
+ const body = await response.text().catch(() => "");
253
+ throw new Error(`translation failed (${response.status}): ${body}`);
254
+ }
255
+ const payload = await response.json().catch(() => null);
256
+ const translated = typeof payload?.text === "string" ? payload.text.trim() : "";
257
+ if (translated) {
258
+ speechTranslationCallback?.(translated);
259
+ }
260
+ return translated;
261
+ }, [proxyAuthToken, language, getRequestContextHeaders, openaiTranslationEndpoint, openaiTranslationModel, speechTranslationCallback]);
262
+ const emitFinal = (0, _react.useCallback)(async () => {
263
+ if (finalizedRef.current) return;
264
+ finalizedRef.current = true;
265
+ const finalText = (finalTranscriptRef.current || interimTranscriptRef.current).trim();
266
+ let parseText = finalText;
267
+ try {
268
+ const translated = await translateToEnglish(finalText);
269
+ if (translated) {
270
+ parseText = translated;
271
+ }
272
+ } catch (error) {
273
+ _logger.default.warn("[OpenAI Native SR] translation failed:", error);
274
+ } finally {
275
+ speechStatusCallback(false, "");
276
+ if (parseText) {
277
+ speechResultCallback(parseText);
278
+ }
279
+ }
280
+ }, [speechResultCallback, speechStatusCallback, translateToEnglish]);
281
+ const finalizeAndReset = (0, _react.useCallback)(async () => {
282
+ clearCommitFinalWait();
283
+ await emitFinal();
284
+ resetTranscriptRefs();
285
+ }, [clearCommitFinalWait, emitFinal, resetTranscriptRefs]);
286
+ const handleMessage = (0, _react.useCallback)(payload => {
287
+ const type = String(payload?.type || "");
288
+ const acceptsTranscript = isRecordingRef.current || awaitingCommitFinalRef.current;
289
+ if (!acceptsTranscript) {
290
+ return;
291
+ }
292
+ const shouldPublishInterim = isRecordingRef.current;
293
+ const delta = extractDeltaText(payload);
294
+ const completed = extractCompletedText(payload);
295
+ if (delta) {
296
+ interimTranscriptRef.current = (0, _groqTranscription.mergeTranscriptParts)(finalTranscriptRef.current, delta);
297
+ if (shouldPublishInterim) {
298
+ speechStatusCallback(true, interimTranscriptRef.current);
299
+ }
300
+ }
301
+ if (completed) {
302
+ finalTranscriptRef.current = (0, _groqTranscription.mergeTranscriptParts)(finalTranscriptRef.current, completed);
303
+ interimTranscriptRef.current = finalTranscriptRef.current;
304
+ if (shouldPublishInterim) {
305
+ speechStatusCallback(true, finalTranscriptRef.current);
306
+ }
307
+ }
308
+ const looksCompleted = !!completed || type.includes("completed");
309
+ if (awaitingCommitFinalRef.current && looksCompleted && getBufferedTranscript()) {
310
+ finalizeAndReset().catch(error => emitError(error));
311
+ return;
312
+ }
313
+ if (openaiAutoStopOnVadSilence && type === "input_audio_buffer.speech_stopped") {
314
+ const pauseTranscript = getBufferedTranscript();
315
+ speechStatusCallback(false, pauseTranscript);
316
+ }
317
+ }, [emitError, finalizeAndReset, getBufferedTranscript, openaiAutoStopOnVadSilence, speechStatusCallback]);
318
+ const startNativeWebRtcSession = (0, _react.useCallback)(async token => {
319
+ const webrtc = nativeWebRTC;
320
+ if (!webrtc?.RTCPeerConnection || !webrtc?.mediaDevices?.getUserMedia) {
321
+ throw new Error("react-native-webrtc is not installed. Install it for OpenAI native realtime speech.");
322
+ }
323
+ const stream = await webrtc.mediaDevices.getUserMedia({
324
+ audio: true,
325
+ video: false
326
+ });
327
+ streamRef.current = stream;
328
+ setAudioCaptureEnabled(false);
329
+ const pc = new webrtc.RTCPeerConnection();
330
+ pcRef.current = pc;
331
+ const tracks = typeof stream.getTracks === "function" ? stream.getTracks() : [];
332
+ tracks.forEach(track => pc.addTrack(track, stream));
333
+ const dataChannel = pc.createDataChannel("oai-events");
334
+ dataChannelRef.current = dataChannel;
335
+ dataChannel.onopen = () => {
336
+ notifyReady(true);
337
+ };
338
+ dataChannel.onmessage = event => {
339
+ try {
340
+ const payload = JSON.parse(String(event.data || "{}"));
341
+ if (payload?.type === "error") {
342
+ const message = String(payload?.error?.message || "OpenAI realtime error");
343
+ if (isCommitBufferTooSmallError(message)) {
344
+ // Ignore commit buffer-too-small errors for low-latency fast-stop path.
345
+ return;
346
+ }
347
+ if (isSessionDurationLimitError(message)) {
348
+ handleExpiredSession(dataChannel, pc);
349
+ return;
350
+ }
351
+ throw new Error(message);
352
+ }
353
+ handleMessage(payload);
354
+ } catch (error) {
355
+ emitError(error);
356
+ }
357
+ };
358
+ dataChannel.onerror = () => {
359
+ if (suppressedChannelErrorRef.current === dataChannel) {
360
+ return;
361
+ }
362
+ notifyReady(false);
363
+ emitError(new Error("OpenAI native realtime data channel error"));
364
+ };
365
+ dataChannel.onclose = () => {
366
+ notifyReady(false);
367
+ };
368
+ const offer = await pc.createOffer();
369
+ await pc.setLocalDescription(offer);
370
+ const response = await fetch(openaiRealtimeWebRtcUrl, {
371
+ method: "POST",
372
+ headers: {
373
+ Authorization: `Bearer ${token}`,
374
+ "content-type": "application/sdp"
375
+ },
376
+ body: offer?.sdp || ""
377
+ });
378
+ if (!response.ok) {
379
+ const body = await response.text().catch(() => "");
380
+ throw new Error(`webrtc negotiation failed (${response.status}): ${body}`);
381
+ }
382
+ const answerSdp = await response.text();
383
+ await pc.setRemoteDescription({
384
+ type: "answer",
385
+ sdp: answerSdp
386
+ });
387
+ await waitForDataChannelOpen(dataChannel);
388
+ }, [emitError, handleMessage, notifyReady, openaiRealtimeWebRtcUrl, setAudioCaptureEnabled, waitForDataChannelOpen]);
389
+ const getEphemeralToken = (0, _react.useCallback)(async () => {
390
+ const headers = _objectSpread({
391
+ "content-type": "application/json"
392
+ }, getRequestContextHeaders());
393
+ if (proxyAuthToken) {
394
+ headers.Authorization = `Bearer ${proxyAuthToken}`;
395
+ }
396
+ const response = await fetch(openaiTranscriptionSessionEndpoint, {
397
+ method: "POST",
398
+ headers,
399
+ body: JSON.stringify({
400
+ input_audio_format: "pcm16",
401
+ input_audio_transcription: {
402
+ model: openaiRealtimeModel,
403
+ language
404
+ },
405
+ turn_detection: buildTurnDetection() || undefined
406
+ })
407
+ });
408
+ if (!response.ok) {
409
+ const body = await response.text().catch(() => "");
410
+ throw new Error(`transcription session request failed (${response.status}): ${body}`);
411
+ }
412
+ const payload = await response.json().catch(() => ({}));
413
+ const token = payload?.client_secret?.value || payload?.client_secret || payload?.value || "";
414
+ if (!token) {
415
+ throw new Error("No ephemeral token returned from transcription session endpoint");
416
+ }
417
+ return token;
418
+ }, [buildTurnDetection, getRequestContextHeaders, proxyAuthToken, language, openaiRealtimeModel, openaiTranscriptionSessionEndpoint]);
419
+ const hasReusableSession = (0, _react.useCallback)(() => {
420
+ return !!pcRef.current && !!streamRef.current && dataChannelRef.current?.readyState === "open";
421
+ }, []);
422
+ const ensureNativeWebRtcSession = (0, _react.useCallback)(async () => {
423
+ if (hasReusableSession()) {
424
+ return;
425
+ }
426
+ if (sessionInitRef.current) {
427
+ await sessionInitRef.current;
428
+ return;
429
+ }
430
+ sessionInitRef.current = (async () => {
431
+ const token = await getEphemeralToken();
432
+ await startNativeWebRtcSession(token);
433
+ })();
434
+ try {
435
+ await sessionInitRef.current;
436
+ } finally {
437
+ sessionInitRef.current = null;
438
+ }
439
+ }, [getEphemeralToken, hasReusableSession, startNativeWebRtcSession]);
440
+ const cleanup = (0, _react.useCallback)(() => {
441
+ sessionInitRef.current = null;
442
+ try {
443
+ if (dataChannelRef.current) {
444
+ dataChannelRef.current.close();
445
+ }
446
+ } catch (error) {
447
+ _logger.default.warn("[OpenAI Native SR] close data channel warning:", error);
448
+ } finally {
449
+ dataChannelRef.current = null;
450
+ }
451
+ try {
452
+ if (pcRef.current) {
453
+ pcRef.current.close();
454
+ }
455
+ } catch (error) {
456
+ _logger.default.warn("[OpenAI Native SR] close peer warning:", error);
457
+ } finally {
458
+ pcRef.current = null;
459
+ }
460
+ try {
461
+ if (streamRef.current?.getTracks) {
462
+ streamRef.current.getTracks().forEach(track => track.stop?.());
463
+ }
464
+ } catch (error) {
465
+ _logger.default.warn("[OpenAI Native SR] stop stream warning:", error);
466
+ } finally {
467
+ streamRef.current = null;
468
+ }
469
+ }, []);
470
+ (0, _react.useEffect)(() => {
471
+ if (sessionRecoveryToken === 0 || !sessionRecoveryModeRef.current) {
472
+ return;
473
+ }
474
+ let cancelled = false;
475
+ const recoveryMode = sessionRecoveryModeRef.current;
476
+ (async () => {
477
+ try {
478
+ await ensureNativeWebRtcSession();
479
+ if (cancelled) {
480
+ return;
481
+ }
482
+ if (recoveryMode === "listen" && shouldListenRef.current) {
483
+ setAudioCaptureEnabled(true);
484
+ setIsRecording(true);
485
+ }
486
+ notifyReady(dataChannelRef.current?.readyState === "open");
487
+ } catch (error) {
488
+ if (cancelled) {
489
+ return;
490
+ }
491
+ emitError(error);
492
+ setAudioCaptureEnabled(false);
493
+ cleanup();
494
+ setIsRecording(false);
495
+ notifyReady(false);
496
+ speechStatusCallback(false, "");
497
+ } finally {
498
+ if (cancelled) {
499
+ return;
500
+ }
501
+ sessionRecoveryModeRef.current = null;
502
+ sessionRecoveryInFlightRef.current = false;
503
+ suppressedChannelErrorRef.current = null;
504
+ }
505
+ })();
506
+ return () => {
507
+ cancelled = true;
508
+ };
509
+ }, [cleanup, emitError, ensureNativeWebRtcSession, notifyReady, sessionRecoveryToken, setAudioCaptureEnabled, speechStatusCallback]);
510
+ const startRecording = (0, _react.useCallback)(async () => {
511
+ if (isRecording || stopInFlightRef.current || sessionRecoveryInFlightRef.current) {
512
+ return;
513
+ }
514
+ resetTranscriptRefs();
515
+ try {
516
+ clearCommitFinalWait();
517
+ notifyReady(false);
518
+ const reusingWarmSession = hasReusableSession();
519
+ await ensureNativeWebRtcSession();
520
+ if (reusingWarmSession) {
521
+ clearRealtimeInputBuffer("start_recording");
522
+ }
523
+ if (!shouldListenRef.current) {
524
+ setAudioCaptureEnabled(false);
525
+ notifyReady(dataChannelRef.current?.readyState === "open");
526
+ return;
527
+ }
528
+ setAudioCaptureEnabled(true);
529
+ setIsRecording(true);
530
+ notifyReady(dataChannelRef.current?.readyState === "open");
531
+ } catch (error) {
532
+ emitError(error);
533
+ setAudioCaptureEnabled(false);
534
+ cleanup();
535
+ setIsRecording(false);
536
+ notifyReady(false);
537
+ speechStatusCallback(false, "");
538
+ }
539
+ }, [cleanup, clearCommitFinalWait, clearRealtimeInputBuffer, ensureNativeWebRtcSession, emitError, hasReusableSession, isRecording, notifyReady, resetTranscriptRefs, setAudioCaptureEnabled, speechStatusCallback]);
540
+ const stopRecording = (0, _react.useCallback)(async () => {
541
+ if (!isRecording || stopInFlightRef.current) return;
542
+ stopInFlightRef.current = true;
543
+ setIsRecording(false);
544
+ setAudioCaptureEnabled(false);
545
+ notifyReady(false);
546
+ try {
547
+ if (dataChannelRef.current?.readyState === "open") {
548
+ dataChannelRef.current.send(JSON.stringify({
549
+ type: "input_audio_buffer.commit"
550
+ }));
551
+ }
552
+ const buffered = getBufferedTranscript();
553
+ if (buffered) {
554
+ await finalizeAndReset();
555
+ } else {
556
+ speechStatusCallback(false, "");
557
+ awaitingCommitFinalRef.current = true;
558
+ if (commitFinalTimeoutRef.current) {
559
+ clearTimeout(commitFinalTimeoutRef.current);
560
+ }
561
+ // Short fallback: if no post-commit transcript arrives, reset state and exit.
562
+ commitFinalTimeoutRef.current = setTimeout(() => {
563
+ if (!awaitingCommitFinalRef.current) return;
564
+ clearCommitFinalWait();
565
+ resetTranscriptRefs();
566
+ }, 1500);
567
+ }
568
+ } catch (error) {
569
+ emitError(error);
570
+ speechStatusCallback(false, "");
571
+ } finally {
572
+ stopInFlightRef.current = false;
573
+ notifyReady(false);
574
+ }
575
+ }, [emitError, finalizeAndReset, getBufferedTranscript, isRecording, notifyReady, clearCommitFinalWait, resetTranscriptRefs, setAudioCaptureEnabled, speechStatusCallback]);
576
+ (0, _react.useEffect)(() => {
577
+ if (!openaiPrewarmOnMount || didPrewarmRef.current) {
578
+ return;
579
+ }
580
+ didPrewarmRef.current = true;
581
+ ensureNativeWebRtcSession().then(() => {
582
+ notifyReady(true);
583
+ }).catch(error => {
584
+ emitError(error);
585
+ });
586
+ }, [emitError, ensureNativeWebRtcSession, notifyReady, openaiPrewarmOnMount]);
587
+ (0, _react.useEffect)(() => {
588
+ if (shouldListen && !isRecording) {
589
+ startRecording();
590
+ } else if (!shouldListen && isRecording) {
591
+ stopRecording();
592
+ }
593
+ }, [isRecording, shouldListen, startRecording, stopRecording]);
594
+ (0, _react.useEffect)(() => {
595
+ return () => {
596
+ notifyReady(false);
597
+ clearCommitFinalWait();
598
+ setAudioCaptureEnabled(false);
599
+ cleanup();
600
+ };
601
+ }, [cleanup, notifyReady, clearCommitFinalWait, setAudioCaptureEnabled]);
602
+ return /*#__PURE__*/_react.default.createElement(_reactNative.View, null);
603
+ };
604
+ exports.OpenAINativeSpeechRecognizer = OpenAINativeSpeechRecognizer;
605
+ function extractDeltaText(payload) {
606
+ const type = String(payload?.type || "");
607
+ if (!type.includes("delta")) return "";
608
+ const candidates = [payload?.delta, payload?.text_delta, payload?.transcript_delta, payload?.item?.content?.[0]?.transcript];
609
+ for (const value of candidates) {
610
+ if (typeof value === "string" && value.trim()) return value.trim();
611
+ }
612
+ return "";
613
+ }
614
+ function extractCompletedText(payload) {
615
+ const type = String(payload?.type || "");
616
+ if (!type.includes("completed")) return "";
617
+ const candidates = [payload?.transcript, payload?.text, payload?.item?.content?.[0]?.transcript, payload?.item?.transcript];
618
+ for (const value of candidates) {
619
+ if (typeof value === "string" && value.trim()) return value.trim();
620
+ }
621
+ return "";
622
+ }
623
+ function extractItemId(payload) {
624
+ const candidates = [payload?.item_id, payload?.item?.id];
625
+ for (const value of candidates) {
626
+ if (typeof value === "string" && value.trim()) {
627
+ return value.trim();
628
+ }
629
+ }
630
+ return null;
631
+ }
632
+ function isCommitBufferTooSmallError(message) {
633
+ const normalized = message.toLowerCase();
634
+ return normalized.includes("input audio buffer") && normalized.includes("buffer too small");
635
+ }
636
+ function isSessionDurationLimitError(message) {
637
+ const normalized = message.toLowerCase();
638
+ return normalized.includes("session") && (normalized.includes("maximum duration") || normalized.includes("max duration"));
639
+ }
640
+ function isOpenAINativeSpeechAvailable() {
641
+ return (_reactNative.Platform.OS === "ios" || _reactNative.Platform.OS === "android") && !!nativeWebRTC?.RTCPeerConnection && !!nativeWebRTC?.mediaDevices?.getUserMedia;
642
+ }
643
+ function getOpenAINativeSpeechCapabilities() {
644
+ return {
645
+ available: isOpenAINativeSpeechAvailable(),
646
+ platform: _reactNative.Platform.OS,
647
+ supportsServerVAD: true,
648
+ transport: "webrtc",
649
+ requiresWebRTCDependency: true
650
+ };
651
+ }
652
+ var _default = exports.default = OpenAINativeSpeechRecognizer;
653
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZCIsInJlcXVpcmUiLCJfcmVhY3ROYXRpdmUiLCJfbG9nZ2VyIiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsIl9ncm9xVHJhbnNjcmlwdGlvbiIsImUiLCJfX2VzTW9kdWxlIiwiZGVmYXVsdCIsInQiLCJXZWFrTWFwIiwiciIsIm4iLCJvIiwiaSIsImYiLCJfX3Byb3RvX18iLCJoYXMiLCJnZXQiLCJzZXQiLCJoYXNPd25Qcm9wZXJ0eSIsImNhbGwiLCJPYmplY3QiLCJkZWZpbmVQcm9wZXJ0eSIsImdldE93blByb3BlcnR5RGVzY3JpcHRvciIsIm93bktleXMiLCJrZXlzIiwiZ2V0T3duUHJvcGVydHlTeW1ib2xzIiwiZmlsdGVyIiwiZW51bWVyYWJsZSIsInB1c2giLCJhcHBseSIsIl9vYmplY3RTcHJlYWQiLCJhcmd1bWVudHMiLCJsZW5ndGgiLCJmb3JFYWNoIiwiX2RlZmluZVByb3BlcnR5IiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyIsImRlZmluZVByb3BlcnRpZXMiLCJfdG9Qcm9wZXJ0eUtleSIsInZhbHVlIiwiY29uZmlndXJhYmxlIiwid3JpdGFibGUiLCJfdG9QcmltaXRpdmUiLCJTeW1ib2wiLCJ0b1ByaW1pdGl2ZSIsIlR5cGVFcnJvciIsIlN0cmluZyIsIk51bWJlciIsImxvYWRSZWFjdE5hdGl2ZVdlYlJUQyIsIm1vZHVsZSIsInJlc29sdmVkIiwiUlRDUGVlckNvbm5lY3Rpb24iLCJtZWRpYURldmljZXMiLCJnZXRVc2VyTWVkaWEiLCJuYXRpdmVXZWJSVEMiLCJERUZBVUxUX1JFQUxUSU1FX01PREVMIiwiREVGQVVMVF9SRUFMVElNRV9XRUJSVENfVVJMIiwiREFUQV9DSEFOTkVMX09QRU5fVElNRU9VVF9NUyIsIk9wZW5BSU5hdGl2ZVNwZWVjaFJlY29nbml6ZXIiLCJzaG91bGRMaXN0ZW4iLCJzcGVlY2hTdGF0dXNDYWxsYmFjayIsInNwZWVjaFJlc3VsdENhbGxiYWNrIiwic3BlZWNoVHJhbnNsYXRpb25DYWxsYmFjayIsInNwZWVjaFJlYWR5Q2FsbGJhY2siLCJjbGllbnRTZWNyZXQiLCJvcGVuYWlUcmFuc2NyaXB0aW9uU2Vzc2lvbkVuZHBvaW50Iiwib3BlbmFpVHJhbnNsYXRpb25FbmRwb2ludCIsIm9wZW5haVJlYWx0aW1lV2ViUnRjVXJsIiwib3BlbmFpUmVhbHRpbWVNb2RlbCIsIm9wZW5haVRyYW5zbGF0aW9uTW9kZWwiLCJvcGVuYWlWYWRFbmFibGVkIiwib3BlbmFpQXV0b1N0b3BPblZhZFNpbGVuY2UiLCJvcGVuYWlWYWRUaHJlc2hvbGQiLCJvcGVuYWlWYWRQcmVmaXhQYWRkaW5nTXMiLCJvcGVuYWlWYWRTaWxlbmNlRHVyYXRpb25NcyIsIm9wZW5haVZhZElkbGVUaW1lb3V0TXMiLCJvcGVuYWlQcmV3YXJtT25Nb3VudCIsImxhbmd1YWdlIiwicmVxdWVzdENvbnRleHRQcm92aWRlciIsIm9uRXJyb3IiLCJwcm94eUF1dGhUb2tlbiIsImlzUmVjb3JkaW5nIiwic2V0SXNSZWNvcmRpbmciLCJ1c2VTdGF0ZSIsInNlc3Npb25SZWNvdmVyeVRva2VuIiwic2V0U2Vzc2lvblJlY292ZXJ5VG9rZW4iLCJwY1JlZiIsInVzZVJlZiIsImRhdGFDaGFubmVsUmVmIiwic3RyZWFtUmVmIiwic2Vzc2lvbkluaXRSZWYiLCJmaW5hbFRyYW5zY3JpcHRSZWYiLCJpbnRlcmltVHJhbnNjcmlwdFJlZiIsInN0b3BJbkZsaWdodFJlZiIsImZpbmFsaXplZFJlZiIsImF3YWl0aW5nQ29tbWl0RmluYWxSZWYiLCJjb21taXRGaW5hbFRpbWVvdXRSZWYiLCJkaWRQcmV3YXJtUmVmIiwiaXNSZWNvcmRpbmdSZWYiLCJzaG91bGRMaXN0ZW5SZWYiLCJvcGVuYWlQcmV3YXJtT25Nb3VudFJlZiIsInNlc3Npb25SZWNvdmVyeU1vZGVSZWYiLCJzZXNzaW9uUmVjb3ZlcnlJbkZsaWdodFJlZiIsInN1cHByZXNzZWRDaGFubmVsRXJyb3JSZWYiLCJlbWl0RXJyb3IiLCJ1c2VDYWxsYmFjayIsImVycm9yIiwiZXJyIiwiRXJyb3IiLCJsb2dnZXIiLCJidWlsZFR1cm5EZXRlY3Rpb24iLCJ0eXBlIiwidGhyZXNob2xkIiwicHJlZml4X3BhZGRpbmdfbXMiLCJzaWxlbmNlX2R1cmF0aW9uX21zIiwid2FpdEZvckRhdGFDaGFubmVsT3BlbiIsImNoYW5uZWwiLCJyZWFkeVN0YXRlIiwic3RhcnQiLCJEYXRlIiwibm93IiwiUHJvbWlzZSIsInJlc29sdmUiLCJzZXRUaW1lb3V0IiwicmVzZXRUcmFuc2NyaXB0UmVmcyIsImN1cnJlbnQiLCJnZXRCdWZmZXJlZFRyYW5zY3JpcHQiLCJ0cmltIiwiY2xlYXJDb21taXRGaW5hbFdhaXQiLCJjbGVhclRpbWVvdXQiLCJub3RpZnlSZWFkeSIsInJlYWR5IiwidXNlRWZmZWN0Iiwic2V0QXVkaW9DYXB0dXJlRW5hYmxlZCIsImVuYWJsZWQiLCJzdHJlYW0iLCJnZXRUcmFja3MiLCJ0cmFja3MiLCJ0cmFjayIsImtpbmQiLCJ3YXJuIiwiaGFuZGxlRXhwaXJlZFNlc3Npb24iLCJwYyIsImNsb3NlIiwic3RvcCIsImNsZWFyUmVhbHRpbWVJbnB1dEJ1ZmZlciIsInJlYXNvbiIsInNlbmQiLCJKU09OIiwic3RyaW5naWZ5IiwiZGVidWciLCJnZXRSZXF1ZXN0Q29udGV4dEhlYWRlcnMiLCJjb250ZXh0IiwiaGVhZGVycyIsInRocmVhZElkIiwidHVybklkIiwic2Vzc2lvbklkIiwidW5kZWZpbmVkIiwic2VudHJ5VHJhY2UiLCJiYWdnYWdlIiwidHJhbnNsYXRlVG9FbmdsaXNoIiwidGV4dCIsImlucHV0IiwidG9Mb3dlckNhc2UiLCJzdGFydHNXaXRoIiwiQXV0aG9yaXphdGlvbiIsInJlc3BvbnNlIiwiZmV0Y2giLCJtZXRob2QiLCJib2R5Iiwic291cmNlTGFuZ3VhZ2UiLCJtb2RlbCIsIm9rIiwiY2F0Y2giLCJzdGF0dXMiLCJwYXlsb2FkIiwianNvbiIsInRyYW5zbGF0ZWQiLCJlbWl0RmluYWwiLCJmaW5hbFRleHQiLCJwYXJzZVRleHQiLCJmaW5hbGl6ZUFuZFJlc2V0IiwiaGFuZGxlTWVzc2FnZSIsImFjY2VwdHNUcmFuc2NyaXB0Iiwic2hvdWxkUHVibGlzaEludGVyaW0iLCJkZWx0YSIsImV4dHJhY3REZWx0YVRleHQiLCJjb21wbGV0ZWQiLCJleHRyYWN0Q29tcGxldGVkVGV4dCIsIm1lcmdlVHJhbnNjcmlwdFBhcnRzIiwibG9va3NDb21wbGV0ZWQiLCJpbmNsdWRlcyIsInBhdXNlVHJhbnNjcmlwdCIsInN0YXJ0TmF0aXZlV2ViUnRjU2Vzc2lvbiIsInRva2VuIiwid2VicnRjIiwiYXVkaW8iLCJ2aWRlbyIsImFkZFRyYWNrIiwiZGF0YUNoYW5uZWwiLCJjcmVhdGVEYXRhQ2hhbm5lbCIsIm9ub3BlbiIsIm9ubWVzc2FnZSIsImV2ZW50IiwicGFyc2UiLCJkYXRhIiwibWVzc2FnZSIsImlzQ29tbWl0QnVmZmVyVG9vU21hbGxFcnJvciIsImlzU2Vzc2lvbkR1cmF0aW9uTGltaXRFcnJvciIsIm9uZXJyb3IiLCJvbmNsb3NlIiwib2ZmZXIiLCJjcmVhdGVPZmZlciIsInNldExvY2FsRGVzY3JpcHRpb24iLCJzZHAiLCJhbnN3ZXJTZHAiLCJzZXRSZW1vdGVEZXNjcmlwdGlvbiIsImdldEVwaGVtZXJhbFRva2VuIiwiaW5wdXRfYXVkaW9fZm9ybWF0IiwiaW5wdXRfYXVkaW9fdHJhbnNjcmlwdGlvbiIsInR1cm5fZGV0ZWN0aW9uIiwiY2xpZW50X3NlY3JldCIsImhhc1JldXNhYmxlU2Vzc2lvbiIsImVuc3VyZU5hdGl2ZVdlYlJ0Y1Nlc3Npb24iLCJjbGVhbnVwIiwiY2FuY2VsbGVkIiwicmVjb3ZlcnlNb2RlIiwic3RhcnRSZWNvcmRpbmciLCJyZXVzaW5nV2FybVNlc3Npb24iLCJzdG9wUmVjb3JkaW5nIiwiYnVmZmVyZWQiLCJ0aGVuIiwiY3JlYXRlRWxlbWVudCIsIlZpZXciLCJleHBvcnRzIiwiY2FuZGlkYXRlcyIsInRleHRfZGVsdGEiLCJ0cmFuc2NyaXB0X2RlbHRhIiwiaXRlbSIsImNvbnRlbnQiLCJ0cmFuc2NyaXB0IiwiZXh0cmFjdEl0ZW1JZCIsIml0ZW1faWQiLCJpZCIsIm5vcm1hbGl6ZWQiLCJpc09wZW5BSU5hdGl2ZVNwZWVjaEF2YWlsYWJsZSIsIlBsYXRmb3JtIiwiT1MiLCJnZXRPcGVuQUlOYXRpdmVTcGVlY2hDYXBhYmlsaXRpZXMiLCJhdmFpbGFibGUiLCJwbGF0Zm9ybSIsInN1cHBvcnRzU2VydmVyVkFEIiwidHJhbnNwb3J0IiwicmVxdWlyZXNXZWJSVENEZXBlbmRlbmN5IiwiX2RlZmF1bHQiXSwic291cmNlcyI6WyIuLi8uLi9zcmMvc3BlZWNoLXJlY29nbml0aW9uL3NwZWVjaC1yZWNvZ25pdGlvbi1vcGVuYWktbmF0aXZlLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgUmVhY3QsIHsgdXNlQ2FsbGJhY2ssIHVzZUVmZmVjdCwgdXNlUmVmLCB1c2VTdGF0ZSB9IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IHsgUGxhdGZvcm0sIFZpZXcgfSBmcm9tIFwicmVhY3QtbmF0aXZlXCI7XG5pbXBvcnQgbG9nZ2VyIGZyb20gXCIuLi9sb2dnZXJcIjtcbmltcG9ydCB7IG1lcmdlVHJhbnNjcmlwdFBhcnRzIH0gZnJvbSBcIi4vdXRpbHMvZ3JvcS10cmFuc2NyaXB0aW9uXCI7XG5cbnR5cGUgUmVhY3ROYXRpdmVXZWJSVENNb2R1bGUgPSB7XG4gIFJUQ1BlZXJDb25uZWN0aW9uOiBuZXcgKC4uLmFyZ3M6IGFueVtdKSA9PiBhbnk7XG4gIG1lZGlhRGV2aWNlczoge1xuICAgIGdldFVzZXJNZWRpYTogKGNvbnN0cmFpbnRzOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KSA9PiBQcm9taXNlPGFueT47XG4gIH07XG59O1xuXG5mdW5jdGlvbiBsb2FkUmVhY3ROYXRpdmVXZWJSVEMoKTogUmVhY3ROYXRpdmVXZWJSVENNb2R1bGUgfCBudWxsIHtcbiAgdHJ5IHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXZhci1yZXF1aXJlc1xuICAgIGNvbnN0IG1vZHVsZSA9IHJlcXVpcmUoXCJyZWFjdC1uYXRpdmUtd2VicnRjXCIpO1xuICAgIGNvbnN0IHJlc29sdmVkID0gbW9kdWxlPy5kZWZhdWx0IHx8IG1vZHVsZTtcbiAgICBpZiAoXG4gICAgICByZXNvbHZlZD8uUlRDUGVlckNvbm5lY3Rpb24gJiZcbiAgICAgIHJlc29sdmVkPy5tZWRpYURldmljZXM/LmdldFVzZXJNZWRpYVxuICAgICkge1xuICAgICAgcmV0dXJuIHJlc29sdmVkIGFzIFJlYWN0TmF0aXZlV2ViUlRDTW9kdWxlO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbn1cblxuY29uc3QgbmF0aXZlV2ViUlRDID0gbG9hZFJlYWN0TmF0aXZlV2ViUlRDKCk7XG5jb25zdCBERUZBVUxUX1JFQUxUSU1FX01PREVMID0gXCJncHQtNG8tdHJhbnNjcmliZVwiO1xuY29uc3QgREVGQVVMVF9SRUFMVElNRV9XRUJSVENfVVJMID1cbiAgXCJodHRwczovL2FwaS5vcGVuYWkuY29tL3YxL3JlYWx0aW1lP2ludGVudD10cmFuc2NyaXB0aW9uXCI7XG5jb25zdCBEQVRBX0NIQU5ORUxfT1BFTl9USU1FT1VUX01TID0gNjAwMDtcblxuZXhwb3J0IGludGVyZmFjZSBPcGVuQUlOYXRpdmVTcGVlY2hSZWNvZ25pemVyUHJvcHMge1xuICBzaG91bGRMaXN0ZW46IGJvb2xlYW47XG4gIHNwZWVjaFN0YXR1c0NhbGxiYWNrOiAoc3RhdHVzOiBib29sZWFuLCB0cmFuc2NyaXB0OiBzdHJpbmcpID0+IHZvaWQ7XG4gIHNwZWVjaFJlc3VsdENhbGxiYWNrOiAocmVzdWx0OiBzdHJpbmcpID0+IHZvaWQ7XG4gIHNwZWVjaFRyYW5zbGF0aW9uQ2FsbGJhY2s/OiAodHJhbnNsYXRpb246IHN0cmluZykgPT4gdm9pZDtcbiAgc3BlZWNoUmVhZHlDYWxsYmFjaz86IChyZWFkeTogYm9vbGVhbikgPT4gdm9pZDtcbiAgY2xpZW50U2VjcmV0Pzogc3RyaW5nO1xuICBvcGVuYWlUcmFuc2NyaXB0aW9uU2Vzc2lvbkVuZHBvaW50OiBzdHJpbmc7XG4gIG9wZW5haVRyYW5zbGF0aW9uRW5kcG9pbnQ/OiBzdHJpbmc7XG4gIG9wZW5haVJlYWx0aW1lV2ViUnRjVXJsPzogc3RyaW5nO1xuICBvcGVuYWlSZWFsdGltZU1vZGVsPzogXCJncHQtNG8tdHJhbnNjcmliZVwiIHwgXCJncHQtNG8tbWluaS10cmFuc2NyaWJlXCI7XG4gIG9wZW5haVRyYW5zbGF0aW9uTW9kZWw/OiBzdHJpbmc7XG4gIG9wZW5haVZhZEVuYWJsZWQ/OiBib29sZWFuO1xuICBvcGVuYWlBdXRvU3RvcE9uVmFkU2lsZW5jZT86IGJvb2xlYW47XG4gIG9wZW5haVZhZFRocmVzaG9sZD86IG51bWJlcjtcbiAgb3BlbmFpVmFkUHJlZml4UGFkZGluZ01zPzogbnVtYmVyO1xuICBvcGVuYWlWYWRTaWxlbmNlRHVyYXRpb25Ncz86IG51bWJlcjtcbiAgb3BlbmFpVmFkSWRsZVRpbWVvdXRNcz86IG51bWJlcjtcbiAgb3BlbmFpUHJld2FybU9uTW91bnQ/OiBib29sZWFuO1xuICBsYW5ndWFnZT86IHN0cmluZztcbiAgcmVxdWVzdENvbnRleHRQcm92aWRlcj86ICgpID0+XG4gICAgfCB7XG4gICAgICAgIHRocmVhZElkPzogc3RyaW5nIHwgbnVsbDtcbiAgICAgICAgdHVybklkPzogc3RyaW5nIHwgbnVsbDtcbiAgICAgICAgc2Vzc2lvbklkPzogc3RyaW5nIHwgbnVtYmVyIHwgbnVsbDtcbiAgICAgICAgc2VudHJ5VHJhY2U/OiBzdHJpbmcgfCBudWxsO1xuICAgICAgICBiYWdnYWdlPzogc3RyaW5nIHwgbnVsbDtcbiAgICAgIH1cbiAgICB8IG51bGxcbiAgICB8IHVuZGVmaW5lZDtcbiAgb25FcnJvcj86IChlcnJvcjogRXJyb3IpID0+IHZvaWQ7XG59XG5cbmV4cG9ydCBjb25zdCBPcGVuQUlOYXRpdmVTcGVlY2hSZWNvZ25pemVyOiBSZWFjdC5GQzxcbiAgT3BlbkFJTmF0aXZlU3BlZWNoUmVjb2duaXplclByb3BzXG4+ID0gKHtcbiAgc2hvdWxkTGlzdGVuLFxuICBzcGVlY2hTdGF0dXNDYWxsYmFjayxcbiAgc3BlZWNoUmVzdWx0Q2FsbGJhY2ssXG4gIHNwZWVjaFRyYW5zbGF0aW9uQ2FsbGJhY2ssXG4gIHNwZWVjaFJlYWR5Q2FsbGJhY2ssXG4gIGNsaWVudFNlY3JldCxcbiAgb3BlbmFpVHJhbnNjcmlwdGlvblNlc3Npb25FbmRwb2ludCxcbiAgb3BlbmFpVHJhbnNsYXRpb25FbmRwb2ludCxcbiAgb3BlbmFpUmVhbHRpbWVXZWJSdGNVcmwgPSBERUZBVUxUX1JFQUxUSU1FX1dFQlJUQ19VUkwsXG4gIG9wZW5haVJlYWx0aW1lTW9kZWwgPSBERUZBVUxUX1JFQUxUSU1FX01PREVMLFxuICBvcGVuYWlUcmFuc2xhdGlvbk1vZGVsID0gXCJncHQtNC4xLW1pbmlcIixcbiAgb3BlbmFpVmFkRW5hYmxlZCA9IHRydWUsXG4gIG9wZW5haUF1dG9TdG9wT25WYWRTaWxlbmNlID0gZmFsc2UsXG4gIG9wZW5haVZhZFRocmVzaG9sZCA9IDAuNyxcbiAgb3BlbmFpVmFkUHJlZml4UGFkZGluZ01zID0gNDAwLFxuICBvcGVuYWlWYWRTaWxlbmNlRHVyYXRpb25NcyA9IDEwMDAsXG4gIG9wZW5haVZhZElkbGVUaW1lb3V0TXMgPSA2MDAwLFxuICBvcGVuYWlQcmV3YXJtT25Nb3VudCA9IGZhbHNlLFxuICBsYW5ndWFnZSA9IFwiZW5cIixcbiAgcmVxdWVzdENvbnRleHRQcm92aWRlcixcbiAgb25FcnJvcixcbn0pID0+IHtcbiAgY29uc3QgcHJveHlBdXRoVG9rZW4gPSBjbGllbnRTZWNyZXQ7XG4gIGNvbnN0IFtpc1JlY29yZGluZywgc2V0SXNSZWNvcmRpbmddID0gdXNlU3RhdGUoZmFsc2UpO1xuICBjb25zdCBbc2Vzc2lvblJlY292ZXJ5VG9rZW4sIHNldFNlc3Npb25SZWNvdmVyeVRva2VuXSA9IHVzZVN0YXRlKDApO1xuICBjb25zdCBwY1JlZiA9IHVzZVJlZjxhbnk+KG51bGwpO1xuICBjb25zdCBkYXRhQ2hhbm5lbFJlZiA9IHVzZVJlZjxhbnk+KG51bGwpO1xuICBjb25zdCBzdHJlYW1SZWYgPSB1c2VSZWY8YW55PihudWxsKTtcbiAgY29uc3Qgc2Vzc2lvbkluaXRSZWYgPSB1c2VSZWY8UHJvbWlzZTx2b2lkPiB8IG51bGw+KG51bGwpO1xuICBjb25zdCBmaW5hbFRyYW5zY3JpcHRSZWYgPSB1c2VSZWYoXCJcIik7XG4gIGNvbnN0IGludGVyaW1UcmFuc2NyaXB0UmVmID0gdXNlUmVmKFwiXCIpO1xuICBjb25zdCBzdG9wSW5GbGlnaHRSZWYgPSB1c2VSZWYoZmFsc2UpO1xuICBjb25zdCBmaW5hbGl6ZWRSZWYgPSB1c2VSZWYoZmFsc2UpO1xuICBjb25zdCBhd2FpdGluZ0NvbW1pdEZpbmFsUmVmID0gdXNlUmVmKGZhbHNlKTtcbiAgY29uc3QgY29tbWl0RmluYWxUaW1lb3V0UmVmID0gdXNlUmVmPFJldHVyblR5cGU8dHlwZW9mIHNldFRpbWVvdXQ+IHwgbnVsbD4obnVsbCk7XG4gIGNvbnN0IGRpZFByZXdhcm1SZWYgPSB1c2VSZWYoZmFsc2UpO1xuICBjb25zdCBpc1JlY29yZGluZ1JlZiA9IHVzZVJlZihmYWxzZSk7XG4gIGNvbnN0IHNob3VsZExpc3RlblJlZiA9IHVzZVJlZihzaG91bGRMaXN0ZW4pO1xuICBjb25zdCBvcGVuYWlQcmV3YXJtT25Nb3VudFJlZiA9IHVzZVJlZihvcGVuYWlQcmV3YXJtT25Nb3VudCk7XG4gIGNvbnN0IHNlc3Npb25SZWNvdmVyeU1vZGVSZWYgPSB1c2VSZWY8XCJsaXN0ZW5cIiB8IFwicHJld2FybVwiIHwgbnVsbD4obnVsbCk7XG4gIGNvbnN0IHNlc3Npb25SZWNvdmVyeUluRmxpZ2h0UmVmID0gdXNlUmVmKGZhbHNlKTtcbiAgY29uc3Qgc3VwcHJlc3NlZENoYW5uZWxFcnJvclJlZiA9IHVzZVJlZjxhbnk+KG51bGwpO1xuXG4gIGNvbnN0IGVtaXRFcnJvciA9IHVzZUNhbGxiYWNrKFxuICAgIChlcnJvcjogdW5rbm93bikgPT4ge1xuICAgICAgY29uc3QgZXJyID0gZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yIDogbmV3IEVycm9yKFN0cmluZyhlcnJvcikpO1xuICAgICAgbG9nZ2VyLmVycm9yKFwiW09wZW5BSSBOYXRpdmUgU1JdIGVycm9yOlwiLCBlcnIpO1xuICAgICAgb25FcnJvcj8uKGVycik7XG4gICAgfSxcbiAgICBbb25FcnJvcl1cbiAgKTtcblxuICBjb25zdCBidWlsZFR1cm5EZXRlY3Rpb24gPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgaWYgKCFvcGVuYWlWYWRFbmFibGVkKSByZXR1cm4gbnVsbDtcbiAgICByZXR1cm4ge1xuICAgICAgdHlwZTogXCJzZXJ2ZXJfdmFkXCIsXG4gICAgICB0aHJlc2hvbGQ6IG9wZW5haVZhZFRocmVzaG9sZCxcbiAgICAgIHByZWZpeF9wYWRkaW5nX21zOiBvcGVuYWlWYWRQcmVmaXhQYWRkaW5nTXMsXG4gICAgICBzaWxlbmNlX2R1cmF0aW9uX21zOiBvcGVuYWlWYWRTaWxlbmNlRHVyYXRpb25NcyxcbiAgICB9O1xuICB9LCBbXG4gICAgb3BlbmFpVmFkRW5hYmxlZCxcbiAgICBvcGVuYWlWYWRUaHJlc2hvbGQsXG4gICAgb3BlbmFpVmFkUHJlZml4UGFkZGluZ01zLFxuICAgIG9wZW5haVZhZFNpbGVuY2VEdXJhdGlvbk1zLFxuICBdKTtcblxuICBjb25zdCB3YWl0Rm9yRGF0YUNoYW5uZWxPcGVuID0gdXNlQ2FsbGJhY2soXG4gICAgYXN5bmMgKGNoYW5uZWw6IGFueSk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgICAgaWYgKGNoYW5uZWw/LnJlYWR5U3RhdGUgPT09IFwib3BlblwiKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHN0YXJ0ID0gRGF0ZS5ub3coKTtcbiAgICAgIHdoaWxlIChEYXRlLm5vdygpIC0gc3RhcnQgPCBEQVRBX0NIQU5ORUxfT1BFTl9USU1FT1VUX01TKSB7XG4gICAgICAgIGlmIChjaGFubmVsPy5yZWFkeVN0YXRlID09PSBcIm9wZW5cIikge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCA1MCkpO1xuICAgICAgfVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgT3BlbkFJIG5hdGl2ZSByZWFsdGltZSBkYXRhIGNoYW5uZWwgZGlkIG5vdCBvcGVuIHdpdGhpbiAke0RBVEFfQ0hBTk5FTF9PUEVOX1RJTUVPVVRfTVN9bXMgKHN0YXRlPSR7U3RyaW5nKFxuICAgICAgICAgIGNoYW5uZWw/LnJlYWR5U3RhdGUgPz8gXCJ1bmtub3duXCJcbiAgICAgICAgKX0pYFxuICAgICAgKTtcbiAgICB9LFxuICAgIFtdXG4gICk7XG5cbiAgY29uc3QgcmVzZXRUcmFuc2NyaXB0UmVmcyA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICBmaW5hbFRyYW5zY3JpcHRSZWYuY3VycmVudCA9IFwiXCI7XG4gICAgaW50ZXJpbVRyYW5zY3JpcHRSZWYuY3VycmVudCA9IFwiXCI7XG4gICAgZmluYWxpemVkUmVmLmN1cnJlbnQgPSBmYWxzZTtcbiAgfSwgW10pO1xuXG4gIGNvbnN0IGdldEJ1ZmZlcmVkVHJhbnNjcmlwdCA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICByZXR1cm4gKFxuICAgICAgZmluYWxUcmFuc2NyaXB0UmVmLmN1cnJlbnQgfHxcbiAgICAgIGludGVyaW1UcmFuc2NyaXB0UmVmLmN1cnJlbnRcbiAgICApLnRyaW0oKTtcbiAgfSwgW10pO1xuXG4gIGNvbnN0IGNsZWFyQ29tbWl0RmluYWxXYWl0ID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgIGF3YWl0aW5nQ29tbWl0RmluYWxSZWYuY3VycmVudCA9IGZhbHNlO1xuICAgIGlmIChjb21taXRGaW5hbFRpbWVvdXRSZWYuY3VycmVudCkge1xuICAgICAgY2xlYXJUaW1lb3V0KGNvbW1pdEZpbmFsVGltZW91dFJlZi5jdXJyZW50KTtcbiAgICAgIGNvbW1pdEZpbmFsVGltZW91dFJlZi5jdXJyZW50ID0gbnVsbDtcbiAgICB9XG4gIH0sIFtdKTtcblxuICBjb25zdCBub3RpZnlSZWFkeSA9IHVzZUNhbGxiYWNrKFxuICAgIChyZWFkeTogYm9vbGVhbikgPT4ge1xuICAgICAgc3BlZWNoUmVhZHlDYWxsYmFjaz8uKHJlYWR5KTtcbiAgICB9LFxuICAgIFtzcGVlY2hSZWFkeUNhbGxiYWNrXVxuICApO1xuXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgaXNSZWNvcmRpbmdSZWYuY3VycmVudCA9IGlzUmVjb3JkaW5nO1xuICB9LCBbaXNSZWNvcmRpbmddKTtcblxuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIHNob3VsZExpc3RlblJlZi5jdXJyZW50ID0gc2hvdWxkTGlzdGVuO1xuICB9LCBbc2hvdWxkTGlzdGVuXSk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBvcGVuYWlQcmV3YXJtT25Nb3VudFJlZi5jdXJyZW50ID0gb3BlbmFpUHJld2FybU9uTW91bnQ7XG4gIH0sIFtvcGVuYWlQcmV3YXJtT25Nb3VudF0pO1xuXG4gIGNvbnN0IHNldEF1ZGlvQ2FwdHVyZUVuYWJsZWQgPSB1c2VDYWxsYmFjaygoZW5hYmxlZDogYm9vbGVhbikgPT4ge1xuICAgIGNvbnN0IHN0cmVhbSA9IHN0cmVhbVJlZi5jdXJyZW50O1xuICAgIGlmICghc3RyZWFtIHx8IHR5cGVvZiBzdHJlYW0uZ2V0VHJhY2tzICE9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgdHJhY2tzID0gc3RyZWFtXG4gICAgICAgIC5nZXRUcmFja3MoKVxuICAgICAgICAuZmlsdGVyKCh0cmFjazogYW55KSA9PiB0cmFjaz8ua2luZCA9PT0gXCJhdWRpb1wiKTtcbiAgICAgIHRyYWNrcy5mb3JFYWNoKCh0cmFjazogYW55KSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgdHJhY2suZW5hYmxlZCA9IGVuYWJsZWQ7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgbG9nZ2VyLndhcm4oXCJbT3BlbkFJIE5hdGl2ZSBTUl0gdG9nZ2xlIGF1ZGlvIHRyYWNrIHdhcm5pbmc6XCIsIGVycm9yKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGxvZ2dlci53YXJuKFwiW09wZW5BSSBOYXRpdmUgU1JdIGVudW1lcmF0ZSBhdWRpbyB0cmFja3Mgd2FybmluZzpcIiwgZXJyb3IpO1xuICAgIH1cbiAgfSwgW10pO1xuXG4gIGNvbnN0IGhhbmRsZUV4cGlyZWRTZXNzaW9uID0gdXNlQ2FsbGJhY2soXG4gICAgKGNoYW5uZWw6IGFueSwgcGM6IGFueSkgPT4ge1xuICAgICAgaWYgKHNlc3Npb25SZWNvdmVyeUluRmxpZ2h0UmVmLmN1cnJlbnQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgaWYgKGRhdGFDaGFubmVsUmVmLmN1cnJlbnQgIT09IGNoYW5uZWwpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBzZXNzaW9uUmVjb3ZlcnlJbkZsaWdodFJlZi5jdXJyZW50ID0gdHJ1ZTtcbiAgICAgIHN1cHByZXNzZWRDaGFubmVsRXJyb3JSZWYuY3VycmVudCA9IGNoYW5uZWw7XG4gICAgICBzZXNzaW9uUmVjb3ZlcnlNb2RlUmVmLmN1cnJlbnQgPSBzaG91bGRMaXN0ZW5SZWYuY3VycmVudFxuICAgICAgICA/IFwibGlzdGVuXCJcbiAgICAgICAgOiBvcGVuYWlQcmV3YXJtT25Nb3VudFJlZi5jdXJyZW50XG4gICAgICAgICAgPyBcInByZXdhcm1cIlxuICAgICAgICAgIDogbnVsbDtcblxuICAgICAgY2xlYXJDb21taXRGaW5hbFdhaXQoKTtcbiAgICAgIHJlc2V0VHJhbnNjcmlwdFJlZnMoKTtcbiAgICAgIHNldEF1ZGlvQ2FwdHVyZUVuYWJsZWQoZmFsc2UpO1xuICAgICAgc2Vzc2lvbkluaXRSZWYuY3VycmVudCA9IG51bGw7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNoYW5uZWw/LmNsb3NlPy4oKTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGxvZ2dlci53YXJuKFwiW09wZW5BSSBOYXRpdmUgU1JdIGNsb3NlIGRhdGEgY2hhbm5lbCB3YXJuaW5nOlwiLCBlcnJvcik7XG4gICAgICB9XG4gICAgICB0cnkge1xuICAgICAgICBwYz8uY2xvc2U/LigpO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oXCJbT3BlbkFJIE5hdGl2ZSBTUl0gY2xvc2UgcGVlciB3YXJuaW5nOlwiLCBlcnJvcik7XG4gICAgICB9XG4gICAgICB0cnkge1xuICAgICAgICBzdHJlYW1SZWYuY3VycmVudD8uZ2V0VHJhY2tzPy4oKS5mb3JFYWNoKCh0cmFjazogYW55KSA9PiB0cmFjay5zdG9wPy4oKSk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBsb2dnZXIud2FybihcIltPcGVuQUkgTmF0aXZlIFNSXSBzdG9wIHN0cmVhbSB3YXJuaW5nOlwiLCBlcnJvcik7XG4gICAgICB9XG5cbiAgICAgIGlmIChkYXRhQ2hhbm5lbFJlZi5jdXJyZW50ID09PSBjaGFubmVsKSB7XG4gICAgICAgIGRhdGFDaGFubmVsUmVmLmN1cnJlbnQgPSBudWxsO1xuICAgICAgfVxuICAgICAgaWYgKHBjUmVmLmN1cnJlbnQgPT09IHBjKSB7XG4gICAgICAgIHBjUmVmLmN1cnJlbnQgPSBudWxsO1xuICAgICAgfVxuICAgICAgc3RyZWFtUmVmLmN1cnJlbnQgPSBudWxsO1xuXG4gICAgICBzZXRJc1JlY29yZGluZyhmYWxzZSk7XG4gICAgICBub3RpZnlSZWFkeShmYWxzZSk7XG4gICAgICBzcGVlY2hTdGF0dXNDYWxsYmFjayhmYWxzZSwgXCJcIik7XG5cbiAgICAgIGlmIChzZXNzaW9uUmVjb3ZlcnlNb2RlUmVmLmN1cnJlbnQpIHtcbiAgICAgICAgc2V0U2Vzc2lvblJlY292ZXJ5VG9rZW4oKHZhbHVlKSA9PiB2YWx1ZSArIDEpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc2Vzc2lvblJlY292ZXJ5SW5GbGlnaHRSZWYuY3VycmVudCA9IGZhbHNlO1xuICAgICAgICBzdXBwcmVzc2VkQ2hhbm5lbEVycm9yUmVmLmN1cnJlbnQgPSBudWxsO1xuICAgICAgfVxuICAgIH0sXG4gICAgW1xuICAgICAgY2xlYXJDb21taXRGaW5hbFdhaXQsXG4gICAgICBub3RpZnlSZWFkeSxcbiAgICAgIHJlc2V0VHJhbnNjcmlwdFJlZnMsXG4gICAgICBzZXRBdWRpb0NhcHR1cmVFbmFibGVkLFxuICAgICAgc3BlZWNoU3RhdHVzQ2FsbGJhY2ssXG4gICAgXVxuICApO1xuXG4gIGNvbnN0IGNsZWFyUmVhbHRpbWVJbnB1dEJ1ZmZlciA9IHVzZUNhbGxiYWNrKChyZWFzb246IHN0cmluZykgPT4ge1xuICAgIGlmIChkYXRhQ2hhbm5lbFJlZi5jdXJyZW50Py5yZWFkeVN0YXRlICE9PSBcIm9wZW5cIikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgZGF0YUNoYW5uZWxSZWYuY3VycmVudC5zZW5kKFxuICAgICAgICBKU09OLnN0cmluZ2lmeSh7IHR5cGU6IFwiaW5wdXRfYXVkaW9fYnVmZmVyLmNsZWFyXCIgfSlcbiAgICAgICk7XG4gICAgICBsb2dnZXIuZGVidWcoYFtPcGVuQUkgTmF0aXZlIFNSXSBjbGVhcmVkIGlucHV0IGJ1ZmZlciAoJHtyZWFzb259KWApO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBsb2dnZXIud2FybihcIltPcGVuQUkgTmF0aXZlIFNSXSBjbGVhciBpbnB1dCBidWZmZXIgd2FybmluZzpcIiwgZXJyb3IpO1xuICAgIH1cbiAgfSwgW10pO1xuXG4gIGNvbnN0IGdldFJlcXVlc3RDb250ZXh0SGVhZGVycyA9IHVzZUNhbGxiYWNrKCgpOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0+IHtcbiAgICBjb25zdCBjb250ZXh0ID0gcmVxdWVzdENvbnRleHRQcm92aWRlcj8uKCk7XG4gICAgaWYgKCFjb250ZXh0KSByZXR1cm4ge307XG5cbiAgICBjb25zdCBoZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG4gICAgaWYgKGNvbnRleHQudGhyZWFkSWQpIHtcbiAgICAgIGhlYWRlcnNbXCJ4LXRocmVhZC1pZFwiXSA9IFN0cmluZyhjb250ZXh0LnRocmVhZElkKTtcbiAgICB9XG4gICAgaWYgKGNvbnRleHQudHVybklkKSB7XG4gICAgICBoZWFkZXJzW1wieC10dXJuLWlkXCJdID0gU3RyaW5nKGNvbnRleHQudHVybklkKTtcbiAgICB9XG4gICAgaWYgKGNvbnRleHQuc2Vzc2lvbklkICE9PSB1bmRlZmluZWQgJiYgY29udGV4dC5zZXNzaW9uSWQgIT09IG51bGwpIHtcbiAgICAgIGhlYWRlcnNbXCJ4LXZvaWNlLXNlc3Npb24taWRcIl0gPSBTdHJpbmcoY29udGV4dC5zZXNzaW9uSWQpO1xuICAgIH1cbiAgICBpZiAoY29udGV4dC5zZW50cnlUcmFjZSkge1xuICAgICAgaGVhZGVyc1tcInNlbnRyeS10cmFjZVwiXSA9IFN0cmluZyhjb250ZXh0LnNlbnRyeVRyYWNlKTtcbiAgICB9XG4gICAgaWYgKGNvbnRleHQuYmFnZ2FnZSkge1xuICAgICAgaGVhZGVycy5iYWdnYWdlID0gU3RyaW5nKGNvbnRleHQuYmFnZ2FnZSk7XG4gICAgfVxuICAgIHJldHVybiBoZWFkZXJzO1xuICB9LCBbcmVxdWVzdENvbnRleHRQcm92aWRlcl0pO1xuXG4gIGNvbnN0IHRyYW5zbGF0ZVRvRW5nbGlzaCA9IHVzZUNhbGxiYWNrKFxuICAgIGFzeW5jICh0ZXh0OiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4gPT4ge1xuICAgICAgY29uc3QgaW5wdXQgPSB0ZXh0LnRyaW0oKTtcbiAgICAgIGlmICghaW5wdXQgfHwgIW9wZW5haVRyYW5zbGF0aW9uRW5kcG9pbnQpIHJldHVybiBcIlwiO1xuICAgICAgaWYgKGxhbmd1YWdlLnRvTG93ZXJDYXNlKCkuc3RhcnRzV2l0aChcImVuXCIpKSByZXR1cm4gXCJcIjtcblxuICAgICAgY29uc3QgaGVhZGVyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcbiAgICAgICAgXCJjb250ZW50LXR5cGVcIjogXCJhcHBsaWNhdGlvbi9qc29uXCIsXG4gICAgICAgIC4uLmdldFJlcXVlc3RDb250ZXh0SGVhZGVycygpLFxuICAgICAgfTtcbiAgICAgIGlmIChwcm94eUF1dGhUb2tlbikge1xuICAgICAgICBoZWFkZXJzLkF1dGhvcml6YXRpb24gPSBgQmVhcmVyICR7cHJveHlBdXRoVG9rZW59YDtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaChvcGVuYWlUcmFuc2xhdGlvbkVuZHBvaW50LCB7XG4gICAgICAgIG1ldGhvZDogXCJQT1NUXCIsXG4gICAgICAgIGhlYWRlcnMsXG4gICAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICB0ZXh0OiBpbnB1dCxcbiAgICAgICAgICBzb3VyY2VMYW5ndWFnZTogbGFuZ3VhZ2UsXG4gICAgICAgICAgbW9kZWw6IG9wZW5haVRyYW5zbGF0aW9uTW9kZWwsXG4gICAgICAgIH0pLFxuICAgICAgfSk7XG4gICAgICBpZiAoIXJlc3BvbnNlLm9rKSB7XG4gICAgICAgIGNvbnN0IGJvZHkgPSBhd2FpdCByZXNwb25zZS50ZXh0KCkuY2F0Y2goKCkgPT4gXCJcIik7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgdHJhbnNsYXRpb24gZmFpbGVkICgke3Jlc3BvbnNlLnN0YXR1c30pOiAke2JvZHl9YCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHBheWxvYWQgPSBhd2FpdCByZXNwb25zZS5qc29uKCkuY2F0Y2goKCkgPT4gbnVsbCk7XG4gICAgICBjb25zdCB0cmFuc2xhdGVkID1cbiAgICAgICAgdHlwZW9mIHBheWxvYWQ/LnRleHQgPT09IFwic3RyaW5nXCIgPyBwYXlsb2FkLnRleHQudHJpbSgpIDogXCJcIjtcbiAgICAgIGlmICh0cmFuc2xhdGVkKSB7XG4gICAgICAgIHNwZWVjaFRyYW5zbGF0aW9uQ2FsbGJhY2s/Lih0cmFuc2xhdGVkKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0cmFuc2xhdGVkO1xuICAgIH0sXG4gICAgW1xuICAgICAgcHJveHlBdXRoVG9rZW4sXG4gICAgICBsYW5ndWFnZSxcbiAgICAgIGdldFJlcXVlc3RDb250ZXh0SGVhZGVycyxcbiAgICAgIG9wZW5haVRyYW5zbGF0aW9uRW5kcG9pbnQsXG4gICAgICBvcGVuYWlUcmFuc2xhdGlvbk1vZGVsLFxuICAgICAgc3BlZWNoVHJhbnNsYXRpb25DYWxsYmFjayxcbiAgICBdXG4gICk7XG5cbiAgY29uc3QgZW1pdEZpbmFsID0gdXNlQ2FsbGJhY2soYXN5bmMgKCkgPT4ge1xuICAgIGlmIChmaW5hbGl6ZWRSZWYuY3VycmVudCkgcmV0dXJuO1xuICAgIGZpbmFsaXplZFJlZi5jdXJyZW50ID0gdHJ1ZTtcblxuICAgIGNvbnN0IGZpbmFsVGV4dCA9IChcbiAgICAgIGZpbmFsVHJhbnNjcmlwdFJlZi5jdXJyZW50IHx8XG4gICAgICBpbnRlcmltVHJhbnNjcmlwdFJlZi5jdXJyZW50XG4gICAgKS50cmltKCk7XG5cbiAgICBsZXQgcGFyc2VUZXh0ID0gZmluYWxUZXh0O1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB0cmFuc2xhdGVkID0gYXdhaXQgdHJhbnNsYXRlVG9FbmdsaXNoKGZpbmFsVGV4dCk7XG4gICAgICBpZiAodHJhbnNsYXRlZCkge1xuICAgICAgICBwYXJzZVRleHQgPSB0cmFuc2xhdGVkO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBsb2dnZXIud2FybihcIltPcGVuQUkgTmF0aXZlIFNSXSB0cmFuc2xhdGlvbiBmYWlsZWQ6XCIsIGVycm9yKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgc3BlZWNoU3RhdHVzQ2FsbGJhY2soZmFsc2UsIFwiXCIpO1xuICAgICAgaWYgKHBhcnNlVGV4dCkge1xuICAgICAgICBzcGVlY2hSZXN1bHRDYWxsYmFjayhwYXJzZVRleHQpO1xuICAgICAgfVxuICAgIH1cbiAgfSwgW3NwZWVjaFJlc3VsdENhbGxiYWNrLCBzcGVlY2hTdGF0dXNDYWxsYmFjaywgdHJhbnNsYXRlVG9FbmdsaXNoXSk7XG5cbiAgY29uc3QgZmluYWxpemVBbmRSZXNldCA9IHVzZUNhbGxiYWNrKGFzeW5jICgpID0+IHtcbiAgICBjbGVhckNvbW1pdEZpbmFsV2FpdCgpO1xuICAgIGF3YWl0IGVtaXRGaW5hbCgpO1xuICAgIHJlc2V0VHJhbnNjcmlwdFJlZnMoKTtcbiAgfSwgW2NsZWFyQ29tbWl0RmluYWxXYWl0LCBlbWl0RmluYWwsIHJlc2V0VHJhbnNjcmlwdFJlZnNdKTtcblxuICBjb25zdCBoYW5kbGVNZXNzYWdlID0gdXNlQ2FsbGJhY2soXG4gICAgKHBheWxvYWQ6IGFueSkgPT4ge1xuICAgICAgY29uc3QgdHlwZSA9IFN0cmluZyhwYXlsb2FkPy50eXBlIHx8IFwiXCIpO1xuICAgICAgY29uc3QgYWNjZXB0c1RyYW5zY3JpcHQgPVxuICAgICAgICBpc1JlY29yZGluZ1JlZi5jdXJyZW50IHx8IGF3YWl0aW5nQ29tbWl0RmluYWxSZWYuY3VycmVudDtcbiAgICAgIGlmICghYWNjZXB0c1RyYW5zY3JpcHQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBzaG91bGRQdWJsaXNoSW50ZXJpbSA9IGlzUmVjb3JkaW5nUmVmLmN1cnJlbnQ7XG4gICAgICBjb25zdCBkZWx0YSA9IGV4dHJhY3REZWx0YVRleHQocGF5bG9hZCk7XG4gICAgICBjb25zdCBjb21wbGV0ZWQgPSBleHRyYWN0Q29tcGxldGVkVGV4dChwYXlsb2FkKTtcblxuICAgICAgaWYgKGRlbHRhKSB7XG4gICAgICAgIGludGVyaW1UcmFuc2NyaXB0UmVmLmN1cnJlbnQgPSBtZXJnZVRyYW5zY3JpcHRQYXJ0cyhcbiAgICAgICAgICBmaW5hbFRyYW5zY3JpcHRSZWYuY3VycmVudCxcbiAgICAgICAgICBkZWx0YVxuICAgICAgICApO1xuICAgICAgICBpZiAoc2hvdWxkUHVibGlzaEludGVyaW0pIHtcbiAgICAgICAgICBzcGVlY2hTdGF0dXNDYWxsYmFjayh0cnVlLCBpbnRlcmltVHJhbnNjcmlwdFJlZi5jdXJyZW50KTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoY29tcGxldGVkKSB7XG4gICAgICAgIGZpbmFsVHJhbnNjcmlwdFJlZi5jdXJyZW50ID0gbWVyZ2VUcmFuc2NyaXB0UGFydHMoXG4gICAgICAgICAgZmluYWxUcmFuc2NyaXB0UmVmLmN1cnJlbnQsXG4gICAgICAgICAgY29tcGxldGVkXG4gICAgICAgICk7XG4gICAgICAgIGludGVyaW1UcmFuc2NyaXB0UmVmLmN1cnJlbnQgPSBmaW5hbFRyYW5zY3JpcHRSZWYuY3VycmVudDtcbiAgICAgICAgaWYgKHNob3VsZFB1Ymxpc2hJbnRlcmltKSB7XG4gICAgICAgICAgc3BlZWNoU3RhdHVzQ2FsbGJhY2sodHJ1ZSwgZmluYWxUcmFuc2NyaXB0UmVmLmN1cnJlbnQpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGxvb2tzQ29tcGxldGVkID0gISFjb21wbGV0ZWQgfHwgdHlwZS5pbmNsdWRlcyhcImNvbXBsZXRlZFwiKTtcbiAgICAgIGlmIChcbiAgICAgICAgYXdhaXRpbmdDb21taXRGaW5hbFJlZi5jdXJyZW50ICYmXG4gICAgICAgIGxvb2tzQ29tcGxldGVkICYmXG4gICAgICAgIGdldEJ1ZmZlcmVkVHJhbnNjcmlwdCgpXG4gICAgICApIHtcbiAgICAgICAgZmluYWxpemVBbmRSZXNldCgpLmNhdGNoKChlcnJvcikgPT4gZW1pdEVycm9yKGVycm9yKSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKG9wZW5haUF1dG9TdG9wT25WYWRTaWxlbmNlICYmIHR5cGUgPT09IFwiaW5wdXRfYXVkaW9fYnVmZmVyLnNwZWVjaF9zdG9wcGVkXCIpIHtcbiAgICAgICAgY29uc3QgcGF1c2VUcmFuc2NyaXB0ID0gZ2V0QnVmZmVyZWRUcmFuc2NyaXB0KCk7XG4gICAgICAgIHNwZWVjaFN0YXR1c0NhbGxiYWNrKGZhbHNlLCBwYXVzZVRyYW5zY3JpcHQpO1xuICAgICAgfVxuICAgIH0sXG4gICAgW1xuICAgICAgZW1pdEVycm9yLFxuICAgICAgZmluYWxpemVBbmRSZXNldCxcbiAgICAgIGdldEJ1ZmZlcmVkVHJhbnNjcmlwdCxcbiAgICAgIG9wZW5haUF1dG9TdG9wT25WYWRTaWxlbmNlLFxuICAgICAgc3BlZWNoU3RhdHVzQ2FsbGJhY2ssXG4gICAgXVxuICApO1xuXG4gIGNvbnN0IHN0YXJ0TmF0aXZlV2ViUnRjU2Vzc2lvbiA9IHVzZUNhbGxiYWNrKFxuICAgIGFzeW5jICh0b2tlbjogc3RyaW5nKSA9PiB7XG4gICAgICBjb25zdCB3ZWJydGMgPSBuYXRpdmVXZWJSVEM7XG4gICAgICBpZiAoIXdlYnJ0Yz8uUlRDUGVlckNvbm5lY3Rpb24gfHwgIXdlYnJ0Yz8ubWVkaWFEZXZpY2VzPy5nZXRVc2VyTWVkaWEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIFwicmVhY3QtbmF0aXZlLXdlYnJ0YyBpcyBub3QgaW5zdGFsbGVkLiBJbnN0YWxsIGl0IGZvciBPcGVuQUkgbmF0aXZlIHJlYWx0aW1lIHNwZWVjaC5cIlxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBzdHJlYW0gPSBhd2FpdCB3ZWJydGMubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYSh7XG4gICAgICAgIGF1ZGlvOiB0cnVlLFxuICAgICAgICB2aWRlbzogZmFsc2UsXG4gICAgICB9KTtcbiAgICAgIHN0cmVhbVJlZi5jdXJyZW50ID0gc3RyZWFtO1xuICAgICAgc2V0QXVkaW9DYXB0dXJlRW5hYmxlZChmYWxzZSk7XG5cbiAgICAgIGNvbnN0IHBjID0gbmV3IHdlYnJ0Yy5SVENQZWVyQ29ubmVjdGlvbigpO1xuICAgICAgcGNSZWYuY3VycmVudCA9IHBjO1xuICAgICAgY29uc3QgdHJhY2tzID0gdHlwZW9mIHN0cmVhbS5nZXRUcmFja3MgPT09IFwiZnVuY3Rpb25cIiA/IHN0cmVhbS5nZXRUcmFja3MoKSA6IFtdO1xuICAgICAgdHJhY2tzLmZvckVhY2goKHRyYWNrOiBhbnkpID0+IHBjLmFkZFRyYWNrKHRyYWNrLCBzdHJlYW0pKTtcblxuICAgICAgY29uc3QgZGF0YUNoYW5uZWwgPSBwYy5jcmVhdGVEYXRhQ2hhbm5lbChcIm9haS1ldmVudHNcIik7XG4gICAgICBkYXRhQ2hhbm5lbFJlZi5jdXJyZW50ID0gZGF0YUNoYW5uZWw7XG5cbiAgICAgIGRhdGFDaGFubmVsLm9ub3BlbiA9ICgpID0+IHtcbiAgICAgICAgbm90aWZ5UmVhZHkodHJ1ZSk7XG4gICAgICB9O1xuICAgICAgZGF0YUNoYW5uZWwub25tZXNzYWdlID0gKGV2ZW50OiB7IGRhdGE6IHN0cmluZyB9KSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgcGF5bG9hZCA9IEpTT04ucGFyc2UoU3RyaW5nKGV2ZW50LmRhdGEgfHwgXCJ7fVwiKSk7XG4gICAgICAgICAgaWYgKHBheWxvYWQ/LnR5cGUgPT09IFwiZXJyb3JcIikge1xuICAgICAgICAgICAgY29uc3QgbWVzc2FnZSA9IFN0cmluZyhcbiAgICAgICAgICAgICAgcGF5bG9hZD8uZXJyb3I/Lm1lc3NhZ2UgfHwgXCJPcGVuQUkgcmVhbHRpbWUgZXJyb3JcIlxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGlmIChpc0NvbW1pdEJ1ZmZlclRvb1NtYWxsRXJyb3IobWVzc2FnZSkpIHtcbiAgICAgICAgICAgICAgLy8gSWdub3JlIGNvbW1pdCBidWZmZXItdG9vLXNtYWxsIGVycm9ycyBmb3IgbG93LWxhdGVuY3kgZmFzdC1zdG9wIHBhdGguXG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpc1Nlc3Npb25EdXJhdGlvbkxpbWl0RXJyb3IobWVzc2FnZSkpIHtcbiAgICAgICAgICAgICAgaGFuZGxlRXhwaXJlZFNlc3Npb24oZGF0YUNoYW5uZWwsIHBjKTtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1lc3NhZ2UpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBoYW5kbGVNZXNzYWdlKHBheWxvYWQpO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIGVtaXRFcnJvcihlcnJvcik7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgICBkYXRhQ2hhbm5lbC5vbmVycm9yID0gKCkgPT4ge1xuICAgICAgICBpZiAoc3VwcHJlc3NlZENoYW5uZWxFcnJvclJlZi5jdXJyZW50ID09PSBkYXRhQ2hhbm5lbCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBub3RpZnlSZWFkeShmYWxzZSk7XG4gICAgICAgIGVtaXRFcnJvcihuZXcgRXJyb3IoXCJPcGVuQUkgbmF0aXZlIHJlYWx0aW1lIGRhdGEgY2hhbm5lbCBlcnJvclwiKSk7XG4gICAgICB9O1xuICAgICAgZGF0YUNoYW5uZWwub25jbG9zZSA9ICgpID0+IHtcbiAgICAgICAgbm90aWZ5UmVhZHkoZmFsc2UpO1xuICAgICAgfTtcblxuICAgICAgY29uc3Qgb2ZmZXIgPSBhd2FpdCBwYy5jcmVhdGVPZmZlcigpO1xuICAgICAgYXdhaXQgcGMuc2V0TG9jYWxEZXNjcmlwdGlvbihvZmZlcik7XG5cbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2gob3BlbmFpUmVhbHRpbWVXZWJSdGNVcmwsIHtcbiAgICAgICAgbWV0aG9kOiBcIlBPU1RcIixcbiAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgIEF1dGhvcml6YXRpb246IGBCZWFyZXIgJHt0b2tlbn1gLFxuICAgICAgICAgIFwiY29udGVudC10eXBlXCI6IFwiYXBwbGljYXRpb24vc2RwXCIsXG4gICAgICAgIH0sXG4gICAgICAgIGJvZHk6IG9mZmVyPy5zZHAgfHwgXCJcIixcbiAgICAgIH0pO1xuXG4gICAgICBpZiAoIXJlc3BvbnNlLm9rKSB7XG4gICAgICAgIGNvbnN0IGJvZHkgPSBhd2FpdCByZXNwb25zZS50ZXh0KCkuY2F0Y2goKCkgPT4gXCJcIik7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgd2VicnRjIG5lZ290aWF0aW9uIGZhaWxlZCAoJHtyZXNwb25zZS5zdGF0dXN9KTogJHtib2R5fWApO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBhbnN3ZXJTZHAgPSBhd2FpdCByZXNwb25zZS50ZXh0KCk7XG4gICAgICBhd2FpdCBwYy5zZXRSZW1vdGVEZXNjcmlwdGlvbih7XG4gICAgICAgIHR5cGU6IFwiYW5zd2VyXCIsXG4gICAgICAgIHNkcDogYW5zd2VyU2RwLFxuICAgICAgfSk7XG4gICAgICBhd2FpdCB3YWl0Rm9yRGF0YUNoYW5uZWxPcGVuKGRhdGFDaGFubmVsKTtcbiAgICB9LFxuICAgIFtcbiAgICAgIGVtaXRFcnJvcixcbiAgICAgIGhhbmRsZU1lc3NhZ2UsXG4gICAgICBub3RpZnlSZWFkeSxcbiAgICAgIG9wZW5haVJlYWx0aW1lV2ViUnRjVXJsLFxuICAgICAgc2V0QXVkaW9DYXB0dXJlRW5hYmxlZCxcbiAgICAgIHdhaXRGb3JEYXRhQ2hhbm5lbE9wZW4sXG4gICAgXVxuICApO1xuXG4gIGNvbnN0IGdldEVwaGVtZXJhbFRva2VuID0gdXNlQ2FsbGJhY2soYXN5bmMgKCk6IFByb21pc2U8c3RyaW5nPiA9PiB7XG4gICAgY29uc3QgaGVhZGVyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcbiAgICAgIFwiY29udGVudC10eXBlXCI6IFwiYXBwbGljYXRpb24vanNvblwiLFxuICAgICAgLi4uZ2V0UmVxdWVzdENvbnRleHRIZWFkZXJzKCksXG4gICAgfTtcbiAgICBpZiAocHJveHlBdXRoVG9rZW4pIHtcbiAgICAgIGhlYWRlcnMuQXV0aG9yaXphdGlvbiA9IGBCZWFyZXIgJHtwcm94eUF1dGhUb2tlbn1gO1xuICAgIH1cblxuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2gob3BlbmFpVHJhbnNjcmlwdGlvblNlc3Npb25FbmRwb2ludCwge1xuICAgICAgbWV0aG9kOiBcIlBPU1RcIixcbiAgICAgIGhlYWRlcnMsXG4gICAgICBib2R5OiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgIGlucHV0X2F1ZGlvX2Zvcm1hdDogXCJwY20xNlwiLFxuICAgICAgICBpbnB1dF9hdWRpb190cmFuc2NyaXB0aW9uOiB7XG4gICAgICAgICAgbW9kZWw6IG9wZW5haVJlYWx0aW1lTW9kZWwsXG4gICAgICAgICAgbGFuZ3VhZ2UsXG4gICAgICAgIH0sXG4gICAgICAgIHR1cm5fZGV0ZWN0aW9uOiBidWlsZFR1cm5EZXRlY3Rpb24oKSB8fCB1bmRlZmluZWQsXG4gICAgICB9KSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgIGNvbnN0IGJvZHkgPSBhd2FpdCByZXNwb25zZS50ZXh0KCkuY2F0Y2goKCkgPT4gXCJcIik7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGB0cmFuc2NyaXB0aW9uIHNlc3Npb24gcmVxdWVzdCBmYWlsZWQgKCR7cmVzcG9uc2Uuc3RhdHVzfSk6ICR7Ym9keX1gXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IHBheWxvYWQgPSBhd2FpdCByZXNwb25zZS5qc29uKCkuY2F0Y2goKCkgPT4gKHt9KSk7XG4gICAgY29uc3QgdG9rZW4gPVxuICAgICAgcGF5bG9hZD8uY2xpZW50X3NlY3JldD8udmFsdWUgfHxcbiAgICAgIHBheWxvYWQ/LmNsaWVudF9zZWNyZXQgfHxcbiAgICAgIHBheWxvYWQ/LnZhbHVlIHx8XG4gICAgICBcIlwiO1xuICAgIGlmICghdG9rZW4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgXCJObyBlcGhlbWVyYWwgdG9rZW4gcmV0dXJuZWQgZnJvbSB0cmFuc2NyaXB0aW9uIHNlc3Npb24gZW5kcG9pbnRcIlxuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdG9rZW47XG4gIH0sIFtcbiAgICBidWlsZFR1cm5EZXRlY3Rpb24sXG4gICAgZ2V0UmVxdWVzdENvbnRleHRIZWFkZXJzLFxuICAgIHByb3h5QXV0aFRva2VuLFxuICAgIGxhbmd1YWdlLFxuICAgIG9wZW5haVJlYWx0aW1lTW9kZWwsXG4gICAgb3BlbmFpVHJhbnNjcmlwdGlvblNlc3Npb25FbmRwb2ludCxcbiAgXSk7XG5cbiAgY29uc3QgaGFzUmV1c2FibGVTZXNzaW9uID0gdXNlQ2FsbGJhY2soKCk6IGJvb2xlYW4gPT4ge1xuICAgIHJldHVybiAoXG4gICAgICAhIXBjUmVmLmN1cnJlbnQgJiZcbiAgICAgICEhc3RyZWFtUmVmLmN1cnJlbnQgJiZcbiAgICAgIGRhdGFDaGFubmVsUmVmLmN1cnJlbnQ/LnJlYWR5U3RhdGUgPT09IFwib3BlblwiXG4gICAgKTtcbiAgfSwgW10pO1xuXG4gIGNvbnN0IGVuc3VyZU5hdGl2ZVdlYlJ0Y1Nlc3Npb24gPSB1c2VDYWxsYmFjayhhc3luYyAoKSA9PiB7XG4gICAgaWYgKGhhc1JldXNhYmxlU2Vzc2lvbigpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChzZXNzaW9uSW5pdFJlZi5jdXJyZW50KSB7XG4gICAgICBhd2FpdCBzZXNzaW9uSW5pdFJlZi5jdXJyZW50O1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHNlc3Npb25Jbml0UmVmLmN1cnJlbnQgPSAoYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdG9rZW4gPSBhd2FpdCBnZXRFcGhlbWVyYWxUb2tlbigpO1xuICAgICAgYXdhaXQgc3RhcnROYXRpdmVXZWJSdGNTZXNzaW9uKHRva2VuKTtcbiAgICB9KSgpO1xuXG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHNlc3Npb25Jbml0UmVmLmN1cnJlbnQ7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHNlc3Npb25Jbml0UmVmLmN1cnJlbnQgPSBudWxsO1xuICAgIH1cbiAgfSwgW2dldEVwaGVtZXJhbFRva2VuLCBoYXNSZXVzYWJsZVNlc3Npb24sIHN0YXJ0TmF0aXZlV2ViUnRjU2Vzc2lvbl0pO1xuXG4gIGNvbnN0IGNsZWFudXAgPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgc2Vzc2lvbkluaXRSZWYuY3VycmVudCA9IG51bGw7XG5cbiAgICB0cnkge1xuICAgICAgaWYgKGRhdGFDaGFubmVsUmVmLmN1cnJlbnQpIHtcbiAgICAgICAgZGF0YUNoYW5uZWxSZWYuY3VycmVudC5jbG9zZSgpO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBsb2dnZXIud2FybihcIltPcGVuQUkgTmF0aXZlIFNSXSBjbG9zZSBkYXRhIGNoYW5uZWwgd2FybmluZzpcIiwgZXJyb3IpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBkYXRhQ2hhbm5lbFJlZi5jdXJyZW50ID0gbnVsbDtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgaWYgKHBjUmVmLmN1cnJlbnQpIHtcbiAgICAgICAgcGNSZWYuY3VycmVudC5jbG9zZSgpO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBsb2dnZXIud2FybihcIltPcGVuQUkgTmF0aXZlIFNSXSBjbG9zZSBwZWVyIHdhcm5pbmc6XCIsIGVycm9yKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgcGNSZWYuY3VycmVudCA9IG51bGw7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGlmIChzdHJlYW1SZWYuY3VycmVudD8uZ2V0VHJhY2tzKSB7XG4gICAgICAgIHN0cmVhbVJlZi5jdXJyZW50LmdldFRyYWNrcygpLmZvckVhY2goKHRyYWNrOiBhbnkpID0+IHRyYWNrLnN0b3A/LigpKTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgbG9nZ2VyLndhcm4oXCJbT3BlbkFJIE5hdGl2ZSBTUl0gc3RvcCBzdHJlYW0gd2FybmluZzpcIiwgZXJyb3IpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBzdHJlYW1SZWYuY3VycmVudCA9IG51bGw7XG4gICAgfVxuICB9LCBbXSk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBpZiAoc2Vzc2lvblJlY292ZXJ5VG9rZW4gPT09IDAgfHwgIXNlc3Npb25SZWNvdmVyeU1vZGVSZWYuY3VycmVudCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGxldCBjYW5jZWxsZWQgPSBmYWxzZTtcbiAgICBjb25zdCByZWNvdmVyeU1vZGUgPSBzZXNzaW9uUmVjb3ZlcnlNb2RlUmVmLmN1cnJlbnQ7XG5cbiAgICAoYXN5bmMgKCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgZW5zdXJlTmF0aXZlV2ViUnRjU2Vzc2lvbigpO1xuICAgICAgICBpZiAoY2FuY2VsbGVkKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHJlY292ZXJ5TW9kZSA9PT0gXCJsaXN0ZW5cIiAmJiBzaG91bGRMaXN0ZW5SZWYuY3VycmVudCkge1xuICAgICAgICAgIHNldEF1ZGlvQ2FwdHVyZUVuYWJsZWQodHJ1ZSk7XG4gICAgICAgICAgc2V0SXNSZWNvcmRpbmcodHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgbm90aWZ5UmVhZHkoZGF0YUNoYW5uZWxSZWYuY3VycmVudD8ucmVhZHlTdGF0ZSA9PT0gXCJvcGVuXCIpO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgaWYgKGNhbmNlbGxlZCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBlbWl0RXJyb3IoZXJyb3IpO1xuICAgICAgICBzZXRBdWRpb0NhcHR1cmVFbmFibGVkKGZhbHNlKTtcbiAgICAgICAgY2xlYW51cCgpO1xuICAgICAgICBzZXRJc1JlY29yZGluZyhmYWxzZSk7XG4gICAgICAgIG5vdGlmeVJlYWR5KGZhbHNlKTtcbiAgICAgICAgc3BlZWNoU3RhdHVzQ2FsbGJhY2soZmFsc2UsIFwiXCIpO1xuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgaWYgKGNhbmNlbGxlZCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBzZXNzaW9uUmVjb3ZlcnlNb2RlUmVmLmN1cnJlbnQgPSBudWxsO1xuICAgICAgICBzZXNzaW9uUmVjb3ZlcnlJbkZsaWdodFJlZi5jdXJyZW50ID0gZmFsc2U7XG4gICAgICAgIHN1cHByZXNzZWRDaGFubmVsRXJyb3JSZWYuY3VycmVudCA9IG51bGw7XG4gICAgICB9XG4gICAgfSkoKTtcblxuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICBjYW5jZWxsZWQgPSB0cnVlO1xuICAgIH07XG4gIH0sIFtcbiAgICBjbGVhbnVwLFxuICAgIGVtaXRFcnJvcixcbiAgICBlbnN1cmVOYXRpdmVXZWJSdGNTZXNzaW9uLFxuICAgIG5vdGlmeVJlYWR5LFxuICAgIHNlc3Npb25SZWNvdmVyeVRva2VuLFxuICAgIHNldEF1ZGlvQ2FwdHVyZUVuYWJsZWQsXG4gICAgc3BlZWNoU3RhdHVzQ2FsbGJhY2ssXG4gIF0pO1xuXG4gIGNvbnN0IHN0YXJ0UmVjb3JkaW5nID0gdXNlQ2FsbGJhY2soYXN5bmMgKCkgPT4ge1xuICAgIGlmIChpc1JlY29yZGluZyB8fCBzdG9wSW5GbGlnaHRSZWYuY3VycmVudCB8fCBzZXNzaW9uUmVjb3ZlcnlJbkZsaWdodFJlZi5jdXJyZW50KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHJlc2V0VHJhbnNjcmlwdFJlZnMoKTtcbiAgICB0cnkge1xuICAgICAgY2xlYXJDb21taXRGaW5hbFdhaXQoKTtcbiAgICAgIG5vdGlmeVJlYWR5KGZhbHNlKTtcbiAgICAgIGNvbnN0IHJldXNpbmdXYXJtU2Vzc2lvbiA9IGhhc1JldXNhYmxlU2Vzc2lvbigpO1xuICAgICAgYXdhaXQgZW5zdXJlTmF0aXZlV2ViUnRjU2Vzc2lvbigpO1xuICAgICAgaWYgKHJldXNpbmdXYXJtU2Vzc2lvbikge1xuICAgICAgICBjbGVhclJlYWx0aW1lSW5wdXRCdWZmZXIoXCJzdGFydF9yZWNvcmRpbmdcIik7XG4gICAgICB9XG4gICAgICBpZiAoIXNob3VsZExpc3RlblJlZi5jdXJyZW50KSB7XG4gICAgICAgIHNldEF1ZGlvQ2FwdHVyZUVuYWJsZWQoZmFsc2UpO1xuICAgICAgICBub3RpZnlSZWFkeShkYXRhQ2hhbm5lbFJlZi5jdXJyZW50Py5yZWFkeVN0YXRlID09PSBcIm9wZW5cIik7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHNldEF1ZGlvQ2FwdHVyZUVuYWJsZWQodHJ1ZSk7XG4gICAgICBzZXRJc1JlY29yZGluZyh0cnVlKTtcbiAgICAgIG5vdGlmeVJlYWR5KGRhdGFDaGFubmVsUmVmLmN1cnJlbnQ/LnJlYWR5U3RhdGUgPT09IFwib3BlblwiKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgZW1pdEVycm9yKGVycm9yKTtcbiAgICAgIHNldEF1ZGlvQ2FwdHVyZUVuYWJsZWQoZmFsc2UpO1xuICAgICAgY2xlYW51cCgpO1xuICAgICAgc2V0SXNSZWNvcmRpbmcoZmFsc2UpO1xuICAgICAgbm90aWZ5UmVhZHkoZmFsc2UpO1xuICAgICAgc3BlZWNoU3RhdHVzQ2FsbGJhY2soZmFsc2UsIFwiXCIpO1xuICAgIH1cbiAgfSwgW1xuICAgIGNsZWFudXAsXG4gICAgY2xlYXJDb21taXRGaW5hbFdhaXQsXG4gICAgY2xlYXJSZWFsdGltZUlucHV0QnVmZmVyLFxuICAgIGVuc3VyZU5hdGl2ZVdlYlJ0Y1Nlc3Npb24sXG4gICAgZW1pdEVycm9yLFxuICAgIGhhc1JldXNhYmxlU2Vzc2lvbixcbiAgICBpc1JlY29yZGluZyxcbiAgICBub3RpZnlSZWFkeSxcbiAgICByZXNldFRyYW5zY3JpcHRSZWZzLFxuICAgIHNldEF1ZGlvQ2FwdHVyZUVuYWJsZWQsXG4gICAgc3BlZWNoU3RhdHVzQ2FsbGJhY2ssXG4gIF0pO1xuXG4gIGNvbnN0IHN0b3BSZWNvcmRpbmcgPSB1c2VDYWxsYmFjayhhc3luYyAoKSA9PiB7XG4gICAgaWYgKCFpc1JlY29yZGluZyB8fCBzdG9wSW5GbGlnaHRSZWYuY3VycmVudCkgcmV0dXJuO1xuICAgIHN0b3BJbkZsaWdodFJlZi5jdXJyZW50ID0gdHJ1ZTtcbiAgICBzZXRJc1JlY29yZGluZyhmYWxzZSk7XG4gICAgc2V0QXVkaW9DYXB0dXJlRW5hYmxlZChmYWxzZSk7XG4gICAgbm90aWZ5UmVhZHkoZmFsc2UpO1xuICAgIHRyeSB7XG4gICAgICBpZiAoZGF0YUNoYW5uZWxSZWYuY3VycmVudD8ucmVhZHlTdGF0ZSA9PT0gXCJvcGVuXCIpIHtcbiAgICAgICAgZGF0YUNoYW5uZWxSZWYuY3VycmVudC5zZW5kKFxuICAgICAgICAgIEpTT04uc3RyaW5naWZ5KHsgdHlwZTogXCJpbnB1dF9hdWRpb19idWZmZXIuY29tbWl0XCIgfSlcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGJ1ZmZlcmVkID0gZ2V0QnVmZmVyZWRUcmFuc2NyaXB0KCk7XG4gICAgICBpZiAoYnVmZmVyZWQpIHtcbiAgICAgICAgYXdhaXQgZmluYWxpemVBbmRSZXNldCgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc3BlZWNoU3RhdHVzQ2FsbGJhY2soZmFsc2UsIFwiXCIpO1xuICAgICAgICBhd2FpdGluZ0NvbW1pdEZpbmFsUmVmLmN1cnJlbnQgPSB0cnVlO1xuICAgICAgICBpZiAoY29tbWl0RmluYWxUaW1lb3V0UmVmLmN1cnJlbnQpIHtcbiAgICAgICAgICBjbGVhclRpbWVvdXQoY29tbWl0RmluYWxUaW1lb3V0UmVmLmN1cnJlbnQpO1xuICAgICAgICB9XG4gICAgICAgIC8vIFNob3J0IGZhbGxiYWNrOiBpZiBubyBwb3N0LWNvbW1pdCB0cmFuc2NyaXB0IGFycml2ZXMsIHJlc2V0IHN0YXRlIGFuZCBleGl0LlxuICAgICAgICBjb21taXRGaW5hbFRpbWVvdXRSZWYuY3VycmVudCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgIGlmICghYXdhaXRpbmdDb21taXRGaW5hbFJlZi5jdXJyZW50KSByZXR1cm47XG4gICAgICAgICAgY2xlYXJDb21taXRGaW5hbFdhaXQoKTtcbiAgICAgICAgICByZXNldFRyYW5zY3JpcHRSZWZzKCk7XG4gICAgICAgIH0sIDE1MDApO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBlbWl0RXJyb3IoZXJyb3IpO1xuICAgICAgc3BlZWNoU3RhdHVzQ2FsbGJhY2soZmFsc2UsIFwiXCIpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBzdG9wSW5GbGlnaHRSZWYuY3VycmVudCA9IGZhbHNlO1xuICAgICAgbm90aWZ5UmVhZHkoZmFsc2UpO1xuICAgIH1cbiAgfSwgW1xuICAgIGVtaXRFcnJvcixcbiAgICBmaW5hbGl6ZUFuZFJlc2V0LFxuICAgIGdldEJ1ZmZlcmVkVHJhbnNjcmlwdCxcbiAgICBpc1JlY29yZGluZyxcbiAgICBub3RpZnlSZWFkeSxcbiAgICBjbGVhckNvbW1pdEZpbmFsV2FpdCxcbiAgICByZXNldFRyYW5zY3JpcHRSZWZzLFxuICAgIHNldEF1ZGlvQ2FwdHVyZUVuYWJsZWQsXG4gICAgc3BlZWNoU3RhdHVzQ2FsbGJhY2ssXG4gIF0pO1xuXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgaWYgKCFvcGVuYWlQcmV3YXJtT25Nb3VudCB8fCBkaWRQcmV3YXJtUmVmLmN1cnJlbnQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZGlkUHJld2FybVJlZi5jdXJyZW50ID0gdHJ1ZTtcbiAgICBlbnN1cmVOYXRpdmVXZWJSdGNTZXNzaW9uKClcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgbm90aWZ5UmVhZHkodHJ1ZSk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICBlbWl0RXJyb3IoZXJyb3IpO1xuICAgICAgfSk7XG4gIH0sIFtlbWl0RXJyb3IsIGVuc3VyZU5hdGl2ZVdlYlJ0Y1Nlc3Npb24sIG5vdGlmeVJlYWR5LCBvcGVuYWlQcmV3YXJtT25Nb3VudF0pO1xuXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgaWYgKHNob3VsZExpc3RlbiAmJiAhaXNSZWNvcmRpbmcpIHtcbiAgICAgIHN0YXJ0UmVjb3JkaW5nKCk7XG4gICAgfSBlbHNlIGlmICghc2hvdWxkTGlzdGVuICYmIGlzUmVjb3JkaW5nKSB7XG4gICAgICBzdG9wUmVjb3JkaW5nKCk7XG4gICAgfVxuICB9LCBbaXNSZWNvcmRpbmcsIHNob3VsZExpc3Rlbiwgc3RhcnRSZWNvcmRpbmcsIHN0b3BSZWNvcmRpbmddKTtcblxuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICBub3RpZnlSZWFkeShmYWxzZSk7XG4gICAgICBjbGVhckNvbW1pdEZpbmFsV2FpdCgpO1xuICAgICAgc2V0QXVkaW9DYXB0dXJlRW5hYmxlZChmYWxzZSk7XG4gICAgICBjbGVhbnVwKCk7XG4gICAgfTtcbiAgfSwgW2NsZWFudXAsIG5vdGlmeVJlYWR5LCBjbGVhckNvbW1pdEZpbmFsV2FpdCwgc2V0QXVkaW9DYXB0dXJlRW5hYmxlZF0pO1xuXG4gIHJldHVybiA8VmlldyAvPjtcbn07XG5cbmZ1bmN0aW9uIGV4dHJhY3REZWx0YVRleHQocGF5bG9hZDogYW55KTogc3RyaW5nIHtcbiAgY29uc3QgdHlwZSA9IFN0cmluZyhwYXlsb2FkPy50eXBlIHx8IFwiXCIpO1xuICBpZiAoIXR5cGUuaW5jbHVkZXMoXCJkZWx0YVwiKSkgcmV0dXJuIFwiXCI7XG4gIGNvbnN0IGNhbmRpZGF0ZXMgPSBbXG4gICAgcGF5bG9hZD8uZGVsdGEsXG4gICAgcGF5bG9hZD8udGV4dF9kZWx0YSxcbiAgICBwYXlsb2FkPy50cmFuc2NyaXB0X2RlbHRhLFxuICAgIHBheWxvYWQ/Lml0ZW0/LmNvbnRlbnQ/LlswXT8udHJhbnNjcmlwdCxcbiAgXTtcbiAgZm9yIChjb25zdCB2YWx1ZSBvZiBjYW5kaWRhdGVzKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJzdHJpbmdcIiAmJiB2YWx1ZS50cmltKCkpIHJldHVybiB2YWx1ZS50cmltKCk7XG4gIH1cbiAgcmV0dXJuIFwiXCI7XG59XG5cbmZ1bmN0aW9uIGV4dHJhY3RDb21wbGV0ZWRUZXh0KHBheWxvYWQ6IGFueSk6IHN0cmluZyB7XG4gIGNvbnN0IHR5cGUgPSBTdHJpbmcocGF5bG9hZD8udHlwZSB8fCBcIlwiKTtcbiAgaWYgKCF0eXBlLmluY2x1ZGVzKFwiY29tcGxldGVkXCIpKSByZXR1cm4gXCJcIjtcbiAgY29uc3QgY2FuZGlkYXRlcyA9IFtcbiAgICBwYXlsb2FkPy50cmFuc2NyaXB0LFxuICAgIHBheWxvYWQ/LnRleHQsXG4gICAgcGF5bG9hZD8uaXRlbT8uY29udGVudD8uWzBdPy50cmFuc2NyaXB0LFxuICAgIHBheWxvYWQ/Lml0ZW0/LnRyYW5zY3JpcHQsXG4gIF07XG4gIGZvciAoY29uc3QgdmFsdWUgb2YgY2FuZGlkYXRlcykge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIgJiYgdmFsdWUudHJpbSgpKSByZXR1cm4gdmFsdWUudHJpbSgpO1xuICB9XG4gIHJldHVybiBcIlwiO1xufVxuXG5mdW5jdGlvbiBleHRyYWN0SXRlbUlkKHBheWxvYWQ6IGFueSk6IHN0cmluZyB8IG51bGwge1xuICBjb25zdCBjYW5kaWRhdGVzID0gW3BheWxvYWQ/Lml0ZW1faWQsIHBheWxvYWQ/Lml0ZW0/LmlkXTtcbiAgZm9yIChjb25zdCB2YWx1ZSBvZiBjYW5kaWRhdGVzKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJzdHJpbmdcIiAmJiB2YWx1ZS50cmltKCkpIHtcbiAgICAgIHJldHVybiB2YWx1ZS50cmltKCk7XG4gICAgfVxuICB9XG4gIHJldHVybiBudWxsO1xufVxuXG5mdW5jdGlvbiBpc0NvbW1pdEJ1ZmZlclRvb1NtYWxsRXJyb3IobWVzc2FnZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gIGNvbnN0IG5vcm1hbGl6ZWQgPSBtZXNzYWdlLnRvTG93ZXJDYXNlKCk7XG4gIHJldHVybiAoXG4gICAgbm9ybWFsaXplZC5pbmNsdWRlcyhcImlucHV0IGF1ZGlvIGJ1ZmZlclwiKSAmJlxuICAgIG5vcm1hbGl6ZWQuaW5jbHVkZXMoXCJidWZmZXIgdG9vIHNtYWxsXCIpXG4gICk7XG59XG5cbmZ1bmN0aW9uIGlzU2Vzc2lvbkR1cmF0aW9uTGltaXRFcnJvcihtZXNzYWdlOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgY29uc3Qgbm9ybWFsaXplZCA9IG1lc3NhZ2UudG9Mb3dlckNhc2UoKTtcbiAgcmV0dXJuIChcbiAgICBub3JtYWxpemVkLmluY2x1ZGVzKFwic2Vzc2lvblwiKSAmJlxuICAgIChub3JtYWxpemVkLmluY2x1ZGVzKFwibWF4aW11bSBkdXJhdGlvblwiKSB8fFxuICAgICAgbm9ybWFsaXplZC5pbmNsdWRlcyhcIm1heCBkdXJhdGlvblwiKSlcbiAgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzT3BlbkFJTmF0aXZlU3BlZWNoQXZhaWxhYmxlKCk6IGJvb2xlYW4ge1xuICByZXR1cm4gKFxuICAgIChQbGF0Zm9ybS5PUyA9PT0gXCJpb3NcIiB8fCBQbGF0Zm9ybS5PUyA9PT0gXCJhbmRyb2lkXCIpICYmXG4gICAgISFuYXRpdmVXZWJSVEM/LlJUQ1BlZXJDb25uZWN0aW9uICYmXG4gICAgISFuYXRpdmVXZWJSVEM/Lm1lZGlhRGV2aWNlcz8uZ2V0VXNlck1lZGlhXG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRPcGVuQUlOYXRpdmVTcGVlY2hDYXBhYmlsaXRpZXMoKSB7XG4gIHJldHVybiB7XG4gICAgYXZhaWxhYmxlOiBpc09wZW5BSU5hdGl2ZVNwZWVjaEF2YWlsYWJsZSgpLFxuICAgIHBsYXRmb3JtOiBQbGF0Zm9ybS5PUyxcbiAgICBzdXBwb3J0c1NlcnZlclZBRDogdHJ1ZSxcbiAgICB0cmFuc3BvcnQ6IFwid2VicnRjXCIsXG4gICAgcmVxdWlyZXNXZWJSVENEZXBlbmRlbmN5OiB0cnVlLFxuICB9O1xufVxuXG5leHBvcnQgZGVmYXVsdCBPcGVuQUlOYXRpdmVTcGVlY2hSZWNvZ25pemVyO1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7OztBQUFB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LEVBQUVuRSxPQUFPLEVBQUUrRCxJQUFJLEVBQUVLLEVBQUUsQ0FBQztFQUN4RCxLQUFLLE1BQU01TSxLQUFLLElBQUlvTSxVQUFVLEVBQUU7SUFDOUIsSUFBSSxPQUFPcE0sS0FBSyxLQUFLLFFBQVEsSUFBSUEsS0FBSyxDQUFDd0YsSUFBSSxDQUFDLENBQUMsRUFBRTtNQUM3QyxPQUFPeEYsS0FBSyxDQUFDd0YsSUFBSSxDQUFDLENBQUM7SUFDckI7RUFDRjtFQUNBLE9BQU8sSUFBSTtBQUNiO0FBRUEsU0FBU2dGLDJCQUEyQkEsQ0FBQ0QsT0FBZSxFQUFXO0VBQzdELE1BQU1zQyxVQUFVLEdBQUd0QyxPQUFPLENBQUMzQyxXQUFXLENBQUMsQ0FBQztFQUN4QyxPQUNFaUYsVUFBVSxDQUFDckQsUUFBUSxDQUFDLG9CQUFvQixDQUFDLElBQ3pDcUQsVUFBVSxDQUFDckQsUUFBUSxDQUFDLGtCQUFrQixDQUFDO0FBRTNDO0FBRUEsU0FBU2lCLDJCQUEyQkEsQ0FBQ0YsT0FBZSxFQUFXO0VBQzdELE1BQU1zQyxVQUFVLEdBQUd0QyxPQUFPLENBQUMzQyxXQUFXLENBQUMsQ0FBQztFQUN4QyxPQUNFaUYsVUFBVSxDQUFDckQsUUFBUSxDQUFDLFNBQVMsQ0FBQyxLQUM3QnFELFVBQVUsQ0FBQ3JELFFBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxJQUN0Q3FELFVBQVUsQ0FBQ3JELFFBQVEsQ0FBQyxjQUFjLENBQUMsQ0FBQztBQUUxQztBQUVPLFNBQVNzRCw2QkFBNkJBLENBQUEsRUFBWTtFQUN2RCxPQUNFLENBQUNDLHFCQUFRLENBQUNDLEVBQUUsS0FBSyxLQUFLLElBQUlELHFCQUFRLENBQUNDLEVBQUUsS0FBSyxTQUFTLEtBQ25ELENBQUMsQ0FBQ2pNLFlBQVksRUFBRUgsaUJBQWlCLElBQ2pDLENBQUMsQ0FBQ0csWUFBWSxFQUFFRixZQUFZLEVBQUVDLFlBQVk7QUFFOUM7QUFFTyxTQUFTbU0saUNBQWlDQSxDQUFBLEVBQUc7RUFDbEQsT0FBTztJQUNMQyxTQUFTLEVBQUVKLDZCQUE2QixDQUFDLENBQUM7SUFDMUNLLFFBQVEsRUFBRUoscUJBQVEsQ0FBQ0MsRUFBRTtJQUNyQkksaUJBQWlCLEVBQUUsSUFBSTtJQUN2QkMsU0FBUyxFQUFFLFFBQVE7SUFDbkJDLHdCQUF3QixFQUFFO0VBQzVCLENBQUM7QUFDSDtBQUFDLElBQUFDLFFBQUEsR0FBQXBCLE9BQUEsQ0FBQW5PLE9BQUEsR0FFY21ELDRCQUE0QiIsImlnbm9yZUxpc3QiOltdfQ==