class RubyLLM::Browser::Capabilities

What a backend can actually guarantee.

Capabilities are the Gem’s fail-closed gate. Policy refuses to start a session unless a backend claims enforced egress isolation; a URL allowlist in Ruby can never substitute for it. Local mode needs a host-pinned server binary, and the Stagehand SDK always merges STAGEHAND_CUSTOM_HEADERS, so those headers must be host-approved before any session starts.

Constants

EGRESS_ISOLATION

Supported egress-isolation postures.

  • ‘:enforced` every initiated request stays within approved destinations and

    public address ranges at connection time
    
  • ‘:unverified` not proven; the Gem treats this as unusable for live sessions

SERVER_MODES

Server/topology modes.

Attributes

egress_isolation[R]
server_mode[R]

Public Class Methods

new(server_mode: :remote, egress_isolation: :unverified, local_binary_pinned: false, custom_headers_present: false, custom_headers_approved: false, act_supported: false) click to toggle source
# File lib/ruby_llm/browser/capabilities.rb, line 25
def initialize(server_mode: :remote, egress_isolation: :unverified,
               local_binary_pinned: false, custom_headers_present: false,
               custom_headers_approved: false, act_supported: false)
  @server_mode = symbolize!(server_mode, SERVER_MODES, :server_mode)
  @egress_isolation = symbolize!(egress_isolation, EGRESS_ISOLATION, :egress_isolation)
  @local_binary_pinned = !!local_binary_pinned
  @custom_headers_present = !!custom_headers_present
  @custom_headers_approved = !!custom_headers_approved
  @act_supported = !!act_supported
  freeze
end

Public Instance Methods

==(other) click to toggle source
# File lib/ruby_llm/browser/capabilities.rb, line 57
def ==(other)
  other.is_a?(Capabilities) && to_h == other.to_h
end
act_supported?(= @act_supported) click to toggle source
# File lib/ruby_llm/browser/capabilities.rb, line 42
    def act_supported? = @act_supported

    def to_h
      {
        server_mode: server_mode,
        egress_isolation: egress_isolation,
        local_binary_pinned: @local_binary_pinned,
        custom_headers_present: @custom_headers_present,
        custom_headers_approved: @custom_headers_approved,
        act_supported: @act_supported
      }
    end

    def digest = Redactor.digest(to_h)

    def ==(other)
      other.is_a?(Capabilities) && to_h == other.to_h
    end
    alias eql? ==

    def hash = to_h.hash

    def inspect = "#<#{self.class} #{to_h.map { |k, v| "#{k}=#{v}" }.join(" ")}>"

    private

    def symbolize!(value, allowed, name)
      symbol = value.to_sym
      return symbol if allowed.include?(symbol)

      raise InvalidInput, "#{name} must be one of #{allowed.inspect}"
    end
  end
end
custom_headers_approved?(= @custom_headers_approved) click to toggle source
# File lib/ruby_llm/browser/capabilities.rb, line 41
  def custom_headers_approved? = @custom_headers_approved
  def act_supported? = @act_supported

  def to_h
    {
      server_mode: server_mode,
      egress_isolation: egress_isolation,
      local_binary_pinned: @local_binary_pinned,
      custom_headers_present: @custom_headers_present,
      custom_headers_approved: @custom_headers_approved,
      act_supported: @act_supported
    }
  end

  def digest = Redactor.digest(to_h)

  def ==(other)
    other.is_a?(Capabilities) && to_h == other.to_h
  end
  alias eql? ==

  def hash = to_h.hash

  def inspect = "#<#{self.class} #{to_h.map { |k, v| "#{k}=#{v}" }.join(" ")}>"

  private

  def symbolize!(value, allowed, name)
    symbol = value.to_sym
    return symbol if allowed.include?(symbol)

    raise InvalidInput, "#{name} must be one of #{allowed.inspect}"
  end
end
custom_headers_present?(= @custom_headers_present) click to toggle source
# File lib/ruby_llm/browser/capabilities.rb, line 40
def custom_headers_present? = @custom_headers_present
def custom_headers_approved? = @custom_headers_approved
def act_supported? = @act_supported

def to_h
  {
    server_mode: server_mode,
    egress_isolation: egress_isolation,
    local_binary_pinned: @local_binary_pinned,
    custom_headers_present: @custom_headers_present,
    custom_headers_approved: @custom_headers_approved,
    act_supported: @act_supported
  }
end

def digest = Redactor.digest(to_h)

def ==(other)
  other.is_a?(Capabilities) && to_h == other.to_h
end
alias eql? ==

def hash = to_h.hash

def inspect = "#<#{self.class} #{to_h.map { |k, v| "#{k}=#{v}" }.join(" ")}>"

private

def symbolize!(value, allowed, name)
  symbol = value.to_sym
  return symbol if allowed.include?(symbol)

  raise InvalidInput, "#{name} must be one of #{allowed.inspect}"
end
    
digest(= Redactor.digest(to_h)) click to toggle source
# File lib/ruby_llm/browser/capabilities.rb, line 55
      def digest = Redactor.digest(to_h)

      def ==(other)
        other.is_a?(Capabilities) && to_h == other.to_h
      end
      alias eql? ==

      def hash = to_h.hash

      def inspect = "#<#{self.class} #{to_h.map { |k, v| "#{k}=#{v}" }.join(" ")}>"

      private

      def symbolize!(value, allowed, name)
        symbol = value.to_sym
        return symbol if allowed.include?(symbol)

        raise InvalidInput, "#{name} must be one of #{allowed.inspect}"
      end
    end
  end
