Class: AgentC::Tools::Grep

Inherits:
RubyLLM::Tool
  • Object
show all
Defined in:
lib/agent_c/tools/grep.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(workspace_dir: nil) ⇒ Grep

Returns a new instance of Grep.

Raises:

  • (ArgumentError)


63
64
65
66
# File 'lib/agent_c/tools/grep.rb', line 63

def initialize(workspace_dir: nil, **)
  raise ArgumentError, "workspace_dir is required" unless workspace_dir
  @workspace_dir = workspace_dir
end

Instance Attribute Details

#workspace_dirObject (readonly)

Returns the value of attribute workspace_dir.



62
63
64
# File 'lib/agent_c/tools/grep.rb', line 62

def workspace_dir
  @workspace_dir
end

Instance Method Details

#execute(pattern:, file_pattern: nil, ignore_case: false, context_lines: 0, line_range_start: 1, line_range_end: nil, **params) ⇒ Object



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
110
111
112
113
114
115
116
# File 'lib/agent_c/tools/grep.rb', line 68

def execute(pattern:, file_pattern: nil, ignore_case: false, context_lines: 0, line_range_start: 1, line_range_end: nil, **params)
  if params.any?
    return "The following params were passed but are not allowed: #{params.keys.join(",")}"
  end

  Dir.chdir(workspace_dir) do

    cmd = ["git", "grep", "-n", "--extended-regexp"]  # -n shows line numbers

    cmd << "-i" if ignore_case
    cmd << "-C" << context_lines.to_s if context_lines > 0

    cmd << "-e" << pattern

    if file_pattern
      cmd << "--" << file_pattern
    end


    stdout, stderr, status = Open3.capture3(*cmd)

    if status.success?
      lines = stdout.force_encoding("UTF-8").split("\n")

      # Apply line range (convert to 0-indexed)
      start_idx = [line_range_start - 1, 0].max
      end_idx = line_range_end ? line_range_end - 1 : -1
      lines = lines[start_idx..end_idx] || []

      lines = lines.map { |l| l[0..100]}

      total_lines = lines.length
      max_lines = 300

      if total_lines > max_lines
        limited_content = lines[0...max_lines].join("\n")
        return "Returning #{max_lines} lines out of #{total_lines} total lines:\n\n#{limited_content}"
      else
        return lines.join("\n")
      end
    elsif status.exitstatus == 1
      # Exit status 1 means no matches found
      return "No matches found."
    else
      # Other error
      return "Error: #{stderr}"
    end
  end
end