@lobehub/lobehub 2.0.0-next.241 → 2.0.0-next.243

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 (90) hide show
  1. package/.cursor/rules/desktop-feature-implementation.mdc +2 -2
  2. package/.cursor/rules/desktop-local-tools-implement.mdc +2 -2
  3. package/.github/workflows/test.yml +13 -5
  4. package/CHANGELOG.md +52 -0
  5. package/apps/desktop/Development.md +1 -6
  6. package/apps/desktop/README.md +2 -17
  7. package/apps/desktop/README.zh-CN.md +1 -15
  8. package/apps/desktop/build/Icon-beta.Assets.car +0 -0
  9. package/apps/desktop/build/Icon-beta.icns +0 -0
  10. package/apps/desktop/build/icon-beta.ico +0 -0
  11. package/apps/desktop/build/icon-beta.png +0 -0
  12. package/apps/desktop/src/main/controllers/index.ts +1 -1
  13. package/apps/desktop/src/main/controllers/registry.ts +0 -9
  14. package/apps/desktop/src/main/core/App.ts +1 -11
  15. package/apps/desktop/src/main/core/browser/Browser.ts +278 -457
  16. package/apps/desktop/src/main/core/browser/WindowStateManager.ts +180 -0
  17. package/apps/desktop/src/main/core/browser/WindowThemeManager.ts +167 -0
  18. package/apps/desktop/src/main/core/browser/__tests__/WindowStateManager.test.ts +237 -0
  19. package/apps/desktop/src/main/core/browser/__tests__/WindowThemeManager.test.ts +240 -0
  20. package/apps/desktop/src/main/exports.d.ts +1 -1
  21. package/apps/desktop/src/main/exports.ts +1 -1
  22. package/apps/desktop/src/main/utils/__tests__/http-headers.test.ts +131 -0
  23. package/apps/desktop/src/main/utils/http-headers.ts +61 -0
  24. package/apps/desktop/src/main/utils/ipc/__tests__/base.test.ts +1 -22
  25. package/apps/desktop/src/main/utils/ipc/base.ts +0 -20
  26. package/apps/desktop/src/main/utils/ipc/index.ts +1 -9
  27. package/changelog/v1.json +10 -0
  28. package/locales/ar/models.json +48 -7
  29. package/locales/ar/plugin.json +9 -0
  30. package/locales/ar/providers.json +1 -0
  31. package/locales/bg-BG/models.json +35 -7
  32. package/locales/bg-BG/plugin.json +9 -0
  33. package/locales/bg-BG/providers.json +1 -0
  34. package/locales/de-DE/models.json +26 -6
  35. package/locales/de-DE/plugin.json +9 -0
  36. package/locales/de-DE/providers.json +1 -0
  37. package/locales/en-US/models.json +10 -10
  38. package/locales/en-US/oauth.json +0 -1
  39. package/locales/en-US/providers.json +1 -0
  40. package/locales/en-US/subscription.json +2 -2
  41. package/locales/es-ES/models.json +42 -7
  42. package/locales/es-ES/plugin.json +9 -0
  43. package/locales/es-ES/providers.json +1 -0
  44. package/locales/fa-IR/models.json +52 -10
  45. package/locales/fa-IR/plugin.json +9 -0
  46. package/locales/fa-IR/providers.json +1 -0
  47. package/locales/fr-FR/models.json +36 -7
  48. package/locales/fr-FR/plugin.json +9 -0
  49. package/locales/fr-FR/providers.json +1 -0
  50. package/locales/it-IT/models.json +42 -7
  51. package/locales/it-IT/plugin.json +9 -0
  52. package/locales/it-IT/providers.json +1 -0
  53. package/locales/ja-JP/models.json +35 -6
  54. package/locales/ja-JP/plugin.json +9 -0
  55. package/locales/ja-JP/providers.json +1 -0
  56. package/locales/ko-KR/models.json +28 -7
  57. package/locales/ko-KR/plugin.json +9 -0
  58. package/locales/ko-KR/providers.json +1 -0
  59. package/locales/nl-NL/models.json +35 -6
  60. package/locales/nl-NL/plugin.json +9 -0
  61. package/locales/nl-NL/providers.json +1 -0
  62. package/locales/pl-PL/models.json +36 -7
  63. package/locales/pl-PL/plugin.json +9 -0
  64. package/locales/pl-PL/providers.json +1 -0
  65. package/locales/pt-BR/models.json +35 -6
  66. package/locales/pt-BR/plugin.json +9 -0
  67. package/locales/pt-BR/providers.json +1 -0
  68. package/locales/ru-RU/models.json +35 -7
  69. package/locales/ru-RU/plugin.json +9 -0
  70. package/locales/ru-RU/providers.json +1 -0
  71. package/locales/tr-TR/models.json +5 -7
  72. package/locales/tr-TR/plugin.json +9 -0
  73. package/locales/tr-TR/providers.json +1 -0
  74. package/locales/vi-VN/models.json +5 -5
  75. package/locales/vi-VN/plugin.json +9 -0
  76. package/locales/vi-VN/providers.json +1 -0
  77. package/locales/zh-CN/models.json +48 -6
  78. package/locales/zh-CN/oauth.json +0 -1
  79. package/locales/zh-CN/providers.json +1 -0
  80. package/locales/zh-CN/subscription.json +1 -1
  81. package/locales/zh-TW/models.json +10 -10
  82. package/locales/zh-TW/plugin.json +9 -0
  83. package/locales/zh-TW/providers.json +1 -0
  84. package/package.json +1 -1
  85. package/src/features/ChatInput/InputEditor/Placeholder.tsx +4 -1
  86. package/src/locales/default/subscription.ts +2 -3
  87. package/src/server/services/memory/userMemory/extract.ts +46 -6
  88. package/apps/desktop/src/main/controllers/UploadFileServerCtr.ts +0 -33
  89. package/apps/desktop/src/main/controllers/__tests__/UploadFileServerCtr.test.ts +0 -55
  90. package/src/server/modules/ElectronIPCClient/index.ts +0 -92
