legionio 1.9.29 → 1.9.31

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: 952eb59489faed844f57a13d5fb71a10d4f6e737b3af38f96cc9ab7beec5a9da
4
- data.tar.gz: e8af435fd6f5caa5324f678c45a38d7c8bde94a801a80c8380032f43d9721fbf
3
+ metadata.gz: 765d0bb57b5a10135d49ccbaca56669a33b201118421fc90242acd4f12d752ec
4
+ data.tar.gz: 464deff220c28495e29c7def972d4c5a7c925abdee6572991fd01d84e6791878
5
5
  SHA512:
6
- metadata.gz: 1cd3acf9f4e8af3da0db483123afbeb5b9c8b69430dbaf538474523a3d5fb02aa8e5fd9ac262244a61ed1f9a0ed7add934bdc59ecdd239a3cd8621ddbdec02e4
7
- data.tar.gz: dc7a8cc98adcd63d75419cc29d88f025539185fc2c9254d9c9a1b8abdeaeadc1ff7e3e1481de1352e398a63826c74e41975f8c13708e462a6dcebb35fd97ef4b
6
+ metadata.gz: aba6393b1e60a435ff0e752ae6b7d5a035387a1e6012ec997d3c0f1c0ee31d408d7fb78f8ed4340e1594963b0510189047ea1fd0f6d49f18b7d914ff247fa60b
7
+ data.tar.gz: dd3c0bd6abd74759c9858c8192b8938dbdf17333093e9173bdc681868c1f0fd039fb87f9659e8a0388bde76e47cfd71a97937e24f619c31a9d2b32476aded675
data/CHANGELOG.md CHANGED
@@ -2,6 +2,23 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [1.9.31] - 2026-05-14
6
+
7
+ ### Added
8
+ - `GET /api/identity` endpoint returning live process identity, provider resolution status, and registered provider metadata.
9
+ - `autobuild_submodules` recursive walk in `Legion::Extensions` — nested sub-modules (e.g. `Delegated`, `Application`, `ManagedIdentity`, `WorkloadIdentity` inside `lex-identity-entra`) now have their actors autobuilt and started.
10
+
11
+ ### Fixed
12
+ - `Extensions::Helpers::Base#full_path` now walks up gem name segments to find the parent gem when a sub-module gem doesn't exist as a standalone gem (e.g. `lex-identity-entra-delegated`).
13
+
14
+ ## [1.9.30] - 2026-05-12
15
+
16
+ ### Changed
17
+ - Slimmed agentic pack to only cognitive/coordination extensions; removed non-agentic gems (`lex-audit`, `lex-autofix`, `lex-codegen`, `lex-cost-scanner`, `lex-dataset`, `lex-factory`, `lex-finops`, `lex-governance`, `lex-llm-ledger`, `lex-onboard`, `lex-pilot-infra-monitor`, `lex-pilot-knowledge-assist`, `lex-prompt`, `lex-react`, `lex-swarm`, `lex-swarm-github`, `lex-transformer`).
18
+ - Added `legion-mcp` to the LLM pack.
19
+ - Added `lex-kerberos` to the identity pack.
20
+ - Added new `developer` pack: `lex-developer`, `lex-dynatrace`, `lex-eval`, `lex-exec`, `lex-github`, `lex-http`, `lex-jfrog`, `lex-skill-superpowers`, `lex-ssh`.
21
+
5
22
  ## [1.9.29] - 2026-05-11
6
23
 
7
24
  ### Fixed
data/Gemfile CHANGED
@@ -3,64 +3,41 @@
3
3
  source 'https://rubygems.org'
4
4
 
5
5
  gemspec
