diff --git a/docs/desktop/01-quick-start.md b/docs/desktop/01-quick-start.md new file mode 100644 index 00000000..597c472a --- /dev/null +++ b/docs/desktop/01-quick-start.md @@ -0,0 +1,383 @@ +# Claude Code 桌面端 — 快速上手 + +> 告别纯黑终端,用图形界面释放 Claude Code 的全部潜能。 + +

+界面布局 · 对话操作 · 多标签系统 · 权限控制 · 项目管理 · 模型与提供商 · IM 适配器 · 定时任务 +

+ +![桌面端界面总览](./images/01-desktop-overview.png) + +--- + +## 一、界面布局 + +桌面端采用**三栏 + 标签页**的经典 IDE 布局,从左到右分为: + +| 区域 | 位置 | 功能 | +|------|------|------| +| **侧边栏** | 左侧 | 会话列表、项目筛选、搜索、导航入口 | +| **标签栏** | 顶部 | 多标签切换、拖拽排序、右键菜单 | +| **内容区** | 中央 | 对话界面 / 设置页 / 任务页 | +| **状态栏** | 底部 | 当前项目名、模型名称 | + +### 侧边栏 + +侧边栏是你与 Claude Code 交互的导航中心: + +- **品牌区域**:显示「Claude Code Haha」标识,点击 GitHub 图标跳转仓库 +- **操作按钮**: + - `+` 新建会话 + - 时钟图标 → 定时任务管理 + - 齿轮图标 → 设置页面 +- **项目筛选器**:按工作目录过滤会话列表 +- **搜索框**:实时搜索会话标题(不区分大小写) +- **会话列表**:按时间自动分组 —— 今天 / 昨天 / 最近 7 天 / 最近 30 天 / 更早 + +**右键菜单**:在会话项上右键可以 **重命名** 或 **删除** 会话。 + +### 状态栏 + +底部状态栏显示当前会话的项目路径和正在使用的 AI 模型名称,一目了然。 + +--- + +## 二、对话操作 + +### 新建会话 + +1. 点击侧边栏 `+` 按钮,或使用快捷键 `Cmd/Ctrl + N` +2. 在空白会话页选择**工作目录**(关联本地项目文件夹) +3. 输入第一条消息开始对话 + +### 发送消息 + +在底部输入框编写消息: + +- **Enter** → 发送消息 +- **Shift + Enter** → 换行(多行输入) +- 输入框会自动调整高度(最高 200px) + +### 附件上传 + +桌面端支持多种附件方式: + +| 方式 | 操作 | +|------|------| +| **粘贴图片** | 在输入框中 `Cmd/Ctrl + V` 粘贴剪贴板图片 | +| **拖拽上传** | 将文件拖入输入区域 | +| **文件选择** | 点击 `+` 按钮 → 「添加文件」 | + +附件会在输入框上方以缩略图画廊展示,支持预览和移除。 + +### 斜杠命令 + +输入 `/` 触发命令自动补全菜单: + +``` +/commit — 提交代码 +/review-pr — 审查 PR +/memory — 管理记忆 +/debug — 调试模式 +... +``` + +- **上下箭头** 导航选项 +- **Enter / Tab** 确认选择 +- **Esc** 关闭菜单 +- 命令列表由服务端动态提供,支持搜索过滤 + +### @ 文件引用 + +输入 `@` 触发文件搜索菜单,快速将文件引入对话上下文: + +- 支持路径和文件名自动补全 +- 上下箭头导航、Enter 选择 + +### 消息类型 + +对话中会展示多种消息类型: + +| 类型 | 说明 | 展示形式 | +|------|------|----------| +| **用户消息** | 你发送的文本和附件 | 用户头像 + 消息气泡 | +| **助手消息** | AI 回复内容 | 带边框气泡 + Markdown 渲染 | +| **思考块** | AI 的推理过程(Extended Thinking) | 可展开/折叠,显示思考预览 | +| **工具调用** | Bash、Edit、Read 等工具操作 | 工具图标 + 可展开详情 | +| **工具结果** | 工具执行的输出 | 代码块展示,带成功/错误状态 | +| **权限请求** | 需要用户审批的操作 | 交互式对话框,含允许/拒绝按钮 | +| **AskUser** | AI 向你提问 | 特殊输入框 | + +### 流式输出 + +AI 回复时实时流式展示,支持: + +- 打字效果的闪烁光标 `▍` +- 流式代码高亮(使用 Shiki 引擎,VS Code 级别语法着色) +- 随时可点击 **停止** 按钮(或 `Cmd/Ctrl + .`)中断生成 + +### 消息操作 + +悬浮在消息上时,右下角出现操作栏: + +- **复制** — 复制消息文本内容 + +--- + +## 三、多标签系统 + +桌面端支持同时打开多个对话标签,像浏览器一样管理会话。 + +### 标签操作 + +| 操作 | 方式 | +|------|------| +| **新建标签** | `Cmd/Ctrl + N` 或点击 `+` | +| **切换标签** | 点击目标标签 | +| **关闭标签** | 悬浮标签 → 点击 `×` | +| **拖拽排序** | 按住标签拖动到目标位置 | +| **左右滚动** | 标签过多时出现滚动箭头 | + +### 标签状态指示 + +- **绿色脉冲点** → 会话正在运行 +- **红色点** → 会话出错 +- **无标记** → 会话空闲 + +### 右键菜单 + +右键标签打开上下文菜单: + +- 关闭当前标签 +- 关闭其他标签 +- 关闭左侧标签 +- 关闭右侧标签 +- 关闭全部标签 + +### 关闭保护 + +当关闭一个**正在运行的会话标签**时,会弹出确认对话框: + +- **继续运行** — 保留标签 +- **停止并关闭** — 终止会话后关闭 +- **取消** — 放弃操作 + +标签状态自动保存到 `localStorage`,下次启动时恢复。 + +--- + +## 四、权限控制 + +Claude Code 在执行文件修改、Shell 命令等操作前,会请求你的权限。 + +### 权限请求对话框 + +当 AI 需要执行敏感操作时,会弹出权限请求卡片,显示: + +- 工具类型(如 Bash、Edit、Write) +- 操作预览(命令内容、Diff 变更等) +- 详细输入参数(可展开查看) + +你可以选择: + +| 按钮 | 效果 | +|------|------| +| **允许** | 仅本次允许执行 | +| **一直允许** | 本次会话内自动允许同类操作 | +| **拒绝** | 拒绝本次执行 | + +### 四种权限模式 + +在设置中可切换全局权限模式: + +| 模式 | 说明 | 适用场景 | +|------|------|----------| +| **询问权限** (default) | 每个操作都需确认 | 安全第一 | +| **自动接受** (acceptEdits) | 自动允许编辑操作 | 信任文件修改 | +| **计划模式** (plan) | 只展示计划不执行 | 审查方案 | +| **绕过权限** (bypassPermissions) | 全部自动执行 | 完全信任(需二次确认) | + +> 切换到「绕过权限」时需要确认警告对话框,防止误操作。 + +--- + +## 五、项目管理 + +每个会话都绑定一个**工作目录**,即你的本地项目文件夹。 + +### 工作目录 + +- 新建会话时通过 **DirectoryPicker** 选择工作目录 +- 系统自动检测目录是否存在,不存在时显示警告 +- 支持 Git 仓库识别,状态栏和会话信息中展示: + - 仓库名称 + - 当前分支 + - 项目路径 + +### 项目筛选 + +侧边栏中的 **ProjectFilter** 组件可按项目过滤会话: + +1. 点击项目筛选下拉框 +2. 选择目标项目 +3. 会话列表仅显示该项目的会话 + +### 最近项目 + +通过 API 获取最近使用的项目列表,包含: + +- 项目路径和名称 +- 是否为 Git 仓库 +- 分支名 +- 会话数量 +- 最后修改时间 + +--- + +## 六、模型与提供商 + +### 模型选择 + +点击状态栏的模型名称,或在设置中打开模型选择器: + +- 显示所有可用模型(带图标区分 Opus/Sonnet/Haiku) +- 单选切换当前模型 +- 支持 **Effort 级别** 调节:Low / Medium / High / Max + +### 自定义 Provider + +在设置 → **Providers** 标签页管理 AI 提供商: + +#### 预设提供商 + +系统内置多种预设,快速配置: + +- **Anthropic** — 官方 API +- **OpenAI** — GPT 系列 +- **OpenRouter** — 多模型聚合 +- **Ollama** — 本地模型 +- 其他 Anthropic 兼容服务 + +#### 配置项 + +| 字段 | 说明 | +|------|------| +| API Key | 提供商密钥 | +| Base URL | API 基础地址 | +| API 格式 | anthropic / openai_chat / openai_responses | +| 模型映射 | main / haiku / sonnet / opus 对应的实际模型名 | + +#### 连接测试 + +配置完成后可点击 **测试连接**,系统会发送测试请求验证配置是否正确(两步验证:连接性 + 模型可用性)。 + +--- + +## 七、IM 适配器接入 + +桌面端不仅提供本地 GUI,还支持通过 **Telegram 和飞书** 远程对话。 + +### 配置步骤 + +1. 打开设置 → **Adapters** 标签页 +2. 填入平台凭证: + - **Telegram**:Bot Token + - **飞书**:App ID + App Secret +3. 配置默认工作目录和允许的用户 +4. 启动适配器进程 + +### 用户配对 + +为了安全,IM 用户需要通过**配对码**授权: + +1. 在桌面端设置中点击「生成配对码」 +2. 获取一个 **6 位安全字符码**(60 分钟有效、一次性使用) +3. 在 Telegram/飞书中向 Bot 发送该配对码 +4. 配对成功后即可开始对话 + +安全特性: +- 排除易混淆字符(0/O/1/I/L) +- 同一用户 5 分钟内最多失败 5 次 +- 密钥在 API 返回时自动脱敏(仅显示后 4 位) + +### IM 内操作 + +配对成功后,可在 IM 中: + +| 命令 | 效果 | +|------|------| +| 直接发文本 | 与 Claude Code 对话 | +| `/new [项目名]` 或 `新会话` | 开始新会话(支持模糊匹配项目) | +| `/projects` 或 `项目列表` | 查看最近项目 | +| `/stop` 或 `停止` | 停止当前生成 | + +权限请求在 IM 中以**按钮卡片**形式展示(Telegram Inline Keyboard / 飞书 Interactive Card),点击即可审批。 + +--- + +## 八、定时任务 + +桌面端支持创建 **Cron 定时任务**,让 Claude Code 按计划自动执行。 + +### 进入任务管理 + +点击侧边栏的**时钟图标**进入定时任务页面。 + +页面顶部显示统计卡片:总任务数 / 活跃数 / 禁用数。 + +### 创建任务 + +点击「新建任务」,填写: + +| 字段 | 说明 | +|------|------| +| 任务名称 | 描述性名称 | +| 提示词 | Claude Code 执行的 Prompt | +| Cron 表达式 | 执行时间计划 | +| 周日期 | 可视化选择执行的星期几 | +| 模型 | 使用的 AI 模型 | +| 权限模式 | 任务执行时的权限策略 | + +### 任务管理 + +每个任务行显示: +- 名称和描述 +- Cron 表达式(人性化展示) +- 启用/禁用开关 +- 运行历史(可展开查看) +- 手动运行按钮 +- 删除按钮 + +> 注意:定时任务在桌面应用运行时才会执行。 + +--- + +## 九、键盘快捷键速查 + +| 快捷键 | 功能 | +|--------|------| +| `Cmd/Ctrl + N` | 新建会话 | +| `Cmd/Ctrl + K` | 聚焦侧边栏搜索 | +| `Cmd/Ctrl + .` | 停止当前生成 | +| `Escape` | 关闭模态框 | +| `Enter` | 发送消息 | +| `Shift + Enter` | 输入框换行 | +| `/` | 触发斜杠命令菜单 | +| `@` | 触发文件搜索菜单 | + +--- + +## 十、主题与国际化 + +### 主题切换 + +在设置中切换 **浅色 / 深色** 主题。 + +桌面端采用暖色调设计系统: +- 浅色模式:奶油色背景(#FAF9F5) +- 深色模式:深色背景 +- 品牌色:褐红色(#8F482F) + +### 国际化 + +支持 **中文** 和 **英文** 两种语言,在设置 → 通用 中切换。 diff --git a/docs/desktop/02-architecture.md b/docs/desktop/02-architecture.md new file mode 100644 index 00000000..84a03a5c --- /dev/null +++ b/docs/desktop/02-architecture.md @@ -0,0 +1,835 @@ +# Claude Code 桌面端 — 架构设计 + +> 从 Tauri 窗口到 CLI 子进程,深入理解桌面端的三层通信架构。 + +

