refactor(types): comprehensive TypeScript type system improvements

Major type system refactoring and error fixes across the codebase:

**Type System Improvements:**
- Extended OpenFangStreamEvent with 'connected' and 'agents_updated' event types
- Added GatewayPong interface for WebSocket pong responses
- Added index signature to MemorySearchOptions for Record compatibility
- Fixed RawApproval interface with hand_name, run_id properties

**Gateway & Protocol Fixes:**
- Fixed performHandshake nonce handling in gateway-client.ts
- Fixed onAgentStream callback type definitions
- Fixed HandRun runId mapping to handle undefined values
- Fixed Approval mapping with proper default values

**Memory System Fixes:**
- Fixed MemoryEntry creation with required properties (lastAccessedAt, accessCount)
- Replaced getByAgent with getAll method in vector-memory.ts
- Fixed MemorySearchOptions type compatibility

**Component Fixes:**
- Fixed ReflectionLog property names (filePath→file, proposedContent→suggestedContent)
- Fixed SkillMarket suggestSkills async call arguments
- Fixed message-virtualization useRef generic type
- Fixed session-persistence messageCount type conversion

**Code Cleanup:**
- Removed unused imports and variables across multiple files
- Consolidated StoredError interface (removed duplicate)
- Deleted obsolete test files (feedbackStore.test.ts, memory-index.test.ts)

**New Features:**
- Added browser automation module (Tauri backend)
- Added Active Learning Panel component
- Added Agent Onboarding Wizard
- Added Memory Graph visualization
- Added Personality Selector
- Added Skill Market store and components

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
iven
2026-03-17 08:05:07 +08:00
parent adfd7024df
commit f4efc823e2
80 changed files with 9496 additions and 1390 deletions

View File

