#!/usr/bin/env bash
# La configuracion de Hermes, PARSEADA.
#
# Esta prueba existe por un fallo concreto que casi cuela. El config.yaml que
# genera el instalador declara `provider` y `base_url` DOS VECES dentro del
# bloque model:, una arriba y otra ~45 lineas mas abajo. En YAML gana la ultima.
# Al configurar Ollama en las de arriba el fichero PARECIA correcto leyendolo, y
# al parsearlo salia provider=auto, base_url=https://openrouter.ai/api/v1: el
# carril habria salido por OpenRouter creyendo nosotros que iba a localhost.
#
# Con 1890 lineas y 121 activas, leer el fichero no demuestra nada. Aqui todo se
# comprueba con yaml.safe_load, que es lo mismo que hace Hermes al arrancar.

cd "$(dirname "$0")" && . ./comun.sh

titulo "El cerebro"

afirma "existe $CONFIG" test -f "$CONFIG"

comprueba "el modelo por defecto es el verde" "$(config_model default)" "$MODELO"

# Sin esto Hermes se cree lo que dice /api/show, que son 262144 —el maximo del
# modelo— y no los 24576 configurados. El sintoma serian respuestas truncadas y
# llamadas rotas, y la conclusion natural ("el 4B no vale") seria falsa.
CTX_YAML=$(config_model context_length)
CTX_REAL=$(parametro "$MODELO" num_ctx)
comprueba "Hermes sabe el contexto REAL, no el que reporta /api/show" \
    "$CTX_YAML" "$CTX_REAL"

# Los dos numeros tienen que ser iguales Y llegar al suelo de 64k. Poner aqui
# 65536 con el modelo a 24576 pasaria el arranque y romperia en marcha: Hermes
# no comprimiria hasta acercarse a 64k y ollama iria tirando los tokens mas
# viejos, que son el prompt de sistema y los esquemas de las herramientas. El
# agente dejaria de llamar herramientas a mitad de sesion, sin un solo error.
mayor_que "y ese contexto llega al suelo de Hermes" "${CTX_YAML:-0}" 63999

BASE=$(config_model base_url)
case "$BASE" in
    http://127.0.0.1:*|http://localhost:*)
        echo "  $(verde OK) el cerebro apunta a esta maquina ($BASE)"; _ok=$((_ok + 1)) ;;
    *)
        echo "  $(rojo FALLO) base_url NO es local: $BASE"; _fallo=$((_fallo + 1)) ;;
esac

titulo "Cero nube"

# Se recorre el YAML entero, no solo el bloque model:. Cualquier http(s) que no
# apunte al propio equipo es una salida potencial y tiene que estar justificada.
FUERA=$(python3 - "$CONFIG" <<'PY'
import re, sys, yaml

LOCAL = re.compile(r'^https?://(127\.0\.0\.1|localhost|0\.0\.0\.0|\[::1\])')
URL   = re.compile(r'https?://[^\s"\']+')
fuera = []

def anda(nodo, ruta=""):
    if isinstance(nodo, dict):
        for k, v in nodo.items():
            anda(v, f"{ruta}.{k}" if ruta else str(k))
    elif isinstance(nodo, list):
        for i, v in enumerate(nodo):
            anda(v, f"{ruta}[{i}]")
    elif isinstance(nodo, str):
        for u in URL.findall(nodo):
            if not LOCAL.match(u):
                fuera.append(f"{ruta} = {u}")

anda(yaml.safe_load(open(sys.argv[1])))
for f in fuera:
    print(f)
PY
)
if [ -z "$FUERA" ]; then
    echo "  $(verde OK) ninguna URL de nube activa en el config"; _ok=$((_ok + 1))
else
    echo "  $(rojo FALLO) hay URLs que salen de esta maquina:"
    printf '%s\n' "$FUERA" | sed 's/^/        /'
    _fallo=$((_fallo + 1))
fi

titulo "Desde donde mira el agente"

# `cwd: "."` de fabrica NO es "el directorio desde el que lanzas hermes", por
# mucho que lo diga su documentacion: el agente arranca en $HOME. Con la raiz
# ahi, "lee verde/README.md" acaba leyendo $HOME/README.md —el de
# Gitleaks— y resumiendolo perfectamente. Ningun error, respuesta inutil.
CWD_AGENTE=$(python3 -c "
import yaml
print(yaml.safe_load(open('$CONFIG')).get('terminal', {}).get('cwd', ''))" 2>/dev/null)
comprueba "el agente arranca en la raiz del proyecto" "$CWD_AGENTE" "$RAIZ"

titulo "El lanzador entra donde debe"

# Un `cd` antes de llamar a hermes NO basta: Hermes restaura el directorio que
# tenga apuntado en la sesion. El sintoma no parece de rutas — se le pide "lee
# verde/README.md y resumelo" y devuelve un resumen impecable de OTRO fichero,
# sin un solo error — asi que se comprueba estaticamente.
if grep -q -- '--in "\$RAIZ"' "$VERDE/verde-launcher.sh"; then
    echo "  $(verde OK) verde-launcher.sh pasa --in y no confia en el cd"; _ok=$((_ok + 1))
else
    echo "  $(rojo FALLO) verde-launcher.sh no pasa --in: Hermes abrira en otro sitio"
    _fallo=$((_fallo + 1))
fi

titulo "La voz apunta a la del naranja"

# Sin esto la comparacion de voz entre carriles no diria nada: Hermes se
# descargaria su propia voz de Piper (la GPL de OHF-Voice) en vez de usar el
# binario MIT y el .onnx que ya tiene el naranja.
ORDEN=$(python3 -c "
import yaml
t = yaml.safe_load(open('$CONFIG')).get('tts', {})
p = t.get('providers', {}).get(t.get('provider', ''), {})
print(p.get('command', ''))
" 2>/dev/null)
case "$ORDEN" in
    */verde/voz-verde.sh*)
        echo "  $(verde OK) TTS por comando -> voz-verde.sh"; _ok=$((_ok + 1)) ;;
    *)
        echo "  $(rojo FALLO) el TTS no apunta al adaptador: $ORDEN"; _fallo=$((_fallo + 1)) ;;
esac

stt_local() {   # $1 = clave dentro de stt.local
    python3 -c "
import yaml
print(yaml.safe_load(open('$CONFIG')).get('stt', {}).get('local', {}).get('$1', ''))
" 2>/dev/null | tr -d '\n'
}

comprueba "la escucha es la local de Hermes" "$(stt_local model)" "small"

# 839 MiB de pico contra una tarjeta con 3301 MiB de modelo dentro: whisper
# tiene que soltar la VRAM cuando calla, o la siguiente frase da OOM.
menor_que "whisper suelta la VRAM tras callar (s)" "$(stt_local unload_after_idle_seconds)" 601

resumen
