Feat: Model-Manager — Ko-Residenz-Schalter + "verdraengt das Hirn"-Warnung

Verhindert versehentliches Verdraengen des warmen Hirns im Modell-Manager.
- api.ts: GroupsResp-Typ + getGroups/setGroup (PUT /api/groups).
- queries.ts: useGroups-Hook (qk.groups).
- Cockpit: pro Modell ein "Brain"-Schalter (Ko-Residenz in der brains-Gruppe
  an/aus) + "Ko-resident"-Badge. Beim Laden eines gruppenlosen Modells, das
  ein warmes brains-Mitglied rauswerfen wuerde, erscheint eine Bestaetigung
  mit Hinweis auf den Schalter (beide warm halten).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Hitonabi
2026-06-28 22:52:00 +02:00
parent 68cad9c0f1
commit 50e04e0aee
9 changed files with 5568 additions and 5466 deletions
+14
View File
@@ -53,6 +53,20 @@ export async function api<T = unknown>(path: string, init?: RequestInit): Promis
return res.json() as Promise<T>
}
// llama-swap-`groups`: Mitglieder mit swap=false dürfen GLEICHZEITIG resident sein (Ko-Residenz).
// Die `brains`-Gruppe hält Hirn (fast) + Augen (vision) gemeinsam warm, statt sich zu verdrängen.
export interface GroupSpec {
swap: boolean
persist: boolean
members: string[]
}
export interface GroupsResp {
groups: Record<string, GroupSpec>
}
export const getGroups = () => api<GroupsResp>("/api/groups")
export const setGroup = (group: string, members: string[], swap = false, persist = true) =>
api("/api/groups", { method: "PUT", body: JSON.stringify({ group, members, swap, persist }) })
export interface Capabilities {
moe: boolean
active_b: number | null
+5
View File
@@ -10,6 +10,7 @@ import {
type ConnectHealth,
type DiscoverResp,
type DraftsResp,
type GroupsResp,
type HermesBrainResp,
type Health,
type Job,
@@ -29,6 +30,7 @@ export const qk = {
systemStatus: ["system-status"] as const,
services: ["services"] as const,
models: ["models"] as const,
groups: ["groups"] as const,
routing: ["routing"] as const,
jobs: ["jobs"] as const,
tokenStats: ["token-stats"] as const,
@@ -62,6 +64,9 @@ export const useServices = (refetchInterval = 3_000) =>
export const useModels = (refetchInterval = 4_000) =>
useQuery({ queryKey: qk.models, queryFn: () => api<ModelsResp>("/api/models"), refetchInterval })
export const useGroups = (refetchInterval = 8_000) =>
useQuery({ queryKey: qk.groups, queryFn: () => api<GroupsResp>("/api/groups"), refetchInterval })
export const useRouting = (refetchInterval = 4_000) =>
useQuery({ queryKey: qk.routing, queryFn: () => api<RoutingResp>("/api/routing"), refetchInterval })