Commit Graph
3080 Commits
Author SHA1 Message Date
erio 99e6dc9b8e fix: resolve CI failures — gofmt, unused functions, missing test helpers
- 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
2026-04-05 13:52:48 +08:00
erio 066b18b405 refactor: remove unused OpenAIOAuthOptions after Sora platform removal
The options parameter only served to switch between 'openai' and 'sora'
platforms. With Sora removed, the parameter is unnecessary.
2026-04-05 13:41:51 +08:00
erio 031ca66c7e fix: remove remaining unused Sora variables causing TypeScript build failure
- Remove unused accessTokenInput ref from OAuthAuthorizationFlow
- Remove unused parsedSessionToken* computed and handleValidateSessionToken
- Prefix unused options parameter in useOpenAIOAuth
2026-04-05 04:11:30 +08:00
erio 99e5a09d89 fix: remove unused Sora references causing TypeScript build failure
- Remove handleImportAccessToken event binding from CreateAccountModal
- Remove unused imports/variables from OAuthAuthorizationFlow (useAppStore,
  parsedAccessToken*, handleImportAccessToken)
- Remove unused oauthPlatform variable from useOpenAIOAuth composable
2026-04-05 04:04:47 +08:00
erio 5b849d10b7 chore: drop Sora database schema and regenerate ent code
- Add migration 090_drop_sora.sql to drop sora_tasks, sora_generations,
  sora_accounts tables and Sora columns from groups/users/usage_logs
- Remove Sora fields from ent schemas (group, user, usage_log)
- Regenerate ent code via go generate ./ent/...
- All tests pass
2026-04-05 00:55:14 +08:00
erio dece8987e9 revert: completely remove all Sora functionality
Remove ALL Sora code — client, gateway, generation, S3 storage, accounts,
media, SDK, quota, scheduling, billing, OAuth, settings, and frontend UI.

Backend: 60+ files deleted/cleaned, including service layer (scheduling,
billing, token provider), handler layer (client/gateway handlers, DTOs),
repository layer (sora repos), config, wire DI, routes, domain constants.

Frontend: 14 files deleted + 29 files cleaned, including components, views,
API clients, composables, i18n keys, types, router entries.

Cloudflare challenge detection migrated from soraerror to httputil package.
Migration files retained (046/047/063/070) to preserve DB migration history.

136 files changed, ~24,300 lines removed. All tests pass.
2026-04-04 23:50:00 +08:00
erio 60d84d621c fix: remove leftover affinity test cases from gateway_multiplatform_test.go 2026-04-04 19:18:48 +08:00
erio 53afb8c540 fix: restore upstream Sora frontend components and remove leftover i18n affinity keys 2026-04-04 17:08:43 +08:00
erio c790b808dd revert: remove affinity scheduling, Claude Max cache simulation, Sora async tasks, and GDrive remnants
Remove 4 features from the release branch to keep it focused on channel management + upstream:

1. Affinity scheduling: gateway affinity flow, Redis Lua scripts, account methods,
   handler endpoints, frontend components (AffinityBadge, AffinityConfigCard)

2. Claude Max cache simulation: billing policy, tokenizer, response helpers,
   Group.SimulateClaudeMaxEnabled field, ent schema changes, frontend toggles

3. Sora async tasks: task service/worker/repo, videos handler, object storage
   abstraction, frontend components (SoraGeneratePage, SoraProgressCard, etc.),
   S3 storage admin settings

4. Google Drive remnants: gdrive constant cleanup (base revert was already done)

All tests pass. Channel management code preserved intact.
2026-04-04 16:34:17 +08:00
erio d1499ee56f refactor: unify interval filtering and eliminate redundant Resolve calls
- applyRequestTierOverrides now uses filterValidIntervals consistently
- CostInput.Resolved allows passing pre-resolved pricing to skip duplicate Resolve
- Gateway billing paths capture resolveChannelPricing result and pass it through
2026-04-04 15:48:12 +08:00
erio 950ac48f9f revert: remove Google Drive storage backend
Remove all GDrive/Google Drive storage extension code:
- Delete 7 GDrive-specific files (handler, service, tests, router, frontend)
- Remove GDrive fields from setting service and DTOs
- Remove GDrive routes, wire dependencies, i18n entries
- Revert DataManagementView to S3-only storage management
2026-04-03 18:38:16 +08:00
erio fc5e96aa9f merge: upstream v0.1.106 into release/custom-0.1.106
Resolved conflicts:
- VERSION: set to 0.1.106.1
- wire_gen.go: keep our version with accountUsageService
- antigravity_gateway_service.go: keep accountUsageService field/param
- openai_gateway_service.go: keep billing model override logic
- account.go: keep both affinity methods and new custom base URL methods
- dto/types.go: keep both affinity fields and new custom base URL fields
- CreateAccountModal.vue: keep both affinity and custom base URL logic
- EditAccountModal.vue: keep both affinity and custom base URL state
2026-04-03 15:47:18 +08:00
erio 2ffdd2a573 chore: bump version to 0.1.105.41 2026-04-03 13:54:48 +08:00
erio 90d99f77e4 feat(channel): improve cache strategy and add restriction logging
- 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)
2026-04-03 13:54:18 +08:00
erio 8d32daa9fe chore: bump version to 0.1.105.40 2026-04-03 02:11:42 +08:00
erio 2e9c151e8f style: fix gofmt struct tag alignment 2026-04-03 02:09:49 +08:00
erio fa430746ac feat(redeem): support negative values for refund/deduction
Allow redeem codes with negative values to enable refund scenarios:
- Balance: negative value deducts balance (clamped to 0, never negative)
- Concurrency: negative value reduces concurrency (clamped to 0)
- Subscription: negative validity_days reduces remaining days; if
  remaining days <= 0, the subscription is canceled (set to expired)

