Commit Graph
642 Commits
Author SHA1 Message Date
Wesley Liddick 002aaaa3d0 Merge branch 'main' into fix/anthropic-chat-bridge-reasoning-passback 2026-08-28 11:55:10 +08:00
Wesley Liddick 28fa458dc7 Merge branch 'main' into fix/issue-6240-preserve-multimodal-tool-output 2026-08-28 11:37:40 +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
shaw 8ba81615e0 merge: resolve conflict with main (upstream endpoint observability)
Merge origin/main into contrib/routed-codex-model-catalog.

Single conflict in openai_gateway_forward.go: main added
ClearActualOpenAIUpstreamEndpoint + SetActualOpenAIUpstreamEndpoint
(commit 4795650d2) at the same insertion point where the PR added
filterOpenAIResponsesNoneReasoningEffortForAccount. Both changes
are independent — endpoint observability first, then body filtering.
2026-08-26 15:29:01 +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
Long LiandCursor 77b6c5bb0c merge: sync contrib/routed-codex-model-catalog with upstream v0.1.182
Keep catalog membership on schedulable accounts and intersect advertised
capabilities across all active group members that map an alias. Preserve
upstream plugin, service-tier, and models-list body-limit changes.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-25 21:28:57 +09:00
shaw 9fb260439f fix(grok): use official CLI user agent 2026-08-24 22:14:45 +08:00
Wesley Liddick c40edb4070 Merge pull request #6139 from xz-dev/fix/configurable-model-list-read-limit
feat(gateway): configure model list read limit
2026-08-24 15:04:50 +08:00
Xiangzhe 847c0c4526 feat(gateway): configure model list read limit
Add gateway.models_list_read_max_bytes with the existing 8 MiB behavior as its default, and apply it consistently to generic, Codex, and Antigravity model-list reads.

Read one sentinel byte for Codex manifests so oversized responses return an explicit bounded upstream error instead of malformed JSON.
2026-08-24 14:20:18 +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 c4ae3550dd Merge pull request #6119 from feeeei/feat/go1.27.0
feat(go1.27.0): 升级 Go 1.27.0,默认启用 jsonv2 ,并同步 CI/Dockerfile
2026-08-24 14:11:03 +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
feeeei 73aabc861c build: 取消 gosec G703/G704 全局排除,生产代码逐点 nolint、测试文件按路径豁免;DEV_GUIDE 同步 golangci-lint v2.13 2026-08-24 12:21:06 +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
Long Li e471be7302 feat(codex): complete routed model catalogs
Codex treats the downloaded model catalog as a capability contract. Slug-only entries hide supported reasoning levels, can advertise invalid image inputs, and expose automatic or media-only models in the model picker. Generate complete route-aware metadata, preserve official manifests, filter non-agent models, and compute validators from the final catalog.
2026-08-22 14:43:40 +09: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 844b118785 Merge pull request #5938 from Hakunm/fix/google-one-model-catalog
fix(gemini): 限制 Google One OAuth 模型目录 / constrain Google One model catalog
2026-08-22 13:34:05 +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
Wesley Liddick 4eb7630ab5 Merge pull request #5625 from sweetcornna/fix/antigravity-official-daily-endpoint
fix(antigravity): use official daily endpoint
2026-08-21 17:40:29 +08:00
Hakunm f98a056f75 fix(gemini): constrain Google One model catalog 2026-08-21 02:33:00 +08:00
IanShaw 2e68b10aad 完善 Grok 内容拒绝计费与媒体兼容 2026-08-20 09:12:52 -07:00
IanShaw 39485f2e28 更新 Grok 默认模型与官方计费目录 2026-08-20 02:32:22 -07:00
IanShaw ed4207a16f 校正 Grok 模型目录计费与工具出站 2026-08-20 01:03:29 -07: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
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
Wesley Liddick 58ccea4eaa Merge pull request #5767 from hansnow/fix/ws-http-bridge-custom-tools
fix(openai): 补齐客户端工具终止事件恢复
2026-08-18 16:21:50 +08:00
hansnow c253bd2c72 fix(openai): restore client tools in terminal events 2026-08-18 15:48:02 +08:00
Wesley Liddick 37732dcd34 Merge pull request #5725 from tamseno/fix/gemini-include-server-side-tool-invocations
fix(gemini): support includeServerSideToolInvocations in GeminiToolConfig
2026-08-18 15:35:01 +08:00
yaxin 1ba92449c7 fix(gemini): wire includeServerSideToolInvocations into the typed transform path
The struct field alone never reached the wire: the raw passthrough
pipeline is covered by enableMixedGeminiToolInvocations (#5711), but
TransformClaudeToGeminiWithOptions builds GeminiToolConfig from scratch
and never set the flag, so gemini-* models entering through the Claude
format gateway could still hit the upstream 400 from issue #5709.

- Set IncludeServerSideToolInvocations=true when the built tool
  declarations mix functionDeclarations with googleSearch, matching the
  raw-path injection semantics.
- Replace the marshal-roundtrip-only test with behavior tests that
  drive TransformClaudeToGeminiWithOptions: mixed tools set the flag,
  function-only and web-search-only requests leave it unset.
2026-08-18 15:05:54 +08:00
o2e 16e4f7ecc3 修复 Codex 额度探针模型兼容性 2026-08-18 13:08:28 +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
Tamseno 3c3bb2fa19 fix(gemini): support includeServerSideToolInvocations in GeminiToolConfig
- Add IncludeServerSideToolInvocations field to GeminiToolConfig to prevent dropping client tool settings.
- Fix HTTP 400 error when mixing built-in tools (e.g. Google Search) with function calling on Gemini 3.6/3.7 models.
- Add serialization/deserialization unit test TestGeminiToolConfig_IncludeServerSideToolInvocations.

Fixes #5709
2026-08-17 15:23:49 +08:00
lyen1688 cb7b03795d feat: 优化分组用量统计 2026-08-14 22:34:43 +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