@copilotkitnext/angular 1.52.0-next.8 → 1.52.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/README.md +225 -432
  2. package/dist/README.md +225 -432
  3. package/dist/fesm2022/copilotkitnext-angular.mjs +312 -161
  4. package/dist/fesm2022/copilotkitnext-angular.mjs.map +1 -1
  5. package/dist/lib/agent.d.ts +20 -20
  6. package/dist/lib/components/chat/copilot-chat-assistant-message.d.ts +46 -46
  7. package/dist/lib/components/chat/copilot-chat-message-view.d.ts +126 -126
  8. package/dist/lib/components/chat/copilot-chat-tool-calls-view.d.ts +23 -23
  9. package/dist/lib/components/chat/copilot-chat-user-message-branch-navigation.d.ts +6 -6
  10. package/dist/lib/components/chat/copilot-chat-user-message.d.ts +6 -6
  11. package/dist/lib/components/chat/copilot-chat-view-scroll-view.d.ts +18 -18
  12. package/dist/lib/components/chat/copilot-chat-view.d.ts +54 -54
  13. package/dist/lib/components/chat/copilot-chat.d.ts +18 -18
  14. package/dist/lib/config.d.ts +1 -0
  15. package/dist/lib/copilotkit.d.ts +6 -1
  16. package/dist/lib/license-watermark.d.ts +1 -0
  17. package/dist/lib/render-tool-calls.d.ts +23 -23
  18. package/dist/styles.css +3 -0
  19. package/package.json +18 -18
  20. package/dist/esm2022/copilotkitnext-angular.mjs +0 -5
  21. package/dist/esm2022/index.mjs +0 -2
  22. package/dist/esm2022/lib/agent-context.mjs +0 -25
  23. package/dist/esm2022/lib/agent.mjs +0 -73
  24. package/dist/esm2022/lib/chat-config.mjs +0 -35
  25. package/dist/esm2022/lib/chat-state.mjs +0 -18
  26. package/dist/esm2022/lib/components/chat/copilot-chat-assistant-message-buttons.mjs +0 -344
  27. package/dist/esm2022/lib/components/chat/copilot-chat-assistant-message-renderer.mjs +0 -260
  28. package/dist/esm2022/lib/components/chat/copilot-chat-assistant-message-toolbar.mjs +0 -22
  29. package/dist/esm2022/lib/components/chat/copilot-chat-assistant-message.mjs +0 -415
  30. package/dist/esm2022/lib/components/chat/copilot-chat-assistant-message.types.mjs +0 -2
  31. package/dist/esm2022/lib/components/chat/copilot-chat-audio-recorder.mjs +0 -196
  32. package/dist/esm2022/lib/components/chat/copilot-chat-buttons.mjs +0 -299
  33. package/dist/esm2022/lib/components/chat/copilot-chat-input-defaults.mjs +0 -39
  34. package/dist/esm2022/lib/components/chat/copilot-chat-input.mjs +0 -634
  35. package/dist/esm2022/lib/components/chat/copilot-chat-input.types.mjs +0 -10
  36. package/dist/esm2022/lib/components/chat/copilot-chat-message-view-cursor.mjs +0 -27
  37. package/dist/esm2022/lib/components/chat/copilot-chat-message-view.mjs +0 -269
  38. package/dist/esm2022/lib/components/chat/copilot-chat-message-view.types.mjs +0 -2
  39. package/dist/esm2022/lib/components/chat/copilot-chat-textarea.mjs +0 -139
  40. package/dist/esm2022/lib/components/chat/copilot-chat-tool-calls-view.mjs +0 -36
  41. package/dist/esm2022/lib/components/chat/copilot-chat-toolbar.mjs +0 -20
  42. package/dist/esm2022/lib/components/chat/copilot-chat-tools-menu.mjs +0 -203
  43. package/dist/esm2022/lib/components/chat/copilot-chat-user-message-branch-navigation.mjs +0 -118
  44. package/dist/esm2022/lib/components/chat/copilot-chat-user-message-buttons.mjs +0 -182
  45. package/dist/esm2022/lib/components/chat/copilot-chat-user-message-renderer.mjs +0 -28
  46. package/dist/esm2022/lib/components/chat/copilot-chat-user-message-toolbar.mjs +0 -25
  47. package/dist/esm2022/lib/components/chat/copilot-chat-user-message.mjs +0 -328
  48. package/dist/esm2022/lib/components/chat/copilot-chat-user-message.types.mjs +0 -2
  49. package/dist/esm2022/lib/components/chat/copilot-chat-view-disclaimer.mjs +0 -48
  50. package/dist/esm2022/lib/components/chat/copilot-chat-view-feather.mjs +0 -41
  51. package/dist/esm2022/lib/components/chat/copilot-chat-view-handlers.mjs +0 -19
  52. package/dist/esm2022/lib/components/chat/copilot-chat-view-input-container.mjs +0 -96
  53. package/dist/esm2022/lib/components/chat/copilot-chat-view-scroll-to-bottom-button.mjs +0 -89
  54. package/dist/esm2022/lib/components/chat/copilot-chat-view-scroll-view.mjs +0 -456
  55. package/dist/esm2022/lib/components/chat/copilot-chat-view.mjs +0 -404
  56. package/dist/esm2022/lib/components/chat/copilot-chat-view.types.mjs +0 -2
  57. package/dist/esm2022/lib/components/chat/copilot-chat.mjs +0 -165
  58. package/dist/esm2022/lib/config.mjs +0 -9
  59. package/dist/esm2022/lib/copilotkit.mjs +0 -125
  60. package/dist/esm2022/lib/directives/copilotkit-agent-context.mjs +0 -130
  61. package/dist/esm2022/lib/directives/stick-to-bottom.mjs +0 -170
  62. package/dist/esm2022/lib/directives/tooltip.mjs +0 -217
  63. package/dist/esm2022/lib/human-in-the-loop.mjs +0 -19
  64. package/dist/esm2022/lib/render-tool-calls.mjs +0 -167
  65. package/dist/esm2022/lib/resize-observer.mjs +0 -152
  66. package/dist/esm2022/lib/scroll-position.mjs +0 -123
  67. package/dist/esm2022/lib/slots/copilot-slot.mjs +0 -156
  68. package/dist/esm2022/lib/slots/index.mjs +0 -4
  69. package/dist/esm2022/lib/slots/slot.types.mjs +0 -6
  70. package/dist/esm2022/lib/slots/slot.utils.mjs +0 -235
  71. package/dist/esm2022/lib/tools.mjs +0 -31
  72. package/dist/esm2022/lib/utils.mjs +0 -10
  73. package/dist/esm2022/public-api.mjs +0 -48
