refactor: update dev-scripts for unified launcher model

Actualiza todos los scripts de desarrollo para el modelo de launcher unificado.
Ya no se inician procesos individuales por agente — un solo proceso corre todos.

_common.sh: helpers para launcher unificado (is_launcher_running, read_launcher_pid,
launcher_pid_file/log_file), agent_status() ahora deriva estado del launcher
start.sh: inicia el launcher unificado (sin -c flag, descubre todos los agentes)
stop.sh: detiene el launcher unificado
restart.sh: stop + start del launcher
ps.sh: muestra stats del proceso launcher + lista de agentes enabled/disabled
logs.sh: tail -f del log unificado del launcher
server.sh: añade comandos enable/disable para gestionar agentes, elimina start/stop por agente
remove.sh: simplificado a toggle enabled:false + sugerencia de restart

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-06 09:06:11 +00:00
parent 1af0457c1f
commit b86da0b805
8 changed files with 265 additions and 307 deletions
+28 -1
View File
@@ -114,13 +114,40 @@ agent_status() {
local id="$1" enabled="$2" local id="$1" enabled="$2"
if [[ "$enabled" != "true" ]]; then if [[ "$enabled" != "true" ]]; then
echo "disabled" echo "disabled"
elif is_running "$id"; then elif is_launcher_running; then
echo "running" echo "running"
else else
echo "stopped" echo "stopped"
fi fi
} }
# ── Unified launcher helpers ───────────────────────────────────────────────
LAUNCHER_ID="launcher"
launcher_pid_file() { echo "$RUN_DIR/$LAUNCHER_ID.pid"; }
launcher_log_file() { echo "$RUN_DIR/$LAUNCHER_ID.log"; }
read_launcher_pid() {
local f; f="$(launcher_pid_file)"
[[ -f "$f" ]] && cat "$f" || echo 0
}
is_launcher_running() {
local pid; pid="$(read_launcher_pid)"
if [[ "$pid" -gt 0 ]] && kill -0 "$pid" 2>/dev/null; then
return 0
fi
# Fallback: search for launcher process without -c flag
local pids; pids="$(pgrep -f 'launcher.*--log-level' 2>/dev/null || true)"
if [[ -n "$pids" ]]; then
local first_pid; first_pid="$(echo "$pids" | head -1)"
echo "$first_pid" > "$(launcher_pid_file)"
return 0
fi
[[ "$pid" -gt 0 ]] && rm -f "$(launcher_pid_file)"
return 1
}
# ── Agent discovery ──────────────────────────────────────────────────────── # ── Agent discovery ────────────────────────────────────────────────────────
# Prints: id|version|enabled|description (one line per agent) # Prints: id|version|enabled|description (one line per agent)
list_agents_raw() { list_agents_raw() {
+9 -19
View File
@@ -1,31 +1,21 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# logs.sh — sigue los logs de uno o todos los agentes # logs.sh — sigue los logs del launcher unificado
# #
# Uso: # Uso:
# ./dev-scripts/logs.sh # tail -f de todos los logs activos # ./dev-scripts/logs.sh # tail -f del launcher log
# ./dev-scripts/logs.sh assistant-bot # solo ese agente # ./dev-scripts/logs.sh 100 # últimas 100 líneas
# ./dev-scripts/logs.sh assistant-bot 100 # últimas 100 líneas
source "$(dirname "$0")/_common.sh" source "$(dirname "$0")/_common.sh"
TARGET="${1:-}" LINES="${1:-50}"
LINES="${2:-50}" LOG="$(launcher_log_file)"
log_files=() if [[ ! -f "$LOG" ]]; then
fail "No hay logs todavía — inicia el launcher primero"
while IFS='|' read -r id _version _enabled _desc _cfg; do
[[ -n "$TARGET" && "$id" != "$TARGET" ]] && continue
local_log="$(log_file "$id")"
[[ -f "$local_log" ]] && log_files+=("$local_log")
done < <(list_agents_raw)
if [[ "${#log_files[@]}" -eq 0 ]]; then
[[ -n "$TARGET" ]] && fail "No hay logs para '$TARGET' (¿ha sido iniciado alguna vez?)"
fail "No hay logs todavía — inicia algún agente primero"
fi fi
info "Siguiendo logs: ${log_files[*]}" info "Siguiendo logs: $LOG"
dim " Ctrl+C para salir" dim " Ctrl+C para salir"
echo "" echo ""
tail -n "$LINES" -f "${log_files[@]}" tail -n "$LINES" -f "$LOG"
+29 -40
View File
@@ -1,35 +1,29 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# ps.sh — muestra procesos de agentes con detalles (PID, uptime, memoria, CPU) # ps.sh — muestra el estado del launcher unificado y agentes
# #
# Uso: # Uso:
# ./dev-scripts/ps.sh # todos los agentes corriendo # ./dev-scripts/ps.sh
# ./dev-scripts/ps.sh assistant-bot # uno específico
source "$(dirname "$0")/_common.sh" source "$(dirname "$0")/_common.sh"
TARGET="${1:-}" if ! is_launcher_running; then
found=0 echo ""
dim " Launcher no está corriendo."
# Cabecera echo ""
printf "%-22s %-8s %-12s %-10s %-8s %s\n" \ echo " Agentes:"
"AGENT" "PID" "UPTIME" "MEM (RSS)" "CPU %" "LOG SIZE" while IFS='|' read -r id _v enabled _d _c; do
printf '%s\n' "$(printf '─%.0s' {1..78})" if [[ "$enabled" == "true" ]]; then
echo -e " ${GRN}${RST} $id (enabled)"
while IFS='|' read -r id _version _enabled _desc _cfg; do else
[[ -n "$TARGET" && "$id" != "$TARGET" ]] && continue echo -e " ${DIM}$id (disabled)${RST}"
if ! is_running "$id"; then
if [[ -n "$TARGET" ]]; then
printf "%-22s ${DIM}%-8s${RST}\n" "$id" "stopped"
fi fi
continue done < <(list_agents_raw)
exit 0
fi fi
pid="$(read_pid "$id")" pid="$(read_launcher_pid)"
instance_count="$(count_instances "$id")"
((found++)) || true
# Uptime: calcular desde el inicio del proceso # Uptime
if [[ -f /proc/$pid/stat ]]; then if [[ -f /proc/$pid/stat ]]; then
start_ticks=$(awk '{print $22}' /proc/$pid/stat 2>/dev/null || echo 0) start_ticks=$(awk '{print $22}' /proc/$pid/stat 2>/dev/null || echo 0)
clk_tck=$(getconf CLK_TCK) clk_tck=$(getconf CLK_TCK)
@@ -51,7 +45,7 @@ while IFS='|' read -r id _version _enabled _desc _cfg; do
uptime="n/a" uptime="n/a"
fi fi
# Memoria RSS y CPU desde ps # Memory and CPU
read -r mem_kb cpu_pct < <(ps -p "$pid" -o rss=,pcpu= 2>/dev/null || echo "0 0") read -r mem_kb cpu_pct < <(ps -p "$pid" -o rss=,pcpu= 2>/dev/null || echo "0 0")
if [[ "$mem_kb" -gt 1048576 ]]; then if [[ "$mem_kb" -gt 1048576 ]]; then
mem="$(( mem_kb / 1048576 )) GB" mem="$(( mem_kb / 1048576 )) GB"
@@ -61,8 +55,8 @@ while IFS='|' read -r id _version _enabled _desc _cfg; do
mem="${mem_kb} KB" mem="${mem_kb} KB"
fi fi
# Tamaño del log # Log size
log="$(log_file "$id")" log="$(launcher_log_file)"
if [[ -f "$log" ]]; then if [[ -f "$log" ]]; then
log_bytes=$(stat -c%s "$log" 2>/dev/null || echo 0) log_bytes=$(stat -c%s "$log" 2>/dev/null || echo 0)
if [[ "$log_bytes" -gt 1048576 ]]; then if [[ "$log_bytes" -gt 1048576 ]]; then
@@ -76,21 +70,16 @@ while IFS='|' read -r id _version _enabled _desc _cfg; do
log_size="-" log_size="-"
fi fi
printf "%-22s ${GRN}%-8s${RST} %-12s %-10s %-8s %s\n" \ echo ""
"$id" "$pid" "$uptime" "$mem" "${cpu_pct}%" "$log_size" echo -e " ${GRN}● Launcher running${RST} PID $pid"
echo -e " uptime: $uptime mem: $mem cpu: ${cpu_pct}% log: $log_size"
echo ""
echo " Agentes:"
# Warn about duplicate instances while IFS='|' read -r id _v enabled _d _c; do
if [[ "$instance_count" -gt 1 ]]; then if [[ "$enabled" == "true" ]]; then
printf " ${RED}⚠ WARNING: %d instances running!${RST} PIDs: %s\n" \ echo -e " ${GRN}${RST} $id (enabled, running in launcher)"
"$instance_count" "$(find_agent_pids "$id" | tr '\n' ' ')"
fi
done < <(list_agents_raw)
if [[ "$found" -eq 0 ]]; then
if [[ -n "$TARGET" ]]; then
fail "Agente '$TARGET' no está corriendo."
else else
dim " No hay agentes corriendo." echo -e " ${DIM}$id (disabled)${RST}"
fi
fi fi
done < <(list_agents_raw)
+2 -13
View File
@@ -14,22 +14,11 @@ while IFS='|' read -r id _version _enabled _desc cfg; do
[[ "$id" != "$TARGET" ]] && continue [[ "$id" != "$TARGET" ]] && continue
found=true found=true
# Detener si está corriendo # Marcar como disabled en el config
if is_running "$id"; then
local_pid="$(read_pid "$id")"
info "Deteniendo $id (PID $local_pid)..."
kill -TERM "$local_pid" 2>/dev/null || true
sleep 1
kill -0 "$local_pid" 2>/dev/null && kill -9 "$local_pid" 2>/dev/null || true
rm -f "$(pid_file "$id")"
ok "$id detenido"
fi
# Marcar como disabled en el config (reemplaza solo la primera ocurrencia)
if grep -q 'enabled: true' "$cfg"; then if grep -q 'enabled: true' "$cfg"; then
# sed compatible con Linux y macOS
sed -i 's/enabled: true/enabled: false/' "$cfg" sed -i 's/enabled: true/enabled: false/' "$cfg"
ok "$id marcado como disabled en $cfg" ok "$id marcado como disabled en $cfg"
info "Reinicia el launcher para aplicar: ./dev-scripts/server.sh restart"
else else
warn "$id ya estaba marcado como disabled" warn "$id ya estaba marcado como disabled"
fi fi
+6 -9
View File
@@ -1,17 +1,14 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# restart.sh — reinicia uno o todos los agentes # restart.sh — reinicia el launcher unificado
# #
# Uso: # Uso:
# ./dev-scripts/restart.sh # reinicia todos los habilitados # ./dev-scripts/restart.sh
# ./dev-scripts/restart.sh assistant-bot # reinicia uno específico
source "$(dirname "$0")/_common.sh" source "$(dirname "$0")/_common.sh"
TARGET="${1:-}" info "Deteniendo launcher..."
"$REPO_ROOT/dev-scripts/stop.sh"
info "Deteniendo agentes..."
"$REPO_ROOT/dev-scripts/stop.sh" ${TARGET:+"$TARGET"}
echo "" echo ""
info "Iniciando agentes..." info "Iniciando launcher..."
"$REPO_ROOT/dev-scripts/start.sh" ${TARGET:+"$TARGET"} "$REPO_ROOT/dev-scripts/start.sh"
+82 -67
View File
@@ -2,122 +2,137 @@
# server.sh — gestión unificada del servidor de bots # server.sh — gestión unificada del servidor de bots
# #
# Uso: # Uso:
# ./dev-scripts/server.sh start [agent-id] # iniciar uno o todos # ./dev-scripts/server.sh start # iniciar el launcher
# ./dev-scripts/server.sh stop [agent-id] # detener uno o todos # ./dev-scripts/server.sh stop # detener el launcher
# ./dev-scripts/server.sh restart [agent-id] # reiniciar uno o todos # ./dev-scripts/server.sh restart # reiniciar el launcher
# ./dev-scripts/server.sh status # resumen general del servidor # ./dev-scripts/server.sh status # resumen general del servidor
# ./dev-scripts/server.sh ps [agent-id] # procesos con detalle # ./dev-scripts/server.sh ps # proceso con detalle
# ./dev-scripts/server.sh logs [agent-id] # tail -f de logs # ./dev-scripts/server.sh logs [lines] # tail -f de logs
# ./dev-scripts/server.sh kill [agent-id] # SIGKILL forzado (emergencia) # ./dev-scripts/server.sh kill # SIGKILL forzado (emergencia)
# ./dev-scripts/server.sh enable <id> # habilitar un agente
# ./dev-scripts/server.sh disable <id> # deshabilitar un agente
# ./dev-scripts/server.sh dashboard # TUI interactivo # ./dev-scripts/server.sh dashboard # TUI interactivo
source "$(dirname "$0")/_common.sh" source "$(dirname "$0")/_common.sh"
CMD="${1:-status}" CMD="${1:-status}"
shift || true shift || true
AGENT="${1:-}" ARG="${1:-}"
toggle_agent_enabled() {
local id="$1" value="$2"
for cfg in agents/*/config.yaml; do
[[ -f "$cfg" ]] || continue
local cid
cid=$(grep -m1 '^ id:' "$cfg" | awk '{print $2}')
if [[ "$cid" == "$id" ]]; then
sed -i "s/^\\( enabled:\\).*/\\1 $value/" "$cfg"
ok "$id enabled: $value"
info "Reinicia el launcher para aplicar: ./dev-scripts/server.sh restart"
return 0
fi
done
fail "Agente '$id' no encontrado"
}
case "$CMD" in case "$CMD" in
start) start)
exec "$REPO_ROOT/dev-scripts/start.sh" ${AGENT:+"$AGENT"} exec "$REPO_ROOT/dev-scripts/start.sh"
;; ;;
stop) stop)
exec "$REPO_ROOT/dev-scripts/stop.sh" ${AGENT:+"$AGENT"} exec "$REPO_ROOT/dev-scripts/stop.sh"
;; ;;
restart) restart)
exec "$REPO_ROOT/dev-scripts/restart.sh" ${AGENT:+"$AGENT"} exec "$REPO_ROOT/dev-scripts/restart.sh"
;; ;;
ps) ps)
exec "$REPO_ROOT/dev-scripts/ps.sh" ${AGENT:+"$AGENT"} exec "$REPO_ROOT/dev-scripts/ps.sh"
;; ;;
logs) logs)
exec "$REPO_ROOT/dev-scripts/logs.sh" ${AGENT:+"$AGENT"} exec "$REPO_ROOT/dev-scripts/logs.sh" ${ARG:+"$ARG"}
;; ;;
dashboard|tui) dashboard|tui)
exec "$REPO_ROOT/dev-scripts/dashboard.sh" exec "$REPO_ROOT/dev-scripts/dashboard.sh"
;; ;;
kill) enable)
# SIGKILL forzado para emergencias [[ -n "$ARG" ]] || fail "Uso: $0 enable <agent-id>"
if [[ -n "$AGENT" ]]; then toggle_agent_enabled "$ARG" "true"
agents=("$AGENT") ;;
else
agents=()
while IFS='|' read -r id _v _e _d _c; do
agents+=("$id")
done < <(list_agents_raw)
fi
killed=0 disable)
for id in "${agents[@]}"; do [[ -n "$ARG" ]] || fail "Uso: $0 disable <agent-id>"
all_pids="$(find_agent_pids "$id")" toggle_agent_enabled "$ARG" "false"
if [[ -n "$all_pids" ]]; then ;;
cnt="$(echo "$all_pids" | wc -l)"
for p in $all_pids; do kill)
kill -9 "$p" 2>/dev/null || true if ! is_launcher_running; then
done dim " El launcher no está corriendo."
rm -f "$(pid_file "$id")" exit 0
ok "$id killed ($cnt instance(s), PIDs: $(echo $all_pids | tr '\n' ' '))"
((killed++)) || true
else
dim " $id (no estaba corriendo)"
fi fi
done pid="$(read_launcher_pid)"
[[ "$killed" -eq 0 ]] && dim "Ningún proceso eliminado." kill -9 "$pid" 2>/dev/null || true
rm -f "$(launcher_pid_file)"
ok "Launcher killed (PID $pid)"
;; ;;
status) status)
# Resumen general del servidor
total=0
running=0
stopped=0
disabled=0
while IFS='|' read -r id _version enabled _desc _cfg; do
((total++)) || true
st=$(agent_status "$id" "$enabled")
case "$st" in
running) ((running++)) || true ;;
stopped) ((stopped++)) || true ;;
disabled) ((disabled++)) || true ;;
esac
done < <(list_agents_raw)
echo "" echo ""
echo -e " ${BLU}Bot Server Status${RST}" echo -e " ${BLU}Bot Server Status${RST}"
printf '%s\n' " $(printf '─%.0s' {1..40})" printf '%s\n' " $(printf '─%.0s' {1..40})"
echo -e " Agentes totales: $total"
echo -e " ${GRN}● Running:${RST} $running" if is_launcher_running; then
echo -e " ${DIM}○ Stopped:${RST} $stopped" pid="$(read_launcher_pid)"
echo -e " ${YLW} Disabled:${RST} $disabled" echo -e " ${GRN}● Launcher running${RST} PID $pid"
else
echo -e " ${DIM}○ Launcher stopped${RST}"
fi
echo ""
enabled=0
disabled=0
total=0
while IFS='|' read -r id _v en _d _c; do
((total++)) || true
if [[ "$en" == "true" ]]; then
((enabled++)) || true
else
((disabled++)) || true
fi
done < <(list_agents_raw)
echo -e " Agentes totales: $total"
echo -e " ${GRN}● Enabled:${RST} $enabled"
echo -e " ${DIM}○ Disabled:${RST} $disabled"
echo "" echo ""
# Mostrar tabla de agentes
"$REPO_ROOT/dev-scripts/list.sh" "$REPO_ROOT/dev-scripts/list.sh"
# Si hay agentes corriendo, mostrar uso de recursos if is_launcher_running; then
if [[ "$running" -gt 0 ]]; then
echo "" echo ""
"$REPO_ROOT/dev-scripts/ps.sh" "$REPO_ROOT/dev-scripts/ps.sh"
fi fi
;; ;;
*) *)
echo "Uso: $0 {start|stop|restart|status|ps|logs|kill|dashboard} [agent-id]" echo "Uso: $0 {start|stop|restart|status|ps|logs|kill|enable|disable|dashboard}"
echo "" echo ""
echo "Comandos:" echo "Comandos:"
echo " start [id] Iniciar uno o todos los agentes habilitados" echo " start Iniciar el launcher unificado"
echo " stop [id] Detener uno o todos los agentes" echo " stop Detener el launcher"
echo " restart [id] Reiniciar uno o todos los agentes" echo " restart Reiniciar el launcher"
echo " status Resumen general del servidor" echo " status Resumen general del servidor"
echo " ps [id] Procesos corriendo con detalle (PID, mem, CPU)" echo " ps Proceso del launcher con detalle (PID, mem, CPU)"
echo " logs [id] Tail -f de logs" echo " logs [lines] Tail -f de logs del launcher"
echo " kill [id] SIGKILL forzado (solo emergencias)" echo " kill SIGKILL forzado (solo emergencias)"
echo " enable <id> Habilitar un agente (requiere restart)"
echo " disable <id> Deshabilitar un agente (requiere restart)"
echo " dashboard TUI interactivo de gestión" echo " dashboard TUI interactivo de gestión"
exit 1 exit 1
;; ;;
+36 -58
View File
@@ -1,73 +1,51 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# start.sh — inicia uno o todos los agentes habilitados en background # start.sh — inicia el launcher unificado (todos los agentes habilitados)
# #
# Uso: # Uso:
# ./dev-scripts/start.sh # inicia todos los habilitados # ./dev-scripts/start.sh # inicia el launcher unificado
# ./dev-scripts/start.sh assistant-bot # inicia uno específico
source "$(dirname "$0")/_common.sh" source "$(dirname "$0")/_common.sh"
load_env load_env
TARGET="${1:-}" if is_launcher_running; then
pid="$(read_launcher_pid)"
start_agent() { fail "El launcher ya está corriendo (PID $pid). Usa restart.sh para reiniciar."
local id="$1" cfg="$2"
local log; log="$(log_file "$id")"
local pid_f; pid_f="$(pid_file "$id")"
local bin="$REPO_ROOT/bin/launcher"
info "Iniciando $id..."
# Build the binary first to avoid go run wrapper PID issues
if [[ ! -x "$bin" ]] || [[ "$(find ./cmd/launcher -newer "$bin" 2>/dev/null | head -1)" ]]; then
info "Ejecutando tests..."
"$GO" test -tags goolm ./... || {
fail "$id tests fallaron — corrige antes de compilar"
return 1
}
info "Compilando launcher..."
mkdir -p "$(dirname "$bin")"
"$GO" build -tags goolm -o "$bin" ./cmd/launcher || {
fail "$id error de compilación — revisa el código"
return 1
}
fi fi
# Launch the compiled binary directly (no go run wrapper) BIN="$REPO_ROOT/bin/launcher"
nohup "$bin" -c "$cfg" --log-level "${LOG_LEVEL:-info}" \ LOG="$(launcher_log_file)"
>> "$log" 2>&1 & PID_F="$(launcher_pid_file)"
local pid=$! # Build if needed
echo "$pid" > "$pid_f" if [[ ! -x "$BIN" ]] || [[ "$(find ./cmd/launcher -newer "$BIN" 2>/dev/null | head -1)" ]]; then
info "Ejecutando tests..."
"$GO" test -tags goolm ./... || fail "Tests fallaron — corrige antes de compilar"
info "Compilando launcher..."
mkdir -p "$(dirname "$BIN")"
"$GO" build -tags goolm -o "$BIN" ./cmd/launcher || fail "Error de compilación"
fi
info "Iniciando launcher unificado..."
nohup "$BIN" --log-level "${LOG_LEVEL:-info}" \
>> "$LOG" 2>&1 &
pid=$!
echo "$pid" > "$PID_F"
# Espera un momento y verifica que el proceso siga vivo
sleep 1 sleep 1
if kill -0 "$pid" 2>/dev/null; then if kill -0 "$pid" 2>/dev/null; then
local inst; inst="$(count_instances "$id")" # Count enabled agents
ok "$id PID $pid (instances: $inst) → logs: $log" enabled=0
else total=0
rm -f "$pid_f" while IFS='|' read -r _id _v en _d _c; do
fail "$id arrancó pero murió — revisa: tail -f $log" ((total++)) || true
fi [[ "$en" == "true" ]] && ((enabled++)) || true
}
started=0
while IFS='|' read -r id version enabled desc cfg; do
# Filtrar por TARGET si se especificó uno
[[ -n "$TARGET" && "$id" != "$TARGET" ]] && continue
if [[ "$enabled" != "true" ]]; then
warn "$id (disabled en config, saltar)"
continue
fi
start_agent "$id" "$cfg"
((started++)) || true
done < <(list_agents_raw) done < <(list_agents_raw)
[[ "$started" -eq 0 && -z "$TARGET" ]] && warn "Ningún agente iniciado." ok "Launcher PID $pid ($enabled/$total agentes habilitados) → logs: $LOG"
[[ -n "$TARGET" && "$started" -eq 0 ]] && fail "Agente '$TARGET' no encontrado o ya está corriendo." else
rm -f "$PID_F"
true fail "Launcher arrancó pero murió — revisa: tail -f $LOG"
fi
+15 -42
View File
@@ -1,59 +1,32 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# stop.sh — detiene uno o todos los agentes en ejecución # stop.sh — detiene el launcher unificado
# #
# Uso: # Uso:
# ./dev-scripts/stop.sh # detiene todos los que estén corriendo # ./dev-scripts/stop.sh
# ./dev-scripts/stop.sh assistant-bot # detiene uno específico
source "$(dirname "$0")/_common.sh" source "$(dirname "$0")/_common.sh"
TARGET="${1:-}" if ! is_launcher_running; then
stopped=0 dim " El launcher no está corriendo."
exit 0
while IFS='|' read -r id _version _enabled _desc _cfg; do
[[ -n "$TARGET" && "$id" != "$TARGET" ]] && continue
if ! is_running "$id"; then
dim " $id (no está corriendo)"
continue
fi fi
# Kill ALL instances, not just the one in the PID file pid="$(read_launcher_pid)"
all_pids="$(find_agent_pids "$id")" info "Deteniendo launcher (PID $pid)..."
instance_count="$(echo "$all_pids" | grep -c . 2>/dev/null || echo 0)"
if [[ "$instance_count" -gt 1 ]]; then kill -TERM "$pid" 2>/dev/null || true
warn "$id has $instance_count instances running — stopping all"
fi
# Send SIGTERM to all instances
for p in $all_pids; do
kill -TERM "$p" 2>/dev/null || true
done
# Wait up to 5s for graceful shutdown # Wait up to 5s for graceful shutdown
for _ in {1..10}; do for _ in {1..10}; do
remaining="$(find_agent_pids "$id")" kill -0 "$pid" 2>/dev/null || break
[[ -z "$remaining" ]] && break
sleep 0.5 sleep 0.5
done done
# SIGKILL any survivors # SIGKILL if still alive
survivors="$(find_agent_pids "$id")" if kill -0 "$pid" 2>/dev/null; then
if [[ -n "$survivors" ]]; then warn "Launcher no respondió a SIGTERM, enviando SIGKILL..."
warn "$id no respondió a SIGTERM, enviando SIGKILL..." kill -9 "$pid" 2>/dev/null || true
for p in $survivors; do
kill -9 "$p" 2>/dev/null || true
done
fi fi
rm -f "$(pid_file "$id")" rm -f "$(launcher_pid_file)"
ok "$id detenido ($instance_count instance(s) stopped)" ok "Launcher detenido"
((stopped++)) || true
done < <(list_agents_raw)
[[ "$stopped" -eq 0 && -z "$TARGET" ]] && dim "Ningún agente estaba corriendo."
[[ -n "$TARGET" && "$stopped" -eq 0 ]] && fail "Agente '$TARGET' no encontrado o no estaba corriendo."
true