@copilotkitnext/angular 0.0.2 → 0.0.5

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 (173) hide show
  1. package/README.md +3 -3
  2. package/dist/README.md +3 -3
  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/core/copilotkit.providers.d.ts +1 -1
  7. package/dist/core/copilotkit.service.d.ts +5 -5
  8. package/dist/core/copilotkit.types.d.ts +8 -10
  9. package/dist/directives/copilotkit-frontend-tool.directive.d.ts +1 -1
  10. package/dist/esm2022/components/chat/copilot-chat-assistant-message-buttons.component.mjs +384 -0
  11. package/dist/esm2022/components/chat/copilot-chat-assistant-message-renderer.component.mjs +286 -0
  12. package/dist/esm2022/components/chat/copilot-chat-assistant-message-toolbar.component.mjs +27 -0
  13. package/dist/esm2022/components/chat/copilot-chat-assistant-message.component.mjs +433 -0
  14. package/dist/esm2022/components/chat/copilot-chat-assistant-message.types.mjs +2 -0
  15. package/dist/esm2022/components/chat/copilot-chat-audio-recorder.component.mjs +202 -0
  16. package/dist/esm2022/components/chat/copilot-chat-buttons.component.mjs +321 -0
  17. package/dist/esm2022/components/chat/copilot-chat-input-defaults.mjs +38 -0
  18. package/dist/esm2022/components/chat/copilot-chat-input.component.mjs +666 -0
  19. package/dist/esm2022/components/chat/copilot-chat-input.types.mjs +10 -0
  20. package/dist/esm2022/components/chat/copilot-chat-message-view-cursor.component.mjs +45 -0
  21. package/dist/esm2022/components/chat/copilot-chat-message-view.component.mjs +296 -0
  22. package/dist/esm2022/components/chat/copilot-chat-message-view.types.mjs +2 -0
  23. package/dist/esm2022/components/chat/copilot-chat-textarea.component.mjs +188 -0
  24. package/dist/esm2022/components/chat/copilot-chat-tool-calls-view.component.mjs +216 -0
  25. package/dist/esm2022/components/chat/copilot-chat-toolbar.component.mjs +25 -0
  26. package/dist/esm2022/components/chat/copilot-chat-tools-menu.component.mjs +199 -0
  27. package/dist/esm2022/components/chat/copilot-chat-user-message-branch-navigation.component.mjs +137 -0
  28. package/dist/esm2022/components/chat/copilot-chat-user-message-buttons.component.mjs +207 -0
  29. package/dist/esm2022/components/chat/copilot-chat-user-message-renderer.component.mjs +35 -0
  30. package/dist/esm2022/components/chat/copilot-chat-user-message-toolbar.component.mjs +34 -0
  31. package/dist/esm2022/components/chat/copilot-chat-user-message.component.mjs +341 -0
  32. package/dist/esm2022/components/chat/copilot-chat-user-message.types.mjs +2 -0
  33. package/dist/esm2022/components/chat/copilot-chat-view-disclaimer.component.mjs +52 -0
  34. package/dist/esm2022/components/chat/copilot-chat-view-feather.component.mjs +55 -0
  35. package/dist/esm2022/components/chat/copilot-chat-view-handlers.service.mjs +19 -0
  36. package/dist/esm2022/components/chat/copilot-chat-view-input-container.component.mjs +110 -0
  37. package/dist/esm2022/components/chat/copilot-chat-view-scroll-to-bottom-button.component.mjs +93 -0
  38. package/dist/esm2022/components/chat/copilot-chat-view-scroll-view.component.mjs +443 -0
  39. package/dist/esm2022/components/chat/copilot-chat-view.component.mjs +479 -0
  40. package/dist/esm2022/components/chat/copilot-chat-view.types.mjs +2 -0
  41. package/dist/esm2022/components/chat/copilot-chat.component.mjs +214 -0
  42. package/dist/esm2022/components/copilotkit-tool-render.component.mjs +153 -0
  43. package/dist/esm2022/copilotkitnext-angular.mjs +5 -0
  44. package/dist/esm2022/core/chat-configuration/chat-configuration.providers.mjs +65 -0
  45. package/dist/esm2022/core/chat-configuration/chat-configuration.service.mjs +145 -0
  46. package/dist/esm2022/core/chat-configuration/chat-configuration.types.mjs +26 -0
  47. package/dist/esm2022/core/copilotkit.providers.mjs +34 -0
  48. package/dist/esm2022/core/copilotkit.service.mjs +426 -0
  49. package/dist/esm2022/core/copilotkit.types.mjs +13 -0
  50. package/dist/esm2022/directives/copilotkit-agent-context.directive.mjs +130 -0
  51. package/dist/esm2022/directives/copilotkit-agent.directive.mjs +217 -0
  52. package/dist/esm2022/directives/copilotkit-chat-config.directive.mjs +218 -0
  53. package/dist/esm2022/directives/copilotkit-config.directive.mjs +94 -0
  54. package/dist/esm2022/directives/copilotkit-frontend-tool.directive.mjs +128 -0
  55. package/dist/esm2022/directives/copilotkit-human-in-the-loop.directive.mjs +265 -0
  56. package/dist/esm2022/directives/stick-to-bottom.directive.mjs +181 -0
  57. package/dist/esm2022/index.mjs +70 -0
  58. package/dist/esm2022/lib/directives/tooltip.directive.mjs +211 -0
  59. package/dist/esm2022/lib/slots/copilot-slot.component.mjs +144 -0
  60. package/dist/esm2022/lib/slots/slot.types.mjs +6 -0
  61. package/dist/esm2022/lib/slots/slot.utils.mjs +222 -0
  62. package/dist/esm2022/lib/utils.mjs +10 -0
  63. package/dist/esm2022/services/resize-observer.service.mjs +152 -0
  64. package/dist/esm2022/services/scroll-position.service.mjs +124 -0
  65. package/dist/esm2022/types/frontend-tool.mjs +2 -0
  66. package/dist/esm2022/types/human-in-the-loop.mjs +2 -0
  67. package/dist/esm2022/utils/agent-context.utils.mjs +114 -0
  68. package/dist/esm2022/utils/agent.utils.mjs +204 -0
  69. package/dist/esm2022/utils/chat-config.utils.mjs +186 -0
  70. package/dist/esm2022/utils/copilotkit.utils.mjs +20 -0
  71. package/dist/esm2022/utils/frontend-tool.utils.mjs +224 -0
  72. package/dist/esm2022/utils/human-in-the-loop.utils.mjs +293 -0
  73. package/dist/fesm2022/copilotkitnext-angular.mjs +174 -187
  74. package/dist/fesm2022/copilotkitnext-angular.mjs.map +1 -1
  75. package/dist/utils/frontend-tool.utils.d.ts +1 -1
  76. package/package.json +23 -20
  77. package/vitest.config.mts +32 -21
  78. package/.turbo/turbo-build.log +0 -38
  79. package/.turbo/turbo-check-types.log +0 -0
  80. package/.turbo/turbo-test.log +0 -71
  81. package/ng-package.json +0 -19
  82. package/src/components/chat/__tests__/copilot-chat-assistant-message.component.spec.ts +0 -282
  83. package/src/components/chat/__tests__/copilot-chat-input.component.spec.ts +0 -419
  84. package/src/components/chat/__tests__/copilot-chat-message-view.component.spec.ts +0 -372
  85. package/src/components/chat/__tests__/copilot-chat-user-message.component.spec.ts +0 -249
  86. package/src/components/chat/copilot-chat-assistant-message-buttons.component.ts +0 -292
  87. package/src/components/chat/copilot-chat-assistant-message-renderer.component.ts +0 -472
  88. package/src/components/chat/copilot-chat-assistant-message-toolbar.component.ts +0 -29
  89. package/src/components/chat/copilot-chat-assistant-message.component.ts +0 -463
  90. package/src/components/chat/copilot-chat-assistant-message.types.ts +0 -50
  91. package/src/components/chat/copilot-chat-audio-recorder.component.ts +0 -241
  92. package/src/components/chat/copilot-chat-buttons.component.ts +0 -308
  93. package/src/components/chat/copilot-chat-buttons.component.ts.bak +0 -471
  94. package/src/components/chat/copilot-chat-input-defaults.ts +0 -47
  95. package/src/components/chat/copilot-chat-input.component.ts +0 -512
  96. package/src/components/chat/copilot-chat-input.types.ts +0 -148
  97. package/src/components/chat/copilot-chat-message-view-cursor.component.ts +0 -51
  98. package/src/components/chat/copilot-chat-message-view.component.ts +0 -233
  99. package/src/components/chat/copilot-chat-message-view.types.ts +0 -39
  100. package/src/components/chat/copilot-chat-textarea.component.ts +0 -220
  101. package/src/components/chat/copilot-chat-tool-calls-view.component.ts +0 -261
  102. package/src/components/chat/copilot-chat-toolbar.component.ts +0 -35
  103. package/src/components/chat/copilot-chat-tools-menu.component.ts +0 -185
  104. package/src/components/chat/copilot-chat-user-message-branch-navigation.component.ts +0 -121
  105. package/src/components/chat/copilot-chat-user-message-buttons.component.ts +0 -170
  106. package/src/components/chat/copilot-chat-user-message-renderer.component.ts +0 -37
  107. package/src/components/chat/copilot-chat-user-message-toolbar.component.ts +0 -37
  108. package/src/components/chat/copilot-chat-user-message.component.ts +0 -247
  109. package/src/components/chat/copilot-chat-user-message.types.ts +0 -42
  110. package/src/components/chat/copilot-chat-view-disclaimer.component.ts +0 -51
  111. package/src/components/chat/copilot-chat-view-feather.component.ts +0 -47
  112. package/src/components/chat/copilot-chat-view-handlers.service.ts +0 -14
  113. package/src/components/chat/copilot-chat-view-input-container.component.ts +0 -87
  114. package/src/components/chat/copilot-chat-view-scroll-to-bottom-button.component.ts +0 -79
  115. package/src/components/chat/copilot-chat-view-scroll-view.component.ts +0 -322
  116. package/src/components/chat/copilot-chat-view.component.ts +0 -420
  117. package/src/components/chat/copilot-chat-view.types.ts +0 -52
  118. package/src/components/chat/copilot-chat.component.ts +0 -232
  119. package/src/components/copilotkit-tool-render.component.ts +0 -169
  120. package/src/core/__tests__/copilotkit.service.spec.ts +0 -1051
  121. package/src/core/__tests__/copilotkit.service.wildcard.spec.ts +0 -316
  122. package/src/core/chat-configuration/__tests__/chat-configuration.service.spec.ts +0 -287
  123. package/src/core/chat-configuration/chat-configuration.providers.ts +0 -71
  124. package/src/core/chat-configuration/chat-configuration.service.ts +0 -162
  125. package/src/core/chat-configuration/chat-configuration.types.ts +0 -57
  126. package/src/core/copilotkit.providers.ts +0 -59
  127. package/src/core/copilotkit.service.ts +0 -542
  128. package/src/core/copilotkit.types.ts +0 -132
  129. package/src/directives/__tests__/copilotkit-agent-context.directive.spec.ts +0 -384
  130. package/src/directives/__tests__/copilotkit-agent.directive.spec.ts +0 -253
  131. package/src/directives/__tests__/copilotkit-chat-config.directive.spec.ts +0 -385
  132. package/src/directives/__tests__/copilotkit-config.directive.spec.ts +0 -69
  133. package/src/directives/__tests__/copilotkit-frontend-tool-simple.directive.spec.ts +0 -60
  134. package/src/directives/__tests__/copilotkit-frontend-tool.directive.spec.ts +0 -108
  135. package/src/directives/__tests__/copilotkit-human-in-the-loop.directive.spec.ts +0 -452
  136. package/src/directives/copilotkit-agent-context.directive.ts +0 -138
  137. package/src/directives/copilotkit-agent.directive.ts +0 -225
  138. package/src/directives/copilotkit-chat-config.directive.ts +0 -241
  139. package/src/directives/copilotkit-config.directive.ts +0 -81
  140. package/src/directives/copilotkit-frontend-tool.directive.ts +0 -145
  141. package/src/directives/copilotkit-human-in-the-loop.directive.ts +0 -281
  142. package/src/directives/stick-to-bottom.directive.ts +0 -204
  143. package/src/index.ts +0 -105
  144. package/src/lib/directives/tooltip.directive.ts +0 -292
  145. package/src/lib/slots/__tests__/slot.utils.spec.ts +0 -377
  146. package/src/lib/slots/copilot-slot.component.ts +0 -135
  147. package/src/lib/slots/index.ts +0 -3
  148. package/src/lib/slots/slot.types.ts +0 -64
  149. package/src/lib/slots/slot.utils.ts +0 -289
  150. package/src/lib/utils.ts +0 -10
  151. package/src/public-api.ts +0 -1
  152. package/src/services/resize-observer.service.ts +0 -181
  153. package/src/services/scroll-position.service.ts +0 -169
  154. package/src/styles/globals.css +0 -266
  155. package/src/styles/index.css +0 -3
  156. package/src/test-setup.ts +0 -15
  157. package/src/testing/index.ts +0 -3
  158. package/src/testing/testing.utils.ts +0 -248
  159. package/src/types/frontend-tool.ts +0 -44
  160. package/src/types/human-in-the-loop.ts +0 -52
  161. package/src/utils/__tests__/agent.utils.spec.ts +0 -234
  162. package/src/utils/__tests__/chat-config.utils.spec.ts +0 -306
  163. package/src/utils/__tests__/frontend-tool-inject.spec.ts +0 -350
  164. package/src/utils/__tests__/frontend-tool-integration.spec.ts +0 -199
  165. package/src/utils/__tests__/frontend-tool.utils.spec.ts +0 -272
  166. package/src/utils/__tests__/human-in-the-loop.utils.spec.ts +0 -365
  167. package/src/utils/agent-context.utils.ts +0 -133
  168. package/src/utils/agent.utils.ts +0 -239
  169. package/src/utils/chat-config.utils.ts +0 -221
  170. package/src/utils/copilotkit.utils.ts +0 -20
  171. package/src/utils/frontend-tool.utils.ts +0 -266
  172. package/src/utils/human-in-the-loop.utils.ts +0 -359
  173. package/tsconfig.spec.json +0 -12
