defmodule SyntropyWeb.Api.AgentConnections do @moduledoc """ Shapes an agent's connection map into the ordered list rendered by the agents and history JSON views, resolving bare agent ids to runtime-scoped ids when the payload carries an explicit runtime id. """ alias Syntropy.ClusterInfo @spec ordered(map()) :: [map()] def ordered(%{connections: connections} = agent) when is_map(connections) do connections |> Enum.sort_by(fn {target_id, _value} -> target_id end) |> Enum.map(fn {target_id, connection} -> %{ target_agent_id: connection_target_id(agent, target_id), weight: connection.weight, interactions: connection.interactions } end) end def ordered(%{connections: connections} = agent) when is_list(connections) do connections |> Enum.map(fn connection -> Map.put( connection, :target_agent_id, connection_target_id(agent, connection.target_agent_id) ) end) |> Enum.sort_by(& &1.target_agent_id) end defp connection_target_id(%{} = agent, target_id) when is_binary(target_id) do cond do String.contains?(target_id, "::") -> target_id explicit_runtime_id?(agent) -> ClusterInfo.runtime_id(target_id, node_id_for(agent)) true -> target_id end end defp explicit_runtime_id?(agent) do case payload_value(agent, :runtime_id) do runtime_id when is_binary(runtime_id) and runtime_id != "" -> true _other -> false end end defp node_id_for(%{} = value), do: payload_value(value, :node_id, "local") defp payload_value(payload, key, default \\ nil) when is_map(payload) do string_key = Atom.to_string(key) cond do Map.has_key?(payload, key) -> Map.get(payload, key) Map.has_key?(payload, string_key) -> Map.get(payload, string_key) true -> default end end end