@lobehub/lobehub 2.0.0-next.221 → 2.0.0-next.222
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/.github/workflows/claude-auto-testing.yml +6 -3
- package/.github/workflows/claude-dedupe-issues.yml +8 -1
- package/.github/workflows/claude-issue-triage.yml +8 -14
- package/.github/workflows/claude-translate-comments.yml +6 -3
- package/.github/workflows/claude-translator.yml +12 -14
- package/.github/workflows/claude.yml +10 -20
- package/.github/workflows/test.yml +26 -0
- package/CHANGELOG.md +33 -0
- package/changelog/v1.json +9 -0
- package/locales/zh-CN/components.json +1 -0
- package/package.json +3 -3
- package/packages/const/src/index.ts +0 -1
- package/packages/memory-user-memory/package.json +1 -0
- package/packages/memory-user-memory/src/extractors/context.test.ts +3 -2
- package/packages/memory-user-memory/src/extractors/experience.test.ts +3 -2
- package/packages/memory-user-memory/src/extractors/identity.test.ts +23 -6
- package/packages/memory-user-memory/src/extractors/preference.test.ts +3 -2
- package/packages/memory-user-memory/vitest.config.ts +4 -0
- package/packages/model-runtime/src/providers/replicate/index.ts +1 -1
- package/packages/ssrf-safe-fetch/index.test.ts +2 -2
- package/packages/ssrf-safe-fetch/package.json +3 -2
- package/packages/types/src/serverConfig.ts +2 -0
- package/packages/utils/package.json +1 -1
- package/packages/utils/src/client/xor-obfuscation.test.ts +32 -32
- package/packages/utils/src/client/xor-obfuscation.ts +3 -4
- package/packages/utils/src/imageToBase64.ts +1 -1
- package/packages/utils/src/server/__tests__/auth.test.ts +1 -1
- package/packages/utils/src/server/auth.ts +1 -1
- package/packages/utils/src/server/xor.test.ts +9 -7
- package/packages/utils/src/server/xor.ts +1 -1
- package/packages/web-crawler/package.json +1 -1
- package/packages/web-crawler/src/crawImpl/__tests__/naive.test.ts +1 -1
- package/packages/web-crawler/src/crawImpl/naive.ts +1 -1
- package/scripts/prebuild.mts +58 -1
- package/src/app/(backend)/api/auth/[...all]/route.ts +2 -1
- package/src/app/(backend)/middleware/auth/index.ts +3 -3
- package/src/app/(backend)/middleware/auth/utils.test.ts +1 -1
- package/src/app/(backend)/middleware/auth/utils.ts +1 -1
- package/src/app/(backend)/webapi/chat/[provider]/route.test.ts +2 -2
- package/src/app/(backend)/webapi/models/[provider]/route.test.ts +1 -1
- package/src/app/(backend)/webapi/plugin/gateway/route.ts +1 -1
- package/src/app/(backend)/webapi/proxy/route.ts +1 -1
- package/src/app/[variants]/(auth)/login/[[...login]]/page.tsx +1 -1
- package/src/app/[variants]/(auth)/reset-password/layout.tsx +1 -1
- package/src/app/[variants]/(auth)/signin/layout.tsx +1 -1
- package/src/app/[variants]/(auth)/signin/useSignIn.ts +2 -2
- package/src/app/[variants]/(auth)/signup/[[...signup]]/page.tsx +1 -1
- package/src/app/[variants]/(auth)/signup/[[...signup]]/useSignUp.tsx +12 -6
- package/src/app/[variants]/(auth)/verify-email/layout.tsx +1 -1
- package/src/app/[variants]/(main)/settings/profile/features/AvatarRow.tsx +1 -1
- package/src/app/[variants]/(main)/settings/security/index.tsx +1 -1
- package/src/app/[variants]/(mobile)/me/(home)/__tests__/UserBanner.test.tsx +1 -1
- package/src/app/[variants]/(mobile)/me/(home)/__tests__/useCategory.test.tsx +1 -1
- package/src/app/[variants]/(mobile)/me/(home)/features/UserBanner.tsx +1 -1
- package/src/app/[variants]/(mobile)/settings/_layout/Header.tsx +1 -1
- package/src/components/ModelSelect/index.tsx +103 -72
- package/src/envs/auth.ts +30 -9
- package/src/features/Conversation/Messages/AssistantGroup/components/EditState.tsx +15 -32
- package/src/features/Conversation/Messages/AssistantGroup/index.tsx +9 -7
- package/src/features/EditorModal/EditorCanvas.tsx +31 -50
- package/src/features/EditorModal/TextareCanvas.tsx +3 -1
- package/src/features/EditorModal/index.tsx +14 -4
- package/src/features/ModelSwitchPanel/components/Footer.tsx +42 -0
- package/src/features/ModelSwitchPanel/components/List/MultipleProvidersModelItem.tsx +103 -0
- package/src/features/ModelSwitchPanel/components/List/SingleProviderModelItem.tsx +24 -0
- package/src/features/ModelSwitchPanel/components/List/VirtualItemRenderer.tsx +180 -0
- package/src/features/ModelSwitchPanel/components/List/index.tsx +99 -0
- package/src/features/ModelSwitchPanel/components/PanelContent.tsx +77 -0
- package/src/features/ModelSwitchPanel/components/Toolbar.tsx +54 -0
- package/src/features/ModelSwitchPanel/const.ts +29 -0
- package/src/features/ModelSwitchPanel/hooks/useBuildVirtualItems.ts +122 -0
- package/src/features/ModelSwitchPanel/hooks/useCurrentModelName.ts +18 -0
- package/src/features/ModelSwitchPanel/hooks/useDelayedRender.ts +18 -0
- package/src/features/ModelSwitchPanel/hooks/useModelAndProvider.ts +14 -0
- package/src/features/ModelSwitchPanel/hooks/usePanelHandlers.ts +33 -0
- package/src/features/ModelSwitchPanel/hooks/usePanelSize.ts +33 -0
- package/src/features/ModelSwitchPanel/hooks/usePanelState.ts +20 -0
- package/src/features/ModelSwitchPanel/index.tsx +25 -706
- package/src/features/ModelSwitchPanel/styles.ts +58 -0
- package/src/features/ModelSwitchPanel/types.ts +73 -0
- package/src/features/ModelSwitchPanel/utils.ts +24 -0
- package/src/features/User/UserPanel/PanelContent.tsx +1 -1
- package/src/features/User/__tests__/PanelContent.test.tsx +1 -1
- package/src/features/User/__tests__/UserAvatar.test.tsx +1 -1
- package/src/features/User/__tests__/useMenu.test.tsx +1 -1
- package/src/layout/GlobalProvider/StoreInitialization.tsx +2 -1
- package/src/libs/better-auth/auth-client.ts +7 -3
- package/src/libs/better-auth/define-config.ts +2 -2
- package/src/libs/next/proxy/define-config.ts +1 -2
- package/src/libs/oidc-provider/provider.test.ts +1 -1
- package/src/libs/trpc/async/context.ts +1 -1
- package/src/libs/trpc/lambda/context.ts +7 -8
- package/src/libs/trpc/middleware/userAuth.ts +1 -1
- package/src/libs/trusted-client/getSessionUser.ts +1 -1
- package/src/locales/default/components.ts +1 -0
- package/src/server/globalConfig/index.ts +2 -0
- package/src/server/routers/async/caller.ts +1 -1
- package/src/server/routers/lambda/__tests__/user.test.ts +2 -2
- package/src/server/routers/lambda/user.ts +2 -1
- package/src/services/_auth.ts +3 -3
- package/src/services/chat/index.ts +1 -1
- package/src/services/chat/mecha/contextEngineering.ts +1 -1
- package/src/store/global/initialState.ts +10 -0
- package/src/store/global/selectors/systemStatus.ts +5 -0
- package/src/store/serverConfig/selectors.ts +5 -1
- package/src/store/tool/slices/mcpStore/action.ts +74 -75
- package/src/store/user/slices/auth/action.test.ts +1 -1
- package/src/store/user/slices/auth/action.ts +1 -1
- package/src/store/user/slices/auth/initialState.ts +1 -1
- package/src/store/user/slices/auth/selectors.test.ts +1 -1
- package/src/store/user/slices/auth/selectors.ts +1 -1
- package/src/store/user/slices/common/action.ts +1 -1
- package/src/store/userMemory/slices/context/action.ts +6 -6
- package/packages/const/src/auth.ts +0 -14
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { createStaticStyles } from 'antd-style';
|
|
2
|
+
|
|
3
|
+
export const styles = createStaticStyles(({ css, cssVar }) => ({
|
|
4
|
+
container: css`
|
|
5
|
+
overflow: hidden;
|
|
6
|
+
padding: 0 !important;
|
|
7
|
+
`,
|
|
8
|
+
footer: css`
|
|
9
|
+
border-block-start: 1px solid ${cssVar.colorBorderSecondary};
|
|
10
|
+
`,
|
|
11
|
+
|
|
12
|
+
groupHeader: css`
|
|
13
|
+
width: 100%;
|
|
14
|
+
color: ${cssVar.colorTextSecondary};
|
|
15
|
+
|
|
16
|
+
.settings-icon {
|
|
17
|
+
opacity: 0;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
&:hover {
|
|
21
|
+
.settings-icon {
|
|
22
|
+
opacity: 1;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
`,
|
|
26
|
+
list: css`
|
|
27
|
+
position: relative;
|
|
28
|
+
overflow: hidden auto;
|
|
29
|
+
width: 100%;
|
|
30
|
+
`,
|
|
31
|
+
menuItem: css`
|
|
32
|
+
cursor: pointer;
|
|
33
|
+
|
|
34
|
+
position: relative;
|
|
35
|
+
|
|
36
|
+
gap: 8px;
|
|
37
|
+
align-items: center;
|
|
38
|
+
|
|
39
|
+
margin-block: 1px;
|
|
40
|
+
margin-inline: 4px;
|
|
41
|
+
padding-block: 8px;
|
|
42
|
+
padding-inline: 8px;
|
|
43
|
+
border-radius: ${cssVar.borderRadiusSM};
|
|
44
|
+
|
|
45
|
+
.settings-icon {
|
|
46
|
+
opacity: 0;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
&:hover {
|
|
50
|
+
.settings-icon {
|
|
51
|
+
opacity: 1;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
`,
|
|
55
|
+
toolbar: css`
|
|
56
|
+
border-block-end: 1px solid ${cssVar.colorBorderSecondary};
|
|
57
|
+
`,
|
|
58
|
+
}));
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { AiModelForSelect } from 'model-bank';
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
import type { EnabledProviderWithModels } from '@/types/aiProvider';
|
|
5
|
+
|
|
6
|
+
export type GroupMode = 'byModel' | 'byProvider';
|
|
7
|
+
|
|
8
|
+
export interface ModelWithProviders {
|
|
9
|
+
displayName: string;
|
|
10
|
+
model: AiModelForSelect;
|
|
11
|
+
providers: Array<{
|
|
12
|
+
id: string;
|
|
13
|
+
logo?: string;
|
|
14
|
+
name: string;
|
|
15
|
+
source?: EnabledProviderWithModels['source'];
|
|
16
|
+
}>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type VirtualItem =
|
|
20
|
+
| {
|
|
21
|
+
data: ModelWithProviders;
|
|
22
|
+
type: 'model-item-single';
|
|
23
|
+
}
|
|
24
|
+
| {
|
|
25
|
+
data: ModelWithProviders;
|
|
26
|
+
type: 'model-item-multiple';
|
|
27
|
+
}
|
|
28
|
+
| {
|
|
29
|
+
provider: EnabledProviderWithModels;
|
|
30
|
+
type: 'group-header';
|
|
31
|
+
}
|
|
32
|
+
| {
|
|
33
|
+
model: AiModelForSelect;
|
|
34
|
+
provider: EnabledProviderWithModels;
|
|
35
|
+
type: 'provider-model-item';
|
|
36
|
+
}
|
|
37
|
+
| {
|
|
38
|
+
provider: EnabledProviderWithModels;
|
|
39
|
+
type: 'empty-model';
|
|
40
|
+
}
|
|
41
|
+
| {
|
|
42
|
+
type: 'no-provider';
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export type DropdownPlacement =
|
|
46
|
+
| 'bottom'
|
|
47
|
+
| 'bottomLeft'
|
|
48
|
+
| 'bottomRight'
|
|
49
|
+
| 'top'
|
|
50
|
+
| 'topLeft'
|
|
51
|
+
| 'topRight';
|
|
52
|
+
|
|
53
|
+
export interface ModelSwitchPanelProps {
|
|
54
|
+
children?: ReactNode;
|
|
55
|
+
/**
|
|
56
|
+
* Current model ID. If not provided, uses currentAgentModel from store.
|
|
57
|
+
*/
|
|
58
|
+
model?: string;
|
|
59
|
+
/**
|
|
60
|
+
* Callback when model changes. If not provided, uses updateAgentConfig from store.
|
|
61
|
+
*/
|
|
62
|
+
onModelChange?: (params: { model: string; provider: string }) => Promise<void>;
|
|
63
|
+
onOpenChange?: (open: boolean) => void;
|
|
64
|
+
open?: boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Dropdown placement. Defaults to 'topLeft'.
|
|
67
|
+
*/
|
|
68
|
+
placement?: DropdownPlacement;
|
|
69
|
+
/**
|
|
70
|
+
* Current provider ID. If not provided, uses currentAgentModelProvider from store.
|
|
71
|
+
*/
|
|
72
|
+
provider?: string;
|
|
73
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { VirtualItem } from './types';
|
|
2
|
+
|
|
3
|
+
export const menuKey = (provider: string, model: string) => `${provider}-${model}`;
|
|
4
|
+
|
|
5
|
+
export const getVirtualItemKey = (item: VirtualItem): string => {
|
|
6
|
+
switch (item.type) {
|
|
7
|
+
case 'model-item-single':
|
|
8
|
+
case 'model-item-multiple': {
|
|
9
|
+
return item.data.displayName;
|
|
10
|
+
}
|
|
11
|
+
case 'provider-model-item': {
|
|
12
|
+
return menuKey(item.provider.id, item.model.id);
|
|
13
|
+
}
|
|
14
|
+
case 'group-header': {
|
|
15
|
+
return `header-${item.provider.id}`;
|
|
16
|
+
}
|
|
17
|
+
case 'empty-model': {
|
|
18
|
+
return `empty-${item.provider.id}`;
|
|
19
|
+
}
|
|
20
|
+
case 'no-provider': {
|
|
21
|
+
return 'no-provider';
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { ENABLE_BUSINESS_FEATURES } from '@lobechat/business-const';
|
|
2
|
-
import { enableBetterAuth, enableNextAuth } from '@lobechat/const';
|
|
3
2
|
import { Flexbox } from '@lobehub/ui';
|
|
4
3
|
import { useRouter } from 'next/navigation';
|
|
5
4
|
import { memo } from 'react';
|
|
@@ -10,6 +9,7 @@ import BusinessPanelContent from '@/business/client/features/User/BusinessPanelC
|
|
|
10
9
|
import BrandWatermark from '@/components/BrandWatermark';
|
|
11
10
|
import Menu from '@/components/Menu';
|
|
12
11
|
import { isDesktop } from '@/const/version';
|
|
12
|
+
import { enableBetterAuth, enableNextAuth } from '@/envs/auth';
|
|
13
13
|
import { useUserStore } from '@/store/user';
|
|
14
14
|
import { authSelectors } from '@/store/user/selectors';
|
|
15
15
|
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { INBOX_SESSION_ID
|
|
3
|
+
import { INBOX_SESSION_ID } from '@lobechat/const';
|
|
4
4
|
import { memo } from 'react';
|
|
5
5
|
import { useTranslation } from 'react-i18next';
|
|
6
6
|
import { createStoreUpdater } from 'zustand-utils';
|
|
7
7
|
|
|
8
|
+
import { enableNextAuth } from '@/envs/auth';
|
|
8
9
|
import { useIsMobile } from '@/hooks/useIsMobile';
|
|
9
10
|
import { useAgentStore } from '@/store/agent';
|
|
10
11
|
import { useAiInfraStore } from '@/store/aiInfra';
|
|
@@ -10,7 +10,6 @@ import type { auth } from '@/auth';
|
|
|
10
10
|
import { getAuthConfig } from '@/envs/auth';
|
|
11
11
|
|
|
12
12
|
const { NEXT_PUBLIC_AUTH_URL } = getAuthConfig();
|
|
13
|
-
const enableMagicLink = getAuthConfig().NEXT_PUBLIC_ENABLE_MAGIC_LINK;
|
|
14
13
|
|
|
15
14
|
export const {
|
|
16
15
|
linkSocial,
|
|
@@ -26,11 +25,16 @@ export const {
|
|
|
26
25
|
useSession,
|
|
27
26
|
} = createAuthClient({
|
|
28
27
|
/** The base URL of the server (optional if you're using the same domain) */
|
|
29
|
-
|
|
28
|
+
...(NEXT_PUBLIC_AUTH_URL
|
|
29
|
+
? {
|
|
30
|
+
baseURL: NEXT_PUBLIC_AUTH_URL,
|
|
31
|
+
}
|
|
32
|
+
: {}),
|
|
30
33
|
plugins: [
|
|
31
34
|
adminClient(),
|
|
32
35
|
inferAdditionalFields<typeof auth>(),
|
|
33
36
|
genericOAuthClient(),
|
|
34
|
-
|
|
37
|
+
// Always include magicLinkClient - server will reject if not enabled
|
|
38
|
+
magicLinkClient(),
|
|
35
39
|
],
|
|
36
40
|
});
|
|
@@ -58,7 +58,7 @@ const getPasskeyOrigins = (): string[] | undefined => {
|
|
|
58
58
|
const MAGIC_LINK_EXPIRES_IN = 900;
|
|
59
59
|
// OTP expiration time (in seconds) - 5 minutes for mobile OTP verification
|
|
60
60
|
const OTP_EXPIRES_IN = 300;
|
|
61
|
-
const enableMagicLink = authEnv.
|
|
61
|
+
const enableMagicLink = authEnv.ENABLE_MAGIC_LINK;
|
|
62
62
|
const enabledSSOProviders = parseSSOProviders(authEnv.AUTH_SSO_PROVIDERS);
|
|
63
63
|
|
|
64
64
|
const { socialProviders, genericOAuthProviders } = initBetterAuthSSOProviders();
|
|
@@ -91,7 +91,7 @@ export function defineConfig(customOptions: CustomBetterAuthOptions) {
|
|
|
91
91
|
enabled: true,
|
|
92
92
|
maxPasswordLength: 64,
|
|
93
93
|
minPasswordLength: 8,
|
|
94
|
-
requireEmailVerification: authEnv.
|
|
94
|
+
requireEmailVerification: authEnv.AUTH_EMAIL_VERIFICATION,
|
|
95
95
|
|
|
96
96
|
// Compatible with bcrypt password hashes migrated from Clerk; after login, you can re-hash in the backend using BetterAuth's default scrypt.
|
|
97
97
|
password: {
|
|
@@ -5,11 +5,10 @@ import { UAParser } from 'ua-parser-js';
|
|
|
5
5
|
import urlJoin from 'url-join';
|
|
6
6
|
|
|
7
7
|
import { auth } from '@/auth';
|
|
8
|
-
import { OAUTH_AUTHORIZED } from '@/const/auth';
|
|
9
8
|
import { LOBE_LOCALE_COOKIE } from '@/const/locale';
|
|
10
9
|
import { isDesktop } from '@/const/version';
|
|
11
10
|
import { appEnv } from '@/envs/app';
|
|
12
|
-
import { authEnv } from '@/envs/auth';
|
|
11
|
+
import { OAUTH_AUTHORIZED , authEnv } from '@/envs/auth';
|
|
13
12
|
import NextAuth from '@/libs/next-auth';
|
|
14
13
|
import { type Locales } from '@/locales/resources';
|
|
15
14
|
import { parseBrowserLanguage } from '@/utils/locale';
|
|
@@ -2,7 +2,7 @@ import { type LobeChatDatabase } from '@lobechat/database';
|
|
|
2
2
|
import debug from 'debug';
|
|
3
3
|
import { type NextRequest } from 'next/server';
|
|
4
4
|
|
|
5
|
-
import { LOBE_CHAT_AUTH_HEADER } from '@/
|
|
5
|
+
import { LOBE_CHAT_AUTH_HEADER } from '@/envs/auth';
|
|
6
6
|
import { KeyVaultsGateKeeper } from '@/server/modules/KeyVaultsEncrypt';
|
|
7
7
|
|
|
8
8
|
const log = debug('lobe-async:context');
|
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
LOBE_CHAT_AUTH_HEADER,
|
|
3
|
-
LOBE_CHAT_OIDC_AUTH_HEADER,
|
|
4
|
-
enableBetterAuth,
|
|
5
|
-
enableClerk,
|
|
6
|
-
enableNextAuth,
|
|
7
|
-
} from '@lobechat/const';
|
|
8
1
|
import { type ClientSecretPayload } from '@lobechat/types';
|
|
9
2
|
import { parse } from 'cookie';
|
|
10
3
|
import debug from 'debug';
|
|
11
4
|
import { type User } from 'next-auth';
|
|
12
5
|
import { type NextRequest } from 'next/server';
|
|
13
6
|
|
|
14
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
LOBE_CHAT_AUTH_HEADER,
|
|
9
|
+
LOBE_CHAT_OIDC_AUTH_HEADER,
|
|
10
|
+
enableBetterAuth,
|
|
11
|
+
enableClerk,
|
|
12
|
+
enableNextAuth,
|
|
13
|
+
authEnv } from '@/envs/auth';
|
|
15
14
|
import { ClerkAuth, type IClerkAuth } from '@/libs/clerk-auth';
|
|
16
15
|
import { validateOIDCJWT } from '@/libs/oidc-provider/jwt';
|
|
17
16
|
|
|
@@ -114,6 +114,7 @@ export default {
|
|
|
114
114
|
'ModelSwitchPanel.goToSettings': 'Go to settings',
|
|
115
115
|
'ModelSwitchPanel.manageProvider': 'Manage Provider',
|
|
116
116
|
'ModelSwitchPanel.provider': 'Provider',
|
|
117
|
+
'ModelSwitchPanel.searchPlaceholder': 'Search models...',
|
|
117
118
|
'ModelSwitchPanel.title': 'Model',
|
|
118
119
|
'ModelSwitchPanel.useModelFrom': 'Use this model from:',
|
|
119
120
|
'MultiImagesUpload.actions.uploadMore': 'Click or drag to upload more',
|
|
@@ -74,7 +74,9 @@ export const getServerGlobalConfig = async () => {
|
|
|
74
74
|
defaultAgent: {
|
|
75
75
|
config: parseAgentConfig(DEFAULT_AGENT_CONFIG),
|
|
76
76
|
},
|
|
77
|
+
enableEmailVerification: authEnv.AUTH_EMAIL_VERIFICATION,
|
|
77
78
|
enableKlavis: !!klavisEnv.KLAVIS_API_KEY,
|
|
79
|
+
enableMagicLink: authEnv.ENABLE_MAGIC_LINK,
|
|
78
80
|
enableMarketTrustedClient: !!(
|
|
79
81
|
appEnv.MARKET_TRUSTED_CLIENT_SECRET && appEnv.MARKET_TRUSTED_CLIENT_ID
|
|
80
82
|
),
|
|
@@ -2,8 +2,8 @@ import { createTRPCClient, httpLink } from '@trpc/client';
|
|
|
2
2
|
import superjson from 'superjson';
|
|
3
3
|
import urlJoin from 'url-join';
|
|
4
4
|
|
|
5
|
-
import { LOBE_CHAT_AUTH_HEADER } from '@/const/auth';
|
|
6
5
|
import { appEnv } from '@/envs/app';
|
|
6
|
+
import { LOBE_CHAT_AUTH_HEADER } from '@/envs/auth';
|
|
7
7
|
import { createAsyncCallerFactory } from '@/libs/trpc/async';
|
|
8
8
|
import { signInternalJWT } from '@/libs/trpc/utils/internalJwt';
|
|
9
9
|
import { KeyVaultsGateKeeper } from '@/server/modules/KeyVaultsEncrypt';
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// @vitest-environment node
|
|
2
2
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
3
|
|
|
4
|
-
import { enableClerk } from '@/const/auth';
|
|
5
4
|
import { MessageModel } from '@/database/models/message';
|
|
6
5
|
import { SessionModel } from '@/database/models/session';
|
|
7
6
|
import { UserModel, UserNotFoundError } from '@/database/models/user';
|
|
8
7
|
import { serverDB } from '@/database/server';
|
|
8
|
+
import { enableClerk } from '@/envs/auth';
|
|
9
9
|
import { KeyVaultsGateKeeper } from '@/server/modules/KeyVaultsEncrypt';
|
|
10
10
|
import { NextAuthUserService } from '@/server/services/nextAuthUser';
|
|
11
11
|
import { UserService } from '@/server/services/user';
|
|
@@ -28,7 +28,7 @@ vi.mock('@/server/modules/KeyVaultsEncrypt');
|
|
|
28
28
|
vi.mock('@/server/modules/S3');
|
|
29
29
|
vi.mock('@/server/services/user');
|
|
30
30
|
vi.mock('@/server/services/nextAuthUser');
|
|
31
|
-
vi.mock('@/
|
|
31
|
+
vi.mock('@/envs/auth', () => ({
|
|
32
32
|
enableBetterAuth: false,
|
|
33
33
|
enableClerk: true,
|
|
34
34
|
enableNextAuth: false,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type UserJSON } from '@clerk/backend';
|
|
2
|
-
import {
|
|
2
|
+
import { isDesktop } from '@lobechat/const';
|
|
3
3
|
import {
|
|
4
4
|
NextAuthAccountSchame,
|
|
5
5
|
Plans,
|
|
@@ -20,6 +20,7 @@ import { getIsInWaitList, getReferralStatus, getSubscriptionPlan } from '@/busin
|
|
|
20
20
|
import { MessageModel } from '@/database/models/message';
|
|
21
21
|
import { SessionModel } from '@/database/models/session';
|
|
22
22
|
import { UserModel, UserNotFoundError } from '@/database/models/user';
|
|
23
|
+
import { enableClerk } from '@/envs/auth';
|
|
23
24
|
import { ClerkAuth } from '@/libs/clerk-auth';
|
|
24
25
|
import { pino } from '@/libs/logger';
|
|
25
26
|
import { authedProcedure, router } from '@/libs/trpc/lambda';
|
package/src/services/_auth.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { LOBE_CHAT_AUTH_HEADER } from '@lobechat/const';
|
|
2
1
|
import {
|
|
3
2
|
type AWSBedrockKeyVault,
|
|
4
3
|
type AzureOpenAIKeyVault,
|
|
@@ -11,6 +10,7 @@ import {
|
|
|
11
10
|
import { clientApiKeyManager } from '@lobechat/utils/client';
|
|
12
11
|
import { ModelProvider } from 'model-bank';
|
|
13
12
|
|
|
13
|
+
import { LOBE_CHAT_AUTH_HEADER, SECRET_XOR_KEY } from '@/envs/auth';
|
|
14
14
|
import { aiProviderSelectors, useAiInfraStore } from '@/store/aiInfra';
|
|
15
15
|
import { useUserStore } from '@/store/user';
|
|
16
16
|
import { userProfileSelectors } from '@/store/user/selectors';
|
|
@@ -107,7 +107,7 @@ export const getProviderAuthPayload = (
|
|
|
107
107
|
const createAuthTokenWithPayload = (payload = {}) => {
|
|
108
108
|
const userId = userProfileSelectors.userId(useUserStore.getState());
|
|
109
109
|
|
|
110
|
-
return obfuscatePayloadWithXOR<ClientSecretPayload>({ userId, ...payload });
|
|
110
|
+
return obfuscatePayloadWithXOR<ClientSecretPayload>({ userId, ...payload }, SECRET_XOR_KEY);
|
|
111
111
|
};
|
|
112
112
|
|
|
113
113
|
interface AuthParams {
|
|
@@ -130,7 +130,7 @@ export const createPayloadWithKeyVaults = (provider: string) => {
|
|
|
130
130
|
|
|
131
131
|
export const createXorKeyVaultsPayload = (provider: string) => {
|
|
132
132
|
const payload = createPayloadWithKeyVaults(provider);
|
|
133
|
-
return obfuscatePayloadWithXOR(payload);
|
|
133
|
+
return obfuscatePayloadWithXOR(payload, SECRET_XOR_KEY);
|
|
134
134
|
};
|
|
135
135
|
|
|
136
136
|
// eslint-disable-next-line no-undef
|
|
@@ -24,8 +24,8 @@ import {
|
|
|
24
24
|
import { merge } from 'es-toolkit/compat';
|
|
25
25
|
import { ModelProvider } from 'model-bank';
|
|
26
26
|
|
|
27
|
-
import { enableAuth } from '@/const/auth';
|
|
28
27
|
import { DEFAULT_AGENT_CONFIG } from '@/const/settings';
|
|
28
|
+
import { enableAuth } from '@/envs/auth';
|
|
29
29
|
import { getSearchConfig } from '@/helpers/getSearchConfig';
|
|
30
30
|
import { createAgentToolsEngine, createToolsEngine } from '@/helpers/toolEngineering';
|
|
31
31
|
import { getAgentStoreState } from '@/store/agent';
|
|
@@ -74,7 +74,7 @@ interface ContextEngineeringContext {
|
|
|
74
74
|
topicId?: string;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
// REVIEW
|
|
77
|
+
// REVIEW: Maybe we can constrain identity, preference, exp to reorder or trim the context instead of passing everything in
|
|
78
78
|
export const contextEngineering = async ({
|
|
79
79
|
messages = [],
|
|
80
80
|
manifests,
|
|
@@ -113,6 +113,14 @@ export interface SystemStatus {
|
|
|
113
113
|
leftPanelWidth: number;
|
|
114
114
|
mobileShowPortal?: boolean;
|
|
115
115
|
mobileShowTopic?: boolean;
|
|
116
|
+
/**
|
|
117
|
+
* ModelSwitchPanel 的分组模式
|
|
118
|
+
*/
|
|
119
|
+
modelSwitchPanelGroupMode?: 'byModel' | 'byProvider';
|
|
120
|
+
/**
|
|
121
|
+
* ModelSwitchPanel 的宽度
|
|
122
|
+
*/
|
|
123
|
+
modelSwitchPanelWidth?: number;
|
|
116
124
|
noWideScreen?: boolean;
|
|
117
125
|
/**
|
|
118
126
|
* number of pages (documents) to display per page
|
|
@@ -179,6 +187,8 @@ export const INITIAL_STATUS = {
|
|
|
179
187
|
knowledgeBaseModalViewMode: 'list' as const,
|
|
180
188
|
leftPanelWidth: 320,
|
|
181
189
|
mobileShowTopic: false,
|
|
190
|
+
modelSwitchPanelGroupMode: 'byProvider',
|
|
191
|
+
modelSwitchPanelWidth: 430,
|
|
182
192
|
noWideScreen: true,
|
|
183
193
|
pagePageSize: 20,
|
|
184
194
|
portalWidth: 400,
|
|
@@ -24,6 +24,9 @@ const showImageTopicPanel = (s: GlobalState) => s.status.showImageTopicPanel;
|
|
|
24
24
|
const hidePWAInstaller = (s: GlobalState) => s.status.hidePWAInstaller;
|
|
25
25
|
const isShowCredit = (s: GlobalState) => s.status.isShowCredit;
|
|
26
26
|
const language = (s: GlobalState) => s.status.language || 'auto';
|
|
27
|
+
const modelSwitchPanelGroupMode = (s: GlobalState) =>
|
|
28
|
+
s.status.modelSwitchPanelGroupMode || 'byProvider';
|
|
29
|
+
const modelSwitchPanelWidth = (s: GlobalState) => s.status.modelSwitchPanelWidth || 430;
|
|
27
30
|
|
|
28
31
|
const showChatHeader = (s: GlobalState) => !s.status.zenMode;
|
|
29
32
|
const inZenMode = (s: GlobalState) => s.status.zenMode;
|
|
@@ -68,6 +71,8 @@ export const systemStatusSelectors = {
|
|
|
68
71
|
leftPanelWidth,
|
|
69
72
|
mobileShowPortal,
|
|
70
73
|
mobileShowTopic,
|
|
74
|
+
modelSwitchPanelGroupMode,
|
|
75
|
+
modelSwitchPanelWidth,
|
|
71
76
|
pagePageSize,
|
|
72
77
|
portalWidth,
|
|
73
78
|
sessionGroupKeys,
|
|
@@ -3,8 +3,12 @@ import { type ServerConfigStore } from './store';
|
|
|
3
3
|
export const featureFlagsSelectors = (s: ServerConfigStore) => s.featureFlags;
|
|
4
4
|
|
|
5
5
|
export const serverConfigSelectors = {
|
|
6
|
+
enableEmailVerification: (s: ServerConfigStore) =>
|
|
7
|
+
s.serverConfig.enableEmailVerification || false,
|
|
6
8
|
enableKlavis: (s: ServerConfigStore) => s.serverConfig.enableKlavis || false,
|
|
7
|
-
|
|
9
|
+
enableMagicLink: (s: ServerConfigStore) => s.serverConfig.enableMagicLink || false,
|
|
10
|
+
enableMarketTrustedClient: (s: ServerConfigStore) =>
|
|
11
|
+
s.serverConfig.enableMarketTrustedClient || false,
|
|
8
12
|
enableUploadFileToServer: (s: ServerConfigStore) => s.serverConfig.enableUploadFileToServer,
|
|
9
13
|
enabledAccessCode: (s: ServerConfigStore) => !!s.serverConfig?.enabledAccessCode,
|
|
10
14
|
enabledTelemetryChat: (s: ServerConfigStore) => s.serverConfig.telemetry.langfuse || false,
|