From adfd7024df05251754bb26af6e64a6ef543e16a3 Mon Sep 17 00:00:00 2001 From: iven Date: Mon, 16 Mar 2026 13:54:03 +0800 Subject: [PATCH] docs(claude): restructure documentation management and add feedback system MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Restructure §8 from "文档沉淀规则" to "文档管理规则" with 4 subsections - Add docs/ structure with features/ and knowledge-base/ directories - Add feature documentation template with 7 sections (概述/设计初衷/技术设计/预期作用/实际效果/演化路线/头脑风暴) - Add feature update trigger matrix (新增/修改/完成/问题/反馈) - Add documentation quality checklist - Add §16 --- CLAUDE.md | 80 +- desktop/src/App.tsx | 10 + .../components/Feedback/FeedbackButton.tsx | 40 + .../components/Feedback/FeedbackHistory.tsx | 193 +++++ .../src/components/Feedback/FeedbackModal.tsx | 292 ++++++++ .../src/components/Feedback/feedbackStore.ts | 143 ++++ desktop/src/components/Feedback/index.ts | 11 + desktop/src/components/MessageSearch.tsx | 464 ++++++++++++ desktop/src/components/RightPanel.tsx | 50 +- desktop/src/components/Sidebar.tsx | 19 +- desktop/src/components/SwarmDashboard.tsx | 5 +- desktop/src/components/ui/ErrorAlert.tsx | 345 +++++++++ desktop/src/components/ui/ErrorBoundary.tsx | 179 +++++ desktop/src/lib/agent-memory.ts | 197 ++++- desktop/src/lib/error-handling.ts | 373 ++++++++++ desktop/src/lib/error-types.ts | 524 +++++++++++++ desktop/src/lib/memory-index.ts | 443 +++++++++++ desktop/src/lib/session-persistence.ts | 656 +++++++++++++++++ desktop/src/lib/vector-memory.ts | 379 ++++++++++ desktop/src/lib/viking-client.ts | 23 + desktop/src/types/skill-market.ts | 77 ++ docs/WORK_SUMMARY_2026-03-16.md | 63 +- .../00-architecture/01-communication-layer.md | 232 ++++++ .../00-architecture/02-state-management.md | 265 +++++++ .../00-architecture/03-security-auth.md | 220 ++++++ .../01-core-features/00-chat-interface.md | 272 +++++++ .../01-core-features/05-swarm-coordination.md | 265 +++++++ .../02-intelligence-layer/00-agent-memory.md | 269 +++++++ .../03-reflection-engine.md | 301 ++++++++ .../05-autonomy-manager.md | 310 ++++++++ .../00-openviking-integration.md | 290 ++++++++ .../04-skills-ecosystem/00-skill-system.md | 288 ++++++++ .../05-hands-system/00-hands-overview.md | 300 ++++++++ .../00-openfang-integration.md | 273 +++++++ docs/features/README.md | 189 +++++ docs/features/brainstorming-notes.md | 256 +++++++ docs/features/roadmap.md | 294 ++++++++ .../memory-panel-verification.png | Bin 0 -> 388951 bytes plans/squishy-mapping-storm.md | 289 ++++++++ plans/virtual-conjuring-stardust.md | 306 ++++---- .../components/Feedback/feedbackStore.test.ts | 142 ++++ tests/desktop/memory-index.test.ts | 694 ++++++++++++++++++ tests/desktop/session-persistence.test.ts | 424 +++++++++++ tests/desktop/vector-memory.test.ts | 294 ++++++++ 44 files changed, 10491 insertions(+), 248 deletions(-) create mode 100644 desktop/src/components/Feedback/FeedbackButton.tsx create mode 100644 desktop/src/components/Feedback/FeedbackHistory.tsx create mode 100644 desktop/src/components/Feedback/FeedbackModal.tsx create mode 100644 desktop/src/components/Feedback/feedbackStore.ts create mode 100644 desktop/src/components/Feedback/index.ts create mode 100644 desktop/src/components/MessageSearch.tsx create mode 100644 desktop/src/components/ui/ErrorAlert.tsx create mode 100644 desktop/src/components/ui/ErrorBoundary.tsx create mode 100644 desktop/src/lib/error-handling.ts create mode 100644 desktop/src/lib/error-types.ts create mode 100644 desktop/src/lib/memory-index.ts create mode 100644 desktop/src/lib/session-persistence.ts create mode 100644 desktop/src/lib/vector-memory.ts create mode 100644 desktop/src/types/skill-market.ts create mode 100644 docs/features/00-architecture/01-communication-layer.md create mode 100644 docs/features/00-architecture/02-state-management.md create mode 100644 docs/features/00-architecture/03-security-auth.md create mode 100644 docs/features/01-core-features/00-chat-interface.md create mode 100644 docs/features/01-core-features/05-swarm-coordination.md create mode 100644 docs/features/02-intelligence-layer/00-agent-memory.md create mode 100644 docs/features/02-intelligence-layer/03-reflection-engine.md create mode 100644 docs/features/02-intelligence-layer/05-autonomy-manager.md create mode 100644 docs/features/03-context-database/00-openviking-integration.md create mode 100644 docs/features/04-skills-ecosystem/00-skill-system.md create mode 100644 docs/features/05-hands-system/00-hands-overview.md create mode 100644 docs/features/06-tauri-backend/00-openfang-integration.md create mode 100644 docs/features/README.md create mode 100644 docs/features/brainstorming-notes.md create mode 100644 docs/features/roadmap.md create mode 100644 docs/test-screenshots/memory-panel-verification.png create mode 100644 plans/squishy-mapping-storm.md create mode 100644 tests/desktop/components/Feedback/feedbackStore.test.ts create mode 100644 tests/desktop/memory-index.test.ts create mode 100644 tests/desktop/session-persistence.test.ts create mode 100644 tests/desktop/vector-memory.test.ts diff --git a/CLAUDE.md b/CLAUDE.md index 5adb853..b594a11 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -282,9 +282,63 @@ pnpm tsc --noEmit --- -## 8. 文档沉淀规则 +## 8. 文档管理规则 -凡是出现以下情况,应更新 `docs/openfang-knowledge-base.md` 或相关文档: +### 8.1 文档结构 + +```text +docs/ +├── features/ # 功能全景文档 +│ ├── README.md # 功能索引和优先级矩阵 +│ ├── brainstorming-notes.md # 头脑风暴记录 +│ ├── 00-architecture/ # 架构层功能 +│ ├── 01-core-features/ # 核心功能 +│ ├── 02-intelligence-layer/ # 智能层 (L4 自演化) +│ ├── 03-context-database/ # 上下文数据库 +│ ├── 04-skills-ecosystem/ # Skills 生态 +│ ├── 05-hands-system/ # Hands 系统 +│ └── 06-tauri-backend/ # Tauri 后端 +├── knowledge-base/ # 技术知识库 +│ ├── openfang-technical-reference.md +│ ├── openfang-websocket-protocol.md +│ └── troubleshooting.md +└── WORK_SUMMARY_*.md # 工作日志 +``` + +### 8.2 功能文档维护规范 + +**何时更新功能文档**: + +| 触发条件 | 更新内容 | +|---------|---------| +| 新增功能 | 创建新文档,填写设计初衷 | +| 功能修改 | 更新技术设计、预期作用 | +| 功能完成 | 更新实际效果、测试覆盖 | +| 发现问题 | 更新已知问题、风险挑战 | +| 用户反馈 | 更新用户反馈、演化路线 | + +**功能文档模板**: + +```markdown +# [功能名称] + +> **分类**: [架构层/核心功能/智能层/上下文数据库/Skills/Hands/Tauri] +> **优先级**: [P0-决定性 / P1-重要 / P2-增强] +> **成熟度**: [L0-概念 / L1-原型 / L2-可用 / L3-成熟 / L4-生产] +> **最后更新**: YYYY-MM-DD + +## 一、功能概述 +## 二、设计初衷(问题背景、设计目标、竞品参考、设计约束) +## 三、技术设计(核心接口、数据流、状态管理) +## 四、预期作用(用户价值、系统价值、成功指标) +## 五、实际效果(已实现、测试覆盖、已知问题、用户反馈) +## 六、演化路线(短期/中期/长期) +## 七、头脑风暴笔记(待讨论问题、创意想法、风险挑战) +``` + +### 8.3 知识库更新规则 + +凡是出现以下情况,应更新 `docs/knowledge-base/` 或相关文档: - 新的协议坑 (REST/WebSocket) - 新的握手/配置/模型排障结论 @@ -294,6 +348,16 @@ pnpm tsc --noEmit 原则:**修完就记,避免二次踩坑。** +### 8.4 文档质量检查清单 + +每次更新文档后,检查: + +- [ ] 文件路径引用正确 +- [ ] 技术术语统一 +- [ ] ICE 评分已更新 +- [ ] 成熟度等级已更新 +- [ ] 已知问题列表已更新 + --- ## 9. 常见高风险点 @@ -407,3 +471,15 @@ docs(knowledge-base): capture OpenFang RBAC permission issues - [ ] 插件从 TypeScript 改为 SKILL.md - [ ] 添加 Hands/Workflow 相关 UI - [ ] 处理 16 层安全防护的交互 + +--- + +## 16. 参考文档更新 + +- `docs/features/README.md` - 功能索引和优先级矩阵 +- `docs/features/brainstorming-notes.md` - 头脑风暴记录 +- `docs/knowledge-base/openfang-technical-reference.md` - OpenFang 技术参考 +- `docs/knowledge-base/openfang-websocket-protocol.md` - WebSocket 协议 +- `docs/knowledge-base/troubleshooting.md` - 排障指南 +- `skills/` - SKILL.md 技能定义 +- `hands/` - HAND.toml 自主能力包 diff --git a/desktop/src/App.tsx b/desktop/src/App.tsx index 193faf1..8a5c6dc 100644 --- a/desktop/src/App.tsx +++ b/desktop/src/App.tsx @@ -8,6 +8,7 @@ import { SettingsLayout } from './components/Settings/SettingsLayout'; 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 { useTeamStore } from './store/teamStore'; import { getStoredGatewayToken } from './lib/gateway-client'; @@ -110,6 +111,15 @@ function App() { description="Choose a team from the list on the left, or click + to create a new multi-Agent collaboration team." /> ) + ) : mainContentView === 'swarm' ? ( + + + ) : ( )} diff --git a/desktop/src/components/Feedback/FeedbackButton.tsx b/desktop/src/components/Feedback/FeedbackButton.tsx new file mode 100644 index 0000000..687868e --- /dev/null +++ b/desktop/src/components/Feedback/FeedbackButton.tsx @@ -0,0 +1,40 @@ +import { MessageCircle } from 'lucide-react'; +import { motion } from 'framer-motion'; +import { useFeedbackStore } from './feedbackStore'; +import { Button } from '../ui'; + +interface FeedbackButtonProps { + onClick: () => void; + showCount?: boolean; +} + +export function FeedbackButton({ onClick, showCount = true }: FeedbackButtonProps) { + const feedbackItems = useFeedbackStore((state) => state.feedbackItems); + const pendingCount = feedbackItems.filter((f) => f.status === 'pending' || f.status === 'submitted').length; + + return ( + + + + ); +} diff --git a/desktop/src/components/Feedback/FeedbackHistory.tsx b/desktop/src/components/Feedback/FeedbackHistory.tsx new file mode 100644 index 0000000..e1a03fd --- /dev/null +++ b/desktop/src/components/Feedback/FeedbackHistory.tsx @@ -0,0 +1,193 @@ +import { format } from 'date-fns'; +import { motion, AnimatePresence } from 'framer-motion'; +import { Clock, CheckCircle, AlertCircle, Hourglass, Trash2, ChevronDown, ChevronUp } from 'lucide-react'; +import { useFeedbackStore, type FeedbackSubmission, type FeedbackStatus } from './feedbackStore'; +import { Button, Badge } from '../ui'; + +const statusConfig: Record = { + pending: { label: 'Pending', color: 'text-gray-500', icon: }, + submitted: { label: 'Submitted', color: 'text-blue-500', icon: }, + acknowledged: { label: 'Acknowledged', color: 'text-purple-500', icon: }, + in_progress: { label: 'In Progress', color: 'text-yellow-500', icon: }, + resolved: { label: 'Resolved', color: 'text-green-500', icon: }, +}; + +const typeLabels: Record = { + bug: 'Bug Report', + feature: 'Feature Request'; + general: 'General Feedback', +}; +const priorityLabels: Record = { + low: 'Low', + medium: 'Medium', + high: 'High', +}; + +interface FeedbackHistoryProps { + onViewDetails?: (feedback: FeedbackSubmission) => void; +} + +export function FeedbackHistory({ onViewDetails }: FeedbackHistoryProps) { + const { feedbackItems, deleteFeedback, updateFeedbackStatus } = useFeedbackStore(); + const [expandedId, setExpandedId] = useState(null); + + const formatDate = (timestamp: number) => { + return format(new Date(timestamp), 'yyyy-MM-dd HH:mm'); + }; + + const handleDelete = (id: string) => { + if (confirm('Are you sure you want to delete this feedback?')) { + deleteFeedback(id); + } + }; + + const handleStatusChange = (id: string, newStatus: FeedbackStatus) => { + updateFeedbackStatus(id, newStatus); + }; + + if (feedbackItems.length === 0) { + return ( +
+

