@@ -65,9 +65,7 @@ def __init__(
65
65
if config :
66
66
self .browserbase_api_key = config .api_key or browserbase_api_key or os .getenv ("BROWSERBASE_API_KEY" )
67
67
self .browserbase_project_id = config .project_id or browserbase_project_id or os .getenv ("BROWSERBASE_PROJECT_ID" )
68
- self .model_api_key = model_api_key or (
69
- config .model_client_options .get ("apiKey" ) if config .model_client_options else None
70
- ) or os .getenv ("MODEL_API_KEY" )
68
+ self .model_api_key = os .getenv ("MODEL_API_KEY" )
71
69
self .session_id = config .browserbase_session_id or session_id
72
70
self .model_name = config .model_name or model_name
73
71
self .dom_settle_timeout_ms = config .dom_settle_timeout_ms or dom_settle_timeout_ms
@@ -200,20 +198,38 @@ async def close(self):
200
198
return
201
199
202
200
self ._log ("Closing resources..." , level = 1 )
203
- if self ._playwright_page :
204
- self ._log ("Closing the Playwright page..." , level = 1 )
205
- await self ._playwright_page .close ()
206
- self ._playwright_page = None
201
+
202
+ # End the session on the server if we have a session ID
203
+ if self .session_id :
204
+ try :
205
+ self ._log (f"Ending session { self .session_id } on the server..." , level = 1 )
206
+ client = self .httpx_client or httpx .AsyncClient (timeout = self .timeout_settings )
207
+ headers = {
208
+ "x-bb-api-key" : self .browserbase_api_key ,
209
+ "x-bb-project-id" : self .browserbase_project_id ,
210
+ "Content-Type" : "application/json" ,
211
+ }
212
+
213
+ async with client :
214
+ await self ._execute ("end" , {"sessionId" : self .session_id })
215
+ self ._log (f"Session { self .session_id } ended successfully" , level = 1 )
216
+ except Exception as e :
217
+ self ._log (f"Error ending session: { str (e )} " , level = 2 )
218
+
219
+ # if self._playwright_page:
220
+ # self._log("Closing the Playwright page...", level=1)
221
+ # await self._playwright_page.close()
222
+ # self._playwright_page = None
207
223
208
- if self ._context :
209
- self ._log ("Closing the context..." , level = 1 )
210
- await self ._context .close ()
211
- self ._context = None
224
+ # if self._context:
225
+ # self._log("Closing the context...", level=1)
226
+ # await self._context.close()
227
+ # self._context = None
212
228
213
- if self ._browser :
214
- self ._log ("Closing the browser..." , level = 1 )
215
- await self ._browser .close ()
216
- self ._browser = None
229
+ # if self._browser:
230
+ # self._log("Closing the browser...", level=1)
231
+ # await self._browser.close()
232
+ # self._browser = None
217
233
218
234
if self ._playwright :
219
235
self ._log ("Stopping Playwright..." , level = 1 )
@@ -315,56 +331,76 @@ async def _execute(self, method: str, payload: Dict[str, Any]) -> Any:
315
331
headers ["x-model-api-key" ] = self .model_api_key
316
332
317
333
client = self .httpx_client or httpx .AsyncClient (timeout = self .timeout_settings )
318
- print (f"Executing { method } with payload: { payload } and headers: { headers } " )
334
+ print (f"\n ==== EXECUTING { method .upper ()} ====" )
335
+ print (f"URL: { self .server_url } /sessions/{ self .session_id } /{ method } " )
336
+ print (f"Payload: { payload } " )
337
+ print (f"Headers: { headers } " )
338
+
319
339
async with client :
320
- async with client .stream (
321
- "POST" ,
322
- f"{ self .server_url } /sessions/{ self .session_id } /{ method } " ,
323
- json = payload ,
324
- headers = headers ,
325
- ) as response :
326
- if response .status_code != 200 :
327
- error_text = await response .aread ()
328
- self ._log (f"Error: { error_text .decode ('utf-8' )} " , level = 2 )
329
- return None
330
-
331
- async for line in response .aiter_lines ():
332
- # Skip empty lines
333
- if not line .strip ():
334
- continue
335
-
336
- try :
337
- # Handle SSE-style messages that start with "data: "
338
- if line .startswith ("data: " ):
339
- line = line [len ("data: " ):]
340
-
341
- message = json .loads (line )
342
- logger .info (f"Message: { message } " )
343
-
344
- # Handle different message types
345
- msg_type = message .get ("type" )
346
-
347
- if msg_type == "system" :
348
- status = message .get ("data" , {}).get ("status" )
349
- if status == "finished" :
350
- return message .get ("data" , {}).get ("result" )
351
- elif msg_type == "log" :
352
- # Log message from data.message
353
- log_msg = message .get ("data" , {}).get ("message" , "" )
354
- self ._log (log_msg , level = 1 )
355
- if self .on_log :
356
- await self .on_log (message )
357
- else :
358
- # Log any other message types
359
- self ._log (f"Unknown message type: { msg_type } " , level = 2 )
360
- if self .on_log :
361
- await self .on_log (message )
362
-
363
- except json .JSONDecodeError :
364
- self ._log (f"Could not parse line as JSON: { line } " , level = 2 )
365
- continue
340
+ try :
341
+ async with client .stream (
342
+ "POST" ,
343
+ f"{ self .server_url } /sessions/{ self .session_id } /{ method } " ,
344
+ json = payload ,
345
+ headers = headers ,
346
+ ) as response :
347
+ print (f"Response status: { response .status_code } " )
348
+
349
+ if response .status_code != 200 :
350
+ error_text = await response .aread ()
351
+ error_message = error_text .decode ('utf-8' )
352
+ print (f"ERROR RESPONSE: { error_message } " )
353
+ self ._log (f"Error: { error_message } " , level = 2 )
354
+ return None
355
+
356
+ print ("Starting to process streaming response..." )
357
+ async for line in response .aiter_lines ():
358
+ # Skip empty lines
359
+ if not line .strip ():
360
+ continue
361
+
362
+ try :
363
+ # Handle SSE-style messages that start with "data: "
364
+ if line .startswith ("data: " ):
365
+ line = line [len ("data: " ):]
366
+
367
+ message = json .loads (line )
368
+ print (f"RAW MESSAGE: { message } " )
369
+
370
+ # Handle different message types
371
+ msg_type = message .get ("type" )
372
+
373
+ if msg_type == "system" :
374
+ status = message .get ("data" , {}).get ("status" )
375
+ if status == "finished" :
376
+ result = message .get ("data" , {}).get ("result" )
377
+ print (f"FINISHED WITH RESULT: { result } " )
378
+ print (f"==== { method .upper ()} COMPLETE ====\n " )
379
+ return result
380
+ elif msg_type == "log" :
381
+ # Log message from data.message
382
+ log_msg = message .get ("data" , {}).get ("message" , "" )
383
+ print (f"LOG MESSAGE: { log_msg } " )
384
+ self ._log (log_msg , level = 1 )
385
+ if self .on_log :
386
+ await self .on_log (message )
387
+ else :
388
+ # Log any other message types
389
+ print (f"UNKNOWN MESSAGE TYPE: { msg_type } " )
390
+ self ._log (f"Unknown message type: { msg_type } " , level = 2 )
391
+ if self .on_log :
392
+ await self .on_log (message )
393
+
394
+ except json .JSONDecodeError :
395
+ print (f"JSON DECODE ERROR on line: { line } " )
396
+ self ._log (f"Could not parse line as JSON: { line } " , level = 2 )
397
+ continue
398
+ except Exception as e :
399
+ print (f"EXCEPTION IN _EXECUTE: { str (e )} " )
400
+ raise
366
401
367
402
# If we get here without seeing a "finished" message, something went wrong
403
+ print ("==== ERROR: No 'finished' message received ====" )
368
404
raise RuntimeError ("Server connection closed without sending 'finished' message" )
369
405
370
406
async def _handle_log (self , msg : Dict [str , Any ]):
0 commit comments