@@ -0,0 +1,186 @@
1
+ import { inject } from '@angular/core';
2
+ import { CopilotChatConfigurationService } from '../core/chat-configuration/chat-configuration.service';
3
+ /**
4
+ * Watches chat configuration and provides reactive access to all configuration values.
5
+ * Must be called within an injection context.
6
+ *
7
+ * @returns Object with reactive signals and handler functions
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * export class ChatInputComponent {
12
+ * config = watchChatConfig();
13
+ *
14
+ * constructor() {
15
+ * effect(() => {
16
+ * const placeholder = this.config.labels().chatInputPlaceholder;
17
+ * console.log('Placeholder:', placeholder);
18
+ * });
19
+ * }
20
+ *
21
+ * handleSubmit(value: string) {
22
+ * this.config.submitInput(value);
23
+ * }
24
+ * }
25
+ * ```
26
+ */
27
+ export function watchChatConfig() {
28
+ const service = inject(CopilotChatConfigurationService);
29
+ return {
30
+ labels: service.labels,
31
+ inputValue: service.inputValue,
32
+ submitInput: (value) => service.submitInput(value),
33
+ changeInput: (value) => service.changeInput(value)
34
+ };
35
+ }
36
+ /**
37
+ * Registers chat configuration within an injection context.
38
+ * Automatically updates the configuration when called.
39
+ *
40
+ * @param config - The configuration to register
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * export class ChatComponent {
45
+ * constructor() {
46
+ * registerChatConfig({
47
+ * labels: {
48
+ * chatInputPlaceholder: "How can I help?"
49
+ * },
50
+ * onSubmitInput: (value) => this.handleSubmit(value)
51
+ * });
52
+ * }
53
+ * }
54
+ * ```
55
+ */
56
+ export function registerChatConfig(config) {
57
+ const service = inject(CopilotChatConfigurationService);
58
+ service.updateConfiguration(config);
59
+ }
60
+ /**
61
+ * Gets the current chat labels signal.
62
+ *
63
+ * @param service - The CopilotChatConfigurationService instance
64
+ * @returns Signal containing the current labels
65
+ *
66
+ * @example
67
+ * ```typescript
68
+ * export class ChatComponent {
69
+ * constructor(private chatConfig: CopilotChatConfigurationService) {
70
+ * const labels = getChatLabels(this.chatConfig);
71
+ * effect(() => {
72
+ * console.log('Current labels:', labels());
73
+ * });
74
+ * }
75
+ * }
76
+ * ```
77
+ */
78
+ export function getChatLabels(service) {
79
+ return service.labels;
80
+ }
81
+ /**
82
+ * Updates chat labels.
83
+ *
84
+ * @param service - The CopilotChatConfigurationService instance
85
+ * @param labels - Partial labels to merge with defaults
86
+ *
87
+ * @example
88
+ * ```typescript
89
+ * export class ChatComponent {
90
+ * updatePlaceholder(text: string) {
91
+ * setChatLabels(this.chatConfig, {
92
+ * chatInputPlaceholder: text
93
+ * });
94
+ * }
95
+ * }
96
+ * ```
97
+ */
98
+ export function setChatLabels(service, labels) {
99
+ service.setLabels(labels);
100
+ }
101
+ /**
102
+ * Gets the current input value signal.
103
+ *
104
+ * @param service - The CopilotChatConfigurationService instance
105
+ * @returns Signal containing the current input value
106
+ *
107
+ * @example
108
+ * ```typescript
109
+ * export class ChatInputComponent {
110
+ * inputValue = getChatInputValue(this.chatConfig);
111
+ *
112
+ * constructor(private chatConfig: CopilotChatConfigurationService) {
113
+ * effect(() => {
114
+ * const value = this.inputValue();
115
+ * if (value) {
116
+ * this.updateTextarea(value);
117
+ * }
118
+ * });
119
+ * }
120
+ * }
121
+ * ```
122
+ */
123
+ export function getChatInputValue(service) {
124
+ return service.inputValue;
125
+ }
126
+ /**
127
+ * Sets the current input value.
128
+ *
129
+ * @param service - The CopilotChatConfigurationService instance
130
+ * @param value - The new input value
131
+ *
132
+ * @example
133
+ * ```typescript
134
+ * export class ChatInputComponent {
135
+ * onInputChange(event: Event) {
136
+ * const value = (event.target as HTMLInputElement).value;
137
+ * setChatInputValue(this.chatConfig, value);
138
+ * }
139
+ * }
140
+ * ```
141
+ */
142
+ export function setChatInputValue(service, value) {
143
+ service.setInputValue(value);
144
+ }
145
+ /**
146
+ * Creates a chat configuration controller with dynamic update capabilities.
147
+ * This is useful when you need to programmatically manage configuration.
148
+ *
149
+ * @param service - The CopilotChatConfigurationService instance
150
+ * @param initialConfig - Optional initial configuration
151
+ * @returns Controller object with update and reset methods
152
+ *
153
+ * @example
154
+ * ```typescript
155
+ * export class ChatManagerComponent {
156
+ * chatController = createChatConfigController(this.chatConfig, {
157
+ * labels: { chatInputPlaceholder: "Ask me..." }
158
+ * });
159
+ *
160
+ * constructor(private chatConfig: CopilotChatConfigurationService) {}
161
+ *
162
+ * updateForSupportMode() {
163
+ * this.chatController.update({
164
+ * labels: { chatInputPlaceholder: "Describe your issue..." }
165
+ * });
166
+ * }
167
+ *
168
+ * resetToDefaults() {
169
+ * this.chatController.reset();
170
+ * }
171
+ * }
172
+ * ```
173
+ */
174
+ export function createChatConfigController(service, initialConfig) {
175
+ // Apply initial configuration if provided
176
+ if (initialConfig) {
177
+ service.updateConfiguration(initialConfig);
178
+ }
179
+ return {
180
+ update: (config) => service.updateConfiguration(config),
181
+ reset: () => service.reset(),
182
+ getLabels: () => service.labels(),
183
+ getInputValue: () => service.inputValue()
184
+ };
185
+ }
186
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhdC1jb25maWcudXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdXRpbHMvY2hhdC1jb25maWcudXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sRUFBVSxNQUFNLGVBQWUsQ0FBQztBQUMvQyxPQUFPLEVBQUUsK0JBQStCLEVBQUUsTUFBTSx1REFBdUQsQ0FBQztBQU14Rzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F1Qkc7QUFDSCxNQUFNLFVBQVUsZUFBZTtJQU03QixNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsK0JBQStCLENBQUMsQ0FBQztJQUV4RCxPQUFPO1FBQ0wsTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUFNO1FBQ3RCLFVBQVUsRUFBRSxPQUFPLENBQUMsVUFBVTtRQUM5QixXQUFXLEVBQUUsQ0FBQyxLQUFhLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDO1FBQzFELFdBQVcsRUFBRSxDQUFDLEtBQWEsRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUM7S0FDM0QsQ0FBQztBQUNKLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW1CRztBQUNILE1BQU0sVUFBVSxrQkFBa0IsQ0FBQyxNQUFnQztJQUNqRSxNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsK0JBQStCLENBQUMsQ0FBQztJQUN4RCxPQUFPLENBQUMsbUJBQW1CLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDdEMsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7OztHQWlCRztBQUNILE1BQU0sVUFBVSxhQUFhLENBQzNCLE9BQXdDO0lBRXhDLE9BQU8sT0FBTyxDQUFDLE1BQU0sQ0FBQztBQUN4QixDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQkc7QUFDSCxNQUFNLFVBQVUsYUFBYSxDQUMzQixPQUF3QyxFQUN4QyxNQUFrQztJQUVsQyxPQUFPLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQzVCLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBcUJHO0FBQ0gsTUFBTSxVQUFVLGlCQUFpQixDQUMvQixPQUF3QztJQUV4QyxPQUFPLE9BQU8sQ0FBQyxVQUFVLENBQUM7QUFDNUIsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUNILE1BQU0sVUFBVSxpQkFBaUIsQ0FDL0IsT0FBd0MsRUFDeEMsS0FBeUI7SUFFekIsT0FBTyxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUMvQixDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E0Qkc7QUFDSCxNQUFNLFVBQVUsMEJBQTBCLENBQ3hDLE9BQXdDLEVBQ3hDLGFBQXdDO0lBT3hDLDBDQUEwQztJQUMxQyxJQUFJLGFBQWEsRUFBRSxDQUFDO1FBQ2xCLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxhQUFhLENBQUMsQ0FBQztJQUM3QyxDQUFDO0lBRUQsT0FBTztRQUNMLE1BQU0sRUFBRSxDQUFDLE1BQWdDLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxNQUFNLENBQUM7UUFDakYsS0FBSyxFQUFFLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUU7UUFDNUIsU0FBUyxFQUFFLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUU7UUFDakMsYUFBYSxFQUFFLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxVQUFVLEVBQUU7S0FDMUMsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBpbmplY3QsIFNpZ25hbCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29waWxvdENoYXRDb25maWd1cmF0aW9uU2VydmljZSB9IGZyb20gJy4uL2NvcmUvY2hhdC1jb25maWd1cmF0aW9uL2NoYXQtY29uZmlndXJhdGlvbi5zZXJ2aWNlJztcbmltcG9ydCB7IFxuICBDb3BpbG90Q2hhdENvbmZpZ3VyYXRpb24sXG4gIENvcGlsb3RDaGF0TGFiZWxzXG59IGZyb20gJy4uL2NvcmUvY2hhdC1jb25maWd1cmF0aW9uL2NoYXQtY29uZmlndXJhdGlvbi50eXBlcyc7XG5cbi8qKlxuICogV2F0Y2hlcyBjaGF0IGNvbmZpZ3VyYXRpb24gYW5kIHByb3ZpZGVzIHJlYWN0aXZlIGFjY2VzcyB0byBhbGwgY29uZmlndXJhdGlvbiB2YWx1ZXMuXG4gKiBNdXN0IGJlIGNhbGxlZCB3aXRoaW4gYW4gaW5qZWN0aW9uIGNvbnRleHQuXG4gKiBcbiAqIEByZXR1cm5zIE9iamVjdCB3aXRoIHJlYWN0aXZlIHNpZ25hbHMgYW5kIGhhbmRsZXIgZnVuY3Rpb25zXG4gKiBcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBleHBvcnQgY2xhc3MgQ2hhdElucHV0Q29tcG9uZW50IHtcbiAqICAgY29uZmlnID0gd2F0Y2hDaGF0Q29uZmlnKCk7XG4gKiAgIFxuICogICBjb25zdHJ1Y3RvcigpIHtcbiAqICAgICBlZmZlY3QoKCkgPT4ge1xuICogICAgICAgY29uc3QgcGxhY2Vob2xkZXIgPSB0aGlzLmNvbmZpZy5sYWJlbHMoKS5jaGF0SW5wdXRQbGFjZWhvbGRlcjtcbiAqICAgICAgIGNvbnNvbGUubG9nKCdQbGFjZWhvbGRlcjonLCBwbGFjZWhvbGRlcik7XG4gKiAgICAgfSk7XG4gKiAgIH1cbiAqICAgXG4gKiAgIGhhbmRsZVN1Ym1pdCh2YWx1ZTogc3RyaW5nKSB7XG4gKiAgICAgdGhpcy5jb25maWcuc3VibWl0SW5wdXQodmFsdWUpO1xuICogICB9XG4gKiB9XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHdhdGNoQ2hhdENvbmZpZygpOiB7XG4gIGxhYmVsczogU2lnbmFsPENvcGlsb3RDaGF0TGFiZWxzPjtcbiAgaW5wdXRWYWx1ZTogU2lnbmFsPHN0cmluZyB8IHVuZGVmaW5lZD47XG4gIHN1Ym1pdElucHV0OiAodmFsdWU6IHN0cmluZykgPT4gdm9pZDtcbiAgY2hhbmdlSW5wdXQ6ICh2YWx1ZTogc3RyaW5nKSA9PiB2b2lkO1xufSB7XG4gIGNvbnN0IHNlcnZpY2UgPSBpbmplY3QoQ29waWxvdENoYXRDb25maWd1cmF0aW9uU2VydmljZSk7XG4gIFxuICByZXR1cm4ge1xuICAgIGxhYmVsczogc2VydmljZS5sYWJlbHMsXG4gICAgaW5wdXRWYWx1ZTogc2VydmljZS5pbnB1dFZhbHVlLFxuICAgIHN1Ym1pdElucHV0OiAodmFsdWU6IHN0cmluZykgPT4gc2VydmljZS5zdWJtaXRJbnB1dCh2YWx1ZSksXG4gICAgY2hhbmdlSW5wdXQ6ICh2YWx1ZTogc3RyaW5nKSA9PiBzZXJ2aWNlLmNoYW5nZUlucHV0KHZhbHVlKVxuICB9O1xufVxuXG4vKipcbiAqIFJlZ2lzdGVycyBjaGF0IGNvbmZpZ3VyYXRpb24gd2l0aGluIGFuIGluamVjdGlvbiBjb250ZXh0LlxuICogQXV0b21hdGljYWxseSB1cGRhdGVzIHRoZSBjb25maWd1cmF0aW9uIHdoZW4gY2FsbGVkLlxuICogXG4gKiBAcGFyYW0gY29uZmlnIC0gVGhlIGNvbmZpZ3VyYXRpb24gdG8gcmVnaXN0ZXJcbiAqIFxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGV4cG9ydCBjbGFzcyBDaGF0Q29tcG9uZW50IHtcbiAqICAgY29uc3RydWN0b3IoKSB7XG4gKiAgICAgcmVnaXN0ZXJDaGF0Q29uZmlnKHtcbiAqICAgICAgIGxhYmVsczoge1xuICogICAgICAgICBjaGF0SW5wdXRQbGFjZWhvbGRlcjogXCJIb3cgY2FuIEkgaGVscD9cIlxuICogICAgICAgfSxcbiAqICAgICAgIG9uU3VibWl0SW5wdXQ6ICh2YWx1ZSkgPT4gdGhpcy5oYW5kbGVTdWJtaXQodmFsdWUpXG4gKiAgICAgfSk7XG4gKiAgIH1cbiAqIH1cbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJDaGF0Q29uZmlnKGNvbmZpZzogQ29waWxvdENoYXRDb25maWd1cmF0aW9uKTogdm9pZCB7XG4gIGNvbnN0IHNlcnZpY2UgPSBpbmplY3QoQ29waWxvdENoYXRDb25maWd1cmF0aW9uU2VydmljZSk7XG4gIHNlcnZpY2UudXBkYXRlQ29uZmlndXJhdGlvbihjb25maWcpO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIGN1cnJlbnQgY2hhdCBsYWJlbHMgc2lnbmFsLlxuICogXG4gKiBAcGFyYW0gc2VydmljZSAtIFRoZSBDb3BpbG90Q2hhdENvbmZpZ3VyYXRpb25TZXJ2aWNlIGluc3RhbmNlXG4gKiBAcmV0dXJucyBTaWduYWwgY29udGFpbmluZyB0aGUgY3VycmVudCBsYWJlbHNcbiAqIFxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGV4cG9ydCBjbGFzcyBDaGF0Q29tcG9uZW50IHtcbiAqICAgY29uc3RydWN0b3IocHJpdmF0ZSBjaGF0Q29uZmlnOiBDb3BpbG90Q2hhdENvbmZpZ3VyYXRpb25TZXJ2aWNlKSB7XG4gKiAgICAgY29uc3QgbGFiZWxzID0gZ2V0Q2hhdExhYmVscyh0aGlzLmNoYXRDb25maWcpO1xuICogICAgIGVmZmVjdCgoKSA9PiB7XG4gKiAgICAgICBjb25zb2xlLmxvZygnQ3VycmVudCBsYWJlbHM6JywgbGFiZWxzKCkpO1xuICogICAgIH0pO1xuICogICB9XG4gKiB9XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldENoYXRMYWJlbHMoXG4gIHNlcnZpY2U6IENvcGlsb3RDaGF0Q29uZmlndXJhdGlvblNlcnZpY2Vcbik6IFNpZ25hbDxDb3BpbG90Q2hhdExhYmVscz4ge1xuICByZXR1cm4gc2VydmljZS5sYWJlbHM7XG59XG5cbi8qKlxuICogVXBkYXRlcyBjaGF0IGxhYmVscy5cbiAqIFxuICogQHBhcmFtIHNlcnZpY2UgLSBUaGUgQ29waWxvdENoYXRDb25maWd1cmF0aW9uU2VydmljZSBpbnN0YW5jZVxuICogQHBhcmFtIGxhYmVscyAtIFBhcnRpYWwgbGFiZWxzIHRvIG1lcmdlIHdpdGggZGVmYXVsdHNcbiAqIFxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGV4cG9ydCBjbGFzcyBDaGF0Q29tcG9uZW50IHtcbiAqICAgdXBkYXRlUGxhY2Vob2xkZXIodGV4dDogc3RyaW5nKSB7XG4gKiAgICAgc2V0Q2hhdExhYmVscyh0aGlzLmNoYXRDb25maWcsIHtcbiAqICAgICAgIGNoYXRJbnB1dFBsYWNlaG9sZGVyOiB0ZXh0XG4gKiAgICAgfSk7XG4gKiAgIH1cbiAqIH1cbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0Q2hhdExhYmVscyhcbiAgc2VydmljZTogQ29waWxvdENoYXRDb25maWd1cmF0aW9uU2VydmljZSxcbiAgbGFiZWxzOiBQYXJ0aWFsPENvcGlsb3RDaGF0TGFiZWxzPlxuKTogdm9pZCB7XG4gIHNlcnZpY2Uuc2V0TGFiZWxzKGxhYmVscyk7XG59XG5cbi8qKlxuICogR2V0cyB0aGUgY3VycmVudCBpbnB1dCB2YWx1ZSBzaWduYWwuXG4gKiBcbiAqIEBwYXJhbSBzZXJ2aWNlIC0gVGhlIENvcGlsb3RDaGF0Q29uZmlndXJhdGlvblNlcnZpY2UgaW5zdGFuY2VcbiAqIEByZXR1cm5zIFNpZ25hbCBjb250YWluaW5nIHRoZSBjdXJyZW50IGlucHV0IHZhbHVlXG4gKiBcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBleHBvcnQgY2xhc3MgQ2hhdElucHV0Q29tcG9uZW50IHtcbiAqICAgaW5wdXRWYWx1ZSA9IGdldENoYXRJbnB1dFZhbHVlKHRoaXMuY2hhdENvbmZpZyk7XG4gKiAgIFxuICogICBjb25zdHJ1Y3Rvcihwcml2YXRlIGNoYXRDb25maWc6IENvcGlsb3RDaGF0Q29uZmlndXJhdGlvblNlcnZpY2UpIHtcbiAqICAgICBlZmZlY3QoKCkgPT4ge1xuICogICAgICAgY29uc3QgdmFsdWUgPSB0aGlzLmlucHV0VmFsdWUoKTtcbiAqICAgICAgIGlmICh2YWx1ZSkge1xuICogICAgICAgICB0aGlzLnVwZGF0ZVRleHRhcmVhKHZhbHVlKTtcbiAqICAgICAgIH1cbiAqICAgICB9KTtcbiAqICAgfVxuICogfVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRDaGF0SW5wdXRWYWx1ZShcbiAgc2VydmljZTogQ29waWxvdENoYXRDb25maWd1cmF0aW9uU2VydmljZVxuKTogU2lnbmFsPHN0cmluZyB8IHVuZGVmaW5lZD4ge1xuICByZXR1cm4gc2VydmljZS5pbnB1dFZhbHVlO1xufVxuXG4vKipcbiAqIFNldHMgdGhlIGN1cnJlbnQgaW5wdXQgdmFsdWUuXG4gKiBcbiAqIEBwYXJhbSBzZXJ2aWNlIC0gVGhlIENvcGlsb3RDaGF0Q29uZmlndXJhdGlvblNlcnZpY2UgaW5zdGFuY2VcbiAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBuZXcgaW5wdXQgdmFsdWVcbiAqIFxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGV4cG9ydCBjbGFzcyBDaGF0SW5wdXRDb21wb25lbnQge1xuICogICBvbklucHV0Q2hhbmdlKGV2ZW50OiBFdmVudCkge1xuICogICAgIGNvbnN0IHZhbHVlID0gKGV2ZW50LnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50KS52YWx1ZTtcbiAqICAgICBzZXRDaGF0SW5wdXRWYWx1ZSh0aGlzLmNoYXRDb25maWcsIHZhbHVlKTtcbiAqICAgfVxuICogfVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRDaGF0SW5wdXRWYWx1ZShcbiAgc2VydmljZTogQ29waWxvdENoYXRDb25maWd1cmF0aW9uU2VydmljZSxcbiAgdmFsdWU6IHN0cmluZyB8IHVuZGVmaW5lZFxuKTogdm9pZCB7XG4gIHNlcnZpY2Uuc2V0SW5wdXRWYWx1ZSh2YWx1ZSk7XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIGNoYXQgY29uZmlndXJhdGlvbiBjb250cm9sbGVyIHdpdGggZHluYW1pYyB1cGRhdGUgY2FwYWJpbGl0aWVzLlxuICogVGhpcyBpcyB1c2VmdWwgd2hlbiB5b3UgbmVlZCB0byBwcm9ncmFtbWF0aWNhbGx5IG1hbmFnZSBjb25maWd1cmF0aW9uLlxuICogXG4gKiBAcGFyYW0gc2VydmljZSAtIFRoZSBDb3BpbG90Q2hhdENvbmZpZ3VyYXRpb25TZXJ2aWNlIGluc3RhbmNlXG4gKiBAcGFyYW0gaW5pdGlhbENvbmZpZyAtIE9wdGlvbmFsIGluaXRpYWwgY29uZmlndXJhdGlvblxuICogQHJldHVybnMgQ29udHJvbGxlciBvYmplY3Qgd2l0aCB1cGRhdGUgYW5kIHJlc2V0IG1ldGhvZHNcbiAqIFxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGV4cG9ydCBjbGFzcyBDaGF0TWFuYWdlckNvbXBvbmVudCB7XG4gKiAgIGNoYXRDb250cm9sbGVyID0gY3JlYXRlQ2hhdENvbmZpZ0NvbnRyb2xsZXIodGhpcy5jaGF0Q29uZmlnLCB7XG4gKiAgICAgbGFiZWxzOiB7IGNoYXRJbnB1dFBsYWNlaG9sZGVyOiBcIkFzayBtZS4uLlwiIH1cbiAqICAgfSk7XG4gKiAgIFxuICogICBjb25zdHJ1Y3Rvcihwcml2YXRlIGNoYXRDb25maWc6IENvcGlsb3RDaGF0Q29uZmlndXJhdGlvblNlcnZpY2UpIHt9XG4gKiAgIFxuICogICB1cGRhdGVGb3JTdXBwb3J0TW9kZSgpIHtcbiAqICAgICB0aGlzLmNoYXRDb250cm9sbGVyLnVwZGF0ZSh7XG4gKiAgICAgICBsYWJlbHM6IHsgY2hhdElucHV0UGxhY2Vob2xkZXI6IFwiRGVzY3JpYmUgeW91ciBpc3N1ZS4uLlwiIH1cbiAqICAgICB9KTtcbiAqICAgfVxuICogICBcbiAqICAgcmVzZXRUb0RlZmF1bHRzKCkge1xuICogICAgIHRoaXMuY2hhdENvbnRyb2xsZXIucmVzZXQoKTtcbiAqICAgfVxuICogfVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVDaGF0Q29uZmlnQ29udHJvbGxlcihcbiAgc2VydmljZTogQ29waWxvdENoYXRDb25maWd1cmF0aW9uU2VydmljZSxcbiAgaW5pdGlhbENvbmZpZz86IENvcGlsb3RDaGF0Q29uZmlndXJhdGlvblxuKToge1xuICB1cGRhdGU6IChjb25maWc6IENvcGlsb3RDaGF0Q29uZmlndXJhdGlvbikgPT4gdm9pZDtcbiAgcmVzZXQ6ICgpID0+IHZvaWQ7XG4gIGdldExhYmVsczogKCkgPT4gQ29waWxvdENoYXRMYWJlbHM7XG4gIGdldElucHV0VmFsdWU6ICgpID0+IHN0cmluZyB8IHVuZGVmaW5lZDtcbn0ge1xuICAvLyBBcHBseSBpbml0aWFsIGNvbmZpZ3VyYXRpb24gaWYgcHJvdmlkZWRcbiAgaWYgKGluaXRpYWxDb25maWcpIHtcbiAgICBzZXJ2aWNlLnVwZGF0ZUNvbmZpZ3VyYXRpb24oaW5pdGlhbENvbmZpZyk7XG4gIH1cbiAgXG4gIHJldHVybiB7XG4gICAgdXBkYXRlOiAoY29uZmlnOiBDb3BpbG90Q2hhdENvbmZpZ3VyYXRpb24pID0+IHNlcnZpY2UudXBkYXRlQ29uZmlndXJhdGlvbihjb25maWcpLFxuICAgIHJlc2V0OiAoKSA9PiBzZXJ2aWNlLnJlc2V0KCksXG4gICAgZ2V0TGFiZWxzOiAoKSA9PiBzZXJ2aWNlLmxhYmVscygpLFxuICAgIGdldElucHV0VmFsdWU6ICgpID0+IHNlcnZpY2UuaW5wdXRWYWx1ZSgpXG4gIH07XG59Il19
@@ -0,0 +1,20 @@
1
+ import { inject } from "@angular/core";
2
+ import { CopilotKitService } from "../core/copilotkit.service";
3
+ /**
4
+ * Utility function to inject the CopilotKit service in a component or directive.
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * export class MyComponent {
9
+ * private copilotkit = injectCopilotKit();
10
+ *
11
+ * sendMessage() {
12
+ * this.copilotkit.copilotkit.sendMessage(...);
13
+ * }
14
+ * }
15
+ * ```
16
+ */
17
+ export function injectCopilotKit() {
18
+ return inject(CopilotKitService);
19
+ }
20
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29waWxvdGtpdC51dGlscy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy91dGlscy9jb3BpbG90a2l0LnV0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDdkMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFFL0Q7Ozs7Ozs7Ozs7Ozs7R0FhRztBQUNILE1BQU0sVUFBVSxnQkFBZ0I7SUFDOUIsT0FBTyxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQztBQUNuQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgaW5qZWN0IH0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcbmltcG9ydCB7IENvcGlsb3RLaXRTZXJ2aWNlIH0gZnJvbSBcIi4uL2NvcmUvY29waWxvdGtpdC5zZXJ2aWNlXCI7XG5cbi8qKlxuICogVXRpbGl0eSBmdW5jdGlvbiB0byBpbmplY3QgdGhlIENvcGlsb3RLaXQgc2VydmljZSBpbiBhIGNvbXBvbmVudCBvciBkaXJlY3RpdmUuXG4gKiBcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBleHBvcnQgY2xhc3MgTXlDb21wb25lbnQge1xuICogICBwcml2YXRlIGNvcGlsb3RraXQgPSBpbmplY3RDb3BpbG90S2l0KCk7XG4gKiAgIFxuICogICBzZW5kTWVzc2FnZSgpIHtcbiAqICAgICB0aGlzLmNvcGlsb3RraXQuY29waWxvdGtpdC5zZW5kTWVzc2FnZSguLi4pO1xuICogICB9XG4gKiB9XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluamVjdENvcGlsb3RLaXQoKSB7XG4gIHJldHVybiBpbmplY3QoQ29waWxvdEtpdFNlcnZpY2UpO1xufSJdfQ==
@@ -0,0 +1,224 @@
1
+ import { DestroyRef, inject } from '@angular/core';
2
+ import { CopilotKitService } from '../core/copilotkit.service';
3
+ /**
4
+ * Explicitly adds a frontend tool to CopilotKit.
5
+ * Requires CopilotKitService to be passed as a parameter.
6
+ *
7
+ * @param service - The CopilotKitService instance
8
+ * @param tool - The tool to add
9
+ * @returns A cleanup function that removes the tool
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * export class MyComponent implements OnInit, OnDestroy {
14
+ * private cleanupFns: Array<() => void> = [];
15
+ *
16
+ * constructor(private copilotkit: CopilotKitService) {}
17
+ *
18
+ * ngOnInit() {
19
+ * const cleanup = addFrontendTool(this.copilotkit, {
20
+ * name: 'calculator',
21
+ * description: 'Performs calculations',
22
+ * parameters: z.object({
23
+ * expression: z.string()
24
+ * }),
25
+ * handler: async (args) => {
26
+ * return eval(args.expression);
27
+ * }
28
+ * });
29
+ *
30
+ * this.cleanupFns.push(cleanup);
31
+ * }
32
+ *
33
+ * ngOnDestroy() {
34
+ * this.cleanupFns.forEach(fn => fn());
35
+ * }
36
+ * }
37
+ * ```
38
+ */
39
+ export function addFrontendTool(service, tool) {
40
+ // Add the tool to CopilotKit
41
+ service.copilotkit.addTool(tool);
42
+ // Register the render if provided
43
+ if (tool.render) {
44
+ const currentRenders = service.currentRenderToolCalls();
45
+ const existingIndex = currentRenders.findIndex((r) => r.name === tool.name);
46
+ if (existingIndex !== -1) {
47
+ console.error(`Tool with name '${tool.name}' already has a render. Skipping.`);
48
+ }
49
+ else {
50
+ const renderEntry = {
51
+ name: tool.name,
52
+ render: tool.render
53
+ };
54
+ service.setCurrentRenderToolCalls([...currentRenders, renderEntry]);
55
+ }
56
+ }
57
+ // Return cleanup function
58
+ return () => {
59
+ removeFrontendTool(service, tool.name);
60
+ };
61
+ }
62
+ /**
63
+ * Registers a frontend tool with CopilotKit and automatically removes it when the component/service is destroyed.
64
+ * Must be called within an injection context.
65
+ *
66
+ * @param tool - The tool to register
67
+ * @returns The tool name
68
+ *
69
+ * @example
70
+ * ```typescript
71
+ * export class MyComponent implements OnInit {
72
+ * ngOnInit() {
73
+ * // Automatically cleaned up on component destroy
74
+ * registerFrontendTool({
75
+ * name: 'search',
76
+ * description: 'Search for items',
77
+ * parameters: z.object({
78
+ * query: z.string()
79
+ * }),
80
+ * handler: async (args) => {
81
+ * return this.searchService.search(args.query);
82
+ * },
83
+ * render: SearchResultsComponent
84
+ * });
85
+ * }
86
+ * }
87
+ * ```
88
+ */
89
+ export function registerFrontendTool(tool) {
90
+ const service = inject(CopilotKitService);
91
+ const destroyRef = inject(DestroyRef);
92
+ // Add the tool
93
+ service.copilotkit.addTool(tool);
94
+ // Register the render if provided
95
+ if (tool.render) {
96
+ const currentRenders = service.currentRenderToolCalls();
97
+ const existingIndex = currentRenders.findIndex((r) => r.name === tool.name);
98
+ if (existingIndex !== -1) {
99
+ console.error(`Tool with name '${tool.name}' already has a render. Skipping.`);
100
+ }
101
+ else {
102
+ const renderEntry = {
103
+ name: tool.name,
104
+ render: tool.render
105
+ };
106
+ service.setCurrentRenderToolCalls([...currentRenders, renderEntry]);
107
+ }
108
+ }
109
+ // Register cleanup with Angular's DestroyRef
110
+ destroyRef.onDestroy(() => {
111
+ removeFrontendTool(service, tool.name);
112
+ });
113
+ return tool.name;
114
+ }
115
+ /**
116
+ * Explicitly removes a frontend tool from CopilotKit.
117
+ *
118
+ * @param service - The CopilotKitService instance
119
+ * @param toolName - The name of the tool to remove
120
+ *
121
+ * @example
122
+ * ```typescript
123
+ * removeFrontendTool(this.copilotkit, 'calculator');
124
+ * ```
125
+ */
126
+ export function removeFrontendTool(service, toolName) {
127
+ // Remove the tool
128
+ service.copilotkit.removeTool(toolName);
129
+ // Remove the render if it exists
130
+ const currentRenders = service.currentRenderToolCalls();
131
+ const filtered = currentRenders.filter((r) => r.name !== toolName);
132
+ if (filtered.length !== currentRenders.length) {
133
+ service.setCurrentRenderToolCalls(filtered);
134
+ }
135
+ }
136
+ /**
137
+ * Creates a frontend tool with dynamic parameters that can change over time.
138
+ * Uses Angular signals for reactivity.
139
+ *
140
+ * @param name - Tool name
141
+ * @param description - Tool description
142
+ * @param parameters - Zod schema for parameters
143
+ * @param handler - Signal or function that provides the handler
144
+ * @param render - Optional render component or template
145
+ * @returns Object with update and destroy methods
146
+ *
147
+ * @example
148
+ * ```typescript
149
+ * export class MyComponent {
150
+ * private toolConfig = signal({
151
+ * handler: async (args: any) => this.processDefault(args)
152
+ * });
153
+ *
154
+ * ngOnInit() {
155
+ * const tool = createDynamicFrontendTool(
156
+ * 'processor',
157
+ * 'Processes data',
158
+ * z.object({ data: z.string() }),
159
+ * () => this.toolConfig().handler
160
+ * );
161
+ *
162
+ * // Later, update the handler
163
+ * this.toolConfig.set({
164
+ * handler: async (args: any) => this.processAdvanced(args)
165
+ * });
166
+ * tool.update();
167
+ * }
168
+ * }
169
+ * ```
170
+ */
171
+ export function createDynamicFrontendTool(name, description, parameters, handler, render) {
172
+ const service = inject(CopilotKitService);
173
+ const destroyRef = inject(DestroyRef);
174
+ let isRegistered = false;
175
+ const update = () => {
176
+ // Remove old tool if registered
177
+ if (isRegistered) {
178
+ service.copilotkit.removeTool(name);
179
+ }
180
+ // Create new tool configuration
181
+ const desc = typeof description === 'function' ? description() : description;
182
+ const currentHandler = handler();
183
+ const currentRender = render ? render() : undefined;
184
+ const tool = {
185
+ name,
186
+ description: desc,
187
+ parameters,
188
+ handler: currentHandler,
189
+ render: currentRender
190
+ };
191
+ // Add the tool
192
+ service.copilotkit.addTool(tool);
193
+ // Update render if provided
194
+ if (currentRender) {
195
+ const currentRenders = service.currentRenderToolCalls();
196
+ const renderEntry = {
197
+ name: name,
198
+ render: currentRender
199
+ };
200
+ const existingIndex = currentRenders.findIndex((r) => r.name === name);
201
+ if (existingIndex !== -1) {
202
+ const updated = [...currentRenders];
203
+ updated[existingIndex] = renderEntry;
204
+ service.setCurrentRenderToolCalls(updated);
205
+ }
206
+ else {
207
+ service.setCurrentRenderToolCalls([...currentRenders, renderEntry]);
208
+ }
209
+ }
210
+ isRegistered = true;
211
+ };
212
+ const destroy = () => {
213
+ if (isRegistered) {
214
+ removeFrontendTool(service, name);
215
+ isRegistered = false;
216
+ }
217
+ };
218
+ // Initial setup
219
+ update();
220
+ // Register cleanup
221
+ destroyRef.onDestroy(destroy);
222
+ return { update, destroy };
223
+ }
224
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnJvbnRlbmQtdG9vbC51dGlscy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy91dGlscy9mcm9udGVuZC10b29sLnV0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ25ELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBSS9EOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW1DRztBQUNILE1BQU0sVUFBVSxlQUFlLENBQzdCLE9BQTBCLEVBQzFCLElBQTRCO0lBRTVCLDZCQUE2QjtJQUM3QixPQUFPLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUVqQyxrQ0FBa0M7SUFDbEMsSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDaEIsTUFBTSxjQUFjLEdBQUcsT0FBTyxDQUFDLHNCQUFzQixFQUFFLENBQUM7UUFDeEQsTUFBTSxhQUFhLEdBQUcsY0FBYyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQWlCLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRTVGLElBQUksYUFBYSxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDekIsT0FBTyxDQUFDLEtBQUssQ0FBQyxtQkFBbUIsSUFBSSxDQUFDLElBQUksbUNBQW1DLENBQUMsQ0FBQztRQUNqRixDQUFDO2FBQU0sQ0FBQztZQUNOLE1BQU0sV0FBVyxHQUEwQjtnQkFDekMsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJO2dCQUNmLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTTthQUNwQixDQUFDO1lBRUYsT0FBTyxDQUFDLHlCQUF5QixDQUFDLENBQUMsR0FBRyxjQUFjLEVBQUUsV0FBVyxDQUFDLENBQUMsQ0FBQztRQUN0RSxDQUFDO0lB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QUMsR0FBRyxjQUFjLEVBQUUsV0FBVyxDQUFDLENBQUMsQ0FBQztZQUN0RSxDQUFDO1FBQ0gsQ0FBQztRQUVELFlBQVksR0FBRyxJQUFJLENBQUM7SUFDdEIsQ0FBQyxDQUFDO0lBRUYsTUFBTSxPQUFPLEdBQUcsR0FBRyxFQUFFO1FBQ25CLElBQUksWUFBWSxFQUFFLENBQUM7WUFDakIsa0JBQWtCLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQ2xDLFlBQVksR0FBRyxLQUFLLENBQUM7UUFDdkIsQ0FBQztJQUNILENBQUMsQ0FBQztJQUVGLGdCQUFnQjtJQUNoQixNQUFNLEVBQUUsQ0FBQztJQUVULG1CQUFtQjtJQUNuQixVQUFVLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBRTlCLE9BQU8sRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLENBQUM7QUFDN0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERlc3Ryb3lSZWYsIGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29waWxvdEtpdFNlcnZpY2UgfSBmcm9tICcuLi9jb3JlL2NvcGlsb3RraXQuc2VydmljZSc7XG5pbXBvcnQgeyBBbmd1bGFyRnJvbnRlbmRUb29sLCBBbmd1bGFyVG9vbENhbGxSZW5kZXIsIFRvb2xDYWxsUmVuZGVyIH0gZnJvbSAnLi4vY29yZS9jb3BpbG90a2l0LnR5cGVzJztcbmltcG9ydCB0eXBlIHsgeiB9IGZyb20gJ3pvZCc7XG5cbi8qKlxuICogRXhwbGljaXRseSBhZGRzIGEgZnJvbnRlbmQgdG9vbCB0byBDb3BpbG90S2l0LlxuICogUmVxdWlyZXMgQ29waWxvdEtpdFNlcnZpY2UgdG8gYmUgcGFzc2VkIGFzIGEgcGFyYW1ldGVyLlxuICogXG4gKiBAcGFyYW0gc2VydmljZSAtIFRoZSBDb3BpbG90S2l0U2VydmljZSBpbnN0YW5jZVxuICogQHBhcmFtIHRvb2wgLSBUaGUgdG9vbCB0byBhZGRcbiAqIEByZXR1cm5zIEEgY2xlYW51cCBmdW5jdGlvbiB0aGF0IHJlbW92ZXMgdGhlIHRvb2xcbiAqIFxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGV4cG9ydCBjbGFzcyBNeUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcbiAqICAgcHJpdmF0ZSBjbGVhbnVwRm5zOiBBcnJheTwoKSA9PiB2b2lkPiA9IFtdO1xuICogICBcbiAqICAgY29uc3RydWN0b3IocHJpdmF0ZSBjb3BpbG90a2l0OiBDb3BpbG90S2l0U2VydmljZSkge31cbiAqICAgXG4gKiAgIG5nT25Jbml0KCkge1xuICogICAgIGNvbnN0IGNsZWFudXAgPSBhZGRGcm9udGVuZFRvb2wodGhpcy5jb3BpbG90a2l0LCB7XG4gKiAgICAgICBuYW1lOiAnY2FsY3VsYXRvcicsXG4gKiAgICAgICBkZXNjcmlwdGlvbjogJ1BlcmZvcm1zIGNhbGN1bGF0aW9ucycsXG4gKiAgICAgICBwYXJhbWV0ZXJzOiB6Lm9iamVjdCh7XG4gKiAgICAgICAgIGV4cHJlc3Npb246IHouc3RyaW5nKClcbiAqICAgICAgIH0pLFxuICogICAgICAgaGFuZGxlcjogYXN5bmMgKGFyZ3MpID0+IHtcbiAqICAgICAgICAgcmV0dXJuIGV2YWwoYXJncy5leHByZXNzaW9uKTtcbiAqICAgICAgIH1cbiAqICAgICB9KTtcbiAqICAgICBcbiAqICAgICB0aGlzLmNsZWFudXBGbnMucHVzaChjbGVhbnVwKTtcbiAqICAgfVxuICogICBcbiAqICAgbmdPbkRlc3Ryb3koKSB7XG4gKiAgICAgdGhpcy5jbGVhbnVwRm5zLmZvckVhY2goZm4gPT4gZm4oKSk7XG4gKiAgIH1cbiAqIH1cbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gYWRkRnJvbnRlbmRUb29sPFQgZXh0ZW5kcyBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0gUmVjb3JkPHN0cmluZywgYW55Pj4oXG4gIHNlcnZpY2U6IENvcGlsb3RLaXRTZXJ2aWNlLFxuICB0b29sOiBBbmd1bGFyRnJvbnRlbmRUb29sPFQ+XG4pOiAoKSA9PiB2b2lkIHtcbiAgLy8gQWRkIHRoZSB0b29sIHRvIENvcGlsb3RLaXRcbiAgc2VydmljZS5jb3BpbG90a2l0LmFkZFRvb2wodG9vbCk7XG4gIFxuICAvLyBSZWdpc3RlciB0aGUgcmVuZGVyIGlmIHByb3ZpZGVkXG4gIGlmICh0b29sLnJlbmRlcikge1xuICAgIGNvbnN0IGN1cnJlbnRSZW5kZXJzID0gc2VydmljZS5jdXJyZW50UmVuZGVyVG9vbENhbGxzKCk7XG4gICAgY29uc3QgZXhpc3RpbmdJbmRleCA9IGN1cnJlbnRSZW5kZXJzLmZpbmRJbmRleCgocjogVG9vbENhbGxSZW5kZXIpID0+IHIubmFtZSA9PT0gdG9vbC5uYW1lKTtcbiAgICBcbiAgICBpZiAoZXhpc3RpbmdJbmRleCAhPT0gLTEpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoYFRvb2wgd2l0aCBuYW1lICcke3Rvb2wubmFtZX0nIGFscmVhZHkgaGFzIGEgcmVuZGVyLiBTa2lwcGluZy5gKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgcmVuZGVyRW50cnk6IEFuZ3VsYXJUb29sQ2FsbFJlbmRlciA9IHtcbiAgICAgICAgbmFtZTogdG9vbC5uYW1lLFxuICAgICAgICByZW5kZXI6IHRvb2wucmVuZGVyXG4gICAgICB9O1xuICAgICAgXG4gICAgICBzZXJ2aWNlLnNldEN1cnJlbnRSZW5kZXJUb29sQ2FsbHMoWy4uLmN1cnJlbnRSZW5kZXJzLCByZW5kZXJFbnRyeV0pO1xuICAgIH1cbiAgfVxuICBcbiAgLy8gUmV0dXJuIGNsZWFudXAgZnVuY3Rpb25cbiAgcmV0dXJuICgpID0+IHtcbiAgICByZW1vdmVGcm9udGVuZFRvb2woc2VydmljZSwgdG9vbC5uYW1lKTtcbiAgfTtcbn1cblxuLyoqXG4gKiBSZWdpc3RlcnMgYSBmcm9udGVuZCB0b29sIHdpdGggQ29waWxvdEtpdCBhbmQgYXV0b21hdGljYWxseSByZW1vdmVzIGl0IHdoZW4gdGhlIGNvbXBvbmVudC9zZXJ2aWNlIGlzIGRlc3Ryb3llZC5cbiAqIE11c3QgYmUgY2FsbGVkIHdpdGhpbiBhbiBpbmplY3Rpb24gY29udGV4dC5cbiAqIFxuICogQHBhcmFtIHRvb2wgLSBUaGUgdG9vbCB0byByZWdpc3RlclxuICogQHJldHVybnMgVGhlIHRvb2wgbmFtZVxuICogXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogZXhwb3J0IGNsYXNzIE15Q29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcbiAqICAgbmdPbkluaXQoKSB7XG4gKiAgICAgLy8gQXV0b21hdGljYWxseSBjbGVhbmVkIHVwIG9uIGNvbXBvbmVudCBkZXN0cm95XG4gKiAgICAgcmVnaXN0ZXJGcm9udGVuZFRvb2woe1xuICogICAgICAgbmFtZTogJ3NlYXJjaCcsXG4gKiAgICAgICBkZXNjcmlwdGlvbjogJ1NlYXJjaCBmb3IgaXRlbXMnLFxuICogICAgICAgcGFyYW1ldGVyczogei5vYmplY3Qoe1xuICogICAgICAgICBxdWVyeTogei5zdHJpbmcoKVxuICogICAgICAgfSksXG4gKiAgICAgICBoYW5kbGVyOiBhc3luYyAoYXJncykgPT4ge1xuICogICAgICAgICByZXR1cm4gdGhpcy5zZWFyY2hTZXJ2aWNlLnNlYXJjaChhcmdzLnF1ZXJ5KTtcbiAqICAgICAgIH0sXG4gKiAgICAgICByZW5kZXI6IFNlYXJjaFJlc3VsdHNDb21wb25lbnRcbiAqICAgICB9KTtcbiAqICAgfVxuICogfVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWdpc3RlckZyb250ZW5kVG9vbDxUIGV4dGVuZHMgUmVjb3JkPHN0cmluZywgYW55PiA9IFJlY29yZDxzdHJpbmcsIGFueT4+KFxuICB0b29sOiBBbmd1bGFyRnJvbnRlbmRUb29sPFQ+XG4pOiBzdHJpbmcge1xuICBjb25zdCBzZXJ2aWNlID0gaW5qZWN0KENvcGlsb3RLaXRTZXJ2aWNlKTtcbiAgY29uc3QgZGVzdHJveVJlZiA9IGluamVjdChEZXN0cm95UmVmKTtcbiAgXG4gIC8vIEFkZCB0aGUgdG9vbFxuICBzZXJ2aWNlLmNvcGlsb3RraXQuYWRkVG9vbCh0b29sKTtcbiAgXG4gIC8vIFJlZ2lzdGVyIHRoZSByZW5kZXIgaWYgcHJvdmlkZWRcbiAgaWYgKHRvb2wucmVuZGVyKSB7XG4gICAgY29uc3QgY3VycmVudFJlbmRlcnMgPSBzZXJ2aWNlLmN1cnJlbnRSZW5kZXJUb29sQ2FsbHMoKTtcbiAgICBjb25zdCBleGlzdGluZ0luZGV4ID0gY3VycmVudFJlbmRlcnMuZmluZEluZGV4KChyOiBUb29sQ2FsbFJlbmRlcikgPT4gci5uYW1lID09PSB0b29sLm5hbWUpO1xuICAgIFxuICAgIGlmIChleGlzdGluZ0luZGV4ICE9PSAtMSkge1xuICAgICAgY29uc29sZS5lcnJvcihgVG9vbCB3aXRoIG5hbWUgJyR7dG9vbC5uYW1lfScgYWxyZWFkeSBoYXMgYSByZW5kZXIuIFNraXBwaW5nLmApO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCByZW5kZXJFbnRyeTogQW5ndWxhclRvb2xDYWxsUmVuZGVyID0ge1xuICAgICAgICBuYW1lOiB0b29sLm5hbWUsXG4gICAgICAgIHJlbmRlcjogdG9vbC5yZW5kZXJcbiAgICAgIH07XG4gICAgICBcbiAgICAgIHNlcnZpY2Uuc2V0Q3VycmVudFJlbmRlclRvb2xDYWxscyhbLi4uY3VycmVudFJlbmRlcnMsIHJlbmRlckVudHJ5XSk7XG4gICAgfVxuICB9XG4gIFxuICAvLyBSZWdpc3RlciBjbGVhbnVwIHdpdGggQW5ndWxhcidzIERlc3Ryb3lSZWZcbiAgZGVzdHJveVJlZi5vbkRlc3Ryb3koKCkgPT4ge1xuICAgIHJlbW92ZUZyb250ZW5kVG9vbChzZXJ2aWNlLCB0b29sLm5hbWUpO1xuICB9KTtcbiAgXG4gIHJldHVybiB0b29sLm5hbWU7XG59XG5cbi8qKlxuICogRXhwbGljaXRseSByZW1vdmVzIGEgZnJvbnRlbmQgdG9vbCBmcm9tIENvcGlsb3RLaXQuXG4gKiBcbiAqIEBwYXJhbSBzZXJ2aWNlIC0gVGhlIENvcGlsb3RLaXRTZXJ2aWNlIGluc3RhbmNlXG4gKiBAcGFyYW0gdG9vbE5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgdG9vbCB0byByZW1vdmVcbiAqIFxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIHJlbW92ZUZyb250ZW5kVG9vbCh0aGlzLmNvcGlsb3RraXQsICdjYWxjdWxhdG9yJyk7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlbW92ZUZyb250ZW5kVG9vbChcbiAgc2VydmljZTogQ29waWxvdEtpdFNlcnZpY2UsXG4gIHRvb2xOYW1lOiBzdHJpbmdcbik6IHZvaWQge1xuICAvLyBSZW1vdmUgdGhlIHRvb2xcbiAgc2VydmljZS5jb3BpbG90a2l0LnJlbW92ZVRvb2wodG9vbE5hbWUpO1xuICBcbiAgLy8gUmVtb3ZlIHRoZSByZW5kZXIgaWYgaXQgZXhpc3RzXG4gIGNvbnN0IGN1cnJlbnRSZW5kZXJzID0gc2VydmljZS5jdXJyZW50UmVuZGVyVG9vbENhbGxzKCk7XG4gIGNvbnN0IGZpbHRlcmVkID0gY3VycmVudFJlbmRlcnMuZmlsdGVyKChyOiBUb29sQ2FsbFJlbmRlcikgPT4gci5uYW1lICE9PSB0b29sTmFtZSk7XG4gIGlmIChmaWx0ZXJlZC5sZW5ndGggIT09IGN1cnJlbnRSZW5kZXJzLmxlbmd0aCkge1xuICAgIHNlcnZpY2Uuc2V0Q3VycmVudFJlbmRlclRvb2xDYWxscyhmaWx0ZXJlZCk7XG4gIH1cbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgZnJvbnRlbmQgdG9vbCB3aXRoIGR5bmFtaWMgcGFyYW1ldGVycyB0aGF0IGNhbiBjaGFuZ2Ugb3ZlciB0aW1lLlxuICogVXNlcyBBbmd1bGFyIHNpZ25hbHMgZm9yIHJlYWN0aXZpdHkuXG4gKiBcbiAqIEBwYXJhbSBuYW1lIC0gVG9vbCBuYW1lXG4gKiBAcGFyYW0gZGVzY3JpcHRpb24gLSBUb29sIGRlc2NyaXB0aW9uXG4gKiBAcGFyYW0gcGFyYW1ldGVycyAtIFpvZCBzY2hlbWEgZm9yIHBhcmFtZXRlcnNcbiAqIEBwYXJhbSBoYW5kbGVyIC0gU2lnbmFsIG9yIGZ1bmN0aW9uIHRoYXQgcHJvdmlkZXMgdGhlIGhhbmRsZXJcbiAqIEBwYXJhbSByZW5kZXIgLSBPcHRpb25hbCByZW5kZXIgY29tcG9uZW50IG9yIHRlbXBsYXRlXG4gKiBAcmV0dXJucyBPYmplY3Qgd2l0aCB1cGRhdGUgYW5kIGRlc3Ryb3kgbWV0aG9kc1xuICogXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogZXhwb3J0IGNsYXNzIE15Q29tcG9uZW50IHtcbiAqICAgcHJpdmF0ZSB0b29sQ29uZmlnID0gc2lnbmFsKHtcbiAqICAgICBoYW5kbGVyOiBhc3luYyAoYXJnczogYW55KSA9PiB0aGlzLnByb2Nlc3NEZWZhdWx0KGFyZ3MpXG4gKiAgIH0pO1xuICogICBcbiAqICAgbmdPbkluaXQoKSB7XG4gKiAgICAgY29uc3QgdG9vbCA9IGNyZWF0ZUR5bmFtaWNGcm9udGVuZFRvb2woXG4gKiAgICAgICAncHJvY2Vzc29yJyxcbiAqICAgICAgICdQcm9jZXNzZXMgZGF0YScsXG4gKiAgICAgICB6Lm9iamVjdCh7IGRhdGE6IHouc3RyaW5nKCkgfSksXG4gKiAgICAgICAoKSA9PiB0aGlzLnRvb2xDb25maWcoKS5oYW5kbGVyXG4gKiAgICAgKTtcbiAqICAgICBcbiAqICAgICAvLyBMYXRlciwgdXBkYXRlIHRoZSBoYW5kbGVyXG4gKiAgICAgdGhpcy50b29sQ29uZmlnLnNldCh7XG4gKiAgICAgICBoYW5kbGVyOiBhc3luYyAoYXJnczogYW55KSA9PiB0aGlzLnByb2Nlc3NBZHZhbmNlZChhcmdzKVxuICogICAgIH0pO1xuICogICAgIHRvb2wudXBkYXRlKCk7XG4gKiAgIH1cbiAqIH1cbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlRHluYW1pY0Zyb250ZW5kVG9vbDxUIGV4dGVuZHMgUmVjb3JkPHN0cmluZywgYW55PiA9IFJlY29yZDxzdHJpbmcsIGFueT4+KFxuICBuYW1lOiBzdHJpbmcsXG4gIGRlc2NyaXB0aW9uOiBzdHJpbmcgfCAoKCkgPT4gc3RyaW5nKSxcbiAgcGFyYW1ldGVyczogei5ab2RTY2hlbWE8VD4sXG4gIGhhbmRsZXI6ICgpID0+ICgoYXJnczogVCkgPT4gUHJvbWlzZTxhbnk+KSxcbiAgcmVuZGVyPzogKCkgPT4gYW55XG4pOiB7IHVwZGF0ZTogKCkgPT4gdm9pZDsgZGVzdHJveTogKCkgPT4gdm9pZCB9IHtcbiAgY29uc3Qgc2VydmljZSA9IGluamVjdChDb3BpbG90S2l0U2VydmljZSk7XG4gIGNvbnN0IGRlc3Ryb3lSZWYgPSBpbmplY3QoRGVzdHJveVJlZik7XG4gIFxuICBsZXQgaXNSZWdpc3RlcmVkID0gZmFsc2U7XG4gIFxuICBjb25zdCB1cGRhdGUgPSAoKSA9PiB7XG4gICAgLy8gUmVtb3ZlIG9sZCB0b29sIGlmIHJlZ2lzdGVyZWRcbiAgICBpZiAoaXNSZWdpc3RlcmVkKSB7XG4gICAgICBzZXJ2aWNlLmNvcGlsb3RraXQucmVtb3ZlVG9vbChuYW1lKTtcbiAgICB9XG4gICAgXG4gICAgLy8gQ3JlYXRlIG5ldyB0b29sIGNvbmZpZ3VyYXRpb25cbiAgICBjb25zdCBkZXNjID0gdHlwZW9mIGRlc2NyaXB0aW9uID09PSAnZnVuY3Rpb24nID8gZGVzY3JpcHRpb24oKSA6IGRlc2NyaXB0aW9uO1xuICAgIGNvbnN0IGN1cnJlbnRIYW5kbGVyID0gaGFuZGxlcigpO1xuICAgIGNvbnN0IGN1cnJlbnRSZW5kZXIgPSByZW5kZXIgPyByZW5kZXIoKSA6IHVuZGVmaW5lZDtcbiAgICBcbiAgICBjb25zdCB0b29sOiBBbmd1bGFyRnJvbnRlbmRUb29sPFQ+ID0ge1xuICAgICAgbmFtZSxcbiAgICAgIGRlc2NyaXB0aW9uOiBkZXNjLFxuICAgICAgcGFyYW1ldGVycyxcbiAgICAgIGhhbmRsZXI6IGN1cnJlbnRIYW5kbGVyLFxuICAgICAgcmVuZGVyOiBjdXJyZW50UmVuZGVyXG4gICAgfTtcbiAgICBcbiAgICAvLyBBZGQgdGhlIHRvb2xcbiAgICBzZXJ2aWNlLmNvcGlsb3RraXQuYWRkVG9vbCh0b29sKTtcbiAgICBcbiAgICAvLyBVcGRhdGUgcmVuZGVyIGlmIHByb3ZpZGVkXG4gICAgaWYgKGN1cnJlbnRSZW5kZXIpIHtcbiAgICAgIGNvbnN0IGN1cnJlbnRSZW5kZXJzID0gc2VydmljZS5jdXJyZW50UmVuZGVyVG9vbENhbGxzKCk7XG4gICAgICBjb25zdCByZW5kZXJFbnRyeTogQW5ndWxhclRvb2xDYWxsUmVuZGVyID0ge1xuICAgICAgICBuYW1lOiBuYW1lLFxuICAgICAgICByZW5kZXI6IGN1cnJlbnRSZW5kZXJcbiAgICAgIH07XG4gICAgICBcbiAgICAgIGNvbnN0IGV4aXN0aW5nSW5kZXggPSBjdXJyZW50UmVuZGVycy5maW5kSW5kZXgoKHI6IFRvb2xDYWxsUmVuZGVyKSA9PiByLm5hbWUgPT09IG5hbWUpO1xuICAgICAgaWYgKGV4aXN0aW5nSW5kZXggIT09IC0xKSB7XG4gICAgICAgIGNvbnN0IHVwZGF0ZWQgPSBbLi4uY3VycmVudFJlbmRlcnNdO1xuICAgICAgICB1cGRhdGVkW2V4aXN0aW5nSW5kZXhdID0gcmVuZGVyRW50cnk7XG4gICAgICAgIHNlcnZpY2Uuc2V0Q3VycmVudFJlbmRlclRvb2xDYWxscyh1cGRhdGVkKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNlcnZpY2Uuc2V0Q3VycmVudFJlbmRlclRvb2xDYWxscyhbLi4uY3VycmVudFJlbmRlcnMsIHJlbmRlckVudHJ5XSk7XG4gICAgICB9XG4gICAgfVxuICAgIFxuICAgIGlzUmVnaXN0ZXJlZCA9IHRydWU7XG4gIH07XG4gIFxuICBjb25zdCBkZXN0cm95ID0gKCkgPT4ge1xuICAgIGlmIChpc1JlZ2lzdGVyZWQpIHtcbiAgICAgIHJlbW92ZUZyb250ZW5kVG9vbChzZXJ2aWNlLCBuYW1lKTtcbiAgICAgIGlzUmVnaXN0ZXJlZCA9IGZhbHNlO1xuICAgIH1cbiAgfTtcbiAgXG4gIC8vIEluaXRpYWwgc2V0dXBcbiAgdXBkYXRlKCk7XG4gIFxuICAvLyBSZWdpc3RlciBjbGVhbnVwXG4gIGRlc3Ryb3lSZWYub25EZXN0cm95KGRlc3Ryb3kpO1xuICBcbiAgcmV0dXJuIHsgdXBkYXRlLCBkZXN0cm95IH07XG59Il19