@sinequa/assistant 3.6.2 → 3.7.1

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.
@@ -4,7 +4,7 @@ import { AbstractFacet } from "@sinequa/components/facet";
4
4
  import { SearchService } from "@sinequa/components/search";
5
5
  import { AppService } from "@sinequa/core/app-utils";
6
6
  import { PrincipalWebService } from "@sinequa/core/web-services";
7
- import { BehaviorSubject, Subscription, filter, fromEvent, map, merge, switchMap, tap } from "rxjs";
7
+ import { BehaviorSubject, Subscription, combineLatest, filter, fromEvent, map, merge, switchMap, take, tap } from "rxjs";
8
8
  import { ChatService } from "./chat.service";
9
9
  import { InstanceManagerService } from "./instance-manager.service";
10
10
  import { WebSocketChatService } from "./websocket-chat.service";
@@ -16,9 +16,11 @@ import { RestChatService } from "./rest-chat.service";
16
16
  import { TokenProgressBarComponent } from "./token-progress-bar/token-progress-bar.component";
17
17
  import { DebugMessageComponent } from "./debug-message/debug-message.component";
18
18
  import { HubConnectionState } from "@microsoft/signalr";
19
+ import { UtilsModule } from "@sinequa/components/utils";
19
20
  import * as i0 from "@angular/core";
20
21
  import * as i1 from "@angular/common";
21
22
  import * as i2 from "@angular/forms";
23
+ import * as i3 from "@sinequa/components/utils";
22
24
  export class ChatComponent extends AbstractFacet {
23
25
  constructor() {
24
26
  super();
@@ -38,6 +40,8 @@ export class ChatComponent extends AbstractFacet {
38
40
  this.messageHandlers = new Map();
39
41
  /** When the assistant answer a user question, automatically scroll down to the bottom of the discussion */
40
42
  this.automaticScrollToLastResponse = false;
43
+ /** When the assistant answer a user question, automatically focus to the chat input */
44
+ this.focusAfterResponse = false;
41
45
  /** Icon to use for the assistant messages */
42
46
  this.assistantMessageIcon = 'sq-sinequa';
43
47
  /** Event emitter triggered once the signalR connection is established */
@@ -54,10 +58,17 @@ export class ChatComponent extends AbstractFacet {
54
58
  this.openPreview = new EventEmitter();
55
59
  /** Event emitter triggered when the user clicks on a suggested action */
56
60
  this.suggestAction = new EventEmitter();
61
+ /** Event emitter triggered when the user clicks on a chat starter */
62
+ this.chatStarter = new EventEmitter();
57
63
  this.messages$ = new BehaviorSubject(undefined);
58
64
  this.question = '';
59
65
  this._actions = [];
60
- this.sub = new Subscription();
66
+ this._resetChatAction = new Action({
67
+ icon: 'fas fa-sync',
68
+ title: "Reset assistant",
69
+ action: () => this.newChat()
70
+ });
71
+ this._sub = new Subscription();
61
72
  this.changes$ = new BehaviorSubject(undefined);
62
73
  this.firstChangesHandled = false;
63
74
  this.isAtBottom = true;
@@ -75,16 +86,14 @@ export class ChatComponent extends AbstractFacet {
75
86
  'Other'
76
87
  ];
77
88
  this.issueType = '';
78
- this.showReportIssue = false;
89
+ this.reportType = 'dislike';
90
+ this.showReport = false;
79
91
  this.showDebugMessages = false;
80
- this._actions.push(new Action({
81
- icon: 'fas fa-sync',
82
- title: 'Reset chat',
83
- action: () => this.newChat()
84
- }));
92
+ this._reloadSubscription = undefined;
93
+ this._actions.push(this._resetChatAction);
85
94
  }
86
95
  ngOnInit() {
87
- this.sub.add(this.loginService.events.pipe(filter(e => e.type === 'login-complete'), tap(_ => this.instantiateChatService()), map(_ => this.chatService.initChatConfig()), switchMap(() => this.chatService.initConfig$), filter(initConfig => !!initConfig), switchMap(_ => this.chatService.init()), switchMap(_ => this.chatService.initProcess$), filter(success => !!success), tap(_ => {
96
+ this._sub.add(this.loginService.events.pipe(filter(e => e.type === 'login-complete'), tap(_ => this.instantiateChatService()), map(_ => this.chatService.initChatConfig()), switchMap(() => this.chatService.initConfig$), filter(initConfig => !!initConfig), switchMap(_ => this.chatService.init()), switchMap(_ => this.chatService.initProcess$), filter(success => !!success), tap(_ => {
88
97
  if (this.chatService instanceof WebSocketChatService) {
89
98
  this.connection.emit(this.chatService.connection);
90
99
  }
@@ -108,6 +117,12 @@ export class ChatComponent extends AbstractFacet {
108
117
  throw error;
109
118
  }
110
119
  })).subscribe());
120
+ this._sub.add(combineLatest([
121
+ this.chatService.streaming$,
122
+ this.chatService.stoppingGeneration$
123
+ ]).pipe(map(([streaming, stoppingGeneration]) => !!(streaming || stoppingGeneration))).subscribe((result) => {
124
+ this._resetChatAction.disabled = result;
125
+ }));
111
126
  }
112
127
  ngOnChanges(changes) {
113
128
  this.changes$.next(changes);
@@ -116,12 +131,19 @@ export class ChatComponent extends AbstractFacet {
116
131
  }
117
132
  }
118
133
  ngOnDestroy() {
119
- this.sub.unsubscribe();
120
- this.dataSubscription?.unsubscribe();
134
+ this._sub.unsubscribe();
135
+ this._dataSubscription?.unsubscribe();
136
+ this._reloadSubscription?.unsubscribe();
137
+ if (this.chatService instanceof WebSocketChatService) {
138
+ this.chatService.stopConnection();
139
+ }
121
140
  }
122
141
  get isAdmin() {
123
142
  return this.principalService.principal?.isAdministrator || false;
124
143
  }
144
+ get visibleMessagesCount() {
145
+ return this.messages$.value?.filter(m => m.additionalProperties.display).length || 0;
146
+ }
125
147
  /**
126
148
  * Instantiate the chat service based on the provided @input protocol
127
149
  * This chat service instance will then be stored in the instanceManagerService with provided @input instanceId as a key
@@ -141,6 +163,17 @@ export class ChatComponent extends AbstractFacet {
141
163
  this.instanceManagerService.storeInstance(this.instanceId, this.chatService);
142
164
  }
143
165
  get actions() { return this._actions; }
166
+ /**
167
+ * Handles the changes in the chat component.
168
+ * If the chat service is a WebSocketChatService, it handles the override of the message handlers if they exist.
169
+ * Initializes the chat with the provided chat messages if they exist, otherwise loads the default chat.
170
+ * If the chat is initialized, the initialization event is "Query", the query changes, and the queryChangeShouldTriggerReload function is provided,
171
+ * then the chat should be reloaded if the function returns true. Otherwise, the chat should be reloaded by default.
172
+ * It takes into account the ongoing streaming process and the ongoing stopping process to trigger that conditionally define the logic
173
+ * of the reload :
174
+ * - If the chat is streaming, then stop the generation and wait for the fetch to complete before reloading the chat.
175
+ * - If the chat is stopping the generation, then wait for the fetch to complete before reloading the chat.
176
+ */
144
177
  _handleChanges() {
145
178
  const changes = this.changes$.value;
146
179
  // If the chat service is a WebSocketChatService, handle the override of the message handlers if exists
@@ -175,11 +208,69 @@ export class ChatComponent extends AbstractFacet {
175
208
  */
176
209
  if (this.firstChangesHandled && changes?.query && this.config.modeSettings.initialization.event === 'Query') {
177
210
  if (this.queryChangeShouldTriggerReload ? this.queryChangeShouldTriggerReload(this._previousQuery, this.query) : true) {
178
- this._triggerReloadAfterQueryChange();
211
+ if (!!this.chatService.stoppingGeneration$.value) {
212
+ if (!this._reloadSubscription) {
213
+ // Create a subscription to wait for both streaming$ and stoppingGeneration$ to be false
214
+ this._reloadSubscription = combineLatest([
215
+ this.chatService.streaming$,
216
+ this.chatService.stoppingGeneration$
217
+ ])
218
+ .pipe(filter(([streaming, stopping]) => !streaming && !stopping), // Wait until both are false
219
+ take(1) // Complete after the first match
220
+ ).subscribe(() => {
221
+ // Execute the reload after the query change
222
+ this._triggerReloadAfterQueryChange();
223
+ // Update _previousQuery with the current query
224
+ this._previousQuery = JSON.parse(JSON.stringify(this.query));
225
+ // Clean up subscription and reset its value
226
+ this._reloadSubscription = undefined;
227
+ });
228
+ }
229
+ }
230
+ else if (!!this.chatService.streaming$.value) {
231
+ if (!this._reloadSubscription) {
232
+ this._reloadSubscription = this.chatService.stopGeneration()
233
+ .subscribe({
234
+ next: () => { },
235
+ error: () => {
236
+ // Clean up subscription and reset its value
237
+ this._reloadSubscription?.unsubscribe();
238
+ this._reloadSubscription = undefined;
239
+ },
240
+ complete: () => {
241
+ // Wait for the ongoing fetch to complete, then trigger the reload
242
+ this.chatService.streaming$.pipe(filter((streaming) => !streaming), take(1)).subscribe(() => {
243
+ // Execute the reload after the query change
244
+ this._triggerReloadAfterQueryChange();
245
+ // Update _previousQuery with the current query
246
+ this._previousQuery = JSON.parse(JSON.stringify(this.query));
247
+ // Clean up subscription and reset its value
248
+ this._reloadSubscription.unsubscribe();
249
+ this._reloadSubscription = undefined;
250
+ });
251
+ }
252
+ });
253
+ }
254
+ }
255
+ else {
256
+ // Execute the reload after the query change
257
+ this._triggerReloadAfterQueryChange();
258
+ // Update _previousQuery with the current query
259
+ this._previousQuery = JSON.parse(JSON.stringify(this.query));
260
+ }
261
+ }
262
+ else {
263
+ // Update _previousQuery with the current query
264
+ this._previousQuery = JSON.parse(JSON.stringify(this.query));
179
265
  }
180
- this._previousQuery = JSON.parse(JSON.stringify(this.query)); // Update the previous query
181
266
  }
182
267
  }
268
+ /**
269
+ * Triggers a reload after the query change.
270
+ * This method performs the necessary operations to reload the chat after a query change.
271
+ * It sets the system and user messages, resets the savedChatId, generates a new chatId,
272
+ * generates a new chat audit event, and handles the query mode.
273
+ */
183
274
  _triggerReloadAfterQueryChange() {
184
275
  const systemMsg = { role: 'system', content: this.config.defaultValues.systemPrompt, additionalProperties: { display: false } };
185
276
  const userMsg = { role: 'user', content: ChatService.formatPrompt(this.config.defaultValues.userPrompt, { principal: this.principalService.principal }), additionalProperties: { display: this.config.modeSettings.displayUserPrompt } };
@@ -188,25 +279,48 @@ export class ChatComponent extends AbstractFacet {
188
279
  this.chatService.generateAuditEvent('new-chat', { 'configuration': JSON.stringify(this.chatService.chatConfig$.value) }); // Generate a new chat audit event
189
280
  this._handleQueryMode(systemMsg, userMsg);
190
281
  }
282
+ /**
283
+ * Adds a scroll listener to the message list element.
284
+ * The listener is triggered when any of the following events occur:
285
+ * - Loading state changes
286
+ * - Messages change
287
+ * - Streaming state changes
288
+ * - Scroll event occurs on the message list element
289
+ *
290
+ * When the listener is triggered, it updates the `isAtBottom` property.
291
+ */
191
292
  _addScrollListener() {
192
- this.sub.add(merge(this.loading$, this.messages$, this.chatService.streaming$, fromEvent(this.messageList.nativeElement, 'scroll')).subscribe(() => {
293
+ this._sub.add(merge(this.loading$, this.messages$, this.chatService.streaming$, fromEvent(this.messageList.nativeElement, 'scroll')).subscribe(() => {
193
294
  this.isAtBottom = this._toggleScrollButtonVisibility();
194
295
  this.cdr.detectChanges();
195
296
  }));
196
297
  }
298
+ /**
299
+ * Get the model description based on the defaultValues service_id and model_id
300
+ */
197
301
  updateModelDescription() {
198
302
  this.modelDescription = this.chatService.getModel(this.config.defaultValues.service_id, this.config.defaultValues.model_id);
199
303
  this.cdr.detectChanges();
200
304
  }
305
+ /**
306
+ * Submits a question from the user.
307
+ * If the user is editing a previous message, removes all subsequent messages from the chat history.
308
+ * Triggers the fetch of the answer for the submitted question by calling _fetchAnswer().
309
+ * Clears the input value in the UI.
310
+ */
201
311
  submitQuestion() {
312
+ if (!!this.chatService.streaming$.value || !!this.chatService.stoppingGeneration$.value) {
313
+ return;
314
+ }
202
315
  if (this.question.trim() && this.messages$.value && this.chatService.chatHistory) {
203
316
  // When the user submits a question, if the user is editing a previous message, remove all subsequent messages from the chat history
204
317
  if (this.messageToEdit !== undefined) {
205
318
  // Update the messages in the UI
206
319
  this.messages$.next(this.messages$.value.slice(0, this.messageToEdit));
207
320
  // Update the raw messages in the chat history which is the clean version used to make the next request
208
- this.chatService.chatHistory = this.chatService.chatHistory.slice(0, this.messageToEdit);
321
+ this.chatService.chatHistory = this.chatService.chatHistory.slice(0, this.remappedMessageToEdit);
209
322
  this.messageToEdit = undefined;
323
+ this.remappedMessageToEdit = undefined;
210
324
  }
211
325
  // Remove the search warning message if exists
212
326
  if (this.chatService.chatHistory.at(-1)?.role === 'search-warning') {
@@ -219,6 +333,13 @@ export class ChatComponent extends AbstractFacet {
219
333
  this.questionInput.nativeElement.style.height = `auto`;
220
334
  }
221
335
  }
336
+ /**
337
+ * Triggers the fetch of the answer for the given question and updates the conversation.
338
+ * Generates an audit event for the user input.
339
+ *
340
+ * @param question - The question asked by the user.
341
+ * @param conversation - The current conversation messages.
342
+ */
222
343
  _fetchAnswer(question, conversation) {
223
344
  const userMsg = { role: 'user', content: question, additionalProperties: { display: true, isUserInput: true, additionalWorkflowProperties: this.config.additionalWorkflowProperties } };
224
345
  const messages = [...conversation, userMsg];
@@ -230,15 +351,15 @@ export class ChatComponent extends AbstractFacet {
230
351
  * Depending on the connection's state :
231
352
  * - If connected => given a list of messages, the chat endpoint is invoked for a continuation and updates the list of messages accordingly.
232
353
  * - If any other state => a connection error message is displayed in the chat.
233
- * @param messages
354
+ * @param messages The list of messages to invoke the chat endpoint with
234
355
  */
235
356
  fetch(messages) {
236
357
  this._updateConnectionStatus();
237
358
  this.cdr.detectChanges();
238
359
  if (this.isConnected) {
239
360
  this.loading$.next(true);
240
- this.dataSubscription?.unsubscribe();
241
- this.dataSubscription = this.chatService.fetch(messages, this.query)
361
+ this._dataSubscription?.unsubscribe();
362
+ this._dataSubscription = this.chatService.fetch(messages, this.query)
242
363
  .subscribe({
243
364
  next: res => this.updateData(res.history),
244
365
  error: () => {
@@ -250,6 +371,14 @@ export class ChatComponent extends AbstractFacet {
250
371
  this.terminateFetch();
251
372
  },
252
373
  complete: () => {
374
+ // Remove the last message if it's an empty message
375
+ // This is due to the manner in which the chat service handles consecutive messages
376
+ const lastMessage = this.messages$.value?.at(-1);
377
+ if (lastMessage?.role === 'assistant' && lastMessage?.content === ""
378
+ && !lastMessage?.additionalProperties?.$attachment && !lastMessage?.additionalProperties?.$progress
379
+ && !lastMessage?.additionalProperties?.$debug && !lastMessage?.additionalProperties?.$suggestedAction) {
380
+ this.messages$.next(this.messages$.value?.slice(0, -1));
381
+ }
253
382
  this.terminateFetch();
254
383
  }
255
384
  });
@@ -273,10 +402,21 @@ export class ChatComponent extends AbstractFacet {
273
402
  if (this.chatService instanceof WebSocketChatService) {
274
403
  // A one-time listener for reconnected event
275
404
  const onReconnectedHandler = () => {
405
+ // Get the messages without the last one (the connection error message)
276
406
  const messages = this.messages$.value.slice(0, -1);
277
- const lastMessage = messages.at(-1);
278
- if (lastMessage && lastMessage.role === 'user') { // And it is always the case: the last message is always from the user
279
- this.fetch(messages); // If the last message if from a user, an answer from the assistant is expected
407
+ // Find the last "user" message in the messages list
408
+ let index = messages.length - 1;
409
+ while (index >= 0 && messages[index].role !== 'user') {
410
+ index--;
411
+ }
412
+ // If a user message is found (and it should always be the case), remove all subsequent messages from the chat history
413
+ // Update the messages in the UI
414
+ // and fetch the answer from the assistant
415
+ if (index >= 0) {
416
+ this.messages$.next(this.messages$.value.slice(0, index + 1));
417
+ const remappedIndex = this._remapIndexInChatHistory(index);
418
+ this.chatService.chatHistory = this.chatService.chatHistory.slice(0, remappedIndex + 1);
419
+ this.fetch(this.chatService.chatHistory);
280
420
  }
281
421
  this.retrialAttempts = undefined; // Reset the number of retrial attempts
282
422
  /**
@@ -335,12 +475,18 @@ export class ChatComponent extends AbstractFacet {
335
475
  this.scrollDown();
336
476
  }
337
477
  }
478
+ /**
479
+ * @returns true if the chat discussion is scrolled down to the bottom, false otherwise
480
+ */
338
481
  _toggleScrollButtonVisibility() {
339
482
  if (this.messageList?.nativeElement) {
340
483
  return Math.round(this.messageList?.nativeElement.scrollHeight - this.messageList?.nativeElement.scrollTop - 1) <= this.messageList?.nativeElement.clientHeight;
341
484
  }
342
485
  return true;
343
486
  }
487
+ /**
488
+ * Scroll down to the bottom of the chat discussion
489
+ */
344
490
  scrollDown() {
345
491
  setTimeout(() => {
346
492
  if (this.messageList?.nativeElement) {
@@ -355,12 +501,39 @@ export class ChatComponent extends AbstractFacet {
355
501
  * If the savedChat feature is enabled, the list of saved chats will be refreshed
356
502
  */
357
503
  newChat() {
504
+ if (!!this.chatService.streaming$.value || !!this.chatService.stoppingGeneration$.value) {
505
+ return;
506
+ }
358
507
  this.chatService.setSavedChatId(undefined); // Reset the savedChatId
359
508
  this.chatService.generateChatId(); // Generate a new chatId
360
509
  this.chatService.listSavedChat(); // Refresh the list of saved chats
361
510
  this.chatService.generateAuditEvent('new-chat', { 'configuration': JSON.stringify(this.chatService.chatConfig$.value) }); // Generate a new chat audit event
362
511
  this.loadDefaultChat(); // Start a new chat
363
512
  }
513
+ /**
514
+ * Attaches the specified document IDs to the assistant.
515
+ * If the chat is streaming or stopping the generation, the operation is not allowed.
516
+ * If no document IDs are provided, the operation is not allowed.
517
+ * If the action for attaching a document is not defined at the application customization level, an error is logged.
518
+ * @param ids - An array of document IDs to attach.
519
+ */
520
+ attachToChat(ids) {
521
+ if (!!this.chatService.streaming$.value || !!this.chatService.stoppingGeneration$.value) {
522
+ return;
523
+ }
524
+ if (!ids || ids?.length < 1) {
525
+ return;
526
+ }
527
+ const attachDocAction = this.config.modeSettings.actions?.["attachDocAction"];
528
+ if (!attachDocAction) {
529
+ console.error(`No action is defined for attaching a document to the assistant "${this.instanceId}"`);
530
+ return;
531
+ }
532
+ const userMsg = { role: 'user', content: '', additionalProperties: { display: false, isUserInput: false, type: "Action", forcedWorkflow: attachDocAction.forcedWorkflow, forcedWorkflowProperties: { ...(attachDocAction.forcedWorkflowProperties || {}), ids }, additionalWorkflowProperties: this.config.additionalWorkflowProperties } };
533
+ const messages = [...this.chatService.chatHistory, userMsg];
534
+ this.messages$.next(messages);
535
+ this.fetch(messages);
536
+ }
364
537
  /**
365
538
  * Start the default chat with the defaultValues settings
366
539
  * If the chat is meant to be initialized with event === "Query", the corresponding user query message will be added to the chat history
@@ -420,7 +593,7 @@ export class ChatComponent extends AbstractFacet {
420
593
  */
421
594
  openChat(messages, savedChatId) {
422
595
  if (!messages || !Array.isArray(messages)) {
423
- console.error('Error occurs while trying to load the chat discussion. Invalid messages received :', messages);
596
+ console.error('Error occurs while trying to load the discussion. Invalid messages received :', messages);
424
597
  return;
425
598
  }
426
599
  if (savedChatId) {
@@ -453,16 +626,36 @@ export class ChatComponent extends AbstractFacet {
453
626
  this.question = '';
454
627
  this.terminateFetch();
455
628
  }
629
+ /**
630
+ * Fetch and Load the saved chat from the saved chat index.
631
+ * If the saved chat is found, the chat discussion will be loaded with the provided messages and chatId
632
+ */
456
633
  onLoadChat() {
457
634
  this.loading$.next(true);
458
- this.sub.add(this.chatService.loadSavedChat$
635
+ this._sub.add(this.chatService.loadSavedChat$
459
636
  .pipe(filter(savedChat => !!savedChat), switchMap(savedChat => this.chatService.getSavedChat(savedChat.id)), filter(savedChatHistory => !!savedChatHistory), tap(savedChatHistory => this.openChat(savedChatHistory.history, savedChatHistory.id))).subscribe());
460
637
  }
638
+ /**
639
+ * Stop the generation of the current assistant's answer.
640
+ * The fetch subscription will be terminated.
641
+ */
642
+ stopGeneration() {
643
+ this.chatService.stopGeneration().subscribe(() => this.terminateFetch());
644
+ }
645
+ /**
646
+ * Terminate the fetch process by unsubscribing from the data subscription and updating the loading status to false.
647
+ * Additionally, focus on the chat input if the focusAfterResponse flag is set to true.
648
+ */
461
649
  terminateFetch() {
462
- this.dataSubscription?.unsubscribe();
463
- this.dataSubscription = undefined;
650
+ this._dataSubscription?.unsubscribe();
651
+ this._dataSubscription = undefined;
464
652
  this.loading$.next(false);
465
653
  this.cdr.detectChanges();
654
+ if (this.focusAfterResponse) {
655
+ setTimeout(() => {
656
+ this.questionInput?.nativeElement.focus();
657
+ });
658
+ }
466
659
  }
467
660
  /**
468
661
  * Copy a previous user message of the chat history to the chat user input.
@@ -473,15 +666,18 @@ export class ChatComponent extends AbstractFacet {
473
666
  */
474
667
  editMessage(index) {
475
668
  this.messageToEdit = index;
476
- this.question = this.chatService.chatHistory[index].content;
477
- this.chatService.generateAuditEvent('edit.click', { 'rank': index });
669
+ this.remappedMessageToEdit = this._remapIndexInChatHistory(index);
670
+ this.question = this.chatService.chatHistory[this._remapIndexInChatHistory(index)].content;
671
+ this.chatService.generateAuditEvent('edit.click', { 'rank': this._remapIndexInChatHistory(index) });
478
672
  }
479
673
  /**
480
674
  * Copy a previous assistant message of the chat history to the clipboard.
481
675
  * @param index The index of the assistant's message to edit
482
676
  */
483
677
  copyMessage(index) {
484
- this.chatService.generateAuditEvent('copy.click', { 'rank': index });
678
+ // Remap the index in the chat history
679
+ const idx = this._remapIndexInChatHistory(index);
680
+ this.chatService.generateAuditEvent('copy.click', { 'rank': idx });
485
681
  }
486
682
  /**
487
683
  * Starting from the provided index, remove all subsequent messages from the chat history and the UI accordingly.
@@ -489,14 +685,50 @@ export class ChatComponent extends AbstractFacet {
489
685
  * @param index The index of the assistant's message to regenerate
490
686
  */
491
687
  regenerateMessage(index) {
492
- // Define the chat history based on which the assistant will generate a new answer
493
- const slicedMessages = this.chatService.chatHistory.slice(0, index);
494
- // Accordingly update the messages in the UI
495
- this.messages$.next(slicedMessages);
496
- // Fetch the answer
497
- this.fetch(slicedMessages);
498
- this.chatService.generateAuditEvent('regenerate.click', { 'rank': index });
688
+ // Update the messages in the UI by removing all subsequent 'assistant' messages starting from the provided index until the first previous 'user' message
689
+ let i = index;
690
+ while (i >= 0 && (this.messages$.value)[i].role !== 'user') {
691
+ i--;
692
+ }
693
+ // It should always be the case that i > 0
694
+ if (i >= 0) {
695
+ this.messages$.next(this.messages$.value.slice(0, i + 1));
696
+ // Remap the index of this found first previous 'user' message in the chat history
697
+ const idx = this._remapIndexInChatHistory(i);
698
+ // Define and Update the chat history based on which the assistant will generate a new answer
699
+ this.chatService.chatHistory = this.chatService.chatHistory.slice(0, idx + 1);
700
+ // Fetch the answer
701
+ this.fetch(this.chatService.chatHistory);
702
+ this.chatService.generateAuditEvent('regenerate.click', { 'rank': idx });
703
+ }
704
+ }
705
+ /**
706
+ * Remaps the index in the chat history.
707
+ * The chat history is a list of messages where some messages can be hidden (display set to false).
708
+ * The index provided as input is the index of the message in the chat history displayed in the UI.
709
+ * This function should be removed once the backend is updated to add the ids of the messages in the chat history
710
+ * @param index - The index to be remapped.
711
+ */
712
+ _remapIndexInChatHistory(index) {
713
+ // a copy of the chat history is created to avoid modifying the original chat history. Additionally, a rank is giving to each message.
714
+ const history = this.chatService.chatHistory.slice().map((message, idx) => {
715
+ return { ...message, additionalProperties: { ...message.additionalProperties, rank: idx } };
716
+ });
717
+ // Count the number of hidden messages in messages$ before the provided index
718
+ // This is mandatory to get the correct rank of the message in the chat history
719
+ // Since some hidden messages (like 'system' messages) are not displayed in the UI but have been counted in the provided index
720
+ const numberOfHiddenMessagesInMessages$BeforeIndex = this.messages$.value.slice(0, index).filter(message => !message.additionalProperties.display).length;
721
+ // remove all messages that have display set to false
722
+ // this is mandatory since at the point of time when the assistant answers a question,
723
+ // it might have some hidden messages (for example contextMessages) that are available in the chat history but don't figure in messages$ unless a new question is asked
724
+ const filteredHistory = history.filter(message => message.additionalProperties.display);
725
+ // return the index of the message in the filtered history
726
+ return filteredHistory[index - numberOfHiddenMessagesInMessages$BeforeIndex].additionalProperties.rank;
499
727
  }
728
+ /**
729
+ * Handles the key up event for 'Backspace' and 'Enter' keys.
730
+ * @param event - The keyboard event.
731
+ */
500
732
  onKeyUp(event) {
501
733
  switch (event.key) {
502
734
  case 'Backspace':
@@ -513,6 +745,11 @@ export class ChatComponent extends AbstractFacet {
513
745
  break;
514
746
  }
515
747
  }
748
+ /**
749
+ * Calculates and adjusts the height of the question input element based on its content.
750
+ * If the Enter key is pressed without the Shift key, it prevents the default behavior.
751
+ * @param event The keyboard event
752
+ */
516
753
  calculateHeight(event) {
517
754
  if (event?.key === 'Enter' && !event.shiftKey) {
518
755
  event?.preventDefault();
@@ -526,43 +763,59 @@ export class ChatComponent extends AbstractFacet {
526
763
  }
527
764
  /**
528
765
  * Send a "like" event on clicking on the thumb-up icon of an assistant's message
766
+ * @param message The assistant message to like
529
767
  * @param rank The rank of the message to like
530
768
  */
531
- onLike(rank) {
532
- this.chatService.generateAuditEvent('thumb-up.click', { rank });
769
+ onLike(message, rank) {
770
+ // Remap the index in the chat history
771
+ const idx = this._remapIndexInChatHistory(rank);
772
+ this.chatService.generateAuditEvent('thumb-up.click', { rank: idx });
773
+ this.reportType = 'like';
774
+ this.messageToReport = message;
775
+ this.reportComment = undefined;
776
+ this.reportRank = rank;
777
+ this.showReport = true;
533
778
  }
534
779
  /**
535
780
  * Send a "dislike" event on clicking on the thumb-down icon of an assistant's message.
536
781
  * It also opens the issue reporting dialog.
537
782
  * @param message The assistant message to dislike
538
- * @param rank The rank of the message to dislike
783
+ * @param index The rank of the message to dislike
539
784
  */
540
785
  onDislike(message, rank) {
541
- this.chatService.generateAuditEvent('thumb-down.click', { rank });
542
- this.messageRelatedIssue = message;
786
+ // Remap the index in the chat history
787
+ const idx = this._remapIndexInChatHistory(rank);
788
+ this.chatService.generateAuditEvent('thumb-down.click', { rank: idx });
789
+ this.reportType = 'dislike';
790
+ this.messageToReport = message;
543
791
  this.issueType = '';
544
- this.issueComment = undefined;
545
- this.issueRank = rank;
546
- this.showReportIssue = true;
792
+ this.reportComment = undefined;
793
+ this.reportRank = rank;
794
+ this.showReport = true;
547
795
  }
548
796
  /**
549
797
  * Report an issue related to the assistant's message.
550
798
  */
551
- sendIssue() {
799
+ sendReport() {
552
800
  const details = {
553
- 'report-type': this.issueType,
554
- 'comment': this.issueComment,
555
- 'text': this.messageRelatedIssue.content,
556
- 'rank': this.issueRank,
801
+ 'comment': this.reportComment,
802
+ 'text': this.messageToReport.content,
803
+ 'rank': this.reportRank,
557
804
  };
558
- this.chatService.generateAuditEvent('negative-report.send', details);
559
- this.showReportIssue = false;
805
+ if (this.reportType === 'dislike') {
806
+ details['report-type'] = this.issueType;
807
+ this.chatService.generateAuditEvent('negative-report.send', details);
808
+ }
809
+ else {
810
+ this.chatService.generateAuditEvent('positive-report.send', details);
811
+ }
812
+ this.showReport = false;
560
813
  }
561
814
  /**
562
- * Close the issue reporting dialog.
815
+ * Close the reporting dialog.
563
816
  */
564
- ignoreIssue() {
565
- this.showReportIssue = false;
817
+ ignoreReport() {
818
+ this.showReport = false;
566
819
  }
567
820
  /**
568
821
  * Handle the click on a reference's 'open preview'.
@@ -607,27 +860,69 @@ export class ChatComponent extends AbstractFacet {
607
860
  this.suggestAction.emit(action);
608
861
  this.chatService.generateAuditEvent('suggestedAction.click', { 'text': action.content, 'suggestedAction-type': action.type });
609
862
  }
863
+ /**
864
+ * Handle the click on a chat starter.
865
+ * @param starter the chat starter.
866
+ */
867
+ chatStarterClick(starter) {
868
+ this.chatStarter.emit(starter);
869
+ }
870
+ /**
871
+ * It looks for the debug messages available in the current group of "assistant" messages.
872
+ * By design, the debug messages are only available in the first visible message among the group "assistant" messages.
873
+ * @param index The rank of the message
874
+ * @returns The debug messages available in the current group of "assistant" messages
875
+ */
876
+ getDebugMessages(index) {
877
+ // If it is not an assistant message, return
878
+ if ((this.messages$.value)[index].role !== 'assistant') {
879
+ return [];
880
+ }
881
+ // Get the array of messages up to the indicated index
882
+ const array = this.messages$.value.slice(0, index + 1);
883
+ // If it is an assistant message, look for the debug messages available in the current group of "assistant" messages
884
+ // By design, the debug messages are only available in the first visible message among the group "assistant" messages.
885
+ const idx = this.chatService.firstVisibleAssistantMessageIndex(array);
886
+ if (idx > -1) {
887
+ return (this.messages$.value)[idx].additionalProperties.$debug || [];
888
+ }
889
+ return [];
890
+ }
610
891
  /**
611
892
  * Handle the click on the 'show log info' button of a message.
612
- * @param message The message of the ChatHistory to show its debug messages
893
+ * @param index The rank of the message
613
894
  */
614
- showDebug(message) {
615
- this.debugMessages = message.additionalProperties.$debug;
895
+ showDebug(index) {
896
+ this.debugMessages = this.getDebugMessages(index);
616
897
  this.showDebugMessages = true;
617
898
  this.cdr.detectChanges();
618
899
  }
900
+ /**
901
+ * Verify whether the current message is an assistant message and that all following messages are assistant ones
902
+ * Used to keep the "View progress" opened even though the assistant is sending additional messages after the current one
903
+ * @param messages the list of current messages
904
+ * @param index the index of the current message
905
+ * @returns if this messages and the following ones (if any) are the last ones
906
+ */
907
+ isAssistantLastMessages(messages, index) {
908
+ for (let i = index; i < messages.length; i++) {
909
+ if (messages[i].role !== 'assistant')
910
+ return false;
911
+ }
912
+ return true;
913
+ }
619
914
  }
620
915
  ChatComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ChatComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
621
- ChatComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: ChatComponent, isStandalone: true, selector: "sq-chat-v3", inputs: { instanceId: "instanceId", query: "query", queryChangeShouldTriggerReload: "queryChangeShouldTriggerReload", protocol: "protocol", messageHandlers: "messageHandlers", automaticScrollToLastResponse: "automaticScrollToLastResponse", chat: "chat", assistantMessageIcon: "assistantMessageIcon", userMessageIcon: "userMessageIcon", connectionErrorMessageIcon: "connectionErrorMessageIcon", searchWarningMessageIcon: "searchWarningMessageIcon" }, outputs: { connection: "connection", loading$: "loading", _config: "config", data: "data", openDocument: "openDocument", openPreview: "openPreview", suggestAction: "suggestAction" }, providers: [
916
+ ChatComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: ChatComponent, isStandalone: true, selector: "sq-chat-v3", inputs: { instanceId: "instanceId", query: "query", queryChangeShouldTriggerReload: "queryChangeShouldTriggerReload", protocol: "protocol", messageHandlers: "messageHandlers", automaticScrollToLastResponse: "automaticScrollToLastResponse", focusAfterResponse: "focusAfterResponse", chat: "chat", assistantMessageIcon: "assistantMessageIcon", userMessageIcon: "userMessageIcon", connectionErrorMessageIcon: "connectionErrorMessageIcon", searchWarningMessageIcon: "searchWarningMessageIcon" }, outputs: { connection: "connection", loading$: "loading", _config: "config", data: "data", openDocument: "openDocument", openPreview: "openPreview", suggestAction: "suggestAction", chatStarter: "chatStarter" }, providers: [
622
917
  RestChatService,
623
918
  WebSocketChatService
624
- ], queries: [{ propertyName: "loadingTpl", first: true, predicate: ["loadingTpl"], descendants: true }, { propertyName: "reportIssueTpl", first: true, predicate: ["reportIssueTpl"], descendants: true }, { propertyName: "tokenConsumptionTpl", first: true, predicate: ["tokenConsumptionTpl"], descendants: true }, { propertyName: "debugMessagesTpl", first: true, predicate: ["debugMessagesTpl"], descendants: true }], viewQueries: [{ propertyName: "messageList", first: true, predicate: ["messageList"], descendants: true }, { propertyName: "questionInput", first: true, predicate: ["questionInput"], descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<ng-container *ngIf=\"!initializationError\">\n <div *ngIf=\"messages$ | async as messages; else loadingTpl || loadingTplDefault\" class=\"h-100 d-flex flex-column\">\n <!-- Token consumption -->\n <div class=\"ms-1\" *ngIf=\"config?.globalSettings?.displayUserQuotaConsumption || config?.globalSettings?.displayChatTokensConsumption\">\n <ng-container *ngTemplateOutlet=\"tokenConsumptionTpl || defaultTokenConsumptionTpl; context: { $implicit: instanceId }\"></ng-container>\n </div>\n\n <!-- Chat Messages -->\n <ul class=\"list-group list-group-flush overflow-auto flex-grow-1 pe-2 pb-2\" #messageList>\n <ng-container *ngFor=\"let message of messages; let index = index; let last = last\">\n <!-- Regular messages -->\n <li class=\"list-group-item\" [style.--bs-list-group-item-padding-y.rem]=\"'0.6'\" *ngIf=\"message.additionalProperties.display\"\n [class.opacity-50]=\"messageToEdit && messageToEdit < index + 1\">\n <sq-chat-message\n [class.sq-user-message]=\"message.role === 'user'\"\n [class.last-message]=\"last\"\n [message]=\"message\"\n [conversation]=\"messages\"\n [suggestedActions]=\"last ? message.additionalProperties.$suggestedAction : undefined\"\n [assistantMessageIcon]=\"assistantMessageIcon\"\n [userMessageIcon]=\"userMessageIcon\"\n [connectionErrorMessageIcon]=\"connectionErrorMessageIcon\"\n [searchWarningMessageIcon]=\"searchWarningMessageIcon\"\n [streaming]=\"last && (chatService.streaming$ | async)\"\n [canEdit]=\"(loading$ | async) === false && ((chatService.streaming$ | async) === false || !last) && messageToEdit === undefined && message.role === 'user'\"\n [canRegenerate]=\"(loading$ | async) === false && (chatService.streaming$ | async) === false && messageToEdit === undefined && message.role === 'assistant' && last\"\n [canCopy]=\"((chatService.streaming$ | async) === false || !last) && messageToEdit === undefined && message.role !== 'connection-error' && message.role !== 'search-warning'\"\n [canDebug]=\"((chatService.streaming$ | async) === false || !last) && message.role === 'assistant' && isAdmin && message.additionalProperties.$debug\"\n [canLike]=\"((chatService.streaming$ | async) === false || !last) && message.role === 'assistant'\"\n [canDislike]=\"((chatService.streaming$ | async) === false || !last) && message.role === 'assistant'\"\n (edit)=\"editMessage(index)\"\n (copy)=\"copyMessage(index)\"\n (regenerate)=\"regenerateMessage(index)\"\n (openDocument)=\"openOriginalAttachment($event)\"\n (openPreview)=\"openAttachmentPreview($event)\"\n (suggestAction)=\"suggestActionClick($event, index)\"\n (like)=\"onLike(index)\"\n (dislike)=\"onDislike($event, index)\"\n (debug)=\"showDebug($event)\">\n </sq-chat-message>\n </li>\n </ng-container>\n <!-- Loading spinner -->\n <li class=\"list-group-item\" *ngIf=\"(loading$ | async) === true\">\n <ng-container *ngTemplateOutlet=\"loadingTpl || loadingTplDefault\"></ng-container>\n </li>\n </ul>\n\n <!-- Reporting an issue form -->\n <div class=\"issue-report bg-light pt-3 pb-2\" *ngIf=\"showReportIssue\">\n <ng-container *ngTemplateOutlet=\"reportIssueTpl || reportIssueTplDefault; context: { $implicit: messageRelatedIssue, rank: issueRank }\"></ng-container>\n </div>\n\n <!-- User text input -->\n <div class=\"user-input mt-auto\" *ngIf=\"!showReportIssue\">\n <div class=\"py-2\">\n <div [hidden]=\"!isConnected\">\n <ng-container *ngIf=\"enabledUserInput\" [ngTemplateOutlet]=\"inputTpl\"></ng-container>\n </div>\n <!-- Retry button -->\n <button [hidden]=\"isConnected\" class=\"btn mb-4 ast-error ast-btn sq-retry\" (click)=\"retryFetch()\">\n <span>Try again</span>\n <span *ngIf=\"retrialAttempts\" class=\"ms-2 attempts\">{{ retrialAttempts }}</span>\n </button>\n <div class=\"text-end small text-muted px-3\" *ngIf=\"!!config?.globalSettings?.disclaimer\">\n {{ config?.globalSettings?.disclaimer }}\n </div>\n </div>\n </div>\n\n <!-- Floating scroll button -->\n <div *ngIf=\"!isAtBottom && !showReportIssue\" class=\"sq-floating-scroll\" [ngClass]=\"enabledUserInput ? 'sq-floating-scroll--when-user-input' : 'sq-floating-scroll--without-user-input'\">\n <button class=\"btn shadow\" (click)=\"scrollDown()\">\n <i class=\"fas fa-angle-double-down\"></i>\n </button>\n </div>\n </div>\n</ng-container>\n\n<!-- NG TEMPLATES-->\n\n<ng-template #loadingTplDefault>\n <div class=\"spinner-grow text-primary d-block mx-auto my-5\" role=\"status\">\n <span class=\"visually-hidden\">Loading...</span>\n </div>\n</ng-template>\n\n<ng-template #inputTpl>\n <div class=\"px-3 py-1\">\n <div class=\"ast-input-container\">\n <button disabled class=\"btn btn-light\">\n <i class=\"fas fa-search\"></i>\n </button>\n <textarea #questionInput rows=\"1\"\n type=\"text\" class=\"form-control\"\n placeholder=\"Ask something\" autofocus\n [(ngModel)]=\"question\"\n (keyup)=\"onKeyUp($event)\"\n (keydown)=\"calculateHeight($event)\"\n [disabled]=\"(loading$ | async) || (chatService.streaming$ | async)\">\n </textarea>\n <button\n *ngIf=\"!(chatService.streaming$ | async) && !(loading$ | async)\"\n type=\"button\"\n class=\"btn btn-light ms-2\"\n title=\"Send message\"\n (click)=\"submitQuestion()\">\n <i class=\"fas fa-paper-plane\"></i>\n </button>\n <!--<button\n *ngIf=\"(chatService.streaming$ | async)\"\n type=\"button\"\n class=\"btn btn-light ms-2\"\n title=\"Stop generating\"\n (click)=\"terminateFetch()\">\n <i class=\"fas fa-stop\"></i>\n </button>-->\n <button\n *ngIf=\"messageToEdit\"\n type=\"button\"\n class=\"btn btn-light ms-2\"\n title=\"Cancel edition\"\n (click)=\"messageToEdit = undefined; question = ''\">\n <i class=\"fas fa-undo-alt\"></i>\n </button>\n </div>\n </div>\n</ng-template>\n\n<ng-template #reportIssueTplDefault let-message let-rank=\"rank\">\n <div class=\"px-3\">\n <h5>Issue type</h5>\n <select class=\"form-select mb-4\" [(ngModel)]=\"issueType\">\n <option [value]=\"''\">Choose an issue type</option>\n <option *ngFor=\"let type of (issueTypes ?? defaultIssueTypes)\">{{type}}</option>\n </select>\n <h5>Comment (optional)</h5>\n <textarea class=\"form-control\" [(ngModel)]=\"issueComment\" placeholder=\"What was unsatisfying about this response?\"></textarea>\n <div class=\"d-flex flex-row-reverse mt-2\">\n <button class=\"btn btn-primary\" [disabled]=\"!issueType\" (click)=\"sendIssue()\">Send</button>\n <button class=\"btn btn-light\" (click)=\"ignoreIssue()\">Cancel</button>\n </div>\n </div>\n</ng-template>\n\n<ng-template #defaultTokenConsumptionTpl let-instanceId>\n <sq-token-progress-bar\n [instanceId]=\"instanceId\">\n </sq-token-progress-bar>\n</ng-template>\n\n<div class=\"debug-messages\" [class.displayed]=\"showDebugMessages\">\n <button *ngIf=\"showDebugMessages\" class=\"btn btn-light shadow back-btn\" (click)=\"showDebugMessages=false\">\n <i class=\"fas fa-chevron-right\"></i>\n </button>\n <ng-container *ngTemplateOutlet=\"debugMessagesTpl || defaultDebugMessagesTpl; context: { $implicit: debugMessages }\">\n </ng-container>\n</div>\n\n<ng-template #defaultDebugMessagesTpl let-debugMessages>\n <sq-debug-message [data]=\"debugMessages\"></sq-debug-message>\n</ng-template>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-error{background-color:var(--ast-error-bg, rgba(249, 58, 55, .2))}.ast-error:hover{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.ast-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference,:host ::ng-deep .attachment .reference{position:relative;bottom:var(--ast-reference-bottom, .3em);font-weight:var(--ast-reference-font-weight, bold);padding:var(--ast-reference-padding, 0 .2em);margin:var(--ast-reference-margin, 0 .1em);border-radius:var(--ast-reference-border-radius, .2em);background-color:var(--ast-reference-background-color, lightblue);color:var(--ast-reference-color, black)}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference{font-size:var(--ast-reference-message-font-size, .7em)}:host ::ng-deep .attachment .reference{font-size:var(--ast-reference-attachment-font-size, 13px)}:host{font-size:.875rem}:host>div>.user-input>div:not(.progress),:host>div>.issue-report>div,:host>div>ul>li{width:var(--ast-chat-container-width, 100%);max-width:100%;margin-left:auto;margin-right:auto}:host>div>ul{padding-top:var(--ast-chat-padding-top, 0);padding-bottom:var(--ast-chat-padding-bottom, 0)}li.attachment>p{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;-webkit-line-clamp:3}li.attachment.expanded>p{display:block}.progress{--bs-progress-height: 3px}.progress.disabled{--bs-progress-height: 20px;--bs-progress-bar-bg: var(--bs-danger)}.user-input{z-index:1}.user-input ul.list-group{max-height:30vh}.form-control:disabled{background-color:#ededed}a.disabled{cursor:default;opacity:.5}.no-max-height{max-height:initial!important}.sq-floating-scroll{position:absolute;right:50%;text-align:center}.sq-floating-scroll--when-user-input{bottom:75px}.sq-floating-scroll--without-user-input{bottom:15px}.sq-floating-scroll .btn{background-color:#fff}.sq-floating-scroll .btn:hover{background-color:#fff;opacity:.9}.ast-input-container{display:flex;align-items:end;background-color:var(--ast-input-bg, #F8F8F8);border-radius:var(--ast-size-3, .75rem)}.ast-input-container>i{padding-left:var(--ast-size-3, .75rem);color:var(--ast-muted-color, rgba(33, 37, 41, .75))}.ast-input-container textarea{padding-left:var(--ast-size-3, .75rem);padding-right:var(--ast-size-3, .75rem);resize:none}.ast-input-container textarea,.ast-input-container button,.ast-input-container button:hover{background-color:transparent;border:0}.ast-input-container button:hover{color:var(--ast-primary-color, #005DA7)}.ast-input-container button:not(:hover){color:var(--ast-muted-color, rgba(33, 37, 41, .75))}sq-chat-message.sq-user-message{float:var(--ast-user-message-float, none)}sq-token-progress-bar{z-index:10;position:absolute;top:0;right:0}.debug-messages{position:fixed;z-index:999999;right:-60%;top:0;width:60%;height:100%;transition:all .5s ease;background-color:var(--bs-body-bg);overflow:auto}.debug-messages .back-btn{position:fixed;right:0%;transition:all .5s ease}.debug-messages.displayed{right:0}.debug-messages.displayed .back-btn{right:60%}.debug-messages sq-debug-message:first-of-type{display:block;width:100%}.sq-retry{display:flex;margin:auto;font-weight:var(--font-weight-bold, 500)}.sq-retry .attempts{display:flex;border-radius:100%;background:white;height:20px;width:20px;place-content:center;align-items:center}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ChatMessageComponent, selector: "sq-chat-message", inputs: ["message", "conversation", "suggestedActions", "assistantMessageIcon", "userMessageIcon", "connectionErrorMessageIcon", "searchWarningMessageIcon", "streaming", "canEdit", "canRegenerate", "canCopy", "canDebug", "canLike", "canDislike"], outputs: ["openDocument", "openPreview", "suggestAction", "edit", "copy", "regenerate", "like", "dislike", "debug"] }, { kind: "component", type: TokenProgressBarComponent, selector: "sq-token-progress-bar", inputs: ["instanceId"] }, { kind: "component", type: DebugMessageComponent, selector: "sq-debug-message", inputs: ["data", "level", "parentColor"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
919
+ ], queries: [{ propertyName: "loadingTpl", first: true, predicate: ["loadingTpl"], descendants: true }, { propertyName: "reportTpl", first: true, predicate: ["reportTpl"], descendants: true }, { propertyName: "tokenConsumptionTpl", first: true, predicate: ["tokenConsumptionTpl"], descendants: true }, { propertyName: "debugMessagesTpl", first: true, predicate: ["debugMessagesTpl"], descendants: true }], viewQueries: [{ propertyName: "messageList", first: true, predicate: ["messageList"], descendants: true }, { propertyName: "questionInput", first: true, predicate: ["questionInput"], descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<ng-container *ngIf=\"!initializationError\">\n <div *ngIf=\"messages$ | async as messages; else loadingTpl || loadingTplDefault\" class=\"h-100 d-flex flex-column\">\n <!-- Token consumption -->\n <div class=\"ms-1\" *ngIf=\"config?.globalSettings?.displayUserQuotaConsumption || config?.globalSettings?.displayChatTokensConsumption\">\n <ng-container *ngTemplateOutlet=\"tokenConsumptionTpl || defaultTokenConsumptionTpl; context: { $implicit: instanceId }\"></ng-container>\n </div>\n\n <!-- Chat Messages -->\n <ul class=\"list-group list-group-flush overflow-auto flex-grow-1 pe-2 pb-2\" #messageList>\n <ng-container *ngFor=\"let message of messages; let index = index; let last = last\">\n <!-- Regular messages -->\n <li class=\"list-group-item\"\n *ngIf=\"message.additionalProperties.display\"\n [style.--bs-list-group-item-padding-y.rem]=\"'0.6'\"\n [class.opacity-50]=\"messageToEdit && messageToEdit < index + 1\">\n <sq-chat-message\n [class.sq-user-message]=\"message.role === 'user'\"\n [class.last-message]=\"last\"\n [message]=\"message\"\n [conversation]=\"messages\"\n [suggestedActions]=\"last ? message.additionalProperties.$suggestedAction : undefined\"\n [chatStarters]=\"visibleMessagesCount === 1 ? config.modeSettings.initialization.chatStarters : undefined\"\n [assistantMessageIcon]=\"assistantMessageIcon\"\n [userMessageIcon]=\"userMessageIcon\"\n [connectionErrorMessageIcon]=\"connectionErrorMessageIcon\"\n [searchWarningMessageIcon]=\"searchWarningMessageIcon\"\n [streaming]=\"(chatService.streaming$ | async) && (last || isAssistantLastMessages(messages, index))\"\n [canEdit]=\"(loading$ | async) === false && ((chatService.streaming$ | async) === false || !last) && messageToEdit === undefined && message.role === 'user'\"\n [canCopy]=\"((chatService.streaming$ | async) === false || !last) && messageToEdit === undefined && message.role !== 'connection-error' && message.role !== 'search-warning'\"\n [canLike]=\"((chatService.streaming$ | async) === false || !last) && message.role === 'assistant'\"\n [canDislike]=\"((chatService.streaming$ | async) === false || !last) && message.role === 'assistant'\"\n [canDebug]=\"(((chatService.streaming$ | async) === false && last) || (!last && messages[index+1].role !== 'assistant')) && message.role === 'assistant' && isAdmin && (getDebugMessages(index).length > 0) && config?.defaultValues.debug\"\n [canRegenerate]=\"(loading$ | async) === false && (((chatService.streaming$ | async) === false && last) || (!last && messages[index+1].role !== 'assistant')) && message.role === 'assistant' && messageToEdit === undefined\"\n (edit)=\"editMessage(index)\"\n (copy)=\"copyMessage(index)\"\n (regenerate)=\"regenerateMessage(index)\"\n (openDocument)=\"openOriginalAttachment($event)\"\n (openPreview)=\"openAttachmentPreview($event)\"\n (suggestAction)=\"suggestActionClick($event, index)\"\n (chatStarterClicked)=\"chatStarterClick($event)\"\n (like)=\"onLike($event, index)\"\n (dislike)=\"onDislike($event, index)\"\n (debug)=\"showDebug(index)\">\n </sq-chat-message>\n </li>\n </ng-container>\n <!-- Loading spinner -->\n <li class=\"list-group-item\" *ngIf=\"(loading$ | async) === true\">\n <ng-container *ngTemplateOutlet=\"loadingTpl || loadingTplDefault\"></ng-container>\n </li>\n </ul>\n\n <!-- Reporting a feedback form -->\n <div class=\"issue-report bg-light pt-3 pb-2\" *ngIf=\"showReport\">\n <ng-container *ngTemplateOutlet=\"reportTpl || reportTplDefault; context: { $implicit: messageToReport, rank: reportRank, type: reportType }\"></ng-container>\n </div>\n\n <!-- User text input -->\n <div class=\"user-input mt-auto\" *ngIf=\"!showReport\">\n <div class=\"py-2\">\n <div [hidden]=\"!isConnected\">\n <ng-container *ngIf=\"enabledUserInput\" [ngTemplateOutlet]=\"inputTpl\"></ng-container>\n </div>\n <!-- Retry button -->\n <button [hidden]=\"isConnected\" class=\"btn mb-4 ast-error ast-btn sq-retry\" (click)=\"retryFetch()\">\n <span>Try again</span>\n <span *ngIf=\"retrialAttempts\" class=\"ms-2 attempts\">{{ retrialAttempts }}</span>\n </button>\n <div class=\"text-end small text-muted px-3\" *ngIf=\"!!config?.globalSettings?.disclaimer\">\n {{ config?.globalSettings?.disclaimer }}\n </div>\n </div>\n </div>\n\n <!-- Floating scroll button -->\n <div *ngIf=\"!isAtBottom && !showReport\" class=\"sq-floating-scroll\" [ngClass]=\"enabledUserInput ? 'sq-floating-scroll--when-user-input' : 'sq-floating-scroll--without-user-input'\">\n <button class=\"btn shadow\" (click)=\"scrollDown()\">\n <i class=\"fas fa-angle-double-down\"></i>\n </button>\n </div>\n </div>\n</ng-container>\n\n<!-- NG TEMPLATES-->\n\n<ng-template #loadingTplDefault>\n <div class=\"spinner-grow text-primary d-block mx-auto my-5\" role=\"status\">\n <span class=\"visually-hidden\">Loading...</span>\n </div>\n</ng-template>\n\n<ng-template #inputTpl>\n <div class=\"px-3 py-1\">\n <div class=\"ast-input-container\">\n <button disabled class=\"btn btn-light\">\n <i class=\"fas fa-search\"></i>\n </button>\n <textarea #questionInput rows=\"1\"\n type=\"text\" class=\"form-control\"\n placeholder=\"Ask something\" autofocus\n [(ngModel)]=\"question\"\n (keyup)=\"onKeyUp($event)\"\n (keydown)=\"calculateHeight($event)\"\n [disabled]=\"(loading$ | async) || (chatService.streaming$ | async) || (chatService.stoppingGeneration$ | async)\">\n </textarea>\n <button\n *ngIf=\"!(chatService.streaming$ | async) && !(loading$ | async) && !(chatService.stoppingGeneration$ | async)\"\n type=\"button\"\n class=\"btn btn-light ms-2\"\n sqTooltip=\"Send message\"\n (click)=\"submitQuestion()\">\n <i class=\"fas fa-paper-plane\"></i>\n </button>\n <button\n *ngIf=\"messageToEdit\"\n type=\"button\"\n class=\"btn btn-light ms-2\"\n sqTooltip=\"Cancel edition\"\n (click)=\"messageToEdit = undefined; question = ''\">\n <i class=\"fas fa-undo-alt\"></i>\n </button>\n <span *ngIf=\"(chatService.streaming$ | async) && !(chatService.stoppingGeneration$ | async)\" class=\"processing ms-2\">\n Generating <i class=\"ms-1 fas fa-spinner fa-pulse\"></i>\n </span>\n <span *ngIf=\"(chatService.stoppingGeneration$ | async)\" class=\"processing ms-2\">\n Stopping <i class=\"ms-1 fas fa-spinner fa-pulse\"></i>\n </span>\n <button\n *ngIf=\"(chatService.streaming$ | async) && !(chatService.stoppingGeneration$ | async)\"\n type=\"button\"\n class=\"btn btn-light ms-2\"\n sqTooltip=\"Stop generating\"\n (click)=\"stopGeneration()\">\n <i class=\"fas fa-stop\"></i>\n </button>\n </div>\n </div>\n</ng-template>\n\n<ng-template #reportTplDefault let-message let-rank=\"rank\" let-type=\"type\">\n <div class=\"px-3\">\n <ng-container *ngIf=\"type === 'dislike'\">\n <h5>Issue type</h5>\n <select class=\"form-select mb-4\" [(ngModel)]=\"issueType\">\n <option [value]=\"''\">Choose an issue type</option>\n <option *ngFor=\"let type of (issueTypes ?? defaultIssueTypes)\">{{type}}</option>\n </select>\n <h5>What was unsatisfying about this response? (optional)</h5>\n </ng-container>\n <ng-container *ngIf=\"type === 'like'\">\n <h5>Why did you like this answer? (optional)</h5>\n </ng-container>\n <textarea class=\"form-control\" [(ngModel)]=\"reportComment\" placeholder=\"Write your comment\"></textarea>\n <div class=\"d-flex flex-row-reverse mt-2\">\n <button class=\"btn btn-primary\" [disabled]=\"type === 'dislike' && !issueType\" (click)=\"sendReport()\">Send</button>\n <button class=\"btn btn-light\" (click)=\"ignoreReport()\">Cancel</button>\n </div>\n </div>\n</ng-template>\n\n<ng-template #defaultTokenConsumptionTpl let-instanceId>\n <sq-token-progress-bar\n [instanceId]=\"instanceId\">\n </sq-token-progress-bar>\n</ng-template>\n\n<div class=\"debug-messages\" [class.displayed]=\"showDebugMessages\">\n <button *ngIf=\"showDebugMessages\" class=\"btn btn-light shadow back-btn\" (click)=\"showDebugMessages=false\">\n <i class=\"fas fa-chevron-right\"></i>\n </button>\n <ng-container *ngTemplateOutlet=\"debugMessagesTpl || defaultDebugMessagesTpl; context: { $implicit: debugMessages }\">\n </ng-container>\n</div>\n\n<ng-template #defaultDebugMessagesTpl let-debugMessages>\n <sq-debug-message [data]=\"debugMessages\"></sq-debug-message>\n</ng-template>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-error{background-color:var(--ast-error-bg, rgba(249, 58, 55, .2));color:var(--ast-action-buttons-color, inherit)}.ast-error:hover{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.ast-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black;--ast-action-buttons-color: white;--ast-action-buttons-hover-color: #6dbee6}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference,:host ::ng-deep .attachment .reference{position:relative;bottom:var(--ast-reference-bottom, .3em);font-weight:var(--ast-reference-font-weight, bold);padding:var(--ast-reference-padding, 0 .2em);margin:var(--ast-reference-margin, 0 .1em);border-radius:var(--ast-reference-border-radius, .2em);background-color:var(--ast-reference-background-color, lightblue);color:var(--ast-reference-color, black)}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference{font-size:var(--ast-reference-message-font-size, .7em)}:host ::ng-deep .attachment .reference{font-size:var(--ast-reference-attachment-font-size, 13px)}:host{font-size:.875rem}:host>div>.user-input>div:not(.progress),:host>div>.issue-report>div,:host>div>ul>li{width:var(--ast-chat-container-width, 100%);max-width:100%;margin-left:auto;margin-right:auto}:host>div>ul{padding-top:var(--ast-chat-padding-top, 0);padding-bottom:var(--ast-chat-padding-bottom, 0)}li.attachment>p{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;-webkit-line-clamp:3}li.attachment.expanded>p{display:block}.progress{--bs-progress-height: 3px}.progress.disabled{--bs-progress-height: 20px;--bs-progress-bar-bg: var(--bs-danger)}.user-input{z-index:1}.user-input ul.list-group{max-height:30vh}.form-control:disabled{background-color:#ededed}a.disabled{cursor:default;opacity:.5}.no-max-height{max-height:initial!important}.sq-floating-scroll{position:absolute;right:50%;text-align:center}.sq-floating-scroll--when-user-input{bottom:75px}.sq-floating-scroll--without-user-input{bottom:15px}.sq-floating-scroll .btn{background-color:#fff}.sq-floating-scroll .btn:hover{background-color:#fff;opacity:.9}.ast-input-container{display:flex;align-items:center;background-color:var(--ast-input-bg, #F8F8F8);border-radius:var(--ast-size-3, .75rem)}.ast-input-container>i{padding-left:var(--ast-size-3, .75rem);color:var(--ast-muted-color, rgba(33, 37, 41, .75))}.ast-input-container textarea{padding-left:var(--ast-size-3, .75rem);padding-right:var(--ast-size-3, .75rem);resize:none}.ast-input-container textarea,.ast-input-container button,.ast-input-container button:hover{background-color:transparent;border:0}.ast-input-container button:hover{color:var(--ast-primary-color, #005DA7)}.ast-input-container button:not(:hover){color:var(--ast-muted-color, rgba(33, 37, 41, .75))}.ast-input-container .processing{display:flex;align-items:center;color:var(--ast-secondary-color, #FF732E)}sq-chat-message.sq-user-message{float:var(--ast-user-message-float, none)}sq-token-progress-bar{z-index:10;position:absolute;top:0;right:0}.debug-messages{position:fixed;z-index:999999;right:-60%;top:0;width:60%;height:100%;transition:all .5s ease;background-color:var(--bs-body-bg);overflow:auto}.debug-messages .back-btn{position:fixed;right:0%;transition:all .5s ease}.debug-messages.displayed{right:0}.debug-messages.displayed .back-btn{right:60%}.debug-messages sq-debug-message:first-of-type{display:block;width:100%}.sq-retry{display:flex;margin:auto;font-weight:var(--font-weight-bold, 500)}.sq-retry .attempts{display:flex;border-radius:100%;background:white;height:20px;width:20px;place-content:center;align-items:center}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ChatMessageComponent, selector: "sq-chat-message", inputs: ["message", "conversation", "suggestedActions", "chatStarters", "assistantMessageIcon", "userMessageIcon", "connectionErrorMessageIcon", "searchWarningMessageIcon", "streaming", "canEdit", "canRegenerate", "canCopy", "canDebug", "canLike", "canDislike"], outputs: ["openDocument", "openPreview", "suggestAction", "chatStarterClicked", "edit", "copy", "regenerate", "like", "dislike", "debug"] }, { kind: "component", type: TokenProgressBarComponent, selector: "sq-token-progress-bar", inputs: ["instanceId"] }, { kind: "component", type: DebugMessageComponent, selector: "sq-debug-message", inputs: ["data", "level", "parentColor"] }, { kind: "ngmodule", type: UtilsModule }, { kind: "directive", type: i3.TooltipDirective, selector: "[sqTooltip]", inputs: ["sqTooltip", "sqTooltipData", "sqTooltipTemplate", "placement", "fallbackPlacements", "delay", "hoverableTooltip", "tooltipClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
625
920
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ChatComponent, decorators: [{
626
921
  type: Component,
627
922
  args: [{ selector: 'sq-chat-v3', providers: [
628
923
  RestChatService,
629
924
  WebSocketChatService
630
- ], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, FormsModule, ChatMessageComponent, TokenProgressBarComponent, DebugMessageComponent], template: "<ng-container *ngIf=\"!initializationError\">\n <div *ngIf=\"messages$ | async as messages; else loadingTpl || loadingTplDefault\" class=\"h-100 d-flex flex-column\">\n <!-- Token consumption -->\n <div class=\"ms-1\" *ngIf=\"config?.globalSettings?.displayUserQuotaConsumption || config?.globalSettings?.displayChatTokensConsumption\">\n <ng-container *ngTemplateOutlet=\"tokenConsumptionTpl || defaultTokenConsumptionTpl; context: { $implicit: instanceId }\"></ng-container>\n </div>\n\n <!-- Chat Messages -->\n <ul class=\"list-group list-group-flush overflow-auto flex-grow-1 pe-2 pb-2\" #messageList>\n <ng-container *ngFor=\"let message of messages; let index = index; let last = last\">\n <!-- Regular messages -->\n <li class=\"list-group-item\" [style.--bs-list-group-item-padding-y.rem]=\"'0.6'\" *ngIf=\"message.additionalProperties.display\"\n [class.opacity-50]=\"messageToEdit && messageToEdit < index + 1\">\n <sq-chat-message\n [class.sq-user-message]=\"message.role === 'user'\"\n [class.last-message]=\"last\"\n [message]=\"message\"\n [conversation]=\"messages\"\n [suggestedActions]=\"last ? message.additionalProperties.$suggestedAction : undefined\"\n [assistantMessageIcon]=\"assistantMessageIcon\"\n [userMessageIcon]=\"userMessageIcon\"\n [connectionErrorMessageIcon]=\"connectionErrorMessageIcon\"\n [searchWarningMessageIcon]=\"searchWarningMessageIcon\"\n [streaming]=\"last && (chatService.streaming$ | async)\"\n [canEdit]=\"(loading$ | async) === false && ((chatService.streaming$ | async) === false || !last) && messageToEdit === undefined && message.role === 'user'\"\n [canRegenerate]=\"(loading$ | async) === false && (chatService.streaming$ | async) === false && messageToEdit === undefined && message.role === 'assistant' && last\"\n [canCopy]=\"((chatService.streaming$ | async) === false || !last) && messageToEdit === undefined && message.role !== 'connection-error' && message.role !== 'search-warning'\"\n [canDebug]=\"((chatService.streaming$ | async) === false || !last) && message.role === 'assistant' && isAdmin && message.additionalProperties.$debug\"\n [canLike]=\"((chatService.streaming$ | async) === false || !last) && message.role === 'assistant'\"\n [canDislike]=\"((chatService.streaming$ | async) === false || !last) && message.role === 'assistant'\"\n (edit)=\"editMessage(index)\"\n (copy)=\"copyMessage(index)\"\n (regenerate)=\"regenerateMessage(index)\"\n (openDocument)=\"openOriginalAttachment($event)\"\n (openPreview)=\"openAttachmentPreview($event)\"\n (suggestAction)=\"suggestActionClick($event, index)\"\n (like)=\"onLike(index)\"\n (dislike)=\"onDislike($event, index)\"\n (debug)=\"showDebug($event)\">\n </sq-chat-message>\n </li>\n </ng-container>\n <!-- Loading spinner -->\n <li class=\"list-group-item\" *ngIf=\"(loading$ | async) === true\">\n <ng-container *ngTemplateOutlet=\"loadingTpl || loadingTplDefault\"></ng-container>\n </li>\n </ul>\n\n <!-- Reporting an issue form -->\n <div class=\"issue-report bg-light pt-3 pb-2\" *ngIf=\"showReportIssue\">\n <ng-container *ngTemplateOutlet=\"reportIssueTpl || reportIssueTplDefault; context: { $implicit: messageRelatedIssue, rank: issueRank }\"></ng-container>\n </div>\n\n <!-- User text input -->\n <div class=\"user-input mt-auto\" *ngIf=\"!showReportIssue\">\n <div class=\"py-2\">\n <div [hidden]=\"!isConnected\">\n <ng-container *ngIf=\"enabledUserInput\" [ngTemplateOutlet]=\"inputTpl\"></ng-container>\n </div>\n <!-- Retry button -->\n <button [hidden]=\"isConnected\" class=\"btn mb-4 ast-error ast-btn sq-retry\" (click)=\"retryFetch()\">\n <span>Try again</span>\n <span *ngIf=\"retrialAttempts\" class=\"ms-2 attempts\">{{ retrialAttempts }}</span>\n </button>\n <div class=\"text-end small text-muted px-3\" *ngIf=\"!!config?.globalSettings?.disclaimer\">\n {{ config?.globalSettings?.disclaimer }}\n </div>\n </div>\n </div>\n\n <!-- Floating scroll button -->\n <div *ngIf=\"!isAtBottom && !showReportIssue\" class=\"sq-floating-scroll\" [ngClass]=\"enabledUserInput ? 'sq-floating-scroll--when-user-input' : 'sq-floating-scroll--without-user-input'\">\n <button class=\"btn shadow\" (click)=\"scrollDown()\">\n <i class=\"fas fa-angle-double-down\"></i>\n </button>\n </div>\n </div>\n</ng-container>\n\n<!-- NG TEMPLATES-->\n\n<ng-template #loadingTplDefault>\n <div class=\"spinner-grow text-primary d-block mx-auto my-5\" role=\"status\">\n <span class=\"visually-hidden\">Loading...</span>\n </div>\n</ng-template>\n\n<ng-template #inputTpl>\n <div class=\"px-3 py-1\">\n <div class=\"ast-input-container\">\n <button disabled class=\"btn btn-light\">\n <i class=\"fas fa-search\"></i>\n </button>\n <textarea #questionInput rows=\"1\"\n type=\"text\" class=\"form-control\"\n placeholder=\"Ask something\" autofocus\n [(ngModel)]=\"question\"\n (keyup)=\"onKeyUp($event)\"\n (keydown)=\"calculateHeight($event)\"\n [disabled]=\"(loading$ | async) || (chatService.streaming$ | async)\">\n </textarea>\n <button\n *ngIf=\"!(chatService.streaming$ | async) && !(loading$ | async)\"\n type=\"button\"\n class=\"btn btn-light ms-2\"\n title=\"Send message\"\n (click)=\"submitQuestion()\">\n <i class=\"fas fa-paper-plane\"></i>\n </button>\n <!--<button\n *ngIf=\"(chatService.streaming$ | async)\"\n type=\"button\"\n class=\"btn btn-light ms-2\"\n title=\"Stop generating\"\n (click)=\"terminateFetch()\">\n <i class=\"fas fa-stop\"></i>\n </button>-->\n <button\n *ngIf=\"messageToEdit\"\n type=\"button\"\n class=\"btn btn-light ms-2\"\n title=\"Cancel edition\"\n (click)=\"messageToEdit = undefined; question = ''\">\n <i class=\"fas fa-undo-alt\"></i>\n </button>\n </div>\n </div>\n</ng-template>\n\n<ng-template #reportIssueTplDefault let-message let-rank=\"rank\">\n <div class=\"px-3\">\n <h5>Issue type</h5>\n <select class=\"form-select mb-4\" [(ngModel)]=\"issueType\">\n <option [value]=\"''\">Choose an issue type</option>\n <option *ngFor=\"let type of (issueTypes ?? defaultIssueTypes)\">{{type}}</option>\n </select>\n <h5>Comment (optional)</h5>\n <textarea class=\"form-control\" [(ngModel)]=\"issueComment\" placeholder=\"What was unsatisfying about this response?\"></textarea>\n <div class=\"d-flex flex-row-reverse mt-2\">\n <button class=\"btn btn-primary\" [disabled]=\"!issueType\" (click)=\"sendIssue()\">Send</button>\n <button class=\"btn btn-light\" (click)=\"ignoreIssue()\">Cancel</button>\n </div>\n </div>\n</ng-template>\n\n<ng-template #defaultTokenConsumptionTpl let-instanceId>\n <sq-token-progress-bar\n [instanceId]=\"instanceId\">\n </sq-token-progress-bar>\n</ng-template>\n\n<div class=\"debug-messages\" [class.displayed]=\"showDebugMessages\">\n <button *ngIf=\"showDebugMessages\" class=\"btn btn-light shadow back-btn\" (click)=\"showDebugMessages=false\">\n <i class=\"fas fa-chevron-right\"></i>\n </button>\n <ng-container *ngTemplateOutlet=\"debugMessagesTpl || defaultDebugMessagesTpl; context: { $implicit: debugMessages }\">\n </ng-container>\n</div>\n\n<ng-template #defaultDebugMessagesTpl let-debugMessages>\n <sq-debug-message [data]=\"debugMessages\"></sq-debug-message>\n</ng-template>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-error{background-color:var(--ast-error-bg, rgba(249, 58, 55, .2))}.ast-error:hover{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.ast-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference,:host ::ng-deep .attachment .reference{position:relative;bottom:var(--ast-reference-bottom, .3em);font-weight:var(--ast-reference-font-weight, bold);padding:var(--ast-reference-padding, 0 .2em);margin:var(--ast-reference-margin, 0 .1em);border-radius:var(--ast-reference-border-radius, .2em);background-color:var(--ast-reference-background-color, lightblue);color:var(--ast-reference-color, black)}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference{font-size:var(--ast-reference-message-font-size, .7em)}:host ::ng-deep .attachment .reference{font-size:var(--ast-reference-attachment-font-size, 13px)}:host{font-size:.875rem}:host>div>.user-input>div:not(.progress),:host>div>.issue-report>div,:host>div>ul>li{width:var(--ast-chat-container-width, 100%);max-width:100%;margin-left:auto;margin-right:auto}:host>div>ul{padding-top:var(--ast-chat-padding-top, 0);padding-bottom:var(--ast-chat-padding-bottom, 0)}li.attachment>p{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;-webkit-line-clamp:3}li.attachment.expanded>p{display:block}.progress{--bs-progress-height: 3px}.progress.disabled{--bs-progress-height: 20px;--bs-progress-bar-bg: var(--bs-danger)}.user-input{z-index:1}.user-input ul.list-group{max-height:30vh}.form-control:disabled{background-color:#ededed}a.disabled{cursor:default;opacity:.5}.no-max-height{max-height:initial!important}.sq-floating-scroll{position:absolute;right:50%;text-align:center}.sq-floating-scroll--when-user-input{bottom:75px}.sq-floating-scroll--without-user-input{bottom:15px}.sq-floating-scroll .btn{background-color:#fff}.sq-floating-scroll .btn:hover{background-color:#fff;opacity:.9}.ast-input-container{display:flex;align-items:end;background-color:var(--ast-input-bg, #F8F8F8);border-radius:var(--ast-size-3, .75rem)}.ast-input-container>i{padding-left:var(--ast-size-3, .75rem);color:var(--ast-muted-color, rgba(33, 37, 41, .75))}.ast-input-container textarea{padding-left:var(--ast-size-3, .75rem);padding-right:var(--ast-size-3, .75rem);resize:none}.ast-input-container textarea,.ast-input-container button,.ast-input-container button:hover{background-color:transparent;border:0}.ast-input-container button:hover{color:var(--ast-primary-color, #005DA7)}.ast-input-container button:not(:hover){color:var(--ast-muted-color, rgba(33, 37, 41, .75))}sq-chat-message.sq-user-message{float:var(--ast-user-message-float, none)}sq-token-progress-bar{z-index:10;position:absolute;top:0;right:0}.debug-messages{position:fixed;z-index:999999;right:-60%;top:0;width:60%;height:100%;transition:all .5s ease;background-color:var(--bs-body-bg);overflow:auto}.debug-messages .back-btn{position:fixed;right:0%;transition:all .5s ease}.debug-messages.displayed{right:0}.debug-messages.displayed .back-btn{right:60%}.debug-messages sq-debug-message:first-of-type{display:block;width:100%}.sq-retry{display:flex;margin:auto;font-weight:var(--font-weight-bold, 500)}.sq-retry .attempts{display:flex;border-radius:100%;background:white;height:20px;width:20px;place-content:center;align-items:center}\n"] }]
925
+ ], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, FormsModule, ChatMessageComponent, TokenProgressBarComponent, DebugMessageComponent, UtilsModule], template: "<ng-container *ngIf=\"!initializationError\">\n <div *ngIf=\"messages$ | async as messages; else loadingTpl || loadingTplDefault\" class=\"h-100 d-flex flex-column\">\n <!-- Token consumption -->\n <div class=\"ms-1\" *ngIf=\"config?.globalSettings?.displayUserQuotaConsumption || config?.globalSettings?.displayChatTokensConsumption\">\n <ng-container *ngTemplateOutlet=\"tokenConsumptionTpl || defaultTokenConsumptionTpl; context: { $implicit: instanceId }\"></ng-container>\n </div>\n\n <!-- Chat Messages -->\n <ul class=\"list-group list-group-flush overflow-auto flex-grow-1 pe-2 pb-2\" #messageList>\n <ng-container *ngFor=\"let message of messages; let index = index; let last = last\">\n <!-- Regular messages -->\n <li class=\"list-group-item\"\n *ngIf=\"message.additionalProperties.display\"\n [style.--bs-list-group-item-padding-y.rem]=\"'0.6'\"\n [class.opacity-50]=\"messageToEdit && messageToEdit < index + 1\">\n <sq-chat-message\n [class.sq-user-message]=\"message.role === 'user'\"\n [class.last-message]=\"last\"\n [message]=\"message\"\n [conversation]=\"messages\"\n [suggestedActions]=\"last ? message.additionalProperties.$suggestedAction : undefined\"\n [chatStarters]=\"visibleMessagesCount === 1 ? config.modeSettings.initialization.chatStarters : undefined\"\n [assistantMessageIcon]=\"assistantMessageIcon\"\n [userMessageIcon]=\"userMessageIcon\"\n [connectionErrorMessageIcon]=\"connectionErrorMessageIcon\"\n [searchWarningMessageIcon]=\"searchWarningMessageIcon\"\n [streaming]=\"(chatService.streaming$ | async) && (last || isAssistantLastMessages(messages, index))\"\n [canEdit]=\"(loading$ | async) === false && ((chatService.streaming$ | async) === false || !last) && messageToEdit === undefined && message.role === 'user'\"\n [canCopy]=\"((chatService.streaming$ | async) === false || !last) && messageToEdit === undefined && message.role !== 'connection-error' && message.role !== 'search-warning'\"\n [canLike]=\"((chatService.streaming$ | async) === false || !last) && message.role === 'assistant'\"\n [canDislike]=\"((chatService.streaming$ | async) === false || !last) && message.role === 'assistant'\"\n [canDebug]=\"(((chatService.streaming$ | async) === false && last) || (!last && messages[index+1].role !== 'assistant')) && message.role === 'assistant' && isAdmin && (getDebugMessages(index).length > 0) && config?.defaultValues.debug\"\n [canRegenerate]=\"(loading$ | async) === false && (((chatService.streaming$ | async) === false && last) || (!last && messages[index+1].role !== 'assistant')) && message.role === 'assistant' && messageToEdit === undefined\"\n (edit)=\"editMessage(index)\"\n (copy)=\"copyMessage(index)\"\n (regenerate)=\"regenerateMessage(index)\"\n (openDocument)=\"openOriginalAttachment($event)\"\n (openPreview)=\"openAttachmentPreview($event)\"\n (suggestAction)=\"suggestActionClick($event, index)\"\n (chatStarterClicked)=\"chatStarterClick($event)\"\n (like)=\"onLike($event, index)\"\n (dislike)=\"onDislike($event, index)\"\n (debug)=\"showDebug(index)\">\n </sq-chat-message>\n </li>\n </ng-container>\n <!-- Loading spinner -->\n <li class=\"list-group-item\" *ngIf=\"(loading$ | async) === true\">\n <ng-container *ngTemplateOutlet=\"loadingTpl || loadingTplDefault\"></ng-container>\n </li>\n </ul>\n\n <!-- Reporting a feedback form -->\n <div class=\"issue-report bg-light pt-3 pb-2\" *ngIf=\"showReport\">\n <ng-container *ngTemplateOutlet=\"reportTpl || reportTplDefault; context: { $implicit: messageToReport, rank: reportRank, type: reportType }\"></ng-container>\n </div>\n\n <!-- User text input -->\n <div class=\"user-input mt-auto\" *ngIf=\"!showReport\">\n <div class=\"py-2\">\n <div [hidden]=\"!isConnected\">\n <ng-container *ngIf=\"enabledUserInput\" [ngTemplateOutlet]=\"inputTpl\"></ng-container>\n </div>\n <!-- Retry button -->\n <button [hidden]=\"isConnected\" class=\"btn mb-4 ast-error ast-btn sq-retry\" (click)=\"retryFetch()\">\n <span>Try again</span>\n <span *ngIf=\"retrialAttempts\" class=\"ms-2 attempts\">{{ retrialAttempts }}</span>\n </button>\n <div class=\"text-end small text-muted px-3\" *ngIf=\"!!config?.globalSettings?.disclaimer\">\n {{ config?.globalSettings?.disclaimer }}\n </div>\n </div>\n </div>\n\n <!-- Floating scroll button -->\n <div *ngIf=\"!isAtBottom && !showReport\" class=\"sq-floating-scroll\" [ngClass]=\"enabledUserInput ? 'sq-floating-scroll--when-user-input' : 'sq-floating-scroll--without-user-input'\">\n <button class=\"btn shadow\" (click)=\"scrollDown()\">\n <i class=\"fas fa-angle-double-down\"></i>\n </button>\n </div>\n </div>\n</ng-container>\n\n<!-- NG TEMPLATES-->\n\n<ng-template #loadingTplDefault>\n <div class=\"spinner-grow text-primary d-block mx-auto my-5\" role=\"status\">\n <span class=\"visually-hidden\">Loading...</span>\n </div>\n</ng-template>\n\n<ng-template #inputTpl>\n <div class=\"px-3 py-1\">\n <div class=\"ast-input-container\">\n <button disabled class=\"btn btn-light\">\n <i class=\"fas fa-search\"></i>\n </button>\n <textarea #questionInput rows=\"1\"\n type=\"text\" class=\"form-control\"\n placeholder=\"Ask something\" autofocus\n [(ngModel)]=\"question\"\n (keyup)=\"onKeyUp($event)\"\n (keydown)=\"calculateHeight($event)\"\n [disabled]=\"(loading$ | async) || (chatService.streaming$ | async) || (chatService.stoppingGeneration$ | async)\">\n </textarea>\n <button\n *ngIf=\"!(chatService.streaming$ | async) && !(loading$ | async) && !(chatService.stoppingGeneration$ | async)\"\n type=\"button\"\n class=\"btn btn-light ms-2\"\n sqTooltip=\"Send message\"\n (click)=\"submitQuestion()\">\n <i class=\"fas fa-paper-plane\"></i>\n </button>\n <button\n *ngIf=\"messageToEdit\"\n type=\"button\"\n class=\"btn btn-light ms-2\"\n sqTooltip=\"Cancel edition\"\n (click)=\"messageToEdit = undefined; question = ''\">\n <i class=\"fas fa-undo-alt\"></i>\n </button>\n <span *ngIf=\"(chatService.streaming$ | async) && !(chatService.stoppingGeneration$ | async)\" class=\"processing ms-2\">\n Generating <i class=\"ms-1 fas fa-spinner fa-pulse\"></i>\n </span>\n <span *ngIf=\"(chatService.stoppingGeneration$ | async)\" class=\"processing ms-2\">\n Stopping <i class=\"ms-1 fas fa-spinner fa-pulse\"></i>\n </span>\n <button\n *ngIf=\"(chatService.streaming$ | async) && !(chatService.stoppingGeneration$ | async)\"\n type=\"button\"\n class=\"btn btn-light ms-2\"\n sqTooltip=\"Stop generating\"\n (click)=\"stopGeneration()\">\n <i class=\"fas fa-stop\"></i>\n </button>\n </div>\n </div>\n</ng-template>\n\n<ng-template #reportTplDefault let-message let-rank=\"rank\" let-type=\"type\">\n <div class=\"px-3\">\n <ng-container *ngIf=\"type === 'dislike'\">\n <h5>Issue type</h5>\n <select class=\"form-select mb-4\" [(ngModel)]=\"issueType\">\n <option [value]=\"''\">Choose an issue type</option>\n <option *ngFor=\"let type of (issueTypes ?? defaultIssueTypes)\">{{type}}</option>\n </select>\n <h5>What was unsatisfying about this response? (optional)</h5>\n </ng-container>\n <ng-container *ngIf=\"type === 'like'\">\n <h5>Why did you like this answer? (optional)</h5>\n </ng-container>\n <textarea class=\"form-control\" [(ngModel)]=\"reportComment\" placeholder=\"Write your comment\"></textarea>\n <div class=\"d-flex flex-row-reverse mt-2\">\n <button class=\"btn btn-primary\" [disabled]=\"type === 'dislike' && !issueType\" (click)=\"sendReport()\">Send</button>\n <button class=\"btn btn-light\" (click)=\"ignoreReport()\">Cancel</button>\n </div>\n </div>\n</ng-template>\n\n<ng-template #defaultTokenConsumptionTpl let-instanceId>\n <sq-token-progress-bar\n [instanceId]=\"instanceId\">\n </sq-token-progress-bar>\n</ng-template>\n\n<div class=\"debug-messages\" [class.displayed]=\"showDebugMessages\">\n <button *ngIf=\"showDebugMessages\" class=\"btn btn-light shadow back-btn\" (click)=\"showDebugMessages=false\">\n <i class=\"fas fa-chevron-right\"></i>\n </button>\n <ng-container *ngTemplateOutlet=\"debugMessagesTpl || defaultDebugMessagesTpl; context: { $implicit: debugMessages }\">\n </ng-container>\n</div>\n\n<ng-template #defaultDebugMessagesTpl let-debugMessages>\n <sq-debug-message [data]=\"debugMessages\"></sq-debug-message>\n</ng-template>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-error{background-color:var(--ast-error-bg, rgba(249, 58, 55, .2));color:var(--ast-action-buttons-color, inherit)}.ast-error:hover{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.ast-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black;--ast-action-buttons-color: white;--ast-action-buttons-hover-color: #6dbee6}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference,:host ::ng-deep .attachment .reference{position:relative;bottom:var(--ast-reference-bottom, .3em);font-weight:var(--ast-reference-font-weight, bold);padding:var(--ast-reference-padding, 0 .2em);margin:var(--ast-reference-margin, 0 .1em);border-radius:var(--ast-reference-border-radius, .2em);background-color:var(--ast-reference-background-color, lightblue);color:var(--ast-reference-color, black)}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference{font-size:var(--ast-reference-message-font-size, .7em)}:host ::ng-deep .attachment .reference{font-size:var(--ast-reference-attachment-font-size, 13px)}:host{font-size:.875rem}:host>div>.user-input>div:not(.progress),:host>div>.issue-report>div,:host>div>ul>li{width:var(--ast-chat-container-width, 100%);max-width:100%;margin-left:auto;margin-right:auto}:host>div>ul{padding-top:var(--ast-chat-padding-top, 0);padding-bottom:var(--ast-chat-padding-bottom, 0)}li.attachment>p{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;-webkit-line-clamp:3}li.attachment.expanded>p{display:block}.progress{--bs-progress-height: 3px}.progress.disabled{--bs-progress-height: 20px;--bs-progress-bar-bg: var(--bs-danger)}.user-input{z-index:1}.user-input ul.list-group{max-height:30vh}.form-control:disabled{background-color:#ededed}a.disabled{cursor:default;opacity:.5}.no-max-height{max-height:initial!important}.sq-floating-scroll{position:absolute;right:50%;text-align:center}.sq-floating-scroll--when-user-input{bottom:75px}.sq-floating-scroll--without-user-input{bottom:15px}.sq-floating-scroll .btn{background-color:#fff}.sq-floating-scroll .btn:hover{background-color:#fff;opacity:.9}.ast-input-container{display:flex;align-items:center;background-color:var(--ast-input-bg, #F8F8F8);border-radius:var(--ast-size-3, .75rem)}.ast-input-container>i{padding-left:var(--ast-size-3, .75rem);color:var(--ast-muted-color, rgba(33, 37, 41, .75))}.ast-input-container textarea{padding-left:var(--ast-size-3, .75rem);padding-right:var(--ast-size-3, .75rem);resize:none}.ast-input-container textarea,.ast-input-container button,.ast-input-container button:hover{background-color:transparent;border:0}.ast-input-container button:hover{color:var(--ast-primary-color, #005DA7)}.ast-input-container button:not(:hover){color:var(--ast-muted-color, rgba(33, 37, 41, .75))}.ast-input-container .processing{display:flex;align-items:center;color:var(--ast-secondary-color, #FF732E)}sq-chat-message.sq-user-message{float:var(--ast-user-message-float, none)}sq-token-progress-bar{z-index:10;position:absolute;top:0;right:0}.debug-messages{position:fixed;z-index:999999;right:-60%;top:0;width:60%;height:100%;transition:all .5s ease;background-color:var(--bs-body-bg);overflow:auto}.debug-messages .back-btn{position:fixed;right:0%;transition:all .5s ease}.debug-messages.displayed{right:0}.debug-messages.displayed .back-btn{right:60%}.debug-messages sq-debug-message:first-of-type{display:block;width:100%}.sq-retry{display:flex;margin:auto;font-weight:var(--font-weight-bold, 500)}.sq-retry .attempts{display:flex;border-radius:100%;background:white;height:20px;width:20px;place-content:center;align-items:center}\n"] }]
631
926
  }], ctorParameters: function () { return []; }, propDecorators: { instanceId: [{
632
927
  type: Input
633
928
  }], query: [{
@@ -640,6 +935,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImpor
640
935
  type: Input
641
936
  }], automaticScrollToLastResponse: [{
642
937
  type: Input
938
+ }], focusAfterResponse: [{
939
+ type: Input
643
940
  }], chat: [{
644
941
  type: Input
645
942
  }], assistantMessageIcon: [{
@@ -666,6 +963,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImpor
666
963
  type: Output
667
964
  }], suggestAction: [{
668
965
  type: Output
966
+ }], chatStarter: [{
967
+ type: Output
669
968
  }], messageList: [{
670
969
  type: ViewChild,
671
970
  args: ['messageList']
@@ -675,9 +974,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImpor
675
974
  }], loadingTpl: [{
676
975
  type: ContentChild,
677
976
  args: ['loadingTpl']
678
- }], reportIssueTpl: [{
977
+ }], reportTpl: [{
679
978
  type: ContentChild,
680
- args: ['reportIssueTpl']
979
+ args: ['reportTpl']
681
980
  }], tokenConsumptionTpl: [{
682
981
  type: ContentChild,
683
982
  args: ['tokenConsumptionTpl']
@@ -685,4 +984,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImpor
685
984
  type: ContentChild,
686
985
  args: ['debugMessagesTpl']
687
986
  }] } });
688
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhdC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9hc3Npc3RhbnQvY2hhdC9jaGF0LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uL3Byb2plY3RzL2Fzc2lzdGFudC9jaGF0L2NoYXQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSx1QkFBdUIsRUFBRSxpQkFBaUIsRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFjLFlBQVksRUFBRSxLQUFLLEVBQWdDLE1BQU0sRUFBOEIsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzFOLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDMUQsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQzNELE9BQU8sRUFBRSxVQUFVLEVBQVMsTUFBTSx5QkFBeUIsQ0FBQztBQUM1RCxPQUFPLEVBQUUsbUJBQW1CLEVBQXFCLE1BQU0sNEJBQTRCLENBQUM7QUFDcEYsT0FBTyxFQUFFLGVBQWUsRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDcEcsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRTdDLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ3BFLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ2hFLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLHVDQUF1QyxDQUFDO0FBQzdFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsV0FB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Z0I7c0JBQWpELFlBQVk7dUJBQUMsa0JBQWtCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgaW5qZWN0LCBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ2hhbmdlRGV0ZWN0b3JSZWYsIENvbXBvbmVudCwgQ29udGVudENoaWxkLCBFbGVtZW50UmVmLCBFdmVudEVtaXR0ZXIsIElucHV0LCBPbkNoYW5nZXMsIE9uRGVzdHJveSwgT25Jbml0LCBPdXRwdXQsIFNpbXBsZUNoYW5nZXMsIFRlbXBsYXRlUmVmLCBWaWV3Q2hpbGQgfSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuaW1wb3J0IHsgQWN0aW9uIH0gZnJvbSBcIkBzaW5lcXVhL2NvbXBvbmVudHMvYWN0aW9uXCI7XG5pbXBvcnQgeyBBYnN0cmFjdEZhY2V0IH0gZnJvbSBcIkBzaW5lcXVhL2NvbXBvbmVudHMvZmFjZXRcIjtcbmltcG9ydCB7IFNlYXJjaFNlcnZpY2UgfSBmcm9tIFwiQHNpbmVxdWEvY29tcG9uZW50cy9zZWFyY2hcIjtcbmltcG9ydCB7IEFwcFNlcnZpY2UsIFF1ZXJ5IH0gZnJvbSBcIkBzaW5lcXVhL2NvcmUvYXBwLXV0aWxzXCI7XG5pbXBvcnQgeyBQcmluY2lwYWxXZWJTZXJ2aWNlLCBSZWNvcmQgYXMgQXJ0aWNsZSB9IGZyb20gXCJAc2luZXF1YS9jb3JlL3dlYi1zZXJ2aWNlc1wiO1xuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBTdWJzY3JpcHRpb24sIGZpbHRlciwgZnJvbUV2ZW50LCBtYXAsIG1lcmdlLCBzd2l0Y2hNYXAsIHRhcCB9IGZyb20gXCJyeGpzXCI7XG5pbXBvcnQgeyBDaGF0U2VydmljZSB9IGZyb20gXCIuL2NoYXQuc2VydmljZVwiO1xuaW1wb3J0IHsgQ2hhdENvbnRleHRBdHRhY2htZW50LCBDaGF0Q29uZmlnLCBDaGF0TWVzc2FnZSwgR2xsbU1vZGVsRGVzY3JpcHRpb24sIE1lc3NhZ2VIYW5kbGVyLCBSYXdNZXNzYWdlLCBTdWdnZXN0ZWRBY3Rpb24sIEluaXRDaGF0LCBEZWJ1Z01lc3NhZ2UgfSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHsgSW5zdGFuY2VNYW5hZ2VyU2VydmljZSB9IGZyb20gXCIuL2luc3RhbmNlLW1hbmFnZXIuc2VydmljZVwiO1xuaW1wb3J0IHsgV2ViU29ja2V0Q2hhdFNlcnZpY2UgfSBmcm9tIFwiLi93ZWJzb2NrZXQtY2hhdC5zZXJ2aWNlXCI7XG5pbXBvcnQgeyBDaGF0TWVzc2FnZUNvbXBvbmVudCB9IGZyb20gXCIuL2NoYXQtbWVzc2FnZS9jaGF0LW1lc3NhZ2UuY29tcG9uZW50XCI7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tIFwiQGFuZ3VsYXIvY29tbW9uXCI7XG5pbXBvcnQgeyBGb3Jtc01vZHVsZSB9IGZyb20gXCJAYW5ndWxhci9mb3Jtc1wiO1xuaW1wb3J0IHsgTG9naW5TZXJ2aWNlIH0gZnJvbSBcIkBzaW5lcXVhL2NvcmUvbG9naW5cIjtcbmltcG9ydCB7IFJlc3RDaGF0U2VydmljZSB9IGZyb20gXCIuL3Jlc3QtY2hhdC5zZXJ2aWNlXCI7XG5pbXBvcnQgeyBUb2tlblByb2dyZXNzQmFyQ29tcG9uZW50IH0gZnJvbSBcIi4vdG9rZW4tcHJvZ3Jlc3MtYmFyL3Rva2VuLXByb2dyZXNzLWJhci5jb21wb25lbnRcIjtcbmltcG9ydCB7IERlYnVnTWVzc2FnZUNvbXBvbmVudCB9IGZyb20gXCIuL2RlYnVnLW1lc3NhZ2UvZGVidWctbWVzc2FnZS5jb21wb25lbnRcIjtcbmltcG9ydCB7IEh1YkNvbm5lY3Rpb24sIEh1YkNvbm5lY3Rpb25TdGF0ZSAgfSBmcm9tIFwiQG1pY3Jvc29mdC9zaWduYWxyXCI7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3NxLWNoYXQtdjMnLCAvLyBtYW5kYXRvcnkgc2luY2UgQHNpbmVxdWEvY29tcG9uZW50cyBhbHJlYWR5IGhhcyB0aGUgc2FtZSB0YWctbmFtZSBcInNxLWNoYXRcIlxuICB0ZW1wbGF0ZVVybDogJy4vY2hhdC5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL2NoYXQuY29tcG9uZW50LnNjc3MnXSxcbiAgcHJvdmlkZXJzOiBbXG4gICAgUmVzdENoYXRTZXJ2aWNlLFxuICAgIFdlYlNvY2tldENoYXRTZXJ2aWNlXG4gIF0sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlLCBGb3Jtc01vZHVsZSwgQ2hhdE1lc3NhZ2VDb21wb25lbnQsIFRva2VuUHJvZ3Jlc3NCYXJDb21wb25lbnQsIERlYnVnTWVzc2FnZUNvbXBvbmVudF1cbn0pXG5leHBvcnQgY2xhc3MgQ2hhdENvbXBvbmVudCBleHRlbmRzIEFic3RyYWN0RmFjZXQgaW1wbGVtZW50cyBPbkluaXQsIE9uQ2hhbmdlcywgT25EZXN0cm95IHtcblxuICBwdWJsaWMgbG9naW5TZXJ2aWNlID0gaW5qZWN0KExvZ2luU2VydmljZSk7XG4gIHB1YmxpYyB3ZWJzb2NrZXRTZXJ2aWNlID0gaW5qZWN0KFdlYlNvY2tldENoYXRTZXJ2aWNlKTtcbiAgcHVibGljIHJlc3RTZXJ2aWNlID0gaW5qZWN0KFJlc3RDaGF0U2VydmljZSk7XG4gIHB1YmxpYyBpbnN0YW5jZU1hbmFnZXJTZXJ2aWNlID0gaW5qZWN0KEluc3RhbmNlTWFuYWdlclNlcnZpY2UpO1xuICBwdWJsaWMgc2VhcmNoU2VydmljZSA9IGluamVjdChTZWFyY2hTZXJ2aWNlKTtcbiAgcHVibGljIHByaW5jaXBhbFNlcnZpY2UgPSBpbmplY3QoUHJpbmNpcGFsV2ViU2VydmljZSk7XG4gIHB1YmxpYyBjZHIgPSBpbmplY3QoQ2hhbmdlRGV0ZWN0b3JSZWYpO1xuICBwdWJsaWMgYXBwU2VydmljZSA9IGluamVjdChBcHBTZXJ2aWNlKTtcblxuICAvKiogRGVmaW5lIHRoZSBrZXkgYmFzZWQgb24gaXQsIHRoZSBjaGF0IHNlcnZpY2UgaW5zdGFuY2Ugd2lsbCBiZSBzdG9yZWQgKi9cbiAgQElucHV0KCkgaW5zdGFuY2VJZDogc3RyaW5nO1xuICAvKiogRGVmaW5lIHRoZSBxdWVyeSB0byB1c2UgdG8gZmV0Y2ggYW5zd2VycyAqL1xuICBASW5wdXQoKSBxdWVyeTogUXVlcnkgPSB0aGlzLnNlYXJjaFNlcnZpY2UucXVlcnk7XG4gIC8qKiBGdW5jdGlvbiB0aGF0IGRldGVybWluZXMgd2hldGhlciB0aGUgY2hhdCBzaG91bGQgYmUgcmVsb2FkZWQgYWZ0ZXIgdGhlIHF1ZXJ5IGNoYW5nZXNcbiAgICogSWYgbm90IHByb3ZpZGVkLCB0aGUgY2hhdCB3aWxsIGJlIHJlbG9hZGVkIGJ5IGRlZmF1bHRcbiAgICogQHBhcmFtIHByZXZRdWVyeSBUaGUgcHJldmlvdXMgcXVlcnlcbiAgICogQHBhcmFtIG5ld1F1ZXJ5IFRoZSBuZXcgcXVlcnlcbiAgICogQHJldHVybnMgdHJ1ZSBpZiB0aGUgY2hhdCBzaG91bGQgYmUgcmVsb2FkZWQsIGZhbHNlIG90aGVyd2lzZVxuICAgKi9cbiAgQElucHV0KCkgcXVlcnlDaGFuZ2VTaG91bGRUcmlnZ2VyUmVsb2FkOiAocHJldlF1ZXJ5OiBRdWVyeSwgbmV3UXVlcnk6IFF1ZXJ5KSA9PiBib29sZWFuO1xuICAvKiogRGVmaW5lIHRoZSBwcm90b2NvbCB0byBiZSB1c2VkIGZvciB0aGlzIGNoYXQgaW5zdGFuY2UqL1xuICBASW5wdXQoKSBwcm90b2NvbDogJ1JFU1QnIHwgJ1dFQlNPQ0tFVCcgPSBcIldFQlNPQ0tFVFwiO1xuICAvKiogTWFwIG9mIGxpc3RlbmVycyBvdmVycmlkaW5nIGRlZmF1bHQgcmVnaXN0ZXJlZCBvbmVzKi9cbiAgQElucHV0KCkgbWVzc2FnZUhhbmRsZXJzOiBNYXA8c3RyaW5nLCBNZXNzYWdlSGFuZGxlcjxhbnk+PiA9IG5ldyBNYXAoKTtcbiAgLyoqIFdoZW4gdGhlIGFzc2lzdGFudCBhbnN3ZXIgYSB1c2VyIHF1ZXN0aW9uLCBhdXRvbWF0aWNhbGx5IHNjcm9sbCBkb3duIHRvIHRoZSBib3R0b20gb2YgdGhlIGRpc2N1c3Npb24gKi9cbiAgQElucHV0KCkgYXV0b21hdGljU2Nyb2xsVG9MYXN0UmVzcG9uc2UgPSBmYWxzZTtcbiAgLyoqIEEgY2hhdCBkaXNjdXNzaW9uIHRoYXQgdGhlIGNvbXBvbmVudCBzaG91bGQgZ2V0IGluaXRpYWxpemVkIHdpdGggaXQgKi9cbiAgQElucHV0KCkgY2hhdD86IEluaXRDaGF0O1xuICAvKiogSWNvbiB0byB1c2UgZm9yIHRoZSBhc3Npc3RhbnQgbWVzc2FnZXMgKi9cbiAgQElucHV0KCkgYXNzaXN0YW50TWVzc2FnZUljb24gPSAnc3Etc2luZXF1YSc7XG4gIC8qKiBJY29uIHRvIHVzZSBmb3IgdGhlIHVzZXIgbWVzc2FnZXMgKi9cbiAgQElucHV0KCkgdXNlck1lc3NhZ2VJY29uOiBzdHJpbmc7XG4gIC8qKiBJY29uIHRvIHVzZSBmb3IgdGhlIGNvbm5lY3Rpb24gZXJyb3IgbWVzc2FnZXMgKi9cbiAgQElucHV0KCkgY29ubmVjdGlvbkVycm9yTWVzc2FnZUljb246IHN0cmluZztcbiAgLyoqIEljb24gdG8gdXNlIGZvciB0aGUgc2VhcmNoIHdhcm5pbmcgbWVzc2FnZXMgKi9cbiAgQElucHV0KCkgc2VhcmNoV2FybmluZ01lc3NhZ2VJY29uOiBzdHJpbmc7XG4gIC8qKiBFdmVudCBlbWl0dGVyIHRyaWdnZXJlZCBvbmNlIHRoZSBzaWduYWxSIGNvbm5lY3Rpb24gaXMgZXN0YWJsaXNoZWQgICovXG4gIEBPdXRwdXQoKSBjb25uZWN0aW9uID0gbmV3IEV2ZW50RW1pdHRlcjxIdWJDb25uZWN0aW9uPigpO1xuICAvKiogRXZlbnQgZW1pdHRlciB0cmlnZ2VyZWQgZWFjaCB0aW1lIHRoZSBhc3Npc3RhbnQgdXBkYXRlcyB0aGUgY3VycmVudCBjaGF0ICovXG4gIC8qKiBFdmVudCBlbWl0dGVyIHRyaWdnZXJlZCB3aGVuIHRoZSBjaGF0IGlzIGxvYWRpbmcgbmV3IGNvbnRlbnQgKi9cbiAgQE91dHB1dChcImxvYWRpbmdcIikgbG9hZGluZyQgPSBuZXcgRXZlbnRFbWl0dGVyPGJvb2xlYW4+KGZhbHNlKTtcbiAgLyoqIEVtaXRzIHRoZSBhc3Npc3RhbnQgY29uZmlndXJhdGlvbiB1c2VkIHdoZW4gaW5zdGFudGlhdGluZyB0aGUgY29tcG9uZW50ICovXG4gIEBPdXRwdXQoXCJjb25maWdcIikgX2NvbmZpZyA9IG5ldyBFdmVudEVtaXR0ZXI8Q2hhdENvbmZpZz4oKTtcbiAgQE91dHB1dCgpIGRhdGEgPSBuZXcgRXZlbnRFbWl0dGVyPENoYXRNZXNzYWdlW10+KCk7XG4gIC8qKiBFdmVudCBlbWl0dGVyIHRyaWdnZXJlZCB3aGVuIHRoZSB1c2VyIGNsaWNrcyB0byBvcGVuIHRoZSBvcmlnaW5hbCBkb2N1bWVudCByZXByZXNlbnRpbmcgdGhlIGNvbnRleHQgYXR0YWNobWVudCovXG4gIEBPdXRwdXQoKSBvcGVuRG9jdW1lbnQgPSBuZXcgRXZlbnRFbWl0dGVyPEFydGljbGU+KCk7XG4gIC8qKiBFdmVudCBlbWl0dGVyIHRyaWdnZXJlZCB3aGVuIHRoZSB1c2VyIGNsaWNrcyB0byBvcGVuIHRoZSBwcmV2aWV3IG9mIGEgZG9jdW1lbnQgcmVwcmVzZW50aW5nIHRoZSBjb250ZXh0IGF0dGFjaG1lbnQgKi9cbiAgQE91dHB1dCgpIG9wZW5QcmV2aWV3ID0gbmV3IEV2ZW50RW1pdHRlcjxDaGF0Q29udGV4dEF0dGFjaG1lbnQ+KCk7XG4gIC8qKiBFdmVudCBlbWl0dGVyIHRyaWdnZXJlZCB3aGVuIHRoZSB1c2VyIGNsaWNrcyBvbiBhIHN1Z2dlc3RlZCBhY3Rpb24gKi9cbiAgQE91dHB1dCgpIHN1Z2dlc3RBY3Rpb24gPSBuZXcgRXZlbnRFbWl0dGVyPFN1Z2dlc3RlZEFjdGlvbj4oKTtcblxuICBAVmlld0NoaWxkKCdtZXNzYWdlTGlzdCcpIG1lc3NhZ2VMaXN0PzogRWxlbWVudFJlZjxIVE1MVUxpc3RFbGVtZW50PjtcbiAgQFZpZXdDaGlsZCgncXVlc3Rpb25JbnB1dCcpIHF1ZXN0aW9uSW5wdXQ/OiBFbGVtZW50UmVmPEhUTUxUZXh0QXJlYUVsZW1lbnQ+O1xuXG4gIEBDb250ZW50Q2hpbGQoJ2xvYWRpbmdUcGwnKSBsb2FkaW5nVHBsPzogVGVtcGxhdGVSZWY8YW55PjtcbiAgQENvbnRlbnRDaGlsZCgncmVwb3J0SXNzdWVUcGwnKSByZXBvcnRJc3N1ZVRwbD86IFRlbXBsYXRlUmVmPGFueT47XG4gIEBDb250ZW50Q2hpbGQoJ3Rva2VuQ29uc3VtcHRpb25UcGwnKSB0b2tlbkNvbnN1bXB0aW9uVHBsPzogVGVtcGxhdGVSZWY8YW55PjtcbiAgQENvbnRlbnRDaGlsZCgnZGVidWdNZXNzYWdlc1RwbCcpIGRlYnVnTWVzc2FnZXNUcGw/OiBUZW1wbGF0ZVJlZjxhbnk+O1xuXG4gIGNoYXRTZXJ2aWNlOiBDaGF0U2VydmljZTtcbiAgY29uZmlnOiBDaGF0Q29uZmlnO1xuICBtZXNzYWdlcyQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PENoYXRNZXNzYWdlW10gfCB1bmRlZmluZWQ+KHVuZGVmaW5lZCk7XG5cbiAgcXVlc3Rpb24gPSAnJztcblxuICBfYWN0aW9uczogQWN0aW9uW10gPSBbXTtcblxuICBzdWIgPSBuZXcgU3Vic2NyaXB0aW9uKCk7XG4gIGRhdGFTdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbiB8IHVuZGVmaW5lZDtcblxuICAvKiogVmFyaWFibGVzIHRoYXQgZGVwZW5kIG9uIHRoZSB0eXBlIG9mIG1vZGVsIGluIHVzZSAqL1xuICBtb2RlbERlc2NyaXB0aW9uPzogR2xsbU1vZGVsRGVzY3JpcHRpb247XG5cbiAgbWVzc2FnZVRvRWRpdD86IG51bWJlcjtcbiAgY2hhbmdlcyQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PFNpbXBsZUNoYW5nZXMgfCB1bmRlZmluZWQ+KHVuZGVmaW5lZCk7XG4gIGN1cnJlbnRNZXNzYWdlSW5kZXg6IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgZmlyc3RDaGFuZ2VzSGFuZGxlZCA9IGZhbHNlO1xuICBpc0F0Qm90dG9tID0gdHJ1ZTtcbiAgaW5pdGlhbGl6YXRpb25FcnJvciA9IGZhbHNlO1xuICBlbmFibGVkVXNlcklucHV0ID0gZmFsc2U7XG4gIGlzQ29ubmVjdGVkID0gdHJ1ZTsgLy8gQnkgZGVmYXVsdCwgdGhlIGNoYXQgaXMgY29uc2lkZXJlZCBjb25uZWN0ZWRcbiAgcmV0cmlhbEF0dGVtcHRzOiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gIC8vIEZsYWcgdG8gdHJhY2sgd2hldGhlciB0aGUgJ3JlY29ubmVjdGVkJyBsaXN0ZW5lciBpcyBhbHJlYWR5IHJlZ2lzdGVyZWRcbiAgcHJpdmF0ZSBfaXNSZWNvbm5lY3RlZExpc3RlbmVyUmVnaXN0ZXJlZCA9IGZhbHNlO1xuXG4gIC8vIElzc3VlIHJlcG9ydGluZ1xuICBpc3N1ZVR5cGVzPzogc3RyaW5nW107XG4gIGRlZmF1bHRJc3N1ZVR5cGVzOiBzdHJpbmdbXSA9IFtcbiAgICAnVXNlciBJbnRlcmZhY2UgYnVnJyxcbiAgICAnSW5jb3JyZWN0IG9yIG1pc2xlYWRpbmcgcmVzcG9uc2UnLFxuICAgICdJbmNvbXBsZXRlIHJlc3BvbnNlJyxcbiAgICAnVGVjaG5pY2FsIGlzc3VlJyxcbiAgICAnUHJpdmFjeS9kYXRhIHNlY3VyaXR5IGlzc3VlJyxcbiAgICAnT3RoZXInXG4gIF07XG4gIGlzc3VlVHlwZTogc3RyaW5nID0gJyc7XG4gIGlzc3VlQ29tbWVudD86IHN0cmluZztcbiAgbWVzc2FnZVJlbGF0ZWRJc3N1ZT86IENoYXRNZXNzYWdlO1xuICBpc3N1ZVJhbms/OiBudW1iZXI7XG4gIHNob3dSZXBvcnRJc3N1ZSA9IGZhbHNlO1xuXG4gIC8vIERlYnVnIG1lc3NhZ2VzXG4gIGRlYnVnTWVzc2FnZXM6IERlYnVnTWVzc2FnZVtdIHwgdW5kZWZpbmVkO1xuICBzaG93RGVidWdNZXNzYWdlcyA9IGZhbHNlO1xuXG4gIHByaXZhdGUgX3ByZXZpb3VzUXVlcnk6IFF1ZXJ5O1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICB0aGlzLl9hY3Rpb25zLnB1c2gobmV3IEFjdGlvbih7XG4gICAgICBpY29uOiAnZmFzIGZhLXN5bmMnLFxuICAgICAgdGl0bGU6ICdSZXNldCBjaGF0JyxcbiAgICAgIGFjdGlvbjogKCkgPT4gdGhpcy5uZXdDaGF0KClcbiAgICB9KSk7XG4gIH1cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLnN1Yi5hZGQoXG4gICAgICB0aGlzLmxvZ2luU2VydmljZS5ldmVudHMucGlwZShcbiAgICAgICAgZmlsdGVyKGUgPT4gZS50eXBlID09PSAnbG9naW4tY29tcGxldGUnKSxcbiAgICAgICAgdGFwKF8gPT4gdGhpcy5pbnN0YW50aWF0ZUNoYXRTZXJ2aWNlKCkpLFxuICAgICAgICBtYXAoXyA9PiB0aGlzLmNoYXRTZXJ2aWNlLmluaXRDaGF0Q29uZmlnKCkpLFxuICAgICAgICBzd2l0Y2hNYXAoKCkgPT4gdGhpcy5jaGF0U2VydmljZS5pbml0Q29uZmlnJCksXG4gICAgICAgIGZpbHRlcihpbml0Q29uZmlnID0+ICEhaW5pdENvbmZpZyksXG4gICAgICAgIHN3aXRjaE1hcChfID0+IHRoaXMuY2hhdFNlcnZpY2UuaW5pdCgpKSxcbiAgICAgICAgc3dpdGNoTWFwKF8gPT4gdGhpcy5jaGF0U2VydmljZS5pbml0UHJvY2VzcyQpLFxuICAgICAgICBmaWx0ZXIoc3VjY2VzcyA9PiAhIXN1Y2Nlc3MpLFxuICAgICAgICB0YXAoXyA9PiB7XG4gICAgICAgICAgaWYgKHRoaXMuY2hhdFNlcnZpY2UgaW5zdGFuY2VvZiBXZWJTb2NrZXRDaGF0U2VydmljZSkge1xuICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLmVtaXQodGhpcy5jaGF0U2VydmljZS5jb25uZWN0aW9uKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5vbkxvYWRDaGF0KCk7XG4gICAgICAgIH0pLFxuICAgICAgICBzd2l0Y2hNYXAoXyA9PiB0aGlzLmNoYXRTZXJ2aWNlLmNoYXRDb25maWckKSxcbiAgICAgICAgdGFwKGNvbmZpZyA9PiB7XG4gICAgICAgICAgdGhpcy5jb25maWcgPSBjb25maWchO1xuICAgICAgICAgIHRoaXMuZW5hYmxlZFVzZXJJbnB1dCA9IHRoaXMuY29uZmlnLm1vZGVTZXR0aW5ncy5lbmFibGVkVXNlcklucHV0O1xuICAgICAgICAgIHRoaXMuaXNzdWVUeXBlcyA9IHRoaXMuY29uZmlnLmF1ZGl0U2V0dGluZ3M/Lmlzc3VlVHlwZXM/Lmxlbmd0aCA/IHRoaXMuY29uZmlnLmF1ZGl0U2V0dGluZ3MhLmlzc3VlVHlwZXMgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgdGhpcy5fY29uZmlnLmVtaXQoY29uZmlnKTtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgdGhpcy51cGRhdGVNb2RlbERlc2NyaXB0aW9uKCk7XG4gICAgICAgICAgICBpZighdGhpcy5maXJzdENoYW5nZXNIYW5kbGVkKSB7XG4gICAgICAgICAgICAgIHRoaXMuX3ByZXZpb3VzUXVlcnkgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KHRoaXMucXVlcnkpKTsgLy8gSW5pdGlhbGl6ZSB0aGUgcHJldmlvdXMgcXVlcnlcbiAgICAgICAgICAgICAgdGhpcy5faGFuZGxlQ2hhbmdlcygpO1xuICAgICAgICAgICAgICB0aGlzLl9hZGRTY3JvbGxMaXN0ZW5lcigpO1xuICAgICAgICAgICAgICB0aGlzLmZpcnN0Q2hhbmdlc0hhbmRsZWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICB0aGlzLmluaXRpYWxpemF0aW9uRXJyb3IgPSB0cnVlXG4gICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICApLnN1YnNjcmliZSgpXG4gICAgKTtcbiAgfVxuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpIHtcbiAgICB0aGlzLmNoYW5nZXMkLm5leHQoY2hhbmdlcyk7XG4gICAgaWYgKHRoaXMuY29uZmlnKSB7XG4gICAgICB0aGlzLl9oYW5kbGVDaGFuZ2VzKCk7XG4gICAgfVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5zdWIudW5zdWJzY3JpYmUoKTtcbiAgICB0aGlzLmRhdGFTdWJzY3JpcHRpb24/LnVuc3Vic2NyaWJlKCk7XG4gIH1cblxuICBnZXQgaXNBZG1pbigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5wcmluY2lwYWxTZXJ2aWNlLnByaW5jaXBhbD8uaXNBZG1pbmlzdHJhdG9yIHx8IGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEluc3RhbnRpYXRlIHRoZSBjaGF0IHNlcnZpY2UgYmFzZWQgb24gdGhlIHByb3ZpZGVkIEBpbnB1dCBwcm90b2NvbFxuICAgKiBUaGlzIGNoYXQgc2VydmljZSBpbnN0YW5jZSB3aWxsIHRoZW4gYmUgc3RvcmVkIGluIHRoZSBpbnN0YW5jZU1hbmFnZXJTZXJ2aWNlIHdpdGggcHJvdmlkZWQgQGlucHV0IGluc3RhbmNlSWQgYXMgYSBrZXlcbiAgICovXG4gIGluc3RhbnRpYXRlQ2hhdFNlcnZpY2UoKTogdm9pZCB7XG4gICAgc3dpdGNoICh0aGlzLnByb3RvY29sKSB7XG4gICAgICBjYXNlICdSRVNUJzpcbiAgICAgICAgdGhpcy5jaGF0U2VydmljZSA9IHRoaXMucmVzdFNlcnZpY2U7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnV0VCU09DS0VUJzpcbiAgICAgICAgdGhpcy5jaGF0U2VydmljZSA9IHRoaXMud2Vic29ja2V0U2VydmljZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENvdWxkIG5vdCBmb3VuZCBhIENoYXRTZXJ2aWNlIGltcGxlbWVudGF0aW9uIGNvcnJlc3BvbmRpbmcgdG8gdGhlIHByb3ZpZGVkIHByb3RvY29sOiAnJHt0aGlzLnByb3RvY29sfSdgKTtcbiAgICB9XG4gICAgdGhpcy5jaGF0U2VydmljZS5zZXRDaGF0SW5zdGFuY2VJZCh0aGlzLmluc3RhbmNlSWQpO1xuICAgIHRoaXMuaW5zdGFuY2VNYW5hZ2VyU2VydmljZS5zdG9yZUluc3RhbmNlKHRoaXMuaW5zdGFuY2VJZCwgdGhpcy5jaGF0U2VydmljZSk7XG4gIH1cblxuICBvdmVycmlkZSBnZXQgYWN0aW9ucygpIHsgcmV0dXJuIHRoaXMuX2FjdGlvbnM7IH1cblxuICBwcml2YXRlIF9oYW5kbGVDaGFuZ2VzKCkge1xuICAgIGNvbnN0IGNoYW5nZXMgPSB0aGlzLmNoYW5nZXMkLnZhbHVlO1xuICAgIC8vIElmIHRoZSBjaGF0IHNlcnZpY2UgaXMgYSBXZWJTb2NrZXRDaGF0U2VydmljZSwgaGFuZGxlIHRoZSBvdmVycmlkZSBvZiB0aGUgbWVzc2FnZSBoYW5kbGVycyBpZiBleGlzdHNcbiAgICBpZiAoY2hhbmdlcz8ubWVzc2FnZUhhbmRsZXJzICYmIHRoaXMubWVzc2FnZUhhbmRsZXJzICYmIHRoaXMuY2hhdFNlcnZpY2UgaW5zdGFuY2VvZiBXZWJTb2NrZXRDaGF0U2VydmljZSkge1xuICAgICAgdGhpcy5jaGF0U2VydmljZS5vdmVycmlkZU1lc3NhZ2VIYW5kbGVycyh0aGlzLm1lc3NhZ2VIYW5kbGVycyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEluaXRpYWxpemUgdGhlIGNoYXQgd2l0aCB0aGUgcHJvdmlkZWQgY2hhdCBtZXNzYWdlcyBpZiBleGlzdHMsIG90aGVyd2lzZSBsb2FkIHRoZSBkZWZhdWx0IGNoYXRcbiAgICAgKiBPbmNlIHRoZSBjaGF0IGlzIGluaXRpYWxpemVkIChmaXJzdENoYW5nZXNIYW5kbGVkIGlzIHRydWUpLCBhbGxvdyBvcGVuaW5nIHRoZSBjaGF0IHdpdGggdGhlIG5ldyBwcm92aWRlZCBtZXNzYWdlcyAoaWYgZXhpc3RzKVxuICAgICAqL1xuICAgIGlmICghdGhpcy5maXJzdENoYW5nZXNIYW5kbGVkIHx8IGNoYW5nZXM/LmNoYXQpIHtcbiAgICAgIGNvbnN0IG9wZW5DaGF0ID0gKCkgPT4ge1xuICAgICAgICBpZiAodGhpcy5tZXNzYWdlcyQudmFsdWUpIHtcbiAgICAgICAgICB0aGlzLmNoYXRTZXJ2aWNlLmxpc3RTYXZlZENoYXQoKTsgLy8gUmVmcmVzaCB0aGUgbGlzdCBvZiBzYXZlZCBjaGF0c1xuICAgICAgICB9XG4gICAgICAgIHRoaXMub3BlbkNoYXQodGhpcy5jaGF0IS5tZXNzYWdlcyk7XG4gICAgICB9O1xuICAgICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUNoYXRJZCgpO1xuICAgICAgaWYgKHRoaXMuY2hhdCkge1xuICAgICAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudCgnbmV3LWNoYXQnLCB7J2NvbmZpZ3VyYXRpb24nOiBKU09OLnN0cmluZ2lmeSh0aGlzLmNoYXRTZXJ2aWNlLmNoYXRDb25maWckLnZhbHVlKSwnY2hhdC1pbml0JzogSlNPTi5zdHJpbmdpZnkodGhpcy5jaGF0KX0pO1xuICAgICAgICBvcGVuQ2hhdCgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ25ldy1jaGF0Jywgeydjb25maWd1cmF0aW9uJzogSlNPTi5zdHJpbmdpZnkodGhpcy5jaGF0U2VydmljZS5jaGF0Q29uZmlnJC52YWx1ZSl9KTtcbiAgICAgICAgdGhpcy5sb2FkRGVmYXVsdENoYXQoKTtcbiAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogSWYgdGhlIGNoYXQgaXMgaW5pdGlhbGl6ZWQsIHRoZSBpbml0aWFsaXphdGlvbiBldmVudCBpcyBcIlF1ZXJ5XCIsIHRoZSBxdWVyeSBjaGFuZ2VzIGFuZCB0aGUgcXVlcnlDaGFuZ2VTaG91bGRUcmlnZ2VyUmVsb2FkIGZ1bmN0aW9uIGlzIHByb3ZpZGVkLFxuICAgICAqIHRoZW4gdGhlIGNoYXQgc2hvdWxkIGJlIHJlbG9hZGVkIGlmIHRoZSBmdW5jdGlvbiByZXR1cm5zIHRydWVcbiAgICAgKiBPdGhlcndpc2UsIHRoZSBjaGF0IHNob3VsZCBiZSByZWxvYWRlZCBieSBkZWZhdWx0XG4gICAgICovXG4gICAgaWYgKHRoaXMuZmlyc3RDaGFuZ2VzSGFuZGxlZCAmJiBjaGFuZ2VzPy5xdWVyeSAmJiB0aGlzLmNvbmZpZy5tb2RlU2V0dGluZ3MuaW5pdGlhbGl6YXRpb24uZXZlbnQgPT09ICdRdWVyeScpIHtcbiAgICAgIGlmICh0aGlzLnF1ZXJ5Q2hhbmdlU2hvdWxkVHJpZ2dlclJlbG9hZCA/IHRoaXMucXVlcnlDaGFuZ2VTaG91bGRUcmlnZ2VyUmVsb2FkKHRoaXMuX3ByZXZpb3VzUXVlcnksIHRoaXMucXVlcnkpIDogdHJ1ZSkge1xuICAgICAgICB0aGlzLl90cmlnZ2VyUmVsb2FkQWZ0ZXJRdWVyeUNoYW5nZSgpO1xuICAgICAgfVxuICAgICAgdGhpcy5fcHJldmlvdXNRdWVyeSA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkodGhpcy5xdWVyeSkpOyAvLyBVcGRhdGUgdGhlIHByZXZpb3VzIHF1ZXJ5XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfdHJpZ2dlclJlbG9hZEFmdGVyUXVlcnlDaGFuZ2UoKSB7XG4gICAgY29uc3Qgc3lzdGVtTXNnID0ge3JvbGU6ICdzeXN0ZW0nLCBjb250ZW50OiB0aGlzLmNvbmZpZy5kZWZhdWx0VmFsdWVzLnN5c3RlbVByb21wdCwgYWRkaXRpb25hbFByb3BlcnRpZXM6IHtkaXNwbGF5OiBmYWxzZX19O1xuICAgIGNvbnN0IHVzZXJNc2cgPSB7cm9sZTogJ3VzZXInLCBjb250ZW50OiBDaGF0U2VydmljZS5mb3JtYXRQcm9tcHQodGhpcy5jb25maWcuZGVmYXVsdFZhbHVlcy51c2VyUHJvbXB0LCB7cHJpbmNpcGFsOiB0aGlzLnByaW5jaXBhbFNlcnZpY2UucHJpbmNpcGFsfSksIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiB7ZGlzcGxheTogdGhpcy5jb25maWcubW9kZVNldHRpbmdzLmRpc3BsYXlVc2VyUHJvbXB0fX07XG4gICAgdGhpcy5jaGF0U2VydmljZS5zZXRTYXZlZENoYXRJZCh1bmRlZmluZWQpOyAvLyBSZXNldCB0aGUgc2F2ZWRDaGF0SWRcbiAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQ2hhdElkKCk7IC8vIEdlbmVyYXRlIGEgbmV3IGNoYXRJZFxuICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVBdWRpdEV2ZW50KCduZXctY2hhdCcsIHsnY29uZmlndXJhdGlvbic6IEpTT04uc3RyaW5naWZ5KHRoaXMuY2hhdFNlcnZpY2UuY2hhdENvbmZpZyQudmFsdWUpfSk7IC8vIEdlbmVyYXRlIGEgbmV3IGNoYXQgYXVkaXQgZXZlbnRcbiAgICB0aGlzLl9oYW5kbGVRdWVyeU1vZGUoc3lzdGVtTXNnLCB1c2VyTXNnKTtcbiAgfVxuXG4gIHByaXZhdGUgX2FkZFNjcm9sbExpc3RlbmVyKCkge1xuICAgIHRoaXMuc3ViLmFkZChcbiAgICAgIG1lcmdlKHRoaXMubG9hZGluZyQsIHRoaXMubWVzc2FnZXMkLCB0aGlzLmNoYXRTZXJ2aWNlLnN0cmVhbWluZyQsIGZyb21FdmVudCh0aGlzLm1lc3NhZ2VMaXN0IS5uYXRpdmVFbGVtZW50LCAnc2Nyb2xsJykpLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgIHRoaXMuaXNBdEJvdHRvbSA9IHRoaXMuX3RvZ2dsZVNjcm9sbEJ1dHRvblZpc2liaWxpdHkoKTtcbiAgICAgICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpO1xuICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgdXBkYXRlTW9kZWxEZXNjcmlwdGlvbigpIHtcbiAgICB0aGlzLm1vZGVsRGVzY3JpcHRpb24gPSB0aGlzLmNoYXRTZXJ2aWNlLmdldE1vZGVsKHRoaXMuY29uZmlnLmRlZmF1bHRWYWx1ZXMuc2VydmljZV9pZCwgdGhpcy5jb25maWcuZGVmYXVsdFZhbHVlcy5tb2RlbF9pZCk7XG4gICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpO1xuICB9XG5cbiAgc3VibWl0UXVlc3Rpb24oKSB7XG4gICAgaWYodGhpcy5xdWVzdGlvbi50cmltKCkgJiYgdGhpcy5tZXNzYWdlcyQudmFsdWUgJiYgdGhpcy5jaGF0U2VydmljZS5jaGF0SGlzdG9yeSkge1xuICAgICAgLy8gV2hlbiB0aGUgdXNlciBzdWJtaXRzIGEgcXVlc3Rpb24sIGlmIHRoZSB1c2VyIGlzIGVkaXRpbmcgYSBwcmV2aW91cyBtZXNzYWdlLCByZW1vdmUgYWxsIHN1YnNlcXVlbnQgbWVzc2FnZXMgZnJvbSB0aGUgY2hhdCBoaXN0b3J5XG4gICAgICBpZiAodGhpcy5tZXNzYWdlVG9FZGl0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgLy8gVXBkYXRlIHRoZSBtZXNzYWdlcyBpbiB0aGUgVUlcbiAgICAgICAgdGhpcy5tZXNzYWdlcyQubmV4dCh0aGlzLm1lc3NhZ2VzJC52YWx1ZS5zbGljZSgwLCB0aGlzLm1lc3NhZ2VUb0VkaXQpKTtcbiAgICAgICAgLy8gVXBkYXRlIHRoZSByYXcgbWVzc2FnZXMgaW4gdGhlIGNoYXQgaGlzdG9yeSB3aGljaCBpcyB0aGUgY2xlYW4gdmVyc2lvbiB1c2VkIHRvIG1ha2UgdGhlIG5leHQgcmVxdWVzdFxuICAgICAgICB0aGlzLmNoYXRTZXJ2aWNlLmNoYXRIaXN0b3J5ID0gdGhpcy5jaGF0U2VydmljZS5jaGF0SGlzdG9yeS5zbGljZSgwLCB0aGlzLm1lc3NhZ2VUb0VkaXQpO1xuICAgICAgICB0aGlzLm1lc3NhZ2VUb0VkaXQgPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICAvLyBSZW1vdmUgdGhlIHNlYXJjaCB3YXJuaW5nIG1lc3NhZ2UgaWYgZXhpc3RzXG4gICAgICBpZiAodGhpcy5jaGF0U2VydmljZS5jaGF0SGlzdG9yeS5hdCgtMSk/LnJvbGUgPT09ICdzZWFyY2gtd2FybmluZycpIHtcbiAgICAgICAgdGhpcy5jaGF0U2VydmljZS5jaGF0SGlzdG9yeS5wb3AoKTtcbiAgICAgIH1cbiAgICAgIC8vIEZldGNoIHRoZSBhbnN3ZXJcbiAgICAgIHRoaXMuX2ZldGNoQW5zd2VyKHRoaXMucXVlc3Rpb24udHJpbSgpLCB0aGlzLmNoYXRTZXJ2aWNlLmNoYXRIaXN0b3J5KTtcbiAgICAgIC8vIENsZWFyIHRoZSBpbnB1dCB2YWx1ZSBpbiB0aGUgVUlcbiAgICAgIHRoaXMucXVlc3Rpb25JbnB1dCEubmF0aXZlRWxlbWVudC52YWx1ZSA9ICcnO1xuICAgICAgdGhpcy5xdWVzdGlvbklucHV0IS5uYXRpdmVFbGVtZW50LnN0eWxlLmhlaWdodCA9IGBhdXRvYDtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9mZXRjaEFuc3dlcihxdWVzdGlvbjogc3RyaW5nLCBjb252ZXJzYXRpb246IENoYXRNZXNzYWdlW10pIHtcbiAgICBjb25zdCB1c2VyTXNnID0ge3JvbGU6ICd1c2VyJywgY29udGVudDogcXVlc3Rpb24sIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiB7ZGlzcGxheTogdHJ1ZSwgaXNVc2VySW5wdXQ6IHRydWUsIGFkZGl0aW9uYWxXb3JrZmxvd1Byb3BlcnRpZXM6IHRoaXMuY29uZmlnLmFkZGl0aW9uYWxXb3JrZmxvd1Byb3BlcnRpZXN9fTtcbiAgICBjb25zdCBtZXNzYWdlcyA9IFsuLi5jb252ZXJzYXRpb24sIHVzZXJNc2ddO1xuICAgIHRoaXMubWVzc2FnZXMkLm5leHQobWVzc2FnZXMpO1xuICAgIHRoaXMuZmV0Y2gobWVzc2FnZXMpO1xuICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVBdWRpdEV2ZW50KCdtZXNzYWdlJywgey4uLnRoaXMuX2RlZmluZU1lc3NhZ2VBdWRpdERldGFpbHModXNlck1zZywgbWVzc2FnZXMubGVuZ3RoIC0gMSksICdxdWVyeSc6IEpTT04uc3RyaW5naWZ5KHRoaXMucXVlcnkpLCAnaXMtdXNlci1pbnB1dCc6IHRydWUsICdlbmFibGVkLWZ1bmN0aW9ucyc6IHRoaXMuY29uZmlnLmRlZmF1bHRWYWx1ZXMuZnVuY3Rpb25zPy5maWx0ZXIoZnVuYyA9PiBmdW5jLmVuYWJsZWQpLm1hcChmdW5jID0+IGZ1bmMubmFtZSksICdhZGRpdGlvbmFsLXdvcmtmbG93LXByb3BlcnRpZXMnOiBKU09OLnN0cmluZ2lmeSh0aGlzLmNvbmZpZy5hZGRpdGlvbmFsV29ya2Zsb3dQcm9wZXJ0aWVzKX0pO1xuICB9XG5cbiAgLyoqXG4gICAqIERlcGVuZGluZyBvbiB0aGUgY29ubmVjdGlvbidzIHN0YXRlIDpcbiAgICogIC0gSWYgY29ubmVjdGVkID0+IGdpdmVuIGEgbGlzdCBvZiBtZXNzYWdlcywgdGhlIGNoYXQgZW5kcG9pbnQgaXMgaW52b2tlZCBmb3IgYSBjb250aW51YXRpb24gYW5kIHVwZGF0ZXMgdGhlIGxpc3Qgb2YgbWVzc2FnZXMgYWNjb3JkaW5nbHkuXG4gICAqICAtIElmIGFueSBvdGhlciBzdGF0ZSA9PiBhIGNvbm5lY3Rpb24gZXJyb3IgbWVzc2FnZSBpcyBkaXNwbGF5ZWQgaW4gdGhlIGNoYXQuXG4gICAqIEBwYXJhbSBtZXNzYWdlc1xuICAgKi9cbiAgcHVibGljIGZldGNoKG1lc3NhZ2VzOiBDaGF0TWVzc2FnZVtdKSB7XG4gICAgdGhpcy5fdXBkYXRlQ29ubmVjdGlvblN0YXR1cygpO1xuICAgIHRoaXMuY2RyLmRldGVjdENoYW5nZXMoKTtcblxuICAgIGlmICh0aGlzLmlzQ29ubmVjdGVkKSB7XG4gICAgICB0aGlzLmxvYWRpbmckLm5leHQodHJ1ZSk7XG4gICAgICB0aGlzLmRhdGFTdWJzY3JpcHRpb24/LnVuc3Vic2NyaWJlKCk7XG4gICAgICB0aGlzLmRhdGFTdWJzY3JpcHRpb24gPSB0aGlzLmNoYXRTZXJ2aWNlLmZldGNoKG1lc3NhZ2VzLCB0aGlzLnF1ZXJ5KVxuICAgICAgICAuc3Vic2NyaWJlKHtcbiAgICAgICAgICBuZXh0OiByZXMgPT4gdGhpcy51cGRhdGVEYXRhKHJlcy5oaXN0b3J5KSxcbiAgICAgICAgICBlcnJvcjogKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5fdXBkYXRlQ29ubmVjdGlvblN0YXR1cygpO1xuICAgICAgICAgICAgaWYgKCF0aGlzLmlzQ29ubmVjdGVkKSB7XG4gICAgICAgICAgICAgIGNvbnN0IG1lc3NhZ2UgPSB7cm9sZTogJ2Nvbm5lY3Rpb24tZXJyb3InLCBjb250ZW50OiB0aGlzLmNvbmZpZy5jb25uZWN0aW9uU2V0dGluZ3MuY29ubmVjdGlvbkVycm9yTWVzc2FnZSwgYWRkaXRpb25hbFByb3BlcnRpZXM6IHtkaXNwbGF5OiB0cnVlfX07XG4gICAgICAgICAgICAgIHRoaXMubWVzc2FnZXMkLm5leHQoWy4uLm1lc3NhZ2VzLCBtZXNzYWdlXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnRlcm1pbmF0ZUZldGNoKCk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICBjb21wbGV0ZTogKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy50ZXJtaW5hdGVGZXRjaCgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSB7cm9sZTogJ2Nvbm5lY3Rpb24tZXJyb3InLCBjb250ZW50OiB0aGlzLmNvbmZpZy5jb25uZWN0aW9uU2V0dGluZ3MuY29ubmVjdGlvbkVycm9yTWVzc2FnZSwgYWRkaXRpb25hbFByb3BlcnRpZXM6IHtkaXNwbGF5OiB0cnVlfX07XG4gICAgICB0aGlzLm1lc3NhZ2VzJC5uZXh0KFsuLi5tZXNzYWdlcywgbWVzc2FnZV0pO1xuICAgIH1cblxuICAgIGlmKHRoaXMuYXV0b21hdGljU2Nyb2xsVG9MYXN0UmVzcG9uc2UpIHtcbiAgICAgIHRoaXMuc2Nyb2xsRG93bigpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyeSB0byBmZXRjaCB0aGUgbWVzc2FnZXMgaWYgdGhlIGNvbm5lY3Rpb24gaXNzdWVzLlxuICAgKiAgLSBJZiByZWNvbm5lY3RpbmcgPT4ga2VlcCBkaXNwbGF5IHRoZSBjb25uZWN0aW9uIGVycm9yIG1lc3NhZ2UgZXZlbiB3aGVuIGNsaWNraW5nIG9uIHRoZSBcInJldHJ5XCIgYnV0dG9uIGFuZCBpbmNyZWFzaW5nIHRoZSBudW1iZXIgb2YgcmV0cmlhbCBhdHRlbXB0cywgdW50aWwgdGhlIGNvbm5lY3Rpb24gaXMgcmUtZXN0YWJsaXNoZWRcbiAgICogIC0gSWYgZGlzY29ubmVjdGVkID0+IE9uIGNsaWNrIG9uIHRoZSBcInJldHJ5XCIgYnV0dG9uLCBzdGFydCB0aGUgY29ubmVjdGlvbiBwcm9jZXNzIHdoaWxlIGRpc3BsYXlpbmcgdGhlIGNvbm5lY3Rpb24gZXJyb3IgbWVzc2FnZSA6XG4gICAqICAgICAgKiBJZiBzdWNjZXNzZnVsID0+IGdpdmVuIGEgbGlzdCBvZiBtZXNzYWdlcywgdGhlIGNoYXQgZW5kcG9pbnQgaXMgaW52b2tlZCBmb3IgYSBjb250aW51YXRpb24gYW5kIHVwZGF0ZXMgdGhlIGxpc3Qgb2YgbWVzc2FnZXMgYWNjb3JkaW5nbHkuXG4gICAqICAgICAgKiBJZiBmYWlsZWQgPT4gaW5jcmVhc2UgdGhlIG51bWJlciBvZiByZXRyaWFsIGF0dGVtcHRzXG4gICAqL1xuICByZXRyeUZldGNoKCkge1xuICAgIGlmKHRoaXMuY2hhdFNlcnZpY2UgaW5zdGFuY2VvZiBXZWJTb2NrZXRDaGF0U2VydmljZSkge1xuICAgICAgLy8gQSBvbmUtdGltZSBsaXN0ZW5lciBmb3IgcmVjb25uZWN0ZWQgZXZlbnRcbiAgICAgIGNvbnN0IG9uUmVjb25uZWN0ZWRIYW5kbGVyID0gKCkgPT4ge1xuICAgICAgICBjb25zdCBtZXNzYWdlcyA9IHRoaXMubWVzc2FnZXMkLnZhbHVlIS5zbGljZSgwLCAtMSk7XG4gICAgICAgIGNvbnN0IGxhc3RNZXNzYWdlID0gbWVzc2FnZXMuYXQoLTEpO1xuICAgICAgICBpZihsYXN0TWVzc2FnZSAmJiBsYXN0TWVzc2FnZS5yb2xlID09PSAndXNlcicpIHsgLy8gQW5kIGl0IGlzIGFsd2F5cyB0aGUgY2FzZTogdGhlIGxhc3QgbWVzc2FnZSBpcyBhbHdheXMgZnJvbSB0aGUgdXNlclxuICAgICAgICAgIHRoaXMuZmV0Y2gobWVzc2FnZXMpOyAvLyBJZiB0aGUgbGFzdCBtZXNzYWdlIGlmIGZyb20gYSB1c2VyLCBhbiBhbnN3ZXIgZnJvbSB0aGUgYXNzaXN0YW50IGlzIGV4cGVjdGVkXG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZXRyaWFsQXR0ZW1wdHMgPSB1bmRlZmluZWQ7IC8vIFJlc2V0IHRoZSBudW1iZXIgb2YgcmV0cmlhbCBhdHRlbXB0c1xuICAgICAgICAvKipcbiAgICAgICAgICogVG8gcmVtb3ZlIHRoZSBoYW5kbGVyIGZvciBvbnJlY29ubmVjdGVkKCkgYWZ0ZXIgaXQncyBiZWVuIHJlZ2lzdGVyZWQsY2Fubm90IGRpcmVjdGx5IHVzZSBvZmYoKSBsaWtlIHlvdSB3b3VsZCBmb3Igbm9ybWFsIGV2ZW50cyByZWdpc3RlcmVkIHdpdGggY29ubmVjdGlvbi5vbigpLlxuICAgICAgICAgKiBJbnN0ZWFkLCB5b3UgbmVlZCB0byBleHBsaWNpdGx5IHJlbW92ZSBvciByZXNldCB0aGUgaGFuZGxlciBieSBhc3NpZ25pbmcgaXQgdG8gbnVsbCBvciBhbiBlbXB0eSBmdW5jdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgKHRoaXMuY2hhdFNlcnZpY2UgYXMgV2ViU29ja2V0Q2hhdFNlcnZpY2UpLmNvbm5lY3Rpb24hLm9ucmVjb25uZWN0ZWQoKCkgPT4ge30pO1xuICAgICAgICAvLyBSZXNldCB0aGUgZmxhZyB0byBlbnN1cmUgdGhlIGhhbmRsZXIgaXMgcmVnaXN0ZXJlZCBhZ2FpbiB3aGVuIG5lZWRlZFxuICAgICAgICB0aGlzLl9pc1JlY29ubmVjdGVkTGlzdGVuZXJSZWdpc3RlcmVkID0gZmFsc2U7XG4gICAgICB9XG4gICAgICAvLyBEZXBlbmRpbmcgb24gdGhlIGNvbm5lY3Rpb24ncyBzdGF0ZSwgdGFrZSB0aGUgYXBwcm9wcmlhdGUgYWN0aW9uXG4gICAgICBzd2l0Y2ggKHRoaXMuY2hhdFNlcnZpY2UuY29ubmVjdGlvbiEuc3RhdGUpIHtcbiAgICAgICAgY2FzZSBIdWJDb25uZWN0aW9uU3RhdGUuQ29ubmVjdGVkOlxuICAgICAgICAgIC8vIElmIHRoZSBjb25uZWN0aW9uIGlzIHJlLWVzdGFibGlzaGVkIGluIHRoZSBtZWFudGltZSwgZmV0Y2ggdGhlIG1lc3NhZ2VzXG4gICAgICAgICAgb25SZWNvbm5lY3RlZEhhbmRsZXIoKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBIdWJDb25uZWN0aW9uU3RhdGUuUmVjb25uZWN0aW5nOlxuICAgICAgICAgIC8vIEF0dGFjaCB0aGUgcmVjb25uZWN0ZWQgbGlzdGVuZXIgaWYgbm90IGFscmVhZHkgcmVnaXN0ZXJlZFxuICAgICAgICAgIGlmICghdGhpcy5faXNSZWNvbm5lY3RlZExpc3RlbmVyUmVnaXN0ZXJlZCkge1xuICAgICAgICAgICAgdGhpcy5jaGF0U2VydmljZS5jb25uZWN0aW9uIS5vbnJlY29ubmVjdGVkKG9uUmVjb25uZWN0ZWRIYW5kbGVyKTtcbiAgICAgICAgICAgIHRoaXMuX2lzUmVjb25uZWN0ZWRMaXN0ZW5lclJlZ2lzdGVyZWQgPSB0cnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBJbmNyZWFzZSB0aGUgbnVtYmVyIG9mIHJldHJpYWwgYXR0ZW1wdHNcbiAgICAgICAgICB0aGlzLnJldHJpYWxBdHRlbXB0cyA9IHRoaXMucmV0cmlhbEF0dGVtcHRzID8gdGhpcy5yZXRyaWFsQXR0ZW1wdHMrMSA6IDE7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgSHViQ29ubmVjdGlvblN0YXRlLkRpc2Nvbm5lY3RlZDpcbiAgICAgICAgICAvLyBTdGFydCB0aGUgbmV3IGNvbm5lY3Rpb25cbiAgICAgICAgICB0aGlzLmNoYXRTZXJ2aWNlLnN0YXJ0Q29ubmVjdGlvbigpXG4gICAgICAgICAgLnRoZW4oKCkgPT4gb25SZWNvbm5lY3RlZEhhbmRsZXIoKSlcbiAgICAgICAgICAuY2F0Y2goKCkgPT4geyAvLyBJZiB0aGUgY29ubmVjdGlvbiBmYWlscywgaW5jcmVhc2UgdGhlIG51bWJlciBvZiByZXRyaWFsIGF0dGVtcHRzXG4gICAgICAgICAgICB0aGlzLnJldHJpYWxBdHRlbXB0cyA9IHRoaXMucmV0cmlhbEF0dGVtcHRzID8gdGhpcy5yZXRyaWFsQXR0ZW1wdHMrMSA6IDE7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIHRoZSBzaWduYWxSIGNvbm5lY3Rpb24gaXMgY29ubmVjdGVkLlxuICAgKiBGb3IgdGhlIFJFU1QgcHJvdG9jb2wsIHRoZSBjb25uZWN0aW9uIGlzIGFsd2F5cyBjb25zaWRlcmVkIGNvbm5lY3RlZCAoZm9yIHRoZSBtb21lbnQpLlxuICAgKi9cbiAgcHJpdmF0ZSBfdXBkYXRlQ29ubmVjdGlvblN0YXR1cygpIHtcbiAgICB0aGlzLmlzQ29ubmVjdGVkID0gKHRoaXMuY2hhdFNlcnZpY2UgaW5zdGFuY2VvZiBXZWJTb2NrZXRDaGF0U2VydmljZSkgPyB0aGlzLmNoYXRTZXJ2aWNlLmNvbm5lY3Rpb24hLnN0YXRlID09PSBIdWJDb25uZWN0aW9uU3RhdGUuQ29ubmVjdGVkIDogdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVcGRhdGUgdGhlIFVJIHdpdGggdGhlIG5ldyBtZXNzYWdlc1xuICAgKiBAcGFyYW0gbWVzc2FnZXNcbiAgICovXG4gIHVwZGF0ZURhdGEobWVzc2FnZXM6IENoYXRNZXNzYWdlW10pIHtcbiAgICB0aGlzLm1lc3NhZ2VzJC5uZXh0KG1lc3NhZ2VzKTtcbiAgICB0aGlzLmRhdGEuZW1pdChtZXNzYWdlcyk7XG4gICAgdGhpcy5sb2FkaW5nJC5uZXh0KGZhbHNlKTtcbiAgICB0aGlzLnF1ZXN0aW9uID0gJyc7XG4gICAgaWYodGhpcy5hdXRvbWF0aWNTY3JvbGxUb0xhc3RSZXNwb25zZSkge1xuICAgICAgdGhpcy5zY3JvbGxEb3duKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfdG9nZ2xlU2Nyb2xsQnV0dG9uVmlzaWJpbGl0eSgpOiBib29sZWFuIHtcbiAgICBpZih0aGlzLm1lc3NhZ2VMaXN0Py5uYXRpdmVFbGVtZW50KSB7XG4gICAgICByZXR1cm4gTWF0aC5yb3VuZCh0aGlzLm1lc3NhZ2VMaXN0Py5uYXRpdmVFbGVtZW50LnNjcm9sbEhlaWdodCAtIHRoaXMubWVzc2FnZUxpc3Q/Lm5hdGl2ZUVsZW1lbnQuc2Nyb2xsVG9wIC0gMSkgPD0gdGhpcy5tZXNzYWdlTGlzdD8ubmF0aXZlRWxlbWVudC5jbGllbnRIZWlnaHQ7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgc2Nyb2xsRG93bigpIHtcbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIGlmKHRoaXMubWVzc2FnZUxpc3Q/Lm5hdGl2ZUVsZW1lbnQpIHtcbiAgICAgICAgdGhpcy5tZXNzYWdlTGlzdC5uYXRpdmVFbGVtZW50LnNjcm9sbFRvcCA9IHRoaXMubWVzc2FnZUxpc3QubmF0aXZlRWxlbWVudC5zY3JvbGxIZWlnaHQ7XG4gICAgICAgIHRoaXMuY2RyLmRldGVjdENoYW5nZXMoKTtcbiAgICAgIH1cbiAgICB9LCAxMCk7XG4gIH1cblxuICAvKipcbiAgICogU3RhcnQgYSBuZXcgY2hhdCB3aXRoIHRoZSBkZWZhdWx0VmFsdWVzIHNldHRpbmdzXG4gICAqIFRoZSBzYXZlZENoYXRJZCBpbiB0aGUgY2hhdCBzZXJ2aWNlIHdpbGwgYmUgcmVzZXQsIHNvIHRoYXQgdGhlIHVwY29taW5nIHNhdmVkIGNoYXQgb3BlcmF0aW9ucyB3aWxsIGJlIHBlcmZvcm1lZCBvbiB0aGUgZnJlc2ggbmV3IGNoYXRcbiAgICogSWYgdGhlIHNhdmVkQ2hhdCBmZWF0dXJlIGlzIGVuYWJsZWQsIHRoZSBsaXN0IG9mIHNhdmVkIGNoYXRzIHdpbGwgYmUgcmVmcmVzaGVkXG4gICAqL1xuICBuZXdDaGF0KCkge1xuICAgIHRoaXMuY2hhdFNlcnZpY2Uuc2V0U2F2ZWRDaGF0SWQodW5kZWZpbmVkKTsgLy8gUmVzZXQgdGhlIHNhdmVkQ2hhdElkXG4gICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUNoYXRJZCgpOyAvLyBHZW5lcmF0ZSBhIG5ldyBjaGF0SWRcbiAgICB0aGlzLmNoYXRTZXJ2aWNlLmxpc3RTYXZlZENoYXQoKTsgLy8gUmVmcmVzaCB0aGUgbGlzdCBvZiBzYXZlZCBjaGF0c1xuICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVBdWRpdEV2ZW50KCduZXctY2hhdCcsIHsnY29uZmlndXJhdGlvbic6IEpTT04uc3RyaW5naWZ5KHRoaXMuY2hhdFNlcnZpY2UuY2hhdENvbmZpZyQudmFsdWUpfSk7IC8vIEdlbmVyYXRlIGEgbmV3IGNoYXQgYXVkaXQgZXZlbnRcbiAgICB0aGlzLmxvYWREZWZhdWx0Q2hhdCgpOyAvLyBTdGFydCBhIG5ldyBjaGF0XG4gIH1cblxuICAvKipcbiAgICogU3RhcnQgdGhlIGRlZmF1bHQgY2hhdCB3aXRoIHRoZSBkZWZhdWx0VmFsdWVzIHNldHRpbmdzXG4gICAqIElmIHRoZSBjaGF0IGlzIG1lYW50IHRvIGJlIGluaXRpYWxpemVkIHdpdGggZXZlbnQgPT09IFwiUXVlcnlcIiwgdGhlIGNvcnJlc3BvbmRpbmcgdXNlciBxdWVyeSBtZXNzYWdlIHdpbGwgYmUgYWRkZWQgdG8gdGhlIGNoYXQgaGlzdG9yeVxuICAgKi9cbiAgbG9hZERlZmF1bHRDaGF0KCkge1xuICAgIC8vIERlZmluZSB0aGUgZGVmYXVsdCBzeXN0ZW0gcHJvbXB0IGFuZCB1c2VyIHByb21wdCBtZXNzYWdlc1xuICAgIGNvbnN0IHN5c3RlbU1zZyA9IHtyb2xlOiAnc3lzdGVtJywgY29udGVudDogdGhpcy5jb25maWcuZGVmYXVsdFZhbHVlcy5zeXN0ZW1Qcm9tcHQsIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiB7ZGlzcGxheTogZmFsc2V9fTtcbiAgICBjb25zdCB1c2VyTXNnID0ge3JvbGU6ICd1c2VyJywgY29udGVudDogQ2hhdFNlcnZpY2UuZm9ybWF0UHJvbXB0KHRoaXMuY29uZmlnLmRlZmF1bHRWYWx1ZXMudXNlclByb21wdCwge3ByaW5jaXBhbDogdGhpcy5wcmluY2lwYWxTZXJ2aWNlLnByaW5jaXBhbH0pLCBhZGRpdGlvbmFsUHJvcGVydGllczoge2Rpc3BsYXk6IHRoaXMuY29uZmlnLm1vZGVTZXR0aW5ncy5kaXNwbGF5VXNlclByb21wdH19O1xuXG4gICAgaWYgKHRoaXMuY29uZmlnLm1vZGVTZXR0aW5ncy5pbml0aWFsaXphdGlvbi5ldmVudCA9PT0gJ1F1ZXJ5Jykge1xuICAgICAgdGhpcy5faGFuZGxlUXVlcnlNb2RlKHN5c3RlbU1zZywgdXNlck1zZyk7XG4gICAgfSBlbHNlIHsgLy8gSWYgdGhlIGNoYXQgaXMgbWVhbnQgdG8gYmUgaW5pdGlhbGl6ZWQgd2l0aCBldmVudCA9PT0gXCJQcm9tcHRcIlxuICAgICAgdGhpcy5vcGVuQ2hhdChbc3lzdGVtTXNnLCB1c2VyTXNnXSk7XG4gICAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudCgnbWVzc2FnZScsIHRoaXMuX2RlZmluZU1lc3NhZ2VBdWRpdERldGFpbHMoc3lzdGVtTXNnLCAwKSk7XG4gICAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudCgnbWVzc2FnZScsIHRoaXMuX2RlZmluZU1lc3NhZ2VBdWRpdERldGFpbHModXNlck1zZywgMSkpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJZiB0aGUgcHJvdmlkZWQgcXVlcnkgdGV4dCBpcyBub3QgZW1wdHksIHRoZW4gYWRkIHRoZSB1c2VyIHF1ZXJ5IG1lc3NhZ2UgdG8gdGhlIGNoYXQgaGlzdG9yeSBhbmQgaW52b2tlIHRoZSBhc3Npc3RhbnRcbiAgICogT3RoZXJ3aXNlLCBqdXN0IHN0YXJ0IGEgbmV3IGNoYXQgd2l0aCBhIHdhcm5pbmcgbWVzc2FnZSBpbnZpdGluZyB0aGUgdXNlciB0byBwZXJmb3JtIGEgZnVsbCB0ZXh0IHNlYXJjaCB0byByZXRyaWV2ZSBzb21lIHJlc3VsdHNcbiAgICovXG4gIHByaXZhdGUgX2hhbmRsZVF1ZXJ5TW9kZShzeXN0ZW1Nc2c6IENoYXRNZXNzYWdlLCB1c2VyTXNnOiBDaGF0TWVzc2FnZSkge1xuICAgIGlmICghIXRoaXMucXVlcnkudGV4dCkge1xuICAgICAgY29uc3QgdXNlclF1ZXJ5TXNnID0ge3JvbGU6ICd1c2VyJywgY29udGVudDogdGhpcy5xdWVyeS50ZXh0LCBhZGRpdGlvbmFsUHJvcGVydGllczoge2Rpc3BsYXk6IHRoaXMuY29uZmlnLm1vZGVTZXR0aW5ncy5pbml0aWFsaXphdGlvbi5kaXNwbGF5VXNlclF1ZXJ5LCBxdWVyeTogdGhpcy5xdWVyeSwgZm9yY2VkV29ya2Zsb3c6IHRoaXMuY29uZmlnLm1vZGVTZXR0aW5ncy5pbml0aWFsaXphdGlvbi5mb3JjZWRXb3JrZmxvdywgaXNVc2VySW5wdXQ6IHRydWUsIGFkZGl0aW9uYWxXb3JrZmxvd1Byb3BlcnRpZXM6IHRoaXMuY29uZmlnLmFkZGl0aW9uYWxXb3JrZmxvd1Byb3BlcnRpZXN9fTtcbiAgICAgIGlmICh0aGlzLmNvbmZpZy5tb2RlU2V0dGluZ3Muc2VuZFVzZXJQcm9tcHQpIHtcbiAgICAgICAgdGhpcy5vcGVuQ2hhdChbc3lzdGVtTXNnLCB1c2VyTXNnLCB1c2VyUXVlcnlNc2ddKTtcbiAgICAgICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ21lc3NhZ2UnLCB0aGlzLl9kZWZpbmVNZXNzYWdlQXVkaXREZXRhaWxzKHN5c3RlbU1zZywgMCkpO1xuICAgICAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudCgnbWVzc2FnZScsIHRoaXMuX2RlZmluZU1lc3NhZ2VBdWRpdERldGFpbHModXNlck1zZywgMSkpO1xuICAgICAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudCgnbWVzc2FnZScsIHsuLi50aGlzLl9kZWZpbmVNZXNzYWdlQXVkaXREZXRhaWxzKHVzZXJRdWVyeU1zZywgMiksICdxdWVyeSc6IEpTT04uc3RyaW5naWZ5KHRoaXMucXVlcnkpICwnaXMtdXNlci1pbnB1dCc6IHRydWUsICdmb3JjZWQtd29ya2Zsb3cnOiB0aGlzLmNvbmZpZy5tb2RlU2V0dGluZ3MuaW5pdGlhbGl6YXRpb24uZm9yY2VkV29ya2Zsb3csICdlbmFibGVkLWZ1bmN0aW9ucyc6IHRoaXMuY29uZmlnLmRlZmF1bHRWYWx1ZXMuZnVuY3Rpb25zPy5maWx0ZXIoZnVuYyA9PiBmdW5jLmVuYWJsZWQpLm1hcChmdW5jID0+IGZ1bmMubmFtZSksICdhZGRpdGlvbmFsLXdvcmtmbG93LXByb3BlcnRpZXMnOkpTT04uc3RyaW5naWZ5KHRoaXMuY29uZmlnLmFkZGl0aW9uYWxXb3JrZmxvd1Byb3BlcnRpZXMpfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLm9wZW5DaGF0KFtzeXN0ZW1Nc2csIHVzZXJRdWVyeU1zZ10pO1xuICAgICAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudCgnbWVzc2FnZScsIHRoaXMuX2RlZmluZU1lc3NhZ2VBdWRpdERldGFpbHMoc3lzdGVtTXNnLCAwKSk7XG4gICAgICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVBdWRpdEV2ZW50KCdtZXNzYWdlJywgey4uLnRoaXMuX2RlZmluZU1lc3NhZ2VBdWRpdERldGFpbHModXNlclF1ZXJ5TXNnLCAxKSwgJ3F1ZXJ5JzogSlNPTi5zdHJpbmdpZnkodGhpcy5xdWVyeSkgLCdpcy11c2VyLWlucHV0JzogdHJ1ZSwgJ2ZvcmNlZC13b3JrZmxvdyc6IHRoaXMuY29uZmlnLm1vZGVTZXR0aW5ncy5pbml0aWFsaXphdGlvbi5mb3JjZWRXb3JrZmxvdywgJ2VuYWJsZWQtZnVuY3Rpb25zJzogdGhpcy5jb25maWcuZGVmYXVsdFZhbHVlcy5mdW5jdGlvbnM/LmZpbHRlcihmdW5jID0+IGZ1bmMuZW5hYmxlZCkubWFwKGZ1bmMgPT4gZnVuYy5uYW1lKSwgJ2FkZGl0aW9uYWwtd29ya2Zsb3ctcHJvcGVydGllcyc6IEpTT04uc3RyaW5naWZ5KHRoaXMuY29uZmlnLmFkZGl0aW9uYWxXb3JrZmxvd1Byb3BlcnRpZXMpfSk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHdhcm5pbmdNc2cgPSB7cm9sZTogJ3NlYXJjaC13YXJuaW5nJywgY29udGVudDogdGhpcy5jb25maWcuZ2xvYmFsU2V0dGluZ3Muc2VhcmNoV2FybmluZ01lc3NhZ2UsIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiB7ZGlzcGxheTogdHJ1ZX19O1xuICAgICAgdGhpcy5vcGVuQ2hhdChbc3lzdGVtTXNnLCB3YXJuaW5nTXNnXSk7XG4gICAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudCgnbWVzc2FnZScsIHRoaXMuX2RlZmluZU1lc3NhZ2VBdWRpdERldGFpbHMod2FybmluZ01zZywgMCkpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX2RlZmluZU1lc3NhZ2VBdWRpdERldGFpbHMobWVzc2FnZTogQ2hhdE1lc3NhZ2UsIHJhbms6IG51bWJlcik6IFJlY29yZDxzdHJpbmcsIGFueT4ge1xuICAgIHJldHVybiB7XG4gICAgICAnZHVyYXRpb24nOiAwLFxuICAgICAgJ3RleHQnOiBtZXNzYWdlLmNvbnRlbnQsXG4gICAgICAncm9sZSc6IG1lc3NhZ2Uucm9sZSxcbiAgICAgICdyYW5rJzogcmFua1xuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogU3RhcnQvb3BlbiBhIG5ldyBjaGF0IHdpdGggdGhlIHByb3ZpZGVkIG1lc3NhZ2VzIGFuZCBjaGF0SWRcbiAgICogSWYgdGhlIGxhc3QgbWVzc2FnZSBpcyBmcm9tIHRoZSB1c2VyLCBhIHJlcXVlc3QgdG8gdGhlIGFzc2lzdGFudCBpcyBtYWRlIHRvIGdldCBhbiBhbnN3ZXJcbiAgICogSWYgdGhlIGxhc3QgbWVzc2FnZSBpcyBmcm9tIHRoZSBhc3Npc3RhbnQsIHRoZSBjb252ZXJzYXRpb24gaXMgbG9hZGVkIHJpZ2h0IGF3YXlcbiAgICogQHBhcmFtIG1lc3NhZ2VzIFRoZSBsaXN0IG9mIG1lc3NhZ2VzIG9mIHRoZSBjaGF0XG4gICAqIEBwYXJhbSBzYXZlZENoYXRJZCAgVGhlIGlkIG9mIHRoZSBzYXZlZCBjaGF0LiBJZiBwcm92aWRlZCAoaWUuIGFuIGV4aXN0aW5nIGRpc2N1c3Npb24gaW4gdGhlIHNhdmVkIGNoYXQgaW5kZXgpLCB1cGRhdGUgdGhlIHNhdmVkQ2hhdElkIGluIHRoZSBjaGF0IHNlcnZpY2UgZm9yIHRoZSB1cGNvbWluZyBzYXZlZCBjaGF0IG9wZXJhdGlvbnNcbiAgICovXG4gIG9wZW5DaGF0KG1lc3NhZ2VzOiBSYXdNZXNzYWdlW10sIHNhdmVkQ2hhdElkPzogc3RyaW5nKSB7XG4gICAgaWYgKCFtZXNzYWdlcyB8fCAhQXJyYXkuaXNBcnJheShtZXNzYWdlcykpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIG9jY3VycyB3aGlsZSB0cnlpbmcgdG8gbG9hZCB0aGUgY2hhdCBkaXNjdXNzaW9uLiBJbnZhbGlkIG1lc3NhZ2VzIHJlY2VpdmVkIDonLCBtZXNzYWdlcyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChzYXZlZENoYXRJZCkge1xuICAgICAgdGhpcy5jaGF0U2VydmljZS5zZXRTYXZlZENoYXRJZChzYXZlZENoYXRJZCk7XG4gICAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQ2hhdElkKHNhdmVkQ2hhdElkKTtcbiAgICB9XG4gICAgdGhpcy5yZXNldENoYXQoKTtcbiAgICB0aGlzLm1lc3NhZ2VzJC5uZXh0KG1lc3NhZ2VzKTtcbiAgICB0aGlzLmNoYXRTZXJ2aWNlLmNoYXRIaXN0b3J5ID0gbWVzc2FnZXM7XG4gICAgY29uc3QgbGFzdE1lc3NhZ2UgPSBtZXNzYWdlcy5hdCgtMSk7XG4gICAgaWYobGFzdE1lc3NhZ2UgJiYgbGFzdE1lc3NhZ2Uucm9sZSA9PT0gJ3VzZXInKSB7XG4gICAgICB0aGlzLmZldGNoKG1lc3NhZ2VzKTsgLy8gSWYgdGhlIGxhc3QgbWVzc2FnZSBpZiBmcm9tIGEgdXNlciwgYW4gYW5zd2VyIGZyb20gdGhlIGFzc2lzdGFudCBpcyBleHBlY3RlZFxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHRoaXMudXBkYXRlRGF0YShtZXNzYWdlcyk7IC8vIElmIHRoZSBsYXN0IG1lc3NhZ2UgaWYgZnJvbSB0aGUgYXNzaXN0YW50LCB3ZSBjYW4gbG9hZCB0aGUgY29udmVyc2F0aW9uIHJpZ2h0IGF3YXlcbiAgICAgIHRoaXMudGVybWluYXRlRmV0Y2goKTtcbiAgICB9XG4gICAgdGhpcy5fYWRkU2Nyb2xsTGlzdGVuZXIoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNldCB0aGUgY2hhdCBieSBjbGVhcmluZyB0aGUgY2hhdCBoaXN0b3J5IGFuZCB0aGUgVUkgYWNjb3JkaW5nbHlcbiAgICogVGhlIHVzZXIgaW5wdXQgd2lsbCBiZSBjbGVhcmVkXG4gICAqIFRoZSBmZXRjaCBzdWJzY3JpcHRpb24gd2lsbCBiZSB0ZXJtaW5hdGVkXG4gICAqL1xuICByZXNldENoYXQoKSB7XG4gICAgaWYodGhpcy5tZXNzYWdlcyQudmFsdWUpIHtcbiAgICAgIHRoaXMubWVzc2FnZXMkLm5leHQodW5kZWZpbmVkKTsgLy8gUmVzZXQgY2hhdFxuICAgIH1cbiAgICB0aGlzLmNoYXRTZXJ2aWNlLmNoYXRIaXN0b3J5ID0gdW5kZWZpbmVkOyAvLyBSZXNldCBjaGF0IGhpc3RvcnlcbiAgICB0aGlzLnF1ZXN0aW9uID0gJyc7XG4gICAgdGhpcy50ZXJtaW5hdGVGZXRjaCgpO1xuICB9XG5cbiAgb25Mb2FkQ2hhdCgpIHtcbiAgICB0aGlzLmxvYWRpbmckLm5leHQodHJ1ZSk7XG4gICAgdGhpcy5zdWIuYWRkKFxuICAgICAgdGhpcy5jaGF0U2VydmljZS5sb2FkU2F2ZWRDaGF0JFxuICAgICAgICAucGlwZShcbiAgICAgICAgICBmaWx0ZXIoc2F2ZWRDaGF0ID0+ICEhc2F2ZWRDaGF0KSxcbiAgICAgICAgICBzd2l0Y2hNYXAoc2F2ZWRDaGF0ID0+IHRoaXMuY2hhdFNlcnZpY2UuZ2V0U2F2ZWRDaGF0KHNhdmVkQ2hhdCEuaWQpKSxcbiAgICAgICAgICBmaWx0ZXIoc2F2ZWRDaGF0SGlzdG9yeSA9PiAhIXNhdmVkQ2hhdEhpc3RvcnkpLFxuICAgICAgICAgIHRhcChzYXZlZENoYXRIaXN0b3J5ID0+IHRoaXMub3BlbkNoYXQoc2F2ZWRDaGF0SGlzdG9yeSEuaGlzdG9yeSwgc2F2ZWRDaGF0SGlzdG9yeSEuaWQpKVxuICAgICAgICApLnN1YnNjcmliZSgpXG4gICAgKTtcbiAgfVxuXG4gIHRlcm1pbmF0ZUZldGNoKCkge1xuICAgIHRoaXMuZGF0YVN1YnNjcmlwdGlvbj8udW5zdWJzY3JpYmUoKTtcbiAgICB0aGlzLmRhdGFTdWJzY3JpcHRpb24gPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5sb2FkaW5nJC5uZXh0KGZhbHNlKTtcbiAgICB0aGlzLmNkci5kZXRlY3RDaGFuZ2VzKCk7XG4gIH1cblxuICAvKipcbiAgICogQ29weSBhIHByZXZpb3VzIHVzZXIgbWVzc2FnZSBvZiB0aGUgY2hhdCBoaXN0b3J5IHRvIHRoZSBjaGF0IHVzZXIgaW5wdXQuXG4gICAqIFRodXMsIHRoZSB1c2VyIGNhbiBlZGl0IGFuZCByZXN1Ym1pdCB0aGUgbWVzc2FnZS5cbiAgICogT25jZSB0aGUgZWRpdGVkIG1lc3NhZ2UgaXMgc3VibWl0dGVkLCBhbGwgc3Vic2VxdWVudCBtZXNzYWdlcyBzdGFydGluZyBmcm9tIEBwYXJhbSBpbmRleCB3aWxsIGJlIHJlbW92ZWQgZnJvbSB0aGUgaGlzdG9yeSBhbmQgdGhlIFVJIHdpbGwgYmUgdXBkYXRlZCBhY2NvcmRpbmdseS5cbiAgICogVGhlIGFzc2lzdGFudCB3aWxsIHJlZ2VuZXJhdGUgYSBuZXcgYW5zd2VyIGJhc2VkIG9uIHRoZSB1cGRhdGVkIGNoYXQgaGlzdG9yeS5cbiAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgdXNlcidzIG1lc3NhZ2UgdG8gZWRpdFxuICAgKi9cbiAgZWRpdE1lc3NhZ2UoaW5kZXg6IG51bWJlcikge1xuICAgIHRoaXMubWVzc2FnZVRvRWRpdCA9IGluZGV4O1xuICAgIHRoaXMucXVlc3Rpb24gPSB0aGlzLmNoYXRTZXJ2aWNlLmNoYXRIaXN0b3J5IVtpbmRleF0uY29udGVudDtcbiAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudCgnZWRpdC5jbGljaycsIHsncmFuayc6IGluZGV4fSk7XG4gIH1cblxuICAvKipcbiAgICogQ29weSBhIHByZXZpb3VzIGFzc2lzdGFudCBtZXNzYWdlIG9mIHRoZSBjaGF0IGhpc3RvcnkgdG8gdGhlIGNsaXBib2FyZC5cbiAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgYXNzaXN0YW50J3MgbWVzc2FnZSB0byBlZGl0XG4gICAqL1xuICBjb3B5TWVzc2FnZShpbmRleDogbnVtYmVyKSB7XG4gICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ2NvcHkuY2xpY2snLCB7J3JhbmsnOiBpbmRleH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFN0YXJ0aW5nIGZyb20gdGhlIHByb3ZpZGVkIGluZGV4LCByZW1vdmUgYWxsIHN1YnNlcXVlbnQgbWVzc2FnZXMgZnJvbSB0aGUgY2hhdCBoaXN0b3J5IGFuZCB0aGUgVUkgYWNjb3JkaW5nbHkuXG4gICAqIFRoZSBhc3Npc3RhbnQgd2lsbCByZWdlbmVyYXRlIGEgbmV3IGFuc3dlciBiYXNlZCBvbiB0aGUgdXBkYXRlZCBjaGF0IGhpc3RvcnkuXG4gICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGFzc2lzdGFudCdzIG1lc3NhZ2UgdG8gcmVnZW5lcmF0ZVxuICAgKi9cbiAgcmVnZW5lcmF0ZU1lc3NhZ2UoaW5kZXg6IG51bWJlcikge1xuICAgICAvLyBEZWZpbmUgdGhlIGNoYXQgaGlzdG9yeSBiYXNlZCBvbiB3aGljaCB0aGUgYXNzaXN0YW50IHdpbGwgZ2VuZXJhdGUgYSBuZXcgYW5zd2VyXG4gICAgY29uc3Qgc2xpY2VkTWVzc2FnZXMgPSB0aGlzLmNoYXRTZXJ2aWNlLmNoYXRIaXN0b3J5IS5zbGljZSgwLCBpbmRleCk7XG4gICAgLy8gQWNjb3JkaW5nbHkgdXBkYXRlIHRoZSBtZXNzYWdlcyBpbiB0aGUgVUlcbiAgICB0aGlzLm1lc3NhZ2VzJC5uZXh0KHNsaWNlZE1lc3NhZ2VzKTtcbiAgICAvLyBGZXRjaCB0aGUgYW5zd2VyXG4gICAgdGhpcy5mZXRjaChzbGljZWRNZXNzYWdlcyk7XG4gICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ3JlZ2VuZXJhdGUuY2xpY2snLCB7J3JhbmsnOiBpbmRleH0pO1xuICB9XG5cbiAgb25LZXlVcChldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xuICAgIHN3aXRjaCAoZXZlbnQua2V5KSB7XG4gICAgICBjYXNlICdCYWNrc3BhY2UnOlxuICAgICAgICB0aGlzLmNhbGN1bGF0ZUhlaWdodCgpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ0VudGVyJzpcbiAgICAgICAgaWYgKCFldmVudC5zaGlmdEtleSkge1xuICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgdGhpcy5zdWJtaXRRdWVzdGlvbigpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2FsY3VsYXRlSGVpZ2h0KCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgY2FsY3VsYXRlSGVpZ2h0KGV2ZW50PzogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xuICAgIGlmIChldmVudD8ua2V5ID09PSAnRW50ZXInICYmICFldmVudC5zaGlmdEtleSkge1xuICAgICAgZXZlbnQ/LnByZXZlbnREZWZhdWx0KCk7XG4gICAgfVxuICAgIGNvbnN0IG1heEhlaWdodCA9IDE3MDtcbiAgICBjb25zdCBlbCA9IHRoaXMucXVlc3Rpb25JbnB1dCEubmF0aXZlRWxlbWVudDtcbiAgICBlbC5zdHlsZS5tYXhIZWlnaHQgPSBgJHttYXhIZWlnaHR9cHhgO1xuICAgIGVsLnN0eWxlLmhlaWdodCA9ICdhdXRvJztcbiAgICBlbC5zdHlsZS5oZWlnaHQgPSBgJHtlbC5zY3JvbGxIZWlnaHR9cHhgO1xuICAgIGVsLnN0eWxlLm92ZXJmbG93WSA9IGVsLnNjcm9sbEhlaWdodCA+PSBtYXhIZWlnaHQgPyAnc2Nyb2xsJyA6ICdoaWRkZW4nO1xuICB9XG5cbiAgLyoqXG4gICAqIFNlbmQgYSBcImxpa2VcIiBldmVudCBvbiBjbGlja2luZyBvbiB0aGUgdGh1bWItdXAgaWNvbiBvZiBhbiBhc3Npc3RhbnQncyBtZXNzYWdlXG4gICAqIEBwYXJhbSByYW5rIFRoZSByYW5rIG9mIHRoZSBtZXNzYWdlIHRvIGxpa2VcbiAgICovXG4gIG9uTGlrZShyYW5rOiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudCgndGh1bWItdXAuY2xpY2snLCB7cmFua30pO1xuICB9XG5cbiAgLyoqXG4gICAqIFNlbmQgYSBcImRpc2xpa2VcIiBldmVudCBvbiBjbGlja2luZyBvbiB0aGUgdGh1bWItZG93biBpY29uIG9mIGFuIGFzc2lzdGFudCdzIG1lc3NhZ2UuXG4gICAqIEl0IGFsc28gb3BlbnMgdGhlIGlzc3VlIHJlcG9ydGluZyBkaWFsb2cuXG4gICAqIEBwYXJhbSBtZXNzYWdlIFRoZSBhc3Npc3RhbnQgbWVzc2FnZSB0byBkaXNsaWtlXG4gICAqIEBwYXJhbSByYW5rIFRoZSByYW5rIG9mIHRoZSBtZXNzYWdlIHRvIGRpc2xpa2VcbiAgICovXG4gIG9uRGlzbGlrZShtZXNzYWdlOiBDaGF0TWVzc2FnZSwgcmFuazogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ3RodW1iLWRvd24uY2xpY2snLCB7cmFua30pO1xuICAgIHRoaXMubWVzc2FnZVJlbGF0ZWRJc3N1ZSA9IG1lc3NhZ2U7XG4gICAgdGhpcy5pc3N1ZVR5cGUgPSAnJztcbiAgICB0aGlzLmlzc3VlQ29tbWVudCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmlzc3VlUmFuayA9IHJhbms7XG4gICAgdGhpcy5zaG93UmVwb3J0SXNzdWUgPSB0cnVlXG4gIH1cblxuICAvKipcbiAgICogUmVwb3J0IGFuIGlzc3VlIHJlbGF0ZWQgdG8gdGhlIGFzc2lzdGFudCdzIG1lc3NhZ2UuXG4gICAqL1xuICBzZW5kSXNzdWUoKTogdm9pZCB7XG4gICAgY29uc3QgZGV0YWlscyA9IHtcbiAgICAgICdyZXBvcnQtdHlwZSc6IHRoaXMuaXNzdWVUeXBlLFxuICAgICAgJ2NvbW1lbnQnOiB0aGlzLmlzc3VlQ29tbWVudCxcbiAgICAgICd0ZXh0JzogdGhpcy5tZXNzYWdlUmVsYXRlZElzc3VlIS5jb250ZW50LFxuICAgICAgJ3JhbmsnOiB0aGlzLmlzc3VlUmFuayxcbiAgICB9O1xuICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVBdWRpdEV2ZW50KCduZWdhdGl2ZS1yZXBvcnQuc2VuZCcsIGRldGFpbHMpO1xuICAgIHRoaXMuc2hvd1JlcG9ydElzc3VlID0gZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogQ2xvc2UgdGhlIGlzc3VlIHJlcG9ydGluZyBkaWFsb2cuXG4gICAqL1xuICBpZ25vcmVJc3N1ZSgpOiB2b2lkIHtcbiAgICB0aGlzLnNob3dSZXBvcnRJc3N1ZSA9IGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZSB0aGUgY2xpY2sgb24gYSByZWZlcmVuY2UncyAnb3BlbiBwcmV2aWV3Jy5cbiAgICogQHBhcmFtIGRhdGFcbiAgICovXG4gIG9wZW5BdHRhY2htZW50UHJldmlldyhkYXRhOiB7cmVmZXJlbmNlOiBDaGF0Q29udGV4dEF0dGFjaG1lbnQsIHBhcnRJZD86IG51bWJlcn0pIHtcbiAgICB0aGlzLm9wZW5QcmV2aWV3LmVtaXQoZGF0YS5yZWZlcmVuY2UpO1xuICAgIGNvbnN0IGRldGFpbHMgPSB7XG4gICAgICAnZG9jLWlkJzogZGF0YS5yZWZlcmVuY2UucmVjb3JkSWQsXG4gICAgICAndGl0bGUnOiBkYXRhLnJlZmVyZW5jZS5yZWNvcmQudGl0bGUsXG4gICAgICAnc291cmNlJzogZGF0YS5yZWZlcmVuY2UucmVjb3JkLnRyZWVwYXRoLFxuICAgICAgJ2NvbGxlY3Rpb24nOiBkYXRhLnJlZmVyZW5jZS5yZWNvcmQuY29sbGVjdGlvbixcbiAgICAgICdpbmRleCc6IGRhdGEucmVmZXJlbmNlLnJlY29yZC5kYXRhYmFzZWFsaWFzLFxuICAgIH07XG4gICAgaWYoISFkYXRhLnBhcnRJZCkgZGV0YWlsc1sncGFydC1pZCddID0gZGF0YS5wYXJ0SWQ7XG4gICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ2F0dGFjaG1lbnQucHJldmlldy5jbGljaycsIGRldGFpbHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZSB0aGUgY2xpY2sgb24gYSByZWZlcmVuY2UncyAnb3BlbiBvcmlnaW5hbCBkb2N1bWVudCcuXG4gICAqIEBwYXJhbSBkYXRhXG4gICAqL1xuICBvcGVuT3JpZ2luYWxBdHRhY2htZW50KGRhdGE6IHtyZWZlcmVuY2U6IENoYXRDb250ZXh0QXR0YWNobWVudCwgcGFydElkPzogbnVtYmVyfSkge1xuICAgIHRoaXMub3BlbkRvY3VtZW50LmVtaXQoZGF0YS5yZWZlcmVuY2UucmVjb3JkKTtcbiAgICBjb25zdCBkZXRhaWxzID0ge1xuICAgICAgJ2RvYy1pZCc6IGRhdGEucmVmZXJlbmNlLnJlY29yZElkLFxuICAgICAgJ3RpdGxlJzogZGF0YS5yZWZlcmVuY2UucmVjb3JkLnRpdGxlLFxuICAgICAgJ3NvdXJjZSc6IGRhdGEucmVmZXJlbmNlLnJlY29yZC50cmVlcGF0aCxcbiAgICAgICdjb2xsZWN0aW9uJzogZGF0YS5yZWZlcmVuY2UucmVjb3JkLmNvbGxlY3Rpb24sXG4gICAgICAnaW5kZXgnOiBkYXRhLnJlZmVyZW5jZS5yZWNvcmQuZGF0YWJhc2VhbGlhcyxcbiAgICB9O1xuICAgIGlmKCEhZGF0YS5wYXJ0SWQpIGRldGFpbHNbJ3BhcnQtaWQnXSA9IGRhdGEucGFydElkO1xuICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVBdWRpdEV2ZW50KCdhdHRhY2htZW50LmxpbmsuY2xpY2snLCBkZXRhaWxzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGUgdGhlIGNsaWNrIG9uIGEgc3VnZ2VzdGVkIGFjdGlvbi5cbiAgICogQHBhcmFtIGFjdGlvbiBTdWdnZXN0ZWQgYWN0aW9uLlxuICAgKiBAcGFyYW0gaW5kZXggUmFuayBvZiB0aGUgbWVzc2FnZSBpbiB0aGUgY2hhdEhpc3RvcnkgcmVsYXRlZCB0byB0aGUgc3VnZ2VzdGVkIGFjdGlvbi5cbiAgICovXG4gIHN1Z2dlc3RBY3Rpb25DbGljayhhY3Rpb246IFN1Z2dlc3RlZEFjdGlvbiwgaW5kZXg6IG51bWJlcikge1xuICAgIHRoaXMuc3VnZ2VzdEFjdGlvbi5lbWl0KGFjdGlvbik7XG4gICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ3N1Z2dlc3RlZEFjdGlvbi5jbGljaycsIHsndGV4dCc6IGFjdGlvbi5jb250ZW50LCAnc3VnZ2VzdGVkQWN0aW9uLXR5cGUnOiBhY3Rpb24udHlwZX0pXG4gIH1cblxuICAvKipcbiAgICogSGFuZGxlIHRoZSBjbGljayBvbiB0aGUgJ3Nob3cgbG9nIGluZm8nIGJ1dHRvbiBvZiBhIG1lc3NhZ2UuXG4gICAqIEBwYXJhbSBtZXNzYWdlIFRoZSBtZXNzYWdlIG9mIHRoZSBDaGF0SGlzdG9yeSB0byBzaG93IGl0cyBkZWJ1ZyBtZXNzYWdlc1xuICAgKi9cbiAgc2hvd0RlYnVnKG1lc3NhZ2U6IENoYXRNZXNzYWdlKTogdm9pZCB7XG4gICAgdGhpcy5kZWJ1Z01lc3NhZ2VzID0gbWVzc2FnZS5hZGRpdGlvbmFsUHJvcGVydGllcy4kZGVidWc7XG4gICAgdGhpcy5zaG93RGVidWdNZXNzYWdlcyA9IHRydWU7XG4gICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpO1xuICB9XG59XG4iLCI8bmctY29udGFpbmVyICpuZ0lmPVwiIWluaXRpYWxpemF0aW9uRXJyb3JcIj5cbiAgPGRpdiAqbmdJZj1cIm1lc3NhZ2VzJCB8IGFzeW5jIGFzIG1lc3NhZ2VzOyBlbHNlIGxvYWRpbmdUcGwgfHwgbG9hZGluZ1RwbERlZmF1bHRcIiBjbGFzcz1cImgtMTAwIGQtZmxleCBmbGV4LWNvbHVtblwiPlxuICAgIDwhLS0gVG9rZW4gY29uc3VtcHRpb24gLS0+XG4gICAgPGRpdiBjbGFzcz1cIm1zLTFcIiAqbmdJZj1cImNvbmZpZz8uZ2xvYmFsU2V0dGluZ3M/LmRpc3BsYXlVc2VyUXVvdGFDb25zdW1wdGlvbiB8fCBjb25maWc/Lmdsb2JhbFNldHRpbmdzPy5kaXNwbGF5Q2hhdFRva2Vuc0NvbnN1bXB0aW9uXCI+XG4gICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwidG9rZW5Db25zdW1wdGlvblRwbCB8fCBkZWZhdWx0VG9rZW5Db25zdW1wdGlvblRwbDsgY29udGV4dDogeyAkaW1wbGljaXQ6IGluc3RhbmNlSWQgfVwiPjwvbmctY29udGFpbmVyPlxuICAgIDwvZGl2PlxuXG4gICAgPCEtLSBDaGF0IE1lc3NhZ2VzIC0tPlxuICAgIDx1bCBjbGFzcz1cImxpc3QtZ3JvdXAgbGlzdC1ncm91cC1mbHVzaCBvdmVyZmxvdy1hdXRvIGZsZXgtZ3Jvdy0xIHBlLTIgcGItMlwiICNtZXNzYWdlTGlzdD5cbiAgICAgIDxuZy1jb250YWluZXIgKm5nRm9yPVwibGV0IG1lc3NhZ2Ugb2YgbWVzc2FnZXM7IGxldCBpbmRleCA9IGluZGV4OyBsZXQgbGFzdCA9IGxhc3RcIj5cbiAgICAgICAgPCEtLSBSZWd1bGFyIG1lc3NhZ2VzIC0tPlxuICAgICAgICA8bGkgY2xhc3M9XCJsaXN0LWdyb3VwLWl0ZW1cIiBbc3R5bGUuLS1icy1saXN0LWdyb3VwLWl0ZW0tcGFkZGluZy15LnJlbV09XCInMC42J1wiICpuZ0lmPVwibWVzc2FnZS5hZGRpdGlvbmFsUHJvcGVydGllcy5kaXNwbGF5XCJcbiAgICAgICAgICBbY2xhc3Mub3BhY2l0eS01MF09XCJtZXNzYWdlVG9FZGl0ICYmIG1lc3NhZ2VUb0VkaXQgPCBpbmRleCArIDFcIj5cbiAgICAgICAgICA8c3EtY2hhdC1tZXNzYWdlXG4gICAgICAgICAgICBbY2xhc3Muc3EtdXNlci1tZXNzYWdlXT1cIm1lc3NhZ2Uucm9sZSA9PT0gJ3VzZXInXCJcbiAgICAgICAgICAgIFtjbGFzcy5sYXN0LW1lc3NhZ2VdPVwibGFzdFwiXG4gICAgICAgICAgICBbbWVzc2FnZV09XCJtZXNzYWdlXCJcbiAgICAgICAgICAgIFtjb252ZXJzYXRpb25dPVwibWVzc2FnZXNcIlxuICAgICAgICAgICAgW3N1Z2dlc3RlZEFjdGlvbnNdPVwibGFzdCA/IG1lc3NhZ2UuYWRkaXRpb25hbFByb3BlcnRpZXMuJHN1Z2dlc3RlZEFjdGlvbiA6IHVuZGVmaW5lZFwiXG4gICAgICAgICAgICBbYXNzaXN0YW50TWVzc2FnZUljb25dPVwiYXNzaXN0YW50TWVzc2FnZUljb25cIlxuICAgICAgICAgICAgW3VzZXJNZXNzYWdlSWNvbl09XCJ1c2VyTWVzc2FnZUljb25cIlxuICAgICAgICAgICAgW2Nvbm5lY3Rpb25FcnJvck1lc3NhZ2VJY29uXT1cImNvbm5lY3Rpb25FcnJvck1lc3NhZ2VJY29uXCJcbiAgICAgICAgICAgIFtzZWFyY2hXYXJuaW5nTWVzc2FnZUljb25dPVwic2VhcmNoV2FybmluZ01lc3NhZ2VJY29uXCJcbiAgICAgICAgICAgIFtzdHJlYW1pbmddPVwibGFzdCAmJiAoY2hhdFNlcnZpY2Uuc3RyZWFtaW5nJCB8IGFzeW5jKVwiXG4gICAgICAgICAgICBbY2FuRWRpdF09XCIobG9hZGluZyQgfCBhc3luYykgPT09IGZhbHNlICYmICgoY2hhdFNlcnZpY2Uuc3RyZWFtaW5nJCB8IGFzeW5jKSA9PT0gZmFsc2UgfHwgIWxhc3QpICYmIG1lc3NhZ2VUb0VkaXQgPT09IHVuZGVmaW5lZCAmJiBtZXNzYWdlLnJvbGUgPT09ICd1c2VyJ1wiXG4gICAgICAgICAgICBbY2FuUmVnZW5lcmF0ZV09XCIobG9hZGluZyQgfCBhc3luYykgPT09IGZhbHNlICYmIChjaGF0U2VydmljZS5zdHJlYW1pbmckIHwgYXN5bmMpID09PSBmYWxzZSAmJiBtZXNzYWdlVG9FZGl0ID09PSB1bmRlZmluZWQgJiYgbWVzc2FnZS5yb2xlID09PSAnYXNzaXN0YW50JyAmJiBsYXN0XCJcbiAgICAgICAgICAgIFtjYW5Db3B5XT1cIigoY2hhdFNlcnZpY2Uuc3RyZWFtaW5nJCB8IGFzeW5jKSA9PT0gZmFsc2UgfHwgIWxhc3QpICYmIG1lc3NhZ2VUb0VkaXQgPT09IHVuZGVmaW5lZCAmJiBtZXNzYWdlLnJvbGUgIT09ICdjb25uZWN0aW9uLWVycm9yJyAmJiBtZXNzYWdlLnJvbGUgIT09ICdzZWFyY2gtd2FybmluZydcIlxuICAgICAgICAgICAgW2NhbkRlYnVnXT1cIigoY2hhdFNlcnZpY2Uuc3RyZWFtaW5nJCB8IGFzeW5jKSA9PT0gZmFsc2UgfHwgIWxhc3QpICYmIG1lc3NhZ2Uucm9sZSA9PT0gJ2Fzc2lzdGFudCcgJiYgaXNBZG1pbiAmJiBtZXNzYWdlLmFkZGl0aW9uYWxQcm9wZXJ0aWVzLiRkZWJ1Z1wiXG4gICAgICAgICAgICBbY2FuTGlrZV09XCIoKGNoYXRTZXJ2aWNlLnN0cmVhbWluZyQgfCBhc3luYykgPT09IGZhbHNlIHx8ICFsYXN0KSAmJiBtZXNzYWdlLnJvbGUgPT09ICdhc3Npc3RhbnQnXCJcbiAgICAgICAgICAgIFtjYW5EaXNsaWtlXT1cIigoY2hhdFNlcnZpY2Uuc3RyZWFtaW5nJCB8IGFzeW5jKSA9PT0gZmFsc2UgfHwgIWxhc3QpICYmIG1lc3NhZ2Uucm9sZSA9PT0gJ2Fzc2lzdGFudCdcIlxuICAgICAgICAgICAgKGVkaXQpPVwiZWRpdE1lc3NhZ2UoaW5kZXgpXCJcbiAgICAgICAgICAgIChjb3B5KT1cImNvcHlNZXNzYWdlKGluZGV4KVwiXG4gICAgICAgICAgICAocmVnZW5lcmF0ZSk9XCJyZWdlbmVyYXRlTWVzc2FnZShpbmRleClcIlxuICAgICAgICAgICAgKG9wZW5Eb2N1bWVudCk9XCJvcGVuT3JpZ2luYWxBdHRhY2htZW50KCRldmVudClcIlxuICAgICAgICAgICAgKG9wZW5QcmV2aWV3KT1cIm9wZW5BdHRhY2htZW50UHJldmlldygkZXZlbnQpXCJcbiAgICAgICAgICAgIChzdWdnZXN0QWN0aW9uKT1cInN1Z2dlc3RBY3Rpb25DbGljaygkZXZlbnQsIGluZGV4KVwiXG4gICAgICAgICAgICAobGlrZSk9XCJvbkxpa2UoaW5kZXgpXCJcbiAgICAgICAgICAgIChkaXNsaWtlKT1cIm9uRGlzbGlrZSgkZXZlbnQsIGluZGV4KVwiXG4gICAgICAgICAgICAoZGVidWcpPVwic2hvd0RlYnVnKCRldmVudClcIj5cbiAgICAgICAgICA8L3NxLWNoYXQtbWVzc2FnZT5cbiAgICAgICAgPC9saT5cbiAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgPCEtLSBMb2FkaW5nIHNwaW5uZXIgLS0+XG4gICAgICA8bGkgY2xhc3M9XCJsaXN0LWdyb3VwLWl0ZW1cIiAqbmdJZj1cIihsb2FkaW5nJCB8IGFzeW5jKSA9PT0gdHJ1ZVwiPlxuICAgICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwibG9hZGluZ1RwbCB8fCBsb2FkaW5nVHBsRGVmYXVsdFwiPjwvbmctY29udGFpbmVyPlxuICAgICAgPC9saT5cbiAgICA8L3VsPlxuXG4gICAgPCEtLSBSZXBvcnRpbmcgYW4gaXNzdWUgZm9ybSAtLT5cbiAgICA8ZGl2IGNsYXNzPVwiaXNzdWUtcmVwb3J0IGJnLWxpZ2h0IHB0LTMgcGItMlwiICpuZ0lmPVwic2hvd1JlcG9ydElzc3VlXCI+XG4gICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwicmVwb3J0SXNzdWVUcGwgfHwgcmVwb3J0SXNzdWVUcGxEZWZhdWx0OyBjb250ZXh0OiB7ICRpbXBsaWNpdDogbWVzc2FnZVJlbGF0ZWRJc3N1ZSwgcmFuazogaXNzdWVSYW5rIH1cIj48L25nLWNvbnRhaW5lcj5cbiAgICA8L2Rpdj5cblxuICAgIDwhLS0gVXNlciB0ZXh0IGlucHV0IC0tPlxuICAgIDxkaXYgY2xhc3M9XCJ1c2VyLWlucHV0IG10LWF1dG9cIiAqbmdJZj1cIiFzaG93UmVwb3J0SXNzdWVcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJweS0yXCI+XG4gICAgICAgIDxkaXYgW2hpZGRlbl09XCIhaXNDb25uZWN0ZWRcIj5cbiAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiZW5hYmxlZFVzZXJJbnB1dFwiIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImlucHV0VHBsXCI+PC9uZy1jb250YWluZXI+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8IS0tIFJldHJ5IGJ1dHRvbiAtLT5cbiAgICAgICAgPGJ1dHRvbiBbaGlkZGVuXT1cImlzQ29ubmVjdGVkXCIgY2xhc3M9XCJidG4gbWItNCBhc3QtZXJyb3IgYXN0LWJ0biBzcS1yZXRyeVwiIChjbGljayk9XCJyZXRyeUZldGNoKClcIj5cbiAgICAgICAgICA8c3Bhbj5UcnkgYWdhaW48L3NwYW4+XG4gICAgICAgICAgPHNwYW4gKm5nSWY9XCJyZXRyaWFsQXR0ZW1wdHNcIiBjbGFzcz1cIm1zLTIgYXR0ZW1wdHNcIj57eyByZXRyaWFsQXR0ZW1wdHMgfX08L3NwYW4+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgICA8ZGl2IGNsYXNzPVwidGV4dC1lbmQgc21hbGwgdGV4dC1tdXRlZCBweC0zXCIgKm5nSWY9XCIhIWNvbmZpZz8uZ2xvYmFsU2V0dGluZ3M/LmRpc2NsYWltZXJcIj5cbiAgICAgICAgICB7eyBjb25maWc/Lmdsb2JhbFNldHRpbmdzPy5kaXNjbGFpbWVyIH19XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG5cbiAgICA8IS0tIEZsb2F0aW5nIHNjcm9sbCBidXR0b24gLS0+XG4gICAgPGRpdiAqbmdJZj1cIiFpc0F0Qm90dG9tICYmICFzaG93UmVwb3J0SXNzdWVcIiBjbGFzcz1cInNxLWZsb2F0aW5nLXNjcm9sbFwiIFtuZ0NsYXNzXT1cImVuYWJsZWRVc2VySW5wdXQgPyAnc3EtZmxvYXRpbmctc2Nyb2xsLS13aGVuLXVzZXItaW5wdXQnIDogJ3NxLWZsb2F0aW5nLXNjcm9sbC0td2l0aG91dC11c2VyLWlucHV0J1wiPlxuICAgICAgPGJ1dHRvbiBjbGFzcz1cImJ0biBzaGFkb3dcIiAoY2xpY2spPVwic2Nyb2xsRG93bigpXCI+XG4gICAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLWFuZ2xlLWRvdWJsZS1kb3duXCI+PC9pPlxuICAgICAgPC9idXR0b24+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuPC9uZy1jb250YWluZXI+XG5cbjwhLS0gTkcgVEVNUExBVEVTLS0+XG5cbjxuZy10ZW1wbGF0ZSAjbG9hZGluZ1RwbERlZmF1bHQ+XG4gIDxkaXYgY2xhc3M9XCJzcGlubmVyLWdyb3cgdGV4dC1wcmltYXJ5IGQtYmxvY2sgbXgtYXV0byBteS01XCIgcm9sZT1cInN0YXR1c1wiPlxuICAgIDxzcGFuIGNsYXNzPVwidmlzdWFsbHktaGlkZGVuXCI+TG9hZGluZy4uLjwvc3Bhbj5cbiAgPC9kaXY+XG48L25nLXRlbXBsYXRlPlxuXG48bmctdGVtcGxhdGUgI2lucHV0VHBsPlxuICA8ZGl2IGNsYXNzPVwicHgtMyBweS0xXCI+XG4gICAgPGRpdiBjbGFzcz1cImFzdC1pbnB1dC1jb250YWluZXJcIj5cbiAgICAgIDxidXR0b24gZGlzYWJsZWQgY2xhc3M9XCJidG4gYnRuLWxpZ2h0XCI+XG4gICAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLXNlYXJjaFwiPjwvaT5cbiAgICAgIDwvYnV0dG9uPlxuICAgICAgPHRleHRhcmVhICNxdWVzdGlvbklucHV0IHJvd3M9XCIxXCJcbiAgICAgICAgdHlwZT1cInRleHRcIiBjbGFzcz1cImZvcm0tY29udHJvbFwiXG4gICAgICAgIHBsYWNlaG9sZGVyPVwiQXNrIHNvbWV0aGluZ1wiIGF1dG9mb2N1c1xuICAgICAgICBbKG5nTW9kZWwpXT1cInF1ZXN0aW9uXCJcbiAgICAgICAgKGtleXVwKT1cIm9uS2V5VXAoJGV2ZW50KVwiXG4gICAgICAgIChrZXlkb3duKT1cImNhbGN1bGF0ZUhlaWdodCgkZXZlbnQpXCJcbiAgICAgICAgW2Rpc2FibGVkXT1cIihsb2FkaW5nJCB8IGFzeW5jKSB8fCAoY2hhdFNlcnZpY2Uuc3RyZWFtaW5nJCB8IGFzeW5jKVwiPlxuICAgICAgPC90ZXh0YXJlYT5cbiAgICAgIDxidXR0b25cbiAgICAgICAgKm5nSWY9XCIhKGNoYXRTZXJ2aWNlLnN0cmVhbWluZyQgfCBhc3luYykgJiYgIShsb2FkaW5nJCB8IGFzeW5jKVwiXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICBjbGFzcz1cImJ0biBidG4tbGlnaHQgbXMtMlwiXG4gICAgICAgIHRpdGxlPVwiU2VuZCBtZXNzYWdlXCJcbiAgICAgICAgKGNsaWNrKT1cInN1Ym1pdFF1ZXN0aW9uKClcIj5cbiAgICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtcGFwZXItcGxhbmVcIj48L2k+XG4gICAgICA8L2J1dHRvbj5cbiAgICAgIDwhLS08YnV0dG9uXG4gICAgICAgICpuZ0lmPVwiKGNoYXRTZXJ2aWNlLnN0cmVhbWluZyQgfCBhc3luYylcIlxuICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgY2xhc3M9XCJidG4gYnRuLWxpZ2h0IG1zLTJcIlxuICAgICAgICB0aXRsZT1cIlN0b3AgZ2VuZXJhdGluZ1wiXG4gICAgICAgIChjbGljayk9XCJ0ZXJtaW5hdGVGZXRjaCgpXCI+XG4gICAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLXN0b3BcIj48L2k+XG4gICAgICA8L2J1dHRvbj4tLT5cbiAgICAgIDxidXR0b25cbiAgICAgICAgKm5nSWY9XCJtZXNzYWdlVG9FZGl0XCJcbiAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1saWdodCBtcy0yXCJcbiAgICAgICAgdGl0bGU9XCJDYW5jZWwgZWRpdGlvblwiXG4gICAgICAgIChjbGljayk9XCJtZXNzYWdlVG9FZGl0ID0gdW5kZWZpbmVkOyBxdWVzdGlvbiA9ICcnXCI+XG4gICAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLXVuZG8tYWx0XCI+PC9pPlxuICAgICAgPC9idXR0b24+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuPC9uZy10ZW1wbGF0ZT5cblxuPG5nLXRlbXBsYXRlICNyZXBvcnRJc3N1ZVRwbERlZmF1bHQgbGV0LW1lc3NhZ2UgbGV0LXJhbms9XCJyYW5rXCI+XG4gIDxkaXYgY2xhc3M9XCJweC0zXCI+XG4gICAgPGg1Pklzc3VlIHR5cGU8L2g1PlxuICAgIDxzZWxlY3QgY2xhc3M9XCJmb3JtLXNlbGVjdCBtYi00XCIgWyhuZ01vZGVsKV09XCJpc3N1ZVR5cGVcIj5cbiAgICAgIDxvcHRpb24gW3ZhbHVlXT1cIicnXCI+Q2hvb3NlIGFuIGlzc3VlIHR5cGU8L29wdGlvbj5cbiAgICAgIDxvcHRpb24gKm5nRm9yPVwibGV0IHR5cGUgb2YgKGlzc3VlVHlwZXMgPz8gZGVmYXVsdElzc3VlVHlwZXMpXCI+e3t0eXBlfX08L29wdGlvbj5cbiAgICA8L3NlbGVjdD5cbiAgICA8aDU+Q29tbWVudCAob3B0aW9uYWwpPC9oNT5cbiAgICA8dGV4dGFyZWEgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIiBbKG5nTW9kZWwpXT1cImlzc3VlQ29tbWVudFwiIHBsYWNlaG9sZGVyPVwiV2hhdCB3YXMgdW5zYXRpc2Z5aW5nIGFib3V0IHRoaXMgcmVzcG9uc2U/XCI+PC90ZXh0YXJlYT5cbiAgICA8ZGl2IGNsYXNzPVwiZC1mbGV4IGZsZXgtcm93LXJldmVyc2UgbXQtMlwiPlxuICAgICAgPGJ1dHRvbiBjbGFzcz1cImJ0biBidG4tcHJpbWFyeVwiIFtkaXNhYmxlZF09XCIhaXNzdWVUeXBlXCIgKGNsaWNrKT1cInNlbmRJc3N1ZSgpXCI+U2VuZDwvYnV0dG9uPlxuICAgICAgPGJ1dHRvbiBjbGFzcz1cImJ0biBidG4tbGlnaHRcIiAoY2xpY2spPVwiaWdub3JlSXNzdWUoKVwiPkNhbmNlbDwvYnV0dG9uPlxuICAgIDwvZGl2PlxuICA8L2Rpdj5cbjwvbmctdGVtcGxhdGU+XG5cbjxuZy10ZW1wbGF0ZSAjZGVmYXVsdFRva2VuQ29uc3VtcHRpb25UcGwgbGV0LWluc3RhbmNlSWQ+XG4gIDxzcS10b2tlbi1wcm9ncmVzcy1iYXJcbiAgICBbaW5zdGFuY2VJZF09XCJpbnN0YW5jZUlkXCI+XG4gIDwvc3EtdG9rZW4tcHJvZ3Jlc3MtYmFyPlxuPC9uZy10ZW1wbGF0ZT5cblxuPGRpdiBjbGFzcz1cImRlYnVnLW1lc3NhZ2VzXCIgW2NsYXNzLmRpc3BsYXllZF09XCJzaG93RGVidWdNZXNzYWdlc1wiPlxuICA8YnV0dG9uICpuZ0lmPVwic2hvd0RlYnVnTWVzc2FnZXNcIiBjbGFzcz1cImJ0biBidG4tbGlnaHQgc2hhZG93IGJhY2stYnRuXCIgKGNsaWNrKT1cInNob3dEZWJ1Z01lc3NhZ2VzPWZhbHNlXCI+XG4gICAgPGkgY2xhc3M9XCJmYXMgZmEtY2hldnJvbi1yaWdodFwiPjwvaT5cbiAgPC9idXR0b24+XG4gIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJkZWJ1Z01lc3NhZ2VzVHBsIHx8IGRlZmF1bHREZWJ1Z01lc3NhZ2VzVHBsOyBjb250ZXh0OiB7ICRpbXBsaWNpdDogZGVidWdNZXNzYWdlcyB9XCI+XG4gIDwvbmctY29udGFpbmVyPlxuPC9kaXY+XG5cbjxuZy10ZW1wbGF0ZSAjZGVmYXVsdERlYnVnTWVzc2FnZXNUcGwgbGV0LWRlYnVnTWVzc2FnZXM+XG4gIDxzcS1kZWJ1Zy1tZXNzYWdlIFtkYXRhXT1cImRlYnVnTWVzc2FnZXNcIj48L3NxLWRlYnVnLW1lc3NhZ2U+XG48L25nLXRlbXBsYXRlPlxuIl19
987
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhdC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9hc3Npc3RhbnQvY2hhdC9jaGF0LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uL3Byb2plY3RzL2Fzc2lzdGFudC9jaGF0L2NoYXQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSx1QkFBdUIsRUFBRSxpQkFBaUIsRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFjLFlBQVksRUFBRSxLQUFLLEVBQWdDLE1BQU0sRUFBOEIsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzFOLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDMUQsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQzNELE9BQU8sRUFBRSxVQUFVLEVBQVMsTUFBTSx5QkFBeUIsQ0FBQztBQUM1RCxPQUFPLEVBQUUsbUJBQW1CLEVBQXFCLE1BQU0sNEJBQTRCLENBQUM7QUFDcEYsT0FBTyxFQUFFLGVBQWUsRUFBRSxZQUFZLEVBQUUsYUFBYSxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUN6SCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFN0MsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDcEUsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDaEUsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sdUNBQXVDLENBQUM7QUFDN0UsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFD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O2dCQU9HLDhCQUE4QjtzQkFBdEMsS0FBSztnQkFFRyxRQUFRO3NCQUFoQixLQUFLO2dCQUVHLGVBQWU7c0JBQXZCLEtBQUs7Z0JBRUcsNkJBQTZCO3NCQUFyQyxLQUFLO2dCQUVHLGtCQUFrQjtzQkFBMUIsS0FBSztnQkFFRyxJQUFJO3NCQUFaLEtBQUs7Z0JBRUcsb0JBQW9CO3NCQUE1QixLQUFLO2dCQUVHLGVBQWU7c0JBQXZCLEtBQUs7Z0JBRUcsMEJBQTBCO3NCQUFsQyxLQUFLO2dCQUVHLHdCQUF3QjtzQkFBaEMsS0FBSztnQkFFSSxVQUFVO3NCQUFuQixNQUFNO2dCQUdZLFFBQVE7c0JBQTFCLE1BQU07dUJBQUMsU0FBUztnQkFFQyxPQUFPO3NCQUF4QixNQUFNO3VCQUFDLFFBQVE7Z0JBQ04sSUFBSTtzQkFBYixNQUFNO2dCQUVHLFlBQVk7c0JBQXJCLE1BQU07Z0JBRUcsV0FBVztzQkFBcEIsTUFBTTtnQkFFRyxhQUFhO3NCQUF0QixNQUFNO2dCQUVHLFdBQVc7c0JBQXBCLE1BQU07Z0JBRW1CLFdBQVc7c0JBQXBDLFNBQVM7dUJBQUMsYUFBYTtnQkFDSSxhQUFhO3NCQUF4QyxTQUFTO3VCQUFDLGVBQWU7Z0JBRUUsVUFBVTtzQkFBckMsWUFBWTt1QkFBQyxZQUFZO2dCQUNDLFNBQVM7c0JBQW5DLFlBQVk7dUJBQUMsV0FBVztnQkFDWSxtQkFBbUI7c0JBQXZELFlBQVk7dUJBQUMscUJBQXFCO2dCQUNELGdCQUFnQjtzQkFBakQsWUFBWTt1QkFBQyxrQkFBa0IiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBpbmplY3QsIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDaGFuZ2VEZXRlY3RvclJlZiwgQ29tcG9uZW50LCBDb250ZW50Q2hpbGQsIEVsZW1lbnRSZWYsIEV2ZW50RW1pdHRlciwgSW5wdXQsIE9uQ2hhbmdlcywgT25EZXN0cm95LCBPbkluaXQsIE91dHB1dCwgU2ltcGxlQ2hhbmdlcywgVGVtcGxhdGVSZWYsIFZpZXdDaGlsZCB9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgeyBBY3Rpb24gfSBmcm9tIFwiQHNpbmVxdWEvY29tcG9uZW50cy9hY3Rpb25cIjtcbmltcG9ydCB7IEFic3RyYWN0RmFjZXQgfSBmcm9tIFwiQHNpbmVxdWEvY29tcG9uZW50cy9mYWNldFwiO1xuaW1wb3J0IHsgU2VhcmNoU2VydmljZSB9IGZyb20gXCJAc2luZXF1YS9jb21wb25lbnRzL3NlYXJjaFwiO1xuaW1wb3J0IHsgQXBwU2VydmljZSwgUXVlcnkgfSBmcm9tIFwiQHNpbmVxdWEvY29yZS9hcHAtdXRpbHNcIjtcbmltcG9ydCB7IFByaW5jaXBhbFdlYlNlcnZpY2UsIFJlY29yZCBhcyBBcnRpY2xlIH0gZnJvbSBcIkBzaW5lcXVhL2NvcmUvd2ViLXNlcnZpY2VzXCI7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIFN1YnNjcmlwdGlvbiwgY29tYmluZUxhdGVzdCwgZmlsdGVyLCBmcm9tRXZlbnQsIG1hcCwgbWVyZ2UsIHN3aXRjaE1hcCwgdGFrZSwgdGFwIH0gZnJvbSBcInJ4anNcIjtcbmltcG9ydCB7IENoYXRTZXJ2aWNlIH0gZnJvbSBcIi4vY2hhdC5zZXJ2aWNlXCI7XG5pbXBvcnQgeyBDaGF0Q29udGV4dEF0dGFjaG1lbnQsIENoYXRDb25maWcsIENoYXRNZXNzYWdlLCBHbGxtTW9kZWxEZXNjcmlwdGlvbiwgTWVzc2FnZUhhbmRsZXIsIFJhd01lc3NhZ2UsIFN1Z2dlc3RlZEFjdGlvbiwgSW5pdENoYXQsIERlYnVnTWVzc2FnZSwgQ2hhdFN0YXJ0ZXIgfSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHsgSW5zdGFuY2VNYW5hZ2VyU2VydmljZSB9IGZyb20gXCIuL2luc3RhbmNlLW1hbmFnZXIuc2VydmljZVwiO1xuaW1wb3J0IHsgV2ViU29ja2V0Q2hhdFNlcnZpY2UgfSBmcm9tIFwiLi93ZWJzb2NrZXQtY2hhdC5zZXJ2aWNlXCI7XG5pbXBvcnQgeyBDaGF0TWVzc2FnZUNvbXBvbmVudCB9IGZyb20gXCIuL2NoYXQtbWVzc2FnZS9jaGF0LW1lc3NhZ2UuY29tcG9uZW50XCI7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tIFwiQGFuZ3VsYXIvY29tbW9uXCI7XG5pbXBvcnQgeyBGb3Jtc01vZHVsZSB9IGZyb20gXCJAYW5ndWxhci9mb3Jtc1wiO1xuaW1wb3J0IHsgTG9naW5TZXJ2aWNlIH0gZnJvbSBcIkBzaW5lcXVhL2NvcmUvbG9naW5cIjtcbmltcG9ydCB7IFJlc3RDaGF0U2VydmljZSB9IGZyb20gXCIuL3Jlc3QtY2hhdC5zZXJ2aWNlXCI7XG5pbXBvcnQgeyBUb2tlblByb2dyZXNzQmFyQ29tcG9uZW50IH0gZnJvbSBcIi4vdG9rZW4tcHJvZ3Jlc3MtYmFyL3Rva2VuLXByb2dyZXNzLWJhci5jb21wb25lbnRcIjtcbmltcG9ydCB7IERlYnVnTWVzc2FnZUNvbXBvbmVudCB9IGZyb20gXCIuL2RlYnVnLW1lc3NhZ2UvZGVidWctbWVzc2FnZS5jb21wb25lbnRcIjtcbmltcG9ydCB7IEh1YkNvbm5lY3Rpb24sIEh1YkNvbm5lY3Rpb25TdGF0ZSAgfSBmcm9tIFwiQG1pY3Jvc29mdC9zaWduYWxyXCI7XG5pbXBvcnQgeyBVdGlsc01vZHVsZSB9IGZyb20gXCJAc2luZXF1YS9jb21wb25lbnRzL3V0aWxzXCI7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3NxLWNoYXQtdjMnLCAvLyBtYW5kYXRvcnkgc2luY2UgQHNpbmVxdWEvY29tcG9uZW50cyBhbHJlYWR5IGhhcyB0aGUgc2FtZSB0YWctbmFtZSBcInNxLWNoYXRcIlxuICB0ZW1wbGF0ZVVybDogJy4vY2hhdC5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL2NoYXQuY29tcG9uZW50LnNjc3MnXSxcbiAgcHJvdmlkZXJzOiBbXG4gICAgUmVzdENoYXRTZXJ2aWNlLFxuICAgIFdlYlNvY2tldENoYXRTZXJ2aWNlXG4gIF0sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlLCBGb3Jtc01vZHVsZSwgQ2hhdE1lc3NhZ2VDb21wb25lbnQsIFRva2VuUHJvZ3Jlc3NCYXJDb21wb25lbnQsIERlYnVnTWVzc2FnZUNvbXBvbmVudCwgVXRpbHNNb2R1bGVdXG59KVxuZXhwb3J0IGNsYXNzIENoYXRDb21wb25lbnQgZXh0ZW5kcyBBYnN0cmFjdEZhY2V0IGltcGxlbWVudHMgT25Jbml0LCBPbkNoYW5nZXMsIE9uRGVzdHJveSB7XG5cbiAgcHVibGljIGxvZ2luU2VydmljZSA9IGluamVjdChMb2dpblNlcnZpY2UpO1xuICBwdWJsaWMgd2Vic29ja2V0U2VydmljZSA9IGluamVjdChXZWJTb2NrZXRDaGF0U2VydmljZSk7XG4gIHB1YmxpYyByZXN0U2VydmljZSA9IGluamVjdChSZXN0Q2hhdFNlcnZpY2UpO1xuICBwdWJsaWMgaW5zdGFuY2VNYW5hZ2VyU2VydmljZSA9IGluamVjdChJbnN0YW5jZU1hbmFnZXJTZXJ2aWNlKTtcbiAgcHVibGljIHNlYXJjaFNlcnZpY2UgPSBpbmplY3QoU2VhcmNoU2VydmljZSk7XG4gIHB1YmxpYyBwcmluY2lwYWxTZXJ2aWNlID0gaW5qZWN0KFByaW5jaXBhbFdlYlNlcnZpY2UpO1xuICBwdWJsaWMgY2RyID0gaW5qZWN0KENoYW5nZURldGVjdG9yUmVmKTtcbiAgcHVibGljIGFwcFNlcnZpY2UgPSBpbmplY3QoQXBwU2VydmljZSk7XG5cbiAgLyoqIERlZmluZSB0aGUga2V5IGJhc2VkIG9uIGl0LCB0aGUgY2hhdCBzZXJ2aWNlIGluc3RhbmNlIHdpbGwgYmUgc3RvcmVkICovXG4gIEBJbnB1dCgpIGluc3RhbmNlSWQ6IHN0cmluZztcbiAgLyoqIERlZmluZSB0aGUgcXVlcnkgdG8gdXNlIHRvIGZldGNoIGFuc3dlcnMgKi9cbiAgQElucHV0KCkgcXVlcnk6IFF1ZXJ5ID0gdGhpcy5zZWFyY2hTZXJ2aWNlLnF1ZXJ5O1xuICAvKiogRnVuY3Rpb24gdGhhdCBkZXRlcm1pbmVzIHdoZXRoZXIgdGhlIGNoYXQgc2hvdWxkIGJlIHJlbG9hZGVkIGFmdGVyIHRoZSBxdWVyeSBjaGFuZ2VzXG4gICAqIElmIG5vdCBwcm92aWRlZCwgdGhlIGNoYXQgd2lsbCBiZSByZWxvYWRlZCBieSBkZWZhdWx0XG4gICAqIEBwYXJhbSBwcmV2UXVlcnkgVGhlIHByZXZpb3VzIHF1ZXJ5XG4gICAqIEBwYXJhbSBuZXdRdWVyeSBUaGUgbmV3IHF1ZXJ5XG4gICAqIEByZXR1cm5zIHRydWUgaWYgdGhlIGNoYXQgc2hvdWxkIGJlIHJlbG9hZGVkLCBmYWxzZSBvdGhlcndpc2VcbiAgICovXG4gIEBJbnB1dCgpIHF1ZXJ5Q2hhbmdlU2hvdWxkVHJpZ2dlclJlbG9hZDogKHByZXZRdWVyeTogUXVlcnksIG5ld1F1ZXJ5OiBRdWVyeSkgPT4gYm9vbGVhbjtcbiAgLyoqIERlZmluZSB0aGUgcHJvdG9jb2wgdG8gYmUgdXNlZCBmb3IgdGhpcyBjaGF0IGluc3RhbmNlKi9cbiAgQElucHV0KCkgcHJvdG9jb2w6ICdSRVNUJyB8ICdXRUJTT0NLRVQnID0gXCJXRUJTT0NLRVRcIjtcbiAgLyoqIE1hcCBvZiBsaXN0ZW5lcnMgb3ZlcnJpZGluZyBkZWZhdWx0IHJlZ2lzdGVyZWQgb25lcyovXG4gIEBJbnB1dCgpIG1lc3NhZ2VIYW5kbGVyczogTWFwPHN0cmluZywgTWVzc2FnZUhhbmRsZXI8YW55Pj4gPSBuZXcgTWFwKCk7XG4gIC8qKiBXaGVuIHRoZSBhc3Npc3RhbnQgYW5zd2VyIGEgdXNlciBxdWVzdGlvbiwgYXV0b21hdGljYWxseSBzY3JvbGwgZG93biB0byB0aGUgYm90dG9tIG9mIHRoZSBkaXNjdXNzaW9uICovXG4gIEBJbnB1dCgpIGF1dG9tYXRpY1Njcm9sbFRvTGFzdFJlc3BvbnNlID0gZmFsc2U7XG4gIC8qKiBXaGVuIHRoZSBhc3Npc3RhbnQgYW5zd2VyIGEgdXNlciBxdWVzdGlvbiwgYXV0b21hdGljYWxseSBmb2N1cyB0byB0aGUgY2hhdCBpbnB1dCAqL1xuICBASW5wdXQoKSBmb2N1c0FmdGVyUmVzcG9uc2UgPSBmYWxzZTtcbiAgLyoqIEEgY2hhdCBkaXNjdXNzaW9uIHRoYXQgdGhlIGNvbXBvbmVudCBzaG91bGQgZ2V0IGluaXRpYWxpemVkIHdpdGggaXQgKi9cbiAgQElucHV0KCkgY2hhdD86IEluaXRDaGF0O1xuICAvKiogSWNvbiB0byB1c2UgZm9yIHRoZSBhc3Npc3RhbnQgbWVzc2FnZXMgKi9cbiAgQElucHV0KCkgYXNzaXN0YW50TWVzc2FnZUljb24gPSAnc3Etc2luZXF1YSc7XG4gIC8qKiBJY29uIHRvIHVzZSBmb3IgdGhlIHVzZXIgbWVzc2FnZXMgKi9cbiAgQElucHV0KCkgdXNlck1lc3NhZ2VJY29uOiBzdHJpbmc7XG4gIC8qKiBJY29uIHRvIHVzZSBmb3IgdGhlIGNvbm5lY3Rpb24gZXJyb3IgbWVzc2FnZXMgKi9cbiAgQElucHV0KCkgY29ubmVjdGlvbkVycm9yTWVzc2FnZUljb246IHN0cmluZztcbiAgLyoqIEljb24gdG8gdXNlIGZvciB0aGUgc2VhcmNoIHdhcm5pbmcgbWVzc2FnZXMgKi9cbiAgQElucHV0KCkgc2VhcmNoV2FybmluZ01lc3NhZ2VJY29uOiBzdHJpbmc7XG4gIC8qKiBFdmVudCBlbWl0dGVyIHRyaWdnZXJlZCBvbmNlIHRoZSBzaWduYWxSIGNvbm5lY3Rpb24gaXMgZXN0YWJsaXNoZWQgICovXG4gIEBPdXRwdXQoKSBjb25uZWN0aW9uID0gbmV3IEV2ZW50RW1pdHRlcjxIdWJDb25uZWN0aW9uPigpO1xuICAvKiogRXZlbnQgZW1pdHRlciB0cmlnZ2VyZWQgZWFjaCB0aW1lIHRoZSBhc3Npc3RhbnQgdXBkYXRlcyB0aGUgY3VycmVudCBjaGF0ICovXG4gIC8qKiBFdmVudCBlbWl0dGVyIHRyaWdnZXJlZCB3aGVuIHRoZSBjaGF0IGlzIGxvYWRpbmcgbmV3IGNvbnRlbnQgKi9cbiAgQE91dHB1dChcImxvYWRpbmdcIikgbG9hZGluZyQgPSBuZXcgRXZlbnRFbWl0dGVyPGJvb2xlYW4+KGZhbHNlKTtcbiAgLyoqIEVtaXRzIHRoZSBhc3Npc3RhbnQgY29uZmlndXJhdGlvbiB1c2VkIHdoZW4gaW5zdGFudGlhdGluZyB0aGUgY29tcG9uZW50ICovXG4gIEBPdXRwdXQoXCJjb25maWdcIikgX2NvbmZpZyA9IG5ldyBFdmVudEVtaXR0ZXI8Q2hhdENvbmZpZz4oKTtcbiAgQE91dHB1dCgpIGRhdGEgPSBuZXcgRXZlbnRFbWl0dGVyPENoYXRNZXNzYWdlW10+KCk7XG4gIC8qKiBFdmVudCBlbWl0dGVyIHRyaWdnZXJlZCB3aGVuIHRoZSB1c2VyIGNsaWNrcyB0byBvcGVuIHRoZSBvcmlnaW5hbCBkb2N1bWVudCByZXByZXNlbnRpbmcgdGhlIGNvbnRleHQgYXR0YWNobWVudCovXG4gIEBPdXRwdXQoKSBvcGVuRG9jdW1lbnQgPSBuZXcgRXZlbnRFbWl0dGVyPEFydGljbGU+KCk7XG4gIC8qKiBFdmVudCBlbWl0dGVyIHRyaWdnZXJlZCB3aGVuIHRoZSB1c2VyIGNsaWNrcyB0byBvcGVuIHRoZSBwcmV2aWV3IG9mIGEgZG9jdW1lbnQgcmVwcmVzZW50aW5nIHRoZSBjb250ZXh0IGF0dGFjaG1lbnQgKi9cbiAgQE91dHB1dCgpIG9wZW5QcmV2aWV3ID0gbmV3IEV2ZW50RW1pdHRlcjxDaGF0Q29udGV4dEF0dGFjaG1lbnQ+KCk7XG4gIC8qKiBFdmVudCBlbWl0dGVyIHRyaWdnZXJlZCB3aGVuIHRoZSB1c2VyIGNsaWNrcyBvbiBhIHN1Z2dlc3RlZCBhY3Rpb24gKi9cbiAgQE91dHB1dCgpIHN1Z2dlc3RBY3Rpb24gPSBuZXcgRXZlbnRFbWl0dGVyPFN1Z2dlc3RlZEFjdGlvbj4oKTtcbiAgLyoqIEV2ZW50IGVtaXR0ZXIgdHJpZ2dlcmVkIHdoZW4gdGhlIHVzZXIgY2xpY2tzIG9uIGEgY2hhdCBzdGFydGVyICovXG4gIEBPdXRwdXQoKSBjaGF0U3RhcnRlciA9IG5ldyBFdmVudEVtaXR0ZXI8Q2hhdFN0YXJ0ZXI+KCk7XG4gIC8qKiBWaWV3Q2hpbGQgZGVjb3JhdG9ycyB0byBhY2Nlc3MgdGhlIHRlbXBsYXRlIGVsZW1lbnRzICovXG4gIEBWaWV3Q2hpbGQoJ21lc3NhZ2VMaXN0JykgbWVzc2FnZUxpc3Q/OiBFbGVtZW50UmVmPEhUTUxVTGlzdEVsZW1lbnQ+O1xuICBAVmlld0NoaWxkKCdxdWVzdGlvbklucHV0JykgcXVlc3Rpb25JbnB1dD86IEVsZW1lbnRSZWY8SFRNTFRleHRBcmVhRWxlbWVudD47XG4gIC8qKiBDb250ZW50Q2hpbGQgZGVjb3JhdG9ycyBhbGxvd2luZyB0aGUgb3ZlcnJpZGUgb2YgdGhlIGRlZmF1bHQgdGVtcGxhdGVzIGZyb20gdGhlIHBhcmVudCBjb21wb25lbnQgKi9cbiAgQENvbnRlbnRDaGlsZCgnbG9hZGluZ1RwbCcpIGxvYWRpbmdUcGw/OiBUZW1wbGF0ZVJlZjxhbnk+O1xuICBAQ29udGVudENoaWxkKCdyZXBvcnRUcGwnKSByZXBvcnRUcGw/OiBUZW1wbGF0ZVJlZjxhbnk+O1xuICBAQ29udGVudENoaWxkKCd0b2tlbkNvbnN1bXB0aW9uVHBsJykgdG9rZW5Db25zdW1wdGlvblRwbD86IFRlbXBsYXRlUmVmPGFueT47XG4gIEBDb250ZW50Q2hpbGQoJ2RlYnVnTWVzc2FnZXNUcGwnKSBkZWJ1Z01lc3NhZ2VzVHBsPzogVGVtcGxhdGVSZWY8YW55PjtcblxuICBjaGF0U2VydmljZTogQ2hhdFNlcnZpY2U7XG4gIGNvbmZpZzogQ2hhdENvbmZpZztcbiAgbWVzc2FnZXMkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxDaGF0TWVzc2FnZVtdIHwgdW5kZWZpbmVkPih1bmRlZmluZWQpO1xuXG4gIHF1ZXN0aW9uID0gJyc7XG5cbiAgX2FjdGlvbnM6IEFjdGlvbltdID0gW107XG4gIHByaXZhdGUgX3Jlc2V0Q2hhdEFjdGlvbiA9IG5ldyBBY3Rpb24oe1xuICAgIGljb246ICdmYXMgZmEtc3luYycsXG4gICAgdGl0bGU6IFwiUmVzZXQgYXNzaXN0YW50XCIsXG4gICAgYWN0aW9uOiAoKSA9PiB0aGlzLm5ld0NoYXQoKVxuICB9KTtcblxuICBwcml2YXRlIF9zdWIgPSBuZXcgU3Vic2NyaXB0aW9uKCk7XG4gIHByaXZhdGUgX2RhdGFTdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbiB8IHVuZGVmaW5lZDtcblxuICAvKiogVmFyaWFibGVzIHRoYXQgZGVwZW5kIG9uIHRoZSB0eXBlIG9mIG1vZGVsIGluIHVzZSAqL1xuICBtb2RlbERlc2NyaXB0aW9uPzogR2xsbU1vZGVsRGVzY3JpcHRpb247XG5cbiAgbWVzc2FnZVRvRWRpdD86IG51bWJlcjtcbiAgcmVtYXBwZWRNZXNzYWdlVG9FZGl0PzogbnVtYmVyO1xuICBjaGFuZ2VzJCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8U2ltcGxlQ2hhbmdlcyB8IHVuZGVmaW5lZD4odW5kZWZpbmVkKTtcbiAgY3VycmVudE1lc3NhZ2VJbmRleDogbnVtYmVyIHwgdW5kZWZpbmVkO1xuICBmaXJzdENoYW5nZXNIYW5kbGVkID0gZmFsc2U7XG4gIGlzQXRCb3R0b20gPSB0cnVlO1xuICBpbml0aWFsaXphdGlvbkVycm9yID0gZmFsc2U7XG4gIGVuYWJsZWRVc2VySW5wdXQgPSBmYWxzZTtcbiAgaXNDb25uZWN0ZWQgPSB0cnVlOyAvLyBCeSBkZWZhdWx0LCB0aGUgY2hhdCBpcyBjb25zaWRlcmVkIGNvbm5lY3RlZFxuICByZXRyaWFsQXR0ZW1wdHM6IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgLy8gRmxhZyB0byB0cmFjayB3aGV0aGVyIHRoZSAncmVjb25uZWN0ZWQnIGxpc3RlbmVyIGlzIGFscmVhZHkgcmVnaXN0ZXJlZFxuICBwcml2YXRlIF9pc1JlY29ubmVjdGVkTGlzdGVuZXJSZWdpc3RlcmVkID0gZmFsc2U7XG5cbiAgLy8gSXNzdWUgcmVwb3J0aW5nXG4gIGlzc3VlVHlwZXM/OiBzdHJpbmdbXTtcbiAgZGVmYXVsdElzc3VlVHlwZXM6IHN0cmluZ1tdID0gW1xuICAgICdVc2VyIEludGVyZmFjZSBidWcnLFxuICAgICdJbmNvcnJlY3Qgb3IgbWlzbGVhZGluZyByZXNwb25zZScsXG4gICAgJ0luY29tcGxldGUgcmVzcG9uc2UnLFxuICAgICdUZWNobmljYWwgaXNzdWUnLFxuICAgICdQcml2YWN5L2RhdGEgc2VjdXJpdHkgaXNzdWUnLFxuICAgICdPdGhlcidcbiAgXTtcbiAgaXNzdWVUeXBlOiBzdHJpbmcgPSAnJztcbiAgcmVwb3J0Q29tbWVudD86IHN0cmluZztcbiAgbWVzc2FnZVRvUmVwb3J0PzogQ2hhdE1lc3NhZ2U7XG4gIHJlcG9ydFJhbms/OiBudW1iZXI7XG4gIHJlcG9ydFR5cGU6ICdsaWtlJyB8ICdkaXNsaWtlJyA9ICdkaXNsaWtlJztcbiAgc2hvd1JlcG9ydCA9IGZhbHNlO1xuXG4gIC8vIERlYnVnIG1lc3NhZ2VzXG4gIGRlYnVnTWVzc2FnZXM6IERlYnVnTWVzc2FnZVtdIHwgdW5kZWZpbmVkO1xuICBzaG93RGVidWdNZXNzYWdlcyA9IGZhbHNlO1xuXG4gIHByaXZhdGUgX3ByZXZpb3VzUXVlcnk6IFF1ZXJ5O1xuICBwcml2YXRlIF9yZWxvYWRTdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbiB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuICAgIHRoaXMuX2FjdGlvbnMucHVzaCh0aGlzLl9yZXNldENoYXRBY3Rpb24pO1xuICB9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy5fc3ViLmFkZChcbiAgICAgIHRoaXMubG9naW5TZXJ2aWNlLmV2ZW50cy5waXBlKFxuICAgICAgICBmaWx0ZXIoZSA9PiBlLnR5cGUgPT09ICdsb2dpbi1jb21wbGV0ZScpLFxuICAgICAgICB0YXAoXyA9PiB0aGlzLmluc3RhbnRpYXRlQ2hhdFNlcnZpY2UoKSksXG4gICAgICAgIG1hcChfID0+IHRoaXMuY2hhdFNlcnZpY2UuaW5pdENoYXRDb25maWcoKSksXG4gICAgICAgIHN3aXRjaE1hcCgoKSA9PiB0aGlzLmNoYXRTZXJ2aWNlLmluaXRDb25maWckKSxcbiAgICAgICAgZmlsdGVyKGluaXRDb25maWcgPT4gISFpbml0Q29uZmlnKSxcbiAgICAgICAgc3dpdGNoTWFwKF8gPT4gdGhpcy5jaGF0U2VydmljZS5pbml0KCkpLFxuICAgICAgICBzd2l0Y2hNYXAoXyA9PiB0aGlzLmNoYXRTZXJ2aWNlLmluaXRQcm9jZXNzJCksXG4gICAgICAgIGZpbHRlcihzdWNjZXNzID0+ICEhc3VjY2VzcyksXG4gICAgICAgIHRhcChfID0+IHtcbiAgICAgICAgICBpZiAodGhpcy5jaGF0U2VydmljZSBpbnN0YW5jZW9mIFdlYlNvY2tldENoYXRTZXJ2aWNlKSB7XG4gICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uZW1pdCh0aGlzLmNoYXRTZXJ2aWNlLmNvbm5lY3Rpb24pO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzLm9uTG9hZENoYXQoKTtcbiAgICAgICAgfSksXG4gICAgICAgIHN3aXRjaE1hcChfID0+IHRoaXMuY2hhdFNlcnZpY2UuY2hhdENvbmZpZyQpLFxuICAgICAgICB0YXAoY29uZmlnID0+IHtcbiAgICAgICAgICB0aGlzLmNvbmZpZyA9IGNvbmZpZyE7XG4gICAgICAgICAgdGhpcy5lbmFibGVkVXNlcklucHV0ID0gdGhpcy5jb25maWcubW9kZVNldHRpbmdzLmVuYWJsZWRVc2VySW5wdXQ7XG4gICAgICAgICAgdGhpcy5pc3N1ZVR5cGVzID0gdGhpcy5jb25maWcuYXVkaXRTZXR0aW5ncz8uaXNzdWVUeXBlcz8ubGVuZ3RoID8gdGhpcy5jb25maWcuYXVkaXRTZXR0aW5ncyEuaXNzdWVUeXBlcyA6IHVuZGVmaW5lZDtcbiAgICAgICAgICB0aGlzLl9jb25maWcuZW1pdChjb25maWcpO1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZU1vZGVsRGVzY3JpcHRpb24oKTtcbiAgICAgICAgICAgIGlmKCF0aGlzLmZpcnN0Q2hhbmdlc0hhbmRsZWQpIHtcbiAgICAgICAgICAgICAgdGhpcy5fcHJldmlvdXNRdWVyeSA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkodGhpcy5xdWVyeSkpOyAvLyBJbml0aWFsaXplIHRoZSBwcmV2aW91cyBxdWVyeVxuICAgICAgICAgICAgICB0aGlzLl9oYW5kbGVDaGFuZ2VzKCk7XG4gICAgICAgICAgICAgIHRoaXMuX2FkZFNjcm9sbExpc3RlbmVyKCk7XG4gICAgICAgICAgICAgIHRoaXMuZmlyc3RDaGFuZ2VzSGFuZGxlZCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIHRoaXMuaW5pdGlhbGl6YXRpb25FcnJvciA9IHRydWVcbiAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICkuc3Vic2NyaWJlKClcbiAgICApO1xuXG4gICAgdGhpcy5fc3ViLmFkZChcbiAgICAgIGNvbWJpbmVMYXRlc3QoW1xuICAgICAgICB0aGlzLmNoYXRTZXJ2aWNlLnN0cmVhbWluZyQsXG4gICAgICAgIHRoaXMuY2hhdFNlcnZpY2Uuc3RvcHBpbmdHZW5lcmF0aW9uJFxuICAgICAgXSkucGlwZShcbiAgICAgICAgbWFwKChbc3RyZWFtaW5nLCBzdG9wcGluZ0dlbmVyYXRpb25dKSA9PiAhIShzdHJlYW1pbmcgfHwgc3RvcHBpbmdHZW5lcmF0aW9uKSlcbiAgICAgICkuc3Vic2NyaWJlKChyZXN1bHQpID0+IHtcbiAgICAgICAgdGhpcy5fcmVzZXRDaGF0QWN0aW9uLmRpc2FibGVkID0gcmVzdWx0O1xuICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcykge1xuICAgIHRoaXMuY2hhbmdlcyQubmV4dChjaGFuZ2VzKTtcbiAgICBpZiAodGhpcy5jb25maWcpIHtcbiAgICAgIHRoaXMuX2hhbmRsZUNoYW5nZXMoKTtcbiAgICB9XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLl9zdWIudW5zdWJzY3JpYmUoKTtcbiAgICB0aGlzLl9kYXRhU3Vic2NyaXB0aW9uPy51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMuX3JlbG9hZFN1YnNjcmlwdGlvbj8udW5zdWJzY3JpYmUoKTtcbiAgICBpZiAodGhpcy5jaGF0U2VydmljZSBpbnN0YW5jZW9mIFdlYlNvY2tldENoYXRTZXJ2aWNlKSB7XG4gICAgICB0aGlzLmNoYXRTZXJ2aWNlLnN0b3BDb25uZWN0aW9uKCk7XG4gICAgfVxuICB9XG5cbiAgZ2V0IGlzQWRtaW4oKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMucHJpbmNpcGFsU2VydmljZS5wcmluY2lwYWw/LmlzQWRtaW5pc3RyYXRvciB8fCBmYWxzZTtcbiAgfVxuXG4gIGdldCB2aXNpYmxlTWVzc2FnZXNDb3VudCgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzJC52YWx1ZT8uZmlsdGVyKG0gPT4gbS5hZGRpdGlvbmFsUHJvcGVydGllcy5kaXNwbGF5KS5sZW5ndGggfHwgMDtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbnN0YW50aWF0ZSB0aGUgY2hhdCBzZXJ2aWNlIGJhc2VkIG9uIHRoZSBwcm92aWRlZCBAaW5wdXQgcHJvdG9jb2xcbiAgICogVGhpcyBjaGF0IHNlcnZpY2UgaW5zdGFuY2Ugd2lsbCB0aGVuIGJlIHN0b3JlZCBpbiB0aGUgaW5zdGFuY2VNYW5hZ2VyU2VydmljZSB3aXRoIHByb3ZpZGVkIEBpbnB1dCBpbnN0YW5jZUlkIGFzIGEga2V5XG4gICAqL1xuICBpbnN0YW50aWF0ZUNoYXRTZXJ2aWNlKCk6IHZvaWQge1xuICAgIHN3aXRjaCAodGhpcy5wcm90b2NvbCkge1xuICAgICAgY2FzZSAnUkVTVCc6XG4gICAgICAgIHRoaXMuY2hhdFNlcnZpY2UgPSB0aGlzLnJlc3RTZXJ2aWNlO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ1dFQlNPQ0tFVCc6XG4gICAgICAgIHRoaXMuY2hhdFNlcnZpY2UgPSB0aGlzLndlYnNvY2tldFNlcnZpY2U7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDb3VsZCBub3QgZm91bmQgYSBDaGF0U2VydmljZSBpbXBsZW1lbnRhdGlvbiBjb3JyZXNwb25kaW5nIHRvIHRoZSBwcm92aWRlZCBwcm90b2NvbDogJyR7dGhpcy5wcm90b2NvbH0nYCk7XG4gICAgfVxuICAgIHRoaXMuY2hhdFNlcnZpY2Uuc2V0Q2hhdEluc3RhbmNlSWQodGhpcy5pbnN0YW5jZUlkKTtcbiAgICB0aGlzLmluc3RhbmNlTWFuYWdlclNlcnZpY2Uuc3RvcmVJbnN0YW5jZSh0aGlzLmluc3RhbmNlSWQsIHRoaXMuY2hhdFNlcnZpY2UpO1xuICB9XG5cbiAgb3ZlcnJpZGUgZ2V0IGFjdGlvbnMoKSB7IHJldHVybiB0aGlzLl9hY3Rpb25zOyB9XG5cblxuICAvKipcbiAgICogSGFuZGxlcyB0aGUgY2hhbmdlcyBpbiB0aGUgY2hhdCBjb21wb25lbnQuXG4gICAqIElmIHRoZSBjaGF0IHNlcnZpY2UgaXMgYSBXZWJTb2NrZXRDaGF0U2VydmljZSwgaXQgaGFuZGxlcyB0aGUgb3ZlcnJpZGUgb2YgdGhlIG1lc3NhZ2UgaGFuZGxlcnMgaWYgdGhleSBleGlzdC5cbiAgICogSW5pdGlhbGl6ZXMgdGhlIGNoYXQgd2l0aCB0aGUgcHJvdmlkZWQgY2hhdCBtZXNzYWdlcyBpZiB0aGV5IGV4aXN0LCBvdGhlcndpc2UgbG9hZHMgdGhlIGRlZmF1bHQgY2hhdC5cbiAgICogSWYgdGhlIGNoYXQgaXMgaW5pdGlhbGl6ZWQsIHRoZSBpbml0aWFsaXphdGlvbiBldmVudCBpcyBcIlF1ZXJ5XCIsIHRoZSBxdWVyeSBjaGFuZ2VzLCBhbmQgdGhlIHF1ZXJ5Q2hhbmdlU2hvdWxkVHJpZ2dlclJlbG9hZCBmdW5jdGlvbiBpcyBwcm92aWRlZCxcbiAgICogdGhlbiB0aGUgY2hhdCBzaG91bGQgYmUgcmVsb2FkZWQgaWYgdGhlIGZ1bmN0aW9uIHJldHVybnMgdHJ1ZS4gT3RoZXJ3aXNlLCB0aGUgY2hhdCBzaG91bGQgYmUgcmVsb2FkZWQgYnkgZGVmYXVsdC5cbiAgICogSXQgdGFrZXMgaW50byBhY2NvdW50IHRoZSBvbmdvaW5nIHN0cmVhbWluZyBwcm9jZXNzIGFuZCB0aGUgb25nb2luZyBzdG9wcGluZyBwcm9jZXNzIHRvIHRyaWdnZXIgdGhhdCBjb25kaXRpb25hbGx5IGRlZmluZSB0aGUgbG9naWNcbiAgICogb2YgdGhlIHJlbG9hZCA6XG4gICAqIC0gSWYgdGhlIGNoYXQgaXMgc3RyZWFtaW5nLCB0aGVuIHN0b3AgdGhlIGdlbmVyYXRpb24gYW5kIHdhaXQgZm9yIHRoZSBmZXRjaCB0byBjb21wbGV0ZSBiZWZvcmUgcmVsb2FkaW5nIHRoZSBjaGF0LlxuICAgKiAtIElmIHRoZSBjaGF0IGlzIHN0b3BwaW5nIHRoZSBnZW5lcmF0aW9uLCB0aGVuIHdhaXQgZm9yIHRoZSBmZXRjaCB0byBjb21wbGV0ZSBiZWZvcmUgcmVsb2FkaW5nIHRoZSBjaGF0LlxuICAgKi9cbiAgcHJpdmF0ZSBfaGFuZGxlQ2hhbmdlcygpIHtcbiAgICBjb25zdCBjaGFuZ2VzID0gdGhpcy5jaGFuZ2VzJC52YWx1ZTtcbiAgICAvLyBJZiB0aGUgY2hhdCBzZXJ2aWNlIGlzIGEgV2ViU29ja2V0Q2hhdFNlcnZpY2UsIGhhbmRsZSB0aGUgb3ZlcnJpZGUgb2YgdGhlIG1lc3NhZ2UgaGFuZGxlcnMgaWYgZXhpc3RzXG4gICAgaWYgKGNoYW5nZXM/Lm1lc3NhZ2VIYW5kbGVycyAmJiB0aGlzLm1lc3NhZ2VIYW5kbGVycyAmJiB0aGlzLmNoYXRTZXJ2aWNlIGluc3RhbmNlb2YgV2ViU29ja2V0Q2hhdFNlcnZpY2UpIHtcbiAgICAgIHRoaXMuY2hhdFNlcnZpY2Uub3ZlcnJpZGVNZXNzYWdlSGFuZGxlcnModGhpcy5tZXNzYWdlSGFuZGxlcnMpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplIHRoZSBjaGF0IHdpdGggdGhlIHByb3ZpZGVkIGNoYXQgbWVzc2FnZXMgaWYgZXhpc3RzLCBvdGhlcndpc2UgbG9hZCB0aGUgZGVmYXVsdCBjaGF0XG4gICAgICogT25jZSB0aGUgY2hhdCBpcyBpbml0aWFsaXplZCAoZmlyc3RDaGFuZ2VzSGFuZGxlZCBpcyB0cnVlKSwgYWxsb3cgb3BlbmluZyB0aGUgY2hhdCB3aXRoIHRoZSBuZXcgcHJvdmlkZWQgbWVzc2FnZXMgKGlmIGV4aXN0cylcbiAgICAgKi9cbiAgICBpZiAoIXRoaXMuZmlyc3RDaGFuZ2VzSGFuZGxlZCB8fCBjaGFuZ2VzPy5jaGF0KSB7XG4gICAgICBjb25zdCBvcGVuQ2hhdCA9ICgpID0+IHtcbiAgICAgICAgaWYgKHRoaXMubWVzc2FnZXMkLnZhbHVlKSB7XG4gICAgICAgICAgdGhpcy5jaGF0U2VydmljZS5saXN0U2F2ZWRDaGF0KCk7IC8vIFJlZnJlc2ggdGhlIGxpc3Qgb2Ygc2F2ZWQgY2hhdHNcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm9wZW5DaGF0KHRoaXMuY2hhdCEubWVzc2FnZXMpO1xuICAgICAgfTtcbiAgICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVDaGF0SWQoKTtcbiAgICAgIGlmICh0aGlzLmNoYXQpIHtcbiAgICAgICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ25ldy1jaGF0Jywgeydjb25maWd1cmF0aW9uJzogSlNPTi5zdHJpbmdpZnkodGhpcy5jaGF0U2VydmljZS5jaGF0Q29uZmlnJC52YWx1ZSksJ2NoYXQtaW5pdCc6IEpTT04uc3RyaW5naWZ5KHRoaXMuY2hhdCl9KTtcbiAgICAgICAgb3BlbkNoYXQoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVBdWRpdEV2ZW50KCduZXctY2hhdCcsIHsnY29uZmlndXJhdGlvbic6IEpTT04uc3RyaW5naWZ5KHRoaXMuY2hhdFNlcnZpY2UuY2hhdENvbmZpZyQudmFsdWUpfSk7XG4gICAgICAgIHRoaXMubG9hZERlZmF1bHRDaGF0KCk7XG4gICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIElmIHRoZSBjaGF0IGlzIGluaXRpYWxpemVkLCB0aGUgaW5pdGlhbGl6YXRpb24gZXZlbnQgaXMgXCJRdWVyeVwiLCB0aGUgcXVlcnkgY2hhbmdlcyBhbmQgdGhlIHF1ZXJ5Q2hhbmdlU2hvdWxkVHJpZ2dlclJlbG9hZCBmdW5jdGlvbiBpcyBwcm92aWRlZCxcbiAgICAgKiB0aGVuIHRoZSBjaGF0IHNob3VsZCBiZSByZWxvYWRlZCBpZiB0aGUgZnVuY3Rpb24gcmV0dXJucyB0cnVlXG4gICAgICogT3RoZXJ3aXNlLCB0aGUgY2hhdCBzaG91bGQgYmUgcmVsb2FkZWQgYnkgZGVmYXVsdFxuICAgICAqL1xuICAgIGlmICh0aGlzLmZpcnN0Q2hhbmdlc0hhbmRsZWQgJiYgY2hhbmdlcz8ucXVlcnkgJiYgdGhpcy5jb25maWcubW9kZVNldHRpbmdzLmluaXRpYWxpemF0aW9uLmV2ZW50ID09PSAnUXVlcnknKSB7XG4gICAgICBpZiAodGhpcy5xdWVyeUNoYW5nZVNob3VsZFRyaWdnZXJSZWxvYWQgPyB0aGlzLnF1ZXJ5Q2hhbmdlU2hvdWxkVHJpZ2dlclJlbG9hZCh0aGlzLl9wcmV2aW91c1F1ZXJ5LCB0aGlzLnF1ZXJ5KSA6IHRydWUpIHtcbiAgICAgICAgaWYgKCEhdGhpcy5jaGF0U2VydmljZS5zdG9wcGluZ0dlbmVyYXRpb24kLnZhbHVlKSB7XG4gICAgICAgICAgaWYgKCF0aGlzLl9yZWxvYWRTdWJzY3JpcHRpb24pIHtcbiAgICAgICAgICAgIC8vIENyZWF0ZSBhIHN1YnNjcmlwdGlvbiB0byB3YWl0IGZvciBib3RoIHN0cmVhbWluZyQgYW5kIHN0b3BwaW5nR2VuZXJhdGlvbiQgdG8gYmUgZmFsc2VcbiAgICAgICAgICAgIHRoaXMuX3JlbG9hZFN1YnNjcmlwdGlvbiA9IGNvbWJpbmVMYXRlc3QoW1xuICAgICAgICAgICAgICB0aGlzLmNoYXRTZXJ2aWNlLnN0cmVhbWluZyQsXG4gICAgICAgICAgICAgIHRoaXMuY2hhdFNlcnZpY2Uuc3RvcHBpbmdHZW5lcmF0aW9uJFxuICAgICAgICAgICAgXSlcbiAgICAgICAgICAgIC5waXBlKFxuICAgICAgICAgICAgICBmaWx0ZXIoKFtzdHJlYW1pbmcsIHN0b3BwaW5nXSkgPT4gIXN0cmVhbWluZyAmJiAhc3RvcHBpbmcpLCAvLyBXYWl0IHVudGlsIGJvdGggYXJlIGZhbHNlXG4gICAgICAgICAgICAgIHRha2UoMSkgLy8gQ29tcGxldGUgYWZ0ZXIgdGhlIGZpcnN0IG1hdGNoXG4gICAgICAgICAgICApLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgICAgICAgIC8vIEV4ZWN1dGUgdGhlIHJlbG9hZCBhZnRlciB0aGUgcXVlcnkgY2hhbmdlXG4gICAgICAgICAgICAgIHRoaXMuX3RyaWdnZXJSZWxvYWRBZnRlclF1ZXJ5Q2hhbmdlKCk7XG4gICAgICAgICAgICAgIC8vIFVwZGF0ZSBfcHJldmlvdXNRdWVyeSB3aXRoIHRoZSBjdXJyZW50IHF1ZXJ5XG4gICAgICAgICAgICAgIHRoaXMuX3ByZXZpb3VzUXVlcnkgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KHRoaXMucXVlcnkpKTtcbiAgICAgICAgICAgICAgLy8gQ2xlYW4gdXAgc3Vic2NyaXB0aW9uIGFuZCByZXNldCBpdHMgdmFsdWVcbiAgICAgICAgICAgICAgdGhpcy5fcmVsb2FkU3Vic2NyaXB0aW9uID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKCEhdGhpcy5jaGF0U2VydmljZS5zdHJlYW1pbmckLnZhbHVlKSB7XG4gICAgICAgICAgaWYgKCF0aGlzLl9yZWxvYWRTdWJzY3JpcHRpb24pIHtcbiAgICAgICAgICAgIHRoaXMuX3JlbG9hZFN1YnNjcmlwdGlvbiA9IHRoaXMuY2hhdFNlcnZpY2Uuc3RvcEdlbmVyYXRpb24oKVxuICAgICAgICAgICAgLnN1YnNjcmliZSh7XG4gICAgICAgICAgICAgIG5leHQ6ICgpID0+IHt9LFxuICAgICAgICAgICAgICBlcnJvcjogKCkgPT4ge1xuICAgICAgICAgICAgICAgIC8vIENsZWFuIHVwIHN1YnNjcmlwdGlvbiBhbmQgcmVzZXQgaXRzIHZhbHVlXG4gICAgICAgICAgICAgICAgdGhpcy5fcmVsb2FkU3Vic2NyaXB0aW9uPy51bnN1YnNjcmliZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuX3JlbG9hZFN1YnNjcmlwdGlvbiA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgY29tcGxldGU6ICgpID0+IHtcbiAgICAgICAgICAgICAgICAvLyBXYWl0IGZvciB0aGUgb25nb2luZyBmZXRjaCB0byBjb21wbGV0ZSwgdGhlbiB0cmlnZ2VyIHRoZSByZWxvYWRcbiAgICAgICAgICAgICAgICB0aGlzLmNoYXRTZXJ2aWNlLnN0cmVhbWluZyQucGlwZShcbiAgICAgICAgICAgICAgICAgIGZpbHRlcigoc3RyZWFtaW5nKSA9PiAhc3RyZWFtaW5nKSxcbiAgICAgICAgICAgICAgICAgIHRha2UoMSlcbiAgICAgICAgICAgICAgICApLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAvLyBFeGVjdXRlIHRoZSByZWxvYWQgYWZ0ZXIgdGhlIHF1ZXJ5IGNoYW5nZVxuICAgICAgICAgICAgICAgICAgdGhpcy5fdHJpZ2dlclJlbG9hZEFmdGVyUXVlcnlDaGFuZ2UoKTtcbiAgICAgICAgICAgICAgICAgIC8vIFVwZGF0ZSBfcHJldmlvdXNRdWVyeSB3aXRoIHRoZSBjdXJyZW50IHF1ZXJ5XG4gICAgICAgICAgICAgICAgICB0aGlzLl9wcmV2aW91c1F1ZXJ5ID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeSh0aGlzLnF1ZXJ5KSk7XG4gICAgICAgICAgICAgICAgICAvLyBDbGVhbiB1cCBzdWJzY3JpcHRpb24gYW5kIHJlc2V0IGl0cyB2YWx1ZVxuICAgICAgICAgICAgICAgICAgdGhpcy5fcmVsb2FkU3Vic2NyaXB0aW9uIS51bnN1YnNjcmliZSgpO1xuICAgICAgICAgICAgICAgICAgdGhpcy5fcmVsb2FkU3Vic2NyaXB0aW9uID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gRXhlY3V0ZSB0aGUgcmVsb2FkIGFmdGVyIHRoZSBxdWVyeSBjaGFuZ2VcbiAgICAgICAgICB0aGlzLl90cmlnZ2VyUmVsb2FkQWZ0ZXJRdWVyeUNoYW5nZSgpO1xuICAgICAgICAgIC8vIFVwZGF0ZSBfcHJldmlvdXNRdWVyeSB3aXRoIHRoZSBjdXJyZW50IHF1ZXJ5XG4gICAgICAgICAgdGhpcy5fcHJldmlvdXNRdWVyeSA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkodGhpcy5xdWVyeSkpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBVcGRhdGUgX3ByZXZpb3VzUXVlcnkgd2l0aCB0aGUgY3VycmVudCBxdWVyeVxuICAgICAgICB0aGlzLl9wcmV2aW91c1F1ZXJ5ID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeSh0aGlzLnF1ZXJ5KSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRyaWdnZXJzIGEgcmVsb2FkIGFmdGVyIHRoZSBxdWVyeSBjaGFuZ2UuXG4gICAqIFRoaXMgbWV0aG9kIHBlcmZvcm1zIHRoZSBuZWNlc3Nhcnkgb3BlcmF0aW9ucyB0byByZWxvYWQgdGhlIGNoYXQgYWZ0ZXIgYSBxdWVyeSBjaGFuZ2UuXG4gICAqIEl0IHNldHMgdGhlIHN5c3RlbSBhbmQgdXNlciBtZXNzYWdlcywgcmVzZXRzIHRoZSBzYXZlZENoYXRJZCwgZ2VuZXJhdGVzIGEgbmV3IGNoYXRJZCxcbiAgICogZ2VuZXJhdGVzIGEgbmV3IGNoYXQgYXVkaXQgZXZlbnQsIGFuZCBoYW5kbGVzIHRoZSBxdWVyeSBtb2RlLlxuICAgKi9cbiAgcHJpdmF0ZSBfdHJpZ2dlclJlbG9hZEFmdGVyUXVlcnlDaGFuZ2UoKSB7XG4gICAgY29uc3Qgc3lzdGVtTXNnID0ge3JvbGU6ICdzeXN0ZW0nLCBjb250ZW50OiB0aGlzLmNvbmZpZy5kZWZhdWx0VmFsdWVzLnN5c3RlbVByb21wdCwgYWRkaXRpb25hbFByb3BlcnRpZXM6IHtkaXNwbGF5OiBmYWxzZX19O1xuICAgIGNvbnN0IHVzZXJNc2cgPSB7cm9sZTogJ3VzZXInLCBjb250ZW50OiBDaGF0U2VydmljZS5mb3JtYXRQcm9tcHQodGhpcy5jb25maWcuZGVmYXVsdFZhbHVlcy51c2VyUHJvbXB0LCB7cHJpbmNpcGFsOiB0aGlzLnByaW5jaXBhbFNlcnZpY2UucHJpbmNpcGFsfSksIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiB7ZGlzcGxheTogdGhpcy5jb25maWcubW9kZVNldHRpbmdzLmRpc3BsYXlVc2VyUHJvbXB0fX07XG4gICAgdGhpcy5jaGF0U2VydmljZS5zZXRTYXZlZENoYXRJZCh1bmRlZmluZWQpOyAvLyBSZXNldCB0aGUgc2F2ZWRDaGF0SWRcbiAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQ2hhdElkKCk7IC8vIEdlbmVyYXRlIGEgbmV3IGNoYXRJZFxuICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVBdWRpdEV2ZW50KCduZXctY2hhdCcsIHsnY29uZmlndXJhdGlvbic6IEpTT04uc3RyaW5naWZ5KHRoaXMuY2hhdFNlcnZpY2UuY2hhdENvbmZpZyQudmFsdWUpfSk7IC8vIEdlbmVyYXRlIGEgbmV3IGNoYXQgYXVkaXQgZXZlbnRcbiAgICB0aGlzLl9oYW5kbGVRdWVyeU1vZGUoc3lzdGVtTXNnLCB1c2VyTXNnKTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIEFkZHMgYSBzY3JvbGwgbGlzdGVuZXIgdG8gdGhlIG1lc3NhZ2UgbGlzdCBlbGVtZW50LlxuICAgKiBUaGUgbGlzdGVuZXIgaXMgdHJpZ2dlcmVkIHdoZW4gYW55IG9mIHRoZSBmb2xsb3dpbmcgZXZlbnRzIG9jY3VyOlxuICAgKiAtIExvYWRpbmcgc3RhdGUgY2hhbmdlc1xuICAgKiAtIE1lc3NhZ2VzIGNoYW5nZVxuICAgKiAtIFN0cmVhbWluZyBzdGF0ZSBjaGFuZ2VzXG4gICAqIC0gU2Nyb2xsIGV2ZW50IG9jY3VycyBvbiB0aGUgbWVzc2FnZSBsaXN0IGVsZW1lbnRcbiAgICpcbiAgICogV2hlbiB0aGUgbGlzdGVuZXIgaXMgdHJpZ2dlcmVkLCBpdCB1cGRhdGVzIHRoZSBgaXNBdEJvdHRvbWAgcHJvcGVydHkuXG4gICAqL1xuICBwcml2YXRlIF9hZGRTY3JvbGxMaXN0ZW5lcigpIHtcbiAgICB0aGlzLl9zdWIuYWRkKFxuICAgICAgbWVyZ2UodGhpcy5sb2FkaW5nJCwgdGhpcy5tZXNzYWdlcyQsIHRoaXMuY2hhdFNlcnZpY2Uuc3RyZWFtaW5nJCwgZnJvbUV2ZW50KHRoaXMubWVzc2FnZUxpc3QhLm5hdGl2ZUVsZW1lbnQsICdzY3JvbGwnKSkuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgdGhpcy5pc0F0Qm90dG9tID0gdGhpcy5fdG9nZ2xlU2Nyb2xsQnV0dG9uVmlzaWJpbGl0eSgpO1xuICAgICAgICB0aGlzLmNkci5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgICB9KVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBtb2RlbCBkZXNjcmlwdGlvbiBiYXNlZCBvbiB0aGUgZGVmYXVsdFZhbHVlcyBzZXJ2aWNlX2lkIGFuZCBtb2RlbF9pZFxuICAgKi9cbiAgdXBkYXRlTW9kZWxEZXNjcmlwdGlvbigpIHtcbiAgICB0aGlzLm1vZGVsRGVzY3JpcHRpb24gPSB0aGlzLmNoYXRTZXJ2aWNlLmdldE1vZGVsKHRoaXMuY29uZmlnLmRlZmF1bHRWYWx1ZXMuc2VydmljZV9pZCwgdGhpcy5jb25maWcuZGVmYXVsdFZhbHVlcy5tb2RlbF9pZCk7XG4gICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpO1xuICB9XG5cbiAgLyoqXG4gICAqIFN1Ym1pdHMgYSBxdWVzdGlvbiBmcm9tIHRoZSB1c2VyLlxuICAgKiBJZiB0aGUgdXNlciBpcyBlZGl0aW5nIGEgcHJldmlvdXMgbWVzc2FnZSwgcmVtb3ZlcyBhbGwgc3Vic2VxdWVudCBtZXNzYWdlcyBmcm9tIHRoZSBjaGF0IGhpc3RvcnkuXG4gICAqIFRyaWdnZXJzIHRoZSBmZXRjaCBvZiB0aGUgYW5zd2VyIGZvciB0aGUgc3VibWl0dGVkIHF1ZXN0aW9uIGJ5IGNhbGxpbmcgX2ZldGNoQW5zd2VyKCkuXG4gICAqIENsZWFycyB0aGUgaW5wdXQgdmFsdWUgaW4gdGhlIFVJLlxuICAgKi9cbiAgc3VibWl0UXVlc3Rpb24oKSB7XG4gICAgaWYgKCEhdGhpcy5jaGF0U2VydmljZS5zdHJlYW1pbmckLnZhbHVlIHx8ICEhdGhpcy5jaGF0U2VydmljZS5zdG9wcGluZ0dlbmVyYXRpb24kLnZhbHVlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmKHRoaXMucXVlc3Rpb24udHJpbSgpICYmIHRoaXMubWVzc2FnZXMkLnZhbHVlICYmIHRoaXMuY2hhdFNlcnZpY2UuY2hhdEhpc3RvcnkpIHtcbiAgICAgIC8vIFdoZW4gdGhlIHVzZXIgc3VibWl0cyBhIHF1ZXN0aW9uLCBpZiB0aGUgdXNlciBpcyBlZGl0aW5nIGEgcHJldmlvdXMgbWVzc2FnZSwgcmVtb3ZlIGFsbCBzdWJzZXF1ZW50IG1lc3NhZ2VzIGZyb20gdGhlIGNoYXQgaGlzdG9yeVxuICAgICAgaWYgKHRoaXMubWVzc2FnZVRvRWRpdCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIC8vIFVwZGF0ZSB0aGUgbWVzc2FnZXMgaW4gdGhlIFVJXG4gICAgICAgIHRoaXMubWVzc2FnZXMkLm5leHQodGhpcy5tZXNzYWdlcyQudmFsdWUuc2xpY2UoMCwgdGhpcy5tZXNzYWdlVG9FZGl0KSk7XG4gICAgICAgIC8vIFVwZGF0ZSB0aGUgcmF3IG1lc3NhZ2VzIGluIHRoZSBjaGF0IGhpc3Rvcnkgd2hpY2ggaXMgdGhlIGNsZWFuIHZlcnNpb24gdXNlZCB0byBtYWtlIHRoZSBuZXh0IHJlcXVlc3RcbiAgICAgICAgdGhpcy5jaGF0U2VydmljZS5jaGF0SGlzdG9yeSA9IHRoaXMuY2hhdFNlcnZpY2UuY2hhdEhpc3Rvcnkuc2xpY2UoMCwgdGhpcy5yZW1hcHBlZE1lc3NhZ2VUb0VkaXQpO1xuICAgICAgICB0aGlzLm1lc3NhZ2VUb0VkaXQgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMucmVtYXBwZWRNZXNzYWdlVG9FZGl0ID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgLy8gUmVtb3ZlIHRoZSBzZWFyY2ggd2FybmluZyBtZXNzYWdlIGlmIGV4aXN0c1xuICAgICAgaWYgKHRoaXMuY2hhdFNlcnZpY2UuY2hhdEhpc3RvcnkuYXQoLTEpPy5yb2xlID09PSAnc2VhcmNoLXdhcm5pbmcnKSB7XG4gICAgICAgIHRoaXMuY2hhdFNlcnZpY2UuY2hhdEhpc3RvcnkucG9wKCk7XG4gICAgICB9XG4gICAgICAvLyBGZXRjaCB0aGUgYW5zd2VyXG4gICAgICB0aGlzLl9mZXRjaEFuc3dlcih0aGlzLnF1ZXN0aW9uLnRyaW0oKSwgdGhpcy5jaGF0U2VydmljZS5jaGF0SGlzdG9yeSk7XG4gICAgICAvLyBDbGVhciB0aGUgaW5wdXQgdmFsdWUgaW4gdGhlIFVJXG4gICAgICB0aGlzLnF1ZXN0aW9uSW5wdXQhLm5hdGl2ZUVsZW1lbnQudmFsdWUgPSAnJztcbiAgICAgIHRoaXMucXVlc3Rpb25JbnB1dCEubmF0aXZlRWxlbWVudC5zdHlsZS5oZWlnaHQgPSBgYXV0b2A7XG4gICAgfVxuICB9XG5cblxuICAvKipcbiAgICogVHJpZ2dlcnMgdGhlIGZldGNoIG9mIHRoZSBhbnN3ZXIgZm9yIHRoZSBnaXZlbiBxdWVzdGlvbiBhbmQgdXBkYXRlcyB0aGUgY29udmVyc2F0aW9uLlxuICAgKiBHZW5lcmF0ZXMgYW4gYXVkaXQgZXZlbnQgZm9yIHRoZSB1c2VyIGlucHV0LlxuICAgKlxuICAgKiBAcGFyYW0gcXVlc3Rpb24gLSBUaGUgcXVlc3Rpb24gYXNrZWQgYnkgdGhlIHVzZXIuXG4gICAqIEBwYXJhbSBjb252ZXJzYXRpb24gLSBUaGUgY3VycmVudCBjb252ZXJzYXRpb24gbWVzc2FnZXMuXG4gICAqL1xuICBwcml2YXRlIF9mZXRjaEFuc3dlcihxdWVzdGlvbjogc3RyaW5nLCBjb252ZXJzYXRpb246IENoYXRNZXNzYWdlW10pIHtcbiAgICBjb25zdCB1c2VyTXNnID0ge3JvbGU6ICd1c2VyJywgY29udGVudDogcXVlc3Rpb24sIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiB7ZGlzcGxheTogdHJ1ZSwgaXNVc2VySW5wdXQ6IHRydWUsIGFkZGl0aW9uYWxXb3JrZmxvd1Byb3BlcnRpZXM6IHRoaXMuY29uZmlnLmFkZGl0aW9uYWxXb3JrZmxvd1Byb3BlcnRpZXN9fTtcbiAgICBjb25zdCBtZXNzYWdlcyA9IFsuLi5jb252ZXJzYXRpb24sIHVzZXJNc2ddO1xuICAgIHRoaXMubWVzc2FnZXMkLm5leHQobWVzc2FnZXMpO1xuICAgIHRoaXMuZmV0Y2gobWVzc2FnZXMpO1xuICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVBdWRpdEV2ZW50KCdtZXNzYWdlJywgey4uLnRoaXMuX2RlZmluZU1lc3NhZ2VBdWRpdERldGFpbHModXNlck1zZywgbWVzc2FnZXMubGVuZ3RoIC0gMSksICdxdWVyeSc6IEpTT04uc3RyaW5naWZ5KHRoaXMucXVlcnkpLCAnaXMtdXNlci1pbnB1dCc6IHRydWUsICdlbmFibGVkLWZ1bmN0aW9ucyc6IHRoaXMuY29uZmlnLmRlZmF1bHRWYWx1ZXMuZnVuY3Rpb25zPy5maWx0ZXIoZnVuYyA9PiBmdW5jLmVuYWJsZWQpLm1hcChmdW5jID0+IGZ1bmMubmFtZSksICdhZGRpdGlvbmFsLXdvcmtmbG93LXByb3BlcnRpZXMnOiBKU09OLnN0cmluZ2lmeSh0aGlzLmNvbmZpZy5hZGRpdGlvbmFsV29ya2Zsb3dQcm9wZXJ0aWVzKX0pO1xuICB9XG5cbiAgLyoqXG4gICAqIERlcGVuZGluZyBvbiB0aGUgY29ubmVjdGlvbidzIHN0YXRlIDpcbiAgICogIC0gSWYgY29ubmVjdGVkID0+IGdpdmVuIGEgbGlzdCBvZiBtZXNzYWdlcywgdGhlIGNoYXQgZW5kcG9pbnQgaXMgaW52b2tlZCBmb3IgYSBjb250aW51YXRpb24gYW5kIHVwZGF0ZXMgdGhlIGxpc3Qgb2YgbWVzc2FnZXMgYWNjb3JkaW5nbHkuXG4gICAqICAtIElmIGFueSBvdGhlciBzdGF0ZSA9PiBhIGNvbm5lY3Rpb24gZXJyb3IgbWVzc2FnZSBpcyBkaXNwbGF5ZWQgaW4gdGhlIGNoYXQuXG4gICAqIEBwYXJhbSBtZXNzYWdlcyBUaGUgbGlzdCBvZiBtZXNzYWdlcyB0byBpbnZva2UgdGhlIGNoYXQgZW5kcG9pbnQgd2l0aFxuICAgKi9cbiAgcHVibGljIGZldGNoKG1lc3NhZ2VzOiBDaGF0TWVzc2FnZVtdKSB7XG4gICAgdGhpcy5fdXBkYXRlQ29ubmVjdGlvblN0YXR1cygpO1xuICAgIHRoaXMuY2RyLmRldGVjdENoYW5nZXMoKTtcblxuICAgIGlmICh0aGlzLmlzQ29ubmVjdGVkKSB7XG4gICAgICB0aGlzLmxvYWRpbmckLm5leHQodHJ1ZSk7XG4gICAgICB0aGlzLl9kYXRhU3Vic2NyaXB0aW9uPy51bnN1YnNjcmliZSgpO1xuICAgICAgdGhpcy5fZGF0YVN1YnNjcmlwdGlvbiA9IHRoaXMuY2hhdFNlcnZpY2UuZmV0Y2gobWVzc2FnZXMsIHRoaXMucXVlcnkpXG4gICAgICAgIC5zdWJzY3JpYmUoe1xuICAgICAgICAgIG5leHQ6IHJlcyA9PiB0aGlzLnVwZGF0ZURhdGEocmVzLmhpc3RvcnkpLFxuICAgICAgICAgIGVycm9yOiAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLl91cGRhdGVDb25uZWN0aW9uU3RhdHVzKCk7XG4gICAgICAgICAgICBpZiAoIXRoaXMuaXNDb25uZWN0ZWQpIHtcbiAgICAgICAgICAgICAgY29uc3QgbWVzc2FnZSA9IHtyb2xlOiAnY29ubmVjdGlvbi1lcnJvcicsIGNvbnRlbnQ6IHRoaXMuY29uZmlnLmNvbm5lY3Rpb25TZXR0aW5ncy5jb25uZWN0aW9uRXJyb3JNZXNzYWdlLCBhZGRpdGlvbmFsUHJvcGVydGllczoge2Rpc3BsYXk6IHRydWV9fTtcbiAgICAgICAgICAgICAgdGhpcy5tZXNzYWdlcyQubmV4dChbLi4ubWVzc2FnZXMsIG1lc3NhZ2VdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMudGVybWluYXRlRmV0Y2goKTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIGNvbXBsZXRlOiAoKSA9PiB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgdGhlIGxhc3QgbWVzc2FnZSBpZiBpdCdzIGFuIGVtcHR5IG1lc3NhZ2VcbiAgICAgICAgICAgIC8vIFRoaXMgaXMgZHVlIHRvIHRoZSBtYW5uZXIgaW4gd2hpY2ggdGhlIGNoYXQgc2VydmljZSBoYW5kbGVzIGNvbnNlY3V0aXZlIG1lc3NhZ2VzXG4gICAgICAgICAgICBjb25zdCBsYXN0TWVzc2FnZSA9IHRoaXMubWVzc2FnZXMkLnZhbHVlPy5hdCgtMSk7XG4gICAgICAgICAgICBpZiAobGFzdE1lc3NhZ2U/LnJvbGUgPT09ICdhc3Npc3RhbnQnICYmIGxhc3RNZXNzYWdlPy5jb250ZW50ID09PSBcIlwiXG4gICAgICAgICAgICAgICAgJiYgIWxhc3RNZXNzYWdlPy5hZGRpdGlvbmFsUHJvcGVydGllcz8uJGF0dGFjaG1lbnQgJiYgIWxhc3RNZXNzYWdlPy5hZGRpdGlvbmFsUHJvcGVydGllcz8uJHByb2dyZXNzXG4gICAgICAgICAgICAgICAgJiYgIWxhc3RNZXNzYWdlPy5hZGRpdGlvbmFsUHJvcGVydGllcz8uJGRlYnVnICYmICFsYXN0TWVzc2FnZT8uYWRkaXRpb25hbFByb3BlcnRpZXM/LiRzdWdnZXN0ZWRBY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAgIHRoaXMubWVzc2FnZXMkLm5leHQodGhpcy5tZXNzYWdlcyQudmFsdWU/LnNsaWNlKDAsIC0xKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnRlcm1pbmF0ZUZldGNoKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgbWVzc2FnZSA9IHtyb2xlOiAnY29ubmVjdGlvbi1lcnJvcicsIGNvbnRlbnQ6IHRoaXMuY29uZmlnLmNvbm5lY3Rpb25TZXR0aW5ncy5jb25uZWN0aW9uRXJyb3JNZXNzYWdlLCBhZGRpdGlvbmFsUHJvcGVydGllczoge2Rpc3BsYXk6IHRydWV9fTtcbiAgICAgIHRoaXMubWVzc2FnZXMkLm5leHQoWy4uLm1lc3NhZ2VzLCBtZXNzYWdlXSk7XG4gICAgfVxuXG4gICAgaWYodGhpcy5hdXRvbWF0aWNTY3JvbGxUb0xhc3RSZXNwb25zZSkge1xuICAgICAgdGhpcy5zY3JvbGxEb3duKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHJ5IHRvIGZldGNoIHRoZSBtZXNzYWdlcyBpZiB0aGUgY29ubmVjdGlvbiBpc3N1ZXMuXG4gICAqICAtIElmIHJlY29ubmVjdGluZyA9PiBrZWVwIGRpc3BsYXkgdGhlIGNvbm5lY3Rpb24gZXJyb3IgbWVzc2FnZSBldmVuIHdoZW4gY2xpY2tpbmcgb24gdGhlIFwicmV0cnlcIiBidXR0b24gYW5kIGluY3JlYXNpbmcgdGhlIG51bWJlciBvZiByZXRyaWFsIGF0dGVtcHRzLCB1bnRpbCB0aGUgY29ubmVjdGlvbiBpcyByZS1lc3RhYmxpc2hlZFxuICAgKiAgLSBJZiBkaXNjb25uZWN0ZWQgPT4gT24gY2xpY2sgb24gdGhlIFwicmV0cnlcIiBidXR0b24sIHN0YXJ0IHRoZSBjb25uZWN0aW9uIHByb2Nlc3Mgd2hpbGUgZGlzcGxheWluZyB0aGUgY29ubmVjdGlvbiBlcnJvciBtZXNzYWdlIDpcbiAgICogICAgICAqIElmIHN1Y2Nlc3NmdWwgPT4gZ2l2ZW4gYSBsaXN0IG9mIG1lc3NhZ2VzLCB0aGUgY2hhdCBlbmRwb2ludCBpcyBpbnZva2VkIGZvciBhIGNvbnRpbnVhdGlvbiBhbmQgdXBkYXRlcyB0aGUgbGlzdCBvZiBtZXNzYWdlcyBhY2NvcmRpbmdseS5cbiAgICogICAgICAqIElmIGZhaWxlZCA9PiBpbmNyZWFzZSB0aGUgbnVtYmVyIG9mIHJldHJpYWwgYXR0ZW1wdHNcbiAgICovXG4gIHJldHJ5RmV0Y2goKSB7XG4gICAgaWYodGhpcy5jaGF0U2VydmljZSBpbnN0YW5jZW9mIFdlYlNvY2tldENoYXRTZXJ2aWNlKSB7XG4gICAgICAvLyBBIG9uZS10aW1lIGxpc3RlbmVyIGZvciByZWNvbm5lY3RlZCBldmVudFxuICAgICAgY29uc3Qgb25SZWNvbm5lY3RlZEhhbmRsZXIgPSAoKSA9PiB7XG4gICAgICAgIC8vIEdldCB0aGUgbWVzc2FnZXMgd2l0aG91dCB0aGUgbGFzdCBvbmUgKHRoZSBjb25uZWN0aW9uIGVycm9yIG1lc3NhZ2UpXG4gICAgICAgIGNvbnN0IG1lc3NhZ2VzID0gdGhpcy5tZXNzYWdlcyQudmFsdWUhLnNsaWNlKDAsIC0xKTtcbiAgICAgICAgLy8gRmluZCB0aGUgbGFzdCBcInVzZXJcIiBtZXNzYWdlIGluIHRoZSBtZXNzYWdlcyBsaXN0XG4gICAgICAgIGxldCBpbmRleCA9IG1lc3NhZ2VzLmxlbmd0aCAtIDE7XG4gICAgICAgIHdoaWxlIChpbmRleCA+PSAwICYmIG1lc3NhZ2VzW2luZGV4XS5yb2xlICE9PSAndXNlcicpIHtcbiAgICAgICAgICBpbmRleC0tO1xuICAgICAgICB9XG4gICAgICAgIC8vIElmIGEgdXNlciBtZXNzYWdlIGlzIGZvdW5kIChhbmQgaXQgc2hvdWxkIGFsd2F5cyBiZSB0aGUgY2FzZSksIHJlbW92ZSBhbGwgc3Vic2VxdWVudCBtZXNzYWdlcyBmcm9tIHRoZSBjaGF0IGhpc3RvcnlcbiAgICAgICAgLy8gVXBkYXRlIHRoZSBtZXNzYWdlcyBpbiB0aGUgVUlcbiAgICAgICAgLy8gYW5kIGZldGNoIHRoZSBhbnN3ZXIgZnJvbSB0aGUgYXNzaXN0YW50XG4gICAgICAgIGlmIChpbmRleCA+PSAwKSB7XG4gICAgICAgICAgdGhpcy5tZXNzYWdlcyQubmV4dCh0aGlzLm1lc3NhZ2VzJC52YWx1ZSEuc2xpY2UoMCwgaW5kZXgrMSkpO1xuICAgICAgICAgIGNvbnN0IHJlbWFwcGVkSW5kZXggPSB0aGlzLl9yZW1hcEluZGV4SW5DaGF0SGlzdG9yeShpbmRleCk7XG4gICAgICAgICAgdGhpcy5jaGF0U2VydmljZS5jaGF0SGlzdG9yeSA9IHRoaXMuY2hhdFNlcnZpY2UuY2hhdEhpc3RvcnkhLnNsaWNlKDAsIHJlbWFwcGVkSW5kZXgrMSk7XG4gICAgICAgICAgdGhpcy5mZXRjaCh0aGlzLmNoYXRTZXJ2aWNlLmNoYXRIaXN0b3J5KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJldHJpYWxBdHRlbXB0cyA9IHVuZGVmaW5lZDsgLy8gUmVzZXQgdGhlIG51bWJlciBvZiByZXRyaWFsIGF0dGVtcHRzXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUbyByZW1vdmUgdGhlIGhhbmRsZXIgZm9yIG9ucmVjb25uZWN0ZWQoKSBhZnRlciBpdCdzIGJlZW4gcmVnaXN0ZXJlZCxjYW5ub3QgZGlyZWN0bHkgdXNlIG9mZigpIGxpa2UgeW91IHdvdWxkIGZvciBub3JtYWwgZXZlbnRzIHJlZ2lzdGVyZWQgd2l0aCBjb25uZWN0aW9uLm9uKCkuXG4gICAgICAgICAqIEluc3RlYWQsIHlvdSBuZWVkIHRvIGV4cGxpY2l0bHkgcmVtb3ZlIG9yIHJlc2V0IHRoZSBoYW5kbGVyIGJ5IGFzc2lnbmluZyBpdCB0byBudWxsIG9yIGFuIGVtcHR5IGZ1bmN0aW9uXG4gICAgICAgICAqL1xuICAgICAgICAodGhpcy5jaGF0U2VydmljZSBhcyBXZWJTb2NrZXRDaGF0U2VydmljZSkuY29ubmVjdGlvbiEub25yZWNvbm5lY3RlZCgoKSA9PiB7fSk7XG4gICAgICAgIC8vIFJlc2V0IHRoZSBmbGFnIHRvIGVuc3VyZSB0aGUgaGFuZGxlciBpcyByZWdpc3RlcmVkIGFnYWluIHdoZW4gbmVlZGVkXG4gICAgICAgIHRoaXMuX2lzUmVjb25uZWN0ZWRMaXN0ZW5lclJlZ2lzdGVyZWQgPSBmYWxzZTtcbiAgICAgIH1cbiAgICAgIC8vIERlcGVuZGluZyBvbiB0aGUgY29ubmVjdGlvbidzIHN0YXRlLCB0YWtlIHRoZSBhcHByb3ByaWF0ZSBhY3Rpb25cbiAgICAgIHN3aXRjaCAodGhpcy5jaGF0U2VydmljZS5jb25uZWN0aW9uIS5zdGF0ZSkge1xuICAgICAgICBjYXNlIEh1YkNvbm5lY3Rpb25TdGF0ZS5Db25uZWN0ZWQ6XG4gICAgICAgICAgLy8gSWYgdGhlIGNvbm5lY3Rpb24gaXMgcmUtZXN0YWJsaXNoZWQgaW4gdGhlIG1lYW50aW1lLCBmZXRjaCB0aGUgbWVzc2FnZXNcbiAgICAgICAgICBvblJlY29ubmVjdGVkSGFuZGxlcigpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIEh1YkNvbm5lY3Rpb25TdGF0ZS5SZWNvbm5lY3Rpbmc6XG4gICAgICAgICAgLy8gQXR0YWNoIHRoZSByZWNvbm5lY3RlZCBsaXN0ZW5lciBpZiBub3QgYWxyZWFkeSByZWdpc3RlcmVkXG4gICAgICAgICAgaWYgKCF0aGlzLl9pc1JlY29ubmVjdGVkTGlzdGVuZXJSZWdpc3RlcmVkKSB7XG4gICAgICAgICAgICB0aGlzLmNoYXRTZXJ2aWNlLmNvbm5lY3Rpb24hLm9ucmVjb25uZWN0ZWQob25SZWNvbm5lY3RlZEhhbmRsZXIpO1xuICAgICAgICAgICAgdGhpcy5faXNSZWNvbm5lY3RlZExpc3RlbmVyUmVnaXN0ZXJlZCA9IHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIEluY3JlYXNlIHRoZSBudW1iZXIgb2YgcmV0cmlhbCBhdHRlbXB0c1xuICAgICAgICAgIHRoaXMucmV0cmlhbEF0dGVtcHRzID0gdGhpcy5yZXRyaWFsQXR0ZW1wdHMgPyB0aGlzLnJldHJpYWxBdHRlbXB0cysxIDogMTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBIdWJDb25uZWN0aW9uU3RhdGUuRGlzY29ubmVjdGVkOlxuICAgICAgICAgIC8vIFN0YXJ0IHRoZSBuZXcgY29ubmVjdGlvblxuICAgICAgICAgIHRoaXMuY2hhdFNlcnZpY2Uuc3RhcnRDb25uZWN0aW9uKClcbiAgICAgICAgICAudGhlbigoKSA9PiBvblJlY29ubmVjdGVkSGFuZGxlcigpKVxuICAgICAgICAgIC5jYXRjaCgoKSA9PiB7IC8vIElmIHRoZSBjb25uZWN0aW9uIGZhaWxzLCBpbmNyZWFzZSB0aGUgbnVtYmVyIG9mIHJldHJpYWwgYXR0ZW1wdHNcbiAgICAgICAgICAgIHRoaXMucmV0cmlhbEF0dGVtcHRzID0gdGhpcy5yZXRyaWFsQXR0ZW1wdHMgPyB0aGlzLnJldHJpYWxBdHRlbXB0cysxIDogMTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgaWYgdGhlIHNpZ25hbFIgY29ubmVjdGlvbiBpcyBjb25uZWN0ZWQuXG4gICAqIEZvciB0aGUgUkVTVCBwcm90b2NvbCwgdGhlIGNvbm5lY3Rpb24gaXMgYWx3YXlzIGNvbnNpZGVyZWQgY29ubmVjdGVkIChmb3IgdGhlIG1vbWVudCkuXG4gICAqL1xuICBwcml2YXRlIF91cGRhdGVDb25uZWN0aW9uU3RhdHVzKCkge1xuICAgIHRoaXMuaXNDb25uZWN0ZWQgPSAodGhpcy5jaGF0U2VydmljZSBpbnN0YW5jZW9mIFdlYlNvY2tldENoYXRTZXJ2aWNlKSA/IHRoaXMuY2hhdFNlcnZpY2UuY29ubmVjdGlvbiEuc3RhdGUgPT09IEh1YkNvbm5lY3Rpb25TdGF0ZS5Db25uZWN0ZWQgOiB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIFVwZGF0ZSB0aGUgVUkgd2l0aCB0aGUgbmV3IG1lc3NhZ2VzXG4gICAqIEBwYXJhbSBtZXNzYWdlc1xuICAgKi9cbiAgdXBkYXRlRGF0YShtZXNzYWdlczogQ2hhdE1lc3NhZ2VbXSkge1xuICAgIHRoaXMubWVzc2FnZXMkLm5leHQobWVzc2FnZXMpO1xuICAgIHRoaXMuZGF0YS5lbWl0KG1lc3NhZ2VzKTtcbiAgICB0aGlzLmxvYWRpbmckLm5leHQoZmFsc2UpO1xuICAgIHRoaXMucXVlc3Rpb24gPSAnJztcbiAgICBpZih0aGlzLmF1dG9tYXRpY1Njcm9sbFRvTGFzdFJlc3BvbnNlKSB7XG4gICAgICB0aGlzLnNjcm9sbERvd24oKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybnMgdHJ1ZSBpZiB0aGUgY2hhdCBkaXNjdXNzaW9uIGlzIHNjcm9sbGVkIGRvd24gdG8gdGhlIGJvdHRvbSwgZmFsc2Ugb3RoZXJ3aXNlXG4gICAqL1xuICBwcml2YXRlIF90b2dnbGVTY3JvbGxCdXR0b25WaXNpYmlsaXR5KCk6IGJvb2xlYW4ge1xuICAgIGlmKHRoaXMubWVzc2FnZUxpc3Q/Lm5hdGl2ZUVsZW1lbnQpIHtcbiAgICAgIHJldHVybiBNYXRoLnJvdW5kKHRoaXMubWVzc2FnZUxpc3Q/Lm5hdGl2ZUVsZW1lbnQuc2Nyb2xsSGVpZ2h0IC0gdGhpcy5tZXNzYWdlTGlzdD8ubmF0aXZlRWxlbWVudC5zY3JvbGxUb3AgLSAxKSA8PSB0aGlzLm1lc3NhZ2VMaXN0Py5uYXRpdmVFbGVtZW50LmNsaWVudEhlaWdodDtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogU2Nyb2xsIGRvd24gdG8gdGhlIGJvdHRvbSBvZiB0aGUgY2hhdCBkaXNjdXNzaW9uXG4gICAqL1xuICBzY3JvbGxEb3duKCkge1xuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgaWYodGhpcy5tZXNzYWdlTGlzdD8ubmF0aXZlRWxlbWVudCkge1xuICAgICAgICB0aGlzLm1lc3NhZ2VMaXN0Lm5hdGl2ZUVsZW1lbnQuc2Nyb2xsVG9wID0gdGhpcy5tZXNzYWdlTGlzdC5uYXRpdmVFbGVtZW50LnNjcm9sbEhlaWdodDtcbiAgICAgICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpO1xuICAgICAgfVxuICAgIH0sIDEwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTdGFydCBhIG5ldyBjaGF0IHdpdGggdGhlIGRlZmF1bHRWYWx1ZXMgc2V0dGluZ3NcbiAgICogVGhlIHNhdmVkQ2hhdElkIGluIHRoZSBjaGF0IHNlcnZpY2Ugd2lsbCBiZSByZXNldCwgc28gdGhhdCB0aGUgdXBjb21pbmcgc2F2ZWQgY2hhdCBvcGVyYXRpb25zIHdpbGwgYmUgcGVyZm9ybWVkIG9uIHRoZSBmcmVzaCBuZXcgY2hhdFxuICAgKiBJZiB0aGUgc2F2ZWRDaGF0IGZlYXR1cmUgaXMgZW5hYmxlZCwgdGhlIGxpc3Qgb2Ygc2F2ZWQgY2hhdHMgd2lsbCBiZSByZWZyZXNoZWRcbiAgICovXG4gIG5ld0NoYXQoKSB7XG4gICAgaWYgKCEhdGhpcy5jaGF0U2VydmljZS5zdHJlYW1pbmckLnZhbHVlIHx8ICEhdGhpcy5jaGF0U2VydmljZS5zdG9wcGluZ0dlbmVyYXRpb24kLnZhbHVlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuY2hhdFNlcnZpY2Uuc2V0U2F2ZWRDaGF0SWQodW5kZWZpbmVkKTsgLy8gUmVzZXQgdGhlIHNhdmVkQ2hhdElkXG4gICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUNoYXRJZCgpOyAvLyBHZW5lcmF0ZSBhIG5ldyBjaGF0SWRcbiAgICB0aGlzLmNoYXRTZXJ2aWNlLmxpc3RTYXZlZENoYXQoKTsgLy8gUmVmcmVzaCB0aGUgbGlzdCBvZiBzYXZlZCBjaGF0c1xuICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVBdWRpdEV2ZW50KCduZXctY2hhdCcsIHsnY29uZmlndXJhdGlvbic6IEpTT04uc3RyaW5naWZ5KHRoaXMuY2hhdFNlcnZpY2UuY2hhdENvbmZpZyQudmFsdWUpfSk7IC8vIEdlbmVyYXRlIGEgbmV3IGNoYXQgYXVkaXQgZXZlbnRcbiAgICB0aGlzLmxvYWREZWZhdWx0Q2hhdCgpOyAvLyBTdGFydCBhIG5ldyBjaGF0XG4gIH1cblxuICAvKipcbiAgICogQXR0YWNoZXMgdGhlIHNwZWNpZmllZCBkb2N1bWVudCBJRHMgdG8gdGhlIGFzc2lzdGFudC5cbiAgICogSWYgdGhlIGNoYXQgaXMgc3RyZWFtaW5nIG9yIHN0b3BwaW5nIHRoZSBnZW5lcmF0aW9uLCB0aGUgb3BlcmF0aW9uIGlzIG5vdCBhbGxvd2VkLlxuICAgKiBJZiBubyBkb2N1bWVudCBJRHMgYXJlIHByb3ZpZGVkLCB0aGUgb3BlcmF0aW9uIGlzIG5vdCBhbGxvd2VkLlxuICAgKiBJZiB0aGUgYWN0aW9uIGZvciBhdHRhY2hpbmcgYSBkb2N1bWVudCBpcyBub3QgZGVmaW5lZCBhdCB0aGUgYXBwbGljYXRpb24gY3VzdG9taXphdGlvbiBsZXZlbCwgYW4gZXJyb3IgaXMgbG9nZ2VkLlxuICAgKiBAcGFyYW0gaWRzIC0gQW4gYXJyYXkgb2YgZG9jdW1lbnQgSURzIHRvIGF0dGFjaC5cbiAgICovXG4gIGF0dGFjaFRvQ2hhdChpZHM6IHN0cmluZ1tdKSB7XG4gICAgaWYgKCEhdGhpcy5jaGF0U2VydmljZS5zdHJlYW1pbmckLnZhbHVlIHx8ICEhdGhpcy5jaGF0U2VydmljZS5zdG9wcGluZ0dlbmVyYXRpb24kLnZhbHVlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICghaWRzIHx8IGlkcz8ubGVuZ3RoIDwgMSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBhdHRhY2hEb2NBY3Rpb24gPSB0aGlzLmNvbmZpZy5tb2RlU2V0dGluZ3MuYWN0aW9ucz8uW1wiYXR0YWNoRG9jQWN0aW9uXCJdO1xuICAgIGlmICghYXR0YWNoRG9jQWN0aW9uKSB7XG4gICAgICBjb25zb2xlLmVycm9yKGBObyBhY3Rpb24gaXMgZGVmaW5lZCBmb3IgYXR0YWNoaW5nIGEgZG9jdW1lbnQgdG8gdGhlIGFzc2lzdGFudCBcIiR7dGhpcy5pbnN0YW5jZUlkfVwiYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHVzZXJNc2cgPSB7IHJvbGU6ICd1c2VyJywgY29udGVudDogJycsIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiB7ZGlzcGxheTogZmFsc2UsIGlzVXNlcklucHV0OiBmYWxzZSwgdHlwZTogXCJBY3Rpb25cIiwgZm9yY2VkV29ya2Zsb3c6IGF0dGFjaERvY0FjdGlvbi5mb3JjZWRXb3JrZmxvdywgZm9yY2VkV29ya2Zsb3dQcm9wZXJ0aWVzOiB7Li4uKGF0dGFjaERvY0FjdGlvbi5mb3JjZWRXb3JrZmxvd1Byb3BlcnRpZXMgfHwge30pLCBpZHN9LCBhZGRpdGlvbmFsV29ya2Zsb3dQcm9wZXJ0aWVzOiB0aGlzLmNvbmZpZy5hZGRpdGlvbmFsV29ya2Zsb3dQcm9wZXJ0aWVzfX07XG4gICAgY29uc3QgbWVzc2FnZXMgPSBbLi4udGhpcy5jaGF0U2VydmljZS5jaGF0SGlzdG9yeSEsIHVzZXJNc2ddO1xuICAgIHRoaXMubWVzc2FnZXMkLm5leHQobWVzc2FnZXMpO1xuICAgIHRoaXMuZmV0Y2gobWVzc2FnZXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFN0YXJ0IHRoZSBkZWZhdWx0IGNoYXQgd2l0aCB0aGUgZGVmYXVsdFZhbHVlcyBzZXR0aW5nc1xuICAgKiBJZiB0aGUgY2hhdCBpcyBtZWFudCB0byBiZSBpbml0aWFsaXplZCB3aXRoIGV2ZW50ID09PSBcIlF1ZXJ5XCIsIHRoZSBjb3JyZXNwb25kaW5nIHVzZXIgcXVlcnkgbWVzc2FnZSB3aWxsIGJlIGFkZGVkIHRvIHRoZSBjaGF0IGhpc3RvcnlcbiAgICovXG4gIGxvYWREZWZhdWx0Q2hhdCgpIHtcbiAgICAvLyBEZWZpbmUgdGhlIGRlZmF1bHQgc3lzdGVtIHByb21wdCBhbmQgdXNlciBwcm9tcHQgbWVzc2FnZXNcbiAgICBjb25zdCBzeXN0ZW1Nc2cgPSB7cm9sZTogJ3N5c3RlbScsIGNvbnRlbnQ6IHRoaXMuY29uZmlnLmRlZmF1bHRWYWx1ZXMuc3lzdGVtUHJvbXB0LCBhZGRpdGlvbmFsUHJvcGVydGllczoge2Rpc3BsYXk6IGZhbHNlfX07XG4gICAgY29uc3QgdXNlck1zZyA9IHtyb2xlOiAndXNlcicsIGNvbnRlbnQ6IENoYXRTZXJ2aWNlLmZvcm1hdFByb21wdCh0aGlzLmNvbmZpZy5kZWZhdWx0VmFsdWVzLnVzZXJQcm9tcHQsIHtwcmluY2lwYWw6IHRoaXMucHJpbmNpcGFsU2VydmljZS5wcmluY2lwYWx9KSwgYWRkaXRpb25hbFByb3BlcnRpZXM6IHtkaXNwbGF5OiB0aGlzLmNvbmZpZy5tb2RlU2V0dGluZ3MuZGlzcGxheVVzZXJQcm9tcHR9fTtcblxuICAgIGlmICh0aGlzLmNvbmZpZy5tb2RlU2V0dGluZ3MuaW5pdGlhbGl6YXRpb24uZXZlbnQgPT09ICdRdWVyeScpIHtcbiAgICAgIHRoaXMuX2hhbmRsZVF1ZXJ5TW9kZShzeXN0ZW1Nc2csIHVzZXJNc2cpO1xuICAgIH0gZWxzZSB7IC8vIElmIHRoZSBjaGF0IGlzIG1lYW50IHRvIGJlIGluaXRpYWxpemVkIHdpdGggZXZlbnQgPT09IFwiUHJvbXB0XCJcbiAgICAgIHRoaXMub3BlbkNoYXQoW3N5c3RlbU1zZywgdXNlck1zZ10pO1xuICAgICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ21lc3NhZ2UnLCB0aGlzLl9kZWZpbmVNZXNzYWdlQXVkaXREZXRhaWxzKHN5c3RlbU1zZywgMCkpO1xuICAgICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ21lc3NhZ2UnLCB0aGlzLl9kZWZpbmVNZXNzYWdlQXVkaXREZXRhaWxzKHVzZXJNc2csIDEpKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSWYgdGhlIHByb3ZpZGVkIHF1ZXJ5IHRleHQgaXMgbm90IGVtcHR5LCB0aGVuIGFkZCB0aGUgdXNlciBxdWVyeSBtZXNzYWdlIHRvIHRoZSBjaGF0IGhpc3RvcnkgYW5kIGludm9rZSB0aGUgYXNzaXN0YW50XG4gICAqIE90aGVyd2lzZSwganVzdCBzdGFydCBhIG5ldyBjaGF0IHdpdGggYSB3YXJuaW5nIG1lc3NhZ2UgaW52aXRpbmcgdGhlIHVzZXIgdG8gcGVyZm9ybSBhIGZ1bGwgdGV4dCBzZWFyY2ggdG8gcmV0cmlldmUgc29tZSByZXN1bHRzXG4gICAqL1xuICBwcml2YXRlIF9oYW5kbGVRdWVyeU1vZGUoc3lzdGVtTXNnOiBDaGF0TWVzc2FnZSwgdXNlck1zZzogQ2hhdE1lc3NhZ2UpIHtcbiAgICBpZiAoISF0aGlzLnF1ZXJ5LnRleHQpIHtcbiAgICAgIGNvbnN0IHVzZXJRdWVyeU1zZyA9IHtyb2xlOiAndXNlcicsIGNvbnRlbnQ6IHRoaXMucXVlcnkudGV4dCwgYWRkaXRpb25hbFByb3BlcnRpZXM6IHtkaXNwbGF5OiB0aGlzLmNvbmZpZy5tb2RlU2V0dGluZ3MuaW5pdGlhbGl6YXRpb24uZGlzcGxheVVzZXJRdWVyeSwgcXVlcnk6IHRoaXMucXVlcnksIGZvcmNlZFdvcmtmbG93OiB0aGlzLmNvbmZpZy5tb2RlU2V0dGluZ3MuaW5pdGlhbGl6YXRpb24uZm9yY2VkV29ya2Zsb3csIGlzVXNlcklucHV0OiB0cnVlLCBhZGRpdGlvbmFsV29ya2Zsb3dQcm9wZXJ0aWVzOiB0aGlzLmNvbmZpZy5hZGRpdGlvbmFsV29ya2Zsb3dQcm9wZXJ0aWVzfX07XG4gICAgICBpZiAodGhpcy5jb25maWcubW9kZVNldHRpbmdzLnNlbmRVc2VyUHJvbXB0KSB7XG4gICAgICAgIHRoaXMub3BlbkNoYXQoW3N5c3RlbU1zZywgdXNlck1zZywgdXNlclF1ZXJ5TXNnXSk7XG4gICAgICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVBdWRpdEV2ZW50KCdtZXNzYWdlJywgdGhpcy5fZGVmaW5lTWVzc2FnZUF1ZGl0RGV0YWlscyhzeXN0ZW1Nc2csIDApKTtcbiAgICAgICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ21lc3NhZ2UnLCB0aGlzLl9kZWZpbmVNZXNzYWdlQXVkaXREZXRhaWxzKHVzZXJNc2csIDEpKTtcbiAgICAgICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ21lc3NhZ2UnLCB7Li4udGhpcy5fZGVmaW5lTWVzc2FnZUF1ZGl0RGV0YWlscyh1c2VyUXVlcnlNc2csIDIpLCAncXVlcnknOiBKU09OLnN0cmluZ2lmeSh0aGlzLnF1ZXJ5KSAsJ2lzLXVzZXItaW5wdXQnOiB0cnVlLCAnZm9yY2VkLXdvcmtmbG93JzogdGhpcy5jb25maWcubW9kZVNldHRpbmdzLmluaXRpYWxpemF0aW9uLmZvcmNlZFdvcmtmbG93LCAnZW5hYmxlZC1mdW5jdGlvbnMnOiB0aGlzLmNvbmZpZy5kZWZhdWx0VmFsdWVzLmZ1bmN0aW9ucz8uZmlsdGVyKGZ1bmMgPT4gZnVuYy5lbmFibGVkKS5tYXAoZnVuYyA9PiBmdW5jLm5hbWUpLCAnYWRkaXRpb25hbC13b3JrZmxvdy1wcm9wZXJ0aWVzJzpKU09OLnN0cmluZ2lmeSh0aGlzLmNvbmZpZy5hZGRpdGlvbmFsV29ya2Zsb3dQcm9wZXJ0aWVzKX0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5vcGVuQ2hhdChbc3lzdGVtTXNnLCB1c2VyUXVlcnlNc2ddKTtcbiAgICAgICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ21lc3NhZ2UnLCB0aGlzLl9kZWZpbmVNZXNzYWdlQXVkaXREZXRhaWxzKHN5c3RlbU1zZywgMCkpO1xuICAgICAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudCgnbWVzc2FnZScsIHsuLi50aGlzLl9kZWZpbmVNZXNzYWdlQXVkaXREZXRhaWxzKHVzZXJRdWVyeU1zZywgMSksICdxdWVyeSc6IEpTT04uc3RyaW5naWZ5KHRoaXMucXVlcnkpICwnaXMtdXNlci1pbnB1dCc6IHRydWUsICdmb3JjZWQtd29ya2Zsb3cnOiB0aGlzLmNvbmZpZy5tb2RlU2V0dGluZ3MuaW5pdGlhbGl6YXRpb24uZm9yY2VkV29ya2Zsb3csICdlbmFibGVkLWZ1bmN0aW9ucyc6IHRoaXMuY29uZmlnLmRlZmF1bHRWYWx1ZXMuZnVuY3Rpb25zPy5maWx0ZXIoZnVuYyA9PiBmdW5jLmVuYWJsZWQpLm1hcChmdW5jID0+IGZ1bmMubmFtZSksICdhZGRpdGlvbmFsLXdvcmtmbG93LXByb3BlcnRpZXMnOiBKU09OLnN0cmluZ2lmeSh0aGlzLmNvbmZpZy5hZGRpdGlvbmFsV29ya2Zsb3dQcm9wZXJ0aWVzKX0pO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCB3YXJuaW5nTXNnID0ge3JvbGU6ICdzZWFyY2gtd2FybmluZycsIGNvbnRlbnQ6IHRoaXMuY29uZmlnLmdsb2JhbFNldHRpbmdzLnNlYXJjaFdhcm5pbmdNZXNzYWdlLCBhZGRpdGlvbmFsUHJvcGVydGllczoge2Rpc3BsYXk6IHRydWV9fTtcbiAgICAgIHRoaXMub3BlbkNoYXQoW3N5c3RlbU1zZywgd2FybmluZ01zZ10pO1xuICAgICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ21lc3NhZ2UnLCB0aGlzLl9kZWZpbmVNZXNzYWdlQXVkaXREZXRhaWxzKHdhcm5pbmdNc2csIDApKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9kZWZpbmVNZXNzYWdlQXVkaXREZXRhaWxzKG1lc3NhZ2U6IENoYXRNZXNzYWdlLCByYW5rOiBudW1iZXIpOiBSZWNvcmQ8c3RyaW5nLCBhbnk+IHtcbiAgICByZXR1cm4ge1xuICAgICAgJ2R1cmF0aW9uJzogMCxcbiAgICAgICd0ZXh0JzogbWVzc2FnZS5jb250ZW50LFxuICAgICAgJ3JvbGUnOiBtZXNzYWdlLnJvbGUsXG4gICAgICAncmFuayc6IHJhbmtcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFN0YXJ0L29wZW4gYSBuZXcgY2hhdCB3aXRoIHRoZSBwcm92aWRlZCBtZXNzYWdlcyBhbmQgY2hhdElkXG4gICAqIElmIHRoZSBsYXN0IG1lc3NhZ2UgaXMgZnJvbSB0aGUgdXNlciwgYSByZXF1ZXN0IHRvIHRoZSBhc3Npc3RhbnQgaXMgbWFkZSB0byBnZXQgYW4gYW5zd2VyXG4gICAqIElmIHRoZSBsYXN0IG1lc3NhZ2UgaXMgZnJvbSB0aGUgYXNzaXN0YW50LCB0aGUgY29udmVyc2F0aW9uIGlzIGxvYWRlZCByaWdodCBhd2F5XG4gICAqIEBwYXJhbSBtZXNzYWdlcyBUaGUgbGlzdCBvZiBtZXNzYWdlcyBvZiB0aGUgY2hhdFxuICAgKiBAcGFyYW0gc2F2ZWRDaGF0SWQgIFRoZSBpZCBvZiB0aGUgc2F2ZWQgY2hhdC4gSWYgcHJvdmlkZWQgKGllLiBhbiBleGlzdGluZyBkaXNjdXNzaW9uIGluIHRoZSBzYXZlZCBjaGF0IGluZGV4KSwgdXBkYXRlIHRoZSBzYXZlZENoYXRJZCBpbiB0aGUgY2hhdCBzZXJ2aWNlIGZvciB0aGUgdXBjb21pbmcgc2F2ZWQgY2hhdCBvcGVyYXRpb25zXG4gICAqL1xuICBvcGVuQ2hhdChtZXNzYWdlczogUmF3TWVzc2FnZVtdLCBzYXZlZENoYXRJZD86IHN0cmluZykge1xuICAgIGlmICghbWVzc2FnZXMgfHwgIUFycmF5LmlzQXJyYXkobWVzc2FnZXMpKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBvY2N1cnMgd2hpbGUgdHJ5aW5nIHRvIGxvYWQgdGhlIGRpc2N1c3Npb24uIEludmFsaWQgbWVzc2FnZXMgcmVjZWl2ZWQgOicsIG1lc3NhZ2VzKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHNhdmVkQ2hhdElkKSB7XG4gICAgICB0aGlzLmNoYXRTZXJ2aWNlLnNldFNhdmVkQ2hhdElkKHNhdmVkQ2hhdElkKTtcbiAgICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVDaGF0SWQoc2F2ZWRDaGF0SWQpO1xuICAgIH1cbiAgICB0aGlzLnJlc2V0Q2hhdCgpO1xuICAgIHRoaXMubWVzc2FnZXMkLm5leHQobWVzc2FnZXMpO1xuICAgIHRoaXMuY2hhdFNlcnZpY2UuY2hhdEhpc3RvcnkgPSBtZXNzYWdlcztcbiAgICBjb25zdCBsYXN0TWVzc2FnZSA9IG1lc3NhZ2VzLmF0KC0xKTtcbiAgICBpZihsYXN0TWVzc2FnZSAmJiBsYXN0TWVzc2FnZS5yb2xlID09PSAndXNlcicpIHtcbiAgICAgIHRoaXMuZmV0Y2gobWVzc2FnZXMpOyAvLyBJZiB0aGUgbGFzdCBtZXNzYWdlIGlmIGZyb20gYSB1c2VyLCBhbiBhbnN3ZXIgZnJvbSB0aGUgYXNzaXN0YW50IGlzIGV4cGVjdGVkXG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgdGhpcy51cGRhdGVEYXRhKG1lc3NhZ2VzKTsgLy8gSWYgdGhlIGxhc3QgbWVzc2FnZSBpZiBmcm9tIHRoZSBhc3Npc3RhbnQsIHdlIGNhbiBsb2FkIHRoZSBjb252ZXJzYXRpb24gcmlnaHQgYXdheVxuICAgICAgdGhpcy50ZXJtaW5hdGVGZXRjaCgpO1xuICAgIH1cbiAgICB0aGlzLl9hZGRTY3JvbGxMaXN0ZW5lcigpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc2V0IHRoZSBjaGF0IGJ5IGNsZWFyaW5nIHRoZSBjaGF0IGhpc3RvcnkgYW5kIHRoZSBVSSBhY2NvcmRpbmdseVxuICAgKiBUaGUgdXNlciBpbnB1dCB3aWxsIGJlIGNsZWFyZWRcbiAgICogVGhlIGZldGNoIHN1YnNjcmlwdGlvbiB3aWxsIGJlIHRlcm1pbmF0ZWRcbiAgICovXG4gIHJlc2V0Q2hhdCgpIHtcbiAgICBpZih0aGlzLm1lc3NhZ2VzJC52YWx1ZSkge1xuICAgICAgdGhpcy5tZXNzYWdlcyQubmV4dCh1bmRlZmluZWQpOyAvLyBSZXNldCBjaGF0XG4gICAgfVxuICAgIHRoaXMuY2hhdFNlcnZpY2UuY2hhdEhpc3RvcnkgPSB1bmRlZmluZWQ7IC8vIFJlc2V0IGNoYXQgaGlzdG9yeVxuICAgIHRoaXMucXVlc3Rpb24gPSAnJztcbiAgICB0aGlzLnRlcm1pbmF0ZUZldGNoKCk7XG4gIH1cblxuICAvKipcbiAgICogRmV0Y2ggYW5kIExvYWQgdGhlIHNhdmVkIGNoYXQgZnJvbSB0aGUgc2F2ZWQgY2hhdCBpbmRleC5cbiAgICogSWYgdGhlIHNhdmVkIGNoYXQgaXMgZm91bmQsIHRoZSBjaGF0IGRpc2N1c3Npb24gd2lsbCBiZSBsb2FkZWQgd2l0aCB0aGUgcHJvdmlkZWQgbWVzc2FnZXMgYW5kIGNoYXRJZFxuICAgKi9cbiAgb25Mb2FkQ2hhdCgpIHtcbiAgICB0aGlzLmxvYWRpbmckLm5leHQodHJ1ZSk7XG4gICAgdGhpcy5fc3ViLmFkZChcbiAgICAgIHRoaXMuY2hhdFNlcnZpY2UubG9hZFNhdmVkQ2hhdCRcbiAgICAgICAgLnBpcGUoXG4gICAgICAgICAgZmlsdGVyKHNhdmVkQ2hhdCA9PiAhIXNhdmVkQ2hhdCksXG4gICAgICAgICAgc3dpdGNoTWFwKHNhdmVkQ2hhdCA9PiB0aGlzLmNoYXRTZXJ2aWNlLmdldFNhdmVkQ2hhdChzYXZlZENoYXQhLmlkKSksXG4gICAgICAgICAgZmlsdGVyKHNhdmVkQ2hhdEhpc3RvcnkgPT4gISFzYXZlZENoYXRIaXN0b3J5KSxcbiAgICAgICAgICB0YXAoc2F2ZWRDaGF0SGlzdG9yeSA9PiB0aGlzLm9wZW5DaGF0KHNhdmVkQ2hhdEhpc3RvcnkhLmhpc3RvcnksIHNhdmVkQ2hhdEhpc3RvcnkhLmlkKSlcbiAgICAgICAgKS5zdWJzY3JpYmUoKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogU3RvcCB0aGUgZ2VuZXJhdGlvbiBvZiB0aGUgY3VycmVudCBhc3Npc3RhbnQncyBhbnN3ZXIuXG4gICAqIFRoZSBmZXRjaCBzdWJzY3JpcHRpb24gd2lsbCBiZSB0ZXJtaW5hdGVkLlxuICAgKi9cbiAgc3RvcEdlbmVyYXRpb24oKSB7XG4gICAgdGhpcy5jaGF0U2VydmljZS5zdG9wR2VuZXJhdGlvbigpLnN1YnNjcmliZShcbiAgICAgICgpID0+IHRoaXMudGVybWluYXRlRmV0Y2goKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogVGVybWluYXRlIHRoZSBmZXRjaCBwcm9jZXNzIGJ5IHVuc3Vic2NyaWJpbmcgZnJvbSB0aGUgZGF0YSBzdWJzY3JpcHRpb24gYW5kIHVwZGF0aW5nIHRoZSBsb2FkaW5nIHN0YXR1cyB0byBmYWxzZS5cbiAgICogQWRkaXRpb25hbGx5LCBmb2N1cyBvbiB0aGUgY2hhdCBpbnB1dCBpZiB0aGUgZm9jdXNBZnRlclJlc3BvbnNlIGZsYWcgaXMgc2V0IHRvIHRydWUuXG4gICAqL1xuICB0ZXJtaW5hdGVGZXRjaCgpIHtcbiAgICB0aGlzLl9kYXRhU3Vic2NyaXB0aW9uPy51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMuX2RhdGFTdWJzY3JpcHRpb24gPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5sb2FkaW5nJC5uZXh0KGZhbHNlKTtcbiAgICB0aGlzLmNkci5kZXRlY3RDaGFuZ2VzKCk7XG5cbiAgICBpZiAodGhpcy5mb2N1c0FmdGVyUmVzcG9uc2UpIHtcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICB0aGlzLnF1ZXN0aW9uSW5wdXQ/Lm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDb3B5IGEgcHJldmlvdXMgdXNlciBtZXNzYWdlIG9mIHRoZSBjaGF0IGhpc3RvcnkgdG8gdGhlIGNoYXQgdXNlciBpbnB1dC5cbiAgICogVGh1cywgdGhlIHVzZXIgY2FuIGVkaXQgYW5kIHJlc3VibWl0IHRoZSBtZXNzYWdlLlxuICAgKiBPbmNlIHRoZSBlZGl0ZWQgbWVzc2FnZSBpcyBzdWJtaXR0ZWQsIGFsbCBzdWJzZXF1ZW50IG1lc3NhZ2VzIHN0YXJ0aW5nIGZyb20gQHBhcmFtIGluZGV4IHdpbGwgYmUgcmVtb3ZlZCBmcm9tIHRoZSBoaXN0b3J5IGFuZCB0aGUgVUkgd2lsbCBiZSB1cGRhdGVkIGFjY29yZGluZ2x5LlxuICAgKiBUaGUgYXNzaXN0YW50IHdpbGwgcmVnZW5lcmF0ZSBhIG5ldyBhbnN3ZXIgYmFzZWQgb24gdGhlIHVwZGF0ZWQgY2hhdCBoaXN0b3J5LlxuICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSB1c2VyJ3MgbWVzc2FnZSB0byBlZGl0XG4gICAqL1xuICBlZGl0TWVzc2FnZShpbmRleDogbnVtYmVyKSB7XG4gICAgdGhpcy5tZXNzYWdlVG9FZGl0ID0gaW5kZXg7XG4gICAgdGhpcy5yZW1hcHBlZE1lc3NhZ2VUb0VkaXQgPSB0aGlzLl9yZW1hcEluZGV4SW5DaGF0SGlzdG9yeShpbmRleCk7XG4gICAgdGhpcy5xdWVzdGlvbiA9IHRoaXMuY2hhdFNlcnZpY2UuY2hhdEhpc3RvcnkhW3RoaXMuX3JlbWFwSW5kZXhJbkNoYXRIaXN0b3J5KGluZGV4KV0uY29udGVudDtcbiAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudCgnZWRpdC5jbGljaycsIHsncmFuayc6IHRoaXMuX3JlbWFwSW5kZXhJbkNoYXRIaXN0b3J5KGluZGV4KX0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENvcHkgYSBwcmV2aW91cyBhc3Npc3RhbnQgbWVzc2FnZSBvZiB0aGUgY2hhdCBoaXN0b3J5IHRvIHRoZSBjbGlwYm9hcmQuXG4gICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGFzc2lzdGFudCdzIG1lc3NhZ2UgdG8gZWRpdFxuICAgKi9cbiAgY29weU1lc3NhZ2UoaW5kZXg6IG51bWJlcikge1xuICAgIC8vIFJlbWFwIHRoZSBpbmRleCBpbiB0aGUgY2hhdCBoaXN0b3J5XG4gICAgY29uc3QgaWR4ID0gdGhpcy5fcmVtYXBJbmRleEluQ2hhdEhpc3RvcnkoaW5kZXgpO1xuICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVBdWRpdEV2ZW50KCdjb3B5LmNsaWNrJywgeydyYW5rJzogaWR4fSk7XG4gIH1cblxuICAvKipcbiAgICogU3RhcnRpbmcgZnJvbSB0aGUgcHJvdmlkZWQgaW5kZXgsIHJlbW92ZSBhbGwgc3Vic2VxdWVudCBtZXNzYWdlcyBmcm9tIHRoZSBjaGF0IGhpc3RvcnkgYW5kIHRoZSBVSSBhY2NvcmRpbmdseS5cbiAgICogVGhlIGFzc2lzdGFudCB3aWxsIHJlZ2VuZXJhdGUgYSBuZXcgYW5zd2VyIGJhc2VkIG9uIHRoZSB1cGRhdGVkIGNoYXQgaGlzdG9yeS5cbiAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgYXNzaXN0YW50J3MgbWVzc2FnZSB0byByZWdlbmVyYXRlXG4gICAqL1xuICByZWdlbmVyYXRlTWVzc2FnZShpbmRleDogbnVtYmVyKSB7XG4gICAgLy8gVXBkYXRlIHRoZSBtZXNzYWdlcyBpbiB0aGUgVUkgYnkgcmVtb3ZpbmcgYWxsIHN1YnNlcXVlbnQgJ2Fzc2lzdGFudCcgbWVzc2FnZXMgc3RhcnRpbmcgZnJvbSB0aGUgcHJvdmlkZWQgaW5kZXggdW50aWwgdGhlIGZpcnN0IHByZXZpb3VzICd1c2VyJyBtZXNzYWdlXG4gICAgbGV0IGkgPSBpbmRleDtcbiAgICB3aGlsZSAoaSA+PSAwICYmICh0aGlzLm1lc3NhZ2VzJC52YWx1ZSEpW2ldLnJvbGUgIT09ICd1c2VyJykge1xuICAgICAgaS0tO1xuICAgIH1cbiAgICAvLyBJdCBzaG91bGQgYWx3YXlzIGJlIHRoZSBjYXNlIHRoYXQgaSA+IDBcbiAgICBpZiAoaSA+PSAwKSB7XG4gICAgICB0aGlzLm1lc3NhZ2VzJC5uZXh0KHRoaXMubWVzc2FnZXMkLnZhbHVlIS5zbGljZSgwLCBpKzEpKTtcbiAgICAgIC8vIFJlbWFwIHRoZSBpbmRleCBvZiB0aGlzIGZvdW5kIGZpcnN0IHByZXZpb3VzICd1c2VyJyBtZXNzYWdlIGluIHRoZSBjaGF0IGhpc3RvcnlcbiAgICAgIGNvbnN0IGlkeCA9IHRoaXMuX3JlbWFwSW5kZXhJbkNoYXRIaXN0b3J5KGkpO1xuICAgICAgLy8gRGVmaW5lIGFuZCBVcGRhdGUgdGhlIGNoYXQgaGlzdG9yeSBiYXNlZCBvbiB3aGljaCB0aGUgYXNzaXN0YW50IHdpbGwgZ2VuZXJhdGUgYSBuZXcgYW5zd2VyXG4gICAgICB0aGlzLmNoYXRTZXJ2aWNlLmNoYXRIaXN0b3J5ID0gdGhpcy5jaGF0U2VydmljZS5jaGF0SGlzdG9yeSEuc2xpY2UoMCwgaWR4KzEpO1xuICAgICAgLy8gRmV0Y2ggdGhlIGFuc3dlclxuICAgICAgdGhpcy5mZXRjaCh0aGlzLmNoYXRTZXJ2aWNlLmNoYXRIaXN0b3J5KTtcbiAgICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVBdWRpdEV2ZW50KCdyZWdlbmVyYXRlLmNsaWNrJywgeydyYW5rJzogaWR4fSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlbWFwcyB0aGUgaW5kZXggaW4gdGhlIGNoYXQgaGlzdG9yeS5cbiAgICogVGhlIGNoYXQgaGlzdG9yeSBpcyBhIGxpc3Qgb2YgbWVzc2FnZXMgd2hlcmUgc29tZSBtZXNzYWdlcyBjYW4gYmUgaGlkZGVuIChkaXNwbGF5IHNldCB0byBmYWxzZSkuXG4gICAqIFRoZSBpbmRleCBwcm92aWRlZCBhcyBpbnB1dCBpcyB0aGUgaW5kZXggb2YgdGhlIG1lc3NhZ2UgaW4gdGhlIGNoYXQgaGlzdG9yeSBkaXNwbGF5ZWQgaW4gdGhlIFVJLlxuICAgKiBUaGlzIGZ1bmN0aW9uIHNob3VsZCBiZSByZW1vdmVkIG9uY2UgdGhlIGJhY2tlbmQgaXMgdXBkYXRlZCB0byBhZGQgdGhlIGlkcyBvZiB0aGUgbWVzc2FnZXMgaW4gdGhlIGNoYXQgaGlzdG9yeVxuICAgKiBAcGFyYW0gaW5kZXggLSBUaGUgaW5kZXggdG8gYmUgcmVtYXBwZWQuXG4gICAqL1xuICBwcml2YXRlIF9yZW1hcEluZGV4SW5DaGF0SGlzdG9yeShpbmRleDogbnVtYmVyKSB7XG4gICAgLy8gYSBjb3B5IG9mIHRoZSBjaGF0IGhpc3RvcnkgaXMgY3JlYXRlZCB0byBhdm9pZCBtb2RpZnlpbmcgdGhlIG9yaWdpbmFsIGNoYXQgaGlzdG9yeS4gQWRkaXRpb25hbGx5LCBhIHJhbmsgaXMgZ2l2aW5nIHRvIGVhY2ggbWVzc2FnZS5cbiAgICBjb25zdCBoaXN0b3J5ID0gdGhpcy5jaGF0U2VydmljZS5jaGF0SGlzdG9yeSEuc2xpY2UoKS5tYXAoKG1lc3NhZ2UsIGlkeCkgPT4ge1xuICAgICAgcmV0dXJuIHsuLi5tZXNzYWdlLCBhZGRpdGlvbmFsUHJvcGVydGllczogey4uLm1lc3NhZ2UuYWRkaXRpb25hbFByb3BlcnRpZXMsIHJhbms6IGlkeH19O1xuICAgIH0pO1xuICAgIC8vIENvdW50IHRoZSBudW1iZXIgb2YgaGlkZGVuIG1lc3NhZ2VzIGluIG1lc3NhZ2VzJCBiZWZvcmUgdGhlIHByb3ZpZGVkIGluZGV4XG4gICAgLy8gVGhpcyBpcyBtYW5kYXRvcnkgdG8gZ2V0IHRoZSBjb3JyZWN0IHJhbmsgb2YgdGhlIG1lc3NhZ2UgaW4gdGhlIGNoYXQgaGlzdG9yeVxuICAgIC8vIFNpbmNlIHNvbWUgaGlkZGVuIG1lc3NhZ2VzIChsaWtlICdzeXN0ZW0nIG1lc3NhZ2VzKSBhcmUgbm90IGRpc3BsYXllZCBpbiB0aGUgVUkgYnV0IGhhdmUgYmVlbiBjb3VudGVkIGluIHRoZSBwcm92aWRlZCBpbmRleFxuICAgIGNvbnN0IG51bWJlck9mSGlkZGVuTWVzc2FnZXNJbk1lc3NhZ2VzJEJlZm9yZUluZGV4ID0gdGhpcy5tZXNzYWdlcyQudmFsdWUhLnNsaWNlKDAsIGluZGV4KS5maWx0ZXIobWVzc2FnZSA9PiAhbWVzc2FnZS5hZGRpdGlvbmFsUHJvcGVydGllcy5kaXNwbGF5KS5sZW5ndGg7XG4gICAgLy8gcmVtb3ZlIGFsbCBtZXNzYWdlcyB0aGF0IGhhdmUgZGlzcGxheSBzZXQgdG8gZmFsc2VcbiAgICAvLyB0aGlzIGlzIG1hbmRhdG9yeSBzaW5jZSBhdCB0aGUgcG9pbnQgb2YgdGltZSB3aGVuIHRoZSBhc3Npc3RhbnQgYW5zd2VycyBhIHF1ZXN0aW9uLFxuICAgIC8vIGl0IG1pZ2h0IGhhdmUgc29tZSBoaWRkZW4gbWVzc2FnZXMgKGZvciBleGFtcGxlIGNvbnRleHRNZXNzYWdlcykgdGhhdCBhcmUgYXZhaWxhYmxlIGluIHRoZSBjaGF0IGhpc3RvcnkgYnV0IGRvbid0IGZpZ3VyZSBpbiBtZXNzYWdlcyQgdW5sZXNzIGEgbmV3IHF1ZXN0aW9uIGlzIGFza2VkXG4gICAgY29uc3QgZmlsdGVyZWRIaXN0b3J5ID0gaGlzdG9yeS5maWx0ZXIobWVzc2FnZSA9PiBtZXNzYWdlLmFkZGl0aW9uYWxQcm9wZXJ0aWVzLmRpc3BsYXkpO1xuICAgIC8vIHJldHVybiB0aGUgaW5kZXggb2YgdGhlIG1lc3NhZ2UgaW4gdGhlIGZpbHRlcmVkIGhpc3RvcnlcbiAgICByZXR1cm4gZmlsdGVyZWRIaXN0b3J5W2luZGV4IC0gbnVtYmVyT2ZIaWRkZW5NZXNzYWdlc0luTWVzc2FnZXMkQmVmb3JlSW5kZXhdLmFkZGl0aW9uYWxQcm9wZXJ0aWVzLnJhbms7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBIYW5kbGVzIHRoZSBrZXkgdXAgZXZlbnQgZm9yICdCYWNrc3BhY2UnIGFuZCAnRW50ZXInIGtleXMuXG4gICAqIEBwYXJhbSBldmVudCAtIFRoZSBrZXlib2FyZCBldmVudC5cbiAgICovXG4gIG9uS2V5VXAoZXZlbnQ6IEtleWJvYXJkRXZlbnQpOiB2b2lkIHtcbiAgICBzd2l0Y2ggKGV2ZW50LmtleSkge1xuICAgICAgY2FzZSAnQmFja3NwYWNlJzpcbiAgICAgICAgdGhpcy5jYWxjdWxhdGVIZWlnaHQoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdFbnRlcic6XG4gICAgICAgIGlmICghZXZlbnQuc2hpZnRLZXkpIHtcbiAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgIHRoaXMuc3VibWl0UXVlc3Rpb24oKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNhbGN1bGF0ZUhlaWdodCgpO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxjdWxhdGVzIGFuZCBhZGp1c3RzIHRoZSBoZWlnaHQgb2YgdGhlIHF1ZXN0aW9uIGlucHV0IGVsZW1lbnQgYmFzZWQgb24gaXRzIGNvbnRlbnQuXG4gICAqIElmIHRoZSBFbnRlciBrZXkgaXMgcHJlc3NlZCB3aXRob3V0IHRoZSBTaGlmdCBrZXksIGl0IHByZXZlbnRzIHRoZSBkZWZhdWx0IGJlaGF2aW9yLlxuICAgKiBAcGFyYW0gZXZlbnQgVGhlIGtleWJvYXJkIGV2ZW50XG4gICAqL1xuICBjYWxjdWxhdGVIZWlnaHQoZXZlbnQ/OiBLZXlib2FyZEV2ZW50KTogdm9pZCB7XG4gICAgaWYgKGV2ZW50Py5rZXkgPT09ICdFbnRlcicgJiYgIWV2ZW50LnNoaWZ0S2V5KSB7XG4gICAgICBldmVudD8ucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG4gICAgY29uc3QgbWF4SGVpZ2h0ID0gMTcwO1xuICAgIGNvbnN0IGVsID0gdGhpcy5xdWVzdGlvbklucHV0IS5uYXRpdmVFbGVtZW50O1xuICAgIGVsLnN0eWxlLm1heEhlaWdodCA9IGAke21heEhlaWdodH1weGA7XG4gICAgZWwuc3R5bGUuaGVpZ2h0ID0gJ2F1dG8nO1xuICAgIGVsLnN0eWxlLmhlaWdodCA9IGAke2VsLnNjcm9sbEhlaWdodH1weGA7XG4gICAgZWwuc3R5bGUub3ZlcmZsb3dZID0gZWwuc2Nyb2xsSGVpZ2h0ID49IG1heEhlaWdodCA/ICdzY3JvbGwnIDogJ2hpZGRlbic7XG4gIH1cblxuICAvKipcbiAgICogU2VuZCBhIFwibGlrZVwiIGV2ZW50IG9uIGNsaWNraW5nIG9uIHRoZSB0aHVtYi11cCBpY29uIG9mIGFuIGFzc2lzdGFudCdzIG1lc3NhZ2VcbiAgICogQHBhcmFtIG1lc3NhZ2UgVGhlIGFzc2lzdGFudCBtZXNzYWdlIHRvIGxpa2VcbiAgICogQHBhcmFtIHJhbmsgVGhlIHJhbmsgb2YgdGhlIG1lc3NhZ2UgdG8gbGlrZVxuICAgKi9cbiAgb25MaWtlKG1lc3NhZ2U6IENoYXRNZXNzYWdlLCByYW5rOiBudW1iZXIpOiB2b2lkIHtcbiAgICAvLyBSZW1hcCB0aGUgaW5kZXggaW4gdGhlIGNoYXQgaGlzdG9yeVxuICAgIGNvbnN0IGlkeCA9IHRoaXMuX3JlbWFwSW5kZXhJbkNoYXRIaXN0b3J5KHJhbmspO1xuICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVBdWRpdEV2ZW50KCd0aHVtYi11cC5jbGljaycsIHtyYW5rOiBpZHh9KTtcbiAgICB0aGlzLnJlcG9ydFR5cGUgPSAnbGlrZSc7XG4gICAgdGhpcy5tZXNzYWdlVG9SZXBvcnQgPSBtZXNzYWdlO1xuICAgIHRoaXMucmVwb3J0Q29tbWVudCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLnJlcG9ydFJhbmsgPSByYW5rO1xuICAgIHRoaXMuc2hvd1JlcG9ydCA9IHRydWVcbiAgfVxuXG5cbiAgLyoqXG4gICAqIFNlbmQgYSBcImRpc2xpa2VcIiBldmVudCBvbiBjbGlja2luZyBvbiB0aGUgdGh1bWItZG93biBpY29uIG9mIGFuIGFzc2lzdGFudCdzIG1lc3NhZ2UuXG4gICAqIEl0IGFsc28gb3BlbnMgdGhlIGlzc3VlIHJlcG9ydGluZyBkaWFsb2cuXG4gICAqIEBwYXJhbSBtZXNzYWdlIFRoZSBhc3Npc3RhbnQgbWVzc2FnZSB0byBkaXNsaWtlXG4gICAqIEBwYXJhbSBpbmRleCBUaGUgcmFuayBvZiB0aGUgbWVzc2FnZSB0byBkaXNsaWtlXG4gICAqL1xuICBvbkRpc2xpa2UobWVzc2FnZTogQ2hhdE1lc3NhZ2UsIHJhbms6IG51bWJlcik6IHZvaWQge1xuICAgIC8vIFJlbWFwIHRoZSBpbmRleCBpbiB0aGUgY2hhdCBoaXN0b3J5XG4gICAgY29uc3QgaWR4ID0gdGhpcy5fcmVtYXBJbmRleEluQ2hhdEhpc3RvcnkocmFuayk7XG4gICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ3RodW1iLWRvd24uY2xpY2snLCB7cmFuazogaWR4fSk7XG4gICAgdGhpcy5yZXBvcnRUeXBlID0gJ2Rpc2xpa2UnO1xuICAgIHRoaXMubWVzc2FnZVRvUmVwb3J0ID0gbWVzc2FnZTtcbiAgICB0aGlzLmlzc3VlVHlwZSA9ICcnO1xuICAgIHRoaXMucmVwb3J0Q29tbWVudCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLnJlcG9ydFJhbmsgPSByYW5rO1xuICAgIHRoaXMuc2hvd1JlcG9ydCA9IHRydWVcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXBvcnQgYW4gaXNzdWUgcmVsYXRlZCB0byB0aGUgYXNzaXN0YW50J3MgbWVzc2FnZS5cbiAgICovXG4gIHNlbmRSZXBvcnQoKTogdm9pZCB7XG4gICAgY29uc3QgZGV0YWlscyA9IHtcbiAgICAgICdjb21tZW50JzogdGhpcy5yZXBvcnRDb21tZW50LFxuICAgICAgJ3RleHQnOiB0aGlzLm1lc3NhZ2VUb1JlcG9ydCEuY29udGVudCxcbiAgICAgICdyYW5rJzogdGhpcy5yZXBvcnRSYW5rLFxuICAgIH07XG4gICAgaWYgKHRoaXMucmVwb3J0VHlwZSA9PT0gJ2Rpc2xpa2UnKSB7XG4gICAgICBkZXRhaWxzWydyZXBvcnQtdHlwZSddID0gdGhpcy5pc3N1ZVR5cGU7XG4gICAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudCgnbmVnYXRpdmUtcmVwb3J0LnNlbmQnLCBkZXRhaWxzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ3Bvc2l0aXZlLXJlcG9ydC5zZW5kJywgZGV0YWlscyk7XG4gICAgfVxuICAgIHRoaXMuc2hvd1JlcG9ydCA9IGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIENsb3NlIHRoZSByZXBvcnRpbmcgZGlhbG9nLlxuICAgKi9cbiAgaWdub3JlUmVwb3J0KCk6IHZvaWQge1xuICAgIHRoaXMuc2hvd1JlcG9ydCA9IGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZSB0aGUgY2xpY2sgb24gYSByZWZlcmVuY2UncyAnb3BlbiBwcmV2aWV3Jy5cbiAgICogQHBhcmFtIGRhdGFcbiAgICovXG4gIG9wZW5BdHRhY2htZW50UHJldmlldyhkYXRhOiB7cmVmZXJlbmNlOiBDaGF0Q29udGV4dEF0dGFjaG1lbnQsIHBhcnRJZD86IG51bWJlcn0pIHtcbiAgICB0aGlzLm9wZW5QcmV2aWV3LmVtaXQoZGF0YS5yZWZlcmVuY2UpO1xuICAgIGNvbnN0IGRldGFpbHMgPSB7XG4gICAgICAnZG9jLWlkJzogZGF0YS5yZWZlcmVuY2UucmVjb3JkSWQsXG4gICAgICAndGl0bGUnOiBkYXRhLnJlZmVyZW5jZS5yZWNvcmQudGl0bGUsXG4gICAgICAnc291cmNlJzogZGF0YS5yZWZlcmVuY2UucmVjb3JkLnRyZWVwYXRoLFxuICAgICAgJ2NvbGxlY3Rpb24nOiBkYXRhLnJlZmVyZW5jZS5yZWNvcmQuY29sbGVjdGlvbixcbiAgICAgICdpbmRleCc6IGRhdGEucmVmZXJlbmNlLnJlY29yZC5kYXRhYmFzZWFsaWFzLFxuICAgIH07XG4gICAgaWYoISFkYXRhLnBhcnRJZCkgZGV0YWlsc1sncGFydC1pZCddID0gZGF0YS5wYXJ0SWQ7XG4gICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ2F0dGFjaG1lbnQucHJldmlldy5jbGljaycsIGRldGFpbHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZSB0aGUgY2xpY2sgb24gYSByZWZlcmVuY2UncyAnb3BlbiBvcmlnaW5hbCBkb2N1bWVudCcuXG4gICAqIEBwYXJhbSBkYXRhXG4gICAqL1xuICBvcGVuT3JpZ2luYWxBdHRhY2htZW50KGRhdGE6IHtyZWZlcmVuY2U6IENoYXRDb250ZXh0QXR0YWNobWVudCwgcGFydElkPzogbnVtYmVyfSkge1xuICAgIHRoaXMub3BlbkRvY3VtZW50LmVtaXQoZGF0YS5yZWZlcmVuY2UucmVjb3JkKTtcbiAgICBjb25zdCBkZXRhaWxzID0ge1xuICAgICAgJ2RvYy1pZCc6IGRhdGEucmVmZXJlbmNlLnJlY29yZElkLFxuICAgICAgJ3RpdGxlJzogZGF0YS5yZWZlcmVuY2UucmVjb3JkLnRpdGxlLFxuICAgICAgJ3NvdXJjZSc6IGRhdGEucmVmZXJlbmNlLnJlY29yZC50cmVlcGF0aCxcbiAgICAgICdjb2xsZWN0aW9uJzogZGF0YS5yZWZlcmVuY2UucmVjb3JkLmNvbGxlY3Rpb24sXG4gICAgICAnaW5kZXgnOiBkYXRhLnJlZmVyZW5jZS5yZWNvcmQuZGF0YWJhc2VhbGlhcyxcbiAgICB9O1xuICAgIGlmKCEhZGF0YS5wYXJ0SWQpIGRldGFpbHNbJ3BhcnQtaWQnXSA9IGRhdGEucGFydElkO1xuICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVBdWRpdEV2ZW50KCdhdHRhY2htZW50LmxpbmsuY2xpY2snLCBkZXRhaWxzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGUgdGhlIGNsaWNrIG9uIGEgc3VnZ2VzdGVkIGFjdGlvbi5cbiAgICogQHBhcmFtIGFjdGlvbiBTdWdnZXN0ZWQgYWN0aW9uLlxuICAgKiBAcGFyYW0gaW5kZXggUmFuayBvZiB0aGUgbWVzc2FnZSBpbiB0aGUgY2hhdEhpc3RvcnkgcmVsYXRlZCB0byB0aGUgc3VnZ2VzdGVkIGFjdGlvbi5cbiAgICovXG4gIHN1Z2dlc3RBY3Rpb25DbGljayhhY3Rpb246IFN1Z2dlc3RlZEFjdGlvbiwgaW5kZXg6IG51bWJlcikge1xuICAgIHRoaXMuc3VnZ2VzdEFjdGlvbi5lbWl0KGFjdGlvbik7XG4gICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ3N1Z2dlc3RlZEFjdGlvbi5jbGljaycsIHsndGV4dCc6IGFjdGlvbi5jb250ZW50LCAnc3VnZ2VzdGVkQWN0aW9uLXR5cGUnOiBhY3Rpb24udHlwZX0pXG4gIH1cblxuICAvKipcbiAgICogSGFuZGxlIHRoZSBjbGljayBvbiBhIGNoYXQgc3RhcnRlci5cbiAgICogQHBhcmFtIHN0YXJ0ZXIgdGhlIGNoYXQgc3RhcnRlci5cbiAgICovXG4gIGNoYXRTdGFydGVyQ2xpY2soc3RhcnRlcjogQ2hhdFN0YXJ0ZXIpIHtcbiAgICB0aGlzLmNoYXRTdGFydGVyLmVtaXQoc3RhcnRlcik7XG4gIH1cblxuICAvKipcbiAgICogSXQgbG9va3MgZm9yIHRoZSBkZWJ1ZyBtZXNzYWdlcyBhdmFpbGFibGUgaW4gdGhlIGN1cnJlbnQgZ3JvdXAgb2YgXCJhc3Npc3RhbnRcIiBtZXNzYWdlcy5cbiAgICogQnkgZGVzaWduLCB0aGUgZGVidWcgbWVzc2FnZXMgYXJlIG9ubHkgYXZhaWxhYmxlIGluIHRoZSBmaXJzdCB2aXNpYmxlIG1lc3NhZ2UgYW1vbmcgdGhlIGdyb3VwIFwiYXNzaXN0YW50XCIgbWVzc2FnZXMuXG4gICAqIEBwYXJhbSBpbmRleCBUaGUgcmFuayBvZiB0aGUgbWVzc2FnZVxuICAgKiBAcmV0dXJucyBUaGUgZGVidWcgbWVzc2FnZXMgYXZhaWxhYmxlIGluIHRoZSBjdXJyZW50IGdyb3VwIG9mIFwiYXNzaXN0YW50XCIgbWVzc2FnZXNcbiAgICovXG4gIGdldERlYnVnTWVzc2FnZXMoaW5kZXg6IG51bWJlcik6IERlYnVnTWVzc2FnZVtdIHtcbiAgICAvLyBJZiBpdCBpcyBub3QgYW4gYXNzaXN0YW50IG1lc3NhZ2UsIHJldHVyblxuICAgIGlmICgodGhpcy5tZXNzYWdlcyQudmFsdWUhKVtpbmRleF0ucm9sZSAhPT0gJ2Fzc2lzdGFudCcpIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG4gICAgLy8gR2V0IHRoZSBhcnJheSBvZiBtZXNzYWdlcyB1cCB0byB0aGUgaW5kaWNhdGVkIGluZGV4XG4gICAgY29uc3QgYXJyYXkgPSB0aGlzLm1lc3NhZ2VzJC52YWx1ZSEuc2xpY2UoMCwgaW5kZXggKyAxKTtcbiAgICAvLyBJZiBpdCBpcyBhbiBhc3Npc3RhbnQgbWVzc2FnZSwgbG9vayBmb3IgdGhlIGRlYnVnIG1lc3NhZ2VzIGF2YWlsYWJsZSBpbiB0aGUgY3VycmVudCBncm91cCBvZiBcImFzc2lzdGFudFwiIG1lc3NhZ2VzXG4gICAgLy8gQnkgZGVzaWduLCB0aGUgZGVidWcgbWVzc2FnZXMgYXJlIG9ubHkgYXZhaWxhYmxlIGluIHRoZSBmaXJzdCB2aXNpYmxlIG1lc3NhZ2UgYW1vbmcgdGhlIGdyb3VwIFwiYXNzaXN0YW50XCIgbWVzc2FnZXMuXG4gICAgY29uc3QgaWR4ID0gdGhpcy5jaGF0U2VydmljZS5maXJzdFZpc2libGVBc3Npc3RhbnRNZXNzYWdlSW5kZXgoYXJyYXkpO1xuICAgIGlmIChpZHggPiAtMSkge1xuICAgICAgcmV0dXJuICh0aGlzLm1lc3NhZ2VzJC52YWx1ZSEpW2lkeF0uYWRkaXRpb25hbFByb3BlcnRpZXMuJGRlYnVnIHx8IFtdO1xuICAgIH1cbiAgICByZXR1cm4gW107XG4gIH1cblxuICAvKipcbiAgICogSGFuZGxlIHRoZSBjbGljayBvbiB0aGUgJ3Nob3cgbG9nIGluZm8nIGJ1dHRvbiBvZiBhIG1lc3NhZ2UuXG4gICAqIEBwYXJhbSBpbmRleCBUaGUgcmFuayBvZiB0aGUgbWVzc2FnZVxuICAgKi9cbiAgc2hvd0RlYnVnKGluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLmRlYnVnTWVzc2FnZXMgPSB0aGlzLmdldERlYnVnTWVzc2FnZXMoaW5kZXgpO1xuICAgIHRoaXMuc2hvd0RlYnVnTWVzc2FnZXMgPSB0cnVlO1xuICAgIHRoaXMuY2RyLmRldGVjdENoYW5nZXMoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWZXJpZnkgd2hldGhlciB0aGUgY3VycmVudCBtZXNzYWdlIGlzIGFuIGFzc2lzdGFudCBtZXNzYWdlIGFuZCB0aGF0IGFsbCBmb2xsb3dpbmcgbWVzc2FnZXMgYXJlIGFzc2lzdGFudCBvbmVzXG4gICAqIFVzZWQgdG8ga2VlcCB0aGUgXCJWaWV3IHByb2dyZXNzXCIgb3BlbmVkIGV2ZW4gdGhvdWdoIHRoZSBhc3Npc3RhbnQgaXMgc2VuZGluZyBhZGRpdGlvbmFsIG1lc3NhZ2VzIGFmdGVyIHRoZSBjdXJyZW50IG9uZVxuICAgKiBAcGFyYW0gbWVzc2FnZXMgdGhlIGxpc3Qgb2YgY3VycmVudCBtZXNzYWdlc1xuICAgKiBAcGFyYW0gaW5kZXggdGhlIGluZGV4IG9mIHRoZSBjdXJyZW50IG1lc3NhZ2VcbiAgICogQHJldHVybnMgaWYgdGhpcyBtZXNzYWdlcyBhbmQgdGhlIGZvbGxvd2luZyBvbmVzIChpZiBhbnkpIGFyZSB0aGUgbGFzdCBvbmVzXG4gICAqL1xuICBpc0Fzc2lzdGFudExhc3RNZXNzYWdlcyhtZXNzYWdlczogQ2hhdE1lc3NhZ2VbXSwgaW5kZXg6IG51bWJlcik6IGJvb2xlYW4ge1xuICAgIGZvciAobGV0IGkgPSBpbmRleDsgaSA8IG1lc3NhZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAobWVzc2FnZXNbaV0ucm9sZSAhPT0gJ2Fzc2lzdGFudCcpIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbn1cbiIsIjxuZy1jb250YWluZXIgKm5nSWY9XCIhaW5pdGlhbGl6YXRpb25FcnJvclwiPlxuICA8ZGl2ICpuZ0lmPVwibWVzc2FnZXMkIHwgYXN5bmMgYXMgbWVzc2FnZXM7IGVsc2UgbG9hZGluZ1RwbCB8fCBsb2FkaW5nVHBsRGVmYXVsdFwiIGNsYXNzPVwiaC0xMDAgZC1mbGV4IGZsZXgtY29sdW1uXCI+XG4gICAgPCEtLSBUb2tlbiBjb25zdW1wdGlvbiAtLT5cbiAgICA8ZGl2IGNsYXNzPVwibXMtMVwiICpuZ0lmPVwiY29uZmlnPy5nbG9iYWxTZXR0aW5ncz8uZGlzcGxheVVzZXJRdW90YUNvbnN1bXB0aW9uIHx8IGNvbmZpZz8uZ2xvYmFsU2V0dGluZ3M/LmRpc3BsYXlDaGF0VG9rZW5zQ29uc3VtcHRpb25cIj5cbiAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJ0b2tlbkNvbnN1bXB0aW9uVHBsIHx8IGRlZmF1bHRUb2tlbkNvbnN1bXB0aW9uVHBsOyBjb250ZXh0OiB7ICRpbXBsaWNpdDogaW5zdGFuY2VJZCB9XCI+PC9uZy1jb250YWluZXI+XG4gICAgPC9kaXY+XG5cbiAgICA8IS0tIENoYXQgTWVzc2FnZXMgLS0+XG4gICAgPHVsIGNsYXNzPVwibGlzdC1ncm91cCBsaXN0LWdyb3VwLWZsdXNoIG92ZXJmbG93LWF1dG8gZmxleC1ncm93LTEgcGUtMiBwYi0yXCIgI21lc3NhZ2VMaXN0PlxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdGb3I9XCJsZXQgbWVzc2FnZSBvZiBtZXNzYWdlczsgbGV0IGluZGV4ID0gaW5kZXg7IGxldCBsYXN0ID0gbGFzdFwiPlxuICAgICAgICA8IS0tIFJlZ3VsYXIgbWVzc2FnZXMgLS0+XG4gICAgICAgIDxsaSBjbGFzcz1cImxpc3QtZ3JvdXAtaXRlbVwiXG4gICAgICAgICAgKm5nSWY9XCJtZXNzYWdlLmFkZGl0aW9uYWxQcm9wZXJ0aWVzLmRpc3BsYXlcIlxuICAgICAgICAgIFtzdHlsZS4tLWJzLWxpc3QtZ3JvdXAtaXRlbS1wYWRkaW5nLXkucmVtXT1cIicwLjYnXCJcbiAgICAgICAgICBbY2xhc3Mub3BhY2l0eS01MF09XCJtZXNzYWdlVG9FZGl0ICYmIG1lc3NhZ2VUb0VkaXQgPCBpbmRleCArIDFcIj5cbiAgICAgICAgICA8c3EtY2hhdC1tZXNzYWdlXG4gICAgICAgICAgICBbY2xhc3Muc3EtdXNlci1tZXNzYWdlXT1cIm1lc3NhZ2Uucm9sZSA9PT0gJ3VzZXInXCJcbiAgICAgICAgICAgIFtjbGFzcy5sYXN0LW1lc3NhZ2VdPVwibGFzdFwiXG4gICAgICAgICAgICBbbWVzc2FnZV09XCJtZXNzYWdlXCJcbiAgICAgICAgICAgIFtjb252ZXJzYXRpb25dPVwibWVzc2FnZXNcIlxuICAgICAgICAgICAgW3N1Z2dlc3RlZEFjdGlvbnNdPVwibGFzdCA/IG1lc3NhZ2UuYWRkaXRpb25hbFByb3BlcnRpZXMuJHN1Z2dlc3RlZEFjdGlvbiA6IHVuZGVmaW5lZFwiXG4gICAgICAgICAgICBbY2hhdFN0YXJ0ZXJzXT1cInZpc2libGVNZXNzYWdlc0NvdW50ID09PSAxID8gY29uZmlnLm1vZGVTZXR0aW5ncy5pbml0aWFsaXphdGlvbi5jaGF0U3RhcnRlcnMgOiB1bmRlZmluZWRcIlxuICAgICAgICAgICAgW2Fzc2lzdGFudE1lc3NhZ2VJY29uXT1cImFzc2lzdGFudE1lc3NhZ2VJY29uXCJcbiAgICAgICAgICAgIFt1c2VyTWVzc2FnZUljb25dPVwidXNlck1lc3NhZ2VJY29uXCJcbiAgICAgICAgICAgIFtjb25uZWN0aW9uRXJyb3JNZXNzYWdlSWNvbl09XCJjb25uZWN0aW9uRXJyb3JNZXNzYWdlSWNvblwiXG4gICAgICAgICAgICBbc2VhcmNoV2FybmluZ01lc3NhZ2VJY29uXT1cInNlYXJjaFdhcm5pbmdNZXNzYWdlSWNvblwiXG4gICAgICAgICAgICBbc3RyZWFtaW5nXT1cIihjaGF0U2VydmljZS5zdHJlYW1pbmckIHwgYXN5bmMpICYmIChsYXN0IHx8IGlzQXNzaXN0YW50TGFzdE1lc3NhZ2VzKG1lc3NhZ2VzLCBpbmRleCkpXCJcbiAgICAgICAgICAgIFtjYW5FZGl0XT1cIihsb2FkaW5nJCB8IGFzeW5jKSA9PT0gZmFsc2UgJiYgKChjaGF0U2VydmljZS5zdHJlYW1pbmckIHwgYXN5bmMpID09PSBmYWxzZSB8fCAhbGFzdCkgJiYgbWVzc2FnZVRvRWRpdCA9PT0gdW5kZWZpbmVkICYmIG1lc3NhZ2Uucm9sZSA9PT0gJ3VzZXInXCJcbiAgICAgICAgICAgIFtjYW5Db3B5XT1cIigoY2hhdFNlcnZpY2Uuc3RyZWFtaW5nJCB8IGFzeW5jKSA9PT0gZmFsc2UgfHwgIWxhc3QpICYmIG1lc3NhZ2VUb0VkaXQgPT09IHVuZGVmaW5lZCAmJiBtZXNzYWdlLnJvbGUgIT09ICdjb25uZWN0aW9uLWVycm9yJyAmJiBtZXNzYWdlLnJvbGUgIT09ICdzZWFyY2gtd2FybmluZydcIlxuICAgICAgICAgICAgW2Nhbkxpa2VdPVwiKChjaGF0U2VydmljZS5zdHJlYW1pbmckIHwgYXN5bmMpID09PSBmYWxzZSB8fCAhbGFzdCkgJiYgbWVzc2FnZS5yb2xlID09PSAnYXNzaXN0YW50J1wiXG4gICAgICAgICAgICBbY2FuRGlzbGlrZV09XCIoKGNoYXRTZXJ2aWNlLnN0cmVhbWluZyQgfCBhc3luYykgPT09IGZhbHNlIHx8ICFsYXN0KSAmJiBtZXNzYWdlLnJvbGUgPT09ICdhc3Npc3RhbnQnXCJcbiAgICAgICAgICAgIFtjYW5EZWJ1Z109XCIoKChjaGF0U2VydmljZS5zdHJlYW1pbmckIHwgYXN5bmMpID09PSBmYWxzZSAmJiBsYXN0KSB8fCAoIWxhc3QgJiYgbWVzc2FnZXNbaW5kZXgrMV0ucm9sZSAhPT0gJ2Fzc2lzdGFudCcpKSAmJiBtZXNzYWdlLnJvbGUgPT09ICdhc3Npc3RhbnQnICYmIGlzQWRtaW4gJiYgKGdldERlYnVnTWVzc2FnZXMoaW5kZXgpLmxlbmd0aCA+IDApICYmIGNvbmZpZz8uZGVmYXVsdFZhbHVlcy5kZWJ1Z1wiXG4gICAgICAgICAgICBbY2FuUmVnZW5lcmF0ZV09XCIobG9hZGluZyQgfCBhc3luYykgPT09IGZhbHNlICYmICgoKGNoYXRTZXJ2aWNlLnN0cmVhbWluZyQgfCBhc3luYykgPT09IGZhbHNlICAmJiBsYXN0KSB8fCAoIWxhc3QgJiYgbWVzc2FnZXNbaW5kZXgrMV0ucm9sZSAhPT0gJ2Fzc2lzdGFudCcpKSAgJiYgbWVzc2FnZS5yb2xlID09PSAnYXNzaXN0YW50JyAmJiBtZXNzYWdlVG9FZGl0ID09PSB1bmRlZmluZWRcIlxuICAgICAgICAgICAgKGVkaXQpPVwiZWRpdE1lc3NhZ2UoaW5kZXgpXCJcbiAgICAgICAgICAgIChjb3B5KT1cImNvcHlNZXNzYWdlKGluZGV4KVwiXG4gICAgICAgICAgICAocmVnZW5lcmF0ZSk9XCJyZWdlbmVyYXRlTWVzc2FnZShpbmRleClcIlxuICAgICAgICAgICAgKG9wZW5Eb2N1bWVudCk9XCJvcGVuT3JpZ2luYWxBdHRhY2htZW50KCRldmVudClcIlxuICAgICAgICAgICAgKG9wZW5QcmV2aWV3KT1cIm9wZW5BdHRhY2htZW50UHJldmlldygkZXZlbnQpXCJcbiAgICAgICAgICAgIChzdWdnZXN0QWN0aW9uKT1cInN1Z2dlc3RBY3Rpb25DbGljaygkZXZlbnQsIGluZGV4KVwiXG4gICAgICAgICAgICAoY2hhdFN0YXJ0ZXJDbGlja2VkKT1cImNoYXRTdGFydGVyQ2xpY2soJGV2ZW50KVwiXG4gICAgICAgICAgICAobGlrZSk9XCJvbkxpa2UoJGV2ZW50LCBpbmRleClcIlxuICAgICAgICAgICAgKGRpc2xpa2UpPVwib25EaXNsaWtlKCRldmVudCwgaW5kZXgpXCJcbiAgICAgICAgICAgIChkZWJ1Zyk9XCJzaG93RGVidWcoaW5kZXgpXCI+XG4gICAgICAgICAgPC9zcS1jaGF0LW1lc3NhZ2U+XG4gICAgICAgIDwvbGk+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgIDwhLS0gTG9hZGluZyBzcGlubmVyIC0tPlxuICAgICAgPGxpIGNsYXNzPVwibGlzdC1ncm91cC1pdGVtXCIgKm5nSWY9XCIobG9hZGluZyQgfCBhc3luYykgPT09IHRydWVcIj5cbiAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImxvYWRpbmdUcGwgfHwgbG9hZGluZ1RwbERlZmF1bHRcIj48L25nLWNvbnRhaW5lcj5cbiAgICAgIDwvbGk+XG4gICAgPC91bD5cblxuICAgIDwhLS0gUmVwb3J0aW5nIGEgZmVlZGJhY2sgZm9ybSAtLT5cbiAgICA8ZGl2IGNsYXNzPVwiaXNzdWUtcmVwb3J0IGJnLWxpZ2h0IHB0LTMgcGItMlwiICpuZ0lmPVwic2hvd1JlcG9ydFwiPlxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cInJlcG9ydFRwbCB8fCByZXBvcnRUcGxEZWZhdWx0OyBjb250ZXh0OiB7ICRpbXBsaWNpdDogbWVzc2FnZVRvUmVwb3J0LCByYW5rOiByZXBvcnRSYW5rLCB0eXBlOiByZXBvcnRUeXBlIH1cIj48L25nLWNvbnRhaW5lcj5cbiAgICA8L2Rpdj5cblxuICAgIDwhLS0gVXNlciB0ZXh0IGlucHV0IC0tPlxuICAgIDxkaXYgY2xhc3M9XCJ1c2VyLWlucHV0IG10LWF1dG9cIiAqbmdJZj1cIiFzaG93UmVwb3J0XCI+XG4gICAgICA8ZGl2IGNsYXNzPVwicHktMlwiPlxuICAgICAgICA8ZGl2IFtoaWRkZW5dPVwiIWlzQ29ubmVjdGVkXCI+XG4gICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImVuYWJsZWRVc2VySW5wdXRcIiBbbmdUZW1wbGF0ZU91dGxldF09XCJpbnB1dFRwbFwiPjwvbmctY29udGFpbmVyPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPCEtLSBSZXRyeSBidXR0b24gLS0+XG4gICAgICAgIDxidXR0b24gW2hpZGRlbl09XCJpc0Nvbm5lY3RlZFwiIGNsYXNzPVwiYnRuIG1iLTQgYXN0LWVycm9yIGFzdC1idG4gc3EtcmV0cnlcIiAoY2xpY2spPVwicmV0cnlGZXRjaCgpXCI+XG4gICAgICAgICAgPHNwYW4+VHJ5IGFnYWluPC9zcGFuPlxuICAgICAgICAgIDxzcGFuICpuZ0lmPVwicmV0cmlhbEF0dGVtcHRzXCIgY2xhc3M9XCJtcy0yIGF0dGVtcHRzXCI+e3sgcmV0cmlhbEF0dGVtcHRzIH19PC9zcGFuPlxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPGRpdiBjbGFzcz1cInRleHQtZW5kIHNtYWxsIHRleHQtbXV0ZWQgcHgtM1wiICpuZ0lmPVwiISFjb25maWc/Lmdsb2JhbFNldHRpbmdzPy5kaXNjbGFpbWVyXCI+XG4gICAgICAgICAge3sgY29uZmlnPy5nbG9iYWxTZXR0aW5ncz8uZGlzY2xhaW1lciB9fVxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuXG4gICAgPCEtLSBGbG9hdGluZyBzY3JvbGwgYnV0dG9uIC0tPlxuICAgIDxkaXYgKm5nSWY9XCIhaXNBdEJvdHRvbSAmJiAhc2hvd1JlcG9ydFwiIGNsYXNzPVwic3EtZmxvYXRpbmctc2Nyb2xsXCIgW25nQ2xhc3NdPVwiZW5hYmxlZFVzZXJJbnB1dCA/ICdzcS1mbG9hdGluZy1zY3JvbGwtLXdoZW4tdXNlci1pbnB1dCcgOiAnc3EtZmxvYXRpbmctc2Nyb2xsLS13aXRob3V0LXVzZXItaW5wdXQnXCI+XG4gICAgICA8YnV0dG9uIGNsYXNzPVwiYnRuIHNoYWRvd1wiIChjbGljayk9XCJzY3JvbGxEb3duKClcIj5cbiAgICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtYW5nbGUtZG91YmxlLWRvd25cIj48L2k+XG4gICAgICA8L2J1dHRvbj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L25nLWNvbnRhaW5lcj5cblxuPCEtLSBORyBURU1QTEFURVMtLT5cblxuPG5nLXRlbXBsYXRlICNsb2FkaW5nVHBsRGVmYXVsdD5cbiAgPGRpdiBjbGFzcz1cInNwaW5uZXItZ3JvdyB0ZXh0LXByaW1hcnkgZC1ibG9jayBteC1hdXRvIG15LTVcIiByb2xlPVwic3RhdHVzXCI+XG4gICAgPHNwYW4gY2xhc3M9XCJ2aXN1YWxseS1oaWRkZW5cIj5Mb2FkaW5nLi4uPC9zcGFuPlxuICA8L2Rpdj5cbjwvbmctdGVtcGxhdGU+XG5cbjxuZy10ZW1wbGF0ZSAjaW5wdXRUcGw+XG4gIDxkaXYgY2xhc3M9XCJweC0zIHB5LTFcIj5cbiAgICA8ZGl2IGNsYXNzPVwiYXN0LWlucHV0LWNvbnRhaW5lclwiPlxuICAgICAgPGJ1dHRvbiBkaXNhYmxlZCBjbGFzcz1cImJ0biBidG4tbGlnaHRcIj5cbiAgICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtc2VhcmNoXCI+PC9pPlxuICAgICAgPC9idXR0b24+XG4gICAgICA8dGV4dGFyZWEgI3F1ZXN0aW9uSW5wdXQgcm93cz1cIjFcIlxuICAgICAgICB0eXBlPVwidGV4dFwiIGNsYXNzPVwiZm9ybS1jb250cm9sXCJcbiAgICAgICAgcGxhY2Vob2xkZXI9XCJBc2sgc29tZXRoaW5nXCIgYXV0b2ZvY3VzXG4gICAgICAgIFsobmdNb2RlbCldPVwicXVlc3Rpb25cIlxuICAgICAgICAoa2V5dXApPVwib25LZXlVcCgkZXZlbnQpXCJcbiAgICAgICAgKGtleWRvd24pPVwiY2FsY3VsYXRlSGVpZ2h0KCRldmVudClcIlxuICAgICAgICBbZGlzYWJsZWRdPVwiKGxvYWRpbmckIHwgYXN5bmMpIHx8IChjaGF0U2VydmljZS5zdHJlYW1pbmckIHwgYXN5bmMpIHx8IChjaGF0U2VydmljZS5zdG9wcGluZ0dlbmVyYXRpb24kIHwgYXN5bmMpXCI+XG4gICAgICA8L3RleHRhcmVhPlxuICAgICAgPGJ1dHRvblxuICAgICAgICAqbmdJZj1cIiEoY2hhdFNlcnZpY2Uuc3RyZWFtaW5nJCB8IGFzeW5jKSAmJiAhKGxvYWRpbmckIHwgYXN5bmMpICYmICEoY2hhdFNlcnZpY2Uuc3RvcHBpbmdHZW5lcmF0aW9uJCB8IGFzeW5jKVwiXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICBjbGFzcz1cImJ0biBidG4tbGlnaHQgbXMtMlwiXG4gICAgICAgIHNxVG9vbHRpcD1cIlNlbmQgbWVzc2FnZVwiXG4gICAgICAgIChjbGljayk9XCJzdWJtaXRRdWVzdGlvbigpXCI+XG4gICAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLXBhcGVyLXBsYW5lXCI+PC9pPlxuICAgICAgPC9idXR0b24+XG4gICAgICA8YnV0dG9uXG4gICAgICAgICpuZ0lmPVwibWVzc2FnZVRvRWRpdFwiXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICBjbGFzcz1cImJ0biBidG4tbGlnaHQgbXMtMlwiXG4gICAgICAgIHNxVG9vbHRpcD1cIkNhbmNlbCBlZGl0aW9uXCJcbiAgICAgICAgKGNsaWNrKT1cIm1lc3NhZ2VUb0VkaXQgPSB1bmRlZmluZWQ7IHF1ZXN0aW9uID0gJydcIj5cbiAgICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtdW5kby1hbHRcIj48L2k+XG4gICAgICA8L2J1dHRvbj5cbiAgICAgIDxzcGFuICpuZ0lmPVwiKGNoYXRTZXJ2aWNlLnN0cmVhbWluZyQgfCBhc3luYykgJiYgIShjaGF0U2VydmljZS5zdG9wcGluZ0dlbmVyYXRpb24kIHwgYXN5bmMpXCIgY2xhc3M9XCJwcm9jZXNzaW5nIG1zLTJcIj5cbiAgICAgICAgR2VuZXJhdGluZyA8aSBjbGFzcz1cIm1zLTEgZmFzIGZhLXNwaW5uZXIgZmEtcHVsc2VcIj48L2k+XG4gICAgICA8L3NwYW4+XG4gICAgICA8c3BhbiAqbmdJZj1cIihjaGF0U2VydmljZS5zdG9wcGluZ0dlbmVyYXRpb24kIHwgYXN5bmMpXCIgY2xhc3M9XCJwcm9jZXNzaW5nIG1zLTJcIj5cbiAgICAgICAgU3RvcHBpbmcgPGkgY2xhc3M9XCJtcy0xIGZhcyBmYS1zcGlubmVyIGZhLXB1bHNlXCI+PC9pPlxuICAgICAgPC9zcGFuPlxuICAgICAgPGJ1dHRvblxuICAgICAgICAqbmdJZj1cIihjaGF0U2VydmljZS5zdHJlYW1pbmckIHwgYXN5bmMpICYmICEoY2hhdFNlcnZpY2Uuc3RvcHBpbmdHZW5lcmF0aW9uJCB8IGFzeW5jKVwiXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICBjbGFzcz1cImJ0biBidG4tbGlnaHQgbXMtMlwiXG4gICAgICAgIHNxVG9vbHRpcD1cIlN0b3AgZ2VuZXJhdGluZ1wiXG4gICAgICAgIChjbGljayk9XCJzdG9wR2VuZXJhdGlvbigpXCI+XG4gICAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLXN0b3BcIj48L2k+XG4gICAgICA8L2J1dHRvbj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L25nLXRlbXBsYXRlPlxuXG48bmctdGVtcGxhdGUgI3JlcG9ydFRwbERlZmF1bHQgbGV0LW1lc3NhZ2UgbGV0LXJhbms9XCJyYW5rXCIgbGV0LXR5cGU9XCJ0eXBlXCI+XG4gIDxkaXYgY2xhc3M9XCJweC0zXCI+XG4gICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cInR5cGUgPT09ICdkaXNsaWtlJ1wiPlxuICAgICAgPGg1Pklzc3VlIHR5cGU8L2g1PlxuICAgICAgPHNlbGVjdCBjbGFzcz1cImZvcm0tc2VsZWN0IG1iLTRcIiBbKG5nTW9kZWwpXT1cImlzc3VlVHlwZVwiPlxuICAgICAgICA8b3B0aW9uIFt2YWx1ZV09XCInJ1wiPkNob29zZSBhbiBpc3N1ZSB0eXBlPC9vcHRpb24+XG4gICAgICAgIDxvcHRpb24gKm5nRm9yPVwibGV0IHR5cGUgb2YgKGlzc3VlVHlwZXMgPz8gZGVmYXVsdElzc3VlVHlwZXMpXCI+e3t0eXBlfX08L29wdGlvbj5cbiAgICAgIDwvc2VsZWN0PlxuICAgICAgPGg1PldoYXQgd2FzIHVuc2F0aXNmeWluZyBhYm91dCB0aGlzIHJlc3BvbnNlPyAob3B0aW9uYWwpPC9oNT5cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8bmctY29udGFpbmVyICpuZ0lmPVwidHlwZSA9PT0gJ2xpa2UnXCI+XG4gICAgICA8aDU+V2h5IGRpZCB5b3UgbGlrZSB0aGlzIGFuc3dlcj8gKG9wdGlvbmFsKTwvaDU+XG4gICAgPC9uZy1jb250YWluZXI+XG4gICAgPHRleHRhcmVhIGNsYXNzPVwiZm9ybS1jb250cm9sXCIgWyhuZ01vZGVsKV09XCJyZXBvcnRDb21tZW50XCIgcGxhY2Vob2xkZXI9XCJXcml0ZSB5b3VyIGNvbW1lbnRcIj48L3RleHRhcmVhPlxuICAgIDxkaXYgY2xhc3M9XCJkLWZsZXggZmxleC1yb3ctcmV2ZXJzZSBtdC0yXCI+XG4gICAgICA8YnV0dG9uIGNsYXNzPVwiYnRuIGJ0bi1wcmltYXJ5XCIgW2Rpc2FibGVkXT1cInR5cGUgPT09ICdkaXNsaWtlJyAmJiAhaXNzdWVUeXBlXCIgKGNsaWNrKT1cInNlbmRSZXBvcnQoKVwiPlNlbmQ8L2J1dHRvbj5cbiAgICAgIDxidXR0b24gY2xhc3M9XCJidG4gYnRuLWxpZ2h0XCIgKGNsaWNrKT1cImlnbm9yZVJlcG9ydCgpXCI+Q2FuY2VsPC9idXR0b24+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuPC9uZy10ZW1wbGF0ZT5cblxuPG5nLXRlbXBsYXRlICNkZWZhdWx0VG9rZW5Db25zdW1wdGlvblRwbCBsZXQtaW5zdGFuY2VJZD5cbiAgPHNxLXRva2VuLXByb2dyZXNzLWJhclxuICAgIFtpbnN0YW5jZUlkXT1cImluc3RhbmNlSWRcIj5cbiAgPC9zcS10b2tlbi1wcm9ncmVzcy1iYXI+XG48L25nLXRlbXBsYXRlPlxuXG48ZGl2IGNsYXNzPVwiZGVidWctbWVzc2FnZXNcIiBbY2xhc3MuZGlzcGxheWVkXT1cInNob3dEZWJ1Z01lc3NhZ2VzXCI+XG4gIDxidXR0b24gKm5nSWY9XCJzaG93RGVidWdNZXNzYWdlc1wiIGNsYXNzPVwiYnRuIGJ0bi1saWdodCBzaGFkb3cgYmFjay1idG5cIiAoY2xpY2spPVwic2hvd0RlYnVnTWVzc2FnZXM9ZmFsc2VcIj5cbiAgICA8aSBjbGFzcz1cImZhcyBmYS1jaGV2cm9uLXJpZ2h0XCI+PC9pPlxuICA8L2J1dHRvbj5cbiAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImRlYnVnTWVzc2FnZXNUcGwgfHwgZGVmYXVsdERlYnVnTWVzc2FnZXNUcGw7IGNvbnRleHQ6IHsgJGltcGxpY2l0OiBkZWJ1Z01lc3NhZ2VzIH1cIj5cbiAgPC9uZy1jb250YWluZXI+XG48L2Rpdj5cblxuPG5nLXRlbXBsYXRlICNkZWZhdWx0RGVidWdNZXNzYWdlc1RwbCBsZXQtZGVidWdNZXNzYWdlcz5cbiAgPHNxLWRlYnVnLW1lc3NhZ2UgW2RhdGFdPVwiZGVidWdNZXNzYWdlc1wiPjwvc3EtZGVidWctbWVzc2FnZT5cbjwvbmctdGVtcGxhdGU+XG4iXX0=