Class: Tools::Edit

Inherits:
Base
  • Object
show all
Defined in:
lib/tools/edit.rb

Overview

Performs surgical text replacement with uniqueness constraint. Finds old_text in the file (must match exactly one location), replaces with new_text, and returns a unified diff. Falls back to whitespace-normalized fuzzy matching when exact match fails.

Normalizes BOM and CRLF line endings for matching, restoring them after the edit. Rejects ambiguous edits where old_text matches zero or multiple locations.

Examples:

Replacing a method body

tool.execute("path" => "app.rb",
             "old_text" => "def greet\n  'hi'\nend",
             "new_text" => "def greet\n  'hello'\nend")
# => "--- app.rb\n+++ app.rb\n@@ -1,3 +1,3 @@\n ..."

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

schema, truncation_threshold

Constructor Details

#initialize(shell_session: nil) ⇒ Edit

Returns a new instance of Edit.

Parameters:

  • shell_session (ShellSession, nil) (defaults to: nil)

    provides working directory for resolving relative paths



36
37
38
# File 'lib/tools/edit.rb', line 36

def initialize(shell_session: nil, **)
  @working_directory = shell_session&.pwd
end

Class Method Details

.descriptionObject



21
# File 'lib/tools/edit.rb', line 21

def self.description = "Replace text in a file."

.input_schemaObject



23
24
25
26
27
28
29
30
31
32
33
# File 'lib/tools/edit.rb', line 23

def self.input_schema
  {
    type: "object",
    properties: {
      path: {type: "string", description: "Relative paths resolve against working directory."},
      old_text: {type: "string", description: "Must match exactly one location. Include surrounding lines for uniqueness."},
      new_text: {type: "string", description: "Empty string to delete."}
    },
    required: %w[path old_text new_text]
  }
end

.tool_nameObject



19
# File 'lib/tools/edit.rb', line 19

def self.tool_name = "edit_file"

Instance Method Details

#execute(input) ⇒ String, Hash

Parameters:

  • input (Hash<String, Object>)

    string-keyed hash from the Anthropic API

Returns:

  • (String)

    unified diff showing the change

  • (Hash)

    with :error key on failure



43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/tools/edit.rb', line 43

def execute(input)
  path, old_text, new_text = extract_params(input)
  return {error: "Path cannot be blank"} if path.empty?
  return {error: "old_text cannot be blank"} if old_text.empty?

  path = resolve_path(path)

  error = validate_file(path)
  return error if error

  edit_file(path, old_text, new_text)
end