feat(agent): add learn action flow and grounding guards

This commit is contained in:
Dom
2026-06-02 16:24:10 +02:00
parent 86b3c8f7e7
commit d38f0b0f2f
39 changed files with 5901 additions and 212 deletions

View File

@@ -371,7 +371,13 @@ class SmartTrayV1:
)
if name and name.strip():
name = name.strip()
# Utiliser l'etat partage si disponible
# --- P1-LEA-SHADOW : d\u00e9clencher d'abord l'orchestrateur L\u00e9a Linux ---
# On contacte agent-chat AVANT la capture locale. Si \u00e9chec,
# bascule en mode d\u00e9grad\u00e9 (capture locale sans assistance).
self._start_lea_orchestrator_session(name)
# --- Comportement historique pr\u00e9serv\u00e9 : capture locale ---
if self._shared_state is not None:
try:
self._shared_state.start_recording(name)
@@ -393,6 +399,55 @@ class SmartTrayV1:
threading.Thread(target=_dialog, daemon=True).start()
def _start_lea_orchestrator_session(self, session_name: str) -> None:
"""Appelle POST /api/learn/start côté agent-chat Linux (P1-LEA-SHADOW).
Fail-safe : toute erreur (config absente, httpx manquant, timeout,
5xx serveur...) bascule en mode dégradé sans bloquer la capture
locale. L'utilisateur est informé via le NotificationManager.
"""
try:
from ..config import AGENT_CHAT_URL, API_TOKEN, MACHINE_ID
from ..network.lea_orchestrator_client import (
LeaOrchestratorError,
start_learning_session,
)
except Exception as exc: # pragma: no cover (import-time)
logger.error("Impossible de charger le client orchestrateur Léa : %s", exc)
self._notifier.notify(
"Léa",
"Serveur injoignable — apprentissage local uniquement.",
)
return
try:
resp = start_learning_session(
AGENT_CHAT_URL,
machine_id=MACHINE_ID,
session_name=session_name,
api_token=API_TOKEN,
trigger_source="tray_button",
)
except LeaOrchestratorError as exc:
logger.error("Orchestrateur Léa injoignable : %s", exc)
self._notifier.notify(
"Léa",
"Serveur injoignable — apprentissage local uniquement.",
)
return
except Exception: # noqa: BLE001 — défensif
logger.exception("Erreur inattendue orchestrateur Léa")
self._notifier.notify(
"Léa",
"Erreur orchestrateur — apprentissage local uniquement.",
)
return
logger.info(
"Session orchestrateur Léa OK : id=%s state=%s",
resp.session_id, resp.state,
)
def _on_stop_session(self, _icon=None, _item=None) -> None:
"""Termine la session en cours et envoie les donnees."""
count = self.actions_count