Skip to content

Commit e1e1f64

Browse files
committed
stash
1 parent 45dd330 commit e1e1f64

File tree

6 files changed

+679
-4
lines changed

6 files changed

+679
-4
lines changed

examples/demo.py

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Basic demo example for browser-use Python library.
4+
5+
This example demonstrates:
6+
1. Creating a task
7+
2. Polling for task completion
8+
3. Displaying the results
9+
10+
Usage:
11+
python examples/demo.py
12+
"""
13+
14+
import os
15+
import time
16+
17+
from utils import spinner
18+
19+
from browser_use import BrowserUse
20+
from browser_use.types.task_view import TaskView
21+
22+
23+
def main():
24+
"""Main function demonstrating basic task usage."""
25+
# Get API key from environment variable
26+
api_key = os.getenv("BROWSER_USE_API_KEY")
27+
if not api_key:
28+
print("Error: BROWSER_USE_API_KEY environment variable not set")
29+
print("Please set your API key: export BROWSER_USE_API_KEY='your-api-key'")
30+
return
31+
32+
# Initialize the client
33+
browser_use = BrowserUse(api_key=api_key)
34+
35+
print("🚀 Creating task...")
36+
37+
# Create a simple task
38+
response = browser_use.tasks.create(task="What's the current weather in San Francisco and what's the temperature?")
39+
40+
print(f"✅ Task created with ID: {response.id}")
41+
print(f"📝 Task: {response.task}")
42+
print(f"🤖 LLM Model: {response.llm}")
43+
print(f"🔄 Status: {response.status}")
44+
45+
if response.session_live_url:
46+
print(f"🔗 Live session: {response.session_live_url}")
47+
48+
# Poll for completion
49+
print("\n⏳ Waiting for task completion...")
50+
log_message = "starting"
51+
stop_spinner = spinner(lambda: log_message)
52+
53+
try:
54+
while True:
55+
# Wait a bit before checking
56+
time.sleep(2)
57+
58+
# Get task status
59+
status = browser_use.tasks.retrieve(response.id, status_only=False)
60+
61+
# Handle different status types
62+
if isinstance(status, TaskView):
63+
if status.status == "finished":
64+
stop_spinner()
65+
print(f"\n✅ Task completed!")
66+
print(f"📊 Output: {status.done_output}")
67+
68+
if status.steps:
69+
print(f"📋 Total steps: {len(status.steps)}")
70+
if status.steps:
71+
last_step = status.steps[-1]
72+
print(f"🎯 Final goal: {last_step.next_goal}")
73+
74+
break
75+
elif status.status in ["started", "paused", "stopped"]:
76+
steps_count = len(status.steps) if status.steps else 0
77+
steps_info = f"({steps_count} steps)"
78+
79+
if status.steps and status.steps[-1].next_goal:
80+
last_goal = status.steps[-1].next_goal
81+
steps_info += f", last: {last_goal}"
82+
83+
live_url_info = ""
84+
if status.session_live_url:
85+
live_url_info = f", live: {status.session_live_url}"
86+
87+
log_message = f"agent {status.status} {steps_info}{live_url_info}"
88+
# Update the spinner message by redefining the lambda
89+
stop_spinner = spinner(lambda: log_message)
90+
else:
91+
print(f"\n❌ Unexpected status: {status.status}")
92+
break
93+
else:
94+
print(f"\n❌ Unexpected response type: {type(status)}")
95+
break
96+
97+
except KeyboardInterrupt:
98+
stop_spinner()
99+
print("\n\n⏹️ Task monitoring interrupted by user")
100+
print("Note: The task will continue running on the server")
101+
except Exception as e:
102+
stop_spinner()
103+
print(f"\n❌ Error: {e}")
104+
105+
106+
if __name__ == "__main__":
107+
main()

examples/structured_output.py

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Structured output example for browser-use Python library.
4+
5+
This example demonstrates:
6+
1. Defining Pydantic models for structured output
7+
2. Creating tasks with structured output schemas
8+
3. Parsing and validating the results
9+
4. Type-safe access to task outputs
10+
11+
Usage:
12+
python examples/structured_output.py
13+
"""
14+
15+
import os
16+
import time
17+
from typing import List
18+
19+
from pydantic import Field, BaseModel
20+
21+
from browser_use import BrowserUse
22+
from utils import spinner
23+
24+
25+
# Define structured output schemas using Pydantic
26+
class HackerNewsPost(BaseModel):
27+
"""Schema for a single Hacker News post."""
28+
29+
title: str = Field(description="The title of the post")
30+
url: str = Field(description="The URL of the post")
31+
score: int = Field(description="The score/points of the post")
32+
33+
34+
class TaskOutput(BaseModel):
35+
"""Schema for the complete task output."""
36+
37+
posts: List[HackerNewsPost] = Field(description="List of top Hacker News posts", min_items=1, max_items=10)
38+
39+
40+
def main():
41+
"""Main function demonstrating structured output usage."""
42+
# Get API key from environment variable
43+
api_key = os.getenv("BROWSER_USE_API_KEY")
44+
if not api_key:
45+
print("Error: BROWSER_USE_API_KEY environment variable not set")
46+
print("Please set your API key: export BROWSER_USE_API_KEY='your-api-key'")
47+
return
48+
49+
# Initialize the client
50+
browser_use = BrowserUse(api_key=api_key)
51+
52+
print("🚀 Creating task with structured output...")
53+
print("📋 Expected output schema:")
54+
print(" - List of up to 10 Hacker News posts")
55+
print(" - Each post has: title, URL, and score")
56+
57+
# Create a task with structured output
58+
response = browser_use.tasks.create_with_structured_output(
59+
task="Extract the top 10 Hacker News posts and return the title, URL, and score for each",
60+
structured_output_json=TaskOutput,
61+
)
62+
63+
print(f"✅ Task created with ID: {response.id}")
64+
print(f"📝 Task: {response.task}")
65+
print(f"🤖 LLM Model: {response.llm}")
66+
print(f"🔄 Status: {response.status}")
67+
68+
if response.session_live_url:
69+
print(f"🔗 Live session: {response.session_live_url}")
70+
71+
# Poll for completion
72+
print("\n⏳ Waiting for task completion...")
73+
log_message = "starting"
74+
stop_spinner = spinner(lambda: log_message)
75+
76+
try:
77+
while True:
78+
# Wait a bit before checking
79+
time.sleep(2)
80+
81+
# Get task status with structured output parsing
82+
status = browser_use.tasks.retrieve_with_structured_output(response.id, structured_output_json=TaskOutput)
83+
84+
if status.status == "finished":
85+
stop_spinner()
86+
print(f"\n✅ Task completed!")
87+
88+
# Access the structured output
89+
if status.done_output is not None:
90+
print("\n📊 STRUCTURED OUTPUT:")
91+
print("=" * 50)
92+
93+
# Type-safe access to the parsed data
94+
for i, post in enumerate(status.done_output.posts, 1):
95+
print(f"{i:2d}. {post.title}")
96+
print(f" Score: {post.score} | URL: {post.url}")
97+
print()
98+
99+
print(f"Total posts extracted: {len(status.done_output.posts)}")
100+
else:
101+
print("❌ No structured output available")
102+
print("This might happen if the task output couldn't be parsed")
103+
104+
# Show additional task information
105+
if status.steps:
106+
print(f"\n📋 Total execution steps: {len(status.steps)}")
107+
if status.steps:
108+
last_step = status.steps[-1]
109+
print(f"🎯 Final goal: {last_step.next_goal}")
110+
111+
break
112+
113+
elif status.status in ["started", "paused", "stopped"]:
114+
steps_count = len(status.steps) if status.steps else 0
115+
steps_info = f"({steps_count} steps)"
116+
117+
if status.steps and status.steps[-1].next_goal:
118+
last_goal = status.steps[-1].next_goal
119+
steps_info += f", last: {last_goal}"
120+
121+
live_url_info = ""
122+
if status.session_live_url:
123+
live_url_info = f", live: {status.session_live_url}"
124+
125+
log_message = f"agent {status.status} {steps_info}{live_url_info}"
126+
# Update the spinner message by redefining the lambda
127+
stop_spinner = spinner(lambda: log_message)
128+
else:
129+
print(f"\n❌ Unexpected status: {status.status}")
130+
break
131+
132+
except KeyboardInterrupt:
133+
stop_spinner()
134+
print("\n\n⏹️ Task monitoring interrupted by user")
135+
print("Note: The task will continue running on the server")
136+
except Exception as e:
137+
stop_spinner()
138+
print(f"\n❌ Error: {e}")
139+
140+
141+
def demonstrate_schema_validation():
142+
"""Demonstrate how the Pydantic schema validation works."""
143+
print("\n🔍 SCHEMA VALIDATION DEMO:")
144+
print("=" * 40)
145+
146+
# Valid data
147+
try:
148+
valid_data = {"posts": [{"title": "Test Post", "url": "https://example.com", "score": 100}]}
149+
result = TaskOutput.model_validate(valid_data)
150+
print("✅ Valid data accepted")
151+
print(f" First post title: {result.posts[0].title}")
152+
except Exception as e:
153+
print(f"❌ Unexpected validation error: {e}")
154+
155+
# Invalid data (missing required field)
156+
try:
157+
invalid_data = {
158+
"posts": [
159+
{"title": "Test Post", "url": "https://example.com"}
160+
# Missing 'score' field
161+
]
162+
}
163+
TaskOutput.model_validate(invalid_data)
164+
print("❌ Invalid data was accepted (this shouldn't happen)")
165+
except Exception as e:
166+
print("✅ Invalid data correctly rejected")
167+
print(f" Error: {e}")
168+
169+
170+
if __name__ == "__main__":
171+
# Show schema validation demo
172+
demonstrate_schema_validation()
173+
174+
# Run the main example
175+
print("\n" + "=" * 60)
176+
main()

examples/test_spinner.py

Whitespace-only changes.

examples/utils.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Utility functions for browser-use examples.
4+
"""
5+
6+
import sys
7+
import time
8+
import threading
9+
from typing import Callable
10+
11+
SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]
12+
13+
14+
def spinner(render_text: Callable[[], str]) -> Callable[[], None]:
15+
"""
16+
Start a spinner that updates the text every 100ms.
17+
18+
Args:
19+
render_text: A function that returns the text to display.
20+
21+
Returns:
22+
A function to stop the spinner.
23+
"""
24+
frame_index = 0
25+
running = True
26+
27+
def spin():
28+
nonlocal frame_index
29+
while running:
30+
frame = SPINNER_FRAMES[frame_index % len(SPINNER_FRAMES)]
31+
text = f"{frame} {render_text()}"
32+
33+
# Clear line and write new text
34+
sys.stdout.write(f"\r{text}")
35+
sys.stdout.flush()
36+
37+
frame_index += 1
38+
time.sleep(0.1)
39+
40+
def stop():
41+
nonlocal running
42+
running = False
43+
# Clear the line
44+
sys.stdout.write("\r" + " " * 80 + "\r")
45+
sys.stdout.flush()
46+
47+
# Start spinner in a daemon thread
48+
thread = threading.Thread(target=spin, daemon=True)
49+
thread.start()
50+
51+
return stop

0 commit comments

Comments
 (0)