Skip to content

🚀 feat: launch v1.0 — next-generation frontend built from the ground up#4265

Open
t0ng7u wants to merge 5534 commits intomainfrom
v1
Open

🚀 feat: launch v1.0 — next-generation frontend built from the ground up#4265
t0ng7u wants to merge 5534 commits intomainfrom
v1

Conversation

@t0ng7u
Copy link
Copy Markdown
Collaborator

@t0ng7u t0ng7u commented Apr 15, 2026

⚠️ 提交说明 / PR Notice

Important

  • 请提供人工撰写的简洁摘要,避免直接粘贴未经整理的 AI 输出。

📝 变更描述 / Description

Introduce a completely redesigned default frontend powered by React 19,
TypeScript, Rsbuild, Radix UI, and Tailwind CSS — replacing the legacy
Semi Design stack with a modern, accessible, and performance-first
architecture.
Highlights:

  • Full rewrite: 823 new files, 142K+ lines of purpose-built UI code
  • TanStack Router + React Query + React Table for type-safe routing,
    server state, and high-performance data grids
  • Zustand for lightweight, scalable state management
  • React Hook Form + Zod for declarative, schema-validated forms
  • VChart-powered analytics dashboard with real-time metrics
  • Complete i18n coverage across 6 languages (en/zh/fr/ja/ru/vi)
  • Mobile-first responsive design with adaptive layouts for every page
  • Backend-configurable theme switching (default/classic)
  • Passkey/WebAuthn, OAuth, and multi-factor authentication flows
  • Channel affinity rules, model pricing editor, and subscription management
    This marks the transition from v0.x to v1.x — a milestone release
    that sets the foundation for the next era of the platform.

🚀 变更类型 / Type of change

  • 🐛 Bug 修复 (Bug fix) - 请关联对应 Issue,避免将设计取舍、理解偏差或预期不一致直接归类为 bug
  • [ x ] ✨ 新功能 (New feature) - 重大特性建议先通过 Issue 沟通
  • ⚡ 性能优化 / 重构 (Refactor)
  • 📝 文档更新 (Documentation)

🔗 关联任务 / Related Issue

  • Closes # (如有)

✅ 提交前检查项 / Checklist

  • [ x ] 人工确认: 我已亲自整理并撰写此描述,没有直接粘贴未经处理的 AI 输出。
  • [ x ] 非重复提交: 我已搜索现有的 IssuesPRs,确认不是重复提交。
  • [ x ] Bug fix 说明: 若此 PR 标记为 Bug fix,我已提交或关联对应 Issue,且不会将设计取舍、预期不一致或理解偏差直接归类为 bug。
  • [ x ] 变更理解: 我已理解这些更改的工作原理及可能影响。
  • [ x ] 范围聚焦: 本 PR 未包含任何与当前任务无关的代码改动。
  • [ x ] 本地验证: 已在本地运行并通过测试或手动验证,维护者可以据此复核结果。
  • [ x ] 安全合规: 代码中无敏感凭据,且符合项目代码规范。

📸 运行证明 / Proof of Work

f253582482ba565fbe6da6edf38c7196

Calcium-Ion and others added 30 commits December 31, 2025 21:22
feat(checkin): add check-in functionality
- Add initialLoaded state to track first data load completion
- Set isCollapsed to null initially, determined after data loads
- Show loading state on button and description text before data arrives
- Remove auto-collapse effect that caused visual flicker
- Add i18n translations for loading states (en/fr/ja/ru/vi/zh)

Fixes issue where component would collapse/expand after data loads,
causing visual flicker when navigating to personal settings page.
…rim_suffix, ensure_prefix, ensure_suffix, trim_space, to_lower, to_upper, replace, and regex_replace
移除gorm:"default:false",避免每次 AutoMigrate时都执行ALTER TABLE `tokens` MODIFY COLUMN `cross_group_retry` boolean DEFAULT false
且bool默认false不影响原有功能
* feat: add support for Doubao /v1/responses
feat: check-in feature integrates Turnstile security check
fix: gemini request -> openai tool call
…#2556)

* fix: fix model deployment style issues, lint problems, and i18n gaps.

* fix: adjust the key not to be displayed on the frontend, tested via the backend.

* fix: adjust the sidebar configuration logic to use the default configuration items if they are not defined.
fix: 修复 gemini 文件类型不支持 image/jpg
…figuration && the AWS calling side did not apply the relay timeout.
fix: fix the proxyURL is empty, not using the default HTTP client configuration && the AWS calling side did not apply the relay timeout.
t0ng7u and others added 19 commits April 12, 2026 21:54
# Conflicts:
#	web/src/features/pricing/components/model-row.tsx
…nfig

- Add 425+ missing translations across fr, ja, ru, zh, vi locales
  for subscription management, sidebar navigation, Grok settings,
  upstream model updates, pricing page, and other UI components
- Add 37 missing i18n keys used in t() calls but absent from locale
  files (pricing filters, display options, audio/cache labels, etc.)
- Fix stale tech stack info in CLAUDE.md, AGENTS.md, and project.mdc:
  React 18 → 19, Vite → Rsbuild, Semi Design → Radix UI + Tailwind
- Fix i18n key format description: "Chinese source strings" → English
- Deduplicate .cursor/rules/project.mdc to avoid triple-loading the
  same rules already present in root CLAUDE.md and AGENTS.md
- Add i18n-translate Cursor skill for repeatable translation workflow
Replace Card-based dashboard components with a flat, border-driven design
system consistent with the pricing page, following the ui-style.mdc conventions.

Overview section:
- StatCard: replace Card wrapper with flat flex layout, monospace tabular
  values, uppercase tracking-wider labels, layered opacity hierarchy
- PanelWrapper: replace Card/CardHeader/CardContent with rounded-lg border
  container and border-b header
- SummaryCards: merge three stat cards into a single bordered container
  with divide-x separators; decouple border from stagger animation to
  prevent border deformation during entrance transitions
- ApiInfoPanel/Item: full-width list rows with border-b separators,
  monospace route names, layered opacity for URLs and descriptions
- AnnouncementsPanel: native button rows with hover:bg-muted/40, i18n for
  "Click for details" hint
