create-browser-app 0.1.11__tar.gz → 0.1.13__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {create_browser_app-0.1.11 → create_browser_app-0.1.13}/PKG-INFO +2 -2
- {create_browser_app-0.1.11 → create_browser_app-0.1.13}/create_browser_app/main.py +32 -28
- create_browser_app-0.1.13/create_browser_app/template_fetcher.py +127 -0
- create_browser_app-0.1.13/create_browser_app/templates.py +156 -0
- {create_browser_app-0.1.11 → create_browser_app-0.1.13}/create_browser_app.egg-info/PKG-INFO +2 -2
- {create_browser_app-0.1.11 → create_browser_app-0.1.13}/create_browser_app.egg-info/requires.txt +1 -1
- {create_browser_app-0.1.11 → create_browser_app-0.1.13}/pyproject.toml +2 -2
- create_browser_app-0.1.11/create_browser_app/template_fetcher.py +0 -75
- create_browser_app-0.1.11/create_browser_app/templates.py +0 -140
- {create_browser_app-0.1.11 → create_browser_app-0.1.13}/README.md +0 -0
- {create_browser_app-0.1.11 → create_browser_app-0.1.13}/create_browser_app/__init__.py +0 -0
- {create_browser_app-0.1.11 → create_browser_app-0.1.13}/create_browser_app.egg-info/SOURCES.txt +0 -0
- {create_browser_app-0.1.11 → create_browser_app-0.1.13}/create_browser_app.egg-info/dependency_links.txt +0 -0
- {create_browser_app-0.1.11 → create_browser_app-0.1.13}/create_browser_app.egg-info/entry_points.txt +0 -0
- {create_browser_app-0.1.11 → create_browser_app-0.1.13}/create_browser_app.egg-info/top_level.txt +0 -0
- {create_browser_app-0.1.11 → create_browser_app-0.1.13}/setup.cfg +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: create-browser-app
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.13
|
|
4
4
|
Summary: Start your Stagehand project with a single command
|
|
5
5
|
Requires-Python: >=3.10
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
7
|
-
Requires-Dist: stagehand
|
|
7
|
+
Requires-Dist: stagehand>=3.4.0
|
|
8
8
|
Requires-Dist: click>=8.0
|
|
9
9
|
Requires-Dist: rich>=13.0
|
|
10
10
|
Requires-Dist: inquirer>=3.0
|
|
@@ -10,13 +10,13 @@ from rich.panel import Panel
|
|
|
10
10
|
from rich.text import Text
|
|
11
11
|
import shutil
|
|
12
12
|
from .templates import TEMPLATE_BASIC, TEMPLATE_REQUIREMENTS, TEMPLATE_ENV, TEMPLATE_README, TEMPLATE_GITIGNORE
|
|
13
|
-
from .template_fetcher import
|
|
13
|
+
from .template_fetcher import fetch_all_template_files
|
|
14
14
|
|
|
15
15
|
console = Console()
|
|
16
16
|
|
|
17
17
|
@click.command()
|
|
18
18
|
@click.argument('name', default='my-stagehand-app', required=False)
|
|
19
|
-
@click.option('--template', '-t', default='basic', help='Template to use (basic or
|
|
19
|
+
@click.option('--template', '-t', default='basic', help='Template to use (basic or dynamically fetched from GitHub)')
|
|
20
20
|
def main(name, template):
|
|
21
21
|
"""Start your Stagehand project with a single command"""
|
|
22
22
|
|
|
@@ -36,7 +36,11 @@ def main(name, template):
|
|
|
36
36
|
console.print("[yellow]Stagehand[/yellow]")
|
|
37
37
|
console.print("[dim]The AI Browser Framework[/dim]\n")
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
# If user specified a template but not a custom name, use the template name
|
|
40
|
+
if name == 'my-stagehand-app' and template != 'basic':
|
|
41
|
+
project_name = template
|
|
42
|
+
else:
|
|
43
|
+
project_name = name
|
|
40
44
|
|
|
41
45
|
# Sanitize project name for directory
|
|
42
46
|
project_dir = project_name.lower().replace(" ", "-").replace("_", "-")
|
|
@@ -54,40 +58,40 @@ def main(name, template):
|
|
|
54
58
|
# Create directories
|
|
55
59
|
project_path.mkdir(parents=True, exist_ok=True)
|
|
56
60
|
|
|
57
|
-
#
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
# If not using basic template, try to fetch from GitHub
|
|
61
|
+
# Fetch template files from GitHub (if not basic)
|
|
62
|
+
template_files = {}
|
|
61
63
|
if template != 'basic':
|
|
62
64
|
console.print(f"Fetching template [cyan]{template}[/cyan] from GitHub...")
|
|
63
|
-
|
|
64
|
-
if
|
|
65
|
-
|
|
66
|
-
if fetched_content:
|
|
67
|
-
template_content = fetched_content
|
|
68
|
-
console.print(f"[green]✓[/green] Using template from GitHub: {template}")
|
|
69
|
-
else:
|
|
70
|
-
console.print(f"[yellow]⚠[/yellow] Could not fetch template, using basic template")
|
|
65
|
+
template_files = fetch_all_template_files(template)
|
|
66
|
+
if template_files:
|
|
67
|
+
console.print(f"[green]✓[/green] Fetched {len(template_files)} files from GitHub: {template}")
|
|
71
68
|
else:
|
|
72
|
-
console.print(f"[yellow]⚠[/yellow]
|
|
69
|
+
console.print(f"[yellow]⚠[/yellow] Could not fetch template, using basic template")
|
|
73
70
|
|
|
74
|
-
# Create main.py
|
|
71
|
+
# Create main.py (from template or default)
|
|
75
72
|
main_file = project_path / "main.py"
|
|
76
|
-
main_file.write_text(
|
|
77
|
-
|
|
78
|
-
# Create requirements.txt
|
|
79
|
-
requirements_file = project_path / "requirements.txt"
|
|
80
|
-
requirements_file.write_text(TEMPLATE_REQUIREMENTS)
|
|
73
|
+
main_file.write_text(template_files.get("main.py", TEMPLATE_BASIC))
|
|
81
74
|
|
|
82
|
-
# Create .
|
|
83
|
-
|
|
84
|
-
|
|
75
|
+
# Create requirements.txt or pyproject.toml (prefer template's version)
|
|
76
|
+
if "pyproject.toml" in template_files:
|
|
77
|
+
(project_path / "pyproject.toml").write_text(template_files["pyproject.toml"])
|
|
78
|
+
elif "requirements.txt" in template_files:
|
|
79
|
+
(project_path / "requirements.txt").write_text(template_files["requirements.txt"])
|
|
80
|
+
else:
|
|
81
|
+
(project_path / "requirements.txt").write_text(TEMPLATE_REQUIREMENTS)
|
|
85
82
|
|
|
86
|
-
# Create README.md
|
|
83
|
+
# Create README.md (prefer template's version)
|
|
87
84
|
readme_file = project_path / "README.md"
|
|
88
|
-
|
|
85
|
+
if "README.md" in template_files:
|
|
86
|
+
readme_file.write_text(template_files["README.md"])
|
|
87
|
+
else:
|
|
88
|
+
readme_file.write_text(TEMPLATE_README.format(project_name=project_name))
|
|
89
|
+
|
|
90
|
+
# Create .env.example (prefer template's version)
|
|
91
|
+
env_file = project_path / ".env.example"
|
|
92
|
+
env_file.write_text(template_files.get(".env.example", TEMPLATE_ENV))
|
|
89
93
|
|
|
90
|
-
# Create .gitignore
|
|
94
|
+
# Create .gitignore (always use default)
|
|
91
95
|
gitignore_file = project_path / ".gitignore"
|
|
92
96
|
gitignore_file.write_text(TEMPLATE_GITIGNORE)
|
|
93
97
|
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
import requests
|
|
3
|
+
from typing import Dict, List, Optional
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
|
|
6
|
+
@dataclass
|
|
7
|
+
class TemplateInfo:
|
|
8
|
+
name: str
|
|
9
|
+
url: str
|
|
10
|
+
|
|
11
|
+
def fetch_github_templates() -> List[str]:
|
|
12
|
+
"""Fetch list of Python templates from GitHub API."""
|
|
13
|
+
try:
|
|
14
|
+
response = requests.get(
|
|
15
|
+
"https://api.github.com/repos/browserbase/templates/contents/python",
|
|
16
|
+
headers={"User-Agent": "create-browser-app-py"},
|
|
17
|
+
timeout=10
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
if response.status_code != 200:
|
|
21
|
+
raise Exception(f"GitHub API returned status {response.status_code}")
|
|
22
|
+
|
|
23
|
+
data = response.json()
|
|
24
|
+
if not isinstance(data, list):
|
|
25
|
+
raise Exception("Invalid response format from GitHub API")
|
|
26
|
+
|
|
27
|
+
# Filter directories and exclude README.md
|
|
28
|
+
template_names = []
|
|
29
|
+
for item in data:
|
|
30
|
+
if (isinstance(item, dict) and
|
|
31
|
+
item.get("type") == "dir" and
|
|
32
|
+
item.get("name") != "README.md"):
|
|
33
|
+
template_names.append(item["name"])
|
|
34
|
+
|
|
35
|
+
return sorted(template_names)
|
|
36
|
+
|
|
37
|
+
except Exception as e:
|
|
38
|
+
# Re-raise with more context for debugging
|
|
39
|
+
raise Exception(f"Failed to fetch templates from GitHub: {e}")
|
|
40
|
+
|
|
41
|
+
def get_template_by_name(name: str) -> Optional[TemplateInfo]:
|
|
42
|
+
"""Get a specific template by name."""
|
|
43
|
+
# Normalize to lowercase to match GitHub directory naming convention
|
|
44
|
+
normalized_name = name.lower()
|
|
45
|
+
url = f"https://raw.githubusercontent.com/browserbase/templates/refs/heads/dev/python/{normalized_name}/main.py"
|
|
46
|
+
return TemplateInfo(name=normalized_name, url=url)
|
|
47
|
+
|
|
48
|
+
def fetch_template_content(template: TemplateInfo) -> Optional[str]:
|
|
49
|
+
"""Fetch the content of a specific template from GitHub."""
|
|
50
|
+
try:
|
|
51
|
+
response = requests.get(
|
|
52
|
+
template.url,
|
|
53
|
+
headers={"User-Agent": "create-browser-app-py"},
|
|
54
|
+
timeout=10
|
|
55
|
+
)
|
|
56
|
+
if response.status_code != 200:
|
|
57
|
+
return None
|
|
58
|
+
return response.text
|
|
59
|
+
except Exception:
|
|
60
|
+
return None
|
|
61
|
+
|
|
62
|
+
def fetch_template_files(template_name: str) -> List[Dict]:
|
|
63
|
+
"""Fetch list of files in a template directory from GitHub API."""
|
|
64
|
+
normalized_name = template_name.lower()
|
|
65
|
+
try:
|
|
66
|
+
response = requests.get(
|
|
67
|
+
f"https://api.github.com/repos/browserbase/templates/contents/python/{normalized_name}",
|
|
68
|
+
headers={"User-Agent": "create-browser-app-py"},
|
|
69
|
+
timeout=10
|
|
70
|
+
)
|
|
71
|
+
if response.status_code != 200:
|
|
72
|
+
return []
|
|
73
|
+
|
|
74
|
+
data = response.json()
|
|
75
|
+
if not isinstance(data, list):
|
|
76
|
+
return []
|
|
77
|
+
|
|
78
|
+
# Return file info for each file (not directories)
|
|
79
|
+
files = []
|
|
80
|
+
for item in data:
|
|
81
|
+
if isinstance(item, dict) and item.get("type") == "file":
|
|
82
|
+
files.append({
|
|
83
|
+
"name": item["name"],
|
|
84
|
+
"download_url": item.get("download_url")
|
|
85
|
+
})
|
|
86
|
+
return files
|
|
87
|
+
except Exception:
|
|
88
|
+
return []
|
|
89
|
+
|
|
90
|
+
def fetch_all_template_files(template_name: str) -> Dict[str, str]:
|
|
91
|
+
"""Fetch all files from a template directory.
|
|
92
|
+
|
|
93
|
+
Returns dict mapping filename -> content.
|
|
94
|
+
"""
|
|
95
|
+
files = fetch_template_files(template_name)
|
|
96
|
+
if not files:
|
|
97
|
+
return {}
|
|
98
|
+
|
|
99
|
+
result = {}
|
|
100
|
+
for file_info in files:
|
|
101
|
+
name = file_info["name"]
|
|
102
|
+
download_url = file_info.get("download_url")
|
|
103
|
+
if download_url:
|
|
104
|
+
try:
|
|
105
|
+
response = requests.get(
|
|
106
|
+
download_url,
|
|
107
|
+
headers={"User-Agent": "create-browser-app-py"},
|
|
108
|
+
timeout=10
|
|
109
|
+
)
|
|
110
|
+
if response.status_code == 200:
|
|
111
|
+
result[name] = response.text
|
|
112
|
+
except Exception:
|
|
113
|
+
pass # Skip files that fail to download
|
|
114
|
+
|
|
115
|
+
return result
|
|
116
|
+
|
|
117
|
+
def get_available_templates() -> List[str]:
|
|
118
|
+
"""Get templates from GitHub API, fallback to basic only."""
|
|
119
|
+
try:
|
|
120
|
+
github_templates = fetch_github_templates()
|
|
121
|
+
return ["basic"] + github_templates
|
|
122
|
+
except Exception:
|
|
123
|
+
return ["basic"] # Fallback when GitHub unreachable
|
|
124
|
+
|
|
125
|
+
def list_templates() -> List[str]:
|
|
126
|
+
"""Get a list of template names."""
|
|
127
|
+
return get_available_templates()
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
TEMPLATE_BASIC = '''import asyncio
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
from dotenv import load_dotenv
|
|
5
|
+
from pydantic import BaseModel
|
|
6
|
+
from stagehand import AsyncStagehand
|
|
7
|
+
|
|
8
|
+
load_dotenv()
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class StagehandDescription(BaseModel):
|
|
12
|
+
answer: str
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ModelInfo(BaseModel):
|
|
16
|
+
name: str
|
|
17
|
+
provider: str = ""
|
|
18
|
+
accuracy: float = 0.0
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
async def main():
|
|
22
|
+
"""Basic Stagehand browser automation example."""
|
|
23
|
+
|
|
24
|
+
client = AsyncStagehand(
|
|
25
|
+
browserbase_api_key=os.getenv("BROWSERBASE_API_KEY"),
|
|
26
|
+
browserbase_project_id=os.getenv("BROWSERBASE_PROJECT_ID"),
|
|
27
|
+
model_api_key=os.getenv("MODEL_API_KEY"),
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
# Start a Stagehand session
|
|
31
|
+
session = await client.sessions.create(model_name="google/gemini-3-flash-preview")
|
|
32
|
+
print(f"Session started: {session.id}")
|
|
33
|
+
print(f"View live: https://www.browserbase.com/sessions/{session.id}")
|
|
34
|
+
|
|
35
|
+
try:
|
|
36
|
+
# Navigate to a webpage
|
|
37
|
+
await session.navigate(url="https://docs.stagehand.dev")
|
|
38
|
+
|
|
39
|
+
# Extract data using Stagehand AI
|
|
40
|
+
result = await session.extract(
|
|
41
|
+
instruction="In a few words, what is Stagehand?",
|
|
42
|
+
schema=StagehandDescription.model_json_schema(),
|
|
43
|
+
)
|
|
44
|
+
print(f"Extracted: {result.data.result}")
|
|
45
|
+
|
|
46
|
+
# Perform AI-powered action
|
|
47
|
+
await session.act(input="click on models")
|
|
48
|
+
|
|
49
|
+
# Observe elements on the page
|
|
50
|
+
observe_response = await session.observe(
|
|
51
|
+
instruction="find the graph with the list of most accurate models",
|
|
52
|
+
)
|
|
53
|
+
print(f"Found {len(observe_response.data.result)} elements")
|
|
54
|
+
|
|
55
|
+
# Extract structured data
|
|
56
|
+
result = await session.extract(
|
|
57
|
+
instruction="the most accurate model",
|
|
58
|
+
schema=ModelInfo.model_json_schema(),
|
|
59
|
+
)
|
|
60
|
+
print(f"Most accurate model: {result.data.result}")
|
|
61
|
+
|
|
62
|
+
finally:
|
|
63
|
+
await session.end()
|
|
64
|
+
print("Session ended")
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
if __name__ == "__main__":
|
|
68
|
+
asyncio.run(main())
|
|
69
|
+
'''
|
|
70
|
+
|
|
71
|
+
TEMPLATE_REQUIREMENTS = '''stagehand>=3.4.0
|
|
72
|
+
pydantic
|
|
73
|
+
python-dotenv
|
|
74
|
+
'''
|
|
75
|
+
|
|
76
|
+
TEMPLATE_ENV = '''# Browserbase credentials (required)
|
|
77
|
+
BROWSERBASE_API_KEY=your_api_key_here
|
|
78
|
+
BROWSERBASE_PROJECT_ID=your_project_id_here
|
|
79
|
+
|
|
80
|
+
# LLM API key (required - using Google Gemini by default)
|
|
81
|
+
MODEL_API_KEY=your_api_key_here
|
|
82
|
+
'''
|
|
83
|
+
|
|
84
|
+
TEMPLATE_README = '''# {project_name}
|
|
85
|
+
|
|
86
|
+
A Stagehand browser automation project.
|
|
87
|
+
|
|
88
|
+
## Setup
|
|
89
|
+
|
|
90
|
+
1. Install dependencies:
|
|
91
|
+
```bash
|
|
92
|
+
pip install -r requirements.txt
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
2. Configure your environment variables in `.env`:
|
|
96
|
+
```bash
|
|
97
|
+
BROWSERBASE_API_KEY=your_api_key_here
|
|
98
|
+
BROWSERBASE_PROJECT_ID=your_project_id_here
|
|
99
|
+
MODEL_API_KEY=your_api_key_here
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
3. Run the project:
|
|
103
|
+
```bash
|
|
104
|
+
python main.py
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## About Stagehand
|
|
108
|
+
|
|
109
|
+
Stagehand is the AI browser automation framework. Learn more at:
|
|
110
|
+
- [Stagehand Documentation](https://docs.stagehand.dev/v3/sdk/python)
|
|
111
|
+
- [Browserbase](https://browserbase.com)
|
|
112
|
+
'''
|
|
113
|
+
|
|
114
|
+
TEMPLATE_GITIGNORE = '''# Python
|
|
115
|
+
__pycache__/
|
|
116
|
+
*.py[cod]
|
|
117
|
+
*$py.class
|
|
118
|
+
*.so
|
|
119
|
+
.Python
|
|
120
|
+
build/
|
|
121
|
+
develop-eggs/
|
|
122
|
+
dist/
|
|
123
|
+
downloads/
|
|
124
|
+
eggs/
|
|
125
|
+
.eggs/
|
|
126
|
+
lib/
|
|
127
|
+
lib64/
|
|
128
|
+
parts/
|
|
129
|
+
sdist/
|
|
130
|
+
var/
|
|
131
|
+
wheels/
|
|
132
|
+
*.egg-info/
|
|
133
|
+
.installed.cfg
|
|
134
|
+
*.egg
|
|
135
|
+
|
|
136
|
+
# Virtual Environment
|
|
137
|
+
venv/
|
|
138
|
+
ENV/
|
|
139
|
+
env/
|
|
140
|
+
.venv
|
|
141
|
+
|
|
142
|
+
# Environment variables
|
|
143
|
+
.env
|
|
144
|
+
.env.local
|
|
145
|
+
|
|
146
|
+
# IDE
|
|
147
|
+
.vscode/
|
|
148
|
+
.idea/
|
|
149
|
+
*.swp
|
|
150
|
+
*.swo
|
|
151
|
+
*~
|
|
152
|
+
.DS_Store
|
|
153
|
+
|
|
154
|
+
# Logs
|
|
155
|
+
*.log
|
|
156
|
+
'''
|
{create_browser_app-0.1.11 → create_browser_app-0.1.13}/create_browser_app.egg-info/PKG-INFO
RENAMED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: create-browser-app
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.13
|
|
4
4
|
Summary: Start your Stagehand project with a single command
|
|
5
5
|
Requires-Python: >=3.10
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
7
|
-
Requires-Dist: stagehand
|
|
7
|
+
Requires-Dist: stagehand>=3.4.0
|
|
8
8
|
Requires-Dist: click>=8.0
|
|
9
9
|
Requires-Dist: rich>=13.0
|
|
10
10
|
Requires-Dist: inquirer>=3.0
|
|
@@ -4,12 +4,12 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "create-browser-app"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.13"
|
|
8
8
|
description = "Start your Stagehand project with a single command"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
11
11
|
dependencies = [
|
|
12
|
-
"stagehand",
|
|
12
|
+
"stagehand>=3.4.0",
|
|
13
13
|
"click>=8.0",
|
|
14
14
|
"rich>=13.0",
|
|
15
15
|
"inquirer>=3.0",
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
import requests
|
|
3
|
-
from typing import Dict, List, Optional
|
|
4
|
-
from dataclasses import dataclass
|
|
5
|
-
|
|
6
|
-
@dataclass
|
|
7
|
-
class TemplateInfo:
|
|
8
|
-
name: str
|
|
9
|
-
url: str
|
|
10
|
-
|
|
11
|
-
GITHUB_TEMPLATES: List[TemplateInfo] = [
|
|
12
|
-
TemplateInfo(
|
|
13
|
-
name="example",
|
|
14
|
-
url="https://raw.githubusercontent.com/browserbase/stagehand-python/main/examples/example.py",
|
|
15
|
-
),
|
|
16
|
-
TemplateInfo(
|
|
17
|
-
name="cua-example",
|
|
18
|
-
url="https://raw.githubusercontent.com/browserbase/stagehand-python/main/examples/cua-example.py",
|
|
19
|
-
),
|
|
20
|
-
TemplateInfo(
|
|
21
|
-
name="form-filling",
|
|
22
|
-
url="https://raw.githubusercontent.com/browserbase/templates/refs/heads/dev/python/form-filling/main.py",
|
|
23
|
-
),
|
|
24
|
-
TemplateInfo(
|
|
25
|
-
name="gift-finder",
|
|
26
|
-
url="https://raw.githubusercontent.com/browserbase/templates/refs/heads/dev/python/gift-finder/main.py",
|
|
27
|
-
),
|
|
28
|
-
TemplateInfo(
|
|
29
|
-
name="pickleball",
|
|
30
|
-
url="https://raw.githubusercontent.com/browserbase/templates/refs/heads/dev/python/pickleball/main.py",
|
|
31
|
-
),
|
|
32
|
-
TemplateInfo(
|
|
33
|
-
name="license-verification",
|
|
34
|
-
url="https://raw.githubusercontent.com/browserbase/templates/refs/heads/dev/python/license-verification/main.py",
|
|
35
|
-
),
|
|
36
|
-
TemplateInfo(
|
|
37
|
-
name="context",
|
|
38
|
-
url="https://raw.githubusercontent.com/browserbase/templates/refs/heads/dev/python/context/main.py",
|
|
39
|
-
),
|
|
40
|
-
TemplateInfo(
|
|
41
|
-
name="proxies",
|
|
42
|
-
url="https://raw.githubusercontent.com/browserbase/templates/refs/heads/dev/python/proxies/main.py",
|
|
43
|
-
),
|
|
44
|
-
]
|
|
45
|
-
|
|
46
|
-
def get_template_by_name(name: str) -> Optional[TemplateInfo]:
|
|
47
|
-
"""Get a specific template by name."""
|
|
48
|
-
for template in GITHUB_TEMPLATES:
|
|
49
|
-
if template.name == name:
|
|
50
|
-
return template
|
|
51
|
-
return None
|
|
52
|
-
|
|
53
|
-
def fetch_template_content(template: TemplateInfo) -> Optional[str]:
|
|
54
|
-
"""Fetch the content of a specific template from GitHub."""
|
|
55
|
-
try:
|
|
56
|
-
response = requests.get(
|
|
57
|
-
template.url,
|
|
58
|
-
headers={"User-Agent": "create-browser-app-py"},
|
|
59
|
-
timeout=10
|
|
60
|
-
)
|
|
61
|
-
if response.status_code != 200:
|
|
62
|
-
return None
|
|
63
|
-
return response.text
|
|
64
|
-
except Exception:
|
|
65
|
-
return None
|
|
66
|
-
|
|
67
|
-
def get_available_templates() -> List[str]:
|
|
68
|
-
"""Get a list of available template names."""
|
|
69
|
-
default_templates = ["basic"]
|
|
70
|
-
github_templates = [t.name for t in GITHUB_TEMPLATES]
|
|
71
|
-
return default_templates + github_templates
|
|
72
|
-
|
|
73
|
-
def list_templates() -> List[str]:
|
|
74
|
-
"""Get a list of template names."""
|
|
75
|
-
return get_available_templates()
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
TEMPLATE_BASIC = '''from stagehand import Stagehand
|
|
2
|
-
import asyncio
|
|
3
|
-
import os
|
|
4
|
-
from dotenv import load_dotenv
|
|
5
|
-
from pydantic import BaseModel
|
|
6
|
-
load_dotenv()
|
|
7
|
-
|
|
8
|
-
async def main():
|
|
9
|
-
"""Basic Stagehand browser automation example."""
|
|
10
|
-
|
|
11
|
-
# Check all the configurations in StagehandConfig
|
|
12
|
-
stagehand = Stagehand(
|
|
13
|
-
env="LOCAL", # or "BROWSERBASE"
|
|
14
|
-
verbose=1, # 0: silent, 1: info, 2: debug
|
|
15
|
-
model_name="gpt-4.1",
|
|
16
|
-
model_api_key=os.getenv("OPENAI_API_KEY"),
|
|
17
|
-
)
|
|
18
|
-
await stagehand.init()
|
|
19
|
-
|
|
20
|
-
page = stagehand.page
|
|
21
|
-
await page.goto("https://docs.stagehand.dev")
|
|
22
|
-
result = await page.extract("In a few words, what is Stagehand?")
|
|
23
|
-
print()
|
|
24
|
-
print(result)
|
|
25
|
-
print()
|
|
26
|
-
|
|
27
|
-
await page.act("click on models")
|
|
28
|
-
await page.act({
|
|
29
|
-
"method": "click",
|
|
30
|
-
"selector": "/html/body[1]/div[2]/div[2]/div[3]/div[2]/div[2]/a[1]",
|
|
31
|
-
"description": "the model evaluation card",
|
|
32
|
-
"args": []
|
|
33
|
-
})
|
|
34
|
-
elements = await page.observe("find the graph with the list of most accurate models")
|
|
35
|
-
print()
|
|
36
|
-
print(elements)
|
|
37
|
-
print()
|
|
38
|
-
|
|
39
|
-
class Model(BaseModel):
|
|
40
|
-
name: str
|
|
41
|
-
provider: str
|
|
42
|
-
accuracy: float
|
|
43
|
-
|
|
44
|
-
extraction = await page.extract(
|
|
45
|
-
"the most accurate model",
|
|
46
|
-
schema=Model
|
|
47
|
-
)
|
|
48
|
-
print()
|
|
49
|
-
print(extraction)
|
|
50
|
-
print()
|
|
51
|
-
if __name__ == "__main__":
|
|
52
|
-
asyncio.run(main())
|
|
53
|
-
|
|
54
|
-
'''
|
|
55
|
-
|
|
56
|
-
TEMPLATE_REQUIREMENTS = '''stagehand
|
|
57
|
-
python-dotenv
|
|
58
|
-
'''
|
|
59
|
-
|
|
60
|
-
TEMPLATE_ENV = '''# Add your environment variables here
|
|
61
|
-
# BROWSERBASE_API_KEY=your_api_key_here
|
|
62
|
-
# BROWSERBASE_PROJECT_ID=your_project_id_here
|
|
63
|
-
# Add your LLM key
|
|
64
|
-
# OPENAI_API_KEY=your_api_key_here
|
|
65
|
-
# ANTHROPIC=your_api_key_here
|
|
66
|
-
# GOOGLE_API_KEY=your_api_key_here
|
|
67
|
-
'''
|
|
68
|
-
|
|
69
|
-
TEMPLATE_README = '''# {project_name}
|
|
70
|
-
|
|
71
|
-
A Stagehand browser automation project.
|
|
72
|
-
|
|
73
|
-
## Setup
|
|
74
|
-
|
|
75
|
-
1. Install dependencies:
|
|
76
|
-
```bash
|
|
77
|
-
pip install -r requirements.txt
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
2. Configure your environment variables in `.env`:
|
|
81
|
-
```bash
|
|
82
|
-
BROWSERBASE_API_KEY=your_api_key_here
|
|
83
|
-
BROWSERBASE_PROJECT_ID=your_project_id_here
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
3. Run the project:
|
|
87
|
-
```bash
|
|
88
|
-
python main.py
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
## About Stagehand
|
|
92
|
-
|
|
93
|
-
Stagehand is a Python library for browser automation built on Playwright. Learn more at:
|
|
94
|
-
- [Stagehand Documentation](https://github.com/browserbase/stagehand)
|
|
95
|
-
- [Browserbase](https://browserbase.com)
|
|
96
|
-
'''
|
|
97
|
-
|
|
98
|
-
TEMPLATE_GITIGNORE = '''# Python
|
|
99
|
-
__pycache__/
|
|
100
|
-
*.py[cod]
|
|
101
|
-
*$py.class
|
|
102
|
-
*.so
|
|
103
|
-
.Python
|
|
104
|
-
build/
|
|
105
|
-
develop-eggs/
|
|
106
|
-
dist/
|
|
107
|
-
downloads/
|
|
108
|
-
eggs/
|
|
109
|
-
.eggs/
|
|
110
|
-
lib/
|
|
111
|
-
lib64/
|
|
112
|
-
parts/
|
|
113
|
-
sdist/
|
|
114
|
-
var/
|
|
115
|
-
wheels/
|
|
116
|
-
*.egg-info/
|
|
117
|
-
.installed.cfg
|
|
118
|
-
*.egg
|
|
119
|
-
|
|
120
|
-
# Virtual Environment
|
|
121
|
-
venv/
|
|
122
|
-
ENV/
|
|
123
|
-
env/
|
|
124
|
-
.venv
|
|
125
|
-
|
|
126
|
-
# Environment variables
|
|
127
|
-
.env
|
|
128
|
-
.env.local
|
|
129
|
-
|
|
130
|
-
# IDE
|
|
131
|
-
.vscode/
|
|
132
|
-
.idea/
|
|
133
|
-
*.swp
|
|
134
|
-
*.swo
|
|
135
|
-
*~
|
|
136
|
-
.DS_Store
|
|
137
|
-
|
|
138
|
-
# Logs
|
|
139
|
-
*.log
|
|
140
|
-
'''
|
|
File without changes
|
|
File without changes
|
{create_browser_app-0.1.11 → create_browser_app-0.1.13}/create_browser_app.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{create_browser_app-0.1.11 → create_browser_app-0.1.13}/create_browser_app.egg-info/entry_points.txt
RENAMED
|
File without changes
|
{create_browser_app-0.1.11 → create_browser_app-0.1.13}/create_browser_app.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|