From bbd9f0f2e63b312404d5575151d3ddf85125261a Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 24 Feb 2026 21:49:48 +0000 Subject: [PATCH] style: align agent wizard UI with existing product design patterns - Replace indigo palette with blue (blue-500/600) to match MCP/agent pages - Remove all emojis from UI elements - Use Tremor TextInput + Button, Ant Design Form.Item with InfoCircleOutlined tooltips - Use Ant Design Switch instead of Checkbox for tool/skill toggles - Match label styling (text-sm font-medium text-gray-700) from create_mcp_server.tsx - Match modal pattern (width 900, header with border-b, 24px padding) - Use border-t border-gray-200 section dividers like MCP form - Use KeyOutlined, CopyOutlined, CheckCircleOutlined icons instead of emoji Co-authored-by: Ishaan Jaff --- .../components/agents/add_agent_wizard.tsx | 401 +++++++----------- 1 file changed, 161 insertions(+), 240 deletions(-) diff --git a/ui/litellm-dashboard/src/components/agents/add_agent_wizard.tsx b/ui/litellm-dashboard/src/components/agents/add_agent_wizard.tsx index 23519e218b5..1c0df7d7d7e 100644 --- a/ui/litellm-dashboard/src/components/agents/add_agent_wizard.tsx +++ b/ui/litellm-dashboard/src/components/agents/add_agent_wizard.tsx @@ -1,6 +1,7 @@ import React, { useState, useEffect } from "react"; -import { Modal, Form, message, Select, Input, InputNumber, Switch, Checkbox } from "antd"; -import { Button } from "@tremor/react"; +import { Modal, Form, message, Select, Input, InputNumber, Tooltip, Switch } from "antd"; +import { Button, TextInput } from "@tremor/react"; +import { InfoCircleOutlined, CheckCircleOutlined, CopyOutlined, KeyOutlined } from "@ant-design/icons"; import { createAgentCall, getAgentCreateMetadata, @@ -9,11 +10,7 @@ import { } from "../networking"; import { getDefaultFormValues, buildAgentDataFromForm } from "./agent_config"; import { buildDynamicAgentData } from "./dynamic_agent_form_fields"; -import { - CheckCircleIcon, - ClipboardCopyIcon, - InformationCircleIcon, -} from "@heroicons/react/outline"; +import { CheckCircleIcon } from "@heroicons/react/outline"; const WIZARD_STEPS = [ { key: 1, label: "Configure" }, @@ -23,36 +20,11 @@ const WIZARD_STEPS = [ ]; const AVAILABLE_TOOLS = [ - { - id: "web_search", - name: "Web Search", - description: "Search the internet for real-time info", - icon: "๐ŸŒ", - }, - { - id: "code_interpreter", - name: "Code Interpreter", - description: "Execute Python/JS code in a sandbox", - icon: "" - }, - { - id: "http_request", - name: "HTTP Request", - description: "Make outbound API calls", - icon: "โšก", - }, - { - id: "file_reader", - name: "File Reader", - description: "Read and parse uploaded files", - icon: "๐Ÿ“„", - }, - { - id: "database_query", - name: "Database Query", - description: "Run read-only SQL queries", - icon: "๐Ÿ—ƒ๏ธ", - }, + { id: "web_search", name: "Web Search", description: "Search the internet for real-time info" }, + { id: "code_interpreter", name: "Code Interpreter", description: "Execute Python/JS code in a sandbox" }, + { id: "http_request", name: "HTTP Request", description: "Make outbound API calls" }, + { id: "file_reader", name: "File Reader", description: "Read and parse uploaded files" }, + { id: "database_query", name: "Database Query", description: "Run read-only SQL queries" }, ]; const AVAILABLE_SKILLS = [ @@ -92,9 +64,9 @@ const StepIndicator: React.FC<{ currentStep: number }> = ({ currentStep }) => (
@@ -107,7 +79,7 @@ const StepIndicator: React.FC<{ currentStep: number }> = ({ currentStep }) => ( @@ -117,7 +89,7 @@ const StepIndicator: React.FC<{ currentStep: number }> = ({ currentStep }) => ( {idx < WIZARD_STEPS.length - 1 && (
)} @@ -133,20 +105,17 @@ const ToolCard: React.FC<{ }> = ({ tool, selected, onToggle }) => (
-
- {tool.icon} -
-
{tool.name}
-
{tool.description}
-
+
+
{tool.name}
+
{tool.description}
- +
); @@ -157,15 +126,15 @@ const SkillCard: React.FC<{ }> = ({ skill, selected, onToggle }) => (
{skill.name} - +
{skill.description}
@@ -186,16 +155,13 @@ const AddAgentWizard: React.FC = ({ const [agentType, setAgentType] = useState("a2a"); const [agentTypeMetadata, setAgentTypeMetadata] = useState([]); - // Step 2 state const [maxIterations, setMaxIterations] = useState(10); const [selectedTools, setSelectedTools] = useState([]); const [selectedSkills, setSelectedSkills] = useState([]); - // Step 3 state const [keyOption, setKeyOption] = useState<"create" | "existing" | "skip">("create"); const [keyName, setKeyName] = useState("new-agent-key"); - // Step 4 state const [createdAgent, setCreatedAgent] = useState(null); useEffect(() => { @@ -238,17 +204,13 @@ const AddAgentWizard: React.FC = ({ const toggleTool = (toolId: string) => { setSelectedTools((prev) => - prev.includes(toolId) - ? prev.filter((t) => t !== toolId) - : [...prev, toolId] + prev.includes(toolId) ? prev.filter((t) => t !== toolId) : [...prev, toolId] ); }; const toggleSkill = (skillId: string) => { setSelectedSkills((prev) => - prev.includes(skillId) - ? prev.filter((s) => s !== skillId) - : [...prev, skillId] + prev.includes(skillId) ? prev.filter((s) => s !== skillId) : [...prev, skillId] ); }; @@ -305,14 +267,12 @@ const AddAgentWizard: React.FC = ({ agentData = buildDynamicAgentData(values, selectedAgentTypeInfo); } - // Attach capabilities metadata if (!agentData.litellm_params) { agentData.litellm_params = {}; } agentData.litellm_params.max_iterations = maxIterations; agentData.litellm_params.tools = selectedTools; - // Merge selected skills into agent_card_params.skills const existingSkills = agentData.agent_card_params?.skills || []; const wizardSkills = selectedSkills.map((skillId) => { const skillDef = AVAILABLE_SKILLS.find((s) => s.id === skillId); @@ -324,15 +284,11 @@ const AddAgentWizard: React.FC = ({ }; }); if (agentData.agent_card_params) { - agentData.agent_card_params.skills = [ - ...existingSkills, - ...wizardSkills, - ]; + agentData.agent_card_params.skills = [...existingSkills, ...wizardSkills]; } const response = await createAgentCall(accessToken, agentData); - // Create key if requested let createdKeyName: string | undefined; let createdKeyValue: string | undefined; if (keyOption === "create" && keyName.trim()) { @@ -379,16 +335,23 @@ const AddAgentWizard: React.FC = ({ }; const renderStep1 = () => ( -
+
Agent Type} + label={ + + Agent Type + + + + + } required - tooltip="Select the type of agent you want to create" > + = ({ name="name" rules={[{ required: true, message: "Please enter a display name" }]} > - + = ({ name="description" rules={[{ required: true, message: "Please enter a description" }]} > - + URL} + label={ + + URL + + + + + } name="url" rules={[{ required: true, message: "Please enter the agent URL" }]} - tooltip="Base URL where the agent is hosted" > - +
); @@ -466,13 +447,13 @@ const AddAgentWizard: React.FC = ({ {/* Max Iterations */}
-
- Max Iterations - -
- - How many reasoning loops before the agent stops + + Max Iterations + + + + Range: 1โ€“100
@@ -507,7 +488,7 @@ const AddAgentWizard: React.FC = ({ onClick={() => setMaxIterations(preset)} className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${ maxIterations === preset - ? "bg-indigo-600 text-white" + ? "bg-blue-600 text-white" : "bg-gray-100 text-gray-700 hover:bg-gray-200" }`} > @@ -515,18 +496,17 @@ const AddAgentWizard: React.FC = ({ ))}
-

- Range: 1โ€“100. Lower values reduce cost; higher values allow more complex tasks. -

{/* Tools */} -
+
-
- Tools - -
+ + Tools + + + + {selectedTools.length} selected
@@ -542,15 +522,15 @@ const AddAgentWizard: React.FC = ({
{/* Skills */} -
+
-
- Skills - -
- - {selectedSkills.length} selected + + Skills + + + + {selectedSkills.length} selected
{AVAILABLE_SKILLS.map((skill) => ( @@ -571,61 +551,51 @@ const AddAgentWizard: React.FC = ({ return (
- - ๐Ÿค– {agentName} + + {agentName}
{/* Create new key */}
setKeyOption("create")} - className={`p-5 rounded-xl border-2 cursor-pointer transition-all ${ - keyOption === "create" - ? "border-indigo-500 bg-indigo-50/30" - : "border-gray-200 hover:border-gray-300" + className={`p-5 rounded-lg border cursor-pointer transition-all ${ + keyOption === "create" ? "border-blue-500 bg-blue-50" : "border-gray-200 hover:border-gray-300" }`} >
- {keyOption === "create" && ( -
- )} + {keyOption === "create" &&
}
- ๐Ÿ”‘ - - Create a new key for this agent - - + + Create a new key for this agent + Recommended
-

+

A dedicated key scoped to this agent. Recommended for production.

{keyOption === "create" && ( -
+
- setKeyName(e.target.value)} placeholder="new-agent-key" - className="mt-1" + className="mt-1 rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500" />
- +
)} @@ -636,28 +606,24 @@ const AddAgentWizard: React.FC = ({ {/* Assign existing key */}
setKeyOption("existing")} - className={`p-5 rounded-xl border-2 cursor-pointer transition-all ${ - keyOption === "existing" - ? "border-indigo-500 bg-indigo-50/30" - : "border-gray-200 hover:border-gray-300" + className={`p-5 rounded-lg border cursor-pointer transition-all ${ + keyOption === "existing" ? "border-blue-500 bg-blue-50" : "border-gray-200 hover:border-gray-300" }`} >
- {keyOption === "existing" && ( -
- )} + {keyOption === "existing" &&
}
- ๐Ÿ” - Assign an existing key + + Assign an existing key
-

+

Link a key you've already created.

@@ -669,8 +635,8 @@ const AddAgentWizard: React.FC = ({ + + copyToClipboard(createdAgent.key_value!)} + className="cursor-pointer text-gray-400 hover:text-blue-500" + /> +
)}

- Active & ready + Active & ready

)}
- -
@@ -791,35 +725,25 @@ const AddAgentWizard: React.FC = ({ const getStepContent = () => { switch (currentStep) { - case 1: - return renderStep1(); - case 2: - return renderStep2(); - case 3: - return renderStep3(); - case 4: - return renderStep4(); - default: - return null; + case 1: return renderStep1(); + case 2: return renderStep2(); + case 3: return renderStep3(); + case 4: return renderStep4(); + default: return null; } }; - const getNextButtonText = () => { - if (currentStep === 3) return isSubmitting ? "Creating..." : "Create Agent"; - return "Next"; - }; - return ( +

Add New Agent

} open={visible} onCancel={handleClose} footer={null} - width={720} + width={900} className="top-8" styles={{ body: { padding: "24px", maxHeight: "70vh", overflowY: "auto" }, @@ -827,34 +751,31 @@ const AddAgentWizard: React.FC = ({ }} destroyOnClose > -
+
{getStepContent()}
- {/* Footer buttons */} {currentStep < 4 && (
{currentStep > 1 && ( - )}
-
)}