+
    iυ                        ^ RI t ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	H
t
 ^ RIHt ^ RIHtHt ^ RIt^ RItR R lt]! 4        ^ RIt^ RIH t ^ RIt^ RIHt ^ RIHtHt ^ R	IHt ^ R
IHt ^ RI H!t" ^RI#H$t$ ^RI%H&t& ^RI'H(t(H)t)H*t* ^RI+H,t,H-t-H.t.H/t/H0t0H1t1H2t2H3t3 ]Ph                  ! R4      t5]$! 4        ]&! 4       t6]7! ]Pp                  ! RR4      4      t9]Pp                  ! RR4      t:]Pp                  ! RR4      t;]6Py                  R4      ;'       g    RP{                  RR4      t>]6R,          t?]6Py                  R4      ;'       g    Rt@]6R,          tA]6Py                  R4      ;'       g    RtB]6R ,          tC]6R!,          tD]6R",          tE]6R#,          tF]6R$,          tG]
 ! R% R&4      4       tH ! R' R(4      tIR) tJR* tK]LR+8X  d   ] P                  ! ]K! 4       4       R# R# ),    N)	dataclass)deque)AnyOptionalc                    V ^8  d   QhRR/#    returnN )formats   "[E:\live-kit-agent\livekit_voicebot\backend\agent_runtime\src\mcube_integration\ws_bridge.py__annotate__r      s     #$ #$ #$    c                     Rp V \         P                  9   d   R#  ! R R4      p\        P                  ! V 4      pVP                  P                  RR.RV/4       V\         P                  V &   R# )ag  
LiveKit Agents currently imports `livekit.agents.tokenize.blingfire`, which loads a native
extension (`lk_blingfire`). On some Windows setups (WDAC / App Control) that extension is blocked
and the entire `livekit.agents` import fails.

The MCube WS bridge doesn't depend on blingfire, so we provide a minimal stub module to keep
`livekit.agents` importable.
z!livekit.agents.tokenize.blingfireNc                   v   a  ] tR t^t o R^R^
RR/V 3R lR lltRR/V 3R	 lR
 lltRR/V 3R lR lltRtV tR# ):_install_livekit_blingfire_stub.<locals>.SentenceTokenizermin_sentence_lenstream_context_lenretain_formatFc                0   < V ^8  d   QhRS[ RS[ RS[RR/# )r	   r   r   r   r
   N)intbool)r   __classdict__s   "r   r   G_install_livekit_blingfire_stub.<locals>.SentenceTokenizer.__annotate__    s5     	6 	6 "	6 !$		6
  	6 	6r   c               F    \        V4      V n        \        V4      V n        R # N)r   _min_sentence_lenr   _retain_format)selfr   r   r   s   &$$$r   __init__C_install_livekit_blingfire_stub.<locals>.SentenceTokenizer.__init__    s     &))9%:D""&}"5Dr   languageNc                J   < V ^8  d   QhRS[ RS[ R,          RS[S[ ,          /# )r	   textr"   Nr
   )strlist)r   r   s   "r   r   r   *   s/     	J 	J 	J3: 	Jc 	Jr   c                  \         P                  ! R T;'       g    R4       Uu. uF*  q3P                  4       '       g   K  VP                  4       NK,  	  ppV Uu. uF!  p\        V4      V P                  8  g   K  VNK#  	  up# u upi u upi )z(?<=[.!?])\s+ )resplitstriplenr   )r   r$   r"   ppartss   &&$  r   tokenizeC_install_livekit_blingfire_stub.<locals>.SentenceTokenizer.tokenize*   sl    (*1A4::2(N\(N1RYRYR[YQWWY(NE\$Iu!A$2H2H(HAAuII ]Is   B BB	;B	c                .   < V ^8  d   QhRS[ R,          /# )r	   r"   Nr%   )r   r   s   "r   r   r   /   s     	\ 	\cDj 	\r   c                   \        R 4      h)z2Streaming tokenizer not supported in fallback stub)NotImplementedError)r   r"   s   &$r   streamA_install_livekit_blingfire_stub.<locals>.SentenceTokenizer.stream/   s    %&Z[[r   )r   r   )	__name__
__module____qualname____firstlineno__r    r/   r5   __static_attributes____classdictcell__r   s   @r   SentenceTokenizerr      s[     	6 %'	6 ')		6
 #(	6 	6	J 	J 	J
	\4 	\ 	\ 	\r   r>   __all__)sysmodulestypes
ModuleType__dict__update)module_namer>   stubs      r   _install_livekit_blingfire_stubrH      se     6Kckk!\ \& K(DMM)&9%:<OQbcd#CKKr   )SpeechEventType)cartesia
elevenlabs)rtc)StreamAdapter)VAD)load_agent_runtime_dotenv)get_default_mcube_call_config)MCUBE_AUDIO_SPECfrom_base64_strpcm16_to_mulaw)AI_UTTERANCES_QUEUERABBITMQ_URLcontrol_queue_namedeclare_durable_queueconnectget_channelpublish_jsontts_queue_namezmcube.ws_bridgeMCUBE_WS_BRIDGE_PORT9001MCUBE_WS_BRIDGE_HOSTz0.0.0.0	REDIS_URLzredis://localhost:6379/0system_promptr(   z\n
	llm_modelllm_provider	tts_modeltts_providerrK   tts_voice_idtts_encodingstt_language_codestt_model_idstt_providerc                   ,   a  ] tR t^ft o V 3R ltRtV tR# )PendingPlayc                T   < V ^8  d   Qh/ S[ ;R&   S[P                  R,          ;R&   # )r	   nameNfuture)r%   asyncioFuture)r   r   s   "r   r   PendingPlay.__annotate__f   s%     
