lex-apollo 0.4.21 → 0.4.23

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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -0
  3. data/lib/legion/extensions/apollo/actors/corroboration_checker.rb +3 -1
  4. data/lib/legion/extensions/apollo/actors/decay.rb +3 -1
  5. data/lib/legion/extensions/apollo/actors/entity_watchdog.rb +10 -21
  6. data/lib/legion/extensions/apollo/actors/expertise_aggregator.rb +3 -1
  7. data/lib/legion/extensions/apollo/actors/gas_subscriber.rb +1 -1
  8. data/lib/legion/extensions/apollo/actors/ingest.rb +1 -1
  9. data/lib/legion/extensions/apollo/actors/query_responder.rb +1 -1
  10. data/lib/legion/extensions/apollo/actors/writeback_store.rb +1 -1
  11. data/lib/legion/extensions/apollo/actors/writeback_vectorize.rb +2 -2
  12. data/lib/legion/extensions/apollo/api.rb +56 -30
  13. data/lib/legion/extensions/apollo/gaia_integration.rb +13 -11
  14. data/lib/legion/extensions/apollo/helpers/capability.rb +12 -13
  15. data/lib/legion/extensions/apollo/helpers/confidence.rb +5 -8
  16. data/lib/legion/extensions/apollo/helpers/data_models.rb +61 -0
  17. data/lib/legion/extensions/apollo/helpers/entity_watchdog.rb +8 -15
  18. data/lib/legion/extensions/apollo/helpers/similarity.rb +5 -6
  19. data/lib/legion/extensions/apollo/helpers/writeback.rb +13 -14
  20. data/lib/legion/extensions/apollo/runners/expertise.rb +10 -8
  21. data/lib/legion/extensions/apollo/runners/gas.rb +18 -14
  22. data/lib/legion/extensions/apollo/runners/knowledge.rb +77 -62
  23. data/lib/legion/extensions/apollo/runners/maintenance.rb +5 -4
  24. data/lib/legion/extensions/apollo/runners/request.rb +7 -1
  25. data/lib/legion/extensions/apollo/version.rb +1 -1
  26. data/lib/legion/extensions/apollo.rb +96 -0
  27. data/spec/legion/extensions/apollo/actors/writeback_vectorize_spec.rb +3 -3
  28. data/spec/legion/extensions/apollo/api_spec.rb +84 -0
  29. data/spec/legion/extensions/apollo/helpers/capability_spec.rb +4 -4
  30. data/spec/legion/extensions/apollo/runners/gas_anticipate_spec.rb +0 -3
  31. data/spec/legion/extensions/apollo/runners/gas_relate_spec.rb +0 -4
  32. data/spec/legion/extensions/apollo/runners/gas_synthesize_spec.rb +0 -11
  33. data/spec/legion/extensions/apollo/runners/knowledge_spec.rb +19 -9
  34. data/spec/legion/extensions/apollo/runners/request_spec.rb +4 -4
  35. data/spec/spec_helper.rb +4 -0
  36. metadata +2 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 31dc882a8d5fd761bceaba21ff853a3d3dd898df9d4377464b72b110d306af0a
4
- data.tar.gz: 8dcfd2bc7c2557b298f3d503cc94b07e5a78b5a9777789f724dede41b9d0efdb
3
+ metadata.gz: af5cbbe35e69f28430c0c4d2862294024e465b79a7fdba279bb50562bc0d81d4
4
+ data.tar.gz: d2cf12984c06eb60752f7202935649a411377ca141e20d719d2faa2ec4c05b3b
5
5
  SHA512:
