@lobehub/lobehub 2.0.0-next.68 → 2.0.0-next.69

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.
Files changed (59) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/changelog/v1.json +9 -0
  3. package/package.json +1 -1
  4. package/packages/const/src/version.ts +0 -5
  5. package/packages/database/src/models/__tests__/chunk.test.ts +38 -0
  6. package/src/app/(backend)/api/webhooks/clerk/route.ts +1 -2
  7. package/src/app/[variants]/(main)/(mobile)/me/(home)/__tests__/useCategory.test.tsx +0 -20
  8. package/src/app/[variants]/(main)/(mobile)/me/(home)/features/useCategory.tsx +4 -33
  9. package/src/app/[variants]/(main)/(mobile)/me/profile/features/Category.tsx +18 -23
  10. package/src/app/[variants]/(main)/(mobile)/me/settings/features/useCategory.tsx +5 -15
  11. package/src/app/[variants]/(main)/discover/(detail)/provider/[...slugs]/features/Sidebar/ActionButton/ProviderConfig.tsx +4 -11
  12. package/src/app/[variants]/(main)/image/@menu/features/ConfigPanel/components/ModelSelect/index.tsx +12 -27
  13. package/src/app/[variants]/(main)/image/layout.tsx +0 -4
  14. package/src/app/[variants]/(main)/profile/hooks/useCategory.tsx +10 -13
  15. package/src/app/[variants]/(main)/profile/stats/features/ShareButton/Preview.tsx +2 -14
  16. package/src/app/[variants]/(main)/settings/_layout/Desktop/index.tsx +2 -3
  17. package/src/app/[variants]/(main)/settings/_layout/SettingsContent.tsx +1 -12
  18. package/src/app/[variants]/(main)/settings/_layout/type.ts +0 -1
  19. package/src/app/[variants]/(main)/settings/hooks/useCategory.tsx +8 -16
  20. package/src/app/[variants]/(main)/settings/page.tsx +3 -7
  21. package/src/app/[variants]/(main)/settings/provider/features/ProviderConfig/index.tsx +2 -4
  22. package/src/app/[variants]/(main)/settings/storage/index.tsx +1 -9
  23. package/src/app/[variants]/(main)/settings/system-agent/index.tsx +1 -2
  24. package/src/components/InvalidAPIKey/APIKeyForm/useApiKey.ts +0 -12
  25. package/src/config/featureFlags/schema.test.ts +1 -3
  26. package/src/config/featureFlags/schema.ts +0 -3
  27. package/src/features/ChatInput/ActionBar/Knowledge/index.tsx +2 -3
  28. package/src/features/ChatInput/ActionBar/Search/index.tsx +5 -7
  29. package/src/features/ChatInput/ActionBar/Upload/index.tsx +1 -3
  30. package/src/features/Conversation/Messages/Assistant/index.tsx +1 -1
  31. package/src/features/Conversation/components/ShareMessageModal/index.tsx +3 -8
  32. package/src/features/DevPanel/PostgresViewer/usePgTable.ts +3 -11
  33. package/src/features/ModelSwitchPanel/index.tsx +9 -24
  34. package/src/features/ShareModal/index.tsx +7 -13
  35. package/src/features/User/UserPanel/PanelContent.tsx +6 -8
  36. package/src/hooks/useCheckPluginsIsInstalled.ts +1 -4
  37. package/src/hooks/useFetchGroups.ts +1 -4
  38. package/src/hooks/useFetchInstalledPlugins.ts +1 -4
  39. package/src/hooks/useFetchMessages.ts +1 -4
  40. package/src/hooks/useFetchSessions.ts +1 -4
  41. package/src/hooks/useFetchThreads.ts +1 -5
  42. package/src/hooks/useFetchTopics.ts +1 -4
  43. package/src/hooks/useInterceptingRoutes.test.ts +0 -19
  44. package/src/hooks/useInterceptingRoutes.ts +1 -7
  45. package/src/layout/GlobalProvider/StoreInitialization.tsx +2 -4
  46. package/src/services/_auth.ts +2 -11
  47. package/src/services/_header.ts +2 -10
  48. package/src/services/chat/chat.test.ts +53 -10
  49. package/src/services/chat/clientModelRuntime.test.ts +108 -172
  50. package/src/services/chat/contextEngineering.ts +2 -2
  51. package/src/services/config.ts +2 -2
  52. package/src/store/aiInfra/slices/aiProvider/action.ts +3 -4
  53. package/src/store/chat/slices/thread/action.ts +2 -2
  54. package/src/store/global/selectors/systemStatus.test.ts +0 -98
  55. package/src/store/global/selectors/systemStatus.ts +0 -30
  56. package/src/store/serverConfig/selectors.test.ts +2 -2
  57. package/src/store/serverConfig/store.test.ts +0 -1
  58. package/src/app/[variants]/(main)/settings/storage/IndexedDBStorage.tsx +0 -55
  59. package/src/features/ChatInput/ActionBar/Upload/ClientMode.tsx +0 -62
