xlplbo
df8eceba0c
fix(apicompat): chat 桥保留 Codex agent_message 任务正文
2026-09-10 20:25:38 +08:00
xlplbo
95a04c8dff
test(apicompat): additional_tools 走 chat 桥的回归用例
2026-09-10 19:50:26 +08:00
Wesley Liddick
8116d235ef
Merge pull request #6629 from superdav42/fix/preserve-function-arguments-done
...
fix(apicompat): preserve function arguments from done events
2026-09-07 17:36:10 +08:00
David Stone
6271c517da
fix(apicompat): preserve arguments from done events
2026-09-04 21:18:36 -06:00
wucm667
51631d0324
fix(apicompat): preserve discovered tools in chat fallback
2026-09-04 18:33:23 +08:00
li
8f5451587e
fix(apicompat): Anthropic→Responses 流式转换在 thinking 块前关闭 message item 并推进 content_index
...
thinking 块开始时不关闭已打开的 message item,直接覆盖 CurrentItemType/
CurrentItemID,累积的助手文本既不进 state.Outputs 也拿不到 output_item.done,
response.completed 只带 reasoning——客户端收到「成功但无输出」。同 switch 的
tool_use 分支本来就先调 closeCurrentResponsesItem,只有 thinking 漏了。
content_index 只在 item 打开时置 0,从不推进。同一 message item 里第二个 text
块会再发一次 content_part.added(content_index=0),与第一个 part 撞在同一下标,
SDK 累积式 helper 按 content[content_index] 写入时后者覆盖前者。反方向
responses_to_anthropic.go 有三处 ContentBlockIndex++,正方向一处都没有。
新增用例覆盖两条坏顺序,外加一条生命周期不变式用例(output_item.added 与
output_item.done 必须配平、terminal 事件按announce 顺序逐项携带)。
2026-08-31 16:15:08 +08:00
wucm667
5345881b1d
Merge remote-tracking branch 'upstream/main' into fix/issue-5843-antigravity-mixed-tools
...
# Conflicts:
# backend/internal/repository/group_usage_rollup_trigger_integration_test.go
2026-08-28 17:36:43 +08:00
Wesley Liddick
f7dca22ea5
Merge branch 'main' into fix/responses-synthesized-created-at
2026-08-28 12:05:38 +08:00
Wesley Liddick
002aaaa3d0
Merge branch 'main' into fix/anthropic-chat-bridge-reasoning-passback
2026-08-28 11:55:10 +08:00
li
4a02e54171
Merge remote-tracking branch 'origin/main' into fix/anthropic-chat-bridge-reasoning-passback
2026-08-27 13:40:29 +08:00
li
9192426d2e
merge: 合入 origin/main,与新增的 service_tier 字段并存
...
主线在 ResponsesResponse 与两处流式事件上新增了 service_tier;本分支新增的
created_at 与之并列,无语义冲突。同时跟进 ChatCompletionsResponseToResponses
新增的 functionTools 形参。
2026-08-27 13:40:07 +08:00
wucm667
50ba146298
fix(openai): preserve multimodal client tool outputs
2026-08-26 15:04:17 +08:00
Wesley Liddick
e8cb019fab
Merge pull request #6078 from YogaSakti/fix/responses-custom-tool-call-id
...
fix(openai): keep restored tool-call item IDs typed
2026-08-25 21:32:34 +08:00
Wesley Liddick
bd17411d0e
Merge pull request #6129 from alfadb/feature/openai-fast-service-tier
...
feat(openai): Fast 档位请求校验、响应透传与按上游实际档位计费
2026-08-24 14:16:47 +08:00
Wesley Liddick
b8651947c3
Merge pull request #6137 from yan9651688/codex/fix-cn-anthropic-usage-billing
...
fix(billing): normalize CN Anthropic usage tokens
2026-08-24 14:09:45 +08:00
yan9651688
695ebede70
fix(billing): normalize CN Anthropic usage tokens
2026-08-24 13:05:12 +08:00
alfadb
1591477a3e
test(apicompat): adapt ChatCompletionsResponseToResponses call to upstream functionTools signature
2026-08-24 11:58:01 +08:00
alfadb
f06bf181d2
feat(openai): support Fast mode service_tier across responses/chat/WS paths
...
- Accept fast|priority (canonical priority), flex|auto|default|scale on
/v1/responses and /v1/chat/completions; reject unknown/empty/non-string
with HTTP 400; omitted and null stay compatible.
- Propagate service_tier through JSON/SSE, Responses<->Chat conversions,
fallback paths and HTTP->upstream WebSocket bridge.
- Billing prefers the upstream terminal tier; the outbound (policy-
transformed) tier is used only when upstream omits the field.
Explicit upstream default bills Standard even when Fast was requested.
- Pricing: Fast premium 2x Standard for gpt-5.6-sol/terra/luna and
gpt-5.4; 2.5x for gpt-5.5; channel FastMultiplier stays authoritative.
- Live verification (official Codex 0.149.0 + gateway, HTTP & WS):
upstream ChatGPT backend may return terminal default even when the
account catalog advertises priority; billing follows the actual tier.
2026-08-24 11:52:48 +08:00
Wesley Liddick
f25f399be0
Merge pull request #5905 from wucm667/fix/issue-5883-restore-custom-tool-alias
...
fix(openai): restore namespaced custom tool aliases
2026-08-24 11:23:37 +08:00
wucm667
4eadee1074
[verified] test(openai): update responses bridge signature
2026-08-23 08:45:04 +08:00
wucm667
31d5b67baa
fix(openai): restore namespaced custom tool aliases
2026-08-23 08:11:20 +08:00
wucm667
7a09a2eaf7
fix(responses): remove orphan deferred tool flags
2026-08-22 16:42:56 +08:00
Yoga Sakti
e0e5e45cd2
fix(openai): keep restored tool-call item IDs typed
...
The Responses client-tool restore raised an upstream function_call back to
custom_tool_call and tool_search_call without touching its item ID, so the
client received a custom_tool_call carrying the upstream's fc_ ID. That
combination is invalid: once the item lands in the client's history, any
later replay to an upstream that validates item IDs fails the whole request
with "Invalid 'input[N].id': 'fc_...'. Expected an ID that begins with
'ctc'", and every following message re-submits the same bad item.
Re-prefix the ID to match the type it is raised to, keeping the suffix so
the ID stays stable and unique per upstream item. IDs without a known
tool-call prefix are left alone rather than guessed at.
The lowering direction has to reverse this, because the WebSocket HTTP
bridge replays restored items back to the upstream and would otherwise lose
the upstream's own ID. normalizeLoweredFunctionItemID now maps a ctc_/tsc_
call ID back to fc_ instead of dropping it, which makes the round trip
lossless; output item IDs (ctco_/tso_) still have no function-protocol
counterpart and are still dropped. The helper was renamed from
dropInvalidLoweredFunctionItemID to match what it now does.
The stream restorer keeps the upstream ID for its own bookkeeping so later
upstream events still match the call, and emits the client-facing ID on
output_item.added/done and the custom_tool_call_input events.
Closes #6071
2026-08-22 14:03:25 +07:00
Wesley Liddick
fd6cd474d6
Merge pull request #5846 from lbyxiaolizi/fix/responses-chat-malformed-tool-arguments
...
fix(apicompat): reject malformed tool-call arguments
2026-08-22 13:35:02 +08:00
Wesley Liddick
6244090c1c
Merge pull request #5487 from an-epiphany/fix/file-part-min
...
fix(apicompat): chat/completions 的 file part 转换为 Responses input_file,不再静默丢弃
2026-08-22 13:34:18 +08:00
Wesley Liddick
f646a1f974
Merge pull request #5632 from 3219378872/fix/apicompat-streaming-tool-name-empty
...
fix(apicompat): omit empty tool name on streamed arguments deltas
2026-08-21 17:49:55 +08:00
Nai Long 7th
9ede0f7165
fix(grok): promote tool-search discoveries into callable tools
2026-08-20 12:37:39 +08:00
Nai Long 7th
5b2089c5a3
fix(grok): lower Codex tool-search discovery outputs
2026-08-20 06:55:47 +08:00
wucm667
b1737cc841
fix(antigravity): preserve mixed built-in chat tools
2026-08-20 00:29:33 +08:00
lbyxiaolizi
fbc9ee626d
fix(apicompat): narrow malformed tool-call handling
2026-08-19 20:49:31 +08:00
lbyxiaolizi
e2d9ce0cad
fix(apicompat): reject malformed tool-call arguments
2026-08-19 18:48:35 +08:00
hansnow
fefd0d5145
test(apicompat): avoid unchecked tool history assertions
2026-08-19 15:31:18 +08:00
hansnow
e4896c41d2
test(apicompat): satisfy client tool type assertions
2026-08-19 15:26:19 +08:00
hansnow
b94e484e23
fix(openai): preserve client tools across WS bridge turns
2026-08-19 15:19:33 +08:00
Wesley Liddick
e943f817b1
Merge pull request #5729 from lbyxiaolizi/fix/responses-chat-reasoning-content-passback
...
fix(openai-compat): Responses→Chat 桥接按 reasoning item id 缓存回注 reasoning_content (#5520 )
2026-08-19 14:03:03 +08:00
hansnow
c253bd2c72
fix(openai): restore client tools in terminal events
2026-08-18 15:48:02 +08:00
lbyxiaolizi
401dd43b4b
fix(apicompat): 链式工具调用回放本轮 reasoning_content
...
codex 0.147.0 真实 resume 历史复现:DeepSeek 每轮只在开头流式产生一次
reasoning,reasoning → call A → output A → call B 的链式调用中 call B 前
没有 reasoning item,其 assistant 消息缺 reasoning_content,DeepSeek
thinking mode 400 整个历史。
buildChatMessagesFromItems 新增 lastTurnReasoning:记录本轮最近一次
reasoning,跨 tool output 存活,仅被 user 侧 item 清除;assistant 消息
(文本或 tool_calls)在 pendingReasoning 为空时回放本轮 reasoning。
2026-08-17 18:51:17 +08:00
lbyxiaolizi
612436a5a7
fix(openai-compat): Responses→Chat 桥接按 reasoning item id 缓存回注 reasoning_content
...
修复 #5520:Codex 经 force_chat_completions 桥接到 DeepSeek thinking 上游时,
历史中的 encrypted-only reasoning item(summary 为空 + 不透明 encrypted_content,
远程 compaction / 跨会话恢复后常见)取不出明文,后续 assistant 消息缺
reasoning_content,DeepSeek 400 "The reasoning_content in the thinking mode
must be passed back to the API",客户端仅看到通用 502。
reasoning item 的 id 一定会被客户端回传,以其为 key 做服务端缓存:
- GatewayCache 新增 Set/GetReasoningContent(Redis,默认 TTL 7 天)
- 响应侧:流式扫 response.output_item.done、非流式扫 output,把 reasoning
全文按 item id 写缓存;客户端断连后 drain 期间用 detached ctx 仍会写完
- 请求侧:apicompat 新增 ResponsesToChatCompletionsRequestWithOptions 与
ReasoningContentByID 钩子,encrypted-only item 查缓存补回 pendingReasoning;
缓存 miss/出错一律 fail-open 维持原行为
- 自愈:历史里带明文 summary 的 reasoning item 顺手刷新缓存,覆盖 Redis
flush / 跨实例漂移
测试:apicompat(命中恢复/miss 保持原样/明文优先)、service 端到端(流式
写缓存、请求侧回注+自愈)、repository miniredis 存取。
2026-08-17 16:48:36 +08:00
风起
bafd2e293f
fix(apicompat): omit empty tool name on streamed arguments deltas
...
The responses->chat streaming converter re-emits the tool name as an empty
string on every function_call_arguments.delta because ChatFunctionCall.Name
has no omitempty. OpenAI-compatible clients accumulate the name from the
first tool-call delta, so the trailing "name":"" overwrites it and the
call fails dispatch (unknown tool ""). Empty names also break the next
round-trip upstream (missing field 'name').
Fixes #5631
2026-08-14 06:32:38 +00:00
li
3c5553e253
fix(responses): 网关合成的 Responses 对象补齐 created_at,修复严格客户端反序列化失败
...
严格的 Responses 客户端(Rust serde 系,如 Codex / Grok CLI)把 created_at 声明为
必填字段,缺失即 `missing field 'created_at'` 直接读不出响应。
apicompat.ResponsesResponse 此前根本没有这个字段,六个构造点全部不写:
Chat→Responses 与 Anthropic→Responses 两座桥的非流式结果、response.created、
终止事件,以及两处手写的 response.failed 帧。
两个流式 state 早就在 New*State() 里采集了 Created 时间戳,只是没有出口——
反方向(Responses→Chat)每个 chunk 都老老实实发 created,正方向直接丢在地上。
原生 Responses 透传走 gjson/sjson 字节级改写,保留上游原样,不受影响;
本次只补合成路径。
Fixes #5601
2026-08-14 11:05:29 +08:00
li
901a77cfb1
fix(apicompat): Anthropic→Chat 桥回传工具调用的 thinking,修复 DeepSeek 多轮 400
...
/v1/messages 打到只支持 Chat Completions 的 OpenAI 兼容上游时,
anthropicAssistantToChatMessages 把历史 assistant 消息里的 thinking 块整块丢弃。
DeepSeek 的 thinking mode 要求产生工具调用的 reasoning_content 随该 assistant
消息回传,缺失即 400 —— 表现为「单轮正常,一进多轮工具对话必现失败」。
这些 thinking 块本来就是同一个文件的出站方向
(chatMessageToAnthropicBlocks) 用上游 reasoning_content 生成的,客户端只是
原样回传:桥自己造出来的东西,回来时被自己丢掉。
兄弟路径 Responses→Chat (buildChatMessagesFromItems 的 pendingReasoning) 早已
处理同一约束。本次把同一策略补到漏掉的这条桥上,作用域严格对齐:reasoning 只挂
到带 tool_calls 的 assistant 消息,纯文本轮次维持现状。
Fixes #5528
2026-08-14 10:33:47 +08:00
IanShaw027
c4d883b8da
feat: Chat 与 Responses 往返保留 x_search,并补 sources 抽取
...
Chat Completions 的 {"type":"x_search"} 会被 apicompat 丢掉,独立
/x_search 又没带 include 与结构化提示,主路径容易返回空结果仍计费。
- Chat↔Responses 保留 x_search 过滤字段与 tool_choice
- declared 只注册实际存活的 x_search,web_search 选择项仍丢弃
- 上游补 include x_search_call.action.sources 与结构化输出提示
2026-08-13 08:37:57 +08:00
Wesley Liddick
6876477371
Merge pull request #5304 from wucm667/fix/issue-5302-chat-reasoning-alias
...
fix(apicompat): accept chat reasoning alias
2026-08-11 13:59:49 +08:00
Pengap
4d4a0be1ad
fix(apicompat): chat/completions file part 不再被静默丢弃,转换为 Responses input_file
...
/v1/chat/completions → Responses 转换层此前只处理 text 和 image_url 两种
content part,type:"file"(PDF 附件)被静默丢弃:请求返回 200、模型正常
回答,但 prompt 里没有文件(prompt_tokens 只剩纯文字)。
现将 file part 映射为 Responses API 的 input_file(filename/file_data/
file_id 透传),与同网关 /v1/responses + input_file 实测可用的格式一致。
无 file_data 且无 file_id 的空 file part 跳过,与空 image URL 行为一致。
参考上游 PR #2497(因混入无关改动未合并)。
2026-08-10 13:59:20 +08:00
li
64090de664
fix(apicompat): Responses→Anthropic 转换不再发出上游会拒收的 content block
...
convertResponsesInputToAnthropic 的 default 分支把未知 item 的 content 逐字
透传成 Anthropic user 消息,Responses 专有的分片类型会原样进入上游请求体。
最典型的是工具执行后回放的 reasoning item:带 content 数组时,reasoning_text
块直接发给 Anthropic,上游回 400 Request body format invalid,而该 item 会一直
留在会话历史里,导致此后每一轮都继续失败。
同时修正两处会产出空内容消息的路径——Anthropic 拒收空内容消息与空白 text 块:
分片全部不可识别时,user 消息退化成 content:""、assistant 消息退化成单个空
text 块。
改动:
- type=reasoning 显式跳过。Anthropic 无法摄入 OpenAI reasoning:encrypted_content
不透明,thinking 重放需要上游签发的 signature。Codex 常见形态(只带 summary +
encrypted_content)本来就会被丢弃,这里让带 content 的形态行为一致。
- default 分支改走 convertResponsesUserToAnthropicContent 白名单转换,保留其中
可识别的文本/图片,丢弃其余分片。
- user / assistant 分支在转换结果为空内容或纯空白文本时跳过该消息。
Fixes #5329
2026-08-07 23:09:03 +08:00
wucm667
8aa425d22f
fix(apicompat): accept chat reasoning alias
2026-08-05 18:25:58 +08:00
tudoujun
2bf9c6d56b
修复工具输出图片桥接
2026-07-31 19:36:47 +08:00
Ricardo-binZzz
7dde9370e4
Codex++ Responses<->Anthropic compatibility fixes
...
Namespace tool flatten/restore, array function_call_output, omit empty input_schema for native tools, lift additional_tools; scoped to ForwardAsResponses.
2026-07-27 08:19:19 +08:00
superman2003
f8445a241b
fix(grok): round-trip Codex client tools on Responses
2026-07-22 12:15:48 +08:00
shaw
3c41984733
style(apicompat): gofmt types.go after merge
2026-07-20 11:47:13 +08:00