# `PhoenixKitAI.Tasks`
[🔗](https://github.com/BeamLabEU/phoenix_kit_ai/blob/v0.26.1/lib/phoenix_kit_ai/tasks.ex#L1)

The registry of AI tasks (`PhoenixKitAI.TaskSpec`) and whether an endpoint
fits one.

## Discovery

Every module in `PhoenixKit.ModuleRegistry.all_modules/0` that exports
`ai_tasks/0` declares its tasks there (duck-typed, like
`handle_ai_usage/1`); this module declares `ai.translation` and
`ai.playground` itself. The registry is built on first use and again
only when the set of registered modules changes — never per call. A task
of a module that is switched off is listed with `enabled: false`.
Two declarations of one key: the first wins, with a warning.

## Fitness

`fitness/2` compares a task's hard needs (`:vision`, `:file_input`,
`:image_output`, `:tools`, `:json_schema`) with `PhoenixKitAI.Capabilities.for_endpoint/1` (the
catalogue, the endpoint's declaration filling what it does not know):
`:fit`, `{:unfit, missing}` when the model says no to something, or
`{:unknown, unclear}` when nobody knows. `:json` is soft — the module falls
back to asking for JSON in the prompt — and never makes an endpoint unfit.

Settings forms of consumers use `endpoint_options/1` (the enabled
endpoints with their fitness) and `check_selection/2` before saving.

# `fitness`

```elixir
@type fitness() ::
  :fit
  | {:unfit, [PhoenixKitAI.TaskSpec.need()]}
  | {:unknown, [PhoenixKitAI.TaskSpec.need()]}
```

# `check_selection`

```elixir
@spec check_selection(
  String.t() | PhoenixKitAI.TaskSpec.t(),
  PhoenixKitAI.Endpoint.t() | String.t()
) ::
  :ok | {:error, term()}
```

Whether a consumer's settings form may save `endpoint` for the task:
`:ok` for a fit endpoint; `{:error, {:model_unfit, missing}}` when its
model lacks a requirement; `{:error, {:model_unverified, unclear}}` when
nobody knows whether it has one — an admin marks the capabilities on the
endpoint first. Takes an endpoint or its uuid.

# `endpoint_options`

```elixir
@spec endpoint_options(String.t() | PhoenixKitAI.TaskSpec.t()) :: [
  %{endpoint: PhoenixKitAI.Endpoint.t(), fitness: fitness()}
]
```

The enabled endpoints, each with its fitness for the task — for a
consumer's settings form to show which can be chosen.

# `endpoints`

```elixir
@spec endpoints(PhoenixKitAI.TaskSpec.t()) :: [PhoenixKitAI.Endpoint.t()]
```

The endpoints the task uses now, from its `endpoints` callback; `[]` when
it has none or the callback fails.

# `fitness`

```elixir
@spec fitness(String.t() | PhoenixKitAI.TaskSpec.t(), PhoenixKitAI.Endpoint.t()) ::
  fitness()
```

Whether `endpoint` can do what the task needs: `:fit`, `{:unfit, missing}`
or `{:unknown, unclear}`. Takes a task key or a `%TaskSpec{}`; a key no
module declares has no needs.

# `get`

```elixir
@spec get(String.t()) :: PhoenixKitAI.TaskSpec.t() | nil
```

The task declared under `key`, or `nil`.

# `list`

```elixir
@spec list() :: [PhoenixKitAI.TaskSpec.t()]
```

Every declared task, by key, each marked whether its module is on.

# `need_label`

```elixir
@spec need_label(PhoenixKitAI.TaskSpec.need()) :: String.t()
```

A requirement in words: images, documents, image generation, tools, JSON schema, JSON.

# `need_labels`

```elixir
@spec need_labels([PhoenixKitAI.TaskSpec.need()]) :: String.t()
```

Several requirements in words, comma-separated.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
