Commit Graph
5340 Commits
Author SHA1 Message Date
Wesley Liddick f71332ff85 Merge pull request #4980 from yan9651688/feat/model-id-copy
feat(accounts): add one-click model ID copy
2026-07-28 11:06:48 +08:00
Wesley Liddick c342a885b5 Merge pull request #4942 from HuntercodeT/fix/openai-passthrough-model-mapping-4936
fix(openai): honor passthrough over non-empty model_mapping in account selection (#4936)
2026-07-28 11:06:33 +08:00
Wesley Liddick 1aeacf4d41 Merge pull request #4983 from Wei-Shaw/fix/issue-4887-prompt-audit-recovery
fix(security-audit): 解密失败不再吞掉整份配置,修复升级后配置消失且无法保存的死锁
2026-07-28 09:49:40 +08:00
Wesley Liddick d95f6b98ce Merge pull request #4975 from Vibeone/fix/msg-id-format-authentic
fix(gateway): 修复模拟响应 message ID 格式,改为正宗 Anthropic msg_01 格式
2026-07-28 09:49:31 +08:00
shaw bfbe113f5e fix(security-audit): 解密失败不再吞掉整份配置,修复升级后配置消失且无法保存的死锁 (#4887)
根因:prompt audit 是共享 TOTP_ENCRYPTION_KEY 加密器的功能中唯一不校验
EncryptionKeyConfigured 的落点。未配置固定密钥的部署每次重启自动生成新
密钥,v162 保存的节点 Token 密文在升级重启后永久无法解密,Reload 中
ActiveFromStorage 整体失败导致快照永远装不上:管理端 GET 回退默认 v1
(v166 起为 503),而保存路径直读数据库做 CAS 版本对比,必然冲突——
配置既看不见也改不掉。PR #4893 仅改变了报错形态,未修复根因。

修复:
- ActiveFromStorage 对单节点解密失败降级容忍:该节点运行时禁用并标记
  TokenInvalid,配置整体照常激活;管理端恢复显示真实版本号,重新输入
  Token 即可自愈(密文保留,密钥恢复后自动复原)
- blocking 意图下零可用节点时 evaluator 仍返回 unavailable,请求照旧
  被拒,fail-closed 语义不回归;async 意图下 enqueue 直接 drop 并告警
- Save 在未配置固定加密密钥时拒绝保存新 Token(与 TOTP/Ollama/备份
  一致的门控),错误码 prompt_audit_encryption_key_required
- token_status 新增 invalid 状态,前端凭据列与编辑框提示重新输入
- 新增 config_token_invalid 告警日志(集合变化时记录一次,不随 5s
  刷新刷屏)
2026-07-28 09:31:36 +08:00
yan9651688 d8ae153ae9 feat(accounts): make model IDs easy to copy
Administrators often need exact model identifiers while editing account whitelists. Add a dedicated copy action without changing model selection or upstream sync behavior.

Constraint: Keep the contribution frontend-only and avoid model routing or persistence changes
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep copy and selection as separate actions
Tested: focused Vitest, account component regression tests, frontend typecheck, lint, and production build
Not-tested: Authenticated browser screenshot
Related: Wei-Shaw/sub2api#2151
2026-07-28 09:23:52 +08:00
eyre 248236ce6d fix(gateway): 修复模拟响应使用 Bedrock msg_bdrk_ 格式,改为正宗 Anthropic msg_01 格式
问题:
探针拦截(suggestion mode / warmup / max_tokens=1 haiku)的模拟响应以及
Gemini/Antigravity 兼容层生成的 message ID 不符合 Anthropic 官方 API 格式,
容易被客户端识别为非正宗响应。

修复:
1. generateRealisticMsgID():msg_bdrk_ + 24字符 → msg_01 + 22位 Base62
   (与官方 API 返回的 msg_011CdS6b8gAhoKWdW9jE87Zs 格式一致)
2. 去掉固定的 msg_mock_suggestion / msg_mock_warmup,统一使用随机 ID
3. 流式响应格式对齐官方:
   - message_start 增加 stop_details/cache token 字段
   - content_block_start 字段顺序修正
   - message_delta.usage 只含 output_tokens
4. 非流式响应:增加 stop_details:null,移除非标准 total_tokens
5. Gemini Messages/ChatCompletions 兼容层:msg_ + hex → msg_01 + Base62
6. Antigravity response/stream transformer:msg_ + 12位 → msg_01 + 22位 Base62

验证方式:对照 Anthropic 官方 API 实际响应格式确认。
2026-07-27 15:20:03 +00:00
github-actions[bot] 59ce11c780 chore: sync VERSION to 0.1.166 [skip ci] 2026-07-27 08:57:42 +00:00
shaw dc893dd0b8 chore: update sponsors v0.1.166 2026-07-27 15:49:14 +08:00
Wesley Liddick f18f3143e2 Merge pull request #4946 from Wei-Shaw/feat/panel-api-rate-limit
feat(security): 面板 API 限流保护——防止高频刷接口打爆数据库
2026-07-27 15:44:06 +08:00
shaw fead4c7ec3 feat(security): add panel API rate limiting to protect DB from high-frequency requests
用户可高频刷面板接口(usage/dashboard 等重聚合查询)直接打爆数据库:
现有限流器只覆盖登录/注册等公开认证入口,登录后的全部面板端点无任何限流。

三层防护(阈值均可在后台可视化配置,panel_rate_limit_settings):

1. 认证面板接口按「用户 ID」限流,与来源 IP 无关——反向代理/NAT 共享出口
   (所有请求源地址坍缩为 127.0.0.1 等)不会互相误伤:
   - Global 档(默认 240 rpm/账号):user/auth/payment/admin 全部登录后路由
   - Heavy 档(默认 60 rpm/账号):/usage、/usage/dashboard/*、
     /user/api-keys/:id/usage/daily 等重 SQL 聚合端点叠加计数
   - 管理员默认豁免(可关闭)

2. 无认证公开接口(/api/v1/settings/*,每次请求都查 DB)按安全客户端 IP
   限流(默认 300 rpm/IP);回环/私网/链路本地地址(反代内部转发地址)
   一律跳过计数,杜绝把整条反代链路合并进同一个桶造成大面积误拦截。

3. 修复既有隐患:auth 入口限流的 IP 取值从 c.ClientIP() 切换到与审计日志/
   会话绑定/API Key ACL 同源的安全客户端 IP 解析(尊重后台「信任反代转发
   IP」开关快照)。原实现下默认反代部署(未配置 server.trusted_proxies)
   所有用户共享同一个登录限流桶,既会全员误拦也可被单人恶意占满形成登录
   DoS;开关关闭时行为与原来完全一致。

工程约束:
- 配置热路径走进程内缓存(atomic.Value + singleflight,60s TTL),
  限流中间件零 DB 访问;保存后当前节点立即生效
- 面板限流 Redis 故障 fail-open(auth 入口保持原有 fail-close)
- 429 响应携带 Retry-After;错误码 RATE_LIMITED
- 支付 webhook / 公开支付回调有意不挂限流
- 新增 GET/PUT /api/v1/admin/settings/panel-rate-limit;设置页安全 tab
  新增「面板接口限流」卡片(zh/en i18n 全量)

测试:rate_limiter/panel_rate_limit/setting_panel_rate_limit 单测全绿;
routes、handler/admin、-tags unit 契约测试通过;前端 vue-tsc/ESLint/
SettingsView spec(26/26,含新增交互用例)/i18n 守卫全部通过。
2026-07-27 15:12:51 +08:00
HuntercodeT 83b368553d fix(openai): honor passthrough over model_mapping in IsModelSupported (#4936)
An OpenAI account with auto-passthrough enabled (extra.openai_passthrough=true,
"replace auth only, allow all models") was still filtered out during account
selection when it had a non-empty credentials.model_mapping that did not list the
requested model. isOpenAICompatibleAccountEligibleForRequest calls
Account.IsModelSupported directly, and IsModelSupported only bypassed the mapping
whitelist for passthrough accounts when the mapping was empty. A leftover mapping
(common after switching an account from whitelist mode to passthrough) therefore
excluded the account -> zero candidates -> ErrNoAvailableAccounts, and the client
saw 404 "Model ... is not supported by any configured account in this group" even
though a direct account test with the same model succeeded (that path already
honored passthrough via isModelSupportedByAccount).

Fix: short-circuit passthrough at the top of Account.IsModelSupported, before the
model_mapping check, so it is consistent with isModelSupportedByAccount. Add a
regression test covering passthrough + non-empty leftover mapping.
2026-07-27 14:20:12 +08:00
Wesley Liddick d96b6a31ff Merge pull request #4908 from chinnsenn/fix/antigravity-openai-compat
fix(antigravity): route OpenAI-compatible requests through native gateway
2026-07-27 13:59:47 +08:00
Wesley Liddick ab73bc0c77 Merge pull request #4924 from Cynicismcart/fix/group-description-wrapping
修复分组描述换行与下拉框溢出
2026-07-27 13:52:44 +08:00
Senn Chinn 3ce8efc125 Merge branch 'Wei-Shaw:main' into fix/antigravity-openai-compat 2026-07-27 13:40:05 +09:00
chinnsenn cc84cd8b4c test(gemini): check function declaration assertions 2026-07-27 13:19:00 +09:00
Wesley Liddick 95590b5530 Merge pull request #4932 from Ricardo-binZzz/codex-responses-compat
Fix Codex (Responses API) <-> Anthropic tool compatibility
2026-07-27 11:47:13 +08:00
Wesley Liddick b765a7f9f6 Merge pull request #4890 from SemonCat/fix/openai-cross-mode-reasoning-failover
fix(openai): strip foreign reasoning on account failover
2026-07-27 11:46:49 +08:00
Wesley Liddick b72d487b85 Merge pull request #4878 from StarryKira/codex/fix-payment-dashboard-currencies
fix(payment): group dashboard stats by currency
2026-07-27 11:46:23 +08:00
Wesley Liddick ad34f89152 Merge pull request #4933 from visa2/fix/usage-model-mapping-statistics
fix(usage): report channel-mapped requests under their real upstream model
2026-07-27 11:45:58 +08:00
Wesley Liddick de6b189a6b Merge pull request #4879 from wey-gu/fix/security-deps-20260726
fix(deps): update image and telemetry packages
2026-07-27 11:45:06 +08:00
Wesley Liddick a74e11c26a Merge pull request #4868 from visa2/fix/settings-partial-update-clobber
fix(settings): keep fields a settings PUT never sent at their stored value
2026-07-27 11:44:40 +08:00
Wesley Liddick 131d42d25d Merge pull request #4839 from visa2/fix/composite-route-prefix-passthrough
fix(composite): pass the requested model through when a prefix route leaves upstream_model empty
2026-07-27 11:44:15 +08:00
Wesley Liddick 031c83b7e0 Merge pull request #4875 from StarryKira/codex/fix-4859-gemini-36-flash-billing
fix(billing): price Antigravity Gemini 3.6 Flash
2026-07-27 11:43:49 +08:00
Wesley Liddick 7a3fda57c8 Merge pull request #4820 from feeeei/main
fix(gemini): 完善gemini号池模式时retryable失效问题
2026-07-27 11:43:13 +08:00
Wesley Liddick 16365199aa Merge pull request #4884 from Brisbanehuang/fix/probe-scheduling-nanosecond-timestamps
fix(repository): 修复上游计费倍率探测因纳秒时间戳解析失败导致的调度饿死
2026-07-27 11:42:59 +08:00
Wesley Liddick 91a2281c7a Merge pull request #4861 from coo1white/fix-flaky-concurrency-tests
test: stop four concurrency tests from failing on a busy machine
2026-07-27 11:42:34 +08:00
Wesley Liddick ece9517091 Merge pull request #4930 from wucm667/fix/issue-4928-config-file-path
fix(config): honor explicit CONFIG_FILE path
2026-07-27 11:42:08 +08:00
Wesley Liddick 4cc88e27b6 Merge pull request #4873 from wey-gu/fix/admin-usage-request-id-filter
fix(admin): filter usage logs by request id
2026-07-27 11:41:09 +08:00
Wesley Liddick b468e428e9 Merge pull request #4926 from Vibeone/fix/oauth-mimicry-cache-prefix-break
fix(gateway): 识别被代理的 Claude Code 流量,避免 mimicry 重写破坏 prompt cache
2026-07-27 11:40:43 +08:00
Wesley Liddick a40d6de12e Merge pull request #4907 from feitianbubu/fix/bump-claude-cli-version-2.1.220
fix(claude): 伪装的 Claude Code CLI 版本号升级到 2.1.220
2026-07-27 11:40:18 +08:00
Wesley Liddick bc9173be15 Merge pull request #4934 from OG-Wang/fix/monitor-timeline-overflow
fix(frontend): 修复渠道监控时间线在窄卡片下溢出
2026-07-27 11:39:34 +08:00
Wesley Liddick eb6e3d1f1d Merge pull request #4787 from KtzeAbyss/fix/4760-ws-turn-model-billing
fix(openai): track WebSocket models per turn
2026-07-27 10:25:57 +08:00
Wesley Liddick a93bfb6623 Merge pull request #4757 from lucas-ward/codex/fix-4691-caddy-sse-buffering
fix(deploy): prevent Caddy compression from buffering SSE
2026-07-27 10:22:58 +08:00
Wesley Liddick 8f47bd5fa0 Merge pull request #4893 from wucm667/fix/issue-4887-prompt-audit-config-load
fix(security-audit): reject unavailable prompt config
2026-07-27 10:20:14 +08:00
Wesley Liddick beeb4b84ed Merge pull request #4900 from wucm667/fix/issue-4889-mobile-available-channels
fix(frontend): adapt available channels for mobile
2026-07-27 10:19:44 +08:00
Wesley Liddick aac44473aa Merge pull request #4876 from wucm667/fix/issue-4846-show-usage-user
fix: show routed user in usage filters
2026-07-27 10:19:31 +08:00
Wesley Liddick 465362e1af Merge pull request #4877 from wucm667/fix/issue-4863-turnstile-invite-overlap
fix: show optional affiliate code on registration
2026-07-27 10:19:16 +08:00
Wesley Liddick 6ee2304dcd Merge pull request #4912 from yan9651688/fix/issue-4794-grok-test-402
fix(grok): pause accounts after manual test payment failure
2026-07-27 10:19:01 +08:00
Rick e94383a4c4 fix(frontend): 修复渠道监控时间线在窄卡片下溢出
MonitorTimeline 每根柱子设置了 min-w-[3px],60 根柱子加 2px 间距的
最小总宽度为 298px。当卡片内容区宽度低于该值时(如 100% 缩放下的
部分布局),时间线整体溢出卡片边缘。改为 min-w-0 让柱子随容器等分
压缩,任意宽度下均不再溢出。
2026-07-27 09:08:56 +08:00
shaw 7d3a896fcd chore: update sponsors 2026-07-27 08:59:12 +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
wucm667 5c471485ab fix(config): honor explicit CONFIG_FILE path
Make CONFIG_FILE select an explicit config for both full loading and lightweight address lookup, with regression tests.
2026-07-27 06:20:11 +08:00
eyre 7b3ed2a961 fix(gateway): detect proxied Claude Code traffic by body to preserve prompt cache
When an upstream API gateway (e.g. new-api) relays real Claude Code
requests, the User-Agent becomes Go-http-client while the body retains
the full Claude Code fingerprint (billing attribution block +
metadata.user_id + cache_control breakpoints).

Previously, the OAuth mimicry path relied solely on UA matching to
detect Claude Code clients. Without a matching UA, the gateway would
rewrite the system prompt — replacing the client's carefully structured
system blocks and cache_control breakpoints with its own injection.
This breaks Anthropic's prefix-based prompt cache: since the cache key
evaluates tools → system → messages in order, a changed system
invalidates all downstream message caching.

Symptoms observed:
- cache_read permanently locked at ~25K (only system prompt cached)
- cache_creation growing monotonically every turn (full messages rewrite)
- Single-request costs $17-27 instead of normal $1-2

Fix: when UA does not match but the body contains a valid billing
attribution block (x-anthropic-billing-header with cc_entrypoint=),
treat the request as proxied Claude Code traffic and skip mimicry.
This preserves the client's original system structure and cache_control
breakpoints, allowing Anthropic's prompt cache to function correctly.
2026-07-26 17:54:56 +00:00
visa2 be65c713ff fix(usage): preserve final upstream model 2026-07-27 00:43:53 +08:00
Cynicismcart 78f78947f1 fix(frontend): 完善下拉框视口边界处理 2026-07-27 00:41:40 +08:00
Cynicismcart 005a5d2a37 fix(frontend): 修复分组描述换行和下拉框溢出 2026-07-27 00:35:15 +08:00
visa2 1f45c99de7 fix(usage): correct mapped model statistics 2026-07-26 23:56:34 +08:00
chinnsenn 3e08106116 fix(gemini): preserve Hermes web search functions 2026-07-26 22:09:26 +09:00
yan9651688 2db0cbd292 fix(grok): pause accounts after manual test payment failure
Manual Grok connection tests previously surfaced upstream HTTP 402 errors without changing account availability. Persist the same 30-minute payment-required cooldown used by the live forwarding path so refreshed account lists no longer present the account as schedulable.

Constraint: Keep manual-test HTTP 402 handling aligned with existing Grok forwarding semantics.
Rejected: Mark the account permanently error | payment state can recover and the forwarding path intentionally uses a bounded cooldown.
Confidence: high
Scope-risk: narrow
Directive: Keep the manual-test cooldown reason and duration aligned with handleGrokAccountUpstreamError.
Tested: go test -tags=unit ./internal/service -count=1; go vet -tags=unit ./internal/service; production package compile check
Not-tested: Live xAI account with an exhausted subscription
Related: #4794
2026-07-26 21:04:18 +08:00