feat(frontend): supervisor presence indicator on agent call card

- useAgentState hook returns { state, supervisorPresence }
- SSE events: supervisor-whisper → "Supervisor coaching" (blue badge)
  supervisor-barge → "Supervisor on call" (brand badge)
  supervisor-left → badge disappears
- Listen mode is silent — no badge shown
- Updated call sites: sidebar.tsx, agent-status-toggle.tsx destructure

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-12 16:16:31 +05:30
parent 42d1a03f9d
commit ee9da619c1
4 changed files with 34 additions and 5 deletions

View File

@@ -2,11 +2,13 @@ import { useState, useEffect, useRef } from 'react';
import { notify } from '@/lib/toast';
export type OzonetelState = 'ready' | 'break' | 'training' | 'calling' | 'in-call' | 'acw' | 'offline';
export type SupervisorPresence = 'none' | 'whisper' | 'barge';
const API_URL = import.meta.env.VITE_API_URL ?? 'http://localhost:4100';
export const useAgentState = (agentId: string | null): OzonetelState => {
export const useAgentState = (agentId: string | null): { state: OzonetelState; supervisorPresence: SupervisorPresence } => {
const [state, setState] = useState<OzonetelState>('offline');
const [supervisorPresence, setSupervisorPresence] = useState<SupervisorPresence>('none');
const prevStateRef = useRef<OzonetelState>('offline');
const esRef = useRef<EventSource | null>(null);
@@ -56,6 +58,20 @@ export const useAgentState = (agentId: string | null): OzonetelState => {
return;
}
// Supervisor presence events — don't replace agent state
if (data.state === 'supervisor-whisper') {
setSupervisorPresence('whisper');
return;
}
if (data.state === 'supervisor-barge') {
setSupervisorPresence('barge');
return;
}
if (data.state === 'supervisor-left') {
setSupervisorPresence('none');
return;
}
prevStateRef.current = data.state;
setState(data.state);
} catch {
@@ -74,5 +90,5 @@ export const useAgentState = (agentId: string | null): OzonetelState => {
};
}, [agentId]);
return state;
return { state, supervisorPresence };
};