- 08 Apr, 2026 1 commit
-
-
shaw authored
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前缀) 保持原有剥离行为。
-
- 07 Apr, 2026 6 commits
-
-
Elysia authored
当上游返回SSE格式响应(如sub2api链路)时,API Key账号的非流式路径 未检测SSE,导致终态事件中空output直接透传给客户端。 - 将Content-Type SSE检测从仅OAuth扩展至所有账号类型 - 重命名handleOAuthSSEToJSON为handleSSEToJSON(无OAuth专属逻辑) - 为透传路径新增handlePassthroughSSEToJSON,支持SSE转JSON及空output重建 Co-Authored-By:Claude Opus 4.6 (1M context) <noreply@anthropic.com>
-
shaw authored
-
shaw authored
上游API近期更新后,response.completed终态SSE事件的output字段可能为空, 实际内容仅通过response.output_text.delta等增量事件下发。流式路径不受影响, 但chat_completions非流式路径和responses OAuth非流式路径只依赖终态事件的 output,导致返回空响应。 新增BufferedResponseAccumulator累积器,在SSE扫描过程中收集delta事件内容 (文本、function_call、reasoning),当终态output为空时补充重建。 同时修复handleChatBufferedStreamingResponse遗漏response.done事件类型的问题。
-
shaw authored
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客户端请求完全不受影响(原样透传)。
-
Alex authored
-
Alex authored
-
- 05 Apr, 2026 10 commits
-
-
erio authored
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
-
erio authored
Antigravity groups were incorrectly matching pricing and model mapping entries from anthropic/gemini platform tabs. Each platform should be strictly isolated — antigravity groups only use antigravity-tagged pricing.
-
erio authored
-
erio authored
Restore gateway_service.go, setting_handler.go, routes/admin.go, dto/settings.go, group_repo.go, api_key_repo.go, wire_gen.go to upstream/main versions and surgically remove only Sora references. This preserves upstream-only features (RequireOauthOnly, RequirePrivacySet, GroupResolution, etc.) that were missing when using release branch versions.
-
shaw authored
When a channel has no model mapping for the requested model, ChannelMappedModel equals OriginalModel (the user's arbitrary input). Combined with the default BillingModelSource="channel_mapped", this incorrectly overrides the BillingModel set by the OpenAI format conversion layer (e.g., gpt-5.4 from DefaultMappedModel) back to the unmapped original model (e.g., glm) which has no pricing — resulting in zero-cost billing. Add guard condition so the channel_mapped override only fires when the channel actually changed the model (ChannelMappedModel != OriginalModel).
-
erio authored
-
erio authored
-
erio authored
- gofmt: user.go, config_test.go, group_handler.go, smart_retry_test.go - Remove unused: mergeGroupIDs, resolveProxyURL, "time" import - Fix api_contract_test.go: remove extra Sora args from NewAdminService, NewSettingHandler, NewAccountHandler; remove Sora field expectations - Fix account_test_service_openai_test.go: restore test helpers
-
erio authored
- Run gofmt on user schema, config test, group handler - Remove unused mergeGroupIDs function - Restore shared test helpers (newJSONResponse, queuedHTTPUpstream) that were in deleted Sora test file
-
erio authored
-
- 04 Apr, 2026 23 commits
-
-
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
-
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
-
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
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.
-
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
-
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)
-
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
-
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
-
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)
-
erio authored
- Fix 7 stale comments still mentioning "限制检查" in handlers/services - Make billingModelForRestriction explicitly list channel_mapped case - Add slog.Warn for error swallowing in ResolveChannelMapping and needsUpstreamChannelRestrictionCheck - Document sticky session upstream check exemption
-
erio authored
Move the model pricing restriction check from 8 handler entry points to the account scheduling phase (SelectAccountForModelWithExclusions / SelectAccountWithLoadAwareness), aligning restriction with billing: - requested: check original request model against pricing list - channel_mapped: check channel-mapped model against pricing list - upstream: per-account check using account-mapped model Handler layer now only resolves channel mapping (no restriction). Scheduling layer performs pre-check for requested/channel_mapped, and per-account filtering for upstream billing source.
-
erio authored
- Extract resolveChannelPricing to DRY the resolver pattern shared by calculateImageCost/calculateTokenCost - Remove unnecessary IIFE wrapper and pass accountRateMultiplier as parameter - Extract resolveBillingMode, resolveMediaType, optionalSubscriptionID to simplify buildRecordUsageLog (104→65 lines) - Extract shouldDeductAPIKeyQuota/shouldUpdateRateLimits/shouldUpdateAccountQuota methods on postUsageBillingParams to unify duplicated billing conditions
-
erio authored
- Extract recordUsageCore with recordUsageOpts for parameterized differences - RecordUsage (276 lines) → thin wrapper (~40 lines) - RecordUsageWithLongContext (251 lines) → thin wrapper (~20 lines) - Split billing logic into calculateSoraMediaCost, calculateImageCost, calculateTokenCost sub-functions - Extract buildRecordUsageLog for usage log construction - Net reduction: -79 lines, eliminated ~170 lines of duplication
-
erio authored
- calculateTokenCost reduced from 80 to 15 lines - calculateCostInternal reduced from 91 to 15 lines - Shared logic in computeTokenBreakdown + computeCacheCreationCost - Unified rateMultiplier <= 0 protection in both paths
-
erio authored
- Extract newEmptyChannelCache() factory to deduplicate map init - Extract expandPricingToCache() for model pricing expansion - Extract expandMappingToCache() for model mapping expansion - buildCache reduced from 110 to 50 lines
-
erio authored
- PricingSourceChannel/LiteLLM/Fallback for resolver source - MediaTypeImage/Video/Prompt for result.MediaType - Reuse BillingModeToken/BillingModeImage for billing mode - Reuse BillingModelSourceChannelMapped/PlatformAnthropic in handler
-
erio authored
Instead of hardcoding BillingMode="image" when ImageCount>0, let cost.BillingMode (set by CalculateCostUnified/CalculateImageCost) take priority. This ensures channel token pricing shows "token" mode.
-
erio authored
When ImageCount > 0, check if channel has token pricing configured: - YES (source=channel, mode=token) → use token billing with image_output_tokens - NO → fall back to CalculateImageCost (original per-image billing) This allows channels to configure $/MTok pricing for image generation models while maintaining backward compatibility for setups without channel pricing.
-
erio authored
- clearCreditsExhausted: sync Redis scheduler cache after DB update - Image billing mode UI: write to per_request_price instead of image_output_price - OpenAI RecordUsage: use BillingModelSourceRequested constant, add s.cfg nil guard - Fix i18n key path: admin.channels.perRequestPriceRequired → admin.channels.form.perRequestPriceRequired
-
erio authored
- TestIsPlatformPricingMatch: 12 cases covering all platform combinations - TestMatchingPlatforms: 4 cases for platform expansion - TestGetChannelModelPricing_AntigravityCrossPlatform: antigravity sees anthropic pricing - TestGetChannelModelPricing_AnthropicCannotSeeAntigravityPricing: no reverse leakage - TestResolveChannelMapping_AntigravityCrossPlatform: antigravity uses anthropic mapping - TestFilterValidIntervals: 8 cases for empty interval filtering - TestHasEnoughCredits: 10 cases for credits balance threshold logic - Extract hasEnoughCredits() pure function for testability
-
erio authored
- Backend: reject intervals with all-null price fields on save - Backend: filterValidIntervals skips empty intervals in pricing resolver - Frontend: red border + asterisk on empty interval rows - Backend: antigravity groups now match anthropic/gemini channel pricing
-
erio authored
Antigravity platform serves both Claude and Gemini models, but channel pricing/mapping is configured under Anthropic/Gemini tabs. The cache builder was using strict platform equality, causing antigravity groups to miss all channel pricing entries, resulting in $0 billing. Add isPlatformPricingMatch() to treat antigravity as superset of anthropic+gemini for pricing and mapping cache indexing.
-
erio authored
- Apply same nil-pointer protection as OpenAI path - Remove unused accessToken/proxyURL params from checkAccountCredits
-