1
0

fix: 完善转换代理行为

This commit is contained in:
2026-04-26 21:48:17 +08:00
parent 155244433f
commit 9622d44aac
33 changed files with 1127 additions and 1117 deletions

View File

@@ -75,7 +75,7 @@
│ │ │ │
│ │ 入站: /{protocol}/{native_path} │ │
│ │ │ │
│ │ /openai/chat/completions → client=openai, /chat/completions │ │
│ │ /openai/v1/chat/completions → client=openai, /v1/chat/completions │ │
│ │ /anthropic/v1/messages → client=anthropic, /v1/messages │ │
│ │ │ │
│ │ Step 1: 识别 client protocolURL 前缀 / 配置映射 / 任意方式) │ │
@@ -117,8 +117,8 @@
```
入站 URL 调用方剥离前缀后 引擎出站
──────────────────────────────────────────────────────────────────────────────
/openai/chat/completions → /chat/completions → /chat/completions
/openai/models → /models → /models
/openai/v1/chat/completions → /v1/chat/completions → /chat/completions
/openai/v1/models → /v1/models → /models
/anthropic/v1/messages → /v1/messages → /v1/messages
/anthropic/v1/models → /v1/models → /v1/models
```
@@ -459,7 +459,7 @@ interface ProtocolAdapter {
**`buildHeaders` 的设计**Adapter 只需从 `provider` 中提取自己协议需要的认证和配置信息,构建自己的 Header 格式。不再需要理解其他协议的 Header。
**URL 事实来源**Adapter 的 `detectInterfaceType``buildUrl` 必须以本地 API reference 为事实来源。OpenAI 参考 `docs/api_reference/openai`(忽略 `responses` 目录),其 nativePath 不包含 `/v1`,例如 `/chat/completions``/models``/embeddings`。Anthropic 参考 `docs/api_reference/anthropic`nativePath 保留 `/v1`,例如 `/v1/messages``/v1/models`。不得根据其他协议是否包含 `/v1` 推断当前协议路径。
**URL 事实来源**Adapter 的 `detectInterfaceType``buildUrl` 必须以本地 API reference 及网关对外协议契约为事实来源。OpenAI 对外路径为 `/openai/v1/...`,剥离协议前缀后的 nativePath 保留 `/v1`,例如 `/v1/chat/completions``/v1/models``/v1/embeddings`;但 OpenAI 供应商 `base_url` 配置到版本路径一级,`buildUrl` 输出上游 path 时移除 `/v1`,例如 `/chat/completions``/models``/embeddings`。Anthropic 参考 `docs/api_reference/anthropic`nativePath 与上游 path 均保留 `/v1`,例如 `/v1/messages``/v1/models`。不得根据其他协议是否包含 `/v1` 推断当前协议路径。
**智能透传方法的契约**
- `rewriteRequestModelName` / `rewriteResponseModelName` 必须**幂等**(多次调用结果相同)
@@ -868,7 +868,7 @@ engine.registerAdapter(new OpenAIAdapter())
engine.registerAdapter(new AnthropicAdapter())
// 场景1: 跨协议 Chat 转换
// 入站: /openai/chat/completions
// 入站: /openai/v1/chat/completions
provider = TargetProvider {
base_url: "https://api.anthropic.com",
api_key: "xxx",
@@ -1301,7 +1301,7 @@ Canonical Model 是**活的公共契约**,不是固定不变的。其字段集
| URL 映射表 | 每种 InterfaceType 的目标 URL 路径(`buildUrl` |
**重要**`detectInterfaceType` 由各协议 Adapter 实现,因为不同协议有不同的 URL 路径约定。例如:
- OpenAI: `/chat/completions` → CHAT
- OpenAI: `/v1/chat/completions` → CHAT
- Anthropic: `/v1/messages` → CHAT
### D.3 请求头构建

View File

@@ -24,7 +24,7 @@
| -------- | ----------------------------------- |
| 协议名称 | `"openai"` |
| 协议版本 | 无固定版本头API 持续演进 |
| Base URL | `https://api.openai.com` |
| Base URL | `https://api.openai.com/v1`(供应商配置到版本路径一级) |
| 认证方式 | `Authorization: Bearer <api_key>` |
---
@@ -47,13 +47,13 @@
OpenAI.detectInterfaceType(nativePath):
if nativePath == "/v1/chat/completions": return CHAT
if nativePath == "/v1/models": return MODELS
if nativePath matches "^/v1/models/[^/]+$": return MODEL_INFO
if nativePath startsWith "/v1/models/" and suffix is not empty: return MODEL_INFO
if nativePath == "/v1/embeddings": return EMBEDDINGS
if nativePath == "/v1/rerank": return RERANK
return PASSTHROUGH
```
**说明**`detectInterfaceType` 由 OpenAI Adapter 实现,根据 OpenAI 协议的 URL 路径约定识别接口类型。
**说明**`detectInterfaceType` 由 OpenAI Adapter 实现,根据 OpenAI 协议的 URL 路径约定识别接口类型。网关剥离 `/openai` 协议前缀后OpenAI Adapter 接收的 nativePath 保留 `/v1`
### 2.3 接口能力矩阵
@@ -74,14 +74,16 @@ OpenAI.supportsInterface(type):
```
OpenAI.buildUrl(nativePath, interfaceType):
switch interfaceType:
case CHAT: return "/v1/chat/completions"
case MODELS: return "/v1/models"
case MODEL_INFO: return "/v1/models/{modelId}"
case EMBEDDINGS: return "/v1/embeddings"
case RERANK: return "/v1/rerank"
case CHAT: return "/chat/completions"
case MODELS: return "/models"
case MODEL_INFO: return "/models/{modelId}"
case EMBEDDINGS: return "/embeddings"
case RERANK: return "/rerank"
default: return nativePath
```
**说明**OpenAI 供应商 `base_url` 配置到版本路径一级,`buildUrl` 输出上游 path 时移除 nativePath 中的 `/v1`,避免拼接出重复版本段。
---
## 3. 请求头构建