Module: Roast::Tools::SearchFile

Extended by:
SearchFile
Included in:
SearchFile
Defined in:
lib/roast/tools/search_file.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object

Add this method to be included in other classes



10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/roast/tools/search_file.rb', line 10

def included(base)
  base.class_eval do
    function(
      :search_for_file,
      "Search for a file in the project using a glob pattern.",
      glob_pattern: { type: "string", description: "A glob pattern to search for. Example: 'test/**/*_test.rb'" },
      path: { type: "string", description: "path to search from", default: "." },
    ) do |params|
      Roast::Tools::SearchFile.call(params[:glob_pattern], params[:path]).tap do |result|
        Roast::Helpers::Logger.debug(result) if ENV["DEBUG"]
      end
    end
  end
end

Instance Method Details

#call(glob_pattern, path = ".") ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/roast/tools/search_file.rb', line 26

def call(glob_pattern, path = ".")
  raise ArgumentError, "glob_pattern is required" if glob_pattern.nil?

  path ||= "."

  unless File.exist?(path)
    Roast::Helpers::Logger.error("Path does not exist: #{path}")
    return "Path does not exist: #{path}"
  end

  # prefix **/ to the glob pattern if it doesn't already have it
  glob_pattern = "**/#{glob_pattern}" unless glob_pattern.start_with?("**")

  Roast::Helpers::Logger.info("🔍 Searching for: '#{glob_pattern}' in '#{File.expand_path(path)}'\n")
  search_for(glob_pattern, path).then do |results|
    return "No results found for #{glob_pattern} in #{path}" if results.empty?
    return read_contents(File.join(path, results.first)) if results.size == 1

    results.map { |result| File.join(path, result) }.join("\n") # purposely give the AI list of actual paths so that it can read without searching first
  end
rescue StandardError => e
  "Error searching for '#{glob_pattern}' in '#{path}': #{e.message}".tap do |error_message|
    Roast::Helpers::Logger.error(error_message + "\n")
    Roast::Helpers::Logger.debug(e.backtrace.join("\n") + "\n") if ENV["DEBUG"]
  end
end

#read_contents(path) ⇒ Object



53
54
55
56
57
58
59
60
61
# File 'lib/roast/tools/search_file.rb', line 53

def read_contents(path)
  contents = File.read(path)
  token_count = contents.size / 4
  if token_count > 25_000
    path
  else
    contents
  end
end

#search_for(pattern, path) ⇒ Object



63
64
65
# File 'lib/roast/tools/search_file.rb', line 63

def search_for(pattern, path)
  Dir.glob(pattern, base: path)
end