Class: ClaudeMemory::Store::SQLiteStore

Inherits:
Object
  • Object
show all
Defined in:
lib/claude_memory/store/sqlite_store.rb

Constant Summary collapse

SCHEMA_VERSION =
2

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(db_path) ⇒ SQLiteStore

Returns a new instance of SQLiteStore.



13
14
15
16
17
# File 'lib/claude_memory/store/sqlite_store.rb', line 13

def initialize(db_path)
  @db_path = db_path
  @db = Sequel.sqlite(db_path)
  ensure_schema!
end

Instance Attribute Details

#dbObject (readonly)

Returns the value of attribute db.



11
12
13
# File 'lib/claude_memory/store/sqlite_store.rb', line 11

def db
  @db
end

Instance Method Details

#closeObject



19
20
21
# File 'lib/claude_memory/store/sqlite_store.rb', line 19

def close
  @db.disconnect
end

#conflictsObject



55
56
57
# File 'lib/claude_memory/store/sqlite_store.rb', line 55

def conflicts
  @db[:conflicts]
end

#content_itemsObject



27
28
29
# File 'lib/claude_memory/store/sqlite_store.rb', line 27

def content_items
  @db[:content_items]
end

#delta_cursorsObject



31
32
33
# File 'lib/claude_memory/store/sqlite_store.rb', line 31

def delta_cursors
  @db[:delta_cursors]
end

#entitiesObject



35
36
37
# File 'lib/claude_memory/store/sqlite_store.rb', line 35

def entities
  @db[:entities]
end

#entity_aliasesObject



39
40
41
# File 'lib/claude_memory/store/sqlite_store.rb', line 39

def entity_aliases
  @db[:entity_aliases]
end


51
52
53
# File 'lib/claude_memory/store/sqlite_store.rb', line 51

def fact_links
  @db[:fact_links]
end

#factsObject



43
44
45
# File 'lib/claude_memory/store/sqlite_store.rb', line 43

def facts
  @db[:facts]
end

#facts_for_slot(subject_entity_id, predicate, status: "active") ⇒ Object



291
292
293
294
295
296
297
298
# File 'lib/claude_memory/store/sqlite_store.rb', line 291

def facts_for_slot(subject_entity_id, predicate, status: "active")
  facts
    .where(subject_entity_id: subject_entity_id, predicate: predicate, status: status)
    .select(:id, :subject_entity_id, :predicate, :object_entity_id, :object_literal,
      :datatype, :polarity, :valid_from, :valid_to, :status, :confidence,
      :created_from, :created_at)
    .all
end

#find_or_create_entity(type:, name:) ⇒ Object



245
246
247
248
249
250
251
252
# File 'lib/claude_memory/store/sqlite_store.rb', line 245

def find_or_create_entity(type:, name:)
  slug = slugify(type, name)
  existing = entities.where(slug: slug).get(:id)
  return existing if existing

  now = Time.now.utc.iso8601
  entities.insert(type: type, canonical_name: name, slug: slug, created_at: now)
end

#get_delta_cursor(session_id, transcript_path) ⇒ Object



226
227
228
# File 'lib/claude_memory/store/sqlite_store.rb', line 226

def get_delta_cursor(session_id, transcript_path)
  delta_cursors.where(session_id: session_id, transcript_path: transcript_path).get(:last_byte_offset)
end

#insert_conflict(fact_a_id:, fact_b_id:, status: "open", notes: nil) ⇒ Object



314
315
316
317
318
319
320
321
322
323
# File 'lib/claude_memory/store/sqlite_store.rb', line 314

def insert_conflict(fact_a_id:, fact_b_id:, status: "open", notes: nil)
  now = Time.now.utc.iso8601
  conflicts.insert(
    fact_a_id: fact_a_id,
    fact_b_id: fact_b_id,
    status: status,
    detected_at: now,
    notes: notes
  )
end

#insert_fact(subject_entity_id:, predicate:, object_entity_id: nil, object_literal: nil, datatype: nil, polarity: "positive", valid_from: nil, status: "active", confidence: 1.0, created_from: nil, scope: "project", project_path: nil) ⇒ Object



254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
# File 'lib/claude_memory/store/sqlite_store.rb', line 254

