@lobehub/chat 1.97.3 → 1.97.4

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/CHANGELOG.md CHANGED
@@ -2,6 +2,32 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 1.97.4](https://github.com/lobehub/lobe-chat/compare/v1.97.3...v1.97.4)
6
+
7
+ <sup>Released on **2025-07-10**</sup>
8
+
9
+ #### 💄 Styles
10
+
11
+ - **misc**: Add `grok-4-0709` model from xAI, fix theme issue in desktop.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### Styles
19
+
20
+ - **misc**: Add `grok-4-0709` model from xAI, closes [#8379](https://github.com/lobehub/lobe-chat/issues/8379) ([b7ca447](https://github.com/lobehub/lobe-chat/commit/b7ca447))
21
+ - **misc**: Fix theme issue in desktop, closes [#8380](https://github.com/lobehub/lobe-chat/issues/8380) ([c7ae78b](https://github.com/lobehub/lobe-chat/commit/c7ae78b))
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
+
5
31
  ### [Version 1.97.3](https://github.com/lobehub/lobe-chat/compare/v1.97.2...v1.97.3)
6
32
 
7
33
  <sup>Released on **2025-07-10**</sup>
@@ -1,15 +1,27 @@
1
1
  import { ElectronAppState, ThemeMode } from '@lobechat/electron-client-ipc';
2
- import { app, shell, systemPreferences } from 'electron';
2
+ import { app, nativeTheme, shell, systemPreferences } from 'electron';
3
3
  import { macOS } from 'electron-is';
4
4
  import { readFileSync, writeFileSync } from 'node:fs';
5
5
  import { join } from 'node:path';
6
6
  import process from 'node:process';
7
7
 
8
8
  import { DB_SCHEMA_HASH_FILENAME, LOCAL_DATABASE_DIR, userDataDir } from '@/const/dir';
9
+ import { createLogger } from '@/utils/logger';
9
10
 
10
11
  import { ControllerModule, ipcClientEvent, ipcServerEvent } from './index';
11
12
 
13
+ const logger = createLogger('controllers:SystemCtr');
14
+
12
15
  export default class SystemController extends ControllerModule {
16
+ private systemThemeListenerInitialized = false;
17
+
18
+ /**
19
+ * Initialize system theme listener when app is ready
20
+ */
21
+ afterAppReady() {
22
+ this.initializeSystemThemeListener();
23
+ }
24
+
13
25
  /**
14
26
  * Handles the 'getDesktopAppState' IPC request.
15
27
  * Gathers essential application and system information.
@@ -26,6 +38,7 @@ export default class SystemController extends ControllerModule {
26
38
  isMac: platform === 'darwin',
27
39
  isWindows: platform === 'win32',
28
40
  platform: platform as 'darwin' | 'win32' | 'linux',
41
+ systemAppearance: nativeTheme.shouldUseDarkColors ? 'dark' : 'light',
29
42
  userPath: {
30
43
  // User Paths (ensure keys match UserPathData / DesktopAppState interface)
31
44
  desktop: app.getPath('desktop'),
@@ -100,4 +113,37 @@ export default class SystemController extends ControllerModule {
100
113
  private get DB_SCHEMA_HASH_PATH() {
101
114
  return join(this.app.appStoragePath, DB_SCHEMA_HASH_FILENAME);
102
115
  }
116
+
117
+ /**
118
+ * Initialize system theme listener to monitor OS theme changes
119
+ */
120
+ private initializeSystemThemeListener() {
121
+ if (this.systemThemeListenerInitialized) {
122
+ logger.debug('System theme listener already initialized');
123
+ return;
124
+ }
125
+
126
+ logger.info('Initializing system theme listener');
127
+
128
+ // Get initial system theme
129
+ const initialDarkMode = nativeTheme.shouldUseDarkColors;
130
+ const initialSystemTheme: ThemeMode = initialDarkMode ? 'dark' : 'light';
131
+ logger.info(`Initial system theme: ${initialSystemTheme}`);
132
+
133
+ // Listen for system theme changes
134
+ nativeTheme.on('updated', () => {
135
+ const isDarkMode = nativeTheme.shouldUseDarkColors;
136
+ const systemTheme: ThemeMode = isDarkMode ? 'dark' : 'light';
137
+
138
+ logger.info(`System theme changed to: ${systemTheme}`);
139
+
140
+ // Broadcast system theme change to all renderer processes
141
+ this.app.browserManager.broadcastToAllWindows('systemThemeChanged', {
142
+ themeMode: systemTheme,
143
+ });
144
+ });
145
+
146
+ this.systemThemeListenerInitialized = true;
147
+ logger.info('System theme listener initialized successfully');
148
+ }
103
149
  }
package/changelog/v1.json CHANGED
@@ -1,4 +1,13 @@
1
1
  [
2
+ {
3
+ "children": {
4
+ "improvements": [
5
+ "Add grok-4-0709 model from xAI, fix theme issue in desktop."
6
+ ]
7
+ },
8
+ "date": "2025-07-10",
9
+ "version": "1.97.4"
10
+ },
2
11
  {
3
12
  "children": {},
4
13
  "date": "2025-07-10",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "1.97.3",
3
+ "version": "1.97.4",
4
4
  "description": "Lobe Chat - an open-source, high-performance chatbot 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",
@@ -1,3 +1,5 @@
1
+ import { ThemeAppearance } from 'antd-style';
2
+
1
3
  import { ElectronAppState, ThemeMode } from '../types';
2
4
 
3
5
  export interface SystemDispatchEvents {
@@ -16,5 +18,6 @@ export interface SystemDispatchEvents {
16
18
  }
17
19
 
18
20
  export interface SystemBroadcastEvents {
21
+ systemThemeChanged: (data: { themeMode: ThemeAppearance }) => void;
19
22
  themeChanged: (data: { themeMode: ThemeMode }) => void;
20
23
  }
@@ -3,7 +3,8 @@ export interface ElectronAppState {
3
3
  isLinux?: boolean;
4
4
  isMac?: boolean;
5
5
  isWindows?: boolean;
6
- platform?: 'darwin' | 'win32' | 'linux'; // , etc.
6
+ platform?: 'darwin' | 'win32' | 'linux';
7
+ systemAppearance?: string;
7
8
  userPath?: UserPathData;
8
9
  }
9
10
 
@@ -2,6 +2,31 @@ import { AIChatModelCard } from '@/types/aiModel';
2
2
 
3
3
  // https://docs.x.ai/docs/models
4
4
  const xaiChatModels: AIChatModelCard[] = [
5
+ {
6
+ abilities: {
7
+ functionCall: true,
8
+ reasoning: true,
9
+ search: true,
10
+ },
11
+ contextWindowTokens: 256_000,
12
+ description:
13
+ '我们最新最强大的旗舰模型,在自然语言处理、数学计算和推理方面表现卓越 —— 是一款完美的全能型选手。',
14
+ displayName: 'Grok 4 0709',
15
+ enabled: true,
16
+ id: 'grok-4-0709',
17
+ pricing: {
18
+ cachedInput: 0.75,
19
+ input: 3,
20
+ output: 15,
21
+ },
22
+ releasedAt: '2025-07-09',
23
+ settings: {
24
+ // reasoning_effort is not supported by grok-4. Specifying reasoning_effort parameter will get an error response.
25
+ // extendParams: ['reasoningEffort'],
26
+ searchImpl: 'params',
27
+ },
28
+ type: 'chat',
29
+ },
5
30
  {
6
31
  abilities: {
7
32
  functionCall: true,
@@ -11,7 +36,6 @@ const xaiChatModels: AIChatModelCard[] = [
11
36
  description:
12
37
  '旗舰级模型,擅长数据提取、编程和文本摘要等企业级应用,拥有金融、医疗、法律和科学等领域的深厚知识。',
13
38
  displayName: 'Grok 3',
14
- enabled: true,
15
39
  id: 'grok-3',
16
40
  pricing: {
17
41
  cachedInput: 0.75,
@@ -3,19 +3,32 @@ import { useTheme } from 'antd-style';
3
3
  import { rgba } from 'polished';
4
4
  import { useEffect } from 'react';
5
5
 
6
+ import { useElectronStore } from '@/store/electron';
6
7
  import { useGlobalStore } from '@/store/global';
7
8
 
8
9
  export const useWatchThemeUpdate = () => {
10
+ const [systemAppearance, updateElectronAppState] = useElectronStore((s) => [
11
+ s.appState.systemAppearance,
12
+ s.updateElectronAppState,
13
+ ]);
9
14
  const switchThemeMode = useGlobalStore((s) => s.switchThemeMode);
10
15
 
11
- const token = useTheme();
16
+ const theme = useTheme();
12
17
 
13
18
  useWatchBroadcast('themeChanged', ({ themeMode }) => {
14
19
  switchThemeMode(themeMode, { skipBroadcast: true });
15
20
  });
16
21
 
22
+ useWatchBroadcast('systemThemeChanged', ({ themeMode }) => {
23
+ updateElectronAppState({ systemAppearance: themeMode });
24
+ });
25
+
17
26
  useEffect(() => {
18
27
  document.documentElement.style.background = 'none';
19
- document.body.style.background = rgba(token.colorBgLayout, 0.66);
20
- }, [token]);
28
+
29
+ // https://x.com/alanblogsooo/status/1939208908993896684
30
+ const isNotSameTheme = !systemAppearance ? true : theme.appearance !== systemAppearance;
31
+
32
+ document.body.style.background = rgba(theme.colorBgLayout, isNotSameTheme ? 0.95 : 0.66);
33
+ }, [theme, systemAppearance]);
21
34
  };
@@ -7,6 +7,11 @@ export interface XAIModelCard {
7
7
  id: string;
8
8
  }
9
9
 
10
+ export const GrokReasoningModels = new Set([
11
+ 'grok-3-mini',
12
+ 'grok-4-0709',
13
+ ]);
14
+
10
15
  export const LobeXAI = createOpenAICompatibleRuntime({
11
16
  baseURL: 'https://api.x.ai/v1',
12
17
  chatCompletion: {
@@ -15,9 +20,9 @@ export const LobeXAI = createOpenAICompatibleRuntime({
15
20
 
16
21
  return {
17
22
  ...rest,
18
- frequency_penalty: model.includes('grok-3-mini') ? undefined : frequency_penalty,
23
+ frequency_penalty: GrokReasoningModels.has(model) ? undefined : frequency_penalty,
19
24
  model,
20
- presence_penalty: model.includes('grok-3-mini') ? undefined : presence_penalty,
25
+ presence_penalty: GrokReasoningModels.has(model) ? undefined : presence_penalty,
21
26
  stream: true,
22
27
  ...(enabledSearch && {
23
28
  search_parameters: {
@@ -6,18 +6,15 @@ import { useOnlyFetchOnceSWR } from '@/libs/swr';
6
6
  // Import for type usage
7
7
  import { electronSystemService } from '@/services/electron/system';
8
8
  import { globalAgentContextManager } from '@/utils/client/GlobalAgentContextManager';
9
+ import { merge } from '@/utils/merge';
9
10
 
10
11
  import { ElectronStore } from '../store';
11
12
 
12
- // Import the new service
13
-
14
- // ======== State ======== //
15
-
16
- // Note: Actual state is defined in initialState.ts and ElectronState interface
17
-
18
13
  // ======== Action Interface ======== //
19
14
 
20
15
  export interface ElectronAppAction {
16
+ updateElectronAppState: (state: ElectronAppState) => void;
17
+
21
18
  /**
22
19
  * Initializes the basic Electron application state, including system info and special paths.
23
20
  * Should be called once when the application starts.
@@ -32,7 +29,12 @@ export const createElectronAppSlice: StateCreator<
32
29
  [['zustand/devtools', never]],
33
30
  [],
34
31
  ElectronAppAction
35
- > = (set) => ({
32
+ > = (set, get) => ({
33
+ updateElectronAppState: (state: ElectronAppState) => {
34
+ const prevState = get().appState;
35
+ set({ appState: merge(prevState, state) });
36
+ },
37
+
36
38
  useInitElectronAppState: () =>
37
39
  useOnlyFetchOnceSWR<ElectronAppState>(
38
40
  'initElectronAppState',