1. 22 Feb, 2026 25 commits
    • Merge pull request #2960 from seefs001/feature/minimax-native-claude · f8f3ee29
      feat: minimax native /v1/messages
      Calcium-Ion committed
    • Merge pull request #2961 from seefs001/feature/codex-oauth-with-proxy · c9486526
      feat: codex oauth proxy
      Calcium-Ion committed
    • feat: add missing OpenAI/Claude/Gemini request fields (#2971) · 49eb6d3c
      * feat: add missing OpenAI/Claude/Gemini request fields and responses stream options
      
      * fix: skip field filtering when request passthrough is enabled
      
      * fix: include subscription in personal sidebar module controls
      
      * feat: gate Claude inference_geo passthrough behind channel setting and add field docs
      Calcium-Ion committed
    • fix: claude affinity cache counter (#2980) · 8cfc2b43
      * fix: claude affinity cache counter
      
      * fix: claude affinity cache counter
      
      * fix: stabilize cache usage stats format and simplify modal rendering
      Seefs committed
    • feat: add validation for invalid status code entries in channel modal · bf03f277
      - Introduced a new function to collect invalid status code entries from the status code mapping.
      - Updated the EditChannelModal to display an error message if invalid status codes are detected.
      - Enhanced localization files to include new error messages for invalid status codes in multiple languages.
      - Removed unused styles from the RiskAcknowledgementModal for cleaner UI.
      CaIon committed
    • Merge pull request #2987 from seefs001/feature/channel-retry-warning · 63edb57c
      Feature/channel retry warning
      Calcium-Ion committed
    • Update README · 06fc6015
      CaIon committed
    • feat(task): introduce task timeout configuration and cleanup unfinished tasks · bc7c5cf9
      - Added TaskTimeoutMinutes constant to configure the timeout duration for asynchronous tasks.
      - Implemented sweepTimedOutTasks function to identify and handle unfinished tasks that exceed the timeout limit, marking them as failed and processing refunds if applicable.
      - Enhanced task polling loop to include the new timeout handling logic, ensuring timely cleanup of stale tasks.
      CaIon committed
    • feat(task): add model redirection, per-call billing, and multipart retry fix for async tasks · 06fe03e3
      1. Async task model redirection (aligned with sync tasks):
         - Integrate ModelMappedHelper in RelayTaskSubmit after model name
           determination, populating OriginModelName / UpstreamModelName on RelayInfo.
         - All task adaptors now send UpstreamModelName to upstream providers:
           - Gemini & Vertex: BuildRequestURL uses UpstreamModelName.
           - Doubao & Ali: BuildRequestBody conditionally overwrites body.Model.
           - Vidu, Kling, Hailuo, Jimeng: convertToRequestPayload accepts RelayInfo
             and unconditionally uses info.UpstreamModelName.
           - Sora: BuildRequestBody parses JSON and multipart bodies to replace
             the "model" field with UpstreamModelName.
         - Frontend log visibility: LogTaskConsumption and taskBillingOther now
           emit is_model_mapped / upstream_model_name in the "other" JSON field.
         - Billing safety: RecalculateTaskQuotaByTokens reads model name from
           BillingContext.OriginModelName (via taskModelName) instead of
           task.Data["model"], preventing billing leaks from upstream model names.
      
      2. Per-call billing (TaskPricePatches lifecycle):
         - Rename TaskBillingContext.ModelName → OriginModelName; add PerCallBilling
           bool field, populated from TaskPricePatches at submission time.
         - settleTaskBillingOnComplete short-circuits when PerCallBilling is true,
           skipping both adaptor adjustments and token-based recalculation.
         - Remove ModelName from TaskSubmitResult; use relayInfo.OriginModelName
           consistently in controller/relay.go for billing context and logging.
      
      3. Multipart retry boundary mismatch fix:
         - Root cause: after Sora (or OpenAI audio) rebuilds a multipart body with a
           new boundary and overwrites c.Request.Header["Content-Type"], subsequent
           calls to ParseMultipartFormReusable on retry would parse the cached
           original body with the wrong boundary, causing "NextPart: EOF".
         - Fix: ParseMultipartFormReusable now caches the original Content-Type in
           gin context key "_original_multipart_ct" on first call and reuses it for
           all subsequent parses, making multipart parsing retry-safe globally.
         - Sora adaptor reverted to the standard pattern (direct header set/get),
           which is now safe thanks to the root fix.
      
      4. Tests:
         - task_billing_test.go: update makeTask to use OriginModelName; add
           PerCallBilling settlement tests (skip adaptor adjust, skip token recalc);
           add non-per-call adaptor adjustment test with refund verification.
      CaIon committed
    • refactor(task): enhance UpdateWithStatus for CAS updates and add integration tests · 374aabf3
      - Updated UpdateWithStatus method to use Model().Select("*").Updates() for conditional updates, preventing GORM's INSERT fallback.
      - Introduced comprehensive integration tests for UpdateWithStatus, covering scenarios for winning and losing CAS updates, as well as concurrent updates.
      - Added task_cas_test.go to validate the new behavior and ensure data integrity during concurrent state transitions.
      CaIon committed
    • refactor(task): add CAS-guarded updates to prevent concurrent billing conflicts · b386490d
      Replace all bare task.Update() (DB.Save) calls with UpdateWithStatus(),
      which adds a WHERE status = ? guard to prevent concurrent processes from
      overwriting each other's state transitions.
      
      Key changes:
      
      model/task.go:
      - Add taskSnapshot struct with Equal() method for change detection
      - Add Snapshot() method to capture pre-update state
      - Add UpdateWithStatus(fromStatus) using DB.Where().Save() for CAS
        semantics with full-struct save (no explicit field listing needed)
      
      model/midjourney.go:
      - Add UpdateWithStatus(fromStatus string) with same CAS pattern
      
      service/task_polling.go (updateVideoSingleTask):
      - Snapshot before processing upstream response; skip DB write if unchanged
      - Terminal transitions (SUCCESS/FAILURE) use UpdateWithStatus CAS:
        billing/refund only executes if this process wins the transition
      - Non-terminal updates also use UpdateWithStatus to prevent overwriting
        a concurrent terminal transition back to IN_PROGRESS
      - Defer settleTaskBillingOnComplete to after CAS check (shouldSettle flag)
      
      relay/relay_task.go (tryRealtimeFetch):
      - Add snapshot + change detection; use UpdateWithStatus for CAS safety
      
      controller/midjourney.go (UpdateMidjourneyTaskBulk):
      - Capture preStatus before mutations; use UpdateWithStatus CAS
      - Gate refund (IncreaseUserQuota) on CAS success (won && shouldReturnQuota)
      
      This prevents the multi-instance race condition where:
      1. Instance A reads task (IN_PROGRESS), fetches upstream (still IN_PROGRESS)
      2. Instance B reads same task, fetches upstream (now SUCCESS), writes SUCCESS
      3. Instance A's bare Save() overwrites SUCCESS back to IN_PROGRESS
      CaIon committed
    • refactor(relay): improve channel locking and retry logic in RelayTask · 6f39c028
      - Enhanced the RelayTask function to utilize a locked channel when available, allowing for better reuse during retries.
      - Updated error handling to ensure proper context setup for the selected channel.
      - Clarified comments in ResolveOriginTask regarding channel locking and retry behavior.
      - Introduced a new field in TaskRelayInfo to store the locked channel object, improving type safety and reducing import cycles.
      CaIon committed
    • refactor(relay): enhance remix logic for billing context extraction · 143b4535
      - Updated the remix handling in ResolveOriginTask to prioritize extracting OtherRatios from the BillingContext of the original task if available.
      - Retained the previous logic for extracting seconds and size from task data as a fallback.
      - Improved clarity and maintainability of the remix logic by separating the new and old approaches.
      CaIon committed
    • refactor(relay): rename RelayTask to RelayTaskFetch and update routing · 7d5fc3ff
      - Renamed RelayTask function to RelayTaskFetch for clarity.
      - Updated routing in relay-router.go and video-router.go to use RelayTaskFetch for fetch operations.
      - Enhanced error handling in RelayTaskFetch function.
      - Adjusted task data conversion in TaskAdaptor to include task ID.
      CaIon committed
    • feat(task): add adaptor billing interface and async settlement framework · 8374a830
      Add three billing lifecycle methods to the TaskAdaptor interface:
      - EstimateBilling: compute OtherRatios from user request before pricing
      - AdjustBillingOnSubmit: adjust ratios from upstream submit response
      - AdjustBillingOnComplete: determine final quota at task terminal state
      
      Introduce BaseBilling as embeddable no-op default for adaptors without
      custom billing. Move Sora/Ali OtherRatios logic from shared validation
      into per-adaptor EstimateBilling implementations.
      
      Add TaskBillingContext to persist pricing params (model_price, group_ratio,
      other_ratios) in task private data for async polling settlement.
      
      Extract RecalculateTaskQuota as a general-purpose delta settlement
      function and unify polling billing via settleTaskBillingOnComplete
      (adaptor-first, then token-based fallback).
      CaIon committed
    • refactor(task): extract billing and polling logic from controller to service layer · ba25ba88
      Restructure the task relay system for better separation of concerns:
      - Extract task billing into service/task_billing.go with unified settlement flow
      - Move task polling loop from controller to service/task_polling.go (supports Suno + video platforms)
      - Split RelayTask into fetch/submit paths with dedicated retry logic (taskSubmitWithRetry)
      - Add TaskDto, TaskResponse generics, and FetchReq to dto/task.go
      - Add taskcommon/helpers.go for shared task adaptor utilities
      - Remove controller/task_video.go (logic consolidated into service layer)
      - Update all task adaptors (ali, doubao, gemini, hailuo, jimeng, kling, sora, suno, vertex, vidu)
      - Simplify frontend task logs to use new TaskDto response format
      CaIon committed
    • imporve oauth provider UI/UX (#2983) · 29c2c895
      * feat: imporve UI/UX
      
      * fix: stabilize provider enabled toggle and polish custom OAuth settings UX
      
      * fix: add access policy/message templates and persist advanced fields reliably
      
      * fix: move template fill actions below fields and keep advanced form flow cleaner
      Seefs committed
  2. 21 Feb, 2026 5 commits
  3. 20 Feb, 2026 3 commits
  4. 19 Feb, 2026 4 commits
  5. 17 Feb, 2026 2 commits
  6. 12 Feb, 2026 1 commit