feat: correx-managed model lifecycle slice 5 — Go TUI model swap + telemetry

Go TUI decodes model.changed / model.list / resource.status and renders a
status-bar VRAM/GPU%/RAM gauge plus a models overlay (m key / palette 'models'):
lists configured models with the resident one marked, enter swaps (SwapModel),
c clears the pin (ClearModelPin). All three new server messages are
non-event-bearing control/gauge frames, applied immediately like
provider.status_changed.

Server addition required for the picker: ServerMessage.ModelList (model.list,
NonEventMessage) sent once in the initial snapshot from
ManagedInferenceRouter.availableModelIds()/currentModelId() — the TUI otherwise
cannot enumerate swap targets.

Completes the 5-slice model-lifecycle feature. ./gradlew check green; go build/vet clean.

Plan: docs/plans/2026-05-31-model-lifecycle-management.md (slice 5 of 5).
This commit is contained in:
2026-06-01 13:36:01 +04:00
parent 7b1df95627
commit 55a18b4b3a
9 changed files with 174 additions and 2 deletions
@@ -79,6 +79,12 @@ class ManagedInferenceRouter(
/** The currently pinned model id, or null when no manual swap is active. */
fun pinnedModel(): String? = pinnedModelId
/** All configured model ids, in config order — the swap candidates surfaced to clients. */
fun availableModelIds(): List<String> = ordered.map { it.modelId }
/** The currently resident model id, or null when none is loaded. */
fun currentModelId(): String? = manager.currentModel()?.modelId
/**
* Selects the configured model whose declared capabilities cover every required capability,
* preferring the highest summed score over those required capabilities. Returns null when no