Skip to content

Commit c58e7e4

Browse files
monadoidstainless-app[bot]
authored andcommitted
STG-1306: update model names and README examples
1 parent 9b690c0 commit c58e7e4

7 files changed

Lines changed: 146 additions & 139 deletions

README.md

Lines changed: 132 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,58 @@
11
# Stagehand Ruby API library
22

3+
<!-- x-stagehand-custom-start -->
4+
<div id="toc" align="center" style="margin-bottom: 0;">
5+
<ul style="list-style: none; margin: 0; padding: 0;">
6+
<a href="https://stagehand.dev">
7+
<picture>
8+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/browserbase/stagehand/main/media/dark_logo.png" />
9+
<img alt="Stagehand" src="https://raw.githubusercontent.com/browserbase/stagehand/main/media/light_logo.png" width="200" style="margin-right: 30px;" />
10+
</picture>
11+
</a>
12+
</ul>
13+
</div>
14+
<p align="center">
15+
<strong>The AI Browser Automation Framework</strong><br>
16+
<a href="https://docs.stagehand.dev/v3/sdk/ruby">Read the Docs</a>
17+
</p>
18+
19+
<p align="center">
20+
<a href="https://github.com/browserbase/stagehand/tree/main?tab=MIT-1-ov-file#MIT-1-ov-file">
21+
<picture>
22+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/browserbase/stagehand/main/media/dark_license.svg" />
23+
<img alt="MIT License" src="https://raw.githubusercontent.com/browserbase/stagehand/main/media/light_license.svg" />
24+
</picture>
25+
</a>
26+
<a href="https://stagehand.dev/discord">
27+
<picture>
28+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/browserbase/stagehand/main/media/dark_discord.svg" />
29+
<img alt="Discord Community" src="https://raw.githubusercontent.com/browserbase/stagehand/main/media/light_discord.svg" />
30+
</picture>
31+
</a>
32+
</p>
33+
34+
<p align="center">
35+
<a href="https://trendshift.io/repositories/12122" target="_blank"><img src="https://trendshift.io/api/badge/repositories/12122" alt="browserbase%2Fstagehand | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
36+
</p>
37+
38+
<p align="center">
39+
If you're looking for other languages, you can find them
40+
<a href="https://docs.stagehand.dev/v3/first-steps/introduction"> here</a>
41+
</p>
42+
43+
<div align="center" style="display: flex; align-items: center; justify-content: center; gap: 4px; margin-bottom: 0;">
44+
<b>Vibe code</b>
45+
<span style="font-size: 1.05em;"> Stagehand with </span>
46+
<a href="https://director.ai" style="display: flex; align-items: center;">
47+
<span>Director</span>
48+
</a>
49+
<span> </span>
50+
<picture>
51+
<img alt="Director" src="https://raw.githubusercontent.com/browserbase/stagehand/main/media/director_icon.svg" width="25" />
52+
</picture>
53+
</div>
54+
<!-- x-stagehand-custom-end -->
55+
356
The Stagehand Ruby library provides convenient access to the Stagehand REST API from any Ruby 3.2.0+ application. It ships with comprehensive types & docstrings in Yard, RBS, and RBI – [see below](https://github.com/browserbase/stagehand-ruby#Sorbet) for usage with Sorbet. The standard library's `net/http` is used as the HTTP transport, with connection pooling via the `connection_pool` gem.
457

558
It is generated with [Stainless](https://www.stainless.com/).
@@ -24,165 +77,119 @@ gem "stagehand", :git => "git://github.com/browserbase/stagehand-ruby.git"
2477

2578
## Usage
2679

80+
This mirrors `examples/remote_browser_playwright_example.rb`.
81+
2782
```ruby
2883
require "bundler/setup"
2984
require "stagehand"
3085

31-
# Create a new Stagehand client with your credentials
86+
require_relative "examples/env"
87+
ExampleEnv.load!
88+
89+
require "playwright"
90+
3291
client = Stagehand::Client.new(
33-
browserbase_api_key: ENV["BROWSERBASE_API_KEY"], # defaults to ENV["BROWSERBASE_API_KEY"]
34-
browserbase_project_id: ENV["BROWSERBASE_PROJECT_ID"], # defaults to ENV["BROWSERBASE_PROJECT_ID"]
35-
model_api_key: ENV["MODEL_API_KEY"] # defaults to ENV["MODEL_API_KEY"]
92+
browserbase_api_key: ENV["BROWSERBASE_API_KEY"],
93+
browserbase_project_id: ENV["BROWSERBASE_PROJECT_ID"],
94+
model_api_key: ENV["MODEL_API_KEY"],
95+
server: "remote"
3696
)
3797

38-
# Start a new browser session
3998
start_response = client.sessions.start(
40-
model_name: "openai/gpt-5-nano"
99+
model_name: "anthropic/claude-sonnet-4-6",
100+
browser: { type: :browserbase }
41101
)
42-
puts "Session started: #{start_response.data.session_id}"
43102

44103
session_id = start_response.data.session_id
104+
cdp_url = start_response.data.cdp_url
105+
raise "No CDP URL returned for this session." if cdp_url.to_s.empty?
45106

46-
# Navigate to a webpage
47-
client.sessions.navigate(
48-
session_id,
49-
url: "https://news.ycombinator.com"
50-
)
51-
puts "Navigated to Hacker News"
107+
Playwright.create(playwright_cli_executable_path: "./node_modules/.bin/playwright") do |playwright|
108+
browser = playwright.chromium.connect_over_cdp(cdp_url)
109+
context = browser.contexts.first || browser.new_context
110+
page = context.pages.first || context.new_page
52111

53-
# Use Observe to find possible actions on the page
54-
observe_response = client.sessions.observe(
55-
session_id,
56-
instruction: "find the link to view comments for the top post"
57-
)
58-
59-
actions = observe_response.data.result
60-
puts "Found #{actions.length} possible actions"
112+
client.sessions.navigate(session_id, url: "https://news.ycombinator.com")
113+
page.wait_for_load_state(state: "domcontentloaded")
61114

62-
# Take the first action returned by Observe
63-
action = actions.first
64-
puts "Acting on: #{action.description}"
115+
observe_stream = client.sessions.observe_streaming(
116+
session_id,
117+
instruction: "find the link to view comments for the top post"
118+
)
119+
observe_stream.each { |_event| }
65120

66-
# Pass the structured action to Act
67-
# Convert the observe result to a hash and ensure method is set to "click"
68-
act_response = client.sessions.act(
69-
session_id,
70-
input: action.to_h.merge(method: "click")
71-
)
72-
puts "Act completed: #{act_response.data.result[:message]}"
73-
74-
# Extract data from the page
75-
# We're now on the comments page, so extract the top comment text
76-
extract_response = client.sessions.extract(
77-
session_id,
78-
instruction: "extract the text of the top comment on this page",
79-
schema: {
80-
type: "object",
81-
properties: {
82-
comment_text: {
83-
type: "string",
84-
description: "The text content of the top comment"
121+
act_stream = client.sessions.act_streaming(
122+
session_id,
123+
input: "Click the comments link for the top post"
124+
)
125+
act_stream.each { |_event| }
126+
127+
extract_stream = client.sessions.extract_streaming(
128+
session_id,
129+
instruction: "extract the text of the top comment on this page",
130+
schema: {
131+
type: "object",
132+
properties: {
133+
commentText: {type: "string"},
134+
author: {type: "string"}
85135
},
86-
author: {
87-
type: "string",
88-
description: "The username of the comment author"
89-
}
136+
required: ["commentText"]
137+
}
138+
)
139+
extract_stream.each { |_event| }
140+
141+
execute_stream = client.sessions.execute_streaming(
142+
session_id,
143+
execute_options: {
144+
instruction: "Click the 'Learn more' link if available",
145+
max_steps: 3
90146
},
91-
required: ["comment_text"]
92-
}
93-
)
94-
puts "Extracted data: #{extract_response.data.result}"
95-
96-
# Get the author from the extracted data
97-
extracted_data = extract_response.data.result
98-
author = extracted_data[:author]
99-
puts "Looking up profile for author: #{author}"
100-
101-
# Use the Agent to find the author's profile
102-
# Execute runs an autonomous agent that can navigate and interact with pages
103-
execute_response = client.sessions.execute(
104-
session_id,
105-
execute_options: {
106-
instruction: "Find any personal website, GitHub, LinkedIn, or other best profile URL for the Hacker News user '#{author}'. " \
107-
"Click on their username to go to their profile page and look for any links they have shared.",
108-
max_steps: 15
109-
},
110-
agent_config: {
111-
model: Stagehand::ModelConfig::ModelConfigObject.new(
112-
model_name: "openai/gpt-5-nano",
113-
api_key: ENV["MODEL_API_KEY"]
114-
),
115-
cua: false
116-
}
117-
)
118-
puts "Agent completed: #{execute_response.data.result[:message]}"
119-
puts "Agent success: #{execute_response.data.result[:success]}"
120-
puts "Agent actions taken: #{execute_response.data.result[:actions]&.length || 0}"
147+
agent_config: {
148+
model: Stagehand::ModelConfig.new(
149+
model_name: "anthropic/claude-sonnet-4-6",
150+
api_key: ENV["MODEL_API_KEY"]
151+
),
152+
cua: false
153+
}
154+
)
155+
execute_stream.each { |_event| }
156+
end
121157

122-
# End the session to cleanup browser resources
123158
client.sessions.end_(session_id)
124-
puts "Session ended"
125159
```
126160

127-
### Running the Examples
161+
## Running the Example
128162

129-
Install dependencies, set credentials, and run the scripts below.
163+
Set your environment variables (from `examples/.env.example`):
130164

131-
```bash
132-
# Install the gem dependencies
133-
bundle install
134-
```
135-
136-
Remote browser example:
165+
- `STAGEHAND_API_URL`
166+
- `MODEL_API_KEY`
167+
- `BROWSERBASE_API_KEY`
168+
- `BROWSERBASE_PROJECT_ID`
137169

138170
```bash
139171
cp examples/.env.example examples/.env
140172
# Edit examples/.env with your credentials.
141-
bundle exec ruby examples/remote_browser_example.rb
142173
```
143174

144175
The examples load `examples/.env` automatically.
145176

146-
Local mode example (embedded server, local Chrome/Chromium):
147-
148-
```bash
149-
cp examples/.env.example examples/.env
150-
# Edit examples/.env with your credentials.
151-
bundle exec ruby examples/local_browser_example.rb
152-
```
153-
154-
Playwright local example (SSE streaming):
177+
Examples and dependencies:
155178

156-
```bash
157-
gem install playwright-ruby-client
158-
npm install playwright
159-
./node_modules/.bin/playwright install chromium
160-
export MODEL_API_KEY="your-openai-api-key"
161-
bundle exec ruby examples/local_playwright_example.rb
179+
- `examples/remote_browser_example.rb`: stagehand only
180+
- `examples/local_browser_example.rb`: stagehand only
181+
- `examples/remote_browser_playwright_example.rb`: `playwright-ruby-client` + Playwright browsers
182+
- `examples/local_browser_playwright_example.rb`: `playwright-ruby-client` + Playwright browsers
183+
- `examples/local_playwright_example.rb`: `playwright-ruby-client` + Playwright browsers
184+
- `examples/local_watir_example.rb`: `watir`
162185

163-
bundle exec ruby examples/local_browser_playwright_example.rb
164-
```
165-
166-
Playwright remote example:
186+
Install dependencies for the example you want to run, then execute it:
167187

168188
```bash
169-
gem install playwright-ruby-client
170-
npm install playwright
171-
./node_modules/.bin/playwright install chromium
172-
export BROWSERBASE_API_KEY="your-browserbase-api-key"
173-
export BROWSERBASE_PROJECT_ID="your-browserbase-project-id"
174-
export MODEL_API_KEY="your-openai-api-key"
189+
bundle install
175190
bundle exec ruby examples/remote_browser_playwright_example.rb
176191
```
177192

178-
Watir local example:
179-
180-
```bash
181-
gem install watir
182-
export MODEL_API_KEY="your-openai-api-key"
183-
bundle exec ruby examples/local_watir_example.rb
184-
```
185-
186193
### Streaming
187194

188195
We provide support for streaming responses using Server-Sent Events (SSE).
@@ -204,7 +211,7 @@ When the library is unable to connect to the API, or if the API returns a non-su
204211

205212
```ruby
206213
begin
207-
session = stagehand.sessions.start(model_name: "openai/gpt-5-nano")
214+
session = stagehand.sessions.start(model_name: "anthropic/claude-sonnet-4-6")
208215
rescue Stagehand::Errors::APIConnectionError => e
209216
puts("The server could not be reached")
210217
puts(e.cause) # an underlying Exception, likely raised within `net/http`
@@ -247,7 +254,7 @@ stagehand = Stagehand::Client.new(
247254
)
248255

249256
# Or, configure per-request:
250-
stagehand.sessions.start(model_name: "openai/gpt-5-nano", request_options: {max_retries: 5})
257+
stagehand.sessions.start(model_name: "anthropic/claude-sonnet-4-6", request_options: {max_retries: 5})
251258
```
252259

253260
### Timeouts
@@ -261,7 +268,7 @@ stagehand = Stagehand::Client.new(
261268
)
262269

263270
# Or, configure per-request:
264-
stagehand.sessions.start(model_name: "openai/gpt-5-nano", request_options: {timeout: 5})
271+
stagehand.sessions.start(model_name: "anthropic/claude-sonnet-4-6", request_options: {timeout: 5})
265272
```
266273

267274
On timeout, `Stagehand::Errors::APITimeoutError` is raised.
@@ -293,7 +300,7 @@ Note: the `extra_` parameters of the same name overrides the documented paramete
293300
```ruby
294301
response =
295302
stagehand.sessions.start(
296-
model_name: "openai/gpt-5-nano",
303+
model_name: "anthropic/claude-sonnet-4-6",
297304
request_options: {
298305
extra_query: {my_query_parameter: value},
299306
extra_body: {my_body_parameter: value},

examples/local_browser_example.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def stream_with_result(label, stream)
5555

5656
begin
5757
start_response = client.sessions.start(
58-
model_name: "openai/gpt-5-nano",
58+
model_name: "anthropic/claude-sonnet-4-6",
5959
browser: {
6060
type: :local,
6161
launch_options: {
@@ -109,7 +109,7 @@ def stream_with_result(label, stream)
109109
},
110110
agent_config: {
111111
model: Stagehand::ModelConfig.new(
112-
model_name: "openai/gpt-5-nano",
112+
model_name: "anthropic/claude-sonnet-4-6",
113113
api_key: model_key
114114
),
115115
cua: false

examples/local_browser_playwright_example.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ def stream_with_result(label, stream)
7474
cdp_url = browser_server.ws_endpoint
7575

7676
start_response = client.sessions.start(
77-
model_name: "openai/gpt-5-nano",
77+
model_name: "anthropic/claude-sonnet-4-6",
7878
browser: {
7979
type: :local,
8080
launch_options: {
@@ -160,7 +160,7 @@ def stream_with_result(label, stream)
160160
},
161161
agent_config: {
162162
model: {
163-
model_name: "openai/gpt-5-nano",
163+
model_name: "anthropic/claude-sonnet-4-6",
164164
api_key: model_key
165165
},
166166
cua: false
@@ -176,7 +176,7 @@ def stream_with_result(label, stream)
176176
},
177177
agent_config: {
178178
model: {
179-
model_name: "openai/gpt-5-nano",
179+
model_name: "anthropic/claude-sonnet-4-6",
180180
api_key: model_key
181181
},
182182
cua: false

examples/local_playwright_example.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ def stream_with_result(label, stream)
119119
session_id = nil
120120
begin
121121
start_response = client.sessions.start(
122-
model_name: "openai/gpt-5-nano",
122+
model_name: "anthropic/claude-sonnet-4-6",
123123
browser: {
124124
type: :local,
125125
launch_options: {
@@ -174,7 +174,7 @@ def stream_with_result(label, stream)
174174
},
175175
agent_config: {
176176
model: Stagehand::ModelConfig.new(
177-
model_name: "openai/gpt-5-nano",
177+
model_name: "anthropic/claude-sonnet-4-6",
178178
api_key: model_key
179179
),
180180
cua: false

0 commit comments

Comments
 (0)