feat(dashboard): launch supervised competence tests

This commit is contained in:
Dom
2026-06-01 12:09:09 +02:00
parent 1a58a0d1f1
commit 335d576830
4 changed files with 476 additions and 3 deletions

View File

@@ -2515,6 +2515,151 @@ def dashboard_promote_competence(competence_id):
}), status
def _dashboard_streaming_json_request(
method: str,
path: str,
*,
payload: dict | None = None,
timeout: int = 10,
):
"""Proxy JSON minimal vers le streaming server, avec Bearer token."""
import urllib.error
import urllib.request
base_url = os.environ.get('RPA_STREAMING_URL', 'http://localhost:5005').rstrip('/')
url = f"{base_url}{path}"
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
token = os.environ.get('RPA_API_TOKEN', '')
if token:
headers['Authorization'] = f'Bearer {token}'
data_bytes = None
if payload is not None:
data_bytes = json.dumps(payload).encode('utf-8')
try:
req = urllib.request.Request(url, data=data_bytes, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=timeout) as response:
raw = response.read().decode('utf-8')
try:
data = json.loads(raw) if raw else {}
except json.JSONDecodeError:
data = {'raw': raw}
return jsonify(data), response.status
except urllib.error.HTTPError as exc:
raw = exc.read().decode('utf-8')
try:
detail = json.loads(raw) if raw else {'error': str(exc)}
except json.JSONDecodeError:
detail = {'error': raw or str(exc)}
return jsonify(detail), exc.code
except urllib.error.URLError as exc:
return jsonify({
'success': False,
'error': f'Serveur streaming (5005) inaccessible : {exc}',
'hint': 'Vérifiez que le service streaming est démarré et que lagent Windows est connecté.',
}), 502
@app.route('/api/v1/lea/competences/<competence_id>/replay', methods=['POST'])
def dashboard_replay_competence(competence_id):
"""Start a supervised competence replay through the dashboard."""
from urllib.parse import quote
payload = request.get_json(silent=True) or {}
replay_payload = {
'supervised': bool(payload.get('supervised', True)),
'start_replay': bool(payload.get('start_replay', True)),
'session_id': str(payload.get('session_id') or ''),
}
machine_id = str(payload.get('machine_id') or '').strip()
if machine_id:
replay_payload['machine_id'] = machine_id
encoded_id = quote(competence_id, safe='')
return _dashboard_streaming_json_request(
'POST',
f'/api/v1/lea/competences/{encoded_id}/replay',
payload=replay_payload,
timeout=30,
)
@app.route('/api/v1/lea/replays/<replay_id>', methods=['GET'])
def dashboard_replay_status(replay_id):
"""Return replay status from the streaming server."""
from urllib.parse import quote
encoded_id = quote(replay_id, safe='')
return _dashboard_streaming_json_request(
'GET',
f'/api/v1/traces/stream/replay/{encoded_id}',
timeout=5,
)
@app.route('/api/v1/lea/replays/<replay_id>/resume', methods=['POST'])
def dashboard_resume_replay(replay_id):
"""Resume a supervised replay from the dashboard modal."""
from urllib.parse import quote
payload = request.get_json(silent=True) or {}
encoded_id = quote(replay_id, safe='')
return _dashboard_streaming_json_request(
'POST',
f'/api/v1/traces/stream/replay/{encoded_id}/resume',
payload={
'acknowledged_check_ids': payload.get('acknowledged_check_ids') or [],
},
timeout=10,
)
@app.route('/api/v1/lea/competences/<competence_id>/verdict', methods=['POST'])
def dashboard_submit_competence_verdict(competence_id):
"""Persist a supervised competence verdict from the dashboard."""
try:
from core.competences.verdicts import (
CompetenceVerdictError,
store_competence_verdict,
)
payload = request.get_json(silent=True) or {}
verdict = store_competence_verdict(competence_id, payload)
except KeyError:
return jsonify({
'success': False,
'error': f"Competence '{competence_id}' introuvable",
'write_back_enabled': False,
'yaml_write': False,
}), 404
except CompetenceVerdictError as exc:
return jsonify({
'success': False,
'error': str(exc),
'write_back_enabled': False,
'yaml_write': False,
}), 400
except Exception as exc:
return jsonify({
'success': False,
'error': str(exc),
'write_back_enabled': False,
'yaml_write': False,
}), 500
return jsonify({
'success': True,
'competence_id': competence_id,
'verdict': verdict,
'duplicate': verdict['duplicate'],
'write_back_enabled': False,
'yaml_write': False,
}), 200 if verdict['duplicate'] else 201
def _kb_faiss_stats() -> dict:
"""Statistiques de l'index FAISS."""
faiss_index_path = DATA_PATH / "faiss_index" / "main.index"