feat: DeerFlow 2.0 core capabilities — Phase 1.0 + 1.1
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled

Phase 1.0 — Butler Mode UI:
- Hide "自动化" and "技能市场" entries from sidebar navigation
- Remove AutomationPanel and SkillMarket view rendering from App.tsx
- Simplify MainViewType to only 'chat'
- Main interface is now: chat + conversation list + detail panel only

Phase 1.1 — Mode Differentiation:
- Add subagent_enabled field to ChatModeConfig (Rust), StreamChatRequest (Tauri),
  gateway-client, kernel-client, saas-relay-client, and streamStore
- TaskTool is now only registered when subagent_enabled=true (Ultra mode)
- System prompt includes sub-agent delegation instructions only in Ultra mode
- Frontend transmits subagent_enabled from ChatMode config through the full stack

This connects the 4-tier mode selector (Flash/Thinking/Pro/Ultra) to actual
backend behavioral differences — Ultra mode now truly enables sub-agent delegation.
This commit is contained in:
iven
2026-04-06 12:46:43 +08:00
parent 9c346ed6fb
commit cb140b5151
10 changed files with 72 additions and 105 deletions

View File

@@ -1,12 +1,9 @@
import { useState, useEffect, useCallback, useRef } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import './index.css';
import { Sidebar, MainViewType } from './components/Sidebar';
import { Sidebar } from './components/Sidebar';
import { ChatArea } from './components/ChatArea';
import { RightPanel } from './components/RightPanel';
import { SettingsLayout } from './components/Settings/SettingsLayout';
import { AutomationPanel } from './components/Automation';
import { SkillMarket } from './components/SkillMarket';
import { AgentOnboardingWizard } from './components/AgentOnboardingWizard';
import { HandApprovalModal } from './components/HandApprovalModal';
import { TopBar } from './components/TopBar';
@@ -17,7 +14,7 @@ import { useHandStore, type HandRun } from './store/handStore';
import { useChatStore } from './store/chatStore';
import { initializeStores } from './store';
import { getStoredGatewayToken } from './lib/gateway-client';
import { pageVariants, defaultTransition, fadeInVariants } from './lib/animations';
import { Loader2 } from 'lucide-react';
import { isTauriRuntime, getLocalGatewayStatus, startLocalGateway } from './lib/tauri-gateway';
import { LoginPage } from './components/LoginPage';
@@ -49,7 +46,6 @@ function BootstrapScreen({ status }: { status: string }) {
function App() {
const [view, setView] = useState<View>('main');
const [mainContentView, setMainContentView] = useState<MainViewType>('chat');
const [bootstrapping, setBootstrapping] = useState(true);
const [bootstrapStatus, setBootstrapStatus] = useState('Initializing...');
const [showOnboarding, setShowOnboarding] = useState(false);
@@ -379,11 +375,6 @@ function App() {
}
};
// 处理主视图切换
const handleMainViewChange = (view: MainViewType) => {
setMainContentView(view);
};
// 登录门禁 — 必须登录才能使用
if (isRestoring) {
return <BootstrapScreen status="Restoring session..." />;
@@ -457,7 +448,6 @@ function App() {
{/* 左侧边栏 */}
<Sidebar
onOpenSettings={() => setView('settings')}
onMainViewChange={handleMainViewChange}
/>
{/* 主内容区 */}
@@ -468,62 +458,8 @@ function App() {
onOpenDetail={() => setShowDetailDrawer(true)}
/>
{/* 内容区域 */}
<AnimatePresence mode="wait">
<motion.main
key={mainContentView}
variants={pageVariants}
initial="initial"
animate="animate"
exit="exit"
transition={defaultTransition}
className="flex-1 overflow-hidden relative flex flex-col"
>
{mainContentView === 'automation' ? (
<motion.div
variants={fadeInVariants}
initial="initial"
animate="animate"
className="h-full overflow-y-auto"
>
<div className="sticky top-0 z-10 flex items-center gap-2 px-4 py-2 bg-white/80 dark:bg-gray-900/80 backdrop-blur-sm border-b border-gray-200 dark:border-gray-800">
<button
onClick={() => handleMainViewChange('chat')}
className="p-1.5 hover:bg-black/5 dark:hover:bg-white/5 rounded-md transition-colors text-gray-600 dark:text-gray-400"
title="返回聊天"
>
<svg xmlns="http://www.w3.org/2000/svg" className="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="m15 18-6-6 6-6"/></svg>
</button>
<span className="text-sm font-medium text-gray-900 dark:text-gray-100"></span>
</div>
<AutomationPanel />
</motion.div>
) : mainContentView === 'skills' ? (
<motion.div
variants={fadeInVariants}
initial="initial"
animate="animate"
className="h-full overflow-hidden"
>
<div className="flex items-center gap-2 px-4 py-2 border-b border-gray-200 dark:border-gray-800">
<button
onClick={() => handleMainViewChange('chat')}
className="p-1.5 hover:bg-black/5 dark:hover:bg-white/5 rounded-md transition-colors text-gray-600 dark:text-gray-400"
title="返回聊天"
>
<svg xmlns="http://www.w3.org/2000/svg" className="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="m15 18-6-6 6-6"/></svg>
</button>
<span className="text-sm font-medium text-gray-900 dark:text-gray-100"></span>
</div>
<div className="h-[calc(100%-40px)] overflow-auto">
<SkillMarket />
</div>
</motion.div>
) : (
<ChatArea />
)}
</motion.main>
</AnimatePresence>
{/* 聊天区域 */}
<ChatArea />
</div>
{/* 详情抽屉 - 按需显示 */}