From e8efca526b6a792147eeb2f41f7c74c07ab8d8ac Mon Sep 17 00:00:00 2001 From: Ulysses Date: Thu, 7 Aug 2025 10:33:31 +0700 Subject: [PATCH 1/2] fix: Fix agent modal scrolling to show all agents - Changed overflow-hidden to min-h-0 in AgentsModal to enable proper scrolling - Added max-h constraint and overflow-y-scroll to agent list container - Removed conflicting height constraints that prevented scrolling - Now all agents are visible with proper scrollbar functionality Fixes issue where users couldn't see all their agents in the modal --- src/App.tsx | 8 +++++--- src/components/AgentsModal.tsx | 34 +++++++++++++++++++++++++--------- src/components/CCAgents.tsx | 8 ++++---- 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 0d424fb7..34496134 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -293,9 +293,11 @@ function AppContent() { case "cc-agents": return ( - handleViewChange("welcome")} - /> +
+ handleViewChange("welcome")} + /> +
); case "editor": diff --git a/src/components/AgentsModal.tsx b/src/components/AgentsModal.tsx index a93d2df8..b3e7af74 100644 --- a/src/components/AgentsModal.tsx +++ b/src/components/AgentsModal.tsx @@ -1,6 +1,6 @@ import React, { useState, useEffect } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; -import { Bot, Plus, Loader2, Play, Clock, CheckCircle, XCircle, Trash2, Import, ChevronDown, FileJson, Globe, Download } from 'lucide-react'; +import { Bot, Plus, Loader2, Play, Clock, CheckCircle, XCircle, Trash2, Import, ChevronDown, FileJson, Globe, Download, Edit } from 'lucide-react'; import { Dialog, DialogContent, @@ -17,7 +17,6 @@ import { import { Tabs, TabsList, TabsTrigger, TabsContent } from '@/components/ui/tabs'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; -import { ScrollArea } from '@/components/ui/scroll-area'; import { Toast } from '@/components/ui/toast'; import { api, type Agent, type AgentRunWithMetrics } from '@/lib/api'; import { useTabState } from '@/hooks/useTabState'; @@ -135,6 +134,15 @@ export const AgentsModal: React.FC = ({ open, onOpenChange }) createCreateAgentTab(); }; + const handleEditAgent = (agent: Agent) => { + // Close modal + onOpenChange(false); + // Dispatch custom event to open edit agent tab + window.dispatchEvent(new CustomEvent('open-edit-agent-tab', { + detail: { agent } + })); + }; + const handleImportFromFile = async () => { try { const filePath = await openDialog({ @@ -197,7 +205,7 @@ export const AgentsModal: React.FC = ({ open, onOpenChange }) return ( <> - + @@ -222,10 +230,10 @@ export const AgentsModal: React.FC = ({ open, onOpenChange })
- - + +
{/* Action buttons at the top */} -
+
+
)} - +
- +
{runningAgents.length === 0 ? (
@@ -379,7 +395,7 @@ export const AgentsModal: React.FC = ({ open, onOpenChange })
)} - +
diff --git a/src/components/CCAgents.tsx b/src/components/CCAgents.tsx index 3f272fa2..1eadd8bb 100644 --- a/src/components/CCAgents.tsx +++ b/src/components/CCAgents.tsx @@ -79,7 +79,7 @@ export const CCAgents: React.FC = ({ onBack, className }) => { const [agentToDelete, setAgentToDelete] = useState(null); const [isDeleting, setIsDeleting] = useState(false); - const AGENTS_PER_PAGE = 9; // 3x3 grid + const AGENTS_PER_PAGE = 12; // Show all agents at once since we have scrolling useEffect(() => { loadAgents(); @@ -288,8 +288,8 @@ export const CCAgents: React.FC = ({ onBack, className }) => { // Removed viewRun case - now using modal preview in AgentRunsList return ( -
-
+
+
{/* Header */} = ({ onBack, className }) => { )} {/* Main Content */} -
+
Date: Thu, 7 Aug 2025 10:34:29 +0700 Subject: [PATCH 2/2] feat: Add edit functionality for agents in modal - Added Edit button to each agent in the Agent Management modal - Implemented event system to pass agent data to CreateAgent component - Modified CreateAgent to accept editing data from localStorage - Added proper cleanup of localStorage after editing Closes #259 - Users can now edit existing agents --- src/components/CreateAgent.tsx | 40 +++++++++++++++++++++++++++------- src/components/TabContent.tsx | 14 ++++++++++++ 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/src/components/CreateAgent.tsx b/src/components/CreateAgent.tsx index 3c1ffec8..1dfa1e05 100644 --- a/src/components/CreateAgent.tsx +++ b/src/components/CreateAgent.tsx @@ -43,17 +43,41 @@ export const CreateAgent: React.FC = ({ onAgentCreated, className, }) => { - const [name, setName] = useState(agent?.name || ""); - const [selectedIcon, setSelectedIcon] = useState((agent?.icon as AgentIconName) || "bot"); - const [systemPrompt, setSystemPrompt] = useState(agent?.system_prompt || ""); - const [defaultTask, setDefaultTask] = useState(agent?.default_task || ""); - const [model, setModel] = useState(agent?.model || "sonnet"); + // Check for editing agent in localStorage + const [editingAgent, setEditingAgent] = useState(() => { + if (agent) return agent; + const stored = window.localStorage.getItem('editingAgent'); + if (stored) { + // Don't remove immediately - will clean up after component mounts + return JSON.parse(stored); + } + return undefined; + }); + + // Clean up localStorage after component mounts + React.useEffect(() => { + if (editingAgent && !agent) { + // Small delay to ensure state is set + const timer = setTimeout(() => { + window.localStorage.removeItem('editingAgent'); + }, 500); + return () => clearTimeout(timer); + } + }, [editingAgent, agent]); + + const agentData = editingAgent || agent; + + const [name, setName] = useState(agentData?.name || ""); + const [selectedIcon, setSelectedIcon] = useState((agentData?.icon as AgentIconName) || "bot"); + const [systemPrompt, setSystemPrompt] = useState(agentData?.system_prompt || ""); + const [defaultTask, setDefaultTask] = useState(agentData?.default_task || ""); + const [model, setModel] = useState(agentData?.model || "sonnet"); const [saving, setSaving] = useState(false); const [error, setError] = useState(null); const [toast, setToast] = useState<{ message: string; type: "success" | "error" } | null>(null); const [showIconPicker, setShowIconPicker] = useState(false); - const isEditMode = !!agent; + const isEditMode = !!agentData; const handleSave = async () => { if (!name.trim()) { @@ -70,9 +94,9 @@ export const CreateAgent: React.FC = ({ setSaving(true); setError(null); - if (isEditMode && agent.id) { + if (isEditMode && agentData.id) { await api.updateAgent( - agent.id, + agentData.id, name, selectedIcon, systemPrompt, diff --git a/src/components/TabContent.tsx b/src/components/TabContent.tsx index cb5ca82d..34fc9e2a 100644 --- a/src/components/TabContent.tsx +++ b/src/components/TabContent.tsx @@ -357,6 +357,18 @@ export const TabContent: React.FC = () => { createImportAgentTab(); }; + const handleOpenEditAgentTab = (event: CustomEvent) => { + const { agent } = event.detail; + // Store agent in localStorage temporarily + window.localStorage.setItem('editingAgent', JSON.stringify(agent)); + // Create a new create-agent tab + const tabId = createCreateAgentTab(); + // Update the tab title to show it's editing + setTimeout(() => { + updateTab(tabId, { title: `Edit: ${agent.name}` }); + }, 100); + }; + const handleCloseTab = (event: CustomEvent) => { const { tabId } = event.detail; closeTab(tabId); @@ -387,6 +399,7 @@ export const TabContent: React.FC = () => { window.addEventListener('open-agent-execution', handleOpenAgentExecution as EventListener); window.addEventListener('open-create-agent-tab', handleOpenCreateAgentTab); window.addEventListener('open-import-agent-tab', handleOpenImportAgentTab); + window.addEventListener('open-edit-agent-tab', handleOpenEditAgentTab as EventListener); window.addEventListener('close-tab', handleCloseTab as EventListener); window.addEventListener('claude-session-selected', handleClaudeSessionSelected as EventListener); return () => { @@ -395,6 +408,7 @@ export const TabContent: React.FC = () => { window.removeEventListener('open-agent-execution', handleOpenAgentExecution as EventListener); window.removeEventListener('open-create-agent-tab', handleOpenCreateAgentTab); window.removeEventListener('open-import-agent-tab', handleOpenImportAgentTab); + window.removeEventListener('open-edit-agent-tab', handleOpenEditAgentTab as EventListener); window.removeEventListener('close-tab', handleCloseTab as EventListener); window.removeEventListener('claude-session-selected', handleClaudeSessionSelected as EventListener); };