This commit is contained in:
ZyGuo committed 2026-06-01 17:29:30 +08:00
commit 5f88efb2c9
76 files changed
+11989 -4307

No files matched your search

+74 -24
View File
@@ -1,33 +1,44 @@
"use client";
'use client';
import { useParams, useRouter, useSearchParams } from "next/navigation";
import { useEffect, useMemo, useState } from "react";
import { useParams, useRouter, useSearchParams } from 'next/navigation';
import { useEffect, useMemo, useState } from 'react';
import { loginByUsername } from "@/core/auth/api";
import { setStoredAuth } from "@/core/auth";
import { useTheme } from '@/contexts/ThemeContext';
import { loginByUsername } from '@/core/auth/api';
import { setStoredAuth } from '@/core/auth';
import {
persistExternalLoginParams,
resolveThemeFromQuery,
} from '@/core/auth/external-login';
import {
GENERAL_QA_ROUTE,
loginByYUserId,
persistToolsToken,
} from '@/core/auth/yuser-login';
import {
isSidebarEnabledFromSearch,
persistSidebarEnabled,
} from "@/core/page-layout/sidebar-enabled";
} from '@/core/page-layout/sidebar-enabled';
const DEFAULT_USERNAME = "guest";
const IFRAME_LOGIN_SOURCE = "iframe";
const DEFAULT_REDIRECT_PATH = "/page/workspace/chats/new";
const IFRAME_REDIRECT_PATH = "/page/workspace/chats_iframe/new";
const DEFAULT_USERNAME = 'guest';
const IFRAME_LOGIN_SOURCE = 'iframe';
const DEFAULT_REDIRECT_PATH = '/page/workspace/chats/new';
const IFRAME_REDIRECT_PATH = '/page/workspace/chats_iframe/new';
type LoginStatus = "loading" | "success" | "error";
type LoginStatus = 'loading' | 'success' | 'error';
export default function LoginPage() {
const { username } = useParams<{ username?: string }>();
const router = useRouter();
const searchParams = useSearchParams();
const { setTheme } = useTheme();
const sidebarEnabled = useMemo(
() => isSidebarEnabledFromSearch(searchParams.toString()),
[searchParams],
);
const redirectPath = useMemo(
() =>
searchParams.get("from") === IFRAME_LOGIN_SOURCE
searchParams.get('from') === IFRAME_LOGIN_SOURCE
? IFRAME_REDIRECT_PATH
: DEFAULT_REDIRECT_PATH,
[searchParams],
@@ -36,31 +47,64 @@ export default function LoginPage() {
const raw = username?.trim();
return raw && raw.length > 0 ? raw : DEFAULT_USERNAME;
}, [username]);
const [status, setStatus] = useState<LoginStatus>("loading");
const [errorMessage, setErrorMessage] = useState<string>("");
// 外部跳转参数:theme 直接调 setTheme;ticket/userId/env 持久化到 localStorage
const yUserId = searchParams.get('yUserId')?.trim() ?? '';
const toolToken = searchParams.get('token')?.trim() ?? '';
const externalParams = useMemo(
() => ({
theme: searchParams.get('theme') ?? '',
ticket: searchParams.get('ticket') ?? '',
userId: searchParams.get('userId') ?? '',
env: searchParams.get('env') ?? '',
}),
[searchParams],
);
const [status, setStatus] = useState<LoginStatus>('loading');
const [errorMessage, setErrorMessage] = useState<string>('');
// 主题切换:theme=dark-blue → 深色,其他值或缺省 → 浅色
useEffect(() => {
if (!externalParams.theme) return;
setTheme(resolveThemeFromQuery(externalParams.theme));
}, [externalParams.theme, setTheme]);
// ticket / userId / env 持久化(与 login 请求并行做,互不阻塞)
useEffect(() => {
persistExternalLoginParams({
ticket: externalParams.ticket,
userId: externalParams.userId,
env: externalParams.env,
});
}, [externalParams.ticket, externalParams.userId, externalParams.env]);
useEffect(() => {
let cancelled = false;
async function runLogin() {
setStatus("loading");
setErrorMessage("");
setStatus('loading');
setErrorMessage('');
try {
if (yUserId) {
await loginByYUserId(yUserId, toolToken || null);
} else if (toolToken) {
persistToolsToken(toolToken);
}
const auth = await loginByUsername(resolvedUsername);
if (cancelled) {
return;
}
setStoredAuth(auth);
persistSidebarEnabled(sidebarEnabled);
setStatus("success");
router.replace(redirectPath);
setStatus('success');
router.replace(yUserId ? GENERAL_QA_ROUTE : redirectPath);
} catch (error) {
if (cancelled) {
return;
}
setStatus("error");
setStatus('error');
setErrorMessage(
error instanceof Error ? error.message : "Login request failed.",
error instanceof Error ? error.message : 'Login request failed.',
);
}
}
@@ -69,19 +113,25 @@ export default function LoginPage() {
return () => {
cancelled = true;
};
}, [redirectPath, resolvedUsername, router, sidebarEnabled]);
}, [
redirectPath,
resolvedUsername,
router,
sidebarEnabled,
yUserId,
toolToken,
]);
return (
<div className="flex min-h-screen items-center justify-center bg-background px-6">
<div className="w-full max-w-lg rounded-xl border bg-card p-6 shadow-sm">
<h1 className="text-xl font-semibold">正在进入智能体模式</h1>
{status === "error" && (
{status === 'error' && (
<p className="mt-4 text-sm text-red-600">
登录失败:{errorMessage || "未知错误"}
登录失败:{errorMessage || '未知错误'}
</p>
)}
</div>
</div>
);
}
+11 -2
View File
@@ -36,8 +36,16 @@ function PageLayout() {
)
)}
<main
className={`flex-1 overflow-hidden transition-[padding] duration-300 ${
!sidebarEnabled ? "" : collapsed ? "pl-16" : "pl-64"
className={`flex-1 overflow-hidden ${
!sidebarEnabled
? ""
: isDark
// 深色 sidebar:展开 118px(10 + 98 + 10 gap),收起 = 0 sidebar 完全消失,
// 只剩左下角浮动按钮(fixed,叠在 main 上不影响布局)。
// 不加 transition:transition + sidebar 立刻 unmount 不同步会抽搐
? (collapsed ? "pl-0" : "pl-[118px]")
// 浅色仍保留过渡动画(pl-16 ↔ pl-64 平滑收展)
: `transition-[padding] duration-300 ${collapsed ? "pl-16" : "pl-64"}`
}`}
>
<Routes>
@@ -50,6 +58,7 @@ function PageLayout() {
pageSidebarHidden={!sidebarEnabled}
headerHidden={!sidebarEnabled}
compactWorkspaceSidebar={sidebarEnabled}
pageSidebarDark={isDark}
/>
}
/>
+331 -315
View File
@@ -1,47 +1,47 @@
import type { CSSProperties, ReactNode } from "react";
import { Navigate, Route, Routes } from "react-router-dom";
import type { CSSProperties, ReactNode } from 'react';
import { Navigate, Route, Routes } from 'react-router-dom';
import { getStoredAuth } from "@/core/auth";
import { getStoredAuth } from '@/core/auth';
import { SidebarInset, SidebarProvider } from "@/components/ui/sidebar";
import { PromptInputProvider } from "@/components/ai-elements/prompt-input";
import { WorkspaceSidebar } from "@/components/workspace/workspace-sidebar";
import { CommandPalette } from "@/components/workspace/command-palette";
import { Toaster } from "sonner";
import { SubtasksProvider } from "@/core/tasks/context";
import { ArtifactsProvider } from "@/components/workspace/artifacts";
import { SidebarInset, SidebarProvider } from '@/components/ui/sidebar';
import { PromptInputProvider } from '@/components/ai-elements/prompt-input';
import { WorkspaceSidebar } from '@/components/workspace/workspace-sidebar';
import { CommandPalette } from '@/components/workspace/command-palette';
import { Toaster } from 'sonner';
import { SubtasksProvider } from '@/core/tasks/context';
import { ArtifactsProvider } from '@/components/workspace/artifacts';
import { RouteBaseProvider } from "@/core/route-base";
import { RouteBaseProvider } from '@/core/route-base';
import ChatsPage from "./ChatsPage";
import ChatPage from "./ChatPage";
import IframeChatPage from "./IframeChatPage";
import AgentsPage from "./AgentsPage";
import AgentChatPage from "./AgentChatPage";
import NewAgentPage from "./NewAgentPage";
import AdminAgentsPage from "./AdminAgentsPage";
import AdminScheduledTasksPage from "./AdminScheduledTasksPage";
import AdminSkillsPage from "./AdminSkillsPage";
import ScheduledTaskRunDetailPage from "./ScheduledTaskRunDetailPage";
import ScheduledTasksPage from "./ScheduledTasksPage";
import LlmMetricsPage from "./LlmMetricsPage";
import MemoryPage from "./MemoryPage";
import PromptPrefixSettingsPage from "./PromptPrefixSettingsPage";
import PrivateSquareSettingsPage from "./PrivateSquareSettingsPage";
import SkillEvolutionPage from "./SkillEvolutionPage";
import SkillsPage from "./SkillsPage";
import UsersPage from "./UsersPage";
import AdminUserActivityPage from "./AdminUserActivityPage";
import AdminMemoryPage from "./AdminMemoryPage";
import AdminUserHubPage from "./AdminUserHubPage";
import TagsPage from "./TagsPage";
import RecommendedQuestionsPage from "./RecommendedQuestionsPage";
import AIWritingPage from "@/open-canvas/pages/AIWritingPage";
import StudioNotebooksPage from "./StudioNotebooksPage";
import StudioNotebookDetailPage from "./StudioNotebookDetailPage";
import RoundtablePlanningPage from "@/roundtable-planning/pages/RoundtablePlanningPage";
import "@/roundtable-planning/styles/roundtable-planning.css";
import { cn } from "@/lib/utils";
import ChatsPage from './ChatsPage';
import ChatPage from './ChatPage';
import IframeChatPage from './IframeChatPage';
import AgentsPage from './AgentsPage';
import AgentChatPage from './AgentChatPage';
import NewAgentPage from './NewAgentPage';
import AdminAgentsPage from './AdminAgentsPage';
import AdminScheduledTasksPage from './AdminScheduledTasksPage';
import AdminSkillsPage from './AdminSkillsPage';
import ScheduledTaskRunDetailPage from './ScheduledTaskRunDetailPage';
import ScheduledTasksPage from './ScheduledTasksPage';
import LlmMetricsPage from './LlmMetricsPage';
import MemoryPage from './MemoryPage';
import PromptPrefixSettingsPage from './PromptPrefixSettingsPage';
import PrivateSquareSettingsPage from './PrivateSquareSettingsPage';
import SkillEvolutionPage from './SkillEvolutionPage';
import SkillsPage from './SkillsPage';
import UsersPage from './UsersPage';
import AdminUserActivityPage from './AdminUserActivityPage';
import AdminMemoryPage from './AdminMemoryPage';
import AdminUserHubPage from './AdminUserHubPage';
import TagsPage from './TagsPage';
import RecommendedQuestionsPage from './RecommendedQuestionsPage';
import AIWritingPage from '@/open-canvas/pages/AIWritingPage';
import StudioNotebooksPage from './StudioNotebooksPage';
import StudioNotebookDetailPage from './StudioNotebookDetailPage';
import RoundtablePlanningPage from '@/roundtable-planning/pages/RoundtablePlanningPage';
import '@/roundtable-planning/styles/roundtable-planning.css';
import { cn } from '@/lib/utils';
export function WorkspaceLayout({
children,
@@ -51,6 +51,7 @@ export function WorkspaceLayout({
compactWorkspaceSidebar = false,
wrapperOverflowHidden = false,
insetOverflowHidden = false,
pageSidebarDark = false,
}: {
children: ReactNode;
pageSidebarCollapsed: boolean;
@@ -59,23 +60,33 @@ export function WorkspaceLayout({
compactWorkspaceSidebar?: boolean;
wrapperOverflowHidden?: boolean;
insetOverflowHidden?: boolean;
pageSidebarDark?: boolean;
}) {
const pageSidebarWidth = pageSidebarHidden
? "0rem"
: pageSidebarCollapsed
? "4rem"
: "16rem";
? '0rem'
: pageSidebarDark
? // dark page sidebar:
// 展开: 视觉右边界 108px(外框 98 + 内层 translateX 10)+ 10px gap = 118px
// 收起: sidebar 主体完全消失(连同其占据的宽度),workspace 内容铺到屏幕左边;
// 左下角浮动按钮是 fixed,叠在主内容上不影响 layout
// 与 PageRoutes.tsx 的 main pl-[118px] / pl-0 保持一致
pageSidebarCollapsed
? '0rem'
: '118px'
: pageSidebarCollapsed
? '4rem'
: '16rem';
return (
<SidebarProvider
className={[
"h-full w-full [&_[data-slot=sidebar-container]]:left-[var(--page-sidebar-width)]",
wrapperOverflowHidden ? "overflow-hidden" : "overflow-x-hidden",
].join(" ")}
'h-full w-full [&_[data-slot=sidebar-container]]:left-[var(--page-sidebar-width)]',
wrapperOverflowHidden ? 'overflow-hidden' : 'overflow-x-hidden',
].join(' ')}
style={
{
"--page-sidebar-width": pageSidebarWidth,
"--header-height": headerHidden ? "0rem" : "4rem",
'--page-sidebar-width': pageSidebarWidth,
'--header-height': headerHidden ? '0rem' : '4rem',
} as CSSProperties
}
// Keep the fixed workspace sidebar aligned to the outer page sidebar width.
@@ -85,7 +96,7 @@ export function WorkspaceLayout({
>
<WorkspaceSidebar compactChrome={compactWorkspaceSidebar} />
<SidebarInset
className={cn("min-w-0", insetOverflowHidden && "overflow-hidden")}
className={cn('min-w-0', insetOverflowHidden && 'overflow-hidden')}
>
{children}
</SidebarInset>
@@ -110,302 +121,307 @@ export default function WorkspaceRoutes({
pageSidebarHidden = false,
headerHidden = false,
compactWorkspaceSidebar = false,
pageSidebarDark = false,
}: {
pageSidebarCollapsed?: boolean;
pageSidebarHidden?: boolean;
headerHidden?: boolean;
compactWorkspaceSidebar?: boolean;
pageSidebarDark?: boolean;
}) {
const layoutProps = {
pageSidebarCollapsed,
pageSidebarHidden,
headerHidden,
compactWorkspaceSidebar,
pageSidebarDark,
};
return (
<RouteBaseProvider value="/page/workspace">
<Routes>
<Route index element={<Navigate to="chats/new" replace />} />
<Route
path="chats"
element={
<WorkspaceLayout {...layoutProps}>
<ChatsPage />
</WorkspaceLayout>
}
/>
<Route
path="chats/:thread_id"
element={
<WorkspaceLayout {...layoutProps}>
<ChatRuntime>
<ChatPage />
</ChatRuntime>
</WorkspaceLayout>
}
/>
<Route
path="chats_iframe/new"
element={
<WorkspaceLayout {...layoutProps}>
<ChatRuntime>
<IframeChatPage />
</ChatRuntime>
</WorkspaceLayout>
}
/>
<Route
path="chats_iframe/:thread_id"
element={
<WorkspaceLayout
{...layoutProps}
wrapperOverflowHidden
insetOverflowHidden
>
<ChatRuntime>
<IframeChatPage />
</ChatRuntime>
</WorkspaceLayout>
}
/>
<Route
path="agents"
element={
<WorkspaceLayout {...layoutProps}>
<AgentsPage />
</WorkspaceLayout>
}
/>
<Route
path="agents/new"
element={
<WorkspaceLayout {...layoutProps}>
<NewAgentPage />
</WorkspaceLayout>
}
/>
<Route
path="agents/:agent_id/chats"
element={<Navigate to="/page/workspace/agents" replace />}
/>
<Route
path="agents/:agent_id/chats/:thread_id"
element={
<WorkspaceLayout {...layoutProps}>
<ChatRuntime>
<AgentChatPage />
</ChatRuntime>
</WorkspaceLayout>
}
/>
<Route
path="skills"
element={
<WorkspaceLayout {...layoutProps}>
<SkillsPage />
</WorkspaceLayout>
}
/>
<Route
path="skills/evolution"
element={
<WorkspaceLayout {...layoutProps}>
<SkillEvolutionPage />
</WorkspaceLayout>
}
/>
<Route
path="memory"
element={
<WorkspaceLayout {...layoutProps}>
<MemoryPage />
</WorkspaceLayout>
}
/>
<Route
path="ai-writing"
element={
<WorkspaceLayout {...layoutProps}>
<AIWritingPage hideAdvancedFields />
</WorkspaceLayout>
}
/>
<Route
path="studio/notebooks"
element={
<WorkspaceLayout {...layoutProps}>
<StudioNotebooksPage />
</WorkspaceLayout>
}
/>
<Route
path="studio/notebooks/:notebookId"
element={
<WorkspaceLayout {...layoutProps}>
<ChatRuntime>
<StudioNotebookDetailPage />
</ChatRuntime>
</WorkspaceLayout>
}
/>
<Route
path="roundtable"
element={<Navigate to="/page/workspace/roundtable/planning" replace />}
/>
<Route
path="roundtable/planning"
element={
<WorkspaceLayout {...layoutProps}>
<ChatRuntime>
<RoundtablePlanningPage />
</ChatRuntime>
</WorkspaceLayout>
}
/>
<Route
path="scheduled"
element={<Navigate to="/page/workspace/scheduled/tasks" replace />}
/>
<Route
path="scheduled/tasks"
element={
<WorkspaceLayout {...layoutProps}>
<ScheduledTasksPage />
</WorkspaceLayout>
}
/>
<Route
path="scheduled/runs/:run_id"
element={
<WorkspaceLayout {...layoutProps}>
<ScheduledTaskRunDetailPage />
</WorkspaceLayout>
}
/>
{/* Unified admin user hub */}
<Route
path="admin"
element={
getStoredAuth()?.system_role === "admin" ? (
<WorkspaceLayout {...layoutProps} pageSidebarHidden>
<AdminUserHubPage />
</WorkspaceLayout>
) : (
<Navigate to="/page/workspace/chats/new" replace />
)
}
/>
{/* Legacy redirects */}
<Route
path="admin/users"
element={<Navigate to="/page/workspace/admin" replace />}
/>
<Route
path="admin/user-activity"
element={<Navigate to="/page/workspace/admin" replace />}
/>
<Route
path="admin/memory"
element={<Navigate to="/page/workspace/admin" replace />}
/>
<Route
path="admin/scheduled-tasks"
element={
getStoredAuth()?.system_role === "admin" ? (
<Routes>
<Route index element={<Navigate to="chats/new" replace />} />
<Route
path="chats"
element={
<WorkspaceLayout {...layoutProps}>
<AdminScheduledTasksPage />
<ChatsPage />
</WorkspaceLayout>
) : (
<Navigate to="/page/workspace/chats/new" replace />
)
}
/>
<Route
path="admin/agents"
element={
getStoredAuth()?.system_role === "admin" ? (
}
/>
<Route
path="chats/:thread_id"
element={
<WorkspaceLayout {...layoutProps}>
<AdminAgentsPage />
<ChatRuntime>
<ChatPage />
</ChatRuntime>
</WorkspaceLayout>
) : (
<Navigate to="/page/workspace/chats/new" replace />
)
}
/>
<Route
path="admin/skills"
element={
getStoredAuth()?.system_role === "admin" ? (
}
/>
<Route
path="chats_iframe/new"
element={
<WorkspaceLayout {...layoutProps}>
<AdminSkillsPage />
<ChatRuntime>
<IframeChatPage />
</ChatRuntime>
</WorkspaceLayout>
) : (
<Navigate to="/page/workspace/chats/new" replace />
)
}
/>
<Route
path="admin/tags"
element={
getStoredAuth()?.system_role === "admin" ? (
}
/>
<Route
path="chats_iframe/:thread_id"
element={
<WorkspaceLayout
{...layoutProps}
wrapperOverflowHidden
insetOverflowHidden
>
<ChatRuntime>
<IframeChatPage />
</ChatRuntime>
</WorkspaceLayout>
}
/>
<Route
path="agents"
element={
<WorkspaceLayout {...layoutProps}>
<TagsPage />
<AgentsPage />
</WorkspaceLayout>
) : (
<Navigate to="/page/workspace/chats/new" replace />
)
}
/>
<Route
path="settings/recommended-questions"
element={
getStoredAuth()?.system_role === "admin" ? (
}
/>
<Route
path="agents/new"
element={
<WorkspaceLayout {...layoutProps}>
<RecommendedQuestionsPage />
<NewAgentPage />
</WorkspaceLayout>
) : (
<Navigate to="/page/workspace/chats/new" replace />
)
}
/>
<Route
path="settings/prompt-prefix"
element={
getStoredAuth()?.system_role === "admin" ? (
}
/>
<Route
path="agents/:agent_id/chats"
element={<Navigate to="/page/workspace/agents" replace />}
/>
<Route
path="agents/:agent_id/chats/:thread_id"
element={
<WorkspaceLayout {...layoutProps}>
<PromptPrefixSettingsPage />
<ChatRuntime>
<AgentChatPage />
</ChatRuntime>
</WorkspaceLayout>
) : (
<Navigate to="/page/workspace/chats/new" replace />
)
}
/>
<Route
path="settings/private-square"
element={
getStoredAuth()?.system_role === "admin" ? (
}
/>
<Route
path="skills"
element={
<WorkspaceLayout {...layoutProps}>
<PrivateSquareSettingsPage />
<SkillsPage />
</WorkspaceLayout>
) : (
<Navigate to="/page/workspace/chats/new" replace />
)
}
/>
<Route
path="settings/llm-metrics"
element={
getStoredAuth()?.system_role === "admin" ? (
}
/>
<Route
path="skills/evolution"
element={
<WorkspaceLayout {...layoutProps}>
<LlmMetricsPage />
<SkillEvolutionPage />
</WorkspaceLayout>
) : (
<Navigate to="/page/workspace/chats/new" replace />
)
}
/>
</Routes>
}
/>
<Route
path="memory"
element={
<WorkspaceLayout {...layoutProps}>
<MemoryPage />
</WorkspaceLayout>
}
/>
<Route
path="ai-writing"
element={
<WorkspaceLayout {...layoutProps}>
<AIWritingPage hideAdvancedFields />
</WorkspaceLayout>
}
/>
<Route
path="studio/notebooks"
element={
<WorkspaceLayout {...layoutProps}>
<StudioNotebooksPage />
</WorkspaceLayout>
}
/>
<Route
path="studio/notebooks/:notebookId"
element={
<WorkspaceLayout {...layoutProps}>
<ChatRuntime>
<StudioNotebookDetailPage />
</ChatRuntime>
</WorkspaceLayout>
}
/>
<Route
path="roundtable"
element={
<Navigate to="/page/workspace/roundtable/planning" replace />
}
/>
<Route
path="roundtable/planning"
element={
<WorkspaceLayout {...layoutProps}>
<ChatRuntime>
<RoundtablePlanningPage />
</ChatRuntime>
</WorkspaceLayout>
}
/>
<Route
path="scheduled"
element={<Navigate to="/page/workspace/scheduled/tasks" replace />}
/>
<Route
path="scheduled/tasks"
element={
<WorkspaceLayout {...layoutProps}>
<ScheduledTasksPage />
</WorkspaceLayout>
}
/>
<Route
path="scheduled/runs/:run_id"
element={
<WorkspaceLayout {...layoutProps}>
<ScheduledTaskRunDetailPage />
</WorkspaceLayout>
}
/>
{/* Unified admin user hub */}
<Route
path="admin"
element={
getStoredAuth()?.system_role === 'admin' ? (
<WorkspaceLayout {...layoutProps} pageSidebarHidden>
<AdminUserHubPage />
</WorkspaceLayout>
) : (
<Navigate to="/page/workspace/chats/new" replace />
)
}
/>
{/* Legacy redirects */}
<Route
path="admin/users"
element={<Navigate to="/page/workspace/admin" replace />}
/>
<Route
path="admin/user-activity"
element={<Navigate to="/page/workspace/admin" replace />}
/>
<Route
path="admin/memory"
element={<Navigate to="/page/workspace/admin" replace />}
/>
<Route
path="admin/scheduled-tasks"
element={
getStoredAuth()?.system_role === 'admin' ? (
<WorkspaceLayout {...layoutProps}>
<AdminScheduledTasksPage />
</WorkspaceLayout>
) : (
<Navigate to="/page/workspace/chats/new" replace />
)
}
/>
<Route
path="admin/agents"
element={
getStoredAuth()?.system_role === 'admin' ? (
<WorkspaceLayout {...layoutProps}>
<AdminAgentsPage />
</WorkspaceLayout>
) : (
<Navigate to="/page/workspace/chats/new" replace />
)
}
/>
<Route
path="admin/skills"
element={
getStoredAuth()?.system_role === 'admin' ? (
<WorkspaceLayout {...layoutProps}>
<AdminSkillsPage />
</WorkspaceLayout>
) : (
<Navigate to="/page/workspace/chats/new" replace />
)
}
/>
<Route
path="admin/tags"
element={
getStoredAuth()?.system_role === 'admin' ? (
<WorkspaceLayout {...layoutProps}>
<TagsPage />
</WorkspaceLayout>
) : (
<Navigate to="/page/workspace/chats/new" replace />
)
}
/>
<Route
path="settings/recommended-questions"
element={
getStoredAuth()?.system_role === 'admin' ? (
<WorkspaceLayout {...layoutProps}>
<RecommendedQuestionsPage />
</WorkspaceLayout>
) : (
<Navigate to="/page/workspace/chats/new" replace />
)
}
/>
<Route
path="settings/prompt-prefix"
element={
getStoredAuth()?.system_role === 'admin' ? (
<WorkspaceLayout {...layoutProps}>
<PromptPrefixSettingsPage />
</WorkspaceLayout>
) : (
<Navigate to="/page/workspace/chats/new" replace />
)
}
/>
<Route
path="settings/private-square"
element={
getStoredAuth()?.system_role === 'admin' ? (
<WorkspaceLayout {...layoutProps}>
<PrivateSquareSettingsPage />
</WorkspaceLayout>
) : (
<Navigate to="/page/workspace/chats/new" replace />
)
}
/>
<Route
path="settings/llm-metrics"
element={
getStoredAuth()?.system_role === 'admin' ? (
<WorkspaceLayout {...layoutProps}>
<LlmMetricsPage />
</WorkspaceLayout>
) : (
<Navigate to="/page/workspace/chats/new" replace />
)
}
/>
</Routes>
</RouteBaseProvider>
);
}