@copilotkitnext/angular 1.52.0-next.7 → 1.52.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/README.md +225 -432
  2. package/dist/README.md +225 -432
  3. package/dist/fesm2022/copilotkitnext-angular.mjs +312 -161
  4. package/dist/fesm2022/copilotkitnext-angular.mjs.map +1 -1
  5. package/dist/lib/agent.d.ts +20 -20
  6. package/dist/lib/components/chat/copilot-chat-assistant-message.d.ts +46 -46
  7. package/dist/lib/components/chat/copilot-chat-message-view.d.ts +126 -126
  8. package/dist/lib/components/chat/copilot-chat-tool-calls-view.d.ts +23 -23
  9. package/dist/lib/components/chat/copilot-chat-user-message-branch-navigation.d.ts +6 -6
  10. package/dist/lib/components/chat/copilot-chat-user-message.d.ts +6 -6
  11. package/dist/lib/components/chat/copilot-chat-view-scroll-view.d.ts +18 -18
  12. package/dist/lib/components/chat/copilot-chat-view.d.ts +54 -54
  13. package/dist/lib/components/chat/copilot-chat.d.ts +18 -18
  14. package/dist/lib/config.d.ts +1 -0
  15. package/dist/lib/copilotkit.d.ts +6 -1
  16. package/dist/lib/license-watermark.d.ts +1 -0
  17. package/dist/lib/render-tool-calls.d.ts +23 -23
  18. package/dist/styles.css +3 -0
  19. package/package.json +18 -18
  20. package/dist/esm2022/copilotkitnext-angular.mjs +0 -5
  21. package/dist/esm2022/index.mjs +0 -2
  22. package/dist/esm2022/lib/agent-context.mjs +0 -25
  23. package/dist/esm2022/lib/agent.mjs +0 -73
  24. package/dist/esm2022/lib/chat-config.mjs +0 -35
  25. package/dist/esm2022/lib/chat-state.mjs +0 -18
  26. package/dist/esm2022/lib/components/chat/copilot-chat-assistant-message-buttons.mjs +0 -344
  27. package/dist/esm2022/lib/components/chat/copilot-chat-assistant-message-renderer.mjs +0 -260
  28. package/dist/esm2022/lib/components/chat/copilot-chat-assistant-message-toolbar.mjs +0 -22
  29. package/dist/esm2022/lib/components/chat/copilot-chat-assistant-message.mjs +0 -415
  30. package/dist/esm2022/lib/components/chat/copilot-chat-assistant-message.types.mjs +0 -2
  31. package/dist/esm2022/lib/components/chat/copilot-chat-audio-recorder.mjs +0 -196
  32. package/dist/esm2022/lib/components/chat/copilot-chat-buttons.mjs +0 -299
  33. package/dist/esm2022/lib/components/chat/copilot-chat-input-defaults.mjs +0 -39
  34. package/dist/esm2022/lib/components/chat/copilot-chat-input.mjs +0 -634
  35. package/dist/esm2022/lib/components/chat/copilot-chat-input.types.mjs +0 -10
  36. package/dist/esm2022/lib/components/chat/copilot-chat-message-view-cursor.mjs +0 -27
  37. package/dist/esm2022/lib/components/chat/copilot-chat-message-view.mjs +0 -269
  38. package/dist/esm2022/lib/components/chat/copilot-chat-message-view.types.mjs +0 -2
  39. package/dist/esm2022/lib/components/chat/copilot-chat-textarea.mjs +0 -139
  40. package/dist/esm2022/lib/components/chat/copilot-chat-tool-calls-view.mjs +0 -36
  41. package/dist/esm2022/lib/components/chat/copilot-chat-toolbar.mjs +0 -20
  42. package/dist/esm2022/lib/components/chat/copilot-chat-tools-menu.mjs +0 -203
  43. package/dist/esm2022/lib/components/chat/copilot-chat-user-message-branch-navigation.mjs +0 -118
  44. package/dist/esm2022/lib/components/chat/copilot-chat-user-message-buttons.mjs +0 -182
  45. package/dist/esm2022/lib/components/chat/copilot-chat-user-message-renderer.mjs +0 -28
  46. package/dist/esm2022/lib/components/chat/copilot-chat-user-message-toolbar.mjs +0 -25
  47. package/dist/esm2022/lib/components/chat/copilot-chat-user-message.mjs +0 -328
  48. package/dist/esm2022/lib/components/chat/copilot-chat-user-message.types.mjs +0 -2
  49. package/dist/esm2022/lib/components/chat/copilot-chat-view-disclaimer.mjs +0 -48
  50. package/dist/esm2022/lib/components/chat/copilot-chat-view-feather.mjs +0 -41
  51. package/dist/esm2022/lib/components/chat/copilot-chat-view-handlers.mjs +0 -19
  52. package/dist/esm2022/lib/components/chat/copilot-chat-view-input-container.mjs +0 -96
  53. package/dist/esm2022/lib/components/chat/copilot-chat-view-scroll-to-bottom-button.mjs +0 -89
  54. package/dist/esm2022/lib/components/chat/copilot-chat-view-scroll-view.mjs +0 -456
  55. package/dist/esm2022/lib/components/chat/copilot-chat-view.mjs +0 -404
  56. package/dist/esm2022/lib/components/chat/copilot-chat-view.types.mjs +0 -2
  57. package/dist/esm2022/lib/components/chat/copilot-chat.mjs +0 -165
  58. package/dist/esm2022/lib/config.mjs +0 -9
  59. package/dist/esm2022/lib/copilotkit.mjs +0 -125
  60. package/dist/esm2022/lib/directives/copilotkit-agent-context.mjs +0 -130
  61. package/dist/esm2022/lib/directives/stick-to-bottom.mjs +0 -170
  62. package/dist/esm2022/lib/directives/tooltip.mjs +0 -217
  63. package/dist/esm2022/lib/human-in-the-loop.mjs +0 -19
  64. package/dist/esm2022/lib/render-tool-calls.mjs +0 -167
  65. package/dist/esm2022/lib/resize-observer.mjs +0 -152
  66. package/dist/esm2022/lib/scroll-position.mjs +0 -123
  67. package/dist/esm2022/lib/slots/copilot-slot.mjs +0 -156
  68. package/dist/esm2022/lib/slots/index.mjs +0 -4
  69. package/dist/esm2022/lib/slots/slot.types.mjs +0 -6
  70. package/dist/esm2022/lib/slots/slot.utils.mjs +0 -235
  71. package/dist/esm2022/lib/tools.mjs +0 -31
  72. package/dist/esm2022/lib/utils.mjs +0 -10
  73. package/dist/esm2022/public-api.mjs +0 -48
