feat(browser): implement experimental browser agent (#19284)

This commit is contained in:
Gaurav
2026-02-24 09:22:09 -08:00
committed by GitHub
parent 182c858e67
commit 9e95b8b3c5
23 changed files with 3506 additions and 1 deletions
+68
View File
@@ -1347,6 +1347,74 @@ describe('Server Config (config.ts)', () => {
expect(mockCoreEvents.emitFeedback).not.toHaveBeenCalled();
});
});
describe('BrowserAgentConfig', () => {
it('should return default browser agent config when not provided', () => {
const config = new Config(baseParams);
const browserConfig = config.getBrowserAgentConfig();
expect(browserConfig.enabled).toBe(false);
expect(browserConfig.model).toBeUndefined();
expect(browserConfig.customConfig.sessionMode).toBe('persistent');
expect(browserConfig.customConfig.headless).toBe(false);
expect(browserConfig.customConfig.profilePath).toBeUndefined();
expect(browserConfig.customConfig.visualModel).toBeUndefined();
});
it('should return custom browser agent config from agents.overrides', () => {
const params: ConfigParameters = {
...baseParams,
agents: {
overrides: {
browser_agent: {
enabled: true,
modelConfig: { model: 'custom-model' },
},
},
browser: {
sessionMode: 'existing',
headless: true,
profilePath: '/path/to/profile',
visualModel: 'custom-visual-model',
},
},
};
const config = new Config(params);
const browserConfig = config.getBrowserAgentConfig();
expect(browserConfig.enabled).toBe(true);
expect(browserConfig.model).toBe('custom-model');
expect(browserConfig.customConfig.sessionMode).toBe('existing');
expect(browserConfig.customConfig.headless).toBe(true);
expect(browserConfig.customConfig.profilePath).toBe('/path/to/profile');
expect(browserConfig.customConfig.visualModel).toBe(
'custom-visual-model',
);
});
it('should apply defaults for partial custom config', () => {
const params: ConfigParameters = {
...baseParams,
agents: {
overrides: {
browser_agent: {
enabled: true,
},
},
browser: {
headless: true,
},
},
};
const config = new Config(params);
const browserConfig = config.getBrowserAgentConfig();
expect(browserConfig.enabled).toBe(true);
expect(browserConfig.customConfig.headless).toBe(true);
// Defaults for unspecified fields
expect(browserConfig.customConfig.sessionMode).toBe('persistent');
});
});
});
describe('setApprovalMode with folder trust', () => {
+61
View File
@@ -198,6 +198,10 @@ export interface AgentRunConfig {
maxTurns?: number;
}
/**
* Override configuration for a specific agent.
* Generic fields (modelConfig, runConfig, enabled) are standard across all agents.
*/
export interface AgentOverride {
modelConfig?: ModelConfig;
runConfig?: AgentRunConfig;
@@ -206,6 +210,7 @@ export interface AgentOverride {
export interface AgentSettings {
overrides?: Record<string, AgentOverride>;
browser?: BrowserAgentCustomConfig;
}
export interface CustomTheme {
@@ -259,6 +264,30 @@ export interface CustomTheme {
GradientColors?: string[];
}
/**
* Browser agent custom configuration.
* Used in agents.browser
*
* IMPORTANT: Keep in sync with the browser settings schema in
* packages/cli/src/config/settingsSchema.ts (agents.browser.properties).
*/
export interface BrowserAgentCustomConfig {
/**
* Session mode:
* - 'persistent': Launch Chrome with a persistent profile at ~/.cache/chrome-devtools-mcp/ (default)
* - 'isolated': Launch Chrome with a temporary profile, cleaned up after session
* - 'existing': Attach to an already-running Chrome instance (requires remote debugging
* enabled at chrome://inspect/#remote-debugging)
*/
sessionMode?: 'isolated' | 'persistent' | 'existing';
/** Run browser in headless mode. Default: false */
headless?: boolean;
/** Path to Chrome profile directory for session persistence. */
profilePath?: string;
/** Model override for the visual agent. */
visualModel?: string;
}
/**
* All information required in CLI to handle an extension. Defined in Core so
* that the collection of loaded, active, and inactive extensions can be passed
@@ -2541,6 +2570,38 @@ export class Config {
return this.enableHooksUI;
}
/**
* Get override settings for a specific agent.
* Reads from agents.overrides.<agentName>.
*/
getAgentOverride(agentName: string): AgentOverride | undefined {
return this.getAgentsSettings()?.overrides?.[agentName];
}
/**
* Get browser agent configuration.
* Combines generic AgentOverride fields with browser-specific customConfig.
* This is the canonical way to access browser agent settings.
*/
getBrowserAgentConfig(): {
enabled: boolean;
model?: string;
customConfig: BrowserAgentCustomConfig;
} {
const override = this.getAgentOverride('browser_agent');
const customConfig = this.getAgentsSettings()?.browser ?? {};
return {
enabled: override?.enabled ?? false,
model: override?.modelConfig?.model,
customConfig: {
sessionMode: customConfig.sessionMode ?? 'persistent',
headless: customConfig.headless ?? false,
profilePath: customConfig.profilePath,
visualModel: customConfig.visualModel,
},
};
}
async createToolRegistry(): Promise<ToolRegistry> {
const registry = new ToolRegistry(this, this.messageBus);