legionio 1.5.15 → 1.5.18
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 +19 -0
- data/Gemfile +1 -0
- data/legionio.gemspec +1 -0
- data/lib/legion/extensions/core.rb +13 -0
- data/lib/legion/extensions/helpers/knowledge.rb +141 -0
- data/lib/legion/extensions/helpers/llm.rb +18 -0
- data/lib/legion/readiness.rb +1 -1
- data/lib/legion/service.rb +21 -0
- data/lib/legion/version.rb +1 -1
- metadata +17 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fa969cacd00cbd7fcd3234d1d7b46e720da00a4193b4faa967d0f4e9b662b4e4
|
|
4
|
+
data.tar.gz: 2afe90f9456b0c5abf07f7180d562dd84ac7c901e81aea1b841288f3aae929d6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bf23f83209770f3e9b7c66bd59ccae187f24c136b94059b5bc54a58e9e80188280a94f01ce557eab19eb1a903bcd9e1a9d69cf7a46077ab89297f934ca1b5244
|
|
7
|
+
data.tar.gz: cf041438573f2eb546929ef68e35c527b52af9f552e129fd79b6c94f75862361eeee9d63d4f1fc2b26fecbd70078cc97614c6e928c7fa45cb317b3de858c4eea
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Legion Changelog
|
|
2
2
|
|
|
3
|
+
## [1.5.18] - 2026-03-25
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- `scope:` parameter on `Helpers::Knowledge` (`ingest_knowledge` and `query_knowledge`)
|
|
7
|
+
- Scope routing: `:local` -> `Apollo::Local`, `:global` -> `Apollo`, `:all` -> both with local-first dedup
|
|
8
|
+
- Default query scope configurable via `Settings[:apollo][:local][:default_query_scope]`
|
|
9
|
+
- `setup_apollo` now starts `Apollo::Local` when available
|
|
10
|
+
|
|
11
|
+
## [1.5.17] - 2026-03-25
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
- `Helpers::Knowledge` — universal `ingest_knowledge` and `query_knowledge` mixin for all extensions; included automatically in `Extensions::Core`
|
|
15
|
+
- Automatic file extraction via `Legion::Data::Extract` when a file path is passed to `ingest_knowledge`
|
|
16
|
+
- Graceful degradation when `Legion::Apollo` or `Legion::Data::Extract` are not available
|
|
17
|
+
- `setup_apollo` in `Service` boot sequence (between LLM and GAIA); wires `Legion::Apollo.start` with `LoadError`/`StandardError` rescue
|
|
18
|
+
- `:apollo` added to `Readiness::COMPONENTS` between `:llm` and `:gaia`
|
|
19
|
+
- `legion-apollo >= 0.2.1` dependency in gemspec
|
|
20
|
+
- `Helpers::LLM#llm_embed` in LegionIO now forwards all keyword arguments (`provider:`, `dimensions:`, etc.) via anonymous `**` forwarding
|
|
21
|
+
|
|
3
22
|
## [1.5.15] - 2026-03-25
|
|
4
23
|
|
|
5
24
|
### Removed
|
data/Gemfile
CHANGED
|
@@ -11,6 +11,7 @@ gem 'legion-logging', path: '../legion-logging' if File.exist?(File.expand_path(
|
|
|
11
11
|
gem 'legion-mcp', path: '../legion-mcp' if File.exist?(File.expand_path('../legion-mcp', __dir__))
|
|
12
12
|
gem 'legion-settings', path: '../legion-settings' if File.exist?(File.expand_path('../legion-settings', __dir__))
|
|
13
13
|
|
|
14
|
+
gem 'legion-apollo', path: '../legion-apollo' if File.exist?(File.expand_path('../legion-apollo', __dir__))
|
|
14
15
|
gem 'lex-agentic-memory', path: '../extensions-agentic/lex-agentic-memory' if File.exist?(File.expand_path('../extensions-agentic/lex-agentic-memory', __dir__))
|
|
15
16
|
gem 'lex-llm-gateway', path: '../extensions-core/lex-llm-gateway' if File.exist?(File.expand_path('../extensions-core/lex-llm-gateway', __dir__))
|
|
16
17
|
gem 'lex-microsoft_teams', path: '../extensions/lex-microsoft_teams' if File.exist?(File.expand_path('../extensions/lex-microsoft_teams', __dir__))
|
data/legionio.gemspec
CHANGED
|
@@ -60,6 +60,7 @@ Gem::Specification.new do |spec|
|
|
|
60
60
|
spec.add_dependency 'legion-settings', '>= 1.3.19'
|
|
61
61
|
spec.add_dependency 'legion-transport', '>= 1.4.0'
|
|
62
62
|
|
|
63
|
+
spec.add_dependency 'legion-apollo', '>= 0.2.1'
|
|
63
64
|
spec.add_dependency 'legion-gaia', '>= 0.9.24'
|
|
64
65
|
spec.add_dependency 'legion-llm', '>= 0.5.8'
|
|
65
66
|
spec.add_dependency 'legion-tty', '>= 0.4.35'
|
|
@@ -21,6 +21,18 @@ rescue LoadError => e
|
|
|
21
21
|
Legion::Logging.debug "Extensions::Core: legion-llm helpers not available: #{e.message}" if defined?(Legion::Logging)
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
+
begin
|
|
25
|
+
require_relative 'helpers/llm'
|
|
26
|
+
rescue LoadError => e
|
|
27
|
+
Legion::Logging.debug "Extensions::Core: local llm helper not available: #{e.message}" if defined?(Legion::Logging)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
begin
|
|
31
|
+
require_relative 'helpers/knowledge'
|
|
32
|
+
rescue LoadError => e
|
|
33
|
+
Legion::Logging.debug "Extensions::Core: knowledge helper not available: #{e.message}" if defined?(Legion::Logging)
|
|
34
|
+
end
|
|
35
|
+
|
|
24
36
|
require_relative 'actors/base'
|
|
25
37
|
require_relative 'actors/every'
|
|
26
38
|
require_relative 'actors/loop'
|
|
@@ -35,6 +47,7 @@ module Legion
|
|
|
35
47
|
module Core
|
|
36
48
|
include Legion::Extensions::Helpers::Transport
|
|
37
49
|
include Legion::Extensions::Helpers::Lex
|
|
50
|
+
include Legion::Extensions::Helpers::Knowledge if defined?(Legion::Extensions::Helpers::Knowledge)
|
|
38
51
|
|
|
39
52
|
include Legion::Extensions::Builder::Runners
|
|
40
53
|
include Legion::Extensions::Builder::Helpers
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Helpers
|
|
6
|
+
module Knowledge
|
|
7
|
+
def ingest_knowledge(content_or_path, type: :auto, tags: [], scope: :global, **opts)
|
|
8
|
+
target = resolve_ingest_target(scope)
|
|
9
|
+
return { success: false, error: :apollo_not_available } unless target
|
|
10
|
+
|
|
11
|
+
text, metadata = extract_if_needed(content_or_path, type: type)
|
|
12
|
+
return { success: false, error: :extraction_failed, detail: metadata } unless text
|
|
13
|
+
|
|
14
|
+
extraction_tags = metadata_to_tags(metadata) if metadata
|
|
15
|
+
all_tags = Array(tags) + Array(extraction_tags)
|
|
16
|
+
|
|
17
|
+
target.ingest(
|
|
18
|
+
content: text,
|
|
19
|
+
tags: all_tags,
|
|
20
|
+
source_channel: opts[:source_channel] || derive_lex_name,
|
|
21
|
+
**opts.except(:source_channel)
|
|
22
|
+
)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def query_knowledge(text:, limit: 5, scope: nil, **)
|
|
26
|
+
scope ||= default_query_scope
|
|
27
|
+
|
|
28
|
+
case scope.to_sym
|
|
29
|
+
when :local then query_local(text: text, limit: limit, **)
|
|
30
|
+
when :global then query_global(text: text, limit: limit, **)
|
|
31
|
+
else query_all(text: text, limit: limit, **)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def resolve_ingest_target(scope)
|
|
38
|
+
case scope.to_sym
|
|
39
|
+
when :local
|
|
40
|
+
local_available? ? Legion::Apollo::Local : nil
|
|
41
|
+
else
|
|
42
|
+
global_available? ? Legion::Apollo : nil
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def query_local(text:, limit:, **)
|
|
47
|
+
unless local_available?
|
|
48
|
+
Legion::Logging.debug 'query_knowledge(:local) called but Apollo::Local is not available' if defined?(Legion::Logging)
|
|
49
|
+
return { success: false, error: :apollo_not_available }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
Legion::Apollo::Local.query(text: text, limit: limit, **)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def query_global(text:, limit:, **)
|
|
56
|
+
unless global_available?
|
|
57
|
+
Legion::Logging.debug 'query_knowledge(:global) called but Apollo is not available' if defined?(Legion::Logging)
|
|
58
|
+
return { success: false, error: :apollo_not_available }
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
Legion::Apollo.query(text: text, limit: limit, **)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def query_all(text:, limit:, **)
|
|
65
|
+
local_results = local_available? ? Array((Legion::Apollo::Local.query(text: text, limit: limit, **) || {})[:results]) : []
|
|
66
|
+
global_results = global_available? ? Array((Legion::Apollo.query(text: text, limit: limit, **) || {})[:results]) : []
|
|
67
|
+
|
|
68
|
+
return { success: false, error: :apollo_not_available } if local_results.empty? && global_results.empty? && !local_available? && !global_available?
|
|
69
|
+
|
|
70
|
+
merged = merge_results(local_results, global_results)
|
|
71
|
+
{ success: true, results: merged.first(limit), count: [merged.size, limit].min, mode: :all }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def merge_results(local_results, global_results)
|
|
75
|
+
seen = {}
|
|
76
|
+
merged = []
|
|
77
|
+
|
|
78
|
+
local_results.each do |r|
|
|
79
|
+
key = r[:content_hash] || r[:content]
|
|
80
|
+
seen[key] = true
|
|
81
|
+
merged << r
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
global_results.each do |r|
|
|
85
|
+
key = r[:content_hash] || r[:content]
|
|
86
|
+
merged << r unless seen[key]
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
merged
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def global_available?
|
|
93
|
+
defined?(Legion::Apollo) && Legion::Apollo.started?
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def local_available?
|
|
97
|
+
defined?(Legion::Apollo::Local) && Legion::Apollo::Local.started?
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def default_query_scope
|
|
101
|
+
return :all unless defined?(Legion::Settings)
|
|
102
|
+
|
|
103
|
+
scope = Legion::Settings.dig(:apollo, :local, :default_query_scope)
|
|
104
|
+
scope ? scope.to_sym : :all
|
|
105
|
+
rescue StandardError
|
|
106
|
+
:all
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def extract_if_needed(content_or_path, type:)
|
|
110
|
+
return extract_file(content_or_path, type: type) if content_or_path.is_a?(String) && File.exist?(content_or_path)
|
|
111
|
+
return extract_file(content_or_path, type: type) if content_or_path.respond_to?(:read)
|
|
112
|
+
|
|
113
|
+
[content_or_path.to_s, nil]
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def extract_file(source, type:)
|
|
117
|
+
return [source.to_s, nil] unless defined?(Legion::Data::Extract)
|
|
118
|
+
|
|
119
|
+
result = Legion::Data::Extract.extract(source, type: type)
|
|
120
|
+
if result[:text]
|
|
121
|
+
[result[:text], result[:metadata]]
|
|
122
|
+
else
|
|
123
|
+
[nil, result]
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def metadata_to_tags(metadata)
|
|
128
|
+
tags = []
|
|
129
|
+
tags << metadata[:type].to_s if metadata[:type]
|
|
130
|
+
tags << "pages:#{metadata[:pages]}" if metadata[:pages]
|
|
131
|
+
tags
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def derive_lex_name
|
|
135
|
+
parts = self.class.name&.split('::')
|
|
136
|
+
parts && parts[2] ? parts[2].downcase : 'unknown'
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Helpers
|
|
6
|
+
module LLM
|
|
7
|
+
# Quick embed from any extension runner, forwarding all keyword arguments.
|
|
8
|
+
# Supports provider:, dimensions:, and any future parameters.
|
|
9
|
+
# @param text [String, Array<String>] text to embed
|
|
10
|
+
# @param kwargs [Hash] forwarded to Legion::LLM.embed (model:, provider:, dimensions:, etc.)
|
|
11
|
+
# @return [Hash] embedding result with :vector, :dimensions, :model, :provider
|
|
12
|
+
def llm_embed(text, **)
|
|
13
|
+
Legion::LLM.embed(text, **)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
data/lib/legion/readiness.rb
CHANGED
data/lib/legion/service.rb
CHANGED
|
@@ -98,6 +98,15 @@ module Legion
|
|
|
98
98
|
end
|
|
99
99
|
end
|
|
100
100
|
|
|
101
|
+
begin
|
|
102
|
+
setup_apollo
|
|
103
|
+
Legion::Readiness.mark_ready(:apollo)
|
|
104
|
+
rescue LoadError
|
|
105
|
+
Legion::Logging.info 'Legion::Apollo gem is not installed, starting without Apollo'
|
|
106
|
+
rescue StandardError => e
|
|
107
|
+
Legion::Logging.warn "Legion::Apollo failed to load: #{e.message}"
|
|
108
|
+
end
|
|
109
|
+
|
|
101
110
|
if gaia
|
|
102
111
|
begin
|
|
103
112
|
setup_gaia
|
|
@@ -317,6 +326,18 @@ module Legion
|
|
|
317
326
|
Legion::Logging.warn "Legion::Gaia failed to load: #{e.message}"
|
|
318
327
|
end
|
|
319
328
|
|
|
329
|
+
def setup_apollo
|
|
330
|
+
Legion::Logging.info 'Setting up Legion::Apollo'
|
|
331
|
+
require 'legion/apollo'
|
|
332
|
+
Legion::Apollo.start
|
|
333
|
+
Legion::Apollo::Local.start if defined?(Legion::Apollo::Local)
|
|
334
|
+
Legion::Logging.info 'Legion::Apollo started'
|
|
335
|
+
rescue LoadError
|
|
336
|
+
Legion::Logging.info 'Legion::Apollo gem is not installed, starting without Apollo'
|
|
337
|
+
rescue StandardError => e
|
|
338
|
+
Legion::Logging.warn "Legion::Apollo failed to load: #{e.message}"
|
|
339
|
+
end
|
|
340
|
+
|
|
320
341
|
def setup_transport
|
|
321
342
|
Legion::Logging.info 'Setting up Legion::Transport'
|
|
322
343
|
require 'legion/transport'
|
data/lib/legion/version.rb
CHANGED
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.5.
|
|
4
|
+
version: 1.5.18
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Esity
|
|
@@ -317,6 +317,20 @@ dependencies:
|
|
|
317
317
|
- - ">="
|
|
318
318
|
- !ruby/object:Gem::Version
|
|
319
319
|
version: 1.4.0
|
|
320
|
+
- !ruby/object:Gem::Dependency
|
|
321
|
+
name: legion-apollo
|
|
322
|
+
requirement: !ruby/object:Gem::Requirement
|
|
323
|
+
requirements:
|
|
324
|
+
- - ">="
|
|
325
|
+
- !ruby/object:Gem::Version
|
|
326
|
+
version: 0.2.1
|
|
327
|
+
type: :runtime
|
|
328
|
+
prerelease: false
|
|
329
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
330
|
+
requirements:
|
|
331
|
+
- - ">="
|
|
332
|
+
- !ruby/object:Gem::Version
|
|
333
|
+
version: 0.2.1
|
|
320
334
|
- !ruby/object:Gem::Dependency
|
|
321
335
|
name: legion-gaia
|
|
322
336
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -746,7 +760,9 @@ files:
|
|
|
746
760
|
- lib/legion/extensions/helpers/cache.rb
|
|
747
761
|
- lib/legion/extensions/helpers/core.rb
|
|
748
762
|
- lib/legion/extensions/helpers/data.rb
|
|
763
|
+
- lib/legion/extensions/helpers/knowledge.rb
|
|
749
764
|
- lib/legion/extensions/helpers/lex.rb
|
|
765
|
+
- lib/legion/extensions/helpers/llm.rb
|
|
750
766
|
- lib/legion/extensions/helpers/logger.rb
|
|
751
767
|
- lib/legion/extensions/helpers/segments.rb
|
|
752
768
|
- lib/legion/extensions/helpers/task.rb
|