1
0
Files
nex/openspec/specs/error-responses/spec.md
lanyuanxiaoyao 395887667d feat: 实现统一模型 ID 机制
实现统一模型 ID 格式 (provider_id/model_name),支持跨协议模型标识和 Smart Passthrough。

核心变更:
- 新增 pkg/modelid 包:解析、格式化、校验统一模型 ID
- 数据库迁移:models 表使用 UUID 主键 + UNIQUE(provider_id, model_name) 约束
- Repository 层:FindByProviderAndModelName、ListEnabled 方法
- Service 层:联合唯一校验、provider ID 字符集校验
- Conversion 层:ExtractModelName、RewriteRequestModelName/RewriteResponseModelName 方法
- Handler 层:统一模型 ID 路由、Smart Passthrough、Models API 本地聚合
- 新增 error-responses、unified-model-id 规范

测试覆盖:
- 单元测试:modelid、conversion、handler、service、repository
- 集成测试:统一模型 ID 路由、Smart Passthrough 保真性、跨协议转换
- 迁移测试:UUID 主键、UNIQUE 约束、级联删除

OpenSpec:
- 归档 unified-model-id 变更到 archive/2026-04-21-unified-model-id
- 同步 11 个 delta specs 到 main specs
- 新增 error-responses、unified-model-id 规范文件
2026-04-21 18:14:10 +08:00

