AtomCode Reverse Proxy v2.0 完整架构分析
持续深度分析 — Proxy 架构、OpenAI 兼容层、Daemon 管理 2026-06-23
1. 架构总览
┌──────────────┐ OpenAI API ┌──────────────────────┐ SSE/HTTP ┌──────────────┐
│ AI Clients │ /v1/chat/comp- │ AtomCode Proxy v2.0 │ localhost: │ AtomCode │
│ (Cline, │ letions │ │ 13456 │ Daemon │
│ Codex, │ ────────────────▶ │ FastAPI + Uvicorn │ ────────────▶ │ (Rust │
│ Continue, │ │ Port 8080 │ │ axum) │
│ OpenGPT) │ ◀──────────────── │ SSE → OpenAI Chunks │ ◀──────────── │ │
└──────────────┘ SSE stream └──────────────────────┘ /auth/* └──────────────┘
│ │ /cd │
│ ┌─────────────────┐ │ /models │
│ │ Session Cache │ │ /providers │
│ │ (会话复用) │ │ /health │
│ └─────────────────┘ └──────────────┘
│
│ DaemonManager (进程管理)
│ auto_manage=true daemon lifecycle
└───────────────────────────────────────2. 核心功能
| 特性 | 说明 |
|---|---|
| OpenAI 兼容 | 完全兼容 OpenAI /v1/chat/completions API |
| 流式/非流式 | 支持 stream: true/false |
| 多轮对话 | 会话复用(基于消息摘要的 session_id 缓存) |
| 提供商路由 | 按模型名自动匹配 daemon 提供商 |
| Daemon 管理 | 自动启动/停止/重启/健康监测 |
| 自动登录 | 自动检测登录状态,提示 OAuth 流程 |
| 自动 Claim | 自动声明 CodingPlan 配额 |
| CORS | 全开 CORS(*),适用于浏览器客户端 |
| Docker 就绪 | 完整的 Docker 构建 + 编排 |
| 配置层叠 | 3 层配置搜索路径 |
3. OpenAI API 协议转换
3.1 Daemon SSE 事件 → OpenAI SSE Chunk
Daemon SSE Event ──→ OpenAI Chat Completion Chunk
───────────────── ────────────────────────────
type: "text" → {"choices":[{"delta":{"content":"..."}}]}
type: "reasoning" → {"choices":[{"delta":{"reasoning_content":"..."}}]}
type: "tool_start" → {"choices":[{"delta":{"tool_calls":[{...}]}}]}
type: "tool_output" → (跳过 — 流式不发送)
type: "tool_result" → (跳过 — 合入下一条助手回复)
type: "tokens" → {"usage":{...}} (含 prompt/completion/total tokens)
type: "done" → "data: [DONE]"
type: "error" → {"choices":[{"delta":{},"finish_reason":"error"}]}
type: "stopped" → "data: [DONE]"3.2 响应格式构建
python
# OpenAI 标准
id: "chatcmpl-atomcode"
object: "chat.completion.chunk" (流式) / "chat.completion" (非流式)
created: <unix_timestamp>
model: <model_name>
choices: [{index, delta/message, finish_reason}]
usage: {prompt_tokens, completion_tokens, total_tokens}3.3 支持的非标准字段
| 字段 | 来源 | 支持状态 |
|---|---|---|
reasoning_content | DeepSeek | 支持 (daemon "reasoning" 事件) |
tool_calls | Function Calling | 支持 (daemon "tool_start" 事件) |
finish_reason: "tool_calls" | Function Calling | 支持 (非流式聚合) |
4. 会话管理
4.1 会话复用机制
python
# 对话键生成 (SHA256)
_ (messages + system_prompt) 的 SHA256 摘要作为 conv_key
# 会话缓存
app.state.sessions: Dict[conv_key, daemon_session_id]
app.state.session_times: Dict[conv_key, last_used_timestamp]
# 过期策略
max_age = config["sessions"]["max_age_minutes"] * 60 # 默认 30 分钟4.2 非流式请求流程
1. 构建消息 → _format_messages_for_daemon()
2. 生成会话键 → _conversation_key()
3. 查找已有 daemon_session_id
4. 调用 daemon_client.chat_stream(stream=True, session_id=xxx)
5. 聚合所有事件 → 构建完整 ChatCompletionResponse
6. 保存新 session_id → 后续请求复用4.3 流式请求流程
1. 同上 1-4
2. 逐事件转换 → SSE chunk
3. each "text" event → "data: {"choices":[{...}]}\n\n"
4. "done" event → "data: [DONE]\n\n"
5. 保存新 session_id5. 提供商路由
5.1 模型 → 提供商映射
python
# 用户请求中包含 model name
# 从 daemon 获取所有提供商列表
# 匹配 providers[].model == model_name
# 找到后设置 provider = providers[].name
# 传递到 daemon 的 /chat 接口5.2 ProviderConfig 完整字段 (15 个)
| 字段 | 类型 | 说明 |
|---|---|---|
name | String | 提供商名称 |
provider_type | String | 提供商类型 (openai/anthropic/ollama/...) |
api_key | String | API 密钥 |
base_url | String? | 基础 URL |
model | String? | 默认模型 |
model_type | String? | 模型类型 |
max_tokens | u64? | 最大 token 数 |
thinking_budget | u64? | 思考预算 |
thinking_type | String? | 思考类型 |
thinking_keep | bool? | 保留思考过程 |
reasoning_history | u64? | 推理历史长度 |
skip_tls_verify | bool? | 跳过 TLS 验证 |
effort_applicable | bool? | 支持推理努力级别 |
default | bool? | 是否为默认 |
ephemeral | bool? | 临时提供商 |
6. DaemonManager 进程管理
6.1 生命周期
DaemonManager
├── start() → 启动 daemon 子进程
│ 设置 ATOMCODE_TELEMETRY=0
│ 记录 PID
│ 等待健康检查 (最多 30 次 × 1 秒)
│
├── stop() → 发送 /shutdown 请求
│ 等待进程退出 (最多 5 秒)
│ 发送 SIGKILL 强制终止
│
├── restart() → 调用 stop() → start()
│
├── running → 检查进程是否存活
│
└── _check_health() → GET /health 检查6.2 健康监控 (后台任务)
python
async def _health_monitor():
while True:
await asyncio.sleep(15) # 每 15 秒检查一次
health = daemon_client.health()
if status != "ok":
fail_count += 1
if fail_count >= 3 and auto_manage:
daemon_mgr.restart() # 3 次失败后自动重启
fail_count = 06.3 自动管理配置
yaml
daemon:
auto_manage: false # 默认不管理(需显式启用)
telemetry: false # ATOMCODE_TELEMETRY=07. DaemonClient 通信
7.1 Daemon API 调用
| 方法 | HTTP | 端点 | 超时 | 说明 |
|---|---|---|---|---|
health() | GET | /health | 30s | 健康检查 |
auth_status() | GET | /auth/status | 30s | 登录状态 |
login_start() | POST | /auth/login/start | 30s | 发起登录 |
login_poll() | POST | /auth/login/:id/poll | 30s | 轮询结果 |
models_list() | GET | /models | 30s | 模型列表 |
providers_list() | GET | /providers | 30s | 提供商列表 |
codingplan_setup() | POST | /codingplan/setup | 30s | CodingPlan 设置 |
chat_stream() | POST | /chat | 120s | SSE 流式聊天 |
7.2 认证流程 (OAuth)
python
1. GET /auth/status → {"logged_in": false}
2. POST /auth/login/start → {"login_id": "...", "url": "...",
"expires_in_seconds": 600}
3. 用户浏览器打开 url
4. POST /auth/login/:id/poll → {"status": "pending"} (轮询,2 秒间隔)
5. POST /auth/login/:id/poll → {"status": "authorized",
"user": {name, username, avatar, ...}}8. CLI 命令
| 命令 | 说明 |
|---|---|
python3 atomcode_proxy.py serve | 仅启动代理服务 |
python3 atomcode_proxy.py start | 启动 daemon + 代理 |
python3 atomcode_proxy.py stop | 停止 daemon |
python3 atomcode_proxy.py restart | 重启 daemon + 代理 |
python3 atomcode_proxy.py status | 显示状态 |
python3 atomcode_proxy.py login | OAuth 登录 |
python3 atomcode_proxy.py setup | 登录 + CodingPlan 声明 |
python3 atomcode_proxy.py daemon [status/start/stop/restart] | daemon 管理 |
python3 atomcode_proxy.py models | 列出可用模型 |
9. 消息格式转换
9.1 OpenAI 消息 → Daemon 文本
python
# 输入: OpenAI messages array
[
{"role": "system", "content": "You are..."},
{"role": "user", "content": "Hello"},
{"role": "assistant", "content": "Hi"},
{"role": "user", "content": "Write code"}
]
# 输出: Daemon 消息字符串
"""
[System]
You are...
[User]
Hello
[Assistant]
Hi
[User]
Write code
"""9.2 系统提示提取
python
# 提取第一条 system message
# 剩余消息格式化为对话历史10. Docker 部署
10.1 部署文件结构
Dockerfile
├── python:3.11-slim 基础镜像
├── 安装 atomcode (install.sh)
├── 复制 atomcode_proxy.py, proxy.yaml, requirements.txt
└── entrypoint.sh 入口点
docker-compose.yaml
└── 暴露 8080 端口
└── 使用命名卷 atomcode-data 持久化 ~/.atomcode
└── 环境: ATOMCODE_TELEMETRY=0, LOG_LEVEL=INFO
└── restart: unless-stopped
entrypoint.sh
├── 1. 启动 daemon (ATOMCODE_TELEMETRY=0 atomcode daemon &)
├── 2. 等待 daemon 就绪 (循环 30 次)
├── 3. 检查登录状态
└── 4. 启动 proxy (exec python3 atomcode_proxy.py serve)10.2 交互式配置(容器内)
bash
# OAuth 登录(需要在浏览器中打开 URL)
docker exec -it atomcode-proxy python3 atomcode_proxy.py setup11. 配置系统
11.1 配置搜索路径
| 优先级 | 路径 | 说明 |
|---|---|---|
| 1 | ./proxy.yaml | 当前目录 |
| 2 | ~/.atomcode/proxy.yaml | 用户配置目录 |
| 3 | /etc/atomcode/proxy.yaml | 系统全局配置 |
11.2 配置合并策略
python
# 深度合并 (deep_merge)
# 下层配置继承上层,相同键覆盖11.3 默认配置
yaml
server:
host: "0.0.0.0"
port: 8080
daemon:
url: "http://localhost:13456"
binary_path: null # 自动检测
auto_manage: false
telemetry: false
logging:
level: "INFO"
file: null
sessions:
max_age_minutes: 30
setup:
auto_login: true
auto_claim: true12. 发现的新盲区覆盖
| # | 之前未覆盖的领域 | 状态 | 发现 |
|---|---|---|---|
| 1 | Reverse Proxy v2 完整架构 | ✅ | 1244 行 Python,FastAPI + SSE 流式 |
| 2 | OpenAI 协议转换 | ✅ | 9 种事件翻译规则 |
| 3 | DaemonManager 进程管理 | ✅ | start/stop/restart + 健康监控 + 自动重启 |
| 4 | 会话复用机制 | ✅ | SHA256 摘要键 + 30 分钟过期 |
| 5 | 提供商路由逻辑 | ✅ | 模型名 → 提供商匹配 |
| 6 | OAuth 登录流程代理 | ✅ | 浏览器 OAuth + 轮询 + CodingPlan claim |
| 7 | 消息格式转换 | ✅ | OpenAI → Daemon 文本格式 |
| 8 | Docker 部署架构 | ✅ | Dockerfile + Compose + Entrypoint |
逆向命令索引
bash
# 提取代理架构相关字符串
strings atomcode.bin.bak | grep -iE "proxy|relay|reverse.*proxy" | grep -v "https\?://\|crates/" | sort -u | head -10
# 查看代理 Python 代码结构
grep -c "def \|class " atomcode_proxy.py
# 输出: 1244 行 Python, 多个 class + async def
# 提取 SSE 流转换相关
strings atomcode.bin.bak | grep -iE "sse|stream|chunk|delta" | grep -v "https\?://\|crates/" | sort -u | head -15
# 运行时验证 API 兼容层
curl -s -H "Authorization: Bearer $TOKEN" http://localhost:13456/v1/models 2>/dev/null | head| 9 | 配置系统 | ✅ | 3 层搜索 + 深度合并 |
本报告由持续分析循环生成 — 覆盖了原有盲区清单外的 Proxy 架构深层分析