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:
@@ -38,6 +38,9 @@ const (
|
||||
TypeSnapshotComplete = "snapshot_complete"
|
||||
TypeWorkflowList = "workflow.list"
|
||||
TypeToolAssessed = "tool.assessed"
|
||||
TypeModelChanged = "model.changed"
|
||||
TypeModelList = "model.list"
|
||||
TypeResourceStatus = "resource.status"
|
||||
)
|
||||
|
||||
// ServerMessage is a flat decode of every server->client variant. Field names
|
||||
@@ -69,6 +72,20 @@ type ServerMessage struct {
|
||||
ElapsedMs int64 `json:"elapsedMs"`
|
||||
LastSequence int64 `json:"lastSequence"`
|
||||
|
||||
// model.changed
|
||||
ModelID string `json:"modelId"`
|
||||
Loaded bool `json:"loaded"`
|
||||
|
||||
// model.list (current reuses the field below)
|
||||
Models []string `json:"models"`
|
||||
Current string `json:"current"`
|
||||
|
||||
// resource.status (nil = unavailable)
|
||||
GpuMemoryUsedMb *int64 `json:"gpuMemoryUsedMb"`
|
||||
GpuMemoryTotalMb *int64 `json:"gpuMemoryTotalMb"`
|
||||
GpuUtilizationPct *int `json:"gpuUtilizationPct"`
|
||||
ProcessRssMb *int64 `json:"processRssMb"`
|
||||
|
||||
State *SessionStateDto `json:"state"`
|
||||
RiskSummary *RiskSummaryDto `json:"riskSummary"`
|
||||
Status *ProviderHealthDto `json:"status"`
|
||||
@@ -206,6 +223,16 @@ func Ping(ts int64) []byte {
|
||||
return encode("Ping", map[string]any{"timestamp": ts})
|
||||
}
|
||||
|
||||
// SwapModel asks the server to make modelID resident and pin it.
|
||||
func SwapModel(modelID string) []byte {
|
||||
return encode("SwapModel", map[string]any{"modelId": modelID})
|
||||
}
|
||||
|
||||
// ClearModelPin releases the manual-swap pin so per-stage selection resumes.
|
||||
func ClearModelPin() []byte {
|
||||
return encode("ClearModelPin", map[string]any{})
|
||||
}
|
||||
|
||||
// CreateGrant pre-authorizes a tool/tier so future calls skip the approval gate.
|
||||
// scope is "SESSION" or "STAGE"; permittedTiers are tier names like "T3".
|
||||
func CreateGrant(sessionID, scope string, permittedTiers []string, reason, toolName string) []byte {
|
||||
|
||||
Reference in New Issue
Block a user