Class: Silas::Memory
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- Silas::Memory
- Defined in:
- app/models/silas/memory.rb
Overview
One remembered fact. Triple-ish (subject · attribute · content) with provenance (which turn wrote it) and supersession: a new fact about the same (agent, scope, subject, attribute) retires the old one — temporal versioning without a temporal store. Edges between memories are a deliberate not-yet: add them when a real agent needs multi-hop.
Constant Summary collapse
- SCOPES =
%w[agent app].freeze
Class Method Summary collapse
-
.recall(agent_name:, subjects: [], limit: 10) ⇒ Object
What an agent can see: its own memories + app-shared ones.
-
.remember!(agent_name:, subject:, content:, attribute: nil, scope: "agent", turn: nil) ⇒ Object
Write-through with supersession.
Instance Method Summary collapse
Class Method Details
.recall(agent_name:, subjects: [], limit: 10) ⇒ Object
What an agent can see: its own memories + app-shared ones. Subject-matched first (when subjects given), then most recent.
34 35 36 37 38 39 40 41 42 43 44 |
# File 'app/models/silas/memory.rb', line 34 def self.recall(agent_name:, subjects: [], limit: 10) visible = active.where("agent_name = :a OR scope = 'app'", a: agent_name) if subjects.any? keys = subjects.map { |s| s.to_s.strip.downcase } matched = visible.where(subject: keys).order(created_at: :desc).limit(limit).to_a rest = visible.where.not(subject: keys).order(created_at: :desc).limit(limit - matched.size) matched + rest else visible.order(created_at: :desc).limit(limit).to_a end end |
.remember!(agent_name:, subject:, content:, attribute: nil, scope: "agent", turn: nil) ⇒ Object
Write-through with supersession. attribute nil = free-form note about the subject (accumulates); attribute present = the triple's slot (supersedes).
18 19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'app/models/silas/memory.rb', line 18 def self.remember!(agent_name:, subject:, content:, attribute: nil, scope: "agent", turn: nil) transaction do record = create!(agent_name:, scope:, subject: subject.to_s.strip.downcase, attribute_name: attribute.presence&.strip&.downcase, content:, session_id: turn&.session_id, turn_id: turn&.id) if record.attribute_name active.where(agent_name:, scope:, subject: record.subject, attribute_name: record.attribute_name) .where.not(id: record.id) .update_all(status: "superseded", superseded_by_id: record.id, updated_at: Time.current) end record end end |
Instance Method Details
#to_line ⇒ Object
46 47 48 49 |
# File 'app/models/silas/memory.rb', line 46 def to_line head = attribute_name ? "#{subject} · #{attribute_name}: " : "#{subject}: " head + content end |