chore: initial public snapshot for github upload

This commit is contained in:
Your Name
2026-03-26 20:06:14 +08:00
commit 0e5ecd930e
3497 changed files with 1586236 additions and 0 deletions

View File

@@ -0,0 +1,224 @@
# Subapi Connector 契约清单 v1
- 版本v1.0
- 日期2026-03-17
- 适用阶段S1-S2`subapi` 外部服务模块化接入 + 客户迁移)
- 契约目标:为我方 Router Core 与 `subapi` 之间的调用定义“稳定接口 + 稳定语义 + 可回归验证”。
## 1. 设计目标与边界
## 1.1 目标
1.`subapi` 视为“可替换外部能力模块”,而不是核心业务真相源。
2. 固定北向协议与字段语义,避免上游快速迭代导致我方主路径抖动。
3. 对请求、响应、错误、流式事件建立统一归一模型,支撑审计、计费、告警。
## 1.2 非目标
1. 不在本契约覆盖 `subapi` 后台管理 API`/admin/*`)。
2. 不在本契约定义我方控制面业务模型租户、账务、RBAC的内部存储结构。
3. 不将 `subapi` 私有实现细节(调度算法内部参数)暴露到我方公共 API。
## 2. 接入范围(协议与端点)
## 2.1 Canonical 端点Connector 只使用这一组)
| 协议域 | Method | Path | 说明 |
|---|---|---|---|
| Anthropic 兼容 | `POST` | `/v1/messages` | 统一消息入口 |
| Anthropic 兼容 | `POST` | `/v1/messages/count_tokens` | 仅计数,不计费记录 |
| OpenAI 兼容 | `POST` | `/v1/chat/completions` | Chat Completions |
| OpenAI 兼容 | `POST` | `/v1/responses` | Responses |
| OpenAI 兼容 | `POST` | `/v1/responses/*subpath` | Responses 子资源 |
| OpenAI 兼容WS | `GET` | `/v1/responses` | WebSocket 升级入口 |
| 通用 | `GET` | `/v1/models` | 模型目录 |
| 通用 | `GET` | `/v1/usage` | 用量/额度信息 |
| Gemini 原生 | `GET` | `/v1beta/models` | 模型列表 |
| Gemini 原生 | `GET` | `/v1beta/models/:model` | 模型详情 |
| Gemini 原生 | `POST` | `/v1beta/models/*modelAction` | `generateContent`/`streamGenerateContent` |
## 2.2 Alias 端点处理
1. `subapi` 提供不带 `/v1` 的别名(如 `/responses``/chat/completions`)。
2. Connector 禁止调用 alias统一走 canonical 端点,避免路由歧义。
## 3. 认证与请求头契约
## 3.1 认证头优先级
1. `/v1/*`
- `Authorization: Bearer <key>` > `x-api-key` > `x-goog-api-key`
2. `/v1beta/*`
- `x-goog-api-key` > `Authorization: Bearer <key>` > `x-api-key` > `key(query仅兼容)`
## 3.2 禁止项
1. 禁止通过 query 传 `key`/`api_key`(仅保留兼容读取,不作为标准路径)。
2. Connector 默认不发送 query key。
## 3.3 会话亲和相关头
1. OpenAI 兼容:支持 `session_id``conversation_id`,请求体支持 `prompt_cache_key`
2. Gemini CLI支持 `x-gemini-api-privileged-user-id` + 请求体 tmp 路径哈希会话识别。
3. Anthropic 兼容:可使用 `metadata.user_id` 补充分组内会话亲和。
## 3.4 北向/南向边界(安全强约束,新增)
1. 北向(客户 -> 我方网关):
- 禁止接收任何 query key`key`/`api_key`),统一要求 header 鉴权。
- 外部携带 query key 的请求必须被拒绝并记录审计事件。
2. 南向(我方网关 -> subapi connector
- 仅允许 header 方式传递凭证(`Authorization`/`x-api-key`/`x-goog-api-key`)。
- Connector 默认不透传 query key。
3. 历史兼容策略:
- 若为极少数遗留客户端保留“内部改写”能力,必须在北向入口完成 query->header 改写,且该兼容规则需要白名单与审计日志。
- 该兼容规则默认关闭,并纳入版本化淘汰计划。
## 4. 请求体契约(最小强约束)
## 4.1 通用约束
1. Body 必须是非空 JSON。
2. `model` 必须为非空字符串。
3. `stream` 若出现,必须是布尔值。
## 4.2 OpenAI Responses 额外约束
1. `previous_response_id` 若存在,必须是 `resp_*` 风格,不可传 message id。
2. `input.type=function_call_output` 场景必须满足 call 上下文约束(否则应返回 `400 invalid_request_error`)。
## 4.3 Gemini Action 路径约束
1. `*modelAction` 支持两种格式:`{model}:{action}``{model}/{action}`
2. `streamGenerateContent` 视为流式请求。
## 5. 响应归一契约Connector 内部模型)
Connector 必须将不同协议响应归一为以下内部结构:
```json
{
"protocol": "openai|anthropic|gemini",
"request_id": "string",
"upstream_request_id": "string",
"model_requested": "string",
"model_actual": "string",
"stream": true,
"usage": {
"input_tokens": 0,
"output_tokens": 0,
"cache_creation_input_tokens": 0,
"cache_read_input_tokens": 0,
"total_tokens": 0
},
"first_token_ms": 0,
"duration_ms": 0,
"client_disconnect": false
}
```
## 5.1 字段规则
1. `upstream_request_id`:优先从响应头 `x-request-id` 提取。
2. `request_id`:若协议返回 body request id则保留否则由 Connector 生成稳定 ID。
3. `usage.total_tokens`:若上游未提供,按 `input + output` 计算;均缺失时置 0。
4. `usage` 缺失不视为失败,但必须打 `usage_extracted=false` 观测标签(用于后续补偿分析)。
## 6. 错误归一契约
## 6.1 上游原生错误格式(三类)
1. OpenAI 风格:`{"error":{"type":"...","message":"..."}}`
2. Anthropic 风格:`{"type":"error","error":{"type":"...","message":"..."}}`
3. Google 风格:`{"error":{"code":403,"message":"...","status":"PERMISSION_DENIED"}}`
## 6.2 Connector 统一错误结构
```json
{
"http_status": 429,
"category": "auth|billing|rate_limit|upstream|validation|internal",
"code": "RATE_LIMIT_EXCEEDED",
"message": "human readable",
"retryable": true
}
```
## 6.3 默认映射规则
1. `401/403` 上游鉴权类错误 -> `category=auth``retryable=false`
2. `429` -> `category=rate_limit``retryable=true`
3. `500/502/503/504/529` -> `category=upstream``retryable=true`
4. 计费检查失败(余额/订阅/额度) -> `category=billing``retryable` 取决于具体码。
5. JSON/字段校验失败 -> `category=validation``retryable=false`
## 7. 流式契约SSE/WS
## 7.1 SSE
1. 流开始后如发生错误,按事件帧返回,不再回写普通 JSON 错误。
2. 一旦已向客户端写出任何流内容Connector 禁止触发“同请求 failover 重放”。
3. 必须记录首字时延 `first_token_ms` 与终止类型(正常结束/上游错误/客户端断开)。
## 7.2 WebSocketOpenAI Responses
1. 首帧必须包含合法 JSON 且含 `model`
2. 若首帧不合法,立即关闭连接并返回协议错误。
3. 多轮 turn 必须重新获取并发槽位(避免长连接长期占槽)。
## 8. 重试与回退契约Connector 侧)
1. 仅在“未输出任何字节”时允许请求级重试。
2. 流式一旦开始输出,禁止自动重试。
3. 推荐重试上限:
- 非流式:最多 2 次(指数退避)
- 流式0 次(依赖上游内部 failover
4. HTTP 429/503 可进入短退避重试4xx 校验/鉴权错误直接失败。
## 9. 版本与兼容治理
## 9.1 版本锁定
1. 生产固定 `subapi` 精确版本(`vX.Y.Z`),不允许漂移到未验证版本。
2. 升级必须进入周级升级窗口,禁止临时直升生产。
## 9.2 契约测试门槛(每次升级必须通过)
1. OpenAI `/v1/chat/completions` 非流/流式基础场景。
2. OpenAI `/v1/responses` + `previous_response_id` 校验场景。
3. Anthropic `/v1/messages` + `count_tokens` 场景。
4. Gemini `/v1beta/models/*` 普通与流式场景。
5. 三类错误格式的归一验证OpenAI/Anthropic/Google
6. 流式中断与客户端断开场景(保证不重放、不漏记)。
## 10. 与 S2 目标的对齐(执行约束)
1. `S2` 结束时:
- 全供应商主路径由自研 Router Core 接管率 `>= 60%`
- 国内 LLM 供应商主路径接管率 `= 100%`
2. `subapi` 在 S2 后只承担:
- 长尾协议兼容
- 备用回退通道
## 11. 证据来源(本地代码)
1. 路由范围与协议入口:
`/home/long/project/立交桥/llm-gateway-competitors/sub2api-tar/backend/internal/server/routes/gateway.go`
2. OpenAI/Anthropic 错误与流式处理:
`/home/long/project/立交桥/llm-gateway-competitors/sub2api-tar/backend/internal/handler/openai_gateway_handler.go`
3. Claude 兼容入口、`models`/`usage`/`count_tokens`
`/home/long/project/立交桥/llm-gateway-competitors/sub2api-tar/backend/internal/handler/gateway_handler.go`
4. Gemini 原生入口与错误格式:
`/home/long/project/立交桥/llm-gateway-competitors/sub2api-tar/backend/internal/handler/gemini_v1beta_handler.go`
5. 认证优先级与禁用 query key
`/home/long/project/立交桥/llm-gateway-competitors/sub2api-tar/backend/internal/server/middleware/api_key_auth.go`
`/home/long/project/立交桥/llm-gateway-competitors/sub2api-tar/backend/internal/server/middleware/api_key_auth_google.go`
6. 会话哈希与 header 语义:
`/home/long/project/立交桥/llm-gateway-competitors/sub2api-tar/backend/internal/service/openai_gateway_service.go`
`/home/long/project/立交桥/llm-gateway-competitors/sub2api-tar/backend/internal/service/gateway_service.go`
## 12. 下一步v1 -> v1.1
1. 把本契约转成机器可执行测试清单YAML + golden cases
2. 为每个端点补充“最小请求样例 + 最小响应样例”文件。
3. 将错误映射表下沉为配置化规则,减少硬编码发布频率。