Class: Llmemory::LongTerm::FileBased::Storages::FileStorage

Inherits:
Base
  • Object
show all
Includes:
Crypto::FieldHelpers
Defined in:
lib/llmemory/long_term/file_based/storages/file_storage.rb

Instance Method Summary collapse

Methods inherited from Base

#get_items_around, #get_resources_around

Constructor Details

#initialize(base_path: nil, cipher: nil) ⇒ FileStorage

Returns a new instance of FileStorage.



15
16
17
18
19
# File 'lib/llmemory/long_term/file_based/storages/file_storage.rb', line 15

def initialize(base_path: nil, cipher: nil)
  @base_path = base_path || Llmemory.configuration.long_term_storage_path || "./llmemory_data"
  @base_path = File.expand_path(@base_path)
  @cipher = cipher || Llmemory.build_cipher
end

Instance Method Details

#archive_items(user_id, item_ids) ⇒ Object



127
128
129
# File 'lib/llmemory/long_term/file_based/storages/file_storage.rb', line 127

def archive_items(user_id, item_ids)
  item_ids.each { |id| File.delete(item_path(user_id, id)) if File.file?(item_path(user_id, id)) }
end

#archive_resources(user_id, resource_ids) ⇒ Object



131
132
133
# File 'lib/llmemory/long_term/file_based/storages/file_storage.rb', line 131

def archive_resources(user_id, resource_ids)
  resource_ids.each { |id| File.delete(resource_path(user_id, id)) if File.file?(resource_path(user_id, id)) }
end

#count_items(user_id:) ⇒ Object



176
177
178
# File 'lib/llmemory/long_term/file_based/storages/file_storage.rb', line 176

def count_items(user_id:)
  get_all_items(user_id).size
end

#get_all_items(user_id) ⇒ Object



86
87
88
89
90
91
92
93
94
95
# File 'lib/llmemory/long_term/file_based/storages/file_storage.rb', line 86

def get_all_items(user_id)
  dir = user_path(user_id, "items")
  return [] unless Dir.exist?(dir)
  Dir.children(dir).select { |f| f.end_with?(".json") }.map do |f|
    data = read_encrypted_file(File.join(dir, f))
    data = decrypt_item(data)
    data[:created_at] = parse_time(data[:created_at])
    data
  end.sort_by { |i| i[:created_at] }
end

#get_all_resources(user_id) ⇒ Object



97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/llmemory/long_term/file_based/storages/file_storage.rb', line 97

def get_all_resources(user_id)
  dir = user_path(user_id, "resources")
  return [] unless Dir.exist?(dir)
  Dir.children(dir).select { |f| f.end_with?(".json") }.map do |f|
    data = read_encrypted_file(File.join(dir, f))
    id = File.basename(f, ".json")
    data[:id] = id
    data[:text] = dec(data[:text] || data["text"])
    data[:created_at] = parse_time(data[:created_at])
    data
  end.sort_by { |r| r[:created_at] }
end

#get_items_older_than(user_id, days:) ⇒ Object



81
82
83
84
# File 'lib/llmemory/long_term/file_based/storages/file_storage.rb', line 81

def get_items_older_than(user_id, days:)
  cutoff = Time.now - (days * 86400)
  get_all_items(user_id).select { |i| parse_time(i[:created_at] || i["created_at"]) < cutoff }
end

#get_items_since(user_id, hours:) ⇒ Object



110
111
112
113
# File 'lib/llmemory/long_term/file_based/storages/file_storage.rb', line 110

def get_items_since(user_id, hours:)
  cutoff = Time.now - (hours * 3600)
  get_all_items(user_id).select { |i| parse_time(i[:created_at]) >= cutoff }
end

#get_resources_since(user_id, hours:) ⇒ Object



76
77
78
79
# File 'lib/llmemory/long_term/file_based/storages/file_storage.rb', line 76

def get_resources_since(user_id, hours:)
  cutoff = Time.now - (hours * 3600)
  get_all_resources(user_id).select { |r| parse_time(r[:created_at] || r["created_at"]) >= cutoff }
end

#list_categories(user_id) ⇒ Object



62
63
64
65
66
# File 'lib/llmemory/long_term/file_based/storages/file_storage.rb', line 62

def list_categories(user_id)
  dir = user_path(user_id, "categories")
  return [] unless Dir.exist?(dir)
  Dir.children(dir).select { |f| f.end_with?(".md") }.map { |f| File.basename(f, ".md") }
end

#list_items(user_id:, category: nil, limit: nil, offset: nil) ⇒ Object



168
169
170
171
172
173
174
# File 'lib/llmemory/long_term/file_based/storages/file_storage.rb', line 168

def list_items(user_id:, category: nil, limit: nil, offset: nil)
  list = get_all_items(user_id)
  list = list.select { |i| (i[:category] || i["category"]).to_s == category.to_s } if category
  list = list.drop(offset.to_i) if offset && offset.to_i.positive?
  list = list.take(limit) if limit
  list
end

#list_resources(user_id:, limit: nil, offset: nil) ⇒ Object



162
163
164
165
166
# File 'lib/llmemory/long_term/file_based/storages/file_storage.rb', line 162

