Commit Graph
4289 Commits
Author SHA1 Message Date
xlplbo 75fb3c41c2 fix(apicompat): responses→chat 桥支持 custom 工具,修复 Codex exec 丢失
Codex 0.14x 的核心执行工具 exec 是 type=custom(freeform)工具,
responsesToolsToChatTools 丢弃所有非 function 工具,导致模型工具列表中
没有 exec、无法执行任何命令;SSE 序列化层 responsesItemWire 也缺少
custom_tool_call 分支,即使产出该类型 item,call_id/name/input 也会被
白名单剥离。

- custom 工具降级为单一 input:string 参数的 function 工具
- 回程(非流式+流式)按名字还原 custom_tool_call 项/事件
- 历史 custom_tool_call / custom_tool_call_output 项转换(此前被跳过)
- responsesItemWire 补 custom_tool_call 分支
- tools 全部被丢弃时不再转发 tool_choice(修复上游 400
  "'tool_choice' is only allowed when 'tools' are specified")

feat(apicompat): chat 桥补齐 tool_search/namespace/字符串工具声明

对齐参考实现(cc-switch transform_codex_chat.rs)的工具类型覆盖:
- tool_search → 固定 function 代理工具(query 必填/limit 可选),
  历史项 tool_search_call/tool_search_output 一并转换
- namespace → 子 function 工具摊平为 <namespace>__<name>,
  超 64 字符截断加 sha256 短哈希;历史项带 namespace 字段时同规则摊平
- tools: ["name"] 字符串简写按 custom 工具解析

fix(apicompat): 工具调用宣告延迟到类型可判定,兼容 name 迟到的上游

output_item.added 的 custom/function 判定依赖工具名。名字晚于首个分片
到达时,此前会按 function_call 宣告造成 added/done 项类型不一致。
改为存在 custom 工具且名字未到时延迟宣告,宣告时补发已累积的参数增量;
请求无 custom 工具时行为不变。

PR 标题与正文(可直接粘贴)

标题:fix(apicompat): responses→chat 桥丢弃 custom 工具导致 Codex 无法执行命令

正文:

## 问题

OpenAI APIKey 账号接入仅支持 /v1/chat/completions 的第三方上游
(DeepSeek/GLM/Kimi 等)时,Codex 0.14x 客户端文本对话正常,但无法执行
任何命令:exec 调用全部 "aborted",spawn_agent 派出的子智能体永远卡在
running,多轮后模型自述"环境无法执行文件系统命令"放弃。

## 根因

Codex 0.14x 的核心执行工具 exec 是 Responses API 的 custom(freeform)
工具,而非普通 function:

    {"type": "custom", "name": "exec", "format": {"type": "grammar", ...}}

两处缺陷叠加:

1. `responsesToolsToChatTools` 丢弃所有非 function 工具
   (chatcompletions_responses_bridge.go),模型工具列表中从未出现 exec;
2. SSE 序列化 `responsesItemWire` 按 item 类型白名单重组字段,无
   custom_tool_call 分支,call_id/name/input 会被剥离
   (responses_stream_event_wire.go)。

次生缺陷:工具全部被丢弃时 tool_choice 仍被转发,部分上游报 400
"'tool_choice' is only allowed when 'tools' are specified"。

## 改动

(三个提交的要点清单,见各提交说明)

设计与 cc-switch 的 Codex chat 转换层(transform_codex_chat.rs /
streaming_codex_chat.rs)对齐:custom 工具降级为 {"input": string}
function 工具;custom 调用的参数增量不可流式还原为自由文本,缓冲至
收尾一次性下发 custom_tool_call_input.delta/done。

## 测试

- 新增 17 个单元测试:请求工具转换、tool_choice 兜底、历史项转换、
  非流式/流式回程还原、wire 序列化字段完整性、name 迟到宣告、命名摊平
- `go test ./internal/pkg/apicompat/...` 与 service 相关测试全绿
- 真机验证:Codex CLI 0.142.5 → 本桥 → GLM/DeepSeek 系 chat-only 上游,
  exec 实际执行命令并多轮续作正常

