Happy 项目架构设计与技术实现

一、背景与目标

1. 项目背景

A. 业务场景

Happy 是一个开源的 AI 编程助手生态系统,允许用户从任何设备(手机、平板、电脑)远程控制运行在本地机器上的 AI 编程代理。该项目解决了传统 AI 编程工具受限于桌面环境的问题,实现了真正的"随时随地编码"体验。

该生态系统由三个独立但紧密协作的组件组成:

  • happy:React Native 跨平台客户端,支持 iOS、Android 和 Web
  • happy-cli:命令行工具,作为 AI 代理(Claude、Gemini、Codex)的包装器
  • happy-server:后端同步服务,提供消息中继和用户认证

B. 痛点分析

传统 AI 编程助手存在以下限制:

  • 平台限制:必须在桌面环境使用,移动设备无法参与
  • 数据隐私:代码需要上传到云端服务器,存在泄露风险
  • 订阅费用:商业 AI 编程工具通常需要付费订阅
  • 离线限制:依赖网络连接,无法在离线环境使用

Happy 通过以下设计解决上述问题:

  • AI 代理运行在用户控制的硬件上,完全本地化
  • 端到端加密确保代码隐私,服务器无法解密
  • 开源免费,使用用户自己的硬件和 API 配额
  • 支持离线操作,同步网络恢复后自动合并

2. 设计目标

A. 功能目标

  • 多平台客户端覆盖(iOS、Android、Web、macOS Desktop)
  • 支持多种 AI 代理后端(Claude Code、Gemini、Codex)
  • 实时会话同步和消息推送
  • 端到端加密的代码存储
  • 实时语音交互(实验功能)

B. 非功能目标

  • 性能指标:WebSocket 延迟 < 100ms,消息同步 < 500ms
  • 可用性:99.5% 以上(客户端依赖用户网络)
  • 扩展性:支持水平扩展的服务器架构
  • 安全性:端到端加密、零知识架构、公钥认证

二、总体设计

1. 设计原则

  • 零知识架构:服务器存储加密数据但无法解密
  • 端到端加密:所有敏感数据使用客户端派生的密钥加密
  • 用户控制:AI 代理运行在用户硬件上,而非云端
  • 开源透明:所有组件开源,代码可审计
  • 跨平台优先:使用 React Native 实现多平台复用

2. 系统架构

graph TB
    subgraph 客户端层
        Mobile[移动端 Client<br/>React Native]
        Web[Web Client<br/>React Native Web]
        Desktop[Desktop Client<br/>Tauri]
    end

    subgraph CLI层
        CLI[happy-cli<br/>命令行工具]
        Claude[Claude Code SDK]
        Gemini[Gemini ACP]
        Codex[Codex MCP]
    end

    subgraph 服务器层
        Server[Happy Server<br/>TypeScript + Fastify]
        Socket[Socket.IO<br/>WebSocket]
        API[HTTP REST API]
        Auth[认证模块]
    end

    subgraph 存储层
        PG[(PostgreSQL<br/>关系数据)]
        Redis[(Redis<br/>缓存/PubSub)]
        MinIO[(MinIO<br/>对象存储)]
    end

    Mobile <--> Server
    Web <--> Server
    Desktop <--> Server

    CLI <--> Server

    Server --> Socket
    Server --> API
    Server --> Auth

    Server --> PG
    Server --> Redis
    Server --> MinIO

    CLI --> Claude
    CLI --> Gemini
    CLI --> Codex

系统架构图

3. 组件说明

3.1 客户端层(happy)

  • 技术栈:React Native 0.81、Expo 54、TypeScript 5.9
  • 样式系统:Unistyles(跨平台主题和断点)
  • 路由:Expo Router v5 文件路由
  • 状态管理:React Context + 自定义 reducer
  • 实时通信:Socket.IO Client 4.8
  • 加密:TweetNaCl(Ed25519 签名)、libsodium(AES-256-GCM)

3.2 CLI 层(happy-cli)

  • 技术栈:Node.js 20、TypeScript 5、Ink(React Terminal UI)
  • AI 集成:Claude Code SDK、Gemini ACP、Codex MCP
  • 守护进程:后台服务管理多个会话
  • MCP 服务器:统一的工具接口(ripgrep、difftastic、HTTP 代理)

