Class: ClaudeMemory::MCP::ResponseFormatter
- Inherits:
-
Object
- Object
- ClaudeMemory::MCP::ResponseFormatter
- Defined in:
- lib/claude_memory/mcp/response_formatter.rb
Overview
Pure logic for formatting domain objects into MCP tool responses Follows Functional Core pattern - no I/O, just transformations
Class Method Summary collapse
-
.append_line_range(result, receipt) ⇒ Object
Append stored line range from provenance if available.
-
.append_snippet(result, receipt, query) ⇒ Object
Extract and append snippet from raw_text if available.
-
.format_change(change) ⇒ Hash
Format single change record.
-
.format_changes(since, changes) ⇒ Hash
Format changes list into MCP response.
-
.format_concept_fact(result, compact: false, query: nil) ⇒ Hash
Format single concept search fact with multi-concept similarity.
-
.format_concept_results(concepts, scope, results, compact: false) ⇒ Hash
Format concept search results.
-
.format_conflict(conflict) ⇒ Hash
Format single conflict record.
-
.format_conflicts(conflicts) ⇒ Hash
Format conflicts list into MCP response.
-
.format_context_facts(context_type, context_value, scope, results) ⇒ Hash
Format facts_by_context query results.
-
.format_detailed_explanation(explanation) ⇒ Hash
Format detailed explanation for recall_details response.
-
.format_detailed_receipt(receipt, query: nil) ⇒ Hash
Format detailed receipt with session and timestamp.
-
.format_explanation(explanation, scope) ⇒ Hash
Format explanation with full fact details and relationships.
-
.format_generic_fact(result) ⇒ Hash
Format generic fact with scope and receipts.
-
.format_index_fact(result) ⇒ Hash
Format single index fact with preview.
-
.format_index_results(query, scope, results) ⇒ Hash
Format index query results with token estimates.
-
.format_recall_fact(result, compact: false, query: nil) ⇒ Hash
Format single recall fact result.
-
.format_recall_results(results, compact: false, query: nil) ⇒ Hash
Format recall query results into MCP response.
-
.format_receipt(receipt, query: nil) ⇒ Hash
Format receipt (provenance) with minimal fields.
-
.format_semantic_fact(result, compact: false, query: nil) ⇒ Hash
Format single semantic search fact with similarity.
-
.format_semantic_results(query, mode, scope, results, compact: false) ⇒ Hash
Format semantic search results with similarity scores.
-
.format_shortcut_fact(result) ⇒ Hash
Format fact for shortcut queries (includes scope, no status).
-
.format_shortcut_results(category, results) ⇒ Hash
Format shortcut query results (decisions, architecture, etc.).
-
.format_sweep_stats(scope, stats) ⇒ Hash
Format sweep statistics into MCP response.
-
.format_tool_facts(tool_name, scope, results) ⇒ Hash
Format facts_by_tool query results.
Class Method Details
.append_line_range(result, receipt) ⇒ Object
Append stored line range from provenance if available
159 160 161 162 163 164 |
# File 'lib/claude_memory/mcp/response_formatter.rb', line 159 def self.append_line_range(result, receipt) return unless receipt[:line_start] result[:line_start] = receipt[:line_start] result[:line_end] = receipt[:line_end] end |
.append_snippet(result, receipt, query) ⇒ Object
Extract and append snippet from raw_text if available
170 171 172 173 174 175 176 177 178 179 |
# File 'lib/claude_memory/mcp/response_formatter.rb', line 170 def self.append_snippet(result, receipt, query) return unless query && receipt[:raw_text] extracted = Core::SnippetExtractor.extract_with_lines(receipt[:raw_text], query) return unless extracted result[:snippet] = extracted[:snippet] result[:line_start] = extracted[:line_start] result[:line_end] = extracted[:line_end] end |
.format_change(change) ⇒ Hash
Format single change record
195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/claude_memory/mcp/response_formatter.rb', line 195 def self.format_change(change) { id: change[:id], docid: change[:docid], predicate: change[:predicate], object: change[:object_literal], status: change[:status], created_at: change[:created_at], created_ago: Core::RelativeTime.format(change[:created_at]), source: change[:source] } end |
.format_changes(since, changes) ⇒ Hash
Format changes list into MCP response
185 186 187 188 189 190 |
# File 'lib/claude_memory/mcp/response_formatter.rb', line 185 def self.format_changes(since, changes) { since: since, changes: changes.map { |c| format_change(c) } } end |
.format_concept_fact(result, compact: false, query: nil) ⇒ Hash
Format single concept search fact with multi-concept similarity
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 |
# File 'lib/claude_memory/mcp/response_formatter.rb', line 307 def self.format_concept_fact(result, compact: false, query: nil) fact = { id: result[:fact][:id], docid: result[:fact][:docid], subject: result[:fact][:subject_name], predicate: result[:fact][:predicate], object: result[:fact][:object_literal], scope: result[:fact][:scope], source: result[:source], average_similarity: result[:similarity], concept_similarities: result[:concept_similarities] } fact[:receipts] = result[:receipts].map { |r| format_receipt(r, query: query) } unless compact fact end |
.format_concept_results(concepts, scope, results, compact: false) ⇒ Hash
Format concept search results
292 293 294 295 296 297 298 299 300 |
# File 'lib/claude_memory/mcp/response_formatter.rb', line 292 def self.format_concept_results(concepts, scope, results, compact: false) query = concepts.join(" ") { concepts: concepts, scope: scope, count: results.size, facts: results.map { |r| format_concept_fact(r, compact: compact, query: query) } } end |
.format_conflict(conflict) ⇒ Hash
Format single conflict record
221 222 223 224 225 226 227 228 229 |
# File 'lib/claude_memory/mcp/response_formatter.rb', line 221 def self.format_conflict(conflict) { id: conflict[:id], fact_a: conflict[:fact_a_id], fact_b: conflict[:fact_b_id], status: conflict[:status], source: conflict[:source] } end |
.format_conflicts(conflicts) ⇒ Hash
Format conflicts list into MCP response
211 212 213 214 215 216 |
# File 'lib/claude_memory/mcp/response_formatter.rb', line 211 def self.format_conflicts(conflicts) { count: conflicts.size, conflicts: conflicts.map { |c| format_conflict(c) } } end |
.format_context_facts(context_type, context_value, scope, results) ⇒ Hash
Format facts_by_context query results
370 371 372 373 374 375 376 377 378 |
# File 'lib/claude_memory/mcp/response_formatter.rb', line 370 def self.format_context_facts(context_type, context_value, scope, results) { context_type: context_type, context_value: context_value, scope: scope, count: results.size, facts: results.map { |r| format_generic_fact(r) } } end |
.format_detailed_explanation(explanation) ⇒ Hash
Format detailed explanation for recall_details response
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/claude_memory/mcp/response_formatter.rb', line 104 def self.format_detailed_explanation(explanation) { fact: { id: explanation[:fact][:id], docid: explanation[:fact][:docid], subject: explanation[:fact][:subject_name], predicate: explanation[:fact][:predicate], object: explanation[:fact][:object_literal], status: explanation[:fact][:status], confidence: explanation[:fact][:confidence], scope: explanation[:fact][:scope], valid_from: explanation[:fact][:valid_from], valid_from_ago: Core::RelativeTime.format(explanation[:fact][:valid_from]), valid_to: explanation[:fact][:valid_to] }, receipts: explanation[:receipts].map { |r| format_detailed_receipt(r) }, relationships: { supersedes: explanation[:supersedes], superseded_by: explanation[:superseded_by], conflicts: explanation[:conflicts].map { |c| {id: c[:id], status: c[:status]} } } } end |
.format_detailed_receipt(receipt, query: nil) ⇒ Hash
Format detailed receipt with session and timestamp
143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/claude_memory/mcp/response_formatter.rb', line 143 def self.format_detailed_receipt(receipt, query: nil) result = { quote: receipt[:quote], strength: receipt[:strength], session_id: receipt[:session_id], occurred_at: receipt[:occurred_at], occurred_ago: Core::RelativeTime.format(receipt[:occurred_at]) } append_line_range(result, receipt) append_snippet(result, receipt, query) result end |
.format_explanation(explanation, scope) ⇒ Hash
Format explanation with full fact details and relationships
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/claude_memory/mcp/response_formatter.rb', line 80 def self.format_explanation(explanation, scope) { fact: { id: explanation[:fact][:id], docid: explanation[:fact][:docid], subject: explanation[:fact][:subject_name], predicate: explanation[:fact][:predicate], object: explanation[:fact][:object_literal], status: explanation[:fact][:status], valid_from: explanation[:fact][:valid_from], valid_from_ago: Core::RelativeTime.format(explanation[:fact][:valid_from]), valid_to: explanation[:fact][:valid_to] }, source: scope, receipts: explanation[:receipts].map { |p| format_receipt(p) }, supersedes: explanation[:supersedes], superseded_by: explanation[:superseded_by], conflicts: explanation[:conflicts].map { |c| c[:id] } } end |
.format_generic_fact(result) ⇒ Hash
Format generic fact with scope and receipts
383 384 385 386 387 388 389 390 391 392 393 394 |
# File 'lib/claude_memory/mcp/response_formatter.rb', line 383 def self.format_generic_fact(result) { id: result[:fact][:id], docid: result[:fact][:docid], subject: result[:fact][:subject_name], predicate: result[:fact][:predicate], object: result[:fact][:object_literal], scope: result[:fact][:scope], source: result[:source], receipts: result[:receipts].map { |r| format_receipt(r) } } end |
.format_index_fact(result) ⇒ Hash
Format single index fact with preview
61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/claude_memory/mcp/response_formatter.rb', line 61 def self.format_index_fact(result) { id: result[:id], docid: result[:docid], subject: result[:subject], predicate: result[:predicate], object_preview: result[:object_preview], status: result[:status], scope: result[:scope], confidence: result[:confidence], tokens: result[:token_estimate], source: result[:source] } end |
.format_index_results(query, scope, results) ⇒ Hash
Format index query results with token estimates
46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/claude_memory/mcp/response_formatter.rb', line 46 def self.format_index_results(query, scope, results) total_tokens = results.sum { |r| r[:token_estimate] } { query: query, scope: scope, result_count: results.size, total_estimated_tokens: total_tokens, facts: results.map { |r| format_index_fact(r) } } end |
.format_recall_fact(result, compact: false, query: nil) ⇒ Hash
Format single recall fact result
27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/claude_memory/mcp/response_formatter.rb', line 27 def self.format_recall_fact(result, compact: false, query: nil) fact = { id: result[:fact][:id], docid: result[:fact][:docid], subject: result[:fact][:subject_name], predicate: result[:fact][:predicate], object: result[:fact][:object_literal], status: result[:fact][:status], source: result[:source] } fact[:receipts] = result[:receipts].map { |p| format_receipt(p, query: query) } unless compact fact end |
.format_recall_results(results, compact: false, query: nil) ⇒ Hash
Format recall query results into MCP response
16 17 18 19 20 |
# File 'lib/claude_memory/mcp/response_formatter.rb', line 16 def self.format_recall_results(results, compact: false, query: nil) { facts: results.map { |r| format_recall_fact(r, compact: compact, query: query) } } end |
.format_receipt(receipt, query: nil) ⇒ Hash
Format receipt (provenance) with minimal fields
132 133 134 135 136 137 |
# File 'lib/claude_memory/mcp/response_formatter.rb', line 132 def self.format_receipt(receipt, query: nil) result = {quote: receipt[:quote], strength: receipt[:strength]} append_line_range(result, receipt) append_snippet(result, receipt, query) result end |
.format_semantic_fact(result, compact: false, query: nil) ⇒ Hash
Format single semantic search fact with similarity
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 |
# File 'lib/claude_memory/mcp/response_formatter.rb', line 270 def self.format_semantic_fact(result, compact: false, query: nil) fact = { id: result[:fact][:id], docid: result[:fact][:docid], subject: result[:fact][:subject_name], predicate: result[:fact][:predicate], object: result[:fact][:object_literal], scope: result[:fact][:scope], source: result[:source], similarity: result[:similarity] } fact[:score_trace] = result[:score_trace] if result[:score_trace] fact[:receipts] = result[:receipts].map { |r| format_receipt(r, query: query) } unless compact fact end |
.format_semantic_results(query, mode, scope, results, compact: false) ⇒ Hash
Format semantic search results with similarity scores
255 256 257 258 259 260 261 262 263 |
# File 'lib/claude_memory/mcp/response_formatter.rb', line 255 def self.format_semantic_results(query, mode, scope, results, compact: false) { query: query, mode: mode, scope: scope, count: results.size, facts: results.map { |r| format_semantic_fact(r, compact: compact, query: query) } } end |
.format_shortcut_fact(result) ⇒ Hash
Format fact for shortcut queries (includes scope, no status)
338 339 340 341 342 343 344 345 346 347 348 |
# File 'lib/claude_memory/mcp/response_formatter.rb', line 338 def self.format_shortcut_fact(result) { id: result[:fact][:id], docid: result[:fact][:docid], subject: result[:fact][:subject_name], predicate: result[:fact][:predicate], object: result[:fact][:object_literal], scope: result[:fact][:scope], source: result[:source] } end |
.format_shortcut_results(category, results) ⇒ Hash
Format shortcut query results (decisions, architecture, etc.)
327 328 329 330 331 332 333 |
# File 'lib/claude_memory/mcp/response_formatter.rb', line 327 def self.format_shortcut_results(category, results) { category: category, count: results.size, facts: results.map { |r| format_shortcut_fact(r) } } end |
.format_sweep_stats(scope, stats) ⇒ Hash
Format sweep statistics into MCP response
235 236 237 238 239 240 241 242 243 244 245 246 |
# File 'lib/claude_memory/mcp/response_formatter.rb', line 235 def self.format_sweep_stats(scope, stats) result = { scope: scope, proposed_expired: stats[:proposed_facts_expired], disputed_expired: stats[:disputed_facts_expired], orphaned_deleted: stats[:orphaned_provenance_deleted], content_pruned: stats[:old_content_pruned], elapsed_seconds: stats[:elapsed_seconds].round(3) } result[:escalation_level] = stats[:escalation_level].to_s if stats[:escalation_level] result end |
.format_tool_facts(tool_name, scope, results) ⇒ Hash
Format facts_by_tool query results
355 356 357 358 359 360 361 362 |
# File 'lib/claude_memory/mcp/response_formatter.rb', line 355 def self.format_tool_facts(tool_name, scope, results) { tool_name: tool_name, scope: scope, count: results.size, facts: results.map { |r| format_generic_fact(r) } } end |