package/dist/README.md CHANGED
@@ -1,534 +1,327 @@
1
1
  # CopilotKit for Angular
2
2
 
3
- This package provides native Angular components, directives, and providers to build Copilot chat UIs powered by the CopilotKit runtime and AG-UI agents. It mirrors the React experience with idiomatic Angular APIs.
4
-
5
- ## Quick Start
6
-
7
- 1. **Install**: `pnpm add @copilotkitnext/angular`
8
- 2. **Add styles**: Add `@copilotkitnext/angular/styles.css` to your Angular app styles array or `@import "@copilotkitnext/angular/styles.css";` in a global stylesheet
9
- 3. **Provide CopilotKit**: Set the runtime URL and optional labels via providers
10
- 4. **Use the chat**: Drop `<copilot-chat />` into any template
3
+ Angular bindings for CopilotKit core and AG-UI agents. This package provides services, directives, and utilities for building custom, headless Copilot UIs.
11
4
 
12
5
  ## Installation
13
6
 
14
- ### Package Installation
15
-
16
- Install `@copilotkitnext/angular` in your Angular app (supports Angular 18 and 19):
17
-
18
7
  ```bash
19
- # pnpm (recommended)
20
- pnpm add @copilotkitnext/angular
21
-
22
8
  # npm
23
- npm install @copilotkitnext/angular
24
-
25
- # yarn
26
- yarn add @copilotkitnext/angular
9
+ npm install @copilotkitnext/{core,angular}
27
10
  ```
28
11
 
29
- ### Peer Dependencies
30
-
31
- Ensure these are present (matching your Angular major):
32
-
33
- - `@angular/core`
34
- - `@angular/common`
35
- - `@angular/cdk` (use `^18` with Angular 18, `^19` with Angular 19)
12
+ - `@angular/core` and `@angular/common` (19+)
13
+ - `@angular/cdk` (match your Angular major)
36
14
  - `rxjs`
37
- - `tslib`
38
-
39
- ### Styles
40
15
 
41
- Reference the package CSS so the components render correctly:
16
+ ## Quick start
42
17
 
43
- **Option 1:** In `angular.json`:
18
+ ### 1) Provide CopilotKit
44
19
 
45
- ```json
46
- "styles": [
47
- "@copilotkitnext/angular/styles.css",
48
- "src/styles.css"
49
- ]
50
- ```
51
-
52
- **Option 2:** In your global stylesheet:
53
-
54
- ```css
55
- @import "@copilotkitnext/angular/styles.css";
56
- ```
57
-
58
- ## App Wiring (Providers)
20
+ Configure runtime and tools in your app config:
59
21
 
60
- Add CopilotKit providers in your application config to set labels and runtime URL.
61
-
62
- ### Example (`app.config.ts`):
63
-
64
- ```typescript
65
- import {
66
- provideCopilotKit,
67
- provideCopilotChatConfiguration,
68
- } from "@copilotkitnext/angular";
22
+ ```ts
23
+ import { ApplicationConfig } from "@angular/core";
24
+ import { provideCopilotKit } from "@copilotkitnext/angular";
69
25
 