3.3 服务器层(happy-server)

  • 技术栈:Node.js 20、TypeScript 5.4、Fastify 5
  • 实时通信:Socket.IO 4(WebSocket)
  • 数据库:PostgreSQL 16 + Prisma 6
  • 缓存:Redis 7(PubSub 分布式支持)
  • 对象存储:MinIO(S3 兼容)

4. 交互流程

4.1 认证流程(QR 码挑战-响应)

sequenceDiagram
    participant C as 移动端
    participant S as Happy Server
    participant CLI as happy-cli

    C->>S: 请求认证 QR 码
    S-->>C: 返回包含 challenge 的 QR 码

    C->>CLI: 扫描 QR 码
    Note over CLI: 验证签名

    CLI->>S: 提交认证响应
    S-->>CLI: 返回 JWT Token
    CLI->>S: 建立 WebSocket 连接
    S-->>C: 推送会话更新

认证流程时序图

4.2 消息同步流程

sequenceDiagram
    participant U as 用户
    participant C as happy-cli
    participant S as Happy Server
    participant M as 移动端

    U->>C: 输入指令
    C->>C: AI 处理
    C->>S: 发送加密消息
    S->>S: 存储(无法解密)
    S-->>M: WebSocket 推送
    M->>M: 解密并显示

消息同步流程图

三、详细设计

1. 核心模块

A. 同步引擎(happy/sync)

位于 sources/sync/sync.ts,共 2143 行代码,是客户端的核心同步引擎。

class Sync {
    // 加密管理
    encryption!: Encryption;
    encryptionCache = new EncryptionCache();

    // 同步锁(防重复请求)
    sessionsSync: InvalidateSync;
    messagesSync: Map<string, InvalidateSync>;
    settingsSync: InvalidateSync;

    // 加密密钥存储
    sessionDataKeys: Map<string, Uint8Array>;
    machineDataKeys: Map<string, Uint8Array>;
    artifactDataKeys: Map<string, Uint8Array>;

    // 主要方法
    async create(credentials, encryption)
    async restore(credentials, encryption)
    onSessionVisible(sessionId)
    subscribeToUpdates()
}

InvalidateSync 模式:防重复请求的同步锁,确保同一资源不会同时发起多个同步请求。

B. 消息归约器(happy/sync/reducer)

处理来自 WebSocket 的原始消息,分为五个阶段:

  • Phase 0:处理 AgentState 权限请求
  • Phase 0.5:消息到事件转换
  • Phase 1:处理用户和文本消息
  • Phase 2:处理工具调用
  • Phase 3:处理工具结果
  • Phase 4:处理侧链消息
  • Phase 5:处理模式切换事件

C. Agent Backend 抽象(happy-cli)

统一的 AI 代理接口,支持多种后端:

interface AgentBackend {
    startSession(initialPrompt?: string): Promise<StartSessionResult>
    stop(): Promise<void>
    sendPrompt(sessionId, prompt): Promise<void>
    cancel(sessionId): Promise<void>
    onMessage(handler: (message: AgentMessage) => void): void
    respondToPermission?(requestId: string, approved: boolean): Promise<void>
    dispose(): Promise<void>
}

D. 事件路由器(happy-server)

管理三种连接类型的事件分发:

type ClientConnection =
    | SessionScopedConnection    // { userId, sessionId }
    | UserScopedConnection       // { userId }
    | MachineScopedConnection;   // { userId, machineId }

2. 关键流程

A. 正常会话创建流程

flowchart TD
    A[CLI 启动] --> B[生成 Ed25519 密钥对]
    B --> C[创建认证请求]
    C --> D[显示 QR 码]
    D --> E[移动端扫码]
    E --> F{签名验证}
    F -->|成功| G[交换 Token]
    F -->|失败| H[返回错误]
    G --> I[建立 WebSocket]
    I --> J[创建会话]
    J --> K[开始同步]

会话创建流程图

B. 端到端加密流程

flowchart LR
    A[用户生成密钥对] --> B[公钥注册到服务器]
    B --> C[派生会话密钥 HKDF]
    C --> D[AES-256-GCM 加密数据]
    D --> E[服务器存储加密数据]
    E --> F[客户端私钥解密]

加密流程图

3. 数据存储

A. 数据模型(happy-server)

模型描述加密方式
Account用户账户,公钥认证信息明文
Session用户会话,多设备同步元数据明文,内容加密
Machine设备注册和状态管理明文
SessionMessage会话消息端到端加密
Artifact加密的文件对象Header 和 Body 分别加密
AccessKey访问密钥管理明文
UserRelationship用户社交关系明文
UserKVStore用户键值存储加密
UserFeedItem用户消息流加密

