Module: Legion::LLM::ContentHash

Defined in:
lib/legion/llm/content_hash.rb

Overview

Canonical SHA-256 content hash used wherever an opaque, deterministic fingerprint of textual content is needed (audit ledger request_content_hash / response_content_hash, embedding cache keys, RAG document IDs, etc.). One implementation, one normalization, so records join across systems (G19a).

Accepts either:

- String / nil
- Array<Hash> (message-shaped: each entry's :content or 'content' key)
- any other object that responds to #to_s

Returns the lowercase SHA-256 hex digest, or nil for empty/missing content.

Class Method Summary collapse

Class Method Details

.call(content) ⇒ Object



21
22
23
24
25
26
# File 'lib/legion/llm/content_hash.rb', line 21

def call(content)
  text = normalize(content)
  return nil if text.nil? || text.empty?

  Digest::SHA256.hexdigest(text)
end

.extract_message_text(message) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/legion/llm/content_hash.rb', line 38

def extract_message_text(message)
  return message.to_s unless message.is_a?(Hash)

  # Prefer string-key access (matches AuditPublisher#hash_value precedence
  # so the digest is byte-compatible with previously-emitted ledger rows).
  value = if message.key?('content')
            message['content']
          elsif message.key?(:content)
            message[:content]
          end
  (value || message).to_s
end

.normalize(content) ⇒ Object



28
29
30
31
32
33
34
35
36
# File 'lib/legion/llm/content_hash.rb', line 28

def normalize(content)
  return nil if content.nil?

  if content.is_a?(Array)
    content.map { |m| extract_message_text(m) }.join("\n")
  else
    content.to_s
  end
end