Class: EnhanceSwarm::AgentCommunicator

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
lib/enhance_swarm/agent_communicator.rb

Constant Summary collapse

COMMUNICATION_DIR =
'.enhance_swarm/communication'
MESSAGE_FILE_PATTERN =
'agent_*.json'
USER_RESPONSE_FILE =
'user_responses.json'
PROMPT_TIMEOUT =

2 minutes for user response

120

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeAgentCommunicator

Returns a new instance of AgentCommunicator.



17
18
19
20
21
22
23
24
25
# File 'lib/enhance_swarm/agent_communicator.rb', line 17

def initialize
  @communication_dir = File.join(Dir.pwd, COMMUNICATION_DIR)
  @user_responses = {}
  @pending_messages = {}
  @monitoring_active = false
  @monitoring_thread = nil
  ensure_communication_directory
  load_existing_responses
end

Class Method Details

.agent_decision(*args) ⇒ Object



455
456
457
# File 'lib/enhance_swarm/agent_communicator.rb', line 455

def agent_decision(*args)
  instance.agent_decision(*args)
end

.agent_message(*args) ⇒ Object



439
440
441
# File 'lib/enhance_swarm/agent_communicator.rb', line 439

def agent_message(*args)
  instance.agent_message(*args)
end

.agent_progress(*args) ⇒ Object



451
452
453
# File 'lib/enhance_swarm/agent_communicator.rb', line 451

def agent_progress(*args)
  instance.agent_progress(*args)
end

.agent_question(*args) ⇒ Object



443
444
445
# File 'lib/enhance_swarm/agent_communicator.rb', line 443

def agent_question(*args)
  instance.agent_question(*args)
end

.agent_status(*args) ⇒ Object



447
448
449
# File 'lib/enhance_swarm/agent_communicator.rb', line 447

def agent_status(*args)
  instance.agent_status(*args)
end

.instanceObject



435
436
437
# File 'lib/enhance_swarm/agent_communicator.rb', line 435

def instance
  @instance ||= new
end

Instance Method Details

#agent_decision(agent_id, decision_prompt, options_list, default = nil) ⇒ Object

Agent requests user decision



104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/enhance_swarm/agent_communicator.rb', line 104

def agent_decision(agent_id, decision_prompt, options_list, default = nil)
  agent_message(
    agent_id,
    :decision,
    decision_prompt,
    {
      requires_response: true,
      quick_actions: options_list,
      immediate_prompt: true,
      priority: :high,
      context: { default: default }
    }
  )
end

#agent_get_response(message_id, timeout = PROMPT_TIMEOUT) ⇒ Object

Check for agent response to user input



153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/enhance_swarm/agent_communicator.rb', line 153

def agent_get_response(message_id, timeout = PROMPT_TIMEOUT)
  start_time = Time.now
  
  while Time.now - start_time < timeout
    response_file = File.join(@communication_dir, "response_#{message_id}.json")
    
    if File.exist?(response_file)
      response_data = JSON.parse(File.read(response_file))
      File.delete(response_file) # Cleanup
      return response_data['response']
    end
    
    sleep(1)
  end
  
  nil # Timeout
end

#agent_message(agent_id, message_type, content, options = {}) ⇒ Object

Agent sends a message/question to user



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/enhance_swarm/agent_communicator.rb', line 28

def agent_message(agent_id, message_type, content, options = {})
  message = {
    id: generate_message_id(agent_id),
    agent_id: agent_id,
    role: options[:role] || extract_role_from_id(agent_id),
    type: message_type,
    content: content,
    timestamp: Time.now.iso8601,
    priority: options[:priority] || :medium,
    requires_response: options[:requires_response] || false,
    timeout: options[:timeout] || PROMPT_TIMEOUT,
    quick_actions: options[:quick_actions] || [],
    context: options[:context] || {}
  }

  save_message(message)
  
  if message[:requires_response]
    @pending_messages[message[:id]] = message
    prompt_user_for_response(message) if options[:immediate_prompt]
  end

  # Notify user through notification system
  notify_user_of_message(message)
  
  message[:id]
end

#agent_progress(agent_id, progress_message, percentage = nil, eta = nil) ⇒ Object

Agent reports progress



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/enhance_swarm/agent_communicator.rb', line 87

def agent_progress(agent_id, progress_message, percentage = nil, eta = nil)
  agent_message(
    agent_id,
    :progress,
    progress_message,
    {
      requires_response: false,
      priority: :low,
      context: {
        percentage: percentage,
        eta: eta&.iso8601
      }
    }
  )
end

#agent_question(agent_id, question, quick_actions = [], options = {}) ⇒ Object

Agent asks a quick question requiring user response



57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/enhance_swarm/agent_communicator.rb', line 57

