From 5106687a8c7a491cf3594370ebd91fba63da7634 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 7 May 2026 17:46:25 +0000 Subject: [PATCH 1/8] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 391cde3..57aa7a5 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 8 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase/stagehand-6f6bfb81d092f30a5e2005328c97d61b9ea36132bb19e9e79e55294b9534ce20.yml -openapi_spec_hash: f3fc1e3688a38dc2c28f7178f7d534e5 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase/stagehand-e629569417ad17cad5c73180109b4c3ae778f38063fc72146fa82f82de145911.yml +openapi_spec_hash: 42e4eedbc0fcc772bb271191a067bce1 config_hash: 1fb12ae9b478488bc1e56bfbdc210b01 From 304ebd8ea3e7c9b6621d5382fc1f4c51ce64fb8d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 7 May 2026 18:23:20 +0000 Subject: [PATCH 2/8] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 57aa7a5..094ac49 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 8 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase/stagehand-e629569417ad17cad5c73180109b4c3ae778f38063fc72146fa82f82de145911.yml -openapi_spec_hash: 42e4eedbc0fcc772bb271191a067bce1 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase/stagehand-49b40c7425adba9e67fc102838c5216c45ca1f7ef4c10823c5665fd413538504.yml +openapi_spec_hash: 6880dc029df2e88dfe8943c0dec5a3a5 config_hash: 1fb12ae9b478488bc1e56bfbdc210b01 From 0acc093944e72ee488393ec1fb73dc16450cc825 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 7 May 2026 18:26:04 +0000 Subject: [PATCH 3/8] feat: [feat]: add `ignoreSelectors` to `observe()` --- .stats.yml | 4 ++-- lib/stagehand/models/session_observe_params.rb | 10 +++++++++- rbi/stagehand/models/session_observe_params.rbi | 11 +++++++++++ sig/stagehand/models/session_observe_params.rbs | 7 +++++++ 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 094ac49..0339c57 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 8 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase/stagehand-49b40c7425adba9e67fc102838c5216c45ca1f7ef4c10823c5665fd413538504.yml -openapi_spec_hash: 6880dc029df2e88dfe8943c0dec5a3a5 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase/stagehand-eae8400fade7b2c8329c4148f56de92e147c34c0feecb420c015aab6544a9acc.yml +openapi_spec_hash: 0a9eff1ac1d464e89cbd9db64709b08a config_hash: 1fb12ae9b478488bc1e56bfbdc210b01 diff --git a/lib/stagehand/models/session_observe_params.rb b/lib/stagehand/models/session_observe_params.rb index b2c2f74..8564643 100644 --- a/lib/stagehand/models/session_observe_params.rb +++ b/lib/stagehand/models/session_observe_params.rb @@ -52,6 +52,12 @@ class SessionObserveParams < Stagehand::Internal::Type::BaseModel # @param request_options [Stagehand::RequestOptions, Hash{Symbol=>Object}] class Options < Stagehand::Internal::Type::BaseModel + # @!attribute ignore_selectors + # Selectors for elements and subtrees that should be excluded from observation + # + # @return [Array, nil] + optional :ignore_selectors, Stagehand::Internal::Type::ArrayOf[String], api_name: :ignoreSelectors + # @!attribute model # Model configuration object or model name string (e.g., 'openai/gpt-5-nano') # @@ -79,10 +85,12 @@ class Options < Stagehand::Internal::Type::BaseModel optional :variables, -> { Stagehand::Internal::Type::HashOf[union: Stagehand::SessionObserveParams::Options::Variable] } - # @!method initialize(model: nil, selector: nil, timeout: nil, variables: nil) + # @!method initialize(ignore_selectors: nil, model: nil, selector: nil, timeout: nil, variables: nil) # Some parameter documentations has been truncated, see # {Stagehand::Models::SessionObserveParams::Options} for more details. # + # @param ignore_selectors [Array] Selectors for elements and subtrees that should be excluded from observation + # # @param model [Stagehand::Models::ModelConfig, String] Model configuration object or model name string (e.g., 'openai/gpt-5-nano') # # @param selector [String] CSS selector to scope observation to a specific element diff --git a/rbi/stagehand/models/session_observe_params.rbi b/rbi/stagehand/models/session_observe_params.rbi index ba48ed4..240e691 100644 --- a/rbi/stagehand/models/session_observe_params.rbi +++ b/rbi/stagehand/models/session_observe_params.rbi @@ -100,6 +100,13 @@ module Stagehand ) end + # Selectors for elements and subtrees that should be excluded from observation + sig { returns(T.nilable(T::Array[String])) } + attr_reader :ignore_selectors + + sig { params(ignore_selectors: T::Array[String]).void } + attr_writer :ignore_selectors + # Model configuration object or model name string (e.g., 'openai/gpt-5-nano') sig { returns(T.nilable(T.any(Stagehand::ModelConfig, String))) } attr_reader :model @@ -161,6 +168,7 @@ module Stagehand sig do params( + ignore_selectors: T::Array[String], model: T.any(Stagehand::ModelConfig::OrHash, String), selector: String, timeout: Float, @@ -177,6 +185,8 @@ module Stagehand ).returns(T.attached_class) end def self.new( + # Selectors for elements and subtrees that should be excluded from observation + ignore_selectors: nil, # Model configuration object or model name string (e.g., 'openai/gpt-5-nano') model: nil, # CSS selector to scope observation to a specific element @@ -193,6 +203,7 @@ module Stagehand sig do override.returns( { + ignore_selectors: T::Array[String], model: T.any(Stagehand::ModelConfig, String), selector: String, timeout: Float, diff --git a/sig/stagehand/models/session_observe_params.rbs b/sig/stagehand/models/session_observe_params.rbs index 4aad068..063b837 100644 --- a/sig/stagehand/models/session_observe_params.rbs +++ b/sig/stagehand/models/session_observe_params.rbs @@ -54,6 +54,7 @@ module Stagehand type options = { + ignore_selectors: ::Array[String], model: Stagehand::Models::SessionObserveParams::Options::model, selector: String, timeout: Float, @@ -61,6 +62,10 @@ module Stagehand } class Options < Stagehand::Internal::Type::BaseModel + attr_reader ignore_selectors: ::Array[String]? + + def ignore_selectors=: (::Array[String]) -> ::Array[String] + attr_reader model: Stagehand::Models::SessionObserveParams::Options::model? def model=: ( @@ -82,6 +87,7 @@ module Stagehand ) -> ::Hash[Symbol, Stagehand::Models::SessionObserveParams::Options::variable] def initialize: ( + ?ignore_selectors: ::Array[String], ?model: Stagehand::Models::SessionObserveParams::Options::model, ?selector: String, ?timeout: Float, @@ -89,6 +95,7 @@ module Stagehand ) -> void def to_hash: -> { + ignore_selectors: ::Array[String], model: Stagehand::Models::SessionObserveParams::Options::model, selector: String, timeout: Float, From 9590ccac39407c027e9e2ea3649a719b00660170 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 13 May 2026 02:01:24 +0000 Subject: [PATCH 4/8] ci: pin GitHub Actions to commit SHAs Pin all GitHub Actions referenced in generated workflows (both first-party `actions/*` and third-party) to immutable commit SHAs. Updating pinned actions is now a deliberate codegen-side bump rather than implicit on every workflow run. --- .github/workflows/ci.yml | 14 +++++++------- .github/workflows/publish-gem.yml | 4 ++-- .github/workflows/release-doctor.yml | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7356e9e..bd96cf7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,9 +26,9 @@ jobs: github.repository == 'stainless-sdks/stagehand-ruby' && (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Ruby - uses: ruby/setup-ruby@v1 + uses: ruby/setup-ruby@c4e5b1316158f92e3d49443a9d58b31d25ac0f8f # v1.306.0 with: bundler-cache: false - run: |- @@ -39,7 +39,7 @@ jobs: github.repository == 'stainless-sdks/stagehand-ruby' && !startsWith(github.ref, 'refs/heads/stl/') id: github-oidc - uses: actions/github-script@v8 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: script: core.setOutput('github_token', await core.getIDToken()); @@ -60,9 +60,9 @@ jobs: if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Ruby - uses: ruby/setup-ruby@v1 + uses: ruby/setup-ruby@c4e5b1316158f92e3d49443a9d58b31d25ac0f8f # v1.306.0 with: bundler-cache: false - run: |- @@ -76,9 +76,9 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/stagehand-ruby' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Ruby - uses: ruby/setup-ruby@v1 + uses: ruby/setup-ruby@c4e5b1316158f92e3d49443a9d58b31d25ac0f8f # v1.306.0 with: bundler-cache: false - run: |- diff --git a/.github/workflows/publish-gem.yml b/.github/workflows/publish-gem.yml index 160f82b..c47e5b8 100644 --- a/.github/workflows/publish-gem.yml +++ b/.github/workflows/publish-gem.yml @@ -14,9 +14,9 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Ruby - uses: ruby/setup-ruby@v1 + uses: ruby/setup-ruby@c4e5b1316158f92e3d49443a9d58b31d25ac0f8f # v1.306.0 with: bundler-cache: false - run: |- diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 801df3e..e75d806 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -12,7 +12,7 @@ jobs: 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@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Check release environment run: | From 6149c11d9ab60a0cac69f1e26e3a2f42425ad616 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 14 May 2026 02:01:27 +0000 Subject: [PATCH 5/8] fix(client): elide content type header on requests without body --- lib/stagehand/internal/transport/base_client.rb | 2 ++ test/stagehand/client_test.rb | 9 +++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/stagehand/internal/transport/base_client.rb b/lib/stagehand/internal/transport/base_client.rb index 54200c4..9b452d3 100644 --- a/lib/stagehand/internal/transport/base_client.rb +++ b/lib/stagehand/internal/transport/base_client.rb @@ -306,6 +306,8 @@ def initialize( Stagehand::Internal::Util.deep_merge(*[req[:body], opts[:extra_body]].compact) end + headers.delete("content-type") if body.nil? + url = Stagehand::Internal::Util.join_parsed_uri( @base_url_components, {**req, path: path, query: query} diff --git a/test/stagehand/client_test.rb b/test/stagehand/client_test.rb index 4b96ac0..dc061f1 100644 --- a/test/stagehand/client_test.rb +++ b/test/stagehand/client_test.rb @@ -356,8 +356,8 @@ def test_client_redirect_307 assert_equal(recorded.method, _1.method) assert_equal(recorded.body, _1.body) assert_equal( - recorded.headers.transform_keys(&:downcase).fetch("content-type"), - _1.headers.transform_keys(&:downcase).fetch("content-type") + recorded.headers.transform_keys(&:downcase)["content-type"], + _1.headers.transform_keys(&:downcase)["content-type"] ) end end @@ -474,8 +474,9 @@ def test_default_headers stagehand.sessions.start(model_name: "openai/gpt-5.4-mini") assert_requested(:any, /./) do |req| - headers = req.headers.transform_keys(&:downcase).fetch_values("accept", "content-type") - headers.each { refute_empty(_1) } + headers = req.headers.transform_keys(&:downcase) + expected = req.body.nil? ? ["accept"] : %w[accept content-type] + headers.fetch_values(*expected).each { refute_empty(_1) } end end end From 4b65f221055c7d0d3d7426845fbd0e49ba13d2df Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 20 May 2026 19:16:37 +0000 Subject: [PATCH 6/8] feat: STG-1756 add Vertex auth params to Stagehand spec --- .stats.yml | 4 +- lib/stagehand/models/model_config.rb | 167 +++++++++++++- rbi/stagehand/models/model_config.rbi | 319 ++++++++++++++++++++++++++ sig/stagehand/models/model_config.rbs | 178 +++++++++++++- 4 files changed, 664 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index 0339c57..220445b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 8 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase/stagehand-eae8400fade7b2c8329c4148f56de92e147c34c0feecb420c015aab6544a9acc.yml -openapi_spec_hash: 0a9eff1ac1d464e89cbd9db64709b08a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase/stagehand-e77d6b15f0a94b16a54ef87a84d2cabe49eb11cff5ceba76f00dd788ff483eab.yml +openapi_spec_hash: a1dab7fe72a772d188a15305124ebd73 config_hash: 1fb12ae9b478488bc1e56bfbdc210b01 diff --git a/lib/stagehand/models/model_config.rb b/lib/stagehand/models/model_config.rb index 806ca18..56ae21d 100644 --- a/lib/stagehand/models/model_config.rb +++ b/lib/stagehand/models/model_config.rb @@ -21,29 +21,193 @@ class ModelConfig < Stagehand::Internal::Type::BaseModel # @return [String, nil] optional :base_url, String, api_name: :baseURL + # @!attribute google_auth_options + # google-auth-library options used to authenticate Vertex AI models + # + # @return [Stagehand::Models::ModelConfig::GoogleAuthOptions, nil] + optional :google_auth_options, + -> { Stagehand::ModelConfig::GoogleAuthOptions }, + api_name: :googleAuthOptions + # @!attribute headers # Custom headers sent with every request to the model provider # # @return [Hash{Symbol=>String}, nil] optional :headers, Stagehand::Internal::Type::HashOf[String] + # @!attribute location + # Google Cloud location for Vertex AI models + # + # @return [String, nil] + optional :location, String + + # @!attribute project + # Google Cloud project ID for Vertex AI models + # + # @return [String, nil] + optional :project, String + # @!attribute provider # AI provider for the model (or provide a baseURL endpoint instead) # # @return [Symbol, Stagehand::Models::ModelConfig::Provider, nil] optional :provider, enum: -> { Stagehand::ModelConfig::Provider } - # @!method initialize(model_name:, api_key: nil, base_url: nil, headers: nil, provider: nil) + # @!method initialize(model_name:, api_key: nil, base_url: nil, google_auth_options: nil, headers: nil, location: nil, project: nil, provider: nil) # @param model_name [String] Model name string with provider prefix (e.g., 'openai/gpt-5-nano') # # @param api_key [String] API key for the model provider # # @param base_url [String] Base URL for the model provider # + # @param google_auth_options [Stagehand::Models::ModelConfig::GoogleAuthOptions] google-auth-library options used to authenticate Vertex AI models + # # @param headers [Hash{Symbol=>String}] Custom headers sent with every request to the model provider # + # @param location [String] Google Cloud location for Vertex AI models + # + # @param project [String] Google Cloud project ID for Vertex AI models + # # @param provider [Symbol, Stagehand::Models::ModelConfig::Provider] AI provider for the model (or provide a baseURL endpoint instead) + # @see Stagehand::Models::ModelConfig#google_auth_options + class GoogleAuthOptions < Stagehand::Internal::Type::BaseModel + # @!attribute credentials + # Google Cloud service account credentials + # + # @return [Stagehand::Models::ModelConfig::GoogleAuthOptions::Credentials, nil] + optional :credentials, -> { Stagehand::ModelConfig::GoogleAuthOptions::Credentials } + + # @!attribute project_id + # Google Cloud project ID used by google-auth-library + # + # @return [String, nil] + optional :project_id, String, api_name: :projectId + + # @!attribute scopes + # Google auth scopes for the desired API request + # + # @return [String, Array, nil] + optional :scopes, union: -> { Stagehand::ModelConfig::GoogleAuthOptions::Scopes } + + # @!attribute universe_domain + # Google Cloud universe domain + # + # @return [String, nil] + optional :universe_domain, String, api_name: :universeDomain + + # @!method initialize(credentials: nil, project_id: nil, scopes: nil, universe_domain: nil) + # google-auth-library options used to authenticate Vertex AI models + # + # @param credentials [Stagehand::Models::ModelConfig::GoogleAuthOptions::Credentials] Google Cloud service account credentials + # + # @param project_id [String] Google Cloud project ID used by google-auth-library + # + # @param scopes [String, Array] Google auth scopes for the desired API request + # + # @param universe_domain [String] Google Cloud universe domain + + # @see Stagehand::Models::ModelConfig::GoogleAuthOptions#credentials + class Credentials < Stagehand::Internal::Type::BaseModel + # @!attribute client_email + # + # @return [String] + required :client_email, String + + # @!attribute private_key + # + # @return [String] + required :private_key, String + + # @!attribute auth_provider_x509_cert_url + # + # @return [String, nil] + optional :auth_provider_x509_cert_url, String + + # @!attribute auth_uri + # + # @return [String, nil] + optional :auth_uri, String + + # @!attribute client_id + # + # @return [String, nil] + optional :client_id, String + + # @!attribute client_x509_cert_url + # + # @return [String, nil] + optional :client_x509_cert_url, String + + # @!attribute private_key_id + # + # @return [String, nil] + optional :private_key_id, String + + # @!attribute project_id + # + # @return [String, nil] + optional :project_id, String + + # @!attribute token_uri + # + # @return [String, nil] + optional :token_uri, String + + # @!attribute type + # + # @return [Symbol, Stagehand::Models::ModelConfig::GoogleAuthOptions::Credentials::Type, nil] + optional :type, enum: -> { Stagehand::ModelConfig::GoogleAuthOptions::Credentials::Type } + + # @!attribute universe_domain + # + # @return [String, nil] + optional :universe_domain, String + + # @!method initialize(client_email:, private_key:, auth_provider_x509_cert_url: nil, auth_uri: nil, client_id: nil, client_x509_cert_url: nil, private_key_id: nil, project_id: nil, token_uri: nil, type: nil, universe_domain: nil) + # Google Cloud service account credentials + # + # @param client_email [String] + # @param private_key [String] + # @param auth_provider_x509_cert_url [String] + # @param auth_uri [String] + # @param client_id [String] + # @param client_x509_cert_url [String] + # @param private_key_id [String] + # @param project_id [String] + # @param token_uri [String] + # @param type [Symbol, Stagehand::Models::ModelConfig::GoogleAuthOptions::Credentials::Type] + # @param universe_domain [String] + + # @see Stagehand::Models::ModelConfig::GoogleAuthOptions::Credentials#type + module Type + extend Stagehand::Internal::Type::Enum + + SERVICE_ACCOUNT = :service_account + + # @!method self.values + # @return [Array] + end + end + + # Google auth scopes for the desired API request + # + # @see Stagehand::Models::ModelConfig::GoogleAuthOptions#scopes + module Scopes + extend Stagehand::Internal::Type::Union + + variant String + + variant -> { Stagehand::Models::ModelConfig::GoogleAuthOptions::Scopes::StringArray } + + # @!method self.variants + # @return [Array(String, Array)] + + # @type [Stagehand::Internal::Type::Converter] + StringArray = Stagehand::Internal::Type::ArrayOf[String] + end + end + # AI provider for the model (or provide a baseURL endpoint instead) # # @see Stagehand::Models::ModelConfig#provider @@ -55,6 +219,7 @@ module Provider GOOGLE = :google MICROSOFT = :microsoft BEDROCK = :bedrock + VERTEX = :vertex # @!method self.values # @return [Array] diff --git a/rbi/stagehand/models/model_config.rbi b/rbi/stagehand/models/model_config.rbi index 5d1bc44..ebba7d6 100644 --- a/rbi/stagehand/models/model_config.rbi +++ b/rbi/stagehand/models/model_config.rbi @@ -26,6 +26,17 @@ module Stagehand sig { params(base_url: String).void } attr_writer :base_url + # google-auth-library options used to authenticate Vertex AI models + sig { returns(T.nilable(Stagehand::ModelConfig::GoogleAuthOptions)) } + attr_reader :google_auth_options + + sig do + params( + google_auth_options: Stagehand::ModelConfig::GoogleAuthOptions::OrHash + ).void + end + attr_writer :google_auth_options + # Custom headers sent with every request to the model provider sig { returns(T.nilable(T::Hash[Symbol, String])) } attr_reader :headers @@ -33,6 +44,20 @@ module Stagehand sig { params(headers: T::Hash[Symbol, String]).void } attr_writer :headers + # Google Cloud location for Vertex AI models + sig { returns(T.nilable(String)) } + attr_reader :location + + sig { params(location: String).void } + attr_writer :location + + # Google Cloud project ID for Vertex AI models + sig { returns(T.nilable(String)) } + attr_reader :project + + sig { params(project: String).void } + attr_writer :project + # AI provider for the model (or provide a baseURL endpoint instead) sig { returns(T.nilable(Stagehand::ModelConfig::Provider::OrSymbol)) } attr_reader :provider @@ -45,7 +70,11 @@ module Stagehand model_name: String, api_key: String, base_url: String, + google_auth_options: + Stagehand::ModelConfig::GoogleAuthOptions::OrHash, headers: T::Hash[Symbol, String], + location: String, + project: String, provider: Stagehand::ModelConfig::Provider::OrSymbol ).returns(T.attached_class) end @@ -56,8 +85,14 @@ module Stagehand api_key: nil, # Base URL for the model provider base_url: nil, + # google-auth-library options used to authenticate Vertex AI models + google_auth_options: nil, # Custom headers sent with every request to the model provider headers: nil, + # Google Cloud location for Vertex AI models + location: nil, + # Google Cloud project ID for Vertex AI models + project: nil, # AI provider for the model (or provide a baseURL endpoint instead) provider: nil ) @@ -69,7 +104,10 @@ module Stagehand model_name: String, api_key: String, base_url: String, + google_auth_options: Stagehand::ModelConfig::GoogleAuthOptions, headers: T::Hash[Symbol, String], + location: String, + project: String, provider: Stagehand::ModelConfig::Provider::OrSymbol } ) @@ -77,6 +115,286 @@ module Stagehand def to_hash end + class GoogleAuthOptions < Stagehand::Internal::Type::BaseModel + OrHash = + T.type_alias do + T.any( + Stagehand::ModelConfig::GoogleAuthOptions, + Stagehand::Internal::AnyHash + ) + end + + # Google Cloud service account credentials + sig do + returns( + T.nilable(Stagehand::ModelConfig::GoogleAuthOptions::Credentials) + ) + end + attr_reader :credentials + + sig do + params( + credentials: + Stagehand::ModelConfig::GoogleAuthOptions::Credentials::OrHash + ).void + end + attr_writer :credentials + + # Google Cloud project ID used by google-auth-library + sig { returns(T.nilable(String)) } + attr_reader :project_id + + sig { params(project_id: String).void } + attr_writer :project_id + + # Google auth scopes for the desired API request + sig do + returns( + T.nilable( + Stagehand::ModelConfig::GoogleAuthOptions::Scopes::Variants + ) + ) + end + attr_reader :scopes + + sig do + params( + scopes: Stagehand::ModelConfig::GoogleAuthOptions::Scopes::Variants + ).void + end + attr_writer :scopes + + # Google Cloud universe domain + sig { returns(T.nilable(String)) } + attr_reader :universe_domain + + sig { params(universe_domain: String).void } + attr_writer :universe_domain + + # google-auth-library options used to authenticate Vertex AI models + sig do + params( + credentials: + Stagehand::ModelConfig::GoogleAuthOptions::Credentials::OrHash, + project_id: String, + scopes: Stagehand::ModelConfig::GoogleAuthOptions::Scopes::Variants, + universe_domain: String + ).returns(T.attached_class) + end + def self.new( + # Google Cloud service account credentials + credentials: nil, + # Google Cloud project ID used by google-auth-library + project_id: nil, + # Google auth scopes for the desired API request + scopes: nil, + # Google Cloud universe domain + universe_domain: nil + ) + end + + sig do + override.returns( + { + credentials: + Stagehand::ModelConfig::GoogleAuthOptions::Credentials, + project_id: String, + scopes: + Stagehand::ModelConfig::GoogleAuthOptions::Scopes::Variants, + universe_domain: String + } + ) + end + def to_hash + end + + class Credentials < Stagehand::Internal::Type::BaseModel + OrHash = + T.type_alias do + T.any( + Stagehand::ModelConfig::GoogleAuthOptions::Credentials, + Stagehand::Internal::AnyHash + ) + end + + sig { returns(String) } + attr_accessor :client_email + + sig { returns(String) } + attr_accessor :private_key + + sig { returns(T.nilable(String)) } + attr_reader :auth_provider_x509_cert_url + + sig { params(auth_provider_x509_cert_url: String).void } + attr_writer :auth_provider_x509_cert_url + + sig { returns(T.nilable(String)) } + attr_reader :auth_uri + + sig { params(auth_uri: String).void } + attr_writer :auth_uri + + sig { returns(T.nilable(String)) } + attr_reader :client_id + + sig { params(client_id: String).void } + attr_writer :client_id + + sig { returns(T.nilable(String)) } + attr_reader :client_x509_cert_url + + sig { params(client_x509_cert_url: String).void } + attr_writer :client_x509_cert_url + + sig { returns(T.nilable(String)) } + attr_reader :private_key_id + + sig { params(private_key_id: String).void } + attr_writer :private_key_id + + sig { returns(T.nilable(String)) } + attr_reader :project_id + + sig { params(project_id: String).void } + attr_writer :project_id + + sig { returns(T.nilable(String)) } + attr_reader :token_uri + + sig { params(token_uri: String).void } + attr_writer :token_uri + + sig do + returns( + T.nilable( + Stagehand::ModelConfig::GoogleAuthOptions::Credentials::Type::OrSymbol + ) + ) + end + attr_reader :type + + sig do + params( + type: + Stagehand::ModelConfig::GoogleAuthOptions::Credentials::Type::OrSymbol + ).void + end + attr_writer :type + + sig { returns(T.nilable(String)) } + attr_reader :universe_domain + + sig { params(universe_domain: String).void } + attr_writer :universe_domain + + # Google Cloud service account credentials + sig do + params( + client_email: String, + private_key: String, + auth_provider_x509_cert_url: String, + auth_uri: String, + client_id: String, + client_x509_cert_url: String, + private_key_id: String, + project_id: String, + token_uri: String, + type: + Stagehand::ModelConfig::GoogleAuthOptions::Credentials::Type::OrSymbol, + universe_domain: String + ).returns(T.attached_class) + end + def self.new( + client_email:, + private_key:, + auth_provider_x509_cert_url: nil, + auth_uri: nil, + client_id: nil, + client_x509_cert_url: nil, + private_key_id: nil, + project_id: nil, + token_uri: nil, + type: nil, + universe_domain: nil + ) + end + + sig do + override.returns( + { + client_email: String, + private_key: String, + auth_provider_x509_cert_url: String, + auth_uri: String, + client_id: String, + client_x509_cert_url: String, + private_key_id: String, + project_id: String, + token_uri: String, + type: + Stagehand::ModelConfig::GoogleAuthOptions::Credentials::Type::OrSymbol, + universe_domain: String + } + ) + end + def to_hash + end + + module Type + extend Stagehand::Internal::Type::Enum + + TaggedSymbol = + T.type_alias do + T.all( + Symbol, + Stagehand::ModelConfig::GoogleAuthOptions::Credentials::Type + ) + end + OrSymbol = T.type_alias { T.any(Symbol, String) } + + SERVICE_ACCOUNT = + T.let( + :service_account, + Stagehand::ModelConfig::GoogleAuthOptions::Credentials::Type::TaggedSymbol + ) + + sig do + override.returns( + T::Array[ + Stagehand::ModelConfig::GoogleAuthOptions::Credentials::Type::TaggedSymbol + ] + ) + end + def self.values + end + end + end + + # Google auth scopes for the desired API request + module Scopes + extend Stagehand::Internal::Type::Union + + Variants = T.type_alias { T.any(String, T::Array[String]) } + + sig do + override.returns( + T::Array[ + Stagehand::ModelConfig::GoogleAuthOptions::Scopes::Variants + ] + ) + end + def self.variants + end + + StringArray = + T.let( + Stagehand::Internal::Type::ArrayOf[String], + Stagehand::Internal::Type::Converter + ) + end + end + # AI provider for the model (or provide a baseURL endpoint instead) module Provider extend Stagehand::Internal::Type::Enum @@ -93,6 +411,7 @@ module Stagehand T.let(:microsoft, Stagehand::ModelConfig::Provider::TaggedSymbol) BEDROCK = T.let(:bedrock, Stagehand::ModelConfig::Provider::TaggedSymbol) + VERTEX = T.let(:vertex, Stagehand::ModelConfig::Provider::TaggedSymbol) sig do override.returns( diff --git a/sig/stagehand/models/model_config.rbs b/sig/stagehand/models/model_config.rbs index 60d3ebf..80b6956 100644 --- a/sig/stagehand/models/model_config.rbs +++ b/sig/stagehand/models/model_config.rbs @@ -5,7 +5,10 @@ module Stagehand model_name: String, api_key: String, base_url: String, + google_auth_options: Stagehand::ModelConfig::GoogleAuthOptions, headers: ::Hash[Symbol, String], + location: String, + project: String, provider: Stagehand::Models::ModelConfig::provider } @@ -20,10 +23,24 @@ module Stagehand def base_url=: (String) -> String + attr_reader google_auth_options: Stagehand::ModelConfig::GoogleAuthOptions? + + def google_auth_options=: ( + Stagehand::ModelConfig::GoogleAuthOptions + ) -> Stagehand::ModelConfig::GoogleAuthOptions + attr_reader headers: ::Hash[Symbol, String]? def headers=: (::Hash[Symbol, String]) -> ::Hash[Symbol, String] + attr_reader location: String? + + def location=: (String) -> String + + attr_reader project: String? + + def project=: (String) -> String + attr_reader provider: Stagehand::Models::ModelConfig::provider? def provider=: ( @@ -34,7 +51,10 @@ module Stagehand model_name: String, ?api_key: String, ?base_url: String, + ?google_auth_options: Stagehand::ModelConfig::GoogleAuthOptions, ?headers: ::Hash[Symbol, String], + ?location: String, + ?project: String, ?provider: Stagehand::Models::ModelConfig::provider ) -> void @@ -42,11 +62,166 @@ module Stagehand model_name: String, api_key: String, base_url: String, + google_auth_options: Stagehand::ModelConfig::GoogleAuthOptions, headers: ::Hash[Symbol, String], + location: String, + project: String, provider: Stagehand::Models::ModelConfig::provider } - type provider = :openai | :anthropic | :google | :microsoft | :bedrock + type google_auth_options = + { + credentials: Stagehand::ModelConfig::GoogleAuthOptions::Credentials, + project_id: String, + scopes: Stagehand::Models::ModelConfig::GoogleAuthOptions::scopes, + universe_domain: String + } + + class GoogleAuthOptions < Stagehand::Internal::Type::BaseModel + attr_reader credentials: Stagehand::ModelConfig::GoogleAuthOptions::Credentials? + + def credentials=: ( + Stagehand::ModelConfig::GoogleAuthOptions::Credentials + ) -> Stagehand::ModelConfig::GoogleAuthOptions::Credentials + + attr_reader project_id: String? + + def project_id=: (String) -> String + + attr_reader scopes: Stagehand::Models::ModelConfig::GoogleAuthOptions::scopes? + + def scopes=: ( + Stagehand::Models::ModelConfig::GoogleAuthOptions::scopes + ) -> Stagehand::Models::ModelConfig::GoogleAuthOptions::scopes + + attr_reader universe_domain: String? + + def universe_domain=: (String) -> String + + def initialize: ( + ?credentials: Stagehand::ModelConfig::GoogleAuthOptions::Credentials, + ?project_id: String, + ?scopes: Stagehand::Models::ModelConfig::GoogleAuthOptions::scopes, + ?universe_domain: String + ) -> void + + def to_hash: -> { + credentials: Stagehand::ModelConfig::GoogleAuthOptions::Credentials, + project_id: String, + scopes: Stagehand::Models::ModelConfig::GoogleAuthOptions::scopes, + universe_domain: String + } + + type credentials = + { + client_email: String, + private_key: String, + :auth_provider_x509_cert_url => String, + auth_uri: String, + client_id: String, + :client_x509_cert_url => String, + private_key_id: String, + project_id: String, + token_uri: String, + type: Stagehand::Models::ModelConfig::GoogleAuthOptions::Credentials::type_, + universe_domain: String + } + + class Credentials < Stagehand::Internal::Type::BaseModel + attr_accessor client_email: String + + attr_accessor private_key: String + + attr_reader auth_provider_x509_cert_url: String? + + def auth_provider_x509_cert_url=: (String) -> String + + attr_reader auth_uri: String? + + def auth_uri=: (String) -> String + + attr_reader client_id: String? + + def client_id=: (String) -> String + + attr_reader client_x509_cert_url: String? + + def client_x509_cert_url=: (String) -> String + + attr_reader private_key_id: String? + + def private_key_id=: (String) -> String + + attr_reader project_id: String? + + def project_id=: (String) -> String + + attr_reader token_uri: String? + + def token_uri=: (String) -> String + + attr_reader type: Stagehand::Models::ModelConfig::GoogleAuthOptions::Credentials::type_? + + def type=: ( + Stagehand::Models::ModelConfig::GoogleAuthOptions::Credentials::type_ + ) -> Stagehand::Models::ModelConfig::GoogleAuthOptions::Credentials::type_ + + attr_reader universe_domain: String? + + def universe_domain=: (String) -> String + + def initialize: ( + client_email: String, + private_key: String, + ?auth_provider_x509_cert_url: String, + ?auth_uri: String, + ?client_id: String, + ?client_x509_cert_url: String, + ?private_key_id: String, + ?project_id: String, + ?token_uri: String, + ?type: Stagehand::Models::ModelConfig::GoogleAuthOptions::Credentials::type_, + ?universe_domain: String + ) -> void + + def to_hash: -> { + client_email: String, + private_key: String, + :auth_provider_x509_cert_url => String, + auth_uri: String, + client_id: String, + :client_x509_cert_url => String, + private_key_id: String, + project_id: String, + token_uri: String, + type: Stagehand::Models::ModelConfig::GoogleAuthOptions::Credentials::type_, + universe_domain: String + } + + type type_ = :service_account + + module Type + extend Stagehand::Internal::Type::Enum + + SERVICE_ACCOUNT: :service_account + + def self?.values: -> ::Array[Stagehand::Models::ModelConfig::GoogleAuthOptions::Credentials::type_] + end + end + + type scopes = String | ::Array[String] + + module Scopes + extend Stagehand::Internal::Type::Union + + def self?.variants: -> ::Array[Stagehand::Models::ModelConfig::GoogleAuthOptions::scopes] + + StringArray: Stagehand::Internal::Type::Converter + end + end + + type provider = + :openai | :anthropic | :google | :microsoft | :bedrock | :vertex module Provider extend Stagehand::Internal::Type::Enum @@ -56,6 +231,7 @@ module Stagehand GOOGLE: :google MICROSOFT: :microsoft BEDROCK: :bedrock + VERTEX: :vertex def self?.values: -> ::Array[Stagehand::Models::ModelConfig::provider] end From 7b65ca776e1e13c489f13991b012fa24aecc60e6 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 20 May 2026 21:00:42 +0000 Subject: [PATCH 7/8] feat: Add `screenshot` option to Extract --- .stats.yml | 4 ++-- lib/stagehand/models/session_extract_params.rb | 14 +++++++++++++- rbi/stagehand/models/session_extract_params.rbi | 13 +++++++++++++ sig/stagehand/models/session_extract_params.rbs | 7 +++++++ 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 220445b..9043f09 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 8 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase/stagehand-e77d6b15f0a94b16a54ef87a84d2cabe49eb11cff5ceba76f00dd788ff483eab.yml -openapi_spec_hash: a1dab7fe72a772d188a15305124ebd73 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase/stagehand-80502d74c1be605e77d45ff2b54297fe34ce85dbad1e8f2dfa30ba6d09601219.yml +openapi_spec_hash: fd62f768756a400c3ecd695bfcf3845a config_hash: 1fb12ae9b478488bc1e56bfbdc210b01 diff --git a/lib/stagehand/models/session_extract_params.rb b/lib/stagehand/models/session_extract_params.rb index 1b304fb..8124184 100644 --- a/lib/stagehand/models/session_extract_params.rb +++ b/lib/stagehand/models/session_extract_params.rb @@ -72,6 +72,13 @@ class Options < Stagehand::Internal::Type::BaseModel # @return [Stagehand::Models::ModelConfig, String, nil] optional :model, union: -> { Stagehand::SessionExtractParams::Options::Model } + # @!attribute screenshot + # When true, include a screenshot of the current viewport in the extraction LLM + # call. Defaults to false. + # + # @return [Boolean, nil] + optional :screenshot, Stagehand::Internal::Type::Boolean + # @!attribute selector # CSS selector to scope extraction to a specific element # @@ -84,11 +91,16 @@ class Options < Stagehand::Internal::Type::BaseModel # @return [Float, nil] optional :timeout, Float - # @!method initialize(ignore_selectors: nil, model: nil, selector: nil, timeout: nil) + # @!method initialize(ignore_selectors: nil, model: nil, screenshot: nil, selector: nil, timeout: nil) + # Some parameter documentations has been truncated, see + # {Stagehand::Models::SessionExtractParams::Options} for more details. + # # @param ignore_selectors [Array] Selectors for elements and subtrees that should be excluded from extraction # # @param model [Stagehand::Models::ModelConfig, String] Model configuration object or model name string (e.g., 'openai/gpt-5-nano') # + # @param screenshot [Boolean] When true, include a screenshot of the current viewport in the extraction LLM ca + # # @param selector [String] CSS selector to scope extraction to a specific element # # @param timeout [Float] Timeout in ms for the extraction diff --git a/rbi/stagehand/models/session_extract_params.rbi b/rbi/stagehand/models/session_extract_params.rbi index 2fc2eb4..841a61d 100644 --- a/rbi/stagehand/models/session_extract_params.rbi +++ b/rbi/stagehand/models/session_extract_params.rbi @@ -127,6 +127,14 @@ module Stagehand end attr_writer :model + # When true, include a screenshot of the current viewport in the extraction LLM + # call. Defaults to false. + sig { returns(T.nilable(T::Boolean)) } + attr_reader :screenshot + + sig { params(screenshot: T::Boolean).void } + attr_writer :screenshot + # CSS selector to scope extraction to a specific element sig { returns(T.nilable(String)) } attr_reader :selector @@ -145,6 +153,7 @@ module Stagehand params( ignore_selectors: T::Array[String], model: T.any(Stagehand::ModelConfig::OrHash, String), + screenshot: T::Boolean, selector: String, timeout: Float ).returns(T.attached_class) @@ -154,6 +163,9 @@ module Stagehand ignore_selectors: nil, # Model configuration object or model name string (e.g., 'openai/gpt-5-nano') model: nil, + # When true, include a screenshot of the current viewport in the extraction LLM + # call. Defaults to false. + screenshot: nil, # CSS selector to scope extraction to a specific element selector: nil, # Timeout in ms for the extraction @@ -166,6 +178,7 @@ module Stagehand { ignore_selectors: T::Array[String], model: T.any(Stagehand::ModelConfig, String), + screenshot: T::Boolean, selector: String, timeout: Float } diff --git a/sig/stagehand/models/session_extract_params.rbs b/sig/stagehand/models/session_extract_params.rbs index aedaaca..251245b 100644 --- a/sig/stagehand/models/session_extract_params.rbs +++ b/sig/stagehand/models/session_extract_params.rbs @@ -63,6 +63,7 @@ module Stagehand { ignore_selectors: ::Array[String], model: Stagehand::Models::SessionExtractParams::Options::model, + screenshot: bool, selector: String, timeout: Float } @@ -78,6 +79,10 @@ module Stagehand Stagehand::Models::SessionExtractParams::Options::model ) -> Stagehand::Models::SessionExtractParams::Options::model + attr_reader screenshot: bool? + + def screenshot=: (bool) -> bool + attr_reader selector: String? def selector=: (String) -> String @@ -89,6 +94,7 @@ module Stagehand def initialize: ( ?ignore_selectors: ::Array[String], ?model: Stagehand::Models::SessionExtractParams::Options::model, + ?screenshot: bool, ?selector: String, ?timeout: Float ) -> void @@ -96,6 +102,7 @@ module Stagehand def to_hash: -> { ignore_selectors: ::Array[String], model: Stagehand::Models::SessionExtractParams::Options::model, + screenshot: bool, selector: String, timeout: Float } From 3981726153bc8b8ea61b921308bb01fe470e8ea8 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 20 May 2026 21:01:09 +0000 Subject: [PATCH 8/8] release: 3.21.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 15 +++++++++++++++ Gemfile.lock | 2 +- lib/stagehand/version.rb | 2 +- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index d11c8fc..eba8a04 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "3.20.0" + ".": "3.21.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 8fd0ed0..24013f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## 3.21.0 (2026-05-20) + +Full Changelog: [v3.20.0...v3.21.0](https://github.com/browserbase/stagehand-ruby/compare/v3.20.0...v3.21.0) + +### Features + +* [feat]: add `ignoreSelectors` to `observe()` ([0acc093](https://github.com/browserbase/stagehand-ruby/commit/0acc093944e72ee488393ec1fb73dc16450cc825)) +* Add `screenshot` option to Extract ([7b65ca7](https://github.com/browserbase/stagehand-ruby/commit/7b65ca776e1e13c489f13991b012fa24aecc60e6)) +* STG-1756 add Vertex auth params to Stagehand spec ([4b65f22](https://github.com/browserbase/stagehand-ruby/commit/4b65f221055c7d0d3d7426845fbd0e49ba13d2df)) + + +### Bug Fixes + +* **client:** elide content type header on requests without body ([6149c11](https://github.com/browserbase/stagehand-ruby/commit/6149c11d9ab60a0cac69f1e26e3a2f42425ad616)) + ## 3.20.0 (2026-05-06) Full Changelog: [v3.19.3...v3.20.0](https://github.com/browserbase/stagehand-ruby/compare/v3.19.3...v3.20.0) diff --git a/Gemfile.lock b/Gemfile.lock index 4490644..adcbab3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -11,7 +11,7 @@ GIT PATH remote: . specs: - stagehand (3.20.0) + stagehand (3.21.0) cgi connection_pool diff --git a/lib/stagehand/version.rb b/lib/stagehand/version.rb index 2fbf718..bffebd2 100644 --- a/lib/stagehand/version.rb +++ b/lib/stagehand/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module Stagehand - VERSION = "3.20.0" + VERSION = "3.21.0" end