From 3518fc8ece5b56aa6f7b6c6e4206aa4a8625dd0a Mon Sep 17 00:00:00 2001 From: iven Date: Wed, 18 Mar 2026 17:12:05 +0800 Subject: [PATCH] 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 --- desktop/src-tauri/Cargo.lock | 17 + desktop/src-tauri/Cargo.toml | 3 + desktop/src-tauri/src/lib.rs | 10 +- desktop/src/App.tsx | 191 ++++--- .../src/components/ActiveLearningPanel.tsx | 155 ++--- .../components/Automation/ApprovalQueue.tsx | 352 ++++++++++++ .../components/Automation/ExecutionResult.tsx | 395 +++++++++++++ desktop/src/components/Automation/index.ts | 2 + desktop/src/components/ChatArea.tsx | 62 +- desktop/src/components/CodeSnippetPanel.tsx | 346 +++++++++++ desktop/src/components/DetailDrawer.tsx | 56 ++ desktop/src/components/HandTaskPanel.tsx | 49 +- desktop/src/components/MemoryGraph.tsx | 36 +- desktop/src/components/RightPanel.tsx | 379 ++++++------ desktop/src/components/SchedulerPanel.tsx | 16 +- desktop/src/components/Sidebar.tsx | 157 ++--- desktop/src/components/TopBar.tsx | 53 ++ desktop/src/lib/agent-identity.ts | 15 +- desktop/src/lib/context-compactor.ts | 22 +- desktop/src/lib/gateway-client.ts | 35 +- desktop/src/lib/llm-service.ts | 55 +- desktop/src/lib/memory-extractor.ts | 10 +- desktop/src/lib/reflection-engine.ts | 26 +- desktop/src/lib/skill-discovery.ts | 29 +- desktop/src/main.tsx | 5 +- desktop/src/store/chatStore.ts | 13 +- desktop/src/store/gatewayStore.ts | 6 +- desktop/test-results/.last-run.json | 4 - .../screenshots/01-app-layout.png | Bin 75156 -> 0 bytes .../screenshots/02-connection-state.png | Bin 75156 -> 0 bytes .../screenshots/02-sidebar-navigation.png | Bin 75156 -> 0 bytes .../screenshots/03-chat-input.png | Bin 76216 -> 0 bytes .../screenshots/03-navigation-switch.png | Bin 90177 -> 0 bytes .../screenshots/04-chat-response.png | Bin 77519 -> 0 bytes .../screenshots/04-settings-access.png | Bin 64593 -> 0 bytes .../test-results/screenshots/05-chat-area.png | Bin 75156 -> 0 bytes .../screenshots/06-message-send.png | Bin 76532 -> 0 bytes .../screenshots/07-conversation-list.png | Bin 75156 -> 0 bytes .../screenshots/07-streaming-response.png | Bin 76781 -> 0 bytes .../screenshots/08-hands-list.png | Bin 75156 -> 0 bytes .../screenshots/08-offline-error.png | Bin 77312 -> 0 bytes .../screenshots/10-scheduler-panel.png | Bin 75156 -> 0 bytes .../test-results/screenshots/12-team-view.png | Bin 75156 -> 0 bytes .../screenshots/13-swarm-dashboard.png | Bin 75156 -> 0 bytes .../screenshots/14-settings-page.png | Bin 64593 -> 0 bytes .../screenshots/15-general-settings.png | Bin 64593 -> 0 bytes .../screenshots/16-model-settings.png | Bin 64593 -> 0 bytes .../screenshots/17-right-panel.png | Bin 75156 -> 0 bytes .../screenshots/17-workflow-list.png | Bin 53404 -> 0 bytes .../screenshots/18-offline-error.png | Bin 75156 -> 0 bytes .../screenshots/20-mobile-layout.png | Bin 38277 -> 0 bytes .../screenshots/21-tablet-layout.png | Bin 76943 -> 0 bytes .../test-results/screenshots/21-team-list.png | Bin 4255 -> 0 bytes .../screenshots/22-desktop-layout.png | Bin 86197 -> 0 bytes .../screenshots/24-swarm-dashboard.png | Bin 76953 -> 0 bytes .../screenshots/27-settings-page.png | Bin 64593 -> 0 bytes .../screenshots/28-general-settings.png | Bin 64593 -> 0 bytes .../screenshots/30-gateway-settings.png | Bin 64593 -> 0 bytes .../screenshots/32-right-panel.png | Bin 75156 -> 0 bytes .../screenshots/35-first-time-user.png | Bin 75156 -> 0 bytes .../screenshots/37-view-switching.png | Bin 4255 -> 0 bytes .../screenshots/38-session-persistence.png | Bin 77433 -> 0 bytes .../screenshots/39-rapid-switching.png | Bin 4255 -> 0 bytes .../screenshots/41-keyboard-nav.png | Bin 75978 -> 0 bytes .../openclaw-legacy/workbuddy界面/claw.html | 524 +++++++++++++++++ .../openclaw-legacy/workbuddy界面/专家.html | 477 ++++++++++++++++ .../openclaw-legacy/workbuddy界面/技能.html | 537 ++++++++++++++++++ .../workbuddy界面/新建任务.html | 489 ++++++++++++++++ .../openclaw-legacy/workbuddy界面/自动化.html | 366 ++++++++++++ .../02-intelligence-layer/00-agent-memory.md | 24 +- .../05-autonomy-manager.md | 57 +- docs/features/FRONTEND_INTEGRATION_AUDIT.md | 37 +- docs/knowledge-base/troubleshooting.md | 183 ++++++ plans/humble-popping-anchor.md | 478 ++++++++++------ 74 files changed, 4984 insertions(+), 687 deletions(-) create mode 100644 desktop/src/components/Automation/ApprovalQueue.tsx create mode 100644 desktop/src/components/Automation/ExecutionResult.tsx create mode 100644 desktop/src/components/CodeSnippetPanel.tsx create mode 100644 desktop/src/components/DetailDrawer.tsx create mode 100644 desktop/src/components/TopBar.tsx delete mode 100644 desktop/test-results/.last-run.json delete mode 100644 desktop/test-results/screenshots/01-app-layout.png delete mode 100644 desktop/test-results/screenshots/02-connection-state.png delete mode 100644 desktop/test-results/screenshots/02-sidebar-navigation.png delete mode 100644 desktop/test-results/screenshots/03-chat-input.png delete mode 100644 desktop/test-results/screenshots/03-navigation-switch.png delete mode 100644 desktop/test-results/screenshots/04-chat-response.png delete mode 100644 desktop/test-results/screenshots/04-settings-access.png delete mode 100644 desktop/test-results/screenshots/05-chat-area.png delete mode 100644 desktop/test-results/screenshots/06-message-send.png delete mode 100644 desktop/test-results/screenshots/07-conversation-list.png delete mode 100644 desktop/test-results/screenshots/07-streaming-response.png delete mode 100644 desktop/test-results/screenshots/08-hands-list.png delete mode 100644 desktop/test-results/screenshots/08-offline-error.png delete mode 100644 desktop/test-results/screenshots/10-scheduler-panel.png delete mode 100644 desktop/test-results/screenshots/12-team-view.png delete mode 100644 desktop/test-results/screenshots/13-swarm-dashboard.png delete mode 100644 desktop/test-results/screenshots/14-settings-page.png delete mode 100644 desktop/test-results/screenshots/15-general-settings.png delete mode 100644 desktop/test-results/screenshots/16-model-settings.png delete mode 100644 desktop/test-results/screenshots/17-right-panel.png delete mode 100644 desktop/test-results/screenshots/17-workflow-list.png delete mode 100644 desktop/test-results/screenshots/18-offline-error.png delete mode 100644 desktop/test-results/screenshots/20-mobile-layout.png delete mode 100644 desktop/test-results/screenshots/21-tablet-layout.png delete mode 100644 desktop/test-results/screenshots/21-team-list.png delete mode 100644 desktop/test-results/screenshots/22-desktop-layout.png delete mode 100644 desktop/test-results/screenshots/24-swarm-dashboard.png delete mode 100644 desktop/test-results/screenshots/27-settings-page.png delete mode 100644 desktop/test-results/screenshots/28-general-settings.png delete mode 100644 desktop/test-results/screenshots/30-gateway-settings.png delete mode 100644 desktop/test-results/screenshots/32-right-panel.png delete mode 100644 desktop/test-results/screenshots/35-first-time-user.png delete mode 100644 desktop/test-results/screenshots/37-view-switching.png delete mode 100644 desktop/test-results/screenshots/38-session-persistence.png delete mode 100644 desktop/test-results/screenshots/39-rapid-switching.png delete mode 100644 desktop/test-results/screenshots/41-keyboard-nav.png create mode 100644 docs/archive/openclaw-legacy/workbuddy界面/claw.html create mode 100644 docs/archive/openclaw-legacy/workbuddy界面/专家.html create mode 100644 docs/archive/openclaw-legacy/workbuddy界面/技能.html create mode 100644 docs/archive/openclaw-legacy/workbuddy界面/新建任务.html create mode 100644 docs/archive/openclaw-legacy/workbuddy界面/自动化.html diff --git a/desktop/src-tauri/Cargo.lock b/desktop/src-tauri/Cargo.lock index 843f694..97fe206 100644 --- a/desktop/src-tauri/Cargo.lock +++ b/desktop/src-tauri/Cargo.lock @@ -735,6 +735,7 @@ dependencies = [ "dirs 5.0.1", "fantoccini", "futures", + "keyring", "regex", "reqwest 0.11.27", "serde", @@ -2117,6 +2118,16 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "keyring" +version = "3.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eebcc3aff044e5944a8fbaf69eb277d11986064cba30c468730e8b9909fb551c" +dependencies = [ + "log", + "zeroize", +] + [[package]] name = "kuchikiki" version = "0.8.8-speedreader" @@ -5913,6 +5924,12 @@ dependencies = [ "synstructure", ] +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" + [[package]] name = "zerotrie" version = "0.2.3" diff --git a/desktop/src-tauri/Cargo.toml b/desktop/src-tauri/Cargo.toml index 3551ace..06f1b74 100644 --- a/desktop/src-tauri/Cargo.toml +++ b/desktop/src-tauri/Cargo.toml @@ -35,3 +35,6 @@ base64 = "0.22" thiserror = "2" uuid = { version = "1", features = ["v4", "serde"] } +# Secure storage (OS keyring/keychain) +keyring = "3" + diff --git a/desktop/src-tauri/src/lib.rs b/desktop/src-tauri/src/lib.rs index e8e761f..7b276b0 100644 --- a/desktop/src-tauri/src/lib.rs +++ b/desktop/src-tauri/src/lib.rs @@ -15,6 +15,9 @@ mod llm; // Browser automation module (Fantoccini-based Browser Hand) mod browser; +// Secure storage module for OS keyring/keychain +mod secure_storage; + use serde::Serialize; use serde_json::{json, Value}; use std::fs; @@ -1066,7 +1069,12 @@ pub fn run() { browser::commands::browser_element_screenshot, browser::commands::browser_get_source, browser::commands::browser_scrape_page, - browser::commands::browser_fill_form + browser::commands::browser_fill_form, + // Secure storage commands (OS keyring/keychain) + secure_storage::secure_store_set, + secure_storage::secure_store_get, + secure_storage::secure_store_delete, + secure_storage::secure_store_is_available ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); diff --git a/desktop/src/App.tsx b/desktop/src/App.tsx index 4920ad9..0835b17 100644 --- a/desktop/src/App.tsx +++ b/desktop/src/App.tsx @@ -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('main'); const [mainContentView, setMainContentView] = useState('chat'); - const [selectedHandId, setSelectedHandId] = useState(undefined); const [selectedTeamId, setSelectedTeamId] = useState(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(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 ( -
+
{/* 左侧边栏 */} setView('settings')} onMainViewChange={handleMainViewChange} - selectedHandId={selectedHandId} - onSelectHand={setSelectedHandId} selectedTeamId={selectedTeamId} onSelectTeam={handleSelectTeam} /> - {/* 中间区域 */} - - - {mainContentView === 'hands' && selectedHandId ? ( - setSelectedHandId(undefined)} - /> - ) : mainContentView === 'hands' ? ( - } - 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' ? ( - - - - ) : mainContentView === 'team' ? ( - activeTeam ? ( - - ) : ( - } - 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' ? ( - - - - ) : mainContentView === 'skills' ? ( - - - - ) : ( - - )} - - + {/* 主内容区 */} +
+ {/* 顶部工具栏 */} + setShowDetailDrawer(true)} + /> - {/* 右侧边栏 */} - + {/* 内容区域 */} + + + {mainContentView === 'automation' ? ( + + + + ) : mainContentView === 'team' ? ( + activeTeam ? ( +
+ {/* Team View Tabs */} +
+ + +
+ {/* Tab Content */} +
+ {teamViewMode === 'orchestrator' ? ( + setTeamViewMode('collaboration')} /> + ) : ( + + )} +
+
+ ) : ( + } + title="选择或创建团队" + description="从左侧列表中选择一个团队,或点击 + 创建新的多 Agent 协作团队。" + /> + ) + ) : mainContentView === 'swarm' ? ( + + + + ) : mainContentView === 'skills' ? ( + + + + ) : ( + + )} +
+
+
+ + {/* 详情抽屉 - 按需显示 */} + setShowDetailDrawer(false)} + title="详情" + > + + {/* Hand Approval Modal (global) */}
@@ -70,11 +74,11 @@ function EventItem({ event, onAcknowledge }: EventItemProps) { {typeInfo.label} - {timeAgo} + {timeAgo}
-

{event.observation}

+

{event.observation}

{event.inferredPreference && ( -

→ {event.inferredPreference}

+

→ {event.inferredPreference}

)}
@@ -85,7 +89,7 @@ function EventItem({ event, onAcknowledge }: EventItemProps) { )}
-
+
置信度: {(event.confidence * 100).toFixed(0)}% {event.appliedCount > 0 && ( • 应用 {event.appliedCount} 次 @@ -111,13 +115,15 @@ function SuggestionCard({ suggestion, onApply, onDismiss }: SuggestionCardProps) initial={{ opacity: 0, scale: 0.95 }} animate={{ opacity: 1, scale: 1 }} exit={{ opacity: 0, scale: 0.95 }} - className="p-4 bg-gradient-to-r from-amber-900/20 to-transparent rounded-lg border border-amber-700/50" + whileHover={cardHover} + transition={defaultTransition} + className="p-4 bg-gradient-to-r from-amber-50 to-transparent dark:from-amber-900/20 dark:to-transparent rounded-lg border border-amber-200 dark:border-amber-700/50" >
- +
-

{suggestion.suggestion}

-
+

{suggestion.suggestion}

+
置信度: {(suggestion.confidence * 100).toFixed(0)}% {daysLeft > 0 && • {daysLeft} 天后过期}
@@ -204,63 +210,77 @@ export function ActiveLearningPanel({ className = '' }: ActiveLearningPanelProps }, [agentId, clearEvents]); return ( -
- {/* 夨览栏 */} -
-
- -

主动学习

-
- -
-