@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
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { type AuthObject } from '@clerk/backend';
|
|
2
1
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
2
|
|
|
4
3
|
import { checkAuthMethod } from './utils';
|
|
5
4
|
|
|
6
|
-
let enableClerkMock = false;
|
|
7
5
|
let enableNextAuthMock = false;
|
|
8
6
|
let enableBetterAuthMock = false;
|
|
9
7
|
|
|
@@ -12,9 +10,6 @@ vi.mock('@/envs/auth', async (importOriginal) => {
|
|
|
12
10
|
|
|
13
11
|
return {
|
|
14
12
|
...(data as any),
|
|
15
|
-
get enableClerk() {
|
|
16
|
-
return enableClerkMock;
|
|
17
|
-
},
|
|
18
13
|
get enableBetterAuth() {
|
|
19
14
|
return enableBetterAuthMock;
|
|
20
15
|
},
|
|
@@ -29,29 +24,6 @@ describe('checkAuthMethod', () => {
|
|
|
29
24
|
vi.clearAllMocks();
|
|
30
25
|
});
|
|
31
26
|
|
|
32
|
-
it('should pass with valid Clerk auth', () => {
|
|
33
|
-
enableClerkMock = true;
|
|
34
|
-
expect(() =>
|
|
35
|
-
checkAuthMethod({
|
|
36
|
-
clerkAuth: { userId: 'someUserId' } as AuthObject,
|
|
37
|
-
}),
|
|
38
|
-
).not.toThrow();
|
|
39
|
-
|
|
40
|
-
enableClerkMock = false;
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('should throw error with invalid Clerk auth', () => {
|
|
44
|
-
enableClerkMock = true;
|
|
45
|
-
try {
|
|
46
|
-
checkAuthMethod({
|
|
47
|
-
clerkAuth: {} as any,
|
|
48
|
-
});
|
|
49
|
-
} catch (e) {
|
|
50
|
-
expect(e).toEqual({ errorType: 'InvalidClerkUser' });
|
|
51
|
-
}
|
|
52
|
-
enableClerkMock = false;
|
|
53
|
-
});
|
|
54
|
-
|
|
55
27
|
it('should pass with valid Next auth', () => {
|
|
56
28
|
enableNextAuthMock = true;
|
|
57
29
|
expect(() =>
|
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { AgentRuntimeError } from '@lobechat/model-runtime';
|
|
3
|
-
import { ChatErrorType } from '@lobechat/types';
|
|
4
|
-
|
|
5
|
-
import { enableBetterAuth, enableClerk, enableNextAuth } from '@/envs/auth';
|
|
1
|
+
import { enableBetterAuth, enableNextAuth } from '@/envs/auth';
|
|
6
2
|
|
|
7
3
|
interface CheckAuthParams {
|
|
8
4
|
apiKey?: string;
|
|
9
5
|
betterAuthAuthorized?: boolean;
|
|
10
|
-
clerkAuth?: AuthObject;
|
|
11
6
|
nextAuthAuthorized?: boolean;
|
|
12
7
|
}
|
|
13
8
|
/**
|
|
@@ -16,20 +11,10 @@ interface CheckAuthParams {
|
|
|
16
11
|
* @param {CheckAuthParams} params - Authentication parameters extracted from headers.
|
|
17
12
|
* @param {string} [params.apiKey] - The user API key.
|
|
18
13
|
* @param {boolean} [params.betterAuthAuthorized] - Whether the Better Auth session exists.
|
|
19
|
-
* @param {AuthObject} [params.clerkAuth] - Clerk authentication payload from middleware.
|
|
20
14
|
* @param {boolean} [params.nextAuthAuthorized] - Whether the OAuth 2 header is provided.
|
|
21
|
-
* @throws {AgentRuntimeError} If authentication fails.
|
|
22
15
|
*/
|
|
23
16
|
export const checkAuthMethod = (params: CheckAuthParams) => {
|
|
24
|
-
const { apiKey, betterAuthAuthorized, nextAuthAuthorized
|
|
25
|
-
// clerk auth handler
|
|
26
|
-
if (enableClerk) {
|
|
27
|
-
// if there is no userId, means the use is not login, just throw error
|
|
28
|
-
if (!(clerkAuth as any)?.userId)
|
|
29
|
-
throw AgentRuntimeError.createError(ChatErrorType.InvalidClerkUser);
|
|
30
|
-
// if the user is login, just return
|
|
31
|
-
else return;
|
|
32
|
-
}
|
|
17
|
+
const { apiKey, betterAuthAuthorized, nextAuthAuthorized } = params;
|
|
33
18
|
|
|
34
19
|
// if better auth session exists
|
|
35
20
|
if (enableBetterAuth && betterAuthAuthorized) return;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
// @vitest-environment node
|
|
2
|
-
import { getAuth } from '@clerk/nextjs/server';
|
|
3
2
|
import { LobeRuntimeAI, ModelRuntime } from '@lobechat/model-runtime';
|
|
4
3
|
import { ChatErrorType } from '@lobechat/types';
|
|
5
4
|
import { getXorPayload } from '@lobechat/utils/server';
|
|
@@ -11,10 +10,6 @@ import { initModelRuntimeFromDB } from '@/server/modules/ModelRuntime';
|
|
|
11
10
|
|
|
12
11
|
import { POST } from './route';
|
|
13
12
|
|
|
14
|
-
vi.mock('@clerk/nextjs/server', () => ({
|
|
15
|
-
getAuth: vi.fn(),
|
|
16
|
-
}));
|
|
17
|
-
|
|
18
13
|
vi.mock('@/app/(backend)/middleware/auth/utils', () => ({
|
|
19
14
|
checkAuthMethod: vi.fn(),
|
|
20
15
|
}));
|
|
@@ -28,17 +23,11 @@ vi.mock('@/server/modules/ModelRuntime', () => ({
|
|
|
28
23
|
createTraceOptions: vi.fn().mockReturnValue({}),
|
|
29
24
|
}));
|
|
30
25
|
|
|
31
|
-
// Use vi.hoisted to ensure mockState is initialized before mocks are set up
|
|
32
|
-
const mockState = vi.hoisted(() => ({ enableClerk: false }));
|
|
33
|
-
|
|
34
|
-
// 模拟 @/const/auth 模块
|
|
35
26
|
vi.mock('@/envs/auth', async (importOriginal) => {
|
|
36
|
-
const
|
|
27
|
+
const actual = await importOriginal<typeof import('@/envs/auth')>();
|
|
37
28
|
return {
|
|
38
|
-
...
|
|
39
|
-
|
|
40
|
-
return mockState.enableClerk;
|
|
41
|
-
},
|
|
29
|
+
...actual,
|
|
30
|
+
enableBetterAuth: false,
|
|
42
31
|
};
|
|
43
32
|
});
|
|
44
33
|
|
|
@@ -58,7 +47,6 @@ beforeEach(() => {
|
|
|
58
47
|
afterEach(() => {
|
|
59
48
|
// 清除模拟调用历史
|
|
60
49
|
vi.clearAllMocks();
|
|
61
|
-
mockState.enableClerk = false;
|
|
62
50
|
});
|
|
63
51
|
|
|
64
52
|
describe('POST handler', () => {
|
|
@@ -108,42 +96,6 @@ describe('POST handler', () => {
|
|
|
108
96
|
});
|
|
109
97
|
});
|
|
110
98
|
|
|
111
|
-
it('should have pass clerk Auth when enable clerk', async () => {
|
|
112
|
-
mockState.enableClerk = true;
|
|
113
|
-
|
|
114
|
-
vi.mocked(getXorPayload).mockReturnValueOnce({
|
|
115
|
-
apiKey: 'test-api-key',
|
|
116
|
-
azureApiVersion: 'v1',
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
const mockParams = Promise.resolve({ provider: 'test-provider' });
|
|
120
|
-
vi.mocked(getAuth).mockReturnValue({} as any);
|
|
121
|
-
vi.mocked(checkAuthMethod).mockReset();
|
|
122
|
-
|
|
123
|
-
const mockRuntime: LobeRuntimeAI = { baseURL: 'abc', chat: vi.fn() };
|
|
124
|
-
|
|
125
|
-
// Mock initModelRuntimeFromDB
|
|
126
|
-
vi.mocked(initModelRuntimeFromDB).mockResolvedValue(new ModelRuntime(mockRuntime));
|
|
127
|
-
|
|
128
|
-
const request = new Request(new URL('https://test.com'), {
|
|
129
|
-
method: 'POST',
|
|
130
|
-
body: JSON.stringify({ model: 'test-model' }),
|
|
131
|
-
headers: {
|
|
132
|
-
[LOBE_CHAT_AUTH_HEADER]: 'some-valid-token',
|
|
133
|
-
[OAUTH_AUTHORIZED]: '1',
|
|
134
|
-
},
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
await POST(request, { params: mockParams });
|
|
138
|
-
|
|
139
|
-
expect(checkAuthMethod).toBeCalledWith({
|
|
140
|
-
apiKey: 'test-api-key',
|
|
141
|
-
betterAuthAuthorized: false,
|
|
142
|
-
clerkAuth: {},
|
|
143
|
-
nextAuthAuthorized: true,
|
|
144
|
-
});
|
|
145
|
-
});
|
|
146
|
-
|
|
147
99
|
it('should return InternalServerError error when throw a unknown error', async () => {
|
|
148
100
|
const mockParams = Promise.resolve({ provider: 'test-provider' });
|
|
149
101
|
vi.mocked(getXorPayload).mockImplementationOnce(() => {
|
|
@@ -9,10 +9,6 @@ import { initModelRuntimeFromDB } from '@/server/modules/ModelRuntime';
|
|
|
9
9
|
|
|
10
10
|
import { GET } from './route';
|
|
11
11
|
|
|
12
|
-
vi.mock('@clerk/nextjs/server', () => ({
|
|
13
|
-
getAuth: vi.fn(),
|
|
14
|
-
}));
|
|
15
|
-
|
|
16
12
|
vi.mock('@/app/(backend)/middleware/auth/utils', () => ({
|
|
17
13
|
checkAuthMethod: vi.fn(),
|
|
18
14
|
}));
|
|
@@ -21,6 +17,14 @@ vi.mock('@lobechat/utils/server', () => ({
|
|
|
21
17
|
getXorPayload: vi.fn(),
|
|
22
18
|
}));
|
|
23
19
|
|
|
20
|
+
vi.mock('@/envs/auth', async (importOriginal) => {
|
|
21
|
+
const actual = await importOriginal<typeof import('@/envs/auth')>();
|
|
22
|
+
return {
|
|
23
|
+
...actual,
|
|
24
|
+
enableBetterAuth: false,
|
|
25
|
+
};
|
|
26
|
+
});
|
|
27
|
+
|
|
24
28
|
vi.mock('@/server/modules/ModelRuntime', () => ({
|
|
25
29
|
initModelRuntimeFromDB: vi.fn(),
|
|
26
30
|
}));
|
|
@@ -68,7 +68,8 @@ const BtnListLoading = memo(() => {
|
|
|
68
68
|
* ref: https://authjs.dev/guides/pages/signin
|
|
69
69
|
*/
|
|
70
70
|
export default memo(() => {
|
|
71
|
-
const { t } = useTranslation('
|
|
71
|
+
const { t } = useTranslation('auth');
|
|
72
|
+
const { t: tCommon } = useTranslation('common');
|
|
72
73
|
const router = useRouter();
|
|
73
74
|
const [loadingProvider, setLoadingProvider] = useState<string | null>(null);
|
|
74
75
|
|
|
@@ -100,9 +101,9 @@ export default memo(() => {
|
|
|
100
101
|
};
|
|
101
102
|
|
|
102
103
|
const footerBtns = [
|
|
103
|
-
{ href: DOCUMENTS_REFER_URL, id: 0, label:
|
|
104
|
-
{ href: PRIVACY_URL, id: 1, label: t('
|
|
105
|
-
{ href: TERMS_URL, id: 2, label: t('
|
|
104
|
+
{ href: DOCUMENTS_REFER_URL, id: 0, label: tCommon('document') },
|
|
105
|
+
{ href: PRIVACY_URL, id: 1, label: t('footer.privacy') },
|
|
106
|
+
{ href: TERMS_URL, id: 2, label: t('footer.terms') },
|
|
106
107
|
];
|
|
107
108
|
|
|
108
109
|
return (
|
|
@@ -116,10 +117,10 @@ export default memo(() => {
|
|
|
116
117
|
<div>
|
|
117
118
|
<LobeHub size={48} />
|
|
118
119
|
</div>
|
|
119
|
-
{t('
|
|
120
|
+
{t('signin.title')}
|
|
120
121
|
</Text>
|
|
121
122
|
<Text as={'p'} className={styles.description}>
|
|
122
|
-
{t('
|
|
123
|
+
{t('signin.subtitle', { appName: BRANDING_NAME })}
|
|
123
124
|
</Text>
|
|
124
125
|
</div>
|
|
125
126
|
{/* Content */}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { enableBetterAuth, enableClerk } from '@/envs/auth';
|
|
1
|
+
import { enableBetterAuth } from '@/envs/auth';
|
|
4
2
|
import { notFound } from '@/libs/next/navigation';
|
|
5
3
|
import { metadataModule } from '@/server/metadata';
|
|
6
4
|
import { translation } from '@/server/translation';
|
|
@@ -12,15 +10,6 @@ import BetterAuthSignUpForm from './BetterAuthSignUpForm';
|
|
|
12
10
|
export const generateMetadata = async (props: DynamicLayoutProps) => {
|
|
13
11
|
const locale = await RouteVariants.getLocale(props);
|
|
14
12
|
|
|
15
|
-
if (enableClerk) {
|
|
16
|
-
const { t } = await translation('clerk', locale);
|
|
17
|
-
return metadataModule.generate({
|
|
18
|
-
description: t('signUp.start.subtitle'),
|
|
19
|
-
title: t('signUp.start.title'),
|
|
20
|
-
url: '/signup',
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
|
|
24
13
|
if (enableBetterAuth) {
|
|
25
14
|
const { t } = await translation('auth', locale);
|
|
26
15
|
return metadataModule.generate({
|
|
@@ -37,10 +26,6 @@ export const generateMetadata = async (props: DynamicLayoutProps) => {
|
|
|
37
26
|
};
|
|
38
27
|
|
|
39
28
|
const Page = () => {
|
|
40
|
-
if (enableClerk) {
|
|
41
|
-
return <SignUp path="/signup" />;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
29
|
if (enableBetterAuth) {
|
|
45
30
|
return <BetterAuthSignUpForm />;
|
|
46
31
|
}
|
|
@@ -42,7 +42,7 @@ const AgentList = memo<{ onMoreClick?: () => void }>(({ onMoreClick }) => {
|
|
|
42
42
|
|
|
43
43
|
return (
|
|
44
44
|
<>
|
|
45
|
-
<InboxItem />
|
|
45
|
+
<InboxItem style={{ minHeight: 36 }} />
|
|
46
46
|
{showPinned && <SessionList dataSource={pinnedList!} />}
|
|
47
47
|
{showCustom && <Group dataSource={customList!} />}
|
|
48
48
|
{showDefault && (
|
|
@@ -4,10 +4,10 @@ import { getKlavisServerByServerIdentifier, getLobehubSkillProviderById } from '
|
|
|
4
4
|
import { Avatar, Flexbox, Icon } from '@lobehub/ui';
|
|
5
5
|
import { createStaticStyles } from 'antd-style';
|
|
6
6
|
import { Blocks } from 'lucide-react';
|
|
7
|
-
import { type ReactNode, createElement, memo,
|
|
7
|
+
import { type ReactNode, createElement, memo, useCallback, useMemo } from 'react';
|
|
8
8
|
import { useTranslation } from 'react-i18next';
|
|
9
9
|
|
|
10
|
-
import
|
|
10
|
+
import { createSkillStoreModal } from '@/features/SkillStore';
|
|
11
11
|
import { serverConfigSelectors, useServerConfigStore } from '@/store/serverConfig';
|
|
12
12
|
import { useToolStore } from '@/store/tool';
|
|
13
13
|
|
|
@@ -61,7 +61,6 @@ const BANNER_SKILL_IDS = [
|
|
|
61
61
|
|
|
62
62
|
const SkillInstallBanner = memo(() => {
|
|
63
63
|
const { t } = useTranslation('plugin');
|
|
64
|
-
const [open, setOpen] = useState(false);
|
|
65
64
|
|
|
66
65
|
const isLobehubSkillEnabled = useServerConfigStore(serverConfigSelectors.enableLobehubSkill);
|
|
67
66
|
const isKlavisEnabled = useServerConfigStore(serverConfigSelectors.enableKlavis);
|
|
@@ -108,20 +107,21 @@ const SkillInstallBanner = memo(() => {
|
|
|
108
107
|
return items;
|
|
109
108
|
}, []);
|
|
110
109
|
|
|
110
|
+
const handleOpenStore = useCallback(() => {
|
|
111
|
+
createSkillStoreModal();
|
|
112
|
+
}, []);
|
|
113
|
+
|
|
111
114
|
// Don't show banner if no skills are enabled
|
|
112
115
|
if (!isLobehubSkillEnabled && !isKlavisEnabled) return null;
|
|
113
116
|
|
|
114
117
|
return (
|
|
115
|
-
|
|
116
|
-
<
|
|
117
|
-
<
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
</div>
|
|
123
|
-
<SkillStore open={open} setOpen={setOpen} />
|
|
124
|
-
</>
|
|
118
|
+
<div className={styles.banner} onClick={handleOpenStore}>
|
|
119
|
+
<Flexbox align="center" gap={8} horizontal>
|
|
120
|
+
<Icon className={styles.icon} icon={Blocks} size={18} />
|
|
121
|
+
<span className={styles.text}>{t('skillInstallBanner.title')}</span>
|
|
122
|
+
</Flexbox>
|
|
123
|
+
{avatarItems.length > 0 && <Avatar.Group items={avatarItems} shape="circle" size={24} />}
|
|
124
|
+
</div>
|
|
125
125
|
);
|
|
126
126
|
});
|
|
127
127
|
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
import { Avatar, Block, Center, Flexbox, Icon, Text } from '@lobehub/ui';
|
|
4
4
|
import { cssVar } from 'antd-style';
|
|
5
5
|
import { FileTextIcon } from 'lucide-react';
|
|
6
|
-
import markdownToTxt from 'markdown-to-txt';
|
|
7
6
|
import { memo } from 'react';
|
|
8
7
|
|
|
9
8
|
import Time from '@/app/[variants]/(main)/home/features/components/Time';
|
|
10
9
|
import { RECENT_BLOCK_SIZE } from '@/app/[variants]/(main)/home/features/const';
|
|
11
10
|
import { type FileListItem } from '@/types/files';
|
|
11
|
+
import markdownToTxt from '@/utils/markdownToTxt';
|
|
12
12
|
|
|
13
13
|
// Helper to extract title from markdown content
|
|
14
14
|
const extractTitle = (content: string): string | null => {
|
|
@@ -24,7 +24,7 @@ const getPreviewText = (item: FileListItem): string => {
|
|
|
24
24
|
if (!item.content) return '';
|
|
25
25
|
|
|
26
26
|
// Convert markdown to plain text
|
|
27
|
-
let plainText = markdownToTxt(item.content);
|
|
27
|
+
let plainText = markdownToTxt(item.content.slice(0, 120));
|
|
28
28
|
|
|
29
29
|
// Remove the title line if it exists
|
|
30
30
|
const title = extractTitle(item.content);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type StateCreator } from 'zustand/vanilla';
|
|
2
2
|
|
|
3
|
-
import { type
|
|
3
|
+
import { type ResourceManagerMode } from '@/features/ResourceManager';
|
|
4
4
|
import { type FilesTabs, SortType } from '@/types/files';
|
|
5
5
|
|
|
6
6
|
import { type State, type ViewMode, initialState } from './initialState';
|
|
@@ -67,7 +67,7 @@ export interface Action {
|
|
|
67
67
|
/**
|
|
68
68
|
* Set the view mode
|
|
69
69
|
*/
|
|
70
|
-
setMode: (mode:
|
|
70
|
+
setMode: (mode: ResourceManagerMode) => void;
|
|
71
71
|
/**
|
|
72
72
|
* Set the pending rename item ID
|
|
73
73
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type ResourceManagerMode } from '@/features/ResourceManager';
|
|
2
2
|
import { FilesTabs, SortType } from '@/types/files';
|
|
3
3
|
|
|
4
4
|
export type ViewMode = 'list' | 'masonry';
|
|
@@ -39,7 +39,7 @@ export interface State {
|
|
|
39
39
|
/**
|
|
40
40
|
* View mode for displaying resources
|
|
41
41
|
*/
|
|
42
|
-
mode:
|
|
42
|
+
mode: ResourceManagerMode;
|
|
43
43
|
/**
|
|
44
44
|
* ID of item currently being renamed (for inline editing)
|
|
45
45
|
*/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type StateCreator } from 'zustand/vanilla';
|
|
2
2
|
|
|
3
|
-
import { type
|
|
3
|
+
import { type ResourceManagerMode } from '@/features/ResourceManager';
|
|
4
4
|
|
|
5
5
|
import { type State, initialState } from './initialState';
|
|
6
6
|
|
|
@@ -12,7 +12,7 @@ export interface Action {
|
|
|
12
12
|
/**
|
|
13
13
|
* Set the view mode
|
|
14
14
|
*/
|
|
15
|
-
setMode: (mode:
|
|
15
|
+
setMode: (mode: ResourceManagerMode) => void;
|
|
16
16
|
/**
|
|
17
17
|
* Set selected file IDs
|
|
18
18
|
*/
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type ResourceManagerMode } from '@/features/ResourceManager';
|
|
2
2
|
|
|
3
3
|
export interface State {
|
|
4
4
|
currentViewItemId?: string;
|
|
5
|
-
mode:
|
|
5
|
+
mode: ResourceManagerMode;
|
|
6
6
|
selectedFileIds: string[];
|
|
7
7
|
}
|
|
8
8
|
|
|
@@ -20,7 +20,6 @@ import {
|
|
|
20
20
|
Mic2,
|
|
21
21
|
PaletteIcon,
|
|
22
22
|
PieChart,
|
|
23
|
-
ShieldCheck,
|
|
24
23
|
Sparkles,
|
|
25
24
|
UserCircle,
|
|
26
25
|
} from 'lucide-react';
|
|
@@ -32,7 +31,7 @@ import { electronSyncSelectors } from '@/store/electron/selectors';
|
|
|
32
31
|
import { SettingsTabs } from '@/store/global/initialState';
|
|
33
32
|
import { featureFlagsSelectors, useServerConfigStore } from '@/store/serverConfig';
|
|
34
33
|
import { useUserStore } from '@/store/user';
|
|
35
|
-
import {
|
|
34
|
+
import { userProfileSelectors } from '@/store/user/slices/auth/selectors';
|
|
36
35
|
|
|
37
36
|
export enum SettingsGroupKey {
|
|
38
37
|
AIConfig = 'ai-config',
|
|
@@ -61,8 +60,7 @@ export const useCategory = () => {
|
|
|
61
60
|
const mobile = useServerConfigStore((s) => s.isMobile);
|
|
62
61
|
const { enableSTT, hideDocs, showAiImage, showApiKeyManage } =
|
|
63
62
|
useServerConfigStore(featureFlagsSelectors);
|
|
64
|
-
const [
|
|
65
|
-
authSelectors.isLoginWithClerk(s),
|
|
63
|
+
const [avatar, username] = useUserStore((s) => [
|
|
66
64
|
userProfileSelectors.userAvatar(s),
|
|
67
65
|
userProfileSelectors.nickName(s),
|
|
68
66
|
]);
|
|
@@ -87,11 +85,6 @@ export const useCategory = () => {
|
|
|
87
85
|
key: SettingsTabs.Profile,
|
|
88
86
|
label: username ? username : tAuth('tab.profile'),
|
|
89
87
|
},
|
|
90
|
-
isLoginWithClerk && {
|
|
91
|
-
icon: ShieldCheck,
|
|
92
|
-
key: SettingsTabs.Security,
|
|
93
|
-
label: tAuth('tab.security'),
|
|
94
|
-
},
|
|
95
88
|
{
|
|
96
89
|
icon: ChartColumnBigIcon,
|
|
97
90
|
key: SettingsTabs.Stats,
|
|
@@ -237,18 +230,7 @@ export const useCategory = () => {
|
|
|
237
230
|
});
|
|
238
231
|
|
|
239
232
|
return groups;
|
|
240
|
-
}, [
|
|
241
|
-
t,
|
|
242
|
-
tAuth,
|
|
243
|
-
enableSTT,
|
|
244
|
-
hideDocs,
|
|
245
|
-
mobile,
|
|
246
|
-
showAiImage,
|
|
247
|
-
showApiKeyManage,
|
|
248
|
-
isLoginWithClerk,
|
|
249
|
-
avatarUrl,
|
|
250
|
-
username,
|
|
251
|
-
]);
|
|
233
|
+
}, [t, tAuth, enableSTT, hideDocs, mobile, showAiImage, showApiKeyManage, avatarUrl, username]);
|
|
252
234
|
|
|
253
235
|
return categoryGroups;
|
|
254
236
|
};
|
|
@@ -7,7 +7,6 @@ import { useCallback, useState } from 'react';
|
|
|
7
7
|
import { useTranslation } from 'react-i18next';
|
|
8
8
|
|
|
9
9
|
import { fetchErrorNotification } from '@/components/Error/fetchErrorNotification';
|
|
10
|
-
import { enableAuth } from '@/envs/auth';
|
|
11
10
|
import UserAvatar from '@/features/User/UserAvatar';
|
|
12
11
|
import { useUserStore } from '@/store/user';
|
|
13
12
|
import { authSelectors } from '@/store/user/selectors';
|
|
@@ -54,7 +53,7 @@ const AvatarRow = ({ mobile }: AvatarRowProps) => {
|
|
|
54
53
|
[updateAvatar],
|
|
55
54
|
);
|
|
56
55
|
|
|
57
|
-
const canUpload =
|
|
56
|
+
const canUpload = isLogin;
|
|
58
57
|
|
|
59
58
|
const avatarContent = canUpload ? (
|
|
60
59
|
<Spin indicator={<LoadingOutlined spin />} spinning={uploading}>
|
|
@@ -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
|
|