No feedback submissions yet.

+

Click the feedback button to submit your first feedback.

+
+ ); + } + + return ( +
+ {feedbackItems.map((feedback) => { + const isExpanded = expandedId === feedback.id; + const statusInfo = statusConfig[feedback.status]; + + return ( + + {/* Header */} +
setExpandedId(isExpanded ? null : feedback.id)} + > +
+
+ {feedback.type === 'bug' && } + {feedback.type === 'feature' && } + {feedback.type === 'general' && } +
+
+

+ {feedback.title} +

+

+ {typeLabels[feedback.type]} - {formatDate(feedback.createdAt)} +

+
+ + {priorityLabels[feedback.priority]} + +
+
+ +
+
+ + {/* Expandable Content */} + + {isExpanded && ( + +
+ {/* Description */} +
+
Description
+

+ {feedback.description} +

+
+ + {/* Attachments */} + {feedback.attachments.length > 0 && ( +
+
+ Attachments ({feedback.attachments.length}) +
+
+ {feedback.attachments.map((att, idx) => ( + + {att.name} + + ))} +
+
+ )} + + {/* Metadata */} +
+
System Info
+
+

App Version: {feedback.metadata.appVersion}

+

OS: {feedback.metadata.os}

+

Submitted: {format(feedback.createdAt)}

+
+
+ + {/* Status and Actions */} +
+
+ + {statusInfo.icon} + {statusInfo.label} + +
+
+ + +
+
+
+
+ )} +
+
+ ); + })} +
+ ); +} diff --git a/desktop/src/components/Feedback/FeedbackModal.tsx b/desktop/src/components/Feedback/FeedbackModal.tsx new file mode 100644 index 0000000..7f68838 --- /dev/null +++ b/desktop/src/components/Feedback/FeedbackModal.tsx @@ -0,0 +1,292 @@ +import { useState, useRef } from 'react'; +import { motion, AnimatePresence } from 'framer-motion'; +import { X, Send, Bug, Lightbulb, MessageSquare, AlertCircle, Upload, Trash2 } from 'lucide-react'; +import { useFeedbackStore, type FeedbackType, type FeedbackPriority } from './feedbackStore'; +import { Button } from '../ui'; +import { useToast } from '../ui/Toast'; + +interface FeedbackModalProps { + onClose: () => void; +} + +const typeOptions: { value: FeedbackType; label: string; icon: React.ReactNode }[] = [ + { value: 'bug', label: 'Bug Report', icon: }, + { value: 'feature', label: 'Feature Request', icon: }, + { value: 'general', label: 'General Feedback', icon: }, +]; + +const priorityOptions: { value: FeedbackPriority; label: string; color: string }[] = [ + { value: 'low', label: 'Low', color: 'text-gray-500' }, + { value: 'medium', label: 'Medium', color: 'text-yellow-600' }, + { value: 'high', label: 'High', color: 'text-red-500' }, +]; + +export function FeedbackModal({ onClose }: FeedbackModalProps) { + const { submitFeedback, isLoading, error } = useFeedbackStore(); + const { toast } = useToast(); + const fileInputRef = useRef(null); + + const [type, setType] = useState('bug'); + const [title, setTitle] = useState(''); + const [description, setDescription] = useState(''); + const [priority, setPriority] = useState('medium'); + const [attachments, setAttachments] = useState([]); + + const handleSubmit = async () => { + if (!title.trim() || !description.trim()) { + toast('Please fill in title and description', 'warning'); + return; + } + + // Convert files to base64 for storage + const processedAttachments = await Promise.all( + attachments.map(async (file) => { + return new Promise((resolve) => { + const reader = new FileReader(); + reader.onload = () => { + resolve({ + name: file.name, + type: file.type, + size: file.size, + data: reader.result as string, + }); + }; + reader.readAsDataURL(file); + }); + }) + ); + + try { + const result = await submitFeedback({ + type, + title: title.trim(), + description: description.trim(), + priority, + attachments: processedAttachments, + metadata: { + appVersion: '0.0.0', + os: navigator.platform, + timestamp: Date.now(), + }, + }); + + if (result) { + toast('Feedback submitted successfully!', 'success'); + // Reset form + setTitle(''); + setDescription(''); + setAttachments([]); + setType('bug'); + setPriority('medium'); + onClose(); + } + } catch (err) { + toast('Failed to submit feedback. Please try again.', 'error'); + } + }; + + const handleFileSelect = (e: React.ChangeEvent) => { + const files = Array.from(e.target.files || []); + // Limit to 5 attachments + const newFiles = [...attachments, ...files].slice(0, 5); + setAttachments(newFiles); + }; + + const removeAttachment = (index: number) => { + setAttachments(attachments.filter((_, i) => i !== index)); + }; + + const formatFileSize = (bytes: number): string => { + if (bytes < 1024) return `${bytes} B`; + if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`; + return `${(bytes / (1024 * 1024)).toFixed(1)} MB`; + }; + + return ( + + { + if (e.target === e.currentTarget) onClose(); + }} + > + + {/* Header */} +
+

+ Submit Feedback +

+ +
+ + {/* Content */} +
+ {/* Type Selection */} +
+ +
+ {typeOptions.map((opt) => ( + + ))} +
+
+ + {/* Title */} +
+ + setTitle(e.target.value)} + placeholder="Brief summary of your feedback" + className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-orange-400 dark:bg-gray-700 dark:text-gray-100" + maxLength={100} + /> +
+ + {/* Description */} +
+ +