All deductions generate standard redeem code records for audit trail.
2026-04-03 01:51:14 +08:00
erio 7a1a7d9c8d chore: bump version to 0.1.105.39 2026-04-02 23:47:46 +08:00
erio 89825646bc fix: channel cache fail-close, group conflict check across pages, status toggle stale data
- 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
2026-04-02 23:47:37 +08:00
erio eb90335da1 chore: bump version to 0.1.105.38 2026-04-02 21:03:40 +08:00
erio 259506b429 fix: sticky session upstream restriction bypass + 429 over-aggressive credits exhaustion
1. Sticky session now checks upstream channel restriction:
   - Add isStickyAccountUpstreamRestricted() helper
   - Apply to both routing sticky (selectAccountForModelWithPlatform)
     and normal sticky (selectAccountWithMixedScheduling)

2. shouldMarkCreditsExhausted: only mark on 429 with credits keywords:
   - Node-level rate limiting / transient 429 no longer triggers 5h circuit break
   - Extract containsCreditsExhaustedKeyword() to unify 429 and 403 paths
2026-04-02 20:57:13 +08:00
erio 5a4340e49b chore: add lodash/lodash-es audit exception for GHSA-r5fr-rjxr-66jc
_.template is not used with untrusted input; only internal admin UI.
Exception expires 2026-07-02.
2026-04-02 20:45:23 +08:00
erio 882ab7157d chore: bump version to 0.1.105.37 2026-04-02 20:28:45 +08:00
erio 1a27a4dd4c fix: resolve 5 audit findings in channel/credits/scheduling
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
2026-04-02 20:28:04 +08:00
erio 00679c9fce chore: bump version to 0.1.105.36 2026-04-02 17:22:18 +08:00
erio 3e80807e74 test: add unit tests for channel pricing restriction in scheduling phase
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)
2026-04-02 13:40:36 +08:00
erio 6229773ea0 fix: address review findings for channel restriction refactoring
- 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
2026-04-02 13:36:58 +08:00
erio 513e653a4e refactor: move channel model restriction from handler to scheduling phase
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.
2026-04-02 13:24:30 +08:00
erio 333ddfdb21 refactor: extract helpers to reduce duplication and function length in gateway billing
- 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
2026-04-02 03:28:52 +08:00
erio 5143133153 chore: bump version to 0.1.105.33 2026-04-02 02:50:12 +08:00
erio 75374d9e0d refactor: merge RecordUsage and RecordUsageWithLongContext into shared core
- 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
2026-04-02 02:45:43 +08:00
erio a1825024b4 refactor: split channelToResponse into pricingToResponse + intervalToResponse 2026-04-02 02:35:11 +08:00
erio f968e1bd95 refactor: extract computeTokenBreakdown to deduplicate billing logic
- 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
2026-04-02 02:33:05 +08:00
erio ed01e0dcb0 refactor: use structured error responses in channel handler
Replace response.BadRequest with response.ErrorFrom + infraerrors.BadRequest
to provide machine-readable reason codes (VALIDATION_ERROR, INVALID_CHANNEL_ID,
MISSING_PARAMETER) for frontend i18n support.
2026-04-02 02:32:39 +08:00
erio a745a83521 refactor: split buildCache into sub-functions, reduce nesting 5→2
- 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
2026-04-02 02:28:32 +08:00
erio 2a9cad09c4 refactor(ui): extract formatCacheTokens and formatMultiplier to shared utils 2026-04-02 02:24:05 +08:00
erio 198010f114 refactor: replace magic strings with named constants
- PricingSourceChannel/LiteLLM/Fallback for resolver source
- MediaTypeImage/Video/Prompt for result.MediaType
- Reuse BillingModeToken/BillingModeImage for billing mode
- Reuse BillingModelSourceChannelMapped/PlatformAnthropic in handler
2026-04-02 02:22:15 +08:00
erio bd1fefb475 docs: add code structuring, error response and frontend display standards 2026-04-02 02:02:11 +08:00
erio 180cf97588 fix(ui): show token breakdown when image model uses token billing
Only display image count format when billing_mode is "image".
When channel has token pricing, show input/output/cache token details.
2026-04-02 01:45:13 +08:00
erio 95d9b2d1d0 fix: billing mode display follows cost calculation result
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.
2026-04-02 01:34:19 +08:00
erio ab74dcbf9d debug: add image billing resolve logging for troubleshooting 2026-04-02 01:09:49 +08:00
erio e9586ac085 fix: validate prices must be >= 0, remove debug logs 2026-04-02 00:52:19 +08:00
erio 5fb1340681 chore: remove debug logs for candidatesTokensDetails investigation 2026-04-02 00:48:36 +08:00
erio 435f88d984 debug: print v1internal raw payload for non-stream path 2026-04-02 00:29:44 +08:00
erio 194bde4651 debug: check candidatesTokensDetails in v1internal wrapper 2026-04-02 00:24:35 +08:00
erio e772c6ba2d debug: log candidatesTokensDetails presence in extractGeminiUsage 2026-04-02 00:17:38 +08:00
erio 4a24921ca9 feat: channel token pricing takes priority over per-image billing
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.
2026-04-01 23:29:01 +08:00
erio 97a4adf648 chore: bump version to 0.1.105.32 2026-04-01 23:21:54 +08:00
erio 6b69e5c7cf fix(ui): also fix floating point precision in mTokToPerToken 2026-04-01 23:18:03 +08:00
erio 2646173a84 fix(ui): floating point precision in perTokenToMTok conversion 2026-04-01 23:15:59 +08:00