defmodule SyntropyWeb.Api.ControllerHelpers do @moduledoc false import Phoenix.Controller, only: [json: 2] import Plug.Conn, only: [put_status: 2] @max_limit 100 @spec limit(map(), non_neg_integer()) :: non_neg_integer() def limit(params, default \\ @max_limit) do case Map.get(params, "limit") do nil -> default limit when is_integer(limit) -> normalize_limit(limit, default) limit when is_binary(limit) -> case Integer.parse(limit) do {parsed, ""} -> normalize_limit(parsed, default) _other -> default end _other -> default end end @spec not_found(Plug.Conn.t(), String.t(), String.t()) :: Plug.Conn.t() def not_found(conn, resource, id) do error(conn, :not_found, "not_found", "#{resource} #{id} was not found.") end @spec invalid_request(Plug.Conn.t(), String.t(), list(map())) :: Plug.Conn.t() def invalid_request(conn, message, details) do error(conn, :unprocessable_entity, "invalid_request", message, details) end @spec conflict(Plug.Conn.t(), String.t(), String.t()) :: Plug.Conn.t() def conflict(conn, code, message) do error(conn, :conflict, code, message) end @spec task_failure(Plug.Conn.t(), term()) :: Plug.Conn.t() def task_failure(conn, reason) do case reason do :no_agents -> error(conn, :unprocessable_entity, "task_rejected", "No agents were available.") :no_successful_thoughts -> error(conn, :unprocessable_entity, "task_rejected", "No agents completed the task.") :quota_exceeded -> error( conn, :too_many_requests, "quota_exceeded", "The fair-use token budget for the rolling 30-day window is exhausted." ) _other -> error(conn, :internal_server_error, "task_failed", "Task execution failed.") end end defp error(conn, status, code, message, details \\ nil) do body = %{ error: %{ code: code, message: message } } |> maybe_put_details(details) conn |> put_status(status) |> json(body) end defp maybe_put_details(body, nil), do: body defp maybe_put_details(body, details), do: put_in(body, [:error, :details], details) defp normalize_limit(limit, _default) when is_integer(limit) and limit > 0 do min(limit, @max_limit) end defp normalize_limit(_limit, default), do: default end