Class: RubyLLM::Toolbox::Base
- Inherits:
-
RubyLLM::Tool
- Object
- RubyLLM::Tool
- RubyLLM::Toolbox::Base
- Defined in:
- lib/ruby_llm/toolbox/base.rb
Overview
Every toolbox tool subclasses this instead of RubyLLM::Tool directly. It adds four things on top of the base ruby_llm DSL:
1. A per-instance config snapshot (overridable at construction).
2. An exec gate: tools marked `exec_tool!` refuse to run unless
config.enable_exec_tools is true.
3. A uniform failure contract: tools return { error:, code: } and never
raise into the harness. (This matches ruby_llm's own convention of
returning { error: ... } for bad arguments.)
4. Token-budgeted output via #truncate.
Success returns are whatever the tool produces (usually a String, or a Hash for structured results). Failures are always { error:, code: }.
Direct Known Subclasses
Tools::ApplyPatch, Tools::BashTool, Tools::Bundle, Tools::Calculator, Tools::CreateDirectory, Tools::CsvRead, Tools::CsvWrite, Tools::DateTime, Tools::DeleteFile, Tools::Diff, Tools::DownloadFile, Tools::EditFile, Tools::GemTool, Tools::GitAdd, Tools::GitBlame, Tools::GitBranch, Tools::GitCheckout, Tools::GitCommit, Tools::GitDiff, Tools::GitGrep, Tools::GitLog, Tools::GitShow, Tools::GitStatus, Tools::Glob, Tools::GrepFiles, Tools::HttpRequest, Tools::JsonQuery, Tools::Lint, Tools::ListDirectory, Tools::MoveFile, Tools::MultiEdit, Tools::ParseRuby, Tools::ProcessKill, Tools::ProcessList, Tools::ProcessOutput, Tools::ProcessStart, Tools::PythonTests, Tools::ReadFile, Tools::ReplaceInFiles, Tools::RunPython, Tools::RunRuby, Tools::RunRust, Tools::RunTests, Tools::TodoWrite, Tools::TomlQuery, Tools::Tree, Tools::WebFetch, Tools::WebSearch, Tools::WriteFile, Tools::YamlQuery
Defined Under Namespace
Classes: UnsafeDenied
Instance Attribute Summary collapse
-
#config ⇒ Object
readonly
Returns the value of attribute config.
Class Method Summary collapse
-
.exec_tool! ⇒ Object
Mark a subclass as part of the dangerous set.
- .exec_tool? ⇒ Boolean
Instance Method Summary collapse
-
#call(args) ⇒ Object
Wraps the base #call to enforce the exec gate and guarantee that no exception ever escapes into the model loop.
-
#initialize(**overrides) ⇒ Base
constructor
A new instance of Base.
-
#name ⇒ Object
ruby_llm derives the tool name from the full class name, which would turn RubyLLM::Toolbox::Tools::ReadFile into an ugly namespaced string.
Constructor Details
Instance Attribute Details
#config ⇒ Object (readonly)
Returns the value of attribute config.
41 42 43 |
# File 'lib/ruby_llm/toolbox/base.rb', line 41 def config @config end |
Class Method Details
.exec_tool! ⇒ Object
Mark a subclass as part of the dangerous set.
27 28 29 |
# File 'lib/ruby_llm/toolbox/base.rb', line 27 def exec_tool! @exec_tool = true end |
.exec_tool? ⇒ Boolean
31 32 33 |
# File 'lib/ruby_llm/toolbox/base.rb', line 31 def exec_tool? @exec_tool == true end |
Instance Method Details
#call(args) ⇒ Object
Wraps the base #call to enforce the exec gate and guarantee that no exception ever escapes into the model loop.
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/ruby_llm/toolbox/base.rb', line 58 def call(args) if self.class.exec_tool? && !config.enable_exec_tools return error( "Exec tools are disabled. Set RubyLLM::Toolbox.config.enable_exec_tools = true " \ "(and an allowlist where relevant) to use #{self.class.name}.", code: :exec_disabled ) end super rescue UnsafeDenied => e error(e., code: :unsafe_denied) rescue StandardError => e error("#{self.class.name} failed: #{e.}", code: :tool_exception) end |
#name ⇒ Object
ruby_llm derives the tool name from the full class name, which would turn RubyLLM::Toolbox::Tools::ReadFile into an ugly namespaced string. Demodulize first so tools get clean names (“read_file”, “bash”, …).
46 47 48 49 50 51 52 53 54 |
# File 'lib/ruby_llm/toolbox/base.rb', line 46 def name @name ||= begin base = self.class.name.to_s.split("::").last.to_s base.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2') .gsub(/([a-z\d])([A-Z])/, '\1_\2') .downcase .delete_suffix("_tool") end end |