package/CHANGELOG.md CHANGED
@@ -2,6 +2,31 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ## [Version 2.0.0-next.69](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.68...v2.0.0-next.69)
6
+
7
+ <sup>Released on **2025-11-17**</sup>
8
+
9
+ #### ♻ Code Refactoring
10
+
11
+ - **misc**: Remove `language_model_settings` and remove isDeprecatedEdition.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### Code refactoring
19
+
20
+ - **misc**: Remove `language_model_settings` and remove isDeprecatedEdition, closes [#10264](https://github.com/lobehub/lobe-chat/issues/10264) ([ae613c7](https://github.com/lobehub/lobe-chat/commit/ae613c7))
21
+
22
+ </details>
23
+
24
+ <div align="right">
25
+
26
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
27
+
28
+ </div>
29
+
5
30
  ## [Version 2.0.0-next.68](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.67...v2.0.0-next.68)
6
31
 
7
32
  <sup>Released on **2025-11-16**</sup>
package/changelog/v1.json CHANGED
@@ -1,4 +1,13 @@
1
1
  [
2
+ {
3
+ "children": {
4
+ "improvements": [
5
+ "Remove language_model_settings and remove isDeprecatedEdition."
6
+ ]
7
+ },
8
+ "date": "2025-11-17",
9
+ "version": "2.0.0-next.69"
10
+ },
2
11
  {
3
12
  "children": {
4
13
  "fixes": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/lobehub",
3
- "version": "2.0.0-next.68",
3
+ "version": "2.0.0-next.69",
4
4
  "description": "LobeHub - an open-source,comprehensive AI Agent framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
5
5
  "keywords": [
6
6
  "framework",
@@ -4,13 +4,8 @@ import { BRANDING_NAME, ORG_NAME } from './branding';
4
4
 
5
5
  export const CURRENT_VERSION = pkg.version;
6
6
 
7
- export const isServerMode = true;
8
- export const isUsePgliteDB = false;
9
-
10
7
  export const isDesktop = process.env.NEXT_PUBLIC_IS_DESKTOP_APP === '1';
11
8
 
12
- export const isDeprecatedEdition = false;
13
-
14
9
  // @ts-ignore
15
10
  export const isCustomBranding = BRANDING_NAME !== 'LobeHub';
16
11
  // @ts-ignore
@@ -287,6 +287,44 @@ describe('ChunkModel', () => {
287
287
  expect(result[1].index).toBe(1);
288
288
  expect(result[2].index).toBe(2);
289
289
  });
290
+
291
+ it('should handle chunks with null metadata and return undefined pageNumber', async () => {
292
+ const fileId = '1';
293
+ const [chunk] = await serverDB
294
+ .insert(chunks)
295
+ .values([{ text: 'Chunk with null metadata', userId, index: 0, metadata: null }])
296
+ .returning();
297
+
298
+ await serverDB.insert(fileChunks).values([{ fileId, chunkId: chunk.id, userId }]);
299
+
300
+ const result = await chunkModel.findByFileId(fileId, 0);
301
+
302
+ expect(result).toHaveLength(1);
303
+ expect(result[0].metadata).toBeNull();
304
+ expect(result[0].pageNumber).toBeUndefined();
305
+ });
306
+
307
+ it('should handle chunks with metadata containing pageNumber', async () => {
308
+ const fileId = '1';
309
+ const [chunk] = await serverDB
310
+ .insert(chunks)
311
+ .values([
312
+ {
313
+ text: 'Chunk with pageNumber',
314
+ userId,
315
+ index: 0,
316
+ metadata: { pageNumber: 5 } as any,
317
+ },
318
+ ])
319
+ .returning();
320
+
321
+ await serverDB.insert(fileChunks).values([{ fileId, chunkId: chunk.id, userId }]);
322
+
323
+ const result = await chunkModel.findByFileId(fileId, 0);
324
+
325
+ expect(result).toHaveLength(1);
326
+ expect(result[0].pageNumber).toBe(5);
327
+ });
290
328
  });
291
329
 
292
330
  describe('getChunksTextByFileId', () => {
@@ -1,6 +1,5 @@
1
1
  import { NextResponse } from 'next/server';
2
2
 
3
- import { isServerMode } from '@/const/version';
4
3
  import { serverDB } from '@/database/server';
5
4
  import { authEnv } from '@/envs/auth';
6
5
  import { pino } from '@/libs/logger';
@@ -8,7 +7,7 @@ import { UserService } from '@/server/services/user';
8
7
 
9
8
  import { validateRequest } from './validateRequest';
10
9
 
11
- if (authEnv.NEXT_PUBLIC_ENABLE_CLERK_AUTH && isServerMode && !authEnv.CLERK_WEBHOOK_SECRET) {
10
+ if (authEnv.NEXT_PUBLIC_ENABLE_CLERK_AUTH && !authEnv.CLERK_WEBHOOK_SECRET) {
12
11
  throw new Error('`CLERK_WEBHOOK_SECRET` environment variable is missing');
13
12
  }
14
13
 
@@ -23,10 +23,6 @@ vi.mock('react-i18next', () => ({
23
23
  })),
24
24
  }));
25
25
 
26
- vi.mock('../../settings/features/useCategory', () => ({
27
- useCategory: vi.fn(() => [{ key: 'extraSetting', label: 'Extra Setting' }]),
28
- }));
29
-
30
26
  // 定义一个变量来存储 enableAuth 的值
31
27
  let enableAuth = true;
32
28
  let enableClerk = true;
@@ -68,7 +64,6 @@ describe('useCategory', () => {
68
64
  const items = result.current;
69
65
  expect(items.some((item) => item.key === 'profile')).toBe(true);
70
66
  expect(items.some((item) => item.key === 'setting')).toBe(true);
71
- expect(items.some((item) => item.key === 'data')).toBe(true);
72
67
  expect(items.some((item) => item.key === 'docs')).toBe(true);
73
68
  expect(items.some((item) => item.key === 'feedback')).toBe(true);
74
69
  expect(items.some((item) => item.key === 'changelog')).toBe(true);
@@ -93,19 +88,4 @@ describe('useCategory', () => {
93
88
  expect(items.some((item) => item.key === 'changelog')).toBe(true);
94
89
  });
95
90
  });
96
-
97
- it('should handle settings for non-authenticated users', () => {
98
- act(() => {
99
- useUserStore.setState({ isSignedIn: false });
100
- });
101
- enableClerk = false;
102
- enableAuth = false;
103
-
104
- const { result } = renderHook(() => useCategory(), { wrapper });
105
-
106
- act(() => {
107
- const items = result.current;
108
- expect(items.some((item) => item.key === 'extraSetting')).toBe(true);
109
- });
110
- });
111
91
  });
@@ -1,8 +1,8 @@
1
+ import { DOCUMENTS, FEEDBACK, LOBE_CHAT_CLOUD, OFFICIAL_URL, UTM_SOURCE } from '@lobechat/const';
1
2
  import {
2
3
  Book,
3
4
  CircleUserRound,
4
5
  Cloudy,
5
- Database,
6
6
  Download,
7
7
  Feather,
8
8
  FileClockIcon,
@@ -12,26 +12,17 @@ import { useRouter } from 'next/navigation';
12
12
  import { useTranslation } from 'react-i18next';
13
13
 
14
14
  import { CellProps } from '@/components/Cell';
15
- import { enableAuth } from '@/const/auth';
16
- import { LOBE_CHAT_CLOUD } from '@/const/branding';
17
- import { DOCUMENTS, FEEDBACK, OFFICIAL_URL, UTM_SOURCE } from '@/const/url';
18
- import { isServerMode } from '@/const/version';
19
15
  import { usePWAInstall } from '@/hooks/usePWAInstall';
20
16
  import { featureFlagsSelectors, useServerConfigStore } from '@/store/serverConfig';
21
17
  import { useUserStore } from '@/store/user';
22
18
  import { authSelectors } from '@/store/user/selectors';
23
19
 
24
- import { useCategory as useSettingsCategory } from '../../settings/features/useCategory';
25
-
26
20
  export const useCategory = () => {
27
21
  const router = useRouter();
28
22
  const { canInstall, install } = usePWAInstall();
29
23
  const { t } = useTranslation(['common', 'setting', 'auth']);
30
24
  const { showCloudPromotion, hideDocs } = useServerConfigStore(featureFlagsSelectors);
31
- const [isLogin, isLoginWithAuth] = useUserStore((s) => [
32
- authSelectors.isLogin(s),
33
- authSelectors.isLoginWithAuth(s),
34
- ]);
25
+ const [isLoginWithAuth] = useUserStore((s) => [authSelectors.isLoginWithAuth(s)]);
35
26
 
36
27
  const profile: CellProps[] = [
37
28
  {
@@ -66,29 +57,10 @@ export const useCategory = () => {
66
57
  },
67
58
  ];
68
59
 
69
- const settingsWithoutAuth = [
70
- ...useSettingsCategory(),
71
- {
72
- type: 'divider',
73
- },
74
- ];
75
-
76
60
  /* ↓ cloud slot ↓ */
77
61
 
78
62
  /* ↑ cloud slot ↑ */
79
63
 
80
- const data: CellProps[] = [
81
- {
82
- icon: Database,
83
- key: 'data',
84
- label: t('userPanel.data'),
85
- onClick: () => router.push('/me/data'),
86
- },
87
- {
88
- type: 'divider',
89
- },
90
- ];
91
-
92
64
  const helps: CellProps[] = [
93
65
  showCloudPromotion && {
94
66
  icon: Cloudy,
@@ -120,13 +92,12 @@ export const useCategory = () => {
120
92
  {
121
93
  type: 'divider',
122
94
  },
123
- ...(!enableAuth || (enableAuth && isLoginWithAuth) ? profile : []),
124
- ...(enableAuth ? (isLoginWithAuth ? settings : []) : settingsWithoutAuth),
95
+ ...(isLoginWithAuth ? profile : []),
96
+ ...(isLoginWithAuth ? settings : []),
125
97
  /* ↓ cloud slot ↓ */
126
98
 
127
99
  /* ↑ cloud slot ↑ */
128
100
  ...(canInstall ? pwa : []),
129
- ...(isLogin && !isServerMode ? data : []),
130
101
  ...(!hideDocs ? helps : []),
131
102
  ].filter(Boolean) as CellProps[];
132
103
 
@@ -6,8 +6,6 @@ import { memo } from 'react';
6
6
  import { useTranslation } from 'react-i18next';
7
7
 
8
8
  import Cell, { CellProps } from '@/components/Cell';
9
- import { enableAuth } from '@/const/auth';
10
- import { isDeprecatedEdition } from '@/const/version';
11
9
  import { ProfileTabs } from '@/store/global/initialState';
12
10
  import { useUserStore } from '@/store/user';
13
11
  import { authSelectors } from '@/store/user/selectors';
@@ -27,33 +25,30 @@ const Category = memo(() => {
27
25
  label: t('tab.profile'),
28
26
  onClick: () => router.push('/profile'),
29
27
  },
30
- enableAuth &&
31
- isLoginWithClerk && {
32
- icon: ShieldCheck,
33
- key: ProfileTabs.Security,
34
- label: t('tab.security'),
35
- onClick: () => router.push('/profile/security'),
36
- },
37
- !isDeprecatedEdition && {
28
+ isLoginWithClerk && {
29
+ icon: ShieldCheck,
30
+ key: ProfileTabs.Security,
31
+ label: t('tab.security'),
32
+ onClick: () => router.push('/profile/security'),
33
+ },
34
+ {
38
35
  icon: ChartColumnBigIcon,
39
36
  key: ProfileTabs.Stats,
40
37
  label: t('tab.stats'),
41
38
  onClick: () => router.push('/profile/stats'),
42
39
  },
43
- enableAuth &&
44
- isLogin && {
45
- type: 'divider',
46
- },
47
- enableAuth &&
48
- isLogin && {
49
- icon: LogOut,
50
- key: 'logout',
51
- label: t('signout', { ns: 'auth' }),
52
- onClick: () => {
53
- signOut();
54
- router.push('/login');
55
- },
40
+ isLogin && {
41
+ type: 'divider',
42
+ },
43
+ isLogin && {
44
+ icon: LogOut,
45
+ key: 'logout',
46
+ label: t('signout', { ns: 'auth' }),
47
+ onClick: () => {
48
+ signOut();
49
+ router.push('/login');
56
50
  },
51
+ },
57
52
  ].filter(Boolean) as CellProps[];
58
53
 
59
54
  return items?.map(({ key, ...item }, index) => <Cell key={key || index} {...item} />);
@@ -3,14 +3,11 @@ import { useRouter } from 'next/navigation';
3
3
  import { useTranslation } from 'react-i18next';
4
4
 
5
5
  import { CellProps } from '@/components/Cell';
6
- import { isDeprecatedEdition } from '@/const/version';
7
6
  import { SettingsTabs } from '@/store/global/initialState';
8
- import { featureFlagsSelectors, useServerConfigStore } from '@/store/serverConfig';
9
7
 
10
8
  export const useCategory = () => {
11
9
  const router = useRouter();
12
10
  const { t } = useTranslation('setting');
13
- const { showLLM } = useServerConfigStore(featureFlagsSelectors);
14
11
 
15
12
  const items: CellProps[] = [
16
13
  {
@@ -23,18 +20,11 @@ export const useCategory = () => {
23
20
  key: SettingsTabs.SystemAgent,
24
21
  label: t('tab.system-agent'),
25
22
  },
26
- showLLM &&
27
- (isDeprecatedEdition
28
- ? {
29
- icon: Brain,
30
- key: SettingsTabs.LLM,
31
- label: t('tab.llm'),
32
- }
33
- : {
34
- icon: Brain,
35
- key: SettingsTabs.Provider,
36
- label: t('tab.provider'),
37
- }),
23
+ {
24
+ icon: Brain,
25
+ key: SettingsTabs.Provider,
26
+ label: t('tab.provider'),
27
+ },
38
28
  { icon: Mic2, key: SettingsTabs.TTS, label: t('tab.tts') },
39
29
  {
40
30
  icon: Bot,
@@ -1,5 +1,6 @@
1
1
  'use client';
2
2
 
3
+ import { isDesktop } from '@lobechat/const';
3
4
  import { Button, Icon } from '@lobehub/ui';
4
5
  import { Dropdown } from 'antd';
5
6
  import { createStyles } from 'antd-style';
@@ -9,8 +10,6 @@ import { useRouter } from 'nextjs-toploader/app';
9
10
  import { memo } from 'react';
10
11
  import { useTranslation } from 'react-i18next';
11
12
 
12
- import { isDeprecatedEdition, isDesktop } from '@/const/version';
13
-
14
13
  import { useDetailContext } from '../../DetailProvider';
15
14
 
16
15
  const useStyles = createStyles(({ css }) => ({
@@ -27,10 +26,8 @@ const ProviderConfig = memo(() => {
27
26
  const { url, modelsUrl, identifier } = useDetailContext();
28
27
  const router = useRouter();
29
28
  const openSettings = async () => {
30
- const searchParams = isDeprecatedEdition
31
- ? { active: 'llm' }
32
- : { active: 'provider', provider: identifier };
33
- const tab = isDeprecatedEdition ? 'llm' : 'provider';
29
+ const searchParams = { active: 'provider', provider: identifier };
30
+ const tab = 'provider';
34
31
 
35
32
  if (isDesktop) {
36
33
  const { dispatch } = await import('@lobechat/electron-client-ipc');
@@ -41,11 +38,7 @@ const ProviderConfig = memo(() => {
41
38
  return;
42
39
  }
43
40
 
44
- router.push(
45
- isDeprecatedEdition
46
- ? '/settings?active=llm'
47
- : `/settings?active=provider&provider=${identifier}`,
48
- );
41
+ router.push(`/settings?active=provider&provider=${identifier}`);
49
42
  };
50
43
 
51
44
  const icon = <Icon icon={SquareArrowOutUpRight} size={16} />;
@@ -1,3 +1,4 @@
1
+ import { EnabledProviderWithModels } from '@lobechat/types';
1
2
  import { ActionIcon, Icon, Select, type SelectProps } from '@lobehub/ui';
2
3
  import { createStyles, useTheme } from 'antd-style';
3
4
  import { LucideArrowRight, LucideBolt } from 'lucide-react';
@@ -8,13 +9,10 @@ import { useTranslation } from 'react-i18next';
8
9
  import { Flexbox } from 'react-layout-kit';
9
10
 
10
11
  import { ProviderItemRender } from '@/components/ModelSelect';
11
- import { isDeprecatedEdition } from '@/const/version';
12
12
  import { useAiInfraStore } from '@/store/aiInfra';
13
13
  import { aiProviderSelectors } from '@/store/aiInfra/slices/aiProvider/selectors';
14
14
  import { useImageStore } from '@/store/image';
15
- import { imageGenerationConfigSelectors } from '@/store/image/slices/generationConfig/selectors';
16
- import { featureFlagsSelectors, useServerConfigStore } from '@/store/serverConfig';
17
- import { EnabledProviderWithModels } from '@/types/aiProvider';
15
+ import { imageGenerationConfigSelectors } from '@/store/image/selectors';
18
16
 
19
17
  import ImageModelItem from './ImageModelItem';
20
18
 
@@ -36,7 +34,6 @@ const ModelSelect = memo(() => {
36
34
  const { styles } = useStyles();
37
35
  const { t } = useTranslation('components');
38
36
  const theme = useTheme();
39
- const { showLLM } = useServerConfigStore(featureFlagsSelectors);
40
37
  const router = useRouter();
41
38
 
42
39
  const [currentModel, currentProvider] = useImageStore((s) => [
@@ -67,11 +64,7 @@ const ModelSelect = memo(() => {
67
64
  </Flexbox>
68
65
  ),
69
66
  onClick: () => {
70
- router.push(
71
- isDeprecatedEdition
72
- ? '/settings?active=llm'
73
- : `/settings?active=provider&provider=${provider.id}`,
74
- );
67
+ router.push(`/settings?active=provider&provider=${provider.id}`);
75
68
  },
76
69
  value: `${provider.id}/empty`,
77
70
  },
@@ -93,7 +86,7 @@ const ModelSelect = memo(() => {
93
86
  </Flexbox>
94
87
  ),
95
88
  onClick: () => {
96
- router.push(isDeprecatedEdition ? '/settings?active=llm' : '/settings?active=provider');
89
+ router.push('/settings?active=provider');
97
90
  },
98
91
  value: 'no-provider',
99
92
  },
@@ -114,26 +107,18 @@ const ModelSelect = memo(() => {
114
107
  provider={provider.id}
115
108
  source={provider.source}
116
109
  />
117
- {showLLM && (
118
- <Link
119
- href={
120
- isDeprecatedEdition
121
- ? '/settings?active=llm'
122
- : `/settings?active=provider&provider=${provider.id}`
123
- }
124
- >
125
- <ActionIcon
126
- icon={LucideBolt}
127
- size={'small'}
128
- title={t('ModelSwitchPanel.goToSettings')}
129
- />
130
- </Link>
131
- )}
110
+ <Link href={`/settings?active=provider&provider=${provider.id}`}>
111
+ <ActionIcon
112
+ icon={LucideBolt}
113
+ size={'small'}
114
+ title={t('ModelSwitchPanel.goToSettings')}
115
+ />
116
+ </Link>
132
117
  </Flexbox>
133
118
  ),
134
119
  options: getImageModels(provider),
135
120
  }));
136
- }, [enabledImageModelList, showLLM, t, theme.colorTextTertiary, router]);
121
+ }, [enabledImageModelList, t, theme.colorTextTertiary, router]);
137
122
 
138
123
  const labelRender: SelectProps['labelRender'] = (props) => {
139
124
  const modelInfo = enabledImageModelList
@@ -1,7 +1,5 @@
1
1
  import ServerLayout from '@/components/server/ServerLayout';
2
- import { isServerMode } from '@/const/version';
3
2
 
4
- import NotSupportClient from './NotSupportClient';
5
3
  import Desktop from './_layout/Desktop';
6
4
  import Mobile from './_layout/Mobile';
7
5
  import { LayoutProps } from './_layout/type';
@@ -11,8 +9,6 @@ const AiImageLayout = ServerLayout({ Desktop, Mobile });
11
9
  AiImageLayout.displayName = 'AiImageLayout';
12
10
 
13
11
  const Layout = (props: LayoutProps) => {
14
- if (!isServerMode) return <NotSupportClient />;
15
-
16
12
  return <AiImageLayout {...props} />;
17
13
  };
18
14
 
@@ -4,8 +4,6 @@ import Link from 'next/link';
4
4
  import { useTranslation } from 'react-i18next';
5
5
 
6
6
  import type { MenuProps } from '@/components/Menu';
7
- import { enableAuth } from '@/const/auth';
8
- import { isDeprecatedEdition } from '@/const/version';
9
7
  import { ProfileTabs } from '@/store/global/initialState';
10
8
  import { featureFlagsSelectors, useServerConfigStore } from '@/store/serverConfig';
11
9
  import { useUserStore } from '@/store/user';
@@ -26,17 +24,16 @@ export const useCategory = () => {
26
24
  </Link>
27
25
  ),
28
26
  },
29
- enableAuth &&
30
- isLoginWithClerk && {
31
- icon: <Icon icon={ShieldCheck} />,
32
- key: ProfileTabs.Security,
33
- label: (
34
- <Link href={'/profile/security'} onClick={(e) => e.preventDefault()}>
35
- {t('tab.security')}
36
- </Link>
37
- ),
38
- },
39
- !isDeprecatedEdition && {
27
+ isLoginWithClerk && {
28
+ icon: <Icon icon={ShieldCheck} />,
29
+ key: ProfileTabs.Security,
30
+ label: (
31
+ <Link href={'/profile/security'} onClick={(e) => e.preventDefault()}>
32
+ {t('tab.security')}
33
+ </Link>
34
+ ),
35
+ },
36
+ {
40
37
  icon: <Icon icon={ChartColumnBigIcon} />,
41
38
  key: ProfileTabs.Stats,
42
39
  label: (
@@ -1,4 +1,4 @@
1
- import { Github } from '@lobehub/icons';
1
+ import { OFFICIAL_URL, imageUrl } from '@lobechat/const';
2
2
  import { Grid } from '@lobehub/ui';
3
3
  import { createStyles } from 'antd-style';
4
4
  import { memo } from 'react';
@@ -6,8 +6,6 @@ import { useTranslation } from 'react-i18next';
6
6
  import { Center, Flexbox } from 'react-layout-kit';
7
7
 
8
8
  import { ProductLogo } from '@/components/Branding';
9
- import { OFFICIAL_URL, imageUrl } from '@/const/url';
10
- import { isServerMode } from '@/const/version';
11
9
  import UserAvatar from '@/features/User/UserAvatar';
12
10
 
13
11
  import AiHeatmaps from '../AiHeatmaps';
@@ -94,7 +92,6 @@ const useStyles = createStyles(({ css, token, stylish, cx, responsive }) => ({
94
92
  const Preview = memo(() => {
95
93
  const { styles } = useStyles();
96
94
  const { t } = useTranslation('auth');
97
- const isOfficial = !isServerMode && OFFICIAL_URL.includes(location.host);
98
95
 
99
96
  return (
100
97
  <div className={styles.preview}>
@@ -140,16 +137,7 @@ const Preview = memo(() => {
140
137
  <TotalWords inShare />
141
138
  </Grid>
142
139
  </Flexbox>
143
- <div className={styles.footer}>
144
- {isOfficial ? (
145
- OFFICIAL_URL
146
- ) : (
147
- <Flexbox align={'center'} gap={8} horizontal>
148
- <Github size={16} />
149
- <span>lobehub/lobe-chat</span>
150
- </Flexbox>
151
- )}
152
- </div>
140
+ <div className={styles.footer}>{OFFICIAL_URL}</div>
153
141
  </Center>
154
142
  </div>
155
143
  </div>
@@ -14,8 +14,7 @@ import { LayoutProps } from '../type';
14
14
  import Header from './Header';
15
15
  import SideBar from './SideBar';
16
16
 
17
- const Layout = memo<LayoutProps>((props) => {
18
- const { showLLM = true } = props;
17
+ const Layout = memo<LayoutProps>(() => {
19
18
  const ref = useRef<HTMLDivElement | null>(null);
20
19
  const { md = true } = useResponsive();
21
20
  const theme = useTheme();
@@ -40,7 +39,7 @@ const Layout = memo<LayoutProps>((props) => {
40
39
  <Header getContainer={() => ref.current!}>{category}</Header>
41
40
  )}
42
41
  <SettingContainer maxWidth={'none'}>
43
- <SettingsContent activeTab={activeTab} mobile={false} showLLM={showLLM} />
42
+ <SettingsContent activeTab={activeTab} mobile={false} />
44
43
  </SettingContainer>
45
44
  </Flexbox>
46
45
  );
@@ -1,7 +1,6 @@
1
1
  'use client';
2
2
 
3
3
  import dynamic from 'next/dynamic';
4
- import { notFound } from 'next/navigation';
5
4
  import React, { CSSProperties } from 'react';
6
5
  import { Flexbox } from 'react-layout-kit';
7
6
 
@@ -44,18 +43,9 @@ const componentMap = {
44
43
  interface SettingsContentProps {
45
44
  activeTab?: string;
46
45
  mobile?: boolean;
47
- showLLM?: boolean;
48
46
  }
49
47
 
50
- const SettingsContent = ({ mobile, activeTab, showLLM = true }: SettingsContentProps) => {
51
- const shouldRenderLLMTabs = (tab: string) => {
52
- const isLLMTab =
53
- tab === SettingsTabs.LLM || tab === SettingsTabs.Provider || tab === SettingsTabs.Agent;
54
- return showLLM || !isLLMTab;
55
- };
56
- if (activeTab && !shouldRenderLLMTabs(activeTab)) {
57
- notFound();
58
- }
48
+ const SettingsContent = ({ mobile, activeTab }: SettingsContentProps) => {
59
49
  const renderComponent = (tab: string) => {
60
50
  const Component = componentMap[tab as keyof typeof componentMap] || componentMap.common;
61
51
  if (!Component) return null;
@@ -88,7 +78,6 @@ const SettingsContent = ({ mobile, activeTab, showLLM = true }: SettingsContentP
88
78
  return (
89
79
  <Flexbox height={'100%'} width={'100%'}>
90
80
  {Object.keys(componentMap).map((tabKey) => {
91
- if (!shouldRenderLLMTabs(tabKey)) return null;
92
81
  return (
93
82
  <div key={tabKey} style={getDisplayStyle(tabKey)}>
94
83
  {activeTab === tabKey && renderComponent(tabKey)}
@@ -2,5 +2,4 @@ import { ReactNode } from 'react';
2
2
 
3
3
  export interface LayoutProps {
4
4
  children?: ReactNode;
5
- showLLM?: boolean;
6
5
  }