1. 08 Apr, 2026 22 commits
    • shaw's avatar
      feat: sync billing header cc_version with User-Agent and add opt-in CCH signing · 8e69957b
      shaw authored and 陈曦's avatar 陈曦 committed
      - Sync cc_version in x-anthropic-billing-header with the fingerprint
        User-Agent version, preserving the message-derived suffix
      - Implement xxHash64-based CCH signing to replace the cch=00000
        placeholder with a computed hash
      - Add admin toggle (enable_cch_signing) under gateway forwarding settings,
        disabled by default
      8e69957b
    • shaw's avatar
      fix: 修复非CC客户端OAuth伪装被Anthropic检测为第三方应用的问题 · d845c3ce
      shaw authored and 陈曦's avatar 陈曦 committed
      commit f3aa54b7 的 rewriteSystemForNonClaudeCode 未能通过 Anthropic 第三方检测,
      根因是两个关键信号与真实 Claude Code 不一致:
      
      1. anthropic-beta 头缺少 claude-code-20250219:伪装路径主动将该 beta
         加入 drop set 并移除,但 Anthropic 依赖此 beta 识别 Claude Code 请求。
         修复:非 haiku 模型的伪装请求强制包含 claude-code beta。
      
      2. system 字段使用 string 格式而非 array+cache_control:真实 Claude Code
         始终以 [{type,text,cache_control:{type:"ephemeral"}}] 发送 system,
         string 格式成为第三方检测信号。
         修复:rewriteSystemForNonClaudeCode 改为注入 array 格式。
      
      附带调整:stripSystemCacheControl 按 system 是否被重写动态决定,
      重写时保留 CC prompt 的 cache_control,未重写时(haiku/已含CC前缀)
      保持原有剥离行为。
      d845c3ce
    • shaw's avatar
      feat: Beta策略支持按模型区分处理(模型白名单) · f1f9640c
      shaw authored and 陈曦's avatar 陈曦 committed
      f1f9640c
    • shaw's avatar
      fix: 非Claude Code客户端system prompt迁移至messages以绕过第三方应用检测 · b717956c
      shaw authored and 陈曦's avatar 陈曦 committed
      Anthropic近期引入基于system参数内容的第三方应用检测机制,原有的前置追加
      Claude Code提示词策略无法通过检测(后续内容仍为非Claude Code格式触发429)。
      
      新策略:对非Claude Code客户端的OAuth/SetupToken账号请求,将system字段
      完整替换为Claude Code标识提示词,原始system内容作为user/assistant消息对
      注入messages开头,模型仍接收完整指令。
      
      仅影响/v1/messages路径,chat_completions和responses路径保持原有逻辑不变。
      真正的Claude Code客户端请求完全不受影响(原样透传)。
      b717956c
    • 陈曦's avatar
      去除版本在页面的上的展示 · 4fee20ec
      陈曦 authored
      4fee20ec
    • YanzheL's avatar
      fix(openai): sanitize empty base64 input images · fb233463
      YanzheL authored and 陈曦's avatar 陈曦 committed
      fb233463
    • YanzheL's avatar
      fix(gemini): normalize ai studio google search tools · a8779a2c
      YanzheL authored and 陈曦's avatar 陈曦 committed
      a8779a2c
    • YanzheL's avatar
      fix(gemini): preserve google search in Claude compat tools · e31051f2
      YanzheL authored and 陈曦's avatar 陈曦 committed
      e31051f2
    • YanzheL's avatar
      fix(lint): satisfy errcheck for strings.Builder.WriteString calls · ac28ca64
      YanzheL authored and 陈曦's avatar 陈曦 committed
      ac28ca64
    • YanzheL's avatar
      test(gateway): add tests for content-based session hash fallback · 91a3cae5
      YanzheL authored and 陈曦's avatar 陈曦 committed
      - 20 unit tests for deriveOpenAIContentSessionSeed covering:
        - Empty/nil inputs, model-only, stable across turns
        - Different model/system/first-user produce different seeds
        - Tools, functions, developer role, structured content
        - Responses API: input string, input array, instructions, input_text typed items
        - JSON canonicalization (whitespace/key-order insensitive)
        - Prefix presence, empty tools ignored, messages preferred over input
      - 3 integration tests for GenerateSessionHash content fallback:
        - Content fallback produces stable hash
        - Explicit signals override content fallback
        - Empty body still returns empty hash
      91a3cae5
    • YanzheL's avatar
      fix(gateway): add content-based session hash fallback for non-Codex clients · 16c7bd31
      YanzheL authored and 陈曦's avatar 陈曦 committed
      When no explicit session signals (session_id, conversation_id, prompt_cache_key)
      are provided, derive a stable session seed from the request body content
      (model + tools + system prompt + first user message) to enable sticky routing
      and prompt caching for non-Codex clients using the Chat Completions API.
      
      This mirrors the content-based fallback already present in GatewayService.
      GenerateSessionHash, adapted for the OpenAI gateway's request formats (both
      Chat Completions messages and Responses API input).
      
      JSON fragments are canonicalized via normalizeCompatSeedJSON to ensure
      semantically identical requests produce the same seed regardless of
      whitespace or key ordering.
      
      Closes #1421
      16c7bd31
    • erio's avatar
      refactor(channel): split long functions, extract shared validation, move... · dca85c86
      erio authored and 陈曦's avatar 陈曦 committed
      refactor(channel): split long functions, extract shared validation, move billing validation to service
      
      - Split Update (98→25 lines), buildCache (54→20 lines), Create (51→25 lines)
        into focused sub-functions: applyUpdateInput, checkGroupConflicts,
        fetchChannelData, populateChannelCache, storeErrorCache, getOldGroupIDs,
        invalidateAuthCacheForGroups
      - Extract validateChannelConfig to eliminate duplicated validation calls
        between Create and Update
      - Move validatePricingBillingMode from handler to service layer for
        proper separation of concerns
      - Add error logging to IsModelRestricted (was silently swallowing errors)
      - Add 12 new tests: ToUsageFields, billing mode validation, antigravity
        wildcard mapping isolation, Create/Update mapping conflict integration
      dca85c86
    • Elysia's avatar
      fix: 非流式响应路径扩展SSE检测至所有账号类型 (#1493) · 70836c70
      Elysia authored and 陈曦's avatar 陈曦 committed
      
      
      当上游返回SSE格式响应(如sub2api链路)时,API Key账号的非流式路径
      未检测SSE,导致终态事件中空output直接透传给客户端。
      
      - 将Content-Type SSE检测从仅OAuth扩展至所有账号类型
      - 重命名handleOAuthSSEToJSON为handleSSEToJSON(无OAuth专属逻辑)
      - 为透传路径新增handlePassthroughSSEToJSON,支持SSE转JSON及空output重建
      Co-Authored-By: default avatarClaude Opus 4.6 (1M context) <noreply@anthropic.com>
      70836c70
    • shaw's avatar
      fix: 修复非CC客户端OAuth伪装被Anthropic检测为第三方应用的问题 · 49c19a55
      shaw authored and 陈曦's avatar 陈曦 committed
      commit f3aa54b7 的 rewriteSystemForNonClaudeCode 未能通过 Anthropic 第三方检测,
      根因是两个关键信号与真实 Claude Code 不一致:
      
      1. anthropic-beta 头缺少 claude-code-20250219:伪装路径主动将该 beta
         加入 drop set 并移除,但 Anthropic 依赖此 beta 识别 Claude Code 请求。
         修复:非 haiku 模型的伪装请求强制包含 claude-code beta。
      
      2. system 字段使用 string 格式而非 array+cache_control:真实 Claude Code
         始终以 [{type,text,cache_control:{type:"ephemeral"}}] 发送 system,
         string 格式成为第三方检测信号。
         修复:rewriteSystemForNonClaudeCode 改为注入 array 格式。
      
      附带调整:stripSystemCacheControl 按 system 是否被重写动态决定,
      重写时保留 CC prompt 的 cache_control,未重写时(haiku/已含CC前缀)
      保持原有剥离行为。
      49c19a55
    • haruka's avatar
      fix: resolve errcheck lint for sync.Map type assertion · 1e3ac5f0
      haruka authored and 陈曦's avatar 陈曦 committed
      
      Co-Authored-By: default avatarClaude Opus 4.6 (1M context) <noreply@anthropic.com>
      1e3ac5f0
    • haruka's avatar
      fix: resolve refresh token race condition causing false invalid_grant errors · ef8a7c0a
      haruka authored and 陈曦's avatar 陈曦 committed
      
      
      When multiple goroutines/workers concurrently refresh the same OAuth token,
      the first succeeds but invalidates the old refresh_token (rotation). Subsequent
      attempts using the stale token get invalid_grant, which was incorrectly treated
      as non-retryable, permanently marking the account as ERROR.
      
      Three complementary fixes:
      1. Race-aware recovery: after invalid_grant, re-read DB to check if another
         worker already refreshed (refresh_token changed) — return success instead
         of error
      2. In-process mutex (sync.Map of per-account locks): prevents concurrent
         refreshes within the same process, complementing the Redis distributed lock
      3. Increase default lock TTL from 30s to 60s to reduce TTL-expiry races
      Co-Authored-By: default avatarClaude Opus 4.6 (1M context) <noreply@anthropic.com>
      ef8a7c0a
    • Alex's avatar
      fix(openai): do not normalize /completion API token based accounts · 66e06527
      Alex authored and 陈曦's avatar 陈曦 committed
      66e06527
    • Alex's avatar
      fix(openai): do not normalize API token based accounts · e7439c32
      Alex authored and 陈曦's avatar 陈曦 committed
      e7439c32
    • shaw's avatar
      feat: Beta策略支持按模型区分处理(模型白名单) · 248fe092
      shaw authored and 陈曦's avatar 陈曦 committed
      248fe092
    • shaw's avatar
      fix: 非流式路径在上游终态事件output为空时从delta事件重建响应内容 · b85ab201
      shaw authored and 陈曦's avatar 陈曦 committed
      上游API近期更新后,response.completed终态SSE事件的output字段可能为空,
      实际内容仅通过response.output_text.delta等增量事件下发。流式路径不受影响,
      但chat_completions非流式路径和responses OAuth非流式路径只依赖终态事件的
      output,导致返回空响应。
      
      新增BufferedResponseAccumulator累积器,在SSE扫描过程中收集delta事件内容
      (文本、function_call、reasoning),当终态output为空时补充重建。
      
      同时修复handleChatBufferedStreamingResponse遗漏response.done事件类型的问题。
      b85ab201
    • shaw's avatar
      fix: 非Claude Code客户端system prompt迁移至messages以绕过第三方应用检测 · f568ec76
      shaw authored and 陈曦's avatar 陈曦 committed
      Anthropic近期引入基于system参数内容的第三方应用检测机制,原有的前置追加
      Claude Code提示词策略无法通过检测(后续内容仍为非Claude Code格式触发429)。
      
      新策略:对非Claude Code客户端的OAuth/SetupToken账号请求,将system字段
      完整替换为Claude Code标识提示词,原始system内容作为user/assistant消息对
      注入messages开头,模型仍接收完整指令。
      
      仅影响/v1/messages路径,chat_completions和responses路径保持原有逻辑不变。
      真正的Claude Code客户端请求完全不受影响(原样透传)。
      f568ec76
    • qingyuzhang's avatar
      fix(openai): fail over passthrough 429 and 529 · cec5a3bf
      qingyuzhang authored and 陈曦's avatar 陈曦 committed
      cec5a3bf
  2. 05 Apr, 2026 9 commits
  3. 04 Apr, 2026 9 commits
    • erio's avatar
      refactor: unify interval filtering and eliminate redundant Resolve calls · e88b2890
      erio authored
      - applyRequestTierOverrides now uses filterValidIntervals consistently
        with applyTokenOverrides (per_request/image modes were not filtering)
      - CostInput accepts optional pre-resolved pricing via Resolved field,
        eliminating duplicate Resolver.Resolve() calls in gateway billing paths
      e88b2890
    • erio's avatar
      fix: resolve golangci-lint issues — remove unused constants and functions, fix gofmt · 1b5ae71d
      erio authored
      - Remove unused claudeMax*Tokens constants (Claude Max feature not included)
      - Remove unused UsageMapHook type, SetUsageMapHook method, and usageToMap function
      - Fix gofmt formatting in channel_service.go, openai_model_mapping_test.go,
        chatcompletions_to_responses.go
      1b5ae71d
    • erio's avatar
      revert: remove antigravity credits precheck logic (not part of channel feature) · d4ff835b
      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.
      d4ff835b
    • erio's avatar
      refactor: remove resolveOpenAIUpstreamModel, use normalizeCodexModel directly · e27b0adb
      erio authored
      Eliminates unnecessary indirection layer. The wrapper function only
      called normalizeCodexModel with a special case for "gpt 5.3 codex spark"
      (space-separated variant) that is no longer needed.
      
      All call sites now use normalizeCodexModel directly.
      e27b0adb
    • erio's avatar
      fix: resolve cherry-pick compilation and test issues · e59fa863
      erio authored
      - Add int64(0) param to SelectAccountWithLoadAwareness callers (signature change from channel scheduling refactor)
      - Add UsageMapHook type and struct field to StreamingProcessor
      - Revert Claude Max cache billing code to upstream/main (not part of channel feature)
      - Revert credits overages logic to upstream/main (non-channel change)
      - Remove Instructions field reference (non-channel OpenAI feature)
      - Restore sora_client_handler_test.go from upstream + add channel service nil params
      e59fa863
    • erio's avatar
      feat(channel): improve cache strategy and add restriction logging · 58f758c8
      erio authored
      - Change channel cache TTL from 60s to 10min (reduce unnecessary DB queries)
      - Actively rebuild cache after CRUD instead of lazy invalidation
      - Add slog.Warn logging for channel pricing restriction blocks (4 places)
      58f758c8
    • erio's avatar
      fix: channel cache fail-close, group conflict check across pages, status toggle stale data · feb6999d
      erio authored
      - GetGroupPlatforms failure now stores error-TTL cache and returns error (fail-close)
      - Frontend group-to-channel conflict map loads all channels instead of current page only
      - Toggle channel status reloads list when active filter would hide the changed item
      feb6999d
    • erio's avatar
      fix: resolve 5 audit findings in channel/credits/scheduling · 71f61bbc
      erio authored
      P0-1: Credits degraded response retry + fail-open
      - Add isAntigravityDegradedResponse() to detect transient API failures
      - Retry up to 3 times with exponential backoff (500ms/1s/2s)
      - Invalidate singleflight cache between retries
      - Fail-open after exhausting retries instead of 5h circuit break
      
      P1-1: Fix channel restriction pre-check timing conflict
      - Swap checkClaudeCodeRestriction before checkChannelPricingRestriction
      - Ensures channel restriction is checked against final fallback groupID
      
      P1-2: Add interval pricing validation (frontend + backend)
      - Backend: ValidateIntervals() with boundary, price, overlap checks
      - Frontend: validateIntervals() with Chinese error messages
      - Rules: MinTokens>=0, MaxTokens>MinTokens, prices>=0, no overlap
      
      P2: Fix cross-platform same-model pricing/mapping override
      - Store cache keys using original platform instead of group platform
      - Lookup across matching platforms (antigravity→anthropic→gemini)
      - Prevents anthropic/gemini same-name models from overwriting each other
      71f61bbc
    • erio's avatar
      test: add unit tests for channel pricing restriction in scheduling phase · 6d3ea64a
      erio authored
      20 test cases covering:
      - billingModelForRestriction: 4 cases (requested/channel_mapped/upstream/empty)
      - resolveAccountUpstreamModel: 3 cases (antigravity/unsupported/non-antigravity)
      - checkChannelPricingRestriction: 10 cases (nil guards, 3 billing sources,
        RestrictModels disabled, no channel)
      - isUpstreamModelRestrictedByChannel: 3 cases (restricted/allowed/unsupported)
      6d3ea64a