@@ -37,10 +37,10 @@ LobeChat 桌面端基于 Electron 框架构建,采用主进程-渲染进程架
37
37
  - 位置:`apps/desktop/src/main/controllers/`
38
38
  - 示例:创建 `NewFeatureCtr.ts`
39
39
  - 需继承 `ControllerModule`,并设置 `static readonly groupName`(例如 `static override readonly groupName = 'newFeature';`)
40
- - 按 `_template.ts` 模板格式实现,并在 `apps/desktop/src/main/controllers/registry.ts` 的 `controllerIpcConstructors`(或 `controllerServerIpcConstructors`)中注册,保证类型推导与自动装配
40
+ - 按 `_template.ts` 模板格式实现,并在 `apps/desktop/src/main/controllers/registry.ts` 的 `controllerIpcConstructors` 中注册,保证类型推导与自动装配
41
41
 
42
42
  2. **定义 IPC 事件处理器**
43
- - 使用 `@IpcMethod()` 装饰器暴露渲染进程可访问的通道,或使用 `@IpcServerMethod()` 声明仅供 Next.js 服务器调用的 IPC
43
+ - 使用 `@IpcMethod()` 装饰器暴露渲染进程可访问的通道
44
44
  - 通道名称基于 `groupName.methodName` 自动生成,不再手动拼接字符串
45
45
  - 处理函数可通过 `getIpcContext()` 获取 `sender`、`event` 等上下文信息,并按照需要返回结构化结果
46
46
 
@@ -57,9 +57,9 @@ alwaysApply: false
57
57
  5. **实现后端逻辑 (Controller / IPC Handler):**
58
58
  * **文件:** `apps/desktop/src/main/controllers/[ToolName]Ctr.ts` (例如: `apps/desktop/src/main/controllers/LocalFileCtr.ts`)
59
59
  * **操作:**
60
- * 导入 Node.js 相关模块 (`fs`, `path` 等) 和 IPC 相关依赖 (`ControllerModule`, `IpcMethod`/`IpcServerMethod`、参数类型等)。
60
+ * 导入 Node.js 相关模块 (`fs`, `path` 等) 和 IPC 相关依赖 (`ControllerModule`, `IpcMethod`、参数类型等)。
61
61
  * 添加一个新的 `async` 方法,方法名通常以 `handle` 开头 (例如: `handleRenameFile`)。
