Class: Legion::CLI::Chat::Tools::WorkerStatus

Inherits:
Tools::Base
  • Object
show all
Defined in:
lib/legion/cli/chat/tools/worker_status.rb

Constant Summary collapse

DEFAULT_PORT =
4567
DEFAULT_HOST =
'127.0.0.1'

Class Method Summary collapse

Methods inherited from Tools::Base

deferred, deferred?, description, error_response, extension, handle_exception, input_schema, log, mcp_category, mcp_tier, runner, sticky, tags, text_response, tool_name, trigger_words

Class Method Details

.api_get(path) ⇒ Object



117
118
119
120
121
122
123
124
# File 'lib/legion/cli/chat/tools/worker_status.rb', line 117

def self.api_get(path)
  uri = URI("http://#{DEFAULT_HOST}:#{api_port}#{path}")
  http = Net::HTTP.new(uri.host, uri.port)
  http.open_timeout = 2
  http.read_timeout = 5
  response = http.get(uri.request_uri)
  ::JSON.parse(response.body, symbolize_names: true)
end

.api_portObject



126
127
128
129
130
131
132
# File 'lib/legion/cli/chat/tools/worker_status.rb', line 126

def self.api_port
  return DEFAULT_PORT unless defined?(Legion::Settings)

  Legion::Settings[:api]&.dig(:port) || DEFAULT_PORT
rescue StandardError
  DEFAULT_PORT
end

.call(action: 'list', worker_id: nil, status_filter: nil) ⇒ Object



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/legion/cli/chat/tools/worker_status.rb', line 34

def self.call(action: 'list', worker_id: nil, status_filter: nil)
  case action.to_s
  when 'show'
    return 'worker_id is required for the "show" action.' unless worker_id

    handle_show(worker_id.strip)
  when 'health'
    handle_health
  else
    handle_list(status_filter)
  end
rescue Errno::ECONNREFUSED
  'Legion daemon not running (cannot reach workers API).'
rescue StandardError => e
  Legion::Logging.warn("WorkerStatus#execute failed: #{e.message}") if defined?(Legion::Logging)
  "Error fetching worker data: #{e.message}"
end

.display_fields(worker) ⇒ Object



105
106
107
108
109
110
# File 'lib/legion/cli/chat/tools/worker_status.rb', line 105

def self.display_fields(worker)
  %i[name lifecycle_state risk_tier team extension_name owner_msid health_status
     created_at].filter_map do |key|
    [key, worker[key]] if worker[key]
  end
end

.extract_collection(data) ⇒ Object



112
113
114
115
# File 'lib/legion/cli/chat/tools/worker_status.rb', line 112

def self.extract_collection(data)
  entries = data[:data] || data
  entries.is_a?(Array) ? entries : []
end

.handle_healthObject



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/legion/cli/chat/tools/worker_status.rb', line 80

def self.handle_health
  data = api_get('/api/workers?health_status=unhealthy')
  unhealthy = extract_collection(data)

  data_all = api_get('/api/workers')
  all_workers = extract_collection(data_all)

  active = all_workers.count { |w| w[:lifecycle_state] == 'active' }
  paused = all_workers.count { |w| w[:lifecycle_state] == 'paused' }

  lines = ["Worker Health Summary:\n"]
  lines << "  Total:     #{all_workers.size}"
  lines << "  Active:    #{active}"
  lines << "  Paused:    #{paused}"
  lines << "  Unhealthy: #{unhealthy.size}"

  if unhealthy.any?
    lines << "\n  Unhealthy workers:"
    unhealthy.each do |w|
      lines << "    - #{w[:worker_id] || w[:id]}: #{w[:name] || 'unnamed'}"
    end
  end
  lines.join("\n")
end

.handle_list(status_filter) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/legion/cli/chat/tools/worker_status.rb', line 52

def self.handle_list(status_filter)
  path = '/api/workers'
  path += "?lifecycle_state=#{status_filter}" if status_filter && !status_filter.strip.empty?
  data = api_get(path)
  workers = extract_collection(data)
  return 'No digital workers found.' if workers.empty?

  lines = ["Digital Workers (#{workers.size}):\n"]
  workers.each do |w|
    id = w[:worker_id] || w[:id]
    name = w[:name] || 'unnamed'
    state = w[:lifecycle_state] || 'unknown'
    tier = w[:risk_tier] || '-'
    lines << "  #{id} | #{name} | #{state} | risk: #{tier}"
  end
  lines.join("\n")
end

.handle_show(worker_id) ⇒ Object



70
71
72
73
74
75
76
77
78
# File 'lib/legion/cli/chat/tools/worker_status.rb', line 70

def self.handle_show(worker_id)
  data = api_get("/api/workers/#{worker_id}")
  w = data[:data] || data
  return "Worker #{worker_id} not found." if w[:error]

  lines = ["Worker: #{worker_id}\n"]
  display_fields(w).each { |key, val| lines << "  #{key}: #{val}" }
  lines.join("\n")
end