I  NN4   r   r   N)r7   r8   r9   r:   __annotate_func__r;   r<   r=   s   @r   rl   rl   f   s      r   rl   c                   2  a  ] tR t^lt o V 3R lR ltR tR tR tV 3R lR ltV 3R lR	 lt	V 3R
 lR lt
V 3R lR ltV 3R lR ltR tV 3R lR ltRR/V 3R lR lltR tV 3R lR ltRR/V 3R lR lltV 3R lR ltV 3R lR  ltR! tR" tR#tV tR# )$McubeCallSessionc                T   < V ^8  d   QhRS[ RS[P                  RS[P                  /# )r	   call_id	websocketredis_client)r%   
websocketsWebSocketServerProtocolredis_asyncRedis)r   r   s   "r   r   McubeCallSession.__annotate__m   s<     V- V- V- 55	V- "''V-r   c                   Wn         W n        W0n        W@n        R V n        R V n        R V n        RV n        RV n        / V n	        \        P                  ! 4       V n        RV n        R V n        \        V n        \"        V n        \&        V n        \*        P-                  R4      ;'       g    RP/                  4       V n        RV n        \4        V n        \8        V n        \<        V n        \@        V n!        \D        V n#        \H        V n%        \L        V n'         \Q        ^\S        R\U        \W        \*        P-                  RR4      4      4      4      4      V n,         \W        \*        P-                  RR4      4      V n.         \W        \*        P-                  R
R4      4      V n/         \Q        ^ \U        \W        \*        P-                  RR4      4      4      4      V n0        R V n1        R V n2        R V n3        R V n4        R V n5        R V n6        R V n7        R V n8        \        Pr                  ! 4       V n:        R V n;        R V n<        R V n=        R V n>        R V n?        R V n@        \        4       V nB        RV nC        V P                  ^,          V nD        \        P                  ! 4       V nF        R #   \Z         d    ^T n,         EL]i ; i  \Z         d    R	T n.         ELQi ; i  \Z         d    RT n/         ELEi ; i  \Z         d    ^
T n0         EL&i ; i)NFfirst_messager(     tts_chunk_ms200tts_gainz0.35gffffff?playback_pace_factorz1.0g      ?checkpoint_every10i@  )Grw   wsrabbit_channelry   	stream_idactive_sequence_idcancelled_sequence_idbot_playingresponse_pendingpending_playsrp   Queuetts_segments_tts_done_received_tts_final_chunk_seqSYSTEM_PROMPTr`   	LLM_MODELrb   LLM_PROVIDERrc   
_MCUBE_DEFgetr+   r   _first_message_sentSTT_PROVIDERrj   STT_LANGUAGE_CODErh   STT_MODEL_IDri   TTS_PROVIDERre   	TTS_MODELrd   TTS_VOICE_IDrf   TTS_ENCODINGrg   maxminr   floatr   	Exceptionr   r   r   business_idbot_idagent_iduser_idagent_email
agent_namestt
stt_streamEvent_stt_ready_event	_stt_task_ws_reader_task_playback_task_tts_consumer_task_control_consumer_task_resample_state	bytearray_pcm16_16k_buffer_frame_16k_samples_frame_16k_bytesLock_sequence_lock)r   rw   rx   r   ry   s   &$$$$r   r    McubeCallSession.__init__m   s    ,((, 2648"  % 68 DK==?(-37! +"(#->>/#B#H#Hb"O"O"Q). (!2(("((	$ #As3E*..Y^:_4`0a'b cD	!!*..V"DEDM	,(-jnn=SUZ.[(\D%	'$'3uZ^^DVX\5]/^+_$`D!
 +/%)'+&**.)- #' '7;=A<@@DDH#  $!*"% $ 7 7! ;%llnQ  	$ #D	$  	! DM	!  	,(+D%	,  	'$&D!	'sI   AJ $J5 :$K 7K' J21J25K
KK$#K$'K=<K=c                  "   \         P                  ! V P                  4       R R7      V n        \         P                  ! V P	                  4       RR7      V n        \         P                  ! V P                  4       RR7      V n        \         P                  ! V P                  4       RR7      V n	        V P                  4       G Rj  xL
  R#  L5i)zmcube.stt_events)rn   zmcube.playback_loopzmcube.tts_consumerzmcube.control_consumerN)rp   create_task_consume_stt_eventsr   _playback_loopr   _consume_tts_queuer   _consume_control_queuer   _ws_reader_loop)r   s   &r   startMcubeCallSession.start   s      ,,T-E-E-GN`a%11$2E2E2GNcd #*"5"5d6M6M6OVj"k '.&9&9'')0H'
