@copilotkitnext/angular 0.0.1 → 0.0.4

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 (171) hide show
  1. package/README.md +248 -0
  2. package/dist/README.md +248 -0
  3. package/dist/components/chat/copilot-chat-assistant-message.component.d.ts +10 -10
  4. package/dist/components/chat/copilot-chat-message-view.component.d.ts +42 -42
  5. package/dist/components/chat/copilot-chat-view.component.d.ts +14 -14
  6. package/dist/esm2022/components/chat/copilot-chat-assistant-message-buttons.component.mjs +384 -0
  7. package/dist/esm2022/components/chat/copilot-chat-assistant-message-renderer.component.mjs +286 -0
  8. package/dist/esm2022/components/chat/copilot-chat-assistant-message-toolbar.component.mjs +27 -0
  9. package/dist/esm2022/components/chat/copilot-chat-assistant-message.component.mjs +433 -0
  10. package/dist/esm2022/components/chat/copilot-chat-assistant-message.types.mjs +2 -0
  11. package/dist/esm2022/components/chat/copilot-chat-audio-recorder.component.mjs +202 -0
  12. package/dist/esm2022/components/chat/copilot-chat-buttons.component.mjs +321 -0
  13. package/dist/esm2022/components/chat/copilot-chat-input-defaults.mjs +38 -0
  14. package/dist/esm2022/components/chat/copilot-chat-input.component.mjs +666 -0
  15. package/dist/esm2022/components/chat/copilot-chat-input.types.mjs +10 -0
  16. package/dist/esm2022/components/chat/copilot-chat-message-view-cursor.component.mjs +45 -0
  17. package/dist/esm2022/components/chat/copilot-chat-message-view.component.mjs +296 -0
  18. package/dist/esm2022/components/chat/copilot-chat-message-view.types.mjs +2 -0
  19. package/dist/esm2022/components/chat/copilot-chat-textarea.component.mjs +188 -0
  20. package/dist/esm2022/components/chat/copilot-chat-tool-calls-view.component.mjs +216 -0
  21. package/dist/esm2022/components/chat/copilot-chat-toolbar.component.mjs +25 -0
  22. package/dist/esm2022/components/chat/copilot-chat-tools-menu.component.mjs +199 -0
  23. package/dist/esm2022/components/chat/copilot-chat-user-message-branch-navigation.component.mjs +137 -0
  24. package/dist/esm2022/components/chat/copilot-chat-user-message-buttons.component.mjs +207 -0
  25. package/dist/esm2022/components/chat/copilot-chat-user-message-renderer.component.mjs +35 -0
  26. package/dist/esm2022/components/chat/copilot-chat-user-message-toolbar.component.mjs +34 -0
  27. package/dist/esm2022/components/chat/copilot-chat-user-message.component.mjs +341 -0
  28. package/dist/esm2022/components/chat/copilot-chat-user-message.types.mjs +2 -0
  29. package/dist/esm2022/components/chat/copilot-chat-view-disclaimer.component.mjs +52 -0
  30. package/dist/esm2022/components/chat/copilot-chat-view-feather.component.mjs +55 -0
  31. package/dist/esm2022/components/chat/copilot-chat-view-handlers.service.mjs +19 -0
  32. package/dist/esm2022/components/chat/copilot-chat-view-input-container.component.mjs +110 -0
  33. package/dist/esm2022/components/chat/copilot-chat-view-scroll-to-bottom-button.component.mjs +93 -0
  34. package/dist/esm2022/components/chat/copilot-chat-view-scroll-view.component.mjs +443 -0
  35. package/dist/esm2022/components/chat/copilot-chat-view.component.mjs +479 -0
  36. package/dist/esm2022/components/chat/copilot-chat-view.types.mjs +2 -0
  37. package/dist/esm2022/components/chat/copilot-chat.component.mjs +214 -0
  38. package/dist/esm2022/components/copilotkit-tool-render.component.mjs +153 -0
  39. package/dist/esm2022/copilotkitnext-angular.mjs +5 -0
  40. package/dist/esm2022/core/chat-configuration/chat-configuration.providers.mjs +65 -0
  41. package/dist/esm2022/core/chat-configuration/chat-configuration.service.mjs +145 -0
  42. package/dist/esm2022/core/chat-configuration/chat-configuration.types.mjs +26 -0
  43. package/dist/esm2022/core/copilotkit.providers.mjs +34 -0
  44. package/dist/esm2022/core/copilotkit.service.mjs +430 -0
  45. package/dist/esm2022/core/copilotkit.types.mjs +12 -0
  46. package/dist/esm2022/directives/copilotkit-agent-context.directive.mjs +130 -0
  47. package/dist/esm2022/directives/copilotkit-agent.directive.mjs +217 -0
  48. package/dist/esm2022/directives/copilotkit-chat-config.directive.mjs +218 -0
  49. package/dist/esm2022/directives/copilotkit-config.directive.mjs +94 -0
  50. package/dist/esm2022/directives/copilotkit-frontend-tool.directive.mjs +130 -0
  51. package/dist/esm2022/directives/copilotkit-human-in-the-loop.directive.mjs +266 -0
  52. package/dist/esm2022/directives/stick-to-bottom.directive.mjs +181 -0
  53. package/dist/esm2022/index.mjs +70 -0
  54. package/dist/esm2022/lib/directives/tooltip.directive.mjs +211 -0
  55. package/dist/esm2022/lib/slots/copilot-slot.component.mjs +144 -0
  56. package/dist/esm2022/lib/slots/slot.types.mjs +6 -0
  57. package/dist/esm2022/lib/slots/slot.utils.mjs +222 -0
  58. package/dist/esm2022/lib/utils.mjs +10 -0
  59. package/dist/esm2022/services/resize-observer.service.mjs +152 -0
  60. package/dist/esm2022/services/scroll-position.service.mjs +124 -0
  61. package/dist/esm2022/types/frontend-tool.mjs +2 -0
  62. package/dist/esm2022/types/human-in-the-loop.mjs +2 -0
  63. package/dist/esm2022/utils/agent-context.utils.mjs +114 -0
  64. package/dist/esm2022/utils/agent.utils.mjs +204 -0
  65. package/dist/esm2022/utils/chat-config.utils.mjs +186 -0
  66. package/dist/esm2022/utils/copilotkit.utils.mjs +20 -0
  67. package/dist/esm2022/utils/frontend-tool.utils.mjs +228 -0
  68. package/dist/esm2022/utils/human-in-the-loop.utils.mjs +296 -0
  69. package/dist/fesm2022/copilotkitnext-angular.mjs +163 -164
  70. package/dist/fesm2022/copilotkitnext-angular.mjs.map +1 -1
  71. package/dist/styles.css +0 -27
  72. package/package.json +23 -20
  73. package/vitest.config.mts +32 -21
  74. package/.turbo/turbo-build.log +0 -39
  75. package/.turbo/turbo-check-types.log +0 -0
  76. package/.turbo/turbo-test.log +0 -71
  77. package/README-agent-context.md +0 -310
  78. package/ng-package.json +0 -19
  79. package/slots.md +0 -331
  80. package/src/components/chat/__tests__/copilot-chat-assistant-message.component.spec.ts +0 -282
  81. package/src/components/chat/__tests__/copilot-chat-input.component.spec.ts +0 -419
  82. package/src/components/chat/__tests__/copilot-chat-message-view.component.spec.ts +0 -372
  83. package/src/components/chat/__tests__/copilot-chat-user-message.component.spec.ts +0 -249
  84. package/src/components/chat/copilot-chat-assistant-message-buttons.component.ts +0 -292
  85. package/src/components/chat/copilot-chat-assistant-message-renderer.component.ts +0 -472
  86. package/src/components/chat/copilot-chat-assistant-message-toolbar.component.ts +0 -29
  87. package/src/components/chat/copilot-chat-assistant-message.component.ts +0 -463
  88. package/src/components/chat/copilot-chat-assistant-message.types.ts +0 -50
  89. package/src/components/chat/copilot-chat-audio-recorder.component.ts +0 -241
  90. package/src/components/chat/copilot-chat-buttons.component.ts +0 -308
  91. package/src/components/chat/copilot-chat-buttons.component.ts.bak +0 -471
  92. package/src/components/chat/copilot-chat-input-defaults.ts +0 -47
  93. package/src/components/chat/copilot-chat-input.component.ts +0 -512
  94. package/src/components/chat/copilot-chat-input.types.ts +0 -148
  95. package/src/components/chat/copilot-chat-message-view-cursor.component.ts +0 -51
  96. package/src/components/chat/copilot-chat-message-view.component.ts +0 -233
  97. package/src/components/chat/copilot-chat-message-view.types.ts +0 -39
  98. package/src/components/chat/copilot-chat-textarea.component.ts +0 -220
  99. package/src/components/chat/copilot-chat-tool-calls-view.component.ts +0 -261
  100. package/src/components/chat/copilot-chat-toolbar.component.ts +0 -35
  101. package/src/components/chat/copilot-chat-tools-menu.component.ts +0 -185
  102. package/src/components/chat/copilot-chat-user-message-branch-navigation.component.ts +0 -121
  103. package/src/components/chat/copilot-chat-user-message-buttons.component.ts +0 -170
  104. package/src/components/chat/copilot-chat-user-message-renderer.component.ts +0 -37
  105. package/src/components/chat/copilot-chat-user-message-toolbar.component.ts +0 -37
  106. package/src/components/chat/copilot-chat-user-message.component.ts +0 -247
  107. package/src/components/chat/copilot-chat-user-message.types.ts +0 -42
  108. package/src/components/chat/copilot-chat-view-disclaimer.component.ts +0 -51
  109. package/src/components/chat/copilot-chat-view-feather.component.ts +0 -47
  110. package/src/components/chat/copilot-chat-view-handlers.service.ts +0 -14
  111. package/src/components/chat/copilot-chat-view-input-container.component.ts +0 -87
  112. package/src/components/chat/copilot-chat-view-scroll-to-bottom-button.component.ts +0 -79
  113. package/src/components/chat/copilot-chat-view-scroll-view.component.ts +0 -322
  114. package/src/components/chat/copilot-chat-view.component.ts +0 -420
  115. package/src/components/chat/copilot-chat-view.types.ts +0 -52
  116. package/src/components/chat/copilot-chat.component.ts +0 -232
  117. package/src/components/copilotkit-tool-render.component.ts +0 -169
  118. package/src/core/__tests__/copilotkit.service.spec.ts +0 -1051
  119. package/src/core/__tests__/copilotkit.service.wildcard.spec.ts +0 -316
  120. package/src/core/chat-configuration/__tests__/chat-configuration.service.spec.ts +0 -287
  121. package/src/core/chat-configuration/chat-configuration.providers.ts +0 -71
  122. package/src/core/chat-configuration/chat-configuration.service.ts +0 -162
  123. package/src/core/chat-configuration/chat-configuration.types.ts +0 -57
  124. package/src/core/copilotkit.providers.ts +0 -59
  125. package/src/core/copilotkit.service.ts +0 -542
  126. package/src/core/copilotkit.types.ts +0 -132
  127. package/src/directives/__tests__/copilotkit-agent-context.directive.spec.ts +0 -384
  128. package/src/directives/__tests__/copilotkit-agent.directive.spec.ts +0 -253
  129. package/src/directives/__tests__/copilotkit-chat-config.directive.spec.ts +0 -385
  130. package/src/directives/__tests__/copilotkit-config.directive.spec.ts +0 -69
  131. package/src/directives/__tests__/copilotkit-frontend-tool-simple.directive.spec.ts +0 -60
  132. package/src/directives/__tests__/copilotkit-frontend-tool.directive.spec.ts +0 -108
  133. package/src/directives/__tests__/copilotkit-human-in-the-loop.directive.spec.ts +0 -452
  134. package/src/directives/copilotkit-agent-context.directive.ts +0 -138
  135. package/src/directives/copilotkit-agent.directive.ts +0 -225
  136. package/src/directives/copilotkit-chat-config.directive.ts +0 -241
  137. package/src/directives/copilotkit-config.directive.ts +0 -81
  138. package/src/directives/copilotkit-frontend-tool.directive.ts +0 -145
  139. package/src/directives/copilotkit-human-in-the-loop.directive.ts +0 -281
  140. package/src/directives/stick-to-bottom.directive.ts +0 -204
  141. package/src/index.ts +0 -105
  142. package/src/lib/directives/tooltip.directive.ts +0 -292
  143. package/src/lib/slots/__tests__/slot.utils.spec.ts +0 -377
  144. package/src/lib/slots/copilot-slot.component.ts +0 -135
  145. package/src/lib/slots/index.ts +0 -3
  146. package/src/lib/slots/slot.types.ts +0 -64
  147. package/src/lib/slots/slot.utils.ts +0 -289
  148. package/src/lib/utils.ts +0 -10
  149. package/src/public-api.ts +0 -1
  150. package/src/services/resize-observer.service.ts +0 -181
  151. package/src/services/scroll-position.service.ts +0 -169
  152. package/src/styles/globals.css +0 -266
  153. package/src/styles/index.css +0 -3
  154. package/src/test-setup.ts +0 -15
  155. package/src/testing/index.ts +0 -3
  156. package/src/testing/testing.utils.ts +0 -248
  157. package/src/types/frontend-tool.ts +0 -44
  158. package/src/types/human-in-the-loop.ts +0 -52
  159. package/src/utils/__tests__/agent.utils.spec.ts +0 -234
  160. package/src/utils/__tests__/chat-config.utils.spec.ts +0 -306
  161. package/src/utils/__tests__/frontend-tool-inject.spec.ts +0 -350
  162. package/src/utils/__tests__/frontend-tool-integration.spec.ts +0 -199
  163. package/src/utils/__tests__/frontend-tool.utils.spec.ts +0 -272
  164. package/src/utils/__tests__/human-in-the-loop.utils.spec.ts +0 -365
  165. package/src/utils/agent-context.utils.ts +0 -133
  166. package/src/utils/agent.utils.ts +0 -239
  167. package/src/utils/chat-config.utils.ts +0 -221
  168. package/src/utils/copilotkit.utils.ts +0 -20
  169. package/src/utils/frontend-tool.utils.ts +0 -266
  170. package/src/utils/human-in-the-loop.utils.ts +0 -359
  171. package/tsconfig.spec.json +0 -12
