#!/usr/bin/env bash # JARVIS verde — el banco de pruebas con Hermes Agent. # # verde-launcher.sh abre el TUI de Hermes en verde fosforo # verde-launcher.sh --status que corre y cuanta VRAM, sin arrancar nada # verde-launcher.sh --stop cerrar y soltar la VRAM # verde-launcher.sh --sin-color igual pero sin tocar la paleta # # ── El verde no es decoracion ────────────────────────────────────────────── # # Hay tres JARVIS en esta maquina y se distinguen por color, como ya hacia el # README: cian el de Newelle (congelado), naranja el nucleo (en desarrollo), # verde este. Cuando tienes dos terminales abiertos a las tres de la manana, # el color es lo unico que te dice cual estas tocando. # # Hermes NO tiene tema para su TUI — mirado en hermes_cli/config_defaults.py, # la unica clave "theme" que existe es la del panel web. Asi que el color lo # pone la terminal, con secuencias OSC: # # OSC 10 primer plano OSC 11 fondo OSC 12 cursor # # Se hace asi y no editando tu perfil de terminal a proposito: esto pinta SOLO # esta ventana y solo mientras dura la sesion. Tu perfil por defecto y el del # naranja se quedan como estan. Al salir se restaura con OSC 110/111/112. set -uo pipefail AQUI=$(cd -P "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd) RAIZ=$(cd -P "$AQUI/.." && pwd) # Fosforo verde. Los mismos tonos que jarvis-verde.svg, para que el icono y la # pantalla sean el mismo color. VERDE=${JARVIS_VERDE_TINTA:-#00ff41} FONDO=${JARVIS_VERDE_FONDO:-#04120a} HERMES=${HERMES_BIN:-$HOME/.local/bin/hermes} OLLAMA_URL=${OLLAMA_URL:-http://127.0.0.1:11434} # ── la paleta ────────────────────────────────────────────────────────────── pinta_verde() { [ -t 1 ] || return 0 # sin terminal, nada que pintar printf '\033]10;%s\007' "$VERDE" printf '\033]11;%s\007' "$FONDO" printf '\033]12;%s\007' "$VERDE" } restaura() { [ -t 1 ] || return 0 printf '\033]110\007\033]111\007\033]112\007' } # ── comprobaciones que no arrancan nada ──────────────────────────────────── estado() { printf 'JARVIS verde\n\n' printf ' hermes ' if [ -x "$HERMES" ]; then printf 'instalado en %s\n' "$HERMES" else printf 'NO instalado\n'; fi printf ' ollama ' if curl -fsS --max-time 2 "$OLLAMA_URL/api/tags" >/dev/null 2>&1; then printf 'en pie (%s)\n' "$OLLAMA_URL" else printf 'NO responde en %s\n' "$OLLAMA_URL" fi printf ' modelo ' # El modelo se LEE de la configuracion, no se escribe aqui. El lanzador del # naranja llevaba el nombre a mano y se quedo desfasado: precargaba # qwen3.5:4b mientras la app usaba qwen3.5:4b-jarvis, o sea 2941 MiB del que # no era, ollama tenia que descargar y recargar, y de paso dejaba la tarjeta # sin sitio para whisper. Aqui pasaria igual: este fichero decia # qwen3.5:4b-jarvis y el carril va con qwen3.5:4b-verde. MODELO=$(python3 -c " import yaml print(yaml.safe_load(open('$HOME/.hermes/config.yaml'))['model'].get('default','')) " 2>/dev/null) if [ -z "$MODELO" ]; then printf 'no pude leer model.default de ~/.hermes/config.yaml\n' elif curl -fsS --max-time 2 "$OLLAMA_URL/api/tags" 2>/dev/null \ | grep -q "$MODELO"; then printf '%s disponible\n' "$MODELO" else printf '%s NO esta (lo crea verde/arrancar.sh)\n' "$MODELO" fi printf ' voz ' if [ -x "$AQUI/voz-verde.sh" ] && [ -x "$RAIZ/config/jarvis-piper.sh" ]; then printf 'jarvis-piper.sh, la misma que el naranja\n' else printf 'falta el adaptador o jarvis-piper.sh\n' fi printf ' VRAM ' if command -v nvidia-smi >/dev/null 2>&1; then nvidia-smi --query-gpu=memory.used,memory.total --format=csv,noheader else printf '(sin nvidia-smi)\n' fi } parar() { # El gateway solo existe si algun dia se configura un canal de mensajeria. if [ -x "$HERMES" ]; then "$HERMES" gateway stop 2>/dev/null || true; fi pkill -f 'hermes' 2>/dev/null || true printf 'parado. La VRAM la suelta ollama solo cuando el modelo caduca.\n' } # ── main ─────────────────────────────────────────────────────────────────── COLOR=si case "${1:-}" in --status|--estado) estado; exit 0 ;; --stop|--parar) parar; exit 0 ;; --sin-color) COLOR=no; shift ;; esac if [ ! -x "$HERMES" ]; then printf 'No encuentro hermes en %s\n' "$HERMES" >&2 printf 'Instalalo con: %s/instalar.sh\n' "$AQUI" >&2 exit 1 fi # El cerebro es local: si ollama no esta en pie, Hermes no tiene con que # pensar. Se avisa antes en vez de dejar que falle en la primera frase. if ! curl -fsS --max-time 2 "$OLLAMA_URL/api/tags" >/dev/null 2>&1; then printf 'Aviso: ollama no responde en %s.\n' "$OLLAMA_URL" >&2 printf 'El cerebro del verde es local; arrancalo con: systemctl start ollama\n' >&2 fi if [ "$COLOR" = si ]; then pinta_verde trap restaura EXIT INT TERM fi # ── El cd NO basta: hay que decirselo a Hermes ───────────────────────────── # # Este `cd` estaba solo, y no servia de nada. Hermes RESTAURA el directorio de # trabajo que tenga apuntado en la sesion y se salta aquel desde el que lo # lanzas. El sintoma no parece un fallo de rutas: se le pide "lee # verde/README.md y resumelo" y contesta un resumen impecable de OTRO fichero # —$HOME/README.md, que resulta ser el de Gitleaks— sin un solo error por # ningun lado. Parece el modelo alucinando y es el directorio. # # --in DIR entra en el directorio Y se salta la restauracion; es la bandera que # existe justo para esto. El cd se queda porque las comprobaciones de arriba y # los ficheros de contexto (AGENTS.md, cwd files) se leen antes. cd "$RAIZ" exec "$HERMES" --in "$RAIZ" "$@"