legionio 1.4.51 → 1.4.52

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1a711d9a3b6b942849185b3ec8eb16e4ecaa8b054c4c157799140f23d0bfc5f9
4
- data.tar.gz: 64f138151ce16a625846a982fe66ab03d3e6403aba144509a62218a34c75fbae
3
+ metadata.gz: '08a5e7057699e03532d0815dc93823ed321ea0f5767915033b10ca5aa75afb40'
4
+ data.tar.gz: bf1311709df94b55812ba9e53360b456b3b80cd1d1bed0450fe7a1b33d5e04c2
5
5
  SHA512:
6
- metadata.gz: 9acd3652f07de505bfa8b3262c20b65715668eb7a2a012dcb1a222a27cf0b94d91facef2bd961468ee93cab3f89e5b06f100a6bf32eaf8dd2368da5c3979a675
7
- data.tar.gz: ebd3a23ee70a99b2e86d709c931221262656f3eb3be4f638c20e4f8c24f7f8ad08c9dd0d54928be0f3f781725380ea298a13f93da05771a19b71fdd452333f7b
6
+ metadata.gz: c44772264edc55cf816923a596d5092f43394dcd292884eadbddc0b88d09e25cb17a75cab374ee3dfffe046e81edd142728bc4647f2ab2c6a3edcc67f1729bc6
7
+ data.tar.gz: '096080ad2b1b2a9103d262ba2547c9442249a08505bf86b60a88927820a00528ba2cc6fed53e9ee9f330202631834b14dc017df394215abdddfaff38d4851887'
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Legion Changelog
2
2
 
3
+ ## [1.4.52] - 2026-03-17
4
+
5
+ ### Added
6
+ - `legion dashboard`: TUI operational dashboard with auto-refresh polling
7
+ - `Dashboard::DataFetcher`: polls REST API for workers, health, and recent events
8
+ - `Dashboard::Renderer`: terminal-based dashboard rendering with sections for workers, events, health
9
+ - Configurable API URL (`--url`) and refresh interval (`--refresh`)
10
+
3
11
  ## [1.4.51] - 2026-03-17
4
12
 
5
13
  ### Added
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'net/http'
4
+
5
+ module Legion
6
+ module CLI
7
+ module Dashboard
8
+ class DataFetcher
9
+ def initialize(base_url: 'http://localhost:4567')
10
+ @base_url = base_url
11
+ end
12
+
13
+ def workers
14
+ fetch('/api/workers') || []
15
+ end
16
+
17
+ def health
18
+ fetch('/api/health') || {}
19
+ end
20
+
21
+ def recent_events(limit: 10)
22
+ fetch("/api/events/recent?limit=#{limit}") || []
23
+ end
24
+
25
+ def summary
26
+ {
27
+ workers: workers,
28
+ health: health,
29
+ events: recent_events,
30
+ fetched_at: Time.now
31
+ }
32
+ end
33
+
34
+ private
35
+
36
+ def fetch(path)
37
+ uri = URI("#{@base_url}#{path}")
38
+ response = Net::HTTP.get_response(uri)
39
+ return nil unless response.is_a?(Net::HTTPSuccess)
40
+
41
+ Legion::JSON.load(response.body)
42
+ rescue StandardError
43
+ nil
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module CLI
5
+ module Dashboard
6
+ class Renderer
7
+ def initialize(width: nil)
8
+ @width = width || default_width
9
+ end
10
+
11
+ def render(data)
12
+ lines = []
13
+ lines << header_line(data)
14
+ lines << separator
15
+ lines << workers_section(data[:workers] || [])
16
+ lines << separator
17
+ lines << events_section(data[:events] || [])
18
+ lines << separator
19
+ lines << health_section(data[:health] || {})
20
+ lines << footer_line(data[:fetched_at])
21
+ lines.flatten.join("\n")
22
+ end
23
+
24
+ private
25
+
26
+ def default_width
27
+ defined?(TTY::Screen) ? TTY::Screen.width : 80
28
+ end
29
+
30
+ def header_line(data)
31
+ workers = data[:workers]&.size || 0
32
+ "Legion Dashboard | Workers: #{workers} | #{Time.now.strftime('%H:%M:%S')}"
33
+ end
34
+
35
+ def separator
36
+ '-' * @width
37
+ end
38
+
39
+ def workers_section(workers)
40
+ lines = ['Active Workers:']
41
+ workers.first(5).each do |w|
42
+ id = w[:worker_id] || w[:id] || 'unknown'
43
+ status = w[:status] || w[:lifecycle_state] || 'unknown'
44
+ lines << " #{id.to_s.ljust(20)} #{status.to_s.ljust(10)}"
45
+ end
46
+ lines << ' (none)' if workers.empty?
47
+ lines
48
+ end
49
+
50
+ def events_section(events)
51
+ lines = ['Recent Events:']
52
+ events.first(5).each do |e|
53
+ time = e[:timestamp] || e[:created_at] || ''
54
+ name = e[:event_name] || e[:name] || ''
55
+ lines << " #{time.to_s[11..18]} #{name}"
56
+ end
57
+ lines << ' (none)' if events.empty?
58
+ lines
59
+ end
60
+
61
+ def health_section(health)
62
+ components = health.map { |k, v| "#{k}: #{v}" }.join(' | ')
63
+ "Health: #{components.empty? ? 'unknown' : components}"
64
+ end
65
+
66
+ def footer_line(fetched_at)
67
+ "Last updated: #{fetched_at&.strftime('%H:%M:%S') || 'never'} | Press q to quit, r to refresh"
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'thor'
4
+
5
+ module Legion
6
+ module CLI
7
+ class DashboardCommand < Thor
8
+ namespace 'dashboard'
9
+
10
+ desc 'start', 'Launch the TUI dashboard'
11
+ option :url, type: :string, default: 'http://localhost:4567', desc: 'API base URL'
12
+ option :refresh, type: :numeric, default: 2, desc: 'Refresh interval in seconds'
13
+ def start
14
+ require 'legion/cli/dashboard/data_fetcher'
15
+ require 'legion/cli/dashboard/renderer'
16
+
17
+ fetcher = Dashboard::DataFetcher.new(base_url: options[:url])
18
+ renderer = Dashboard::Renderer.new
19
+
20
+ puts 'Starting dashboard... (press q to quit)'
21
+ loop do
22
+ system('clear') || system('cls')
23
+ data = fetcher.summary
24
+ puts renderer.render(data)
25
+
26
+ ready = $stdin.wait_readable(options[:refresh])
27
+ if ready
28
+ input = $stdin.getc
29
+ break if input == 'q'
30
+ end
31
+ rescue Interrupt
32
+ break
33
+ end
34
+ puts 'Dashboard stopped.'
35
+ end
36
+
37
+ default_task :start
38
+ end
39
+ end
40
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Legion
4
- VERSION = '1.4.51'
4
+ VERSION = '1.4.52'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: legionio
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.51
4
+ version: 1.4.52
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity
@@ -401,6 +401,9 @@ files:
401
401
  - lib/legion/cli/connection.rb
402
402
  - lib/legion/cli/cost/data_client.rb
403
403
  - lib/legion/cli/cost_command.rb
404
+ - lib/legion/cli/dashboard/data_fetcher.rb
405
+ - lib/legion/cli/dashboard/renderer.rb
406
+ - lib/legion/cli/dashboard_command.rb
404
407
  - lib/legion/cli/doctor/bundle_check.rb
405
408
  - lib/legion/cli/doctor/cache_check.rb
406
409
  - lib/legion/cli/doctor/config_check.rb