Commit Graph
2411 Commits
Author SHA1 Message Date
Seefs eab18a8357 fix: record reasoning effort consistently in usage logs (#6641) 2026-08-10 12:48:14 +08:00
Seefs 7dd1000a19 perf(web): debounce server and large-list searches (#6727) 2026-08-10 12:47:55 +08:00
Seefs 5d3423bec1 feat(channels): add auto-disable-only channel test mode (#6728) 2026-08-10 12:47:44 +08:00
Seefs 823e26304a fix(channels): classify Qwen TTS models correctly (#6711) 2026-08-08 14:31:29 +08:00
lihu-001 e926e5cace fix: 修复兑换码额度精度损失 (#6685)
* fix: 修复兑换码额度精度损失(#6680)

* fix(redemption): guard update data integrity
2026-08-07 17:06:32 +08:00
Seefs c9bc038649 feat(channels): refine fetched model categorization (#6632)
* feat(channels): refine fetched model categorization

* fix: channel category

* fix: hy3 category
2026-08-07 13:34:56 +08:00
Calcium-Ion 0ab0202060 Feat/auto group (#6590)
* 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
2026-08-01 23:19:01 +08:00
feitianbubu aa7d0d39a4 style: use text-sm for public header nav links to match other nav components (#6557) 2026-07-31 14:54:23 +08:00
Neimar Avila e78e1db1e4 fix(oauth): stop treating a foreign window.opener as a bind flow (#6425)
* fix(oauth): stop treating a foreign window.opener as a bind flow

The /oauth/:provider callback decided between an account bind and a plain
login with `window.opener ? 'bind' : 'login'`. Any tab opened from an
external link (target="_blank", Slack, mail clients, another site) carries
a live opener, and that opener survives the cross-origin round trip to the
identity provider. Such a login callback was therefore misread as a bind:
it posted a handshake to a window that speaks no such protocol, showed the
"binding your account" screen, and hung until the 30s deadline fired with
"OAuth binding timed out" — while the backend was never called at all.

Reproduced against a real Keycloak round trip: a tab opened via window.open
still reports window.opener !== null on the callback, so mode resolved to
'bind' for an ordinary OIDC login.

A bind now requires positive proof: the popup we open for it is same-origin
(about:blank) before being sent to the provider, so we stamp its own
sessionStorage. The stamp rides through the provider round trip and is
scoped to that popup alone, so a login tab can never carry it. Ambiguity
resolves to 'login', which is the recoverable direction.

Affects every provider sharing this callback (OIDC, GitHub, Discord,
LinuxDO, custom).

* fix(oauth): harden bind popup detection
2026-07-31 14:53:59 +08:00
Seefs 84834eee85 feat(logs): expose stream status to log owners (#6558) 2026-07-31 13:29:07 +08:00
June Chi cb4c8c02f8 feat(oidc): 支持自定义 OIDC 登录显示名称 (#6012)
* 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
2026-07-29 16:27:15 +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 398cdafecf feat: add New API channel support 2026-07-27 15:20:19 +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
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
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
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
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
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
CaIon 923a17ca8a fix: update high-risk status code retry confirmation texts 2026-07-17 21:54:29 +08:00
DawnMoon1542 dc9aeab98b fix(data-table): update table body immediately when toggling columns (#6253)
DataTableRow's React.memo did not depend on columnVisibility.
TanStack row references stay stable when visible columns change, so the
table body did not refresh after View -> Toggle columns until another
action rebuilt the column definitions.

Capture a visible column id signature (visibleColumnIds) outside the
memo and compare it, matching the existing isSelected snapshot pattern.
All tables that use DataTableRow pick up the fix.
2026-07-17 19:38:16 +08:00
DawnMoon1542 506e41c116 fix: add server-side sorting to user list, prevent client-side sort on paged data (#6194)
* 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).
2026-07-17 19:36:44 +08:00
QuentinHsu 9a2d660316 fix(users): prevent large quota values from overflowing (#6134)
- widen the quota column and add consistent spacing between remaining and total values.
- extract quota rendering into a dedicated component and truncate oversized text within the cell.
- preserve full-value tooltips, progress indicators, and the zero-quota state.
2026-07-14 20:15:27 +08:00
feitianbubu 93e936f701 fix: list only channel models in unset price models tab 2026-07-11 23:41:11 +08:00
CaIon bde9b2f448 fix: harden unset price models tab batch copy, feedback, and memo equality
Persist committed editor drafts to the source model during batch copy so
targets never carry pricing the source would lose, surface loading/error
states for the enabled-models query, and compare saved* props in the
visual editor memo so rows leave the unset list reliably after save.
2026-07-11 22:57:22 +08:00
feitianbubu 8283df169e feat: add unset price models tab to model pricing settings (#6124)
* feat: add unset price models tab to model pricing settings

* feat: add unset price models tab translations
2026-07-11 22:48:02 +08:00
CaIon 7a2b9d86e8 feat: enhance model search functionality with status and sync filters 2026-07-11 22:36:09 +08:00
CaIon 92d3c9d18f fix: bound uncached remainder by prompt-max(cached,write) and forward compact prompt_cache_key 2026-07-11 22:18:26 +08:00
CaIon 48068ce923 feat: bill OpenAI cache_write_tokens at cache-creation price with zero clamp
Parse OpenAI's native cache_write_tokens (chat prompt_tokens_details /
responses input_tokens_details), bill it at the cache-creation ratio, and
clamp the uncached prompt remainder at zero since cached + cache-write can
exceed prompt_tokens. Propagate the field through chat/responses/claude
format conversions and tiered expression billing (cc variable).
2026-07-11 21:18:49 +08:00
Calcium-Ion c36418c863 feat: enhance text protocol conversion and advanced custom routing (#5825)
* 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
2026-07-11 20:44:12 +08:00
CaIon 1250fb2eb5 fix: adjust margin for StatusBadge component in logs columns 2026-07-11 20:23:15 +08:00
CaIon e400619656 feat: enhance stale instance handling and update theme colors 2026-07-11 19:37:34 +08:00
CaIon 162f87925c feat: update theme colors 2026-07-11 19:25:04 +08:00
CaIon 6bbddb1046 feat(timing): add timing metrics display for stream logs and enhance localization 2026-07-11 15:32:35 +08:00
CaIon 1b1b23d1d0 revert: restore StatusBadge horizontal padding
Revert 6869cd94b (perf(web): align table badge spacing).
Restores px padding on status badges so usage-log timing/duration
pills are not flush against the edges.
2026-07-11 15:04:12 +08:00
CaIon 337169e0a4 revert: undo t0ng7u UI design-system refactor
Revert the following commits:
- 308e3e347 feat(web): polish themed data views and add task log details
- b2a890e75 fix: Fontsource asset resolution across workspace layouts
- 9d1ca545e refactor(web): refine data-table cards and pricing page layout
- 0918bdb49 refactor(web): consolidate design-system primitives and responsive data views
- 262ab9312 style(web): unify design system across default frontend
2026-07-11 14:51:54 +08:00