@lobehub/lobehub 2.0.0-next.213 → 2.0.0-next.215

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 (87) hide show
  1. package/.github/workflows/e2e.yml +1 -1
  2. package/.github/workflows/pr-build-desktop.yml +2 -2
  3. package/.github/workflows/release-desktop-beta.yml +2 -2
  4. package/.github/workflows/release.yml +1 -1
  5. package/.github/workflows/test.yml +2 -2
  6. package/CHANGELOG.md +51 -0
  7. package/apps/desktop/package.json +3 -2
  8. package/apps/desktop/src/main/const/store.ts +1 -1
  9. package/apps/desktop/src/main/controllers/SystemCtr.ts +2 -3
  10. package/apps/desktop/src/main/core/App.ts +10 -3
  11. package/apps/desktop/src/main/types/store.ts +1 -1
  12. package/changelog/v1.json +14 -0
  13. package/package.json +4 -3
  14. package/packages/builtin-tool-knowledge-base/src/client/Render/SearchKnowledgeBase/Item/index.tsx +4 -2
  15. package/packages/builtin-tool-local-system/src/client/Intervention/EditLocalFile/index.tsx +3 -2
  16. package/packages/builtin-tool-local-system/src/client/Render/EditLocalFile/index.tsx +3 -2
  17. package/packages/const/src/theme.ts +0 -2
  18. package/packages/desktop-bridge/src/routeVariants.ts +2 -9
  19. package/packages/electron-client-ipc/src/types/system.ts +1 -1
  20. package/scripts/electronWorkflow/modifiers/nextConfig.mts +41 -13
  21. package/src/app/[variants]/(auth)/_layout/index.tsx +3 -2
  22. package/src/app/[variants]/(auth)/_layout/style.ts +8 -18
  23. package/src/app/[variants]/(auth)/layout.tsx +7 -3
  24. package/src/app/[variants]/(desktop)/desktop-onboarding/_layout/index.tsx +4 -2
  25. package/src/app/[variants]/(desktop)/desktop-onboarding/_layout/style.ts +3 -0
  26. package/src/app/[variants]/(main)/_layout/DesktopLayoutContainer.tsx +3 -2
  27. package/src/app/[variants]/(main)/chat/profile/features/ProfileEditor/PluginTag.tsx +3 -2
  28. package/src/app/[variants]/(main)/community/(list)/_layout/Footer.tsx +3 -2
  29. package/src/app/[variants]/(main)/group/features/Conversation/ChatItem/Thread.tsx +3 -2
  30. package/src/app/[variants]/(main)/group/profile/features/AgentBuilder/index.tsx +0 -1
  31. package/src/app/[variants]/(main)/group/profile/features/ProfileEditor/PluginTag.tsx +3 -2
  32. package/src/app/[variants]/(main)/home/_layout/Body/Agent/List/AgentItem/Editing.tsx +2 -2
  33. package/src/app/[variants]/(main)/home/_layout/Footer/index.tsx +1 -1
  34. package/src/app/[variants]/(main)/home/_layout/index.tsx +3 -2
  35. package/src/app/[variants]/(main)/home/features/CommunityAgents/Item.tsx +3 -2
  36. package/src/app/[variants]/(main)/image/_layout/ConfigPanel/components/AspectRatioSelect/index.tsx +4 -2
  37. package/src/app/[variants]/(main)/image/_layout/ConfigPanel/components/ModelSelect/ImageModelItem.tsx +3 -2
  38. package/src/app/[variants]/(main)/image/_layout/ConfigPanel/components/Select/index.tsx +4 -2
  39. package/src/app/[variants]/(main)/image/features/PromptInput/index.tsx +3 -2
  40. package/src/app/[variants]/(main)/memory/features/TimeLineView/index.tsx +9 -4
  41. package/src/app/[variants]/(main)/page/_layout/Body/List/Item/Editing.tsx +2 -2
  42. package/src/app/[variants]/(main)/settings/common/features/Common/Common.tsx +11 -11
  43. package/src/app/[variants]/(main)/settings/provider/(list)/ProviderGrid/Card.tsx +3 -2
  44. package/src/app/[variants]/(main)/settings/stats/features/overview/ShareButton/TotalCard.tsx +4 -2
  45. package/src/app/[variants]/(mobile)/me/(home)/features/Header.tsx +6 -8
  46. package/src/app/[variants]/layout.tsx +10 -15
  47. package/src/app/[variants]/onboarding/_layout/index.tsx +3 -2
  48. package/src/app/[variants]/onboarding/features/ModeSelectionStep.tsx +3 -2
  49. package/src/app/[variants]/router/index.tsx +12 -8
  50. package/src/components/Cell/Divider.tsx +4 -2
  51. package/src/components/DataStyleModal/index.tsx +4 -2
  52. package/src/components/FeatureList/index.tsx +4 -2
  53. package/src/components/FileParsingStatus/EmbeddingStatus.tsx +3 -2
  54. package/src/components/FileParsingStatus/index.tsx +3 -2
  55. package/src/components/Notification/index.tsx +4 -2
  56. package/src/components/client/ClientOnly.tsx +17 -0
  57. package/src/features/AlertBanner/CloudBanner.tsx +4 -3
  58. package/src/features/CommandMenu/ThemeMenu.tsx +1 -1
  59. package/src/features/CommandMenu/types.ts +5 -2
  60. package/src/features/CommandMenu/useCommandMenu.ts +3 -2
  61. package/src/features/Conversation/Markdown/plugins/LobeArtifact/Render/index.tsx +3 -2
  62. package/src/features/Conversation/Messages/components/FileChunks/ChunkItem.tsx +3 -2
  63. package/src/features/Conversation/Messages/components/FileChunks/index.tsx +4 -2
  64. package/src/features/Conversation/Messages/components/SearchGrounding.tsx +3 -2
  65. package/src/features/ElectronTitlebar/hooks/useWatchThemeUpdate.ts +21 -38
  66. package/src/features/GroupChatSettings/AgentCard.tsx +3 -2
  67. package/src/features/GroupChatSettings/HostMemberCard.tsx +3 -2
  68. package/src/features/PageEditor/DiffAllToolbar.tsx +4 -2
  69. package/src/features/Portal/Document/Header.tsx +11 -9
  70. package/src/features/User/UserPanel/ThemeButton.tsx +18 -29
  71. package/src/hooks/useIsDark.ts +11 -0
  72. package/src/layout/AuthProvider/Clerk/useAppearance.ts +4 -2
  73. package/src/layout/AuthProvider/MarketAuth/MarketAuthConfirmModal.tsx +3 -2
  74. package/src/layout/GlobalProvider/AppTheme.tsx +15 -19
  75. package/src/layout/GlobalProvider/NextThemeProvider.tsx +22 -0
  76. package/src/layout/GlobalProvider/StyleRegistry.tsx +18 -13
  77. package/src/layout/GlobalProvider/index.tsx +38 -36
  78. package/src/libs/next/proxy/define-config.ts +2 -11
  79. package/src/store/global/action.test.ts +0 -15
  80. package/src/store/global/actions/__tests__/general.test.ts +0 -37
  81. package/src/store/global/actions/general.ts +0 -21
  82. package/src/store/global/initialState.ts +0 -6
  83. package/src/store/global/selectors/systemStatus.test.ts +0 -20
  84. package/src/store/global/selectors/systemStatus.ts +0 -2
  85. package/src/styles/global.ts +0 -2
  86. package/src/utils/server/routeVariants.test.ts +17 -51
  87. package/src/utils/server/routeVariants.ts +0 -1