62
- * 使用 `@IpcMethod()` 或 `@IpcServerMethod()` 装饰器将此方法注册为对应 IPC 事件的处理器,确保方法名与 Manifest 中的 `name` 以及 Service 层的链式调用一致。
62
+ * 使用 `@IpcMethod()` 装饰器将此方法注册为对应 IPC 事件的处理器,确保方法名与 Manifest 中的 `name` 以及 Service 层的链式调用一致。
63
63
  * 方法的参数应解构自 Service 层传递过来的对象,类型与步骤 2 中定义的 IPC 参数类型匹配。
64
64
  * 实现核心业务逻辑:
65
65
  * 进行必要的输入验证。
@@ -64,15 +64,23 @@ jobs:
64
64
  run: |
65
65
  curl -Os https://cli.codecov.io/latest/linux/codecov
66
66
  chmod +x codecov
67
+ TOKEN="${{ secrets.CODECOV_TOKEN }}"
67
68
  for package in $PACKAGES; do
68
69
  dir="${package#@lobechat/}"
69
70
  if [ -f "./packages/$dir/coverage/lcov.info" ]; then
70
71
  echo "Uploading coverage for $dir..."
71
- ./codecov upload-process \
72
- -t ${{ secrets.CODECOV_TOKEN }} \
73
- -f ./packages/$dir/coverage/lcov.info \
74
- -F packages/$dir \
75
- --disable-search
72
+ if [ -n "$TOKEN" ]; then
73
+ ./codecov upload-process \
74
+ -t "$TOKEN" \
75
+ -f ./packages/$dir/coverage/lcov.info \
76
+ -F packages/$dir \
77
+ --disable-search
78
+ else
79
+ ./codecov upload-process \
80
+ -f ./packages/$dir/coverage/lcov.info \
81
+ -F packages/$dir \
82
+ --disable-search
83
+ fi
76
84
  fi
77
85
  done
78
86
 