def insert_fact(subject_entity_id:, predicate:, object_entity_id: nil, object_literal: nil,
  datatype: nil, polarity: "positive", valid_from: nil, status: "active",
  confidence: 1.0, created_from: nil, scope: "project", project_path: nil)
  now = Time.now.utc.iso8601
  facts.insert(
    subject_entity_id: subject_entity_id,
    predicate: predicate,
    object_entity_id: object_entity_id,
    object_literal: object_literal,
    datatype: datatype,
    polarity: polarity,
    valid_from: valid_from || now,
    status: status,
    confidence: confidence,
    created_from: created_from,
    created_at: now,
    scope: scope,
    project_path: project_path
  )
end


329
330
331
# File 'lib/claude_memory/store/sqlite_store.rb', line 329

def insert_fact_link(from_fact_id:, to_fact_id:, link_type:)
  fact_links.insert(from_fact_id: from_fact_id, to_fact_id: to_fact_id, link_type: link_type)
end

#insert_provenance(fact_id:, content_item_id: nil, quote: nil, attribution_entity_id: nil, strength: "stated") ⇒ Object



300
301
302
303
304
305
306
307
308
# File 'lib/claude_memory/store/sqlite_store.rb', line 300

def insert_provenance(fact_id:, content_item_id: nil, quote: nil, attribution_entity_id: nil, strength: "stated")
  provenance.insert(
    fact_id: fact_id,
    content_item_id: content_item_id,
    quote: quote,
    attribution_entity_id: attribution_entity_id,
    strength: strength
  )
end

#open_conflictsObject



325
326
327
# File 'lib/claude_memory/store/sqlite_store.rb', line 325

def open_conflicts
  conflicts.where(status: "open").all
end

#provenanceObject



47
48
49
# File 'lib/claude_memory/store/sqlite_store.rb', line 47

def provenance
  @db[:provenance]
end

#provenance_for_fact(fact_id) ⇒ Object



310
311
312
# File 'lib/claude_memory/store/sqlite_store.rb', line 310

def provenance_for_fact(fact_id)
  provenance.where(fact_id: fact_id).all
end

#schema_versionObject



23
24
25
# File 'lib/claude_memory/store/sqlite_store.rb', line 23

def schema_version
  @db[:meta].where(key: "schema_version").get(:value)&.to_i
end

#update_delta_cursor(session_id, transcript_path, offset) ⇒ Object



230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/claude_memory/store/sqlite_store.rb', line 230

def update_delta_cursor(session_id, transcript_path, offset)
  now = Time.now.utc.iso8601
  delta_cursors
    .insert_conflict(
      target: [:session_id, :transcript_path],
      update: {last_byte_offset: offset, updated_at: now}
    )
    .insert(
      session_id: session_id,
      transcript_path: transcript_path,
      last_byte_offset: offset,
      updated_at: now
    )
end

#update_fact(fact_id, status: nil, valid_to: nil, scope: nil, project_path: nil) ⇒ Object



275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
# File 'lib/claude_memory/store/sqlite_store.rb', line 275

def update_fact(fact_id, status: nil, valid_to: nil, scope: nil, project_path: nil)
  updates = {}
  updates[:status] = status if status
  updates[:valid_to] = valid_to if valid_to

  if scope
    updates[:scope] = scope
    updates[:project_path] = (scope == "global") ? nil : project_path
  end

  return false if updates.empty?

  facts.where(id: fact_id).update(updates)
  true
end

#upsert_content_item(source:, text_hash:, byte_len:, session_id: nil, transcript_path: nil, project_path: nil, occurred_at: nil, raw_text: nil, metadata: nil) ⇒ Object



206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/claude_memory/store/sqlite_store.rb', line 206

def upsert_content_item(source:, text_hash:, byte_len:, session_id: nil, transcript_path: nil,
  project_path: nil, occurred_at: nil, raw_text: nil, metadata: nil)
  existing = content_items.where(text_hash: text_hash, session_id: session_id).get(:id)
  return existing if existing

  now = Time.now.utc.iso8601
  content_items.insert(
    source: source,
    session_id: session_id,
    transcript_path: transcript_path,
    project_path: project_path,
    occurred_at: occurred_at || now,
    ingested_at: now,
    text_hash: text_hash,
    byte_len: byte_len,
    raw_text: raw_text,
    metadata_json: &.to_json
  )
end