proxy-playbook/docs/ARCHITECTURE.md

48 lines
1.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 整体架构
## 核心流程
1. 客户端 POST /v1/chat/completions 到本地端口
2. 中间件做三件事:
- 校验本地 API Key(Authorization: Bearer <key>)
- 读 body 里的 model,按前缀路由
- 如果带前缀,把 model 改成去掉前缀后的上游模型名
3. 根据 stream 字段选择转发方式:
- stream=true → 打开上游 SSE,字节流实时转发
- 非流式 → 缓冲上游完整响应后返回
## 模型前缀路由
| 前缀 | ProviderKind | Region |
|---|---|---|
| wbcn- / workbuddy-cn / codebuddy- | WORKBUDDY_CN | CN |
| wbintl- / workbuddy-intl / workbuddy- | WORKBUDDY_INTL | INTL |
| traecn- / trae-cn / trae- | TRAE_CN | CN |
| traeintl- / trae-intl | TRAE_INTL | INTL |
| 其它 | OPENAI_COMPATIBLE(Sub2API 透传) | - |
## 请求生命周期
POST /v1/chat/completions
-> authorized() // 401 if invalid key
-> extractModel(rawBody) // "traecn-glm-5.2"
-> router.route(model) // (TRAE_CN, CN)
-> stripModelPrefix(model) // "glm-5.2"
-> rewriteModelBody() // 替换 body.model
-> pooled = pool.next(kind, region, sessionKey)
-> traeChatProxy.openStreamingChat(body, pooled?.accountId, region)
-> respondOutputStream(...) // 逐块写上游字节
## 账号池
- 从 CredentialRepository.accountsFor(service) 读取实时账号
- 每个 ProviderKind 一个轮询游标(round-robin)
- 会话粘性:X-Conversation-Id 或 body user 作为 key,同会话复用同一账号
- 地区匹配:优先选择 credential.region == route.region,没有则回退全部
## 本地服务
- GET /health → 存活检查
- GET /v1/models → 透传 Sub2API 模型列表
- POST /v1/chat/completions → 聊天代理