Files
zclaw_openfang/desktop/src/store/skillMarketStore.ts
iven f4efc823e2 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>
2026-03-17 08:05:07 +08:00

412 lines
14 KiB
TypeScript

/**
* * skillMarketStore.ts - 技能市场状态管理
*
* * 猛攻状态管理技能浏览、搜索、安装/卸载等功能
*/
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import type { Skill, SkillReview, SkillMarketState } from '../types/skill-market';
// === 存储键 ===
const STORAGE_KEY = 'zclaw-skill-market';
const INSTALLED_KEY = 'zclaw-installed-skills';
// === 默认状态 ===
const initialState: SkillMarketState = {
skills: [],
installedSkills: [],
searchResults: [],
selectedSkill: null,
searchQuery: '',
categoryFilter: 'all',
isLoading: false,
error: null,
};
// === Store 定义 ===
interface SkillMarketActions {
// 技能加载
loadSkills: () => Promise<void>;
// 技能搜索
searchSkills: (query: string) => void;
// 分类过滤
filterByCategory: (category: string) => void;
// 选择技能
selectSkill: (skill: Skill | null) => void;
// 安装技能
installSkill: (skillId: string) => Promise<boolean>;
// 卸载技能
uninstallSkill: (skillId: string) => Promise<boolean>;
// 获取技能详情
getSkillDetails: (skillId: string) => Promise<Skill | null>;
// 加载评论
loadReviews: (skillId: string) => Promise<SkillReview[]>;
// 添加评论
addReview: (skillId: string, review: Omit<SkillReview, 'id' | 'skillId' | 'createdAt'>) => Promise<void>;
// 刷新技能列表
refreshSkills: () => Promise<void>;
// 清除错误
clearError: () => void;
// 重置状态
reset: () => void;
}
// === Store 创建 ===
export const useSkillMarketStore = create<SkillMarketState & SkillMarketActions>()(
persist({
key: STORAGE_KEY,
storage: localStorage,
partialize: (state) => ({
installedSkills: state.installedSkills,
categoryFilter: state.categoryFilter,
}),
}),
initialState,
{
// === 技能加载 ===
loadSkills: async () => {
set({ isLoading: true, error: null });
try {
// 扫描 skills 目录获取可用技能
const skills = await scanSkillsDirectory();
// 从 localStorage 恢复安装状态
const stored = localStorage.getItem(INSTALLED_KEY);
const installedSkills: string[] = stored ? JSON.parse(stored) : [];
// 更新技能的安装状态
const updatedSkills = skills.map(skill => ({
...skill,
installed: installedSkills.includes(skill.id),
})));
set({
skills: updatedSkills,
installedSkills,
isLoading: false,
});
} catch (err) {
set({
isLoading: false,
error: err instanceof Error ? err.message : '加载技能失败',
});
}
},
// === 技能搜索 ===
searchSkills: (query: string) => {
const { skills } = get();
set({ searchQuery: query });
if (!query.trim()) {
set({ searchResults: [] });
return;
}
const queryLower = query.toLowerCase();
const results = skills.filter(skill => {
return (
skill.name.toLowerCase().includes(queryLower) ||
skill.description.toLowerCase().includes(queryLower) ||
skill.triggers.some(t => t.toLowerCase().includes(queryLower)) ||
skill.capabilities.some(c => c.toLowerCase().includes(queryLower)) ||
skill.tags?.some(t => t.toLowerCase().includes(queryLower))
);
});
set({ searchResults: results });
},
// === 分类过滤 ===
filterByCategory: (category: string) => {
set({ categoryFilter: category });
},
// === 选择技能 ===
selectSkill: (skill: Skill | null) => {
set({ selectedSkill: skill });
},
// === 安装技能 ===
installSkill: async (skillId: string) => {
const { skills, installedSkills } = get();
const skill = skills.find(s => s.id === skillId);
if (!skill) return false;
try {
// 更新安装状态
const newInstalledSkills = [...installedSkills, skillId];
const updatedSkills = skills.map(s => ({
...s,
installed: s.id === skillId ? true : s.installed,
installedAt: s.id === skillId ? new Date().toISOString() : s.installedAt,
}));
// 持久化安装列表
localStorage.setItem(INSTALLED_KEY, JSON.stringify(newInstalledSkills));
set({
skills: updatedSkills,
installedSkills: newInstalledSkills,
});
return true;
} catch (err) {
set({
error: err instanceof Error ? err.message : '安装技能失败',
});
return false;
}
},
// === 卸载技能 ===
uninstallSkill: async (skillId: string) => {
const { skills, installedSkills } = get();
try {
// 更新安装状态
const newInstalledSkills = installedSkills.filter(id => id !== skillId);
const updatedSkills = skills.map(s => ({
...s,
installed: s.id === skillId ? false : s.installed,
installedAt: s.id === skillId ? undefined : s.installedAt,
}));
// 持久化安装列表
localStorage.setItem(INSTALLED_KEY, JSON.stringify(newInstalledSkills));
set({
skills: updatedSkills,
installedSkills: newInstalledSkills,
});
return true;
} catch (err) {
set({
error: err instanceof Error ? err.message : '卸载技能失败',
});
return false;
}
},
// === 获取技能详情 ===
getSkillDetails: async (skillId: string) => {
const { skills } = get();
return skills.find(s => s.id === skillId) || null;
},
// === 加载评论 ===
loadReviews: async (skillId: string) => {
// MVP: 从 localStorage 模拟加载评论
const reviewsKey = `zclaw-skill-reviews-${skillId}`;
const stored = localStorage.getItem(reviewsKey);
const reviews: SkillReview[] = stored ? JSON.parse(stored) : [];
return reviews;
},
// === 添加评论 ===
addReview: async (skillId: string, review: Omit<SkillReview, 'id' | 'skillId' | 'createdAt'>) => {
const reviews = await get().loadReviews(skillId);
const newReview: SkillReview = {
...review,
id: `review-${Date.now()}`,
skillId,
createdAt: new Date().toISOString(),
};
const updatedReviews = [...reviews, newReview];
// 更新技能的评分和评论数
const { skills } = get();
const updatedSkills = skills.map(s => {
if (s.id === skillId) {
const totalRating = updatedReviews.reduce((sum, r) => sum + r.rating, 0);
const avgRating = totalRating / updatedReviews.length;
return {
...s,
rating: Math.round(avgRating * 10) / 10,
reviewCount: updatedReviews.length,
};
}
return s;
});
// 持久化评论
const reviewsKey = `zclaw-skill-reviews-${skillId}`;
localStorage.setItem(reviewsKey, JSON.stringify(updatedReviews));
set({ skills: updatedSkills });
},
// === 刷新技能列表 ===
refreshSkills: async () => {
// 清除缓存并重新加载
localStorage.removeItem(STORAGE_KEY);
await get().loadSkills();
},
// === 清除错误 ===
clearError: () => {
set({ error: null });
},
// === 重置状态 ===
reset: () => {
localStorage.removeItem(STORAGE_KEY);
localStorage.removeItem(INSTALLED_KEY);
set(initialState);
},
}
);
// === 辅助函数 ===
/**
* 扫描 skills 目录获取可用技能
*/
async function scanSkillsDirectory(): Promise<Skill[]> {
// 这里我们模拟扫描,实际实现需要通过 Tauri API 访问文件系统
// 或者从预定义的技能列表中加载
const skills: Skill[] = [
// 开发类
{
id: 'code-review',
name: '代码审查',
description: '审查代码、分析代码质量、提供改进建议',
triggers: ['审查代码', '代码审查', 'code review', 'PR Review', '检查代码', '分析代码'],
capabilities: ['代码质量分析', '架构评估', '最佳实践检查', '安全审计'],
toolDeps: ['read', 'grep', 'glob'],
category: 'development',
installed: false,
tags: ['代码', '审查', '质量'],
},
{
id: 'translation',
name: '翻译助手',
description: '翻译文本、多语言转换、保持语言风格一致性',
triggers: ['翻译', 'translate', '中译英', '英译中', '翻译成', '转换成'],
capabilities: ['多语言翻译', '技术文档翻译', '代码注释翻译', 'UI 文本翻译', '风格保持'],
toolDeps: ['read', 'write'],
category: 'content',
installed: false,
tags: ['翻译', '语言', '国际化'],
},
{
id: 'chinese-writing',
name: '中文写作',
description: '中文写作助手 - 帮助撰写各类中文文档、文章、报告',
triggers: ['写一篇', '帮我写', '撰写', '起草', '润色', '中文写作'],
capabilities: ['撰写文档', '润色修改', '调整语气', '中英文翻译'],
toolDeps: ['read', 'write'],
category: 'content',
installed: false,
tags: ['写作', '文档', '中文'],
},
{
id: 'web-search',
name: '网络搜索',
description: '搜索互联网信息、整合多方来源',
triggers: ['搜索', 'search', '查找信息', '查询', '搜索网络'],
capabilities: ['搜索引擎集成', '信息提取', '来源验证', '结果整合'],
toolDeps: ['web_search'],
category: 'research',
installed: false,
tags: ['搜索', '互联网', '信息'],
},
{
id: 'data-analysis',
name: '数据分析',
description: '数据清洗、统计分析、可视化图表',
triggers: ['数据分析', '统计', '可视化', '图表', 'analytics'],
capabilities: ['数据清洗', '统计分析', '可视化图表', '报告生成'],
toolDeps: ['read', 'write', 'shell'],
category: 'analytics',
installed: false,
tags: ['数据', '分析', '可视化'],
},
{
id: 'git',
name: 'Git 操作',
description: 'Git 版本控制操作、分支管理、冲突解决',
triggers: ['git', '版本控制', '分支', '合并', 'commit', 'merge'],
capabilities: ['分支管理', '冲突解决', 'rebase', 'cherry-pick'],
toolDeps: ['shell'],
category: 'development',
installed: false,
tags: ['git', '版本控制', '分支'],
},
{
id: 'shell-command',
name: 'Shell 命令',
description: '执行 Shell 命令、系统操作',
triggers: ['shell', '命令行', '终端', 'terminal', 'bash'],
capabilities: ['命令执行', '管道操作', '脚本运行', '环境管理'],
toolDeps: ['shell'],
category: 'ops',
installed: false,
tags: ['shell', '命令', '系统'],
},
{
id: 'file-operations',
name: '文件操作',
description: '文件读写、目录管理、文件搜索',
triggers: ['文件', 'file', '读取', '写入', '目录', '文件夹'],
capabilities: ['文件读写', '目录管理', '文件搜索', '批量操作'],
toolDeps: ['read', 'write', 'glob'],
category: 'ops',
installed: false,
tags: ['文件', '目录', '读写'],
},
{
id: 'security-engineer',
name: '安全工程师',
description: '安全工程师 - 负责安全审计、漏洞检测、合规检查',
triggers: ['安全审计', '漏洞检测', '安全检查', 'security', '渗透测试'],
capabilities: ['漏洞扫描', '合规检查', '安全加固', '威胁建模'],
toolDeps: ['read', 'grep', 'shell'],
category: 'security',
installed: false,
tags: ['安全', '审计', '漏洞'],
},
{
id: 'ai-engineer',
name: 'AI 工程师',
description: 'AI/ML 工程师 - 专注机器学习模型开发、LLM 集成和生产系统部署',
triggers: ['AI工程师', '机器学习', 'ML模型', 'LLM集成', '深度学习', '模型训练'],
capabilities: ['ML 框架', 'LLM 集成', 'RAG 系统', '向量数据库'],
toolDeps: ['bash', 'read', 'write', 'grep', 'glob'],
category: 'development',
installed: false,
tags: ['AI', 'ML', 'LLM'],
},
{
id: 'senior-developer',
name: '高级开发',
description: '高级开发工程师 - 端到端功能实现、复杂问题解决',
triggers: ['高级开发', 'senior developer', '端到端', '复杂功能', '架构实现'],
capabilities: ['端到端实现', '架构设计', '性能优化', '代码重构'],
toolDeps: ['bash', 'read', 'write', 'grep', 'glob'],
category: 'development',
installed: false,
tags: ['开发', '架构', '实现'],
},
{
id: 'frontend-developer',
name: '前端开发',
description: '前端开发专家 - 擅长 React/Vue/CSS/TypeScript',
triggers: ['前端开发', '页面开发', 'UI开发', 'React', 'Vue', 'CSS'],
capabilities: ['组件开发', '样式调整', '性能优化', '响应式设计'],
toolDeps: ['read', 'write', 'shell'],
category: 'development',
installed: false,
types: ['前端', 'UI', '组件'],
},
{
id: 'backend-architect',
name: '后端架构',
description: '后端架构设计、API设计、数据库建模',
triggers: ['后端架构', 'API设计', '数据库设计', '系统架构', '微服务'],
capabilities: ['架构设计', 'API规范', '数据库建模', '性能优化'],
toolDeps: ['read', 'write', 'shell'],
category: 'development',
installed: false,
tags: ['后端', '架构', 'API'],
},
{
id: 'devops-automator',
name: 'DevOps 自动化',
description: 'CI/CD、Docker、K8s、自动化部署',
triggers: ['DevOps', 'CI/CD', 'Docker', '部署', '自动化', 'K8s'],
capabilities: ['CI/CD配置', '容器化', '自动化部署', '监控告警'],
toolDeps: ['shell', 'read', 'write'],
category: 'ops',
installed: false,
tags: ['DevOps', 'Docker', 'CI/CD'],
},
{
id: 'senior-pm',
name: '高级PM',
description: '项目管理、需求分析、迭代规划',
triggers: ['项目管理', '需求分析', '迭代规划', '产品设计', 'PRD'],
capabilities: ['需求拆解', '迭代排期', '风险评估', '文档撰写'],
toolDeps: ['read', 'write'],
category: 'management',
installed: false,
tags: ['PM', '需求', '迭代'],
},
];
return skills;
}