2625 Commits
Author SHA1 Message Date
jimmyleocn 37d23dcc86 fix(profile): honor global sidebar visibility (#7429)
* fix(profile): honor global sidebar visibility

* fix(profile): wait for sidebar status
2026-10-30 18:15:09 +08:00
Seefs 77436271f4 fix(deps): upgrade DOMPurify to 3.4.17 (#8116)
Upgrade the direct dependency and override to address GHSA-cg2g-xh64-v4q7.

Regenerate bun.lock with Bun and update the third-party license inventory.
2026-10-30 17:39:39 +08:00
CaIon 883eeb87d8 feat(plugins): warn about task models a plugin cannot charge
A plugin change can leave a task model without a usable price: no price
is set, the price uses usage the plugin no longer provides, or the
plugin no longer offers the model. The gateway now lists these models.
The list follows the plugins currently serving, so a gateway update
that changes a built-in plugin shows up too.

- Uploading, installing from the marketplace, activating or enabling a
  plugin, or deleting its active version, lists the models it cannot
  charge in the upload dialog or in the notice after the action.
- Model pricing marks each of them "Price needs attention" with the
  reason, and a "Price status" filter lists them. A plugin model that
  was never priced now appears in the table too. The badge replaces
  "Task pricing not configured".
- The sidebar shows how many models need attention on System Settings,
  Billing & Payment and Model Pricing, for super administrators.
- GET /api/option/model_pricing/issues returns the list. It is root
  only; access tokens need the option:read scope.
- Prices kept for a switched-off plugin are not reported. They apply
  again when the plugin is switched back on.
2026-10-30 17:34:37 +08:00
dependabot[bot] 1e8c707aca chore(deps): bump @codemirror/language from 6.12.4 to 6.13.1 in /web (#8102)
Bumps [@codemirror/language](https://github.com/codemirror/language) from 6.12.4 to 6.13.1.
- [Changelog](https://github.com/codemirror/language/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codemirror/language/commits)

---
updated-dependencies:
- dependency-name: "@codemirror/language"
  dependency-version: 6.13.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-30 17:30:07 +08:00
dependabot[bot] 6e78cb3288 chore(deps): bump marked from 18.0.6 to 18.1.2 in /web (#8103)
Bumps [marked](https://github.com/markedjs/marked) from 18.0.6 to 18.1.2.
- [Release notes](https://github.com/markedjs/marked/releases)
- [Commits](https://github.com/markedjs/marked/compare/v18.0.6...v18.1.2)

---
updated-dependencies:
- dependency-name: marked
  dependency-version: 18.1.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-30 17:29:51 +08:00
dependabot[bot] 9fc70bb834 chore(deps-dev): bump @tanstack/react-query-devtools in /web (#8104)
Bumps [@tanstack/react-query-devtools](https://github.com/TanStack/query/tree/HEAD/packages/react-query-devtools) from 5.101.2 to 5.105.0.
- [Release notes](https://github.com/TanStack/query/releases)
- [Changelog](https://github.com/TanStack/query/blob/main/packages/react-query-devtools/CHANGELOG.md)
- [Commits](https://github.com/TanStack/query/commits/@tanstack/react-query-devtools@5.105.0/packages/react-query-devtools)

---
updated-dependencies:
- dependency-name: "@tanstack/react-query-devtools"
  dependency-version: 5.105.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-30 17:29:36 +08:00
dependabot[bot] cef78205e8 chore(deps-dev): bump knip from 6.27.0 to 6.43.0 in /web (#8105)
Bumps [knip](https://github.com/webpro-nl/knip/tree/HEAD/packages/knip) from 6.27.0 to 6.43.0.
- [Release notes](https://github.com/webpro-nl/knip/releases)
- [Commits](https://github.com/webpro-nl/knip/commits/knip@6.43.0/packages/knip)

---
updated-dependencies:
- dependency-name: knip
  dependency-version: 6.43.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-30 17:29:22 +08:00
dependabot[bot] 1695171fa2 chore(deps): bump tailwind-merge from 3.6.0 to 3.7.0 in /web (#8106)
Bumps [tailwind-merge](https://github.com/dcastil/tailwind-merge/tree/HEAD/packages/tailwind-merge) from 3.6.0 to 3.7.0.
- [Release notes](https://github.com/dcastil/tailwind-merge/releases)
- [Commits](https://github.com/dcastil/tailwind-merge/commits/tailwind-merge@3.7.0/packages/tailwind-merge)

---
updated-dependencies:
- dependency-name: tailwind-merge
  dependency-version: 3.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-30 17:29:04 +08:00
undercat a3851c29e1 fix: save Turnstile keys before enabling (#7960) 2026-10-30 17:11:25 +08:00
feitianbubu 829f0828a5 fix: unmount authenticated layout on sign-out to stop credential-less refetches (#8110) 2026-10-30 14:56:56 +08:00
RedwindA 9eda50a32f Merge commit from fork
Upgrade @visactor/vchart and @visactor/react-vchart to 2.1.7. Since 2.1.6
the DOM tooltip renders the title as text (VisActor/VChart#4640).
2026-10-30 14:28:03 +08:00
Seefs 26c488c447 fix(relay): allow Azure channels to opt in to Responses WebSocket (#8047) (#8075)
Azure channels with responses_websocket_enabled were rejected by
FilterResponsesWebSocket, and the channel form hid the toggle for type 3.
The OpenAI adaptor already builds the Azure /openai/v1/responses URL with
api-version and sets the api-key header, and DoWssRequest reuses both, so
no relay URL change is needed.
2026-10-28 15:22:48 +08:00
Seefs f1569d1ea7 fix(pricing): classify dynamic per-request billing correctly (#8010)
* fix(pricing): classify dynamic per-request billing correctly

* fix(pricing): classify mixed billing as token-based
2026-10-25 20:41:57 +08:00
dependabot[bot]andCaIon e835b1bfc4 chore(deps): bump axios from 1.18.1 to 1.20.0 in /web (#7835)
Bumps [axios](https://github.com/axios/axios) from 1.18.1 to 1.20.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.18.1...v1.20.0)

---
updated-dependencies:
- dependency-name: axios
  dependency-version: 1.20.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: CaIon <i@caion.me>
2026-10-24 23:10:05 +08:00
dependabot[bot] 5c8032d700 chore(deps): bump react-i18next from 17.0.10 to 17.1.0 in /web (#7981)
Bumps [react-i18next](https://github.com/i18next/react-i18next) from 17.0.10 to 17.1.0.
- [Changelog](https://github.com/i18next/react-i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/react-i18next/compare/v17.0.10...v17.1.0)

---
updated-dependencies:
- dependency-name: react-i18next
  dependency-version: 17.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-24 22:49:15 +08:00
dependabot[bot] 0b667ca478 chore(deps): bump i18next from 26.3.6 to 26.5.3 in /web (#7979)
Bumps [i18next](https://github.com/i18next/i18next) from 26.3.6 to 26.5.3.
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v26.3.6...v26.5.3)

---
updated-dependencies:
- dependency-name: i18next
  dependency-version: 26.5.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-24 22:49:08 +08:00
dependabot[bot] 4105bd089c chore(deps): bump input-otp from 1.4.2 to 1.5.0 in /web (#7980)
Bumps [input-otp](https://github.com/guilhermerodz/input-otp/tree/HEAD/packages/input-otp) from 1.4.2 to 1.5.0.
- [Release notes](https://github.com/guilhermerodz/input-otp/releases)
- [Changelog](https://github.com/guilhermerodz/input-otp/blob/master/CHANGELOG.md)
- [Commits](https://github.com/guilhermerodz/input-otp/commits/v1.5.0/packages/input-otp)

---
updated-dependencies:
- dependency-name: input-otp
  dependency-version: 1.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-24 22:49:01 +08:00
dependabot[bot] b6b85cae59 chore(deps): bump react-resizable-panels from 4.12.2 to 4.14.6 in /web (#7982)
Bumps [react-resizable-panels](https://github.com/bvaughn/react-resizable-panels) from 4.12.2 to 4.14.6.
- [Release notes](https://github.com/bvaughn/react-resizable-panels/releases)
- [Changelog](https://github.com/bvaughn/react-resizable-panels/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bvaughn/react-resizable-panels/compare/4.12.2...4.14.6)

---
updated-dependencies:
- dependency-name: react-resizable-panels
  dependency-version: 4.14.6
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-24 22:48:53 +08:00
CaIon a404460413 chore(web): upgrade Bun to 1.4.4 and use bun check 2026-10-24 21:07:03 +08:00
Seefs 33c61a2423 fix: prevent stale values when switching edit drawer records (#7989) 2026-10-23 14:31:23 +08:00
Seefs 7fb6e57a5f fix(channels): preserve advanced custom body passthrough settings (#7971) 2026-10-23 00:23:08 +08:00
Calcium-Ion e9d4d6353c feat(billing): bill OpenAI 12-hour prompt cache writes at their own price (#7965)
OpenAI added a 12-hour prompt cache to the Responses API on 2026-10-20
(prompt_cache_options.ttl "12h", GPT-5.6 and later). A 12-hour write
costs 2.5x the input price, twice the 30-minute write. We already
forwarded the option but billed every cache write at the 30-minute price.

- Read cache_write_tokens_details from Responses usage and keep the split
  through streaming, compaction and format conversion.
- Ratio pricing bills 12-hour writes at twice the cache write ratio, the
  same way Claude 1-hour writes use 6/3.75.
- Expressions get a cc12h price. When an expression leaves the long-lived
  price out, 12-hour writes cost twice the cc price and Claude 1-hour
  writes 6/3.75 times it; without a cc price they bill as input. Claude
  cache writes are no longer free when an expression omits cc or cc1h.
- gpt-6-astra prices 12-hour writes at $25 ($50 above 272K tokens).
- GPT models with a cache write ratio convert to expressions with cc12h.
- Chat Completions forwards prompt_cache_options.
- The pricing editor, cost estimator, pricing pages and usage log details
  show the 12-hour price and tokens.
2026-10-22 22:41:17 +08:00
CaIon d8e65613c0 feat(web): copy model names from usage log details
The request, upstream and response model rows in a usage log's response
details now each have a copy button.
2026-10-22 16:23:19 +08:00
CaIon 8802113263 feat(task): let ordinary channels compete on shared plugin endpoints
When a task plugin claimed a model on a shared host endpoint
(/v1/images/generations, /v1/images/edits, /v1/responses, /v1/videos),
every request for that model went to the plugin, even when an ordinary
OpenAI-compatible channel served the model too. Ordinary channels and
the matching plugin channels now compete for the request under the usual
group, priority, weight, affinity and channel-pin rules. When an
ordinary channel wins, the original request reaches the ordinary relay
unchanged: no plugin decoder, mode check or model rewrite runs, and
retries stay on ordinary channels. When a plugin channel wins, the
plugin handles the request as before and retries stay on its accepted
plugin candidates. Native plugin routes still belong to their plugins.

Ordinary and plugin prices are kept apart. Task expressions return USD,
while ordinary expressions keep their USD-per-million result, so an
ordinary request now fails with 400 model_price_error before any quota
is reserved when the model's expression reads task usage (u()) or is
still inherited by a task plugin on that endpoint. The model pricing
editor can set ordinary OpenAI prices, per returned image with
fixed(...) * image_count, while each plugin keeps its price in its own
override. A model served by a single plugin now shows that plugin's
pricing editor as well.
2026-10-22 16:23:19 +08:00
CaIon eb169e74d7 feat(pricing): adjust synced upstream prices by the site exchange rate
Upstream price sync saved an upstream's price as it was, so a price
quoted in another currency had to be corrected by hand afterwards. Each
selected model now has a price adjustment: keep the source price, or
divide or multiply it by the site exchange rate. "Set selected prices"
applies one choice to every selected model. Fixed prices, ratios and the
prices inside billing expressions are adjusted; an expression that
cannot be adjusted automatically has to keep its source price or be
edited by hand. The confirmation dialog shows the adjustment, the final
saved price and the price in the site currency, with the exchange rate
in use.

"Show models with matching prices" also lists upstream prices that
already match the local ones, so they can be selected and adjusted too.
2026-10-22 16:23:19 +08:00
CaIon e2321a5a9f chore(web): sort locale keys
Order the keys of every web locale file the way localeCompare sorts them,
with numeric keys first as JSON objects keep them. No key or translation
is added, removed or changed.
2026-10-22 16:23:18 +08:00
dependabot[bot] 4d36f2c524 chore(deps-dev): bump vitest from 4.1.10 to 5.0.4 in /web (#7838)
Bumps [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) from 4.1.10 to 5.0.4.
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v5.0.4/packages/vitest)

---
updated-dependencies:
- dependency-name: vitest
  dependency-version: 5.0.4
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-22 00:08:51 +08:00
Seefs 603a5ceb55 feat(dashboard): show cache usage alongside total tokens (#7773)
* feat(dashboard): show cache usage alongside total tokens

* fix(dashboard): align cache stat descriptions and fix typecheck
2026-10-20 15:42:31 +08:00
邹云森森andCaIon 32e587406c feat(email): 添加 resend 邮件服务商接口 (#7880)
* feat(email): add Resend delivery provider

Add Resend as an alternative to SMTP with separately editable sender address
and name, credential-safe configuration status, and validation before activation.
Preserve the target repository's email notification and balance reminder settings.
Only Resend changes are transplanted from hicoderai/new-api; no landing,
legal-document, model-group, pricing, branding, or dependency changes are included.

Validation: Go common/controller email regression tests; 19 frontend email and
notification tests; frontend production build; tsgo typecheck; touched-file lint.
Frontend validation uses the target lockfile's Axios 1.18.1 with local cached tools.

Security references: OWASP Authentication, Session Management, and Forgot Password
Cheat Sheets. Tests cover credential non-disclosure, invalid activation, sanitized
transport errors, and no automatic retry or fallback; token and session flows
are unchanged.
https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html
https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html
https://cheatsheetseries.owasp.org/cheatsheets/Forgot_Password_Cheat_Sheet.html

* fix(email): log Resend rejections and translate Resend errors

Resend's reason for a rejected or failed send now goes to the server log.
People who asked for the email still see the short error.
Resend and email method errors are translatable messages in all seven
languages.
The email settings hints are shorter and reuse the existing key hint.
The new frontend files carry the license header, the sender name check
passes lint, and test fixtures use neutral names.

* fix(email): check Resend settings while Resend is active

Saving the sender address or API key now checks the whole Resend setup
while Resend sends the mail. A typo the form accepts, such as
notify..team@example.com, is rejected instead of breaking every send.
Resend's error text and network errors are quoted in the server log.

---------

Co-authored-by: CaIon <i@caion.me>
2026-10-19 20:22:37 +08:00
Calcium-Ion 6cf0d90b5f feat(deepseek): support V4.1 Flash, the Search and Fetch APIs, and @ reasoning modifiers (#7867)
* fix(model): find channels for @-modified model names without the memory cache

With the channel memory cache off (no Redis and MEMORY_CACHE_ENABLED
unset), channel selection matched abilities by the exact requested name,
so a name such as deepseek-flash@effort:max found no channel. Retry with
the routing name when the exact name has no channel, as the cached path
already does.

* feat(deepseek): support V4.1 Flash, the Search and Fetch APIs, and @ reasoning modifiers

Follows the DeepSeek API update of 2026-10-17.

- Default models: deepseek-flash and deepseek-v4-pro, each with -none,
  -low and -max, plus deepseek-search and deepseek-fetch. The retired
  deepseek-chat, deepseek-reasoner and deepseek-v4-flash names are no
  longer listed.
- Thinking: the -none/-low/-max tails also work on deepseek-flash.
  @thinking and @effort now reach DeepSeek's own fields on Chat
  (thinking, reasoning_effort), Anthropic (thinking, output_config.effort)
  and Responses (reasoning.effort), and take precedence over the tails.
- Built-in prices: peak/off-peak expressions for deepseek-flash (also the
  deepseek-v4-flash aliases) and deepseek-v4-pro, and $0.75 per 1,000
  requests for deepseek-search and deepseek-fetch.
- Server-side search: searches and page fetches DeepSeek runs for Claude
  Code and Codex bill at $0.75 per 1,000 under deepseek_search and
  deepseek_fetch, whatever model name the client sent. Searches whose
  results already arrived stay billed when a stream ends before its final
  usage; this also applies to Alibaba's Anthropic endpoint.
- New endpoints POST /v1/tools/search and /v1/tools/fetch relay the
  DeepSeek APIs like /v1/alpha/search. A call is charged only when
  DeepSeek returns results or page content.

* fix(deepseek): price /v1/tools/search and /v1/tools/fetch by endpoint

A model named in the request body chose the billing model, so a body such
as {"query":"...","model":"deepseek-flash"} was priced as a chat model with
no tokens and the search or fetch cost nothing. Both endpoints now always
use their routing name, deepseek-search or deepseek-fetch. DeepSeek ignores
the body field, so the body is still forwarded unchanged.

* fix(deepseek): bill Claude-format page fetches at the DeepSeek Fetch price

usage.server_tool_use.web_fetch_requests always went to the web_fetch
tool price, which has no built-in value, while only searches used the
DeepSeek key. A channel can now name its own fetch key next to the search
key, and DeepSeek channels bill reported fetches under deepseek_fetch. A
channel retry clears it like the search key.
2026-10-17 23:24:33 +08:00
Calcium-Ion 6461f084ff feat(notify): turn each kind of notification on or off (#7868)
SMTP settings now only decide whether mail can be sent. Verification
codes, password reset, email binding and account security mails depend
on SMTP alone, and no notification switch affects them.

Admins get a site-wide low balance reminder switch, on by default, next
to the SMTP settings. The default threshold is entered as an amount.

Users choose which notifications they receive. Low balance reminders are
on for everyone by default. Admins can also turn channel notifications
and upstream model update notices on or off. The root user receives
channel notifications until it turns them off. Other admins receive them
after they turn them on.

A low balance reminder is sent once, when a charge takes the balance
below the threshold. A top-up above the threshold arms it again.

Channel notifications reach every admin who has them on, in that admin's
language. Email binding codes and account security mails follow the
account's language.

Saving notification settings no longer clears the language, the sidebar
layout or the billing preference.

Existing settings keep their behavior, and old clients that do not send
the new fields keep the stored switches. Webhook, Bark and Gotify
payloads are unchanged.
2026-10-17 22:17:59 +08:00
CaIon 5c31c1fa9e feat(channels): improve priority dragging and add onboarding guides
Keep table drop targets stable, use compact previews, and prevent
accidental mode switches and leftover row transforms.

Add first-use guides for card and table views with automatic playback,
pause and replay controls, and translations for all seven locales.
2026-10-17 21:52:39 +08:00
CaIon 5e9595190e feat(channels): add drag mode for channel priority ordering
Support priority ordering in table and card views with automatic priority calculation, same-tier and between-tier drop targets, live previews, conflict detection, and undo.

Keep drag mode off by default and place its toggle before Batch Operations. Consolidate sorting controls and preserve the shared visibility and view controls.
2026-10-17 20:19:41 +08:00
CaIon 5a59d69153 fix(pricing): hide task prices left at zero when another price is set
A task plugin can offer two billing modes, such as per task for some
models and per second for others. An administrator who prices a model
per second leaves its per-task price at zero. The model card, the list
view and the detail page then showed that unused zero price next to
the real one, and it read as a free item.

A usage price that is zero in every tier is now hidden when another
usage price is set. A model priced at zero throughout still shows its
zero prices. The card also drops the tier name when a model has a
single tier, since that name was always the editor's default "base".
2026-10-17 20:19:40 +08:00
RedwindA b0a98ac49c fix(web): apply theme class before first paint so Dark Reader detects dark mode (#7571)
Dark Reader checks html.dark / color-scheme only once during page load,
but the theme class was added by ThemeProvider after React mounted.
Resolve the saved theme in an inline head script and declare
color-scheme: dark on .dark.
2026-10-17 14:03:48 +08:00
xuu1998andxuu1998 f92c576506 fix(web): cover Cloudflare clef and NVIDIA model families in provider rules (#7840)
The usage-log model badge resolves its icon from MODEL_PROVIDER_RULES by model
name only. clef (Cloudflare) and the NVIDIA families without an nvidia prefix
(nv-embed, nv-rerank, riva-, parakeet-, canary-, nemoretriever) matched no rule
and fell back to the plain dot.

Co-authored-by: xuu1998 <xuu1998@users.noreply.github.com>
2026-10-17 13:07:41 +08:00
CaIon d032204733 feat(aws): add Mantle Messages API support
Add an opt-in Mantle interface with top-level cache_control, API key and
SigV4 authentication, and native Claude response handling. Keep InvokeModel
as the default for existing AWS channels.

Strip hop-by-hop headers before signing and map the dated Haiku alias to
Mantle's model ID. Cover signatures over HTTP/1.1 and HTTP/2, cache usage,
legacy routing, and channel configuration with regression tests.

Refs #4791
2026-10-16 14:45:17 +08:00
RedwindA 6549a17eda fix(dashboard): draw flow chart labels in the theme text color (#7821)
The Sankey labels were hard-coded to #475569, which is nearly invisible
on the dark theme. Read the app's --foreground token at runtime instead,
so labels and the active node outline match the surrounding text in
light/dark mode and every theme preset, and follow preset switches live.
2026-10-15 18:00:20 +08:00
Seefs c9179d38b7 fix(playground): support the reasoning field in chat responses (#7831) 2026-10-15 17:59:00 +08:00
CaIon 908f94d65d fix(web): hide pages the user cannot open from console search
The search box in the console header listed every page, so regular
users saw the admin pages and only found out on click that they had
no access. It now offers the same pages as the sidebar, which already
filters them by role and by the sidebar settings.

The layout now renders the search dialog instead of the search
provider, which removes the import cycle between the two.
2026-10-15 17:57:30 +08:00
CaIon f196934ce6 feat(plugins): bind Hailuo, Vidu and Veo plugins to New API channels
The hailuo, vidu, google and vertex-ai plugins now declare the new_api
upstream, so a New API (type 60) channel can bind them, and each serves its
vendor wire format on prefixed native routes that a downstream gateway
running the same plugin addresses:

- hailuo: /hailuo/v1/video_generation and /hailuo/v2/video_generation, with
  path-parameter queries. Through a gateway, v1 videos download from the
  upstream's task artifact, since only the upstream can resolve the MiniMax
  file link.
- vidu: /vidu/ent/v2/{text2video,img2video,start-end2video,reference2video}
  and the creations query; the route names the action, so one or two
  reference images stay a reference request.
- google: models/{model}:predictLongRunning and operation polling. The
  operation is renamed after the gateway task, and videos download from the
  upstream's task artifact, since the Gemini file needs the upstream key.
- vertex-ai: one dynamic route for predictLongRunning and
  fetchPredictOperation. Operation names echo the caller's project and
  location and never carry the upstream project.

Status presenters render a task that is not polled yet as pending and a
task the poller failed while its snapshot was still running as failed, so
the downstream gateway reads the upstream state and settles on the same
usage.

Versions: hailuo 1.3.0; vidu, google and vertex-ai 1.1.0.
2026-10-14 23:20:54 +08:00
feitianbubu c9f7b62081 fix(web): sort pricing models by input, output and per-request price (#7813) 2026-10-14 21:36:19 +08:00
枭钰钰 a0bf6a8a41 fix(vertex): pass project_id in API Key mode to avoid 404 on official endpoints (#6330)
* fix(vertex): pass project_id in API Key mode to avoid 404 on official endpoints

Closes #6250.

Vertex AI channel in vertex_key_type=api_key mode: getRequestUrl passed
an empty string as project_id to BuildGoogleModelURL /
BuildAnthropicModelURL, leaving the URL without the
/projects/{PROJECT_ID}/locations/{REGION}/ segment, so the official
Vertex endpoints returned 404.

In JSON mode project_id is parsed from the service account, so the bug
is specific to api_key mode.

Fix:
- Add VertexProjectID to ChannelOtherSettings (used only in api_key
  mode; JSON mode keeps parsing from the service account, unchanged).
- In adaptor.go's api_key branch, use ChannelOtherSettings.VertexProjectID
  instead of the hardcoded empty string. When unset, fall back to the
  legacy behavior so existing api_key channels are not broken.
- Frontend (web/default): show a Project ID input when
  VertexKeyType=api_key, persist settings.vertex_project_id, and require
  it via superRefine so users cannot save an api_key channel that would
  still 404. Clear the residual field in non-api_key mode or non-Vertex
  channels.
- Add translations across 7 locales (en/zh/zh-TW/ja/fr/ru/vi).

Regression tests (relay/channel/vertex/adaptor_api_key_url_test.go)
cover 4 scenarios:
- api_key mode + configured project_id -> URL contains /projects/.../locations/
- api_key mode + stream suffix -> key joined with &, path contains project_id
- api_key mode + Claude mode -> anthropic publisher path
- api_key mode + empty project_id -> falls back to legacy behavior

* fix(vertex): make the API Key project ID optional

Express-mode API keys are documented without a project, so a required
project ID would block saving those channels. Without one the URL keeps
the express-mode form as before; with one, the URL carries the project
and the deployment region, so a global region is honored.

- Drop the required check and describe the field in plain words.
- Treat vertex_project_id as a sensitive field, like the key format.
- Assert exact request URLs in a table test, including the global case.
- Cover saving, clearing and loading the project ID in the channel form.
2026-10-14 20:16:30 +08:00
CaIon 7de10f2c60 feat(token): let an API key read its owner's quota
Add a per-token "Allow querying user quota" switch. When it is on,
GET /api/usage/token/ also returns user_quota with the account's
remaining and used quota in quota units. New tokens start with the
switch on: the console form, POST /api/token/ without the field, and the
default token created at registration. Tokens created before this change
stay off. PUT /api/token/ keeps the stored value when the field is
absent, and the token audit lists the field when it changes.

The key usage and key log queries now check the key's IP whitelist the
same way API requests do, and answer 403 from an address outside it.
Expired and exhausted keys can still use both queries.

New API channels now query their balance from the upstream's
/api/usage/token/ with the channel key. When the upstream also returns
the owner's quota, the smaller of the key's and the owner's remaining
quota is the balance, and an unlimited key uses the owner's quota alone.
Without it, a limited key reports its own remaining quota, and an
unlimited key asks for the switch to be turned on upstream. Quota
converts to USD with the upstream's quota_per_unit from /api/status.

Refs #3122
Refs #6828
2026-10-13 21:39:52 +08:00
Seefs b4be2a7847 feat(ui): show newly added pricing groups at the top (#7782) 2026-10-13 12:35:05 +08:00
Calcium-Ion 633b4c5b19 feat(logs): export usage logs from the common log page (#7774)
* feat(logs): export usage logs from the common log page

The common log page has an Export button next to Search. It asks for a
time range and downloads the logs of the current view, with the page's
other filters, as a CSV file in the viewer's language. Users export their
own logs; administrators in the all-users view export every user's logs.

Each user runs one export at a time. A second export started while one is
running, from another tab or another node, is refused until the first one
ends. With Redis the reservation holds across nodes and lapses within a
minute if its node stops.

Log Maintenance settings add two options: whether users may export (on by
default) and the longest log time range in days (30 by default). Regular
users can search their logs within that range at once, and every export
is limited to it. A user's log search had no limit before.

* fix(web): split the log maintenance page into four modules

The log maintenance page ran its settings, the history log cleanup and
the server log files together. It now shows four modules, each under its
own heading and separated by a divider, like the performance page: log
recording, log search and export, history log cleanup, and server log
management. The history log cleanup no longer sits in a box of its own.

The history log cleanup and the server log files are now components of
their own; what they do is unchanged.

* feat(logs): default the log time range to 365 days and apply it to the dashboard

The longest log time range now defaults to 365 days instead of 30.
Regular users had no limit on log searches before this setting, and 30
days could not cover a 31-day month.

A user's own usage and traffic charts on the dashboard were held to a
fixed one-month range. They now follow the same setting, so the
dashboard, the log search and the export share one limit, and a range
that is too long gets the same "cannot exceed N days" message.
2026-10-12 21:33:53 +08:00
dependabot[bot] 9f048107ed chore(deps): bump ai from 7.0.31 to 7.0.136 in /web (#7767)
Bumps [ai](https://github.com/vercel/ai/tree/HEAD/packages/ai) from 7.0.31 to 7.0.136.
- [Release notes](https://github.com/vercel/ai/releases)
- [Changelog](https://github.com/vercel/ai/blob/main/packages/ai/CHANGELOG.md)
- [Commits](https://github.com/vercel/ai/commits/ai@7.0.136/packages/ai)

---
updated-dependencies:
- dependency-name: ai
  dependency-version: 7.0.136
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-12 20:44:18 +08:00
dependabot[bot] bf4e1ebfb8 build(deps-dev): bump oxfmt from 0.57.0 to 0.72.0 in /web (#7766)
Bumps [oxfmt](https://github.com/oxc-project/oxc/tree/HEAD/npm/oxfmt) from 0.57.0 to 0.72.0.
- [Release notes](https://github.com/oxc-project/oxc/releases)
- [Changelog](https://github.com/oxc-project/oxc/blob/main/npm/oxfmt/CHANGELOG.md)
- [Commits](https://github.com/oxc-project/oxc/commits/oxfmt_v0.72.0/npm/oxfmt)

---
updated-dependencies:
- dependency-name: oxfmt
  dependency-version: 0.72.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-12 20:38:31 +08:00
dependabot[bot] 82306b3c35 build(deps-dev): bump @tanstack/router-plugin in /web (#7768)
Bumps [@tanstack/router-plugin](https://github.com/TanStack/router/tree/HEAD/packages/router-plugin) from 1.168.23 to 1.168.42.
- [Release notes](https://github.com/TanStack/router/releases)
- [Changelog](https://github.com/TanStack/router/blob/main/packages/router-plugin/CHANGELOG.md)
- [Commits](https://github.com/TanStack/router/commits/@tanstack/router-plugin@1.168.42/packages/router-plugin)

---
updated-dependencies:
- dependency-name: "@tanstack/router-plugin"
  dependency-version: 1.168.42
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-12 20:38:05 +08:00
dependabot[bot] c730add954 build(deps): bump stream-markdown-parser from 1.1.3 to 1.2.18 in /web (#7769)
Bumps [stream-markdown-parser](https://github.com/Simon-He95/markstream-vue/tree/HEAD/packages/markdown-parser) from 1.1.3 to 1.2.18.
- [Release notes](https://github.com/Simon-He95/markstream-vue/releases)
- [Changelog](https://github.com/Simon-He95/markstream-vue/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Simon-He95/markstream-vue/commits/stream-markdown-parser@1.2.18/packages/markdown-parser)

---
updated-dependencies:
- dependency-name: stream-markdown-parser
  dependency-version: 1.2.18
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-12 20:37:50 +08:00