Module: Riffer::Tools::Toolable

Included in:
Riffer::Tool
Defined in:
lib/riffer/tools/toolable.rb

Overview

Shared class-level DSL for anything that presents as a tool to an LLM. Extend it to make a class discoverable as a tool; instance-level execution (+call+, call_with_validation) lives on Riffer::Tool instead.

class MyTool
extend Riffer::Tools::Toolable

description "Does something useful"

params do
  required :input, String
end
end

Constant Summary collapse

DEFAULT_TIMEOUT =

RBS:

  • self.@extenders: Array[Module]?

  • @description: String?

  • @identifier: String?

  • @timeout: (Integer | Float)?

  • @params_builder: Riffer::Params?

  • @kind: Symbol?

10

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.allObject

Returns all classes that have extended Toolable.

--

Signature:

  • () -> Array[Module]



41
42
43
# File 'lib/riffer/tools/toolable.rb', line 41

def self.all
  @extenders || []
end

.extended(base) ⇒ Object

Tracks all classes that extend Toolable.

--

Signature:

  • (Module) -> void



32
33
34
35
# File 'lib/riffer/tools/toolable.rb', line 32

def self.extended(base)
  extenders = (@extenders ||= []) #: Array[Module]
  extenders << base
end

Instance Method Details

#description(value = nil) ⇒ Object

Gets or sets the tool description.

--

Signature:

  • (?String?) -> String?



49
50
51
52
53
# File 'lib/riffer/tools/toolable.rb', line 49

def description(value = nil)
  return @description if value.nil?

  @description = value.to_s
end

#identifier(value = nil) ⇒ Object

Gets or sets the tool identifier/name.

--

Signature:

  • (?String?) -> String



59
60
61
62
63
64
65
# File 'lib/riffer/tools/toolable.rb', line 59

def identifier(value = nil)
  if value.nil?
    return @identifier || Riffer::Helpers::ClassNameConverter.convert(Module.instance_method(:name).bind_call(self))
  end

  @identifier = value.to_s
end

#kind(value = nil) ⇒ Object

Returns the kind of toolable entity; defaults to :tool.

Signature:

  • (?Symbol?) -> Symbol



110
111
112
113
114
# File 'lib/riffer/tools/toolable.rb', line 110

def kind(value = nil)
  return @kind || :tool if value.nil?

  @kind = value.to_sym
end

#name(value = nil) ⇒ Object

Alias for identifier — used by providers.

--

Signature:

  • (?String?) -> String



71
72
73
74
75
# File 'lib/riffer/tools/toolable.rb', line 71

def name(value = nil)
  return identifier(value) if value

  identifier
end

#parameters_schema(strict: false) ⇒ Object

Returns the JSON Schema for the tool's parameters.

--

Signature:

  • (?strict: bool) -> Hash[Symbol, untyped]



103
104
105
# File 'lib/riffer/tools/toolable.rb', line 103

def parameters_schema(strict: false)
  @params_builder&.to_json_schema(strict: strict) || empty_schema
end

#params(&block) ⇒ Object

Defines parameters using the Params DSL.

--

Signature:

  • () ?{ (Riffer::Params) [self: Riffer::Params] -> void } -> Riffer::Params?



91
92
93
94
95
96
97
# File 'lib/riffer/tools/toolable.rb', line 91

def params(&block)
  return @params_builder if block.nil?

  builder = Riffer::Params.new
  builder.instance_eval(&block)
  @params_builder = builder
end

#timeout(value = nil) ⇒ Object

Gets or sets the tool timeout in seconds.

--

Signature:

  • (?(Integer | Float)?) -> (Integer | Float)



81
82
83
84
85
# File 'lib/riffer/tools/toolable.rb', line 81

def timeout(value = nil)
  return @timeout || DEFAULT_TIMEOUT if value.nil?

  @timeout = value.to_f
end

#to_tool_schema(strict: false) ⇒ Object

Returns a provider-agnostic tool schema hash.

--

Signature:

  • (?strict: bool) -> Hash[Symbol, untyped]



120
121
122
123
124
125
126
# File 'lib/riffer/tools/toolable.rb', line 120

def to_tool_schema(strict: false)
  {
    name: name,
    description: description,
    parameters_schema: parameters_schema(strict: strict),
  }
end

#validate_as_tool!Object

Validates that the minimum required metadata is present for LLM tool use.

Raises Riffer::ArgumentError if validation fails.

--

Signature:

  • () -> true

Raises:



134
135
136
137
138
139
140
141
142
# File 'lib/riffer/tools/toolable.rb', line 134

def validate_as_tool!
  if description.nil? || description.to_s.strip.empty?
    raise Riffer::ArgumentError,
          "#{self} must define a description"
  end
  raise Riffer::ArgumentError, "#{self} must have an identifier" if identifier.nil? || identifier.to_s.strip.empty?

  true
end