@@ -46,7 +46,7 @@ jobs:
46
46
  - name: Setup Bun
47
47
  uses: oven-sh/setup-bun@v2
48
48
  with:
49
- bun-version: 1.2.23
49
+ bun-version: latest
50
50
 
51
51
  - name: Install dependencies (bun)
52
52
  run: bun install
@@ -33,7 +33,7 @@ jobs:
33
33
  uses: ./.github/actions/setup-node-bun
34
34
  with:
35
35
  node-version: 24.11.1
36
- bun-version: 1.2.23
36
+ bun-version: latest
37
37
  package-manager-cache: 'false'
38
38
 
39
39
  - name: Install deps
@@ -224,7 +224,7 @@ jobs:
224
224
  uses: ./.github/actions/setup-node-bun
225
225
  with:
226
226
  node-version: 24.11.1
227
- bun-version: 1.2.23
227
+ bun-version: latest
228
228
  package-manager-cache: 'false'
229
229
 
230
230
  # 下载所有平台的构建产物
@@ -32,7 +32,7 @@ jobs:
32
32
  - name: Install bun
33
33
  uses: oven-sh/setup-bun@v2
34
34
  with:
35
- bun-version: 1.2.23
35
+ bun-version: latest
36
36
 
37
37
  - name: Install deps
38
38
  run: bun i
