Skip to content

Commit 2ad7a87

Browse files
author
Dylan Huang
committed
Refactor chat components and implement agent service
- Removed the Agent class and integrated its functionality into the new AgentService. - Added BubbleContainer component for consistent message display. - Enhanced ChatWindow to manage chat state using MobX and handle AI message processing. - Introduced ThinkingBubble for loading states and Spinner component for visual feedback. - Updated ChatMessages to show a prompt when no messages are present and display loading state. - Implemented ToolResults component to handle and display results from tool calls. - Improved Textarea component to support disabled state styling.
1 parent 33205a5 commit 2ad7a87

File tree

12 files changed

+1012
-182
lines changed

12 files changed

+1012
-182
lines changed

vite-app/src/agent/agent.ts

Lines changed: 0 additions & 14 deletions
This file was deleted.
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import type { ReactNode } from "react";
2+
import Button from "./Button";
3+
import { Tooltip } from "./Tooltip";
4+
5+
interface BubbleContainerProps {
6+
role: "user" | "assistant" | "system" | "tool" | "thinking";
7+
children: ReactNode;
8+
onCopy?: () => void;
9+
copySuccess?: boolean;
10+
showCopyButton?: boolean;
11+
}
12+
13+
export const BubbleContainer = ({
14+
role,
15+
children,
16+
onCopy,
17+
copySuccess = false,
18+
showCopyButton = true,
19+
}: BubbleContainerProps) => {
20+
const isUser = role === "user";
21+
const isSystem = role === "system";
22+
const isTool = role === "tool";
23+
const isAssistant = role === "assistant";
24+
const isThinking = role === "thinking";
25+
26+
const handleCopy = async () => {
27+
if (onCopy) {
28+
await onCopy();
29+
}
30+
};
31+
32+
return (
33+
<div className={`flex ${isUser ? "justify-end" : "justify-start"} mb-1`}>
34+
<div
35+
className={`max-w-sm lg:max-w-md xl:max-w-lg px-2 py-1 border text-xs relative overflow-scroll ${
36+
isUser
37+
? "bg-blue-50 border-blue-200 text-blue-900"
38+
: isAssistant
39+
? "bg-gray-50 border-gray-200 text-gray-800"
40+
: isSystem
41+
? "bg-gray-50 border-gray-200 text-gray-800"
42+
: isTool
43+
? "bg-green-50 border-green-200 text-green-900"
44+
: isThinking
45+
? "bg-gray-100 border-gray-200 text-gray-800"
46+
: "bg-yellow-50 border-yellow-200 text-yellow-900"
47+
}`}
48+
>
49+
{/* Copy button positioned in top-right corner */}
50+
{showCopyButton && onCopy && (
51+
<div className="absolute top-1 right-1">
52+
<Tooltip
53+
content={copySuccess ? "Copied!" : "Copy message to clipboard"}
54+
position="top"
55+
>
56+
<Button
57+
onClick={handleCopy}
58+
size="sm"
59+
variant="secondary"
60+
className={`p-0.5 h-5 text-[10px] opacity-60 hover:opacity-100 transition-opacity cursor-pointer ${
61+
isUser
62+
? "text-blue-600 hover:bg-blue-100"
63+
: isSystem
64+
? "text-gray-600 hover:bg-gray-100"
65+
: isTool
66+
? "text-green-600 hover:bg-green-100"
67+
: isThinking
68+
? "text-gray-600 hover:bg-gray-100"
69+
: "text-yellow-600 hover:bg-yellow-100"
70+
}`}
71+
>
72+
Copy
73+
</Button>
74+
</Tooltip>
75+
</div>
76+
)}
77+
78+
<div className="font-semibold text-xs mb-0.5 capitalize pr-8">
79+
{role}
80+
</div>
81+
{children}
82+
</div>
83+
</div>
84+
);
85+
};

vite-app/src/components/ChatMessages.tsx

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
import { useRef, useEffect } from "react";
22
import type { Message } from "../types/eval-protocol";
33
import { MessageBubble } from "./MessageBubble";
4+
import { ThinkingBubble } from "./ThinkingBubble";
45

56
interface ChatMessagesProps {
67
messages: Message[];
8+
isLoading?: boolean;
79
}
810

9-
export const ChatMessages = ({ messages }: ChatMessagesProps) => {
11+
export const ChatMessages = ({
12+
messages,
13+
isLoading = false,
14+
}: ChatMessagesProps) => {
1015
const scrollContainerRef = useRef<HTMLDivElement>(null);
1116
const prevMessagesLengthRef = useRef(0);
1217

@@ -40,9 +45,25 @@ export const ChatMessages = ({ messages }: ChatMessagesProps) => {
4045
ref={scrollContainerRef}
4146
className="flex-1 overflow-y-auto p-3 space-y-2"
4247
>
43-
{messages.map((message, msgIndex) => (
44-
<MessageBubble key={msgIndex} message={message} />
45-
))}
48+
{messages.length === 0 ? (
49+
<div className="flex items-center justify-center h-full text-gray-500">
50+
<div className="text-center">
51+
<div className="text-lg mb-2">🤖</div>
52+
<div className="text-sm">
53+
Start a conversation with the AI assistant
54+
</div>
55+
<div className="text-xs mt-1">
56+
Ask about your evaluation data, trends, or insights
57+
</div>
58+
</div>
59+
</div>
60+
) : (
61+
messages.map((message, index) => (
62+
<MessageBubble key={index} message={message} />
63+
))
64+
)}
65+
66+
{isLoading && <ThinkingBubble />}
4667
</div>
4768
);
4869
};

0 commit comments

Comments
 (0)