♻️ refactor: rename browser identifier from 'chat' to 'app' (#10940)

Rename the main browser identifier from 'chat' to 'app' to better represent its purpose as the main application window. Also update the initial path from '/agent' to '/' for the root route.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Innei
2025-12-24 20:43:11 +08:00
committed by GitHub
parent e5f3a58056
commit dc870c7635
5 changed files with 69 additions and 64 deletions

View File

@@ -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,

View File

@@ -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 {

View File

@@ -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,

View File

@@ -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() {

View File

@@ -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();
});
});