- Add apps/ directory with modular components: - captain.py: Main orchestrator - corp/, deck/, devops/, docker/, hst/: Domain-specific apps - Fix duplicate logger handlers in long sessions - Add flush=True to print statements for real-time output Note: flow-ui, mindlink, tzzr-cli are separate repos (not included) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
166 lines
5.2 KiB
Python
166 lines
5.2 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
CAPTAIN CLAUDE - CLI Unificado para el Sistema TZZR
|
|
Punto de entrada principal para todas las apps
|
|
"""
|
|
import sys
|
|
import os
|
|
import subprocess
|
|
|
|
APPS_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
|
|
APPS = {
|
|
"devops": {
|
|
"path": f"{APPS_DIR}/devops/app.py",
|
|
"desc": "Gestión de despliegues y construcción",
|
|
"alias": ["deploy", "build"]
|
|
},
|
|
"deck": {
|
|
"path": f"{APPS_DIR}/deck/app.py",
|
|
"desc": "Servidor DECK (72.62.1.113) - Agentes, Mail, Apps",
|
|
"alias": ["d"]
|
|
},
|
|
"corp": {
|
|
"path": f"{APPS_DIR}/corp/app.py",
|
|
"desc": "Servidor CORP (92.112.181.188) - Margaret, Jared, Mason, Feldman",
|
|
"alias": ["c"]
|
|
},
|
|
"hst": {
|
|
"path": f"{APPS_DIR}/hst/app.py",
|
|
"desc": "Servidor HST (72.62.2.84) - Directus, Imágenes",
|
|
"alias": ["h"]
|
|
},
|
|
"docker": {
|
|
"path": f"{APPS_DIR}/docker/app.py",
|
|
"desc": "Gestión Docker multi-servidor",
|
|
"alias": ["dk"]
|
|
}
|
|
}
|
|
|
|
def print_banner():
|
|
print("""
|
|
╔═══════════════════════════════════════════════════════════════╗
|
|
║ CAPTAIN CLAUDE ║
|
|
║ Sistema Multiagente TZZR ║
|
|
╠═══════════════════════════════════════════════════════════════╣
|
|
║ Servidor Central: 69.62.126.110 (Gitea, PostgreSQL) ║
|
|
║ DECK: 72.62.1.113 │ CORP: 92.112.181.188 ║
|
|
║ HST: 72.62.2.84 │ R2: Cloudflare Storage ║
|
|
╚═══════════════════════════════════════════════════════════════╝
|
|
""")
|
|
|
|
def print_help():
|
|
print_banner()
|
|
print("Uso: python captain.py <app> [comando] [argumentos]\n")
|
|
print("Apps disponibles:")
|
|
print("─" * 60)
|
|
|
|
for name, info in APPS.items():
|
|
aliases = ", ".join(info["alias"]) if info["alias"] else ""
|
|
alias_str = f" (alias: {aliases})" if aliases else ""
|
|
print(f" {name}{alias_str}")
|
|
print(f" └─ {info['desc']}")
|
|
print()
|
|
|
|
print("Ejemplos:")
|
|
print(" python captain.py devops deploy clara deck")
|
|
print(" python captain.py deck agents")
|
|
print(" python captain.py corp pending")
|
|
print(" python captain.py docker ps all")
|
|
print(" python captain.py hst directus")
|
|
print()
|
|
print("Atajos rápidos:")
|
|
print(" python captain.py d agents # DECK agents")
|
|
print(" python captain.py c flows # CORP flows")
|
|
print(" python captain.py dk dashboard # Docker dashboard")
|
|
|
|
def resolve_app(name: str) -> str:
|
|
"""Resuelve nombre o alias a nombre de app"""
|
|
if name in APPS:
|
|
return name
|
|
|
|
for app_name, info in APPS.items():
|
|
if name in info.get("alias", []):
|
|
return app_name
|
|
|
|
return None
|
|
|
|
def run_app(app: str, args: list):
|
|
"""Ejecuta una app con los argumentos dados"""
|
|
app_name = resolve_app(app)
|
|
|
|
if not app_name:
|
|
print(f"❌ App no encontrada: {app}")
|
|
print(f" Apps disponibles: {', '.join(APPS.keys())}")
|
|
return 1
|
|
|
|
app_path = APPS[app_name]["path"]
|
|
|
|
if not os.path.exists(app_path):
|
|
print(f"❌ Archivo no encontrado: {app_path}")
|
|
return 1
|
|
|
|
cmd = ["python3", app_path] + args
|
|
|
|
try:
|
|
result = subprocess.run(cmd)
|
|
return result.returncode
|
|
except KeyboardInterrupt:
|
|
print("\n⚠️ Interrumpido")
|
|
return 130
|
|
except Exception as e:
|
|
print(f"❌ Error: {e}")
|
|
return 1
|
|
|
|
def quick_status():
|
|
"""Muestra estado rápido de todos los servidores"""
|
|
print_banner()
|
|
print("📊 Estado rápido del sistema:\n")
|
|
|
|
servers = [
|
|
("DECK", "root@72.62.1.113"),
|
|
("CORP", "root@92.112.181.188"),
|
|
("HST", "root@72.62.2.84")
|
|
]
|
|
|
|
for name, host in servers:
|
|
cmd = f"ssh -i ~/.ssh/tzzr -o ConnectTimeout=3 {host} 'docker ps -q | wc -l' 2>/dev/null"
|
|
try:
|
|
result = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=5)
|
|
if result.returncode == 0:
|
|
count = result.stdout.strip()
|
|
print(f" ✅ {name} ({host.split('@')[1]}): {count} contenedores")
|
|
else:
|
|
print(f" ❌ {name} ({host.split('@')[1]}): No responde")
|
|
except:
|
|
print(f" ❌ {name} ({host.split('@')[1]}): Timeout")
|
|
|
|
print()
|
|
|
|
def main():
|
|
if len(sys.argv) < 2:
|
|
print_help()
|
|
return 0
|
|
|
|
cmd = sys.argv[1]
|
|
|
|
# Comandos especiales
|
|
if cmd in ["-h", "--help", "help"]:
|
|
print_help()
|
|
return 0
|
|
|
|
if cmd in ["status", "s"]:
|
|
quick_status()
|
|
return 0
|
|
|
|
if cmd in ["version", "-v", "--version"]:
|
|
print("Captain Claude v1.0.0")
|
|
return 0
|
|
|
|
# Ejecutar app
|
|
args = sys.argv[2:] if len(sys.argv) > 2 else []
|
|
return run_app(cmd, args)
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|