From 1d9e3645235f7d4011b10c48558a09bd53d9bc54 Mon Sep 17 00:00:00 2001 From: marko-kraemer Date: Wed, 9 Jul 2025 19:47:52 +0200 Subject: [PATCH] wip --- .../agents/_components/agent-builder-chat.tsx | 7 +- .../agents/_components/agent-preview.tsx | 7 +- .../agents/_components/agents-grid.tsx | 2 +- .../_components/mcp/mcp-configuration-new.tsx | 5 +- .../agents/_components/results-info.tsx | 2 +- .../{new => config}/[agentId]/layout.tsx | 0 .../agents/{new => config}/[agentId]/page.tsx | 8 +- .../[agentId]/workflow/[workflowId]/page.tsx | 0 .../[agentId]/workflow/layout.tsx | 0 frontend/src/app/(dashboard)/agents/page.tsx | 2 +- .../_components/dashboard-content.tsx | 2 + .../triggers/agent-triggers-configuration.tsx | 1 - .../agent-workflows-configuration.tsx | 4 +- .../thread/chat-input/agent-selector.tsx | 138 -------------- .../thread/chat-input/chat-input.tsx | 54 +++++- .../chat-input/chat-settings-dropdown.tsx | 180 +++++++++++------- .../thread/chat-input/message-input.tsx | 26 +-- 17 files changed, 193 insertions(+), 245 deletions(-) rename frontend/src/app/(dashboard)/agents/{new => config}/[agentId]/layout.tsx (100%) rename frontend/src/app/(dashboard)/agents/{new => config}/[agentId]/page.tsx (98%) rename frontend/src/app/(dashboard)/agents/{new => config}/[agentId]/workflow/[workflowId]/page.tsx (100%) rename frontend/src/app/(dashboard)/agents/{new => config}/[agentId]/workflow/layout.tsx (100%) delete mode 100644 frontend/src/components/thread/chat-input/agent-selector.tsx diff --git a/frontend/src/app/(dashboard)/agents/_components/agent-builder-chat.tsx b/frontend/src/app/(dashboard)/agents/_components/agent-builder-chat.tsx index d120d84e..e16bcb59 100644 --- a/frontend/src/app/(dashboard)/agents/_components/agent-builder-chat.tsx +++ b/frontend/src/app/(dashboard)/agents/_components/agent-builder-chat.tsx @@ -1,7 +1,6 @@ 'use client'; import React, { useState, useEffect, useCallback, useRef } from 'react'; -import { Loader2 } from 'lucide-react'; import { ChatInput, ChatInputHandles } from '@/components/thread/chat-input/chat-input'; import { ThreadContent } from '@/components/thread/content/ThreadContent'; import { useAgentStream } from '@/hooks/useAgentStream'; @@ -11,10 +10,6 @@ import { useInitiateAgentWithInvalidation } from '@/hooks/react-query/dashboard/ import { useAgentBuilderChatHistory } from '@/hooks/react-query/agents/use-agents'; import { toast } from 'sonner'; import { UnifiedMessage } from '@/components/thread/types'; -import { StylePicker } from './style-picker'; -import { EditableText } from '@/components/ui/editable'; -import { Badge } from '@/components/ui/badge'; -import { Check, Clock } from 'lucide-react'; import { BillingError } from '@/lib/api'; import { useQueryClient } from '@tanstack/react-query'; import { agentKeys } from '@/hooks/react-query/agents/keys'; @@ -387,7 +382,7 @@ export const AgentBuilderChat = React.memo(function AgentBuilderChat({
🤖
-

Lets start with a brief description of what you'd like to build

+

