Skip to content

Commit e7aee4c

Browse files
committed
Add viewport and network tools to browser automation
Introduces two new browser tools: browser_set_viewport for setting or clearing the browser viewport size using CDP, and browser_get_network_requests for retrieving captured network requests and responses. Updates tool routing, type definitions, documentation, and tool registration to support these features. Also replaces browser_get_cdp_info with browser_get_state for improved browser state reporting.
1 parent 1e567bf commit e7aee4c

8 files changed

Lines changed: 635 additions & 110 deletions

File tree

src/vs/workbench/contrib/roopik/electron-main/channel/roopikToolsChannel.ts

Lines changed: 108 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@
1717
* Tool Naming Convention: category_action (e.g., browser_navigate, component_add)
1818
*
1919
* Tool Categories:
20-
* - Browser Tools (10): browser_open, browser_navigate, browser_reload, browser_screenshot,
21-
* browser_execute_script, browser_inspect_element, browser_get_errors,
22-
* browser_get_console_logs, browser_get_performance, browser_get_cdp_info
20+
* - Browser Tools (14): browser_open, browser_close, browser_navigate, browser_reload, browser_screenshot,
21+
* browser_action_input, browser_execute_script, browser_inspect_element, browser_get_errors,
22+
* browser_get_console_logs, browser_get_performance, browser_get_state,
23+
* browser_set_viewport, browser_get_network_requests
2324
* - Project Tools (3): project_get_active, project_start, project_stop
2425
* - Canvas Tools (3): canvas_list, canvas_get_active, canvas_create
2526
* - Component Tools (6): component_add, component_add_batch, component_remove,
@@ -116,8 +117,14 @@ export class RoopikToolsChannel implements IServerChannel {
116117
case 'browser_get_performance':
117118
return this.handleBrowserGetPerformance();
118119

119-
case 'browser_get_cdp_info':
120-
return this.handleBrowserGetCdpInfo();
120+
case 'browser_get_state':
121+
return this.handleBrowserGetState();
122+
123+
case 'browser_set_viewport':
124+
return this.handleSetViewport(arg as { width?: number; height?: number; deviceScaleFactor?: number; mobile?: boolean } | undefined);
125+
126+
case 'browser_get_network_requests':
127+
return this.handleGetNetworkRequests(arg as { urlFilter?: string; method?: string; statusFilter?: string; limit?: number });
121128

122129
// ============================================================
123130
// Project Tools (3)
@@ -363,69 +370,32 @@ export class RoopikToolsChannel implements IServerChannel {
363370
}
364371

365372
/**
366-
* Get CDP connection info for external agents to connect to the browser.
373+
* Get browser state information.
367374
*
368-
* Returns information about the current browser state and how external
369-
* agents (Claude Code, Copilot, etc.) can interact with it.
375+
* Returns the current browser status including URL, title, loading state,
376+
* and dev server info if running.
370377
*
371-
* Note: Electron's BrowserView doesn't expose a WebSocket server by default.
372-
* External agents should use Roopik's IPC tools instead of direct CDP connection.
373-
* This tool provides context about what's available.
378+
* Note: Use tools/list for available tools, not this method.
374379
*/
375-
private async handleBrowserGetCdpInfo(): Promise<RoopikToolResult> {
380+
private async handleBrowserGetState(): Promise<RoopikToolResult> {
376381
const browserViewId = this.browserViewService.getActiveBrowserViewId();
377382

378383
// Get dev server info if running
379384
const runningServer = await this.devServerService.getRunningServer();
380385

381-
const availableTools = [
382-
// Browser tools
383-
'browser_open',
384-
'browser_navigate',
385-
'browser_reload',
386-
'browser_screenshot',
387-
'browser_execute_script',
388-
'browser_inspect_element',
389-
'browser_get_errors',
390-
'browser_get_console_logs',
391-
'browser_get_performance',
392-
'browser_get_cdp_info',
393-
// Project tools
394-
'project_get_active',
395-
'project_start',
396-
'project_stop',
397-
// Canvas tools
398-
'canvas_list',
399-
'canvas_get_active',
400-
'canvas_create',
401-
// Component tools
402-
'component_add',
403-
'component_add_batch',
404-
'component_remove',
405-
'component_get_info',
406-
'component_list',
407-
'component_rebuild'
408-
];
409-
410386
if (browserViewId === undefined) {
411387
return {
412388
success: true,
413389
data: {
414390
browserOpen: false,
391+
devServerRunning: !!runningServer,
415392
devServer: runningServer ? {
416-
running: true,
417393
url: runningServer.url,
418394
projectRoot: runningServer.projectRoot,
419395
port: runningServer.port,
420396
framework: runningServer.framework
421397
} : null,
422-
cdpAccess: {
423-
// Electron BrowserView uses in-process debugger, not WebSocket
424-
type: 'internal',
425-
note: 'Roopik uses Electron in-process CDP. External agents should use Roopik IPC tools.',
426-
availableTools
427-
},
428-
message: 'No browser open. Use browser_open to open a browser.'
398+
message: 'No browser open. Use browser_open or project_start to open a browser.'
429399
}
430400
};
431401
}
@@ -441,27 +411,14 @@ export class RoopikToolsChannel implements IServerChannel {
441411
currentUrl: navState.url,
442412
title: navState.title,
443413
isLoading: navState.isLoading,
414+
devServerRunning: !!runningServer,
444415
devServer: runningServer ? {
445-
running: true,
446416
url: runningServer.url,
447417
projectRoot: runningServer.projectRoot,
448418
port: runningServer.port,
449419
framework: runningServer.framework
450420
} : null,
451-
cdpAccess: {
452-
// Electron BrowserView uses in-process debugger
453-
type: 'internal',
454-
note: 'Roopik uses Electron in-process CDP. External agents should use Roopik IPC tools instead of WebSocket CDP.',
455-
availableTools,
456-
// For future: If we want to expose remote debugging, we'd need to:
457-
// 1. Start Chromium with --remote-debugging-port
458-
// 2. Or use a CDP proxy that exposes WebSocket
459-
remoteDebugging: {
460-
enabled: false,
461-
reason: 'Electron BrowserView does not expose WebSocket CDP by default. Use Roopik IPC tools for full CDP access.'
462-
}
463-
},
464-
message: `Browser open at ${navState.url}. Use Roopik tools for CDP operations.`
421+
message: `Browser open at ${navState.url}`
465422
}
466423
};
467424
}
@@ -769,6 +726,93 @@ export class RoopikToolsChannel implements IServerChannel {
769726
};
770727
}
771728