70
26
  export const appConfig: ApplicationConfig = {
71
27
  providers: [
72
- importProvidersFrom(BrowserModule),
73
- ...provideCopilotKit({
74
- // runtimeUrl can also be set via template directive; see below
75
- }),
76
- provideCopilotChatConfiguration({
77
- labels: {
78
- chatInputPlaceholder: "Ask me anything...",
79
- chatDisclaimerText: "AI responses may need verification.",
80
- },
28
+ provideCopilotKit({
29
+ licenseKey: "ck_pub_your_public_api_key",
30
+ runtimeUrl: "http://localhost:3001/api/copilotkit",
31
+ headers: { Authorization: "Bearer ..." },
32
+ properties: { app: "demo" },
81
33
  }),
82
34
  ],
83
35
  };
84
36
  ```
85
37
 
86
- ## Runtime URL (Template Directive)
87
-
88
- You can declare the CopilotKit runtime endpoint directly in templates via the `CopilotKitConfigDirective`.
89
-
90
- ### Component Template Example:
91
-
92
- ```html
93
- <div
94
- [copilotkitConfig]="{ runtimeUrl: runtimeUrl }"
95
- style="display:block;height:100vh"
96
- >
97
- <copilot-chat></copilot-chat>
98
- </div>
99
- ```
100
-
101
- ### Component Class:
102
-
103
- ```typescript
104
- export class AppComponent {
105
- runtimeUrl = "http://localhost:3001/api/copilotkit";
106
- }
107
- ```
108
-
109
- ## Using the Chat Component
110
-
111
- ### Minimal Usage:
112
-
113
- ```html
114
- <copilot-chat></copilot-chat>
115
- ```
38
+ ### 2) Build a custom UI with `injectAgentStore`
116
39
 
117
- ### With a Specific Agent:
118
-
119
- ```html
120
- <copilot-chat [agentId]="'sales'"></copilot-chat>
121
- ```
122
-
123
- ### Behavior:
124
-
125
- - If `agentId` is omitted, the component uses the default agent (ID: `default`)
126
-
127
- ## Custom Input Components (Angular)
128
-
129
- When building custom input components for CopilotKit Angular, use the service-based pattern with `CopilotChatConfigurationService` for message submission. This is the idiomatic Angular approach leveraging dependency injection.
130
-
131
- ### Service-Based Custom Input Example:
132
-
133
- ```typescript
134
- import { Component } from "@angular/core";
135
- import { FormsModule } from "@angular/forms";
136
- import { CopilotChatConfigurationService } from "@copilotkitnext/angular";
40
+ ```ts
41
+ import { Component, inject, signal } from "@angular/core";
42
+ import { Message } from "@ag-ui/client";
43
+ import { CopilotKit, injectAgentStore } from "@copilotkitnext/angular";
44
+ import { randomUUID } from "@copilotkitnext/shared";
137
45
 
138
46
  @Component({
139
- selector: "my-custom-input",
140
- standalone: true,
141
- imports: [FormsModule],
142
47
  template: `
143
- <div class="custom-input-wrapper">
144
- <input
145
- [(ngModel)]="inputValue"
146
- (keyup.enter)="submitMessage()"
147
- placeholder="Type your message..."
148
- />
149
- <button (click)="submitMessage()">Send</button>
150
- </div>
151
- `,
152
- })
153
- export class MyCustomInputComponent {
154
- inputValue = "";
155
-
156
- constructor(private chat: CopilotChatConfigurationService) {}
157
-
158
- submitMessage() {
159
- const value = this.inputValue.trim();
160
- if (value) {
161
- // Use the service to submit the message
162
- this.chat.submitInput(value);
163
- this.inputValue = "";
48
+ @for (let message of messages(); track message.id) {
49
+ <div>
50
+ <em>{{ message.role }}</em>
51
+ <p>{{ message.content }}</p>
52
+ </div>
164
53
  }
165
- }
166
- }
167
- ```
168
-
169
- ### Using the Custom Input Component:
170
-
171
- ```typescript
172
- import { Component } from "@angular/core";
173
- import { CopilotChatViewComponent } from "@copilotkitnext/angular";
174
- import { MyCustomInputComponent } from "./my-custom-input.component";
175
54
 
176
- @Component({
177
- selector: "app-chat",
178
- standalone: true,
179
- imports: [CopilotChatViewComponent],
180
- template: `
181
- <copilot-chat-view
182
- [messages]="messages"
183
- [inputComponent]="customInputComponent"
184
- >
185
- </copilot-chat-view>
55
+ <input
56
+ [value]="input()"
57
+ (input)="input.set($any($event.target).value)"
58
+ (keyup.enter)="send()"
59
+ />
60
+ <button (click)="send()" [disabled]="store().isRunning()">Send</button>
186
61
  `,
187
62
  })
188
- export class ChatComponent {
189
- messages = [];
190
- customInputComponent = MyCustomInputComponent;
191
- }
192
- ```
63
+ export class HeadlessChatComponent {
64
+ readonly copilotKit = inject(CopilotKit);
65
+ readonly store = injectAgentStore("default");
66
+ readonly messages = this.store().messages;
193
67
 
194
- ### Key Points:
68
+ readonly input = signal("");
195
69
 
196
- - **No callback props**: Unlike React which uses `onSubmitMessage` callbacks, Angular uses dependency injection
197
- - **Service injection**: Inject `CopilotChatConfigurationService` to access `submitInput()`
198
- - **Cross-component communication**: The service handles message submission internally
199
- - **Type safety**: Full TypeScript support with proper type inference
70
+ async send() {
71
+ const content = this.input().trim();
72
+ if (!content) return;
200
73
 
201
- ### Alternative: Using the Chat Config Directive
74
+ const agent = this.store().agent;
202
75
 
203
- For template-level hooks, you can also use the `copilotkitChatConfig` directive:
204
-
205
- ```html
206
- <div
207
- [copilotkitChatConfig]="{
208
- onSubmitInput: handleSubmit,
209
- onChangeInput: handleChange
210
- }"
211
- >
212
- <copilot-chat></copilot-chat>
213
- </div>
214
- ```
76
+ agent.addMessage({
77
+ id: randomUUID(),
78
+ role: "user",
79
+ content,
80
+ });
215
81
 
216
- ```typescript
217
- export class ChatComponent {
218
- handleSubmit = (value: string) => {
219
- console.log("Message submitted:", value);
220
- };
82
+ this.input.set("");
221
83
 
222
- handleChange = (value: string) => {
223
- console.log("Input changed:", value);
224
- };
84
+ await this.copilotKit.core.runAgent({ agent });
85
+ }
225
86
  }
226
87
  ```
227
88
 
228
- ## Agents 101 (AG-UI)
229
-
230
- - **Agent model**: CopilotKit uses AG-UI's `AbstractAgent` interface (package `@ag-ui/client`)
231
- - **Frontend vs backend**:
232
- - **Backend (runtime)**: Host your real agents. You can use any AG-UI agent on the server
233
- - **Frontend (Angular app)**: Discovers remote agents from the runtime automatically, and can also host local in-browser agents if desired
234
- - **Default agent**: The ID `default` is special; when present, it is used by `<copilot-chat>` if no `agentId` is provided
235
- - **Compatibility**: Any agent that supports AG-UI works. See https://docs.ag-ui.com/
89
+ The `agent` is an AG-UI `AbstractAgent`. Refer to your AG-UI agent implementation for available methods and message formats.
236
90
 
237
- > **Note**: In most real apps, you define agents on the server (runtime). The frontend will auto-discover them when a `runtimeUrl` is configured.
91
+ ## Core configuration
238
92
 
239
- ## Backend Runtime (Hono Server)
93
+ ### `CopilotKitConfig`
240
94
 
241
- Example Angular server (from `apps/angular/demo-server`):
95
+ `provideCopilotKit` accepts a `CopilotKitConfig` object:
242
96
 
243
- ### `index.ts`
244
-
245
- ```typescript
246
- import { serve } from "@hono/node-server";
247
- import { Hono } from "hono";
248
- import { cors } from "hono/cors";
249
- import {
250
- CopilotRuntime,
251
- createCopilotEndpoint,
252
- InMemoryAgentRunner,
253
- } from "@copilotkitnext/runtime";
254
- import { AnyAGUIAgent } from "@ag-ui/your-desired-agent-framework";
255
-
256
- const runtime = new CopilotRuntime({
257
- agents: { default: new AnyAGUIAgent() },
258
- });
97
+ ```ts
98
+ export interface CopilotKitConfig {
99
+ runtimeUrl?: string;
100
+ headers?: Record<string, string>;
101
+ licenseKey?: string;
102
+ properties?: Record<string, unknown>;
103
+ agents?: Record<string, AbstractAgent>;
104
+ tools?: ClientTool[];
105
+ renderToolCalls?: RenderToolCallConfig[];
106
+ frontendTools?: FrontendToolConfig[];
107
+ humanInTheLoop?: HumanInTheLoopConfig[];
108
+ }
109
+ ```
259
110
 
260
- // Create a main app with CORS enabled
261
- const app = new Hono();
262
-
263
- // Enable CORS for local dev (Angular demo at http://localhost:4200)
264
- app.use(
265
- "*",
266
- cors({
267
- origin: "http://localhost:4200",
268
- allowMethods: ["GET", "POST", "OPTIONS", "PUT", "DELETE"],
269
- allowHeaders: ["Content-Type", "Authorization", "X-Requested-With"],
270
- exposeHeaders: ["Content-Type"],
271
- credentials: true,
272
- maxAge: 86400,
273
- }),
274
- );
275
-
276
- // Create the CopilotKit endpoint
277
- const copilotApp = createCopilotEndpoint({
278
- runtime,
279
- basePath: "/api/copilotkit",
280
- });
111
+ - `runtimeUrl`: URL to your CopilotKit runtime.
112
+ - `headers`: Default headers sent to the runtime.
113
+ - `licenseKey`: Copilot Cloud public API key (`ck_pub_...`), required by `provideCopilotKit`.
114
+ - `properties`: Arbitrary props forwarded to agent runs.
115
+ - `agents`: Local, in-browser agents keyed by `agentId`.
116
+ - `tools`: Tool definitions advertised to the runtime (no handler).
117
+ - `renderToolCalls`: Components to render tool calls in the UI.
118
+ - `frontendTools`: Client-side tools with handlers.
119
+ - `humanInTheLoop`: Tools that pause for user input.
281
120
 
282
- // Mount the CopilotKit app
283
- app.route("/", copilotApp);
121
+ ### Injection helpers
284
122
 
285
- const port = Number(process.env.PORT || 3001);
286
- serve({ fetch: app.fetch, port });
287
- console.log(
288
- `CopilotKit runtime listening at http://localhost:${port}/api/copilotkit`,
289
- );
290
- ```
123
+ - `provideCopilotKit(config)`: Provider for `CopilotKitConfig`.
291
124
 
292
- ## CopilotKit Angular APIs (Most Used)
125
+ ## `CopilotKit` service
293
126
 
294
- ### Components
127
+ ### Readonly signals
295
128
 
296
- - **`CopilotChatComponent`**: Full chat UI
297
- - Inputs: `agentId?: string`
129
+ - `agents`: `Signal<Record<string, AbstractAgent>>`
130
+ - `runtimeConnectionStatus`: `Signal<CopilotKitCoreRuntimeConnectionStatus>`
131
+ - `runtimeUrl`: `Signal<string | undefined>`
132
+ - `runtimeTransport`: `Signal<CopilotRuntimeTransport>` (`"rest" | "single"`)
133
+ - `headers`: `Signal<Record<string, string>>`
134
+ - `toolCallRenderConfigs`: `Signal<RenderToolCallConfig[]>`
135
+ - `clientToolCallRenderConfigs`: `Signal<FrontendToolConfig[]>`
136
+ - `humanInTheLoopToolRenderConfigs`: `Signal<HumanInTheLoopConfig[]>`
298
137
 
299
- ### Directives
138
+ ### Methods
300
139
 
301
- - **`CopilotKitConfigDirective`** (`[copilotkitConfig]`): Set `runtimeUrl`, `headers`, `properties`, and/or `agents` declaratively
302
- - **`CopilotKitAgentDirective`** (`[copilotkitAgent]`): Observe agent state; defaults to the `default` agent if no `agentId` is provided
140
+ - `getAgent(agentId: string): AbstractAgent | undefined`
141
+ - `addFrontendTool(config: FrontendToolConfig & { injector: Injector }): void`
142
+ - `addRenderToolCall(config: RenderToolCallConfig): void`
143
+ - `addHumanInTheLoop(config: HumanInTheLoopConfig): void`
144
+ - `removeTool(toolName: string, agentId?: string): void`
145
+ - `updateRuntime(options: { runtimeUrl?: string; runtimeTransport?: CopilotRuntimeTransport; headers?: Record<string,string>; properties?: Record<string, unknown>; agents?: Record<string, AbstractAgent>; }): void`
303
146
 
304
- ### Providers
147
+ ### Advanced
305
148
 
306
- - **`provideCopilotKit(...)`**: Set runtime URL, headers, properties, agents, tools, human-in-the-loop handlers
307
- - **`provideCopilotChatConfiguration(...)`**: Set UI labels and behavior for chat input/view
149
+ - `core`: The underlying `CopilotKitCore` instance.
308
150
 
309
- ## Headless Usage: Building Custom Chat UIs
151
+ ## Agents
310
152
 
311
- For advanced use cases where you need full control over the chat UI, you can use the `watchAgent` utility directly to build a custom chat component.
153
+ ### `injectAgentStore`
312
154
 
313
- ### Using `watchAgent` for Custom Components
155
+ ```ts
156
+ const store = injectAgentStore("default");
157
+ // or: injectAgentStore(signal(agentId))
158
+ ```
314
159
 
315
- The `watchAgent` function provides reactive signals for agent state, making it easy to build custom chat interfaces:
160
+ Returns a `Signal<AgentStore>`. The store exposes:
316
161
 
317
- ```typescript
318
- import { Component, effect } from "@angular/core";
319
- import { watchAgent } from "@copilotkitnext/angular";
162
+ - `agent`: `AbstractAgent`
163
+ - `messages`: `Signal<Message[]>`
164
+ - `state`: `Signal<any>`
165
+ - `isRunning`: `Signal<boolean>`
166
+ - `teardown()`: Clean up subscriptions
320
167
 
321
- @Component({
322
- selector: "my-custom-chat",
323
- template: `
324
- <div class="custom-chat">
325
- <div *ngFor="let msg of messages()" class="message">
326
- {{ msg.content }}
327
- </div>
328
- <input [disabled]="isRunning()" (keyup.enter)="sendMessage($event)" />
329
- </div>
330
- `,
331
- })
332
- export class MyCustomChatComponent {
333
- protected agent!: ReturnType<typeof watchAgent>["agent"];
334
- protected messages!: ReturnType<typeof watchAgent>["messages"];
335
- protected isRunning!: ReturnType<typeof watchAgent>["isRunning"];
336
-
337
- constructor() {
338
- const w = watchAgent({ agentId: "custom" });
339
- this.agent = w.agent;
340
- this.messages = w.messages;
341
- this.isRunning = w.isRunning;
342
-
343
- // React to agent changes
344
- effect(() => {
345
- const currentAgent = this.agent();
346
- if (currentAgent) {
347
- console.log("Agent ready:", currentAgent.id);
348
- }
349
- });
350
- }
168
+ If the agent is not available locally but a `runtimeUrl` is configured, a proxy agent is created while the runtime connects. If the agent still cannot be resolved, an error is thrown that includes the configured runtime and known agent IDs.
351
169
 
352
- async sendMessage(event: Event) {
353
- const input = event.target as HTMLInputElement;
354
- const content = input.value.trim();
355
- if (!content || !this.agent()) return;
170
+ ### `CopilotkitAgentFactory`
356
171
 
357
- // Add user message and run agent
358
- this.agent()!.addMessage({ role: "user", content });
359
- input.value = "";
360
- await this.agent()!.runAgent();
361
- }
362
- }
363
- ```
172
+ Advanced factory for creating `AgentStore` signals. Most apps should use `injectAgentStore` instead.
364
173
 
365
- ### Switching Agents at Runtime
174
+ ## Agent context
366
175
 
367
- Use `watchAgentWith` when you need to switch agents dynamically outside of the constructor:
176
+ ### `connectAgentContext`
368
177
 
369
- ```typescript
370
- import { Component, Injector } from "@angular/core";
371
- import { watchAgent, watchAgentWith } from "@copilotkitnext/angular";
178
+ Connect AG-UI context to the runtime (auto-cleanup when the effect is destroyed):
372
179
 
373
- @Component({
374
- selector: "agent-switcher",
375
- template: `
376
- <button (click)="switchToAgent('sales')">Sales Agent</button>
377
- <button (click)="switchToAgent('support')">Support Agent</button>
378
- <div>Current Agent: {{ agent()?.id || "None" }}</div>
379
- `,
380
- })
381
- export class AgentSwitcherComponent {
382
- protected agent!: ReturnType<typeof watchAgent>["agent"];
383
- protected messages!: ReturnType<typeof watchAgent>["messages"];
384
- protected isRunning!: ReturnType<typeof watchAgent>["isRunning"];
385
- private watcher?: ReturnType<typeof watchAgent>;
386
-
387
- constructor(private injector: Injector) {
388
- // Initialize with default agent
389
- this.switchToAgent("default");
390
- }
180
+ ```ts
181
+ import { connectAgentContext } from "@copilotkitnext/angular";
391
182
 
392
- switchToAgent(agentId: string) {
393
- // Clean up previous watcher
394
- this.watcher?.unsubscribe();
183
+ connectAgentContext({
184
+ description: "User preferences",
185
+ value: { theme: "dark" },
186
+ });
187
+ ```
395
188
 
396
- // Create new watcher with the ergonomic helper
397
- const w = watchAgentWith(this.injector, { agentId });
189
+ You must call it within an injection context (e.g., inside a component constructor or `runInInjectionContext`), or pass an explicit `Injector`:
398
190
 
399
- // Update component signals
400
- this.agent = w.agent;
401
- this.messages = w.messages;
402
- this.isRunning = w.isRunning;
403
- this.watcher = w;
404
- }
405
- }
191
+ ```ts
192
+ connectAgentContext(contextSignal, { injector });
406
193
  ```
407
194
 
408
- ### Rendering Tool Calls (Headless)
409
-
410
- To render tool calls in a headless UI, register renderers in your providers and drop the lightweight view in your template.
195
+ ## Tools and tool rendering
411
196
 
412
- 1. Register tool renderers (e.g., a wildcard that renders any tool):
197
+ ### Types
413
198
 
414
199
  ```ts
415
- import { ApplicationConfig, importProvidersFrom } from "@angular/core";
416
- import { BrowserModule } from "@angular/platform-browser";
417
- import { provideCopilotKit } from "@copilotkitnext/angular";
200
+ export interface RenderToolCallConfig<Args> {
201
+ name: string; // tool name, or "*" for wildcard
202
+ args: z.ZodType<Args>; // Zod schema for args
203
+ component: Type<ToolRenderer<Args>>;
204
+ agentId?: string; // optional agent scope
205
+ }
418
206
 
419
- // Simple demo renderer (Component or TemplateRef accepted)
420
- @Component({
421
- standalone: true,
422
- template: `
423
- <div
424
- style="padding:12px;border:1px solid #e5e7eb;border-radius:8px;background:#fff;margin:8px 0;"
425
- >
426
- <div style="font-weight:600;margin-bottom:6px;">Tool: {{ name }}</div>
427
- <pre style="margin:0;white-space:pre-wrap;">{{ args | json }}</pre>
428
- <div *ngIf="result" style="margin-top:6px;">Result: {{ result }}</div>
429
- </div>
430
- `,
431
- })
432
- export class WildcardToolRenderComponent {
433
- @Input() name!: string;
434
- @Input() args: any;
435
- @Input() status: any;
436
- @Input() result?: string;
207
+ export interface FrontendToolConfig<Args> {
208
+ name: string;
209
+ description: string;
210
+ parameters: z.ZodType<Args>;
211
+ component?: Type<ToolRenderer<Args>>; // optional UI renderer
212
+ handler: (args: Args, context: FrontendToolHandlerContext) => Promise<unknown>;
213
+ agentId?: string;
437
214
  }
438
215
 
439
- export const appConfig: ApplicationConfig = {
440
- providers: [
441
- importProvidersFrom(BrowserModule),
442
- ...provideCopilotKit({
443
- renderToolCalls: [{ name: "*", render: WildcardToolRenderComponent }],
444
- }),
445
- ],
216
+ export interface HumanInTheLoopConfig<Args> {
217
+ name: string;
218
+ description: string;
219
+ parameters: z.ZodType<Args>;
220
+ component: Type<HumanInTheLoopToolRenderer<Args>>;
221
+ agentId?: string;
222
+ }
223
+
224
+ export type ClientTool<Args> = Omit<FrontendTool<Args>, \"handler\"> & {
225
+ renderer?: Type<ToolRenderer<Args>>;
446
226
  };
447
227
  ```
448
228
 
449
- 2. Render tool calls under assistant messages using the headless view component:
229
+ Renderer components receive a signal:
450
230
 
451
231
  ```ts
452
- import { Component } from "@angular/core";
453
- import {
454
- watchAgent,
455
- CopilotChatToolCallsViewComponent,
456
- } from "@copilotkitnext/angular";
232
+ export interface ToolRenderer<Args> {
233
+ toolCall: Signal<AngularToolCall<Args>>;
234
+ }
457
235
 
458
- @Component({
459
- standalone: true,
460
- imports: [CopilotChatToolCallsViewComponent],
461
- template: `
462
- <div *ngFor="let m of messages()">
463
- <div>{{ m.role }}: {{ m.content }}</div>
464
- <ng-container *ngIf="m.role === 'assistant'">
465
- <copilot-chat-tool-calls-view
466
- [message]="m"
467
- [messages]="messages()"
468
- [isLoading]="isRunning()"
469
- />
470
- </ng-container>
471
- </div>
472
- `,
473
- })
474
- export class HeadlessWithToolsComponent {
475
- agent = watchAgent().agent;
476
- messages = watchAgent().messages;
477
- isRunning = watchAgent().isRunning;
236
+ export interface HumanInTheLoopToolRenderer<Args> {
237
+ toolCall: Signal<HumanInTheLoopToolCall<Args>>; // includes respond(result)
478
238
  }
479
239
  ```
480
240
 
481
- Notes:
241
+ `AngularToolCall` / `HumanInTheLoopToolCall` expose `args`, `status` (`"in-progress" | "executing" | "complete"`), and `result`.
482
242
 
483
- - If you prefer full manual control, you can render a specific tool call with `CopilotKitToolRenderComponent` and pass `toolName`, `args`, `status`, and `result` yourself.
484
- - You can also register tool renders declaratively via the `CopilotKitFrontendToolDirective` by using `[copilotkitFrontendTool]` in templates.
243
+ ### Register tools with DI
485
244
 
486
- ### Key Benefits of Headless Usage
245
+ These helpers auto-remove tools when the current injection context is destroyed:
246
+ Call them from an injection context (e.g., a component constructor, directive, or `runInInjectionContext`).
247
+
248
+ ```ts
249
+ import {
250
+ registerFrontendTool,
251
+ registerRenderToolCall,
252
+ registerHumanInTheLoop,
253
+ } from "@copilotkitnext/angular";
254
+ import { z } from "zod";
487
255
 
488
- - **Full control**: Build any UI you need without constraints
489
- - **Reactive signals**: Automatically update UI when agent state changes
490
- - **Type safety**: Full TypeScript support with AG-UI types
491
- - **Memory efficient**: Automatic cleanup via Angular's DestroyRef
492
- - **Framework agnostic**: Works with any AG-UI compatible agent
256
+ registerFrontendTool({
257
+ name: "lookup",
258
+ description: "Fetch a record",
259
+ parameters: z.object({ id: z.string() }),
260
+ handler: async ({ id }) => ({ id, ok: true }),
261
+ });
493
262
 
494
- ## End-to-End: Running the Demo
263
+ registerRenderToolCall({
264
+ name: "*", // wildcard renderer
265
+ args: z.any(),
266
+ component: MyToolCallRenderer,
267
+ });
495
268
 
496
- From the repo root:
269
+ registerHumanInTheLoop({
270
+ name: "approval",
271
+ description: "Request approval",
272
+ parameters: z.object({ reason: z.string() }),
273
+ component: ApprovalRenderer,
274
+ });
275
+ ```
497
276
 
498
- 1. **Install deps**: `pnpm install`
499
- 2. **Start both demo server and Angular demo app**: pnpm build && pnpm demo:angular`
500
- - Frontend: runs on http://localhost:4200
501
- - Backend: runs on http://localhost:3001/api/copilotkit
502
- 3. **Prerequisite**: Set `OPENAI_API_KEY` in `apps/angular/demo-server/.env` if using the OpenAI demo agent
277
+ ### Configure tools in `provideCopilotKit`
503
278
 
504
- ## Building This Monorepo
279
+ ```ts
280
+ provideCopilotKit({
281
+ licenseKey: "ck_pub_your_public_api_key",
282
+ frontendTools: [
283
+ /* FrontendToolConfig[] */
284
+ ],
285
+ renderToolCalls: [
286
+ /* RenderToolCallConfig[] */
287
+ ],
288
+ humanInTheLoop: [
289
+ /* HumanInTheLoopConfig[] */
290
+ ],
291
+ tools: [
292
+ /* ClientTool[] */
293
+ ],
294
+ });
295
+ ```
505
296
 
506
- - **Full build**: `pnpm build` (compiles all packages including Angular)
507
- - **Clean**: `pnpm clean`
508
- - **Package-only dev (watch)**: `pnpm dev`
297
+ `tools` are advertised to the runtime. If you include `renderer` + `parameters` on a `ClientTool`, CopilotKit will also register a renderer for tool calls.
509
298
 
510
- ## Angular Storybook
299
+ ## `RenderToolCalls` component
511
300
 
512
- ### Dev Server
301
+ `RenderToolCalls` renders tool call components under an assistant message based on registered render configs.
513
302
 
514
- ```bash
515
- pnpm storybook:angular
303
+ ```html
304
+ <copilot-render-tool-calls
305
+ [message]="assistantMessage"
306
+ [messages]="messages"
307
+ [isLoading]="isRunning"
308
+ ></copilot-render-tool-calls>
516
309
  ```
517
310
 
518
- - Serves Storybook for Angular components on http://localhost:6007
519
- - For live chat stories, ensure the demo server is running so the chat can connect:
520
- ```bash
521
- pnpm --filter @copilotkitnext/angular-demo-server dev
522
- ```
311
+ Inputs:
523
312
 
524
- ### Production Build
313
+ - `message`: `AssistantMessage` (must include `toolCalls`)
314
+ - `messages`: full `Message[]` list (used to find tool results)
315
+ - `isLoading`: whether the agent is currently running
525
316
 
526
- ```bash
527
- pnpm -C apps/angular/storybook build
528
- ```
317
+ Tool arguments are parsed with `partialJSONParse`, so incomplete JSON during streaming still renders.
318
+
319
+ ## Runtime notes
320
+
321
+ - Set `runtimeUrl` to your CopilotKit runtime endpoint.
322
+ - If you need to change runtime settings at runtime, call `CopilotKit.updateRuntime(...)`.
323
+ - `runtimeTransport` supports `"rest"` or `"single"` (SSE single-stream transport).
529
324
 
530
- ## Notes
325
+ ## Not documented here
531
326
 
532
- - Node 18+ and pnpm 9+ recommended
533
- - If using custom CORS or non-default ports, update `runtimeUrl` and server CORS settings accordingly
534
- - Styles must be included for proper rendering; if customizing CSS, prefer overriding classes instead of modifying the distributed CSS
327
+ This package also exports a full set of chat UI components under `src/lib/components/chat`. Those APIs are intentionally omitted from this README.