cc-haha/docs/ui-clone/03-server-architecture.md
程序员阿江(Relakkes) 0c6d2754b4 feat: add Desktop UI backend server with full REST API and WebSocket support
Add complete server-side implementation for the Claude Code Desktop App UI:

- REST API: sessions, conversations, settings, models, scheduled tasks,
  search, agents, and status endpoints (9 modules, 30+ endpoints)
- WebSocket: real-time chat streaming with state transitions, ping/pong,
  permission request forwarding, and stop generation support
- Services: sessionService (JSONL read/write, CLI-compatible),
  settingsService (atomic writes), cronService, searchService (ripgrep),
  agentService (YAML management)
- Middleware: CORS (localhost-only), auth, unified error handling
- Tests: 180 tests (unit + E2E + business flow), all passing
- Docs: PRD, UI design spec, server architecture design

Non-invasive: all new code under src/server/, no changes to existing CLI code.
CLI/UI data interop: reads/writes the same JSONL/JSON files as the CLI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 13:23:44 +08:00

9.7 KiB
Raw Blame History

Claude Code Desktop App — 服务端架构设计

一、设计原则

  1. 非侵入性: 不修改现有 CLI 源代码,在 src/server/ 下新建服务层
  2. 数据一致性: 读写与 CLI 完全相同的文件JSONL 会话、JSON 设置、Cron 任务)
  3. CLI/UI 互通: UI 的操作落盘到 CLI 的文件系统CLI 的会话在 UI 可见
  4. 渐进式: 先实现核心 API再扩展高级功能

二、技术栈

技术 理由
HTTP Server Bun.serve() 原项目已用 Bun零额外依赖
WebSocket Bun 原生 WebSocket 已有 ws 依赖Bun 原生更高效
验证 Zod v4 已在依赖中
测试 bun:test Bun 内置,无需额外依赖
API 风格 REST + WebSocket REST 用于 CRUDWS 用于流式传输

三、目录结构

src/server/
├── index.ts                    # 服务器入口
├── router.ts                   # 路由注册
├── middleware/
│   ├── auth.ts                 # API Key 鉴权
│   ├── cors.ts                 # CORS 处理
│   └── errorHandler.ts         # 统一错误处理
├── api/
│   ├── sessions.ts             # 会话管理 API
│   ├── conversations.ts        # 对话/消息 API
│   ├── settings.ts             # 设置 API
│   ├── models.ts               # 模型选择 API
│   ├── scheduled-tasks.ts      # 定时任务 API
│   ├── search.ts               # 搜索 API
│   ├── agents.ts               # Agent 管理 API
│   ├── mcp.ts                  # MCP 服务器管理 API
│   └── status.ts               # 状态与诊断 API
├── ws/
│   ├── handler.ts              # WebSocket 连接管理
│   ├── chatStream.ts           # 对话流式传输
│   └── events.ts               # 事件类型定义
├── services/
│   ├── sessionService.ts       # 会话服务(封装 sessionStorage
│   ├── conversationService.ts  # 对话服务(封装 query engine
│   ├── settingsService.ts      # 设置服务(封装 settings
│   ├── cronService.ts          # 定时任务服务(封装 cronTasks
│   ├── searchService.ts        # 搜索服务(封装 ripgrep
│   ├── agentService.ts         # Agent 服务
│   └── mcpService.ts           # MCP 服务
└── __tests__/
    ├── sessions.test.ts
    ├── conversations.test.ts
    ├── settings.test.ts
    ├── scheduled-tasks.test.ts
    ├── search.test.ts
    └── e2e/
        └── full-flow.test.ts

四、API 设计

4.1 会话管理 (Sessions)

方法 路径 描述
GET /api/sessions 获取会话列表(支持分页、项目过滤)
GET /api/sessions/:id 获取会话详情(标题、消息数、时间)
POST /api/sessions 创建新会话
DELETE /api/sessions/:id 删除会话
PATCH /api/sessions/:id 更新会话(重命名)
GET /api/sessions/:id/messages 获取会话消息历史

数据来源: ~/.claude/projects/{proj}/{sid}.jsonl (JSONL 格式)

实现要点:

  • 调用 loadMessageLogs() 获取会话列表
  • 调用 loadTranscriptFile() 解析 JSONL 消息
  • 使用 getProjectDir() 定位项目目录
  • 会话 ID 为 UUID v4

4.2 对话 (Conversations)

方法 路径 描述
POST /api/sessions/:id/chat 发送消息(返回任务 ID
GET /api/sessions/:id/chat/status 获取对话状态
POST /api/sessions/:id/chat/stop 停止生成

WebSocket: ws://host:port/ws/chat/:sessionId

  • 发送消息 → 流式接收 AI 回复
  • 实时推送工具调用进度
  • 权限请求转发给前端

WebSocket 消息格式:

// 客户端 → 服务器
type ClientMessage =
  | { type: 'user_message'; content: string; attachments?: Attachment[] }
  | { type: 'permission_response'; requestId: string; allowed: boolean }
  | { type: 'stop_generation' }

// 服务器 → 客户端
type ServerMessage =
  | { type: 'content_start'; blockType: 'text' | 'tool_use' }
  | { type: 'content_delta'; text?: string; toolInput?: string }
  | { type: 'tool_use_complete'; toolName: string; toolUseId: string }
  | { type: 'tool_result'; toolUseId: string; content: any; isError: boolean }
  | { type: 'permission_request'; requestId: string; toolName: string; input: any }
  | { type: 'message_complete'; usage: Usage }
  | { type: 'error'; message: string; code: string }
  | { type: 'status'; state: 'thinking' | 'tool_executing' | 'idle' }

4.3 设置 (Settings)

方法 路径 描述
GET /api/settings 获取合并后的设置
GET /api/settings/user 获取用户级设置
GET /api/settings/project 获取项目级设置
PUT /api/settings/user 更新用户级设置
PUT /api/settings/project 更新项目级设置
GET /api/permissions/mode 获取当前权限模式
PUT /api/permissions/mode 切换权限模式

数据来源: ~/.claude/settings.json + .claude/settings.json

4.4 模型 (Models)

方法 路径 描述
GET /api/models 获取可用模型列表
GET /api/models/current 获取当前选中模型
PUT /api/models/current 切换模型
GET /api/effort 获取当前 Effort 等级
PUT /api/effort 设置 Effort 等级

4.5 定时任务 (Scheduled Tasks)

方法 路径 描述
GET /api/scheduled-tasks 获取定时任务列表
POST /api/scheduled-tasks 创建定时任务
PUT /api/scheduled-tasks/:id 更新定时任务
DELETE /api/scheduled-tasks/:id 删除定时任务

数据来源: .claude/scheduled_tasks.json

方法 路径 描述
POST /api/search 全局搜索ripgrep
POST /api/search/sessions 搜索会话历史

4.7 Agent 管理

方法 路径 描述
GET /api/agents 获取 Agent 定义列表
GET /api/agents/:name 获取 Agent 详情
POST /api/agents 创建 Agent 定义
PUT /api/agents/:name 更新 Agent 定义
DELETE /api/agents/:name 删除 Agent 定义
GET /api/tasks 获取后台任务列表
GET /api/tasks/:id 获取任务详情

4.8 MCP 服务器管理

方法 路径 描述
GET /api/mcp/servers 获取 MCP 服务器列表
POST /api/mcp/servers 添加 MCP 服务器
DELETE /api/mcp/servers/:name 移除 MCP 服务器
GET /api/mcp/tools 获取 MCP 工具列表

4.9 状态与诊断

方法 路径 描述
GET /api/status 服务器状态(健康检查)
GET /api/status/diagnostics 系统诊断信息
GET /api/status/usage Token 用量统计
GET /api/status/user 用户信息

五、服务层设计

每个 Service 封装对现有工具函数的调用,提供统一的错误处理和数据转换:

// 示例: SessionService
class SessionService {
  // 列出所有会话
  async listSessions(options: { project?: string; limit?: number; offset?: number }): Promise<SessionListResponse>
  
  // 获取会话消息
  async getSessionMessages(sessionId: string): Promise<Message[]>
  
  // 创建新会话
  async createSession(workDir: string): Promise<SessionInfo>
  
  // 删除会话
  async deleteSession(sessionId: string): Promise<void>
  
  // 重命名会话
  async renameSession(sessionId: string, title: string): Promise<void>
}

关键实现:

  • SessionService 调用 loadMessageLogs()loadTranscriptFile()
  • SettingsService 调用 getSettings()updateSettingsForSource()
  • CronService 调用 readCronTasks()writeCronTasks()
  • SearchService 调用 ripgrep 流式搜索
  • ConversationService 使用 queryModelWithStreaming() + StreamingToolExecutor

六、WebSocket 协议

连接流程

1. 客户端连接: ws://host:port/ws/chat/{sessionId}
   Headers: Authorization: Bearer {apiKey}

2. 服务器确认: { type: 'connected', sessionId: '...' }

3. 客户端发送消息: { type: 'user_message', content: '...' }

4. 服务器流式响应:
   { type: 'status', state: 'thinking' }
   { type: 'content_start', blockType: 'text' }
   { type: 'content_delta', text: 'Let me...' }
   { type: 'content_delta', text: ' help you...' }
   { type: 'content_start', blockType: 'tool_use', toolName: 'Bash' }
   { type: 'tool_use_complete', toolName: 'Bash', toolUseId: '...' }
   { type: 'permission_request', requestId: '...', toolName: 'Bash', input: {...} }
   
5. 客户端批准: { type: 'permission_response', requestId: '...', allowed: true }

6. 服务器继续:
   { type: 'tool_result', toolUseId: '...', content: '...', isError: false }
   { type: 'content_delta', text: 'Done!' }
   { type: 'message_complete', usage: { input_tokens: 1000, output_tokens: 500 } }
   { type: 'status', state: 'idle' }

七、鉴权方案

  • 本地运行: 简单 API Key 验证(从 .env 读取)
  • Header: Authorization: Bearer {ANTHROPIC_API_KEY}
  • WebSocket: 首次连接时通过 URL query 或首条消息验证
  • 不做复杂的用户系统,依赖 Anthropic API Key 鉴权

八、测试策略

单元测试

  • 每个 Service 独立测试
  • Mock 文件系统操作
  • 验证输入输出格式

集成测试

  • 启动测试服务器
  • 发送 HTTP 请求验证响应
  • WebSocket 连接和消息流测试

E2E 测试

  • 完整对话流程(创建会话 → 发消息 → 收回复 → 停止 → 查看历史)
  • 定时任务 CRUD
  • 设置读写
  • 搜索功能