From c45bcf686ebeccdc4481c083138602abbe226e22 Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Sun, 16 Nov 2025 17:24:24 +0100 Subject: [PATCH 1/2] feat(ui): show loaded models in the index Signed-off-by: Ettore Di Giacinto --- core/http/views/index.html | 115 +++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/core/http/views/index.html b/core/http/views/index.html index 92f71d706123..4b00d84b5bfe 100644 --- a/core/http/views/index.html +++ b/core/http/views/index.html @@ -237,6 +237,43 @@

Documentation + + + {{ $loadedModels := .LoadedModels }} + {{ end }} @@ -334,6 +371,84 @@

// Make startChat available globally window.startChat = startChat; + +// Stop individual model +async function stopModel(modelName) { + if (!confirm(`Are you sure you want to stop "${modelName}"?`)) { + return; + } + + try { + const response = await fetch('/backend/shutdown', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ model: modelName }) + }); + + if (response.ok) { + // Reload page after short delay to reflect changes + setTimeout(() => { + window.location.reload(); + }, 500); + } else { + alert('Failed to stop model'); + } + } catch (error) { + console.error('Error stopping model:', error); + alert('Failed to stop model'); + } +} + +// Stop all loaded models +async function stopAllModels(component) { + const loadedModelNamesStr = '{{ $loadedModels := .LoadedModels }}{{ range .ModelsConfig }}{{ if index $loadedModels .Name }}{{.Name}},{{ end }}{{ end }}'; + const loadedModelNames = loadedModelNamesStr.split(',').filter(name => name.length > 0); + + if (loadedModelNames.length === 0) { + return; + } + + if (!confirm(`Are you sure you want to stop all ${loadedModelNames.length} loaded model(s)?`)) { + return; + } + + // Set loading state + if (component) { + component.stoppingAll = true; + } + + try { + // Stop all models in parallel + const stopPromises = loadedModelNames.map(modelName => + fetch('/backend/shutdown', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ model: modelName }) + }) + ); + + await Promise.all(stopPromises); + + // Reload page after short delay to reflect changes + setTimeout(() => { + window.location.reload(); + }, 1000); + } catch (error) { + console.error('Error stopping models:', error); + alert('Failed to stop some models'); + if (component) { + component.stoppingAll = false; + } + } +} + +// Make functions available globally for Alpine.js +window.stopModel = stopModel; +window.stopAllModels = stopAllModels; From 9a6331c6978b56515707d19799fc1773941f0ef4 Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Sun, 16 Nov 2025 17:45:35 +0100 Subject: [PATCH 2/2] chore(ui): re-organize navbar Signed-off-by: Ettore Di Giacinto --- core/http/views/index.html | 2 +- core/http/views/manage.html | 563 +++++++++++++-------------- core/http/views/partials/navbar.html | 155 +++++--- 3 files changed, 373 insertions(+), 347 deletions(-) diff --git a/core/http/views/index.html b/core/http/views/index.html index 4b00d84b5bfe..def505b95569 100644 --- a/core/http/views/index.html +++ b/core/http/views/index.html @@ -220,7 +220,7 @@

- Manage Models + System diff --git a/core/http/views/manage.html b/core/http/views/manage.html index c35dabffb61d..c9bc9f4684ce 100644 --- a/core/http/views/manage.html +++ b/core/http/views/manage.html @@ -32,40 +32,38 @@ -
+
-
-

- - Model & Backend Management - +
+

+ Model & Backend Management

-

Manage your installed models and backends

+

Manage your installed models and backends

-
+ @@ -76,46 +74,41 @@

{{ if eq (len .ModelsConfig) 0 }} -
+
-
- +
+
-

No models installed yet

-

Get started by installing a model from the gallery or importing it

+

No models installed yet

+

Get started by installing a model from the gallery or importing it

-
- - + {{ if ne (len .Models) 0 }} -
-

- +
+

+ Detected Model Files

-

These models were found but don't have configuration files yet

-
+

These models were found but don't have configuration files yet

+
{{ range .Models }} -
-
- -
-
-

{{.}}

-

No configuration

-
+
+ + {{.}}
{{end}}
@@ -124,294 +117,282 @@

{{ else }} - + {{ $modelsN := len .ModelsConfig}} {{ $modelsN = add $modelsN (len .Models)}} -
-
-

- - Installed Models -

-

- {{$modelsN}} model{{if gt $modelsN 1}}s{{end}} ready to use -

-
+
+

+ + Installed Models +

+

+ {{$modelsN}} model{{if gt $modelsN 1}}s{{end}} ready to use +

-
- {{$galleryConfig:=.GalleryConfig}} - {{ $loadedModels := .LoadedModels }} - - {{ range .ModelsConfig }} - {{ $backendCfg := . }} - {{ $cfg:= index $galleryConfig .Name}} -
- -
-
- {{ if and $cfg $cfg.Icon }} - {{.Name}} icon - {{ else }} - - {{ end }} - {{ if index $loadedModels .Name }} -
- {{ end }} -
+
+ + + + + + + + + + + + {{$galleryConfig:=.GalleryConfig}} + {{ $loadedModels := .LoadedModels }} -
-

{{.Name}}

