JARVIS/config/recorrido.sh
sito 8e4bc8ad94 JARVIS: asistente de voz local para Linux
Nucleo propio: oye con whisper.cpp, piensa con un modelo de Ollama, habla
con Piper, y hace RAG sobre los apuntes del usuario. 100% local, sin
cuentas ni claves.

Escrito bajo una restriccion dura, 4 GB de VRAM: el cerebro y whisper
comparten tarjeta y solo caben porque estan dimensionados para ello. El
RAG usa embeddings estaticos con busqueda hibrida; la voz clonada se sirve
de una cache de frases.

Incluye instalador (install.sh), requisitos, y documentacion del stack,
del manejo de root y de las acciones. Los apuntes indexados y el diario NO
se incluyen: son privados y el .gitignore los bloquea.
2026-08-16 15:34:37 +02:00

114 lines
4.1 KiB
Bash
Executable file

#!/usr/bin/env bash
# Recorre el catalogo grupo por grupo, en voz alta y a ritmo de mirar.
#
# Distinto de demo_en_directo.sh: aquel probaba once acciones sueltas; este
# recorre TODOS los grupos con una muestra representativa de cada uno, anuncia
# el grupo antes de entrar, y deja pausas para que se pueda seguir en pantalla.
#
# Lo destructivo y lo que pide root no se ejecuta: en uso normal eso pasa por
# un dialogo que aprueba una persona.
#
# ./recorrido.sh todo, con voz
# ./recorrido.sh --mudo sin voz
# ./recorrido.sh sistema solo un grupo
set -uo pipefail
RAIZ=$(cd -P "$(dirname "${BASH_SOURCE[0]:-$0}")/.." && pwd)
CATALOGO=$RAIZ/newelle/data/acciones/acciones.json
MUDO=no; SOLO=""
for a in "$@"; do
case "$a" in --mudo) MUDO=si;; *) SOLO=$a;; esac
done
WAV=$(mktemp --suffix=.wav); trap 'rm -f "$WAV"' EXIT
dice() {
[ "$MUDO" = si ] && { sleep 0.4; return 0; }
"$RAIZ/config/jarvis-voz.sh" "$WAV" "$1" >/dev/null 2>&1
# < /dev/null: si no, se comen la entrada del bucle que los llama
[ -s "$WAV" ] && { paplay "$WAV" </dev/null 2>/dev/null || aplay -q "$WAV" </dev/null 2>/dev/null; }
}
campo() { python3 -c "
import json,sys
d=json.load(open('$CATALOGO',encoding='utf-8'))
for a in d.get('acciones', d if isinstance(d,list) else []):
if a['id']==sys.argv[1]: print(a.get(sys.argv[2],'') or ''); break
" "$1" "$2"; }
# grupo|id|frase que se diria|argumento
RECORRIDO='
sistema|disco_libre|cuanto espacio queda|
sistema|memoria|cuanta memoria|
sistema|temperatura|que temperatura hay|
sistema|uptime|cuanto lleva encendido|
sistema|procesos_top|que esta consumiendo|
sistema|red_ip|cual es mi ip|
sistema|red_wifi|a que wifi estoy conectado|
sistema|gpu_procesos|que usa la grafica|
sistema|pantallas|cuantas pantallas hay|
sistema|captura_pantalla|hazme una captura|
sistema|terminal_abrir|abre una terminal|
sistema|videos_listar|que peliculas tengo|
ficheros|buscar_fichero|busca el fichero README|README.md
ficheros|grep_recursivo|busca la palabra JARVIS|JARVIS
ficheros|tamano_carpeta|cuanto ocupa la carpeta config|'"$RAIZ"'/config
ficheros|descargas_listar|que hay en descargas|
oasis|oasis_corriendo|esta oasis funcionando|
oasis|oasis_conexiones|cuantos pubs hay conectados|
pentest|mis_puertos|que puertos tengo abiertos yo|
ventanas|ventanas_listar|que ventanas tengo abiertas|
ventanas|ventana_izquierda|pon la ventana a la izquierda|
ventanas|ventana_derecha|manda la ventana a la derecha|
ventanas|ventana_centrar|centra la ventana activa|
ventanas|ventana_maximizar|maximiza la ventana activa|
ventanas|ventana_restaurar|restaura la ventana activa|
ventanas|ventana_a_pantalla|manda la ventana a la pantalla uno|uno
'
grupo_actual=""
n=0
while IFS='|' read -r -u 3 grupo id frase argumento; do
[ -z "${grupo:-}" ] && continue
[ -n "$SOLO" ] && [ "$SOLO" != "$grupo" ] && continue
if [ "$grupo" != "$grupo_actual" ]; then
grupo_actual=$grupo
printf '\n\n\033[1m ══ grupo: %s ══\033[0m\n' "$grupo"
dice "Grupo $grupo, señor."
sleep 0.6
fi
comando=$(campo "$id" comando)
[ -z "$comando" ] && { printf ' (%s no existe en el catalogo)\n' "$id"; continue; }
acuse=$(campo "$id" acuse)
plantilla=$(campo "$id" respuesta)
n=$((n+1))
printf '\n %2d. tu: "%s"\n' "$n" "$frase"
printf ' jarvis: %s\n' "$acuse"
dice "$acuse"
real=${comando//\{argumento\}/$(printf '%q' "${argumento:-}")}
salida=$(timeout 40 bash -lc "$real" </dev/null 2>&1 | head -6)
if [ -n "$salida" ]; then
echo "$salida" | sed 's/^/ /' | cut -c1-104
else
printf ' (hecho, sin salida)\n'
fi
# decir la respuesta si la plantilla se puede resolver
if [ -n "$plantilla" ] && [ -n "$salida" ]; then
ultima=$(echo "$salida" | tail -1); primera=$(echo "$salida" | head -1)
lineas=$(echo "$salida" | wc -l)
h=${plantilla//\{ultima\}/$ultima}; h=${h//\{primera\}/$primera}
h=${h//\{lineas\}/$lineas}; h=${h//\{salida\}/$salida}
case "$h" in
*"{"*) ;;
*) [ ${#h} -lt 170 ] && { printf ' jarvis: %s\n' "$h"; dice "$h"; };;
esac
fi
sleep 1.5
done 3<<< "$RECORRIDO"
printf '\n\n ── %d acciones mostradas ──\n' "$n"
dice "Recorrido terminado, señor."