@lobehub/lobehub 2.0.0-next.343 → 2.0.0-next.345
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/Dockerfile +3 -13
- package/README.md +3 -5
- package/README.zh-CN.md +3 -5
- package/changelog/v1.json +24 -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 +7 -9
- 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/builtin-tool-cloud-sandbox/src/ExecutionRuntime/index.ts +161 -12
- 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/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/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)/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/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/MasonryView/MasonryFileItem/NoteFileItem.tsx +1 -1
- 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 +6 -0
- 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/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
|
@@ -1,30 +1,9 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { Skeleton } from '@lobehub/ui';
|
|
4
|
-
import { useTranslation } from 'react-i18next';
|
|
5
3
|
import { Navigate } from 'react-router-dom';
|
|
6
4
|
|
|
7
|
-
import SettingHeader from '@/app/[variants]/(main)/settings/features/SettingHeader';
|
|
8
|
-
import { enableClerk } from '@/envs/auth';
|
|
9
|
-
import dynamic from '@/libs/next/dynamic';
|
|
10
|
-
|
|
11
|
-
const ClerkProfile = dynamic(() => import('./features/ClerkProfile'), {
|
|
12
|
-
loading: () => (
|
|
13
|
-
<div style={{ flex: 1 }}>
|
|
14
|
-
<Skeleton paragraph={{ rows: 8 }} title={false} />
|
|
15
|
-
</div>
|
|
16
|
-
),
|
|
17
|
-
});
|
|
18
|
-
|
|
19
5
|
const Page = () => {
|
|
20
|
-
|
|
21
|
-
if (!enableClerk) return <Navigate replace to="/settings" />;
|
|
22
|
-
return (
|
|
23
|
-
<>
|
|
24
|
-
<SettingHeader title={t('tab.security')} />
|
|
25
|
-
<ClerkProfile />
|
|
26
|
-
</>
|
|
27
|
-
);
|
|
6
|
+
return <Navigate replace to="/settings" />;
|
|
28
7
|
};
|
|
29
8
|
|
|
30
9
|
export default Page;
|
|
@@ -8,7 +8,7 @@ import { Loader2, MoreVerticalIcon, SquareArrowOutUpRight, Unplug } from 'lucide
|
|
|
8
8
|
import { memo, useCallback, useEffect, useRef, useState } from 'react';
|
|
9
9
|
import { useTranslation } from 'react-i18next';
|
|
10
10
|
|
|
11
|
-
import
|
|
11
|
+
import { createIntegrationDetailModal } from '@/features/IntegrationDetailModal';
|
|
12
12
|
import { useToolStore } from '@/store/tool';
|
|
13
13
|
import { type KlavisServer, KlavisServerStatus } from '@/store/tool/slices/klavisStore';
|
|
14
14
|
import { useUserStore } from '@/store/user';
|
|
@@ -72,7 +72,6 @@ const KlavisSkillItem = memo<KlavisSkillItemProps>(({ serverType, server }) => {
|
|
|
72
72
|
const { modal } = App.useApp();
|
|
73
73
|
const [isConnecting, setIsConnecting] = useState(false);
|
|
74
74
|
const [isWaitingAuth, setIsWaitingAuth] = useState(false);
|
|
75
|
-
const [detailOpen, setDetailOpen] = useState(false);
|
|
76
75
|
|
|
77
76
|
const oauthWindowRef = useRef<Window | null>(null);
|
|
78
77
|
const windowCheckIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
|
@@ -313,8 +312,7 @@ const KlavisSkillItem = memo<KlavisSkillItemProps>(({ serverType, server }) => {
|
|
|
313
312
|
const isConnected = server?.status === KlavisServerStatus.CONNECTED;
|
|
314
313
|
|
|
315
314
|
return (
|
|
316
|
-
|
|
317
|
-
<Flexbox
|
|
315
|
+
<Flexbox
|
|
318
316
|
align="center"
|
|
319
317
|
className={styles.container}
|
|
320
318
|
gap={16}
|
|
@@ -324,7 +322,16 @@ const KlavisSkillItem = memo<KlavisSkillItemProps>(({ serverType, server }) => {
|
|
|
324
322
|
<Flexbox align="center" gap={16} horizontal style={{ flex: 1, overflow: 'hidden' }}>
|
|
325
323
|
<div className={styles.icon}>{renderIcon()}</div>
|
|
326
324
|
<Flexbox gap={4} style={{ overflow: 'hidden' }}>
|
|
327
|
-
<span
|
|
325
|
+
<span
|
|
326
|
+
className={styles.title}
|
|
327
|
+
onClick={() =>
|
|
328
|
+
createIntegrationDetailModal({
|
|
329
|
+
identifier: serverType.identifier,
|
|
330
|
+
serverName: serverType.serverName,
|
|
331
|
+
type: 'klavis',
|
|
332
|
+
})
|
|
333
|
+
}
|
|
334
|
+
>
|
|
328
335
|
{serverType.label}
|
|
329
336
|
</span>
|
|
330
337
|
{!isConnected && renderStatus()}
|
|
@@ -335,15 +342,6 @@ const KlavisSkillItem = memo<KlavisSkillItemProps>(({ serverType, server }) => {
|
|
|
335
342
|
{renderAction()}
|
|
336
343
|
</Flexbox>
|
|
337
344
|
</Flexbox>
|
|
338
|
-
<IntegrationDetailModal
|
|
339
|
-
identifier={serverType.identifier}
|
|
340
|
-
isConnecting={isConnecting || isWaitingAuth}
|
|
341
|
-
onClose={() => setDetailOpen(false)}
|
|
342
|
-
onConnect={handleConnect}
|
|
343
|
-
open={detailOpen}
|
|
344
|
-
type="klavis"
|
|
345
|
-
/>
|
|
346
|
-
</>
|
|
347
345
|
);
|
|
348
346
|
});
|
|
349
347
|
|
|
@@ -8,7 +8,7 @@ import { Loader2, MoreVerticalIcon, SquareArrowOutUpRight, Unplug } from 'lucide
|
|
|
8
8
|
import { memo, useCallback, useEffect, useRef, useState } from 'react';
|
|
9
9
|
import { useTranslation } from 'react-i18next';
|
|
10
10
|
|
|
11
|
-
import
|
|
11
|
+
import { createIntegrationDetailModal } from '@/features/IntegrationDetailModal';
|
|
12
12
|
import { useToolStore } from '@/store/tool';
|
|
13
13
|
import {
|
|
14
14
|
type LobehubSkillServer,
|
|
@@ -75,7 +75,6 @@ const LobehubSkillItem = memo<LobehubSkillItemProps>(({ provider, server }) => {
|
|
|
75
75
|
const { modal } = App.useApp();
|
|
76
76
|
const [isConnecting, setIsConnecting] = useState(false);
|
|
77
77
|
const [isWaitingAuth, setIsWaitingAuth] = useState(false);
|
|
78
|
-
const [detailOpen, setDetailOpen] = useState(false);
|
|
79
78
|
|
|
80
79
|
const oauthWindowRef = useRef<Window | null>(null);
|
|
81
80
|
const windowCheckIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
|
@@ -299,8 +298,7 @@ const LobehubSkillItem = memo<LobehubSkillItemProps>(({ provider, server }) => {
|
|
|
299
298
|
const isConnected = server?.status === LobehubSkillStatus.CONNECTED;
|
|
300
299
|
|
|
301
300
|
return (
|
|
302
|
-
|
|
303
|
-
<Flexbox
|
|
301
|
+
<Flexbox
|
|
304
302
|
align="center"
|
|
305
303
|
className={styles.container}
|
|
306
304
|
gap={16}
|
|
@@ -314,7 +312,12 @@ const LobehubSkillItem = memo<LobehubSkillItemProps>(({ provider, server }) => {
|
|
|
314
312
|
<Flexbox gap={4} style={{ overflow: 'hidden' }}>
|
|
315
313
|
<span
|
|
316
314
|
className={`${styles.title} ${!isConnected ? styles.disconnectedTitle : ''}`}
|
|
317
|
-
onClick={() =>
|
|
315
|
+
onClick={() =>
|
|
316
|
+
createIntegrationDetailModal({
|
|
317
|
+
identifier: provider.id,
|
|
318
|
+
type: 'lobehub',
|
|
319
|
+
})
|
|
320
|
+
}
|
|
318
321
|
>
|
|
319
322
|
{provider.label}
|
|
320
323
|
</span>
|
|
@@ -326,15 +329,6 @@ const LobehubSkillItem = memo<LobehubSkillItemProps>(({ provider, server }) => {
|
|
|
326
329
|
{renderAction()}
|
|
327
330
|
</Flexbox>
|
|
328
331
|
</Flexbox>
|
|
329
|
-
<IntegrationDetailModal
|
|
330
|
-
identifier={provider.id}
|
|
331
|
-
isConnecting={isConnecting || isWaitingAuth}
|
|
332
|
-
onClose={() => setDetailOpen(false)}
|
|
333
|
-
onConnect={handleConnect}
|
|
334
|
-
open={detailOpen}
|
|
335
|
-
type="lobehub"
|
|
336
|
-
/>
|
|
337
|
-
</>
|
|
338
332
|
);
|
|
339
333
|
});
|
|
340
334
|
|
|
@@ -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';
|