B. 缓存策略

  • 令牌缓存:认证令牌永久缓存
  • 加密缓存:EncryptionCache 缓存派生密钥
  • 消息去重:使用 Set 防止重复处理
  • 状态缓存:InvalidateSync 模式防止重复请求

四、技术选型

1. 技术栈

A. 前端技术

技术版本用途选择理由
React Native0.81跨平台框架生态成熟,代码复用率高
Expo54开发工具链降低原生开发门槛
Unistyles3.0样式系统主题和断点支持完善
Socket.IO4.8WebSocket 客户端自动重连,事件驱动
React Navigation6路由导航Expo Router 深度集成

B. 后端技术

技术版本用途选择理由
Node.js20运行时与前端技术栈统一
TypeScript5.4开发语言类型安全,代码可维护
Fastify5Web 框架高性能,插件生态完善
Prisma6ORM类型安全,迁移管理方便
Socket.IO4WebSocket 服务与客户端协议一致

C. 基础设施

技术版本用途选择理由
PostgreSQL16关系数据库ACID 支持,JSON 类型
Redis7缓存和 PubSub高性能,分布式支持
MinIO最新对象存储S3 兼容,可私有部署
Docker最新容器化环境一致性,部署方便

2. 选型对比

A. 客户端框架

方案优点缺点选择
React Native生态成熟,代码复用高性能略逊于原生✅ 选择
Flutter性能好,UI 一致学习曲线陡峭
原生开发性能最佳开发成本高,维护困难

B. 后端框架

方案优点缺点选择
Fastify高性能,类型安全生态不如 Express✅ 选择
Express生态成熟性能一般,类型支持弱
NestJS功能完善过度设计,学习曲线陡

C. 数据库

方案优点缺点选择
PostgreSQL功能强大,JSON 支持资源占用较高✅ 选择
MySQL成熟稳定JSON 支持较弱
MongoDB灵活,Schema 自由事务支持弱

五、部署架构

1. 部署图

graph LR
    LB[负载均衡<br/>Nginx] --> App1[App 实例 1<br/>:3005]
    LB --> App2[App 实例 2<br/>:3005]

    App1 --> PG[(PostgreSQL<br/>主从)]
    App2 --> PG

    App1 --> Redis[(Redis<br/>哨兵模式)]
    App2 --> Redis

    App1 --> MinIO[(MinIO<br/>分布式)]
    App2 --> MinIO

    Redis -.PubSub.-> Redis

部署架构图

2. 容量规划

组件配置实例数总资源
App 服务器4 核 8G312 核 24G
PostgreSQL8 核 32G2(主从)16 核 64G
Redis4 核 16G3(哨兵)12 核 48G
MinIO8 核 32G4(分布式)32 核 128G

3. 高可用设计

  • 应用层:多实例部署,负载均衡
  • 数据库:主从复制,自动故障转移
  • 缓存:Redis 哨兵模式,自动选主
  • 对象存储:MinIO 分布式模式,纠删码

4. 降级熔断

  • 服务降级:非核心功能(推送通知)可降级
  • 熔断策略:错误率超过 5% 触发熔断
  • 限流保护:每用户每分钟 100 次请求

六、安全设计

1. 认证授权

A. 公钥认证

使用 Ed25519 签名验证,无需密码:

// 1. 客户端生成密钥对
const keyPair = nacl.sign.keyPair();

// 2. 创建签名挑战
const challenge = randomBytes(32);
const signature = nacl.sign.detached(challenge, keyPair.secretKey);

// 3. 服务器验证签名
const isValid = nacl.sign.detached.verify(
    challenge,
    signature,
    publicKey
);

B. JWT Token

认证成功后颁发 JWT Token:

// 持久令牌(用户认证)
async createToken(userId: string, extras?: any): Promise<string>

// 临时令牌(OAuth,5 分钟 TTL)
async createGithubToken(userId: string): Promise<string>

2. 数据加密

A. 端到端加密

  • 密钥派生:使用 HKDF 从主密钥派生会话密钥
  • 加密算法:AES-256-GCM
  • 密钥存储:客户端本地安全存储
// 派生会话密钥
async deriveSessionKey(sessionId: string): Promise<Uint8Array> {
    const info = new TextEncoder().encode(`session:${sessionId}`);
    return hkdf(this.keyPair.secretKey, info, 32);
}

