diff --git a/apps/desktop/src/main/appBrowsers.ts b/apps/desktop/src/main/appBrowsers.ts index 3da32f84a1..89f3a0f3e8 100644 --- a/apps/desktop/src/main/appBrowsers.ts +++ b/apps/desktop/src/main/appBrowsers.ts @@ -1,18 +1,18 @@ import type { BrowserWindowOpts } from './core/browser/Browser'; export const BrowsersIdentifiers = { - chat: 'chat', + app: 'app', devtools: 'devtools', }; export const appBrowsers = { - chat: { + app: { autoHideMenuBar: true, height: 800, - identifier: 'chat', + identifier: 'app', keepAlive: true, minWidth: 400, - path: '/agent', + path: '/', showOnInit: true, titleBarStyle: 'hidden', vibrancy: 'under-window', @@ -25,7 +25,7 @@ export const appBrowsers = { identifier: 'devtools', maximizable: false, minWidth: 400, - parentIdentifier: 'chat', + parentIdentifier: 'app', path: '/desktop/devtools', titleBarStyle: 'hiddenInset', vibrancy: 'under-window', @@ -76,7 +76,7 @@ export const windowTemplates = { height: 600, keepAlive: false, // Multi-instance windows don't need to stay alive minWidth: 400, - parentIdentifier: 'chat', + parentIdentifier: 'app', titleBarStyle: 'hidden', vibrancy: 'under-window', width: 900, diff --git a/apps/desktop/src/main/controllers/McpInstallCtr.ts b/apps/desktop/src/main/controllers/McpInstallCtr.ts index 1450ec8e9f..e71b050792 100644 --- a/apps/desktop/src/main/controllers/McpInstallCtr.ts +++ b/apps/desktop/src/main/controllers/McpInstallCtr.ts @@ -138,7 +138,7 @@ export default class McpInstallController extends ControllerModule { // 通过应用实例广播到前端 if (this.app?.browserManager) { - this.app.browserManager.broadcastToWindow('chat', 'mcpInstallRequest', installRequest); + this.app.browserManager.broadcastToWindow('app', 'mcpInstallRequest', installRequest); logger.debug(`🔧 [McpInstall] Install request broadcasted successfully`); return true; } else { diff --git a/apps/desktop/src/main/controllers/__tests__/McpInstallCtr.test.ts b/apps/desktop/src/main/controllers/__tests__/McpInstallCtr.test.ts index 0d092d5410..2bf50cceea 100644 --- a/apps/desktop/src/main/controllers/__tests__/McpInstallCtr.test.ts +++ b/apps/desktop/src/main/controllers/__tests__/McpInstallCtr.test.ts @@ -84,7 +84,7 @@ describe('McpInstallController', () => { expect(result).toBe(true); expect(mockBrowserManager.broadcastToWindow).toHaveBeenCalledWith( - 'chat', + 'app', 'mcpInstallRequest', { marketId: 'lobehub', @@ -143,7 +143,7 @@ describe('McpInstallController', () => { expect(result).toBe(true); expect(mockBrowserManager.broadcastToWindow).toHaveBeenCalledWith( - 'chat', + 'app', 'mcpInstallRequest', { marketId: 'third-party', @@ -162,7 +162,7 @@ describe('McpInstallController', () => { expect(result).toBe(true); expect(mockBrowserManager.broadcastToWindow).toHaveBeenCalledWith( - 'chat', + 'app', 'mcpInstallRequest', { marketId: 'third-party', @@ -235,7 +235,7 @@ describe('McpInstallController', () => { expect(result).toBe(true); expect(mockBrowserManager.broadcastToWindow).toHaveBeenCalledWith( - 'chat', + 'app', 'mcpInstallRequest', expect.objectContaining({ schema: schemaWithOptionalFields, diff --git a/apps/desktop/src/main/core/browser/BrowserManager.ts b/apps/desktop/src/main/core/browser/BrowserManager.ts index 63cd5440de..5f3d9b0fa6 100644 --- a/apps/desktop/src/main/core/browser/BrowserManager.ts +++ b/apps/desktop/src/main/core/browser/BrowserManager.ts @@ -5,6 +5,7 @@ import { createLogger } from '@/utils/logger'; import { AppBrowsersIdentifiers, + BrowsersIdentifiers, WindowTemplateIdentifiers, appBrowsers, windowTemplates, @@ -29,7 +30,7 @@ export class BrowserManager { } getMainWindow() { - return this.retrieveByIdentifier('chat'); + return this.retrieveByIdentifier(BrowsersIdentifiers.app); } showMainWindow() { diff --git a/apps/desktop/src/main/core/browser/__tests__/BrowserManager.test.ts b/apps/desktop/src/main/core/browser/__tests__/BrowserManager.test.ts index 171f2eecbd..a646a2f9a7 100644 --- a/apps/desktop/src/main/core/browser/__tests__/BrowserManager.test.ts +++ b/apps/desktop/src/main/core/browser/__tests__/BrowserManager.test.ts @@ -33,10 +33,10 @@ const { MockBrowser, mockAppBrowsers, mockWindowTemplates } = vi.hoisted(() => { return { MockBrowser, mockAppBrowsers: { - chat: { - identifier: 'chat', + app: { + identifier: 'app', keepAlive: true, - path: '/chat', + path: '/app', }, settings: { identifier: 'settings', @@ -61,6 +61,10 @@ vi.mock('../Browser', () => ({ // Mock appBrowsers config vi.mock('../../../appBrowsers', () => ({ + BrowsersIdentifiers: { + app: 'app', + devtools: 'devtools', + }, appBrowsers: mockAppBrowsers, windowTemplates: mockWindowTemplates, })); @@ -102,10 +106,10 @@ describe('BrowserManager', () => { }); describe('getMainWindow', () => { - it('should return chat window', () => { + it('should return app window', () => { const mainWindow = manager.getMainWindow(); - expect(mainWindow.identifier).toBe('chat'); + expect(mainWindow.identifier).toBe('app'); }); }); @@ -113,27 +117,27 @@ describe('BrowserManager', () => { it('should show the main window', () => { manager.showMainWindow(); - const chatBrowser = manager.browsers.get('chat'); - expect(chatBrowser?.show).toHaveBeenCalled(); + const appBrowser = manager.browsers.get('app'); + expect(appBrowser?.show).toHaveBeenCalled(); }); }); describe('retrieveByIdentifier', () => { it('should return existing browser', () => { // First call creates the browser - const browser1 = manager.retrieveByIdentifier('chat'); + const browser1 = manager.retrieveByIdentifier('app'); // Second call should return same instance - const browser2 = manager.retrieveByIdentifier('chat'); + const browser2 = manager.retrieveByIdentifier('app'); expect(browser1).toBe(browser2); expect(MockBrowser).toHaveBeenCalledTimes(1); }); it('should create static browser when not exists', () => { - const browser = manager.retrieveByIdentifier('chat'); + const browser = manager.retrieveByIdentifier('app'); - expect(MockBrowser).toHaveBeenCalledWith(mockAppBrowsers.chat, mockApp); - expect(browser.identifier).toBe('chat'); + expect(MockBrowser).toHaveBeenCalledWith(mockAppBrowsers.app, mockApp); + expect(browser.identifier).toBe('app'); }); it('should throw error for non-static browser that does not exist', () => { @@ -188,13 +192,13 @@ describe('BrowserManager', () => { it('should return windows matching template prefix', () => { manager.createMultiInstanceWindow('popup' as any, '/path1', 'popup_1'); manager.createMultiInstanceWindow('popup' as any, '/path2', 'popup_2'); - manager.retrieveByIdentifier('chat'); // This should not be included + manager.retrieveByIdentifier('app'); // This should not be included const popupWindows = manager.getWindowsByTemplate('popup'); expect(popupWindows).toContain('popup_1'); expect(popupWindows).toContain('popup_2'); - expect(popupWindows).not.toContain('chat'); + expect(popupWindows).not.toContain('app'); }); it('should return empty array when no matching windows', () => { @@ -228,23 +232,23 @@ describe('BrowserManager', () => { it('should initialize keepAlive browsers', () => { manager.initializeBrowsers(); - // chat has keepAlive: true, settings has keepAlive: false - expect(manager.browsers.has('chat')).toBe(true); + // app has keepAlive: true, settings has keepAlive: false + expect(manager.browsers.has('app')).toBe(true); expect(manager.browsers.has('settings')).toBe(false); }); }); describe('broadcastToAllWindows', () => { it('should broadcast to all browsers', () => { - manager.retrieveByIdentifier('chat'); + manager.retrieveByIdentifier('app'); manager.retrieveByIdentifier('settings'); manager.broadcastToAllWindows('updateAvailable' as any, { version: '1.0.0' } as any); - const chatBrowser = manager.browsers.get('chat'); + const appBrowser = manager.browsers.get('app'); const settingsBrowser = manager.browsers.get('settings'); - expect(chatBrowser?.broadcast).toHaveBeenCalledWith('updateAvailable', { version: '1.0.0' }); + expect(appBrowser?.broadcast).toHaveBeenCalledWith('updateAvailable', { version: '1.0.0' }); expect(settingsBrowser?.broadcast).toHaveBeenCalledWith('updateAvailable', { version: '1.0.0', }); @@ -253,15 +257,15 @@ describe('BrowserManager', () => { describe('broadcastToWindow', () => { it('should broadcast to specific window', () => { - manager.retrieveByIdentifier('chat'); + manager.retrieveByIdentifier('app'); manager.retrieveByIdentifier('settings'); - const chatBrowser = manager.browsers.get('chat'); + const appBrowser = manager.browsers.get('app'); const settingsBrowser = manager.browsers.get('settings'); - manager.broadcastToWindow('chat', 'updateAvailable' as any, { version: '1.0.0' } as any); + manager.broadcastToWindow('app', 'updateAvailable' as any, { version: '1.0.0' } as any); - expect(chatBrowser?.broadcast).toHaveBeenCalledWith('updateAvailable', { version: '1.0.0' }); + expect(appBrowser?.broadcast).toHaveBeenCalledWith('updateAvailable', { version: '1.0.0' }); expect(settingsBrowser?.broadcast).not.toHaveBeenCalled(); }); @@ -274,35 +278,35 @@ describe('BrowserManager', () => { describe('redirectToPage', () => { it('should load URL and show window', async () => { - const browser = await manager.redirectToPage('chat', 'agent'); + const browser = await manager.redirectToPage('app', 'agent'); expect(browser.hide).toHaveBeenCalled(); - expect(browser.loadUrl).toHaveBeenCalledWith('/chat/agent'); + expect(browser.loadUrl).toHaveBeenCalledWith('/app/agent'); expect(browser.show).toHaveBeenCalled(); }); it('should handle subPath correctly', async () => { - const browser = await manager.redirectToPage('chat', 'settings/profile'); + const browser = await manager.redirectToPage('app', 'settings/profile'); - expect(browser.loadUrl).toHaveBeenCalledWith('/chat/settings/profile'); + expect(browser.loadUrl).toHaveBeenCalledWith('/app/settings/profile'); }); it('should handle search parameters', async () => { - const browser = await manager.redirectToPage('chat', 'agent', 'id=123'); + const browser = await manager.redirectToPage('app', 'agent', 'id=123'); - expect(browser.loadUrl).toHaveBeenCalledWith('/chat/agent?id=123'); + expect(browser.loadUrl).toHaveBeenCalledWith('/app/agent?id=123'); }); it('should handle search parameters starting with ?', async () => { - const browser = await manager.redirectToPage('chat', undefined, '?id=123'); + const browser = await manager.redirectToPage('app', undefined, '?id=123'); - expect(browser.loadUrl).toHaveBeenCalledWith('/chat?id=123'); + expect(browser.loadUrl).toHaveBeenCalledWith('/app?id=123'); }); it('should handle no subPath', async () => { - const browser = await manager.redirectToPage('chat'); + const browser = await manager.redirectToPage('app'); - expect(browser.loadUrl).toHaveBeenCalledWith('/chat'); + expect(browser.loadUrl).toHaveBeenCalledWith('/app'); }); it('should throw error on failure', async () => { @@ -315,7 +319,7 @@ describe('BrowserManager', () => { hide: vi.fn(), identifier: options.identifier, loadUrl: vi.fn().mockRejectedValue(mockError), - options: { path: '/chat' }, + options: { path: '/app' }, show: vi.fn(), webContents: { id: 1 }, })); @@ -323,18 +327,18 @@ describe('BrowserManager', () => { // Clear the browser cache manager.browsers.clear(); - await expect(manager.redirectToPage('chat', 'agent')).rejects.toThrow('Load failed'); + await expect(manager.redirectToPage('app', 'agent')).rejects.toThrow('Load failed'); }); }); describe('window operations', () => { describe('closeWindow', () => { it('should close specified window', () => { - manager.retrieveByIdentifier('chat'); + manager.retrieveByIdentifier('app'); - manager.closeWindow('chat'); + manager.closeWindow('app'); - const browser = manager.browsers.get('chat'); + const browser = manager.browsers.get('app'); expect(browser?.close).toHaveBeenCalled(); }); @@ -345,33 +349,33 @@ describe('BrowserManager', () => { describe('minimizeWindow', () => { it('should minimize specified window', () => { - manager.retrieveByIdentifier('chat'); + manager.retrieveByIdentifier('app'); - manager.minimizeWindow('chat'); + manager.minimizeWindow('app'); - const browser = manager.browsers.get('chat'); + const browser = manager.browsers.get('app'); expect(browser?.browserWindow.minimize).toHaveBeenCalled(); }); }); describe('maximizeWindow', () => { it('should maximize when not maximized', () => { - manager.retrieveByIdentifier('chat'); - const browser = manager.browsers.get('chat'); + manager.retrieveByIdentifier('app'); + const browser = manager.browsers.get('app'); browser!.browserWindow.isMaximized = vi.fn().mockReturnValue(false); - manager.maximizeWindow('chat'); + manager.maximizeWindow('app'); expect(browser?.browserWindow.maximize).toHaveBeenCalled(); expect(browser?.browserWindow.unmaximize).not.toHaveBeenCalled(); }); it('should unmaximize when already maximized', () => { - manager.retrieveByIdentifier('chat'); - const browser = manager.browsers.get('chat'); + manager.retrieveByIdentifier('app'); + const browser = manager.browsers.get('app'); browser!.browserWindow.isMaximized = vi.fn().mockReturnValue(true); - manager.maximizeWindow('chat'); + manager.maximizeWindow('app'); expect(browser?.browserWindow.unmaximize).toHaveBeenCalled(); expect(browser?.browserWindow.maximize).not.toHaveBeenCalled(); @@ -381,12 +385,12 @@ describe('BrowserManager', () => { describe('getIdentifierByWebContents', () => { it('should return identifier for known webContents', () => { - const browser = manager.retrieveByIdentifier('chat'); + const browser = manager.retrieveByIdentifier('app'); const webContents = browser.browserWindow.webContents; const identifier = manager.getIdentifierByWebContents(webContents as any); - expect(identifier).toBe('chat'); + expect(identifier).toBe('app'); }); it('should return null for unknown webContents', () => { @@ -400,15 +404,15 @@ describe('BrowserManager', () => { describe('handleAppThemeChange', () => { it('should notify all browsers of theme change', () => { - manager.retrieveByIdentifier('chat'); + manager.retrieveByIdentifier('app'); manager.retrieveByIdentifier('settings'); manager.handleAppThemeChange(); - const chatBrowser = manager.browsers.get('chat'); + const appBrowser = manager.browsers.get('app'); const settingsBrowser = manager.browsers.get('settings'); - expect(chatBrowser?.handleAppThemeChange).toHaveBeenCalled(); + expect(appBrowser?.handleAppThemeChange).toHaveBeenCalled(); expect(settingsBrowser?.handleAppThemeChange).toHaveBeenCalled(); }); });