Module: Legion::CLI::Chat::MemoryStore

Defined in:
lib/legion/cli/chat/memory_store.rb

Constant Summary collapse

DEFAULT_PROJECT_FILE =
'.legion/memory.md'
DEFAULT_GLOBAL_DIR =
File.join(Dir.home, '.legion', 'memory')
DEFAULT_GLOBAL_FILE =
File.join(DEFAULT_GLOBAL_DIR, 'global.md')

Class Method Summary collapse

Class Method Details

.add(text, scope: :project, base_dir: Dir.pwd) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/legion/cli/chat/memory_store.rb', line 44

def add(text, scope: :project, base_dir: Dir.pwd)
  path = scope == :global ? global_path : project_path(base_dir)
  ensure_dir(path)

  timestamp = Time.now.strftime('%Y-%m-%d %H:%M')
  entry = "\n- #{text} _(#{timestamp})_\n"

  if File.exist?(path)
    File.open(path, 'a', encoding: 'utf-8') { |f| f.write(entry) }
  else
    header = scope == :global ? "# Global Memory\n" : "# Project Memory\n"
    File.write(path, "#{header}#{entry}", encoding: 'utf-8')
  end

  sync_to_team(text)
  path
end

.clear(scope: :project, base_dir: Dir.pwd) ⇒ Object



83
84
85
86
87
88
89
# File 'lib/legion/cli/chat/memory_store.rb', line 83

def clear(scope: :project, base_dir: Dir.pwd)
  path = scope == :global ? global_path : project_path(base_dir)
  return false unless File.exist?(path)

  File.delete(path)
  true
end

.forget(pattern, scope: :project, base_dir: Dir.pwd) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
# File 'lib/legion/cli/chat/memory_store.rb', line 62

def forget(pattern, scope: :project, base_dir: Dir.pwd)
  path = scope == :global ? global_path : project_path(base_dir)
  return 0 unless File.exist?(path)

  lines = File.readlines(path, encoding: 'utf-8')
  original_count = lines.length
  lines.reject! { |line| line.include?(pattern) }
  removed = original_count - lines.length
  File.write(path, lines.join, encoding: 'utf-8')
  removed
end

.global_pathObject



20
21
22
# File 'lib/legion/cli/chat/memory_store.rb', line 20

def global_path
  DEFAULT_GLOBAL_FILE
end

.list(scope: :project, base_dir: Dir.pwd) ⇒ Object



74
75
76
77
78
79
80
81
# File 'lib/legion/cli/chat/memory_store.rb', line 74

def list(scope: :project, base_dir: Dir.pwd)
  path = scope == :global ? global_path : project_path(base_dir)
  return [] unless File.exist?(path)

  File.readlines(path, encoding: 'utf-8')
      .select { |line| line.start_with?('- ') }
      .map { |line| line.sub(/\A- /, '').strip }
end

.load_all(base_dir = Dir.pwd) ⇒ Object



24
25
26
27
28
29
30
31
32
# File 'lib/legion/cli/chat/memory_store.rb', line 24

def load_all(base_dir = Dir.pwd)
  memories = []
  [global_path, project_path(base_dir)].each do |path|
    next unless File.exist?(path)

    memories << { source: path, content: File.read(path, encoding: 'utf-8') }
  end
  memories
end

.load_context(base_dir = Dir.pwd) ⇒ Object



34
35
36
37
38
39
40
41
42
# File 'lib/legion/cli/chat/memory_store.rb', line 34

def load_context(base_dir = Dir.pwd)
  parts = load_all(base_dir).map do |m|
    label = m[:source].include?('global') ? 'Global Memory' : 'Project Memory'
    "## #{label}\n\n#{m[:content]}"
  end
  return nil if parts.empty?

  parts.join("\n\n---\n\n")
end

.project_path(base_dir = Dir.pwd) ⇒ Object



16
17
18
# File 'lib/legion/cli/chat/memory_store.rb', line 16

def project_path(base_dir = Dir.pwd)
  File.join(base_dir, DEFAULT_PROJECT_FILE)
end

.search(query, base_dir: Dir.pwd) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
# File 'lib/legion/cli/chat/memory_store.rb', line 91

def search(query, base_dir: Dir.pwd)
  results = []
  load_all(base_dir).each do |m|
    m[:content].lines.each_with_index do |line, idx|
      next unless line.downcase.include?(query.downcase)

      results << { source: m[:source], line: idx + 1, text: line.strip }
    end
  end
  results
end