Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 49 additions & 24 deletions apps/web/src/features/agents/components/agent-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,29 @@ function SupportedConfigBadge({
<Tooltip>
<TooltipTrigger>
{type === "rag" && (
<Badge variant="brand">
<Brain />
<Badge
variant="brand"
className="border-emerald-200 bg-emerald-50 text-emerald-700 transition-colors hover:bg-emerald-100 dark:border-emerald-800 dark:bg-emerald-950 dark:text-emerald-300"
>
<Brain className="h-3 w-3" />
RAG
</Badge>
)}
{type === "tools" && (
<Badge variant="info">
<Wrench />
<Badge
variant="info"
className="border-blue-200 bg-blue-50 text-blue-700 transition-colors hover:bg-blue-100 dark:border-blue-800 dark:bg-blue-950 dark:text-blue-300"
>
<Wrench className="h-3 w-3" />
MCP Tools
</Badge>
)}
{type === "supervisor" && (
<Badge variant="brand">
<User />
<Badge
variant="brand"
className="border-purple-200 bg-purple-50 text-purple-700 transition-colors hover:bg-purple-100 dark:border-purple-800 dark:bg-purple-950 dark:text-purple-300"
>
<User className="h-3 w-3" />
Supervisor
</Badge>
)}
Expand Down Expand Up @@ -78,19 +87,24 @@ export function AgentCard({ agent, showDeployment }: AgentCardProps) {
<>
<Card
key={agent.assistant_id}
className="overflow-hidden"
className="group from-card to-card/50 overflow-hidden border-0 bg-gradient-to-br backdrop-blur-sm transition-all duration-200 hover:-translate-y-0.5 hover:shadow-lg hover:shadow-black/5"
>
<CardHeader className="space-y-2 pb-2">
<CardHeader className="space-y-3 pb-3">
<div className="flex items-start justify-between">
<CardTitle className="flex w-full flex-wrap items-center gap-2">
<p>{agent.name}</p>
<h3 className="text-foreground group-hover:text-primary text-lg font-semibold transition-colors">
{agent.name}
</h3>
{showDeployment && selectedDeployment && (
<div className="flex flex-wrap items-center gap-1">
<div className="flex flex-wrap items-center gap-1.5">
<TooltipProvider>
<Tooltip>
<TooltipTrigger>
<Badge variant="outline">
<Cloud />
<Badge
variant="outline"
className="bg-muted/50 border-muted-foreground/20 text-muted-foreground hover:bg-muted/80 transition-colors"
>
<Cloud className="h-3 w-3" />
{selectedDeployment.name}
</Badge>
</TooltipTrigger>
Expand All @@ -101,8 +115,11 @@ export function AgentCard({ agent, showDeployment }: AgentCardProps) {

<Tooltip>
<TooltipTrigger>
<Badge variant="outline">
<Bot />
<Badge
variant="outline"
className="bg-muted/50 border-muted-foreground/20 text-muted-foreground hover:bg-muted/80 transition-colors"
>
<Bot className="h-3 w-3" />
{agent.graph_id}
</Badge>
</TooltipTrigger>
Expand All @@ -115,27 +132,32 @@ export function AgentCard({ agent, showDeployment }: AgentCardProps) {
)}
</CardTitle>
</div>
<div className="flex flex-0 flex-wrap items-center justify-start gap-2">
<div className="flex flex-col gap-3">
{agent.metadata?.description &&
typeof agent.metadata.description === "string" ? (
<p className="text-muted-foreground mt-1 text-sm">
<p className="text-muted-foreground line-clamp-2 text-sm leading-relaxed">
{agent.metadata.description}
</p>
) : null}
{agent.supportedConfigs?.map((config) => (
<SupportedConfigBadge
key={`${agent.assistant_id}-${config}`}
type={config}
/>
))}
{agent.supportedConfigs && agent.supportedConfigs.length > 0 && (
<div className="flex flex-wrap items-center gap-1.5">
{agent.supportedConfigs.map((config) => (
<SupportedConfigBadge
key={`${agent.assistant_id}-${config}`}
type={config}
/>
))}
</div>
)}
</div>
</CardHeader>
<CardFooter className="mt-auto flex w-full justify-between pt-2">
<CardFooter className="border-border/50 mt-auto flex w-full justify-between border-t pt-3">
{!isDefaultAgent && (
<Button
variant="outline"
size="sm"
onClick={() => setShowEditDialog(true)}
className="hover:bg-accent/50 transition-colors"
>
<Edit className="mr-2 h-3.5 w-3.5" />
Edit
Expand All @@ -145,7 +167,10 @@ export function AgentCard({ agent, showDeployment }: AgentCardProps) {
href={`/?agentId=${agent.assistant_id}&deploymentId=${agent.deploymentId}`}
className="ml-auto"
>
<Button size="sm">
<Button
size="sm"
className="bg-primary hover:bg-primary/90 text-primary-foreground shadow-sm transition-all duration-200 hover:shadow-md"
>
<MessageSquare className="mr-2 h-3.5 w-3.5" />
Chat
</Button>
Expand Down
31 changes: 19 additions & 12 deletions apps/web/src/features/agents/components/agent-dashboard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,11 @@ export function AgentDashboard() {
<div className="space-y-6">
<div className="flex flex-col gap-4">
<div className="flex flex-col items-start justify-between gap-4 sm:flex-row sm:items-center">
<div className="relative w-full max-w-sm">
<Search className="text-muted-foreground absolute top-2.5 left-2.5 h-4 w-4" />
<div className="relative w-full max-w-md">
<Search className="text-muted-foreground absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2" />
<Input
placeholder="Search agents..."
className="pl-8"
className="bg-background/50 border-border/50 focus:bg-background pl-10 transition-colors"
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
/>
Expand All @@ -98,14 +98,16 @@ export function AgentDashboard() {
<div className="flex flex-wrap items-center gap-4">
<div className="flex items-center gap-2">
<Filter className="text-muted-foreground h-4 w-4" />
<span className="text-sm font-medium">Filters:</span>
<span className="text-foreground text-sm font-medium">
Filters:
</span>
</div>

<Select
value={graphFilter}
onValueChange={setGraphFilter}
>
<SelectTrigger className="h-9 min-w-[180px]">
<SelectTrigger className="bg-background/50 border-border/50 focus:bg-background h-9 min-w-[180px] transition-colors">
<SelectValue placeholder="All Templates" />
</SelectTrigger>
<SelectContent>
Expand Down Expand Up @@ -134,21 +136,26 @@ export function AgentDashboard() {
</div>

{filteredAgents.length === 0 ? (
<div className="animate-in fade-in-50 flex flex-col items-center justify-center rounded-lg border border-dashed p-8 text-center">
<div className="bg-muted mx-auto flex h-20 w-20 items-center justify-center rounded-full">
<Search className="text-muted-foreground h-10 w-10" />
<div className="animate-in fade-in-50 border-border/50 from-muted/30 to-muted/10 flex flex-col items-center justify-center rounded-xl border border-dashed bg-gradient-to-br p-12 text-center">
<div className="bg-muted/50 border-border/50 mx-auto flex h-24 w-24 items-center justify-center rounded-full border">
<Search className="text-muted-foreground h-12 w-12" />
</div>
<h2 className="mt-6 text-xl font-semibold">No agents found</h2>
<p className="text-muted-foreground mt-2 mb-8 text-center">
<h2 className="text-foreground mt-6 text-2xl font-semibold">
No agents found
</h2>
<p className="text-muted-foreground mt-3 mb-8 max-w-md text-center leading-relaxed">
We couldn't find any agents matching your search criteria. Try
adjusting your filters or create a new agent.
</p>
<Button onClick={() => setShowCreateDialog(true)}>
<Button
onClick={() => setShowCreateDialog(true)}
className="bg-primary hover:bg-primary/90 text-primary-foreground shadow-sm transition-all duration-200 hover:shadow-md"
>
Create Agent
</Button>
</div>
) : (
<div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
<div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
{filteredAgents.map((agent) => (
<AgentCard
key={`agent-dashboard-${agent.assistant_id}`}
Expand Down
17 changes: 12 additions & 5 deletions apps/web/src/features/agents/components/page-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,22 @@ interface PageHeaderProps {
export function PageHeader({ title, description, action }: PageHeaderProps) {
const [showCreateAgentDialog, setShowCreateAgentDialog] = useState(false);
return (
<div className="flex flex-col items-start justify-between gap-4 sm:flex-row sm:items-center">
<div>
<h1 className="text-2xl font-bold tracking-tight">{title}</h1>
<div className="flex flex-col items-start justify-between gap-6 sm:flex-row sm:items-center">
<div className="space-y-2">
<h1 className="text-foreground text-3xl font-bold tracking-tight">
{title}
</h1>
{description && (
<p className="text-muted-foreground mt-1">{description}</p>
<p className="text-muted-foreground text-lg leading-relaxed">
{description}
</p>
)}
</div>
{action || (
<Button onClick={() => setShowCreateAgentDialog(true)}>
<Button
onClick={() => setShowCreateAgentDialog(true)}
className="bg-primary hover:bg-primary/90 text-primary-foreground shadow-sm transition-all duration-200 hover:shadow-md"
>
<PlusCircle className="mr-2 h-4 w-4" />
Create Agent
</Button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,42 +32,45 @@ export function AgentList({ agents, deploymentId }: AgentListProps) {
return (
<div className="space-y-4">
<div className="flex flex-col items-start justify-between gap-4 sm:flex-row sm:items-center">
<div className="relative w-full max-w-sm">
<Search className="text-muted-foreground absolute top-2.5 left-2.5 h-4 w-4" />
<div className="relative w-full max-w-md">
<Search className="text-muted-foreground absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2" />
<Input
placeholder="Search agents..."
className="pl-8"
className="bg-background/50 border-border/50 focus:bg-background pl-10 transition-colors"
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
/>
</div>
<Button
size="sm"
onClick={() => setShowCreateDialog(true)}
className="bg-primary hover:bg-primary/90 text-primary-foreground shadow-sm transition-all duration-200 hover:shadow-md"
>
<Plus className="mr-2 h-4 w-4" />
New Agent
</Button>
</div>

{filteredAgents.length === 0 ? (
<div className="flex flex-col items-center justify-center rounded-lg border border-dashed p-6 text-center">
<h3 className="text-lg font-medium">No agents found</h3>
<p className="text-muted-foreground mt-1 text-sm">
<div className="border-border/50 from-muted/20 to-muted/5 flex flex-col items-center justify-center rounded-xl border border-dashed bg-gradient-to-br p-8 text-center">
<h3 className="text-foreground text-lg font-medium">
No agents found
</h3>
<p className="text-muted-foreground mt-2 text-sm leading-relaxed">
Create a new agent or try a different search.
</p>
<Button
variant="outline"
size="sm"
className="mt-4"
className="hover:bg-accent/50 mt-4 transition-colors"
onClick={() => setShowCreateDialog(true)}
>
<Plus className="mr-2 h-4 w-4" />
Create Agent
</Button>
</div>
) : (
<div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
<div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
{filteredAgents.map((agent) => (
<AgentCard
key={`agent-list-${agent.assistant_id}`}
Expand Down
20 changes: 11 additions & 9 deletions apps/web/src/features/agents/components/templates-list/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,26 +70,28 @@ export function TemplatesList() {
}

return (
<div className="space-y-6">
<div className="space-y-8">
<div className="flex flex-col items-start justify-between gap-4 sm:flex-row sm:items-center">
<div className="relative flex-1">
<Search className="text-muted-foreground absolute top-1/2 left-2.5 h-4 w-4 -translate-y-1/2" />
<div className="relative max-w-md flex-1">
<Search className="text-muted-foreground absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2" />
<Input
placeholder="Search by graph or agent name..."
className="pl-8"
className="bg-background/50 border-border/50 focus:bg-background pl-10 transition-colors"
value={searchQueryState}
onChange={(e) => setSearchQueryState(e.target.value)}
/>
</div>
</div>

{filteredGraphGroupsState.length === 0 ? (
<div className="animate-in fade-in-50 flex flex-col items-center justify-center rounded-lg border border-dashed p-8 text-center">
<div className="bg-muted mx-auto flex h-20 w-20 items-center justify-center rounded-full">
<Search className="text-muted-foreground h-10 w-10" />
<div className="animate-in fade-in-50 border-border/50 from-muted/30 to-muted/10 flex flex-col items-center justify-center rounded-xl border border-dashed bg-gradient-to-br p-12 text-center">
<div className="bg-muted/50 border-border/50 mx-auto flex h-24 w-24 items-center justify-center rounded-full border">
<Search className="text-muted-foreground h-12 w-12" />
</div>
<h2 className="mt-6 text-xl font-semibold">No graphs found</h2>
<p className="text-muted-foreground mt-2 mb-8 text-center">
<h2 className="text-foreground mt-6 text-2xl font-semibold">
No graphs found
</h2>
<p className="text-muted-foreground mt-3 mb-8 max-w-md text-center leading-relaxed">
{searchQueryState
? "We couldn't find any graphs matching your search."
: "There are no agent graphs configured yet."}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@ export function TemplateCard({
return (
<Card
className={cn(
"overflow-hidden",
isOpen ? "" : "hover:bg-accent/50 cursor-pointer transition-colors",
"overflow-hidden transition-all duration-200",
isOpen
? "border-primary/20 from-card to-card/50 bg-gradient-to-br shadow-lg shadow-black/5"
: "from-card to-card/50 cursor-pointer border-0 bg-gradient-to-br backdrop-blur-sm hover:-translate-y-0.5 hover:shadow-md hover:shadow-black/5",
)}
onClick={() => {
// Don't allow toggling via clicking the card if it's already open
Expand All @@ -49,14 +51,14 @@ export function TemplateCard({
open={isOpen}
onOpenChange={() => toggleGraph(graphDeploymentId)}
>
<CardHeader className="flex flex-row items-center bg-inherit">
<CardHeader className="flex flex-row items-center bg-inherit pb-4">
<div className="flex-1">
<div className="flex items-center">
<CollapsibleTrigger asChild>
<Button
variant="ghost"
size="sm"
className="mr-2 h-8 w-8 p-0"
className="hover:bg-accent/50 mr-3 h-9 w-9 p-0 transition-colors"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
Expand All @@ -71,12 +73,19 @@ export function TemplateCard({
<span className="sr-only">Toggle</span>
</Button>
</CollapsibleTrigger>
<CardTitle className="flex items-center gap-2">
<p className="text-2xl">{_.startCase(graphId)}</p>
<CardTitle className="flex items-center gap-3">
<h2 className="text-foreground text-xl font-semibold">
{_.startCase(graphId)}
</h2>
<TooltipProvider>
<Tooltip>
<TooltipTrigger>
<Badge variant="outline">{deployment.name}</Badge>
<Badge
variant="outline"
className="bg-muted/50 border-muted-foreground/20 text-muted-foreground hover:bg-muted/80 transition-colors"
>
{deployment.name}
</Badge>
</TooltipTrigger>
<TooltipContent className="max-w-[350px]">
The deployment the graph belongs to. Deployments typically
Expand All @@ -88,13 +97,16 @@ export function TemplateCard({
</div>
</div>
<div className="flex items-center gap-2">
<Badge variant="outline">
<Badge
variant="outline"
className="bg-primary/10 text-primary border-primary/20 hover:bg-primary/20 transition-colors"
>
{agentsCount} Agent{agentsCount === 1 ? "" : "s"}
</Badge>
</div>
</CardHeader>
<CollapsibleContent>
<CardContent className="pt-6">
<CardContent className="border-border/50 border-t pt-4">
<AgentList
agents={agents}
deploymentId={deployment.id}
Expand Down
Loading