defmodule Pi.Plugin.API do @moduledoc "Callable API metadata exposed by executable skills and plugins." @type t :: %__MODULE__{ name: atom(), module: module(), alias: atom() | nil, description: String.t(), examples: [String.t()] } @enforce_keys [:name, :module] defstruct [:name, :module, :alias, description: "", examples: []] def new(%__MODULE__{} = api), do: api def new(attrs) when is_list(attrs) do attrs |> Map.new() |> new() end def new(%{name: name, module: module} = attrs) when is_atom(name) and is_atom(module) do %__MODULE__{ name: name, module: module, alias: Map.get(attrs, :alias) || default_alias(module), description: Map.get(attrs, :description, ""), examples: Map.get(attrs, :examples, []) } end defp default_alias(module) do module |> Module.split() |> Enum.reject(&(&1 in ["Pi", "Plugin", "Plugins", "API"])) |> List.last() |> :erlang.binary_to_atom() end end