feat(models): add bulk model deletion controls
This commit is contained in:
@@ -132,6 +132,76 @@ class ModelMapper:
|
||||
self._ensure()
|
||||
return {k: sorted(v) for k, v in self._folder_files.items()}
|
||||
|
||||
def delete_models(self, models):
|
||||
"""Delete verified model files and return per-model results.
|
||||
|
||||
Each requested file must still be in the mapper's known model list and
|
||||
resolve beneath the configured root for its model type. This keeps the
|
||||
HTTP endpoint from being usable to remove arbitrary files.
|
||||
"""
|
||||
self._ensure()
|
||||
try:
|
||||
import folder_paths
|
||||
except ImportError:
|
||||
return [{"status": "error", "message": "folder_paths unavailable"}]
|
||||
|
||||
results = []
|
||||
seen = set()
|
||||
for item in models:
|
||||
if not isinstance(item, dict):
|
||||
results.append({"status": "error", "message": "invalid model entry"})
|
||||
continue
|
||||
model_type = item.get("model_type")
|
||||
model_name = item.get("model_name")
|
||||
if not isinstance(model_type, str) or not isinstance(model_name, str):
|
||||
results.append({
|
||||
"model_type": model_type,
|
||||
"model_name": model_name,
|
||||
"status": "error",
|
||||
"message": "invalid model entry",
|
||||
})
|
||||
continue
|
||||
key = (model_type, model_name)
|
||||
if key in seen:
|
||||
continue
|
||||
seen.add(key)
|
||||
result = {"model_type": model_type, "model_name": model_name}
|
||||
|
||||
known = self._folder_files.get(model_type, frozenset())
|
||||
if model_name not in known:
|
||||
result.update(status="error", message="model is not installed")
|
||||
results.append(result)
|
||||
continue
|
||||
|
||||
try:
|
||||
path = folder_paths.get_full_path(model_type, model_name)
|
||||
roots = folder_paths.get_folder_paths(model_type)
|
||||
path = os.path.abspath(path) if path else None
|
||||
allowed = any(
|
||||
os.path.commonpath([path, os.path.abspath(root)]) == os.path.abspath(root)
|
||||
for root in roots
|
||||
) if path else False
|
||||
except (OSError, TypeError, ValueError):
|
||||
path = None
|
||||
allowed = False
|
||||
|
||||
if not path or not allowed or not os.path.isfile(path):
|
||||
result.update(status="error", message="model file not found in its configured folder")
|
||||
results.append(result)
|
||||
continue
|
||||
|
||||
try:
|
||||
os.remove(path)
|
||||
result["status"] = "deleted"
|
||||
except OSError as exc:
|
||||
result.update(status="error", message=str(exc))
|
||||
results.append(result)
|
||||
|
||||
# The model-folder listing is now stale whether any deletion succeeded
|
||||
# or not (another process could have changed it), so rebuild next time.
|
||||
self.invalidate()
|
||||
return results
|
||||
|
||||
def extract_models_from_prompt(self, prompt):
|
||||
"""Scan a prompt dict and return (model_name, model_type) pairs.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user