
    Rfvh8                       % S r SSKrSSKrSSKrSSKrSSKrSSKrSSK	r	SSK
Jr  SSKJrJrJrJrJrJrJrJrJrJrJrJrJrJrJrJrJrJrJrJ r   SSK!J"r"  SSK#J$r$  SSK%J&r&  SSK'r'SSK(r(SSK)J*r*  SS	K+J,r,  0 r-\$\.S
4   \/S'   Sr0\.\/S'   Sr1Sr2Sr3 " S S\"5      r4S\.S\5\.   4S jr6S\.4S jr7 " S S
5      r8\&SS\Rr                  S\.S-  4S jj5       r:g)u=  
Sessioni simultanee
Per impostazione predefinita, puoi avere fino a 10 sessioni simultanee per progetto.


https://ai.google.dev/gemini-api/docs/live?hl=it
https://cloud.google.com/vertex-ai/generative-ai/docs/live-api?hl=it
https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/multimodal-live?hl=it#limitations

Estensione della durata della sessione
https://ai.google.dev/gemini-api/docs/live?hl=it#extend-session-duration



Conteggio token
https://ai.google.dev/gemini-api/docs/live?hl=it#token-count


Rilevamento attività vocale (VAD)
https://ai.google.dev/gemini-api/docs/live?hl=it#voice-activity-detection


Gestione delle interruzioni
https://ai.google.dev/gemini-api/docs/live?hl=it#interruptions



-------------------------------------------------------------------------------------------------------------

conda activate avatar
cd /home/cirillo/Desktop/GEMINI/GEMINI_RETAIL22
uvicorn main:app --reload --host 0.0.0.0 --port 9102




APRI LA PAGINA index.html ed imposta la porta identica a quella che vedi qui
http://localhost:9102/static/index.html


-------------------------------------------------------------------------------------------------------------

AGGIORNARE I FILE SUL SERVER
il conda è gemini                   /root/miniconda3/envs/gemini

A2HOSTING
export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/:$LD_LIBRARY_PATH
ssh -p 7822 root@68.66.251.32
synap.si77
sudo systemctl restart uvicorn.service
sudo journalctl -u uvicorn.service -f


sudo systemctl daemon-reload
sudo systemctl restart fastapi-gemini
sudo systemctl status fastapi-gemini


    N)genai)LiveConnectConfigPrebuiltVoiceConfigSpeechConfigVoiceConfigAudioTranscriptionConfigToolFunctionResponseFunctionDeclarationStartSensitivityEndSensitivityCreateCachedContentConfigContextWindowCompressionConfigGenerateContentConfigSafetySettingThinkingConfigSlidingWindowPartSchemaContentType)Enum)Dict)asynccontextmanager)deque)cycleGeminiHandleractive_handlerszCONTESTO/categorie.jsonstructured_cache_namez#gemini-2.5-flash-lite-preview-06-17z3models/gemini-2.5-flash-preview-native-audio-dialogzrhttps://script.google.com/macros/s/AKfycbzFsHcVfZztV3zq4guPqAs_Gz-R2jYYVv0RfB4SsOjmsyCQFZxZTyegbAOKIWrdfmdyng/execc                   $    \ rS rSrSrSrSrSrSrg)SessionStateo   disconnected	listeningthinkingspeaking N)	__name__
__module____qualname____firstlineno__DISCONNECTED	LISTENINGTHINKINGSPEAKING__static_attributes__r'       %/var/www/html/gemini/gemini_module.pyr!   r!   o   s    !LIHHr1   r!   wordreturnc                    / SQ/ SQ/ SQ/ SQ/ SQSS/SS	/S
/SS/SS// SQSS/SS/SS/SS/S.nU R                  5       R                  SS5      R                  SS5      R                  SS5      R                  SS5      R                  SS5      R                  SS5      R                  SS5      R                  5       n/ nSnU[        U5      :  a  SnUR	                  5        HW  u  pg[        US  S!9 H:  nX$U[        U5      -    U:X  d  M  UR                  U5        U[        U5      -  nS"n  O   U(       d  MW    O   U(       d  UR                  X$   5        US#-  nU[        U5      :  a  M  U$ )$N)cecichechi)sciascioscisce)cchgghq)sssz)pbmdtfvrlglngn)e   è   éa   ài   ìo   òu   ù)CHSHkkSSPPDDFFRRLNNEaaihohourS   rR   rT   u   ’'r   Fc                     [        U 5      * $ N)len)xs    r2   <lambda>!map_to_phonemes.<locals>.<lambda>   s
    s1vgr1   )keyT   )lowerreplacestripro   itemssortedappend)	r3   phoneme_rules
normalizedphonemesrW   matchedvisemepatternspats	            r2   map_to_phonemesr   v   sv    ),)CjCjeDkDkDkDkDkDkM& 	

WT3c 27743EWT3c 27743EWUC 	  H	A
c*o
 - 3 3 5Fh,=>CH-4OOF+SMA"G ? w !6 OOJM*FA c*o
 Or1   	json_pathc                 8   [        U SSS9 n[        R                  " U5      nSSS5        / nWR                  5        HH  u  pEUR	                  [        UUS   [        [        R                  UR                  S0 5      S9S95        MJ     U$ ! , (       d  f       Nn= f)	za
Carica dal file JSON le specifiche di ogni funzione e
ritorna una lista di FunctionDeclaration.
rM   utf-8encodingNdescription
parameters)type
properties)namer   r   )
openjsonloadrx   rz   r   r   r   OBJECTget)r   rK   specsdeclarationsr   infos         r2   load_function_declarationsr      s    
 
iw	/1		! 
0 Lkkm
 /!#xxb9		
 $  
0	/s   B
Bc                   (   \ rS rSr/ SQrS%S\R                  S\S\4S jjr	S\
\\4   4S jrS	 rS&S
 jrS rS rS\\
\\4      4S jrS'S jrS\\
\\4      S\4S jrS rS(S\S\S\S\S\S\S\S\4S jjrS rS rS\SS 4S! jrS\4S" jrS#rg$))r      )ra   rg   Ord   rc   r`   r]   THrb   r_   rh   ri   rj   rk   re   rf   IUrg   silclient
voice_namesample_ratec                    Xl         X l        X0l        [        R                  " SS9U l        [        R                  " SS9U l        / U l        SU l        SU l	        SU l
        SU l        S U l        [        R                  " 5       U l        [        R                   U l        SU l        [&        R&                  R)                  5       U l        0 U l        [        R                  " 5       U l        / U l        [2        U l        [7        [8        SSS9 n[:        R<                  " U5      U l        S S S 5        S U l         [C        S	S
9U l"        [G        U RH                  5      U l%        SU l&        g ! , (       d  f       NE= f)Nd   )maxsizeFr    rM   r   r   
   )maxleng        )'r   r   output_sample_rateasyncioQueue
_raw_queue_chunk_queue_tasks_closed_total_audio_bytes
accum_textquestion_text_structured_jsonEvent
quit_eventr!   r,   session_statespeaker_muteddatetimeutcnow	last_seen_clients_outgoing_audio_queueaudio_chunks_bufferGOOGLE_SHEETendpointr   FUNCTIONS_CATEGORIES_PATHr   r   categorie_datalast_categoriar   chat_historyr   VALID_VISEMES_viseme_cycle_time_offset)selfr   r   r   rK   s        r2   __init__GeminiHandler.__init__   s2   $"- 18c0J 3:--2L +- (),0!--/ *66" -5,=,=,D,D,F 13 HO}}" ;=  %+S7Cq"&))A,D D"494D"4#5#56 DCs   
E%%
E3framec                 ^   #    Uu  p#U R                   R                  U5      I Sh  vN   g N7f)zW
(abbiamo ricevuto) AUDIO FRONTEND -> BACKEND (dove siamo) -> (dove lo inviamo) GEMINI
N)r   put)r   r   r   raws       r2   receiveGeminiHandler.receive   s)      ! oo!!#&&&s   #-+-c                b   #     U R                   R                  5       I Sh  vN nU7v   M)   N7f)zO
Generator asincrono che yielda i chunk a 16 kHz
prelevandoli da _chunk_queue.
N)r   r   )r   chunks     r2   _stream_generatorGeminiHandler._stream_generator  s.     
 ++//11EK 1s   /-/c                    U R                   n[        U5      S-  U-  nU=(       d    SU 3n[        U R                  5      n[	        U R
                  S5      n[	        U R
                  U-   S5      n	SSS[	        US5      USSXUS./XhU	S./XxU	S	./S
.n
[        S5        [        U
5        U =R
                  U-  sl        U
$ )z=
Crea un payload di visemi FALSO per un singolo chunk audio.
   chunk_viseme_phrase
transcribeitalianr   )idseekstartendtext)r3   r   r   )phonemer   r   )r   tasklanguagedurationr   segmentswordsr}   PAYLOAD)r   ro   nextr   roundr   print)r   index	raw_audior   r   r   r3   r   r   r   payloads              r2   assemble_chunk_payload$GeminiHandler.assemble_chunk_payload  s     --y>A%3'w'd(()d''+d''(2A6
 $ !h*!eN c: #3?
$ 	igX%r1   c                 J  #      U R                   R                  5       I Sh  vN u  pU R                  (       a  g[        R                  " U5      R                  S5      nU R                  XSS9nX4S'   XS'   [        U5      US'   SUS	'   [        R                  " U5      n[        U R                  R                  5       5       H  n UR                  U5      I Sh  vN   M     M   N N! [         a     M4  f = f! [        R                    a     g[         a     GM  f = f7f)
a@  
INVIO IMMEDIATO DELL'AUDIO RICEVUTO DA GEMINI AL FRONTEND
Ogni volta che qualcuno mette (index, raw_audio) in _outgoing_audio_queue,
estraggolo e costruisco il JSON come:
  { "type":"audio_chunk", "index":idx, "length":chunk_len, "audio":base64(raw_audio) }
e lo invio via ws.send_text(...) a tutti i WebSocket attivi.
Nr   ...r   audior   lengthr   r   )r   r   r   base64	b64encodedecoder   ro   r   dumpslistr   values	send_text	Exceptionr   CancelledError)r   idxr   b64chunkviseme_payloaddatawss          r2   _audio_senderGeminiHandler._audio_sender8  s     %'+'A'A'E'E'G!G <<
 "++I6==gF!%!<!<SRW!<!X +3w'*-w'+.y>x()8v& zz.1t}}3356B ll4000 73  "H0 1$  ))  s   D#C< C'C< D#BC< C+C)C+!C< %D#'C< )C++
