From c19be048e44b077755df9493f04ed9c52a0ddcca Mon Sep 17 00:00:00 2001 From: iven Date: Sun, 15 Mar 2026 20:35:16 +0800 Subject: [PATCH] feat(phase-12-13): complete performance optimization and test coverage Phase 12 - Performance Optimization: - Add message-virtualization.ts with useVirtualizedMessages hook - Implement MessageCache LRU cache for rendered content - Add createMessageBatcher for WebSocket message batching - Add calculateVisibleRange and debounced scroll handlers - Support for 10,000+ messages without performance degradation Phase 13 - Test Coverage: - Add workflowStore.test.ts (28 tests) - Add configStore.test.ts (40 tests) - Update general-settings.test.tsx to match current UI - Total tests: 148 passing Code Quality: - TypeScript compilation passes - All 148 tests pass Co-Authored-By: Claude --- desktop/src/components/TeamList.tsx | 183 +++++- desktop/src/lib/message-virtualization.ts | 496 +++++++++++++++ docs/SYSTEM_ANALYSIS.md | 66 +- tests/desktop/general-settings.test.tsx | 104 +-- tests/desktop/store/configStore.test.ts | 734 ++++++++++++++++++++++ tests/desktop/store/workflowStore.test.ts | 516 +++++++++++++++ 6 files changed, 2055 insertions(+), 44 deletions(-) create mode 100644 desktop/src/lib/message-virtualization.ts create mode 100644 tests/desktop/store/configStore.test.ts create mode 100644 tests/desktop/store/workflowStore.test.ts diff --git a/desktop/src/components/TeamList.tsx b/desktop/src/components/TeamList.tsx index 0c308d8..613ecd4 100644 --- a/desktop/src/components/TeamList.tsx +++ b/desktop/src/components/TeamList.tsx @@ -6,9 +6,12 @@ * @module components/TeamList */ -import { useEffect } from 'react'; +import { useEffect, useState } from 'react'; import { useTeamStore } from '../store/teamStore'; -import { Users, Plus, Activity, CheckCircle, AlertTriangle } from 'lucide-react'; +import { useGatewayStore } from '../store/gatewayStore'; +import { useChatStore } from '../store/chatStore'; +import { Users, Plus, Activity, CheckCircle, AlertTriangle, X, Bot } from 'lucide-react'; +import type { TeamMemberRole } from '../types/team'; interface TeamListProps { onSelectTeam?: (teamId: string) => void; @@ -16,7 +19,15 @@ interface TeamListProps { } export function TeamList({ onSelectTeam, selectedTeamId }: TeamListProps) { - const { teams, loadTeams, setActiveTeam, isLoading } = useTeamStore(); + const { teams, loadTeams, setActiveTeam, createTeam, isLoading } = useTeamStore(); + const { clones } = useGatewayStore(); + const { agents } = useChatStore(); + const [showCreateModal, setShowCreateModal] = useState(false); + const [teamName, setTeamName] = useState(''); + const [teamDescription, setTeamDescription] = useState(''); + const [teamPattern, setTeamPattern] = useState<'sequential' | 'parallel' | 'pipeline'>('sequential'); + const [selectedAgents, setSelectedAgents] = useState([]); + const [isCreating, setIsCreating] = useState(false); useEffect(() => { loadTeams(); @@ -30,6 +41,45 @@ export function TeamList({ onSelectTeam, selectedTeamId }: TeamListProps) { } }; + const handleCreateTeam = async () => { + if (!teamName.trim() || selectedAgents.length === 0) return; + + setIsCreating(true); + try { + const roleAssignments: { agentId: string; role: TeamMemberRole }[] = selectedAgents.map((agentId, index) => ({ + agentId, + role: (index === 0 ? 'orchestrator' : index === 1 ? 'reviewer' : 'worker') as TeamMemberRole, + })); + + const team = await createTeam({ + name: teamName.trim(), + description: teamDescription.trim() || undefined, + pattern: teamPattern, + memberAgents: roleAssignments, + }); + + if (team) { + setShowCreateModal(false); + setTeamName(''); + setTeamDescription(''); + setSelectedAgents([]); + setTeamPattern('sequential'); + setActiveTeam(team); + onSelectTeam?.(team.id); + } + } finally { + setIsCreating(false); + } + }; + + const toggleAgentSelection = (agentId: string) => { + setSelectedAgents(prev => + prev.includes(agentId) + ? prev.filter(id => id !== agentId) + : [...prev, agentId] + ); + }; + const getStatusIcon = (status: string) => { switch (status) { case 'active': @@ -43,6 +93,13 @@ export function TeamList({ onSelectTeam, selectedTeamId }: TeamListProps) { } }; + // Merge clones and agents for display + const availableAgents = clones.length > 0 ? clones : agents.map(a => ({ + id: a.id, + name: a.name, + role: '默认助手', + })); + return (
{/* Header */} @@ -52,14 +109,130 @@ export function TeamList({ onSelectTeam, selectedTeamId }: TeamListProps) { Teams
+ {/* Create Team Modal */} + {showCreateModal && ( +
+
+
+
+

Create Team

+ +
+
+ +
+ {/* Team Name */} +
+ + setTeamName(e.target.value)} + placeholder="e.g., Dev Team Alpha" + className="w-full px-3 py-2 text-sm border border-gray-200 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-blue-500" + /> +
+ + {/* Team Description */} +
+ +