Class: SwarmSDK::Tools::Write

Inherits:
Base
  • Object
show all
Includes:
PathResolver
Defined in:
lib/swarm_sdk/tools/write.rb

Overview

Write tool for writing content to files

Creates new files or overwrites existing files. Enforces read-before-write rule for existing files. Includes validation and usage guidelines via system reminders.

Instance Attribute Summary

Attributes included from PathResolver

#agent_name, #directory

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

removable, removable?, #removable?

Constructor Details

#initialize(agent_name:, directory:) ⇒ Write

Initialize the Write tool for a specific agent



50
51
52
53
# File 'lib/swarm_sdk/tools/write.rb', line 50

def initialize(agent_name:, directory:)
  super()
  initialize_agent_context(agent_name: agent_name, directory: directory)
end

Class Method Details

.creation_requirementsObject



15
16
17
# File 'lib/swarm_sdk/tools/write.rb', line 15

def creation_requirements
  [:agent_name, :directory]
end

Instance Method Details

#execute(file_path:, content:) ⇒ Object



60
61
62
63
64
65
66
67
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
# File 'lib/swarm_sdk/tools/write.rb', line 60

def execute(file_path:, content:)
  # Validate inputs
  return validation_error("file_path is required") if file_path.nil? || file_path.to_s.strip.empty?
  return validation_error("content is required") if content.nil?

  # CRITICAL: Resolve path against agent directory
  resolved_path = resolve_path(file_path)

  # Check if file already exists (use resolved path)
  file_exists = File.exist?(resolved_path)

  # Enforce read-before-write for existing files (use resolved path)
  if file_exists && !Stores::ReadTracker.file_read?(@agent_name, resolved_path)
    return validation_error(
      "Cannot write to existing file without reading it first. " \
        "You must use the Read tool on '#{file_path}' before overwriting it. " \
        "This ensures you have context about the file's current contents.",
    )
  end

  # Create parent directory if it doesn't exist (use resolved path)
  parent_dir = File.dirname(resolved_path)
  FileUtils.mkdir_p(parent_dir) unless File.directory?(parent_dir)

  # Write the file (use resolved path)
  File.write(resolved_path, content, encoding: "UTF-8")

  # Build success message
  byte_size = content.bytesize
  line_count = content.lines.count
  action = file_exists ? "overwrote" : "created"

  message = "Successfully #{action} file: #{file_path} (#{line_count} lines, #{byte_size} bytes)"

  # Add system reminder for overwritten files
  if file_exists
    reminder = "<system-reminder>You overwrote an existing file. Make sure this was intentional and that you read the file first if you needed to preserve any content.</system-reminder>"
    "#{message}\n\n#{reminder}"
  else
    message
  end
rescue Errno::EACCES
  error("Permission denied: Cannot write to file '#{file_path}'")
rescue Errno::EISDIR
  error("Path is a directory, not a file.")
rescue Errno::ENOENT => e
  error("Failed to create parent directory: #{e.message}")
rescue StandardError => e
  error("Unexpected error writing file: #{e.class.name} - #{e.message}")
end

#nameObject

Override name to return simple "Write" instead of full class path



56
57
58
# File 'lib/swarm_sdk/tools/write.rb', line 56

def name
  "Write"
end