Skip to content

Add three new tabs to allow models and backends management from within the UI - #851

Open
srossitto79 wants to merge 46 commits into
mostlygeek:mainfrom
srossitto79:main
Open

Add three new tabs to allow models and backends management from within the UI#851
srossitto79 wants to merge 46 commits into
mostlygeek:mainfrom
srossitto79:main

Conversation

@srossitto79

Copy link
Copy Markdown
  • Add Hub models search, download and management
  • Add Backends management that allow automatic download and compile of custom llama.cpp backends
  • Add Config tab with editor for the config file (needs hot-reload config enabled to work properly)

This PR add some functionality that I found useful to myself.
The additions are mostly graphical changes in the UI and the addition of some backend endpoint to serve the new pages.
I also added a shell script to build llama.cpp that is invoked from go to builds from within the web-ui.
I don't know how useful you could find them but I leave this decision to the maintainer.
Hope they can come helpful for someone...

In case of PR accepted, consider removing Dockerfile.simplified because it doesn't follow the smart layer approach used in build-image.sh, also the docker compose is pretty customized to my needs and it would be better to generalize it.

If you find the work useful and want to include it, I can eventually make a branch do some change as per your requests.

@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 2bc666d6-014e-4008-b57c-e481213466f1

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jun 16, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds a new "Mantle" subsystem (new internal/mantle package, three new UI routes) that lets users search HuggingFace, download and manage GGUF/safetensors models, compile custom llama.cpp backends, and edit the live config file — all from the web UI. It also ships a pipe-wrap.py helper that bridges stdin/stdout CLI inference tools into an OpenAI-compatible HTTP endpoint.

  • New internal/mantle package (~1 500 LOC): task manager, HF search/download, backend build runner, GGUF metadata parser, and REST API handlers registered into the existing server mux.
  • Three new UI tabs (ModelManager, BackendManager, ConfigEditor) backed by a new mantleApi.ts client and a reactive task store.
  • New CLI flags (--models-dir, --backends-dir, --build-script) with defaults derived from the config file directory; runtime paths are preserved across hot-reloads.

Confidence Score: 2/5

The download handler can write remote content to arbitrary filesystem paths; this must be fixed before merging.

The filename field in the download request is placed into filepath.Join without any path sanitisation, so a caller can redirect a downloaded file to any location on disk. This affects the core download flow introduced by the PR.

internal/mantle/download.go (path traversal in filename), internal/mantle/mantle.go (unencoded query in HF URL), internal/mantle/api.go (missing name guard on backend delete).

Security Review

  • Path traversal / arbitrary file write (internal/mantle/download.go:738): the filename field in POST /api/mantle/models/download is concatenated with modelsDir via filepath.Join without sanitisation; .. segments resolve to paths outside the intended directory, allowing a caller to write downloaded content to arbitrary filesystem locations.
  • Missing input validation on backend delete (internal/mantle/api.go:343): handleDeleteBackend does not call isSafeBackendName before passing the URL-supplied name to os.RemoveAll; the create path (build) does validate, creating an inconsistency.

Important Files Changed

Filename Overview
internal/mantle/download.go New file — handles single-file and whole-repo HuggingFace downloads. The filename parameter written to disk via filepath.Join is not validated, allowing path traversal to write files outside modelsDir.
internal/mantle/api.go New HTTP handler file — registers all mantle API routes directly via mux.HandleFunc (bypassing the apiChain middleware used by other API routes). handleDeleteBackend lacks the isSafeBackendName check that handleStartBuild applies.
internal/mantle/mantle.go New file — task manager, HuggingFace search/list. SearchHFModels inserts the user query into the URL without encoding; ListHFFiles inserts modelID without encoding. TaskManager.tasks is never pruned so completed tasks accumulate in memory.
internal/mantle/build.go New file — spawns bash build-llamacpp.sh with user-supplied repo, branch, and cmake args. Args are passed as separate exec.Command arguments (no shell injection), and backendName is validated before this point.
internal/mantle/config.go New file — lists/deletes local models and backends. DeleteLocalModel and DeleteBackend rely on filepath.Join path resolution; URL normalization in Go's mux limits traversal risk for URL-sourced names.
internal/server/server.go Wires mantle handler into the server. Mantle routes are registered via mux.HandleFunc directly, not through apiChain, so they do not benefit from whatever middleware apiChain provides.
llama-swap.go Adds three new CLI flags (--models-dir, --backends-dir, --build-script) with sane defaults derived from the config file's directory; runtime paths are re-applied on config reload.
scripts/pipe-wrap.py New Python helper that wraps a stdin/stdout CLI inference tool as an OpenAI-compatible HTTP server. Serialises concurrent requests with a lock; streaming uses two SSE chunks (full text + stop).

Comments Outside Diff (2)

  1. internal/mantle/download.go, line 738 (link)

    P0 security Path traversal via filename parameter

    The filename value from the JSON body is placed directly into filepath.Join(modelsDir, ..., filename). filepath.Join resolves .. segments, so a caller supplying "filename": "../../etc/cron.d/backdoor" causes localPath to escape modelsDir entirely — the downloaded content is then written to that resolved path via os.Rename. In a containerised deployment running as root this means any file on the host-mapped filesystem can be overwritten.

    Add a guard before the download starts: reject any filename that is absolute or whose cleaned form contains a .. component.

  2. internal/mantle/mantle.go, line 1070-1073 (link)

    P1 query inserted into HuggingFace URL without encoding

    query (taken directly from the user-supplied q query parameter) is interpolated into the URL string with fmt.Sprintf without url.QueryEscape. A value like ggml&pipeline_tag=text-to-image would inject an extra parameter into the HuggingFace API request, bypassing the kind filter logic and potentially returning unexpected results. Use url.Values to build the URL safely.

Reviews (1): Last reviewed commit: "Merge branch 'mostlygeek:main' into main" | Re-trigger Greptile

Comment thread internal/mantle/api.go
…skip any that already exist as a local model. Fix: ui-svelte/src/components/playground/ConcurrencyInterface.svelte:395-397 — show "Connecting…" instead of "No models configured." when the SSE isn't yet connected.
Merge upstream changes (v229-v241) while preserving llama-mantle features:

- Resolved event ID conflicts (ProfileChangedEvent=0x08, mantle events at 0x09,0x0A)
- Updated server.New() to accept both store.Store and mantle.TaskManager
- Preserved mantle runtime paths (ConfigPath, ModelsDir, BackendsDir, BuildScript)
- Kept upstream's UpstreamConfig field
- Adopted upstream's shadcn-svelte UI rewrite with profile support
- Added mantle routes (Model Hub, Config Editor, Backend Manager) to new router
- Accepted upstream deletions of Header/ModelsPanel (replaced by AppSidebar)
- Kept docker/unified/build-image.sh deleted (our docker refactoring)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant