9
9
from playwright .async_api import async_playwright
10
10
from .page import StagehandPage
11
11
from .utils import default_log_handler
12
+ from .config import StagehandConfig
12
13
13
14
load_dotenv ()
14
15
@@ -19,15 +20,15 @@ class Stagehand:
19
20
Python client for interacting with a running Stagehand server and Browserbase remote headless browser.
20
21
21
22
Now supports automatically creating a new session if no session_id is provided.
22
- You can also optionally provide modelName, domSettleTimeoutMs, verbose, and debugDom,
23
- which will be sent to the server if a new session is created.
23
+ You can also optionally provide a configuration via the 'config' parameter to centralize all parameters.
24
24
"""
25
25
26
26
# Dictionary to store one lock per session_id
27
27
_session_locks = {}
28
28
29
29
def __init__ (
30
30
self ,
31
+ config : Optional [StagehandConfig ] = None ,
31
32
server_url : Optional [str ] = None ,
32
33
session_id : Optional [str ] = None ,
33
34
browserbase_api_key : Optional [str ] = None ,
@@ -42,36 +43,56 @@ def __init__(
42
43
timeout_settings : Optional [httpx .Timeout ] = None ,
43
44
):
44
45
"""
45
- :param server_url: The running Stagehand server URL.
46
- :param session_id: An existing Browserbase session ID (if you already have one).
47
- :param browserbase_api_key: Your Browserbase API key.
48
- :param browserbase_project_id: Your Browserbase project ID.
49
- :param model_api_key: Your model API key (e.g. OpenAI, Anthropic, etc).
50
- :param on_log: Async callback for log messages streamed from the server.
51
- :param verbose: Verbosity level for console logs from this client.
52
- :param model_name: Model name to use when creating a new session (e.g., "gpt-4o").
53
- :param dom_settle_timeout_ms: Additional time for the DOM to settle.
54
- :param debug_dom: Whether or not to enable DOM debug mode.
55
- :param httpx_client: Optional custom httpx.AsyncClient instance.
56
- :param timeout_settings: Optional custom timeout settings for httpx.
46
+ Initialize the Stagehand client.
47
+
48
+ Args:
49
+ config (Optional[StagehandConfig]): Optional configuration object encapsulating common parameters.
50
+ server_url (Optional[str]): The running Stagehand server URL.
51
+ session_id (Optional[str]): An existing Browserbase session ID.
52
+ browserbase_api_key (Optional[str]): Your Browserbase API key.
53
+ browserbase_project_id (Optional[str]): Your Browserbase project ID.
54
+ model_api_key (Optional[str]): Your model API key (e.g. OpenAI, Anthropic, etc.).
55
+ on_log (Optional[Callable[[Dict[str, Any]], Awaitable[None]]]): Async callback for log messages from the server.
56
+ verbose (int): Verbosity level for logs.
57
+ model_name (Optional[str]): Model name to use when creating a new session.
58
+ dom_settle_timeout_ms (Optional[int]): Additional time for the DOM to settle (in ms).
59
+ debug_dom (Optional[bool]): Whether to enable DOM debugging mode.
60
+ httpx_client (Optional[httpx.AsyncClient]): Optional custom httpx.AsyncClient instance.
61
+ timeout_settings (Optional[httpx.Timeout]): Optional custom timeout settings for httpx.
57
62
"""
58
-
59
63
self .server_url = server_url or os .getenv ("STAGEHAND_SERVER_URL" )
60
- self .session_id = session_id
61
- self .browserbase_api_key = browserbase_api_key or os .getenv ("BROWSERBASE_API_KEY" )
62
- self .browserbase_project_id = browserbase_project_id or os .getenv ("BROWSERBASE_PROJECT_ID" )
63
- self .model_api_key = model_api_key or os .getenv ("OPENAI_API_KEY" ) # Fallback to OPENAI_API_KEY for backwards compatibility
64
+
65
+ if config :
66
+ self .browserbase_api_key = config .api_key or browserbase_api_key or os .getenv ("BROWSERBASE_API_KEY" )
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" )
71
+ self .session_id = config .browserbase_session_id or session_id
72
+ self .model_name = config .model_name or model_name
73
+ self .dom_settle_timeout_ms = config .dom_settle_timeout_ms or dom_settle_timeout_ms
74
+ self .debug_dom = config .debug_dom if config .debug_dom is not None else debug_dom
75
+ self ._custom_logger = config .logger # For future integration if needed
76
+ # Additional config parameters available for future use:
77
+ self .headless = config .headless
78
+ self .enable_caching = config .enable_caching
79
+ else :
80
+ self .browserbase_api_key = browserbase_api_key or os .getenv ("BROWSERBASE_API_KEY" )
81
+ self .browserbase_project_id = browserbase_project_id or os .getenv ("BROWSERBASE_PROJECT_ID" )
82
+ self .model_api_key = model_api_key or os .getenv ("MODEL_API_KEY" )
83
+ self .session_id = session_id
84
+ self .model_name = model_name
85
+ self .dom_settle_timeout_ms = dom_settle_timeout_ms
86
+ self .debug_dom = debug_dom
87
+
64
88
self .on_log = on_log
65
89
self .verbose = verbose
66
- self .model_name = model_name
67
- self .dom_settle_timeout_ms = dom_settle_timeout_ms
68
- self .debug_dom = debug_dom
69
90
self .httpx_client = httpx_client
70
91
self .timeout_settings = timeout_settings or httpx .Timeout (
71
- connect = 90.0 , # connection timeout
72
- read = 90.0 , # read timeout
73
- write = 90.0 , # write timeout
74
- pool = 90.0 , # pool timeout
92
+ connect = 90.0 ,
93
+ read = 90.0 ,
94
+ write = 90.0 ,
95
+ pool = 90.0 ,
75
96
)
76
97
self .streamed_response = True # Default to True for streamed responses
77
98
@@ -82,16 +103,16 @@ def __init__(
82
103
self ._playwright_page = None
83
104
self .page : Optional [StagehandPage ] = None
84
105
85
- self ._initialized = False # Flag to track if we've already run init()
86
- self ._closed = False # Flag to track if we've closed
106
+ self ._initialized = False # Flag to track if init() has run
107
+ self ._closed = False # Flag to track if resources have been closed
87
108
88
- # Validate essential fields if session_id was given
109
+ # Validate essential fields if session_id was provided
89
110
if self .session_id :
90
111
if not self .browserbase_api_key :
91
112
raise ValueError ("browserbase_api_key is required (or set BROWSERBASE_API_KEY in env)." )
92
113
if not self .browserbase_project_id :
93
114
raise ValueError ("browserbase_project_id is required (or set BROWSERBASE_PROJECT_ID in env)." )
94
-
115
+
95
116
def _get_lock_for_session (self ) -> asyncio .Lock :
96
117
"""
97
118
Return an asyncio.Lock for this session. If one doesn't exist yet, create it.
@@ -288,7 +309,7 @@ async def _execute(self, method: str, payload: Dict[str, Any]) -> Any:
288
309
"x-bb-project-id" : self .browserbase_project_id ,
289
310
"Content-Type" : "application/json" ,
290
311
"Connection" : "keep-alive" ,
291
- "x-streamed -response" : str (self .streamed_response ).lower ()
312
+ "x-stream -response" : str (self .streamed_response ).lower ()
292
313
}
293
314
if self .model_api_key :
294
315
headers ["x-model-api-key" ] = self .model_api_key
0 commit comments