Class: Tidewave::Tools::ProjectEval

Inherits:
Tidewave::Tool show all
Defined in:
lib/tidewave/tools/project_eval.rb

Constant Summary collapse

DESCRIPTION =
"Evaluates Ruby code in the context of the project.\n\nThe current Ruby version is: \#{RUBY_VERSION}\n\nUse this tool every time you need to evaluate Ruby code,\nincluding to test the behaviour of a function or to debug\nsomething. The tool also returns anything written to standard\noutput. DO NOT use shell tools to evaluate Ruby code.\n".freeze
DEFAULT_TIMEOUT =
30_000

Instance Method Summary collapse

Methods inherited from Tidewave::Tool

descendants, inherited, #initialize, #validate_and_call

Constructor Details

This class inherits a constructor from Tidewave::Tool

Instance Method Details

#call(arguments_hash) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/tidewave/tools/project_eval.rb', line 51

def call(arguments_hash)
  code = arguments_hash.fetch("code")
  arguments = arguments_hash.fetch("arguments", [])
  timeout = arguments_hash.fetch("timeout", DEFAULT_TIMEOUT)
  json = arguments_hash.fetch("json", false)

  original_stdout = $stdout
  original_stderr = $stderr

  stdout_capture = StringIO.new
  stderr_capture = StringIO.new
  $stdout = stdout_capture
  $stderr = stderr_capture

  begin
    timeout_seconds = timeout / 1000.0

    success, result = begin
      Timeout.timeout(timeout_seconds) do
        [ true, eval(code, eval_binding(arguments)) ]
      end
    rescue Timeout::Error
      [ false, "Timeout::Error: Evaluation timed out after #{timeout} milliseconds." ]
    rescue => e
      [ false, e.full_message ]
    end

    stdout = stdout_capture.string
    stderr = stderr_capture.string

    if json
      JSON.generate({
        "result" => result,
        "success" => success,
        "stdout" => stdout,
        "stderr" => stderr
      })
    elsif stdout.empty? && stderr.empty?
      result.to_s
    else
      "        STDOUT:\n\n        \#{stdout}\n\n        STDERR:\n\n        \#{stderr}\n\n        Result:\n\n        \#{result}\n      OUTPUT\n    end\n  ensure\n    $stdout = original_stdout\n    $stderr = original_stderr\n  end\nend\n"

#definitionObject



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/tidewave/tools/project_eval.rb', line 21

def definition
  {
    "name" => "project_eval",
    "description" => DESCRIPTION,
    "inputSchema" => {
      "type" => "object",
      "properties" => {
        "arguments" => {
          "description" => "The arguments to pass to evaluation. They are available inside the evaluated code as `arguments`.",
          "items" => {},
          "type" => "array"
        },
        "code" => {
          "description" => "The Ruby code to evaluate",
          "type" => "string",
          "minLength" => 1
        },
        "timeout" => {
          "description" => "The timeout in milliseconds. If the evaluation takes longer than this, it will be terminated. Defaults to 30000 (30 seconds).",
          "type" => "integer",
          "not" => {
            "type" => "null"
          }
        }
      },
      "required" => [ "code" ]
    }
  }
end