diff --git a/.gitignore b/.gitignore index 137b91d..a99f9b3 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,5 @@ desktop/src-tauri/binaries/ *.exe *.pdb +#test +desktop/test-results/ \ No newline at end of file diff --git a/desktop/src-tauri/src/browser/actions.rs b/desktop/src-tauri/src/browser/actions.rs index ba4dc9a..8929906 100644 --- a/desktop/src-tauri/src/browser/actions.rs +++ b/desktop/src-tauri/src/browser/actions.rs @@ -1,4 +1,7 @@ // Browser action definitions for Hands system +// Note: These types are reserved for future Browser Hand automation features + +#![allow(dead_code)] use serde::{Deserialize, Serialize}; diff --git a/desktop/src-tauri/src/browser/client.rs b/desktop/src-tauri/src/browser/client.rs index 6291210..beb2df3 100644 --- a/desktop/src-tauri/src/browser/client.rs +++ b/desktop/src-tauri/src/browser/client.rs @@ -324,10 +324,10 @@ impl BrowserClient { let client = self.get_client(session_id).await?; let locator = Locator::Css(selector); - // Use wait_for_find with proper API + // Use the new wait().for_element() API instead of deprecated wait_for_find let element = tokio::time::timeout( Duration::from_millis(timeout_ms), - client.wait_for_find(locator) + client.wait().for_element(locator) ) .await .map_err(|_| BrowserError::Timeout { diff --git a/desktop/src-tauri/src/browser/commands.rs b/desktop/src-tauri/src/browser/commands.rs index 97c7313..50059e6 100644 --- a/desktop/src-tauri/src/browser/commands.rs +++ b/desktop/src-tauri/src/browser/commands.rs @@ -1,8 +1,10 @@ // Tauri commands for browser automation +// Note: Some imports are reserved for future Browser Hand features -use crate::browser::actions::{ActionResult, BrowserAction, BrowserTask, FormField}; +#![allow(unused_imports)] + +use crate::browser::actions::BrowserAction; use crate::browser::client::BrowserClient; -use crate::browser::error::BrowserError; use crate::browser::session::{BrowserType, SessionConfig}; use serde::{Deserialize, Serialize}; use std::sync::Arc; diff --git a/desktop/src-tauri/src/browser/error.rs b/desktop/src-tauri/src/browser/error.rs index dafe6ee..5a32a5e 100644 --- a/desktop/src-tauri/src/browser/error.rs +++ b/desktop/src-tauri/src/browser/error.rs @@ -1,4 +1,7 @@ // Browser automation error types +// Note: Some variants are reserved for future error handling scenarios + +#![allow(dead_code)] use serde::Serialize; use thiserror::Error; diff --git a/desktop/src-tauri/src/browser/mod.rs b/desktop/src-tauri/src/browser/mod.rs index 3b2d45c..64bfea4 100644 --- a/desktop/src-tauri/src/browser/mod.rs +++ b/desktop/src-tauri/src/browser/mod.rs @@ -1,5 +1,9 @@ // Browser automation module using Fantoccini // Provides Browser Hand capabilities for ZCLAW +// +// Note: Public exports are reserved for future Browser Hand features + +#![allow(unused_imports)] pub mod client; pub mod commands; @@ -7,6 +11,7 @@ pub mod error; pub mod session; pub mod actions; +// Re-export main types for convenience pub use client::BrowserClient; pub use error::{BrowserError, Result}; pub use session::{BrowserSession, SessionConfig}; diff --git a/desktop/src-tauri/src/browser/session.rs b/desktop/src-tauri/src/browser/session.rs index dc8272c..d4d48d4 100644 --- a/desktop/src-tauri/src/browser/session.rs +++ b/desktop/src-tauri/src/browser/session.rs @@ -166,6 +166,9 @@ impl SessionManager { sessions.values().cloned().collect() } + /// Get the number of active sessions + /// Reserved for future status dashboard + #[allow(dead_code)] pub async fn session_count(&self) -> usize { let sessions = self.sessions.read().await; sessions.len() diff --git a/desktop/src-tauri/src/llm/mod.rs b/desktop/src-tauri/src/llm/mod.rs index 324a957..5a58e1b 100644 --- a/desktop/src-tauri/src/llm/mod.rs +++ b/desktop/src-tauri/src/llm/mod.rs @@ -2,6 +2,10 @@ //! //! Provides LLM API integration for memory extraction. //! Supports multiple providers with a unified interface. +//! +//! Note: Some fields are reserved for future streaming and provider selection features + +#![allow(dead_code)] use serde::{Deserialize, Serialize}; use std::collections::HashMap; diff --git a/desktop/src-tauri/src/memory/context_builder.rs b/desktop/src-tauri/src/memory/context_builder.rs index 13e9ef1..b457dc6 100644 --- a/desktop/src-tauri/src/memory/context_builder.rs +++ b/desktop/src-tauri/src/memory/context_builder.rs @@ -9,6 +9,10 @@ //! - L2 (Deep): Load full content for most relevant items //! //! Reference: ZCLAW_AGENT_INTELLIGENCE_EVOLUTION.md §4.3 +//! +//! Note: These types are reserved for future memory integration features + +#![allow(dead_code)] use serde::{Deserialize, Serialize}; use std::collections::HashMap; diff --git a/desktop/src-tauri/src/memory/extractor.rs b/desktop/src-tauri/src/memory/extractor.rs index cd749ac..b6266f8 100644 --- a/desktop/src-tauri/src/memory/extractor.rs +++ b/desktop/src-tauri/src/memory/extractor.rs @@ -9,9 +9,12 @@ //! - agent_lesson: Lessons learned by the agent from interactions //! - agent_pattern: Recurring patterns the agent should remember //! - task: Task-related information for follow-up +//! +//! Note: Some fields and methods are reserved for future LLM-powered extraction + +#![allow(dead_code)] use serde::{Deserialize, Serialize}; -use std::collections::HashMap; // === Types === diff --git a/desktop/src-tauri/src/memory/mod.rs b/desktop/src-tauri/src/memory/mod.rs index 2d5f01a..f7e5188 100644 --- a/desktop/src-tauri/src/memory/mod.rs +++ b/desktop/src-tauri/src/memory/mod.rs @@ -9,5 +9,9 @@ pub mod extractor; pub mod context_builder; +// Re-export main types for convenience +// Note: Some types are reserved for future memory integration features +#[allow(unused_imports)] pub use extractor::{SessionExtractor, ExtractedMemory, ExtractionConfig}; +#[allow(unused_imports)] pub use context_builder::{ContextBuilder, EnhancedContext, ContextLevel}; diff --git a/desktop/src-tauri/src/viking_commands.rs b/desktop/src-tauri/src/viking_commands.rs index e7fb7df..0f34a7e 100644 --- a/desktop/src-tauri/src/viking_commands.rs +++ b/desktop/src-tauri/src/viking_commands.rs @@ -7,7 +7,6 @@ use serde::{Deserialize, Serialize}; use std::process::Command; -use tauri::AppHandle; // === Types === @@ -131,6 +130,9 @@ fn run_viking_cli(args: &[&str]) -> Result { } } +/// Helper function to run Viking CLI and parse JSON output +/// Reserved for future JSON-based commands +#[allow(dead_code)] fn run_viking_cli_json Deserialize<'de>>(args: &[&str]) -> Result { let output = run_viking_cli(args)?; diff --git a/desktop/src/App.tsx b/desktop/src/App.tsx index 2496fca..4920ad9 100644 --- a/desktop/src/App.tsx +++ b/desktop/src/App.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from 'react'; +import { useState, useEffect, useCallback } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import './index.css'; import { Sidebar, MainViewType } from './components/Sidebar'; @@ -9,14 +9,19 @@ import { HandTaskPanel } from './components/HandTaskPanel'; import { SchedulerPanel } from './components/SchedulerPanel'; import { TeamCollaborationView } from './components/TeamCollaborationView'; import { SwarmDashboard } from './components/SwarmDashboard'; -import { useGatewayStore } from './store/gatewayStore'; +import { SkillMarket } from './components/SkillMarket'; +import { AgentOnboardingWizard } from './components/AgentOnboardingWizard'; +import { HandApprovalModal } from './components/HandApprovalModal'; +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 { silentErrorHandler } from './lib/error-utils'; import { Bot, Users, Loader2 } from 'lucide-react'; import { EmptyState } from './components/ui'; import { isTauriRuntime, getLocalGatewayStatus, startLocalGateway } from './lib/tauri-gateway'; +import { useOnboarding } from './lib/use-onboarding'; +import type { Clone } from './store/agentStore'; type View = 'main' | 'settings'; @@ -39,13 +44,66 @@ function App() { const [selectedTeamId, setSelectedTeamId] = useState(undefined); const [bootstrapping, setBootstrapping] = useState(true); const [bootstrapStatus, setBootstrapStatus] = useState('Initializing...'); - const { connect, connectionState } = useGatewayStore(); + const [showOnboarding, setShowOnboarding] = useState(false); + + // Hand Approval state + const [pendingApprovalRun, setPendingApprovalRun] = useState(null); + const [showApprovalModal, setShowApprovalModal] = useState(false); + + const { connect, hands, approveHand, loadHands } = useGatewayStore(); const { activeTeam, setActiveTeam, teams } = useTeamStore(); + const { setCurrentAgent } = useChatStore(); + const { isNeeded: onboardingNeeded, isLoading: onboardingLoading, markCompleted } = useOnboarding(); useEffect(() => { document.title = 'ZCLAW'; }, []); + // Watch for Hands that need approval + useEffect(() => { + const handsNeedingApproval = hands.filter(h => h.status === 'needs_approval'); + if (handsNeedingApproval.length > 0 && !showApprovalModal) { + // Find the first hand with needs_approval and create a pending run + const hand = handsNeedingApproval[0]; + if (hand.currentRunId) { + setPendingApprovalRun({ + runId: hand.currentRunId, + status: 'needs_approval', + startedAt: new Date().toISOString(), + }); + setShowApprovalModal(true); + } + } + }, [hands, showApprovalModal]); + + // Handle approval/rejection of Hand runs + const handleApproveHand = useCallback(async (runId: string) => { + // Find the hand that owns this run + const hand = hands.find(h => h.currentRunId === runId); + if (!hand) return; + + await approveHand(hand.id, runId, true); + await loadHands(); + setShowApprovalModal(false); + setPendingApprovalRun(null); + }, [hands, approveHand, loadHands]); + + const handleRejectHand = useCallback(async (runId: string, reason: string) => { + // Find the hand that owns this run + const hand = hands.find(h => h.currentRunId === runId); + if (!hand) return; + + await approveHand(hand.id, runId, false, reason); + await loadHands(); + setShowApprovalModal(false); + setPendingApprovalRun(null); + }, [hands, approveHand, loadHands]); + + const handleCloseApprovalModal = useCallback(() => { + setShowApprovalModal(false); + // Don't clear pendingApprovalRun - keep it for reference + }, []); + // Bootstrap: Start OpenFang Gateway before rendering main UI useEffect(() => { let mounted = true; @@ -64,43 +122,65 @@ function App() { setBootstrapStatus('Starting OpenFang Gateway...'); console.log('[App] Local gateway not running, auto-starting...'); - await startLocalGateway(); + await startLocalGateway(); - // Wait for gateway to be ready - await new Promise(resolve => setTimeout(resolve, 2000)); - console.log('[App] Local gateway started'); - } else if (isRunning) { - console.log('[App] Local gateway already running'); - } - } catch (err) { - console.warn('[App] Failed to check/start local gateway:', err); + // Wait for gateway to be ready + await new Promise(resolve => setTimeout(resolve, 2000)); + console.log('[App] Local gateway started'); + } else if (isRunning) { + console.log('[App] Local gateway already running'); } + } catch (err) { + console.warn('[App] Failed to check/start local gateway:', err); } - - if (!mounted) return; - - // Step 2: Connect to gateway - setBootstrapStatus('Connecting to gateway...'); - const gatewayToken = getStoredGatewayToken(); - await connect(undefined, gatewayToken); - - if (!mounted) return; - - // Step 3: Bootstrap complete - setBootstrapping(false); - } catch (err) { - console.error('[App] Bootstrap failed:', err); - // Still allow app to load, connection status will show error - setBootstrapping(false); } - }; + + if (!mounted) return; + + // Step 2: Connect to gateway + setBootstrapStatus('Connecting to gateway...'); + const gatewayToken = getStoredGatewayToken(); + await connect(undefined, gatewayToken); + + if (!mounted) return; + + // Step 3: Check if onboarding is needed + if (onboardingNeeded && !onboardingLoading) { + setShowOnboarding(true); + } + + // Step 4: Bootstrap complete + setBootstrapping(false); + } catch (err) { + console.error('[App] Bootstrap failed:', err); + // Still allow app to load, connection status will show error + setBootstrapping(false); + } + }; bootstrap(); return () => { mounted = false; }; - }, [connect]); + }, [connect, onboardingNeeded, onboardingLoading]); + + // Handle onboarding completion + const handleOnboardingSuccess = (clone: Clone) => { + markCompleted({ + userName: clone.userName || 'User', + userRole: clone.userRole, + }); + setCurrentAgent({ + id: clone.id, + name: clone.name, + icon: clone.emoji || '🦞', + color: 'bg-gradient-to-br from-orange-500 to-red-500', + lastMessage: clone.role || 'New Agent', + time: '', + }); + setShowOnboarding(false); + }; // 当切换到非 hands 视图时清除选中的 Hand const handleMainViewChange = (view: MainViewType) => { @@ -128,6 +208,24 @@ function App() { return ; } + // Show onboarding wizard for first-time users + if (showOnboarding) { + return ( + { + // Skip onboarding and mark as completed with default values + markCompleted({ + userName: 'User', + userRole: 'user', + }); + setShowOnboarding(false); + }} + onSuccess={handleOnboardingSuccess} + /> + ); + } + return (
{/* 左侧边栏 */} @@ -190,6 +288,15 @@ function App() { > + ) : mainContentView === 'skills' ? ( + + + ) : ( )} @@ -198,6 +305,15 @@ function App() { {/* 右侧边栏 */} + + {/* Hand Approval Modal (global) */} +
); } diff --git a/desktop/src/components/ActiveLearningPanel.tsx b/desktop/src/components/ActiveLearningPanel.tsx index fbf3f6b..1c22d34 100644 --- a/desktop/src/components/ActiveLearningPanel.tsx +++ b/desktop/src/components/ActiveLearningPanel.tsx @@ -4,7 +4,7 @@ * 展示学习事件、模式和系统建议。 */ -import { useCallback, useEffect, useState } from 'react'; +import { useCallback, useState } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { Brain, @@ -12,24 +12,17 @@ import { Lightbulb, Check, X, - RefreshCw, Download, - Upload, - Settings, - BarChart3, Clock, - Zap, } from 'lucide-react'; -import { Button, Badge, EmptyState } from './ui'; +import { Button, EmptyState } from './ui'; +import { useActiveLearningStore } from '../store/activeLearningStore'; import { - useActiveLearningStore, type LearningEvent, - type LearningPattern, type LearningSuggestion, type LearningEventType, -} from '../store/activeLearningStore'; +} from '../types/active-learning'; import { useChatStore } from '../store/chatStore'; -import { cardHover, defaultTransition } from '../lib/animations'; // === Constants === @@ -74,9 +67,9 @@ function EventItem({ event, onAcknowledge }: EventItemProps) {
- + {typeInfo.label} - + {timeAgo}

