* feat(token): support custom auto group order
* feat(keys): enhance auto group presentation
* fix(keys): rework Auto flow border and compact inherited order
The Auto group highlight previously tinted the whole control surface
with a gradient and animated only a 1px top sweep, which read as a
background color rather than a flowing border. Replace it with a
border-only effect: an aria-hidden, pointer-events-none overlay whose
conic gradient is masked down to a thin ring hugging the rounded
perimeter, so the highlight travels around all four edges and corners
every 3.2s. The interior stays neutral with a restrained static
primary border and glow; prefers-reduced-motion hides the moving
layer while keeping the static emphasis.
The inherited global Auto order also rendered as spacious two-line
rows with circular sequence markers, wasting drawer space. Render it
as a compact wrapping strip of one-line chips (index, name, ratio
badge) with descriptions kept accessible via title and sr-only text,
scrolling only past a much smaller max height.
Custom add/remove/reorder editing, empty-array inheritance semantics,
and the submit payload are unchanged.
* fix(keys): preserve Auto inheritance and unify effects
* refactor(keys): temporarily disable AutoGroupBadge in api-key-group-cell
Follow-up to #6518 (issue #6480) addressing three review findings:
- Document and lock in arrears semantics for the wallet Reserve top-up:
when an auto-group retry lands on a more expensive group, the full
reservation delta is deducted unconditionally (balance may go
negative), mirroring settlement, so the logged pre-consumed quota
always reconciles with the actual balance movement. Genuine DB
errors still fail the attempt with update_data_error. Subscription
funding keeps its insufficient-quota behavior: subscriptions enforce
a hard used<=total cap and do not support arrears.
- PriceData.FreeModel is cleared when a retry switches from a free
group to a paid one, keeping it consistent with the billing session
created at that point.
- getChannel refreshes GroupRatioInfo only after channel selection
succeeds, and the retry loop records the channel in use_channel
before PrepareTieredBillingForSelectedGroup can fail.
* docs: add design spec for OIDC custom display name
Mirrors the existing Custom OAuth Provider name pattern so admins can
show a meaningful label instead of the hardcoded "OIDC" on the login
page and in related copy.
* feat(oidc): add configurable display name with OIDC fallback
* feat(oidc): use configured display name in provider name and status API
* feat(oidc): add display name field to default-theme OIDC settings
Claude-Session: https://claude.ai/code/session_01FDkWJqigJi9yE3HG5pjZP5
* feat(oidc): show configured display name on default-theme login button
* feat(oidc): add display name field to classic-theme OIDC settings
* feat(oidc): show configured display name on classic-theme login button
* fix(oidc): trim whitespace before applying display name fallback
* chore: remove internal design doc from PR
Design/planning docs are working artifacts for this session and
shouldn't be submitted to the upstream project.
* fix(oidc): lead with example in classic-theme display name placeholder
Reorders the combined placeholder to show the example first, then
the fallback note, matching the Custom OAuth Provider Name field's
placeholder convention (example-only) that this feature mirrors.
* fix(i18n): improve Russian grammar in OIDC display-name placeholder translation
Leads each clause with its condition/subject and adds the missing
verb, per PR review feedback.
* test(web): remove redundant OIDC harness tests
* test(relayconvert): add golden snapshot matrix and relaykit boundary guard
Phase 0 of the relaykit extraction plan: pin byte-level output of every
registered (from,to) request/response/stream conversion route, and
forbid kit-bound packages from growing host-only imports.
* wip(relayconvert): drop gin.Context from converter signatures; add convmeta draft
Phase 1 in progress: relayconvert now takes context.Context; host media
resolver adapts gin.Context back at the service boundary.
* refactor(relayconvert): decouple converters from RelayInfo, gin, and settings
Phase 1 of the relaykit extraction plan:
- converters now depend on convmeta.Meta (implemented by RelayInfo) instead
of *relaycommon.RelayInfo; ClaudeConvertInfo and the format guesser move
to convmeta with aliases left behind
- host settings reach converters via a convmeta.Options snapshot built in
RelayInfo.ConvOptions; no more model_setting/reasoning global reads inside
the conversion layer
- effort-suffix helpers move to service/relayconvert/reasoning (old package
forwards); chat-to-responses upgrade policy moves to service (host routing
logic, not conversion)
- golden conversion matrix unchanged
* test(relayconvert): tighten boundary — kit packages now free of gin/setting imports
* refactor(dto): drop gin and logger dependencies
Phase 2 (part 1): dto.Request.IsStream now takes *http.Request instead of
*gin.Context (Gemini's impl reads query/path off the std request); dto's
three logger calls become common.SysError. Boundary test allowlist is now
empty — kit-bound packages import no gin/setting/logger/model.
* refactor(kit): extract dependency-free kitutil; dto/types/relayconvert stop importing common
Phase 2 of the relaykit extraction plan:
- new service/relayconvert/kitutil holds the pure helpers the kit needs
(JSON wrappers, pointer/string/uuid/timestamp utils, MaskSensitiveInfo,
pluggable LogInfo/LogError hooks, Debug flag)
- dto, types, and all relayconvert packages now use kitutil; their only
remaining internal deps are dto/types/constant
- common keeps every original symbol (MaskSensitiveInfo delegates to
kitutil) so host code is untouched; main.go routes kit logging into
common.SysLog/SysError and mirrors DebugEnabled
- golden conversion matrix unchanged
* refactor(kit): move EndpointType/FinishReason to types; OpenRouter dialect via Options
Kit packages (dto/types/relayconvert/reasonmap) no longer import constant:
- EndpointType and finish-reason values live in types; constant re-exports
- the OpenRouter special-case in claude->openai request conversion reads
Options.OpenRouterDialect, set by the host from the channel type;
InitChannelMeta invalidates the cached snapshot on channel switch
* refactor: extract relaykit submodule (dto/types/relayconvert/reasonmap)
Phase 3 of the relaykit extraction plan:
- new go module github.com/QuantumNous/new-api/relaykit containing dto
(minus task family), types, relayconvert (with convmeta/kitutil/reasoning),
and reasonmap; host consumes it via require + replace, go.work for dev
- task-family dto (task/suno/midjourney/video) stays in the host dto
package; dual-consumer host files alias it as taskdto
- relaykit builds and tests standalone (GOWORK=off): no host imports,
no gin, no DB, no settings
- golden conversion matrix unchanged
* build(docker): copy relaykit/go.mod before go mod download
The local-replace submodule's go.mod must exist inside the build context
for the main module graph to resolve.
* fix: address relaykit extraction regressions
* fix: address relaykit review regressions
* docs: document Meta nil receiver contract
* fix(relaykit): fail OpenAI→Claude conversion without max_tokens; reject negative default_max_tokens
The Claude Messages API requires max_tokens (omitting it is a 400
"Field required"), but with a nil Options.Claude.DefaultMaxTokens hook
the converters silently emitted a request the upstream is guaranteed to
reject. Both OpenAI Chat and Responses → Claude conversions now return
sharedclaude.ErrMissingMaxTokens when no path (client value, default
hook, thinking-adapter floor) supplied one. Unreachable in the host,
which always configures the hook.
Host side, claude.default_max_tokens now rejects negative values at the
option API before persisting — they would wrap into huge unsigned values
during conversion. Zero stays allowed: the current API treats
max_tokens: 0 as cache pre-warming.
* fix: make Gemini safety settings read path race-free
When the dashboard token refresh endpoint returned 429 (shared
critical rate limit) the frontend classified it as out_of_sync,
cleared local auth state, and redirected to /sign-in. The rate limit
itself is working as intended; the bug is that a temporary rejection
was treated as a terminal auth failure.
- Treat 429 refresh responses as transient errors on the frontend,
keeping the session retryable instead of clearing it. Only explicit
401 or confirmed session mismatch/race exhaustion clears auth state.
- Return Retry-After on all rate-limited responses (remaining TTL on
Redis, window duration on the in-memory limiter) so clients can
back off.
- Log the underlying error with request context when auth session
errors map to 500 AUTH_INTERNAL_ERROR, and replace fmt.Println with
request-scoped logging in the Redis rate limiter error paths.
Fixes#6361
* fix(playground): resolve auto group model listing
- merge and deduplicate available models in configured auto group order.
- reuse special usable group rules and add model filtering regression coverage.
* refactor: extract GetGroupsEnabledModels to dedupe group model expansion
* feat: support upstream model fetch for advanced custom channels
* fix: add advanced custom routes as separate groups
* fix: select advanced custom route entry before adding
---------
Co-authored-by: CaIon <i@caion.me>
* fix(i18n): clarify Go regex and field passthrough copy
* feat(channel): support Codex upstream model discovery
* Revert "fix(i18n): clarify Go regex and field passthrough copy"
This reverts commit d63d7975db3e34ff44e189112d3c15ad8c24ad88.
* fix: add server-side sorting to user list, prevent client-side sort on paged data
The user management table applied client-side sorting to the current
page slice while pagination was handled server-side, causing ID-asc
views to show pages out of order (e.g. 23-42, 3-22, 1-2).
Backend: add sort_by/sort_order query params to GetAllUsers and
SearchUsers with a column whitelist for safe ORDER BY generation.
Frontend: pass sorting state to the API and reset to page 1 on sort
change. Generic useDataTable hook now disables client-side sorted row
model and sort UI for tables with manual pagination but no server-side
sort handler.
* fix: add id tie-breaker to non-unique sort columns, remove side effect from state updater
Append secondary ORDER BY id DESC when sorting by non-unique columns
(quota, created_at, etc.) to prevent row duplication/skipping across
OFFSET pages.
Move onPaginationChange out of setSorting updater to avoid side effects
inside a pure function (React Strict Mode double-invocation safety).
* fix: purge authentication data on hard user deletion
* fix: fail closed when 2FA status lookup fails
* fix: reject stale Telegram login callbacks
* fix(twofa): prevent concurrent backup code and lockout bypasses
* fix(auth): harden user deletion and Telegram verification
* refactor: consolidate relay protocol converters
* refactor relayconvert text converters
* feat: refine relay converters and advanced custom routing
* refactor: enhance logging and add thought signature handling for Gemini requests
* refactor: enhance channel cache and pricing endpoint handling for advanced custom models
* feat: preserve billing usage semantics
* feat: add protocol-aware billing usage
* Delete useless files
* chore: update action versions in workflow files
* chore: update Docker action versions in workflow files
* fix: harden billing usage settlement and hot-path route matching
- estimate Gemini completion tokens locally when billable usageMetadata is
prompt-only but output content was received (e.g. client aborts the stream
before the final chunk), and rebuild the attached billing_usage as estimated
so settlement does not bill zero output tokens
- guard NewClaudeMessagesBillingUsage against all-zero ClaudeUsage, matching
the OpenAI/Gemini constructors, so a zero billing_usage cannot override a
non-zero top-level usage during settlement
- cache compiled advanced-custom route model regexes; they run on the request
hot path and were recompiled per request
- move the effectiveBillingUsage remap to PostTextConsumeQuota only, and
document that calculateTextQuotaSummary expects remapped usage
- document the updatePricingLock -> channelSyncLock lock ordering that
InitChannelCache/CacheUpdateChannel rely on, and the aux-struct pitfall in
GeminiChatResponse.UnmarshalJSON
controller/task_video.go and service/pre_consume_quota.go were already
removed in ba25ba88f and 116004fd4 (logic lives in service/task_polling.go
and BillingSession now), then brought back as stale copies by a42b39760.
Both have zero callers.
controller/swag_video.go is a leftover swag stub: the swaggo pipeline is
gone and docs/openapi/relay.json already documents these routes.
* feat(subscription): add admin quota reset actions
* fix(subscription): keep quota reset in plan row actions
* refactor(subscription): move user subscription actions into menu
Thread int32 saturation clamps from tiered settlement and video task
recompute into the consume/task logs under admin_info, so oversized or
malformed billing inputs stay auditable. Clamp negative audio duration
before token conversion and gate the saturation UI markers on admin.
Bound user-supplied count/duration parameters at request validation,
route ratio multipliers through guarded setters, and use saturating
int conversions in all quota math paths.
Pin down the checkUpdatePassword contract:
- changing a password requires the correct current password
- OAuth/passwordless accounts (empty password hash) cannot set a
password through the self-service endpoint and must use the password
reset flow instead
- setupLogin never writes back the password column
These guard against regressing the password-change path back into a
short-circuit that lets passwordless accounts set a password directly.
- normalize emails (trim + lowercase) and enforce uniqueness across
registration, OAuth auto-registration, and email binding
- serialize concurrent writers on the same normalized email within a
transaction to avoid duplicate accounts
- resolve password reset to a single matching account and reject
ambiguous or absent matches
- require an existing password before self-service password change and
reject login for accounts without a usable password
* refactor(playground): streamline chat request state
- extract conversation actions from the page component to keep message flow logic reusable.
- unify streaming and non-streaming generation state, including abort support for non-stream requests.
- simplify message rendering and payload construction while localizing Playground prompts.
* fix(playground): validate persisted chat state
- wrap saved Playground state with a storage version while still reading legacy values.
- validate config, parameter toggles, and messages before restoring them from localStorage.
- cap stored chat history to the latest messages to avoid oversized or stale state.
* refactor(playground): centralize message content access
- route chat rendering, copy actions, and error display through shared message helpers.
- reuse the current-version update helper for non-streaming assistant responses.
- keep message version details behind utility functions to reduce future model churn.
* refactor(playground): split storage schemas
- move Playground storage validation schemas into a dedicated module.
- keep storage read and write logic focused on migration, trimming, and persistence.
- preserve the existing storage envelope and validation behavior.
* refactor(playground): extract options loading hook
- move model and group queries into a dedicated hook so the page component stays focused on layout wiring.
- preserve existing fallback selection and error toast behavior while reusing the hook through the playground barrel export.
* refactor(playground): extract prompt suggestions
- move static prompt suggestion rendering into a focused component so the input stays centered on compose controls.
- preserve translated suggestion submission behavior while isolating icon metadata from the input form.
* refactor(playground): extract input tools
- move attachment and search controls into a dedicated component so the prompt input stays focused on compose state.
- keep existing development toast behavior and disabled handling while centralizing tool metadata.
* refactor(playground): extract input controls
- move model, group, send, and stop controls into a focused component so the input only manages compose state.
- preserve existing disabled states and generation button behavior while isolating control rendering.
* refactor(playground): extract message content display
- move sources, reasoning, loading, error, and response rendering into a dedicated message content component.
- keep the chat list focused on message iteration, edit state, and action wiring without changing display behavior.
* refactor(playground): extract message editor
- move inline message editing controls into a dedicated editor component so the chat list stays focused on rendering flow.
- preserve save, save-and-submit, cancel, and disabled-state behavior for edited messages.
* refactor(playground): extract stream error parsing
- move SSE error payload parsing into a reusable stream utility so the request hook stays focused on lifecycle handling.
- preserve existing error message, error code, and fallback behavior for raw or empty stream errors.
* refactor(playground): extract request error parsing
- move non-stream request error extraction into a shared utility so the chat handler stays focused on request flow.
- preserve the existing response message, error code, and fallback priority for failed chat completions.
* refactor(playground): extract streaming chunk updates
- move reasoning and content chunk application into a message utility so the chat handler only wires stream events.
- preserve error-state skipping, reasoning accumulation, and content streaming behavior for assistant messages.
* refactor(playground): extract message reasoning parser
- move think tag parsing into a dedicated playground message utility.
- export the parser through the shared playground lib barrel for consistent imports.
* refactor(playground): extract message streaming utilities
- move stream chunk application and message finalization into a dedicated utility.
- keep stored message sanitization with the streaming lifecycle helpers.
* refactor(playground): extract message update utilities
- move assistant message update helpers into a focused playground utility.
- keep error-state message updates separate from core message construction helpers.
* refactor(playground): extract completion choice handling
- move non-streaming choice application into the message streaming utilities.
- keep the chat handler focused on request orchestration and message updates.
* refactor(playground): centralize assistant completion state
- add a helper for finalizing assistant messages with complete status.
- reuse the helper in stream completion and stop-generation paths.
* refactor(playground): extract stream message parsing
- move SSE delta parsing into a shared stream utility.
- keep the stream request hook focused on lifecycle handling and update dispatch.
* refactor(playground): extract stream ready state checks
- move SSE ready-state status handling into stream utilities.
- keep weak source status typing outside the stream request hook.
* refactor(playground): extract conversation message helpers
- move send, regenerate, and edit message list construction into focused utilities.
- keep the conversation hook focused on edit state and update dispatch.
* refactor(playground): extract state initialization helpers
- move playground initial state loading into focused utility helpers.
- centralize message state updater resolution outside the React state hook.
* refactor(playground): extract option fallback helpers
- move model and group fallback selection into focused playground utilities.
- keep the options hook focused on query results, toasts, and config updates.
* refactor(playground): extract message action helpers
- move message action state derivation into focused utilities.
- keep the action component focused on guarded handlers and rendering.
* refactor(playground): extract input control state
- move submit, stop, and selector state derivation into a pure helper.
- keep input controls focused on rendering model selectors and action buttons.
* refactor(playground): extract message content state
- move source, reasoning, loader, and body visibility checks into a pure helper.
- use a discriminated state shape so rendered reasoning content stays type-safe.
* refactor(playground): extract message editor state
- move save eligibility and submit visibility checks into a pure helper.
- keep the editor component focused on textarea and button rendering.
* refactor(playground): extract message error state
- move error kind, fallback content, and admin visibility checks into a pure helper.
- centralize the model pricing settings path used by the error action.
* refactor(playground): extract chat render state
- move editing content lookup and per-message render flags into conversation helpers.
- keep the chat component focused on mapping messages to editor and content views.
* refactor(playground): extract suggestion display state
- move suggestion class selection into a pure helper.
- keep the suggestions component focused on translation and rendering.
* refactor(playground): extract assistant message state checks
- move final and pending assistant status checks into streaming utilities.
- keep the chat handler focused on request lifecycle updates.
* refactor(playground): extract input tool state
- move attachment action metadata and development notices into input tool utilities.
- keep the input tools component focused on menu and button rendering.
* refactor(playground): extract stream protocol checks
- move SSE done-message and closed-ready-state checks into stream utilities.
- keep the stream request hook focused on event handling flow.
* refactor(playground): extract message removal helper
- move delete-message filtering into conversation message utilities.
- keep the conversation hook focused on action orchestration.
* refactor(playground): extract option error messages
- move option load error message selection into playground option utilities
- keep the options hook focused on query effects and fallback updates
* refactor(playground): extract input submit text helper
- move prompt submit text validation into input control utilities
- let the input component submit only when a concrete text value is available
* refactor(playground): centralize error message checks
- add a shared helper for identifying error messages
- remove direct status string checks from message content rendering
* refactor(playground): extract message content display checks
- move loader and content visibility decisions into local helper functions
- keep message content state assembly focused on composing render state
* refactor(playground): replace raw message role checks
- use shared message role constants in conversation edit handling
- avoid raw assistant role literals when validating API messages
* refactor(playground): extract non-stream response handling
- move chat completion response choice handling into message streaming utilities
- keep the chat handler focused on request lifecycle and error routing
* refactor(playground): centralize stream cleanup
- reuse one stream cleanup path for completion, errors, startup failures, and manual stops
- preserve the current-source guard when closing SSE streams
* refactor(playground): extract pending assistant check
- centralize pending assistant message detection in streaming utilities
- reuse the helper when sanitizing stored playground messages
* perf(playground): improve mobile input controls
- split mobile input controls into selector and action rows
- keep the desktop input footer compact while reducing mobile control crowding
* perf(playground): add starter empty state
- show starter prompts in the empty playground chat area
- wire empty-state prompt selection into the existing send flow
- add localized copy for the new empty state
* perf(playground): improve mobile message actions
- collapse mobile message actions into a touch-friendly dropdown menu
- keep the desktop hover action strip unchanged for pointer workflows
- share one action list between desktop buttons and the mobile menu
* perf(playground): add error recovery actions
- show retry, edit, and delete actions inside error message alerts
- route edit recovery to the previous user prompt when available
- keep recovery controls touch-friendly on mobile layouts
* perf(playground): refine message editing experience
- present message edits in a focused bordered editor panel
- add unsaved-change state, reset, and cancel confirmation flows
- improve mobile touch targets and keyboard shortcuts for editing
* perf(playground): improve markdown code blocks
- render fenced markdown code with syntax highlighting, line numbers, and fallback plain text
- add copy, download, and collapse controls for playground AI responses
- tighten code block layout and theme token styles for responsive markdown rendering
* fix(playground): constrain markdown code block height
- collapse long playground code blocks after a short preview instead of waiting for very large snippets
- cap expanded code blocks so long responses scroll inside the code block
- keep generic code block usage unconstrained unless a caller opts in
* feat(playground): add chat history clearing
- add a toolbar action that is enabled only when saved playground messages exist.
- confirm destructive clears before removing browser-stored conversation state.
- add localized strings for the action, dialog, and completion toast.
* perf(playground): improve chat markdown rendering
- refine assistant and user message surfaces so chat content matches the app UI.
- normalize markdown typography, tables, images, lists, blockquotes, and details rendering.
- add indentation cues for collapsible reasoning and source sections.
* style: format code block component
* style: format playground frontend files
* feat(playground): render markdown with stream parser
- replace Streamdown with stream-markdown-parser for project-owned markdown rendering and styling.
- split response rendering into focused block, inline, table, alert, details, and footnote modules.
- pass message final state into response parsing so streaming content can be parsed incrementally.
* fix(playground): localize reasoning and chat feedback
- translate reasoning status, message actions, playground errors, and response renderer fallbacks across supported locales.
- keep reasoning duration numeric and tighten the collapsible layout to prevent trigger jitter.
- register dynamic keys so i18n sync keeps runtime labels covered.
* refactor(playground): group files by functional area
- move chat, input, and message components into focused subdirectories to make the UI structure easier to scan.
- split playground helpers into input, message, streaming, storage, options, state, and suggestions modules.
- update barrel exports and imports so existing feature entry points continue to work.
* fix(playground): prevent history replay from freezing page
- defer saved conversation loading so route entry no longer blocks on localStorage parsing and markdown rendering.
- limit initial history rendering and skip expensive markdown parsing for oversized responses.
- normalize corrupted streaming snapshots and cumulative chunks to keep saved playground history bounded.
- add message timing metadata and layout alignment groundwork without introducing live timers.
* feat(playground): allow regenerating from user messages
- show regenerate actions on user messages with saved content.
- truncate following conversation state before starting a fresh assistant response.
* feat(playground): add raw response source view
- add a per-message source toggle for assistant responses.
- render raw response content with the existing code block viewer.
- localize the new source and preview action labels.
* feat(playground): render code with unified editor
- replace Shiki HTML rendering with a read-only CodeMirror view for code blocks and raw responses.
- reuse the same CodeMirror frame for message editing so source and edit modes stay visually aligned.
- add lightweight CodeMirror dependencies while keeping language support scoped to Markdown.
* perf(playground): streamline chat input controls
- combine model and group selection into one compact picker for faster context switching.
- switch playground action buttons to icon-first controls with tooltips to reduce toolbar width.
- refresh input footer styling and submit states so active and destructive actions are clearer.
- bump dompurify lockfile entry to keep the frontend dependency current.
* fix(playground): filter models by selected group
- query user models by the selected playground group instead of reusing the cross-group model union.
- clear unavailable model selections and block sending when the active group has no models.
- align model selector and error action controls with the existing playground interaction style.
* perf(playground): remove input suggestion chips
- remove the prompt suggestion row below the playground input to reduce visual noise.
- delete the now-unused suggestion component and display helper.
* perf(playground): stabilize reasoning trigger layout
- use fixed icon slots around the reasoning label so the left content stays still when toggling.
- limit the open state animation to the chevron rotation for a smoother collapse interaction.
* perf(playground): smooth reasoning expansion
- use the collapsible panel height animation for vertical reasoning reveals.
- sync inner content opacity and position with the panel state.