defmodule SyntropyWeb.AgentLive do use SyntropyWeb, :live_view import SyntropyWeb.RuntimeViewHelpers alias Syntropy.{HistoryStore, LatticeSupervisor, RecommendationStore, TaskScheduler} @history_limit 20 @impl true def mount(_params, _session, socket) do if connected?(socket) do Phoenix.PubSub.subscribe(Syntropy.PubSub, "lattice:events") end {:ok, assign(socket, agent: nil, task_history: [], recommendation_history: [], snapshot_history: [] )} end @impl true def handle_params(%{"id" => agent_id}, _uri, socket) do {:noreply, load_agent(socket, agent_id)} end @impl true def handle_info({:lattice_event, _event}, socket) do agent_id = socket.assigns.agent && socket.assigns.agent.id {:noreply, load_agent(socket, agent_id)} end @impl true def render(assigns) do ~H"""

Agent inspection

Retained state and recent participation for one agent.

<%= if @agent do %>

<%= @agent.name %>

<%= if @agent.temporary do %> temporary <% end %> <.link navigate={graph_path(nil, @agent.id)} class="status-chip status-chip--muted"> Focus in live graph
ID <%= @agent.id %>
Node <%= Syntropy.node_id() %>
Perspective <%= @agent.perspective %>
Position <%= format_score(@agent.position) %>

Connections

<%= if map_size(@agent.connections) == 0 do %>

No retained connections.

<% else %>
    <%= for {target_id, connection} <- Enum.sort_by(@agent.connections, fn {target_id, _} -> target_id end) do %>
  • <%= target_id %> weight <%= format_score(connection.weight) %> · <%= connection.interactions %> interactions
  • <% end %>
<% end %>

Recent task participation

<%= if @task_history == [] do %>

No recent task participation.

<% else %>
    <%= for entry <- @task_history do %>
  • <%= entry.task.task_id %> node <%= node_id_for(entry.task) %>
    <%= entry.task.strategy %> resolved <%= entry.task.resolved_mode %> <%= if entry.snapshot do %> <.link navigate={graph_path(entry.snapshot.id, @agent.id)} class="status-chip status-chip--muted"> <%= entry.snapshot.id %> <% end %>
  • <% end %>
<% end %>

Recent recommendation involvement

<%= if @recommendation_history == [] do %>

No recent recommendation involvement.

<% else %>
    <%= for recommendation <- @recommendation_history do %>
  • <%= recommendation.id %> node <%= node_id_for(recommendation) %>
    <%= recommendation.kind %> <%= recommendation.status %>
  • <% end %>
<% end %>

Recent snapshots

<%= if @snapshot_history == [] do %>

No recent snapshots for this agent.

<% else %>
    <%= for snapshot <- @snapshot_history do %>
  • <.link navigate={graph_path(snapshot.id, @agent.id)} class="text-link"> <%= snapshot.id %> node <%= node_id_for(snapshot) %>
    trigger <%= snapshot.trigger_kind %>
  • <% end %>
<% end %>
<% else %>

Agent not found.

<% end %>
""" end defp load_agent(socket, nil), do: assign(socket, agent: nil, task_history: [], recommendation_history: [], snapshot_history: [] ) defp load_agent(socket, agent_id) do agent = Enum.find(LatticeSupervisor.list_agents(), &(&1.id == agent_id)) assign(socket, agent: agent, task_history: recent_tasks_for(agent_id), recommendation_history: recent_recommendations_for(agent_id), snapshot_history: recent_snapshots_for(agent_id) ) end defp recent_tasks_for(nil), do: [] defp recent_tasks_for(agent_id) do snapshots_by_task_id = HistoryStore.recent(@history_limit) |> Map.new(fn snapshot -> {snapshot.task_id, snapshot} end) TaskScheduler.recent(@history_limit) |> Enum.filter(fn task -> agent_id in task.selected_agent_ids or agent_id in task.contributing_agent_ids end) |> Enum.map(fn task -> %{ task: task, snapshot: Map.get(snapshots_by_task_id, task.task_id) } end) end defp recent_recommendations_for(nil), do: [] defp recent_recommendations_for(agent_id) do RecommendationStore.recent(@history_limit) |> Enum.filter(fn recommendation -> agent_id in recommendation.candidate_agent_ids or recommendation.applied_agent_id == agent_id end) end defp recent_snapshots_for(nil), do: [] defp recent_snapshots_for(agent_id) do HistoryStore.recent(@history_limit) |> Enum.filter(fn snapshot -> Enum.any?(snapshot.agents, &(&1.id == agent_id)) end) end defp graph_path(snapshot_id, agent_id) do params = %{} |> maybe_put("snapshot", snapshot_id) |> maybe_put("agent", agent_id) ~p"/?#{params}" end defp maybe_put(params, _key, nil), do: params defp maybe_put(params, key, value), do: Map.put(params, key, value) end