AtomCode Daemon API 与 LiveWire WebUI 实时协议深度分析
持续深度分析 — Daemon API 端点完整映射 + LiveWire SSE 实时协议 2026-06-23
1. Daemon API 端点全集(含 SPA 调用)
通过 WebUI 嵌入的 JavaScript (assets/index-CM83LMnS.js) 提取到的完整端点列表:
1.1 会话管理
| 方法 | 端点 | 请求体 | JS 函数 | 说明 |
|---|---|---|---|---|
| GET | /sessions | — | Pe() | 获取所有项目会话列表 |
| GET | /projects | — | Le() | 获取项目列表 |
| GET | /project | — | Re() | 获取当前项目信息 |
| GET | /projects/:hash/sessions/:id | — | Je() | 获取指定会话详情 |
| DELETE | /projects/:hash/sessions/:id | — | Ie() | 删除指定会话 |
| PATCH | /projects/:hash/sessions/:id/rename | {name: string} | Fe() | 重命名会话 |
1.2 实时通信(LiveWire SSE)
| 方法 | 端点 | 说明 |
|---|---|---|
| GET | /live | SSE 流式会话事件(实时推送) |
| POST | /live/message | 发送用户消息 |
| POST | /live/provider | 切换提供商 |
| POST | /live/permission | 响应权限请求 |
| POST | /live/reasoning_effort | 设置推理努力级别 |
1.3 权限系统
| 方法 | 端点 | 请求体 | 说明 |
|---|---|---|---|
| POST | /chat/permission | {session_id, decision, tool_name} | 工具调用权限决策 |
1.4 文件系统
| 方法 | 端点 | 请求体 | 说明 |
|---|---|---|---|
| GET | /fs/list?path= | — | 列出目录内容 |
| POST | /fs/mkdir | {path: string} | 创建目录 |
| POST | /cd | {path: string, set_default: bool} | 更改工作目录 |
1.5 配置
| 方法 | 端点 | 说明 |
|---|---|---|
| GET | /config | 获取配置 |
| POST | /config/reload | 重载配置文件 |
1.6 模型/提供商
| 方法 | 端点 | 请求体 | 说明 |
|---|---|---|---|
| GET | /models | — | 获取可用模型 |
| GET | /providers | — | 获取提供商列表 |
| POST | /providers | CreateProviderRequest | 创建提供商 |
| PATCH | /providers/:name | PatchProviderRequest | 更新提供商 |
| DELETE | /providers/:name | — | 删除提供商 |
| POST | /providers/:name/default | — | 设为默认提供商 |
| POST | /providers/:name/thinking | PatchThinkingRequest | 配置思考设置 |
1.7 认证
| 方法 | 端点 | 说明 |
|---|---|---|
| GET | /auth/status | 登录状态 |
| POST | /auth/login/start | 发起登录 |
| POST | /auth/login/:id/poll | 轮询登录结果 |
| POST | /auth/logout | 登出 |
1.8 杂项
| 方法 | 端点 | 说明 |
|---|---|---|
| GET | /skills | 获取 Skills 列表 |
| GET | /tunnel/status | Tunnel 状态(QR + URL) |
| GET | /mcp/status | MCP 服务器状态 |
| POST | /mcp/reload | 重载 MCP 配置 |
| GET | /health | 健康检查 |
| POST | /shutdown | 关闭 daemon |
2. LiveWire 实时协议(SSE 流)
2.1 连接方式
GET /live
Accept: text/event-stream
→ SSE 流(持续连接)2.2 事件推送格式
data: {JSON payload}\n\n2.3 LiveWire 事件类型
| 事件字段 | 类型 | 说明 |
|---|---|---|
running | bool | 代理是否正在运行 |
tool_start | object | 工具开始调用 |
tool_batch | object | 批量工具调用 |
tool_output | string | 工具输出文本 |
tool_result | object | 工具调用结果 |
output | string | LLM 输出文本 |
completion | object | 回合完成事件 |
reasoning | string | 推理过程 |
artifact_start | object | 产物开始 |
artifact_end | object | 产物结束 |
tool_calls | array | 工具调用序列 |
permission_request | object | 权限请求 |
stopped | bool | 会话已停止 |
error | object | 错误事件 |
2.4 客户端 JS 读取
javascript
async function Ye(e, t, n) {
let r = n ? `?session_id=${encodeURIComponent(n)}` : ``;
let i = await fetch(`/live${r}`, { headers: G(), signal: t });
let a = i.body.getReader();
let o = new TextDecoder();
let s = ``;
for(;;) {
let { done: t, value: n } = await a.read();
if (t) break;
s += o.decode(n, { stream: true });
let r = s.split("\n");
for (let c = 0; c < r.length - 1; c++) {
let l = r[c];
// parse "data: " prefixed JSON
}
// ...
}
}使用 Fetch API + ReadableStream(非 EventSource),支持更细粒度控制和自动重连。
3. 请求结构体全集
3.1 ChatRequest
rust
struct ChatRequest {
session_id: String, // 会话 UUID
message: String, // 用户消息
images: Vec<ImageInput>?, // 可选的图片输入
provider: String?, // 可选:指定提供商
model: String?, // 可选:指定模型
}3.2 ImageInput
rust
struct ImageInput {
media_type: String, // 图片类型 (image/png, image/jpeg)
data: String, // Base64 编码数据
}3.3 LiveMessageReq
rust
struct LiveMessageReq {
session_id: String, // 会话 UUID
message: String, // 消息内容
images: Vec<ImageInput>?, // 图片输入
provider: String?, // 提供商
model: String?, // 模型名
}3.4 LiveProviderReq
rust
struct LiveProviderReq {
provider: String, // 提供商名
}3.5 LivePermissionReq
rust
struct LivePermissionReq {
session_id: String, // 会话 UUID
decision: String, // "allow" | "block" | "modify"
tool_name: String, // 工具名
}3.6 ChangeDirRequest
rust
struct ChangeDirRequest {
path: String, // 目标路径
set_default: bool, // 设为默认工作目录
}3.7 PatchProviderRequest
rust
struct PatchProviderRequest { // 19 个字段
// 以下字段均为 Optional
name: String?,
provider_type: String?,
api_key: String?, // 清除用 clear_api_key
base_url: String?, // 清除用 clear_base_url
model: String?,
max_tokens: u64?,
thinking_budget: u64?,
thinking_type: String?,
thinking_keep: bool?,
reasoning_history: u64?,
skip_tls_verify: bool?,
set_default: bool?,
user_agent: String?,
ip: String?,
// ...
}3.8 CreateProviderRequest
rust
struct CreateProviderRequest { // 16 个字段
name: String,
provider_type: String,
api_key: String,
base_url: String?,
model: String?,
model_type: String?,
max_tokens: u64?,
thinking_budget: u64?,
thinking_type: String?,
// ...
}3.9 PatchThinkingRequest
rust
struct PatchThinkingRequest { // 6 个字段
thinking_type: String?, // "extended" | "normal" | "off"
thinking_budget: u64?,
thinking_keep: bool?,
reasoning_history: u64?,
// ...
}3.10 CodingPlanSetupRequest
rust
struct CodingPlanSetupRequest {
plan_type: String, // CodingPlan 计划类型
}3.11 PermissionDecisionRequest
rust
struct PermissionDecisionRequest {
session_id: String,
decision: String, // "allow" | "block" | "modify"
tool_name: String,
}4. API 响应结构体
4.1 AuthStatusResponse
rust
struct AuthStatusResponse {
logged_in: bool,
auth_path: String?, // 登录路径
user: UserInfo?, // 用户信息(如已登录)
}4.2 LoginStartResponse
rust
struct LoginStartResponse {
login_id: String, // 登录会话 ID
expires_in_seconds: u64, // 过期秒数
auth_url: String?, // 浏览器打开的 URL
}4.3 LoginPollResponse
rust
struct LoginPollResponse {
status: String, // "pending" | "success" | "expired" | "error"
token: TokenInfo?, // 登录成功时返回令牌
error: String?, // 错误信息
}4.4 TokenInfo
rust
struct TokenInfo {
access_token: String,
token_type: String,
expires_in: u64,
has_refresh_token: bool,
}4.5 TunnelStatus
rust
struct TunnelStatus {
bind_host: String, // 绑定地址
reachable: bool, // 是否可达
remote_url: String?, // 远程访问 URL
qr_svg: String?, // QR 码 SVG
}4.6 ConfigResponse
rust
struct ConfigResponse {
default_workdir: String?, // 默认工作目录
// ...
}4.7 ProjectInfo
rust
struct ProjectInfo {
name: String,
path: String,
session_count: u64,
last_updated: String,
// ...
}4.8 SessionDetail
rust
struct SessionDetail {
id: String,
name: String?,
created_at: String,
updated_at: String,
turn_count: u64,
message_count: u64,
// ...
}4.9 SkillInfo
rust
struct SkillInfo {
name: String,
description: String,
// ...
}4.10 ProviderInfo
rust
struct ProviderInfo {
name: String,
provider_type: String,
model: String,
is_default: bool,
has_api_key: bool, // 是否已配置(不返回真实 API 密钥)
ephemeral: bool,
effort_applicable: bool, // 是否支持推理努力级别
// ...
}4.11 McpStatusResponse
rust
struct McpStatusResponse {
servers: Vec<McpServerStatus>,
}
struct McpServerStatus {
name: String,
status: String, // "connected" | "disconnected" | "error"
tool_count: u64,
// ...
}4.12 ProviderConfig
rust
struct ProviderConfig { // 15 个字段
name: String,
provider_type: String,
api_key: String?, // 仅在创建/更新时使用
base_url: String?,
model: String?,
max_tokens: u64?,
thinking_budget: u64?,
thinking_type: String?,
thinking_keep: bool?,
reasoning_history: u64?,
skip_tls_verify: bool?,
effort_applicable: bool?,
default: bool?,
// ...
}4.13 HealthResponse
rust
struct HealthResponse {
service: String, // "atomcode-daemon"
status: String, // "ok" | "error"
version: String, // 版本号
// ...
}4.14 ModelInfo
rust
struct ModelInfo {
id: String,
provider_type: String,
effort_applicable: bool, // 是否支持 effort
// ...
}5. WebUI 头像设置
从嵌入式 JS 提取的 UI 设置选项:
javascript
// 设置面板
d === `theme` → 主题选择(ThemePanel)
d === `language` → 语言选择(LanguagePanel)
d === `model` → 模型选择(ModelPanel)
d === `remote` → 远程访问(TunnelPanel)5.1 UI 组件树
App
├── AppSidebar
│ ├── SessionList
│ ├── CwdBreadcrumb
│ ├── DirBrowser
│ └── PermissionDecision
├── HeaderRemoteBtn → RemotePanel (Tunnel QR)
├── ThemePanel
├── LanguagePanel
├── ModelPanel
├── RemotePanel (Tunnel)
├── ChatBody
│ ├── ChatLanding
│ ├── MessageList
│ ├── ArtifactDisplay
│ └── CodeBlockWrapper
└── SessionRename → RenamePanel
SessionDelete → DeleteConfirmPanel5.2 远程访问面板(Tunnel)
javascript
let e = await fetch(`/tunnel/status`, { headers: G() });
// returns: { bind_host, reachable, remote_url, qr_svg }6. Daemon → Client 通信模型
┌──────────────────┐
│ AI Provider │
│ (OpenAI/Anthropic) │
└────────┬─────────┘
│ API calls
▼
┌──────────┐ /live (SSE) ┌──────────────────┐
│ WebUI │ ◀──────────── │ │
│ (Browser)│ ────────────▶ │ AtomCode Daemon │
│ │ POST /live/* │ (localhost: │
│ TUI │ (msg/prov/ │ 13456) │
│ (Term) │ perm/effort)│ │
└──────────┘ │ ┌────────────┐ │
│ │ Agent Loop │ │
┌──────────┐ │ └────────────┘ │
│ VS Code │ ◀──────────── │ │
│ Ext │ HTTP API │ ┌────────────┐ │
└──────────┘ │ │ Tool Exec │ │
│ └────────────┘ │
┌──────────┐ └──────────────────┘
│ Proxy │
│ (v1/v2) │ ──── HTTP ───▶ localhost:13456
└──────────┘7. 协议总览
| 协议/接口 | 端口 | 传输方式 | 客户端 |
|---|---|---|---|
| Daemon HTTP API | 13456 | HTTP/1.1 JSON | VS Code, WebUI, TUI, Proxy |
| Daemon SSE (Live) | 13456 | text/event-stream | WebUI Browser |
| WebUI | 13457 | HTTP (托管 SPA) | Browser |
| Tunnel (远程) | 动态 | WebSocket/SSH | 远程浏览器 |
| Proxy v2 (OpenAI) | 8080 | HTTP/1.1 JSON | Cline/Codex/AI Tools |
7.1 认证令牌传递
javascript
// 认证头生成
function G() {
let t = getAuthToken(); // 从存储中获取
return t ? { "Authorization": `Bearer ${t}` } : {};
}
// 或者使用 Yi()
function Yi() {
let t = getAuthToken();
return t ? { "Authorization": `Bearer ${t}` } : {};
}所有 daemon API 请求均通过 Authorization: Bearer <token> 认证。
8. 新发现的盲区覆盖
| # | 之前未覆盖的领域 | 状态 | 发现 |
|---|---|---|---|
| 1 | Daemon API 端点完整映射 | ✅ | 30+ 端点,含 SPA 调用的全部 19 个端点 |
| 2 | LiveWire SSE 实时协议 | ✅ | 基于 ReadableStream 的 SSE,16 种事件类型 |
| 3 | API 请求/响应结构体 | ✅ | 15 个结构体,完整字段列表 |
| 4 | WebUI 组件树 | ✅ | 8 个主面板 + 会话/权限/远程组件 |
| 5 | 提供商管理完整字段 | ✅ | ProviderConfig 15 字段 + PatchProviderRequest 19 字段 |
逆向命令索引
bash
# 提取 SSE 事件类型
strings atomcode.bin.bak | grep -E "\"type\":\"[a-z_]+\"" | sed 's/.*"type":"\([^"]*\)".*/\1/' | sort -u
# 输出: text reasoning tool_start tool_result tool_output tokens done error
# permission_request provider snapshot state stopped user
# 提取 Live API 结构体
strings atomcode.bin.bak | grep -E "struct LiveMessageReq|struct LivePermissionReq|struct LiveProviderReq" | sort -u
# 输出:
# struct LiveMessageReq with 4 elements
# struct LivePermissionReq with 2 elements
# struct LiveProviderReq with 1 element
# 运行时抓取 SSE 流
curl -N -X POST http://localhost:13456/chat \
-H "Authorization: Bearer $(cat ~/.atomcode/auth.toml | grep access_token | cut -d'"' -f2)" \
-H "Content-Type: application/json" \
-d '{"message":"hi"}' 2>&1 | grep "^data:" | head -10| 6 | Token 传递机制 | ✅ | Authorization: Bearer 统一头 |
本报告由持续分析循环生成 — 覆盖了原有盲区清单外的深层协议分析