22 * Agent Chat Route
33 *
44 * Demonstrates CopilotKit integration with syncable-cli AG-UI server.
5- * Uses CopilotKit's built-in chat components for agent conversations.
5+ * Uses CopilotKit's built-in CopilotChat component for conversations.
66 */
77import { createFileRoute } from "@tanstack/react-router" ;
8- import { useState , useCallback , FormEvent } from "react" ;
9- import { useCopilotChat } from "@copilotkit/react-core" ;
10- import { MessageCircle , Send , Loader2 , Bot , User , Terminal } from "lucide-react" ;
8+ import { CopilotChat } from "@copilotkit/react-ui" ;
9+ import { Bot , Terminal } from "lucide-react" ;
10+
11+ // Import CopilotKit styles
12+ import "@copilotkit/react-ui/styles.css" ;
1113
1214export const Route = createFileRoute ( "/agent" ) ( {
1315 component : AgentChat ,
1416} ) ;
1517
1618function AgentChat ( ) {
17- const [ input , setInput ] = useState ( "" ) ;
18-
19- const {
20- visibleMessages,
21- appendMessage,
22- isLoading,
23- } = useCopilotChat ( ) ;
24-
25- const handleSubmit = useCallback (
26- async ( e : FormEvent ) => {
27- e . preventDefault ( ) ;
28- if ( ! input . trim ( ) || isLoading ) return ;
29-
30- const message = input . trim ( ) ;
31- setInput ( "" ) ;
32-
33- // Append user message and trigger agent response
34- await appendMessage ( {
35- id : crypto . randomUUID ( ) ,
36- role : "user" ,
37- content : message ,
38- } ) ;
39- } ,
40- [ input , isLoading , appendMessage ]
41- ) ;
42-
4319 return (
4420 < main className = "min-h-screen bg-slate-950 relative overflow-hidden" >
4521 { /* Background */ }
@@ -53,7 +29,7 @@ function AgentChat() {
5329 < div className = "p-3 rounded-2xl bg-linear-to-br from-emerald-500/20 to-cyan-600/20 border border-emerald-500/30 shadow-[0_0_30px_rgba(16,185,129,0.15)]" >
5430 < Bot className = "w-8 h-8 text-emerald-400" />
5531 </ div >
56- < h1 className = "text-4xl font-bold tracking-tight bg-gradient -to-r from-emerald-400 via-cyan-400 to-blue-400 bg-clip-text text-transparent" >
32+ < h1 className = "text-4xl font-bold tracking-tight bg-linear -to-r from-emerald-400 via-cyan-400 to-blue-400 bg-clip-text text-transparent" >
5733 Agent Chat
5834 </ h1 >
5935 </ div >
@@ -64,85 +40,15 @@ function AgentChat() {
6440 </ header >
6541
6642 { /* Chat Container */ }
67- < div className = "bg-slate-900/50 border border-slate-800 rounded-2xl overflow-hidden" >
68- { /* Messages Area */ }
69- < div className = "h-[500px] overflow-y-auto p-4 space-y-4" >
70- { visibleMessages . length === 0 ? (
71- < div className = "flex flex-col items-center justify-center h-full text-slate-500" >
72- < MessageCircle className = "w-12 h-12 mb-4 opacity-50" />
73- < p className = "text-sm" > No messages yet. Start a conversation!</ p >
74- </ div >
75- ) : (
76- visibleMessages . map ( ( message ) => (
77- < div
78- key = { message . id }
79- className = { `flex gap-3 ${
80- message . role === "user" ? "justify-end" : "justify-start"
81- } `}
82- >
83- { message . role !== "user" && (
84- < div className = "flex-shrink-0 w-8 h-8 rounded-lg bg-emerald-500/20 flex items-center justify-center" >
85- < Bot className = "w-4 h-4 text-emerald-400" />
86- </ div >
87- ) }
88- < div
89- className = { `max-w-[80%] rounded-2xl px-4 py-3 ${
90- message . role === "user"
91- ? "bg-cyan-600/20 border border-cyan-500/30 text-cyan-100"
92- : "bg-slate-800/50 border border-slate-700/50 text-slate-200"
93- } `}
94- >
95- < p className = "text-sm whitespace-pre-wrap" > { message . content } </ p >
96- </ div >
97- { message . role === "user" && (
98- < div className = "flex-shrink-0 w-8 h-8 rounded-lg bg-cyan-500/20 flex items-center justify-center" >
99- < User className = "w-4 h-4 text-cyan-400" />
100- </ div >
101- ) }
102- </ div >
103- ) )
104- ) }
105-
106- { /* Loading indicator */ }
107- { isLoading && (
108- < div className = "flex gap-3 justify-start" >
109- < div className = "flex-shrink-0 w-8 h-8 rounded-lg bg-emerald-500/20 flex items-center justify-center" >
110- < Bot className = "w-4 h-4 text-emerald-400" />
111- </ div >
112- < div className = "bg-slate-800/50 border border-slate-700/50 rounded-2xl px-4 py-3" >
113- < div className = "flex items-center gap-2 text-slate-400" >
114- < Loader2 className = "w-4 h-4 animate-spin" />
115- < span className = "text-sm" > Agent is thinking...</ span >
116- </ div >
117- </ div >
118- </ div >
119- ) }
120- </ div >
121-
122- { /* Input Area */ }
123- < form onSubmit = { handleSubmit } className = "border-t border-slate-800 p-4" >
124- < div className = "flex gap-3" >
125- < input
126- type = "text"
127- value = { input }
128- onChange = { ( e ) => setInput ( e . target . value ) }
129- placeholder = "Type your message..."
130- className = "flex-1 bg-slate-800/50 border border-slate-700 rounded-xl px-4 py-3 text-slate-100 placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-cyan-500/50 focus:border-cyan-500/50 transition-all"
131- disabled = { isLoading }
132- />
133- < button
134- type = "submit"
135- disabled = { ! input . trim ( ) || isLoading }
136- className = "px-6 py-3 rounded-xl bg-gradient-to-r from-emerald-500 to-cyan-500 text-white font-medium shadow-lg shadow-emerald-500/25 hover:shadow-emerald-500/40 hover:scale-105 disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:scale-100 transition-all duration-200 flex items-center gap-2"
137- >
138- { isLoading ? (
139- < Loader2 className = "w-5 h-5 animate-spin" />
140- ) : (
141- < Send className = "w-5 h-5" />
142- ) }
143- </ button >
144- </ div >
145- </ form >
43+ < div className = "bg-slate-900/50 border border-slate-800 rounded-2xl overflow-hidden h-[500px]" >
44+ < CopilotChat
45+ className = "h-full"
46+ labels = { {
47+ title : "Syncable Agent" ,
48+ initial : "Hi! I'm the Syncable agent. How can I help you today?" ,
49+ placeholder : "Type your message..." ,
50+ } }
51+ />
14652 </ div >
14753
14854 { /* Connection Info */ }
0 commit comments