C95C< 8C99C< <D D#	D D#D  D#c                 D  #    Sn / nU R                   R                  5        H=  u  p4UR                  SS5      R                  5       nUR	                  SU SU S35        M?     SR                  U5      nSU S3n[        U5        [        S/[        S	[        [        U R                  S
9S9S9[        5       [        5       [        [        R                  " US9/SS9[!        S[#        SS9S9SS[$        R&                  [(        R*                  SSS.0S9nU R,                  R.                  R0                  R3                  [4        US9 ISh  vN n	Sn
U	R7                  U R9                  5       SS9  Sh  vN nSnSnUR:                  (       Ga"  UR:                  R<                  (       Ga   UR>                  R@                  =(       d    SnUR>                  RB                  =(       d    SnSnSnSU l"        UR>                  RF                  (       am  UR>                  RF                   HS  nURH                  RJ                  S:X  a  URL                  nM+  URH                  RJ                  S:X  d  MG  URL                  nMU     [N        RP                  " U RS                  U RT                  WWUUUUSS 95         UR:                  RX                  RZ                  n[        S"UR:                  5        U =R\                  U-  sl.        S#n UR^                  nUR:                  R`                  b$  UR:                  R`                  n[        S$US%U5        [c        U5      nU =Rd                  U-  sl2        U Rf                  Ri                  UU45      I Sh  vN   US&-  nSn UR:                  R`                  RZ                  n[        S'UR:                  R`                  RZ                  5        W(       ar  [        S(5        U Rj                  R	                  SU R\                  R                  5       45        [N        RP                  " U Rm                  U Rj                  U	5      5        SnU(       a  U =Rn                  U-  sl7        SnS#n
OS#n U(       d  GM  U(       d  GM  U
(       d  GM)  [        S)5        [        S*U R\                  5        [        S+U Rn                  5        SU l2        U R\                  R                  5       nU Rn                  R                  5       nU Rj                  R	                  S,U Rn                  R                  5       45        SU l7        SU l.        / U l8        Sn
SnGM   GN GN! [V         a  n[        S!U5         SnAGNSnAff = f! [V         a     GNf = f GN! [V         a    S#n GNf = f! [V         a    S#n GNAf = f
 SSS5      ISh  vN    g! , ISh  vN  (       d  f       g= f! [N        Rr                   a    e [V         a  n[        S-U 35        e SnAff = f7f).z
Si connette a Gemini Live, accumula testo/audio e fa broadcast.
Restituisce correttamente al loop e tiene aperto l'async for.

default_api.get_exhibit_description()


r   descrizioner   z## 
u  
            Sei EVA, la guida virtuale dell’autosalone Tesla.

            Rispondi alle domande degli utenti **solo** in base alle informazioni presenti nella seguente Knowledge Base, adattando sempre lo stile e le istruzioni qui sotto.

            ────────────────────────────
            KNOWLEDGE BASE AUTOSALONE
            ────────────────────────────

            u{  

            ────────────────────────────
            ISTRUZIONI E STILE DI RISPOSTA
            ────────────────────────────

            - Usa **esclusivamente** le informazioni contenute nella Knowledge Base qui sopra per rispondere.
            - Se la domanda non trova risposta nella Knowledge Base, spiega gentilmente che non puoi aiutare su quell’argomento.
            - Se una domanda è personale (es. età, interessi), rispondi brevemente e riporta il discorso sui servizi dell’autosalone.
            - Le risposte devono essere sempre chiare, sintetiche, al massimo una frase non troppo lunga.
            - Evita dettagli inutili o argomenti non pertinenti.
            - Chiamati EVA se ti chiedono il nome, ma non aggiungere dettagli personali diversi da quelli consentiti.
            - Rispondi in modo accogliente e gentile.
            - Quando non hai informazioni, suggerisci di parlare con un consulente dello showroom.

            ────────────────────────────
            ESEMPI
            ────────────────────────────

            Utente: “Che orari fate?”  
            EVA: “Siamo aperti dal lunedì al venerdì dalle 9 alle 19, il sabato dalle 9 alle 13.”

            Utente: “Avete la Model Y?”  
            EVA: “Sì, la Model Y è disponibile in vari allestimenti presso il nostro showroom.”

            Utente: “Posso prenotare un test drive?”  
            EVA: “Certo! Puoi prenotare un test drive tramite telefono, email o sito.”

            Utente: “Vendete BMW?”  
            EVA: “Trattiamo solo veicoli Tesla.”

            Utente: “Cosa fai nel tempo libero?”  
            EVA: “Preferisco non parlare di me. Vuoi sapere qualcosa sui nostri servizi Tesla?”

            ────────────────────────────

            **Rispondi sempre attenendoti alle informazioni della Knowledge Base.**

            AUDIOzit-IT)r   )prebuilt_voice_config)language_codevoice_configr   user)partsrolei  i  )target_tokens)trigger_tokenssliding_windowautomatic_activity_detectionF   r   )disabledstart_of_speech_sensitivityend_of_speech_sensitivityprefix_padding_mssilence_duration_ms)response_modalitiesspeech_configoutput_audio_transcriptioninput_audio_transcriptionsystem_instructioncontext_window_compressionrealtime_input_config)modelconfigNz	audio/pcm)stream	mime_typeTEXTFoglio1)endpoint_urlquestionresponseprompt_tokensresponse_audio_tokensresponse_text_tokenstotal_tokens
sheet_nameu0   ❌ 22 - Errore durante l'invio al Google Sheet:zTEXT INPUT: Tz+ AUDIO OUTPUT: z  --  rt   z- TEXT OUTPUT: z&Lancio background_structured_and_speakz'+++++++++ ALL DONE! *******************z	DOMANDA: z
RISPOSTA: agentz%[GeminiHandler.run] Errore inatteso: ):r   rx   r   rw   rz   joinr   r   r   r   r   r   r   r   r   	from_textr   r   r   START_SENSITIVITY_LOWr   END_SENSITIVITY_LOWr   aioliveconnectGEMINI_LIVEAUDIO_modelstart_streamr   server_contentturn_completeusage_metadataprompt_token_counttotal_token_countr   response_tokens_detailsmodalityr   token_countr   create_tasksend_to_google_sheetr   r   input_transcriptionr   r   r   output_transcriptionro   r   r   r   r   _call_structured_and_speakr   r   r   )r   r   kb_sectionsrs   r   r  full_kb_textPROMPTr  sessionsendr#  no_audiono_transcriptr$  r'  r%  r&  rH   r"  response_textrR   text_inai2r   transcription_obj	chunk_len
transcripts                               r2   runGeminiHandler.runj  s     B	@ K!00668	"hh}b9??A""SR}B#?@ 9
  99[1L	 N &/Fd &M '%,I*")!,.A'+/" ,D+E*B*D#*>>v67f$
 ,J'+'44'H,
 3$)7G7]7]5C5W5W-//25)-FB {{++33,V 4 > >AH '.&:&:$BXBXBZfq&:&r H"(  %H$)M   ...83J3J3X3X3XY,4,C,C,V,V,[Z[M+3+B+B+T+T+YXYL45134001D-'66NN)1)@)@)X)XA'(zz''A@A(=)*F)B?@}}(<	 *Y $// $ 9 915-5-:2?:O9M1=/8 !: 	!"$"*"9"9"M"M"R"Rnh.E.EF**g5*"( %-MM	#22GGS080G0G0\0\-!"46GS\]$'	N	 //9</ #88<<eY=OPPP
#(-%-%<%<%Q%Q%V%V
/1H1H1]1]1b1bc!"JK --44fd>P>P>V>V>X5YZ#//0O0OPTPaPacj0kl"'C% OOz9O,1M#'D,0M  xMMddGHk4+=+=>lDOO< 34/
 $(#5#5#;#;#=(,(=(=(?))00'4??;P;P;R1ST +--/*350$ !_>H"d  ) Y!"TVWXXY % * Q % (#'(* % -(,-W 's> > >d e> > >d %% 	 	9!=>	sU  X EW+ 	U
W+ !W.V>2U3V>63W*B=U +AU 0AV>BVVVC#V+5W6V+8WWWCWW+ V> 
V*U<6W<VW
VWVWVV($W'V((W+V;7W:V;;W?W+ 
WW+ X W(WW($W+ 'X (W+ +X	XXX historyc                   ^ ^#    [         R                  " 5       nUR                  S UU 4S j5      I S h  vN n [        R                  " U5      nS n[        T5       H  u  pxUS:X  d  M  Un  O   Ub  SU;  d
  US   (       d  Sn	U=(       d    SU	S.T l        O+US   S   R                  S	S
5      n	U=(       d    SU	S.T l        T R                  T5      I S h  vN n
[        S5        [        T5        [        S5        [        SU	5        [        ST R                  5        S T l        g  N! [
         a  n[        SU5        S n S nANS nAff = f Nv7f)Nc                  &   > TR                  T 5      $ rn   )_sync_generate_structured)rO  r   s   r2   rq   :GeminiHandler._call_structured_and_speak.<locals>.<lambda>  s    D227;r1   u   ❌ Errore nel parsing JSON:r  rispostenoner   )domanda	categoriar   rW  categoria_mancantez----------------------------zCATEGORIA: zPREV CATEGORIA: )r   get_running_looprun_in_executorr   loadsr   r   reversedr   r   wait_for_last_agentr   )r   rO  rC  loopr   rR   ultima_domanda_utenter	  r   rW  ultima_risposta_agents   ``         r2   r?  (GeminiHandler._call_structured_and_speak  sN    '')((;
 

	**S/C !%"7+JDv~(,% ,
 ;*C/s:I06B&%D!
 J*..{<PQI06B&%D! '+&>&>w&G G,-g,-mY' $"5"56V !%e
  	0!4C	4 !HsL   0ED(ED* E*A.EEAE*
E4EEEEc                    #    SnXC:  aD  U(       a  US   S   S:X  a  US   S   $ [         R                  " U5      I Sh  vN   XB-  nXC:  a  MD  g N7f)z;
Attende che l'ultimo turno della history sia dell'agente.
r   r)  rt   NT)r   sleep)r   rO  check_intervaltimeoutwaiteds        r2   r]  !GeminiHandler.wait_for_last_agent  s^      72;q>W4r{1~%--///$F	   0s   <AAAAr4   c                    S/nU H5  u  p4US:X  a  UR                  SU 35        M!  UR                  SU 35        M7     SR                  U5      n[        S5        [        U5        [        S[        R
                  " US9/S9/n[        [        [        S	S
9[        SSS9[        SSS9[        SSS9[        SSS9/S[        [        R                  S/S[        [        R                  [        [        R                  S/S[        [        R                  S90S9S90S9S9nU R                  R                   R#                  [$        UUS9nUR&                  R)                  5       $ )zR
Prende gli ultimi N turni della conversazione e li invia al modello strutturato.
zConversazione:r  zUtente: zAgente: r  CONVERSATIONr   )r	  r  r   )thinking_budgetHARM_CATEGORY_HARASSMENTBLOCK_MEDIUM_AND_ABOVE)category	thresholdHARM_CATEGORY_HATE_SPEECHHARM_CATEGORY_SEXUALLY_EXPLICITHARM_CATEGORY_DANGEROUS_CONTENTzapplication/jsonrT  rW  )r   )r   requiredr   )r   rx   )cached_contentthinking_configsafety_settingsresponse_mime_typeresponse_schema)r  contentsr  )rz   r*  r   r   r   r+  r   r   r   r   r   r   r   ARRAYSTRINGr   modelsgenerate_contentGEMINI_modelr   rw   )	r   rO  conversation_linesr	  r   conversation_strry  cfgr#  s	            r2   rR  'GeminiHandler._sync_generate_structured+  ss   
 //!JDv~"))HTF*;<"))HTF*;<	 "
  99%78n <L(M'NO
 $0 +1= 'AMef'BNfg'HTlm'HTlm	  2"[[$!ZZ$!%&1] +V-E(
!
@ ;;%%66 7 

 }}""$$r1   c                 :  #     Sn[         R                  " / [         R                  S9n U R                  R	                  5       I Sh  vN n[         R
                  " U[         R                  S9n[         R                  " X$/5      n[        U5      nXQ-  nXFU-  S n[        U5       HC  nXGU-  US-   U-   nUR                  5       n	U R                  R                  U	5      I Sh  vN   ME     M   N N! [        R                   a    e [         a  n
e Sn
A
ff = f7f)z
(abbiamo ricevuto) AUDIO FRONTEND -> BACKEND (dove siamo) -> (dove lo inviamo) GEMINI
Preleva i buffer raw (48 kHz) da _raw_queue,
li converte a 16 kHz, li spezza in chunk da 960 sample,
e li mette in _chunk_queue.
i  )dtypeNrt   )nparrayint16r   r   
frombufferconcatenatero   rangetobytesr   r   r   r   r   )r   
chunk_sizeresidualr   arr16totaln_chunksrW   r   	raw_chunkrR   s              r2   
feed_audioGeminiHandler.feed_audio  s    $	Jxx"((3H OO//11 c: '89E
 . J!6!89 xA!j.AEZ3GHE %I++//	:::	 )- 10 ;%% 	 		sB   DAC4 C0BC4 %C2&C4 2C4 4DDDDr!  r"  r#  r$  r%  r&  r'  r(  c	                 j  #    [         R                   R                  5       R                  S5      n	S n
SR                  U	[	        U5      [	        U5      [	        U5      [	        U5      U
" U5      U
" U5      /5      nU SU 3n [
        R                  " 5        ISh  vN nUR                  XSS0S9I Sh  vN nUR                  S	:X  a  [        S
5        SSS5      ISh  vN   g NJ N2 N	! , ISh  vN  (       d  f       g= f! [         a  n[        S[	        U5      5         SnAgSnAff = f7f)z
Invia un record al Google Sheet via Apps Script:
Data, Tokens_prompt, Tokens_response_audio, Tokens_response_text, Tokens_total, Domanda, Risposta
z%Y-%m-%d %H:%M:%Sc                 b    U R                  SS5      R                  SS5      R                  5       $ )N, r  )rv   rw   )rC   s    r2   rq   4GeminiHandler.send_to_google_sheet.<locals>.<lambda>  s%    !))C-55dC@FFHr1   r  z?sheet=NzContent-Typez
text/plain)urlcontentheaders   u)   ✅ Riga inviata al Google Sheet (async).u+   ❌ Errore durante l'invio al Google Sheet:)r   nowstrftimer*  strhttpxAsyncClientpoststatus_coder   r   )r   r!  r"  r#  r$  r%  r&  r'  r(  now_strcleancsv_payloadr  r   resrR   s                   r2   r<  "GeminiHandler.send_to_google_sheet  s    
 ##'')223FG Ihh%&$%(O(O 
  gj\2	I((**f"KK><:X (   ??c)EF +** +***  	I?QHH	Is   B D3D C'D  C-6C)7C-D !C+"D &D3'D )C-+D -D3C64D D D3D 
D0D+&D3+D00D3c                 8    U R                   R                  5         g rn   )r   clear)r   s    r2   reset_historyGeminiHandler.reset_history  s    !r1   c                   #    U R                  5         U R                  (       a  gSU l        U R                   H  nUR                  5         M     [        R
                  " U R                  SS06I Sh  vN   U R                  R                  5       (       d<   U R                  R                  5         U R                  R                  5       (       d  M<  U R                  R                  5       (       d=   U R                  R                  5         U R                  R                  5       (       d  M<  gg N! [         a     Ml  f = f! [         a     gf = f7f)zU
Cancella i singoli Task creati, poi svuota le due code (_raw_queue e _chunk_queue).
NTreturn_exceptions)r  r   r   cancelr   gatherr   empty
get_nowaitr   r   )r   rJ   s     r2   acloseGeminiHandler.aclose  s
    
 	<< AHHJ  nndkkBTBBB //''))**, //'')) ##))++!!,,. ##))++ 	C    sf   A0E2D/3#ED1 1EE2E E-E1
D?;E>D??E
EEEE	client_idr   	WebSocketc                      X R                   U'   g rn   )r   )r   r  r   s      r2   register_wsGeminiHandler.register_ws  s    #%i r1   c                 <    U R                   R                  US 5        g rn   )r   pop)r   r  s     r2   unregister_wsGeminiHandler.unregister_ws  s    )T*r1   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   N)Aoedei]  )r   )g?g       @)r   )r(   r)   r*   r+   r   r   Clientr  intr   tuplebytesr   r   r   r   rM  r   r?  r]  rR  r  r<  r  r  r  r  r0   r'   r1   r2   r   r      s&    GM1 u|| 1  1 UX 1 f
'5e#4 
'%N/dNr
U%eCHo8N U%r:%uS#X1G :%C :%n+^Is IS ITW Ihk I  EH I  `c I  sv I  DG I@"@&S &k &+s +r1   r   
session_idc                   #    [        U 5      n[        R                  " 5       nU IS h  vN    UR                  UR	                  5       5      nUR                  UR                  5       5      nUR                  UR                  5       5      nXEU/Ul        Ub,  U[        U'   [        R                  R                  5       Ul        U7v   UR                  5       I S h  vN   U(       a  U[        ;   a  [        R                  U5        S S S 5      IS h  vN   g  N N=! UR                  5       I S h  vN    U(       a!  U[        ;   a  [        R                  U5        f f f = f NO! , IS h  vN  (       d  f       g = f7frn   )r   r   	TaskGroupr;  rM  r  r   r   r   r   r   r   r  r  )r   r  handlertgt1t2t3s          r2   connect_geminir    s    F#G				B r	0.B 2 2 45B 5 5 78B b\GN %.5
+$,$5$5$<$<$>! M .."""jO;##J/) rr$ #'.."""jO;##J/ <z' rrrsz   'E>DE>E$BD	E$D*E$E>E"E>E$E0D3
1.EE$"E>$E;*E-+E;7E>rn   );__doc__r   r   r   r   numpyr  scipy.signalscipyr  googler   google.genai.typesr   r   r   r   r   r	   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   enumr   typingr   
contextlibr   pathlibrecollectionsr   	itertoolsr   r   r  __annotations__r   r~  r1  r   r!   r   r   r   r   r  r  r'   r1   r2   <module>r     s   :|        
 
 
 
 
 
*   *  	   /1c?*+ 05  2L  D4 ,# ,$s) ,`# @s+ s+p 0 03: 0 0HYr1   