Commit Graph
6181 Commits
Author SHA1 Message Date
CaIon c27d1ef651 Update .gitattributes 2026-07-29 13:45:10 +08:00
CaIon afe16c64cd feat: add README.md for RelayKit module with capabilities and usage examples 2026-07-28 15:24:37 +08:00
CaIon 1db6ae1957 feat: enhance CI workflow to include vetting for Go modules 2026-07-28 15:09:49 +08:00
CaIon 8e2bfe278b refactor: remove mutex from CustomEvent and update TCP connection handling in tests 2026-07-28 15:09:49 +08:00
feitianbubu c3db41407d fix: 慢查询/错误 SQL 日志参数化 (#6493)
* fix: parameterize slow/error SQL logs to avoid leaking credentials

* fix: validate SQL_SLOW_THRESHOLD_MS range

* fix: sanitize database driver error messages in SQL logs

* refactor: sanitize at gorm log writer seam to keep caller attribution
2026-07-27 22:21:31 +08:00
CaIon f01c13b086 feat: add CI workflow for backend and frontend build, typecheck, and test 2026-07-27 22:07:09 +08:00
CaIon 2cf3c8d71e docs: update AGENTS.md 2026-07-27 21:41:31 +08:00
CaIon e99a9bd86f feat: add per-channel HTTP transport controls 2026-07-27 21:41:13 +08:00
CaIon b27b2b1d6f fix(web): detect iPad login sessions correctly 2026-07-27 21:19:42 +08:00
CaIon a043eef559 feat: implement Gemini to OpenAI chat stream conversion with state management and terminal handling 2026-07-27 20:17:20 +08:00
CaIon f3ab2cff36 feat: enhance GitCode release workflow to handle bootstrap and matrix assets 2026-07-27 18:24:43 +08:00
CaIon 6d57d250f8 feat: enhance GitCode release workflow with bootstrap asset and asset matrix 2026-07-27 18:20:01 +08:00
CaIon 2ec6171faa fix: replace ASCII apostrophes in release notes to prevent script breakage 2026-07-27 17:17:01 +08:00
CaIon 8a7a49072a feat: add workflow to sync GitHub releases to GitCode 2026-07-27 17:09:27 +08:00
CaIon 8aa5e754a8 refactor: rename trusted_proxies package to middleware and update function calls 2026-07-27 16:48:23 +08:00
CaIon b8bb3f40ac refactor: update import paths to use new types package 2026-07-27 16:45:02 +08:00
CaIon 60a1acb703 refactor: update import paths to use relaykit module 2026-07-27 16:00:25 +08:00
Calcium-Ion 86ac0f7745 refactor: extract protocol conversion layer into standalone relaykit module (#6369)
* 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
2026-07-27 15:56:21 +08:00
CaIon f51dd4d808 fix: allow Advanced Custom Responses Compact
close #6461
2026-07-27 15:21:30 +08:00
CaIon 398cdafecf feat: add New API channel support 2026-07-27 15:20:19 +08:00
CaIon bc14c18f60 refactor: update task refund logic and remove legacy handling 2026-07-26 20:47:52 +08:00
CaIon 2d23cdf291 feat: configurable tool pricing, Sub2API channel, and alpha search billing
Add admin-configurable tool-call prices with cross-provider surcharge
settlement, Sub2API channel support, /v1/alpha/search relay, and usage-log
surcharge UI.
2026-07-26 20:05:15 +08:00
feitianbubu 3e1e728279 perf(web): debounce users page search input (#6474) 2026-07-26 14:46:19 +08:00
feitianbubu ab65d2582f fix: allow topup amount input to be fully cleared (#6473) 2026-07-26 14:46:05 +08:00
feitianbubu 08f88d25e5 feat: support Tencent TokenHub API key via OpenAI-compatible protocol (#6232)
* feat: support tencent tokenhub api key via openai-compatible protocol

* fix: use tokenhub base url for tencent api key channels

* test: cover tencent key-format dispatch and add TokenHub key prompt locales
2026-07-25 22:05:09 +08:00
feitianbubu 8b41defbe0 feat: add gemini-3-pro-image and gemini-3.1-flash-image GA models (#6371) 2026-07-25 20:28:08 +08:00
CaIon ae17f2749d fix(json-code-editor): remove opaque line-number layer background hiding editor content
The line-number layer spans the full editor, so giving it an opaque
background and raised z-index covered the highlighted content. Reverts
the gutter background added in 88868002f; the horizontal-scroll
gutter overlap it targeted returns as a known cosmetic issue.
2026-07-25 19:23:18 +08:00
CaIon 5ede832d80 chore(README): update AtomGit badge and remove Product Hunt badge 2026-07-25 19:17:47 +08:00
CaIon 257223be26 chore(README): update AtomGit badge and remove Product Hunt badge 2026-07-25 19:17:43 +08:00
QuentinHsu eb4a1bd193 perf(json-editor): unify admin JSON editing experience (#6421)
* perf(json-editor): improve JSON editing experience

- integrate Yace for syntax highlighting, history, indentation, auto-closing, and smart line breaks.
- add copy support, cursor location feedback, and synchronized content and line-number scrolling.
- extract JSON editor utilities and cover key interactions with unit tests.

* perf(system-settings): improve JSON configuration editing

- replace raw JSON textareas with the shared editor for highlighting, validation, copy, and formatting.
- preserve field-specific examples and make placeholders visible through the transparent editor layer.
- remove duplicate formatting controls while keeping existing form validation and save behavior.

* perf(json-editor): standardize JSON inputs across admin settings

- replace pure JSON textareas with the shared editor across system settings and channel workflows.
- preserve form focus, validation, placeholders, and visual or JSON editing modes.
- add happy-dom component coverage for form bindings, controlled updates, and formatting.

* fix(json-code-editor): address accessibility review findings

- Drop the unconditional aria-label that overrode every field's
  label-derived accessible name; add an optional ariaLabel prop and
  set it at call sites without an associated label
- Associate standalone Labels via htmlFor/id in channel-affinity views
- Hide the highlight mirror and line-number layers from the
  accessibility tree (aria-hidden)
- Give the line-number gutter an opaque background so horizontally
  scrolled code no longer slides under it
- Degrade to no scroll sync instead of destroying the editor when the
  line-number layer is not found
2026-07-25 19:10:28 +08:00
CaIon 18b0b7631a refactor: rename channel priority update to channel field update 2026-07-25 16:59:05 +08:00
RedwindA a0d0e5049e fix(web/channel): stabilize inline priority updates (#6415)
* fix(channel): debounce inline priority updates

* fix(channel): commit spinner edits only on Enter or focus leave

Blurring the inline edit input to the +/- buttons flushed the pending
priority update immediately, bypassing the container focus-containment
check and defeating the debounce. Commit now happens via the container
blur handler or explicitly on Enter. Add unit tests for the priority
update scheduler.

* fix(channel): preserve row identity when priority updates reorder channels
2026-07-25 15:59:59 +08:00
CaIon bf8cfcc512 fix(model-mutate-drawer): prevent form reset on modelSettings refetch 2026-07-25 14:51:23 +08:00
feitianbubu 27235a277a fix: prevent model create from wiping existing pricing for same name (#6365)
* fix: prevent model create from wiping existing pricing for same name

* fix(models): keep create from wiping pricing for any existing name

Prefilling from the drawer's open-time model name only covered the
missing-models entry point. Submit deletes the pricing entries for the
name in the form, which is editable and starts empty from the toolbar
"Create model" button, so both a hand-typed existing name and a renamed
prefill still dropped the configured pricing.

Track the name whose pricing was actually read into the form and scope
the delete-then-readd to it, or to a name the user explicitly priced.
Editing still clears pricing by emptying the fields, a prefilled create
does too, and a name the form never loaded is left alone -- which also
stops an edit that renames onto an existing name from destroying that
name's pricing.

Read the prefill through one shared readPricingConfig instead of
duplicating the seven-map parse in both branches, and open the advanced
section for ratios that are configured as 0 rather than only truthy ones.
2026-07-25 14:15:48 +08:00
bigsong 84a79b6807 fix: log response body when parsed upstream error message is empty
When an upstream error response parses as valid JSON but yields no usable
error message (e.g. an aggregator gateway returning {"error":{"message":""}}),
RelayErrorHandler previously produced a bare "bad response status code N"
error with no trace of the original body, making the failure undiagnosable.
Log the body preview in that case, mirroring the existing behavior for
unparseable bodies.
2026-07-24 14:10:32 +08:00
Seefs cbd9b30aa4 fix(github): restore issue form visibility (#6454) 2026-07-24 13:53:56 +08:00
Seefs cb96ab0208 chore(github): migrate issue templates to required forms (#6452) 2026-07-24 13:46:54 +08:00
CaIon 1721144221 fix(auth): keep login state on rate-limited or failing token refresh
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
2026-07-21 12:39:29 +08:00
feitianbubuandCaIon e0d5156115 fix: prevent duplicate suno task refunds via cas status update (#6074)
* fix: prevent duplicate suno task refunds via cas status update

* fix: reconcile failed task refunds

---------

Co-authored-by: CaIon <i@caion.me>
2026-07-20 22:03:13 +08:00
QuentinHsu 4aa08f917e fix(playground): resolve auto group model listing (#6163)
* 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
2026-07-20 18:21:24 +08:00
yyhhyyyyyy e13d4033e5 fix(channel): improve proxy client compatibility and cache lifecycle (#6157)
* fix(channel): improve proxy client compatibility and cache lifecycle

* test(controller): use non-fatal assertions for channel tests
2026-07-20 18:11:22 +08:00
RedwindA 08677566f8 fix(web): show used quota for unlimited API keys (#6224) 2026-07-20 18:08:53 +08:00
QuentinHsu 270accc322 perf(data-table): optimize action column width allocation (#6135)
- apply a minimum width hint to content-sized columns to prevent wasted space.
- preserve remaining table width allocation across regular data columns.
2026-07-20 18:04:05 +08:00
QuentinHsu 2ef4cfff9c fix(playground): prevent model group option stretching (#6120)
* fix(playground): prevent model group option stretching

- keep group options at a fixed 2rem height and align them to the top.
- organize layout code in a dedicated module and cover layout and scrolling behavior.

* docs(web): strengthen frontend testing requirements

- require regression coverage for behavior changes, bug fixes, and UI states.
- define module-scoped test organization, stable assertions, mocks, and verification rules.
2026-07-20 18:03:49 +08:00
feitianbubu 16bfae1750 fix: drop realtime beta header for ga models and register new ones (#6032) 2026-07-20 17:48:09 +08:00
CaIon d0e23e1e0f chore: include frontend in language stats 2026-07-20 16:53:08 +08:00
Calcium-Ion 31d70fca39 refactor(auth): replace dashboard sessions with stateless tokens and session control (#6329)
* refactor(auth): replace dashboard sessions with stateless tokens

* feat(auth): harden session issuance and distributed enforcement

* fix(proxy): preserve trusted proxy compatibility defaults

* refactor: address dashboard auth review feedback

* refactor: remove classic frontend and flatten web app
2026-07-20 16:48:43 +08:00
CaIon 5a6c53d496 feat: standardize OpenAI Models label usage across components 2026-07-18 15:44:48 +08:00
SeefsandCaIon a6cf42c0f1 feat: support upstream model fetch for advanced custom channels (#5971)
* 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>
2026-07-18 13:39:53 +08:00
Seefs 57746fc972 feat(channel): support Codex upstream model discovery (#6184)
* 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.
2026-07-18 13:04:16 +08:00