Packages
A Fair Source multi-agent runtime with deterministic agent scoring and replayable run history.
Retired package: Deprecated - superseded — operator console moved to the Syntropy app
Current section
Files
Jump to
Current section
Files
lib/syntropy_web/controllers/api/task_request.ex
defmodule SyntropyWeb.Api.TaskRequest do
@moduledoc false
@type parsed_request :: %{prompt: String.t(), opts: keyword()}
@strategies ~w(single parallel all auto)
@spec parse(map()) :: {:ok, parsed_request()} | {:error, [map()]}
def parse(params) do
with {:ok, prompt} <- parse_prompt(Map.get(params, "prompt")),
{:ok, strategy} <- parse_strategy(Map.get(params, "strategy")),
{:ok, agent_ids} <- parse_agent_ids(Map.get(params, "agent_ids")),
{:ok, agent_count} <-
parse_positive_integer(Map.get(params, "agent_count"), 3, "agent_count"),
{:ok, synthesize} <- parse_boolean(Map.get(params, "synthesize"), true, "synthesize") do
{:ok,
%{
prompt: prompt,
opts:
[]
|> Keyword.put(:strategy, strategy)
|> maybe_put(:agent_ids, agent_ids)
|> Keyword.put(:agent_count, agent_count)
|> Keyword.put(:synthesize, synthesize)
}}
else
{:error, errors} -> {:error, errors}
end
end
defp maybe_put(opts, _key, nil), do: opts
defp maybe_put(opts, key, value), do: Keyword.put(opts, key, value)
defp parse_prompt(prompt) when is_binary(prompt) do
trimmed = String.trim(prompt)
if trimmed == "" do
{:error, [error("prompt", "must be a non-empty string")]}
else
{:ok, trimmed}
end
end
defp parse_prompt(_prompt), do: {:error, [error("prompt", "is required")]}
defp parse_strategy(nil), do: {:ok, :parallel}
defp parse_strategy(strategy) when is_binary(strategy) do
if strategy in @strategies do
{:ok, String.to_atom(strategy)}
else
{:error, [error("strategy", "must be one of single, parallel, all, auto")]}
end
end
defp parse_strategy(_strategy),
do: {:error, [error("strategy", "must be one of single, parallel, all, auto")]}
defp parse_agent_ids(nil), do: {:ok, nil}
defp parse_agent_ids(agent_ids) when is_list(agent_ids) do
if Enum.all?(agent_ids, &is_binary/1) do
{:ok, agent_ids}
else
{:error, [error("agent_ids", "must be an array of strings")]}
end
end
defp parse_agent_ids(_agent_ids),
do: {:error, [error("agent_ids", "must be an array of strings")]}
defp parse_positive_integer(nil, default, _field), do: {:ok, default}
defp parse_positive_integer(value, _default, _field) when is_integer(value) and value > 0,
do: {:ok, value}
defp parse_positive_integer(value, _default, field) when is_binary(value) do
case Integer.parse(value) do
{parsed, ""} when parsed > 0 -> {:ok, parsed}
_other -> {:error, [error(field, "must be a positive integer")]}
end
end
defp parse_positive_integer(_value, _default, field),
do: {:error, [error(field, "must be a positive integer")]}
defp parse_boolean(nil, default, _field), do: {:ok, default}
defp parse_boolean(value, _default, _field) when is_boolean(value), do: {:ok, value}
defp parse_boolean(_value, _default, field), do: {:error, [error(field, "must be a boolean")]}
defp error(field, message), do: %{field: field, message: message}
end