Current section
Files
Jump to
Current section
Files
lib/pi/agent/registry.ex
defmodule Pi.Agent.Registry do
@moduledoc "Tracks logical Pi agent sessions and message history."
use GenServer
alias Pi.Agent.Messages
alias Pi.Agent.Session
def start_link(opts \\ []), do: GenServer.start_link(__MODULE__, opts, name: __MODULE__)
def install do
case Process.whereis(__MODULE__) do
nil -> start_link([])
_pid -> :ok
end
end
def put(%Session{} = session) do
install()
GenServer.call(__MODULE__, {:put, session})
end
def append(session_id, message) when is_binary(session_id) do
install()
GenServer.call(__MODULE__, {:append, session_id, Messages.normalize(message)})
end
def sessions do
install()
GenServer.call(__MODULE__, :sessions)
end
def children(%Session{id: id}), do: children(id)
def children(parent_id) when is_binary(parent_id) do
install()
GenServer.call(__MODULE__, {:children, parent_id})
end
def history(%Session{id: id}), do: history(id)
def history(session_id) when is_binary(session_id) do
install()
GenServer.call(__MODULE__, {:history, session_id})
end
@impl true
def init(_opts), do: {:ok, %{sessions: %{}, history: %{}}}
@impl true
def handle_call({:put, session}, _from, state) do
sessions = Map.put(state.sessions, session.id, session)
history = Map.put_new(state.history, session.id, session.messages)
{:reply, session, %{state | sessions: sessions, history: history}}
end
def handle_call({:append, session_id, message}, _from, state) do
history = Map.update(state.history, session_id, [message], &(&1 ++ [message]))
{:reply, :ok, %{state | history: history}}
end
def handle_call(:sessions, _from, state) do
{:reply, Map.values(state.sessions), state}
end
def handle_call({:children, parent_id}, _from, state) do
children =
state.sessions
|> Enum.filter(fn {_id, session} -> session.parent_id == parent_id end)
|> Enum.map(fn {_id, session} -> session end)
{:reply, children, state}
end
def handle_call({:history, session_id}, _from, state) do
{:reply, Map.get(state.history, session_id, []), state}
end
end