- 14 Apr, 2026 11 commits
-
-
erio authored
QuotaLimitCard now requires quotaNotifyGlobalEnabled prop to control visibility of QuotaNotifyToggle components. When the global account quota notification is disabled in admin settings, per-account threshold toggles are hidden in both Edit and Create account modals.
-
erio authored
- Move sanitizeEmailHeader to SendEmailWithConfig entry point, covering all email senders (verify code, password reset, ops alerts, notifications) - Add panic recovery to UpdateBalance goroutine - Fix stale comment in getAccountQuotaNotifyEmails (email="" no longer used) - Log error instead of silently discarding verifyNotifyCode cache update failure
-
erio authored
P0: fix wildcard matching test assertion (config order, not longest prefix) P0: add TotalRecharged to auth cache snapshot (v5) for percentage threshold P1: move pricing rules into per-platform sections in ChannelsView P1: populate account name cache when editing existing channel rules P1: sanitize email subject headers to prevent SMTP injection P1: make Redis INCR+EXPIRE idempotent for rate limiting P1: deep copy FeaturesConfig in Channel.Clone() P2: clean up stale email="" placeholder comments P2: replace log.Printf with slog in email_service.go
-
erio authored
WebSearch tri-state switch: - Account-level web_search_emulation changed from bool to tri-state string: "default" (follow channel) / "enabled" / "disabled" - shouldEmulateWebSearch checks channel config when account is "default" - SQL migration converts old bool values - Frontend select replaces toggle in Edit/CreateAccountModal Account stats pricing: - resolveAccountStatsCost uses upstream model (post-mapping) for matching - Priority: custom rules → model pricing file (when toggle on) → default - Custom rules always configurable, independent of toggle - Account ID field changed to searchable selector filtered by platform - Description updated to reflect new behavior Quota notification cache fix: - CheckAccountQuotaAfterIncrement fetches real-time account from DB - Reconstructs pre-increment usage for accurate threshold crossing detection - New AccountQuotaReader interface (minimal: GetByID only) Usage tooltip: - Per-request/image billing shows per-request price instead of $0 token price - Token billing continues to show input/output price per million tokens
-
erio authored
- API Key show/copy buttons moved inside input field (inline icons) - Proxy selector and test button on same row to save vertical space - Test opens a dialog modal instead of inline display - Hide all websearch config in channels/accounts when global toggle is off
-
erio authored
- Fix GetByKeyForAuth not selecting balance notify fields (notifications never triggered in gateway path) - Fix provider-level ProxyURL never resolved: inject ProxyRepository into SettingService, resolve proxy URLs when building Manager - Fix admin manual balance adjustment not updating total_recharged - Add threshold_type input validation (reject invalid values) - Fix user threshold_type inheritance: custom threshold defaults to "fixed" instead of inheriting global type (prevents $5 being treated as 5%) - Add try-catch for clipboard.writeText (fails on non-HTTPS) - Add SetTotalRecharged to user Update for admin balance operations
-
erio authored
- User balance low notification: email alert when balance drops below configurable threshold (user email + verified extra emails) - Account quota notification: broadcast email to admin-configured recipients when daily/weekly/total quota usage exceeds alert threshold - Admin settings: global enable/disable, default threshold, quota notification email list (Email Settings tab) - User profile: enable/disable, custom threshold, add/remove extra notification emails with verification code flow - Account quota: per-dimension alert toggle and threshold in quota control card - Trigger logic: first-crossing only (old >= threshold && new < threshold for balance; old < threshold && new >= threshold for quota), naturally prevents duplicate notifications without Redis dedup
-
erio authored
Backend: - Define OrderTypeBalance/Subscription, EntityStatusActive, DeductionType*, NotificationStatus* constants in payment/types.go - Replace all magic strings in payment_order, payment_fulfillment, payment_refund - Add local constants in easypay.go (tradeStatusSuccess, signTypeMD5) - Add 27 unit tests for load balancer (filterByLimits, pickLeastAmount, getInstanceChannelLimits, startOfDay) Frontend: - Remove all `any` types in SettingsView.vue (18 catch blocks + 1 payload) - Fix bare catch blocks in PaymentResultView, PaymentView - Add `unknown` type annotation to all catch blocks chore: bump version to 0.1.108.140
-
erio authored
Backend: - Extract YuanToFen/FenToYuan to payment/amount.go using shopspring/decimal - Require alipay publicKey in config validation - Fix wxpay webhook response to return JSON per V3 spec - Remove wxpay certSerial fallback to publicKeyId - Define magic strings as named constants in wxpay/alipay providers - Add slog warning for wxpay H5→Native payment downgrade - Make EncryptionKey validation return error on invalid (non-empty) key - Make decryptConfig propagate errors instead of returning nil - Add idempotency check in doBalance to prevent stuck FAILED retries Frontend: - Fix dashboard currency symbol from $ to ¥ - Fix AdminPaymentPlansView any type to proper SubscriptionPlan type - Make quick amount buttons follow selected payment method limits - Center help image with larger height and text below
-
erio authored
The paginated List query was selecting 9 columns but scanning 10 fields, missing c.features. GetByID and ListAll already included it correctly.
-
erio authored
-
- 13 Apr, 2026 1 commit
-
-
github-actions[bot] authored
-
- 12 Apr, 2026 1 commit
-
-
github-actions[bot] authored
-
- 11 Apr, 2026 2 commits
-
-
erio authored
Upstream removed sora feature (090_drop_sora.sql) but left i18n keys and wire.go references. Clean up: - Remove entire sora i18n block from en.ts and zh.ts (~190 lines) - Remove sora nav key and unused 'data' settings tab key - Remove sora_client_enabled from settings (fork-specific) - Remove SoraMediaCleanupService from wire.go
-
erio authored
Add a full payment and subscription system supporting EasyPay (Alipay/WeChat), Stripe, and direct Alipay/WeChat Pay providers with multi-instance load balancing.
-
- 08 Apr, 2026 2 commits
-
-
ius authored
-
github-actions[bot] authored
-
- 07 Apr, 2026 1 commit
-
-
github-actions[bot] authored
-
- 05 Apr, 2026 4 commits
-
-
github-actions[bot] authored
-
erio authored
-
erio authored
-
github-actions[bot] authored
-
- 04 Apr, 2026 6 commits
-
-
erio authored
Restore account_usage_service.go, antigravity_gateway_service.go, antigravity_credits_overages.go and its test to upstream/main state. These credits balance precheck changes were accidentally included during cherry-pick of channel management commits.
-
erio authored
- Parse candidatesTokensDetails from Gemini API to separate image/text output tokens - Add image_output_tokens and image_output_cost to usage_log (migration 089) - Support per-image-token pricing via output_cost_per_image_token from model pricing data - Channel pricing ImageOutputPrice override works in token billing mode - Auto-fill image_output_price in channel pricing form from model defaults - Add "channel_mapped" billing model source as new default (migration 088) - Bills by model name after channel mapping, before account mapping - Fix channel cache error TTL sign error (115s → 5s) - Fix Update channel only invalidating new groups, not removed groups - Fix frontend model_mapping clearing sending undefined instead of {} - Credits balance precheck via shared AccountUsageService cache before injection - Skip credits injection for accounts with insufficient balance - Don't mark credits exhausted for "exhausted your capacity on this model" 429s -
erio authored
- 定价查找支持通配符(suffix *),最长前缀优先匹配 - 模型限制(restrict_models)同样支持通配符匹配 - OpenAI 网关接入渠道映射/BillingModelSource/模型限制 - 按次/图片计费模式创建时强制要求价格或层级(前后端) - 用户使用记录列表增加计费模式 badge 列
-
erio authored
- GatewayService/OpenAIGatewayService 注入 ModelPricingResolver - RecordUsage 从旧路径迁移到 CalculateCostUnified(支持 per_request/image 模式) - 无渠道时自动回退旧路径,保持原有行为 - 长上下文双倍计费仅在无渠道定价时生效 - CostBreakdown 新增 BillingMode 字段,使用日志记录实际计费模式 - 模型限制错误改为与"无可用账号"相同的 503 响应
-
erio authored
- 新增 GET /admin/channels/model-pricing?model=xxx API - 从 BillingService 查询 LiteLLM/Fallback 默认定价 - 前端添加模型时自动查询并填充价格($/MTok) - 仅在所有价格字段为空时才自动填充,不覆盖手动配置
-
erio authored
Cherry-picked from release/custom-0.1.106: a9117600
-
- 30 Mar, 2026 1 commit
-
-
github-actions[bot] authored
-
- 27 Mar, 2026 3 commits
-
-
erio authored
When an antigravity account returns 500 "Internal error encountered." on all 3 retry attempts, increment a Redis counter and apply escalating penalties: - 1st round: temp unschedulable 10 minutes - 2nd round: temp unschedulable 10 hours - 3rd round: permanently mark as error Counter resets on any successful response (< 400).
-
github-actions[bot] authored
-
shaw authored
新增功能: - 新增 TLS 指纹 Profile CRUD 管理(Ent schema + 迁移 + Admin API + 前端管理界面) - 支持账号绑定数据库中的自定义 TLS Profile,或随机选择(profile_id=-1) - HTTPUpstream.DoWithTLS 接口从 bool 改为 *tlsfingerprint.Profile,支持按账号指定 Profile - AccountUsageService 注入 TLSFingerprintProfileService,统一 usage 场景与网关的 Profile 解析逻辑 代码优化: - 删除已被 TLSFingerprintProfileService 完全取代的 registry.go 死代码(418 行) - 提取 3 个 dialer 的重复 TLS 握手逻辑为 performTLSHandshake() 共用函数 - 修复 GetTLSFingerprintProfileID 缺少 json.Number 处理的 bug - gateway_service.Forward 中 ResolveTLSProfile 从重试循环内重复调用改为预解析局部变量 - 删除冗余的 buildClientHelloSpec() 单行 wrapper 和 int64(e.ID) 无效转换 - tls_fingerprint_profile_cache.go 日志从 log.Printf 改为 slog 结构化日志 - dialer_capture_test.go 添加 //go:build integration 标签,防止 CI 失败 - 去重 TestProfileExpectation 类型至共享 test_types_test.go - 修复 9 个测试文件缺少 tlsfingerprint import 的编译错误 - 修复 error_policy_integration_test.go 中 handleError 回调签名被错误替换的问题
-
- 24 Mar, 2026 1 commit
-
-
QTom authored
1. accounts/check 补全 plan_type:当 id_token 缺少 plan_type(如 Mobile RT), 自动调用 accounts/check 端点获取订阅类型 2. orgID 精确匹配账号:从 JWT 提取 poid 匹配正确账号,避免 Go map 遍历顺序随机导致 plan_type 不稳定 3. RT 刷新时设置隐私:调用 disableOpenAITraining 关闭训练数据共享, 结果存入 extra.privacy_mode,后续跳过重复设置 Co-Authored-By:Claude Opus 4.6 (1M context) <noreply@anthropic.com>
-
- 20 Mar, 2026 1 commit
-
-
github-actions[bot] authored
-
- 19 Mar, 2026 1 commit
-
-
erio authored
## Problem When a proxy is unreachable, token refresh retries up to 4 times with 30s timeout each, causing requests to hang for ~2 minutes before failing with a generic 502 error. The failed account is not marked, so subsequent requests keep hitting it. ## Changes ### Proxy connection fast-fail - Set TCP dial timeout to 5s and TLS handshake timeout to 5s on antigravity client, so proxy connectivity issues fail within 5s instead of 30s - Reduce overall HTTP client timeout from 30s to 10s - Export `IsConnectionError` for service-layer use - Detect proxy connection errors in `RefreshToken` and return immediately with "proxy unavailable" error (no retries) ### Token refresh temp-unschedulable - Add 8s context timeout for token refresh on request path - Mark account as temp-unschedulable for 10min when refresh fails (both background `TokenRefreshService` and request-path `GetAccessToken`) - Sync temp-unschedulable state to Redis cache for immediate scheduler effect - Inject `TempUnschedCache` into `AntigravityTokenProvider` ### Account failover - Return `UpstreamFailoverError` on `GetAccessToken` failure in `Forward`/`ForwardGemini` to trigger handler-level account switch instead of returning 502 directly ### Proxy probe alignment - Apply same 5s dial/TLS timeout to shared `httpclient` pool - Reduce proxy probe timeout from 30s to 10s
-
- 18 Mar, 2026 2 commits
-
-
QTom authored
复用 GroupCapacityService,在 admin 分组列表中添加容量列, 显示每个分组的实时并发/会话/RPM 使用量和上限。 Co-Authored-By:Claude Opus 4.6 (1M context) <noreply@anthropic.com>
-
QTom authored
分组管理列表增强: 1. 今日/累计用量列: - 新增独立端点 GET /admin/groups/usage-summary - 一次查询返回所有分组的今日费用和累计费用(actual_cost) - 前端异步加载后合并显示在分组列表中 2. 账号数区分可用/限流/总量: - 将账号数列从单一总量改为 badge 内多行展示 - 可用: active + schedulable 的账号数(绿色) - 限流: rate_limit/overload/temp_unschedulable 的账号数(橙色,无限流时隐藏) - 总量: 全部关联账号数 Co-Authored-By:Claude Opus 4.6 (1M context) <noreply@anthropic.com>
-
- 15 Mar, 2026 1 commit
-
-
erio authored
Introduce OAuthRefreshAPI as the single entry point for all OAuth token refresh operations, eliminating the race condition where background refresh and inline refresh could simultaneously use the same refresh_token (fixes #1035). Key changes: - Add OAuthRefreshExecutor interface extending TokenRefresher with CacheKey - Add OAuthRefreshAPI.RefreshIfNeeded with lock → DB re-read → double-check flow - Add ProviderRefreshPolicy / BackgroundRefreshPolicy strategy types - Simplify all 4 TokenProviders to delegate to OAuthRefreshAPI - Rewrite TokenRefreshService.refreshWithRetry to use unified API path - Add MergeCredentials and BuildClaudeAccountCredentials helpers - Add 40 unit tests covering all new and modified code paths
-
- 14 Mar, 2026 1 commit
-
-
Rose Ding authored
1. S3 凭证加密存储:使用 SecretEncryptor (AES-256-GCM) 加密 SecretAccessKey, 防止备份文件中泄露 S3 凭证,兼容旧的未加密数据 2. 修复 saveRecord 竞态条件:添加 recordsMu 互斥锁保护 records 的 load/save 3. 恢复操作增加服务端验证:handler 层要求重新输入管理员密码,通过 bcrypt 校验,前端弹出密码输入框 4. pg_dump/psql/S3 操作抽象为接口:定义 DBDumper 和 BackupObjectStore 接口, 实现放入 repository 层,遵循项目依赖注入架构规范 5. 改为流式处理避免大数据库 OOM:备份时 pg_dump stdout -> gzip -> io.Pipe -> S3 upload;恢复时 S3 download -> gzip reader -> psql stdin,不再全量加载 6. loadRecords 区分"无数据"和"数据损坏"场景:JSON 解析失败返回明确错误 7. 添加 18 个核心逻辑单元测试:覆盖加密、并发、流式备份/恢复、错误处理等 Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 13 Mar, 2026 1 commit
-
-
Rose Ding authored
Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-