Skip to content

Commit 567e676

Browse files
authored
All constructor params inside config + default config (#86)
* consolidate stagehand constructor params and config * formatting
1 parent a68cd20 commit 567e676

File tree

3 files changed

+35
-53
lines changed

3 files changed

+35
-53
lines changed

stagehand/api.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ async def _create_session(self):
7373
"x-language": "python",
7474
}
7575

76-
client = self.httpx_client or httpx.AsyncClient(timeout=self.timeout_settings)
76+
client = httpx.AsyncClient(timeout=self.timeout_settings)
7777
async with client:
7878
resp = await client.post(
7979
f"{self.api_url}/sessions/start",
@@ -109,7 +109,7 @@ async def _execute(self, method: str, payload: dict[str, Any]) -> Any:
109109
# Convert snake_case keys to camelCase for the API
110110
modified_payload = convert_dict_keys_to_camel_case(payload)
111111

112-
client = self.httpx_client or httpx.AsyncClient(timeout=self.timeout_settings)
112+
client = httpx.AsyncClient(timeout=self.timeout_settings)
113113

114114
async with client:
115115
try:

stagehand/client.py

Lines changed: 11 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import sys
55
import time
66
from pathlib import Path
7-
from typing import Any, Literal, Optional
7+
from typing import Any, Optional
88

99
import httpx
1010
from dotenv import load_dotenv
@@ -54,47 +54,19 @@ class Stagehand:
5454

5555
def __init__(
5656
self,
57-
config: Optional[StagehandConfig] = None,
58-
*,
59-
api_url: Optional[str] = None,
60-
model_api_key: Optional[str] = None,
61-
session_id: Optional[str] = None,
62-
env: Optional[Literal["BROWSERBASE", "LOCAL"]] = None,
63-
httpx_client: Optional[httpx.AsyncClient] = None,
64-
timeout_settings: Optional[httpx.Timeout] = None,
65-
use_rich_logging: bool = True,
57+
config: StagehandConfig = default_config,
6658
**config_overrides,
6759
):
6860
"""
6961
Initialize the Stagehand client.
7062
7163
Args:
7264
config (Optional[StagehandConfig]): Configuration object. If not provided, uses default_config.
73-
api_url (Optional[str]): The running Stagehand server URL. Overrides config if provided.
74-
model_api_key (Optional[str]): Your model API key (e.g. OpenAI, Anthropic, etc.). Overrides config if provided.
75-
session_id (Optional[str]): Existing Browserbase session ID to connect to. Overrides config if provided.
76-
env (Optional[Literal["BROWSERBASE", "LOCAL"]]): Environment to run in. Overrides config if provided.
77-
httpx_client (Optional[httpx.AsyncClient]): Optional custom httpx.AsyncClient instance.
78-
timeout_settings (Optional[httpx.Timeout]): Optional custom timeout settings for httpx.
79-
use_rich_logging (bool): Whether to use Rich for colorized logging.
8065
**config_overrides: Additional configuration overrides to apply to the config.
8166
"""
82-
# Start with provided config or default config
83-
if config is None:
84-
config = default_config
8567

8668
# Apply any overrides
8769
overrides = {}
88-
if api_url is not None:
89-
# api_url isn't in config, handle separately
90-
pass
91-
if model_api_key is not None:
92-
# model_api_key isn't in config, handle separately
93-
pass
94-
if session_id is not None:
95-
overrides["browserbase_session_id"] = session_id
96-
if env is not None:
97-
overrides["env"] = env
9870

9971
# Add any additional config overrides
10072
overrides.update(config_overrides)
@@ -106,8 +78,9 @@ def __init__(
10678
self.config = config
10779

10880
# Handle non-config parameters
109-
self.api_url = api_url or os.getenv("STAGEHAND_API_URL")
110-
self.model_api_key = model_api_key or os.getenv("MODEL_API_KEY")
81+
self.api_url = self.config.api_url or os.getenv("STAGEHAND_API_URL")
82+
self.model_api_key = self.config.model_api_key or os.getenv("MODEL_API_KEY")
83+
self.model_name = self.config.model_name
11184

11285
# Extract frequently used values from config for convenience
11386
self.browserbase_api_key = self.config.api_key or os.getenv(
@@ -117,7 +90,6 @@ def __init__(
11790
"BROWSERBASE_PROJECT_ID"
11891
)
11992
self.session_id = self.config.browserbase_session_id
120-
self.model_name = self.config.model_name
12193
self.dom_settle_timeout_ms = self.config.dom_settle_timeout_ms
12294
self.self_heal = self.config.self_heal
12395
self.wait_for_captcha_solves = self.config.wait_for_captcha_solves
@@ -141,8 +113,7 @@ def __init__(
141113
# Handle streaming response setting
142114
self.streamed_response = True
143115

144-
self.httpx_client = httpx_client
145-
self.timeout_settings = timeout_settings or httpx.Timeout(
116+
self.timeout_settings = httpx.Timeout(
146117
connect=180.0,
147118
read=180.0,
148119
write=180.0,
@@ -164,7 +135,9 @@ def __init__(
164135
# Initialize the centralized logger with the specified verbosity
165136
self.on_log = self.config.logger or default_log_handler
166137
self.logger = StagehandLogger(
167-
verbose=self.verbose, external_logger=self.on_log, use_rich=use_rich_logging
138+
verbose=self.verbose,
139+
external_logger=self.on_log,
140+
use_rich=self.config.use_rich_logging,
168141
)
169142

170143
# If using BROWSERBASE, session_id or creation params are needed
@@ -425,9 +398,7 @@ async def init(self):
425398

426399
if self.env == "BROWSERBASE":
427400
if not self._client:
428-
self._client = self.httpx_client or httpx.AsyncClient(
429-
timeout=self.timeout_settings
430-
)
401+
self._client = httpx.AsyncClient(timeout=self.timeout_settings)
431402

432403
# Create session if we don't have one
433404
if not self.session_id:
@@ -539,8 +510,7 @@ async def close(self):
539510
"Cannot end server session: HTTP client not available."
540511
)
541512

542-
# Close internal HTTPX client if it was created by Stagehand
543-
if self._client and not self.httpx_client:
513+
if self._client:
544514
self.logger.debug("Closing the internal HTTPX client...")
545515
await self._client.aclose()
546516
self._client = None

stagehand/config.py

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Any, Callable, Optional
1+
from typing import Any, Callable, Literal, Optional
22

33
from browserbase.types import SessionCreateParams as BrowserbaseSessionCreateParams
44
from pydantic import BaseModel, ConfigDict, Field
@@ -12,37 +12,49 @@ class StagehandConfig(BaseModel):
1212
1313
Attributes:
1414
env (str): Environment type. 'BROWSERBASE' for remote usage
15-
api_key (Optional[str]): API key for authentication.
16-
project_id (Optional[str]): Project identifier.
17-
headless (bool): Run browser in headless mode.
18-
logger (Optional[Callable[[Any], None]]): Custom logging function.
19-
dom_settle_timeout_ms (Optional[int]): Timeout for DOM to settle (in milliseconds).
15+
api_key (Optional[str]): BrowserbaseAPI key for authentication.
16+
project_id (Optional[str]): Browserbase Project identifier.
17+
api_url (Optional[str]): Stagehand API URL.
2018
browserbase_session_create_params (Optional[BrowserbaseSessionCreateParams]): Browserbase session create params.
21-
enable_caching (Optional[bool]): Enable caching functionality.
2219
browserbase_session_id (Optional[str]): Session ID for resuming Browserbase sessions.
2320
model_name (Optional[str]): Name of the model to use.
21+
model_api_key (Optional[str]): Model API key.
22+
logger (Optional[Callable[[Any], None]]): Custom logging function.
23+
verbose (Optional[int]): Verbosity level for logs (1=minimal, 2=medium, 3=detailed).
24+
use_rich_logging (bool): Whether to use Rich for colorized logging.
25+
dom_settle_timeout_ms (Optional[int]): Timeout for DOM to settle (in milliseconds).
26+
enable_caching (Optional[bool]): Enable caching functionality.
2427
self_heal (Optional[bool]): Enable self-healing functionality.
2528
wait_for_captcha_solves (Optional[bool]): Whether to wait for CAPTCHA to be solved.
2629
act_timeout_ms (Optional[int]): Timeout for act commands (in milliseconds).
30+
headless (bool): Run browser in headless mode
2731
system_prompt (Optional[str]): System prompt to use for LLM interactions.
28-
verbose (Optional[int]): Verbosity level for logs (1=minimal, 2=medium, 3=detailed).
2932
local_browser_launch_options (Optional[dict[str, Any]]): Local browser launch options.
3033
"""
3134

32-
env: str = "BROWSERBASE"
35+
env: Literal["BROWSERBASE", "LOCAL"] = "BROWSERBASE"
3336
api_key: Optional[str] = Field(
3437
None, alias="apiKey", description="Browserbase API key for authentication"
3538
)
3639
project_id: Optional[str] = Field(
3740
None, alias="projectId", description="Browserbase project ID"
3841
)
42+
api_url: Optional[str] = Field(
43+
None, alias="apiUrl", description="Stagehand API URL"
44+
) # might add a default value here
45+
model_api_key: Optional[str] = Field(
46+
None, alias="modelApiKey", description="Model API key"
47+
)
3948
verbose: Optional[int] = Field(
4049
1,
41-
description="Verbosity level for logs: 1=minimal (INFO), 2=medium (WARNING), 3=detailed (DEBUG)",
50+
description="Verbosity level for logs: 0=minimal (ERROR), 1=medium (INFO), 2=detailed (DEBUG)",
4251
)
4352
logger: Optional[Callable[[Any], None]] = Field(
4453
None, description="Custom logging function"
4554
)
55+
use_rich_logging: Optional[bool] = Field(
56+
True, description="Whether to use Rich for colorized logging"
57+
)
4658
dom_settle_timeout_ms: Optional[int] = Field(
4759
3000,
4860
alias="domSettleTimeoutMs",

0 commit comments

Comments
 (0)