Le serveur compagnon /vr (Node/TS, PostgreSQL puwapi_vr) orchestre trois choses :
la gestion des salons pilotée par le hub, le reporting des sessions, et
l'assistant IA temps réel de la simulation.
Cycle de vie d'un salon¶
Le hub est l'autorité ; les casques sont exécutants.
- L'admin crée un salon dans le hub (
/vr) : nom, simulation, capacité, mode, participants affectés. - Il l'ouvre (
POST /rooms/:id/open). Un salon fermé n'est visible d'aucun casque. - Côté casque, la tablette liste les salons ouverts affectés à l'utilisateur
(
GET /runtime/rooms). Le premier arrivé héberge (POST /rooms/:id/host, Netcode for GameObjects en hôte local/LAN) → une session démarre. - Chaque participant signale sa présence (
POST /rooms/:id/heartbeat, ~20 s : nom affiché, étape courante, hôte ou non) — c'est ce qui alimente l'onglet En direct du hub (TTL 60 s). POST /rooms/:id/leave: le départ de l'hôte clôt la session.
Sessions & télémétrie¶
Chaque run est historisé (vr_sessions). L'app Unity miroir son bus interne
SimulationEvents vers POST /sessions/:id/telemetry
({events:[{userId?, type, label, detail}]}) : étapes franchies, objets saisis, etc.
Les rapports du hub (GET /reports/overview, /reports/sessions) en dérivent taux de
complétion, durée et progression par participant.
Assistant IA (WebSocket /assistant)¶
L'assistant est conscient de la scène : chaque message du casque embarque un snapshot JSON du contexte (objets, étape en cours, derniers événements).
Casque → serveur :
{ "type": "user_message", "text": "Que dois-je faire ?", "context": { … } }
{ "type": "event", "name": "step_changed", "detail": "Poser la roue", "context": { … } }
Serveur → casque :
{ "type": "delta", "text": "Prends la " }
{ "type": "message", "text": "Prends la roue…" }
{ "type": "action", "name": "highlight_object", "args": "{\"objectName\":\"Roue\"}" }
L'IA peut agir dans la scène via des outils (highlight_object, show_hint) — côté
Unity, AssistantActions traduit chaque action. Pour donner un nouveau pouvoir à l'IA :
un outil côté serveur + un case dans AssistantActions.
L'inférence passe par la couche IA de Puwapi (surface interne, X-Internal-Secret) —
voir Référence — Formation VR. Sans clé configurée, l'annuaire de salons fonctionne mais
l'assistant est désactivé.
Sécurité & temps réel¶
- Toutes les routes REST (hors
/health) et le WebSocket exigent un JWT Identity Hub (Authorization: Bearerou?token=pour le WS) + le modulevrà l'abonnement. - Le tenant vient toujours du token, jamais du corps : salons, sessions et rapports sont isolés par organisation.
- Ouverture/fermeture de salon, arrivées/départs et débuts/fins de session notifient le hub en temps réel (Convex, best-effort) — sinon le hub retombe sur du polling.
La liste complète des routes est dans la Référence — Formation VR.