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:
@@ -283,6 +283,19 @@ sealed interface ServerMessage {
|
||||
override val sessionSequence: Long? = null,
|
||||
) : ServerMessage, NonEventMessage
|
||||
|
||||
/**
|
||||
* The configured local models and which one is currently resident. Sent once in the initial
|
||||
* snapshot when correx manages the model process, so clients can offer a swap picker.
|
||||
*/
|
||||
@Serializable
|
||||
@SerialName("model.list")
|
||||
data class ModelList(
|
||||
val models: List<String>,
|
||||
val current: String?,
|
||||
override val sequence: Long? = null,
|
||||
override val sessionSequence: Long? = null,
|
||||
) : ServerMessage, NonEventMessage
|
||||
|
||||
/**
|
||||
* Live resource gauge pushed periodically on the global stream (not event-derived). All fields
|
||||
* are nullable: GPU fields are null on a non-NVIDIA host, `processRssMb` is null when no model
|
||||
|
||||
@@ -149,6 +149,16 @@ class GlobalStreamHandler(private val module: ServerModule) {
|
||||
ServerMessage.WorkflowList(workflows = workflows),
|
||||
)))
|
||||
|
||||
// Configured models + current, so the client can offer a swap picker (managed path only).
|
||||
module.modelSwapper?.let { swapper ->
|
||||
session.send(Frame.Text(ProtocolSerializer.encodeServerMessage(
|
||||
ServerMessage.ModelList(
|
||||
models = swapper.availableModelIds(),
|
||||
current = swapper.currentModelId(),
|
||||
),
|
||||
)))
|
||||
}
|
||||
|
||||
// Initial resource gauge so a freshly-connected client renders VRAM/RAM immediately.
|
||||
val snapshot = withContext(Dispatchers.IO) { module.resourceProbe.probe() }
|
||||
session.send(Frame.Text(ProtocolSerializer.encodeServerMessage(snapshot.toResourceStatus())))
|
||||
|
||||
Reference in New Issue
Block a user