Module: RubyLLM::Tools::ProviderTools

Defined in:
lib/ruby_llm/tools/provider_tools.rb

Overview

Normalizes and resolves the provider tools a chat enabled with Chat#with_provider_tools. Protocols declare an alias table mapping portable names such as :web_search to their wire format; raw Hashes pass through verbatim so new provider tools work without a gem update. :nodoc:

Defined Under Namespace

Classes: Resolution

Class Method Summary collapse

Class Method Details

.normalize(tools, tools_with_options) ⇒ Object

Normalizes with_provider_tools arguments into entry hashes: options: for aliases and raw: for verbatim tool specs.



66
67
68
69
# File 'lib/ruby_llm/tools/provider_tools.rb', line 66

def normalize(tools, tools_with_options)
  entries = tools.compact.map { |tool| normalize_positional(tool) }
  entries + tools_with_options.map { |name, options| { name: name.to_sym, options: options.to_h } }
end

.normalize_positional(tool) ⇒ Object



71
72
73
74
75
76
77
78
79
80
# File 'lib/ruby_llm/tools/provider_tools.rb', line 71

def normalize_positional(tool)
  case tool
  when Symbol, String then { name: tool.to_sym, options: {} }
  when Hash then normalized_entry?(tool) ? tool : { raw: tool }
  else
    raise ArgumentError,
          "Provider tools must be Symbols or Hashes, got #{tool.class}. " \
          'Pass :web_search for a portable alias or the provider\'s tool definition as a Hash.'
  end
end

.normalized_entry?(hash) ⇒ Boolean

Entries that already went through normalize (an Agent's declared provider_tools, for example) pass through unchanged.

Returns:

  • (Boolean)


84
85
86
# File 'lib/ruby_llm/tools/provider_tools.rb', line 84

def normalized_entry?(hash)
  hash.key?(:raw) ? hash.size == 1 : hash.size == 2 && hash.key?(:name) && hash.key?(:options)
end

.raise_unknown_alias(name, aliases, owner) ⇒ Object



101
102
103
104
105
106
# File 'lib/ruby_llm/tools/provider_tools.rb', line 101

def raise_unknown_alias(name, aliases, owner)
  known = aliases.keys.map { |key| ":#{key}" }.join(', ')
  raise UnsupportedServerToolError,
        "#{owner} has no server tool alias :#{name}. Known aliases: #{known}. " \
        'New or unlisted tools work by passing the provider\'s tool definition as a Hash.'
end

.resolve(entries, aliases:, owner:) ⇒ Object

Resolves normalized entries against a protocol's alias table.



89
90
91
92
93
94
95
96
97
98
99
# File 'lib/ruby_llm/tools/provider_tools.rb', line 89

def resolve(entries, aliases:, owner:)
  entries.each_with_object(Resolution.new) do |entry, resolution|
    if entry[:raw]
      resolution.add_raw(entry[:raw])
    else
      spec = aliases[entry[:name]]
      raise_unknown_alias(entry[:name], aliases, owner) unless spec
      resolution.add(spec, entry[:options])
    end
  end
end