- 29 Apr, 2026 1 commit
-
-
shaw authored
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.
-
- 26 Apr, 2026 1 commit
-
-
shaw authored
- 修复返利不到账的根因:tryClaimAffiliateRebateAudit 中 PostgreSQL 参数类型推断冲突 - 补全 OAuth 注册路径(LinuxDo/OIDC/WeChat/Pending Flow)的邀请码绑定 - 前端 OAuth 注册页面传递 aff_code 参数 - 新增返利冻结期机制:可配置冻结时间,到期后自动解冻(懒解冻) - 新增返利有效期:绑定后 N 天内有效,过期不再产生返利 - 新增单人返利上限:超出上限部分精确截断 - 增强返利流程 slog 结构化日志,便于排查问题 - 已邀请用户列表增加返利明细列
-
- 25 Apr, 2026 3 commits
-
-
shaw authored
- 在系统设置「功能开关」中新增邀请返利总开关,默认关闭; 关闭态:菜单隐藏、注册忽略 aff、新充值不返利,但已有 quota 仍可转余额 - 支持管理员为指定用户设置专属邀请码(覆盖随机码,全局唯一) - 支持管理员为指定用户设置专属返利比例(覆盖全局比例,可单条/批量调整) - 在系统设置邀请返利卡片内嵌入专属用户管理表格(搜索/编辑/批量/删除), 删除采用项目通用 ConfirmDialog,会同时清除专属比例并把邀请码重置为系统随机码 - /affiliate 用户页新增「我的返利比例」卡片与动态使用说明,让用户直观看到 分享后能拿到多少(同源 resolveRebateRatePercent 计算,与实际充值一致) - 新增数据库迁移 132 添加 aff_rebate_rate_percent 与 aff_code_custom 列 - 新增 admin 路由组 /api/v1/admin/affiliates/users/* 共 5 个端点 - AffiliateService 改为只依赖 *SettingService,去除冗余的 SettingRepository - 邀请码格式校验放宽到 [A-Z0-9_-]{4,32},兼容旧 12 位系统码与新自定义码 - 补充单元测试与集成测试覆盖新方法、冲突路径与边界值 -
shaw authored
将 vansour/sub2api#1555 的 OpenAI compact 能力建模手工移植到当前 main:账号 级 compact 状态/auto-force_on-force_off 模式、compact-only 模型映射、调度器 tier 分层(已支持 > 未知 > 已知不支持)、管理后台 compact 主动探测,以及对应 i18n/状态徽章。普通 /responses 流量行为不变,无数据库迁移。
-
shaw authored
- Drop SetAffiliateService setters and ProvideAuthService / ProvidePaymentService / ProvideUserHandler wrappers in favor of direct Wire constructor injection. AffiliateService has no back-edge to Auth/Payment/User, so the indirection was never required. - Change RegisterWithVerification's variadic affiliateCode to a fixed parameter; adjust all call sites. - Validate aff_code length and charset in BindInviterByCode before any DB lookup, eliminating timing-side-channel and useless DB roundtrips on malformed input. - Make affiliate cache invalidation synchronous; surface Redis errors via the project logger instead of swallowing them in a detached goroutine. - Add an integration test guarding cross-layer tx propagation in AccrueQuota and a unit test pinning the aff_code format rules.
-
- 24 Apr, 2026 1 commit
-
-
VpSanta33 authored
-
- 23 Apr, 2026 6 commits
-
-
erio authored
Revert payment/wechat, sora/claude-max cleanup, fork-only migrations, and cosmetic changes that were brought in by the release sync commit. Keep only channel-monitor related improvements: - PublicSettingsInjectionPayload named struct with drift test - ChannelMonitorRunner graceful shutdown in wire - image_output_price in SupportedModelChip - Simplified buildSelfNavItems in AppSidebar - Gateway WARN logs for 503 branches
-
erio authored
- Extract PublicSettingsInjectionPayload named struct with drift test - Add channel_monitor_default_interval_seconds to SSR injection - Add image_output_price to SupportedModelChip - Simplify AppSidebar buildSelfNavItems (admins see available channels) - Add gateway WARN logs for 503 no-available-accounts branches - Wire ChannelMonitorRunner into provideCleanup for graceful shutdown - Add migrations 130/131 (CC template userid fix + mimicry field cleanup) - Clean up fork-only features (sora, claude max simulation, client affinity) - Remove ~320 obsolete i18n keys - Add codexUsage utility, WechatServiceButton, BulkEditAccountModal - Tidy go.sum
-
james-6-23 authored
P0: - rpm_override 嵌入 Auth Cache Snapshot,消除每请求 DB 查询 (snapshot v6→v7) - 429 RPM 响应返回 Retry-After 头(当前分钟剩余秒数) P1: - ClearAll 按钮直连 DELETE API,带 loading 防重复 - 新增 GET /admin/users/:id/rpm-status 管理员 RPM 用量查询端点 优化: - checkRPM 从级联互斥改为并行取最严,user.rpm_limit 作为全局硬上限始终生效 - Override/Group 变更后自动失效 auth cache - fail-open 语义不变,Redis 故障不阻塞业务
-
wucm667 authored
-
wx-11 authored
-
zhoukailian authored
-
- 22 Apr, 2026 10 commits
-
-
shaw authored
-
IanShaw027 authored
-
IanShaw027 authored
-
IanShaw027 authored
-
IanShaw027 authored
-
IanShaw027 authored
-
IanShaw027 authored
-
IanShaw027 authored
-
IanShaw027 authored
-
IanShaw027 authored
-
- 21 Apr, 2026 8 commits
-
-
IanShaw027 authored
-
IanShaw027 authored
-
IanShaw027 authored
-
IanShaw027 authored
-
IanShaw027 authored
-
IanShaw027 authored
-
IanShaw027 authored
-
IanShaw027 authored
-
- 20 Apr, 2026 3 commits
-
-
IanShaw027 authored
-
IanShaw027 authored
-
IanShaw027 authored
-
- 21 Apr, 2026 3 commits
-
-
erio authored
- History retention 1d → 30d(60s × 30d ≈ 43200 行/model,PG 无压力); ComputeAvailability* 不再 UNION rollup 表,直接扫 histories 精度更高。 - Timeline bar 四级高度+颜色双重编码:operational 高+绿 / degraded 中+黄 / failed+error 短+红 / 未测试 很短+灰。 - migration 113 seed「Claude Code 伪装」模板(ON CONFLICT DO NOTHING)。 user_id 用 legacy 格式(user_<64hex>_account_<uuid>_session_<uuid>), 避免新版 JSON 字符串内嵌 JSON 在编辑器里一长串 \" 难读。 - MonitorAdvancedRequestConfig 加「格式化」按钮 + white-space:pre 让 body textarea 对长字符串不压扁。
-
erio authored
Apply flow: - POST /admin/channel-monitor-templates/:id/apply now requires monitor_ids (non-empty array). Service applies the template only to the selected subset, gated by AND template_id = :id (so users can't sneak in unrelated monitor IDs). - New GET /admin/channel-monitor-templates/:id/monitors returns the associated monitor briefs (id/name/provider/enabled) for the picker. - ApplyToMonitors signature gains monitorIDs []int64; empty list returns ErrChannelMonitorTemplateApplyEmpty. Frontend: - New MonitorTemplateApplyPickerDialog.vue: list of associated monitors with checkboxes (default all checked), 全选 / 全不选 shortcuts, live selected/total count. Submit calls apply(id, ids). - MonitorTemplateManagerDialog replaces the old ConfirmDialog flow with the picker; onApplied refetches the list to refresh associated counts. i18n: applyPicker* + common.selectAll keys. chore: bump version to 0.1.114.33 The CC 2.1.114 (sdk-cli) UA / APIKeyBetaHeader / JSON metadata.user_id baseline (already verified working via the in-process apply on prod template id=1) is documented in internal/pkg/claude/constants.go and is what the seed template in the manager UI should follow.
-
erio authored
Problem: Upstream channels can reject monitor probes based on client fingerprint (e.g. "only Claude Code clients allowed"). The monitor had no way to customize the outgoing request to bypass such restrictions. Solution: Introduce reusable request templates that carry extra_headers plus an optional body override; monitors reference a template and receive a snapshot copy on apply. Template edits do NOT auto-propagate — users must click "apply to associated monitors" to refresh snapshots, so a bad template edit cannot instantly break all production monitors. Data model (migration 112): - channel_monitor_request_templates: id, name, provider, description, extra_headers jsonb, body_override_mode ('off'|'merge'|'replace'), body_override jsonb. Unique (provider, name). - channel_monitors: +template_id (FK, ON DELETE SET NULL), +extra_headers, +body_override_mode, +body_override (the three runtime snapshot fields). Checker (channel_monitor_checker.go): - callProvider + runCheckForModel accept a CheckOptions carrying the snapshot fields. mergeHeaders applies user headers on top of adapter defaults (forbidden list: Host / Content-Length / Transfer-Encoding / Connection / Content-Encoding). - buildRequestBody: off -> adapter default body merge -> shallow-merge over default; per-provider deny list (model/messages/contents) protects the challenge contract replace -> user body verbatim - Replace mode skips challenge validation; instead HTTP 2xx + non-empty extracted response text = operational, empty = failed. - 4 new unit tests cover all three modes + replace/empty-response case. Admin API: - /admin/channel-monitor-templates CRUD + /:id/apply (overwrite snapshot on all template_id=id monitors, returns affected count). - channel_monitor request/response DTOs gain the 4 new fields. Frontend: - channelMonitorTemplate.ts API client. - MonitorAdvancedRequestConfig.vue shared component for headers textarea + body mode radio + body JSON editor; used by both template and monitor forms. - MonitorTemplateManagerDialog.vue: provider tabs, list/create/edit/ delete/apply, live "associated monitors" count per row. - MonitorFiltersBar: new 模板管理 button next to 新增监控. - MonitorFormDialog: collapsible 高级 section with template dropdown (filtered by form.provider, clears on provider change) + embedded AdvancedRequestConfig. Picking a template copies its fields into the form (snapshot semantics mirrored on the client). - i18n zh/en entries for all new copy. chore: bump version to 0.1.114.32
-
- 23 Apr, 2026 1 commit
-
-
erio authored
### 后端修复:日志表不该用软删除 channel_monitor_histories / channel_monitor_daily_rollups 都是日志/聚合表, 没有恢复需求。110 里加的 SoftDeleteMixin 会让 DELETE 自动变成 UPDATE deleted_at, 导致行和索引只增不减,徒增磁盘占用和查询成本。 改回分批物理删(参考 OpsCleanupService.deleteOldRowsByID 模板): - ent schema 移除 SoftDeleteMixin,重新 go generate - repo 新增 deleteChannelMonitorBatched 辅助 + 两条 prune SQL 常量 (WITH batch AS SELECT id LIMIT 5000 → DELETE IN batch) - DeleteHistoryBefore / DeleteRollupsBefore 改调分批 raw SQL - 移除 ComputeAvailability / ComputeAvailabilityForMonitors / UpsertDailyRollupsFor / ListLatestPerModel / ListLatestForMonitorIDs / ListRecentHistoryForMonitors 等 raw SQL 中的 deleted_at IS NULL 过滤 - UpsertDailyRollupsFor 的 ON CONFLICT 去掉 deleted_at = NULL 重置 - migration 111 DROP COLUMN deleted_at + 对应索引(110 已部署但 maintenance 首跑在次日 02:00,此时尚无业务数据在依赖软删除) ### 前端重构:feature flag 声明式 + 复用 AppSidebar.vue 里 7 处 `...(flag ? [item] : [])` 样板代码删光,改为 NavItem 加 featureFlag?: () => boolean | undefined 字段,加一个 applyFeatureFlags 递归 过滤(含 children)。语义统一为 `!== false`(宽容策略,undefined 时默认显示, 避免 public settings 未加载完成时菜单闪烁消失 — 对应用户反馈"刷新后菜单消失 要去保存设置才回来")。 - 集中声明 4 个 flag getter:flagChannelMonitor / flagPayment / flagOpsMonitoring / flagAdminPayment - 提取 buildSelfNavItems 复用用户端主菜单和管理员"我的账户"子菜单 - 未来新增开关:在统一位置加一个 flag getter + 给对应 NavItem 加字段 (不用再动渲染逻辑) bump 0.1.114.29
-
- 21 Apr, 2026 1 commit
-
-
erio authored
明细只保留 1 天,超过 1 天聚合到新表 channel_monitor_daily_rollups(按 monitor_id/model/bucket_date 维度),聚合保留 30 天。两张表都用 SoftDeleteMixin 软删除(DELETE 自动改为 UPDATE deleted_at = NOW())。 聚合 + 清理任务由 OpsCleanupService 的 cron 统一调度,与运维监控的清理共享 schedule(默认 0 2 * * *)和 leader lock。ChannelMonitorRunner 的 cleanupLoop 被移除,只保留 dueCheckLoop。 读取路径 ComputeAvailability* 改为 UNION 明细(今天 deleted_at IS NULL)+ 聚合(过去 windowDays 天 deleted_at IS NULL),SUM(ok)/SUM(total) 自然加权 计算可用率,AVG latency 用 SUM(sum_latency_ms)/SUM(count_latency)。 watermark 表 channel_monitor_aggregation_watermark 单行(id=1),记录 last_aggregated_date,重启后从该日期 +1 继续聚合,首次为 nil 则从 today - 30d 开始回填,单次最多 35 天上限避免长事务。 raw SQL 的 ListLatestPerModel / ListLatestForMonitorIDs / ListRecentHistoryForMonitors 都补上 deleted_at IS NULL 过滤(SoftDeleteMixin interceptor 只对 ent query 生效)。 bump version to 0.1.114.28 GroupBadge 在 MonitorKeyPickerDialog 中复用平台主题色 + 倍率/专属倍率 (顺手优化)。
-
- 20 Apr, 2026 2 commits
-
-
IanShaw027 authored
-
IanShaw027 authored
-