
    avh8                       U d Z ddlZddlZddlZddlZddlZddlZddl	Z	ddl
mZ ddlmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZm Z  ddl!m"Z" ddl#m$Z$ ddl%m&Z& ddl'Z'ddl(Z(ddl)m*Z* dd	l+m,Z, i Z-e$e.d
f   e/d<   dZ0e.e/d<   dZ1dZ2dZ3 G d de"      Z4de.de5e.   fdZ6de.fdZ7 G d d
      Z8e&ddejr                  de.dz  fd       Z:y)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                       e Zd ZdZdZdZdZy)SessionStatedisconnected	listeningthinkingspeakingN)__name__
__module____qualname__DISCONNECTED	LISTENINGTHINKINGSPEAKING     =/home/cirillo/Desktop/GEMINI/GEMINI_RETAIL24/gemini_module.pyr!   r!   o   s    !LIHHr.   r!   wordreturnc                    g dg dg dg dg dddgdd	gd
gddgddgg dddgddgddgddgd}| j                         j                  dd      j                  dd      j                  dd      j                  dd      j                  dd      j                  dd      j                  dd      j                         }g }d}|t        |      k  rd}|j	                         D ]S  \  }}t        |d  !      D ]9  }|||t        |      z    |k(  s|j                  |       |t        |      z  }d"} n |sS n |s|j                  ||          |d#z  }|t        |      k  r|S )$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ourP   rO   rQ   u   ’'r   Fc                     t        |        S N)len)xs    r/   <lambda>z!map_to_phonemes.<locals>.<lambda>   s    s1vg r.   )keyT   )lowerreplacestriprl   itemssortedappend)	r0   phoneme_rules
normalizedphonemesrT   matchedvisemepatternspats	            r/   map_to_phonemesr~   v   s    ),)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 	FHh,=> aCH-4OOF+SMA"G 	 OOJqM*FA c*o
 Or.   	json_pathc                 <   t        | dd      5 }t        j                  |      }ddd       g }j                         D ]N  \  }}|j	                  t        ||d   t        t        j                  |j                  di                          P |S # 1 sw Y   nxY w)	zm
    Carica dal file JSON le specifiche di ogni funzione e
    ritorna una lista di FunctionDeclaration.
    rJ   utf-8encodingNdescription
parameters)type
properties)namer   r   )
openjsonloadrt   rv   r   r   r   OBJECTget)r   rH   specsdeclarationsr   infos         r/   load_function_declarationsr      s    
 
iw	/ 1		! Lkkm 


d /!#xxb9		


  s   BBc                   
   e Zd Zg dZd#dej
                  dedefdZde	ee
f   fdZd Zd$d	Zd
 Zd Zdee	eef      fdZd%dZdee	eef      defdZd Zd&dedededededededefdZd Zd Zdeddfd Zdefd!Zy")'r   )r^   rd   Ora   r`   r]   rZ   THr_   r\   re   rf   rg   rh   rb   rc   IUrd   silclient
voice_namesample_ratec                    || _         || _        || _        t        j                  d      | _        t        j                  d      | _        g | _        d| _        d| _	        d| _
        d| _        d | _        t        j                         | _        t        j                   | _        d| _        t&        j&                  j)                         | _        i | _        t        j                         | _        g | _        t2        | _        t7        t8        dd      5 }t;        j<                  |      | _        d d d        d | _         tC        d	
      | _"        tG        | jH                        | _%        d| _&        y # 1 sw Y   CxY w)Nd   )maxsizeFr    rJ   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   rH   s        r/   __init__zGeminiHandler.__init__   s=   $"- 18c0J 3:--2L +- (),0!--/ *66" -5,=,=,D,D,F 13 HO}}" ;=  %+S7C 	/q"&))A,D	/"494D"4#5#56	/ 	/s   E//E8framec                 `   K   |\  }}| j                   j                  |       d{    y7 w)zg
        (abbiamo ricevuto) AUDIO FRONTEND -> BACKEND (dove siamo) -> (dove lo inviamo) GEMINI
        N)r   put)r   r   r   raws       r/   receivezGeminiHandler.receive   s,      !S oo!!#&&&s   $.,.c                `   K   	 | j                   j                          d{   }| (7 