def agent_question(agent_id, question, quick_actions = [], options = {})
  agent_message(
    agent_id,
    :question,
    question,
    {
      requires_response: true,
      quick_actions: quick_actions,
      immediate_prompt: options[:immediate_prompt] || false,
      priority: options[:priority] || :high,
      **options
    }
  )
end

#agent_status(agent_id, status, details = {}) ⇒ Object

Agent provides status update



73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/enhance_swarm/agent_communicator.rb', line 73

def agent_status(agent_id, status, details = {})
  agent_message(
    agent_id,
    :status,
    status,
    {
      requires_response: false,
      priority: :low,
      context: details
    }
  )
end

#cleanup_old_messages(days_old = 7) ⇒ Object

Clean up old messages



245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
# File 'lib/enhance_swarm/agent_communicator.rb', line 245

def cleanup_old_messages(days_old = 7)
  cutoff = Time.now - (days_old * 24 * 60 * 60)
  
  Dir.glob(File.join(@communication_dir, MESSAGE_FILE_PATTERN)).each do |file|
    begin
      message = JSON.parse(File.read(file))
      message_time = Time.parse(message['timestamp'])
      
      if message_time < cutoff
        File.delete(file)
      end
    rescue
      # Delete malformed files
      File.delete(file)
    end
  end
end

#interactive_response_modeObject

CLI: Interactive response mode



205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
# File 'lib/enhance_swarm/agent_communicator.rb', line 205

def interactive_response_mode
  pending = pending_messages
  
  if pending.empty?
    puts "No pending messages".colorize(:yellow)
    return
  end
  
  puts "\nšŸ’¬ Interactive Agent Communication".colorize(:blue)
  
  pending.each_with_index do |message, index|
    puts "\n#{'-' * 60}".colorize(:light_black)
    show_message_detail(message, index + 1)
    
    if message[:quick_actions].any?
      puts "\nQuick actions:".colorize(:yellow)
      message[:quick_actions].each_with_index do |action, i|
        puts "  #{i + 1}. #{action}"
      end
      puts "  c. Custom response"
    end
    
    print "\nYour response: ".colorize(:blue)
    response = $stdin.gets&.chomp
    
    next if response.nil? || response.empty?
    
    # Handle quick action selection
    if message[:quick_actions].any? && response.match?(/^\d+$/)
      action_index = response.to_i - 1
      if action_index >= 0 && action_index < message[:quick_actions].length
        response = message[:quick_actions][action_index]
      end
    end
    
    user_respond(message[:id], response)
  end
end

#pending_messagesObject

Get pending messages for user



142
143
144
# File 'lib/enhance_swarm/agent_communicator.rb', line 142

def pending_messages
  @pending_messages.values.sort_by { |msg| msg[:timestamp] }
end

#recent_messages(limit = 10) ⇒ Object

Get recent messages (responded + pending)



147
148
149
150
# File 'lib/enhance_swarm/agent_communicator.rb', line 147

def recent_messages(limit = 10)
  all_messages = load_all_messages
  all_messages.sort_by { |msg| msg[:timestamp] }.last(limit)
end

#show_pending_messagesObject

CLI: Show pending messages



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/enhance_swarm/agent_communicator.rb', line 188

def show_pending_messages
  pending = pending_messages
  
  if pending.empty?
    puts "No pending messages from agents".colorize(:yellow)
    return
  end
  
  puts "\nšŸ’¬ Pending Agent Messages:".colorize(:blue)
  pending.each_with_index do |message, index|
    show_message_summary(message, index + 1)
  end
  
  puts "\nUse 'enhance-swarm communicate --respond <id> <response>' to reply".colorize(:light_black)
end

#start_monitoringObject

Start monitoring for user responses (CLI integration)



172
173
174
175
176
177
178
179
# File 'lib/enhance_swarm/agent_communicator.rb', line 172

def start_monitoring
  return if @monitoring_active
  
  @monitoring_active = true
  @monitoring_thread = Thread.new do
    monitor_for_pending_messages
  end
end

#stop_monitoringObject



181
182
183
184
185
# File 'lib/enhance_swarm/agent_communicator.rb', line 181

def stop_monitoring
  @monitoring_active = false
  @monitoring_thread&.kill
  @monitoring_thread = nil
end

#user_respond(message_id, response) ⇒ Object

User responds to a pending message



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/enhance_swarm/agent_communicator.rb', line 120

def user_respond(message_id, response)
  if @pending_messages[message_id]
    @user_responses[message_id] = {
      response: response,
      timestamp: Time.now.iso8601
    }
    
    save_user_responses
    @pending_messages.delete(message_id)
    
    # Notify agent via file system
    create_response_file(message_id, response)
    
    puts "āœ… Response sent to agent".colorize(:green)
    true
  else
    puts "āŒ Message ID not found or already responded".colorize(:red)
    false
  end
end