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.
114 lines
4.1 KiB
Bash
Executable file
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."
|