210 lines
5.6 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.
# Error Responses
## Purpose
定义系统统一的错误响应格式和各类错误场景,确保客户端能够一致地处理错误。
## Requirements
### Requirement: 统一错误响应格式
系统 SHALL 使用统一的错误响应格式。
#### Scenario: 标准错误格式
- **WHEN** 返回错误响应
- **THEN** SHALL 使用以下 JSON 格式:
```json
{
"error": "错误描述",
"code": "ERROR_CODE"
}
```
- **THEN** `error` 字段 SHALL 包含人类可读的错误描述
- **THEN** `code` 字段 SHALL 包含机器可读的错误代码(可选)
### Requirement: provider_id 校验错误
系统 SHALL 对 provider_id 校验错误返回明确的错误信息。
#### Scenario: provider_id 包含非法字符
- **WHEN** 创建或更新供应商时provider_id 包含非 `[a-zA-Z0-9_]` 字符
- **THEN** SHALL 返回 HTTP 400 Bad Request
- **THEN** SHALL 返回以下 JSON 格式:
```json
{
"error": "供应商 ID 仅允许字母、数字、下划线",
"code": "INVALID_PROVIDER_ID"
}
```
#### Scenario: provider_id 长度超限
- **WHEN** 创建或更新供应商时provider_id 长度超过 64
- **THEN** SHALL 返回 HTTP 400 Bad Request
- **THEN** SHALL 返回以下 JSON 格式:
```json
{
"error": "供应商 ID 长度不能超过 64 个字符",
"code": "INVALID_PROVIDER_ID"
}
```
### Requirement: 联合唯一约束冲突错误
系统 SHALL 对联合唯一约束冲突返回明确的错误信息。
#### Scenario: 创建模型时 provider_id + model_name 组合已存在
- **WHEN** 创建模型时provider_id + model_name 组合已存在
- **THEN** SHALL 返回 HTTP 409 Conflict
- **THEN** SHALL 返回以下 JSON 格式:
```json
{
"error": "同一供应商下模型名称已存在",
"code": "duplicate_model"
}
```
#### Scenario: 更新模型时导致 provider_id + model_name 组合冲突
- **WHEN** 更新模型时,修改 provider_id 或 model_name 导致与已有记录冲突
- **THEN** SHALL 返回 HTTP 409 Conflict
- **THEN** SHALL 返回以下 JSON 格式:
```json
{
"error": "同一供应商下模型名称已存在",
"code": "duplicate_model"
}
```
### Requirement: 资源不存在错误
系统 SHALL 对资源不存在返回明确的错误信息。
#### Scenario: 模型不存在
- **WHEN** 查询或操作不存在的模型
- **THEN** SHALL 返回 HTTP 404 Not Found
- **THEN** SHALL 返回以下 JSON 格式:
```json
{
"error": "模型未找到"
}
```
#### Scenario: 供应商不存在
- **WHEN** 创建模型时指定的供应商不存在
- **THEN** SHALL 返回 HTTP 400 Bad Request
- **THEN** SHALL 返回以下 JSON 格式:
```json
{
"error": "供应商不存在"
}
```
### Requirement: 统一模型 ID 格式错误
系统 SHALL 对统一模型 ID 格式错误返回明确的错误信息。
#### Scenario: 统一模型 ID 格式无效
- **WHEN** 代理请求中的 model 字段不是有效的统一模型 ID 格式
- **THEN** 请求 SHALL 走 forwardPassthrough 透传到上游(兼容未适配的客户端)
- **THEN** 不返回错误,保持与上游的兼容性
**设计理由:**
- 统一模型 ID 是 BREAKING CHANGE部分旧客户端可能仍使用原始模型名
- 透传策略允许上游自行判断并返回错误(如 404 model not found
- 网关作为透明代理,不应拦截所有格式非法的请求
#### Scenario: 统一模型 ID 格式有效但对应模型不存在
- **WHEN** 代理请求中的 model 字段是有效的统一模型 ID 格式(含 `/`),但数据库中找不到对应的模型
- **THEN** SHALL 返回 HTTP 404 Not Found
- **THEN** SHALL 返回以下 JSON 格式:
```json
{
"error": "模型未找到"
}
```
#### Scenario: 统一模型 ID 对应的模型不存在
- **WHEN** 解析统一模型 ID 后,数据库中找不到对应的模型
- **THEN** SHALL 返回 HTTP 404 Not Found
- **THEN** SHALL 返回以下 JSON 格式:
```json
{
"error": "模型未找到"
}
```
#### Scenario: 统一模型 ID 对应的模型已禁用
- **WHEN** 解析统一模型 ID 后,对应的模型 enabled 为 false
- **THEN** SHALL 返回 HTTP 404 Not Found
- **THEN** SHALL 返回以下 JSON 格式:
```json
{
"error": "模型未找到"
}
```
#### Scenario: 统一模型 ID 对应的供应商已禁用
- **WHEN** 解析统一模型 ID 后,对应的供应商 enabled 为 false
- **THEN** SHALL 返回 HTTP 404 Not Found
- **THEN** SHALL 返回以下 JSON 格式:
```json
{
"error": "模型未找到"
}
```
### Requirement: JSON 格式错误
系统 SHALL 对请求体 JSON 格式错误返回明确的错误信息。
#### Scenario: 请求体 JSON 格式错误
- **WHEN** 代理请求的请求体不是有效的 JSON 格式
- **THEN** SHALL 返回 HTTP 400 Bad Request
- **THEN** SHALL 返回以下 JSON 格式:
```json
{
"error": "请求体 JSON 格式错误",
"code": "INVALID_JSON"
}
```
#### Scenario: Smart Passthrough 时请求体 JSON 格式错误
- **WHEN** 同协议 Smart Passthrough 场景下,请求体 JSON 格式不正确
- **THEN** SHALL 返回 HTTP 400 Bad Request
- **THEN** SHALL 返回以下 JSON 格式:
```json
{
"error": "请求体 JSON 格式错误",
"code": "INVALID_JSON"
}
```
### Requirement: 不可变字段错误
系统 SHALL 对尝试修改不可变字段返回明确的错误信息。
#### Scenario: 尝试修改供应商 ID
- **WHEN** 更新供应商时,请求体中包含 `id` 字段
- **THEN** SHALL 返回 HTTP 400 Bad Request
- **THEN** SHALL 返回以下 JSON 格式:
```json
{
"error": "供应商 ID 不允许修改",
"code": "IMMUTABLE_FIELD"
}
```