Class: SwarmSDK::Tools::TodoWrite

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

Overview

TodoWrite tool for creating and managing structured task lists

This tool helps agents track progress on complex multi-step tasks. Each agent maintains its own independent todo list.

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

removable, removable?, #removable?

Constructor Details

#initialize(agent_name:) ⇒ TodoWrite

Initialize the TodoWrite tool for a specific agent

Parameters:

  • agent_name (Symbol, String)

    The agent identifier



118
119
120
121
# File 'lib/swarm_sdk/tools/todo_write.rb', line 118

def initialize(agent_name:)
  super()
  @agent_name = agent_name.to_sym
end

Class Method Details

.creation_requirementsObject



14
15
16
# File 'lib/swarm_sdk/tools/todo_write.rb', line 14

def creation_requirements
  [:agent_name]
end

Instance Method Details

#execute(todos_json:) ⇒ Object



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/swarm_sdk/tools/todo_write.rb', line 128

def execute(todos_json:)
  # Parse JSON
  todos = begin
    JSON.parse(todos_json)
  rescue JSON::ParserError
    nil
  end

  return validation_error("Invalid JSON format. Please provide a valid JSON array of todo objects.") if todos.nil?

  # Validate todos structure
  unless todos.is_a?(Array)
    return validation_error("todos must be an array of todo objects")
  end

  if todos.empty?
    return validation_error("todos array cannot be empty")
  end

  validated_todos = []
  errors = []

  todos.each_with_index do |todo, index|
    unless todo.is_a?(Hash)
      errors << "Todo at index #{index} must be a hash/object"
      next
    end

    # Convert string keys to symbols for consistency
    todo = todo.transform_keys(&:to_sym) if todo.is_a?(Hash)

    # Validate required fields
    unless todo[:content]
      errors << "Todo at index #{index} missing required field 'content'"
      next
    end

    unless todo[:status]
      errors << "Todo at index #{index} missing required field 'status'"
      next
    end

    unless todo[:activeForm]
      errors << "Todo at index #{index} missing required field 'activeForm'"
      next
    end

    # Validate status values
    valid_statuses = ["pending", "in_progress", "completed"]
    unless valid_statuses.include?(todo[:status].to_s)
      errors << "Todo at index #{index} has invalid status '#{todo[:status]}'. Must be one of: #{valid_statuses.join(", ")}"
      next
    end

    # Validate content and activeForm are non-empty
    if todo[:content].to_s.strip.empty?
      errors << "Todo at index #{index} has empty content"
      next
    end

    if todo[:activeForm].to_s.strip.empty?
      errors << "Todo at index #{index} has empty activeForm"
      next
    end

    validated_todos << {
      content: todo[:content].to_s,
      status: todo[:status].to_s,
      activeForm: todo[:activeForm].to_s,
    }
  end

  return validation_error("TodoWrite failed due to the following issues:\n#{errors.join("\n")}") unless errors.empty?

  # Check that exactly one task is in_progress (with helpful message)
  in_progress_count = validated_todos.count { |t| t[:status] == "in_progress" }
  warning_message = if in_progress_count == 0
    "Warning: No tasks marked as in_progress. You should have exactly ONE task in_progress at a time.\n" \
      "Please mark the task you're currently working on as in_progress.\n\n"
  elsif in_progress_count > 1
    "Warning: Multiple tasks marked as in_progress (#{in_progress_count} tasks).\n" \
      "You should have exactly ONE task in_progress at a time.\n" \
      "Please ensure only the current task is in_progress, others should be pending or completed.\n\n"
  else
    ""
  end

  # Store the validated todos
  Stores::TodoManager.set_todos(@agent_name, validated_todos)

  <<~RESPONSE
    <system-reminder>
    #{warning_message}Your todo list has changed. DO NOT mention this explicitly to the user. Here are the latest contents of your todo list:
    #{validated_todos.map { |t| "- #{t[:content]} (#{t[:status]})" }.join("\n")}
    Keep going with the tasks at hand if applicable.
    </system-reminder>
  RESPONSE
rescue StandardError => e
  "Error managing todos: #{e.class.name} - #{e.message}"
end

#nameObject

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



124
125
126
# File 'lib/swarm_sdk/tools/todo_write.rb', line 124

def name
  "TodoWrite"
end