fix(gateway): 剥离 Cursor raw body 透传路径中 Codex 不支持的 Responses API 参数

在前一个 commit 的 isResponsesShape 短路路径基础上,补充对 Cursor 云端
带过来的、Codex 上游统一不支持的顶层 Responses API 参数的剥离:

  - prompt_cache_retention
  - safety_identifier
  - metadata
  - stream_options

根因补充:这条 raw-body 透传路径为了保留 Cursor 的 input 数组整体结构,
不再经过 ChatCompletionsRequest 的反序列化过滤,所以这些 Go 结构体里
没有对应字段的参数会被原样发到上游,上游返回:
    Unsupported parameter: <field>
常规 Chat Completions 转换路径天然通过 ChatCompletionsRequest 丢弃未知字段,
不受影响;此处仅在 isResponsesShape 分支内用 sjson.DeleteBytes 显式过滤,
作用域最小。剥离列表与 openai_gateway_service.go:2034 的
unsupportedFields 语义对齐。

另外在 applyCodexOAuthTransform 的 OAuth 兜底 strip 列表里同步追加
prompt_cache_retention,作为对该函数所有其他 OAuth 调用点的 defense
in depth(当前只有 Cursor 路径的短路已在前面剥过,但保留这一层更稳)。

测试:
- TestCursorMixedShape_StripsUnsupportedFields — 验证所有 4 个字段都被剥
- TestApplyCodexOAuthTransform_StripsPromptCacheRetention — OAuth 兜底路径

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
shuanbao0
2026-04-11 22:48:45 +08:00
parent b7edc3ed82
commit 422e25c99f
4 changed files with 98 additions and 0 deletions

View File

@@ -124,6 +124,14 @@ func applyCodexOAuthTransform(reqBody map[string]any, isCodexCLI bool, isCompact
"top_p",
"frequency_penalty",
"presence_penalty",
// prompt_cache_retention is a newer Responses API parameter (cache TTL).
// The ChatGPT internal Codex endpoint rejects it with
// "Unsupported parameter: prompt_cache_retention". Defense-in-depth
// for any OAuth path that reaches this transform — the Cursor
// Responses-shape short-circuit in ForwardAsChatCompletions strips
// it earlier too, but we keep this line so other OAuth callers are
// equally protected.
"prompt_cache_retention",
} {
if _, ok := reqBody[key]; ok {
delete(reqBody, key)