@@ -216,7 +216,7 @@ jobs:
216
216
  - name: Install bun
217
217
  uses: oven-sh/setup-bun@v2
218
218
  with:
219
- bun-version: 1.2.23
219
+ bun-version: latest
220
220
 
221
221
  # 下载所有平台的构建产物
222
222
  - name: Download artifacts
@@ -41,7 +41,7 @@ jobs:
41
41
  - name: Install bun
42
42
  uses: oven-sh/setup-bun@v2
43
43
  with:
44
- bun-version: 1.2.23
44
+ bun-version: latest
45
45
 
46
46
  - name: Install deps
47
47
  run: bun i
@@ -72,7 +72,7 @@ jobs:
72
72
  - name: Install bun
73
73
  uses: oven-sh/setup-bun@v2
74
74
  with:
75
- bun-version: 1.2.23
75
+ bun-version: latest
76
76
 
77
77
  - name: Install deps
78
78
  run: bun i
@@ -105,7 +105,7 @@ jobs:
105
105
  - name: Install bun
106
106
  uses: oven-sh/setup-bun@v2
107
107
  with:
108
- bun-version: 1.2.23
108
+ bun-version: latest
109
109
 
110
110
  - name: Install deps
111
111
  run: bun i
package/CHANGELOG.md CHANGED
@@ -2,6 +2,57 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ## [Version 2.0.0-next.215](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.214...v2.0.0-next.215)
6
+
7
+ <sup>Released on **2026-01-05**</sup>
8
+
9
+ #### 🐛 Bug Fixes
10
+
11
+ - **misc**: Update CI bun version to v1.2.4, when the document filetype is agent/plan, not show the saveinto docs button.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### What's fixed
19
+
20
+ - **misc**: Update CI bun version to v1.2.4, closes [#11232](https://github.com/lobehub/lobe-chat/issues/11232) ([dd022d5](https://github.com/lobehub/lobe-chat/commit/dd022d5))
21
+ - **misc**: When the document filetype is agent/plan, not show the saveinto docs button, closes [#11227](https://github.com/lobehub/lobe-chat/issues/11227) ([3a22f32](https://github.com/lobehub/lobe-chat/commit/3a22f32))
22
+
23
+ </details>
24
+
25
+ <div align="right">
26
+
27
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
28
+
29
+ </div>
30
+
31
+ ## [Version 2.0.0-next.214](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.213...v2.0.0-next.214)
32
+
33
+ <sup>Released on **2026-01-05**</sup>
34
+
35
+ #### 🐛 Bug Fixes
36
+
37
+ - **electron**: Correct next config codemod pattern matching.
38
+
39
+ <br/>
40
+
41
+ <details>
42
+ <summary><kbd>Improvements and Fixes</kbd></summary>
43
+
44
+ #### What's fixed
45
+
46
+ - **electron**: Correct next config codemod pattern matching, closes [#11228](https://github.com/lobehub/lobe-chat/issues/11228) ([06cb019](https://github.com/lobehub/lobe-chat/commit/06cb019))
47
+
48
+ </details>
49
+
50
+ <div align="right">
51
+
52
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
53
+
54
+ </div>
55
+
5
56
  ## [Version 2.0.0-next.213](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.212...v2.0.0-next.213)
6
57
 
7
58
  <sup>Released on **2026-01-05**</sup>
@@ -18,6 +18,7 @@
18
18
  "build:mac:local": "npm run build && UPDATE_CHANNEL=nightly electron-builder --mac --config electron-builder.js --publish never",
19
19
  "build:win": "npm run build && electron-builder --win --config electron-builder.js --publish never",
20
20
  "dev": "electron-vite dev",
21
+ "dev:static": "cross-env DESKTOP_RENDERER_STATIC=1 npm run electron:dev",
21
22
  "electron:dev": "electron-vite dev",
22
23
  "electron:run-unpack": "electron .",
23
24
  "format": "prettier --write ",
@@ -57,11 +58,11 @@
57
58
  "@lobechat/file-loaders": "workspace:*",
58
59
  "@lobehub/i18n-cli": "^1.25.1",
59
60
  "@modelcontextprotocol/sdk": "^1.24.3",
61
+ "@t3-oss/env-core": "^0.13.8",
60
62
  "@types/async-retry": "^1.4.9",
61
63
  "@types/resolve": "^1.20.6",
62
64
  "@types/semver": "^7.7.1",
63
65
  "@types/set-cookie-parser": "^2.4.10",
64
- "@t3-oss/env-core": "^0.13.8",
65
66
  "@typescript/native-preview": "7.0.0-dev.20251210.1",
66
67
  "async-retry": "^1.3.3",
67
68
  "consola": "^3.4.2",
@@ -104,4 +105,4 @@
104
105
  "electron-builder"
105
106
  ]
106
107
  }
107
- }
108
+ }
@@ -31,5 +31,5 @@ export const STORE_DEFAULTS: ElectronMainStore = {
31
31
  networkProxy: defaultProxySettings,
32
32
  shortcuts: DEFAULT_SHORTCUTS_CONFIG,
33
33
  storagePath: appStorageDir,
34
- themeMode: 'auto',
34
+ themeMode: 'system',
35
35
  };