end
enforced_egress?(= egress_isolation == :enforced) click to toggle source
# File lib/ruby_llm/browser/capabilities.rb, line 38
def enforced_egress? = egress_isolation == :enforced
def local_binary_pinned? = @local_binary_pinned
def custom_headers_present? = @custom_headers_present
def custom_headers_approved? = @custom_headers_approved
def act_supported? = @act_supported

def to_h
  {
    server_mode: server_mode,
    egress_isolation: egress_isolation,
    local_binary_pinned: @local_binary_pinned,
    custom_headers_present: @custom_headers_present,
    custom_headers_approved: @custom_headers_approved,
    act_supported: @act_supported
  }
end

def digest = Redactor.digest(to_h)

def ==(other)
  other.is_a?(Capabilities) && to_h == other.to_h
end
alias eql? ==

def hash = to_h.hash

def inspect = "#<#{self.class} #{to_h.map { |k, v| "#{k}=#{v}" }.join(" ")}>"

private

def symbolize!(value, allowed, name)
  symbol = value.to_sym
  return symbol if allowed.include?(symbol)

  raise InvalidInput, "#{name} must be one of #{allowed.inspect}"
hash(= to_h.hash) click to toggle source
# File lib/ruby_llm/browser/capabilities.rb, line 62
    def hash = to_h.hash

    def inspect = "#<#{self.class} #{to_h.map { |k, v| "#{k}=#{v}" }.join(" ")}>"

    private

    def symbolize!(value, allowed, name)
      symbol = value.to_sym
      return symbol if allowed.include?(symbol)

      raise InvalidInput, "#{name} must be one of #{allowed.inspect}"
    end
  end
end
inspect(= " click to toggle source
# File lib/ruby_llm/browser/capabilities.rb, line 64
  def inspect = "#<#{self.class} #{to_h.map { |k, v| "#{k}=#{v}" }.join(" ")}>"

  private

  def symbolize!(value, allowed, name)
    symbol = value.to_sym
    return symbol if allowed.include?(symbol)

    raise InvalidInput, "#{name} must be one of #{allowed.inspect}"
  end
end
local_binary_pinned?(= @local_binary_pinned) click to toggle source
# File lib/ruby_llm/browser/capabilities.rb, line 39
def local_binary_pinned? = @local_binary_pinned
def custom_headers_present? = @custom_headers_present
def custom_headers_approved? = @custom_headers_approved
def act_supported? = @act_supported

def to_h
  {
    server_mode: server_mode,
    egress_isolation: egress_isolation,
    local_binary_pinned: @local_binary_pinned,
    custom_headers_present: @custom_headers_present,
    custom_headers_approved: @custom_headers_approved,
    act_supported: @act_supported
  }
end

def digest = Redactor.digest(to_h)

def ==(other)
  other.is_a?(Capabilities) && to_h == other.to_h
end
alias eql? ==

def hash = to_h.hash

def inspect = "#<#{self.class} #{to_h.map { |k, v| "#{k}=#{v}" }.join(" ")}>"

private

def symbolize!(value, allowed, name)
  symbol = value.to_sym
  return symbol if allowed.include?(symbol)

  raise InvalidInput, "#{name} must be one of #{allowed.inspect}"
end
local_mode?(= server_mode == :local) click to toggle source
# File lib/ruby_llm/browser/capabilities.rb, line 37
def local_mode? = server_mode == :local
def enforced_egress? = egress_isolation == :enforced
def local_binary_pinned? = @local_binary_pinned
def custom_headers_present? = @custom_headers_present
def custom_headers_approved? = @custom_headers_approved
def act_supported? = @act_supported

def to_h
  {
    server_mode: server_mode,
    egress_isolation: egress_isolation,
    local_binary_pinned: @local_binary_pinned,
    custom_headers_present: @custom_headers_present,
    custom_headers_approved: @custom_headers_approved,
    act_supported: @act_supported
  }
end

def digest = Redactor.digest(to_h)

def ==(other)
  other.is_a?(Capabilities) && to_h == other.to_h
end
alias eql? ==

def hash = to_h.hash

def inspect = "#<#{self.class} #{to_h.map { |k, v| "#{k}=#{v}" }.join(" ")}>"

private

def symbolize!(value, allowed, name)
  symbol = value.to_sym
  return symbol if allowed.include?(symbol)

  raise InvalidInput, 
symbolize!(value, allowed, name) click to toggle source
# File lib/ruby_llm/browser/capabilities.rb, line 68
def symbolize!(value, allowed, name)
  symbol = value.to_sym
  return symbol if allowed.include?(symbol)

  raise InvalidInput, "#{name} must be one of #{allowed.inspect}"
end
to_h() click to toggle source
# File lib/ruby_llm/browser/capabilities.rb, line 44
def to_h
  {
    server_mode: server_mode,
    egress_isolation: egress_isolation,
    local_binary_pinned: @local_binary_pinned,
    custom_headers_present: @custom_headers_present,
    custom_headers_approved: @custom_headers_approved,
    act_supported: @act_supported
  }
end