emanate-ai-chat-lib 0.1.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.
- package/README.md +409 -0
- package/bundles/emanate-ai-chat-lib.umd.js +1545 -0
- package/bundles/emanate-ai-chat-lib.umd.js.map +1 -0
- package/emanate-ai-chat-lib.d.ts +5 -0
- package/esm2015/emanate-ai-chat-lib.js +5 -0
- package/esm2015/lib/components/ai-chat.component.js +706 -0
- package/esm2015/lib/emanate-ai-chat-lib.component.js +26 -0
- package/esm2015/lib/emanate-ai-chat-lib.module.js +45 -0
- package/esm2015/lib/emanate-ai-chat-lib.service.js +14 -0
- package/esm2015/lib/models/icon-config.interface.js +113 -0
- package/esm2015/lib/services/ai-agent.service.js +86 -0
- package/esm2015/public-api.js +12 -0
- package/fesm2015/emanate-ai-chat-lib.js +985 -0
- package/fesm2015/emanate-ai-chat-lib.js.map +1 -0
- package/lib/components/ai-chat.component.d.ts +131 -0
- package/lib/emanate-ai-chat-lib.component.d.ts +8 -0
- package/lib/emanate-ai-chat-lib.module.d.ts +11 -0
- package/lib/emanate-ai-chat-lib.service.d.ts +6 -0
- package/lib/models/icon-config.interface.d.ts +45 -0
- package/lib/services/ai-agent.service.d.ts +60 -0
- package/package.json +38 -0
- package/public-api.d.ts +6 -0
|
@@ -0,0 +1,706 @@
|
|
|
1
|
+
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
|
2
|
+
import { Subject } from 'rxjs';
|
|
3
|
+
import { takeUntil } from 'rxjs/operators';
|
|
4
|
+
import { getIconSet } from '../models/icon-config.interface';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
import * as i1 from "../services/ai-agent.service";
|
|
7
|
+
import * as i2 from "@angular/platform-browser";
|
|
8
|
+
import * as i3 from "@angular/common";
|
|
9
|
+
import * as i4 from "@angular/forms";
|
|
10
|
+
export class AiChatComponent {
|
|
11
|
+
constructor(aiAgentService, sanitizer) {
|
|
12
|
+
this.aiAgentService = aiAgentService;
|
|
13
|
+
this.sanitizer = sanitizer;
|
|
14
|
+
this.title = 'Chat with Maestro';
|
|
15
|
+
this.placeholder = 'Type your inquiry here... (Press Enter to send, Shift+Enter for new line)';
|
|
16
|
+
this.showDebugInfo = false;
|
|
17
|
+
this.enableImageUpload = false; // Enable/disable image upload button
|
|
18
|
+
this.enableFileUpload = false; // Enable/disable file upload button
|
|
19
|
+
this.iconSet = 'feather'; // Icon set selection
|
|
20
|
+
this.messageReceived = new EventEmitter();
|
|
21
|
+
this.messageSent = new EventEmitter();
|
|
22
|
+
this.fileUploaded = new EventEmitter();
|
|
23
|
+
this.sizeChanged = new EventEmitter();
|
|
24
|
+
this.messages = [];
|
|
25
|
+
this.currentInquiry = '';
|
|
26
|
+
this.authorName = '';
|
|
27
|
+
this.intent = '';
|
|
28
|
+
this.isLoading = false;
|
|
29
|
+
this.configurationStatus = '';
|
|
30
|
+
// Resizing properties
|
|
31
|
+
this.currentSize = 'default';
|
|
32
|
+
this.isFullscreen = false;
|
|
33
|
+
this.isResizing = false;
|
|
34
|
+
this.containerWidth = 800;
|
|
35
|
+
this.containerHeight = 600;
|
|
36
|
+
this.minWidth = 400;
|
|
37
|
+
this.maxWidth = 1400;
|
|
38
|
+
this.minHeight = 400;
|
|
39
|
+
this.maxHeight = window.innerHeight - 100;
|
|
40
|
+
this.startX = 0;
|
|
41
|
+
this.startY = 0;
|
|
42
|
+
this.startWidth = 0;
|
|
43
|
+
this.startHeight = 0;
|
|
44
|
+
// File upload properties
|
|
45
|
+
this.maxFileSize = 10 * 1024 * 1024; // 10MB
|
|
46
|
+
this.allowedImageTypes = ['image/png', 'image/jpeg', 'image/jpg', 'image/gif', 'image/webp'];
|
|
47
|
+
this.allowedFileTypes = ['application/pdf', 'application/msword',
|
|
48
|
+
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
49
|
+
'text/plain', 'text/csv'];
|
|
50
|
+
this.selectedFiles = [];
|
|
51
|
+
// Icon configuration
|
|
52
|
+
this.icons = getIconSet('feather');
|
|
53
|
+
this.sanitizedIcons = {};
|
|
54
|
+
this.destroy$ = new Subject();
|
|
55
|
+
}
|
|
56
|
+
ngOnInit() {
|
|
57
|
+
this.configurationStatus = 'Initializing...';
|
|
58
|
+
console.log('AI Chat Component initialized');
|
|
59
|
+
// Load icon set
|
|
60
|
+
this.icons = getIconSet(this.iconSet, this.customIcons);
|
|
61
|
+
this.sanitizeIcons();
|
|
62
|
+
// Configure API URL and App Key if provided
|
|
63
|
+
if (this.apiUrl || this.appKey) {
|
|
64
|
+
this.aiAgentService.configure({
|
|
65
|
+
apiUrl: this.apiUrl,
|
|
66
|
+
appKey: this.appKey
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
// Load historical messages if provided
|
|
71
|
+
if (this.historicalMessages && this.historicalMessages.length > 0) {
|
|
72
|
+
this.loadHistoricalMessages(this.historicalMessages);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
this.addWelcomeMessage();
|
|
76
|
+
}
|
|
77
|
+
this.testConfiguration();
|
|
78
|
+
this.loadSavedSize();
|
|
79
|
+
this.applySizePreset(this.currentSize);
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
console.error('Error during component initialization:', error);
|
|
83
|
+
this.configurationStatus = 'Initialization error';
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
ngOnChanges(changes) {
|
|
87
|
+
// Detect when historicalMessages input changes
|
|
88
|
+
if (changes['historicalMessages'] && !changes['historicalMessages'].firstChange) {
|
|
89
|
+
const newMessages = changes['historicalMessages'].currentValue;
|
|
90
|
+
// console.log('Historical messages changed:', newMessages);
|
|
91
|
+
// Clear existing messages and reload
|
|
92
|
+
this.messages = [];
|
|
93
|
+
if (newMessages && newMessages.length > 0) {
|
|
94
|
+
this.loadHistoricalMessages(newMessages);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
this.addWelcomeMessage();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// Detect when conversationId changes
|
|
101
|
+
if (changes['conversationId'] && !changes['conversationId'].firstChange) {
|
|
102
|
+
// console.log('Conversation ID changed:', changes['conversationId'].currentValue);
|
|
103
|
+
// Update all existing messages with new conversationId if needed
|
|
104
|
+
this.messages.forEach(msg => {
|
|
105
|
+
if (msg.conversationId !== this.conversationId) {
|
|
106
|
+
msg.conversationId = this.conversationId;
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
// Detect when icon set changes
|
|
111
|
+
if (changes['iconSet'] || changes['customIcons']) {
|
|
112
|
+
this.icons = getIconSet(this.iconSet, this.customIcons);
|
|
113
|
+
this.sanitizeIcons();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
ngOnDestroy() {
|
|
117
|
+
this.destroy$.next();
|
|
118
|
+
this.destroy$.complete();
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Sanitize icon SVG strings for safe rendering in innerHTML bindings
|
|
122
|
+
*/
|
|
123
|
+
sanitizeIcons() {
|
|
124
|
+
this.sanitizedIcons = {};
|
|
125
|
+
Object.keys(this.icons).forEach(key => {
|
|
126
|
+
const svgString = this.icons[key];
|
|
127
|
+
if (svgString) {
|
|
128
|
+
this.sanitizedIcons[key] = this.sanitizer.bypassSecurityTrustHtml(svgString);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
testConfiguration() {
|
|
133
|
+
this.configurationStatus = 'Testing connection...';
|
|
134
|
+
this.aiAgentService.testConfiguration()
|
|
135
|
+
.pipe(takeUntil(this.destroy$))
|
|
136
|
+
.subscribe({
|
|
137
|
+
next: (response) => {
|
|
138
|
+
if (response.success) {
|
|
139
|
+
this.configurationStatus = 'AI Agent is ready';
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
this.configurationStatus = `Configuration error: ${response.error}`;
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
error: (errorResponse) => {
|
|
146
|
+
this.configurationStatus = `Connection error: Cannot connect to backend service`;
|
|
147
|
+
console.error('API connection test failed:', errorResponse);
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
addWelcomeMessage() {
|
|
152
|
+
const welcomeText = this.welcomeMessage ||
|
|
153
|
+
`<h3>Hello ${this.firstName}!</h3>Hi, I'm Maestro—your AI assistant. I'm here to help with your policy-related inquiries.<br><br>How can I assist you today?`;
|
|
154
|
+
this.messages.push({
|
|
155
|
+
isUser: false,
|
|
156
|
+
content: welcomeText,
|
|
157
|
+
intent: 'welcome',
|
|
158
|
+
timestamp: new Date()
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Load and transform historical messages from parent component
|
|
163
|
+
* Accepts messages in the format from your backend/state management
|
|
164
|
+
*/
|
|
165
|
+
loadHistoricalMessages(historicalMessages) {
|
|
166
|
+
// console.log('Loading historical messages:', historicalMessages);
|
|
167
|
+
// console.log('Number of messages to load:', historicalMessages.length);
|
|
168
|
+
// Transform your backend format to ChatMessage format
|
|
169
|
+
const transformedMessages = historicalMessages.map((msg) => {
|
|
170
|
+
// Determine if message is from user based on sender or role
|
|
171
|
+
const isUserMessage = this.isUserMessage(msg);
|
|
172
|
+
const transformed = {
|
|
173
|
+
messageId: msg.messageId || msg.id,
|
|
174
|
+
conversationId: msg.conversationId || this.conversationId,
|
|
175
|
+
isUser: isUserMessage,
|
|
176
|
+
content: msg.messageText || msg.message || msg.text || msg.content || '',
|
|
177
|
+
sender: msg.sender || (isUserMessage ? this.userName || 'User' : 'Maestro'),
|
|
178
|
+
intent: msg.intent || '',
|
|
179
|
+
authorName: msg.authorName || msg.sender,
|
|
180
|
+
confidenceScore: msg.confidenceScore || msg.confidence || 0,
|
|
181
|
+
timestamp: msg.timestamp || msg.createdAt
|
|
182
|
+
? new Date(msg.timestamp || msg.createdAt)
|
|
183
|
+
: new Date(),
|
|
184
|
+
isLoading: false
|
|
185
|
+
};
|
|
186
|
+
// console.log('Transformed message:', transformed);
|
|
187
|
+
return transformed;
|
|
188
|
+
});
|
|
189
|
+
// Sort messages by timestamp to maintain chronological order
|
|
190
|
+
transformedMessages.sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
|
|
191
|
+
// console.log('Sorted messages count:', transformedMessages.length);
|
|
192
|
+
// Add welcome message first if no messages or load historical messages
|
|
193
|
+
if (transformedMessages.length === 0) {
|
|
194
|
+
// console.log('No messages to load, adding welcome message');
|
|
195
|
+
this.addWelcomeMessage();
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
// Check if first message is a welcome message, if not add one
|
|
199
|
+
const hasWelcome = transformedMessages.some(msg => msg.intent === 'welcome' || msg.content.includes('Hello'));
|
|
200
|
+
if (!hasWelcome) {
|
|
201
|
+
// console.log('No welcome message found, adding one');
|
|
202
|
+
this.addWelcomeMessage();
|
|
203
|
+
}
|
|
204
|
+
// console.log('Pushing transformed messages to messages array');
|
|
205
|
+
this.messages.push(...transformedMessages);
|
|
206
|
+
}
|
|
207
|
+
// console.log('Total loaded messages in component:', this.messages.length);
|
|
208
|
+
// console.log('Messages array:', this.messages);
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Helper method to determine if a message is from the user
|
|
212
|
+
*/
|
|
213
|
+
isUserMessage(msg) {
|
|
214
|
+
var _a, _b;
|
|
215
|
+
// Check various properties that might indicate user message
|
|
216
|
+
if (msg.isUser !== undefined)
|
|
217
|
+
return msg.isUser;
|
|
218
|
+
if (msg.role)
|
|
219
|
+
return msg.role.toLowerCase() === 'user';
|
|
220
|
+
if (msg.sender) {
|
|
221
|
+
const sender = msg.sender.toLowerCase();
|
|
222
|
+
return sender === 'user' ||
|
|
223
|
+
sender === ((_a = this.userName) === null || _a === void 0 ? void 0 : _a.toLowerCase()) ||
|
|
224
|
+
sender === ((_b = this.userId) === null || _b === void 0 ? void 0 : _b.toLowerCase()) ||
|
|
225
|
+
sender.includes('user');
|
|
226
|
+
}
|
|
227
|
+
// Default to false (bot message) if can't determine
|
|
228
|
+
return false;
|
|
229
|
+
}
|
|
230
|
+
sendInquiry() {
|
|
231
|
+
if (!this.currentInquiry.trim() || this.isLoading) {
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
const userMessage = {
|
|
235
|
+
messageId: this.generateMessageId(),
|
|
236
|
+
conversationId: this.conversationId,
|
|
237
|
+
isUser: true,
|
|
238
|
+
sender: this.userName || 'User',
|
|
239
|
+
intent: this.intent,
|
|
240
|
+
content: this.currentInquiry,
|
|
241
|
+
timestamp: new Date()
|
|
242
|
+
};
|
|
243
|
+
this.messages.push(userMessage);
|
|
244
|
+
this.messageSent.emit(userMessage);
|
|
245
|
+
// Add loading message
|
|
246
|
+
const loadingMessage = {
|
|
247
|
+
isUser: false,
|
|
248
|
+
intent: '',
|
|
249
|
+
content: 'Processing your inquiry...',
|
|
250
|
+
timestamp: new Date(),
|
|
251
|
+
isLoading: true
|
|
252
|
+
};
|
|
253
|
+
this.messages.push(loadingMessage);
|
|
254
|
+
const inquiry = this.currentInquiry.trim();
|
|
255
|
+
this.currentInquiry = '';
|
|
256
|
+
this.authorName = '';
|
|
257
|
+
this.intent = '';
|
|
258
|
+
this.isLoading = true;
|
|
259
|
+
const request = {
|
|
260
|
+
query: inquiry,
|
|
261
|
+
chatHistory: [],
|
|
262
|
+
userId: this.userId,
|
|
263
|
+
userName: this.userName,
|
|
264
|
+
appSource: this.appSource
|
|
265
|
+
};
|
|
266
|
+
this.aiAgentService.processInquiry(request)
|
|
267
|
+
.pipe(takeUntil(this.destroy$))
|
|
268
|
+
.subscribe({
|
|
269
|
+
next: (response) => {
|
|
270
|
+
this.isLoading = false;
|
|
271
|
+
// Remove loading message
|
|
272
|
+
this.messages = this.messages.filter(msg => !msg.isLoading);
|
|
273
|
+
if (response.answer || (response.contents && response.contents.length > 0)) {
|
|
274
|
+
if (response.answer) {
|
|
275
|
+
const botMessage = {
|
|
276
|
+
messageId: this.generateMessageId(),
|
|
277
|
+
conversationId: this.conversationId,
|
|
278
|
+
isUser: false,
|
|
279
|
+
sender: 'Maestro',
|
|
280
|
+
intent: response.searchIntent || inquiry,
|
|
281
|
+
content: this.formatMessageContent(response.answer),
|
|
282
|
+
authorName: response.contents && response.contents.length > 0 ? response.contents[0].authorName : undefined,
|
|
283
|
+
timestamp: new Date()
|
|
284
|
+
};
|
|
285
|
+
this.messages.push(botMessage);
|
|
286
|
+
this.messageReceived.emit(botMessage);
|
|
287
|
+
}
|
|
288
|
+
else if (response.contents && response.contents.length > 0) {
|
|
289
|
+
// Push each content as a separate message
|
|
290
|
+
response.contents.forEach(contentItem => {
|
|
291
|
+
if (contentItem.content) {
|
|
292
|
+
const botMessage = {
|
|
293
|
+
messageId: this.generateMessageId(),
|
|
294
|
+
conversationId: this.conversationId,
|
|
295
|
+
isUser: false,
|
|
296
|
+
sender: contentItem.authorName || 'Maestro',
|
|
297
|
+
intent: response.searchIntent || inquiry,
|
|
298
|
+
content: this.formatMessageContent(contentItem.content || 'No content available'),
|
|
299
|
+
authorName: contentItem.authorName,
|
|
300
|
+
timestamp: new Date()
|
|
301
|
+
};
|
|
302
|
+
this.messages.push(botMessage);
|
|
303
|
+
this.messageReceived.emit(botMessage);
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
const errorMessage = {
|
|
310
|
+
messageId: this.generateMessageId(),
|
|
311
|
+
conversationId: this.conversationId,
|
|
312
|
+
isUser: false,
|
|
313
|
+
sender: 'Maestro',
|
|
314
|
+
intent: inquiry,
|
|
315
|
+
content: `Sorry, I didn't receive a valid response.`,
|
|
316
|
+
authorName: this.authorName,
|
|
317
|
+
timestamp: new Date()
|
|
318
|
+
};
|
|
319
|
+
this.messages.push(errorMessage);
|
|
320
|
+
this.messageReceived.emit(errorMessage);
|
|
321
|
+
}
|
|
322
|
+
},
|
|
323
|
+
error: (error) => {
|
|
324
|
+
this.isLoading = false;
|
|
325
|
+
// Remove loading message
|
|
326
|
+
this.messages = this.messages.filter(msg => !msg.isLoading);
|
|
327
|
+
const errorMessage = {
|
|
328
|
+
messageId: this.generateMessageId(),
|
|
329
|
+
conversationId: this.conversationId,
|
|
330
|
+
isUser: false,
|
|
331
|
+
sender: 'Maestro',
|
|
332
|
+
intent: inquiry,
|
|
333
|
+
content: 'Sorry, I encountered an error processing your request. Please try again.',
|
|
334
|
+
authorName: this.authorName,
|
|
335
|
+
timestamp: new Date()
|
|
336
|
+
};
|
|
337
|
+
this.messages.push(errorMessage);
|
|
338
|
+
this.messageReceived.emit(errorMessage);
|
|
339
|
+
console.error('Error processing inquiry:', error);
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
clearChat() {
|
|
344
|
+
this.messages = [];
|
|
345
|
+
this.addWelcomeMessage();
|
|
346
|
+
}
|
|
347
|
+
onKeyPress(event) {
|
|
348
|
+
if (event.key === 'Enter' && !event.shiftKey) {
|
|
349
|
+
event.preventDefault();
|
|
350
|
+
this.sendInquiry();
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
trackByIndex(index) {
|
|
354
|
+
return index;
|
|
355
|
+
}
|
|
356
|
+
getThemeClass() {
|
|
357
|
+
// Default theme if no template design is specified
|
|
358
|
+
if (!this.templateDesign) {
|
|
359
|
+
return 'theme-default';
|
|
360
|
+
}
|
|
361
|
+
// Validate and return theme class
|
|
362
|
+
const validThemes = ['default', 'dark', 'blue', 'green', 'purple', 'minimal', 'corporate', 'red', 'yellow', 'orange'];
|
|
363
|
+
const theme = this.templateDesign.toLowerCase();
|
|
364
|
+
if (validThemes.includes(theme)) {
|
|
365
|
+
return `theme-${theme}`;
|
|
366
|
+
}
|
|
367
|
+
// Fallback to default if invalid theme
|
|
368
|
+
console.warn(`Invalid theme '${this.templateDesign}' provided. Using default theme.`);
|
|
369
|
+
return 'theme-default';
|
|
370
|
+
}
|
|
371
|
+
formatMessageContent(content) {
|
|
372
|
+
if (!content)
|
|
373
|
+
return '';
|
|
374
|
+
// If content already contains HTML tags, return as-is
|
|
375
|
+
if (content.includes('<') && content.includes('>')) {
|
|
376
|
+
return content;
|
|
377
|
+
}
|
|
378
|
+
// Convert newlines to HTML breaks
|
|
379
|
+
let formatted = content.replace(/\n/g, '<br>');
|
|
380
|
+
// Convert escaped newlines to HTML breaks
|
|
381
|
+
formatted = formatted.replace(/\\n/g, '<br>');
|
|
382
|
+
// Convert markdown-style bold to HTML
|
|
383
|
+
formatted = formatted.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>');
|
|
384
|
+
// Convert bullet points to HTML lists
|
|
385
|
+
const lines = formatted.split('<br>');
|
|
386
|
+
let inList = false;
|
|
387
|
+
const processedLines = [];
|
|
388
|
+
for (let line of lines) {
|
|
389
|
+
if (line.trim().startsWith('• ')) {
|
|
390
|
+
if (!inList) {
|
|
391
|
+
processedLines.push('<ul>');
|
|
392
|
+
inList = true;
|
|
393
|
+
}
|
|
394
|
+
processedLines.push('<li>' + line.replace(/^• /, '') + '</li>');
|
|
395
|
+
}
|
|
396
|
+
else {
|
|
397
|
+
if (inList) {
|
|
398
|
+
processedLines.push('</ul>');
|
|
399
|
+
inList = false;
|
|
400
|
+
}
|
|
401
|
+
processedLines.push(line);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
if (inList) {
|
|
405
|
+
processedLines.push('</ul>');
|
|
406
|
+
}
|
|
407
|
+
return processedLines.join('<br>').replace(/<br><ul>/g, '<ul>').replace(/<\/ul><br>/g, '</ul>');
|
|
408
|
+
}
|
|
409
|
+
generateSessionId() {
|
|
410
|
+
return 'session_' + Math.random().toString(36).substr(2, 9) + '_' + Date.now();
|
|
411
|
+
}
|
|
412
|
+
generateMessageId() {
|
|
413
|
+
return 'msg_' + Math.random().toString(36).substr(2, 9) + '_' + Date.now();
|
|
414
|
+
}
|
|
415
|
+
getFormattedTime(timestamp) {
|
|
416
|
+
return timestamp.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
|
|
417
|
+
}
|
|
418
|
+
// ============= Resize Methods =============
|
|
419
|
+
startResize(event, direction) {
|
|
420
|
+
event.preventDefault();
|
|
421
|
+
this.isResizing = true;
|
|
422
|
+
this.startX = event.clientX;
|
|
423
|
+
this.startY = event.clientY;
|
|
424
|
+
this.startWidth = this.containerWidth;
|
|
425
|
+
this.startHeight = this.containerHeight;
|
|
426
|
+
const mouseMoveHandler = (e) => this.onResize(e, direction);
|
|
427
|
+
const mouseUpHandler = () => this.stopResize(mouseMoveHandler, mouseUpHandler);
|
|
428
|
+
document.addEventListener('mousemove', mouseMoveHandler);
|
|
429
|
+
document.addEventListener('mouseup', mouseUpHandler);
|
|
430
|
+
}
|
|
431
|
+
onResize(event, direction) {
|
|
432
|
+
if (!this.isResizing)
|
|
433
|
+
return;
|
|
434
|
+
const deltaX = event.clientX - this.startX;
|
|
435
|
+
const deltaY = event.clientY - this.startY;
|
|
436
|
+
if (direction === 'width' || direction === 'both') {
|
|
437
|
+
const newWidth = Math.min(Math.max(this.startWidth + deltaX, this.minWidth), this.maxWidth);
|
|
438
|
+
this.containerWidth = newWidth;
|
|
439
|
+
}
|
|
440
|
+
if (direction === 'both') {
|
|
441
|
+
const newHeight = Math.min(Math.max(this.startHeight + deltaY, this.minHeight), this.maxHeight);
|
|
442
|
+
this.containerHeight = newHeight;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
stopResize(mouseMoveHandler, mouseUpHandler) {
|
|
446
|
+
this.isResizing = false;
|
|
447
|
+
document.removeEventListener('mousemove', mouseMoveHandler);
|
|
448
|
+
document.removeEventListener('mouseup', mouseUpHandler);
|
|
449
|
+
this.saveSizePreference();
|
|
450
|
+
this.emitSizeChange();
|
|
451
|
+
}
|
|
452
|
+
applySizePreset(size) {
|
|
453
|
+
this.currentSize = size;
|
|
454
|
+
switch (size) {
|
|
455
|
+
case 'compact':
|
|
456
|
+
this.containerWidth = 400;
|
|
457
|
+
this.containerHeight = 500;
|
|
458
|
+
this.isFullscreen = false;
|
|
459
|
+
break;
|
|
460
|
+
case 'default':
|
|
461
|
+
this.containerWidth = 800;
|
|
462
|
+
this.containerHeight = 600;
|
|
463
|
+
this.isFullscreen = false;
|
|
464
|
+
break;
|
|
465
|
+
case 'expanded':
|
|
466
|
+
this.containerWidth = 1200;
|
|
467
|
+
this.containerHeight = 800;
|
|
468
|
+
this.isFullscreen = false;
|
|
469
|
+
break;
|
|
470
|
+
case 'fullscreen':
|
|
471
|
+
this.toggleFullscreen();
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
this.saveSizePreference();
|
|
475
|
+
this.emitSizeChange();
|
|
476
|
+
}
|
|
477
|
+
toggleFullscreen() {
|
|
478
|
+
if (!this.isFullscreen) {
|
|
479
|
+
// Entering fullscreen - save current state first
|
|
480
|
+
sessionStorage.setItem('chatbox-previous-size', JSON.stringify({
|
|
481
|
+
width: this.containerWidth,
|
|
482
|
+
height: this.containerHeight,
|
|
483
|
+
size: this.currentSize,
|
|
484
|
+
wasFullscreen: this.isFullscreen
|
|
485
|
+
}));
|
|
486
|
+
this.isFullscreen = true;
|
|
487
|
+
this.currentSize = 'fullscreen';
|
|
488
|
+
}
|
|
489
|
+
else {
|
|
490
|
+
// Exiting fullscreen - restore previous state
|
|
491
|
+
try {
|
|
492
|
+
const previous = sessionStorage.getItem('chatbox-previous-size');
|
|
493
|
+
if (previous) {
|
|
494
|
+
const prevData = JSON.parse(previous);
|
|
495
|
+
this.containerWidth = prevData.width || 800;
|
|
496
|
+
this.containerHeight = prevData.height || 600;
|
|
497
|
+
this.currentSize = prevData.size === 'fullscreen' ? 'default' : prevData.size;
|
|
498
|
+
}
|
|
499
|
+
else {
|
|
500
|
+
this.currentSize = 'default';
|
|
501
|
+
this.containerWidth = 800;
|
|
502
|
+
this.containerHeight = 600;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
catch (error) {
|
|
506
|
+
this.currentSize = 'default';
|
|
507
|
+
this.containerWidth = 800;
|
|
508
|
+
this.containerHeight = 600;
|
|
509
|
+
}
|
|
510
|
+
this.isFullscreen = false;
|
|
511
|
+
}
|
|
512
|
+
this.saveSizePreference();
|
|
513
|
+
this.emitSizeChange();
|
|
514
|
+
}
|
|
515
|
+
saveSizePreference() {
|
|
516
|
+
const sizeData = {
|
|
517
|
+
size: this.currentSize,
|
|
518
|
+
width: this.containerWidth,
|
|
519
|
+
height: this.containerHeight,
|
|
520
|
+
isFullscreen: this.isFullscreen
|
|
521
|
+
};
|
|
522
|
+
try {
|
|
523
|
+
sessionStorage.setItem('chatbox-size-preference', JSON.stringify(sizeData));
|
|
524
|
+
}
|
|
525
|
+
catch (error) {
|
|
526
|
+
console.warn('Failed to save size preference:', error);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
loadSavedSize() {
|
|
530
|
+
try {
|
|
531
|
+
const saved = sessionStorage.getItem('chatbox-size-preference');
|
|
532
|
+
if (saved) {
|
|
533
|
+
const sizeData = JSON.parse(saved);
|
|
534
|
+
this.currentSize = sizeData.size || 'default';
|
|
535
|
+
this.containerWidth = sizeData.width || 800;
|
|
536
|
+
this.containerHeight = sizeData.height || 600;
|
|
537
|
+
this.isFullscreen = sizeData.isFullscreen || false;
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
catch (error) {
|
|
541
|
+
console.warn('Failed to load size preference:', error);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
emitSizeChange() {
|
|
545
|
+
this.sizeChanged.emit({
|
|
546
|
+
size: this.currentSize,
|
|
547
|
+
width: this.containerWidth,
|
|
548
|
+
height: this.containerHeight
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
getContainerStyle() {
|
|
552
|
+
if (this.isFullscreen) {
|
|
553
|
+
return {
|
|
554
|
+
width: '100vw !important',
|
|
555
|
+
height: '100vh !important',
|
|
556
|
+
maxWidth: '100vw !important',
|
|
557
|
+
maxHeight: '100vh !important',
|
|
558
|
+
position: 'fixed',
|
|
559
|
+
top: '0',
|
|
560
|
+
left: '0',
|
|
561
|
+
right: '0',
|
|
562
|
+
bottom: '0',
|
|
563
|
+
margin: '0',
|
|
564
|
+
zIndex: 99999
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
return {
|
|
568
|
+
width: `${this.containerWidth}px`,
|
|
569
|
+
height: `${this.containerHeight}px`,
|
|
570
|
+
maxWidth: `${this.maxWidth}px`
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
// ============= File Upload Methods =============
|
|
574
|
+
onImageUpload(event) {
|
|
575
|
+
const input = event.target;
|
|
576
|
+
if (input.files && input.files.length > 0) {
|
|
577
|
+
this.handleFileSelection(Array.from(input.files), 'image');
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
onFileUpload(event) {
|
|
581
|
+
const input = event.target;
|
|
582
|
+
if (input.files && input.files.length > 0) {
|
|
583
|
+
this.handleFileSelection(Array.from(input.files), 'file');
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
handleFileSelection(files, type) {
|
|
587
|
+
files.forEach(file => {
|
|
588
|
+
// Validate file type
|
|
589
|
+
const allowedTypes = type === 'image' ? this.allowedImageTypes : this.allowedFileTypes;
|
|
590
|
+
if (!allowedTypes.includes(file.type)) {
|
|
591
|
+
console.warn(`File type ${file.type} not allowed`);
|
|
592
|
+
return;
|
|
593
|
+
}
|
|
594
|
+
// Validate file size
|
|
595
|
+
if (file.size > this.maxFileSize) {
|
|
596
|
+
console.warn(`File ${file.name} exceeds maximum size of ${this.maxFileSize / 1024 / 1024}MB`);
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
599
|
+
const reader = new FileReader();
|
|
600
|
+
reader.onload = (e) => {
|
|
601
|
+
var _a;
|
|
602
|
+
const attachment = {
|
|
603
|
+
id: this.generateMessageId(),
|
|
604
|
+
name: file.name,
|
|
605
|
+
type: file.type,
|
|
606
|
+
size: file.size,
|
|
607
|
+
data: ((_a = e.target) === null || _a === void 0 ? void 0 : _a.result) || undefined
|
|
608
|
+
};
|
|
609
|
+
this.selectedFiles.push(attachment);
|
|
610
|
+
this.fileUploaded.emit(attachment);
|
|
611
|
+
};
|
|
612
|
+
if (type === 'image') {
|
|
613
|
+
reader.readAsDataURL(file);
|
|
614
|
+
}
|
|
615
|
+
else {
|
|
616
|
+
reader.readAsArrayBuffer(file);
|
|
617
|
+
}
|
|
618
|
+
});
|
|
619
|
+
}
|
|
620
|
+
removeAttachment(attachmentId) {
|
|
621
|
+
this.selectedFiles = this.selectedFiles.filter(f => f.id !== attachmentId);
|
|
622
|
+
}
|
|
623
|
+
triggerImageUpload() {
|
|
624
|
+
const input = document.getElementById('image-upload-input');
|
|
625
|
+
if (input) {
|
|
626
|
+
input.click();
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
triggerFileUpload() {
|
|
630
|
+
const input = document.getElementById('file-upload-input');
|
|
631
|
+
if (input) {
|
|
632
|
+
input.click();
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
getFileIcon(fileType) {
|
|
636
|
+
if (fileType.startsWith('image/'))
|
|
637
|
+
return '🖼️';
|
|
638
|
+
if (fileType.includes('pdf'))
|
|
639
|
+
return '📄';
|
|
640
|
+
if (fileType.includes('word') || fileType.includes('document'))
|
|
641
|
+
return '📝';
|
|
642
|
+
if (fileType.includes('text'))
|
|
643
|
+
return '📃';
|
|
644
|
+
return '📎';
|
|
645
|
+
}
|
|
646
|
+
getFileSizeFormatted(bytes) {
|
|
647
|
+
if (bytes < 1024)
|
|
648
|
+
return bytes + ' B';
|
|
649
|
+
if (bytes < 1024 * 1024)
|
|
650
|
+
return (bytes / 1024).toFixed(1) + ' KB';
|
|
651
|
+
return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
AiChatComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: AiChatComponent, deps: [{ token: i1.AiAgentService }, { token: i2.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component });
|
|
655
|
+
AiChatComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.17", type: AiChatComponent, selector: "emanate-ai-chat", inputs: { title: "title", placeholder: "placeholder", showDebugInfo: "showDebugInfo", apiUrl: "apiUrl", appKey: "appKey", appSource: "appSource", userId: "userId", firstName: "firstName", userName: "userName", templateDesign: "templateDesign", welcomeMessage: "welcomeMessage", historicalMessages: "historicalMessages", conversationId: "conversationId", enableImageUpload: "enableImageUpload", enableFileUpload: "enableFileUpload", iconSet: "iconSet", customIcons: "customIcons" }, outputs: { messageReceived: "messageReceived", messageSent: "messageSent", fileUploaded: "fileUploaded", sizeChanged: "sizeChanged" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"ai-chat-container\" \r\n [ngClass]=\"getThemeClass()\" \r\n [ngStyle]=\"getContainerStyle()\"\r\n [class.fullscreen]=\"isFullscreen\"\r\n [class.resizing]=\"isResizing\">\r\n \r\n <!-- Resize Handles -->\r\n <div class=\"resize-handle resize-handle-right\" \r\n (mousedown)=\"startResize($event, 'width')\"\r\n *ngIf=\"!isFullscreen\"\r\n title=\"Drag to resize width\">\r\n </div>\r\n \r\n <div class=\"resize-handle resize-handle-corner\" \r\n (mousedown)=\"startResize($event, 'both')\"\r\n *ngIf=\"!isFullscreen\"\r\n title=\"Drag to resize\">\r\n </div>\r\n \r\n <!-- Debug Information (only shown when showDebugInfo is true) -->\r\n <div *ngIf=\"showDebugInfo\" class=\"debug-info\">\r\n <h3>DEBUG: AI Chat Component Loaded</h3>\r\n <p>Status: {{ configurationStatus || 'Loading...' }}</p>\r\n <p>Messages count: {{ messages.length || 0 }}</p>\r\n <p>Theme: {{ templateDesign || 'default' }}</p>\r\n <p>Size: {{ currentSize }} ({{ containerWidth }}x{{ containerHeight }})</p>\r\n </div>\r\n\r\n <div class=\"chat-header\">\r\n <div class=\"header-left\">\r\n <h2>{{ title }}</h2>\r\n <!-- Icon-only status indicator -->\r\n <div class=\"status-indicator-icon\" \r\n [ngClass]=\"{'status-ready': configurationStatus === 'AI Agent is ready', \r\n 'status-error': configurationStatus !== 'AI Agent is ready',\r\n 'status-loading': configurationStatus === 'Initializing...' || configurationStatus === 'Testing connection...'}\"\r\n [title]=\"configurationStatus\">\r\n </div>\r\n </div>\r\n \r\n <div class=\"header-controls\">\r\n <!-- Size Preset Buttons -->\r\n <div class=\"size-controls\" *ngIf=\"!isFullscreen\">\r\n <button class=\"control-button size-button\" \r\n (click)=\"applySizePreset('compact')\"\r\n [class.active]=\"currentSize === 'compact'\"\r\n title=\"Compact View\"\r\n attr.aria-label=\"Compact View\">\r\n <span class=\"icon-svg\" [innerHTML]=\"sanitizedIcons.compactView\"></span>\r\n </button>\r\n <button class=\"control-button size-button\" \r\n (click)=\"applySizePreset('default')\"\r\n [class.active]=\"currentSize === 'default'\"\r\n title=\"Default View\"\r\n attr.aria-label=\"Default View\">\r\n <span class=\"icon-svg\" [innerHTML]=\"sanitizedIcons.defaultView\"></span>\r\n </button>\r\n <button class=\"control-button size-button\" \r\n (click)=\"applySizePreset('expanded')\"\r\n [class.active]=\"currentSize === 'expanded'\"\r\n title=\"Expanded View\"\r\n attr.aria-label=\"Expanded View\">\r\n <span class=\"icon-svg\" [innerHTML]=\"sanitizedIcons.expandedView\"></span>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"chat-messages\" #messagesContainer>\r\n <div *ngFor=\"let message of messages; let i = index; trackBy: trackByIndex\" class=\"message-wrapper\">\r\n <!-- Message -->\r\n <div class=\"message\" \r\n [ngClass]=\"{'user-message': message.isUser, 'ai-message': !message.isUser, 'loading-message': message.isLoading}\">\r\n \r\n <div class=\"message-content\">\r\n <div [innerHTML]=\"message.content\"></div>\r\n <div class=\"message-timestamp\">{{ getFormattedTime(message.timestamp) }}</div>\r\n </div>\r\n \r\n <div class=\"message-avatar\">\r\n <span *ngIf=\"message.isUser\" class=\"avatar-icon\" [innerHTML]=\"sanitizedIcons.userAvatar\"></span>\r\n <span *ngIf=\"!message.isUser && !message.isLoading\" class=\"avatar-icon\" [innerHTML]=\"sanitizedIcons.aiAvatar\"></span>\r\n <span *ngIf=\"message.isLoading\" class=\"avatar-icon loading-spinner\" [innerHTML]=\"sanitizedIcons.loadingAvatar\"></span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"chat-input\">\r\n <!-- Attachments Preview -->\r\n <div class=\"attachments-preview\" *ngIf=\"selectedFiles.length > 0\">\r\n <div class=\"attachment-item\" *ngFor=\"let file of selectedFiles\">\r\n <svg class=\"attachment-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <path d=\"M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48\"></path>\r\n </svg>\r\n <span class=\"attachment-name\">{{ file.name }}</span>\r\n <span class=\"attachment-size\">{{ getFileSizeFormatted(file.size) }}</span>\r\n <button class=\"remove-attachment\" (click)=\"removeAttachment(file.id)\" title=\"Remove\" attr.aria-label=\"Remove attachment\">\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\r\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n \r\n <div class=\"input-container\">\r\n <!-- File Upload Inputs (Hidden) -->\r\n <input type=\"file\" \r\n id=\"image-upload-input\" \r\n accept=\"image/*\" \r\n multiple \r\n (change)=\"onImageUpload($event)\"\r\n style=\"display: none;\"\r\n [disabled]=\"!enableImageUpload\">\r\n \r\n <input type=\"file\" \r\n id=\"file-upload-input\" \r\n accept=\".pdf,.doc,.docx,.txt,.csv\" \r\n multiple \r\n (change)=\"onFileUpload($event)\"\r\n style=\"display: none;\"\r\n [disabled]=\"!enableFileUpload\">\r\n \r\n <!-- Upload Buttons (Conditionally rendered) -->\r\n <div class=\"upload-buttons\" *ngIf=\"enableImageUpload || enableFileUpload\">\r\n <button *ngIf=\"enableImageUpload\" \r\n class=\"upload-button image-upload\" \r\n (click)=\"triggerImageUpload()\"\r\n [disabled]=\"isLoading\"\r\n title=\"Upload Image\"\r\n attr.aria-label=\"Upload Image\">\r\n <span class=\"icon-svg\" [innerHTML]=\"sanitizedIcons.imageUpload\"></span>\r\n </button>\r\n \r\n <button *ngIf=\"enableFileUpload\" \r\n class=\"upload-button file-upload\" \r\n (click)=\"triggerFileUpload()\"\r\n [disabled]=\"isLoading\"\r\n title=\"Attach File\"\r\n attr.aria-label=\"Attach File\">\r\n <span class=\"icon-svg\" [innerHTML]=\"sanitizedIcons.fileUpload\"></span>\r\n </button>\r\n </div>\r\n \r\n <textarea \r\n [(ngModel)]=\"currentInquiry\" \r\n (keypress)=\"onKeyPress($event)\"\r\n [placeholder]=\"placeholder\"\r\n rows=\"2\"\r\n [disabled]=\"isLoading\"\r\n class=\"inquiry-textarea\"\r\n attr.aria-label=\"Type your message\"></textarea>\r\n \r\n <button \r\n (click)=\"sendInquiry()\" \r\n [disabled]=\"!currentInquiry.trim() || isLoading\"\r\n class=\"send-button\"\r\n title=\"Send Message\"\r\n attr.aria-label=\"Send Message\">\r\n <span *ngIf=\"!isLoading\" class=\"icon-svg\" [innerHTML]=\"sanitizedIcons.send\"></span>\r\n <span *ngIf=\"isLoading\" class=\"icon-svg loading-icon\" [innerHTML]=\"sanitizedIcons.sendLoading\"></span>\r\n <span class=\"text\">{{ isLoading ? 'Sending...' : 'Send' }}</span>\r\n </button>\r\n </div>\r\n </div>\r\n</div>", styles: ["@charset \"UTF-8\";.ai-chat-container{display:flex;flex-direction:column;height:100vh;max-width:800px;margin:0 auto;background:#ffffff;border-radius:12px;overflow:hidden;position:relative;transition:all .25s cubic-bezier(.4,0,.2,1);box-shadow:0 2px 8px #00000014,0 4px 16px #0000000a;--icon-primary: #667eea;--icon-secondary: #6b7280;--icon-avatar-user: #667eea;--icon-avatar-ai: #764ba2;--icon-header: #ffffff;--icon-upload: #667eea;--icon-send: #ffffff;--icon-active: #667eea;--icon-disabled: #d1d5db;--icon-hover: #5568d3}.ai-chat-container.fullscreen{position:fixed!important;top:0!important;left:0!important;right:0!important;bottom:0!important;width:100vw!important;height:100vh!important;max-width:100vw!important;max-height:100vh!important;border-radius:0;z-index:99999;margin:0}.ai-chat-container.resizing{-webkit-user-select:none;user-select:none;cursor:nwse-resize;transition:none}.resize-handle{position:absolute;background:rgba(102,126,234,.3);transition:background .2s ease;z-index:10}.resize-handle:hover{background:rgba(102,126,234,.6)}.resize-handle.resize-handle-right{top:0;right:-4px;width:8px;height:100%;cursor:ew-resize}.resize-handle.resize-handle-corner{bottom:-4px;right:-4px;width:20px;height:20px;cursor:nwse-resize;border-radius:0 0 8px}.resize-handle.resize-handle-corner:after{content:\"\\22f0\";position:absolute;bottom:2px;right:2px;font-size:12px;color:#fffc}.debug-info{background:yellow;padding:10px;border:1px solid orange}.debug-info h3{margin:0;font-size:1.2rem}.debug-info p{margin:5px 0}.icon-svg{display:inline-block;width:20px;height:20px;color:var(--icon-secondary)}.icon-svg svg{width:100%;height:100%;stroke-width:2;transition:all .2s ease}.avatar-icon{display:inline-block;width:28px;height:28px}.avatar-icon svg{width:100%;height:100%}.chat-header{background:linear-gradient(135deg,#667eea 0%,#764ba2 100%);color:#fff;padding:1rem 1.25rem;display:flex;justify-content:space-between;align-items:center;grid-gap:1rem;gap:1rem;flex-wrap:wrap;box-shadow:0 2px 4px #0000001a}.chat-header .header-left{display:flex;align-items:center;grid-gap:.75rem;gap:.75rem;flex:1;min-width:200px}.chat-header .header-left h2{margin:0;font-size:1.25rem;font-weight:600;letter-spacing:-.01em}.chat-header .header-controls{display:flex;align-items:center;grid-gap:.5rem;gap:.5rem}.chat-header .header-controls .icon-svg{color:var(--icon-header)}.chat-header .status-indicator-icon{width:10px;height:10px;border-radius:50%;background:rgba(255,255,255,.4);transition:all .3s ease;box-shadow:0 0 0 2px #fff3;cursor:help}.chat-header .status-indicator-icon.status-ready{background:#2ecc71;box-shadow:0 0 0 2px #2ecc714d,0 0 8px #2ecc7166}.chat-header .status-indicator-icon.status-error{background:#e74c3c;box-shadow:0 0 0 2px #e74c3c4d,0 0 8px #e74c3c66}.chat-header .status-indicator-icon.status-loading{background:#f39c12;box-shadow:0 0 0 2px #f39c124d;animation:pulse 1.5s ease-in-out infinite}@keyframes pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.6;transform:scale(1.1)}}.size-controls{display:flex;grid-gap:.5rem;gap:.5rem;background:transparent;padding:0;border-radius:0;backdrop-filter:none}.control-button{background:transparent;border:none;border-radius:0;width:28px;height:28px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s cubic-bezier(.4,0,.2,1);color:#fff;padding:0}.control-button .icon-svg{width:18px;height:18px;color:var(--icon-header)}.control-button:hover:not(:disabled){opacity:.8;transform:scale(1.1)}.control-button:active:not(:disabled){transform:scale(.95)}.control-button.active{opacity:1;transform:scale(1.15)}.control-button:disabled{opacity:.4;cursor:not-allowed}.fullscreen-button{background:transparent}.fullscreen-button:hover:not(:disabled){opacity:.8;transform:scale(1.1)}.clear-button{background:transparent}.clear-button:hover:not(:disabled){opacity:.8;transform:scale(1.1);color:#fcc}.chat-messages{flex:1;overflow-y:auto;overflow-x:hidden;padding:1.25rem;display:flex;flex-direction:column;grid-gap:.875rem;gap:.875rem;scroll-behavior:smooth;background:#f8f9fa}.chat-messages::-webkit-scrollbar{width:6px}.chat-messages::-webkit-scrollbar-track{background:transparent}.chat-messages::-webkit-scrollbar-thumb{background:rgba(0,0,0,.15);border-radius:3px}.chat-messages::-webkit-scrollbar-thumb:hover{background:rgba(0,0,0,.25)}.message-wrapper{display:flex;flex-direction:column}.message{display:flex;max-width:75%;animation:fadeInSlide .25s cubic-bezier(.4,0,.2,1)}.message.user-message{align-self:flex-end;flex-direction:row-reverse}.message.user-message .message-content{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;border-radius:18px 18px 4px;box-shadow:0 1px 2px #0000001a}.message.user-message .avatar-icon{color:var(--icon-avatar-user)}.message.ai-message{align-self:flex-start}.message.ai-message .message-content{background:white;color:#1a1a1a;border-radius:18px 18px 18px 4px;border:1px solid #e8e8e8;box-shadow:0 1px 2px #0000000d}.message.ai-message .avatar-icon{color:var(--icon-avatar-ai)}.message.loading-message{opacity:.7}.message.loading-message .message-content{font-style:italic}@keyframes fadeInSlide{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.message-content{padding:.75rem 1rem;margin:0 .5rem;word-wrap:break-word;max-width:100%;line-height:1.5;font-size:.9375rem}.message-timestamp{font-size:.6875rem;opacity:.65;margin-top:.375rem;text-align:right;font-weight:500}.message-avatar{width:36px;height:36px;display:flex;align-items:center;justify-content:center;flex-shrink:0}.message-avatar .avatar-icon{opacity:.9}.loading-spinner{animation:spin 1.2s linear infinite;opacity:.7}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.chat-input{background:white;padding:1rem 1.25rem;border-top:1px solid #e8e8e8;display:flex;flex-direction:column;grid-gap:.75rem;gap:.75rem;box-shadow:0 -2px 8px #0000000a}.input-container{display:flex;grid-gap:.5rem;gap:.5rem;align-items:flex-end}.upload-buttons{display:flex;grid-gap:.5rem;gap:.5rem;flex-direction:column}.upload-button{background:#f5f5f5;border:1px solid #e0e0e0;border-radius:10px;width:42px;height:42px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s cubic-bezier(.4,0,.2,1)}.upload-button .icon-svg{width:20px;height:20px;color:var(--icon-upload)}.upload-button:hover:not(:disabled){background:var(--icon-upload);border-color:var(--icon-upload);transform:translateY(-1px);box-shadow:0 2px 8px #667eea40}.upload-button:hover:not(:disabled) .icon-svg{color:#fff}.upload-button:active:not(:disabled){transform:translateY(0)}.upload-button:disabled{opacity:.4;cursor:not-allowed;background:#fafafa}.attachments-preview{display:flex;flex-wrap:wrap;grid-gap:.5rem;gap:.5rem;padding:.75rem;background:#f8f9fa;border-radius:10px;border:1px solid #e8e8e8}.attachment-item{display:flex;align-items:center;grid-gap:.625rem;gap:.625rem;background:white;border:1px solid #e0e0e0;border-radius:8px;padding:.625rem .875rem;font-size:.875rem;transition:all .2s ease}.attachment-item:hover{border-color:#667eea;box-shadow:0 2px 4px #667eea1a}.attachment-item .attachment-icon{width:20px;height:20px;color:#667eea;flex-shrink:0}.attachment-item .attachment-name{font-weight:500;max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:#1a1a1a}.attachment-item .attachment-size{color:#666;font-size:.75rem;font-weight:500}.attachment-item .remove-attachment{background:transparent;border:none;color:#999;cursor:pointer;padding:.25rem;margin-left:.25rem;transition:all .2s ease;display:flex;align-items:center;justify-content:center;border-radius:4px}.attachment-item .remove-attachment svg{width:16px;height:16px}.attachment-item .remove-attachment:hover{color:#e74c3c;background:rgba(231,76,60,.1)}.inquiry-textarea{flex:1;border:1.5px solid #e0e0e0;border-radius:22px;padding:.875rem 1.125rem;font-family:inherit;font-size:.9375rem;line-height:1.5;resize:none;outline:none;transition:all .2s cubic-bezier(.4,0,.2,1);background:#fafafa}.inquiry-textarea:focus{border-color:#667eea;background:white;box-shadow:0 0 0 3px #667eea14}.inquiry-textarea:disabled{background:#f5f5f5;cursor:not-allowed;opacity:.6}.inquiry-textarea::placeholder{color:#999}.send-button{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;border:none;border-radius:50px;padding:.875rem 1.75rem;font-size:.9375rem;font-weight:600;cursor:pointer;display:flex;align-items:center;grid-gap:.5rem;gap:.5rem;transition:all .2s cubic-bezier(.4,0,.2,1);min-width:110px;justify-content:center;box-shadow:0 2px 8px #667eea40}.send-button .icon-svg{width:18px;height:18px;color:var(--icon-send)}.send-button .loading-icon{animation:spin 1.2s linear infinite}.send-button:hover:not(:disabled){transform:translateY(-1px);box-shadow:0 4px 16px #667eea66}.send-button:active:not(:disabled){transform:translateY(0)}.send-button:disabled{background:#d0d0d0;cursor:not-allowed;box-shadow:none;opacity:.6}@media (max-width: 768px){.ai-chat-container{max-width:100%;border-radius:0;height:100vh}.ai-chat-container:not(.fullscreen){width:100%!important}.resize-handle{display:none}.size-controls{display:none}.chat-header{padding:.875rem 1rem}.chat-header .header-left h2{font-size:1.125rem}.chat-header .status-indicator-icon{width:8px;height:8px}.control-button{width:36px;height:36px}.control-button .icon-svg{width:18px;height:18px}.message{max-width:85%}.message-content{font-size:.875rem}.upload-buttons{flex-direction:row}.input-container{flex-wrap:wrap}.send-button{min-width:90px;padding:.75rem 1.25rem}.send-button .text{display:none}.chat-input{padding:.875rem 1rem}}@media (max-width: 480px){.chat-header{flex-direction:column;align-items:flex-start;grid-gap:.625rem;gap:.625rem}.chat-header .header-controls{width:100%;justify-content:space-between}.control-button{width:34px;height:34px}.control-button .icon-svg{width:16px;height:16px}.message-content{padding:.625rem .875rem;font-size:.875rem}.attachments-preview{flex-direction:column}.attachment-item{width:100%}.attachment-item .attachment-name{max-width:120px}.send-button{padding:.75rem 1rem;min-width:80px}}.control-button:focus,.upload-button:focus,.send-button:focus,.clear-button:focus{outline:3px solid #667eea;outline-offset:2px}@media (prefers-contrast: high){.control-button,.upload-button,.send-button{border:2px solid currentColor}.message-content{border:2px solid currentColor}}@media (prefers-reduced-motion: reduce){*{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}.theme-dark{background:#2c2c2c;--icon-primary: #818cf8;--icon-secondary: #9ca3af;--icon-avatar-user: #818cf8;--icon-avatar-ai: #a78bfa;--icon-header: #e5e7eb;--icon-upload: #818cf8;--icon-send: #ffffff;--icon-active: #818cf8;--icon-disabled: #4b5563;--icon-hover: #6366f1}.theme-dark .chat-header{background:linear-gradient(135deg,#1a1a1a,#333)}.theme-dark .chat-messages{background:#2c2c2c}.theme-dark .ai-message .message-content{background:#3a3a3a;color:#fff;border-color:#555}.theme-dark .chat-input{background:#3a3a3a;border-color:#555}.theme-dark .inquiry-textarea{background:#2c2c2c;color:#fff;border-color:#555}.theme-dark .inquiry-textarea:focus{border-color:#667eea}.theme-dark .attachments-preview{background:#3a3a3a;border-color:#555}.theme-dark .attachment-item{background:#2c2c2c;border-color:#555;color:#fff}.theme-dark .upload-button{background:rgba(255,255,255,.1);border-color:#fff3}.theme-dark .upload-button:hover:not(:disabled){background:rgba(255,255,255,.2)}.theme-blue{background:#e3f2fd;--icon-primary: #1976d2;--icon-secondary: #546e7a;--icon-avatar-user: #1976d2;--icon-avatar-ai: #0288d1;--icon-header: #ffffff;--icon-upload: #1976d2;--icon-send: #ffffff;--icon-active: #1976d2;--icon-disabled: #b0bec5;--icon-hover: #1565c0}.theme-blue .chat-header{background:linear-gradient(135deg,#1976d2,#42a5f5)}.theme-blue .user-message .message-content{background:linear-gradient(135deg,#1976d2,#42a5f5)}.theme-blue .ai-message .message-content{border-color:#bbdefb}.theme-blue .inquiry-textarea:focus{border-color:#1976d2}.theme-blue .send-button{background:linear-gradient(135deg,#1976d2,#42a5f5)}.theme-blue .upload-button{background:rgba(25,118,210,.1);border-color:#1976d24d}.theme-blue .upload-button:hover:not(:disabled){background:rgba(25,118,210,.2)}.theme-green{background:#e8f5e8;--icon-primary: #388e3c;--icon-secondary: #546e7a;--icon-avatar-user: #388e3c;--icon-avatar-ai: #2e7d32;--icon-header: #ffffff;--icon-upload: #388e3c;--icon-send: #ffffff;--icon-active: #388e3c;--icon-disabled: #b0bec5;--icon-hover: #2e7d32}.theme-green .chat-header{background:linear-gradient(135deg,#388e3c,#66bb6a)}.theme-green .user-message .message-content{background:linear-gradient(135deg,#388e3c,#66bb6a)}.theme-green .ai-message .message-content{border-color:#c8e6c9}.theme-green .inquiry-textarea:focus{border-color:#388e3c}.theme-green .send-button{background:linear-gradient(135deg,#388e3c,#66bb6a)}.theme-green .upload-button{background:rgba(56,142,60,.1);border-color:#388e3c4d}.theme-green .upload-button:hover:not(:disabled){background:rgba(56,142,60,.2)}.theme-purple{background:#f3e5f5;--icon-primary: #7b1fa2;--icon-secondary: #6a1b9a;--icon-avatar-user: #7b1fa2;--icon-avatar-ai: #8e24aa;--icon-header: #ffffff;--icon-upload: #7b1fa2;--icon-send: #ffffff;--icon-active: #7b1fa2;--icon-disabled: #ce93d8;--icon-hover: #6a1b9a}.theme-purple .chat-header{background:linear-gradient(135deg,#7b1fa2,#ab47bc)}.theme-purple .user-message .message-content{background:linear-gradient(135deg,#7b1fa2,#ab47bc)}.theme-purple .ai-message .message-content{border-color:#e1bee7}.theme-purple .inquiry-textarea:focus{border-color:#7b1fa2}.theme-purple .send-button{background:linear-gradient(135deg,#7b1fa2,#ab47bc)}.theme-purple .upload-button{background:rgba(123,31,162,.1);border-color:#7b1fa24d}.theme-purple .upload-button:hover:not(:disabled){background:rgba(123,31,162,.2)}.theme-minimal{background:#fafafa;--icon-primary: #333333;--icon-secondary: #757575;--icon-avatar-user: #424242;--icon-avatar-ai: #616161;--icon-header: #333333;--icon-upload: #424242;--icon-send: #ffffff;--icon-active: #333333;--icon-disabled: #bdbdbd;--icon-hover: #212121}.theme-minimal .chat-header{background:#fff;color:#333;border-bottom:1px solid #e0e0e0}.theme-minimal .user-message .message-content{background:#007bff;color:#fff;border-radius:18px}.theme-minimal .ai-message .message-content{background:#f8f9fa;color:#333;border:1px solid #dee2e6}.theme-minimal .send-button{background:#007bff;border-radius:4px}.theme-minimal .upload-button{background:rgba(0,123,255,.1);border-color:#007bff4d}.theme-minimal .upload-button:hover:not(:disabled){background:rgba(0,123,255,.2)}.theme-corporate{background:#f8f9fa}.theme-corporate .chat-header{background:linear-gradient(135deg,#495057,#6c757d)}.theme-corporate .user-message .message-content{background:#495057}.theme-corporate .ai-message .message-content{background:#fff;border-color:#dee2e6}.theme-corporate .inquiry-textarea:focus{border-color:#495057}.theme-corporate .send-button{background:#495057}.theme-corporate .upload-button{background:rgba(73,80,87,.1);border-color:#4950574d}.theme-corporate .upload-button:hover:not(:disabled){background:rgba(73,80,87,.2)}.theme-red{background:#ffebee}.theme-red .chat-header{background:linear-gradient(135deg,#d32f2f,#f44336)}.theme-red .user-message .message-content{background:linear-gradient(135deg,#d32f2f,#f44336)}.theme-red .ai-message .message-content{border-color:#ffcdd2}.theme-red .inquiry-textarea:focus{border-color:#d32f2f}.theme-red .send-button{background:linear-gradient(135deg,#d32f2f,#f44336)}.theme-red .upload-button{background:rgba(211,47,47,.1);border-color:#d32f2f4d}.theme-red .upload-button:hover:not(:disabled){background:rgba(211,47,47,.2)}.theme-yellow{background:#fffde7}.theme-yellow .chat-header{background:linear-gradient(135deg,#f57f17,#ffb300)}.theme-yellow .user-message .message-content{background:linear-gradient(135deg,#f57f17,#ffb300)}.theme-yellow .ai-message .message-content{border-color:#fff9c4}.theme-yellow .inquiry-textarea:focus{border-color:#f57f17}.theme-yellow .send-button{background:linear-gradient(135deg,#f57f17,#ffb300)}.theme-yellow .upload-button{background:rgba(245,127,23,.1);border-color:#f57f174d}.theme-yellow .upload-button:hover:not(:disabled){background:rgba(245,127,23,.2)}.theme-orange{background:#fff3e0}.theme-orange .chat-header{background:linear-gradient(135deg,#e65100,#ff9800)}.theme-orange .user-message .message-content{background:linear-gradient(135deg,#e65100,#ff9800)}.theme-orange .ai-message .message-content{border-color:#ffe0b2}.theme-orange .inquiry-textarea:focus{border-color:#e65100}.theme-orange .send-button{background:linear-gradient(135deg,#e65100,#ff9800)}.theme-orange .upload-button{background:rgba(230,81,0,.1);border-color:#e651004d}.theme-orange .upload-button:hover:not(:disabled){background:rgba(230,81,0,.2)}\n"], directives: [{ type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i4.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
|
|
656
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: AiChatComponent, decorators: [{
|
|
657
|
+
type: Component,
|
|
658
|
+
args: [{
|
|
659
|
+
selector: 'emanate-ai-chat',
|
|
660
|
+
templateUrl: './ai-chat.component.html',
|
|
661
|
+
styleUrls: ['./ai-chat.component.scss']
|
|
662
|
+
}]
|
|
663
|
+
}], ctorParameters: function () { return [{ type: i1.AiAgentService }, { type: i2.DomSanitizer }]; }, propDecorators: { title: [{
|
|
664
|
+
type: Input
|
|
665
|
+
}], placeholder: [{
|
|
666
|
+
type: Input
|
|
667
|
+
}], showDebugInfo: [{
|
|
668
|
+
type: Input
|
|
669
|
+
}], apiUrl: [{
|
|
670
|
+
type: Input
|
|
671
|
+
}], appKey: [{
|
|
672
|
+
type: Input
|
|
673
|
+
}], appSource: [{
|
|
674
|
+
type: Input
|
|
675
|
+
}], userId: [{
|
|
676
|
+
type: Input
|
|
677
|
+
}], firstName: [{
|
|
678
|
+
type: Input
|
|
679
|
+
}], userName: [{
|
|
680
|
+
type: Input
|
|
681
|
+
}], templateDesign: [{
|
|
682
|
+
type: Input
|
|
683
|
+
}], welcomeMessage: [{
|
|
684
|
+
type: Input
|
|
685
|
+
}], historicalMessages: [{
|
|
686
|
+
type: Input
|
|
687
|
+
}], conversationId: [{
|
|
688
|
+
type: Input
|
|
689
|
+
}], enableImageUpload: [{
|
|
690
|
+
type: Input
|
|
691
|
+
}], enableFileUpload: [{
|
|
692
|
+
type: Input
|
|
693
|
+
}], iconSet: [{
|
|
694
|
+
type: Input
|
|
695
|
+
}], customIcons: [{
|
|
696
|
+
type: Input
|
|
697
|
+
}], messageReceived: [{
|
|
698
|
+
type: Output
|
|
699
|
+
}], messageSent: [{
|
|
700
|
+
type: Output
|
|
701
|
+
}], fileUploaded: [{
|
|
702
|
+
type: Output
|
|
703
|
+
}], sizeChanged: [{
|
|
704
|
+
type: Output
|
|
705
|
+
}] } });
|
|
706
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWktY2hhdC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9lbWFuYXRlLWFpLWNoYXQtbGliL3NyYy9saWIvY29tcG9uZW50cy9haS1jaGF0LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2VtYW5hdGUtYWktY2hhdC1saWIvc3JjL2xpYi9jb21wb25lbnRzL2FpLWNoYXQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBK0MsTUFBTSxlQUFlLENBQUM7QUFFcEgsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUMvQixPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFM0MsT0FBTyxFQUErQixVQUFVLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQzs7Ozs7O0FBZ0MxRixNQUFNLE9BQU8sZUFBZTtJQTJEMUIsWUFDVSxjQUE4QixFQUM5QixTQUF1QjtRQUR2QixtQkFBYyxHQUFkLGNBQWMsQ0FBZ0I7UUFDOUIsY0FBUyxHQUFULFNBQVMsQ0FBYztRQTVEeEIsVUFBSyxHQUFXLG1CQUFtQixDQUFDO1FBQ3BDLGdCQUFXLEdBQVcsMkVBQTJFLENBQUM7UUFDbEcsa0JBQWEsR0FBWSxLQUFLLENBQUM7UUFXL0Isc0JBQWlCLEdBQVksS0FBSyxDQUFDLENBQUMscUNBQXFDO1FBQ3pFLHFCQUFnQixHQUFZLEtBQUssQ0FBQyxDQUFFLG9DQUFvQztRQUN4RSxZQUFPLEdBQWdCLFNBQVMsQ0FBQyxDQUFHLHFCQUFxQjtRQUV4RCxvQkFBZSxHQUFHLElBQUksWUFBWSxFQUFlLENBQUM7UUFDbEQsZ0JBQVcsR0FBRyxJQUFJLFlBQVksRUFBZSxDQUFDO1FBQzlDLGlCQUFZLEdBQUcsSUFBSSxZQUFZLEVBQWtCLENBQUM7UUFDbEQs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akIsS0FBSztnQkFDRyxRQUFRO3NCQUFoQixLQUFLO2dCQUNHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBQ0csY0FBYztzQkFBdEIsS0FBSztnQkFDRyxrQkFBa0I7c0JBQTFCLEtBQUs7Z0JBQ0csY0FBYztzQkFBdEIsS0FBSztnQkFDRyxpQkFBaUI7c0JBQXpCLEtBQUs7Z0JBQ0csZ0JBQWdCO3NCQUF4QixLQUFLO2dCQUNHLE9BQU87c0JBQWYsS0FBSztnQkFDRyxXQUFXO3NCQUFuQixLQUFLO2dCQUNJLGVBQWU7c0JBQXhCLE1BQU07Z0JBQ0csV0FBVztzQkFBcEIsTUFBTTtnQkFDRyxZQUFZO3NCQUFyQixNQUFNO2dCQUNHLFdBQVc7c0JBQXBCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIElucHV0LCBPdXRwdXQsIEV2ZW50RW1pdHRlciwgT25Jbml0LCBPbkRlc3Ryb3ksIE9uQ2hhbmdlcywgU2ltcGxlQ2hhbmdlcyB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBEb21TYW5pdGl6ZXIsIFNhZmVIdG1sIH0gZnJvbSAnQGFuZ3VsYXIvcGxhdGZvcm0tYnJvd3Nlcic7XHJcbmltcG9ydCB7IFN1YmplY3QgfSBmcm9tICdyeGpzJztcclxuaW1wb3J0IHsgdGFrZVVudGlsIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xyXG5pbXBvcnQgeyBBaUFnZW50U2VydmljZSwgQWdlbnRSZXNwb25zZSwgU3VwcG9ydEJvdFJlcXVlc3QsIFN1cHBvcnRCb3RSZXNwb25zZSwgQ2hhdENvbnRlbnQgfSBmcm9tICcuLi9zZXJ2aWNlcy9haS1hZ2VudC5zZXJ2aWNlJztcclxuaW1wb3J0IHsgSWNvblNldFR5cGUsIENoYXRJY29uQ29uZmlnLCBnZXRJY29uU2V0IH0gZnJvbSAnLi4vbW9kZWxzL2ljb24tY29uZmlnLmludGVyZmFjZSc7XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIENoYXRNZXNzYWdlIHtcclxuICBtZXNzYWdlSWQ/OiBzdHJpbmc7ICAgICAgICAgICAvLyBVbmlxdWUgbWVzc2FnZSBpZGVudGlmaWVyXHJcbiAgY29udmVyc2F0aW9uSWQ/OiBzdHJpbmc7ICAgICAgIC8vIENvbnZlcnNhdGlvbi9zZXNzaW9uIGlkZW50aWZpZXJcclxuICBpc1VzZXI6IGJvb2xlYW47XHJcbiAgY29udGVudDogc3RyaW5nO1xyXG4gIHNlbmRlcj86IHN0cmluZzsgICAgICAgICAgICAgICAvLyBTZW5kZXIgbmFtZSAobWFwcyB0byB5b3VyICdzZW5kZXInIGZpZWxkKVxyXG4gIGludGVudD86IHN0cmluZztcclxuICBhdXRob3JOYW1lPzogc3RyaW5nO1xyXG4gIGNvbmZpZGVuY2VTY29yZT86IG51bWJlcjsgICAgICAvLyBBSSBjb25maWRlbmNlIHNjb3JlXHJcbiAgdGltZXN0YW1wOiBEYXRlO1xyXG4gIGlzTG9hZGluZz86IGJvb2xlYW47XHJcbiAgYXR0YWNobWVudHM/OiBGaWxlQXR0YWNobWVudFtdOyAvLyBGaWxlL0ltYWdlIGF0dGFjaG1lbnRzXHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgRmlsZUF0dGFjaG1lbnQge1xyXG4gIGlkOiBzdHJpbmc7XHJcbiAgbmFtZTogc3RyaW5nO1xyXG4gIHR5cGU6IHN0cmluZztcclxuICBzaXplOiBudW1iZXI7XHJcbiAgdXJsPzogc3RyaW5nO1xyXG4gIGRhdGE/OiBzdHJpbmcgfCBBcnJheUJ1ZmZlcjtcclxufVxyXG5cclxuZXhwb3J0IHR5cGUgQ2hhdFNpemUgPSAnY29tcGFjdCcgfCAnZGVmYXVsdCcgfCAnZXhwYW5kZWQnIHwgJ2Z1bGxzY3JlZW4nO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdlbWFuYXRlLWFpLWNoYXQnLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi9haS1jaGF0LmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybHM6IFsnLi9haS1jaGF0LmNvbXBvbmVudC5zY3NzJ11cclxufSlcclxuZXhwb3J0IGNsYXNzIEFpQ2hhdENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95LCBPbkNoYW5nZXMge1xyXG4gIEBJbnB1dCgpIHRpdGxlOiBzdHJpbmcgPSAnQ2hhdCB3aXRoIE1hZXN0cm8nO1xyXG4gIEBJbnB1dCgpIHBsYWNlaG9sZGVyOiBzdHJpbmcgPSAnVHlwZSB5b3VyIGlucXVpcnkgaGVyZS4uLiAoUHJlc3MgRW50ZXIgdG8gc2VuZCwgU2hpZnQrRW50ZXIgZm9yIG5ldyBsaW5lKSc7XHJcbiAgQElucHV0KCkgc2hvd0RlYnVnSW5mbzogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIEBJbnB1dCgpIGFwaVVybD86IHN0cmluZztcclxuICBASW5wdXQoKSBhcHBLZXk/OiBzdHJpbmc7XHJcbiAgQElucHV0KCkgYXBwU291cmNlPzogc3RyaW5nO1xyXG4gIEBJbnB1dCgpIHVzZXJJZD86IHN0cmluZztcclxuICBASW5wdXQoKSBmaXJzdE5hbWU/OiBzdHJpbmc7XHJcbiAgQElucHV0KCkgdXNlck5hbWU/OiBzdHJpbmc7XHJcbiAgQElucHV0KCkgdGVtcGxhdGVEZXNpZ24/OiBzdHJpbmc7XHJcbiAgQElucHV0KCkgd2VsY29tZU1lc3NhZ2U/OiBzdHJpbmc7XHJcbiAgQElucHV0KCkgaGlzdG9yaWNhbE1lc3NhZ2VzPzogYW55W107IC8vIEhpc3RvcmljYWwgbWVzc2FnZXMgZnJvbSBwYXJlbnRcclxuICBASW5wdXQoKSBjb252ZXJzYXRpb25JZD86IHN0cmluZzsgICAgLy8gQ3VycmVudCBjb252ZXJzYXRpb24gSURcclxuICBASW5wdXQoKSBlbmFibGVJbWFnZVVwbG9hZDogYm9vbGVhbiA9IGZhbHNlOyAvLyBFbmFibGUvZGlzYWJsZSBpbWFnZSB1cGxvYWQgYnV0dG9uXHJcbiAgQElucHV0KCkgZW5hYmxlRmlsZVVwbG9hZDogYm9vbGVhbiA9IGZhbHNlOyAgLy8gRW5hYmxlL2Rpc2FibGUgZmlsZSB1cGxvYWQgYnV0dG9uXHJcbiAgQElucHV0KCkgaWNvblNldDogSWNvblNldFR5cGUgPSAnZmVhdGhlcic7ICAgLy8gSWNvbiBzZXQgc2VsZWN0aW9uXHJcbiAgQElucHV0KCkgY3VzdG9tSWNvbnM/OiBQYXJ0aWFsPENoYXRJY29uQ29uZmlnPjsgLy8gQ3VzdG9tIGljb24gb3ZlcnJpZGVzXHJcbiAgQE91dHB1dCgpIG1lc3NhZ2VSZWNlaXZlZCA9IG5ldyBFdmVudEVtaXR0ZXI8Q2hhdE1lc3NhZ2U+KCk7XHJcbiAgQE91dHB1dCgpIG1lc3NhZ2VTZW50ID0gbmV3IEV2ZW50RW1pdHRlcjxDaGF0TWVzc2FnZT4oKTtcclxuICBAT3V0cHV0KCkgZmlsZVVwbG9hZGVkID0gbmV3IEV2ZW50RW1pdHRlcjxGaWxlQXR0YWNobWVudD4oKTtcclxuICBAT3V0cHV0KCkgc2l6ZUNoYW5nZWQgPSBuZXcgRXZlbnRFbWl0dGVyPHsgc2l6ZTogQ2hhdFNpemUsIHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyIH0+KCk7XHJcblxyXG4gIG1lc3NhZ2VzOiBDaGF0TWVzc2FnZVtdID0gW107XHJcbiAgY3VycmVudElucXVpcnkgPSAnJztcclxuICBhdXRob3JOYW1lID0gJyc7XHJcbiAgaW50ZW50ID0gJyc7XHJcbiAgaXNMb2FkaW5nID0gZmFsc2U7XHJcbiAgY29uZmlndXJhdGlvblN0YXR1cyA9ICcnO1xyXG4gIFxyXG4gIC8vIFJlc2l6aW5nIHByb3BlcnRpZXNcclxuICBjdXJyZW50U2l6ZTogQ2hhdFNpemUgPSAnZGVmYXVsdCc7XHJcbiAgaXNGdWxsc2NyZWVuID0gZmFsc2U7XHJcbiAgaXNSZXNpemluZyA9IGZhbHNlO1xyXG4gIGNvbnRhaW5lcldpZHRoID0gODAwO1xyXG4gIGNvbnRhaW5lckhlaWdodCA9IDYwMDtcclxuICBtaW5XaWR0aCA9IDQwMDtcclxuICBtYXhXaWR0aCA9IDE0MDA7XHJcbiAgbWluSGVpZ2h0ID0gNDAwO1xyXG4gIG1heEhlaWdodCA9IHdpbmRvdy5pbm5lckhlaWdodCAtIDEwMDtcclxuICBzdGFydFggPSAwO1xyXG4gIHN0YXJ0WSA9IDA7XHJcbiAgc3RhcnRXaWR0aCA9IDA7XHJcbiAgc3RhcnRIZWlnaHQgPSAwO1xyXG4gIFxyXG4gIC8vIEZpbGUgdXBsb2FkIHByb3BlcnRpZXNcclxuICBtYXhGaWxlU2l6ZSA9IDEwICogMTAyNCAqIDEwMjQ7IC8vIDEwTUJcclxuICBhbGxvd2VkSW1hZ2VUeXBlcyA9IFsnaW1hZ2UvcG5nJywgJ2ltYWdlL2pwZWcnLCAnaW1hZ2UvanBnJywgJ2ltYWdlL2dpZicsICdpbWFnZS93ZWJwJ107XHJcbiAgYWxsb3dlZEZpbGVUeXBlcyA9IFsnYXBwbGljYXRpb24vcGRmJywgJ2FwcGxpY2F0aW9uL21zd29yZCcsIFxyXG4gICAgJ2FwcGxpY2F0aW9uL3ZuZC5vcGVueG1sZm9ybWF0cy1vZmZpY2Vkb2N1bWVudC53b3JkcHJvY2Vzc2luZ21sLmRvY3VtZW50JyxcclxuICAgICd0ZXh0L3BsYWluJywgJ3RleHQvY3N2J107XHJcbiAgc2VsZWN0ZWRGaWxlczogRmlsZUF0dGFjaG1lbnRbXSA9IFtdO1xyXG4gIFxyXG4gIC8vIEljb24gY29uZmlndXJhdGlvblxyXG4gIGljb25zOiBDaGF0SWNvbkNvbmZpZyA9IGdldEljb25TZXQoJ2ZlYXRoZXInKTtcclxuICBzYW5pdGl6ZWRJY29uczogeyBba2V5OiBzdHJpbmddOiBTYWZlSHRtbCB9ID0ge307XHJcbiAgXHJcbiAgcHJpdmF0ZSBkZXN0cm95JCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgcHJpdmF0ZSBhaUFnZW50U2VydmljZTogQWlBZ2VudFNlcnZpY2UsXHJcbiAgICBwcml2YXRlIHNhbml0aXplcjogRG9tU2FuaXRpemVyXHJcbiAgKSB7fVxyXG5cclxuICBuZ09uSW5pdCgpOiB2b2lkIHtcclxuICAgIHRoaXMuY29uZmlndXJhdGlvblN0YXR1cyA9ICdJbml0aWFsaXppbmcuLi4nO1xyXG4gICAgY29uc29sZS5sb2coJ0FJIENoYXQgQ29tcG9uZW50IGluaXRpYWxpemVkJyk7XHJcbiAgICBcclxuICAgIC8vIExvYWQgaWNvbiBzZXRcclxuICAgIHRoaXMuaWNvbnMgPSBnZXRJY29uU2V0KHRoaXMuaWNvblNldCwgdGhpcy5jdXN0b21JY29ucyk7XHJcbiAgICB0aGlzLnNhbml0aXplSWNvbnMoKTtcclxuICAgIFxyXG4gICAgLy8gQ29uZmlndXJlIEFQSSBVUkwgYW5kIEFwcCBLZXkgaWYgcHJvdmlkZWRcclxuICAgIGlmICh0aGlzLmFwaVVybCB8fCB0aGlzLmFwcEtleSkge1xyXG4gICAgICB0aGlzLmFpQWdlbnRTZXJ2aWNlLmNvbmZpZ3VyZSh7IFxyXG4gICAgICAgIGFwaVVybDogdGhpcy5hcGlVcmwsXHJcbiAgICAgICAgYXBwS2V5OiB0aGlzLmFwcEtleSBcclxuICAgICAgfSk7XHJcbiAgICB9XHJcbiAgICBcclxuICAgIHRyeSB7XHJcbiAgICAgIC8vIExvYWQgaGlzdG9yaWNhbCBtZXNzYWdlcyBpZiBwcm92aWRlZFxyXG4gICAgICBpZiAodGhpcy5oaXN0b3JpY2FsTWVzc2FnZXMgJiYgdGhpcy5oaXN0b3JpY2FsTWVzc2FnZXMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgIHRoaXMubG9hZEhpc3RvcmljYWxNZXNzYWdlcyh0aGlzLmhpc3RvcmljYWxNZXNzYWdlcyk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdGhpcy5hZGRXZWxjb21lTWVzc2FnZSgpO1xyXG4gICAgICB9XHJcbiAgICAgIFxyXG4gICAgICB0aGlzLnRlc3RDb25maWd1cmF0aW9uKCk7XHJcbiAgICAgIHRoaXMubG9hZFNhdmVkU2l6ZSgpO1xyXG4gICAgICB0aGlzLmFwcGx5U2l6ZVByZXNldCh0aGlzLmN1cnJlbnRTaXplKTtcclxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGR1cmluZyBjb21wb25lbnQgaW5pdGlhbGl6YXRpb246JywgZXJyb3IpO1xyXG4gICAgICB0aGlzLmNvbmZpZ3VyYXRpb25TdGF0dXMgPSAnSW5pdGlhbGl6YXRpb24gZXJyb3InO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xyXG4gICAgLy8gRGV0ZWN0IHdoZW4gaGlzdG9yaWNhbE1lc3NhZ2VzIGlucHV0IGNoYW5nZXNcclxuICAgIGlmIChjaGFuZ2VzWydoaXN0b3JpY2FsTWVzc2FnZXMnXSAmJiAhY2hhbmdlc1snaGlzdG9yaWNhbE1lc3NhZ2VzJ10uZmlyc3RDaGFuZ2UpIHtcclxuICAgICAgY29uc3QgbmV3TWVzc2FnZXMgPSBjaGFuZ2VzWydoaXN0b3JpY2FsTWVzc2FnZXMnXS5jdXJyZW50VmFsdWU7XHJcbiAgICAgIC8vIGNvbnNvbGUubG9nKCdIaXN0b3JpY2FsIG1lc3NhZ2VzIGNoYW5nZWQ6JywgbmV3TWVzc2FnZXMpO1xyXG4gICAgICBcclxuICAgICAgLy8gQ2xlYXIgZXhpc3RpbmcgbWVzc2FnZXMgYW5kIHJlbG9hZFxyXG4gICAgICB0aGlzLm1lc3NhZ2VzID0gW107XHJcbiAgICAgIFxyXG4gICAgICBpZiAobmV3TWVzc2FnZXMgJiYgbmV3TWVzc2FnZXMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgIHRoaXMubG9hZEhpc3RvcmljYWxNZXNzYWdlcyhuZXdNZXNzYWdlcyk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdGhpcy5hZGRXZWxjb21lTWVzc2FnZSgpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICBcclxuICAgIC8vIERldGVjdCB3aGVuIGNvbnZlcnNhdGlvbklkIGNoYW5nZXNcclxuICAgIGlmIChjaGFuZ2VzWydjb252ZXJzYXRpb25JZCddICYmICFjaGFuZ2VzWydjb252ZXJzYXRpb25JZCddLmZpcnN0Q2hhbmdlKSB7XHJcbiAgICAgIC8vIGNvbnNvbGUubG9nKCdDb252ZXJzYXRpb24gSUQgY2hhbmdlZDonLCBjaGFuZ2VzWydjb252ZXJzYXRpb25JZCddLmN1cnJlbnRWYWx1ZSk7XHJcbiAgICAgIC8vIFVwZGF0ZSBhbGwgZXhpc3RpbmcgbWVzc2FnZXMgd2l0aCBuZXcgY29udmVyc2F0aW9uSWQgaWYgbmVlZGVkXHJcbiAgICAgIHRoaXMubWVzc2FnZXMuZm9yRWFjaChtc2cgPT4ge1xyXG4gICAgICAgIGlmIChtc2cuY29udmVyc2F0aW9uSWQgIT09IHRoaXMuY29udmVyc2F0aW9uSWQpIHtcclxuICAgICAgICAgIG1zZy5jb252ZXJzYXRpb25JZCA9IHRoaXMuY29udmVyc2F0aW9uSWQ7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuICAgIH1cclxuICAgIFxyXG4gICAgLy8gRGV0ZWN0IHdoZW4gaWNvbiBzZXQgY2hhbmdlc1xyXG4gICAgaWYgKGNoYW5nZXNbJ2ljb25TZXQnXSB8fCBjaGFuZ2VzWydjdXN0b21JY29ucyddKSB7XHJcbiAgICAgIHRoaXMuaWNvbnMgPSBnZXRJY29uU2V0KHRoaXMuaWNvblNldCwgdGhpcy5jdXN0b21JY29ucyk7XHJcbiAgICAgIHRoaXMuc2FuaXRpemVJY29ucygpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcbiAgICB0aGlzLmRlc3Ryb3kkLm5leHQoKTtcclxuICAgIHRoaXMuZGVzdHJveSQuY29tcGxldGUoKTtcclxuICB9XHJcbiAgXHJcbiAgLyoqXHJcbiAgICogU2FuaXRpemUgaWNvbiBTVkcgc3RyaW5ncyBmb3Igc2FmZSByZW5kZXJpbmcgaW4gaW5uZXJIVE1MIGJpbmRpbmdzXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBzYW5pdGl6ZUljb25zKCk6IHZvaWQge1xyXG4gICAgdGhpcy5zYW5pdGl6ZWRJY29ucyA9IHt9O1xyXG4gICAgT2JqZWN0LmtleXModGhpcy5pY29ucykuZm9yRWFjaChrZXkgPT4ge1xyXG4gICAgICBjb25zdCBzdmdTdHJpbmcgPSB0aGlzLmljb25zW2tleSBhcyBrZXlvZiBDaGF0SWNvbkNvbmZpZ107XHJcbiAgICAgIGlmIChzdmdTdHJpbmcpIHtcclxuICAgICAgICB0aGlzLnNhbml0aXplZEljb25zW2tleV0gPSB0aGlzLnNhbml0aXplci5ieXBhc3NTZWN1cml0eVRydXN0SHRtbChzdmdTdHJpbmcpO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHRlc3RDb25maWd1cmF0aW9uKCk6IHZvaWQge1xyXG4gICAgdGhpcy5jb25maWd1cmF0aW9uU3RhdHVzID0gJ1Rlc3RpbmcgY29ubmVjdGlvbi4uLic7XHJcbiAgICBcclxuICAgIHRoaXMuYWlBZ2VudFNlcnZpY2UudGVzdENvbmZpZ3VyYXRpb24oKVxyXG4gICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpXHJcbiAgICAgIC5zdWJzY3JpYmUoe1xyXG4gICAgICAgIG5leHQ6IChyZXNwb25zZTogQWdlbnRSZXNwb25zZSkgPT4ge1xyXG4gICAgICAgICAgaWYgKHJlc3BvbnNlLnN1Y2Nlc3MpIHtcclxuICAgICAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uU3RhdHVzID0gJ0FJIEFnZW50IGlzIHJlYWR5JztcclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvblN0YXR1cyA9IGBDb25maWd1cmF0aW9uIGVycm9yOiAke3Jlc3BvbnNlLmVycm9yfWA7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSxcclxuICAgICAgICBlcnJvcjogKGVycm9yUmVzcG9uc2U6IGFueSkgPT4ge1xyXG4gICAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uU3RhdHVzID0gYENvbm5lY3Rpb24gZXJyb3I6IENhbm5vdCBjb25uZWN0IHRvIGJhY2tlbmQgc2VydmljZWA7XHJcbiAgICAgICAgICBjb25zb2xlLmVycm9yKCdBUEkgY29ubmVjdGlvbiB0ZXN0IGZhaWxlZDonLCBlcnJvclJlc3BvbnNlKTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgYWRkV2VsY29tZU1lc3NhZ2UoKTogdm9pZCB7XHJcbiAgICBjb25zdCB3ZWxjb21lVGV4dCA9IHRoaXMud2VsY29tZU1lc3NhZ2UgfHwgXHJcbiAgICAgIGA8aDM+SGVsbG8gJHt0aGlzLmZpcnN0TmFtZX0hPC9oMz5IaSwgSSdtIE1hZXN0cm/igJR5b3VyIEFJIGFzc2lzdGFudC4gSSdtIGhlcmUgdG8gaGVscCB3aXRoIHlvdXIgcG9saWN5LXJlbGF0ZWQgaW5xdWlyaWVzLjxicj48YnI+SG93IGNhbiBJIGFzc2lzdCB5b3UgdG9kYXk/YDtcclxuICAgIFxyXG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKHtcclxuICAgICAgaXNVc2VyOiBmYWxzZSxcclxuICAgICAgY29udGVudDogd2VsY29tZVRleHQsIC8vIERvbid0IGZvcm1hdCBIVE1MIGNvbnRlbnQsIHVzZSBpdCBkaXJlY3RseVxyXG4gICAgICBpbnRlbnQ6ICd3ZWxjb21lJyxcclxuICAgICAgdGltZXN0YW1wOiBuZXcgRGF0ZSgpXHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIExvYWQgYW5kIHRyYW5zZm9ybSBoaXN0b3JpY2FsIG1lc3NhZ2VzIGZyb20gcGFyZW50IGNvbXBvbmVudFxyXG4gICAqIEFjY2VwdHMgbWVzc2FnZXMgaW4gdGhlIGZvcm1hdCBmcm9tIHlvdXIgYmFja2VuZC9zdGF0ZSBtYW5hZ2VtZW50XHJcbiAgICovXHJcbiAgbG9hZEhpc3RvcmljYWxNZXNzYWdlcyhoaXN0b3JpY2FsTWVzc2FnZXM6IGFueVtdKTogdm9pZCB7XHJcbiAgICAvLyBjb25zb2xlLmxvZygnTG9hZGluZyBoaXN0b3JpY2FsIG1lc3NhZ2VzOicsIGhpc3RvcmljYWxNZXNzYWdlcyk7XHJcbiAgICAvLyBjb25zb2xlLmxvZygnTnVtYmVyIG9mIG1lc3NhZ2VzIHRvIGxvYWQ6JywgaGlzdG9yaWNhbE1lc3NhZ2VzLmxlbmd0aCk7XHJcbiAgICBcclxuICAgIC8vIFRyYW5zZm9ybSB5b3VyIGJhY2tlbmQgZm9ybWF0IHRvIENoYXRNZXNzYWdlIGZvcm1hdFxyXG4gICAgY29uc3QgdHJhbnNmb3JtZWRNZXNzYWdlczogQ2hhdE1lc3NhZ2VbXSA9IGhpc3RvcmljYWxNZXNzYWdlcy5tYXAoKG1zZzogYW55KSA9PiB7XHJcbiAgICAgIC8vIERldGVybWluZSBpZiBtZXNzYWdlIGlzIGZyb20gdXNlciBiYXNlZCBvbiBzZW5kZXIgb3Igcm9sZVxyXG4gICAgICBjb25zdCBpc1VzZXJNZXNzYWdlID0gdGhpcy5pc1VzZXJNZXNzYWdlKG1zZyk7XHJcbiAgICAgIFxyXG4gICAgICBjb25zdCB0cmFuc2Zvcm1lZCA9IHtcclxuICAgICAgICBtZXNzYWdlSWQ6IG1zZy5tZXNzYWdlSWQgfHwgbXNnLmlkLFxyXG4gICAgICAgIGNvbnZlcnNhdGlvbklkOiBtc2cuY29udmVyc2F0aW9uSWQgfHwgdGhpcy5jb252ZXJzYXRpb25JZCxcclxuICAgICAgICBpc1VzZXI6IGlzVXNlck1lc3NhZ2UsXHJcbiAgICAgICAgY29udGVudDogbXNnLm1lc3NhZ2VUZXh0IHx8IG1zZy5tZXNzYWdlIHx8IG1zZy50ZXh0IHx8IG1zZy5jb250ZW50IHx8ICcnLFxyXG4gICAgICAgIHNlbmRlcjogbXNnLnNlbmRlciB8fCAoaXNVc2VyTWVzc2FnZSA/IHRoaXMudXNlck5hbWUgfHwgJ1VzZXInIDogJ01hZXN0cm8nKSxcclxuICAgICAgICBpbnRlbnQ6IG1zZy5pbnRlbnQgfHwgJycsXHJcbiAgICAgICAgYXV0aG9yTmFtZTogbXNnLmF1dGhvck5hbWUgfHwgbXNnLnNlbmRlcixcclxuICAgICAgICBjb25maWRlbmNlU2NvcmU6IG1zZy5jb25maWRlbmNlU2NvcmUgfHwgbXNnLmNvbmZpZGVuY2UgfHwgMCxcclxuICAgICAgICB0aW1lc3RhbXA6IG1zZy50aW1lc3RhbXAgfHwgbXNnLmNyZWF0ZWRBdCBcclxuICAgICAgICAgID8gbmV3IERhdGUobXNnLnRpbWVzdGFtcCB8fCBtc2cuY3JlYXRlZEF0KSBcclxuICAgICAgICAgIDogbmV3IERhdGUoKSxcclxuICAgICAgICBpc0xvYWRpbmc6IGZhbHNlXHJcbiAgICAgIH0gYXMgQ2hhdE1lc3NhZ2U7XHJcbiAgICAgIFxyXG4gICAgICAvLyBjb25zb2xlLmxvZygnVHJhbnNmb3JtZWQgbWVzc2FnZTonLCB0cmFuc2Zvcm1lZCk7XHJcbiAgICAgIHJldHVybiB0cmFuc2Zvcm1lZDtcclxuICAgIH0pO1xyXG4gICAgXHJcbiAgICAvLyBTb3J0IG1lc3NhZ2VzIGJ5IHRpbWVzdGFtcCB0byBtYWludGFpbiBjaHJvbm9sb2dpY2FsIG9yZGVyXHJcbiAgICB0cmFuc2Zvcm1lZE1lc3NhZ2VzLnNvcnQoKGEsIGIpID0+IFxyXG4gICAgICBhLnRpbWVzdGFtcC5nZXRUaW1lKCkgLSBiLnRpbWVzdGFtcC5nZXRUaW1lKClcclxuICAgICk7XHJcbiAgICBcclxuICAgIC8vIGNvbnNvbGUubG9nKCdTb3J0ZWQgbWVzc2FnZXMgY291bnQ6JywgdHJhbnNmb3JtZWRNZXNzYWdlcy5sZW5ndGgpO1xyXG4gICAgXHJcbiAgICAvLyBBZGQgd2VsY29tZSBtZXNzYWdlIGZpcnN0IGlmIG5vIG1lc3NhZ2VzIG9yIGxvYWQgaGlzdG9yaWNhbCBtZXNzYWdlc1xyXG4gICAgaWYgKHRyYW5zZm9ybWVkTWVzc2FnZXMubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgIC8vIGNvbnNvbGUubG9nKCdObyBtZXNzYWdlcyB0byBsb2FkLCBhZGRpbmcgd2VsY29tZSBtZXNzYWdlJyk7XHJcbiAgICAgIHRoaXMuYWRkV2VsY29tZU1lc3NhZ2UoKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIC8vIENoZWNrIGlmIGZpcnN0IG1lc3NhZ2UgaXMgYSB3ZWxjb21lIG1lc3NhZ2UsIGlmIG5vdCBhZGQgb25lXHJcbiAgICAgIGNvbnN0IGhhc1dlbGNvbWUgPSB0cmFuc2Zvcm1lZE1lc3NhZ2VzLnNvbWUobXNnID0+IFxyXG4gICAgICAgIG1zZy5pbnRlbnQgPT09ICd3ZWxjb21lJyB8fCBtc2cuY29udGVudC5pbmNsdWRlcygnSGVsbG8nKVxyXG4gICAgICApO1xyXG4gICAgICBcclxuICAgICAgaWYgKCFoYXNXZWxjb21lKSB7XHJcbiAgICAgICAgLy8gY29uc29sZS5sb2coJ05vIHdlbGNvbWUgbWVzc2FnZSBmb3VuZCwgYWRkaW5nIG9uZScpO1xyXG4gICAgICAgIHRoaXMuYWRkV2VsY29tZU1lc3NhZ2UoKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gY29uc29sZS5sb2coJ1B1c2hpbmcgdHJhbnNmb3JtZWQgbWVzc2FnZXMgdG8gbWVzc2FnZXMgYXJyYXknKTtcclxuICAgICAgdGhpcy5tZXNzYWdlcy5wdXNoKC4uLnRyYW5zZm9ybWVkTWVzc2FnZXMpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIGNvbnNvbGUubG9nKCdUb3RhbCBsb2FkZWQgbWVzc2FnZXMgaW4gY29tcG9uZW50OicsIHRoaXMubWVzc2FnZXMubGVuZ3RoKTtcclxuICAgIC8vIGNvbnNvbGUubG9nKCdNZXNzYWdlcyBhcnJheTonLCB0aGlzLm1lc3NhZ2VzKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEhlbHBlciBtZXRob2QgdG8gZGV0ZXJtaW5lIGlmIGEgbWVzc2FnZSBpcyBmcm9tIHRoZSB1c2VyXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBpc1VzZXJNZXNzYWdlKG1zZzogYW55KTogYm9vbGVhbiB7XHJcbiAgICAvLyBDaGVjayB2YXJpb3VzIHByb3BlcnRpZXMgdGhhdCBtaWdodCBpbmRpY2F0ZSB1c2VyIG1lc3NhZ2VcclxuICAgIGlmIChtc2cuaXNVc2VyICE9PSB1bmRlZmluZWQpIHJldHVybiBtc2cuaXNVc2VyO1xyXG4gICAgaWYgKG1zZy5yb2xlKSByZXR1cm4gbXNnLnJvbGUudG9Mb3dlckNhc2UoKSA9PT0gJ3VzZXInO1xyXG4gICAgaWYgKG1zZy5zZW5kZXIpIHtcclxuICAgICAgY29uc3Qgc2VuZGVyID0gbXNnLnNlbmRlci50b0xvd2VyQ2FzZSgpO1xyXG4gICAgICByZXR1cm4gc2VuZGVyID09PSAndXNlcicgfHwgXHJcbiAgICAgICAgICAgICBzZW5kZXIgPT09IHRoaXMudXNlck5hbWU/LnRvTG93ZXJDYXNlKCkgfHxcclxuICAgICAgICAgICAgIHNlbmRlciA9PT0gdGhpcy51c2VySWQ/LnRvTG93ZXJDYXNlKCkgfHxcclxuICAgICAgICAgICAgIHNlbmRlci5pbmNsdWRlcygndXNlcicpO1xyXG4gICAgfVxyXG4gICAgLy8gRGVmYXVsdCB0byBmYWxzZSAoYm90IG1lc3NhZ2UpIGlmIGNhbid0IGRldGVybWluZVxyXG4gICAgcmV0dXJuIGZhbHNlO1xyXG4gIH1cclxuXHJcbiAgc2VuZElucXVpcnkoKTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMuY3VycmVudElucXVpcnkudHJpbSgpIHx8IHRoaXMuaXNMb2FkaW5nKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCB1c2VyTWVzc2FnZTogQ2hhdE1lc3NhZ2UgPSB7XHJcbiAgICAgIG1lc3NhZ2VJZDogdGhpcy5nZW5lcmF0ZU1lc3NhZ2VJZCgpLFxyXG4gICAgICBjb252ZXJzYXRpb25JZDogdGhpcy5jb252ZXJzYXRpb25JZCxcclxuICAgICAgaXNVc2VyOiB0cnVlLFxyXG4gICAgICBzZW5kZXI6IHRoaXMudXNlck5hbWUgfHwgJ1VzZXInLFxyXG4gICAgICBpbnRlbnQ6IHRoaXMuaW50ZW50LFxyXG4gICAgICBjb250ZW50OiB0aGlzLmN1cnJlbnRJbnF1aXJ5LFxyXG4gICAgICB0aW1lc3RhbXA6IG5ldyBEYXRlKClcclxuICAgIH07XHJcbiAgICBcclxuICAgIHRoaXMubWVzc2FnZXMucHVzaCh1c2VyTWVzc2FnZSk7XHJcbiAgICB0aGlzLm1lc3NhZ2VTZW50LmVtaXQodXNlck1lc3NhZ2UpO1xyXG5cclxuICAgIC8vIEFkZCBsb2FkaW5nIG1lc3NhZ2VcclxuICAgIGNvbnN0IGxvYWRpbmdNZXNzYWdlOiBDaGF0TWVzc2FnZSA9IHtcclxuICAgICAgaXNVc2VyOiBmYWxzZSxcclxuICAgICAgaW50ZW50OiAnJyxcclxuICAgICAgY29udGVudDogJ1Byb2Nlc3NpbmcgeW91ciBpbnF1aXJ5Li4uJyxcclxuICAgICAgdGltZXN0YW1wOiBuZXcgRGF0ZSgpLFxyXG4gICAgICBpc0xvYWRpbmc6IHRydWVcclxuICAgIH07XHJcbiAgICB0aGlzLm1lc3NhZ2VzLnB1c2gobG9hZGluZ01lc3NhZ2UpO1xyXG5cclxuICAgIGNvbnN0IGlucXVpcnkgPSB0aGlzLmN1cnJlbnRJbnF1aXJ5LnRyaW0oKTtcclxuICAgIHRoaXMuY3VycmVudElucXVpcnkgPSAnJztcclxuICAgIHRoaXMuYXV0aG9yTmFtZSA9ICcnO1xyXG4gICAgdGhpcy5pbnRlbnQgPSAnJztcclxuICAgIHRoaXMuaXNMb2FkaW5nID0gdHJ1ZTtcclxuXHJcbiAgICBjb25zdCByZXF1ZXN0OiBTdXBwb3J0Qm90UmVxdWVzdCA9IHtcclxuICAgICAgcXVlcnk6IGlucXVpcnksXHJcbiAgICAgIGNoYXRIaXN0b3J5OiBbXSxcclxuICAgICAgdXNlcklkOiB0aGlzLnVzZXJJZCxcclxuICAgICAgdXNlck5hbWU6IHRoaXMudXNlck5hbWUsXHJcbiAgICAgIGFwcFNvdXJjZTogdGhpcy5hcHBTb3VyY2VcclxuICAgIH07XHJcblxyXG4gICAgdGhpcy5haUFnZW50U2VydmljZS5wcm9jZXNzSW5xdWlyeShyZXF1ZXN0KVxyXG4gICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpXHJcbiAgICAgIC5zdWJzY3JpYmUoe1xyXG4gICAgICAgIG5leHQ6IChyZXNwb25zZTogU3VwcG9ydEJvdFJlc3BvbnNlKSA9PiB7XHJcbiAgICAgICAgICB0aGlzLmlzTG9hZGluZyA9IGZhbHNlO1xyXG4gICAgICAgICAgXHJcbiAgICAgICAgICAvLyBSZW1vdmUgbG9hZGluZyBtZXNzYWdlXHJcbiAgICAgICAgICB0aGlzLm1lc3NhZ2VzID0gdGhpcy5tZXNzYWdlcy5maWx0ZXIobXNnID0+ICFtc2cuaXNMb2FkaW5nKTtcclxuICAgICAgICAgIFxyXG4gICAgICAgICAgaWYgKHJlc3BvbnNlLmFuc3dlciB8fCAocmVzcG9uc2UuY29udGVudHMgJiYgcmVzcG9uc2UuY29udGVudHMubGVuZ3RoID4gMCkpIHtcclxuICAgICAgICAgICAgaWYgKHJlc3BvbnNlLmFuc3dlcikge1xyXG4gICAgICAgICAgICAgIGNvbnN0IGJvdE1lc3NhZ2U6IENoYXRNZXNzYWdlID0ge1xyXG4gICAgICAgICAgICAgICAgbWVzc2FnZUlkOiB0aGlzLmdlbmVyYXRlTWVzc2FnZUlkKCksXHJcbiAgICAgICAgICAgICAgICBjb252ZXJzYXRpb25JZDogdGhpcy5jb252ZXJzYXRpb25JZCxcclxuICAgICAgICAgICAgICAgIGlzVXNlcjogZmFsc2UsXHJcbiAgICAgICAgICAgICAgICBzZW5kZXI6ICdNYWVzdHJvJyxcclxuICAgICAgICAgICAgICAgIGludGVudDogcmVzcG9uc2Uuc2VhcmNoSW50ZW50IHx8IGlucXVpcnksXHJcbiAgICAgICAgICAgICAgICBjb250ZW50OiB0aGlzLmZvcm1hdE1lc3NhZ2VDb250ZW50KHJlc3BvbnNlLmFuc3dlciksXHJcbiAgICAgICAgICAgICAgICBhdXRob3JOYW1lOiByZXNwb25zZS5jb250ZW50cyAmJiByZXNwb25zZS5jb250ZW50cy5sZW5ndGggPiAwID8gcmVzcG9uc2UuY29udGVudHNbMF0uYXV0aG9yTmFtZSA6IHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgICAgIHRpbWVzdGFtcDogbmV3IERhdGUoKVxyXG4gICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgICAgdGhpcy5tZXNzYWdlcy5wdXNoKGJvdE1lc3NhZ2UpO1xyXG4gICAgICAgICAgICAgIHRoaXMubWVzc2FnZVJlY2VpdmVkLmVtaXQoYm90TWVzc2FnZSk7XHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocmVzcG9uc2UuY29udGVudHMgJiYgcmVzcG9uc2UuY29udGVudHMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICAgIC8vIFB1c2ggZWFjaCBjb250ZW50IGFzIGEgc2VwYXJhdGUgbWVzc2FnZVxyXG4gICAgICAgICAgICAgIHJlc3BvbnNlLmNvbnRlbnRzLmZvckVhY2goY29udGVudEl0ZW0gPT4ge1xyXG4gICAgICAgICAgICAgICAgaWYgKGNvbnRlbnRJdGVtLmNvbnRlbnQpIHtcclxuICAgICAgICAgICAgICAgICAgY29uc3QgYm90TWVzc2FnZTogQ2hhdE1lc3NhZ2UgPSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZUlkOiB0aGlzLmdlbmVyYXRlTWVzc2FnZUlkKCksXHJcbiAgICAgICAgICAgICAgICAgICAgY29udmVyc2F0aW9uSWQ6IHRoaXMuY29udmVyc2F0aW9uSWQsXHJcbiAgICAgICAgICAgICAgICAgICAgaXNVc2VyOiBmYWxzZSxcclxuICAgICAgICAgICAgICAgICAgICBzZW5kZXI6IGNvbnRlbnRJdGVtLmF1dGhvck5hbWUgfHwgJ01hZXN0cm8nLFxyXG4gICAgICAgICAgICAgICAgICAgIGludGVudDogcmVzcG9uc2Uuc2VhcmNoSW50ZW50IHx8IGlucXVpcnksXHJcbiAgICAgICAgICAgICAgICAgICAgY29udGVudDogdGhpcy5mb3JtYXRNZXNzYWdlQ29udGVudChjb250ZW50SXRlbS5jb250ZW50IHx8ICdObyBjb250ZW50IGF2YWlsYWJsZScpLFxyXG4gICAgICAgICAgICAgICAgICAgIGF1dGhvck5hbWU6IGNvbnRlbnRJdGVtLmF1dGhvck5hbWUsXHJcbiAgICAgICAgICAgICAgICAgICAgdGltZXN0YW1wOiBuZXcgRGF0ZSgpXHJcbiAgICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgICAgICAgIHRoaXMubWVzc2FnZXMucHVzaChib3RNZXNzYWdlKTtcclxuICAgICAgICAgICAgICAgICAgdGhpcy5tZXNzYWdlUmVjZWl2ZWQuZW1pdChib3RNZXNzYWdlKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgY29uc3QgZXJyb3JNZXNzYWdlOiBDaGF0TWVzc2FnZSA9IHtcclxuICAgICAgICAgICAgICBtZXNzYWdlSWQ6IHRoaXMuZ2VuZXJhdGVNZXNzYWdlSWQoKSxcclxuICAgICAgICAgICAgICBjb252ZXJzYXRpb25JZDogdGhpcy5jb252ZXJzYXRpb25JZCxcclxuICAgICAgICAgICAgICBpc1VzZXI6IGZhbHNlLFxyXG4gICAgICAgICAgICAgIHNlbmRlcjogJ01hZXN0cm8nLFxyXG4gICAgICAgICAgICAgIGludGVudDogaW5xdWlyeSxcclxuICAgICAgICAgICAgICBjb250ZW50OiBgU29ycnksIEkgZGlkbid0IHJlY2VpdmUgYSB2YWxpZCByZXNwb25zZS5gLFxyXG4gICAgICAgICAgICAgIGF1dGhvck5hbWU6IHRoaXMuYXV0aG9yTmFtZSxcclxuICAgICAgICAgICAgICB0aW1lc3RhbXA6IG5ldyBEYXRlKClcclxuICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgdGhpcy5tZXNzYWdlcy5wdXNoKGVycm9yTWVzc2FnZSk7XHJcbiAgICAgICAgICAgIHRoaXMubWVzc2FnZVJlY2VpdmVkLmVtaXQoZXJyb3JNZXNzYWdlKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9LFxyXG4gICAgICAgIGVycm9yOiAoZXJyb3IpID0+IHtcclxuICAgICAgICAgIHRoaXMuaXNMb2FkaW5nID0gZmFsc2U7XHJcbiAgICAgICAgICBcclxuICAgICAgICAgIC8vIFJlbW92ZSBsb2FkaW5nIG1lc3NhZ2VcclxuICAgICAgICAgIHRoaXMubWVzc2FnZXMgPSB0aGlzLm1lc3NhZ2VzLmZpbHRlcihtc2cgPT4gIW1zZy5pc0xvYWRpbmcpO1xyXG4gICAgICAgICAgXHJcbiAgICAgICAgICBjb25zdCBlcnJvck1lc3NhZ2U6IENoYXRNZXNzYWdlID0ge1xyXG4gICAgICAgICAgICBtZXNzYWdlSWQ6IHRoaXMuZ2VuZXJhdGVNZXNzYWdlSWQoKSxcclxuICAgICAgICAgICAgY29udmVyc2F0aW9uSWQ6IHRoaXMuY29udmVyc2F0aW9uSWQsXHJcbiAgICAgICAgICAgIGlzVXNlcjogZmFsc2UsXHJcbiAgICAgICAgICAgIHNlbmRlcjogJ01hZXN0cm8nLFxyXG4gICAgICAgICAgICBpbnRlbnQ6IGlucXVpcnksXHJcbiAgICAgICAgICAgIGNvbnRlbnQ6ICdTb3JyeSwgSSBlbmNvdW50ZXJlZCBhbiBlcnJvciBwcm9jZXNzaW5nIHlvdXIgcmVxdWVzdC4gUGxlYXNlIHRyeSBhZ2Fpbi4nLFxyXG4gICAgICAgICAgICBhdXRob3JOYW1lOiB0aGlzLmF1dGhvck5hbWUsXHJcbiAgICAgICAgICAgIHRpbWVzdGFtcDogbmV3IERhdGUoKVxyXG4gICAgICAgICAgfTtcclxuICAgICAgICAgIHRoaXMubWVzc2FnZXMucHVzaChlcnJvck1lc3NhZ2UpO1xyXG4gICAgICAgICAgdGhpcy5tZXNzYWdlUmVjZWl2ZWQuZW1pdChlcnJvck1lc3NhZ2UpO1xyXG4gICAgICAgICAgXHJcbiAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBwcm9jZXNzaW5nIGlucXVpcnk6JywgZXJyb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcbiAgfVxyXG5cclxuICBjbGVhckNoYXQoKTogdm9pZCB7XHJcbiAgICB0aGlzLm1lc3NhZ2VzID0gW107XHJcbiAgICB0aGlzLmFkZFdlbGNvbWVNZXNzYWdlKCk7XHJcbiAgfVxyXG5cclxuICBvbktleVByZXNzKGV2ZW50OiBLZXlib2FyZEV2ZW50KTogdm9pZCB7XHJcbiAgICBpZiAoZXZlbnQua2V5ID09PSAnRW50ZXInICYmICFldmVudC5zaGlmdEtleSkge1xyXG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgICB0aGlzLnNlbmRJbnF1aXJ5KCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICB0cmFja0J5SW5kZXgoaW5kZXg6IG51bWJlcik6IG51bWJlciB7XHJcbiAgICByZXR1cm4gaW5kZXg7XHJcbiAgfVxyXG5cclxuICBnZXRUaGVtZUNsYXNzKCk6IHN0cmluZyB7XHJcbiAgICAvLyBEZWZhdWx0IHRoZW1lIGlmIG5vIHRlbXBsYXRlIGRlc2lnbiBpcyBzcGVjaWZpZWRcclxuICAgIGlmICghdGhpcy50ZW1wbGF0ZURlc2lnbikge1xyXG4gICAgICByZXR1cm4gJ3RoZW1lLWRlZmF1bHQnO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFZhbGlkYXRlIGFuZCByZXR1cm4gdGhlbWUgY2xhc3NcclxuICAgIGNvbnN0IHZhbGlkVGhlbWVzID0gWydkZWZhdWx0JywgJ2RhcmsnLCAnYmx1ZScsICdncmVlbicsICdwdXJwbGUnLCAnbWluaW1hbCcsICdjb3Jwb3JhdGUnLCAncmVkJywgJ3llbGxvdycsICdvcmFuZ2UnXTtcclxuICAgIGNvbnN0IHRoZW1lID0gdGhpcy50ZW1wbGF0ZURlc2lnbi50b0xvd2VyQ2FzZSgpO1xyXG4gICAgXHJcbiAgICBpZiAodmFsaWRUaGVtZXMuaW5jbHVkZXModGhlbWUpKSB7XHJcbiAgICAgIHJldHVybiBgdGhlbWUtJHt0aGVtZX1gO1xyXG4gICAgfVxyXG4gICAgXHJcbiAgICAvLyBGYWxsYmFjayB0byBkZWZhdWx0IGlmIGludmFsaWQgdGhlbWVcclxuICAgIGNvbnNvbGUud2FybihgSW52YWxpZCB0aGVtZSAnJHt0aGlzLnRlbXBsYXRlRGVzaWdufScgcHJvdmlkZWQuIFVzaW5nIGRlZmF1bHQgdGhlbWUuYCk7XHJcbiAgICByZXR1cm4gJ3RoZW1lLWRlZmF1bHQnO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBmb3JtYXRNZXNzYWdlQ29udGVudChjb250ZW50OiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgaWYgKCFjb250ZW50KSByZXR1cm4gJyc7XHJcbiAgICBcclxuICAgIC8vIElmIGNvbnRlbnQgYWxyZWFkeSBjb250YWlucyBIVE1MIHRhZ3MsIHJldHVybiBhcy1pc1xyXG4gICAgaWYgKGNvbnRlbnQuaW5jbHVkZXMoJzwnKSAmJiBjb250ZW50LmluY2x1ZGVzKCc+JykpIHtcclxuICAgICAgcmV0dXJuIGNvbnRlbnQ7XHJcbiAgICB9XHJcbiAgICBcclxuICAgIC8vIENvbnZlcnQgbmV3bGluZXMgdG8gSFRNTCBicmVha3NcclxuICAgIGxldCBmb3JtYXR0ZWQgPSBjb250ZW50LnJlcGxhY2UoL1xcbi9nLCAnPGJyPicpO1xyXG4gICAgXHJcbiAgICAvLyBDb252ZXJ0IGVzY2FwZWQgbmV3bGluZXMgdG8gSFRNTCBicmVha3NcclxuICAgIGZvcm1hdHRlZCA9IGZvcm1hdHRlZC5yZXBsYWNlKC9cXFxcbi9nLCAnPGJyPicpO1xyXG4gICAgXHJcbiAgICAvLyBDb252ZXJ0IG1hcmtkb3duLXN0eWxlIGJvbGQgdG8gSFRNTFxyXG4gICAgZm9ybWF0dGVkID0gZm9ybWF0dGVkLnJlcGxhY2UoL1xcKlxcKiguKj8pXFwqXFwqL2csICc8c3Ryb25nPiQxPC9zdHJvbmc+Jyk7XHJcbiAgICBcclxuICAgIC8vIENvbnZlcnQgYnVsbGV0IHBvaW50cyB0byBIVE1MIGxpc3RzXHJcbiAgICBjb25zdCBsaW5lcyA9IGZvcm1hdHRlZC5zcGxpdCgnPGJyPicpO1xyXG4gICAgbGV0IGluTGlzdCA9IGZhbHNlO1xyXG4gICAgY29uc3QgcHJvY2Vzc2VkTGluZXM6IHN0cmluZ1tdID0gW107XHJcbiAgICBcclxuICAgIGZvciAobGV0IGxpbmUgb2YgbGluZXMpIHtcclxuICAgICAgaWYgKGxpbmUudHJpbSgpLnN0YXJ0c1dpdGgoJ+KAoiAnKSkge1xyXG4gICAgICAgIGlmICghaW5MaXN0KSB7XHJcbiAgICAgICAgICBwcm9jZXNzZWRMaW5lcy5wdXNoKCc8dWw+Jyk7XHJcbiAgICAgICAgICBpbkxpc3QgPSB0cnVlO1xyXG4gICAgICAgIH1cclxuICAgICAgICBwcm9jZXNzZWRMaW5lcy5wdXNoKCc8bGk+JyArIGxpbmUucmVwbGFjZSgvXuKAoiAvLCAnJykgKyAnPC9saT4nKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBpZiAoaW5MaXN0KSB7XHJcbiAgICAgICAgICBwcm9jZXNzZWRMaW5lcy5wdXNoKCc8L3VsPicpO1xyXG4gICAgICAgICAgaW5MaXN0ID0gZmFsc2U7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHByb2Nlc3NlZExpbmVzLnB1c2gobGluZSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIFxyXG4gICAgaWYgKGluTGlzdCkge1xyXG4gICAgICBwcm9jZXNzZWRMaW5lcy5wdXNoKCc8L3VsPicpO1xyXG4gICAgfVxyXG4gICAgXHJcbiAgICByZXR1cm4gcHJvY2Vzc2VkTGluZXMuam9pbignPGJyPicpLnJlcGxhY2UoLzxicj48dWw+L2csICc8dWw+JykucmVwbGFjZSgvPFxcL3VsPjxicj4vZywgJzwvdWw+Jyk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGdlbmVyYXRlU2Vzc2lvbklkKCk6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gJ3Nlc3Npb25fJyArIE1hdGgucmFuZG9tKCkudG9TdHJpbmcoMzYpLnN1YnN0cigyLCA5KSArICdfJyArIERhdGUubm93KCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGdlbmVyYXRlTWVzc2FnZUlkKCk6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gJ21zZ18nICsgTWF0aC5yYW5kb20oKS50b1N0cmluZygzNikuc3Vic3RyKDIsIDkpICsgJ18nICsgRGF0ZS5ub3coKTtcclxuICB9XHJcblxyXG4gIGdldEZvcm1hdHRlZFRpbWUodGltZXN0YW1wOiBEYXRlKTogc3RyaW5nIHtcclxuICAgIHJldHVybiB0aW1lc3RhbXAudG9Mb2NhbGVUaW1lU3RyaW5nKFtdLCB7IGhvdXI6ICcyLWRpZ2l0JywgbWludXRlOiAnMi1kaWdpdCcgfSk7XHJcbiAgfVxyXG5cclxuICAvLyA9PT09PT09PT09PT09IFJlc2l6ZSBNZXRob2RzID09PT09PT09PT09PT1cclxuICBcclxuICBzdGFydFJlc2l6ZShldmVudDogTW91c2VFdmVudCwgZGlyZWN0aW9uOiAnd2lkdGgnIHwgJ2JvdGgnKTogdm9pZCB7XHJcbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgdGhpcy5pc1Jlc2l6aW5nID0gdHJ1ZTtcclxuICAgIHRoaXMuc3RhcnRYID0gZXZlbnQuY2xpZW50WDtcclxuICAgIHRoaXMuc3RhcnRZID0gZXZlbnQuY2xpZW50WTtcclxuICAgIHRoaXMuc3RhcnRXaWR0aCA9IHRoaXMuY29udGFpbmVyV2lkdGg7XHJcbiAgICB0aGlzLnN0YXJ0SGVpZ2h0ID0gdGhpcy5jb250YWluZXJIZWlnaHQ7XHJcbiAgICBcclxuICAgIGNvbnN0IG1vdXNlTW92ZUhhbmRsZXIgPSAoZTogTW91c2VFdmVudCkgPT4gdGhpcy5vblJlc2l6ZShlLCBkaXJlY3Rpb24pO1xyXG4gICAgY29uc3QgbW91c2VVcEhhbmRsZXIgPSAoKSA9PiB0aGlzLnN0b3BSZXNpemUobW91c2VNb3ZlSGFuZGxlciwgbW91c2VVcEhhbmRsZXIpO1xyXG4gICAgXHJcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCBtb3VzZU1vdmVIYW5kbGVyKTtcclxuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCBtb3VzZVVwSGFuZGxlcik7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIG9uUmVzaXplKGV2ZW50OiBNb3VzZUV2ZW50LCBkaXJlY3Rpb246ICd3aWR0aCcgfCAnYm90aCcpOiB2b2lkIHtcclxuICAgIGlmICghdGhpcy5pc1Jlc2l6aW5nKSByZXR1cm47XHJcbiAgICBcclxuICAgIGNvbnN0IGRlbHRhWCA9IGV2ZW50LmNsaWVudFggLSB0aGlzLnN0YXJ0WDtcclxuICAgIGNvbnN0IGRlbHRhWSA9IGV2ZW50LmNsaWVudFkgLSB0aGlzLnN0YXJ0WTtcclxuICAgIFxyXG4gICAgaWYgKGRpcmVjdGlvbiA9PT0gJ3dpZHRoJyB8fCBkaXJlY3Rpb24gPT09ICdib3RoJykge1xyXG4gICAgICBjb25zdCBuZXdXaWR0aCA9IE1hdGgubWluKFxyXG4gICAgICAgIE1hdGgubWF4KHRoaXMuc3RhcnRXaWR0aCArIGRlbHRhWCwgdGhpcy5taW5XaWR0aCksXHJcbiAgICAgICAgdGhpcy5tYXhXaWR0aFxyXG4gICAgICApO1xyXG4gICAgICB0aGlzLmNvbnRhaW5lcldpZHRoID0gbmV3V2lkdGg7XHJcbiAgICB9XHJcbiAgICBcclxuICAgIGlmIChkaXJlY3Rpb24gPT09ICdib3RoJykge1xyXG4gICAgICBjb25zdCBuZXdIZWlnaHQgPSBNYXRoLm1pbihcclxuICAgICAgICBNYXRoLm1heCh0aGlzLnN0YXJ0SGVpZ2h0ICsgZGVsdGFZLCB0aGlzLm1pbkhlaWdodCksXHJcbiAgICAgICAgdGhpcy5tYXhIZWlnaHRcclxuICAgICAgKTtcclxuICAgICAgdGhpcy5jb250YWluZXJIZWlnaHQgPSBuZXdIZWlnaHQ7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHN0b3BSZXNpemUobW91c2VNb3ZlSGFuZGxlcjogKGU6IE1vdXNlRXZlbnQpID0+IHZvaWQsIG1vdXNlVXBIYW5kbGVyOiAoKSA9PiB2b2lkKTogdm9pZCB7XHJcbiAgICB0aGlzLmlzUmVzaXppbmcgPSBmYWxzZTtcclxuICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIG1vdXNlTW92ZUhhbmRsZXIpO1xyXG4gICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIG1vdXNlVXBIYW5kbGVyKTtcclxuICAgIFxyXG4gICAgdGhpcy5zYXZlU2l6ZVByZWZlcmVuY2UoKTtcclxuICAgIHRoaXMuZW1pdFNpemVDaGFuZ2UoKTtcclxuICB9XHJcblxyXG4gIGFwcGx5U2l6ZVByZXNldChzaXplOiBDaGF0U2l6ZSk6IHZvaWQge1xyXG4gICAgdGhpcy5jdXJyZW50U2l6ZSA9IHNpemU7XHJcbiAgICBcclxuICAgIHN3aXRjaCAoc2l6ZSkge1xyXG4gICAgICBjYXNlICdjb21wYWN0JzpcclxuICAgICAgICB0aGlzLmNvbnRhaW5lcldpZHRoID0gNDAwO1xyXG4gICAgICAgIHRoaXMuY29udGFpbmVySGVpZ2h0ID0gNTAwO1xyXG4gICAgICAgIHRoaXMuaXNGdWxsc2NyZWVuID0gZmFsc2U7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgJ2RlZmF1bHQnOlxyXG4gICAgICAgIHRoaXMuY29udGFpbmVyV2lkdGggPSA4MDA7XHJcbiAgICAgICAgdGhpcy5jb250YWluZXJIZWlnaHQgPSA2MDA7XHJcbiAgICAgICAgdGhpcy5pc0Z1bGxzY3JlZW4gPSBmYWxzZTtcclxuICAgICAgICBicmVhaztcclxuICAgICAgY2FzZSAnZXhwYW5kZWQnOlxyXG4gICAgICAgIHRoaXMuY29udGFpbmVyV2lkdGggPSAxMjAwO1xyXG4gICAgICAgIHRoaXMuY29udGFpbmVySGVpZ2h0ID0gODAwO1xyXG4gICAgICAgIHRoaXMuaXNGdWxsc2NyZWVuID0gZmFsc2U7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgJ2Z1bGxzY3JlZW4nOlxyXG4gICAgICAgIHRoaXMudG9nZ2xlRnVsbHNjcmVlbigpO1xyXG4gICAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIFxyXG4gICAgdGhpcy5zYXZlU2l6ZVByZWZlcmVuY2UoKTtcclxuICAgIHRoaXMuZW1pdFNpemVDaGFuZ2UoKTtcclxuICB9XHJcblxyXG4gIHRvZ2dsZUZ1bGxzY3JlZW4oKTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMuaXNGdWxsc2NyZWVuKSB7XHJcbiAgICAgIC8vIEVudGVyaW5nIGZ1bGxzY3JlZW4gLSBzYXZlIGN1cnJlbnQgc3RhdGUgZmlyc3RcclxuICAgICAgc2Vzc2lvblN0b3JhZ2Uuc2V0SXRlbSgnY2hhdGJveC1wcmV2aW91cy1zaXplJywgSlNPTi5zdHJpbmdpZnkoe1xyXG4gICAgICAgIHdpZHRoOiB0aGlzLmNvbnRhaW5lcldpZHRoLFxyXG4gICAgICAgIGhlaWdodDogdGhpcy5jb250YWluZXJIZWlnaHQsXHJcbiAgICAgICAgc2l6ZTogdGhpcy5jdXJyZW50U2l6ZSxcclxuICAgICAgICB3YXNGdWxsc2NyZWVuOiB0aGlzLmlzRnVsbHNjcmVlblxyXG4gICAgICB9KSk7XHJcbiAgICAgIFxyXG4gICAgICB0aGlzLmlzRnVsbHNjcmVlbiA9IHRydWU7XHJcbiAgICAgIHRoaXMuY3VycmVudFNpemUgPSAnZnVsbHNjcmVlbic7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICAvLyBFeGl0aW5nIGZ1bGxzY3JlZW4gLSByZXN0b3JlIHByZXZpb3VzIHN0YXRlXHJcbiAgICAgIHRyeSB7XHJcbiAgICAgICAgY29uc3QgcHJldmlvdXMgPSBzZXNzaW9uU3RvcmFnZS5nZXRJdGVtKCdjaGF0Ym94LXByZXZpb3VzLXNpemUnKTtcclxuICAgICAgICBpZiAocHJldmlvdXMpIHtcclxuICAgICAgICAgIGNvbnN0IHByZXZEYXRhID0gSlNPTi5wYXJzZShwcmV2aW91cyk7XHJcbiAgICAgICAgICB0aGlzLmNvbnRhaW5lcldpZHRoID0gcHJldkRhdGEud2lkdGggfHwgODAwO1xyXG4gICAgICAgICAgdGhpcy5jb250YWluZXJIZWlnaHQgPSBwcmV2RGF0YS5oZWlnaHQgfHwgNjAwO1xyXG4gICAgICAgICAgdGhpcy5jdXJyZW50U2l6ZSA9IHByZXZEYXRhLnNpemUgPT09ICdmdWxsc2NyZWVuJyA/ICdkZWZhdWx0JyA6IHByZXZEYXRhLnNpemU7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHRoaXMuY3VycmVudFNpemUgPSAnZGVmYXVsdCc7XHJcbiAgICAgICAgICB0aGlzLmNvbnRhaW5lcldpZHRoID0gODAwO1xyXG4gICAgICAgICAgdGhpcy5jb250YWluZXJIZWlnaHQgPSA2MDA7XHJcbiAgICAgICAgfVxyXG4gICAgICB9IGNhdGNoIChlcnJvcikge1xyXG4gICAgICAgIHRoaXMuY3VycmVudFNpemUgPSAnZGVmYXVsdCc7XHJcbiAgICAgICAgdGhpcy5jb250YWluZXJXaWR0aCA9IDgwMDtcclxuICAgICAgICB0aGlzLmNvbnRhaW5lckhlaWdodCA9IDYwMDtcclxuICAgICAgfVxyXG4gICAgICBcclxuICAgICAgdGhpcy5pc0Z1bGxzY3JlZW4gPSBmYWxzZTtcclxuICAgIH1cclxuICAgIFxyXG4gICAgdGhpcy5zYXZlU2l6ZVByZWZlcmVuY2UoKTtcclxuICAgIHRoaXMuZW1pdFNpemVDaGFuZ2UoKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgc2F2ZVNpemVQcmVmZXJlbmNlKCk6IHZvaWQge1xyXG4gICAgY29uc3Qgc2l6ZURhdGEgPSB7XHJcbiAgICAgIHNpemU6IHRoaXMuY3VycmVudFNpemUsXHJcbiAgICAgIHdpZHRoOiB0aGlzLmNvbnRhaW5lcldpZHRoLFxyXG4gICAgICBoZWlnaHQ6IHRoaXMuY29udGFpbmVySGVpZ2h0LFxyXG4gICAgICBpc0Z1bGxzY3JlZW46IHRoaXMuaXNGdWxsc2NyZWVuXHJcbiAgICB9O1xyXG4gICAgXHJcbiAgICB0cnkge1xyXG4gICAgICBzZXNzaW9uU3RvcmFnZS5zZXRJdGVtKCdjaGF0Ym94LXNpemUtcHJlZmVyZW5jZScsIEpTT04uc3RyaW5naWZ5KHNpemVEYXRhKSk7XHJcbiAgICB9IGNhdGNoIChlcnJvcikge1xyXG4gICAgICBjb25zb2xlLndhcm4oJ0ZhaWxlZCB0byBzYXZlIHNpemUgcHJlZmVyZW5jZTonLCBlcnJvcik7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGxvYWRTYXZlZFNpemUoKTogdm9pZCB7XHJcbiAgICB0cnkge1xyXG4gICAgICBjb25zdCBzYXZlZCA9IHNlc3Npb25TdG9yYWdlLmdldEl0ZW0oJ2NoYXRib3gtc2l6ZS1wcmVmZXJlbmNlJyk7XHJcbiAgICAgIGlmIChzYXZlZCkge1xyXG4gICAgICAgIGNvbnN0IHNpemVEYXRhID0gSlNPTi5wYXJzZShzYXZlZCk7XHJcbiAgICAgICAgdGhpcy5jdXJyZW50U2l6ZSA9IHNpemVEYXRhLnNpemUgfHwgJ2RlZmF1bHQnO1xyXG4gICAgICAgIHRoaXMuY29udGFpbmVyV2lkdGggPSBzaXplRGF0YS53aWR0aCB8fCA4MDA7XHJcbiAgICAgICAgdGhpcy5jb250YWluZXJIZWlnaHQgPSBzaXplRGF0YS5oZWlnaHQgfHwgNjAwO1xyXG4gICAgICAgIHRoaXMuaXNGdWxsc2NyZWVuID0gc2l6ZURhdGEuaXNGdWxsc2NyZWVuIHx8IGZhbHNlO1xyXG4gICAgICB9XHJcbiAgICB9IGNhdGNoIChlcnJvcikge1xyXG4gICAgICBjb25zb2xlLndhcm4oJ0ZhaWxlZCB0byBsb2FkIHNpemUgcHJlZmVyZW5jZTonLCBlcnJvcik7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGVtaXRTaXplQ2hhbmdlKCk6IHZvaWQge1xyXG4gICAgdGhpcy5zaXplQ2hhbmdlZC5lbWl0KHtcclxuICAgICAgc2l6ZTogdGhpcy5jdXJyZW50U2l6ZSxcclxuICAgICAgd2lkdGg6IHRoaXMuY29udGFpbmVyV2lkdGgsXHJcbiAgICAgIGhlaWdodDogdGhpcy5jb250YWluZXJIZWlnaHRcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgZ2V0Q29udGFpbmVyU3R5bGUoKTogYW55IHtcclxuICAgIGlmICh0aGlzLmlzRnVsbHNjcmVlbikge1xyXG4gICAgICByZXR1cm4ge1xyXG4gICAgICAgIHdpZHRoOiAnMTAwdncgIWltcG9ydGFudCcsXHJcbiAgICAgICAgaGVpZ2h0OiAnMTAwdmggIWltcG9ydGFudCcsXHJcbiAgICAgICAgbWF4V2lkdGg6ICcxMDB2dyAhaW1wb3J0YW50JyxcclxuICAgICAgICBtYXhIZWlnaHQ6ICcxMDB2aCAhaW1wb3J0YW50JyxcclxuICAgICAgICBwb3NpdGlvbjogJ2ZpeGVkJyxcclxuICAgICAgICB0b3A6ICcwJyxcclxuICAgICAgICBsZWZ0OiAnMCcsXHJcbiAgICAgICAgcmlnaHQ6ICcwJyxcclxuICAgICAgICBib3R0b206ICcwJyxcclxuICAgICAgICBtYXJnaW46ICcwJyxcclxuICAgICAgICB6SW5kZXg6IDk5OTk5XHJcbiAgICAgIH07XHJcbiAgICB9XHJcbiAgICBcclxuICAgIHJldHVybiB7XHJcbiAgICAgIHdpZHRoOiBgJHt0aGlzLmNvbnRhaW5lcldpZHRofXB4YCxcclxuICAgICAgaGVpZ2h0OiBgJHt0aGlzLmNvbnRhaW5lckhlaWdodH1weGAsXHJcbiAgICAgIG1heFdpZHRoOiBgJHt0aGlzLm1heFdpZHRofXB4YFxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIC8vID09PT09PT09PT09PT0gRmlsZSBVcGxvYWQgTWV0aG9kcyA9PT09PT09PT09PT09XHJcbiAgXHJcbiAgb25JbWFnZVVwbG9hZChldmVudDogRXZlbnQpOiB2b2lkIHtcclxuICAgIGNvbnN0IGlucHV0ID0gZXZlbnQudGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnQ7XHJcbiAgICBpZiAoaW5wdXQuZmlsZXMgJiYgaW5wdXQuZmlsZXMubGVuZ3RoID4gMCkge1xyXG4gICAgICB0aGlzLmhhbmRsZUZpbGVTZWxlY3Rpb24oQXJyYXkuZnJvbShpbnB1dC5maWxlcyksICdpbWFnZScpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgb25GaWxlVXBsb2FkKGV2ZW50OiBFdmVudCk6IHZvaWQge1xyXG4gICAgY29uc3QgaW5wdXQgPSBldmVudC50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudDtcclxuICAgIGlmIChpbnB1dC5maWxlcyAmJiBpbnB1dC5maWxlcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgIHRoaXMuaGFuZGxlRmlsZVNlbGVjdGlvbihBcnJheS5mcm9tKGlucHV0LmZpbGVzKSwgJ2ZpbGUnKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgaGFuZGxlRmlsZVNlbGVjdGlvbihmaWxlczogRmlsZVtdLCB0eXBlOiAnaW1hZ2UnIHwgJ2ZpbGUnKTogdm9pZCB7XHJcbiAgICBmaWxlcy5mb3JFYWNoKGZpbGUgPT4ge1xyXG4gICAgICAvLyBWYWxpZGF0ZSBmaWxlIHR5cGVcclxuICAgICAgY29uc3QgYWxsb3dlZFR5cGVzID0gdHlwZSA9PT0gJ2ltYWdlJyA/IHRoaXMuYWxsb3dlZEltYWdlVHlwZXMgOiB0aGlzLmFsbG93ZWRGaWxlVHlwZXM7XHJcbiAgICAgIGlmICghYWxsb3dlZFR5cGVzLmluY2x1ZGVzKGZpbGUudHlwZSkpIHtcclxuICAgICAgICBjb25zb2xlLndhcm4oYEZpbGUgdHlwZSAke2ZpbGUudHlwZX0gbm90IGFsbG93ZWRgKTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIFZhbGlkYXRlIGZpbGUgc2l6ZVxyXG4gICAgICBpZiAoZmlsZS5zaXplID4gdGhpcy5tYXhGaWxlU2l6ZSkge1xyXG4gICAgICAgIGNvbnNvbGUud2FybihgRmlsZSAke2ZpbGUubmFtZX0gZXhjZWVkcyBtYXhpbXVtIHNpemUgb2YgJHt0aGlzLm1heEZpbGVTaXplIC8gMTAyNCAvIDEwMjR9TUJgKTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGNvbnN0IHJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKCk7XHJcbiAgICAgIHJlYWRlci5vbmxvYWQgPSAoZTogUHJvZ3Jlc3NFdmVudDxGaWxlUmVhZGVyPikgPT4ge1xyXG4gICAgICAgIGNvbnN0IGF0dGFjaG1lbnQ6IEZpbGVBdHRhY2htZW50ID0ge1xyXG4gICAgICAgICAgaWQ6IHRoaXMuZ2VuZXJhdGVNZXNzYWdlSWQoKSxcclxuICAgICAgICAgIG5hbWU6IGZpbGUubmFtZSxcclxuICAgICAgICAgIHR5cGU6IGZpbGUudHlwZSxcclxuICAgICAgICAgIHNpemU6IGZpbGUuc2l6ZSxcclxuICAgICAgICAgIGRhdGE6IGUudGFyZ2V0Py5yZXN1bHQgfHwgdW5kZWZpbmVkXHJcbiAgICAgICAgfTtcclxuICAgICAgICBcclxuICAgICAgICB0aGlzLnNlbGVjdGVkRmlsZXMucHVzaChhdHRhY2htZW50KTtcclxuICAgICAgICB0aGlzLmZpbGVVcGxvYWRlZC5lbWl0KGF0dGFjaG1lbnQpO1xyXG4gICAgICB9O1xyXG4gICAgICBcclxuICAgICAgaWYgKHR5cGUgPT09ICdpbWFnZScpIHtcclxuICAgICAgICByZWFkZXIucmVhZEFzRGF0YVVSTChmaWxlKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICByZWFkZXIucmVhZEFzQXJyYXlCdWZmZXIoZmlsZSk7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgcmVtb3ZlQXR0YWNobWVudChhdHRhY2htZW50SWQ6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgdGhpcy5zZWxlY3RlZEZpbGVzID0gdGhpcy5zZWxlY3RlZEZpbGVzLmZpbHRlcihmID0+IGYuaWQgIT09IGF0dGFjaG1lbnRJZCk7XHJcbiAgfVxyXG5cclxuICB0cmlnZ2VySW1hZ2VVcGxvYWQoKTogdm9pZCB7XHJcbiAgICBjb25zdCBpbnB1dCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdpbWFnZS11cGxvYWQtaW5wdXQnKSBhcyBIVE1MSW5wdXRFbGVtZW50O1xyXG4gICAgaWYgKGlucHV0KSB7XHJcbiAgICAgIGlucHV0LmNsaWNrKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICB0cmlnZ2VyRmlsZVVwbG9hZCgpOiB2b2lkIHtcclxuICAgIGNvbnN0IGlucHV0ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2ZpbGUtdXBsb2FkLWlucHV0JykgYXMgSFRNTElucHV0RWxlbWVudDtcclxuICAgIGlmIChpbnB1dCkge1xyXG4gICAgICBpbnB1dC5jbGljaygpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgZ2V0RmlsZUljb24oZmlsZVR5cGU6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICBpZiAoZmlsZVR5cGUuc3RhcnRzV2l0aCgnaW1hZ2UvJykpIHJldHVybiAn8J+WvO+4jyc7XHJcbiAgICBpZiAoZmlsZVR5cGUuaW5jbHVkZXMoJ3BkZicpKSByZXR1cm4gJ/Cfk4QnO1xyXG4gICAgaWYgKGZpbGVUeXBlLmluY2x1ZGVzKCd3b3JkJykgfHwgZmlsZVR5cGUuaW5jbHVkZXMoJ2RvY3VtZW50JykpIHJldHVybiAn8J+TnSc7XHJcbiAgICBpZiAoZmlsZVR5cGUuaW5jbHVkZXMoJ3RleHQnKSkgcmV0dXJuICfwn5ODJztcclxuICAgIHJldHVybiAn8J+Tjic7XHJcbiAgfVxyXG5cclxuICBnZXRGaWxlU2l6ZUZvcm1hdHRlZChieXRlczogbnVtYmVyKTogc3RyaW5nIHtcclxuICAgIGlmIChieXRlcyA8IDEwMjQpIHJldHVybiBieXRlcyArICcgQic7XHJcbiAgICBpZiAoYnl0ZXMgPCAxMDI0ICogMTAyNCkgcmV0dXJuIChieXRlcyAvIDEwMjQpLnRvRml4ZWQoMSkgKyAnIEtCJztcclxuICAgIHJldHVybiAoYnl0ZXMgLyAoMTAyNCAqIDEwMjQpKS50b0ZpeGVkKDEpICsgJyBNQic7XHJcbiAgfVxyXG59IiwiPGRpdiBjbGFzcz1cImFpLWNoYXQtY29udGFpbmVyXCIgXHJcbiAgICAgW25nQ2xhc3NdPVwiZ2V0VGhlbWVDbGFzcygpXCIgXHJcbiAgICAgW25nU3R5bGVdPVwiZ2V0Q29udGFpbmVyU3R5bGUoKVwiXHJcbiAgICAgW2NsYXNzLmZ1bGxzY3JlZW5dPVwiaXNGdWxsc2NyZWVuXCJcclxuICAgICBbY2xhc3MucmVzaXppbmddPVwiaXNSZXNpemluZ1wiPlxyXG4gIFxyXG4gIDwhLS0gUmVzaXplIEhhbmRsZXMgLS0+XHJcbiAgPGRpdiBjbGFzcz1cInJlc2l6ZS1oYW5kbGUgcmVzaXplLWhhbmRsZS1yaWdodFwiIFxyXG4gICAgICAgKG1vdXNlZG93bik9XCJzdGFydFJlc2l6ZSgkZXZlbnQsICd3aWR0aCcpXCJcclxuICAgICAgICpuZ0lmPVwiIWlzRnVsbHNjcmVlblwiXHJcbiAgICAgICB0aXRsZT1cIkRyYWcgdG8gcmVzaXplIHdpZHRoXCI+XHJcbiAgPC9kaXY+XHJcbiAgXHJcbiAgPGRpdiBjbGFzcz1cInJlc2l6ZS1oYW5kbGUgcmVzaXplLWhhbmRsZS1jb3JuZXJcIiBcclxuICAgICAgIChtb3VzZWRvd24pPVwic3RhcnRSZXNpemUoJGV2ZW50LCAnYm90aCcpXCJcclxuICAgICAgICpuZ0lmPVwiIWlzRnVsbHNjcmVlblwiXHJcbiAgICAgICB0aXRsZT1cIkRyYWcgdG8gcmVzaXplXCI+XHJcbiAgPC9kaXY+XHJcbiAgXHJcbiAgPCEtLSBEZWJ1ZyBJbmZvcm1hdGlvbiAob25seSBzaG93biB3aGVuIHNob3dEZWJ1Z0luZm8gaXMgdHJ1ZSkgLS0+XHJcbiAgPGRpdiAqbmdJZj1cInNob3dEZWJ1Z0luZm9cIiBjbGFzcz1cImRlYnVnLWluZm9cIj5cclxuICAgIDxoMz5ERUJVRzogQUkgQ2hhdCBDb21wb25lbnQgTG9hZGVkPC9oMz5cclxuICAgIDxwPlN0YXR1czoge3sgY29uZmlndXJhdGlvblN0YXR1cyB8fCAnTG9hZGluZy4uLicgfX08L3A+XHJcbiAgICA8cD5NZXNzYWdlcyBjb3VudDoge3sgbWVzc2FnZXMubGVuZ3RoIHx8IDAgfX08L3A+XHJcbiAgICA8cD5UaGVtZToge3sgdGVtcGxhdGVEZXNpZ24gfHwgJ2RlZmF1bHQnIH19PC9wPlxyXG4gICAgPHA+U2l6ZToge3sgY3VycmVudFNpemUgfX0gKHt7IGNvbnRhaW5lcldpZHRoIH19eHt7IGNvbnRhaW5lckhlaWdodCB9fSk8L3A+XHJcbiAgPC9kaXY+XHJcblxyXG4gIDxkaXYgY2xhc3M9XCJjaGF0LWhlYWRlclwiPlxyXG4gICAgPGRpdiBjbGFzcz1cImhlYWRlci1sZWZ0XCI+XHJcbiAgICAgIDxoMj57eyB0aXRsZSB9fTwvaDI+XHJcbiAgICAgIDwhLS0gSWNvbi1vbmx5IHN0YXR1cyBpbmRpY2F0b3IgLS0+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJzdGF0dXMtaW5kaWNhdG9yLWljb25cIiBcclxuICAgICAgICAgICBbbmdDbGFzc109XCJ7J3N0YXR1cy1yZWFkeSc6IGNvbmZpZ3VyYXRpb25TdGF0dXMgPT09ICdBSSBBZ2VudCBpcyByZWFkeScsIFxyXG4gICAgICAgICAgICAgICAgICAgICAgJ3N0YXR1cy1lcnJvcic6IGNvbmZpZ3VyYXRpb25TdGF0dXMgIT09ICdBSSBBZ2VudCBpcyByZWFkeScsXHJcbiAgICAgICAgICAgICAgICAgICAgICAnc3RhdHVzLWxvYWRpbmcnOiBjb25maWd1cmF0aW9uU3RhdHVzID09PSAnSW5pdGlhbGl6aW5nLi4uJyB8fCBjb25maWd1cmF0aW9uU3RhdHVzID09PSAnVGVzdGluZyBjb25uZWN0aW9uLi4uJ31cIlxyXG4gICAgICAgICAgIFt0aXRsZV09XCJjb25maWd1cmF0aW9uU3RhdHVzXCI+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgPC9kaXY+XHJcbiAgICBcclxuICAgIDxkaXYgY2xhc3M9XCJoZWFkZXItY29udHJvbHNcIj5cclxuICAgICAgPCEtLSBTaXplIFByZXNldCBCdXR0b25zIC0tPlxyXG4gICAgICA8ZGl2IGNsYXNzPVwic2l6ZS1jb250cm9sc1wiICpuZ0lmPVwiIWlzRnVsbHNjcmVlblwiPlxyXG4gICAgICAgIDxidXR0b24gY2xhc3M9XCJjb250cm9sLWJ1dHRvbiBzaXplLWJ1dHRvblwiIFxyXG4gICAgICAgICAgICAgICAgKGNsaWNrKT1cImFwcGx5U2l6ZVByZXNldCgnY29tcGFjdCcpXCJcclxuICAgICAgICAgICAgICAgIFtjbGFzcy5hY3RpdmVdPVwiY3VycmVudFNpemUgPT09ICdjb21wYWN0J1wiXHJcbiAgICAgICAgICAgICAgICB0aXRsZT1cIkNvbXBhY3QgVmlld1wiXHJcbiAgICAgICAgICAgICAgICBhdHRyLmFyaWEtbGFiZWw9XCJDb21wYWN0IFZpZXdcIj5cclxuICAgICAgICAgIDxzcGFuIGNsYXNzPVwiaWNvbi1zdmdcIiBbaW5uZXJIVE1MXT1cInNhbml0aXplZEljb25zLmNvbXBhY3RWaWV3XCI+PC9zcGFuPlxyXG4gICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgIDxidXR0b24gY2xhc3M9XCJjb250cm9sLWJ1dHRvbiBzaXplLWJ1dHRvblwiIFxyXG4gICAgICAgICAgICAgICAgKGNsaWNrKT1cImFwcGx5U2l6ZVByZXNldCgnZGVmYXVsdCcpXCJcclxuICAgICAgICAgICAgICAgIFtjbGFzcy5hY3RpdmVdPVwiY3VycmVudFNpemUgPT09ICdkZWZhdWx0J1wiXHJcbiAgICAgICAgICAgICAgICB0aXRsZT1cIkRlZmF1bHQgVmlld1wiXHJcbiAgICAgICAgICAgICAgICBhdHRyLmFyaWEtbGFiZWw9XCJEZWZhdWx0IFZpZXdcIj5cclxuICAgICAgICAgIDxzcGFuIGNsYXNzPVwiaWNvbi1zdmdcIiBbaW5uZXJIVE1MXT1cInNhbml0aXplZEljb25zLmRlZmF1bHRWaWV3XCI+PC9zcGFuPlxyXG4gICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgIDxidXR0b24gY2xhc3M9XCJjb250cm9sLWJ1dHRvbiBzaXplLWJ1dHRvblwiIFxyXG4gICAgICAgICAgICAgICAgKGNsaWNrKT1cImFwcGx5U2l6ZVByZXNldCgnZXhwYW5kZWQnKVwiXHJcbiAgICAgICAgICAgICAgICBbY2xhc3MuYWN0aXZlXT1cImN1cnJlbnRTaXplID09PSAnZXhwYW5kZWQnXCJcclxuICAgICAgICAgICAgICAgIHRpdGxlPVwiRXhwYW5kZWQgVmlld1wiXHJcbiAgICAgICAgICAgICAgICBhdHRyLmFyaWEtbGFiZWw9XCJFeHBhbmRlZCBWaWV3XCI+XHJcbiAgICAgICAgICA8c3BhbiBjbGFzcz1cImljb24tc3ZnXCIgW2lubmVySFRNTF09XCJzYW5pdGl6ZWRJY29ucy5leHBhbmRlZFZpZXdcIj48L3NwYW4+XHJcbiAgICAgICAgPC9idXR0b24+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgPC9kaXY+XHJcbiAgPC9kaXY+XHJcblxyXG4gIDxkaXYgY2xhc3M9XCJjaGF0LW1lc3NhZ2VzXCIgI21lc3NhZ2VzQ29udGFpbmVyPlxyXG4gICAgPGRpdiAqbmdGb3I9XCJsZXQgbWVzc2FnZSBvZiBtZXNzYWdlczsgbGV0IGkgPSBpbmRleDsgdHJhY2tCeTogdHJhY2tCeUluZGV4XCIgY2xhc3M9XCJtZXNzYWdlLXdyYXBwZXJcIj5cclxuICAgICAgPCEtLSBNZXNzYWdlIC0tPlxyXG4gICAgICA8ZGl2IGNsYXNzPVwibWVzc2FnZVwiIFxyXG4gICAgICAgICAgIFtuZ0NsYXNzXT1cInsndXNlci1tZXNzYWdlJzogbWVzc2FnZS5pc1VzZXIsICdhaS1tZXNzYWdlJzogIW1lc3NhZ2UuaXNVc2VyLCAnbG9hZGluZy1tZXNzYWdlJzogbWVzc2FnZS5pc0xvYWRpbmd9XCI+XHJcbiAgICAgICAgXHJcbiAgICAgICAgPGRpdiBjbGFzcz1cIm1lc3NhZ2UtY29udGVudFwiPlxyXG4gICAgICAgICAgPGRpdiBbaW5uZXJIVE1MXT1cIm1lc3NhZ2UuY29udGVudFwiPjwvZGl2PlxyXG4gICAgICAgICAgPGRpdiBjbGFzcz1cIm1lc3NhZ2UtdGltZXN0YW1wXCI+e3sgZ2V0Rm9ybWF0dGVkVGltZShtZXNzYWdlLnRpbWVzdGFtcCkgfX08L2Rpdj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgICBcclxuICAgICAgICA8ZGl2IGNsYXNzPVwibWVzc2FnZS1hdmF0YXJcIj5cclxuICAgICAgICAgIDxzcGFuICpuZ0lmPVwibWVzc2FnZS5pc1VzZXJcIiBjbGFzcz1cImF2YXRhci1pY29uXCIgW2lubmVySFRNTF09XCJzYW5pdGl6ZWRJY29ucy51c2VyQXZhdGFyXCI+PC9zcGFuPlxyXG4gICAgICAgICAgPHNwYW4gKm5nSWY9XCIhbWVzc2FnZS5pc1VzZXIgJiYgIW1lc3NhZ2UuaXNMb2FkaW5nXCIgY2xhc3M9XCJhdmF0YXItaWNvblwiIFtpbm5lckhUTUxdPVwic2FuaXRpemVkSWNvbnMuYWlBdmF0YXJcIj48L3NwYW4+XHJcbiAgICAgICAgICA8c3BhbiAqbmdJZj1cIm1lc3NhZ2UuaXNMb2FkaW5nXCIgY2xhc3M9XCJhdmF0YXItaWNvbiBsb2FkaW5nLXNwaW5uZXJcIiBbaW5uZXJIVE1MXT1cInNhbml0aXplZEljb25zLmxvYWRpbmdBdmF0YXJcIj48L3NwYW4+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgPC9kaXY+XHJcbiAgPC9kaXY+XHJcblxyXG4gIDxkaXYgY2xhc3M9XCJjaGF0LWlucHV0XCI+XHJcbiAgICA8IS0tIEF0dGFjaG1lbnRzIFByZXZpZXcgLS0+XHJcbiAgICA8ZGl2IGNsYXNzPVwiYXR0YWNobWVudHMtcHJldmlld1wiICpuZ0lmPVwic2VsZWN0ZWRGaWxlcy5sZW5ndGggPiAwXCI+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJhdHRhY2htZW50LWl0ZW1cIiAqbmdGb3I9XCJsZXQgZmlsZSBvZiBzZWxlY3RlZEZpbGVzXCI+XHJcbiAgICAgICAgPHN2ZyBjbGFzcz1cImF0dGFjaG1lbnQtaWNvblwiIHZpZXdCb3g9XCIwIDAgMjQgMjRcIiBmaWxsPVwibm9uZVwiIHN0cm9rZT1cImN1cnJlbnRDb2xvclwiIHN0cm9rZS13aWR0aD1cIjJcIj5cclxuICAgICAgICAgIDxwYXRoIGQ9XCJNMjEuNDQgMTEuMDVsLTkuMTkgOS4xOWE2IDYgMCAwIDEtOC40OS04LjQ5bDkuMTktOS4xOWE0IDQgMCAwIDEgNS42NiA1LjY2bC05LjIgOS4xOWEyIDIgMCAwIDEtMi44My0yLjgzbDguNDktOC40OFwiPjwvcGF0aD5cclxuICAgICAgICA8L3N2Zz5cclxuICAgICAgICA8c3BhbiBjbGFzcz1cImF0dGFjaG1lbnQtbmFtZVwiPnt7IGZpbGUubmFtZSB9fTwvc3Bhbj5cclxuICAgICAgICA8c3BhbiBjbGFzcz1cImF0dGFjaG1lbnQtc2l6ZVwiPnt7IGdldEZpbGVTaXplRm9ybWF0dGVkKGZpbGUuc2l6ZSkgfX08L3NwYW4+XHJcbiAgICAgICAgPGJ1dHRvbiBjbGFzcz1cInJlbW92ZS1hdHRhY2htZW50XCIgKGNsaWNrKT1cInJlbW92ZUF0dGFjaG1lbnQoZmlsZS5pZClcIiB0aXRsZT1cIlJlbW92ZVwiIGF0dHIuYXJpYS1sYWJlbD1cIlJlbW92ZSBhdHRhY2htZW50XCI+XHJcbiAgICAgICAgICA8c3ZnIHZpZXdCb3g9XCIwIDAgMjQgMjRcIiBmaWxsPVwibm9uZVwiIHN0cm9rZT1cImN1cnJlbnRDb2xvclwiIHN0cm9rZS13aWR0aD1cIjJcIj5cclxuICAgICAgICAgICAgPGxpbmUgeDE9XCIxOFwiIHkxPVwiNlwiIHgyPVwiNlwiIHkyPVwiMThcIj48L2xpbmU+XHJcbiAgICAgICAgICAgIDxsaW5lIHgxPVwiNlwiIHkxPVwiNlwiIHgyPVwiMThcIiB5Mj1cIjE4XCI+PC9saW5lPlxyXG4gICAgICAgICAgPC9zdmc+XHJcbiAgICAgICAgPC9idXR0b24+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgPC9kaXY+XHJcbiAgICBcclxuICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1jb250YWluZXJcIj5cclxuICAgICAgPCEtLSBGaWxlIFVwbG9hZCBJbnB1dHMgKEhpZGRlbikgLS0+XHJcbiAgICAgIDxpbnB1dCB0eXBlPVwiZmlsZVwiIFxyXG4gICAgICAgICAgICAgaWQ9XCJpbWFnZS11cGxvYWQtaW5wdXRcIiBcclxuICAgICAgICAgICAgIGFjY2VwdD1cImltYWdlLypcIiBcclxuICAgICAgICAgICAgIG11bHRpcGxlIFxyXG4gICAgICAgICAgICAgKGNoYW5nZSk9XCJvbkltYWdlVXBsb2FkKCRldmVudClcIlxyXG4gICAgICAgICAgICAgc3R5bGU9XCJkaXNwbGF5OiBub25lO1wiXHJcbiAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiIWVuYWJsZUltYWdlVXBsb2FkXCI+XHJcbiAgICAgIFxyXG4gICAgICA8aW5wdXQgdHlwZT1cImZpbGVcIiBcclxuICAgICAgICAgICAgIGlkPVwiZmlsZS11cGxvYWQtaW5wdXRcIiBcclxuICAgICAgICAgICAgIGFjY2VwdD1cIi5wZGYsLmRvYywuZG9jeCwudHh0LC5jc3ZcIiBcclxuICAgICAgICAgICAgIG11bHRpcGxlIFxyXG4gICAgICAgICAgICAgKGNoYW5nZSk9XCJvbkZpbGVVcGxvYWQoJGV2ZW50KVwiXHJcbiAgICAgICAgICAgICBzdHlsZT1cImRpc3BsYXk6IG5vbmU7XCJcclxuICAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhZW5hYmxlRmlsZVVwbG9hZFwiPlxyXG4gICAgICBcclxuICAgICAgPCEtLSBVcGxvYWQgQnV0dG9ucyAoQ29uZGl0aW9uYWxseSByZW5kZXJlZCkgLS0+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJ1cGxvYWQtYnV0dG9uc1wiICpuZ0lmPVwiZW5hYmxlSW1hZ2VVcGxvYWQgfHwgZW5hYmxlRmlsZVVwbG9hZFwiPlxyXG4gICAgICAgIDxidXR0b24gKm5nSWY9XCJlbmFibGVJbWFnZVVwbG9hZFwiIFxyXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJ1cGxvYWQtYnV0dG9uIGltYWdlLXVwbG9hZFwiIFxyXG4gICAgICAgICAgICAgICAgKGNsaWNrKT1cInRyaWdnZXJJbWFnZVVwbG9hZCgpXCJcclxuICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJpc0xvYWRpbmdcIlxyXG4gICAgICAgICAgICAgICAgdGl0bGU9XCJVcGxvYWQgSW1hZ2VcIlxyXG4gICAgICAgICAgICAgICAgYXR0ci5hcmlhLWxhYmVsPVwiVXBsb2FkIEltYWdlXCI+XHJcbiAgICAgICAgICA8c3BhbiBjbGFzcz1cImljb24tc3ZnXCIgW2lubmVySFRNTF09XCJzYW5pdGl6ZWRJY29ucy5pbWFnZVVwbG9hZFwiPjwvc3Bhbj5cclxuICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICBcclxuICAgICAgICA8YnV0dG9uICpuZ0lmPVwiZW5hYmxlRmlsZVVwbG9hZFwiIFxyXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJ1cGxvYWQtYnV0dG9uIGZpbGUtdXBsb2FkXCIgXHJcbiAgICAgICAgICAgICAgICAoY2xpY2spPVwidHJpZ2dlckZpbGVVcGxvYWQoKVwiXHJcbiAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiaXNMb2FkaW5nXCJcclxuICAgICAgICAgICAgICAgIHRpdGxlPVwiQXR0YWNoIEZpbGVcIlxyXG4gICAgICAgICAgICAgICAgYXR0ci5hcmlhLWxhYmVsPVwiQXR0YWNoIEZpbGVcIj5cclxuICAgICAgICAgIDxzcGFuIGNsYXNzPVwiaWNvbi1zdmdcIiBbaW5uZXJIVE1MXT1cInNhbml0aXplZEljb25zLmZpbGVVcGxvYWRcIj48L3NwYW4+XHJcbiAgICAgICAgPC9idXR0b24+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgICBcclxuICAgICAgPHRleHRhcmVhIFxyXG4gICAgICAgIFsobmdNb2RlbCldPVwiY3VycmVudElucXVpcnlcIiBcclxuICAgICAgICAoa2V5cHJlc3MpPVwib25LZXlQcmVzcygkZXZlbnQpXCJcclxuICAgICAgICBbcGxhY2Vob2xkZXJdPVwicGxhY2Vob2xkZXJcIlxyXG4gICAgICAgIHJvd3M9XCIyXCJcclxuICAgICAgICBbZGlzYWJsZWRdPVwiaXNMb2FkaW5nXCJcclxuICAgICAgICBjbGFzcz1cImlucXVpcnktdGV4dGFyZWFcIlxyXG4gICAgICAgIGF0dHIuYXJpYS1sYWJlbD1cIlR5cGUgeW91ciBtZXNzYWdlXCI+PC90ZXh0YXJlYT5cclxuICAgICAgXHJcbiAgICAgIDxidXR0b24gXHJcbiAgICAgICAgKGNsaWNrKT1cInNlbmRJbnF1aXJ5KClcIiBcclxuICAgICAgICBbZGlzYWJsZWRdPVwiIWN1cnJlbnRJbnF1aXJ5LnRyaW0oKSB8fCBpc0xvYWRpbmdcIlxyXG4gICAgICAgIGNsYXNzPVwic2VuZC1idXR0b25cIlxyXG4gICAgICAgIHRpdGxlPVwiU2VuZCBNZXNzYWdlXCJcclxuICAgICAgICBhdHRyLmFyaWEtbGFiZWw9XCJTZW5kIE1lc3NhZ2VcIj5cclxuICAgICAgICA8c3BhbiAqbmdJZj1cIiFpc0xvYWRpbmdcIiBjbGFzcz1cImljb24tc3ZnXCIgW2lubmVySFRNTF09XCJzYW5pdGl6ZWRJY29ucy5zZW5kXCI+PC9zcGFuPlxyXG4gICAgICAgIDxzcGFuICpuZ0lmPVwiaXNMb2FkaW5nXCIgY2xhc3M9XCJpY29uLXN2ZyBsb2FkaW5nLWljb25cIiBbaW5uZXJIVE1MXT1cInNhbml0aXplZEljb25zLnNlbmRMb2FkaW5nXCI+PC9zcGFuPlxyXG4gICAgICAgIDxzcGFuIGNsYXNzPVwidGV4dFwiPnt7IGlzTG9hZGluZyA/ICdTZW5kaW5nLi4uJyA6ICdTZW5kJyB9fTwvc3Bhbj5cclxuICAgICAgPC9idXR0b24+XHJcbiAgICA8L2Rpdj5cclxuICA8L2Rpdj5cclxuPC9kaXY+Il19
|