@lobehub/lobehub 2.0.0-next.324 → 2.0.0-next.326

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 (69) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/CLAUDE.md +4 -0
  3. package/apps/desktop/src/main/core/browser/Browser.ts +40 -1
  4. package/apps/desktop/src/main/core/infrastructure/I18nManager.ts +0 -11
  5. package/apps/desktop/src/main/core/infrastructure/UpdaterManager.ts +52 -2
  6. package/apps/desktop/src/main/core/infrastructure/__tests__/UpdaterManager.test.ts +41 -0
  7. package/changelog/v1.json +10 -0
  8. package/package.json +2 -2
  9. package/packages/database/src/models/__tests__/session.test.ts +0 -29
  10. package/src/app/[variants]/(main)/agent/features/Conversation/AgentWelcome/OpeningQuestions.tsx +0 -2
  11. package/src/app/[variants]/(main)/community/(detail)/agent/features/Sidebar/TocList/index.tsx +0 -36
  12. package/src/app/[variants]/(main)/community/(list)/_layout/Header.tsx +0 -2
  13. package/src/app/[variants]/(main)/group/_layout/Sidebar/GroupConfig/GroupMember.tsx +0 -4
  14. package/src/app/[variants]/(main)/group/features/Conversation/ConversationArea.tsx +0 -7
  15. package/src/app/[variants]/(main)/group/features/Conversation/MainChatInput/GroupChat.tsx +0 -2
  16. package/src/app/[variants]/(main)/home/_layout/Body/index.tsx +0 -2
  17. package/src/app/[variants]/(main)/page/_layout/Body/List/Item/useDropdownMenu.tsx +0 -6
  18. package/src/app/[variants]/(main)/page/_layout/Body/useDropdownMenu.tsx +0 -15
  19. package/src/app/[variants]/(main)/resource/features/DndContextWrapper.tsx +0 -5
  20. package/src/app/[variants]/(main)/settings/provider/features/ModelList/CreateNewModelModal/index.tsx +0 -1
  21. package/src/app/[variants]/(main)/settings/provider/features/ModelList/ModelItem.tsx +0 -10
  22. package/src/app/[variants]/(main)/settings/provider/features/ProviderConfig/Checker.tsx +1 -1
  23. package/src/app/[variants]/(mobile)/(home)/features/SessionListContent/List/Item/Actions.tsx +0 -1
  24. package/src/app/[variants]/layout.tsx +0 -2
  25. package/src/envs/__tests__/app.test.ts +0 -6
  26. package/src/features/ChatInput/ActionBar/Knowledge/useControls.tsx +0 -22
  27. package/src/features/ChatInput/store/action.ts +0 -2
  28. package/src/features/Conversation/Messages/Task/TaskDetailPanel/index.tsx +1 -15
  29. package/src/features/DataImporter/ImportDetail.tsx +0 -20
  30. package/src/features/DevPanel/features/Table/TableCell.tsx +1 -36
  31. package/src/features/DevPanel/index.tsx +0 -9
  32. package/src/features/ModelSwitchPanel/__mocks__/mockEnabledChatModels.ts +159 -0
  33. package/src/features/ModelSwitchPanel/components/List/{VirtualItemRenderer.tsx → ListItemRenderer.tsx} +15 -25
  34. package/src/features/ModelSwitchPanel/components/List/MultipleProvidersModelItem.tsx +95 -69
  35. package/src/features/ModelSwitchPanel/components/List/index.tsx +39 -40
  36. package/src/features/ModelSwitchPanel/components/PanelContent.tsx +0 -8
  37. package/src/features/ModelSwitchPanel/hooks/{useBuildVirtualItems.ts → useBuildListItems.ts} +7 -17
  38. package/src/features/ModelSwitchPanel/index.tsx +24 -23
  39. package/src/features/ModelSwitchPanel/styles.ts +3 -0
  40. package/src/features/ModelSwitchPanel/types.ts +3 -8
  41. package/src/features/ModelSwitchPanel/utils.ts +2 -2
  42. package/src/features/NavPanel/SideBarDrawer.tsx +12 -2
  43. package/src/features/NavPanel/SideBarHeaderLayout.tsx +3 -1
  44. package/src/features/Portal/GroupThread/Body/index.tsx +0 -6
  45. package/src/features/ResourceManager/components/Header/AddButton.tsx +0 -16
  46. package/src/features/ShareModal/ShareImage/index.tsx +0 -8
  47. package/src/hooks/useProviderName.ts +0 -1
  48. package/src/layout/GlobalProvider/Locale.tsx +0 -12
  49. package/src/layout/GlobalProvider/index.tsx +0 -1
  50. package/src/libs/better-auth/sso/helpers.ts +0 -1
  51. package/src/libs/next/config/define-config.ts +5 -0
  52. package/src/locales/create.ts +0 -17
  53. package/src/services/aiChat.ts +0 -4
  54. package/src/services/debug.ts +1 -34
  55. package/src/services/models.ts +0 -15
  56. package/src/store/chat/agents/GroupOrchestration/createGroupOrchestrationExecutors.ts +0 -9
  57. package/src/store/chat/slices/aiChat/actions/conversationLifecycle.ts +0 -3
  58. package/src/store/chat/slices/aiChat/actions/index.ts +1 -3
  59. package/src/store/file/slices/chat/action.test.ts +0 -89
  60. package/src/store/file/slices/chunk/selectors.ts +0 -1
  61. package/src/store/file/slices/fileManager/selectors.ts +0 -1
  62. package/src/store/file/slices/tts/selectors.ts +0 -2
  63. package/src/store/tool/slices/customPlugin/index.ts +0 -1
  64. package/src/store/tool/slices/mcpStore/index.ts +0 -1
  65. package/src/store/tool/slices/oldStore/index.ts +0 -1
  66. package/src/store/tool/slices/plugin/index.ts +0 -1
  67. package/src/styles/global.ts +6 -0
  68. package/src/utils/router.tsx +1 -7
  69. package/src/utils/server/parseModels.ts +0 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,64 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ## [Version 2.0.0-next.326](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.325...v2.0.0-next.326)
