Class: Legion::CLI::Chat::Tools::Reflect
Constant Summary
collapse
- DEFAULT_PORT =
4567
- DEFAULT_HOST =
'127.0.0.1'
<<~PROMPT
Extract discrete, reusable knowledge entries from the following text.
Each entry should be a standalone fact, pattern, decision, or procedure
that would be useful in future conversations.
Rules:
- One entry per line, prefixed with "- "
- Be specific and actionable, not vague
- Include context (file paths, module names, patterns)
- Skip trivial observations
- Maximum 5 entries
Return ONLY the entries, no headers or commentary.
PROMPT
Class Method Summary
collapse
Methods inherited from Tools::Base
deferred, deferred?, description, error_response, extension, handle_exception, input_schema, log, mcp_category, mcp_tier, runner, sticky, tags, text_response, tool_name, trigger_words
Class Method Details
.api_port ⇒ Object
130
131
132
133
134
135
136
|
# File 'lib/legion/cli/chat/tools/reflect.rb', line 130
def self.api_port
return DEFAULT_PORT unless defined?(Legion::Settings)
Legion::Settings[:api]&.dig(:port) || DEFAULT_PORT
rescue StandardError
DEFAULT_PORT
end
|
.call(text:, domain: nil) ⇒ Object
49
50
51
52
53
54
55
56
57
58
|
# File 'lib/legion/cli/chat/tools/reflect.rb', line 49
def self.call(text:, domain: nil)
entries = (text)
return 'No actionable knowledge found to reflect on.' if entries.empty?
results = ingest_entries(entries, domain)
format_results(entries, results)
rescue StandardError => e
Legion::Logging.warn("Reflect#execute failed: #{e.message}") if defined?(Legion::Logging)
"Error during reflection: #{e.message}"
end
|
60
61
62
63
64
65
66
67
68
69
70
|
# File 'lib/legion/cli/chat/tools/reflect.rb', line 60
def self.(text)
return [text] unless llm_available?
response = Legion::LLM.chat_direct(
message: "#{EXTRACTION_PROMPT}\n\nText:\n#{text}",
model: nil, provider: nil
)
parse_entries(response.content)
rescue StandardError
[text]
end
|
118
119
120
121
122
123
124
|
# File 'lib/legion/cli/chat/tools/reflect.rb', line 118
def self.format_results(entries, results)
lines = ["Reflected on #{entries.size} knowledge entries:\n"]
entries.each_with_index { |e, i| lines << " #{i + 1}. #{e}" }
lines << ''
lines << "Saved: #{results[:apollo]} to Apollo, #{results[:memory]} to memory"
lines.join("\n")
end
|
.ingest_entries(entries, domain) ⇒ Object
81
82
83
84
85
86
87
88
|
# File 'lib/legion/cli/chat/tools/reflect.rb', line 81
def self.ingest_entries(entries, domain)
results = { apollo: 0, memory: 0 }
entries.each do |entry|
results[:apollo] += 1 if ingest_to_apollo(entry, domain)
results[:memory] += 1 if save_to_memory(entry)
end
results
end
|
.ingest_to_apollo(content, domain) ⇒ Object
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
# File 'lib/legion/cli/chat/tools/reflect.rb', line 90
def self.ingest_to_apollo(content, domain)
uri = URI("http://#{DEFAULT_HOST}:#{api_port}/api/apollo/ingest")
http = Net::HTTP.new(uri.host, uri.port)
http.open_timeout = 2
http.read_timeout = 5
req = Net::HTTP::Post.new(uri.path, 'Content-Type' => 'application/json')
req.body = ::JSON.dump({
content: content,
content_type: 'observation',
tags: %w[reflection auto-learned],
source_agent: 'chat',
source_channel: 'reflection',
knowledge_domain: domain
})
response = http.request(req)
response.is_a?(Net::HTTPSuccess)
rescue StandardError
false
end
|
.llm_available? ⇒ Boolean
126
127
128
|
# File 'lib/legion/cli/chat/tools/reflect.rb', line 126
def self.llm_available?
defined?(Legion::LLM) && Legion::LLM.respond_to?(:chat_direct)
end
|
.parse_entries(content) ⇒ Object
72
73
74
75
76
77
78
79
|
# File 'lib/legion/cli/chat/tools/reflect.rb', line 72
def self.parse_entries(content)
content.lines
.map(&:strip)
.select { |line| line.start_with?('- ') }
.map { |line| line.sub(/\A- /, '').strip }
.reject(&:empty?)
.first(5)
end
|
.save_to_memory(entry) ⇒ Object
110
111
112
113
114
115
116
|
# File 'lib/legion/cli/chat/tools/reflect.rb', line 110
def self.save_to_memory(entry)
require 'legion/cli/chat/memory_store'
MemoryStore.add(entry, scope: :project)
true
rescue StandardError
false
end
|