win
a420179abb
chore: merge upstream Wei-Shaw/sub2api v0.1.133
2026-05-29 17:48:27 +08:00
github-actions[bot]
7321e4dea8
chore: sync VERSION to 0.1.133 [skip ci]
2026-05-29 08:50:18 +00:00
wucm667
c9caadb378
fix(account): address second-round review on quota auto-pause
...
- TopK initial filter now drops quota-paused accounts: fold the quota check
into isAccountRequestCompatible so session-hash, TopK pool, and per-candidate
rechecks all skip paused accounts. Previously the candidate pool was built
without the quota check, so paused accounts could fill TopK and leave the
scheduler returning "no available accounts" even with healthy ones available.
- Add per-account explicit disable flags auto_pause_5h_disabled /
auto_pause_7d_disabled with toggles in EditAccountModal. Without these,
leaving the account threshold blank silently falls back to the global default,
so admins could not exempt a single account once a global default existed.
Disable is per-window: an account can opt out of 5h auto-pause while still
honoring 7d. Schedule snapshot whitelist includes the new fields, i18n EN/ZH
updated, threshold-hint text revised to explain "blank = global default".
- Move quota auto-pause settings off the request hot path: replace the per-repo
TTL+singleflight sync DB read with a per-SettingService stale-while-revalidate
in-memory snapshot. Get is non-blocking (atomic.Pointer load + async refresh
on staleness); writes via UpdateOpsAdvancedSettings push directly into the
cache through an injected sink; wire warms the cache at startup. Adds Warm
(sync) for tests/init and SetOpenAIQuotaAutoPauseSettings (sink target).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-29 14:32:45 +08:00
win
f519a02ec9
chore: merge upstream Wei-Shaw/sub2api v0.1.132
...
Conflicts resolved (preserving fork customizations):
- config.go: keep NodeTLSProxy + add upstream OpenAIHTTP2
- gateway_service.go: NewGatewayService now takes both rpmTokenBucketSvc
(local) and userPlatformQuotaRepo (upstream)
- wire_gen.go: wire both new args into the call site
- http_upstream.go: drop redundant settings re-assignment; keep proxy
URL log redaction
- http_upstream_test.go: adopt upstream's explicit-0-disables semantics;
keep 600s default constant in nil-cfg fallback test
- user_handler_test.go / gateway_record_usage_test.go: pick up new
userPlatformQuotaRepo nil parameter
Also updated test stubs (windsurf_google_login_test.go,
windsurf_tier_access_service_test.go, gateway_models_test.go) for new
SetModelRateLimit variadic signature and the extra NewGatewayService arg.
Upstream highlights: OpenAI embeddings gateway, user x platform USD
quota, content-moderation risk thresholds, OAuth 401 credentials
no-overwrite fix, HTTP/2 OpenAI upstream config, pool retry status code
configurability, long-context cache pricing multipliers.
2026-05-29 07:21:32 +08:00
github-actions[bot]
89d96f4b25
chore: sync VERSION to 0.1.132 [skip ci]
2026-05-27 14:28:22 +00:00
github-actions[bot]
9ef144874a
chore: sync VERSION to 0.1.131 [skip ci]
2026-05-26 06:43:49 +00:00
DaydreamCoding
6b39b344d8
feat(quota): 用户 × 平台 USD 配额
...
为用户在 anthropic/openai/gemini/antigravity 四个平台上提供日/周/月
三个窗口的 USD 配额管控。配额语义:未设置=不限制,0=禁用,>0=美元上限。
两层模型:
- 配置层:系统默认配额,以及 email/linuxdo/oidc/wechat/github/google/
dingtalk 七个鉴权来源的默认配额,存于 settings,以嵌套 JSON 整体读写
(系统 1 个 key + 每个来源 1 个 key),整体替换语义。
- 运行时层:user_platform_quota 表按用户记录实际配额,与配置层解耦。
后端:新增 ent schema 与 140_user_platform_quotas.sql 迁移、repository
与 service 端口、计费链路集成、管理端与用户端读写接口。
前端:管理端设置页配额编辑、用户配额管理 Modal、用户 Dashboard 展示、
中英文案。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 10:49:20 +08:00
win
e938be5f3f
chore: merge upstream Wei-Shaw/sub2api latest (v0.1.130+)
...
Upstream features: bedrock CC compat, email whitelist wildcard,
content moderation per-model toggle, redeem code batch update,
OIDC verified-email fast path, subscription expiry email,
cache hit rate fix, audit dedup, js-cookie security fix,
x/net vulnerability fix, OpenAI account cooldown optimization,
reverse proxy client IP fix, API key ACL trusted forwarded IP.
Local additions preserved: rpmTokenBucketService, quotaFactor
scoring, P2C scheduler selection.
2026-05-24 15:54:54 +08:00
github-actions[bot]
63b0631a58
chore: sync VERSION to 0.1.130 [skip ci]
2026-05-23 06:40:10 +00:00
shaw
b6c0b40848
fix: update x/net vulnerability dependency
2026-05-23 10:55:44 +08:00
shaw
1e406fed52
fix: optimize OpenAI account cooldown scheduling
2026-05-23 10:18:43 +08:00
shaw
a613a587ba
feat: add subscription expiry email toggle
2026-05-21 14:27:50 +08:00
win
82bc1e199f
chore: remove unused real-time log stream / request event bus
...
删除 fork 独有的实时日志相关功能(上游 Wei-Shaw/sub2api 不存在):
A. OpsLogBroadcaster + SSE 日志流(前端有用但用户不需要):
- backend/internal/service/ops_log_broadcaster{,_test}.go
- backend/internal/handler/ops_log_stream_middleware.go
- backend/internal/handler/admin/ops_log_stream_handler.go
- backend/internal/server/routes/admin.go: GET /admin/ops/logs/{stream,recent}
- backend/internal/server/routes/{gateway,windsurf_gateway}.go: opsLogStream middleware
- backend/internal/service/wire.go: ProvideOpsLogBroadcaster
- frontend/src/views/admin/ops/OpsLogStreamView.vue
- frontend/src/api/admin/ops.ts: subscribeOpsLogStream, getRecentOpsLogs,
OpsLogEntry/OpsLogFilter/OpsLogRecentResponse 类型
- frontend/src/router/index.ts: AdminOpsLogStream 路由
- frontend/src/components/layout/AppSidebar.vue: 侧边栏入口
- frontend/src/i18n/locales/{en,zh}.ts: nav.opsLogStream + admin.ops.logStream 全部文案
B. RequestEventBus + WS 请求事件流(前端零调用 dead code):
- backend/internal/service/request_event_bus{,_test}.go
- backend/internal/handler/admin/ops_ws_requests_handler.go
- backend/internal/server/routes/admin.go: GET /admin/ops/ws/requests
- backend/internal/handler/gateway_handler.go: RequestEventBus 字段/参数 +
reqStartTime + reqEventAccountID/reqEventStatus 跟踪 + defer Publish
- backend/internal/service/wire.go: NewRequestEventBus
- backend/internal/handler/admin/ops_handler.go: OpsHandler 中
requestEventBus + logBroadcaster 字段,简化 NewOpsHandler 签名
保留:
- /admin/ops/ws/qps (前端 QPS 监控仍在用)
- /admin/ops/realtime-traffic (前端在用)
- OpsErrorLoggerMiddleware (与本次无关)
签名变更:
- NewOpsHandler(opsService) — 移除 requestEventBus, logBroadcaster
- NewGatewayHandler(...): 移除 requestEventBus 末位参数
- ProvideRouter / SetupRouter / registerRoutes / RegisterGatewayRoutes /
RegisterWindsurfGatewayRoutes: 移除 opsLogBroadcaster 参数
- 同步更新 wire_gen.go + 测试调用点
验证:
- 后端 go build/vet 通过
- 前端 pnpm run build 通过 (9.48s)
- 测试: 2 个 baseline 既存失败 (TestProxyImportData...,
TestWindsurfTierAccessService_Snapshot_HappyPath) 与本次无关
2026-05-20 22:43:20 +08:00
win
4e3ba04717
chore: merge upstream Wei-Shaw/sub2api v0.1.129
...
Upstream 改动 (2 commits):
- ci: 限制 CLA workflow 只在 upstream 仓库运行 (Wei-Shaw/sub2api),
避免 fork 触发 CLA 检查
- chore: VERSION 0.1.128 -> 0.1.129
无代码变更,无冲突,直接 fast-forward 风格 merge。
2026-05-20 18:07:13 +08:00
win
92433656f5
chore: merge upstream Wei-Shaw/sub2api v0.1.128 — keep fork customizations
...
Upstream 新功能 (34 commits, ~main..origin/main):
- feat(email): 通知邮件模板服务、模板编辑器、订阅/余额提醒邮件
- feat(notification): NotificationEmailService 注入到 Balance/Payment/Setting
- feat(payment): 支付成功通知邮件
- feat(usage): 用户 API Key 用量页支持按日明细
- feat(openai-gateway): Codex OAuth 浏览器 UA 自动改写规避 Cloudflare 质询
- feat(admin): 邮件模板管理接口
- fix(auth): 停用/删除分组后阻断 API Key
- fix(group): 修正分组账号可用计数口径
- fix(openai): /v1/responses respect force chat completions, images n 参数透传
- test(repository): AES Encryptor 单元测试
- chore: VERSION 0.1.128
冲突解决 (backend/cmd/server/wire_gen.go):
- 引入 upstream 新 wire providers: notificationEmailService,
ProvidePaymentService(10 args), ProvideAdminSettingHandler(8 args)
- 保留 fork 独有依赖: rpmTokenBucketService (RPM 平滑),
NewOpsHandler 3 参数版本 (requestEventBus, opsLogBroadcaster)
- ProvideBalanceNotifyService 接受 4 参数 (含 notificationEmailService)
修复 session-id helper 设计 (claude_code_session_id.go):
- 发现: TestGatewayService_AnthropicOAuth_InjectsClaudeCodeSessionHeaderFromMetadata
在 OAuth + mimicClaudeCode=false 场景失败
- 重新审视设计原则: OAuth 凭证本身就是 Claude Code 客户端,可信任 metadata
派生 session_id;不应受 mimicClaudeCode 标志阻止
- 修复: metadata 派生只看 tokenType=="oauth";UUID 兜底仍需 oauth && mimic
- 更新测试: OAuthNonMimicDerivesFromMetadata 取代原 IgnoresMetadata
所有 fork 独有功能保留:
- Claude Code 2.1.145 mimicry bundle (上个 commit 引入)
- RPM token bucket smoothing (commit 95814974)
- Windsurf/Antigravity/Omniroute 定制
- claudemask/ 校验包 (upstream 已删除,我们仍在 gateway_service 中使用)
不在范围:
- 不修复 baseline 既存的 2 个测试失败 (TestProxyImportData...,
TestWindsurfTierAccessService_Snapshot_HappyPath) - 与 merge 无关
2026-05-20 17:50:44 +08:00
github-actions[bot]
771e0ca973
chore: sync VERSION to 0.1.129 [skip ci]
2026-05-20 09:11:41 +00:00
github-actions[bot]
f5a2ad688a
chore: sync VERSION to 0.1.128 [skip ci]
2026-05-20 07:44:15 +00:00
Wesley Liddick
378a0a6a61
Merge pull request #2599 from Arron196/feature/email-template-editor
...
feat: 添加邮件模板编辑器与通知邮件模板化
2026-05-20 15:12:57 +08:00
win
158785bfc9
chore: merge upstream v0.1.127 — keep omniroute customizations
...
Upstream highlights:
- v0.1.127 release (150 commits): channel-monitor 协议管理、OpenAI
Responses 路由配置、模型定价 LiteLLM 默认、payment 强制扫码、
钉钉 OAuth、用户用量按平台拆分、Ops 错误分类 SLA 调整、
Anthropic passthrough keepalive、Gemini chat completions 路由 ...
- 91da8159 feat(risk-control): 内容审计新增关键词拦截
- 3d22dd34 feat: gemini-3.5-flash 模型支持
Conflicts resolved:
- Dockerfile: keep pnpm pin to 9.15.9 (upstream pinned generic v9 floating).
- wire_gen.go: combine upstream NewSettingHandler(+userAttributeService)
with local NewOpsHandler(opsService, requestEventBus, opsLogBroadcaster).
Verified by re-running wire generate.
- scheduler_cache.go: keep both upstream openai_responses_{mode,supported}
keys and local model_rate_limits key in filterSchedulerExtra().
- gateway_service.go: keep local context-compression block; drop now-dead
setOpsUpstreamRequestBody call (upstream removed ops retry replay).
- docker-compose.yml: keep local windsurf-ls service profile and named
volumes; keep local healthcheck start_period values.
Test mock signatures bumped to match current constructors:
- gateway_models_test.go: add nil for RPMTokenBucketService.
- account_handler_available_models_test.go: add nil for windsurfChatService.
2026-05-20 12:39:40 +08:00
benjamin
8cef9a7ab1
chore(wire): 注入通知邮件服务
...
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent )
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-20 11:09:18 +08:00
wucm667
92ad68a314
feat(channels): 模型定价支持一键同步最新模型
...
从 LiteLLM 定价目录中读取指定平台的最新模型列表,
将尚未录入的模型以新定价条目(价格留空)的形式追加,
管理员只需点击同步最新模型按钮即可完成操作。
- backend/service: PricingService 新增 ListModelNamesByProvider
- backend/handler: ChannelHandler 新增 SyncPricingModels (GET /api/v1/admin/channels/pricing/sync-models)
- backend/routes: 注册新路由(在 /:id 通配符之前)
- backend/wire_gen: 手动更新 NewChannelHandler 调用
- frontend/api: channels.ts 新增 syncPricingModels
- frontend/i18n: zh.ts / en.ts 新增 5 个 key
- frontend/view: ChannelsView 定价区域标题行新增「同步最新模型」按钮
- tests: pricing_service_test + channel_handler_test 新增单元测试
2026-05-19 20:32:32 +08:00
github-actions[bot]
8927ab091e
chore: sync VERSION to 0.1.127 [skip ci]
2026-05-19 09:51:46 +00:00
DaydreamCoding
b19da9c7fe
feat(dingtalk): 钉钉 OAuth 登录接入与 internal_only 用户属性同步
...
⚠️ 应用类型约束:当前实现仅支持「钉钉登录-企业内部应用」(DingTalk 开放平台
internal_app 类型)。第三方个人应用、第三方企业应用类型暂不支持——OAuth 流程
相同但 corp 校验、跨企业行为不同。backend 通过 DingTalkAppKind 校验对非
internal_app 类型 fail-closed(硬约束)。
钉钉 OAuth 登录主链
- 4 步 OAuth 链:ExchangeCodeForUserToken / GetUnionIdByUserToken /
GetUserIdByUnionId / GetStaffInfoByUserId;app token 缓存
- pending session 机制持久化 OAuth 中间态;cookie-only token 持久化
- 三种分流:bind_login_required / email_completion / choose_account_action
- corp_restriction_policy 支持 none + internal_only;stale "whitelist" 在
加载层与写入层均静默 coerce 为 none + slog.Warn
- bypass_registration 开关:企业内部模式豁免全局 REGISTRATION_DISABLED
- isReservedEmail / signup_source / canUnbindProvider / OAuth pending flow
等横切点支持 dingtalk provider
- migration 136:4 表 CHECK 约束加入 'dingtalk' provider 值
internal_only 模式同步企业邮箱/姓名/部门到用户属性
- SyncCorpEmail / SyncDisplayName / SyncDept 三个独立开关 + 对应
SyncXxxAttrKey 目标属性 key(默认 dingtalk_email / dingtalk_name /
dingtalk_department);非 internal_only policy 在写入层与加载层均
coerce 为 false,admin handler 与 setting_service 双层兜底
- 同步语义:首次注册写 users.username(昵称优先 → 企业姓名 fallback),
之后每次登录刷新 3 个属性;空值也写入以覆盖旧值
- 邮箱三级 fallback:org_email > email > extension["企业邮箱"]
(钉钉自定义字段 JSON)
- 部门路径递归向上拼接,跳过 dept_id=1 选首个真实子部门,剥离根组织名
- GetUnionIdByUserToken 同时返回 OIDC /contact/users/me 的 nick 字段;
新增 GetDeptInfo 调用 OAPI /topapi/v2/department/get
- AuthHandler 注入 UserAttributeService;OAuth pending flow 在
createPendingOAuthAccount / bindPendingOAuthLogin 分别派发到
AfterRegistration(syncUsername=true)/ AfterLogin
- migration 137 seed dingtalk_email/name/department 三个用户属性定义
附带修复(同集成路径暴露的两个 OAuth 注册回归)
- LoginOrRegisterOAuthWithTokenPair 新建用户分支用 inferLegacySignupSource
覆写 caller 显式传入的 signupSource,导致 dingtalk/linuxdo/oidc/wechat
渠道授权按 email 渠道读取;改为只在 caller 未显式传入时回退邮箱推断
- mergeProviderDefaultGrantSettings 把 parse fallback 默认值
(Concurrency=5 / Balance=0) 当作"未配置"哨兵,admin 显式设 5 时被误判
退回全局默认(复现:全局默认 1 + 渠道默认并发 5 + grant_on_signup → 新
用户实际 concurrency=1);去掉哨兵,admin 任何 >=0 值都覆盖 globalDefaults
前端
- DingTalk Login / Callback / EmailCompletion / ChoiceAccount / Error
视图;router + auth API client
- admin SettingsView:corp policy radio(none / internal_only)+ bypass
注册开关 + i18n;internal_only 下展示三同步开关 + 目标 attr key 下拉
(拉取 user attribute definitions),展示 fieldEmail /
qyapi_get_department_list 钉钉权限申请提示
- Profile:S1 主动绑定 / S5 解绑钉钉按钮 + 合成邮箱防自锁
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 15:27:47 +08:00
win
35c6c2b097
chore: merge upstream v0.1.126 — Airwallex, OpenAI fixes, Antigravity UA config
...
吸收上游 26 个新 commit:
- feat: Airwallex 支付 + 多币种支持 (b23055af)
- feat: Antigravity user agent 版本可配置 (a07a0dac)
- fix(mimic): 同步 messages 里 tool_use 名称 (f97b8534)
- fix: cache_control 改写默认关闭 (9377c967)
- fix(openai): 多 tool_use 上下文延续 (87d73236)
- fix(openai): 未定价模型零成本记录 (6d69ae87)
- fix(openai): WS replay tool 输出延续 (16a31557)
- fix(openai): 429 plan type 同步 (c3a14717)
- fix(gemini): Vertex token 走 account proxy (2a17c0b2)
- fix(ccswitch): codex 模型 import deeplink (65493df9)
- fix: 订单详情/支付页 NaN 修复 (ba1c6fa5, 6884b03e)
- 系统设置标签导航优化 (18cc4691)
本地解决:
- config.go CSP: 合并 Firebase Auth (Windsurf) + Airwallex 域名
- KeysView.vue: 删除死代码(已被 buildCcSwitchImportDeeplink 取代)
- ccswitchImport.ts: 补充 windsurf 平台 case
- 修复 NewOpsHandler/RegisterGatewayRoutes/SelectAccountWithScheduler 测试签名
保留:
- Antigravity newapi 兼容 (ForwardUpstream /v1/messages 透传)
- Antigravity 核心(gateway_service, oauth, client, credits_overages 等)
- Windsurf 全套
- Claude 网关 + TLS 指纹路由
- 其他本地 feat: P2C 调度 / viewer / context 压缩 / RPM / fallback / health
2026-05-12 13:48:40 +08:00
win
8d0ef3d2ef
chore: antigravity 瘦身,删除边缘文件保留核心
2026-05-12 12:19:22 +08:00
github-actions[bot]
62ccd0ff39
chore: sync VERSION to 0.1.126 [skip ci]
2026-05-11 15:30:51 +00:00
win
7347dfffc1
chore: merge upstream v0.1.124-125, keep Windsurf/Antigravity customizations
...
Upstream changes:
- feat: 邮箱 + GitHub + Google OAuth 快捷登录
- feat: Codex image bridge 开关
- feat: 内容审核 (content moderation) — 新增 contentModerationService/Handler
- feat: redeem code 返利、批量并发 API、markdown 页面渲染
- feat: 登录注册条款确认
- fix(security): pages API 加 JWT + 可见性校验
- fix: 修复 markdown 页面图片路径
- fix(gateway): 不再默认注入 redact thinking beta
- fix: 稳定 anthropic passthrough 超时错误
- chore: VERSION 升到 0.1.125 + golang:1.26.3-alpine
Conflict resolutions:
- Dockerfile/backend/Dockerfile: 取 upstream golang:1.26.3-alpine
- backend/go.mod: 取 upstream term v0.42.0,保留定制 protobuf v1.36.10
- frontend/src/api/admin/index.ts: 并集 (windsurf + riskControl)
- backend/cmd/server/wire_gen.go: 接 upstream contentModeration*,保留 windsurfHandler/windsurfGatewayService/billingCacheService/requestEventBus;并通过 wire 重生成
- frontend/src/views/admin/AccountsView.vue: 采用 upstream 双层布局 + OpenAI Meta,保留 is_enterprise prop 和 Windsurf tier badge
Note:
- WIP commit (de048fad) preserved Windsurf tier access service / NLU
extractor / ops log stream / Google OAuth login modal et al before merge.
- 3 pre-existing go vet issues in test files (NewOpsHandler, RegisterGatewayRoutes,
DefaultCLIProductVersion) are unrelated to this merge — leftover from local
customization refactors; production code (go build ./...) passes.
2026-05-09 01:42:39 +08:00
win
de048fad25
chore(wip): save Windsurf/Antigravity/ops customizations before upstream merge
...
WIP commit保存以下定制工作以便后续合并 upstream v0.1.124-125:
- Windsurf: tier access service, NLU extractor, cold threshold, Google login
- Antigravity: client/oauth 调整
- Ops: log stream handler/broadcaster/middleware, OpsLogStreamView
- Frontend: WindsurfLoginModal Google, GoogleIcon, AccountsView, sidebar/router/i18n
2026-05-09 00:41:19 +08:00
github-actions[bot]
a466e80ed6
chore: sync VERSION to 0.1.125 [skip ci]
2026-05-07 11:42:30 +00:00
github-actions[bot]
f3577bc69c
chore: sync VERSION to 0.1.124 [skip ci]
2026-05-07 03:21:26 +00:00
Wesley Liddick
d52da45363
Merge pull request #2202 from Michael-Jetson/main
...
新增三大功能:兑换码邀请返利、批量修改用户并发数、Markdown页面渲染
2026-05-07 09:35:14 +08:00
shaw
fff4a300c6
feat(risk-control): add content moderation audit
2026-05-07 09:14:47 +08:00
win
3fe228d143
chore: merge upstream v0.1.122-123, keep Windsurf/Antigravity customizations
...
New upstream features:
- feat: improve OpenAI messages compatibility for Claude Code
- feat: image generation stream & concurrency controls
- fix(rate-limit): remove 429 cooldown config option
- fix: skip previous_response_id recovery when payload has function_call_output
- feat: support select search in group/account views
- fix: ops cleanup settings
- chore: remove openspec and update axios
Conflict resolutions:
- config.go: kept AntigravityLSWorker+NodeTLSProxy AND added ImageConcurrency
- account_test_service.go: kept windsurf import AND added openai_compat import
- docker-compose.yml: kept Windsurf env vars AND added image concurrency env vars
2026-05-06 11:50:54 +08:00
Michael-Jetson
4cbd4932a0
feat: add redeem code affiliate rebate, batch concurrency API, and markdown page rendering
...
1. Redeem code affiliate rebate: balance-type redeem codes now trigger
invite rebate for the inviter. Payment fulfillment uses context key
to prevent double-rebate.
2. Batch concurrency update: new POST /admin/users/batch-concurrency
endpoint supporting mode=set/add with all=true for all users.
3. Markdown page rendering: new GET /api/v1/pages/:slug API serves local
.md files. Custom menu items with url="md:slug" render markdown with
collapsible TOC sidebar, scroll spy, and copy buttons on code blocks.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-05 06:44:37 -07:00
Wesley Liddick
ab918fde37
Merge pull request #2180 from touwaeriol/feat/fix-ops-cleanup-settings
...
fix(ops-cleanup): wire UI data-retention settings into OpsCleanupService
2026-05-05 20:36:46 +08:00
github-actions[bot]
4de28fec8c
chore: sync VERSION to 0.1.123 [skip ci]
2026-05-04 10:25:38 +00:00
erio
c4598aa9b6
fix(ops-cleanup): 让 UI 数据保留策略真正生效
...
UI 上 admin 改的数据保留策略(cron + retention 天数)此前只写入 settings 表的
ops_advanced_settings.data_retention,但 OpsCleanupService 启动时只读
cfg.Ops.Cleanup(config.yaml / 环境变量),从未读取 settings 表,导致 UI 配置
完全不生效——cron 实际仍按默认 0 2 * * * 每日跑、retention 30 天。
改动:
- OpsCleanupService 增加 settingRepo 依赖,新增 effective 配置 + Reload 方法。
Start/Reload 时从 settings.ops_advanced_settings.data_retention 覆盖
cfg.Ops.Cleanup(Enabled、Schedule、*RetentionDays),无 settings 时整体
fallback 到 cfg。runScheduled 顶部刷新一次 effective,让 retention 改动当次
即生效(schedule/enabled 改动需要 Reload 才换 cron)。
- 用 mu + started/stopped 替换 startOnce/stopOnce 以支持 Reload 重建 cron。
- OpsService 增加 CleanupReloader 接口与 SetCleanupReloader setter;
UpdateOpsAdvancedSettings 写入后调用 Reload。
- wire 通过 setter 注入 cleanup hook,避免构造期循环依赖。
- 新增单测覆盖 overlay 五种情形 + Update 触发 Reload。
2026-05-04 12:43:15 +08:00
github-actions[bot]
d9e68f2ca1
chore: sync VERSION to 0.1.122 [skip ci]
2026-05-03 16:32:09 +00:00
win
c5eb305f7f
chore: merge upstream v0.1.119-121, keep Windsurf/Antigravity customizations
...
Upstream changes merged:
- fix(scheduler): resolve SetSnapshot race conditions with Lua CAS script
- fix: improve sticky session scheduling (debug logs + layer 1.5 checks)
- feat: Anthropic cache TTL injection toggle
- fix(gateway): stream EOF failover + sanitize stream errors
- feat(httputil): zstd/gzip/deflate request decompression + bomb guard
- feat(openai): OpenAI Fast/Flex Policy (HTTP + WebSocket + Admin)
- feat(vertex): Vertex Service Account support
- feat: account bulk edit scope and compact settings
- feat(affiliate): rebate freeze migration
- fix(openai): various fixes (passthrough fields, compact payload, etc.)
Conflict resolutions:
- domain/constants.go: keep both AccountTypeWindsurfSession + AccountTypeServiceAccount
- scheduler_cache_unit_test.go: keep both test functions
- gateway_service.go: remove dead code (claudeCodeUserAgentRe, isClaudeCodeRequest)
- wire_gen.go: keep Windsurf service chain + add upstream claudeTokenProvider param
- frontend/src/types/index.ts: keep windsurf + service_account types
- frontend CreateAccountModal.vue: keep Windsurf login + Vertex service_account blocks
- frontend PlatformTypeBadge.vue: keep both Session + Vertex cases
- account_test_service.go: fix createTestPayload call to pass empty prompt arg
2026-05-02 16:52:21 +08:00
github-actions[bot]
48912014a1
chore: sync VERSION to 0.1.121 [skip ci]
2026-04-30 06:06:12 +00:00
github-actions[bot]
8ad099baa6
chore: sync VERSION to 0.1.120 [skip ci]
2026-04-29 15:08:59 +00:00
Wesley Liddick
17ced6b73a
Merge pull request #2027 from hansnow/codex/fix-api-key-rate-limit-reset
...
fix(api-key): reset rate limit usage cache
2026-04-29 21:27:52 +08:00
Wesley Liddick
63ef23108c
Merge pull request #1977 from sholiverlee/vertex
...
feat: 支持 Vertex Service Account(Anthropic / Gemini)
2026-04-29 15:48:26 +08:00
win
fdd2d08a4d
feat: merge feat/omniroute-ideas — P2C scheduler, quota scoring, tier fallback
2026-04-29 15:42:37 +08:00
win
0a3666ef24
x
Security Scan / backend-security (push) Failing after 1m31s
Security Scan / frontend-security (push) Failing after 7s
CI / test (push) Failing after 6s
CI / frontend (push) Failing after 4s
CI / golangci-lint (push) Failing after 4s
CI / windsurf-platform (macos-latest) (push) Has been cancelled
CI / windsurf-platform (windows-latest) (push) Has been cancelled
2026-04-29 10:32:36 +08:00
win
d1e2d39c26
feat(viewer): add real-time request stream WebSocket endpoint
...
Adds GET /api/v1/admin/ops/ws/requests — a fan-out WebSocket that pushes
per-request metadata (method, path, model, account_id, status, latency_ms)
to all connected admin clients the moment each gateway dispatch completes.
- service/request_event_bus.go: lock-free pub/sub with non-blocking drop
when per-subscriber buffer (64 slots) is full; nil-safe Publish
- service/request_event_bus_test.go: 6 tests (basic, fanout, drop, nil, close)
- GatewayHandler: records reqStartTime at entry; defer emits RequestEvent on
every return; sets status success/error/rate_limited in both Gemini and
Anthropic dispatch paths
- OpsHandler: accepts *RequestEventBus; wires it to RequestStreamWSHandler
- ops_ws_requests_handler.go: subscribes to bus, pushes JSON per event,
reuses existing upgrader/conn-limit/ping-pong infrastructure
- Route: ws.GET("/requests", ...) alongside existing /ws/qps
- wire_gen.go: requestEventBus shared between OpsHandler and GatewayHandler
2026-04-29 01:48:15 +08:00
win
95814974de
feat(rpm): add token bucket smoothing for RPM rate limiting
...
- New RPMTokenBucketService: per-account continuous-refill token buckets
(rate = rpm/60 tokens/sec, capacity = rpm). No new dependencies.
- GatewayService.AcquireRPMToken() delegates to the bucket service.
- Gateway handler inserts RPM token wait BEFORE wrapReleaseOnDone in both
Gemini and Anthropic dispatch paths; timeout returns 429 and releases slot.
- Config: gateway.rpm_smoothing.enabled (default false) + max_wait_ms (default 5000).
- 7 unit tests covering: immediate acquire, zero RPM, timeout, wait+refill,
context cancel, account isolation, bucket reset on RPM change.
2026-04-29 01:22:54 +08:00
win
110902ad4b
feat(health): split liveness and readiness probes
...
Add HealthService with Liveness (no-op) and Readiness (DB+Redis ping
with per-component timeout) checks. Expose three endpoints:
- /healthz : new liveness endpoint, zero-dependency, always 200
- /ready : new readiness endpoint, returns 503 with details on dep
failure; suitable for K8s readinessProbe and load balancers
- /health : preserved for backward compatibility, equivalent to
/healthz
Switch primary docker-compose healthcheck to /ready so the container
is only marked healthy once DB+Redis are reachable. Standalone/dev/
local compose files keep /health to avoid disrupting existing setups.
Tests: unit tests cover liveness, readiness with both deps healthy,
each dep failing independently, and per-component timeout enforcement.
2026-04-28 23:39:50 +08:00
DaydreamCoding
30f55a1f72
feat(openai): OpenAI Fast/Flex Policy 完整实现(HTTP + WebSocket + Admin)
...
对称参照 Claude BetaPolicy 的 fast-mode 过滤实现,新增针对 OpenAI 上游
service_tier 字段(priority / flex,含客户端 "fast" → "priority" 归一化)的
pass / filter / block 三态策略,覆盖全部 OpenAI 入口 + admin 配置入口。
后端核心
- 新增 SettingKeyOpenAIFastPolicySettings、OpenAIFastPolicyRule、
OpenAIFastPolicySettings 配置模型,含规则的 service_tier × action × scope
× 模型白名单 × fallback action 维度。
- SettingService.Get/SetOpenAIFastPolicySettings;缺失时返回内置默认策略
(所有模型的 priority 走 filter,whitelist 为空,fallback=pass)。设计
依据:service_tier=fast 是用户级开关,与 model 字段正交,默认锁定特定
model slug 会留下"用 gpt-4 + fast 透传 priority 上游"的绕过路径。JSON
解析失败不再静默 fallback,slog.Warn 记录脏数据,便于运维定位。
- service_tier 归一化(trim + ToLower + fast→priority + 白名单 priority/flex)
与策略评估(evaluateOpenAIFastPolicy)作为唯一真实来源,HTTP / WS 共用。
抽出纯函数 evaluateOpenAIFastPolicyWithSettings,配合 ctx-bound settings
快照(withOpenAIFastPolicyContext / openAIFastPolicySettingsFromContext),
WS 长会话入口预取一次后所有帧复用,避免每帧打到 settingService。
HTTP 入口(4 个)
- Chat Completions、Anthropic 兼容(Messages,含 BetaFastMode→priority 二次
命中)、原生 Responses、Passthrough Responses 全部接入
applyOpenAIFastPolicyToBody,filter 走 sjson 顶层删除 service_tier,block
返回 403 forbidden_error JSON。
- 4 入口统一使用 upstream 视角的 model(GetMappedModel +
normalizeOpenAIModelForUpstream + Codex OAuth normalize 后的 slug),
避免 chat/messages/native /responses/passthrough 因为 model 维度不同
造成 whitelist 命中差异。
- 在 pass 路径也把客户端 "fast" 别名归一化为 "priority" 写回 body,
否则 native /responses 与 passthrough 入口会把 "fast" 原样透传给上游
导致 400/拒绝(chat-completions 入口的 normalizeResponsesBodyServiceTier
此前已具备同等行为)。
WebSocket 入口
- 新增 applyOpenAIFastPolicyToWSResponseCreate:严格匹配
type="response.create",仅处理顶层 service_tier;filter 用 sjson 删字段,
block 返回 typed *OpenAIFastBlockedError。
- ingress 路径在 parseClientPayload 内调用,block 命中先 Write Realtime
风格 error event 再返回 OpenAIWSClientCloseError(StatusPolicyViolation
=1008),依赖底层 WebSocket Conn.Write 的同步 flush 保证 error 先于
close。
- passthrough 路径在 RunEntry 前对 firstClientMessage 应用策略,并通过
openAIWSPolicyEnforcingFrameConn 包装 ReadFrame 对每个 client→upstream
帧执行策略;后续帧无 model 字段时回退到 capturedSessionModel。
filter 闭包内同时侦测 session.update / session.created 帧的 session.model
字段刷新 capturedSessionModel,封堵"首帧 model=gpt-4o(pass)→
session.update 改为 gpt-5.5 → 不带 model 的 response.create fallback
到 gpt-4o"的 mid-session 绕过路径。
- passthrough billing:requestServiceTier 在策略 filter 之后再从
firstClientMessage 提取,filter 命中时 OpenAIForwardResult.ServiceTier
上报 nil(default tier),与 HTTP 入口(reqBody 来自 post-filter map)
/ WS ingress(payload 来自 post-filter bytes)的语义一致。
- 错误事件 schema:{event_id: "evt_<32hex>", type: "error",
error: {type: "forbidden_error", code: "policy_violation", message}},
与 OpenAI codex 客户端 error event 解析兼容。
Admin / Frontend
- dto.SystemSettings / UpdateSettingsRequest 新增
openai_fast_policy_settings 字段(omitempty),bulk GET/PUT 接入。
- Settings 页 Gateway 页签新增 Fast/Flex Policy 表单卡片:
service_tier × action × scope × 模型白名单 × fallback action 全字段配置。
- 前端守门:openaiFastPolicyLoaded 标志仅在 GET 真带回字段时才允许回写,
避免 rollout/错误把默认规则覆盖成空;saveSettings 回写循环 skip 该字段,
由专用刷新逻辑处理;仅 action=block 时发送 error_message,匹配后端
omitempty 行为。
测试
- HTTP 路径:openai_fast_policy_test.go 覆盖默认配置(whitelist=[],所有
模型 priority filter)/ block 自定义错误 / scope 区分 / filter 删字段 /
block 不改 body / block 短路上游 / Anthropic BetaFastMode 触发 OpenAI
fast policy 等场景。
- WebSocket 路径:openai_fast_policy_ws_test.go 覆盖
helper 单元(filter / fast→priority 归一化 / flex 透传 / block typed
error / 无 service_tier 字节不变 / 非 response.create 帧不动 / 空 type
帧不动 / event_id+code 字段断言 / 非字符串 service_tier 容错)+
pass 路径 fast 别名归一化回归 +
ingress 端到端(filter 后上游不含 service_tier / block 后客户端先收
error event 再收 close 1008 且上游 0 写)+
passthrough capturedSessionModel fallback 用例(whitelist 策略下首帧
建立、缺 model 命中 fallback、缺少 fallback 时的 leak 文档化)+
passthrough session.update / session.created 旋转 capturedSessionModel
的 mid-session 绕过回归 +
passthrough billing post-filter ServiceTier 与 idempotent filter 回归。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 11:15:09 +08:00
win
9da079a5ee
x
Security Scan / backend-security (push) Failing after 3s
Security Scan / frontend-security (push) Failing after 5s
CI / test (push) Failing after 3s
CI / frontend (push) Failing after 3s
CI / golangci-lint (push) Failing after 3s
CI / windsurf-platform (macos-latest) (push) Has been cancelled
CI / windsurf-platform (windows-latest) (push) Has been cancelled
2026-04-27 19:01:41 +08:00