feat[agents]: added folder structure for agent builder

This commit is contained in:
Emir Karabeg
2025-03-17 17:17:25 -07:00
parent b95707f29c
commit d904c1e38e
12 changed files with 466 additions and 40 deletions
+62
View File
@@ -0,0 +1,62 @@
'use client'
import { useEffect } from 'react'
import { useAgentStore } from './stores/store'
/**
* Main Agent Builder Component
*
* This is the root component for the Agent Builder application:
* - Initializes and manages application state
* - Coordinates between components
* - Handles loading states and errors
* - Renders the main application layout
*
* @module Agents
*/
export default function Agents() {
const {
agents,
filteredAgents,
mcpServers,
loading,
error,
setLoading,
setError,
setAgents,
setMCPServers,
} = useAgentStore()
// Initialize store data on component mount
useEffect(() => {
// This would typically fetch data from an API
// For now, we'll just initialize with empty arrays
setAgents([])
setMCPServers([])
setLoading(false)
}, [setAgents, setMCPServers, setLoading])
if (loading) {
return <div>Loading agent builder...</div>
}
if (error) {
return <div>Error: {error}</div>
}
return (
<div className="agents-container">
<div className="agents-layout">
{/* Main content would be rendered here */}
<div className="agents-empty-state">
<h1>Agent Builder</h1>
<p>Create and manage your AI agents</p>
<p>Total agents: {agents.length}</p>
<p>Total MCP servers: {mcpServers.length}</p>
<p>This is a placeholder. Implement your components in the respective folders.</p>
</div>
</div>
</div>
)
}
@@ -0,0 +1,8 @@
/**
* Sidebar component for the Agent Builder
*
* This component provides navigation and management for agents:
* - Lists all available agents
* - Allows creation of new agents
* - Handles agent selection
*/
@@ -0,0 +1,10 @@
/**
* Toolbar component for the Agent Builder
*
* This component provides configuration tools for agents:
* - Model selection controls
* - MCP server connection management
* - Prompt configuration options
* - Testing and deployment actions
* - Save/publish functionality
*/
+3
View File
@@ -0,0 +1,3 @@
import Agents from './agents'
export default Agents
+190
View File
@@ -0,0 +1,190 @@
/**
* Agent Builder Zustand Store
*
* Central state management for the Agent Builder application:
* - Maintains collections of agents, MCP servers, and chat sessions
* - Handles CRUD operations for all entities
* - Manages UI state including selections, filters, and sorting
* - Provides actions for modifying state
* - Implements filtering and sorting logic
*
* @module AgentStore
*/
import { create } from 'zustand'
import { AgentState, Agent, MCPServer, ChatSession, ChatMessage } from './types'
export const useAgentStore = create<AgentState>((set, get) => ({
// Collections
agents: [],
mcpServers: [],
chatSessions: [],
// UI state
selectedAgentId: null,
selectedSessionId: null,
isCreatingAgent: false,
isEditingAgent: false,
sortBy: 'name',
sortDirection: 'asc',
searchQuery: '',
filteredAgents: [],
// Status
loading: true,
error: null,
// Agent actions
setAgents: (agents) => {
set({ agents, filteredAgents: agents, loading: false })
get().applyFilters()
},
addAgent: (agent) => {
set((state) => ({
agents: [...state.agents, agent],
loading: false
}))
get().applyFilters()
},
updateAgent: (id, updates) => {
set((state) => ({
agents: state.agents.map(agent =>
agent.id === id ? { ...agent, ...updates } : agent
)
}))
get().applyFilters()
},
deleteAgent: (id) => {
set((state) => ({
agents: state.agents.filter(agent => agent.id !== id)
}))
get().applyFilters()
},
selectAgent: (id) => {
set({ selectedAgentId: id })
},
// MCP Server actions
setMCPServers: (servers) => {
set({ mcpServers: servers })
},
addMCPServer: (server) => {
set((state) => ({
mcpServers: [...state.mcpServers, server]
}))
},
updateMCPServer: (id, updates) => {
set((state) => ({
mcpServers: state.mcpServers.map(server =>
server.id === id ? { ...server, ...updates } : server
)
}))
},
deleteMCPServer: (id) => {
set((state) => ({
mcpServers: state.mcpServers.filter(server => server.id !== id)
}))
},
// Chat session actions
setChatSessions: (sessions) => {
set({ chatSessions: sessions })
},
addChatSession: (session) => {
set((state) => ({
chatSessions: [...state.chatSessions, session]
}))
},
updateChatSession: (id, updates) => {
set((state) => ({
chatSessions: state.chatSessions.map(session =>
session.id === id ? { ...session, ...updates } : session
)
}))
},
deleteChatSession: (id) => {
set((state) => ({
chatSessions: state.chatSessions.filter(session => session.id !== id)
}))
},
selectChatSession: (id) => {
set({ selectedSessionId: id })
},
addMessageToSession: (sessionId, message) => {
set((state) => ({
chatSessions: state.chatSessions.map(session =>
session.id === sessionId
? { ...session, messages: [...session.messages, message] }
: session
)
}))
},
// UI state actions
setSearchQuery: (query) => {
set({ searchQuery: query })
get().applyFilters()
},
setSortBy: (sortBy) => {
set({ sortBy })
get().applyFilters()
},
setSortDirection: (direction) => {
set({ sortDirection: direction })
get().applyFilters()
},
// Status actions
setLoading: (loading) => set({ loading }),
setError: (error) => set({ error }),
// Filters and sorting
applyFilters: () => {
const { agents, searchQuery, sortBy, sortDirection } = get()
// Filter by search query
let filtered = [...agents]
if (searchQuery.trim()) {
const query = searchQuery.toLowerCase().trim()
filtered = filtered.filter(agent =>
agent.name.toLowerCase().includes(query) ||
agent.description.toLowerCase().includes(query)
)
}
// Sort agents
filtered.sort((a, b) => {
let comparison = 0
switch (sortBy) {
case 'name':
comparison = a.name.localeCompare(b.name)
break
case 'createdAt':
comparison = new Date(a.config.createdAt).getTime() - new Date(b.config.createdAt).getTime()
break
case 'updatedAt':
comparison = new Date(a.config.updatedAt).getTime() - new Date(b.config.updatedAt).getTime()
break
}
return sortDirection === 'asc' ? comparison : -comparison
})
set({ filteredAgents: filtered })
}
}))
+109
View File
@@ -0,0 +1,109 @@
/**
* Type Definitions for Agent Builder
*
* This module defines the TypeScript interfaces and types used throughout the Agent Builder:
* - Data models for agents, MCP servers, and chat sessions
* - State interfaces for Zustand stores
* - Type definitions for UI state and actions
* - Utility types for filtering and sorting
*
* @module AgentTypes
*/
export interface MCPServer {
id: string
name: string
url: string
apiKey?: string
status: 'connected' | 'disconnected' | 'error'
lastConnected?: string
}
export interface AgentConfig {
id: string
name: string
description: string
model: string
systemPrompt: string
mcpServerId?: string
createdAt: string
updatedAt: string
}
export interface Agent {
id: string
name: string
description: string
config: AgentConfig
mcpServer?: MCPServer
}
export interface ChatMessage {
id: string
agentId: string
role: 'user' | 'assistant' | 'system'
content: string
timestamp: string
}
export interface ChatSession {
id: string
agentId: string
name: string
messages: ChatMessage[]
createdAt: string
updatedAt: string
}
type AgentSortOption = 'name' | 'createdAt' | 'updatedAt'
type SortDirection = 'asc' | 'desc'
export interface AgentState {
// Collections
agents: Agent[]
mcpServers: MCPServer[]
chatSessions: ChatSession[]
// UI state
selectedAgentId: string | null
selectedSessionId: string | null
isCreatingAgent: boolean
isEditingAgent: boolean
sortBy: AgentSortOption
sortDirection: SortDirection
searchQuery: string
filteredAgents: Agent[]
// Status
loading: boolean
error: string | null
// Actions
setAgents: (agents: Agent[]) => void
addAgent: (agent: Agent) => void
updateAgent: (id: string, updates: Partial<Agent>) => void
deleteAgent: (id: string) => void
selectAgent: (id: string | null) => void
setMCPServers: (servers: MCPServer[]) => void
addMCPServer: (server: MCPServer) => void
updateMCPServer: (id: string, updates: Partial<MCPServer>) => void
deleteMCPServer: (id: string) => void
setChatSessions: (sessions: ChatSession[]) => void
addChatSession: (session: ChatSession) => void
updateChatSession: (id: string, updates: Partial<ChatSession>) => void
deleteChatSession: (id: string) => void
selectChatSession: (id: string | null) => void
addMessageToSession: (sessionId: string, message: ChatMessage) => void
setSearchQuery: (query: string) => void
setSortBy: (sortBy: AgentSortOption) => void
setSortDirection: (direction: SortDirection) => void
setLoading: (loading: boolean) => void
setError: (error: string | null) => void
// Filter and sort
applyFilters: () => void
}
+15
View File
@@ -0,0 +1,15 @@
/**
* Agent Management Utilities
*
* This module provides utilities for working with agent configurations:
* - Validation of agent configurations
* - Creation of default agents with sensible defaults
* - Template generation for common agent use cases
* - ID generation and unique identifier management
* - Configuration transformation and normalization
*
* These utilities help maintain consistency in agent configurations
* and provide helper functions for common agent-related operations.
*
* @module AgentUtils
*/
+15
View File
@@ -0,0 +1,15 @@
/**
* MCP Server Connection Utilities
*
* This module provides utilities for managing connections to MCP servers via Smithery:
* - Connection testing and validation
* - Connection pooling for efficient resource usage
* - Model discovery and capability detection
* - Agent execution on remote servers
* - Health monitoring and status checks
*
* These utilities abstract the complexities of Smithery integration and provide
* a clean API for the rest of the application to use when interacting with MCP servers.
*
* @module MCPServerUtils
*/
@@ -22,9 +22,9 @@ export function NavItem({
<Link
href={href}
className={clsx(
'flex h-9 w-9 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:text-foreground md:h-8 md:w-8',
'flex !h-9 !w-9 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:text-foreground md:h-8 md:w-8',
{
'bg-accent text-black': pathname === href,
'bg-accent': pathname === href,
}
)}
>
+23 -1
View File
@@ -4,7 +4,7 @@ import { useMemo, useState } from 'react'
import Link from 'next/link'
import { usePathname, useRouter } from 'next/navigation'
import clsx from 'clsx'
import { HelpCircle, Plus, ScrollText, Settings } from 'lucide-react'
import { Anvil, HelpCircle, Plus, ScrollText, Settings } from 'lucide-react'
import { AgentIcon } from '@/components/icons'
import { Button } from '@/components/ui/button'
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
@@ -97,6 +97,28 @@ export function Sidebar() {
</nav>
<nav className="flex flex-col items-center gap-4 px-2 py-[18px]">
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="ghost"
size="icon"
asChild
className={clsx(
'flex !h-9 !w-9 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:text-foreground md:h-8 md:w-8',
{
'bg-accent': pathname === '/w/agents',
}
)}
>
<Link href="/w/agents">
<Anvil className="!h-5 !w-5" />
<span className="sr-only">Agents</span>
</Link>
</Button>
</TooltipTrigger>
<TooltipContent side="right">Agents</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger asChild>
<Button
+1 -30
View File
@@ -1,34 +1,5 @@
import { create } from 'zustand'
import { WorkflowLog } from './types'
export type TimeRange = 'Past 30 minutes' | 'Past hour' | 'Past 24 hours' | 'All time'
export type LogLevel = 'error' | 'info' | 'all'
interface FilterState {
// Original logs from API
logs: WorkflowLog[]
// Filtered logs to display
filteredLogs: WorkflowLog[]
// Filter states
timeRange: TimeRange
level: LogLevel
workflowIds: string[]
searchQuery: string
// Loading state
loading: boolean
error: string | null
// Actions
setLogs: (logs: WorkflowLog[]) => void
setTimeRange: (timeRange: TimeRange) => void
setLevel: (level: LogLevel) => void
setWorkflowIds: (workflowIds: string[]) => void
toggleWorkflowId: (workflowId: string) => void
setSearchQuery: (query: string) => void
setLoading: (loading: boolean) => void
setError: (error: string | null) => void
// Apply filters
applyFilters: () => void
}
import { FilterState } from './types'
export const useFilterStore = create<FilterState>((set, get) => ({
logs: [],
+28 -7
View File
@@ -52,10 +52,31 @@ export interface WorkflowLog {
}
}
export interface LogsResponse {
data: WorkflowLog[]
total: number
page: number
pageSize: number
totalPages: number
}
type TimeRange = 'Past 30 minutes' | 'Past hour' | 'Past 24 hours' | 'All time'
type LogLevel = 'error' | 'info' | 'all'
export interface FilterState {
// Original logs from API
logs: WorkflowLog[]
// Filtered logs to display
filteredLogs: WorkflowLog[]
// Filter states
timeRange: TimeRange
level: LogLevel
workflowIds: string[]
searchQuery: string
// Loading state
loading: boolean
error: string | null
// Actions
setLogs: (logs: WorkflowLog[]) => void
setTimeRange: (timeRange: TimeRange) => void
setLevel: (level: LogLevel) => void
setWorkflowIds: (workflowIds: string[]) => void
toggleWorkflowId: (workflowId: string) => void
setSearchQuery: (query: string) => void
setLoading: (loading: boolean) => void
setError: (error: string | null) => void
// Apply filters
applyFilters: () => void
}