w)zg
        Generator asincrono che yielda i chunk a 16 kHz
        prelevandoli da _chunk_queue.
        N)r   r   )r   chunks     r/   _stream_generatorzGeminiHandler._stream_generator  s/     
 ++//11EK 1s   .,.c                 |   | j                   }t        |      dz  |z  }|xs d| }t        | j                        }t	        | j
                  d      }t	        | j
                  |z   d      }	dddt	        |d      |dd||	|dg|||	dg|||	d	gd
}
t        d       t        |
       | xj
                  |z  c_        |
S )zM
        Crea un payload di visemi FALSO per un singolo chunk audio.
           chunk_viseme_phrase
transcribeitalianr   )idseekstartendtext)r0   r   r   )phonemer   r   )r   tasklanguagedurationr   segmentswordsry   PAYLOAD)r   rl   nextr   roundr   print)r   index	raw_audior   r   r   r0   r{   r   r   payloads              r/   assemble_chunk_payloadz$GeminiHandler.assemble_chunk_payload  s     --y>A%3'w'd(()d''+d''(2A6
 $ !h*!eCN c: #U3?
$ 	igX%r.   c                 <  K   	 	 | j                   j                          d{   \  }}| j                  ryt        j                  |      j                  d      }| j                  ||d      }||d<   ||d<   t        |      |d<   d|d	<   t        j                  |      }t        | j                  j                               D ]  }	 |j                  |       d{     	 7 7 
# t        $ r Y 0w xY w# t        j                   $ r Y yt        $ r Y w xY ww)
ap  
        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   rl   r   dumpslistr   values	send_text	Exceptionr   CancelledError)r   idxr   b64chunkviseme_payloaddatawss          r/   _audio_senderzGeminiHandler._audio_sender8  s(     %'+'A'A'E'E'G!GY <<
 "++I6==gF!%!<!<S)RW!<!X +3w'*-w'+.y>x()8v& zz.1t}}3356 B ll40003  "H0 1$  ))  s   DC8 C%C8 DBC8 C)C'C)!C8 #D%C8 'C))	C52C8 4C55C8 8DDDDDDc                   K   d}	 g }| j                   j                         D ]=  \  }}|j                  dd      j                         }|j	                  d| d| d       ? dj                  |      }d| d}t        |       t        dgt        d	t        t        | j                  
                  t               t               t        t        j                  |      gd      t!        dt#        d            ddt$        j&                  t(        j*                  dddi      }| j,                  j.                  j0                  j3                  t4        |      4 d{   }	d}
|	j7                  | j9                         d      2 3 d{   }d}d}|j:                  r	|j:                  j<                  r	 |j>                  j@                  xs d}|j>                  jB                  xs d}d}d}d| _"        |j>                  jF                  rg|j>                  jF                  D ]N  }|jH                  jJ                  dk(  r|jL                  })|jH                  jJ                  dk(  sC|jL                  }P tO        jP                  | jS                  | jT                  ||||d              	 |j:                  jX                  jZ                  }t        d"|j:                         | xj\                  |z  c_.        d#}	 |j^                  }|j:                  j`                  $|j:                  j`                  }t        d$|d%|       tc        |      }| xjd                  |z  c_2        | jf                  ji                  ||f       d{    |d&z  }d}	 |j:                  j`                  jZ                  }t        d'|j:                  j`                  jZ                         rqt        d(       | jj                  j	                  d| j\                  j                         f       tO        jP                  | jm                  | jj                  |	             d}|r| xjn                  |z  c_7        d}d#}
nd#}|s|s|
st        d)       t        d*| j\                         t        d+| jn                         d| _2        | j\                  j                         }| jn                  j                         }| jj                  j	                  d,| jn                  j                         f       d| _7        d| _.        g | _8        d}
d}7 7 # tV        $ r}t        d!|       Y d}~d}~ww xY w# tV        $ r Y rw xY w7 # tV        $ r d#}Y w xY w# tV        $ r d#}Y *w xY w6 ddd      d{  7   y# 1 d{  7  sw Y   yxY w# tN        jr                  $ r  tV        $ r}t        d-|         d}~ww xY ww).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  --  rp   z- TEXT OUTPUT: z&Lancio background_structured_and_speakz'+++++++++ ALL DONE! *******************z	DOMANDA: z
RISPOSTA: agentz%[GeminiHandler.run] Errore inatteso: ):r   rt   r   rs   rv   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_transcriptionrl   r   r   r   r   _call_structured_and_speakr   r   r   )r   r   kb_sectionsro   r   r   full_kb_textPROMPTr  sessionsendr  no_audiono_transcriptr  r  r  r  rE   r  response_textrO   text_inai2r   transcription_obj	chunk_len
transcripts                               r/   runzGeminiHandler.runj  s     B	@ K!00668 A	T"hh}b9??A""SR}B#?@A
  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 > O" O"AH '.&:&:$BXBXBZfq&:&r H" H"(  %H$)M   ..83J3J3X3XY,4,C,C,V,V,[Z[M+3+B+B+T+T+YXYL45134001D-'66NN)1)@)@)X)X !MA'(zz''A@A(=)*F)B?@}}(<	!M $// $ 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  MdGHk4+=+=>lDOO< 34/
 $(#5#5#;#;#=(,(=(=(?))00'4??;P;P;R1ST +--/*350$ !_O"H"d  ) Y!"TVWXXY % * Q % (#'(* % -(,-W 'sO" O" O"d eO" O" O"d %% 	 	9!=>	sI  W3EW  "T8#W  &$V+
VT;V(V+;B-T>)AT>.AU!<BU4U1U4CV*V+.V+2V+6CV+8W  ;V>	UUV+UV+!	U.*V+-U..V+1U44V?V+VV+VV+VV+W  $V'%W  *W3+V=1V42V=9W  <W3=W   W0W++W00W3historyc                 v   K   t        j                         }|j                  d  fd       d {   }	 t        j                  |      }d }t              D ]  \  }}|dk(  s|} n |	d|vs|d   sd}	|xs d|	d _        n&|d   d   j                  d	d
      }	|xs d|	d _         j                         d {   }
