feat(automation): complete unified automation system redesign
Phase 4 completion: - Add ApprovalQueue component for managing pending approvals - Add ExecutionResult component for displaying hand/workflow results - Update Sidebar navigation to use unified AutomationPanel - Replace separate 'hands' and 'workflow' tabs with single 'automation' tab - Fix TypeScript type safety issues with unknown types in JSX expressions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,19 +5,21 @@ import { Sidebar, MainViewType } from './components/Sidebar';
|
||||
import { ChatArea } from './components/ChatArea';
|
||||
import { RightPanel } from './components/RightPanel';
|
||||
import { SettingsLayout } from './components/Settings/SettingsLayout';
|
||||
import { HandTaskPanel } from './components/HandTaskPanel';
|
||||
import { SchedulerPanel } from './components/SchedulerPanel';
|
||||
import { AutomationPanel } from './components/Automation';
|
||||
import { TeamCollaborationView } from './components/TeamCollaborationView';
|
||||
import { TeamOrchestrator } from './components/TeamOrchestrator';
|
||||
import { SwarmDashboard } from './components/SwarmDashboard';
|
||||
import { SkillMarket } from './components/SkillMarket';
|
||||
import { AgentOnboardingWizard } from './components/AgentOnboardingWizard';
|
||||
import { HandApprovalModal } from './components/HandApprovalModal';
|
||||
import { TopBar } from './components/TopBar';
|
||||
import { DetailDrawer } from './components/DetailDrawer';
|
||||
import { useGatewayStore, type HandRun } from './store/gatewayStore';
|
||||
import { useTeamStore } from './store/teamStore';
|
||||
import { useChatStore } from './store/chatStore';
|
||||
import { getStoredGatewayToken } from './lib/gateway-client';
|
||||
import { pageVariants, defaultTransition, fadeInVariants } from './lib/animations';
|
||||
import { Bot, Users, Loader2 } from 'lucide-react';
|
||||
import { Users, Loader2, Settings } from 'lucide-react';
|
||||
import { EmptyState } from './components/ui';
|
||||
import { isTauriRuntime, getLocalGatewayStatus, startLocalGateway } from './lib/tauri-gateway';
|
||||
import { useOnboarding } from './lib/use-onboarding';
|
||||
@@ -40,15 +42,16 @@ function BootstrapScreen({ status }: { status: string }) {
|
||||
function App() {
|
||||
const [view, setView] = useState<View>('main');
|
||||
const [mainContentView, setMainContentView] = useState<MainViewType>('chat');
|
||||
const [selectedHandId, setSelectedHandId] = useState<string | undefined>(undefined);
|
||||
const [selectedTeamId, setSelectedTeamId] = useState<string | undefined>(undefined);
|
||||
const [bootstrapping, setBootstrapping] = useState(true);
|
||||
const [bootstrapStatus, setBootstrapStatus] = useState('Initializing...');
|
||||
const [showOnboarding, setShowOnboarding] = useState(false);
|
||||
const [showDetailDrawer, setShowDetailDrawer] = useState(false);
|
||||
|
||||
// Hand Approval state
|
||||
const [pendingApprovalRun, setPendingApprovalRun] = useState<HandRun | null>(null);
|
||||
const [showApprovalModal, setShowApprovalModal] = useState(false);
|
||||
const [teamViewMode, setTeamViewMode] = useState<'collaboration' | 'orchestrator'>('collaboration');
|
||||
|
||||
const { connect, hands, approveHand, loadHands } = useGatewayStore();
|
||||
const { activeTeam, setActiveTeam, teams } = useTeamStore();
|
||||
@@ -182,13 +185,9 @@ function App() {
|
||||
setShowOnboarding(false);
|
||||
};
|
||||
|
||||
// 当切换到非 hands 视图时清除选中的 Hand
|
||||
// 处理主视图切换
|
||||
const handleMainViewChange = (view: MainViewType) => {
|
||||
setMainContentView(view);
|
||||
if (view !== 'hands') {
|
||||
// 可选:清除选中的 Hand
|
||||
// setSelectedHandId(undefined);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSelectTeam = (teamId: string) => {
|
||||
@@ -227,84 +226,120 @@ function App() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="h-screen flex overflow-hidden text-gray-800 text-sm">
|
||||
<div className="h-screen flex overflow-hidden text-gray-800 text-sm bg-white dark:bg-gray-950">
|
||||
{/* 左侧边栏 */}
|
||||
<Sidebar
|
||||
onOpenSettings={() => setView('settings')}
|
||||
onMainViewChange={handleMainViewChange}
|
||||
selectedHandId={selectedHandId}
|
||||
onSelectHand={setSelectedHandId}
|
||||
selectedTeamId={selectedTeamId}
|
||||
onSelectTeam={handleSelectTeam}
|
||||
/>
|
||||
|
||||
{/* 中间区域 */}
|
||||
<AnimatePresence mode="wait">
|
||||
<motion.main
|
||||
key={mainContentView}
|
||||
variants={pageVariants}
|
||||
initial="initial"
|
||||
animate="animate"
|
||||
exit="exit"
|
||||
transition={defaultTransition}
|
||||
className="flex-1 flex flex-col bg-white relative overflow-hidden"
|
||||
>
|
||||
{mainContentView === 'hands' && selectedHandId ? (
|
||||
<HandTaskPanel
|
||||
handId={selectedHandId}
|
||||
onBack={() => setSelectedHandId(undefined)}
|
||||
/>
|
||||
) : mainContentView === 'hands' ? (
|
||||
<EmptyState
|
||||
icon={<Bot className="w-8 h-8" />}
|
||||
title="Select a Hand"
|
||||
description="Choose an autonomous capability package from the list on the left to view its task list and execution results."
|
||||
/>
|
||||
) : mainContentView === 'workflow' ? (
|
||||
<motion.div
|
||||
variants={fadeInVariants}
|
||||
initial="initial"
|
||||
animate="animate"
|
||||
className="flex-1 overflow-y-auto"
|
||||
>
|
||||
<SchedulerPanel />
|
||||
</motion.div>
|
||||
) : mainContentView === 'team' ? (
|
||||
activeTeam ? (
|
||||
<TeamCollaborationView teamId={activeTeam.id} />
|
||||
) : (
|
||||
<EmptyState
|
||||
icon={<Users className="w-8 h-8" />}
|
||||
title="Select or Create a Team"
|
||||
description="Choose a team from the list on the left, or click + to create a new multi-Agent collaboration team."
|
||||
/>
|
||||
)
|
||||
) : mainContentView === 'swarm' ? (
|
||||
<motion.div
|
||||
variants={fadeInVariants}
|
||||
initial="initial"
|
||||
animate="animate"
|
||||
className="flex-1 overflow-hidden"
|
||||
>
|
||||
<SwarmDashboard />
|
||||
</motion.div>
|
||||
) : mainContentView === 'skills' ? (
|
||||
<motion.div
|
||||
variants={fadeInVariants}
|
||||
initial="initial"
|
||||
animate="animate"
|
||||
className="flex-1 overflow-hidden"
|
||||
>
|
||||
<SkillMarket />
|
||||
</motion.div>
|
||||
) : (
|
||||
<ChatArea />
|
||||
)}
|
||||
</motion.main>
|
||||
</AnimatePresence>
|
||||
{/* 主内容区 */}
|
||||
<div className="flex-1 flex flex-col overflow-hidden">
|
||||
{/* 顶部工具栏 */}
|
||||
<TopBar
|
||||
title="ZCLAW"
|
||||
onOpenDetail={() => setShowDetailDrawer(true)}
|
||||
/>
|
||||
|
||||
{/* 右侧边栏 */}
|
||||
<RightPanel />
|
||||
{/* 内容区域 */}
|
||||
<AnimatePresence mode="wait">
|
||||
<motion.main
|
||||
key={mainContentView}
|
||||
variants={pageVariants}
|
||||
initial="initial"
|
||||
animate="animate"
|
||||
exit="exit"
|
||||
transition={defaultTransition}
|
||||
className="flex-1 overflow-hidden relative"
|
||||
>
|
||||
{mainContentView === 'automation' ? (
|
||||
<motion.div
|
||||
variants={fadeInVariants}
|
||||
initial="initial"
|
||||
animate="animate"
|
||||
className="h-full overflow-y-auto"
|
||||
>
|
||||
<AutomationPanel />
|
||||
</motion.div>
|
||||
) : mainContentView === 'team' ? (
|
||||
activeTeam ? (
|
||||
<div className="h-full flex flex-col">
|
||||
{/* Team View Tabs */}
|
||||
<div className="flex border-b border-gray-200 dark:border-gray-700 px-4">
|
||||
<button
|
||||
onClick={() => setTeamViewMode('collaboration')}
|
||||
className={`flex items-center gap-1.5 px-4 py-2.5 text-sm font-medium border-b-2 transition-colors ${
|
||||
teamViewMode === 'collaboration'
|
||||
? 'text-orange-600 dark:text-orange-400 border-orange-500'
|
||||
: 'text-gray-500 dark:text-gray-400 border-transparent hover:text-gray-700 dark:hover:text-gray-300'
|
||||
}`}
|
||||
>
|
||||
<Users className="w-4 h-4" />
|
||||
协作视图
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setTeamViewMode('orchestrator')}
|
||||
className={`flex items-center gap-1.5 px-4 py-2.5 text-sm font-medium border-b-2 transition-colors ${
|
||||
teamViewMode === 'orchestrator'
|
||||
? 'text-orange-600 dark:text-orange-400 border-orange-500'
|
||||
: 'text-gray-500 dark:text-gray-400 border-transparent hover:text-gray-700 dark:hover:text-gray-300'
|
||||
}`}
|
||||
>
|
||||
<Settings className="w-4 h-4" />
|
||||
编排管理
|
||||
</button>
|
||||
</div>
|
||||
{/* Tab Content */}
|
||||
<div className="flex-1 overflow-hidden">
|
||||
{teamViewMode === 'orchestrator' ? (
|
||||
<TeamOrchestrator isOpen={true} onClose={() => setTeamViewMode('collaboration')} />
|
||||
) : (
|
||||
<TeamCollaborationView teamId={activeTeam.id} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<EmptyState
|
||||
icon={<Users className="w-8 h-8" />}
|
||||
title="选择或创建团队"
|
||||
description="从左侧列表中选择一个团队,或点击 + 创建新的多 Agent 协作团队。"
|
||||
/>
|
||||
)
|
||||
) : mainContentView === 'swarm' ? (
|
||||
<motion.div
|
||||
variants={fadeInVariants}
|
||||
initial="initial"
|
||||
animate="animate"
|
||||
className="h-full overflow-hidden"
|
||||
>
|
||||
<SwarmDashboard />
|
||||
</motion.div>
|
||||
) : mainContentView === 'skills' ? (
|
||||
<motion.div
|
||||
variants={fadeInVariants}
|
||||
initial="initial"
|
||||
animate="animate"
|
||||
className="h-full overflow-hidden"
|
||||
>
|
||||
<SkillMarket />
|
||||
</motion.div>
|
||||
) : (
|
||||
<ChatArea />
|
||||
)}
|
||||
</motion.main>
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
|
||||
{/* 详情抽屉 - 按需显示 */}
|
||||
<DetailDrawer
|
||||
open={showDetailDrawer}
|
||||
onClose={() => setShowDetailDrawer(false)}
|
||||
title="详情"
|
||||
>
|
||||
<RightPanel />
|
||||
</DetailDrawer>
|
||||
|
||||
{/* Hand Approval Modal (global) */}
|
||||
<HandApprovalModal
|
||||
|
||||
Reference in New Issue
Block a user