Packages
fnord
0.8.74
0.9.40
0.9.39
0.9.38
0.9.37
0.9.36
0.9.35
0.9.34
0.9.33
0.9.32
0.9.31
0.9.30
0.9.29
0.9.28
0.9.27
0.9.26
0.9.25
0.9.24
0.9.23
0.9.22
0.9.21
0.9.20
0.9.19
0.9.18
0.9.17
0.9.16
0.9.15
0.9.14
0.9.13
0.9.12
0.9.11
0.9.10
0.9.9
0.9.8
0.9.7
0.9.6
0.9.5
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.99
0.8.98
0.8.97
0.8.96
0.8.95
0.8.94
0.8.93
0.8.92
0.8.91
0.8.90
0.8.89
0.8.88
0.8.87
0.8.86
0.8.85
0.8.84
0.8.83
0.8.82
0.8.81
0.8.80
0.8.79
0.8.78
0.8.77
0.8.76
0.8.75
0.8.74
0.8.73
0.8.72
0.8.71
0.8.70
0.8.69
0.8.68
0.8.67
0.8.66
0.8.65
0.8.64
0.8.63
0.8.62
0.8.61
0.8.60
0.8.59
0.8.58
0.8.57
0.8.56
0.8.55
0.8.54
0.8.53
0.8.52
0.8.51
0.8.50
0.8.49
0.8.48
0.8.47
0.8.46
0.8.45
0.8.44
0.8.43
0.8.42
0.8.41
0.8.40
0.8.39
0.8.38
0.8.37
0.8.36
0.8.35
0.8.34
0.8.33
0.8.32
0.8.31
0.8.30
0.8.29
0.8.27
0.8.26
0.8.25
0.8.24
0.8.23
0.8.22
0.8.21
0.8.20
0.8.19
0.8.18
0.8.17
0.8.16
0.8.15
0.8.14
0.8.13
0.8.12
0.8.11
0.8.1
0.8.0
0.7.24
0.7.23
0.7.22
0.7.21
0.7.20
0.7.19
0.7.18
0.7.17
0.7.16
0.7.15
0.7.14
0.7.13
0.7.12
0.7.11
0.7.10
0.7.9
0.7.8
0.7.7
0.7.6
0.7.5
0.7.3
0.7.2
0.7.1
0.7.0
0.6.9
0.6.8
0.6.7
0.6.6
0.6.5
0.6.4
0.6.3
0.6.1
0.6.0
0.5.9
0.5.8
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.44
0.4.43
0.4.42
0.4.41
0.4.40
0.4.39
0.4.38
0.4.37
0.4.36
0.4.35
0.4.34
0.4.33
0.4.32
0.4.30
0.4.29
0.4.28
0.4.27
0.4.26
0.4.25
0.4.24
0.4.23
0.4.22
0.4.21
0.4.20
0.4.19
0.4.18
0.4.17
0.4.16
0.4.15
0.4.14
0.4.13
0.4.12
0.4.11
0.4.10
0.4.9
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.0
0.2.0
0.1.0
AI code archaeology
Current section
Files
Jump to
Current section
Files
lib/store/memories/children.ex
defmodule Store.Memories.Children do
@moduledoc """
Handles children.log file operations for memories.
Format: newline-delimited list of child slugs (one per line).
"""
@filename "children.log"
@doc """
Reads children.log from a memory directory.
Returns list of child slugs.
"""
@spec read(String.t()) :: [String.t()]
def read(memory_dir) do
path = Path.join(memory_dir, @filename)
case File.read(path) do
{:ok, content} ->
content
|> String.split("\n", trim: true)
{:error, :enoent} ->
[]
{:error, _} ->
[]
end
end
@doc """
Writes children.log for a memory using atomic write.
Takes a memory struct.
"""
@spec write(AI.Memory.t(), [String.t()]) :: :ok | {:error, term}
def write(memory, children) do
memory_dir = get_memory_dir(memory)
write_path(memory_dir, children)
end
@doc """
Writes children.log to a specific path (used by parent operations).
"""
@spec write_path(String.t(), [String.t()]) :: :ok | {:error, term}
def write_path(memory_dir, children) do
path = Path.join(memory_dir, @filename)
content = Enum.join(children, "\n")
write_atomic(path, content)
end
# ----------------------------------------------------------------------------
# Private Helpers
# ----------------------------------------------------------------------------
defp get_memory_dir(%AI.Memory{scope: :global, slug: slug}) do
Path.join([Settings.get_user_home(), ".fnord/memories", slug])
end
defp get_memory_dir(%AI.Memory{scope: :project, slug: slug}) do
case Settings.get_selected_project() do
{:ok, project_name} ->
Path.join([Settings.get_user_home(), ".fnord/projects", project_name, "memories", slug])
{:error, :project_not_set} ->
raise "Cannot save project-scoped memory without a selected project. Use 'fnord config set-project <name>' first."
end
end
defp write_atomic(path, content) do
dir = Path.dirname(path)
base = Path.basename(path)
tmp = Path.join(dir, ".#{base}.#{System.unique_integer([:positive])}.tmp")
with :ok <- File.write(tmp, content),
:ok <- File.rename(tmp, path) do
:ok
else
error ->
File.rm(tmp)
error
end
end
end