【免费下载链接】happier
Web, Desktop & Mobile client and orchestrator for Codex, Claude Code, OpenCode, Pi, Cursor, Grok, Antigravity, Kimi, Augment Code, Qwen, fully end-to-end encrypted
Happy 是一个面向 Codex、Claude Code、OpenCode、Pi、Cursor、Grok 等编码智能体的 Web、桌面与移动端客户端和编排器,所有会话数据全程端到端加密。本文带你完整解析 Happy 的 HTTP API 端点目录、Bearer Token 签发机制,以及三种核心认证流程(密钥挑战签名、终端二维码配对、移动端批准),帮助新手快速理解它的接口设计与数据同步原理。
为什么 Happy 需要一套自己的 HTTP API?
想象一下:你在 Mac 桌面上启动了 Claude Code 会话,出门路上想用手机随时查看进度、批准权限请求。这背后的每一次"会话列表刷新""消息同步""推送唤醒",都由 Happy Server 的 HTTP 端点和 WebSocket 通道驱动。
官方 API 文档定义了完整的接口面:docs/api.md,并约定了清晰的方法语义:
| 方法 | 用途 | 示例 |
|---|---|---|
GET | 只读查询 | 列出会话、获取账户资料 |
POST | 变更或动作(即使不映射到单一实体) | 创建会话、发起认证 |
DELETE | 意图明确的删除 | 删除会话、移除访问密钥 |
Happy 有意避开了完整的 REST 动词集合,因为很多操作跨越多个实体或具有非 CRUD 语义——这一取舍在 docs/api.md 中有明确说明。
🔑 关键前提:除少数公开端点外,绝大多数接口都要求请求头携带Authorization: Bearer <token>。那么 Token 从哪来?这正是接下来三种认证流程的故事。
认证流程一:密钥挑战签名(POST /v1/auth)
这是最快的一种登录方式,也是 CLI 启动时最常用的路径。整个过程不需要密码,而是用非对称签名证明"我持有私钥":
- 客户端用 Ed25519 密钥对生成一个随机
challenge(挑战串); - 客户端用私钥签名,向服务器提交三样东西(均为 base64 字符串):
publicKey、challenge、signature; - 服务器用公钥验证签名,通过则按公钥 Upsert 账户,并返回
{ success: true, token }。
服务器端的校验逻辑非常严谨:公钥长度、签名长度、base64 合法性都会逐一检查,任何一步失败都返回401 Invalid signature。如果账户带有内容公钥(E2EE 模式),还会额外验证contentPublicKeySig的内容密钥绑定签名,防止密钥被恶意替换。
这段核心实现位于 apps/server/sources/app/api/routes/auth/registerKeyChallengeAuthRoute.ts,客户端对应的挑战生成与请求代码在 apps/cli/src/api/auth.ts。
⚠️ 小细节:如果服务器禁用了匿名注册(anonymousSignupEnabled为 false),首次登录会收到403 signup-disabled。
认证流程二:终端二维码配对(auth request)
当你在终端里运行happier auth login却不想直接暴露密钥时,就走"终端配对"流程。它分四步完成:
- 请求:终端生成一次性密钥对,调用
POST /v1/auth/request提交publicKey(可选携带supportsV2与claimSecretHash),服务器返回{ state: "requested" },并生成一个可被 App 或网页展示的配对凭证; - 查询:终端轮询
GET /v1/auth/request/status?publicKey=...,状态会在not_found/pending/authorized之间流转; - 批准:手机 App 或网页端确认后,服务端将配对响应写入该请求;
- 领取:终端再次调用
POST /v1/auth/request(或使用claimSecret调用/v1/auth/request/claim)拿到{ state: "authorized", token, response }。
这套路由实现见 apps/server/sources/app/api/routes/auth/registerTerminalAuthRequestRoutes.ts,终端侧命令逻辑在 apps/cli/src/cli/commands/auth/request.ts。几个值得注意的边界状态:
| 状态码 | 含义 |
|---|---|
409 claim_mismatch | 领取密钥不匹配,防止他人抢占授权 |
410 expired | 配对请求超时被清理 |
401 Invalid public key | 公钥格式非法 |
💡 移动端只需一次轻点,就能完成对远程终端的授权——这就是"随时随地接管编码会话"体验的底层支撑。
认证流程三:移动端批准与账户关联(auth response)
配对请求被"批准"这个动作本身,就是带认证的 HTTP 调用:
POST /v1/auth/response:Body 为{ response, publicKey },需要 Bearer Token,表示当前已登录账户同意为某个新终端签发密钥;POST /v1/auth/account/request+POST /v1/auth/account/response:用于账户关联,让同一人用不同密钥对的设备共享一个账户(实现见 apps/server/sources/app/api/routes/auth/registerAccountAuthRoutes.ts)。v2 版本更巧妙地把 Token 用一次性密钥对加密后传输,避免明文出现在响应里。
另外,还有一个轻量端点GET /v1/auth/ping(见 apps/server/sources/app/api/routes/auth/authRoutes.ts),用于在正式请求前确认"我的 Token 还有效吗"——返回{ ok: true }即代表会话凭证健康。
Bearer Token 是如何签发与校验的?
服务器并不是随手生成一个字符串。Token 由独立的privacy-kit库基于Ed25519 持久令牌签发,密钥树源自服务器环境变量HANDY_MASTER_SECRET:
- 生成与验证分别由
AuthModule内部封装,代码位于 apps/server/sources/app/auth/auth.ts; - 验证结果会进入带 TTL 的 LRU 缓存(默认 600 秒),减少高频请求下的重复验签开销;
- 账户被禁用、登录资格校验失败时,Token 会在下一次认证时被拒绝(
enforceLoginEligibility)。
也就是说,Token 本身是自包含、无状态的,服务器不需要查库即可验证大部分请求,这让 API 在断网恢复、多设备并发时依然稳定。
核心 HTTP 端点全目录
认证之后,客户端真正干活靠的是下面这些端点(完整清单以 docs/api.md 为准):
| 分组 | 代表端点 | 说明 |
|---|---|---|
| 会话 | GET /v2/sessions、POST /v1/sessions | 分页列出(游标cursor)、按tag创建或加载 |
| 消息 | GET /v1/sessions/:id/messages | 拉取会话消息(加密 Blob) |
| 机器 | POST /v1/machines、GET /v1/machines/:id | 注册/查询你这台计算机 |
| 产物 | POST /v1/artifacts | 版本化上传/更新制品 |
| 访问密钥 | GET/POST/PUT /v1/access-keys/:sessionId/:machineId | 设备间共享解密密钥 |
| KV 存储 | POST /v1/kv/bulk、GET /v1/kv?prefix=... | 加密键值同步(偏好、状态) |
| 账户与用量 | GET /v1/account/profile、POST /v1/usage/query | 资料、设置与用量查询 |
| 推送 | POST /v1/push-tokens | 注册 APNs/FCM 推送令牌 |
| 第三方连接 | POST /v1/connect/:vendor/register | 绑定 OpenAI/Anthropic/Gemini 供应商密钥 |
会话列表是移动端体验的核心:GET /v2/sessions?cursor=...&limit=...&changedSince=...支持游标分页与增量拉取,服务器端分页实现见 apps/server/sources/app/api/routes/session/registerSessionListingRoutes.ts。
HTTP 之外:WebSocket 的认证握手
静态数据走 HTTP,实时事件走 WebSocket。Happy 基于 Socket.IO,认证直接发生在握手阶段:客户端把 Token 放进socket.handshake.auth.token,可附带sessionId、machineId、clientType(user-scoped/session-scoped/machine-scoped)。服务器在连接建立时调用auth.verifyToken(token)校验,失败即断开——代码位于 apps/server/sources/app/api/socket.ts。
这意味着:同一个 Bearer Token 同时保护 HTTP API 与实时通道,客户端只需要一次认证。事件载荷(如new-message、update-session)的详细协议见 docs/protocol.md。
端到端加密如何与 API 协同?
所有敏感字段(会话元数据、消息、机器状态、KV 值、制品内容)在离开客户端前就已加密为 base64 Blob,服务器只当"不透明字符串"存储与转发,完全看不到内容。两种加密变体:
- legacy:NaCl
secretbox(XSalsa20-Poly1305),32 字节共享密钥; - dataKey:AES-256-GCM,配合每个会话/机器的独立数据密钥,密钥本身再经一次性密钥对包裹(
dataEncryptionKey字段)。
完整二进制布局与解密流程图解在 docs/encryption.md 中,客户端加密实现在 apps/cli/src/api/encryption.ts。
新手速查:常见问题
Q:调用返回 401 怎么办?通常是 Token 过期或签名校验失败。先用GET /v1/auth/ping探活,失败则重新执行happier auth login获取新 Token。
Q:会话里的消息为什么是乱码?那是 base64 加密体。只有持有对应数据密钥的客户端才能解密——这正是端到端加密的设计目标。
Q:想理解完整协议应该读哪些文件?按顺序阅读:docs/api.md(HTTP 面)→ docs/protocol.md(WebSocket 事件)→ docs/encryption.md(加密细节);路由源码统一放在 apps/server/sources/app/api/routes/ 下。
掌握这三条认证链路与端点目录后,你不仅能看懂 Happy 的每一次网络交互,也能为自建中继服务器或开发第三方客户端打下坚实基础。🚀
【免费下载链接】happier
Web, Desktop & Mobile client and orchestrator for Codex, Claude Code, OpenCode, Pi, Cursor, Grok, Antigravity, Kimi, Augment Code, Qwen, fully end-to-end encrypted
相关推荐
ClawHub HTTP API 完整参考:公开目录、CLI 认证端点与速率限制实践指南
ClawHub HTTP API 完整参考:公开目录、CLI 认证端点与速率限制实践指南 ClawHub 是 OpenClaw 生态的 Skill + Plug
后端前端AI 技能AI 插件搜索引擎OneUptime REST API 参考指南:认证、核心端点与分页机制详解
OneUptime REST API 参考指南:认证、核心端点与分页机制详解 本文是 OneUptime 官方 API 文档( App/FeatureSet/D
可观测性后端运维前端云原生微服务AI Agentbook-to-skill 完整指南:把任意技术书变成可查询的 Agent Skill
book to skill 完整指南:把任意技术书变成可查询的 Agent Skill book to skill 是一个开源转换器:把任意技术书(PDF、EP
AI 技能
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考