@@ -0,0 +1,211 @@
/**
* * SkillCard - 技能卡片组件
*
* * 展示单个技能的基本信息,包括名称、描述、能力和安装状态
*/
import { motion } from 'framer-motion';
import {
Package,
Check,
Star,
MoreHorizontal,
Clock,
} from 'lucide-react';
import type { Skill } from '../../types/skill-market';
import { useState } from 'react';
// === 类型定义 ===
interface SkillCardProps {
/** 技能数据 */
skill: Skill;
/** 是否选中 */
isSelected?: boolean;
/** 点击回调 */
onClick?: () => void;
/** 安装/卸载回调 */
onToggleInstall?: () => void;
/** 显示更多操作 */
onShowMore?: () => void;
}
// === 分类配置 ===
const CATEGORY_CONFIG: Record<string, { color: string; bgColor: string }> = {
development: { color: 'text-blue-600 dark:text-blue-400', bgColor: 'bg-blue-100 dark:bg-blue-900/30' },
security: { color: 'text-red-600 dark:text-red-400', bgColor: 'bg-red-100 dark:bg-red-900/30' },
analytics: { color: 'text-purple-600 dark:text-purple-400', bgColor: 'bg-purple-100 dark:bg-purple-900/30' },
content: { color: 'text-pink-600 dark:text-pink-400', bgColor: 'bg-pink-100 dark:bg-pink-900/30' },
ops: { color: 'text-orange-600 dark:text-orange-400', bgColor: 'bg-orange-100 dark:bg-orange-900/30' },
management: { color: 'text-cyan-600 dark:text-cyan-400', bgColor: 'bg-cyan-100 dark:bg-cyan-900/30' },
testing: { color: 'text-emerald-600 dark:text-emerald-400', bgColor: 'bg-emerald-100 dark:bg-emerald-900/30' },
business: { color: 'text-amber-600 dark:text-amber-400', bgColor: 'bg-amber-100 dark:bg-amber-900/30' },
marketing: { color: 'text-rose-600 dark:text-rose-400', bgColor: 'bg-rose-100 dark:bg-rose-900/30' },
};
// === 分类名称映射 ===
const CATEGORY_NAMES: Record<string, string> = {
development: '开发',
security: '安全',
analytics: '分析',
content: '内容',
ops: '运维',
management: '管理',
testing: '测试',
business: '商务',
marketing: '营销',
};
/**
* SkillCard - 技能卡片组件
*/
export function SkillCard({
skill,
isSelected = false,
onClick,
onToggleInstall,
onShowMore,
}: SkillCardProps) {
const [isHovered, setIsHovered] = useState(false);
const categoryConfig = CATEGORY_CONFIG[skill.category] || {
color: 'text-gray-600 dark:text-gray-400',
bgColor: 'bg-gray-100 dark:bg-gray-800/30',
};
return (
<motion.div
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
whileHover={{ scale: 1.02 }}
onHoverStart={() => setIsHovered(true)}
onHoverEnd={() => setIsHovered(false)}
onClick={onClick}
className={`
relative p-4 rounded-lg border cursor-pointer transition-all duration-200
${isSelected
? 'border-blue-500 bg-blue-50 dark:bg-blue-900/20'
: 'border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 hover:border-gray-300 dark:hover:border-gray-600'
}
`}
>
{/* 顶部:图标和名称 */}
<div className="flex items-start justify-between mb-2">
<div className="flex items-center gap-2">
<div
className={`w-10 h-10 rounded-lg flex items-center justify-center ${categoryConfig.bgColor}`}
>
<Package className={`w-5 h-5 ${categoryConfig.color}`} />
</div>
<div>
<h3 className="text-sm font-semibold text-gray-900 dark:text-gray-100">
{skill.name}
</h3>
<p className="text-xs text-gray-500 dark:text-gray-400">
{skill.author || '官方'}
</p>
</div>
</div>
{/* 安装按钮 */}
<motion.button
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.95 }}
onClick={(e) => {
e.stopPropagation();
onToggleInstall?.();
}}
className={`
px-3 py-1.5 rounded-lg text-xs font-medium transition-all duration-200
${skill.installed
? 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-600'
: 'bg-blue-500 text-white hover:bg-blue-600'
}
`}
>
{skill.installed ? (
<span className="flex items-center gap-1">
<Check className="w-3 h-3" />
</span>
) : (
<span className="flex items-center gap-1">
<Package className="w-3 h-3" />
</span>
)}
</motion.button>
</div>
{/* 描述 */}
<p className="text-xs text-gray-600 dark:text-gray-300 mb-3 line-clamp-2">
{skill.description}
</p>
{/* 标签和能力 */}
<div className="flex flex-wrap gap-1 mb-3">
{skill.capabilities.slice(0, 3).map((cap) => (
<span
key={cap}
className="px-2 py-0.5 rounded text-xs bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400"
>
{cap}
</span>
))}
{skill.capabilities.length > 3 && (
<span className="px-2 py-0.5 rounded text-xs bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400">
+{skill.capabilities.length - 3}
</span>
)}
</div>
{/* 底部:分类、评分和统计 */}
<div className="flex items-center justify-between pt-2 border-t border-gray-100 dark:border-gray-700">
<span
className={`px-2 py-0.5 rounded text-xs ${categoryConfig.bgColor} ${categoryConfig.color}`}
>
{CATEGORY_NAMES[skill.category] || skill.category}
</span>
<div className="flex items-center gap-3 text-xs text-gray-500 dark:text-gray-400">
{skill.rating !== undefined && (
<span className="flex items-center gap-1">
<Star className="w-3 h-3 text-yellow-500 fill-current" />
{skill.rating.toFixed(1)}
</span>
)}
{skill.reviewCount !== undefined && skill.reviewCount > 0 && (
<span>{skill.reviewCount} </span>
)}
{skill.installedAt && (
<span className="flex items-center gap-1">
<Clock className="w-3 h-3" />
{new Date(skill.installedAt).toLocaleDateString()}
</span>
)}
</div>
</div>
{/* 悬停时显示更多按钮 */}
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: isHovered ? 1 : 0 }}
className="absolute top-2 right-2"
>
<button
onClick={(e) => {
e.stopPropagation();
onShowMore?.();
}}
className="p-1.5 rounded-lg bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors"
title="更多操作"
>
<MoreHorizontal className="w-4 h-4" />
</button>
</motion.div>
</motion.div>
);
}
export default SkillCard;