Skip to content

Commit a253cca

Browse files
committed
bb session close, log
1 parent b37377f commit a253cca

File tree

5 files changed

+137
-27
lines changed

5 files changed

+137
-27
lines changed

browserbase/config.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export type Config = {
3737
/**
3838
* Configuration for the browser_take_screenshot tool.
3939
*/
40-
browser_take_screenshot?: {
40+
browserbase_take_screenshot?: {
4141
/**
4242
* Whether to disable base64-encoded image responses to the clients that
4343
* don't support binary data or prefer to save on tokens.

browserbase/src/index.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,10 @@ export async function createServer(config: Config): Promise<Server> {
5555
const tools: Tool<any>[] = [
5656
...common,
5757
...snapshot,
58-
...keyboard, // Call the function and spread the result array
59-
// getText, // Include the tool object directly
60-
// navigate, // Include the tool object directly
61-
// session, // Include the tool object directly
62-
...getText, // Spread the array exported by getText.ts
63-
...navigate, // Spread the array exported by navigate.ts
64-
session, // Add the single tool object directly
58+
...keyboard,
59+
...getText,
60+
...navigate,
61+
...session,
6562
...contextTools,
6663
...cookies,
6764
];

browserbase/src/tools/navigate.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const navigate: ToolFactory = captureSnapshot => defineTool({
2222
capability: 'core',
2323

2424
schema: {
25-
name: 'browser_navigate',
25+
name: 'browserbase_navigate',
2626
description: 'Navigate to a URL',
2727
inputSchema: z.object({
2828
url: z.string().describe('The URL to navigate to'),

browserbase/src/tools/session.ts

Lines changed: 130 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
11
import { z } from "zod";
2-
// Import ToolResult and adjust Tool type usage
3-
import type { Tool, ToolSchema, ToolContext, ToolResult } from "./tool.js"; // Assuming these exist
4-
import { createSuccessResult, createErrorResult } from "./toolUtils.js"; // Assuming these exist
2+
import type { Tool, ToolSchema, ToolResult } from "./tool.js"; // Assuming these exist
53
import type { Context } from "../context.js"; // For handle signature
64
import type { ToolActionResult } from "../context.js"; // For action return type
7-
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
8-
// Remove Browserbase SDK import if not needed directly anymore
9-
// import Browserbase from "@browserbasehq/sdk";
10-
import dotenv from "dotenv";
115

126
// Import SessionManager functions
137
import {
@@ -17,8 +11,6 @@ import {
1711
type BrowserSession,
1812
} from "../sessionManager.js";
1913

20-
// Remove redundant dotenv config call
21-
// dotenv.config();
2214

2315
// --- Tool: Create Session ---
2416
const CreateSessionInputSchema = z.object({
@@ -54,13 +46,10 @@ async function handleCreateSession(
5446
if (params.sessionId) {
5547
targetSessionId = params.sessionId;
5648
process.stderr.write(
57-
`[tool.createSession] Attempting to create/assign session with specified ID: ${targetSessionId}\n`
49+
`[tool.createSession] Attempting to create/assign session with specified ID: ${targetSessionId}`
5850
);
5951
} else {
6052
targetSessionId = defaultSessionId;
61-
process.stderr.write(
62-
`[tool.createSession] Attempting to create/ensure default session (ID: ${targetSessionId})\n`
63-
);
6453
}
6554

6655
let session: BrowserSession;
@@ -78,9 +67,11 @@ async function handleCreateSession(
7867

7968
context.currentSessionId = targetSessionId;
8069
process.stderr.write(
81-
`[tool.createSession] Successfully ensured session. Internal ID: ${targetSessionId}, Actual ID: ${session.sessionId}\n`
70+
`[tool.connected] Successfully connected to Browserbase session. Internal ID: ${targetSessionId}, Actual ID: ${session.sessionId}`
8271
);
8372

73+
process.stderr.write(`[SessionManager] Browserbase Live Debugger URL: https://www.browserbase.com/sessions/${session.sessionId}`);
74+
8475
return {
8576
content: [
8677
{
@@ -93,7 +84,7 @@ async function handleCreateSession(
9384
process.stderr.write(
9485
`[tool.createSession] Action failed: ${
9586
error.message || String(error)
96-
}\n`
87+
}`
9788
);
9889
// Re-throw to be caught by Context.run's error handling for actions
9990
throw new Error(
@@ -120,5 +111,127 @@ const createSessionTool: Tool<typeof CreateSessionInputSchema> = {
120111
handle: handleCreateSession,
121112
};
122113

123-
// Export the single tool object as default
124-
export default createSessionTool;
114+
// --- Tool: Close Session ---
115+
const CloseSessionInputSchema = z.object({
116+
random_string: z
117+
.string()
118+
.optional()
119+
.describe("Dummy parameter to ensure consistent tool call format."),
120+
});
121+
type CloseSessionInput = z.infer<typeof CloseSessionInputSchema>;
122+
123+
const closeSessionSchema: ToolSchema<typeof CloseSessionInputSchema> = {
124+
name: "browserbase_session_close",
125+
description:
126+
"Closes the current Browserbase session by disconnecting the Playwright browser. This will terminate the recording for the session.",
127+
inputSchema: CloseSessionInputSchema,
128+
};
129+
130+
async function handleCloseSession(
131+
context: Context,
132+
_params: CloseSessionInput
133+
): Promise<ToolResult> {
134+
const code = [`// Attempting to close the current Browserbase session.`];
135+
136+
const action = async (): Promise<ToolActionResult> => {
137+
// Store the current session ID before it's potentially changed.
138+
// This allows us to reference the original session ID later if needed.
139+
const previousSessionId = context.currentSessionId; // Capture the ID before any changes
140+
let browser: BrowserSession["browser"] | null = null;
141+
let browserClosedSuccessfully = false;
142+
let browserCloseErrorMessage = "";
143+
144+
// Step 1: Attempt to get the active browser instance
145+
try {
146+
// This call might be associated with 'previousSessionId' (which could be default or specific)
147+
browser = await context.getActiveBrowser();
148+
} catch (error: any) {
149+
process.stderr.write(
150+
`[tool.closeSession] Error retrieving active browser (session ID was ${previousSessionId || 'default/unknown'}): ${error.message || String(error)}`
151+
);
152+
// If we can't even get the browser, we can't close it.
153+
// We will still proceed to reset context.
154+
}
155+
156+
// Step 2: If a browser instance was retrieved, attempt to close it
157+
if (browser) {
158+
try {
159+
process.stderr.write(
160+
`[tool.closeSession] Attempting to close browser for session: ${previousSessionId || 'default (actual might differ)'}`
161+
);
162+
await browser.close();
163+
browserClosedSuccessfully = true;
164+
process.stderr.write(
165+
`[tool.closeSession] Browser connection for session (was ${previousSessionId}) closed.`
166+
);
167+
168+
process.stderr.write(
169+
`[tool.closeSession] View session replay at https://www.browserbase.com/sessions/${previousSessionId}`
170+
);
171+
172+
} catch (error: any) {
173+
browserCloseErrorMessage = error.message || String(error);
174+
process.stderr.write(
175+
`[tool.closeSession] Error during browser.close() for session (was ${previousSessionId}): ${browserCloseErrorMessage}`
176+
);
177+
}
178+
} else {
179+
process.stderr.write(
180+
`[tool.closeSession] No active browser instance found to close. (Session ID in context was: ${previousSessionId || 'default/unknown'}).`
181+
);
182+
}
183+
184+
// Step 3: Always reset the context's current session ID to default
185+
// and clear snapshot if the previous session was a specific one.
186+
const oldContextSessionId = context.currentSessionId; // This should effectively be 'previousSessionId'
187+
context.currentSessionId = defaultSessionId;
188+
if (oldContextSessionId && oldContextSessionId !== defaultSessionId) {
189+
context.clearLatestSnapshot();
190+
process.stderr.write(
191+
`[tool.closeSession] Snapshot cleared for previous session: ${oldContextSessionId}.`
192+
);
193+
}
194+
process.stderr.write(
195+
`[tool.closeSession] Session context reset to default. Previous context session ID was ${oldContextSessionId || 'default/unknown'}.`
196+
);
197+
198+
// Step 4: Determine the result message
199+
if (browser && !browserClosedSuccessfully) { // An attempt was made to close, but it failed
200+
throw new Error(
201+
`Failed to close the Browserbase browser (session ID in context was ${previousSessionId || 'default/unknown'}). Error: ${browserCloseErrorMessage}. Session context has been reset to default.`
202+
);
203+
}
204+
205+
if (browserClosedSuccessfully) { // Browser was present and closed
206+
let successMessage = `Browserbase session (associated with context ID ${previousSessionId || 'default'}) closed successfully. Context reset to default.`;
207+
if (previousSessionId && previousSessionId !== defaultSessionId) {
208+
successMessage += ` If this was a uniquely named session (${previousSessionId}), view replay (if available) at https://browserbase.com/sessions/${previousSessionId}`;
209+
}
210+
return { content: [{ type: "text", text: successMessage }] };
211+
}
212+
213+
// No browser was found, or browser was null initially.
214+
let infoMessage = "No active browser instance was found to close. Session context has been reset to default.";
215+
if (previousSessionId && previousSessionId !== defaultSessionId) {
216+
// This means a specific session was in context, but no browser for it.
217+
infoMessage = `No active browser found for session ID '${previousSessionId}' in context. The context has been reset to default.`;
218+
}
219+
return { content: [{ type: "text", text: infoMessage }] };
220+
};
221+
222+
return {
223+
action: action,
224+
code: code,
225+
captureSnapshot: false,
226+
waitForNetwork: false,
227+
};
228+
}
229+
230+
const closeSessionTool: Tool<typeof CloseSessionInputSchema> = {
231+
capability: "core",
232+
schema: closeSessionSchema,
233+
handle: handleCloseSession,
234+
};
235+
236+
// Export an array of the tool objects as default
237+
export default [createSessionTool, closeSessionTool];

browserbase/src/tools/snapshot.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,7 @@ const screenshot = defineTool<typeof screenshotSchema>({
487487
const action = async (): Promise<ToolActionResult> => {
488488
// Access config via context.config
489489
const includeBase64 =
490-
!context.config.tools?.browser_take_screenshot?.omitBase64;
490+
!context.config.tools?.browserbase_take_screenshot?.omitBase64;
491491

492492
// Use the page directly for full page screenshots if locator is null
493493
const screenshotBuffer = locator

0 commit comments

Comments
 (0)