Commit df5321f

mo khan <mo@mokhan.ca>
2026-01-21 19:57:17
refactor: extract a Tool class
1 parent 131253b
lib/elelem/tool.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module Elelem
+  class Tool
+    attr_reader :name, :description, :params, :required, :aliases
+
+    def initialize(name, description:, params: {}, required: [], aliases: [], &fn)
+      @name = name
+      @description = description
+      @params = params
+      @required = required
+      @aliases = aliases
+      @fn = fn
+    end
+
+    def call(args)
+      @fn.call(args)
+    end
+
+    def to_h
+      {
+        type: "function",
+        function: {
+          name: name,
+          description: description,
+          parameters: { type: "object", properties: params, required: required }
+        }
+      }
+    end
+  end
+end
lib/elelem/toolbox.rb
@@ -11,8 +11,9 @@ module Elelem
     end
 
     def add(name, description:, params: {}, required: [], aliases: [], &fn)
-      @tools[name] = { description: description, params: params, required: required, fn: fn }
-      aliases.each { |a| @aliases[a] = name }
+      tool = Tool.new(name, description: description, params: params, required: required, aliases: aliases, &fn)
+      @tools[name] = tool
+      tool.aliases.each { |a| @aliases[a] = name }
     end
 
     def before(tool_name, &block)
@@ -33,11 +34,11 @@ module Elelem
       tool = tools[name]
       return { error: "unknown tool: #{name}" } unless tool
 
-      missing = (tool[:required] || []) - (args&.keys || [])
+      missing = tool.required - (args&.keys || [])
       return { error: "missing required args: #{missing.join(', ')}" } if missing.any?
 
       @hooks[:before][name].each { |h| h.call(args) }
-      result = tool[:fn].call(args)
+      result = tool.call(args)
       @hooks[:after][name].each { |h| h.call(args, result) }
       result
     rescue => e
@@ -45,16 +46,7 @@ module Elelem
     end
 
     def to_a
-      tools.map do |name, tool|
-        {
-          type: "function",
-          function: {
-            name: name,
-            description: tool[:description],
-            parameters: { type: "object", properties: tool[:params], required: tool[:required] }
-          }
-        }
-      end
+      tools.values.map(&:to_h)
     end
   end
 end
lib/elelem.rb
@@ -14,6 +14,7 @@ require_relative "elelem/mcp"
 require_relative "elelem/net"
 require_relative "elelem/plugins"
 require_relative "elelem/terminal"
+require_relative "elelem/tool"
 require_relative "elelem/toolbox"
 require_relative "elelem/version"
 
elelem.gemspec
@@ -34,8 +34,13 @@ Gem::Specification.new do |spec|
     "lib/elelem/net/openai.rb",
     "lib/elelem/plugins.rb",
     "lib/elelem/plugins/confirm.rb",
+    "lib/elelem/plugins/execute.rb",
+    "lib/elelem/plugins/mcp.rb",
+    "lib/elelem/plugins/read.rb",
     "lib/elelem/plugins/verify.rb",
+    "lib/elelem/plugins/write.rb",
     "lib/elelem/terminal.rb",
+    "lib/elelem/tool.rb",
     "lib/elelem/toolbox.rb",
     "lib/elelem/version.rb",
   ]