legionio 1.7.20 → 1.7.21
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 +4 -4
- data/CHANGELOG.md +7 -0
- data/CLAUDE.md +1 -1
- data/README.md +4 -4
- data/lib/legion/readiness.rb +12 -4
- data/lib/legion/service.rb +83 -5
- data/lib/legion/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f1c44047319bdcf02eb061d73517101f695f380d976cb65ad9e2a0d2afb824b2
|
|
4
|
+
data.tar.gz: e756182d3fdfea35882961412f7d3093884d7477954c3b67d2037039ad310189
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1178b2efaadc7801e37a68fd556add983eede7acd3f01dd1c744b029c8e048dc7ac681db0b578fc545419ca8d4f447cc518d3f7d5c2b351323350c1ae9ea908c
|
|
7
|
+
data.tar.gz: c9f34008bef206a7108cbc4013213342c4bc25fa6396884fec1e471b3b6d46d7110027214a0829c05a0d59d59c348fad8726d089c03ffbb1b40ce5f7d9de10a7
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [1.7.21] - 2026-04-06
|
|
6
|
+
### Fixed
|
|
7
|
+
- Optional components (rbac, llm, apollo, gaia) no longer block readiness when not installed
|
|
8
|
+
- Split `Readiness::COMPONENTS` into `REQUIRED_COMPONENTS` and `OPTIONAL_COMPONENTS`
|
|
9
|
+
- Added `Readiness.mark_skipped` for components that are absent or disabled
|
|
10
|
+
- Reload path now correctly marks optional components as skipped when not loaded
|
|
11
|
+
|
|
5
12
|
## [1.7.20] - 2026-04-06
|
|
6
13
|
### Added
|
|
7
14
|
- `Legion::Mode` module with `LEGACY_MAP`, ENV/Settings fallback chain, `agent?`/`worker?`/`infra?`/`lite?` predicates
|
data/CLAUDE.md
CHANGED
|
@@ -9,7 +9,7 @@ The primary gem for the LegionIO framework. An extensible async job engine for s
|
|
|
9
9
|
|
|
10
10
|
**GitHub**: https://github.com/LegionIO/LegionIO
|
|
11
11
|
**Gem**: `legionio`
|
|
12
|
-
**Version**: 1.7.
|
|
12
|
+
**Version**: 1.7.21
|
|
13
13
|
**License**: Apache-2.0
|
|
14
14
|
**Docker**: `legionio/legion`
|
|
15
15
|
**Ruby**: >= 3.4
|
data/README.md
CHANGED
|
@@ -8,13 +8,13 @@ Schedule tasks, chain services into dependency graphs, run them concurrently via
|
|
|
8
8
|
╭──────────────────────────────────────╮
|
|
9
9
|
│ L E G I O N I O │
|
|
10
10
|
│ │
|
|
11
|
-
│ 280+ extensions ·
|
|
11
|
+
│ 280+ extensions · 60 MCP tools │
|
|
12
12
|
│ AI chat CLI · REST API · HA │
|
|
13
13
|
│ cognitive architecture · Vault │
|
|
14
14
|
╰──────────────────────────────────────╯
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
**Ruby >= 3.4** | **v1.
|
|
17
|
+
**Ruby >= 3.4** | **v1.7.21** | **Apache-2.0** | [@Esity](https://github.com/Esity)
|
|
18
18
|
|
|
19
19
|
---
|
|
20
20
|
|
|
@@ -33,7 +33,7 @@ When A completes, B runs. B triggers C, D, and E in parallel. Conditions gate ex
|
|
|
33
33
|
But that's just the foundation. LegionIO is also:
|
|
34
34
|
|
|
35
35
|
- **An AI coding assistant** — interactive chat with tools, code review, commit messages, PR generation, and multi-agent workflows
|
|
36
|
-
- **An MCP server** —
|
|
36
|
+
- **An MCP server** — 60 tools that let any AI agent run tasks, manage extensions, and query your infrastructure
|
|
37
37
|
- **A cognitive computing platform** — 242 brain-modeled extensions across 18 cognitive domains
|
|
38
38
|
- **A digital worker platform** — AI-as-labor with governance, risk tiers, and cost tracking
|
|
39
39
|
|
|
@@ -359,7 +359,7 @@ legion mcp http # streamable HTTP on localhost:9393
|
|
|
359
359
|
legion mcp http --port 8080 --host 0.0.0.0
|
|
360
360
|
```
|
|
361
361
|
|
|
362
|
-
**
|
|
362
|
+
**60 tools** in the `legion.*` namespace:
|
|
363
363
|
|
|
364
364
|
| Category | Tools |
|
|
365
365
|
|----------|-------|
|
data/lib/legion/readiness.rb
CHANGED
|
@@ -4,7 +4,9 @@ require 'concurrent'
|
|
|
4
4
|
|
|
5
5
|
module Legion
|
|
6
6
|
module Readiness
|
|
7
|
-
|
|
7
|
+
REQUIRED_COMPONENTS = %i[settings crypt transport cache data extensions api].freeze
|
|
8
|
+
OPTIONAL_COMPONENTS = %i[rbac llm apollo gaia identity].freeze
|
|
9
|
+
COMPONENTS = (REQUIRED_COMPONENTS + OPTIONAL_COMPONENTS).freeze
|
|
8
10
|
DRAIN_TIMEOUT = 5
|
|
9
11
|
|
|
10
12
|
class << self
|
|
@@ -22,14 +24,19 @@ module Legion
|
|
|
22
24
|
Legion::Logging.debug "[Readiness] #{component} is not ready" if defined?(Legion::Logging)
|
|
23
25
|
end
|
|
24
26
|
|
|
27
|
+
def mark_skipped(component)
|
|
28
|
+
status[component.to_sym] = :skipped
|
|
29
|
+
Legion::Logging.debug "[Readiness] #{component} skipped (optional)" if defined?(Legion::Logging)
|
|
30
|
+
end
|
|
31
|
+
|
|
25
32
|
def ready?(component = nil)
|
|
26
33
|
if component
|
|
27
|
-
result = status[component.to_sym]
|
|
34
|
+
result = [true, :skipped].include?(status[component.to_sym])
|
|
28
35
|
Legion::Logging.warn "[Readiness] #{component} is not ready" if !result && defined?(Legion::Logging)
|
|
29
36
|
return result
|
|
30
37
|
end
|
|
31
38
|
|
|
32
|
-
not_ready = COMPONENTS.reject { |c| status[c]
|
|
39
|
+
not_ready = COMPONENTS.reject { |c| [true, :skipped].include?(status[c]) }
|
|
33
40
|
not_ready.each { |c| Legion::Logging.warn "[Readiness] #{c} is not ready" } if !not_ready.empty? && defined?(Legion::Logging)
|
|
34
41
|
not_ready.empty?
|
|
35
42
|
end
|
|
@@ -50,7 +57,8 @@ module Legion
|
|
|
50
57
|
|
|
51
58
|
def to_h
|
|
52
59
|
COMPONENTS.to_h do |c|
|
|
53
|
-
|
|
60
|
+
val = status[c]
|
|
61
|
+
[c, [true, :skipped].include?(val)]
|
|
54
62
|
end
|
|
55
63
|
end
|
|
56
64
|
end
|
data/lib/legion/service.rb
CHANGED
|
@@ -102,7 +102,11 @@ module Legion
|
|
|
102
102
|
end
|
|
103
103
|
end
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
if data
|
|
106
|
+
setup_rbac
|
|
107
|
+
else
|
|
108
|
+
Legion::Readiness.mark_skipped(:rbac)
|
|
109
|
+
end
|
|
106
110
|
setup_cluster if data
|
|
107
111
|
|
|
108
112
|
if llm
|
|
@@ -112,9 +116,13 @@ module Legion
|
|
|
112
116
|
rescue LoadError => e
|
|
113
117
|
handle_exception(e, level: :debug, operation: 'service.initialize.llm', availability: 'missing')
|
|
114
118
|
log.info 'Legion::LLM gem is not installed'
|
|
119
|
+
Legion::Readiness.mark_skipped(:llm)
|
|
115
120
|
rescue StandardError => e
|
|
116
121
|
handle_exception(e, level: :warn, operation: 'service.initialize.llm')
|
|
122
|
+
Legion::Readiness.mark_skipped(:llm)
|
|
117
123
|
end
|
|
124
|
+
else
|
|
125
|
+
Legion::Readiness.mark_skipped(:llm)
|
|
118
126
|
end
|
|
119
127
|
|
|
120
128
|
begin
|
|
@@ -123,8 +131,10 @@ module Legion
|
|
|
123
131
|
rescue LoadError => e
|
|
124
132
|
handle_exception(e, level: :debug, operation: 'service.initialize.apollo', availability: 'missing')
|
|
125
133
|
log.info 'Legion::Apollo gem is not installed, starting without Apollo'
|
|
134
|
+
Legion::Readiness.mark_skipped(:apollo)
|
|
126
135
|
rescue StandardError => e
|
|
127
136
|
handle_exception(e, level: :warn, operation: 'service.initialize.apollo')
|
|
137
|
+
Legion::Readiness.mark_skipped(:apollo)
|
|
128
138
|
end
|
|
129
139
|
|
|
130
140
|
if gaia
|
|
@@ -134,9 +144,13 @@ module Legion
|
|
|
134
144
|
rescue LoadError => e
|
|
135
145
|
handle_exception(e, level: :debug, operation: 'service.initialize.gaia', availability: 'missing')
|
|
136
146
|
log.info 'Legion::Gaia gem is not installed'
|
|
147
|
+
Legion::Readiness.mark_skipped(:gaia)
|
|
137
148
|
rescue StandardError => e
|
|
138
149
|
handle_exception(e, level: :warn, operation: 'service.initialize.gaia')
|
|
150
|
+
Legion::Readiness.mark_skipped(:gaia)
|
|
139
151
|
end
|
|
152
|
+
else
|
|
153
|
+
Legion::Readiness.mark_skipped(:gaia)
|
|
140
154
|
end
|
|
141
155
|
|
|
142
156
|
setup_telemetry
|
|
@@ -178,6 +192,7 @@ module Legion
|
|
|
178
192
|
require 'legion/api/default_settings'
|
|
179
193
|
api_settings = Legion::Settings[:api]
|
|
180
194
|
@api_enabled = api && api_settings[:enabled]
|
|
195
|
+
setup_apm if @api_enabled
|
|
181
196
|
setup_api if @api_enabled
|
|
182
197
|
setup_network_watchdog
|
|
183
198
|
Legion::Settings[:client][:ready] = true
|
|
@@ -232,8 +247,10 @@ module Legion
|
|
|
232
247
|
rescue LoadError => e
|
|
233
248
|
handle_exception(e, level: :debug, operation: 'service.setup_rbac', availability: 'missing')
|
|
234
249
|
log.debug 'Legion::Rbac gem is not installed, starting without RBAC'
|
|
250
|
+
Legion::Readiness.mark_skipped(:rbac)
|
|
235
251
|
rescue StandardError => e
|
|
236
252
|
handle_exception(e, level: :warn, operation: 'service.setup_rbac')
|
|
253
|
+
Legion::Readiness.mark_skipped(:rbac)
|
|
237
254
|
end
|
|
238
255
|
|
|
239
256
|
def setup_cluster
|
|
@@ -309,6 +326,42 @@ module Legion
|
|
|
309
326
|
)
|
|
310
327
|
end
|
|
311
328
|
|
|
329
|
+
def setup_apm
|
|
330
|
+
apm_settings = Legion::Settings[:apm] || {}
|
|
331
|
+
return unless apm_settings[:enabled]
|
|
332
|
+
|
|
333
|
+
require 'elastic-apm'
|
|
334
|
+
|
|
335
|
+
config = {
|
|
336
|
+
service_name: apm_settings[:service_name] || "legion-#{Legion::Settings[:client][:name]}",
|
|
337
|
+
server_url: apm_settings[:server_url] || 'http://localhost:8200',
|
|
338
|
+
environment: apm_settings[:environment] || Legion::Settings[:environment] || 'development',
|
|
339
|
+
secret_token: apm_settings[:secret_token],
|
|
340
|
+
api_key: apm_settings[:api_key],
|
|
341
|
+
log_level: apm_settings[:log_level]&.to_sym || Logger::WARN,
|
|
342
|
+
transaction_sample_rate: apm_settings[:sample_rate] || 1.0
|
|
343
|
+
}.compact
|
|
344
|
+
|
|
345
|
+
ElasticAPM.start(**config)
|
|
346
|
+
@apm_running = true
|
|
347
|
+
log.info "Elastic APM started: server=#{config[:server_url]} service=#{config[:service_name]}"
|
|
348
|
+
rescue LoadError => e
|
|
349
|
+
handle_exception(e, level: :debug, operation: 'service.setup_apm', availability: 'missing')
|
|
350
|
+
log.info 'elastic-apm gem is not installed, starting without APM'
|
|
351
|
+
rescue StandardError => e
|
|
352
|
+
handle_exception(e, level: :warn, operation: 'service.setup_apm')
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
def shutdown_apm
|
|
356
|
+
return unless @apm_running
|
|
357
|
+
|
|
358
|
+
ElasticAPM.stop if defined?(ElasticAPM) && ElasticAPM.running?
|
|
359
|
+
@apm_running = false
|
|
360
|
+
log.info 'Elastic APM stopped'
|
|
361
|
+
rescue StandardError => e
|
|
362
|
+
handle_exception(e, level: :warn, operation: 'service.shutdown_apm')
|
|
363
|
+
end
|
|
364
|
+
|
|
312
365
|
def setup_api # rubocop:disable Metrics/MethodLength
|
|
313
366
|
if @api_thread&.alive?
|
|
314
367
|
log.warn 'API already running, skipping duplicate setup_api call'
|
|
@@ -667,6 +720,7 @@ module Legion
|
|
|
667
720
|
shutdown_network_watchdog
|
|
668
721
|
shutdown_audit_archiver
|
|
669
722
|
shutdown_api
|
|
723
|
+
shutdown_apm
|
|
670
724
|
|
|
671
725
|
Legion::Metrics.reset! if defined?(Legion::Metrics)
|
|
672
726
|
|
|
@@ -738,6 +792,7 @@ module Legion
|
|
|
738
792
|
|
|
739
793
|
shutdown_network_watchdog
|
|
740
794
|
shutdown_api
|
|
795
|
+
shutdown_apm
|
|
741
796
|
|
|
742
797
|
if defined?(Legion::Gaia) && Legion::Gaia.respond_to?(:started?) && Legion::Gaia.started?
|
|
743
798
|
shutdown_component('Gaia') { Legion::Gaia.shutdown }
|
|
@@ -786,11 +841,33 @@ module Legion
|
|
|
786
841
|
setup_data
|
|
787
842
|
Legion::Readiness.mark_ready(:data)
|
|
788
843
|
|
|
789
|
-
|
|
790
|
-
|
|
844
|
+
if defined?(Legion::Rbac)
|
|
845
|
+
setup_rbac
|
|
846
|
+
else
|
|
847
|
+
Legion::Readiness.mark_skipped(:rbac)
|
|
848
|
+
end
|
|
849
|
+
|
|
850
|
+
if defined?(Legion::LLM)
|
|
851
|
+
setup_llm
|
|
852
|
+
else
|
|
853
|
+
Legion::Readiness.mark_skipped(:llm)
|
|
854
|
+
end
|
|
791
855
|
|
|
792
|
-
|
|
793
|
-
|
|
856
|
+
if defined?(Legion::Apollo)
|
|
857
|
+
setup_apollo
|
|
858
|
+
Legion::Readiness.mark_ready(:apollo)
|
|
859
|
+
else
|
|
860
|
+
Legion::Readiness.mark_skipped(:apollo)
|
|
861
|
+
end
|
|
862
|
+
|
|
863
|
+
if defined?(Legion::Gaia)
|
|
864
|
+
setup_gaia
|
|
865
|
+
Legion::Readiness.mark_ready(:gaia)
|
|
866
|
+
else
|
|
867
|
+
Legion::Readiness.mark_skipped(:gaia)
|
|
868
|
+
end
|
|
869
|
+
|
|
870
|
+
Legion::Readiness.mark_ready(:identity)
|
|
794
871
|
|
|
795
872
|
setup_supervision
|
|
796
873
|
load_extensions
|
|
@@ -801,6 +878,7 @@ module Legion
|
|
|
801
878
|
register_core_tools
|
|
802
879
|
|
|
803
880
|
Legion::Crypt.cs
|
|
881
|
+
setup_apm if @api_enabled
|
|
804
882
|
setup_api if @api_enabled
|
|
805
883
|
|
|
806
884
|
if defined?(Legion::MCP)
|
data/lib/legion/version.rb
CHANGED