6
-
7
- def local_gem_version(path, version_file)
8
- version_path = File.expand_path(File.join(path, version_file), __dir__)
9
- return unless File.file?(version_path)
10
-
11
- version_source = File.read(version_path)
12
- version_source[/VERSION\s*=\s*['"]([^'"]+)['"]/, 1]
13
- end
14
-
15
- def local_gem_satisfies?(path, version_file, requirement)
16
- version = local_gem_version(path, version_file)
17
- version && Gem::Requirement.new(requirement).satisfied_by?(Gem::Version.new(version))
18
- end
19
-
20
- def local_gem_path(name, default_path, version_file, requirement)
21
- env_name = "#{name.upcase.tr('-', '_')}_PATH"
22
- env_path = ENV.fetch(env_name, nil)
23
- return env_path if env_path && File.exist?(File.expand_path(env_path, __dir__))
24
-
25
- return unless File.exist?(File.expand_path(default_path, __dir__))
26
- return unless local_gem_satisfies?(default_path, version_file, requirement)
27
-
28
- default_path
29
- end
30
-
31
- gem 'legion-apollo', path: '../legion-apollo' if File.exist?(File.expand_path('../legion-apollo', __dir__))
32
- gem 'legion-data', path: '../legion-data' if File.exist?(File.expand_path('../legion-data', __dir__))
33
- gem 'legion-logging', path: '../legion-logging' if File.exist?(File.expand_path('../legion-logging', __dir__))
34
- gem 'legion-settings', path: '../legion-settings' if File.exist?(File.expand_path('../legion-settings', __dir__))
35
- if (legion_tty_path = local_gem_path('legion-tty', '../legion-tty', 'lib/legion/tty/version.rb', '>= 0.5.4'))
36
- gem 'legion-tty', path: legion_tty_path
37
- end
38
-
39
- gem 'legion-gaia', path: '../legion-gaia' if File.exist?(File.expand_path('../legion-gaia', __dir__))
40
- if (legion_llm_path = local_gem_path('legion-llm', '../legion-llm', 'lib/legion/llm/version.rb', '>= 0.8.47'))
41
- gem 'legion-llm', path: legion_llm_path
42
- end
43
- gem 'legion-mcp', path: '../legion-mcp' if File.exist?(File.expand_path('../legion-mcp', __dir__))
44
-
45
- gem 'lex-kerberos'
46
-
47
- gem 'lex-apollo', path: '../extensions/lex-apollo' if File.exist?(File.expand_path('../extensions/lex-apollo', __dir__))
48
- gem 'lex-llm', path: '../extensions-ai/lex-llm' if File.exist?(File.expand_path('../extensions-ai/lex-llm', __dir__))
49
- gem 'lex-llm-ledger', path: '../extensions-ai/lex-llm-ledger' if File.exist?(File.expand_path('../extensions-ai/lex-llm-ledger', __dir__))
50
-
51
- %w[anthropic azure-foundry bedrock gemini mlx ollama openai vertex vllm].each do |provider|
52
- provider_path = "../extensions-ai/lex-llm-#{provider}"
53
- gem "lex-llm-#{provider}", path: provider_path if File.exist?(File.expand_path(provider_path, __dir__))
54
- end
55
-
56
- # gem 'lex-microsoft_teams', path: '../extensions/lex-microsoft_teams' if File.exist?(File.expand_path('../extensions/lex-microsoft_teams', __dir__))
57
-
58
6
  gem 'pg'
59
7
 
60
8
  gem 'kramdown', '>= 2.0'
61
9
  gem 'mysql2'
62
10
 
63
11
  group :test do