I'm your Agent Builder. Describe the exact workflows and tasks you want to automate, and I'll configure your agent to handle them.

} /> diff --git a/frontend/src/app/(dashboard)/agents/_components/agent-preview.tsx b/frontend/src/app/(dashboard)/agents/_components/agent-preview.tsx index c64d52e3..310c1d75 100644 --- a/frontend/src/app/(dashboard)/agents/_components/agent-preview.tsx +++ b/frontend/src/app/(dashboard)/agents/_components/agent-preview.tsx @@ -359,7 +359,8 @@ export const AgentPreview = ({ agent }: AgentPreviewProps) => {
{avatar}
-

Start conversation with your new agent {agent.name}

+

Start conversation with your new agent {agent.name}

+

Test your agent's configuration and chat back and forth to see how it performs with your current settings, tools, and knowledge base.

} /> @@ -381,6 +382,10 @@ export const AgentPreview = ({ agent }: AgentPreviewProps) => { agentName={agent.name} hideAttachments={false} bgColor='bg-muted-foreground/10' + selectedAgentId={agent.agent_id} + onAgentSelect={() => { + toast.info("You can only test the agent you are currently configuring"); + }} /> diff --git a/frontend/src/app/(dashboard)/agents/_components/agents-grid.tsx b/frontend/src/app/(dashboard)/agents/_components/agents-grid.tsx index ef7d21b5..2623e1fa 100644 --- a/frontend/src/app/(dashboard)/agents/_components/agents-grid.tsx +++ b/frontend/src/app/(dashboard)/agents/_components/agents-grid.tsx @@ -194,7 +194,7 @@ export const AgentsGrid = ({ }; const handleCustomize = (agentId: string) => { - router.push(`/agents/new/${agentId}`); + router.push(`/agents/config/${agentId}`); setSelectedAgent(null); }; diff --git a/frontend/src/app/(dashboard)/agents/_components/mcp/mcp-configuration-new.tsx b/frontend/src/app/(dashboard)/agents/_components/mcp/mcp-configuration-new.tsx index 76f77115..a0668ec2 100644 --- a/frontend/src/app/(dashboard)/agents/_components/mcp/mcp-configuration-new.tsx +++ b/frontend/src/app/(dashboard)/agents/_components/mcp/mcp-configuration-new.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react'; import { Button } from '@/components/ui/button'; import { Plus, Settings, Zap, Code2, Server, Store } from 'lucide-react'; -import { Dialog, DialogContent } from '@/components/ui/dialog'; +import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { MCPConfigurationProps, MCPConfiguration as MCPConfigurationType } from './types'; import { ConfiguredMcpList } from './configured-mcp-list'; import { CustomMCPDialog } from './custom-mcp-dialog'; @@ -155,6 +155,9 @@ export const MCPConfigurationNew: React.FC = ({ )} + + Select Integration + diff --git a/frontend/src/app/(dashboard)/agents/_components/results-info.tsx b/frontend/src/app/(dashboard)/agents/_components/results-info.tsx index 12c8830e..81aad40e 100644 --- a/frontend/src/app/(dashboard)/agents/_components/results-info.tsx +++ b/frontend/src/app/(dashboard)/agents/_components/results-info.tsx @@ -51,7 +51,7 @@ export const ResultsInfo = ({ }; const newAgent = await createAgentMutation.mutateAsync(defaultAgentData); - router.push(`/agents/new/${newAgent.agent_id}`); + router.push(`/agents/config/${newAgent.agent_id}`); } catch (error) { console.error('Error creating agent:', error); } diff --git a/frontend/src/app/(dashboard)/agents/new/[agentId]/layout.tsx b/frontend/src/app/(dashboard)/agents/config/[agentId]/layout.tsx similarity index 100% rename from frontend/src/app/(dashboard)/agents/new/[agentId]/layout.tsx rename to frontend/src/app/(dashboard)/agents/config/[agentId]/layout.tsx diff --git a/frontend/src/app/(dashboard)/agents/new/[agentId]/page.tsx b/frontend/src/app/(dashboard)/agents/config/[agentId]/page.tsx similarity index 98% rename from frontend/src/app/(dashboard)/agents/new/[agentId]/page.tsx rename to frontend/src/app/(dashboard)/agents/config/[agentId]/page.tsx index 1c89e368..03edb965 100644 --- a/frontend/src/app/(dashboard)/agents/new/[agentId]/page.tsx +++ b/frontend/src/app/(dashboard)/agents/config/[agentId]/page.tsx @@ -294,12 +294,12 @@ export default function AgentConfigurationPage() {
- Agent Builder - + Prompt to configure + {/* Beta - + */} - Manual + Config
diff --git a/frontend/src/app/(dashboard)/agents/new/[agentId]/workflow/[workflowId]/page.tsx b/frontend/src/app/(dashboard)/agents/config/[agentId]/workflow/[workflowId]/page.tsx similarity index 100% rename from frontend/src/app/(dashboard)/agents/new/[agentId]/workflow/[workflowId]/page.tsx rename to frontend/src/app/(dashboard)/agents/config/[agentId]/workflow/[workflowId]/page.tsx diff --git a/frontend/src/app/(dashboard)/agents/new/[agentId]/workflow/layout.tsx b/frontend/src/app/(dashboard)/agents/config/[agentId]/workflow/layout.tsx similarity index 100% rename from frontend/src/app/(dashboard)/agents/new/[agentId]/workflow/layout.tsx rename to frontend/src/app/(dashboard)/agents/config/[agentId]/workflow/layout.tsx diff --git a/frontend/src/app/(dashboard)/agents/page.tsx b/frontend/src/app/(dashboard)/agents/page.tsx index 309d595d..dd086a60 100644 --- a/frontend/src/app/(dashboard)/agents/page.tsx +++ b/frontend/src/app/(dashboard)/agents/page.tsx @@ -184,7 +184,7 @@ export default function AgentsPage() { }; const newAgent = await createAgentMutation.mutateAsync(defaultAgentData); - router.push(`/agents/new/${newAgent.agent_id}`); + router.push(`/agents/config/${newAgent.agent_id}`); } catch (error) { console.error('Error creating agent:', error); } diff --git a/frontend/src/app/(dashboard)/dashboard/_components/dashboard-content.tsx b/frontend/src/app/(dashboard)/dashboard/_components/dashboard-content.tsx index aa460ca4..3c396630 100644 --- a/frontend/src/app/(dashboard)/dashboard/_components/dashboard-content.tsx +++ b/frontend/src/app/(dashboard)/dashboard/_components/dashboard-content.tsx @@ -237,6 +237,8 @@ export function DashboardContent() { hideAttachments={false} selectedAgentId={selectedAgentId} onAgentSelect={setSelectedAgentId} + enableAdvancedConfig={true} + onConfigureAgent={(agentId) => router.push(`/agents/config/${agentId}`)} /> diff --git a/frontend/src/components/agents/triggers/agent-triggers-configuration.tsx b/frontend/src/components/agents/triggers/agent-triggers-configuration.tsx index 514a4a43..697a8de7 100644 --- a/frontend/src/components/agents/triggers/agent-triggers-configuration.tsx +++ b/frontend/src/components/agents/triggers/agent-triggers-configuration.tsx @@ -16,7 +16,6 @@ import { useTriggerProviders } from '@/hooks/react-query/triggers'; import { toast } from 'sonner'; -import { getTriggerIcon } from './utils'; import { OneClickIntegrations } from './one-click-integrations'; interface AgentTriggersConfigurationProps { diff --git a/frontend/src/components/agents/workflows/agent-workflows-configuration.tsx b/frontend/src/components/agents/workflows/agent-workflows-configuration.tsx index 5fec133b..657cd893 100644 --- a/frontend/src/components/agents/workflows/agent-workflows-configuration.tsx +++ b/frontend/src/components/agents/workflows/agent-workflows-configuration.tsx @@ -57,7 +57,7 @@ export function AgentWorkflowsConfiguration({ agentId, agentName }: AgentWorkflo agentId, workflow: defaultWorkflow }); - router.push(`/agents/new/${agentId}/workflow/${newWorkflow.id}`); + router.push(`/agents/config/${agentId}/workflow/${newWorkflow.id}`); } catch (error) { toast.error('Failed to create workflow'); } @@ -77,7 +77,7 @@ export function AgentWorkflowsConfiguration({ agentId, agentName }: AgentWorkflo }, []); const handleWorkflowClick = useCallback((workflowId: string) => { - router.push(`/agents/new/${agentId}/workflow/${workflowId}`); + router.push(`/agents/config/${agentId}/workflow/${workflowId}`); }, [agentId, router]); const handleDeleteWorkflow = useCallback((workflow: AgentWorkflow) => { diff --git a/frontend/src/components/thread/chat-input/agent-selector.tsx b/frontend/src/components/thread/chat-input/agent-selector.tsx deleted file mode 100644 index 9f721b12..00000000 --- a/frontend/src/components/thread/chat-input/agent-selector.tsx +++ /dev/null @@ -1,138 +0,0 @@ -'use client'; - -import React, { useEffect, useState } from 'react'; -import { Check, ChevronsUpDown, Plus, Bot } from 'lucide-react'; -import { cn } from '@/lib/utils'; -import { Button } from '@/components/ui/button'; -import { - Command, - CommandEmpty, - CommandGroup, - CommandInput, - CommandItem, - CommandList, -} from '@/components/ui/command'; -import { - Popover, - PopoverContent, - PopoverTrigger, -} from '@/components/ui/popover'; -import { useAgents } from '@/hooks/react-query/agents/use-agents'; -import { Badge } from '@/components/ui/badge'; -import { useRouter } from 'next/navigation'; - -interface AgentSelectorProps { - selectedAgentId?: string; - onAgentSelect: (agentId: string | undefined) => void; - disabled?: boolean; - className?: string; -} - -export function AgentSelector({ - selectedAgentId, - onAgentSelect, - disabled = false, - className, -}: AgentSelectorProps) { - const [open, setOpen] = useState(false); - const router = useRouter(); - - const { data: agentsResponse, isLoading } = useAgents({ - limit: 100, - sort_by: 'name', - sort_order: 'asc' - }); - - const agents = agentsResponse?.agents || []; - - const selectedAgent = agents?.find(a => a.agent_id === selectedAgentId); - const defaultAgent = agents?.find(a => a.is_default); - - useEffect(() => { - if (!selectedAgentId && defaultAgent && !isLoading) { - onAgentSelect(defaultAgent.agent_id); - } - }, [selectedAgentId, defaultAgent, isLoading, onAgentSelect]); - - const handleCreateNew = () => { - setOpen(false); - router.push('/agents'); - }; - - return ( - - - - - - - - - No agents found. - - {agents?.map((agent) => ( - { - onAgentSelect(agent.agent_id); - setOpen(false); - }} - > - -
-
- {agent.name} - {agent.is_default && ( - - Default - - )} -
- {agent.description && ( -

- {agent.description} -

- )} -
-
- ))} -
- - - - Create new agent - - -
-
-
-
- ); -} \ No newline at end of file diff --git a/frontend/src/components/thread/chat-input/chat-input.tsx b/frontend/src/components/thread/chat-input/chat-input.tsx index f41c200f..332b0ec5 100644 --- a/frontend/src/components/thread/chat-input/chat-input.tsx +++ b/frontend/src/components/thread/chat-input/chat-input.tsx @@ -7,17 +7,16 @@ import React, { forwardRef, useImperativeHandle, } from 'react'; -import { motion } from 'framer-motion'; -import { Loader2, X } from 'lucide-react'; import { Card, CardContent } from '@/components/ui/card'; import { handleFiles } from './file-upload-handler'; import { MessageInput } from './message-input'; import { AttachmentGroup } from '../attachment-group'; import { useModelSelection } from './_use-model-selection'; -import { AgentSelector } from './agent-selector'; import { useFileDelete } from '@/hooks/react-query/files'; import { useQueryClient } from '@tanstack/react-query'; import { FloatingToolPreview, ToolCallInput } from './floating-tool-preview'; +import { Settings2, Sparkles, Brain, ChevronRight, Zap, Workflow } from 'lucide-react'; +import { Button } from '@/components/ui/button'; export interface ChatInputHandles { getPendingFiles: () => File[]; @@ -50,6 +49,8 @@ export interface ChatInputProps { showToolPreview?: boolean; onExpandToolPreview?: () => void; isLoggedIn?: boolean; + enableAdvancedConfig?: boolean; + onConfigureAgent?: (agentId: string) => void; } export interface UploadedFile { @@ -85,6 +86,8 @@ export const ChatInput = forwardRef( showToolPreview = false, onExpandToolPreview, isLoggedIn = true, + enableAdvancedConfig = false, + onConfigureAgent, }, ref, ) => { @@ -244,8 +247,9 @@ export const ChatInput = forwardRef( agentName={agentName} isVisible={showToolPreview} /> + { @@ -267,7 +271,7 @@ export const ChatInput = forwardRef( }} >
- + ( onAgentSelect={onAgentSelect} /> + + {enableAdvancedConfig && selectedAgentId && ( +
onConfigureAgent?.(selectedAgentId)} + > +
+
+
+
+ Integrations + Integrations +
+
G
+
D
+
N
+
+
+
+
+ + Instructions + Instructions +
+
+
+ + Triggers +
+
+
+ + Workflows +
+
+
+ +
+
+ )}
diff --git a/frontend/src/components/thread/chat-input/chat-settings-dropdown.tsx b/frontend/src/components/thread/chat-input/chat-settings-dropdown.tsx index 624c1254..8ab69374 100644 --- a/frontend/src/components/thread/chat-input/chat-settings-dropdown.tsx +++ b/frontend/src/components/thread/chat-input/chat-settings-dropdown.tsx @@ -137,6 +137,12 @@ export const ChatSettingsDropdown: React.FC = ({ setIsOpen(false); }; + const handleAgentSettings = (agentId: string, e: React.MouseEvent) => { + e.stopPropagation(); + setIsOpen(false); + router.push(`/agents/config/${agentId}`); + }; + const handleSearchInputKeyDown = (e: React.KeyboardEvent) => { e.stopPropagation(); if (e.key === 'ArrowDown') { @@ -168,6 +174,65 @@ export const ChatSettingsDropdown: React.FC = ({ setDialogOpen(true); }; + const renderAgentItem = (agent: any, index: number) => { + const isSelected = agent.id === selectedAgentId; + const isHighlighted = index === highlightedIndex; + const hasSettings = agent.type === 'custom' && agent.id; + + return ( + + + + handleAgentSelect(agent.id)} + onMouseEnter={() => setHighlightedIndex(index)} + > +
+ {agent.icon} +
+
+
+ + {agent.name} + +
+ + {agent.description} + +
+
+ {hasSettings && ( + + )} + {isSelected && ( +
+ +
+ )} +
+
+
+ +

{truncateString(agent.description, 35)}

+
+
+
+ ); + }; + const agentDisplay = getAgentDisplay(); return ( @@ -180,18 +245,27 @@ export const ChatSettingsDropdown: React.FC = ({ @@ -204,15 +278,16 @@ export const ChatSettingsDropdown: React.FC = ({ -
+ {/* Search Header */} +
- + = ({ value={searchQuery} onChange={(e) => setSearchQuery(e.target.value)} onKeyDown={handleSearchInputKeyDown} - className="w-full pl-10 pr-3 py-2 text-sm bg-transparent border border-input rounded-md focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2" + className={cn( + "w-full pl-10 pr-3 py-2 text-sm bg-muted/40 border-0 rounded-xl", + "focus:outline-none focus:ring-1 focus:ring-ring focus:ring-offset-0 focus:bg-muted/60", + "placeholder:text-muted-foreground/60 transition-all duration-200" + )} />
-
+ {/* Agent List */} +
{agentsLoading ? ( -
- Loading agents... +
+
Loading agents...
) : filteredAgents.length === 0 ? ( -
- No agents found +
+ +

No agents found

+

Try adjusting your search

) : ( - filteredAgents.map((agent, index) => { - const isSelected = agent.id === selectedAgentId; - const isHighlighted = index === highlightedIndex; - - return ( - - - - handleAgentSelect(agent.id)} - onMouseEnter={() => setHighlightedIndex(index)} - > -
- {agent.icon} -
-
-
- - {agent.name} - - {agent.type === 'custom' && ( - - custom - - )} -
- - {agent.description} - -
- {isSelected && ( - - )} -
-
- -

{truncateString(agent.description, 35)}

-
-
-
- ); - }) +
+ {filteredAgents.map((agent, index) => renderAgentItem(agent, index))} +
)}
-
+ {/* Footer Actions */} +
diff --git a/frontend/src/components/thread/chat-input/message-input.tsx b/frontend/src/components/thread/chat-input/message-input.tsx index f7cb91b3..c3bbb364 100644 --- a/frontend/src/components/thread/chat-input/message-input.tsx +++ b/frontend/src/components/thread/chat-input/message-input.tsx @@ -48,6 +48,7 @@ interface MessageInputProps { refreshCustomModels?: () => void; selectedAgentId?: string; onAgentSelect?: (agentId: string | undefined) => void; + enableAdvancedConfig?: boolean; } export const MessageInput = forwardRef( @@ -84,6 +85,7 @@ export const MessageInput = forwardRef( selectedAgentId, onAgentSelect, + enableAdvancedConfig = false, }, ref, ) => { @@ -127,18 +129,7 @@ export const MessageInput = forwardRef( const renderDropdown = () => { if (isLoggedIn) { - if (!customAgentsEnabled || flagsLoading) { - return - } else { + if (enableAdvancedConfig || (customAgentsEnabled && !flagsLoading)) { return ( refreshCustomModels={refreshCustomModels} disabled={loading || (disabled && !isAgentRunning)} /> + } else { + return } } return ;