Class: Brute::Tools::Shell

Inherits:
RubyLLM::Tool
  • Object
show all
Defined in:
lib/brute/tools/shell.rb

Overview

Existing features (ref: opencode bash tool):

  1. Tail-mode truncation — when output exceeds limits, keep the LAST N lines / bytes instead of the first. Command output typically has the important info (errors, summaries) at the end.

  2. Save full output to disk — when truncating, write the complete output to a temp file and include the path in the truncated result so the LLM can use Read with offset/limit to inspect it.

  3. Align limits with universal truncation (2000 lines / 50 KB).

  4. Configurable per-call timeout — accept a timeout parameter from the LLM (defaults to 5 minutes).

  5. Return a plain string instead of a Hash.

Constant Summary collapse

DEFAULT_TIMEOUT =

5 minutes

300

Instance Method Summary collapse

Instance Method Details

#execute(command:, cwd: nil, timeout: nil) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/brute/tools/shell.rb', line 37

def execute(command:, cwd: nil, timeout: nil)
  dir = cwd ? File.expand_path(cwd) : Dir.pwd
  raise "Directory not found: #{dir}" unless File.directory?(dir)

  timeout_secs = timeout || DEFAULT_TIMEOUT
  stdout, stderr, status = nil
  Timeout.timeout(timeout_secs) do
    stdout, stderr, status = Open3.capture3("bash", "-c", command, chdir: dir)
  end

  out = stdout.to_s
  err = stderr.to_s

  # Combine output, preferring tail-mode truncation so errors/summaries at end are preserved
  combined = out
  combined += "\nSTDERR:\n#{err}" unless err.empty?
  combined += "\n[exit code: #{status.exitstatus}]" if status.exitstatus != 0

  Brute::Truncation.truncate(combined, direction: :tail)
rescue Timeout::Error
  "Command timed out after #{timeout_secs}s: #{command}"
end

#nameObject



33
# File 'lib/brute/tools/shell.rb', line 33

def name; "shell"; end