12
+ gem 'legion-data', path: '../legion-data' if File.exist?(File.expand_path('../legion-data', __dir__))
13
+ gem 'legion-logging', path: '../legion-logging' if File.exist?(File.expand_path('../legion-logging', __dir__))
14
+ gem 'legion-settings', path: '../legion-settings' if File.exist?(File.expand_path('../legion-settings', __dir__))
15
+
16
+ gem 'legion-apollo', path: '../legion-apollo' if File.exist?(File.expand_path('../legion-apollo', __dir__))
17
+ gem 'legion-gaia', path: '../legion-gaia' if File.exist?(File.expand_path('../legion-gaia', __dir__))
18
+ gem 'legion-llm', path: '../legion-llm' if File.exist?(File.expand_path('../legion-llm', __dir__))
19
+ gem 'legion-mcp', path: '../legion-mcp' if File.exist?(File.expand_path('../legion-mcp', __dir__))
20
+ gem 'legion-tty', path: '../legion-tty' if File.exist?(File.expand_path('../legion-tty', __dir__))
21
+
22
+ gem 'lex-apollo', path: '../extensions/lex-apollo' if File.exist?(File.expand_path('../extensions/lex-apollo', __dir__))
23
+ gem 'lex-llm', path: '../extensions-ai/lex-llm' if File.exist?(File.expand_path('../extensions-ai/lex-llm', __dir__))
24
+ gem 'lex-llm-ledger', path: '../extensions-ai/lex-llm-ledger' if File.exist?(File.expand_path('../extensions-ai/lex-llm-ledger', __dir__))
25
+
26
+ if File.exist?(File.expand_path('../extensions-identity/lex-identity-entra', __dir__))
27
+ gem 'lex-identity-entra', path: '../extensions-identity/lex-identity-entra'
28
+ end
29
+ if File.exist?(File.expand_path('../extensions-identity/lex-identity-kerberos', __dir__))
30
+ gem 'lex-identity-kerberos', path: '../extensions-identity/lex-identity-kerberos'
31
+ end
32
+ if File.exist?(File.expand_path('../extensions-identity/lex-identity-system', __dir__))
33
+ gem 'lex-identity-system', path: '../extensions-identity/lex-identity-system'
34
+ end
35
+
36
+ %w[anthropic azure-foundry bedrock gemini mlx ollama openai vertex vllm].each do |provider|
37
+ provider_path = "../extensions-ai/lex-llm-#{provider}"
38
+ gem "lex-llm-#{provider}", path: provider_path if File.exist?(File.expand_path(provider_path, __dir__))
39
+ end
40
+
64
41
  gem 'faraday'
65
42
  gem 'faraday-net_http'
66
43
  gem 'graphql'
@@ -7,6 +7,26 @@ module Legion
7
7
  def self.registered(app)
8
8
  app.helpers IdentityAuditHelpers
9
9
 
10
+ app.get '/api/identity' do
11
+ identity = defined?(Legion::Identity::Process) ? Legion::Identity::Process.identity_hash : {}
12
+
13
+ registered_providers = if defined?(Legion::Identity::Resolver)
14
+ Legion::Identity::Resolver.providers.map do |p|
15
+ {
16
+ name: p.provider_name,
17
+ type: p.provider_type,
18
+ trust_level: p.trust_level,
19
+ priority: p.respond_to?(:priority) ? p.priority : nil,
20
+ capabilities: p.respond_to?(:capabilities) ? p.capabilities : []
21
+ }
22
+ end
23
+ else
24
+ []
25
+ end
26
+
27
+ json_response(identity.merge(registered_providers: registered_providers))
28
+ end
29
+
10
30
  app.get '/api/identity/audit' do
11
31
  require_data!
12
32
  halt 503, json_error('unavailable', 'identity audit log not available') unless defined?(Legion::Data::Model::Identity::AuditLog)
@@ -28,38 +28,32 @@ module Legion
28
28
  }.freeze
29
29
 