#
 ""$$$s   C CC	Cc           	       "    V P                     R j  xL
  p \        P                  ! V4      p TP                  R4      ;R8X  d    T P                  T4      G R j  xL
  KU  ;R8X  d    T P                  T4      G R j  xL
  Kx  ;R8X  d    T P                  T4      G R j  xL
  K  R8X  d    M K  T P                  4       G R j  xL
  R #  L  \         d%    \        P                  RT P                  4        K  i ; i L L Lc  \         d6    \        P                  RT P                  TP                  R4      4        EK9  i ; iED8L L  T P                  4       G R j  xL 
  i ; i5i)Nz$ws non-json frame ignored call_id=%seventr   mediaplayedStreamstopz,ws event handling failed call_id=%s event=%s)r   jsonloadsr   logwarningrw   r   	_on_start	_on_media_on_played_stream	exception_cleanup)r   rawmsgs   &  r   r    McubeCallSession._ws_reader_loop   s-    	"!WW r rc**S/C
r'''*$"&.."555$"&.."555+"&"8"8"===#! 
 --/!!1r ! KK FU 65= ! rMM"PRVR^R^`c`g`gho`pqqr) %0 "$--/!!s   E0E ECEE C,D
DD
#E %D
DD
E D
$D%D
)E +D
1E 3D
4E 6E0	E
E0E+D=E  DE D
D
D

;E
E 	E

E E0E-&E)'E--E0c                  "    V P                   '       dF   V P                  P                  \        P                  ! R RRV P                   /4      4      G Rj  xL
  \        T P                  P                  4       4       F?  pTP                  P                  4       '       d   K%  TP                  P                  4        KA  	  T P                  P                  4         T P                  e   T P                  P                  4         \        T RR4      e#   T P                   P#                  4       G Rj  xL
  T P$                  T P&                  T P(                  T P*                  3 F5  pT'       g   K  TP                  4       '       d   K%  TP                  4        K7  	  R#  ELI  \
         d     ELUi ; i  \
         d     Li ; i L  \
         d     Li ; i5i)r   	terminatestreamIdN_http_session)r   r   sendr   dumpsr   r&   r   valuesro   donecancelclearr   	end_inputgetattrr   closer   r   r   r   )r   ppts   &  r   r   McubeCallSession._cleanup   sh    	~~~ggll4::wZQUQ_Q_.`#abbb t))0023B99>>##		  " 4 	  "	*))+
	t_d3?((..000
 --t/F/FX\XkXklAq
 m1 c 		  		 1 		s   GAF" FF" AG#8G(F4 ,G 1G2G 66G1G	GF" "F1-G0F11G4G?GGGG GGGGc                    < V ^8  d   QhRS[ /# r	   r   dict)r   r   s   "r   r   r~     s     O O4 Or   c                  "   VR ,          R,          V n         VR ,          R,          P                  R4      p\        VR ,          R,          P                  R\        P                  4      4      pV\        P
                  8w  g   V\        P                  8w  d#   \        P                  RV P                  VV4       \        P                  RV P                  V P                   4       V P                  4       G Rj  xL
  V P                  4       G Rj  xL
  V P                  '       dC   V P                  '       g/   RV n        V P                  R	V P                  R
7      G Rj  xL
  R# R# R#  Lr L\ L5i)r   r   mediaFormatencoding
sampleRatezLMCube audio format mismatch call_id=%s encoding=%s sr=%s (expected mulaw@8k)z#mcube start call_id=%s stream_id=%sNTr(   )bot_say_text)r   r   r   rQ   sample_rater   r   r   rw   info_load_call_config	_init_sttr   r   _publish_utterance)r   r   r   r   s   &&  r   r   McubeCallSession._on_start  s!    Wj1w<.22:>#g,}599,HXHdHdef'000KCSC_C_4_KK^	 	6dnnU$$&&&nn d&>&>&>'+D$))"4;M;M)NNN '?	 	'
 OsB   C6E18E+9E1E-E1'E19'E1 E/!E1-E1/E1c                   < V ^8  d   QhRR/# r   r   )r   r   s   "r   r   r~   (  s     77 77 77r   c           
        "    V P                   P                  RV P                   24      G Rj  xL
 pV'       g   R# \        V\        \
        34      '       d   VP                  RRR7      pM\        V4      p\        P                  ! V4      pTP                  RT P                  4      T n        TP                  R4      ;'       g    T P                  ;'       g    R	P                  4       T n        TP                  R
T P                   4      T n        TP                  RT P"                  4      ;'       g    R	T n        TP                  RT P$                  4      ;'       g    T P$                  T n        TP                  RT P&                  4      ;'       g    T P&                  T n        TP                  RT P(                  4      ;'       g    T P(                  T n        TP                  RT P*                  4      ;'       g    T P*                  T n        TP                  RT P,                  4      ;'       g    T P,                  T n        TP                  RT P.                  4      ;'       g    T P.                  T n        TP                  RT P0                  4      ;'       g    T P0                  T n        RRR 3RRR 3RRR 3RRR 33 F=  w  rEpTP                  T4      f   K   \3        YT! TP                  T4      4      4       K?  	  RpT F5  w  rTP                  T4      f   K  \3        YTP                  T4      4       K7  	  R#  EL  \         d%    \        P                  RT P                  4        R# i ; i  \         d     K  i ; i5i)z
Load per-call config from Redis (written by the /api/mcube/outbound-call endpoint).
If not present, fall back to env defaults.
zmcube_call_config:Nutf-8replace)errorsz+failed to load mcube call config call_id=%sr`   r   r(   rb   rc   rj   rh   ri   re   rd   rf   rg   r   c                 R    \        ^\        R\        \        V 4      4      4      4      # )   r   )r   r   r   r   xs   &r   <lambda>4McubeCallSession._load_call_config.<locals>.<lambda>I  s    s1c#s5QR8}>U7Vr   r   c                     \        V 4      # r   r   r   s   &r   r   r   J  s    uQxr   r   c                     \        V 4      # r   r  r   s   &r   r   r   K  s    uQxr   r   c                 >    \        ^ \        \        V 4      4      4      # )r   )r   r   r   r   s   &r   r   r   L  s    s1c%PQ(m?Tr   ))r   r   )r   r   )r   r   )r   r   )r   r   )emailr   )r   r   )ry   r   rw   
isinstancebytesr   decoder%   r   r   r   r   r   r`   r   r+   rb   rc   rj   rh   ri   re   rd   rf   rg   setattr)	r   r   raw_strcfgckattrcasterid_mapjson_keys	   &        r   r   "McubeCallSession._load_call_config(  s    
	))--0B4<<..QRRC#y122**WY*?c(**W%C
 !WW_d6H6HI!ggo6RR$:L:LRRPRYY[dnn=GGND4E4EFLL"GGND4E4EF[[$J[J[!$)<d>T>T!U!o!oY]YoYoGGND4E4EF[[$J[J[GGND4E4EF[[$J[J[dnn=OOGGND4E4EF[[$J[J[GGND4E4EF[[$J[J[ ^-VW%78#%;=OP!35TU	!
Bf wwr{&Dswwr{(;<!

 %NHwwx ,CGGH$56 %_ S  	MMGV	6 ! s   N+M
 MM
 NAM
 8NNAN6*N!4N4N4N 4N54N*4N>N#!M<N&!NM
 
+M95N8M99N<NN
NNc                   < V ^8  d   QhRR/# r   r   )r   r   s   "r   r   r~   a  s     ;$ ;$ ;$r   c           	       "   RV n         \        4       V n        V P                  P	                  4        \
        P                  ! R4      ;'       g!    \
        P                  ! R4      ;'       g    Rp\
        P                  ! R4      ;'       g    Rp\        P                  ! 4       V n	        \        P                  RV P                  V P                  V P                  4       V P                  R8X  d   V'       g   \        P                  R4       M\         P"                  ! V P                  ;'       g    R	V P                  ;'       g    R
RRVV P                  R7      V n        V P$                  P'                  4       V n        V P                  P+                  4        R# \,        P"                  ! V P                  VV P                  R7      p W0n        V P$                  P'                  4       V n        V P                  P+                  4        R#   \.         dL    \0        P2                  ! RRR7      p\5        Y4R7      T n        T P$                  P'                  4       T n         Lqi ; i5i)z4
Initialize STT stream for the configured provider.
NELEVENLABS_API_KEYELEVEN_API_KEYr(   CARTESIA_API_KEYz.mcube stt init provider=%s model_id=%s lang=%srJ   z8CARTESIA_API_KEY not set; falling back to elevenlabs STTzink-whisperen	pcm_s16le>  )modelr"   r   r   api_keyhttp_session)language_coder  r  T)r   	force_cpu)r   vad)r   r   r   r   r   osgetenvaiohttpClientSessionr   r   r   rj   ri   rh   r   rJ   STTr   r5   r   setrK   r4   	SileroVADloadrM   )r   elevenlabs_keycartesia_keybase_sttr  s   &    r   r   McubeCallSession._init_stta  s    
  $!*##%#78]]BIIFV<W]][]yy!34:: %224<""		
 
*VW#<<++<<}!33;;t( %(!%!3!3 #'((//"3%%))+ >>00"++
		0H"hhoo/DO 	!!# # 	0 ..UdCC$;DH"hhoo/DO	0sK   A+I&.I&A+I&:8I&3I&BI&%H 1I&AI# I&"I##I&c                    < V ^8  d   QhRS[ /# r   r   )r   r   s   "r   r   r~     s     (. (.4 (.r   c                  "   V P                   '       g   R # V P                  P                  4       '       g   R # VP                  R4      ;'       g    / pVP                  R4      R8w  d   R # VP                  R4      ;'       g    Rp \	        V4      p\
        P                  ! V^4      p\
        P                  ! T^^RRT P                  4      w  q`n        T P                  P                  T4       \        T P                  4      T P                   8  d   \#        T P                  R T P                    4      pT P                  R T P                   1 \$        P&                  ! TR^T P(                  R	7      pT P*                  f   Q hT P*                  P-                  T4       K  R #   \         d/    \        P                  RT P                  \        T4      4        R # i ; i5i)
Nr   trackinboundpayloadr(   z1invalid media payload ignored call_id=%s bytes=%si@  r  )r   num_channelssamples_per_channel)r   r   is_setr   rR   audioopulaw2linr   r   r   rw   r,   ratecvr   r   extendr   r  rL   
AudioFramer   r   
push_frame)	r   r   r   b64mulaw_bytespcm16_8k	pcm16_16kframe_bytesframes	   &&       r   r   McubeCallSession._on_media  s    ~~~$$++-- &&B99W*ii	"((b	)#.K''Q7H +2..  +
'	' 	%%i0$(()T-B-BB 6 67N9N9N OPK&&'>)>)>'>?NN!$($;$;	E ??...OO&&u- C  	KKKT\\[^_b[cd	s;   4GG2GG"F# *C9G#5GGGGc                    < V ^8  d   QhRS[ /# r   r   )r   r   s   "r   r   r~     s     	/ 	/4 	/r   c                @  "   VP                  R 4      pV'       g   R# V P                  P                  V4      pV'       d\   VP                  P                  4       '       g:   VP                  P	                  R4       V P                  P                  VR4       R# R# R# 5i)rn   N)r   r   ro   r   
set_resultpop)r   r   rn   r   s   &&  r   r   "McubeCallSession._on_played_stream  sp     wwv##D)biinn&&II  &""4. '2s   >BB!=Bc                ,  "   V P                   P                  4       G R j  xL
  V P                  f   Q hV P                    R j  xL
  pVP                  \        P
                  8X  d   V P                  '       dl   VP                  '       d   VP                  ^ ,          MR pV'       d   VP                  MRP                  4       pV'       d   V P                  4       G R j  xL
  K  VP                  \        P                  8X  g   K  VP                  '       d   VP                  ^ ,          MR pV'       d%   V'       d   VP                  MRP                  4       MRpV'       g   EK)  V P                  V4      G R j  xL
  EKE   ELf ELD L LEDJR # 5i)Nr(   )r   waitr   typerI   INTERIM_TRANSCRIPTr   alternativesr$   r+   _barge_in_clearFINAL_TRANSCRIPT_handle_final_transcript)r   evaltpartialr$   s   &    r   r   $McubeCallSession._consume_stt_events  s    ##((****** 	> 	>"ww/<<<###02"//!,TC+.sxxB==?G"22444ww/:::,.OOObooa(<?CR668R4 77===' 	+	> 5 >! (s   FF FFF	F	2F<FF+#FF"F#"F
FF9F#F*F>F?F	FFFFc                    < V ^8  d   QhRS[ /# )r	   r$   r2   )r   r   s   "r   r   r~     s     , ,3 ,r   c                   "   V P                   '       g   V P                  '       d   R # V P                  V4      G R j  xL
  R #  L5ir   )r   r   r   )r   r$   s   &&r   rL  )McubeCallSession._handle_final_transcript  s5     t444 %%d+++s   $AAAAr   Nc                4   < V ^8  d   QhRS[ RS[ R,          /# )r	   r$   r   Nr2   )r   r   s   "r   r   r~     s     4
 4
S 4
3: 4
r   c               j  "   V P                   ;_uu_4       GR j  xL
   V P                  P                  RV P                   24      G R j  xL
 pV P                  P	                  RV P                   2R4      G R j  xL
  R R R 4      GR j  xL
  \        X4      V n        RV n	        RV n
        RV n        R V n        RV P                  R\        V4      RVRV P                  R	V P                  R
V P                  RV P                   RV P"                  RV P$                  RV P&                  RV P(                  /pV'       d   W$R&   R F  p\+        WR 4      pVf   K  WdV&   K  	  \-        V P.                  \0        VR7      G R j  xL
  \2        P5                  RV P                  VVV P                   V P"                  V P$                  V P&                  4       R #  EL EL ELa  \
         d#    \        \        P                  ! 4       4      p ELi ; i EL  + GR j  xL 
 '       g   i     EL; i L5i)Nz
mcube:seq:i  FTrw   sequence_id
transcriptr`   rb   rc   re   rd   rf   rg   r   r   )channel
queue_namer/  zjpublished utterance call_id=%s seq=%s text=%r tts_provider=%s tts_model=%s tts_voice_id=%s tts_encoding=%s)r   r   r   r   r   r   )r   ry   incrrw   expirer   r   timer   r   r   r   r   r`   rb   rc   re   rd   rf   rg   r   r   rZ   r   rT   r   r   )r   r$   r   seqr/  kvs   &&$    r   r   #McubeCallSession._publish_utterance  s    &&&&' --22Z~3NOO''..DLL>/JDQQQ '& #&c(  $"'$(! t||3s8$T//D--D--D--D--D--
 &2N#^A&A}
 _
 ''*
 	
 	

 	xLLNN		
S 'OQ '$))+&'	 '&&&H	
s   H3GH3H+G!G0G!=G>G!H3HC	H3'H3H1AH3G!G!!)H
HHHH3H.	H
H.	&H.	(
H3c                J  "   V P                   '       g3   V P                   '       g!   \        P                  ! R 4      G Rj  xL
  K2  \        V P                  4      pV P
                  P                  VRR7      G Rj  xL
 pVP                  4       ;_uu_4       GRj  xL
 pV  Rj  xL
  pVP                  RR7      ;_uu_4       GRj  xL
  VP                  P                  R4      p \        P                  ! V4      p\        TP                  RR4      4      pT P                   e$   YpP                   8X  d    RRR4      GRj  xL
  K  TP                  R4      R	8X  d   T P"                  e   YpP"                  8w  d    RRR4      GRj  xL
  K  \        TR
,          4      p\%        TR,          4      p	T^ 8X  d,   \&        P)                  RT P                  T\+        T	4      4       T P,                  P/                  YxT	34      G Rj  xL
  MoTP                  R4      R8X  dZ   T P"                  e   YpP"                  8w  d    RRR4      GRj  xL
  EK  RT n        \        TP                  RR4      4      T n        RRR4      GRj  xL
  EK   ELT EL EL EL EL  \         d     RRR4      GRj  xL 
  EK  i ; i EL EL; L L| LD  + GRj  xL 
 '       g   i     EKJ  ; iEDHRRR4      GRj  xL 
  R#   + GRj  xL 
 '       g   i     R# ; i5i)g{Gz?NTdurableFrequeuer   rV  rG  tts_audio_chunk	chunk_seqaudio_pcm_b64z0tts_audio_chunk_first call_id=%s seq=%s bytes=%stts_donefinal_chunk_seq)r   rp   sleepr[   rw   r   declare_queueiteratorprocessbodyr  r   r   r   r   r   r   r   rR   r   r   r,   r   putr   r   )
r   rY  queueq_itermessagedatar/  r]  rg  pcm16_8k_bytess
   &         r   r   #McubeCallSession._consume_tts_queue)  sa    ~~~nnnmmD)))#DLL1
 ))77
D7QQ>>###v!' \ \g"??5?999"<<..w7D!"&**T"2 gkk-<=C11=#IcIcBc  :99 {{6*.??22:cE\E\>\$ :99 %((<$=	)89Q)R$>HH R $ # #N 3	 #//33S^4TUUU V,
:22:cE\E\>\$7 :998 37/47DUWY8Z4[1; :99 *
 R#\9 % !  :99!	 :. V/ :999 "( $#####s  $L#L# J;L#<J= L#JL#!L$K1(J
)K1, LJ LK-J#
:K=LK
	L5KLK

LA6KK:KLK
L'KLK
LL#L#L#K1 L#K.K/L:J=
;LKKL
LKLLK.K
K.%K.'L3L#>L?L#L 	L
L 	L 		L#c                6   < V ^8  d   QhRS[ RS[S[,          /# )r	   r/  r
   )r   r   r%   )r   r   s   "r   r   r~   V  s      D Xc] r   c                   VP                  R4      ;'       gD    VP                  R4      ;'       g+    VP                  R4      ;'       g    VP                  R4      pV'       d   \        V\        4      '       g   R# VP                  4       pV'       g   R# VP	                  4       P                  R4      '       d4    VP                  R^4      ^,          P                  R^4      ^ ,          pV# V#   \         d     R# i ; i)	z
Extract transfer target from tool/control payload.

We accept several keys so different producers (ai_worker variants) stay compatible.
transfer_tophone_numbertransfer_numbersip_uriNzsip::@)r   r  r%   r+   lower
startswithr*   r   )r   r/  rz  s   && r   _extract_transfer_to%McubeCallSession._extract_transfer_toV  s     KK& & &{{>*& &{{,-& & {{9%	 	 *[#">">!'') ))&11)//Q7:@@aHK {  s   =0C1 1D ?D cancelled_seqc                4   < V ^8  d   QhRS[ S[,          RR/# )r	   r  r
   N)r   r   )r   r   s   "r   r   r~   r  s      Xc] d r   c                  Vf   V P                   pWn        RV n        RV n        RV n         RV n        RV n        \        V P                  P                  4       4       FA  w  r#VP                  P                  4       '       d   K'  VP                  P                  4        KC  	  V P                  P                  4          V P                  P                  4        K    \        P                    d     R# i ; i)z
Immediately stop any bot playback and cancel pending playedStream futures.
This is used for MCube `terminate/transfer` and should be more aggressive
than barge-in clear.
NF)r   r   r   r   r   r   r&   r   itemsro   r   r   r   r   
get_nowaitrp   
QueueEmpty)r   r  _r   s   &$  r   _force_stop_playback%McubeCallSession._force_stop_playbackr  s       33M%2"  %"&"'$(! $,,2245EA99>>##		  " 6 	  "	!!,,.!! 		s   =C C32C3c                   < V ^8  d   QhRR/# r   r   )r   r   s   "r   r   r~     s     @ @d @r   c                  "   \        V P                  4      pV P                  P                  VRR7      G Rj  xL
 pVP	                  4       ;_uu_4       GRj  xL
 pV  Rj  xL
  pVP                  RR7      ;_uu_4       GRj  xL
   \        P                  ! VP                  P                  R4      4      pT P                  T4      G Rj  xL
  RRR4      GRj  xL
  K   L L L Le  \         d     RRR4      GRj  xL 
  K  i ; i LA L3  + GRj  xL 
 '       g   i     K  ; iDRRR4      GRj  xL 
  R#   + GRj  xL 
 '       g   i     R# ; i5i)zU
Consume per-call control queue and execute MCube call actions (terminate/transfer).
Trb  NFrd  r   )rV   rw   r   rm  rn  ro  r   r   rp  r  r   _handle_control_message)r   rY  rr  rs  rt  r/  s   &     r   r   'McubeCallSession._consume_control_queue  s     (5
))77
D7QQ>>###v!' @ @g"??5?999!"&**W\\-@-@-I"J 66w??? :99	 R#@9 % ! 	 :99! @ :999 "( $#####s  6E%C( E%C*E%E D4$C,
%D4( EC.	ED/C0
=DDDE!D
"E(E%*E%,D4.E0D;D<ED

EDDED1D 
D1)D1+
E5E% EE%E"	E
E"	E"		E%c                $   < V ^8  d   QhRS[ RR/# )r	   r/  r
   Nr   )r   r   s   "r   r   r~     s     " "T "d "r   c                4  "   VP                  R 4      pVP                  R4      p\        V\        \        34      '       d+   \        V4      P	                  4       '       d   \        V4      MRpVe!   V P
                  e   W@P
                  8w  d   R# VR8X  dl   V P                  '       dF   V P                  P                  \        P                  ! RRRV P                  /4      4      G Rj  xL
  V P                  VR7       R# VR8X  d   V P                  V4      pV'       d\   V P                  '       dJ   V P                  P                  \        P                  ! RR	RV P                  R
VRR/4      4      G Rj  xL
  V P                  VR7       R# R#  L L5i)rG  rV  Nmcube_terminater   r   r   )r  mcube_transfertransfer
transferToshowOriginalCallerIdT)r   r  r   r%   isdigitr   r   r   r   r   r   r  r  )r   r/  msg_typer]  r  rz  s   &&    r   r  (McubeCallSession._handle_control_message  sY    ;;v&kk-(3=cC:3N3NSVWZS[ScScSeSes3xko %''3!8!88 ((~~~ggll4::wZQUQ_Q_.`#abbb%%M%B''33G<Kt~~~ggllJJ#Z&(+2D		 	 	 %%M%B (	 c	s8   B'F*A F*F+7F#F5AF9F:FFc                  "   V P                   p V P                  P                  4       G Rj  xL
 w  r#pV P                  e   W P                  8X  d   KF  V P                  e   W P                  8w  d   Kf  V P
                  '       g   Kz  V P                   RV 2pR V n         ^ RIp\        V P                  4      pVP                  ! V^V4      p\        V4      pV P                  P                  \         P"                  ! RRRR\$        P&                  R\$        P(                  R\*        P,                  ! V4      P/                  R	4      R
V//4      4      G Rj  xL
  V^ 8  d\   V^ 8X  g   W1,          ^ 8X  dH   V P                  P                  \         P"                  ! RRRV P
                  R
V/4      4      G Rj  xL
   \1        V4      ^,          \$        P(                  ,          p	\        V P2                  4      p
\4        P6                  ! \9        RV	R,          V
,          4      4      G Rj  xL
  V P:                  '       g   EK7  V P<                  f   EKH  W0P<                  8  g   EK[  V P                  P?                  4       '       g   EK~  RV n        RV n         RV n        RV n        RV n        RV n        EK   EL  \         d     ELi ; i ELx EL L  \         d#    \4        P6                  ! R4      G Rj  xL 
   Li ; i5i)TN_seg_r   	playAudior   contentTyper   r/  asciirn   
checkpointr   g        g\(\?g?F)!r   r   r   r   r   r   rw   r   r3  r   r   mulr   rS   r   r   r   r   rQ   r   r   base64	b64encoder  r,   r   rp   rl  r   r   r   emptyr   )r   r   r]  rg  rv  rn   r3  gainmulawchunk_duration_spaces   &          r   r   McubeCallSession._playback_loop  s      00373D3D3H3H3J-J*CN ))5#A[A[:[&&.#9P9P2P>>>ll^54D#D
T]]+!(^Q!E #>2E'',,

)+;+D+D(*:*F*F%v'7'7'>'E'Eg'N"D	"
    !#aI<X\]<]ggllJJ#\&"D  )$'$7!$;?O?[?[#[ T667mmC-=-Dt-K$LMMM '''--9!:!::%%++--#( (-%-1**.'*/',0)M .K*    N )mmC((()s   +LJ:ALL"-J= BLKA!L9K:L?A-K ,K-K 1LLL*L.L=KLKLLK $L;K><LLLLc                &  "   V P                   '       g   R # V P                  '       g   R # \        P                  RV P                  V P
                  4       V P
                  V n        RV n        RV n        R V n        \        V P                  P                  4       4       F[  w  rVP                  P                  4       '       g   VP                  P                  4        V P                  P                  VR 4       K]  	   V P                  P!                  \"        P$                  ! RRRV P                   /4      4      G R j  xL
    V P(                  P+                  4        K   L"  \&         d     L-i ; i  \,        P.                   d     R # i ; i5i)Nz barge-in clear call_id=%s seq=%sFr   
clearAudior   )r   r   r   r   rw   r   r   r   r&   r   r  ro   r   r   rC  r   r   r   r   r   r   r  rp   r  )r   rn   r   s   &  r   rJ   McubeCallSession._barge_in_clear  s5    ~~~3T\\4CZCZ[%)%<%<"  %"& T//5578HD99>>##		  """4. 9	'',,tzz7L*dnn*]^___
	!!,,. ` 		 !! 		sZ   &FCF?A E$ ?E" E$ E5 "E$ $E2/F1E22F5F
FFF)1r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rw   r   r   r   rb   rc   r   r   r   ry   r   r   r   rh   ri   rj   r   r`   r   rg   r   rd   re   r   rf   r   r   )r7   r8   r9   r:   r    r   r   r   r   r   r   r   r   r   rL  r   r   r  r  r   r  r   rJ  r;   r<   r=   s   @r   ru   ru   l   s     V- V-p% ":>O O.77 77r;$ ;$z(. (.T	/ 	/>,, ,4
PT 4
 4
