Skip to content

Commit a9dd4e7

Browse files
resolve merge conflict w target branch
2 parents d1c342a + 223d161 commit a9dd4e7

20 files changed

+584
-157
lines changed

.env.example

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
MODEL_API_KEY = "anthropic-or-openai-api-key"
22
BROWSERBASE_API_KEY = "browserbase-api-key"
33
BROWSERBASE_PROJECT_ID = "browserbase-project-id"
4-
STAGEHAND_SERVER_URL = "api_url"
4+
STAGEHAND_API_URL = "api_url"

.bumpversion.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[bumpversion]
2-
current_version = 0.3.3
2+
current_version = 0.3.8
33
commit = True
44
tag = True
55

README.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@
33
<a href="https://stagehand.dev">
44
<picture>
55
<source media="(prefers-color-scheme: dark)" srcset="https://stagehand.dev/logo-dark.svg" />
6-
<img alt="Stagehand" src="https://stagehand.dev/logo-light.svg" />
6+
<img alt="Stagehand" src="https://www.stagehand.dev/_next/image?url=%2Flogos%2Fmain-logo.webp&w=384&q=75" width="200" style="margin-right: 30px;" />
77
</picture>
88
</a>
99
</ul>
1010
</div>
1111

1212
<p align="center">
13-
An AI web browsing framework focused on simplicity and extensibility.<br>
13+
<strong>The AI Browser Automation Framework</strong><br>
14+
<a href="https://docs.stagehand.dev">Read the Docs</a>
1415
</p>
1516

