feat: controles de hot-reload por agente en el dashboard TUI
Añade opciones de Reload (hot-reload) separadas de Restart (reinicio
completo) en el dashboard, usando el mecanismo SIGHUP implementado en
el issue 0013.
Cambios en pkg/tui/ (capa pura):
- IntentReloadAgent: hot-reload de un agente individual via SIGHUP
- IntentReloadAll: hot-reload de todos los agentes via SIGHUP
- AgentActionOptions: añade "Reload" antes de "Restart" con descripciones
clarificadas ("sin interrumpir los demás" vs "launcher completo")
- ServerMenuOptions (running): añade "Reload All" como primera opción
- executeAction: maneja "Reload" → IntentReloadAgent
- executeServerAction: maneja "Reload All" → IntentReloadAll
- Mensajes de estado diferenciados: "Reload OK — X recargado sin
interrupciones" vs "Restart OK — launcher reiniciado"
Cambios en shell/tui/ (capa impura):
- reloadAgent(id): escribe run/reload.txt + SIGHUP; error si launcher
no está corriendo (no hay fallback a full restart)
- reloadAll(): elimina reload.txt + SIGHUP; error si no está corriendo
- restartAgent(id): restaurado a su comportamiento original de
stop+start completo del launcher
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+5
-2
@@ -96,6 +96,7 @@ func TestMenuOptions() []MenuOption {
|
||||
func ServerMenuOptions(running bool) []MenuOption {
|
||||
if running {
|
||||
return []MenuOption{
|
||||
{Label: "Reload All", Desc: "Hot-reload de todos los agentes (SIGHUP)"},
|
||||
{Label: "Stop", Desc: "Detener el launcher"},
|
||||
{Label: "Restart", Desc: "Reiniciar el launcher"},
|
||||
{Label: "Kill", Desc: "SIGKILL forzado"},
|
||||
@@ -115,13 +116,15 @@ func ServerMenuOptions(running bool) []MenuOption {
|
||||
func AgentActionOptions(enabled bool) []MenuOption {
|
||||
if enabled {
|
||||
return []MenuOption{
|
||||
{Label: "Restart", Desc: "Reiniciar launcher para aplicar cambios"},
|
||||
{Label: "Reload", Desc: "Hot-reload este agente (SIGHUP, sin interrumpir los demás)"},
|
||||
{Label: "Restart", Desc: "Reiniciar el launcher completo (todos los agentes)"},
|
||||
{Label: "Disable", Desc: "Desactivar agente (requiere restart)"},
|
||||
{Label: "Logs", Desc: "Ver log del launcher"},
|
||||
}
|
||||
}
|
||||
return []MenuOption{
|
||||
{Label: "Restart", Desc: "Reiniciar launcher para aplicar cambios"},
|
||||
{Label: "Reload", Desc: "Hot-reload este agente (SIGHUP, sin interrumpir los demás)"},
|
||||
{Label: "Restart", Desc: "Reiniciar el launcher completo (todos los agentes)"},
|
||||
{Label: "Enable", Desc: "Activar agente (requiere restart)"},
|
||||
{Label: "Logs", Desc: "Ver log del launcher"},
|
||||
}
|
||||
|
||||
+14
-2
@@ -14,7 +14,9 @@ const (
|
||||
// Agent-level
|
||||
IntentEnableAgent IntentKind = "enable_agent"
|
||||
IntentDisableAgent IntentKind = "disable_agent"
|
||||
IntentRestartAgent IntentKind = "restart_agent"
|
||||
IntentReloadAgent IntentKind = "reload_agent" // hot-reload via SIGHUP (solo este agente)
|
||||
IntentReloadAll IntentKind = "reload_all" // hot-reload via SIGHUP (todos los agentes)
|
||||
IntentRestartAgent IntentKind = "restart_agent" // restart completo del launcher
|
||||
|
||||
// Unified launcher operations
|
||||
IntentStartLauncher IntentKind = "start_launcher"
|
||||
@@ -74,8 +76,10 @@ func Update(model Model, msg interface{}) (Model, []Intent) {
|
||||
case MsgActionDone:
|
||||
if m.Err != nil {
|
||||
model.StatusMsg = fmt.Sprintf("Error: %s %s: %v", m.Action, m.AgentID, m.Err)
|
||||
} else if m.Action == "Reload" {
|
||||
model.StatusMsg = fmt.Sprintf("Reload OK — %s recargado sin interrupciones", m.AgentID)
|
||||
} else if m.Action == "Restart" {
|
||||
model.StatusMsg = fmt.Sprintf("Restart OK — all agents reloaded")
|
||||
model.StatusMsg = "Restart OK — launcher reiniciado"
|
||||
} else {
|
||||
model.StatusMsg = fmt.Sprintf("%s %s OK — restart launcher to apply", m.Action, m.AgentID)
|
||||
}
|
||||
@@ -84,6 +88,8 @@ func Update(model Model, msg interface{}) (Model, []Intent) {
|
||||
case MsgServerActionDone:
|
||||
if m.Err != nil {
|
||||
model.StatusMsg = fmt.Sprintf("Error: %s: %v", m.Action, m.Err)
|
||||
} else if m.Action == "Reload All" {
|
||||
model.StatusMsg = "Reload All OK — SIGHUP enviado al launcher"
|
||||
} else {
|
||||
model.StatusMsg = fmt.Sprintf("%s OK", m.Action)
|
||||
}
|
||||
@@ -245,6 +251,9 @@ func executeAction(model Model, action string) (Model, []Intent) {
|
||||
case "Disable":
|
||||
model.StatusMsg = "Disabling " + id + "..."
|
||||
return model, []Intent{{Kind: IntentDisableAgent, AgentID: id}}
|
||||
case "Reload":
|
||||
model.StatusMsg = "Hot-reloading " + id + "..."
|
||||
return model, []Intent{{Kind: IntentReloadAgent, AgentID: id}}
|
||||
case "Restart":
|
||||
model.StatusMsg = "Restarting launcher (all agents)..."
|
||||
return model, []Intent{{Kind: IntentRestartAgent, AgentID: id}}
|
||||
@@ -302,6 +311,9 @@ func updateServerScreen(model Model, key KeyMsg) (Model, []Intent) {
|
||||
|
||||
func executeServerAction(model Model, action string) (Model, []Intent) {
|
||||
switch action {
|
||||
case "Reload All":
|
||||
model.StatusMsg = "Hot-reloading all agents..."
|
||||
return model, []Intent{{Kind: IntentReloadAll}}
|
||||
case "Start":
|
||||
model.StatusMsg = "Starting launcher..."
|
||||
return model, []Intent{{Kind: IntentStartLauncher}}
|
||||
|
||||
Reference in New Issue
Block a user