Skip to content

Commit c9372c2

Browse files
authored
Implement activity message rendering (#32)
1 parent c3dcad7 commit c9372c2

33 files changed

+1045
-500
lines changed

apps/angular/demo-server/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"start": "node --env-file=.env --loader tsx src/index.ts"
99
},
1010
"dependencies": {
11-
"@ag-ui/client": "0.0.40-alpha.6",
11+
"@ag-ui/client": "0.0.40-alpha.11",
1212
"@ag-ui/langgraph": "^0.0.11",
1313
"@copilotkitnext/demo-agents": "workspace:^",
1414
"@copilotkitnext/runtime": "workspace:^",

apps/angular/storybook/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"storybook:build": "ng run storybook-angular:build-storybook"
1010
},
1111
"dependencies": {
12-
"@ag-ui/client": "0.0.40-alpha.6",
12+
"@ag-ui/client": "0.0.40-alpha.11",
1313
"@angular/animations": "^18.2.0",
1414
"@angular/common": "^18.2.0",
1515
"@angular/compiler": "^18.2.0",

apps/angular/storybook/stories/CopilotChatUserMessage.stories.ts

Lines changed: 22 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,14 @@
11
import type { Meta, StoryObj } from "@storybook/angular";
22
import { moduleMetadata } from "@storybook/angular";
33
import { CommonModule } from "@angular/common";
4-
import {
5-
CopilotChatUserMessage,
6-
provideCopilotChatLabels,
7-
type UserMessage,
8-
} from "@copilotkitnext/angular";
4+
import { CopilotChatUserMessage, provideCopilotChatLabels } from "@copilotkitnext/angular";
5+
import { UserMessage } from "@ag-ui/client";
96

107
// Simple default message
118
const simpleMessage: UserMessage = {
129
id: "simple-user-message",
1310
content: "Hello! Can you help me build an Angular component?",
1411
role: "user",
15-
timestamp: new Date(),
1612
};
1713

1814
// Longer user message
@@ -29,7 +25,6 @@ const longMessage: UserMessage = {
2925
3026
Can you help me implement this step by step? I'm particularly struggling with the form validation and state management parts.`,
3127
role: "user",
32-
timestamp: new Date(),
3328
};
3429

3530
// Code-related user message
@@ -55,15 +50,13 @@ export class UserListComponent {
5550
5651
How can I fix this?`,
5752
role: "user",
58-
timestamp: new Date(),
5953
};
6054

6155
// Short question
6256
const shortMessage: UserMessage = {
6357
id: "short-user-message",
6458
content: "What's the difference between signals and observables in Angular?",
6559
role: "user",
66-
timestamp: new Date(),
6760
};
6861

6962
const meta: Meta<CopilotChatUserMessage> = {
@@ -130,7 +123,7 @@ export class ChatComponent {
130123
role: 'user',
131124
timestamp: new Date(),
132125
};
133-
126+
134127
onEditMessage(event: any): void {
135128
console.log('Edit message:', event);
136129
}
@@ -179,7 +172,7 @@ Can you help me implement this step by step? I'm particularly struggling with th
179172
role: 'user',
180173
timestamp: new Date(),
181174
};
182-
175+
183176
onEditMessage(event: any): void {
184177
console.log('Edit message:', event);
185178
}
@@ -220,7 +213,7 @@ export class ChatComponent {
220213
role: 'user',
221214
timestamp: new Date(),
222215
};
223-
216+
224217
onEditMessage(event: any): void {
225218
alert('Edit message clicked!');
226219
console.log('Edit message:', event);
@@ -261,7 +254,7 @@ export class ChatComponent {
261254
role: 'user',
262255
timestamp: new Date(),
263256
};
264-
257+
265258
// No edit handler - edit button won't appear
266259
}`,
267260
language: "typescript",
@@ -318,7 +311,7 @@ How can I fix this?\`,
318311
role: 'user',
319312
timestamp: new Date(),
320313
};
321-
314+
322315
onEditMessage(event: any): void {
323316
alert('Edit code message clicked!');
324317
}
@@ -359,7 +352,7 @@ export class ChatComponent {
359352
role: 'user',
360353
timestamp: new Date(),
361354
};
362-
355+
363356
onEditMessage(event: any): void {
364357
console.log('Edit short message clicked!');
365358
}
@@ -391,7 +384,7 @@ export const WithAdditionalToolbarItems: Story = {
391384
🔄
392385
</button>
393386
</ng-template>
394-
387+
395388
<div style="display: flex; justify-content: center; align-items: flex-start; min-height: 100vh; padding: 16px;">
396389
<div style="width: 100%; max-width: 640px;">
397390
<copilot-chat-user-message
@@ -429,7 +422,7 @@ import { CopilotChatUserMessage, UserMessage } from '@copilotkitnext/angular';
429422
🔄
430423
</button>
431424
</ng-template>
432-
425+
433426
<copilot-chat-user-message
434427
[message]="message"
435428
[additionalToolbarItems]="additionalItems"
@@ -439,22 +432,22 @@ import { CopilotChatUserMessage, UserMessage } from '@copilotkitnext/angular';
439432
})
440433
export class ChatComponent {
441434
@ViewChild('additionalItems') additionalItems!: TemplateRef<any>;
442-
435+
443436
message: UserMessage = {
444437
id: 'simple-user-message',
445438
content: 'Hello! Can you help me build an Angular component?',
446439
role: 'user',
447440
timestamp: new Date(),
448441
};
449-
442+
450443
onEditMessage(event: any): void {
451444
console.log('Edit clicked!');
452445
}
453-
446+
454447
onCustomAction1(): void {
455448
alert('Custom button 1 clicked!');
456449
}
457-
450+
458451
onCustomAction2(): void {
459452
alert('Custom button 2 clicked!');
460453
}
@@ -482,7 +475,7 @@ export const CustomAppearance: Story = {
482475
{{ content }}
483476
</div>
484477
</ng-template>
485-
478+
486479
<ng-template #toolbar>
487480
<div class="w-full bg-transparent flex items-center justify-end -mr-[5px] mt-[8px] invisible group-hover:visible">
488481
<div class="flex items-center gap-1 justify-end">
@@ -499,7 +492,7 @@ export const CustomAppearance: Story = {
499492
</div>
500493
</div>
501494
</ng-template>
502-
495+
503496
<div style="display: flex; justify-content: center; align-items: flex-start; min-height: 100vh; padding: 16px;">
504497
<div style="width: 100%; max-width: 640px;">
505498
<copilot-chat-user-message
@@ -522,8 +515,7 @@ export const CustomComponents: Story = {
522515
args: {
523516
message: simpleMessage,
524517
editMessage: () => console.log("Edit clicked!"),
525-
inputClass:
526-
"bg-gradient-to-r from-purple-100 to-pink-100 rounded-xl p-4 shadow-sm",
518+
inputClass: "bg-gradient-to-r from-purple-100 to-pink-100 rounded-xl p-4 shadow-sm",
527519
},
528520
render: () => ({
529521
props: {
@@ -536,7 +528,7 @@ export const CustomComponents: Story = {
536528
💬 {{ content }}
537529
</div>
538530
</ng-template>
539-
531+
540532
<div style="display: flex; justify-content: center; align-items: flex-start; min-height: 100vh; padding: 16px;">
541533
<div style="width: 100%; max-width: 640px;">
542534
<copilot-chat-user-message
@@ -559,30 +551,26 @@ export const WithBranchNavigation: Story = {
559551
args: {
560552
message: {
561553
id: "branch-message",
562-
content:
563-
"This message has multiple branches. You can navigate between them using the branch controls.",
554+
content: "This message has multiple branches. You can navigate between them using the branch controls.",
564555
role: "user",
565556
},
566557
editMessage: () => console.log("Edit clicked!"),
567558
branchIndex: 2,
568559
numberOfBranches: 3,
569-
switchToBranch: ({ branchIndex }) =>
570-
console.log(`Switching to branch ${branchIndex + 1}`),
560+
switchToBranch: ({ branchIndex }) => console.log(`Switching to branch ${branchIndex + 1}`),
571561
},
572562
};
573563

574564
export const WithManyBranches: Story = {
575565
args: {
576566
message: {
577567
id: "many-branches-message",
578-
content:
579-
"This is branch 5 of 10. Use the navigation arrows to explore different variations of this message.",
568+
content: "This is branch 5 of 10. Use the navigation arrows to explore different variations of this message.",
580569
role: "user",
581570
},
582571
editMessage: () => console.log("Edit clicked!"),
583572
branchIndex: 4,
584573
numberOfBranches: 10,
585-
switchToBranch: ({ branchIndex }) =>
586-
alert(`Would switch to branch ${branchIndex + 1} of 10`),
574+
switchToBranch: ({ branchIndex }) => alert(`Would switch to branch ${branchIndex + 1} of 10`),
587575
},
588576
};

apps/react/demo/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
"lint": "next lint"
1010
},
1111
"dependencies": {
12-
"@ag-ui/client": "0.0.40-alpha.6",
12+
"@ag-ui/client": "0.0.40-alpha.11",
13+
"@ag-ui/a2a": "0.0.5",
14+
"@a2a-js/sdk": "^0.2.2",
1315
"@copilotkitnext/agent": "workspace:*",
1416
"@copilotkitnext/core": "workspace:*",
1517
"@copilotkitnext/react": "workspace:*",

apps/react/demo/src/app/api/copilotkit/[[...slug]]/route.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { CopilotRuntime, createCopilotEndpoint, InMemoryAgentRunner } from "@copilotkitnext/runtime";
22
import { handle } from "hono/vercel";
33
import { BasicAgent } from "@copilotkitnext/agent";
4+
import { A2AAgent } from "@ag-ui/a2a";
5+
import { A2AClient } from "@a2a-js/sdk/client";
46

57
// Determine which model to use based on available API keys
68
const getModelConfig = () => {
@@ -15,11 +17,14 @@ const getModelConfig = () => {
1517
return "openai/gpt-4o";
1618
};
1719

18-
const agent = new BasicAgent({
19-
model: getModelConfig(),
20-
prompt: "You are a helpful AI assistant.",
21-
temperature: 0.7,
22-
});
20+
// const agent = new BasicAgent({
21+
// model: getModelConfig(),
22+
// prompt: "You are a helpful AI assistant.",
23+
// temperature: 0.7,
24+
// });
25+
//
26+
const a2aClient = new A2AClient("http://localhost:10002");
27+
const agent = new A2AAgent({ a2aClient, debug: true });
2328

2429
const runtime = new CopilotRuntime({
2530
agents: {

apps/react/demo/src/app/page.tsx

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,20 @@ export default function Home() {
3939
});
4040

4141
return (
42-
<CopilotKitProvider runtimeUrl="/api/copilotkit" renderToolCalls={[wildcardRenderer]} showDevConsole="auto">
42+
<CopilotKitProvider
43+
runtimeUrl="/api/copilotkit"
44+
renderToolCalls={[wildcardRenderer]}
45+
showDevConsole="auto"
46+
renderActivityMessages={[
47+
{
48+
activityType: "a2ui-surface",
49+
content: z.any(),
50+
render: ({ content }) => {
51+
return <pre>{JSON.stringify(content, null, 2)}</pre>;
52+
},
53+
},
54+
]}
55+
>
4356
<div style={{ height: "100vh", margin: 0, padding: 0, overflow: "hidden" }}>
4457
<Chat />
4558
</div>
@@ -48,9 +61,9 @@ export default function Home() {
4861
}
4962

5063
function Chat() {
51-
useConfigureSuggestions({
52-
instructions: "Suggest helpful next actions",
53-
});
64+
//useConfigureSuggestions({
65+
// instructions: "Suggest helpful next actions",
66+
//});
5467

5568
// useConfigureSuggestions({
5669
// suggestions: [

packages/agent/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
"vitest": "^3.0.5"
3737
},
3838
"dependencies": {
39-
"@ag-ui/client": "0.0.40-alpha.6",
39+
"@ag-ui/client": "0.0.40-alpha.11",
4040
"@ai-sdk/anthropic": "^2.0.22",
4141
"@ai-sdk/google": "^2.0.17",
4242
"@ai-sdk/openai": "^2.0.42",

packages/agent/src/index.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,34 @@ export function defineTool<TParameters extends z.ZodTypeAny>(config: {
232232
};
233233
}
234234

235+
type AGUIUserMessage = Extract<Message, { role: "user" }>;
236+
237+
function flattenUserMessageContent(content?: AGUIUserMessage["content"]): string {
238+
if (!content) {
239+
return "";
240+
}
241+
242+
if (typeof content === "string") {
243+
return content;
244+
}
245+
246+
return content
247+
.map((part) => {
248+
if (
249+
part &&
250+
typeof part === "object" &&
251+
"type" in part &&
252+
(part as { type?: unknown }).type === "text" &&
253+
typeof (part as { text?: unknown }).text === "string"
254+
) {
255+
return (part as { text: string }).text;
256+
}
257+
return "";
258+
})
259+
.filter((text) => text.length > 0)
260+
.join("\n");
261+
}
262+
235263
/**
236264
* Converts AG-UI messages to Vercel AI SDK ModelMessage format
237265
*/
@@ -260,7 +288,7 @@ export function convertMessagesToVercelAISDKMessages(messages: Message[]): Model
260288
} else if (message.role === "user") {
261289
const userMsg: UserModelMessage = {
262290
role: "user",
263-
content: message.content || "",
291+
content: flattenUserMessageContent(message.content),
264292
};
265293
result.push(userMsg);
266294
} else if (message.role === "tool") {

packages/angular/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@
3131
"test:watch": "vitest --watch"
3232
},
3333
"dependencies": {
34-
"@ag-ui/client": "0.0.40-alpha.6",
35-
"@ag-ui/core": "0.0.40-alpha.6",
34+
"@ag-ui/client": "0.0.40-alpha.11",
35+
"@ag-ui/core": "0.0.40-alpha.11",
3636
"@copilotkitnext/core": "workspace:*",
3737
"@copilotkitnext/shared": "workspace:*",
3838
"clsx": "^2.1.1",

0 commit comments

Comments
 (0)