1617
<p align="center">
@@ -104,7 +105,7 @@ Before running your script, set the following environment variables:
104105
export BROWSERBASE_API_KEY="your-api-key"
105106
export BROWSERBASE_PROJECT_ID="your-project-id"
106107
export MODEL_API_KEY="your-openai-api-key" # or your preferred model's API key
107-
export STAGEHAND_SERVER_URL="url-of-stagehand-server"
108+
export STAGEHAND_API_URL="url-of-stagehand-server"
108109
```
109110

110111
You can also make a copy of `.env.example` and add these to your `.env` file.
@@ -134,7 +135,7 @@ def main():
134135
)
135136

136137
# Initialize Stagehand
137-
stagehand = Stagehand(config=config, server_url=os.getenv("STAGEHAND_SERVER_URL"))
138+
stagehand = Stagehand(config=config, server_url=os.getenv("STAGEHAND_API_URL"))
138139
stagehand.init()
139140
print(f"Session created: {stagehand.session_id}")
140141

@@ -184,7 +185,7 @@ async def main():
184185
)
185186

186187
# Initialize Stagehand
187-
stagehand = Stagehand(config=config, server_url=os.getenv("STAGEHAND_SERVER_URL"))
188+
stagehand = Stagehand(config=config, server_url=os.getenv("STAGEHAND_API_URL"))
188189
await stagehand.init()
189190
print(f"Session created: {stagehand.session_id}")
190191

@@ -238,7 +239,7 @@ def main():
238239
)
239240

240241
# Initialize Stagehand
241-
stagehand = Stagehand(config=config, server_url=os.getenv("STAGEHAND_SERVER_URL"))
242+
stagehand = Stagehand(config=config, server_url=os.getenv("STAGEHAND_API_URL"))
242243
stagehand.init()
243244
print(f"Session created: {stagehand.session_id}")
244245

@@ -415,7 +416,7 @@ While there's no limit to what you could instruct Stagehand to do, our primitive
415416

416417
Stagehand can be configured via environment variables or through a `StagehandConfig` object. Available configuration options include:
417418

418-
- `stagehand_server_url`: URL of the Stagehand API server.
419+
- `STAGEHAND_API_URL`: URL of the Stagehand API server.
419420
- `browserbase_api_key`: Your Browserbase API key (`BROWSERBASE_API_KEY`).
420421
- `browserbase_project_id`: Your Browserbase project ID (`BROWSERBASE_PROJECT_ID`).
421422
- `model_api_key`: Your model API key (e.g. OpenAI, Anthropic, etc.) (`MODEL_API_KEY`).

examples/agent_example.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ async def main():
6464
# Create a Stagehand client using the configuration object.
6565
stagehand = Stagehand(
6666
config=config,
67-
server_url=os.getenv("STAGEHAND_SERVER_URL"),
67+
server_url=os.getenv("STAGEHAND_API_URL"),
6868
)
6969

7070
# Initialize - this creates a new session automatically.
@@ -95,7 +95,8 @@ async def main():
9595
console.print("✅ [success]Navigated to Google[/]")
9696

9797
console.print("\n▶️ [highlight] Using Agent to perform a task[/]: playing a game of 2048")
98-
agent_result = await stagehand.agent.execute(agent_config, execute_options)
98+
agent = stagehand.agent(agent_config)
99+
agent_result = await agent.execute(execute_options)
99100

100101
console.print("📊 [info]Agent execution result:[/]")
101102
console.print(f"✅ Success: [bold]{'Yes' if agent_result.success else 'No'}[/]")

examples/agent_example_sync.py

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
import logging
2+
import os
3+
4+
from dotenv import load_dotenv
5+
from rich.console import Console
6+
from rich.panel import Panel
7+
from rich.theme import Theme
8+
9+
from stagehand.sync import Stagehand
10+
from stagehand import StagehandConfig, AgentConfig, configure_logging
11+
from stagehand.schemas import AgentExecuteOptions, AgentProvider
12+
13+
# Create a custom theme for consistent styling
14+
custom_theme = Theme(
15+
{
16+
"info": "cyan",
17+
"success": "green",
18+
"warning": "yellow",
19+
"error": "red bold",
20+
"highlight": "magenta",
21+
"url": "blue underline",
22+
}
23+
)
24+
25+
# Create a Rich console instance with our theme
26+
console = Console(theme=custom_theme)
27+
28+
load_dotenv()
29+
30+
# Configure logging with the utility function
31+
configure_logging(
32+
level=logging.INFO, # Set to INFO for regular logs, DEBUG for detailed
33+
quiet_dependencies=True, # Reduce noise from dependencies
34+
)
35+
36+
console.print(
37+
Panel.fit(
38+
"[yellow]Logging Levels:[/]\n"
39+
"[white]- Set [bold]verbose=0[/] for errors (ERROR)[/]\n"
40+
"[white]- Set [bold]verbose=1[/] for minimal logs (INFO)[/]\n"
41+
"[white]- Set [bold]verbose=2[/] for medium logs (WARNING)[/]\n"
42+
"[white]- Set [bold]verbose=3[/] for detailed logs (DEBUG)[/]",
43+
title="Verbosity Options",
44+
border_style="blue",
45+
)
46+
)
47+
48+
def main():
49+
# Build a unified configuration object for Stagehand
50+
config = StagehandConfig(
51+
env="BROWSERBASE",
52+
api_key=os.getenv("BROWSERBASE_API_KEY"),
53+
project_id=os.getenv("BROWSERBASE_PROJECT_ID"),
54+
headless=False,
55+
dom_settle_timeout_ms=3000,
56+
model_name="gpt-4o",
57+
self_heal=True,
58+
wait_for_captcha_solves=True,
59+
system_prompt="You are a browser automation assistant that helps users navigate websites effectively.",
60+
model_client_options={"apiKey": os.getenv("MODEL_API_KEY")},
61+
verbose=2,
62+
)
63+
64+
# Create a Stagehand client using the configuration object.
65+
stagehand = Stagehand(
66+
config=config,
67+
server_url=os.getenv("STAGEHAND_API_URL"),
68+
)
69+
70+
# Initialize - this creates a new session automatically.
71+
console.print("\n🚀 [info]Initializing Stagehand...[/]")
72+
stagehand.init()
73+
console.print(f"\n[yellow]Created new session:[/] {stagehand.session_id}")
74+
console.print(
75+
f"🌐 [white]View your live browser:[/] [url]https://www.browserbase.com/sessions/{stagehand.session_id}[/]"
76+
)
77+
78+
# Configure the agent
79+
agent_config = AgentConfig(
80+
provider=AgentProvider.OPENAI,
81+
model="computer-use-preview",
82+
instructions="You are a helpful web navigation assistant that helps users find information. You are currently on the following page: google.com. Do not ask follow up questions, the user will trust your judgement.",
83+
options={"apiKey": os.getenv("MODEL_API_KEY")}
84+
)
85+
86+
# Define the task for the agent
87+
execute_options = AgentExecuteOptions(
88+
instruction="Play a game of 2048",
89+
max_steps=20,
90+
auto_screenshot=True,
91+
)
92+
93+
# Navigate to google
94+
console.print("\n▶️ [highlight] Navigating[/] to Google")
95+
stagehand.page.goto("https://google.com/")
96+
console.print("✅ [success]Navigated to Google[/]")
97+
98+
console.print("\n▶️ [highlight] Using Agent to perform a task[/]: playing a game of 2048")
99+
agent = stagehand.agent(agent_config)
100+
agent_result = agent.execute(execute_options)
101+
102+
console.print("📊 [info]Agent execution result:[/]")
103+
console.print(f"✅ Success: [bold]{'Yes' if agent_result.success else 'No'}[/]")
104+
console.print(f"🎯 Completed: [bold]{'Yes' if agent_result.completed else 'No'}[/]")
105+
if agent_result.message:
106+
console.print(f"💬 Message: [italic]{agent_result.message}[/]")
107+
108+
if agent_result.actions:
109+
console.print(f"🔄 Actions performed: [bold]{len(agent_result.actions)}[/]")
110+
for i, action in enumerate(agent_result.actions):
111+
console.print(f" Action {i+1}: {action.get('type', 'Unknown')} - {action.get('description', 'No description')}")
112+
113+
# For debugging, you can also print the full JSON
114+
console.print("[dim]Full response JSON:[/]")
115+
console.print_json(f"{agent_result.model_dump_json()}")
116+
117+
# Close the session
118+
console.print("\n⏹️ [warning]Closing session...[/]")
119+
stagehand.close()
120+
console.print("✅ [success]Session closed successfully![/]")
121+
console.rule("[bold]End of Example[/]")
122+
123+
124+
if __name__ == "__main__":
125+
# Add a fancy header
126+
console.print(
127+
"\n",
128+
Panel.fit(
129+
"[light_gray]Stagehand 🤘 Sync Agent Example[/]",
130+
border_style="green",
131+
padding=(1, 10),
132+
),
133+
)
134+
main()

examples/example.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ async def main():
5454
project_id=os.getenv("BROWSERBASE_PROJECT_ID"),
5555
headless=False,
5656
dom_settle_timeout_ms=3000,
57-
model_name="gpt-4o",
57+
model_name="gpt-4o-mini",
5858
self_heal=True,
5959
wait_for_captcha_solves=True,
6060
system_prompt="You are a browser automation assistant that helps users navigate websites effectively.",
@@ -65,11 +65,10 @@ async def main():
6565

6666
stagehand = Stagehand(
6767
config=config,
68-
server_url=os.getenv("STAGEHAND_SERVER_URL"),
68+
server_url=os.getenv("STAGEHAND_API_URL"),
6969
)
7070

7171
# Initialize - this creates a new session automatically.
72-
console.print("Launch on server: ", os.getenv("STAGEHAND_SERVER_URL"))
7372
console.print("\n🚀 [info]Initializing Stagehand...[/]")
7473
await stagehand.init()
7574
page = stagehand.page

examples/example_sync.py

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import logging
2+
import os
3+
from rich.console import Console
4+
from rich.panel import Panel
5+
from rich.theme import Theme
6+
import json
7+
from dotenv import load_dotenv
8+
9+
from stagehand.sync import Stagehand
10+
from stagehand import StagehandConfig
11+
from stagehand import configure_logging
12+
13+
# Create a custom theme for consistent styling
14+
custom_theme = Theme(
15+
{
16+
"info": "cyan",
17+
"success": "green",
18+
"warning": "yellow",
19+
"error": "red bold",
20+
"highlight": "magenta",
21+
"url": "blue underline",
22+
}
23+
)
24+
25+
# Create a Rich console instance with our theme
26+
console = Console(theme=custom_theme)
27+
28+
load_dotenv()
29+
30+
# Configure logging with the utility function
31+
configure_logging(
32+
level=logging.INFO, # Set to INFO for regular logs, DEBUG for detailed logs
33+
use_rich=True, # Use Rich for colorized output
34+
quiet_dependencies=True, # Reduce noise from dependencies
35+
)
36+
37+
console.print(
38+
Panel.fit(
39+
"[yellow]Logging Levels:[/]\n"
40+
"[white]- Set [bold]verbose=0[/] for errors only (ERROR)[/]\n"
41+
"[white]- Set [bold]verbose=1[/] for minimal logs (INFO)[/]\n"
42+
"[white]- Set [bold]verbose=2[/] for medium logs (WARNING)[/]\n"
43+
"[white]- Set [bold]verbose=3[/] for detailed logs (DEBUG)[/]",
44+
title="Verbosity Options",
45+
border_style="blue",
46+
)
47+
)
48+
49+
def main():
50+
# Build a unified configuration object for Stagehand
51+
config = StagehandConfig(
52+
env="BROWSERBASE",
53+
api_key=os.getenv("BROWSERBASE_API_KEY"),
54+
project_id=os.getenv("BROWSERBASE_PROJECT_ID"),
55+
headless=False,
56+
dom_settle_timeout_ms=3000,
57+
model_name="gpt-4o-mini",
58+
self_heal=True,
59+
wait_for_captcha_solves=True,
60+
system_prompt="You are a browser automation assistant that helps users navigate websites effectively.",
61+
model_client_options={"apiKey": os.getenv("MODEL_API_KEY")},
62+
verbose=2,
63+
)
64+
65+
# Create a Stagehand client using the configuration object.
66+
stagehand = Stagehand(
67+
config=config,
68+
server_url=os.getenv("STAGEHAND_API_URL"),
69+
)
70+
71+
# Initialize - this creates a new session automatically.
72+
console.print("\n🚀 [info]Initializing Stagehand...[/]")
73+
stagehand.init()
74+
console.print(f"\n[yellow]Created new session:[/] {stagehand.session_id}")
75+
console.print(
76+
f"🌐 [white]View your live browser:[/] [url]https://www.browserbase.com/sessions/{stagehand.session_id}[/]"
77+
)
78+
79+
import time
80+
81+
time.sleep(2)
82+
83+
console.print("\n▶️ [highlight] Navigating[/] to Google")
84+
stagehand.page.goto("https://google.com/")
85+
console.print("✅ [success]Navigated to Google[/]")
86+
87+
console.print("\n▶️ [highlight] Clicking[/] on About link")
88+
# Click on the "About" link using Playwright
89+
stagehand.page.get_by_role("link", name="About", exact=True).click()
90+
console.print("✅ [success]Clicked on About link[/]")
91+
92+
time.sleep(2)
93+
console.print("\n▶️ [highlight] Navigating[/] back to Google")
94+
stagehand.page.goto("https://google.com/")
95+
console.print("✅ [success]Navigated back to Google[/]")
96+
97+
console.print("\n▶️ [highlight] Performing action:[/] search for openai")
98+
stagehand.page.act("search for openai")
99+
stagehand.page.keyboard.press("Enter")
100+
console.print("✅ [success]Performing Action:[/] Action completed successfully")
101+
102+
console.print("\n▶️ [highlight] Observing page[/] for news button")
103+
observed = stagehand.page.observe("find the news button on the page")
104+
if len(observed) > 0:
105+
element = observed[0]
106+
console.print("✅ [success]Found element:[/] News button")
107+
stagehand.page.act(element)
108+
else:
109+
console.print("❌ [error]No element found[/]")
110+
111+
console.print("\n▶️ [highlight] Extracting[/] first search result")
112+
data = stagehand.page.extract("extract the first result from the search")
113+
console.print("📊 [info]Extracted data:[/]")
114+
console.print_json(f"{data.model_dump_json()}")
115+
116+
# Close the session
117+
console.print("\n⏹️ [warning]Closing session...[/]")
118+
stagehand.close()
119+
console.print("✅ [success]Session closed successfully![/]")
120+
console.rule("[bold]End of Example[/]")
121+
122+
123+
if __name__ == "__main__":
124+
# Add a fancy header
125+
console.print(
126+
"\n",
127+
Panel.fit(
128+
"[light_gray]Stagehand 🤘 Python Sync Example[/]",
129+
border_style="green",
130+
padding=(1, 10),
131+
),
132+
)
133+
main()

0 commit comments

Comments
 (0)