l+\Z 8T  <@ @"" "LM1^ r   ru   c          	      Z  "   \        V R R4      ;'       g    Rp\        V RR4      pV'       g   Ve   \        VR R4      ;'       g    Rp\        P                  RT\        V RR4      V'       d(   VP                  R4      P	                  R4      R,          MR4       V'       d!   VP                  R4      P	                  R4      M. pV'       d
   VR,          MRpV'       g   V P                  RRR	7      G Rj  xL
  R# \        VV VVR
7      pVP                  4       G Rj  xL
  R#  L/ L5i)pathr(   requestNz4ws accepted path=%s remote=%s call_hint_from_path=%sremote_address/i  zmissing call_id)codereason)rw   rx   r   ry   rk  )r   r   r   r+   r*   r   ru   r   )rx   r   ry   r  reqr.   rw   sesss   &$$     r   _ws_handlerr  6  s      9fb)//RD
)Y
-CCOsFB'--2HH>	+T2*.

3c"2&B	 +/DJJsO!!#&BE eBibGoo40AoBBB%!	D **, 	C s=   AD+AD+$)D+D+!D+7D'8(D+ D)!D+)D+c                  N  aaa"   \         P                  ! \         P                  R 7       \        4       G Rj  xL
 p \	        V 4      G Rj  xL
 o\
        P                  ! \        RR7      o\        P                  R\        \        4       \        P                  ! 4       oV3R lp\        P                  ! 4       p\        P                   \        P"                  3 F  p VP%                  W14       K  	  VVV3R lpV! 4       G Rj  xL
  R#  L L  \&         d     KD  i ; i L5i))levelNF)decode_responsesz"mcube ws bridge listening on %s:%sc                  Z   < SP                  4       '       g   SP                  R 4       R# R# )TN)r   rB  )r  r   s   *r   _signal_handlermain.<locals>._signal_handlera  s    yy{{OOD! r   c            	         <"   \         P                  ! V V3R  l\        \        R^^R7      ;_uu_4       GRj  xL
  SG Rj  xL
  RRR4      GRj  xL
  R#  L  L L
  + GRj  xL 
 '       g   i     R# ; i5i)c                     < \        V SSR 7      # ))r   ry   )r  )r   rX  ry   s   &r   r   &main.<locals>.runner.<locals>.<lambda>o  s    {2gLYr   )max_sizeping_intervalping_timeoutNi   )rz   serveWS_HOSTWS_PORT)rX  ry   r   s   r   runnermain.<locals>.runnerm  sa     ##Y
 
 
 JJ
 
 
 
 
 
 
