Commit Graph

5841 Commits

Author SHA1 Message Date
learner-i ff06067a18 fix: 移除 fcIdx -1 偏移,修复并发工具调用撞键问题 (#5095)
当 Claude 直接以多个 tool_use 块起始(无文本前导,index=0)时,
-1 偏移导致 index=0 和 index=1 同时映射到 fcIdx=0:
- index=0 的工具 args 先流完,发出一次合法调用 ✓
- index=1 的 args 追加到同一 map 槽位,污染后为非法 JSON,该工具丢失 ✗
- index=2 以后的工具各自独占唯一 fcIdx,正常发出 ✓

结果:每轮并发调用中第 2 个工具必然丢失,
模型收不到对应的工具结果后重试剩余工具,
产生雪球效应(10个→9个→8个...逐轮收缩)。

修复:直接使用 Claude 的 block index 作为 fcIdx,不做偏移。
fcIdx 仅作为本地 map 的 key,只需保证唯一性,无需从 0 开始。
2026-05-25 23:13:06 +08:00
CaIon 51ca897cf4 refactor(home): redesign hero section to dual-column layout with compliant copywriting
Redesigns the hero section into a balanced horizontal dual-column layout:
- Left Column: Features title, clean legal-compliant descriptions, CTA buttons with BookOpen Docs link, and enlarged supported apps buttons (Cherry Studio and CC Switch with lobe icons)
- Right Column: Smoothly integrates the terminal API demo with top horizontal alignment
- i18n: Configures compliance translations for en, zh, fr, ja, ru, and vi locales
2026-05-25 23:11:05 +08:00
Seefs 1288028181 fix: truncate oversized upstream error logs (#5083) 2026-05-25 23:10:30 +08:00
真的非她不可 2a528d46cb fix(relay): correct image quality parameter handling (#5103) 2026-05-25 22:57:02 +08:00
t0ng7u 583da45296 refactor(ui): Improve usage log filter responsiveness and mobile UX
Refactor the usage log filter toolbar into a shared reusable component for common, drawing, and task logs. Optimize desktop filters with a responsive grid, move secondary filters into a mobile drawer, standardize filter typography, remove redundant filter icons, and add the missing i18n translations for the new drawer description.
2026-05-25 05:35:44 +08:00
t0ng7u b302be30e3 🛠️ fix: v1 interface feedback regressions
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 '^$'
2026-05-25 02:42:22 +08:00
t0ng7u 88437a1869 ⬆️ chore(deps): Upgrade default frontend dependencies
Upgrade all web/default dependencies to their latest versions and refresh the Bun lockfile. Add dependency overrides for vulnerable transitive packages so bun audit reports no known vulnerabilities.

Update TypeScript configuration for TypeScript 6 by removing deprecated baseUrl usage and explicitly enabling Node types where needed. Adapt the calendar component to react-day-picker v10 by replacing the removed table class key with month_grid.

Validation:
- bun outdated: no outdated dependencies
- bun audit: no vulnerabilities found
- bun run typecheck: passed
- bun run build: passed
2026-05-25 01:06:42 +08:00
t0ng7u b08febaa3c refactor: system settings UI for consistent, compact layouts
Redesign the system settings interface to align with the rest of the console experience by using fixed header actions, removing redundant subtitles, respecting global content width, and standardizing responsive form layouts.

Introduce reusable settings layout primitives for forms, switch rows, grouped controls, nested control sections, title status indicators, and page action portals. Replace duplicated card-style switch markup with explicit compact components, improve nested switch readability, and reduce visual noise across authentication, billing, content, integrations, maintenance, models, and request-limit settings.

Also complete missing i18n translations, remove obsolete subtitle translation keys, refine i18n sync reporting, fix sidebar truncation for long labels, and verify the frontend with type checking and lint diagnostics.
2026-05-25 00:34:26 +08:00
t0ng7u 92a0959448 refactor(web/default): adopt drill-in sidebar pattern for System Settings
Replace the ad-hoc "workspace" abstraction with a focused, URL-driven
"sidebar view" registry that implements the modern Vercel / Cloudflare
drill-in pattern: clicking a top-level entry (e.g. System Settings)
swaps the sidebar to a contextual workspace, with a `← Back to
Dashboard` affordance, instead of stacking sub-navigation in the root.

Architecture
------------
- types.ts
    + SidebarView           — declarative nested view config
                              (id, pathPattern, parent, getNavGroups)
    + SidebarViewParent     — back-navigation descriptor
    + ResolvedSidebarView   — { key, view, navGroups } returned by hook
    + SidebarData           — slimmed to { navGroups } only
    - Workspace             — removed (logo/plan never rendered)

- lib/sidebar-view-registry.ts (new, replaces workspace-registry.ts)
    + SIDEBAR_VIEWS array — single source of truth for nested views
    + resolveSidebarView(pathname)
    + getNavGroupsForPath(pathname, t) — back-compat helper for the
      command palette

- config/system-settings.config.ts
    Refactored to export a single SYSTEM_SETTINGS_VIEW (SidebarView)
    with parent `/dashboard/overview` + label `Back to Dashboard`.

- components/sidebar-view-header.tsx (new)
    Renders only the back affordance (chevron + label). Uses the
    default SidebarMenuButton size so its typography matches the
    nav items below; collapses gracefully into icon mode via the
    existing tooltip behavior. The redundant "title + icon" row was
    removed — workspace context is already carried by the nav groups.

- hooks/use-sidebar-view.ts (new)
    Encapsulates view resolution and root-nav filtering:
      · matched view  → returns its nav groups verbatim (route-level
                        beforeLoad guards already enforce access);
      · no match      → returns root nav groups, narrowed by user
                        role (admin gate) and useSidebarConfig
                        (admin × user sidebar_modules overlay).

- components/app-sidebar.tsx
    Now a thin presentation layer: reads { key, view, navGroups }
    from useSidebarView() and orchestrates the view transition via
    AnimatePresence + MOTION_VARIANTS.sidebarSlide (respects
    prefers-reduced-motion). No logic, no role checks, no path
    matching — those live in the hook.

- components/command-menu.tsx
    Switched to the new getNavGroupsForPath() API; behavior preserved.

Cleanup
-------
- Deleted layout/context/workspace-context.tsx (zero consumers).
- Deleted layout/lib/workspace-registry.ts and its
  workspace-registry.example.ts companion (over-abstracted: name/id
  metadata, isInWorkspace / getAllWorkspaces / WORKSPACE_IDS were
  registered but never read).
- Removed `workspaces` field from useSidebarData (never consumed
  after the top-switcher was dropped).
- Dropped WorkspaceProvider from authenticated-layout.tsx.
- Trimmed dead `Manage and configure` translation key from all six
  locale files and from static-keys.ts.

i18n
----
Added the `Back to Dashboard` key to en, zh, fr, ja, ru, vi, and
registered it in static-keys.ts under "Sidebar views".

Verification
------------
- bun run typecheck: passes
- Lint: no new warnings/errors on the touched files
- Adding a new drill-in workspace now only requires registering a
  SidebarView in SIDEBAR_VIEWS — no changes to AppSidebar required.
2026-05-24 22:09:05 +08:00
Seefs 49bc3a1175 fix(payment): hide classic Waffo Pancake settings (#5085) 2026-05-24 16:37:43 +08:00
Hill-waffo 0354c38bef [BugFix] fix webhook process (#5047) 2026-05-24 16:19:27 +08:00
同語 ebbe315533 🐛 fix(channel): evict auto-disabled multi-key channels from cache (#4983)
* 🐛 fix(channel): evict auto-disabled multi-key channels from cache

Ensure multi-key channels are removed from the in-memory routing cache when all keys become auto-disabled, preventing subsequent requests from repeatedly selecting channels with no available keys.

Also make multi-key status updates more robust by handling missing key matches, checking actual enabled key availability, and restoring the channel status when a key is re-enabled. Add regression coverage for disabled cached channels and multi-key cache eviction.
2026-05-23 13:24:56 +08:00
CaIon fddf54ccc5 perf: reduce heap residency for large base64 relay requests
Three layered optimizations targeting Gemini-style 5MB base64 payloads where
RSS could balloon to tens of GB under concurrent load:

1. Byte-based param override (relay/common/override.go)
   - Switch legacy/operations hot paths from common.Marshal round-trips and
     map[string]any conversions to gjson/sjson on []byte directly.
   - Avoids cloning 5MB strings during each Set/Delete operation.

2. strings.Builder for Gemini response markdown (relay/channel/gemini/relay-gemini.go)
   - Replace string concatenation + strings.Join when assembling
     "![image](data:...;base64,DATA)" content for inline image responses.
   - Pre-allocates capacity from inline_data byte sizes.

3. Outbound BodyStorage + streaming Decoder (this commit's core)
   - New relay/common/outbound_body.go helper wraps marshaled upstream bodies
     in common.BodyStorage, allowing disk-cache mode to offload jsonData to
     a temp file while waiting for upstream TTFB. The original []byte can
     then be GC'd, removing ~5MB/req of heap residency during the longest
     window of a request.
   - All 7 relay handlers (gemini/claude/responses/embedding/image/compatible/
     rerank) plus chat_completions_via_responses adopt the helper with
     defer closer.Close() and explicit jsonData = nil.
   - relay/common/relay_info.go: new UpstreamRequestBodySize so
     relay/channel/api_request.go can populate req.ContentLength (lost when
     body becomes a type-erased io.Reader).
   - common/gin.go UnmarshalBodyReusable: when storage is disk-backed and
     content-type is JSON, decode via DecodeJson(storage) instead of
     storage.Bytes()+Unmarshal, removing one transient 5MB copy per request.
     memory mode and form/multipart paths unchanged.
2026-05-22 19:08:38 +08:00
CaIon b9bc6f0e21 Revert "fix: correct usage logs filtering (#4883)"
This reverts commit 554defe4f4.
2026-05-22 16:19:54 +08:00
Seefs f2c7647ecf fix: enforce Waffo subscription compliance and product ID update (#5038)
* fix: enforce Waffo subscription compliance and product ID updates

* fix: hide Waffo Pancake settings in classic UI
2026-05-22 11:48:32 +08:00
Hill-waffo 19f1821fc8 [Feature Request] Waffo Pancake gateway — full integration with subscription support + admin catalog binding flow (#4935) 2026-05-22 11:00:58 +08:00
JunXiaoRuo 8e5e89bb5b 修复 切换新版前端Turnstile 开启后注册页未显示验证的问题 (#5011)
Co-authored-by: Codex <codex@users.noreply.github.com>
2026-05-22 10:39:24 +08:00
yyhhyyyyyy e13d673454 fix: update default frontend hardcoded route links (#5016) 2026-05-22 10:36:50 +08:00
Seefs ae6a03364d perf: optimize request metadata extraction and disabled field filtering (#5009)
* perf: optimize request metadata extraction and disabled field filtering

* perf: optimize stream usage estimation path
2026-05-22 10:32:11 +08:00
yyhhyyyyyy 006e801652 fix: resolve model owned_by from active channels (#4416)
* fix: resolve model owned_by from active channels

* fix: respect token group when resolving model owners
2026-05-21 11:16:17 +08:00
yyhhyyyyyy 6f11d19877 fix: normalize model pricing display drift (#4985) 2026-05-21 11:10:22 +08:00
yyhhyyyyyy 58ba867dd6 fix: improve channel test failure details UX (#4988)
* fix: improve channel test failure details UX

* fix: add accessible label to channel models region
2026-05-21 11:09:51 +08:00
Seefs 20d3e73734 fix: filter perf metrics summary by active groups (#4976) 2026-05-20 11:38:09 +08:00
Seefs 2d1ca15384 fix: respect dashboard content visibility settings (#4975) 2026-05-19 18:46:21 +08:00
Seefs 0d4b25795a fix: expose param override audits for sensitive message fields (#4974) 2026-05-19 18:28:03 +08:00
Calcium-Ion 146dd77b83 fix(keys): call submit handler directly to avoid stale form linkage (#4858) (#4967)
Users reported that the API key edit drawer's "Save changes" button
becomes unresponsive after the drawer has been open / idle for a
while: no loading state, no request, no error. Reopening the drawer
restores it because a fresh DOM is created.

The button lived in `SheetFooter` (a portaled Base UI Sheet) and was
linked to the form via the HTML `form='api-key-form'` attribute. Once
the portal/DOM relationship goes stale, the click no longer triggers
the form's submit event, hence the silent failure.

Defensive fix: drop the cross-DOM `form` linkage and call
`form.handleSubmit(onSubmit)` directly via `onClick`. The native
submit path (Enter key, original `<form onSubmit>`) is preserved.

Closes #4858
2026-05-19 16:40:11 +08:00
Calcium-Ion 5e88f97ac1 fix(data-table): make faceted filter popover width adaptive (#4905) (#4966)
The faceted filter popover used a fixed width of 200px, which clipped
long option labels (e.g. user-defined channel group names) and forced
the truncated text to be unreadable without leaving a way to see the
full value.

- Switch PopoverContent from `w-[200px]` to
  `min-w-[200px] max-w-[360px]` so short option lists keep their
  current footprint while long labels can expand up to 360px before
  the existing truncate kicks in.
- Add `title={t(option.label)}` on the truncated label span so users
  can still hover to see the full text on extreme cases.

Closes #4905
2026-05-19 16:39:57 +08:00
Calcium-Ion 0cd9a3a068 fix(auth): use aff_code field name in registration payload (#4945) (#4965)
The new UI's sign-up form sent the invite code under key `aff`, but
the backend `Register` controller binds it to `User.AffCode` whose
JSON tag is `aff_code` (see model/user.go). Result: every invited
sign-up landed with `inviter_id = 0`, breaking the affiliate flow.

Rename only the request payload field so it matches the backend
contract. URL query parameter (`/sign-up?aff=...`), localStorage key
and OAuth state continue to use `aff` and are unchanged.

Closes #4945
2026-05-19 16:39:42 +08:00
Micah-Zheng 032993ed49 fix: check save result in handleSaveAll and add slate to validColors (#4823)
Signed-off-by: Micah-Zheng <102610064+Micah-Zheng@users.noreply.github.com>
2026-05-19 16:15:13 +08:00
Micah-Zheng c78573ce03 fix(web/default): api-info color dot shows wrong color due to semantic token mismatch (#4824)
* fix: unify color system for api-info, add slate to SemanticColor

Signed-off-by: Micah-Zheng <102610064+Micah-Zheng@users.noreply.github.com>

* fix: use direct Tailwind color classes in colorToBgClass for accurate color display

Signed-off-by: Micah-Zheng <102610064+Micah-Zheng@users.noreply.github.com>

---------

Signed-off-by: Micah-Zheng <102610064+Micah-Zheng@users.noreply.github.com>
2026-05-19 16:15:02 +08:00
panxinyu 8db32213e7 fix(web/default/wallet): make recharge preset selection visible in dark mode (#4897)
Selected preset buttons looked identical to unselected in dark mode: the
override classes `border-foreground bg-foreground/5` carry no `dark:`
variant, while the Button `outline` variant base contains
`dark:border-input dark:bg-input/30`. tailwind-merge keeps both (different
variants → no conflict), and in dark mode CSS specificity makes
`.dark .border-input` win over `.border-foreground`, so the override is
silently overridden and the bright-border/tinted-bg selection state never
applies.

Add explicit `dark:border-foreground dark:bg-foreground/10` to the
override so tailwind-merge resolves the dark-variant conflict in favor
of the override and the selected state is clearly distinguishable on
both light and dark backgrounds.

Co-authored-by: xinnyu <xinnyu@users.noreply.github.com>
2026-05-19 16:14:56 +08:00
Neo cb9270ed23 fix(auth): localize reset password confirmation (#4769)
* fix(auth): localize reset password confirmation

Wrap reset confirmation page copy in frontend i18n calls and add matching locale entries so the page no longer mixes translated labels with hardcoded English copy.

* fix(auth): use semantic reset i18n keys
2026-05-19 16:14:49 +08:00
Ellis Fan fc08c133e2 fix(web/default): update pagination button labels in ModelCardGrid (#4675)
Change 'Previous' to 'Previous page' and 'Next' to 'Next page'
for improved clarity in the ModelCardGrid component.
2026-05-19 16:14:37 +08:00
Yuhan Guo丨Eohan b397c58bab fix(auth): expose register_enabled in /api/status and gate sign-up link (#4871)
/api/status never returned `register_enabled` or `password_register_enabled`,
so the sign-in page had no way to react when an admin disabled registration.
The "Sign up" link was only gated on `self_use_mode_enabled`, which is a
separate and unrelated concept (single-user vs. multi-user deployment).

Result: toggling "Registration Enabled" in admin settings had no visible
effect on the login page — users could still see the sign-up link even when
registration was disabled, and could not see it even when it was enabled
(if the system happened to be in self-use mode from initial setup).

Fix:
- Add `register_enabled` and `password_register_enabled` to GetStatus()
- Gate the "Sign up" link on `register_enabled !== false` in addition to
  the existing `!self_use_mode_enabled` check

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 16:14:34 +08:00
Baiyuan Chiu 8ae095c3b8 fix user create and delete handling (#4818) 2026-05-19 16:14:11 +08:00
yyhhyyyyyy 04b4483d7d fix(web): normalize model detail tabs layout (#4938) 2026-05-19 16:14:08 +08:00
Li Duoyang ee9736bbc8 fix: add type="submit" to forgot password form button (#4910)
The "Send reset email" button was missing type="submit", preventing
form submission when clicked. All other auth forms (sign-in, sign-up,
OTP) already have this attribute set correctly.

Closes #4793
2026-05-19 16:14:03 +08:00
Seefs 0936e25046 perf: avoid eager formatting in debug log calls (#4929) 2026-05-19 12:11:24 +08:00
NitroFire 5dd0d3bcbd fix: add analytics placeholder (#4928) 2026-05-17 18:54:39 +08:00
QuentinHsu f69ceb6967 fix: 修复新 UI 语言与文案显示问题 (#4876)
* chore(dev): add local setup state reset target

- add a reset-setup make target to clear setup records, root users, and related options.
- support both docker dev PostgreSQL and local SQLite development databases.
- restart the docker dev backend so setup status is recalculated after reset.

* fix(chat): prevent preset menu text overflow

- add truncation layout for chat preset names to keep long labels inside the sidebar menu.
- prevent loading and external-link icons from shrinking in constrained menu rows.

* fix(i18n): translate dashboard granularity options

- call t() for granularity option labels in dashboard system settings.
- keep localized text consistent between the select trigger and dropdown items.

* chore(dev): add backend dev service rebuild target

- add a dev-api-rebuild make target to rebuild and start the docker backend service.
- reuse DEV_COMPOSE_FILE and DEV_BACKEND_SERVICE variables to avoid repeated compose config literals.

* fix(i18n): align interface language option labels

- add shared interface language options to keep display names consistent.
- reuse the shared options in the header switcher and profile preferences.
- normalize language codes so zh-CN and zh_CN resolve to Simplified Chinese.

* fix(i18n): add missing frontend translation keys

- route channel key prompts, form validation messages, and channel fallback text through i18n.
- add missing translations across six locales for channels, rankings, billing, and logs.
- update i18n sync reports so literal t() keys are present in the base locale.
2026-05-17 11:45:27 +08:00
Seefs 68830e6097 feat: support request_header key source (#4903)
* feat: support request_header key source in backend and settings UI

* feat: support request_header channel affinity source
2026-05-17 11:44:38 +08:00
yyhhyyyyyy 2d968c3eab fix: apply group filter to channel list queries (#4885) 2026-05-17 11:44:07 +08:00
Seefs cb7a61466e Merge pull request #4684 from SAY-5/fix/perf-metric-ambiguous-column
fix: qualify column names in PerfMetric upsert to avoid PG ambiguity
2026-05-16 22:11:38 +08:00
DraftGo 132d7b9f94 fix: GetAllChannels ignores group filter parameter (#4847)
When users filter channels by group without entering a search keyword,
the frontend calls GetAllChannels (GET /api/channel/) instead of
SearchChannels. However, GetAllChannels did not process the group
query parameter, causing the filter to have no effect.

Added group filtering logic to GetAllChannels for both normal mode
and tag mode, using the same CONCAT/|| pattern as SearchChannels
for cross-database compatibility (MySQL, PostgreSQL, SQLite).
2026-05-16 14:54:50 +08:00
yyhhyyyyyy 6f8668e4c3 fix: enforce header nav access control for public modules (#4889) 2026-05-16 14:54:47 +08:00
yyhhyyyyyy 8a10dedb7d fix(web): handle unlimited API key quota validation (#4881) 2026-05-16 14:54:35 +08:00
yyhhyyyyyy 554defe4f4 fix: correct usage logs filtering (#4883) 2026-05-16 14:54:23 +08:00
yyhhyyyyyy 8f9ee9ba88 fix: allow clearing channel remark (#4886) 2026-05-16 14:54:18 +08:00
CaIon 3caa6e467b fix(web/default): batch fix new UI issues #4880 #4893 #4817 #4877 #4898
- Add singleSelect to status/role filters in API keys, users, and redemptions tables (#4880)
- Fix affiliate link 404 by changing /register to /sign-up (#4893)
- Open FetchModelsDialog in channel creation mode via customFetcher prop (#4817)
- Add TruncatedText component with tooltip for long channel names, token names, and usernames (#4877)
- Elevate forgot-password link z-index to prevent label click interception (#4898)
2026-05-16 14:48:49 +08:00
CaIon 18282e610d chore(deps): update axios from 1.15.0 to 1.15.2 2026-05-13 22:23:45 +08:00