From a5b0030896fe166f8d4186939addafb99bde7b08 Mon Sep 17 00:00:00 2001 From: 0xShug0 <231717474+0xShug0@users.noreply.github.com> Date: Sat, 15 Aug 2026 10:50:28 -0400 Subject: [PATCH 1/2] Remove local ideas notes --- ideas/native_ui_config_mode_tracking.md | 28 ------------------------- 1 file changed, 28 deletions(-) delete mode 100644 ideas/native_ui_config_mode_tracking.md diff --git a/ideas/native_ui_config_mode_tracking.md b/ideas/native_ui_config_mode_tracking.md deleted file mode 100644 index e793f6b7..00000000 --- a/ideas/native_ui_config_mode_tracking.md +++ /dev/null @@ -1,28 +0,0 @@ -# Native UI Config Mode Tracking - -Issue: https://github.com/0xShug0/audio.cpp/issues/234 - -This note tracks native UI gaps seen when `audiocpp_server` is launched with a -server config but without `--ui-management`. - -## Bugs - -- The Studio model picker is built from the embedded model catalog, not from the - configured `/v1/models` response. In config mode this exposes models that the - server was not configured to serve. -- The UI uses catalog IDs as request model IDs. Configured server model IDs are - deployment-local, so a resident configured model may not be found if its ID - differs from the catalog ID. -- Management-only endpoints such as path inspection are correctly forbidden - when `ui_management=false`, but the UI still probes them and presents unclear - state. -- Package choice defaults are precision-centric. This can hide installed BF16 - packages behind a Q8 default and cannot represent multi-axis variants such as - ACE-Step base vs turbo. - -## Intended Direction - -- Add a config-mode UI path where selectable models come from `/v1/models`. -- Keep catalog/package-management behavior behind `--ui-management`. -- Make loaded/resident state use the actual server model ID. -- Represent package variants without assuming precision is the only choice axis. From b5760f79dec7e2fedc433f2ca16574c8b66e4676 Mon Sep 17 00:00:00 2001 From: 0xShug0 <231717474+0xShug0@users.noreply.github.com> Date: Sat, 15 Aug 2026 11:00:09 -0400 Subject: [PATCH 2/2] Fix native UI loaded model display --- webui/native/dist/index.html | 20 +++++------ webui/native/src/routes/+page.svelte | 54 ++++++++++++++++++++++------ 2 files changed, 53 insertions(+), 21 deletions(-) diff --git a/webui/native/dist/index.html b/webui/native/dist/index.html index dcbb7910..89091cdb 100644 --- a/webui/native/dist/index.html +++ b/webui/native/dist/index.html @@ -13,20 +13,20 @@
diff --git a/webui/native/src/routes/+page.svelte b/webui/native/src/routes/+page.svelte index 9394325e..03958046 100644 --- a/webui/native/src/routes/+page.svelte +++ b/webui/native/src/routes/+page.svelte @@ -183,10 +183,6 @@ } } - function loadedModelName(model: LoadedModel) { - return catalog.find((entry) => entry.id === model.id)?.display_name || model.id; - } - const workflowTabs = [ { id: 'tts', label: 'Text to speech', filterLabel: 'TTS', tasks: ['tts', 'clon'] }, { id: 'asr', label: 'ASR / Transcription', filterLabel: 'ASR', tasks: ['asr'] }, @@ -215,13 +211,53 @@ seed_vc: 'Seed-VC' }; + function pathVariantLabel(path: string) { + const normalized = path.replace(/\\/g, '/'); + const filename = normalized.split('/').filter(Boolean).pop() || ''; + const match = filename.match(/(?:^|[-_])(\d+(?:\.\d+)?[bm])(?:[-_]|$)/i); + return match ? match[1].toUpperCase() : ''; + } + + function catalogPathMatches(expectedPath: string, actualPath: string) { + const actual = comparablePath(actualPath); + const expected = comparablePath(resolveCatalogPath(expectedPath)); + if (actual === expected) return true; + const relative = comparablePath(expectedPath).replace(/^models\//, ''); + return actual === relative || actual.endsWith(`/${relative}`); + } + + function catalogEntryMatchesLoadedModel(entry: CatalogEntry, model: LoadedModel) { + if (entry.family !== model.family || entry.task !== model.task) return false; + if (catalogPathMatches(entry.path, model.path)) return true; + return Boolean((entry.install_packages || []).some((choice) => + catalogPathMatches(choice.path, model.path))); + } + + function loadedCatalogEntry(model: LoadedModel) { + const exact = catalog.find((entry) => entry.id === model.id); + if (exact && catalogEntryMatchesLoadedModel(exact, model)) return exact; + return catalog.find((entry) => catalogEntryMatchesLoadedModel(entry, model)); + } + + function inferredLoadedModelName(model: LoadedModel, base?: CatalogEntry) { + const variant = pathVariantLabel(model.path); + const familyName = familyLabels[model.family] || base?.display_name || model.family; + return variant && !familyName.toLowerCase().includes(variant.toLowerCase()) + ? `${familyName} ${variant}` + : familyName; + } + + function loadedModelName(model: LoadedModel) { + return loadedCatalogEntry(model)?.display_name || inferredLoadedModelName(model); + } + function compareModelNames(left: string, right: string) { return left.localeCompare(right, 'en', { sensitivity: 'base', numeric: true }); } function configuredCatalogEntries() { return loadedModels.map((model) => { - const exact = catalog.find((entry) => entry.id === model.id); + const exact = loadedCatalogEntry(model); const familyMatch = catalog.find((entry) => entry.family === model.family && entry.task === model.task); const base = exact || familyMatch; @@ -235,7 +271,7 @@ mode: model.mode }), id: model.id, - display_name: exact ? exact.display_name : base ? `${base.display_name} (${model.id})` : model.id, + display_name: exact ? exact.display_name : inferredLoadedModelName(model, base), display_name_en: exact ? exact.display_name_en : base?.display_name_en, family: model.family, path: model.path, @@ -353,11 +389,7 @@ } function packagePathMatches(choice: InstallPackageChoice, path: string) { - const actual = comparablePath(path); - const expected = comparablePath(resolveCatalogPath(choice.path)); - if (actual === expected) return true; - const relative = comparablePath(choice.path).replace(/^models\//, ''); - return actual === relative || actual.endsWith(`/${relative}`); + return catalogPathMatches(choice.path, path); } function residentModel(entry: CatalogEntry, models = loadedModels) {