Files
LocalAI/gallery/addons
Ettore Di Giacinto 02a707558e feat(addons): ship Studio and Talk as add-ons instead of built-in pages
Studio and Talk were compiled into the web bundle and always listed in
the Add-ons drawer. They are add-ons now, like Voice, Face, fine-tuning
and quantization: a person installs and removes them, the drawer lists
them only while they are installed, and they are packaged the same way.

Move the pages, their components, hooks and helpers into addons/studio
and addons/talk. Each has a manifest, a UI bundle, a release platform
matrix and a catalog template, and is built by the compat mode of the
shared builder. The core API stays where it is: the pages call it with
the signed-in person's session. The history keeps its browser storage
keys. The unit tests of the moved helpers move with them.

In the core, drop the two pages, the Create group of the sidebar (Chat
joins Home and Models in the old layout), the built-in catalog entries
(the catalog is empty) and the talk locale namespace. The old addresses
(/app/studio, /app/talk and the generator links) redirect to the add-on
pages, with the model as ?model=. The Home /studio command is offered
only while the Studio add-on is installed and opens it.

The release workflow and its tests now list seven add-ons.

Assisted-by: Claude Code:claude-sonnet-5-5 go node
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
2026-10-20 21:40:00 +00:00
..

First-party add-on catalog

This directory holds the template of the catalog entries of the first-party add-ons. It holds no live URL, registry or namespace. The registry and repository are inputs of the release workflow (ADDON_OCI_REPOSITORY). Each first-party add-on has its own template (tables, voice, face, fine-tuning, quantization, studio, talk) and its own release platform matrix, addons/<id>/package/platforms.yaml. The templates differ in name: only.

Render entries

go run ./scripts/addons/cmd/addonpkg catalog \
  --config addons/tables/package/platforms.yaml \
  --template gallery/addons/tables.yaml.tmpl \
  --merged <merged layout> \
  --repository <registry>/<namespace>/<repository> \
  --tag <immutable tag: the version or sha-<12 hex>> \
  --channel <latest | development | branch-...> \
  --owner-repo <owner>/<repository> \
  --signer-ref <refs/tags/vX.Y.Z | refs/heads/master> \
  --out <catalog.yaml>

To render the entries of another package, name its matrix and its template. For example, for Voice:

go run ./scripts/addons/cmd/addonpkg catalog \
  --config addons/voice/package/platforms.yaml \
  --template gallery/addons/voice.yaml.tmpl \
  --merged <merged layout of voice> ... # the other flags as above

Use face, fine-tuning, quantization, studio or talk in place of voice for the other packages. Each package has its own repository, so pass the repository of that package.

The add-on packages live in quay.io/go-skynet/local-ai-addons; the template itself holds no registry value. The result is a YAML list with one entry for each enabled platform. Each entry:

  • pins the digest of the platform image, so a tag that moves later changes nothing;
  • names oci://<repository>:<tag> for the immutable tag;
  • carries the channel it is current for and the version of the package, so the channel is metadata that maps to a digest;
  • states the signature policy: signature required, issuer https://token.actions.githubusercontent.com, identity https://github.com/<owner>/<repository>/.github/workflows/addons-package.yml@<signer ref>.

The command fails when the repository is empty or a backend image repository, when the channel is not a channel alias, when a platform of the matrix has no image, or when the template holds an unknown placeholder or weakens the policy.

Placeholders

{{addon}}, {{version}}, {{tag}}, {{channel}}, {{repository}}, {{digest}}, {{os}}, {{arch}}, {{issuer}}, {{identity}}, {{title}}, {{description}}, {{main_page}}, {{icon}}. The title, description, main page and icon come from the verified manifest of the package.

Signature policy of the library

The host replaces the policy of an entry with the policy of the library (source) that serves it. Configure the library with signature required, the issuer above and the identity of the entries. The identity is an exact string and carries the ref of the signing run, so one library names the identity of one release ref. A pattern is not supported by the library policy today.