diff --git a/frontend/src/app/(dashboard)/agents/config/[agentId]/page.tsx b/frontend/src/app/(dashboard)/agents/config/[agentId]/page.tsx index d74c1189..b74f0b0c 100644 --- a/frontend/src/app/(dashboard)/agents/config/[agentId]/page.tsx +++ b/frontend/src/app/(dashboard)/agents/config/[agentId]/page.tsx @@ -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({ name: '', description: '', @@ -73,30 +59,18 @@ export default function AgentConfigurationPageRefactored() { const [originalData, setOriginalData] = useState(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 (
- + {error.message || 'Failed to load agent configuration'} @@ -224,7 +195,10 @@ export default function AgentConfigurationPageRefactored() { if (isLoading) { return (
- +
+ +

Loading agent configuration...

+
); } @@ -232,14 +206,13 @@ export default function AgentConfigurationPageRefactored() { if (!agent) { return (
- + Agent not found
); } - // 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 ( -
+
-
+
-
-
- - { - setOriginalData(formData); - }} - /> -
-
- {hasUnsavedChanges && !isViewingOldVersion && ( - )} - Save Changes - +
+
+ {isViewingOldVersion && ( + )} +
- -
-
- {isViewingOldVersion && ( - - -
- - You are viewing a read-only version. To make changes, please activate this version or switch back to the current version. - -
- {versionData && ( - - {versionData.version_name} - - )} - -
-
-
- )} -
- -
-
-
- -
-
{currentStyle.avatar}
-
-
- handleFieldChange('name', value)} - className="text-md font-semibold bg-transparent" - placeholder="Click to add agent name..." - disabled={isViewingOldVersion} - /> -
- - - Agent Builder - - Configuration - -
-
- - - {isViewingOldVersion ? ( -
-
-
🔒
-
-

Agent Builder Disabled

-

- The Agent Builder is only available for the current version. - To use the Agent Builder, please activate this version first. -

-
-
-
- ) : ( - - )} -
- {activeTab === 'configuration' && ( -
- handleFieldChange('system_prompt', value)} - placeholder="Click to set system instructions..." - title="System Instructions" - disabled={isViewingOldVersion} - /> -
- )} - - - - -
-
- -
- Tools -
-
- - handleFieldChange('agentpress_tools', tools)} - /> - -
- - - -
-
- -
- Integrations -
-
- - - -
- - - -
-
- -
- Knowledge Base -
-
- - - -
- - - -
-
- -
- Workflows -
-
- - - -
- - - -
-
- -
- Triggers -
-
- - - -
-
-
-
+
+ + + + + + + +
-
- {previewAgent && } +
+
+ {previewAgent && } +
@@ -527,17 +347,17 @@ export default function AgentConfigurationPageRefactored() { - - + + Agent Preview -
+
{previewAgent && }
diff --git a/frontend/src/components/agents/config/agent-builder-tab.tsx b/frontend/src/components/agents/config/agent-builder-tab.tsx new file mode 100644 index 00000000..26e6e9d0 --- /dev/null +++ b/frontend/src/components/agents/config/agent-builder-tab.tsx @@ -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 ( +
+
+
🔒
+
+

Builder Unavailable

+

+ Only available for the current version. Please activate this version first. +

+
+
+
+ ); + } + + return ( +
+ +
+ ); +} \ No newline at end of file diff --git a/frontend/src/components/agents/config/agent-header.tsx b/frontend/src/components/agents/config/agent-header.tsx new file mode 100644 index 00000000..21be0b19 --- /dev/null +++ b/frontend/src/components/agents/config/agent-header.tsx @@ -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 ( +
+
+ +
+
{currentStyle.avatar}
+
+
+
+ onFieldChange('name', value)} + className="text-lg font-semibold bg-transparent text-foreground placeholder:text-muted-foreground" + placeholder="Agent name..." + disabled={isViewingOldVersion} + /> +
+
+ + + + + Prompt to Build + + + + Manual Config + + + +
+ ); +} \ No newline at end of file diff --git a/frontend/src/components/agents/config/configuration-tab.tsx b/frontend/src/components/agents/config/configuration-tab.tsx new file mode 100644 index 00000000..58756953 --- /dev/null +++ b/frontend/src/components/agents/config/configuration-tab.tsx @@ -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 ( +
+ + + +
+
+ +
+
+

System Prompt

+

Define agent behavior and goals

+
+
+
+ + onFieldChange('system_prompt', value)} + placeholder="Click to set system instructions..." + title="System Instructions" + disabled={isViewingOldVersion} + /> + +
+ + + +
+
+ +
+
+

Default Tools

+

Configure default agentpress tools

+
+
+
+ + onFieldChange('agentpress_tools', tools)} + /> + +
+ + + +
+
+ +
+
+

Integrations

+

Connect external services via MCPs

+
+
+
+ + + +
+ + + +
+
+ +
+
+

Knowledge Base

+

Upload and manage knowledge for the agent

+
+
+
+ + + +
+ + + +
+
+ +
+
+

Workflows

+

Automate complex processes

+
+
+
+ + + +
+ + + +
+
+ +
+
+

Triggers

+

Set up automated agent runs

+
+
+
+ + + +
+
+
+ ); +} diff --git a/frontend/src/components/agents/config/index.ts b/frontend/src/components/agents/config/index.ts new file mode 100644 index 00000000..1c039859 --- /dev/null +++ b/frontend/src/components/agents/config/index.ts @@ -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'; \ No newline at end of file diff --git a/frontend/src/components/agents/config/version-alert.tsx b/frontend/src/components/agents/config/version-alert.tsx new file mode 100644 index 00000000..c41ef961 --- /dev/null +++ b/frontend/src/components/agents/config/version-alert.tsx @@ -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 ( +
+
+ + + You are viewing a read-only version of the agent + + +
+
+ ); +} \ No newline at end of file