Files
2026-10-03 17:13:39 +02:00

54 lines
1.6 KiB
Python

# -*- coding: utf-8 -*-
"""aviso.py — Aviso por voz local (RF-14, RF-15).
Emite un aviso sonoro local (reutiliza `scripts/aviso_sonoro.py` del repo de negocio)
solo cuando el resumen del ciclo contiene elementos que requieren atencion, o cuando
la IA fallo (RF-13). Nunca envia nada fuera del equipo (Regla 5).
El runner es inyectable para poder testear sin reproducir audio.
"""
from __future__ import annotations
import subprocess
import sys
from typing import Callable
from . import config
import infra_paths
def _script_aviso():
"""Ruta del script de aviso sonoro (repo de negocio)."""
return infra_paths.biblioteca_repo() / "scripts" / "aviso_sonoro.py"
def _runner_default(tipo: str) -> None:
"""Reproduce el aviso sonoro lanzando el script en un subproceso."""
subprocess.run([sys.executable, str(_script_aviso()), tipo], check=False)
def avisar(resumen: dict, cfg: dict | None = None, _runner: Callable[[str], None] | None = None) -> bool:
"""Emite el aviso por voz si procede. Devuelve True si aviso.
- Si `aviso.voz` esta desactivado en config -> no hace nada.
- Avisa si `fallo_ia` o si hay elementos en `requiere_atencion`.
"""
cfg = cfg or config.cargar()
if not cfg.get("aviso", {}).get("voz", True):
return False
fallo_ia = bool(resumen.get("fallo_ia"))
atencion = bool(resumen.get("requiere_atencion"))
if not (fallo_ia or atencion):
return False
tipo = "fin" if atencion else "error"
runner = _runner or _runner_default
try:
runner(tipo)
except Exception:
pass
return True