Class: Legion::CLI::Chat::Tools::ProviderHealth
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
.call(provider: nil) ⇒ Object
26
27
28
29
30
31
32
33
34
35
36
37
|
# File 'lib/legion/cli/chat/tools/provider_health.rb', line 26
def self.call(provider: nil)
return 'LLM provider inventory not available.' unless provider_stats_available?
if provider
format_detail(provider.strip)
else
format_report
end
rescue StandardError => e
Legion::Logging.warn("ProviderHealth#execute failed: #{e.message}") if defined?(Legion::Logging)
"Error checking provider health: #{e.message}"
end
|
64
65
66
67
68
|
# File 'lib/legion/cli/chat/tools/provider_health.rb', line 64
def self.format_circuit_summary(summary)
format(' Circuits: %<closed>d closed, %<open>d open, %<half>d half-open (of %<total>d)',
closed: summary[:closed], open: summary[:open],
half: summary[:half_open], total: summary[:total])
end
|
52
53
54
55
56
57
58
59
60
61
62
|
# File 'lib/legion/cli/chat/tools/provider_health.rb', line 52
def self.format_detail(provider)
entry = provider_detail(provider)
return "Router not available: #{entry[:error]}" if entry[:error]
return "Provider not found: #{provider}" if entry.empty?
lines = ["Provider: #{entry[:provider]}\n"]
lines << " Circuit: #{entry[:circuit]}"
lines << " Healthy: #{entry[:healthy] ? 'YES' : 'NO'}"
lines << " Adjustment: #{entry[:adjustment]}"
lines.join("\n")
end
|
.format_entry(entry) ⇒ Object
70
71
72
73
74
75
76
77
78
|
# File 'lib/legion/cli/chat/tools/provider_health.rb', line 70
def self.format_entry(entry)
icon = entry[:healthy] ? '+' : '!'
suffix = +''
suffix << " offerings=#{entry[:offerings]}" if entry.key?(:offerings)
suffix << " models=#{entry[:models].length}" if entry[:models].respond_to?(:length)
format(' [%<icon>s] %<name>-15s circuit=%<circuit>s adj=%<adj>d%<suffix>s',
icon: icon, name: entry[:provider],
circuit: entry[:circuit], adj: entry[:adjustment], suffix: suffix)
end
|
39
40
41
42
43
44
45
46
47
48
49
50
|
# File 'lib/legion/cli/chat/tools/provider_health.rb', line 39
def self.format_report
report = provider_health_report
return "Router not available: #{report[:error]}" if report.is_a?(Hash) && report[:error]
return 'No providers configured.' if report.empty?
summary = provider_circuit_summary(report)
lines = ["Provider Health Report:\n"]
lines << format_circuit_summary(summary) if summary.is_a?(Hash) && !summary[:error]
lines << ''
report.each { |entry| lines << format_entry(entry) }
lines.join("\n")
end
|
.native_provider_health_report ⇒ Object
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
# File 'lib/legion/cli/chat/tools/provider_health.rb', line 92
def self.native_provider_health_report
groups = Legion::LLM::Inventory.providers
return [] unless groups.respond_to?(:map)
groups.map do |provider, offerings|
provider_offerings = Array(offerings)
health = provider_offerings.map { |offering| offering_value(offering, :health) }
.find { |entry| entry.is_a?(Hash) } || {}
circuit = health[:circuit_state] || health['circuit_state'] || 'unknown'
{
provider: provider.to_s,
circuit: circuit,
adjustment: health[:adjustment] || health['adjustment'] || 0,
healthy: circuit.to_s != 'open',
offerings: provider_offerings.size,
models: provider_offerings.map { |offering| offering_value(offering, :model) }.compact.uniq,
types: provider_offerings.map { |offering| offering_value(offering, :type) }.compact.uniq,
instances: provider_offerings.map do |offering|
offering_value(offering, :provider_instance) || offering_value(offering, :instance_id)
end.compact.uniq
}
end
end
|
.native_provider_stats_available? ⇒ Boolean
84
85
86
|
# File 'lib/legion/cli/chat/tools/provider_health.rb', line 84
def self.native_provider_stats_available?
defined?(Legion::LLM::Inventory) && Legion::LLM::Inventory.respond_to?(:providers)
end
|
.offering_value(offering, key) ⇒ Object
131
132
133
134
135
|
# File 'lib/legion/cli/chat/tools/provider_health.rb', line 131
def self.offering_value(offering, key)
return unless offering.respond_to?(:[])
offering[key] || offering[key.to_s]
end
|
.provider_circuit_summary(report) ⇒ Object
116
117
118
119
120
121
122
123
124
|
# File 'lib/legion/cli/chat/tools/provider_health.rb', line 116
def self.provider_circuit_summary(report)
circuits = report.map { |entry| entry[:circuit].to_s }
{
total: report.size,
closed: circuits.count('closed'),
open: circuits.count('open'),
half_open: circuits.count('half_open')
}
end
|
.provider_detail(provider) ⇒ Object
126
127
128
129
|
# File 'lib/legion/cli/chat/tools/provider_health.rb', line 126
def self.provider_detail(provider)
provider_name = provider.to_s
provider_health_report.find { |entry| entry[:provider] == provider_name } || {}
end
|
.provider_health_report ⇒ Object
88
89
90
|
# File 'lib/legion/cli/chat/tools/provider_health.rb', line 88
def self.provider_health_report
native_provider_health_report
end
|
.provider_stats_available? ⇒ Boolean
80
81
82
|
# File 'lib/legion/cli/chat/tools/provider_health.rb', line 80
def self.provider_stats_available?
native_provider_stats_available?
end
|