* 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
* 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
* 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
- 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.
Resolve verified V1 frontend feedback by improving channel workflows, auth behavior, API key interactions, user filtering, layout persistence, subscription quota handling, i18n text, pricing metadata, and stale frontend cache recovery.
- Add a global frontend cache version cleanup to prevent old frontend localStorage from causing page errors after upgrades.
- Fix channel copy refresh, model mapping input focus loss, create-channel fetch-model title state, upstream model update confirmation, and batch test toast behavior.
- Respect password login settings and improve Turnstile, forgot-password, registration, and invite-link flows.
- Make user role/status filtering server-side and preserve table page size in URLs.
- Improve API key edit validation feedback and prefetch real keys for reliable copy actions.
- Fix rankings access fail-open behavior, double scrollbars, subscription received amount conversion/display, token i18n wording, model deletion confirmation grammar, and Claude pricing context inference.
- Add clearer Playground model/group loading errors.
Validation:
- bun run typecheck
- bun run i18n:sync
- gofmt on modified Go files
- go test ./controller ./model -run '^$'
Admin username/ID was embedded directly into the log Content for
quota changes and forced 2FA disable, leaking the operator's
identity to the target user via their own usage log page.
Move operator info into Other.admin_info so formatUserLogs strips
it for non-admin viewers, and render it in the expand panel only
for admins as "操作管理员".
Closes#4301
When an admin disables/deletes/promotes/demotes a user via ManageUser,
explicitly evict the user cache and all of the user's token caches from
Redis. This prevents a disabled user from continuing to make successful
API requests until the user cache TTL expires, and ensures subsequent
requests reload fresh status from the database.
ValidateAndFill now checks the DB query result and returns sentinel errors
(ErrDatabase, ErrInvalidCredentials, ErrUserEmptyCredentials) instead of
hardcoded Chinese strings. The controller maps each sentinel to the
appropriate i18n message, so users see "please contact admin" on DB errors
instead of a misleading "wrong password" message. Non-DB errors still
return a unified vague response to avoid leaking user existence.
- Refactor token, redemption, and user quota inputs to prioritize monetary
amount entry, with raw quota input collapsed by default
- Add atomic quota adjustment modal for users with add/subtract/override modes,
bypassing batch update queue for immediate DB consistency
- Make user quota fields readonly in edit form; all modifications go through
the dedicated adjust-quota modal via POST /api/user/manage
- Add DecreaseUserQuota `db` parameter for direct DB writes, matching
IncreaseUserQuota behavior
- Support negative quota display in amount conversion helpers
- Add i18n keys for all new UI strings across all locales
- Switch /api/oauth/email/bind and /api/oauth/wechat/bind from GET to
POST with JSON body for better REST semantics
- Normalize password reset endpoint to return consistent responses
- Apply url.QueryEscape to WeChat code parameter for robustness
- Change default language fallback to English instead of Chinese
- Add ErrRedeemFailed typed error for model layer translation
- Migrate remaining hardcoded messages in controller/user.go
- Add translation keys: redeem.failed, user.create_default_token_error, common.uuid_duplicate, common.invalid_input
- Add go-i18n library for internationalization
- Create i18n package with translation keys and YAML locale files (zh/en)
- Implement i18n middleware for language detection from user settings and Accept-Language header
- Add Language field to UserSetting DTO
- Update API response helpers with i18n support (ApiErrorI18n, ApiSuccessI18n)
- Migrate hardcoded messages in token, redemption, and user controllers
- Add frontend language preference settings component
- Sync language preference across header selector and user settings
- Auto-restore user language preference on login
This commit refactors the logging mechanism across the application by replacing direct logger calls with a centralized logging approach using the `common` package. Key changes include:
- Replaced instances of `logger.SysLog` and `logger.FatalLog` with `common.SysLog` and `common.FatalLog` for consistent logging practices.
- Updated resource initialization error handling to utilize the new logging structure, enhancing maintainability and readability.
- Minor adjustments to improve code clarity and organization throughout various modules.
This change aims to streamline logging and improve the overall architecture of the codebase.
This commit introduces a major architectural refactoring to improve quota management, centralize logging, and streamline the relay handling logic.
Key changes:
- **Pre-consume Quota:** Implements a new mechanism to check and reserve user quota *before* making the request to the upstream provider. This ensures more accurate quota deduction and prevents users from exceeding their limits due to concurrent requests.
- **Unified Relay Handlers:** Refactors the relay logic to use generic handlers (e.g., `ChatHandler`, `ImageHandler`) instead of provider-specific implementations. This significantly reduces code duplication and simplifies adding new channels.
- **Centralized Logger:** A new dedicated `logger` package is introduced, and all system logging calls are migrated to use it, moving this responsibility out of the `common` package.
- **Code Reorganization:** DTOs are generalized (e.g., `dalle.go` -> `openai_image.go`) and utility code is moved to more appropriate packages (e.g., `common/http.go` -> `service/http.go`) for better code structure.