@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
@@ -1,266 +0,0 @@
1
- import { DestroyRef, inject } from '@angular/core';
2
- import { CopilotKitService } from '../core/copilotkit.service';
3
- import { AngularFrontendTool, AngularToolCallRender, ToolCallRender } from '../core/copilotkit.types';
4
- import { z } from 'zod';
5
-
6
- /**
7
- * Explicitly adds a frontend tool to CopilotKit.
8
- * Requires CopilotKitService to be passed as a parameter.
9
- *
10
- * @param service - The CopilotKitService instance
11
- * @param tool - The tool to add
12
- * @returns A cleanup function that removes the tool
13
- *
14
- * @example
15
- * ```typescript
16
- * export class MyComponent implements OnInit, OnDestroy {
17
- * private cleanupFns: Array<() => void> = [];
18
- *
19
- * constructor(private copilotkit: CopilotKitService) {}
20
- *
21
- * ngOnInit() {
22
- * const cleanup = addFrontendTool(this.copilotkit, {
23
- * name: 'calculator',
24
- * description: 'Performs calculations',
25
- * parameters: z.object({
26
- * expression: z.string()
27
- * }),
28
- * handler: async (args) => {
29
- * return eval(args.expression);
30
- * }
31
- * });
32
- *
33
- * this.cleanupFns.push(cleanup);
34
- * }
35
- *
36
- * ngOnDestroy() {
37
- * this.cleanupFns.forEach(fn => fn());
38
- * }
39
- * }
40
- * ```
41
- */
42
- export function addFrontendTool<T extends Record<string, any> = Record<string, any>>(
43
- service: CopilotKitService,
44
- tool: AngularFrontendTool<T>
45
- ): () => void {
46
- // Add the tool to CopilotKit
47
- service.copilotkit.addTool(tool);
48
-
49
- // Register the render if provided
50
- if (tool.render) {
51
- const currentRenders = service.currentRenderToolCalls();
52
- const existingIndex = currentRenders.findIndex((r: ToolCallRender<unknown>) => r.name === tool.name);
53
-
54
- if (existingIndex !== -1) {
55
- console.error(`Tool with name '${tool.name}' already has a render. Skipping.`);
56
- } else {
57
- const renderEntry: AngularToolCallRender<T> = {
58
- name: tool.name,
59
- args: tool.parameters || (z.object({}) as unknown as z.ZodSchema<T>),
60
- render: tool.render
61
- };
62
-
63
- service.setCurrentRenderToolCalls([...currentRenders, renderEntry]);
64
- }
65
- }
66
-
67
- // Return cleanup function
68
- return () => {
69
- removeFrontendTool(service, tool.name);
70
- };
71
- }
72
-
73
- /**
74
- * Registers a frontend tool with CopilotKit and automatically removes it when the component/service is destroyed.
75
- * Must be called within an injection context.
76
- *
77
- * @param tool - The tool to register
78
- * @returns The tool name
79
- *
80
- * @example
81
- * ```typescript
82
- * export class MyComponent implements OnInit {
83
- * ngOnInit() {
84
- * // Automatically cleaned up on component destroy
85
- * registerFrontendTool({
86
- * name: 'search',
87
- * description: 'Search for items',
88
- * parameters: z.object({
89
- * query: z.string()
90
- * }),
91
- * handler: async (args) => {
92
- * return this.searchService.search(args.query);
93
- * },
94
- * render: SearchResultsComponent
95
- * });
96
- * }
97
- * }
98
- * ```
99
- */
100
- export function registerFrontendTool<T extends Record<string, any> = Record<string, any>>(
101
- tool: AngularFrontendTool<T>
102
- ): string {
103
- const service = inject(CopilotKitService);
104
- const destroyRef = inject(DestroyRef);
105
-
106
- // Add the tool
107
- service.copilotkit.addTool(tool);
108
-
109
- // Register the render if provided
110
- if (tool.render) {
111
- const currentRenders = service.currentRenderToolCalls();
112
- const existingIndex = currentRenders.findIndex((r: ToolCallRender<unknown>) => r.name === tool.name);
113
-
114
- if (existingIndex !== -1) {
115
- console.error(`Tool with name '${tool.name}' already has a render. Skipping.`);
116
- } else {
117
- const renderEntry: AngularToolCallRender<T> = {
118
- name: tool.name,
119
- args: tool.parameters || (z.object({}) as unknown as z.ZodSchema<T>),
120
- render: tool.render
121
- };
122
-
123
- service.setCurrentRenderToolCalls([...currentRenders, renderEntry]);
124
- }
125
- }
126
-
127
- // Register cleanup with Angular's DestroyRef
128
- destroyRef.onDestroy(() => {
129
- removeFrontendTool(service, tool.name);
130
- });
131
-
132
- return tool.name;
133
- }
134
-
135
- /**
136
- * Explicitly removes a frontend tool from CopilotKit.
137
- *
138
- * @param service - The CopilotKitService instance
139
- * @param toolName - The name of the tool to remove
140
- *
141
- * @example
142
- * ```typescript
143
- * removeFrontendTool(this.copilotkit, 'calculator');
144
- * ```
145
- */
146
- export function removeFrontendTool(
147
- service: CopilotKitService,
148
- toolName: string
149
- ): void {
150
- // Remove the tool
151
- service.copilotkit.removeTool(toolName);
152
-
153
- // Remove the render if it exists
154
- const currentRenders = service.currentRenderToolCalls();
155
- const filtered = currentRenders.filter((r: ToolCallRender<unknown>) => r.name !== toolName);
156
- if (filtered.length !== currentRenders.length) {
157
- service.setCurrentRenderToolCalls(filtered);
158
- }
159
- }
160
-
161
- /**
162
- * Creates a frontend tool with dynamic parameters that can change over time.
163
- * Uses Angular signals for reactivity.
164
- *
165
- * @param name - Tool name
166
- * @param description - Tool description
167
- * @param parameters - Zod schema for parameters
168
- * @param handler - Signal or function that provides the handler
169
- * @param render - Optional render component or template
170
- * @returns Object with update and destroy methods
171
- *
172
- * @example
173
- * ```typescript
174
- * export class MyComponent {
175
- * private toolConfig = signal({
176
- * handler: async (args: any) => this.processDefault(args)
177
- * });
178
- *
179
- * ngOnInit() {
180
- * const tool = createDynamicFrontendTool(
181
- * 'processor',
182
- * 'Processes data',
183
- * z.object({ data: z.string() }),
184
- * () => this.toolConfig().handler
185
- * );
186
- *
187
- * // Later, update the handler
188
- * this.toolConfig.set({
189
- * handler: async (args: any) => this.processAdvanced(args)
190
- * });
191
- * tool.update();
192
- * }
193
- * }
194
- * ```
195
- */
196
- export function createDynamicFrontendTool<T extends Record<string, any> = Record<string, any>>(
197
- name: string,
198
- description: string | (() => string),
199
- parameters: z.ZodSchema<T>,
200
- handler: () => ((args: T) => Promise<any>),
201
- render?: () => any
202
- ): { update: () => void; destroy: () => void } {
203
- const service = inject(CopilotKitService);
204
- const destroyRef = inject(DestroyRef);
205
-
206
- let isRegistered = false;
207
-
208
- const update = () => {
209
- // Remove old tool if registered
210
- if (isRegistered) {
211
- service.copilotkit.removeTool(name);
212
- }
213
-
214
- // Create new tool configuration
215
- const desc = typeof description === 'function' ? description() : description;
216
- const currentHandler = handler();
217
- const currentRender = render ? render() : undefined;
218
-
219
- const tool: AngularFrontendTool<T> = {
220
- name,
221
- description: desc,
222
- parameters,
223
- handler: currentHandler,
224
- render: currentRender
225
- };
226
-
227
- // Add the tool
228
- service.copilotkit.addTool(tool);
229
-
230
- // Update render if provided
231
- if (currentRender) {
232
- const currentRenders = service.currentRenderToolCalls();
233
- const renderEntry: AngularToolCallRender<T> = {
234
- name: name,
235
- args: parameters,
236
- render: currentRender
237
- };
238
-
239
- const existingIndex = currentRenders.findIndex((r: ToolCallRender<unknown>) => r.name === name);
240
- if (existingIndex !== -1) {
241
- const updated = [...currentRenders];
242
- updated[existingIndex] = renderEntry;
243
- service.setCurrentRenderToolCalls(updated);
244
- } else {
245
- service.setCurrentRenderToolCalls([...currentRenders, renderEntry]);
246
- }
247
- }
248
-
249
- isRegistered = true;
250
- };
251
-
252
- const destroy = () => {
253
- if (isRegistered) {
254
- removeFrontendTool(service, name);
255
- isRegistered = false;
256
- }
257
- };
258
-
259
- // Initial setup
260
- update();
261
-
262
- // Register cleanup
263
- destroyRef.onDestroy(destroy);
264
-
265
- return { update, destroy };
266
- }
@@ -1,359 +0,0 @@
1
- import {
2
- DestroyRef,
3
- inject,
4
- signal,
5
- Signal,
6
- Type,
7
- TemplateRef
8
- } from '@angular/core';
9
- import { CopilotKitService } from '../core/copilotkit.service';
10
- import {
11
- AngularHumanInTheLoop,
12
- ToolCallStatus,
13
- HumanInTheLoopState,
14
- HumanInTheLoopProps,
15
- AngularFrontendTool
16
- } from '../core/copilotkit.types';
17
-
18
- /**
19
- * Registers a human-in-the-loop tool that requires user interaction.
20
- * Must be called within an injection context.
21
- * Automatically cleans up when the component/service is destroyed.
22
- *
23
- * @param tool - The human-in-the-loop tool configuration
24
- * @returns The tool ID
25
- *
26
- * @example
27
- * ```typescript
28
- * export class ApprovalComponent {
29
- * toolId = registerHumanInTheLoop({
30
- * name: 'requireApproval',
31
- * description: 'Requires user approval',
32
- * args: z.object({ action: z.string() }),
33
- * render: ApprovalDialogComponent
34
- * });
35
- * }
36
- * ```
37
- */
38
- export function registerHumanInTheLoop<T extends Record<string, any> = Record<string, any>>(
39
- tool: AngularHumanInTheLoop<T>
40
- ): string {
41
- const service = inject(CopilotKitService);
42
- const destroyRef = inject(DestroyRef);
43
-
44
- // Create state management
45
- const statusSignal = signal<ToolCallStatus>(ToolCallStatus.InProgress);
46
- let resolvePromise: ((result: unknown) => void) | null = null;
47
-
48
- // Create respond function
49
- const respond = async (result: unknown): Promise<void> => {
50
- if (resolvePromise) {
51
- resolvePromise(result);
52
- statusSignal.set(ToolCallStatus.Complete);
53
- resolvePromise = null;
54
- }
55
- };
56
-
57
- // Create handler that returns a Promise
58
- const handler = async (_args: T): Promise<unknown> => {
59
- return new Promise((resolve) => {
60
- statusSignal.set(ToolCallStatus.Executing);
61
- resolvePromise = resolve;
62
- });
63
- };
64
-
65
- // Create enhanced render function
66
- const enhancedRender = createEnhancedRender(tool.render, statusSignal, respond);
67
-
68
- // Create the frontend tool
69
- const frontendTool: AngularFrontendTool<T> = {
70
- ...tool,
71
- handler,
72
- render: enhancedRender
73
- };
74
-
75
- // Add the tool (returns void, so we use the tool name as ID)
76
- service.copilotkit.addTool(frontendTool);
77
- const toolId = frontendTool.name;
78
-
79
- // Register tool render if provided
80
- if (frontendTool.render && tool.parameters) {
81
- service.registerToolRender(frontendTool.name, {
82
- name: frontendTool.name,
83
- args: tool.parameters,
84
- render: frontendTool.render
85
- });
86
- }
87
-
88
- // Cleanup on destroy
89
- destroyRef.onDestroy(() => {
90
- service.copilotkit.removeTool(toolId);
91
- if (frontendTool.render) {
92
- service.unregisterToolRender(frontendTool.name);
93
- }
94
- });
95
-
96
- return toolId;
97
- }
98
-
99
- /**
100
- * Adds a human-in-the-loop tool with explicit service parameter.
101
- * Returns a cleanup function.
102
- *
103
- * @param service - The CopilotKitService instance
104
- * @param tool - The human-in-the-loop tool configuration
105
- * @returns Cleanup function to remove the tool
106
- *
107
- * @example
108
- * ```typescript
109
- * export class MyComponent implements OnInit, OnDestroy {
110
- * private cleanup?: () => void;
111
- *
112
- * constructor(private copilotkit: CopilotKitService) {}
113
- *
114
- * ngOnInit() {
115
- * this.cleanup = addHumanInTheLoop(this.copilotkit, {
116
- * name: 'requireApproval',
117
- * description: 'Requires user approval',
118
- * args: z.object({ action: z.string() }),
119
- * render: ApprovalDialogComponent
120
- * });
121
- * }
122
- *
123
- * ngOnDestroy() {
124
- * this.cleanup?.();
125
- * }
126
- * }
127
- * ```
128
- */
129
- export function addHumanInTheLoop<T extends Record<string, any> = Record<string, any>>(
130
- service: CopilotKitService,
131
- tool: AngularHumanInTheLoop<T>
132
- ): () => void {
133
- // Create state management
134
- const statusSignal = signal<ToolCallStatus>(ToolCallStatus.InProgress);
135
- let resolvePromise: ((result: unknown) => void) | null = null;
136
-
137
- // Create respond function
138
- const respond = async (result: unknown): Promise<void> => {
139
- if (resolvePromise) {
140
- resolvePromise(result);
141
- statusSignal.set(ToolCallStatus.Complete);
142
- resolvePromise = null;
143
- }
144
- };
145
-
146
- // Create handler that returns a Promise
147
- const handler = async (_args: T): Promise<unknown> => {
148
- return new Promise((resolve) => {
149
- statusSignal.set(ToolCallStatus.Executing);
150
- resolvePromise = resolve;
151
- });
152
- };
153
-
154
- // Create enhanced render function
155
- const enhancedRender = createEnhancedRender(tool.render, statusSignal, respond);
156
-
157
- // Create the frontend tool
158
- const frontendTool: AngularFrontendTool<T> = {
159
- ...tool,
160
- handler,
161
- render: enhancedRender
162
- };
163
-
164
- // Add the tool (returns void, so we use the tool name as ID)
165
- service.copilotkit.addTool(frontendTool);
166
- const toolId = frontendTool.name;
167
-
168
- // Register tool render if provided
169
- if (frontendTool.render && tool.parameters) {
170
- service.registerToolRender(frontendTool.name, {
171
- name: frontendTool.name,
172
- args: tool.parameters,
173
- render: frontendTool.render
174
- });
175
- }
176
-
177
- // Return cleanup function
178
- return () => {
179
- service.copilotkit.removeTool(toolId);
180
- if (frontendTool.render) {
181
- service.unregisterToolRender(frontendTool.name);
182
- }
183
- };
184
- }
185
-
186
- /**
187
- * Creates a human-in-the-loop tool with dynamic update capabilities.
188
- *
189
- * @param service - The CopilotKitService instance
190
- * @param tool - The human-in-the-loop tool configuration
191
- * @returns Object with status signal, update and destroy methods
192
- *
193
- * @example
194
- * ```typescript
195
- * export class MyComponent {
196
- * humanInTheLoop = createHumanInTheLoop(this.copilotkit, {
197
- * name: 'requireApproval',
198
- * description: 'Requires user approval',
199
- * args: z.object({ action: z.string() }),
200
- * render: ApprovalDialogComponent
201
- * });
202
- *
203
- * updateDescription(newDesc: string) {
204
- * this.humanInTheLoop.update({ description: newDesc });
205
- * }
206
- *
207
- * ngOnDestroy() {
208
- * this.humanInTheLoop.destroy();
209
- * }
210
- * }
211
- * ```
212
- */
213
- export function createHumanInTheLoop<T extends Record<string, any> = Record<string, any>>(
214
- service: CopilotKitService,
215
- tool: AngularHumanInTheLoop<T>
216
- ): HumanInTheLoopState & { update: (updates: Partial<AngularHumanInTheLoop<T>>) => void } {
217
- // Create state management
218
- const statusSignal = signal<ToolCallStatus>(ToolCallStatus.InProgress);
219
- let currentTool = { ...tool };
220
- let toolId: string = '';
221
- let resolvePromise: ((result: unknown) => void) | null = null;
222
-
223
- // Create respond function
224
- const respond = async (result: unknown): Promise<void> => {
225
- if (resolvePromise) {
226
- resolvePromise(result);
227
- statusSignal.set(ToolCallStatus.Complete);
228
- resolvePromise = null;
229
- }
230
- };
231
-
232
- // Create handler that returns a Promise
233
- const handler = async (_args: T): Promise<unknown> => {
234
- return new Promise((resolve) => {
235
- statusSignal.set(ToolCallStatus.Executing);
236
- resolvePromise = resolve;
237
- });
238
- };
239
-
240
- // Function to add the tool
241
- const addTool = () => {
242
- // Create enhanced render function
243
- const enhancedRender = createEnhancedRender(currentTool.render, statusSignal, respond);
244
-
245
- // Create the frontend tool
246
- const frontendTool: AngularFrontendTool<T> = {
247
- ...currentTool,
248
- handler,
249
- render: enhancedRender
250
- };
251
-
252
- // Add tool (returns void, so we use the tool name as ID)
253
- service.copilotkit.addTool(frontendTool);
254
- toolId = frontendTool.name;
255
-
256
- // Register tool render if provided
257
- if (frontendTool.render && currentTool.parameters) {
258
- service.registerToolRender(frontendTool.name, {
259
- name: frontendTool.name,
260
- args: currentTool.parameters,
261
- render: frontendTool.render
262
- });
263
- }
264
- };
265
-
266
- // Initialize the tool
267
- addTool();
268
-
269
- return {
270
- status: statusSignal.asReadonly(),
271
- toolId,
272
- update: (updates: Partial<AngularHumanInTheLoop<T>>) => {
273
- // Remove old tool
274
- service.copilotkit.removeTool(toolId);
275
- if (currentTool.render) {
276
- service.unregisterToolRender(currentTool.name);
277
- }
278
-
279
- // Update tool configuration
280
- currentTool = { ...currentTool, ...updates };
281
-
282
- // Re-add with new configuration
283
- addTool();
284
- },
285
- destroy: () => {
286
- service.copilotkit.removeTool(toolId);
287
- if (currentTool.render) {
288
- service.unregisterToolRender(currentTool.name);
289
- }
290
- }
291
- };
292
- }
293
-
294
- /**
295
- * Creates an enhanced render function that injects the respond function
296
- * when the status is 'executing'.
297
- */
298
- function createEnhancedRender<T extends Record<string, any>>(
299
- originalRender: Type<any> | TemplateRef<HumanInTheLoopProps<T>>,
300
- _statusSignal: Signal<ToolCallStatus>,
301
- _respond: (result: unknown) => Promise<void>
302
- ): Type<any> | TemplateRef<any> {
303
- // For component classes, we need to create a wrapper
304
- if (isComponentClass(originalRender)) {
305
- // Return a wrapper component factory
306
- // This is complex in Angular and would require dynamic component creation
307
- // For now, we'll return the original and rely on prop injection
308
- return originalRender;
309
- }
310
-
311
- // For templates, we can't easily wrap them
312
- // The template context will be enhanced in the render component
313
- return originalRender;
314
- }
315
-
316
- /**
317
- * Helper function to check if a value is a component class
318
- */
319
- function isComponentClass(value: any): value is Type<any> {
320
- return typeof value === 'function' && value.prototype;
321
- }
322
-
323
- /**
324
- * Enhanced component wrapper for human-in-the-loop.
325
- * This would be used internally by the tool render component to inject
326
- * the respond function based on status.
327
- *
328
- * @internal
329
- */
330
- export function enhancePropsForHumanInTheLoop<T>(
331
- props: HumanInTheLoopProps<T>,
332
- status: ToolCallStatus,
333
- respond?: (result: unknown) => Promise<void>
334
- ): HumanInTheLoopProps<T> {
335
- if (status === ToolCallStatus.Executing && respond) {
336
- return {
337
- ...props,
338
- status: ToolCallStatus.Executing,
339
- respond
340
- } as HumanInTheLoopProps<T>;
341
- }
342
-
343
- if (status === ToolCallStatus.Complete) {
344
- return {
345
- ...props,
346
- status: ToolCallStatus.Complete,
347
- result: typeof props.result === 'string' ? props.result : '',
348
- respond: undefined
349
- } as HumanInTheLoopProps<T>;
350
- }
351
-
352
- // InProgress
353
- return {
354
- ...props,
355
- status: ToolCallStatus.InProgress,
356
- result: undefined,
357
- respond: undefined
358
- } as HumanInTheLoopProps<T>;
359
- }
@@ -1,12 +0,0 @@
1
- {
2
- "extends": "./tsconfig.json",
3
- "compilerOptions": {
4
- "types": ["node", "vitest/globals"]
5
- },
6
- "include": [
7
- "src/**/*.spec.ts",
8
- "src/**/*.test.ts",
9
- "src/**/*.d.ts"
10
- ],
11
- "exclude": ["node_modules", "dist"]
12
- }