30
30
  PACKS = {
31
- agentic: {
32
- description: 'Full cognitive stack: core libs, agentic domains, AI providers, and operational extensions',
31
+ agentic: {
32
+ description: 'Cognitive stack: agentic domains, AI providers, and coordination',
33
33
  gems: %w[
34
34
  legion-apollo legion-gaia legion-llm legion-mcp legion-rbac
35
35
  lex-acp lex-adapter lex-agentic-affect lex-agentic-attention
36
36
  lex-agentic-defense lex-agentic-executive lex-agentic-homeostasis
37
37
  lex-agentic-imagination lex-agentic-inference lex-agentic-integration
38
38
  lex-agentic-language lex-agentic-learning lex-agentic-memory
39
- lex-agentic-self lex-agentic-social lex-apollo lex-audit lex-autofix
40
- lex-codegen lex-coldstart
41
- lex-conditioner lex-cost-scanner lex-dataset lex-detect
42
- lex-eval lex-exec lex-extinction lex-factory lex-finops
43
- lex-governance lex-kerberos lex-knowledge lex-llm
44
- lex-llm-anthropic lex-llm-azure-foundry lex-llm-bedrock
45
- lex-llm-gemini lex-llm-ledger lex-llm-mlx
46
- lex-llm-ollama lex-llm-openai lex-llm-vertex lex-llm-vllm
47
- lex-metering lex-mesh lex-microsoft_teams lex-mind-growth lex-node
48
- lex-onboard lex-pilot-infra-monitor
49
- lex-pilot-knowledge-assist lex-privatecore lex-prompt lex-react
50
- lex-swarm lex-swarm-github lex-synapse lex-telemetry lex-tick
51
- lex-transformer
39
+ lex-agentic-self lex-agentic-social lex-apollo lex-coldstart
40
+ lex-conditioner lex-detect lex-extinction lex-kerberos lex-knowledge
41
+ lex-llm lex-llm-anthropic lex-llm-azure-foundry lex-llm-bedrock
42
+ lex-llm-gemini lex-llm-mlx lex-llm-ollama lex-llm-openai
43
+ lex-llm-vertex lex-llm-vllm lex-metering lex-mesh
44
+ lex-microsoft_teams lex-mind-growth lex-node lex-privatecore
45
+ lex-synapse lex-telemetry lex-tick
52
46
  ]
53
47
  },
54
- llm: {
48
+ llm: {
55
49
  description: 'LLM routing and provider integration (no cognitive stack)',
56
50
  gems: %w[
57
- legion-llm lex-llm lex-llm-anthropic lex-llm-azure-foundry
51
+ legion-llm legion-mcp lex-llm lex-llm-anthropic lex-llm-azure-foundry
58
52
  lex-llm-bedrock lex-llm-gemini lex-llm-mlx
59
53
  lex-llm-ollama lex-llm-openai lex-llm-vertex lex-llm-vllm
60
54
  ]
61
55
  },
62
- gaia: {
56
+ gaia: {
63
57
  description: 'Cognitive coordination engine + agentic extensions (GAIA stack)',
64
58
  gems: %w[
65
59
  legion-gaia
@@ -70,13 +64,20 @@ module Legion
70
64
  lex-synapse lex-mind-growth lex-tick
71
65
  ]
72
66
  },
73
- identity: {
67
+ identity: {
74
68
  description: 'Identity and access management (RBAC + identity providers)',
75
69
  gems: %w[
76
- legion-rbac lex-identity-system lex-identity-kerberos
70
+ legion-rbac lex-identity-entra lex-identity-kerberos lex-identity-system lex-kerberos
71
+ ]
72
+ },
73
+ developer: {
74
+ description: 'Developer tooling and CI/CD integrations',
75
+ gems: %w[
76
+ lex-developer lex-dynatrace lex-eval lex-exec lex-github
77
+ lex-http lex-jfrog lex-skill-superpowers lex-ssh
77
78
  ]
78
79
  },
79
- channels: {
80
+ channels: {
80
81
  description: 'Channel adapters for chat platforms',
81
82
  gems: %w[lex-slack lex-microsoft_teams]
82
83
  }
@@ -95,19 +95,35 @@ module Legion
95
95
  end
96
96
 
97
97
  def full_path
98
- @full_path ||= begin
99
- base_name = segments.join('-')
100
- gem_name = "lex-#{base_name}"
98
+ @full_path ||= find_gem_path
99
+ end
100
+
101
+ def find_gem_path
102
+ segs = segments.dup
103
+ gem_dir = nil
104
+ while segs.length >= 1
105
+ base_name = segs.join('-')
106
+ gem_name = "lex-#{base_name}"
101
107
  gem_dir = begin
102
108
  Gem::Specification.find_by_name(gem_name).gem_dir
103
109
  rescue Gem::MissingSpecError
104
- Gem::Specification.find_by_name("lex-#{base_name.tr('_', '-')}").gem_dir
110
+ begin
111
+ Gem::Specification.find_by_name("lex-#{base_name.tr('_', '-')}").gem_dir
112
+ rescue Gem::MissingSpecError
113
+ segs.pop
114
+ next
115
+ end
105
116
  end
106
- require_path = Helpers::Segments.derive_require_path(gem_name)
107
- "#{gem_dir}/lib/#{require_path}"
117
+ break
108
118
  end
109
- rescue Gem::MissingSpecError => e
110
- Legion::Logging.error "#{e.class} => #{e.message}"
119
+
120
+ unless gem_dir
121
+ Legion::Logging.error "#{self.class}: could not find gem for segments #{segments.inspect}"
122
+ return nil
123
+ end
124
+
125
+ require_path = Helpers::Segments.derive_require_path("lex-#{segments.join('-')}")
126
+ "#{gem_dir}/lib/#{require_path}"
111
127
  end
112
128
  alias extension_path full_path
113
129
 
@@ -9,6 +9,8 @@ require 'legion/runner'
9
9
 
10
10
  module Legion
11
11
  module Extensions
12
+ SUBMODULE_SKIP = %i[VERSION Actor Actors Runners Helpers Transport Data].freeze
13
+
12
14
  class << self
13
15
  def setup
14
16
  hook_extensions
@@ -299,6 +301,8 @@ module Legion
299
301
  extension.log.debug("deferring literal actor: #{actor}") if has_logger
300
302
  @pending_actors << actor
301
303
  end
304
+
305
+ autobuild_submodules(extension, has_logger)
302
306
  extension.log.info "Loaded v#{extension::VERSION}"
303
307
  Legion::Events.emit('extension.loaded', name: ext_name, version: entry[:gem_name])
304
308
 
@@ -493,6 +497,51 @@ module Legion
493
497
 
494
498
  private
495
499
 
500
+ def autobuild_submodules(extension, has_logger)
501
+ return unless extension.is_a?(Module)
502
+
503
+ extension.constants(false).each do |const_name|
504
+ next if SUBMODULE_SKIP.include?(const_name)
505
+
506
+ submod = extension.const_get(const_name, false)
507
+ next unless submod.is_a?(Module) && submod.respond_to?(:autobuild)
508
+
509
+ autobuild_one_submodule(extension, submod, const_name, has_logger)
510
+ rescue StandardError => e
511
+ Legion::Logging.warn "autobuild_submodules: failed for #{extension}::#{const_name} — #{e.message}" if defined?(Legion::Logging)
512
+ end
513
+ end
514
+
515
+ def autobuild_one_submodule(extension, submod, const_name, has_logger)
516
+ submod.autobuild
517
+ collect_submodule_actors(submod, has_logger)
518
+ register_submodule_capabilities(extension, submod, const_name)
519
+ autobuild_submodules(submod, has_logger)
520
+ end
521
+
522
+ def collect_submodule_actors(submod, has_logger)
523
+ if submod.respond_to?(:meta_actors) && submod.meta_actors.is_a?(Hash)
524
+ submod.meta_actors.each_value do |actor|
525
+ submod.log.debug("deferring submodule meta actor: #{actor}") if has_logger
526
+ @pending_actors << actor
527
+ end
528
+ end
529
+
530
+ return unless submod.respond_to?(:actors)
531
+
532
+ submod.actors.each_value do |actor|
533
+ submod.log.debug("deferring submodule literal actor: #{actor}") if has_logger
534
+ @pending_actors << actor
535
+ end
536
+ end
537
+
538
+ def register_submodule_capabilities(extension, submod, const_name)
539
+ return unless submod.respond_to?(:runners)
540
+
541
+ prefix = extension.respond_to?(:lex_name) ? extension.lex_name : extension.name
542
+ register_capabilities("#{prefix}/#{const_name}", submod.runners)
543
+ end
544
+
496
545
  def write_lex_cli_manifest(entry, extension)
497
546
  require 'legion/cli/lex_cli_manifest'
498
547
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Legion
4
- VERSION = '1.9.29'
4
+ VERSION = '1.9.31'
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.9.29
4
+ version: 1.9.31
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity