+
    _&i?                        ^ RI t ^ RIt^ RIHt ^ RIHt ^ RIHtHtH	t	H
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Ht ^ RIHtHt ^ RIHtHtHt ^ RI t R R lt!R R lt"R R lt#R R lt$R R lt%R?R R llt&R@t'R R lt(R R lt)R R lt*R R  lt+R! R" lt,R# R$ lt-R% R& lt.R' R( lt/R) R* lt0R+ R, lt1R- R. lt2R/ R0 lt3R1 R2 lt4R?R3 R4 llt5R5 R6 lt6R7 R8 lt7R9 R: lt8R; R< lt9 ! R= R>]Pt                  4      t;R# )A    N)uuid4)defaultdict)AnyDictListOptional)connections)statusviewsets)action)Response)AgentConfig)AgentConfigCreateSerializerAgentConfigSerializer)_q_identensure_business_cluster_tables)list_cloud_agent_deploymentsprepare_workdir_for_botrun_lk_agentc                0    V ^8  d   QhR\         R\        /#    vreturnr   bool)formats   "=E:\live-kit-agent\livekit_voicebot\backend\apps\agents\api.py__annotate__r      s     / /3 /4 /    c                     V R9   # )   )r"   T1trueTrue r   s   &r   _truthy_colr(          ...r    c                <    V ^8  d   QhR\         R\        R\        /# )r   r   defaultr   )r   int)r   s   "r   r   r      s!       s s r    c                 L     \        V 4      #   \        \        3 d    Tu # i ; iN)r,   	TypeError
ValueError)r   r+   s   &&r   	_safe_intr1      s)    1vz" s   
 ##c                0    V ^8  d   QhR\         R\        /# r   valr   r   list)r   s   "r   r   r      s      c d r    c                     V f   . # \        V \        4      '       d   V # \        V \        4      '       d2    \        P                  ! V 4      p\        V\        4      '       d   V# . # . #   \
         d    . u # i ; ir.   
isinstancer6   strjsonloads	Exception)r4   parseds   & r   _parse_transfer_destinationsr?      q    
{	#t
#s	ZZ_F'556=2= I  	I	   -A( $A( (A87A8c                0    V ^8  d   QhR\         R\         /# r   rowr   dict)r   s   "r   r   r   ,   s     h hd ht hr    c                d   \        V 4      pVP                  R4      p\        V\        4      '       d    \        P
                  ! V4      VR&   VP                  R4      p\        V\        4      '       d    \        P
                  ! V4      VR&   \        VP                  R4      \         4      '       g   R\        VP                  R4      4      RVP                  R4      ;'       g    R;'       g    RRVP                  R	4      ;'       g    R;'       g    RR
\        VP                  R4      ^
4      R\        VP                  R4      4      /VR&   \        VP                  R4      \         4      '       g   R\        VP                  R4      4      RVP                  R4      ;'       g    R;'       g    RRVP                  R4      ;'       g    R;'       g    RR\        VP                  R4      4      /VR&   \        VP                  R4      \         4      '       g   R\        VP                  R4      4      RVP                  R4      ;'       g    R;'       g    RRVP                  R4      ;'       g    R;'       g    RR\        VP                  R4      4      /VR&   \        VP                  R4      \         4      '       g   R\        VP                  R4      4      RVP                  R4      ;'       g    R;'       g    RRVP                  R4      ;'       g    R;'       g    RR\        VP                  R4      4      /VR&   VP                  R4      p\        V\         4      '       d   RpMVe   \        V4      P                  4       MRp\        VP                  R4      4      pV'       g   \        RV// 4      p\        VP                  R4      \         4      '       g   R\        VP                  R4      4      RVP                  R4      ;'       g    R;'       g    RRVP                  R4      ;'       g    R;'       g    RR VP                  R!4      ;'       g    R";'       g    R"R#VRVR\        VP                  R$4      4      /VR&   VP                  R%4      p\        V\        4      '       d    \        P
                  ! V4      pMVf   / pM\        V\         4      '       g   / pVP                  R&4      pVe   \        V4      P                  4       VR'&   MVP                  R'4      '       g   RVR'&   WqR%&   VP                  R(4      p	\        V	\         4      '       g   T	p
V
f   R*p
R)V
/VR(&   V#   \         d     EL<i ; i  \         d     ELi ; i  \         d    / p Li ; i)+z
Cluster rows store features as flat columns; clients expect nested objects matching POST shape.
Build `end_conversation`, `skip_turn`, etc. without putting them back into `platform_settings`.
voiceplatform_settingsend_conversationenableddescriptionend_conversation_description promptend_conversation_prompttimeoutend_conversation_timeoutdisable_interruptions&end_conversation_disable_interruptions	skip_turnskip_turn_descriptionskip_turn_promptskip_turn_disable_interruptionsvoicemail_detectionvoicemail_descriptionvoicemail_detection_prompt)voicemail_detection_disable_interruptionsdetect_languagedetect_language_descriptiondetect_language_prompt%detect_language_disable_interruptionstransfer_to_numbertransfer_destinationsdestinationstransfer_enabledtransfer_number_descriptiontransfer_to_number_promptdestination_typetransfer_destination_typephonephone_number(transfer_to_number_disable_interruptionsadvanced_settingsfiller_keywordskeywordsconcurrent_callslimit)rF   getr9   r:   r;   r<   r=   r(   r1   stripr?   _transfer_phone_for_column)rD   out	voice_rawps	phone_col	phone_strrc   advfkraw_cclims   &          r   _enrich_cluster_bot_responser~   ,   s   
 s)C I)S!!	::i0CL 
$	%B"c	'+zz"~C#$
 cgg01488{377+=#>?CGG$BCPIrPPbsww89F?RFFBy)C!DbI#[9a1b%c#
 cggk*D11{377;#78CGG$;<IBIIrsww12?8b??R#[9Z1[%\	
K cgg34d;;{377+@#ABCGG$;<IBIIrsww;<IBIIr#[9d1e%f	&
!" cgg/0$77{377+<#=>CGG$ABOHbOORsww78E>BEE2#[9`1a%b	"
 ,-I)T""	.7.CC	N((*	/8O0PQL./MrR	cgg23T::{377+=#>?CGG$ABOHbOORsww:;HArHHb)D!E \!P \ \U\IL#[9c1d%e%
 ! ''%
&C#s	**S/C 
T""	"	#B	~b'--/JWWZ  J"WW'(Ffd##;C#*C.J{  		  		@  	C	s5   U; 5V ;V ;V
	V
VVV/.V/c                0    V ^8  d   QhR\         R\         /# rC   rE   )r   s   "r   r   r      s     	 	 	 	r    c                    \        \        V 4      4      pVP                  R4      pVe   W!R&   VP                  R4      ;'       g    VP                  R4      pVe   W1R&   V# )zKAlign cluster `{bid}_bots` rows with AgentConfig-shaped API (`id`, `name`).bot_ididbot_namename)r~   rF   rr   )rD   ru   bidr   s   &   r   _normalize_cluster_botr      sZ    
&tCy
1C
''(
C
D	wwz"55cggfoHFJr    c                t    V ^8  d   QhR\         R\        \        \        \        3,          ,          R\         /# )r   request_data	validatedr   )rF   r   r   r:   r   )r   s   "r   r   r      s0      T htCQTH~>V bf r    c                 F   V '       d   V P                  R 4      MR;'       g&    V'       d   T;'       g    / P                  R 4      MRp\        V\        4      '       d    \        P                  ! V4      p\        V\        4      '       g   / pV#   \
         d    / p L)i ; i)voice_configNrr   r9   r:   r;   r<   r=   rF   )r   r   	voice_cfgs   && r   _voice_config_from_requestr      s    5A!!.1t  1:bn-  )S!!	

9-I i&&		  	I	s    B B B c                ^    V ^8  d   QhR\         R\         R\        \        \        3,          /# )r   r   bsr   )rF   r   r:   r   )r   s   "r   r   r      s,       4 DQTVYQYN r    c                Z   \        VP                  R4      ;'       g    / 4      pT ;'       g    / P                  4        F	  w  r4WBV&   K  	  / p\         FS  pW29  d   K  VP                  V4      pVf   K"  \	        V\
        4      '       d   VP                  4       R8X  d   KO  WEV&   KU  	  V# )zZVoice tab controls stored under `platform_settings.voice` (subset of full `voice` column).rH   rN   )rF   rr   itemsVOICE_TAB_PLATFORM_KEYSr9   r:   rs   )r   r   mergedkr   ru   s   &&    r   )_voice_tab_settings_for_platform_settingsr      s    !"&&/"7"7R8Fb'')q	 *C$?JJqM9a!'')r/A % Jr    c                0    V ^8  d   QhR\         R\        /# r3   )r   r:   )r   s   "r   r   r      s      c c r    c                     V f   R# \        V 4      P                  4       P                  4       P                  RR4      pVR9   d   R# VR	9   d   R# VR
9   d   R# VR9   d   R# V# )NrN    _ri   phone_dynamic_variablesip_urisip_uri_dynamic_variable)ri   rj   )r   phone_number_dynamicphone_as_dynamic_variable)r   )r   sip_uri_dynamic)r:   lowerrs   replace)r4   ss   & r   $_normalize_transfer_destination_typer      sd    
{C ((c2A%%[['L;;)Hr    c                0    V ^8  d   QhR\         R\        /# )r   rawr   r5   )r   s   "r   r   r      s      # $ r    c                     V f   . # \        V \        4      '       d   V # \        V \        4      '       d2    \        P                  ! V 4      p\        V\        4      '       d   V# . # . #   \
         d    . u # i ; ir.   r8   )r   r>   s   & r   _parse_destinations_listr      r@   rA   c                <    V ^8  d   QhR\         R\         R\        /# )r   tnfeaturesr   rF   r:   )r   s   "r   r   r      s!     ( (4 (4 (C (r    c                .   \        V P                  R4      ;'       g    VP                  R4      ;'       g    R4      P                  4       pV'       d
   VR,          # \        V P                  R4      4      pV'       g   \        VP                  R4      4      pV F  p\	        V\
        4      '       g   K  \        VP                  R4      ;'       g    VP                  R4      4      pVR	8w  d   KW  VP                  R4      ;'       g    VP                  R4      ;'       g    Rp\        V4      P                  4       pV'       g   K  VR,          u # 	  V'       d   V^ ,          p\	        V\
        4      '       d   \        VP                  R4      ;'       g    VP                  R4      4      pVR	8X  d_   VP                  R4      ;'       g    VP                  R4      ;'       g    Rp\        V4      P                  4       pV'       d
   VR,          # R# )
z
Resolve `transfer_to_number` VARCHAR from explicit fields or first phone-type destination row.
UI label "Phone Number" maps to destination type `phone`.
rj   transfer_phone_numberrN   :N@   Nrc   rb   rh   typeri   )r:   rr   rs   r   r9   rF   r   )	r   r   ri   rc   destdtprw   firsts	   &&       r   rt   rt      s   
 
~MM(,,/F"GMM2eg 
 Sz+BFF>,BCL/=T0UV$%%1HH01EETXXf5E
 =HH,-OO.1IOORV\\^2c7N  QeT""5		56KK%))F:KB W}II56YY%))N:SYYWYV\\^c7Nr    c                0    V ^8  d   QhR\         R\        /# r   r   )r   s   "r   r   r     s     L L L Lr    c                     V R J ;'       g9    V R8H  ;'       g,    \        V \        4      ;'       d    V P                  4       R8H  # NrN   )r9   r:   rs   r'   s   &r   	_blankishr     s9    9KKRKKJq#$6$J$J1779?Kr    c                0    V ^8  d   QhR\         R\         /# )r   r   r   rE   )r   s   "r   r   r     s     
0 
0d 
0t 
0r    c                    V P                  R 4      pVf   / # \        V\        4      '       d2    \        P                  ! V4      p\        V\
        4      '       d   V# / # \        V\
        4      '       d   V# / #   \         d    / u # i ; i)bot_settings)rr   r9   r:   r;   r<   rF   r=   )r   r   r>   s   &  r   _parse_bot_settingsr     s    


>
*C
{	#s	ZZ_F'556=2= S$''3/R/  	I	s   -A9 A9 9B	B	c                R    V ^8  d   QhR\         R\         R\        \         ,          /# )r   r   r   r   )rF   r   )r   s   "r   r   r   '  s%      T  (4. r    c                     VP                  R 4      pVf   V '       d   V P                  R 4      p\        V\        4      '       d    \        P                  ! V4      p\        V\        4      '       d   V'       d   V# R#   \
         d     R# i ; i)conversation_behaviorNr   )r   r   r   s   && r   _parse_conversation_behaviorr   '  su    


2
3C
{rff,-#s	**S/C #t
	  		s   A> >BBc          
      T    V ^8  d   QhR\         R\         R\         R\         R\        /# )r   r   r   vdr   r   r   )r   s   "r   r   r   5  s4      #'7;r    c                `    \        W4      p/ pV'       d   WER&   \        P                  ! V4      # )z
`platform_settings` keeps a compact `voice` object for Voice tab fields only.

Full merged voice (incl. voice_id) stays in the `voice` column; language in
`default_language`; features/prompts in dedicated columns.
rH   )r   r;   dumps)r   r   r   r   	voice_tabpayloads   &&&&  r   %_build_platform_settings_column_valuer   5  s-     :)HI G$::gr    c                0    V ^8  d   QhR\         R\        /# r   r   )r   s   "r   r   r   E  s     / /s /t /r    c                     V R9   # )T)Tr"   r#   r$   r%   r&   r'   s   &r   _truthyr   E  r)   r    c                @    V ^8  d   QhR\         R\        R\         RR/# )r   r   
table_colsrD   r   NrF   set)r   s   "r   r   r   I  s.     F9 F9 F93 F9T F9d F9r    c                   V '       g   R# R	pV F9  w  rEW@9  g   WQ9  d   K  \        V P                  V4      4      '       d   ^M^ W%&   K;  	  RV9   d/   RV 9   d(   \        V P                  R4      4      '       d   ^M^ VR&   R
pV FU  w  ruWQ9  g   Wp9  d   K  V P                  V4      pVe*   \        V4      P                  4       R8w  d   \        V4      MRW%&   KW  	  Rp	V	 FU  w  ruWQ9  g   Wp9  d   K  V P                  V4      pVe*   \        V4      P                  4       R8w  d   \        V4      MRW%&   KW  	  RV9   d0   RV 9   d)    \	        ^ \        V P                  R4      4      4      VR&   RV9   dR   RV 9   dK   V P                  R4      pVe1   \        V4      P                  4       R8w  d   \        V4      R,          MRVR&   RV9   dN   RV 9   dG   V P                  R4      p
V
e2   \        V
\        4      '       g   \        P                  ! V
4      MT
VR&   RpV F9  w  ruWQ9  g   Wp9  d   K  \        V P                  V4      4      '       d   ^M^ W%&   K;  	  R#   \        \        3 d
    RTR&    ELi ; i)zEMap `platform_settings.features` into dedicated `{bid}_bots` columns.Nrd   ra   rN   rR   rh   N    Nrb   ))rU   rU   )r]   r]   )rJ   rJ   )rY   rY   ))rW   rW   )r_   r_   )rP   rP   )rf   rf   )r[   r[   ))rV   rV   )r^   r^   )rM   rM   )re   re   )rZ   rZ   ))rX   rX   )r`   r`   )rT   rT   )rk   rk   )r\   r\   )r   rr   r:   rs   maxr,   r/   r0   r9   r;   r   )r   r   rD   	bool_keysfeat_keycol	long_textr{   r   
short_texttdinterrupt_colss   &&&         r   _apply_features_to_columnsr   I  sP   I ##s'<X 6771Q #
 Z',@H,L'.x||<P/Q'R'R!XYI  B$6LL]s1v||~/C3q6	 J  B$6LL]s1v||~/C3q6	  "Z/4NRZ4Z	3.1!SF`9a5b.cC*+ #j05PT\5\LL45:;-CPQFLLN^`L`3q6#;fj'(*,1HH1T\\12>AKBPSATAT4::b>Z\C'(N " B$6R 0111q "' :& 	3.2C*+	3s   
