erio
ebac0dc628
feat(channel): 缓存扁平化 + 网关映射集成 + 计费模式统一 + 模型限制
...
- 缓存重构为 O(1) 哈希结构 (pricingByGroupModel, mappingByGroupModel)
- 渠道模型映射接入网关流程 (Forward 前应用, a→b→c 映射链)
- 新增 billing_model_source 配置 (请求模型/最终模型计费)
- usage_logs 新增 channel_id, model_mapping_chain, billing_tier 字段
- 每种计费模式统一支持默认价格 + 区间定价
- 渠道模型限制开关 (restrict_models)
- 分组按平台分类展示 + 彩色图标
- 必填字段红色星号 + 模型映射 UI
- 去除模型通配符支持
2026-04-04 11:09:01 +08:00
erio
29d58f2414
feat(channel): 模型映射 + 分组搜索 + 卡片折叠 + 冲突校验
...
- 渠道模型映射:新增 model_mapping JSONB 字段,在账号映射之前执行
- 分组选择:添加搜索过滤 + 平台图标
- 定价卡片:支持折叠/展开,已有数据默认折叠
- 模型冲突校验:前后端均禁止同一渠道内重复模型
- 迁移 083: channels 表添加 model_mapping 列
2026-04-04 11:06:36 +08:00
erio
dca0054e93
feat(channel): 模型标签输入 + $/MTok 价格单位 + 左开右闭区间 + i18n
...
- 模型输入改为标签列表(输入回车添加,支持粘贴批量导入)
- 价格显示单位改为 $/MTok(每百万 token),提交时自动转换
- Token 模式增加图片输出价格字段(适配 Gemini 图片模型按 token 计费)
- 区间边界改为左开右闭 (min, max],右边界包含
- 默认价格作为未命中区间时的回退价格
- 添加完整中英文 i18n 翻译
2026-04-04 11:01:22 +08:00
erio
983fe58959
fix: CI lint/test fixes — gofmt, errcheck, handler test args
2026-04-04 11:01:22 +08:00
erio
91c9b8d062
feat(channel): 渠道管理系统 — 多模式定价 + 统一计费解析
...
Cherry-picked from release/custom-0.1.106: a9117600
2026-04-04 11:00:55 +08:00
Wesley Liddick
b384570de3
Merge pull request #1439 from touwaeriol/feat/redeem-negative-value
...
feat(redeem): support negative values for refund/deduction
2026-04-03 22:22:54 +08:00
Wesley Liddick
0507852a34
Merge pull request #1437 from DaydreamCoding/fix/openai-oauth-improvements
...
feat(openai): OpenAI OAuth 账号管理增强:订阅状态、隐私设置、Token 刷新修复
2026-04-03 09:22:10 +08:00
Wesley Liddick
7b6ff135fb
Merge pull request #1424 from DaydreamCoding/fix/antigravity-batch-privacy
...
fix(antigravity): 修复批量刷新令牌不设置隐私模式的问题
2026-04-03 09:21:39 +08:00
erio
bf24de88ed
style: fix gofmt struct tag alignment
2026-04-03 02:00:21 +08:00
erio
ff6d4ab39a
chore: add lodash/lodash-es audit exception for GHSA-r5fr-rjxr-66jc
2026-04-03 01:53:17 +08:00
erio
66fde7a2e6
feat(redeem): support negative values for refund/deduction
...
Allow redeem codes with negative values to enable refund scenarios:
- Balance: negative value deducts balance (clamped to 0, never negative)
- Concurrency: negative value reduces concurrency (clamped to 0)
- Subscription: negative validity_days reduces remaining days; if
remaining days <= 0, the subscription is canceled (set to expired)
All deductions generate standard redeem code records for audit trail.
2026-04-03 01:50:26 +08:00
QTom
e8efaa4cd9
style: gofmt struct field alignment
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 20:50:38 +08:00
QTom
00947d6492
feat(openai): 显示订阅到期时间
...
从 /backend-api/accounts/check 的 entitlement.expires_at 提取订阅
到期日期,每次 token 刷新时更新并存入 credentials,前端账号列表
的订阅类型和隐私下方以灰色小字显示(仅非 Free 账号)。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 20:44:28 +08:00
QTom
cf70fb1b4e
fix(openai): Mobile RT 账号隐私设置失败
...
1. CreateAccount 补齐 OpenAI OAuth 隐私入口(与 BatchCreate 对齐)
2. disableOpenAITraining 请求头修正:覆盖 ImpersonateChrome() 的
浏览器导航默认头(accept: text/html, sec-fetch-mode: navigate),
改为 API 请求语义(Accept: application/json, sec-fetch-mode: cors),
避免 Cloudflare 将 PATCH API 请求误判为异常导航流量而拦截
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 20:44:22 +08:00
QTom
ef1a992cf0
fix(openai): refresh token when expires_at missing and account is rate-limited
...
Prevents token silent expiry during 7-day rate limit periods.
Made-with: Cursor
2026-04-02 20:44:12 +08:00
QTom
1f6a73f0db
fix(openai): treat 401 {"detail":"Unauthorized"} as permanent auth failure
...
- ratelimit_service: detect non-standard OpenAI 401 format and permanently disable account
- account_test_service: mark account error on 401 during connection test
Made-with: Cursor
2026-04-02 20:44:05 +08:00
QTom
f2e596f6ec
fix(oauth): 每次刷新都通过 backend-api 获取最新 plan_type
...
账号订阅类型可能每月变化,id_token 中的 plan_type 是签发时的快照,
不一定反映当前状态。移除 plan_type == "" 前置条件,确保每次刷新都
调用 ChatGPT backend-api 获取实时订阅类型并覆盖旧值。
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 20:43:56 +08:00
Yanzhe Lee
77ba9e728d
Merge branch 'Wei-Shaw:main' into fix/openai-gateway-content-session-hash-fallback
2026-04-02 01:56:18 +08:00
YanzheL
cf9efefd96
fix(lint): satisfy errcheck for strings.Builder.WriteString calls
2026-04-02 01:03:22 +08:00
YanzheL
4fb1603001
test(gateway): add tests for content-based session hash fallback
...
- 20 unit tests for deriveOpenAIContentSessionSeed covering:
- Empty/nil inputs, model-only, stable across turns
- Different model/system/first-user produce different seeds
- Tools, functions, developer role, structured content
- Responses API: input string, input array, instructions, input_text typed items
- JSON canonicalization (whitespace/key-order insensitive)
- Prefix presence, empty tools ignored, messages preferred over input
- 3 integration tests for GenerateSessionHash content fallback:
- Content fallback produces stable hash
- Explicit signals override content fallback
- Empty body still returns empty hash
2026-04-02 00:11:17 +08:00
YanzheL
c5aac1251d
fix(gateway): add content-based session hash fallback for non-Codex clients
...
When no explicit session signals (session_id, conversation_id, prompt_cache_key)
are provided, derive a stable session seed from the request body content
(model + tools + system prompt + first user message) to enable sticky routing
and prompt caching for non-Codex clients using the Chat Completions API.
This mirrors the content-based fallback already present in GatewayService.
GenerateSessionHash, adapted for the OpenAI gateway's request formats (both
Chat Completions messages and Responses API input).
JSON fragments are canonicalized via normalizeCompatSeedJSON to ensure
semantically identical requests produce the same seed regardless of
whitespace or key ordering.
Closes #1421
2026-04-02 00:11:06 +08:00
win
47ce45fbed
fix: SOCKS5 dialer 日志改 Info 级别,OAuth 超时延长至 60s
2026-04-01 16:54:33 +08:00
win
cc737d789e
fix: SOCKS5ProxyDialer 使用 ContextDialer 避免 Docker 内本地 DNS 解析失败
...
- 原实现 proxy.SOCKS5(..., proxy.Direct) 会先在本地做 DNS 解析
Docker 容器内无法解析 platform.claude.com 导致 30s 超时
- 改用 &net.Dialer{} + DialContext 让域名直接发给代理端远端解析
- 同时影响 OAuth token exchange 和 API 请求的 SOCKS5 路由
2026-04-01 12:55:13 +08:00
win
40d624eb81
fix: 添加 OAuth setup token 端点的代理路由诊断日志
2026-04-01 12:48:37 +08:00
win
da55bd64a1
fix: OAuth client 强制 HTTP/1.1 + 代理路由调试日志
...
- createReqClient: EnableForceHTTP1() 避免 H2 ALPN 升级与自定义 TLS dialer 冲突
- 超时从 15s 延长到 30s
- 增加代理路由日志,方便诊断 proxy_id 是否正确传递
- proxyurl.Parse 返回的 parsedProxy 直接复用,省去二次 url.Parse
2026-04-01 12:34:46 +08:00
QTom
b155bc564b
fix(antigravity): 修复批量刷新令牌不设置隐私模式的问题
...
- refreshSingleAccount ProjectIDMissing 提前返回前补上 EnsureAntigravityPrivacy 调用
- EnsureAntigravityPrivacy 跳过条件从"有任何值"改为"仅 privacy_set 成功时跳过",
privacy_set_failed 允许重试,对齐 OpenAI shouldSkipOpenAIPrivacyEnsure 的行为
- 后台 TokenRefreshService.ensureAntigravityPrivacy 同步修改
- ExchangeCode/ValidateRefreshToken 获得令牌后立即调用 setAntigravityPrivacy,
不依赖后续账号创建流程
Made-with: Cursor
2026-04-01 12:24:52 +08:00
win
58ad47ba80
fix: 对齐 Claude Code 2.1.88 源码指纹
...
- 1P event_logging/batch 添加 OAuth Bearer auth header
- DD hostname 改为固定 "claude-code"(与真实 CLI 一致)
- 事件名对齐真实 CLI: tengu_api_query/tengu_api_success/tengu_api_error/tengu_tool_use_success
- DD header 大小写改为 DD-API-KEY
- ResponseHeaderTimeout 300s → 600s(与真实 CLI 10min 超时对齐)
2026-04-01 08:53:39 +08:00
Wesley Liddick
055c48ab33
Merge pull request #1262 from InCerryGit/main
...
fix(openai): preserve bare gpt-5.3-codex-spark across forwarding paths
2026-04-01 08:31:12 +08:00
Wesley Liddick
6663e1eda6
Merge pull request #1420 from YanzheL/fix/1202-gemini-customtools-404
...
Fix Gemini CLI 404s for gemini-3.1-pro-preview-customtools
2026-04-01 08:30:40 +08:00
win
d8d8adb37f
feat: 移除 Node.js TLS 代理依赖,全部走 Go 原生 utls 指纹
...
- Do() 路由从 doViaNodeTLSProxy(转发到 localhost:3456 Node.js 进程)
改为 doWithTLSFingerprint(直接使用 Go utls dialer),解决 h2 connect
timeout 问题(Node.js proxy 的 H2 路径不支持 per-account 代理隧道)
- 新增 internal/pkg/telemetry 包,从 proxy.js 移植全部遥测逻辑:
Anthropic event_logging/batch + Datadog log intake + 虚拟主机身份 +
会话状态管理 + process metrics 模拟
- 保留 proxy.js 中的 H1 降级修复作为备用
2026-04-01 08:24:49 +08:00
YanzheL
649afef512
fix(handler): fallback known gemini models on v1beta 404
2026-04-01 02:20:13 +08:00
YanzheL
4514f3fc11
fix(gemini): resolve customtools alias in mapping lookup
2026-04-01 02:19:42 +08:00
YanzheL
095bef9554
fix(gemini): add customtools fallback metadata
2026-04-01 02:19:10 +08:00
win
b856586412
修复h1
CI / test (push) Failing after 16m30s
CI / golangci-lint (push) Failing after 4s
Security Scan / backend-security (push) Failing after 1m35s
Security Scan / frontend-security (push) Failing after 1m31s
2026-04-01 01:35:49 +08:00
YanzheL
f00351c106
fix(openai): sanitize empty base64 input images
2026-04-01 00:46:38 +08:00
YanzheL
936fce68d0
fix(apicompat): skip empty base64 image URLs
2026-04-01 00:46:16 +08:00
YanzheL
d978ac97f1
test(antigravity): cover mixed web search transforms
2026-04-01 00:46:14 +08:00
YanzheL
dd5978f222
fix(gemini): normalize ai studio google search tools
2026-04-01 00:45:56 +08:00
YanzheL
0ebe0ce585
fix(gemini): preserve google search in Claude compat tools
2026-04-01 00:33:39 +08:00
YanzheL
c8cfad7c00
fix(antigravity): preserve google search with function tools
2026-04-01 00:33:16 +08:00
win
1e19d9caca
feat: 行为模拟补全 — GrowthBook/PolicyLimits 轮询 + tengu_exit
...
CI / test (push) Failing after 7s
CI / golangci-lint (push) Failing after 7s
Security Scan / backend-security (push) Failing after 6s
Security Scan / frontend-security (push) Failing after 13s
补全真实 CLI 的后台行为模式,消除关联分析缺口:
1. GrowthBook SDK 轮询: 每 20min GET /sub/features/sdk-zAZezfDKGoZuXXKe
- 匹配真实 CLI 的 setupPeriodicGrowthBookRefresh()
- 带 OAuth Bearer + anthropic-beta header
- per-account jitter 避免同时请求
2. Policy Limits 轮询: 每 1h GET /api/claude_code/policy_limits
- 匹配真实 CLI 的 refreshPolicyLimits()
- OAuth 认证 + ETag 缓存模式
3. tengu_exit 会话结束: 10min 空闲后触发
- 匹配真实 CLI 进程退出时的遥测事件
- 清理 session 状态允许下次请求重新 bootstrap
4. 重构 bootstrap_preflight.go 为 backgroundSimulator 统一管理
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 22:32:38 +08:00
win
dab4142ab2
feat: Claude Code 2.1.88 源码级指纹还原
...
CI / test (push) Failing after 11s
CI / golangci-lint (push) Failing after 8s
Security Scan / backend-security (push) Failing after 5s
Security Scan / frontend-security (push) Failing after 6s
基于 Claude Code 2.1.88 反编译源码,完成全面的反追踪指纹还原:
1. 版本升级 2.1.87 → 2.1.88(constants.go, identity_service.go, proxy.js)
2. 新增 6 个 beta header 常量(task-budgets, token-efficient-tools, structured-outputs, advisor, web-search)
3. 更新所有组合 beta header 字符串,加入 context-1m, redact-thinking, effort 等
4. 注入 x-anthropic-billing-header attribution block 到 system prompt 首位
- 完整复刻 fingerprint 算法: SHA256(salt + msg[4,7,20] + version)[:3]
- 正确省略 cch 字段(npm 版行为,非原生二进制)
5. X-Claude-Code-Session-Id: 有则同步,无则按 account 生成
6. x-client-request-id: 每请求自动生成 UUID
7. Bootstrap 预热: 模拟 GET /api/claude_cli/bootstrap(per-account, 1h cooldown)
8. 停止无条件剥离 temperature/tool_choice(与真实 CLI 行为一致)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 21:57:51 +08:00
win
1eed02c325
fix: restore node-tls-proxy routing lost during rebase
...
CI / test (push) Failing after 1m32s
CI / golangci-lint (push) Failing after 1m32s
Security Scan / backend-security (push) Failing after 32s
Security Scan / frontend-security (push) Failing after 32s
- Re-add NodeTLSProxyConfig struct to GatewayConfig (removed by upstream)
- Re-create http_upstream_antigravity.go with proxy routing functions
- Add proxy intercept hook in Do() for api.anthropic.com requests
2026-03-31 14:08:24 +08:00
Wesley Liddick
83a16dec19
Merge pull request #1407 from DaydreamCoding/feat/cache-driven-rpm-buffer
...
feat(gateway): Cache-Driven RPM Buffer
2026-03-31 14:01:23 +08:00
Wesley Liddick
820c531814
Merge pull request #1406 from DaydreamCoding/feat/group-account-filter
...
feat(group-filter): 分组账号过滤控制 — require_oauth_only + require_privacy_set
2026-03-31 14:01:05 +08:00
Wesley Liddick
1727b8df3b
Merge pull request #1404 from DaydreamCoding/feat/antigravity-privacy-on-refresh-fail
...
feat(antigravity): 令牌刷新失败及创建账号时也设置隐私
2026-03-31 14:00:53 +08:00
shaw
a025a15f5d
feat: add refresh button to admin and user dashboard pages
2026-03-31 13:53:49 +08:00
QTom
72e5876c64
feat(gateway): Cache-Driven RPM Buffer
...
- buffer 公式从 baseRPM/5 改为 concurrency + maxSessions
保留 baseRPM/5 作为 floor 向后兼容
- 粘性路径 fallback 新增 [StickyCacheMiss] 结构化日志
reason: rpm_red / gate_check / session_limit / wait_queue_full / account_cleared
- session_limit 路径跳过 wait queue 重试(RegisterSession 拒绝无副作用)
- 典型配置 buffer 从 3 提升至 13,大幅减少高峰期 Prompt Cache Miss
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 13:24:22 +08:00
win
d3d885cf75
fix: node-tls-proxy not receiving traffic due to viper BindEnv bug
...
CI / test (push) Failing after 6s
CI / golangci-lint (push) Failing after 5s
Security Scan / backend-security (push) Failing after 5s
Security Scan / frontend-security (push) Failing after 7s
- Add explicit viper.BindEnv() for all gateway.node_tls_proxy.* keys
to fix viper's AutomaticEnv+Unmarshal nested struct bug where env vars
are silently ignored when config.yaml lacks the corresponding section
- Sync proxy.js CLI_VERSION 2.1.84→2.1.87 and BUILD_TIME to match
constants.go, eliminating API/telemetry version mismatch
2026-03-31 13:16:02 +08:00
win
53eaae61a3
fix: TLS fingerprint lifecycle consistency and bump CLI version to 2.1.87
...
- Update User-Agent from claude-cli/2.1.84 to 2.1.87 in constants.go
and identity_service.go to match latest Claude Code binary
- Replace ImpersonateChrome() in OAuth createReqClient with Node.js 24.x
uTLS profile (tlsfingerprint.Profile) to ensure consistent JA3 hash
across token exchange, refresh, and API calls
- Support direct/HTTP-proxy/SOCKS5 proxy modes with uTLS in OAuth client
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 13:14:56 +08:00