# `PhoenixKitCatalogue.AIPrompt`
[🔗](https://github.com/BeamLabEU/phoenix_kit_catalogue/blob/v0.44.2/lib/phoenix_kit_catalogue/ai_prompt.ex#L1)

Idempotent provisioning of the catalogue's AI-translation prompts.

`PhoenixKitAI.Translations.default_prompt_uuid/0` (the shared
`phoenixkit-translate-content` prompt) hard-codes six field slots
(`name`/`title`/`summary`/`description`/`body`/`content`) and none of
those match `catalogue_set_label`'s/`catalogue_set_value`'s vocabulary
(`label`/`title`) either — every catalogue call would render the
unmatched slots as literal, unbound `{{placeholder}}` text (the engine
substitutes variables globally, with no notion of "this field wasn't
sent"), and a call binding only `label` or only `title` would fail
`{:missing_fields, [...]}` outright since the shared template has no
such slot at all. This module gives catalogue its own two prompts
instead:

  * `ensure_prompt/0` — items/categories, vocabulary `name`/
    `description`/`summary`/`seo_title`/`seo_description`.
  * `ensure_sets_prompt/0` — attribute-set labels/value titles,
    vocabulary `label`/`title`.

Both carry the same measurement-unit rule the shared prompt has no
reason to carry — attribute values (e.g. sizes) are exactly where units
show up.

## Rollout

Each prompt is content-addressed: `ensure_prompt/0`/`ensure_sets_prompt/0`
are idempotent by their own slug, and `Prompt.metadata["content_sha"]`
(sha256 hex of the module's template) tells them whether the stored row
still matches. Editing a template and redeploying makes the next call
update the stored prompt in place and keep the same uuid — no version
counter, because the content already is the version.

# `ensure_prompt`

```elixir
@spec ensure_prompt() :: {:ok, String.t()} | {:error, term()}
```

Ensures the catalogue item/category translation prompt exists and
matches this module's current template, creating or updating it as
needed.

Idempotent by slug: repeated calls return the same uuid as long as the
template hasn't changed. When it has (a redeploy shipped an edited
template), the next call updates the stored prompt in place and keeps
the same uuid — callers holding an old `prompt_uuid` still resolve to
the current rules.

# `ensure_sets_prompt`

```elixir
@spec ensure_sets_prompt() :: {:ok, String.t()} | {:error, term()}
```

Ensures the catalogue attribute-set translation prompt (labels and
value titles, `{{label}}`/`{{title}}`) exists and matches this module's
current template — same idempotent-by-slug, content-addressed rollout
as `ensure_prompt/0`, under its own slug so it never collides with the
item/category prompt or the shared `phoenixkit-translate-content` one.

# `sets_slug`

```elixir
@spec sets_slug() :: String.t()
```

The attribute-set translation prompt's slug — stable across redeploys.

# `slug`

```elixir
@spec slug() :: String.t()
```

The item/category translation prompt's slug — stable across redeploys.

---

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