openskynet / docs /history /TUI_DAEMON_INTEGRATION_COMPLETE.md
Darochin's picture
Mirror OpenSkyNet workspace snapshot from Git HEAD
fc93158 verified

TUI ↔️ DAEMON INTEGRATION - COMPLETADO

✅ CAMBIOS REALIZADOS

1. src/tui/tui.ts (Integración)

Imports agregados:

import {
  createInteractionLock,
  releaseInteractionLock,
  refreshInteractionLock,
} from "../omega/daemon-cooperative.js";

Variables de estado (línea ~380):

const workspaceRoot = process.cwd();
let cancelLockRefresh: (() => Promise<void>) | null = null;

Al conectar con gateway (línea ~550):

// Create interaction lock for daemon coordination
try {
  cancelLockRefresh = await refreshInteractionLock(workspaceRoot, 10_000);
} catch (error) {
  console.warn("[TUI] Warning: Failed to create interaction lock:", error);
}

Función requestExit modificada (ahora async):

const requestExit = async () => {
  if (exitRequested) {
    return;
  }
  exitRequested = true;
  client.stop();
  stopTuiSafely(() => tui.stop());

  // Release daemon interaction lock
  if (cancelLockRefresh) {
    try {
      await cancelLockRefresh();
    } catch (error) {
      console.warn("[TUI] Warning: Failed to release interaction lock:", error);
    }
  }

  process.exitCode = 0;
};

Cambios en handlers de eventos → void requestExit():

  • Línea ~942: if (decision.action === "exit")void requestExit()
  • Línea ~952: editor.onCtrlDvoid requestExit()
  • Línea ~1031: sigtermHandlervoid requestExit()

(Usamos void para ejecutar async sin bloquear el handler síncrono)


FLUJO COMPLETO (TUI ↔️ DAEMON)

Usuario abre: pnpm openskynet tui
    ↓
runTui() se ejecuta
    ↓
[TUI] → refreshInteractionLock(cwd, 10_000)
  ├─ Crea .interaction-lock
  ├─ Configura intervalo cada 10s para actualizar timestamp
  └─ Retorna función cancelLockRefresh()
    ↓
[DAEMON] → Detecta .interaction-lock existente
  ├─ <60s viejo = TUI activa
  ├─ Pausa ciclos
  └─ Verifica cada 10s si lock desapareció
    ↓
Usuario cierra TUI (Ctrl+C, Ctrl+D, o kill signal)
    ↓
requestExit() se llama
  ├─ Detiene cliente
  ├─ Detiene TUI
  ├─ Llama await cancelLockRefresh()
  │  ├─ Limpia intervalo de actualización
  │  └─ Borra .interaction-lock
  └─ Establece process.exitCode = 0
    ↓
[DAEMON] → Detecta .interaction-lock desapareció
  ├─ Espera un ciclo completo
  └─ Reanuda ciclos normales (cada 5 min)

ARCHIVOS INVOLUCRADOS

Archivo Cambios
src/tui/tui.ts ✅ Integración lock create/release/refresh
src/omega/daemon-cooperative.ts ✅ Ya exporta las funciones necesarias
src/omega/heartbeat.ts ✅ Ya ejecuta runOneHeartbeatCycle()
src/omega/daemon-cli.ts ✅ CLI para manejar el daemon
.interaction-lock 🔒 Archivo temporal (creado/borrado por TUI)

VERIFICACIÓN DE IMPORTS (Sin Ciclos)

Circular dependency check:

tui.ts
  ↓ imports
daemon-cooperative.ts
  ↓ imports
fs, path (node builtins only)

No hay ciclo. tui.ts importa daemon-cooperative.ts, pero daemon-cooperative.ts NO importa nada de TUI.


PRÓXIMOS PASOS

1️⃣ Compilar y Verificar Sintaxis

# Compila TypeScript sin errores
pnpm tsc --noEmit

# Verifica que no hay imports circulares
pnpm knip

2️⃣ Test Manual (Escenario A: Sin TUI)

# Terminal 1: Inicia daemon
pnpm tsx src/omega/daemon-cli.ts install
pnpm tsx src/omega/daemon-cli.ts start

# Verifica logs (Linux)
journalctl -u openclaw-openskynet-autonomous -f

# Verifica que .interaction-lock NO existe
ls -la .interaction-lock  # → No such file

