Class: Insika::MemoryStore

Inherits:
Object
  • Object
show all
Defined in:
lib/insika/memory_store.rb

Overview

AGENT-MEMORY DOMAIN store. Two layers scoped per tenant over any Insika::Store: profile (stable key-value facts) and notes (append-only free-form notes). Mirrors the PendingActionStore (normalizes symbol→string on write, O(n) scan on read, records with a timestamp).

NOT to be confused with Insika::Stores::Memory (in-memory KV backend): this is the domain store; that one is one of the backends this writes to.

Defined Under Namespace

Classes: Fact, Note

Constant Summary collapse

SCOPE_PREFIX =

scope = "memory:"

"memory"
FACT_PREFIX =
"fact:"
NOTE_PREFIX =
"note:"
DEFAULT_TENANT =

no tenant in the Command

"_default"

Instance Method Summary collapse

Constructor Details

#initialize(store:) ⇒ MemoryStore

Returns a new instance of MemoryStore.



24
25
26
# File 'lib/insika/memory_store.rb', line 24

def initialize(store:)
  @store = store
end

Instance Method Details

#add_note(tenant:, text:, id: SecureRandom.uuid, at: nil) ⇒ Object

Append. at (ISO8601) goes at the START of the key so list returns the notes in chronological order; id/at injectable for deterministic tests. -> Note



57
58
59
60
61
62
# File 'lib/insika/memory_store.rb', line 57

def add_note(tenant:, text:, id: SecureRandom.uuid, at: nil)
  at ||= timestamp
  record = { "id" => id.to_s, "text" => text.to_s, "created_at" => at }
  @store.set(scope_for(tenant), NOTE_PREFIX + "#{at}:#{id}", record)
  to_note(record)
end

#facts(tenant:) ⇒ Object

-> [Fact] sorted by key (list is lexicographic).



42
43
44
45
46
47
48
# File 'lib/insika/memory_store.rb', line 42

def facts(tenant:)
  scope = scope_for(tenant)
  @store.list(scope, FACT_PREFIX).filter_map do |k|
    record = @store.get(scope, k)
    record && to_fact(record)
  end
end

#forget_fact(tenant:, key:) ⇒ Object

-> bool (did it exist?)



51
52
53
# File 'lib/insika/memory_store.rb', line 51

def forget_fact(tenant:, key:)
  @store.delete(scope_for(tenant), FACT_PREFIX + key.to_s)
end

#get_fact(tenant:, key:) ⇒ Object

-> Fact | nil



36
37
38
39
# File 'lib/insika/memory_store.rb', line 36

def get_fact(tenant:, key:)
  record = @store.get(scope_for(tenant), FACT_PREFIX + key.to_s)
  record && to_fact(record)
end

#notes(tenant:, limit: nil) ⇒ Object

-> [Note] MOST RECENT first, capped by limit.



65
66
67
68
69
70
71
72
73
# File 'lib/insika/memory_store.rb', line 65

def notes(tenant:, limit: nil)
  scope = scope_for(tenant)
  keys = @store.list(scope, NOTE_PREFIX).reverse # list is chronological -> reverse = most recent first
  keys = keys.first(limit) if limit
  keys.filter_map do |k|
    record = @store.get(scope, k)
    record && to_note(record)
  end
end

#put_fact(tenant:, key:, value:) ⇒ Object

Upsert (last-write-wins, Store contract). -> Fact



29
30
31
32
33
# File 'lib/insika/memory_store.rb', line 29

def put_fact(tenant:, key:, value:)
  record = { "key" => key.to_s, "value" => stringify(value), "updated_at" => timestamp }
  @store.set(scope_for(tenant), FACT_PREFIX + key.to_s, record)
  to_fact(record)
end