Class: Rubino::Tools::RubyTool

Inherits:
Base
  • Object
show all
Defined in:
lib/rubino/tools/ruby_tool.rb

Overview

Tool for evaluating Ruby code in a sandboxed context.

The snippet runs in a SEPARATE Ruby process (issue #102) rooted at the workspace, with the project's lib/ and the workspace root prepended to $LOAD_PATH (mirroring ruby -Ilib -I. -e ...). That lets the model require 'my_project/file' and use relative requires against the code it is working on — the original in-process eval ran in the agent's own $LOAD_PATH/cwd, so any such require raised LoadError and the model fell back to shell. A child process also keeps the snippet from crashing or polluting the agent (it can exit, redefine constants, spawn threads, leak globals) without affecting the host.

Instance Attribute Summary

Attributes inherited from Base

#cancel_token, #read_tracker, #stream_chunk, #stream_kind

Instance Method Summary collapse

Methods inherited from Base

#cancellation_requested?, #config_key, #display_name, #emit_chunk, #mcp?, #risky?, #to_tool_definition, workspace_root, workspace_roots

Instance Method Details

#call(arguments) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
# File 'lib/rubino/tools/ruby_tool.rb', line 48

def call(arguments)
  # Fail-closed (tools.sandbox.require): refuse before spawning when the
  # operator requires the OS jail but no mechanism can enforce it — the
  # same gate the shell consults, so ruby cannot bypass it (#544 / HOLE 2).
  if (refusal = Security::Sandbox.refusal_reason)
    return "Error: #{refusal}"
  end

  code = arguments["code"] || arguments[:code]
  evaluate(code)
end

#descriptionObject



23
24
25
26
27
28
29
# File 'lib/rubino/tools/ruby_tool.rb', line 23

def description
  "Evaluate Ruby code and return the result. " \
    "Useful for calculations, data transformations, and scripting tasks. " \
    "Runs in a separate Ruby process rooted at the workspace, with the " \
    "project's lib/ (and the workspace root) on the load path, so " \
    "`require 'my_project/file'` and relative requires of project code work."
end

#input_schemaObject



31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/rubino/tools/ruby_tool.rb', line 31

def input_schema
  {
    type: "object",
    properties: {
      code: {
        type: "string",
        description: "The Ruby code to evaluate"
      }
    },
    required: %w[code]
  }
end

#nameObject



19
20
21
# File 'lib/rubino/tools/ruby_tool.rb', line 19

def name
  "ruby"
end

#risk_levelObject



44
45
46
# File 'lib/rubino/tools/ruby_tool.rb', line 44

def risk_level
  :medium
end