lex-apollo 0.4.23 → 0.4.24
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 +8 -0
- data/lib/legion/extensions/apollo/gaia_integration.rb +3 -2
- data/lib/legion/extensions/apollo/helpers/capability.rb +7 -4
- data/lib/legion/extensions/apollo/runners/gas.rb +29 -13
- data/lib/legion/extensions/apollo/runners/knowledge.rb +19 -19
- data/lib/legion/extensions/apollo/runners/maintenance.rb +4 -3
- data/lib/legion/extensions/apollo/version.rb +1 -1
- data/spec/legion/extensions/apollo/runners/knowledge_spec.rb +6 -6
- data/spec/legion/extensions/apollo/runners/maintenance_spec.rb +8 -8
- data/spec/legion/extensions/apollo/runners/request_spec.rb +4 -4
- 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: 2dceee29e5b2af12bab5833beac8b837d2366eaf9509c7e4ce04e88b44a5c28f
|
|
4
|
+
data.tar.gz: 97d62a6385f375b19a6f48b1881fef8525e5949c4348bfe0cd07581d9ff710f2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 90065729231f3322eeaaeaa0e44e03b9b79350157674bec30f174fa6447d74bc53b4794e3385eee9d617c13c62cb22198de39fc21ebece7d2d512e7b1dd09ba6
|
|
7
|
+
data.tar.gz: f1c1b607fd9d9d244c0937b654ea95ca361980f5732c6e513719a6163004595ce0aaa9baab4181db56c8e6e8d1c511c1d6695c9110905e2094a252ba06e5a2c6
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.4.24] - 2026-05-07
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- Prevent zero-vector embeddings from being stored as valid semantic vectors when LLM embedding is unavailable.
|
|
7
|
+
- Avoid self-referential corroboration relations, bound corroboration maintenance scans, and preserve valid decay age filtering.
|
|
8
|
+
- Parse structured GAS LLM phase responses from `result[:data]` before falling back to JSON strings.
|
|
9
|
+
- Make Apollo write-privilege memoization thread-safe.
|
|
10
|
+
|
|
3
11
|
## [0.4.23] - 2026-05-06
|
|
4
12
|
|
|
5
13
|
### Fixed
|
|
@@ -24,8 +24,9 @@ module Legion
|
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def publishable?(insight)
|
|
27
|
-
(insight[:confidence] || 0)
|
|
28
|
-
|
|
27
|
+
confidence = (insight[:confidence] || 0).to_f
|
|
28
|
+
novelty = insight[:novelty] ? insight[:novelty].to_f : (1.0 - confidence)
|
|
29
|
+
confidence > PUBLISH_CONFIDENCE_THRESHOLD && novelty > PUBLISH_NOVELTY_THRESHOLD
|
|
29
30
|
end
|
|
30
31
|
|
|
31
32
|
def handle_mesh_departure(agent_id:)
|
|
@@ -9,6 +9,7 @@ module Legion
|
|
|
9
9
|
extend Legion::Settings::Helper
|
|
10
10
|
|
|
11
11
|
EMBEDDING_MODELS = %w[mxbai-embed-large bge-large snowflake-arctic-embed].freeze
|
|
12
|
+
PRIVILEGE_MUTEX = Mutex.new
|
|
12
13
|
|
|
13
14
|
module_function
|
|
14
15
|
|
|
@@ -57,11 +58,13 @@ module Legion
|
|
|
57
58
|
end
|
|
58
59
|
|
|
59
60
|
def check_db_write_privilege
|
|
60
|
-
|
|
61
|
+
PRIVILEGE_MUTEX.synchronize do
|
|
62
|
+
return @apollo_write_privilege unless @apollo_write_privilege.nil?
|
|
61
63
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
64
|
+
@apollo_write_privilege = Legion::Data.connection
|
|
65
|
+
.fetch("SELECT has_table_privilege(current_user, 'apollo_entries', 'INSERT') AS can_insert")
|
|
66
|
+
.first[:can_insert] == true
|
|
67
|
+
end
|
|
65
68
|
rescue StandardError => e
|
|
66
69
|
handle_exception(e, level: :warn, operation: 'apollo.capability.check_db_write_privilege')
|
|
67
70
|
@apollo_write_privilege = false
|
|
@@ -212,7 +212,7 @@ module Legion
|
|
|
212
212
|
{ from_content: fact[:content], to_id: entry[:id], relation_type: 'similar_to', confidence: fallback_confidence }
|
|
213
213
|
end
|
|
214
214
|
|
|
215
|
-
def llm_classify_relation(fact, entry)
|
|
215
|
+
def llm_classify_relation(fact, entry) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
216
216
|
prompt = <<~PROMPT
|
|
217
217
|
Classify the relationship between these two knowledge entries.
|
|
218
218
|
Valid types: #{RELATION_TYPES.join(', ')}
|
|
@@ -245,9 +245,13 @@ module Legion
|
|
|
245
245
|
phase: 'gas_relate'
|
|
246
246
|
)
|
|
247
247
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
248
|
+
rels = if result.is_a?(Hash) && result[:data].is_a?(Hash)
|
|
249
|
+
result[:data][:relations] || result.dig(:data, 'relations') || []
|
|
250
|
+
else
|
|
251
|
+
content = result.respond_to?(:message) ? result.message[:content] : result.to_s
|
|
252
|
+
parsed = json_load(content)
|
|
253
|
+
parsed.is_a?(Hash) ? (parsed[:relations] || parsed['relations'] || []) : []
|
|
254
|
+
end
|
|
251
255
|
best = rels.max_by { |r| r[:confidence] || r['confidence'] || 0 }
|
|
252
256
|
|
|
253
257
|
return fallback_relation(fact, entry) unless best
|
|
@@ -302,9 +306,13 @@ module Legion
|
|
|
302
306
|
phase: 'gas_synthesize'
|
|
303
307
|
)
|
|
304
308
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
309
|
+
items = if result.is_a?(Hash) && result[:data].is_a?(Hash)
|
|
310
|
+
result[:data][:synthesis] || result.dig(:data, 'synthesis') || []
|
|
311
|
+
else
|
|
312
|
+
content = result.respond_to?(:message) ? result.message[:content] : result.to_s
|
|
313
|
+
parsed = json_load(content)
|
|
314
|
+
parsed.is_a?(Hash) ? (parsed[:synthesis] || parsed['synthesis'] || []) : []
|
|
315
|
+
end
|
|
308
316
|
|
|
309
317
|
items.map { |item| build_synthesis_entry(item, facts) }
|
|
310
318
|
rescue StandardError => e
|
|
@@ -358,9 +366,13 @@ module Legion
|
|
|
358
366
|
phase: 'gas_anticipate'
|
|
359
367
|
)
|
|
360
368
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
369
|
+
questions = if result.is_a?(Hash) && result[:data].is_a?(Hash)
|
|
370
|
+
result[:data][:questions] || result.dig(:data, 'questions') || []
|
|
371
|
+
else
|
|
372
|
+
content = result.respond_to?(:message) ? result.message[:content] : result.to_s
|
|
373
|
+
parsed = json_load(content)
|
|
374
|
+
parsed.is_a?(Hash) ? (parsed[:questions] || parsed['questions'] || []) : []
|
|
375
|
+
end
|
|
364
376
|
questions = questions.first(max_anticipations)
|
|
365
377
|
|
|
366
378
|
questions.map do |q|
|
|
@@ -426,9 +438,13 @@ module Legion
|
|
|
426
438
|
phase: 'gas_comprehend'
|
|
427
439
|
)
|
|
428
440
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
441
|
+
facts_array = if result.is_a?(Hash) && result[:data].is_a?(Hash)
|
|
442
|
+
result[:data][:facts] || result.dig(:data, 'facts') || []
|
|
443
|
+
else
|
|
444
|
+
content = result.respond_to?(:message) ? result.message[:content] : result.to_s
|
|
445
|
+
parsed = json_load(content)
|
|
446
|
+
parsed.is_a?(Hash) ? (parsed[:facts] || parsed['facts'] || []) : Array(parsed)
|
|
447
|
+
end
|
|
432
448
|
facts_array.map do |f|
|
|
433
449
|
{
|
|
434
450
|
content: f[:content] || f['content'],
|
|
@@ -133,7 +133,7 @@ module Legion
|
|
|
133
133
|
{ success: false, error: e.message }
|
|
134
134
|
end
|
|
135
135
|
|
|
136
|
-
def handle_query(query:, limit: Helpers::GraphQuery.default_query_limit, min_confidence: Helpers::GraphQuery.default_query_min_confidence, status: UNSET, tags: nil, domain: nil, agent_id: 'unknown', **) # rubocop:disable Layout/LineLength
|
|
136
|
+
def handle_query(query:, limit: Helpers::GraphQuery.default_query_limit, min_confidence: Helpers::GraphQuery.default_query_min_confidence, status: UNSET, tags: nil, domain: nil, agent_id: 'unknown', **) # rubocop:disable Layout/LineLength, Metrics/CyclomaticComplexity
|
|
137
137
|
return { success: false, error: 'apollo_data_not_available' } unless Helpers::DataModels.apollo_entry_available?
|
|
138
138
|
|
|
139
139
|
entry_model = Helpers::DataModels.apollo_entry
|
|
@@ -147,6 +147,12 @@ module Legion
|
|
|
147
147
|
end
|
|
148
148
|
|
|
149
149
|
embedding = embed_text(query)
|
|
150
|
+
if embedding.nil?
|
|
151
|
+
log.warn('Apollo Knowledge.handle_query embedding unavailable; falling back to browse query')
|
|
152
|
+
return list_entries_chronologically(query: query, limit: limit, status: requested_status,
|
|
153
|
+
status_defaulted: status_defaulted, tags: tags, domain: domain)
|
|
154
|
+
end
|
|
155
|
+
|
|
150
156
|
sql = Helpers::GraphQuery.build_semantic_search_sql(
|
|
151
157
|
limit: limit, min_confidence: min_confidence,
|
|
152
158
|
statuses: Array(requested_status).map(&:to_s), tags: tags, domain: domain
|
|
@@ -255,6 +261,11 @@ module Legion
|
|
|
255
261
|
return { success: true, entries: [], count: 0 } if query.nil? || query.to_s.strip.empty?
|
|
256
262
|
|
|
257
263
|
embedding = embed_text(query)
|
|
264
|
+
if embedding.nil?
|
|
265
|
+
log.warn('Apollo Knowledge.retrieve_relevant embedding unavailable; returning empty result')
|
|
266
|
+
return { success: true, entries: [], count: 0, degraded: :no_embedding }
|
|
267
|
+
end
|
|
268
|
+
|
|
258
269
|
sql = Helpers::GraphQuery.build_semantic_search_sql(
|
|
259
270
|
limit: limit, min_confidence: min_confidence,
|
|
260
271
|
statuses: %w[confirmed candidate], tags: tags, domain: domain
|
|
@@ -354,12 +365,6 @@ module Legion
|
|
|
354
365
|
return { success: false, error: 'content is required' }
|
|
355
366
|
end
|
|
356
367
|
|
|
357
|
-
if content_type.nil?
|
|
358
|
-
log.warn('[apollo][handle_ingest] early-return: content_type is required ' \
|
|
359
|
-
"content_length=#{content.to_s.length}")
|
|
360
|
-
return { success: false, error: 'content_type is required' }
|
|
361
|
-
end
|
|
362
|
-
|
|
363
368
|
return nil if Helpers::DataModels.apollo_entry_available?
|
|
364
369
|
|
|
365
370
|
log.warn('[apollo][handle_ingest] early-return: apollo_data_not_available ' \
|
|
@@ -378,16 +383,16 @@ module Legion
|
|
|
378
383
|
log.debug("Apollo Knowledge.embed_text text_length=#{text.length}")
|
|
379
384
|
result = Legion::LLM::Call::Embeddings.generate(text: text)
|
|
380
385
|
vector = result.is_a?(Hash) ? result[:vector] : result
|
|
381
|
-
if vector.is_a?(Array) && vector.any?
|
|
386
|
+
if vector.is_a?(Array) && vector.any? && vector.any? { |v| v != 0.0 }
|
|
382
387
|
log.debug("Apollo Knowledge.embed_text vector_dimensions=#{vector.length}")
|
|
383
388
|
vector
|
|
384
389
|
else
|
|
385
|
-
log.warn('Apollo Knowledge.embed_text returned no vector;
|
|
386
|
-
|
|
390
|
+
log.warn('Apollo Knowledge.embed_text returned no usable vector; skipping embedding')
|
|
391
|
+
nil
|
|
387
392
|
end
|
|
388
393
|
rescue StandardError => e
|
|
389
394
|
handle_exception(e, level: :warn, operation: 'apollo.knowledge.embed_text')
|
|
390
|
-
|
|
395
|
+
nil
|
|
391
396
|
end
|
|
392
397
|
|
|
393
398
|
def normalize_text_input(value)
|
|
@@ -460,7 +465,7 @@ module Legion
|
|
|
460
465
|
submitted_by: metadata[:submitted_by],
|
|
461
466
|
submitted_from: metadata[:submitted_from],
|
|
462
467
|
content_hash: content_hash,
|
|
463
|
-
embedding: Sequel.lit("'[#{embedding.join(',')}]'::vector")
|
|
468
|
+
embedding: embedding ? Sequel.lit("'[#{embedding.join(',')}]'::vector") : nil
|
|
464
469
|
)
|
|
465
470
|
log.info("Apollo Knowledge.handle_ingest created entry_id=#{new_entry.id} status=candidate domain=#{metadata[:domain]} source_agent=#{metadata[:source_agent]}") # rubocop:disable Layout/LineLength
|
|
466
471
|
new_entry.id
|
|
@@ -584,6 +589,8 @@ module Legion
|
|
|
584
589
|
end
|
|
585
590
|
|
|
586
591
|
def find_corroboration(embedding, content_type_sym, source_agent, source_channel = nil)
|
|
592
|
+
return [false, nil] unless embedding
|
|
593
|
+
|
|
587
594
|
scan_limit = Helpers::Confidence.apollo_setting(:corroboration, :scan_limit, default: 50)
|
|
588
595
|
log.debug("Apollo Knowledge.find_corroboration content_type=#{content_type_sym} source_agent=#{source_agent} source_channel=#{source_channel || 'nil'} scan_limit=#{scan_limit}") # rubocop:disable Layout/LineLength
|
|
589
596
|
existing = Helpers::DataModels.apollo_entry
|
|
@@ -611,13 +618,6 @@ module Legion
|
|
|
611
618
|
confidence: Helpers::Confidence.apply_corroboration_boost(confidence: entry.confidence, weight: weight),
|
|
612
619
|
updated_at: Time.now
|
|
613
620
|
)
|
|
614
|
-
Helpers::DataModels.apollo_relation.create(
|
|
615
|
-
from_entry_id: entry.id,
|
|
616
|
-
to_entry_id: entry.id,
|
|
617
|
-
relation_type: 'similar_to',
|
|
618
|
-
source_agent: source_agent,
|
|
619
|
-
weight: sim
|
|
620
|
-
)
|
|
621
621
|
log.info("Apollo Knowledge.find_corroboration matched entry_id=#{entry.id} source_agent=#{source_agent} similarity=#{sim}")
|
|
622
622
|
return [true, entry.id]
|
|
623
623
|
end
|
|
@@ -43,7 +43,8 @@ module Legion
|
|
|
43
43
|
)
|
|
44
44
|
|
|
45
45
|
min_age_filter = Sequel.lit(
|
|
46
|
-
"COALESCE(updated_at, created_at) < NOW() - INTERVAL '
|
|
46
|
+
"COALESCE(updated_at, created_at) < NOW() - (? * INTERVAL '1 hour')",
|
|
47
|
+
min_age_hours
|
|
47
48
|
)
|
|
48
49
|
|
|
49
50
|
decayed = conn[:apollo_entries]
|
|
@@ -71,8 +72,8 @@ module Legion
|
|
|
71
72
|
return { success: false, error: 'apollo_data_not_available' }
|
|
72
73
|
end
|
|
73
74
|
|
|
74
|
-
candidates = Helpers::DataModels.apollo_entry.where(status: 'candidate').exclude(embedding: nil).all
|
|
75
|
-
confirmed = Helpers::DataModels.apollo_entry.where(status: 'confirmed').exclude(embedding: nil).all
|
|
75
|
+
candidates = Helpers::DataModels.apollo_entry.where(status: 'candidate').exclude(embedding: nil).limit(100).all
|
|
76
|
+
confirmed = Helpers::DataModels.apollo_entry.where(status: 'confirmed').exclude(embedding: nil).limit(500).all
|
|
76
77
|
log.debug("Apollo Maintenance.check_corroboration candidates=#{candidates.size} confirmed=#{confirmed.size}")
|
|
77
78
|
|
|
78
79
|
promoted = 0
|
|
@@ -18,7 +18,7 @@ RSpec.describe Legion::Extensions::Apollo::Runners::Knowledge do
|
|
|
18
18
|
before do
|
|
19
19
|
embeddings_mod = Module.new do
|
|
20
20
|
def self.generate(*, **)
|
|
21
|
-
{ vector: Array.new(1024, 0.
|
|
21
|
+
{ vector: Array.new(1024, 0.1), model: 'test', provider: :ollama, dimensions: 1024, tokens: 0 }
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
24
|
stub_const('Legion::LLM::Call::Embeddings', embeddings_mod)
|
|
@@ -159,7 +159,7 @@ RSpec.describe Legion::Extensions::Apollo::Runners::Knowledge do
|
|
|
159
159
|
stub_const('Legion::Data::Model::ApolloExpertise', mock_expertise_class)
|
|
160
160
|
stub_const('Legion::Data::Model::ApolloAccessLog', mock_access_log_class)
|
|
161
161
|
allow(Legion::LLM::Call::Embeddings).to receive(:generate)
|
|
162
|
-
.and_return({ vector: Array.new(1024, 0.
|
|
162
|
+
.and_return({ vector: Array.new(1024, 0.1), model: 'test', provider: :ollama, dimensions: 1024, tokens: 0 })
|
|
163
163
|
|
|
164
164
|
# Corroboration lookup chain
|
|
165
165
|
allow(mock_entry_class).to receive(:where).and_return(double(exclude: double(limit: empty_dataset)))
|
|
@@ -328,7 +328,7 @@ RSpec.describe Legion::Extensions::Apollo::Runners::Knowledge do
|
|
|
328
328
|
before do
|
|
329
329
|
stub_const('Legion::Data::Model::ApolloEntry', Class.new)
|
|
330
330
|
allow(Legion::LLM::Call::Embeddings).to receive(:generate)
|
|
331
|
-
.and_return({ vector: Array.new(1024, 0.
|
|
331
|
+
.and_return({ vector: Array.new(1024, 0.1), model: 'test', provider: :ollama, dimensions: 1024, tokens: 0 })
|
|
332
332
|
allow(Legion::Data::Model::ApolloEntry).to receive(:where)
|
|
333
333
|
.and_raise(Sequel::Error, 'connection lost')
|
|
334
334
|
end
|
|
@@ -406,7 +406,7 @@ RSpec.describe Legion::Extensions::Apollo::Runners::Knowledge do
|
|
|
406
406
|
stub_const('Legion::Data::Model::ApolloEntry', mock_entry_class)
|
|
407
407
|
stub_const('Legion::Data::Model::ApolloAccessLog', mock_access_log_class)
|
|
408
408
|
allow(Legion::LLM::Call::Embeddings).to receive(:generate)
|
|
409
|
-
.and_return({ vector: Array.new(1024, 0.
|
|
409
|
+
.and_return({ vector: Array.new(1024, 0.1), model: 'test', provider: :ollama, dimensions: 1024, tokens: 0 })
|
|
410
410
|
allow(mock_entry_class).to receive(:db).and_return(mock_db)
|
|
411
411
|
allow(mock_db).to receive(:fetch).and_return(double(all: sample_entries))
|
|
412
412
|
allow(mock_entry_class).to receive(:where).and_return(double(update: true))
|
|
@@ -441,7 +441,7 @@ RSpec.describe Legion::Extensions::Apollo::Runners::Knowledge do
|
|
|
441
441
|
before do
|
|
442
442
|
stub_const('Legion::Data::Model::ApolloEntry', mock_entry_class)
|
|
443
443
|
allow(Legion::LLM::Call::Embeddings).to receive(:generate)
|
|
444
|
-
.and_return({ vector: Array.new(1024, 0.
|
|
444
|
+
.and_return({ vector: Array.new(1024, 0.1), model: 'test', provider: :ollama, dimensions: 1024, tokens: 0 })
|
|
445
445
|
allow(mock_entry_class).to receive(:db).and_return(mock_db)
|
|
446
446
|
allow(mock_db).to receive(:fetch).and_return(double(all: []))
|
|
447
447
|
end
|
|
@@ -555,7 +555,7 @@ RSpec.describe Legion::Extensions::Apollo::Runners::Knowledge do
|
|
|
555
555
|
before do
|
|
556
556
|
stub_const('Legion::Data::Model::ApolloEntry', mock_entry_class)
|
|
557
557
|
allow(Legion::LLM::Call::Embeddings).to receive(:generate)
|
|
558
|
-
.and_return({ vector: Array.new(1024, 0.
|
|
558
|
+
.and_return({ vector: Array.new(1024, 0.1), model: 'test', provider: :ollama, dimensions: 1024, tokens: 0 })
|
|
559
559
|
allow(mock_entry_class).to receive(:db).and_return(mock_db)
|
|
560
560
|
allow(mock_db).to receive(:fetch).and_return(double(all: sample_entries))
|
|
561
561
|
allow(mock_entry_class).to receive(:where).and_return(double(update: true))
|
|
@@ -107,9 +107,9 @@ RSpec.describe Legion::Extensions::Apollo::Runners::Maintenance do
|
|
|
107
107
|
before do
|
|
108
108
|
stub_const('Legion::Data::Model::ApolloEntry', mock_entry_class)
|
|
109
109
|
allow(mock_entry_class).to receive(:where).with(status: 'candidate')
|
|
110
|
-
.and_return(double(exclude: double(all: [])))
|
|
110
|
+
.and_return(double(exclude: double(limit: double(all: []))))
|
|
111
111
|
allow(mock_entry_class).to receive(:where).with(status: 'confirmed')
|
|
112
|
-
.and_return(double(exclude: double(all: [])))
|
|
112
|
+
.and_return(double(exclude: double(limit: double(all: []))))
|
|
113
113
|
end
|
|
114
114
|
|
|
115
115
|
it 'returns zero promoted and scanned' do
|
|
@@ -136,9 +136,9 @@ RSpec.describe Legion::Extensions::Apollo::Runners::Maintenance do
|
|
|
136
136
|
stub_const('Legion::Data::Model::ApolloEntry', mock_entry_class)
|
|
137
137
|
stub_const('Legion::Data::Model::ApolloRelation', mock_relation_class)
|
|
138
138
|
allow(mock_entry_class).to receive(:where).with(status: 'candidate')
|
|
139
|
-
.and_return(double(exclude: double(all: [candidate])))
|
|
139
|
+
.and_return(double(exclude: double(limit: double(all: [candidate]))))
|
|
140
140
|
allow(mock_entry_class).to receive(:where).with(status: 'confirmed')
|
|
141
|
-
.and_return(double(exclude: double(all: [confirmed_entry])))
|
|
141
|
+
.and_return(double(exclude: double(limit: double(all: [confirmed_entry]))))
|
|
142
142
|
allow(mock_relation_class).to receive(:create)
|
|
143
143
|
end
|
|
144
144
|
|
|
@@ -174,9 +174,9 @@ RSpec.describe Legion::Extensions::Apollo::Runners::Maintenance do
|
|
|
174
174
|
stub_const('Legion::Data::Model::ApolloEntry', mock_entry_class)
|
|
175
175
|
stub_const('Legion::Data::Model::ApolloRelation', mock_relation_class)
|
|
176
176
|
allow(mock_entry_class).to receive(:where).with(status: 'candidate')
|
|
177
|
-
.and_return(double(exclude: double(all: [candidate])))
|
|
177
|
+
.and_return(double(exclude: double(limit: double(all: [candidate]))))
|
|
178
178
|
allow(mock_entry_class).to receive(:where).with(status: 'confirmed')
|
|
179
|
-
.and_return(double(exclude: double(all: [confirmed_entry])))
|
|
179
|
+
.and_return(double(exclude: double(limit: double(all: [confirmed_entry]))))
|
|
180
180
|
end
|
|
181
181
|
|
|
182
182
|
it 'does not promote even with different providers' do
|
|
@@ -198,9 +198,9 @@ RSpec.describe Legion::Extensions::Apollo::Runners::Maintenance do
|
|
|
198
198
|
before do
|
|
199
199
|
stub_const('Legion::Data::Model::ApolloEntry', mock_entry_class)
|
|
200
200
|
allow(mock_entry_class).to receive(:where).with(status: 'candidate')
|
|
201
|
-
.and_return(double(exclude: double(all: [candidate])))
|
|
201
|
+
.and_return(double(exclude: double(limit: double(all: [candidate]))))
|
|
202
202
|
allow(mock_entry_class).to receive(:where).with(status: 'confirmed')
|
|
203
|
-
.and_return(double(exclude: double(all: [confirmed_entry])))
|
|
203
|
+
.and_return(double(exclude: double(limit: double(all: [confirmed_entry]))))
|
|
204
204
|
end
|
|
205
205
|
|
|
206
206
|
it 'does not promote' do
|
|
@@ -14,7 +14,7 @@ RSpec.describe Legion::Extensions::Apollo::Runners::Request do
|
|
|
14
14
|
|
|
15
15
|
embeddings_mod = Module.new do
|
|
16
16
|
def self.generate(*, **)
|
|
17
|
-
{ vector: Array.new(1024, 0.
|
|
17
|
+
{ vector: Array.new(1024, 0.1), model: 'test', provider: :ollama, dimensions: 1024, tokens: 0 }
|
|
18
18
|
end
|
|
19
19
|
end
|
|
20
20
|
stub_const('Legion::LLM::Call::Embeddings', embeddings_mod)
|
|
@@ -40,7 +40,7 @@ RSpec.describe Legion::Extensions::Apollo::Runners::Request do
|
|
|
40
40
|
stub_const('Legion::Data::Model::ApolloEntry', mock_entry_class)
|
|
41
41
|
stub_const('Legion::Data::Model::ApolloAccessLog', mock_access_log_class)
|
|
42
42
|
allow(Legion::LLM::Call::Embeddings).to receive(:generate)
|
|
43
|
-
.and_return({ vector: Array.new(1024, 0.
|
|
43
|
+
.and_return({ vector: Array.new(1024, 0.1), model: 'test', provider: :ollama, dimensions: 1024, tokens: 0 })
|
|
44
44
|
allow(mock_entry_class).to receive(:db).and_return(mock_db)
|
|
45
45
|
allow(mock_db).to receive(:fetch).and_return(double(all: sample_entries))
|
|
46
46
|
allow(mock_entry_class).to receive(:where).and_return(double(update: true))
|
|
@@ -104,7 +104,7 @@ RSpec.describe Legion::Extensions::Apollo::Runners::Request do
|
|
|
104
104
|
before do
|
|
105
105
|
stub_const('Legion::Data::Model::ApolloEntry', mock_entry_class)
|
|
106
106
|
allow(Legion::LLM::Call::Embeddings).to receive(:generate)
|
|
107
|
-
.and_return({ vector: Array.new(1024, 0.
|
|
107
|
+
.and_return({ vector: Array.new(1024, 0.1), model: 'test', provider: :ollama, dimensions: 1024, tokens: 0 })
|
|
108
108
|
allow(mock_entry_class).to receive(:db).and_return(mock_db)
|
|
109
109
|
allow(mock_db).to receive(:fetch).and_return(double(all: []))
|
|
110
110
|
allow(mock_entry_class).to receive(:where).and_return(double(update: true))
|
|
@@ -143,7 +143,7 @@ RSpec.describe Legion::Extensions::Apollo::Runners::Request do
|
|
|
143
143
|
stub_const('Legion::Data::Model::ApolloExpertise', mock_expertise_class)
|
|
144
144
|
stub_const('Legion::Data::Model::ApolloAccessLog', mock_access_log_class)
|
|
145
145
|
allow(Legion::LLM::Call::Embeddings).to receive(:generate)
|
|
146
|
-
.and_return({ vector: Array.new(1024, 0.
|
|
146
|
+
.and_return({ vector: Array.new(1024, 0.1), model: 'test', provider: :ollama, dimensions: 1024, tokens: 0 })
|
|
147
147
|
allow(mock_entry_class).to receive(:where).and_return(double(exclude: double(limit: double(each: nil), first: nil)))
|
|
148
148
|
allow(mock_entry_class).to receive(:exclude)
|
|
149
149
|
.and_return(double(exclude: double(limit: double(all: []))))
|