@lobehub/lobehub 2.0.0-next.344 → 2.0.0-next.346
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/rules/i18n.mdc +1 -1
- package/.cursor/rules/modal-imperative.mdc +162 -0
- package/.cursor/rules/rules-index.mdc +1 -0
- package/.env.example +0 -14
- package/.eslintrc.js +8 -1
- package/CHANGELOG.md +66 -0
- package/CLAUDE.md +4 -2
- package/Dockerfile +3 -13
- package/README.md +3 -5
- package/README.zh-CN.md +3 -5
- package/changelog/v1.json +20 -0
- package/docs/self-hosting/advanced/auth/clerk-to-betterauth.mdx +11 -42
- package/docs/self-hosting/advanced/auth/clerk-to-betterauth.zh-CN.mdx +10 -41
- package/e2e/src/support/webServer.ts +2 -0
- package/locales/ar/error.json +0 -4
- package/locales/bg-BG/error.json +0 -4
- package/locales/de-DE/error.json +0 -4
- package/locales/en-US/error.json +0 -4
- package/locales/es-ES/error.json +0 -4
- package/locales/fa-IR/error.json +0 -4
- package/locales/fr-FR/error.json +0 -4
- package/locales/it-IT/error.json +0 -4
- package/locales/ja-JP/error.json +0 -4
- package/locales/ko-KR/error.json +0 -4
- package/locales/nl-NL/error.json +0 -4
- package/locales/pl-PL/error.json +0 -4
- package/locales/pt-BR/error.json +0 -4
- package/locales/ru-RU/error.json +0 -4
- package/locales/tr-TR/error.json +0 -4
- package/locales/vi-VN/error.json +0 -4
- package/locales/zh-CN/error.json +0 -4
- package/locales/zh-TW/error.json +0 -4
- package/package.json +12 -12
- package/packages/builtin-agents/package.json +2 -0
- package/packages/builtin-agents/src/agents/agent-builder/index.ts +4 -2
- package/packages/builtin-agents/src/agents/group-agent-builder/index.ts +4 -2
- package/packages/builtin-agents/src/agents/page-agent/index.ts +5 -2
- package/packages/context-engine/src/engine/messages/MessagesEngine.ts +9 -9
- package/packages/context-engine/src/providers/GroupContextInjector.ts +19 -33
- package/packages/context-engine/src/providers/__tests__/GroupContextInjector.test.ts +79 -43
- package/packages/context-engine/src/providers/__tests__/__snapshots__/GroupContextInjector.test.ts.snap +5 -15
- package/packages/database/src/repositories/userMemory/__tests__/UserMemoryTopicRepository.test.ts +24 -3
- package/packages/file-loaders/package.json +1 -1
- package/packages/file-loaders/src/loadFile.ts +10 -15
- package/packages/file-loaders/src/loaders/index.ts +68 -19
- package/packages/file-loaders/src/loaders/pdf/__snapshots__/index.test.ts.snap +1 -1
- package/packages/file-loaders/test/__snapshots__/loaders.test.ts.snap +1 -1
- package/packages/model-bank/src/modelProviders/comfyui.ts +0 -1
- package/packages/model-bank/src/modelProviders/fal.ts +0 -1
- package/packages/types/src/fetch.ts +1 -2
- package/packages/utils/src/server/__tests__/auth.test.ts +0 -47
- package/packages/utils/src/server/auth.ts +1 -9
- package/pnpm-workspace.yaml +1 -0
- package/scripts/_shared/checkDeprecatedClerkEnv.js +42 -0
- package/scripts/changelogWorkflow/buildStaticChangelog.ts +2 -1
- package/scripts/clerk-to-betterauth/_internal/types.ts +53 -20
- package/scripts/clerk-to-betterauth/export-clerk-users-with-api.ts +43 -36
- package/scripts/countEnWord.ts +1 -1
- package/scripts/electronWorkflow/modifiers/appCode.mts +2 -131
- package/scripts/i18nWorkflow/protectedPatterns.ts +1 -2
- package/scripts/prebuild.mts +10 -8
- package/scripts/serverLauncher/startServer.js +23 -5
- package/src/app/(backend)/middleware/auth/index.test.ts +8 -4
- package/src/app/(backend)/middleware/auth/index.ts +0 -15
- package/src/app/(backend)/middleware/auth/utils.test.ts +0 -28
- package/src/app/(backend)/middleware/auth/utils.ts +2 -17
- package/src/app/(backend)/webapi/chat/[provider]/route.test.ts +3 -51
- package/src/app/(backend)/webapi/models/[provider]/route.test.ts +8 -4
- package/src/app/[variants]/(auth)/next-auth/signin/AuthSignInBox.tsx +7 -6
- package/src/app/[variants]/(auth)/signup/[[...signup]]/page.tsx +1 -16
- package/src/app/[variants]/(main)/home/_layout/Body/Agent/List/index.tsx +1 -1
- package/src/app/[variants]/(main)/home/features/InputArea/SkillInstallBanner.tsx +13 -13
- package/src/app/[variants]/(main)/home/features/RecentPage/Item.tsx +2 -2
- package/src/app/[variants]/(main)/resource/features/store/action.ts +2 -2
- package/src/app/[variants]/(main)/resource/features/store/initialState.ts +2 -2
- package/src/app/[variants]/(main)/resource/store/action.ts +2 -2
- package/src/app/[variants]/(main)/resource/store/initialState.ts +2 -2
- package/src/app/[variants]/(main)/settings/hooks/useCategory.tsx +3 -21
- package/src/app/[variants]/(main)/settings/profile/features/AvatarRow.tsx +1 -2
- package/src/app/[variants]/(main)/settings/security/index.tsx +1 -22
- package/src/app/[variants]/(main)/settings/skill/features/KlavisSkillItem.tsx +12 -14
- package/src/app/[variants]/(main)/settings/skill/features/LobehubSkillItem.tsx +8 -14
- package/src/app/[variants]/(main)/settings/skill/index.tsx +7 -5
- package/src/app/[variants]/(mobile)/me/(home)/__tests__/UserBanner.test.tsx +2 -35
- package/src/app/[variants]/(mobile)/me/(home)/__tests__/useCategory.test.tsx +0 -20
- package/src/app/[variants]/(mobile)/me/(home)/features/UserBanner.tsx +1 -2
- package/src/app/[variants]/(mobile)/me/profile/features/Category.tsx +3 -13
- package/src/app/[variants]/(mobile)/settings/_layout/Header.tsx +2 -3
- package/src/app/[variants]/share/t/[id]/_layout/index.tsx +1 -1
- package/src/app/[variants]/share/t/[id]/index.tsx +1 -1
- package/src/app/robots.tsx +1 -1
- package/src/envs/auth.ts +2 -27
- package/src/envs/llm.ts +2 -2
- package/src/features/AgentSetting/AgentPlugin/index.tsx +9 -12
- package/src/features/ChatInput/ActionBar/Tools/index.tsx +7 -5
- package/src/features/ChatMiniMap/utils.ts +1 -1
- package/src/features/CommandMenu/SearchResults.tsx +1 -1
- package/src/features/Conversation/ChatList/components/AutoScroll/DebugInspector.tsx +166 -0
- package/src/features/Conversation/ChatList/components/AutoScroll/index.tsx +86 -0
- package/src/features/Conversation/ChatList/components/VirtualizedList.tsx +11 -17
- package/src/features/Conversation/Messages/AgentCouncil/components/AutoScrollShadow.tsx +25 -14
- package/src/features/Conversation/Messages/AgentCouncil/components/CouncilMember.tsx +1 -1
- package/src/features/FileViewer/Renderer/PDF/index.tsx +5 -8
- package/src/features/IntegrationDetailModal/IntegrationDetailContent.tsx +305 -0
- package/src/features/IntegrationDetailModal/index.tsx +21 -283
- package/src/features/MCPPluginDetail/Deployment/index.tsx +1 -1
- package/src/features/MCPPluginDetail/Schema/Prompts.tsx +1 -1
- package/src/features/MCPPluginDetail/Schema/Tools.tsx +1 -1
- package/src/features/ProfileEditor/AgentTool.tsx +14 -20
- package/src/features/ResourceManager/components/Explorer/ListView/ListItem/index.tsx +0 -8
- package/src/features/ResourceManager/components/Explorer/MasonryView/MasonryFileItem/NoteFileItem.tsx +1 -1
- package/src/features/ResourceManager/index.tsx +1 -1
- package/src/features/ShareModal/SharePdf/PdfPreview.tsx +4 -4
- package/src/features/SkillStore/LobeHubList/index.tsx +50 -87
- package/src/features/SkillStore/Search/index.tsx +1 -1
- package/src/features/SkillStore/{Content.tsx → SkillStoreContent.tsx} +3 -8
- package/src/features/SkillStore/index.tsx +15 -33
- package/src/features/User/UserPanel/PanelContent.tsx +0 -8
- package/src/features/User/__tests__/PanelContent.test.tsx +1 -35
- package/src/features/User/__tests__/UserAvatar.test.tsx +30 -57
- package/src/features/User/__tests__/useMenu.test.tsx +2 -43
- package/src/layout/AuthProvider/index.tsx +0 -5
- package/src/libs/next/config/define-config.ts +20 -15
- package/src/libs/next/proxy/createRouteMatcher.test.ts +121 -0
- package/src/libs/next/proxy/createRouteMatcher.ts +18 -0
- package/src/libs/next/proxy/define-config.ts +4 -53
- package/src/libs/next-auth/adapter/index.ts +1 -2
- package/src/libs/oidc-provider/provider.test.ts +5 -316
- package/src/libs/pdfjs/pdf.worker.ts +1 -0
- package/src/libs/pdfjs/worker.ts +12 -0
- package/src/libs/trpc/lambda/context.test.ts +0 -13
- package/src/libs/trpc/lambda/context.ts +3 -22
- package/src/libs/trpc/middleware/userAuth.ts +2 -4
- package/src/libs/trusted-client/getSessionUser.ts +2 -17
- package/src/locales/default/error.ts +0 -6
- package/src/locales/default/index.ts +0 -2
- package/src/proxy.ts +0 -1
- package/src/server/routers/lambda/__tests__/user.test.ts +0 -71
- package/src/server/routers/lambda/user.ts +6 -63
- package/src/server/services/changelog/index.test.ts +3 -2
- package/src/server/services/changelog/index.ts +1 -1
- package/src/server/services/user/index.ts +0 -83
- package/src/services/chat/index.ts +1 -2
- package/src/services/chat/mecha/agentConfigResolver.test.ts +43 -0
- package/src/services/chat/mecha/agentConfigResolver.ts +3 -1
- package/src/store/chat/slices/aiChat/actions/__tests__/streamingExecutor.test.ts +58 -14
- package/src/store/chat/slices/aiChat/actions/streamingExecutor.ts +10 -2
- package/src/store/user/slices/auth/action.test.ts +1 -81
- package/src/store/user/slices/auth/action.ts +3 -28
- package/src/store/user/slices/auth/initialState.ts +1 -18
- package/src/store/user/slices/auth/selectors.test.ts +2 -127
- package/src/store/user/slices/auth/selectors.ts +1 -21
- package/src/utils/errorResponse.ts +1 -4
- package/src/utils/markdownToTxt.ts +20 -0
- package/locales/ar/clerk.json +0 -545
- package/locales/bg-BG/clerk.json +0 -545
- package/locales/de-DE/clerk.json +0 -545
- package/locales/en-US/clerk.json +0 -545
- package/locales/es-ES/clerk.json +0 -545
- package/locales/fa-IR/clerk.json +0 -545
- package/locales/fr-FR/clerk.json +0 -545
- package/locales/it-IT/clerk.json +0 -545
- package/locales/ja-JP/clerk.json +0 -545
- package/locales/ko-KR/clerk.json +0 -545
- package/locales/nl-NL/clerk.json +0 -545
- package/locales/pl-PL/clerk.json +0 -545
- package/locales/pt-BR/clerk.json +0 -545
- package/locales/ru-RU/clerk.json +0 -545
- package/locales/tr-TR/clerk.json +0 -545
- package/locales/vi-VN/clerk.json +0 -545
- package/locales/zh-CN/clerk.json +0 -545
- package/locales/zh-TW/clerk.json +0 -545
- package/src/app/(backend)/api/webhooks/clerk/__tests__/fixtures/createUser.json +0 -73
- package/src/app/(backend)/api/webhooks/clerk/route.ts +0 -95
- package/src/app/(backend)/api/webhooks/clerk/validateRequest.ts +0 -22
- package/src/app/[variants]/(auth)/login/[[...login]]/page.tsx +0 -27
- package/src/app/[variants]/(main)/settings/security/features/ClerkProfile.tsx +0 -67
- package/src/features/Conversation/ChatList/components/AutoScroll.tsx +0 -25
- package/src/layout/AuthProvider/Clerk/UserUpdater.tsx +0 -40
- package/src/layout/AuthProvider/Clerk/index.tsx +0 -54
- package/src/layout/AuthProvider/Clerk/useAppearance.ts +0 -133
- package/src/libs/clerk-auth/index.test.ts +0 -216
- package/src/libs/clerk-auth/index.ts +0 -80
- package/src/locales/default/clerk.ts +0 -677
- package/src/server/services/user/index.test.ts +0 -220
|
@@ -2,30 +2,32 @@
|
|
|
2
2
|
|
|
3
3
|
import { Button, Icon } from '@lobehub/ui';
|
|
4
4
|
import { Store } from 'lucide-react';
|
|
5
|
-
import {
|
|
5
|
+
import { useCallback } from 'react';
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
7
7
|
|
|
8
8
|
import SettingHeader from '@/app/[variants]/(main)/settings/features/SettingHeader';
|
|
9
|
-
import
|
|
9
|
+
import { createSkillStoreModal } from '@/features/SkillStore';
|
|
10
10
|
|
|
11
11
|
import SkillList from './features/SkillList';
|
|
12
12
|
|
|
13
13
|
const Page = () => {
|
|
14
14
|
const { t } = useTranslation('setting');
|
|
15
|
-
|
|
15
|
+
|
|
16
|
+
const handleOpenStore = useCallback(() => {
|
|
17
|
+
createSkillStoreModal();
|
|
18
|
+
}, []);
|
|
16
19
|
|
|
17
20
|
return (
|
|
18
21
|
<>
|
|
19
22
|
<SettingHeader
|
|
20
23
|
extra={
|
|
21
|
-
<Button icon={<Icon icon={Store} />} onClick={
|
|
24
|
+
<Button icon={<Icon icon={Store} />} onClick={handleOpenStore}>
|
|
22
25
|
{t('skillStore.button')}
|
|
23
26
|
</Button>
|
|
24
27
|
}
|
|
25
28
|
title={t('tab.skill')}
|
|
26
29
|
/>
|
|
27
30
|
<SkillList />
|
|
28
|
-
<SkillStore open={open} setOpen={setOpen} />
|
|
29
31
|
</>
|
|
30
32
|
);
|
|
31
33
|
};
|
|
@@ -31,48 +31,16 @@ vi.mock('@/const/version', () => ({
|
|
|
31
31
|
isDesktop: false,
|
|
32
32
|
}));
|
|
33
33
|
|
|
34
|
-
// Use vi.hoisted to ensure variables exist before vi.mock factory executes
|
|
35
|
-
const { enableAuth, enableClerk } = vi.hoisted(() => ({
|
|
36
|
-
enableAuth: { value: true },
|
|
37
|
-
enableClerk: { value: false },
|
|
38
|
-
}));
|
|
39
|
-
|
|
40
|
-
vi.mock('@/envs/auth', () => ({
|
|
41
|
-
get enableAuth() {
|
|
42
|
-
return enableAuth.value;
|
|
43
|
-
},
|
|
44
|
-
get enableClerk() {
|
|
45
|
-
return enableClerk.value;
|
|
46
|
-
},
|
|
47
|
-
}));
|
|
48
|
-
|
|
49
34
|
afterEach(() => {
|
|
50
|
-
enableAuth.value = true;
|
|
51
|
-
enableClerk.value = false;
|
|
52
35
|
mockNavigate.mockReset();
|
|
53
36
|
});
|
|
54
37
|
|
|
55
38
|
describe('UserBanner', () => {
|
|
56
|
-
it('should render UserInfo and DataStatistics when
|
|
57
|
-
act(() => {
|
|
58
|
-
useUserStore.setState({ isSignedIn: false });
|
|
59
|
-
});
|
|
60
|
-
enableAuth.value = false;
|
|
61
|
-
|
|
62
|
-
render(<UserBanner />);
|
|
63
|
-
|
|
64
|
-
expect(screen.getByText('Mocked UserInfo')).toBeInTheDocument();
|
|
65
|
-
expect(screen.getByText('Mocked DataStatistics')).toBeInTheDocument();
|
|
66
|
-
expect(screen.queryByText('Mocked UserLoginOrSignup')).not.toBeInTheDocument();
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
it('should render UserInfo and DataStatistics when user is logged in with auth enabled', () => {
|
|
39
|
+
it('should render UserInfo and DataStatistics when user is logged in', () => {
|
|
70
40
|
act(() => {
|
|
71
41
|
useUserStore.setState({ isSignedIn: true });
|
|
72
42
|
});
|
|
73
43
|
|
|
74
|
-
enableClerk.value = true;
|
|
75
|
-
|
|
76
44
|
render(<UserBanner />);
|
|
77
45
|
|
|
78
46
|
expect(screen.getByText('Mocked UserInfo')).toBeInTheDocument();
|
|
@@ -80,11 +48,10 @@ describe('UserBanner', () => {
|
|
|
80
48
|
expect(screen.queryByText('Mocked UserLoginOrSignup')).not.toBeInTheDocument();
|
|
81
49
|
});
|
|
82
50
|
|
|
83
|
-
it('should render UserLoginOrSignup when user is not logged in
|
|
51
|
+
it('should render UserLoginOrSignup when user is not logged in', () => {
|
|
84
52
|
act(() => {
|
|
85
53
|
useUserStore.setState({ isSignedIn: false });
|
|
86
54
|
});
|
|
87
|
-
enableClerk.value = true;
|
|
88
55
|
|
|
89
56
|
render(<UserBanner />);
|
|
90
57
|
|
|
@@ -22,21 +22,6 @@ vi.mock('react-i18next', () => ({
|
|
|
22
22
|
})),
|
|
23
23
|
}));
|
|
24
24
|
|
|
25
|
-
// Use vi.hoisted to ensure variables exist before vi.mock factory executes
|
|
26
|
-
const { enableAuth, enableClerk } = vi.hoisted(() => ({
|
|
27
|
-
enableAuth: { value: true },
|
|
28
|
-
enableClerk: { value: true },
|
|
29
|
-
}));
|
|
30
|
-
|
|
31
|
-
vi.mock('@/envs/auth', () => ({
|
|
32
|
-
get enableAuth() {
|
|
33
|
-
return enableAuth.value;
|
|
34
|
-
},
|
|
35
|
-
get enableClerk() {
|
|
36
|
-
return enableClerk.value;
|
|
37
|
-
},
|
|
38
|
-
}));
|
|
39
|
-
|
|
40
25
|
// Mock version constants
|
|
41
26
|
vi.mock('@/const/version', async (importOriginal) => {
|
|
42
27
|
const actual = await importOriginal<typeof import('@/const/version')>();
|
|
@@ -47,8 +32,6 @@ vi.mock('@/const/version', async (importOriginal) => {
|
|
|
47
32
|
});
|
|
48
33
|
|
|
49
34
|
afterEach(() => {
|
|
50
|
-
enableAuth.value = true;
|
|
51
|
-
enableClerk.value = true;
|
|
52
35
|
mockNavigate.mockReset();
|
|
53
36
|
});
|
|
54
37
|
|
|
@@ -57,8 +40,6 @@ describe('useCategory', () => {
|
|
|
57
40
|
act(() => {
|
|
58
41
|
useUserStore.setState({ isSignedIn: true });
|
|
59
42
|
});
|
|
60
|
-
enableAuth.value = true;
|
|
61
|
-
enableClerk.value = false;
|
|
62
43
|
|
|
63
44
|
const mockOpenChangelogModal = vi.fn();
|
|
64
45
|
const { result } = renderHook(() => useCategory(mockOpenChangelogModal), { wrapper });
|
|
@@ -77,7 +58,6 @@ describe('useCategory', () => {
|
|
|
77
58
|
act(() => {
|
|
78
59
|
useUserStore.setState({ isSignedIn: false });
|
|
79
60
|
});
|
|
80
|
-
enableAuth.value = true;
|
|
81
61
|
|
|
82
62
|
const mockOpenChangelogModal = vi.fn();
|
|
83
63
|
const { result } = renderHook(() => useCategory(mockOpenChangelogModal), { wrapper });
|
|
@@ -4,7 +4,6 @@ import { Flexbox } from '@lobehub/ui';
|
|
|
4
4
|
import { memo } from 'react';
|
|
5
5
|
import { Link } from 'react-router-dom';
|
|
6
6
|
|
|
7
|
-
import { enableAuth } from '@/envs/auth';
|
|
8
7
|
import DataStatistics from '@/features/User/DataStatistics';
|
|
9
8
|
import UserInfo from '@/features/User/UserInfo';
|
|
10
9
|
import UserLoginOrSignup from '@/features/User/UserLoginOrSignup/Community';
|
|
@@ -17,7 +16,7 @@ const UserBanner = memo(() => {
|
|
|
17
16
|
|
|
18
17
|
return (
|
|
19
18
|
<Flexbox gap={12} paddingBlock={8}>
|
|
20
|
-
{
|
|
19
|
+
{isLoginWithAuth ? (
|
|
21
20
|
<>
|
|
22
21
|
<Link style={{ color: 'inherit' }} to="/settings/profile">
|
|
23
22
|
<UserInfo />
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { ChartColumnBigIcon, LogOut,
|
|
3
|
+
import { ChartColumnBigIcon, LogOut, UserCircle } from 'lucide-react';
|
|
4
4
|
import { memo } from 'react';
|
|
5
5
|
import { useTranslation } from 'react-i18next';
|
|
6
6
|
import { useNavigate } from 'react-router-dom';
|
|
@@ -11,11 +11,7 @@ import { useUserStore } from '@/store/user';
|
|
|
11
11
|
import { authSelectors } from '@/store/user/selectors';
|
|
12
12
|
|
|
13
13
|
const Category = memo(() => {
|
|
14
|
-
const [isLogin,
|
|
15
|
-
authSelectors.isLogin(s),
|
|
16
|
-
authSelectors.isLoginWithClerk(s),
|
|
17
|
-
s.logout,
|
|
18
|
-
]);
|
|
14
|
+
const [isLogin, signOut] = useUserStore((s) => [authSelectors.isLogin(s), s.logout]);
|
|
19
15
|
const navigate = useNavigate();
|
|
20
16
|
const { t } = useTranslation('auth');
|
|
21
17
|
const items: CellProps[] = [
|
|
@@ -25,12 +21,6 @@ const Category = memo(() => {
|
|
|
25
21
|
label: t('tab.profile'),
|
|
26
22
|
onClick: () => navigate('/settings/profile'),
|
|
27
23
|
},
|
|
28
|
-
isLoginWithClerk && {
|
|
29
|
-
icon: ShieldCheck,
|
|
30
|
-
key: ProfileTabs.Security,
|
|
31
|
-
label: t('tab.security'),
|
|
32
|
-
onClick: () => navigate('/settings/security'),
|
|
33
|
-
},
|
|
34
24
|
{
|
|
35
25
|
icon: ChartColumnBigIcon,
|
|
36
26
|
key: ProfileTabs.Stats,
|
|
@@ -46,7 +36,7 @@ const Category = memo(() => {
|
|
|
46
36
|
label: t('signout', { ns: 'auth' }),
|
|
47
37
|
onClick: () => {
|
|
48
38
|
signOut();
|
|
49
|
-
navigate('/
|
|
39
|
+
navigate('/signin');
|
|
50
40
|
},
|
|
51
41
|
},
|
|
52
42
|
].filter(Boolean) as CellProps[];
|
|
@@ -6,7 +6,6 @@ import { memo } from 'react';
|
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
7
7
|
import { useNavigate, useParams } from 'react-router-dom';
|
|
8
8
|
|
|
9
|
-
import { enableAuth } from '@/envs/auth';
|
|
10
9
|
import { useShowMobileWorkspace } from '@/hooks/useShowMobileWorkspace';
|
|
11
10
|
import { type SettingsTabs } from '@/store/global/initialState';
|
|
12
11
|
import { useSessionStore } from '@/store/session';
|
|
@@ -16,7 +15,7 @@ const Header = memo(() => {
|
|
|
16
15
|
const { t } = useTranslation('setting');
|
|
17
16
|
const showMobileWorkspace = useShowMobileWorkspace();
|
|
18
17
|
const navigate = useNavigate();
|
|
19
|
-
const params = useParams<{ providerId?: string
|
|
18
|
+
const params = useParams<{ providerId?: string; tab?: string }>();
|
|
20
19
|
|
|
21
20
|
const isSessionActive = useSessionStore((s) => !!s.activeId);
|
|
22
21
|
const isProvider = params.providerId && params.providerId !== 'all';
|
|
@@ -27,7 +26,7 @@ const Header = memo(() => {
|
|
|
27
26
|
} else if (isProvider) {
|
|
28
27
|
navigate('/settings/provider/all');
|
|
29
28
|
} else {
|
|
30
|
-
navigate(
|
|
29
|
+
navigate('/me/settings');
|
|
31
30
|
}
|
|
32
31
|
};
|
|
33
32
|
|
package/src/app/robots.tsx
CHANGED
package/src/envs/auth.ts
CHANGED
|
@@ -6,11 +6,6 @@ declare global {
|
|
|
6
6
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
7
7
|
namespace NodeJS {
|
|
8
8
|
interface ProcessEnv {
|
|
9
|
-
// ===== Clerk ===== //
|
|
10
|
-
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY?: string;
|
|
11
|
-
CLERK_SECRET_KEY?: string;
|
|
12
|
-
CLERK_WEBHOOK_SECRET?: string;
|
|
13
|
-
|
|
14
9
|
// ===== Auth (shared by Better Auth / Next Auth) ===== //
|
|
15
10
|
AUTH_SECRET?: string;
|
|
16
11
|
AUTH_EMAIL_VERIFICATION?: string;
|
|
@@ -136,10 +131,6 @@ declare global {
|
|
|
136
131
|
export const getAuthConfig = () => {
|
|
137
132
|
return createEnv({
|
|
138
133
|
client: {
|
|
139
|
-
// ---------------------------------- clerk ----------------------------------
|
|
140
|
-
NEXT_PUBLIC_ENABLE_CLERK_AUTH: z.boolean().optional().default(false),
|
|
141
|
-
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: z.string().optional(),
|
|
142
|
-
|
|
143
134
|
// ---------------------------------- better auth ----------------------------------
|
|
144
135
|
NEXT_PUBLIC_ENABLE_BETTER_AUTH: z.boolean().optional(),
|
|
145
136
|
|
|
@@ -147,10 +138,6 @@ export const getAuthConfig = () => {
|
|
|
147
138
|
NEXT_PUBLIC_ENABLE_NEXT_AUTH: z.boolean().optional(),
|
|
148
139
|
},
|
|
149
140
|
server: {
|
|
150
|
-
// ---------------------------------- clerk ----------------------------------
|
|
151
|
-
CLERK_SECRET_KEY: z.string().optional(),
|
|
152
|
-
CLERK_WEBHOOK_SECRET: z.string().optional(),
|
|
153
|
-
|
|
154
141
|
// ---------------------------------- better auth ----------------------------------
|
|
155
142
|
AUTH_SECRET: z.string().optional(),
|
|
156
143
|
AUTH_SSO_PROVIDERS: z.string().optional().default(''),
|
|
@@ -261,14 +248,6 @@ export const getAuthConfig = () => {
|
|
|
261
248
|
},
|
|
262
249
|
|
|
263
250
|
runtimeEnv: {
|
|
264
|
-
// Clerk
|
|
265
|
-
NEXT_PUBLIC_ENABLE_CLERK_AUTH:
|
|
266
|
-
process.env.NEXT_PUBLIC_ENABLE_CLERK_AUTH === '1' ||
|
|
267
|
-
!!process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY,
|
|
268
|
-
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY,
|
|
269
|
-
CLERK_SECRET_KEY: process.env.CLERK_SECRET_KEY,
|
|
270
|
-
CLERK_WEBHOOK_SECRET: process.env.CLERK_WEBHOOK_SECRET,
|
|
271
|
-
|
|
272
251
|
// ---------------------------------- better auth ----------------------------------
|
|
273
252
|
NEXT_PUBLIC_ENABLE_BETTER_AUTH: process.env.NEXT_PUBLIC_ENABLE_BETTER_AUTH === '1',
|
|
274
253
|
// Fallback to NEXT_PUBLIC_* for seamless migration
|
|
@@ -396,13 +375,9 @@ export const getAuthConfig = () => {
|
|
|
396
375
|
export const authEnv = getAuthConfig();
|
|
397
376
|
|
|
398
377
|
// Auth flags - use process.env directly for build-time dead code elimination
|
|
399
|
-
|
|
400
|
-
process.env.NEXT_PUBLIC_ENABLE_CLERK_AUTH === '1'
|
|
401
|
-
? true
|
|
402
|
-
: !!process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY;
|
|
403
|
-
export const enableBetterAuth = process.env.NEXT_PUBLIC_ENABLE_BETTER_AUTH === '1';
|
|
378
|
+
// Better Auth is the default auth solution when NextAuth is not explicitly enabled
|
|
404
379
|
export const enableNextAuth = process.env.NEXT_PUBLIC_ENABLE_NEXT_AUTH === '1';
|
|
405
|
-
export const
|
|
380
|
+
export const enableBetterAuth = !enableNextAuth;
|
|
406
381
|
|
|
407
382
|
// Auth headers and constants
|
|
408
383
|
export const LOBE_CHAT_AUTH_HEADER = 'X-lobe-chat-auth';
|
package/src/envs/llm.ts
CHANGED
|
@@ -241,7 +241,7 @@ export const getLLMConfig = () => {
|
|
|
241
241
|
ENABLED_DEEPSEEK: !!process.env.DEEPSEEK_API_KEY,
|
|
242
242
|
DEEPSEEK_API_KEY: process.env.DEEPSEEK_API_KEY,
|
|
243
243
|
|
|
244
|
-
ENABLED_GOOGLE:
|
|
244
|
+
ENABLED_GOOGLE: process.env.ENABLED_GOOGLE !== '0',
|
|
245
245
|
GOOGLE_API_KEY: process.env.GOOGLE_API_KEY,
|
|
246
246
|
|
|
247
247
|
ENABLED_VERTEXAI: !!process.env.VERTEXAI_CREDENTIALS,
|
|
@@ -252,7 +252,7 @@ export const getLLMConfig = () => {
|
|
|
252
252
|
ENABLED_PERPLEXITY: !!process.env.PERPLEXITY_API_KEY,
|
|
253
253
|
PERPLEXITY_API_KEY: process.env.PERPLEXITY_API_KEY,
|
|
254
254
|
|
|
255
|
-
ENABLED_ANTHROPIC:
|
|
255
|
+
ENABLED_ANTHROPIC: process.env.ENABLED_ANTHROPIC !== '0',
|
|
256
256
|
ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY,
|
|
257
257
|
|
|
258
258
|
ENABLED_MINIMAX: !!process.env.MINIMAX_API_KEY,
|
|
@@ -5,14 +5,14 @@ import { Center, Flexbox } from '@lobehub/ui';
|
|
|
5
5
|
import { Space, Switch } from 'antd';
|
|
6
6
|
import isEqual from 'fast-deep-equal';
|
|
7
7
|
import { LucideTrash2, Plug2, Store } from 'lucide-react';
|
|
8
|
-
import { memo,
|
|
8
|
+
import { memo, useCallback } from 'react';
|
|
9
9
|
import { Trans, useTranslation } from 'react-i18next';
|
|
10
10
|
import { Link, useNavigate } from 'react-router-dom';
|
|
11
11
|
|
|
12
12
|
import PluginAvatar from '@/components/Plugins/PluginAvatar';
|
|
13
13
|
import PluginTag from '@/components/Plugins/PluginTag';
|
|
14
14
|
import { FORM_STYLE } from '@/const/layoutTokens';
|
|
15
|
-
import
|
|
15
|
+
import { createSkillStoreModal } from '@/features/SkillStore';
|
|
16
16
|
import { useFetchInstalledPlugins } from '@/hooks/useFetchInstalledPlugins';
|
|
17
17
|
import { featureFlagsSelectors, useServerConfigStore } from '@/store/serverConfig';
|
|
18
18
|
import { pluginHelpers, useToolStore } from '@/store/tool';
|
|
@@ -27,10 +27,12 @@ import PluginAction from './PluginAction';
|
|
|
27
27
|
const AgentPlugin = memo(() => {
|
|
28
28
|
const { t } = useTranslation('setting');
|
|
29
29
|
|
|
30
|
-
const [showStore, setShowStore] = useState(false);
|
|
31
|
-
|
|
32
30
|
const navigate = useNavigate();
|
|
33
31
|
|
|
32
|
+
const handleOpenStore = useCallback(() => {
|
|
33
|
+
createSkillStoreModal();
|
|
34
|
+
}, []);
|
|
35
|
+
|
|
34
36
|
const [userEnabledPlugins, toggleAgentPlugin] = useStore((s) => [
|
|
35
37
|
s.config.plugins || [],
|
|
36
38
|
s.toggleAgentPlugin,
|
|
@@ -120,7 +122,7 @@ const AgentPlugin = memo(() => {
|
|
|
120
122
|
icon={Store}
|
|
121
123
|
onClick={(e) => {
|
|
122
124
|
e.stopPropagation();
|
|
123
|
-
|
|
125
|
+
handleOpenStore();
|
|
124
126
|
}}
|
|
125
127
|
size={'small'}
|
|
126
128
|
/>
|
|
@@ -139,7 +141,7 @@ const AgentPlugin = memo(() => {
|
|
|
139
141
|
onClick={(e) => {
|
|
140
142
|
e.stopPropagation();
|
|
141
143
|
e.preventDefault();
|
|
142
|
-
|
|
144
|
+
handleOpenStore();
|
|
143
145
|
navigate('/community/mcp');
|
|
144
146
|
}}
|
|
145
147
|
to={'/community/mcp'}
|
|
@@ -168,12 +170,7 @@ const AgentPlugin = memo(() => {
|
|
|
168
170
|
title: t('settingPlugin.title'),
|
|
169
171
|
};
|
|
170
172
|
|
|
171
|
-
return
|
|
172
|
-
<>
|
|
173
|
-
<SkillStore open={showStore} setOpen={setShowStore} />
|
|
174
|
-
<Form items={[plugin]} itemsType={'group'} variant={'borderless'} {...FORM_STYLE} />
|
|
175
|
-
</>
|
|
176
|
-
);
|
|
173
|
+
return <Form items={[plugin]} itemsType={'group'} variant={'borderless'} {...FORM_STYLE} />;
|
|
177
174
|
});
|
|
178
175
|
|
|
179
176
|
export default AgentPlugin;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Blocks } from 'lucide-react';
|
|
2
|
-
import { Suspense, memo, useState } from 'react';
|
|
2
|
+
import { Suspense, memo, useCallback, useState } from 'react';
|
|
3
3
|
import { useTranslation } from 'react-i18next';
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import { createSkillStoreModal } from '@/features/SkillStore';
|
|
6
6
|
import { useModelSupportToolUse } from '@/hooks/useModelSupportToolUse';
|
|
7
7
|
import { useAgentStore } from '@/store/agent';
|
|
8
8
|
import { agentByIdSelectors } from '@/store/agent/selectors';
|
|
@@ -15,7 +15,6 @@ import { useControls } from './useControls';
|
|
|
15
15
|
|
|
16
16
|
const Tools = memo(() => {
|
|
17
17
|
const { t } = useTranslation('setting');
|
|
18
|
-
const [modalOpen, setModalOpen] = useState(false);
|
|
19
18
|
const [updating, setUpdating] = useState(false);
|
|
20
19
|
const { marketItems } = useControls({
|
|
21
20
|
setUpdating,
|
|
@@ -29,6 +28,10 @@ const Tools = memo(() => {
|
|
|
29
28
|
|
|
30
29
|
const enableFC = useModelSupportToolUse(model, provider);
|
|
31
30
|
|
|
31
|
+
const handleOpenStore = useCallback(() => {
|
|
32
|
+
createSkillStoreModal();
|
|
33
|
+
}, []);
|
|
34
|
+
|
|
32
35
|
if (!enableFC)
|
|
33
36
|
return <Action disabled icon={Blocks} showTooltip={true} title={t('tools.disabled')} />;
|
|
34
37
|
|
|
@@ -42,7 +45,7 @@ const Tools = memo(() => {
|
|
|
42
45
|
<PopoverContent
|
|
43
46
|
enableKlavis={enableKlavis}
|
|
44
47
|
items={marketItems}
|
|
45
|
-
onOpenStore={
|
|
48
|
+
onOpenStore={handleOpenStore}
|
|
46
49
|
/>
|
|
47
50
|
),
|
|
48
51
|
maxWidth: 320,
|
|
@@ -56,7 +59,6 @@ const Tools = memo(() => {
|
|
|
56
59
|
showTooltip={false}
|
|
57
60
|
title={t('tools.title')}
|
|
58
61
|
/>
|
|
59
|
-
<SkillStore open={modalOpen} setOpen={setModalOpen} />
|
|
60
62
|
</Suspense>
|
|
61
63
|
);
|
|
62
64
|
});
|
|
@@ -11,12 +11,12 @@ import {
|
|
|
11
11
|
Puzzle,
|
|
12
12
|
Sparkles,
|
|
13
13
|
} from 'lucide-react';
|
|
14
|
-
import { markdownToTxt } from 'markdown-to-txt';
|
|
15
14
|
import { memo } from 'react';
|
|
16
15
|
import { useTranslation } from 'react-i18next';
|
|
17
16
|
import { useNavigate } from 'react-router-dom';
|
|
18
17
|
|
|
19
18
|
import type { SearchResult } from '@/database/repositories/search';
|
|
19
|
+
import { markdownToTxt } from '@/utils/markdownToTxt';
|
|
20
20
|
|
|
21
21
|
import { CommandItem } from './components';
|
|
22
22
|
import { styles } from './styles';
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { memo } from 'react';
|
|
4
|
+
import { createPortal } from 'react-dom';
|
|
5
|
+
|
|
6
|
+
import { messageStateSelectors, useConversationStore, virtuaListSelectors } from '../../../store';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 判断是否在底部的阈值(单位:px)
|
|
10
|
+
* 当距离底部小于等于此值时,认为在底部
|
|
11
|
+
*/
|
|
12
|
+
export const AT_BOTTOM_THRESHOLD = 300;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* 是否开启调试面板
|
|
16
|
+
* 设为 true 可以显示滚动位置调试信息
|
|
17
|
+
*/
|
|
18
|
+
export const OPEN_DEV_INSPECTOR = false;
|
|
19
|
+
|
|
20
|
+
const DebugInspector = memo(() => {
|
|
21
|
+
const atBottom = useConversationStore(virtuaListSelectors.atBottom);
|
|
22
|
+
const isScrolling = useConversationStore(virtuaListSelectors.isScrolling);
|
|
23
|
+
const isGenerating = useConversationStore(messageStateSelectors.isAIGenerating);
|
|
24
|
+
const virtuaScrollMethods = useConversationStore((s) => s.virtuaScrollMethods);
|
|
25
|
+
|
|
26
|
+
const shouldAutoScroll = atBottom && isGenerating && !isScrolling;
|
|
27
|
+
const scrollOffset = virtuaScrollMethods?.getScrollOffset?.() ?? 0;
|
|
28
|
+
const scrollSize = virtuaScrollMethods?.getScrollSize?.() ?? 0;
|
|
29
|
+
const viewportSize = virtuaScrollMethods?.getViewportSize?.() ?? 0;
|
|
30
|
+
const distanceToBottom = scrollSize - scrollOffset - viewportSize;
|
|
31
|
+
// 可视化计算
|
|
32
|
+
const visualHeight = 120;
|
|
33
|
+
const scale = scrollSize > 0 ? visualHeight / scrollSize : 0;
|
|
34
|
+
const viewportVisualHeight = Math.max(viewportSize * scale, 10);
|
|
35
|
+
const scrollVisualOffset = scrollOffset * scale;
|
|
36
|
+
const thresholdVisualHeight = Math.min(AT_BOTTOM_THRESHOLD * scale, visualHeight * 0.3);
|
|
37
|
+
|
|
38
|
+
const panel = (
|
|
39
|
+
<div
|
|
40
|
+
style={{
|
|
41
|
+
background: 'rgba(0,0,0,0.9)',
|
|
42
|
+
borderRadius: 8,
|
|
43
|
+
bottom: 80,
|
|
44
|
+
display: 'flex',
|
|
45
|
+
fontFamily: 'monospace',
|
|
46
|
+
fontSize: 11,
|
|
47
|
+
gap: 16,
|
|
48
|
+
left: 12,
|
|
49
|
+
padding: '10px 14px',
|
|
50
|
+
position: 'fixed',
|
|
51
|
+
zIndex: 9999,
|
|
52
|
+
}}
|
|
53
|
+
>
|
|
54
|
+
{/* 滚动条可视化 */}
|
|
55
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
|
|
56
|
+
<div style={{ color: '#9ca3af', fontSize: 10 }}>Scroll Position</div>
|
|
57
|
+
<div
|
|
58
|
+
style={{
|
|
59
|
+
background: '#374151',
|
|
60
|
+
borderRadius: 3,
|
|
61
|
+
height: visualHeight,
|
|
62
|
+
position: 'relative',
|
|
63
|
+
width: 24,
|
|
64
|
+
}}
|
|
65
|
+
>
|
|
66
|
+
{/* threshold 区域 (底部 200px) */}
|
|
67
|
+
<div
|
|
68
|
+
style={{
|
|
69
|
+
background: atBottom ? 'rgba(34, 197, 94, 0.3)' : 'rgba(239, 68, 68, 0.3)',
|
|
70
|
+
borderRadius: '0 0 3px 3px',
|
|
71
|
+
bottom: 0,
|
|
72
|
+
height: thresholdVisualHeight,
|
|
73
|
+
left: 0,
|
|
74
|
+
position: 'absolute',
|
|
75
|
+
right: 0,
|
|
76
|
+
}}
|
|
77
|
+
/>
|
|
78
|
+
{/* 当前视口位置 */}
|
|
79
|
+
<div
|
|
80
|
+
style={{
|
|
81
|
+
background: atBottom ? '#22c55e' : '#3b82f6',
|
|
82
|
+
borderRadius: 2,
|
|
83
|
+
height: viewportVisualHeight,
|
|
84
|
+
left: 2,
|
|
85
|
+
position: 'absolute',
|
|
86
|
+
right: 2,
|
|
87
|
+
top: scrollVisualOffset,
|
|
88
|
+
transition: 'top 0.1s',
|
|
89
|
+
}}
|
|
90
|
+
/>
|
|
91
|
+
{/* threshold 线 */}
|
|
92
|
+
<div
|
|
93
|
+
style={{
|
|
94
|
+
background: '#f59e0b',
|
|
95
|
+
bottom: thresholdVisualHeight,
|
|
96
|
+
height: 1,
|
|
97
|
+
left: 0,
|
|
98
|
+
position: 'absolute',
|
|
99
|
+
right: 0,
|
|
100
|
+
}}
|
|
101
|
+
/>
|
|
102
|
+
</div>
|
|
103
|
+
<div style={{ color: '#f59e0b', fontSize: 9, textAlign: 'center' }}>
|
|
104
|
+
{AT_BOTTOM_THRESHOLD}px
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
|
|
108
|
+
{/* 数值信息 */}
|
|
109
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
|
|
110
|
+
<div style={{ color: '#9ca3af', fontSize: 10 }}>
|
|
111
|
+
scrollSize: <span style={{ color: 'white' }}>{Math.round(scrollSize)}px</span>
|
|
112
|
+
</div>
|
|
113
|
+
<div style={{ color: '#9ca3af', fontSize: 10 }}>
|
|
114
|
+
viewport: <span style={{ color: 'white' }}>{Math.round(viewportSize)}px</span>
|
|
115
|
+
</div>
|
|
116
|
+
<div style={{ color: '#9ca3af', fontSize: 10 }}>
|
|
117
|
+
offset: <span style={{ color: 'white' }}>{Math.round(scrollOffset)}px</span>
|
|
118
|
+
</div>
|
|
119
|
+
<div
|
|
120
|
+
style={{
|
|
121
|
+
color: atBottom ? '#22c55e' : '#ef4444',
|
|
122
|
+
fontSize: 10,
|
|
123
|
+
fontWeight: 'bold',
|
|
124
|
+
}}
|
|
125
|
+
>
|
|
126
|
+
toBottom: {Math.round(distanceToBottom)}px
|
|
127
|
+
{distanceToBottom <= AT_BOTTOM_THRESHOLD ? ' ≤' : ' >'} {AT_BOTTOM_THRESHOLD}
|
|
128
|
+
</div>
|
|
129
|
+
|
|
130
|
+
<div style={{ borderTop: '1px solid #374151', marginTop: 4, paddingTop: 4 }}>
|
|
131
|
+
<div style={{ color: atBottom ? '#22c55e' : '#ef4444', fontSize: 10 }}>
|
|
132
|
+
atBottom: {atBottom ? 'YES' : 'NO'}
|
|
133
|
+
</div>
|
|
134
|
+
<div style={{ color: isGenerating ? '#3b82f6' : '#6b7280', fontSize: 10 }}>
|
|
135
|
+
generating: {isGenerating ? 'YES' : 'NO'}
|
|
136
|
+
</div>
|
|
137
|
+
<div style={{ color: isScrolling ? '#f59e0b' : '#6b7280', fontSize: 10 }}>
|
|
138
|
+
scrolling: {isScrolling ? 'YES' : 'NO'}
|
|
139
|
+
</div>
|
|
140
|
+
</div>
|
|
141
|
+
|
|
142
|
+
<div
|
|
143
|
+
style={{
|
|
144
|
+
background: shouldAutoScroll ? '#22c55e' : '#ef4444',
|
|
145
|
+
borderRadius: 3,
|
|
146
|
+
color: 'white',
|
|
147
|
+
fontSize: 10,
|
|
148
|
+
marginTop: 4,
|
|
149
|
+
padding: '2px 6px',
|
|
150
|
+
textAlign: 'center',
|
|
151
|
+
}}
|
|
152
|
+
>
|
|
153
|
+
autoScroll: {shouldAutoScroll ? 'YES' : 'NO'}
|
|
154
|
+
</div>
|
|
155
|
+
</div>
|
|
156
|
+
</div>
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
if (typeof document === 'undefined') return null;
|
|
160
|
+
|
|
161
|
+
return createPortal(panel, document.body);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
DebugInspector.displayName = 'DebugInspector';
|
|
165
|
+
|
|
166
|
+
export default DebugInspector;
|