'I   I:9I:c          
      L    V ^8  d   QhR\         R\         R\        R\         RR/# )r   r   r   r   rD   r   Nr   )r   s   "r   r   r     s@     Ml Ml Ml MlRU Ml\` Mlei Mlr    c                   V P                  R4      ;'       g    / pRV9  dK   RV9   dD   VP                  R4      pVe*   \        V4      P                  4       R8w  d   \        V4      MRVR&   RV9  dK   RV9   dD   VP                  R4      pVe*   \        V4      P                  4       R8w  d   \        V4      MRVR&   RV9  d0   RV9   d)    \        ^ \	        VP                  R	4      4      4      VR&   R
V9  d/   R
V9   d(   \        VP                  R4      4      '       d   ^M^ VR
&   V P                  R4      ;'       g    / pRV9  dK   RV9   dD   VP                  R4      pVe*   \        V4      P                  4       R8w  d   \        V4      MRVR&   RV9  dK   RV9   dD   VP                  R4      pVe*   \        V4      P                  4       R8w  d   \        V4      MRVR&   RV9  dR   RV9   dK   VP                  R4      pVe1   \        V4      P                  4       R8w  d   \        V4      R,          MRVR&   RV9  dN   RV9   dG   VP                  R4      pVe2   \        V\        4      '       g   \        P                  ! V4      MTVR&   RV9  d/   RV9   d(   \        VP                  R4      4      '       d   ^M^ VR&   V P                  R4      ;'       g    / pRV9  dK   RV9   dD   VP                  R4      pVe*   \        V4      P                  4       R8w  d   \        V4      MRVR&   RV9  dK   RV9   dD   VP                  R4      pVe*   \        V4      P                  4       R8w  d   \        V4      MRVR&   RV9  d/   RV9   d(   \        VP                  R4      4      '       d   ^M^ VR&   V P                  R4      ;'       g    / p	RV9  dK   RV9   dD   V	P                  R4      pVe*   \        V4      P                  4       R8w  d   \        V4      MRVR&   RV9  dK   RV9   dD   V	P                  R4      pVe*   \        V4      P                  4       R8w  d   \        V4      MRVR&   RV9  d/   RV9   d(   \        V	P                  R4      4      '       d   ^M^ VR&   V P                  R4      ;'       g    / p
RV9  dK   RV9   dD   V
P                  R4      pVe*   \        V4      P                  4       R8w  d   \        V4      MRVR&   RV9  dK   RV9   dD   V
P                  R4      pVe*   \        V4      P                  4       R8w  d   \        V4      MRVR&   R V9  d3   R V9   d*   \        V
P                  R4      4      '       d   ^M^ VR &   R# R# R#   \
        \        3 d
    RTR&    ELi ; i)!z
Fill prompt/description/timeout/interrupt columns from top-level `bot_settings` sections
when those keys were not supplied via `platform_settings.features`.
rJ   rP   rO   NrN   rM   rL   rR   rQ   rT   rS   ra   rf   re   rh   rg   r   rb   rc   rk   rY   r[   rZ   r\   rU   rW   rV   rX   r]   r_   r^   r`   )rr   r:   rs   r   r,   r/   r0   r   r9   r;   r   )r   r   r   rD   ecr   r   r   vmstdls   &&&&       r   '_apply_flat_bot_settings_detail_columnsr     s-   
 
"	#	)	)rB 05NR\5\FF834=SV\\^WYEYQ_c%&%X5:X\f:fFF=!89#a&,,.\^J^c!fdh*+!16PT^6^	3.1!S	9J5K.LC*+ 	1@4
B=DRVVLcEd=e=ekl45	$	%	+	+B"(27RV`7`FF856]s1v||~Y[G[3q6ae'($H49VZd9dFF=!78}Q[]I]SVcg)*"(27RV`7`FF%&:;-CPQFLLN^`L`3q6#;fj'(h.3Jj3XVVN#>AKBPSATAT4::b>Z\C'(2(B6*D?FrvvNeGf?g?g!mn67	%	&	,	,"B#838TXb8bFF867mAZ\H\CFbf()h.3Jj3XFF=!123q6<<>UWCWs1v]a#$38C7:E@GOfHg@h@h1no78			"	"B).@J.NFF8,-Mc!fllnPR>R#a&X\h.3Jj3XFF=!123q6<<>UWCWs1v]a#$(8=^bl=l6=bffE\>]6^6^de-.	!	"	(	(bBx/4LPZ4ZFF823-CFLLNVXDXA^b$%$H49VZd9dFF=!78}Q[]I]SVcg)*/x?3zA<CBFFKbDc<d<dqjk34 B 	@w :& 	3.2C*+	3s   'V# #V=<V=c          
      L    V ^8  d   QhR\         R\        R\         R\         RR/# )r   r   r   rD   r   r   Nr   )r   s   "r   r   r     s;     Q& Q&Q&Q&$(Q&59Q&	Q&r    c           	        / pV '       dQ   V P                  R4      p\        V\        4      '       d*   VP                  R4      p\        V\        4      '       d   Tp\        WAV4       \	        WW4       V '       g   RV9   d   RV9  d   ^VR&   R# V P                  R4      ;'       g    / pRV9   d&   RV9  d   VP                  R4      '       d   ^M^ VR&   V P                  R4      ;'       g    / pRV9   d&   RV9  d   VP                  R4      '       d   ^M^ VR&   V P                  R4      ;'       g    / p	RV9   d&   RV9  d   V	P                  R4      '       d   ^M^ VR&   V P                  R4      ;'       g    / p
RV9   d&   RV9  d   V
P                  R4      '       d   ^M^ VR&   V P                  R	4      ;'       g    / pR
V9   d&   R	V9  d   VP                  R4      '       d   ^M^ VR
&   R	V9   d   \        W4      pV'       d   TMRVR	&   V P                  R4      ;'       g    / pVP                  R4      pRV9   d<   Ve   VR8X  g   VR8X  d   RVR&   M# \        ^ \        R\        V4      4      4      VR&   V P                  R4      ;'       g    / pVP                  R4      pRV9   dE   Ve<   \        V4      P                  4       R8w  d   \        V4      P                  4       VR&   MRVR&   RV9   d[   / pVP                  R4      e    \        VP                  R4      4      VR&   V'       d   \        P                  ! V4      VR&   MRVR&   \        V P                  R4      ;'       g    / 4      pVP                  R4      '       d"   VP                  RVP                  R4      4       VP!                  4        F  w  ppVP                  VV4       K  	  RV9   d&   V'       d   \        P                  ! V4      VR&   R# R# R#   \        \        3 d
    RTR&    ELi ; i  \        \        3 d    TP                  R4      TR&    EL"i ; i)zODedicated columns for features + toggles; platform_settings JSON stays minimal.rI   r   r]   NrJ   rK   rU   rY   ra   rd   ro   rp   rN   i,  rl   rn   rm   turn_timeoutrH   voice_idrq   )rr   r9   rF   r   r   rt   r   minr,   r/   r0   r:   rs   r;   r   
setdefaultr   )r   r   rD   r   r   rw   rawfr   r   r   r   r   ri   ccr}   rz   rn   restvor   r   s   &&&&                 r   "_apply_bot_settings_to_cluster_rowr     s    H	VV'(b$66*%D$%%xS9+B*J
*/@/K%&C!"	"	#	)	)rBZ',>h,N')vvi'8'8!a			"	"Bj [%@ "y 1 11qK	%	&	,	,"B
*/DH/T*,&&*;*;Q!"	!	"	(	(bBJ&+<H+L&(ffY&7&7Q	$	%	+	+BZ',@,P')vvi'8'8!az)*28-2E !	"	#	)	)rB
&&/CZ';#)sby&*C"#/*-aS#c(1C*D&' &&$
%
+
+Cwwz"HJ&CM$7$7$9R$?%(]%8%8%:C!"%)C!"j(77>".?'*377>+B'C^$ '+zz$'7C#$'+C#$	bffWo##	$B}}Z  
j)--
";<!1
a "*zz"~G "$9 z* /*.&'/  z* ?'*ww~'>^$?s$    "P P- P*)P*-%QQc                0    V ^8  d   QhR\         R\         /# rC   rE   )r   s   "r   r   r   6  s     ! !t ! !r    c                >   \        V 4      pRV9   dI   VR,          p\        V4      '       d   ^VR&   M(\        V4      P                  4       p \	        V4      VR&   R F8  pWA9  d   K  W,          p\        V4      '       d   RW&   K*   \	        V4      W&   K:  	  RV9   dM   VP                  R4      p\        V4      '       d   RVR&   V# \        V4      P                  4       R,          VR&   V#   \
         d    Y1R&    Li ; i  \        \
        3 d	    RY&    K  i ; i)zc
Legacy `{bid}_bots` tables often use INT for mcube_gid; empty strings from JSON must not be sent.
	mcube_gidNagent_idN   N)ro   )rF   r   r:   rs   r,   r0   r/   rr   )rD   ru   r   r   r   s   &    r   %_sanitize_cluster_bots_row_for_insertr   6  s    s)CcQ<< CAA%#&q6K  %>HQ<<CH q6 % SGGJQ<<"C
O J "!fllnT2C
OJ)  %#$K % z*   s$   C. D.D ?D DDc                    V ^8  d   QhR\         R\        R\        R\        \        \
        \        3,          ,          R\         /# )r   r   r   r   r   r   )rF   r,   r   r   r   r:   r   )r   s   "r   r   r   Z  sB     =; =;=; =;.1=;>FtCQTH~>V=;	=;r    c                 \	   T;'       g    / p\        W4      p\        V 4      pR TRVP                  R4      ;'       g    V P                  R4      ;'       g    RP                  4       ;'       g    RRV P                  R4      ;'       g    V P                  R4      RVP                  R4      ;'       g    V P                  R4      ;'       g    RP                  4       ;'       g    RRVP                  R4      e   VP                  R4      MV P                  R4      ;'       g    RR
VP                  R4      e   VP                  R4      MV P                  R4      ;'       g    RR\	        WeW@4      RRR^/	p\        W`4      pVe!   RV9   d   \        P                  ! V4      VR&   RVP                  R4      e   VP                  R4      MV P                  R4      RVP                  R4      e   VP                  R4      MV P                  R4      RVP                  R4      e   VP                  R4      MV P                  R4      RVP                  R4      e   VP                  R4      MV P                  R4      RVP                  R4      e   VP                  R4      MV P                  R4      RVP                  R4      e   VP                  R4      MV P                  R4      RVP                  R4      e   VP                  R4      MV P                  R4      R\        P                  ! V P                  R4      ;'       g    VP                  R4      ;'       g    . 4      R\        P                  ! V P                  R4      ;'       g    VP                  R4      ;'       g    . 4      RVR,          /
p	V	P                  4        F  w  rW9   g   K  Vf   K  WV
&   K  	  RV9   d   VP                  R4      e   VP                  R4      MV P                  R4      pVeC   \        V4      P                  4       R8w  d%   \        V4      P                  4       R,          VR&   MR	VR&   \        WbWu4       VP                  4        U
Uu/ uF  w  rW9   g   K  WbK  	  pp
p\        V4      # u upp
i )business_idr   r   rN   Unnamed Botr   agentId
agent_name	llm_modelNrO   system_promptrI   
voice_name	is_activer   stt_providertts_providerllm_providermcube_exenumberr   message_inboundfirst_message_inboundmessage_outboundfirst_message_outbound
guardrailssystem_toolsdefault_languager   )r   r   rr   rs   r   r   r;   r   r   r:   r   r   )r   r   r   r   r   r   r   rD   cboptional_mapr   r   dlangfiltereds   &&&&          r   _build_cluster_bot_rowr  Z  s    
bB*<<I	\	*B 	sRVVF^EE|'7'7'?EE2LLN__R_L$$Z0OOL4D4DY4Orvvf~GG)9)9&)AGGRNNPaaTaBFF;,?,KRVVK(R^RbRbcnRoRuRusu66/". &&)/552B2RTcbQC  
&b	7B	~1Z?'+zz"~#$ 	"&&2H2T~.ZfZjZjkyZz"&&2H2T~.ZfZjZjkyZz"&&2H2T~.ZfZjZjkyZz?P8Q8]266"34cocscs  uF  dGBFF;,?,KRVVK(Q]QaQabmQn66)*6 66"9:5666*+7 FF#;<67djj!1!1,!?!]!]266,CW!]!][]^

<#3#3N#C#c#crvvnG]#c#cacdS!45L  ""$?q}F % Z' vv()5 FF%&!!"45 	
 U!1!1!3r!9&)%j&6&6&8&=C"#&*C"#&rsF!$@H@0:: As   
R(R(c                <    V ^8  d   QhR\         R\        R\         /# )r   r   r   r   r   )r   s   "r   r   r     s&     C C C3 C4 Cr    c                z   RRRRRRRRRRRRR	R	R
R
RRRRRRRRRR/p/ pVP                  4        F  w  rEW@9   g   K  WQ9   g   K  W,          pVR8X  d   VR9   d   ^M^ W5&   K3  VR8X  d8   \        V4      '       g!   \        V4      P                  4       R,          MRW5&   Kq  VR8X  d8   \        V4      '       g!   \        V4      P                  4       R,          MRW5&   K  VR8X  dA   \        V4      '       d   ^W5&   K  \        V4      P                  4       p \	        V4      W5&   K  WcV&   K  	  \        V 4      pRV 9   d   \        V 4      p	/ p
\        WW4       V
P                  4        F  w  rW9   g   K  WV&   K  	  \        W4      pVe!   RV9   d   \        P                  ! V4      VR&   RV P                  R4      /pRV9   d   \        WW4      VR&   RV9   dE   RV 9   d>   V P                  R4      pVR9  d!   \        V4      P                  4       R,          MRVR&   V# RV 9   g   RV 9   du   RV9   d#   \        / VRV P                  R4      /V 4      VR&   RV9   dE   RV 9   d>   V P                  R4      pVR9  d!   \        V4      P                  4       R,          MRVR&   V#   \
         d
    YsT&    EK  i ; i)z1Map JSON/API fields to cluster columns for PATCH.r   r   r   r   r   rO   r   r   r   r   r  r   r  r  r  r  r   r   N:N   Nr   r   r  rI   r   r   )Tr"   r#   r$   r   )r   r   r:   rs   r,   r0   r   r   r   r   r;   r   rr   r   )r   r   mappingupdatesapi_keyr   r4   r   r   r   tmpr   r   r	  vd_patchr   s   &&              r   _cluster_update_valuesr    s    	
Jl[,[!2 "4[G G"s'8'C+%$'+A$AqqJ&=Fs^^s3x~~/5QUL(=Fs^^s3x~~/5QU#S>>#$GLC(A)'*1v  #' (* +<8I% .*23JIIKDA
   *";>5C/3zz"~G+,&(8(89K(LM*,+Px,G'( +0Bl0R!!"45BBDJBV#b'--/#*>\`G&' N 
<	'+=+M*,+PI 2L4D4DEW4XY[g,G'( +0Bl0R!!"45BBDJBV#b'--/#*>\`G&'NC & )'()s   J&&J:9J:c                0    V ^8  d   QhR\         R\         /# rC   rE   )r   s   "r   r   r     s      D T r    c                   \        V 4      pVP                  R4      ;'       g    RVR&   VP                  R4      ;'       g    RVR&   VP                  R4      pV'       d%   \        V4      P                  R4      '       d   W!R&   V# )zPMatch `DocumentViewSet` cluster rows so `doc_name` appears as `name` for the UI.doc_namerN   r   doc_url	file_pathweb_url)zhttp://zhttps://)rF   rr   r:   
startswith)rD   ru   dus   &  r   _shape_cluster_kb_documentr    sr    
s)C''*%++CKwwy)//RC		B	c"g  !899IJr    c          	          V ^8  d   QhR\         R\        \         ,          R\        \         \        \        ,          3,          /# )r   r   bot_idsr   )r,   r   r   rF   )r   s   "r   r   r     s7     ' ' 'd3i 'DQTVZ[_V`Q`La 'r    c           	        V'       g   / # \        V 4      p\        V4       V R2p. p\        4       pV F9  p \        V4      pYu9  g   K  TP                  T4       TP                  T4       K;  	  V'       g   / # RP                  R.\        V4      ,          4      pR\        V4       RV R2p	\        R,          P                  4       ;_uu_ 4       p
V
P                  W4       V
P                   Uu. uF  q^ ,          NK  	  ppV
P                  4       pRRR4       \        \         4      pX F\  p\#        \%        \'        XV4      4      4      pVP)                  R	4      pVf   K8   \        V4      pTT,          P                  T4       K^  	  \%        V4      #   \        \        3 d     EKz  i ; iu upi   + '       g   i     L; i  \        \        3 d     K  i ; i)
zSLoad `{business_id}_knowledgebase` rows grouped by `bot_id` (newest first per bot)._knowledgebase, %sSELECT * FROM z WHERE bot_id IN (z) ORDER BY bot_id ASC, id DESCclusterNr   )r,   r   r   r/   r0   addappendjoinlenr   r	   cursorexecuterL   fetchallr   r6   r  rF   ziprr   )r   r!  r   tableuniqseenxixplaceholderssqlcurccolsraw_rowsby_botrdb_ids   &&                r   _knowledge_documents_by_bot_idr?    s   	
k
C"3'e>"ED5D	QB >HHRLKKO  	99dVc$i/0L
%));L> J' 	'  
Y		&	&	(	(CC!oo.o!o.<<> 
) %0$5F&tCaL'9:uuX<	t9D 	tA  <7 :& 		 / 
)	( :& 		sA   F F72F2F7'G
F/.F/2F77G	
GGc                J    V ^8  d   QhR\         R\        \        ,          RR/# )r   r   botsr   N)r,   r   rF   )r   s   "r   r   r     s*     Q QS QT
 Qt Qr    c                   . pV FJ  pVP                  R4      pVf   VP                  R4      pVf   K/   VP                  \        V4      4       KL  	  \        W4      pV FV  pVP                  R4      pVf   VP                  R4      p Ve   \        V4      MRpVe   VP                  V. 4      M. VR&   KX  	  R#   \        \        3 d     K  i ; i  \        \        3 d    Rp LNi ; i)zXMutate bot dicts in place: set `knowledge_documents` from cluster `{bid}_knowledgebase`.r   Nr   knowledge_documents)rr   r)  r,   r/   r0   r?  )r   rA  idsbr   groupediks   &&     r   _attach_knowledge_documentsrH    s    CeeHo;%%+C?

3s8$  -[>GeeHo;%%+C	 _S$B ;=.7;;r2#6b
   z*  :& 	B	s#   B<
C<CCC*)C*c                      a a ] tR tRt oRt]P                  P                  4       P                  R4      t	R t
V 3R ltV 3R ltR tR tV3R	 lV 3R
 lltV 3R ltR t]! RR.RR7      RR l4       tRtVtV ;t# )
BotViewSeti-  z
Bot CRUD. With `business_id`, stores rows only in cluster DB `{business_id}_bots`.
Without `business_id`, uses legacy master `AgentConfig` (agents_agent_config).
r   c                <    V P                   R 8X  d   \        # \        # )create)r   r   r   )selfs   &r   get_serializer_classBotViewSet.get_serializer_class5  s    ;;("..$$r    c                  < VP                   P                  R4      pV'       d    \        V4      p\        V4       V R2p\        R,          P                  4       ;_uu_ 4       pVP                  R\        V4       R24       VP                   Uu. uF  q^ ,          NK  	  p	pVP                  4        U
u. uF   p
\        \        \        W4      4      4      NK"  	  pp
\        W[4       RRR4       \        X4      # \&        SV `P  ! V.VO5/ VB # u upi u up
i   + '       g   i     L9; i  \         d3   p\        RRR	\!        T4      /\"        P$                  R
7      u Rp?# Rp?ii ; i)z}
If business_id is provided, read bots from cluster `{business_id}_bots`.
Otherwise fall back to master DB AgentConfig list.
r   _botsr'  r&  z ORDER BY bot_id DESCNmessagez!Failed to load bots from cluster.errorr
   )query_paramsrr   r,   r   r	   r,  r-  r   rL   r.  r   rF   r/  rH  r   r=   r:   r
   HTTP_500_INTERNAL_SERVER_ERRORsuperr6   )rM  requestargskwargsr   r   r0  r7  r8  r9  r<  rowse	__class__s   &&*,         r   r6   BotViewSet.list:  s9   
 **..}=+&.s3%u +2244KK.%0AAV WX*-//:/QaDD/D:PSP\P\P^_P^124D3EFP^D_/:	 5
  ~% w|G5d5f55 ;_ 54   CWcRSfU!@@ sS   >D- $-DD"D6&DD)D- 
DD*	%D- -E*8'E%E*%E*c           
     J  < VP                   P                  R 4      pVP                  R4      pV'       Ed   Ve    \        V4      p\        V4       V R2p\        R,          P                  4       ;_uu_ 4       pVP                  R\        V4       R2V.4       VP                  4       p	V	'       g(   \        RR/\        P                  R	7      uuRRR4       # VP                   U
u. uF  q^ ,          NK  	  pp
\        \        \        W4      4      4      p\!        Wl.4       \        V4      uuRRR4       # \(        SV `T  ! V.VO5/ VB # u up
i   + '       g   i     L); i  \"         d3   p\        R
RR\%        T4      /\        P&                  R	7      u Rp?# Rp?ii ; i)r   pkNrQ  r'  r&   WHERE bot_id = %sdetail
Not found.rT  rR  z Failed to load bot from cluster.rS  )rU  rr   r,   r   r	   r,  r-  r   fetchoner   r
   HTTP_404_NOT_FOUNDrL   r   rF   r/  rH  r=   r:   rV  rW  retrieve)rM  rX  rY  rZ  bid_rawr`  r   r0  r7  rD   r8  r9  r   r\  r]  s   &&*,          r   rf  BotViewSet.retrieveR  sa   &&**=9ZZ7r~'l.s3%u +2244KK.%0AAS TWYVZ[,,.C'<(@IbIbc	 54
 +.//:/QaDD/D:4T#d.5IJG/Y?#G, 54 w9$9&99 ; 54   BGSQRVT!@@ sZ   >E% :AE
E% E(E95E.
E% EE"	E% "E% %F"0'FF"F"c                2    V P                   ! V.VO5R R/VB # )partialT_update_cluster_or_masterrM  rX  rY  rZ  s   &&*,r   partial_updateBotViewSet.partial_updatej  s"    --gUdUtUfUUr    c                2    V P                   ! V.VO5R R/VB # )rj  Frk  rm  s   &&*,r   updateBotViewSet.updatem  s"    --gVtVuVvVVr    c                    < V ^8  d   QhRS[ /# )r   rj  )r   )r   __classdict__s   "r   r   BotViewSet.__annotate__p  s     )8 )8$ )8r    c           
     ~  < VP                   P                  R 4      ;'       g    VP                  P                  R 4      pVP                  R4      pV'       EdT   VEeO    \        V4      p\	        V4       V R2p\
        R,          P                  4       ;_uu_ 4       p	V	P                  R\        V4       R24       V	P                   U
u0 uF  q^ ,          kK  	  pp
\        VP                   V4      pV'       g   V	P                  R\        V4       R2V.4       V	P                  4       pV'       g(   \        RR	/\        P                  R
7      uuRRR4       # V	P                   U
u. uF  q^ ,          NK  	  pp
\        \!        \#        W4      4      4      p\%        W.4       \        V4      uuRRR4       # RP'                  R V 4       4      p\)        VP+                  4       4      pVP-                  V4       V	P                  R\        V4       RV R2V4       V	P                  R\        V4       R2V.4       V	P                  4       pV	P                   U
u. uF  q^ ,          NK  	  pp
\        \!        \#        W4      4      4      p\%        W.4       \        V4      uuRRR4       # V'       d   \4        SV `l  ! V.VO5/ VB # \4        SV `p  ! V.VO5/ VB # u up
i u up
i u up
i   + '       g   i     LO; i  \.         d3   p\        RRR\1        T4      /\        P2                  R
7      u Rp?# Rp?ii ; i)r   r`  NrQ  r'  r&   LIMIT 0ra  rb  rc  rT  r$  c              3   >   "   T F  p\        V4       R 2x  K  	  R# 5i)z = %sNr   ).0r   s   & r   	<genexpr>7BotViewSet._update_cluster_or_master.<locals>.<genexpr>  s     )QAXa[M*?s   zUPDATE z SET rR  z Failed to update bot in cluster.rS  )datarr   rU  r,   r   r	   r,  r-  r   rL   r  rd  r   r
   re  r   rF   r/  rH  r*  r6   valuesr)  r=   r:   rV  rW  rn  rq  )rM  rX  rj  rY  rZ  rg  r`  r   r0  r7  r8  r   r  rD   r9  r   	set_partsvalsr\  r]  s   &&&*,              r   rl  $BotViewSet._update_cluster_or_masterp  s   ,,""=1\\W5I5I5M5Mm5\ZZ7r~"'l.s3%u +2244KK.%0A JK03!@1A$$J!@4W\\:NG"nXe_4EEW$X[]Z^_!lln"#+X|,DVMfMf#g 54 /2oo>o!o>"8c$n9M"N3CC'0 54 !%		)Q)Q QI 01DKKOKK!(5/!2%	{BTU KK.%0AAS TWYVZ[,,.C*-//:/QaDD/D:4T#d.5IJG/Y?#G,3 54> 7)'CDCFCCw~g7777? "A  ? ;- 544   BGSQRVT!@@ s    >K? -K,KA4K,
K? K,)K":5K,/
K? :B"K,K'-5K,"
K? K,,K<	7K? <K? ?L<
'L71L<7L<c           	       < VP                   P                  R 4      ;'       g    VP                  P                  R 4      pVP                  R4      pV'       d   Ve    \        V4      p\	        V4       V R2p\
        R,          P                  4       ;_uu_ 4       pVP                  R\        V4       R2V.4       RRR4       \        \        P                  R7      # \        S
V `@  ! V.VO5/ VB #   + '       g   i     L>; i  \         d3   p	\        RR	R
\        T	4      /\        P                  R7      u Rp	?	# Rp	?	ii ; i)r   r`  NrQ  r'  zDELETE FROM ra  rT  rR  z"Failed to delete bot from cluster.rS  )rU  rr   r}  r,   r   r	   r,  r-  r   r   r
   HTTP_204_NO_CONTENTr=   r:   rV  rW  destroy)rM  rX  rY  rZ  rg  r`  r   r0  r7  r\  r]  s   &&*,      r   r  BotViewSet.destroy  s   &&**=9\\W\\=M=Mm=\ZZr~'l.s3%u +2244KK,x.??Q RUWTXY 5v'A'ABB ww8888 54   DgsSTvV!@@ s6   >D !C3=!D 3D	>D E'D>8E>Ec                   V P                  VP                  R7      pVP                  RR7       VP                  P                  R4      pVR19  Ed    \	        V4      p\        T4       T R	2p\        R
,          P                  4       ;_uu_ 4       pTP                  R\        T4       R24       TP                   U	u0 uF  q^ ,          kK  	  p
p	RRR4       \!        \"        P$                  ! RR4      4      P'                  4       R29   pRpRp\!        TP(                  P                  R4      ;'       g&    TP                  P                  R4      ;'       g    R4      P+                  4       ;'       g    RpT'       Ed(    \-        T4      p\"        P$                  ! R4      p\"        P$                  ! R4      ;'       g    Rp\/        RTTT'       d"   \!        T4      P+                  4       '       d   TMR\	        \"        P$                  ! RR4      4      RR7      pTP                  R4      pT'       gu   \!        TP                  R4      ;'       g    R4      pRTP'                  4       9   d<   \1        4       pT'       d
   T^ ,          MR;'       g    \"        P$                  ! R4      p\5        TP                  4      pT'       d   TTR&   TTR&   \7        TTX
TP(                  4      pT'       g   \        R R!/\        P8                  R7      # \;        TP=                  4       4      pR"P?                  R#.\A        T4      ,          4      pR"P?                  R$ T 4       4      pR%\        T4       R&T R'T R(2p\        R
,          P                  4       ;_uu_ 4       pTP                  TT U	u. uF  p	TT	,          NK  	  up	4       TPB                  pTP                  R\        T4       R)2T.4       TPE                  4       pTP                   U	u. uF  q^ ,          NK  	  pp	RRR4       \G        \5        \I        XX4      4      4      p\K        TT.4       Te   R\M        TP                  R4      4      R*TP                  R*4      R+TP                  R+4      RTP                  R4      RTP                  R4      R,TP                  R,4      RTP                  R4      /TR-&   T PO                  T4      p\        T\        PP                  TR.7      # VPS                  4       p \U        V R/V/R07      P                  pV PO                  V4      p\        V\        PP                  VR.7      #   \
        \        3 d"    \        RR./\        P                  R7      u # i ; iu up	i   + '       g   i     EL; i  \2         d   pRRR\!        T4      /p Rp?EL#Rp?ii ; iu up	i u up	i   + '       g   i     EL; i)3z
With business_id: insert only into cluster `{business_id}_bots` (livekitvoicebot_cluster).
Without business_id: legacy create on master AgentConfig.
)r}  T)raise_exceptionr   NrN   zInvalid business_id.rT  rQ  r'  r&  rw  !LIVEKIT_AUTO_DEPLOY_ON_BOT_CREATEfalser   r   LIVEKIT_AGENT_SECRETS_FILELIVEKIT_AGENT_REGIONzus-eastrL  LIVEKIT_AGENT_CREATE_TIMEOUT_S1800)regionsecrets_file	timeout_ssilentr   stderrz maximum number of agents reachedLIVEKIT_FALLBACK_AGENT_IDokFrR  r   rb  z+Cluster bots table has no writable columns.r$  r%  c              3   8   "   T F  p\        V4      x  K  	  R # 5ir.   ry  )rz  r8  s   & r   r{  $BotViewSet.create.<locals>.<genexpr>  s     :TTs   zINSERT INTO z (z
) VALUES ()ra  	exit_codecommandstdoutlivekit_deploy)r
   headersrX  )contextr   )r#   r$   yeson)+get_serializerr}  is_validrr   r,   r/   r0   r   r
   HTTP_400_BAD_REQUESTr   r	   r,  r-  r   rL   r:   osgetenvr   validated_datars   r   r   r   r=   rF   r  rV  r6   keysr*  r+  	lastrowidrd  r   r/  rH  r   get_success_headersHTTP_201_CREATEDsaver   )!rM  rX  rY  rZ  
serializerbusiness_id_rawr   r0  r7  r8  r   auto_deploydeploy_infolivekit_agent_idr   workdirr  r  r  existingr\  request_for_rowrD   r9  r5  col_sqlr6  bot_pkfetchedout_colsr   r  bots!   &&*,                             r   rL  BotViewSet.create  s   
 ((gll(;
D1!,,**=9*,/* +3/e5MEY'..00CnXe_,=XFG,/OO<OqddO
< 1 bii(KWUV\\^ c K (,K+/J--11&9[[W\\=M=Mf=U[[Y[\bbd ! !   {C5h?G#%99-I#JLYY'=>KK)F". %5Ac,FWF]F]F_F_\ei"%bii0PRX&Y"Z##K (3z'B$+!$[__X%>%D%D"!E=O'C'EH?GT 0 0VXV_V_ ;W, #7<<0O.>
+,4OL)(#z:KdKdeCLM!@@ 
 
#D99dVc$i%78Lii:T::G % 1G9J|nTUVCY'..00CC$!7$Q#a&&$!78nXe_,==OPSYRZ[,,.*-//:/QaDD/: 1 -T#h2H-IJG'gY7&${t45!={y9
 ;{y9kooh7kooh7-() ..w7GGF,C,CWUU oo'i5IJOO**73(?(?QQA z* "%;$<=!66  = 100N ! C#'	3q6"BKC, "8 ; 100s   U -V>VV=V* ?BV* ?V* V* W'W9AW
WW/VVVV'	*W5W

W
WW-	Tpostzinitiate-call)rb  methodsurl_pathc                   VP                   ;'       g    / p\        VP                  R4      ;'       g5    VP                  R4      ;'       g    VP                  R4      ;'       g    R4      P                  4       pV'       g    \	        RRRR/\
        P                  R	7      # VP                  R
4      ;'       g    VP                  P                  R
4      p VR09  d   \        V4      MRpRp Ve/   \        P                  P                  VR7      P                  4       MRp\        VP                  R4      ;'       g$    VP                  R4      ;'       g    \        4       4      p\        \        P                   ! RR4      ;'       g    R4      P#                  R4      p	\        \        P                   ! RR4      ;'       g    R4      P#                  R4      p
\        \        P                   ! RR4      ;'       g    R4      p\        \        P                   ! RR4      ;'       g    R4      P                  4       p\        VP                  R4      ;'       g    R4      P                  4       pV'       g   V	'       d   V	 V 2p\        VP                  R4      ;'       g    R4      P                  4       pV'       g!   V
'       d   V
 VP#                  R4       RV 2p\        VP                  R4      ;'       g    R4      P                  4       pV'       g9   \        \%        VRR4      ;'       g    R4      P                  4       ;'       g    RpRVRVRV/pV'       d   VVR&   V'       d   VVR&   Ve    \        V4      VR&   Ve   VVR
&   V'       d   \%        VRR4      '       d'   \        VP&                  4      P                  4       VR&   \%        VRR4      '       d1   \        VP(                  4      P                  4       ;'       g    RVR &   \%        VR!R4      '       d'   \        VP*                  4      P                  4       VR"&   \        P                   ! R#R$4      p\-        \        P                   ! R%R&4      4      p \.        P0                  ! VR'7      ;_uu_ 4       pVP3                  VVR(7      pVP4                  '       d   VP7                  4       M/ pRRR4       XP:                  R19  d.   \	        RRRR+R,TP:                  R-X/\
        P8                  R	7      # \	        RR.RR/RTR-X/\
        P<                  R	7      #   \         d    Rp ELgi ; i  \         d    Rp ELDi ; i  \         d
    TTR&    ELi ; i  + '       g   i     L; i  \         d5   p\	        RRRR)R*\        T4      /\
        P8                  R	7      u Rp?# Rp?ii ; i)2z
Click-to-call entrypoint from the UI.

Expected body: { "customer_number": "...", "bot_id": "<pk>" }
Also accepts aliases used by other integrations: `to`, `custnumber`.
customer_number
custnumbertorN   successFrR  zcustomer_number is requiredrT  r   N)r   call_idrefidMCUBE_PUBLIC_BASE_URL/MCUBE_PUBLIC_WS_URL_BASEMCUBE_WEBHOOK_PATHz/webhooks/mcubeMCUBE_WS_PATH_PREFIXz/wscallback_urlrefurlr   r   r+   r   r  	exenumberr   r#   gidmcube_http_authorizationHTTP_AUTHORIZATIONMCUBE_OUTBOUND_CALL_URLz-http://127.0.0.1:8088/api/mcube/outbound-callMCUBE_OUTBOUND_CALL_TIMEOUT_S20)rQ   )r;   z$Failed to call outbound-call servicerS  z'Outbound-call service returned an errorhttp_statusresponseTzCall initiatedr   )      )r}  r:   rr   rs   r   r
   r  rU  r,   r=   r   objectsfilterr   r   r  r  rstripgetattrr  r   r  floathttpxClientr  contentr;   HTTP_502_BAD_GATEWAYstatus_codeHTTP_200_OK)rM  rX  r`  r}  r  r   business_id_intr  r  public_basepublic_ws_basewebhook_pathws_path_prefixr  r  r   r   	mcube_urlr  clientresp	resp_jsonr\  s   &&&                    r   initiate_callBotViewSet.initiate_call  s    ||!!r*+]]txx/E]]RV]][]^ddf 	 E9.KL22  hh}-XX1E1E1I1I-1X	#2=Z2Oc+.UYO
 #'	?A~+%%,,,399;SWC dhhy)IITXXg->II%'J"))$;R@FFBGNNsSRYY'A2FLL"MTTUXY299%9;LMbbQbcRYY'=uENNOUUW488N399r:@@B)]<.9LTXXh'--2.446.&'(=(=c(B'C1WINF,/5526<<>
WS&"5;;<BBDQQ	J /*w#

 &2GN# &GH >'$'G! &%4GM" s-r22'*3+>+>'?'E'E'G$sK,,!$S]]!3!9!9!;!B!Bss6;;03C4P4P0Q0W0W0Y,-II79hi	"))$CTJK		i00F{{97{;+/<<<DIIKR	 1 :-uH!4#3#3		 22  i)99gz[de%%
 	
g  	#"O	#  	C	L  '$&!'$ 10  	E9.TV]_bcd_ef22 	sr   U .4U 6U* V !8VV UUU'&U'*U>=U>V	V V W)WWWr&   r.   )__name__
__module____qualname____firstlineno____doc__r   r  allorder_byquerysetrN  r6   rf  rn  rq  rl  r  rL  r   r  __static_attributes____classdictcell____classcell__)r]  rt  s   @@r   rJ  rJ  -  s     
 ""&&(11&9H%
60:0VW)8 )8V9$lR\ 4&ODk
 Ek
 k
r    rJ  r.   )text_normalisation_typeoptimize_streaming_latencystreaming_latency_optimizationpronunciation_dictionary_path	stabilityspeed
similarity)<r;   r  uuidr   collectionsr   typingr   r   r   r   	django.dbr	   rest_frameworkr
   r   rest_framework.decoratorsr   rest_framework.responser   modelsr   serializersr   r   apps.cluster.dynamic_tablesr   r   apps.livekit.clir   r   r   r  r(   r1   r?   r~   r   r   r   r   r   r   rt   r   r   r   r   r   r   r   r   r   r  r  r  r?  rH  ModelViewSetrJ  r&   r    r   <module>r	     s     	  # , , ! + , ,  K P ` ` /hV	 $(VL
0 /F9RMl`Q&h!H=;@CL'TQ0Z
&& Z
r    