feat: Langfuse trace notice & fix theme redirect loop#6
Conversation
When Langfuse is enabled AND trace_content (full statistics) is enabled, display a warning banner on the Logs and Keys pages: '本站使用Langfuse记录用户提示词等数据,请注意安全。' - Add langfuse_trace_content field to /api/status public endpoint - Create LangfuseTraceNotice reusable component - Add notice to Usage Logs page - Add notice to API Keys page - Add i18n translations for en/zh/fr/ja/ru/vi
- Expand MapFrontendPath with complete classic<->default path mappings - Move path mapping logic from router to common/frontend_theme.go - Fix infinite redirect loop in classic theme UserProvider - Fix default theme auth redirect to only redirect for classic - Fix _authenticated route to redirect to /console for classic theme - Replace hardcoded /console/xxx paths with GetThemeAwarePath() in: - epay/stripe/waffo payment controllers - telegram bind controller - topup controllers - Fix hardcoded /console/xxx links in default frontend components: - channels-columns.tsx, channel-test-dialog.tsx, message-error.tsx - Remove duplicate setFrontendTheme from classic PageLayout
|
Caution Review failedPull request was closed or merged during review No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (22)
✅ Files skipped from review due to trivial changes (4)
📝 WalkthroughWalkthroughThis PR centralizes theme-aware frontend path routing in the backend, applies it across payment/topup handlers, refactors frontend theme navigation with safer redirect logic, adds Langfuse observability UI with security notices, and updates i18n across six languages. ChangesTheme routing and observability
🎯 3 (Moderate) | ⏱️ ~25 minutes
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Code Review
This pull request introduces theme-aware path mapping and redirection logic to maintain navigation consistency between the 'classic' and 'default' frontend themes. It also adds Langfuse LLM observability features, including a frontend notice component and backend status flags. Feedback focuses on correcting path mapping errors where missing trailing slashes would lead to broken sub-path URLs and resolving an inconsistency in the deployment route mapping. Additionally, several i18n entries in the English and other non-Chinese locale files need to be corrected as they currently contain untranslated Chinese text.
| } | ||
|
|
||
| var classicToDefaultPrefixes = []struct{ prefix, replacement string }{ | ||
| {"/console/chat/", "/playground"}, |
There was a problem hiding this comment.
| } | ||
|
|
||
| var defaultToClassicPrefixes = []struct{ prefix, replacement string }{ | ||
| {"/dashboard/", "/console"}, |
There was a problem hiding this comment.
| "/console/midjourney": "/usage-logs", | ||
| "/console/task": "/usage-logs", | ||
| "/console/models": "/models", | ||
| "/console/deployment": "/models", |
There was a problem hiding this comment.
Inconsistency detected: /console/deployment is mapped to /models here, but the frontend code in channels-columns.tsx (line 664) uses /models/deployments. Please update this mapping to match the actual frontend route.
| "/console/deployment": "/models", | |
| "/console/deployment": "/models/deployments", |
| "Configuration for Stripe payment integration": "Configuration for Stripe payment integration", | ||
| "Configuration required": "Configuration required", | ||
| "Configure": "Configure", | ||
| "Configure Langfuse LLM observability": "配置 Langfuse LLM 可观测性", |
| "Enable Langfuse Tracing": "启用 Langfuse 追踪", | ||
| "Include full prompt and completion content in traces. Disabling sends only token counts and metadata.": "在追踪中包含完整的提示词和补全内容。禁用时仅发送 Token 数量和元数据。", | ||
| "Langfuse Host": "Langfuse 地址", | ||
| "Langfuse server URL (cloud or self-hosted)": "Langfuse 服务器地址(云端或自托管)", | ||
| "Langfuse Tracing": "Langfuse 追踪", | ||
| "Public Key": "公钥", |
There was a problem hiding this comment.
These entries in the English locale file contain Chinese translations. They should be translated to English. This issue also appears in other non-Chinese locale files (fr, ja, ru, vi).
| "Enable Langfuse Tracing": "启用 Langfuse 追踪", | |
| "Include full prompt and completion content in traces. Disabling sends only token counts and metadata.": "在追踪中包含完整的提示词和补全内容。禁用时仅发送 Token 数量和元数据。", | |
| "Langfuse Host": "Langfuse 地址", | |
| "Langfuse server URL (cloud or self-hosted)": "Langfuse 服务器地址(云端或自托管)", | |
| "Langfuse Tracing": "Langfuse 追踪", | |
| "Public Key": "公钥", | |
| "Enable Langfuse Tracing": "Enable Langfuse Tracing", | |
| "Include full prompt and completion content in traces. Disabling sends only token counts and metadata.": "Include full prompt and completion content in traces. Disabling sends only token counts and metadata.", | |
| "Langfuse Host": "Langfuse Host", | |
| "Langfuse server URL (cloud or self-hosted)": "Langfuse server URL (cloud or self-hosted)", | |
| "Langfuse Tracing": "Langfuse Tracing", | |
| "Public Key": "Public Key", |
| "Interface Language": "Interface Language", | ||
| "Interface Style": "Interface Style", | ||
| "Interface style updated. Reloading...": "Interface style updated. Reloading...", | ||
| "Interface style updated. Redirecting...": "界面风格已更新,正在跳转...", |
| "Statistical quota": "Statistical quota", | ||
| "Statistical tokens": "Statistical tokens", | ||
| "Statistics reset": "Statistics reset", | ||
| "Statistics": "统计", |
There was a problem hiding this comment.
Actionable comments posted: 15
🧹 Nitpick comments (3)
common/frontend_theme.go (1)
99-125: ⚡ Quick winAdd table-driven tests for mapping edge cases.
This mapper is now a redirect critical path; add tests for exact mapping, prefix mapping, trailing slash normalization, and escaped paths to prevent regressions.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@common/frontend_theme.go` around lines 99 - 125, Add table-driven unit tests for MapFrontendPath to cover exact key mapping, prefix replacement, trailing-slash normalization and URL-escaped inputs so we catch regressions in the redirect hot path; create a test table that feeds various inputs to MapFrontendPath (including values that exercise normalizeMapPath, entries in defaultToClassicMap/classicToDefaultMap and prefixes in defaultToClassicPrefixes/classicToDefaultPrefixes) and assert expected outputs for theme="classic" and theme="default", including cases that should return "" for no-match; include cases for trailing slashes and percent-encoded paths to validate normalization and prefix handling.web/default/src/components/langfuse-trace-notice.tsx (1)
16-18: 💤 Low valueTranslation key uses full sentence instead of semantic identifier.
The translation key is a complete English sentence rather than a semantic key (e.g.,
'langfuse.trace.security_warning'). This pattern makes translations harder to maintain and update across locales.♻️ Consider using a semantic key
- {t( - 'This site uses Langfuse to record user prompts and other data. Please be aware of security risks.' - )} + {t('langfuse.trace.security_warning')}Then update locale files with the appropriate key-value pairs.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/default/src/components/langfuse-trace-notice.tsx` around lines 16 - 18, The translation call in langfuse-trace-notice.tsx uses a full English sentence as the key; change the t(...) invocation to use a semantic key like 'langfuse.trace.security_warning' (update the call site in the component where t(...) is used), then add the corresponding key/value entry to your locale JSON files for each language (e.g., "langfuse.trace.security_warning": "This site uses Langfuse to record user prompts and other data. Please be aware of security risks."). Ensure the new semantic key is used consistently wherever this message appears.controller/misc.go (1)
123-123: 💤 Low valueConsider caching the Langfuse setting call for readability.
The expression calls
GetLangfuseSetting()twice. While likely inexpensive, extracting to a local variable would improve readability.♻️ Optional refactor
+ langfuseSetting := langfuse_setting.GetLangfuseSetting() data := gin.H{ "version": common.Version, // ... other fields ... - "langfuse_trace_content": langfuse_setting.GetLangfuseSetting().Enabled && langfuse_setting.GetLangfuseSetting().TraceContent, + "langfuse_trace_content": langfuseSetting.Enabled && langfuseSetting.TraceContent, }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@controller/misc.go` at line 123, Assign the result of langfuse_setting.GetLangfuseSetting() to a local variable (e.g., lf := langfuse_setting.GetLangfuseSetting()) and then use lf.Enabled && lf.TraceContent for the "langfuse_trace_content" assignment to avoid calling GetLangfuseSetting() twice and improve readability; update the expression in the controller/misc.go block that currently uses langfuse_setting.GetLangfuseSetting() && langfuse_setting.GetLangfuseSetting().TraceContent accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@common/frontend_theme.go`:
- Around line 65-77: The prefix-rewrite arrays classicToDefaultPrefixes and
defaultToClassicPrefixes contain two replacement strings missing the trailing
slash, causing nested routes to merge (e.g., "/console/chat/abc" →
"/playgroundabc"). Update the replacement values so they preserve the separator:
in classicToDefaultPrefixes change the replacement for prefix "/console/chat/"
from "/playground" to "/playground/" and in defaultToClassicPrefixes change the
replacement for prefix "/dashboard/" from "/console" to "/console/"; keep other
entries unchanged so nested paths remain valid.
In `@web/classic/src/context/User/index.jsx`:
- Around line 32-33: The module-scoped mutable object themeRedirectAttempted
persists across component lifetimes and should be replaced with a per-instance
React ref: inside the UserProvider component create a ref via useRef (e.g.,
const themeRedirectAttemptedRef = useRef(false)) and replace all reads/writes of
themeRedirectAttempted.current with themeRedirectAttemptedRef.current so the
flag resets when UserProvider unmounts/remounts; update any imports/usages in
this file to reference the ref variable rather than the module-scoped
themeRedirectAttempted.
- Around line 63-66: UserContext's automatic redirect to '/dashboard' (in
web/classic/src/context/User/index.jsx using themeRedirectAttempted.current)
conflicts with the delayed navigation from PreferencesSettings
(PreferencesSettings.jsx calling getFrontendThemeSettingsPath('default') after
300ms); fix by introducing a shared "theme navigation pending" flag that
PreferencesSettings sets before scheduling its navigation and clears after
navigation completes, and have UserContext check that flag (skip its
'/dashboard' redirect when set) or use a small public API on UserContext (e.g.,
startThemeNavigation()/endThemeNavigation) so only one redirect runs per theme
change.
In `@web/default/src/features/auth/hooks/use-auth-redirect.ts`:
- Around line 92-93: In use-auth-redirect.ts, the savedTheme === 'classic'
branch currently calls window.location.assign('/console'); change this to
window.location.replace('/console') so the redirect does not preserve the
current page in browser history; update the savedTheme check in the redirect
logic (the function handling post-auth redirect in useAuthRedirect hook) to use
replace for consistency with _authenticated/route.tsx.
In `@web/default/src/features/channels/components/channels-columns.tsx`:
- Around line 664-666: The deep-link currently always builds targetUrl as
`/models/deployments?deployment_id=${deploymentId}` which the default theme
ignores and the classic theme expects a different path; update the onClick in
ChannelsColumns (where targetUrl and window.open are used) to branch on theme:
if classic theme, open `/console/deployment?deployment_id=${deploymentId}`,
otherwise open a route the default theme will honor (use a path segment with the
id, e.g. `/models/deployments/${deploymentId}` or the app's canonical deployment
route that accepts an id); detect theme via the existing theme flag/prop (e.g.
isClassicTheme or theme.name) and set targetUrl accordingly before calling
window.open.
In
`@web/default/src/features/channels/components/dialogs/channel-test-dialog.tsx`:
- Around line 355-356: The window.open call inside the ChannelTestDialog
component currently uses window.open('/system-settings?tab=ratio', '_blank')
which leaves window.opener available; update that call to include the third
parameter to prevent access from the opened page (e.g. use
window.open('/system-settings?tab=ratio', '_blank', 'noopener') or
'noopener,noreferrer') so the new window cannot access window.opener.
In `@web/default/src/features/playground/components/message-error.tsx`:
- Around line 42-43: The window.open call in message-error.tsx (inside the
component handling the ratio settings link) should include the 'noopener'
feature to prevent the newly opened page from accessing window.opener; update
the window.open('/system-settings?tab=ratio', '_blank') invocation to pass a
features string that includes 'noopener' (e.g. third argument 'noopener' or
'noopener,noreferrer' as appropriate) so the opened page cannot manipulate the
parent window.
In `@web/default/src/i18n/locales/en.json`:
- Line 744: Several entries in en.json were accidentally replaced with Chinese;
restore the English strings so the English locale shows correct UI text. Find
the key "Configure Langfuse LLM observability" (and the other entries that were
changed to Chinese in this file) and replace their values with the original
English phrases, keeping the keys unchanged; after updating, run the
i18n/localization check or build to verify no missing/invalid English strings
remain.
In `@web/default/src/i18n/locales/fr.json`:
- Line 403: The French locale file contains untranslated English strings;
replace the English value for the key "Automatically bind this subscription plan
to new users upon registration" in fr.json (and the duplicate at the other
occurrence) with the correct French translation, ensuring the JSON string
remains valid and preserves surrounding punctuation and spacing; search for the
exact English phrase to find both occurrences and update them to the proper
French text.
- Line 744: The fr.json contains Chinese values instead of French for keys like
"Configure Langfuse LLM observability" (and other occurrences flagged in the
review); update each Chinese string to an accurate French translation for the
corresponding JSON keys (search fr.json for any values containing Chinese
characters or keys shown in the review) so the French locale is fully French,
keep the JSON key names intact, preserve surrounding punctuation/escaping, and
run the i18n/lint check to ensure encoding and formatting remain valid before
committing.
In `@web/default/src/i18n/locales/ja.json`:
- Line 403: Replace the untranslated English values in the Japanese locale JSON:
update the value "Automatically bind this subscription plan to new users upon
registration" to its Japanese translation and update "Initial Subscription Plan"
to its Japanese translation in the ja.json file (they currently appear as
English values); locate the JSON entries by those exact English strings and
replace their values with the correct Japanese text, preserving the JSON key
structure and quoting/commas.
- Line 744: Several values in the Japanese locale file are written in Chinese
(e.g., the value for "Configure Langfuse LLM observability", the Langfuse
settings block around lines 1254–1259, "追踪请求/响应内容", the Langfuse trace
descriptions, and "统计"); update each of those translation values in
web/default/src/i18n/locales/ja.json to proper Japanese equivalents (replace "配置
Langfuse LLM 可观测性" and the other Chinese strings with correct Japanese
translations), keep existing correct entries like "シークレットキー" untouched, and run
your i18n/lint validation to ensure no other non-Japanese strings remain.
In `@web/default/src/i18n/locales/ru.json`:
- Line 403: Two locale entries remain in English and must be translated into
Russian: update the string value for the key "Automatically bind this
subscription plan to new users upon registration" (and the other identical
English key found later in the file) to a proper Russian translation; locate
these keys in ru.json and replace the English text with the Russian equivalent
while keeping the JSON key intact and preserving punctuation and formatting.
- Line 744: Several values in the Russian locale file are still Chinese; replace
any Chinese value strings with proper Russian translations — for example change
the value for the key "Configure Langfuse LLM observability" to a Russian string
like "Настроить наблюдение за LLM Langfuse" and similarly update the other
Chinese-valued entries referenced (the entries around the block at lines
1254–1261, the key at line 1893, the two keys at 3245–3246, and the key at 3371)
so all values in ru.json are Russian.
In `@web/default/src/i18n/locales/vi.json`:
- Line 403: The Vietnamese locale file contains untranslated/mixed-language
entries (e.g., the key whose value is "Automatically bind this subscription plan
to new users upon registration" and other entries flagged at lines referenced in
the review); update those values to proper Vietnamese translations by replacing
the English/Chinese strings in vi.json with their Vietnamese equivalents,
ensuring you modify the exact locale keys shown (use the exact string values as
identifiers to locate entries) and keep the JSON formatting and quotes intact so
the locale file remains valid.
---
Nitpick comments:
In `@common/frontend_theme.go`:
- Around line 99-125: Add table-driven unit tests for MapFrontendPath to cover
exact key mapping, prefix replacement, trailing-slash normalization and
URL-escaped inputs so we catch regressions in the redirect hot path; create a
test table that feeds various inputs to MapFrontendPath (including values that
exercise normalizeMapPath, entries in defaultToClassicMap/classicToDefaultMap
and prefixes in defaultToClassicPrefixes/classicToDefaultPrefixes) and assert
expected outputs for theme="classic" and theme="default", including cases that
should return "" for no-match; include cases for trailing slashes and
percent-encoded paths to validate normalization and prefix handling.
In `@controller/misc.go`:
- Line 123: Assign the result of langfuse_setting.GetLangfuseSetting() to a
local variable (e.g., lf := langfuse_setting.GetLangfuseSetting()) and then use
lf.Enabled && lf.TraceContent for the "langfuse_trace_content" assignment to
avoid calling GetLangfuseSetting() twice and improve readability; update the
expression in the controller/misc.go block that currently uses
langfuse_setting.GetLangfuseSetting() &&
langfuse_setting.GetLangfuseSetting().TraceContent accordingly.
In `@web/default/src/components/langfuse-trace-notice.tsx`:
- Around line 16-18: The translation call in langfuse-trace-notice.tsx uses a
full English sentence as the key; change the t(...) invocation to use a semantic
key like 'langfuse.trace.security_warning' (update the call site in the
component where t(...) is used), then add the corresponding key/value entry to
your locale JSON files for each language (e.g.,
"langfuse.trace.security_warning": "This site uses Langfuse to record user
prompts and other data. Please be aware of security risks."). Ensure the new
semantic key is used consistently wherever this message appears.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: f1c76e1a-2de5-4a43-b95b-bd2d5a65b44c
📒 Files selected for processing (31)
common/frontend_theme.gocontroller/misc.gocontroller/subscription_payment_epay.gocontroller/subscription_payment_stripe.gocontroller/telegram.gocontroller/topup.gocontroller/topup_stripe.gocontroller/topup_waffo.gocontroller/topup_waffo_pancake.gorouter/web-router.goweb/classic/src/components/layout/PageLayout.jsxweb/classic/src/context/User/index.jsxweb/default/src/components/langfuse-trace-notice.tsxweb/default/src/features/auth/hooks/use-auth-redirect.tsweb/default/src/features/channels/components/channels-columns.tsxweb/default/src/features/channels/components/dialogs/channel-test-dialog.tsxweb/default/src/features/keys/index.tsxweb/default/src/features/playground/components/message-error.tsxweb/default/src/features/usage-logs/index.tsxweb/default/src/i18n/locales/_reports/_sync-report.jsonweb/default/src/i18n/locales/_reports/fr.untranslated.jsonweb/default/src/i18n/locales/_reports/ja.untranslated.jsonweb/default/src/i18n/locales/_reports/ru.untranslated.jsonweb/default/src/i18n/locales/_reports/vi.untranslated.jsonweb/default/src/i18n/locales/en.jsonweb/default/src/i18n/locales/fr.jsonweb/default/src/i18n/locales/ja.jsonweb/default/src/i18n/locales/ru.jsonweb/default/src/i18n/locales/vi.jsonweb/default/src/i18n/locales/zh.jsonweb/default/src/routes/_authenticated/route.tsx
💤 Files with no reviewable changes (1)
- web/classic/src/components/layout/PageLayout.jsx
| const targetUrl = `/models/deployments?deployment_id=${deploymentId}` | ||
| window.open(targetUrl, '_blank', 'noopener') | ||
| }} |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Search for the deployments route definition
# Search for route definitions containing "deployments"
rg -n "deployments" --type=ts --type=tsx -g "**/*route*" -g "**/*router*" -C3Repository: CuzTeam/new-api
Length of output: 87
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Search for explicit path '/models/deployments' =="
rg -n "/models/deployments" -S -g "*.ts" -g "*.tsx" -C2 || true
echo
echo "== Search for path substring 'models/deployments' =="
rg -n "models/deployments" -S -g "*.ts" -g "*.tsx" -C2 || true
echo
echo "== Search for deployment_id usage around deployments route =="
rg -n "deployment_id" -S -g "*.ts" -g "*.tsx" -C2 || true
echo
echo "== Search for route/router definitions referencing 'deployments' =="
rg -n "deployments" -S -g "*.ts" -g "*.tsx" -g "*route*" -g "*router*" -C3 || trueRepository: CuzTeam/new-api
Length of output: 50371
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== deployment_id usage in models UI =="
rg -n "deployment_id" web/default/src/features/models -S -g "*.ts" -g "*.tsx" || true
echo
echo "== '/models/deployments' usage in classic theme =="
rg -n "/models/deployments" -S -g "*.ts" -g "*.tsx" web/classic || true
echo
echo "== deployments route definition files in default theme =="
rg -n "'deployments'|models/deployments|_authenticated/models" -S -g "*.ts" -g "*.tsx" web/default/src/features/models web/default/src -C1 || trueRepository: CuzTeam/new-api
Length of output: 8453
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Inspect default route handler for /_authenticated/models/$section =="
ls -la web/default/src/routes/_authenticated/models || true
wc -l web/default/src/routes/_authenticated/models/\$section.tsx web/default/src/routes/_authenticated/models/index.tsx 2>/dev/null || true
sed -n '1,200p' web/default/src/routes/_authenticated/models/\$section.tsx
echo "----"
sed -n '1,200p' web/default/src/routes/_authenticated/models/index.tsx
echo
echo "== Search for deployment_id usage in the default route chain =="
rg -n "deployment[_-]?id" web/default/src/routes/_authenticated/models -S --glob "*.ts" --glob "*.tsx" || true
rg -n "deployment[_-]?id" web/default/src/features/models -S --glob "*.ts" --glob "*.tsx" || true
rg -n "searchParams|query|location|useSearchParams|useLocation" web/default/src/routes/_authenticated/models/\$section.tsx -S --glob "*.ts" --glob "*.tsx" || true
echo
echo "== Check classic theme for equivalent /models/$section route =="
rg -n "/models/\\$section|/_authenticated/models|models/\\$section" web/classic -S --glob "*.ts" --glob "*.tsx" || true
echo
echo "== Classic theme: direct usage of '/models/deployments' =="
rg -n "/models/deployments" web/classic -S --glob "*.ts" --glob "*.tsx" || trueRepository: CuzTeam/new-api
Length of output: 104
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Inspect default route handler files =="
ls -la web/default/src/routes/_authenticated/models || true
echo
echo "== File: web/default/src/routes/_authenticated/models/\$section.tsx =="
wc -l 'web/default/src/routes/_authenticated/models/$section.tsx' || true
sed -n '1,220p' 'web/default/src/routes/_authenticated/models/$section.tsx'
echo
echo "== File: web/default/src/routes/_authenticated/models/index.tsx =="
wc -l web/default/src/routes/_authenticated/models/index.tsx || true
sed -n '1,220p' web/default/src/routes/_authenticated/models/index.tsx
echo
echo "== Search default route code for deployment_id / query params =="
rg -n "deployment[_-]?id|searchParams|useSearchParams|query\\.|location\\.search" \
web/default/src/routes/_authenticated/models -S --glob "*.ts" --glob "*.tsx" || true
echo
echo "== Check classic theme for models section route equivalents =="
rg -n "(_authenticated/models|/models/\\$section|/models/deployments)" \
web/classic -S --glob "*.ts" --glob "*.tsx" || true
echo
echo "== Check if classic theme references deployment_id query param =="
rg -n "deployment[_-]?id" web/classic -S --glob "*.ts" --glob "*.tsx" || trueRepository: CuzTeam/new-api
Length of output: 2781
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Search for 'deployment_id' handling in web/default =="
rg -n "deployment_id" web/default/src -S --glob "*.ts" --glob "*.tsx" || true
echo
echo "== Search for deployment query param usage in web/default (deploymentId / deployment-id) =="
rg -n "deployment[-_]id|deploymentId" web/default/src -S --glob "*.ts" --glob "*.tsx" || true
echo
echo "== Classic theme: search for /models/deployments or models/$section route files =="
rg -n "/models/deployments|_authenticated/models|models/\\$section" web/classic -S --glob "*.ts" --glob "*.tsx" || true
echo
echo "== Classic theme: find any models route definitions (file name patterns) =="
fd -t f -e ts -e tsx -e js -e jsx -a "models" web/classic/src 2>/dev/null | head -n 50 || true
echo
echo "== Default theme: confirm /models/deployments section is registered =="
rg -n "'deployments'|MODELS_SECTION_IDS|models/\\$section|/_authenticated/models" web/default/src/features/models -S --glob "*.ts" --glob "*.tsx" || trueRepository: CuzTeam/new-api
Length of output: 9042
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Classic theme: list route-related files under web/classic/src (shallow) =="
ls -la web/classic/src 2>/dev/null | head || true
fd -t f -a "route" web/classic/src 2>/dev/null | head -n 50 || true
echo
echo "== Classic theme: search for '/models/deployments' usage =="
rg -n "/models/deployments" web/classic/src -S --glob "*.ts" --glob "*.tsx" --glob "*.js" --glob "*.jsx" || true
echo
echo "== Classic theme: search for 'deployments' section under models routes =="
rg -n "models.*deployments|deployments.*models|/models/.*deployments|models/\\$section" \
web/classic/src -S --glob "*.ts" --glob "*.tsx" --glob "*.js" --glob "*.jsx" || true
echo
echo "== Classic theme: search for deployment_id query handling =="
rg -n "deployment[_-]?id|deploymentId" web/classic/src -S --glob "*.ts" --glob "*.tsx" --glob "*.js" --glob "*.jsx" || trueRepository: CuzTeam/new-api
Length of output: 870
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Default theme: does models UI read deployment_id from URL/search params? =="
rg -n "useSearchParams|useLocation\\(|searchParams|get\\(.*deployment|deployment[_-]?id" \
web/default/src/features/models -S --glob "*.ts" --glob "*.tsx" || true
echo
echo "== Default theme: does routes/_authenticated/models validate/allow deployment_id? =="
rg -n "validateSearch|modelsSearchSchema|deployment[_-]?id" \
web/default/src/routes/_authenticated/models -S --glob "*.ts" --glob "*.tsx" || true
echo
echo "== Classic theme: any route/path definition containing '/models' or '/models/' =="
rg -n "\"/models|'/models|/models/:" web/classic/src -S --glob "*.js" --glob "*.jsx" --glob "*.ts" --glob "*.tsx" || true
echo
echo "== Classic theme: any '/models/deployments' literal usage anywhere =="
rg -n "/models/deployments" web/classic/src -S --glob "*.js" --glob "*.jsx" --glob "*.ts" --glob "*.tsx" || true
echo
echo "== Classic theme: any 'deployments' route/section routing =="
rg -n "models.*deployments|deployments.*models|/models.*deployments" \
web/classic/src -S --glob "*.js" --glob "*.jsx" --glob "*.ts" --glob "*.tsx" || trueRepository: CuzTeam/new-api
Length of output: 2182
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Default theme: inspect Models component to see if it reads search params / deployment_id =="
sed -n '1,240p' web/default/src/features/models/index.tsx
echo "----"
sed -n '1,260p' web/default/src/features/models/components/deployments-table.tsx
echo "----"
rg -n "deployment[_-]?id|useSearchParams|searchParams|location\\.search|query\\." \
web/default/src/features/models/index.tsx web/default/src/features/models/components/deployments-table.tsx \
-S --glob "*.ts" --glob "*.tsx" || true
echo
echo "== Classic theme: search for deep-link target and query param usage =="
rg -n "models/deployments" web/classic/src -S --glob "*.js" --glob "*.jsx" --glob "*.ts" --glob "*.tsx" || true
rg -n "deployment[_-]?id" web/classic/src -S --glob "*.js" --glob "*.jsx" --glob "*.ts" --glob "*.tsx" || true
echo
echo "== Classic theme: search for any '/models' strings in routing or navigation =="
rg -n "'/models|\"/models|/models/" web/classic/src -S --glob "*.js" --glob "*.jsx" --glob "*.ts" --glob "*.tsx" || true
echo
echo "== Classic theme: search for models section terms that might indicate routing =="
rg -n "models|deployments" web/classic/src -S --glob "*.js" --glob "*.jsx" --glob "*.ts" --glob "*.tsx" --max-count 200 || trueRepository: CuzTeam/new-api
Length of output: 50372
Fix deep-link behavior for /models/deployments?deployment_id=...
- In the default theme,
/models/deploymentsresolves to thedeploymentssection, butdeployment_idis not handled: the/ _authenticated/models/$sectionsearch schema and the deployments-table URL state only accept paging/filter fields (so the query param is ignored). - In the classic theme, there’s no
/models/deploymentsroute usage; deployment deep-links go to/console/deployment?deployment_id=...instead—adjust the target URL per theme if deployment-specific navigation is required.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@web/default/src/features/channels/components/channels-columns.tsx` around
lines 664 - 666, The deep-link currently always builds targetUrl as
`/models/deployments?deployment_id=${deploymentId}` which the default theme
ignores and the classic theme expects a different path; update the onClick in
ChannelsColumns (where targetUrl and window.open are used) to branch on theme:
if classic theme, open `/console/deployment?deployment_id=${deploymentId}`,
otherwise open a route the default theme will honor (use a path segment with the
id, e.g. `/models/deployments/${deploymentId}` or the app's canonical deployment
route that accepts an id); detect theme via the existing theme flag/prop (e.g.
isClassicTheme or theme.name) and set targetUrl accordingly before calling
window.open.
- Fix /console/deployment mapping to /models/deployments (not /models) - Fix missing trailing slash in prefix replacements: - /dashboard/ -> /console/ (was /console, causing /consolesomething) - /console/chat/ -> /playground/ (was /playground, causing /playgroundxxx) - Fix en.json: replace Chinese translations with English - Fix fr/ja/ru/vi.json: replace Chinese translations with proper translations
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (2)
web/default/src/i18n/locales/ja.json (2)
1877-1877:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winCritical: Untranslated English string in Japanese locale.
Line 1877 contains English text that must be translated to Japanese:
"Initial Subscription Plan"All translation values in
ja.jsonmust be in Japanese for users to see the correct language.Suggested Japanese translation
- "Initial Subscription Plan": "Initial Subscription Plan", + "Initial Subscription Plan": "初期サブスクリプションプラン",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/default/src/i18n/locales/ja.json` at line 1877, Replace the English value for the JSON key "Initial Subscription Plan" in ja.json with a Japanese translation so the Japanese locale contains only Japanese text; locate the entry with the key "Initial Subscription Plan" (currently: "Initial Subscription Plan") and change its value to a proper Japanese string such as "初期サブスクリプションプラン".
403-403:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winCritical: Untranslated English string in Japanese locale.
Line 403 contains English text that must be translated to Japanese:
"Automatically bind this subscription plan to new users upon registration"All translation values in
ja.jsonmust be in Japanese for users to see the correct language.Suggested Japanese translation
- "Automatically bind this subscription plan to new users upon registration": "Automatically bind this subscription plan to new users upon registration", + "Automatically bind this subscription plan to new users upon registration": "登録時に新規ユーザーにこのサブスクリプションプランを自動的に紐付ける",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/default/src/i18n/locales/ja.json` at line 403, Replace the untranslated English value for the key "Automatically bind this subscription plan to new users upon registration" in the ja.json locale with a Japanese translation; locate the exact string in the file and set its value to a natural Japanese phrase (e.g., "登録時に新しいユーザーにこのサブスクリプションプランを自動的に紐付ける") so all entries in ja.json are in Japanese.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@common/frontend_theme.go`:
- Line 43: The route map is missing an exact reverse mapping for the deployment
path so "/models/deployments" falls through to the generic "/models/" rule; add
an exact entry mapping "/models/deployments" -> "/console/deployment" in the
same routing map (the map that contains the existing "/console/deployment":
"/models/deployments" entry) so requests to "/models/deployments" are rewritten
back to the exact console deployment route rather than the generic models
prefix.
---
Duplicate comments:
In `@web/default/src/i18n/locales/ja.json`:
- Line 1877: Replace the English value for the JSON key "Initial Subscription
Plan" in ja.json with a Japanese translation so the Japanese locale contains
only Japanese text; locate the entry with the key "Initial Subscription Plan"
(currently: "Initial Subscription Plan") and change its value to a proper
Japanese string such as "初期サブスクリプションプラン".
- Line 403: Replace the untranslated English value for the key "Automatically
bind this subscription plan to new users upon registration" in the ja.json
locale with a Japanese translation; locate the exact string in the file and set
its value to a natural Japanese phrase (e.g.,
"登録時に新しいユーザーにこのサブスクリプションプランを自動的に紐付ける") so all entries in ja.json are in
Japanese.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: f713274a-ff30-4509-8cb1-ca8233f52fdf
📒 Files selected for processing (7)
common/frontend_theme.goweb/default/src/i18n/locales/_reports/_sync-report.jsonweb/default/src/i18n/locales/en.jsonweb/default/src/i18n/locales/fr.jsonweb/default/src/i18n/locales/ja.jsonweb/default/src/i18n/locales/ru.jsonweb/default/src/i18n/locales/vi.json
| "/console/midjourney": "/usage-logs", | ||
| "/console/task": "/usage-logs", | ||
| "/console/models": "/models", | ||
| "/console/deployment": "/models/deployments", |
There was a problem hiding this comment.
Add the missing reverse mapping for deployment routes.
Line 43 adds /console/deployment -> /models/deployments, but there is no exact reverse entry. In classic theme, /models/deployments currently falls through to the generic /models/ prefix and rewrites to /console/models/deployments, which is inconsistent and can send users to the wrong route.
Suggested fix
var defaultToClassicMap = map[string]string{
"/dashboard": "/console",
"/profile": "/console/personal",
"/channels": "/console/channel",
"/keys": "/console/token",
+ "/models/deployments": "/console/deployment",
"/models": "/console/models",
"/usage-logs": "/console/log",
"/system-settings": "/console/setting",
"/playground": "/console/playground",
"/wallet": "/console/topup",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@common/frontend_theme.go` at line 43, The route map is missing an exact
reverse mapping for the deployment path so "/models/deployments" falls through
to the generic "/models/" rule; add an exact entry mapping "/models/deployments"
-> "/console/deployment" in the same routing map (the map that contains the
existing "/console/deployment": "/models/deployments" entry) so requests to
"/models/deployments" are rewritten back to the exact console deployment route
rather than the generic models prefix.
- Fix classic UserProvider: use useRef instead of module-scoped mutable - Fix theme redirect conflict: add startThemeNavigation() API to UserContext so PreferencesSettings can signal pending navigation - Fix use-auth-redirect.ts: use replace() instead of assign() for classic theme redirect - Fix window.open security: add 'noopener' to channel-test-dialog and message-error - Fix controller/misc.go: use local variable for GetLangfuseSetting() - Fix fr/ja/ru/vi.json: translate 'Automatically bind this subscription plan' and 'Initial Subscription Plan' entries
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@web/classic/src/context/User/index.jsx`:
- Around line 37-41: UserContext’s default value is an object but UserProvider
supplies a tuple/array [state, dispatch, startThemeNavigation] and consumers
destructure it as an array; change the UserContext default to the same tuple
shape (e.g., [initialState, () => null, () => {}]) so components using
useContext(UserContext) and array-destructuring (e.g., const [userState]) won’t
throw when rendered outside UserProvider; update the export const UserContext =
React.createContext(...) to provide that array-shaped default matching
UserProvider and referencing initialState and startThemeNavigation names.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 4268973f-60c9-49d9-b8c2-dc4851dacedd
📒 Files selected for processing (11)
.gitignorecontroller/misc.goweb/classic/src/components/settings/personal/cards/PreferencesSettings.jsxweb/classic/src/context/User/index.jsxweb/default/src/features/auth/hooks/use-auth-redirect.tsweb/default/src/features/channels/components/dialogs/channel-test-dialog.tsxweb/default/src/features/playground/components/message-error.tsxweb/default/src/i18n/locales/fr.jsonweb/default/src/i18n/locales/ja.jsonweb/default/src/i18n/locales/ru.jsonweb/default/src/i18n/locales/vi.json
✅ Files skipped from review due to trivial changes (1)
- .gitignore
| export const UserContext = React.createContext({ | ||
| state: initialState, | ||
| dispatch: () => null, | ||
| startThemeNavigation: () => {}, | ||
| }); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE="web/classic/src/context/User/index.jsx"
if [ ! -f "$FILE" ]; then
echo "Missing file: $FILE" >&2
exit 1
fi
nl -ba "$FILE" | sed -n '1,140p'Repository: CuzTeam/new-api
Length of output: 102
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE="web/classic/src/context/User/index.jsx"
ls -la "$FILE" >/dev/null
echo "=== $FILE (lines 1-120) ==="
sed -n '1,120p' "$FILE"
echo "=== $FILE (lines 60-110) ==="
sed -n '60,110p' "$FILE"
echo "=== $FILE (lines 30-50) ==="
sed -n '30,50p' "$FILE"Repository: CuzTeam/new-api
Length of output: 4681
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n "UserContext" web/classic/src | head -n 200Repository: CuzTeam/new-api
Length of output: 3130
🏁 Script executed:
#!/bin/bash
set -euo pipefail
sed -n '70,110p' web/classic/src/pages/Playground/index.jsx
echo "----"
sed -n '20,70p' web/classic/src/hooks/model-pricing/useModelPricingData.jsx
echo "----"
sed -n '35,80p' web/classic/src/components/layout/PageLayout.jsxRepository: CuzTeam/new-api
Length of output: 5133
Align UserContext default value with the provider tuple shape.
UserProvider supplies value={[state, dispatch, startThemeNavigation]}, but UserContext’s default is an object. Components destructure it as an array (e.g., const [userState] = useContext(UserContext)), which can throw when rendered outside UserProvider (object is not iterable).
💡 Minimal fix
-export const UserContext = React.createContext({
- state: initialState,
- dispatch: () => null,
- startThemeNavigation: () => {},
-});
+export const UserContext = React.createContext([
+ initialState,
+ () => null,
+ () => {},
+]);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@web/classic/src/context/User/index.jsx` around lines 37 - 41, UserContext’s
default value is an object but UserProvider supplies a tuple/array [state,
dispatch, startThemeNavigation] and consumers destructure it as an array; change
the UserContext default to the same tuple shape (e.g., [initialState, () =>
null, () => {}]) so components using useContext(UserContext) and
array-destructuring (e.g., const [userState]) won’t throw when rendered outside
UserProvider; update the export const UserContext = React.createContext(...) to
provide that array-shaped default matching UserProvider and referencing
initialState and startThemeNavigation names.
…napping - Fix OAuth window.open calls in default theme (oauth.ts): GitHub, Discord, OIDC, LinuxDO - Fix OAuth window.open in classic theme (api.js): redirectToOAuthUrl - Fix payment window.open calls: use-waffo-payment, use-payment, use-creem-payment, subscription-purchase-dialog - Fix utility window.open calls: audio-preview-dialog, cc-switch-dialog, view-details-dialog, ionet-deployment-settings-section - Fix classic theme window.open calls: topup, SubscriptionPlansCard, CCSwitchModal, AudioPreviewModal, ContentModal, ViewLogsModal, ModelTestModal, MessageContent, MarkdownRenderer, useTokensData, SettingModelDeployment, Home
Changes
1. Langfuse 完整统计提示 (feat)
当 Langfuse 启用且完整统计(trace_content)同时开启时,在日志和 Keys 页面显示警告横幅:
本站使用Langfuse记录用户提示词等数据,请注意安全。
只开启统计不开启完整统计则不显示提示。
2. 主题重定向循环修复 (fix)
Summary by CodeRabbit
New Features
Bug Fixes / Improvements
Documentation
Chores