Skip to content

Commit cceadc8

Browse files
authored
Implement Suggestions (#12)
1 parent 732c619 commit cceadc8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+6328
-1343
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.38-alpha.2",
11+
"@ag-ui/client": "0.0.40-alpha.3",
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.38-alpha.2",
12+
"@ag-ui/client": "0.0.40-alpha.3",
1313
"@angular/animations": "^18.2.0",
1414
"@angular/common": "^18.2.0",
1515
"@angular/compiler": "^18.2.0",

apps/react/demo/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"lint": "next lint"
1010
},
1111
"dependencies": {
12-
"@ag-ui/client": "0.0.38-alpha.2",
12+
"@ag-ui/client": "0.0.40-alpha.3",
1313
"@copilotkitnext/core": "workspace:*",
1414
"@copilotkitnext/demo-agents": "workspace:*",
1515
"@copilotkitnext/react": "workspace:*",

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

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import { HttpAgent } from "@ag-ui/client";
44
import {
55
CopilotChat,
66
CopilotKitProvider,
7-
useCopilotKit,
87
useFrontendTool,
98
defineToolCallRender,
9+
useConfigureSuggestions,
1010
} from "@copilotkitnext/react";
1111
import { z } from "zod";
1212

@@ -19,13 +19,15 @@ export default function Home() {
1919
name: "*",
2020
// No args needed for wildcard - defaults to z.any()
2121
render: ({ name, args, status }) => (
22-
<div style={{
23-
padding: "12px",
24-
margin: "8px 0",
25-
backgroundColor: "#f0f0f0",
26-
borderRadius: "8px",
27-
border: "1px solid #ccc"
28-
}}>
22+
<div
23+
style={{
24+
padding: "12px",
25+
margin: "8px 0",
26+
backgroundColor: "#f0f0f0",
27+
borderRadius: "8px",
28+
border: "1px solid #ccc",
29+
}}
30+
>
2931
<strong>Unknown Tool: {name}</strong>
3032
<pre style={{ marginTop: "8px", fontSize: "12px" }}>
3133
Status: {status}
@@ -36,21 +38,31 @@ export default function Home() {
3638
});
3739

3840
return (
39-
<CopilotKitProvider
40-
runtimeUrl="/api/copilotkit"
41-
renderToolCalls={[wildcardRenderer]}
42-
>
43-
<div
44-
style={{ height: "100vh", margin: 0, padding: 0, overflow: "hidden" }}
45-
>
41+
<CopilotKitProvider runtimeUrl="/api/copilotkit" renderToolCalls={[wildcardRenderer]}>
42+
<div style={{ height: "100vh", margin: 0, padding: 0, overflow: "hidden" }}>
4643
<Chat />
4744
</div>
4845
</CopilotKitProvider>
4946
);
5047
}
5148

5249
function Chat() {
53-
const { copilotkit } = useCopilotKit();
50+
useConfigureSuggestions({
51+
instructions: "Suggest helpful next actions",
52+
});
53+
54+
// useConfigureSuggestions({
55+
// suggestions: [
56+
// {
57+
// title: "Action 1",
58+
// message: "Do action 1",
59+
// },
60+
// {
61+
// title: "Action 2",
62+
// message: "Do action 2",
63+
// },
64+
// ],
65+
// });
5466

5567
useFrontendTool({
5668
name: "sayHello",
@@ -62,5 +74,5 @@ function Chat() {
6274
return `Hello ${name}`;
6375
},
6476
});
65-
return <CopilotChat threadId="xyz" />;
77+
return <CopilotChat />;
6678
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import type { Meta, StoryObj } from "@storybook/react";
2+
import { Sparkles, ArrowRight } from "lucide-react";
3+
import { CopilotChatSuggestionPill } from "@copilotkitnext/react";
4+
5+
const meta = {
6+
title: "UI/CopilotChatSuggestionPill",
7+
component: CopilotChatSuggestionPill,
8+
args: {
9+
children: "Draft a project brief",
10+
},
11+
parameters: {
12+
layout: "centered",
13+
},
14+
} satisfies Meta<typeof CopilotChatSuggestionPill>;
15+
16+
export default meta;
17+
18+
type Story = StoryObj<typeof CopilotChatSuggestionPill>;
19+
20+
export const Default: Story = {};
21+
22+
export const WithIcon: Story = {
23+
args: {
24+
icon: <Sparkles className="h-4 w-4" aria-hidden="true" />,
25+
},
26+
};
27+
28+
export const Loading: Story = {
29+
args: {
30+
isLoading: true,
31+
},
32+
};
33+
34+
export const WithArrow: Story = {
35+
args: {
36+
icon: <ArrowRight className="h-4 w-4" aria-hidden="true" />,
37+
children: "Summarize notes into next steps",
38+
},
39+
};
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import type { Meta, StoryObj } from "@storybook/react";
2+
import {
3+
CopilotChatSuggestionView,
4+
CopilotChatSuggestionPill,
5+
} from "@copilotkitnext/react";
6+
import { Suggestion } from "@copilotkitnext/core";
7+
import { Sparkles } from "lucide-react";
8+
9+
const suggestions: Suggestion[] = [
10+
{ title: "Summarize this thread", message: "Summarize the latest chat", isLoading: false },
11+
{ title: "Draft a reply", message: "Draft a polite follow-up", isLoading: false },
12+
{ title: "Create action items", message: "List next steps", isLoading: false },
13+
];
14+
15+
const meta = {
16+
title: "UI/CopilotChatSuggestionView",
17+
component: CopilotChatSuggestionView,
18+
args: {
19+
suggestions,
20+
},
21+
parameters: {
22+
layout: "centered",
23+
},
24+
} satisfies Meta<typeof CopilotChatSuggestionView>;
25+
26+
export default meta;
27+
28+
type Story = StoryObj<typeof CopilotChatSuggestionView>;
29+
30+
export const Default: Story = {};
31+
32+
export const LoadingSecond: Story = {
33+
args: {
34+
suggestions: suggestions.map((suggestion, index) =>
35+
index === 1 ? { ...suggestion, isLoading: true } : suggestion,
36+
),
37+
},
38+
};
39+
40+
export const CustomSuggestionSlot: Story = {
41+
args: {
42+
suggestion: (props) => (
43+
<CopilotChatSuggestionPill
44+
{...props}
45+
icon={<Sparkles className="h-4 w-4" aria-hidden="true" />}
46+
/>
47+
),
48+
},
49+
};

apps/react/storybook/stories/CopilotChatView.stories.tsx

Lines changed: 106 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
CopilotChatView,
55
CopilotKitProvider,
66
} from "@copilotkitnext/react";
7+
import { Suggestion } from "@copilotkitnext/core";
78

89
const meta = {
910
title: "UI/CopilotChatView",
@@ -34,16 +35,96 @@ export const Default: Story = {
3435
),
3536
],
3637
render: () => {
37-
const messages = [
38-
{
39-
id: "user-1",
40-
content: "Hello! Can you help me understand how React hooks work?",
41-
timestamp: new Date(),
42-
role: "user" as const,
43-
},
44-
{
45-
id: "assistant-1",
46-
content: `React hooks are functions that let you use state and other React features in functional components. Here are the most common ones:
38+
return (
39+
<CopilotKitProvider>
40+
<CopilotChatConfigurationProvider threadId="storybook-thread">
41+
<div style={{ height: "100%" }}>
42+
<CopilotChatView
43+
messages={storyMessages}
44+
inputProps={{
45+
onSubmitMessage: (value) => {
46+
alert(`Message submitted: ${value}`);
47+
},
48+
}}
49+
messageView={{
50+
assistantMessage: {
51+
onThumbsUp: () => {
52+
alert("thumbsUp");
53+
},
54+
onThumbsDown: () => {
55+
alert("thumbsDown");
56+
},
57+
},
58+
}}
59+
/>
60+
</div>
61+
</CopilotChatConfigurationProvider>
62+
</CopilotKitProvider>
63+
);
64+
},
65+
};
66+
67+
export const WithSuggestions: Story = {
68+
parameters: {
69+
layout: "fullscreen",
70+
},
71+
decorators: Default.decorators,
72+
render: () => (
73+
<CopilotKitProvider>
74+
<CopilotChatConfigurationProvider threadId="storybook-thread">
75+
<div style={{ height: "100%" }}>
76+
<CopilotChatView
77+
messages={storyMessages}
78+
suggestions={suggestionSamples}
79+
onSelectSuggestion={(suggestion) =>
80+
alert(`Selected suggestion: ${suggestion.title}`)
81+
}
82+
inputProps={{
83+
onSubmitMessage: (value) => {
84+
alert(`Message submitted: ${value}`);
85+
},
86+
}}
87+
messageView={{
88+
assistantMessage: {
89+
onThumbsUp: () => alert("thumbsUp"),
90+
onThumbsDown: () => alert("thumbsDown"),
91+
},
92+
}}
93+
/>
94+
</div>
95+
</CopilotChatConfigurationProvider>
96+
</CopilotKitProvider>
97+
),
98+
};
99+
100+
const suggestionSamples: Suggestion[] = [
101+
{
102+
title: "Summarize conversation",
103+
message: "Summarize our latest messages",
104+
isLoading: false,
105+
},
106+
{
107+
title: "Draft reply",
108+
message: "Draft a detailed response",
109+
isLoading: false,
110+
},
111+
{
112+
title: "List next steps",
113+
message: "List action items from this chat",
114+
isLoading: true,
115+
},
116+
];
117+
118+
const storyMessages = [
119+
{
120+
id: "user-1",
121+
content: "Hello! Can you help me understand how React hooks work?",
122+
timestamp: new Date(),
123+
role: "user" as const,
124+
},
125+
{
126+
id: "assistant-1",
127+
content: `React hooks are functions that let you use state and other React features in functional components. Here are the most common ones:
47128
48129
- **useState** - Manages local state
49130
- **useEffect** - Handles side effects
@@ -52,18 +133,18 @@ export const Default: Story = {
52133
- **useMemo** - Memoizes values
53134
54135
Would you like me to explain any of these in detail?`,
55-
timestamp: new Date(),
56-
role: "assistant" as const,
57-
},
58-
{
59-
id: "user-2",
60-
content: "Yes, could you explain useState with a simple example?",
61-
timestamp: new Date(),
62-
role: "user" as const,
63-
},
64-
{
65-
id: "assistant-2",
66-
content: `Absolutely! Here's a simple useState example:
136+
timestamp: new Date(),
137+
role: "assistant" as const,
138+
},
139+
{
140+
id: "user-2",
141+
content: "Yes, could you explain useState with a simple example?",
142+
timestamp: new Date(),
143+
role: "user" as const,
144+
},
145+
{
146+
id: "assistant-2",
147+
content: `Absolutely! Here's a simple useState example:
67148
68149
\`\`\`jsx
69150
import React, { useState } from 'react';
@@ -87,31 +168,7 @@ In this example:
87168
- It returns an array: \`[currentValue, setterFunction]\`
88169
- \`count\` is the current state value
89170
- \`setCount\` is the function to update the state`,
90-
timestamp: new Date(),
91-
role: "assistant" as const,
92-
},
93-
];
94-
95-
return (
96-
<CopilotKitProvider>
97-
<CopilotChatConfigurationProvider threadId="storybook-thread">
98-
<div style={{ height: "100%" }}>
99-
<CopilotChatView
100-
messages={messages}
101-
messageView={{
102-
assistantMessage: {
103-
onThumbsUp: () => {
104-
alert("thumbsUp");
105-
},
106-
onThumbsDown: () => {
107-
alert("thumbsDown");
108-
},
109-
},
110-
}}
111-
/>
112-
</div>
113-
</CopilotChatConfigurationProvider>
114-
</CopilotKitProvider>
115-
);
171+
timestamp: new Date(),
172+
role: "assistant" as const,
116173
},
117-
};
174+
];

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.38-alpha.2",
35-
"@ag-ui/core": "0.0.38-alpha.2",
34+
"@ag-ui/client": "0.0.40-alpha.3",
35+
"@ag-ui/core": "0.0.40-alpha.3",
3636
"@copilotkitnext/core": "workspace:*",
3737
"@copilotkitnext/shared": "workspace:*",
3838
"clsx": "^2.1.1",

packages/core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
"vitest": "^3.2.4"
3737
},
3838
"dependencies": {
39-
"@ag-ui/client": "0.0.38-alpha.2",
39+
"@ag-ui/client": "0.0.40-alpha.3",
4040
"@copilotkitnext/shared": "workspace:*",
4141
"rxjs": "7.8.1",
4242
"zod": "^3.25.75",

0 commit comments

Comments
 (0)