- FAQPanel: lighter border-border/60 accordion dividers, muted answer text
- UptimePanel: uppercase tracking-wider group headers with bg-muted/30
  background, monospace uptime percentages, fine-grained border opacity

Models section:
- LogStatCards: replace Card with rounded-lg border + divide-x grid,
  fix react-hooks/exhaustive-deps by destructuring props before useEffect
- ModelCharts: replace Card+Tabs with bordered container + custom
  segmented control matching ui-style spec
- Suspense fallbacks: match new flat skeleton layout with accurate
  column structure

Animation:
- Wrap models section in FadeIn with staggered delay
- Keep CardStagger for overview panel grid (each panel has own border)

Other:
- Add ui-style.mdc cursor rule documenting the design language
- Disable react-refresh/only-export-components for src/routes/** in
  eslint config (TanStack Router route files always export Route objects)
- Fix zh.json: "Token-based" translation "基于令牌的" → "按量计费"
Replace the bordered/colored-background StatusBadge and Badge components
across the entire frontend with a minimal flat design: a small colored
dot followed by colored text, eliminating visual noise from heavy
borders, backgrounds, and rounded pill shapes.

Key changes:

- Redesign StatusBadge to use dot + text instead of bordered pill style,
  removing cva-based background/border variants in favor of exported
  dotColorMap and textColorMap lookup tables
- Add children prop support to StatusBadge for flexible content rendering
  alongside the existing label prop
- Migrate all Badge usages (except pricing page) to StatusBadge with
  appropriate variant mappings (default→info, secondary→neutral,
  outline→neutral, destructive→danger)
- Consolidate adjacent multi-badge groups into single-dot layouts with
  dot separators (·) to reduce visual clutter in:
  - Channel balance columns (used + remaining)
  - Channel type column (type + IO.NET indicator)
  - User invite info column (invited + revenue + inviter)
  - Usage log stats bar (usage + RPM + TPM)
  - Usage log time/FRT column (time + FRT + stream status)
  - Subscription plan counts (active + expired)
  - Channel affinity scope/regex/key-source columns
  - Prefill group card headers (type + ID)
- Export dotColorMap and textColorMap for direct use in custom inline
  layouts that need consistent status colors without the full component
Overhaul the public-facing layout, header, and homepage to deliver a
polished, animation-rich landing experience inspired by contemporary
SaaS design patterns.

Header:
- Replace sticky header with fixed floating navbar that compacts into
  a pill-shaped glass-morphism bar on scroll (backdrop-blur + ring)
- Add smooth 700ms cubic-bezier transitions for scroll-based shrinking
- Build full-screen mobile menu overlay with staggered entry animations
- Remove background color from logo container, show logo image directly

Homepage sections:
- Hero: gradient text title, radial gradient + grid pattern background,
  interactive terminal demo showcasing API request/response
- Terminal demo: auto-cycles through gpt-4o, claude-sonnet-4-20250514,
  gemini-2.5-pro, deepseek-chat with smooth cross-fade transitions,
  clickable model badges, dual theme support (light/dark), fixed height
- Stats: animated counters driven by IntersectionObserver with
  cubic-bezier easing, supports integer and decimal modes
- Features: Bento grid layout with gap-px border technique, each card
  includes contextual visuals (model list, security badge, workflow)
- How It Works: new three-step process section (Configure → Connect →
  Monitor) with connecting gradient line and numbered badges
- CTA: gradient mesh background with scale-in scroll animation
- Footer: streamlined brand column + link columns layout

New components:
- AnimateInView: IntersectionObserver-based scroll animation component
  supporting fade-up, fade-in, scale-in, fade-left, fade-right
- HeroTerminalDemo: themed terminal with model carousel and live
  request/response preview

CSS:
- Add landing page scroll-triggered keyframe animations
- Add terminal demo animations (blink cursor, spinner, pulse indicator)
- Respect prefers-reduced-motion throughout

i18n:
- Add 17 new translation keys across all 6 locales (en/zh/fr/ja/ru/vi)
Usage logs
- Show Refund (type 6) in detail dialog and hide conversion chain for refunds
- Sync filter dialog state from URL for model, token, group, username, and requestId

Channels
- Support optional stream flag in channel test API, actions, and test dialog
- Show upstream model update badges (+added / -removed) on fetchable channel types
- Add form fields and drawer toggles for upstream model update check and auto-sync
- Persist upstream model update flags in channel settings JSON for fetchable types

i18n
- Add locale strings for upstream model update UI (en, zh, fr, ja, ru, vi)
…mations

Add overflow-y-clip to the shared Table container (data-slot=table-container)
alongside overflow-x-auto. Setting overflow-x to auto implicitly pairs with
overflow-y: auto in browsers, which made the table shell briefly show a
vertical scrollbar during route enter motion (y/blur) and table row stagger.

Remove the redundant descendant selector workaround from the model pricing
GroupPricingSection; behavior is now covered globally by the Table component.
…le content, and pinned footer

Overhaul the authenticated console layout to match the OpenAI dashboard
pattern: header and page title bar stay fixed at the top, only the
content area scrolls, and table pagination is pinned to the bottom.

Layout architecture:
- Lock SidebarInset to full viewport height (h-svh) so all inner
  regions are controlled by flexbox instead of document scroll
- Convert Main from a generic div to a semantic <main> flex container
  with overflow-hidden, removing the legacy `fixed` prop and
  `data-layout` attribute
- Strip scroll-shadow logic and `fixed` prop from Header/AppHeader;
  the header is now naturally fixed as a shrink-0 flex child
- Restructure SectionPageLayout into three flex regions: a shrink-0
  title bar, a flex-1 overflow-auto content area, and a shrink-0
  footer portal target with empty:hidden
- Add min-h-0 to AnimatedOutlet wrappers to prevent flex overflow

Footer portal system:
- Introduce PageFooterProvider / PageFooterPortal (React Context +
  createPortal) so deeply nested table components can render their
  DataTablePagination into the fixed footer without prop drilling
- Migrate all 8 data tables (api-keys, channels, users, models,
  deployments, usage-logs, subscriptions, redemption-codes) to use
  PageFooterPortal for pagination

Page-level fixes:
- Profile: wrap content in a scrollable flex child with proper padding
- SystemSettings: remove overflow-auto from wrapper to avoid nested
  scrollbars (sub-pages manage their own scroll)
- Playground / Error pages: remove obsolete `fixed` props

API keys UX improvement:
- Replace inline key show/hide toggle with a Popover-based reveal,
  removing toggleKeyVisibility and keyVisibility state from the
  provider context

Cleanup:
- Remove dead CSS rule for body:has([data-layout='fixed'])
- Remove unused `fixed` prop from Header, AppHeader, and Main types
- Export PageFooterPortal from layout barrel file
…itions

- Standardize primary action buttons (Create, Add, Search) to size="sm"
  across all pages for visual consistency with channels and models
- Redesign NumericSpinnerInput with minimal inline style: plain text by
  default, hover-revealed +/- buttons, click-to-edit — replacing the
  clunky bordered input with stacked chevron arrows
- Fix vertical scrollbar in channels group column by replacing
  overflow-x-auto with overflow-hidden (redundant with +N collapse)
- Simplify API keys group column: replace colorful StatusBadge pairs
  with clean typography using opacity hierarchy and dot separators
- Move API key copy loading indicator from key text to the copy button
  itself, eliminating layout shift during key resolution
- Reduce page title from text-2xl to text-lg and subtitle to text-sm
  in SectionPageLayout for a more compact header
- Add smooth opacity transition (duration-150) on all 7 server-paginated
  tables during background data fetches (isFetching && !isLoading),
  with pointer-events-none to prevent interaction during loading
- Constrain usage logs Details column width (size: 200, maxSize: 220)
The console layout refactor in d215046 moved padding ownership from
Main onto each route, but SystemSettings was missed — its Outlet
wrapper had no padding, so the content area sat flush against the
sidebar and top nav. Add `px-4 pt-6 pb-4` to match the vertical
rhythm used by SectionPageLayout and the Profile page.
…e pages

Unify mobile experience for all data table pages (channels, keys, models,
deployments, usage-logs, users, redemption-codes, subscriptions) with a
consistent layout pattern and cleaner header area.

DataTableToolbar:
- Redesign mobile layout: full-width search input + collapsible filter
  toggle button with active filter count badge
- Filters, additional search, and reset button collapse into an
  expandable section on mobile, keeping the default view compact
- Desktop layout remains unchanged

SectionPageLayout:
- Tighten mobile spacing (padding, gaps) for higher content density
- Scale down title (text-base) and description (text-xs) on mobile
- Shrink action button gaps on small screens

ChannelsPrimaryButtons:
- Move Tag Mode and Sort by ID toggles into the "More" dropdown on
  mobile (via DropdownMenuCheckboxItem), freeing header space
- Desktop toggle switches remain visible outside the dropdown

MobileCardList (shared component):
- Compact list-item layout with title + badge header row and
  side-by-side key fields, replacing individual card components
- Structured (CompactRow) and fallback (FallbackRow) rendering modes
  driven by column meta (mobileTitle, mobileBadge, mobileHidden)

New MobileCardList integration:
- Users table: username as title, status as badge; hide id,
  display_name, invite_info on mobile
- Redemptions table: name as title, status as badge; hide id,
  created_time, expired_time, used_user_id on mobile
- Subscriptions table: plan title as title, enabled as badge; hide id,
  sort_order, reset, payment, total_amount, upgrade_group on mobile

Column meta updates:
- Add mobileTitle/mobileBadge/mobileHidden meta across all 8 table
  column definitions for consistent mobile field prioritization

Minor fixes:
- Hide Subscriptions Stripe/Creem alert on mobile
- Disable card hover animations on mobile via CSS media query
Favicon stayed at the hardcoded /logo.png while document.title already
followed system_name, leaving tab icon and site branding out of sync.
Apply the logo as favicon from localStorage cache on startup, refresh
from getStatus(), and re-apply when useSystemConfig finishes preloading.
Extract applyFaviconToDom helper into lib/dom-utils with idempotent guard
to avoid redundant DOM writes.
… visual editing

Port missing features from legacy frontend (b8650b9 merge) to the new
React frontend:

- Add Codex CLI and Claude CLI channel affinity rule templates with
  header passthrough presets (pass_headers operations for Originator,
  Session_id, X-Codex-*, X-Stainless-*, Anthropic-*, etc.)
- Introduce "Add Rule" dropdown menu with blank, Codex CLI, and Claude
  CLI template options in the channel affinity settings page
- Add "Fill Templates" button to batch-append both CLI templates with
  duplicate name resolution and confirmation dialog
- Support templateKey prop in RuleEditorDialog to pre-fill form fields
  from selected template, auto-expanding advanced settings when a
  param_override_template is present
- Add CreateCacheRatio support to the model ratio visual editor, edit
  dialog, and form — previously only editable in JSON mode, now fully
  integrated into the visual table column, add/edit dialog fields, and
  save/delete handlers
- Fix About page URL detection: replace naive `startsWith('https://')`
  with proper `new URL()` validation to support both http and https, and
  handle untrimmed input that previously caused silent misdetection
- Fix About page HTML detection: remove overly broad `startsWith('<')`
  and `endsWith('>')` checks that could misclassify Markdown or XML
  content; align with LegalDocument's regex-only `isLikelyHtml` approach
- Fix Home page URL detection: same `startsWith('https://')` bug,
  replaced with `new URL()` protocol validation
- Refactor About page to use early-return pattern instead of deeply
  nested ternary expressions for better readability
- Replace About loading spinner with Skeleton placeholder consistent
  with LegalDocument
- Add `prose prose-neutral dark:prose-invert` typography classes to
  About HTML/Markdown rendering for proper dark mode support
- Remove unused `Code` icon import from About page
# Conflicts:
#	web/bun.lock
#	web/package.json
#	web/src/i18n/locales/en.json
#	web/src/i18n/locales/fr.json
#	web/src/i18n/locales/ja.json
#	web/src/i18n/locales/ru.json
#	web/src/i18n/locales/vi.json
…i18n

Backport and enhance several features from the old frontend (web/old)
that were missing or incomplete in the new React frontend:

- Playground & channel test: parse structured JSON error responses from
  SSE streams and non-streaming API calls, extract error codes, and
  display actionable UI for `model_price_error` (admin settings link)
- User management: replace local quota manipulation with atomic
  server-side quota adjustments (add/subtract/override) via dedicated
  API endpoint, making the quota field read-only in the edit drawer
- Subscriptions: display next quota reset time for active subscriptions
- Dashboard: limit model ranking chart to top 20 models with an "Other"
  bucket, add dimension tooltips with sorted values and totals to model
  call trend and user consumption trend charts
- i18n: add 24 new translation keys across all 6 locales (en, zh, fr,
  ja, ru, vi) for the newly introduced UI elements and messages
…assic)

Introduce runtime frontend theme switching so administrators can switch
between the new frontend (Radix UI + Tailwind) and the classic frontend
(Semi Design) from the settings page without restarting the server.

Directory restructuring:
- Move new frontend from web/ to web/default/
- Move classic frontend from web/old/ to web/classic/
- One-frontend-per-folder layout for extensibility

Backend (injection pattern):
- Add setting/system_setting/theme.go with GlobalConfig.Register("theme")
  so the DB key "theme.frontend" is handled automatically by
  handleConfigUpdate — no switch-case in updateOptionMap needed
- Use atomic.Value in common.GetTheme()/SetTheme() for lock-free
  concurrent reads on the hot path (static file middleware)
- Add themeAwareFileSystem that delegates to the correct embedded FS
  based on the current theme at request time
- Embed both frontends into the binary via go:embed
- Add controller validation for theme.frontend values
- Expose theme in GET /api/status response

Frontend settings UI:
- New frontend: add "Frontend Theme" select in System Information section
  using Radix UI Select + react-hook-form + Zod validation
- Classic frontend: add "前端主题" select in Personalization section
  using Semi Design Form.Select

Build system:
- Update Dockerfile with multi-stage builds for both frontends
- Update Makefile with separate build targets for each frontend
- Update GitHub Actions release workflow for dual frontend builds

i18n:
- New frontend: add translations for all 6 locales (en/zh/fr/ja/ru/vi)
- Classic frontend: add translations for all 7 locales (en/zh-TW/ja/fr/ru/vi)
- Fix zh "AI Proxy Library" → "AI 代理库"

Documentation:
- Update CLAUDE.md, AGENTS.md, .cursor/rules/project.mdc to reflect
  the new web/default/ and web/classic/ directory structure
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 15, 2026

Important

Review skipped

Too many files!

This PR contains 292 files, which is 142 over the limit of 150.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 65180920-d9b7-4821-8017-bebade1eda6d

📥 Commits

Reviewing files that changed from the base of the PR and between 3cad6b9 and 8153f7c.

⛔ Files ignored due to path filters (8)
  • web/classic/bun.lock is excluded by !**/*.lock
  • web/classic/public/azure_model_name.png is excluded by !**/*.png
  • web/classic/public/favicon.ico is excluded by !**/*.ico
  • web/classic/public/logo.png is excluded by !**/*.png
  • web/classic/public/pay-apple.png is excluded by !**/*.png
  • web/classic/public/pay-card.png is excluded by !**/*.png
  • web/classic/public/pay-google.png is excluded by !**/*.png
  • web/classic/public/ratio.png is excluded by !**/*.png
📒 Files selected for processing (292)
  • .agents/skills/vercel-react-best-practices/AGENTS.md
  • .cursor/rules/project.mdc
  • .github/FUNDING.yml
  • .github/workflows/docker-build.yml
  • .github/workflows/release.yml
  • .gitignore
  • AGENTS.md
  • CLAUDE.md
  • Dockerfile
  • Dockerfile.dev
  • README.en.md
  • common/constants.go
  • common/embed-file-system.go
  • controller/discord.go
  • controller/github.go
  • controller/linuxdo.go
  • controller/misc.go
  • controller/oidc.go
  • controller/option.go
  • controller/task_video.go
  • docker-compose.dev.yml
  • main.go
  • makefile
  • model/option.go
  • model/task.go
  • router/main.go
  • router/web-router.go
  • service/pre_consume_quota.go
  • setting/system_setting/theme.go
  • web/classic/.eslintrc.cjs
  • web/classic/.gitignore
  • web/classic/.prettierrc.mjs
  • web/classic/i18next.config.js
  • web/classic/index.html
  • web/classic/jsconfig.json
  • web/classic/package.json
  • web/classic/postcss.config.js
  • web/classic/public/cover-4.webp
  • web/classic/public/robots.txt
  • web/classic/src/App.jsx
  • web/classic/src/components/auth/LoginForm.jsx
  • web/classic/src/components/auth/OAuth2Callback.jsx
  • web/classic/src/components/auth/PasswordResetConfirm.jsx
  • web/classic/src/components/auth/PasswordResetForm.jsx
  • web/classic/src/components/auth/RegisterForm.jsx
  • web/classic/src/components/auth/TwoFAVerification.jsx
  • web/classic/src/components/common/DocumentRenderer/index.jsx
  • web/classic/src/components/common/ErrorBoundary.jsx
  • web/classic/src/components/common/examples/ChannelKeyViewExample.jsx
  • web/classic/src/components/common/logo/LinuxDoIcon.jsx
  • web/classic/src/components/common/logo/OIDCIcon.jsx
  • web/classic/src/components/common/logo/WeChatIcon.jsx
  • web/classic/src/components/common/markdown/MarkdownRenderer.jsx
  • web/classic/src/components/common/markdown/markdown.css
  • web/classic/src/components/common/modals/RiskAcknowledgementModal.jsx
  • web/classic/src/components/common/modals/SecureVerificationModal.jsx
  • web/classic/src/components/common/modals/TwoFactorAuthModal.jsx
  • web/classic/src/components/common/ui/CardPro.jsx
  • web/classic/src/components/common/ui/CardTable.jsx
  • web/classic/src/components/common/ui/ChannelKeyDisplay.jsx
  • web/classic/src/components/common/ui/CompactModeToggle.jsx
  • web/classic/src/components/common/ui/JSONEditor.jsx
  • web/classic/src/components/common/ui/Loading.jsx
  • web/classic/src/components/common/ui/RenderUtils.jsx
  • web/classic/src/components/common/ui/ScrollableContainer.jsx
  • web/classic/src/components/common/ui/SelectableButtonGroup.jsx
  • web/classic/src/components/dashboard/AnnouncementsPanel.jsx
  • web/classic/src/components/dashboard/ApiInfoPanel.jsx
  • web/classic/src/components/dashboard/ChartsPanel.jsx
  • web/classic/src/components/dashboard/DashboardHeader.jsx
  • web/classic/src/components/dashboard/FaqPanel.jsx
  • web/classic/src/components/dashboard/StatsCards.jsx
  • web/classic/src/components/dashboard/UptimePanel.jsx
  • web/classic/src/components/dashboard/index.jsx
  • web/classic/src/components/dashboard/modals/SearchModal.jsx
  • web/classic/src/components/layout/Footer.jsx
  • web/classic/src/components/layout/NoticeModal.jsx
  • web/classic/src/components/layout/PageLayout.jsx
  • web/classic/src/components/layout/SetupCheck.js
  • web/classic/src/components/layout/SiderBar.jsx
  • web/classic/src/components/layout/components/SkeletonWrapper.jsx
  • web/classic/src/components/layout/headerbar/ActionButtons.jsx
  • web/classic/src/components/layout/headerbar/HeaderLogo.jsx
  • web/classic/src/components/layout/headerbar/LanguageSelector.jsx
  • web/classic/src/components/layout/headerbar/MobileMenuButton.jsx
  • web/classic/src/components/layout/headerbar/Navigation.jsx
  • web/classic/src/components/layout/headerbar/NewYearButton.jsx
  • web/classic/src/components/layout/headerbar/NotificationButton.jsx
  • web/classic/src/components/layout/headerbar/ThemeToggle.jsx
  • web/classic/src/components/layout/headerbar/UserArea.jsx
  • web/classic/src/components/layout/headerbar/index.jsx
  • web/classic/src/components/model-deployments/DeploymentAccessGuard.jsx
  • web/classic/src/components/playground/ChatArea.jsx
  • web/classic/src/components/playground/CodeViewer.jsx
  • web/classic/src/components/playground/ConfigManager.jsx
  • web/classic/src/components/playground/CustomInputRender.jsx
  • web/classic/src/components/playground/CustomRequestEditor.jsx
  • web/classic/src/components/playground/DebugPanel.jsx
  • web/classic/src/components/playground/FloatingButtons.jsx
  • web/classic/src/components/playground/ImageUrlInput.jsx
  • web/classic/src/components/playground/MessageActions.jsx
  • web/classic/src/components/playground/MessageContent.jsx
  • web/classic/src/components/playground/OptimizedComponents.js
  • web/classic/src/components/playground/ParameterControl.jsx
  • web/classic/src/components/playground/SSEViewer.jsx
  • web/classic/src/components/playground/SettingsPanel.jsx
  • web/classic/src/components/playground/ThinkingContent.jsx
  • web/classic/src/components/playground/configStorage.js
  • web/classic/src/components/playground/index.js
  • web/classic/src/components/settings/ChannelSelectorModal.jsx
  • web/classic/src/components/settings/ChatsSetting.jsx
  • web/classic/src/components/settings/CustomOAuthSetting.jsx
  • web/classic/src/components/settings/DashboardSetting.jsx
  • web/classic/src/components/settings/DrawingSetting.jsx
  • web/classic/src/components/settings/HttpStatusCodeRulesInput.jsx
  • web/classic/src/components/settings/ModelDeploymentSetting.jsx
  • web/classic/src/components/settings/ModelSetting.jsx
  • web/classic/src/components/settings/OperationSetting.jsx
  • web/classic/src/components/settings/OtherSetting.jsx
  • web/classic/src/components/settings/PaymentSetting.jsx
  • web/classic/src/components/settings/PerformanceSetting.jsx
  • web/classic/src/components/settings/PersonalSetting.jsx
  • web/classic/src/components/settings/RateLimitSetting.jsx
  • web/classic/src/components/settings/RatioSetting.jsx
  • web/classic/src/components/settings/SystemSetting.jsx
  • web/classic/src/components/settings/personal/cards/AccountManagement.jsx
  • web/classic/src/components/settings/personal/cards/CheckinCalendar.jsx
  • web/classic/src/components/settings/personal/cards/ModelsList.jsx
  • web/classic/src/components/settings/personal/cards/NotificationSettings.jsx
  • web/classic/src/components/settings/personal/cards/PreferencesSettings.jsx
  • web/classic/src/components/settings/personal/components/TwoFASetting.jsx
  • web/classic/src/components/settings/personal/components/UserInfoHeader.jsx
  • web/classic/src/components/settings/personal/modals/AccountDeleteModal.jsx
  • web/classic/src/components/settings/personal/modals/ChangePasswordModal.jsx
  • web/classic/src/components/settings/personal/modals/EmailBindModal.jsx
  • web/classic/src/components/settings/personal/modals/WeChatBindModal.jsx
  • web/classic/src/components/setup/SetupWizard.jsx
  • web/classic/src/components/setup/components/StepNavigation.jsx
  • web/classic/src/components/setup/components/steps/AdminStep.jsx
  • web/classic/src/components/setup/components/steps/CompleteStep.jsx
  • web/classic/src/components/setup/components/steps/DatabaseStep.jsx
  • web/classic/src/components/setup/components/steps/UsageModeStep.jsx
  • web/classic/src/components/setup/index.jsx
  • web/classic/src/components/table/channels/ChannelsActions.jsx
  • web/classic/src/components/table/channels/ChannelsColumnDefs.jsx
  • web/classic/src/components/table/channels/ChannelsFilters.jsx
  • web/classic/src/components/table/channels/ChannelsTable.jsx
  • web/classic/src/components/table/channels/ChannelsTabs.jsx
  • web/classic/src/components/table/channels/index.jsx
  • web/classic/src/components/table/channels/modals/BatchTagModal.jsx
  • web/classic/src/components/table/channels/modals/ChannelUpstreamUpdateModal.jsx
  • web/classic/src/components/table/channels/modals/CodexOAuthModal.jsx
  • web/classic/src/components/table/channels/modals/CodexUsageModal.jsx
  • web/classic/src/components/table/channels/modals/ColumnSelectorModal.jsx
  • web/classic/src/components/table/channels/modals/EditChannelModal.jsx
  • web/classic/src/components/table/channels/modals/EditTagModal.jsx
  • web/classic/src/components/table/channels/modals/ModelSelectModal.jsx
  • web/classic/src/components/table/channels/modals/ModelTestModal.jsx
  • web/classic/src/components/table/channels/modals/MultiKeyManageModal.jsx
  • web/classic/src/components/table/channels/modals/OllamaModelModal.jsx
  • web/classic/src/components/table/channels/modals/ParamOverrideEditorModal.jsx
  • web/classic/src/components/table/channels/modals/SingleModelSelectModal.jsx
  • web/classic/src/components/table/channels/modals/StatusCodeRiskGuardModal.jsx
  • web/classic/src/components/table/channels/modals/statusCodeRiskGuard.js
  • web/classic/src/components/table/mj-logs/MjLogsActions.jsx
  • web/classic/src/components/table/mj-logs/MjLogsColumnDefs.jsx
  • web/classic/src/components/table/mj-logs/MjLogsFilters.jsx
  • web/classic/src/components/table/mj-logs/MjLogsTable.jsx
  • web/classic/src/components/table/mj-logs/index.jsx
  • web/classic/src/components/table/mj-logs/modals/ColumnSelectorModal.jsx
  • web/classic/src/components/table/mj-logs/modals/ContentModal.jsx
  • web/classic/src/components/table/model-deployments/DeploymentsActions.jsx
  • web/classic/src/components/table/model-deployments/DeploymentsColumnDefs.jsx
  • web/classic/src/components/table/model-deployments/DeploymentsFilters.jsx
  • web/classic/src/components/table/model-deployments/DeploymentsTable.jsx
  • web/classic/src/components/table/model-deployments/index.jsx
  • web/classic/src/components/table/model-deployments/modals/ColumnSelectorModal.jsx
  • web/classic/src/components/table/model-deployments/modals/ConfirmationDialog.jsx
  • web/classic/src/components/table/model-deployments/modals/CreateDeploymentModal.jsx
  • web/classic/src/components/table/model-deployments/modals/EditDeploymentModal.jsx
  • web/classic/src/components/table/model-deployments/modals/ExtendDurationModal.jsx
  • web/classic/src/components/table/model-deployments/modals/UpdateConfigModal.jsx
  • web/classic/src/components/table/model-deployments/modals/ViewDetailsModal.jsx
  • web/classic/src/components/table/model-deployments/modals/ViewLogsModal.jsx
  • web/classic/src/components/table/model-pricing/filter/PricingDisplaySettings.jsx
  • web/classic/src/components/table/model-pricing/filter/PricingEndpointTypes.jsx
  • web/classic/src/components/table/model-pricing/filter/PricingGroups.jsx
  • web/classic/src/components/table/model-pricing/filter/PricingQuotaTypes.jsx
  • web/classic/src/components/table/model-pricing/filter/PricingTags.jsx
  • web/classic/src/components/table/model-pricing/filter/PricingVendors.jsx
  • web/classic/src/components/table/model-pricing/layout/PricingPage.jsx
  • web/classic/src/components/table/model-pricing/layout/PricingSidebar.jsx
  • web/classic/src/components/table/model-pricing/layout/content/PricingContent.jsx
  • web/classic/src/components/table/model-pricing/layout/content/PricingView.jsx
  • web/classic/src/components/table/model-pricing/layout/header/PricingTopSection.jsx
  • web/classic/src/components/table/model-pricing/layout/header/PricingVendorIntro.jsx
  • web/classic/src/components/table/model-pricing/layout/header/PricingVendorIntroSkeleton.jsx
  • web/classic/src/components/table/model-pricing/layout/header/PricingVendorIntroWithSkeleton.jsx
  • web/classic/src/components/table/model-pricing/layout/header/SearchActions.jsx
  • web/classic/src/components/table/model-pricing/modal/ModelDetailSideSheet.jsx
  • web/classic/src/components/table/model-pricing/modal/PricingFilterModal.jsx
  • web/classic/src/components/table/model-pricing/modal/components/FilterModalContent.jsx
  • web/classic/src/components/table/model-pricing/modal/components/FilterModalFooter.jsx
  • web/classic/src/components/table/model-pricing/modal/components/ModelBasicInfo.jsx
  • web/classic/src/components/table/model-pricing/modal/components/ModelEndpoints.jsx
  • web/classic/src/components/table/model-pricing/modal/components/ModelHeader.jsx
  • web/classic/src/components/table/model-pricing/modal/components/ModelPricingTable.jsx
  • web/classic/src/components/table/model-pricing/view/card/PricingCardSkeleton.jsx
  • web/classic/src/components/table/model-pricing/view/card/PricingCardView.jsx
  • web/classic/src/components/table/model-pricing/view/table/PricingTable.jsx
  • web/classic/src/components/table/model-pricing/view/table/PricingTableColumns.jsx
  • web/classic/src/components/table/models/ModelsActions.jsx
  • web/classic/src/components/table/models/ModelsColumnDefs.jsx
  • web/classic/src/components/table/models/ModelsDescription.jsx
  • web/classic/src/components/table/models/ModelsFilters.jsx
  • web/classic/src/components/table/models/ModelsTable.jsx
  • web/classic/src/components/table/models/ModelsTabs.jsx
  • web/classic/src/components/table/models/components/SelectionNotification.jsx
  • web/classic/src/components/table/models/index.jsx
  • web/classic/src/components/table/models/modals/EditModelModal.jsx
  • web/classic/src/components/table/models/modals/EditPrefillGroupModal.jsx
  • web/classic/src/components/table/models/modals/EditVendorModal.jsx
  • web/classic/src/components/table/models/modals/MissingModelsModal.jsx
  • web/classic/src/components/table/models/modals/PrefillGroupManagement.jsx
  • web/classic/src/components/table/models/modals/SyncWizardModal.jsx
  • web/classic/src/components/table/models/modals/UpstreamConflictModal.jsx
  • web/classic/src/components/table/redemptions/RedemptionsActions.jsx
  • web/classic/src/components/table/redemptions/RedemptionsColumnDefs.jsx
  • web/classic/src/components/table/redemptions/RedemptionsDescription.jsx
  • web/classic/src/components/table/redemptions/RedemptionsFilters.jsx
  • web/classic/src/components/table/redemptions/RedemptionsTable.jsx
  • web/classic/src/components/table/redemptions/index.jsx
  • web/classic/src/components/table/redemptions/modals/DeleteRedemptionModal.jsx
  • web/classic/src/components/table/redemptions/modals/EditRedemptionModal.jsx
  • web/classic/src/components/table/subscriptions/SubscriptionsActions.jsx
  • web/classic/src/components/table/subscriptions/SubscriptionsColumnDefs.jsx
  • web/classic/src/components/table/subscriptions/SubscriptionsDescription.jsx
  • web/classic/src/components/table/subscriptions/SubscriptionsTable.jsx
  • web/classic/src/components/table/subscriptions/index.jsx
  • web/classic/src/components/table/subscriptions/modals/AddEditSubscriptionModal.jsx
  • web/classic/src/components/table/task-logs/TaskLogsActions.jsx
  • web/classic/src/components/table/task-logs/TaskLogsColumnDefs.jsx
  • web/classic/src/components/table/task-logs/TaskLogsFilters.jsx
  • web/classic/src/components/table/task-logs/TaskLogsTable.jsx
  • web/classic/src/components/table/task-logs/index.jsx
  • web/classic/src/components/table/task-logs/modals/AudioPreviewModal.jsx
  • web/classic/src/components/table/task-logs/modals/ColumnSelectorModal.jsx
  • web/classic/src/components/table/task-logs/modals/ContentModal.jsx
  • web/classic/src/components/table/tokens/TokensActions.jsx
  • web/classic/src/components/table/tokens/TokensColumnDefs.jsx
  • web/classic/src/components/table/tokens/TokensDescription.jsx
  • web/classic/src/components/table/tokens/TokensFilters.jsx
  • web/classic/src/components/table/tokens/TokensTable.jsx
  • web/classic/src/components/table/tokens/index.jsx
  • web/classic/src/components/table/tokens/modals/CCSwitchModal.jsx
  • web/classic/src/components/table/tokens/modals/CopyTokensModal.jsx
  • web/classic/src/components/table/tokens/modals/DeleteTokensModal.jsx
  • web/classic/src/components/table/tokens/modals/EditTokenModal.jsx
  • web/classic/src/components/table/usage-logs/UsageLogsActions.jsx
  • web/classic/src/components/table/usage-logs/UsageLogsColumnDefs.jsx
  • web/classic/src/components/table/usage-logs/UsageLogsFilters.jsx
  • web/classic/src/components/table/usage-logs/UsageLogsTable.jsx
  • web/classic/src/components/table/usage-logs/components/ParamOverrideEntry.jsx
  • web/classic/src/components/table/usage-logs/index.jsx
  • web/classic/src/components/table/usage-logs/modals/ChannelAffinityUsageCacheModal.jsx
  • web/classic/src/components/table/usage-logs/modals/ColumnSelectorModal.jsx
  • web/classic/src/components/table/usage-logs/modals/ParamOverrideModal.jsx
  • web/classic/src/components/table/usage-logs/modals/UserInfoModal.jsx
  • web/classic/src/components/table/users/UsersActions.jsx
  • web/classic/src/components/table/users/UsersColumnDefs.jsx
  • web/classic/src/components/table/users/UsersDescription.jsx
  • web/classic/src/components/table/users/UsersFilters.jsx
  • web/classic/src/components/table/users/UsersTable.jsx
  • web/classic/src/components/table/users/index.jsx
  • web/classic/src/components/table/users/modals/AddUserModal.jsx
  • web/classic/src/components/table/users/modals/DeleteUserModal.jsx
  • web/classic/src/components/table/users/modals/DemoteUserModal.jsx
  • web/classic/src/components/table/users/modals/EditUserModal.jsx
  • web/classic/src/components/table/users/modals/EnableDisableUserModal.jsx
  • web/classic/src/components/table/users/modals/PromoteUserModal.jsx
  • web/classic/src/components/table/users/modals/ResetPasskeyModal.jsx
  • web/classic/src/components/table/users/modals/ResetTwoFAModal.jsx
  • web/classic/src/components/table/users/modals/UserBindingManagementModal.jsx
  • web/classic/src/components/table/users/modals/UserSubscriptionsModal.jsx
  • web/classic/src/components/topup/InvitationCard.jsx
  • web/classic/src/components/topup/RechargeCard.jsx
  • web/classic/src/components/topup/SubscriptionPlansCard.jsx
  • web/classic/src/components/topup/index.jsx
  • web/classic/src/components/topup/modals/PaymentConfirmModal.jsx
  • web/classic/src/components/topup/modals/SubscriptionPurchaseModal.jsx
  • web/classic/src/components/topup/modals/TopupHistoryModal.jsx
  • web/classic/src/components/topup/modals/TransferModal.jsx

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch v1

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@t0ng7u t0ng7u self-assigned this Apr 15, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR introduces a theme-aware dual-frontend setup (default + classic) with runtime switching, alongside several backend feature additions (theme config sync, OAuth providers, quota pre-consumption return, video task updates) and build/deployment workflow updates.

Changes:

  • Add backend-managed frontend theme selection and serve embedded assets for both default/classic themes at runtime.
  • Introduce/extend multiple controllers (OIDC/GitHub/Discord/LinuxDO OAuth, video task updater) and supporting model/service utilities.
  • Update build tooling and CI to build/embed both frontends; add dev Docker Compose + backend-only dev Dockerfile.

Reviewed changes

Copilot reviewed 96 out of 1336 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
web/classic/src/components/table/models/ModelsDescription.jsx Adds classic UI header/description for models table with compact toggle.
web/classic/src/components/settings/personal/cards/ModelsList.jsx Adds categorized model list UI with expand/collapse and skeleton/empty states.
web/classic/src/components/settings/OtherSetting.jsx Adds theme.frontend option UI + submit handler in classic settings.
web/classic/src/components/playground/index.js Adds barrel exports for playground components + config storage helpers.
web/classic/src/components/common/modals/TwoFactorAuthModal.jsx Introduces reusable 2FA modal UI.
web/classic/src/components/common/examples/ChannelKeyViewExample.jsx Example integration of SecureVerification flow for viewing channel keys.
web/classic/.gitignore Ignores /dist build output for classic frontend.
setting/system_setting/theme.go Adds theme settings registration and sync to common theme value.
service/pre_consume_quota.go Implements pre-consume quota logic and async return on failure.
router/web-router.go Serves theme-aware embedded static FS; chooses index.html by theme.
router/main.go Updates router wiring to pass ThemeAssets.
model/task.go Adds bulk update by upstream task_id strings.
model/option.go Syncs theme/performance settings after config updates.
makefile Builds both frontends; adds dev targets for API + both web themes.
main.go Embeds both default/classic dist folders; injects analytics into both index pages.
docker-compose.dev.yml Adds backend dev stack (Go build container + Redis + Postgres).
controller/task_video.go Adds video async task updater incl. parsing, redaction, and quota adjustments.
controller/option.go Validates theme.frontend option values (default/classic).
controller/oidc.go Adds OIDC OAuth login/bind flow.
controller/misc.go Exposes current theme in /status payload.
controller/linuxdo.go Adds LinuxDO OAuth login/bind flow.
controller/github.go Adds GitHub OAuth login/bind flow.
controller/discord.go Adds Discord OAuth login/bind flow.
common/embed-file-system.go Adds theme-aware FS wrapper selecting embedded assets by theme at runtime.
common/constants.go Stores theme in atomic.Value with getters/setters.
README.en.md Adds English README documentation.
Dockerfile.dev Adds backend-only dev image build (with embedded frontend placeholders).
Dockerfile Builds and embeds both default/classic frontends into final Go binary image.
CLAUDE.md Updates documented tech stack and frontend/i18n paths.
AGENTS.md Updates documented tech stack and frontend/i18n paths.
.github/workflows/release.yml Builds both frontends during release workflow.
.github/workflows/docker-build.yml Adds Docker build+push workflow.
.github/FUNDING.yml Adds funding configuration.
.cursor/skills/vercel-react-best-practices Adds Cursor skill pointer to repo skills.
.cursor/skills/i18n-translate/SKILL.md Adds i18n translation workflow documentation for default frontend.
.cursor/rules/ui-style.mdc Adds UI style guide rules for Cursor.
.cursor/rules/project.mdc Replaces/updates Cursor project guide to match new frontend setup.
.agents/skills/vercel-react-best-practices/** Adds performance best-practices reference documents.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread controller/task_video.go
t := responseItems.Data
taskResult.TaskID = t.TaskID
taskResult.Status = string(t.Status)
taskResult.Url = t.FailReason
Comment thread controller/task_video.go
Comment on lines +155 to +157
var taskData map[string]interface{}
if err := json.Unmarshal(task.Data, &taskData); err == nil {
if modelName, ok := taskData["model"].(string); ok && modelName != "" {
Comment thread controller/task_video.go
Comment on lines +281 to +305
func redactVideoResponseBody(body []byte) []byte {
var m map[string]any
if err := json.Unmarshal(body, &m); err != nil {
return body
}
resp, _ := m["response"].(map[string]any)
if resp != nil {
delete(resp, "bytesBase64Encoded")
if v, ok := resp["video"].(string); ok {
resp["video"] = truncateBase64(v)
}
if vs, ok := resp["videos"].([]any); ok {
for i := range vs {
if vm, ok := vs[i].(map[string]any); ok {
delete(vm, "bytesBase64Encoded")
}
}
}
}
b, err := json.Marshal(m)
if err != nil {
return body
}
return b
}
Comment thread controller/task_video.go
Comment on lines +99 to +106
logger.LogDebug(ctx, fmt.Sprintf("UpdateVideoSingleTask response: %s", string(responseBody)))

taskResult := &relaycommon.TaskInfo{}
// try parse as New API response format
var responseItems dto.TaskResponse[model.Task]
if err = common.Unmarshal(responseBody, &responseItems); err == nil && responseItems.IsSuccess() {
logger.LogDebug(ctx, fmt.Sprintf("UpdateVideoSingleTask parsed as new api response format: %+v", responseItems))
t := responseItems.Data
Comment on lines +43 to +51
const savedState = localStorage.getItem('modelsExpanded');
return savedState ? JSON.parse(savedState) : false;
});
const [activeModelCategory, setActiveModelCategory] = useState('all');
const MODELS_DISPLAY_COUNT = 25; // 默认显示的模型数量

// Save models expanded state to localStorage whenever it changes
useEffect(() => {
localStorage.setItem('modelsExpanded', JSON.stringify(isModelsExpanded));
Comment on lines +43 to +51
const savedState = localStorage.getItem('modelsExpanded');
return savedState ? JSON.parse(savedState) : false;
});
const [activeModelCategory, setActiveModelCategory] = useState('all');
const MODELS_DISPLAY_COUNT = 25; // 默认显示的模型数量

// Save models expanded state to localStorage whenever it changes
useEffect(() => {
localStorage.setItem('modelsExpanded', JSON.stringify(isModelsExpanded));
Comment thread Dockerfile.dev
@@ -0,0 +1,35 @@
# Backend-only build for frontend development
# Skips frontend build, uses a placeholder for //go:embed web/dist
t0ng7u added 5 commits April 15, 2026 21:07
…ti-key index and inference_geo scope

- Add `allow_speed` toggle for Anthropic (type 14) channels to control
  Claude inference speed mode passthrough, with full form schema,
  settings persistence, and UI switch
- Fix `allow_inference_geo` to also apply to Anthropic (type 14) channels,
  not just OpenAI (type 1), matching the backend behavior for Claude data
  residency region control
- Fix multi-key management dialog to display 1-based key indices instead
  of 0-based (#{key.index + 1})
- Fix TypeScript type error in section-registry by adding type assertion
  for theme.frontend enum
- Add i18n translations for all new keys across 6 locales (en, zh, fr,
  ja, ru, vi)
…lassic as default theme

- Add .cursor/ to .gitignore and remove tracked editor config files
  (.cursor/rules/, .cursor/skills/) from version control
- Consolidate .agents/skills/vercel-react-best-practices by keeping only
  the compiled AGENTS.md and removing redundant SKILL.md and 57 individual
  rule files under rules/
- Change default frontend theme from "default" to "classic" in both
  common/constants.go init and setting/system_setting/theme.go
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.