@@ -258,9 +258,8 @@ export default class SystemController extends ControllerModule {
258
258
  return nativeTheme.themeSource;
259
259
  }
260
260
 
261
- @IpcMethod()
262
- async setSystemThemeMode(themeMode: ThemeMode) {
263
- nativeTheme.themeSource = themeMode === 'auto' ? 'system' : themeMode;
261
+ private async setSystemThemeMode(themeMode: ThemeMode) {
262
+ nativeTheme.themeSource = themeMode;
264
263
  }
265
264
 
266
265
  /**
@@ -142,10 +142,17 @@ export class App {
142
142
  * This allows nativeTheme.shouldUseDarkColors to be used consistently everywhere
143
143
  */
144
144
  private initializeThemeMode() {
145
- const themeMode = this.storeManager.get('themeMode');
145
+ let themeMode = this.storeManager.get('themeMode');
146
+
147
+ // Migrate legacy 'auto' value to 'system' (nativeTheme.themeSource doesn't accept 'auto')
148
+ if (Object.is(themeMode, 'auto')) {
149
+ themeMode = 'system';
150
+ this.storeManager.set('themeMode', themeMode);
151
+ logger.info(`Migrated legacy theme mode 'auto' to 'system'`);
152
+ }
146
153
 
147
154
  if (themeMode) {
148
- nativeTheme.themeSource = themeMode === 'auto' ? 'system' : themeMode;
155
+ nativeTheme.themeSource = themeMode;
149
156
  logger.debug(
150
157
  `Theme mode initialized to: ${themeMode} (themeSource: ${nativeTheme.themeSource})`,
151
158
  );
@@ -401,4 +408,4 @@ export class App {
401
408
  // 执行清理操作
402
409
  this.staticFileServerManager.destroy();
403
410
  };
404
- }
411
+ }
@@ -11,7 +11,7 @@ export interface ElectronMainStore {
11
11
  networkProxy: NetworkProxySettings;
12
12
  shortcuts: Record<string, string>;
13
13
  storagePath: string;
14
- themeMode: 'dark' | 'light' | 'auto';
14
+ themeMode: 'dark' | 'light' | 'system';
15
15
  }
16
16
 
17
17
  export type StoreKey = keyof ElectronMainStore;
package/changelog/v1.json CHANGED
@@ -1,4 +1,18 @@
1
1
  [
2
+ {
3
+ "children": {
4
+ "fixes": [
5
+ "Update CI bun version to v1.2.4, when the document filetype is agent/plan, not show the saveinto docs button."
6
+ ]
7
+ },
8
+ "date": "2026-01-05",
9
+ "version": "2.0.0-next.215"
10
+ },
11
+ {
12
+ "children": {},
13
+ "date": "2026-01-05",
14
+ "version": "2.0.0-next.214"
15
+ },
2
16
  {
3
17
  "children": {
4
18
  "improvements": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/lobehub",
3
- "version": "2.0.0-next.213",
3
+ "version": "2.0.0-next.215",
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",
@@ -205,7 +205,7 @@
205
205
  "@lobehub/icons": "^4.0.2",
206
206
  "@lobehub/market-sdk": "^0.25.1",
207
207
  "@lobehub/tts": "^4.0.2",
208
- "@lobehub/ui": "^4.8.0",
208
+ "@lobehub/ui": "^4.9.0",
209
209
  "@modelcontextprotocol/sdk": "^1.25.1",
210
210
  "@neondatabase/serverless": "^1.0.2",
211
211
  "@next/third-parties": "^16.1.1",
@@ -234,7 +234,7 @@
234
234
  "@zumer/snapdom": "^1.9.14",
235
235
  "ahooks": "^3.9.6",
236
236
  "antd": "^6.1.1",
237
- "antd-style": "^4.1.0",
237
+ "antd-style": "4.1.0",
238
238
  "async-retry": "^1.3.3",
239
239
  "bcryptjs": "^3.0.3",
240
240
  "better-auth": "1.4.6",
@@ -281,6 +281,7 @@
281
281
  "next": "^16.1.1",
282
282
  "next-auth": "5.0.0-beta.30",
283
283
  "next-mdx-remote": "^5.0.0",
284
+ "next-themes": "^0.4.6",
284
285
  "nextjs-toploader": "^3.9.17",
285
286
  "node-machine-id": "^1.1.12",
286
287
  "nodemailer": "^7.0.11",
@@ -2,7 +2,8 @@
2
2
 
3
3
  import { FileSearchResult } from '@lobechat/types';
4
4
  import { Center, Flexbox, MaterialFileTypeIcon, Text, Tooltip } from '@lobehub/ui';
5
- import { cx, useThemeMode } from 'antd-style';
5
+ import { cx } from 'antd-style';
6
+ import { useTheme } from 'next-themes';
6
7
  import { memo } from 'react';
7
8
 
8
9
  import { styles } from './style';
@@ -12,7 +13,8 @@ export interface FileItemProps extends FileSearchResult {
12
13
  }
13
14
 
14
15
  const FileItem = memo<FileItemProps>(({ fileId, fileName, relevanceScore }) => {
15
- const { isDarkMode } = useThemeMode();
16
+ const { resolvedTheme } = useTheme();
17
+ const isDarkMode = resolvedTheme === 'dark';
16
18
 
17
19
  return (
18
20
  <Flexbox
@@ -1,9 +1,9 @@
1
1
  import { type EditLocalFileParams } from '@lobechat/electron-client-ipc';
2
2
  import { type BuiltinInterventionProps } from '@lobechat/types';
3
3
  import { Flexbox, Icon, Skeleton, Text } from '@lobehub/ui';
4
- import { useThemeMode } from 'antd-style';
5
4
  import { createPatch } from 'diff';
6
5
  import { ChevronRight } from 'lucide-react';
6
+ import { useTheme } from 'next-themes';
7
7
  import path from 'path-browserify-esm';
8
8
  import React, { memo, useMemo } from 'react';
9
9
  import { Diff, Hunk, parseDiff } from 'react-diff-view';
@@ -29,7 +29,8 @@ const EditLocalFile = memo<BuiltinInterventionProps<EditLocalFileParams>>(({ arg
29
29
  },
30
30
  );
31
31
 
32
- const { isDarkMode } = useThemeMode();
32
+ const { resolvedTheme } = useTheme();
33
+ const isDarkMode = resolvedTheme === 'dark';
33
34
  // Generate diff from full file content
34
35
  const files = useMemo(() => {
35
36
  if (!fileData?.content) return [];
@@ -2,8 +2,8 @@ import { type EditLocalFileState } from '@lobechat/builtin-tool-local-system';
2
2
  import { type EditLocalFileParams } from '@lobechat/electron-client-ipc';
3
3
  import { type BuiltinRenderProps } from '@lobechat/types';
4
4
  import { Alert, Flexbox, Icon, Skeleton } from '@lobehub/ui';
5
- import { useThemeMode } from 'antd-style';
6
5
  import { ChevronRight } from 'lucide-react';
6
+ import { useTheme } from 'next-themes';
7
7
  import path from 'path-browserify-esm';
8
8
  import React, { memo, useMemo } from 'react';
9
9
  import { Diff, Hunk, parseDiff } from 'react-diff-view';
@@ -28,7 +28,8 @@ const EditLocalFile = memo<BuiltinRenderProps<EditLocalFileParams, EditLocalFile
28
28
  return [];
29
29
  }
30
30
  }, [pluginState?.diffText]);
31
- const { isDarkMode } = useThemeMode();
31
+ const { resolvedTheme } = useTheme();
32
+ const isDarkMode = resolvedTheme === 'dark';
32
33
 
33
34
  if (!args) return <Skeleton active />;
34
35
 
@@ -1,5 +1,3 @@
1
- export const LOBE_THEME_APPEARANCE = 'LOBE_THEME_APPEARANCE';
2
-
3
1
  export const LOBE_THEME_PRIMARY_COLOR = 'LOBE_THEME_PRIMARY_COLOR';
4
2
 
5
3
  export const LOBE_THEME_NEUTRAL_COLOR = 'LOBE_THEME_NEUTRAL_COLOR';
@@ -31,31 +31,26 @@ export interface IRouteVariants {
31
31
  locale: Locales;
32
32
  neutralColor?: string;
33
33
  primaryColor?: string;
34
- theme: 'dark' | 'light';
35
34
  }
36
35
 
37
- const SUPPORTED_THEMES = ['dark', 'light'] as const;
38
-
39
36
  export const DEFAULT_VARIANTS: IRouteVariants = {
40
37
  isMobile: false,
41
38
  locale: DEFAULT_LANG,
42
- theme: 'light',
43
39
  };
44
40
 
45
41
  const SPLITTER = '__';
46
42
 
47
43
  export class RouteVariants {
48
44
  static serializeVariants = (variants: IRouteVariants): string =>
49
- [variants.locale, Number(variants.isMobile), variants.theme].join(SPLITTER);
45
+ [variants.locale, Number(variants.isMobile)].join(SPLITTER);
50
46
 
51
47
  static deserializeVariants = (serialized: string): IRouteVariants => {
52
48
  try {
53
- const [locale, isMobile, theme] = serialized.split(SPLITTER);
49
+ const [locale, isMobile] = serialized.split(SPLITTER);
54
50
 
55
51
  return {
56
52
  isMobile: isMobile === '1',
57
53
  locale: RouteVariants.isValidLocale(locale) ? (locale as Locales) : DEFAULT_VARIANTS.locale,
58
- theme: RouteVariants.isValidTheme(theme) ? (theme as any) : DEFAULT_VARIANTS.theme,
59
54
  };
60
55
  } catch {
61
56
  return { ...DEFAULT_VARIANTS };
@@ -68,6 +63,4 @@ export class RouteVariants {
68
63
  });
69
64
 
70
65
  private static isValidLocale = (locale: string): boolean => locales.includes(locale as any);
71
-
72
- private static isValidTheme = (theme: string): boolean => SUPPORTED_THEMES.includes(theme as any);
73
66
  }
@@ -25,5 +25,5 @@ export interface UserPathData {
25
25
  videos?: string; // User's home directory
26
26
  }
27
27
 
28
- export type ThemeMode = 'auto' | 'dark' | 'light';
28
+ export type ThemeMode = 'system' | 'dark' | 'light';
29
29
  export type ThemeAppearance = 'dark' | 'light' | string;
@@ -40,13 +40,19 @@ export const modifyNextConfig = async (TEMP_DIR: string) => {
40
40
  }
41
41
 
42
42
  // 1. Remove redirects
43
- const redirectsPair = nextConfigDecl.find({
44
- rule: {
45
- pattern: 'redirects: $A',
46
- },
47
- });
48
- if (redirectsPair) {
49
- const range = redirectsPair.range();
43
+ const redirectsPair = nextConfigDecl
44
+ .findAll({
45
+ rule: {
46
+ kind: 'pair',
47
+ },
48
+ })
49
+ .find((node) => {
50
+ const text = node.text();
51
+ return text.startsWith('redirects:') || text.startsWith('redirects :');
52
+ });
53
+ invariant(redirectsPair, '[modifyNextConfig] redirects pair not found');
54
+ {
55
+ const range = redirectsPair!.range();
50
56
  edits.push({ end: range.end.index, start: range.start.index, text: '' });
51
57
  }
52
58
 
@@ -61,18 +67,39 @@ export const modifyNextConfig = async (TEMP_DIR: string) => {
61
67
  const text = node.text();
62
68
  return text.startsWith('async headers') || text.startsWith('headers');
63
69
  });
64
- if (headersMethod) {
65
- const range = headersMethod.range();
70
+ invariant(headersMethod, '[modifyNextConfig] headers method not found');
71
+ {
72
+ const range = headersMethod!.range();
73
+ edits.push({ end: range.end.index, start: range.start.index, text: '' });
74
+ }
75
+
76
+ // 3. Remove webVitalsAttribution
77
+ const webVitalsPair = nextConfigDecl
78
+ .findAll({
79
+ rule: {
80
+ kind: 'pair',
81
+ },
82
+ })
83
+ .find((node) => {
84
+ const text = node.text();
85
+ return (
86
+ text.startsWith('webVitalsAttribution:') || text.startsWith('webVitalsAttribution :')
87
+ );
88
+ });
89
+ invariant(webVitalsPair, '[modifyNextConfig] webVitalsAttribution pair not found');
90
+ {
91
+ const range = webVitalsPair!.range();
66
92
  edits.push({ end: range.end.index, start: range.start.index, text: '' });
67
93
  }
68
94
 
69
- // 3. Remove spread element
95
+ // 4. Remove spread element
70
96
  const spreads = nextConfigDecl.findAll({
71
97
  rule: {
72
98
  kind: 'spread_element',
73
99
  },
74
100
  });
75
101
 
102
+ // eslint-disable-next-line unicorn/consistent-function-scoping
76
103
  const isObjectLevelSpread = (node: any) => node.parent()?.kind() === 'object';
77
104
 
78
105
  const standaloneSpread = spreads.find((node) => {
@@ -84,12 +111,13 @@ export const modifyNextConfig = async (TEMP_DIR: string) => {
84
111
  const objectLevelSpread = standaloneSpread ? null : spreads.find(isObjectLevelSpread);
85
112
 
86
113
  const spreadToRemove = standaloneSpread || objectLevelSpread;
87
- if (spreadToRemove) {
88
- const range = spreadToRemove.range();
114
+ invariant(spreadToRemove, '[modifyNextConfig] spread element not found');
115
+ {
116
+ const range = spreadToRemove!.range();
89
117
  edits.push({ end: range.end.index, start: range.start.index, text: '' });
90
118
  }
91
119
 
92
- // 4. Inject/force output: 'export'
120
+ // 5. Inject/force output: 'export'
93
121
  const outputPair = nextConfigDecl.find({
94
122
  rule: {
95
123
  pattern: 'output: $A',
@@ -2,17 +2,18 @@
2
2
 
3
3
  import { Center, Flexbox, Text } from '@lobehub/ui';
4
4
  import { Divider } from 'antd';
5
- import { cx, useThemeMode } from 'antd-style';
5
+ import { cx } from 'antd-style';
6
6
  import type { FC, PropsWithChildren } from 'react';
7
7
 
8
8
  import { ProductLogo } from '@/components/Branding';
9
9
  import LangButton from '@/features/User/UserPanel/LangButton';
10
10
  import ThemeButton from '@/features/User/UserPanel/ThemeButton';
11
+ import { useIsDark } from '@/hooks/useIsDark';
11
12
 
12
13
  import { styles } from './style';
13
14
 
14
15
  const AuthContainer: FC<PropsWithChildren> = ({ children }) => {
15
- const { isDarkMode } = useThemeMode();
16
+ const isDarkMode = useIsDark();
16
17
  return (
17
18
  <Flexbox className={styles.outerContainer} height={'100%'} padding={8} width={'100%'}>
18
19
  <Flexbox
@@ -1,18 +1,13 @@
1
1
  import { createStaticStyles } from 'antd-style';
2
2
 
3
3
  export const styles = createStaticStyles(({ css, cssVar }) => ({
4
-
5
-
6
- // Divider 样式
7
- divider: css`
4
+ // Divider 样式
5
+ divider: css`
8
6
  height: 24px;
9
7
  `,
10
8
 
11
-
12
-
13
-
14
- // 内层容器 - 深色模式
15
- innerContainerDark: css`
9
+ // 内层容器 - 深色模式
10
+ innerContainerDark: css`
16
11
  position: relative;
17
12
 
18
13
  overflow: hidden;
@@ -23,11 +18,8 @@ innerContainerDark: css`
23
18
  background: ${cssVar.colorBgContainer};
24
19
  `,
25
20
 
26
-
27
-
28
-
29
- // 内层容器 - 浅色模式
30
- innerContainerLight: css`
21
+ // 内层容器 - 浅色模式
22
+ innerContainerLight: css`
31
23
  position: relative;
32
24
 
33
25
  overflow: hidden;
@@ -38,10 +30,8 @@ innerContainerLight: css`
38
30
  background: ${cssVar.colorBgContainer};
39
31
  `,
40
32
 
41
-
42
-
43
- // 外层容器
44
- outerContainer: css`
33
+ // 外层容器
34
+ outerContainer: css`
45
35
  position: relative;
46
36
  `,
47
37
  }));
@@ -1,13 +1,17 @@
1
1
  import { NuqsAdapter } from 'nuqs/adapters/next/app';
2
2
  import { type FC, type PropsWithChildren } from 'react';
3
3
 
4
+ import ClientOnly from '@/components/client/ClientOnly';
5
+
4
6
  import AuthContainer from './_layout';
5
7
 
6
8
  const AuthLayout: FC<PropsWithChildren> = ({ children }) => {
7
9
  return (
8
- <NuqsAdapter>
9
- <AuthContainer>{children}</AuthContainer>
10
- </NuqsAdapter>
10
+ <ClientOnly>
11
+ <NuqsAdapter>
12
+ <AuthContainer>{children}</AuthContainer>
13
+ </NuqsAdapter>
14
+ </ClientOnly>
11
15
  );
12
16
  };
13
17
 
@@ -2,16 +2,17 @@
2
2
 
3
3
  import { Center, Flexbox, Text } from '@lobehub/ui';
4
4
  import { Divider } from 'antd';
5
- import { cx, useThemeMode } from 'antd-style';
5
+ import { cx } from 'antd-style';
6
6
  import type { FC, PropsWithChildren } from 'react';
7
7
 
8
8
  import LangButton from '@/features/User/UserPanel/LangButton';
9
9
  import ThemeButton from '@/features/User/UserPanel/ThemeButton';
10
+ import { useIsDark } from '@/hooks/useIsDark';
10
11
 
11
12
  import { styles } from './style';
12
13
 
13
14
  const OnboardingContainer: FC<PropsWithChildren> = ({ children }) => {
14
- const { isDarkMode } = useThemeMode();
15
+ const isDarkMode = useIsDark();
15
16
  return (
16
17
  <Flexbox className={styles.outerContainer} height={'100%'} padding={8} width={'100%'}>
17
18
  <Flexbox
@@ -21,6 +22,7 @@ const OnboardingContainer: FC<PropsWithChildren> = ({ children }) => {
21
22
  >
22
23
  <Flexbox
23
24
  align={'center'}
25
+ className={cx(styles.drag)}
24
26
  gap={8}
25
27
  horizontal
26
28
  justify={'space-between'}
@@ -6,6 +6,9 @@ export const styles = createStaticStyles(({ css, cssVar }) => ({
6
6
  height: 24px;
7
7
  `,
8
8
 
9
+ drag: css`
10
+ -webkit-app-region: drag;
11
+ `,
9
12
  // 内层容器 - 深色模式
10
13
  innerContainerDark: css`
11
14
  position: relative;
@@ -1,15 +1,16 @@
1
1
  import { Flexbox } from '@lobehub/ui';
2
- import { cssVar, useThemeMode } from 'antd-style';
2
+ import { cssVar } from 'antd-style';
3
3
  import { type FC, type PropsWithChildren, useMemo } from 'react';
4
4
 
5
5
  import { isDesktop } from '@/const/version';
6
+ import { useIsDark } from '@/hooks/useIsDark';
6
7
  import { useGlobalStore } from '@/store/global';
7
8
  import { systemStatusSelectors } from '@/store/global/selectors';
8
9
 
9
10
  import { styles } from './DesktopLayoutContainer/style';
10
11
 
11
12
  const DesktopLayoutContainer: FC<PropsWithChildren> = ({ children }) => {
12
- const { isDarkMode } = useThemeMode();
13
+ const isDarkMode = useIsDark();
13
14
  const [expand] = useGlobalStore((s) => [systemStatusSelectors.showLeftPanel(s)]);
14
15
 
15
16
  // CSS 变量用于动态样式
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { KLAVIS_SERVER_TYPES, type KlavisServerType } from '@lobechat/const';
4
4
  import { Avatar, Icon, Tag } from '@lobehub/ui';
5
- import { createStaticStyles, cssVar, useThemeMode } from 'antd-style';
5
+ import { createStaticStyles, cssVar } from 'antd-style';
6
6
  import isEqual from 'fast-deep-equal';
7
7
  import { AlertCircle, X } from 'lucide-react';
8
8
  import Image from 'next/image';
@@ -10,6 +10,7 @@ import React, { memo, useMemo } from 'react';
10
10
  import { useTranslation } from 'react-i18next';
11
11
 
12
12
  import PluginAvatar from '@/components/Plugins/PluginAvatar';
13
+ import { useIsDark } from '@/hooks/useIsDark';
13
14
  import { useDiscoverStore } from '@/store/discover';
14
15
  import { serverConfigSelectors, useServerConfigStore } from '@/store/serverConfig';
15
16
  import { useToolStore } from '@/store/tool';
@@ -53,7 +54,7 @@ interface PluginTagProps {
53
54
  }
54
55
 
55
56
  const PluginTag = memo<PluginTagProps>(({ pluginId, onRemove }) => {
56
- const { isDarkMode } = useThemeMode();
57
+ const isDarkMode = useIsDark();
57
58
  const { t } = useTranslation('setting');
58
59
 
59
60
  // Extract identifier