1191 Commits

Author SHA1 Message Date
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
shaw
fda1ed459d feat: 优化 OAuth 账号导入流程 2026-05-08 11:36:09 +08:00
shaw
e872cbec0b feat: 添加登录注册条款确认 2026-05-07 17:35:05 +08:00
shaw
6681aee98d 更新账号模型白名单 2026-05-07 15:11:38 +08:00
shaw
0eca600ffa fix moderation key handling and key UI 2026-05-07 14:31:19 +08:00
shaw
7a9c1d7edd feat(frontend): add account Codex image bridge control 2026-05-07 11:07:33 +08:00
Wesley Liddick
45b1e6ae41
Merge pull request #2233 from Arron196/fix/codex-image-generation-bridge-switch
fix(openai): 增加 Codex 图片生成桥接显式开关
2026-05-07 10:30:26 +08:00
Wesley Liddick
e69319e747
Merge pull request #2224 from lyen1688/feat-email-oauth-github-google
feat: 增加 GitHub 和 Google 邮箱快捷登录
2026-05-07 10:07:28 +08:00
shaw
989f87fe08 fix: harden markdown page image paths 2026-05-07 10:05:49 +08: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
Jlypx
246e48215d feat(frontend): add Codex image bridge toggle
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-07 00:10:20 +08:00
lyen1688
e69256a706 fix: 完善邮箱快捷登录注册流程 2026-05-06 20:52:10 +08:00
lyen1688
7f185422a5 fix: 修复邮箱快捷登录前端回调兜底 2026-05-06 20:03:44 +08:00
lyen1688
af550fa64e feat: 增加 GitHub 和 Google 邮箱快捷登录 2026-05-06 16:06:11 +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
cf2d5067c3 fix(security): add JWT auth + visibility check to pages API
- GET /pages/:slug now requires JWT + checks custom_menu_items visibility
- GET /pages (list) is admin-only
- GET /pages/:slug/images/* uses visibility check without JWT (browser
  img tags cannot carry auth headers), blocks admin-only page images
- Frontend fetch adds Authorization header from authStore.token
- settingService nil guard changed to fail-closed (deny access)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-05 07:00:08 -07: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
a1106e8167
Merge pull request #2165 from zhangdeyu/feature/support-select-search
feat: Select 和 GroupSelector 组件支持自动搜索
2026-05-05 21:10:07 +08:00
Wesley Liddick
37f7c7128c
Merge pull request #2120 from gaoren002/fix/rate-limit-429-cooldown-config
fix(rate-limit): make 429 fallback cooldown configurable
2026-05-05 19:46:11 +08:00
shaw
dc05d4b250 chore: remove openspec and update axios 2026-05-05 17:13:25 +08:00
2ue
6faa344916 feat: add OpenAI image generation controls 2026-05-05 03:26:54 +08:00
Wesley Liddick
c129825f9b
Merge pull request #2116 from KnowSky404/fix/openai-bulk-edit-compact-config
fix: add OpenAI compact bulk edit fields
2026-05-04 00:14:46 +08:00
shaw
0b84d12dbb fix: correct affiliate audit record sources 2026-05-03 22:12:57 +08:00
lyen1688
3ab40269b4 完善返利转入余额历史显示 2026-05-03 20:33:14 +08:00
lyen1688
650ddb2e39 fix: make affiliate record users clickable 2026-05-03 20:33:14 +08:00
lyen1688
6a41cf6a51 feat: add admin affiliate record pages 2026-05-03 20:33:13 +08:00
Derek
f2f6bc6c04 feat: Select 和 GroupSelector 组件支持自动搜索
当选项数量 > 5 时自动启用搜索过滤,无需修改任何使用处代码。
- Select.vue: searchable 默认值改为 'auto',内部自动判断
- GroupSelector.vue: 新增 searchable prop 和搜索输入框
2026-05-02 23:57:10 +08: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
Wesley Liddick
9c448f89a8
Merge pull request #2118 from DaydreamCoding/fix/restore-pagination-localStorage
fix: 恢复表格分页大小 localStorage 持久化
2026-04-30 13:42:18 +08:00
shaw
73b872998e feat: 添加 Anthropic 缓存 TTL 注入开关 2026-04-30 13:38:22 +08:00
gaoren002
4b904c887c fix(rate-limit): make 429 fallback cooldown configurable 2026-04-30 03:01:39 +00:00
DaydreamCoding
f084d30d65 fix: 恢复表格分页大小 localStorage 持久化
- usePersistedPageSize: 恢复 localStorage 读写,以系统配置为 fallback
- useTableLoader: handlePageSizeChange 时写入 localStorage
- Pagination.vue: handlePageSizeChange 时写入 localStorage

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-30 10:35:15 +08:00
KnowSky404
3953dc9ce4 fix: add OpenAI compact bulk edit fields 2026-04-30 10:19:59 +08:00
shaw
8bf2a7b88a fix(scheduler): resolve SetSnapshot race conditions and remove usage throttle
Backend: Fix three race conditions in SetSnapshot that caused account
scheduling anomalies and broken sticky sessions:
- Use Lua CAS script for atomic version activation, preventing version
  rollback when concurrent goroutines write snapshots simultaneously
- Add UnlockBucket to release rebuild lock immediately after completion
  instead of waiting 30s TTL expiry
- Replace immediate DEL of old snapshots with 60s EXPIRE grace period,
  preventing readers from hitting empty ZRANGE during version switches

Frontend: Remove serial queue throttle (1-2s delay per request) from
usage loading since backend now uses passive sampling. All usage
requests execute immediately in parallel.
2026-04-29 22:48:39 +08:00
Wesley Liddick
27cad10d30
Merge pull request #2030 from KnowSky404/feature/account-bulk-edit-scope-and-compact
feat: support filtered account bulk edit and align compact OpenAI bulk fields
2026-04-29 20:56:43 +08:00
shaw
93d91e20b9 fix(vertex): audit fixes for Vertex Service Account feature (#1977)
- Security: force token_uri to Google default, preventing SSRF via crafted service account JSON
- Dedup: extract shared getVertexServiceAccountAccessToken() to eliminate ~35 lines of duplication between ClaudeTokenProvider and GeminiTokenProvider
- Fix: apply model mapping + Vertex model ID normalization in forward_as_responses and forward_as_chat_completions paths
- Fix: exclude service_account from AI Studio endpoint selection (Vertex cannot serve generativelanguage.googleapis.com)
- Feature: add model restriction/mapping UI for service_account in EditAccountModal
- Dedup: extract VERTEX_LOCATION_OPTIONS to shared constants
- i18n: replace all hardcoded Chinese strings in Vertex UI with translation keys
2026-04-29 16:53:09 +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
erio
4b6954f9f0 feat(ops): allow retention days = 0 to wipe table on each scheduled cleanup
Background / 背景

The ops cleanup task currently rejects retention days < 1 in both validate
and normalize, so operators who want minimal-history setups (e.g. high
churn deployments that prefer near-realtime cleanup) cannot express that
intent through the UI. The only options are 1+ days, which keeps at least
24h of history regardless of cron frequency.

ops 清理任务目前在 validate 和 normalize 两处都拒绝小于 1 的保留天数,
让希望尽量不留历史的运维场景(高吞吐部署 + 想用近实时清理)无法通过 UI
表达。最低只能配 1,等于不管 cron 多频繁,至少都会保留 24 小时的历史。

Purpose / 目的

Let admins set retention days to 0, meaning "every scheduled cleanup
run wipes the corresponding table(s) entirely". Combined with a more
frequent cron (e.g. `0 * * * *`) this yields effectively rolling cleanup.

允许管理员把保留天数设为 0,语义为"每次定时清理时把对应表全部清空"。
搭配更频繁的 cron(比如每小时整点)即可获得近似滚动清理的效果。

Changes / 改动内容

Backend

- service/ops_settings.go: validate accepts [0, 365]; normalize only
  refills default 30 when value is < 0 (negative is treated as legacy
  bad data, 0 is honoured)
- service/ops_cleanup_service.go: introduce `opsCleanupPlan(now, days)`
  returning `(cutoff, truncate, ok)`. days==0 returns truncate=true and
  short-circuits to a new `truncateOpsTable` helper that uses
  `TRUNCATE TABLE` (O(1), no WAL, no VACUUM pressure). days>0 keeps
  the existing batched DELETE path unchanged. Empty tables skip
  TRUNCATE to avoid the ACCESS EXCLUSIVE lock entirely
- Extract `isMissingRelationError` helper to dedupe the "table not
  yet created" tolerance shared by both delete and truncate paths
- Add unit tests for `opsCleanupPlan` (three branches) and
  `isMissingRelationError`

后端

- service/ops_settings.go: validate 接受 [0, 365];normalize 仅在 < 0
  时回填默认 30(负数视为脏数据,0 被尊重)
- service/ops_cleanup_service.go: 抽 `opsCleanupPlan(now, days)` 返回
  `(cutoff, truncate, ok)`。days==0 → truncate=true,走新增
  `truncateOpsTable`(TRUNCATE TABLE,O(1),无 WAL、无 VACUUM 压力);
  days>0 仍走原批量 DELETE 路径,行为完全不变。空表跳过 TRUNCATE,
  避免无意义的 ACCESS EXCLUSIVE 锁
- 抽 `isMissingRelationError` helper 复用 delete / truncate 两处的
  "表不存在"宽容判断
- 补 `opsCleanupPlan` 三分支 + `isMissingRelationError` 单元测试

Frontend

- OpsSettingsDialog.vue: validation accepts [0, 365]; input min=0
- i18n (zh/en): hint mentions "0 = wipe all on every cleanup",
  validation message updated to 0-365 range

前端

- OpsSettingsDialog.vue: 校验放宽到 [0, 365],input min 改 0
- i18n(zh/en):hint 补"0 = 每次清理时清空所有",错误提示改 0-365

Trade-offs / 取舍

- TRUNCATE requires ACCESS EXCLUSIVE lock briefly, but ops tables only
  have the cleanup task as a writer, so the lock is invisible to other
  workloads
- Empty-table guard avoids the lock when there is nothing to clean
- Negative values are still treated as legacy bad data and replaced
  with default 30 to preserve compatibility
2026-04-29 15:01:02 +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
KnowSky404
53b24bc2d8 fix: tighten account bulk edit target typing 2026-04-27 18:20:36 +08:00
KnowSky404
a161f9d045 feat: align OpenAI bulk edit compact settings 2026-04-27 18:15:23 +08:00
KnowSky404
c5a1a82223 test: cover missing OpenAI bulk edit fields 2026-04-27 18:13:14 +08:00
KnowSky404
2ab6b34fd1 feat: add filtered-result account bulk edit 2026-04-27 18:12:24 +08:00
KnowSky404
764afbe37a test: cover account bulk edit target scopes 2026-04-27 18:08:22 +08:00
Oliver Li
3f05ef2ae3
Merge branch 'Wei-Shaw:main' into vertex 2026-04-26 08:39:41 -04:00
shaw
9b6dcc57bd feat(affiliate): 完善邀请返利系统
- 修复返利不到账的根因:tryClaimAffiliateRebateAudit 中 PostgreSQL 参数类型推断冲突
  - 补全 OAuth 注册路径(LinuxDo/OIDC/WeChat/Pending Flow)的邀请码绑定
  - 前端 OAuth 注册页面传递 aff_code 参数
  - 新增返利冻结期机制:可配置冻结时间,到期后自动解冻(懒解冻)
  - 新增返利有效期:绑定后 N 天内有效,过期不再产生返利
  - 新增单人返利上限:超出上限部分精确截断
  - 增强返利流程 slog 结构化日志,便于排查问题
  - 已邀请用户列表增加返利明细列
2026-04-26 12:42:35 +08:00
Oliver
6d11f9ed77 Add Vertex service account support 2026-04-25 20:39:58 -04:00
Oliver
489a4d934e Show today stats for Vertex usage window 2026-04-25 19:46:32 -04:00