improve agent config ui

This commit is contained in:
Saumya 2025-07-15 00:16:40 +05:30
parent 76eef5081c
commit df29b41a2f
6 changed files with 489 additions and 286 deletions

View File

@ -2,32 +2,23 @@
import React, { useState, useCallback, useEffect } from 'react';
import { useParams, useRouter } from 'next/navigation';
import { Loader2, Save, Eye, Check, Wrench, Server, BookOpen, Workflow, Zap } from 'lucide-react';
import { Loader2, Save, Eye } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/components/ui/accordion';
import { Badge } from '@/components/ui/badge';
import { Alert, AlertDescription } from '@/components/ui/alert';
import { Drawer, DrawerContent, DrawerHeader, DrawerTitle, DrawerTrigger } from '@/components/ui/drawer';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { Dialog, DialogContent } from '@/components/ui/dialog';
import { useUpdateAgent } from '@/hooks/react-query/agents/use-agents';
import { useCreateAgentVersion, useActivateAgentVersion } from '@/hooks/react-query/agents/use-agent-versions';
import { AgentMCPConfiguration } from '../../../../../components/agents/agent-mcp-configuration';
import { toast } from 'sonner';
import { AgentToolsConfiguration } from '../../../../../components/agents/agent-tools-configuration';
import { AgentPreview } from '../../../../../components/agents/agent-preview';
import { getAgentAvatar } from '../../../../../lib/utils/get-agent-style';
import { EditableText } from '@/components/ui/editable';
import { ExpandableMarkdownEditor } from '@/components/ui/expandable-markdown-editor';
import { StylePicker } from '../../../../../components/agents/style-picker';
import { AgentBuilderChat } from '../../../../../components/agents/agent-builder-chat';
import { AgentTriggersConfiguration } from '@/components/agents/triggers/agent-triggers-configuration';
import { AgentKnowledgeBaseManager } from '@/components/agents/knowledge-base/agent-knowledge-base-manager';
import { AgentWorkflowsConfiguration } from '@/components/agents/workflows/agent-workflows-configuration';
import { AgentPreview } from '../../../../../components/agents/agent-preview';
import { AgentVersionSwitcher } from '@/components/agents/agent-version-switcher';
import { CreateVersionButton } from '@/components/agents/create-version-button';
import { useAgentVersionData } from '../../../../../hooks/use-agent-version-data';
import { useAgentVersionStore } from '../../../../../lib/stores/agent-version-store';
import { cn } from '@/lib/utils';
import { AgentHeader, VersionAlert, AgentBuilderTab, ConfigurationTab } from '@/components/agents/config';
interface FormData {
name: string;
@ -46,18 +37,13 @@ export default function AgentConfigurationPageRefactored() {
const router = useRouter();
const agentId = params.agentId as string;
// Use modular hooks
const { agent, versionData, isViewingOldVersion, isLoading, error } = useAgentVersionData({ agentId });
// Debug logging
console.log('[Agent Config] Loading state:', { isLoading, error, agentId });
const { hasUnsavedChanges, setHasUnsavedChanges } = useAgentVersionStore();
const updateAgentMutation = useUpdateAgent();
const createVersionMutation = useCreateAgentVersion();
const activateVersionMutation = useActivateAgentVersion();
// State management
const [formData, setFormData] = useState<FormData>({
name: '',
description: '',
@ -73,30 +59,18 @@ export default function AgentConfigurationPageRefactored() {
const [originalData, setOriginalData] = useState<FormData>(formData);
const [isSaving, setIsSaving] = useState(false);
const [isPreviewOpen, setIsPreviewOpen] = useState(false);
const [isComparisonOpen, setIsComparisonOpen] = useState(false);
const [activeTab, setActiveTab] = useState('agent-builder');
// Initialize form data from agent/version data
useEffect(() => {
if (!agent) return;
console.log('[Agent Config] Agent data:', agent);
console.log('[Agent Config] Version data:', versionData);
// Determine the source of configuration data
let configSource = agent;
// If we have explicit version data (from URL param), use it
if (versionData) {
configSource = versionData;
}
// If no URL param but agent has current_version data, use that
else if (agent.current_version) {
configSource = agent.current_version;
}
console.log('[Agent Config] Config source:', configSource);
const initialData: FormData = {
name: agent.name || '',
description: agent.description || '',
@ -190,19 +164,16 @@ export default function AgentConfigurationPageRefactored() {
}));
}, [isViewingOldVersion]);
// Version activation handler
const handleActivateVersion = useCallback(async (versionId: string) => {
try {
await activateVersionMutation.mutateAsync({ agentId, versionId });
toast.success('Version activated successfully');
// Refresh page without version param
router.push(`/agents/config/${agentId}`);
} catch (error) {
toast.error('Failed to activate version');
}
}, [agentId, activateVersionMutation, router]);
// Auto-switch to configuration tab when viewing old versions
useEffect(() => {
if (isViewingOldVersion && activeTab === 'agent-builder') {
setActiveTab('configuration');
@ -212,7 +183,7 @@ export default function AgentConfigurationPageRefactored() {
if (error) {
return (
<div className="flex items-center justify-center h-screen">
<Alert variant="destructive">
<Alert variant="destructive" className="max-w-md">
<AlertDescription>
{error.message || 'Failed to load agent configuration'}
</AlertDescription>
@ -224,7 +195,10 @@ export default function AgentConfigurationPageRefactored() {
if (isLoading) {
return (
<div className="flex items-center justify-center h-screen">
<Loader2 className="h-8 w-8 animate-spin" />
<div className="flex flex-col items-center gap-3">
<Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
<p className="text-sm text-muted-foreground">Loading agent configuration...</p>
</div>
</div>
);
}
@ -232,14 +206,13 @@ export default function AgentConfigurationPageRefactored() {
if (!agent) {
return (
<div className="flex items-center justify-center h-screen">
<Alert>
<Alert className="max-w-md">
<AlertDescription>Agent not found</AlertDescription>
</Alert>
</div>
);
}
// Use version data when viewing old version, otherwise use form data
const displayData = isViewingOldVersion && versionData ? {
name: agent?.name || '',
description: agent?.description || '',
@ -263,260 +236,107 @@ export default function AgentConfigurationPageRefactored() {
};
return (
<div className="h-screen flex flex-col">
<div className="h-screen flex flex-col bg-background">
<div className="flex-1 flex overflow-hidden">
<div className="hidden md:flex w-full h-full">
<div className="w-1/2 border-r bg-background h-full flex flex-col">
<div className="w-1/2 border-r border-border/40 bg-background h-full flex flex-col">
<div className="h-full flex flex-col">
<div className="flex justify-between items-center mb-4 p-4 border-b">
<div className="flex items-center gap-2">
<AgentVersionSwitcher
agentId={agentId}
currentVersionId={agent?.current_version_id}
currentFormData={{
system_prompt: formData.system_prompt,
configured_mcps: formData.configured_mcps,
custom_mcps: formData.custom_mcps,
agentpress_tools: formData.agentpress_tools
}}
/>
<CreateVersionButton
agentId={agentId}
currentFormData={{
system_prompt: formData.system_prompt,
configured_mcps: formData.configured_mcps,
custom_mcps: formData.custom_mcps,
agentpress_tools: formData.agentpress_tools
}}
hasChanges={hasUnsavedChanges && !isViewingOldVersion}
onVersionCreated={() => {
setOriginalData(formData);
}}
/>
</div>
<div className="flex items-center gap-2">
{hasUnsavedChanges && !isViewingOldVersion && (
<Button
size="sm"
onClick={handleSave}
disabled={isSaving}
>
{isSaving ? (
<Loader2 className="h-4 w-4 animate-spin" />
) : (
<Save className="h-4 w-4" />
<div className="flex-shrink-0 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<div className="p-4">
<div className="flex items-center justify-between mb-4">
<div className="flex items-center gap-2">
<AgentVersionSwitcher
agentId={agentId}
currentVersionId={agent?.current_version_id}
currentFormData={{
system_prompt: formData.system_prompt,
configured_mcps: formData.configured_mcps,
custom_mcps: formData.custom_mcps,
agentpress_tools: formData.agentpress_tools
}}
/>
<CreateVersionButton
agentId={agentId}
currentFormData={{
system_prompt: formData.system_prompt,
configured_mcps: formData.configured_mcps,
custom_mcps: formData.custom_mcps,
agentpress_tools: formData.agentpress_tools
}}
hasChanges={hasUnsavedChanges && !isViewingOldVersion}
onVersionCreated={() => {
setOriginalData(formData);
}}
/>
</div>
<div className="flex items-center gap-2">
{hasUnsavedChanges && !isViewingOldVersion && (
<Button
size="sm"
onClick={handleSave}
disabled={isSaving}
className="bg-primary hover:bg-primary/90 text-primary-foreground"
>
{isSaving ? (
<Loader2 className="h-3 w-3 animate-spin" />
) : (
<Save className="h-3 w-3" />
)}
Save
</Button>
)}
Save Changes
</Button>
</div>
</div>
{isViewingOldVersion && (
<VersionAlert
versionData={versionData}
isActivating={activateVersionMutation.isPending}
onActivateVersion={handleActivateVersion}
/>
)}
<AgentHeader
agentId={agentId}
displayData={displayData}
currentStyle={currentStyle}
activeTab={activeTab}
isViewingOldVersion={isViewingOldVersion}
onFieldChange={handleFieldChange}
onStyleChange={handleStyleChange}
onTabChange={setActiveTab}
/>
</div>
</div>
<div className="flex-1 flex flex-col overflow-hidden -mt-4">
<div className="flex-shrink-0 space-y-6 px-4 mt-2">
{isViewingOldVersion && (
<Alert className="mb-4">
<Eye className="h-4 w-4" />
<div className="flex items-center justify-between w-full">
<AlertDescription>
You are viewing a read-only version. To make changes, please activate this version or switch back to the current version.
</AlertDescription>
<div className="ml-4 flex items-center gap-2">
{versionData && (
<Badge className="text-xs">
{versionData.version_name}
</Badge>
)}
<Button
size="sm"
variant="outline"
onClick={() => versionData && handleActivateVersion(versionData.version_id)}
disabled={activateVersionMutation.isPending}
>
{activateVersionMutation.isPending ? (
<Loader2 className="h-3 w-3 animate-spin mr-1" />
) : (
<Check className="h-3 w-3" />
)}
Set as Current
</Button>
</div>
</div>
</Alert>
)}
</div>
<Tabs value={activeTab} onValueChange={setActiveTab} className="flex flex-col flex-1 overflow-hidden">
<div className="flex-shrink-0 space-y-4 px-4 py-2">
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<StylePicker
currentEmoji={currentStyle.avatar}
currentColor={currentStyle.color}
onStyleChange={handleStyleChange}
agentId={agentId}
>
<div className="h-10 w-10 rounded-xl flex items-center justify-center gap-2" style={{ backgroundColor: currentStyle.color }}>
<div className="text-lg font-medium">{currentStyle.avatar}</div>
</div>
</StylePicker>
<EditableText
value={displayData.name}
onSave={(value) => handleFieldChange('name', value)}
className="text-md font-semibold bg-transparent"
placeholder="Click to add agent name..."
disabled={isViewingOldVersion}
/>
</div>
<TabsList className="grid grid-cols-2">
<TabsTrigger
value="agent-builder"
disabled={isViewingOldVersion}
className={isViewingOldVersion ? "opacity-50 cursor-not-allowed" : ""}
>
Agent Builder
</TabsTrigger>
<TabsTrigger value="configuration">Configuration</TabsTrigger>
</TabsList>
</div>
</div>
<TabsContent value="agent-builder" className="flex-1 h-0 px-4">
{isViewingOldVersion ? (
<div className="flex items-center justify-center h-full">
<div className="text-center space-y-4 max-w-md">
<div className="text-6xl">🔒</div>
<div>
<h3 className="text-lg font-semibold text-muted-foreground">Agent Builder Disabled</h3>
<p className="text-sm text-muted-foreground mt-2">
The Agent Builder is only available for the current version.
To use the Agent Builder, please activate this version first.
</p>
</div>
</div>
</div>
) : (
<AgentBuilderChat
agentId={agentId}
formData={displayData}
handleFieldChange={handleFieldChange}
handleStyleChange={handleStyleChange}
currentStyle={currentStyle}
/>
)}
</TabsContent>
{activeTab === 'configuration' && (
<div className='px-4'>
<ExpandableMarkdownEditor
value={displayData.system_prompt}
onSave={(value) => handleFieldChange('system_prompt', value)}
placeholder="Click to set system instructions..."
title="System Instructions"
disabled={isViewingOldVersion}
/>
</div>
)}
<TabsContent value="configuration" className="flex-1 h-0 overflow-y-auto px-4">
<Accordion type="single" collapsible defaultValue="system" className='space-y-2'>
<AccordionItem className='border rounded-xl px-4' value="tools">
<AccordionTrigger>
<div className='flex items-center gap-2'>
<div className='bg-muted rounded-full h-8 w-8 flex items-center justify-center'>
<Wrench className='h-4 w-4' />
</div>
Tools
</div>
</AccordionTrigger>
<AccordionContent>
<AgentToolsConfiguration
tools={displayData.agentpress_tools}
onToolsChange={(tools) => handleFieldChange('agentpress_tools', tools)}
/>
</AccordionContent>
</AccordionItem>
<AccordionItem className='border rounded-xl px-4' value="integrations">
<AccordionTrigger>
<div className='flex items-center gap-2'>
<div className='bg-muted rounded-full h-8 w-8 flex items-center justify-center'>
<Server className='h-4 w-4' />
</div>
Integrations
</div>
</AccordionTrigger>
<AccordionContent>
<AgentMCPConfiguration
configuredMCPs={displayData.configured_mcps}
customMCPs={displayData.custom_mcps}
onMCPChange={handleMCPChange}
agentId={agentId}
versionData={{
configured_mcps: displayData.configured_mcps,
custom_mcps: displayData.custom_mcps,
system_prompt: displayData.system_prompt,
agentpress_tools: displayData.agentpress_tools
}}
saveMode="callback"
versionId={versionData?.version_id}
/>
</AccordionContent>
</AccordionItem>
<AccordionItem className='border rounded-xl px-4' value="knowledge">
<AccordionTrigger>
<div className='flex items-center gap-2'>
<div className='bg-muted rounded-full h-8 w-8 flex items-center justify-center'>
<BookOpen className='h-4 w-4' />
</div>
Knowledge Base
</div>
</AccordionTrigger>
<AccordionContent>
<AgentKnowledgeBaseManager
agentId={agentId}
agentName={displayData.name || 'Agent'}
/>
</AccordionContent>
</AccordionItem>
<AccordionItem className='border rounded-xl px-4' value="workflows">
<AccordionTrigger>
<div className='flex items-center gap-2'>
<div className='bg-muted rounded-full h-8 w-8 flex items-center justify-center'>
<Workflow className='h-4 w-4' />
</div>
Workflows
</div>
</AccordionTrigger>
<AccordionContent>
<AgentWorkflowsConfiguration
agentId={agentId}
agentName={displayData.name || 'Agent'}
/>
</AccordionContent>
</AccordionItem>
<AccordionItem className='border rounded-xl px-4' value="triggers">
<AccordionTrigger>
<div className='flex items-center gap-2'>
<div className='bg-muted rounded-full h-8 w-8 flex items-center justify-center'>
<Zap className='h-4 w-4' />
</div>
Triggers
</div>
</AccordionTrigger>
<AccordionContent>
<AgentTriggersConfiguration agentId={agentId} />
</AccordionContent>
</AccordionItem>
</Accordion>
</TabsContent>
</Tabs>
<div className="flex-1 overflow-hidden">
<Tabs value={activeTab} onValueChange={setActiveTab} className="flex flex-col h-full">
<TabsContent value="agent-builder" className="flex-1 h-0 m-0">
<AgentBuilderTab
agentId={agentId}
displayData={displayData}
currentStyle={currentStyle}
isViewingOldVersion={isViewingOldVersion}
onFieldChange={handleFieldChange}
onStyleChange={handleStyleChange}
/>
</TabsContent>
<TabsContent value="configuration" className="flex-1 h-0 m-0 overflow-y-auto">
<ConfigurationTab
agentId={agentId}
displayData={displayData}
versionData={versionData}
isViewingOldVersion={isViewingOldVersion}
onFieldChange={handleFieldChange}
onMCPChange={handleMCPChange}
/>
</TabsContent>
</Tabs>
</div>
</div>
</div>
<div className="w-1/2 overflow-y-auto">
{previewAgent && <AgentPreview agent={previewAgent} />}
<div className="w-1/2 bg-muted/30 overflow-y-auto">
<div className="h-full">
{previewAgent && <AgentPreview agent={previewAgent} />}
</div>
</div>
</div>
@ -527,17 +347,17 @@ export default function AgentConfigurationPageRefactored() {
<Drawer open={isPreviewOpen} onOpenChange={setIsPreviewOpen}>
<DrawerTrigger asChild>
<Button
className="fixed bottom-4 right-4 rounded-full shadow-lg"
className="fixed bottom-6 right-6 rounded-full shadow-lg h-14 w-14 bg-primary hover:bg-primary/90"
size="icon"
>
<Eye className="h-4 w-4" />
<Eye className="h-5 w-5" />
</Button>
</DrawerTrigger>
<DrawerContent>
<DrawerHeader>
<DrawerContent className="h-[85vh]">
<DrawerHeader className="border-b">
<DrawerTitle>Agent Preview</DrawerTitle>
</DrawerHeader>
<div className="flex-1 overflow-y-auto px-4 pb-4">
<div className="flex-1 overflow-y-auto p-4">
{previewAgent && <AgentPreview agent={previewAgent} />}
</div>
</DrawerContent>

View File

@ -0,0 +1,61 @@
import React from 'react';
import { AgentBuilderChat } from '../agent-builder-chat';
interface AgentBuilderTabProps {
agentId: string;
displayData: {
name: string;
description: string;
system_prompt: string;
agentpress_tools: any;
configured_mcps: any[];
custom_mcps: any[];
is_default: boolean;
avatar: string;
avatar_color: string;
};
currentStyle: {
avatar: string;
color: string;
};
isViewingOldVersion: boolean;
onFieldChange: (field: string, value: any) => void;
onStyleChange: (emoji: string, color: string) => void;
}
export function AgentBuilderTab({
agentId,
displayData,
currentStyle,
isViewingOldVersion,
onFieldChange,
onStyleChange,
}: AgentBuilderTabProps) {
if (isViewingOldVersion) {
return (
<div className="flex items-center justify-center h-full">
<div className="text-center space-y-3 max-w-md px-6">
<div className="text-4xl opacity-50">🔒</div>
<div>
<h3 className="text-base font-semibold text-foreground mb-1">Builder Unavailable</h3>
<p className="text-sm text-muted-foreground">
Only available for the current version. Please activate this version first.
</p>
</div>
</div>
</div>
);
}
return (
<div className="px-4 h-full">
<AgentBuilderChat
agentId={agentId}
formData={displayData}
handleFieldChange={onFieldChange}
handleStyleChange={onStyleChange}
currentStyle={currentStyle}
/>
</div>
);
}

View File

@ -0,0 +1,85 @@
import React from 'react';
import { Sparkles, Settings } from 'lucide-react';
import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { EditableText } from '@/components/ui/editable';
import { StylePicker } from '../style-picker';
import { cn } from '@/lib/utils';
interface AgentHeaderProps {
agentId: string;
displayData: {
name: string;
description?: string;
};
currentStyle: {
avatar: string;
color: string;
};
activeTab: string;
isViewingOldVersion: boolean;
onFieldChange: (field: string, value: any) => void;
onStyleChange: (emoji: string, color: string) => void;
onTabChange: (value: string) => void;
}
export function AgentHeader({
agentId,
displayData,
currentStyle,
activeTab,
isViewingOldVersion,
onFieldChange,
onStyleChange,
onTabChange,
}: AgentHeaderProps) {
return (
<div className="flex items-center justify-between mb-4">
<div className="flex items-center gap-3">
<StylePicker
currentEmoji={currentStyle.avatar}
currentColor={currentStyle.color}
onStyleChange={onStyleChange}
agentId={agentId}
>
<div
className="h-9 w-9 rounded-lg flex items-center justify-center shadow-sm ring-1 ring-black/5 hover:ring-black/10 transition-all duration-200 cursor-pointer"
style={{ backgroundColor: currentStyle.color }}
>
<div className="text-lg font-medium">{currentStyle.avatar}</div>
</div>
</StylePicker>
<div className="flex-1 min-w-0">
<EditableText
value={displayData.name}
onSave={(value) => onFieldChange('name', value)}
className="text-lg font-semibold bg-transparent text-foreground placeholder:text-muted-foreground"
placeholder="Agent name..."
disabled={isViewingOldVersion}
/>
</div>
</div>
<Tabs value={activeTab} onValueChange={onTabChange}>
<TabsList className="grid grid-cols-2 bg-muted/50 h-9">
<TabsTrigger
value="agent-builder"
disabled={isViewingOldVersion}
className={cn(
"flex items-center gap-2 text-sm data-[state=active]:bg-background data-[state=active]:shadow-sm",
isViewingOldVersion && "opacity-50 cursor-not-allowed"
)}
>
<Sparkles className="h-3 w-3" />
Prompt to Build
</TabsTrigger>
<TabsTrigger
value="configuration"
className="flex items-center gap-2 text-sm data-[state=active]:bg-background data-[state=active]:shadow-sm"
>
<Settings className="h-3 w-3" />
Manual Config
</TabsTrigger>
</TabsList>
</Tabs>
</div>
);
}

View File

@ -0,0 +1,197 @@
import React from 'react';
import { Settings, Wrench, Server, BookOpen, Workflow, Zap } from 'lucide-react';
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/components/ui/accordion';
import { ExpandableMarkdownEditor } from '@/components/ui/expandable-markdown-editor';
import { AgentToolsConfiguration } from '../agent-tools-configuration';
import { AgentMCPConfiguration } from '../agent-mcp-configuration';
import { AgentKnowledgeBaseManager } from '../knowledge-base/agent-knowledge-base-manager';
import { AgentWorkflowsConfiguration } from '../workflows/agent-workflows-configuration';
import { AgentTriggersConfiguration } from '../triggers/agent-triggers-configuration';
interface ConfigurationTabProps {
agentId: string;
displayData: {
name: string;
description: string;
system_prompt: string;
agentpress_tools: any;
configured_mcps: any[];
custom_mcps: any[];
is_default: boolean;
avatar: string;
avatar_color: string;
};
versionData?: {
version_id: string;
configured_mcps: any[];
custom_mcps: any[];
system_prompt: string;
agentpress_tools: any;
};
isViewingOldVersion: boolean;
onFieldChange: (field: string, value: any) => void;
onMCPChange: (updates: { configured_mcps: any[]; custom_mcps: any[] }) => void;
}
export function ConfigurationTab({
agentId,
displayData,
versionData,
isViewingOldVersion,
onFieldChange,
onMCPChange,
}: ConfigurationTabProps) {
return (
<div className="p-4">
<Accordion type="single" collapsible defaultValue="system" className="space-y-2">
<AccordionItem
value="system"
className="rounded-xl hover:bg-muted/30 border transition-colors duration-200"
>
<AccordionTrigger className="hover:no-underline py-4 px-4 [&[data-state=open]]:pb-3">
<div className="flex items-center gap-3">
<div className="bg-muted rounded-lg h-9 w-9 flex items-center justify-center">
<Settings className="h-4 w-4" />
</div>
<div className="text-left">
<h4 className="font-medium text-sm text-gray-900 dark:text-gray-100">System Prompt</h4>
<p className="text-xs text-gray-500 dark:text-gray-400">Define agent behavior and goals</p>
</div>
</div>
</AccordionTrigger>
<AccordionContent className="px-4 pb-4">
<ExpandableMarkdownEditor
value={displayData.system_prompt}
onSave={(value) => onFieldChange('system_prompt', value)}
placeholder="Click to set system instructions..."
title="System Instructions"
disabled={isViewingOldVersion}
/>
</AccordionContent>
</AccordionItem>
<AccordionItem
value="tools"
className="rounded-xl hover:bg-muted/30 border transition-colors duration-200"
>
<AccordionTrigger className="hover:no-underline py-4 px-4 [&[data-state=open]]:pb-3">
<div className="flex items-center gap-3">
<div className="bg-muted rounded-lg h-9 w-9 flex items-center justify-center">
<Wrench className="h-4 w-4" />
</div>
<div className="text-left">
<h4 className="font-medium text-sm text-gray-900 dark:text-gray-100">Default Tools</h4>
<p className="text-xs text-gray-500 dark:text-gray-400">Configure default agentpress tools</p>
</div>
</div>
</AccordionTrigger>
<AccordionContent className="px-4 pb-4">
<AgentToolsConfiguration
tools={displayData.agentpress_tools}
onToolsChange={(tools) => onFieldChange('agentpress_tools', tools)}
/>
</AccordionContent>
</AccordionItem>
<AccordionItem
value="integrations"
className="rounded-xl hover:bg-muted/30 border transition-colors duration-200"
>
<AccordionTrigger className="hover:no-underline py-4 px-4 [&[data-state=open]]:pb-3">
<div className="flex items-center gap-3">
<div className="bg-muted rounded-lg h-9 w-9 flex items-center justify-center">
<Server className="h-4 w-4" />
</div>
<div className="text-left">
<h4 className="font-medium text-sm text-gray-900 dark:text-gray-100">Integrations</h4>
<p className="text-xs text-gray-500 dark:text-gray-400">Connect external services via MCPs</p>
</div>
</div>
</AccordionTrigger>
<AccordionContent className="px-4 pb-4">
<AgentMCPConfiguration
configuredMCPs={displayData.configured_mcps}
customMCPs={displayData.custom_mcps}
onMCPChange={onMCPChange}
agentId={agentId}
versionData={{
configured_mcps: displayData.configured_mcps,
custom_mcps: displayData.custom_mcps,
system_prompt: displayData.system_prompt,
agentpress_tools: displayData.agentpress_tools
}}
saveMode="callback"
versionId={versionData?.version_id}
/>
</AccordionContent>
</AccordionItem>
<AccordionItem
value="knowledge"
className="rounded-xl hover:bg-muted/30 border transition-colors duration-200"
>
<AccordionTrigger className="hover:no-underline py-4 px-4 [&[data-state=open]]:pb-3">
<div className="flex items-center gap-3">
<div className="bg-muted rounded-lg h-9 w-9 flex items-center justify-center">
<BookOpen className="h-4 w-4" />
</div>
<div className="text-left">
<h4 className="font-medium text-sm text-gray-900 dark:text-gray-100">Knowledge Base</h4>
<p className="text-xs text-gray-500 dark:text-gray-400">Upload and manage knowledge for the agent</p>
</div>
</div>
</AccordionTrigger>
<AccordionContent className="px-4 pb-4">
<AgentKnowledgeBaseManager
agentId={agentId}
agentName={displayData.name || 'Agent'}
/>
</AccordionContent>
</AccordionItem>
<AccordionItem
value="workflows"
className="rounded-xl hover:bg-muted/30 border transition-colors duration-200"
>
<AccordionTrigger className="hover:no-underline py-4 px-4 [&[data-state=open]]:pb-3">
<div className="flex items-center gap-3">
<div className="bg-muted rounded-lg h-9 w-9 flex items-center justify-center">
<Workflow className="h-4 w-4" />
</div>
<div className="text-left">
<h4 className="font-medium text-sm text-gray-900 dark:text-gray-100">Workflows</h4>
<p className="text-xs text-gray-500 dark:text-gray-400">Automate complex processes</p>
</div>
</div>
</AccordionTrigger>
<AccordionContent className="px-4 pb-4">
<AgentWorkflowsConfiguration
agentId={agentId}
agentName={displayData.name || 'Agent'}
/>
</AccordionContent>
</AccordionItem>
<AccordionItem
value="triggers"
className="rounded-xl hover:bg-muted/30 border transition-colors duration-200"
>
<AccordionTrigger className="hover:no-underline py-4 px-4 [&[data-state=open]]:pb-3">
<div className="flex items-center gap-3">
<div className="bg-muted rounded-lg h-9 w-9 flex items-center justify-center">
<Zap className="h-4 w-4" />
</div>
<div className="text-left">
<h4 className="font-medium text-sm text-gray-900 dark:text-gray-100">Triggers</h4>
<p className="text-xs text-gray-500 dark:text-gray-400">Set up automated agent runs</p>
</div>
</div>
</AccordionTrigger>
<AccordionContent className="px-4 pb-4">
<AgentTriggersConfiguration agentId={agentId} />
</AccordionContent>
</AccordionItem>
</Accordion>
</div>
);
}

View File

@ -0,0 +1,4 @@
export { AgentHeader } from './agent-header';
export { VersionAlert } from './version-alert';
export { AgentBuilderTab } from './agent-builder-tab';
export { ConfigurationTab } from './configuration-tab';

View File

@ -0,0 +1,36 @@
import React from 'react';
import { Eye, Check, Loader2, Info } from 'lucide-react';
import { Alert, AlertDescription } from '@/components/ui/alert';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
interface VersionAlertProps {
versionData?: {
version_id: string;
version_name: string;
};
isActivating: boolean;
onActivateVersion: (versionId: string) => void;
}
export function VersionAlert({
versionData,
isActivating,
onActivateVersion,
}: VersionAlertProps) {
if (!versionData) return null;
return (
<div className="mb-4 w-full bg-primary/5 border shadow-xs border-primary/10 p-2 rounded-xl">
<div className="flex items-center gap-2">
<AlertDescription className="text-primary text-sm flex items-center gap-2 flex-1">
<Info className="h-4 w-4 text-primary" />
<span>You are viewing a read-only version of the agent</span>
</AlertDescription>
<Button variant="outline" size="sm" onClick={() => onActivateVersion(versionData.version_id)}>
Activate
</Button>
</div>
</div>
);
}