Class: Tidewave::Tools::ProjectEval

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

Constant Summary collapse

DESCRIPTION =
<<~DESCRIPTION.freeze
  Evaluates Ruby code in the context of the project.

  The current Ruby version is: #{RUBY_VERSION}

  Use this tool every time you need to evaluate Ruby code,
  including to test the behaviour of a function or to debug
  something. The tool also returns anything written to standard
  output. DO NOT use shell tools to evaluate Ruby code.
DESCRIPTION
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
      <<~OUTPUT
        STDOUT:

        #{stdout}

        STDERR:

        #{stderr}

        Result:

        #{result}
      OUTPUT
    end
  ensure
    $stdout = original_stdout
    $stderr = original_stderr
  end
end

#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