package/CHANGELOG.md CHANGED
@@ -2,6 +2,58 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ## [Version 2.0.0-next.243](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.242...v2.0.0-next.243)
6
+
7
+ <sup>Released on **2026-01-08**</sup>
8
+
9
+ #### 🐛 Bug Fixes
10
+
11
+ - **desktop**: Prevent duplicate CORS headers in response.
12
+ - **InputEditor**: Ensure lexical placeholder reactively updates on locale change.
13
+
14
+ <br/>
15
+
16
+ <details>
17
+ <summary><kbd>Improvements and Fixes</kbd></summary>
18
+
19
+ #### What's fixed
20
+
21
+ - **desktop**: Prevent duplicate CORS headers in response, closes [#11350](https://github.com/lobehub/lobe-chat/issues/11350) ([57e725c](https://github.com/lobehub/lobe-chat/commit/57e725c))
22
+ - **InputEditor**: Ensure lexical placeholder reactively updates on locale change, closes [#11352](https://github.com/lobehub/lobe-chat/issues/11352) ([72e796b](https://github.com/lobehub/lobe-chat/commit/72e796b))
23
+
24
+ </details>
25
+
26
+ <div align="right">
27
+
28
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
29
+
30
+ </div>
31
+
32
+ ## [Version 2.0.0-next.242](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.241...v2.0.0-next.242)
33
+
34
+ <sup>Released on **2026-01-08**</sup>
35
+
36
+ #### 🐛 Bug Fixes
37
+
38
+ - **desktop**: Update macOS beta icon size for macOS 26.
39
+
40
+ <br/>
41
+
42
+ <details>
43
+ <summary><kbd>Improvements and Fixes</kbd></summary>
44
+
45
+ #### What's fixed
46
+
47
+ - **desktop**: Update macOS beta icon size for macOS 26, closes [#11348](https://github.com/lobehub/lobe-chat/issues/11348) ([0d1eedf](https://github.com/lobehub/lobe-chat/commit/0d1eedf))
48
+
49
+ </details>
50
+
51
+ <div align="right">
52
+
53
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
54
+
55
+ </div>
56
+
5
57
  ## [Version 2.0.0-next.241](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.240...v2.0.0-next.241)
6
58
 
7
59
  <sup>Released on **2026-01-08**</sup>
@@ -269,7 +269,7 @@ export class ShortcutManager {
269
269
  - 注入 App 实例
270
270
 
271
271
  ```typescript
272
- import { ControllerModule, IpcMethod, IpcServerMethod } from '@/controllers'
272
+ import { ControllerModule, IpcMethod } from '@/controllers'
273
273
 
274
274
  export class ControllerModule implements IControllerModule {
275
275
  constructor(public app: App) {
@@ -284,11 +284,6 @@ export class BrowserWindowsCtr extends ControllerModule {
284
284
  openSettingsWindow(params?: OpenSettingsWindowOptions) {
285
285
  // ...
286
286
  }
287
-
288
- @IpcServerMethod()
289
- handleServerCommand(payload: any) {
290
- // ...
291
- }
292
287
  }
293
288
  ```
294
289
 
@@ -183,16 +183,15 @@ The `App.ts` class orchestrates the entire application lifecycle through key pha
183
183
  #### 🔌 Dependency Injection & Event System
184
184
 
185
185
  - **IoC Container** - WeakMap-based container for decorated controller methods
186
- - **Typed IPC Decorators** - `@IpcMethod` and `@IpcServerMethod` wire controller methods into type-safe channels
186
+ - **Typed IPC Decorators** - `@IpcMethod` wires controller methods into type-safe channels
187
187
  - **Automatic Event Mapping** - Events registered during controller loading
188
188
  - **Service Locator** - Type-safe service and controller retrieval
189
189
 
190
190
  ##### 🧠 Type-Safe IPC Flow
191
191
 
192
192
  - **Async Context Propagation** - `src/main/utils/ipc/base.ts` captures the `IpcContext` with `AsyncLocalStorage`, so controller logic can call `getIpcContext()` anywhere inside an IPC handler without explicitly threading arguments.
193
- - **Service Constructors Registry** - `src/main/controllers/registry.ts` exports `controllerIpcConstructors`, `DesktopIpcServices`, and `DesktopServerIpcServices`, enabling automatic typing of both renderer and server IPC proxies.
193
+ - **Service Constructors Registry** - `src/main/controllers/registry.ts` exports `controllerIpcConstructors` and `DesktopIpcServices`, enabling automatic typing of renderer IPC proxies.
194
194
  - **Renderer Proxy Helper** - `src/utils/electron/ipc.ts` exposes `ensureElectronIpc()` which lazily builds a proxy on top of `window.electronAPI.invoke`, giving React/Next.js code a type-safe API surface without exposing raw proxies in preload.
195
- - **Server Proxy Helper** - `src/server/modules/ElectronIPCClient/index.ts` mirrors the same typing strategy for the Next.js server runtime, providing a dedicated proxy for `@IpcServerMethod` handlers.
196
195
  - **Shared Typings Package** - `apps/desktop/src/main/exports.d.ts` augments `@lobechat/electron-client-ipc` so every package can consume `DesktopIpcServices` without importing desktop business code directly.
197
196
 
198
197
  #### 🪟 Window Management
@@ -278,20 +277,6 @@ await ipc.windows.openSettingsWindow({ tab: 'provider' });
278
277
 
279
278
  The helper internally builds a proxy on top of `window.electronAPI.invoke`, so no proxy objects need to be cloned across the preload boundary.
280
279
 
281
- ##### 🖥️ Server IPC Helper
282
-
283
- Next.js (Node) modules use the same proxy pattern via `ensureElectronServerIpc` from `src/server/modules/ElectronIPCClient`. It lazily wraps the socket-based `ElectronIpcClient` so server code can call controllers with full type safety:
284
-
285
- ```ts
286
- import { ensureElectronServerIpc } from '@/server/modules/ElectronIPCClient';
287
-
288
- const ipc = ensureElectronServerIpc();
289
- const dbPath = await ipc.system.getDatabasePath();
290
- await ipc.upload.deleteFiles(['foo.txt']);
291
- ```
292
-
293
- All server methods are declared via `@IpcServerMethod` and live in dedicated controller classes, keeping renderer typings clean.
294
-
295
280
  #### 🛡️ Security Features
296
281
 
297
282
  - **OAuth 2.0 + PKCE** - Secure authentication with state parameter validation
@@ -183,7 +183,7 @@ src/main/core/
183
183
  #### 🔌 依赖注入和事件系统
184
184
 
185
185
  - **IoC 容器** - 基于 WeakMap 的装饰控制器方法容器
186
- - **装饰器注册** - `@IpcMethod` 和 `@IpcServerMethod` 装饰器
186
+ - **装饰器注册** - `@IpcMethod` 装饰器
187
187
  - **自动事件映射** - 控制器加载期间注册的事件
188
188
  - **服务定位器** - 类型安全的服务和控制器检索
189
189
 
@@ -267,20 +267,6 @@ const ipc = ensureElectronIpc();
267
267
  await ipc.windows.openSettingsWindow({ tab: 'provider' });
268
268
  ```
269
269
 
270
- ##### 🖥️ Server IPC 助手
271
-
272
- Next.js 服务端模块可通过 `ensureElectronServerIpc`(位于 `src/server/modules/ElectronIPCClient`)获得同样的类型安全代理,并复用 socket IPC 通道:
273
-
274
- ```ts
275
- import { ensureElectronServerIpc } from '@/server/modules/ElectronIPCClient';
276
-
277
- const ipc = ensureElectronServerIpc();
278
- const path = await ipc.system.getDatabasePath();
279
- await ipc.upload.deleteFiles(['foo.txt']);
280
- ```
281
-
282
- 所有 `@IpcServerMethod` 方法都放在独立的控制器中,这样渲染端的类型推导不会包含这些仅供服务器调用的通道。
283
-
284
270
  #### 🛡️ 安全功能
285
271
 
286
272
  - **OAuth 2.0 + PKCE** - 具有状态参数验证的安全认证
Binary file
Binary file
Binary file
@@ -50,4 +50,4 @@ export class ControllerModule extends IpcService implements IControllerModule {
50
50
 
51
51
  export type IControlModule = typeof ControllerModule;
52
52
 
53
- export { IpcMethod, IpcServerMethod } from '@/utils/ipc';
53
+ export { IpcMethod } from '@/utils/ipc';
@@ -17,7 +17,6 @@ import SystemController from './SystemCtr';
17
17
  import TrayMenuCtr from './TrayMenuCtr';
18
18
  import UpdaterCtr from './UpdaterCtr';
19
19
  import UploadFileCtr from './UploadFileCtr';
20
- import UploadFileServerCtr from './UploadFileServerCtr';
21
20
 
22
21
  export const controllerIpcConstructors = [
23
22
  AuthCtr,
@@ -42,11 +41,3 @@ export const controllerIpcConstructors = [
42
41
  type DesktopControllerIpcConstructors = typeof controllerIpcConstructors;
43
42
  type DesktopControllerServices = CreateServicesResult<DesktopControllerIpcConstructors>;
44
43
  export type DesktopIpcServices = MergeIpcService<DesktopControllerServices>;
45
-
46
- export const controllerServerIpcConstructors = [
47
- UploadFileServerCtr,
48
- ] as const satisfies readonly IpcServiceConstructor[];
49
-
50
- type DesktopControllerServerConstructors = typeof controllerServerIpcConstructors;
51
- type DesktopServerControllerServices = CreateServicesResult<DesktopControllerServerConstructors>;
52
- export type DesktopServerIpcServices = MergeIpcService<DesktopServerControllerServices>;
@@ -11,7 +11,6 @@ import { isDev } from '@/const/env';
11
11
  import { ELECTRON_BE_PROTOCOL_SCHEME } from '@/const/protocol';
12
12
  import { IControlModule } from '@/controllers';
13
13
  import { IServiceModule } from '@/services';
14
- import { getServerMethodMetadata } from '@/utils/ipc';
15
14
  import { createLogger } from '@/utils/logger';
16
15
 
17
16
  import { BrowserManager } from './browser/BrowserManager';
@@ -330,15 +329,6 @@ export class App {
330
329
  const controller = new ControllerClass(this);
331
330
  this.controllers.set(ControllerClass, controller);
332
331
 
333
- const serverMethods = getServerMethodMetadata(ControllerClass);
334
- serverMethods?.forEach((methodName, propertyKey) => {
335
- const channel = `${ControllerClass.groupName}.${methodName}`;
336
- this.ipcServerEventMap.set(channel, {
337
- controller,
338
- methodName: propertyKey,
339
- });
340
- });
341
-
342
332
  IoCContainer.shortcuts.get(ControllerClass)?.forEach((shortcut) => {
343
333
  this.shortcutMethodMap.set(shortcut.name, async () => {
344
334
  controller[shortcut.methodName]();
@@ -408,4 +398,4 @@ export class App {
408
398
  // 执行清理操作
409
399
  this.staticFileServerManager.destroy();
410
400
  };
411
- }
401
+ }