6
- metadata.gz: 5e066b3c62555b4866bfe99d6bed13a034e2b6b23f613ae7906e8eaebee90ecb2f9dd937a5e928dd8337af8945bfba9a1528deb4d3200eb82b8a92b081b6cf59
7
- data.tar.gz: dd1d625f4efc30df8951ee80db9ee0cfc1c25137bae5d8571dd09265bd5eec79add3482eba3cc88d77f43b052994597577abe634080cd995eb4dc0db7601458e
6
+ metadata.gz: a2bf398b3f6df58ec0e84f810f7ba4e48e68991c88f95ae8e5614ba4510ae7ab9be3994dc757f34138073797cb2af99c795d532f4e24dc9fb2f09ffa0b18d13f
7
+ data.tar.gz: fad944b5457ef0574bb53b1d88251d5d4dce1a70b3cbe8ffadb25b3938877a0170cd36adbf41705d066d84f7036043914efa6b7473db5999daf24badde8a7f5d
data/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.4.23] - 2026-05-06
4
+
5
+ ### Fixed
6
+ - Apollo data model access now prefers the namespaced `Legion::Data::Model::Apollo::*` classes introduced by the legion-data schema cleanup while retaining fallback compatibility with the legacy `ApolloEntry`, `ApolloRelation`, `ApolloAccessLog`, and `ApolloExpertise` constants.
7
+
8
+ ### Changed
9
+ - Apollo defaults are now declared directly in `Apollo.default_settings`, and Apollo helpers, runners, actors, and API paths use `Legion::Logging::Helper`, `Legion::Settings::Helper`, and `Legion::JSON` helper methods instead of direct logging/settings/JSON calls.
10
+
11
+ ## [0.4.22] - 2026-04-28
12
+
13
+ ### Fixed
14
+ - `/api/apollo/stats` now returns the health UI metrics Interlink expects: `recent_24h`, `avg_confidence`, and a synthesized `by_status["active"]` count for non-archived entries. This keeps the Knowledge Health cards populated instead of rendering missing values. Fixes #16.
15
+
3
16
  ## [0.4.21] - 2026-04-27
4
17
 
5
18
  ### Changed
@@ -8,9 +8,11 @@ module Legion
8
8
  module Apollo
9
9
  module Actor
10
10
  class CorroborationChecker < Legion::Extensions::Actors::Every
11
+ include Legion::Settings::Helper
12
+
11
13
  def runner_class = Legion::Extensions::Apollo::Runners::Maintenance
12
14
  def runner_function = 'check_corroboration'
13
- def time = (defined?(Legion::Settings) && Legion::Settings.dig(:apollo, :actors, :corroboration_interval)) || 900
15
+ def time = settings[:actors][:corroboration_interval]
14
16
  def run_now? = false
15
17
  def use_runner? = false
16
18
  def check_subtask? = false
@@ -8,9 +8,11 @@ module Legion
8
8
  module Apollo
9
9
  module Actor
10
10
  class Decay < Legion::Extensions::Actors::Every
11
+ include Legion::Settings::Helper
12
+
11
13
  def runner_class = Legion::Extensions::Apollo::Runners::Maintenance
12
14
  def runner_function = 'run_decay_cycle'
13
- def time = (defined?(Legion::Settings) && Legion::Settings.dig(:apollo, :actors, :decay_interval)) || 3600
15
+ def time = settings[:actors][:decay_interval]
14
16
  def run_now? = false
15
17
  def use_runner? = false
16
18
  def check_subtask? = false
@@ -11,6 +11,7 @@ module Legion
11
11
  class EntityWatchdog < Legion::Extensions::Actors::Every
12
12
  include Legion::Extensions::Apollo::Runners::Knowledge
13
13
  include Legion::Extensions::Apollo::Runners::EntityExtractor
14
+ include Legion::Settings::Helper
14
15
 
15
16
  DEDUP_THRESHOLD_DEFAULT = 0.92
16
17
  TASK_LOG_LOOKBACK_SECONDS = 300
@@ -18,7 +19,7 @@ module Legion
18
19
 
19
20
  def runner_class = self.class
20
21
  def runner_function = 'scan_and_ingest'
21
- def time = (defined?(Legion::Settings) && Legion::Settings.dig(:apollo, :actors, :entity_watchdog_interval)) || 120
22
+ def time = settings[:actors][:entity_watchdog_interval]
22
23
  def run_now? = false
23
24
  def use_runner? = false
24
25
  def check_subtask? = false
@@ -28,7 +29,7 @@ module Legion
28
29
  defined?(Legion::Extensions::Apollo::Runners::EntityExtractor) &&
29
30
  Legion.const_defined?(:Transport, false)
30
31
  rescue StandardError => e
31
- log.warn("EntityWatchdog enabled? check failed: #{e.message}")
32
+ handle_exception(e, level: :warn, operation: 'apollo.entity_watchdog.enabled')
32
33
  false
33
34
  end
34
35
 
@@ -64,8 +65,8 @@ module Legion
64
65
  def recent_task_log_texts
65
66
  return [] unless defined?(Legion::Data) && defined?(Legion::Data::Model::TaskLog)
66
67
 
67
- lookback = (defined?(Legion::Settings) && Legion::Settings.dig(:apollo, :entity_watchdog, :lookback_seconds)) || TASK_LOG_LOOKBACK_SECONDS
68
- log_limit = (defined?(Legion::Settings) && Legion::Settings.dig(:apollo, :entity_watchdog, :log_limit)) || TASK_LOG_LIMIT
68
+ lookback = settings[:entity_watchdog][:lookback_seconds]
69
+ log_limit = settings[:entity_watchdog][:log_limit]
69
70
  cutoff = Time.now - lookback
70
71
  logs = Legion::Data::Model::TaskLog
71
72
  .where { created_at >= cutoff }
@@ -76,7 +77,7 @@ module Legion
76
77
  log.debug("EntityWatchdog recent_task_log_texts lookback=#{lookback} limit=#{log_limit} raw=#{logs.size} unique=#{texts.size}")
77
78
  texts
78
79
  rescue StandardError => e
79
- log.warn("EntityWatchdog recent_task_log_texts failed: #{e.message}")
80
+ handle_exception(e, level: :warn, operation: 'apollo.entity_watchdog.recent_task_log_texts')
80
81
  []
81
82
  end
82
83
 
@@ -93,7 +94,7 @@ module Legion
93
94
  distance = closest[:distance].to_f
94
95
  distance <= (1.0 - dedup_similarity_threshold)
95
96
  rescue StandardError => e
96
- log.warn("EntityWatchdog entity_exists_in_apollo? failed: #{e.message}")
97
+ handle_exception(e, level: :warn, operation: 'apollo.entity_watchdog.entity_exists_in_apollo')
97
98
  false
98
99
  end
99
100
 
@@ -113,27 +114,15 @@ module Legion
113
114
  end
114
115
 
115
116
  def entity_types
116
- if defined?(Legion::Settings)
117
- types = Legion::Settings.dig(:apollo, :entity_watchdog, :types)
118
- return Array(types).map(&:to_s) if types
119
- end
120
- %w[person service repository concept]
117
+ Array(settings[:entity_watchdog][:types]).map(&:to_s)
121
118
  end
122
119
 
123
120
  def min_entity_confidence
124
- if defined?(Legion::Settings)
125
- val = Legion::Settings.dig(:apollo, :entity_watchdog, :min_confidence)
126
- return val.to_f if val
127
- end
128
- 0.7
121
+ settings[:entity_watchdog][:min_confidence].to_f
129
122
  end
130
123
 
131
124
  def dedup_similarity_threshold
132
- if defined?(Legion::Settings)
133
- val = Legion::Settings.dig(:apollo, :entity_watchdog, :dedup_threshold)
134
- return val.to_f if val
135
- end
136
- DEDUP_THRESHOLD_DEFAULT
125
+ settings[:entity_watchdog][:dedup_threshold].to_f
137
126
  end
138
127
  end
139
128
  end
@@ -8,9 +8,11 @@ module Legion
8
8
  module Apollo
9
9
  module Actor
10
10
  class ExpertiseAggregator < Legion::Extensions::Actors::Every
11
+ include Legion::Settings::Helper
12
+
11
13
  def runner_class = Legion::Extensions::Apollo::Runners::Expertise
12
14
  def runner_function = 'aggregate'
13
- def time = (defined?(Legion::Settings) && Legion::Settings.dig(:apollo, :actors, :expertise_interval)) || 1800
15
+ def time = settings[:actors][:expertise_interval]
14
16
  def run_now? = false
15
17
  def use_runner? = false
16
18
  def check_subtask? = false
@@ -17,7 +17,7 @@ module Legion
17
17
  defined?(Legion::Extensions::Apollo::Runners::Gas) &&
18
18
  Legion.const_defined?(:Transport, false)
19
19
  rescue StandardError => e
20
- log.warn("GasSubscriber enabled? check failed: #{e.message}")
20
+ handle_exception(e, level: :warn, operation: 'apollo.gas_subscriber.enabled')
21
21
  false
22
22
  end
23
23
 
@@ -16,7 +16,7 @@ module Legion
16
16
  defined?(Legion::Extensions::Apollo::Runners::Knowledge) &&
17
17
  Legion.const_defined?(:Transport, false)
18
18
  rescue StandardError => e
19
- log.warn("Ingest enabled? check failed: #{e.message}")
19
+ handle_exception(e, level: :warn, operation: 'apollo.ingest.enabled')
20
20
  false
21
21
  end
22
22
  end
@@ -16,7 +16,7 @@ module Legion
16
16
  defined?(Legion::Extensions::Apollo::Runners::Knowledge) &&
17
17
  Legion.const_defined?(:Transport, false)
18
18
  rescue StandardError => e
19
- log.warn("QueryResponder enabled? check failed: #{e.message}")
19
+ handle_exception(e, level: :warn, operation: 'apollo.query_responder.enabled')
20
20
  false
21
21
  end
22
22
  end
@@ -17,7 +17,7 @@ module Legion
17
17
  Legion.const_defined?(:Transport, false) &&
18
18
  Helpers::Capability.apollo_write_enabled?
19
19
  rescue StandardError => e
20
- log.warn("WritebackStore enabled? check failed: #{e.message}")
20
+ handle_exception(e, level: :warn, operation: 'apollo.writeback_store.enabled')
21
21
  false
22
22
  end
23
23
  end
@@ -15,7 +15,7 @@ module Legion
15
15
  def handle_vectorize(payload)
16
16
  payload = symbolize(payload)
17
17
  log.debug("WritebackVectorize handle_vectorize content_length=#{payload[:content].to_s.length} content_type=#{payload[:content_type] || 'nil'}")
18
- result = Legion::LLM::Embeddings.generate(text: payload[:content])
18
+ result = Legion::LLM::Call::Embeddings.generate(text: payload[:content])
19
19
  vector = result.is_a?(Hash) ? result[:vector] : result
20
20
  embedding = vector.is_a?(Array) && vector.any? ? vector : Array.new(1024, 0.0)
21
21
  log.debug("WritebackVectorize embedding_dimensions=#{embedding.length} vector_generated=#{vector.is_a?(Array) && vector.any?}")
@@ -41,7 +41,7 @@ module Legion
41
41
  def enabled? # rubocop:disable Legion/Extension/ActorEnabledSideEffects
42
42
  Legion.const_defined?(:Transport, false) && Helpers::Capability.can_embed?
43
43
  rescue StandardError => e
44
- log.warn("WritebackVectorize enabled? check failed: #{e.message}")
44
+ handle_exception(e, level: :warn, operation: 'apollo.writeback_vectorize.enabled')
45
45
  false
46
46
  end
47
47
 
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'sinatra/base' unless defined?(Sinatra)
4
- require 'json'
4
+ require 'legion/logging'
5
+ require 'legion/json'
6
+ require 'legion/extensions/apollo/helpers/data_models'
5
7
 
6
8
  module Legion
7
9
  module Extensions
@@ -9,18 +11,53 @@ module Legion
9
11
  class Api < Sinatra::Base
10
12
  set :host_authorization, permitted: :any
11
13
 
14
+ class << self
15
+ def stats_payload(now: Time.now)
16
+ return { error: 'apollo_data_not_available' } unless Helpers::DataModels.apollo_entry_available?
17
+
18
+ entries = Helpers::DataModels.apollo_entry
19
+ by_status = grouped_counts(entries, :status)
20
+ by_status['active'] = entries.exclude(status: 'archived').count
21
+
22
+ stats = {
23
+ total_entries: entries.count,
24
+ recent_24h: entries.where { created_at >= (now - 86_400) }.count,
25
+ avg_confidence: average_confidence(entries),
26
+ by_status: by_status,
27
+ by_content_type: grouped_counts(entries, :content_type)
28
+ }
29
+ stats[:total_relations] = Helpers::DataModels.apollo_relation.count if Helpers::DataModels.apollo_relation_available?
30
+ stats
31
+ end
32
+
33
+ private
34
+
35
+ def grouped_counts(entries, column)
36
+ entries.group_and_count(column).all.to_h { |row| [row[column].to_s, row[:count]] }
37
+ end
38
+
39
+ def average_confidence(entries)
40
+ avg = entries.avg(:confidence)
41
+ avg&.to_f&.round(3)
42
+ end
43
+ end
44
+
12
45
  before do
13
46
  content_type :json
14
47
  end
15
48
 
16
49
  helpers do
50
+ include Legion::Logging::Helper
51
+ include Legion::JSON::Helper
52
+
17
53
  def json_body
18
54
  body = request.body.read
19
55
  return {} if body.empty?
20
56
 
21
- ::JSON.parse(body, symbolize_names: true)
22
- rescue ::JSON::ParserError => e
23
- halt 400, { error: "invalid JSON: #{e.message}" }.to_json
57
+ json_parse(body)
58
+ rescue Legion::JSON::ParseError => e
59
+ handle_exception(e, level: :warn, operation: 'apollo.api.json_body')
60
+ halt 400, json_dump(error: "invalid JSON: #{e.message}")
24
61
  end
25
62
 
26
63
  def runner
@@ -42,14 +79,14 @@ module Legion
42
79
 
43
80
  # Health check
44
81
  get '/api/apollo/health' do
45
- available = defined?(Legion::Data::Model::ApolloEntry) ? true : false
46
- { status: available ? 'ok' : 'degraded', data_available: available }.to_json
82
+ available = Helpers::DataModels.apollo_entry_available?
83
+ json_dump(status: available ? 'ok' : 'degraded', data_available: available)
47
84
  end
48
85
 
49
86
  # Query knowledge (semantic search)
50
87
  post '/api/apollo/query' do
51
88
  req = json_body
52
- halt 400, { error: 'query is required' }.to_json unless req[:query]
89
+ halt 400, json_dump(error: 'query is required') unless req[:query]
53
90
 
54
91
  query_options = {
55
92
  query: req[:query],
@@ -63,14 +100,14 @@ module Legion
63
100
 
64
101
  result = runner.handle_query(**query_options)
65
102
  status result[:success] ? 200 : 500
66
- result.to_json
103
+ json_dump(result)
67
104
  end
68
105
 
69
106
  # Ingest knowledge
70
107
  post '/api/apollo/ingest' do
71
108
  req = json_body
72
- halt 400, { error: 'content is required' }.to_json unless req[:content]
73
- halt 400, { error: 'content_type is required' }.to_json unless req[:content_type]
109
+ halt 400, json_dump(error: 'content is required') unless req[:content]
110
+ halt 400, json_dump(error: 'content_type is required') unless req[:content_type]
74
111
 
75
112
  result = runner.handle_ingest(
76
113
  content: req[:content],
@@ -83,13 +120,13 @@ module Legion
83
120
  context: req[:context] || {}
84
121
  )
85
122
  status result[:success] ? 201 : 500
86
- result.to_json
123
+ json_dump(result)
87
124
  end
88
125
 
89
126
  # Graph traversal
90
127
  post '/api/apollo/traverse' do
91
128
  req = json_body
92
- halt 400, { error: 'entry_id is required' }.to_json unless req[:entry_id]
129
+ halt 400, json_dump(error: 'entry_id is required') unless req[:entry_id]
93
130
 
94
131
  result = runner.handle_traverse(
95
132
  entry_id: req[:entry_id],
@@ -98,13 +135,13 @@ module Legion
98
135
  agent_id: req[:agent_id] || 'api'
99
136
  )
100
137
  status result[:success] ? 200 : 500
101
- result.to_json
138
+ json_dump(result)
102
139
  end
103
140
 
104
141
  # Retrieve relevant (GAIA-compatible)
105
142
  post '/api/apollo/retrieve' do
106
143
  req = json_body
107
- halt 400, { error: 'query is required' }.to_json unless req[:query]
144
+ halt 400, json_dump(error: 'query is required') unless req[:query]
108
145
 
109
146
  result = runner.retrieve_relevant(
110
147
  query: req[:query],
@@ -114,7 +151,7 @@ module Legion
114
151
  domain: req[:domain]
115
152
  )
116
153
  status result[:success] ? 200 : 500
117
- result.to_json
154
+ json_dump(result)
118
155
  end
119
156
 
120
157
  # Deprecate entry
@@ -123,35 +160,24 @@ module Legion
123
160
  entry_id: params[:id],
124
161
  reason: json_body[:reason] || 'deprecated via API'
125
162
  )
126
- result.to_json
163
+ json_dump(result)
127
164
  end
128
165
 
129
166
  # Domains at risk — must be declared before /:agent_id to avoid routing conflict
130
167
  get '/api/apollo/expertise/at-risk' do
131
168
  result = expertise_runner.domains_at_risk
132
- result.to_json
169
+ json_dump(result)
133
170
  end
134
171
 
135
172
  # Expertise for an agent
136
173
  get '/api/apollo/expertise/:agent_id' do
137
174
  result = expertise_runner.agent_profile(agent_id: params[:agent_id])
138
- result.to_json
175
+ json_dump(result)
139
176
  end
140
177
 
141
178
  # Statistics
142
179
  get '/api/apollo/stats' do
143
- stats = {}
144
- if defined?(Legion::Data::Model::ApolloEntry)
145
- stats[:total_entries] = Legion::Data::Model::ApolloEntry.count
146
- stats[:by_status] = Legion::Data::Model::ApolloEntry.group_and_count(:status).all
147
- .to_h { |r| [r[:status], r[:count]] }
148
- stats[:by_content_type] = Legion::Data::Model::ApolloEntry.group_and_count(:content_type).all
149
- .to_h { |r| [r[:content_type], r[:count]] }
150
- stats[:total_relations] = Legion::Data::Model::ApolloRelation.count if defined?(Legion::Data::Model::ApolloRelation)
151
- else
152
- stats[:error] = 'apollo_data_not_available'
153
- end
154
- stats.to_json
180
+ json_dump(self.class.stats_payload)
155
181
  end
156
182
  end
157
183
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'helpers/data_models'
4
+
3
5
  module Legion
4
6
  module Extensions
5
7
  module Apollo
@@ -27,13 +29,13 @@ module Legion
27
29
  end
28
30
 
29
31
  def handle_mesh_departure(agent_id:)
30
- return nil unless defined?(Legion::Data::Model::ApolloExpertise)
32
+ return nil unless Helpers::DataModels.apollo_expertise_available?
31
33
 
32
- sole_expert_domains = Legion::Data::Model::ApolloExpertise
33
- .where(agent_id: agent_id)
34
- .all
35
- .select { |e| sole_expert?(e.domain, agent_id) }
36
- .map(&:domain)
34
+ sole_expert_domains = Helpers::DataModels.apollo_expertise
35
+ .where(agent_id: agent_id)
36
+ .all
37
+ .select { |e| sole_expert?(e.domain, agent_id) }
38
+ .map(&:domain)
37
39
 
38
40
  return nil if sole_expert_domains.empty?
39
41
 
@@ -48,12 +50,12 @@ module Legion
48
50
  private
49
51
 
50
52
  def sole_expert?(domain, agent_id)
51
- return false unless defined?(Legion::Data::Model::ApolloExpertise)
53
+ return false unless Helpers::DataModels.apollo_expertise_available?
52
54
 
53
- count = Legion::Data::Model::ApolloExpertise
54
- .where(domain: domain)
55
- .exclude(agent_id: agent_id)
56
- .count
55
+ count = Helpers::DataModels.apollo_expertise
56
+ .where(domain: domain)
57
+ .exclude(agent_id: agent_id)
58
+ .count
57
59
  count.zero?
58
60
  end
59
61
  end
@@ -5,20 +5,19 @@ module Legion
5
5
  module Apollo
6
6
  module Helpers
7
7
  module Capability
8
+ extend Legion::Logging::Helper
9
+ extend Legion::Settings::Helper
10
+
8
11
  EMBEDDING_MODELS = %w[mxbai-embed-large bge-large snowflake-arctic-embed].freeze
9
12
 
10
13
  module_function
11
14
 
12
- def log
13
- Legion::Logging
14
- end
15
-
16
15
  def can_embed?
17
16
  return false unless defined?(Legion::LLM) && Legion::LLM.started?
18
17
 
19
18
  ollama_embedding_available? || cloud_embedding_configured?
20
19
  rescue StandardError => e
21
- log.warn("Apollo Capability.can_embed? failed: #{e.message}")
20
+ handle_exception(e, level: :warn, operation: 'apollo.capability.can_embed')
22
21
  false
23
22
  end
24
23
 
@@ -28,14 +27,14 @@ module Legion
28
27
 
29
28
  check_db_write_privilege
30
29
  rescue StandardError => e
31
- log.warn("Apollo Capability.can_write? failed: #{e.message}")
30
+ handle_exception(e, level: :warn, operation: 'apollo.capability.can_write')
32
31
  false
33
32
  end
34
33
 
35
34
  def apollo_write_enabled?
36
- Legion::Settings.dig(:data, :apollo_write) == true
35
+ settings[:data][:apollo_write] == true
37
36
  rescue StandardError => e
38
- log.warn("Apollo Capability.apollo_write_enabled? failed: #{e.message}")
37
+ handle_exception(e, level: :warn, operation: 'apollo.capability.apollo_write_enabled')
39
38
  false
40
39
  end
41
40
 
@@ -44,16 +43,16 @@ module Legion
44
43
 
45
44
  EMBEDDING_MODELS.any? { |m| Legion::LLM::Discovery::Ollama.model_available?(m) }
46
45
  rescue StandardError => e
47
- log.warn("Apollo Capability.ollama_embedding_available? failed: #{e.message}")
46
+ handle_exception(e, level: :warn, operation: 'apollo.capability.ollama_embedding_available')
48
47
  false
49
48
  end
50
49
 
51
50
  def cloud_embedding_configured?
52
- provider = Legion::Settings.dig(:apollo, :embedding, :provider)
53
- model = Legion::Settings.dig(:apollo, :embedding, :model)
51
+ provider = settings[:embedding][:provider]
52
+ model = settings[:embedding][:model]
54
53
  !provider.nil? && !model.nil?
55
54
  rescue StandardError => e
56
- log.warn("Apollo Capability.cloud_embedding_configured? failed: #{e.message}")
55
+ handle_exception(e, level: :warn, operation: 'apollo.capability.cloud_embedding_configured')
57
56
  false
58
57
  end
59
58
 
@@ -64,7 +63,7 @@ module Legion
64
63
  .fetch("SELECT has_table_privilege(current_user, 'apollo_entries', 'INSERT') AS can_insert")
65
64
  .first[:can_insert] == true
66
65
  rescue StandardError => e
67
- log.warn("Apollo Capability.check_db_write_privilege failed: #{e.message}")
66
+ handle_exception(e, level: :warn, operation: 'apollo.capability.check_db_write_privilege')
68
67
  @apollo_write_privilege = false
69
68
  end
70
69
 
@@ -5,6 +5,9 @@ module Legion
5
5
  module Apollo
6
6
  module Helpers
7
7
  module Confidence
8
+ extend Legion::Logging::Helper
9
+ extend Legion::Settings::Helper
10
+
8
11
  INITIAL_CONFIDENCE = 0.5
9
12
  CORROBORATION_BOOST = 0.3
10
13
  RETRIEVAL_BOOST = 0.02
@@ -21,16 +24,10 @@ module Legion
21
24
 
22
25
  module_function
23
26
 
24
- def log
25
- Legion::Logging
26
- end
27
-
28
27
  def apollo_setting(*keys, default:)
29
- return default unless defined?(Legion::Settings) && !Legion::Settings[:apollo].nil?
30
-
31
- Legion::Settings[:apollo].dig(*keys) || default
28
+ settings.dig(*keys)
32
29
  rescue StandardError => e
33
- log.warn("Apollo Confidence.apollo_setting failed: #{e.message}")
30
+ handle_exception(e, level: :warn, operation: 'apollo.confidence.apollo_setting', keys: keys)
34
31
  default
35
32
  end
36
33
 
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Apollo
6
+ module Helpers
7
+ module DataModels
8
+ class << self
9
+ def apollo_entry
10
+ namespaced_apollo_model(:Entry) || legacy_model(:ApolloEntry)
11
+ end
12
+
13
+ def apollo_relation
14
+ namespaced_apollo_model(:Relation) || legacy_model(:ApolloRelation)
15
+ end
16
+
17
+ def apollo_access_log
18
+ namespaced_apollo_model(:AccessLog) || legacy_model(:ApolloAccessLog)
19
+ end
20
+
21
+ def apollo_expertise
22
+ namespaced_apollo_model(:Expertise) || legacy_model(:ApolloExpertise)
23
+ end
24
+
25
+ def apollo_entry_available?
26
+ !apollo_entry.nil?
27
+ end
28
+
29
+ def apollo_relation_available?
30
+ !apollo_relation.nil?
31
+ end
32
+
33
+ def apollo_access_log_available?
34
+ !apollo_access_log.nil?
35
+ end
36
+
37
+ def apollo_expertise_available?
38
+ !apollo_expertise.nil?
39
+ end
40
+
41
+ private
42
+
43
+ def namespaced_apollo_model(name)
44
+ return nil unless defined?(Legion::Data::Model::Apollo)
45
+ return nil unless Legion::Data::Model::Apollo.const_defined?(name, false)
46
+
47
+ Legion::Data::Model::Apollo.const_get(name, false)
48
+ end
49
+
50
+ def legacy_model(name)
51
+ return nil unless defined?(Legion::Data::Model)
52
+ return nil unless Legion::Data::Model.const_defined?(name, false)
53
+
54
+ Legion::Data::Model.const_get(name, false)
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end