+技术栈 · 三层架构 · WebSocket 协议 · HTTP API · 状态管理 · 会话生命周期 · 协议转换 · 适配器架构 +

+ +![技术栈全景](./images/02-tech-stack.png) + +--- + +## 一、技术栈全景 + +Claude Code 桌面端的技术选型强调**轻量、高性能、跨平台**: + +### 前端层 + +| 技术 | 版本 | 职责 | +|------|------|------| +| **React** | 18.3.1 | UI 框架,函数式组件 + Hooks | +| **Zustand** | 5.0.3 | 轻量级状态管理,零样板代码 | +| **Vite** | 6.0.7 | 构建工具,HMR 热更新 | +| **Tailwind CSS** | 4.0 | 原子化样式框架 | +| **Shiki** | 4.0.2 | VS Code 级别代码语法高亮 | +| **react-diff-viewer** | 4.2.0 | Diff 变更展示 | +| **marked** | 15.0.7 | Markdown 解析渲染 | + +### 桌面层 + +| 技术 | 版本 | 职责 | +|------|------|------| +| **Tauri** | 2.x | 跨平台桌面框架(Rust) | +| **tauri-plugin-shell** | 2.x | Sidecar 进程管理 | +| **tauri-plugin-dialog** | 2.x | 原生文件选择对话框 | +| **tauri-plugin-process** | 2.x | 进程生命周期管理 | + +### 服务端层 + +| 技术 | 职责 | +|------|------| +| **Bun** | JavaScript/TypeScript 运行时 + 构建工具 | +| **Bun.serve** | HTTP/WebSocket 服务器 | +| **Zod** | 请求参数校验 | + +### 字体系统 + +桌面端自托管所有字体,无需 CDN 依赖: + +- **Inter** (400-600) — 正文 +- **Manrope** (400-800) — 标题 +- **JetBrains Mono** — 代码 +- **Material Symbols Outlined** — 图标 + +--- + +## 二、三层架构 + +![三层架构图](./images/03-three-layer-arch.png) + +桌面端采用**三层架构**设计,各层职责明确: + +``` +┌─────────────────────────────────┐ +│ Tauri 主进程 (Rust) │ +│ ┌───────────────────────────┐ │ +│ │ WebView (React App) │ │ ← 用户看到的界面 +│ │ Port 1420 (开发) / 内置 │ │ +│ └───────────┬───────────────┘ │ +│ │ HTTP + WebSocket │ +│ ┌───────────▼───────────────┐ │ +│ │ Sidecar: claude-server │ │ ← Bun 编译的服务端二进制 +│ │ Port: 动态分配 │ │ +│ └───────────┬───────────────┘ │ +│ │ 子进程 spawn │ +│ ┌───────────▼───────────────┐ │ +│ │ CLI 子进程 (claude-cli) │ │ ← 实际执行 AI 对话和工具调用 +│ │ stdin/stdout 通信 │ │ +│ └───────────────────────────┘ │ +└─────────────────────────────────┘ +``` + +### 第一层:Tauri 主进程 + +**职责**:窗口管理、进程编排、原生 API 桥接 + +关键文件:`desktop/src-tauri/src/lib.rs` + +```rust +// 核心功能 +fn reserve_local_port() -> u16 // 获取空闲端口 +fn wait_for_server(port) -> bool // 等待服务就绪(超时 10 秒) +fn start_server_sidecar(port) // 启动 Server 后台进程 +fn stop_server_sidecar() // 停止 Server 后台进程 + +// Tauri 命令(暴露给前端调用) +#[tauri::command] +fn get_server_url() -> String // 返回 http://127.0.0.1:{port} +``` + +启动流程: +1. Tauri 主进程启动 +2. 调用 `reserve_local_port()` 获取空闲端口 +3. 启动 `claude-server` sidecar 进程,传入端口号 +4. 调用 `wait_for_server()` 轮询等待服务就绪 +5. WebView 加载 React 应用 +6. 前端调用 `get_server_url` 获取服务地址 + +### 第二层:Server Sidecar + +**职责**:HTTP API + WebSocket 网关 + 会话管理 + 代理转换 + +关键文件:`src/server/index.ts` + +```typescript +// 服务器启动 +Bun.serve({ + port: config.port, + fetch(req, server) { + // HTTP 路由 + WebSocket 升级 + if (url.pathname.startsWith('/ws/')) { + server.upgrade(req, { data: { sessionId } }) + return + } + return router.handle(req) + }, + websocket: { + open(ws) { /* 连接建立 */ }, + message(ws, msg) { /* 消息处理 */ }, + close(ws) { /* 连接关闭 */ } + } +}) +``` + +Server 提供两类服务: +- **HTTP REST API** — 会话管理、配置读写、模型操作 +- **WebSocket** — 实时消息通道(对话流、权限请求、状态推送) + +### 第三层:CLI 子进程 + +**职责**:AI 对话核心逻辑、工具执行、Agent 编排 + +Server 为每个 Session 创建一个 CLI 子进程: + +```typescript +// 创建 CLI 子进程 +const child = spawn('claude-cli', ['--session', sessionId], { + cwd: workDir, + env: { ...process.env, ANTHROPIC_AUTH_TOKEN: token } +}) + +// 通过 stdin/stdout 通信 +child.stdin.write(JSON.stringify({ type: 'user_message', content })) +child.stdout.on('data', (chunk) => { + // 解析 stream_event,转发给 WebSocket 客户端 +}) +``` + +### Sidecar 构建 + +使用 Bun 将 TypeScript 编译为独立可执行文件: + +```typescript +// desktop/scripts/build-sidecars.ts +// 支持 8 种目标平台: +const targets = [ + 'bun-darwin-arm64', // M1/M2 Mac + 'bun-darwin-x64', // Intel Mac + 'bun-windows-x64', // Windows x64 + 'bun-windows-arm64', // Windows ARM + 'bun-linux-x64', // Linux x64 + 'bun-linux-arm64', // Linux ARM + 'bun-linux-x64-musl', // Alpine Linux + 'bun-linux-arm64-musl', // Alpine ARM +] +``` + +编译产物放置在 `desktop/src-tauri/binaries/`,Tauri 打包时自动包含。 + +--- + +## 三、WebSocket 通信协议 + +![WebSocket 通信协议](./images/04-websocket-protocol.png) + +WebSocket 是桌面端与服务端实时通信的核心通道。 + +### 连接建立 + +``` +ws://127.0.0.1:{port}/ws/{sessionId} +``` + +前端通过 `wsManager`(单例)管理所有 WebSocket 连接: + +```typescript +// desktop/src/api/websocket.ts +class WebSocketManager { + private connections = new Map() + + connect(sessionId: string): void { + const ws = new WebSocket(`${baseUrl}/ws/${sessionId}`) + // 自动重连(指数退避) + // 消息队列(连接未就绪时缓冲) + // 心跳 ping(30 秒间隔) + } +} +``` + +### 客户端 → 服务端消息 + +| type | 字段 | 说明 | +|------|------|------| +| `user_message` | `content`, `attachments?` | 用户发送消息 | +| `permission_response` | `requestId`, `allowed`, `rule?` | 权限审批响应 | +| `set_permission_mode` | `mode` | 切换权限模式 | +| `stop_generation` | — | 停止当前生成 | +| `ping` | — | 心跳保活 | + +### 服务端 → 客户端消息 + +| type | 关键字段 | 说明 | +|------|----------|------| +| `connected` | `sessionId` | 连接成功确认 | +| `status` | `state`, `verb?`, `elapsed?` | 状态变更(thinking/generating) | +| `content_start` | `blockType` | 内容块开始(text/tool_use) | +| `content_delta` | `text?`, `toolInput?` | 增量内容(流式文本) | +| `thinking` | `text` | Extended Thinking 内容 | +| `tool_use_complete` | `toolName`, `input` | 工具调用准备就绪 | +| `tool_result` | `output`, `isError` | 工具执行结果 | +| `permission_request` | `toolName`, `input`, `requestId` | 权限请求 | +| `message_complete` | `usage: TokenUsage` | 消息完成(含 Token 统计) | +| `error` | `message`, `code` | 错误通知 | +| `session_title_updated` | `title` | 会话标题更新 | +| `team_update` | `team` | 团队状态变更 | +| `team_created` / `team_deleted` | `teamName` | 团队创建/删除 | +| `task_update` | `task` | 任务状态变更 | +| `pong` | — | 心跳响应 | + +### 完整消息流示例 + +一条用户消息从发送到收到完整回复的流程: + +``` +用户输入 "写一个排序函数" + ↓ +ChatInput → chatStore.sendMessage() + ↓ +wsManager.send({ type: 'user_message', content: '...' }) + ↓ +Server 收到 → 转发到 CLI 子进程 + ↓ +CLI 开始处理,流式返回事件: + +← { type: 'status', state: 'thinking' } + → UI 显示"思考中..."动画 + +← { type: 'thinking', text: '让我分析...' } + → ThinkingBlock 展示推理过程 + +← { type: 'content_start', blockType: 'text' } + → 准备接收文本内容 + +← { type: 'content_delta', text: 'def sort(' } +← { type: 'content_delta', text: 'arr):\n' } +← { type: 'content_delta', text: ' return sorted(arr)' } + → AssistantMessage 流式渲染,闪烁光标 + +← { type: 'content_start', blockType: 'tool_use' } + → 准备接收工具调用 + +← { type: 'tool_use_complete', toolName: 'Write', input: {...} } + → ToolCallBlock 展示文件写入操作 + +← { type: 'permission_request', toolName: 'Write', requestId: '...' } + → PermissionDialog 弹出,等待用户审批 + +用户点击"允许" + ↓ +→ { type: 'permission_response', requestId: '...', allowed: true } + +← { type: 'tool_result', output: '文件已写入' } + → ToolResultBlock 展示结果 + +← { type: 'message_complete', usage: { input: 1200, output: 350 } } + → 更新 Token 统计,清除流式状态 +``` + +### 连接管理 + +**心跳保活**:每 30 秒发送 `ping`,服务端回复 `pong` + +**自动重连**:指数退避策略 + +``` +重连间隔 = min(1000ms × 2^(attempt-1), 30000ms) +最大重连次数 = 10 +``` + +**消息缓冲**:WebSocket 未就绪时,消息暂存队列,连接恢复后自动发送。 + +--- + +## 四、HTTP API 端点 + +Server 提供完整的 RESTful API,供前端和适配器调用。 + +### 会话管理 + +| 方法 | 端点 | 说明 | +|------|------|------| +| `GET` | `/api/sessions` | 获取会话列表 | +| `POST` | `/api/sessions` | 创建新会话 | +| `GET` | `/api/sessions/:id` | 获取会话详情 | +| `PATCH` | `/api/sessions/:id` | 重命名会话 | +| `DELETE` | `/api/sessions/:id` | 删除会话 | +| `GET` | `/api/sessions/:id/messages` | 获取历史消息 | +| `GET` | `/api/sessions/:id/git-info` | 获取 Git 信息 | +| `GET` | `/api/sessions/:id/slash-commands` | 获取可用斜杠命令 | +| `GET` | `/api/sessions/recent-projects` | 最近项目列表 | + +### 模型与提供商 + +| 方法 | 端点 | 说明 | +|------|------|------| +| `GET` | `/api/models` | 可用模型列表 | +| `GET` | `/api/models/current` | 当前使用的模型 | +| `POST` | `/api/models/:id/set-current` | 切换模型 | +| `GET/POST` | `/api/models/effort` | 获取/设置 Effort 级别 | +| `GET` | `/api/providers` | 提供商列表 | +| `POST` | `/api/providers` | 创建提供商 | +| `PUT` | `/api/providers/:id` | 更新提供商配置 | +| `DELETE` | `/api/providers/:id` | 删除提供商 | +| `POST` | `/api/providers/:id/activate` | 激活提供商 | +| `POST` | `/api/providers/:id/test` | 测试连接 | +| `GET` | `/api/providers/presets` | 获取预设列表 | + +### 定时任务 + +| 方法 | 端点 | 说明 | +|------|------|------| +| `GET` | `/api/scheduled-tasks` | 任务列表 | +| `POST` | `/api/scheduled-tasks` | 创建任务 | +| `PUT` | `/api/scheduled-tasks/:id` | 更新任务 | +| `DELETE` | `/api/scheduled-tasks/:id` | 删除任务 | +| `POST` | `/api/scheduled-tasks/:id/run` | 手动运行 | +| `GET` | `/api/scheduled-tasks/runs` | 所有运行记录 | +| `GET` | `/api/scheduled-tasks/:id/runs` | 单任务运行记录 | + +### Agent 团队 + +| 方法 | 端点 | 说明 | +|------|------|------| +| `GET` | `/api/teams` | 团队列表 | +| `GET` | `/api/teams/:name` | 团队详情 | +| `GET` | `/api/teams/:name/members/:agentId/transcript` | 成员转录 | +| `DELETE` | `/api/teams/:name` | 删除团队 | + +### 其他 + +| 方法 | 端点 | 说明 | +|------|------|------| +| `GET` | `/health` | 健康检查 | +| `GET/POST` | `/api/settings/permission-mode` | 权限模式 | +| `GET` | `/api/agents` | Agent 定义列表 | +| `GET` | `/api/skills` | 技能列表 | +| `GET` | `/api/skills/detail` | 技能详情 | +| `GET/PUT` | `/api/adapters` | 适配器配置 | + +--- + +## 五、状态管理 + +![会话生命周期](./images/05-session-lifecycle.png) + +桌面端使用 **Zustand** 进行状态管理,按领域拆分为多个独立 Store。 + +### Store 架构 + +``` +stores/ +├── chatStore.ts # 聊天状态(消息、流式、权限) 20KB +├── sessionStore.ts # 会话列表、创建、删除 +├── tabStore.ts # 标签页管理、顺序、持久化 5KB +├── settingsStore.ts # 全局设置(模型、权限、语言) +├── providerStore.ts # LLM 提供商配置 +├── uiStore.ts # UI 状态(主题、Toast、模态框) +├── taskStore.ts # 定时任务管理 +├── teamStore.ts # Agent 团队状态 +├── agentStore.ts # Agent 定义管理 +├── skillStore.ts # 技能库 +├── adapterStore.ts # 适配器配置 +└── cliTaskStore.ts # CLI 任务状态 +``` + +### chatStore 核心设计 + +`chatStore` 是最复杂的 Store,为**每个 Session 维护独立状态**: + +```typescript +type PerSessionState = { + messages: UIMessage[] // 消息列表 + chatState: 'idle' | 'thinking' | ... // 对话状态 + connectionState: ConnectionState // WebSocket 连接状态 + streamingText: string // 流式文本缓冲 + streamingToolInput: string // 工具输入流 + activeToolUseId: string | null // 当前工具调用 ID + activeToolName: string | null // 当前工具名称 + activeThinkingId: string | null // 当前思考块 ID + pendingPermission: PermissionRequest | null // 待决权限 + tokenUsage: TokenUsage // Token 使用统计 + elapsedSeconds: number // 经过时间 + statusVerb: string // 随机状态动词 + slashCommands: SlashCommand[] // 可用命令列表 +} +``` + +关键方法: + +| 方法 | 职责 | +|------|------| +| `connectToSession(id)` | 建立 WebSocket 连接 | +| `disconnectSession(id)` | 断开连接 | +| `sendMessage(id, content, attachments)` | 发送用户消息 | +| `respondToPermission(id, requestId, allowed, rule)` | 权限审批 | +| `stopGeneration(id)` | 停止生成 | +| `loadHistory(id)` | 加载历史消息 | +| `handleServerMessage(id, msg)` | 处理服务端消息 | + +### 数据流向 + +``` +用户操作 + ↓ +Component (调用 Store 方法) + ↓ +Store (更新状态 + 调用 API/WebSocket) + ↓ +API 层 (HTTP 请求 / WebSocket 发送) + ↓ +Server 响应 + ↓ +Store (更新状态) + ↓ +Component (自动重渲染) +``` + +### 持久化策略 + +| 数据 | 存储位置 | 说明 | +|------|----------|------| +| 打开的标签页 | `localStorage` | 页面刷新/重启后恢复 | +| 会话数据 | Server JSONL 文件 | `~/.claude/sessions/` | +| 设置 | Server API | 通过 HTTP 读写 | +| 适配器配置 | `~/.claude/adapters.json` | JSON 文件 | +| 会话映射 | `~/.claude/adapter-sessions.json` | 适配器 Chat→Session 映射 | + +--- + +## 六、会话生命周期 + +一个会话从创建到恢复的完整流程: + +### 创建 + +``` +用户点击 + 新建会话 + ↓ +sessionStore.createSession({ workDir }) + ↓ +POST /api/sessions { workDir: '/path/to/project' } + ↓ +Server 创建 Session 记录 → 返回 { sessionId } + ↓ +tabStore.openTab(sessionId) + ↓ +chatStore.connectToSession(sessionId) + ↓ +WebSocket 连接 → 收到 { type: 'connected' } +``` + +### 交互 + +``` +用户发送消息 + ↓ +wsManager.send({ type: 'user_message', content }) + ↓ +Server 转发到 CLI 子进程 + ↓ +CLI 处理 → 流式返回 stream_event + ↓ +Server 转换为 ServerMessage → 推送到 WebSocket + ↓ +chatStore.handleServerMessage() → UI 更新 +``` + +### 断开 + +``` +用户关闭标签页 / 切换到其他标签 + ↓ +chatStore.disconnectSession(sessionId) + ↓ +WebSocket 关闭 + ↓ +CLI 子进程可能继续运行(后台任务) +``` + +### 恢复 + +``` +应用启动 / 切回标签页 + ↓ +tabStore.restoreTabs() // 从 localStorage 读取 + ↓ +验证会话是否仍存在 (GET /api/sessions) + ↓ +chatStore.connectToSession(sessionId) + ↓ +chatStore.loadHistory(sessionId) // GET /api/sessions/:id/messages + ↓ +WebSocket 重连 → 恢复实时通信 +``` + +### 会话持久化 + +Server 使用 **JSONL(JSON Lines)** 格式持久化会话数据: + +``` +~/.claude/sessions/ +├── {sessionId}/ +│ ├── messages.jsonl ← 流式追加,每行一条消息/事件 +│ ├── metadata.json ← 会话元数据(workDir、标题、模型等) +│ └── ... +``` + +JSONL 格式的优势: +- **流式追加**:新消息直接 append,无需重写整个文件 +- **崩溃恢复**:即使中途崩溃,已写入的行不会丢失 +- **大会话支持**:按行读取,无需一次性加载整个 JSON + +--- + +## 七、代理层协议转换 + +Server 内置了多协议代理层(Proxy),让不同 AI 提供商的 API 统一接入。 + +### 支持的 API 格式 + +| 格式 | 说明 | 典型提供商 | +|------|------|-----------| +| `anthropic` | Anthropic Messages API | Anthropic 官方、MiniMax | +| `openai_chat` | OpenAI Chat Completions | OpenAI、DeepSeek | +| `openai_responses` | OpenAI Responses API | OpenAI 新接口 | + +### 协议转换流程 + +``` +前端发送消息 + ↓ +Server 接收 + ↓ +判断当前 Provider 的 API 格式 + ↓ +┌─────────────────────────────────┐ +│ anthropic │ openai_chat/resp │ +│ 直接透传 │ 转换消息格式 │ +│ │ system → 系统消息 │ +│ │ tool_use → 函数调用 │ +│ │ tool_result → 函数结果│ +└──────┬──────┴──────┬────────────┘ + │ │ + ↓ ↓ + Anthropic API OpenAI API + │ │ + ↓ ↓ + 直接返回 反向转换响应格式 + │ │ + └──────┬──────┘ + ↓ + 统一的 ServerMessage 格式 + ↓ + WebSocket 推送给前端 +``` + +### 模型映射 + +每个 Provider 可配置四个模型槽位: + +| 槽位 | 用途 | +|------|------| +| `main` | 主对话模型 | +| `haiku` | 快速/轻量任务 | +| `sonnet` | 中等复杂度 | +| `opus` | 最高能力 | + +例如 OpenRouter 配置: + +```json +{ + "apiFormat": "anthropic", + "baseUrl": "https://openrouter.ai/api/v1", + "modelMapping": { + "main": "anthropic/claude-sonnet-4-20250514", + "haiku": "anthropic/claude-haiku-4-5-20251001", + "opus": "anthropic/claude-opus-4-20250514" + } +} +``` + +--- + +## 八、适配器桥接架构 + +![适配器桥接架构](./images/07-adapter-bridge.png) + +适配器系统让**任何 IM 平台**都可以接入 Claude Code,无需修改核心代码。 + +### 整体架构 + +``` +┌──────────────┐ ┌──────────────┐ +│ Telegram │ │ 飞书 │ ← IM 平台 +│ grammy │ │ Lark SDK │ +└──────┬───────┘ └──────┬───────┘ + │ │ + ▼ ▼ +┌──────────────────────────────────┐ +│ Adapter 进程 │ ← 平台适配层 +│ ┌─────────────────────────────┐ │ +│ │ common/ 共享模块 │ │ +│ │ config │ ws-bridge │ │ +│ │ pairing │ message-buffer │ │ +│ │ dedup │ chat-queue │ │ +│ │ session │ http-client │ │ +│ └─────────────────────────────┘ │ +└──────────────┬───────────────────┘ + │ HTTP + WebSocket + ▼ +┌──────────────────────────────────┐ +│ Desktop Server │ ← 服务端 +│ POST /api/sessions │ +│ WS /ws/{sessionId} │ +└──────────────┬───────────────────┘ + │ + ▼ +┌──────────────────────────────────┐ +│ CLI 子进程 │ ← AI 对话引擎 +└──────────────────────────────────┘ +``` + +### 四层架构 + +| 层级 | 职责 | 关键文件 | +|------|------|----------| +| **配置层** | 桌面端 UI 填写凭证 | `desktop/src/pages/AdapterSettings.tsx` | +| **存储层** | 配置读写和脱敏 | `src/server/services/adapterService.ts` | +| **适配层** | IM SDK 对接、消息路由 | `adapters/telegram/index.ts`, `adapters/feishu/index.ts` | +| **会话层** | WebSocket 桥接到 Server | `adapters/common/ws-bridge.ts` | + +### 共享模块 + +所有适配器共用 `adapters/common/` 模块: + +| 模块 | 职责 | +|------|------| +| `config.ts` | 配置加载(环境变量 > JSON 文件 > 默认值) | +| `ws-bridge.ts` | WebSocket 连接管理(心跳、重连、消息路由) | +| `pairing.ts` | 用户配对(6 位安全码、速率限制) | +| `session-store.ts` | Chat→Session 映射持久化 | +| `message-buffer.ts` | 流式消息缓冲(500ms/200 字符阈值刷新) | +| `message-dedup.ts` | 消息去重(防重连重复) | +| `chat-queue.ts` | 同一 Chat 消息串行队列 | +| `http-client.ts` | HTTP 客户端(创建会话、获取项目列表) | + +### 接入新 IM 平台 + +得益于模块化设计,接入新平台只需三步: + +**1. 创建适配器文件** + +```typescript +// adapters/discord/index.ts +import { WsBridge } from '../common/ws-bridge.js' +import { MessageBuffer } from '../common/message-buffer.js' +import { loadConfig } from '../common/config.js' +import { isPaired, tryPair } from '../common/pairing.js' +``` + +**2. 实现消息接收** + +```typescript +bot.on('message', async (msg) => { + // 去重 → 授权检查 → 会话管理 → WebSocket 桥接 + if (!dedup.tryRecord(msg.id)) return + if (!isPaired('discord', msg.author.id, config)) { + tryPair(msg.content, { userId: msg.author.id, ... }, 'discord') + return + } + bridge.sendUserMessage(chatId, msg.content) +}) +``` + +**3. 处理服务端事件** + +```typescript +bridge.onServerMessage(chatId, async (msg) => { + switch (msg.type) { + case 'content_delta': /* 流式文本 */ break + case 'permission_request': /* 权限按钮 */ break + case 'message_complete': /* 完成 */ break + } +}) +``` + +### 消息缓冲机制 + +为防止 IM 平台的消息频率限制,适配器使用 `MessageBuffer` 批量刷新: + +``` +content_delta: "def " ─┐ +content_delta: "sort(" │→ 缓冲累积 +content_delta: "arr):" │ + ↓ 500ms 或 200 字符 + IM 平台: "def sort(arr): ▍" (编辑消息) + +content_delta: "\n ..." ─┐ +content_delta: "return" │→ 继续缓冲 + ↓ + IM 平台: "def sort(arr):\n return ▍" + +message_complete ↓ + IM 平台: 最终完整文本(分片发送) +``` + +分片限制: +- Telegram: 4000 字符/消息 +- 飞书: 30000 字符/消息 + +--- + +## 九、项目目录结构 + +``` +desktop/ +├── src/ # React 前端 +│ ├── App.tsx # 根组件 +│ ├── main.tsx # 入口 +│ ├── components/ +│ │ ├── layout/ # 布局:AppShell, Sidebar, TabBar +│ │ ├── chat/ # 聊天:MessageList, ChatInput, ToolCallBlock +│ │ ├── shared/ # 通用:Button, Modal, Toast, Spinner +│ │ ├── controls/ # 控件:ModelSelector, PermissionModeSelector +│ │ ├── markdown/ # MarkdownRenderer +│ │ ├── skills/ # 技能浏览 +│ │ ├── tasks/ # 任务管理 +│ │ └── teams/ # 团队视图 +│ ├── pages/ # 页面:ActiveSession, Settings, ScheduledTasks +│ ├── stores/ # Zustand 状态 +│ ├── api/ # HTTP + WebSocket 客户端 +│ ├── types/ # TypeScript 类型定义 +│ ├── hooks/ # 自定义 Hooks +│ ├── i18n/ # 国际化 +│ ├── theme/ # 全局样式 +│ ├── config/ # 提供商预设 +│ └── lib/ # 工具库 +├── src-tauri/ # Tauri Rust 后端 +│ ├── src/lib.rs # 核心:端口管理、Sidecar 启动 +│ ├── Cargo.toml # Rust 依赖 +│ └── tauri.conf.json # Tauri 配置 +├── sidecars/ # Sidecar 启动器 +│ ├── server-launcher.ts # Server 进程启动 +│ └── cli-launcher.ts # CLI 进程启动 +├── scripts/ +│ └── build-sidecars.ts # 跨平台编译脚本 +├── vite.config.ts # Vite 构建配置 +├── package.json # 依赖和脚本 +└── tsconfig.json # TypeScript 配置 + +src/server/ # 服务端(独立于 desktop/) +├── index.ts # 入口:Bun.serve +├── router.ts # HTTP 路由 +├── ws/ # WebSocket 处理 +├── api/ # REST API 路由 +├── services/ # 业务服务 +├── proxy/ # 代理层(协议转换) +├── middleware/ # 中间件 +├── config/ # 服务端配置 +└── types/ # 类型定义 + +adapters/ # 外部 IM 适配器 +├── common/ # 共享模块(9 个文件) +├── telegram/index.ts # Telegram Bot +├── feishu/index.ts # 飞书 Bot +└── package.json # 独立依赖 +``` + +--- + +## 十、快速参考 + +### 关键端口 + +| 端口 | 用途 | +|------|------| +| 1420 | Vite 开发服务器 | +| 动态分配 | Server Sidecar(`reserve_local_port`) | + +### 关键文件路径 + +| 文件 | 说明 | +|------|------| +| `~/.claude/adapters.json` | 适配器配置 | +| `~/.claude/adapter-sessions.json` | 适配器会话映射 | +| `~/.claude/sessions/` | 会话持久化数据 | + +### 开发命令 + +```bash +# 前端开发 +cd desktop && pnpm dev + +# 编译 Sidecar +cd desktop && bun run build:sidecars + +# Tauri 开发模式(前端 + 桌面框架) +cd desktop && pnpm tauri dev + +# 构建发布包 +cd desktop && pnpm tauri build + +# 运行测试 +cd desktop && pnpm test +``` diff --git a/docs/desktop/03-features.md b/docs/desktop/03-features.md new file mode 100644 index 00000000..c88ade5f --- /dev/null +++ b/docs/desktop/03-features.md @@ -0,0 +1,755 @@ +# Claude Code 桌面端 — 功能详解 + +> 深入每一个功能模块,从聊天引擎到定时任务,全面解析桌面端的能力矩阵。 + +