## 影响面

仅影响 "APIKey 账号 + 判定不支持 Responses" 的 chat 直转路径:

- OAuth 账号与透传路径不经过本桥(透传为字节级原文转发)
- CC→Responses 反方向仅构造 ResponsesRequest,新增字段带 omitempty
  且不赋值,序列化输出不变
- 探测逻辑未动,路由判定不变
- 共享类型改动均为增量容错(新字段 omitempty;UnmarshalJSON 只新增
  字符串工具的解析成功路径)
2026-07-07 16:23:44 +08:00
Wesley Liddick db9d92ba8f Merge pull request #3762 from jianjianai/fix/add-chinese-comments
优化 Redis SCAN 清理架构
2026-07-07 09:36:20 +08:00
shaw 7c8e13208b style: replace interface{} with any per golangci-lint gofmt rewrite rules 2026-07-07 09:32:15 +08:00
shaw d37d216f9d Merge remote-tracking branch 'origin/main' into pr-3762
# Conflicts:
#	backend/internal/repository/concurrency_cache.go
#	backend/internal/repository/concurrency_cache_integration_test.go
2026-07-07 09:22:44 +08:00
Wesley Liddick 96f3697ecb Merge pull request #3767 from qqqianye/fix/admin-account-compact-probe
fix(frontend): add compact probe mode to admin account test modal
2026-07-07 09:09:05 +08:00
Wesley Liddick 42ecbeb8c6 Merge pull request #3769 from Wei-Shaw/chore/renew-xlsx-audit-exceptions
chore: renew expired xlsx audit exceptions to 2026-10-06
2026-07-07 08:47:48 +08:00
shaw a564051f83 chore: renew expired xlsx audit exceptions to 2026-10-06
xlsx is frozen at 0.18.5 on the npm registry (fixed versions are only
published on the SheetJS CDN), so GHSA-4r6h-8v6p-xvw6 and
GHSA-5pgg-2g8v-p4x9 remain flagged by pnpm audit. Mitigation is
unchanged: admin-export-only usage behind a dynamic import.
2026-07-07 08:38:30 +08:00
Wesley Liddick a862eac1d8 Merge pull request #3758 from catoncat/fix/test-oauth-codex-headers
fix: add missing Codex CLI headers for OAuth account test
2026-07-07 08:34:18 +08:00
Wesley Liddick 913d838770 Merge pull request #3755 from wucm667/fix/subscription-usd-cny-rate-opt-in
feat(payment): 套餐编辑页展示订阅 CNY 实扣预览
2026-07-07 08:29:12 +08:00
Wesley Liddick 3828a48752 Merge pull request #3751 from heathermhuang/codex/grok-image-pricing-latest
fix: expose Grok image pricing controls
2026-07-07 08:29:01 +08:00
Wesley Liddick 77b1a0452e Merge pull request #3760 from DaydreamCoding/fix/codex-detect-version-gate-message
fix(codex-detect): codex 版本门拒绝返回带版本号的差异化文案
2026-07-07 08:28:51 +08:00
Wesley Liddick 26b51ccfd3 Merge pull request #3737 from wucm667/fix/sync-models-non-v1-base-url
fix(models): 同步上游模型支持非 /v1 API 版本 base_url(如智谱 /v4)
2026-07-07 08:28:41 +08:00
qqqy 7c2a828c56 fix(frontend): add compact probe mode to admin account test modal 2026-07-07 01:18:40 +08:00
Wesley Liddick 67e945f8e8 Merge pull request #3759 from Wei-Shaw/feat/account-header-override
feat: apikey 账号支持请求头覆写(Anthropic/OpenAI)
2026-07-06 20:47:33 +08:00
cat cb151e36eb fix: respect custom User-Agent in OAuth account test
Match the image OAuth test path and gateway behavior: check for a
custom user_agent credential first, fall back to codexCLIUserAgent
only when no custom UA is configured.
2026-07-06 20:45:00 +08:00
jjaw 5089c303e1 优化 Redis SCAN 清理架构 2026-07-06 20:27:13 +08:00
shaw 31b6e0d94a fix: 请求头覆写审计问题修复(禁止名单缺口/beta 对称性/批量清空防护)
后端:
- 禁止名单补充 content-type(multipart boundary 为每请求随机值,静态覆写必坏
  images 路径)、x-claude-code-session-id / x-client-request-id(会击穿每请求
  会话同步,与已禁的 session_id 等同类)、cookie / x-goog-api-key(与透传路径
  的入站鉴权残留清洗保持一致)
