1+ import { z } from "zod" ;
2+ import type { Tool , ToolSchema , ToolContext , ToolResult } from "./tool.js" ;
3+ import { createSuccessResult , createErrorResult } from "./toolUtils.js" ;
4+ import type { Context } from "../context.js" ;
5+ import type { ToolActionResult } from "../context.js" ;
6+ import { Browserbase } from "@browserbasehq/sdk" ;
7+
8+ // Store contexts in memory
9+ // In a production app, these should be persisted to a database
10+ const contexts = new Map < string , string > ( ) ;
11+
12+ // --- Tool: Create Context ---
13+ const CreateContextInputSchema = z . object ( {
14+ name : z
15+ . string ( )
16+ . optional ( )
17+ . describe ( "Optional friendly name to reference this context later (otherwise, you'll need to use the returned ID)" ) ,
18+ } ) ;
19+ type CreateContextInput = z . infer < typeof CreateContextInputSchema > ;
20+
21+ const createContextSchema : ToolSchema < typeof CreateContextInputSchema > = {
22+ name : "browserbase_context_create" ,
23+ description : "Create a new Browserbase context for reusing cookies, authentication, and cached data across browser sessions" ,
24+ inputSchema : CreateContextInputSchema ,
25+ } ;
26+
27+ async function handleCreateContext (
28+ context : Context ,
29+ params : CreateContextInput
30+ ) : Promise < ToolResult > {
31+ try {
32+ const config = context . getConfig ( ) ;
33+
34+ if ( ! config . browserbaseApiKey || ! config . browserbaseProjectId ) {
35+ throw new Error ( "Browserbase API Key or Project ID is missing in the configuration" ) ;
36+ }
37+
38+ const bb = new Browserbase ( {
39+ apiKey : config . browserbaseApiKey ,
40+ } ) ;
41+
42+ console . error ( "Creating new Browserbase context" ) ;
43+ const bbContext = await bb . contexts . create ( {
44+ projectId : config . browserbaseProjectId ,
45+ } ) ;
46+
47+ console . error ( `Successfully created context: ${ bbContext . id } ` ) ;
48+
49+ // Store context ID with optional name if provided
50+ const contextName = params . name || bbContext . id ;
51+ contexts . set ( contextName , bbContext . id ) ;
52+
53+ const result : ToolActionResult = {
54+ content : [
55+ {
56+ type : "text" ,
57+ text : `Created new Browserbase context with ID: ${ bbContext . id } ${ params . name ? ` and name: ${ params . name } ` : '' } ` ,
58+ } ,
59+ ] ,
60+ } ;
61+
62+ return {
63+ resultOverride : result ,
64+ code : [ ] ,
65+ captureSnapshot : false ,
66+ waitForNetwork : false ,
67+ } ;
68+ } catch ( error : any ) {
69+ console . error ( `CreateContext handle failed: ${ error . message || error } ` ) ;
70+ throw new Error ( `Failed to create Browserbase context: ${ error . message || error } ` ) ;
71+ }
72+ }
73+
74+ // --- Tool: Delete Context ---
75+ const DeleteContextInputSchema = z . object ( {
76+ contextId : z
77+ . string ( )
78+ . optional ( )
79+ . describe ( "The context ID to delete (required if name not provided)" ) ,
80+ name : z
81+ . string ( )
82+ . optional ( )
83+ . describe ( "The friendly name of the context to delete (required if contextId not provided)" ) ,
84+ } ) ;
85+ type DeleteContextInput = z . infer < typeof DeleteContextInputSchema > ;
86+
87+ const deleteContextSchema : ToolSchema < typeof DeleteContextInputSchema > = {
88+ name : "browserbase_context_delete" ,
89+ description : "Delete a Browserbase context when you no longer need it" ,
90+ inputSchema : DeleteContextInputSchema ,
91+ } ;
92+
93+ async function handleDeleteContext (
94+ context : Context ,
95+ params : DeleteContextInput
96+ ) : Promise < ToolResult > {
97+ try {
98+ const config = context . getConfig ( ) ;
99+
100+ if ( ! config . browserbaseApiKey ) {
101+ throw new Error ( "Browserbase API Key is missing in the configuration" ) ;
102+ }
103+
104+ if ( ! params . contextId && ! params . name ) {
105+ throw new Error ( "Missing required argument: either contextId or name must be provided" ) ;
106+ }
107+
108+ // Resolve context ID either directly or by name
109+ let contextId = params . contextId ;
110+ if ( ! contextId && params . name ) {
111+ contextId = contexts . get ( params . name ) ;
112+ if ( ! contextId ) {
113+ throw new Error ( `Context with name "${ params . name } " not found` ) ;
114+ }
115+ }
116+
117+ console . error ( `Deleting Browserbase context: ${ contextId } ` ) ;
118+
119+ // Delete from Browserbase API
120+ // The SDK may not have a delete method directly, so we use the REST API
121+ const response = await fetch ( `https://api.browserbase.com/v1/contexts/${ contextId } ` , {
122+ method : 'DELETE' ,
123+ headers : {
124+ 'X-BB-API-Key' : config . browserbaseApiKey ,
125+ } ,
126+ } ) ;
127+
128+ if ( response . status !== 204 ) {
129+ const errorText = await response . text ( ) ;
130+ throw new Error ( `Failed to delete context with status ${ response . status } : ${ errorText } ` ) ;
131+ }
132+
133+ // Remove from local store
134+ if ( params . name ) {
135+ contexts . delete ( params . name ) ;
136+ }
137+
138+ // Delete by ID too (in case it was stored multiple ways)
139+ for ( const [ name , id ] of contexts . entries ( ) ) {
140+ if ( id === contextId ) {
141+ contexts . delete ( name ) ;
142+ }
143+ }
144+
145+ console . error ( `Successfully deleted context: ${ contextId } ` ) ;
146+
147+ const result : ToolActionResult = {
148+ content : [
149+ {
150+ type : "text" ,
151+ text : `Deleted Browserbase context with ID: ${ contextId } ` ,
152+ } ,
153+ ] ,
154+ } ;
155+
156+ return {
157+ resultOverride : result ,
158+ code : [ ] ,
159+ captureSnapshot : false ,
160+ waitForNetwork : false ,
161+ } ;
162+ } catch ( error : any ) {
163+ console . error ( `DeleteContext handle failed: ${ error . message || error } ` ) ;
164+ throw new Error ( `Failed to delete Browserbase context: ${ error . message || error } ` ) ;
165+ }
166+ }
167+
168+ // Helper function to get a context ID from name or direct ID (exported for use by session.ts)
169+ export function getContextId ( nameOrId : string ) : string | undefined {
170+ // First check if it's a direct context ID
171+ if ( nameOrId . length > 20 ) { // Assumption: context IDs are long strings
172+ return nameOrId ;
173+ }
174+
175+ // Otherwise, look it up by name
176+ return contexts . get ( nameOrId ) ;
177+ }
178+
179+ // Define tools
180+ const createContextTool : Tool < typeof CreateContextInputSchema > = {
181+ capability : "core" ,
182+ schema : createContextSchema ,
183+ handle : handleCreateContext ,
184+ } ;
185+
186+ const deleteContextTool : Tool < typeof DeleteContextInputSchema > = {
187+ capability : "core" ,
188+ schema : deleteContextSchema ,
189+ handle : handleDeleteContext ,
190+ } ;
191+
192+ // Export as an array of tools
193+ export default [ createContextTool , deleteContextTool ] ;
0 commit comments