+ {{ range .ModelsConfig }} + {{ $backendCfg := . }} + {{ $cfg:= index $galleryConfig .Name}} +
+ + + + + -
+ +
+ + + + + + + {{ end }} - - - -
-
- {{ if index $loadedModels .Name }} - - {{ end }} -
-
- - Edit - - -
-
- - {{ end }} - - - {{ range .Models }} -
-
-
- -
-
-

{{.}}

- -
- - Auto Backend - - - No Config + + {{ range .Models }} +
+ + + + + + + {{end}} + +
NameStatusBackendUse CasesActions
+
+
+ {{ if and $cfg $cfg.Icon }} + {{.Name}} icon + {{ else }} + + {{ end }} + {{ if index $loadedModels .Name }} +
+ {{ end }} +
+ {{.Name}} + + + +
+
+
+ {{ if index $loadedModels .Name }} + + Running + + {{ end }} + {{ if and $backendCfg (or (ne $backendCfg.MCP.Servers "") (ne $backendCfg.MCP.Stdio "")) }} + + MCP + + {{ end }} +
+
{{ if .Backend }} - - {{.Backend}} + + {{.Backend}} {{ else }} - - Auto + + Auto {{ end }} - - {{ if and $backendCfg (or (ne $backendCfg.MCP.Servers "") (ne $backendCfg.MCP.Stdio "")) }} - - MCP - - {{ end }} - - {{ if index $loadedModels .Name }} - - Running - - {{ end }} - - - - - -
- {{ range .KnownUsecaseStrings }} - {{ if eq . "FLAG_CHAT" }} - - - Chat - - {{ end }} - {{ if eq . "FLAG_IMAGE" }} - - - Image - - {{ end }} - {{ if eq . "FLAG_TTS" }} - - - TTS - - {{ end }} +
+
+ {{ range .KnownUsecaseStrings }} + {{ if eq . "FLAG_CHAT" }} + + Chat + + {{ end }} + {{ if eq . "FLAG_IMAGE" }} + + Image + + {{ end }} + {{ if eq . "FLAG_TTS" }} + + TTS + + {{ end }} + {{ end }} +
+
+
+ {{ if index $loadedModels .Name }} + + {{ end }} + +
+
+
+ + {{.}} +
+
+ + No Config - - -
- - - Configuration required for full functionality +
+ + Auto - - - - - {{end}} - + + + + +
+
{{ end }}
-
-
-

- +
+
+

+ Installed Backends

-

- {{len .InstalledBackends}} backend{{if gt (len .InstalledBackends) 1}}s{{end}} ready to use +

+ {{len .InstalledBackends}} backend{{if gt (len .InstalledBackends) 1}}s{{end}} ready to use

{{ if eq (len .InstalledBackends) 0 }} -
+
-
- +
+
-

No backends installed yet

-

Backends power your AI models. Install them from the backend gallery to get started

+

No backends installed yet

+

Backends power your AI models. Install them from the backend gallery to get started

-
{{ else }} - -
- {{ range .InstalledBackends }} -
- -
-
- -
-
-

{{.Name}}

+ +
+ + + + + + + + + + + {{ range .InstalledBackends }} + + + -
- {{ if .IsSystem }} - - System - - {{ else }} - - User Installed - - {{ end }} - - {{ if .IsMeta }} - - Meta - - {{ end }} -
- - - - -
- {{ if and .Metadata .Metadata.Alias }} -
- -
- Alias: - {{.Metadata.Alias}} -
-
- {{ end }} - - {{ if and .Metadata .Metadata.InstalledAt }} -
- -
- Installed: - {{.Metadata.InstalledAt}} -
-
- {{ end }} - - {{ if and .Metadata .Metadata.MetaBackendFor }} -
- -
- Meta backend for: - {{.Metadata.MetaBackendFor}} -
-
- {{ end }} - - {{ if false }} - {{ if and .Metadata .Metadata.GalleryURL }} - - {{ end }} - -
- -
- Path: - {{.RunFile}} -
-
- {{ end }} -
- - - {{ if not .IsSystem }} -
- -
- {{ end }} - - {{end}} + + + + + + + + + + {{end}} + +
NameTypeMetadataActions
+
+ + {{.Name}} +
+
+
+ {{ if .IsSystem }} + + System + + {{ else }} + + User + + {{ end }} + {{ if .IsMeta }} + + Meta + + {{ end }} +
+
+
+ {{ if and .Metadata .Metadata.Alias }} + + Alias: {{.Metadata.Alias}} + + {{ end }} + {{ if and .Metadata .Metadata.MetaBackendFor }} + + For: {{.Metadata.MetaBackendFor}} + + {{ end }} + {{ if and .Metadata .Metadata.InstalledAt }} + + {{.Metadata.InstalledAt}} + + {{ end }} +
+
+
+ {{ if not .IsSystem }} + + {{ else }} + + {{ end }} +
+
{{ end }}
diff --git a/core/http/views/partials/navbar.html b/core/http/views/partials/navbar.html index 91f754886198..cc98d4d3d592 100644 --- a/core/http/views/partials/navbar.html +++ b/core/http/views/partials/navbar.html @@ -18,66 +18,111 @@
- -