6
+
7
+ <sup>Released on **2026-01-20**</sup>
8
+
9
+ #### 🐛 Bug Fixes
10
+
11
+ - **desktop**: Gracefully handle missing update manifest 404 errors.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### What's fixed
19
+
20
+ - **desktop**: Gracefully handle missing update manifest 404 errors, closes [#11625](https://github.com/lobehub/lobe-chat/issues/11625) ([13e95b9](https://github.com/lobehub/lobe-chat/commit/13e95b9))
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.325](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.324...v2.0.0-next.325)
31
+
32
+ <sup>Released on **2026-01-20**</sup>
33
+
34
+ #### ♻ Code Refactoring
35
+
36
+ - **ModelSwitchPanel**: Migrate from Popover to DropdownMenu with virtual scrolling.
37
+
38
+ #### 🐛 Bug Fixes
39
+
40
+ - **sidebar-drawer**: Fix drawer positioning and title style.
41
+
42
+ <br/>
43
+
44
+ <details>
45
+ <summary><kbd>Improvements and Fixes</kbd></summary>
46
+
47
+ #### Code refactoring
48
+
49
+ - **ModelSwitchPanel**: Migrate from Popover to DropdownMenu with virtual scrolling, closes [#11663](https://github.com/lobehub/lobe-chat/issues/11663) ([c9d9dff](https://github.com/lobehub/lobe-chat/commit/c9d9dff))
50
+
51
+ #### What's fixed
52
+
53
+ - **sidebar-drawer**: Fix drawer positioning and title style, closes [#11655](https://github.com/lobehub/lobe-chat/issues/11655) ([cf5320e](https://github.com/lobehub/lobe-chat/commit/cf5320e))
54
+
55
+ </details>
56
+
57
+ <div align="right">
58
+
59
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
60
+
61
+ </div>
62
+
5
63
  ## [Version 2.0.0-next.324](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.323...v2.0.0-next.324)
6
64
 
7
65
  <sup>Released on **2026-01-20**</sup>
package/CLAUDE.md CHANGED
@@ -32,6 +32,10 @@ This repository adopts a monorepo structure.
32
32
 
33
33
  see @.cursor/rules/typescript.mdc
34
34
 
35
+ ### Code Comments
36
+
37
+ - **Avoid meaningless comments**: Do not write comments that merely restate what the code does. Comments should explain _why_ something is done, not _what_ is being done. The code itself should be self-explanatory.
38
+
35
39
  ### Testing
36
40
 
37
41
  - **Required Rule**: read `.cursor/rules/testing-guide/testing-guide.mdc` before writing tests
@@ -3,6 +3,7 @@ import { MainBroadcastEventKey, MainBroadcastParams } from '@lobechat/electron-c
3
3
  import {
4
4
  BrowserWindow,
5
5
  BrowserWindowConstructorOptions,
6
+ Menu,
6
7
  session as electronSession,
7
8
  ipcMain,
8
9
  screen,
@@ -11,7 +12,7 @@ import console from 'node:console';
11
12
  import { join } from 'node:path';
12
13
 
13
14
  import { preloadDir, resourcesDir } from '@/const/dir';
14
- import { isMac } from '@/const/env';
15
+ import { isDev, isMac } from '@/const/env';
15
16
  import { ELECTRON_BE_PROTOCOL_SCHEME } from '@/const/protocol';
16
17
  import RemoteServerConfigCtr from '@/controllers/RemoteServerConfigCtr';
17
18
  import { backendProxyProtocolManager } from '@/core/infrastructure/BackendProxyProtocolManager';
@@ -191,6 +192,7 @@ export default class Browser {
191
192
  this.setupCloseListener(browserWindow);
192
193
  this.setupFocusListener(browserWindow);
193
194
  this.setupWillPreventUnloadListener(browserWindow);
195
+ this.setupDevContextMenu(browserWindow);
194
196
  }
195
197
 
196
198
  private setupWillPreventUnloadListener(browserWindow: BrowserWindow): void {
@@ -236,6 +238,43 @@ export default class Browser {
236
238
  });
237
239
  }
238
240
 
241
+ /**
242
+ * Setup context menu with "Inspect Element" option in development mode
243
+ */
244
+ private setupDevContextMenu(browserWindow: BrowserWindow): void {
245
+ if (!isDev) return;
246
+
247
+ logger.debug(`[${this.identifier}] Setting up dev context menu.`);
248
+
249
+ browserWindow.webContents.on('context-menu', (_event, params) => {
250
+ const { x, y } = params;
251
+
252
+ const menu = Menu.buildFromTemplate([
253
+ {
254
+ click: () => {
255
+ browserWindow.webContents.inspectElement(x, y);
256
+ },
257
+ label: 'Inspect Element',
258
+ },
259
+ { type: 'separator' },
260
+ {
261
+ click: () => {
262
+ browserWindow.webContents.openDevTools();
263
+ },
264
+ label: 'Open DevTools',
265
+ },
266
+ {
267
+ click: () => {
268
+ browserWindow.webContents.reload();
269
+ },
270
+ label: 'Reload',
271
+ },
272
+ ]);
273
+
274
+ menu.popup({ window: browserWindow });
275
+ });
276
+ }
277
+
239
278
  // ==================== Window Actions ====================
240
279
 
241
280
  show(): void {
@@ -149,17 +149,6 @@ export class I18nManager {
149
149
  */
150
150
  private notifyRendererProcess(lng: string) {
151
151
  logger.debug(`Notifying renderer process of language change: ${lng}`);
152
-
153
- // Send language change event to all windows
154
- // const windows = this.app.browserManager.windows;
155
- //
156
- // if (windows && windows.length > 0) {
157
- // windows.forEach((window) => {
158
- // if (window?.webContents) {
159
- // window.webContents.send('language-changed', lng);
160
- // }
161
- // });
162
- // }
163
152
  }
164
153
 
165
154
  private async loadLocale(language: string) {
@@ -1,3 +1,5 @@
1
+ import type { UpdateInfo } from '@lobechat/electron-client-ipc';
2
+ import { app as electronApp } from 'electron';
1
3
  import log from 'electron-log';
2
4
  import { autoUpdater } from 'electron-updater';
3
5
 
@@ -120,10 +122,22 @@ export class UpdaterManager {
120
122
  try {
121
123
  await autoUpdater.checkForUpdates();
122
124
  } catch (error) {
123
- logger.error('Error checking for updates:', error.message);
125
+ const message = error instanceof Error ? error.message : String(error);
126
+
127
+ // Edge case: Release tag exists but update manifest assets (latest/stable-*.yml) aren't uploaded yet.
128
+ // Treat this gap period as "no updates available" instead of a user-facing error.
129
+ if (this.isMissingUpdateManifestError(error)) {
130
+ logger.warn('[Updater] Update manifest not ready yet, treating as no update:', message);
131
+ if (manual) {
132
+ this.mainWindow.broadcast('manualUpdateNotAvailable', this.getCurrentUpdateInfo());
133
+ }
134
+ return;
135
+ }
136
+
137
+ logger.error('Error checking for updates:', message);
124
138
 
125
139
  if (manual) {
126
- this.mainWindow.broadcast('updateError', (error as Error).message);
140
+ this.mainWindow.broadcast('updateError', message);
127
141
  }
128
142
  } finally {
129
143
  this.checking = false;
@@ -397,6 +411,18 @@ export class UpdaterManager {
397
411
  });
398
412
 
399
413
  autoUpdater.on('error', async (err) => {
414
+ const message = err instanceof Error ? err.message : String(err);
415
+
416
+ // Edge case: Release tag exists but update manifest assets aren't uploaded yet.
417
+ // Skip fallback switching and avoid user-facing errors.
418
+ if (this.isMissingUpdateManifestError(err)) {
419
+ logger.warn('[Updater] Update manifest not ready yet, skipping error handling:', message);
420
+ if (this.isManualCheck) {
421
+ this.mainWindow.broadcast('manualUpdateNotAvailable', this.getCurrentUpdateInfo());
422
+ }
423
+ return;
424
+ }
425
+
400
426
  logger.error('Error in auto-updater:', err);
401
427
  logger.error('[Updater Error Context] Channel:', autoUpdater.channel);
402
428
  logger.error('[Updater Error Context] allowPrerelease:', autoUpdater.allowPrerelease);
@@ -436,4 +462,28 @@ export class UpdaterManager {
436
462
 
437
463
  logger.debug('Updater events registered');
438
464
  }
465
+
466
+ private isMissingUpdateManifestError(error: unknown): boolean {
467
+ const message = error instanceof Error ? error.message : String(error ?? '');
468
+ if (!message) return false;
469
+
470
+ // Expect patterns like:
471
+ // - "Cannot find latest-mac.yml ... HttpError: 404 ..."
472
+ // - "Cannot find stable.yml ... 404 ..."
473
+ if (!/cannot find/i.test(message)) return false;
474
+ if (!/\b404\b/.test(message)) return false;
475
+
476
+ // Match channel manifest filenames across platforms/architectures:
477
+ // latest.yml, latest-mac.yml, latest-linux.yml, stable.yml, stable-mac.yml, etc.
478
+ const manifestMatch = message.match(/\b(?:latest|stable)(?:-[\da-z]+)?\.yml\b/i);
479
+ return Boolean(manifestMatch);
480
+ }
481
+
482
+ private getCurrentUpdateInfo(): UpdateInfo {
483
+ const version = autoUpdater.currentVersion?.version || electronApp.getVersion();
484
+ return {
485
+ releaseDate: new Date().toISOString(),
486
+ version,
487
+ };
488
+ }
439
489
  }
@@ -31,6 +31,7 @@ vi.mock('electron-updater', () => ({
31
31
  autoInstallOnAppQuit: false,
32
32
  channel: 'stable',
33
33
  checkForUpdates: vi.fn(),
34
+ currentVersion: undefined as any,
34
35
  downloadUpdate: vi.fn(),
35
36
  forceDevUpdateConfig: false,
36
37
  logger: null as any,
@@ -46,6 +47,7 @@ vi.mock('electron', () => ({
46
47
  getAllWindows: mockGetAllWindows,
47
48
  },
48
49
  app: {
50
+ getVersion: vi.fn().mockReturnValue('0.0.0'),
49
51
  releaseSingleInstanceLock: mockReleaseSingleInstanceLock,
50
52
  },
51
53
  }));
@@ -108,6 +110,7 @@ describe('UpdaterManager', () => {
108
110
  (autoUpdater as any).allowPrerelease = false;
109
111
  (autoUpdater as any).allowDowngrade = false;
110
112
  (autoUpdater as any).forceDevUpdateConfig = false;
113
+ (autoUpdater as any).currentVersion = undefined;
111
114
 
112
115
  // Capture registered events
113
116
  registeredEvents = new Map();
@@ -212,6 +215,24 @@ describe('UpdaterManager', () => {
212
215
 
213
216
  expect(mockBroadcast).toHaveBeenCalledWith('updateError', 'Network error');
214
217
  });
218
+
219
+ it('should treat missing latest/stable yml 404 as not-available during manual check', async () => {
220
+ const error = new Error(
221
+ 'Cannot find latest-mac.yml in the latest release artifacts (https://github.com/lobehub/lobe-chat/releases/download/v2.0.0-next.311/latest-mac.yml): HttpError: 404',
222
+ );
223
+ vi.mocked(autoUpdater.checkForUpdates).mockRejectedValueOnce(error);
224
+
225
+ await updaterManager.checkForUpdates({ manual: true });
226
+
227
+ expect(mockBroadcast).toHaveBeenCalledWith(
228
+ 'manualUpdateNotAvailable',
229
+ expect.objectContaining({
230
+ releaseDate: expect.any(String),
231
+ version: expect.any(String),
232
+ }),
233
+ );
234
+ expect(mockBroadcast).not.toHaveBeenCalledWith('updateError', expect.anything());
235
+ });
215
236
  });
216
237
 
217
238
  describe('downloadUpdate', () => {
@@ -486,6 +507,26 @@ describe('UpdaterManager', () => {
486
507
 
487
508
  expect(mockBroadcast).not.toHaveBeenCalledWith('updateError', expect.anything());
488
509
  });
510
+
511
+ it('should not broadcast updateError for missing manifest 404 (gap period)', async () => {
512
+ vi.mocked(autoUpdater.checkForUpdates).mockResolvedValue({} as any);
513
+ await updaterManager.checkForUpdates({ manual: true });
514
+
515
+ const error = new Error(
516
+ 'Cannot find latest-mac.yml in the latest release artifacts (https://github.com/lobehub/lobe-chat/releases/download/v2.0.0-next.311/latest-mac.yml): HttpError: 404',
517
+ );
518
+ const handler = registeredEvents.get('error');
519
+ await handler?.(error);
520
+
521
+ expect(mockBroadcast).toHaveBeenCalledWith(
522
+ 'manualUpdateNotAvailable',
523
+ expect.objectContaining({
524
+ releaseDate: expect.any(String),
525
+ version: expect.any(String),
526
+ }),
527
+ );
528
+ expect(mockBroadcast).not.toHaveBeenCalledWith('updateError', expect.anything());
529
+ });
489
530
  });
490
531
  });
491
532
 
package/changelog/v1.json CHANGED
@@ -1,4 +1,14 @@
1
1
  [
2
+ {
3
+ "children": {},
4
+ "date": "2026-01-20",
5
+ "version": "2.0.0-next.326"
6
+ },
7
+ {
8
+ "children": {},
9
+ "date": "2026-01-20",
10
+ "version": "2.0.0-next.325"
11
+ },
2
12
  {
3
13
  "children": {
4
14
  "fixes": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/lobehub",
3
- "version": "2.0.0-next.324",
3
+ "version": "2.0.0-next.326",
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",
@@ -207,7 +207,7 @@
207
207
  "@lobehub/icons": "^4.0.2",
208
208
  "@lobehub/market-sdk": "0.29.1",
209
209
  "@lobehub/tts": "^4.0.2",
210
- "@lobehub/ui": "^4.22.0",
210
+ "@lobehub/ui": "^4.24.0",
211
211
  "@modelcontextprotocol/sdk": "^1.25.1",
212
212
  "@neondatabase/serverless": "^1.0.2",
213
213
  "@next/third-parties": "^16.1.1",
@@ -235,35 +235,6 @@ describe('SessionModel', () => {
235
235
  });
236
236
  });
237
237
 
238
- // describe('getAgentConfigById', () => {
239
- // it('should return agent config by id', async () => {
240
- // await serverDB.transaction(async (trx) => {
241
- // await trx.insert(agents).values([
242
- // { id: '1', userId, model: 'gpt-3.5-turbo' },
243
- // { id: '2', userId, model: 'gpt-3.5' },
244
- // ]);
245
- //
246
- // // @ts-ignore
247
- // await trx.insert(plugins).values([
248
- // { id: 1, userId, identifier: 'abc', title: 'A1', locale: 'en-US', manifest: {} },
249
- // { id: 2, userId, identifier: 'b2', title: 'A2', locale: 'en-US', manifest: {} },
250
- // ]);
251
- //
252
- // await trx.insert(agentsPlugins).values([
253
- // { agentId: '1', pluginId: 1 },
254
- // { agentId: '2', pluginId: 2 },
255
- // { agentId: '1', pluginId: 2 },
256
- // ]);
257
- // });
258
- //
259
- // const result = await sessionModel.getAgentConfigById('1');
260
- //
261
- // expect(result?.id).toBe('1');
262
- // expect(result?.plugins).toBe(['abc', 'b2']);
263
- // expect(result?.model).toEqual('gpt-3.5-turbo');
264
- // expect(result?.chatConfig).toBeDefined();
265
- // });
266
- // });
267
238
  describe('count', () => {
268
239
  it('should return the count of sessions for the user', async () => {
269
240
  // 创建测试数据
@@ -7,8 +7,6 @@ import { useTranslation } from 'react-i18next';
7
7
 
8
8
  import { useConversationStore } from '@/features/Conversation';
9
9
 
10
- // import { useSend } from '../../features/ChatInput/useSend';
11
-
12
10
  const styles = createStaticStyles(({ css, cssVar }) => ({
13
11
  card: css`
14
12
  padding-block: 8px;
@@ -16,42 +16,6 @@ const TocList = memo(() => {
16
16
  const { t } = useTranslation('discover');
17
17
  const { toc = [] } = useToc();
18
18
  const { activeTab = AssistantNavKey.Overview } = useQuery() as { activeTab: AssistantNavKey };
19
- // const { deploymentOptions = [], tools = [], prompts = [] } = useDetailContext();
20
- //
21
- // const schemaToc: AnchorProps['items'] = useMemo(() => {
22
- // return [
23
- // {
24
- // href: `#tools`,
25
- // key: `tools`,
26
- // level: 2,
27
- // title: t('mcp.details.schema.tools.title'),
28
- // },
29
- // ...tools.map((item) => ({
30
- // href: `#tools-${item.name}`,
31
- // key: `tools-${item.name}`,
32
- // level: 3,
33
- // title: item.name,
34
- // })),
35
- // {
36
- // href: `#prompts`,
37
- // key: `prompts`,
38
- // level: 2,
39
- // title: t('mcp.details.schema.prompts.title'),
40
- // },
41
- // ...prompts.map((item) => ({
42
- // href: `#prompts-${item.name}`,
43
- // key: `prompts-${item.name}`,
44
- // level: 3,
45
- // title: item.name,
46
- // })),
47
- // {
48
- // href: `#resources`,
49
- // key: `resources`,
50
- // level: 2,
51
- // title: t('mcp.details.schema.resources.title'),
52
- // },
53
- // ].filter(Boolean) as AnchorProps['items'];
54
- // }, [tools, prompts, t]);
55
19
 
56
20
  const items: AnchorProps['items'] | undefined = useMemo(() => {
57
21
  switch (activeTab) {
@@ -13,7 +13,6 @@ import { styles } from './Header/style';
13
13
 
14
14
  const Header = memo(() => {
15
15
  const location = useLocation();
16
- // const { activeKey } = useNav();
17
16
  const isHome = location.pathname === '/';
18
17
 
19
18
  const cssVariables: Record<string, string> = {
@@ -27,7 +26,6 @@ const Header = memo(() => {
27
26
  right={
28
27
  !isHome && (
29
28
  <>
30
- {/*{activeKey === DiscoverTab.Assistants && <MarketSourceSwitch />}*/}
31
29
  <SortButton />
32
30
  <UserAvatar />
33
31
  </>
@@ -41,12 +41,8 @@ const GroupMember = memo<GroupMemberProps>(({ addModalOpen, onAddModalOpenChange
41
41
  const toggleThread = useAgentGroupStore((s) => s.toggleThread);
42
42
  const pushPortalView = useChatStore((s) => s.pushPortalView);
43
43
 
44
- // Get members from store (excluding supervisor)
45
44
  const groupMembers = useAgentGroupStore(agentGroupSelectors.getGroupMembers(groupId || ''));
46
45
 
47
- // const [agentSettingsOpen, setAgentSettingsOpen] = useState(false);
48
- // const [selectedAgentId, setSelectedAgentId] = useState<string | undefined>();
49
-
50
46
  const handleAddMembers = async (selectedAgents: string[]) => {
51
47
  if (!groupId) {
52
48
  console.error('No active group to add members to');
@@ -18,8 +18,6 @@ import ThreadHydration from './ThreadHydration';
18
18
  import { useActionsBarConfig } from './useActionsBarConfig';
19
19
  import { useGroupContext } from './useGroupContext';
20
20
 
21
- // import { useGroupHooks } from './useGroupHooks';
22
-
23
21
  interface ConversationAreaProps {
24
22
  mobile?: boolean;
25
23
  }
@@ -45,18 +43,13 @@ const Conversation = memo<ConversationAreaProps>(({ mobile = false }) => {
45
43
  // Get operation state from ChatStore for reactive updates
46
44
  const operationState = useOperationState(context);
47
45
 
48
- // Get actionsBar config with branching support from ChatStore
49
46
  const actionsBarConfig = useActionsBarConfig();
50
47
 
51
- // Get group-specific hooks for send logic
52
- // const groupHooks = useGroupHooks(context);
53
-
54
48
  return (
55
49
  <ConversationProvider
56
50
  actionsBar={actionsBarConfig}
57
51
  context={context}
58
52
  hasInitMessages={!!messages}
59
- // hooks={groupHooks}
60
53
  messages={messages}
61
54
  onMessagesChange={(messages, ctx) => {
62
55
  replaceMessages(messages, { context: ctx });
@@ -35,7 +35,6 @@ const rightActions: ActionKeys[] = [];
35
35
  */
36
36
  const Desktop = memo((props: { targetMemberId?: string }) => {
37
37
  const { t } = useTranslation('chat');
38
- // const { send, generating, disabled, stop } = useSendGroupMessage();
39
38
 
40
39
  const isDMPortal = !!props.targetMemberId;
41
40
  const currentGroupMembers = useAgentGroupStore(agentGroupSelectors.currentGroupAgents, isEqual);
@@ -93,7 +92,6 @@ const Desktop = memo((props: { targetMemberId?: string }) => {
93
92
  useChatStore.setState({ inputMessage: content });
94
93
  }}
95
94
  rightActions={isDMPortal ? [] : rightActions}
96
- // sendButtonProps={{ disabled, generating, onStop: stop }}
97
95
  sendMenu={{
98
96
  items: sendMenuItems,
99
97
  }}
@@ -12,11 +12,9 @@ export enum GroupKey {
12
12
  }
13
13
 
14
14
  const Body = memo(() => {
15
- // const { enableKnowledgeBase } = useServerConfigStore(featureFlagsSelectors);
16
15
  return (
17
16
  <Flexbox paddingInline={4}>
18
17
  <Accordion defaultExpandedKeys={[GroupKey.Project, GroupKey.Agent]} gap={8}>
19
- {/*{enableKnowledgeBase && <Repo itemKey={GroupKey.Project} />}*/}
20
18
  <Agent itemKey={GroupKey.Agent} />
21
19
  <BottomMenu />
22
20
  </Accordion>
@@ -56,12 +56,6 @@ export const useDropdownMenu = ({
56
56
  label: t('rename'),
57
57
  onClick: () => toggleEditing(true),
58
58
  },
59
- // {
60
- // icon: <Icon icon={Copy} />,
61
- // key: 'copy',
62
- // label: t('pageList.copyContent', { ns: 'file' }),
63
- // onClick: handleCopy,
64
- // },
65
59
  {
66
60
  icon: <Icon icon={CopyPlus} />,
67
61
  key: 'duplicate',
@@ -32,21 +32,6 @@ export const useDropdownMenu = (): MenuProps['items'] => {
32
32
  }));
33
33
 
34
34
  return [
35
- // {
36
- // icon: <Icon icon={Check} style={{ opacity: !showOnlyPagesNotInLibrary ? 1 : 0 }} />,
37
- // key: 'all',
38
- // label: t('pageList.filter.all'),
39
- // onClick: () => setShowOnlyPagesNotInLibrary(false),
40
- // },
41
- // {
42
- // icon: <Icon icon={Check} style={{ opacity: showOnlyPagesNotInLibrary ? 1 : 0 }} />,
43
- // key: 'onlyInPages',
44
- // label: t('pageList.filter.onlyInPages'),
45
- // onClick: () => setShowOnlyPagesNotInLibrary(true),
46
- // },
47
- // {
48
- // type: 'divider' as const,
49
- // },
50
35
  {
51
36
  children: pageSizeItems,
52
37
  icon: <Icon icon={Hash} />,
@@ -141,11 +141,6 @@ export const DndContextWrapper = memo<PropsWithChildren>(({ children }) => {
141
141
  return;
142
142
  }
143
143
 
144
- // Save current drag data before clearing state
145
- // const draggedItemId = currentDrag.id;
146
- // const draggedItemData = currentDrag.data;
147
-
148
- // Clear drag state immediately for better UX
149
144
  setCurrentDrag(null);
150
145
 
151
146
  // Show loading toast
@@ -51,7 +51,6 @@ const ModelConfigModal = memo<ModelConfigModalProps>(({ open, setOpen }) => {
51
51
  setLoading(false);
52
52
  closeModal();
53
53
  } catch {
54
- /* */
55
54
  setLoading(false);
56
55
  }
57
56
  }}
@@ -240,16 +240,6 @@ const ModelItem = memo<ModelItemProps>(
240
240
  {...abilities}
241
241
  contextWindowTokens={contextWindowTokens}
242
242
  />
243
- {/*{removed && (*/}
244
- {/* <Tooltip*/}
245
- {/* overlayStyle={{ maxWidth: 300 }}*/}
246
- {/* placement={'top'}*/}
247
- {/* style={{ pointerEvents: 'none' }}*/}
248
- {/* title={t('ModelSelect.removed')}*/}
249
- {/* >*/}
250
- {/* <ActionIcon icon={Recycle} style={{ color: theme.colorWarning }} />*/}
251
- {/* </Tooltip>*/}
252
- {/*)}*/}
253
243
  </Flexbox>
254
244
  </Flexbox>
255
245
  <div>
@@ -3,7 +3,7 @@
3
3
  import { CheckCircleFilled } from '@ant-design/icons';
4
4
  import { type ChatMessageError, TraceNameMap } from '@lobechat/types';
5
5
  import { ModelIcon } from '@lobehub/icons';
6
- import { Alert, Button, Flexbox, Highlighter, Icon, Select } from '@lobehub/ui';
6
+ import { Alert, Button, Flexbox, Highlighter, Icon, LobeSelect as Select } from '@lobehub/ui';
7
7
  import { cssVar } from 'antd-style';
8
8
  import { Loader2Icon } from 'lucide-react';
9
9
  import { type ReactNode, memo, useEffect, useState } from 'react';
@@ -66,7 +66,6 @@ const Actions = memo<ActionProps>(({ group, id, openCreateGroupModal, parentType
66
66
  const { modal, message } = App.useApp();
67
67
 
68
68
  const isDefault = group === SessionDefaultGroup.Default;
69
- // const hasDivider = !isDefault || Object.keys(sessionByGroup).length > 0;
70
69
 
71
70
  const items = useMemo(
72
71
  () =>
@@ -52,8 +52,6 @@ const RootLayout = async ({ children, params }: RootLayoutProps) => {
52
52
  <head>
53
53
  {/* eslint-disable-next-line @typescript-eslint/no-use-before-define */}
54
54
  <script dangerouslySetInnerHTML={{ __html: `(${outdateBrowserScript.toString()})();` }} />
55
-
56
- {/* <script dangerouslySetInnerHTML={{ __html: 'setTimeout(() => {debugger}, 16)' }} /> */}
57
55
  {process.env.DEBUG_REACT_SCAN === '1' && (
58
56
  <Script
59
57
  crossOrigin={'anonymous'}
@@ -7,12 +7,6 @@ describe('getServerConfig', () => {
7
7
  vi.resetModules();
8
8
  });
9
9
 
10
- // it('correctly handles values for OPENAI_FUNCTION_REGIONS', () => {
11
- // process.env.OPENAI_FUNCTION_REGIONS = 'iad1,sfo1';
12
- // const config = getAppConfig();
13
- // expect(config.OPENAI_FUNCTION_REGIONS).toStrictEqual(['iad1', 'sfo1']);
14
- // });
15
-
16
10
  describe('index url', () => {
17
11
  it('should return default URLs when no environment variables are set', async () => {
18
12
  const { getAppConfig } = await import('../app');