+聊天引擎 · 工具调用 · 代码展示 · Agent Teams · 提供商管理 · 技能与 Agent · 定时任务 · IM 适配器 · 设计系统 +

+ +![功能全景图](./images/06-features-grid.png) + +--- + +## 一、聊天引擎 + +聊天引擎是桌面端的核心,负责消息的发送、接收、渲染和交互。 + +### 消息列表(MessageList) + +**文件位置**:`desktop/src/components/chat/MessageList.tsx` + +消息列表是对话的主展示区域: + +- **自动滚动**:新消息到达时 smooth 滚动到底部 +- **消息分组**:Tool calls 和对应的 results 按组展示 +- **混合渲染**:支持文本、代码、Diff、工具调用等多种内容类型 + +### 消息类型详解 + +#### 用户消息(UserMessage) + +``` +┌──────────────────────────────┐ +│ 👤 写一个快速排序算法 │ +│ 📎 screenshot.png (附件) │ +│ [复制] │ +└──────────────────────────────┘ +``` + +- 用户头像 + 消息文本 +- 附件画廊展示(图片缩略图、文件图标) +- 悬浮显示消息操作栏 + +#### 助手消息(AssistantMessage) + +``` +┌──────────────────────────────────┐ +│ ┌──────────────────────────────┐ │ +│ │ 好的,我来实现快速排序: │ │ +│ │ │ │ +│ │ ```python │ │ +│ │ def quicksort(arr): │ │ +│ │ if len(arr) <= 1: │ │ +│ │ return arr │ │ +│ │ ``` │ │ +│ │ [复制] ▍ │ │ +│ └──────────────────────────────┘ │ +└──────────────────────────────────┘ +``` + +- 带边框的气泡容器 +- 完整 Markdown 渲染(标题、列表、表格、引用、链接) +- 代码块使用 Shiki 语法高亮 +- 流式输出时显示闪烁光标 `▍` + +#### 思考块(ThinkingBlock) + +``` +┌──────────────────────────────────┐ +│ 💭 思考过程 [展开 ▼] │ +│ │ +│ ┌──────────────────────────────┐ │ +│ │ 让我分析一下用户的需求... │ │ +│ │ 快速排序的时间复杂度是... │ │ +│ │ 我应该用 Lomuto 分区方案... │ │ +│ └──────────────────────────────┘ │ +└──────────────────────────────────┘ +``` + +- 默认折叠,显示第一行预览 +- 点击展开查看完整推理过程 +- 流式更新时显示动画光标 +- 自动滚动到最新思考内容 + +#### 权限请求(PermissionDialog) + +``` +┌──────────────────────────────────┐ +│ ⚠️ 权限请求 │ +│ │ +│ 工具: Write │ +│ 文件: /src/sort.py │ +│ │ +│ ┌──────────────────────────────┐ │ +│ │ + def quicksort(arr): │ │ +│ │ + if len(arr) <= 1: │ │ +│ │ + return arr │ │ +│ └──────────────────────────────┘ │ +│ │ +│ [允许] [一直允许] [拒绝] │ +└──────────────────────────────────┘ +``` + +- 显示工具类型和操作目标 +- 预览操作内容(Diff、命令等) +- 可展开查看完整输入参数 +- 三个操作按钮:允许 / 一直允许 / 拒绝 + +#### AskUser 提问 + +当 AI 使用 `AskUserQuestion` 工具向你提问时,会显示一个专用输入框,你的回答会直接发送给 AI。 + +#### 内联任务摘要(InlineTaskSummary) + +当 AI 创建后台任务时,对话中会内联显示任务的进度和结果摘要。 + +### 输入系统(ChatInput) + +**文件位置**:`desktop/src/components/chat/ChatInput.tsx` + +输入框是一个功能丰富的组合组件: + +``` +┌──────────────────────────────────┐ +│ 📎 screenshot.png × │ ← 附件画廊 +├──────────────────────────────────┤ +│ 🏷️ myproject (main) │ ← 项目上下文芯片 +├──────────────────────────────────┤ +│ │ +│ 输入消息... │ ← 可扩展文本框 +│ │ +├──────────────┬───────────────────┤ +│ [+] │ [发送] │ ← 工具栏 +└──────────────┴───────────────────┘ +``` + +**核心功能**: + +1. **自适应高度**:文本框随内容自动扩展,最高 200px +2. **附件画廊**:显示待发送的文件/图片 +3. **项目上下文芯片**:展示当前 Git 仓库和分支 +4. **Plus 菜单**:添加文件 / 插入斜杠命令 +5. **斜杠命令菜单**:`/` 触发,支持搜索和键盘导航 +6. **文件搜索菜单**:`@` 触发,路径自动补全 +7. **快捷键**:Enter 发送、Shift+Enter 换行、Esc 关闭菜单 + +--- + +## 二、工具调用系统 + +当 AI 执行工具操作时,桌面端会以结构化的方式展示工具调用和结果。 + +### 工具调用块(ToolCallBlock) + +**文件位置**:`desktop/src/components/chat/ToolCallBlock.tsx` + +每种工具有专门的展示方式: + +#### Bash 工具 + +``` +┌──────────────────────────────────┐ +│ 🖥️ Bash │ +│ │ +│ $ npm install express │ ← 终端风格 +│ │ +│ 说明: Install express package │ +│ [展开] │ +└──────────────────────────────────┘ +``` + +使用 `TerminalChrome` 组件模拟终端界面: +- 深色背景 +- 绿色提示符 `$` +- 显示命令内容和说明 + +#### Edit / Write 工具 + +``` +┌──────────────────────────────────┐ +│ ✏️ Edit src/app.ts │ +│ │ +│ ┌──────────────────────────────┐ │ +│ │ - const port = 3000 │ │ ← Diff 视图 +│ │ + const port = 8080 │ │ +│ └──────────────────────────────┘ │ +│ │ +│ +1 -1 行 │ +└──────────────────────────────────┘ +``` + +- 使用 `DiffViewer` 展示文件变更 +- 显示行数统计(+N / -N) +- 自动识别文件语言 +- 词级别 Diff 高亮 + +#### Read 工具 + +展示被读取的文件内容,使用 `CodeViewer` 语法高亮。 + +#### Glob / Grep 工具 + +展示搜索模式和匹配结果。 + +#### WebSearch / WebFetch 工具 + +展示搜索关键词或目标 URL。 + +#### 其他工具 + +以 JSON 格式展示工具的输入参数,可展开查看详情。 + +### 工具结果块(ToolResultBlock) + +工具执行后的输出展示: + +- **成功** → 绿色状态指示 + 输出内容 +- **错误** → 红色状态指示 + 错误信息 +- 输出以代码块展示,支持语法高亮 +- 超长输出自动截断,显示行数摘要 + +--- + +## 三、代码展示系统 + +桌面端在代码展示方面追求**VS Code 级别的体验**。 + +### CodeViewer + +**文件位置**:`desktop/src/components/chat/CodeViewer.tsx` + +- **引擎**:Shiki(与 VS Code 相同的语法高亮引擎) +- **主题**:自定义温暖色调主题,与应用设计系统匹配 +- **行号**:左侧行号显示 +- **折叠**:超过 20 行时自动折叠,点击展开 +- **复制**:右上角一键复制按钮 + +### DiffViewer + +**文件位置**:`desktop/src/components/chat/DiffViewer.tsx` + +- **引擎**:react-diff-viewer-continued +- **模式**:单列(split view 更紧凑) +- **高亮**:词级别变更高亮 +- **统计**:顶部显示 +N/-N 行数变化 +- **语言识别**:根据文件扩展名自动识别语言 + +### MarkdownRenderer + +**文件位置**:`desktop/src/components/markdown/MarkdownRenderer.tsx` + +- 基于 `marked` 解析 Markdown +- 代码块自动使用 Shiki 高亮 +- 支持表格、列表、引用、链接 +- 内联代码和粗体/斜体 + +--- + +## 四、Agent Teams 团队协作 + +![聊天消息流](./images/08-chat-message-flow.png) + +桌面端可视化展示 Agent Teams 的协作状态。 + +### 团队视图(AgentTeams) + +**文件位置**:`desktop/src/pages/AgentTeams.tsx` + +当 AI 创建 Agent Team 时,桌面端显示团队管理界面: + +- **团队列表**:所有活跃团队 +- **成员状态**:每个 Agent 的实时状态 + +| 状态 | 指示 | +|------|------| +| running | 绿色脉冲动画 | +| idle | 灰色 | +| completed | 完成标记 | +| error | 红色错误标记 | + +- **成员标签**:彩色标签显示 Agent 角色和名称 +- **实时更新**:通过 WebSocket 推送 `team_update` 事件 + +### 转录视图(AgentTranscript) + +点击团队成员可查看该 Agent 的完整对话转录: + +- 与主聊天相同的消息渲染 +- 支持查看工具调用和结果 +- 「返回团队」导航按钮 + +### TeamStatusBar + +**文件位置**:`desktop/src/components/teams/TeamStatusBar.tsx` + +在活跃会话底部展示团队状态条: +- 团队名称 +- 成员数量和状态分布 +- 快速导航到团队视图 + +--- + +## 五、提供商管理 + +桌面端提供了完整的 AI 提供商管理界面。 + +### 提供商列表 + +**文件位置**:`desktop/src/pages/Settings.tsx`(Providers 标签页) + +展示所有已配置的提供商: + +``` +┌──────────────────────────────────┐ +│ ✅ Anthropic (Official) [活跃] │ ← 官方提供商 +├──────────────────────────────────┤ +│ 🔵 OpenRouter [编辑]│ ← 自定义提供商 +│ Base: openrouter.ai/api/v1 │ +│ Format: anthropic │ +├──────────────────────────────────┤ +│ ⚪ Ollama (Local) [编辑]│ ← 本地模型 +│ Base: localhost:11434 │ +│ Format: openai_chat │ +├──────────────────────────────────┤ +│ [+ 添加提供商] │ +└──────────────────────────────────┘ +``` + +### 提供商配置 + +每个提供商可配置: + +| 字段 | 说明 | +|------|------| +| 名称 | 提供商显示名称 | +| API Key | 密钥(密码输入,自动脱敏) | +| Base URL | API 基础地址 | +| API 格式 | `anthropic` / `openai_chat` / `openai_responses` | +| 模型映射 | main / haiku / sonnet / opus 槽位对应的模型名 | + +### 预设系统 + +**文件位置**:`desktop/src/config/providerPresets.ts` + +点击「添加提供商」时,可从预设快速创建: + +- Anthropic +- OpenAI +- OpenRouter +- Ollama +- Azure OpenAI +- Google AI +- 自定义... + +预设自动填充 Base URL 和 API 格式,只需填入 API Key。 + +### 连接测试 + +配置完成后点击「测试」,系统执行两步验证: + +1. **连接性测试** — 发送简单请求验证网络可达 +2. **模型可用性测试** — 验证配置的模型是否可用 + +结果以 Toast 通知展示(成功 / 失败 + 错误信息)。 + +--- + +## 六、技能与 Agent 定义 + +### 技能浏览(SkillList / SkillDetail) + +**文件位置**:`desktop/src/components/skills/` + +技能库浏览界面: + +- **列表视图**:按来源分类(bundled / user / project / plugin) +- **搜索过滤**:按名称和描述搜索 +- **详情视图**: + - 技能元数据(描述、版本、来源) + - 源代码目录树 + - 代码文件内容(带语法高亮) + - Frontmatter 属性展示 + +### Agent 定义管理 + +**文件位置**:`desktop/src/pages/Settings.tsx`(Agents 标签页) + +管理 Agent 类型定义: + +| 字段 | 说明 | +|------|------| +| agentType | Agent 类型标识符 | +| description | 描述(何时使用) | +| model | 默认模型(sonnet/haiku/opus) | +| tools | 可用工具列表 | +| systemPrompt | 自定义系统提示词 | +| color | 标识颜色 | + +**来源分类**: + +| 来源 | 说明 | +|------|------| +| built-in | 系统内置(不可修改) | +| plugin | 插件提供 | +| userSettings | 用户级自定义 | +| projectSettings | 项目级自定义 | +| localSettings | 本地自定义 | + +--- + +## 七、定时任务系统 + +### 任务管理页面 + +**文件位置**:`desktop/src/pages/ScheduledTasks.tsx` + +#### 统计卡片 + +页面顶部三个统计卡片: + +``` +┌──────────┐ ┌──────────┐ ┌──────────┐ +│ 总计 5 │ │ 活跃 3 │ │ 禁用 2 │ +└──────────┘ └──────────┘ └──────────┘ +``` + +#### 任务列表 + +每个任务行展示: + +``` +┌──────────────────────────────────────────────┐ +│ 📋 每日代码审查 [启用 ✓] │ +│ 每天 09:00 执行 │ +│ cron: 0 9 * * * │ +│ │ +│ [运行历史 ▼] [手动运行] [删除] │ +│ │ +│ ┌──────────────────────────────────────┐ │ +│ │ 2026-04-10 09:00 ✅ 成功 (12s) │ │ +│ │ 2026-04-09 09:00 ✅ 成功 (8s) │ │ +│ │ 2026-04-08 09:00 ❌ 失败: timeout │ │ +│ └──────────────────────────────────────┘ │ +└──────────────────────────────────────────────┘ +``` + +### 创建任务 + +**文件位置**:`desktop/src/pages/NewTaskModal.tsx` + +模态框表单: + +| 字段 | 组件 | 说明 | +|------|------|------| +| 任务名称 | Input | 描述性名称 | +| 提示词 | PromptEditor | 多行文本编辑器 | +| Cron 表达式 | Input + 解释文本 | 支持标准 Cron 语法 | +| 星期几 | DayOfWeekPicker | 可视化多选星期 | +| 模型 | ModelSelector | 使用的 AI 模型 | +| 权限模式 | PermissionModeSelector | 执行时的权限策略 | + +#### DayOfWeekPicker + +``` +┌───┬───┬───┬───┬───┬───┬───┐ +│ 日│ 一│ 二│ 三│ 四│ 五│ 六│ +│ │ ✓ │ ✓ │ ✓ │ ✓ │ ✓ │ │ +└───┴───┴───┴───┴───┴───┴───┘ +``` + +可视化选择任务执行的星期几,自动更新 Cron 表达式。 + +### Cron 表达式 + +使用 `cronDescribe` 工具将 Cron 表达式转换为人类可读描述: + +``` +0 9 * * 1-5 → "周一到周五每天 09:00" +*/30 * * * * → "每 30 分钟" +0 0 1 * * → "每月 1 号 00:00" +``` + +--- + +## 八、IM 适配器 + +### 适配器设置页面 + +**文件位置**:`desktop/src/pages/AdapterSettings.tsx` + +#### 配对管理 + +``` +┌──────────────────────────────────┐ +│ 🔐 用户配对 │ +│ │ +│ 当前配对码: A3K7NP │ +│ 过期时间: 58 分钟后 │ +│ │ +│ [生成新配对码] │ +│ │ +│ 已配对用户: │ +│ ┌──────────────────────────────┐ │ +│ │ Telegram │ @john 2026-04-01 │ │ +│ │ 飞书 │ 张三 2026-04-05 │ │ +│ └──────────────────────────────┘ │ +└──────────────────────────────────┘ +``` + +#### Telegram 配置 + +| 字段 | 类型 | 说明 | +|------|------|------| +| Bot Token | 密码输入 | Telegram Bot API Token | +| 允许的用户 ID | 逗号分隔 | 静态白名单 | + +#### 飞书配置 + +| 字段 | 类型 | 说明 | +|------|------|------| +| App ID | 文本 | 飞书应用 ID | +| App Secret | 密码 | 飞书应用密钥 | +| 加密密钥 | 密码 | 事件加密密钥 | +| 验证 Token | 密码 | 事件验证 Token | +| 允许的用户 | 逗号分隔 | open_id 白名单 | +| 流式卡片 | 开关 | 是否启用流式消息卡片 | + +### 飞书适配器特性 + +**文件位置**:`adapters/feishu/index.ts` + +- **连接方式**:WebSocket 长连接(无需公网地址) +- **消息格式**:飞书 JSON 富文本 → Markdown 文本 +- **权限审批**:Interactive Card(卡片按钮) +- **消息更新**:Patch API 编辑已发消息(流式效果) +- **分片发送**:超过 30000 字时自动分片 + +### Telegram 适配器特性 + +**文件位置**:`adapters/telegram/index.ts` + +- **连接方式**:Polling 模式(Bot 主动轮询) +- **消息格式**:纯文本 + Markdown +- **权限审批**:Inline Keyboard(内联按钮) +- **消息更新**:`editMessageText` 编辑已发消息 +- **分片发送**:超过 4000 字时自动分片 + +### 权限请求在 IM 中的展示 + +**Telegram**: +``` +⚠️ 权限请求 +工具: Bash +命令: npm install express +说明: Install express package + +[✅ 允许] [❌ 拒绝] ← Inline Keyboard +``` + +**飞书**: +``` +┌──────────────────────────┐ +│ ⚠️ 权限请求 │ +│ │ +│ 工具: Bash │ +│ 命令: npm install express│ +│ │ +│ [✅ 允许] [❌ 拒绝] │ ← Interactive Card +└──────────────────────────┘ +``` + +--- + +## 九、设计系统 + +### 颜色体系 + +桌面端采用**暖色调**设计语言: + +**文件位置**:`desktop/src/theme/globals.css` + +#### 主色 + +| 变量 | 色值 | 用途 | +|------|------|------| +| `--color-primary` | #8F482F | 品牌色、CTA 按钮 | +| `--color-primary-container` | #AD5F45 | 品牌色容器 | +| `--color-on-primary` | #FFFFFF | 品牌色上的文字 | + +#### 表面色 + +| 变量 | 色值 | 用途 | +|------|------|------| +| `--color-surface` | #FAF9F5 | 主背景(浅米色) | +| `--color-surface-container` | #EFEEEA | 卡片背景 | +| `--color-surface-container-low` | #F4F4F0 | 次级容器 | +| `--color-surface-container-high` | #E9E8E4 | 高层级容器 | + +#### 语义色 + +| 变量 | 色值 | 用途 | +|------|------|------| +| `--color-secondary` | #2D628F | 信息、链接 | +| `--color-tertiary` | #4F6237 | 成功、确认 | +| `--color-error` | #BA1A1A | 错误、警告 | + +#### 文本色 + +| 变量 | 色值 | 用途 | +|------|------|------| +| `--color-on-surface` | #1B1C1A | 主文本 | +| `--color-on-surface-variant` | #54433E | 次级文本 | +| `--color-outline` | #87736D | 边框 | +| `--color-outline-variant` | #DAC1BA | 弱边框 | + +### 字体系统 + +| 字体 | 用途 | 字重 | +|------|------|------| +| **Inter** | 正文 | 400-600 | +| **Manrope** | 标题 | 400-800 | +| **JetBrains Mono** | 代码 | 400 | + +### 图标系统 + +使用 **Material Symbols Outlined** 图标集,自托管字体: + +- 齿轮 → 设置 +- 时钟 → 定时任务 +- + → 新建 +- × → 关闭 +- 文件夹 → 项目 +- 搜索 → 搜索 + +### 动画 + +| 名称 | 效果 | 用途 | +|------|------|------| +| `animate-pulse-dot` | 脉冲闪烁 | 运行中会话指示 | +| `animate-shimmer` | 闪烁光标 | 流式输出光标 | +| slide-in / fade-in | 滑入淡入 | Toast 通知 | + +### 通知系统(Toast) + +**文件位置**:`desktop/src/components/shared/Toast.tsx` + +右下角固定位置的通知组件: + +``` + ┌──────────────────────────┐ + │ ✅ 提供商连接测试成功 ×│ + │ 所有模型可用 │ + └──────────────────────────┘ +``` + +四种类型: + +| 类型 | 左边框色 | 场景 | +|------|----------|------| +| success | 绿色 | 操作成功 | +| error | 红色 | 操作失败 | +| warning | 黄色 | 警告提示 | +| info | 蓝色 | 信息通知 | + +- 自动消失(可配置时长) +- 点击 × 手动关闭 +- 从右侧滑入动画 + +--- + +## 十、国际化 + +**文件位置**:`desktop/src/i18n/` + +### 支持语言 + +- **en** — English +- **zh** — 简体中文 + +### 使用方式 + +```typescript +// 在 React 组件中 +const t = useTranslation() +return + +// 支持参数插值 +t('chat.tokenCount', { count: 1200 }) +``` + +### 翻译 Key 体系 + +| 命名空间 | 示例 | 说明 | +|----------|------|------| +| `common.*` | save, cancel, delete | 通用词汇 | +| `sidebar.*` | newSession, search | 侧边栏 | +| `chat.*` | sendMessage, thinking | 聊天 | +| `settings.*` | providers, permissions | 设置 | +| `status.*` | connected, error | 状态 | +| `titlebar.*` | appName | 标题栏 | + +### 切换语言 + +在设置 → 通用 中切换语言,设置保存到 `localStorage`,即时生效。 + +--- + +## 十一、快速参考 + +### 组件清单 + +| 组件 | 路径 | 职责 | +|------|------|------| +| AppShell | `components/layout/AppShell.tsx` | 应用根容器、初始化 | +| Sidebar | `components/layout/Sidebar.tsx` | 侧边栏导航 | +| TabBar | `components/layout/TabBar.tsx` | 标签页管理 | +| ContentRouter | `components/layout/ContentRouter.tsx` | 页面路由 | +| StatusBar | `components/layout/StatusBar.tsx` | 状态栏 | +| ChatInput | `components/chat/ChatInput.tsx` | 消息输入 | +| MessageList | `components/chat/MessageList.tsx` | 消息列表 | +| ToolCallBlock | `components/chat/ToolCallBlock.tsx` | 工具调用展示 | +| CodeViewer | `components/chat/CodeViewer.tsx` | 代码高亮 | +| DiffViewer | `components/chat/DiffViewer.tsx` | Diff 展示 | +| PermissionDialog | `components/chat/PermissionDialog.tsx` | 权限审批 | +| ModelSelector | `components/controls/ModelSelector.tsx` | 模型选择 | +| Toast | `components/shared/Toast.tsx` | 通知系统 | + +### Store 清单 + +| Store | 路径 | 核心状态 | +|-------|------|----------| +| chatStore | `stores/chatStore.ts` | messages, chatState, streamingText | +| sessionStore | `stores/sessionStore.ts` | sessions, activeSessionId | +| tabStore | `stores/tabStore.ts` | tabs, activeTabId, tabOrder | +| settingsStore | `stores/settingsStore.ts` | model, permissionMode, language | +| providerStore | `stores/providerStore.ts` | providers, activeProvider | +| uiStore | `stores/uiStore.ts` | theme, toasts, modals | +| taskStore | `stores/taskStore.ts` | tasks, runs | +| teamStore | `stores/teamStore.ts` | teams, members | + +### API 客户端清单 + +| 模块 | 路径 | 职责 | +|------|------|------| +| client | `api/client.ts` | HTTP 基础客户端 | +| websocket | `api/websocket.ts` | WebSocket 管理器 | +| sessions | `api/sessions.ts` | 会话 CRUD | +| providers | `api/providers.ts` | 提供商管理 | +| models | `api/models.ts` | 模型操作 | +| tasks | `api/tasks.ts` | 定时任务 | +| teams | `api/teams.ts` | Agent 团队 | +| agents | `api/agents.ts` | Agent 定义 | +| skills | `api/skills.ts` | 技能查询 | +| adapters | `api/adapters.ts` | 适配器配置 | +| search | `api/search.ts` | 搜索 | +| filesystem | `api/filesystem.ts` | 文件系统 | diff --git a/docs/desktop/images/01-desktop-overview.png b/docs/desktop/images/01-desktop-overview.png new file mode 100644 index 00000000..f0a93577 Binary files /dev/null and b/docs/desktop/images/01-desktop-overview.png differ diff --git a/docs/desktop/images/02-tech-stack.png b/docs/desktop/images/02-tech-stack.png new file mode 100644 index 00000000..41b943da Binary files /dev/null and b/docs/desktop/images/02-tech-stack.png differ diff --git a/docs/desktop/images/03-three-layer-arch.png b/docs/desktop/images/03-three-layer-arch.png new file mode 100644 index 00000000..0ac37d85 Binary files /dev/null and b/docs/desktop/images/03-three-layer-arch.png differ diff --git a/docs/desktop/images/04-websocket-protocol.png b/docs/desktop/images/04-websocket-protocol.png new file mode 100644 index 00000000..035c691b Binary files /dev/null and b/docs/desktop/images/04-websocket-protocol.png differ diff --git a/docs/desktop/images/05-session-lifecycle.png b/docs/desktop/images/05-session-lifecycle.png new file mode 100644 index 00000000..4836df3f Binary files /dev/null and b/docs/desktop/images/05-session-lifecycle.png differ diff --git a/docs/desktop/images/06-features-grid.png b/docs/desktop/images/06-features-grid.png new file mode 100644 index 00000000..95b04a38 Binary files /dev/null and b/docs/desktop/images/06-features-grid.png differ diff --git a/docs/desktop/images/07-adapter-bridge.png b/docs/desktop/images/07-adapter-bridge.png new file mode 100644 index 00000000..b474cf9f Binary files /dev/null and b/docs/desktop/images/07-adapter-bridge.png differ diff --git a/docs/desktop/images/08-chat-message-flow.png b/docs/desktop/images/08-chat-message-flow.png new file mode 100644 index 00000000..4ca10476 Binary files /dev/null and b/docs/desktop/images/08-chat-message-flow.png differ diff --git a/docs/desktop/index.md b/docs/desktop/index.md new file mode 100644 index 00000000..ab69eed3 --- /dev/null +++ b/docs/desktop/index.md @@ -0,0 +1,119 @@ +# Claude Code 桌面端文档 + +> 图形化的 AI Code Editor,支持多会话、多标签、外部 UI 接入的完整桌面体验。 + +--- + +## 文档目录 + +### [01-quick-start.md](./01-quick-start.md) — 快速上手 + +面向用户的桌面端使用指南,涵盖: + +- **启动与界面**:首次运行、界面布局、主题切换 +- **对话操作**:新建会话、发送消息、附件上传、斜杠命令 +- **多标签系统**:标签切换、拖拽排序、关闭策略 +- **权限控制**:四种权限模式、工具审批流程 +- **项目管理**:工作目录关联、项目筛选、Git 信息展示 +- **模型与提供商**:模型切换、自定义 Provider、连接测试 +- **IM 适配器**:Telegram / 飞书接入、用户配对 +- **定时任务**:Cron 任务创建、运行历史查看 + +**适合人群**:所有桌面端用户 + +--- + +### [02-architecture.md](./02-architecture.md) — 架构设计 + +面向开发者的技术架构解析,涵盖: + +- **技术栈总览**:Tauri 2 + React 18 + Zustand + Vite + Tailwind CSS 4 +- **三层架构**:Tauri Shell → Express Server → CLI 子进程 +- **通信协议**:WebSocket 消息格式、HTTP API 端点、流式输出机制 +- **状态管理**:Zustand Store 设计、数据流向、持久化策略 +- **会话生命周期**:创建 → 连接 → 交互 → 断开 → 恢复 +- **代理层**:多协议转换(Anthropic / OpenAI)、Provider 管理 +- **适配器桥接**:外部 IM 平台的 WebSocket 接入架构 + +**适合人群**:贡献者、架构师、想接入自定义 UI 的开发者 + +--- + +### [03-features.md](./03-features.md) — 功能详解 + +深入解析桌面端每个功能模块,涵盖: + +- **聊天引擎**:消息类型、流式渲染、代码高亮、Diff 展示、思考块 +- **工具调用系统**:权限请求卡片、Tool 输入/输出展示、Bash 终端模拟 +- **Agent Teams**:团队视图、成员状态、转录查看 +- **技能与 Agent 定义**:技能浏览、Agent 配置、自定义扩展 +- **定时任务**:Cron 编辑器、Day-of-Week 选择、运行日志 +- **国际化**:中英文切换、翻译 Key 体系 +- **键盘快捷键**:全局快捷键、输入框快捷操作 + +**适合人群**:想充分利用桌面端功能的高级用户和开发者 + +--- + +## 配图说明 + +所有配图采用深色背景(#1a1a2e)+ Anthropic 品牌橙铜色(#D97757)风格,与项目文档视觉语言一致。 + +| 图片 | 说明 | 所属文档 | +|------|------|----------| +| `01-desktop-overview.png` | 桌面端界面总览 — 布局与核心区域 | 快速上手 | +| `02-tech-stack.png` | 技术栈全景 — 框架与工具链 | 架构设计 | +| `03-three-layer-arch.png` | 三层架构图 — Tauri / Server / CLI | 架构设计 | +| `04-websocket-protocol.png` | WebSocket 通信协议 — 消息类型与流向 | 架构设计 | +| `05-session-lifecycle.png` | 会话生命周期 — 创建到恢复的完整流程 | 架构设计 | +| `06-features-grid.png` | 功能全景图 — 核心功能模块一览 | 功能详解 | +| `07-adapter-bridge.png` | 适配器桥接 — 外部 IM 平台接入架构 | 功能详解 | +| `08-chat-message-flow.png` | 聊天消息流 — 从输入到渲染的数据流 | 功能详解 | + +--- + +## 快速开始 + +### 用户 + +1. 阅读 [快速上手](./01-quick-start.md) +2. 了解界面布局和基本操作 +3. 配置 AI 模型提供商 +4. 开始你的第一次对话 + +### 开发者 + +1. 阅读 [架构设计](./02-architecture.md) +2. 查看源码位置: + - `desktop/src/` — React 前端代码 + - `desktop/src-tauri/` — Tauri Rust 后端 + - `desktop/sidecars/` — Sidecar 启动器 + - `src/server/` — Express API 服务端 + - `adapters/` — 外部 IM 适配器 +3. 理解三层架构和 WebSocket 通信协议 + +--- + +## 核心概念速查 + +| 概念 | 说明 | +|------|------| +| **Tauri** | 轻量级跨平台桌面框架,用 Rust 管理窗口和 Sidecar 进程 | +| **Sidecar** | 随 Tauri 主进程启动的后台服务,运行 Express API 服务器 | +| **Session** | 一次对话会话,绑定工作目录,通过 WebSocket 通信 | +| **Tab** | 标签页,一个 Tab 对应一个 Session 或特殊页面(设置、任务) | +| **Provider** | AI 模型提供商,支持 Anthropic、OpenAI 兼容等多种接口 | +| **Adapter** | 外部 IM 适配器,让 Telegram / 飞书等平台接入 Claude Code | +| **Pairing** | 配对机制,6 位安全码授权外部 IM 用户访问 | +| **Store** | Zustand 状态容器,管理聊天、会话、设置等状态 | +| **Slash Command** | 斜杠命令,`/commit`、`/review-pr` 等快捷操作 | + +--- + +## 相关资源 + +- [Claude Code Haha 主页](/) +- [多 Agent 系统文档](/agent/) +- [记忆系统文档](/memory/) +- [Skills 系统文档](/skills/) +- [GitHub Issues](https://github.com/NanmiCoder/cc-haha/issues)