s\   6A=AA=A AA A=AA=A A= A:	&A)'
A:	2A:	4	A=)loggingbasicConfigINFOrX   rY   r|   from_urlr_   r   r   r  r  rp   rq   get_running_loopsignalSIGINTSIGTERMadd_signal_handlerr4   )
connectionr  loopsigr  rX  ry   r   s        @@@r   mainr  V  s     gll+yJ
++G''	EJLHH17GD>>D" ##%Dv~~.	##C9 /	 (NN? !+ # 		 sR   3D%DD%DBD%D0D%D#D%D%D D%D  D%__main__)Nrp   r3  r  r   r  r  r  r@   r\  dataclassesr   collectionsr   typingr   r   rB   r)   rH   r!  redis.asyncior|   rz   livekit.agents.stt.sttrI   livekit.pluginsrJ   rK   livekitrL   !livekit.agents.stt.stream_adapterrM   livekit.plugins.silero.vadrN   r%  env_loadrO   mcube_defaultsrP   mcube_codecrQ   rR   rS   mqrT   rU   rV   rW   rX   rY   rZ   r[   	getLoggerr   r   r   r   r  r  r_   r   r   r   r   r   r   r   r   r   r   r   r   rl   ru   r  r  r7   runr   r   r   <module>r     s        	  
  !     	#$L   !  #  2 0  ; 7 / 9 J J	 	 	 )*  *,

bii.7
8
))*I
6IIk#=>	066B??tL{#	~~n-33{#	~~n-==.).)23 .).) ! ! !
G GT@"J zKK r   