Class: RubyLLM::Toolbox::Tools::ReplaceInFiles
- Defined in:
- lib/ruby_llm/toolbox/tools/replace_in_files.rb
Overview
EXEC. Find-and-replace across the files in fs_root that match a glob. Literal by default; set regex: true for a pattern (with backreferences in the replacement). Binary files and ignored directories are skipped, the pattern runs under a ReDoS timeout, and every path is jailed to fs_root. Use dry_run: true to preview the impact without writing.
Constant Summary collapse
- MAX_BYTES =
5 * 1024 * 1024
- MAX_LISTED =
100
Instance Attribute Summary
Attributes inherited from Base
Instance Method Summary collapse
Methods inherited from Base
#call, exec_tool!, exec_tool?, #initialize, #name
Constructor Details
This class inherits a constructor from RubyLLM::Toolbox::Base
Instance Method Details
#execute(pattern:, replacement: "", glob: "**/*", regex: false, ignore_case: false, dry_run: false) ⇒ Object
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/ruby_llm/toolbox/tools/replace_in_files.rb', line 44 def execute(pattern:, replacement: "", glob: "**/*", regex: false, ignore_case: false, dry_run: false) return error("pattern must not be empty", code: :empty_pattern) if pattern.to_s.empty? matcher = build_matcher(pattern, regex, ignore_case) jail = Safety::PathJail.new(config.fs_root) root = File.realpath(config.fs_root) changed = [] total = 0 candidate_files(glob, jail, root).each do |abs, rel| content = File.read(abs) next unless text?(content) count, updated = substitute(content, matcher, replacement.to_s, regex) next if count.zero? total += count changed << [rel, count] File.write(abs, updated) unless dry_run end format_summary(changed, total, dry_run) rescue Safety::PathJail::Jailbreak => e error(e., code: :path_denied) rescue Regexp::TimeoutError error("pattern timed out (possible ReDoS); narrow the pattern", code: :regex_timeout) rescue RegexpError => e error("invalid regular expression: #{e.}", code: :bad_regex) end |