admin: keep GGUF model config and whisper-server runner config separate

A GGUF model config (configure + enable the model, load strategy) and a
whisper-server config (the runner: port, gpu, which model) are two distinct
things. Showing whisper-servers as the backing file's configs made the GGUF
row's "Configure" open the whisper form — conflating them.

Whisper-server entries are again excluded from a GGUF file's editable config
list (they live only in their own card); the GGUF row's Configure opens the
general model config modal. The file still reflects "loaded" via its
model_path in the loaded-status sets.
Co-Authored-By: 's avatarClaude Opus 4.8 <noreply@anthropic.com>
parent 615967d8
......@@ -1312,14 +1312,16 @@ def _scan_caches() -> dict:
if isinstance(m, str):
p, s = m, {}
else:
# Whisper-server entries have no "path"; their file is at
# "model_path", so they surface as configs of the backing GGUF
# file. The UI routes editing such a config to the whisper editor
# (which updates in place), so they no longer spawn duplicates.
if m.get("backend") == "whisper-server" and m.get("model_path"):
p = m["model_path"]
else:
p = m.get("path") or m.get("id") or ""
# A whisper-server is the RUNNER config (port, gpu, which model)
# and is managed in its own card — it is a different thing from
# the GGUF MODEL config (which configures/enables the model and
# holds the load strategy). So whisper-server entries must NOT
# appear as configs of the backing GGUF file, or the GGUF row's
# config form would become the whisper form. The file still shows
# "loaded" via its model_path key in the loaded-status sets.
if m.get("backend") == "whisper-server":
continue
p = m.get("path") or m.get("id") or ""
s = m if isinstance(m, dict) else {}
if not p:
continue
......
......@@ -1934,12 +1934,7 @@ function _renderConfigPills(idx, m) {
const configs = m.configs || [];
if (!configs.length) return '';
const pills = configs.map((c, cfgIdx) => {
const cs = c.settings || {};
// Whisper-server configs share the same alias ("whisper"); label them by id
// so the two instances are distinguishable.
const label = cs.config_name
|| (cs.backend === 'whisper-server' ? cs.id : cs.alias)
|| `Config ${cfgIdx + 1}`;
const label = (c.settings && (c.settings.config_name || c.settings.alias)) || `Config ${cfgIdx + 1}`;
return `<span class="badge badge-user" style="font-size:10px;cursor:pointer;vertical-align:middle;margin:.1rem .1rem 0 0" onclick="openCfgModal(${idx},${cfgIdx})" title="Edit this configuration">${esc(label)}</span>${_engineTagHtml(m, c.settings)}`;
}).join('');
const addPill = `<span class="badge" style="font-size:10px;cursor:pointer;vertical-align:middle;margin:.1rem 0 0 0;background:var(--raised);border:1px dashed var(--border);color:var(--text-2)" onclick="openCfgModalNew(${idx})" title="Add another configuration for this model">+ Config</span>`;
......@@ -2995,15 +2990,6 @@ function openCfgModal(idx, cfgIdx){
}
// Determine which config's settings to load
const configs = m.configs || [];
// A whisper-server can appear as a config of its backing GGUF file. Editing it
// must go through the whisper editor (updates in place by id) — not the general
// modal, which would treat it as a config_id-less entry and create duplicates.
const _sel = (cfgIdx != null && cfgIdx >= 0) ? configs[cfgIdx] : (configs[0] || null);
if (_sel && (_sel.settings || {}).backend === 'whisper-server') {
const s = _sel.settings;
_openWhisperServerEdit({ path: s.id, settings: s });
return;
}
// Normalize cfgIdx: undefined/null → 0, -1 → "new"
const _cfgIdx = (cfgIdx == null) ? 0 : cfgIdx;
let s, configId, isNewConfig;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment