From 655f51718008b4c512eed1ce65660dae80039e49 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 18:37:48 +0000 Subject: [PATCH 01/12] feat(api): manual updates --- .github/workflows/publish-gem.yml | 31 ++++++++++++ .github/workflows/release-doctor.yml | 22 +++++++++ .release-please-manifest.json | 3 ++ .stats.yml | 2 +- CONTRIBUTING.md | 4 +- README.md | 8 +++- bin/check-release-environment | 21 +++++++++ release-please-config.json | 70 ++++++++++++++++++++++++++++ stagehand.gemspec | 2 +- 9 files changed, 157 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/publish-gem.yml create mode 100644 .github/workflows/release-doctor.yml create mode 100644 .release-please-manifest.json create mode 100644 bin/check-release-environment create mode 100644 release-please-config.json diff --git a/.github/workflows/publish-gem.yml b/.github/workflows/publish-gem.yml new file mode 100644 index 0000000..62df501 --- /dev/null +++ b/.github/workflows/publish-gem.yml @@ -0,0 +1,31 @@ +# This workflow is triggered when a GitHub release is created. +# It can also be run manually to re-publish to rubygems.org in case it failed for some reason. +# You can run this workflow by navigating to https://www.github.com/browserbase/stagehand-ruby/actions/workflows/publish-gem.yml +name: Publish Gem +on: + workflow_dispatch: + + release: + types: [published] + +jobs: + publish: + name: publish + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + bundler-cache: false + - run: |- + bundle install + + - name: Publish to RubyGems.org + run: | + bash ./bin/publish-gem + env: + # `RUBYGEMS_HOST` is only required for private gem repositories, not https://rubygems.org + RUBYGEMS_HOST: ${{ secrets.STAGEHAND_RUBYGEMS_HOST || secrets.RUBYGEMS_HOST }} + GEM_HOST_API_KEY: ${{ secrets.STAGEHAND_GEM_HOST_API_KEY || secrets.GEM_HOST_API_KEY }} diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml new file mode 100644 index 0000000..f5b4310 --- /dev/null +++ b/.github/workflows/release-doctor.yml @@ -0,0 +1,22 @@ +name: Release Doctor +on: + pull_request: + branches: + - main + workflow_dispatch: + +jobs: + release_doctor: + name: release doctor + runs-on: ubuntu-latest + if: github.repository == 'browserbase/stagehand-ruby' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') + + steps: + - uses: actions/checkout@v4 + + - name: Check release environment + run: | + bash ./bin/check-release-environment + env: + RUBYGEMS_HOST: ${{ secrets.STAGEHAND_RUBYGEMS_HOST || secrets.RUBYGEMS_HOST }} + GEM_HOST_API_KEY: ${{ secrets.STAGEHAND_GEM_HOST_API_KEY || secrets.GEM_HOST_API_KEY }} diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 0000000..1332969 --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "0.0.1" +} \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index acffb05..67a8e43 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-0c12f985340be2a9287e8e01ff8733f7f2d02e019149d1ae95f1a8f8798c6690.yml openapi_spec_hash: efb79934e1dc63763dd4e8493b825273 -config_hash: 5f3345d1d825e49f896f3b0e493e6938 +config_hash: cb2b1795c195a63201c8ef7a617934d1 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 89f025e..96554b4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -43,13 +43,13 @@ If you’d like to use the repository from source, you can either install from g To install via git in your `Gemfile`: ```ruby -gem "stagehand", git: "https://www.github.com/stainless-sdks/stagehand-ruby" +gem "stagehand", git: "https://www.github.com/browserbase/stagehand-ruby" ``` Alternatively, reference local copy of the repo: ```bash -$ git clone -- 'https://www.github.com/stainless-sdks/stagehand-ruby' '' +$ git clone -- 'https://www.github.com/browserbase/stagehand-ruby' '' ``` ```ruby diff --git a/README.md b/README.md index cb2c201..d4a2b87 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Stagehand Ruby API library -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/stainless-sdks/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. +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. It is generated with [Stainless](https://www.stainless.com/). @@ -14,10 +14,14 @@ The REST API documentation can be found on [browserbase.com](https://browserbase To use this gem, install via Bundler by adding the following to your application's `Gemfile`: + + ```ruby gem "stagehand", "~> 0.0.1" ``` + + ## Usage ```ruby @@ -229,4 +233,4 @@ Ruby 3.2.0 or higher. ## Contributing -See [the contributing documentation](https://github.com/stainless-sdks/stagehand-ruby/tree/main/CONTRIBUTING.md). +See [the contributing documentation](https://github.com/browserbase/stagehand-ruby/tree/main/CONTRIBUTING.md). diff --git a/bin/check-release-environment b/bin/check-release-environment new file mode 100644 index 0000000..c05436e --- /dev/null +++ b/bin/check-release-environment @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +errors=() + +if [ -z "${GEM_HOST_API_KEY}" ]; then + errors+=("The GEM_HOST_API_KEY secret has not been set. Please set it in either this repository's secrets or your organization secrets") +fi + +lenErrors=${#errors[@]} + +if [[ lenErrors -gt 0 ]]; then + echo -e "Found the following errors in the release environment:\n" + + for error in "${errors[@]}"; do + echo -e "- $error\n" + done + + exit 1 +fi + +echo "The environment is ready to push releases!" diff --git a/release-please-config.json b/release-please-config.json new file mode 100644 index 0000000..5e06294 --- /dev/null +++ b/release-please-config.json @@ -0,0 +1,70 @@ +{ + "packages": { + ".": {} + }, + "$schema": "https://raw.githubusercontent.com/stainless-api/release-please/main/schemas/config.json", + "include-v-in-tag": true, + "include-component-in-tag": false, + "versioning": "prerelease", + "prerelease": true, + "bump-minor-pre-major": true, + "bump-patch-for-minor-pre-major": false, + "pull-request-header": "Automated Release PR", + "pull-request-title-pattern": "release: ${version}", + "changelog-sections": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "perf", + "section": "Performance Improvements" + }, + { + "type": "revert", + "section": "Reverts" + }, + { + "type": "chore", + "section": "Chores" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "style", + "section": "Styles" + }, + { + "type": "refactor", + "section": "Refactors" + }, + { + "type": "test", + "section": "Tests", + "hidden": true + }, + { + "type": "build", + "section": "Build System" + }, + { + "type": "ci", + "section": "Continuous Integration", + "hidden": true + } + ], + "release-type": "ruby", + "version-file": "lib/stagehand/version.rb", + "extra-files": [ + { + "type": "ruby-readme", + "path": "README.md" + } + ] +} \ No newline at end of file diff --git a/stagehand.gemspec b/stagehand.gemspec index 79c5f4b..3b5af74 100644 --- a/stagehand.gemspec +++ b/stagehand.gemspec @@ -10,7 +10,7 @@ Gem::Specification.new do |s| s.email = "" s.homepage = "https://gemdocs.org/gems/stagehand" s.metadata["homepage_uri"] = s.homepage - s.metadata["source_code_uri"] = "https://github.com/stainless-sdks/stagehand-ruby" + s.metadata["source_code_uri"] = "https://github.com/browserbase/stagehand-ruby" s.metadata["rubygems_mfa_required"] = false.to_s s.required_ruby_version = ">= 3.2.0" From c48f36e307aafd9a2d6ac59d9857be789f29eaa1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 19:03:17 +0000 Subject: [PATCH 02/12] feat(api): tweak branding and fix some config fields --- .github/workflows/publish-gem.yml | 4 +- .github/workflows/release-doctor.yml | 4 +- .stats.yml | 2 +- LICENSE | 2 +- README.md | 32 +++++------ SECURITY.md | 2 +- lib/stagehand/client.rb | 25 ++++++--- rbi/stagehand/client.rbi | 16 +++--- sig/stagehand/client.rbs | 9 +-- stagehand.gemspec | 4 +- test/stagehand/client_test.rb | 67 +++++++++++++---------- test/stagehand/resources/sessions_test.rb | 14 ++--- test/stagehand/test_helper.rb | 2 +- 13 files changed, 101 insertions(+), 82 deletions(-) diff --git a/.github/workflows/publish-gem.yml b/.github/workflows/publish-gem.yml index 62df501..1bd509b 100644 --- a/.github/workflows/publish-gem.yml +++ b/.github/workflows/publish-gem.yml @@ -27,5 +27,5 @@ jobs: bash ./bin/publish-gem env: # `RUBYGEMS_HOST` is only required for private gem repositories, not https://rubygems.org - RUBYGEMS_HOST: ${{ secrets.STAGEHAND_RUBYGEMS_HOST || secrets.RUBYGEMS_HOST }} - GEM_HOST_API_KEY: ${{ secrets.STAGEHAND_GEM_HOST_API_KEY || secrets.GEM_HOST_API_KEY }} + RUBYGEMS_HOST: ${{ secrets.BROWSERBASE_RUBYGEMS_HOST || secrets.RUBYGEMS_HOST }} + GEM_HOST_API_KEY: ${{ secrets.BROWSERBASE_GEM_HOST_API_KEY || secrets.GEM_HOST_API_KEY }} diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index f5b4310..69cf7da 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -18,5 +18,5 @@ jobs: run: | bash ./bin/check-release-environment env: - RUBYGEMS_HOST: ${{ secrets.STAGEHAND_RUBYGEMS_HOST || secrets.RUBYGEMS_HOST }} - GEM_HOST_API_KEY: ${{ secrets.STAGEHAND_GEM_HOST_API_KEY || secrets.GEM_HOST_API_KEY }} + RUBYGEMS_HOST: ${{ secrets.BROWSERBASE_RUBYGEMS_HOST || secrets.RUBYGEMS_HOST }} + GEM_HOST_API_KEY: ${{ secrets.BROWSERBASE_GEM_HOST_API_KEY || secrets.GEM_HOST_API_KEY }} diff --git a/.stats.yml b/.stats.yml index 67a8e43..18b7af8 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-0c12f985340be2a9287e8e01ff8733f7f2d02e019149d1ae95f1a8f8798c6690.yml openapi_spec_hash: efb79934e1dc63763dd4e8493b825273 -config_hash: cb2b1795c195a63201c8ef7a617934d1 +config_hash: 1548ab91b7e8621f7fa79e8cff0c3f93 diff --git a/LICENSE b/LICENSE index 6b24314..2cec9d4 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2025 Stagehand + Copyright 2025 Browserbase Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index d4a2b87..bd7bc38 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# Stagehand Ruby API library +# Browserbase Ruby API library -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. +The Browserbase Ruby library provides convenient access to the Browserbase 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. It is generated with [Stainless](https://www.stainless.com/). @@ -28,12 +28,12 @@ gem "stagehand", "~> 0.0.1" require "bundler/setup" require "stagehand" -stagehand = Stagehand::Client.new( +browserbase = Stagehand::Client.new( api_key: ENV["STAGEHAND_API_KEY"], # This is the default and can be omitted - environment: "environment_1" # defaults to "production" + environment: "dev" # or "production" | "local"; defaults to "production" ) -response = stagehand.sessions.start(env: "LOCAL") +response = browserbase.sessions.start(env: "LOCAL") puts(response.available) ``` @@ -44,7 +44,7 @@ When the library is unable to connect to the API, or if the API returns a non-su ```ruby begin - session = stagehand.sessions.start(env: "LOCAL") + session = browserbase.sessions.start(env: "LOCAL") rescue Stagehand::Errors::APIConnectionError => e puts("The server could not be reached") puts(e.cause) # an underlying Exception, likely raised within `net/http` @@ -82,12 +82,12 @@ You can use the `max_retries` option to configure or disable this: ```ruby # Configure the default for all requests: -stagehand = Stagehand::Client.new( +browserbase = Stagehand::Client.new( max_retries: 0 # default is 2 ) # Or, configure per-request: -stagehand.sessions.start(env: "LOCAL", request_options: {max_retries: 5}) +browserbase.sessions.start(env: "LOCAL", request_options: {max_retries: 5}) ``` ### Timeouts @@ -96,12 +96,12 @@ By default, requests will time out after 60 seconds. You can use the timeout opt ```ruby # Configure the default for all requests: -stagehand = Stagehand::Client.new( +browserbase = Stagehand::Client.new( timeout: nil # default is 60 ) # Or, configure per-request: -stagehand.sessions.start(env: "LOCAL", request_options: {timeout: 5}) +browserbase.sessions.start(env: "LOCAL", request_options: {timeout: 5}) ``` On timeout, `Stagehand::Errors::APITimeoutError` is raised. @@ -132,7 +132,7 @@ Note: the `extra_` parameters of the same name overrides the documented paramete ```ruby response = - stagehand.sessions.start( + browserbase.sessions.start( env: "LOCAL", request_options: { extra_query: {my_query_parameter: value}, @@ -179,18 +179,18 @@ This library provides comprehensive [RBI](https://sorbet.org/docs/rbi) definitio You can provide typesafe request parameters like so: ```ruby -stagehand.sessions.start(env: "LOCAL") +browserbase.sessions.start(env: "LOCAL") ``` Or, equivalently: ```ruby # Hashes work, but are not typesafe: -stagehand.sessions.start(env: "LOCAL") +browserbase.sessions.start(env: "LOCAL") # You can also splat a full Params class: params = Stagehand::SessionStartParams.new(env: "LOCAL") -stagehand.sessions.start(**params) +browserbase.sessions.start(**params) ``` ### Enums @@ -209,13 +209,13 @@ Enum parameters have a "relaxed" type, so you can either pass in enum constants ```ruby # Using the enum constants preserves the tagged type information: -stagehand.sessions.act( +browserbase.sessions.act( x_stream_response: Stagehand::SessionActParams::XStreamResponse::TRUE, # … ) # Literal values are also permissible: -stagehand.sessions.act( +browserbase.sessions.act( x_stream_response: :true, # … ) diff --git a/SECURITY.md b/SECURITY.md index dcfc419..be1c2db 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -16,7 +16,7 @@ before making any information public. ## Reporting Non-SDK Related Security Issues If you encounter security issues that are not directly related to SDKs but pertain to the services -or products provided by Stagehand, please follow the respective company's security reporting guidelines. +or products provided by Browserbase, please follow the respective company's security reporting guidelines. --- diff --git a/lib/stagehand/client.rb b/lib/stagehand/client.rb index 965b308..a3365c5 100644 --- a/lib/stagehand/client.rb +++ b/lib/stagehand/client.rb @@ -18,10 +18,14 @@ class Client < Stagehand::Internal::Transport::BaseClient # rubocop:disable Style/MutableConstant # @type [Hash{Symbol=>String}] ENVIRONMENTS = - {production: "http://localhost:3000/v1", environment_1: "https://api.stagehand.browserbase.com/v1"} + { + production: "https://api.stagehand.browserbase.com/v1", + dev: "https://api.stagehand.dev.browserbase.com/v1", + local: "http://localhost:5000/v1" + } # rubocop:enable Style/MutableConstant - # @return [String, nil] + # @return [String] attr_reader :api_key # @return [Stagehand::Resources::Sessions] @@ -40,15 +44,16 @@ class Client < Stagehand::Internal::Transport::BaseClient # # @param api_key [String, nil] Defaults to `ENV["STAGEHAND_API_KEY"]` # - # @param environment [:production, :environment_1, nil] Specifies the environment to use for the API. + # @param environment [:production, :dev, :local, nil] Specifies the environment to use for the API. # # Each environment maps to a different base URL: # - # - `production` corresponds to `http://localhost:3000/v1` - # - `environment_1` corresponds to `https://api.stagehand.browserbase.com/v1` + # - `production` corresponds to `https://api.stagehand.browserbase.com/v1` + # - `dev` corresponds to `https://api.stagehand.dev.browserbase.com/v1` + # - `local` corresponds to `http://localhost:5000/v1` # # @param base_url [String, nil] Override the default base URL for the API, e.g., - # `"https://api.example.com/v2/"`. Defaults to `ENV["STAGEHAND_BASE_URL"]` + # `"https://api.example.com/v2/"`. Defaults to `ENV["BROWSERBASE_BASE_URL"]` # # @param max_retries [Integer] Max number of retries to attempt after a failed retryable request. # @@ -60,7 +65,7 @@ class Client < Stagehand::Internal::Transport::BaseClient def initialize( api_key: ENV["STAGEHAND_API_KEY"], environment: nil, - base_url: ENV["STAGEHAND_BASE_URL"], + base_url: ENV["BROWSERBASE_BASE_URL"], max_retries: self.class::DEFAULT_MAX_RETRIES, timeout: self.class::DEFAULT_TIMEOUT_IN_SECONDS, initial_retry_delay: self.class::DEFAULT_INITIAL_RETRY_DELAY, @@ -71,7 +76,11 @@ def initialize( raise ArgumentError.new(message) end - @api_key = api_key&.to_s + if api_key.nil? + raise ArgumentError.new("api_key is required, and can be set via environ: \"STAGEHAND_API_KEY\"") + end + + @api_key = api_key.to_s super( base_url: base_url, diff --git a/rbi/stagehand/client.rbi b/rbi/stagehand/client.rbi index ea48fce..7837c69 100644 --- a/rbi/stagehand/client.rbi +++ b/rbi/stagehand/client.rbi @@ -13,13 +13,14 @@ module Stagehand ENVIRONMENTS = T.let( { - production: "http://localhost:3000/v1", - environment_1: "https://api.stagehand.browserbase.com/v1" + production: "https://api.stagehand.browserbase.com/v1", + dev: "https://api.stagehand.dev.browserbase.com/v1", + local: "http://localhost:5000/v1" }, T::Hash[Symbol, String] ) - sig { returns(T.nilable(String)) } + sig { returns(String) } attr_reader :api_key sig { returns(Stagehand::Resources::Sessions) } @@ -49,12 +50,13 @@ module Stagehand # # Each environment maps to a different base URL: # - # - `production` corresponds to `http://localhost:3000/v1` - # - `environment_1` corresponds to `https://api.stagehand.browserbase.com/v1` + # - `production` corresponds to `https://api.stagehand.browserbase.com/v1` + # - `dev` corresponds to `https://api.stagehand.dev.browserbase.com/v1` + # - `local` corresponds to `http://localhost:5000/v1` environment: nil, # Override the default base URL for the API, e.g., - # `"https://api.example.com/v2/"`. Defaults to `ENV["STAGEHAND_BASE_URL"]` - base_url: ENV["STAGEHAND_BASE_URL"], + # `"https://api.example.com/v2/"`. Defaults to `ENV["BROWSERBASE_BASE_URL"]` + base_url: ENV["BROWSERBASE_BASE_URL"], # Max number of retries to attempt after a failed retryable request. max_retries: Stagehand::Client::DEFAULT_MAX_RETRIES, timeout: Stagehand::Client::DEFAULT_TIMEOUT_IN_SECONDS, diff --git a/sig/stagehand/client.rbs b/sig/stagehand/client.rbs index 119ac58..fe115d9 100644 --- a/sig/stagehand/client.rbs +++ b/sig/stagehand/client.rbs @@ -9,11 +9,12 @@ module Stagehand DEFAULT_MAX_RETRY_DELAY: Float ENVIRONMENTS: { - production: "http://localhost:3000/v1", - :environment_1 => "https://api.stagehand.browserbase.com/v1" + production: "https://api.stagehand.browserbase.com/v1", + dev: "https://api.stagehand.dev.browserbase.com/v1", + local: "http://localhost:5000/v1" } - attr_reader api_key: String? + attr_reader api_key: String attr_reader sessions: Stagehand::Resources::Sessions @@ -21,7 +22,7 @@ module Stagehand def initialize: ( ?api_key: String?, - ?environment: :production | :environment_1 | nil, + ?environment: :production | :dev | :local | nil, ?base_url: String?, ?max_retries: Integer, ?timeout: Float, diff --git a/stagehand.gemspec b/stagehand.gemspec index 3b5af74..601509b 100644 --- a/stagehand.gemspec +++ b/stagehand.gemspec @@ -5,8 +5,8 @@ require_relative "lib/stagehand/version" Gem::Specification.new do |s| s.name = "stagehand" s.version = Stagehand::VERSION - s.summary = "Ruby library to access the Stagehand API" - s.authors = ["Stagehand"] + s.summary = "Ruby library to access the Browserbase API" + s.authors = ["Browserbase"] s.email = "" s.homepage = "https://gemdocs.org/gems/stagehand" s.metadata["homepage_uri"] = s.homepage diff --git a/test/stagehand/client_test.rb b/test/stagehand/client_test.rb index 9a20293..8583c5d 100644 --- a/test/stagehand/client_test.rb +++ b/test/stagehand/client_test.rb @@ -34,13 +34,20 @@ def test_raises_on_unknown_environment assert_match(/environment must be one of/, e.message) end + def test_raises_on_missing_non_nullable_opts + e = assert_raises(ArgumentError) do + Stagehand::Client.new + end + assert_match(/is required/, e.message) + end + def test_client_default_request_default_retry_attempts stub_request(:post, "http://localhost/sessions/start").to_return_json(status: 500, body: {}) - stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") + browserbase = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") assert_raises(Stagehand::Errors::InternalServerError) do - stagehand.sessions.start(env: :LOCAL) + browserbase.sessions.start(env: :LOCAL) end assert_requested(:any, /./, times: 3) @@ -49,10 +56,10 @@ def test_client_default_request_default_retry_attempts def test_client_given_request_default_retry_attempts stub_request(:post, "http://localhost/sessions/start").to_return_json(status: 500, body: {}) - stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key", max_retries: 3) + browserbase = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key", max_retries: 3) assert_raises(Stagehand::Errors::InternalServerError) do - stagehand.sessions.start(env: :LOCAL) + browserbase.sessions.start(env: :LOCAL) end assert_requested(:any, /./, times: 4) @@ -61,10 +68,10 @@ def test_client_given_request_default_retry_attempts def test_client_default_request_given_retry_attempts stub_request(:post, "http://localhost/sessions/start").to_return_json(status: 500, body: {}) - stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") + browserbase = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") assert_raises(Stagehand::Errors::InternalServerError) do - stagehand.sessions.start(env: :LOCAL, request_options: {max_retries: 3}) + browserbase.sessions.start(env: :LOCAL, request_options: {max_retries: 3}) end assert_requested(:any, /./, times: 4) @@ -73,10 +80,10 @@ def test_client_default_request_given_retry_attempts def test_client_given_request_given_retry_attempts stub_request(:post, "http://localhost/sessions/start").to_return_json(status: 500, body: {}) - stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key", max_retries: 3) + browserbase = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key", max_retries: 3) assert_raises(Stagehand::Errors::InternalServerError) do - stagehand.sessions.start(env: :LOCAL, request_options: {max_retries: 4}) + browserbase.sessions.start(env: :LOCAL, request_options: {max_retries: 4}) end assert_requested(:any, /./, times: 5) @@ -89,10 +96,10 @@ def test_client_retry_after_seconds body: {} ) - stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key", max_retries: 1) + browserbase = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key", max_retries: 1) assert_raises(Stagehand::Errors::InternalServerError) do - stagehand.sessions.start(env: :LOCAL) + browserbase.sessions.start(env: :LOCAL) end assert_requested(:any, /./, times: 2) @@ -106,11 +113,11 @@ def test_client_retry_after_date body: {} ) - stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key", max_retries: 1) + browserbase = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key", max_retries: 1) assert_raises(Stagehand::Errors::InternalServerError) do Thread.current.thread_variable_set(:time_now, Time.now) - stagehand.sessions.start(env: :LOCAL) + browserbase.sessions.start(env: :LOCAL) Thread.current.thread_variable_set(:time_now, nil) end @@ -125,10 +132,10 @@ def test_client_retry_after_ms body: {} ) - stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key", max_retries: 1) + browserbase = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key", max_retries: 1) assert_raises(Stagehand::Errors::InternalServerError) do - stagehand.sessions.start(env: :LOCAL) + browserbase.sessions.start(env: :LOCAL) end assert_requested(:any, /./, times: 2) @@ -138,10 +145,10 @@ def test_client_retry_after_ms def test_retry_count_header stub_request(:post, "http://localhost/sessions/start").to_return_json(status: 500, body: {}) - stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") + browserbase = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") assert_raises(Stagehand::Errors::InternalServerError) do - stagehand.sessions.start(env: :LOCAL) + browserbase.sessions.start(env: :LOCAL) end 3.times do @@ -152,10 +159,10 @@ def test_retry_count_header def test_omit_retry_count_header stub_request(:post, "http://localhost/sessions/start").to_return_json(status: 500, body: {}) - stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") + browserbase = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") assert_raises(Stagehand::Errors::InternalServerError) do - stagehand.sessions.start( + browserbase.sessions.start( env: :LOCAL, request_options: {extra_headers: {"x-stainless-retry-count" => nil}} ) @@ -169,10 +176,10 @@ def test_omit_retry_count_header def test_overwrite_retry_count_header stub_request(:post, "http://localhost/sessions/start").to_return_json(status: 500, body: {}) - stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") + browserbase = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") assert_raises(Stagehand::Errors::InternalServerError) do - stagehand.sessions.start( + browserbase.sessions.start( env: :LOCAL, request_options: {extra_headers: {"x-stainless-retry-count" => "42"}} ) @@ -192,10 +199,10 @@ def test_client_redirect_307 headers: {"location" => "/redirected"} ) - stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") + browserbase = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") assert_raises(Stagehand::Errors::APIConnectionError) do - stagehand.sessions.start(env: :LOCAL, request_options: {extra_headers: {}}) + browserbase.sessions.start(env: :LOCAL, request_options: {extra_headers: {}}) end recorded, = WebMock::RequestRegistry.instance.requested_signatures.hash.first @@ -221,10 +228,10 @@ def test_client_redirect_303 headers: {"location" => "/redirected"} ) - stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") + browserbase = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") assert_raises(Stagehand::Errors::APIConnectionError) do - stagehand.sessions.start(env: :LOCAL, request_options: {extra_headers: {}}) + browserbase.sessions.start(env: :LOCAL, request_options: {extra_headers: {}}) end assert_requested(:get, "http://localhost/redirected", times: Stagehand::Client::MAX_REDIRECTS) do @@ -245,10 +252,10 @@ def test_client_redirect_auth_keep_same_origin headers: {"location" => "/redirected"} ) - stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") + browserbase = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") assert_raises(Stagehand::Errors::APIConnectionError) do - stagehand.sessions.start( + browserbase.sessions.start( env: :LOCAL, request_options: {extra_headers: {"authorization" => "Bearer xyz"}} ) @@ -275,10 +282,10 @@ def test_client_redirect_auth_strip_cross_origin headers: {"location" => "https://example.com/redirected"} ) - stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") + browserbase = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") assert_raises(Stagehand::Errors::APIConnectionError) do - stagehand.sessions.start( + browserbase.sessions.start( env: :LOCAL, request_options: {extra_headers: {"authorization" => "Bearer xyz"}} ) @@ -293,9 +300,9 @@ def test_client_redirect_auth_strip_cross_origin def test_default_headers stub_request(:post, "http://localhost/sessions/start").to_return_json(status: 200, body: {}) - stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") + browserbase = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") - stagehand.sessions.start(env: :LOCAL) + browserbase.sessions.start(env: :LOCAL) assert_requested(:any, /./) do |req| headers = req.headers.transform_keys(&:downcase).fetch_values("accept", "content-type") diff --git a/test/stagehand/resources/sessions_test.rb b/test/stagehand/resources/sessions_test.rb index 1864622..e063c7f 100644 --- a/test/stagehand/resources/sessions_test.rb +++ b/test/stagehand/resources/sessions_test.rb @@ -7,7 +7,7 @@ def test_act_required_params skip("Prism tests are disabled") response = - @stagehand.sessions.act("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", input: "click the sign in button") + @browserbase.sessions.act("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", input: "click the sign in button") assert_pattern do response => Stagehand::Models::SessionActResponse @@ -25,7 +25,7 @@ def test_act_required_params def test_end_ skip("Prism tests are disabled") - response = @stagehand.sessions.end_("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + response = @browserbase.sessions.end_("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") assert_pattern do response => Stagehand::Models::SessionEndResponse @@ -42,7 +42,7 @@ def test_execute_agent_required_params skip("Prism tests are disabled") response = - @stagehand.sessions.execute_agent( + @browserbase.sessions.execute_agent( "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", agent_config: {}, execute_options: {instruction: "Find and click the first product"} @@ -63,7 +63,7 @@ def test_execute_agent_required_params def test_extract skip("Prism tests are disabled") - response = @stagehand.sessions.extract("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + response = @browserbase.sessions.extract("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") assert_pattern do response => Stagehand::Models::SessionExtractResponse @@ -81,7 +81,7 @@ def test_navigate_required_params skip("Prism tests are disabled") response = - @stagehand.sessions.navigate("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", url: "https://example.com") + @browserbase.sessions.navigate("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", url: "https://example.com") assert_pattern do response => Stagehand::Models::SessionNavigateResponse @@ -99,7 +99,7 @@ def test_navigate_required_params def test_observe skip("Prism tests are disabled") - response = @stagehand.sessions.observe("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + response = @browserbase.sessions.observe("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") assert_pattern do response => ^(Stagehand::Internal::Type::ArrayOf[Stagehand::Action]) @@ -109,7 +109,7 @@ def test_observe def test_start_required_params skip("Prism tests are disabled") - response = @stagehand.sessions.start(env: :LOCAL) + response = @browserbase.sessions.start(env: :LOCAL) assert_pattern do response => Stagehand::Models::SessionStartResponse diff --git a/test/stagehand/test_helper.rb b/test/stagehand/test_helper.rb index 496dbbe..88c4a03 100644 --- a/test/stagehand/test_helper.rb +++ b/test/stagehand/test_helper.rb @@ -74,7 +74,7 @@ def async? def before_all super - @stagehand = Stagehand::Test::SingletonClient.instance + @browserbase = Stagehand::Test::SingletonClient.instance end def around_all = async? ? Sync { super } : super From 87416c46d63864430f360a1fe0ac7ecd45501a88 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 19:14:16 +0000 Subject: [PATCH 03/12] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 18b7af8..ae2d02d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-0c12f985340be2a9287e8e01ff8733f7f2d02e019149d1ae95f1a8f8798c6690.yml openapi_spec_hash: efb79934e1dc63763dd4e8493b825273 -config_hash: 1548ab91b7e8621f7fa79e8cff0c3f93 +config_hash: 905fc70fd4344c8631aab6754bffd883 From 8355d5e6b83f6c31f6494f771fba51b6e31023e7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 19:18:46 +0000 Subject: [PATCH 04/12] feat(api): manual updates --- .github/workflows/publish-gem.yml | 4 +- .github/workflows/release-doctor.yml | 4 +- .stats.yml | 2 +- LICENSE | 2 +- README.md | 32 ++++++------ SECURITY.md | 2 +- lib/stagehand/client.rb | 4 +- rbi/stagehand/client.rbi | 4 +- stagehand.gemspec | 4 +- test/stagehand/client_test.rb | 60 +++++++++++------------ test/stagehand/resources/sessions_test.rb | 14 +++--- test/stagehand/test_helper.rb | 2 +- 12 files changed, 67 insertions(+), 67 deletions(-) diff --git a/.github/workflows/publish-gem.yml b/.github/workflows/publish-gem.yml index 1bd509b..62df501 100644 --- a/.github/workflows/publish-gem.yml +++ b/.github/workflows/publish-gem.yml @@ -27,5 +27,5 @@ jobs: bash ./bin/publish-gem env: # `RUBYGEMS_HOST` is only required for private gem repositories, not https://rubygems.org - RUBYGEMS_HOST: ${{ secrets.BROWSERBASE_RUBYGEMS_HOST || secrets.RUBYGEMS_HOST }} - GEM_HOST_API_KEY: ${{ secrets.BROWSERBASE_GEM_HOST_API_KEY || secrets.GEM_HOST_API_KEY }} + RUBYGEMS_HOST: ${{ secrets.STAGEHAND_RUBYGEMS_HOST || secrets.RUBYGEMS_HOST }} + GEM_HOST_API_KEY: ${{ secrets.STAGEHAND_GEM_HOST_API_KEY || secrets.GEM_HOST_API_KEY }} diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 69cf7da..f5b4310 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -18,5 +18,5 @@ jobs: run: | bash ./bin/check-release-environment env: - RUBYGEMS_HOST: ${{ secrets.BROWSERBASE_RUBYGEMS_HOST || secrets.RUBYGEMS_HOST }} - GEM_HOST_API_KEY: ${{ secrets.BROWSERBASE_GEM_HOST_API_KEY || secrets.GEM_HOST_API_KEY }} + RUBYGEMS_HOST: ${{ secrets.STAGEHAND_RUBYGEMS_HOST || secrets.RUBYGEMS_HOST }} + GEM_HOST_API_KEY: ${{ secrets.STAGEHAND_GEM_HOST_API_KEY || secrets.GEM_HOST_API_KEY }} diff --git a/.stats.yml b/.stats.yml index ae2d02d..8741890 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-0c12f985340be2a9287e8e01ff8733f7f2d02e019149d1ae95f1a8f8798c6690.yml openapi_spec_hash: efb79934e1dc63763dd4e8493b825273 -config_hash: 905fc70fd4344c8631aab6754bffd883 +config_hash: 1de7cb9bd4dc46fe3e20b637bc534908 diff --git a/LICENSE b/LICENSE index 2cec9d4..6b24314 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2025 Browserbase + Copyright 2025 Stagehand Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index bd7bc38..171eb11 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# Browserbase Ruby API library +# Stagehand Ruby API library -The Browserbase Ruby library provides convenient access to the Browserbase 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. +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. It is generated with [Stainless](https://www.stainless.com/). @@ -8,7 +8,7 @@ It is generated with [Stainless](https://www.stainless.com/). Documentation for releases of this gem can be found [on RubyDoc](https://gemdocs.org/gems/stagehand). -The REST API documentation can be found on [browserbase.com](https://browserbase.com). +The REST API documentation can be found on [docs.stagehand.dev](https://docs.stagehand.dev). ## Installation @@ -28,12 +28,12 @@ gem "stagehand", "~> 0.0.1" require "bundler/setup" require "stagehand" -browserbase = Stagehand::Client.new( +stagehand = Stagehand::Client.new( api_key: ENV["STAGEHAND_API_KEY"], # This is the default and can be omitted environment: "dev" # or "production" | "local"; defaults to "production" ) -response = browserbase.sessions.start(env: "LOCAL") +response = stagehand.sessions.start(env: "LOCAL") puts(response.available) ``` @@ -44,7 +44,7 @@ When the library is unable to connect to the API, or if the API returns a non-su ```ruby begin - session = browserbase.sessions.start(env: "LOCAL") + session = stagehand.sessions.start(env: "LOCAL") rescue Stagehand::Errors::APIConnectionError => e puts("The server could not be reached") puts(e.cause) # an underlying Exception, likely raised within `net/http` @@ -82,12 +82,12 @@ You can use the `max_retries` option to configure or disable this: ```ruby # Configure the default for all requests: -browserbase = Stagehand::Client.new( +stagehand = Stagehand::Client.new( max_retries: 0 # default is 2 ) # Or, configure per-request: -browserbase.sessions.start(env: "LOCAL", request_options: {max_retries: 5}) +stagehand.sessions.start(env: "LOCAL", request_options: {max_retries: 5}) ``` ### Timeouts @@ -96,12 +96,12 @@ By default, requests will time out after 60 seconds. You can use the timeout opt ```ruby # Configure the default for all requests: -browserbase = Stagehand::Client.new( +stagehand = Stagehand::Client.new( timeout: nil # default is 60 ) # Or, configure per-request: -browserbase.sessions.start(env: "LOCAL", request_options: {timeout: 5}) +stagehand.sessions.start(env: "LOCAL", request_options: {timeout: 5}) ``` On timeout, `Stagehand::Errors::APITimeoutError` is raised. @@ -132,7 +132,7 @@ Note: the `extra_` parameters of the same name overrides the documented paramete ```ruby response = - browserbase.sessions.start( + stagehand.sessions.start( env: "LOCAL", request_options: { extra_query: {my_query_parameter: value}, @@ -179,18 +179,18 @@ This library provides comprehensive [RBI](https://sorbet.org/docs/rbi) definitio You can provide typesafe request parameters like so: ```ruby -browserbase.sessions.start(env: "LOCAL") +stagehand.sessions.start(env: "LOCAL") ``` Or, equivalently: ```ruby # Hashes work, but are not typesafe: -browserbase.sessions.start(env: "LOCAL") +stagehand.sessions.start(env: "LOCAL") # You can also splat a full Params class: params = Stagehand::SessionStartParams.new(env: "LOCAL") -browserbase.sessions.start(**params) +stagehand.sessions.start(**params) ``` ### Enums @@ -209,13 +209,13 @@ Enum parameters have a "relaxed" type, so you can either pass in enum constants ```ruby # Using the enum constants preserves the tagged type information: -browserbase.sessions.act( +stagehand.sessions.act( x_stream_response: Stagehand::SessionActParams::XStreamResponse::TRUE, # … ) # Literal values are also permissible: -browserbase.sessions.act( +stagehand.sessions.act( x_stream_response: :true, # … ) diff --git a/SECURITY.md b/SECURITY.md index be1c2db..dcfc419 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -16,7 +16,7 @@ before making any information public. ## Reporting Non-SDK Related Security Issues If you encounter security issues that are not directly related to SDKs but pertain to the services -or products provided by Browserbase, please follow the respective company's security reporting guidelines. +or products provided by Stagehand, please follow the respective company's security reporting guidelines. --- diff --git a/lib/stagehand/client.rb b/lib/stagehand/client.rb index a3365c5..234444b 100644 --- a/lib/stagehand/client.rb +++ b/lib/stagehand/client.rb @@ -53,7 +53,7 @@ class Client < Stagehand::Internal::Transport::BaseClient # - `local` corresponds to `http://localhost:5000/v1` # # @param base_url [String, nil] Override the default base URL for the API, e.g., - # `"https://api.example.com/v2/"`. Defaults to `ENV["BROWSERBASE_BASE_URL"]` + # `"https://api.example.com/v2/"`. Defaults to `ENV["STAGEHAND_BASE_URL"]` # # @param max_retries [Integer] Max number of retries to attempt after a failed retryable request. # @@ -65,7 +65,7 @@ class Client < Stagehand::Internal::Transport::BaseClient def initialize( api_key: ENV["STAGEHAND_API_KEY"], environment: nil, - base_url: ENV["BROWSERBASE_BASE_URL"], + base_url: ENV["STAGEHAND_BASE_URL"], max_retries: self.class::DEFAULT_MAX_RETRIES, timeout: self.class::DEFAULT_TIMEOUT_IN_SECONDS, initial_retry_delay: self.class::DEFAULT_INITIAL_RETRY_DELAY, diff --git a/rbi/stagehand/client.rbi b/rbi/stagehand/client.rbi index 7837c69..d5fc53e 100644 --- a/rbi/stagehand/client.rbi +++ b/rbi/stagehand/client.rbi @@ -55,8 +55,8 @@ module Stagehand # - `local` corresponds to `http://localhost:5000/v1` environment: nil, # Override the default base URL for the API, e.g., - # `"https://api.example.com/v2/"`. Defaults to `ENV["BROWSERBASE_BASE_URL"]` - base_url: ENV["BROWSERBASE_BASE_URL"], + # `"https://api.example.com/v2/"`. Defaults to `ENV["STAGEHAND_BASE_URL"]` + base_url: ENV["STAGEHAND_BASE_URL"], # Max number of retries to attempt after a failed retryable request. max_retries: Stagehand::Client::DEFAULT_MAX_RETRIES, timeout: Stagehand::Client::DEFAULT_TIMEOUT_IN_SECONDS, diff --git a/stagehand.gemspec b/stagehand.gemspec index 601509b..3b5af74 100644 --- a/stagehand.gemspec +++ b/stagehand.gemspec @@ -5,8 +5,8 @@ require_relative "lib/stagehand/version" Gem::Specification.new do |s| s.name = "stagehand" s.version = Stagehand::VERSION - s.summary = "Ruby library to access the Browserbase API" - s.authors = ["Browserbase"] + s.summary = "Ruby library to access the Stagehand API" + s.authors = ["Stagehand"] s.email = "" s.homepage = "https://gemdocs.org/gems/stagehand" s.metadata["homepage_uri"] = s.homepage diff --git a/test/stagehand/client_test.rb b/test/stagehand/client_test.rb index 8583c5d..5abdb48 100644 --- a/test/stagehand/client_test.rb +++ b/test/stagehand/client_test.rb @@ -44,10 +44,10 @@ def test_raises_on_missing_non_nullable_opts def test_client_default_request_default_retry_attempts stub_request(:post, "http://localhost/sessions/start").to_return_json(status: 500, body: {}) - browserbase = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") + stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") assert_raises(Stagehand::Errors::InternalServerError) do - browserbase.sessions.start(env: :LOCAL) + stagehand.sessions.start(env: :LOCAL) end assert_requested(:any, /./, times: 3) @@ -56,10 +56,10 @@ def test_client_default_request_default_retry_attempts def test_client_given_request_default_retry_attempts stub_request(:post, "http://localhost/sessions/start").to_return_json(status: 500, body: {}) - browserbase = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key", max_retries: 3) + stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key", max_retries: 3) assert_raises(Stagehand::Errors::InternalServerError) do - browserbase.sessions.start(env: :LOCAL) + stagehand.sessions.start(env: :LOCAL) end assert_requested(:any, /./, times: 4) @@ -68,10 +68,10 @@ def test_client_given_request_default_retry_attempts def test_client_default_request_given_retry_attempts stub_request(:post, "http://localhost/sessions/start").to_return_json(status: 500, body: {}) - browserbase = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") + stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") assert_raises(Stagehand::Errors::InternalServerError) do - browserbase.sessions.start(env: :LOCAL, request_options: {max_retries: 3}) + stagehand.sessions.start(env: :LOCAL, request_options: {max_retries: 3}) end assert_requested(:any, /./, times: 4) @@ -80,10 +80,10 @@ def test_client_default_request_given_retry_attempts def test_client_given_request_given_retry_attempts stub_request(:post, "http://localhost/sessions/start").to_return_json(status: 500, body: {}) - browserbase = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key", max_retries: 3) + stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key", max_retries: 3) assert_raises(Stagehand::Errors::InternalServerError) do - browserbase.sessions.start(env: :LOCAL, request_options: {max_retries: 4}) + stagehand.sessions.start(env: :LOCAL, request_options: {max_retries: 4}) end assert_requested(:any, /./, times: 5) @@ -96,10 +96,10 @@ def test_client_retry_after_seconds body: {} ) - browserbase = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key", max_retries: 1) + stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key", max_retries: 1) assert_raises(Stagehand::Errors::InternalServerError) do - browserbase.sessions.start(env: :LOCAL) + stagehand.sessions.start(env: :LOCAL) end assert_requested(:any, /./, times: 2) @@ -113,11 +113,11 @@ def test_client_retry_after_date body: {} ) - browserbase = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key", max_retries: 1) + stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key", max_retries: 1) assert_raises(Stagehand::Errors::InternalServerError) do Thread.current.thread_variable_set(:time_now, Time.now) - browserbase.sessions.start(env: :LOCAL) + stagehand.sessions.start(env: :LOCAL) Thread.current.thread_variable_set(:time_now, nil) end @@ -132,10 +132,10 @@ def test_client_retry_after_ms body: {} ) - browserbase = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key", max_retries: 1) + stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key", max_retries: 1) assert_raises(Stagehand::Errors::InternalServerError) do - browserbase.sessions.start(env: :LOCAL) + stagehand.sessions.start(env: :LOCAL) end assert_requested(:any, /./, times: 2) @@ -145,10 +145,10 @@ def test_client_retry_after_ms def test_retry_count_header stub_request(:post, "http://localhost/sessions/start").to_return_json(status: 500, body: {}) - browserbase = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") + stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") assert_raises(Stagehand::Errors::InternalServerError) do - browserbase.sessions.start(env: :LOCAL) + stagehand.sessions.start(env: :LOCAL) end 3.times do @@ -159,10 +159,10 @@ def test_retry_count_header def test_omit_retry_count_header stub_request(:post, "http://localhost/sessions/start").to_return_json(status: 500, body: {}) - browserbase = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") + stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") assert_raises(Stagehand::Errors::InternalServerError) do - browserbase.sessions.start( + stagehand.sessions.start( env: :LOCAL, request_options: {extra_headers: {"x-stainless-retry-count" => nil}} ) @@ -176,10 +176,10 @@ def test_omit_retry_count_header def test_overwrite_retry_count_header stub_request(:post, "http://localhost/sessions/start").to_return_json(status: 500, body: {}) - browserbase = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") + stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") assert_raises(Stagehand::Errors::InternalServerError) do - browserbase.sessions.start( + stagehand.sessions.start( env: :LOCAL, request_options: {extra_headers: {"x-stainless-retry-count" => "42"}} ) @@ -199,10 +199,10 @@ def test_client_redirect_307 headers: {"location" => "/redirected"} ) - browserbase = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") + stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") assert_raises(Stagehand::Errors::APIConnectionError) do - browserbase.sessions.start(env: :LOCAL, request_options: {extra_headers: {}}) + stagehand.sessions.start(env: :LOCAL, request_options: {extra_headers: {}}) end recorded, = WebMock::RequestRegistry.instance.requested_signatures.hash.first @@ -228,10 +228,10 @@ def test_client_redirect_303 headers: {"location" => "/redirected"} ) - browserbase = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") + stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") assert_raises(Stagehand::Errors::APIConnectionError) do - browserbase.sessions.start(env: :LOCAL, request_options: {extra_headers: {}}) + stagehand.sessions.start(env: :LOCAL, request_options: {extra_headers: {}}) end assert_requested(:get, "http://localhost/redirected", times: Stagehand::Client::MAX_REDIRECTS) do @@ -252,10 +252,10 @@ def test_client_redirect_auth_keep_same_origin headers: {"location" => "/redirected"} ) - browserbase = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") + stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") assert_raises(Stagehand::Errors::APIConnectionError) do - browserbase.sessions.start( + stagehand.sessions.start( env: :LOCAL, request_options: {extra_headers: {"authorization" => "Bearer xyz"}} ) @@ -282,10 +282,10 @@ def test_client_redirect_auth_strip_cross_origin headers: {"location" => "https://example.com/redirected"} ) - browserbase = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") + stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") assert_raises(Stagehand::Errors::APIConnectionError) do - browserbase.sessions.start( + stagehand.sessions.start( env: :LOCAL, request_options: {extra_headers: {"authorization" => "Bearer xyz"}} ) @@ -300,9 +300,9 @@ def test_client_redirect_auth_strip_cross_origin def test_default_headers stub_request(:post, "http://localhost/sessions/start").to_return_json(status: 200, body: {}) - browserbase = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") + stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") - browserbase.sessions.start(env: :LOCAL) + stagehand.sessions.start(env: :LOCAL) assert_requested(:any, /./) do |req| headers = req.headers.transform_keys(&:downcase).fetch_values("accept", "content-type") diff --git a/test/stagehand/resources/sessions_test.rb b/test/stagehand/resources/sessions_test.rb index e063c7f..1864622 100644 --- a/test/stagehand/resources/sessions_test.rb +++ b/test/stagehand/resources/sessions_test.rb @@ -7,7 +7,7 @@ def test_act_required_params skip("Prism tests are disabled") response = - @browserbase.sessions.act("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", input: "click the sign in button") + @stagehand.sessions.act("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", input: "click the sign in button") assert_pattern do response => Stagehand::Models::SessionActResponse @@ -25,7 +25,7 @@ def test_act_required_params def test_end_ skip("Prism tests are disabled") - response = @browserbase.sessions.end_("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + response = @stagehand.sessions.end_("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") assert_pattern do response => Stagehand::Models::SessionEndResponse @@ -42,7 +42,7 @@ def test_execute_agent_required_params skip("Prism tests are disabled") response = - @browserbase.sessions.execute_agent( + @stagehand.sessions.execute_agent( "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", agent_config: {}, execute_options: {instruction: "Find and click the first product"} @@ -63,7 +63,7 @@ def test_execute_agent_required_params def test_extract skip("Prism tests are disabled") - response = @browserbase.sessions.extract("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + response = @stagehand.sessions.extract("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") assert_pattern do response => Stagehand::Models::SessionExtractResponse @@ -81,7 +81,7 @@ def test_navigate_required_params skip("Prism tests are disabled") response = - @browserbase.sessions.navigate("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", url: "https://example.com") + @stagehand.sessions.navigate("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", url: "https://example.com") assert_pattern do response => Stagehand::Models::SessionNavigateResponse @@ -99,7 +99,7 @@ def test_navigate_required_params def test_observe skip("Prism tests are disabled") - response = @browserbase.sessions.observe("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + response = @stagehand.sessions.observe("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") assert_pattern do response => ^(Stagehand::Internal::Type::ArrayOf[Stagehand::Action]) @@ -109,7 +109,7 @@ def test_observe def test_start_required_params skip("Prism tests are disabled") - response = @browserbase.sessions.start(env: :LOCAL) + response = @stagehand.sessions.start(env: :LOCAL) assert_pattern do response => Stagehand::Models::SessionStartResponse diff --git a/test/stagehand/test_helper.rb b/test/stagehand/test_helper.rb index 88c4a03..496dbbe 100644 --- a/test/stagehand/test_helper.rb +++ b/test/stagehand/test_helper.rb @@ -74,7 +74,7 @@ def async? def before_all super - @browserbase = Stagehand::Test::SingletonClient.instance + @stagehand = Stagehand::Test::SingletonClient.instance end def around_all = async? ? Sync { super } : super From 0cb20b1599698fa3780c6165aed52b332a2cd5cf Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 19:21:50 +0000 Subject: [PATCH 05/12] codegen metadata --- .stats.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 8741890..c128648 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-0c12f985340be2a9287e8e01ff8733f7f2d02e019149d1ae95f1a8f8798c6690.yml -openapi_spec_hash: efb79934e1dc63763dd4e8493b825273 -config_hash: 1de7cb9bd4dc46fe3e20b637bc534908 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-cacb08bfd03b2d325b80318fc3f12bc7da16f229c21e9bd86050fff4ef7c67f7.yml +openapi_spec_hash: 21dc2123dc758a738591bf914410041a +config_hash: bb7561632c1f66c2b9efca06f438f904 From 431fa726a44070c66c15a501358691b683ec6609 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 19:28:31 +0000 Subject: [PATCH 06/12] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index c128648..a06fa53 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-cacb08bfd03b2d325b80318fc3f12bc7da16f229c21e9bd86050fff4ef7c67f7.yml -openapi_spec_hash: 21dc2123dc758a738591bf914410041a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-09064f4021f94fb1b1bd86ce496d998318276b61bbc24de4728ecdb5763847ef.yml +openapi_spec_hash: 911d0631010b372890f98545a038cfb5 config_hash: bb7561632c1f66c2b9efca06f438f904 From 0bcedbaf26918822abdc958e6020f68b263ffee0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 19:39:30 +0000 Subject: [PATCH 07/12] feat(api): manual updates --- .stats.yml | 6 +- README.md | 32 +++-- lib/stagehand/models/session_start_params.rb | 67 ++-------- lib/stagehand/resources/sessions.rb | 12 +- rbi/stagehand/models/session_start_params.rbi | 114 +++--------------- rbi/stagehand/resources/sessions.rbi | 21 ++-- sig/stagehand/models/session_start_params.rbs | 57 ++------- sig/stagehand/resources/sessions.rbs | 6 +- test/stagehand/client_test.rb | 71 ++++++++--- test/stagehand/resources/sessions_test.rb | 6 +- 10 files changed, 136 insertions(+), 256 deletions(-) diff --git a/.stats.yml b/.stats.yml index a06fa53..4664845 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-09064f4021f94fb1b1bd86ce496d998318276b61bbc24de4728ecdb5763847ef.yml -openapi_spec_hash: 911d0631010b372890f98545a038cfb5 -config_hash: bb7561632c1f66c2b9efca06f438f904 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-6a22863a7da4fa45f904657a4cb8fc1a28e236925f03dc94fca25fd8271ca6db.yml +openapi_spec_hash: d5c6108942ad79f39ea4ff1bee9b7996 +config_hash: 2f1ec44e7e07906e07bdc6e075763da9 diff --git a/README.md b/README.md index 171eb11..360dcbe 100644 --- a/README.md +++ b/README.md @@ -33,9 +33,9 @@ stagehand = Stagehand::Client.new( environment: "dev" # or "production" | "local"; defaults to "production" ) -response = stagehand.sessions.start(env: "LOCAL") +response = stagehand.sessions.act("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", input: "click the first link on the page") -puts(response.available) +puts(response.actions) ``` ### Handling errors @@ -44,7 +44,10 @@ When the library is unable to connect to the API, or if the API returns a non-su ```ruby begin - session = stagehand.sessions.start(env: "LOCAL") + session = stagehand.sessions.start( + browserbase_api_key: "BROWSERBASE_API_KEY", + browserbase_project_id: "BROWSERBASE_PROJECT_ID" + ) rescue Stagehand::Errors::APIConnectionError => e puts("The server could not be reached") puts(e.cause) # an underlying Exception, likely raised within `net/http` @@ -87,7 +90,11 @@ stagehand = Stagehand::Client.new( ) # Or, configure per-request: -stagehand.sessions.start(env: "LOCAL", request_options: {max_retries: 5}) +stagehand.sessions.start( + browserbase_api_key: "BROWSERBASE_API_KEY", + browserbase_project_id: "BROWSERBASE_PROJECT_ID", + request_options: {max_retries: 5} +) ``` ### Timeouts @@ -101,7 +108,11 @@ stagehand = Stagehand::Client.new( ) # Or, configure per-request: -stagehand.sessions.start(env: "LOCAL", request_options: {timeout: 5}) +stagehand.sessions.start( + browserbase_api_key: "BROWSERBASE_API_KEY", + browserbase_project_id: "BROWSERBASE_PROJECT_ID", + request_options: {timeout: 5} +) ``` On timeout, `Stagehand::Errors::APITimeoutError` is raised. @@ -133,7 +144,8 @@ Note: the `extra_` parameters of the same name overrides the documented paramete ```ruby response = stagehand.sessions.start( - env: "LOCAL", + browserbase_api_key: "BROWSERBASE_API_KEY", + browserbase_project_id: "BROWSERBASE_PROJECT_ID", request_options: { extra_query: {my_query_parameter: value}, extra_body: {my_body_parameter: value}, @@ -179,18 +191,18 @@ This library provides comprehensive [RBI](https://sorbet.org/docs/rbi) definitio You can provide typesafe request parameters like so: ```ruby -stagehand.sessions.start(env: "LOCAL") +stagehand.sessions.act("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", input: "click the first link on the page") ``` Or, equivalently: ```ruby # Hashes work, but are not typesafe: -stagehand.sessions.start(env: "LOCAL") +stagehand.sessions.act("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", input: "click the first link on the page") # You can also splat a full Params class: -params = Stagehand::SessionStartParams.new(env: "LOCAL") -stagehand.sessions.start(**params) +params = Stagehand::SessionActParams.new(input: "click the first link on the page") +stagehand.sessions.act("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", **params) ``` ### Enums diff --git a/lib/stagehand/models/session_start_params.rb b/lib/stagehand/models/session_start_params.rb index 473dac3..f5d0549 100644 --- a/lib/stagehand/models/session_start_params.rb +++ b/lib/stagehand/models/session_start_params.rb @@ -7,17 +7,17 @@ class SessionStartParams < Stagehand::Internal::Type::BaseModel extend Stagehand::Internal::Type::RequestParameters::Converter include Stagehand::Internal::Type::RequestParameters - # @!attribute env - # Environment to run the browser in + # @!attribute browserbase_api_key + # API key for Browserbase Cloud # - # @return [Symbol, Stagehand::Models::SessionStartParams::Env] - required :env, enum: -> { Stagehand::SessionStartParams::Env } + # @return [String] + required :browserbase_api_key, String, api_name: :BROWSERBASE_API_KEY - # @!attribute api_key - # API key for Browserbase (required when env=BROWSERBASE) + # @!attribute browserbase_project_id + # Project ID for Browserbase # - # @return [String, nil] - optional :api_key, String, api_name: :apiKey + # @return [String] + required :browserbase_project_id, String, api_name: :BROWSERBASE_PROJECT_ID # @!attribute dom_settle_timeout # Timeout in ms to wait for DOM to settle @@ -25,26 +25,12 @@ class SessionStartParams < Stagehand::Internal::Type::BaseModel # @return [Integer, nil] optional :dom_settle_timeout, Integer, api_name: :domSettleTimeout - # @!attribute local_browser_launch_options - # Options for local browser launch - # - # @return [Stagehand::Models::SessionStartParams::LocalBrowserLaunchOptions, nil] - optional :local_browser_launch_options, - -> { Stagehand::SessionStartParams::LocalBrowserLaunchOptions }, - api_name: :localBrowserLaunchOptions - # @!attribute model - # AI model to use for actions + # AI model to use for actions (must be prefixed with provider/) # # @return [String, nil] optional :model, String - # @!attribute project_id - # Project ID for Browserbase (required when env=BROWSERBASE) - # - # @return [String, nil] - optional :project_id, String, api_name: :projectId - # @!attribute self_heal # Enable self-healing for failed actions # @@ -63,18 +49,14 @@ class SessionStartParams < Stagehand::Internal::Type::BaseModel # @return [Integer, nil] optional :verbose, Integer - # @!method initialize(env:, api_key: nil, dom_settle_timeout: nil, local_browser_launch_options: nil, model: nil, project_id: nil, self_heal: nil, system_prompt: nil, verbose: nil, request_options: {}) - # @param env [Symbol, Stagehand::Models::SessionStartParams::Env] Environment to run the browser in + # @!method initialize(browserbase_api_key:, browserbase_project_id:, dom_settle_timeout: nil, model: nil, self_heal: nil, system_prompt: nil, verbose: nil, request_options: {}) + # @param browserbase_api_key [String] API key for Browserbase Cloud # - # @param api_key [String] API key for Browserbase (required when env=BROWSERBASE) + # @param browserbase_project_id [String] Project ID for Browserbase # # @param dom_settle_timeout [Integer] Timeout in ms to wait for DOM to settle # - # @param local_browser_launch_options [Stagehand::Models::SessionStartParams::LocalBrowserLaunchOptions] Options for local browser launch - # - # @param model [String] AI model to use for actions - # - # @param project_id [String] Project ID for Browserbase (required when env=BROWSERBASE) + # @param model [String] AI model to use for actions (must be prefixed with provider/) # # @param self_heal [Boolean] Enable self-healing for failed actions # @@ -83,29 +65,6 @@ class SessionStartParams < Stagehand::Internal::Type::BaseModel # @param verbose [Integer] Logging verbosity level # # @param request_options [Stagehand::RequestOptions, Hash{Symbol=>Object}] - - # Environment to run the browser in - module Env - extend Stagehand::Internal::Type::Enum - - LOCAL = :LOCAL - BROWSERBASE = :BROWSERBASE - - # @!method self.values - # @return [Array] - end - - class LocalBrowserLaunchOptions < Stagehand::Internal::Type::BaseModel - # @!attribute headless - # - # @return [Boolean, nil] - optional :headless, Stagehand::Internal::Type::Boolean - - # @!method initialize(headless: nil) - # Options for local browser launch - # - # @param headless [Boolean] - end end end end diff --git a/lib/stagehand/resources/sessions.rb b/lib/stagehand/resources/sessions.rb index 7107652..5324832 100644 --- a/lib/stagehand/resources/sessions.rb +++ b/lib/stagehand/resources/sessions.rb @@ -192,19 +192,15 @@ def observe(session_id, params = {}) # Initializes a new Stagehand session with a browser instance. Returns a session # ID that must be used for all subsequent requests. # - # @overload start(env:, api_key: nil, dom_settle_timeout: nil, local_browser_launch_options: nil, model: nil, project_id: nil, self_heal: nil, system_prompt: nil, verbose: nil, request_options: {}) + # @overload start(browserbase_api_key:, browserbase_project_id:, dom_settle_timeout: nil, model: nil, self_heal: nil, system_prompt: nil, verbose: nil, request_options: {}) # - # @param env [Symbol, Stagehand::Models::SessionStartParams::Env] Environment to run the browser in + # @param browserbase_api_key [String] API key for Browserbase Cloud # - # @param api_key [String] API key for Browserbase (required when env=BROWSERBASE) + # @param browserbase_project_id [String] Project ID for Browserbase # # @param dom_settle_timeout [Integer] Timeout in ms to wait for DOM to settle # - # @param local_browser_launch_options [Stagehand::Models::SessionStartParams::LocalBrowserLaunchOptions] Options for local browser launch - # - # @param model [String] AI model to use for actions - # - # @param project_id [String] Project ID for Browserbase (required when env=BROWSERBASE) + # @param model [String] AI model to use for actions (must be prefixed with provider/) # # @param self_heal [Boolean] Enable self-healing for failed actions # diff --git a/rbi/stagehand/models/session_start_params.rbi b/rbi/stagehand/models/session_start_params.rbi index 4104a6d..707e3f1 100644 --- a/rbi/stagehand/models/session_start_params.rbi +++ b/rbi/stagehand/models/session_start_params.rbi @@ -11,16 +11,13 @@ module Stagehand T.any(Stagehand::SessionStartParams, Stagehand::Internal::AnyHash) end - # Environment to run the browser in - sig { returns(Stagehand::SessionStartParams::Env::OrSymbol) } - attr_accessor :env + # API key for Browserbase Cloud + sig { returns(String) } + attr_accessor :browserbase_api_key - # API key for Browserbase (required when env=BROWSERBASE) - sig { returns(T.nilable(String)) } - attr_reader :api_key - - sig { params(api_key: String).void } - attr_writer :api_key + # Project ID for Browserbase + sig { returns(String) } + attr_accessor :browserbase_project_id # Timeout in ms to wait for DOM to settle sig { returns(T.nilable(Integer)) } @@ -29,36 +26,13 @@ module Stagehand sig { params(dom_settle_timeout: Integer).void } attr_writer :dom_settle_timeout - # Options for local browser launch - sig do - returns( - T.nilable(Stagehand::SessionStartParams::LocalBrowserLaunchOptions) - ) - end - attr_reader :local_browser_launch_options - - sig do - params( - local_browser_launch_options: - Stagehand::SessionStartParams::LocalBrowserLaunchOptions::OrHash - ).void - end - attr_writer :local_browser_launch_options - - # AI model to use for actions + # AI model to use for actions (must be prefixed with provider/) sig { returns(T.nilable(String)) } attr_reader :model sig { params(model: String).void } attr_writer :model - # Project ID for Browserbase (required when env=BROWSERBASE) - sig { returns(T.nilable(String)) } - attr_reader :project_id - - sig { params(project_id: String).void } - attr_writer :project_id - # Enable self-healing for failed actions sig { returns(T.nilable(T::Boolean)) } attr_reader :self_heal @@ -82,13 +56,10 @@ module Stagehand sig do params( - env: Stagehand::SessionStartParams::Env::OrSymbol, - api_key: String, + browserbase_api_key: String, + browserbase_project_id: String, dom_settle_timeout: Integer, - local_browser_launch_options: - Stagehand::SessionStartParams::LocalBrowserLaunchOptions::OrHash, model: String, - project_id: String, self_heal: T::Boolean, system_prompt: String, verbose: Integer, @@ -96,18 +67,14 @@ module Stagehand ).returns(T.attached_class) end def self.new( - # Environment to run the browser in - env:, - # API key for Browserbase (required when env=BROWSERBASE) - api_key: nil, + # API key for Browserbase Cloud + browserbase_api_key:, + # Project ID for Browserbase + browserbase_project_id:, # Timeout in ms to wait for DOM to settle dom_settle_timeout: nil, - # Options for local browser launch - local_browser_launch_options: nil, - # AI model to use for actions + # AI model to use for actions (must be prefixed with provider/) model: nil, - # Project ID for Browserbase (required when env=BROWSERBASE) - project_id: nil, # Enable self-healing for failed actions self_heal: nil, # Custom system prompt for AI actions @@ -121,13 +88,10 @@ module Stagehand sig do override.returns( { - env: Stagehand::SessionStartParams::Env::OrSymbol, - api_key: String, + browserbase_api_key: String, + browserbase_project_id: String, dom_settle_timeout: Integer, - local_browser_launch_options: - Stagehand::SessionStartParams::LocalBrowserLaunchOptions, model: String, - project_id: String, self_heal: T::Boolean, system_prompt: String, verbose: Integer, @@ -137,52 +101,6 @@ module Stagehand end def to_hash end - - # Environment to run the browser in - module Env - extend Stagehand::Internal::Type::Enum - - TaggedSymbol = - T.type_alias { T.all(Symbol, Stagehand::SessionStartParams::Env) } - OrSymbol = T.type_alias { T.any(Symbol, String) } - - LOCAL = T.let(:LOCAL, Stagehand::SessionStartParams::Env::TaggedSymbol) - BROWSERBASE = - T.let(:BROWSERBASE, Stagehand::SessionStartParams::Env::TaggedSymbol) - - sig do - override.returns( - T::Array[Stagehand::SessionStartParams::Env::TaggedSymbol] - ) - end - def self.values - end - end - - class LocalBrowserLaunchOptions < Stagehand::Internal::Type::BaseModel - OrHash = - T.type_alias do - T.any( - Stagehand::SessionStartParams::LocalBrowserLaunchOptions, - Stagehand::Internal::AnyHash - ) - end - - sig { returns(T.nilable(T::Boolean)) } - attr_reader :headless - - sig { params(headless: T::Boolean).void } - attr_writer :headless - - # Options for local browser launch - sig { params(headless: T::Boolean).returns(T.attached_class) } - def self.new(headless: nil) - end - - sig { override.returns({ headless: T::Boolean }) } - def to_hash - end - end end end end diff --git a/rbi/stagehand/resources/sessions.rbi b/rbi/stagehand/resources/sessions.rbi index 319ed9b..c0b2740 100644 --- a/rbi/stagehand/resources/sessions.rbi +++ b/rbi/stagehand/resources/sessions.rbi @@ -165,13 +165,10 @@ module Stagehand # ID that must be used for all subsequent requests. sig do params( - env: Stagehand::SessionStartParams::Env::OrSymbol, - api_key: String, + browserbase_api_key: String, + browserbase_project_id: String, dom_settle_timeout: Integer, - local_browser_launch_options: - Stagehand::SessionStartParams::LocalBrowserLaunchOptions::OrHash, model: String, - project_id: String, self_heal: T::Boolean, system_prompt: String, verbose: Integer, @@ -179,18 +176,14 @@ module Stagehand ).returns(Stagehand::Models::SessionStartResponse) end def start( - # Environment to run the browser in - env:, - # API key for Browserbase (required when env=BROWSERBASE) - api_key: nil, + # API key for Browserbase Cloud + browserbase_api_key:, + # Project ID for Browserbase + browserbase_project_id:, # Timeout in ms to wait for DOM to settle dom_settle_timeout: nil, - # Options for local browser launch - local_browser_launch_options: nil, - # AI model to use for actions + # AI model to use for actions (must be prefixed with provider/) model: nil, - # Project ID for Browserbase (required when env=BROWSERBASE) - project_id: nil, # Enable self-healing for failed actions self_heal: nil, # Custom system prompt for AI actions diff --git a/sig/stagehand/models/session_start_params.rbs b/sig/stagehand/models/session_start_params.rbs index bca70d2..f731957 100644 --- a/sig/stagehand/models/session_start_params.rbs +++ b/sig/stagehand/models/session_start_params.rbs @@ -2,12 +2,10 @@ module Stagehand module Models type session_start_params = { - env: Stagehand::Models::SessionStartParams::env, - api_key: String, + browserbase_api_key: String, + browserbase_project_id: String, dom_settle_timeout: Integer, - local_browser_launch_options: Stagehand::SessionStartParams::LocalBrowserLaunchOptions, model: String, - project_id: String, self_heal: bool, system_prompt: String, verbose: Integer @@ -18,30 +16,18 @@ module Stagehand extend Stagehand::Internal::Type::RequestParameters::Converter include Stagehand::Internal::Type::RequestParameters - attr_accessor env: Stagehand::Models::SessionStartParams::env + attr_accessor browserbase_api_key: String - attr_reader api_key: String? - - def api_key=: (String) -> String + attr_accessor browserbase_project_id: String attr_reader dom_settle_timeout: Integer? def dom_settle_timeout=: (Integer) -> Integer - attr_reader local_browser_launch_options: Stagehand::SessionStartParams::LocalBrowserLaunchOptions? - - def local_browser_launch_options=: ( - Stagehand::SessionStartParams::LocalBrowserLaunchOptions - ) -> Stagehand::SessionStartParams::LocalBrowserLaunchOptions - attr_reader model: String? def model=: (String) -> String - attr_reader project_id: String? - - def project_id=: (String) -> String - attr_reader self_heal: bool? def self_heal=: (bool) -> bool @@ -55,12 +41,10 @@ module Stagehand def verbose=: (Integer) -> Integer def initialize: ( - env: Stagehand::Models::SessionStartParams::env, - ?api_key: String, + browserbase_api_key: String, + browserbase_project_id: String, ?dom_settle_timeout: Integer, - ?local_browser_launch_options: Stagehand::SessionStartParams::LocalBrowserLaunchOptions, ?model: String, - ?project_id: String, ?self_heal: bool, ?system_prompt: String, ?verbose: Integer, @@ -68,40 +52,15 @@ module Stagehand ) -> void def to_hash: -> { - env: Stagehand::Models::SessionStartParams::env, - api_key: String, + browserbase_api_key: String, + browserbase_project_id: String, dom_settle_timeout: Integer, - local_browser_launch_options: Stagehand::SessionStartParams::LocalBrowserLaunchOptions, model: String, - project_id: String, self_heal: bool, system_prompt: String, verbose: Integer, request_options: Stagehand::RequestOptions } - - type env = :LOCAL | :BROWSERBASE - - module Env - extend Stagehand::Internal::Type::Enum - - LOCAL: :LOCAL - BROWSERBASE: :BROWSERBASE - - def self?.values: -> ::Array[Stagehand::Models::SessionStartParams::env] - end - - type local_browser_launch_options = { headless: bool } - - class LocalBrowserLaunchOptions < Stagehand::Internal::Type::BaseModel - attr_reader headless: bool? - - def headless=: (bool) -> bool - - def initialize: (?headless: bool) -> void - - def to_hash: -> { headless: bool } - end end end end diff --git a/sig/stagehand/resources/sessions.rbs b/sig/stagehand/resources/sessions.rbs index 17418a0..55554bd 100644 --- a/sig/stagehand/resources/sessions.rbs +++ b/sig/stagehand/resources/sessions.rbs @@ -53,12 +53,10 @@ module Stagehand ) -> Stagehand::Models::session_observe_response def start: ( - env: Stagehand::Models::SessionStartParams::env, - ?api_key: String, + browserbase_api_key: String, + browserbase_project_id: String, ?dom_settle_timeout: Integer, - ?local_browser_launch_options: Stagehand::SessionStartParams::LocalBrowserLaunchOptions, ?model: String, - ?project_id: String, ?self_heal: bool, ?system_prompt: String, ?verbose: Integer, diff --git a/test/stagehand/client_test.rb b/test/stagehand/client_test.rb index 5abdb48..6c1f02f 100644 --- a/test/stagehand/client_test.rb +++ b/test/stagehand/client_test.rb @@ -47,7 +47,10 @@ def test_client_default_request_default_retry_attempts stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") assert_raises(Stagehand::Errors::InternalServerError) do - stagehand.sessions.start(env: :LOCAL) + stagehand.sessions.start( + browserbase_api_key: "BROWSERBASE_API_KEY", + browserbase_project_id: "BROWSERBASE_PROJECT_ID" + ) end assert_requested(:any, /./, times: 3) @@ -59,7 +62,10 @@ def test_client_given_request_default_retry_attempts stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key", max_retries: 3) assert_raises(Stagehand::Errors::InternalServerError) do - stagehand.sessions.start(env: :LOCAL) + stagehand.sessions.start( + browserbase_api_key: "BROWSERBASE_API_KEY", + browserbase_project_id: "BROWSERBASE_PROJECT_ID" + ) end assert_requested(:any, /./, times: 4) @@ -71,7 +77,11 @@ def test_client_default_request_given_retry_attempts stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") assert_raises(Stagehand::Errors::InternalServerError) do - stagehand.sessions.start(env: :LOCAL, request_options: {max_retries: 3}) + stagehand.sessions.start( + browserbase_api_key: "BROWSERBASE_API_KEY", + browserbase_project_id: "BROWSERBASE_PROJECT_ID", + request_options: {max_retries: 3} + ) end assert_requested(:any, /./, times: 4) @@ -83,7 +93,11 @@ def test_client_given_request_given_retry_attempts stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key", max_retries: 3) assert_raises(Stagehand::Errors::InternalServerError) do - stagehand.sessions.start(env: :LOCAL, request_options: {max_retries: 4}) + stagehand.sessions.start( + browserbase_api_key: "BROWSERBASE_API_KEY", + browserbase_project_id: "BROWSERBASE_PROJECT_ID", + request_options: {max_retries: 4} + ) end assert_requested(:any, /./, times: 5) @@ -99,7 +113,10 @@ def test_client_retry_after_seconds stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key", max_retries: 1) assert_raises(Stagehand::Errors::InternalServerError) do - stagehand.sessions.start(env: :LOCAL) + stagehand.sessions.start( + browserbase_api_key: "BROWSERBASE_API_KEY", + browserbase_project_id: "BROWSERBASE_PROJECT_ID" + ) end assert_requested(:any, /./, times: 2) @@ -117,7 +134,10 @@ def test_client_retry_after_date assert_raises(Stagehand::Errors::InternalServerError) do Thread.current.thread_variable_set(:time_now, Time.now) - stagehand.sessions.start(env: :LOCAL) + stagehand.sessions.start( + browserbase_api_key: "BROWSERBASE_API_KEY", + browserbase_project_id: "BROWSERBASE_PROJECT_ID" + ) Thread.current.thread_variable_set(:time_now, nil) end @@ -135,7 +155,10 @@ def test_client_retry_after_ms stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key", max_retries: 1) assert_raises(Stagehand::Errors::InternalServerError) do - stagehand.sessions.start(env: :LOCAL) + stagehand.sessions.start( + browserbase_api_key: "BROWSERBASE_API_KEY", + browserbase_project_id: "BROWSERBASE_PROJECT_ID" + ) end assert_requested(:any, /./, times: 2) @@ -148,7 +171,10 @@ def test_retry_count_header stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") assert_raises(Stagehand::Errors::InternalServerError) do - stagehand.sessions.start(env: :LOCAL) + stagehand.sessions.start( + browserbase_api_key: "BROWSERBASE_API_KEY", + browserbase_project_id: "BROWSERBASE_PROJECT_ID" + ) end 3.times do @@ -163,7 +189,8 @@ def test_omit_retry_count_header assert_raises(Stagehand::Errors::InternalServerError) do stagehand.sessions.start( - env: :LOCAL, + browserbase_api_key: "BROWSERBASE_API_KEY", + browserbase_project_id: "BROWSERBASE_PROJECT_ID", request_options: {extra_headers: {"x-stainless-retry-count" => nil}} ) end @@ -180,7 +207,8 @@ def test_overwrite_retry_count_header assert_raises(Stagehand::Errors::InternalServerError) do stagehand.sessions.start( - env: :LOCAL, + browserbase_api_key: "BROWSERBASE_API_KEY", + browserbase_project_id: "BROWSERBASE_PROJECT_ID", request_options: {extra_headers: {"x-stainless-retry-count" => "42"}} ) end @@ -202,7 +230,11 @@ def test_client_redirect_307 stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") assert_raises(Stagehand::Errors::APIConnectionError) do - stagehand.sessions.start(env: :LOCAL, request_options: {extra_headers: {}}) + stagehand.sessions.start( + browserbase_api_key: "BROWSERBASE_API_KEY", + browserbase_project_id: "BROWSERBASE_PROJECT_ID", + request_options: {extra_headers: {}} + ) end recorded, = WebMock::RequestRegistry.instance.requested_signatures.hash.first @@ -231,7 +263,11 @@ def test_client_redirect_303 stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") assert_raises(Stagehand::Errors::APIConnectionError) do - stagehand.sessions.start(env: :LOCAL, request_options: {extra_headers: {}}) + stagehand.sessions.start( + browserbase_api_key: "BROWSERBASE_API_KEY", + browserbase_project_id: "BROWSERBASE_PROJECT_ID", + request_options: {extra_headers: {}} + ) end assert_requested(:get, "http://localhost/redirected", times: Stagehand::Client::MAX_REDIRECTS) do @@ -256,7 +292,8 @@ def test_client_redirect_auth_keep_same_origin assert_raises(Stagehand::Errors::APIConnectionError) do stagehand.sessions.start( - env: :LOCAL, + browserbase_api_key: "BROWSERBASE_API_KEY", + browserbase_project_id: "BROWSERBASE_PROJECT_ID", request_options: {extra_headers: {"authorization" => "Bearer xyz"}} ) end @@ -286,7 +323,8 @@ def test_client_redirect_auth_strip_cross_origin assert_raises(Stagehand::Errors::APIConnectionError) do stagehand.sessions.start( - env: :LOCAL, + browserbase_api_key: "BROWSERBASE_API_KEY", + browserbase_project_id: "BROWSERBASE_PROJECT_ID", request_options: {extra_headers: {"authorization" => "Bearer xyz"}} ) end @@ -302,7 +340,10 @@ def test_default_headers stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") - stagehand.sessions.start(env: :LOCAL) + stagehand.sessions.start( + browserbase_api_key: "BROWSERBASE_API_KEY", + browserbase_project_id: "BROWSERBASE_PROJECT_ID" + ) assert_requested(:any, /./) do |req| headers = req.headers.transform_keys(&:downcase).fetch_values("accept", "content-type") diff --git a/test/stagehand/resources/sessions_test.rb b/test/stagehand/resources/sessions_test.rb index 1864622..ded49cf 100644 --- a/test/stagehand/resources/sessions_test.rb +++ b/test/stagehand/resources/sessions_test.rb @@ -109,7 +109,11 @@ def test_observe def test_start_required_params skip("Prism tests are disabled") - response = @stagehand.sessions.start(env: :LOCAL) + response = + @stagehand.sessions.start( + browserbase_api_key: "BROWSERBASE_API_KEY", + browserbase_project_id: "BROWSERBASE_PROJECT_ID" + ) assert_pattern do response => Stagehand::Models::SessionStartResponse From 2a8b9e7d219360a5e783c650fc7c9544a9a6fbb5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 19:40:28 +0000 Subject: [PATCH 08/12] feat(api): manual updates --- .stats.yml | 4 ++-- lib/stagehand/internal/type/union.rb | 2 +- lib/stagehand/models/session_extract_response.rb | 4 ++-- rbi/stagehand/models/session_extract_response.rbi | 2 +- sig/stagehand/models/session_extract_response.rbs | 2 +- test/stagehand/resources/sessions_test.rb | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.stats.yml b/.stats.yml index 4664845..54cc978 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-6a22863a7da4fa45f904657a4cb8fc1a28e236925f03dc94fca25fd8271ca6db.yml -openapi_spec_hash: d5c6108942ad79f39ea4ff1bee9b7996 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-3607b588cab78536eb7de9f6acffe8ddda1d34aebe5910c2147421aa6c16bf22.yml +openapi_spec_hash: fb507e8d38b4978a5717fbb144197868 config_hash: 2f1ec44e7e07906e07bdc6e075763da9 diff --git a/lib/stagehand/internal/type/union.rb b/lib/stagehand/internal/type/union.rb index 199ba7a..afc4c15 100644 --- a/lib/stagehand/internal/type/union.rb +++ b/lib/stagehand/internal/type/union.rb @@ -10,7 +10,7 @@ module Type # case session_extract_response # when Stagehand::Models::SessionExtractResponse::Extraction # puts(session_extract_response.extraction) - # when Stagehand::Models::SessionExtractResponse::UnionMember1Map + # when Stagehand::Models::SessionExtractResponse::CustomMap # # ... # else # puts(session_extract_response) diff --git a/lib/stagehand/models/session_extract_response.rb b/lib/stagehand/models/session_extract_response.rb index 8549d46..9705fca 100644 --- a/lib/stagehand/models/session_extract_response.rb +++ b/lib/stagehand/models/session_extract_response.rb @@ -12,7 +12,7 @@ module SessionExtractResponse variant -> { Stagehand::Models::SessionExtractResponse::Extraction } # Structured data matching provided schema - variant -> { Stagehand::Models::SessionExtractResponse::UnionMember1Map } + variant -> { Stagehand::Models::SessionExtractResponse::CustomMap } class Extraction < Stagehand::Internal::Type::BaseModel # @!attribute extraction @@ -30,7 +30,7 @@ class Extraction < Stagehand::Internal::Type::BaseModel # @return [Array(Stagehand::Models::SessionExtractResponse::Extraction, Hash{Symbol=>Object})] # @type [Stagehand::Internal::Type::Converter] - UnionMember1Map = Stagehand::Internal::Type::HashOf[Stagehand::Internal::Type::Unknown] + CustomMap = Stagehand::Internal::Type::HashOf[Stagehand::Internal::Type::Unknown] end end end diff --git a/rbi/stagehand/models/session_extract_response.rbi b/rbi/stagehand/models/session_extract_response.rbi index 4b3cf3e..3a31cc4 100644 --- a/rbi/stagehand/models/session_extract_response.rbi +++ b/rbi/stagehand/models/session_extract_response.rbi @@ -47,7 +47,7 @@ module Stagehand def self.variants end - UnionMember1Map = + CustomMap = T.let( Stagehand::Internal::Type::HashOf[Stagehand::Internal::Type::Unknown], Stagehand::Internal::Type::Converter diff --git a/sig/stagehand/models/session_extract_response.rbs b/sig/stagehand/models/session_extract_response.rbs index d8e9661..8c570de 100644 --- a/sig/stagehand/models/session_extract_response.rbs +++ b/sig/stagehand/models/session_extract_response.rbs @@ -21,7 +21,7 @@ module Stagehand def self?.variants: -> ::Array[Stagehand::Models::session_extract_response] - UnionMember1Map: Stagehand::Internal::Type::Converter + CustomMap: Stagehand::Internal::Type::Converter end end end diff --git a/test/stagehand/resources/sessions_test.rb b/test/stagehand/resources/sessions_test.rb index ded49cf..aae77a9 100644 --- a/test/stagehand/resources/sessions_test.rb +++ b/test/stagehand/resources/sessions_test.rb @@ -72,7 +72,7 @@ def test_extract assert_pattern do case response in Stagehand::Models::SessionExtractResponse::Extraction - in Stagehand::Models::SessionExtractResponse::UnionMember1Map + in Stagehand::Models::SessionExtractResponse::CustomMap end end end From 87ce5f320056fb34770be2f0c87985960e995e92 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 20:08:39 +0000 Subject: [PATCH 09/12] feat(api): manual updates --- .stats.yml | 2 +- README.md | 5 +- lib/stagehand/client.rb | 70 ++++++++++-------- rbi/stagehand/client.rbi | 52 ++++++++------ sig/stagehand/client.rbs | 21 +++--- test/stagehand/client_test.rb | 132 ++++++++++++++++++++++++++++------ test/stagehand/test_helper.rb | 7 +- 7 files changed, 205 insertions(+), 84 deletions(-) diff --git a/.stats.yml b/.stats.yml index 54cc978..1e16065 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-3607b588cab78536eb7de9f6acffe8ddda1d34aebe5910c2147421aa6c16bf22.yml openapi_spec_hash: fb507e8d38b4978a5717fbb144197868 -config_hash: 2f1ec44e7e07906e07bdc6e075763da9 +config_hash: fc6606301b5142487a69d296f154b265 diff --git a/README.md b/README.md index 360dcbe..48df5eb 100644 --- a/README.md +++ b/README.md @@ -29,8 +29,9 @@ require "bundler/setup" require "stagehand" stagehand = Stagehand::Client.new( - api_key: ENV["STAGEHAND_API_KEY"], # This is the default and can be omitted - environment: "dev" # or "production" | "local"; defaults to "production" + browserbase_api_key: ENV["BROWSERBASE_API_KEY"], # This is the default and can be omitted + browserbase_project_id: ENV["BROWSERBASE_PROJECT_ID"], # This is the default and can be omitted + model_api_key: ENV["MODEL_API_KEY"] # This is the default and can be omitted ) response = stagehand.sessions.act("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", input: "click the first link on the page") diff --git a/lib/stagehand/client.rb b/lib/stagehand/client.rb index 234444b..c30d249 100644 --- a/lib/stagehand/client.rb +++ b/lib/stagehand/client.rb @@ -15,18 +15,14 @@ class Client < Stagehand::Internal::Transport::BaseClient # Default max retry delay in seconds. DEFAULT_MAX_RETRY_DELAY = 8.0 - # rubocop:disable Style/MutableConstant - # @type [Hash{Symbol=>String}] - ENVIRONMENTS = - { - production: "https://api.stagehand.browserbase.com/v1", - dev: "https://api.stagehand.dev.browserbase.com/v1", - local: "http://localhost:5000/v1" - } - # rubocop:enable Style/MutableConstant + # @return [String] + attr_reader :browserbase_api_key # @return [String] - attr_reader :api_key + attr_reader :browserbase_project_id + + # @return [String, nil] + attr_reader :model_api_key # @return [Stagehand::Resources::Sessions] attr_reader :sessions @@ -35,22 +31,37 @@ class Client < Stagehand::Internal::Transport::BaseClient # # @return [Hash{String=>String}] private def auth_headers - return {} if @api_key.nil? + {**bb_api_key_auth, **bb_project_id_auth, **llm_model_api_key_auth} + end - {"authorization" => "Bearer #{@api_key}"} + # @api private + # + # @return [Hash{String=>String}] + private def bb_api_key_auth + {"x-bb-api-key" => @browserbase_api_key} end - # Creates and returns a new client for interacting with the API. + # @api private # - # @param api_key [String, nil] Defaults to `ENV["STAGEHAND_API_KEY"]` + # @return [Hash{String=>String}] + private def bb_project_id_auth + {"x-bb-project-id" => @browserbase_project_id} + end + + # @api private # - # @param environment [:production, :dev, :local, nil] Specifies the environment to use for the API. + # @return [Hash{String=>String}] + private def llm_model_api_key_auth + {"x-model-api-key" => @model_api_key} + end + + # Creates and returns a new client for interacting with the API. + # + # @param browserbase_api_key [String, nil] Defaults to `ENV["BROWSERBASE_API_KEY"]` # - # Each environment maps to a different base URL: + # @param browserbase_project_id [String, nil] Defaults to `ENV["BROWSERBASE_PROJECT_ID"]` # - # - `production` corresponds to `https://api.stagehand.browserbase.com/v1` - # - `dev` corresponds to `https://api.stagehand.dev.browserbase.com/v1` - # - `local` corresponds to `http://localhost:5000/v1` + # @param model_api_key [String, nil] Defaults to `ENV["MODEL_API_KEY"]` # # @param base_url [String, nil] Override the default base URL for the API, e.g., # `"https://api.example.com/v2/"`. Defaults to `ENV["STAGEHAND_BASE_URL"]` @@ -63,24 +74,27 @@ class Client < Stagehand::Internal::Transport::BaseClient # # @param max_retry_delay [Float] def initialize( - api_key: ENV["STAGEHAND_API_KEY"], - environment: nil, + browserbase_api_key: ENV["BROWSERBASE_API_KEY"], + browserbase_project_id: ENV["BROWSERBASE_PROJECT_ID"], + model_api_key: ENV["MODEL_API_KEY"], base_url: ENV["STAGEHAND_BASE_URL"], max_retries: self.class::DEFAULT_MAX_RETRIES, timeout: self.class::DEFAULT_TIMEOUT_IN_SECONDS, initial_retry_delay: self.class::DEFAULT_INITIAL_RETRY_DELAY, max_retry_delay: self.class::DEFAULT_MAX_RETRY_DELAY ) - base_url ||= Stagehand::Client::ENVIRONMENTS.fetch(environment&.to_sym || :production) do - message = "environment must be one of #{Stagehand::Client::ENVIRONMENTS.keys}, got #{environment}" - raise ArgumentError.new(message) - end + base_url ||= "https://api.stagehand.browserbase.com/v1" - if api_key.nil? - raise ArgumentError.new("api_key is required, and can be set via environ: \"STAGEHAND_API_KEY\"") + if browserbase_api_key.nil? + raise ArgumentError.new("browserbase_api_key is required, and can be set via environ: \"BROWSERBASE_API_KEY\"") + end + if browserbase_project_id.nil? + raise ArgumentError.new("browserbase_project_id is required, and can be set via environ: \"BROWSERBASE_PROJECT_ID\"") end - @api_key = api_key.to_s + @browserbase_api_key = browserbase_api_key.to_s + @browserbase_project_id = browserbase_project_id.to_s + @model_api_key = model_api_key&.to_s super( base_url: base_url, diff --git a/rbi/stagehand/client.rbi b/rbi/stagehand/client.rbi index d5fc53e..e333a80 100644 --- a/rbi/stagehand/client.rbi +++ b/rbi/stagehand/client.rbi @@ -10,18 +10,14 @@ module Stagehand DEFAULT_MAX_RETRY_DELAY = T.let(8.0, Float) - ENVIRONMENTS = - T.let( - { - production: "https://api.stagehand.browserbase.com/v1", - dev: "https://api.stagehand.dev.browserbase.com/v1", - local: "http://localhost:5000/v1" - }, - T::Hash[Symbol, String] - ) + sig { returns(String) } + attr_reader :browserbase_api_key sig { returns(String) } - attr_reader :api_key + attr_reader :browserbase_project_id + + sig { returns(T.nilable(String)) } + attr_reader :model_api_key sig { returns(Stagehand::Resources::Sessions) } attr_reader :sessions @@ -31,11 +27,27 @@ module Stagehand private def auth_headers end + # @api private + sig { returns(T::Hash[String, String]) } + private def bb_api_key_auth + end + + # @api private + sig { returns(T::Hash[String, String]) } + private def bb_project_id_auth + end + + # @api private + sig { returns(T::Hash[String, String]) } + private def llm_model_api_key_auth + end + # Creates and returns a new client for interacting with the API. sig do params( - api_key: T.nilable(String), - environment: T.nilable(T.any(Symbol, String)), + browserbase_api_key: T.nilable(String), + browserbase_project_id: T.nilable(String), + model_api_key: T.nilable(String), base_url: T.nilable(String), max_retries: Integer, timeout: Float, @@ -44,16 +56,12 @@ module Stagehand ).returns(T.attached_class) end def self.new( - # Defaults to `ENV["STAGEHAND_API_KEY"]` - api_key: ENV["STAGEHAND_API_KEY"], - # Specifies the environment to use for the API. - # - # Each environment maps to a different base URL: - # - # - `production` corresponds to `https://api.stagehand.browserbase.com/v1` - # - `dev` corresponds to `https://api.stagehand.dev.browserbase.com/v1` - # - `local` corresponds to `http://localhost:5000/v1` - environment: nil, + # Defaults to `ENV["BROWSERBASE_API_KEY"]` + browserbase_api_key: ENV["BROWSERBASE_API_KEY"], + # Defaults to `ENV["BROWSERBASE_PROJECT_ID"]` + browserbase_project_id: ENV["BROWSERBASE_PROJECT_ID"], + # Defaults to `ENV["MODEL_API_KEY"]` + model_api_key: ENV["MODEL_API_KEY"], # Override the default base URL for the API, e.g., # `"https://api.example.com/v2/"`. Defaults to `ENV["STAGEHAND_BASE_URL"]` base_url: ENV["STAGEHAND_BASE_URL"], diff --git a/sig/stagehand/client.rbs b/sig/stagehand/client.rbs index fe115d9..3033cdf 100644 --- a/sig/stagehand/client.rbs +++ b/sig/stagehand/client.rbs @@ -8,21 +8,26 @@ module Stagehand DEFAULT_MAX_RETRY_DELAY: Float - ENVIRONMENTS: { - production: "https://api.stagehand.browserbase.com/v1", - dev: "https://api.stagehand.dev.browserbase.com/v1", - local: "http://localhost:5000/v1" - } + attr_reader browserbase_api_key: String - attr_reader api_key: String + attr_reader browserbase_project_id: String + + attr_reader model_api_key: String? attr_reader sessions: Stagehand::Resources::Sessions private def auth_headers: -> ::Hash[String, String] + private def bb_api_key_auth: -> ::Hash[String, String] + + private def bb_project_id_auth: -> ::Hash[String, String] + + private def llm_model_api_key_auth: -> ::Hash[String, String] + def initialize: ( - ?api_key: String?, - ?environment: :production | :dev | :local | nil, + ?browserbase_api_key: String?, + ?browserbase_project_id: String?, + ?model_api_key: String?, ?base_url: String?, ?max_retries: Integer, ?timeout: Float, diff --git a/test/stagehand/client_test.rb b/test/stagehand/client_test.rb index 6c1f02f..286d2f2 100644 --- a/test/stagehand/client_test.rb +++ b/test/stagehand/client_test.rb @@ -27,13 +27,6 @@ def after_all super end - def test_raises_on_unknown_environment - e = assert_raises(ArgumentError) do - Stagehand::Client.new(environment: "wrong") - end - assert_match(/environment must be one of/, e.message) - end - def test_raises_on_missing_non_nullable_opts e = assert_raises(ArgumentError) do Stagehand::Client.new @@ -44,7 +37,13 @@ def test_raises_on_missing_non_nullable_opts def test_client_default_request_default_retry_attempts stub_request(:post, "http://localhost/sessions/start").to_return_json(status: 500, body: {}) - stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") + stagehand = + Stagehand::Client.new( + base_url: "http://localhost", + browserbase_api_key: "My Browserbase API Key", + browserbase_project_id: "My Browserbase Project ID", + model_api_key: "My Model API Key" + ) assert_raises(Stagehand::Errors::InternalServerError) do stagehand.sessions.start( @@ -59,7 +58,14 @@ def test_client_default_request_default_retry_attempts def test_client_given_request_default_retry_attempts stub_request(:post, "http://localhost/sessions/start").to_return_json(status: 500, body: {}) - stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key", max_retries: 3) + stagehand = + Stagehand::Client.new( + base_url: "http://localhost", + browserbase_api_key: "My Browserbase API Key", + browserbase_project_id: "My Browserbase Project ID", + model_api_key: "My Model API Key", + max_retries: 3 + ) assert_raises(Stagehand::Errors::InternalServerError) do stagehand.sessions.start( @@ -74,7 +80,13 @@ def test_client_given_request_default_retry_attempts def test_client_default_request_given_retry_attempts stub_request(:post, "http://localhost/sessions/start").to_return_json(status: 500, body: {}) - stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") + stagehand = + Stagehand::Client.new( + base_url: "http://localhost", + browserbase_api_key: "My Browserbase API Key", + browserbase_project_id: "My Browserbase Project ID", + model_api_key: "My Model API Key" + ) assert_raises(Stagehand::Errors::InternalServerError) do stagehand.sessions.start( @@ -90,7 +102,14 @@ def test_client_default_request_given_retry_attempts def test_client_given_request_given_retry_attempts stub_request(:post, "http://localhost/sessions/start").to_return_json(status: 500, body: {}) - stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key", max_retries: 3) + stagehand = + Stagehand::Client.new( + base_url: "http://localhost", + browserbase_api_key: "My Browserbase API Key", + browserbase_project_id: "My Browserbase Project ID", + model_api_key: "My Model API Key", + max_retries: 3 + ) assert_raises(Stagehand::Errors::InternalServerError) do stagehand.sessions.start( @@ -110,7 +129,14 @@ def test_client_retry_after_seconds body: {} ) - stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key", max_retries: 1) + stagehand = + Stagehand::Client.new( + base_url: "http://localhost", + browserbase_api_key: "My Browserbase API Key", + browserbase_project_id: "My Browserbase Project ID", + model_api_key: "My Model API Key", + max_retries: 1 + ) assert_raises(Stagehand::Errors::InternalServerError) do stagehand.sessions.start( @@ -130,7 +156,14 @@ def test_client_retry_after_date body: {} ) - stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key", max_retries: 1) + stagehand = + Stagehand::Client.new( + base_url: "http://localhost", + browserbase_api_key: "My Browserbase API Key", + browserbase_project_id: "My Browserbase Project ID", + model_api_key: "My Model API Key", + max_retries: 1 + ) assert_raises(Stagehand::Errors::InternalServerError) do Thread.current.thread_variable_set(:time_now, Time.now) @@ -152,7 +185,14 @@ def test_client_retry_after_ms body: {} ) - stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key", max_retries: 1) + stagehand = + Stagehand::Client.new( + base_url: "http://localhost", + browserbase_api_key: "My Browserbase API Key", + browserbase_project_id: "My Browserbase Project ID", + model_api_key: "My Model API Key", + max_retries: 1 + ) assert_raises(Stagehand::Errors::InternalServerError) do stagehand.sessions.start( @@ -168,7 +208,13 @@ def test_client_retry_after_ms def test_retry_count_header stub_request(:post, "http://localhost/sessions/start").to_return_json(status: 500, body: {}) - stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") + stagehand = + Stagehand::Client.new( + base_url: "http://localhost", + browserbase_api_key: "My Browserbase API Key", + browserbase_project_id: "My Browserbase Project ID", + model_api_key: "My Model API Key" + ) assert_raises(Stagehand::Errors::InternalServerError) do stagehand.sessions.start( @@ -185,7 +231,13 @@ def test_retry_count_header def test_omit_retry_count_header stub_request(:post, "http://localhost/sessions/start").to_return_json(status: 500, body: {}) - stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") + stagehand = + Stagehand::Client.new( + base_url: "http://localhost", + browserbase_api_key: "My Browserbase API Key", + browserbase_project_id: "My Browserbase Project ID", + model_api_key: "My Model API Key" + ) assert_raises(Stagehand::Errors::InternalServerError) do stagehand.sessions.start( @@ -203,7 +255,13 @@ def test_omit_retry_count_header def test_overwrite_retry_count_header stub_request(:post, "http://localhost/sessions/start").to_return_json(status: 500, body: {}) - stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") + stagehand = + Stagehand::Client.new( + base_url: "http://localhost", + browserbase_api_key: "My Browserbase API Key", + browserbase_project_id: "My Browserbase Project ID", + model_api_key: "My Model API Key" + ) assert_raises(Stagehand::Errors::InternalServerError) do stagehand.sessions.start( @@ -227,7 +285,13 @@ def test_client_redirect_307 headers: {"location" => "/redirected"} ) - stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") + stagehand = + Stagehand::Client.new( + base_url: "http://localhost", + browserbase_api_key: "My Browserbase API Key", + browserbase_project_id: "My Browserbase Project ID", + model_api_key: "My Model API Key" + ) assert_raises(Stagehand::Errors::APIConnectionError) do stagehand.sessions.start( @@ -260,7 +324,13 @@ def test_client_redirect_303 headers: {"location" => "/redirected"} ) - stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") + stagehand = + Stagehand::Client.new( + base_url: "http://localhost", + browserbase_api_key: "My Browserbase API Key", + browserbase_project_id: "My Browserbase Project ID", + model_api_key: "My Model API Key" + ) assert_raises(Stagehand::Errors::APIConnectionError) do stagehand.sessions.start( @@ -288,7 +358,13 @@ def test_client_redirect_auth_keep_same_origin headers: {"location" => "/redirected"} ) - stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") + stagehand = + Stagehand::Client.new( + base_url: "http://localhost", + browserbase_api_key: "My Browserbase API Key", + browserbase_project_id: "My Browserbase Project ID", + model_api_key: "My Model API Key" + ) assert_raises(Stagehand::Errors::APIConnectionError) do stagehand.sessions.start( @@ -319,7 +395,13 @@ def test_client_redirect_auth_strip_cross_origin headers: {"location" => "https://example.com/redirected"} ) - stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") + stagehand = + Stagehand::Client.new( + base_url: "http://localhost", + browserbase_api_key: "My Browserbase API Key", + browserbase_project_id: "My Browserbase Project ID", + model_api_key: "My Model API Key" + ) assert_raises(Stagehand::Errors::APIConnectionError) do stagehand.sessions.start( @@ -338,7 +420,13 @@ def test_client_redirect_auth_strip_cross_origin def test_default_headers stub_request(:post, "http://localhost/sessions/start").to_return_json(status: 200, body: {}) - stagehand = Stagehand::Client.new(base_url: "http://localhost", api_key: "My API Key") + stagehand = + Stagehand::Client.new( + base_url: "http://localhost", + browserbase_api_key: "My Browserbase API Key", + browserbase_project_id: "My Browserbase Project ID", + model_api_key: "My Model API Key" + ) stagehand.sessions.start( browserbase_api_key: "BROWSERBASE_API_KEY", diff --git a/test/stagehand/test_helper.rb b/test/stagehand/test_helper.rb index 496dbbe..55adb3b 100644 --- a/test/stagehand/test_helper.rb +++ b/test/stagehand/test_helper.rb @@ -48,7 +48,12 @@ class Stagehand::Test::SingletonClient < Stagehand::Client TEST_API_BASE_URL = ENV.fetch("TEST_API_BASE_URL", "http://localhost:4010") def initialize - super(base_url: Stagehand::Test::SingletonClient::TEST_API_BASE_URL, api_key: "My API Key") + super( + base_url: Stagehand::Test::SingletonClient::TEST_API_BASE_URL, + browserbase_api_key: "My Browserbase API Key", + browserbase_project_id: "My Browserbase Project ID", + model_api_key: "My Model API Key" + ) end end From 5deaf8ff2011a2808dcfe66ef14470029bb3590e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 20:12:25 +0000 Subject: [PATCH 10/12] feat(api): manual updates --- .stats.yml | 2 +- lib/stagehand/client.rb | 7 +++++-- rbi/stagehand/client.rbi | 2 +- sig/stagehand/client.rbs | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.stats.yml b/.stats.yml index 1e16065..44d6d13 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-3607b588cab78536eb7de9f6acffe8ddda1d34aebe5910c2147421aa6c16bf22.yml openapi_spec_hash: fb507e8d38b4978a5717fbb144197868 -config_hash: fc6606301b5142487a69d296f154b265 +config_hash: 9d54b9fd851ec7ac25b85f579be64425 diff --git a/lib/stagehand/client.rb b/lib/stagehand/client.rb index c30d249..0bf91f3 100644 --- a/lib/stagehand/client.rb +++ b/lib/stagehand/client.rb @@ -21,7 +21,7 @@ class Client < Stagehand::Internal::Transport::BaseClient # @return [String] attr_reader :browserbase_project_id - # @return [String, nil] + # @return [String] attr_reader :model_api_key # @return [Stagehand::Resources::Sessions] @@ -91,10 +91,13 @@ def initialize( if browserbase_project_id.nil? raise ArgumentError.new("browserbase_project_id is required, and can be set via environ: \"BROWSERBASE_PROJECT_ID\"") end + if model_api_key.nil? + raise ArgumentError.new("model_api_key is required, and can be set via environ: \"MODEL_API_KEY\"") + end @browserbase_api_key = browserbase_api_key.to_s @browserbase_project_id = browserbase_project_id.to_s - @model_api_key = model_api_key&.to_s + @model_api_key = model_api_key.to_s super( base_url: base_url, diff --git a/rbi/stagehand/client.rbi b/rbi/stagehand/client.rbi index e333a80..f7f62fe 100644 --- a/rbi/stagehand/client.rbi +++ b/rbi/stagehand/client.rbi @@ -16,7 +16,7 @@ module Stagehand sig { returns(String) } attr_reader :browserbase_project_id - sig { returns(T.nilable(String)) } + sig { returns(String) } attr_reader :model_api_key sig { returns(Stagehand::Resources::Sessions) } diff --git a/sig/stagehand/client.rbs b/sig/stagehand/client.rbs index 3033cdf..0738efb 100644 --- a/sig/stagehand/client.rbs +++ b/sig/stagehand/client.rbs @@ -12,7 +12,7 @@ module Stagehand attr_reader browserbase_project_id: String - attr_reader model_api_key: String? + attr_reader model_api_key: String attr_reader sessions: Stagehand::Resources::Sessions From 2c69d3d2d90f550d8283c9542bc9b9ab855e6a06 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 20:24:19 +0000 Subject: [PATCH 11/12] feat(api): manual updates --- .stats.yml | 6 +++--- lib/stagehand/client.rb | 12 +++++++++--- rbi/stagehand/client.rbi | 10 ++++++++-- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/.stats.yml b/.stats.yml index 44d6d13..91b86f3 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-3607b588cab78536eb7de9f6acffe8ddda1d34aebe5910c2147421aa6c16bf22.yml -openapi_spec_hash: fb507e8d38b4978a5717fbb144197868 -config_hash: 9d54b9fd851ec7ac25b85f579be64425 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-2c88c6d890406ff8a5f1bca692264fb9af4bc4fe64df0986e06d3386fc6d6fcb.yml +openapi_spec_hash: dc6ea17f8152708dc0a390c7f86b1a5d +config_hash: b01f15c540ab2c92808c2bba96368631 diff --git a/lib/stagehand/client.rb b/lib/stagehand/client.rb index 0bf91f3..8d1ff22 100644 --- a/lib/stagehand/client.rb +++ b/lib/stagehand/client.rb @@ -15,12 +15,15 @@ class Client < Stagehand::Internal::Transport::BaseClient # Default max retry delay in seconds. DEFAULT_MAX_RETRY_DELAY = 8.0 + # Your [Browserbase API Key](https://www.browserbase.com/settings) # @return [String] attr_reader :browserbase_api_key + # Your [Browserbase Project ID](https://www.browserbase.com/settings) # @return [String] attr_reader :browserbase_project_id + # Your LLM provider API key (e.g. OPENAI_API_KEY, ANTHROPIC_API_KEY, etc.) # @return [String] attr_reader :model_api_key @@ -57,11 +60,14 @@ class Client < Stagehand::Internal::Transport::BaseClient # Creates and returns a new client for interacting with the API. # - # @param browserbase_api_key [String, nil] Defaults to `ENV["BROWSERBASE_API_KEY"]` + # @param browserbase_api_key [String, nil] Your [Browserbase API Key](https://www.browserbase.com/settings) Defaults to + # `ENV["BROWSERBASE_API_KEY"]` # - # @param browserbase_project_id [String, nil] Defaults to `ENV["BROWSERBASE_PROJECT_ID"]` + # @param browserbase_project_id [String, nil] Your [Browserbase Project ID](https://www.browserbase.com/settings) Defaults to + # `ENV["BROWSERBASE_PROJECT_ID"]` # - # @param model_api_key [String, nil] Defaults to `ENV["MODEL_API_KEY"]` + # @param model_api_key [String, nil] Your LLM provider API key (e.g. OPENAI_API_KEY, ANTHROPIC_API_KEY, etc.) + # Defaults to `ENV["MODEL_API_KEY"]` # # @param base_url [String, nil] Override the default base URL for the API, e.g., # `"https://api.example.com/v2/"`. Defaults to `ENV["STAGEHAND_BASE_URL"]` diff --git a/rbi/stagehand/client.rbi b/rbi/stagehand/client.rbi index f7f62fe..6354fbd 100644 --- a/rbi/stagehand/client.rbi +++ b/rbi/stagehand/client.rbi @@ -10,12 +10,15 @@ module Stagehand DEFAULT_MAX_RETRY_DELAY = T.let(8.0, Float) + # Your [Browserbase API Key](https://www.browserbase.com/settings) sig { returns(String) } attr_reader :browserbase_api_key + # Your [Browserbase Project ID](https://www.browserbase.com/settings) sig { returns(String) } attr_reader :browserbase_project_id + # Your LLM provider API key (e.g. OPENAI_API_KEY, ANTHROPIC_API_KEY, etc.) sig { returns(String) } attr_reader :model_api_key @@ -56,10 +59,13 @@ module Stagehand ).returns(T.attached_class) end def self.new( - # Defaults to `ENV["BROWSERBASE_API_KEY"]` + # Your [Browserbase API Key](https://www.browserbase.com/settings) Defaults to + # `ENV["BROWSERBASE_API_KEY"]` browserbase_api_key: ENV["BROWSERBASE_API_KEY"], - # Defaults to `ENV["BROWSERBASE_PROJECT_ID"]` + # Your [Browserbase Project ID](https://www.browserbase.com/settings) Defaults to + # `ENV["BROWSERBASE_PROJECT_ID"]` browserbase_project_id: ENV["BROWSERBASE_PROJECT_ID"], + # Your LLM provider API key (e.g. OPENAI_API_KEY, ANTHROPIC_API_KEY, etc.) # Defaults to `ENV["MODEL_API_KEY"]` model_api_key: ENV["MODEL_API_KEY"], # Override the default base URL for the API, e.g., From d0a40c284de68a38cd2c8d7449bca0768436bda7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 20:24:33 +0000 Subject: [PATCH 12/12] release: 0.1.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 20 ++++++++++++++++++++ Gemfile.lock | 2 +- README.md | 2 +- lib/stagehand/version.rb | 2 +- 5 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 CHANGELOG.md diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 1332969..3d2ac0b 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.0.1" + ".": "0.1.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..8b15b72 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,20 @@ +# Changelog + +## 0.1.0 (2025-12-16) + +Full Changelog: [v0.0.1...v0.1.0](https://github.com/browserbase/stagehand-ruby/compare/v0.0.1...v0.1.0) + +### Features + +* **api:** manual updates ([5deaf8f](https://github.com/browserbase/stagehand-ruby/commit/5deaf8ff2011a2808dcfe66ef14470029bb3590e)) +* **api:** manual updates ([87ce5f3](https://github.com/browserbase/stagehand-ruby/commit/87ce5f320056fb34770be2f0c87985960e995e92)) +* **api:** manual updates ([2a8b9e7](https://github.com/browserbase/stagehand-ruby/commit/2a8b9e7d219360a5e783c650fc7c9544a9a6fbb5)) +* **api:** manual updates ([0bcedba](https://github.com/browserbase/stagehand-ruby/commit/0bcedbaf26918822abdc958e6020f68b263ffee0)) +* **api:** manual updates ([8355d5e](https://github.com/browserbase/stagehand-ruby/commit/8355d5e6b83f6c31f6494f771fba51b6e31023e7)) +* **api:** manual updates ([655f517](https://github.com/browserbase/stagehand-ruby/commit/655f51718008b4c512eed1ce65660dae80039e49)) +* **api:** tweak branding and fix some config fields ([c48f36e](https://github.com/browserbase/stagehand-ruby/commit/c48f36e307aafd9a2d6ac59d9857be789f29eaa1)) + + +### Chores + +* configure new SDK language ([3be44a3](https://github.com/browserbase/stagehand-ruby/commit/3be44a344d5bc49e7c2e16129c2b24db175f4eb6)) diff --git a/Gemfile.lock b/Gemfile.lock index 217a15c..990a560 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -11,7 +11,7 @@ GIT PATH remote: . specs: - stagehand (0.0.1) + stagehand (0.1.0) connection_pool GEM diff --git a/README.md b/README.md index 48df5eb..ea21572 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ To use this gem, install via Bundler by adding the following to your application ```ruby -gem "stagehand", "~> 0.0.1" +gem "stagehand", "~> 0.1.0" ``` diff --git a/lib/stagehand/version.rb b/lib/stagehand/version.rb index f7a5ec5..78a723a 100644 --- a/lib/stagehand/version.rb +++ b/lib/stagehand/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module Stagehand - VERSION = "0.0.1" + VERSION = "0.1.0" end