Class: PinnedMessage

Inherits:
ApplicationRecord show all
Includes:
TokenEstimation
Defined in:
app/models/pinned_message.rb

Overview

A conversation message pinned to one or more Goals by Mneme to protect it from viewport eviction. Pinned messages appear in the Goals section of the viewport, giving the main agent access to critical context that would otherwise scroll out of the sliding window.

Pinning is goal-scoped: when all Goals referencing a pin complete, the pin is automatically released (reference-counted cleanup).

Constant Summary collapse

MAX_DISPLAY_TEXT_LENGTH =

Display text limit — enough to recognize content, cheap on tokens.

200

Constants included from TokenEstimation

TokenEstimation::BYTES_PER_TOKEN

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from TokenEstimation

estimate_token_count, #estimate_tokens

Instance Attribute Details

#display_textString

Returns truncated message content (~200 chars) shown in the Goals section.

Returns:

  • (String)

    truncated message content (~200 chars) shown in the Goals section



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'app/models/pinned_message.rb', line 16

class PinnedMessage < ApplicationRecord
  include TokenEstimation

  # Display text limit — enough to recognize content, cheap on tokens.
  MAX_DISPLAY_TEXT_LENGTH = 200

  belongs_to :message

  has_many :goal_pinned_messages, dependent: :destroy
  has_many :goals, through: :goal_pinned_messages

  validates :display_text, presence: true, length: {maximum: MAX_DISPLAY_TEXT_LENGTH}
  validates :message_id, uniqueness: true

  # Pinned messages with no remaining active goals — safe to release.
  #
  # @return [ActiveRecord::Relation]
  scope :orphaned, -> {
    where.not(
      "EXISTS (SELECT 1 FROM goal_pinned_messages gpm " \
      "JOIN goals ON goals.id = gpm.goal_id " \
      "WHERE gpm.pinned_message_id = pinned_messages.id " \
      "AND goals.status = 'active')"
    )
  }

  # @return [String] truncated display text used for token estimation and counting
  def tokenization_text
    display_text.to_s
  end
end

#token_countInteger

Returns token count of #display_text. Seeded with a local estimate on create and later refined by CountTokensJob.

Returns:



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'app/models/pinned_message.rb', line 16

class PinnedMessage < ApplicationRecord
  include TokenEstimation

  # Display text limit — enough to recognize content, cheap on tokens.
  MAX_DISPLAY_TEXT_LENGTH = 200

  belongs_to :message

  has_many :goal_pinned_messages, dependent: :destroy
  has_many :goals, through: :goal_pinned_messages

  validates :display_text, presence: true, length: {maximum: MAX_DISPLAY_TEXT_LENGTH}
  validates :message_id, uniqueness: true

  # Pinned messages with no remaining active goals — safe to release.
  #
  # @return [ActiveRecord::Relation]
  scope :orphaned, -> {
    where.not(
      "EXISTS (SELECT 1 FROM goal_pinned_messages gpm " \
      "JOIN goals ON goals.id = gpm.goal_id " \
      "WHERE gpm.pinned_message_id = pinned_messages.id " \
      "AND goals.status = 'active')"
    )
  }

  # @return [String] truncated display text used for token estimation and counting
  def tokenization_text
    display_text.to_s
  end
end

Instance Method Details

#orphanedActiveRecord::Relation

Pinned messages with no remaining active goals — safe to release.

Returns:

  • (ActiveRecord::Relation)


33
34
35
36
37
38
39
40
# File 'app/models/pinned_message.rb', line 33

scope :orphaned, -> {
  where.not(
    "EXISTS (SELECT 1 FROM goal_pinned_messages gpm " \
    "JOIN goals ON goals.id = gpm.goal_id " \
    "WHERE gpm.pinned_message_id = pinned_messages.id " \
    "AND goals.status = 'active')"
  )
}

#tokenization_textString

Returns truncated display text used for token estimation and counting.

Returns:

  • (String)

    truncated display text used for token estimation and counting



43
44
45
# File 'app/models/pinned_message.rb', line 43

def tokenization_text
  display_text.to_s
end