Skip to main content

lib/pi/plugin/api.ex

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