Esperado:

  • Daemon ejecuta ciclos cada 5 min ✅
  • Logs: [DAEMON] 🤖 Ciclo #1 - Daemon activo

3️⃣ Test Manual (Escenario B: TUI Abierta)

# Terminal 1: Daemon corriendo (ve paso anterior)

# Terminal 2: Abre TUI
pnpm openskynet tui

# Terminal 3: Verifica lock creado
watch 'ls -la .interaction-lock'  # → Archivo existe, timestamp actualizado cada 10s

Esperado:

  • .interaction-lock existe y se actualiza cada 10s ✅
  • Daemon logs muestran: [DAEMON] 🧑 Interacción detectada. Pausa...
  • Daemon NO ejecuta ciclos mientras TUI está abierta ✅

4️⃣ Test Manual (Escenario C: TUI Cierra)

# Continúa desde paso anterior

# Terminal 2: Presiona Ctrl+C en TUI
# → TUI cierra

# Terminal 3: Verifica lock
watch 'ls -la .interaction-lock'  # → Desaparece inmediatamente

Esperado:

  • .interaction-lock desaparece cuando TUI cierra ✅
  • Daemon logs: Dentro de 10s ve lock desapareció ✅
  • Daemon reanuda ciclos cada 5 min ✅

5️⃣ Test Manual (Escenario D: Timeout - TUI Crash)

# Terminal 1 & 2: Daemon + TUI (como antes)

# Terminal 3: Mata TUI abruptamente
pkill -9 -f "openskynet tui"

# Verifica lock
watch 'ls -la .interaction-lock'  # → Queda viejo (>60s), luego desaparece

Esperado:

  • .interaction-lock permanece ~60s ✅
  • Daemon detecta >60s viejo → borra automáticamente ✅
  • Daemon continúa sin bloquear ✅

REGRESIÓN TESTING

Asegurar que cambios no rompen TUI normal:

# TUI sin daemon (debería funcionar como antes)
# Cierra daemon primero
pnpm tsx src/omega/daemon-cli.ts stop

# TUI debería funcionar igual
pnpm openskynet tui

# Verifica que NO hay archivo .interaction-lock
ls .interaction-lock  # → ERROR (no existe) ✅

Esperado:

  • TUI abre normalmente ✅
  • TUI funciona exactamente igual que antes ✅
  • No hay errores de lock ✅

COMPORTAMIENTO EN CASOS BORDE

Caso Comportamiento
Lock creation falla TUI abre, daemon continúa (no bloqueado)
Lock release falla TUI cierra normalmente, daemon verifica en 60s
Daemon no existe TUI abre, funciona normal (lock se ignora)
TUI abierta x2 Segundo intento actualiza lock (idempotente)
Lock >60s viejo Daemon lo borra automáticamente
Network timeout Cada componente es independiente

OBSERVABILIDAD

Logs esperados

TUI abre:

[TUI] ✅ Lock creado - Daemon pausado

Daemon pausa (ve lock):

[DAEMON] 🧑 Interacción detectada. Pausa (recheck en 10s)...

TUI cierra:

[TUI] 🔓 Lock liberado - Daemon reanuda

Daemon reanuda:

[DAEMON] 🤖 Ciclo #N - Daemon activo
[DAEMON] ✓ Ciclo N completado

Archivos/Timestamps

# Ver lock en tiempo real
watch 'stat .interaction-lock 2>/dev/null | grep Modify'

# Ver edad del lock
watch 'date; [ -f .interaction-lock ] && echo "Lock age: $(($(date +%s) - $(stat -c %Y .interaction-lock))) s"'

CHECKLIST FINAL

  • Compilar sin errores: pnpm tsc --noEmit
  • Sin imports circulares: pnpm knip
  • Test A (Sin TUI): Daemon ejecuta ciclos
  • Test B (TUI abierta): Daemon pausa, lock existe
  • Test C (TUI cierra): Lock desaparece, daemon reanuda
  • Test D (TUI crash): Timeout graceful, daemon continúa
  • Regresión: TUI sin daemon funciona igual
  • Logs legibles y sin spam

ESTADO ACTUAL

PRONTO PARA TESTING

  • TUI integración: COMPLETADA
  • Daemon cooperativo: COMPLETADA
  • Documentación: COMPLETADA
  • Siguientes: Platform testing + User validation