@lobehub/lobehub 2.0.0-next.21 → 2.0.0-next.23

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 (27) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/apps/desktop/src/main/controllers/AuthCtr.ts +3 -3
  3. package/apps/desktop/src/main/controllers/MenuCtr.ts +5 -5
  4. package/apps/desktop/src/main/controllers/NotificationCtr.ts +29 -29
  5. package/apps/desktop/src/main/controllers/RemoteServerConfigCtr.ts +16 -16
  6. package/apps/desktop/src/main/controllers/ShortcutCtr.ts +2 -2
  7. package/apps/desktop/src/main/controllers/TrayMenuCtr.ts +18 -18
  8. package/apps/desktop/src/main/controllers/UpdaterCtr.ts +4 -4
  9. package/apps/desktop/src/main/controllers/__tests__/TrayMenuCtr.test.ts +5 -5
  10. package/apps/desktop/src/main/controllers/index.ts +4 -4
  11. package/changelog/v1.json +14 -0
  12. package/docs/development/database-schema.dbml +2 -1
  13. package/package.json +2 -2
  14. package/packages/database/migrations/0042_improve_agent_index.sql +1 -0
  15. package/packages/database/migrations/meta/0042_snapshot.json +7800 -0
  16. package/packages/database/migrations/meta/_journal.json +7 -0
  17. package/packages/database/src/core/migrations.json +8 -0
  18. package/packages/database/src/models/agent.ts +16 -13
  19. package/packages/database/src/models/session.ts +20 -9
  20. package/packages/database/src/models/user.ts +2 -1
  21. package/packages/database/src/schemas/agent.ts +4 -1
  22. package/packages/memory-extract/package.json +1 -1
  23. package/packages/types/src/message/ui/params.ts +4 -4
  24. package/renovate.json +49 -13
  25. package/src/server/routers/lambda/message.ts +0 -2
  26. package/src/server/routers/lambda/user.ts +8 -6
  27. package/src/server/services/mcp/deps/MCPSystemDepsCheckService.test.ts +541 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,48 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ## [Version 2.0.0-next.23](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.22...v2.0.0-next.23)
6
+
7
+ <sup>Released on **2025-11-04**</sup>
8
+
9
+ #### 🐛 Bug Fixes
10
+
11
+ - **misc**: Fix send message.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### What's fixed
19
+
20
+ - **misc**: Fix send message, closes [#10041](https://github.com/lobehub/lobe-chat/issues/10041) [#9984](https://github.com/lobehub/lobe-chat/issues/9984) ([7cca60f](https://github.com/lobehub/lobe-chat/commit/7cca60f))
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
+
30
+ ## [Version 2.0.0-next.22](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.21...v2.0.0-next.22)
31
+
32
+ <sup>Released on **2025-11-04**</sup>
33
+
34
+ <br/>
35
+
36
+ <details>
37
+ <summary><kbd>Improvements and Fixes</kbd></summary>
38
+
39
+ </details>
40
+
41
+ <div align="right">
42
+
43
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
44
+
45
+ </div>
46
+
5
47
  ## [Version 2.0.0-next.21](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.20...v2.0.0-next.21)
6
48
 
7
49
  <sup>Released on **2025-11-04**</sup>
@@ -58,7 +58,7 @@ export default class AuthCtr extends ControllerModule {
58
58
  */
59
59
  @ipcClientEvent('requestAuthorization')
60
60
  async requestAuthorization(config: DataSyncConfig) {
61
- // 清理任何旧的授权状态
61
+ // Clear any old authorization state
62
62
  this.clearAuthorizationState();
63
63
 
64
64
  const remoteUrl = await this.remoteServerConfigCtr.getRemoteServerUrl(config);
@@ -186,8 +186,8 @@ export default class AuthCtr extends ControllerModule {
186
186
  }
187
187
 
188
188
  /**
189
- * 清理授权状态
190
- * 在开始新的授权流程前或授权失败/超时后调用
189
+ * Clear authorization state
190
+ * Called before starting a new authorization flow or after authorization failure/timeout
191
191
  */
192
192
  private clearAuthorizationState() {
193
193
  logger.debug('Clearing authorization state');
@@ -2,16 +2,16 @@ import { ControllerModule, ipcClientEvent } from './index';
2
2
 
3
3
  export default class MenuController extends ControllerModule {
4
4
  /**
5
- * 刷新菜单
5
+ * Refresh menu
6
6
  */
7
7
  @ipcClientEvent('refreshAppMenu')
8
8
  refreshAppMenu() {
9
- // 注意:可能需要根据具体情况决定是否允许渲染进程刷新所有菜单
9
+ // Note: May need to decide whether to allow renderer process to refresh all menus based on specific circumstances
10
10
  return this.app.menuManager.refreshMenus();
11
11
  }
12
12
 
13
13
  /**
14
- * 显示上下文菜单
14
+ * Show context menu
15
15
  */
16
16
  @ipcClientEvent('showContextMenu')
17
17
  showContextMenu(params: { data?: any; type: string }) {
@@ -19,11 +19,11 @@ export default class MenuController extends ControllerModule {
19
19
  }
20
20
 
21
21
  /**
22
- * 设置开发菜单可见性
22
+ * Set development menu visibility
23
23
  */
24
24
  @ipcClientEvent('setDevMenuVisibility')
25
25
  setDevMenuVisibility(visible: boolean) {
26
- // 调用 MenuManager 的方法来重建应用菜单
26
+ // Call MenuManager method to rebuild application menu
27
27
  return this.app.menuManager.rebuildAppMenu({ showDevItems: visible });
28
28
  }
29
29
  }
@@ -13,31 +13,31 @@ const logger = createLogger('controllers:NotificationCtr');
13
13
 
14
14
  export default class NotificationCtr extends ControllerModule {
15
15
  /**
16
- * 在应用准备就绪后设置桌面通知
16
+ * Set up desktop notifications after the application is ready
17
17
  */
18
18
  afterAppReady() {
19
19
  this.setupNotifications();
20
20
  }
21
21
 
22
22
  /**
23
- * 设置桌面通知权限和配置
23
+ * Set up desktop notification permissions and configuration
24
24
  */
25
25
  private setupNotifications() {
26
26
  logger.debug('Setting up desktop notifications');
27
27
 
28
28
  try {
29
- // 检查通知支持
29
+ // Check notification support
30
30
  if (!Notification.isSupported()) {
31
31
  logger.warn('Desktop notifications are not supported on this platform');
32
32
  return;
33
33
  }
34
34
 
35
- // macOS 上,我们可能需要显式请求通知权限
35
+ // On macOS, we may need to explicitly request notification permissions
36
36
  if (macOS()) {
37
37
  logger.debug('macOS detected, notification permissions should be handled by system');
38
38
  }
39
39
 
40
- // Windows 上设置应用用户模型 ID
40
+ // Set app user model ID on Windows
41
41
  if (windows()) {
42
42
  app.setAppUserModelId('com.lobehub.chat');
43
43
  logger.debug('Set Windows App User Model ID for notifications');
@@ -49,34 +49,34 @@ export default class NotificationCtr extends ControllerModule {
49
49
  }
50
50
  }
51
51
  /**
52
- * 显示系统桌面通知(仅当窗口隐藏时)
52
+ * Show system desktop notification (only when window is hidden)
53
53
  */
54
54
  @ipcClientEvent('showDesktopNotification')
55
55
  async showDesktopNotification(
56
56
  params: ShowDesktopNotificationParams,
57
57
  ): Promise<DesktopNotificationResult> {
58
- logger.debug('收到桌面通知请求:', params);
58
+ logger.debug('Received desktop notification request:', params);
59
59
 
60
60
  try {
61
- // 检查通知支持
61
+ // Check notification support
62
62
  if (!Notification.isSupported()) {
63
- logger.warn('系统不支持桌面通知');
63
+ logger.warn('System does not support desktop notifications');
64
64
  return { error: 'Desktop notifications not supported', success: false };
65
65
  }
66
66
 
67
- // 检查窗口是否隐藏
67
+ // Check if window is hidden
68
68
  const isWindowHidden = this.isMainWindowHidden();
69
69
 
70
70
  if (!isWindowHidden) {
71
- logger.debug('主窗口可见,跳过桌面通知');
71
+ logger.debug('Main window is visible, skipping desktop notification');
72
72
  return { reason: 'Window is visible', skipped: true, success: true };
73
73
  }
74
74
 
75
- logger.info('窗口已隐藏,显示桌面通知:', params.title);
75
+ logger.info('Window is hidden, showing desktop notification:', params.title);
76
76
 
77
77
  const notification = new Notification({
78
78
  body: params.body,
79
- // 添加更多配置以确保通知能正常显示
79
+ // Add more configuration to ensure notifications display properly
80
80
  hasReply: false,
81
81
  silent: params.silent || false,
82
82
  timeoutType: 'default',
@@ -84,38 +84,38 @@ export default class NotificationCtr extends ControllerModule {
84
84
  urgency: 'normal',
85
85
  });
86
86
 
87
- // 添加更多事件监听来调试
87
+ // Add more event listeners for debugging
88
88
  notification.on('show', () => {
89
- logger.info('通知已显示');
89
+ logger.info('Notification shown');
90
90
  });
91
91
 
92
92
  notification.on('click', () => {
93
- logger.debug('用户点击通知,显示主窗口');
93
+ logger.debug('User clicked notification, showing main window');
94
94
  const mainWindow = this.app.browserManager.getMainWindow();
95
95
  mainWindow.show();
96
96
  mainWindow.browserWindow.focus();
97
97
  });
98
98
 
99
99
  notification.on('close', () => {
100
- logger.debug('通知已关闭');
100
+ logger.debug('Notification closed');
101
101
  });
102
102
 
103
103
  notification.on('failed', (error) => {
104
- logger.error('通知显示失败:', error);
104
+ logger.error('Notification display failed:', error);
105
105
  });
106
106
 
107
- // 使用 Promise 来确保通知显示
107
+ // Use Promise to ensure notification is shown
108
108
  return new Promise((resolve) => {
109
109
  notification.show();
110
110
 
111
- // 给通知一些时间来显示,然后检查结果
111
+ // Give the notification some time to display, then check the result
112
112
  setTimeout(() => {
113
- logger.info('通知显示调用完成');
113
+ logger.info('Notification display call completed');
114
114
  resolve({ success: true });
115
115
  }, 100);
116
116
  });
117
117
  } catch (error) {
118
- logger.error('显示桌面通知失败:', error);
118
+ logger.error('Failed to show desktop notification:', error);
119
119
  return {
120
120
  error: error instanceof Error ? error.message : 'Unknown error',
121
121
  success: false,
@@ -124,7 +124,7 @@ export default class NotificationCtr extends ControllerModule {
124
124
  }
125
125
 
126
126
  /**
127
- * 检查主窗口是否隐藏
127
+ * Check if the main window is hidden
128
128
  */
129
129
  @ipcClientEvent('isMainWindowHidden')
130
130
  isMainWindowHidden(): boolean {
@@ -132,23 +132,23 @@ export default class NotificationCtr extends ControllerModule {
132
132
  const mainWindow = this.app.browserManager.getMainWindow();
133
133
  const browserWindow = mainWindow.browserWindow;
134
134
 
135
- // 如果窗口被销毁,认为是隐藏的
135
+ // If window is destroyed, consider it hidden
136
136
  if (browserWindow.isDestroyed()) {
137
137
  return true;
138
138
  }
139
139
 
140
- // 检查窗口是否可见和聚焦
140
+ // Check if window is visible and focused
141
141
  const isVisible = browserWindow.isVisible();
142
142
  const isFocused = browserWindow.isFocused();
143
143
  const isMinimized = browserWindow.isMinimized();
144
144
 
145
- logger.debug('窗口状态检查:', { isFocused, isMinimized, isVisible });
145
+ logger.debug('Window state check:', { isFocused, isMinimized, isVisible });
146
146
 
147
- // 窗口隐藏的条件:不可见或最小化或失去焦点
147
+ // Window is hidden if: not visible, minimized, or not focused
148
148
  return !isVisible || isMinimized || !isFocused;
149
149
  } catch (error) {
150
- logger.error('检查窗口状态失败:', error);
151
- return true; // 发生错误时认为窗口隐藏,确保通知能显示
150
+ logger.error('Failed to check window state:', error);
151
+ return true; // Consider window hidden on error to ensure notifications can be shown
152
152
  }
153
153
  }
154
154
  }
@@ -246,8 +246,8 @@ export default class RemoteServerConfigCtr extends ControllerModule {
246
246
  }
247
247
 
248
248
  /**
249
- * 刷新访问令牌
250
- * 使用存储的刷新令牌获取新的访问令牌
249
+ * Refresh access token
250
+ * Use stored refresh token to obtain a new access token
251
251
  * Handles concurrent requests by returning the existing refresh promise if one is in progress.
252
252
  */
253
253
  async refreshAccessToken(): Promise<{ error?: string; success: boolean }> {
@@ -271,27 +271,27 @@ export default class RemoteServerConfigCtr extends ControllerModule {
271
271
  */
272
272
  private async performTokenRefresh(): Promise<{ error?: string; success: boolean }> {
273
273
  try {
274
- // 获取配置信息
274
+ // Get configuration information
275
275
  const config = await this.getRemoteServerConfig();
276
276
 
277
277
  if (!config.remoteServerUrl || !config.active) {
278
278
  logger.warn('Remote server not active or configured, skipping refresh.');
279
- return { error: '远程服务器未激活或未配置', success: false };
279
+ return { error: 'Remote server is not active or configured', success: false };
280
280
  }
281
281
 
282
- // 获取刷新令牌
282
+ // Get refresh token
283
283
  const refreshToken = await this.getRefreshToken();
284
284
  if (!refreshToken) {
285
285
  logger.error('No refresh token available for refresh operation.');
286
- return { error: '没有可用的刷新令牌', success: false };
286
+ return { error: 'No refresh token available', success: false };
287
287
  }
288
288
 
289
- // 构造刷新请求
289
+ // Construct refresh request
290
290
  const remoteUrl = await this.getRemoteServerUrl(config);
291
291
 
292
292
  const tokenUrl = new URL('/oidc/token', remoteUrl);
293
293
 
294
- // 构造请求体
294
+ // Construct request body
295
295
  const body = querystring.stringify({
296
296
  client_id: 'lobehub-desktop',
297
297
  grant_type: 'refresh_token',
@@ -300,7 +300,7 @@ export default class RemoteServerConfigCtr extends ControllerModule {
300
300
 
301
301
  logger.debug(`Sending token refresh request to ${tokenUrl.toString()}`);
302
302
 
303
- // 发送请求
303
+ // Send request
304
304
  const response = await fetch(tokenUrl.toString(), {
305
305
  body,
306
306
  headers: {
@@ -310,25 +310,25 @@ export default class RemoteServerConfigCtr extends ControllerModule {
310
310
  });
311
311
 
312
312
  if (!response.ok) {
313
- // 尝试解析错误响应
313
+ // Try to parse error response
314
314
  const errorData = await response.json().catch(() => ({}));
315
- const errorMessage = `刷新令牌失败: ${response.status} ${response.statusText} ${
315
+ const errorMessage = `Token refresh failed: ${response.status} ${response.statusText} ${
316
316
  errorData.error_description || errorData.error || ''
317
317
  }`.trim();
318
318
  logger.error(errorMessage, errorData);
319
319
  return { error: errorMessage, success: false };
320
320
  }
321
321
 
322
- // 解析响应
322
+ // Parse response
323
323
  const data = await response.json();
324
324
 
325
- // 检查响应中是否包含必要令牌
325
+ // Check if response contains necessary tokens
326
326
  if (!data.access_token || !data.refresh_token) {
327
327
  logger.error('Refresh response missing access_token or refresh_token', data);
328
- return { error: '刷新响应中缺少令牌', success: false };
328
+ return { error: 'Missing tokens in refresh response', success: false };
329
329
  }
330
330
 
331
- // 保存新令牌
331
+ // Save new tokens
332
332
  logger.info('Token refresh successful, saving new tokens.');
333
333
  await this.saveTokens(data.access_token, data.refresh_token, data.expires_in);
334
334
 
@@ -336,7 +336,7 @@ export default class RemoteServerConfigCtr extends ControllerModule {
336
336
  } catch (error) {
337
337
  const errorMessage = error instanceof Error ? error.message : String(error);
338
338
  logger.error('Exception during token refresh operation:', errorMessage, error);
339
- return { error: `刷新令牌时发生异常: ${errorMessage}`, success: false };
339
+ return { error: `Exception occurred during token refresh: ${errorMessage}`, success: false };
340
340
  } finally {
341
341
  // Ensure the promise reference is cleared once the operation completes
342
342
  logger.debug('Clearing the refresh promise reference.');
@@ -4,7 +4,7 @@ import { ControllerModule, ipcClientEvent } from '.';
4
4
 
5
5
  export default class ShortcutController extends ControllerModule {
6
6
  /**
7
- * 获取所有快捷键配置
7
+ * Get all shortcut configurations
8
8
  */
9
9
  @ipcClientEvent('getShortcutsConfig')
10
10
  getShortcutsConfig() {
@@ -12,7 +12,7 @@ export default class ShortcutController extends ControllerModule {
12
12
  }
13
13
 
14
14
  /**
15
- * 更新单个快捷键配置
15
+ * Update a single shortcut configuration
16
16
  */
17
17
  @ipcClientEvent('updateShortcutConfig')
18
18
  updateShortcutConfig({
@@ -8,24 +8,24 @@ import { createLogger } from '@/utils/logger';
8
8
 
9
9
  import { ControllerModule, ipcClientEvent } from './index';
10
10
 
11
- // 创建日志记录器
11
+ // Create logger
12
12
  const logger = createLogger('controllers:TrayMenuCtr');
13
13
 
14
14
  export default class TrayMenuCtr extends ControllerModule {
15
15
  async toggleMainWindow() {
16
- logger.debug('通过快捷键切换主窗口可见性');
16
+ logger.debug('Toggle main window visibility via shortcut');
17
17
  const mainWindow = this.app.browserManager.getMainWindow();
18
18
  mainWindow.toggleVisible();
19
19
  }
20
20
 
21
21
  /**
22
- * 显示托盘气泡通知
23
- * @param options 气泡选项
24
- * @returns 操作结果
22
+ * Show tray balloon notification
23
+ * @param options Balloon options
24
+ * @returns Operation result
25
25
  */
26
26
  @ipcClientEvent('showTrayNotification')
27
27
  async showNotification(options: ShowTrayNotificationParams) {
28
- logger.debug('显示托盘气泡通知');
28
+ logger.debug('Show tray balloon notification');
29
29
 
30
30
  if (process.platform === 'win32') {
31
31
  const mainTray = this.app.trayManager.getMainTray();
@@ -42,19 +42,19 @@ export default class TrayMenuCtr extends ControllerModule {
42
42
  }
43
43
 
44
44
  return {
45
- error: '托盘通知仅在 Windows 平台支持',
45
+ error: 'Tray notifications are only supported on Windows platform',
46
46
  success: false,
47
47
  };
48
48
  }
49
49
 
50
50
  /**
51
- * 更新托盘图标
52
- * @param options 图标选项
53
- * @returns 操作结果
51
+ * Update tray icon
52
+ * @param options Icon options
53
+ * @returns Operation result
54
54
  */
55
55
  @ipcClientEvent('updateTrayIcon')
56
56
  async updateTrayIcon(options: UpdateTrayIconParams) {
57
- logger.debug('更新托盘图标');
57
+ logger.debug('Update tray icon');
58
58
 
59
59
  if (process.platform === 'win32') {
60
60
  const mainTray = this.app.trayManager.getMainTray();
@@ -64,7 +64,7 @@ export default class TrayMenuCtr extends ControllerModule {
64
64
  mainTray.updateIcon(options.iconPath);
65
65
  return { success: true };
66
66
  } catch (error) {
67
- logger.error('更新托盘图标失败:', error);
67
+ logger.error('Failed to update tray icon:', error);
68
68
  return {
69
69
  error: String(error),
70
70
  success: false,
@@ -74,19 +74,19 @@ export default class TrayMenuCtr extends ControllerModule {
74
74
  }
75
75
 
76
76
  return {
77
- error: '托盘功能仅在 Windows 平台支持',
77
+ error: 'Tray functionality is only supported on Windows platform',
78
78
  success: false,
79
79
  };
80
80
  }
81
81
 
82
82
  /**
83
- * 更新托盘提示文本
84
- * @param options 提示文本选项
85
- * @returns 操作结果
83
+ * Update tray tooltip text
84
+ * @param options Tooltip text options
85
+ * @returns Operation result
86
86
  */
87
87
  @ipcClientEvent('updateTrayTooltip')
88
88
  async updateTrayTooltip(options: UpdateTrayTooltipParams) {
89
- logger.debug('更新托盘提示文本');
89
+ logger.debug('Update tray tooltip text');
90
90
 
91
91
  if (process.platform === 'win32') {
92
92
  const mainTray = this.app.trayManager.getMainTray();
@@ -98,7 +98,7 @@ export default class TrayMenuCtr extends ControllerModule {
98
98
  }
99
99
 
100
100
  return {
101
- error: '托盘功能仅在 Windows 平台支持',
101
+ error: 'Tray functionality is only supported on Windows platform',
102
102
  success: false,
103
103
  };
104
104
  }
@@ -6,7 +6,7 @@ const logger = createLogger('controllers:UpdaterCtr');
6
6
 
7
7
  export default class UpdaterCtr extends ControllerModule {
8
8
  /**
9
- * 检查更新
9
+ * Check for updates
10
10
  */
11
11
  @ipcClientEvent('checkUpdate')
12
12
  async checkForUpdates() {
@@ -15,7 +15,7 @@ export default class UpdaterCtr extends ControllerModule {
15
15
  }
16
16
 
17
17
  /**
18
- * 下载更新
18
+ * Download update
19
19
  */
20
20
  @ipcClientEvent('downloadUpdate')
21
21
  async downloadUpdate() {
@@ -24,7 +24,7 @@ export default class UpdaterCtr extends ControllerModule {
24
24
  }
25
25
 
26
26
  /**
27
- * 关闭应用并安装更新
27
+ * Quit application and install update
28
28
  */
29
29
  @ipcClientEvent('installNow')
30
30
  quitAndInstallUpdate() {
@@ -33,7 +33,7 @@ export default class UpdaterCtr extends ControllerModule {
33
33
  }
34
34
 
35
35
  /**
36
- * 下次启动时安装更新
36
+ * Install update on next startup
37
37
  */
38
38
  @ipcClientEvent('installLater')
39
39
  installLater() {
@@ -106,7 +106,7 @@ describe('TrayMenuCtr', () => {
106
106
  expect(mockGetMainTray).not.toHaveBeenCalled();
107
107
  expect(mockDisplayBalloon).not.toHaveBeenCalled();
108
108
  expect(result).toEqual({
109
- error: '托盘通知仅在 Windows 平台支持',
109
+ error: 'Tray notifications are only supported on Windows platform',
110
110
  success: false,
111
111
  });
112
112
  });
@@ -126,7 +126,7 @@ describe('TrayMenuCtr', () => {
126
126
  expect(mockGetMainTray).toHaveBeenCalled();
127
127
  expect(mockDisplayBalloon).not.toHaveBeenCalled();
128
128
  expect(result).toEqual({
129
- error: '托盘通知仅在 Windows 平台支持',
129
+ error: 'Tray notifications are only supported on Windows platform',
130
130
  success: false
131
131
  });
132
132
  });
@@ -188,7 +188,7 @@ describe('TrayMenuCtr', () => {
188
188
  const result = await trayMenuCtr.updateTrayIcon(options);
189
189
 
190
190
  expect(result).toEqual({
191
- error: '托盘功能仅在 Windows 平台支持',
191
+ error: 'Tray functionality is only supported on Windows platform',
192
192
  success: false,
193
193
  });
194
194
  });
@@ -226,7 +226,7 @@ describe('TrayMenuCtr', () => {
226
226
  const result = await trayMenuCtr.updateTrayTooltip(options);
227
227
 
228
228
  expect(result).toEqual({
229
- error: '托盘功能仅在 Windows 平台支持',
229
+ error: 'Tray functionality is only supported on Windows platform',
230
230
  success: false,
231
231
  });
232
232
  });
@@ -248,7 +248,7 @@ describe('TrayMenuCtr', () => {
248
248
 
249
249
  expect(mockUpdateTooltip).not.toHaveBeenCalled();
250
250
  expect(result).toEqual({
251
- error: '托盘功能仅在 Windows 平台支持',
251
+ error: 'Tray functionality is only supported on Windows platform',
252
252
  success: false,
253
253
  });
254
254
  });
@@ -19,13 +19,13 @@ const ipcDecorator =
19
19
  };
20
20
 
21
21
  /**
22
- * controller 用的 ipc client event 装饰器
22
+ * IPC client event decorator for controllers
23
23
  */
24
24
  export const ipcClientEvent = (method: keyof ClientDispatchEvents) =>
25
25
  ipcDecorator(method, 'client');
26
26
 
27
27
  /**
28
- * controller 用的 ipc server event 装饰器
28
+ * IPC server event decorator for controllers
29
29
  */
30
30
  export const ipcServerEvent = (method: keyof ServerDispatchEvents) =>
31
31
  ipcDecorator(method, 'server');
@@ -56,8 +56,8 @@ const protocolDecorator =
56
56
 
57
57
  /**
58
58
  * Protocol handler decorator
59
- * @param urlType 协议URL类型 (如: 'plugin')
60
- * @param action 操作类型 (如: 'install')
59
+ * @param urlType Protocol URL type (e.g., 'plugin')
60
+ * @param action Action type (e.g., 'install')
61
61
  */
62
62
  export const createProtocolHandler = (urlType: string) => (action: string) =>
63
63
  protocolDecorator(urlType, action);
package/changelog/v1.json CHANGED
@@ -1,4 +1,18 @@
1
1
  [
2
+ {
3
+ "children": {
4
+ "fixes": [
5
+ "Fix send message."
6
+ ]
7
+ },
8
+ "date": "2025-11-04",
9
+ "version": "2.0.0-next.23"
10
+ },
11
+ {
12
+ "children": {},
13
+ "date": "2025-11-04",
14
+ "version": "2.0.0-next.22"
15
+ },
2
16
  {
3
17
  "children": {
4
18
  "fixes": [
@@ -56,6 +56,7 @@ table agents_knowledge_bases {
56
56
 
57
57
  indexes {
58
58
  (agent_id, knowledge_base_id) [pk]
59
+ agent_id [name: 'agents_knowledge_bases_agent_id_idx']
59
60
  }
60
61
  }
61
62
 
@@ -1176,4 +1177,4 @@ ref: topic_documents.document_id > documents.id
1176
1177
 
1177
1178
  ref: topic_documents.topic_id > topics.id
1178
1179
 
1179
- ref: topics.session_id - sessions.id
1180
+ ref: topics.session_id - sessions.id
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/lobehub",
3
- "version": "2.0.0-next.21",
3
+ "version": "2.0.0-next.23",
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",
@@ -250,7 +250,7 @@
250
250
  "pdfjs-dist": "4.8.69",
251
251
  "pdfkit": "^0.17.2",
252
252
  "pg": "^8.16.3",
253
- "pino": "^9.14.0",
253
+ "pino": "^10.1.0",
254
254
  "plaiceholder": "^3.0.0",
255
255
  "polished": "^4.3.1",
256
256
  "posthog-js": "~1.278.0",
@@ -0,0 +1 @@
1
+ CREATE INDEX IF NOT EXISTS "agents_knowledge_bases_agent_id_idx" ON "agents_knowledge_bases" USING btree ("agent_id");