t        d       t               t        d       t        d|	       t        d j                         d  _        y 7 # t
        $ r}t        d|       d }Y d }~d }~ww xY w7 uw)Nc                  &    j                         S rk   )_sync_generate_structured)rD  r   s   r/   rn   z:GeminiHandler._call_structured_and_speak.<locals>.<lambda>  s    D227; r.   u   ❌ Errore nel parsing JSON:r   rispostenoner   )domanda	categoriar   rK  categoria_mancantez----------------------------zCATEGORIA: zPREV CATEGORIA: )r   get_running_looprun_in_executorr   loadsr   r   reversedr   r   wait_for_last_agentr   )r   rD  r9  loopr   rO   ultima_domanda_utenter   r   rK  ultima_risposta_agents   ``         r/   r5  z(GeminiHandler._call_structured_and_speak  sV    '')((;
 

	**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   .D9DD9D D9&AD9D7AD9	D4D/*D9/D44D9c                    K   d}||k  r=|r|d   d   dk(  r|d   d   S t        j                  |       d{    ||z  }||k  r=y7 w)zK
        Attende che l'ultimo turno della history sia dell'agente.
        r   r  rp   NT)r   sleep)r   rD  check_intervaltimeoutwaiteds        r/   rQ  z!GeminiHandler.wait_for_last_agent  se      w72;q>W4r{1~%--///n$F	 w  0s   5A
AA
A
r1   c                 
   dg}|D ]3  \  }}|dk(  r|j                  d|         |j                  d|        5 dj                  |      }t        d       t        |       t        dt	        j
                  |      g      g}t        t        t        d	
      t        dd      t        dd      t        dd      t        dd      gdt        t        j                  dgdt        t        j                  t        t        j                  dgdt        t        j                        i            i            }| j                  j                   j#                  t$        ||      }|j&                  j)                         S )zb
        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/jsonrH  rK  )r   )r   requiredr   )r   rt   )cached_contentthinking_configsafety_settingsresponse_mime_typeresponse_schema)r  contentsr  )rv   r   r   r   r   r!  r   r   r   r   r   r   r   ARRAYSTRINGr   modelsgenerate_contentGEMINI_modelr   rs   )	r   rD  conversation_linesr   r   conversation_strrk  cfgr  s	            r/   rG  z'GeminiHandler._sync_generate_structured+  sz   
 //! 	=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 

 }}""$$r.   c                 >  K   	 d}t        j                  g t         j                        }	 | j                  j	                          d{   }t        j
                  |t         j                        }t        j                  ||g      }t        |      }||z  }|||z  d }t        |      D ]C  }|||z  |dz   |z   }|j                         }	| j                  j                  |	       d{    E 7 7 	# t        j                  $ r  t        $ r}
 d}
~
ww xY ww)a   
        (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  )dtypeNrp   )nparrayint16r   r   
frombufferconcatenaterl   rangetobytesr   r   r   r   r   )r   
chunk_sizeresidualr   arr16totaln_chunksrT   r   	raw_chunkrO   s              r/   
feed_audiozGeminiHandler.feed_audio  s    $	Jxx"((3H OO//11 c: %'89E
 J. J!6!89 x ;A!!j.AEZ3GHE %I++//	:::	;- 10 ;%% 	 		sB   DAC8 	C4
B"C8 ,C6-C8 6C8 8DDDDr  r  r  r  r  r  r  r  c	                 b  K   t         j                   j                         j                  d      }	d }
dj                  |	t	        |      t	        |      t	        |      t	        |       |
|       |
|      g      }| d| }	 t        j                         4 d{   }|j                  ||ddi       d{   }|j                  d	k(  rt        d
       ddd      d{    y7 M7 17 	# 1 d{  7  sw Y   yxY w# t        $ r}t        dt	        |             Y d}~yd}~ww xY ww)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    | j                  dd      j                  dd      j                         S )N, r   )rr   rs   )r@   s    r/   rn   z4GeminiHandler.send_to_google_sheet.<locals>.<lambda>  s'    !))C-55dC@FFH r.   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   resrO   s                   r/   r2  z"GeminiHandler.send_to_google_sheet  s:    
 ##'')223FG Ihh%&$%(O(O 
  gj\2	I((* G Gf"KK[><:X (   ??c)EFG G GG G G G  	I?QHH	Is   B D/D C)D C/9C+:C/D #C-$D (D/)D +C/-D /D5C86D=D  D/D 	D,D'"D/'D,,D/c                 8    | j                   j                          y rk   )r   clear)r   s    r/   reset_historyzGeminiHandler.reset_history  s    !r.   c                 f  K   | j                          | j                  ryd| _        | j                  D ]  }|j                           t	        j
                  | j                  ddi d{    | j                  j                         s6	 | j                  j                          | j                  j                         s6| j                  j                         s7	 | j                  j                          | j                  j                         s6yy7 # t        $ r Y _w xY w# t        $ r Y yw xY ww)ze
        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   rG   s     r/   aclosezGeminiHandler.aclose  s    
 	<<  	AHHJ	 nndkkBTBBB //'')**, //'') ##))+!!,,. ##))+ 	C    sf   A(D1*D+D1
D $D1?D1D" 4D1D1	DD1DD1"	D.+D1-D..D1	client_idr   	WebSocketc                 "    || j                   |<   y rk   )r   )r   r  r   s      r/   register_wszGeminiHandler.register_ws  s    #%i r.   c                 <    | j                   j                  |d        y rk   )r   pop)r   r  s     r/   unregister_wszGeminiHandler.unregister_ws  s    )T*r.   N)Aoedei]  )r   )g?g       @)r  )r&   r'   r(   r   r   Clientr  intr   tuplebytesr   r   r   r   rC  r   r5  rQ  rG  r  r2  r  r  r  r  r-   r.   r/   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 +r.   r   
session_idc                  K   t        |       }t        j                         }|4 d {    	 |j                  |j	                               }|j                  |j                               }|j                  |j                               }|||g|_        |,|t        |<   t        j                  j                         |_        | |j                          d {    |r|t        v rt        j                  |       	 d d d       d {    y 7 7 7# |j                          d {  7   |r|t        v rt        j                  |       w w w xY w7 H# 1 d {  7  sw Y   y xY wwrk   )r   r   	TaskGroupr1  rC  r  r   r   r   r   r   r   r  r  )r   r  handlertgt1t2t3s          r/   connect_geminir    s5    F#G				B  0 0	0.B 2 2 45B 5 5 78B "b\GN %.5
+$,$5$5$<$<$>! M .."""jO;##J/)0 0 0$ #'.."""jO;##J/ <z'0 0 0 0sz   &E+DE+EBDED$E E+EE+EE)D,
*'EEE+E(EE($E+rk   );__doc__r   r   r   r   numpyrv  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   rp  r'  r   r!   r   r~   r   r   r  r  r-   r.   r/   <module>r     s   :|        
 
 
 
 
 
*   *  	   /1c?*+ 05  2L  D4 ,# ,$s) ,`# @s+ s+p 0 03: 0 0HYr.   