- 16 Mar, 2026 1 commit
-
-
QTom authored
根因:多个用户共享同一 OAuth 账号时,conversation_id/session_id 头 未做用户隔离,导致上游 chatgpt.com 将不同用户的请求关联到同一会话。 HTTP SSE 修复: - 新增 isolateOpenAISessionID(apiKeyID, raw),将 API Key ID 混入 session 标识符(xxhash),确保不同 Key 的用户产生不同上游会话 - buildUpstreamRequest: OAuth 分支先 Del 客户端透传的 session 头, 再用隔离值覆盖 - buildUpstreamRequestOpenAIPassthrough: 透传路径同样隔离 - ForwardAsAnthropic: Anthropic Messages 兼容路径同步修复 - buildOpenAIWSHeaders: WS 路径的 OAuth session 头同步隔离
-
- 15 Mar, 2026 26 commits
-
-
erio authored
- Fix gofmt alignment in admin_service.go and trailing newline in antigravity_credits_overages.go - Suppress errcheck for fmt.Sscanf in client.go GetMinimumAmount
-
erio authored
Remove SimulateClaudeMaxEnabled field and related logic from admin_service.go, and remove applyClaudeMaxCacheBillingPolicyToUsage, applyClaudeMaxNonStreamingRewrite, setupClaudeMaxStreamingHook calls from antigravity_gateway_service.go. These symbols are not yet available in upstream/main.
-
erio authored
Replace process-memory sync.Map + per-model runtime state with a single "AICredits" key in model_rate_limits, making credits exhaustion fully isomorphic with model-level rate limiting. Scheduler: rate-limited accounts with overages enabled + credits available are now scheduled instead of excluded. Forwarding: when model is rate-limited + credits available, inject credits proactively without waiting for a 429 round trip. Storage: credits exhaustion stored as model_rate_limits["AICredits"] with 5h duration, reusing SetModelRateLimit/isRateLimitActiveForKey. Frontend: show credits_active (yellow
⚡ ) when model rate-limited but credits available, credits_exhausted (red) when AICredits key active. Tests: add unit tests for shouldMarkCreditsExhausted, injectEnabledCreditTypes, clearCreditsExhausted, and update existing overages tests. -
SilentFlower authored
-
SilentFlower authored
-
SilentFlower authored
feat: implement resolveCreditsOveragesModelKey function to stabilize model key resolution for credit overages
-
erio authored
-
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
-
Peter authored
-
Ethan0x0000 authored
- Apply InboundEndpointMiddleware to all gateway route groups - Replace normalizedOpenAIInboundEndpoint/normalizedOpenAIUpstreamEndpoint and normalizedGatewayInboundEndpoint/normalizedGatewayUpstreamEndpoint with GetInboundEndpoint/GetUpstreamEndpoint - Remove 4 old constants and 4 old normalization functions (-70 lines) - Migrate existing endpoint normalization test to new API Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode ) Co-authored-by:
Sisyphus <clio-agent@sisyphuslabs.ai>
-
Ethan0x0000 authored
Introduce endpoint.go with shared constants, NormalizeInboundEndpoint, DeriveUpstreamEndpoint, InboundEndpointMiddleware, and context helpers. This replaces the two separate normalization implementations (OpenAI and Gateway) with a single source of truth. Includes comprehensive test coverage. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode ) Co-authored-by:
Sisyphus <clio-agent@sisyphuslabs.ai>
-
Ethan0x0000 authored
Extend RecordUsageInput and RecordUsageLongContextInput structs with InboundEndpoint and UpstreamEndpoint so that Claude, Gemini, and Sora handlers can record endpoint info alongside OpenAI handlers. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode ) Co-authored-by:
Sisyphus <clio-agent@sisyphuslabs.ai>
-
Ethan0x0000 authored
Replace t.Add(24*time.Hour - time.Nanosecond) with t.AddDate(0, 0, 1) and use SQL < instead of <= for end-of-day boundaries. This avoids edge-case misses around DST transitions. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode ) Co-authored-by:
Sisyphus <clio-agent@sisyphuslabs.ai>
-
erio authored
-
erio authored
The upstream Gemini API returns "Insufficient account balance" which doesn't contain the substring "insufficient balance". Add explicit match for the full phrase to ensure the filter works correctly.
-
IanShaw027 authored
-
shaw authored
-
IanShaw027 authored
-
IanShaw027 authored
修复在填写限额时,如果不填写完整的三个限额额度(日限额、周限额、月限额)就会报错的问题。 变更内容: - 后端:添加 optionalLimitField 类型处理空值和空字符串,兼容部分限额字段为空的情况 - 前端:添加 normalizeOptionalLimit 函数规范化限额输入,将空值、空字符串和无效数字统一处理为 null
-
erio authored
- Add 5th error filter switch IgnoreInsufficientBalanceErrors to suppress upstream insufficient balance / insufficient_quota errors from ops log - Extract hardcoded error strings into package-level constants for shouldSkipOpsErrorLog, normalizeOpsErrorType, classifyOpsPhase, and classifyOpsIsBusinessLimited - Define ErrNoAvailableAccounts sentinel error and replace all errors.New("no available accounts") call sites - Update tests to use require.ErrorIs with the sentinel error -
Elysia authored
-
erio authored
Previously, v-model.number produced "" when input was cleared, causing JSON decode errors on the backend. Also, normalizeLimit treated 0 as "unlimited" which prevented setting a zero quota. Now "" is converted to null (unlimited) in frontend, and 0 is preserved as a valid limit. Closes Wei-Shaw/sub2api#1021
-
erio authored
When Redis cache is populated from DB with a NULL window_1d_start, the Lua increment script only updates usage counters without setting window timestamps. IsWindowExpired(nil) previously returned false, so the accumulated usage was never reset across time windows, effectively turning usage_1d into a lifetime counter. Once this exceeded rate_limit_1d the key was incorrectly blocked with "日限额已用完". Fixes Wei-Shaw/sub2api#1022
-
YanzheL authored
Claude's output_config.effort parameter (low/medium/high/max) was not being extracted from requests or logged in the reasoning_effort column of usage logs. Only the OpenAI path populated this field. Changes: - Extract output_config.effort in ParseGatewayRequest - Add ReasoningEffort field to ForwardResult - Populate reasoning_effort in both RecordUsage and RecordUsageWithLongContext - Guard against overwriting service-set effort values in handler - Update stale comments that described reasoning_effort as OpenAI-only - Add unit tests for extraction, normalization, and persistence
-
Ethan0x0000 authored
-
Ethan0x0000 authored
将入站、上游与路径三类端点分布统一到使用记录页的一致化卡片交互中,并补齐端点元数据与统计链路,提升排障与流量分析效率。
-
- 14 Mar, 2026 13 commits
-
-
Elysia authored
当上游在 SSE 流中途返回 event:error 时,handleStreamingResponse 已将 部分 SSE 事件写入客户端,但原先的 failover 逻辑仍会切换到下一个账号 并写入完整流,导致客户端收到两个 message_start 进而产生 400 错误。 修复方案:在每次 Forward 调用前记录 c.Writer.Size(),若 Forward 返回 UpstreamFailoverError 后 writer 字节数增加,说明 SSE 内容已不可撤销地 发送给客户端,此时直接调用 handleFailoverExhausted 发送 SSE error 事件 终止流,而非继续 failover。 Ping-only 场景不受影响:slot 等待期的 ping 字节在 Forward 前后相等, 正常 failover 流程照常进行。 Co-Authored-By:Claude Sonnet 4.6 <noreply@anthropic.com>
-
SsageParuders authored
applyUsageBillingEffects() 中配额更新条件仅检查了 AccountTypeAPIKey, 遗漏了 AccountTypeBedrock,导致 Bedrock 账户的配额计数器永远不递增。 扩展条件以同时支持 APIKey 和 Bedrock 类型。 同时在前端账户筛选下拉框中添加 AWS Bedrock 选项。
-
shaw authored
-
erio authored
Increase MAX(bucket_start) query timeout from 3s to 5s to reduce timeout-induced fallbacks. Shrink backfill window from 30 days to 1 hour so that fallback recomputation stays lightweight instead of scanning the entire retention range.
-
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>
-
wucm667 authored
-
SsageParuders authored
-
SsageParuders authored
Consolidate two separate channel types (bedrock + bedrock-apikey) into a single "AWS Bedrock" channel. Authentication mode is now distinguished by credentials.auth_mode ("sigv4" | "apikey") instead of separate types. Backend: - Remove AccountTypeBedrockAPIKey constant - IsBedrock() simplified; IsBedrockAPIKey() checks auth_mode - Add IsAPIKeyOrBedrock() helper to eliminate repeated type checks - Extend pool mode, quota scheduling, and billing to bedrock - Add RetryableOnSameAccount to handleBedrockUpstreamErrors - Add "bedrock" scope to Beta Policy for independent control Frontend: - Merge two buttons into one "AWS Bedrock" with auth mode radio - Badge displays "Anthropic | AWS" - Pool mode and quota limit UI available for bedrock - Quota display in account list (usage bars, capacity badges, reset) - Remove all bedrock-apikey type references -
ius authored
-
Ethan0x0000 authored
-
Wang Lvyuan authored
-
Wang Lvyuan authored
-
Wang Lvyuan authored
-