@@ -1,634 +0,0 @@
1
- import { Component, TemplateRef, signal, computed, effect, ChangeDetectionStrategy, ViewEncapsulation, ContentChild, input, output, ViewChild, } from "@angular/core";
2
- import { CommonModule } from "@angular/common";
3
- import { CopilotSlot } from "../../slots/copilot-slot";
4
- import { injectChatLabels } from "../../chat-config";
5
- import { LucideAngularModule, ArrowUp } from "lucide-angular";
6
- import { CopilotChatTextarea } from "./copilot-chat-textarea";
7
- import { CopilotChatAudioRecorder } from "./copilot-chat-audio-recorder";
8
- import { CopilotChatStartTranscribeButton, CopilotChatCancelTranscribeButton, CopilotChatFinishTranscribeButton, CopilotChatAddFileButton, } from "./copilot-chat-buttons";
9
- import { CopilotChatToolbar } from "./copilot-chat-toolbar";
10
- import { CopilotChatToolsMenu } from "./copilot-chat-tools-menu";
11
- import { cn } from "../../utils";
12
- import { injectChatState } from "../../chat-state";
13
- import * as i0 from "@angular/core";
14
- import * as i1 from "@angular/common";
15
- import * as i2 from "lucide-angular";
16
- export class CopilotChatInput {
17
- textAreaRef;
18
- audioRecorderRef;
19
- // Capture templates from content projection
20
- sendButtonTemplate;
21
- toolbarTemplate;
22
- textAreaTemplate;
23
- audioRecorderTemplate;
24
- startTranscribeButtonTemplate;
25
- cancelTranscribeButtonTemplate;
26
- finishTranscribeButtonTemplate;
27
- addFileButtonTemplate;
28
- toolsButtonTemplate;
29
- // Class inputs for styling default components
30
- sendButtonClass = input(undefined);
31
- toolbarClass = input(undefined);
32
- textAreaClass = input(undefined);
33
- textAreaMaxRows = input(undefined);
34
- textAreaPlaceholder = input(undefined);
35
- audioRecorderClass = input(undefined);
36
- startTranscribeButtonClass = input(undefined);
37
- cancelTranscribeButtonClass = input(undefined);
38
- finishTranscribeButtonClass = input(undefined);
39
- addFileButtonClass = input(undefined);
40
- toolsButtonClass = input(undefined);
41
- // Component inputs for overrides
42
- sendButtonComponent = input(undefined);
43
- toolbarComponent = input(undefined);
44
- textAreaComponent = input(undefined);
45
- audioRecorderComponent = input(undefined);
46
- startTranscribeButtonComponent = input(undefined);
47
- cancelTranscribeButtonComponent = input(undefined);
48
- finishTranscribeButtonComponent = input(undefined);
49
- addFileButtonComponent = input(undefined);
50
- toolsButtonComponent = input(undefined);
51
- // Regular inputs
52
- mode = input(undefined);
53
- toolsMenu = input(undefined);
54
- autoFocus = input(undefined);
55
- value = input(undefined);
56
- inputClass = input(undefined);
57
- // Note: Prefer host `class` for styling this component;
58
- // keep only `inputClass` to style the internal wrapper if needed.
59
- additionalToolbarItems = input(undefined);
60
- // Output events
61
- submitMessage = output();
62
- startTranscribe = output();
63
- cancelTranscribe = output();
64
- finishTranscribe = output();
65
- addFile = output();
66
- valueChange = output();
67
- // Icons and default classes
68
- ArrowUpIcon = ArrowUp;
69
- defaultButtonClass = cn(
70
- // Base button styles
71
- "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium", "transition-all disabled:pointer-events-none disabled:opacity-50", "shrink-0 outline-none", "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
72
- // chatInputToolbarPrimary variant
73
- "cursor-pointer", "bg-black text-white", "dark:bg-white dark:text-black dark:focus-visible:outline-white", "rounded-full h-9 w-9", "transition-colors", "focus:outline-none", "hover:opacity-70 disabled:hover:opacity-100", "disabled:cursor-not-allowed disabled:bg-[#00000014] disabled:text-[rgb(13,13,13)]", "dark:disabled:bg-[#454545] dark:disabled:text-white");
74
- // Services
75
- labels = injectChatLabels();
76
- // readonly chatConfig = injectChatConfig();
77
- chatState = injectChatState();
78
- // Signals
79
- modeSignal = signal("input");
80
- toolsMenuSignal = signal([]);
81
- autoFocusSignal = signal(true);
82
- customClass = signal(undefined);
83
- // Default components
84
- // Note: CopilotChatTextarea uses attribute selector but is a component
85
- defaultAudioRecorder = CopilotChatAudioRecorder;
86
- defaultSendButton = null; // Will be set to avoid circular dependency
87
- CopilotChatToolbar = CopilotChatToolbar;
88
- CopilotChatAddFileButton = CopilotChatAddFileButton;
89
- CopilotChatToolsMenu = CopilotChatToolsMenu;
90
- CopilotChatCancelTranscribeButton = CopilotChatCancelTranscribeButton;
91
- CopilotChatFinishTranscribeButton = CopilotChatFinishTranscribeButton;
92
- CopilotChatStartTranscribeButton = CopilotChatStartTranscribeButton;
93
- // Computed values
94
- computedMode = computed(() => this.modeSignal());
95
- computedToolsMenu = computed(() => this.toolsMenu() ?? []);
96
- computedAutoFocus = computed(() => this.autoFocus() ?? true);
97
- computedValue = computed(() => {
98
- const customValue = this.value() ?? "";
99
- const configValue = this.chatState.inputValue();
100
- return customValue || configValue || "";
101
- });
102
- computedClass = computed(() => {
103
- const baseClasses = cn(
104
- // Layout
105
- "flex w-full flex-col items-center justify-center",
106
- // Interaction
107
- "cursor-text",
108
- // Overflow and clipping
109
- "overflow-visible bg-clip-padding contain-inline-size",
110
- // Background
111
- "bg-white dark:bg-[#303030]",
112
- // Visual effects
113
- "shadow-[0_4px_4px_0_#0000000a,0_0_1px_0_#0000009e] rounded-[28px]");
114
- return cn(baseClasses, this.customClass());
115
- });
116
- // Context for slots (reactive via signals)
117
- sendButtonContext = computed(() => ({
118
- send: () => this.send(),
119
- disabled: !this.computedValue().trim() || this.computedMode() === "processing",
120
- value: this.computedValue(),
121
- }));
122
- toolbarContext = computed(() => ({
123
- mode: this.computedMode(),
124
- value: this.computedValue(),
125
- }));
126
- textAreaContext = computed(() => ({
127
- value: this.computedValue(),
128
- autoFocus: this.computedAutoFocus(),
129
- disabled: this.computedMode() === "processing",
130
- maxRows: this.textAreaMaxRows(),
131
- placeholder: this.textAreaPlaceholder(),
132
- inputClass: this.textAreaClass(),
133
- onKeyDown: (event) => this.handleKeyDown(event),
134
- onChange: (value) => this.handleValueChange(value),
135
- }));
136
- audioRecorderContext = computed(() => ({
137
- inputShowControls: true,
138
- }));
139
- // Button contexts removed - now using outputs map for click handlers
140
- toolsContext = computed(() => ({
141
- inputToolsMenu: this.computedToolsMenu(),
142
- inputDisabled: this.computedMode() === "transcribe",
143
- }));
144
- constructor() {
145
- // Effect to handle mode changes (no signal writes)
146
- effect(() => {
147
- const currentMode = this.computedMode();
148
- if (currentMode === "transcribe" && this.audioRecorderRef) {
149
- this.audioRecorderRef.start().catch(console.error);
150
- }
151
- else if (this.audioRecorderRef?.getState() === "recording") {
152
- this.audioRecorderRef.stop().catch(console.error);
153
- }
154
- });
155
- }
156
- // Output maps for slots
157
- addFileButtonOutputs = { clicked: () => this.handleAddFile() };
158
- cancelTranscribeButtonOutputs = {
159
- clicked: () => this.handleCancelTranscribe(),
160
- };
161
- finishTranscribeButtonOutputs = {
162
- clicked: () => this.handleFinishTranscribe(),
163
- };
164
- startTranscribeButtonOutputs = {
165
- clicked: () => this.handleStartTranscribe(),
166
- };
167
- // Support both `clicked` (idiomatic in our slots) and `click` (legacy)
168
- sendButtonOutputs = { clicked: () => this.send(), click: () => this.send() };
169
- ngAfterViewInit() {
170
- // Auto-focus if needed
171
- if (this.computedAutoFocus() && this.textAreaRef) {
172
- setTimeout(() => {
173
- this.textAreaRef?.focus();
174
- });
175
- }
176
- }
177
- ngOnDestroy() {
178
- // Clean up any resources
179
- if (this.audioRecorderRef?.getState() === "recording") {
180
- this.audioRecorderRef?.stop().catch(console.error);
181
- }
182
- }
183
- handleKeyDown(event) {
184
- if (event.key === "Enter" && !event.shiftKey) {
185
- event.preventDefault();
186
- this.send();
187
- }
188
- }
189
- handleValueChange(value) {
190
- this.valueChange.emit(value);
191
- if (this.chatState)
192
- this.chatState.changeInput(value);
193
- }
194
- send() {
195
- const trimmed = this.computedValue().trim();
196
- if (trimmed) {
197
- this.submitMessage.emit(trimmed);
198
- this.chatState.submitInput(trimmed);
199
- if (this.chatState)
200
- this.chatState.changeInput("");
201
- if (this.textAreaRef)
202
- this.textAreaRef.setValue("");
203
- // Refocus input
204
- if (this.textAreaRef) {
205
- setTimeout(() => {
206
- this.textAreaRef?.focus();
207
- });
208
- }
209
- }
210
- }
211
- handleStartTranscribe() {
212
- this.startTranscribe.emit();
213
- this.modeSignal.set("transcribe");
214
- }
215
- handleCancelTranscribe() {
216
- this.cancelTranscribe.emit();
217
- this.modeSignal.set("input");
218
- }
219
- handleFinishTranscribe() {
220
- this.finishTranscribe.emit();
221
- this.modeSignal.set("input");
222
- }
223
- handleAddFile() {
224
- this.addFile.emit();
225
- }
226
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CopilotChatInput, deps: [], target: i0.ɵɵFactoryTarget.Component });
227
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: CopilotChatInput, isStandalone: true, selector: "copilot-chat-input", inputs: { sendButtonClass: { classPropertyName: "sendButtonClass", publicName: "sendButtonClass", isSignal: true, isRequired: false, transformFunction: null }, toolbarClass: { classPropertyName: "toolbarClass", publicName: "toolbarClass", isSignal: true, isRequired: false, transformFunction: null }, textAreaClass: { classPropertyName: "textAreaClass", publicName: "textAreaClass", isSignal: true, isRequired: false, transformFunction: null }, textAreaMaxRows: { classPropertyName: "textAreaMaxRows", publicName: "textAreaMaxRows", isSignal: true, isRequired: false, transformFunction: null }, textAreaPlaceholder: { classPropertyName: "textAreaPlaceholder", publicName: "textAreaPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, audioRecorderClass: { classPropertyName: "audioRecorderClass", publicName: "audioRecorderClass", isSignal: true, isRequired: false, transformFunction: null }, startTranscribeButtonClass: { classPropertyName: "startTranscribeButtonClass", publicName: "startTranscribeButtonClass", isSignal: true, isRequired: false, transformFunction: null }, cancelTranscribeButtonClass: { classPropertyName: "cancelTranscribeButtonClass", publicName: "cancelTranscribeButtonClass", isSignal: true, isRequired: false, transformFunction: null }, finishTranscribeButtonClass: { classPropertyName: "finishTranscribeButtonClass", publicName: "finishTranscribeButtonClass", isSignal: true, isRequired: false, transformFunction: null }, addFileButtonClass: { classPropertyName: "addFileButtonClass", publicName: "addFileButtonClass", isSignal: true, isRequired: false, transformFunction: null }, toolsButtonClass: { classPropertyName: "toolsButtonClass", publicName: "toolsButtonClass", isSignal: true, isRequired: false, transformFunction: null }, sendButtonComponent: { classPropertyName: "sendButtonComponent", publicName: "sendButtonComponent", isSignal: true, isRequired: false, transformFunction: null }, toolbarComponent: { classPropertyName: "toolbarComponent", publicName: "toolbarComponent", isSignal: true, isRequired: false, transformFunction: null }, textAreaComponent: { classPropertyName: "textAreaComponent", publicName: "textAreaComponent", isSignal: true, isRequired: false, transformFunction: null }, audioRecorderComponent: { classPropertyName: "audioRecorderComponent", publicName: "audioRecorderComponent", isSignal: true, isRequired: false, transformFunction: null }, startTranscribeButtonComponent: { classPropertyName: "startTranscribeButtonComponent", publicName: "startTranscribeButtonComponent", isSignal: true, isRequired: false, transformFunction: null }, cancelTranscribeButtonComponent: { classPropertyName: "cancelTranscribeButtonComponent", publicName: "cancelTranscribeButtonComponent", isSignal: true, isRequired: false, transformFunction: null }, finishTranscribeButtonComponent: { classPropertyName: "finishTranscribeButtonComponent", publicName: "finishTranscribeButtonComponent", isSignal: true, isRequired: false, transformFunction: null }, addFileButtonComponent: { classPropertyName: "addFileButtonComponent", publicName: "addFileButtonComponent", isSignal: true, isRequired: false, transformFunction: null }, toolsButtonComponent: { classPropertyName: "toolsButtonComponent", publicName: "toolsButtonComponent", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, toolsMenu: { classPropertyName: "toolsMenu", publicName: "toolsMenu", isSignal: true, isRequired: false, transformFunction: null }, autoFocus: { classPropertyName: "autoFocus", publicName: "autoFocus", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, inputClass: { classPropertyName: "inputClass", publicName: "inputClass", isSignal: true, isRequired: false, transformFunction: null }, additionalToolbarItems: { classPropertyName: "additionalToolbarItems", publicName: "additionalToolbarItems", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { submitMessage: "submitMessage", startTranscribe: "startTranscribe", cancelTranscribe: "cancelTranscribe", finishTranscribe: "finishTranscribe", addFile: "addFile", valueChange: "valueChange" }, host: { attributes: { "data-copilotkit": "" } }, queries: [{ propertyName: "sendButtonTemplate", first: true, predicate: ["sendButton"], descendants: true, read: TemplateRef }, { propertyName: "toolbarTemplate", first: true, predicate: ["toolbar"], descendants: true, read: TemplateRef }, { propertyName: "textAreaTemplate", first: true, predicate: ["textArea"], descendants: true, read: TemplateRef }, { propertyName: "audioRecorderTemplate", first: true, predicate: ["audioRecorder"], descendants: true, read: TemplateRef }, { propertyName: "startTranscribeButtonTemplate", first: true, predicate: ["startTranscribeButton"], descendants: true, read: TemplateRef }, { propertyName: "cancelTranscribeButtonTemplate", first: true, predicate: ["cancelTranscribeButton"], descendants: true, read: TemplateRef }, { propertyName: "finishTranscribeButtonTemplate", first: true, predicate: ["finishTranscribeButton"], descendants: true, read: TemplateRef }, { propertyName: "addFileButtonTemplate", first: true, predicate: ["addFileButton"], descendants: true, read: TemplateRef }, { propertyName: "toolsButtonTemplate", first: true, predicate: ["toolsButton"], descendants: true, read: TemplateRef }], viewQueries: [{ propertyName: "textAreaRef", first: true, predicate: CopilotChatTextarea, descendants: true, read: CopilotChatTextarea }, { propertyName: "audioRecorderRef", first: true, predicate: CopilotChatAudioRecorder, descendants: true }], ngImport: i0, template: `
228
- <div [class]="computedClass()">
229
- <!-- Main input area: either textarea or audio recorder -->
230
- @if (computedMode() === "transcribe") {
231
- @if (audioRecorderTemplate || audioRecorderComponent()) {
232
- <copilot-slot
233
- [slot]="audioRecorderTemplate || audioRecorderComponent()"
234
- [context]="audioRecorderContext()"
235
- [defaultComponent]="defaultAudioRecorder"
236
- >
237
- </copilot-slot>
238
- } @else {
239
- <copilot-chat-audio-recorder [inputShowControls]="true">
240
- </copilot-chat-audio-recorder>
241
- }
242
- } @else {
243
- @if (textAreaTemplate || textAreaComponent()) {
244
- <copilot-slot
245
- [slot]="textAreaTemplate || textAreaComponent()"
246
- [context]="textAreaContext()"
247
- >
248
- </copilot-slot>
249
- } @else {
250
- <textarea
251
- copilotChatTextarea
252
- [inputValue]="computedValue()"
253
- [inputAutoFocus]="computedAutoFocus()"
254
- [inputDisabled]="computedMode() === 'processing'"
255
- [inputClass]="textAreaClass()"
256
- [inputMaxRows]="textAreaMaxRows()"
257
- [inputPlaceholder]="textAreaPlaceholder()"
258
- (keyDown)="handleKeyDown($event)"
259
- (valueChange)="handleValueChange($event)"
260
- ></textarea>
261
- }
262
- }
263
-
264
- <!-- Toolbar -->
265
- @if (toolbarTemplate || toolbarComponent()) {
266
- <copilot-slot
267
- [slot]="toolbarTemplate || toolbarComponent()"
268
- [context]="toolbarContext()"
269
- [defaultComponent]="CopilotChatToolbar"
270
- >
271
- </copilot-slot>
272
- } @else {
273
- <div copilotChatToolbar>
274
- <div class="flex items-center">
275
- @if (addFileButtonTemplate || addFileButtonComponent()) {
276
- <copilot-slot
277
- [slot]="addFileButtonTemplate || addFileButtonComponent()"
278
- [context]="{ inputDisabled: computedMode() === 'transcribe' }"
279
- [outputs]="addFileButtonOutputs"
280
- [defaultComponent]="CopilotChatAddFileButton"
281
- >
282
- </copilot-slot>
283
- } @else {
284
- <copilot-chat-add-file-button
285
- [disabled]="computedMode() === 'transcribe'"
286
- (clicked)="handleAddFile()"
287
- >
288
- </copilot-chat-add-file-button>
289
- }
290
- @if (computedToolsMenu().length > 0) {
291
- @if (toolsButtonTemplate || toolsButtonComponent()) {
292
- <copilot-slot
293
- [slot]="toolsButtonTemplate || toolsButtonComponent()"
294
- [context]="toolsContext()"
295
- [defaultComponent]="CopilotChatToolsMenu"
296
- >
297
- </copilot-slot>
298
- } @else {
299
- <copilot-chat-tools-menu
300
- [inputToolsMenu]="computedToolsMenu()"
301
- [inputDisabled]="computedMode() === 'transcribe'"
302
- >
303
- </copilot-chat-tools-menu>
304
- }
305
- }
306
- @if (additionalToolbarItems()) {
307
- <ng-container
308
- [ngTemplateOutlet]="additionalToolbarItems() || null"
309
- ></ng-container>
310
- }
311
- </div>
312
- <div class="flex items-center">
313
- @if (computedMode() === "transcribe") {
314
- @if (
315
- cancelTranscribeButtonTemplate ||
316
- cancelTranscribeButtonComponent()
317
- ) {
318
- <copilot-slot
319
- [slot]="
320
- cancelTranscribeButtonTemplate ||
321
- cancelTranscribeButtonComponent()
322
- "
323
- [context]="{}"
324
- [outputs]="cancelTranscribeButtonOutputs"
325
- [defaultComponent]="CopilotChatCancelTranscribeButton"
326
- >
327
- </copilot-slot>
328
- } @else {
329
- <copilot-chat-cancel-transcribe-button
330
- (clicked)="handleCancelTranscribe()"
331
- >
332
- </copilot-chat-cancel-transcribe-button>
333
- }
334
- @if (
335
- finishTranscribeButtonTemplate ||
336
- finishTranscribeButtonComponent()
337
- ) {
338
- <copilot-slot
339
- [slot]="
340
- finishTranscribeButtonTemplate ||
341
- finishTranscribeButtonComponent()
342
- "
343
- [context]="{}"
344
- [outputs]="finishTranscribeButtonOutputs"
345
- [defaultComponent]="CopilotChatFinishTranscribeButton"
346
- >
347
- </copilot-slot>
348
- } @else {
349
- <copilot-chat-finish-transcribe-button
350
- (clicked)="handleFinishTranscribe()"
351
- >
352
- </copilot-chat-finish-transcribe-button>
353
- }
354
- } @else {
355
- @if (
356
- startTranscribeButtonTemplate ||
357
- startTranscribeButtonComponent()
358
- ) {
359
- <copilot-slot
360
- [slot]="
361
- startTranscribeButtonTemplate ||
362
- startTranscribeButtonComponent()
363
- "
364
- [context]="{}"
365
- [outputs]="startTranscribeButtonOutputs"
366
- [defaultComponent]="CopilotChatStartTranscribeButton"
367
- >
368
- </copilot-slot>
369
- } @else {
370
- <copilot-chat-start-transcribe-button
371
- (clicked)="handleStartTranscribe()"
372
- >
373
- </copilot-chat-start-transcribe-button>
374
- }
375
- <!-- Send button with slot -->
376
- @if (sendButtonTemplate || sendButtonComponent()) {
377
- <copilot-slot
378
- [slot]="sendButtonTemplate || sendButtonComponent()"
379
- [context]="sendButtonContext()"
380
- [outputs]="sendButtonOutputs"
381
- >
382
- </copilot-slot>
383
- } @else {
384
- <div class="mr-[10px]">
385
- <button
386
- type="button"
387
- [class]="sendButtonClass() || defaultButtonClass"
388
- [disabled]="
389
- !computedValue().trim() || computedMode() === 'processing'
390
- "
391
- (click)="send()"
392
- >
393
- <lucide-angular
394
- [img]="ArrowUpIcon"
395
- [size]="18"
396
- ></lucide-angular>
397
- </button>
398
- </div>
399
- }
400
- }
401
- </div>
402
- </div>
403
- }
404
- </div>
405
- `, isInline: true, styles: [":host{display:block;width:100%}.shadow-\\[0_4px_4px_0_\\#0000000a\\,_0_0_1px_0_\\#0000009e\\]{box-shadow:0 4px 4px #0000000a,0 0 1px #0000009e!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: CopilotSlot, selector: "copilot-slot", inputs: ["slot", "context", "defaultComponent", "outputs"] }, { kind: "ngmodule", type: LucideAngularModule }, { kind: "component", type: i2.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }, { kind: "component", type: CopilotChatTextarea, selector: "textarea[copilotChatTextarea]", inputs: ["inputValue", "inputPlaceholder", "inputMaxRows", "inputAutoFocus", "inputDisabled", "inputClass"], outputs: ["valueChange", "keyDown"] }, { kind: "component", type: CopilotChatAudioRecorder, selector: "copilot-chat-audio-recorder", inputs: ["inputClass", "inputShowControls"], outputs: ["stateChange", "error"] }, { kind: "component", type: CopilotChatStartTranscribeButton, selector: "copilot-chat-start-transcribe-button", inputs: ["disabled"], outputs: ["clicked"] }, { kind: "component", type: CopilotChatCancelTranscribeButton, selector: "copilot-chat-cancel-transcribe-button", inputs: ["disabled"], outputs: ["clicked"] }, { kind: "component", type: CopilotChatFinishTranscribeButton, selector: "copilot-chat-finish-transcribe-button", inputs: ["disabled"], outputs: ["clicked"] }, { kind: "component", type: CopilotChatAddFileButton, selector: "copilot-chat-add-file-button", inputs: ["disabled"], outputs: ["clicked"] }, { kind: "component", type: CopilotChatToolbar, selector: "div[copilotChatToolbar]", inputs: ["inputClass"] }, { kind: "component", type: CopilotChatToolsMenu, selector: "copilot-chat-tools-menu", inputs: ["inputToolsMenu", "inputDisabled", "inputClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
406
- }
407
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CopilotChatInput, decorators: [{
408
- type: Component,
409
- args: [{ standalone: true, selector: "copilot-chat-input", host: { "data-copilotkit": "" }, imports: [
410
- CommonModule,
411
- CopilotSlot,
412
- LucideAngularModule,
413
- CopilotChatTextarea,
414
- CopilotChatAudioRecorder,
415
- CopilotChatStartTranscribeButton,
416
- CopilotChatCancelTranscribeButton,
417
- CopilotChatFinishTranscribeButton,
418
- CopilotChatAddFileButton,
419
- CopilotChatToolbar,
420
- CopilotChatToolsMenu,
421
- ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: `
422
- <div [class]="computedClass()">
423
- <!-- Main input area: either textarea or audio recorder -->
424
- @if (computedMode() === "transcribe") {
425
- @if (audioRecorderTemplate || audioRecorderComponent()) {
426
- <copilot-slot
427
- [slot]="audioRecorderTemplate || audioRecorderComponent()"
428
- [context]="audioRecorderContext()"
429
- [defaultComponent]="defaultAudioRecorder"
430
- >
431
- </copilot-slot>
432
- } @else {
433
- <copilot-chat-audio-recorder [inputShowControls]="true">
434
- </copilot-chat-audio-recorder>
435
- }
436
- } @else {
437
- @if (textAreaTemplate || textAreaComponent()) {
438
- <copilot-slot
439
- [slot]="textAreaTemplate || textAreaComponent()"
440
- [context]="textAreaContext()"
441
- >
442
- </copilot-slot>
443
- } @else {
444
- <textarea
445
- copilotChatTextarea
446
- [inputValue]="computedValue()"
447
- [inputAutoFocus]="computedAutoFocus()"
448
- [inputDisabled]="computedMode() === 'processing'"
449
- [inputClass]="textAreaClass()"
450
- [inputMaxRows]="textAreaMaxRows()"
451
- [inputPlaceholder]="textAreaPlaceholder()"
452
- (keyDown)="handleKeyDown($event)"
453
- (valueChange)="handleValueChange($event)"
454
- ></textarea>
455
- }
456
- }
457
-
458
- <!-- Toolbar -->
459
- @if (toolbarTemplate || toolbarComponent()) {
460
- <copilot-slot
461
- [slot]="toolbarTemplate || toolbarComponent()"
462
- [context]="toolbarContext()"
463
- [defaultComponent]="CopilotChatToolbar"
464
- >
465
- </copilot-slot>
466
- } @else {
467
- <div copilotChatToolbar>
468
- <div class="flex items-center">
469
- @if (addFileButtonTemplate || addFileButtonComponent()) {
470
- <copilot-slot
471
- [slot]="addFileButtonTemplate || addFileButtonComponent()"
472
- [context]="{ inputDisabled: computedMode() === 'transcribe' }"
473
- [outputs]="addFileButtonOutputs"
474
- [defaultComponent]="CopilotChatAddFileButton"
475
- >
476
- </copilot-slot>
477
- } @else {
478
- <copilot-chat-add-file-button
479
- [disabled]="computedMode() === 'transcribe'"
480
- (clicked)="handleAddFile()"
481
- >
482
- </copilot-chat-add-file-button>
483
- }
484
- @if (computedToolsMenu().length > 0) {
485
- @if (toolsButtonTemplate || toolsButtonComponent()) {
486
- <copilot-slot
487
- [slot]="toolsButtonTemplate || toolsButtonComponent()"
488
- [context]="toolsContext()"
489
- [defaultComponent]="CopilotChatToolsMenu"
490
- >
491
- </copilot-slot>
492
- } @else {
493
- <copilot-chat-tools-menu
494
- [inputToolsMenu]="computedToolsMenu()"
495
- [inputDisabled]="computedMode() === 'transcribe'"
496
- >
497
- </copilot-chat-tools-menu>
498
- }
499
- }
500
- @if (additionalToolbarItems()) {
501
- <ng-container
502
- [ngTemplateOutlet]="additionalToolbarItems() || null"
503
- ></ng-container>
504
- }
505
- </div>
506
- <div class="flex items-center">
507
- @if (computedMode() === "transcribe") {
508
- @if (
509
- cancelTranscribeButtonTemplate ||
510
- cancelTranscribeButtonComponent()
511
- ) {
512
- <copilot-slot
513
- [slot]="
514
- cancelTranscribeButtonTemplate ||
515
- cancelTranscribeButtonComponent()
516
- "
517
- [context]="{}"
518
- [outputs]="cancelTranscribeButtonOutputs"
519
- [defaultComponent]="CopilotChatCancelTranscribeButton"
520
- >
521
- </copilot-slot>
522
- } @else {
523
- <copilot-chat-cancel-transcribe-button
524
- (clicked)="handleCancelTranscribe()"
525
- >
526
- </copilot-chat-cancel-transcribe-button>
527
- }
528
- @if (
529
- finishTranscribeButtonTemplate ||
530
- finishTranscribeButtonComponent()
531
- ) {
532
- <copilot-slot
533
- [slot]="
534
- finishTranscribeButtonTemplate ||
535
- finishTranscribeButtonComponent()
536
- "
537
- [context]="{}"
538
- [outputs]="finishTranscribeButtonOutputs"
539
- [defaultComponent]="CopilotChatFinishTranscribeButton"
540
- >
541
- </copilot-slot>
542
- } @else {
543
- <copilot-chat-finish-transcribe-button
544
- (clicked)="handleFinishTranscribe()"
545
- >
546
- </copilot-chat-finish-transcribe-button>
547
- }
548
- } @else {
549
- @if (
550
- startTranscribeButtonTemplate ||
551
- startTranscribeButtonComponent()
552
- ) {
553
- <copilot-slot
554
- [slot]="
555
- startTranscribeButtonTemplate ||
556
- startTranscribeButtonComponent()
557
- "
558
- [context]="{}"
559
- [outputs]="startTranscribeButtonOutputs"
560
- [defaultComponent]="CopilotChatStartTranscribeButton"
561
- >
562
- </copilot-slot>
563
- } @else {
564
- <copilot-chat-start-transcribe-button
565
- (clicked)="handleStartTranscribe()"
566
- >
567
- </copilot-chat-start-transcribe-button>
568
- }
569
- <!-- Send button with slot -->
570
- @if (sendButtonTemplate || sendButtonComponent()) {
571
- <copilot-slot
572
- [slot]="sendButtonTemplate || sendButtonComponent()"
573
- [context]="sendButtonContext()"
574
- [outputs]="sendButtonOutputs"
575
- >
576
- </copilot-slot>
577
- } @else {
578
- <div class="mr-[10px]">
579
- <button
580
- type="button"
581
- [class]="sendButtonClass() || defaultButtonClass"
582
- [disabled]="
583
- !computedValue().trim() || computedMode() === 'processing'
584
- "
585
- (click)="send()"
586
- >
587
- <lucide-angular
588
- [img]="ArrowUpIcon"
589
- [size]="18"
590
- ></lucide-angular>
591
- </button>
592
- </div>
593
- }
594
- }
595
- </div>
596
- </div>
597
- }
598
- </div>
599
- `, styles: [":host{display:block;width:100%}.shadow-\\[0_4px_4px_0_\\#0000000a\\,_0_0_1px_0_\\#0000009e\\]{box-shadow:0 4px 4px #0000000a,0 0 1px #0000009e!important}\n"] }]
600
- }], ctorParameters: () => [], propDecorators: { textAreaRef: [{
601
- type: ViewChild,
602
- args: [CopilotChatTextarea, { read: CopilotChatTextarea }]
603
- }], audioRecorderRef: [{
604
- type: ViewChild,
605
- args: [CopilotChatAudioRecorder]
606
- }], sendButtonTemplate: [{
607
- type: ContentChild,
608
- args: ["sendButton", { read: TemplateRef }]
609
- }], toolbarTemplate: [{
610
- type: ContentChild,
611
- args: ["toolbar", { read: TemplateRef }]
612
- }], textAreaTemplate: [{
613
- type: ContentChild,
614
- args: ["textArea", { read: TemplateRef }]
615
- }], audioRecorderTemplate: [{
616
- type: ContentChild,
617
- args: ["audioRecorder", { read: TemplateRef }]
618
- }], startTranscribeButtonTemplate: [{
619
- type: ContentChild,
620
- args: ["startTranscribeButton", { read: TemplateRef }]
621
- }], cancelTranscribeButtonTemplate: [{
622
- type: ContentChild,
623
- args: ["cancelTranscribeButton", { read: TemplateRef }]
624
- }], finishTranscribeButtonTemplate: [{
625
- type: ContentChild,
626
- args: ["finishTranscribeButton", { read: TemplateRef }]
627
- }], addFileButtonTemplate: [{
628
- type: ContentChild,
629
- args: ["addFileButton", { read: TemplateRef }]
630
- }], toolsButtonTemplate: [{
631
- type: ContentChild,
632
- args: ["toolsButton", { read: TemplateRef }]
633
- }] } });
634
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29waWxvdC1jaGF0LWlucHV0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9jb21wb25lbnRzL2NoYXQvY29waWxvdC1jaGF0LWlucHV0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQ1QsV0FBVyxFQUNYLE1BQU0sRUFDTixRQUFRLEVBQ1IsTUFBTSxFQUNOLHVCQUF1QixFQUl2QixpQkFBaUIsRUFDakIsWUFBWSxFQUNaLEtBQUssRUFDTCxNQUFNLEVBQ04sU0FBUyxHQUNWLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDdkQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDckQsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE9BQU8sRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzlELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQzlELE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ3pFLE9BQU8sRUFDTCxnQ0FBZ0MsRUFDaEMsaUNBQWlDLEVBQ2pDLGlDQUFpQyxFQUNqQyx3QkFBd0IsR0FDekIsTUFBTSx3QkFBd0IsQ0FBQztBQUNoQyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUM1RCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUtqRSxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ2pDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQzs7OztBQW9PbkQsTUFBTSxPQUFPLGdCQUFnQjtJQUUzQixXQUFXLENBQXVCO0lBR2xDLGdCQUFnQixDQUE0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LEVBQUU7Z0JBR3BELDZCQUE2QjtzQkFENUIsWUFBWTt1QkFBQyx1QkFBdUIsRUFBRSxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUU7Z0JBRzVELDhCQUE4QjtzQkFEN0IsWUFBWTt1QkFBQyx3QkFBd0IsRUFBRSxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUU7Z0JBRzdELDhCQUE4QjtzQkFEN0IsWUFBWTt1QkFBQyx3QkFBd0IsRUFBRSxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUU7Z0JBRzdELHFCQUFxQjtzQkFEcEIsWUFBWTt1QkFBQyxlQUFlLEVBQUUsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFO2dCQUdwRCxtQkFBbUI7c0JBRGxCLFlBQVk7dUJBQUMsYUFBYSxFQUFFLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENvbXBvbmVudCxcbiAgVGVtcGxhdGVSZWYsXG4gIHNpZ25hbCxcbiAgY29tcHV0ZWQsXG4gIGVmZmVjdCxcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIEFmdGVyVmlld0luaXQsXG4gIE9uRGVzdHJveSxcbiAgVHlwZSxcbiAgVmlld0VuY2Fwc3VsYXRpb24sXG4gIENvbnRlbnRDaGlsZCxcbiAgaW5wdXQsXG4gIG91dHB1dCxcbiAgVmlld0NoaWxkLFxufSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSBcIkBhbmd1bGFyL2NvbW1vblwiO1xuaW1wb3J0IHsgQ29waWxvdFNsb3QgfSBmcm9tIFwiLi4vLi4vc2xvdHMvY29waWxvdC1zbG90XCI7XG5pbXBvcnQgeyBpbmplY3RDaGF0TGFiZWxzIH0gZnJvbSBcIi4uLy4uL2NoYXQtY29uZmlnXCI7XG5pbXBvcnQgeyBMdWNpZGVBbmd1bGFyTW9kdWxlLCBBcnJvd1VwIH0gZnJvbSBcImx1Y2lkZS1hbmd1bGFyXCI7XG5pbXBvcnQgeyBDb3BpbG90Q2hhdFRleHRhcmVhIH0gZnJvbSBcIi4vY29waWxvdC1jaGF0LXRleHRhcmVhXCI7XG5pbXBvcnQgeyBDb3BpbG90Q2hhdEF1ZGlvUmVjb3JkZXIgfSBmcm9tIFwiLi9jb3BpbG90LWNoYXQtYXVkaW8tcmVjb3JkZXJcIjtcbmltcG9ydCB7XG4gIENvcGlsb3RDaGF0U3RhcnRUcmFuc2NyaWJlQnV0dG9uLFxuICBDb3BpbG90Q2hhdENhbmNlbFRyYW5zY3JpYmVCdXR0b24sXG4gIENvcGlsb3RDaGF0RmluaXNoVHJhbnNjcmliZUJ1dHRvbixcbiAgQ29waWxvdENoYXRBZGRGaWxlQnV0dG9uLFxufSBmcm9tIFwiLi9jb3BpbG90LWNoYXQtYnV0dG9uc1wiO1xuaW1wb3J0IHsgQ29waWxvdENoYXRUb29sYmFyIH0gZnJvbSBcIi4vY29waWxvdC1jaGF0LXRvb2xiYXJcIjtcbmltcG9ydCB7IENvcGlsb3RDaGF0VG9vbHNNZW51IH0gZnJvbSBcIi4vY29waWxvdC1jaGF0LXRvb2xzLW1lbnVcIjtcbmltcG9ydCB0eXBlIHtcbiAgQ29waWxvdENoYXRJbnB1dE1vZGUsXG4gIFRvb2xzTWVudUl0ZW0sXG59IGZyb20gXCIuL2NvcGlsb3QtY2hhdC1pbnB1dC50eXBlc1wiO1xuaW1wb3J0IHsgY24gfSBmcm9tIFwiLi4vLi4vdXRpbHNcIjtcbmltcG9ydCB7IGluamVjdENoYXRTdGF0ZSB9IGZyb20gXCIuLi8uLi9jaGF0LXN0YXRlXCI7XG5cbi8qKlxuICogQ29udGV4dCBwcm92aWRlZCB0byBzbG90IHRlbXBsYXRlc1xuICovXG5leHBvcnQgaW50ZXJmYWNlIFNlbmRCdXR0b25Db250ZXh0IHtcbiAgc2VuZDogKCkgPT4gdm9pZDtcbiAgZGlzYWJsZWQ6IGJvb2xlYW47XG4gIHZhbHVlOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVG9vbGJhckNvbnRleHQge1xuICBtb2RlOiBDb3BpbG90Q2hhdElucHV0TW9kZTtcbiAgdmFsdWU6IHN0cmluZztcbn1cblxuQENvbXBvbmVudCh7XG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIHNlbGVjdG9yOiBcImNvcGlsb3QtY2hhdC1pbnB1dFwiLFxuICBob3N0OiB7IFwiZGF0YS1jb3BpbG90a2l0XCI6IFwiXCIgfSxcbiAgaW1wb3J0czogW1xuICAgIENvbW1vbk1vZHVsZSxcbiAgICBDb3BpbG90U2xvdCxcbiAgICBMdWNpZGVBbmd1bGFyTW9kdWxlLFxuICAgIENvcGlsb3RDaGF0VGV4dGFyZWEsXG4gICAgQ29waWxvdENoYXRBdWRpb1JlY29yZGVyLFxuICAgIENvcGlsb3RDaGF0U3RhcnRUcmFuc2NyaWJlQnV0dG9uLFxuICAgIENvcGlsb3RDaGF0Q2FuY2VsVHJhbnNjcmliZUJ1dHRvbixcbiAgICBDb3BpbG90Q2hhdEZpbmlzaFRyYW5zY3JpYmVCdXR0b24sXG4gICAgQ29waWxvdENoYXRBZGRGaWxlQnV0dG9uLFxuICAgIENvcGlsb3RDaGF0VG9vbGJhcixcbiAgICBDb3BpbG90Q2hhdFRvb2xzTWVudSxcbiAgXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiBbY2xhc3NdPVwiY29tcHV0ZWRDbGFzcygpXCI+XG4gICAgICA8IS0tIE1haW4gaW5wdXQgYXJlYTogZWl0aGVyIHRleHRhcmVhIG9yIGF1ZGlvIHJlY29yZGVyIC0tPlxuICAgICAgQGlmIChjb21wdXRlZE1vZGUoKSA9PT0gXCJ0cmFuc2NyaWJlXCIpIHtcbiAgICAgICAgQGlmIChhdWRpb1JlY29yZGVyVGVtcGxhdGUgfHwgYXVkaW9SZWNvcmRlckNvbXBvbmVudCgpKSB7XG4gICAgICAgICAgPGNvcGlsb3Qtc2xvdFxuICAgICAgICAgICAgW3Nsb3RdPVwiYXVkaW9SZWNvcmRlclRlbXBsYXRlIHx8IGF1ZGlvUmVjb3JkZXJDb21wb25lbnQoKVwiXG4gICAgICAgICAgICBbY29udGV4dF09XCJhdWRpb1JlY29yZGVyQ29udGV4dCgpXCJcbiAgICAgICAgICAgIFtkZWZhdWx0Q29tcG9uZW50XT1cImRlZmF1bHRBdWRpb1JlY29yZGVyXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgPC9jb3BpbG90LXNsb3Q+XG4gICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgIDxjb3BpbG90LWNoYXQtYXVkaW8tcmVjb3JkZXIgW2lucHV0U2hvd0NvbnRyb2xzXT1cInRydWVcIj5cbiAgICAgICAgICA8L2NvcGlsb3QtY2hhdC1hdWRpby1yZWNvcmRlcj5cbiAgICAgICAgfVxuICAgICAgfSBAZWxzZSB7XG4gICAgICAgIEBpZiAodGV4dEFyZWFUZW1wbGF0ZSB8fCB0ZXh0QXJlYUNvbXBvbmVudCgpKSB7XG4gICAgICAgICAgPGNvcGlsb3Qtc2xvdFxuICAgICAgICAgICAgW3Nsb3RdPVwidGV4dEFyZWFUZW1wbGF0ZSB8fCB0ZXh0QXJlYUNvbXBvbmVudCgpXCJcbiAgICAgICAgICAgIFtjb250ZXh0XT1cInRleHRBcmVhQ29udGV4dCgpXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgPC9jb3BpbG90LXNsb3Q+XG4gICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgIDx0ZXh0YXJlYVxuICAgICAgICAgICAgY29waWxvdENoYXRUZXh0YXJlYVxuICAgICAgICAgICAgW2lucHV0VmFsdWVdPVwiY29tcHV0ZWRWYWx1ZSgpXCJcbiAgICAgICAgICAgIFtpbnB1dEF1dG9Gb2N1c109XCJjb21wdXRlZEF1dG9Gb2N1cygpXCJcbiAgICAgICAgICAgIFtpbnB1dERpc2FibGVkXT1cImNvbXB1dGVkTW9kZSgpID09PSAncHJvY2Vzc2luZydcIlxuICAgICAgICAgICAgW2lucHV0Q2xhc3NdPVwidGV4dEFyZWFDbGFzcygpXCJcbiAgICAgICAgICAgIFtpbnB1dE1heFJvd3NdPVwidGV4dEFyZWFNYXhSb3dzKClcIlxuICAgICAgICAgICAgW2lucHV0UGxhY2Vob2xkZXJdPVwidGV4dEFyZWFQbGFjZWhvbGRlcigpXCJcbiAgICAgICAgICAgIChrZXlEb3duKT1cImhhbmRsZUtleURvd24oJGV2ZW50KVwiXG4gICAgICAgICAgICAodmFsdWVDaGFuZ2UpPVwiaGFuZGxlVmFsdWVDaGFuZ2UoJGV2ZW50KVwiXG4gICAgICAgICAgPjwvdGV4dGFyZWE+XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgPCEtLSBUb29sYmFyIC0tPlxuICAgICAgQGlmICh0b29sYmFyVGVtcGxhdGUgfHwgdG9vbGJhckNvbXBvbmVudCgpKSB7XG4gICAgICAgIDxjb3BpbG90LXNsb3RcbiAgICAgICAgICBbc2xvdF09XCJ0b29sYmFyVGVtcGxhdGUgfHwgdG9vbGJhckNvbXBvbmVudCgpXCJcbiAgICAgICAgICBbY29udGV4dF09XCJ0b29sYmFyQ29udGV4dCgpXCJcbiAgICAgICAgICBbZGVmYXVsdENvbXBvbmVudF09XCJDb3BpbG90Q2hhdFRvb2xiYXJcIlxuICAgICAgICA+XG4gICAgICAgIDwvY29waWxvdC1zbG90PlxuICAgICAgfSBAZWxzZSB7XG4gICAgICAgIDxkaXYgY29waWxvdENoYXRUb29sYmFyPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGl0ZW1zLWNlbnRlclwiPlxuICAgICAgICAgICAgQGlmIChhZGRGaWxlQnV0dG9uVGVtcGxhdGUgfHwgYWRkRmlsZUJ1dHRvbkNvbXBvbmVudCgpKSB7XG4gICAgICAgICAgICAgIDxjb3BpbG90LXNsb3RcbiAgICAgICAgICAgICAgICBbc2xvdF09XCJhZGRGaWxlQnV0dG9uVGVtcGxhdGUgfHwgYWRkRmlsZUJ1dHRvbkNvbXBvbmVudCgpXCJcbiAgICAgICAgICAgICAgICBbY29udGV4dF09XCJ7IGlucHV0RGlzYWJsZWQ6IGNvbXB1dGVkTW9kZSgpID09PSAndHJhbnNjcmliZScgfVwiXG4gICAgICAgICAgICAgICAgW291dHB1dHNdPVwiYWRkRmlsZUJ1dHRvbk91dHB1dHNcIlxuICAgICAgICAgICAgICAgIFtkZWZhdWx0Q29tcG9uZW50XT1cIkNvcGlsb3RDaGF0QWRkRmlsZUJ1dHRvblwiXG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgPC9jb3BpbG90LXNsb3Q+XG4gICAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgICAgPGNvcGlsb3QtY2hhdC1hZGQtZmlsZS1idXR0b25cbiAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiY29tcHV0ZWRNb2RlKCkgPT09ICd0cmFuc2NyaWJlJ1wiXG4gICAgICAgICAgICAgICAgKGNsaWNrZWQpPVwiaGFuZGxlQWRkRmlsZSgpXCJcbiAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICA8L2NvcGlsb3QtY2hhdC1hZGQtZmlsZS1idXR0b24+XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBAaWYgKGNvbXB1dGVkVG9vbHNNZW51KCkubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICBAaWYgKHRvb2xzQnV0dG9uVGVtcGxhdGUgfHwgdG9vbHNCdXR0b25Db21wb25lbnQoKSkge1xuICAgICAgICAgICAgICAgIDxjb3BpbG90LXNsb3RcbiAgICAgICAgICAgICAgICAgIFtzbG90XT1cInRvb2xzQnV0dG9uVGVtcGxhdGUgfHwgdG9vbHNCdXR0b25Db21wb25lbnQoKVwiXG4gICAgICAgICAgICAgICAgICBbY29udGV4dF09XCJ0b29sc0NvbnRleHQoKVwiXG4gICAgICAgICAgICAgICAgICBbZGVmYXVsdENvbXBvbmVudF09XCJDb3BpbG90Q2hhdFRvb2xzTWVudVwiXG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgIDwvY29waWxvdC1zbG90PlxuICAgICAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgICAgICA8Y29waWxvdC1jaGF0LXRvb2xzLW1lbnVcbiAgICAgICAgICAgICAgICAgIFtpbnB1dFRvb2xzTWVudV09XCJjb21wdXRlZFRvb2xzTWVudSgpXCJcbiAgICAgICAgICAgICAgICAgIFtpbnB1dERpc2FibGVkXT1cImNvbXB1dGVkTW9kZSgpID09PSAndHJhbnNjcmliZSdcIlxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICA8L2NvcGlsb3QtY2hhdC10b29scy1tZW51PlxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBAaWYgKGFkZGl0aW9uYWxUb29sYmFySXRlbXMoKSkge1xuICAgICAgICAgICAgICA8bmctY29udGFpbmVyXG4gICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRdPVwiYWRkaXRpb25hbFRvb2xiYXJJdGVtcygpIHx8IG51bGxcIlxuICAgICAgICAgICAgICA+PC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICB9XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImZsZXggaXRlbXMtY2VudGVyXCI+XG4gICAgICAgICAgICBAaWYgKGNvbXB1dGVkTW9kZSgpID09PSBcInRyYW5zY3JpYmVcIikge1xuICAgICAgICAgICAgICBAaWYgKFxuICAgICAgICAgICAgICAgIGNhbmNlbFRyYW5zY3JpYmVCdXR0b25UZW1wbGF0ZSB8fFxuICAgICAgICAgICAgICAgIGNhbmNlbFRyYW5zY3JpYmVCdXR0b25Db21wb25lbnQoKVxuICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICA8Y29waWxvdC1zbG90XG4gICAgICAgICAgICAgICAgICBbc2xvdF09XCJcbiAgICAgICAgICAgICAgICAgICAgY2FuY2VsVHJhbnNjcmliZUJ1dHRvblRlbXBsYXRlIHx8XG4gICAgICAgICAgICAgICAgICAgIGNhbmNlbFRyYW5zY3JpYmVCdXR0b25Db21wb25lbnQoKVxuICAgICAgICAgICAgICAgICAgXCJcbiAgICAgICAgICAgICAgICAgIFtjb250ZXh0XT1cInt9XCJcbiAgICAgICAgICAgICAgICAgIFtvdXRwdXRzXT1cImNhbmNlbFRyYW5zY3JpYmVCdXR0b25PdXRwdXRzXCJcbiAgICAgICAgICAgICAgICAgIFtkZWZhdWx0Q29tcG9uZW50XT1cIkNvcGlsb3RDaGF0Q2FuY2VsVHJhbnNjcmliZUJ1dHRvblwiXG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgIDwvY29waWxvdC1zbG90PlxuICAgICAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgICAgICA8Y29waWxvdC1jaGF0LWNhbmNlbC10cmFuc2NyaWJlLWJ1dHRvblxuICAgICAgICAgICAgICAgICAgKGNsaWNrZWQpPVwiaGFuZGxlQ2FuY2VsVHJhbnNjcmliZSgpXCJcbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPC9jb3BpbG90LWNoYXQtY2FuY2VsLXRyYW5zY3JpYmUtYnV0dG9uPlxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIEBpZiAoXG4gICAgICAgICAgICAgICAgZmluaXNoVHJhbnNjcmliZUJ1dHRvblRlbXBsYXRlIHx8XG4gICAgICAgICAgICAgICAgZmluaXNoVHJhbnNjcmliZUJ1dHRvbkNvbXBvbmVudCgpXG4gICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIDxjb3BpbG90LXNsb3RcbiAgICAgICAgICAgICAgICAgIFtzbG90XT1cIlxuICAgICAgICAgICAgICAgICAgICBmaW5pc2hUcmFuc2NyaWJlQnV0dG9uVGVtcGxhdGUgfHxcbiAgICAgICAgICAgICAgICAgICAgZmluaXNoVHJhbnNjcmliZUJ1dHRvbkNvbXBvbmVudCgpXG4gICAgICAgICAgICAgICAgICBcIlxuICAgICAgICAgICAgICAgICAgW2NvbnRleHRdPVwie31cIlxuICAgICAgICAgICAgICAgICAgW291dHB1dHNdPVwiZmluaXNoVHJhbnNjcmliZUJ1dHRvbk91dHB1dHNcIlxuICAgICAgICAgICAgICAgICAgW2RlZmF1bHRDb21wb25lbnRdPVwiQ29waWxvdENoYXRGaW5pc2hUcmFuc2NyaWJlQnV0dG9uXCJcbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPC9jb3BpbG90LXNsb3Q+XG4gICAgICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAgICAgIDxjb3BpbG90LWNoYXQtZmluaXNoLXRyYW5zY3JpYmUtYnV0dG9uXG4gICAgICAgICAgICAgICAgICAoY2xpY2tlZCk9XCJoYW5kbGVGaW5pc2hUcmFuc2NyaWJlKClcIlxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICA8L2NvcGlsb3QtY2hhdC1maW5pc2gtdHJhbnNjcmliZS1idXR0b24+XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAgICBAaWYgKFxuICAgICAgICAgICAgICAgIHN0YXJ0VHJhbnNjcmliZUJ1dHRvblRlbXBsYXRlIHx8XG4gICAgICAgICAgICAgICAgc3RhcnRUcmFuc2NyaWJlQnV0dG9uQ29tcG9uZW50KClcbiAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgPGNvcGlsb3Qtc2xvdFxuICAgICAgICAgICAgICAgICAgW3Nsb3RdPVwiXG4gICAgICAgICAgICAgICAgICAgIHN0YXJ0VHJhbnNjcmliZUJ1dHRvblRlbXBsYXRlIHx8XG4gICAgICAgICAgICAgICAgICAgIHN0YXJ0VHJhbnNjcmliZUJ1dHRvbkNvbXBvbmVudCgpXG4gICAgICAgICAgICAgICAgICBcIlxuICAgICAgICAgICAgICAgICAgW2NvbnRleHRdPVwie31cIlxuICAgICAgICAgICAgICAgICAgW291dHB1dHNdPVwic3RhcnRUcmFuc2NyaWJlQnV0dG9uT3V0cHV0c1wiXG4gICAgICAgICAgICAgICAgICBbZGVmYXVsdENvbXBvbmVudF09XCJDb3BpbG90Q2hhdFN0YXJ0VHJhbnNjcmliZUJ1dHRvblwiXG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgIDwvY29waWxvdC1zbG90PlxuICAgICAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgICAgICA8Y29waWxvdC1jaGF0LXN0YXJ0LXRyYW5zY3JpYmUtYnV0dG9uXG4gICAgICAgICAgICAgICAgICAoY2xpY2tlZCk9XCJoYW5kbGVTdGFydFRyYW5zY3JpYmUoKVwiXG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgIDwvY29waWxvdC1jaGF0LXN0YXJ0LXRyYW5zY3JpYmUtYnV0dG9uPlxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIDwhLS0gU2VuZCBidXR0b24gd2l0aCBzbG90IC0tPlxuICAgICAgICAgICAgICBAaWYgKHNlbmRCdXR0b25UZW1wbGF0ZSB8fCBzZW5kQnV0dG9uQ29tcG9uZW50KCkpIHtcbiAgICAgICAgICAgICAgICA8Y29waWxvdC1zbG90XG4gICAgICAgICAgICAgICAgICBbc2xvdF09XCJzZW5kQnV0dG9uVGVtcGxhdGUgfHwgc2VuZEJ1dHRvbkNvbXBvbmVudCgpXCJcbiAgICAgICAgICAgICAgICAgIFtjb250ZXh0XT1cInNlbmRCdXR0b25Db250ZXh0KClcIlxuICAgICAgICAgICAgICAgICAgW291dHB1dHNdPVwic2VuZEJ1dHRvbk91dHB1dHNcIlxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICA8L2NvcGlsb3Qtc2xvdD5cbiAgICAgICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1yLVsxMHB4XVwiPlxuICAgICAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgICAgICAgW2NsYXNzXT1cInNlbmRCdXR0b25DbGFzcygpIHx8IGRlZmF1bHRCdXR0b25DbGFzc1wiXG4gICAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJcbiAgICAgICAgICAgICAgICAgICAgICAhY29tcHV0ZWRWYWx1ZSgpLnRyaW0oKSB8fCBjb21wdXRlZE1vZGUoKSA9PT0gJ3Byb2Nlc3NpbmcnXG4gICAgICAgICAgICAgICAgICAgIFwiXG4gICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJzZW5kKClcIlxuICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICA8bHVjaWRlLWFuZ3VsYXJcbiAgICAgICAgICAgICAgICAgICAgICBbaW1nXT1cIkFycm93VXBJY29uXCJcbiAgICAgICAgICAgICAgICAgICAgICBbc2l6ZV09XCIxOFwiXG4gICAgICAgICAgICAgICAgICAgID48L2x1Y2lkZS1hbmd1bGFyPlxuICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICB9XG4gICAgPC9kaXY+XG4gIGAsXG4gIHN0eWxlczogW1xuICAgIGBcbiAgICAgIDpob3N0IHtcbiAgICAgICAgZGlzcGxheTogYmxvY2s7XG4gICAgICAgIHdpZHRoOiAxMDAlO1xuICAgICAgfVxuICAgICAgLnNoYWRvdy1cXFxcWzBfNHB4XzRweF8wX1xcXFwjMDAwMDAwMGFcXFxcMmNfMF8wXzFweF8wX1xcXFwjMDAwMDAwOWVcXFxcXSB7XG4gICAgICAgIGJveC1zaGFkb3c6XG4gICAgICAgICAgMCA0cHggNHB4IDAgIzAwMDAwMDBhLFxuICAgICAgICAgIDAgMCAxcHggMCAjMDAwMDAwOWUgIWltcG9ydGFudDtcbiAgICAgIH1cbiAgICBgLFxuICBdLFxufSlcbmV4cG9ydCBjbGFzcyBDb3BpbG90Q2hhdElucHV0IGltcGxlbWVudHMgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95IHtcbiAgQFZpZXdDaGlsZChDb3BpbG90Q2hhdFRleHRhcmVhLCB7IHJlYWQ6IENvcGlsb3RDaGF0VGV4dGFyZWEgfSlcbiAgdGV4dEFyZWFSZWY/OiBDb3BpbG90Q2hhdFRleHRhcmVhO1xuXG4gIEBWaWV3Q2hpbGQoQ29waWxvdENoYXRBdWRpb1JlY29yZGVyKVxuICBhdWRpb1JlY29yZGVyUmVmPzogQ29waWxvdENoYXRBdWRpb1JlY29yZGVyO1xuXG4gIC8vIENhcHR1cmUgdGVtcGxhdGVzIGZyb20gY29udGVudCBwcm9qZWN0aW9uXG4gIEBDb250ZW50Q2hpbGQoXCJzZW5kQnV0dG9uXCIsIHsgcmVhZDogVGVtcGxhdGVSZWYgfSlcbiAgc2VuZEJ1dHRvblRlbXBsYXRlPzogVGVtcGxhdGVSZWY8U2VuZEJ1dHRvbkNvbnRleHQ+O1xuICBAQ29udGVudENoaWxkKFwidG9vbGJhclwiLCB7IHJlYWQ6IFRlbXBsYXRlUmVmIH0pXG4gIHRvb2xiYXJUZW1wbGF0ZT86IFRlbXBsYXRlUmVmPFRvb2xiYXJDb250ZXh0PjtcbiAgQENvbnRlbnRDaGlsZChcInRleHRBcmVhXCIsIHsgcmVhZDogVGVtcGxhdGVSZWYgfSlcbiAgdGV4dEFyZWFUZW1wbGF0ZT86IFRlbXBsYXRlUmVmPGFueT47XG4gIEBDb250ZW50Q2hpbGQoXCJhdWRpb1JlY29yZGVyXCIsIHsgcmVhZDogVGVtcGxhdGVSZWYgfSlcbiAgYXVkaW9SZWNvcmRlclRlbXBsYXRlPzogVGVtcGxhdGVSZWY8YW55PjtcbiAgQENvbnRlbnRDaGlsZChcInN0YXJ0VHJhbnNjcmliZUJ1dHRvblwiLCB7IHJlYWQ6IFRlbXBsYXRlUmVmIH0pXG4gIHN0YXJ0VHJhbnNjcmliZUJ1dHRvblRlbXBsYXRlPzogVGVtcGxhdGVSZWY8YW55PjtcbiAgQENvbnRlbnRDaGlsZChcImNhbmNlbFRyYW5zY3JpYmVCdXR0b25cIiwgeyByZWFkOiBUZW1wbGF0ZVJlZiB9KVxuICBjYW5jZWxUcmFuc2NyaWJlQnV0dG9uVGVtcGxhdGU/OiBUZW1wbGF0ZVJlZjxhbnk+O1xuICBAQ29udGVudENoaWxkKFwiZmluaXNoVHJhbnNjcmliZUJ1dHRvblwiLCB7IHJlYWQ6IFRlbXBsYXRlUmVmIH0pXG4gIGZpbmlzaFRyYW5zY3JpYmVCdXR0b25UZW1wbGF0ZT86IFRlbXBsYXRlUmVmPGFueT47XG4gIEBDb250ZW50Q2hpbGQoXCJhZGRGaWxlQnV0dG9uXCIsIHsgcmVhZDogVGVtcGxhdGVSZWYgfSlcbiAgYWRkRmlsZUJ1dHRvblRlbXBsYXRlPzogVGVtcGxhdGVSZWY8YW55PjtcbiAgQENvbnRlbnRDaGlsZChcInRvb2xzQnV0dG9uXCIsIHsgcmVhZDogVGVtcGxhdGVSZWYgfSlcbiAgdG9vbHNCdXR0b25UZW1wbGF0ZT86IFRlbXBsYXRlUmVmPGFueT47XG5cbiAgLy8gQ2xhc3MgaW5wdXRzIGZvciBzdHlsaW5nIGRlZmF1bHQgY29tcG9uZW50c1xuICBzZW5kQnV0dG9uQ2xhc3MgPSBpbnB1dDxzdHJpbmcgfCB1bmRlZmluZWQ+KHVuZGVmaW5lZCk7XG4gIHRvb2xiYXJDbGFzcyA9IGlucHV0PHN0cmluZyB8IHVuZGVmaW5lZD4odW5kZWZpbmVkKTtcbiAgdGV4dEFyZWFDbGFzcyA9IGlucHV0PHN0cmluZyB8IHVuZGVmaW5lZD4odW5kZWZpbmVkKTtcbiAgdGV4dEFyZWFNYXhSb3dzID0gaW5wdXQ8bnVtYmVyIHwgdW5kZWZpbmVkPih1bmRlZmluZWQpO1xuICB0ZXh0QXJlYVBsYWNlaG9sZGVyID0gaW5wdXQ8c3RyaW5nIHwgdW5kZWZpbmVkPih1bmRlZmluZWQpO1xuICBhdWRpb1JlY29yZGVyQ2xhc3MgPSBpbnB1dDxzdHJpbmcgfCB1bmRlZmluZWQ+KHVuZGVmaW5lZCk7XG4gIHN0YXJ0VHJhbnNjcmliZUJ1dHRvbkNsYXNzID0gaW5wdXQ8c3RyaW5nIHwgdW5kZWZpbmVkPih1bmRlZmluZWQpO1xuICBjYW5jZWxUcmFuc2NyaWJlQnV0dG9uQ2xhc3MgPSBpbnB1dDxzdHJpbmcgfCB1bmRlZmluZWQ+KHVuZGVmaW5lZCk7XG4gIGZpbmlzaFRyYW5zY3JpYmVCdXR0b25DbGFzcyA9IGlucHV0PHN0cmluZyB8IHVuZGVmaW5lZD4odW5kZWZpbmVkKTtcbiAgYWRkRmlsZUJ1dHRvbkNsYXNzID0gaW5wdXQ8c3RyaW5nIHwgdW5kZWZpbmVkPih1bmRlZmluZWQpO1xuICB0b29sc0J1dHRvbkNsYXNzID0gaW5wdXQ8c3RyaW5nIHwgdW5kZWZpbmVkPih1bmRlZmluZWQpO1xuXG4gIC8vIENvbXBvbmVudCBpbnB1dHMgZm9yIG92ZXJyaWRlc1xuICBzZW5kQnV0dG9uQ29tcG9uZW50ID0gaW5wdXQ8VHlwZTxhbnk+IHwgdW5kZWZpbmVkPih1bmRlZmluZWQpO1xuICB0b29sYmFyQ29tcG9uZW50ID0gaW5wdXQ8VHlwZTxhbnk+IHwgdW5kZWZpbmVkPih1bmRlZmluZWQpO1xuICB0ZXh0QXJlYUNvbXBvbmVudCA9IGlucHV0PFR5cGU8YW55PiB8IHVuZGVmaW5lZD4odW5kZWZpbmVkKTtcbiAgYXVkaW9SZWNvcmRlckNvbXBvbmVudCA9IGlucHV0PFR5cGU8YW55PiB8IHVuZGVmaW5lZD4odW5kZWZpbmVkKTtcbiAgc3RhcnRUcmFuc2NyaWJlQnV0dG9uQ29tcG9uZW50ID0gaW5wdXQ8VHlwZTxhbnk+IHwgdW5kZWZpbmVkPih1bmRlZmluZWQpO1xuICBjYW5jZWxUcmFuc2NyaWJlQnV0dG9uQ29tcG9uZW50ID0gaW5wdXQ8VHlwZTxhbnk+IHwgdW5kZWZpbmVkPih1bmRlZmluZWQpO1xuICBmaW5pc2hUcmFuc2NyaWJlQnV0dG9uQ29tcG9uZW50ID0gaW5wdXQ8VHlwZTxhbnk+IHwgdW5kZWZpbmVkPih1bmRlZmluZWQpO1xuICBhZGRGaWxlQnV0dG9uQ29tcG9uZW50ID0gaW5wdXQ8VHlwZTxhbnk+IHwgdW5kZWZpbmVkPih1bmRlZmluZWQpO1xuICB0b29sc0J1dHRvbkNvbXBvbmVudCA9IGlucHV0PFR5cGU8YW55PiB8IHVuZGVmaW5lZD4odW5kZWZpbmVkKTtcblxuICAvLyBSZWd1bGFyIGlucHV0c1xuICBtb2RlID0gaW5wdXQ8Q29waWxvdENoYXRJbnB1dE1vZGUgfCB1bmRlZmluZWQ+KHVuZGVmaW5lZCk7XG4gIHRvb2xzTWVudSA9IGlucHV0PChUb29sc01lbnVJdGVtIHwgXCItXCIpW10gfCB1bmRlZmluZWQ+KHVuZGVmaW5lZCk7XG4gIGF1dG9Gb2N1cyA9IGlucHV0PGJvb2xlYW4gfCB1bmRlZmluZWQ+KHVuZGVmaW5lZCk7XG4gIHZhbHVlID0gaW5wdXQ8c3RyaW5nIHwgdW5kZWZpbmVkPih1bmRlZmluZWQpO1xuICBpbnB1dENsYXNzID0gaW5wdXQ8c3RyaW5nIHwgdW5kZWZpbmVkPih1bmRlZmluZWQpO1xuICAvLyBOb3RlOiBQcmVmZXIgaG9zdCBgY2xhc3NgIGZvciBzdHlsaW5nIHRoaXMgY29tcG9uZW50O1xuICAvLyBrZWVwIG9ubHkgYGlucHV0Q2xhc3NgIHRvIHN0eWxlIHRoZSBpbnRlcm5hbCB3cmFwcGVyIGlmIG5lZWRlZC5cbiAgYWRkaXRpb25hbFRvb2xiYXJJdGVtcyA9IGlucHV0PFRlbXBsYXRlUmVmPGFueT4gfCB1bmRlZmluZWQ+KHVuZGVmaW5lZCk7XG5cbiAgLy8gT3V0cHV0IGV2ZW50c1xuICBzdWJtaXRNZXNzYWdlID0gb3V0cHV0PHN0cmluZz4oKTtcbiAgc3RhcnRUcmFuc2NyaWJlID0gb3V0cHV0PHZvaWQ+KCk7XG4gIGNhbmNlbFRyYW5zY3JpYmUgPSBvdXRwdXQ8dm9pZD4oKTtcbiAgZmluaXNoVHJhbnNjcmliZSA9IG91dHB1dDx2b2lkPigpO1xuICBhZGRGaWxlID0gb3V0cHV0PHZvaWQ+KCk7XG4gIHZhbHVlQ2hhbmdlID0gb3V0cHV0PHN0cmluZz4oKTtcblxuICAvLyBJY29ucyBhbmQgZGVmYXVsdCBjbGFzc2VzXG4gIHJlYWRvbmx5IEFycm93VXBJY29uID0gQXJyb3dVcDtcbiAgcmVhZG9ubHkgZGVmYXVsdEJ1dHRvbkNsYXNzID0gY24oXG4gICAgLy8gQmFzZSBidXR0b24gc3R5bGVzXG4gICAgXCJpbmxpbmUtZmxleCBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgZ2FwLTIgd2hpdGVzcGFjZS1ub3dyYXAgcm91bmRlZC1tZCB0ZXh0LXNtIGZvbnQtbWVkaXVtXCIsXG4gICAgXCJ0cmFuc2l0aW9uLWFsbCBkaXNhYmxlZDpwb2ludGVyLWV2ZW50cy1ub25lIGRpc2FibGVkOm9wYWNpdHktNTBcIixcbiAgICBcInNocmluay0wIG91dGxpbmUtbm9uZVwiLFxuICAgIFwiZm9jdXMtdmlzaWJsZTpib3JkZXItcmluZyBmb2N1cy12aXNpYmxlOnJpbmctcmluZy81MCBmb2N1cy12aXNpYmxlOnJpbmctWzNweF1cIixcbiAgICAvLyBjaGF0SW5wdXRUb29sYmFyUHJpbWFyeSB2YXJpYW50XG4gICAgXCJjdXJzb3ItcG9pbnRlclwiLFxuICAgIFwiYmctYmxhY2sgdGV4dC13aGl0ZVwiLFxuICAgIFwiZGFyazpiZy13aGl0ZSBkYXJrOnRleHQtYmxhY2sgZGFyazpmb2N1cy12aXNpYmxlOm91dGxpbmUtd2hpdGVcIixcbiAgICBcInJvdW5kZWQtZnVsbCBoLTkgdy05XCIsXG4gICAgXCJ0cmFuc2l0aW9uLWNvbG9yc1wiLFxuICAgIFwiZm9jdXM6b3V0bGluZS1ub25lXCIsXG4gICAgXCJob3ZlcjpvcGFjaXR5LTcwIGRpc2FibGVkOmhvdmVyOm9wYWNpdHktMTAwXCIsXG4gICAgXCJkaXNhYmxlZDpjdXJzb3Itbm90LWFsbG93ZWQgZGlzYWJsZWQ6YmctWyMwMDAwMDAxNF0gZGlzYWJsZWQ6dGV4dC1bcmdiKDEzLDEzLDEzKV1cIixcbiAgICBcImRhcms6ZGlzYWJsZWQ6YmctWyM0NTQ1NDVdIGRhcms6ZGlzYWJsZWQ6dGV4dC13aGl0ZVwiLFxuICApO1xuXG4gIC8vIFNlcnZpY2VzXG4gIHJlYWRvbmx5IGxhYmVscyA9IGluamVjdENoYXRMYWJlbHMoKTtcbiAgLy8gcmVhZG9ubHkgY2hhdENvbmZpZyA9IGluamVjdENoYXRDb25maWcoKTtcbiAgcmVhZG9ubHkgY2hhdFN0YXRlID0gaW5qZWN0Q2hhdFN0YXRlKCk7XG5cbiAgLy8gU2lnbmFsc1xuICBtb2RlU2lnbmFsID0gc2lnbmFsPENvcGlsb3RDaGF0SW5wdXRNb2RlPihcImlucHV0XCIpO1xuICB0b29sc01lbnVTaWduYWwgPSBzaWduYWw8KFRvb2xzTWVudUl0ZW0gfCBcIi1cIilbXT4oW10pO1xuICBhdXRvRm9jdXNTaWduYWwgPSBzaWduYWw8Ym9vbGVhbj4odHJ1ZSk7XG4gIGN1c3RvbUNsYXNzID0gc2lnbmFsPHN0cmluZyB8IHVuZGVmaW5lZD4odW5kZWZpbmVkKTtcblxuICAvLyBEZWZhdWx0IGNvbXBvbmVudHNcbiAgLy8gTm90ZTogQ29waWxvdENoYXRUZXh0YXJlYSB1c2VzIGF0dHJpYnV0ZSBzZWxlY3RvciBidXQgaXMgYSBjb21wb25lbnRcbiAgZGVmYXVsdEF1ZGlvUmVjb3JkZXIgPSBDb3BpbG90Q2hhdEF1ZGlvUmVjb3JkZXI7XG4gIGRlZmF1bHRTZW5kQnV0dG9uOiBhbnkgPSBudWxsOyAvLyBXaWxsIGJlIHNldCB0byBhdm9pZCBjaXJjdWxhciBkZXBlbmRlbmN5XG4gIENvcGlsb3RDaGF0VG9vbGJhciA9IENvcGlsb3RDaGF0VG9vbGJhcjtcbiAgQ29waWxvdENoYXRBZGRGaWxlQnV0dG9uID0gQ29waWxvdENoYXRBZGRGaWxlQnV0dG9uO1xuICBDb3BpbG90Q2hhdFRvb2xzTWVudSA9IENvcGlsb3RDaGF0VG9vbHNNZW51O1xuICBDb3BpbG90Q2hhdENhbmNlbFRyYW5zY3JpYmVCdXR0b24gPSBDb3BpbG90Q2hhdENhbmNlbFRyYW5zY3JpYmVCdXR0b247XG4gIENvcGlsb3RDaGF0RmluaXNoVHJhbnNjcmliZUJ1dHRvbiA9IENvcGlsb3RDaGF0RmluaXNoVHJhbnNjcmliZUJ1dHRvbjtcbiAgQ29waWxvdENoYXRTdGFydFRyYW5zY3JpYmVCdXR0b24gPSBDb3BpbG90Q2hhdFN0YXJ0VHJhbnNjcmliZUJ1dHRvbjtcblxuICAvLyBDb21wdXRlZCB2YWx1ZXNcbiAgY29tcHV0ZWRNb2RlID0gY29tcHV0ZWQoKCkgPT4gdGhpcy5tb2RlU2lnbmFsKCkpO1xuICBjb21wdXRlZFRvb2xzTWVudSA9IGNvbXB1dGVkKCgpID0+IHRoaXMudG9vbHNNZW51KCkgPz8gW10pO1xuICBjb21wdXRlZEF1dG9Gb2N1cyA9IGNvbXB1dGVkKCgpID0+IHRoaXMuYXV0b0ZvY3VzKCkgPz8gdHJ1ZSk7XG4gIGNvbXB1dGVkVmFsdWUgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgY29uc3QgY3VzdG9tVmFsdWUgPSB0aGlzLnZhbHVlKCkgPz8gXCJcIjtcbiAgICBjb25zdCBjb25maWdWYWx1ZSA9IHRoaXMuY2hhdFN0YXRlLmlucHV0VmFsdWUoKTtcbiAgICByZXR1cm4gY3VzdG9tVmFsdWUgfHwgY29uZmlnVmFsdWUgfHwgXCJcIjtcbiAgfSk7XG5cbiAgY29tcHV0ZWRDbGFzcyA9IGNvbXB1dGVkKCgpID0+IHtcbiAgICBjb25zdCBiYXNlQ2xhc3NlcyA9IGNuKFxuICAgICAgLy8gTGF5b3V0XG4gICAgICBcImZsZXggdy1mdWxsIGZsZXgtY29sIGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNlbnRlclwiLFxuICAgICAgLy8gSW50ZXJhY3Rpb25cbiAgICAgIFwiY3Vyc29yLXRleHRcIixcbiAgICAgIC8vIE92ZXJmbG93IGFuZCBjbGlwcGluZ1xuICAgICAgXCJvdmVyZmxvdy12aXNpYmxlIGJnLWNsaXAtcGFkZGluZyBjb250YWluLWlubGluZS1zaXplXCIsXG4gICAgICAvLyBCYWNrZ3JvdW5kXG4gICAgICBcImJnLXdoaXRlIGRhcms6YmctWyMzMDMwMzBdXCIsXG4gICAgICAvLyBWaXN1YWwgZWZmZWN0c1xuICAgICAgXCJzaGFkb3ctWzBfNHB4XzRweF8wXyMwMDAwMDAwYSwwXzBfMXB4XzBfIzAwMDAwMDllXSByb3VuZGVkLVsyOHB4XVwiLFxuICAgICk7XG4gICAgcmV0dXJuIGNuKGJhc2VDbGFzc2VzLCB0aGlzLmN1c3RvbUNsYXNzKCkpO1xuICB9KTtcblxuICAvLyBDb250ZXh0IGZvciBzbG90cyAocmVhY3RpdmUgdmlhIHNpZ25hbHMpXG4gIHNlbmRCdXR0b25Db250ZXh0ID0gY29tcHV0ZWQ8U2VuZEJ1dHRvbkNvbnRleHQ+KCgpID0+ICh7XG4gICAgc2VuZDogKCkgPT4gdGhpcy5zZW5kKCksXG4gICAgZGlzYWJsZWQ6XG4gICAgICAhdGhpcy5jb21wdXRlZFZhbHVlKCkudHJpbSgpIHx8IHRoaXMuY29tcHV0ZWRNb2RlKCkgPT09IFwicHJvY2Vzc2luZ1wiLFxuICAgIHZhbHVlOiB0aGlzLmNvbXB1dGVkVmFsdWUoKSxcbiAgfSkpO1xuXG4gIHRvb2xiYXJDb250ZXh0ID0gY29tcHV0ZWQ8VG9vbGJhckNvbnRleHQ+KCgpID0+ICh7XG4gICAgbW9kZTogdGhpcy5jb21wdXRlZE1vZGUoKSxcbiAgICB2YWx1ZTogdGhpcy5jb21wdXRlZFZhbHVlKCksXG4gIH0pKTtcblxuICB0ZXh0QXJlYUNvbnRleHQgPSBjb21wdXRlZCgoKSA9PiAoe1xuICAgIHZhbHVlOiB0aGlzLmNvbXB1dGVkVmFsdWUoKSxcbiAgICBhdXRvRm9jdXM6IHRoaXMuY29tcHV0ZWRBdXRvRm9jdXMoKSxcbiAgICBkaXNhYmxlZDogdGhpcy5jb21wdXRlZE1vZGUoKSA9PT0gXCJwcm9jZXNzaW5nXCIsXG4gICAgbWF4Um93czogdGhpcy50ZXh0QXJlYU1heFJvd3MoKSxcbiAgICBwbGFjZWhvbGRlcjogdGhpcy50ZXh0QXJlYVBsYWNlaG9sZGVyKCksXG4gICAgaW5wdXRDbGFzczogdGhpcy50ZXh0QXJlYUNsYXNzKCksXG4gICAgb25LZXlEb3duOiAoZXZlbnQ6IEtleWJvYXJkRXZlbnQpID0+IHRoaXMuaGFuZGxlS2V5RG93bihldmVudCksXG4gICAgb25DaGFuZ2U6ICh2YWx1ZTogc3RyaW5nKSA9PiB0aGlzLmhhbmRsZVZhbHVlQ2hhbmdlKHZhbHVlKSxcbiAgfSkpO1xuXG4gIGF1ZGlvUmVjb3JkZXJDb250ZXh0ID0gY29tcHV0ZWQoKCkgPT4gKHtcbiAgICBpbnB1dFNob3dDb250cm9sczogdHJ1ZSxcbiAgfSkpO1xuXG4gIC8vIEJ1dHRvbiBjb250ZXh0cyByZW1vdmVkIC0gbm93IHVzaW5nIG91dHB1dHMgbWFwIGZvciBjbGljayBoYW5kbGVyc1xuXG4gIHRvb2xzQ29udGV4dCA9IGNvbXB1dGVkKCgpID0+ICh7XG4gICAgaW5wdXRUb29sc01lbnU6IHRoaXMuY29tcHV0ZWRUb29sc01lbnUoKSxcbiAgICBpbnB1dERpc2FibGVkOiB0aGlzLmNvbXB1dGVkTW9kZSgpID09PSBcInRyYW5zY3JpYmVcIixcbiAgfSkpO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIC8vIEVmZmVjdCB0byBoYW5kbGUgbW9kZSBjaGFuZ2VzIChubyBzaWduYWwgd3JpdGVzKVxuICAgIGVmZmVjdCgoKSA9PiB7XG4gICAgICBjb25zdCBjdXJyZW50TW9kZSA9IHRoaXMuY29tcHV0ZWRNb2RlKCk7XG4gICAgICBpZiAoY3VycmVudE1vZGUgPT09IFwidHJhbnNjcmliZVwiICYmIHRoaXMuYXVkaW9SZWNvcmRlclJlZikge1xuICAgICAgICB0aGlzLmF1ZGlvUmVjb3JkZXJSZWYuc3RhcnQoKS5jYXRjaChjb25zb2xlLmVycm9yKTtcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5hdWRpb1JlY29yZGVyUmVmPy5nZXRTdGF0ZSgpID09PSBcInJlY29yZGluZ1wiKSB7XG4gICAgICAgIHRoaXMuYXVkaW9SZWNvcmRlclJlZi5zdG9wKCkuY2F0Y2goY29uc29sZS5lcnJvcik7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvLyBPdXRwdXQgbWFwcyBmb3Igc2xvdHNcbiAgYWRkRmlsZUJ1dHRvbk91dHB1dHMgPSB7IGNsaWNrZWQ6ICgpID0+IHRoaXMuaGFuZGxlQWRkRmlsZSgpIH07XG4gIGNhbmNlbFRyYW5zY3JpYmVCdXR0b25PdXRwdXRzID0ge1xuICAgIGNsaWNrZWQ6ICgpID0+IHRoaXMuaGFuZGxlQ2FuY2VsVHJhbnNjcmliZSgpLFxuICB9O1xuICBmaW5pc2hUcmFuc2NyaWJlQnV0dG9uT3V0cHV0cyA9IHtcbiAgICBjbGlja2VkOiAoKSA9PiB0aGlzLmhhbmRsZUZpbmlzaFRyYW5zY3JpYmUoKSxcbiAgfTtcbiAgc3RhcnRUcmFuc2NyaWJlQnV0dG9uT3V0cHV0cyA9IHtcbiAgICBjbGlja2VkOiAoKSA9PiB0aGlzLmhhbmRsZVN0YXJ0VHJhbnNjcmliZSgpLFxuICB9O1xuICAvLyBTdXBwb3J0IGJvdGggYGNsaWNrZWRgIChpZGlvbWF0aWMgaW4gb3VyIHNsb3RzKSBhbmQgYGNsaWNrYCAobGVnYWN5KVxuICBzZW5kQnV0dG9uT3V0cHV0cyA9IHsgY2xpY2tlZDogKCkgPT4gdGhpcy5zZW5kKCksIGNsaWNrOiAoKSA9PiB0aGlzLnNlbmQoKSB9O1xuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICAvLyBBdXRvLWZvY3VzIGlmIG5lZWRlZFxuICAgIGlmICh0aGlzLmNvbXB1dGVkQXV0b0ZvY3VzKCkgJiYgdGhpcy50ZXh0QXJlYVJlZikge1xuICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgIHRoaXMudGV4dEFyZWFSZWY/LmZvY3VzKCk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICAvLyBDbGVhbiB1cCBhbnkgcmVzb3VyY2VzXG4gICAgaWYgKHRoaXMuYXVkaW9SZWNvcmRlclJlZj8uZ2V0U3RhdGUoKSA9PT0gXCJyZWNvcmRpbmdcIikge1xuICAgICAgdGhpcy5hdWRpb1JlY29yZGVyUmVmPy5zdG9wKCkuY2F0Y2goY29uc29sZS5lcnJvcik7XG4gICAgfVxuICB9XG5cbiAgaGFuZGxlS2V5RG93bihldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xuICAgIGlmIChldmVudC5rZXkgPT09IFwiRW50ZXJcIiAmJiAhZXZlbnQuc2hpZnRLZXkpIHtcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB0aGlzLnNlbmQoKTtcbiAgICB9XG4gIH1cblxuICBoYW5kbGVWYWx1ZUNoYW5nZSh2YWx1ZTogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy52YWx1ZUNoYW5nZS5lbWl0KHZhbHVlKTtcbiAgICBpZiAodGhpcy5jaGF0U3RhdGUpIHRoaXMuY2hhdFN0YXRlLmNoYW5nZUlucHV0KHZhbHVlKTtcbiAgfVxuXG4gIHNlbmQoKTogdm9pZCB7XG4gICAgY29uc3QgdHJpbW1lZCA9IHRoaXMuY29tcHV0ZWRWYWx1ZSgpLnRyaW0oKTtcbiAgICBpZiAodHJpbW1lZCkge1xuICAgICAgdGhpcy5zdWJtaXRNZXNzYWdlLmVtaXQodHJpbW1lZCk7XG5cbiAgICAgIHRoaXMuY2hhdFN0YXRlLnN1Ym1pdElucHV0KHRyaW1tZWQpO1xuXG4gICAgICBpZiAodGhpcy5jaGF0U3RhdGUpIHRoaXMuY2hhdFN0YXRlLmNoYW5nZUlucHV0KFwiXCIpO1xuICAgICAgaWYgKHRoaXMudGV4dEFyZWFSZWYpIHRoaXMudGV4dEFyZWFSZWYuc2V0VmFsdWUoXCJcIik7XG5cbiAgICAgIC8vIFJlZm9jdXMgaW5wdXRcbiAgICAgIGlmICh0aGlzLnRleHRBcmVhUmVmKSB7XG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgIHRoaXMudGV4dEFyZWFSZWY/LmZvY3VzKCk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGhhbmRsZVN0YXJ0VHJhbnNjcmliZSgpOiB2b2lkIHtcbiAgICB0aGlzLnN0YXJ0VHJhbnNjcmliZS5lbWl0KCk7XG4gICAgdGhpcy5tb2RlU2lnbmFsLnNldChcInRyYW5zY3JpYmVcIik7XG4gIH1cblxuICBoYW5kbGVDYW5jZWxUcmFuc2NyaWJlKCk6IHZvaWQge1xuICAgIHRoaXMuY2FuY2VsVHJhbnNjcmliZS5lbWl0KCk7XG4gICAgdGhpcy5tb2RlU2lnbmFsLnNldChcImlucHV0XCIpO1xuICB9XG5cbiAgaGFuZGxlRmluaXNoVHJhbnNjcmliZSgpOiB2b2lkIHtcbiAgICB0aGlzLmZpbmlzaFRyYW5zY3JpYmUuZW1pdCgpO1xuICAgIHRoaXMubW9kZVNpZ25hbC5zZXQoXCJpbnB1dFwiKTtcbiAgfVxuXG4gIGhhbmRsZUFkZEZpbGUoKTogdm9pZCB7XG4gICAgdGhpcy5hZGRGaWxlLmVtaXQoKTtcbiAgfVxufVxuIl19