@sinequa/assistant 3.9.2 → 3.9.3
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/chat/chat.component.d.ts +35 -38
- package/chat/chat.service.d.ts +190 -84
- package/chat/debug-message/debug-message-details/debug-message-details.component.d.ts +19 -0
- package/chat/debug-message/debug-message.component.d.ts +9 -12
- package/chat/debug-message/debug-message.service.d.ts +15 -0
- package/chat/documents-upload/document-list/document-list.component.d.ts +1 -0
- package/chat/public-api.d.ts +0 -2
- package/chat/saved-chats/i18n/en.json +1 -1
- package/chat/saved-chats/i18n/fr.json +1 -1
- package/chat/saved-chats/saved-chats.component.d.ts +1 -0
- package/chat/saved-chats/saved-chats.service.d.ts +27 -0
- package/chat/services/assistant-configuration.service.d.ts +34 -0
- package/chat/services/assistant-metadata.service.d.ts +18 -0
- package/chat/services/assistant-tokens-tracking.service.d.ts +23 -0
- package/chat/services/assistant-ws-frames.service.d.ts +50 -0
- package/chat/services/signalR-connection.service.d.ts +25 -0
- package/chat/types.d.ts +12 -3
- package/chat/utils/utils.service.d.ts +67 -0
- package/esm2022/chat/chat.component.mjs +198 -227
- package/esm2022/chat/chat.service.mjs +450 -267
- package/esm2022/chat/debug-message/debug-message-details/debug-message-details.component.mjs +43 -0
- package/esm2022/chat/debug-message/debug-message.component.mjs +27 -30
- package/esm2022/chat/debug-message/debug-message.service.mjs +52 -0
- package/esm2022/chat/dialogs/rename-saved-chat.component.mjs +6 -5
- package/esm2022/chat/documents-upload/document-list/document-list.component.mjs +4 -2
- package/esm2022/chat/public-api.mjs +1 -3
- package/esm2022/chat/saved-chats/saved-chats.component.mjs +11 -10
- package/esm2022/chat/saved-chats/saved-chats.service.mjs +165 -0
- package/esm2022/chat/services/assistant-configuration.service.mjs +171 -0
- package/esm2022/chat/services/assistant-metadata.service.mjs +67 -0
- package/esm2022/chat/services/assistant-tokens-tracking.service.mjs +57 -0
- package/esm2022/chat/services/assistant-ws-frames.service.mjs +392 -0
- package/esm2022/chat/services/signalR-connection.service.mjs +109 -0
- package/esm2022/chat/types.mjs +1 -1
- package/esm2022/chat/unified-plugins/embedded-image-reference.plugin.mjs +2 -3
- package/esm2022/chat/utils/utils.service.mjs +170 -0
- package/fesm2022/sinequa-assistant-chat.mjs +2020 -1648
- package/fesm2022/sinequa-assistant-chat.mjs.map +1 -1
- package/package.json +1 -1
- package/chat/rest-chat.service.d.ts +0 -31
- package/chat/websocket-chat.service.d.ts +0 -102
- package/esm2022/chat/rest-chat.service.mjs +0 -300
- package/esm2022/chat/websocket-chat.service.mjs +0 -659
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
import { Injectable, inject } from '@angular/core';
|
|
2
|
+
import { TranslocoService } from '@jsverse/transloco';
|
|
3
|
+
import { Observable, Subject, fromEvent, merge, of, throwError } from 'rxjs';
|
|
4
|
+
import { map, mergeMap, takeUntil, tap, take, switchMap, finalize } from 'rxjs/operators';
|
|
5
|
+
import { guid } from "@sinequa/atomic";
|
|
6
|
+
import { AppService } from './app.service';
|
|
7
|
+
import { AssistantUtils } from '../utils/utils.service';
|
|
8
|
+
import { NotificationsService } from './notification.service';
|
|
9
|
+
import * as i0 from "@angular/core";
|
|
10
|
+
export class AssistantWsFramesService {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.appService = inject(AppService);
|
|
13
|
+
this.transloco = inject(TranslocoService);
|
|
14
|
+
this.assistantUtils = inject(AssistantUtils);
|
|
15
|
+
this.notificationsService = inject(NotificationsService);
|
|
16
|
+
this._messageHandlers = new Map();
|
|
17
|
+
this._actionMap = new Map();
|
|
18
|
+
this._progress = undefined;
|
|
19
|
+
this._attachments = [];
|
|
20
|
+
this._debugMessages = [];
|
|
21
|
+
}
|
|
22
|
+
init(context) {
|
|
23
|
+
if (this.context) {
|
|
24
|
+
console.warn('AssistantWsFramesService already initialized.');
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
this.context = context;
|
|
28
|
+
}
|
|
29
|
+
ensureInitialized() {
|
|
30
|
+
if (!this.context) {
|
|
31
|
+
throw new Error('AssistantWsFramesService not initialized. Call init() first.');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
fetch(messages, query) {
|
|
35
|
+
this.ensureInitialized();
|
|
36
|
+
const context = this.context;
|
|
37
|
+
const assistantConfig = context.getAssistantConfig();
|
|
38
|
+
// Start streaming by invoking the Chat method
|
|
39
|
+
context.setStreamingStatus(true);
|
|
40
|
+
// Prepare the payload to send to the Chat method
|
|
41
|
+
const data = {
|
|
42
|
+
history: messages,
|
|
43
|
+
functions: assistantConfig.defaultValues.functions?.filter(func => func.enabled).map(func => func.name),
|
|
44
|
+
debug: assistantConfig.defaultValues.debug,
|
|
45
|
+
serviceSettings: {
|
|
46
|
+
service_id: assistantConfig.defaultValues.service_id,
|
|
47
|
+
model_id: assistantConfig.defaultValues.model_id,
|
|
48
|
+
top_p: assistantConfig.defaultValues.top_p,
|
|
49
|
+
temperature: assistantConfig.defaultValues.temperature,
|
|
50
|
+
max_tokens: assistantConfig.defaultValues.max_tokens,
|
|
51
|
+
...assistantConfig.additionalServiceSettings
|
|
52
|
+
},
|
|
53
|
+
appQuery: {
|
|
54
|
+
app: this.appService.appName,
|
|
55
|
+
query
|
|
56
|
+
},
|
|
57
|
+
instanceId: context.getChatInstanceId(),
|
|
58
|
+
chatId: context.getChatId(),
|
|
59
|
+
genericChatErrorMessage: assistantConfig.globalSettings.genericChatErrorMessage ? this.transloco.translate(assistantConfig.globalSettings.genericChatErrorMessage) : ""
|
|
60
|
+
};
|
|
61
|
+
// Initialize the response with an empty assistant message
|
|
62
|
+
// here display: true is needed in order to be able to show the progress
|
|
63
|
+
// here messageId is needed but it is temporary and will be replaced by the correct messageId generated by the assistant when the message starts streaming
|
|
64
|
+
this._response = [{ role: "assistant", content: "", additionalProperties: { display: true, messageId: guid() } }];
|
|
65
|
+
// Create a Subject to signal completion
|
|
66
|
+
const completion$ = new Subject();
|
|
67
|
+
// Create observables for each non-global handler in the _messageHandlers map (default and eventual custom ones) once it is triggered by the hub connection
|
|
68
|
+
const observables = Array
|
|
69
|
+
.from(this._messageHandlers.entries())
|
|
70
|
+
.filter(([eventName, eventHandler]) => !eventHandler.isGlobalHandler)
|
|
71
|
+
.map(([eventName, eventHandler]) => fromEvent(context.getHubConnection(), eventName).pipe(mergeMap((event) => {
|
|
72
|
+
// Wrap the handler in a try-catch block to prevent the entire stream from failing if an error occurs in a single handler
|
|
73
|
+
try {
|
|
74
|
+
// Execute the handler and emit the result
|
|
75
|
+
// NB: here we could use [eventHandler.handler(event)] which behind the scenes mergeMap interprets this array as an observable sequence with one item, which it then emits
|
|
76
|
+
return of(eventHandler.handler(event));
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
console.error(`Error in event handler for ${eventName}:`, error);
|
|
80
|
+
// Use throwError to propagate the error downstream
|
|
81
|
+
return throwError(() => new Error(`Error in event handler for ${eventName}: ${error}`));
|
|
82
|
+
}
|
|
83
|
+
})));
|
|
84
|
+
// Then merge them into a single observable in order to simulate the streaming behavior
|
|
85
|
+
const combined$ = merge(...observables).pipe(map(() => {
|
|
86
|
+
// Define $progress from the _actionMap
|
|
87
|
+
const actions = Array.from(this._actionMap.values());
|
|
88
|
+
this._progress = actions.length > 0
|
|
89
|
+
? actions.map((a) => ({
|
|
90
|
+
title: a.displayName ?? "",
|
|
91
|
+
content: a.displayValue ?? "",
|
|
92
|
+
done: a.executionTime !== undefined,
|
|
93
|
+
time: a.executionTime,
|
|
94
|
+
}))
|
|
95
|
+
: undefined;
|
|
96
|
+
// Always update ONLY the first assistant message of the _response with the new $progress, $attachment and $debug
|
|
97
|
+
// Assuming that the first assistant message is always visible since the hub does not send hidden messages by design
|
|
98
|
+
// So even if the first assistant message is hidden (display: false), the _response[0] will and should contain :
|
|
99
|
+
// - $progress, $attachment and $debug
|
|
100
|
+
// - the content of the first visible assistant message in the workflow
|
|
101
|
+
// This is mandatory in order to match the behavior of consecutive messages and maintain consistency with the chatHistory
|
|
102
|
+
if (!!this._progress || this._attachments.length > 0 || this._debugMessages.length > 0) {
|
|
103
|
+
this._response[0].additionalProperties.$progress = this._progress;
|
|
104
|
+
this._response[0].additionalProperties.$attachment = this._attachments;
|
|
105
|
+
this._response[0].additionalProperties.$debug = this._debugMessages;
|
|
106
|
+
}
|
|
107
|
+
// Return the result
|
|
108
|
+
return { history: [...messages, ...this._response], executionTime: this._executionTime, executionTimeMilliseconds: this._executionTimeMilliseconds };
|
|
109
|
+
}),
|
|
110
|
+
// Complete the observable when completion$ emits
|
|
111
|
+
takeUntil(completion$));
|
|
112
|
+
// return a new Observable that emits the result of the combined stream and handles the eventual errors of the invocation of the Chat method
|
|
113
|
+
return new Observable(observer => {
|
|
114
|
+
// Subscribe to combined stream
|
|
115
|
+
combined$.subscribe({
|
|
116
|
+
next: (value) => observer.next(value),
|
|
117
|
+
error: (err) => observer.error(err)
|
|
118
|
+
});
|
|
119
|
+
// Invoke the Chat method and handle errors
|
|
120
|
+
context.getHubConnection().invoke('Chat', data)
|
|
121
|
+
.then(() => {
|
|
122
|
+
const chatHistory = context.getChatHistory();
|
|
123
|
+
// If a valid assistant message with (display: true) was found, update it
|
|
124
|
+
// and it should always the case
|
|
125
|
+
const index = this.assistantUtils.firstVisibleAssistantMessageIndex(chatHistory);
|
|
126
|
+
if (index !== -1) {
|
|
127
|
+
chatHistory[index].additionalProperties.$progress = this._progress;
|
|
128
|
+
chatHistory[index].additionalProperties.$attachment = this._attachments;
|
|
129
|
+
chatHistory[index].additionalProperties.$debug = this._debugMessages;
|
|
130
|
+
context.setChatHistory(chatHistory);
|
|
131
|
+
}
|
|
132
|
+
// Save/update the chat if savedChat enabled
|
|
133
|
+
if (assistantConfig.savedChatSettings.enabled && context.getChatHistory().some((msg) => msg.additionalProperties?.isUserInput === true)) {
|
|
134
|
+
context.isExistingSavedChat(context.getChatId()).pipe(take(1), switchMap((exists) => exists
|
|
135
|
+
? context.updateSavedChat(context.getChatId(), undefined, context.getChatHistory())
|
|
136
|
+
: context.addSavedChat(context.getChatId(), context.getChatHistory()).pipe(tap(() => context.listSavedChat()))), finalize(() => context.setStreamingStatus(false))).subscribe({
|
|
137
|
+
next: () => { },
|
|
138
|
+
error: (error) => observer.error(error),
|
|
139
|
+
complete: () => observer.complete()
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
context.setStreamingStatus(false);
|
|
144
|
+
observer.complete();
|
|
145
|
+
}
|
|
146
|
+
})
|
|
147
|
+
.catch(error => {
|
|
148
|
+
console.error('Error invoking Chat:', error);
|
|
149
|
+
context.setStreamingStatus(false);
|
|
150
|
+
// Emit the error to the newly created observable
|
|
151
|
+
observer.error(error);
|
|
152
|
+
// Return a resolved promise to handle the error and prevent unhandled promise rejection
|
|
153
|
+
return Promise.resolve();
|
|
154
|
+
})
|
|
155
|
+
.finally(() => {
|
|
156
|
+
// This block concerns ONLY the completion of the "Chat" method invocation.
|
|
157
|
+
// This means the completion of the combined$ stream.
|
|
158
|
+
// It does not take into account the completion of the entire fetch method (the observable returned by fetch) and which depends on the completion of the save chat action if enabled
|
|
159
|
+
this._response = []; // Clear the _response
|
|
160
|
+
this._actionMap.clear(); // Clear the _actionMap
|
|
161
|
+
this._progress = undefined; // Clear the _progress
|
|
162
|
+
this._attachments = []; // Clear the _attachments
|
|
163
|
+
this._debugMessages = []; // Clear the _debugMessages
|
|
164
|
+
this._executionTime = ""; // Clear the _executionTime
|
|
165
|
+
this._executionTimeMilliseconds = undefined; // Clear the _executionTimeMilliseconds
|
|
166
|
+
completion$.next(); // Emit a signal to complete the observables
|
|
167
|
+
completion$.complete(); // Complete the subject
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
initMessageHandlers() {
|
|
172
|
+
this.ensureInitialized();
|
|
173
|
+
const context = this.context;
|
|
174
|
+
this.addMessageHandler("Error", {
|
|
175
|
+
handler: (error) => {
|
|
176
|
+
if (error.indexOf('SavedChatList') !== -1) {
|
|
177
|
+
context.setSavedChatsErrorStatus(true);
|
|
178
|
+
}
|
|
179
|
+
console.error(error);
|
|
180
|
+
this.notificationsService.error(error);
|
|
181
|
+
},
|
|
182
|
+
isGlobalHandler: true
|
|
183
|
+
});
|
|
184
|
+
this.addMessageHandler("Quota", {
|
|
185
|
+
handler: (message) => {
|
|
186
|
+
try {
|
|
187
|
+
context.updateQuota(message.quota);
|
|
188
|
+
}
|
|
189
|
+
catch (error) {
|
|
190
|
+
console.error(error);
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
isGlobalHandler: true
|
|
194
|
+
});
|
|
195
|
+
this.addMessageHandler("Debug", { handler: () => { }, isGlobalHandler: true });
|
|
196
|
+
this.addMessageHandler("ActionStart", {
|
|
197
|
+
handler: (action) => this._actionMap.set(action.guid, action),
|
|
198
|
+
isGlobalHandler: false
|
|
199
|
+
});
|
|
200
|
+
this.addMessageHandler("ActionResult", {
|
|
201
|
+
handler: (action) => this._actionMap.set(action.guid, { ...this._actionMap.get(action.guid), ...action }),
|
|
202
|
+
isGlobalHandler: false
|
|
203
|
+
});
|
|
204
|
+
this.addMessageHandler("ActionStop", {
|
|
205
|
+
handler: (action) => this._actionMap.set(action.guid, { ...this._actionMap.get(action.guid), ...action }),
|
|
206
|
+
isGlobalHandler: false
|
|
207
|
+
});
|
|
208
|
+
this.addMessageHandler("ContextMessage", {
|
|
209
|
+
handler: (message) => { this._attachments.push(message.additionalProperties); },
|
|
210
|
+
isGlobalHandler: false
|
|
211
|
+
});
|
|
212
|
+
this.addMessageHandler("Message", {
|
|
213
|
+
handler: (message) => {
|
|
214
|
+
this._response.at(-1).content += message.delta ?? "";
|
|
215
|
+
this._response.at(-1).additionalProperties.messageId = message.messageId;
|
|
216
|
+
},
|
|
217
|
+
isGlobalHandler: false
|
|
218
|
+
});
|
|
219
|
+
this.addMessageHandler("History", {
|
|
220
|
+
handler: (history) => {
|
|
221
|
+
// The ChatHistory is updated: it is the current copy concatenated with the new items ONLY (it can have multiple messages: the context messages + the response message)
|
|
222
|
+
// This is mandatory to not lose the previous updates of the chatHistory when the assistant is streaming multiple message steps
|
|
223
|
+
const currentChatHistory = (context.getChatHistory() || []);
|
|
224
|
+
const newHistory = [...currentChatHistory, ...(history.history.slice(currentChatHistory.length))];
|
|
225
|
+
context.setChatHistory(newHistory);
|
|
226
|
+
// Emit the updated chat usage metrics
|
|
227
|
+
const lastMessage = newHistory.at(-1);
|
|
228
|
+
if (lastMessage?.additionalProperties.usageMetrics) {
|
|
229
|
+
context.updateChatUsageMetrics(lastMessage.additionalProperties.usageMetrics);
|
|
230
|
+
}
|
|
231
|
+
this._executionTime = history.executionTime;
|
|
232
|
+
this._executionTimeMilliseconds = history.executionTimeMilliseconds;
|
|
233
|
+
},
|
|
234
|
+
isGlobalHandler: false
|
|
235
|
+
});
|
|
236
|
+
this.addMessageHandler("SuggestedActions", {
|
|
237
|
+
handler: (message) => {
|
|
238
|
+
// Since after the "History" and "MessageBreak" that this event is caught,
|
|
239
|
+
// $suggestedAction needs to be updated directly to the last visible "assistant" message in the _response and the chatHistory
|
|
240
|
+
this._response.at(-1).additionalProperties.$suggestedAction = (this._response.at(-1).additionalProperties.$suggestedAction || []).concat(message.suggestedActions);
|
|
241
|
+
const chatHistory = context.getChatHistory();
|
|
242
|
+
const index = this.assistantUtils.lastVisibleAssistantMessageIndex(chatHistory);
|
|
243
|
+
if (index !== -1) {
|
|
244
|
+
chatHistory[index].additionalProperties.$suggestedAction = (chatHistory[index].additionalProperties.$suggestedAction || []).concat(message.suggestedActions);
|
|
245
|
+
context.setChatHistory(chatHistory);
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
isGlobalHandler: false
|
|
249
|
+
});
|
|
250
|
+
this.addMessageHandler("DebugDisplay", {
|
|
251
|
+
handler: (message) => this._debugMessages = this._debugMessages.concat(message),
|
|
252
|
+
isGlobalHandler: false
|
|
253
|
+
});
|
|
254
|
+
this.addMessageHandler("MessageBreak", {
|
|
255
|
+
handler: () => {
|
|
256
|
+
// Systematically happens right after the "History" event
|
|
257
|
+
// This is the moment when the assistant message is fully streamed
|
|
258
|
+
const assistantConfig = context.getAssistantConfig();
|
|
259
|
+
const chatHistory = context.getChatHistory();
|
|
260
|
+
if (!assistantConfig || !chatHistory || !chatHistory.length)
|
|
261
|
+
return;
|
|
262
|
+
const lastChatMessage = chatHistory.at(-1);
|
|
263
|
+
const details = {
|
|
264
|
+
'duration': this._executionTimeMilliseconds !== undefined ? this._executionTimeMilliseconds : this._executionTime,
|
|
265
|
+
'role': lastChatMessage.role,
|
|
266
|
+
'rank': chatHistory.length,
|
|
267
|
+
'message-id': lastChatMessage.additionalProperties.messageId,
|
|
268
|
+
'generation-tokencount': lastChatMessage.additionalProperties.usageMetrics?.completionTokenCount,
|
|
269
|
+
'prompt-tokencount': lastChatMessage.additionalProperties.usageMetrics?.promptTokenCount,
|
|
270
|
+
'attachments': JSON.stringify(this._attachments.map(({ recordId, contextId, parts, type }) => ({
|
|
271
|
+
recordId,
|
|
272
|
+
contextId,
|
|
273
|
+
parts: parts.map(({ partId, text }) => {
|
|
274
|
+
if (!!assistantConfig.auditSettings?.logContent)
|
|
275
|
+
return { partId, text };
|
|
276
|
+
return { partId };
|
|
277
|
+
}),
|
|
278
|
+
type
|
|
279
|
+
})))
|
|
280
|
+
};
|
|
281
|
+
if (!!assistantConfig.auditSettings?.logContent) {
|
|
282
|
+
if (typeof lastChatMessage.content === 'string') {
|
|
283
|
+
details['text'] = lastChatMessage.content;
|
|
284
|
+
}
|
|
285
|
+
else if (Array.isArray(lastChatMessage.content)) {
|
|
286
|
+
details['text'] = lastChatMessage.content.find((msg) => msg.type === "text").text;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
context.generateAuditEvent('ast-message.message', details);
|
|
290
|
+
// Push a new assistant message to the _response array ONLY if the content of the last message is not empty
|
|
291
|
+
if (this._response.at(-1).content !== "") {
|
|
292
|
+
this._response.push({ role: "assistant", content: "", additionalProperties: { display: true, messageId: guid() } });
|
|
293
|
+
}
|
|
294
|
+
},
|
|
295
|
+
isGlobalHandler: false
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
overrideMessageHandlers(_messageHandlers) {
|
|
299
|
+
this.ensureInitialized();
|
|
300
|
+
// Clear the already registered global chat handlers before merging the new ones
|
|
301
|
+
this._messageHandlers.forEach((eventHandler, eventName) => {
|
|
302
|
+
if (eventHandler.isGlobalHandler) {
|
|
303
|
+
this.unsubscribeMessageHandler(eventName);
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
// Merge the new event handlers with the existing ones
|
|
307
|
+
this._messageHandlers = new Map([...this._messageHandlers, ..._messageHandlers]);
|
|
308
|
+
// Register the global handlers among the merged map
|
|
309
|
+
this._messageHandlers.forEach((eventHandler, eventName) => {
|
|
310
|
+
if (eventHandler.isGlobalHandler) {
|
|
311
|
+
this.registerMessageHandler(eventName, eventHandler);
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
addMessageHandler(eventName, eventHandler) {
|
|
316
|
+
this.ensureInitialized();
|
|
317
|
+
this._messageHandlers.set(eventName, eventHandler);
|
|
318
|
+
if (eventHandler.isGlobalHandler) {
|
|
319
|
+
this.registerMessageHandler(eventName, eventHandler);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
registerMessageHandler(eventName, eventHandler) {
|
|
323
|
+
this.ensureInitialized();
|
|
324
|
+
const connection = this.context.getHubConnection();
|
|
325
|
+
if (!connection) {
|
|
326
|
+
console.log("No connection found to register the listener" + eventName);
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
connection.on(eventName, (data) => {
|
|
330
|
+
eventHandler.handler(data);
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
removeMessageHandler(eventName) {
|
|
334
|
+
this.ensureInitialized();
|
|
335
|
+
this._messageHandlers.delete(eventName);
|
|
336
|
+
this.unsubscribeMessageHandler(eventName);
|
|
337
|
+
}
|
|
338
|
+
unsubscribeMessageHandler(eventName) {
|
|
339
|
+
this.ensureInitialized();
|
|
340
|
+
const connection = this.context.getHubConnection();
|
|
341
|
+
connection?.off(eventName);
|
|
342
|
+
}
|
|
343
|
+
stopGeneration() {
|
|
344
|
+
this.ensureInitialized();
|
|
345
|
+
const context = this.context;
|
|
346
|
+
const connection = context.getHubConnection();
|
|
347
|
+
// Start stopping generation by invoking the CancelTasks method
|
|
348
|
+
context.setStoppingGenerationStatus(true);
|
|
349
|
+
// Create a Subject to hold the result of the CancelTasks method
|
|
350
|
+
const stopGenerationSubject$ = new Subject();
|
|
351
|
+
connection.on('CancelTasks', (res) => {
|
|
352
|
+
// When the generation is stopped before streaming any VISIBLE assistant message, this means that $progress, $attachment and $debug properties will be lost.
|
|
353
|
+
// However, the "ContextMessage" frames will be persisted in the chatHistory and the assistant may reference them in the next generation.
|
|
354
|
+
// This leads to the problem of referencing undisplayed attachments in the next generation.
|
|
355
|
+
// To solve this problem, we need to persist $progress, $attachment and $debug properties by adding a new assistant message with empty content and these properties.
|
|
356
|
+
// In the other hand, this leads to the problem of having many empty assistant messages in the chat history, if a stop generation happens multiple times in a row with no content generated yet.
|
|
357
|
+
// To solve this problem mentioned in the ticket ES-27024, we need to allow such operation ONLY if the last assistant message's content in the chat history is not empty.
|
|
358
|
+
const chatHistory = context.getChatHistory();
|
|
359
|
+
const isLastChatHistoryMessageAssistantContentEmpty = chatHistory?.length
|
|
360
|
+
&& chatHistory.at(-1)?.role === "assistant"
|
|
361
|
+
&& (chatHistory.at(-1)?.content === ""
|
|
362
|
+
||
|
|
363
|
+
chatHistory.at(-1)?.content?.find((msg) => msg.type === "text")?.text === "");
|
|
364
|
+
if (this._response && this._response.length === 1 && this._response[0].content === "" && !isLastChatHistoryMessageAssistantContentEmpty) {
|
|
365
|
+
const newChatHistory = chatHistory ? [...chatHistory] : [];
|
|
366
|
+
newChatHistory.push({ role: "assistant", content: "", additionalProperties: { display: true, messageId: guid(), $progress: this._progress, $attachment: this._attachments, $debug: this._debugMessages } });
|
|
367
|
+
context.setChatHistory(newChatHistory);
|
|
368
|
+
}
|
|
369
|
+
// Emit the result of the CancelTasks method
|
|
370
|
+
stopGenerationSubject$.next(!!res);
|
|
371
|
+
// Complete the subject
|
|
372
|
+
stopGenerationSubject$.complete();
|
|
373
|
+
// Complete stopping generation
|
|
374
|
+
context.setStoppingGenerationStatus(false);
|
|
375
|
+
});
|
|
376
|
+
// Invoke the CancelTasks method and handle errors
|
|
377
|
+
connection.invoke('CancelTasks')
|
|
378
|
+
.catch(error => {
|
|
379
|
+
console.error('Error invoking CancelTasks:', error);
|
|
380
|
+
stopGenerationSubject$.error(new Error(error));
|
|
381
|
+
context.setStoppingGenerationStatus(false);
|
|
382
|
+
return Promise.resolve();
|
|
383
|
+
});
|
|
384
|
+
return stopGenerationSubject$.asObservable();
|
|
385
|
+
}
|
|
386
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AssistantWsFramesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
387
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AssistantWsFramesService }); }
|
|
388
|
+
}
|
|
389
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AssistantWsFramesService, decorators: [{
|
|
390
|
+
type: Injectable
|
|
391
|
+
}] });
|
|
392
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXNzaXN0YW50LXdzLWZyYW1lcy5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvYXNzaXN0YW50L2NoYXQvc2VydmljZXMvYXNzaXN0YW50LXdzLWZyYW1lcy5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRW5ELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3RELE9BQU8sRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLFVBQVUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUM3RSxPQUFPLEVBQUUsR0FBRyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFMUYsT0FBTyxFQUFFLElBQUksRUFBUyxNQUFNLGlCQUFpQixDQUFDO0FBMkI5QyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUN4RCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQzs7QUF5QjlELE1BQU0sT0FBTyx3QkFBd0I7SUFEckM7UUFJVSxlQUFVLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ2hDLGNBQVMsR0FBRyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUNyQyxtQkFBYyxHQUFHLE1BQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUN4Qyx5QkFBb0IsR0FBRyxNQUFNLENBQUMsb0JBQW9CLENBQUMsQ0FBQztRQUVwRCxxQkFBZ0IsR0FBcUMsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUUvRCxlQUFVLEdB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QyxHQUFHLENBQUMsQ0FBQztZQUNuQyx1QkFBdUI7WUFDdkIsc0JBQXNCLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDbEMsK0JBQStCO1lBQy9CLE9BQU8sQ0FBQywyQkFBMkIsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM3QyxDQUFDLENBQUMsQ0FBQztRQUVILGtEQUFrRDtRQUNsRCxVQUFVLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQzthQUM3QixLQUFLLENBQUMsS0FBSyxDQUFDLEVBQUU7WUFDYixPQUFPLENBQUMsS0FBSyxDQUFDLDZCQUE2QixFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQ3BELHNCQUFzQixDQUFDLEtBQUssQ0FBQyxJQUFJLEtBQUssQ0FBQyxLQUFlLENBQUMsQ0FBQyxDQUFDO1lBQ3pELE9BQU8sQ0FBQywyQkFBMkIsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUMzQyxPQUFPLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUMzQixDQUFDLENBQUMsQ0FBQztRQUVMLE9BQU8sc0JBQXNCLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDL0MsQ0FBQzsrR0FuYVUsd0JBQXdCO21IQUF4Qix3QkFBd0I7OzRGQUF4Qix3QkFBd0I7a0JBRHBDLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlLCBpbmplY3QgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEh1YkNvbm5lY3Rpb24gfSBmcm9tICdAbWljcm9zb2Z0L3NpZ25hbHInO1xuaW1wb3J0IHsgVHJhbnNsb2NvU2VydmljZSB9IGZyb20gJ0Bqc3ZlcnNlL3RyYW5zbG9jbyc7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBTdWJqZWN0LCBmcm9tRXZlbnQsIG1lcmdlLCBvZiwgdGhyb3dFcnJvciB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgbWFwLCBtZXJnZU1hcCwgdGFrZVVudGlsLCB0YXAsIHRha2UsIHN3aXRjaE1hcCwgZmluYWxpemUgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbmltcG9ydCB7IGd1aWQsIFF1ZXJ5IH0gZnJvbSBcIkBzaW5lcXVhL2F0b21pY1wiO1xuXG5pbXBvcnQge1xuICBBY3Rpb25NZXNzYWdlLFxuICBBY3Rpb25SZXN1bHRFdmVudCxcbiAgQWN0aW9uU3RhcnRFdmVudCxcbiAgQWN0aW9uU3RvcEV2ZW50LFxuICBDaGF0Q29uZmlnLFxuICBDaGF0Q29udGV4dEF0dGFjaG1lbnQsXG4gIENoYXRNZXNzYWdlLFxuICBDaGF0UGF5bG9hZCxcbiAgQ2hhdFByb2dyZXNzLFxuICBDaGF0UmVzcG9uc2UsXG4gIENoYXRVc2FnZU1ldHJpY3MsXG4gIENvbnRleHRNZXNzYWdlRXZlbnQsXG4gIERlYnVnTWVzc2FnZSxcbiAgRGVidWdNZXNzYWdlRXZlbnQsXG4gIEVycm9yRXZlbnQsXG4gIEhpc3RvcnlFdmVudCxcbiAgTWVzc2FnZUhhbmRsZXIsXG4gIE1lc3NhZ2VFdmVudCxcbiAgUXVvdGEsXG4gIFF1b3RhRXZlbnQsXG4gIFNhdmVkQ2hhdFJlc3BvbnNlLFxuICBTdWdnZXN0ZWRBY3Rpb25zRXZlbnRcbn0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQgeyBBcHBTZXJ2aWNlIH0gZnJvbSAnLi9hcHAuc2VydmljZSc7XG5pbXBvcnQgeyBBc3Npc3RhbnRVdGlscyB9IGZyb20gJy4uL3V0aWxzL3V0aWxzLnNlcnZpY2UnO1xuaW1wb3J0IHsgTm90aWZpY2F0aW9uc1NlcnZpY2UgfSBmcm9tICcuL25vdGlmaWNhdGlvbi5zZXJ2aWNlJztcbmltcG9ydCB7IE1lc3NhZ2VDb250ZW50LCBUZXh0TWVzc2FnZUNvbnRlbnQgfSBmcm9tICcuLi90eXBlcy9tZXNzYWdlLWNvbnRlbnQudHlwZXMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEFzc2lzdGFudFdzRnJhbWVzQ29udGV4dCB7XG4gIGdldEFzc2lzdGFudENvbmZpZzogKCkgPT4gQ2hhdENvbmZpZyB8IHVuZGVmaW5lZDtcbiAgZ2V0Q2hhdEluc3RhbmNlSWQ6ICgpID0+IHN0cmluZztcbiAgZ2V0Q2hhdElkOiAoKSA9PiBzdHJpbmc7XG4gIGdldEh1YkNvbm5lY3Rpb246ICgpID0+IEh1YkNvbm5lY3Rpb24gfCB1bmRlZmluZWQ7XG4gIGdldENoYXRIaXN0b3J5OiAoKSA9PiBDaGF0TWVzc2FnZVtdIHwgdW5kZWZpbmVkO1xuXG4gIHNldFN0cmVhbWluZ1N0YXR1czogKGlzU3RyZWFtaW5nOiBib29sZWFuKSA9PiB2b2lkO1xuICBzZXRDaGF0SGlzdG9yeTogKGhpc3Rvcnk6IENoYXRNZXNzYWdlW10gfCB1bmRlZmluZWQpID0+IHZvaWQ7XG4gIHNldFN0b3BwaW5nR2VuZXJhdGlvblN0YXR1czogKGlzU3RvcHBpbmc6IGJvb2xlYW4pID0+IHZvaWQ7XG4gIHNldFNhdmVkQ2hhdHNFcnJvclN0YXR1czogKGhhc0Vycm9yOiBib29sZWFuKSA9PiB2b2lkO1xuXG4gIHVwZGF0ZVF1b3RhOiAocXVvdGE6IFF1b3RhLCBwcm9wYWdhdGVFcnJvcj86IGJvb2xlYW4pID0+IHZvaWQ7XG4gIHVwZGF0ZUNoYXRVc2FnZU1ldHJpY3M6IChtZXRyaWNzOiBDaGF0VXNhZ2VNZXRyaWNzKSA9PiB2b2lkO1xuICBnZW5lcmF0ZUF1ZGl0RXZlbnQ6ICh0eXBlOiBzdHJpbmcsIGRldGFpbHM6IFJlY29yZDxzdHJpbmcsIGFueT4sIGlkPzogc3RyaW5nKSA9PiBQcm9taXNlPHZvaWQ+O1xuICBhZGRTYXZlZENoYXQ6IChpZDogc3RyaW5nLCBtZXNzYWdlczogQ2hhdE1lc3NhZ2VbXSkgPT4gT2JzZXJ2YWJsZTxTYXZlZENoYXRSZXNwb25zZT47XG4gIHVwZGF0ZVNhdmVkQ2hhdDogKGlkOiBzdHJpbmcsIG5hbWU/OiBzdHJpbmcsIG1lc3NhZ2VzPzogQ2hhdE1lc3NhZ2VbXSkgPT4gT2JzZXJ2YWJsZTxTYXZlZENoYXRSZXNwb25zZT47XG4gIGxpc3RTYXZlZENoYXQ6ICgpID0+IHZvaWQ7XG4gIGlzRXhpc3RpbmdTYXZlZENoYXQ6IChpZDogc3RyaW5nKSA9PiBPYnNlcnZhYmxlPGJvb2xlYW4+O1xufVxuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgQXNzaXN0YW50V3NGcmFtZXNTZXJ2aWNlIHtcbiAgcHJpdmF0ZSBjb250ZXh0OiBBc3Npc3RhbnRXc0ZyYW1lc0NvbnRleHQgfCB1bmRlZmluZWQ7XG5cbiAgcHJpdmF0ZSBhcHBTZXJ2aWNlID0gaW5qZWN0KEFwcFNlcnZpY2UpO1xuICBwcml2YXRlIHRyYW5zbG9jbyA9IGluamVjdChUcmFuc2xvY29TZXJ2aWNlKTtcbiAgcHJpdmF0ZSBhc3Npc3RhbnRVdGlscyA9IGluamVjdChBc3Npc3RhbnRVdGlscyk7XG4gIHByaXZhdGUgbm90aWZpY2F0aW9uc1NlcnZpY2UgPSBpbmplY3QoTm90aWZpY2F0aW9uc1NlcnZpY2UpO1xuXG4gIHByaXZhdGUgX21lc3NhZ2VIYW5kbGVyczogTWFwPHN0cmluZywgTWVzc2FnZUhhbmRsZXI8YW55Pj4gPSBuZXcgTWFwKCk7XG4gIHByaXZhdGUgX3Jlc3BvbnNlOiBDaGF0TWVzc2FnZVtdO1xuICBwcml2YXRlIF9hY3Rpb25NYXAgPSBuZXcgTWFwPHN0cmluZywgQWN0aW9uTWVzc2FnZT4oKTtcbiAgcHJpdmF0ZSBfcHJvZ3Jlc3M6IENoYXRQcm9ncmVzc1tdIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuICBwcml2YXRlIF9leGVjdXRpb25UaW1lOiBzdHJpbmc7XG4gIHByaXZhdGUgX2V4ZWN1dGlvblRpbWVNaWxsaXNlY29uZHM/OiBudW1iZXI7XG4gIHByaXZhdGUgX2F0dGFjaG1lbnRzOiBDaGF0Q29udGV4dEF0dGFjaG1lbnRbXSA9IFtdO1xuICBwcml2YXRlIF9kZWJ1Z01lc3NhZ2VzOiBEZWJ1Z01lc3NhZ2VbXSA9IFtdO1xuXG4gIHB1YmxpYyBpbml0KGNvbnRleHQ6IEFzc2lzdGFudFdzRnJhbWVzQ29udGV4dCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmNvbnRleHQpIHtcbiAgICAgIGNvbnNvbGUud2FybignQXNzaXN0YW50V3NGcmFtZXNTZXJ2aWNlIGFscmVhZHkgaW5pdGlhbGl6ZWQuJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuY29udGV4dCA9IGNvbnRleHQ7XG4gIH1cblxuICBwcml2YXRlIGVuc3VyZUluaXRpYWxpemVkKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5jb250ZXh0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Fzc2lzdGFudFdzRnJhbWVzU2VydmljZSBub3QgaW5pdGlhbGl6ZWQuIENhbGwgaW5pdCgpIGZpcnN0LicpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBmZXRjaChtZXNzYWdlczogQ2hhdE1lc3NhZ2VbXSwgcXVlcnk6IFF1ZXJ5KTogT2JzZXJ2YWJsZTxDaGF0UmVzcG9uc2U+IHtcbiAgICB0aGlzLmVuc3VyZUluaXRpYWxpemVkKCk7XG4gICAgY29uc3QgY29udGV4dCA9IHRoaXMuY29udGV4dCE7XG4gICAgY29uc3QgYXNzaXN0YW50Q29uZmlnID0gY29udGV4dC5nZXRBc3Npc3RhbnRDb25maWcoKSE7XG5cbiAgICAgLy8gU3RhcnQgc3RyZWFtaW5nIGJ5IGludm9raW5nIHRoZSBDaGF0IG1ldGhvZFxuICAgIGNvbnRleHQuc2V0U3RyZWFtaW5nU3RhdHVzKHRydWUpO1xuXG4gICAgLy8gUHJlcGFyZSB0aGUgcGF5bG9hZCB0byBzZW5kIHRvIHRoZSBDaGF0IG1ldGhvZFxuICAgIGNvbnN0IGRhdGE6IENoYXRQYXlsb2FkID0ge1xuICAgICAgaGlzdG9yeTogbWVzc2FnZXMsXG4gICAgICBmdW5jdGlvbnM6IGFzc2lzdGFudENvbmZpZy5kZWZhdWx0VmFsdWVzLmZ1bmN0aW9ucz8uZmlsdGVyKGZ1bmMgPT4gZnVuYy5lbmFibGVkKS5tYXAoZnVuYyA9PiBmdW5jLm5hbWUpLFxuICAgICAgZGVidWc6IGFzc2lzdGFudENvbmZpZy5kZWZhdWx0VmFsdWVzLmRlYnVnLFxuICAgICAgc2VydmljZVNldHRpbmdzOiB7XG4gICAgICAgIHNlcnZpY2VfaWQ6IGFzc2lzdGFudENvbmZpZy5kZWZhdWx0VmFsdWVzLnNlcnZpY2VfaWQsXG4gICAgICAgIG1vZGVsX2lkOiBhc3Npc3RhbnRDb25maWcuZGVmYXVsdFZhbHVlcy5tb2RlbF9pZCxcbiAgICAgICAgdG9wX3A6IGFzc2lzdGFudENvbmZpZy5kZWZhdWx0VmFsdWVzLnRvcF9wLFxuICAgICAgICB0ZW1wZXJhdHVyZTogYXNzaXN0YW50Q29uZmlnLmRlZmF1bHRWYWx1ZXMudGVtcGVyYXR1cmUsXG4gICAgICAgIG1heF90b2tlbnM6IGFzc2lzdGFudENvbmZpZy5kZWZhdWx0VmFsdWVzLm1heF90b2tlbnMsXG4gICAgICAgIC4uLmFzc2lzdGFudENvbmZpZy5hZGRpdGlvbmFsU2VydmljZVNldHRpbmdzXG4gICAgICB9LFxuICAgICAgYXBwUXVlcnk6IHtcbiAgICAgICAgYXBwOiB0aGlzLmFwcFNlcnZpY2UuYXBwTmFtZSxcbiAgICAgICAgcXVlcnlcbiAgICAgIH0sXG4gICAgICBpbnN0YW5jZUlkOiBjb250ZXh0LmdldENoYXRJbnN0YW5jZUlkKCksXG4gICAgICBjaGF0SWQ6IGNvbnRleHQuZ2V0Q2hhdElkKCksXG4gICAgICBnZW5lcmljQ2hhdEVycm9yTWVzc2FnZTogYXNzaXN0YW50Q29uZmlnLmdsb2JhbFNldHRpbmdzLmdlbmVyaWNDaGF0RXJyb3JNZXNzYWdlID8gdGhpcy50cmFuc2xvY28udHJhbnNsYXRlKGFzc2lzdGFudENvbmZpZy5nbG9iYWxTZXR0aW5ncy5nZW5lcmljQ2hhdEVycm9yTWVzc2FnZSkgOiBcIlwiXG4gICAgfTtcblxuICAgIC8vIEluaXRpYWxpemUgdGhlIHJlc3BvbnNlIHdpdGggYW4gZW1wdHkgYXNzaXN0YW50IG1lc3NhZ2VcbiAgICAvLyBoZXJlIGRpc3BsYXk6IHRydWUgaXMgbmVlZGVkIGluIG9yZGVyIHRvIGJlIGFibGUgdG8gc2hvdyB0aGUgcHJvZ3Jlc3NcbiAgICAvLyBoZXJlIG1lc3NhZ2VJZCBpcyBuZWVkZWQgYnV0IGl0IGlzIHRlbXBvcmFyeSBhbmQgd2lsbCBiZSByZXBsYWNlZCBieSB0aGUgY29ycmVjdCBtZXNzYWdlSWQgZ2VuZXJhdGVkIGJ5IHRoZSBhc3Npc3RhbnQgd2hlbiB0aGUgbWVzc2FnZSBzdGFydHMgc3RyZWFtaW5nXG4gICAgdGhpcy5fcmVzcG9uc2UgPSBbeyByb2xlOiBcImFzc2lzdGFudFwiLCBjb250ZW50OiBcIlwiLCBhZGRpdGlvbmFsUHJvcGVydGllczogeyBkaXNwbGF5OiB0cnVlLCBtZXNzYWdlSWQ6IGd1aWQoKSB9IH1dO1xuXG4gICAgLy8gQ3JlYXRlIGEgU3ViamVjdCB0byBzaWduYWwgY29tcGxldGlvblxuICAgIGNvbnN0IGNvbXBsZXRpb24kID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICAgIC8vIENyZWF0ZSBvYnNlcnZhYmxlcyBmb3IgZWFjaCBub24tZ2xvYmFsIGhhbmRsZXIgaW4gdGhlIF9tZXNzYWdlSGFuZGxlcnMgbWFwIChkZWZhdWx0IGFuZCBldmVudHVhbCBjdXN0b20gb25lcykgb25jZSBpdCBpcyB0cmlnZ2VyZWQgYnkgdGhlIGh1YiBjb25uZWN0aW9uXG4gICAgY29uc3Qgb2JzZXJ2YWJsZXMgPSBBcnJheVxuICAgICAgLmZyb20odGhpcy5fbWVzc2FnZUhhbmRsZXJzLmVudHJpZXMoKSlcbiAgICAgIC5maWx0ZXIoKFtldmVudE5hbWUsIGV2ZW50SGFuZGxlcl0pID0+ICFldmVudEhhbmRsZXIuaXNHbG9iYWxIYW5kbGVyKVxuICAgICAgLm1hcCgoW2V2ZW50TmFtZSwgZXZlbnRIYW5kbGVyXSkgPT4gZnJvbUV2ZW50PGFueT4oY29udGV4dC5nZXRIdWJDb25uZWN0aW9uKCkhLCBldmVudE5hbWUpLnBpcGUoXG4gICAgICAgICAgbWVyZ2VNYXAoKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICAvLyBXcmFwIHRoZSBoYW5kbGVyIGluIGEgdHJ5LWNhdGNoIGJsb2NrIHRvIHByZXZlbnQgdGhlIGVudGlyZSBzdHJlYW0gZnJvbSBmYWlsaW5nIGlmIGFuIGVycm9yIG9jY3VycyBpbiBhIHNpbmdsZSBoYW5kbGVyXG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAvLyBFeGVjdXRlIHRoZSBoYW5kbGVyIGFuZCBlbWl0IHRoZSByZXN1bHRcbiAgICAgICAgICAgICAgLy8gTkI6IGhlcmUgd2UgY291bGQgdXNlIFtldmVudEhhbmRsZXIuaGFuZGxlcihldmVudCldIHdoaWNoIGJlaGluZCB0aGUgc2NlbmVzIG1lcmdlTWFwIGludGVycHJldHMgdGhpcyBhcnJheSBhcyBhbiBvYnNlcnZhYmxlIHNlcXVlbmNlIHdpdGggb25lIGl0ZW0sIHdoaWNoIGl0IHRoZW4gZW1pdHNcbiAgICAgICAgICAgICAgcmV0dXJuIG9mKGV2ZW50SGFuZGxlci5oYW5kbGVyKGV2ZW50KSk7XG4gICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBFcnJvciBpbiBldmVudCBoYW5kbGVyIGZvciAke2V2ZW50TmFtZX06YCwgZXJyb3IpO1xuICAgICAgICAgICAgICAvLyBVc2UgdGhyb3dFcnJvciB0byBwcm9wYWdhdGUgdGhlIGVycm9yIGRvd25zdHJlYW1cbiAgICAgICAgICAgICAgcmV0dXJuIHRocm93RXJyb3IoKCkgPT4gbmV3IEVycm9yKGBFcnJvciBpbiBldmVudCBoYW5kbGVyIGZvciAke2V2ZW50TmFtZX06ICR7ZXJyb3J9YCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pXG4gICAgICAgICkpO1xuXG4gICAgLy8gVGhlbiBtZXJnZSB0aGVtIGludG8gYSBzaW5nbGUgb2JzZXJ2YWJsZSBpbiBvcmRlciB0byBzaW11bGF0ZSB0aGUgc3RyZWFtaW5nIGJlaGF2aW9yXG4gICAgY29uc3QgY29tYmluZWQkID0gbWVyZ2UoLi4ub2JzZXJ2YWJsZXMpLnBpcGUoXG4gICAgICBtYXAoKCkgPT4ge1xuICAgICAgICAvLyBEZWZpbmUgJHByb2dyZXNzIGZyb20gdGhlIF9hY3Rpb25NYXBcbiAgICAgICAgY29uc3QgYWN0aW9ucyA9IEFycmF5LmZyb20odGhpcy5fYWN0aW9uTWFwLnZhbHVlcygpKTtcbiAgICAgICAgdGhpcy5fcHJvZ3Jlc3MgPSBhY3Rpb25zLmxlbmd0aCA+IDBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgPyBhY3Rpb25zLm1hcCgoYSkgPT4gKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGU6IGEuZGlzcGxheU5hbWUgPz8gXCJcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGVudDogYS5kaXNwbGF5VmFsdWUgPz8gXCJcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9uZTogYS5leGVjdXRpb25UaW1lICE9PSB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpbWU6IGEuZXhlY3V0aW9uVGltZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pKVxuICAgICAgICAgICAgICAgICAgICAgICAgICA6IHVuZGVmaW5lZDtcblxuICAgICAgICAvLyBBbHdheXMgdXBkYXRlIE9OTFkgdGhlIGZpcnN0IGFzc2lzdGFudCBtZXNzYWdlIG9mIHRoZSBfcmVzcG9uc2Ugd2l0aCB0aGUgbmV3ICRwcm9ncmVzcywgJGF0dGFjaG1lbnQgYW5kICRkZWJ1Z1xuICAgICAgICAvLyBBc3N1bWluZyB0aGF0IHRoZSBmaXJzdCBhc3Npc3RhbnQgbWVzc2FnZSBpcyBhbHdheXMgdmlzaWJsZSBzaW5jZSB0aGUgaHViIGRvZXMgbm90IHNlbmQgaGlkZGVuIG1lc3NhZ2VzIGJ5IGRlc2lnblxuICAgICAgICAvLyBTbyBldmVuIGlmIHRoZSBmaXJzdCBhc3Npc3RhbnQgbWVzc2FnZSBpcyBoaWRkZW4gKGRpc3BsYXk6IGZhbHNlKSwgdGhlIF9yZXNwb25zZVswXSB3aWxsIGFuZCBzaG91bGQgY29udGFpbiA6XG4gICAgICAgIC8vICAtICRwcm9ncmVzcywgJGF0dGFjaG1lbnQgYW5kICRkZWJ1Z1xuICAgICAgICAvLyAgLSB0aGUgY29udGVudCBvZiB0aGUgZmlyc3QgdmlzaWJsZSBhc3Npc3RhbnQgbWVzc2FnZSBpbiB0aGUgd29ya2Zsb3dcbiAgICAgICAgLy8gVGhpcyBpcyBtYW5kYXRvcnkgaW4gb3JkZXIgdG8gbWF0Y2ggdGhlIGJlaGF2aW9yIG9mIGNvbnNlY3V0aXZlIG1lc3NhZ2VzIGFuZCBtYWludGFpbiBjb25zaXN0ZW5jeSB3aXRoIHRoZSBjaGF0SGlzdG9yeVxuICAgICAgICBpZighIXRoaXMuX3Byb2dyZXNzIHx8IHRoaXMuX2F0dGFjaG1lbnRzLmxlbmd0aCA+IDAgfHwgdGhpcy5fZGVidWdNZXNzYWdlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgdGhpcy5fcmVzcG9uc2VbMF0uYWRkaXRpb25hbFByb3BlcnRpZXMuJHByb2dyZXNzID0gdGhpcy5fcHJvZ3Jlc3M7XG4gICAgICAgICAgdGhpcy5fcmVzcG9uc2VbMF0uYWRkaXRpb25hbFByb3BlcnRpZXMuJGF0dGFjaG1lbnQgPSB0aGlzLl9hdHRhY2htZW50cztcbiAgICAgICAgICB0aGlzLl9yZXNwb25zZVswXS5hZGRpdGlvbmFsUHJvcGVydGllcy4kZGVidWcgPSB0aGlzLl9kZWJ1Z01lc3NhZ2VzO1xuICAgICAgICB9XG4gICAgICAgIC8vIFJldHVybiB0aGUgcmVzdWx0XG4gICAgICAgIHJldHVybiB7IGhpc3Rvcnk6IFsuLi5tZXNzYWdlcywgLi4udGhpcy5fcmVzcG9uc2VdLCBleGVjdXRpb25UaW1lOiB0aGlzLl9leGVjdXRpb25UaW1lLCBleGVjdXRpb25UaW1lTWlsbGlzZWNvbmRzOiB0aGlzLl9leGVjdXRpb25UaW1lTWlsbGlzZWNvbmRzIH07XG4gICAgICB9KSxcbiAgICAgIC8vIENvbXBsZXRlIHRoZSBvYnNlcnZhYmxlIHdoZW4gY29tcGxldGlvbiQgZW1pdHNcbiAgICAgIHRha2VVbnRpbChjb21wbGV0aW9uJCksXG4gICAgKTtcblxuICAgIC8vIHJldHVybiBhIG5ldyBPYnNlcnZhYmxlIHRoYXQgZW1pdHMgdGhlIHJlc3VsdCBvZiB0aGUgY29tYmluZWQgc3RyZWFtIGFuZCBoYW5kbGVzIHRoZSBldmVudHVhbCBlcnJvcnMgb2YgdGhlIGludm9jYXRpb24gb2YgdGhlIENoYXQgbWV0aG9kXG4gICAgcmV0dXJuIG5ldyBPYnNlcnZhYmxlKG9ic2VydmVyID0+IHtcbiAgICAgIC8vIFN1YnNjcmliZSB0byBjb21iaW5lZCBzdHJlYW1cbiAgICAgIGNvbWJpbmVkJC5zdWJzY3JpYmUoe1xuICAgICAgICBuZXh0OiAodmFsdWUpID0+IG9ic2VydmVyLm5leHQodmFsdWUpLFxuICAgICAgICBlcnJvcjogKGVycikgPT4gb2JzZXJ2ZXIuZXJyb3IoZXJyKVxuICAgICAgfSk7XG5cbiAgICAgIC8vIEludm9rZSB0aGUgQ2hhdCBtZXRob2QgYW5kIGhhbmRsZSBlcnJvcnNcbiAgICAgIGNvbnRleHQuZ2V0SHViQ29ubmVjdGlvbigpIS5pbnZva2UoJ0NoYXQnLCBkYXRhKVxuICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgY29uc3QgY2hhdEhpc3RvcnkgPSBjb250ZXh0LmdldENoYXRIaXN0b3J5KCkhO1xuICAgICAgICAgIC8vIElmIGEgdmFsaWQgYXNzaXN0YW50IG1lc3NhZ2Ugd2l0aCAoZGlzcGxheTogdHJ1ZSkgd2FzIGZvdW5kLCB1cGRhdGUgaXRcbiAgICAgICAgICAvLyBhbmQgaXQgc2hvdWxkIGFsd2F5cyB0aGUgY2FzZVxuICAgICAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy5hc3Npc3RhbnRVdGlscy5maXJzdFZpc2libGVBc3Npc3RhbnRNZXNzYWdlSW5kZXgoY2hhdEhpc3RvcnkpO1xuICAgICAgICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgICAgICAgIGNoYXRIaXN0b3J5W2luZGV4XS5hZGRpdGlvbmFsUHJvcGVydGllcy4kcHJvZ3Jlc3MgPSB0aGlzLl9wcm9ncmVzcztcbiAgICAgICAgICAgIGNoYXRIaXN0b3J5W2luZGV4XS5hZGRpdGlvbmFsUHJvcGVydGllcy4kYXR0YWNobWVudCA9IHRoaXMuX2F0dGFjaG1lbnRzO1xuICAgICAgICAgICAgY2hhdEhpc3RvcnlbaW5kZXhdLmFkZGl0aW9uYWxQcm9wZXJ0aWVzLiRkZWJ1ZyA9IHRoaXMuX2RlYnVnTWVzc2FnZXM7XG4gICAgICAgICAgICBjb250ZXh0LnNldENoYXRIaXN0b3J5KGNoYXRIaXN0b3J5KTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBTYXZlL3VwZGF0ZSB0aGUgY2hhdCBpZiBzYXZlZENoYXQgZW5hYmxlZFxuICAgICAgICAgIGlmIChhc3Npc3RhbnRDb25maWcuc2F2ZWRDaGF0U2V0dGluZ3MuZW5hYmxlZCAmJiBjb250ZXh0LmdldENoYXRIaXN0b3J5KCkhLnNvbWUoKG1zZykgPT4gbXNnLmFkZGl0aW9uYWxQcm9wZXJ0aWVzPy5pc1VzZXJJbnB1dCA9PT0gdHJ1ZSkpIHtcbiAgICAgICAgICAgIGNvbnRleHQuaXNFeGlzdGluZ1NhdmVkQ2hhdChjb250ZXh0LmdldENoYXRJZCgpKS5waXBlKFxuICAgICAgICAgICAgICB0YWtlKDEpLFxuICAgICAgICAgICAgICBzd2l0Y2hNYXAoKGV4aXN0cykgPT5cbiAgICAgICAgICAgICAgICBleGlzdHNcbiAgICAgICAgICAgICAgICAgID8gY29udGV4dC51cGRhdGVTYXZlZENoYXQoY29udGV4dC5nZXRDaGF0SWQoKSwgdW5kZWZpbmVkLCBjb250ZXh0LmdldENoYXRIaXN0b3J5KCkhKVxuICAgICAgICAgICAgICAgICAgOiBjb250ZXh0LmFkZFNhdmVkQ2hhdChjb250ZXh0LmdldENoYXRJZCgpLCBjb250ZXh0LmdldENoYXRIaXN0b3J5KCkhKS5waXBlKFxuICAgICAgICAgICAgICAgICAgICAgIHRhcCgoKSA9PiBjb250ZXh0Lmxpc3RTYXZlZENoYXQoKSlcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICBmaW5hbGl6ZSgoKSA9PiBjb250ZXh0LnNldFN0cmVhbWluZ1N0YXR1cyhmYWxzZSkpXG4gICAgICAgICAgICApLnN1YnNjcmliZSh7XG4gICAgICAgICAgICAgIG5leHQ6ICgpID0+IHt9LFxuICAgICAgICAgICAgICBlcnJvcjogKGVycm9yKSA9PiBvYnNlcnZlci5lcnJvcihlcnJvciksXG4gICAgICAgICAgICAgIGNvbXBsZXRlOiAoKSA9PiBvYnNlcnZlci5jb21wbGV0ZSgpXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29udGV4dC5zZXRTdHJlYW1pbmdTdGF0dXMoZmFsc2UpO1xuICAgICAgICAgICAgb2JzZXJ2ZXIuY29tcGxldGUoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgaW52b2tpbmcgQ2hhdDonLCBlcnJvcik7XG4gICAgICAgICAgY29udGV4dC5zZXRTdHJlYW1pbmdTdGF0dXMoZmFsc2UpO1xuICAgICAgICAgIC8vIEVtaXQgdGhlIGVycm9yIHRvIHRoZSBuZXdseSBjcmVhdGVkIG9ic2VydmFibGVcbiAgICAgICAgICBvYnNlcnZlci5lcnJvcihlcnJvcik7XG4gICAgICAgICAgLy8gUmV0dXJuIGEgcmVzb2x2ZWQgcHJvbWlzZSB0byBoYW5kbGUgdGhlIGVycm9yIGFuZCBwcmV2ZW50IHVuaGFuZGxlZCBwcm9taXNlIHJlamVjdGlvblxuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgfSlcbiAgICAgICAgLmZpbmFsbHkoKCkgPT4ge1xuICAgICAgICAgIC8vIFRoaXMgYmxvY2sgY29uY2VybnMgT05MWSB0aGUgY29tcGxldGlvbiBvZiB0aGUgXCJDaGF0XCIgbWV0aG9kIGludm9jYXRpb24uXG4gICAgICAgICAgLy8gVGhpcyBtZWFucyB0aGUgY29tcGxldGlvbiBvZiB0aGUgY29tYmluZWQkIHN0cmVhbS5cbiAgICAgICAgICAvLyBJdCBkb2VzIG5vdCB0YWtlIGludG8gYWNjb3VudCB0aGUgY29tcGxldGlvbiBvZiB0aGUgZW50aXJlIGZldGNoIG1ldGhvZCAodGhlIG9ic2VydmFibGUgcmV0dXJuZWQgYnkgZmV0Y2gpIGFuZCB3aGljaCBkZXBlbmRzIG9uIHRoZSBjb21wbGV0aW9uIG9mIHRoZSBzYXZlIGNoYXQgYWN0aW9uIGlmIGVuYWJsZWRcbiAgICAgICAgICB0aGlzLl9yZXNwb25zZSA9IFtdOyAvLyBDbGVhciB0aGUgX3Jlc3BvbnNlXG4gICAgICAgICAgdGhpcy5fYWN0aW9uTWFwLmNsZWFyKCk7IC8vIENsZWFyIHRoZSBfYWN0aW9uTWFwXG4gICAgICAgICAgdGhpcy5fcHJvZ3Jlc3MgPSB1bmRlZmluZWQ7IC8vIENsZWFyIHRoZSBfcHJvZ3Jlc3NcbiAgICAgICAgICB0aGlzLl9hdHRhY2htZW50cyA9IFtdOyAvLyBDbGVhciB0aGUgX2F0dGFjaG1lbnRzXG4gICAgICAgICAgdGhpcy5fZGVidWdNZXNzYWdlcyA9IFtdOyAvLyBDbGVhciB0aGUgX2RlYnVnTWVzc2FnZXNcbiAgICAgICAgICB0aGlzLl9leGVjdXRpb25UaW1lID0gXCJcIjsgLy8gQ2xlYXIgdGhlIF9leGVjdXRpb25UaW1lXG4gICAgICAgICAgdGhpcy5fZXhlY3V0aW9uVGltZU1pbGxpc2Vjb25kcyA9IHVuZGVmaW5lZDsgLy8gQ2xlYXIgdGhlIF9leGVjdXRpb25UaW1lTWlsbGlzZWNvbmRzXG4gICAgICAgICAgY29tcGxldGlvbiQubmV4dCgpOyAvLyBFbWl0IGEgc2lnbmFsIHRvIGNvbXBsZXRlIHRoZSBvYnNlcnZhYmxlc1xuICAgICAgICAgIGNvbXBsZXRpb24kLmNvbXBsZXRlKCk7IC8vIENvbXBsZXRlIHRoZSBzdWJqZWN0XG4gICAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIGluaXRNZXNzYWdlSGFuZGxlcnMoKTogdm9pZCB7XG4gICAgdGhpcy5lbnN1cmVJbml0aWFsaXplZCgpO1xuICAgIGNvbnN0IGNvbnRleHQgPSB0aGlzLmNvbnRleHQhO1xuXG4gICAgdGhpcy5hZGRNZXNzYWdlSGFuZGxlcihcIkVycm9yXCIsIHtcbiAgICAgICAgaGFuZGxlcjogKGVycm9yOiBFcnJvckV2ZW50KSA9PiB7XG4gICAgICAgICAgaWYgKGVycm9yLmluZGV4T2YoJ1NhdmVkQ2hhdExpc3QnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIGNvbnRleHQuc2V0U2F2ZWRDaGF0c0Vycm9yU3RhdHVzKHRydWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICB0aGlzLm5vdGlmaWNhdGlvbnNTZXJ2aWNlLmVycm9yKGVycm9yKTtcbiAgICAgICAgfSxcbiAgICAgICAgaXNHbG9iYWxIYW5kbGVyOiB0cnVlXG4gICAgICB9XG4gICAgKTtcbiAgICB0aGlzLmFkZE1lc3NhZ2VIYW5kbGVyKFwiUXVvdGFcIiwge1xuICAgICAgICBoYW5kbGVyOiAobWVzc2FnZTogUXVvdGFFdmVudCkgPT4ge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb250ZXh0LnVwZGF0ZVF1b3RhKG1lc3NhZ2UucXVvdGEpO1xuICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGlzR2xvYmFsSGFuZGxlcjogdHJ1ZVxuICAgICAgfVxuICAgICk7XG4gICAgdGhpcy5hZGRNZXNzYWdlSGFuZGxlcihcIkRlYnVnXCIsIHsgaGFuZGxlcjogKCkgPT4ge30sIGlzR2xvYmFsSGFuZGxlcjogdHJ1ZSB9KTtcbiAgICB0aGlzLmFkZE1lc3NhZ2VIYW5kbGVyKFwiQWN0aW9uU3RhcnRcIiwge1xuICAgICAgaGFuZGxlcjogKGFjdGlvbjogQWN0aW9uU3RhcnRFdmVudCkgPT4gdGhpcy5fYWN0aW9uTWFwLnNldChhY3Rpb24uZ3VpZCwgYWN0aW9uKSxcbiAgICAgIGlzR2xvYmFsSGFuZGxlcjogZmFsc2VcbiAgICB9KTtcbiAgICB0aGlzLmFkZE1lc3NhZ2VIYW5kbGVyKFwiQWN0aW9uUmVzdWx0XCIsIHtcbiAgICAgIGhhbmRsZXI6IChhY3Rpb246IEFjdGlvblJlc3VsdEV2ZW50KSA9PiB0aGlzLl9hY3Rpb25NYXAuc2V0KGFjdGlvbi5ndWlkLCB7IC4uLnRoaXMuX2FjdGlvbk1hcC5nZXQoYWN0aW9uLmd1aWQpLCAuLi5hY3Rpb24gfSksXG4gICAgICBpc0dsb2JhbEhhbmRsZXI6IGZhbHNlXG4gICAgfSk7XG4gICAgdGhpcy5hZGRNZXNzYWdlSGFuZGxlcihcIkFjdGlvblN0b3BcIiwge1xuICAgICAgaGFuZGxlcjogKGFjdGlvbjogQWN0aW9uU3RvcEV2ZW50KSA9PiB0aGlzLl9hY3Rpb25NYXAuc2V0KGFjdGlvbi5ndWlkLCB7IC4uLnRoaXMuX2FjdGlvbk1hcC5nZXQoYWN0aW9uLmd1aWQpLCAuLi5hY3Rpb24gfSksXG4gICAgICBpc0dsb2JhbEhhbmRsZXI6IGZhbHNlXG4gICAgfSk7XG4gICAgdGhpcy5hZGRNZXNzYWdlSGFuZGxlcihcIkNvbnRleHRNZXNzYWdlXCIsIHtcbiAgICAgIGhhbmRsZXI6IChtZXNzYWdlOiBDb250ZXh0TWVzc2FnZUV2ZW50KSA9PiB7IHRoaXMuX2F0dGFjaG1lbnRzLnB1c2gobWVzc2FnZS5hZGRpdGlvbmFsUHJvcGVydGllcyk7IH0sXG4gICAgICBpc0dsb2JhbEhhbmRsZXI6IGZhbHNlXG4gICAgfSk7XG4gICAgdGhpcy5hZGRNZXNzYWdlSGFuZGxlcihcIk1lc3NhZ2VcIiwge1xuICAgICAgaGFuZGxlcjogKG1lc3NhZ2U6IE1lc3NhZ2VFdmVudCkgPT4ge1xuICAgICAgICB0aGlzLl9yZXNwb25zZS5hdCgtMSkhLmNvbnRlbnQgKz0gbWVzc2FnZS5kZWx0YSA/PyBcIlwiO1xuICAgICAgICB0aGlzLl9yZXNwb25zZS5hdCgtMSkhLmFkZGl0aW9uYWxQcm9wZXJ0aWVzLm1lc3NhZ2VJZCA9IG1lc3NhZ2UubWVzc2FnZUlkO1xuICAgICAgfSxcbiAgICAgIGlzR2xvYmFsSGFuZGxlcjogZmFsc2VcbiAgICB9KTtcbiAgICB0aGlzLmFkZE1lc3NhZ2VIYW5kbGVyKFwiSGlzdG9yeVwiLCB7XG4gICAgICAgIGhhbmRsZXI6IChoaXN0b3J5OiBIaXN0b3J5RXZlbnQpID0+IHtcbiAgICAgICAgICAvLyBUaGUgQ2hhdEhpc3RvcnkgaXMgdXBkYXRlZDogaXQgaXMgdGhlIGN1cnJlbnQgY29weSBjb25jYXRlbmF0ZWQgd2l0aCB0aGUgbmV3IGl0ZW1zIE9OTFkgKGl0IGNhbiBoYXZlIG11bHRpcGxlIG1lc3NhZ2VzOiB0aGUgY29udGV4dCBtZXNzYWdlcyArIHRoZSByZXNwb25zZSBtZXNzYWdlKVxuICAgICAgICAgIC8vIFRoaXMgaXMgbWFuZGF0b3J5IHRvIG5vdCBsb3NlIHRoZSBwcmV2aW91cyB1cGRhdGVzIG9mIHRoZSBjaGF0SGlzdG9yeSB3aGVuIHRoZSBhc3Npc3RhbnQgaXMgc3RyZWFtaW5nIG11bHRpcGxlIG1lc3NhZ2Ugc3RlcHNcbiAgICAgICAgICBjb25zdCBjdXJyZW50Q2hhdEhpc3RvcnkgPSAoY29udGV4dC5nZXRDaGF0SGlzdG9yeSgpIHx8IFtdKSBhcyBDaGF0TWVzc2FnZVtdO1xuICAgICAgICAgIGNvbnN0IG5ld0hpc3RvcnkgPSBbLi4uY3VycmVudENoYXRIaXN0b3J5LCAuLi4oaGlzdG9yeS5oaXN0b3J5LnNsaWNlKGN1cnJlbnRDaGF0SGlzdG9yeS5sZW5ndGgpKV0gYXMgQ2hhdE1lc3NhZ2VbXTtcbiAgICAgICAgICBjb250ZXh0LnNldENoYXRIaXN0b3J5KG5ld0hpc3RvcnkpO1xuXG4gICAgICAgICAgLy8gRW1pdCB0aGUgdXBkYXRlZCBjaGF0IHVzYWdlIG1ldHJpY3NcbiAgICAgICAgICBjb25zdCBsYXN0TWVzc2FnZSA9IG5ld0hpc3RvcnkuYXQoLTEpO1xuICAgICAgICAgIGlmIChsYXN0TWVzc2FnZT8uYWRkaXRpb25hbFByb3BlcnRpZXMudXNhZ2VNZXRyaWNzKSB7XG4gICAgICAgICAgICBjb250ZXh0LnVwZGF0ZUNoYXRVc2FnZU1ldHJpY3MobGFzdE1lc3NhZ2UuYWRkaXRpb25hbFByb3BlcnRpZXMudXNhZ2VNZXRyaWNzKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5fZXhlY3V0aW9uVGltZSA9IGhpc3RvcnkuZXhlY3V0aW9uVGltZTtcbiAgICAgICAgICB0aGlzLl9leGVjdXRpb25UaW1lTWlsbGlzZWNvbmRzID0gaGlzdG9yeS5leGVjdXRpb25UaW1lTWlsbGlzZWNvbmRzO1xuICAgICAgICB9LFxuICAgICAgICBpc0dsb2JhbEhhbmRsZXI6IGZhbHNlXG4gICAgICB9XG4gICAgKTtcbiAgICB0aGlzLmFkZE1lc3NhZ2VIYW5kbGVyKFwiU3VnZ2VzdGVkQWN0aW9uc1wiLCB7XG4gICAgICAgIGhhbmRsZXI6IChtZXNzYWdlOiBTdWdnZXN0ZWRBY3Rpb25zRXZlbnQpID0+IHtcbiAgICAgICAgICAvLyBTaW5jZSBhZnRlciB0aGUgXCJIaXN0b3J5XCIgYW5kIFwiTWVzc2FnZUJyZWFrXCIgdGhhdCB0aGlzIGV2ZW50IGlzIGNhdWdodCxcbiAgICAgICAgICAvLyAkc3VnZ2VzdGVkQWN0aW9uIG5lZWRzIHRvIGJlIHVwZGF0ZWQgZGlyZWN0bHkgdG8gdGhlIGxhc3QgdmlzaWJsZSBcImFzc2lzdGFudFwiIG1lc3NhZ2UgaW4gdGhlIF9yZXNwb25zZSBhbmQgdGhlIGNoYXRIaXN0b3J5XG4gICAgICAgICAgdGhpcy5fcmVzcG9uc2UuYXQoLTEpIS5hZGRpdGlvbmFsUHJvcGVydGllcy4kc3VnZ2VzdGVkQWN0aW9uID0gKHRoaXMuX3Jlc3BvbnNlLmF0KC0xKSEuYWRkaXRpb25hbFByb3BlcnRpZXMuJHN1Z2dlc3RlZEFjdGlvbiB8fCBbXSkuY29uY2F0KG1lc3NhZ2Uuc3VnZ2VzdGVkQWN0aW9ucyk7XG4gICAgICAgICAgY29uc3QgY2hhdEhpc3RvcnkgPSBjb250ZXh0LmdldENoYXRIaXN0b3J5KCkhO1xuICAgICAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy5hc3Npc3RhbnRVdGlscy5sYXN0VmlzaWJsZUFzc2lzdGFudE1lc3NhZ2VJbmRleChjaGF0SGlzdG9yeSk7XG4gICAgICAgICAgaWYgKGluZGV4ICE9PSAtMSkge1xuICAgICAgICAgICAgY2hhdEhpc3RvcnlbaW5kZXhdLmFkZGl0aW9uYWxQcm9wZXJ0aWVzLiRzdWdnZXN0ZWRBY3Rpb24gPSAoY2hhdEhpc3RvcnlbaW5kZXhdLmFkZGl0aW9uYWxQcm9wZXJ0aWVzLiRzdWdnZXN0ZWRBY3Rpb24gfHwgW10pLmNvbmNhdChtZXNzYWdlLnN1Z2dlc3RlZEFjdGlvbnMpO1xuICAgICAgICAgICAgY29udGV4dC5zZXRDaGF0SGlzdG9yeShjaGF0SGlzdG9yeSk7XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBpc0dsb2JhbEhhbmRsZXI6IGZhbHNlXG4gICAgICB9XG4gICAgKTtcbiAgICB0aGlzLmFkZE1lc3NhZ2VIYW5kbGVyKFwiRGVidWdEaXNwbGF5XCIsIHtcbiAgICAgIGhhbmRsZXI6IChtZXNzYWdlOiBEZWJ1Z01lc3NhZ2VFdmVudCkgPT4gdGhpcy5fZGVidWdNZXNzYWdlcyA9IHRoaXMuX2RlYnVnTWVzc2FnZXMuY29uY2F0KG1lc3NhZ2UpLFxuICAgICAgaXNHbG9iYWxIYW5kbGVyOiBmYWxzZVxuICAgIH0pO1xuICAgIHRoaXMuYWRkTWVzc2FnZUhhbmRsZXIoXCJNZXNzYWdlQnJlYWtcIiwge1xuICAgICAgICBoYW5kbGVyOiAoKSA9PiB7XG4gICAgICAgICAgLy8gU3lzdGVtYXRpY2FsbHkgaGFwcGVucyByaWdodCBhZnRlciB0aGUgXCJIaXN0b3J5XCIgZXZlbnRcbiAgICAgICAgICAvLyBUaGlzIGlzIHRoZSBtb21lbnQgd2hlbiB0aGUgYXNzaXN0YW50IG1lc3NhZ2UgaXMgZnVsbHkgc3RyZWFtZWRcbiAgICAgICAgICBjb25zdCBhc3Npc3RhbnRDb25maWcgPSBjb250ZXh0LmdldEFzc2lzdGFudENvbmZpZygpO1xuICAgICAgICAgIGNvbnN0IGNoYXRIaXN0b3J5ID0gY29udGV4dC5nZXRDaGF0SGlzdG9yeSgpO1xuICAgICAgICAgIGlmICghYXNzaXN0YW50Q29uZmlnIHx8ICFjaGF0SGlzdG9yeSB8fCAhY2hhdEhpc3RvcnkubGVuZ3RoKSByZXR1cm47XG5cbiAgICAgICAgICBjb25zdCBsYXN0Q2hhdE1lc3NhZ2UgPSBjaGF0SGlzdG9yeS5hdCgtMSkhO1xuXG4gICAgICAgICAgY29uc3QgZGV0YWlscyA9IHtcbiAgICAgICAgICAgICdkdXJhdGlvbic6IHRoaXMuX2V4ZWN1dGlvblRpbWVNaWxsaXNlY29uZHMgIT09IHVuZGVmaW5lZCA/IHRoaXMuX2V4ZWN1dGlvblRpbWVNaWxsaXNlY29uZHMgOiB0aGlzLl9leGVjdXRpb25UaW1lLFxuICAgICAgICAgICAgJ3JvbGUnOiBsYXN0Q2hhdE1lc3NhZ2Uucm9sZSxcbiAgICAgICAgICAgICdyYW5rJzogY2hhdEhpc3RvcnkubGVuZ3RoLFxuICAgICAgICAgICAgJ21lc3NhZ2UtaWQnOiBsYXN0Q2hhdE1lc3NhZ2UuYWRkaXRpb25hbFByb3BlcnRpZXMubWVzc2FnZUlkLFxuICAgICAgICAgICAgJ2dlbmVyYXRpb24tdG9rZW5jb3VudCc6IGxhc3RDaGF0TWVzc2FnZS5hZGRpdGlvbmFsUHJvcGVydGllcy51c2FnZU1ldHJpY3M/LmNvbXBsZXRpb25Ub2tlbkNvdW50LFxuICAgICAgICAgICAgJ3Byb21wdC10b2tlbmNvdW50JzogbGFzdENoYXRNZXNzYWdlLmFkZGl0aW9uYWxQcm9wZXJ0aWVzLnVzYWdlTWV0cmljcz8ucHJvbXB0VG9rZW5Db3VudCxcbiAgICAgICAgICAgICdhdHRhY2htZW50cyc6IEpTT04uc3RyaW5naWZ5KHRoaXMuX2F0dGFjaG1lbnRzLm1hcCgoeyByZWNvcmRJZCwgY29udGV4dElkLCBwYXJ0cywgdHlwZSB9KSA9PiAoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY29yZElkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRleHRJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXJ0czogcGFydHMubWFwKCh7IHBhcnRJZCwgdGV4dCB9KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFhc3Npc3RhbnRDb25maWcuYXVkaXRTZXR0aW5ncz8ubG9nQ29udGVudCkgcmV0dXJuIHsgcGFydElkLCB0ZXh0IH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4geyBwYXJ0SWQgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlXG4gICAgICAgICAgICAgICAgICAgICAgICAgIH0pKSlcbiAgICAgICAgICB9O1xuICAgICAgICAgIGlmICghIWFzc2lzdGFudENvbmZpZy5hdWRpdFNldHRpbmdzPy5sb2dDb250ZW50KSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGxhc3RDaGF0TWVzc2FnZS5jb250ZW50ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAoZGV0YWlscyBhcyBhbnkpWyd0ZXh0J10gPSBsYXN0Q2hhdE1lc3NhZ2UuY29udGVudDtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShsYXN0Q2hhdE1lc3NhZ2UuY29udGVudCkpIHtcbiAgICAgICAgICAgICAgKGRldGFpbHMgYXMgYW55KVsndGV4dCddID0gKGxhc3RDaGF0TWVzc2FnZS5jb250ZW50LmZpbmQoKG1zZykgPT4gbXNnLnR5cGUgPT09IFwidGV4dFwiKSBhcyBUZXh0TWVzc2FnZUNvbnRlbnQpLnRleHRcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgY29udGV4dC5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ2FzdC1tZXNzYWdlLm1lc3NhZ2UnLCBkZXRhaWxzKTtcbiAgICAgICAgICAvLyBQdXNoIGEgbmV3IGFzc2lzdGFudCBtZXNzYWdlIHRvIHRoZSBfcmVzcG9uc2UgYXJyYXkgT05MWSBpZiB0aGUgY29udGVudCBvZiB0aGUgbGFzdCBtZXNzYWdlIGlzIG5vdCBlbXB0eVxuICAgICAgICAgIGlmICh0aGlzLl9yZXNwb25zZS5hdCgtMSkhLmNvbnRlbnQgIT09IFwiXCIpIHtcbiAgICAgICAgICAgIHRoaXMuX3Jlc3BvbnNlLnB1c2goe3JvbGU6IFwiYXNzaXN0YW50XCIsIGNvbnRlbnQ6IFwiXCIsIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiB7ZGlzcGxheTogdHJ1ZSwgbWVzc2FnZUlkOiBndWlkKCl9fSk7XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBpc0dsb2JhbEhhbmRsZXI6IGZhbHNlXG4gICAgICB9XG4gICAgKTtcbiAgfVxuXG4gIHB1YmxpYyBvdmVycmlkZU1lc3NhZ2VIYW5kbGVyczxUPihfbWVzc2FnZUhhbmRsZXJzOiBNYXA8c3RyaW5nLCBNZXNzYWdlSGFuZGxlcjxUPj4pOiB2b2lkIHtcbiAgICB0aGlzLmVuc3VyZUluaXRpYWxpemVkKCk7XG4gICAgLy8gQ2xlYXIgdGhlIGFscmVhZHkgcmVnaXN0ZXJlZCBnbG9iYWwgY2hhdCBoYW5kbGVycyBiZWZvcmUgbWVyZ2luZyB0aGUgbmV3IG9uZXNcbiAgICB0aGlzLl9tZXNzYWdlSGFuZGxlcnMuZm9yRWFjaCgoZXZlbnRIYW5kbGVyLCBldmVudE5hbWUpID0+IHtcbiAgICAgIGlmKGV2ZW50SGFuZGxlci5pc0dsb2JhbEhhbmRsZXIpIHtcbiAgICAgICAgdGhpcy51bnN1YnNjcmliZU1lc3NhZ2VIYW5kbGVyKGV2ZW50TmFtZSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgLy8gTWVyZ2UgdGhlIG5ldyBldmVudCBoYW5kbGVycyB3aXRoIHRoZSBleGlzdGluZyBvbmVzXG4gICAgdGhpcy5fbWVzc2FnZUhhbmRsZXJzID0gbmV3IE1hcChbLi4udGhpcy5fbWVzc2FnZUhhbmRsZXJzLCAuLi5fbWVzc2FnZUhhbmRsZXJzXSk7XG4gICAgLy8gUmVnaXN0ZXIgdGhlIGdsb2JhbCBoYW5kbGVycyBhbW9uZyB0aGUgbWVyZ2VkIG1hcFxuICAgIHRoaXMuX21lc3NhZ2VIYW5kbGVycy5mb3JFYWNoKChldmVudEhhbmRsZXIsIGV2ZW50TmFtZSkgPT4ge1xuICAgICAgaWYoZXZlbnRIYW5kbGVyLmlzR2xvYmFsSGFuZGxlcikge1xuICAgICAgICB0aGlzLnJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIoZXZlbnROYW1lLCBldmVudEhhbmRsZXIpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIGFkZE1lc3NhZ2VIYW5kbGVyPFQ+KGV2ZW50TmFtZTogc3RyaW5nLCBldmVudEhhbmRsZXI6IE1lc3NhZ2VIYW5kbGVyPFQ+KTogdm9pZCB7XG4gICAgdGhpcy5lbnN1cmVJbml0aWFsaXplZCgpO1xuICAgIHRoaXMuX21lc3NhZ2VIYW5kbGVycy5zZXQoZXZlbnROYW1lLCBldmVudEhhbmRsZXIpO1xuICAgIGlmKGV2ZW50SGFuZGxlci5pc0dsb2JhbEhhbmRsZXIpIHtcbiAgICAgIHRoaXMucmVnaXN0ZXJNZXNzYWdlSGFuZGxlcihldmVudE5hbWUsIGV2ZW50SGFuZGxlcik7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIHJlZ2lzdGVyTWVzc2FnZUhhbmRsZXI8VD4oZXZlbnROYW1lOiBzdHJpbmcsIGV2ZW50SGFuZGxlcjogTWVzc2FnZUhhbmRsZXI8VD4pOiB2b2lkIHtcbiAgICB0aGlzLmVuc3VyZUluaXRpYWxpemVkKCk7XG4gICAgY29uc3QgY29ubmVjdGlvbiA9IHRoaXMuY29udGV4dCEuZ2V0SHViQ29ubmVjdGlvbigpO1xuICAgIGlmICghY29ubmVjdGlvbikge1xuICAgICAgY29uc29sZS5sb2coXCJObyBjb25uZWN0aW9uIGZvdW5kIHRvIHJlZ2lzdGVyIHRoZSBsaXN0ZW5lclwiICsgZXZlbnROYW1lKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29ubmVjdGlvbi5vbihldmVudE5hbWUsIChkYXRhOiBUKSA9PiB7XG4gICAgICBldmVudEhhbmRsZXIuaGFuZGxlcihkYXRhKTtcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyByZW1vdmVNZXNzYWdlSGFuZGxlcihldmVudE5hbWU6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuZW5zdXJlSW5pdGlhbGl6ZWQoKTtcbiAgICB0aGlzLl9tZXNzYWdlSGFuZGxlcnMuZGVsZXRlKGV2ZW50TmFtZSk7XG4gICAgdGhpcy51bnN1YnNjcmliZU1lc3NhZ2VIYW5kbGVyKGV2ZW50TmFtZSk7XG4gIH1cblxuICBwdWJsaWMgdW5zdWJzY3JpYmVNZXNzYWdlSGFuZGxlcihldmVudE5hbWU6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuZW5zdXJlSW5pdGlhbGl6ZWQoKTtcbiAgICBjb25zdCBjb25uZWN0aW9uID0gdGhpcy5jb250ZXh0IS5nZXRIdWJDb25uZWN0aW9uKCk7XG4gICAgY29ubmVjdGlvbj8ub2ZmKGV2ZW50TmFtZSk7XG4gIH1cblxuICBwdWJsaWMgc3RvcEdlbmVyYXRpb24oKTogT2JzZXJ2YWJsZTxib29sZWFuPiB7XG4gICAgdGhpcy5lbnN1cmVJbml0aWFsaXplZCgpO1xuICAgIGNvbnN0IGNvbnRleHQgPSB0aGlzLmNvbnRleHQhO1xuICAgIGNvbnN0IGNvbm5lY3Rpb24gPSBjb250ZXh0LmdldEh1YkNvbm5lY3Rpb24oKSE7XG5cbiAgICAgLy8gU3RhcnQgc3RvcHBpbmcgZ2VuZXJhdGlvbiBieSBpbnZva2luZyB0aGUgQ2FuY2VsVGFza3MgbWV0aG9kXG4gICAgY29udGV4dC5zZXRTdG9wcGluZ0dlbmVyYXRpb25TdGF0dXModHJ1ZSk7XG4gICAgLy8gQ3JlYXRlIGEgU3ViamVjdCB0byBob2xkIHRoZSByZXN1bHQgb2YgdGhlIENhbmNlbFRhc2tzIG1ldGhvZFxuICAgIGNvbnN0IHN0b3BHZW5lcmF0aW9uU3ViamVjdCQgPSBuZXcgU3ViamVjdDxib29sZWFuPigpO1xuXG4gICAgY29ubmVjdGlvbi5vbignQ2FuY2VsVGFza3MnLCAocmVzKSA9PiB7XG4gICAgICAvLyBXaGVuIHRoZSBnZW5lcmF0aW9uIGlzIHN0b3BwZWQgYmVmb3JlIHN0cmVhbWluZyBhbnkgVklTSUJMRSBhc3Npc3RhbnQgbWVzc2FnZSwgdGhpcyBtZWFucyB0aGF0ICRwcm9ncmVzcywgJGF0dGFjaG1lbnQgYW5kICRkZWJ1ZyBwcm9wZXJ0aWVzIHdpbGwgYmUgbG9zdC5cbiAgICAgIC8vIEhvd2V2ZXIsIHRoZSBcIkNvbnRleHRNZXNzYWdlXCIgZnJhbWVzIHdpbGwgYmUgcGVyc2lzdGVkIGluIHRoZSBjaGF0SGlzdG9yeSBhbmQgdGhlIGFzc2lzdGFudCBtYXkgcmVmZXJlbmNlIHRoZW0gaW4gdGhlIG5leHQgZ2VuZXJhdGlvbi5cbiAgICAgIC8vIFRoaXMgbGVhZHMgdG8gdGhlIHByb2JsZW0gb2YgcmVmZXJlbmNpbmcgdW5kaXNwbGF5ZWQgYXR0YWNobWVudHMgaW4gdGhlIG5leHQgZ2VuZXJhdGlvbi5cbiAgICAgIC8vIFRvIHNvbHZlIHRoaXMgcHJvYmxlbSwgd2UgbmVlZCB0byBwZXJzaXN0ICRwcm9ncmVzcywgJGF0dGFjaG1lbnQgYW5kICRkZWJ1ZyBwcm9wZXJ0aWVzIGJ5IGFkZGluZyBhIG5ldyBhc3Npc3RhbnQgbWVzc2FnZSB3aXRoIGVtcHR5IGNvbnRlbnQgYW5kIHRoZXNlIHByb3BlcnRpZXMuXG4gICAgICAvLyBJbiB0aGUgb3RoZXIgaGFuZCwgdGhpcyBsZWFkcyB0byB0aGUgcHJvYmxlbSBvZiBoYXZpbmcgbWFueSBlbXB0eSBhc3Npc3RhbnQgbWVzc2FnZXMgaW4gdGhlIGNoYXQgaGlzdG9yeSwgaWYgYSBzdG9wIGdlbmVyYXRpb24gaGFwcGVucyBtdWx0aXBsZSB0aW1lcyBpbiBhIHJvdyB3aXRoIG5vIGNvbnRlbnQgZ2VuZXJhdGVkIHlldC5cbiAgICAgIC8vIFRvIHNvbHZlIHRoaXMgcHJvYmxlbSBtZW50aW9uZWQgaW4gdGhlIHRpY2tldCBFUy0yNzAyNCwgd2UgbmVlZCB0byBhbGxvdyBzdWNoIG9wZXJhdGlvbiBPTkxZIGlmIHRoZSBsYXN0IGFzc2lzdGFudCBtZXNzYWdlJ3MgY29udGVudCBpbiB0aGUgY2hhdCBoaXN0b3J5IGlzIG5vdCBlbXB0eS5cbiAgICAgIGNvbnN0IGNoYXRIaXN0b3J5ID0gY29udGV4dC5nZXRDaGF0SGlzdG9yeSgpO1xuICAgICAgY29uc3QgaXNMYXN0Q2hhdEhpc3RvcnlNZXNzYWdlQXNzaXN0YW50Q29udGVudEVtcHR5ID0gY2hhdEhpc3Rvcnk/Lmxlbmd0aFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICYmICBjaGF0SGlzdG9yeS5hdCgtMSk/LnJvbGUgPT09IFwiYXNzaXN0YW50XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAmJiAoY2hhdEhpc3RvcnkuYXQoLTEpPy5jb250ZW50ID09PSBcIlwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICgoY2hhdEhpc3RvcnkuYXQoLTEpPy5jb250ZW50IGFzIE1lc3NhZ2VDb250ZW50W10pPy5maW5kKChtc2cpID0+IG1zZy50eXBlID09PSBcInRleHRcIikgYXMgVGV4dE1lc3NhZ2VDb250ZW50KT8udGV4dCA9PT0gXCJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgIGlmICh0aGlzLl9yZXNwb25zZSAmJiB0aGlzLl9yZXNwb25zZS5sZW5ndGggPT09IDEgJiYgdGhpcy5fcmVzcG9uc2VbMF0uY29udGVudCA9PT0gXCJcIiAmJiAhaXNMYXN0Q2hhdEhpc3RvcnlNZXNzYWdlQXNzaXN0YW50Q29udGVudEVtcHR5KSB7XG4gICAgICAgIGNvbnN0IG5ld0NoYXRIaXN0b3J5ID0gY2hhdEhpc3RvcnkgPyBbLi4uY2hhdEhpc3RvcnldIDogW107XG4gICAgICAgIG5ld0NoYXRIaXN0b3J5LnB1c2goe3JvbGU6IFwiYXNzaXN0YW50XCIsIGNvbnRlbnQ6IFwiXCIsIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiB7ZGlzcGxheTogdHJ1ZSwgbWVzc2FnZUlkOiBndWlkKCksICRwcm9ncmVzczogdGhpcy5fcHJvZ3Jlc3MsICRhdHRhY2htZW50OiB0aGlzLl9hdHRhY2htZW50cywgJGRlYnVnOiB0aGlzLl9kZWJ1Z01lc3NhZ2VzfX0pO1xuICAgICAgICBjb250ZXh0LnNldENoYXRIaXN0b3J5KG5ld0NoYXRIaXN0b3J5KTtcbiAgICAgIH1cbiAgICAgIC8vIEVtaXQgdGhlIHJlc3VsdCBvZiB0aGUgQ2FuY2VsVGFza3MgbWV0aG9kXG4gICAgICBzdG9wR2VuZXJhdGlvblN1YmplY3QkLm5leHQoISFyZXMpO1xuICAgICAgLy8gQ29tcGxldGUgdGhlIHN1YmplY3RcbiAgICAgIHN0b3BHZW5lcmF0aW9uU3ViamVjdCQuY29tcGxldGUoKTtcbiAgICAgIC8vIENvbXBsZXRlIHN0b3BwaW5nIGdlbmVyYXRpb25cbiAgICAgIGNvbnRleHQuc2V0U3RvcHBpbmdHZW5lcmF0aW9uU3RhdHVzKGZhbHNlKTtcbiAgICB9KTtcblxuICAgIC8vIEludm9rZSB0aGUgQ2FuY2VsVGFza3MgbWV0aG9kIGFuZCBoYW5kbGUgZXJyb3JzXG4gICAgY29ubmVjdGlvbi5pbnZva2UoJ0NhbmNlbFRhc2tzJylcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGludm9raW5nIENhbmNlbFRhc2tzOicsIGVycm9yKTtcbiAgICAgICAgc3RvcEdlbmVyYXRpb25TdWJqZWN0JC5lcnJvcihuZXcgRXJyb3IoZXJyb3IgYXMgc3RyaW5nKSk7XG4gICAgICAgIGNvbnRleHQuc2V0U3RvcHBpbmdHZW5lcmF0aW9uU3RhdHVzKGZhbHNlKTtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgfSk7XG5cbiAgICByZXR1cm4gc3RvcEdlbmVyYXRpb25TdWJqZWN0JC5hc09ic2VydmFibGUoKTtcbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { Injectable, inject } from '@angular/core';
|
|
2
|
+
import { HttpTransportType, LogLevel } from '@microsoft/signalr';
|
|
3
|
+
import { getToken } from '@sinequa/atomic';
|
|
4
|
+
import { AssistantUtils } from '../utils/utils.service';
|
|
5
|
+
import { SignalRWebService } from './signalR.web.service';
|
|
6
|
+
import * as i0 from "@angular/core";
|
|
7
|
+
export class SignalRConnectionService {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.signalRWebService = inject(SignalRWebService);
|
|
10
|
+
this.assistantUtils = inject(AssistantUtils);
|
|
11
|
+
}
|
|
12
|
+
init(config) {
|
|
13
|
+
if (this.operationConfig) {
|
|
14
|
+
console.warn('SignalRConnectionService already initialized.');
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
this.operationConfig = config;
|
|
18
|
+
}
|
|
19
|
+
ensureInitialized() {
|
|
20
|
+
if (!this.operationConfig) {
|
|
21
|
+
throw new Error('SignalRConnectionService not initialized. Call init() first.');
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
_getLogLevel() {
|
|
25
|
+
this.ensureInitialized();
|
|
26
|
+
const assistantConfig = this.operationConfig.getAssistantConfigValue();
|
|
27
|
+
switch (assistantConfig?.connectionSettings.signalRLogLevel) {
|
|
28
|
+
case "Critical": return LogLevel.Critical;
|
|
29
|
+
case "Debug": return LogLevel.Debug;
|
|
30
|
+
case "Error": return LogLevel.Error;
|
|
31
|
+
case "Information": return LogLevel.Information;
|
|
32
|
+
case "None": return LogLevel.None;
|
|
33
|
+
case "Trace": return LogLevel.Trace;
|
|
34
|
+
case "Warning": return LogLevel.Warning;
|
|
35
|
+
default: return LogLevel.None;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
_getTransports() {
|
|
39
|
+
this.ensureInitialized();
|
|
40
|
+
const assistantConfig = this.operationConfig.getAssistantConfigValue();
|
|
41
|
+
switch (assistantConfig?.connectionSettings.signalRTransport) {
|
|
42
|
+
case "WebSockets": return HttpTransportType.WebSockets;
|
|
43
|
+
case "ServerSentEvents": return HttpTransportType.ServerSentEvents;
|
|
44
|
+
case "LongPolling": return HttpTransportType.LongPolling;
|
|
45
|
+
default: return HttpTransportType.None;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
getDefaultOptions() {
|
|
49
|
+
this.ensureInitialized();
|
|
50
|
+
let headers = {
|
|
51
|
+
"sinequa-force-camel-case": "true",
|
|
52
|
+
"x-language": this.assistantUtils.getCurrentLocaleName(),
|
|
53
|
+
"ui-language": this.assistantUtils.getCurrentLocaleName(),
|
|
54
|
+
};
|
|
55
|
+
const token = getToken();
|
|
56
|
+
if (token) {
|
|
57
|
+
headers = { ...headers, "sinequa-csrf-token": token };
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
transport: this._getTransports(),
|
|
61
|
+
withCredentials: true,
|
|
62
|
+
headers,
|
|
63
|
+
skipNegotiation: false,
|
|
64
|
+
accessTokenFactory: () => token || ""
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
buildConnection(options) {
|
|
68
|
+
this.ensureInitialized();
|
|
69
|
+
return new Promise((resolve, reject) => {
|
|
70
|
+
const wsRequestUrl = this.operationConfig.getWsRequestUrl();
|
|
71
|
+
if (!wsRequestUrl) {
|
|
72
|
+
reject(new Error("No endpoint provided to connect the websocket to"));
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const assistantConfig = this.operationConfig.getAssistantConfigValue();
|
|
76
|
+
const logLevel = this._getLogLevel();
|
|
77
|
+
const defaultOpts = this.getDefaultOptions();
|
|
78
|
+
if (assistantConfig?.connectionSettings.signalRSkipNegotiation === true) {
|
|
79
|
+
options = { ...options, skipNegotiation: true };
|
|
80
|
+
}
|
|
81
|
+
const connection = this.signalRWebService.buildConnection(wsRequestUrl, { ...defaultOpts, ...options }, logLevel, true);
|
|
82
|
+
const signalRServerTimeoutInMilliseconds = assistantConfig?.connectionSettings.signalRServerTimeoutInMilliseconds;
|
|
83
|
+
if (signalRServerTimeoutInMilliseconds && connection) {
|
|
84
|
+
connection.serverTimeoutInMilliseconds = signalRServerTimeoutInMilliseconds;
|
|
85
|
+
}
|
|
86
|
+
this.operationConfig.setHubConnection(connection);
|
|
87
|
+
resolve();
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
startConnection() {
|
|
91
|
+
this.ensureInitialized();
|
|
92
|
+
const connection = this.operationConfig.getHubConnection();
|
|
93
|
+
return this.signalRWebService.startConnection(connection);
|
|
94
|
+
}
|
|
95
|
+
stopConnection() {
|
|
96
|
+
this.ensureInitialized();
|
|
97
|
+
const connection = this.operationConfig.getHubConnection();
|
|
98
|
+
return this.signalRWebService.stopConnection(connection);
|
|
99
|
+
}
|
|
100
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SignalRConnectionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
101
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SignalRConnectionService, providedIn: 'root' }); }
|
|
102
|
+
}
|
|
103
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SignalRConnectionService, decorators: [{
|
|
104
|
+
type: Injectable,
|
|
105
|
+
args: [{
|
|
106
|
+
providedIn: 'root'
|
|
107
|
+
}]
|
|
108
|
+
}] });
|
|
109
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2lnbmFsUi1jb25uZWN0aW9uLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9hc3Npc3RhbnQvY2hhdC9zZXJ2aWNlcy9zaWduYWxSLWNvbm5lY3Rpb24uc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNuRCxPQUFPLEVBQWlCLGlCQUFpQixFQUFFLFFBQVEsRUFBa0IsTUFBTSxvQkFBb0IsQ0FBQztBQUNoRyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDM0MsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3hELE9BQU8sRUFBRSxpQkFBaUIsRUFBcUIsTUFBTSx1QkFBdUIsQ0FBQzs7QUFhN0UsTUFBTSxPQUFPLHdCQUF3QjtJQUhyQztRQUtVLHNCQUFpQixHQUFHLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1FBQzlDLG1CQUFjLEdBQUcsTUFBTSxDQUFDLGNBQWMsQ0FBQyxDQUFDO0tBbUdqRDtJQWpHUSxJQUFJLENBQUMsTUFBd0M7UUFDbEQsSUFBSSxJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7WUFDekIsT0FBTyxDQUFDLElBQUksQ0FBQywrQ0FBK0MsQ0FBQyxDQUFDO1lBQzlELE9BQU87UUFDVCxDQUFDO1FBQ0QsSUFBSSxDQUFDLGVBQWUsR0FBRyxNQUFNLENBQUM7SUFDaEMsQ0FBQztJQUVPLGlCQUFpQjtRQUN2QixJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsOERBQThELENBQUMsQ0FBQztRQUNsRixDQUFDO0lBQ0gsQ0FBQztJQUVPLFlBQVk7UUFDbEIsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7UUFDekIsTUFBTSxlQUFlLEdBQUcsSUFBSSxDQUFDLGVBQWdCLENBQUMsdUJBQXVCLEVBQUUsQ0FBQztRQUN4RSxRQUFRLGVBQWUsRUFBRSxrQkFBa0IsQ0FBQyxlQUFlLEVBQUUsQ0FBQztZQUM1RCxLQUFLLFVBQVUsQ0FBQyxDQUFDLE9BQU8sUUFBUSxDQUFDLFFBQVEsQ0FBQztZQUMxQyxLQUFLLE9BQU8sQ0FBQyxDQUFDLE9BQU8sUUFBUSxDQUFDLEtBQUssQ0FBQztZQUNwQyxLQUFLLE9BQU8sQ0FBQyxDQUFDLE9BQU8sUUFBUSxDQUFDLEtBQUssQ0FBQztZQUNwQyxLQUFLLGFBQWEsQ0FBQyxDQUFDLE9BQU8sUUFBUSxDQUFDLFdBQVcsQ0FBQztZQUNoRCxLQUFLLE1BQU0sQ0FBQyxDQUFDLE9BQU8sUUFBUSxDQUFDLElBQUksQ0FBQztZQUNsQyxLQUFLLE9BQU8sQ0FBQyxDQUFDLE9BQU8sUUFBUSxDQUFDLEtBQUssQ0FBQztZQUNwQyxLQUFLLFNBQVMsQ0FBQyxDQUFDLE9BQU8sUUFBUSxDQUFDLE9BQU8sQ0FBQztZQUN4QyxPQUFPLENBQUMsQ0FBQyxPQUFPLFFBQVEsQ0FBQyxJQUFJLENBQUM7UUFDaEMsQ0FBQztJQUNILENBQUM7SUFFTyxjQUFjO1FBQ3BCLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBQ3pCLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxlQUFnQixDQUFDLHVCQUF1QixFQUFFLENBQUM7UUFDeEUsUUFBUSxlQUFlLEVBQUUsa0JBQWtCLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUM3RCxLQUFLLFlBQVksQ0FBQyxDQUFDLE9BQU8saUJBQWlCLENBQUMsVUFBVSxDQUFDO1lBQ3ZELEtBQUssa0JBQWtCLENBQUMsQ0FBQyxPQUFPLGlCQUFpQixDQUFDLGdCQUFnQixDQUFDO1lBQ25FLEtBQUssYUFBYSxDQUFDLENBQUMsT0FBTyxpQkFBaUIsQ0FBQyxXQUFXLENBQUM7WUFDekQsT0FBTyxDQUFDLENBQUMsT0FBTyxpQkFBaUIsQ0FBQyxJQUFJLENBQUM7UUFDekMsQ0FBQztJQUNILENBQUM7SUFFTyxpQkFBaUI7UUFDdkIsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7UUFDekIsSUFBSSxPQUFPLEdBQW1CO1lBQzVCLDBCQUEwQixFQUFFLE1BQU07WUFDbEMsWUFBWSxFQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsb0JBQW9CLEVBQUU7WUFDeEQsYUFBYSxFQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsb0JBQW9CLEVBQUU7U0FDMUQsQ0FBQztRQUNGLE1BQU0sS0FBSyxHQUFHLFFBQVEsRUFBRSxDQUFDO1FBQ3pCLElBQUksS0FBSyxFQUFFLENBQUM7WUFDVixPQUFPLEdBQUcsRUFBRSxHQUFHLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxLQUFLLEVBQUUsQ0FBQztRQUN4RCxDQUFDO1FBRUQsT0FBTztZQUNMLFNBQVMsRUFBRSxJQUFJLENBQUMsY0FBYyxFQUFFO1lBQ2hDLGVBQWUsRUFBRSxJQUFJO1lBQ3JCLE9BQU87WUFDUCxlQUFlLEVBQUUsS0FBSztZQUN0QixrQkFBa0IsRUFBRSxHQUFHLEVBQUUsQ0FBQyxLQUFLLElBQUksRUFBRTtTQUN0QyxDQUFDO0lBQ0osQ0FBQztJQUVNLGVBQWUsQ0FBQyxPQUEyQjtRQUNoRCxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztRQUN6QixPQUFPLElBQUksT0FBTyxDQUFPLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQzNDLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxlQUFnQixDQUFDLGVBQWUsRUFBRSxDQUFDO1lBQzdELElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztnQkFDbEIsTUFBTSxDQUFDLElBQUksS0FBSyxDQUFDLGtEQUFrRCxDQUFDLENBQUMsQ0FBQztnQkFDdEUsT0FBTztZQUNULENBQUM7WUFDRCxNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsZUFBZ0IsQ0FBQyx1QkFBdUIsRUFBRSxDQUFDO1lBQ3hFLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUNyQyxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztZQUM3QyxJQUFJLGVBQWUsRUFBRSxrQkFBa0IsQ0FBQyxzQkFBc0IsS0FBSyxJQUFJLEVBQUUsQ0FBQztnQkFDeEUsT0FBTyxHQUFHLEVBQUMsR0FBRyxPQUFPLEVBQUUsZUFBZSxFQUFFLElBQUksRUFBQyxDQUFDO1lBQ2hELENBQUM7WUFDRCxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsZUFBZSxDQUFDLFlBQVksRUFBRSxFQUFFLEdBQUcsV0FBVyxFQUFFLEdBQUcsT0FBTyxFQUFFLEVBQUUsUUFBUSxFQUFFLElBQUksQ0FBQyxDQUFDO1lBRXhILE1BQU0sa0NBQWtDLEdBQUcsZUFBZSxFQUFFLGtCQUFrQixDQUFDLGtDQUFrQyxDQUFDO1lBQ2xILElBQUksa0NBQWtDLElBQUksVUFBVSxFQUFFLENBQUM7Z0JBQ3JELFVBQVUsQ0FBQywyQkFBMkIsR0FBRyxrQ0FBa0MsQ0FBQztZQUM5RSxDQUFDO1lBQ0QsSUFBSSxDQUFDLGVBQWdCLENBQUMsZ0JBQWdCLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDbkQsT0FBTyxFQUFFLENBQUM7UUFDWixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTSxlQUFlO1FBQ3BCLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBQ3pCLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxlQUFnQixDQUFDLGdCQUFnQixFQUFFLENBQUM7UUFDNUQsT0FBTyxJQUFJLENBQUMsaUJBQWlCLENBQUMsZUFBZSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzVELENBQUM7SUFFTSxjQUFjO1FBQ25CLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBQ3pCLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxlQUFnQixDQUFDLGdCQUFnQixFQUFFLENBQUM7UUFDNUQsT0FBTyxJQUFJLENBQUMsaUJBQWlCLENBQUMsY0FBYyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzNELENBQUM7K0dBckdVLHdCQUF3QjttSEFBeEIsd0JBQXdCLGNBRnZCLE1BQU07OzRGQUVQLHdCQUF3QjtrQkFIcEMsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlLCBpbmplY3QgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEh1YkNvbm5lY3Rpb24sIEh0dHBUcmFuc3BvcnRUeXBlLCBMb2dMZXZlbCwgTWVzc2FnZUhlYWRlcnMgfSBmcm9tICdAbWljcm9zb2Z0L3NpZ25hbHInO1xuaW1wb3J0IHsgZ2V0VG9rZW4gfSBmcm9tICdAc2luZXF1YS9hdG9taWMnO1xuaW1wb3J0IHsgQXNzaXN0YW50VXRpbHMgfSBmcm9tICcuLi91dGlscy91dGlscy5zZXJ2aWNlJztcbmltcG9ydCB7IFNpZ25hbFJXZWJTZXJ2aWNlLCBDb25uZWN0aW9uT3B0aW9ucyB9IGZyb20gJy4vc2lnbmFsUi53ZWIuc2VydmljZSc7XG5pbXBvcnQgeyBDaGF0Q29uZmlnIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIFNpZ25hbFJDb25uZWN0aW9uT3BlcmF0aW9uQ29uZmlnIHtcbiAgZ2V0V3NSZXF1ZXN0VXJsOiAoKSA9PiBzdHJpbmc7XG4gIGdldEFzc2lzdGFudENvbmZpZ1ZhbHVlOiAoKSA9PiBDaGF0Q29uZmlnIHwgdW5kZWZpbmVkO1xuICBnZXRIdWJDb25uZWN0aW9uOiAoKSA9PiBIdWJDb25uZWN0aW9uIHwgdW5kZWZpbmVkO1xuICBzZXRIdWJDb25uZWN0aW9uOiAoY29ubmVjdGlvbjogSHViQ29ubmVjdGlvbiB8IHVuZGVmaW5lZCkgPT4gdm9pZDtcbn1cblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCdcbn0pXG5leHBvcnQgY2xhc3MgU2lnbmFsUkNvbm5lY3Rpb25TZXJ2aWNlIHtcbiAgcHJpdmF0ZSBvcGVyYXRpb25Db25maWc6IFNpZ25hbFJDb25uZWN0aW9uT3BlcmF0aW9uQ29uZmlnIHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIHNpZ25hbFJXZWJTZXJ2aWNlID0gaW5qZWN0KFNpZ25hbFJXZWJTZXJ2aWNlKTtcbiAgcHJpdmF0ZSBhc3Npc3RhbnRVdGlscyA9IGluamVjdChBc3Npc3RhbnRVdGlscyk7XG5cbiAgcHVibGljIGluaXQoY29uZmlnOiBTaWduYWxSQ29ubmVjdGlvbk9wZXJhdGlvbkNvbmZpZyk6IHZvaWQge1xuICAgIGlmICh0aGlzLm9wZXJhdGlvbkNvbmZpZykge1xuICAgICAgY29uc29sZS53YXJuKCdTaWduYWxSQ29ubmVjdGlvblNlcnZpY2UgYWxyZWFkeSBpbml0aWFsaXplZC4nKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5vcGVyYXRpb25Db25maWcgPSBjb25maWc7XG4gIH1cblxuICBwcml2YXRlIGVuc3VyZUluaXRpYWxpemVkKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5vcGVyYXRpb25Db25maWcpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignU2lnbmFsUkNvbm5lY3Rpb25TZXJ2aWNlIG5vdCBpbml0aWFsaXplZC4gQ2FsbCBpbml0KCkgZmlyc3QuJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfZ2V0TG9nTGV2ZWwoKTogTG9nTGV2ZWwge1xuICAgIHRoaXMuZW5zdXJlSW5pdGlhbGl6ZWQoKTtcbiAgICBjb25zdCBhc3Npc3RhbnRDb25maWcgPSB0aGlzLm9wZXJhdGlvbkNvbmZpZyEuZ2V0QXNzaXN0YW50Q29uZmlnVmFsdWUoKTtcbiAgICBzd2l0Y2ggKGFzc2lzdGFudENvbmZpZz8uY29ubmVjdGlvblNldHRpbmdzLnNpZ25hbFJMb2dMZXZlbCkge1xuICAgICAgY2FzZSBcIkNyaXRpY2FsXCI6IHJldHVybiBMb2dMZXZlbC5Dcml0aWNhbDtcbiAgICAgIGNhc2UgXCJEZWJ1Z1wiOiByZXR1cm4gTG9nTGV2ZWwuRGVidWc7XG4gICAgICBjYXNlIFwiRXJyb3JcIjogcmV0dXJuIExvZ0xldmVsLkVycm9yO1xuICAgICAgY2FzZSBcIkluZm9ybWF0aW9uXCI6IHJldHVybiBMb2dMZXZlbC5JbmZvcm1hdGlvbjtcbiAgICAgIGNhc2UgXCJOb25lXCI6IHJldHVybiBMb2dMZXZlbC5Ob25lO1xuICAgICAgY2FzZSBcIlRyYWNlXCI6IHJldHVybiBMb2dMZXZlbC5UcmFjZTtcbiAgICAgIGNhc2UgXCJXYXJuaW5nXCI6IHJldHVybiBMb2dMZXZlbC5XYXJuaW5nO1xuICAgICAgZGVmYXVsdDogcmV0dXJuIExvZ0xldmVsLk5vbmU7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfZ2V0VHJhbnNwb3J0cygpOiBIdHRwVHJhbnNwb3J0VHlwZSB7XG4gICAgdGhpcy5lbnN1cmVJbml0aWFsaXplZCgpO1xuICAgIGNvbnN0IGFzc2lzdGFudENvbmZpZyA9IHRoaXMub3BlcmF0aW9uQ29uZmlnIS5nZXRBc3Npc3RhbnRDb25maWdWYWx1ZSgpO1xuICAgIHN3aXRjaCAoYXNzaXN0YW50Q29uZmlnPy5jb25uZWN0aW9uU2V0dGluZ3Muc2lnbmFsUlRyYW5zcG9ydCkge1xuICAgICAgY2FzZSBcIldlYlNvY2tldHNcIjogcmV0dXJuIEh0dHBUcmFuc3BvcnRUeXBlLldlYlNvY2tldHM7XG4gICAgICBjYXNlIFwiU2VydmVyU2VudEV2ZW50c1wiOiByZXR1cm4gSHR0cFRyYW5zcG9ydFR5cGUuU2VydmVyU2VudEV2ZW50cztcbiAgICAgIGNhc2UgXCJMb25nUG9sbGluZ1wiOiByZXR1cm4gSHR0cFRyYW5zcG9ydFR5cGUuTG9uZ1BvbGxpbmc7XG4gICAgICBkZWZhdWx0OiByZXR1cm4gSHR0cFRyYW5zcG9ydFR5cGUuTm9uZTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGdldERlZmF1bHRPcHRpb25zKCk6IENvbm5lY3Rpb25PcHRpb25zIHtcbiAgICB0aGlzLmVuc3VyZUluaXRpYWxpemVkKCk7XG4gICAgbGV0IGhlYWRlcnM6IE1lc3NhZ2VIZWFkZXJzID0ge1xuICAgICAgXCJzaW5lcXVhLWZvcmNlLWNhbWVsLWNhc2VcIjogXCJ0cnVlXCIsXG4gICAgICBcIngtbGFuZ3VhZ2VcIjogdGhpcy5hc3Npc3RhbnRVdGlscy5nZXRDdXJyZW50TG9jYWxlTmFtZSgpLFxuICAgICAgXCJ1aS1sYW5ndWFnZVwiOiB0aGlzLmFzc2lzdGFudFV0aWxzLmdldEN1cnJlbnRMb2NhbGVOYW1lKCksXG4gICAgfTtcbiAgICBjb25zdCB0b2tlbiA9IGdldFRva2VuKCk7XG4gICAgaWYgKHRva2VuKSB7XG4gICAgICBoZWFkZXJzID0geyAuLi5oZWFkZXJzLCBcInNpbmVxdWEtY3NyZi10b2tlblwiOiB0b2tlbiB9O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICB0cmFuc3BvcnQ6IHRoaXMuX2dldFRyYW5zcG9ydHMoKSxcbiAgICAgIHdpdGhDcmVkZW50aWFsczogdHJ1ZSxcbiAgICAgIGhlYWRlcnMsXG4gICAgICBza2lwTmVnb3RpYXRpb246IGZhbHNlLFxuICAgICAgYWNjZXNzVG9rZW5GYWN0b3J5OiAoKSA9PiB0b2tlbiB8fCBcIlwiXG4gICAgfTtcbiAgfVxuXG4gIHB1YmxpYyBidWlsZENvbm5lY3Rpb24ob3B0aW9ucz86IENvbm5lY3Rpb25PcHRpb25zKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5lbnN1cmVJbml0aWFsaXplZCgpO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCB3c1JlcXVlc3RVcmwgPSB0aGlzLm9wZXJhdGlvbkNvbmZpZyEuZ2V0V3NSZXF1ZXN0VXJsKCk7XG4gICAgICBpZiAoIXdzUmVxdWVzdFVybCkge1xuICAgICAgICByZWplY3QobmV3IEVycm9yKFwiTm8gZW5kcG9pbnQgcHJvdmlkZWQgdG8gY29ubmVjdCB0aGUgd2Vic29ja2V0IHRvXCIpKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgY29uc3QgYXNzaXN0YW50Q29uZmlnID0gdGhpcy5vcGVyYXRpb25Db25maWchLmdldEFzc2lzdGFudENvbmZpZ1ZhbHVlKCk7XG4gICAgICBjb25zdCBsb2dMZXZlbCA9IHRoaXMuX2dldExvZ0xldmVsKCk7XG4gICAgICBjb25zdCBkZWZhdWx0T3B0cyA9IHRoaXMuZ2V0RGVmYXVsdE9wdGlvbnMoKTtcbiAgICAgIGlmIChhc3Npc3RhbnRDb25maWc/LmNvbm5lY3Rpb25TZXR0aW5ncy5zaWduYWxSU2tpcE5lZ290aWF0aW9uID09PSB0cnVlKSB7XG4gICAgICAgIG9wdGlvbnMgPSB7Li4ub3B0aW9ucywgc2tpcE5lZ290aWF0aW9uOiB0cnVlfTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSB0aGlzLnNpZ25hbFJXZWJTZXJ2aWNlLmJ1aWxkQ29ubmVjdGlvbih3c1JlcXVlc3RVcmwsIHsgLi4uZGVmYXVsdE9wdHMsIC4uLm9wdGlvbnMgfSwgbG9nTGV2ZWwsIHRydWUpO1xuXG4gICAgICBjb25zdCBzaWduYWxSU2VydmVyVGltZW91dEluTWlsbGlzZWNvbmRzID0gYXNzaXN0YW50Q29uZmlnPy5jb25uZWN0aW9uU2V0dGluZ3Muc2lnbmFsUlNlcnZlclRpbWVvdXRJbk1pbGxpc2Vjb25kcztcbiAgICAgIGlmIChzaWduYWxSU2VydmVyVGltZW91dEluTWlsbGlzZWNvbmRzICYmIGNvbm5lY3Rpb24pIHtcbiAgICAgICAgY29ubmVjdGlvbi5zZXJ2ZXJUaW1lb3V0SW5NaWxsaXNlY29uZHMgPSBzaWduYWxSU2VydmVyVGltZW91dEluTWlsbGlzZWNvbmRzO1xuICAgICAgfVxuICAgICAgdGhpcy5vcGVyYXRpb25Db25maWchLnNldEh1YkNvbm5lY3Rpb24oY29ubmVjdGlvbik7XG4gICAgICByZXNvbHZlKCk7XG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgc3RhcnRDb25uZWN0aW9uKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuZW5zdXJlSW5pdGlhbGl6ZWQoKTtcbiAgICBjb25zdCBjb25uZWN0aW9uID0gdGhpcy5vcGVyYXRpb25Db25maWchLmdldEh1YkNvbm5lY3Rpb24oKTtcbiAgICByZXR1cm4gdGhpcy5zaWduYWxSV2ViU2VydmljZS5zdGFydENvbm5lY3Rpb24oY29ubmVjdGlvbik7XG4gIH1cblxuICBwdWJsaWMgc3RvcENvbm5lY3Rpb24oKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5lbnN1cmVJbml0aWFsaXplZCgpO1xuICAgIGNvbnN0IGNvbm5lY3Rpb24gPSB0aGlzLm9wZXJhdGlvbkNvbmZpZyEuZ2V0SHViQ29ubmVjdGlvbigpO1xuICAgIHJldHVybiB0aGlzLnNpZ25hbFJXZWJTZXJ2aWNlLnN0b3BDb25uZWN0aW9uKGNvbm5lY3Rpb24pO1xuICB9XG59XG4iXX0=
|