{event.observation}

@@ -133,14 +126,13 @@ function SuggestionCard({ suggestion, onApply, onDismiss }: SuggestionCardProps)
+ + 应用 + -
+ + 忽略 +
); @@ -160,10 +152,7 @@ export function ActiveLearningPanel({ className = '' }: ActiveLearningPanelProps const { events, - patterns, - suggestions, config, - isLoading, acknowledgeEvent, getPatterns, getSuggestions, @@ -364,9 +353,9 @@ export function ActiveLearningPanel({ className = '' }: ActiveLearningPanelProps {typeInfo.icon} {typeInfo.label}
- + {(pattern.confidence * 100).toFixed(0)}% - +

{pattern.description}

diff --git a/desktop/src/components/AgentOnboardingWizard.tsx b/desktop/src/components/AgentOnboardingWizard.tsx index d807bca..1055439 100644 --- a/desktop/src/components/AgentOnboardingWizard.tsx +++ b/desktop/src/components/AgentOnboardingWizard.tsx @@ -77,7 +77,7 @@ const steps = [ // === Component === export function AgentOnboardingWizard({ isOpen, onClose, onSuccess }: AgentOnboardingWizardProps) { - const { createClone, isLoading, error, clearError } = useAgentStore(); + const { createClone, updateClone, clones, isLoading, error, clearError } = useAgentStore(); const [currentStep, setCurrentStep] = useState(1); const [formData, setFormData] = useState(initialFormData); const [errors, setErrors] = useState>({}); @@ -164,7 +164,7 @@ export function AgentOnboardingWizard({ isOpen, onClose, onSuccess }: AgentOnboa setSubmitStatus('idle'); try { - const createOptions: CloneCreateOptions = { + const personalityUpdates = { name: formData.agentName, role: formData.agentRole || undefined, nickname: formData.agentNickname || undefined, @@ -173,13 +173,23 @@ export function AgentOnboardingWizard({ isOpen, onClose, onSuccess }: AgentOnboa scenarios: formData.scenarios, workspaceDir: formData.workspaceDir || undefined, restrictFiles: formData.restrictFiles, - privacyOptIn: formData.privacyOptIn, emoji: formData.emoji, personality: formData.personality, notes: formData.notes || undefined, }; - const clone = await createClone(createOptions); + let clone: Clone | undefined; + + // If there's an existing clone, update it instead of creating a new one + if (clones && clones.length > 0) { + clone = await updateClone(clones[0].id, personalityUpdates); + } else { + const createOptions: CloneCreateOptions = { + ...personalityUpdates, + privacyOptIn: formData.privacyOptIn, + }; + clone = await createClone(createOptions); + } if (clone) { setSubmitStatus('success'); @@ -516,32 +526,6 @@ export function AgentOnboardingWizard({ isOpen, onClose, onSuccess }: AgentOnboa />
- -
-
-

- 匿名使用数据 -

-

- 允许收集匿名使用数据以改进产品 -

-
- -
@@ -623,7 +607,7 @@ export function AgentOnboardingWizard({ isOpen, onClose, onSuccess }: AgentOnboa
)} + {/* Parameters Form (shown when activating) */} + {showParamsForm && parameters.length > 0 && ( +
+

+ 执行参数 +

+ +
+ )} + {/* Dashboard Metrics */} {hand.metrics && hand.metrics.length > 0 && (
@@ -234,13 +323,13 @@ function HandDetailsModal({ hand, isOpen, onClose, onActivate, isActivating }: H {/* Footer */}
+ + +
{activeTab === 'memory' ? ( + ) : activeTab === 'reflection' ? ( + + ) : activeTab === 'autonomy' ? ( + + ) : activeTab === 'learning' ? ( + ) : activeTab === 'agent' ? (
('scheduled'); const [isCreateModalOpen, setIsCreateModalOpen] = useState(false); + const [isWorkflowEditorOpen, setIsWorkflowEditorOpen] = useState(false); + const [editingWorkflow, setEditingWorkflow] = useState(undefined); + const [selectedWorkflow, setSelectedWorkflow] = useState(null); + const [isSavingWorkflow, setIsSavingWorkflow] = useState(false); useEffect(() => { loadScheduledTasks(); - }, [loadScheduledTasks]); + loadWorkflows(); + }, [loadScheduledTasks, loadWorkflows]); const handleCreateJob = useCallback(() => { setIsCreateModalOpen(true); @@ -653,6 +670,60 @@ export function SchedulerPanel() { loadScheduledTasks(); }, [loadScheduledTasks]); + // Workflow handlers + const handleCreateWorkflow = useCallback(() => { + setEditingWorkflow(undefined); + setIsWorkflowEditorOpen(true); + }, []); + + const handleEditWorkflow = useCallback((workflow: Workflow) => { + setEditingWorkflow(workflow); + setIsWorkflowEditorOpen(true); + }, []); + + const handleViewWorkflowHistory = useCallback((workflow: Workflow) => { + setSelectedWorkflow(workflow); + }, []); + + const handleSaveWorkflow = useCallback(async (data: { + name: string; + description?: string; + steps: Array<{ + handName: string; + name?: string; + params?: Record; + condition?: string; + }>; + }) => { + setIsSavingWorkflow(true); + try { + if (editingWorkflow) { + // Update existing workflow + console.log('Update workflow:', editingWorkflow.id, data); + } else { + // Create new workflow + await createWorkflow(data); + } + setIsWorkflowEditorOpen(false); + setEditingWorkflow(undefined); + await loadWorkflows(); + } catch (error) { + console.error('Failed to save workflow:', error); + throw error; + } finally { + setIsSavingWorkflow(false); + } + }, [editingWorkflow, createWorkflow, loadWorkflows]); + + const handleExecuteWorkflow = useCallback(async (workflowId: string) => { + try { + await executeWorkflow(workflowId); + await loadWorkflows(); + } catch (error) { + console.error('Failed to execute workflow:', error); + } + }, [executeWorkflow, loadWorkflows]); + if (isLoading && scheduledTasks.length === 0) { return (
@@ -706,6 +777,12 @@ export function SchedulerPanel() { icon={Zap} label="事件触发器" /> + setActiveTab('workflows')} + icon={GitBranch} + label="工作流" + /> setActiveTab('history')} @@ -722,6 +799,15 @@ export function SchedulerPanel() { 新建任务 )} + {activeTab === 'workflows' && ( + + )}
{/* Tab Content */} @@ -787,6 +873,86 @@ export function SchedulerPanel() {
)} + {/* Workflows Tab */} + {activeTab === 'workflows' && ( + selectedWorkflow ? ( + setSelectedWorkflow(null)} + /> + ) : ( +
+ {workflows.length === 0 ? ( + + ) : ( +
+ {workflows.map((workflow) => ( +
+
+
+ +
+
+
+ {workflow.name} +
+
+ {workflow.description || '无描述'} +
+
+
+
+ {workflow.steps && ( + + {workflow.steps} 步骤 + + )} + + + +
+
+ ))} + +
+ )} +
+ ) + )} + {activeTab === 'history' && (
setIsCreateModalOpen(false)} onSuccess={handleCreateSuccess} /> + + {/* Workflow Editor Modal */} + { + setIsWorkflowEditorOpen(false); + setEditingWorkflow(undefined); + }} + onSave={handleSaveWorkflow} + isSaving={isSavingWorkflow} + /> ); } diff --git a/desktop/src/components/Settings/SettingsLayout.tsx b/desktop/src/components/Settings/SettingsLayout.tsx index 089efbd..20328b8 100644 --- a/desktop/src/components/Settings/SettingsLayout.tsx +++ b/desktop/src/components/Settings/SettingsLayout.tsx @@ -1,4 +1,5 @@ import { useState } from 'react'; +import { useGatewayStore } from '../../store/gatewayStore'; import { Settings as SettingsIcon, BarChart3, @@ -28,6 +29,7 @@ import { About } from './About'; import { Credits } from './Credits'; import { AuditLogsPanel } from '../AuditLogsPanel'; import { SecurityStatus } from '../SecurityStatus'; +import { SecurityLayersPanel } from '../SecurityLayersPanel'; import { TaskList } from '../TaskList'; interface SettingsLayoutProps { @@ -69,6 +71,7 @@ const menuItems: { id: SettingsPage; label: string; icon: React.ReactNode }[] = export function SettingsLayout({ onBack }: SettingsLayoutProps) { const [activePage, setActivePage] = useState('general'); + const { securityStatus } = useGatewayStore(); const renderPage = () => { switch (activePage) { @@ -82,9 +85,22 @@ export function SettingsLayout({ onBack }: SettingsLayoutProps) { case 'workspace': return ; case 'privacy': return ; case 'security': return ( -
-

安全状态

- +
+
+

安全状态

+ +
+
+

安全架构详情

+ +
); case 'audit': return ; diff --git a/desktop/src/components/Sidebar.tsx b/desktop/src/components/Sidebar.tsx index 7017700..e2790d5 100644 --- a/desktop/src/components/Sidebar.tsx +++ b/desktop/src/components/Sidebar.tsx @@ -1,16 +1,17 @@ import { useState } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; -import { Settings, Users, Bot, GitBranch, MessageSquare, Layers } from 'lucide-react'; +import { Settings, Users, Bot, GitBranch, MessageSquare, Layers, Package } from 'lucide-react'; import { CloneManager } from './CloneManager'; import { HandList } from './HandList'; import { WorkflowList } from './WorkflowList'; import { TeamList } from './TeamList'; import { SwarmDashboard } from './SwarmDashboard'; +import { SkillMarket } from './SkillMarket'; import { useGatewayStore } from '../store/gatewayStore'; import { Button } from './ui'; import { containerVariants, defaultTransition } from '../lib/animations'; -export type MainViewType = 'chat' | 'hands' | 'workflow' | 'team' | 'swarm'; +export type MainViewType = 'chat' | 'hands' | 'workflow' | 'team' | 'swarm' | 'skills'; interface SidebarProps { onOpenSettings?: () => void; @@ -21,12 +22,13 @@ interface SidebarProps { onSelectTeam?: (teamId: string) => void; } -type Tab = 'clones' | 'hands' | 'workflow' | 'team' | 'swarm'; +type Tab = 'clones' | 'hands' | 'workflow' | 'team' | 'swarm' | 'skills'; const TABS: { key: Tab; label: string; icon: React.ComponentType<{ className?: string }>; mainView?: MainViewType }[] = [ { key: 'clones', label: '分身', icon: Bot }, { key: 'hands', label: 'Hands', icon: MessageSquare, mainView: 'hands' }, { key: 'workflow', label: '工作流', icon: GitBranch, mainView: 'workflow' }, + { key: 'skills', label: '技能', icon: Package, mainView: 'skills' }, { key: 'team', label: '团队', icon: Users, mainView: 'team' }, { key: 'swarm', label: '协作', icon: Layers, mainView: 'swarm' }, ]; @@ -107,6 +109,7 @@ export function Sidebar({ /> )} {activeTab === 'workflow' && } + {activeTab === 'skills' && } {activeTab === 'team' && ( { + try { + // Use /api/agents endpoint which returns array of agents + const agents = await this.restGet>('/api/agents'); + if (agents && agents.length > 0) { + // Prefer agent with state "Running", otherwise use first agent + const runningAgent = agents.find((a: { id: string; name?: string; state?: string }) => a.state === 'Running'); + const defaultAgent = runningAgent || agents[0]; + this.defaultAgentId = defaultAgent.id; + this.log('info', `Fetched default agent from /api/agents: ${this.defaultAgentId} (${defaultAgent.name || 'unnamed'})`); + return this.defaultAgentId; + } + } catch (err) { + this.log('warn', `Failed to fetch default agent from /api/agents: ${err}`); + } + return null; + } /** Set the default agent ID */ setDefaultAgentId(agentId: string): void { @@ -642,7 +661,18 @@ export class GatewayClient { maxTokens?: number; }): Promise<{ runId: string; sessionId?: string; response?: string }> { // OpenFang uses /api/agents/{agentId}/message endpoint - const agentId = opts?.agentId || this.defaultAgentId; + let agentId = opts?.agentId || this.defaultAgentId; + + // If no agent ID, try to fetch from OpenFang status + if (!agentId) { + await this.fetchDefaultAgentId(); + agentId = this.defaultAgentId; + } + + if (!agentId) { + throw new Error('No agent available. Please ensure OpenFang has at least one agent.'); + } + const result = await this.restPost<{ response?: string; input_tokens?: number; output_tokens?: number }>(`/api/agents/${agentId}/message`, { message, session_id: opts?.sessionKey, @@ -670,10 +700,29 @@ export class GatewayClient { agentId?: string; } ): Promise<{ runId: string }> { - const agentId = opts?.agentId || this.defaultAgentId; + let agentId = opts?.agentId || this.defaultAgentId; const runId = createIdempotencyKey(); const sessionId = opts?.sessionKey || `session_${Date.now()}`; + // If no agent ID, try to fetch from OpenFang status (async, but we'll handle it in connectOpenFangStream) + if (!agentId) { + // Try to get default agent asynchronously + this.fetchDefaultAgentId().then(() => { + const resolvedAgentId = this.defaultAgentId; + if (resolvedAgentId) { + this.streamCallbacks.set(runId, callbacks); + this.connectOpenFangStream(resolvedAgentId, runId, sessionId, message); + } else { + callbacks.onError('No agent available. Please ensure OpenFang has at least one agent.'); + callbacks.onComplete(); + } + }).catch((err) => { + callbacks.onError(`Failed to get agent: ${err}`); + callbacks.onComplete(); + }); + return { runId }; + } + // Store callbacks for this run this.streamCallbacks.set(runId, callbacks); @@ -1087,7 +1136,11 @@ export class GatewayClient { async getQuickConfig(): Promise { try { // Use /api/config endpoint (OpenFang's actual config endpoint) - const config = await this.restGet('/api/config'); + const config = await this.restGet<{ + data_dir?: string; + home_dir?: string; + default_model?: { model?: string; provider?: string }; + }>('/api/config'); // Map OpenFang config to frontend expected format return { quickConfig: { @@ -1098,7 +1151,7 @@ export class GatewayClient { agentNickname: 'ZCLAW', scenarios: ['通用对话', '代码助手', '文档编写'], workspaceDir: config.data_dir || config.home_dir, - gatewayUrl: this.baseUrl, + gatewayUrl: this.getRestBaseUrl(), defaultModel: config.default_model?.model, defaultProvider: config.default_model?.provider, theme: 'dark', diff --git a/desktop/src/lib/llm-service.ts b/desktop/src/lib/llm-service.ts index c0620f8..08382f6 100644 --- a/desktop/src/lib/llm-service.ts +++ b/desktop/src/lib/llm-service.ts @@ -90,10 +90,8 @@ const LLM_CONFIG_KEY = 'zclaw-llm-config'; // === Mock Adapter (for testing) === class MockLLMAdapter implements LLMServiceAdapter { - private config: LLMConfig; - - constructor(config: LLMConfig) { - this.config = config; + constructor(_config: LLMConfig) { + // Config is stored for future use (e.g., custom mock behavior based on config) } async complete(messages: LLMMessage[]): Promise { diff --git a/desktop/src/lib/message-virtualization.ts b/desktop/src/lib/message-virtualization.ts index 5ae2e8d..a95c4c1 100644 --- a/desktop/src/lib/message-virtualization.ts +++ b/desktop/src/lib/message-virtualization.ts @@ -9,10 +9,7 @@ import { useRef, useCallback, useMemo, useEffect, type CSSProperties, type ReactNode } from 'react'; import React from 'react'; -import { VariableSizeList } from 'react-window'; - -// Type alias for convenience -type List = VariableSizeList; +import type { ListImperativeAPI } from 'react-window'; /** * Message item interface for virtualization @@ -52,8 +49,8 @@ const DEFAULT_HEIGHTS: Record = { * Hook return type for virtualized message management */ export interface UseVirtualizedMessagesReturn { - /** Reference to the VariableSizeList instance */ - listRef: React.RefObject; + /** Reference to the List instance */ + listRef: React.RefObject; /** Get the current height for a message by id and role */ getHeight: (id: string, role: string) => number; /** Update the measured height for a message */ @@ -99,7 +96,7 @@ export function useVirtualizedMessages( messages: VirtualizedMessageItem[], defaultHeights: Record = DEFAULT_HEIGHTS ): UseVirtualizedMessagesReturn { - const listRef = useRef(null); + const listRef = useRef(null); const heightsRef = useRef>(new Map()); const prevMessagesLengthRef = useRef(0); @@ -121,8 +118,7 @@ export function useVirtualizedMessages( const current = heightsRef.current.get(id); if (current !== height) { heightsRef.current.set(id, height); - // Reset cache to force recalculation - listRef.current?.resetAfterIndex(0); + // Height updated - the list will use the new height on next render } }, []); @@ -141,7 +137,7 @@ export function useVirtualizedMessages( */ const scrollToBottom = useCallback((): void => { if (listRef.current && messages.length > 0) { - listRef.current.scrollToItem(messages.length - 1, 'end'); + listRef.current.scrollToRow({ index: messages.length - 1, align: 'end' }); } }, [messages.length]); @@ -150,7 +146,7 @@ export function useVirtualizedMessages( */ const scrollToIndex = useCallback((index: number): void => { if (listRef.current && index >= 0 && index < messages.length) { - listRef.current.scrollToItem(index, 'center'); + listRef.current.scrollToRow({ index, align: 'center' }); } }, [messages.length]); @@ -159,7 +155,6 @@ export function useVirtualizedMessages( */ const resetCache = useCallback((): void => { heightsRef.current.clear(); - listRef.current?.resetAfterIndex(0); }, []); /** diff --git a/desktop/src/lib/use-onboarding.ts b/desktop/src/lib/use-onboarding.ts new file mode 100644 index 0000000..bb2b3fd --- /dev/null +++ b/desktop/src/lib/use-onboarding.ts @@ -0,0 +1,128 @@ +/** + * useOnboarding - Hook for detecting and managing first-time user onboarding + * + * Determines if user needs to go through the onboarding wizard. + * Stores completion status in localStorage. + */ + +import { useState, useEffect, useCallback } from 'react'; + +const ONBOARDING_COMPLETED_KEY = 'zclaw-onboarding-completed'; +const USER_PROFILE_KEY = 'zclaw-user-profile'; + +export interface UserProfile { + userName: string; + userRole?: string; + completedAt: string; +} + +export interface OnboardingState { + isNeeded: boolean; + isLoading: boolean; + userProfile: UserProfile | null; + markCompleted: (profile: Omit) => void; + resetOnboarding: () => void; +} + +/** + * Hook to manage first-time user onboarding + * + * Usage: + * ```tsx + * const { isNeeded, isLoading, markCompleted } = useOnboarding(); + * + * if (isNeeded) { + * return ; + * } + * ``` + */ +export function useOnboarding(): OnboardingState { + const [isNeeded, setIsNeeded] = useState(false); + const [isLoading, setIsLoading] = useState(true); + const [userProfile, setUserProfile] = useState(null); + + // Check onboarding status on mount + useEffect(() => { + try { + const completed = localStorage.getItem(ONBOARDING_COMPLETED_KEY); + const profileStr = localStorage.getItem(USER_PROFILE_KEY); + + if (completed === 'true' && profileStr) { + const profile = JSON.parse(profileStr) as UserProfile; + setUserProfile(profile); + setIsNeeded(false); + } else { + // No onboarding record - first time user + setIsNeeded(true); + } + } catch (err) { + console.warn('[useOnboarding] Failed to check onboarding status:', err); + setIsNeeded(true); + } finally { + setIsLoading(false); + } + }, []); + + // Mark onboarding as completed + const markCompleted = useCallback((profile: Omit) => { + const fullProfile: UserProfile = { + ...profile, + completedAt: new Date().toISOString(), + }; + + try { + localStorage.setItem(ONBOARDING_COMPLETED_KEY, 'true'); + localStorage.setItem(USER_PROFILE_KEY, JSON.stringify(fullProfile)); + setUserProfile(fullProfile); + setIsNeeded(false); + console.log('[useOnboarding] Onboarding completed for user:', profile.userName); + } catch (err) { + console.error('[useOnboarding] Failed to save onboarding status:', err); + } + }, []); + + // Reset onboarding (for testing or user request) + const resetOnboarding = useCallback(() => { + try { + localStorage.removeItem(ONBOARDING_COMPLETED_KEY); + localStorage.removeItem(USER_PROFILE_KEY); + setUserProfile(null); + setIsNeeded(true); + console.log('[useOnboarding] Onboarding reset'); + } catch (err) { + console.error('[useOnboarding] Failed to reset onboarding:', err); + } + }, []); + + return { + isNeeded, + isLoading, + userProfile, + markCompleted, + resetOnboarding, + }; +} + +/** + * Get stored user profile without hook (for use outside React components) + */ +export function getStoredUserProfile(): UserProfile | null { + try { + const profileStr = localStorage.getItem(USER_PROFILE_KEY); + if (profileStr) { + return JSON.parse(profileStr) as UserProfile; + } + } catch (err) { + console.warn('[useOnboarding] Failed to get user profile:', err); + } + return null; +} + +/** + * Check if onboarding is completed (for use outside React components) + */ +export function isOnboardingCompleted(): boolean { + return localStorage.getItem(ONBOARDING_COMPLETED_KEY) === 'true'; +} + +export default useOnboarding; diff --git a/desktop/src/lib/vector-memory.ts b/desktop/src/lib/vector-memory.ts index 645baad..088ffe2 100644 --- a/desktop/src/lib/vector-memory.ts +++ b/desktop/src/lib/vector-memory.ts @@ -123,7 +123,9 @@ export class VectorMemoryService { importance: Math.round((1 - result.score) * 10), // Invert score to importance createdAt: new Date().toISOString(), source: 'auto', - tags: (result.metadata as Record)?.tags ?? [], + tags: Array.isArray((result.metadata as Record)?.tags) + ? (result.metadata as Record).tags as string[] + : [], lastAccessedAt: new Date().toISOString(), accessCount: 0, }; @@ -132,7 +134,9 @@ export class VectorMemoryService { memory, score: result.score, uri: result.uri, - highlights: (result.metadata as Record)?.highlights as string[] | undefined, + highlights: Array.isArray((result.metadata as Record)?.highlights) + ? (result.metadata as Record).highlights as string[] + : undefined, }); } diff --git a/desktop/src/lib/viking-client.ts b/desktop/src/lib/viking-client.ts index 96417ef..e1a66aa 100644 --- a/desktop/src/lib/viking-client.ts +++ b/desktop/src/lib/viking-client.ts @@ -49,6 +49,7 @@ export interface FindResult { level: ContextLevel; abstract?: string; overview?: string; + metadata?: Record; } export interface GrepOptions { diff --git a/desktop/src/store/chatStore.ts b/desktop/src/store/chatStore.ts index cdea111..ed41a02 100644 --- a/desktop/src/store/chatStore.ts +++ b/desktop/src/store/chatStore.ts @@ -207,7 +207,25 @@ export const useChatStore = create()( return { currentAgent: agent }; } + // Save current conversation before switching const conversations = upsertActiveConversation([...state.conversations], state); + + // Try to find existing conversation for this agent + const agentConversation = conversations.find(c => c.agentId === agent.id); + + if (agentConversation) { + // Restore the agent's previous conversation + return { + conversations, + currentAgent: agent, + messages: [...agentConversation.messages], + sessionKey: agentConversation.sessionKey, + isStreaming: false, + currentConversationId: agentConversation.id, + }; + } + + // No existing conversation, start fresh return { conversations, currentAgent: agent, @@ -627,7 +645,7 @@ export const useChatStore = create()( partialize: (state) => ({ conversations: state.conversations, currentModel: state.currentModel, - messages: state.messages, + currentAgentId: state.currentAgent?.id, currentConversationId: state.currentConversationId, }), onRehydrateStorage: () => (state) => { @@ -642,6 +660,15 @@ export const useChatStore = create()( } } } + + // Restore messages from current conversation if exists + if (state?.currentConversationId && state.conversations) { + const currentConv = state.conversations.find(c => c.id === state.currentConversationId); + if (currentConv) { + state.messages = [...currentConv.messages]; + state.sessionKey = currentConv.sessionKey; + } + } }, }, ), diff --git a/desktop/src/store/gatewayStore.ts b/desktop/src/store/gatewayStore.ts index e74934b..74758dd 100644 --- a/desktop/src/store/gatewayStore.ts +++ b/desktop/src/store/gatewayStore.ts @@ -150,11 +150,27 @@ interface RawApproval { request_type?: string; handId?: string; hand_id?: string; + hand_name?: string; + handName?: string; + run_id?: string; + runId?: string; requester?: string; requested_by?: string; + requested_at?: string; + requestedAt?: string; + reason?: string; + description?: string; + action?: string; + params?: Record; status?: string; createdAt?: string; created_at?: string; + responded_at?: string; + respondedAt?: string; + responded_by?: string; + respondedBy?: string; + response_reason?: string; + responseReason?: string; details?: Record; metadata?: Record; } @@ -173,6 +189,7 @@ interface RawSession { updated_at?: string; messageCount?: number; message_count?: number; + metadata?: Record; } interface RawSessionMessage { @@ -184,6 +201,7 @@ interface RawSessionMessage { createdAt?: string; created_at?: string; metadata?: Record; + tokens?: { input?: number; output?: number }; } interface RawWorkflowRun { @@ -202,6 +220,8 @@ interface RawWorkflowRun { totalSteps?: number; total_steps?: number; error?: string; + step?: string; + result?: unknown; } // === OpenFang Types === @@ -780,21 +800,22 @@ export const useGatewayStore = create((set, get) => { try { const result = await get().client.listClones(); // API 可能返回数组,也可能返回 {clones: [...]} 或 {agents: [...]} - const clones = Array.isArray(result) ? result : (result?.clones || result?.agents || []); - set({ clones }); - useChatStore.getState().syncAgents(clones); + let clones = Array.isArray(result) ? result : (result?.clones || result?.agents || []); - // Set default agent ID if we have agents and none is set + console.log('[Gateway] Loaded agents:', clones.length, clones.map((c: { id?: string; name?: string }) => ({ id: c.id, name: c.name }))); + + // Set default agent ID if we have agents if (clones.length > 0 && clones[0].id) { const client = get().client; - const currentDefault = client.getDefaultAgentId(); - // Only set if the default doesn't exist in the list - const defaultExists = clones.some((c) => c.id === currentDefault); - if (!defaultExists) { - client.setDefaultAgentId(clones[0].id); - } + client.setDefaultAgentId(clones[0].id); + console.log('[Gateway] Set default agent ID:', clones[0].id); } - } catch { /* ignore if method not available */ } + + set({ clones }); + useChatStore.getState().syncAgents(clones); + } catch (err) { + console.warn('[Gateway] Failed to load clones:', err); + } }, createClone: async (opts) => { @@ -1084,7 +1105,7 @@ export const useGatewayStore = create((set, get) => { set({ localGateway: status, localGatewayBusy: false }); return status; } catch (err: unknown) { - const message = err?.message || '读取本地 Gateway 状态失败'; + const message = err instanceof Error ? err.message : '读取本地 Gateway 状态失败'; const nextStatus = { ...get().localGateway, supported: true, @@ -1108,7 +1129,7 @@ export const useGatewayStore = create((set, get) => { set({ localGateway: status, localGatewayBusy: false }); return status; } catch (err: unknown) { - const message = err?.message || '启动本地 Gateway 失败'; + const message = err instanceof Error ? err.message : '启动本地 Gateway 失败'; const nextStatus = { ...get().localGateway, supported: true, @@ -1132,7 +1153,7 @@ export const useGatewayStore = create((set, get) => { set({ localGateway: status, localGatewayBusy: false }); return status; } catch (err: unknown) { - const message = err?.message || '停止本地 Gateway 失败'; + const message = err instanceof Error ? err.message : '停止本地 Gateway 失败'; const nextStatus = { ...get().localGateway, supported: true, @@ -1156,7 +1177,7 @@ export const useGatewayStore = create((set, get) => { set({ localGateway: status, localGatewayBusy: false }); return status; } catch (err: unknown) { - const message = err?.message || '重启本地 Gateway 失败'; + const message = err instanceof Error ? err.message : '重启本地 Gateway 失败'; const nextStatus = { ...get().localGateway, supported: true, @@ -1522,13 +1543,13 @@ export const useGatewayStore = create((set, get) => { const approvals: Approval[] = (result?.approvals || []).map((a: RawApproval) => ({ id: a.id || a.approval_id || '', handName: a.hand_name || a.handName || '', - runId: a.run_id || a.runId || '', - status: a.status || 'pending', + runId: a.run_id || a.runId, + status: (a.status || 'pending') as ApprovalStatus, requestedAt: a.requested_at || a.requestedAt || new Date().toISOString(), - requestedBy: a.requested_by || a.requestedBy || '', - reason: a.reason || a.description || '', - action: a.action || 'execute', - params: a.params || {}, + requestedBy: a.requested_by || a.requester, + reason: a.reason || a.description, + action: a.action, + params: a.params, respondedAt: a.responded_at || a.respondedAt, respondedBy: a.responded_by || a.respondedBy, responseReason: a.response_reason || a.responseReason, @@ -1553,15 +1574,17 @@ export const useGatewayStore = create((set, get) => { loadSessions: async (opts?: { limit?: number; offset?: number }) => { try { const result = await get().client.listSessions(opts); - const sessions: Session[] = (result?.sessions || []).map((s: RawSession) => ({ - id: s.id, - agentId: s.agent_id, - createdAt: s.created_at, - updatedAt: s.updated_at, - messageCount: s.message_count, - status: s.status, - metadata: s.metadata, - })); + const sessions: Session[] = (result?.sessions || []) + .filter((s: RawSession) => s.id || s.session_id) // Filter out sessions without IDs + .map((s: RawSession) => ({ + id: s.id || s.session_id || '', + agentId: s.agent_id || s.agentId || '', + createdAt: s.created_at || s.createdAt || new Date().toISOString(), + updatedAt: s.updated_at || s.updatedAt, + messageCount: s.message_count || s.messageCount, + status: s.status as Session['status'], + metadata: s.metadata, + })); set({ sessions }); } catch { /* ignore if sessions API not available */ @@ -1631,10 +1654,10 @@ export const useGatewayStore = create((set, get) => { try { const result = await get().client.getSessionMessages(sessionId, opts); const messages: SessionMessage[] = (result?.messages || []).map((m: RawSessionMessage) => ({ - id: m.id, - role: m.role, - content: m.content, - createdAt: m.created_at, + id: m.id || m.message_id || '', + role: (m.role || 'user') as 'user' | 'assistant' | 'system', + content: m.content || '', + createdAt: m.created_at || m.createdAt || new Date().toISOString(), tokens: m.tokens, })); set(state => ({ @@ -1668,13 +1691,10 @@ export const useGatewayStore = create((set, get) => { try { const result = await get().client.listWorkflowRuns(workflowId, opts); const runs: WorkflowRun[] = (result?.runs || []).map((r: RawWorkflowRun) => ({ - runId: r.runId || r.run_id, - status: r.status, - startedAt: r.startedAt || r.started_at, - completedAt: r.completedAt || r.completed_at, - step: r.step, + runId: r.runId || r.run_id || r.id || '', + status: r.status || 'unknown', + step: r.step || r.currentStep?.toString(), result: r.result, - error: r.error, })); // Store runs by workflow ID set(state => ({ diff --git a/desktop/src/types/hands.ts b/desktop/src/types/hands.ts index 9a787e8..cba7db7 100644 --- a/desktop/src/types/hands.ts +++ b/desktop/src/types/hands.ts @@ -11,7 +11,7 @@ * - Browser: Browser automation */ -export type HandStatus = 'idle' | 'running' | 'needs_approval' | 'completed' | 'error'; +export type HandStatus = 'idle' | 'running' | 'needs_approval' | 'error' | 'unavailable' | 'setup_needed'; export type HandId = 'clip' | 'lead' | 'collector' | 'predictor' | 'researcher' | 'twitter' | 'browser'; @@ -35,10 +35,10 @@ export interface HandParameter { } export interface Hand { - id: HandId; + id: string; // Can be HandId or any string from backend name: string; description: string; - icon: string; + icon?: string; // Optional, as backend may not provide it status: HandStatus; parameters?: HandParameter[]; lastRun?: string; diff --git a/desktop/test-results/.last-run.json b/desktop/test-results/.last-run.json index f28959e..cbcc1fb 100644 --- a/desktop/test-results/.last-run.json +++ b/desktop/test-results/.last-run.json @@ -1,11 +1,4 @@ { - "status": "failed", - "failedTests": [ - "ea562bc8f2f5f42dadea-a9ad995be4600240d5d9", - "ea562bc8f2f5f42dadea-aa98d5dacb19aae6a62f", - "ea562bc8f2f5f42dadea-24005574dbd87061e5f7", - "ea562bc8f2f5f42dadea-faee21c3e777f7004b5c", - "ea562bc8f2f5f42dadea-27f22490c6765498e906", - "ea562bc8f2f5f42dadea-233185470e18cdb79c26" - ] + "status": "passed", + "failedTests": [] } \ No newline at end of file diff --git a/desktop/test-results/functional-scenarios-1-应用启动与初始化-1-1-应用正常启动并渲染所有核心组件-chromium/error-context.md b/desktop/test-results/functional-scenarios-1-应用启动与初始化-1-1-应用正常启动并渲染所有核心组件-chromium/error-context.md deleted file mode 100644 index 691d255..0000000 --- a/desktop/test-results/functional-scenarios-1-应用启动与初始化-1-1-应用正常启动并渲染所有核心组件-chromium/error-context.md +++ /dev/null @@ -1,246 +0,0 @@ -# Page snapshot - -```yaml -- generic [ref=e3]: - - complementary [ref=e4]: - - tablist [ref=e5]: - - tab "分身" [selected] [ref=e6]: - - img [ref=e7] - - generic [ref=e10]: 分身 - - tab "Hands" [ref=e11]: - - img [ref=e12] - - generic [ref=e14]: Hands - - tab "工作流" [ref=e15]: - - img [ref=e16] - - generic [ref=e20]: 工作流 - - tab "团队" [ref=e21]: - - img [ref=e22] - - generic [ref=e27]: 团队 - - tab "协作" [ref=e28]: - - img [ref=e29] - - generic [ref=e33]: 协作 - - generic [ref=e37]: - - generic [ref=e38] [cursor=pointer]: - - img [ref=e40] - - generic [ref=e43]: - - generic [ref=e44]: - - generic [ref=e45]: trader-hand - - generic [ref=e46]: 当前 - - paragraph [ref=e47]: 新分身 - - button "删除": - - img - - generic [ref=e48] [cursor=pointer]: - - img [ref=e50] - - generic [ref=e53]: - - generic [ref=e55]: researcher - - paragraph [ref=e56]: 新分身 - - button "删除": - - img - - generic [ref=e57] [cursor=pointer]: - - img [ref=e59] - - generic [ref=e62]: - - generic [ref=e64]: browser-hand - - paragraph [ref=e65]: 新分身 - - button "删除": - - img - - generic [ref=e66] [cursor=pointer]: - - img [ref=e68] - - generic [ref=e71]: - - generic [ref=e73]: collector-hand - - paragraph [ref=e74]: 新分身 - - button "删除": - - img - - generic [ref=e75] [cursor=pointer]: - - img [ref=e77] - - generic [ref=e80]: - - generic [ref=e82]: researcher-hand - - paragraph [ref=e83]: 新分身 - - button "删除": - - img - - generic [ref=e84] [cursor=pointer]: - - img [ref=e86] - - generic [ref=e89]: - - generic [ref=e91]: lead-hand - - paragraph [ref=e92]: 新分身 - - button "删除": - - img - - generic [ref=e93] [cursor=pointer]: - - img [ref=e95] - - generic [ref=e98]: - - generic [ref=e100]: test-agent - - paragraph [ref=e101]: 新分身 - - button "删除": - - img - - generic [ref=e102] [cursor=pointer]: - - img [ref=e104] - - generic [ref=e107]: - - generic [ref=e109]: predictor-hand - - paragraph [ref=e110]: 新分身 - - button "删除": - - img - - generic [ref=e111] [cursor=pointer]: - - img [ref=e113] - - generic [ref=e116]: - - generic [ref=e118]: 测试助手 - - paragraph [ref=e119]: 新分身 - - button "删除": - - img - - generic [ref=e120] [cursor=pointer]: - - img [ref=e122] - - generic [ref=e125]: 创建新 Agent - - generic [ref=e127]: - - generic [ref=e128]: 用 - - generic [ref=e129]: 用户 - - button "打开设置" [ref=e130]: - - img [ref=e131] - - main [ref=e134]: - - generic [ref=e136]: - - heading "trader-hand" [level=2] [ref=e137] - - generic [ref=e138]: Gateway 已连接 - - generic [ref=e142]: - - generic [ref=e145]: 🦞 - - paragraph [ref=e147]: 你好! 我是 trader-hand。有什么我可以帮你的吗? - - generic [ref=e148]: - - generic [ref=e149]: - - img [ref=e150] - - generic [ref=e152]: 快速开始 - - button "💡 帮我写一个 Python 脚本处理 Excel 文件" [ref=e153]: - - generic [ref=e154]: 💡 - - generic [ref=e155]: 帮我写一个 Python 脚本处理 Excel 文件 - - img [ref=e156] - - button "📊 分析这个数据集的趋势和关键指标" [ref=e158]: - - generic [ref=e159]: 📊 - - generic [ref=e160]: 分析这个数据集的趋势和关键指标 - - img [ref=e161] - - button "✍️ 帮我起草一份产品需求文档" [ref=e163]: - - generic [ref=e164]: ✍️ - - generic [ref=e165]: 帮我起草一份产品需求文档 - - img [ref=e166] - - paragraph [ref=e168]: 发送消息开始对话,或点击上方建议 - - generic [ref=e170]: - - generic [ref=e171]: - - button "添加附件" [ref=e172]: - - img [ref=e173] - - textbox "发送给 trader-hand" [ref=e176] - - generic [ref=e177]: - - button "选择模型" [ref=e178]: - - generic [ref=e179]: glm-5 - - img [ref=e180] - - button "发送消息" [disabled] [ref=e182]: - - img [ref=e183] - - generic [ref=e185]: Agent 在本地运行,内容由 AI 生成 - - complementary [ref=e186]: - - generic [ref=e187]: - - generic [ref=e188]: - - generic [ref=e189]: - - img [ref=e190] - - generic [ref=e192]: "0" - - generic [ref=e193]: 当前消息 - - tablist [ref=e194]: - - tab "Status" [selected] [ref=e195]: - - img [ref=e196] - - tab "Files" [ref=e198]: - - img [ref=e199] - - tab "Agent" [ref=e202]: - - img [ref=e203] - - tab "Memory" [ref=e206]: - - img [ref=e207] - - generic [ref=e215]: - - generic [ref=e216]: - - generic [ref=e217]: - - generic [ref=e218]: - - img [ref=e219] - - generic [ref=e223]: Gateway Connected - - button "Refresh data" [ref=e224]: - - img [ref=e225] - - generic [ref=e230]: - - generic [ref=e231]: - - generic [ref=e232]: 地址 - - generic [ref=e233]: ws://127.0.0.1:50051/ws - - generic [ref=e234]: - - generic [ref=e235]: 当前模型 - - generic [ref=e236]: glm-5 - - generic [ref=e237]: - - heading "当前会话" [level=3] [ref=e238]: - - img [ref=e239] - - text: 当前会话 - - generic [ref=e241]: - - generic [ref=e242]: - - generic [ref=e243]: 用户消息 - - generic [ref=e244]: "0" - - generic [ref=e245]: - - generic [ref=e246]: 助手回复 - - generic [ref=e247]: "0" - - generic [ref=e248]: - - generic [ref=e249]: 工具调用 - - generic [ref=e250]: "0" - - generic [ref=e251]: - - generic [ref=e252]: 总消息数 - - generic [ref=e253]: "0" - - generic [ref=e254]: - - heading "分身状态" [level=3] [ref=e255]: - - img [ref=e256] - - text: 分身状态 - - generic [ref=e259]: - - generic [ref=e260]: - - img [ref=e262] - - generic [ref=e265]: trader-hand - - generic [ref=e266]: - - img [ref=e268] - - generic [ref=e271]: researcher - - generic [ref=e272]: - - img [ref=e274] - - generic [ref=e277]: browser-hand - - generic [ref=e278]: - - img [ref=e280] - - generic [ref=e283]: collector-hand - - generic [ref=e284]: - - img [ref=e286] - - generic [ref=e289]: researcher-hand - - paragraph [ref=e290]: +4 个分身 - - generic [ref=e291]: - - heading "用量统计" [level=3] [ref=e292]: - - img [ref=e293] - - text: 用量统计 - - generic [ref=e295]: - - generic [ref=e296]: - - generic [ref=e297]: 总会话数 - - generic [ref=e298]: "0" - - generic [ref=e299]: - - generic [ref=e300]: 总消息数 - - generic [ref=e301]: "0" - - generic [ref=e302]: - - generic [ref=e303]: 总 Token - - generic [ref=e304]: "0" - - generic [ref=e305]: - - heading "插件 (3)" [level=3] [ref=e306]: - - img [ref=e307] - - text: 插件 (3) - - generic [ref=e309]: - - generic [ref=e310]: - - generic [ref=e311]: Chat - - generic [ref=e312]: 运行中 - - generic [ref=e313]: - - generic [ref=e314]: Code - - generic [ref=e315]: 运行中 - - generic [ref=e316]: - - generic [ref=e317]: File - - generic [ref=e318]: 运行中 - - generic [ref=e319]: - - heading "运行概览" [level=3] [ref=e320]: - - img [ref=e321] - - text: 运行概览 - - generic [ref=e324]: - - generic [ref=e325]: - - generic [ref=e326]: 连接状态 - - generic [ref=e327]: 已连接 - - generic [ref=e328]: - - generic [ref=e329]: Gateway 版本 - - generic [ref=e330]: "-" - - generic [ref=e331]: - - generic [ref=e332]: 已加载分身 - - generic [ref=e333]: "9" - - generic [ref=e334]: - - generic [ref=e335]: 已加载插件 - - generic [ref=e336]: "3" -``` \ No newline at end of file diff --git a/desktop/test-results/functional-scenarios-1-应用启动与初始化-1-1-应用正常启动并渲染所有核心组件-chromium/test-failed-1.png b/desktop/test-results/functional-scenarios-1-应用启动与初始化-1-1-应用正常启动并渲染所有核心组件-chromium/test-failed-1.png deleted file mode 100644 index a798ec2..0000000 Binary files a/desktop/test-results/functional-scenarios-1-应用启动与初始化-1-1-应用正常启动并渲染所有核心组件-chromium/test-failed-1.png and /dev/null differ diff --git a/desktop/test-results/functional-scenarios-1-应用启动与初始化-1-1-应用正常启动并渲染所有核心组件-chromium/video.webm b/desktop/test-results/functional-scenarios-1-应用启动与初始化-1-1-应用正常启动并渲染所有核心组件-chromium/video.webm deleted file mode 100644 index 97eea70..0000000 Binary files a/desktop/test-results/functional-scenarios-1-应用启动与初始化-1-1-应用正常启动并渲染所有核心组件-chromium/video.webm and /dev/null differ diff --git a/desktop/test-results/functional-scenarios-10-完整用户流程-10-2-完整聊天流程-chromium/error-context.md b/desktop/test-results/functional-scenarios-10-完整用户流程-10-2-完整聊天流程-chromium/error-context.md deleted file mode 100644 index 8c385ff..0000000 --- a/desktop/test-results/functional-scenarios-10-完整用户流程-10-2-完整聊天流程-chromium/error-context.md +++ /dev/null @@ -1,243 +0,0 @@ -# Page snapshot - -```yaml -- generic [ref=e3]: - - complementary [ref=e4]: - - tablist [ref=e5]: - - tab "分身" [selected] [ref=e6]: - - img [ref=e7] - - generic [ref=e10]: 分身 - - tab "Hands" [ref=e11]: - - img [ref=e12] - - generic [ref=e14]: Hands - - tab "工作流" [ref=e15]: - - img [ref=e16] - - generic [ref=e20]: 工作流 - - tab "团队" [ref=e21]: - - img [ref=e22] - - generic [ref=e27]: 团队 - - tab "协作" [ref=e28]: - - img [ref=e29] - - generic [ref=e33]: 协作 - - generic [ref=e37]: - - generic [ref=e38] [cursor=pointer]: - - img [ref=e40] - - generic [ref=e43]: - - generic [ref=e44]: - - generic [ref=e45]: trader-hand - - generic [ref=e46]: 当前 - - paragraph [ref=e47]: 新分身 - - button "删除": - - img - - generic [ref=e48] [cursor=pointer]: - - img [ref=e50] - - generic [ref=e53]: - - generic [ref=e55]: researcher - - paragraph [ref=e56]: 新分身 - - button "删除": - - img - - generic [ref=e57] [cursor=pointer]: - - img [ref=e59] - - generic [ref=e62]: - - generic [ref=e64]: browser-hand - - paragraph [ref=e65]: 新分身 - - button "删除": - - img - - generic [ref=e66] [cursor=pointer]: - - img [ref=e68] - - generic [ref=e71]: - - generic [ref=e73]: collector-hand - - paragraph [ref=e74]: 新分身 - - button "删除": - - img - - generic [ref=e75] [cursor=pointer]: - - img [ref=e77] - - generic [ref=e80]: - - generic [ref=e82]: researcher-hand - - paragraph [ref=e83]: 新分身 - - button "删除": - - img - - generic [ref=e84] [cursor=pointer]: - - img [ref=e86] - - generic [ref=e89]: - - generic [ref=e91]: lead-hand - - paragraph [ref=e92]: 新分身 - - button "删除": - - img - - generic [ref=e93] [cursor=pointer]: - - img [ref=e95] - - generic [ref=e98]: - - generic [ref=e100]: test-agent - - paragraph [ref=e101]: 新分身 - - button "删除": - - img - - generic [ref=e102] [cursor=pointer]: - - img [ref=e104] - - generic [ref=e107]: - - generic [ref=e109]: predictor-hand - - paragraph [ref=e110]: 新分身 - - button "删除": - - img - - generic [ref=e111] [cursor=pointer]: - - img [ref=e113] - - generic [ref=e116]: - - generic [ref=e118]: 测试助手 - - paragraph [ref=e119]: 新分身 - - button "删除": - - img - - generic [ref=e120] [cursor=pointer]: - - img [ref=e122] - - generic [ref=e125]: 创建新 Agent - - generic [ref=e127]: - - generic [ref=e128]: 用 - - generic [ref=e129]: 用户 - - button "打开设置" [ref=e130]: - - img [ref=e131] - - main [ref=e134]: - - generic [ref=e135]: - - generic [ref=e136]: - - heading "trader-hand" [level=2] [ref=e137] - - generic [ref=e138]: 正在输入中 - - button "开始新对话" [ref=e141]: - - img [ref=e142] - - text: 新对话 - - generic [ref=e145]: - - generic [ref=e147]: - - generic [ref=e148]: 用 - - generic [ref=e151]: 你好 - - generic [ref=e153]: - - generic [ref=e154]: Z - - generic [ref=e156]: - - generic [ref=e157]: "⚠️ Request failed: Request failed: Missing API key: No LLM provider configured. Set an API key (e.g. GROQ_API_KEY) and restart, configure a provider via the dashboard, or use Ollama for local models (no API key neede..." - - paragraph [ref=e158]: "Request failed: Request failed: Missing API key: No LLM provider configured. Set an API key (e.g. GROQ_API_KEY) and restart, configure a provider via the dashboard, or use Ollama for local models (no API key neede..." - - generic [ref=e160]: - - generic [ref=e161]: 用 - - generic [ref=e164]: 请帮我写一个简单的函数 - - generic [ref=e167]: Z - - generic [ref=e173]: - - generic [ref=e174]: - - button "添加附件" [ref=e175]: - - img [ref=e176] - - textbox "Agent 正在回复..." [disabled] [ref=e179] - - generic [ref=e180]: - - button "选择模型" [ref=e181]: - - generic [ref=e182]: glm-5 - - img [ref=e183] - - button "发送消息" [disabled] [ref=e185]: - - img [ref=e186] - - generic [ref=e188]: Agent 在本地运行,内容由 AI 生成 - - complementary [ref=e189]: - - generic [ref=e190]: - - generic [ref=e191]: - - generic [ref=e192]: - - img [ref=e193] - - generic [ref=e195]: "4" - - generic [ref=e196]: 当前消息 - - tablist [ref=e197]: - - tab "Status" [selected] [ref=e198]: - - img [ref=e199] - - tab "Files" [ref=e201]: - - img [ref=e202] - - tab "Agent" [ref=e205]: - - img [ref=e206] - - tab "Memory" [ref=e209]: - - img [ref=e210] - - generic [ref=e218]: - - generic [ref=e219]: - - generic [ref=e220]: - - generic [ref=e221]: - - img [ref=e222] - - generic [ref=e226]: Gateway Connected - - button "Refresh data" [ref=e227]: - - img [ref=e228] - - generic [ref=e233]: - - generic [ref=e234]: - - generic [ref=e235]: 地址 - - generic [ref=e236]: ws://127.0.0.1:50051/ws - - generic [ref=e237]: - - generic [ref=e238]: 当前模型 - - generic [ref=e239]: glm-5 - - generic [ref=e240]: - - heading "当前会话" [level=3] [ref=e241]: - - img [ref=e242] - - text: 当前会话 - - generic [ref=e244]: - - generic [ref=e245]: - - generic [ref=e246]: 用户消息 - - generic [ref=e247]: "2" - - generic [ref=e248]: - - generic [ref=e249]: 助手回复 - - generic [ref=e250]: "2" - - generic [ref=e251]: - - generic [ref=e252]: 工具调用 - - generic [ref=e253]: "0" - - generic [ref=e254]: - - generic [ref=e255]: 总消息数 - - generic [ref=e256]: "4" - - generic [ref=e257]: - - heading "分身状态" [level=3] [ref=e258]: - - img [ref=e259] - - text: 分身状态 - - generic [ref=e262]: - - generic [ref=e263]: - - img [ref=e265] - - generic [ref=e268]: trader-hand - - generic [ref=e269]: - - img [ref=e271] - - generic [ref=e274]: researcher - - generic [ref=e275]: - - img [ref=e277] - - generic [ref=e280]: browser-hand - - generic [ref=e281]: - - img [ref=e283] - - generic [ref=e286]: collector-hand - - generic [ref=e287]: - - img [ref=e289] - - generic [ref=e292]: researcher-hand - - paragraph [ref=e293]: +4 个分身 - - generic [ref=e294]: - - heading "用量统计" [level=3] [ref=e295]: - - img [ref=e296] - - text: 用量统计 - - generic [ref=e298]: - - generic [ref=e299]: - - generic [ref=e300]: 总会话数 - - generic [ref=e301]: "0" - - generic [ref=e302]: - - generic [ref=e303]: 总消息数 - - generic [ref=e304]: "0" - - generic [ref=e305]: - - generic [ref=e306]: 总 Token - - generic [ref=e307]: "0" - - generic [ref=e308]: - - heading "插件 (3)" [level=3] [ref=e309]: - - img [ref=e310] - - text: 插件 (3) - - generic [ref=e312]: - - generic [ref=e313]: - - generic [ref=e314]: Chat - - generic [ref=e315]: 运行中 - - generic [ref=e316]: - - generic [ref=e317]: Code - - generic [ref=e318]: 运行中 - - generic [ref=e319]: - - generic [ref=e320]: File - - generic [ref=e321]: 运行中 - - generic [ref=e322]: - - heading "运行概览" [level=3] [ref=e323]: - - img [ref=e324] - - text: 运行概览 - - generic [ref=e327]: - - generic [ref=e328]: - - generic [ref=e329]: 连接状态 - - generic [ref=e330]: 已连接 - - generic [ref=e331]: - - generic [ref=e332]: Gateway 版本 - - generic [ref=e333]: "-" - - generic [ref=e334]: - - generic [ref=e335]: 已加载分身 - - generic [ref=e336]: "9" - - generic [ref=e337]: - - generic [ref=e338]: 已加载插件 - - generic [ref=e339]: "3" -``` \ No newline at end of file diff --git a/desktop/test-results/functional-scenarios-10-完整用户流程-10-2-完整聊天流程-chromium/test-failed-1.png b/desktop/test-results/functional-scenarios-10-完整用户流程-10-2-完整聊天流程-chromium/test-failed-1.png deleted file mode 100644 index 063154f..0000000 Binary files a/desktop/test-results/functional-scenarios-10-完整用户流程-10-2-完整聊天流程-chromium/test-failed-1.png and /dev/null differ diff --git a/desktop/test-results/functional-scenarios-10-完整用户流程-10-2-完整聊天流程-chromium/video.webm b/desktop/test-results/functional-scenarios-10-完整用户流程-10-2-完整聊天流程-chromium/video.webm deleted file mode 100644 index 5e87e63..0000000 Binary files a/desktop/test-results/functional-scenarios-10-完整用户流程-10-2-完整聊天流程-chromium/video.webm and /dev/null differ diff --git a/desktop/test-results/functional-scenarios-11-性能与稳定性-11-4-长时间运行稳定性-chromium/error-context.md b/desktop/test-results/functional-scenarios-11-性能与稳定性-11-4-长时间运行稳定性-chromium/error-context.md deleted file mode 100644 index c1cac1b..0000000 --- a/desktop/test-results/functional-scenarios-11-性能与稳定性-11-4-长时间运行稳定性-chromium/error-context.md +++ /dev/null @@ -1,243 +0,0 @@ -# Page snapshot - -```yaml -- generic [ref=e3]: - - complementary [ref=e4]: - - tablist [ref=e5]: - - tab "分身" [selected] [ref=e6]: - - img [ref=e7] - - generic [ref=e10]: 分身 - - tab "Hands" [ref=e11]: - - img [ref=e12] - - generic [ref=e14]: Hands - - tab "工作流" [ref=e15]: - - img [ref=e16] - - generic [ref=e20]: 工作流 - - tab "团队" [ref=e21]: - - img [ref=e22] - - generic [ref=e27]: 团队 - - tab "协作" [ref=e28]: - - img [ref=e29] - - generic [ref=e33]: 协作 - - generic [ref=e37]: - - generic [ref=e38] [cursor=pointer]: - - img [ref=e40] - - generic [ref=e43]: - - generic [ref=e44]: - - generic [ref=e45]: trader-hand - - generic [ref=e46]: 当前 - - paragraph [ref=e47]: 新分身 - - button "删除": - - img - - generic [ref=e48] [cursor=pointer]: - - img [ref=e50] - - generic [ref=e53]: - - generic [ref=e55]: researcher - - paragraph [ref=e56]: 新分身 - - button "删除": - - img - - generic [ref=e57] [cursor=pointer]: - - img [ref=e59] - - generic [ref=e62]: - - generic [ref=e64]: browser-hand - - paragraph [ref=e65]: 新分身 - - button "删除": - - img - - generic [ref=e66] [cursor=pointer]: - - img [ref=e68] - - generic [ref=e71]: - - generic [ref=e73]: collector-hand - - paragraph [ref=e74]: 新分身 - - button "删除": - - img - - generic [ref=e75] [cursor=pointer]: - - img [ref=e77] - - generic [ref=e80]: - - generic [ref=e82]: researcher-hand - - paragraph [ref=e83]: 新分身 - - button "删除": - - img - - generic [ref=e84] [cursor=pointer]: - - img [ref=e86] - - generic [ref=e89]: - - generic [ref=e91]: lead-hand - - paragraph [ref=e92]: 新分身 - - button "删除": - - img - - generic [ref=e93] [cursor=pointer]: - - img [ref=e95] - - generic [ref=e98]: - - generic [ref=e100]: test-agent - - paragraph [ref=e101]: 新分身 - - button "删除": - - img - - generic [ref=e102] [cursor=pointer]: - - img [ref=e104] - - generic [ref=e107]: - - generic [ref=e109]: predictor-hand - - paragraph [ref=e110]: 新分身 - - button "删除": - - img - - generic [ref=e111] [cursor=pointer]: - - img [ref=e113] - - generic [ref=e116]: - - generic [ref=e118]: 测试助手 - - paragraph [ref=e119]: 新分身 - - button "删除": - - img - - generic [ref=e120] [cursor=pointer]: - - img [ref=e122] - - generic [ref=e125]: 创建新 Agent - - generic [ref=e127]: - - generic [ref=e128]: 用 - - generic [ref=e129]: 用户 - - button "打开设置" [ref=e130]: - - img [ref=e131] - - main [ref=e134]: - - generic [ref=e135]: - - generic [ref=e136]: - - heading "trader-hand" [level=2] [ref=e137] - - generic [ref=e138]: 正在输入中 - - button "开始新对话" [ref=e141]: - - img [ref=e142] - - text: 新对话 - - generic [ref=e145]: - - generic [ref=e147]: - - generic [ref=e148]: 用 - - generic [ref=e151]: 测试消息 1 - - generic [ref=e153]: - - generic [ref=e154]: Z - - generic [ref=e156]: - - generic [ref=e157]: "⚠️ Request failed: Request failed: Missing API key: No LLM provider configured. Set an API key (e.g. GROQ_API_KEY) and restart, configure a provider via the dashboard, or use Ollama for local models (no API key neede..." - - paragraph [ref=e158]: "Request failed: Request failed: Missing API key: No LLM provider configured. Set an API key (e.g. GROQ_API_KEY) and restart, configure a provider via the dashboard, or use Ollama for local models (no API key neede..." - - generic [ref=e160]: - - generic [ref=e161]: 用 - - generic [ref=e164]: 测试消息 2 - - generic [ref=e167]: Z - - generic [ref=e173]: - - generic [ref=e174]: - - button "添加附件" [ref=e175]: - - img [ref=e176] - - textbox "Agent 正在回复..." [disabled] [ref=e179] - - generic [ref=e180]: - - button "选择模型" [ref=e181]: - - generic [ref=e182]: glm-5 - - img [ref=e183] - - button "发送消息" [disabled] [ref=e185]: - - img [ref=e186] - - generic [ref=e188]: Agent 在本地运行,内容由 AI 生成 - - complementary [ref=e189]: - - generic [ref=e190]: - - generic [ref=e191]: - - generic [ref=e192]: - - img [ref=e193] - - generic [ref=e195]: "4" - - generic [ref=e196]: 当前消息 - - tablist [ref=e197]: - - tab "Status" [selected] [ref=e198]: - - img [ref=e199] - - tab "Files" [ref=e201]: - - img [ref=e202] - - tab "Agent" [ref=e205]: - - img [ref=e206] - - tab "Memory" [ref=e209]: - - img [ref=e210] - - generic [ref=e218]: - - generic [ref=e219]: - - generic [ref=e220]: - - generic [ref=e221]: - - img [ref=e222] - - generic [ref=e226]: Gateway Connected - - button "Refresh data" [ref=e227]: - - img [ref=e228] - - generic [ref=e233]: - - generic [ref=e234]: - - generic [ref=e235]: 地址 - - generic [ref=e236]: ws://127.0.0.1:50051/ws - - generic [ref=e237]: - - generic [ref=e238]: 当前模型 - - generic [ref=e239]: glm-5 - - generic [ref=e240]: - - heading "当前会话" [level=3] [ref=e241]: - - img [ref=e242] - - text: 当前会话 - - generic [ref=e244]: - - generic [ref=e245]: - - generic [ref=e246]: 用户消息 - - generic [ref=e247]: "2" - - generic [ref=e248]: - - generic [ref=e249]: 助手回复 - - generic [ref=e250]: "2" - - generic [ref=e251]: - - generic [ref=e252]: 工具调用 - - generic [ref=e253]: "0" - - generic [ref=e254]: - - generic [ref=e255]: 总消息数 - - generic [ref=e256]: "4" - - generic [ref=e257]: - - heading "分身状态" [level=3] [ref=e258]: - - img [ref=e259] - - text: 分身状态 - - generic [ref=e262]: - - generic [ref=e263]: - - img [ref=e265] - - generic [ref=e268]: trader-hand - - generic [ref=e269]: - - img [ref=e271] - - generic [ref=e274]: researcher - - generic [ref=e275]: - - img [ref=e277] - - generic [ref=e280]: browser-hand - - generic [ref=e281]: - - img [ref=e283] - - generic [ref=e286]: collector-hand - - generic [ref=e287]: - - img [ref=e289] - - generic [ref=e292]: researcher-hand - - paragraph [ref=e293]: +4 个分身 - - generic [ref=e294]: - - heading "用量统计" [level=3] [ref=e295]: - - img [ref=e296] - - text: 用量统计 - - generic [ref=e298]: - - generic [ref=e299]: - - generic [ref=e300]: 总会话数 - - generic [ref=e301]: "0" - - generic [ref=e302]: - - generic [ref=e303]: 总消息数 - - generic [ref=e304]: "0" - - generic [ref=e305]: - - generic [ref=e306]: 总 Token - - generic [ref=e307]: "0" - - generic [ref=e308]: - - heading "插件 (3)" [level=3] [ref=e309]: - - img [ref=e310] - - text: 插件 (3) - - generic [ref=e312]: - - generic [ref=e313]: - - generic [ref=e314]: Chat - - generic [ref=e315]: 运行中 - - generic [ref=e316]: - - generic [ref=e317]: Code - - generic [ref=e318]: 运行中 - - generic [ref=e319]: - - generic [ref=e320]: File - - generic [ref=e321]: 运行中 - - generic [ref=e322]: - - heading "运行概览" [level=3] [ref=e323]: - - img [ref=e324] - - text: 运行概览 - - generic [ref=e327]: - - generic [ref=e328]: - - generic [ref=e329]: 连接状态 - - generic [ref=e330]: 已连接 - - generic [ref=e331]: - - generic [ref=e332]: Gateway 版本 - - generic [ref=e333]: "-" - - generic [ref=e334]: - - generic [ref=e335]: 已加载分身 - - generic [ref=e336]: "9" - - generic [ref=e337]: - - generic [ref=e338]: 已加载插件 - - generic [ref=e339]: "3" -``` \ No newline at end of file diff --git a/desktop/test-results/functional-scenarios-11-性能与稳定性-11-4-长时间运行稳定性-chromium/test-failed-1.png b/desktop/test-results/functional-scenarios-11-性能与稳定性-11-4-长时间运行稳定性-chromium/test-failed-1.png deleted file mode 100644 index f5d6e37..0000000 Binary files a/desktop/test-results/functional-scenarios-11-性能与稳定性-11-4-长时间运行稳定性-chromium/test-failed-1.png and /dev/null differ diff --git a/desktop/test-results/functional-scenarios-11-性能与稳定性-11-4-长时间运行稳定性-chromium/video.webm b/desktop/test-results/functional-scenarios-11-性能与稳定性-11-4-长时间运行稳定性-chromium/video.webm deleted file mode 100644 index 056f6b8..0000000 Binary files a/desktop/test-results/functional-scenarios-11-性能与稳定性-11-4-长时间运行稳定性-chromium/video.webm and /dev/null differ diff --git a/desktop/test-results/functional-scenarios-3-Agent-分身管理-3-1-分身列表显示-chromium/error-context.md b/desktop/test-results/functional-scenarios-3-Agent-分身管理-3-1-分身列表显示-chromium/error-context.md deleted file mode 100644 index 691d255..0000000 --- a/desktop/test-results/functional-scenarios-3-Agent-分身管理-3-1-分身列表显示-chromium/error-context.md +++ /dev/null @@ -1,246 +0,0 @@ -# Page snapshot - -```yaml -- generic [ref=e3]: - - complementary [ref=e4]: - - tablist [ref=e5]: - - tab "分身" [selected] [ref=e6]: - - img [ref=e7] - - generic [ref=e10]: 分身 - - tab "Hands" [ref=e11]: - - img [ref=e12] - - generic [ref=e14]: Hands - - tab "工作流" [ref=e15]: - - img [ref=e16] - - generic [ref=e20]: 工作流 - - tab "团队" [ref=e21]: - - img [ref=e22] - - generic [ref=e27]: 团队 - - tab "协作" [ref=e28]: - - img [ref=e29] - - generic [ref=e33]: 协作 - - generic [ref=e37]: - - generic [ref=e38] [cursor=pointer]: - - img [ref=e40] - - generic [ref=e43]: - - generic [ref=e44]: - - generic [ref=e45]: trader-hand - - generic [ref=e46]: 当前 - - paragraph [ref=e47]: 新分身 - - button "删除": - - img - - generic [ref=e48] [cursor=pointer]: - - img [ref=e50] - - generic [ref=e53]: - - generic [ref=e55]: researcher - - paragraph [ref=e56]: 新分身 - - button "删除": - - img - - generic [ref=e57] [cursor=pointer]: - - img [ref=e59] - - generic [ref=e62]: - - generic [ref=e64]: browser-hand - - paragraph [ref=e65]: 新分身 - - button "删除": - - img - - generic [ref=e66] [cursor=pointer]: - - img [ref=e68] - - generic [ref=e71]: - - generic [ref=e73]: collector-hand - - paragraph [ref=e74]: 新分身 - - button "删除": - - img - - generic [ref=e75] [cursor=pointer]: - - img [ref=e77] - - generic [ref=e80]: - - generic [ref=e82]: researcher-hand - - paragraph [ref=e83]: 新分身 - - button "删除": - - img - - generic [ref=e84] [cursor=pointer]: - - img [ref=e86] - - generic [ref=e89]: - - generic [ref=e91]: lead-hand - - paragraph [ref=e92]: 新分身 - - button "删除": - - img - - generic [ref=e93] [cursor=pointer]: - - img [ref=e95] - - generic [ref=e98]: - - generic [ref=e100]: test-agent - - paragraph [ref=e101]: 新分身 - - button "删除": - - img - - generic [ref=e102] [cursor=pointer]: - - img [ref=e104] - - generic [ref=e107]: - - generic [ref=e109]: predictor-hand - - paragraph [ref=e110]: 新分身 - - button "删除": - - img - - generic [ref=e111] [cursor=pointer]: - - img [ref=e113] - - generic [ref=e116]: - - generic [ref=e118]: 测试助手 - - paragraph [ref=e119]: 新分身 - - button "删除": - - img - - generic [ref=e120] [cursor=pointer]: - - img [ref=e122] - - generic [ref=e125]: 创建新 Agent - - generic [ref=e127]: - - generic [ref=e128]: 用 - - generic [ref=e129]: 用户 - - button "打开设置" [ref=e130]: - - img [ref=e131] - - main [ref=e134]: - - generic [ref=e136]: - - heading "trader-hand" [level=2] [ref=e137] - - generic [ref=e138]: Gateway 已连接 - - generic [ref=e142]: - - generic [ref=e145]: 🦞 - - paragraph [ref=e147]: 你好! 我是 trader-hand。有什么我可以帮你的吗? - - generic [ref=e148]: - - generic [ref=e149]: - - img [ref=e150] - - generic [ref=e152]: 快速开始 - - button "💡 帮我写一个 Python 脚本处理 Excel 文件" [ref=e153]: - - generic [ref=e154]: 💡 - - generic [ref=e155]: 帮我写一个 Python 脚本处理 Excel 文件 - - img [ref=e156] - - button "📊 分析这个数据集的趋势和关键指标" [ref=e158]: - - generic [ref=e159]: 📊 - - generic [ref=e160]: 分析这个数据集的趋势和关键指标 - - img [ref=e161] - - button "✍️ 帮我起草一份产品需求文档" [ref=e163]: - - generic [ref=e164]: ✍️ - - generic [ref=e165]: 帮我起草一份产品需求文档 - - img [ref=e166] - - paragraph [ref=e168]: 发送消息开始对话,或点击上方建议 - - generic [ref=e170]: - - generic [ref=e171]: - - button "添加附件" [ref=e172]: - - img [ref=e173] - - textbox "发送给 trader-hand" [ref=e176] - - generic [ref=e177]: - - button "选择模型" [ref=e178]: - - generic [ref=e179]: glm-5 - - img [ref=e180] - - button "发送消息" [disabled] [ref=e182]: - - img [ref=e183] - - generic [ref=e185]: Agent 在本地运行,内容由 AI 生成 - - complementary [ref=e186]: - - generic [ref=e187]: - - generic [ref=e188]: - - generic [ref=e189]: - - img [ref=e190] - - generic [ref=e192]: "0" - - generic [ref=e193]: 当前消息 - - tablist [ref=e194]: - - tab "Status" [selected] [ref=e195]: - - img [ref=e196] - - tab "Files" [ref=e198]: - - img [ref=e199] - - tab "Agent" [ref=e202]: - - img [ref=e203] - - tab "Memory" [ref=e206]: - - img [ref=e207] - - generic [ref=e215]: - - generic [ref=e216]: - - generic [ref=e217]: - - generic [ref=e218]: - - img [ref=e219] - - generic [ref=e223]: Gateway Connected - - button "Refresh data" [ref=e224]: - - img [ref=e225] - - generic [ref=e230]: - - generic [ref=e231]: - - generic [ref=e232]: 地址 - - generic [ref=e233]: ws://127.0.0.1:50051/ws - - generic [ref=e234]: - - generic [ref=e235]: 当前模型 - - generic [ref=e236]: glm-5 - - generic [ref=e237]: - - heading "当前会话" [level=3] [ref=e238]: - - img [ref=e239] - - text: 当前会话 - - generic [ref=e241]: - - generic [ref=e242]: - - generic [ref=e243]: 用户消息 - - generic [ref=e244]: "0" - - generic [ref=e245]: - - generic [ref=e246]: 助手回复 - - generic [ref=e247]: "0" - - generic [ref=e248]: - - generic [ref=e249]: 工具调用 - - generic [ref=e250]: "0" - - generic [ref=e251]: - - generic [ref=e252]: 总消息数 - - generic [ref=e253]: "0" - - generic [ref=e254]: - - heading "分身状态" [level=3] [ref=e255]: - - img [ref=e256] - - text: 分身状态 - - generic [ref=e259]: - - generic [ref=e260]: - - img [ref=e262] - - generic [ref=e265]: trader-hand - - generic [ref=e266]: - - img [ref=e268] - - generic [ref=e271]: researcher - - generic [ref=e272]: - - img [ref=e274] - - generic [ref=e277]: browser-hand - - generic [ref=e278]: - - img [ref=e280] - - generic [ref=e283]: collector-hand - - generic [ref=e284]: - - img [ref=e286] - - generic [ref=e289]: researcher-hand - - paragraph [ref=e290]: +4 个分身 - - generic [ref=e291]: - - heading "用量统计" [level=3] [ref=e292]: - - img [ref=e293] - - text: 用量统计 - - generic [ref=e295]: - - generic [ref=e296]: - - generic [ref=e297]: 总会话数 - - generic [ref=e298]: "0" - - generic [ref=e299]: - - generic [ref=e300]: 总消息数 - - generic [ref=e301]: "0" - - generic [ref=e302]: - - generic [ref=e303]: 总 Token - - generic [ref=e304]: "0" - - generic [ref=e305]: - - heading "插件 (3)" [level=3] [ref=e306]: - - img [ref=e307] - - text: 插件 (3) - - generic [ref=e309]: - - generic [ref=e310]: - - generic [ref=e311]: Chat - - generic [ref=e312]: 运行中 - - generic [ref=e313]: - - generic [ref=e314]: Code - - generic [ref=e315]: 运行中 - - generic [ref=e316]: - - generic [ref=e317]: File - - generic [ref=e318]: 运行中 - - generic [ref=e319]: - - heading "运行概览" [level=3] [ref=e320]: - - img [ref=e321] - - text: 运行概览 - - generic [ref=e324]: - - generic [ref=e325]: - - generic [ref=e326]: 连接状态 - - generic [ref=e327]: 已连接 - - generic [ref=e328]: - - generic [ref=e329]: Gateway 版本 - - generic [ref=e330]: "-" - - generic [ref=e331]: - - generic [ref=e332]: 已加载分身 - - generic [ref=e333]: "9" - - generic [ref=e334]: - - generic [ref=e335]: 已加载插件 - - generic [ref=e336]: "3" -``` \ No newline at end of file diff --git a/desktop/test-results/functional-scenarios-3-Agent-分身管理-3-1-分身列表显示-chromium/test-failed-1.png b/desktop/test-results/functional-scenarios-3-Agent-分身管理-3-1-分身列表显示-chromium/test-failed-1.png deleted file mode 100644 index f872849..0000000 Binary files a/desktop/test-results/functional-scenarios-3-Agent-分身管理-3-1-分身列表显示-chromium/test-failed-1.png and /dev/null differ diff --git a/desktop/test-results/functional-scenarios-3-Agent-分身管理-3-1-分身列表显示-chromium/video.webm b/desktop/test-results/functional-scenarios-3-Agent-分身管理-3-1-分身列表显示-chromium/video.webm deleted file mode 100644 index c54e6ef..0000000 Binary files a/desktop/test-results/functional-scenarios-3-Agent-分身管理-3-1-分身列表显示-chromium/video.webm and /dev/null differ diff --git a/desktop/test-results/functional-scenarios-4-Hands-系统-4-1-Hands-列表显示-chromium/error-context.md b/desktop/test-results/functional-scenarios-4-Hands-系统-4-1-Hands-列表显示-chromium/error-context.md deleted file mode 100644 index 691d255..0000000 --- a/desktop/test-results/functional-scenarios-4-Hands-系统-4-1-Hands-列表显示-chromium/error-context.md +++ /dev/null @@ -1,246 +0,0 @@ -# Page snapshot - -```yaml -- generic [ref=e3]: - - complementary [ref=e4]: - - tablist [ref=e5]: - - tab "分身" [selected] [ref=e6]: - - img [ref=e7] - - generic [ref=e10]: 分身 - - tab "Hands" [ref=e11]: - - img [ref=e12] - - generic [ref=e14]: Hands - - tab "工作流" [ref=e15]: - - img [ref=e16] - - generic [ref=e20]: 工作流 - - tab "团队" [ref=e21]: - - img [ref=e22] - - generic [ref=e27]: 团队 - - tab "协作" [ref=e28]: - - img [ref=e29] - - generic [ref=e33]: 协作 - - generic [ref=e37]: - - generic [ref=e38] [cursor=pointer]: - - img [ref=e40] - - generic [ref=e43]: - - generic [ref=e44]: - - generic [ref=e45]: trader-hand - - generic [ref=e46]: 当前 - - paragraph [ref=e47]: 新分身 - - button "删除": - - img - - generic [ref=e48] [cursor=pointer]: - - img [ref=e50] - - generic [ref=e53]: - - generic [ref=e55]: researcher - - paragraph [ref=e56]: 新分身 - - button "删除": - - img - - generic [ref=e57] [cursor=pointer]: - - img [ref=e59] - - generic [ref=e62]: - - generic [ref=e64]: browser-hand - - paragraph [ref=e65]: 新分身 - - button "删除": - - img - - generic [ref=e66] [cursor=pointer]: - - img [ref=e68] - - generic [ref=e71]: - - generic [ref=e73]: collector-hand - - paragraph [ref=e74]: 新分身 - - button "删除": - - img - - generic [ref=e75] [cursor=pointer]: - - img [ref=e77] - - generic [ref=e80]: - - generic [ref=e82]: researcher-hand - - paragraph [ref=e83]: 新分身 - - button "删除": - - img - - generic [ref=e84] [cursor=pointer]: - - img [ref=e86] - - generic [ref=e89]: - - generic [ref=e91]: lead-hand - - paragraph [ref=e92]: 新分身 - - button "删除": - - img - - generic [ref=e93] [cursor=pointer]: - - img [ref=e95] - - generic [ref=e98]: - - generic [ref=e100]: test-agent - - paragraph [ref=e101]: 新分身 - - button "删除": - - img - - generic [ref=e102] [cursor=pointer]: - - img [ref=e104] - - generic [ref=e107]: - - generic [ref=e109]: predictor-hand - - paragraph [ref=e110]: 新分身 - - button "删除": - - img - - generic [ref=e111] [cursor=pointer]: - - img [ref=e113] - - generic [ref=e116]: - - generic [ref=e118]: 测试助手 - - paragraph [ref=e119]: 新分身 - - button "删除": - - img - - generic [ref=e120] [cursor=pointer]: - - img [ref=e122] - - generic [ref=e125]: 创建新 Agent - - generic [ref=e127]: - - generic [ref=e128]: 用 - - generic [ref=e129]: 用户 - - button "打开设置" [ref=e130]: - - img [ref=e131] - - main [ref=e134]: - - generic [ref=e136]: - - heading "trader-hand" [level=2] [ref=e137] - - generic [ref=e138]: Gateway 已连接 - - generic [ref=e142]: - - generic [ref=e145]: 🦞 - - paragraph [ref=e147]: 你好! 我是 trader-hand。有什么我可以帮你的吗? - - generic [ref=e148]: - - generic [ref=e149]: - - img [ref=e150] - - generic [ref=e152]: 快速开始 - - button "💡 帮我写一个 Python 脚本处理 Excel 文件" [ref=e153]: - - generic [ref=e154]: 💡 - - generic [ref=e155]: 帮我写一个 Python 脚本处理 Excel 文件 - - img [ref=e156] - - button "📊 分析这个数据集的趋势和关键指标" [ref=e158]: - - generic [ref=e159]: 📊 - - generic [ref=e160]: 分析这个数据集的趋势和关键指标 - - img [ref=e161] - - button "✍️ 帮我起草一份产品需求文档" [ref=e163]: - - generic [ref=e164]: ✍️ - - generic [ref=e165]: 帮我起草一份产品需求文档 - - img [ref=e166] - - paragraph [ref=e168]: 发送消息开始对话,或点击上方建议 - - generic [ref=e170]: - - generic [ref=e171]: - - button "添加附件" [ref=e172]: - - img [ref=e173] - - textbox "发送给 trader-hand" [ref=e176] - - generic [ref=e177]: - - button "选择模型" [ref=e178]: - - generic [ref=e179]: glm-5 - - img [ref=e180] - - button "发送消息" [disabled] [ref=e182]: - - img [ref=e183] - - generic [ref=e185]: Agent 在本地运行,内容由 AI 生成 - - complementary [ref=e186]: - - generic [ref=e187]: - - generic [ref=e188]: - - generic [ref=e189]: - - img [ref=e190] - - generic [ref=e192]: "0" - - generic [ref=e193]: 当前消息 - - tablist [ref=e194]: - - tab "Status" [selected] [ref=e195]: - - img [ref=e196] - - tab "Files" [ref=e198]: - - img [ref=e199] - - tab "Agent" [ref=e202]: - - img [ref=e203] - - tab "Memory" [ref=e206]: - - img [ref=e207] - - generic [ref=e215]: - - generic [ref=e216]: - - generic [ref=e217]: - - generic [ref=e218]: - - img [ref=e219] - - generic [ref=e223]: Gateway Connected - - button "Refresh data" [ref=e224]: - - img [ref=e225] - - generic [ref=e230]: - - generic [ref=e231]: - - generic [ref=e232]: 地址 - - generic [ref=e233]: ws://127.0.0.1:50051/ws - - generic [ref=e234]: - - generic [ref=e235]: 当前模型 - - generic [ref=e236]: glm-5 - - generic [ref=e237]: - - heading "当前会话" [level=3] [ref=e238]: - - img [ref=e239] - - text: 当前会话 - - generic [ref=e241]: - - generic [ref=e242]: - - generic [ref=e243]: 用户消息 - - generic [ref=e244]: "0" - - generic [ref=e245]: - - generic [ref=e246]: 助手回复 - - generic [ref=e247]: "0" - - generic [ref=e248]: - - generic [ref=e249]: 工具调用 - - generic [ref=e250]: "0" - - generic [ref=e251]: - - generic [ref=e252]: 总消息数 - - generic [ref=e253]: "0" - - generic [ref=e254]: - - heading "分身状态" [level=3] [ref=e255]: - - img [ref=e256] - - text: 分身状态 - - generic [ref=e259]: - - generic [ref=e260]: - - img [ref=e262] - - generic [ref=e265]: trader-hand - - generic [ref=e266]: - - img [ref=e268] - - generic [ref=e271]: researcher - - generic [ref=e272]: - - img [ref=e274] - - generic [ref=e277]: browser-hand - - generic [ref=e278]: - - img [ref=e280] - - generic [ref=e283]: collector-hand - - generic [ref=e284]: - - img [ref=e286] - - generic [ref=e289]: researcher-hand - - paragraph [ref=e290]: +4 个分身 - - generic [ref=e291]: - - heading "用量统计" [level=3] [ref=e292]: - - img [ref=e293] - - text: 用量统计 - - generic [ref=e295]: - - generic [ref=e296]: - - generic [ref=e297]: 总会话数 - - generic [ref=e298]: "0" - - generic [ref=e299]: - - generic [ref=e300]: 总消息数 - - generic [ref=e301]: "0" - - generic [ref=e302]: - - generic [ref=e303]: 总 Token - - generic [ref=e304]: "0" - - generic [ref=e305]: - - heading "插件 (3)" [level=3] [ref=e306]: - - img [ref=e307] - - text: 插件 (3) - - generic [ref=e309]: - - generic [ref=e310]: - - generic [ref=e311]: Chat - - generic [ref=e312]: 运行中 - - generic [ref=e313]: - - generic [ref=e314]: Code - - generic [ref=e315]: 运行中 - - generic [ref=e316]: - - generic [ref=e317]: File - - generic [ref=e318]: 运行中 - - generic [ref=e319]: - - heading "运行概览" [level=3] [ref=e320]: - - img [ref=e321] - - text: 运行概览 - - generic [ref=e324]: - - generic [ref=e325]: - - generic [ref=e326]: 连接状态 - - generic [ref=e327]: 已连接 - - generic [ref=e328]: - - generic [ref=e329]: Gateway 版本 - - generic [ref=e330]: "-" - - generic [ref=e331]: - - generic [ref=e332]: 已加载分身 - - generic [ref=e333]: "9" - - generic [ref=e334]: - - generic [ref=e335]: 已加载插件 - - generic [ref=e336]: "3" -``` \ No newline at end of file diff --git a/desktop/test-results/functional-scenarios-4-Hands-系统-4-1-Hands-列表显示-chromium/test-failed-1.png b/desktop/test-results/functional-scenarios-4-Hands-系统-4-1-Hands-列表显示-chromium/test-failed-1.png deleted file mode 100644 index f872849..0000000 Binary files a/desktop/test-results/functional-scenarios-4-Hands-系统-4-1-Hands-列表显示-chromium/test-failed-1.png and /dev/null differ diff --git a/desktop/test-results/functional-scenarios-4-Hands-系统-4-1-Hands-列表显示-chromium/video.webm b/desktop/test-results/functional-scenarios-4-Hands-系统-4-1-Hands-列表显示-chromium/video.webm deleted file mode 100644 index 2e8c5ff..0000000 Binary files a/desktop/test-results/functional-scenarios-4-Hands-系统-4-1-Hands-列表显示-chromium/video.webm and /dev/null differ diff --git a/desktop/test-results/functional-scenarios-8-设置页面-8-3-模型配置-chromium/error-context.md b/desktop/test-results/functional-scenarios-8-设置页面-8-3-模型配置-chromium/error-context.md deleted file mode 100644 index 094c1da..0000000 --- a/desktop/test-results/functional-scenarios-8-设置页面-8-3-模型配置-chromium/error-context.md +++ /dev/null @@ -1,89 +0,0 @@ -# Page snapshot - -```yaml -- generic [ref=e3]: - - complementary [ref=e4]: - - button "返回应用" [ref=e6]: - - img [ref=e7] - - generic [ref=e9]: 返回应用 - - navigation [ref=e10]: - - button "通用" [ref=e11]: - - img [ref=e12] - - generic [ref=e15]: 通用 - - button "用量统计" [ref=e16]: - - img [ref=e17] - - generic [ref=e19]: 用量统计 - - button "积分详情" [ref=e20]: - - img [ref=e21] - - generic [ref=e26]: 积分详情 - - button "模型与 API" [ref=e27]: - - img [ref=e28] - - generic [ref=e31]: 模型与 API - - button "MCP 服务" [ref=e32]: - - img [ref=e33] - - generic [ref=e35]: MCP 服务 - - button "技能" [ref=e36]: - - img [ref=e37] - - generic [ref=e39]: 技能 - - button "IM 频道" [ref=e40]: - - img [ref=e41] - - generic [ref=e43]: IM 频道 - - button "工作区" [ref=e44]: - - img [ref=e45] - - generic [ref=e47]: 工作区 - - button "数据与隐私" [ref=e48]: - - img [ref=e49] - - generic [ref=e51]: 数据与隐私 - - button "安全状态" [ref=e52]: - - img [ref=e53] - - generic [ref=e55]: 安全状态 - - button "审计日志" [ref=e56]: - - img [ref=e57] - - generic [ref=e60]: 审计日志 - - button "定时任务" [ref=e61]: - - img [ref=e62] - - generic [ref=e65]: 定时任务 - - button "提交反馈" [ref=e66]: - - img [ref=e67] - - generic [ref=e70]: 提交反馈 - - button "关于" [ref=e71]: - - img [ref=e72] - - generic [ref=e74]: 关于 - - main [ref=e75]: - - generic [ref=e76]: - - heading "通用设置" [level=1] [ref=e77] - - heading "Gateway 连接" [level=2] [ref=e78] - - generic [ref=e79]: - - generic [ref=e80]: - - generic [ref=e81]: 状态 - - generic [ref=e84]: 已连接 - - generic [ref=e85]: - - generic [ref=e86]: 地址 - - generic [ref=e87]: ws://127.0.0.1:50051 - - generic [ref=e88]: - - generic [ref=e89]: Token - - textbox "可选:Gateway auth token" [ref=e90] - - generic [ref=e91]: - - generic [ref=e92]: 当前模型 - - generic [ref=e93]: glm-5 - - button "断开连接" [ref=e95] - - heading "外观与行为" [level=2] [ref=e96] - - generic [ref=e97]: - - generic [ref=e98]: - - generic [ref=e99]: - - generic [ref=e100]: 主题模式 - - generic [ref=e101]: 选择浅色或深色模式。 - - generic [ref=e102]: - - button [ref=e103] - - button [ref=e104] - - generic [ref=e105]: - - generic [ref=e106]: - - generic [ref=e107]: 开机自启 - - generic [ref=e108]: 登录时自动启动 ZCLAW。 - - button [ref=e109] - - generic [ref=e111]: - - generic [ref=e112]: - - generic [ref=e113]: 显示工具调用 - - generic [ref=e114]: 在对话消息中显示模型的工具调用详情块。 - - button [ref=e115] -``` \ No newline at end of file diff --git a/desktop/test-results/functional-scenarios-8-设置页面-8-3-模型配置-chromium/test-failed-1.png b/desktop/test-results/functional-scenarios-8-设置页面-8-3-模型配置-chromium/test-failed-1.png deleted file mode 100644 index dae5e58..0000000 Binary files a/desktop/test-results/functional-scenarios-8-设置页面-8-3-模型配置-chromium/test-failed-1.png and /dev/null differ diff --git a/desktop/test-results/functional-scenarios-8-设置页面-8-3-模型配置-chromium/video.webm b/desktop/test-results/functional-scenarios-8-设置页面-8-3-模型配置-chromium/video.webm deleted file mode 100644 index 17db473..0000000 Binary files a/desktop/test-results/functional-scenarios-8-设置页面-8-3-模型配置-chromium/video.webm and /dev/null differ diff --git a/desktop/test-results/screenshots/01-app-layout.png b/desktop/test-results/screenshots/01-app-layout.png index f872849..b17b8f1 100644 Binary files a/desktop/test-results/screenshots/01-app-layout.png and b/desktop/test-results/screenshots/01-app-layout.png differ diff --git a/desktop/test-results/screenshots/02-connection-state.png b/desktop/test-results/screenshots/02-connection-state.png index f872849..b17b8f1 100644 Binary files a/desktop/test-results/screenshots/02-connection-state.png and b/desktop/test-results/screenshots/02-connection-state.png differ diff --git a/desktop/test-results/screenshots/02-sidebar-navigation.png b/desktop/test-results/screenshots/02-sidebar-navigation.png index f872849..b17b8f1 100644 Binary files a/desktop/test-results/screenshots/02-sidebar-navigation.png and b/desktop/test-results/screenshots/02-sidebar-navigation.png differ diff --git a/desktop/test-results/screenshots/03-chat-input.png b/desktop/test-results/screenshots/03-chat-input.png index d452756..65b366a 100644 Binary files a/desktop/test-results/screenshots/03-chat-input.png and b/desktop/test-results/screenshots/03-chat-input.png differ diff --git a/desktop/test-results/screenshots/03-navigation-switch.png b/desktop/test-results/screenshots/03-navigation-switch.png index f7dfb18..4a3e5d5 100644 Binary files a/desktop/test-results/screenshots/03-navigation-switch.png and b/desktop/test-results/screenshots/03-navigation-switch.png differ diff --git a/desktop/test-results/screenshots/04-chat-response.png b/desktop/test-results/screenshots/04-chat-response.png index 10417a6..7a0e82c 100644 Binary files a/desktop/test-results/screenshots/04-chat-response.png and b/desktop/test-results/screenshots/04-chat-response.png differ diff --git a/desktop/test-results/screenshots/05-chat-area.png b/desktop/test-results/screenshots/05-chat-area.png index 1d548e2..b17b8f1 100644 Binary files a/desktop/test-results/screenshots/05-chat-area.png and b/desktop/test-results/screenshots/05-chat-area.png differ diff --git a/desktop/test-results/screenshots/06-message-send.png b/desktop/test-results/screenshots/06-message-send.png index 2f8df63..f349a17 100644 Binary files a/desktop/test-results/screenshots/06-message-send.png and b/desktop/test-results/screenshots/06-message-send.png differ diff --git a/desktop/test-results/screenshots/07-conversation-list.png b/desktop/test-results/screenshots/07-conversation-list.png index a798ec2..b17b8f1 100644 Binary files a/desktop/test-results/screenshots/07-conversation-list.png and b/desktop/test-results/screenshots/07-conversation-list.png differ diff --git a/desktop/test-results/screenshots/07-streaming-response.png b/desktop/test-results/screenshots/07-streaming-response.png index 586abe2..05d6abc 100644 Binary files a/desktop/test-results/screenshots/07-streaming-response.png and b/desktop/test-results/screenshots/07-streaming-response.png differ diff --git a/desktop/test-results/screenshots/08-hands-list.png b/desktop/test-results/screenshots/08-hands-list.png index a798ec2..b17b8f1 100644 Binary files a/desktop/test-results/screenshots/08-hands-list.png and b/desktop/test-results/screenshots/08-hands-list.png differ diff --git a/desktop/test-results/screenshots/08-offline-error.png b/desktop/test-results/screenshots/08-offline-error.png index 279ceb1..7a8516d 100644 Binary files a/desktop/test-results/screenshots/08-offline-error.png and b/desktop/test-results/screenshots/08-offline-error.png differ diff --git a/desktop/test-results/screenshots/10-scheduler-panel.png b/desktop/test-results/screenshots/10-scheduler-panel.png index a798ec2..b17b8f1 100644 Binary files a/desktop/test-results/screenshots/10-scheduler-panel.png and b/desktop/test-results/screenshots/10-scheduler-panel.png differ diff --git a/desktop/test-results/screenshots/12-team-view.png b/desktop/test-results/screenshots/12-team-view.png index a798ec2..b17b8f1 100644 Binary files a/desktop/test-results/screenshots/12-team-view.png and b/desktop/test-results/screenshots/12-team-view.png differ diff --git a/desktop/test-results/screenshots/13-swarm-dashboard.png b/desktop/test-results/screenshots/13-swarm-dashboard.png index f872849..b17b8f1 100644 Binary files a/desktop/test-results/screenshots/13-swarm-dashboard.png and b/desktop/test-results/screenshots/13-swarm-dashboard.png differ diff --git a/desktop/test-results/screenshots/17-right-panel.png b/desktop/test-results/screenshots/17-right-panel.png index a798ec2..b17b8f1 100644 Binary files a/desktop/test-results/screenshots/17-right-panel.png and b/desktop/test-results/screenshots/17-right-panel.png differ diff --git a/desktop/test-results/screenshots/17-workflow-list.png b/desktop/test-results/screenshots/17-workflow-list.png index f872849..3507cc0 100644 Binary files a/desktop/test-results/screenshots/17-workflow-list.png and b/desktop/test-results/screenshots/17-workflow-list.png differ diff --git a/desktop/test-results/screenshots/18-offline-error.png b/desktop/test-results/screenshots/18-offline-error.png index a798ec2..b17b8f1 100644 Binary files a/desktop/test-results/screenshots/18-offline-error.png and b/desktop/test-results/screenshots/18-offline-error.png differ diff --git a/desktop/test-results/screenshots/18-workflow-create.png b/desktop/test-results/screenshots/18-workflow-create.png deleted file mode 100644 index 1274e56..0000000 Binary files a/desktop/test-results/screenshots/18-workflow-create.png and /dev/null differ diff --git a/desktop/test-results/screenshots/20-mobile-layout.png b/desktop/test-results/screenshots/20-mobile-layout.png index 77c4e3d..5e74631 100644 Binary files a/desktop/test-results/screenshots/20-mobile-layout.png and b/desktop/test-results/screenshots/20-mobile-layout.png differ diff --git a/desktop/test-results/screenshots/21-tablet-layout.png b/desktop/test-results/screenshots/21-tablet-layout.png index 396795e..963bd51 100644 Binary files a/desktop/test-results/screenshots/21-tablet-layout.png and b/desktop/test-results/screenshots/21-tablet-layout.png differ diff --git a/desktop/test-results/screenshots/21-team-list.png b/desktop/test-results/screenshots/21-team-list.png index f872849..0adf228 100644 Binary files a/desktop/test-results/screenshots/21-team-list.png and b/desktop/test-results/screenshots/21-team-list.png differ diff --git a/desktop/test-results/screenshots/22-desktop-layout.png b/desktop/test-results/screenshots/22-desktop-layout.png index 7618cc5..d057a6a 100644 Binary files a/desktop/test-results/screenshots/22-desktop-layout.png and b/desktop/test-results/screenshots/22-desktop-layout.png differ diff --git a/desktop/test-results/screenshots/24-swarm-dashboard.png b/desktop/test-results/screenshots/24-swarm-dashboard.png index f872849..900c7f1 100644 Binary files a/desktop/test-results/screenshots/24-swarm-dashboard.png and b/desktop/test-results/screenshots/24-swarm-dashboard.png differ diff --git a/desktop/test-results/screenshots/32-right-panel.png b/desktop/test-results/screenshots/32-right-panel.png index f872849..b17b8f1 100644 Binary files a/desktop/test-results/screenshots/32-right-panel.png and b/desktop/test-results/screenshots/32-right-panel.png differ diff --git a/desktop/test-results/screenshots/35-first-time-user.png b/desktop/test-results/screenshots/35-first-time-user.png index a798ec2..b17b8f1 100644 Binary files a/desktop/test-results/screenshots/35-first-time-user.png and b/desktop/test-results/screenshots/35-first-time-user.png differ diff --git a/desktop/test-results/screenshots/37-view-switching.png b/desktop/test-results/screenshots/37-view-switching.png index f872849..0adf228 100644 Binary files a/desktop/test-results/screenshots/37-view-switching.png and b/desktop/test-results/screenshots/37-view-switching.png differ diff --git a/desktop/test-results/screenshots/38-session-persistence.png b/desktop/test-results/screenshots/38-session-persistence.png index e8e1564..a3b3ddc 100644 Binary files a/desktop/test-results/screenshots/38-session-persistence.png and b/desktop/test-results/screenshots/38-session-persistence.png differ diff --git a/desktop/test-results/screenshots/39-rapid-switching.png b/desktop/test-results/screenshots/39-rapid-switching.png index f872849..0adf228 100644 Binary files a/desktop/test-results/screenshots/39-rapid-switching.png and b/desktop/test-results/screenshots/39-rapid-switching.png differ diff --git a/desktop/test-results/screenshots/41-keyboard-nav.png b/desktop/test-results/screenshots/41-keyboard-nav.png index a4fc7c5..79a5ba6 100644 Binary files a/desktop/test-results/screenshots/41-keyboard-nav.png and b/desktop/test-results/screenshots/41-keyboard-nav.png differ diff --git a/desktop/tests/e2e/KNOWN_ISSUES.md b/desktop/tests/e2e/KNOWN_ISSUES.md index 035d465..ccbbae6 100644 --- a/desktop/tests/e2e/KNOWN_ISSUES.md +++ b/desktop/tests/e2e/KNOWN_ISSUES.md @@ -1,14 +1,14 @@ # E2E 测试已知问题与修复指南 > 最后更新: 2026-03-17 -> 测试通过率: 88% (65/74) +> 测试通过率: **100%** (74/74) ✅ ## 当前状态 ### 测试结果摘要 - **总测试**: 74 -- **通过**: 65 -- **失败**: 9 +- **通过**: 74 +- **失败**: 0 ### 快速运行测试命令 ```bash @@ -26,119 +26,31 @@ pnpm exec playwright test --config=tests/e2e/playwright.config.ts tests/e2e/spec --- -## 问题 1: 聊天输入禁用问题 +## 已修复的问题 -### 现象 -测试在尝试填写聊天输入框时失败,因为 Agent 正在回复中 (`isStreaming=true`),导致输入框被禁用。 +### 问题 1: 聊天输入禁用问题 ✅ 已修复 +- **根因**: Agent 正在回复时 (`isStreaming=true`),输入框被禁用 +- **修复**: 添加 `waitForChatReady` 辅助函数等待输入框可用 -### 错误信息 -``` -locator resolved to