Add Browserbase support for remote browser over CDP (#3)
* Add Browserbase support for remote browser over CDP When BROWSERBASE_API_KEY and BROWSERBASE_PROJECT_ID env vars are set, connect to a Browserbase session via CDP instead of launching a local browser. * Update URLs to browserbase repo * Add Browserbase support for remote browser over CDP When BROWSERBASE_API_KEY and BROWSERBASE_PROJECT_ID env vars are set, connect to a Browserbase session via CDP instead of launching a local browser. * Update link to Browserbase Dashboard in README * bump browserbase sdk to latest version * remove sdk as a dep * change name back to vercel labs * added try catch blocks, functions to close session * revert package names * remove extra if statement --------- Co-authored-by: Kylejeong2 <kylejeong21@gmail.com>
This commit is contained in:
@@ -657,6 +657,23 @@ curl -o .claude/skills/agent-browser/SKILL.md \
|
||||
https://raw.githubusercontent.com/vercel-labs/agent-browser/main/skills/agent-browser/SKILL.md
|
||||
```
|
||||
|
||||
## Integrations
|
||||
|
||||
### Browserbase
|
||||
|
||||
[Browserbase](https://browserbase.com) provides remote browser infrastructure to make deployment of agentic browsing agents easy. Use it when running the agent-browser CLI in an environment where a local browser isn't feasible.
|
||||
|
||||
To enable Browserbase, set these environment variables:
|
||||
|
||||
```bash
|
||||
export BROWSERBASE_API_KEY="your-api-key"
|
||||
export BROWSERBASE_PROJECT_ID="your-project-id"
|
||||
```
|
||||
|
||||
When both variables are set, agent-browser automatically connects to a Browserbase session instead of launching a local browser. All commands work identically.
|
||||
|
||||
Get your API key and project ID from the [Browserbase Dashboard](https://browserbase.com/overview).
|
||||
|
||||
## License
|
||||
|
||||
Apache-2.0
|
||||
|
||||
+92
-2
@@ -70,6 +70,8 @@ export class BrowserManager {
|
||||
private browser: Browser | null = null;
|
||||
private cdpPort: number | null = null;
|
||||
private isPersistentContext: boolean = false;
|
||||
private browserbaseSessionId: string | null = null;
|
||||
private browserbaseApiKey: string | null = null;
|
||||
private contexts: BrowserContext[] = [];
|
||||
private pages: Page[] = [];
|
||||
private activePageIndex: number = 0;
|
||||
@@ -642,6 +644,79 @@ export class BrowserManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close a Browserbase session via API
|
||||
*/
|
||||
private async closeBrowserbaseSession(sessionId: string, apiKey: string): Promise<void> {
|
||||
await fetch(`https://api.browserbase.com/v1/sessions/${sessionId}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'X-BB-API-Key': apiKey,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to Browserbase remote browser via CDP.
|
||||
* Returns true if connected, false if credentials not available.
|
||||
*/
|
||||
private async connectToBrowserbase(): Promise<boolean> {
|
||||
const browserbaseApiKey = process.env.BROWSERBASE_API_KEY;
|
||||
const browserbaseProjectId = process.env.BROWSERBASE_PROJECT_ID;
|
||||
|
||||
if (!browserbaseApiKey || !browserbaseProjectId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const response = await fetch('https://api.browserbase.com/v1/sessions', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-BB-API-Key': browserbaseApiKey,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
projectId: browserbaseProjectId,
|
||||
}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to create Browserbase session: ${response.statusText}`);
|
||||
}
|
||||
|
||||
const session = await response.json() as { id: string; connectUrl: string };
|
||||
|
||||
const browser = await chromium.connectOverCDP(session.connectUrl).catch(() => {
|
||||
throw new Error('Failed to connect to Browserbase session via CDP');
|
||||
});
|
||||
|
||||
try {
|
||||
const contexts = browser.contexts();
|
||||
if (contexts.length === 0) {
|
||||
throw new Error('No browser context found in Browserbase session');
|
||||
}
|
||||
|
||||
const context = contexts[0];
|
||||
const pages = context.pages();
|
||||
const page = pages[0] ?? (await context.newPage());
|
||||
|
||||
this.browserbaseSessionId = session.id;
|
||||
this.browserbaseApiKey = browserbaseApiKey;
|
||||
this.browser = browser;
|
||||
context.setDefaultTimeout(10000);
|
||||
this.contexts.push(context);
|
||||
this.pages.push(page);
|
||||
this.activePageIndex = 0;
|
||||
this.setupPageTracking(page);
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
await this.closeBrowserbaseSession(session.id, browserbaseApiKey).catch((sessionError) => {
|
||||
console.error('Failed to close Browserbase session during cleanup:', sessionError);
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch the browser with the specified options
|
||||
* If already launched, this is a no-op (browser stays open)
|
||||
@@ -669,6 +744,12 @@ export class BrowserManager {
|
||||
return;
|
||||
}
|
||||
|
||||
// Try connecting to Browserbase if credentials are available
|
||||
if (await this.connectToBrowserbase()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Select browser type
|
||||
const browserType = options.browser ?? 'chromium';
|
||||
if (hasExtensions && browserType !== 'chromium') {
|
||||
throw new Error('Extensions are only supported in Chromium');
|
||||
@@ -1359,8 +1440,15 @@ export class BrowserManager {
|
||||
this.cdpSession = null;
|
||||
}
|
||||
|
||||
// CDP: only disconnect, don't close external app's pages
|
||||
if (this.cdpPort !== null) {
|
||||
if (this.browserbaseSessionId && this.browserbaseApiKey) {
|
||||
await this.closeBrowserbaseSession(this.browserbaseSessionId, this.browserbaseApiKey).catch(
|
||||
(error) => {
|
||||
console.error('Failed to close Browserbase session:', error);
|
||||
}
|
||||
);
|
||||
this.browser = null;
|
||||
} else if (this.cdpPort !== null) {
|
||||
// CDP: only disconnect, don't close external app's pages
|
||||
if (this.browser) {
|
||||
await this.browser.close().catch(() => {});
|
||||
this.browser = null;
|
||||
@@ -1382,6 +1470,8 @@ export class BrowserManager {
|
||||
this.pages = [];
|
||||
this.contexts = [];
|
||||
this.cdpPort = null;
|
||||
this.browserbaseSessionId = null;
|
||||
this.browserbaseApiKey = null;
|
||||
this.isPersistentContext = false;
|
||||
this.activePageIndex = 0;
|
||||
this.refMap = {};
|
||||
|
||||
Reference in New Issue
Block a user