Files
LocalAI/gallery/addons
mudler-agentandEttore Di Giacinto 16acc8926b feat(addons): simplify Office and discover Tables (#13029)
* feat(tables): list accessible databases

Let agents discover existing databases through the host gateway.
Keep listing actor-scoped and separate from executable tools.

Assisted-by: nib:gpt-6.1-sol
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* test(tables): verify database listing authority

Exercise model discovery through the real owner and carrier.
Check shared access, revocation, denial and resource limits.

Assisted-by: nib:gpt-6.1-sol
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* feat(tables): bundle database search guidance

Teach agents to discover existing databases before querying records.
Package and verify the skill with the Tables add-on.

Assisted-by: nib:gpt-6.1-sol
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* test(tables): cover packaged chat skill gates

Load the real receipt-verified Tables instructions through the temporary
Studio workspace. Check the index and load refusal after runtime, chat
switch and saved-agent grant changes.

This fixture starts at the receipt and broker boundary; packaging tests
cover artifact construction and integrity separately.

Assisted-by: nib:gpt-6.1-sol
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* feat(office): parse Markdown and CSV inputs

Convert bounded text inputs into document and workbook structures.
Render supported Markdown formatting without fetching external content.
Preserve spreadsheet fields as strings rather than inferring formulas.

Assisted-by: nib:gpt-6.1-sol
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* fix(office): preserve list markers, breaks and PDF page margins

Cover actual DOCX breaks and tabs, explicit zero list starts, empty list rejection, and PDF margin/pagination regressions.

Assisted-by: nib:gpt-6.1-sol
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* fix(office): guard Markdown parsing work

Check cancellation and nesting during parser callbacks.
Validate table dimensions before padded table allocation.
Keep parser state isolated to each conversion.

Assisted-by: nib:gpt-6.1-sol
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* fix(office): recognize tables before applying limits

Leave mismatched table-like paragraphs as ordinary Markdown.
Keep oversized real tables bounded before allocation.

Assisted-by: nib:gpt-6.1-sol
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* feat(office): simplify document creation inputs

Accept Markdown for DOCX and PDF, and CSV for single-sheet XLSX files.
Replace nested creation schemas to reduce model tool grammar complexity.
Keep existing read, edit and PowerPoint behavior and internal office IDs.

Present the add-on as Simple Office and document the compatibility change.
Keep same-style Markdown fragments editable in generated DOCX files.

Assisted-by: nib:gpt-6.1-sol
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* fix(ci): align add-on fixtures and test inventories

Tables fixtures must carry the skill their manifest declares. Preserve
its bytes in package tests and mark only binaries executable in UI
fixtures. Assert that installation keeps the shipped skill intact.

Register the new Tables tests and the connector case from master in
exact suite inventories. Include the new database read in tool counts.

Run Office regressions through Ginkgo and check reader close errors.
Keep all document assertions and the existing CI gates intact.

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Assisted-by: nib:gpt-6.1-sol

* fix(ci): restore Office and packaging checks

Keep the generated Office label consistent with Simple Office. Install
Poppler for the PDF layout regressions on Linux and macOS.

Separate successful runtime setup from the 300 ms deadline under test.
Keep the timeout, cancellation, stop and admission assertions intact.

Refresh the packaging inventory from all 209 executed cases, retaining
repeated platform checks and the Office and Tables skill checks.

Assisted-by: nib:gpt-6.1-sol
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

---------

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Co-authored-by: Ettore Di Giacinto <mudler@localai.io>
2026-11-02 12:48:08 +01: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, office, sandbox, web) and its own release platform matrix, addons/<id>/package/platforms.yaml. The templates differ in name: only.

Generate the index

gallery/addons/index.yaml is generated from the platform files and the manifests; never edit it by hand. It has one development entry (mutable, no digest) for each enabled platform of each add-on:

sh scripts/addons/catalog.sh --channel development \
  --repository quay.io/go-skynet/local-ai-addons --out gallery/addons/index.yaml

CI runs sh scripts/addons/catalog.sh --channel development --check and fails when the file is stale. Run it after you enable a platform in addons/<id>/package/platforms.yaml, change a manifest (title, description, main page, tools) or add an add-on template.

The release index, pinned by digest and signed by the run of the tag, is rendered by the package workflow from the merged layouts it pushed:

sh scripts/addons/catalog.sh --channel release --repository <repo> --version <semver> \
  --signer-ref refs/tags/v<semver> --merged-root <dir with one merged layout for each add-on id> \
  --out addons-index.yaml

Render entries of one add-on

With --from-manifest in place of --merged, the command renders the development channel from the manifest and the enabled platforms, without a built package.

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 without the id prefix: 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, talk, office, sandbox or web in place of voice for the other packages. All packages share one repository, so pass the same repository for each. The artifact of an entry is oci://<repository>:<id>-<tag>, for example ...:voice-sha-50f0f3de26d2.

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>:<id>-<tag> for the immutable tag of that add-on;
  • 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.

Every entry also carries toolCount and tools: the chat tools the package declares in capabilities.tools (admin tools are not counted), at most 32 names, and the full count. An add-on without chat tools has neither field. To add them to an existing index without a merged layout, read the manifests of the repository:

go run ./scripts/addons/cmd/addonpkg catalog-tools --index gallery/addons/index.yaml --addons addons

It changes no other field, so no digest or artifact moves.

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.