@@ -38,6 +38,17 @@ export default function UserPhoneInterface({
3838 const [ isEnding , setIsEnding ] = useState ( false ) ;
3939 const [ connectionError , setConnectionError ] = useState < string | null > ( null ) ;
4040
41+ // ─── ON-SCREEN DEBUG LOG ───────────────────────────────────────────────────
42+ const [ debugLogs , setDebugLogs ] = useState < string [ ] > ( [ ] ) ;
43+ const [ showDebug , setShowDebug ] = useState ( false ) ;
44+ const addLog = useCallback ( ( msg : string ) => {
45+ const ts = new Date ( ) . toTimeString ( ) . slice ( 0 , 8 ) ;
46+ const line = `[${ ts } ] ${ msg } ` ;
47+ console . log ( '📞 [DIAG]' , line ) ;
48+ setDebugLogs ( prev => [ ...prev . slice ( - 49 ) , line ] ) ; // keep last 50
49+ } , [ ] ) ;
50+ // ──────────────────────────────────────────────────────────────────────────
51+
4152 const timerRef = useRef < NodeJS . Timeout | null > ( null ) ;
4253
4354 // Tracks when the WebSocket connected so we can log the live-to-dead delta.
@@ -54,26 +65,23 @@ export default function UserPhoneInterface({
5465 // re-initialising on every render, which can reset the active WebSocket.
5566 const onConnect = useCallback ( ( ) => {
5667 connectTimeRef . current = Date . now ( ) ;
57- console . log ( '📞 [DIAG] ElevenLabs connected at' , new Date ( ) . toISOString ( ) ) ;
68+ addLog ( '✅ CONNECTED' ) ;
5869 setConnectionError ( null ) ;
5970 setAgentStatus ( 'listening' ) ;
60- } , [ ] ) ;
71+ } , [ addLog ] ) ;
6172
6273 const onDisconnect = useCallback ( ( details ?: DisconnectionDetails ) => {
6374 const uptime = connectTimeRef . current !== null
6475 ? Date . now ( ) - connectTimeRef . current
6576 : null ;
6677 connectTimeRef . current = null ;
6778
68- // ─── DIAGNOSTIC: log every field so we can identify the root cause ───
69- console . log ( '📞 [DIAG] ElevenLabs disconnected' , {
70- reason : details ?. reason ?? '(none)' ,
71- message : ( details as { message ?: string } ) ?. message ,
72- closeCode : ( details as { closeCode ?: number } ) ?. closeCode ,
73- closeReason : ( details as { closeReason ?: string } ) ?. closeReason ,
74- uptimeMs : uptime ,
75- timestamp : new Date ( ) . toISOString ( ) ,
76- } ) ;
79+ const reason = details ?. reason ?? '(none)' ;
80+ const closeCode = ( details as { closeCode ?: number } ) ?. closeCode ?? '' ;
81+ const closeReason = ( details as { closeReason ?: string } ) ?. closeReason ?? '' ;
82+ const errMsg = ( details as { message ?: string } ) ?. message ?? '' ;
83+
84+ addLog ( `❌ DISCONNECTED reason=${ reason } uptimeMs=${ uptime ?? '?' } closeCode=${ closeCode } closeReason="${ closeReason } " errMsg="${ errMsg } "` ) ;
7785
7886 setAgentStatus ( 'idle' ) ;
7987
@@ -82,10 +90,10 @@ export default function UserPhoneInterface({
8290 if ( details ?. reason !== 'user' ) {
8391 endCall ( ) ;
8492 }
85- } , [ endCall ] ) ;
93+ } , [ endCall , addLog ] ) ;
8694
8795 const onMessage = useCallback ( ( message : { source : string ; message : string } ) => {
88- console . log ( `📞 [ ${ message . source } ]: ${ message . message } `) ;
96+ addLog ( `💬 ${ message . source . toUpperCase ( ) } : " ${ message . message } " `) ;
8997 if ( message . source === 'user' ) {
9098 setCurrentTranscript ( message . message ) ;
9199 addMessage ( 'user' , message . message ) ;
@@ -96,28 +104,24 @@ export default function UserPhoneInterface({
96104 addMessage ( 'agent' , message . message ) ;
97105 onTranscript ?.( message . message , 'agent' ) ;
98106 }
99- } , [ addMessage , onTranscript ] ) ;
107+ } , [ addMessage , onTranscript , addLog ] ) ;
100108
101109 const onError = useCallback ( ( message : string , context ?: unknown ) => {
102- // ─── DIAGNOSTIC: log message AND the context object (closeCode, etc.) ───
103- console . error ( '📞 [DIAG] ElevenLabs error:' , message , context ) ;
104- try {
105- console . error ( '📞 [DIAG] ElevenLabs error context (JSON):' , JSON . stringify ( context , null , 2 ) ) ;
106- } catch {
107- // context may not be serialisable (e.g. native Event)
108- }
110+ let ctxStr = '' ;
111+ try { ctxStr = JSON . stringify ( context ) ; } catch { ctxStr = String ( context ) ; }
112+ addLog ( `🔴 ERROR: "${ message } " ctx=${ ctxStr } ` ) ;
109113 setConnectionError ( message ?? 'Connection error' ) ;
110- } , [ ] ) ;
114+ } , [ addLog ] ) ;
111115
112116 const onModeChange = useCallback ( ( modeEvent : { mode : string } ) => {
113- console . log ( '📞 [DIAG] Mode change →' , modeEvent . mode , 'at' , new Date ( ) . toISOString ( ) ) ;
117+ addLog ( `🔄 MODE → ${ modeEvent . mode } ` ) ;
114118 if ( modeEvent . mode === 'speaking' ) {
115119 setAgentStatus ( 'speaking' ) ;
116120 setCurrentTranscript ( '' ) ;
117121 } else if ( modeEvent . mode === 'listening' ) {
118122 setAgentStatus ( 'listening' ) ;
119123 }
120- } , [ ] ) ;
124+ } , [ addLog ] ) ;
121125
122126 // ElevenLabs Conversational AI — handles STT + LLM + TTS in one WebSocket
123127 const conversation = useConversation ( {
@@ -189,16 +193,19 @@ export default function UserPhoneInterface({
189193 }
190194
191195 startCall ( 'voice' ) ;
196+ addLog ( '🟡 Fetching signed URL…' ) ;
192197
193198 try {
194199 const signedUrl = await getSignedUrl ( ) ;
200+ addLog ( `🟡 Got signed URL, starting session…` ) ;
195201 await conversation . startSession ( { signedUrl } ) ;
196202 } catch ( error ) {
197- console . error ( '📞 Failed to start ElevenLabs session:' , error ) ;
198- setConnectionError ( error instanceof Error ? error . message : 'Failed to connect' ) ;
203+ const msg = error instanceof Error ? error . message : String ( error ) ;
204+ addLog ( `🔴 startSession failed: ${ msg } ` ) ;
205+ setConnectionError ( msg || 'Failed to connect' ) ;
199206 setAgentStatus ( 'idle' ) ;
200207 }
201- } , [ startCall , getSignedUrl , conversation ] ) ;
208+ } , [ startCall , getSignedUrl , conversation , addLog ] ) ;
202209
203210 const handleEndCall = useCallback ( async ( ) => {
204211 console . log ( '🔴 End call button pressed' ) ;
@@ -395,6 +402,26 @@ export default function UserPhoneInterface({
395402 </ div >
396403 </ div >
397404
405+ { /* ── On-screen debug log ── */ }
406+ < div className = "absolute top-4 right-4 z-30 text-left" >
407+ < button
408+ onClick = { ( ) => setShowDebug ( v => ! v ) }
409+ className = "text-[10px] font-mono px-2 py-1 rounded bg-white/10 text-white/50 hover:bg-white/20"
410+ >
411+ { showDebug ? 'hide log' : 'show log' }
412+ </ button >
413+ { showDebug && (
414+ < div className = "mt-1 w-80 max-h-52 overflow-y-auto rounded-xl bg-black/80 border border-white/10 p-2" >
415+ { debugLogs . length === 0
416+ ? < p className = "text-white/30 text-[10px] font-mono" > No events yet.</ p >
417+ : debugLogs . map ( ( l , i ) => (
418+ < p key = { i } className = "text-[10px] font-mono text-white/70 leading-relaxed break-all" > { l } </ p >
419+ ) )
420+ }
421+ </ div >
422+ ) }
423+ </ div >
424+
398425 { /* Bottom Controls */ }
399426 < div className = "p-8 pb-[max(2rem,env(safe-area-inset-bottom))] w-full z-20 bg-gradient-to-t from-black via-black/80 to-transparent" >
400427 < div className = "flex items-center justify-center gap-6 max-w-lg mx-auto" >
@@ -455,6 +482,26 @@ export default function UserPhoneInterface({
455482 </ div >
456483 ) }
457484
485+ { /* ── On-screen debug log ── */ }
486+ < div className = "absolute top-4 right-4 z-30 text-left" >
487+ < button
488+ onClick = { ( ) => setShowDebug ( v => ! v ) }
489+ className = "text-[10px] font-mono px-2 py-1 rounded bg-white/10 text-white/50 hover:bg-white/20"
490+ >
491+ { showDebug ? 'hide log' : 'show log' }
492+ </ button >
493+ { showDebug && (
494+ < div className = "mt-1 w-80 max-h-52 overflow-y-auto rounded-xl bg-black/80 border border-white/10 p-2" >
495+ { debugLogs . length === 0
496+ ? < p className = "text-white/30 text-[10px] font-mono" > No events yet.</ p >
497+ : debugLogs . map ( ( l , i ) => (
498+ < p key = { i } className = "text-[10px] font-mono text-white/70 leading-relaxed break-all" > { l } </ p >
499+ ) )
500+ }
501+ </ div >
502+ ) }
503+ </ div >
504+
458505 { /* Main Content Area */ }
459506 < div className = "flex-1 flex flex-col items-center justify-center relative px-6 z-10 w-full max-w-[92vw] sm:max-w-lg mx-auto" >
460507 { /* Avatar */ }
0 commit comments