forked from CopilotKit/CopilotKit
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfiles.json
More file actions
140 lines (140 loc) · 58.8 KB
/
Copy pathfiles.json
File metadata and controls
140 lines (140 loc) · 58.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
{
"agentic_chat": {
"files": [
{
"name": "page.tsx",
"content": "\"use client\";\nimport React, { useState } from \"react\";\nimport \"@copilotkit/react-ui/styles.css\";\nimport \"./style.css\";\nimport {\n CopilotKit,\n useCopilotAction,\n useCopilotChat,\n} from \"@copilotkit/react-core\";\nimport { CopilotChat } from \"@copilotkit/react-ui\";\n\nconst AgenticChat: React.FC = () => {\n return (\n <CopilotKit\n runtimeUrl=\"/api/copilotkit\"\n showDevConsole={false}\n // agent lock to the relevant agent\n agent=\"agenticChatAgent\"\n >\n <Chat />\n </CopilotKit>\n );\n};\n\nconst Chat = () => {\n const [background, setBackground] = useState<string>(\n \"--copilot-kit-background-color\"\n );\n\n useCopilotAction({\n name: \"change_background\",\n description:\n \"Change the background color of the chat. Can be anything that the CSS background attribute accepts. Regular colors, linear of radial gradients etc.\",\n parameters: [\n {\n name: \"background\",\n type: \"string\",\n description: \"The background. Prefer gradients.\",\n },\n ],\n handler: ({ background }) => {\n console.log(\"Changing background to\", background);\n setBackground(background);\n },\n followUp: false,\n });\n\n return (\n <div\n className=\"flex justify-center items-center h-full w-full\"\n style={{ background }}\n >\n <div className=\"w-8/10 h-8/10 rounded-lg\">\n <CopilotChat\n className=\"h-full rounded-2xl\"\n labels={{ initial: \"Hi, I'm an agent. Want to chat?\" }}\n />\n </div>\n </div>\n );\n};\n\nexport default AgenticChat;\n",
"path": "page.tsx",
"language": "typescript"
},
{
"name": "style.css",
"content": ".copilotKitInput {\n border-bottom-left-radius: 0.75rem;\n border-bottom-right-radius: 0.75rem;\n border-top-left-radius: 0.75rem;\n border-top-right-radius: 0.75rem;\n border: 1px solid var(--copilot-kit-separator-color) !important;\n}\n \n.copilotKitChat {\n background-color: #fff !important;\n}\n ",
"path": "style.css",
"language": "css"
},
{
"name": "README.mdx",
"content": "# 🤖 Agentic Chat with Frontend Tools\n\n## What This Demo Shows\n\nThis demo showcases CopilotKit's **agentic chat** capabilities with **frontend tool integration**:\n1. **Natural Conversation**: Chat with your Copilot in a familiar chat interface\n2. **Frontend Tool Execution**: The Copilot can directly interacts with your UI by calling frontend functions\n3. **Seamless Integration**: Tools defined in the frontend and automatically discovered and made available to the agent\n\n## How to Interact\n\nTry asking your Copilot to:\n- \"Can you change the background color to something more vibrant?\"\n- \"Make the background a blue to purple gradient\"\n- \"Set the background to a sunset-themed gradient\"\n- \"Change it back to a simple light color\"\n\nYou can also chat about other topics - the agent will respond conversationally while having the ability to use your UI tools when appropriate.\n\n## ✨ Frontend Tool Integration in Action\n\n**What's happening technically:**\n- The React component defines a frontend function using `useCopilotAction`\n- CopilotKit automatically exposes this function to the agent\n- When you make a request, the agent determines whether to use the tool\n- The agent calls the function with the appropriate parameters\n- The UI immediately updates in response\n\n**What you'll see in this demo:**\n- The Copilot understands requests to change the background\n- It generates CSS values for colors and gradients\n- When it calls the tool, the background changes instantly\n- The agent provides a conversational response about the changes it made\n\nThis technique of exposing frontend functions to your Copilot can be extended to any UI manipulation you want to enable, from theme changes to data filtering, navigation, or complex UI state management! ",
"path": "README.mdx",
"language": "markdown"
}
],
"readmeContent": "# 🤖 Agentic Chat with Frontend Tools\n\n## What This Demo Shows\n\nThis demo showcases CopilotKit's **agentic chat** capabilities with **frontend tool integration**:\n1. **Natural Conversation**: Chat with your Copilot in a familiar chat interface\n2. **Frontend Tool Execution**: The Copilot can directly interacts with your UI by calling frontend functions\n3. **Seamless Integration**: Tools defined in the frontend and automatically discovered and made available to the agent\n\n## How to Interact\n\nTry asking your Copilot to:\n- \"Can you change the background color to something more vibrant?\"\n- \"Make the background a blue to purple gradient\"\n- \"Set the background to a sunset-themed gradient\"\n- \"Change it back to a simple light color\"\n\nYou can also chat about other topics - the agent will respond conversationally while having the ability to use your UI tools when appropriate.\n\n## ✨ Frontend Tool Integration in Action\n\n**What's happening technically:**\n- The React component defines a frontend function using `useCopilotAction`\n- CopilotKit automatically exposes this function to the agent\n- When you make a request, the agent determines whether to use the tool\n- The agent calls the function with the appropriate parameters\n- The UI immediately updates in response\n\n**What you'll see in this demo:**\n- The Copilot understands requests to change the background\n- It generates CSS values for colors and gradients\n- When it calls the tool, the background changes instantly\n- The agent provides a conversational response about the changes it made\n\nThis technique of exposing frontend functions to your Copilot can be extended to any UI manipulation you want to enable, from theme changes to data filtering, navigation, or complex UI state management! "
},
"agentic_generative_ui": {
"files": [
{
"name": "page.tsx",
"content": "\"use client\";\nimport React from \"react\";\nimport \"@copilotkit/react-ui/styles.css\";\nimport \"./style.css\";\nimport { CopilotKit, useCoAgentStateRender } from \"@copilotkit/react-core\";\nimport { CopilotChat } from \"@copilotkit/react-ui\";\n\nconst AgenticGenerativeUI: React.FC = () => {\n return (\n <CopilotKit\n runtimeUrl=\"/api/copilotkit\"\n showDevConsole={false}\n // agent lock to the relevant agent\n agent=\"agentiveGenerativeUIAgent\"\n >\n <Chat />\n </CopilotKit>\n );\n};\n\ninterface AgentState {\n steps: {\n description: string;\n status: \"pending\" | \"completed\";\n }[];\n}\n\nconst Chat = () => {\n useCoAgentStateRender<AgentState>({\n name: \"agentiveGenerativeUIAgent\",\n render: ({ state }) => {\n if (!state.steps || state.steps.length === 0) {\n return null;\n }\n\n return (\n <div className=\"flex\">\n <div className=\"bg-gray-100 rounded-lg w-[500px] p-4 text-black space-y-2\">\n {state.steps.map((step, index) => {\n if (step.status === \"completed\") {\n return (\n <div key={index} className=\"text-sm\">\n ✓ {step.description}\n </div>\n );\n } else if (\n step.status === \"pending\" &&\n index === state.steps.findIndex((s) => s.status === \"pending\")\n ) {\n return (\n <div\n key={index}\n className=\"text-3xl font-bold text-slate-700\"\n >\n <Spinner />\n {step.description}\n </div>\n );\n } else {\n return (\n <div key={index} className=\"text-sm\">\n <Spinner />\n {step.description}\n </div>\n );\n }\n })}\n </div>\n </div>\n );\n },\n });\n\n return (\n <div className=\"flex justify-center items-center h-full w-full\">\n <div className=\"w-8/10 h-8/10 rounded-lg\">\n <CopilotChat\n className=\"h-full rounded-2xl\"\n labels={{\n initial:\n \"Hi, I'm an agent! I can help you with anything you need and will show you progress as I work. What can I do for you?\",\n }}\n />\n </div>\n </div>\n );\n};\n\nfunction Spinner() {\n return (\n <svg\n className=\"mr-2 size-3 animate-spin text-slate-500\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n ></circle>\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n );\n}\n\nexport default AgenticGenerativeUI;\n",
"path": "page.tsx",
"language": "typescript"
},
{
"name": "style.css",
"content": ".copilotKitInput {\n border-bottom-left-radius: 0.75rem;\n border-bottom-right-radius: 0.75rem;\n border-top-left-radius: 0.75rem;\n border-top-right-radius: 0.75rem;\n border: 1px solid var(--copilot-kit-separator-color) !important;\n}\n\n.copilotKitChat {\n background-color: #fff !important;\n}\n",
"path": "style.css",
"language": "css"
},
{
"name": "README.mdx",
"content": "# 🚀 Agentic Generative UI Task Executor\n\n## What This Demo Shows\n\nThis demo showcases CopilotKit's **agentic generative UI** capabilities:\n1. **Real-time Status Updates**: The Copilot provides live feedback as it works through complex tasks\n2. **Long-running Task Execution**: See how agents can handle extended processes with continuous feedback\n3. **Dynamic UI Generation**: The interface updates in real-time to reflect the agent's progress\n\n## How to Interact\n\nSimply ask your Copilot to perform any moderately complex task:\n- \"Make me a sandwich\"\n- \"Plan a vacation to Japan\"\n- \"Create a weekly workout routine\"\n\nThe Copilot will break down the task into steps and begin \"executing\" them, providing real-time status updates as it progresses.\n\n## ✨ Agentic Generative UI in Action\n\n**What's happening technically:**\n- The agent analyzes your request and creates a detailed execution plan\n- Each step is processed sequentially with realistic timing\n- Status updates are streamed to the frontend using CopilotKit's streaming capabilities\n- The UI dynamically renders these updates without page refreshes\n- The entire flow is managed by the agent, requiring no manual intervention\n\n**What you'll see in this demo:**\n- The Copilot breaks your task into logical steps\n- A status indicator shows the current progress\n- Each step is highlighted as it's being executed\n- Detailed status messages explain what's happening at each moment\n- Upon completion, you receive a summary of the task execution\n\nThis pattern of providing real-time progress for long-running tasks is perfect for scenarios where users benefit from transparency into complex processes - from data analysis to content creation, system configurations, or multi-stage workflows! ",
"path": "README.mdx",
"language": "markdown"
}
],
"readmeContent": "# 🚀 Agentic Generative UI Task Executor\n\n## What This Demo Shows\n\nThis demo showcases CopilotKit's **agentic generative UI** capabilities:\n1. **Real-time Status Updates**: The Copilot provides live feedback as it works through complex tasks\n2. **Long-running Task Execution**: See how agents can handle extended processes with continuous feedback\n3. **Dynamic UI Generation**: The interface updates in real-time to reflect the agent's progress\n\n## How to Interact\n\nSimply ask your Copilot to perform any moderately complex task:\n- \"Make me a sandwich\"\n- \"Plan a vacation to Japan\"\n- \"Create a weekly workout routine\"\n\nThe Copilot will break down the task into steps and begin \"executing\" them, providing real-time status updates as it progresses.\n\n## ✨ Agentic Generative UI in Action\n\n**What's happening technically:**\n- The agent analyzes your request and creates a detailed execution plan\n- Each step is processed sequentially with realistic timing\n- Status updates are streamed to the frontend using CopilotKit's streaming capabilities\n- The UI dynamically renders these updates without page refreshes\n- The entire flow is managed by the agent, requiring no manual intervention\n\n**What you'll see in this demo:**\n- The Copilot breaks your task into logical steps\n- A status indicator shows the current progress\n- Each step is highlighted as it's being executed\n- Detailed status messages explain what's happening at each moment\n- Upon completion, you receive a summary of the task execution\n\nThis pattern of providing real-time progress for long-running tasks is perfect for scenarios where users benefit from transparency into complex processes - from data analysis to content creation, system configurations, or multi-stage workflows! "
},
"human_in_the_loop": {
"files": [
{
"name": "page.tsx",
"content": "\"use client\";\nimport React, { useState, useEffect } from \"react\";\nimport \"@copilotkit/react-ui/styles.css\";\nimport \"./style.css\";\nimport { CopilotKit, useCopilotAction } from \"@copilotkit/react-core\";\nimport { CopilotChat } from \"@copilotkit/react-ui\";\n\nconst HumanInTheLoop: React.FC = () => {\n return (\n <CopilotKit\n runtimeUrl=\"/api/copilotkit\"\n showDevConsole={false}\n // agent lock to the relevant agent\n agent=\"humanInTheLoopAgent\"\n >\n <Chat />\n </CopilotKit>\n );\n};\n\nconst Chat = () => {\n useCopilotAction({\n name: \"generate_task_steps\",\n parameters: [\n {\n name: \"steps\",\n type: \"object[]\",\n attributes: [\n {\n name: \"description\",\n type: \"string\",\n },\n {\n name: \"status\",\n type: \"string\",\n enum: [\"enabled\", \"disabled\", \"executing\"],\n },\n ],\n },\n ],\n renderAndWaitForResponse: ({ args, respond, status }) => {\n return <StepsFeedback args={args} respond={respond} status={status} />;\n },\n });\n\n return (\n <div className=\"flex justify-center items-center h-full w-full\">\n <div className=\"w-8/10 h-8/10 rounded-lg\">\n <CopilotChat\n className=\"h-full rounded-2xl\"\n labels={{\n initial:\n \"Hi, I'm an agent specialized in helping you with your tasks. How can I help you?\",\n }}\n />\n </div>\n </div>\n );\n};\n\nconst StepsFeedback = ({\n args,\n respond,\n status,\n}: {\n args: any;\n respond: any;\n status: any;\n}) => {\n const [localSteps, setLocalSteps] = useState<\n {\n description: string;\n status: \"disabled\" | \"enabled\" | \"executing\";\n }[]\n >([]);\n\n useEffect(() => {\n if (status === \"executing\" && localSteps.length === 0) {\n setLocalSteps(args.steps);\n }\n }, [status, args.steps, localSteps]);\n\n if (args.steps === undefined || args.steps.length === 0) {\n return <></>;\n }\n\n const steps = localSteps.length > 0 ? localSteps : args.steps;\n\n const handleCheckboxChange = (index: number) => {\n setLocalSteps((prevSteps) =>\n prevSteps.map((step, i) =>\n i === index\n ? {\n ...step,\n status: step.status === \"enabled\" ? \"disabled\" : \"enabled\",\n }\n : step\n )\n );\n };\n\n return (\n <div className=\"flex flex-col gap-4 w-[500px] bg-gray-100 rounded-lg p-8 mb-4\">\n <div className=\" text-black space-y-2\">\n <h2 className=\"text-lg font-bold mb-4\">Select Steps</h2>\n {steps.map((step: any, index: any) => (\n <div key={index} className=\"text-sm flex items-center\">\n <input\n type=\"checkbox\"\n checked={step.status === \"enabled\"}\n onChange={() => handleCheckboxChange(index)}\n className=\"mr-2\"\n />\n <span\n className={\n step.status !== \"enabled\" && status != \"inProgress\"\n ? \"line-through\"\n : \"\"\n }\n >\n {step.description}\n </span>\n </div>\n ))}\n {status === \"executing\" && (\n <button\n className=\"mt-4 bg-gradient-to-r from-purple-400 to-purple-600 text-white py-2 px-4 rounded cursor-pointer w-48 font-bold\"\n onClick={() => {\n const selectedSteps = localSteps\n .filter((step) => step.status === \"enabled\")\n .map((step) => step.description);\n respond(\n \"The user selected the following steps: \" +\n selectedSteps.join(\", \")\n );\n }}\n >\n ✨ Perform Steps\n </button>\n )}\n </div>\n </div>\n );\n};\n\nfunction Spinner() {\n return (\n <svg\n className=\"mr-2 size-3 animate-spin text-slate-500\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n ></circle>\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n );\n}\nexport default HumanInTheLoop;\n",
"path": "page.tsx",
"language": "typescript"
},
{
"name": "style.css",
"content": ".copilotKitInput {\n border-bottom-left-radius: 0.75rem;\n border-bottom-right-radius: 0.75rem;\n border-top-left-radius: 0.75rem;\n border-top-right-radius: 0.75rem;\n border: 1px solid var(--copilot-kit-separator-color) !important;\n}\n\n.copilotKitChat {\n background-color: #fff !important;\n}\n",
"path": "style.css",
"language": "css"
},
{
"name": "README.mdx",
"content": "# 🤝 Human-in-the-Loop Task Planner\n\n## What This Demo Shows\n\nThis demo showcases CopilotKit's **human-in-the-loop** capabilities:\n1. **Collaborative Planning**: The Copilot generates task steps and lets you decide which ones to perform\n2. **Interactive Decision Making**: Select or deselect steps to customize the execution plan\n3. **Adaptive Responses**: The Copilot adapts its execution based on your choices, even handling missing steps\n\n## How to Interact\n\nTry these steps to experience the demo:\n1. Ask your Copilot to help with a task, such as:\n - \"Make me a sandwich\"\n - \"Plan a weekend trip\"\n - \"Organize a birthday party\"\n - \"Start a garden\"\n\n2. Review the suggested steps provided by your Copilot\n\n3. Select or deselect steps using the checkboxes to customize the plan\n - Try removing essential steps to see how the Copilot adapts!\n\n4. Click \"Execute Plan\" to see the outcome based on your selections\n\n## ✨ Human-in-the-Loop Magic in Action\n\n**What's happening technically:**\n- The agent analyzes your request and breaks it down into logical steps\n- These steps are presented to you through a dynamic UI component\n- Your selections are captured as user input\n- The agent considers your choices when executing the plan\n- The agent adapts to missing steps with creative problem-solving\n\n**What you'll see in this demo:**\n- The Copilot provides a detailed, step-by-step plan for your task\n- You have complete control over which steps to include\n- If you remove essential steps, the Copilot provides entertaining and creative workarounds\n- The final execution reflects your choices, showing how human input shapes the outcome\n- Each response is tailored to your specific selections\n\nThis human-in-the-loop pattern creates a powerful collaborative experience where both human judgment and AI capabilities work together to achieve better results than either could alone! ",
"path": "README.mdx",
"language": "markdown"
}
],
"readmeContent": "# 🤝 Human-in-the-Loop Task Planner\n\n## What This Demo Shows\n\nThis demo showcases CopilotKit's **human-in-the-loop** capabilities:\n1. **Collaborative Planning**: The Copilot generates task steps and lets you decide which ones to perform\n2. **Interactive Decision Making**: Select or deselect steps to customize the execution plan\n3. **Adaptive Responses**: The Copilot adapts its execution based on your choices, even handling missing steps\n\n## How to Interact\n\nTry these steps to experience the demo:\n1. Ask your Copilot to help with a task, such as:\n - \"Make me a sandwich\"\n - \"Plan a weekend trip\"\n - \"Organize a birthday party\"\n - \"Start a garden\"\n\n2. Review the suggested steps provided by your Copilot\n\n3. Select or deselect steps using the checkboxes to customize the plan\n - Try removing essential steps to see how the Copilot adapts!\n\n4. Click \"Execute Plan\" to see the outcome based on your selections\n\n## ✨ Human-in-the-Loop Magic in Action\n\n**What's happening technically:**\n- The agent analyzes your request and breaks it down into logical steps\n- These steps are presented to you through a dynamic UI component\n- Your selections are captured as user input\n- The agent considers your choices when executing the plan\n- The agent adapts to missing steps with creative problem-solving\n\n**What you'll see in this demo:**\n- The Copilot provides a detailed, step-by-step plan for your task\n- You have complete control over which steps to include\n- If you remove essential steps, the Copilot provides entertaining and creative workarounds\n- The final execution reflects your choices, showing how human input shapes the outcome\n- Each response is tailored to your specific selections\n\nThis human-in-the-loop pattern creates a powerful collaborative experience where both human judgment and AI capabilities work together to achieve better results than either could alone! "
},
"shared_state": {
"files": [
{
"name": "page.tsx",
"content": "\"use client\";\nimport { CopilotKit, useCoAgent, useCopilotChat } from \"@copilotkit/react-core\";\nimport { CopilotSidebar } from \"@copilotkit/react-ui\";\nimport { useState, useEffect, useRef } from \"react\";\nimport { Role, TextMessage } from \"@copilotkit/runtime-client-gql\";\nimport \"@copilotkit/react-ui/styles.css\";\nimport \"./style.css\";\n\nenum SkillLevel {\n BEGINNER = \"Beginner\",\n INTERMEDIATE = \"Intermediate\",\n ADVANCED = \"Advanced\",\n}\n\nenum SpecialPreferences {\n HighProtein = \"High Protein\",\n LowCarb = \"Low Carb\",\n Spicy = \"Spicy\",\n BudgetFriendly = \"Budget-Friendly\",\n OnePotMeal = \"One-Pot Meal\",\n Vegetarian = \"Vegetarian\",\n Vegan = \"Vegan\",\n}\n\nenum CookingTime {\n FiveMin = \"5 min\",\n FifteenMin = \"15 min\",\n ThirtyMin = \"30 min\",\n FortyFiveMin = \"45 min\",\n SixtyPlusMin = \"60+ min\",\n}\n\nconst cookingTimeValues = [\n { label: CookingTime.FiveMin, value: 0 },\n { label: CookingTime.FifteenMin, value: 1 },\n { label: CookingTime.ThirtyMin, value: 2 },\n { label: CookingTime.FortyFiveMin, value: 3 },\n { label: CookingTime.SixtyPlusMin, value: 4 },\n];\n\nexport default function SharedState() {\n return (\n <CopilotKit\n runtimeUrl=\"/api/copilotkit\"\n showDevConsole={false}\n // agent lock to the relevant agent\n agent=\"sharedStateAgent\"\n >\n <div\n className=\"min-h-screen w-full flex items-center justify-center\"\n style={\n {\n backgroundImage: \"url('/shared_state_background.png')\",\n backgroundSize: \"cover\",\n backgroundPosition: \"center\",\n backgroundRepeat: \"no-repeat\",\n } as React.CSSProperties\n }\n >\n <Recipe />\n <CopilotSidebar\n defaultOpen={true}\n labels={{\n title: \"AI Recipe Assistant\",\n initial: \"Hi 👋 How can I help with your recipe?\",\n }}\n clickOutsideToClose={false}\n />\n </div>\n </CopilotKit>\n );\n}\n\ninterface Recipe {\n skill_level: SkillLevel;\n special_preferences: SpecialPreferences[];\n cooking_time: CookingTime;\n ingredients: string;\n instructions: string;\n}\n\ninterface RecipeAgentState {\n recipe: Recipe;\n}\n\nconst INITIAL_STATE: RecipeAgentState = {\n recipe: {\n skill_level: SkillLevel.BEGINNER,\n special_preferences: [],\n cooking_time: CookingTime.FifteenMin,\n ingredients: \"\",\n instructions: \"\",\n },\n};\n\nfunction Recipe() {\n const { state: agentState, setState: setAgentState } =\n useCoAgent<RecipeAgentState>({\n name: \"sharedStateAgent\",\n initialState: INITIAL_STATE,\n });\n\n const [recipe, setRecipe] = useState(INITIAL_STATE.recipe);\n const { appendMessage, isLoading } = useCopilotChat();\n\n const updateRecipe = (partialRecipe: Partial<Recipe>) => {\n setAgentState({\n ...agentState,\n recipe: {\n ...recipe,\n ...partialRecipe,\n },\n });\n setRecipe({\n ...recipe,\n ...partialRecipe,\n });\n };\n\n const newRecipeState = { ...recipe };\n const newChangedKeys = [];\n const changedKeysRef = useRef<string[]>([]);\n\n for (const key in recipe) {\n if (\n (agentState.recipe as any)[key] !== undefined &&\n (agentState.recipe as any)[key] !== null\n ) {\n let agentValue = (agentState.recipe as any)[key];\n const recipeValue = (recipe as any)[key];\n\n if (Array.isArray(agentValue) && Array.isArray(recipeValue)) {\n agentValue.sort();\n }\n\n // Check if agentValue is a string and replace \\n with actual newlines\n if (typeof agentValue === \"string\") {\n agentValue = agentValue.replace(/\\\\n/g, \"\\n\");\n }\n\n if (JSON.stringify(agentValue) !== JSON.stringify(recipeValue)) {\n (newRecipeState as any)[key] = agentValue;\n newChangedKeys.push(key);\n }\n }\n }\n\n if (newChangedKeys.length > 0) {\n changedKeysRef.current = newChangedKeys;\n } else if (!isLoading) {\n changedKeysRef.current = [];\n }\n\n useEffect(() => {\n setRecipe(newRecipeState);\n }, [JSON.stringify(newRecipeState)]);\n\n const handleSkillLevelChange = (\n event: React.ChangeEvent<HTMLSelectElement>\n ) => {\n updateRecipe({\n skill_level: event.target.value as SkillLevel,\n });\n };\n\n const handlePreferenceChange = (\n preference: SpecialPreferences,\n checked: boolean\n ) => {\n if (checked) {\n updateRecipe({\n special_preferences: [\n ...agentState.recipe.special_preferences,\n preference,\n ],\n });\n } else {\n updateRecipe({\n special_preferences: agentState.recipe.special_preferences.filter(\n (p) => p !== preference\n ),\n });\n }\n };\n\n const handleCookingTimeChange = (\n event: React.ChangeEvent<HTMLInputElement>\n ) => {\n updateRecipe({\n cooking_time: cookingTimeValues[Number(event.target.value)].label,\n });\n };\n\n const handleIngredientsChange = (\n event: React.ChangeEvent<HTMLTextAreaElement>\n ) => {\n updateRecipe({\n ingredients: event.target.value,\n });\n };\n\n const handleInstructionsChange = (\n event: React.ChangeEvent<HTMLTextAreaElement>\n ) => {\n updateRecipe({\n instructions: event.target.value,\n });\n };\n\n return (\n <form\n className=\"w-full max-w-lg p-6 rounded shadow-md text-black\"\n style={{\n backgroundColor: \"rgba(255, 255, 255, 0.9)\", // Semi-transparent white\n backdropFilter: \"blur(10px)\", // Apply blur for frosted effect\n WebkitBackdropFilter: \"blur(10px)\", // For Safari support\n boxShadow: \"0 4px 30px rgba(0, 0, 0, 0.1)\", // Subtle shadow for depth\n }}\n >\n <div className=\"mb-4 relative\">\n {changedKeysRef.current.includes(\"skill_level\") && <Ping />}\n <label\n className=\"block text-gray-700 text-sm font-bold mb-2\"\n htmlFor=\"skillLevel\"\n >\n Skill Level\n </label>\n <select\n className=\"shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline\"\n id=\"skillLevel\"\n value={recipe.skill_level}\n onChange={handleSkillLevelChange}\n >\n {Object.values(SkillLevel).map((level) => (\n <option key={level} value={level}>\n {level}\n </option>\n ))}\n </select>\n </div>\n <div className=\"mb-4 relative\">\n {changedKeysRef.current.includes(\"cooking_time\") && <Ping />}\n <label\n className=\"block text-gray-700 text-sm font-bold mb-2\"\n htmlFor=\"cookingTime\"\n >\n Cooking Time: {recipe.cooking_time}\n </label>\n <input\n type=\"range\"\n id=\"cookingTime\"\n min=\"0\"\n max={cookingTimeValues.length - 1}\n value={cookingTimeValues.findIndex(\n (value) => value.label === recipe.cooking_time\n )}\n onChange={handleCookingTimeChange}\n className=\"w-full h-2 bg-gray-200 shadow rounded-lg appearance-none cursor-pointer focus:outline-none focus:ring-2 focus:ring-blue-500\"\n />\n </div>\n <div className=\"mb-4 relative\">\n {changedKeysRef.current.includes(\"special_preferences\") && <Ping />}\n <label className=\"block text-gray-700 text-sm font-bold mb-4\">\n Special Preferences:\n </label>\n <div className=\"flex flex-wrap mt-2\">\n {Object.values(SpecialPreferences).map((preference) => (\n <label\n key={preference}\n className=\"flex items-center mr-4 mb-2 whitespace-nowrap uppercase\"\n style={{ fontSize: \"10px\", fontWeight: \"bold\" }}\n >\n <input\n type=\"checkbox\"\n checked={recipe.special_preferences.includes(preference)}\n onChange={(e) =>\n handlePreferenceChange(preference, e.target.checked)\n }\n className=\"mr-1\"\n />\n {preference}\n </label>\n ))}\n </div>\n </div>\n\n <div className=\"mb-4 relative\">\n {changedKeysRef.current.includes(\"ingredients\") && <Ping />}\n <label\n className=\"block text-gray-700 text-sm font-bold mb-2\"\n htmlFor=\"ingredients\"\n >\n Ingredients:\n </label>\n <textarea\n id=\"ingredients\"\n value={recipe.ingredients}\n onChange={handleIngredientsChange}\n className=\"shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline\"\n rows={4}\n placeholder=\"Enter ingredients here...\"\n />\n </div>\n\n <div className=\"mb-4 relative\">\n {changedKeysRef.current.includes(\"instructions\") && <Ping />}\n <label\n className=\"block text-gray-700 text-sm font-bold mb-2\"\n htmlFor=\"instructions\"\n >\n Instructions:\n </label>\n <textarea\n id=\"instructions\"\n value={recipe.instructions}\n onChange={handleInstructionsChange}\n className=\"shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline\"\n rows={6}\n placeholder=\"Enter instructions here...\"\n />\n </div>\n\n <div className=\"flex items-center justify-end mt-2\">\n <button\n className={`${\n isLoading\n ? \"bg-gray-400 cursor-not-allowed\"\n : \"bg-black hover:bg-gray-800\"\n } text-white font-base py-2 px-4 rounded focus:outline-none focus:shadow-outline`}\n type=\"button\"\n onClick={() => {\n if (!isLoading) {\n appendMessage(\n new TextMessage({\n content: \"Improve the recipe\",\n role: Role.User,\n })\n );\n }\n }}\n disabled={isLoading}\n >\n {isLoading ? \"Please Wait...\" : \"Improve with AI\"}\n </button>\n </div>\n </form>\n );\n}\n\nfunction Ping() {\n return (\n <span className=\"absolute flex size-3 top-0 right-0\">\n <span className=\"absolute inline-flex h-full w-full animate-ping rounded-full bg-sky-400 opacity-75\"></span>\n <span className=\"relative inline-flex size-3 rounded-full bg-sky-500\"></span>\n </span>\n );\n}\n",
"path": "page.tsx",
"language": "typescript"
},
{
"name": "style.css",
"content": ".copilotKitWindow {\n box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);\n}\n",
"path": "style.css",
"language": "css"
},
{
"name": "README.mdx",
"content": "# 🍳 Shared State Recipe Creator\n\n## What This Demo Shows\n\nThis demo showcases CopilotKit's **shared state** functionality - a powerful feature that enables bidirectional data flow between:\n1. **Frontend → Agent**: UI controls update the agent's context in real-time\n2. **Agent → Frontend**: The Copilot's recipe creations instantly update the UI components\n\nIt's like having a cooking buddy who not only listens to what you want but also updates your recipe card as you chat - no refresh needed! ✨\n\n## How to Interact\n\nMix and match any of these parameters (or none at all - it's up to you!):\n- **Skill Level**: Beginner to expert 👨🍳\n- **Cooking Time**: Quick meals or slow cooking ⏱️\n- **Special Preferences**: Dietary needs, flavor profiles, health goals 🥗\n- **Ingredients**: Items you want to include 🧅🥩🍄\n- **Instructions**: Any specific steps\n\nThen chat with your Copilot chef with prompts like:\n- \"I'm a beginner cook. Can you make me a quick dinner?\"\n- \"I need something spicy with chicken that takes under 30 minutes!\"\n\n## ✨ Shared State Magic in Action\n\n**What's happening technically:**\n- The UI and Copilot agent share the same state object (**Agent State = UI State**)\n- Changes from either side automatically update the other\n- Neither side needs to manually request updates from the other\n\n**What you'll see in this demo:**\n- Set cooking time to 20 minutes in the UI and watch the Copilot immediately respect your time constraint\n- Add ingredients through the UI and see them appear in your recipe\n- When the Copilot suggests new ingredients, watch them automatically appear in the UI ingredients list\n- Change your skill level and see how the Copilot adapts its instructions in real-time\n\nThis synchronized state creates a seamless experience where the agent always has your current preferences, and any updates to the recipe are instantly reflected in both places.\n\nThis shared state pattern can be applied to any application where you want your UI and Copilot to work together in perfect harmony! ",
"path": "README.mdx",
"language": "markdown"
}
],
"readmeContent": "# 🍳 Shared State Recipe Creator\n\n## What This Demo Shows\n\nThis demo showcases CopilotKit's **shared state** functionality - a powerful feature that enables bidirectional data flow between:\n1. **Frontend → Agent**: UI controls update the agent's context in real-time\n2. **Agent → Frontend**: The Copilot's recipe creations instantly update the UI components\n\nIt's like having a cooking buddy who not only listens to what you want but also updates your recipe card as you chat - no refresh needed! ✨\n\n## How to Interact\n\nMix and match any of these parameters (or none at all - it's up to you!):\n- **Skill Level**: Beginner to expert 👨🍳\n- **Cooking Time**: Quick meals or slow cooking ⏱️\n- **Special Preferences**: Dietary needs, flavor profiles, health goals 🥗\n- **Ingredients**: Items you want to include 🧅🥩🍄\n- **Instructions**: Any specific steps\n\nThen chat with your Copilot chef with prompts like:\n- \"I'm a beginner cook. Can you make me a quick dinner?\"\n- \"I need something spicy with chicken that takes under 30 minutes!\"\n\n## ✨ Shared State Magic in Action\n\n**What's happening technically:**\n- The UI and Copilot agent share the same state object (**Agent State = UI State**)\n- Changes from either side automatically update the other\n- Neither side needs to manually request updates from the other\n\n**What you'll see in this demo:**\n- Set cooking time to 20 minutes in the UI and watch the Copilot immediately respect your time constraint\n- Add ingredients through the UI and see them appear in your recipe\n- When the Copilot suggests new ingredients, watch them automatically appear in the UI ingredients list\n- Change your skill level and see how the Copilot adapts its instructions in real-time\n\nThis synchronized state creates a seamless experience where the agent always has your current preferences, and any updates to the recipe are instantly reflected in both places.\n\nThis shared state pattern can be applied to any application where you want your UI and Copilot to work together in perfect harmony! "
},
"predictive_state_updates": {
"files": [
{
"name": "page.tsx",
"content": "\"use client\";\nimport \"@copilotkit/react-ui/styles.css\";\nimport \"./style.css\";\n\nimport MarkdownIt from \"markdown-it\";\n\nimport { diffWords } from \"diff\";\nimport { useEditor, EditorContent } from \"@tiptap/react\";\nimport StarterKit from \"@tiptap/starter-kit\";\nimport { useEffect, useState } from \"react\";\nimport {\n CopilotKit,\n useCoAgent,\n useCopilotAction,\n useCopilotChat,\n} from \"@copilotkit/react-core\";\nimport { CopilotSidebar } from \"@copilotkit/react-ui\";\n\nconst extensions = [StarterKit];\n\nexport default function PredictiveStateUpdates() {\n return (\n <CopilotKit\n runtimeUrl=\"/api/copilotkit\"\n showDevConsole={false}\n // agent lock to the relevant agent\n agent=\"predictiveStateUpdatesAgent\"\n >\n <div\n className=\"min-h-screen w-full\"\n style={\n {\n // \"--copilot-kit-primary-color\": \"#222\",\n // \"--copilot-kit-separator-color\": \"#CCC\",\n } as React.CSSProperties\n }\n >\n <CopilotSidebar\n defaultOpen={true}\n labels={{\n title: \"AI Document Editor\",\n initial: \"Hi 👋 How can I help with your document?\",\n }}\n clickOutsideToClose={false}\n >\n <DocumentEditor />\n </CopilotSidebar>\n </div>\n </CopilotKit>\n );\n}\n\ninterface AgentState {\n document: string;\n}\n\nconst DocumentEditor = () => {\n const editor = useEditor({\n extensions,\n immediatelyRender: false,\n editorProps: {\n attributes: { class: \"min-h-screen p-10\" },\n },\n });\n const [placeholderVisible, setPlaceholderVisible] = useState(false);\n const [currentDocument, setCurrentDocument] = useState(\"\");\n const { isLoading } = useCopilotChat();\n\n const {\n state: agentState,\n setState: setAgentState,\n nodeName,\n } = useCoAgent<AgentState>({\n name: \"predictiveStateUpdatesAgent\",\n initialState: {\n document: \"\",\n },\n });\n\n useEffect(() => {\n if (isLoading) {\n setCurrentDocument(editor?.getText() || \"\");\n }\n editor?.setEditable(!isLoading);\n }, [isLoading]);\n\n useEffect(() => {\n if (nodeName == \"end\") {\n // set the text one final time when loading is done\n if (\n currentDocument.trim().length > 0 &&\n currentDocument !== agentState?.document\n ) {\n const newDocument = agentState?.document || \"\";\n const diff = diffPartialText(currentDocument, newDocument, true);\n const markdown = fromMarkdown(diff);\n editor?.commands.setContent(markdown);\n }\n }\n }, [nodeName]);\n\n useEffect(() => {\n if (isLoading) {\n if (currentDocument.trim().length > 0) {\n const newDocument = agentState?.document || \"\";\n const diff = diffPartialText(currentDocument, newDocument);\n const markdown = fromMarkdown(diff);\n editor?.commands.setContent(markdown);\n } else {\n const markdown = fromMarkdown(agentState?.document || \"\");\n editor?.commands.setContent(markdown);\n }\n }\n }, [agentState?.document]);\n\n const text = editor?.getText() || \"\";\n\n useEffect(() => {\n setPlaceholderVisible(text.length === 0);\n\n if (!isLoading) {\n setCurrentDocument(text);\n setAgentState({\n document: text,\n });\n }\n }, [text]);\n\n useCopilotAction({\n name: \"confirm_changes\",\n renderAndWaitForResponse: ({ args, respond, status }) => (\n <ConfirmChanges\n args={args}\n respond={respond}\n status={status}\n onReject={() => {\n editor?.commands.setContent(fromMarkdown(currentDocument));\n setAgentState({ document: currentDocument });\n }}\n onConfirm={() => {\n editor?.commands.setContent(fromMarkdown(agentState?.document || \"\"));\n setCurrentDocument(agentState?.document || \"\");\n setAgentState({ document: agentState?.document || \"\" });\n }}\n />\n ),\n });\n\n return (\n <div className=\"relative min-h-screen w-full\">\n {placeholderVisible && (\n <div className=\"absolute top-6 left-6 m-4 pointer-events-none text-gray-400\">\n Write whatever you want here in Markdown format...\n </div>\n )}\n <EditorContent editor={editor} />\n </div>\n );\n};\n\ninterface ConfirmChangesProps {\n args: any;\n respond: any;\n status: any;\n onReject: () => void;\n onConfirm: () => void;\n}\n\nfunction ConfirmChanges({\n args,\n respond,\n status,\n onReject,\n onConfirm,\n}: ConfirmChangesProps) {\n const [accepted, setAccepted] = useState<boolean | null>(null);\n return (\n <div className=\"bg-white p-6 rounded shadow-lg border border-gray-200 mt-5 mb-5\">\n <h2 className=\"text-lg font-bold mb-4\">Confirm Changes</h2>\n <p className=\"mb-6\">Do you want to accept the changes?</p>\n {accepted === null && (\n <div className=\"flex justify-end space-x-4\">\n <button\n className={`bg-gray-200 text-black py-2 px-4 rounded disabled:opacity-50 ${\n status === \"executing\" ? \"cursor-pointer\" : \"cursor-default\"\n }`}\n disabled={status !== \"executing\"}\n onClick={() => {\n if (respond) {\n setAccepted(false);\n onReject();\n respond({ accepted: false });\n }\n }}\n >\n Reject\n </button>\n <button\n className={`bg-black text-white py-2 px-4 rounded disabled:opacity-50 ${\n status === \"executing\" ? \"cursor-pointer\" : \"cursor-default\"\n }`}\n disabled={status !== \"executing\"}\n onClick={() => {\n if (respond) {\n setAccepted(true);\n onConfirm();\n respond({ accepted: true });\n }\n }}\n >\n Confirm\n </button>\n </div>\n )}\n {accepted !== null && (\n <div className=\"flex justify-end\">\n <div className=\"mt-4 bg-gray-200 text-black py-2 px-4 rounded inline-block\">\n {accepted ? \"✓ Accepted\" : \"✗ Rejected\"}\n </div>\n </div>\n )}\n </div>\n );\n}\n\nfunction fromMarkdown(text: string) {\n const md = new MarkdownIt({\n typographer: true,\n html: true,\n });\n\n return md.render(text);\n}\n\nfunction diffPartialText(\n oldText: string,\n newText: string,\n isComplete: boolean = false\n) {\n let oldTextToCompare = oldText;\n if (oldText.length > newText.length && !isComplete) {\n // make oldText shorter\n oldTextToCompare = oldText.slice(0, newText.length);\n }\n\n const changes = diffWords(oldTextToCompare, newText);\n\n let result = \"\";\n changes.forEach((part) => {\n if (part.added) {\n result += `<em>${part.value}</em>`;\n } else if (part.removed) {\n result += `<s>${part.value}</s>`;\n } else {\n result += part.value;\n }\n });\n\n if (oldText.length > newText.length && !isComplete) {\n result += oldText.slice(newText.length);\n }\n\n return result;\n}\n\nfunction isAlpha(text: string) {\n return /[a-zA-Z\\u00C0-\\u017F]/.test(text.trim());\n}\n",
"path": "page.tsx",
"language": "typescript"
},
{
"name": "style.css",
"content": "/* Basic editor styles */\n.tiptap-container {\n height: 100vh; /* Full viewport height */\n width: 100vw; /* Full viewport width */\n display: flex;\n flex-direction: column;\n}\n\n.tiptap {\n flex: 1; /* Take up remaining space */\n overflow: auto; /* Allow scrolling if content overflows */\n}\n\n.tiptap :first-child {\n margin-top: 0;\n}\n\n/* List styles */\n.tiptap ul,\n.tiptap ol {\n padding: 0 1rem;\n margin: 1.25rem 1rem 1.25rem 0.4rem;\n}\n\n.tiptap ul li p,\n.tiptap ol li p {\n margin-top: 0.25em;\n margin-bottom: 0.25em;\n}\n\n/* Heading styles */\n.tiptap h1,\n.tiptap h2,\n.tiptap h3,\n.tiptap h4,\n.tiptap h5,\n.tiptap h6 {\n line-height: 1.1;\n margin-top: 2.5rem;\n text-wrap: pretty;\n font-weight: bold;\n}\n\n.tiptap h1,\n.tiptap h2,\n.tiptap h3,\n.tiptap h4,\n.tiptap h5,\n.tiptap h6 {\n margin-top: 3.5rem;\n margin-bottom: 1.5rem;\n}\n\n.tiptap p {\n margin-bottom: 1rem;\n}\n\n.tiptap h1 {\n font-size: 1.4rem;\n}\n\n.tiptap h2 {\n font-size: 1.2rem;\n}\n\n.tiptap h3 {\n font-size: 1.1rem;\n}\n\n.tiptap h4,\n.tiptap h5,\n.tiptap h6 {\n font-size: 1rem;\n}\n\n/* Code and preformatted text styles */\n.tiptap code {\n background-color: var(--purple-light);\n border-radius: 0.4rem;\n color: var(--black);\n font-size: 0.85rem;\n padding: 0.25em 0.3em;\n}\n\n.tiptap pre {\n background: var(--black);\n border-radius: 0.5rem;\n color: var(--white);\n font-family: \"JetBrainsMono\", monospace;\n margin: 1.5rem 0;\n padding: 0.75rem 1rem;\n}\n\n.tiptap pre code {\n background: none;\n color: inherit;\n font-size: 0.8rem;\n padding: 0;\n}\n\n.tiptap blockquote {\n border-left: 3px solid var(--gray-3);\n margin: 1.5rem 0;\n padding-left: 1rem;\n}\n\n.tiptap hr {\n border: none;\n border-top: 1px solid var(--gray-2);\n margin: 2rem 0;\n}\n\n.tiptap s {\n background-color: #f9818150;\n padding: 2px;\n font-weight: bold;\n color: rgba(0, 0, 0, 0.7);\n}\n\n.tiptap em {\n background-color: #b2f2bb;\n padding: 2px;\n font-weight: bold;\n font-style: normal;\n}\n\n.copilotKitWindow {\n box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);\n}\n\n",
"path": "style.css",
"language": "css"
},
{
"name": "README.mdx",
"content": "# 📝 Predictive State Updates Document Editor\n\n## What This Demo Shows\n\nThis demo showcases CopilotKit's **predictive state updates** for real-time document collaboration:\n1. **Live Document Editing**: Watch as your Copilot makes changes to a document in real-time\n2. **Diff Visualization**: See exactly what's being changed as it happens\n3. **Streaming Updates**: Changes are displayed character-by-character as the Copilot works\n\n## How to Interact\n\nTry these interactions with the collaborative document editor:\n- \"Fix the grammar and typos in this document\"\n- \"Make this text more professional\"\n- \"Add a section about [topic]\"\n- \"Summarize this content in bullet points\"\n- \"Change the tone to be more casual\"\n\nWatch as the Copilot processes your request and edits the document in real-time right before your eyes.\n\n## ✨ Predictive State Updates in Action\n\n**What's happening technically:**\n- The document state is shared between your UI and the Copilot\n- As the Copilot generates content, changes are streamed to the UI\n- Each modification is visualized with additions and deletions\n- The UI renders these changes progressively, without waiting for completion\n- All edits are tracked and displayed in a visually intuitive way\n\n**What you'll see in this demo:**\n- Text changes are highlighted in different colors (green for additions, red for deletions)\n- The document updates character-by-character, creating a typing-like effect\n- You can see the Copilot's thought process as it refines the content\n- The final document seamlessly incorporates all changes\n- The experience feels collaborative, as if someone is editing alongside you\n\nThis pattern of real-time collaborative editing with diff visualization is perfect for document editors, code review tools, content creation platforms, or any application where users benefit from seeing exactly how content is being transformed! ",
"path": "README.mdx",
"language": "markdown"
}
],
"readmeContent": "# 📝 Predictive State Updates Document Editor\n\n## What This Demo Shows\n\nThis demo showcases CopilotKit's **predictive state updates** for real-time document collaboration:\n1. **Live Document Editing**: Watch as your Copilot makes changes to a document in real-time\n2. **Diff Visualization**: See exactly what's being changed as it happens\n3. **Streaming Updates**: Changes are displayed character-by-character as the Copilot works\n\n## How to Interact\n\nTry these interactions with the collaborative document editor:\n- \"Fix the grammar and typos in this document\"\n- \"Make this text more professional\"\n- \"Add a section about [topic]\"\n- \"Summarize this content in bullet points\"\n- \"Change the tone to be more casual\"\n\nWatch as the Copilot processes your request and edits the document in real-time right before your eyes.\n\n## ✨ Predictive State Updates in Action\n\n**What's happening technically:**\n- The document state is shared between your UI and the Copilot\n- As the Copilot generates content, changes are streamed to the UI\n- Each modification is visualized with additions and deletions\n- The UI renders these changes progressively, without waiting for completion\n- All edits are tracked and displayed in a visually intuitive way\n\n**What you'll see in this demo:**\n- Text changes are highlighted in different colors (green for additions, red for deletions)\n- The document updates character-by-character, creating a typing-like effect\n- You can see the Copilot's thought process as it refines the content\n- The final document seamlessly incorporates all changes\n- The experience feels collaborative, as if someone is editing alongside you\n\nThis pattern of real-time collaborative editing with diff visualization is perfect for document editors, code review tools, content creation platforms, or any application where users benefit from seeing exactly how content is being transformed! "
},
"tool_based_generative_ui": {
"files": [
{
"name": "page.tsx",
"content": "\"use client\";\nimport { CopilotKit, useCopilotAction } from \"@copilotkit/react-core\";\nimport { CopilotKitCSSProperties, CopilotSidebar } from \"@copilotkit/react-ui\";\nimport { useState } from \"react\";\nimport \"@copilotkit/react-ui/styles.css\";\nimport \"./style.css\";\n\nexport default function AgenticChat() {\n return (\n <CopilotKit\n runtimeUrl=\"/api/copilotkit\"\n showDevConsole={false}\n // agent lock to the relevant agent\n agent=\"toolBasedGenerativeUIAgent\"\n >\n <div\n className=\"min-h-full w-full flex items-center justify-center\"\n style={\n {\n // \"--copilot-kit-primary-color\": \"#222\",\n // \"--copilot-kit-separator-color\": \"#CCC\",\n } as CopilotKitCSSProperties\n }\n >\n <Haiku />\n <CopilotSidebar\n defaultOpen={true}\n labels={{\n title: \"Haiku Generator\",\n initial: \"I'm a haiku generator 👋. How can I help you?\",\n }}\n clickOutsideToClose={false}\n />\n </div>\n </CopilotKit>\n );\n}\n\nfunction Haiku() {\n const [haiku, setHaiku] = useState<{\n japanese: string[];\n english: string[];\n }>({\n japanese: [\"仮の句よ\", \"まっさらながら\", \"花を呼ぶ\"],\n english: [\n \"A placeholder verse—\",\n \"even in a blank canvas,\",\n \"it beckons flowers.\",\n ],\n });\n\n useCopilotAction({\n name: \"generate_haiku\",\n parameters: [\n {\n name: \"japanese\",\n type: \"string[]\",\n },\n {\n name: \"english\",\n type: \"string[]\",\n },\n ],\n followUp: false,\n handler: async () => {\n return \"Haiku generated.\";\n },\n render: ({ args: generatedHaiku, result, status }) => {\n return (\n <HaikuApproval\n setHaiku={setHaiku}\n generatedHaiku={generatedHaiku}\n status={status}\n />\n );\n },\n });\n return (\n <>\n <div className=\"text-left\">\n {haiku?.japanese.map((line, index) => (\n <div className=\"flex items-center gap-6 mb-2\" key={index}>\n <p className=\"text-4xl font-bold text-gray-500\">{line}</p>\n <p className=\"text-base font-light\">{haiku?.english?.[index]}</p>\n </div>\n ))}\n </div>\n </>\n );\n}\n\ninterface HaikuApprovalProps {\n setHaiku: any;\n status: any;\n generatedHaiku: any;\n}\n\nfunction HaikuApproval({\n setHaiku,\n status,\n generatedHaiku,\n}: HaikuApprovalProps) {\n const [isApplied, setIsApplied] = useState(false);\n if (\n !generatedHaiku ||\n !generatedHaiku.japanese ||\n !generatedHaiku.japanese.length\n ) {\n return <></>;\n }\n\n return (\n <div className=\"text-left rounded-md p-4 mt-4 mb-4 flex flex-col bg-gray-100 dark:bg-zinc-900\">\n <div\n className={status === \"complete\" ? \"border-b border-gray-300 mb-4\" : \"\"}\n >\n {generatedHaiku?.japanese?.map((line: string, index: number) => (\n <div className=\"flex items-center gap-3 mb-2 pb-2\" key={index}>\n <p className=\"text-lg font-bold\">{line}</p>\n <p className=\"text-sm font-light\">\n {generatedHaiku?.english?.[index]}\n </p>\n </div>\n ))}\n </div>\n {status === \"complete\" && (\n <button\n onClick={() => {\n setHaiku(generatedHaiku);\n setIsApplied(true);\n }}\n className=\"ml-auto px-3 py-1 bg-white dark:bg-black text-black dark:text-white text-sm rounded cursor-pointer font-sm border \"\n >\n {isApplied ? \"Applied ✓\" : \"Apply\"}\n </button>\n )}\n </div>\n );\n}\n",
"path": "page.tsx",
"language": "typescript"
},
{
"name": "style.css",
"content": ".copilotKitWindow {\n box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);\n}\n",
"path": "style.css",
"language": "css"
},
{
"name": "README.mdx",
"content": "# 🪶 Tool-Based Generative UI Haiku Creator\n\n## What This Demo Shows\n\nThis demo showcases CopilotKit's **tool-based generative UI** capabilities:\n1. **Frontend Rendering of Tool Calls**: Backend tool calls are automatically rendered in the UI\n2. **Dynamic UI Generation**: The UI updates in real-time as the agent generates content\n3. **Elegant Content Presentation**: Complex structured data (haikus) are beautifully displayed\n\n## How to Interact\n\nChat with your Copilot and ask for haikus about different topics:\n- \"Create a haiku about nature\"\n- \"Write a haiku about technology\"\n- \"Generate a haiku about the changing seasons\"\n- \"Make a humorous haiku about programming\"\n\nEach request will trigger the agent to generate a haiku and display it in a visually appealing card format in the UI.\n\n## ✨ Tool-Based Generative UI in Action\n\n**What's happening technically:**\n- The agent processes your request and determines it should create a haiku\n- It calls a backend tool that returns structured haiku data\n- CopilotKit automatically renders this tool call in the frontend\n- The rendering is handled by the registered tool component in your React app\n- No manual state management is required to display the results\n\n**What you'll see in this demo:**\n- As you request a haiku, a beautifully formatted card appears in the UI\n- The haiku follows the traditional 5-7-5 syllable structure\n- Each haiku is presented with consistent styling\n- Multiple haikus can be generated in sequence\n- The UI adapts to display each new piece of content\n\nThis pattern of tool-based generative UI can be extended to create any kind of dynamic content - from data visualizations to interactive components, all driven by your Copilot's tool calls! ",
"path": "README.mdx",
"language": "markdown"
}
],
"readmeContent": "# 🪶 Tool-Based Generative UI Haiku Creator\n\n## What This Demo Shows\n\nThis demo showcases CopilotKit's **tool-based generative UI** capabilities:\n1. **Frontend Rendering of Tool Calls**: Backend tool calls are automatically rendered in the UI\n2. **Dynamic UI Generation**: The UI updates in real-time as the agent generates content\n3. **Elegant Content Presentation**: Complex structured data (haikus) are beautifully displayed\n\n## How to Interact\n\nChat with your Copilot and ask for haikus about different topics:\n- \"Create a haiku about nature\"\n- \"Write a haiku about technology\"\n- \"Generate a haiku about the changing seasons\"\n- \"Make a humorous haiku about programming\"\n\nEach request will trigger the agent to generate a haiku and display it in a visually appealing card format in the UI.\n\n## ✨ Tool-Based Generative UI in Action\n\n**What's happening technically:**\n- The agent processes your request and determines it should create a haiku\n- It calls a backend tool that returns structured haiku data\n- CopilotKit automatically renders this tool call in the frontend\n- The rendering is handled by the registered tool component in your React app\n- No manual state management is required to display the results\n\n**What you'll see in this demo:**\n- As you request a haiku, a beautifully formatted card appears in the UI\n- The haiku follows the traditional 5-7-5 syllable structure\n- Each haiku is presented with consistent styling\n- Multiple haikus can be generated in sequence\n- The UI adapts to display each new piece of content\n\nThis pattern of tool-based generative UI can be extended to create any kind of dynamic content - from data visualizations to interactive components, all driven by your Copilot's tool calls! "
}
}