Class: Snapshot
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- Snapshot
- Includes:
- TokenEstimation
- Defined in:
- app/models/snapshot.rb
Overview
A persisted summary of conversation context created by Mneme before messages evict from the viewport. Snapshots capture the “gist” of what happened so the agent retains awareness of past context.
Level 1 snapshots are created from raw messages (conversation + thinks). Level 2 snapshots compress multiple Level 1 snapshots (days/weeks scale). Both levels use the same message ID range tracking — an L2 snapshot’s range is the union of its constituent L1 snapshots.
Constant Summary collapse
- MAX_TEXT_BYTES =
32KB — generous upper bound (~8K tokens). The LLM tool description advises a tighter limit (mneme_max_tokens), but this hard cap prevents unbounded storage.
32_768
Constants included from TokenEstimation
TokenEstimation::BYTES_PER_TOKEN
Instance Attribute Summary collapse
-
#from_message_id ⇒ Integer
First message ID covered by this snapshot.
-
#level ⇒ Integer
Compression level (1 = from raw messages, 2 = from L1 snapshots).
-
#text ⇒ String
The summary text generated by Mneme.
-
#to_message_id ⇒ Integer
Last message ID covered by this snapshot.
-
#token_count ⇒ Integer
Token count of the summary text.
Instance Method Summary collapse
-
#tokenization_text ⇒ String
Summary text used for token estimation and remote counting.
Methods included from TokenEstimation
estimate_token_count, #estimate_tokens
Instance Attribute Details
#from_message_id ⇒ Integer
Returns first message ID covered by this snapshot.
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'app/models/snapshot.rb', line 24 class Snapshot < ApplicationRecord include TokenEstimation belongs_to :session # 32KB — generous upper bound (~8K tokens). The LLM tool description advises # a tighter limit (mneme_max_tokens), but this hard cap prevents unbounded storage. MAX_TEXT_BYTES = 32_768 validates :text, presence: true, length: {maximum: MAX_TEXT_BYTES} validates :from_message_id, presence: true validates :to_message_id, presence: true validates :level, presence: true, numericality: {greater_than: 0} validates :token_count, numericality: {greater_than_or_equal_to: 0} validate :from_message_id_not_after_to_message_id scope :for_level, ->(level) { where(level: level) } scope :chronological, -> { order(:from_message_id) } # @return [String] summary text used for token estimation and remote counting def tokenization_text text.to_s end # L1 snapshots whose message range is NOT fully contained within any L2 snapshot. # Used to determine which L1 snapshots are still "live" in the viewport. scope :not_covered_by_l2, -> { where.not( "EXISTS (SELECT 1 FROM snapshots l2 " \ "WHERE l2.session_id = snapshots.session_id " \ "AND l2.level = 2 " \ "AND l2.from_message_id <= snapshots.from_message_id " \ "AND l2.to_message_id >= snapshots.to_message_id)" ) } private def return unless && errors.add(:from_message_id, "must be <= to_message_id") if > end end |
#level ⇒ Integer
Returns compression level (1 = from raw messages, 2 = from L1 snapshots).
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'app/models/snapshot.rb', line 24 class Snapshot < ApplicationRecord include TokenEstimation belongs_to :session # 32KB — generous upper bound (~8K tokens). The LLM tool description advises # a tighter limit (mneme_max_tokens), but this hard cap prevents unbounded storage. MAX_TEXT_BYTES = 32_768 validates :text, presence: true, length: {maximum: MAX_TEXT_BYTES} validates :from_message_id, presence: true validates :to_message_id, presence: true validates :level, presence: true, numericality: {greater_than: 0} validates :token_count, numericality: {greater_than_or_equal_to: 0} validate :from_message_id_not_after_to_message_id scope :for_level, ->(level) { where(level: level) } scope :chronological, -> { order(:from_message_id) } # @return [String] summary text used for token estimation and remote counting def tokenization_text text.to_s end # L1 snapshots whose message range is NOT fully contained within any L2 snapshot. # Used to determine which L1 snapshots are still "live" in the viewport. scope :not_covered_by_l2, -> { where.not( "EXISTS (SELECT 1 FROM snapshots l2 " \ "WHERE l2.session_id = snapshots.session_id " \ "AND l2.level = 2 " \ "AND l2.from_message_id <= snapshots.from_message_id " \ "AND l2.to_message_id >= snapshots.to_message_id)" ) } private def return unless && errors.add(:from_message_id, "must be <= to_message_id") if > end end |
#text ⇒ String
Returns the summary text generated by Mneme.
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'app/models/snapshot.rb', line 24 class Snapshot < ApplicationRecord include TokenEstimation belongs_to :session # 32KB — generous upper bound (~8K tokens). The LLM tool description advises # a tighter limit (mneme_max_tokens), but this hard cap prevents unbounded storage. MAX_TEXT_BYTES = 32_768 validates :text, presence: true, length: {maximum: MAX_TEXT_BYTES} validates :from_message_id, presence: true validates :to_message_id, presence: true validates :level, presence: true, numericality: {greater_than: 0} validates :token_count, numericality: {greater_than_or_equal_to: 0} validate :from_message_id_not_after_to_message_id scope :for_level, ->(level) { where(level: level) } scope :chronological, -> { order(:from_message_id) } # @return [String] summary text used for token estimation and remote counting def tokenization_text text.to_s end # L1 snapshots whose message range is NOT fully contained within any L2 snapshot. # Used to determine which L1 snapshots are still "live" in the viewport. scope :not_covered_by_l2, -> { where.not( "EXISTS (SELECT 1 FROM snapshots l2 " \ "WHERE l2.session_id = snapshots.session_id " \ "AND l2.level = 2 " \ "AND l2.from_message_id <= snapshots.from_message_id " \ "AND l2.to_message_id >= snapshots.to_message_id)" ) } private def return unless && errors.add(:from_message_id, "must be <= to_message_id") if > end end |
#to_message_id ⇒ Integer
Returns last message ID covered by this snapshot.
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'app/models/snapshot.rb', line 24 class Snapshot < ApplicationRecord include TokenEstimation belongs_to :session # 32KB — generous upper bound (~8K tokens). The LLM tool description advises # a tighter limit (mneme_max_tokens), but this hard cap prevents unbounded storage. MAX_TEXT_BYTES = 32_768 validates :text, presence: true, length: {maximum: MAX_TEXT_BYTES} validates :from_message_id, presence: true validates :to_message_id, presence: true validates :level, presence: true, numericality: {greater_than: 0} validates :token_count, numericality: {greater_than_or_equal_to: 0} validate :from_message_id_not_after_to_message_id scope :for_level, ->(level) { where(level: level) } scope :chronological, -> { order(:from_message_id) } # @return [String] summary text used for token estimation and remote counting def tokenization_text text.to_s end # L1 snapshots whose message range is NOT fully contained within any L2 snapshot. # Used to determine which L1 snapshots are still "live" in the viewport. scope :not_covered_by_l2, -> { where.not( "EXISTS (SELECT 1 FROM snapshots l2 " \ "WHERE l2.session_id = snapshots.session_id " \ "AND l2.level = 2 " \ "AND l2.from_message_id <= snapshots.from_message_id " \ "AND l2.to_message_id >= snapshots.to_message_id)" ) } private def return unless && errors.add(:from_message_id, "must be <= to_message_id") if > end end |
#token_count ⇒ Integer
Returns token count of the summary text. Seeded with a local estimate on create and later refined by CountTokensJob using the real Anthropic tokenizer.
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'app/models/snapshot.rb', line 24 class Snapshot < ApplicationRecord include TokenEstimation belongs_to :session # 32KB — generous upper bound (~8K tokens). The LLM tool description advises # a tighter limit (mneme_max_tokens), but this hard cap prevents unbounded storage. MAX_TEXT_BYTES = 32_768 validates :text, presence: true, length: {maximum: MAX_TEXT_BYTES} validates :from_message_id, presence: true validates :to_message_id, presence: true validates :level, presence: true, numericality: {greater_than: 0} validates :token_count, numericality: {greater_than_or_equal_to: 0} validate :from_message_id_not_after_to_message_id scope :for_level, ->(level) { where(level: level) } scope :chronological, -> { order(:from_message_id) } # @return [String] summary text used for token estimation and remote counting def tokenization_text text.to_s end # L1 snapshots whose message range is NOT fully contained within any L2 snapshot. # Used to determine which L1 snapshots are still "live" in the viewport. scope :not_covered_by_l2, -> { where.not( "EXISTS (SELECT 1 FROM snapshots l2 " \ "WHERE l2.session_id = snapshots.session_id " \ "AND l2.level = 2 " \ "AND l2.from_message_id <= snapshots.from_message_id " \ "AND l2.to_message_id >= snapshots.to_message_id)" ) } private def return unless && errors.add(:from_message_id, "must be <= to_message_id") if > end end |
Instance Method Details
#tokenization_text ⇒ String
Returns summary text used for token estimation and remote counting.
44 45 46 |
# File 'app/models/snapshot.rb', line 44 def tokenization_text text.to_s end |