@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
|
@@ -3,10 +3,9 @@
|
|
|
3
3
|
import { KLAVIS_SERVER_TYPES, LOBEHUB_SKILL_PROVIDERS } from '@lobechat/const';
|
|
4
4
|
import { createStaticStyles } from 'antd-style';
|
|
5
5
|
import isEqual from 'fast-deep-equal';
|
|
6
|
-
import
|
|
7
|
-
import { memo, useMemo, useState } from 'react';
|
|
6
|
+
import { memo, useCallback, useMemo } from 'react';
|
|
8
7
|
|
|
9
|
-
import
|
|
8
|
+
import { createIntegrationDetailModal } from '@/features/IntegrationDetailModal';
|
|
10
9
|
import { serverConfigSelectors, useServerConfigStore } from '@/store/serverConfig';
|
|
11
10
|
import { useToolStore } from '@/store/tool';
|
|
12
11
|
import { klavisStoreSelectors, lobehubSkillStoreSelectors } from '@/store/tool/selectors';
|
|
@@ -15,7 +14,6 @@ import { LobehubSkillStatus } from '@/store/tool/slices/lobehubSkillStore/types'
|
|
|
15
14
|
|
|
16
15
|
import Empty from '../Empty';
|
|
17
16
|
import Item from './Item';
|
|
18
|
-
import { useSkillConnect } from './useSkillConnect';
|
|
19
17
|
|
|
20
18
|
const styles = createStaticStyles(({ css }) => ({
|
|
21
19
|
grid: css`
|
|
@@ -36,40 +34,7 @@ interface LobeHubListProps {
|
|
|
36
34
|
keywords: string;
|
|
37
35
|
}
|
|
38
36
|
|
|
39
|
-
interface DetailState {
|
|
40
|
-
identifier: string;
|
|
41
|
-
serverName?: Klavis.McpServerName;
|
|
42
|
-
type: 'klavis' | 'lobehub';
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
interface DetailModalWithConnectProps {
|
|
46
|
-
detailState: DetailState;
|
|
47
|
-
onClose: () => void;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const DetailModalWithConnect = memo<DetailModalWithConnectProps>(({ detailState, onClose }) => {
|
|
51
|
-
const { handleConnect, isConnecting } = useSkillConnect({
|
|
52
|
-
identifier: detailState.identifier,
|
|
53
|
-
serverName: detailState.serverName,
|
|
54
|
-
type: detailState.type,
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
return (
|
|
58
|
-
<IntegrationDetailModal
|
|
59
|
-
identifier={detailState.identifier}
|
|
60
|
-
isConnecting={isConnecting}
|
|
61
|
-
onClose={onClose}
|
|
62
|
-
onConnect={handleConnect}
|
|
63
|
-
open
|
|
64
|
-
type={detailState.type}
|
|
65
|
-
/>
|
|
66
|
-
);
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
DetailModalWithConnect.displayName = 'DetailModalWithConnect';
|
|
70
|
-
|
|
71
37
|
export const LobeHubList = memo<LobeHubListProps>(({ keywords }) => {
|
|
72
|
-
const [detailState, setDetailState] = useState<DetailState | null>(null);
|
|
73
38
|
|
|
74
39
|
const isLobehubSkillEnabled = useServerConfigStore(serverConfigSelectors.enableLobehubSkill);
|
|
75
40
|
const isKlavisEnabled = useServerConfigStore(serverConfigSelectors.enableKlavis);
|
|
@@ -84,13 +49,19 @@ export const LobeHubList = memo<LobeHubListProps>(({ keywords }) => {
|
|
|
84
49
|
useFetchLobehubSkillConnections(isLobehubSkillEnabled);
|
|
85
50
|
useFetchUserKlavisServers(isKlavisEnabled);
|
|
86
51
|
|
|
87
|
-
const getLobehubSkillServerByProvider = (
|
|
88
|
-
|
|
89
|
-
|
|
52
|
+
const getLobehubSkillServerByProvider = useCallback(
|
|
53
|
+
(providerId: string) => {
|
|
54
|
+
return allLobehubSkillServers.find((server) => server.identifier === providerId);
|
|
55
|
+
},
|
|
56
|
+
[allLobehubSkillServers],
|
|
57
|
+
);
|
|
90
58
|
|
|
91
|
-
const getKlavisServerByIdentifier = (
|
|
92
|
-
|
|
93
|
-
|
|
59
|
+
const getKlavisServerByIdentifier = useCallback(
|
|
60
|
+
(identifier: string) => {
|
|
61
|
+
return allKlavisServers.find((server) => server.identifier === identifier);
|
|
62
|
+
},
|
|
63
|
+
[allKlavisServers],
|
|
64
|
+
);
|
|
94
65
|
|
|
95
66
|
const filteredItems = useMemo(() => {
|
|
96
67
|
const items: Array<
|
|
@@ -127,57 +98,49 @@ export const LobeHubList = memo<LobeHubListProps>(({ keywords }) => {
|
|
|
127
98
|
if (filteredItems.length === 0) return <Empty search={hasSearchKeywords} />;
|
|
128
99
|
|
|
129
100
|
return (
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
const isConnected = server?.status === LobehubSkillStatus.CONNECTED;
|
|
136
|
-
return (
|
|
137
|
-
<Item
|
|
138
|
-
description={item.provider.description}
|
|
139
|
-
icon={item.provider.icon}
|
|
140
|
-
identifier={item.provider.id}
|
|
141
|
-
isConnected={isConnected}
|
|
142
|
-
key={item.provider.id}
|
|
143
|
-
label={item.provider.label}
|
|
144
|
-
onOpenDetail={() =>
|
|
145
|
-
setDetailState({ identifier: item.provider.id, type: 'lobehub' })
|
|
146
|
-
}
|
|
147
|
-
type="lobehub"
|
|
148
|
-
/>
|
|
149
|
-
);
|
|
150
|
-
}
|
|
151
|
-
const server = getKlavisServerByIdentifier(item.serverType.identifier);
|
|
152
|
-
const isConnected = server?.status === KlavisServerStatus.CONNECTED;
|
|
101
|
+
<div className={styles.grid}>
|
|
102
|
+
{filteredItems.map((item) => {
|
|
103
|
+
if (item.type === 'lobehub') {
|
|
104
|
+
const server = getLobehubSkillServerByProvider(item.provider.id);
|
|
105
|
+
const isConnected = server?.status === LobehubSkillStatus.CONNECTED;
|
|
153
106
|
return (
|
|
154
107
|
<Item
|
|
155
|
-
description={item.
|
|
156
|
-
icon={item.
|
|
157
|
-
identifier={item.
|
|
108
|
+
description={item.provider.description}
|
|
109
|
+
icon={item.provider.icon}
|
|
110
|
+
identifier={item.provider.id}
|
|
158
111
|
isConnected={isConnected}
|
|
159
|
-
key={item.
|
|
160
|
-
label={item.
|
|
112
|
+
key={item.provider.id}
|
|
113
|
+
label={item.provider.label}
|
|
161
114
|
onOpenDetail={() =>
|
|
162
|
-
|
|
163
|
-
identifier: item.serverType.identifier,
|
|
164
|
-
serverName: item.serverType.serverName,
|
|
165
|
-
type: 'klavis',
|
|
166
|
-
})
|
|
115
|
+
createIntegrationDetailModal({ identifier: item.provider.id, type: 'lobehub' })
|
|
167
116
|
}
|
|
168
|
-
|
|
169
|
-
type="klavis"
|
|
117
|
+
type="lobehub"
|
|
170
118
|
/>
|
|
171
119
|
);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
120
|
+
}
|
|
121
|
+
const server = getKlavisServerByIdentifier(item.serverType.identifier);
|
|
122
|
+
const isConnected = server?.status === KlavisServerStatus.CONNECTED;
|
|
123
|
+
return (
|
|
124
|
+
<Item
|
|
125
|
+
description={item.serverType.description}
|
|
126
|
+
icon={item.serverType.icon}
|
|
127
|
+
identifier={item.serverType.identifier}
|
|
128
|
+
isConnected={isConnected}
|
|
129
|
+
key={item.serverType.identifier}
|
|
130
|
+
label={item.serverType.label}
|
|
131
|
+
onOpenDetail={() =>
|
|
132
|
+
createIntegrationDetailModal({
|
|
133
|
+
identifier: item.serverType.identifier,
|
|
134
|
+
serverName: item.serverType.serverName,
|
|
135
|
+
type: 'klavis',
|
|
136
|
+
})
|
|
137
|
+
}
|
|
138
|
+
serverName={item.serverType.serverName}
|
|
139
|
+
type="klavis"
|
|
140
|
+
/>
|
|
141
|
+
);
|
|
142
|
+
})}
|
|
143
|
+
</div>
|
|
181
144
|
);
|
|
182
145
|
});
|
|
183
146
|
|
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
import { Flexbox, Segmented } from '@lobehub/ui';
|
|
4
4
|
import { type SegmentedOptions } from 'antd/es/segmented';
|
|
5
|
-
import {
|
|
5
|
+
import { useState } from 'react';
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
7
7
|
|
|
8
8
|
import AddSkillButton from './AddSkillButton';
|
|
9
|
-
|
|
10
9
|
import CommunityList from './CommunityList';
|
|
11
10
|
import LobeHubList from './LobeHubList';
|
|
12
11
|
import Search from './Search';
|
|
@@ -16,7 +15,7 @@ export enum SkillStoreTab {
|
|
|
16
15
|
LobeHub = 'lobehub',
|
|
17
16
|
}
|
|
18
17
|
|
|
19
|
-
export const
|
|
18
|
+
export const SkillStoreContent = () => {
|
|
20
19
|
const { t } = useTranslation('setting');
|
|
21
20
|
const [activeTab, setActiveTab] = useState<SkillStoreTab>(SkillStoreTab.LobeHub);
|
|
22
21
|
const [lobehubKeywords, setLobehubKeywords] = useState('');
|
|
@@ -52,8 +51,4 @@ export const Content = memo(() => {
|
|
|
52
51
|
</Flexbox>
|
|
53
52
|
</Flexbox>
|
|
54
53
|
);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
Content.displayName = 'SkillStoreContent';
|
|
58
|
-
|
|
59
|
-
export default Content;
|
|
54
|
+
};
|
|
@@ -1,37 +1,19 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { createModal } from '@lobehub/ui';
|
|
4
|
+
import { t } from 'i18next';
|
|
6
5
|
|
|
7
|
-
import
|
|
6
|
+
import { SkillStoreContent } from './SkillStoreContent';
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
footer={null}
|
|
22
|
-
onCancel={() => setOpen(false)}
|
|
23
|
-
open={open}
|
|
24
|
-
styles={{
|
|
25
|
-
body: { overflow: 'hidden', padding: 0 },
|
|
26
|
-
}}
|
|
27
|
-
title={t('skillStore.title')}
|
|
28
|
-
width={'min(80%, 800px)'}
|
|
29
|
-
>
|
|
30
|
-
<Content />
|
|
31
|
-
</Modal>
|
|
32
|
-
);
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
SkillStore.displayName = 'SkillStore';
|
|
36
|
-
|
|
37
|
-
export default SkillStore;
|
|
8
|
+
export const createSkillStoreModal = () =>
|
|
9
|
+
createModal({
|
|
10
|
+
allowFullscreen: true,
|
|
11
|
+
children: <SkillStoreContent />,
|
|
12
|
+
destroyOnHidden: false,
|
|
13
|
+
footer: null,
|
|
14
|
+
styles: {
|
|
15
|
+
body: { overflow: 'hidden', padding: 0 },
|
|
16
|
+
},
|
|
17
|
+
title: t('skillStore.title', { ns: 'setting' }),
|
|
18
|
+
width: 'min(80%, 800px)',
|
|
19
|
+
});
|
|
@@ -10,8 +10,6 @@ import BusinessPanelContent from '@/business/client/features/User/BusinessPanelC
|
|
|
10
10
|
import BrandWatermark from '@/components/BrandWatermark';
|
|
11
11
|
import Menu from '@/components/Menu';
|
|
12
12
|
import { isDesktop } from '@/const/version';
|
|
13
|
-
import { enableBetterAuth, enableNextAuth } from '@/envs/auth';
|
|
14
|
-
import { useRouter } from '@/libs/next/navigation';
|
|
15
13
|
import { useUserStore } from '@/store/user';
|
|
16
14
|
import { authSelectors } from '@/store/user/selectors';
|
|
17
15
|
|
|
@@ -22,8 +20,6 @@ import LangButton from './LangButton';
|
|
|
22
20
|
import { useMenu } from './useMenu';
|
|
23
21
|
|
|
24
22
|
const PanelContent = memo<{ closePopover: () => void }>(({ closePopover }) => {
|
|
25
|
-
const router = useRouter();
|
|
26
|
-
|
|
27
23
|
const isLoginWithAuth = useUserStore(authSelectors.isLoginWithAuth);
|
|
28
24
|
const [openSignIn, signOut] = useUserStore((s) => [s.openLogin, s.logout]);
|
|
29
25
|
const { mainItems, logoutItems } = useMenu();
|
|
@@ -52,10 +48,6 @@ const PanelContent = memo<{ closePopover: () => void }>(({ closePopover }) => {
|
|
|
52
48
|
|
|
53
49
|
signOut();
|
|
54
50
|
closePopover();
|
|
55
|
-
// NextAuth and Better Auth handle redirect in their own signOut methods
|
|
56
|
-
if (enableNextAuth || enableBetterAuth) return;
|
|
57
|
-
// Clerk uses /login page
|
|
58
|
-
router.push('/login');
|
|
59
51
|
};
|
|
60
52
|
|
|
61
53
|
return (
|
|
@@ -68,19 +68,11 @@ vi.mock('@/const/version', () => ({
|
|
|
68
68
|
}));
|
|
69
69
|
|
|
70
70
|
// Use vi.hoisted to ensure variables exist before vi.mock factory executes
|
|
71
|
-
const {
|
|
72
|
-
enableAuth: { value: true },
|
|
73
|
-
enableClerk: { value: false },
|
|
71
|
+
const { enableNextAuth } = vi.hoisted(() => ({
|
|
74
72
|
enableNextAuth: { value: false },
|
|
75
73
|
}));
|
|
76
74
|
|
|
77
75
|
vi.mock('@/envs/auth', () => ({
|
|
78
|
-
get enableAuth() {
|
|
79
|
-
return enableAuth.value;
|
|
80
|
-
},
|
|
81
|
-
get enableClerk() {
|
|
82
|
-
return enableClerk.value;
|
|
83
|
-
},
|
|
84
76
|
get enableNextAuth() {
|
|
85
77
|
return enableNextAuth.value;
|
|
86
78
|
},
|
|
@@ -140,32 +132,6 @@ describe('PanelContent', () => {
|
|
|
140
132
|
});
|
|
141
133
|
});
|
|
142
134
|
|
|
143
|
-
describe('disable auth', () => {
|
|
144
|
-
it('should render UserInfo', () => {
|
|
145
|
-
act(() => {
|
|
146
|
-
useUserStore.setState({ isSignedIn: true });
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
renderWithRouter(<PanelContent closePopover={closePopover} />);
|
|
150
|
-
|
|
151
|
-
expect(screen.getByText('Mocked UserInfo')).toBeInTheDocument();
|
|
152
|
-
expect(screen.getByText('Mocked DataStatistics')).toBeInTheDocument();
|
|
153
|
-
expect(screen.queryByText('Mocked SignInBlock')).not.toBeInTheDocument();
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
it('should render BrandWatermark when disable auth', () => {
|
|
157
|
-
enableAuth.value = false;
|
|
158
|
-
|
|
159
|
-
act(() => {
|
|
160
|
-
useUserStore.setState({ isSignedIn: false });
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
renderWithRouter(<PanelContent closePopover={closePopover} />);
|
|
164
|
-
|
|
165
|
-
expect(screen.getByText('Mocked BrandWatermark')).toBeInTheDocument();
|
|
166
|
-
});
|
|
167
|
-
});
|
|
168
|
-
|
|
169
135
|
it('should render Menu with main items', () => {
|
|
170
136
|
renderWithRouter(<PanelContent closePopover={closePopover} />);
|
|
171
137
|
|
|
@@ -10,87 +10,60 @@ import UserAvatar from '../UserAvatar';
|
|
|
10
10
|
vi.mock('zustand/traditional');
|
|
11
11
|
|
|
12
12
|
// Use vi.hoisted to ensure variables exist before vi.mock factory executes
|
|
13
|
-
const {
|
|
14
|
-
enableAuth: { value: true },
|
|
15
|
-
enableClerk: { value: false },
|
|
13
|
+
const { enableNextAuth } = vi.hoisted(() => ({
|
|
16
14
|
enableNextAuth: { value: false },
|
|
17
15
|
}));
|
|
18
16
|
|
|
19
17
|
vi.mock('@/envs/auth', () => ({
|
|
20
|
-
get enableAuth() {
|
|
21
|
-
return enableAuth.value;
|
|
22
|
-
},
|
|
23
|
-
get enableClerk() {
|
|
24
|
-
return enableClerk.value;
|
|
25
|
-
},
|
|
26
18
|
get enableNextAuth() {
|
|
27
19
|
return enableNextAuth.value;
|
|
28
20
|
},
|
|
29
21
|
}));
|
|
30
22
|
|
|
31
23
|
afterEach(() => {
|
|
32
|
-
enableAuth.value = true;
|
|
33
|
-
enableClerk.value = false;
|
|
34
24
|
enableNextAuth.value = false;
|
|
35
25
|
});
|
|
36
26
|
|
|
37
27
|
describe('UserAvatar', () => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
isSignedIn: true,
|
|
47
|
-
user: { avatar: mockAvatar, id: 'abc', username: mockUsername },
|
|
48
|
-
});
|
|
28
|
+
it('should show the username and avatar are displayed when the user is logged in', async () => {
|
|
29
|
+
const mockAvatar = 'https://example.com/avatar.png';
|
|
30
|
+
const mockUsername = 'teeeeeestuser';
|
|
31
|
+
|
|
32
|
+
act(() => {
|
|
33
|
+
useUserStore.setState({
|
|
34
|
+
isSignedIn: true,
|
|
35
|
+
user: { avatar: mockAvatar, id: 'abc', username: mockUsername },
|
|
49
36
|
});
|
|
50
|
-
|
|
51
|
-
render(<UserAvatar />);
|
|
52
|
-
|
|
53
|
-
expect(screen.getByAltText(mockUsername)).toBeInTheDocument();
|
|
54
|
-
expect(screen.getByAltText(mockUsername)).toHaveAttribute('src', mockAvatar);
|
|
55
37
|
});
|
|
56
38
|
|
|
57
|
-
|
|
58
|
-
const mockUsername = 'testuser';
|
|
39
|
+
render(<UserAvatar />);
|
|
59
40
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
isSignedIn: true,
|
|
64
|
-
user: { id: 'bbb', username: mockUsername },
|
|
65
|
-
});
|
|
66
|
-
});
|
|
41
|
+
expect(screen.getByAltText(mockUsername)).toBeInTheDocument();
|
|
42
|
+
expect(screen.getByAltText(mockUsername)).toHaveAttribute('src', mockAvatar);
|
|
43
|
+
});
|
|
67
44
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
expect(screen.getByText('TE')).toBeInTheDocument();
|
|
71
|
-
});
|
|
45
|
+
it('should show default avatar when the user is logged in but have no custom avatar', () => {
|
|
46
|
+
const mockUsername = 'testuser';
|
|
72
47
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
48
|
+
act(() => {
|
|
49
|
+
useUserStore.setState({
|
|
50
|
+
isSignedIn: true,
|
|
51
|
+
user: { id: 'bbb', username: mockUsername },
|
|
76
52
|
});
|
|
77
|
-
|
|
78
|
-
render(<UserAvatar />);
|
|
79
|
-
expect(screen.getByAltText(BRANDING_NAME)).toBeInTheDocument();
|
|
80
|
-
expect(screen.getByAltText(BRANDING_NAME)).toHaveAttribute('src', DEFAULT_USER_AVATAR_URL);
|
|
81
53
|
});
|
|
82
|
-
});
|
|
83
54
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
useUserStore.setState({ enableAuth: () => false, isSignedIn: false, user: undefined });
|
|
89
|
-
});
|
|
55
|
+
render(<UserAvatar />);
|
|
56
|
+
// When user has no avatar url, <Avatar /> falls back to initials rendering (not an <img />)
|
|
57
|
+
expect(screen.getByText('TE')).toBeInTheDocument();
|
|
58
|
+
});
|
|
90
59
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
60
|
+
it('should show LobeChat and default avatar when the user is not logged in', () => {
|
|
61
|
+
act(() => {
|
|
62
|
+
useUserStore.setState({ isSignedIn: false, user: undefined });
|
|
94
63
|
});
|
|
64
|
+
|
|
65
|
+
render(<UserAvatar />);
|
|
66
|
+
expect(screen.getByAltText(BRANDING_NAME)).toBeInTheDocument();
|
|
67
|
+
expect(screen.getByAltText(BRANDING_NAME)).toHaveAttribute('src', DEFAULT_USER_AVATAR_URL);
|
|
95
68
|
});
|
|
96
69
|
});
|
|
@@ -48,33 +48,11 @@ vi.mock('./useNewVersion', () => ({
|
|
|
48
48
|
useNewVersion: vi.fn(() => false),
|
|
49
49
|
}));
|
|
50
50
|
|
|
51
|
-
// Use vi.hoisted to ensure variables exist before vi.mock factory executes
|
|
52
|
-
const { enableAuth, enableClerk } = vi.hoisted(() => ({
|
|
53
|
-
enableAuth: { value: true },
|
|
54
|
-
enableClerk: { value: true },
|
|
55
|
-
}));
|
|
56
|
-
|
|
57
|
-
vi.mock('@/envs/auth', () => ({
|
|
58
|
-
get enableAuth() {
|
|
59
|
-
return enableAuth.value;
|
|
60
|
-
},
|
|
61
|
-
get enableClerk() {
|
|
62
|
-
return enableClerk.value;
|
|
63
|
-
},
|
|
64
|
-
}));
|
|
65
|
-
|
|
66
|
-
afterEach(() => {
|
|
67
|
-
enableAuth.value = true;
|
|
68
|
-
enableClerk.value = true;
|
|
69
|
-
});
|
|
70
|
-
|
|
71
51
|
describe('useMenu', () => {
|
|
72
52
|
it('should provide correct menu items when user is logged in with auth', () => {
|
|
73
53
|
act(() => {
|
|
74
|
-
useUserStore.setState({ isSignedIn: true
|
|
54
|
+
useUserStore.setState({ isSignedIn: true });
|
|
75
55
|
});
|
|
76
|
-
enableAuth.value = true;
|
|
77
|
-
enableClerk.value = false;
|
|
78
56
|
|
|
79
57
|
const { result } = renderHook(() => useMenu(), { wrapper });
|
|
80
58
|
|
|
@@ -88,29 +66,10 @@ describe('useMenu', () => {
|
|
|
88
66
|
});
|
|
89
67
|
});
|
|
90
68
|
|
|
91
|
-
it('should provide correct menu items when user is logged in without auth', () => {
|
|
92
|
-
act(() => {
|
|
93
|
-
useUserStore.setState({ isSignedIn: false, enableAuth: () => false });
|
|
94
|
-
});
|
|
95
|
-
enableAuth.value = false;
|
|
96
|
-
|
|
97
|
-
const { result } = renderHook(() => useMenu(), { wrapper });
|
|
98
|
-
|
|
99
|
-
act(() => {
|
|
100
|
-
const { mainItems, logoutItems } = result.current;
|
|
101
|
-
// When not logged in (isLogin = false), these items should not be shown
|
|
102
|
-
// isLogin checks isSignedIn, so with isSignedIn: false, isLogin should be false
|
|
103
|
-
expect(mainItems?.some((item) => item?.key === 'setting')).toBe(false);
|
|
104
|
-
expect(mainItems?.some((item) => item?.key === 'import')).toBe(false);
|
|
105
|
-
expect(logoutItems.some((item) => item?.key === 'logout')).toBe(false);
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
|
|
109
69
|
it('should provide correct menu items when user is not logged in', () => {
|
|
110
70
|
act(() => {
|
|
111
|
-
useUserStore.setState({ isSignedIn: false
|
|
71
|
+
useUserStore.setState({ isSignedIn: false });
|
|
112
72
|
});
|
|
113
|
-
enableAuth.value = true;
|
|
114
73
|
|
|
115
74
|
const { result } = renderHook(() => useMenu(), { wrapper });
|
|
116
75
|
|
|
@@ -4,7 +4,6 @@ import { type PropsWithChildren } from 'react';
|
|
|
4
4
|
import { authEnv } from '@/envs/auth';
|
|
5
5
|
|
|
6
6
|
import BetterAuth from './BetterAuth';
|
|
7
|
-
import Clerk from './Clerk';
|
|
8
7
|
import Desktop from './Desktop';
|
|
9
8
|
import NextAuth from './NextAuth';
|
|
10
9
|
import NoAuth from './NoAuth';
|
|
@@ -14,10 +13,6 @@ const AuthProvider = ({ children }: PropsWithChildren) => {
|
|
|
14
13
|
return <Desktop>{children}</Desktop>;
|
|
15
14
|
}
|
|
16
15
|
|
|
17
|
-
if (authEnv.NEXT_PUBLIC_ENABLE_CLERK_AUTH) {
|
|
18
|
-
return <Clerk>{children}</Clerk>;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
16
|
if (authEnv.NEXT_PUBLIC_ENABLE_BETTER_AUTH) {
|
|
22
17
|
return <BetterAuth>{children}</BetterAuth>;
|
|
23
18
|
}
|
|
@@ -17,16 +17,14 @@ interface CustomNextConfig {
|
|
|
17
17
|
export function defineConfig(config: CustomNextConfig) {
|
|
18
18
|
const isProd = process.env.NODE_ENV === 'production';
|
|
19
19
|
const buildWithDocker = process.env.DOCKER === 'true';
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
const enableReactScan = !!process.env.REACT_SCAN_MONITOR_API_KEY;
|
|
22
22
|
const shouldUseCSP = process.env.ENABLED_CSP === '1';
|
|
23
23
|
|
|
24
24
|
const isTest =
|
|
25
25
|
process.env.NODE_ENV === 'test' || process.env.TEST === '1' || process.env.E2E === '1';
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const isStandaloneMode = buildWithDocker || isDesktop;
|
|
27
|
+
const isStandaloneMode = buildWithDocker || process.env.NEXT_BUILD_STANDALONE === '1';
|
|
30
28
|
|
|
31
29
|
const standaloneConfig: NextConfig = {
|
|
32
30
|
output: 'standalone',
|
|
@@ -38,6 +36,7 @@ export function defineConfig(config: CustomNextConfig) {
|
|
|
38
36
|
const nextConfig: NextConfig = {
|
|
39
37
|
...(isStandaloneMode ? standaloneConfig : {}),
|
|
40
38
|
assetPrefix,
|
|
39
|
+
|
|
41
40
|
compiler: {
|
|
42
41
|
emotion: true,
|
|
43
42
|
},
|
|
@@ -313,15 +312,22 @@ export function defineConfig(config: CustomNextConfig) {
|
|
|
313
312
|
permanent: true,
|
|
314
313
|
source: '/chat',
|
|
315
314
|
},
|
|
315
|
+
// Redirect old Clerk login route to Better Auth signin
|
|
316
|
+
{
|
|
317
|
+
destination: '/signin',
|
|
318
|
+
permanent: true,
|
|
319
|
+
source: '/login',
|
|
320
|
+
},
|
|
316
321
|
...(config.redirects ?? []),
|
|
317
322
|
],
|
|
318
|
-
|
|
319
323
|
// when external packages in dev mode with turbopack, this config will lead to bundle error
|
|
324
|
+
// @napi-rs/canvas is a native module that can't be bundled by Turbopack
|
|
325
|
+
// pdfjs-dist uses @napi-rs/canvas for DOMMatrix polyfill in Node.js environment
|
|
320
326
|
serverExternalPackages: config.serverExternalPackages
|
|
321
327
|
? config.serverExternalPackages
|
|
322
|
-
: ['pdfkit'],
|
|
328
|
+
: ['pdfkit', '@napi-rs/canvas', 'pdfjs-dist'],
|
|
323
329
|
|
|
324
|
-
transpilePackages: ['
|
|
330
|
+
transpilePackages: ['mermaid', 'better-auth-harmony'],
|
|
325
331
|
turbopack: {
|
|
326
332
|
rules: isTest
|
|
327
333
|
? void 0
|
|
@@ -400,14 +406,13 @@ export function defineConfig(config: CustomNextConfig) {
|
|
|
400
406
|
|
|
401
407
|
const withBundleAnalyzer = process.env.ANALYZE === 'true' ? analyzer() : noWrapper;
|
|
402
408
|
|
|
403
|
-
const withPWA =
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
: noWrapper;
|
|
409
|
+
const withPWA = isProd
|
|
410
|
+
? withSerwistInit({
|
|
411
|
+
register: false,
|
|
412
|
+
swDest: 'public/sw.js',
|
|
413
|
+
swSrc: 'src/app/sw.ts',
|
|
414
|
+
})
|
|
415
|
+
: noWrapper;
|
|
411
416
|
|
|
412
417
|
return withBundleAnalyzer(withPWA(nextConfig as NextConfig));
|
|
413
418
|
}
|