fix: support codex alpha search relay#6263
Conversation
WalkthroughAdds Codex Alpha Search request contracts, routes, relay-mode classification, upstream adaptors, response forwarding, and quota billing. Requests are validated, normalized, sent to supported upstream endpoints, and billed as one tool call. ChangesCodex Alpha Search relay
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Client
participant Router
participant Relay
participant Upstream
participant Billing
Client->>Router: POST /alpha/search
Router->>Relay: Validate and dispatch request
Relay->>Upstream: Send normalized Alpha Search request
Upstream-->>Relay: Return JSON response
Relay->>Billing: Consume one Alpha Search quota call
Relay-->>Client: Forward response
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
df4f432 to
93dacf1
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
relay/channel/codex/adaptor.go (1)
187-233: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueInline the single-use header manipulation helper.
As per coding guidelines: "Avoid package-level or module-level helpers with only one caller unless they express a stable business concept; inline single-use mechanical logic instead."
The
setupCodexAlphaSearchHeadersfunction is only called here and performs strictly mechanical header manipulation. Please inline it directly intoSetupRequestHeaderto eliminate the unnecessary indirection.♻️ Proposed refactor to inline the mechanical logic
- if info.RelayMode == relayconstant.RelayModeCodexAlphaSearch { - setupCodexAlphaSearchHeaders(c, req) - } else if req.Get("OpenAI-Beta") == "" { + if info.RelayMode == relayconstant.RelayModeCodexAlphaSearch { + req.Del("OpenAI-Beta") + req.Del("Session_ID") + req.Del("Conversation_ID") + req.Del("X-Codex-Beta-Features") + req.Del("X-Codex-Turn-State") + + if c != nil && c.Request != nil { + for _, name := range []string{ + "Version", + "User-Agent", + "Session_id", + "X-Client-Request-Id", + "X-Codex-Turn-Metadata", + } { + if value := strings.TrimSpace(c.GetHeader(name)); value != "" { + req.Set(name, value) + } + } + } + } else if req.Get("OpenAI-Beta") == "" { req.Set("OpenAI-Beta", "responses=experimental") } if req.Get("originator") == "" { req.Set("originator", "codex_cli_rs") } // chatgpt.com/backend-api/codex/responses is strict about Content-Type. // Clients may omit it or include parameters like `application/json; charset=utf-8`, // which can be rejected by the upstream. Force the exact media type. req.Set("Content-Type", "application/json") if info.RelayMode == relayconstant.RelayModeCodexAlphaSearch { req.Set("Accept", "application/json") } else if info.IsStream { req.Set("Accept", "text/event-stream") } else if req.Get("Accept") == "" { req.Set("Accept", "application/json") } return nil } - -func setupCodexAlphaSearchHeaders(c *gin.Context, req *http.Header) { - req.Del("OpenAI-Beta") - req.Del("Session_ID") - req.Del("Conversation_ID") - req.Del("X-Codex-Beta-Features") - req.Del("X-Codex-Turn-State") - - if c == nil || c.Request == nil { - return - } - - for _, name := range []string{ - "Version", - "User-Agent", - "Session_id", - "X-Client-Request-Id", - "X-Codex-Turn-Metadata", - } { - if value := strings.TrimSpace(c.GetHeader(name)); value != "" { - req.Set(name, value) - } - } -}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@relay/channel/codex/adaptor.go` around lines 187 - 233, Inline the logic from setupCodexAlphaSearchHeaders directly into its sole caller, SetupRequestHeader, within the RelayModeCodexAlphaSearch handling. Preserve the existing header deletions, nil-request guards, and forwarded header values, then remove the now-unused helper function.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@relay/alpha_search_handler.go`:
- Around line 32-33: Update the JSON parsing in the handler’s body-normalization
flow and the additional marshal/unmarshal call sites to use the repository
wrappers from common/json.go instead of the standard json package directly.
Preserve the existing validation and normalized output behavior while routing
all business-code serialization through those wrappers.
In `@service/tool_billing.go`:
- Around line 101-105: Update the billing flow around ComputeToolCallQuota to
use checked quota conversion and checked integer addition, rejecting
non-positive, NaN, or infinite group ratios and preventing negative or
overflow-derived charges. Propagate any conversion clamp into
relayInfo.QuotaClamp before calling attachQuotaSaturation, while preserving the
existing counter update flow only for valid checked results.
---
Nitpick comments:
In `@relay/channel/codex/adaptor.go`:
- Around line 187-233: Inline the logic from setupCodexAlphaSearchHeaders
directly into its sole caller, SetupRequestHeader, within the
RelayModeCodexAlphaSearch handling. Preserve the existing header deletions,
nil-request guards, and forwarded header values, then remove the now-unused
helper function.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 46fb0589-4020-4456-9123-d2b71a2668b0
📒 Files selected for processing (16)
controller/relay.godto/codex_alpha_search.gomiddleware/distributor.gorelay/alpha_search_handler.gorelay/channel/codex/adaptor.gorelay/channel/openai/adaptor.gorelay/channel/openai/relay_alpha_search.gorelay/common/relay_info.gorelay/common/request_conversion.gorelay/constant/relay_mode.gorelay/helper/valid_request.gorouter/relay-router.gorouter/web-router.goservice/tool_billing.gosetting/operation_setting/tools.gotypes/relay_format.go
93dacf1 to
2690764
Compare
2690764 to
b41e1c4
Compare
|
根本无法确认上游兼容openai端点是否支持搜索,你这样打到非codex直接报错,这样的适配不可接受 |
Important
📝 变更描述 / Description
(简述:做了什么?为什么这样改能生效?请基于你对代码逻辑的理解来写,避免粘贴未经整理的内容)
修复 Codex CLI 在 GPT-5.6 / Responses Lite 场景启用 web search 时,请求在 new-api 中无法进入 relay 链路的问题。
根据 #6114 的复现,Codex CLI 会向 provider
base_url发起独立的:POST /v1/alpha/search这个请求不是普通 /v1/responses 请求体中的 hosted web_search tool,而是 Codex CLI 在 GPT-5.6 相关模式下使用的 standalone alpha search 端点。new-api 原本没有注册和处理该路径,请求会落到 NoRoute,最终返回 404 Invalid URL (POST /v1/alpha/search)。
主要变更:
注册 /v1/alpha/search、/alpha/search、/backend-api/codex/alpha/search。
新增 Codex alpha search 请求 DTO,用请求中的 model 参与模型映射、渠道选择和计费。
OpenAI 兼容渠道转发到 /v1/alpha/search。
Codex 渠道转发到 /backend-api/codex/alpha/search。
避免 /alpha/search 被前端 SPA fallback 捕获。
为 alpha search 成功调用补充独立的工具调用计费记录。
🚀 变更类型 / Type of change
🔗 关联任务 / Related Issue
✅ 提交前检查项 / Checklist
Bug fix,我已提交或关联对应 Issue,且不会将设计取舍、预期不一致或理解偏差直接归类为 bug。📸 运行证明 / Proof of Work
(请在此粘贴截图、关键日志或测试报告,以证明变更生效)


[INFO] 2026/07/17 - 17:01:39 | ... | record consume log: userId=1, params={... "model_name":"gpt-5.6-sol", ... "codex_alpha_search":true, "request_path":"/v1/alpha/search", ... "web_search_call_count":1 ...}
[GIN] 2026/07/17 - 17:01:39 | relay | | 200 | 1.892889174s | 172.18.0.1 | POST /v1/alpha/search
Summary by CodeRabbit
/v1/alpha/search,/alpha/search, and backend-compatible endpoints.Accepthandling for Alpha Search.