lex-agentic-self 0.1.1 → 0.1.3

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 (23) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -0
  3. data/LICENSE +201 -21
  4. data/README.md +2 -2
  5. data/lex-agentic-self.gemspec +8 -0
  6. data/lib/legion/extensions/agentic/self/agency/runners/agency.rb +7 -7
  7. data/lib/legion/extensions/agentic/self/anchor/helpers/constants.rb +2 -2
  8. data/lib/legion/extensions/agentic/self/anosognosia/runners/anosognosia.rb +6 -6
  9. data/lib/legion/extensions/agentic/self/default_mode_network/runners/default_mode_network.rb +17 -17
  10. data/lib/legion/extensions/agentic/self/fingerprint/runners/cognitive_fingerprint.rb +7 -7
  11. data/lib/legion/extensions/agentic/self/identity/runners/identity.rb +8 -8
  12. data/lib/legion/extensions/agentic/self/metacognition/runners/metacognition.rb +1 -1
  13. data/lib/legion/extensions/agentic/self/metacognitive_monitoring/runners/metacognitive_monitoring.rb +11 -11
  14. data/lib/legion/extensions/agentic/self/narrative_arc/runners/narrative.rb +9 -9
  15. data/lib/legion/extensions/agentic/self/narrative_identity/runners/narrative_identity.rb +15 -15
  16. data/lib/legion/extensions/agentic/self/narrative_self/runners/narrative_self.rb +4 -4
  17. data/lib/legion/extensions/agentic/self/reflection/helpers/llm_enhancer.rb +26 -0
  18. data/lib/legion/extensions/agentic/self/reflection/runners/reflection.rb +4 -4
  19. data/lib/legion/extensions/agentic/self/self_talk/runners/self_talk.rb +11 -11
  20. data/lib/legion/extensions/agentic/self/version.rb +1 -1
  21. data/spec/legion/extensions/agentic/self/reflection/helpers/llm_enhancer_spec.rb +76 -0
  22. data/spec/spec_helper.rb +22 -17
  23. metadata +99 -1
@@ -26,8 +26,8 @@ module Legion
26
26
  effort: effort
27
27
  )
28
28
 
29
- Legion::Logging.debug "[metacognitive] record_judgment type=#{type_sym} domain=#{domain} " \
30
- "confidence=#{judgment.predicted_confidence.round(2)} id=#{judgment.id[0..7]}"
29
+ log.debug "[metacognitive] record_judgment type=#{type_sym} domain=#{domain} " \
30
+ "confidence=#{judgment.predicted_confidence.round(2)} id=#{judgment.id[0..7]}"
31
31
 
32
32
  { success: true, judgment_id: judgment.id, judgment: judgment.to_h }
33
33
  end
@@ -37,12 +37,12 @@ module Legion
37
37
  judgment = eng.resolve_judgment(judgment_id: judgment_id, actual_outcome: actual_outcome)
38
38
 
39
39
  unless judgment
40
- Legion::Logging.debug "[metacognitive] resolve_judgment not_found id=#{judgment_id[0..7]}"
40
+ log.debug "[metacognitive] resolve_judgment not_found id=#{judgment_id[0..7]}"
41
41
  return { success: false, error: :not_found }
42
42
  end
43
43
 
44
- Legion::Logging.info "[metacognitive] resolved judgment=#{judgment_id[0..7]} " \
45
- "error=#{judgment.calibration_error&.round(3)}"
44
+ log.info "[metacognitive] resolved judgment=#{judgment_id[0..7]} " \
45
+ "error=#{judgment.calibration_error&.round(3)}"
46
46
 
47
47
  { success: true, judgment_id: judgment_id, judgment: judgment.to_h }
48
48
  end
@@ -51,7 +51,7 @@ module Legion
51
51
  eng = engine || monitoring_engine
52
52
  judgment = eng.feeling_of_knowing(domain: domain, query: query)
53
53
 
54
- Legion::Logging.debug "[metacognitive] fok domain=#{domain} confidence=#{judgment.predicted_confidence.round(2)}"
54
+ log.debug "[metacognitive] fok domain=#{domain} confidence=#{judgment.predicted_confidence.round(2)}"
55
55
 