729+
/**
730+
* Set or clear browser viewport override.
731+
* Provide width/height to set a specific size. Call with no args to clear and restore natural size.
732+
* Uses CDP Emulation.setDeviceMetricsOverride / clearDeviceMetricsOverride.
733+
*/
734+
private async handleSetViewport(args?: {
735+
width?: number;
736+
height?: number;
737+
deviceScaleFactor?: number;
738+
mobile?: boolean;
739+
}): Promise<RoopikToolResult> {
740+
const browserViewId = this.browserViewService.getActiveBrowserViewId();
741+
if (browserViewId === undefined) {
742+
return {
743+
success: false,
744+
error: 'No browser is open. Use browser_open or project_start first.'
745+
};
746+
}
747+
748+
try {
749+
// Attach debugger if not already attached
750+
await this.browserViewService.attachDebugger(browserViewId);
751+
752+
// If width/height not provided, clear the viewport override
753+
if (!args?.width || !args?.height) {
754+
await this.browserViewService.sendCDPCommand(browserViewId, 'Emulation.clearDeviceMetricsOverride');
755+
756+
return {
757+
success: true,
758+
data: {
759+
width: 0,
760+
height: 0,
761+
deviceScaleFactor: 1,
762+
mobile: false,
763+
message: 'Viewport override cleared - restored to natural browser size'
764+
}
765+
};
766+
}
767+
768+
const { width, height, deviceScaleFactor = 1, mobile = false } = args;
769+
770+
// Set viewport via CDP Emulation
771+
await this.browserViewService.sendCDPCommand(browserViewId, 'Emulation.setDeviceMetricsOverride', {
772+
width,
773+
height,
774+
deviceScaleFactor,
775+
mobile
776+
});
777+
778+
return {
779+
success: true,
780+
data: {
781+
width,
782+
height,
783+
deviceScaleFactor,
784+
mobile,
785+
message: `Viewport set to ${width}x${height} (scale: ${deviceScaleFactor}, mobile: ${mobile})`
786+
}
787+
};
788+
} catch (error) {
789+
return {
790+
success: false,
791+
error: `Failed to set viewport: ${error instanceof Error ? error.message : String(error)}`
792+
};
793+
}
794+
}
795+
796+
/**
797+
* Get network requests captured by CDP.
798+
* Note: This requires CDP Network domain to be enabled and monitoring active.
799+
* For IPC channel, this delegates to the MCP infrastructure which handles CDP monitoring.
800+
*/
801+
private async handleGetNetworkRequests(_args: {
802+
urlFilter?: string;
803+
method?: string;
804+
statusFilter?: string;
805+
limit?: number;
806+
}): Promise<RoopikToolResult> {
807+
// Network request monitoring requires persistent CDP event listeners
808+
// which are currently managed by the MCP browserExecutor's cdpMonitors.
809+
// For native IPC, we would need to centralize CDP monitoring in BrowserViewService.
810+
return {
811+
success: false,
812+
error: 'Network request monitoring requires CDP monitoring enabled. This feature is available via MCP tools. For native IPC, use browser_execute_script to query performance.getEntries() for network timing.'
813+
};
814+
}
815+
772816
// ========================================================================
773817
// Project Tool Handlers
774818
// ========================================================================

0 commit comments

Comments
 (0)