def list_resources(user_id:, limit: nil, offset: nil)
  list = get_all_resources(user_id)
  list = list.drop(offset.to_i) if offset && offset.to_i.positive?
  limit ? list.take(limit) : list
end

#list_usersObject



157
158
159
160
# File 'lib/llmemory/long_term/file_based/storages/file_storage.rb', line 157

def list_users
  return [] unless Dir.exist?(@base_path)
  Dir.children(@base_path).select { |e| File.directory?(File.join(@base_path, e)) && !e.start_with?(".") }
end

#load_category(user_id, category_name) ⇒ Object



49
50
51
52
53
# File 'lib/llmemory/long_term/file_based/storages/file_storage.rb', line 49

def load_category(user_id, category_name)
  path = category_path(user_id, category_name)
  return "" unless File.file?(path)
  read_encrypted_text_file(path)
end

#load_daily_logs(user_id, from_date:, to_date:) ⇒ Object



143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/llmemory/long_term/file_based/storages/file_storage.rb', line 143

def load_daily_logs(user_id, from_date:, to_date:)
  from_date = Date.parse(from_date.to_s) if from_date.is_a?(String)
  to_date = Date.parse(to_date.to_s) if to_date.is_a?(String)
  dir = user_path(user_id, "memory")
  return [] unless Dir.exist?(dir)

  (from_date..to_date).filter_map do |d|
    path = daily_log_path(user_id, d)
    next unless File.file?(path)

    { date: d, content: read_encrypted_text_file(path) }
  end
end

#replace_items(user_id, ids_to_remove, merged_item) ⇒ Object



115
116
117
118
119
120
121
122
123
124
125
# File 'lib/llmemory/long_term/file_based/storages/file_storage.rb', line 115

def replace_items(user_id, ids_to_remove, merged_item)
  ids_to_remove.each { |id| File.delete(item_path(user_id, id)) if File.file?(item_path(user_id, id)) }
  merged_item = merged_item.merge(created_at: Time.now) unless merged_item.key?(:created_at)
  seq = next_seq(user_id, "item_id_seq")
  id = "item_#{seq}"
  path = item_path(user_id, id)
  data = merged_item.merge(id: id).transform_values { |v| v.respond_to?(:iso8601) ? v.iso8601 : v }
  data[:content] = enc(data[:content]) if data[:content]
  data[:provenance] = enc_json(data[:provenance]) if data[:provenance]
  write_encrypted_file(path, data)
end

#save_category(user_id, category_name, content) ⇒ Object



55
56
57
58
59
60
# File 'lib/llmemory/long_term/file_based/storages/file_storage.rb', line 55

def save_category(user_id, category_name, content)
  ensure_user_dir(user_id, "categories")
  path = category_path(user_id, category_name)
  write_encrypted_text_file(path, content)
  true
end

#save_daily_log_entry(user_id, date, content) ⇒ Object



135
136
137
138
139
140
141
# File 'lib/llmemory/long_term/file_based/storages/file_storage.rb', line 135

def save_daily_log_entry(user_id, date, content)
  ensure_user_dir(user_id, "memory")
  path = daily_log_path(user_id, date)
  entry = "#{Time.now.strftime('%H:%M')} #{content}\n"
  write_encrypted_text_file(path, entry, append: File.file?(path))
  true
end

#save_item(user_id, category:, content:, source_resource_id:, importance: 0.7, provenance: nil) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/llmemory/long_term/file_based/storages/file_storage.rb', line 31

def save_item(user_id, category:, content:, source_resource_id:, importance: 0.7, provenance: nil)
  ensure_user_dir(user_id)
  seq = next_seq(user_id, "item_id_seq")
  id = "item_#{seq}"
  path = item_path(user_id, id)
  data = {
    id: id,
    category: category,
    content: enc(content),
    source_resource_id: source_resource_id,
    importance: importance,
    provenance: provenance ? enc_json(provenance) : nil,
    created_at: Time.now.iso8601
  }
  write_encrypted_file(path, data)
  id
end

#save_resource(user_id, text) ⇒ Object



21
22
23
24
25
26
27
28
29
# File 'lib/llmemory/long_term/file_based/storages/file_storage.rb', line 21

def save_resource(user_id, text)
  ensure_user_dir(user_id)
  seq = next_seq(user_id, "resource_id_seq")
  id = "res_#{seq}"
  path = resource_path(user_id, id)
  data = { text: enc(text), created_at: Time.now.iso8601 }
  write_encrypted_file(path, data)
  id
end

#search_items(user_id, query) ⇒ Object



68
69
70
# File 'lib/llmemory/long_term/file_based/storages/file_storage.rb', line 68

def search_items(user_id, query)
  get_all_items(user_id).select { |i| Llmemory::Tokenizer.matches?(i[:content] || i["content"], query) }
end

#search_resources(user_id, query) ⇒ Object



72
73
74
# File 'lib/llmemory/long_term/file_based/storages/file_storage.rb', line 72

def search_resources(user_id, query)
  get_all_resources(user_id).select { |r| Llmemory::Tokenizer.matches?(r[:text] || r["text"], query) }
end