feat: enable full model file deletion on disk including split parts and vision adapters, update prompt text

This commit is contained in:
Hitonabi
2026-06-26 07:23:06 +02:00
parent e88dfb8f98
commit b90cef3968
4 changed files with 63 additions and 16 deletions
+48 -1
View File
@@ -223,11 +223,58 @@ def set_ctx(model_id: str, ctx: int) -> bool:
def delete_model(model_id: str) -> bool:
"""Entfernt einen Modell-Eintrag aus der config.yaml (und aus allen Gruppen)."""
"""Entfernt einen Modell-Eintrag aus der config.yaml, löscht die zugehörigen
GGUF-Dateien (auch Splits) vom Datenträger und bereinigt leere Ordner.
"""
cfg = read_config()
models = cfg.get("models") or {}
if model_id not in models:
return False
model_spec = models[model_id] or {}
cmd = str(model_spec.get("cmd", "")).strip()
if (m := _PATH_RE.search(cmd)):
path = m.group(1).replace("'", "").replace('"', "")
if path:
# 1. Haupt-GGUF-Datei löschen
if os.path.exists(path):
try:
os.remove(path)
except Exception:
pass
# 2. Split-GGUF-Teile löschen (z.B. dateiname-00001-of-00005.gguf etc.)
dirname = os.path.dirname(path)
basename = os.path.basename(path)
if os.path.isdir(dirname):
split_idx = basename.find("-00001-of-")
if split_idx != -1:
prefix = basename[:split_idx]
for f in os.listdir(dirname):
if f.startswith(prefix) and f.endswith(".gguf"):
try:
os.remove(os.path.join(dirname, f))
except Exception:
pass
# mmproj-Datei (Vision adapter) aus dem Befehl parsen & löschen
if "mmproj" in cmd:
mmproj_match = re.search(r'--mmproj\s+[\'"]?([^\s\'"]+)[\'"]?', cmd)
if mmproj_match:
m_path = mmproj_match.group(1)
if os.path.exists(m_path):
try:
os.remove(m_path)
except Exception:
pass
# 3. Eltern-Ordner löschen, falls er leer ist und nicht der Modelle-Wurzelordner selbst ist
try:
if not os.listdir(dirname) and os.path.basename(dirname) != "models":
os.rmdir(dirname)
except Exception:
pass
del models[model_id]
for g in (cfg.get("groups") or {}).values():
if isinstance(g, dict) and model_id in (g.get("members") or []):
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -6,7 +6,7 @@
<meta name="theme-color" content="#0d1117" />
<link rel="manifest" href="/manifest.webmanifest" />
<title>Mission Control 2.0</title>
<script type="module" crossorigin src="/assets/index-DphlB-Xi.js"></script>
<script type="module" crossorigin src="/assets/index-DMajYfAZ.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-CAfaSDN8.css">
</head>
<body>
+2 -2
View File
@@ -179,7 +179,7 @@ function Cockpit() {
}
async function handleDelete(name: string) {
if (!confirm(`Modell '${name}' aus der Config entfernen? (GGUF-Datei bleibt)`)) return
if (!confirm(`Modell '${name}' und alle zugehörigen GGUF-Dateien unwiderruflich von der Box löschen?`)) return
try {
await api(`/api/models/${encodeURIComponent(name)}`, { method: "DELETE" })
load()
@@ -604,7 +604,7 @@ function Cockpit() {
<button
onClick={() => handleDelete(m.name)}
className="h-7 w-7 rounded-lg flex items-center justify-center border border-border/40 text-muted-foreground hover:text-red-400 hover:bg-red-500/5 transition-all opacity-0 group-hover:opacity-100 shrink-0 cursor-pointer"
title="Modell aus Config entfernen"
title="Modell und GGUF-Dateien löschen"
>
<Trash2 className="h-3.5 w-3.5" />
</button>