// 加密数据
encryptSessionData(data: string, key: Uint8Array): string {
    const nonce = randomBytes(12);
    const cipher = aes_gcm_encrypt(data, key, nonce);
    return base64Encode(nonce + cipher);
}

B. 加密范围

  • 会话消息:完全加密
  • 工件文件:Header 和 Body 分别加密
  • 用户设置:敏感字段加密
  • 键值存储:根据需求加密

3. 防护措施

  • 重放攻击防护:挑战-响应机制,随机 Nonce
  • 中间人攻击防护:HTTPS + 证书固定
  • SQL 注入防护:Prisma 参数化查询
  • XSS 防护:React 自动转义,Content Security Policy

七、监控告警

1. 监控指标

通过 Prometheus 收集以下指标:

A. 应用指标

  • HTTP 请求总数和耗时
  • WebSocket 连接数和事件数
  • 数据库活跃连接数
  • Redis 命令总数和耗时

B. 业务指标

  • 活跃会话数
  • 消息吞吐量
  • 认证成功率
  • 推送通知送达率

2. 告警规则

指标阈值级别处理建议
错误率> 5%P2检查日志,定位错误源
响应时间 P99> 1sP3检查数据库慢查询
WebSocket 断线> 10%P2检查网络和负载均衡
数据库连接> 80%P1扩容连接池或数据库

3. 日志规范

  • 日志级别:DEBUG、INFO、WARN、ERROR
  • 结构化日志:JSON 格式,包含 request_id
  • 敏感信息:自动脱敏,不记录密钥和 Token

八、技术亮点

1. 零知识架构

服务器只存储加密数据,即使服务器被攻破也无法获取用户代码内容。这是通过客户端派生密钥并仅在客户端加密解密实现的。

2. InvalidateSync 模式

class InvalidateSync {
    private invalidated = true;
    private promise: Promise<void> | null = null;

    invalidate(): void {
        this.invalidated = true;
    }

    async awaitQueue(): Promise<void> {
        while (this.invalidated) {
            this.invalidated = false;
            this.promise = this.sync();
            await this.promise;
        }
    }

    async get(): Promise<T> {
        await this.awaitQueue();
        return this.cache;
    }
}

该模式确保:

  • 同一资源不会同时发起多个同步请求
  • 数据更新时自动重新同步
  • 缓存失效后自动刷新

3. 多 AI 代理支持

通过统一的 AgentBackend 接口,支持多种 AI 编程代理:

  • Claude Code:使用官方 SDK 直接集成
  • Gemini:通过 Agent Client Protocol (ACP)
  • Codex:通过 MCP stdio 协议

用户可通过命令轻松切换:

happy              # 默认使用 Claude
happy gemini       # 使用 Gemini
happy codex        # 使用 Codex

4. 跨平台样式系统

使用 Unistyles 实现真正的跨平台样式:

const styles = StyleSheet.create((theme, runtime) => ({
    container: {
        flex: 1,
        backgroundColor: theme.colors.background,
        paddingTop: runtime.insets.top,  // 自动处理安全区域
    },
    responsive: {
        padding: theme.margins.sm,
        backgroundColor: {
            [mq.only.width(0, 768)]: theme.colors.mobile,
            [mq.only.width(768)]: theme.colors.desktop,
        }
    }
}));

九、项目规模

1. 代码统计

项目文件数代码行数主要语言
happy407~50,000TypeScript/TSX
happy-cli150+~20,000TypeScript
happy-server100+~15,000TypeScript

2. 核心文件

文件行数说明
sync/sync.ts2,143主同步引擎
sync/storage.ts53,952本地状态管理
sync/typesRaw.ts31,563消息类型定义
sync/settings.ts17,825设置管理

十、未来规划

1. 短期计划

  • 完善实时语音交互功能
  • 支持更多 AI 代理后端
  • 优化消息同步性能
  • 增加 GitHub 集成

2. 长期愿景

  • 支持团队协作功能
  • 插件系统扩展能力
  • 本地 LLM 支持
  • 更多平台支持(Windows Desktop)

参考资料

  1. Happy - GitHub Repository
  2. happy-cli - GitHub Repository
  3. happy-server - GitHub Repository
  4. Expo Documentation
  5. Socket.IO Documentation
最后修改:2026 年 01 月 19 日
如果觉得我的文章对你有用,请随意赞赏