Class: Ask::Tool
- Inherits:
-
Object
- Object
- Ask::Tool
- Defined in:
- lib/ask/tools/tool.rb
Defined Under Namespace
Class Method Summary collapse
- .build_schema_from_params ⇒ Object
- .deep_stringify_keys(obj) ⇒ Object
- .desc ⇒ Object
- .description(text = nil) ⇒ Object
- .inherited(subclass) ⇒ Object
-
.name(custom = :_no_arg_given) ⇒ Object
Declare a custom tool name.
- .param(name, type:, desc: nil, description: nil, required: true) ⇒ Object
- .parameters ⇒ Object
- .params(schema = nil, &block) ⇒ Object
- .params_schema ⇒ Object
- .provider_params ⇒ Object
- .resolve_params_schema(definition) ⇒ Object
Instance Method Summary collapse
- #call(args = {}, abort_controller = nil) ⇒ Object
- #description ⇒ Object
- #execute(**args) ⇒ Object
- #inspect ⇒ Object
- #name ⇒ Object
- #parameters ⇒ Object
- #params_schema ⇒ Object
- #provider_params ⇒ Object
- #tool_definition ⇒ Object
Class Method Details
.build_schema_from_params ⇒ Object
77 78 79 80 81 82 83 84 85 86 |
# File 'lib/ask/tools/tool.rb', line 77 def build_schema_from_params properties = parameters.to_h do |_name, param| schema = { type: param.type } schema[:description] = param.description if param.description schema[:items] = { type: "string" } if param.type == "array" [param.name.to_s, schema] end required = parameters.select { |_, p| p.required }.keys.map(&:to_s) { type: "object", properties: properties, required: required, additionalProperties: false } end |
.deep_stringify_keys(obj) ⇒ Object
100 101 102 103 104 105 106 |
# File 'lib/ask/tools/tool.rb', line 100 def deep_stringify_keys(obj) case obj when Hash then obj.each_with_object({}) { |(k, v), h| h[k.to_s] = deep_stringify_keys(v) } when Array then obj.map { |v| deep_stringify_keys(v) } else obj end end |
.desc ⇒ Object
30 31 32 33 |
# File 'lib/ask/tools/tool.rb', line 30 def description(text = nil) return @description unless text @description = text end |
.description(text = nil) ⇒ Object
26 27 28 29 |
# File 'lib/ask/tools/tool.rb', line 26 def description(text = nil) return @description unless text @description = text end |
.inherited(subclass) ⇒ Object
17 18 19 20 21 22 23 24 |
# File 'lib/ask/tools/tool.rb', line 17 def inherited(subclass) super @parameters = {} if @parameters.nil? subclass.instance_variable_set(:@description, nil) subclass.instance_variable_set(:@parameters, {}) subclass.instance_variable_set(:@params_schema_definition, nil) subclass.instance_variable_set(:@tool_name, nil) end |
.name(custom = :_no_arg_given) ⇒ Object
Declare a custom tool name. Called with no argument returns the class name (via Module#name). Called with a string stores a custom name for the instance. Example: name "my_custom_tool"
36 37 38 39 40 41 42 |
# File 'lib/ask/tools/tool.rb', line 36 def name(custom = :_no_arg_given) if custom == :_no_arg_given super() # Module#name, returns the Ruby class path else @tool_name = custom end end |
.param(name, type:, desc: nil, description: nil, required: true) ⇒ Object
44 45 46 47 48 49 50 51 |
# File 'lib/ask/tools/tool.rb', line 44 def param(name, type:, desc: nil, description: nil, required: true) type = type.to_s.downcase.to_sym validate_param_type!(type, name) parameters[name] = Parameter.new( name: name, type: map_type(type), description: desc || description, required: required ) end |
.parameters ⇒ Object
57 58 59 |
# File 'lib/ask/tools/tool.rb', line 57 def parameters @parameters ||= {} end |
.params(schema = nil, &block) ⇒ Object
53 54 55 |
# File 'lib/ask/tools/tool.rb', line 53 def params(schema = nil, &block) @params_schema_definition = schema || block end |
.params_schema ⇒ Object
65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/ask/tools/tool.rb', line 65 def params_schema @params_schema ||= begin if @params_schema_definition deep_stringify_keys(resolve_params_schema(@params_schema_definition)) elsif @parameters && @parameters.any? build_schema_from_params else nil end end end |
.provider_params ⇒ Object
61 62 63 |
# File 'lib/ask/tools/tool.rb', line 61 def provider_params @provider_params ||= {} end |
.resolve_params_schema(definition) ⇒ Object
88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/ask/tools/tool.rb', line 88 def resolve_params_schema(definition) case definition when Proc schema_class = Ask::Schema.create(&definition) schema_class.new.to_json_schema.dig(:schema) when Hash then definition when ->(d) { d.respond_to?(:to_json_schema) } definition.to_json_schema.dig(:schema) else nil end end |
Instance Method Details
#call(args = {}, abort_controller = nil) ⇒ Object
152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/ask/tools/tool.rb', line 152 def call(args = {}, abort_controller = nil) normalized = normalize_args(args) validation = validate(normalized) return Ask::Result.failure(validation) if validation normalized[:_abort_controller] = abort_controller if abort_controller execute_kwargs = normalized.reject { |k, _| k == :_abort_controller || k == :abort_controller } execute(**execute_kwargs) rescue Halt => e Ask::Result.ok(data: e.content, metadata: { halted: true }) rescue StandardError => e Ask::Result.failure("#{self.class.name.split('::').last} raised #{e.class}: #{e.}") end |
#description ⇒ Object
144 145 146 |
# File 'lib/ask/tools/tool.rb', line 144 def description self.class.description end |
#execute(**args) ⇒ Object
165 166 167 |
# File 'lib/ask/tools/tool.rb', line 165 def execute(**args) raise NotImplementedError, "#{self.class} must implement #execute(**args)" end |
#inspect ⇒ Object
188 189 190 |
# File 'lib/ask/tools/tool.rb', line 188 def inspect "#<#{self.class.name} name=#{name.inspect}>" end |
#name ⇒ Object
130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/ask/tools/tool.rb', line 130 def name custom = self.class.instance_variable_get(:@tool_name) return custom if custom klass_name = self.class.name.to_s.split("::").last || "" normalized = klass_name.dup.force_encoding("UTF-8").unicode_normalize(:nfkd) normalized.encode("ASCII", replace: "") .gsub(/[^a-zA-Z0-9_-]/, "-") .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2') .gsub(/([a-z\d])([A-Z])/, '\1_\2') .downcase .delete_suffix("_tool") end |
#parameters ⇒ Object
148 149 150 |
# File 'lib/ask/tools/tool.rb', line 148 def parameters self.class.parameters end |
#params_schema ⇒ Object
169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/ask/tools/tool.rb', line 169 def params_schema return @params_schema if defined?(@params_schema) @params_schema = begin if params_schema_definition deep_stringify_keys(resolve_params_schema(params_schema_definition)) elsif parameters.any? build_schema_from_params else nil end end end |
#provider_params ⇒ Object
126 127 128 |
# File 'lib/ask/tools/tool.rb', line 126 def provider_params self.class.provider_params end |
#tool_definition ⇒ Object
182 183 184 185 186 |
# File 'lib/ask/tools/tool.rb', line 182 def tool_definition defn = { name: name, description: description } defn[:input_schema] = params_schema if params_schema defn end |