lex-apollo 0.4.9 → 0.4.14
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 +27 -0
- data/lib/legion/extensions/apollo/actors/entity_watchdog.rb +6 -3
- data/lib/legion/extensions/apollo/actors/gas_subscriber.rb +2 -1
- data/lib/legion/extensions/apollo/actors/ingest.rb +2 -1
- data/lib/legion/extensions/apollo/actors/query_responder.rb +2 -1
- data/lib/legion/extensions/apollo/actors/writeback_store.rb +2 -1
- data/lib/legion/extensions/apollo/actors/writeback_vectorize.rb +2 -1
- data/lib/legion/extensions/apollo/api.rb +2 -2
- data/lib/legion/extensions/apollo/helpers/capability.rb +20 -6
- data/lib/legion/extensions/apollo/helpers/confidence.rb +10 -1
- data/lib/legion/extensions/apollo/helpers/entity_watchdog.rb +9 -1
- data/lib/legion/extensions/apollo/helpers/similarity.rb +10 -1
- data/lib/legion/extensions/apollo/helpers/writeback.rb +19 -7
- data/lib/legion/extensions/apollo/runners/gas.rb +41 -18
- data/lib/legion/extensions/apollo/runners/knowledge.rb +11 -5
- data/lib/legion/extensions/apollo/version.rb +1 -1
- data/lib/legion/extensions/apollo.rb +4 -0
- 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: 5a299ad72e6776724cf5ee9c94d394618adcc130a4af35e205d4966d6f4079f0
|
|
4
|
+
data.tar.gz: 6cf9bee4d6a7a38dcc223442871c5760c4c62076bde2a7d1d5f4af674aa33f33
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 708fed8ac6cae84b333ddf1f4c0fe3a8889be2271f678e49017d590ffb6bb61593c9e286e6999ef521257a9a0e7aa0d7e54ed70b6bcb8b8064ddfddb85ffd1fb
|
|
7
|
+
data.tar.gz: 3c4cd4423c4a58f213b30e3709bbe6bf078a709faeb526f829f1b1b0e960d12c1d215b3be04309b714978e72b011a93f76f3ceee3fd7279c03397612dc13726e
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.4.14] - 2026-03-27
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- Replace `Legion::JSON.load` calls in `Runners::Gas` with `json_load` helper to satisfy CI Helper Migration lint
|
|
7
|
+
|
|
8
|
+
## [0.4.13] - 2026-03-27
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- Replace all `Legion::Logging.xxx(...)` calls in `lib/` with `log.xxx(...)` to satisfy CI Helper Migration lint check
|
|
12
|
+
- Add `log` module-function/class-method to `Runners::Gas`, `Helpers::Similarity`, `Helpers::Capability`, `Helpers::Confidence`, `Helpers::Writeback`, and `Helpers::EntityWatchdog`
|
|
13
|
+
- Instance methods in `Runners::Knowledge` use `log` via existing `Helpers::Lex` include
|
|
14
|
+
|
|
15
|
+
## [0.4.12] - 2026-03-27
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
- All bare `rescue` blocks in `lib/` now capture the exception as `=> e` and log `e.message` to satisfy the Rescue Logging lint rule
|
|
19
|
+
|
|
20
|
+
## [0.4.11] - 2026-03-27
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
- `handle_ingest`: made `content:` and `content_type:` optional with nil defaults, added `skip:` parameter for GAIA dream cycle phase wiring compatibility
|
|
24
|
+
|
|
25
|
+
## [0.4.10] - 2026-03-26
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
- set remote_invocable? false for local dispatch
|
|
29
|
+
|
|
3
30
|
## [0.4.9] - 2026-03-25
|
|
4
31
|
|
|
5
32
|
### Changed
|
|
@@ -27,7 +27,8 @@ module Legion
|
|
|
27
27
|
def enabled?
|
|
28
28
|
defined?(Legion::Extensions::Apollo::Runners::EntityExtractor) &&
|
|
29
29
|
defined?(Legion::Transport)
|
|
30
|
-
rescue StandardError
|
|
30
|
+
rescue StandardError => e
|
|
31
|
+
log.warn("EntityWatchdog enabled? check failed: #{e.message}")
|
|
31
32
|
false
|
|
32
33
|
end
|
|
33
34
|
|
|
@@ -71,7 +72,8 @@ module Legion
|
|
|
71
72
|
.limit(log_limit)
|
|
72
73
|
.select_map(:message)
|
|
73
74
|
logs.map(&:to_s).reject(&:empty?).uniq
|
|
74
|
-
rescue StandardError
|
|
75
|
+
rescue StandardError => e
|
|
76
|
+
log.warn("EntityWatchdog recent_task_log_texts failed: #{e.message}")
|
|
75
77
|
[]
|
|
76
78
|
end
|
|
77
79
|
|
|
@@ -87,7 +89,8 @@ module Legion
|
|
|
87
89
|
closest = result[:entries].first
|
|
88
90
|
distance = closest[:distance].to_f
|
|
89
91
|
distance <= (1.0 - dedup_similarity_threshold)
|
|
90
|
-
rescue StandardError
|
|
92
|
+
rescue StandardError => e
|
|
93
|
+
log.warn("EntityWatchdog entity_exists_in_apollo? failed: #{e.message}")
|
|
91
94
|
false
|
|
92
95
|
end
|
|
93
96
|
|
|
@@ -15,7 +15,8 @@ module Legion
|
|
|
15
15
|
def enabled?
|
|
16
16
|
defined?(Legion::Extensions::Apollo::Runners::Knowledge) &&
|
|
17
17
|
defined?(Legion::Transport)
|
|
18
|
-
rescue StandardError
|
|
18
|
+
rescue StandardError => e
|
|
19
|
+
log.warn("QueryResponder enabled? check failed: #{e.message}")
|
|
19
20
|
false
|
|
20
21
|
end
|
|
21
22
|
end
|
|
@@ -16,7 +16,8 @@ module Legion
|
|
|
16
16
|
defined?(Legion::Extensions::Apollo::Runners::Knowledge) &&
|
|
17
17
|
defined?(Legion::Transport) &&
|
|
18
18
|
Helpers::Capability.apollo_write_enabled?
|
|
19
|
-
rescue StandardError
|
|
19
|
+
rescue StandardError => e
|
|
20
|
+
log.warn("WritebackStore enabled? check failed: #{e.message}")
|
|
20
21
|
false
|
|
21
22
|
end
|
|
22
23
|
end
|
|
@@ -19,8 +19,8 @@ module Legion
|
|
|
19
19
|
return {} if body.empty?
|
|
20
20
|
|
|
21
21
|
::JSON.parse(body, symbolize_names: true)
|
|
22
|
-
rescue ::JSON::ParserError
|
|
23
|
-
halt 400, { error:
|
|
22
|
+
rescue ::JSON::ParserError => e
|
|
23
|
+
halt 400, { error: "invalid JSON: #{e.message}" }.to_json
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def runner
|
|
@@ -9,11 +9,20 @@ module Legion
|
|
|
9
9
|
|
|
10
10
|
module_function
|
|
11
11
|
|
|
12
|
+
def log
|
|
13
|
+
return Legion::Logging if defined?(Legion::Logging)
|
|
14
|
+
|
|
15
|
+
@log ||= Object.new.tap do |nl|
|
|
16
|
+
%i[debug info warn error fatal].each { |m| nl.define_singleton_method(m) { |*| nil } }
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
12
20
|
def can_embed?
|
|
13
21
|
return false unless defined?(Legion::LLM) && Legion::LLM.started?
|
|
14
22
|
|
|
15
23
|
ollama_embedding_available? || cloud_embedding_configured?
|
|
16
|
-
rescue StandardError
|
|
24
|
+
rescue StandardError => e
|
|
25
|
+
log.warn("Apollo Capability.can_embed? failed: #{e.message}")
|
|
17
26
|
false
|
|
18
27
|
end
|
|
19
28
|
|
|
@@ -22,13 +31,15 @@ module Legion
|
|
|
22
31
|
return false unless defined?(Legion::Data) && Legion::Data.connected?
|
|
23
32
|
|
|
24
33
|
check_db_write_privilege
|
|
25
|
-
rescue StandardError
|
|
34
|
+
rescue StandardError => e
|
|
35
|
+
log.warn("Apollo Capability.can_write? failed: #{e.message}")
|
|
26
36
|
false
|
|
27
37
|
end
|
|
28
38
|
|
|
29
39
|
def apollo_write_enabled?
|
|
30
40
|
Legion::Settings.dig(:data, :apollo_write) == true
|
|
31
|
-
rescue StandardError
|
|
41
|
+
rescue StandardError => e
|
|
42
|
+
log.warn("Apollo Capability.apollo_write_enabled? failed: #{e.message}")
|
|
32
43
|
false
|
|
33
44
|
end
|
|
34
45
|
|
|
@@ -36,7 +47,8 @@ module Legion
|
|
|
36
47
|
return false unless defined?(Legion::LLM::Discovery::Ollama)
|
|
37
48
|
|
|
38
49
|
EMBEDDING_MODELS.any? { |m| Legion::LLM::Discovery::Ollama.model_available?(m) }
|
|
39
|
-
rescue StandardError
|
|
50
|
+
rescue StandardError => e
|
|
51
|
+
log.warn("Apollo Capability.ollama_embedding_available? failed: #{e.message}")
|
|
40
52
|
false
|
|
41
53
|
end
|
|
42
54
|
|
|
@@ -44,7 +56,8 @@ module Legion
|
|
|
44
56
|
provider = Legion::Settings.dig(:apollo, :embedding, :provider)
|
|
45
57
|
model = Legion::Settings.dig(:apollo, :embedding, :model)
|
|
46
58
|
!provider.nil? && !model.nil?
|
|
47
|
-
rescue StandardError
|
|
59
|
+
rescue StandardError => e
|
|
60
|
+
log.warn("Apollo Capability.cloud_embedding_configured? failed: #{e.message}")
|
|
48
61
|
false
|
|
49
62
|
end
|
|
50
63
|
|
|
@@ -54,7 +67,8 @@ module Legion
|
|
|
54
67
|
@apollo_write_privilege = Legion::Data.connection
|
|
55
68
|
.fetch("SELECT has_table_privilege(current_user, 'apollo_entries', 'INSERT') AS can_insert")
|
|
56
69
|
.first[:can_insert] == true
|
|
57
|
-
rescue StandardError
|
|
70
|
+
rescue StandardError => e
|
|
71
|
+
log.warn("Apollo Capability.check_db_write_privilege failed: #{e.message}")
|
|
58
72
|
@apollo_write_privilege = false
|
|
59
73
|
end
|
|
60
74
|
|
|
@@ -20,11 +20,20 @@ module Legion
|
|
|
20
20
|
|
|
21
21
|
module_function
|
|
22
22
|
|
|
23
|
+
def log
|
|
24
|
+
return Legion::Logging if defined?(Legion::Logging)
|
|
25
|
+
|
|
26
|
+
@log ||= Object.new.tap do |nl|
|
|
27
|
+
%i[debug info warn error fatal].each { |m| nl.define_singleton_method(m) { |*| nil } }
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
23
31
|
def apollo_setting(*keys, default:)
|
|
24
32
|
return default unless defined?(Legion::Settings) && !Legion::Settings[:apollo].nil?
|
|
25
33
|
|
|
26
34
|
Legion::Settings[:apollo].dig(*keys) || default
|
|
27
|
-
rescue StandardError
|
|
35
|
+
rescue StandardError => e
|
|
36
|
+
log.warn("Apollo Confidence.apollo_setting failed: #{e.message}")
|
|
28
37
|
default
|
|
29
38
|
end
|
|
30
39
|
|
|
@@ -12,6 +12,14 @@ module Legion
|
|
|
12
12
|
}.freeze
|
|
13
13
|
|
|
14
14
|
class << self
|
|
15
|
+
def log
|
|
16
|
+
return Legion::Logging if defined?(Legion::Logging)
|
|
17
|
+
|
|
18
|
+
@log ||= Object.new.tap do |nl|
|
|
19
|
+
%i[debug info warn error fatal].each { |m| nl.define_singleton_method(m) { |*| nil } }
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
15
23
|
def detect_entities(text:, types: nil)
|
|
16
24
|
return [] if text.nil? || text.empty?
|
|
17
25
|
|
|
@@ -84,7 +92,7 @@ module Legion
|
|
|
84
92
|
def create_candidate(entity, _source_context)
|
|
85
93
|
return unless defined?(Runners::Knowledge)
|
|
86
94
|
|
|
87
|
-
|
|
95
|
+
log.debug "[entity_watchdog] candidate: #{entity[:type]}=#{entity[:value]}"
|
|
88
96
|
end
|
|
89
97
|
end
|
|
90
98
|
end
|
|
@@ -9,6 +9,14 @@ module Legion
|
|
|
9
9
|
module Similarity
|
|
10
10
|
module_function
|
|
11
11
|
|
|
12
|
+
def log
|
|
13
|
+
return Legion::Logging if defined?(Legion::Logging)
|
|
14
|
+
|
|
15
|
+
@log ||= Object.new.tap do |nl|
|
|
16
|
+
%i[debug info warn error fatal].each { |m| nl.define_singleton_method(m) { |*| nil } }
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
12
20
|
def cosine_similarity(vec_a:, vec_b:, **)
|
|
13
21
|
vec_a = parse_vector(vec_a)
|
|
14
22
|
vec_b = parse_vector(vec_b)
|
|
@@ -27,7 +35,8 @@ module Legion
|
|
|
27
35
|
return nil unless vec.is_a?(String)
|
|
28
36
|
|
|
29
37
|
::JSON.parse(vec)
|
|
30
|
-
rescue StandardError
|
|
38
|
+
rescue StandardError => e
|
|
39
|
+
log.warn("Apollo Similarity.parse_vector failed: #{e.message}")
|
|
31
40
|
nil
|
|
32
41
|
end
|
|
33
42
|
|
|
@@ -14,6 +14,14 @@ module Legion
|
|
|
14
14
|
|
|
15
15
|
module_function
|
|
16
16
|
|
|
17
|
+
def log
|
|
18
|
+
return Legion::Logging if defined?(Legion::Logging)
|
|
19
|
+
|
|
20
|
+
@log ||= Object.new.tap do |nl|
|
|
21
|
+
%i[debug info warn error fatal].each { |m| nl.define_singleton_method(m) { |*| nil } }
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
17
25
|
def evaluate_and_route(request:, response:, enrichments: {})
|
|
18
26
|
return unless writeback_enabled?
|
|
19
27
|
return unless should_capture?(request, response, enrichments)
|
|
@@ -21,7 +29,7 @@ module Legion
|
|
|
21
29
|
payload = build_payload(request: request, response: response)
|
|
22
30
|
route_payload(payload)
|
|
23
31
|
rescue StandardError => e
|
|
24
|
-
|
|
32
|
+
log.warn("apollo writeback failed: #{e.message}")
|
|
25
33
|
end
|
|
26
34
|
|
|
27
35
|
def should_capture?(_request, response, enrichments)
|
|
@@ -83,7 +91,7 @@ module Legion
|
|
|
83
91
|
Runners::Knowledge.handle_ingest(**payload)
|
|
84
92
|
end
|
|
85
93
|
rescue StandardError => e
|
|
86
|
-
|
|
94
|
+
log.warn("apollo direct write failed, falling back to transport: #{e.message}")
|
|
87
95
|
publish_to_transport(payload, has_embedding: !payload[:embedding].nil?)
|
|
88
96
|
end
|
|
89
97
|
|
|
@@ -94,18 +102,20 @@ module Legion
|
|
|
94
102
|
**payload, has_embedding: has_embedding
|
|
95
103
|
).publish
|
|
96
104
|
rescue StandardError => e
|
|
97
|
-
|
|
105
|
+
log.warn("apollo writeback publish failed: #{e.message}")
|
|
98
106
|
end
|
|
99
107
|
|
|
100
108
|
def writeback_enabled?
|
|
101
109
|
Legion::Settings.dig(:apollo, :writeback, :enabled) != false
|
|
102
|
-
rescue StandardError
|
|
110
|
+
rescue StandardError => e
|
|
111
|
+
log.warn("Apollo Writeback.writeback_enabled? failed: #{e.message}")
|
|
103
112
|
true
|
|
104
113
|
end
|
|
105
114
|
|
|
106
115
|
def min_content_length
|
|
107
116
|
Legion::Settings.dig(:apollo, :writeback, :min_content_length) || MIN_CONTENT_LENGTH
|
|
108
|
-
rescue StandardError
|
|
117
|
+
rescue StandardError => e
|
|
118
|
+
log.warn("Apollo Writeback.min_content_length failed: #{e.message}")
|
|
109
119
|
MIN_CONTENT_LENGTH
|
|
110
120
|
end
|
|
111
121
|
|
|
@@ -125,7 +135,8 @@ module Legion
|
|
|
125
135
|
return 'unknown' unless request.respond_to?(:caller) && request.caller.is_a?(Hash)
|
|
126
136
|
|
|
127
137
|
request.caller.dig(:requested_by, :identity) || 'unknown'
|
|
128
|
-
rescue StandardError
|
|
138
|
+
rescue StandardError => e
|
|
139
|
+
log.warn("Apollo Writeback.extract_identity failed: #{e.message}")
|
|
129
140
|
'unknown'
|
|
130
141
|
end
|
|
131
142
|
|
|
@@ -134,7 +145,8 @@ module Legion
|
|
|
134
145
|
|
|
135
146
|
user_msgs = Array(request.messages).select { |m| m[:role] == 'user' || m['role'] == 'user' }
|
|
136
147
|
(user_msgs.last || {})[:content] || ''
|
|
137
|
-
rescue StandardError
|
|
148
|
+
rescue StandardError => e
|
|
149
|
+
log.warn("Apollo Writeback.extract_user_query failed: #{e.message}")
|
|
138
150
|
''
|
|
139
151
|
end
|
|
140
152
|
|
|
@@ -16,6 +16,18 @@ module Legion
|
|
|
16
16
|
|
|
17
17
|
module_function
|
|
18
18
|
|
|
19
|
+
def log
|
|
20
|
+
return Legion::Logging if defined?(Legion::Logging)
|
|
21
|
+
|
|
22
|
+
@log ||= Object.new.tap do |nl|
|
|
23
|
+
%i[debug info warn error fatal].each { |m| nl.define_singleton_method(m) { |*| nil } }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def json_load(str)
|
|
28
|
+
::JSON.parse(str, symbolize_names: true)
|
|
29
|
+
end
|
|
30
|
+
|
|
19
31
|
def relate_confidence_gate = Helpers::Confidence.apollo_setting(:gas, :relate_confidence_gate, default: RELATE_CONFIDENCE_GATE)
|
|
20
32
|
def synthesis_confidence_cap = Helpers::Confidence.apollo_setting(:gas, :synthesis_confidence_cap, default: SYNTHESIS_CONFIDENCE_CAP)
|
|
21
33
|
def max_anticipations = Helpers::Confidence.apollo_setting(:gas, :max_anticipations, default: MAX_ANTICIPATIONS)
|
|
@@ -42,7 +54,7 @@ module Legion
|
|
|
42
54
|
anticipations: anticipations.length
|
|
43
55
|
}
|
|
44
56
|
rescue StandardError => e
|
|
45
|
-
|
|
57
|
+
log.warn("GAS pipeline error: #{e.message}")
|
|
46
58
|
{ phases_completed: 0, error: e.message }
|
|
47
59
|
end
|
|
48
60
|
|
|
@@ -68,7 +80,8 @@ module Legion
|
|
|
68
80
|
|
|
69
81
|
result = Runners::EntityExtractor.extract_entities(text: audit_event[:response_content])
|
|
70
82
|
result[:success] ? (result[:entities] || []) : []
|
|
71
|
-
rescue StandardError
|
|
83
|
+
rescue StandardError => e
|
|
84
|
+
log.warn("GAS phase_extract failed: #{e.message}")
|
|
72
85
|
[]
|
|
73
86
|
end
|
|
74
87
|
|
|
@@ -95,7 +108,8 @@ module Legion
|
|
|
95
108
|
return [] unless llm_available?
|
|
96
109
|
|
|
97
110
|
llm_synthesize(facts)
|
|
98
|
-
rescue StandardError
|
|
111
|
+
rescue StandardError => e
|
|
112
|
+
log.warn("GAS phase_synthesize failed: #{e.message}")
|
|
99
113
|
[]
|
|
100
114
|
end
|
|
101
115
|
|
|
@@ -116,7 +130,7 @@ module Legion
|
|
|
116
130
|
)
|
|
117
131
|
deposited += 1
|
|
118
132
|
rescue StandardError => e
|
|
119
|
-
|
|
133
|
+
log.warn("GAS deposit error: #{e.message}")
|
|
120
134
|
end
|
|
121
135
|
{ deposited: deposited }
|
|
122
136
|
end
|
|
@@ -127,7 +141,8 @@ module Legion
|
|
|
127
141
|
return [] unless llm_available?
|
|
128
142
|
|
|
129
143
|
llm_anticipate(facts)
|
|
130
|
-
rescue StandardError
|
|
144
|
+
rescue StandardError => e
|
|
145
|
+
log.warn("GAS phase_anticipate failed: #{e.message}")
|
|
131
146
|
[]
|
|
132
147
|
end
|
|
133
148
|
|
|
@@ -138,7 +153,8 @@ module Legion
|
|
|
138
153
|
facts.each do |fact|
|
|
139
154
|
result = Runners::Knowledge.retrieve_relevant(query: fact[:content], limit: lim, min_confidence: min_conf)
|
|
140
155
|
entries.concat(result[:entries]) if result[:success] && result[:entries]&.any?
|
|
141
|
-
rescue StandardError
|
|
156
|
+
rescue StandardError => e
|
|
157
|
+
log.warn("GAS fetch_similar_entries failed for fact: #{e.message}")
|
|
142
158
|
next
|
|
143
159
|
end
|
|
144
160
|
entries.uniq { |e| e[:id] }
|
|
@@ -151,8 +167,9 @@ module Legion
|
|
|
151
167
|
else
|
|
152
168
|
{ from_content: fact[:content], to_id: entry[:id], relation_type: 'similar_to', confidence: fb_conf }
|
|
153
169
|
end
|
|
154
|
-
rescue StandardError
|
|
155
|
-
|
|
170
|
+
rescue StandardError => e
|
|
171
|
+
log.warn("GAS classify_relation failed: #{e.message}")
|
|
172
|
+
{ from_content: fact[:content], to_id: entry[:id], relation_type: 'similar_to', confidence: fallback_confidence }
|
|
156
173
|
end
|
|
157
174
|
|
|
158
175
|
def llm_classify_relation(fact, entry)
|
|
@@ -189,7 +206,7 @@ module Legion
|
|
|
189
206
|
)
|
|
190
207
|
|
|
191
208
|
content = result.respond_to?(:message) ? result.message[:content] : result.to_s
|
|
192
|
-
parsed =
|
|
209
|
+
parsed = json_load(content)
|
|
193
210
|
rels = parsed.is_a?(Hash) ? (parsed[:relations] || parsed['relations'] || []) : []
|
|
194
211
|
best = rels.max_by { |r| r[:confidence] || r['confidence'] || 0 }
|
|
195
212
|
|
|
@@ -200,7 +217,8 @@ module Legion
|
|
|
200
217
|
return fallback_relation(fact, entry) if conf < relate_confidence_gate || !RELATION_TYPES.include?(rtype)
|
|
201
218
|
|
|
202
219
|
{ from_content: fact[:content], to_id: entry[:id], relation_type: rtype, confidence: conf }
|
|
203
|
-
rescue StandardError
|
|
220
|
+
rescue StandardError => e
|
|
221
|
+
log.warn("GAS llm_classify_relation failed: #{e.message}")
|
|
204
222
|
fallback_relation(fact, entry)
|
|
205
223
|
end
|
|
206
224
|
|
|
@@ -245,11 +263,12 @@ module Legion
|
|
|
245
263
|
)
|
|
246
264
|
|
|
247
265
|
content = result.respond_to?(:message) ? result.message[:content] : result.to_s
|
|
248
|
-
parsed =
|
|
266
|
+
parsed = json_load(content)
|
|
249
267
|
items = parsed.is_a?(Hash) ? (parsed[:synthesis] || parsed['synthesis'] || []) : []
|
|
250
268
|
|
|
251
269
|
items.map { |item| build_synthesis_entry(item, facts) }
|
|
252
|
-
rescue StandardError
|
|
270
|
+
rescue StandardError => e
|
|
271
|
+
log.warn("GAS llm_synthesize failed: #{e.message}")
|
|
253
272
|
[]
|
|
254
273
|
end
|
|
255
274
|
|
|
@@ -300,7 +319,7 @@ module Legion
|
|
|
300
319
|
)
|
|
301
320
|
|
|
302
321
|
content = result.respond_to?(:message) ? result.message[:content] : result.to_s
|
|
303
|
-
parsed =
|
|
322
|
+
parsed = json_load(content)
|
|
304
323
|
questions = parsed.is_a?(Hash) ? (parsed[:questions] || parsed['questions'] || []) : []
|
|
305
324
|
questions = questions.first(max_anticipations)
|
|
306
325
|
|
|
@@ -308,7 +327,8 @@ module Legion
|
|
|
308
327
|
promote_to_pattern_store(question: q, facts: facts)
|
|
309
328
|
{ question: q }
|
|
310
329
|
end
|
|
311
|
-
rescue StandardError
|
|
330
|
+
rescue StandardError => e
|
|
331
|
+
log.warn("GAS llm_anticipate failed: #{e.message}")
|
|
312
332
|
[]
|
|
313
333
|
end
|
|
314
334
|
|
|
@@ -320,13 +340,15 @@ module Legion
|
|
|
320
340
|
resolution: { source: 'gas_anticipate', facts: facts.map { |f| f[:content] } },
|
|
321
341
|
confidence: fallback_confidence
|
|
322
342
|
)
|
|
323
|
-
rescue StandardError
|
|
343
|
+
rescue StandardError => e
|
|
344
|
+
log.warn("GAS promote_to_pattern_store failed: #{e.message}")
|
|
324
345
|
nil
|
|
325
346
|
end
|
|
326
347
|
|
|
327
348
|
def llm_available?
|
|
328
349
|
defined?(Legion::LLM::Pipeline::GaiaCaller)
|
|
329
|
-
rescue StandardError
|
|
350
|
+
rescue StandardError => e
|
|
351
|
+
log.warn("GAS llm_available? check failed: #{e.message}")
|
|
330
352
|
false
|
|
331
353
|
end
|
|
332
354
|
|
|
@@ -365,7 +387,7 @@ module Legion
|
|
|
365
387
|
)
|
|
366
388
|
|
|
367
389
|
content = result.respond_to?(:message) ? result.message[:content] : result.to_s
|
|
368
|
-
parsed =
|
|
390
|
+
parsed = json_load(content)
|
|
369
391
|
facts_array = parsed.is_a?(Hash) ? (parsed[:facts] || parsed['facts'] || []) : Array(parsed)
|
|
370
392
|
facts_array.map do |f|
|
|
371
393
|
{
|
|
@@ -373,7 +395,8 @@ module Legion
|
|
|
373
395
|
content_type: (f[:content_type] || f['content_type'] || 'fact').to_sym
|
|
374
396
|
}
|
|
375
397
|
end
|
|
376
|
-
rescue StandardError
|
|
398
|
+
rescue StandardError => e
|
|
399
|
+
log.warn("GAS llm_comprehend failed: #{e.message}")
|
|
377
400
|
mechanical_comprehend(messages, response)
|
|
378
401
|
end
|
|
379
402
|
end
|
|
@@ -58,7 +58,10 @@ module Legion
|
|
|
58
58
|
}
|
|
59
59
|
end
|
|
60
60
|
|
|
61
|
-
def handle_ingest(content
|
|
61
|
+
def handle_ingest(content: nil, content_type: nil, tags: [], source_agent: 'unknown', source_provider: nil, source_channel: nil, knowledge_domain: nil, submitted_by: nil, submitted_from: nil, content_hash: nil, context: {}, skip: false, **) # rubocop:disable Metrics/ParameterLists, Layout/LineLength, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
|
62
|
+
return { status: :skipped } if skip
|
|
63
|
+
return { success: false, error: 'content is required' } if content.nil? || content.to_s.strip.empty?
|
|
64
|
+
return { success: false, error: 'content_type is required' } if content_type.nil?
|
|
62
65
|
return { success: false, error: 'apollo_data_not_available' } unless defined?(Legion::Data::Model::ApolloEntry)
|
|
63
66
|
|
|
64
67
|
# Content hash dedup
|
|
@@ -214,7 +217,7 @@ module Legion
|
|
|
214
217
|
redistributed += 1
|
|
215
218
|
end
|
|
216
219
|
|
|
217
|
-
|
|
220
|
+
log.info("[apollo] redistributed #{redistributed} entries from departing agent=#{agent_id}")
|
|
218
221
|
{ success: true, redistributed: redistributed, agent_id: agent_id }
|
|
219
222
|
rescue Sequel::Error => e
|
|
220
223
|
{ success: false, error: e.message }
|
|
@@ -313,7 +316,8 @@ module Legion
|
|
|
313
316
|
result = Legion::LLM::Embeddings.generate(text: text)
|
|
314
317
|
vector = result.is_a?(Hash) ? result[:vector] : result
|
|
315
318
|
vector.is_a?(Array) && vector.any? ? vector : Array.new(1024, 0.0)
|
|
316
|
-
rescue StandardError
|
|
319
|
+
rescue StandardError => e
|
|
320
|
+
log.warn("Apollo Knowledge.embed_text failed: #{e.message}")
|
|
317
321
|
Array.new(1024, 0.0)
|
|
318
322
|
end
|
|
319
323
|
|
|
@@ -363,7 +367,8 @@ module Legion
|
|
|
363
367
|
contradictions << existing[:id]
|
|
364
368
|
end
|
|
365
369
|
contradictions
|
|
366
|
-
rescue Sequel::Error
|
|
370
|
+
rescue Sequel::Error => e
|
|
371
|
+
log.warn("Apollo Knowledge.detect_contradictions failed: #{e.message}")
|
|
367
372
|
[]
|
|
368
373
|
end
|
|
369
374
|
|
|
@@ -379,7 +384,8 @@ module Legion
|
|
|
379
384
|
caller: { extension: 'lex-apollo', runner: 'knowledge' }
|
|
380
385
|
)
|
|
381
386
|
result[:data]&.dig(:contradicts) == true
|
|
382
|
-
rescue StandardError
|
|
387
|
+
rescue StandardError => e
|
|
388
|
+
log.warn("Apollo Knowledge.llm_detects_conflict? failed: #{e.message}")
|
|
383
389
|
false
|
|
384
390
|
end
|
|
385
391
|
|