- anthropic-beta 覆写与 body 净化对称:四个 Anthropic 构建器在
  sanitizeAnthropicBodyForBetaTokens 前以覆写值为有效 finalBeta,避免覆写
  丢 token 后 header/body 不对称被上游 400
- 保存/应用两路径共用 normalizeHeaderOverrideEntry,消除双份校验规则漂移
- GetHeaderOverrides 按 modelMappingCache 先例增加热路径缓存(WS 每消息
  重建头场景收益最大);ApplyHeaderOverrides 移除无观测效果的排序

前端:
- 禁止名单镜像同步新增项;值长度改按 UTF-8 字节校验(与后端 len() 对齐)
- Create 弹窗切换平台时重置覆写配置,避免上一平台模板行串台
- BulkEdit:开启覆写但无有效行时拦截保存(防止整键替换静默清空所选账号
  既有配置);开启分支显示整体替换警告;混合平台选择时隐藏模板按钮
- 删除未使用的 isBlockedHeaderOverrideName 导出
2026-07-06 20:05:50 +08:00
shaw ec7b20649e feat: apikey 账号支持请求头覆写(Anthropic/OpenAI)
- 账号 credentials 新增 header_override_enabled / header_overrides,
  仅对 anthropic/openai 平台的 api_key 账号生效
- 转发前对同名请求头做大小写不敏感覆盖(EqualFold 全量删除后按
  wire casing 写入单值),值为空的条目视为占位不参与覆盖
- 覆盖全部出站路径:/v1/messages(标准+透传)、count_tokens、
  /v1/responses、chat completions、embeddings、images、全部 WS 模式、
  账号测试/探测、上游模型列表
- 创建/编辑/批量更新统一校验:RFC 7230 名称格式、去重、长度/条目上限、
  24 个禁止覆写头(认证/连接控制/accept-encoding/sec-websocket-*/
  会话隔离头),应用时二次防御过滤
- 前端三个账号弹窗新增开关+键值行编辑器+模板按钮(Claude Code CLI /
  Codex CLI 标准头,值为空),本地校验与后端规则对齐,i18n 中英文
2026-07-06 19:11:08 +08:00
cat 1c0ccb477a fix: add missing Codex CLI headers for OAuth account test
The testOpenAIAccountConnection function was sending requests to
chatgpt.com/backend-api/codex/responses without the required Codex CLI
identification headers, causing 401 Unauthorized for OAuth/PAT accounts.

The gateway Forward path and the compact test path both set these headers:
- Originator: codex_cli_rs
- User-Agent: codex_cli_rs/<version>
- OpenAI-Beta: responses=experimental

This patch adds the same headers to the normal (non-compact) OAuth test
path. API key accounts and other platforms are unaffected since the
headers are inside the isOAuth branch.
2026-07-06 19:09:26 +08:00
DaydreamCodingandClaude Opus 4.8 4b321142bb fix(codex-detect): codex 版本门拒绝返回带版本号的差异化文案
codex_cli_only 的 403 出口此前对所有拒绝原因硬编码同一句
"This account only allows Codex official clients",但能走到版本门
(判定链第 5 步)的请求其实已命中官方 UA/originator,仅版本不符,
再回「只允许官方客户端」会误导。

- CodexClientRestrictionDetectionResult 增 DetectedVersion/MinCodexVersion/
  MaxCodexVersion,仅在 VersionTooLow/VersionTooHigh 分支填充
- 新增 CodexClientRestrictionMessage:too_low/too_high 给出带实际版本号与
  边界的提示;undetectable/未命中/黑名单/缺指纹 仍用通用兜底句(不泄露门控细节)
- Forward 唯一 403 出口改用该映射函数

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 19:03:36 +08:00
Heatherm Huang de31e57333 test: document Grok video media billing unit 2026-07-06 18:32:29 +08:00
Heatherm Huang 95717a7e62 test: clarify Grok video billing test name 2026-07-06 18:30:32 +08:00
Heatherm Huang 6b4c3c6ed1 test: cover Grok video media rate billing 2026-07-06 18:23:38 +08:00
wucm667 a23a263513 feat(payment): preview subscription CNY charge in plan editor 2026-07-06 17:52:53 +08:00
wucm667 f881ff7cb0 fix(models): support non-v1 OpenAI models URLs 2026-07-06 17:46:44 +08:00
shaw 6cea1c35bb feat: 适配 OpenAI 新模型 gpt-5.6-sol/terra/luna 2026-07-06 17:34:22 +08:00
Heatherm Huang a42e9e3fc8 fix: expose Grok image pricing controls 2026-07-06 17:02:28 +08:00
Wesley Liddick d1d3400b69 Merge pull request #3645 from bestony/worktree/lucky-harbor-dbe4
feat(keys): add api key concurrency stats
2026-07-06 16:45:15 +08:00
github-actions[bot] 76bb7b0338 chore: sync VERSION to 0.1.145 [skip ci] 2026-07-06 08:30:51 +00:00
Wesley Liddick 3fa08aa930 Merge pull request #3749 from moonfunjohn/codex/easypay-custom-methods
EasyPay custom visible payment methods
v0.1.145
2026-07-06 16:06:59 +08:00
Albert Coady 27cb485d55 fix: share built-in payment method matching 2026-07-06 15:00:29 +08:00
Albert Coady 22ec77b570 fix: match built-in payment methods exactly 2026-07-06 15:00:29 +08:00
Albert Coady b197ba61ce test: align antigravity mapping preset label 2026-07-06 15:00:29 +08:00
Albert Coady a5a2fea045 Polish EasyPay custom method UI 2026-07-06 15:00:29 +08:00
Albert Coady 0dc6e56aae fix: harden easypay custom method validation 2026-07-06 15:00:29 +08:00
Albert Coady bf76168ba5 feat: add custom easypay payment methods 2026-07-06 15:00:29 +08:00
Wesley Liddick 2854ab2ace Merge pull request #3744 from Wei-Shaw/fix/subscription-cny-optin-rate
fix(payment): 订阅 CNY 换算改为独立汇率配置的显式 opt-in(含 #3738)
2026-07-06 14:58:20 +08:00
Wesley Liddick e95c909ee5 Merge pull request #3747 from Wei-Shaw/revert-3738-fix/subscription-confirm-amount-and-affiliate-base
Revert "fix(payment): 订阅确认页显示换算后 CNY 金额 + 邀请返利按 USD price 计算"
2026-07-06 14:58:00 +08:00
Wesley Liddick ba1bb0a3d3 Revert "fix(payment): 订阅确认页显示换算后 CNY 金额 + 邀请返利按 USD price 计算" 2026-07-06 14:55:04 +08:00
Wesley Liddick 11fd61458c Merge pull request #3738 from wucm667/fix/subscription-confirm-amount-and-affiliate-base
fix(payment): 订阅确认页显示换算后 CNY 金额 + 邀请返利按 USD price 计算
2026-07-06 14:53:59 +08:00
shaw d56e94b875 feat(payment): 订阅 CNY 换算改为独立汇率配置的显式 opt-in
- 新增 SUBSCRIPTION_USD_TO_CNY_RATE 配置(1 USD = X CNY,默认 0=关闭),
  替代复用 balance_recharge_multiplier 的隐式换算,促销倍率与订阅定价解耦
- 未配置汇率时订阅保持 price 直付的存量行为,存量部署升级零影响
- 前端确认页/原价/手续费/方式限额与后端换算条件严格镜像(rate>0 且币种为 CNY)
- 管理后台新增汇率配置输入(zh/en 文案),checkout-info 透出 subscription_usd_to_cny_rate
- 单测锁定:汇率未配置时不换算、换算使用汇率而非余额倍率、余额订单不受影响、返利仍按 USD price
2026-07-06 14:34:17 +08:00
shaw d089c5789c Merge branch 'pr-3738' into fix/subscription-cny-optin-rate 2026-07-06 14:14:19 +08:00
Wesley Liddick 9fac6f15ce Merge pull request #3739 from Wei-Shaw/fix/openai-advanced-scheduler-audit-fixes
fix(scheduler): 修复 OpenAI 高级调度器审计发现的正确性与性能问题
2026-07-06 13:45:15 +08:00
shaw 0fd2e9216d fix(scheduler): 修复 OpenAI 高级调度器审计发现的正确性与性能问题
针对 #3692 合并后审计发现的问题集中修复:

- previous_response_id 剥离条件改为按 call_id 全覆盖校验,
  部分可重建的工具续链不再被误剥离(不受开关门控的行为回归)
- 粘性加权回退路径补分组归属校验并清理失效绑定,杜绝跨分组账号泄漏
- 账号列表页:无 OpenAI 账号时跳过分数计算、过滤池限定 openai 平台、
  负载批查合并为账号并集一次查询,消除全表扫描与 Redis N+1
- 订阅优先模式下常规池不可用时回退订阅池等待计划,
  busy-but-waitable 的订阅账号不再导致请求硬失败
- TopK/权重 DB 覆盖显式受总开关门控,与兄弟子开关语义一致
- 前端未分组 OpenAI 账号回退展示基础分,不再显示 "-"
- ListAllWithFilters 等能力正式进入 AccountRepository/AdminService 接口,
  移除匿名接口断言与静默降级;负载批查失败补 warn 日志
- SelectAccountWithSchedulerForCapability 增加显式 previousResponseCanMove
  参数,移除 "previous_response_can_move" 魔法字符串哨兵
- 设置写入路径补"基础权重不得全为零"聚合校验;
  运行时设置批量读取失败的降级路径覆盖全部键并留痕
2026-07-06 11:43:16 +08:00
Wesley Liddick 759332aa92 Merge pull request #3692 from linshuboy/codex/openai-advanced-scheduler-controls-squashed
[codex] add OpenAI advanced scheduler controls
2026-07-06 10:59:23 +08:00
wucm667 b408edf97b fix(payment): convert subscription CNY pay amount 2026-07-06 10:56:43 +08:00
Wesley Liddick f0f1f59a44 Merge pull request #3716 from wucm667/fix/antigravity-refresh-server-invalidated-token
fix(antigravity): 401 服务端失效的 token 触发主动刷新,修复 NeedsRefresh 仅看 expires_at 的死循环
2026-07-06 10:18:49 +08:00
Wesley Liddick ac68d73f0c Merge pull request #3717 from wucm667/fix/anthropic-models-honor-group-config
fix(gateway): Anthropic /v1/models 返回分组 models_list_config 自定义模型列表
2026-07-06 10:18:36 +08:00
Wesley Liddick 2e70ec0a15 Merge pull request #3714 from MoRanHuiShou-pug/fix-payment-nul-bytes
fix: sanitize payment response NUL bytes
2026-07-06 10:18:18 +08:00
Wesley Liddick de15f29d1f Merge pull request #3718 from wucm667/fix/usage-csv-export-utf8-bom
fix(usage): CSV 导出补 UTF-8 BOM,修复 Excel 打开中文列乱码
2026-07-06 10:12:27 +08:00