56
56
  {
57
57
  success: true,
@@ -66,7 +66,7 @@ module Legion
66
66
  eng = engine || monitoring_engine
67
67
  judgment = eng.judgment_of_learning(domain: domain, content: content)
68
68
 
69
- Legion::Logging.debug "[metacognitive] jol domain=#{domain} confidence=#{judgment.predicted_confidence.round(2)}"
69
+ log.debug "[metacognitive] jol domain=#{domain} confidence=#{judgment.predicted_confidence.round(2)}"
70
70
 
71
71
  {
72
72
  success: true,
@@ -81,7 +81,7 @@ module Legion
81
81
  eng = engine || monitoring_engine
82
82
  findings = eng.detect_overconfidence
83
83
 
84
- Legion::Logging.debug "[metacognitive] overconfidence_scan count=#{findings.size}"
84
+ log.debug "[metacognitive] overconfidence_scan count=#{findings.size}"
85
85
 
86
86
  {
87
87
  success: true,
@@ -94,7 +94,7 @@ module Legion
94
94
  eng = engine || monitoring_engine
95
95
  findings = eng.detect_underconfidence
96
96
 
97
- Legion::Logging.debug "[metacognitive] underconfidence_scan count=#{findings.size}"
97
+ log.debug "[metacognitive] underconfidence_scan count=#{findings.size}"
98
98
 
99
99
  {
100
100
  success: true,
@@ -107,7 +107,7 @@ module Legion
107
107
  eng = engine || monitoring_engine
108
108
  report = eng.calibration_report
109
109
 
110
- Legion::Logging.debug "[metacognitive] calibration_report domains=#{report[:by_domain].size}"
110
+ log.debug "[metacognitive] calibration_report domains=#{report[:by_domain].size}"
111
111
 
112
112
  { success: true, report: report }
113
113
  end
@@ -116,7 +116,7 @@ module Legion
116
116
  eng = engine || monitoring_engine
117
117
  report = eng.monitoring_report
118
118
 
119
- Legion::Logging.debug "[metacognitive] monitoring_report total=#{report[:total_judgments]}"
119
+ log.debug "[metacognitive] monitoring_report total=#{report[:total_judgments]}"
120
120
 
121
121
  { success: true, report: report }
122
122
  end
@@ -16,11 +16,11 @@ module Legion
16
16
  arc = eng.create_arc(title: title, domain: domain, initial_tension: initial_tension)
17
17
 
18
18
  unless arc
19
- Legion::Logging.warn "[narrative_arc] create_arc failed: engine at capacity (#{Helpers::Constants::MAX_ARCS})"
19
+ log.warn "[narrative_arc] create_arc failed: engine at capacity (#{Helpers::Constants::MAX_ARCS})"
20
20
  return { success: false, reason: :engine_at_capacity }
21
21
  end
22
22
 
23
- Legion::Logging.debug "[narrative_arc] arc created: #{arc.arc_id[0..7]} title=#{title} domain=#{domain}"
23
+ log.debug "[narrative_arc] arc created: #{arc.arc_id[0..7]} title=#{title} domain=#{domain}"
24
24
  { success: true, arc_id: arc.arc_id, title: arc.title, arc_phase: arc.arc_phase,
25
25
  tension_level: arc.tension_level }
26
26
  end
@@ -39,11 +39,11 @@ module Legion
39
39
 
40
40
  if result[:success]
41
41
  arc = eng.get_arc(arc_id)
42
- Legion::Logging.debug "[narrative_arc] beat added: arc=#{arc_id[0..7]} type=#{beat_type} " \
43
- "phase=#{result[:arc_phase]} tension=#{result[:tension_level].round(2)}"
42
+ log.debug "[narrative_arc] beat added: arc=#{arc_id[0..7]} type=#{beat_type} " \
43
+ "phase=#{result[:arc_phase]} tension=#{result[:tension_level].round(2)}"
44
44
  result[:dramatic_score] = arc.dramatic_score if arc
45
45
  else
46
- Legion::Logging.debug "[narrative_arc] add_beat failed: #{result[:reason]} arc=#{arc_id[0..7]}"
46
+ log.debug "[narrative_arc] add_beat failed: #{result[:reason]} arc=#{arc_id[0..7]}"
47
47
  end
48
48
 
49
49
  result
@@ -60,14 +60,14 @@ module Legion
60
60
  def active_arcs(engine: nil, **)
61
61
  eng = engine || arc_engine
62
62
  arcs = eng.active_arcs
63
- Legion::Logging.debug "[narrative_arc] active arcs count=#{arcs.size}"
63
+ log.debug "[narrative_arc] active arcs count=#{arcs.size}"
64
64
  { arcs: arcs.map(&:to_h), count: arcs.size }
65
65
  end
66
66
 
67
67
  def completed_arcs(engine: nil, **)
68
68
  eng = engine || arc_engine
69
69
  arcs = eng.completed_arcs
70
- Legion::Logging.debug "[narrative_arc] completed arcs count=#{arcs.size}"
70
+ log.debug "[narrative_arc] completed arcs count=#{arcs.size}"
71
71
  { arcs: arcs.map(&:to_h), count: arcs.size }
72
72
  end
73
73
 
@@ -76,14 +76,14 @@ module Legion
76
76
  arc = eng.most_dramatic_arc
77
77
  return { found: false } unless arc
78
78
 
79
- Legion::Logging.debug "[narrative_arc] most dramatic: #{arc.arc_id[0..7]} score=#{arc.dramatic_score.round(2)}"
79
+ log.debug "[narrative_arc] most dramatic: #{arc.arc_id[0..7]} score=#{arc.dramatic_score.round(2)}"
80
80
  { found: true, arc: arc.to_h }
81
81
  end
82
82
 
83
83
  def arc_report(engine: nil, **)
84
84
  eng = engine || arc_engine
85
85
  report = eng.arc_report
86
- Legion::Logging.debug "[narrative_arc] arc_report total=#{report[:total_arcs]} patterns=#{report[:patterns].inspect}"
86
+ log.debug "[narrative_arc] arc_report total=#{report[:total_arcs]} patterns=#{report[:patterns].inspect}"
87
87
  { success: true, report: report }
88
88
  end
89
89
 
@@ -18,7 +18,7 @@ module Legion
18
18
  content: content, episode_type: episode_type,
19
19
  emotional_valence: emotional_valence, significance: significance, domain: domain
20
20
  )
21
- Legion::Logging.debug "[narrative_identity] recorded episode #{episode.id[0..7]} type=#{episode_type}"
21
+ log.debug "[narrative_identity] recorded episode #{episode.id[0..7]} type=#{episode_type}"
22
22
  { success: true, episode: episode.to_h }
23
23
  rescue StandardError => e
24
24
  { success: false, error: e.message }
@@ -26,7 +26,7 @@ module Legion
26
26
 
27
27
  def assign_episode_to_chapter(episode_id:, chapter_id:, engine: nil, **)
28
28
  result = resolve_engine(engine).assign_to_chapter(episode_id: episode_id, chapter_id: chapter_id)
29
- Legion::Logging.debug "[narrative_identity] assign episode=#{episode_id[0..7]} ok=#{result}"
29
+ log.debug "[narrative_identity] assign episode=#{episode_id[0..7]} ok=#{result}"
30
30
  { success: result, episode_id: episode_id, chapter_id: chapter_id }
31
31
  rescue StandardError => e
32
32
  { success: false, error: e.message }
@@ -37,7 +37,7 @@ module Legion
37
37
  Helpers::Constants::CHAPTER_LABELS.include?(label)
38
38
 
39
39
  chapter = resolve_engine(engine).create_chapter(title: title, label: label)
40
- Legion::Logging.debug "[narrative_identity] created chapter #{chapter.id[0..7]} label=#{label}"
40
+ log.debug "[narrative_identity] created chapter #{chapter.id[0..7]} label=#{label}"
41
41
  { success: true, chapter: chapter.to_h }
42
42
  rescue StandardError => e
43
43
  { success: false, error: e.message }
@@ -45,7 +45,7 @@ module Legion
45
45
 
46
46
  def close_chapter(chapter_id:, engine: nil, **)
47
47
  result = resolve_engine(engine).close_chapter(chapter_id: chapter_id)
48
- Legion::Logging.debug "[narrative_identity] close_chapter #{chapter_id[0..7]} ok=#{result}"
48
+ log.debug "[narrative_identity] close_chapter #{chapter_id[0..7]} ok=#{result}"
49
49
  { success: result, chapter_id: chapter_id }
50
50
  rescue StandardError => e
51
51
  { success: false, error: e.message }
@@ -56,7 +56,7 @@ module Legion
56
56
  Helpers::Constants::THEME_TYPES.include?(theme_type)
57
57
 
58
58
  theme = resolve_engine(engine).add_theme(name: name, theme_type: theme_type)
59
- Legion::Logging.debug "[narrative_identity] added theme #{theme.id[0..7]} type=#{theme_type}"
59
+ log.debug "[narrative_identity] added theme #{theme.id[0..7]} type=#{theme_type}"
60
60
  { success: true, theme: theme.to_h }
61
61
  rescue StandardError => e
62
62
  { success: false, error: e.message }
@@ -64,7 +64,7 @@ module Legion
64
64
 
65
65
  def link_theme(episode_id:, theme_id:, engine: nil, **)
66
66
  result = resolve_engine(engine).link_theme(episode_id: episode_id, theme_id: theme_id)
67
- Legion::Logging.debug "[narrative_identity] link theme=#{theme_id[0..7]} episode=#{episode_id[0..7]} ok=#{result}"
67
+ log.debug "[narrative_identity] link theme=#{theme_id[0..7]} episode=#{episode_id[0..7]} ok=#{result}"
68
68
  { success: result, episode_id: episode_id, theme_id: theme_id }
69
69
  rescue StandardError => e
70
70
  { success: false, error: e.message }
@@ -72,7 +72,7 @@ module Legion
72
72
 
73
73
  def reinforce_theme(theme_id:, amount:, engine: nil, **)
74
74
  result = resolve_engine(engine).reinforce_theme(theme_id: theme_id, amount: amount)
75
- Legion::Logging.debug "[narrative_identity] reinforce theme=#{theme_id[0..7]} amount=#{amount} ok=#{result}"
75
+ log.debug "[narrative_identity] reinforce theme=#{theme_id[0..7]} amount=#{amount} ok=#{result}"
76
76
  { success: result, theme_id: theme_id, amount: amount }
77
77
  rescue StandardError => e
78
78
  { success: false, error: e.message }
@@ -80,7 +80,7 @@ module Legion
80
80
 
81
81
  def narrative_coherence(engine: nil, **)
82
82
  score = resolve_engine(engine).narrative_coherence
83
- Legion::Logging.debug "[narrative_identity] coherence=#{score}"
83
+ log.debug "[narrative_identity] coherence=#{score}"
84
84
  { success: true, coherence: score }
85
85
  rescue StandardError => e
86
86
  { success: false, error: e.message }
@@ -88,7 +88,7 @@ module Legion
88
88
 
89
89
  def identity_summary(engine: nil, **)
90
90
  summary = resolve_engine(engine).identity_summary
91
- Legion::Logging.debug '[narrative_identity] identity_summary requested'
91
+ log.debug '[narrative_identity] identity_summary requested'
92
92
  { success: true, summary: summary }
93
93
  rescue StandardError => e
94
94
  { success: false, error: e.message }
@@ -96,7 +96,7 @@ module Legion
96
96
 
97
97
  def life_story(engine: nil, **)
98
98
  story = resolve_engine(engine).life_story
99
- Legion::Logging.debug "[narrative_identity] life_story chapters=#{story.size}"
99
+ log.debug "[narrative_identity] life_story chapters=#{story.size}"
100
100
  { success: true, life_story: story }
101
101
  rescue StandardError => e
102
102
  { success: false, error: e.message }
@@ -104,7 +104,7 @@ module Legion
104
104
 
105
105
  def most_defining_episodes(limit: 5, engine: nil, **)
106
106
  episodes = resolve_engine(engine).most_defining_episodes(limit: limit)
107
- Legion::Logging.debug "[narrative_identity] defining_episodes count=#{episodes.size}"
107
+ log.debug "[narrative_identity] defining_episodes count=#{episodes.size}"
108
108
  { success: true, episodes: episodes.map(&:to_h) }
109
109
  rescue StandardError => e
110
110
  { success: false, error: e.message }
@@ -112,7 +112,7 @@ module Legion
112
112
 
113
113
  def prominent_themes(engine: nil, **)
114
114
  themes = resolve_engine(engine).prominent_themes
115
- Legion::Logging.debug "[narrative_identity] prominent_themes count=#{themes.size}"
115
+ log.debug "[narrative_identity] prominent_themes count=#{themes.size}"
116
116
  { success: true, themes: themes.map(&:to_h) }
117
117
  rescue StandardError => e
118
118
  { success: false, error: e.message }
@@ -120,7 +120,7 @@ module Legion
120
120
 
121
121
  def current_chapter(engine: nil, **)
122
122
  chapter = resolve_engine(engine).current_chapter
123
- Legion::Logging.debug "[narrative_identity] current_chapter=#{chapter&.id&.slice(0..7)}"
123
+ log.debug "[narrative_identity] current_chapter=#{chapter&.id&.slice(0..7)}"
124
124
  { success: true, chapter: chapter&.to_h }
125
125
  rescue StandardError => e
126
126
  { success: false, error: e.message }
@@ -128,7 +128,7 @@ module Legion
128
128
 
129
129
  def decay_themes(engine: nil, **)
130
130
  resolve_engine(engine).decay_all_themes!
131
- Legion::Logging.debug '[narrative_identity] theme decay applied'
131
+ log.debug '[narrative_identity] theme decay applied'
132
132
  { success: true }
133
133
  rescue StandardError => e
134
134
  { success: false, error: e.message }
@@ -136,7 +136,7 @@ module Legion
136
136
 
137
137
  def narrative_report(engine: nil, **)
138
138
  report = resolve_engine(engine).narrative_report
139
- Legion::Logging.debug '[narrative_identity] narrative_report generated'
139
+ log.debug '[narrative_identity] narrative_report generated'
140
140
  { success: true, report: report }
141
141
  rescue StandardError => e
142
142
  { success: false, error: e.message }
@@ -20,7 +20,7 @@ module Legion
20
20
  emotional_valence: emotional_valence,
21
21
  tags: tags
22
22
  )
23
- Legion::Logging.debug "[narrative_self] recorded episode=#{episode_type} domain=#{domain} sig=#{episode.significance.round(3)}"
23
+ log.debug "[narrative_self] recorded episode=#{episode_type} domain=#{domain} sig=#{episode.significance.round(3)}"
24
24
  { success: true, episode: episode.to_h }
25
25
  end
26
26
 
@@ -41,7 +41,7 @@ module Legion
41
41
 
42
42
  def create_thread(theme:, domain: :general, **)
43
43
  thread = autobiography.create_thread(theme: theme, domain: domain)
44
- Legion::Logging.debug "[narrative_self] created thread=#{theme} domain=#{domain}"
44
+ log.debug "[narrative_self] created thread=#{theme} domain=#{domain}"
45
45
  { success: true, thread: thread.to_h }
46
46
  end
47
47
 
@@ -58,13 +58,13 @@ module Legion
58
58
 
59
59
  def self_summary(**)
60
60
  summary = autobiography.self_summary
61
- Legion::Logging.debug "[narrative_self] summary: episodes=#{summary[:total_episodes]} richness=#{summary[:narrative_richness].round(3)}"
61
+ log.debug "[narrative_self] summary: episodes=#{summary[:total_episodes]} richness=#{summary[:narrative_richness].round(3)}"
62
62
  { success: true, summary: summary }
63
63
  end
64
64
 
65
65
  def update_narrative_self(**)
66
66
  autobiography.decay_all
67
- Legion::Logging.debug "[narrative_self] tick: episodes=#{autobiography.episodes.size} threads=#{autobiography.threads.size}"
67
+ log.debug "[narrative_self] tick: episodes=#{autobiography.episodes.size} threads=#{autobiography.threads.size}"
68
68
  { success: true, episode_count: autobiography.episodes.size, thread_count: autobiography.threads.size }
69
69
  end
70
70
 
@@ -34,6 +34,32 @@ module Legion
34
34
  false
35
35
  end
36
36
 
37
+ def pipeline_available?
38
+ !!(defined?(Legion::LLM::Pipeline::GaiaCaller) &&
39
+ Legion::LLM.respond_to?(:pipeline_enabled?) &&
40
+ Legion::LLM.pipeline_enabled?)
41
+ rescue StandardError
42
+ false
43
+ end
44
+
45
+ def enhance(prompt, phase: 'reflection', **)
46
+ return nil unless available?
47
+
48
+ if pipeline_available?
49
+ response = Legion::LLM::Pipeline::GaiaCaller.chat(
50
+ message: prompt, phase: phase, **
51
+ )
52
+ response&.message&.dig(:content)
53
+ else
54
+ chat = Legion::LLM.chat
55
+ response = chat.ask(prompt)
56
+ response&.content
57
+ end
58
+ rescue StandardError => e
59
+ Legion::Logging.warn("[reflection:llm] enhance failed: #{e.message}")
60
+ nil
61
+ end
62
+
37
63
  def enhance_reflection(monitors_data:, health_scores:)
38
64
  prompt = build_enhance_reflection_prompt(monitors_data: monitors_data, health_scores: health_scores)
39
65
  response = llm_ask(prompt)
@@ -37,7 +37,7 @@ module Legion
37
37
  end
38
38
  end
39
39
 
40
- Legion::Logging.debug "[reflection] generated #{new_reflections.size} reflections, health=#{reflection_store.cognitive_health}"
40
+ log.debug "[reflection] generated #{new_reflections.size} reflections, health=#{reflection_store.cognitive_health}"
41
41
 
42
42
  {
43
43
  reflections_generated: new_reflections.size,
@@ -61,13 +61,13 @@ module Legion
61
61
 
62
62
  reflection ||= build_mechanical_dream_reflection(dream_results)
63
63
 
64
- Legion::Logging.debug "[reflection] dream reflection generated source=#{source}"
64
+ log.debug "[reflection] dream reflection generated source=#{source}"
65
65
  { reflection: reflection, source: source }
66
66
  end
67
67
 
68
68
  def cognitive_health(**)
69
69
  health = reflection_store.cognitive_health
70
- Legion::Logging.debug "[reflection] cognitive health: #{health}"
70
+ log.debug "[reflection] cognitive health: #{health}"
71
71
  {
72
72
  health: health,
73
73
  category_scores: Helpers::Constants::CATEGORIES.to_h { |c| [c, reflection_store.category_score(c)] },
@@ -94,7 +94,7 @@ module Legion
94
94
  return { error: :already_acted } if reflection[:acted_on]
95
95
 
96
96
  reflection_store.mark_acted_on(reflection_id)
97
- Legion::Logging.info "[reflection] adapted: #{reflection[:observation]}"
97
+ log.info "[reflection] adapted: #{reflection[:observation]}"
98
98
  { adapted: true, reflection_id: reflection_id, recommendation: reflection[:recommendation] }
99
99
  end
100
100
 
@@ -18,13 +18,13 @@ module Legion
18
18
  volume: volume,
19
19
  bias_direction: bias_direction
20
20
  )
21
- Legion::Logging.info "[self_talk] register_voice: name=#{name} type=#{voice_type} registered=#{result[:registered]}"
21
+ log.info "[self_talk] register_voice: name=#{name} type=#{voice_type} registered=#{result[:registered]}"
22
22
  result
23
23
  end
24
24
 
25
25
  def start_dialogue(topic:, **)
26
26
  result = engine.start_dialogue(topic: topic)
27
- Legion::Logging.debug "[self_talk] start_dialogue: topic=#{topic} id=#{result[:dialogue][:id]}"
27
+ log.debug "[self_talk] start_dialogue: topic=#{topic} id=#{result[:dialogue][:id]}"
28
28
  result
29
29
  end
30
30
 
@@ -36,14 +36,14 @@ module Legion
36
36
  position: position,
37
37
  strength: strength
38
38
  )
39
- Legion::Logging.debug "[self_talk] add_turn: dialogue=#{dialogue_id} voice=#{voice_id} added=#{result[:added]}"
39
+ log.debug "[self_talk] add_turn: dialogue=#{dialogue_id} voice=#{voice_id} added=#{result[:added]}"
40
40
  result
41
41
  end
42
42
 
43
43
  def conclude_dialogue(dialogue_id:, summary: nil, **)
44
44
  resolved_summary = summary || generate_summary_for_dialogue(dialogue_id)
45
45
  result = engine.conclude_dialogue(dialogue_id: dialogue_id, summary: resolved_summary)
46
- Legion::Logging.info "[self_talk] conclude_dialogue: id=#{dialogue_id} concluded=#{result[:concluded]}"
46
+ log.info "[self_talk] conclude_dialogue: id=#{dialogue_id} concluded=#{result[:concluded]}"
47
47
  result
48
48
  end
49
49
 
@@ -59,37 +59,37 @@ module Legion
59
59
  content: content[:content],
60
60
  position: content[:position]
61
61
  )
62
- Legion::Logging.debug "[self_talk] generate_voice_turn: dialogue=#{dialogue_id} voice=#{voice_id} source=#{source}"
62
+ log.debug "[self_talk] generate_voice_turn: dialogue=#{dialogue_id} voice=#{voice_id} source=#{source}"
63
63
  { generated: true, source: source, turn: turn_result[:turn] }
64
64
  end
65
65
 
66
66
  def deadlock_dialogue(dialogue_id:, **)
67
67
  result = engine.deadlock_dialogue(dialogue_id: dialogue_id)
68
- Legion::Logging.warn "[self_talk] deadlock_dialogue: id=#{dialogue_id} deadlocked=#{result[:deadlocked]}"
68
+ log.warn "[self_talk] deadlock_dialogue: id=#{dialogue_id} deadlocked=#{result[:deadlocked]}"
69
69
  result
70
70
  end
71
71
 
72
72
  def amplify_voice(voice_id:, amount: Helpers::Constants::VOLUME_BOOST, **)
73
73
  result = engine.amplify_voice(voice_id: voice_id, amount: amount)
74
- Legion::Logging.debug "[self_talk] amplify_voice: id=#{voice_id} volume=#{result[:volume]}"
74
+ log.debug "[self_talk] amplify_voice: id=#{voice_id} volume=#{result[:volume]}"
75
75
  result
76
76
  end
77
77
 
78
78
  def dampen_voice(voice_id:, amount: Helpers::Constants::VOLUME_DECAY, **)
79
79
  result = engine.dampen_voice(voice_id: voice_id, amount: amount)
80
- Legion::Logging.debug "[self_talk] dampen_voice: id=#{voice_id} volume=#{result[:volume]}"
80
+ log.debug "[self_talk] dampen_voice: id=#{voice_id} volume=#{result[:volume]}"
81
81
  result
82
82
  end
83
83
 
84
84
  def dialogue_report(dialogue_id:, **)
85
85
  result = engine.dialogue_report(dialogue_id: dialogue_id)
86
- Legion::Logging.debug "[self_talk] dialogue_report: id=#{dialogue_id} found=#{result[:found]}"
86
+ log.debug "[self_talk] dialogue_report: id=#{dialogue_id} found=#{result[:found]}"
87
87
  result
88
88
  end
89
89
 
90
90
  def self_talk_status(**)
91
91
  summary = engine.to_h
92
- Legion::Logging.debug "[self_talk] status: voices=#{summary[:voice_count]} dialogues=#{summary[:dialogue_count]}"
92
+ log.debug "[self_talk] status: voices=#{summary[:voice_count]} dialogues=#{summary[:dialogue_count]}"
93
93
  summary
94
94
  end
95
95
 
@@ -100,7 +100,7 @@ module Legion
100
100
  decayed += 1
101
101
  { id: voice.id, name: voice.name, volume: voice.volume }
102
102
  end
103
- Legion::Logging.debug "[self-talk] voice decay: decayed=#{decayed} voices"
103
+ log.debug "[self-talk] voice decay: decayed=#{decayed} voices"
104
104
  { decayed: decayed, voices: voice_list }
105
105
  end
106
106
 
@@ -4,7 +4,7 @@ module Legion
4
4
  module Extensions
5
5
  module Agentic
6
6
  module Self
7
- VERSION = '0.1.1'
7
+ VERSION = '0.1.3'
8
8
  end
9
9
  end
10
10
  end
@@ -1,6 +1,82 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  RSpec.describe Legion::Extensions::Agentic::Self::Reflection::Helpers::LlmEnhancer do
4
+ let(:enhancer_mod) { described_class }
5
+
6
+ describe '.pipeline_available?' do
7
+ it 'returns false when GaiaCaller is not defined' do
8
+ begin
9
+ hide_const('Legion::LLM::Pipeline::GaiaCaller')
10
+ rescue StandardError
11
+ nil
12
+ end
13
+ expect(described_class.pipeline_available?).to be false
14
+ end
15
+
16
+ it 'returns false when pipeline_enabled? is false' do
17
+ stub_const('Legion::LLM::Pipeline::GaiaCaller', double)
18
+ stub_const('Legion::LLM', double(respond_to?: true, pipeline_enabled?: false))
19
+ expect(described_class.pipeline_available?).to be false
20
+ end
21
+
22
+ it 'returns true when GaiaCaller defined and pipeline enabled' do
23
+ gaia_caller_mod = Module.new
24
+ pipeline_mod = Module.new
25
+ pipeline_mod.const_set(:GaiaCaller, gaia_caller_mod)
26
+ llm_mod = Module.new
27
+ llm_mod.const_set(:Pipeline, pipeline_mod)
28
+ llm_mod.define_singleton_method(:respond_to?) { |*| true }
29
+ llm_mod.define_singleton_method(:pipeline_enabled?) { true }
30
+ stub_const('Legion::LLM', llm_mod)
31
+ expect(described_class.pipeline_available?).to be true
32
+ end
33
+
34
+ it 'returns false on any error' do
35
+ stub_const('Legion::LLM', double)
36
+ allow(Legion::LLM).to receive(:respond_to?).and_raise(StandardError)
37
+ expect(described_class.pipeline_available?).to be false
38
+ end
39
+ end
40
+
41
+ describe '.enhance' do
42
+ it 'uses GaiaCaller when pipeline is available' do
43
+ allow(enhancer_mod).to receive(:available?).and_return(true)
44
+ allow(enhancer_mod).to receive(:pipeline_available?).and_return(true)
45
+
46
+ mock_response = double(message: { content: 'reflected' })
47
+ gaia_caller_mod = Module.new
48
+ gaia_caller_mod.define_singleton_method(:chat) { |**| mock_response }
49
+ pipeline_mod = Module.new
50
+ pipeline_mod.const_set(:GaiaCaller, gaia_caller_mod)
51
+ llm_mod = Module.new
52
+ llm_mod.const_set(:Pipeline, pipeline_mod)
53
+ stub_const('Legion::LLM', llm_mod)
54
+
55
+ expect(gaia_caller_mod).to receive(:chat)
56
+ .with(hash_including(phase: 'reflection'))
57
+ .and_return(mock_response)
58
+
59
+ result = enhancer_mod.enhance('reflect on this', phase: 'reflection')
60
+ expect(result).to eq('reflected')
61
+ end
62
+
63
+ it 'falls back to legacy chat when pipeline unavailable' do
64
+ allow(enhancer_mod).to receive(:available?).and_return(true)
65
+ allow(enhancer_mod).to receive(:pipeline_available?).and_return(false)
66
+
67
+ mock_chat = double(ask: double(content: 'legacy reflected'))
68
+ stub_const('Legion::LLM', double(chat: mock_chat))
69
+
70
+ result = enhancer_mod.enhance('reflect on this', phase: 'reflection')
71
+ expect(result).to eq('legacy reflected')
72
+ end
73
+
74
+ it 'returns nil when not available' do
75
+ allow(enhancer_mod).to receive(:available?).and_return(false)
76
+ expect(enhancer_mod.enhance('hello')).to be_nil
77
+ end
78
+ end
79
+
4
80
  describe '.available?' do
5
81
  context 'when Legion::LLM is not defined' do
6
82
  it 'returns a falsy value' do
data/spec/spec_helper.rb CHANGED
@@ -1,16 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'bundler/setup'
4
+ require 'legion/logging'
5
+ require 'legion/settings'
6
+ require 'legion/cache/helper'
7
+ require 'legion/crypt/helper'
8
+ require 'legion/data/helper'
9
+ require 'legion/json/helper'
10
+ require 'legion/transport/helper'
4
11
 
5
12
  module Legion
6
- module Logging
7
- def self.debug(_msg); end
8
- def self.info(_msg); end
9
- def self.warn(_msg); end
10
- def self.error(_msg); end
11
- def self.fatal(_msg); end
12
- end
13
-
14
13
  module Extensions
15
14
  module Core
16
15
  def self.extended(_base); end
@@ -18,24 +17,30 @@ module Legion
18
17
 
19
18
  module Helpers
20
19
  module Lex
21
- def self.included(_base); end
20
+ include Legion::Logging::Helper
21
+ include Legion::Settings::Helper
22
+ include Legion::Cache::Helper
23
+ include Legion::Crypt::Helper
24
+ include Legion::Data::Helper
25
+ include Legion::JSON::Helper
26
+ include Legion::Transport::Helper
22
27
  end
23
28
  end
24
- end
25
- end
26
29
 
27
- # rubocop:disable Lint/EmptyClass, Style/OneClassPerFile
28
- module Legion
29
- module Extensions
30
30
  module Actors
31
- class Every; end
32
- class Once; end
31
+ class Every
32
+ include Helpers::Lex
33
+ end
34
+
35
+ class Once
36
+ include Helpers::Lex
37
+ end
33
38
  end
34
39
  end
35
40
  end
41
+
36
42
  $LOADED_FEATURES << 'legion/extensions/actors/every'
37
43
  $LOADED_FEATURES << 'legion/extensions/actors/once'
38
- # rubocop:enable Lint/EmptyClass, Style/OneClassPerFile
39
44
 
40
45
  require 'legion/extensions/agentic/self'
41
46