@@ -0,0 +1,216 @@
1
+ import { Component, Input, ViewContainerRef, inject, ViewChild, TemplateRef, ChangeDetectionStrategy, signal, } from "@angular/core";
2
+ import { CommonModule } from "@angular/common";
3
+ import { ToolCallStatus } from "@copilotkitnext/core";
4
+ import { CopilotKitService } from "../../core/copilotkit.service";
5
+ import { partialJSONParse } from "@copilotkitnext/shared";
6
+ import * as i0 from "@angular/core";
7
+ import * as i1 from "@angular/common";
8
+ /**
9
+ * Component for rendering all tool calls for an assistant message.
10
+ * This component iterates through the message's tool calls and renders each one
11
+ * using the registered render functions in CopilotKitService.
12
+ */
13
+ export class CopilotChatToolCallsViewComponent {
14
+ message;
15
+ messages = [];
16
+ isLoading = false;
17
+ container;
18
+ copilotkit = inject(CopilotKitService, {
19
+ optional: true,
20
+ });
21
+ componentRefs = new Map();
22
+ templateCache = new Map();
23
+ // Signals for reactive state
24
+ messageSignal = signal(null);
25
+ messagesSignal = signal([]);
26
+ isLoadingSignal = signal(false);
27
+ ngAfterViewInit() {
28
+ this.renderAllToolCalls();
29
+ }
30
+ ngOnChanges(changes) {
31
+ if (changes["message"]) {
32
+ this.messageSignal.set(this.message);
33
+ }
34
+ if (changes["messages"]) {
35
+ this.messagesSignal.set(this.messages);
36
+ }
37
+ if (changes["isLoading"]) {
38
+ this.isLoadingSignal.set(this.isLoading);
39
+ }
40
+ this.renderAllToolCalls();
41
+ }
42
+ ngOnDestroy() {
43
+ // Clean up all component refs
44
+ this.componentRefs.forEach((ref) => ref.destroy());
45
+ this.componentRefs.clear();
46
+ this.templateCache.clear();
47
+ }
48
+ getTemplateForToolCall(toolCall) {
49
+ return this.templateCache.get(toolCall.id) || null;
50
+ }
51
+ renderAllToolCalls() {
52
+ const message = this.messageSignal();
53
+ if (!message || !message.toolCalls || message.toolCalls.length === 0) {
54
+ return;
55
+ }
56
+ // Clear existing renders
57
+ this.componentRefs.forEach((ref) => ref.destroy());
58
+ this.componentRefs.clear();
59
+ this.templateCache.clear();
60
+ if (!this.copilotkit || !this.container) {
61
+ return;
62
+ }
63
+ const messages = this.messagesSignal();
64
+ const isLoading = this.isLoadingSignal();
65
+ // Render each tool call
66
+ message.toolCalls.forEach((toolCall) => {
67
+ const toolMessage = messages.find((m) => m.role === "tool" && m.toolCallId === toolCall.id);
68
+ this.renderSingleToolCall(toolCall, toolMessage, isLoading);
69
+ });
70
+ }
71
+ renderSingleToolCall(toolCall, toolMessage, isLoading) {
72
+ if (!this.copilotkit) {
73
+ return;
74
+ }
75
+ // Get current render tool calls
76
+ const currentRenderToolCalls = this.copilotkit.currentRenderToolCalls();
77
+ // Find the render config for this tool call by name
78
+ // Also check for wildcard (*) renders if no exact match
79
+ const renderConfig = currentRenderToolCalls.find((rc) => rc.name === toolCall.function.name) || currentRenderToolCalls.find((rc) => rc.name === "*");
80
+ if (!renderConfig) {
81
+ return;
82
+ }
83
+ // Parse the arguments if they're a string
84
+ const args = partialJSONParse(toolCall.function.arguments);
85
+ // Determine status
86
+ let status;
87
+ if (toolMessage) {
88
+ status = ToolCallStatus.Complete;
89
+ }
90
+ else if (isLoading) {
91
+ status = ToolCallStatus.InProgress;
92
+ }
93
+ else {
94
+ status = ToolCallStatus.Complete;
95
+ }
96
+ // Create props based on status - use discriminated union properly
97
+ let props;
98
+ if (status === ToolCallStatus.InProgress) {
99
+ props = {
100
+ name: toolCall.function.name,
101
+ description: "",
102
+ args: args, // Partial args for InProgress
103
+ status: ToolCallStatus.InProgress,
104
+ result: undefined,
105
+ };
106
+ }
107
+ else {
108
+ // Complete status
109
+ props = {
110
+ name: toolCall.function.name,
111
+ description: "",
112
+ args: args, // Full args for Complete
113
+ status: ToolCallStatus.Complete,
114
+ result: toolMessage?.content || "",
115
+ };
116
+ }
117
+ // Check if render is a Component class or TemplateRef
118
+ if (this.isComponentClass(renderConfig.render)) {
119
+ // Create component dynamically
120
+ this.renderComponent(toolCall.id, renderConfig.render, props);
121
+ }
122
+ else if (this.isTemplateRef(renderConfig.render)) {
123
+ // Use template
124
+ this.renderTemplate(toolCall.id, renderConfig.render, props);
125
+ }
126
+ }
127
+ renderComponent(toolCallId, componentClass, props) {
128
+ if (!this.container) {
129
+ return;
130
+ }
131
+ // Create the component
132
+ const componentRef = this.container.createComponent(componentClass);
133
+ this.componentRefs.set(toolCallId, componentRef);
134
+ // Set inputs on the component
135
+ for (const [key, value] of Object.entries(props)) {
136
+ try {
137
+ componentRef.setInput(key, value);
138
+ }
139
+ catch (e) {
140
+ // Input might not exist on the component, which is fine
141
+ }
142
+ }
143
+ // Trigger change detection
144
+ componentRef.changeDetectorRef.detectChanges();
145
+ }
146
+ renderTemplate(toolCallId, template, props) {
147
+ this.templateCache.set(toolCallId, {
148
+ template,
149
+ context: {
150
+ $implicit: props,
151
+ name: props.name,
152
+ description: props.description,
153
+ args: props.args,
154
+ status: props.status,
155
+ result: props.result,
156
+ },
157
+ });
158
+ }
159
+ isComponentClass(value) {
160
+ return typeof value === "function" && value.prototype;
161
+ }
162
+ isTemplateRef(value) {
163
+ return value instanceof TemplateRef;
164
+ }
165
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CopilotChatToolCallsViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
166
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: CopilotChatToolCallsViewComponent, isStandalone: true, selector: "copilot-chat-tool-calls-view", inputs: { message: "message", messages: "messages", isLoading: "isLoading" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["dynamicContainer"], descendants: true, read: ViewContainerRef }], usesOnChanges: true, ngImport: i0, template: `
167
+ @for (toolCall of message?.toolCalls ?? []; track toolCall.id) {
168
+ <ng-container>
169
+ <ng-container #dynamicContainer></ng-container>
170
+ <ng-container *ngIf="getTemplateForToolCall(toolCall) as templateData">
171
+ <ng-container
172
+ *ngTemplateOutlet="
173
+ templateData.template;
174
+ context: templateData.context
175
+ "
176
+ ></ng-container>
177
+ </ng-container>
178
+ </ng-container>
179
+ }
180
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
181
+ }
182
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CopilotChatToolCallsViewComponent, decorators: [{
183
+ type: Component,
184
+ args: [{
185
+ selector: "copilot-chat-tool-calls-view",
186
+ standalone: true,
187
+ imports: [CommonModule],
188
+ changeDetection: ChangeDetectionStrategy.OnPush,
189
+ template: `
190
+ @for (toolCall of message?.toolCalls ?? []; track toolCall.id) {
191
+ <ng-container>
192
+ <ng-container #dynamicContainer></ng-container>
193
+ <ng-container *ngIf="getTemplateForToolCall(toolCall) as templateData">
194
+ <ng-container
195
+ *ngTemplateOutlet="
196
+ templateData.template;
197
+ context: templateData.context
198
+ "
199
+ ></ng-container>
200
+ </ng-container>
201
+ </ng-container>
202
+ }
203
+ `,
204
+ }]
205
+ }], propDecorators: { message: [{
206
+ type: Input,
207
+ args: [{ required: true }]
208
+ }], messages: [{
209
+ type: Input
210
+ }], isLoading: [{
211
+ type: Input
212
+ }], container: [{
213
+ type: ViewChild,
214
+ args: ["dynamicContainer", { read: ViewContainerRef }]
215
+ }] } });
216
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29waWxvdC1jaGF0LXRvb2wtY2FsbHMtdmlldy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvY29tcG9uZW50cy9jaGF0L2NvcGlsb3QtY2hhdC10b29sLWNhbGxzLXZpZXcuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQ1QsS0FBSyxFQUNMLGdCQUFnQixFQUVoQixNQUFNLEVBQ04sU0FBUyxFQUlULFdBQVcsRUFFWCx1QkFBdUIsRUFDdkIsTUFBTSxHQUdQLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQU8vQyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDdEQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDbEUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7OztBQU0xRDs7OztHQUlHO0FBc0JILE1BQU0sT0FBTyxpQ0FBaUM7SUFHakIsT0FBTyxDQUFvQjtJQUM3QyxRQUFRLEdBQWMsRUFBRSxDQUFDO0lBQ3pCLFNBQVMsR0FBRyxLQUFLLENBQUM7SUFHbkIsU0FBUyxDQUFvQjtJQUU3QixVQUFVLEdBQTZCLE1BQU0sQ0FBQyxpQkFBaUIsRUFBRTtRQUN2RSxRQUFRLEVBQUUsSUFBSTtLQUNmLENBQUMsQ0FBQztJQUNLLGFBQWEsR0FBbUMsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUMxRCxhQUFhLEdBR2pCLElBQUksR0FBRyxFQUFFLENBQUM7SUFFZCw2QkFBNkI7SUFDckIsYUFBYSxHQUFHLE1BQU0sQ0FBMEIsSUFBSSxDQUFDLENBQUM7SUFDdEQsY0FBYyxHQUFHLE1BQU0sQ0FBWSxFQUFFLENBQUMsQ0FBQztJQUN2QyxlQUFlLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBRXhDLGVB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Qy9DLFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7Ozs7R0FjVDtpQkFDRjs4QkFJNEIsT0FBTztzQkFBakMsS0FBSzt1QkFBQyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUU7Z0JBQ2hCLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csU0FBUztzQkFBakIsS0FBSztnQkFHRSxTQUFTO3NCQURoQixTQUFTO3VCQUFDLGtCQUFrQixFQUFFLEVBQUUsSUFBSSxFQUFFLGdCQUFnQixFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBJbnB1dCxcbiAgVmlld0NvbnRhaW5lclJlZixcbiAgQ29tcG9uZW50UmVmLFxuICBpbmplY3QsXG4gIFZpZXdDaGlsZCxcbiAgQWZ0ZXJWaWV3SW5pdCxcbiAgT25DaGFuZ2VzLFxuICBTaW1wbGVDaGFuZ2VzLFxuICBUZW1wbGF0ZVJlZixcbiAgVHlwZSxcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIHNpZ25hbCxcbiAgY29tcHV0ZWQsXG4gIE9uRGVzdHJveSxcbn0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gXCJAYW5ndWxhci9jb21tb25cIjtcbmltcG9ydCB0eXBlIHtcbiAgQXNzaXN0YW50TWVzc2FnZSxcbiAgTWVzc2FnZSxcbiAgVG9vbENhbGwsXG4gIFRvb2xNZXNzYWdlLFxufSBmcm9tIFwiQGFnLXVpL2NvcmVcIjtcbmltcG9ydCB7IFRvb2xDYWxsU3RhdHVzIH0gZnJvbSBcIkBjb3BpbG90a2l0bmV4dC9jb3JlXCI7XG5pbXBvcnQgeyBDb3BpbG90S2l0U2VydmljZSB9IGZyb20gXCIuLi8uLi9jb3JlL2NvcGlsb3RraXQuc2VydmljZVwiO1xuaW1wb3J0IHsgcGFydGlhbEpTT05QYXJzZSB9IGZyb20gXCJAY29waWxvdGtpdG5leHQvc2hhcmVkXCI7XG5pbXBvcnQgdHlwZSB7XG4gIFRvb2xDYWxsUHJvcHMsXG4gIFRvb2xDYWxsUmVuZGVyLFxufSBmcm9tIFwiLi4vLi4vY29yZS9jb3BpbG90a2l0LnR5cGVzXCI7XG5cbi8qKlxuICogQ29tcG9uZW50IGZvciByZW5kZXJpbmcgYWxsIHRvb2wgY2FsbHMgZm9yIGFuIGFzc2lzdGFudCBtZXNzYWdlLlxuICogVGhpcyBjb21wb25lbnQgaXRlcmF0ZXMgdGhyb3VnaCB0aGUgbWVzc2FnZSdzIHRvb2wgY2FsbHMgYW5kIHJlbmRlcnMgZWFjaCBvbmVcbiAqIHVzaW5nIHRoZSByZWdpc3RlcmVkIHJlbmRlciBmdW5jdGlvbnMgaW4gQ29waWxvdEtpdFNlcnZpY2UuXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogXCJjb3BpbG90LWNoYXQtdG9vbC1jYWxscy12aWV3XCIsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGVdLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgdGVtcGxhdGU6IGBcbiAgICBAZm9yICh0b29sQ2FsbCBvZiBtZXNzYWdlPy50b29sQ2FsbHMgPz8gW107IHRyYWNrIHRvb2xDYWxsLmlkKSB7XG4gICAgICA8bmctY29udGFpbmVyPlxuICAgICAgICA8bmctY29udGFpbmVyICNkeW5hbWljQ29udGFpbmVyPjwvbmctY29udGFpbmVyPlxuICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiZ2V0VGVtcGxhdGVGb3JUb29sQ2FsbCh0b29sQ2FsbCkgYXMgdGVtcGxhdGVEYXRhXCI+XG4gICAgICAgICAgPG5nLWNvbnRhaW5lclxuICAgICAgICAgICAgKm5nVGVtcGxhdGVPdXRsZXQ9XCJcbiAgICAgICAgICAgICAgdGVtcGxhdGVEYXRhLnRlbXBsYXRlO1xuICAgICAgICAgICAgICBjb250ZXh0OiB0ZW1wbGF0ZURhdGEuY29udGV4dFxuICAgICAgICAgICAgXCJcbiAgICAgICAgICA+PC9uZy1jb250YWluZXI+XG4gICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgfVxuICBgLFxufSlcbmV4cG9ydCBjbGFzcyBDb3BpbG90Q2hhdFRvb2xDYWxsc1ZpZXdDb21wb25lbnRcbiAgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0LCBPbkNoYW5nZXMsIE9uRGVzdHJveVxue1xuICBASW5wdXQoeyByZXF1aXJlZDogdHJ1ZSB9KSBtZXNzYWdlITogQXNzaXN0YW50TWVzc2FnZTtcbiAgQElucHV0KCkgbWVzc2FnZXM6IE1lc3NhZ2VbXSA9IFtdO1xuICBASW5wdXQoKSBpc0xvYWRpbmcgPSBmYWxzZTtcblxuICBAVmlld0NoaWxkKFwiZHluYW1pY0NvbnRhaW5lclwiLCB7IHJlYWQ6IFZpZXdDb250YWluZXJSZWYgfSlcbiAgcHJpdmF0ZSBjb250YWluZXI/OiBWaWV3Q29udGFpbmVyUmVmO1xuXG4gIHByaXZhdGUgY29waWxvdGtpdDogQ29waWxvdEtpdFNlcnZpY2UgfCBudWxsID0gaW5qZWN0KENvcGlsb3RLaXRTZXJ2aWNlLCB7XG4gICAgb3B0aW9uYWw6IHRydWUsXG4gIH0pO1xuICBwcml2YXRlIGNvbXBvbmVudFJlZnM6IE1hcDxzdHJpbmcsIENvbXBvbmVudFJlZjxhbnk+PiA9IG5ldyBNYXAoKTtcbiAgcHJpdmF0ZSB0ZW1wbGF0ZUNhY2hlOiBNYXA8XG4gICAgc3RyaW5nLFxuICAgIHsgdGVtcGxhdGU6IFRlbXBsYXRlUmVmPGFueT47IGNvbnRleHQ6IGFueSB9XG4gID4gPSBuZXcgTWFwKCk7XG5cbiAgLy8gU2lnbmFscyBmb3IgcmVhY3RpdmUgc3RhdGVcbiAgcHJpdmF0ZSBtZXNzYWdlU2lnbmFsID0gc2lnbmFsPEFzc2lzdGFudE1lc3NhZ2UgfCBudWxsPihudWxsKTtcbiAgcHJpdmF0ZSBtZXNzYWdlc1NpZ25hbCA9IHNpZ25hbDxNZXNzYWdlW10+KFtdKTtcbiAgcHJpdmF0ZSBpc0xvYWRpbmdTaWduYWwgPSBzaWduYWwoZmFsc2UpO1xuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLnJlbmRlckFsbFRvb2xDYWxscygpO1xuICB9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIGlmIChjaGFuZ2VzW1wibWVzc2FnZVwiXSkge1xuICAgICAgdGhpcy5tZXNzYWdlU2lnbmFsLnNldCh0aGlzLm1lc3NhZ2UpO1xuICAgIH1cbiAgICBpZiAoY2hhbmdlc1tcIm1lc3NhZ2VzXCJdKSB7XG4gICAgICB0aGlzLm1lc3NhZ2VzU2lnbmFsLnNldCh0aGlzLm1lc3NhZ2VzKTtcbiAgICB9XG4gICAgaWYgKGNoYW5nZXNbXCJpc0xvYWRpbmdcIl0pIHtcbiAgICAgIHRoaXMuaXNMb2FkaW5nU2lnbmFsLnNldCh0aGlzLmlzTG9hZGluZyk7XG4gICAgfVxuXG4gICAgdGhpcy5yZW5kZXJBbGxUb29sQ2FsbHMoKTtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIC8vIENsZWFuIHVwIGFsbCBjb21wb25lbnQgcmVmc1xuICAgIHRoaXMuY29tcG9uZW50UmVmcy5mb3JFYWNoKChyZWYpID0+IHJlZi5kZXN0cm95KCkpO1xuICAgIHRoaXMuY29tcG9uZW50UmVmcy5jbGVhcigpO1xuICAgIHRoaXMudGVtcGxhdGVDYWNoZS5jbGVhcigpO1xuICB9XG5cbiAgZ2V0VGVtcGxhdGVGb3JUb29sQ2FsbChcbiAgICB0b29sQ2FsbDogVG9vbENhbGxcbiAgKTogeyB0ZW1wbGF0ZTogVGVtcGxhdGVSZWY8YW55PjsgY29udGV4dDogYW55IH0gfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy50ZW1wbGF0ZUNhY2hlLmdldCh0b29sQ2FsbC5pZCkgfHwgbnVsbDtcbiAgfVxuXG4gIHByaXZhdGUgcmVuZGVyQWxsVG9vbENhbGxzKCk6IHZvaWQge1xuICAgIGNvbnN0IG1lc3NhZ2UgPSB0aGlzLm1lc3NhZ2VTaWduYWwoKTtcbiAgICBpZiAoIW1lc3NhZ2UgfHwgIW1lc3NhZ2UudG9vbENhbGxzIHx8IG1lc3NhZ2UudG9vbENhbGxzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIENsZWFyIGV4aXN0aW5nIHJlbmRlcnNcbiAgICB0aGlzLmNvbXBvbmVudFJlZnMuZm9yRWFjaCgocmVmKSA9PiByZWYuZGVzdHJveSgpKTtcbiAgICB0aGlzLmNvbXBvbmVudFJlZnMuY2xlYXIoKTtcbiAgICB0aGlzLnRlbXBsYXRlQ2FjaGUuY2xlYXIoKTtcblxuICAgIGlmICghdGhpcy5jb3BpbG90a2l0IHx8ICF0aGlzLmNvbnRhaW5lcikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IG1lc3NhZ2VzID0gdGhpcy5tZXNzYWdlc1NpZ25hbCgpO1xuICAgIGNvbnN0IGlzTG9hZGluZyA9IHRoaXMuaXNMb2FkaW5nU2lnbmFsKCk7XG5cbiAgICAvLyBSZW5kZXIgZWFjaCB0b29sIGNhbGxcbiAgICBtZXNzYWdlLnRvb2xDYWxscy5mb3JFYWNoKCh0b29sQ2FsbCkgPT4ge1xuICAgICAgY29uc3QgdG9vbE1lc3NhZ2UgPSBtZXNzYWdlcy5maW5kKFxuICAgICAgICAobSkgPT5cbiAgICAgICAgICBtLnJvbGUgPT09IFwidG9vbFwiICYmIChtIGFzIFRvb2xNZXNzYWdlKS50b29sQ2FsbElkID09PSB0b29sQ2FsbC5pZFxuICAgICAgKSBhcyBUb29sTWVzc2FnZSB8IHVuZGVmaW5lZDtcblxuICAgICAgdGhpcy5yZW5kZXJTaW5nbGVUb29sQ2FsbCh0b29sQ2FsbCwgdG9vbE1lc3NhZ2UsIGlzTG9hZGluZyk7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIHJlbmRlclNpbmdsZVRvb2xDYWxsKFxuICAgIHRvb2xDYWxsOiBUb29sQ2FsbCxcbiAgICB0b29sTWVzc2FnZTogVG9vbE1lc3NhZ2UgfCB1bmRlZmluZWQsXG4gICAgaXNMb2FkaW5nOiBib29sZWFuXG4gICk6IHZvaWQge1xuICAgIGlmICghdGhpcy5jb3BpbG90a2l0KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gR2V0IGN1cnJlbnQgcmVuZGVyIHRvb2wgY2FsbHNcbiAgICBjb25zdCBjdXJyZW50UmVuZGVyVG9vbENhbGxzID0gdGhpcy5jb3BpbG90a2l0LmN1cnJlbnRSZW5kZXJUb29sQ2FsbHMoKTtcblxuICAgIC8vIEZpbmQgdGhlIHJlbmRlciBjb25maWcgZm9yIHRoaXMgdG9vbCBjYWxsIGJ5IG5hbWVcbiAgICAvLyBBbHNvIGNoZWNrIGZvciB3aWxkY2FyZCAoKikgcmVuZGVycyBpZiBubyBleGFjdCBtYXRjaFxuICAgIGNvbnN0IHJlbmRlckNvbmZpZyA9XG4gICAgICBjdXJyZW50UmVuZGVyVG9vbENhbGxzLmZpbmQoXG4gICAgICAgIChyYzogVG9vbENhbGxSZW5kZXIpID0+IHJjLm5hbWUgPT09IHRvb2xDYWxsLmZ1bmN0aW9uLm5hbWVcbiAgICAgICkgfHwgY3VycmVudFJlbmRlclRvb2xDYWxscy5maW5kKChyYzogVG9vbENhbGxSZW5kZXIpID0+IHJjLm5hbWUgPT09IFwiKlwiKTtcblxuICAgIGlmICghcmVuZGVyQ29uZmlnKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gUGFyc2UgdGhlIGFyZ3VtZW50cyBpZiB0aGV5J3JlIGEgc3RyaW5nXG4gICAgY29uc3QgYXJncyA9IHBhcnRpYWxKU09OUGFyc2UodG9vbENhbGwuZnVuY3Rpb24uYXJndW1lbnRzKTtcblxuICAgIC8vIERldGVybWluZSBzdGF0dXNcbiAgICBsZXQgc3RhdHVzOiBUb29sQ2FsbFN0YXR1cztcbiAgICBpZiAodG9vbE1lc3NhZ2UpIHtcbiAgICAgIHN0YXR1cyA9IFRvb2xDYWxsU3RhdHVzLkNvbXBsZXRlO1xuICAgIH0gZWxzZSBpZiAoaXNMb2FkaW5nKSB7XG4gICAgICBzdGF0dXMgPSBUb29sQ2FsbFN0YXR1cy5JblByb2dyZXNzO1xuICAgIH0gZWxzZSB7XG4gICAgICBzdGF0dXMgPSBUb29sQ2FsbFN0YXR1cy5Db21wbGV0ZTtcbiAgICB9XG5cbiAgICAvLyBDcmVhdGUgcHJvcHMgYmFzZWQgb24gc3RhdHVzIC0gdXNlIGRpc2NyaW1pbmF0ZWQgdW5pb24gcHJvcGVybHlcbiAgICBsZXQgcHJvcHM6IFRvb2xDYWxsUHJvcHM7XG4gICAgaWYgKHN0YXR1cyA9PT0gVG9vbENhbGxTdGF0dXMuSW5Qcm9ncmVzcykge1xuICAgICAgcHJvcHMgPSB7XG4gICAgICAgIG5hbWU6IHRvb2xDYWxsLmZ1bmN0aW9uLm5hbWUsXG4gICAgICAgIGRlc2NyaXB0aW9uOiBcIlwiLFxuICAgICAgICBhcmdzOiBhcmdzLCAvLyBQYXJ0aWFsIGFyZ3MgZm9yIEluUHJvZ3Jlc3NcbiAgICAgICAgc3RhdHVzOiBUb29sQ2FsbFN0YXR1cy5JblByb2dyZXNzLFxuICAgICAgICByZXN1bHQ6IHVuZGVmaW5lZCxcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIENvbXBsZXRlIHN0YXR1c1xuICAgICAgcHJvcHMgPSB7XG4gICAgICAgIG5hbWU6IHRvb2xDYWxsLmZ1bmN0aW9uLm5hbWUsXG4gICAgICAgIGRlc2NyaXB0aW9uOiBcIlwiLFxuICAgICAgICBhcmdzOiBhcmdzLCAvLyBGdWxsIGFyZ3MgZm9yIENvbXBsZXRlXG4gICAgICAgIHN0YXR1czogVG9vbENhbGxTdGF0dXMuQ29tcGxldGUsXG4gICAgICAgIHJlc3VsdDogdG9vbE1lc3NhZ2U/LmNvbnRlbnQgfHwgXCJcIixcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgaWYgcmVuZGVyIGlzIGEgQ29tcG9uZW50IGNsYXNzIG9yIFRlbXBsYXRlUmVmXG4gICAgaWYgKHRoaXMuaXNDb21wb25lbnRDbGFzcyhyZW5kZXJDb25maWcucmVuZGVyKSkge1xuICAgICAgLy8gQ3JlYXRlIGNvbXBvbmVudCBkeW5hbWljYWxseVxuICAgICAgdGhpcy5yZW5kZXJDb21wb25lbnQodG9vbENhbGwuaWQsIHJlbmRlckNvbmZpZy5yZW5kZXIsIHByb3BzKTtcbiAgICB9IGVsc2UgaWYgKHRoaXMuaXNUZW1wbGF0ZVJlZihyZW5kZXJDb25maWcucmVuZGVyKSkge1xuICAgICAgLy8gVXNlIHRlbXBsYXRlXG4gICAgICB0aGlzLnJlbmRlclRlbXBsYXRlKHRvb2xDYWxsLmlkLCByZW5kZXJDb25maWcucmVuZGVyLCBwcm9wcyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZW5kZXJDb21wb25lbnQoXG4gICAgdG9vbENhbGxJZDogc3RyaW5nLFxuICAgIGNvbXBvbmVudENsYXNzOiBUeXBlPGFueT4sXG4gICAgcHJvcHM6IFRvb2xDYWxsUHJvcHNcbiAgKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmNvbnRhaW5lcikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIENyZWF0ZSB0aGUgY29tcG9uZW50XG4gICAgY29uc3QgY29tcG9uZW50UmVmID0gdGhpcy5jb250YWluZXIuY3JlYXRlQ29tcG9uZW50KGNvbXBvbmVudENsYXNzKTtcbiAgICB0aGlzLmNvbXBvbmVudFJlZnMuc2V0KHRvb2xDYWxsSWQsIGNvbXBvbmVudFJlZik7XG5cbiAgICAvLyBTZXQgaW5wdXRzIG9uIHRoZSBjb21wb25lbnRcbiAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhwcm9wcykpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbXBvbmVudFJlZi5zZXRJbnB1dChrZXksIHZhbHVlKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgLy8gSW5wdXQgbWlnaHQgbm90IGV4aXN0IG9uIHRoZSBjb21wb25lbnQsIHdoaWNoIGlzIGZpbmVcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBUcmlnZ2VyIGNoYW5nZSBkZXRlY3Rpb25cbiAgICBjb21wb25lbnRSZWYuY2hhbmdlRGV0ZWN0b3JSZWYuZGV0ZWN0Q2hhbmdlcygpO1xuICB9XG5cbiAgcHJpdmF0ZSByZW5kZXJUZW1wbGF0ZShcbiAgICB0b29sQ2FsbElkOiBzdHJpbmcsXG4gICAgdGVtcGxhdGU6IFRlbXBsYXRlUmVmPGFueT4sXG4gICAgcHJvcHM6IFRvb2xDYWxsUHJvcHNcbiAgKTogdm9pZCB7XG4gICAgdGhpcy50ZW1wbGF0ZUNhY2hlLnNldCh0b29sQ2FsbElkLCB7XG4gICAgICB0ZW1wbGF0ZSxcbiAgICAgIGNvbnRleHQ6IHtcbiAgICAgICAgJGltcGxpY2l0OiBwcm9wcyxcbiAgICAgICAgbmFtZTogcHJvcHMubmFtZSxcbiAgICAgICAgZGVzY3JpcHRpb246IHByb3BzLmRlc2NyaXB0aW9uLFxuICAgICAgICBhcmdzOiBwcm9wcy5hcmdzLFxuICAgICAgICBzdGF0dXM6IHByb3BzLnN0YXR1cyxcbiAgICAgICAgcmVzdWx0OiBwcm9wcy5yZXN1bHQsXG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBpc0NvbXBvbmVudENsYXNzKHZhbHVlOiBhbnkpOiB2YWx1ZSBpcyBUeXBlPGFueT4ge1xuICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT09IFwiZnVuY3Rpb25cIiAmJiB2YWx1ZS5wcm90b3R5cGU7XG4gIH1cblxuICBwcml2YXRlIGlzVGVtcGxhdGVSZWYodmFsdWU6IGFueSk6IHZhbHVlIGlzIFRlbXBsYXRlUmVmPGFueT4ge1xuICAgIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFRlbXBsYXRlUmVmO1xuICB9XG59XG4iXX0=
@@ -0,0 +1,25 @@
1
+ import { Component, Input, signal, computed, ChangeDetectionStrategy, ViewEncapsulation } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { cn } from '../../lib/utils';
4
+ import * as i0 from "@angular/core";
5
+ export class CopilotChatToolbarComponent {
6
+ set inputClass(val) {
7
+ this.customClass.set(val);
8
+ }
9
+ customClass = signal(undefined);
10
+ computedClass = computed(() => {
11
+ const baseClasses = 'w-full h-[60px] bg-transparent flex items-center justify-between';
12
+ return cn(baseClasses, this.customClass());
13
+ });
14
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CopilotChatToolbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
15
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: CopilotChatToolbarComponent, isStandalone: true, selector: "div[copilotChatToolbar]", inputs: { inputClass: "inputClass" }, host: { properties: { "class": "computedClass()" } }, ngImport: i0, template: `<ng-content></ng-content>`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
16
+ }
17
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CopilotChatToolbarComponent, decorators: [{
18
+ type: Component,
19
+ args: [{ selector: 'div[copilotChatToolbar]', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
20
+ '[class]': 'computedClass()'
21
+ }, template: `<ng-content></ng-content>` }]
22
+ }], propDecorators: { inputClass: [{
23
+ type: Input
24
+ }] } });
25
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29waWxvdC1jaGF0LXRvb2xiYXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvY2hhdC9jb3BpbG90LWNoYXQtdG9vbGJhci5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFNBQVMsRUFDVCxLQUFLLEVBQ0wsTUFBTSxFQUNOLFFBQVEsRUFDUix1QkFBdUIsRUFDdkIsaUJBQWlCLEVBQ2xCLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0saUJBQWlCLENBQUM7O0FBY3JDLE1BQU0sT0FBTywyQkFBMkI7SUFDdEMsSUFBYSxVQUFVLENBQUMsR0FBdUI7UUFDN0MsSUFBSSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDNUIsQ0FBQztJQUVELFdBQVcsR0FBRyxNQUFNLENBQXFCLFNBQVMsQ0FBQyxDQUFDO0lBRXBELGFBQWEsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFO1FBQzVCLE1BQU0sV0FBVyxHQUFHLGtFQUFrRSxDQUFDO1FBQ3ZGLE9BQU8sRUFBRSxDQUFDLFdBQVcsRUFBRSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztJQUM3QyxDQUFDLENBQUMsQ0FBQzt3R0FWUSwyQkFBMkI7NEZBQTNCLDJCQUEyQiwrS0FINUIsMkJBQTJCLDJEQU4zQixZQUFZOzs0RkFTWCwyQkFBMkI7a0JBWnZDLFNBQVM7K0JBQ0UseUJBQXlCLGNBQ3ZCLElBQUksV0FDUCxDQUFDLFlBQVksQ0FBQyxtQkFDTix1QkFBdUIsQ0FBQyxNQUFNLGlCQUNoQyxpQkFBaUIsQ0FBQyxJQUFJLFFBQy9CO3dCQUNKLFNBQVMsRUFBRSxpQkFBaUI7cUJBQzdCLFlBQ1MsMkJBQTJCOzhCQUl4QixVQUFVO3NCQUF0QixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBJbnB1dCxcbiAgc2lnbmFsLFxuICBjb21wdXRlZCxcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIFZpZXdFbmNhcHN1bGF0aW9uXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IGNuIH0gZnJvbSAnLi4vLi4vbGliL3V0aWxzJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnZGl2W2NvcGlsb3RDaGF0VG9vbGJhcl0nLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gIGhvc3Q6IHtcbiAgICAnW2NsYXNzXSc6ICdjb21wdXRlZENsYXNzKCknXG4gIH0sXG4gIHRlbXBsYXRlOiBgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PmAsXG4gIHN0eWxlczogW11cbn0pXG5leHBvcnQgY2xhc3MgQ29waWxvdENoYXRUb29sYmFyQ29tcG9uZW50IHtcbiAgQElucHV0KCkgc2V0IGlucHV0Q2xhc3ModmFsOiBzdHJpbmcgfCB1bmRlZmluZWQpIHtcbiAgICB0aGlzLmN1c3RvbUNsYXNzLnNldCh2YWwpO1xuICB9XG4gIFxuICBjdXN0b21DbGFzcyA9IHNpZ25hbDxzdHJpbmcgfCB1bmRlZmluZWQ+KHVuZGVmaW5lZCk7XG4gIFxuICBjb21wdXRlZENsYXNzID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIGNvbnN0IGJhc2VDbGFzc2VzID0gJ3ctZnVsbCBoLVs2MHB4XSBiZy10cmFuc3BhcmVudCBmbGV4IGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWJldHdlZW4nO1xuICAgIHJldHVybiBjbihiYXNlQ2xhc3NlcywgdGhpcy5jdXN0b21DbGFzcygpKTtcbiAgfSk7XG59Il19
@@ -0,0 +1,199 @@
1
+ import { Component, Input, signal, computed, inject, ChangeDetectionStrategy, ViewEncapsulation } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { CdkMenuModule } from '@angular/cdk/menu';
4
+ import { OverlayModule } from '@angular/cdk/overlay';
5
+ import { LucideAngularModule, Settings2, ChevronRight } from 'lucide-angular';
6
+ import { CopilotChatConfigurationService } from '../../core/chat-configuration/chat-configuration.service';
7
+ import { cn } from '../../lib/utils';
8
+ import * as i0 from "@angular/core";
9
+ import * as i1 from "@angular/cdk/menu";
10
+ import * as i2 from "lucide-angular";
11
+ export class CopilotChatToolsMenuComponent {
12
+ Settings2Icon = Settings2;
13
+ ChevronRightIcon = ChevronRight;
14
+ set inputToolsMenu(val) {
15
+ this.toolsMenu.set(val || []);
16
+ }
17
+ set inputDisabled(val) {
18
+ this.disabled.set(val || false);
19
+ }
20
+ set inputClass(val) {
21
+ this.customClass.set(val);
22
+ }
23
+ chatConfig = inject(CopilotChatConfigurationService);
24
+ toolsMenu = signal([]);
25
+ disabled = signal(false);
26
+ customClass = signal(undefined);
27
+ hasItems = computed(() => this.toolsMenu().length > 0);
28
+ label = computed(() => this.chatConfig.labels().chatInputToolbarToolsButtonLabel);
29
+ buttonClass = computed(() => {
30
+ const baseClasses = cn(
31
+ // Base button styles
32
+ 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-full text-sm font-medium', 'transition-all disabled:pointer-events-none disabled:opacity-50', 'shrink-0 outline-none', 'focus-visible:ring-[3px]',
33
+ // chatInputToolbarSecondary variant
34
+ 'cursor-pointer', 'bg-transparent text-[#444444]', 'dark:text-white dark:border-[#404040]', 'transition-colors', 'focus:outline-none', 'hover:bg-[#f8f8f8] hover:text-[#333333]', 'dark:hover:bg-[#404040] dark:hover:text-[#FFFFFF]', 'disabled:cursor-not-allowed disabled:opacity-50', 'disabled:hover:bg-transparent disabled:hover:text-[#444444]', 'dark:disabled:hover:bg-transparent dark:disabled:hover:text-[#CCCCCC]',
35
+ // Size
36
+ 'h-9 px-3 gap-2 font-normal');
37
+ return cn(baseClasses, this.customClass());
38
+ });
39
+ isMenuItem(item) {
40
+ return item && typeof item === 'object' && 'label' in item;
41
+ }
42
+ handleItemClick(item) {
43
+ if (item.action) {
44
+ item.action();
45
+ }
46
+ }
47
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CopilotChatToolsMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
48
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: CopilotChatToolsMenuComponent, isStandalone: true, selector: "copilot-chat-tools-menu", inputs: { inputToolsMenu: "inputToolsMenu", inputDisabled: "inputDisabled", inputClass: "inputClass" }, ngImport: i0, template: `
49
+ @if (hasItems()) {
50
+ <button
51
+ type="button"
52
+ [disabled]="disabled()"
53
+ [class]="buttonClass()"
54
+ [cdkMenuTriggerFor]="menu"
55
+ >
56
+ <lucide-angular [img]="Settings2Icon" [size]="18"></lucide-angular>
57
+ <span class="text-sm font-normal">{{ label() }}</span>
58
+ </button>
59
+
60
+ <ng-template #menu>
61
+ <div class="min-w-[200px] bg-white dark:bg-[#1F1F1F] border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg p-1"
62
+ cdkMenu>
63
+ @for (item of toolsMenu(); track $index) {
64
+ @if (item === '-') {
65
+ <div class="h-px bg-gray-200 dark:bg-gray-700 my-1"></div>
66
+ } @else if (isMenuItem(item)) {
67
+ @if (item.items && item.items.length > 0) {
68
+ <!-- Submenu trigger -->
69
+ <button
70
+ type="button"
71
+ class="w-full px-3 py-2 text-left bg-transparent border-none rounded hover:bg-gray-100 dark:hover:bg-gray-800 cursor-pointer text-sm flex items-center justify-between"
72
+ [cdkMenuTriggerFor]="submenu"
73
+ cdkMenuItem
74
+ >
75
+ {{ item.label }}
76
+ <lucide-angular [img]="ChevronRightIcon" [size]="12" class="ml-auto"></lucide-angular>
77
+ </button>
78
+
79
+ <!-- Submenu template -->
80
+ <ng-template #submenu>
81
+ <div class="min-w-[200px] bg-white dark:bg-[#1F1F1F] border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg p-1"
82
+ cdkMenu>
83
+ @for (subItem of item.items; track $index) {
84
+ @if (subItem === '-') {
85
+ <div class="h-px bg-gray-200 dark:bg-gray-700 my-1"></div>
86
+ } @else if (isMenuItem(subItem)) {
87
+ <button
88
+ type="button"
89
+ class="w-full px-3 py-2 text-left bg-transparent border-none rounded hover:bg-gray-100 dark:hover:bg-gray-800 cursor-pointer text-sm"
90
+ (click)="handleItemClick(subItem)"
91
+ cdkMenuItem
92
+ >
93
+ {{ subItem.label }}
94
+ </button>
95
+ }
96
+ }
97
+ </div>
98
+ </ng-template>
99
+ } @else {
100
+ <!-- Regular menu item -->
101
+ <button
102
+ type="button"
103
+ class="w-full px-3 py-2 text-left bg-transparent border-none rounded hover:bg-gray-100 dark:hover:bg-gray-800 cursor-pointer text-sm"
104
+ (click)="handleItemClick(item)"
105
+ cdkMenuItem
106
+ >
107
+ {{ item.label }}
108
+ </button>
109
+ }
110
+ }
111
+ }
112
+ </div>
113
+ </ng-template>
114
+ }
115
+ `, isInline: true, styles: [".cdk-overlay-pane{position:absolute;pointer-events:auto;z-index:1000}.cdk-overlay-container{position:fixed;z-index:1000}[cdkMenu]{animation:menuFadeIn .15s ease-out}@keyframes menuFadeIn{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: CdkMenuModule }, { kind: "directive", type: i1.CdkMenu, selector: "[cdkMenu]", outputs: ["closed"], exportAs: ["cdkMenu"] }, { kind: "directive", type: i1.CdkMenuItem, selector: "[cdkMenuItem]", inputs: ["cdkMenuItemDisabled", "cdkMenuitemTypeaheadLabel"], outputs: ["cdkMenuItemTriggered"], exportAs: ["cdkMenuItem"] }, { kind: "directive", type: i1.CdkMenuTrigger, selector: "[cdkMenuTriggerFor]", inputs: ["cdkMenuTriggerFor", "cdkMenuPosition", "cdkMenuTriggerData"], outputs: ["cdkMenuOpened", "cdkMenuClosed"], exportAs: ["cdkMenuTriggerFor"] }, { kind: "ngmodule", type: OverlayModule }, { 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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
116
+ }
117
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CopilotChatToolsMenuComponent, decorators: [{
118
+ type: Component,
119
+ args: [{ selector: 'copilot-chat-tools-menu', standalone: true, imports: [
120
+ CommonModule,
121
+ CdkMenuModule,
122
+ OverlayModule,
123
+ LucideAngularModule
124
+ ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: `
125
+ @if (hasItems()) {
126
+ <button
127
+ type="button"
128
+ [disabled]="disabled()"
129
+ [class]="buttonClass()"
130
+ [cdkMenuTriggerFor]="menu"
131
+ >
132
+ <lucide-angular [img]="Settings2Icon" [size]="18"></lucide-angular>
133
+ <span class="text-sm font-normal">{{ label() }}</span>
134
+ </button>
135
+
136
+ <ng-template #menu>
137
+ <div class="min-w-[200px] bg-white dark:bg-[#1F1F1F] border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg p-1"
138
+ cdkMenu>
139
+ @for (item of toolsMenu(); track $index) {
140
+ @if (item === '-') {
141
+ <div class="h-px bg-gray-200 dark:bg-gray-700 my-1"></div>
142
+ } @else if (isMenuItem(item)) {
143
+ @if (item.items && item.items.length > 0) {
144
+ <!-- Submenu trigger -->
145
+ <button
146
+ type="button"
147
+ class="w-full px-3 py-2 text-left bg-transparent border-none rounded hover:bg-gray-100 dark:hover:bg-gray-800 cursor-pointer text-sm flex items-center justify-between"
148
+ [cdkMenuTriggerFor]="submenu"
149
+ cdkMenuItem
150
+ >
151
+ {{ item.label }}
152
+ <lucide-angular [img]="ChevronRightIcon" [size]="12" class="ml-auto"></lucide-angular>
153
+ </button>
154
+
155
+ <!-- Submenu template -->
156
+ <ng-template #submenu>
157
+ <div class="min-w-[200px] bg-white dark:bg-[#1F1F1F] border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg p-1"
158
+ cdkMenu>
159
+ @for (subItem of item.items; track $index) {
160
+ @if (subItem === '-') {
161
+ <div class="h-px bg-gray-200 dark:bg-gray-700 my-1"></div>
162
+ } @else if (isMenuItem(subItem)) {
163
+ <button
164
+ type="button"
165
+ class="w-full px-3 py-2 text-left bg-transparent border-none rounded hover:bg-gray-100 dark:hover:bg-gray-800 cursor-pointer text-sm"
166
+ (click)="handleItemClick(subItem)"
167
+ cdkMenuItem
168
+ >
169
+ {{ subItem.label }}
170
+ </button>
171
+ }
172
+ }
173
+ </div>
174
+ </ng-template>
175
+ } @else {
176
+ <!-- Regular menu item -->
177
+ <button
178
+ type="button"
179
+ class="w-full px-3 py-2 text-left bg-transparent border-none rounded hover:bg-gray-100 dark:hover:bg-gray-800 cursor-pointer text-sm"
180
+ (click)="handleItemClick(item)"
181
+ cdkMenuItem
182
+ >
183
+ {{ item.label }}
184
+ </button>
185
+ }
186
+ }
187
+ }
188
+ </div>
189
+ </ng-template>
190
+ }
191
+ `, styles: [".cdk-overlay-pane{position:absolute;pointer-events:auto;z-index:1000}.cdk-overlay-container{position:fixed;z-index:1000}[cdkMenu]{animation:menuFadeIn .15s ease-out}@keyframes menuFadeIn{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}\n"] }]
192
+ }], propDecorators: { inputToolsMenu: [{
193
+ type: Input
194
+ }], inputDisabled: [{
195
+ type: Input
196
+ }], inputClass: [{
197
+ type: Input
198
+ }] } });
199
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29waWxvdC1jaGF0LXRvb2xzLW1lbnUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvY2hhdC9jb3BpbG90LWNoYXQtdG9vbHMtbWVudS5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFNBQVMsRUFDVCxLQUFLLEVBQ0wsTUFBTSxFQUNOLFFBQVEsRUFDUixNQUFNLEVBQ04sdUJBQXVCLEVBQ3ZCLGlCQUFpQixFQUNsQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUNyRCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzlFLE9BQU8sRUFBRSwrQkFBK0IsRUFBRSxNQUFNLDBEQUEwRCxDQUFDO0FBRTNHLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQzs7OztBQWdIckMsTUFBTSxPQUFPLDZCQUE2QjtJQUMvQixhQUFhLEdBQUcsU0FBUyxDQUFDO0lBQzFCLGdCQUFnQixHQUFHLFlBQVksQ0FBQztJQUV6QyxJQUFhLGNBQWMsQ0FBQyxHQUF3QztRQUNsRSxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxHQUFHLElBQUksRUFBRSxDQUFDLENBQUM7SUFDaEMsQ0FBQztJQUNELElBQWEsYUFBYSxDQUFDLEdBQXdCO1FBQ2pELElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEdBQUcsSUFBSSxLQUFLLENBQUMsQ0FBQztJQUNsQyxDQUFDO0lBQ0QsSUFBYSxVQUFVLENBQUMsR0FBdUI7UUFDN0MsSUFBSSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDNUIsQ0FBQztJQUVPLFVBQVUsR0FBRyxNQUFNLENBQUMsK0JBQStCLENBQUMsQ0FBQztJQUU3RCxTQUFTLEdBQUcsTUFBTSxDQUEwQixFQUFFLENBQUMsQ0FBQztJQUNoRCxRQUFRLEdBQUcsTUFBTSxDQUFVLEtBQUssQ0FBQyxDQUFDO0lBQ2xDLFdBQVcsR0FBRyxNQUFNLENBQXFCLFNBQVMsQ0FBQyxDQUFDO0lBRXBELFFBQVEsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQztJQUV2RCxLQUFLLEdBQUcsUUFBUSxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLENBQUMsZ0NBQWdDLENBQUMsQ0FBQztJQUVsRixXQUFXLEdBQUcsUUFBUSxDQUFDLEdBQUcsRUFBRTtRQUMxQixNQUFNLFdBQVcsR0FBRyxFQUFFO1FBQ3BCLHFCQUFxQjtRQUNyQixrR0FBa0csRUFDbEcsaUVBQWlFLEVBQ2pFLHVCQUF1QixFQUN2QiwwQkFBMEI7UUFDMUIsb0NBQW9DO1FBQ3BDLGdCQUFnQixFQUNoQiwrQkFBK0IsRUFDL0IsdUNBQXVDLEVBQ3ZDLG1CQUFtQixFQUNuQixvQkFBb0IsRUFDcEIseUNBQXlDLEVBQ3pDLG1EQUFtRCxFQUNuRCxpREFBaUQsRUFDakQsNkRBQTZELEVBQzdELHVFQUF1RTtRQUN2RSxPQUFPO1FBQ1AsNEJBQTRCLENBQzdCLENBQUM7UUFDRixPQUFPLEVBQUUsQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7SUFDN0MsQ0FBQyxDQUFDLENBQUM7SUFFSCxVQUFVLENBQUMsSUFBUztRQUNsQixPQUFPLElBQUksSUFBSSxPQUFPLElBQUksS0FBSyxRQUFRLElBQUksT0FBTyxJQUFJLElBQUksQ0FBQztJQUM3RCxDQUFDO0lBRUQsZUFBZSxDQUFDLElBQW1CO1FBQ2pDLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ2hCLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNoQixDQUFDO0lBQ0gsQ0FBQzt3R0F4RFUsNkJBQTZCOzRGQUE3Qiw2QkFBNkIsMkxBbkc5Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW1FVCxtVkExRUMsWUFBWSw4QkFDWixhQUFhLHFqQkFDYixhQUFhLDhCQUNiLG1CQUFtQjs7NEZBdUdWLDZCQUE2QjtrQkE5R3pDLFNBQVM7K0JBQ0UseUJBQXlCLGNBQ3ZCLElBQUksV0FDUDt3QkFDUCxZQUFZO3dCQUNaLGFBQWE7d0JBQ2IsYUFBYTt3QkFDYixtQkFBbUI7cUJBQ3BCLG1CQUNnQix1QkFBdUIsQ0FBQyxNQUFNLGlCQUNoQyxpQkFBaUIsQ0FBQyxJQUFJLFlBQzNCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBbUVUOzhCQW9DWSxjQUFjO3NCQUExQixLQUFLO2dCQUdPLGFBQWE7c0JBQXpCLEtBQUs7Z0JBR08sVUFBVTtzQkFBdEIsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENvbXBvbmVudCxcbiAgSW5wdXQsXG4gIHNpZ25hbCxcbiAgY29tcHV0ZWQsXG4gIGluamVjdCxcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIFZpZXdFbmNhcHN1bGF0aW9uXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IENka01lbnVNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jZGsvbWVudSc7XG5pbXBvcnQgeyBPdmVybGF5TW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY2RrL292ZXJsYXknO1xuaW1wb3J0IHsgTHVjaWRlQW5ndWxhck1vZHVsZSwgU2V0dGluZ3MyLCBDaGV2cm9uUmlnaHQgfSBmcm9tICdsdWNpZGUtYW5ndWxhcic7XG5pbXBvcnQgeyBDb3BpbG90Q2hhdENvbmZpZ3VyYXRpb25TZXJ2aWNlIH0gZnJvbSAnLi4vLi4vY29yZS9jaGF0LWNvbmZpZ3VyYXRpb24vY2hhdC1jb25maWd1cmF0aW9uLnNlcnZpY2UnO1xuaW1wb3J0IHR5cGUgeyBUb29sc01lbnVJdGVtIH0gZnJvbSAnLi9jb3BpbG90LWNoYXQtaW5wdXQudHlwZXMnO1xuaW1wb3J0IHsgY24gfSBmcm9tICcuLi8uLi9saWIvdXRpbHMnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdjb3BpbG90LWNoYXQtdG9vbHMtbWVudScsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtcbiAgICBDb21tb25Nb2R1bGUsXG4gICAgQ2RrTWVudU1vZHVsZSxcbiAgICBPdmVybGF5TW9kdWxlLFxuICAgIEx1Y2lkZUFuZ3VsYXJNb2R1bGVcbiAgXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gIHRlbXBsYXRlOiBgXG4gICAgQGlmIChoYXNJdGVtcygpKSB7XG4gICAgICA8YnV0dG9uXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWQoKVwiXG4gICAgICAgIFtjbGFzc109XCJidXR0b25DbGFzcygpXCJcbiAgICAgICAgW2Nka01lbnVUcmlnZ2VyRm9yXT1cIm1lbnVcIlxuICAgICAgPlxuICAgICAgICA8bHVjaWRlLWFuZ3VsYXIgW2ltZ109XCJTZXR0aW5nczJJY29uXCIgW3NpemVdPVwiMThcIj48L2x1Y2lkZS1hbmd1bGFyPlxuICAgICAgICA8c3BhbiBjbGFzcz1cInRleHQtc20gZm9udC1ub3JtYWxcIj57eyBsYWJlbCgpIH19PC9zcGFuPlxuICAgICAgPC9idXR0b24+XG4gICAgICBcbiAgICAgIDxuZy10ZW1wbGF0ZSAjbWVudT5cbiAgICAgICAgPGRpdiBjbGFzcz1cIm1pbi13LVsyMDBweF0gYmctd2hpdGUgZGFyazpiZy1bIzFGMUYxRl0gYm9yZGVyIGJvcmRlci1ncmF5LTIwMCBkYXJrOmJvcmRlci1ncmF5LTcwMCByb3VuZGVkLWxnIHNoYWRvdy1sZyBwLTFcIlxuICAgICAgICAgICAgIGNka01lbnU+XG4gICAgICAgICAgQGZvciAoaXRlbSBvZiB0b29sc01lbnUoKTsgdHJhY2sgJGluZGV4KSB7XG4gICAgICAgICAgICBAaWYgKGl0ZW0gPT09ICctJykge1xuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiaC1weCBiZy1ncmF5LTIwMCBkYXJrOmJnLWdyYXktNzAwIG15LTFcIj48L2Rpdj5cbiAgICAgICAgICAgIH0gQGVsc2UgaWYgKGlzTWVudUl0ZW0oaXRlbSkpIHtcbiAgICAgICAgICAgICAgQGlmIChpdGVtLml0ZW1zICYmIGl0ZW0uaXRlbXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIDwhLS0gU3VibWVudSB0cmlnZ2VyIC0tPlxuICAgICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAgICAgY2xhc3M9XCJ3LWZ1bGwgcHgtMyBweS0yIHRleHQtbGVmdCBiZy10cmFuc3BhcmVudCBib3JkZXItbm9uZSByb3VuZGVkIGhvdmVyOmJnLWdyYXktMTAwIGRhcms6aG92ZXI6YmctZ3JheS04MDAgY3Vyc29yLXBvaW50ZXIgdGV4dC1zbSBmbGV4IGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWJldHdlZW5cIlxuICAgICAgICAgICAgICAgICAgW2Nka01lbnVUcmlnZ2VyRm9yXT1cInN1Ym1lbnVcIlxuICAgICAgICAgICAgICAgICAgY2RrTWVudUl0ZW1cbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICB7eyBpdGVtLmxhYmVsIH19XG4gICAgICAgICAgICAgICAgICA8bHVjaWRlLWFuZ3VsYXIgW2ltZ109XCJDaGV2cm9uUmlnaHRJY29uXCIgW3NpemVdPVwiMTJcIiBjbGFzcz1cIm1sLWF1dG9cIj48L2x1Y2lkZS1hbmd1bGFyPlxuICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIDwhLS0gU3VibWVudSB0ZW1wbGF0ZSAtLT5cbiAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgI3N1Ym1lbnU+XG4gICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWluLXctWzIwMHB4XSBiZy13aGl0ZSBkYXJrOmJnLVsjMUYxRjFGXSBib3JkZXIgYm9yZGVyLWdyYXktMjAwIGRhcms6Ym9yZGVyLWdyYXktNzAwIHJvdW5kZWQtbGcgc2hhZG93LWxnIHAtMVwiXG4gICAgICAgICAgICAgICAgICAgICAgIGNka01lbnU+XG4gICAgICAgICAgICAgICAgICAgIEBmb3IgKHN1Ykl0ZW0gb2YgaXRlbS5pdGVtczsgdHJhY2sgJGluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgQGlmIChzdWJJdGVtID09PSAnLScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJoLXB4IGJnLWdyYXktMjAwIGRhcms6YmctZ3JheS03MDAgbXktMVwiPjwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgIH0gQGVsc2UgaWYgKGlzTWVudUl0ZW0oc3ViSXRlbSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwidy1mdWxsIHB4LTMgcHktMiB0ZXh0LWxlZnQgYmctdHJhbnNwYXJlbnQgYm9yZGVyLW5vbmUgcm91bmRlZCBob3ZlcjpiZy1ncmF5LTEwMCBkYXJrOmhvdmVyOmJnLWdyYXktODAwIGN1cnNvci1wb2ludGVyIHRleHQtc21cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwiaGFuZGxlSXRlbUNsaWNrKHN1Ykl0ZW0pXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY2RrTWVudUl0ZW1cbiAgICAgICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgICAge3sgc3ViSXRlbS5sYWJlbCB9fVxuICAgICAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgICAgICA8IS0tIFJlZ3VsYXIgbWVudSBpdGVtIC0tPlxuICAgICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAgICAgY2xhc3M9XCJ3LWZ1bGwgcHgtMyBweS0yIHRleHQtbGVmdCBiZy10cmFuc3BhcmVudCBib3JkZXItbm9uZSByb3VuZGVkIGhvdmVyOmJnLWdyYXktMTAwIGRhcms6aG92ZXI6YmctZ3JheS04MDAgY3Vyc29yLXBvaW50ZXIgdGV4dC1zbVwiXG4gICAgICAgICAgICAgICAgICAoY2xpY2spPVwiaGFuZGxlSXRlbUNsaWNrKGl0ZW0pXCJcbiAgICAgICAgICAgICAgICAgIGNka01lbnVJdGVtXG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAge3sgaXRlbS5sYWJlbCB9fVxuICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgfVxuICBgLFxuICBzdHlsZXM6IFtgXG4gICAgLyogQ0RLIE92ZXJsYXkgc3R5bGVzIGZvciBwb3NpdGlvbmluZyAqL1xuICAgIC5jZGstb3ZlcmxheS1wYW5lIHtcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICAgIHBvaW50ZXItZXZlbnRzOiBhdXRvO1xuICAgICAgei1pbmRleDogMTAwMDtcbiAgICB9XG4gICAgXG4gICAgLyogRW5zdXJlIG1lbnUgYXBwZWFycyBhYm92ZSBvdGhlciBjb250ZW50ICovXG4gICAgLmNkay1vdmVybGF5LWNvbnRhaW5lciB7XG4gICAgICBwb3NpdGlvbjogZml4ZWQ7XG4gICAgICB6LWluZGV4OiAxMDAwO1xuICAgIH1cbiAgICBcbiAgICAvKiBNZW51IGFuaW1hdGlvbiAqL1xuICAgIFtjZGtNZW51XSB7XG4gICAgICBhbmltYXRpb246IG1lbnVGYWRlSW4gMC4xNXMgZWFzZS1vdXQ7XG4gICAgfVxuICAgIFxuICAgIEBrZXlmcmFtZXMgbWVudUZhZGVJbiB7XG4gICAgICBmcm9tIHtcbiAgICAgICAgb3BhY2l0eTogMDtcbiAgICAgICAgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKDRweCk7XG4gICAgICB9XG4gICAgICB0byB7XG4gICAgICAgIG9wYWNpdHk6IDE7XG4gICAgICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlWSgwKTtcbiAgICAgIH1cbiAgICB9XG4gIGBdXG59KVxuZXhwb3J0IGNsYXNzIENvcGlsb3RDaGF0VG9vbHNNZW51Q29tcG9uZW50IHtcbiAgcmVhZG9ubHkgU2V0dGluZ3MySWNvbiA9IFNldHRpbmdzMjtcbiAgcmVhZG9ubHkgQ2hldnJvblJpZ2h0SWNvbiA9IENoZXZyb25SaWdodDtcbiAgXG4gIEBJbnB1dCgpIHNldCBpbnB1dFRvb2xzTWVudSh2YWw6IChUb29sc01lbnVJdGVtIHwgJy0nKVtdIHwgdW5kZWZpbmVkKSB7XG4gICAgdGhpcy50b29sc01lbnUuc2V0KHZhbCB8fCBbXSk7XG4gIH1cbiAgQElucHV0KCkgc2V0IGlucHV0RGlzYWJsZWQodmFsOiBib29sZWFuIHwgdW5kZWZpbmVkKSB7XG4gICAgdGhpcy5kaXNhYmxlZC5zZXQodmFsIHx8IGZhbHNlKTtcbiAgfVxuICBASW5wdXQoKSBzZXQgaW5wdXRDbGFzcyh2YWw6IHN0cmluZyB8IHVuZGVmaW5lZCkge1xuICAgIHRoaXMuY3VzdG9tQ2xhc3Muc2V0KHZhbCk7XG4gIH1cbiAgXG4gIHByaXZhdGUgY2hhdENvbmZpZyA9IGluamVjdChDb3BpbG90Q2hhdENvbmZpZ3VyYXRpb25TZXJ2aWNlKTtcbiAgXG4gIHRvb2xzTWVudSA9IHNpZ25hbDwoVG9vbHNNZW51SXRlbSB8ICctJylbXT4oW10pO1xuICBkaXNhYmxlZCA9IHNpZ25hbDxib29sZWFuPihmYWxzZSk7XG4gIGN1c3RvbUNsYXNzID0gc2lnbmFsPHN0cmluZyB8IHVuZGVmaW5lZD4odW5kZWZpbmVkKTtcbiAgXG4gIGhhc0l0ZW1zID0gY29tcHV0ZWQoKCkgPT4gdGhpcy50b29sc01lbnUoKS5sZW5ndGggPiAwKTtcbiAgXG4gIGxhYmVsID0gY29tcHV0ZWQoKCkgPT4gdGhpcy5jaGF0Q29uZmlnLmxhYmVscygpLmNoYXRJbnB1dFRvb2xiYXJUb29sc0J1dHRvbkxhYmVsKTtcbiAgXG4gIGJ1dHRvbkNsYXNzID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIGNvbnN0IGJhc2VDbGFzc2VzID0gY24oXG4gICAgICAvLyBCYXNlIGJ1dHRvbiBzdHlsZXNcbiAgICAgICdpbmxpbmUtZmxleCBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgZ2FwLTIgd2hpdGVzcGFjZS1ub3dyYXAgcm91bmRlZC1mdWxsIHRleHQtc20gZm9udC1tZWRpdW0nLFxuICAgICAgJ3RyYW5zaXRpb24tYWxsIGRpc2FibGVkOnBvaW50ZXItZXZlbnRzLW5vbmUgZGlzYWJsZWQ6b3BhY2l0eS01MCcsXG4gICAgICAnc2hyaW5rLTAgb3V0bGluZS1ub25lJyxcbiAgICAgICdmb2N1cy12aXNpYmxlOnJpbmctWzNweF0nLFxuICAgICAgLy8gY2hhdElucHV0VG9vbGJhclNlY29uZGFyeSB2YXJpYW50XG4gICAgICAnY3Vyc29yLXBvaW50ZXInLFxuICAgICAgJ2JnLXRyYW5zcGFyZW50IHRleHQtWyM0NDQ0NDRdJyxcbiAgICAgICdkYXJrOnRleHQtd2hpdGUgZGFyazpib3JkZXItWyM0MDQwNDBdJyxcbiAgICAgICd0cmFuc2l0aW9uLWNvbG9ycycsXG4gICAgICAnZm9jdXM6b3V0bGluZS1ub25lJyxcbiAgICAgICdob3ZlcjpiZy1bI2Y4ZjhmOF0gaG92ZXI6dGV4dC1bIzMzMzMzM10nLFxuICAgICAgJ2Rhcms6aG92ZXI6YmctWyM0MDQwNDBdIGRhcms6aG92ZXI6dGV4dC1bI0ZGRkZGRl0nLFxuICAgICAgJ2Rpc2FibGVkOmN1cnNvci1ub3QtYWxsb3dlZCBkaXNhYmxlZDpvcGFjaXR5LTUwJyxcbiAgICAgICdkaXNhYmxlZDpob3ZlcjpiZy10cmFuc3BhcmVudCBkaXNhYmxlZDpob3Zlcjp0ZXh0LVsjNDQ0NDQ0XScsXG4gICAgICAnZGFyazpkaXNhYmxlZDpob3ZlcjpiZy10cmFuc3BhcmVudCBkYXJrOmRpc2FibGVkOmhvdmVyOnRleHQtWyNDQ0NDQ0NdJyxcbiAgICAgIC8vIFNpemVcbiAgICAgICdoLTkgcHgtMyBnYXAtMiBmb250LW5vcm1hbCdcbiAgICApO1xuICAgIHJldHVybiBjbihiYXNlQ2xhc3NlcywgdGhpcy5jdXN0b21DbGFzcygpKTtcbiAgfSk7XG4gIFxuICBpc01lbnVJdGVtKGl0ZW06IGFueSk6IGl0ZW0gaXMgVG9vbHNNZW51SXRlbSB7XG4gICAgcmV0dXJuIGl0ZW0gJiYgdHlwZW9mIGl0ZW0gPT09ICdvYmplY3QnICYmICdsYWJlbCcgaW4gaXRlbTtcbiAgfVxuICBcbiAgaGFuZGxlSXRlbUNsaWNrKGl0ZW06IFRvb2xzTWVudUl0ZW0pOiB2b2lkIHtcbiAgICBpZiAoaXRlbS5hY3Rpb24pIHtcbiAgICAgIGl0ZW0uYWN0aW9uKCk7XG4gICAgfVxuICB9XG59XG4iXX0=