Skip to content

feat: native passthrough for OpenAI upstreams supporting both Responses and Chat Completions#3333

Open
StarryKira wants to merge 2 commits into
Wei-Shaw:mainfrom
StarryKira:feat/openai-responses-native-passthrough
Open

feat: native passthrough for OpenAI upstreams supporting both Responses and Chat Completions#3333
StarryKira wants to merge 2 commits into
Wei-Shaw:mainfrom
StarryKira:feat/openai-responses-native-passthrough

Conversation

@StarryKira

Copy link
Copy Markdown
Contributor

问题 / Problem

当 OpenAI APIKey 账号的上游(base_url同时支持 /v1/responses/v1/chat/completions 时,网关此前会把账号的全部流量塞进单一端点,并对不匹配的入站类型做一次有损的跨协议转换

  • 路由由单个布尔 ShouldUseResponsesAPI 决定,在两个分流点以相反含义消费
  • supported=true / 未探测 → 全部走 /v1/responses(Chat Completions 入站被上转)
  • supported=false → 全部走 /v1/chat/completions(Responses 入站被下转)

即便上游双支持,也只能"二选一",无谓地损失原生端点语义。

方案 / Solution

用三态路由解析器 ResolveOpenAITextRoute(extra) → {RouteResponses, RouteChatCompletions, RouteNative} 替换单布尔。RouteNative 按入站类型原生透传,零跨协议转换

  • Responses 入站 → /v1/responses
  • Chat Completions 入站 → /v1/chat/completions

复用已有的原生直转分支(forwardAsRawChatCompletions / 原生 Responses 直转),无需新增转换代码

RouteNative 两种触发方式:

  • 自动auto + 探测确认支持 Responses(openai_responses_supported=true)→ 自动原生透传(不再上转 CC)
  • 手动:账号级新增 native 模式(openai_responses_mode),前端账号创建/编辑弹窗可选

路由映射

mode supported(probe) route
native(新增) 任意 Native
force_responses 任意 Responses
force_chat_completions 任意 ChatCompletions
auto / 缺失 true Native(智能自动,原为 Responses)
auto / 缺失 false ChatCompletions(不变)
auto / 缺失 未探测 Responses(不变,保留存量行为)

OAuth 账号、force_*auto+未探测auto+不支持(如火山方舟工具坏掉)行为均不变。

行为变化 / Behavior change

唯一变化:现有 auto + supported=true 的 APIKey 账号,Chat Completions 入站从"上转 Responses 打 /v1/responses"改为"原生直转 /v1/chat/completions"。对真正双支持的上游更忠实、无损。若个别上游仅暴露 /v1/responses,可用 force_responses 兜底。

验证 / Verification

  • 后端:go test -tags=unit ./internal/pkg/openai_compat/... ./internal/service/... ./internal/handler/... 全绿;golangci-lint run 0 issues
  • 新增 TestResolveOpenAITextRoute 全组合表 + dispatcher 级 TestForwardAsChatCompletions_NativeAndAutoSupportedRouteRawChatCompletions
  • 前端:pnpm typecheck / pnpm lint:check 通过;EditAccountModal.spec.ts 新增 native 用例,18/18 通过

🤖 Generated with Claude Code

StarryKira and others added 2 commits June 17, 2026 06:25
…eam supports both Responses and Chat Completions

Previously OpenAI APIKey routing was governed by a single bool
(ShouldUseResponsesAPI) consumed at two dispatch sites with opposite
meaning. This forced ALL of an account's traffic onto one endpoint and
applied a lossy cross-conversion to the non-matching inbound type, even
when the upstream supports both endpoints.

Replace the bool with a 3-way resolver ResolveOpenAITextRoute ->
{RouteResponses, RouteChatCompletions, RouteNative}. RouteNative passes
each inbound type to its matching upstream endpoint with no conversion:
Responses-in -> /v1/responses, Chat Completions-in -> /v1/chat/completions.

RouteNative is reached two ways:
- smart auto: an account probed as supporting Responses (auto +
  openai_responses_supported=true) now uses native passthrough instead
  of up-converting Chat Completions to Responses
- explicit: a new account-level "native" mode (openai_responses_mode)

force_responses / force_chat_completions, auto+unsupported (CC-only),
auto+unprobed (legacy Responses) and OAuth accounts are unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a "native" choice to the OpenAI APIKey Responses mode selector in the
create/edit account modals, so an admin can force native passthrough
(Responses-in -> /v1/responses, Chat Completions-in -> /v1/chat/completions)
when an upstream supports both endpoints. Includes the OpenAIResponsesMode
type, capability/status labels, en/zh i18n copy, and a component test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 17, 2026 13:29

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@StarryKira

Copy link
Copy Markdown
Contributor Author

问题 / Problem

当 OpenAI APIKey 账号的上游(base_url同时支持 /v1/responses/v1/chat/completions 时,网关此前会把账号的全部流量塞进单一端点,并对不匹配的入站类型做一次有损的跨协议转换

  • 路由由单个布尔 ShouldUseResponsesAPI 决定,在两个分流点以相反含义消费
  • supported=true / 未探测 → 全部走 /v1/responses(Chat Completions 入站被上转)
  • supported=false → 全部走 /v1/chat/completions(Responses 入站被下转)

即便上游双支持,也只能"二选一",无谓地损失原生端点语义。

方案 / Solution

用三态路由解析器 ResolveOpenAITextRoute(extra) → {RouteResponses, RouteChatCompletions, RouteNative} 替换单布尔。RouteNative 按入站类型原生透传,零跨协议转换

  • Responses 入站 → /v1/responses
  • Chat Completions 入站 → /v1/chat/completions

复用已有的原生直转分支(forwardAsRawChatCompletions / 原生 Responses 直转),无需新增转换代码

RouteNative 两种触发方式:

  • 自动auto + 探测确认支持 Responses(openai_responses_supported=true)→ 自动原生透传(不再上转 CC)
  • 手动:账号级新增 native 模式(openai_responses_mode),前端账号创建/编辑弹窗可选

路由映射

mode supported(probe) route
native(新增) 任意 Native
force_responses 任意 Responses
force_chat_completions 任意 ChatCompletions
auto / 缺失 true Native(智能自动,原为 Responses)
auto / 缺失 false ChatCompletions(不变)
auto / 缺失 未探测 Responses(不变,保留存量行为)

OAuth 账号、force_*auto+未探测auto+不支持(如火山方舟工具坏掉)行为均不变。

行为变化 / Behavior change

唯一变化:现有 auto + supported=true 的 APIKey 账号,Chat Completions 入站从"上转 Responses 打 /v1/responses"改为"原生直转 /v1/chat/completions"。对真正双支持的上游更忠实、无损。若个别上游仅暴露 /v1/responses,可用 force_responses 兜底。

验证 / Verification

  • 后端:go test -tags=unit ./internal/pkg/openai_compat/... ./internal/service/... ./internal/handler/... 全绿;golangci-lint run 0 issues
  • 新增 TestResolveOpenAITextRoute 全组合表 + dispatcher 级 TestForwardAsChatCompletions_NativeAndAutoSupportedRouteRawChatCompletions
  • 前端:pnpm typecheck / pnpm lint:check 通过;EditAccountModal.spec.ts 新增 native 用例,18/18 通过

🤖 Generated with Claude Code

这个runner怎么奇奇怪怪的 网络错误无法lint

@StarryKira

Copy link
Copy Markdown
Contributor Author

@Wei-Shaw

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants