Ë
    ãß²jÇx  ã                  ó†  — d Z ddlm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
mZ ddlmZ ddlmZmZmZ ddlmZ ddlmZmZmZmZ dd	lmZ  ej6                  d
«      ZdZdZdZdZ dZ!dZ"dZ#dZ$dZ%dZ&dZ'dZ(dZ)dZ*dZ+dZ,dZ-dZ.dZ/dZ0dZ1dZ2dZ3d Z4dZ5d!Z6d"Z7d#Z8h d$£Z9h d%£Z:dUdVd&„Z;dWd'„Z<dXd(„Z=dYd)„Z>dZd*„Z?dd+œd[d,„Z@d\d-„ZAdd+œd]d.„ZBd^d/„ZCd_d0„ZDd`d1„ZEd2ZFd3ZG	 	 	 	 	 	 	 	 	 	 	 	 	 	 dad4„ZHdbd5„ZIdcd6„ZJdbd7„ZKd8ZLd9ZM ejœ                  d:d;jŸ                  eL«      › d<d;jŸ                  eM«      › d=�ej                   ¬>«      ZQ ejœ                  d?ej¤                  ¬>«      ZSddd@„ZTdedA„ZUdbdB„ZV e
dC¬D«       G dE„ dF«      «       ZWe#e$dGœZX eYdHdIh«       eYdJh«      dGœZZdfdK„Z[dgdL„Z\dbdM„Z]dbdN„Z^dhdO„Z_didP„Z`djdkdQ„ZadldmdR„Zbd`dS„ZcdbdT„Zdy)naô  Cloud TTS backends for ``tools.tts_tool``: Edge, ElevenLabs, xAI, MiniMax, Mistral, Gemini.

Each ``_generate_<provider>(text, output_path, tts_config) -> path`` writes one final-encoded
file. Shared here: bounded upstream response reading (16 MiB cap so a hostile endpoint can't
feed unbounded audio) and the auxiliary-model speech-tag rewrites. OpenAI/DeepInfra live in
``tts_tool_openai``. Origin seams (``_resolve_provider_key``, ``_import_*``)
are resolved through :func:`_origin` at call time.
é    )ÚannotationsN)Ú	dataclassÚfield)ÚPath)ÚAnyÚDictÚOptional)Úurlparse)Ú_originÚ_sectionÚ_wrap_pcm_as_wavÚ_write_wav_bytes_as)Úhermes_xai_user_agentztools.tts_toolzen-US-AriaNeuralÚpNInz6obpgDQGcFmaJgBÚeleven_multilingual_v2Úeleven_flash_v2_5zspeech-02-hdÚEnglish_expressive_narratorz https://api.minimax.io/v1/t2a_v2z"https://api.minimaxi.com/v1/t2a_v2zvoxtral-mini-tts-2603z$c69964a6-ab8b-4f8a-9465-ec0925096ec8ÚeveÚeniÀ]  é ô Fzhttps://api.x.ai/v1çffffffæ?g      ø?ç      ð?zgemini-2.5-flash-preview-ttsÚKorez0https://generativelanguage.googleapis.com/v1betaÚtts_audio_tagsi   i   >   Ú1ÚonÚyesÚtrueÚenabled>   Ú0ÚnoÚoffÚfalseÚdisabledc                óà   — t        | t        t        t        f«      rt        | «      S t        | t        «      r| j                  «       j                  «       nd}|t        t        z  v r|t        v S |S )zNCoerce common YAML/env bool spellings without treating random strings as true.N)	Ú
isinstanceÚboolÚintÚfloatÚstrÚstripÚlowerÚ_TRUE_WORDSÚ_FALSE_WORDS)ÚvalueÚdefaultÚ
normalizeds      ú=/home/ubuntu/.hermes/hermes-agent/tools/tts_tool_providers.pyÚ_config_boolr3   @   sY   € ä�%œ$¤¤UÐ+Ô,Ü�E‹{ÐÜ*4°U¼CÔ*@�—‘“×$Ñ$Ô&Àd€JØ(2´kÄLÑ6PÑ(Pˆ:œÐ$Ð]ÐV]Ð]ó    c                ó2   ‡ — d}t        ˆ fd„|D «       d«      S )zSPick an OpenAI-style response format (opus/wav/flac/mp3) from the output extension.))ú.oggÚopus)ú.wavÚwav)z.flacÚflacc              3  óL   •K  — | ]  \  }}‰j                  |«      sŒ|–— Œ y ­w©N)Úendswith)Ú.0ÚextÚfmtÚoutput_paths      €r2   ú	<genexpr>z1_tts_response_format_from_path.<locals>.<genexpr>K   s"   øè ø€ ÒJ™˜˜c°×0DÑ0DÀSÕ0I”ÑJùs   ƒ$�$Úmp3)Únext)rA   Úformatss   ` r2   Ú_tts_response_format_from_pathrF   H   s   ø€ àD€GÜÓJ WÔJÈEÓRÐRr4   c                óf   — t        «       j                  | |«      xs d}|st        | › d|› �«      ‚|S )zbResolve *env_var* via the origin key resolver; ValueError ``"<ENV> not set. <hint>"`` when absent.Ú z
 not set. )r   Ú_resolve_provider_keyÚ
ValueError)Úenv_varÚprovider_idÚhintÚapi_keys       r2   Ú_require_keyrO   N   s9   € ä‹i×-Ñ-¨g°{ÓCÒIÀr€GÙÜ˜G˜9 J¨t¨fÐ5Ó6Ð6Ø€Nr4   c                óš   — t        t        | dd«      «      syt        | «      }|j                  j	                  d«      xs dt        |«      v S )zWTrue for real ``requests`` responses (or doubles defining ``iter_content`` themselves).Úiter_contentNFz	requests.)ÚcallableÚgetattrÚtypeÚ
__module__Ú
startswithÚvars)ÚresponseÚresponse_types     r2   Ú_response_has_explicit_streamrZ   W   sG   € ä”G˜H n°dÓ;Ô<ØÜ˜“N€MØ×#Ñ#×.Ñ.¨{Ó;Òd¸~ÔQUÐVcÓQdÐ?dÐdr4   c                ó    — t        | dd «      }t        |«      r*t        j                  t        «      5   |«        d d d «       y y # 1 sw Y   y xY w)NÚclose)rS   rR   Ú
contextlibÚsuppressÚ	Exception)rX   r\   s     r2   Ú_close_responser`   _   sI   € Ü�H˜g tÓ,€EÜ�„Ü× Ñ ¤Ó+ñ 	ÙŒG÷	ð 	ð ÷	ð 	ús   ²AÁA)Úlimitc               óJ  — |€t         n|}g }d}	 t        | «      r| j                  t        ¬«      }nOt	        | «      j                  dt        t        | «      dd«      «      }t        |t        t        t        f«      r|fnd}|D ]s  }|sŒt        |t        «      r|j                  dd¬«      }t        |«      }|t        |«      z  }||kD  rt        | «       t        |› d	|› d
�«      ‚|j!                  |«       Œu dj#                  |«      t        | «       S # t        | «       w xY w)z3Read an upstream TTS response with a hard byte cap.r   )Ú
chunk_sizeÚcontentr4   © úutf-8Úreplace©Úerrorsz response exceeds z bytes)ÚTTS_RESPONSE_BODY_LIMIT_BYTESrZ   rQ   ÚTTS_RESPONSE_BODY_CHUNK_BYTESrW   ÚgetrS   rT   r&   r*   ÚbytesÚ	bytearrayÚencodeÚlenr`   ÚRuntimeErrorÚappendÚjoin)rX   Úlabelra   ÚchunksÚtotalÚiteratorrd   Úchunks           r2   Ú_read_tts_response_bytesry   f   s  € à-2¨]Õ)À€EØ€FØ€Eð"Ü(¨Ô2Ø×,Ñ,Ô8UÐ,ÓV‰Hä˜8“n×(Ñ(¨´G¼DÀ»NÈIÐWZÓ4[Ó\ˆGÜ%/°¼#¼uÄiÐ9PÔ%Q˜‘zÐWYˆHØò 
	!ˆEÙØÜ˜%¤Ô%ØŸ™ W°Y˜Ó?�Ü˜%“LˆEØ”S˜“ZÑˆEØ�uŠ}Ü Ô)Ü" e WÐ,>¸u¸gÀVÐ#LÓMÐMØ�M‰M˜%Õ ð
	!ð �x‰x˜Óä˜Õ!øŒ˜Õ!ús   �C9D ÄD"c                óÎ   — |r$t        j                  |j                  d«      «      S t        | «      s3t	        | dd«      }t        |«      r |«       }t        |t        «      r|S i S i S )z¶JSON from the already-read *raw* body. Unit-test doubles often only provide ``.json()``;
    real ``requests`` responses took the streaming path, so production never buffers eagerly.rf   ÚjsonN)r{   ÚloadsÚdecoderZ   rS   rR   r&   Údict)rX   ÚrawÚjson_readerÚparseds       r2   Ú_parse_json_bodyr‚   �   s]   € ñ Ü�z‰z˜#Ÿ*™* WÓ-Ó.Ð.Ü(¨Ô2Ü˜h¨°Ó5ˆÜ�KÔ Ù “]ˆFÜ'¨´Ô5�6Ð=¸2Ð=Ø€Ir4   c               ó2   — t        | t        | ||¬«      «      S )N)rt   ra   )r‚   ry   )rX   rt   ra   s      r2   Ú_read_tts_response_jsonr„   Ž   s   € Ü˜HÔ&>¸xÈuÐ\aÔ&bÓcÐcr4   c                ól   — t        | d«      5 }|j                  |«       d d d «       | S # 1 sw Y   | S xY w)NÚwb)ÚopenÚwrite)rA   Úaudio_bytesÚfs      r2   Ú_write_bytesr‹   ’   s6   € Ü	ˆk˜4Ó	 ð  AØ	�‰�Ô÷àÐ÷àÐús   �)©3c                ó:   — ddl } |j                  | f||dddœ|¤ŽS )z\Streaming ``requests.post`` with the shared 60s timeout (body read via the bounded readers).r   Né<   T)Úheadersr{   ÚtimeoutÚstream)ÚrequestsÚpost)ÚurlÚpayloadrŽ   Úextrar‘   s        r2   Ú
_post_jsonr–   ˜   s(   € ãØˆ8�=‰=˜Ð^ g°GÀRÐPTÑ^ÐX]Ñ^Ð^r4   c                ó~  — 	 t        | j                  d   dd«      }t        |t        «      r|j	                  d«      nt        |dd«      }t        |xs d«      j                  «       }t        j                  d|t        j                  ¬«      }|r|j                  d«      j                  «       S |S # t
        $ r Y yw xY w)	zWThe first choice's message content with any ```fence``` unwrapped ("" when unreadable).r   ÚmessageNrd   rH   z$```(?:[A-Za-z0-9_-]+)?\s*(.*?)\s*```©Úflagsé   )rS   Úchoicesr&   r~   rl   r_   r*   r+   ÚreÚ	fullmatchÚDOTALLÚgroup)rX   r˜   rd   ÚcleanÚfences        r2   Ú_auxiliary_reply_textr£   Ÿ   s§   € ðÜ˜(×*Ñ*¨1Ñ-¨y¸$Ó?ˆÜ,6°wÄÔ,E�'—+‘+˜iÔ(Ì7ÐSZÐ\eÐgiÓKjˆô �’˜2Ó×$Ñ$Ó&€EÜ�L‰LÐ@À%ÌrÏyÉyÔY€EÙ%*ˆ5�;‰;�q‹>×ÑÓ!Ð5°Ð5øô	 ò Ùðús   ‚AB0 Â0	B<Â;B<z{Rules:
- Preserve the spoken words, order, and meaning.
- Do not add new spoken sentences or remove existing spoken words.
zA- Do not explain or comment.
- Return only the tagged TTS script.c               ó¾   — 	 ddl m}  |t        dd| dœd|dœg¬«      }t        |«      xs |S # t        $ r%}t
        j                  |d|||«       |cY d	}~S d	}~ww xY w)
zmAsk the auxiliary model (task ``tts_audio_tags``) to rewrite a script; *fallback* on any failure/empty reply.r   )Úcall_llmr   Úsystem)Úrolerd   Úuser)ÚtaskÚtemperatureÚmessagesz)%s audio tag rewrite failed; using %s: %sN)Úagent.auxiliary_clientr¥   ÚGEMINI_AUDIO_TAG_REWRITE_TASKr£   r_   ÚloggerÚlog)	Úsystem_promptÚuser_promptÚfallbackrt   Úfallback_labelÚlevelr¥   rX   Úexcs	            r2   Ú_rewrite_with_auxiliary_modelr¶   ³   sm   € ð	Ý3ÙÜ.¸CØ'°MÑBØ%°+Ñ>ð@ôAˆô % XÓ.Ò:°(Ð:øÜò Ü�
‰
�5ÐEÀuÈnÐ^aÔbØ�ûðús   ‚+. ®	A·AÁAÁAc           	   ƒ  ó€  K  — t        «       j                  «       }|j                  d«      xs i }t        |j                  d|j                  dd«      «      «      }d|j                  dt        «      i}|dk7  rt        |dz
  dz  «      d›d�|d<    |j                  | fi |¤Žj                  |«      ƒ d {  –—†  |S 7 Œ­w)	NÚedgeÚspeedr   Úvoiceéd   z+dú%Úrate)r   Ú_import_edge_ttsrl   r)   ÚDEFAULT_EDGE_VOICEÚroundÚCommunicateÚsave)ÚtextrA   Ú
tts_configÚedge_ttsÚedge_configr¹   Úkwargss          r2   Ú_generate_edge_ttsrÈ   Ä   s¹   è ø€ Ü‹y×)Ñ)Ó+€HØ—.‘. Ó(Ò.¨B€KÜ�+—/‘/ '¨:¯>©>¸'À3Ó+GÓHÓI€EØ�{—‘ wÔ0BÓCÐD€FØ�‚|Ü! 5¨3¡;°#Ñ"5Ó6°rÐ:¸!Ð<ˆˆv‰Ø
ˆ(×
Ñ
˜tÑ
. vÑ
.×
3Ñ
3°KÓ
@×@Ð@ØÐð Aús   ‚B3B>Â5B<Â6B>c                óð   — | j                  d«      xs dj                  d«      }|si S ddlm} | j                  d«      xs dj                  d«      xs t	        j
                  dd|«      }d	 |||¬
«      iS )z°SDK client kwargs for ``tts.elevenlabs.base_url``/``wss_url``; empty (SDK default) without a
    base_url. ``wss_url`` defaults to the base_url host with a ``ws(s)://`` scheme.Úbase_urlrH   ú/r   )ÚElevenLabsEnvironmentÚwss_urlz^httpÚwsÚenvironment)ÚbaseÚwss)rl   ÚrstripÚelevenlabs.environmentrÌ   r�   Úsub)Ú	el_configrÊ   rÌ   rÍ   s       r2   Ú_elevenlabs_environment_kwargsrÖ   Ð   sq   € ð —‘˜jÓ)Ò/¨R×7Ñ7¸Ó<€HÙØˆ	Ý<Ø�}‰}˜YÓ'Ò-¨2×5Ñ5°cÓ:Ò^¼b¿f¹fÀXÈtÐU]Ó>^€GØÑ0°hÀGÔLÐMÐMr4   c                ó¶  — t        ddd«      }|j                  d«      xs i } t        «       j                  «       dd|it	        |«      ¤Ž}|j
                  j                  | |j                  dt        «      |j                  dt        «      |j                  d«      rdnd	¬
«      }t        |d«      5 }|j                  |«       d d d «       |S # 1 sw Y   |S xY w)NÚELEVENLABS_API_KEYÚ
elevenlabsz!Get one at https://elevenlabs.io/rN   Úvoice_idÚmodel_idr6   Úopus_48000_64Úmp3_44100_128)rÃ   rÚ   rÛ   Úoutput_formatr†   re   )rO   rl   r   Ú_import_elevenlabsrÖ   Útext_to_speechÚconvertÚDEFAULT_ELEVENLABS_VOICE_IDÚDEFAULT_ELEVENLABS_MODEL_IDr=   r‡   Ú
writelines)rÃ   rA   rÄ   rN   rÕ   ÚclientÚaudio_generatorrŠ   s           r2   Ú_generate_elevenlabsrç   Û   sÏ   € ÜÐ/°Ð?bÓc€GØ—‘˜|Ó,Ò2°€IØ+ŒW‹Y×)Ñ)Ó+Ñi°GÐiÔ?]Ð^gÓ?hÑi€FØ×+Ñ+×3Ñ3Ø˜IŸM™M¨*Ô6QÓRØ—‘˜zÔ+FÓGØ)4×)=Ñ)=¸fÔ)E‘oÈ?ð 4ó \€Oô 
ˆk˜4Ó	 ð & AØ	�‰�_Ô%÷&àÐ÷&àÐús   Â2CÃC)Úpausez
long-pausezhum-tuneÚlaughÚchuckleÚgiggleÚcryÚtskztongue-clickz	lip-smackÚbreathÚinhaleÚexhaleÚsigh)ÚsoftÚwhisperÚloudzbuild-intensityzdecrease-intensityzhigher-pitchzlower-pitchÚslowÚfastz	sing-songÚsingingzlaugh-speakÚemphasisz(\[(?:Ú|z
)\]|</?(?:z)>)r™   u   ^(.{12,120}?[.!?â€¦])\s+(?=\S)c           	     ó"  — | j                  «       }|s| S t        j                  ddt        j                  dd|«      «      }t        j	                  |«      st
        j                  d|d¬«      }t        j                  dd|«      j                  «       }t        j	                  |«      r|S d	d
j                  t        «      z   dz   d
j                  t        «      z   dz   t        z   dz   t        z   }t        |d|› �|ddt        j                  ¬«      S )u  Add xAI speech tags: a conservative local pass ([pause] between paragraphs / after the first
    sentence), then â€” only when the text carried no explicit tags â€” an auxiliary-model rewrite
    with the richer xAI tag set, falling back to the locally tagged text on any failure.z\s*\n\s*Ú z\n\s*\n+z	 [pause] z\1 [pause] r›   )Úcountz\s{2,}zYou rewrite transcripts for the xAI /v1/tts endpoint by inserting expressive speech tags.

Valid inline tags (use as `[tag]`): z, z1.
Valid wrapping tags (use as `[tag]...[/tag]`): z.

u%  - Use inline `[tag]` for short modifiers (laughs, sighs, pause, etc.).
- Use wrapping `[tag]...[/tag]` for sustained effects (whisper, soft, slow, fast, loud, etc.).
- Do not use angle-bracket tags like `<tag>...</tag>` â€” xAI uses BBCode-style closing tags with `[/tag]`.
- Do not use SSML.
zTRANSCRIPT TO TAG:
úxAI TTSzlocally-tagged text©rt   r³   r´   )r+   r�   rÔ   Ú_XAI_SPEECH_TAG_REÚsearchÚ_XAI_FIRST_SENTENCE_RErs   Ú_XAI_INLINE_SPEECH_TAGSÚ_XAI_WRAPPING_SPEECH_TAGSÚ_TAG_REWRITE_RULESÚ_TAG_REWRITE_TAILr¶   ÚloggingÚDEBUG)rÃ   r¡   Úlocalr°   s       r2   Ú_apply_xai_auto_speech_tagsr	  õ   s*  € ð �J‰J‹L€EÙØˆÜ�F‰F�; ¤R§V¡V¨K¸ÀeÓ%LÓM€EÜ×$Ñ$ UÔ+Ü&×*Ñ*¨>¸5ÈÐ*ÓJˆÜ�F‰F�9˜c 5Ó)×/Ñ/Ó1€EÜ× Ñ  Ô'Øˆð	/à15·±Ô;RÓ1Sñ	TðW:ñ	:ð =A¿I¹IÔF_Ó<`ñ	að dkñ	kô ñ		ð
	ñ	ô ñ		ð ô )ØÐ-¨e¨WÐ5°uÀIÐ^sô  |C÷  |Iñ  |Iôð r4   c                óz   — | €y| dk7  r		  || «      } t        |t        || «      «      S # t         t        f$ r Y yw xY w)zÀParse an optional numeric knob and clamp into [lo, hi]; ``None``/unparseable -> None. An empty
    string is deliberately clamped unconverted (its TypeError surfaces as a generic TTS failure).NrH   )Ú	TypeErrorrJ   ÚmaxÚmin)r   ÚcastÚloÚhis       r2   Ú_clamped_numberr    sO   € ð €{ØØ
ˆb‚yð	Ù�s“)ˆCô ˆr”3�r˜3“<Ó Ð øô œ:Ð&ò 	Ùð	ús   Š( ¨:¹:c                ó  — ddl m}  |d¬«      }t        |j                  d«      xs d«      j	                  «       }|st        d«      ‚|j                  d«      xs i }t        |j                  d	t        «      «      j	                  «       xs t        }t        |j                  d
t        «      «      j	                  «       xs t        }t        |j                  dt        «      «      t        |j                  dt        «      «      }
}	|j                  d|j                  d«      «      }t        |t        «      rt        | «      } t        |j                  d|j                  d«      «      t        t         t"        «      }t        |j                  d|j                  d«      «      t        dd«      }t        |j                  d«      t$        «      }|j                  d«      dk(  r|j                  d«      }n4ddlm} |j                  d«      xs |j                  d«      xs  |d«      }t        |xs t*        «      j	                  «       j-                  d«      }|j/                  d«      rdnd}| ||dœ}|dk7  s|	t        k7  s	|
t        k7  rd|i}|	r|	|d<   |dk(  r|
r|
|d<   ||d<   |�|t0        k7  r||d<   |d t2        fvr||d<   |rd|d<   t5        |› d�|d |› �d!t7        «       d"œ«      }|j9                  «        t;        |t=        |d#¬$«      «      S )%Nr   )Úresolve_xai_http_credentialsT)Úprefer_api_keyrN   rH   zSNo xAI credentials found. Configure xAI OAuth in `hermes model` or set XAI_API_KEY.ÚxairÚ   ÚlanguageÚsample_rateÚbit_rateÚauto_speech_tagsÚspeech_tagsr¹   Úoptimize_streaming_latencyé   Útext_normalizationÚproviderz	xai-oauthrÊ   ©Úget_env_valueÚXAI_BASE_URLrË   r8   r9   rC   )rÃ   rÚ   r  ÚcodecrÞ   z/ttsúBearer úapplication/json)ÚAuthorizationúContent-Typez
User-Agentrý   ©rt   )Útools.xai_httpr  r*   rl   r+   rJ   ÚDEFAULT_XAI_VOICE_IDÚDEFAULT_XAI_LANGUAGEr(   ÚDEFAULT_XAI_SAMPLE_RATEÚDEFAULT_XAI_BIT_RATEr3   ÚDEFAULT_XAI_AUTO_SPEECH_TAGSr	  r  r)   ÚDEFAULT_XAI_SPEED_MINÚDEFAULT_XAI_SPEED_MAXÚ&DEFAULT_XAI_TEXT_NORMALIZATION_DEFAULTÚhermes_cli.configr   ÚDEFAULT_XAI_BASE_URLrÒ   r=   ÚDEFAULT_XAI_SPEED_DEFAULTÚ.DEFAULT_XAI_OPTIMIZE_STREAMING_LATENCY_DEFAULTr–   r   Úraise_for_statusr‹   ry   )rÃ   rA   rÄ   r  ÚcredsrN   Ú
xai_configrÚ   r  r  r  r  r¹   r  r  rÊ   r   r"  r”   rÞ   rX   s                        r2   Ú_generate_xai_ttsr8    sÛ  € Ý;ñ
 )¸Ô=€EÜ�%—)‘)˜IÓ&Ò,¨"Ó-×3Ñ3Ó5€GÙÜÐnÓoÐoØ—‘ Ó&Ò,¨"€JÜ�:—>‘> *Ô.BÓCÓD×JÑJÓLÒdÔPd€HÜ�:—>‘> *Ô.BÓCÓD×JÑJÓLÒdÔPd€HÜ  §¡°Ô?VÓ!WÓXÜ  §¡°
Ô<PÓ!QÓRð €Kà!—~‘~Ð&8¸*¿.¹.ÈÓ:WÓXÐÜÐ$Ô&BÔCÜ*¨4Ó0ˆô ˜JŸN™N¨7°J·N±NÀ7Ó4KÓLÌeÜ1Ô3HóJ€Eä!0Ø�‰Ð3°Z·^±^ÐD`Ó5aÓbÜˆQ�ó"Ðô &Ø�‰Ð+Ó,Ô.TóVÐà‡y�y�Ó Ò+Ø—9‘9˜ZÓ(‰å3Ø—>‘> *Ó-Òg°·±¸:Ó1FÒgÉ-ÐXfÓJgˆÜ�8Ò3Ô3Ó4×:Ñ:Ó<×CÑCÀCÓH€Hð !×)Ñ)¨&Ô1‰E°u€EØ'+¸ÈxÑX€GØ�‚~˜Ô(?Ò?À8ÔOcÒCcØ)0°%Ð(8ˆÙØ+6ˆM˜-Ñ(Ø�EŠ>™hØ(0ˆM˜*Ñ%Ø#0ˆ�Ñ ØÐ˜UÔ&?Ò?Ø ˆ�ÑØ!¨$Ô0^Ð)_Ñ_Ø0JˆÐ,Ñ-ÙØ(,ˆÐ$Ñ%Ü˜X˜J dÐ+¨WØ" 7 )Ð,Ð>PÜ+Ó-ñ7/ó 0€Hð ×ÑÔÜ˜Ô%=¸hÈiÔ%XÓYÐYr4   T)Úfrozenc                  óL   — e Zd ZU dZded<   ded<   ded<    ed¬«      Zded<   y	)
Ú_MiniMaxTTSRuntimezLA region-bound MiniMax endpoint and credential (key excluded from ``repr``).r*   ÚregionÚendpointÚcredential_sourceF)ÚreprrN   N)Ú__name__rU   Ú__qualname__Ú__doc__Ú__annotations__r   rN   re   r4   r2   r;  r;  Y  s$   … áVàƒKØƒMØÓÙ˜eÔ$€GˆSÔ$r4   r;  )ÚglobalÚcnzapi.minimax.iozapi.minimax.chatzapi.minimaxi.comc                óÖ  — t        | d«      }t        «       j                  }dD ��ci c],  \  }}||t         ||d«      xs d«      j	                  «       f“Œ. }}}t        |j                  d«      xs d«      j	                  «       j                  «       }|r|t        vrt        d«      ‚|s|d   d   r
|d   d   sdnd}||   \  }}|st        |› d	|›�«      ‚t        |j                  d
«      xs	 t        |   «      j	                  «       }|dk(  rdnd}	t        |«      j                  xs dj                  «       t        |	   v rt        d|	›d|›�«      ‚t        ||||¬«      S c c}}w )z¾Select MiniMax region, endpoint and credential atomically: explicit ``tts.minimax.region`` wins,
    else the legacy global credential; ``cn`` only when it is the sole configured credential.Úminimax))rD  ÚMINIMAX_API_KEY)rE  ÚMINIMAX_CN_API_KEYrH   r<  z+tts.minimax.region must be 'global' or 'cn'rE  r›   rD  z  not set for MiniMax TTS region rÊ   z#tts.minimax.base_url points to the z  MiniMax endpoint but region is )r<  r=  r>  rN   )r   r   rI   r*   r+   rl   r,   Ú_MINIMAX_ENDPOINTSrJ   r
   ÚhostnameÚ_MINIMAX_OFFICIAL_HOSTSr;  )
rÄ   Ú	mm_configÚresolve_keyr<  rK   Úcredentialsr>  rN   r=  Úother_regions
             r2   Ú_resolve_minimax_tts_runtimerQ  i  s’  € ô ˜ YÓ/€IÜ“)×1Ñ1€Kð  ]÷^áˆF�Gð 	�œ#™k¨'°9Ó=ÒCÀÓD×JÑJÓLÐMÑMð^€Kñ ^ô �—‘˜xÓ(Ò.¨BÓ/×5Ñ5Ó7×=Ñ=Ó?€FÙ�&Ô 2Ñ2ÜÐFÓGÐGÙØ$ TÑ*¨1Ò-°kÀ(Ñ6KÈAÒ6N‘ÐT\ˆØ!,¨VÑ!4ÑÐ�wÙÜÐ-Ð.Ð.NÈvÈjÐYÓZÐZÜ�9—=‘= Ó,ÒJÔ0BÀ6Ñ0JÓK×QÑQÓS€HØ! XÒ-‘4°8€LÜ�Ó×#Ñ#Ò) r×0Ñ0Ó2Ô6MÈlÑ6[Ñ[ÜØ1°,Ð1AÐAaÐbhÐakÐlónð 	nä V°hÐRcÐmtÔuÐuùó!^s   ¦1E%c           	     ó˜   — | j                  di «      }|j                  dd«      }|dk7  r!t        d|› d|j                  dd«      › �«      ‚y )	NÚ	base_respÚstatus_codeéÿÿÿÿr   zMiniMax TTS API error (code ú): Ú
status_msgzunknown error)rl   rq   )ÚresultrS  rT  s      r2   Ú_raise_minimax_api_errorrY  �  s[   € Ø—
‘
˜;¨Ó+€IØ—-‘- ¨rÓ2€KØ�aÒÜØ*¨;¨-°s¸9¿=¹=ÈÐWfÓ;gÐ:hÐiókð 	kð r4   c           
     ó.  — t        |«      }t        |d«      }|j                  dt        «      }|j                  dt        «      }|j
                  }ddlm} t        |j                  d«      xs d«      j                  «       xs  |d«      xs dj                  «       }	|	rd	|vr|› d
|v rdnd
› d	|	› �}d|v }
|
rs|| ||j                  dd«      |j                  dd«      |j                  dd«      |j                  dd«      dœ|j                  dd«      |j                  dd«      dddœdœ}n|| |dœ}t        ||dd|j                  › �dœ«      }|
rv|j                  «        t        |d ¬!«      }t        |«       |j                  d"i «      j                  d#d«      }|st        d$«      ‚t!        |t"        j%                  |«      «      S |j&                  j                  d%d«      }d&|v rt!        |t)        |d ¬!«      «      S d'}	 t)        |d ¬!«      }t        |r$t+        j,                  |j/                  d(«      «      ni «       t        d,«      ‚# t*        j0                  t2        t4        f$ r, |j                  «        t        d)|› d*t7        |«      › d+�«      ‚w xY w)-z½Generate audio via MiniMax: ``t2a_v2`` (nested payload, JSON reply with hex audio) or the legacy
    ``text_to_speech`` endpoint (flat payload, raw ``audio/*`` body), detected from the URL.rG  ÚmodelrÚ   r   r  Úgroup_idrH   ÚMINIMAX_GROUP_IDzGroupId=ú?ú&Út2a_v2r¹   r   ÚvolÚpitchÚemotionÚneutral)rÚ   r¹   ra  rb  rc  r  i }  Úbitrater   rC   r›   )r  re  ÚformatÚchannel)r[  rÃ   Úvoice_settingÚaudio_setting)r[  rÃ   rÚ   r$  r#  )r&  r%  zMiniMax TTSr'  ÚdataÚaudioz%MiniMax TTS returned empty audio datar&  zaudio/r4   rf   z.MiniMax TTS returned unexpected Content-Type 'z' (z bytes)z"MiniMax TTS returned no audio data)rQ  r   rl   ÚDEFAULT_MINIMAX_MODELÚDEFAULT_MINIMAX_VOICE_IDr=  r1  r   r*   r+   r–   rN   r5  r„   rY  rq   r‹   rm   ÚfromhexrŽ   ry   r{   r|   r}   ÚJSONDecodeErrorÚUnicodeDecodeErrorr  rp   )rÃ   rA   rÄ   ÚruntimerM  r[  rÚ   rÊ   r   r\  Ú	is_t2a_v2r”   rX   rX  Ú	hex_audioÚcontent_typeÚraw_bodys                    r2   Ú_generate_minimax_ttsrv  ‰  s   € ô +¨:Ó6€GÜ˜ YÓ/€IØ�M‰M˜'Ô#8Ó9€EØ�}‰}˜ZÔ)AÓB€HØ×Ñ€Hõ 0Ü�I—M‘M *Ó-Ò3°Ó4×:Ñ:Ó<ò EÙ!Ð"4Ó5Ò;¸×BÑBÓDð á�J hÑ.Ø�Z s¨h¡¡¸CÐ@ÀÈÈ
ÐSˆØ˜HÐ$€IÙà Dà$¨y¯}©}¸WÀcÓ/JÐS\×S`ÑS`ÐafÐhkÓSlØ"Ÿ™ w°Ó2¸y¿}¹}ÈYÐXaÓ?bñð
  )Ÿ}™}¨]¸EÓBÈyÏ}É}Ð]fÐhnÓOoØ¨Aññ

‰ð "¨4¸XÑFˆÜ˜( GØ*¸wÀwÇÁÐFWÐ=Xñ.Zó [€HáØ×!Ñ!Ô#Ü(¨¸ÔGˆÜ  Ô(Ø—J‘J˜v rÓ*×.Ñ.¨w¸Ó;ˆ	ÙÜÐFÓGÐGÜ˜K¬¯©°yÓ)AÓBÐBØ×#Ñ#×'Ñ'¨¸Ó;€LØ�<ÑÜ˜KÔ)AÀ(ÐR_Ô)`ÓaÐaà€HðfÜ+¨H¸MÔJˆÜ É¤§¡¨H¯O©O¸GÓ,DÔ!EÐWYÔZô
 Ð;Ó
<Ð<øô	 × Ñ Ô"4´iÐ@ò fØ×!Ñ!Ô#ÜØ<¸\¸NÈ#ÌcÐRZËmÈ_Ð\cÐdófð 	fðfús   È>I
 É
A
Jc           	     ó¤  — t        ddd«      }|j                  d«      xs i }d|i}|j                  d«      r|d   |d<   t        «       j                  «       }	  |di |¤Ž5 }|j                  j
                  j                  |j                  dt        «      | |j                  d«      xs t        t        |«      ¬	«      }t        j                  |j                  «      }	d d d «       t)        |	«      S # 1 sw Y   ŒxY w# t        $ r ‚ t        $ r?}
t        j!                  d
|
d¬«       t#        dt%        |
«      j&                  › �«      |
‚d }
~
ww xY w)NÚMISTRAL_API_KEYÚmistralz&Get one at https://console.mistral.ai/rN   rÊ   Ú
server_urlr[  rÚ   )r[  ÚinputrÚ   Úresponse_formatzMistral TTS failed: %sT)Úexc_infozMistral TTS failed: re   )rO   rl   r   Ú_import_mistral_clientrk  ÚspeechÚcompleteÚDEFAULT_MISTRAL_TTS_MODELÚDEFAULT_MISTRAL_TTS_VOICE_IDrF   Úbase64Ú	b64decodeÚ
audio_datarJ   r_   r®   Úerrorrq   rT   r@  r‹   )rÃ   rA   rÄ   rN   Ú	mi_configÚclient_kwargsÚMistralrå   rX   r‰   Úes              r2   Ú_generate_mistral_ttsr‹  Á  sI  € ÜÐ,¨iÐ9aÓb€GØ—‘˜yÓ)Ò/¨R€IØ%.°Ð$8€MØ‡}�}�ZÔ Ø&/°
Ñ&;ˆ�lÑ#Ü‹i×.Ñ.Ó0€GðMÙÑ%�}Ñ%ð 	@¨Ø—|‘|×*Ñ*×3Ñ3Ø—m‘m GÔ-FÓGÈtØ"Ÿ™ zÓ2ÒRÔ6RÜ >¸{Ó Kð 4ó MˆHô !×*Ñ*¨8×+>Ñ+>Ó?ˆK÷	@ô ˜ [Ó1Ð1÷	@ð 	@ûô ò ØÜò MÜ�‰Ð-¨q¸4ˆÔ@ÜÐ1´$°q³'×2BÑ2BÐ1CÐDÓEÈ1ÐLûðMús1   ÁC> Á!A=C2ÃC> Ã2C;Ã7C> Ã>EÄ:E
Å
Ec                ó$  — | j                  d«      }t        |t        «      r|j                  «       syt	        t
        j                  j                  |j                  «       «      «      j                  «       }|j                  «       s	 ddl
m}  |«       |z  }	 |j                  d¬«      j                  «       S # t        $ r t	        j                  «       |z  }Y ŒCw xY w# t        t         f$ r!}t"        j%                  d||«       Y d}~yd}~ww xY w)	zVRead ``tts.gemini.persona_prompt_file`` (relative -> under HERMES_HOME), failing soft.Úpersona_prompt_filerH   r   )Úget_hermes_homerf   )Úencodingz4Gemini TTS persona prompt file unavailable at %s: %sN)rl   r&   r*   r+   r   ÚosÚpathÚ
expandvarsÚ
expanduserÚis_absoluteÚhermes_constantsrŽ  r_   ÚcwdÚ	read_textÚOSErrorrp  r®   Úwarning)Úgemini_configr   r‘  rŽ  rµ   s        r2   Ú_read_gemini_persona_promptr›  Ø  sÝ   € à
×
Ñ
Ð1Ó
2€CÜ�cœ3Ô s§y¡y¤{ØÜ”—‘×"Ñ" 3§9¡9£;Ó/Ó0×;Ñ;Ó=€DØ×ÑÔð	%Ý8Ù"Ó$ tÑ+ˆDðØ�~‰~ wˆ~Ó/×5Ñ5Ó7Ð7øô ò 	%Ü—8‘8“: Ñ$ŠDð	%ûô Ô'Ð(ò Ü�‰ÐMÈtÐUXÔYÜûðús*   ÂB9 ÂC Â9 CÃCÃDÃ.D
Ä
Dc                ó4  — | j                  d«      }t        |t        «      r|j                  d«      }t        |t        ¬«      sy|xs dj                  «       j                  «       j                  dd«      d   }d	|v rd
|v ryt        j                  d|«       y)zMAudio tags are opt-in and only Gemini 3.1 TTS models are known to honor them.Ú
audio_tagsr   )r0   FrH   rË   r›   rU  z
gemini-3.1ÚttsTzrGemini TTS audio_tags enabled, but model %s is not known to support Gemini audio tags; skipping hidden tag rewrite)
rl   r&   r~   r3   ÚDEFAULT_GEMINI_AUDIO_TAGSr+   r,   Úrsplitr®   r™  )rš  r[  r   r1   s       r2   Ú_gemini_audio_tags_enabledr¡  ë  s�   € à
×
Ñ
˜LÓ
)€CÜ�#”tÔØ�g‰g�iÓ ˆÜ˜Ô%>Õ?ØØ’+˜2×$Ñ$Ó&×,Ñ,Ó.×5Ñ5°c¸1Ó=¸bÑA€JØ�zÑ! e¨zÑ&9ØÜ
‡N�Nð DØEJôLàr4   c                óÂ   — | j                  «       }|s| S dt        z   dz   t        z   }d|j                  «       xs d› d|› �}t        ||| ddt        j
                  ¬«      S )	zVUse the configured auxiliary model to insert Gemini audio tags (falls back to *text*).aÛ  You rewrite transcripts for Gemini 3.1 Flash TTS by inserting expressive audio tags.

Audio tags are inline square-bracket modifiers such as [whispers], [excitedly], [very slow], [sarcastically], [laughs], [sighs], or [gasp]. There is no fixed allowlist. Use creative freeform tags generously but naturally to control tone, pace, emotional vibe, emphasis, section-level delivery, and non-verbal sounds. Use English audio tags even when the spoken transcript is not English.

zJ- Use square brackets for every audio tag.
- Do not use SSML or XML tags.
zPERSONA AND DIRECTOR CONTEXT:
z(none)z

TRANSCRIPT TO TAG:
ú
Gemini TTSzuntagged textrþ   )r+   r  r  r¶   r  ÚWARNING)rÃ   Úpersona_promptÚ
transcriptr°   r±   s        r2   Ú_rewrite_gemini_tts_audio_tagsr§  ú  sˆ   € à—‘“€JÙØˆð	0ô ñ	ð	+ñ
	+ô ñ	ð ð 5°^×5IÑ5IÓ5KÒ5WÈxÐ4Xð Y*Ø*4¨ð7€Kä(¨¸ÀTÐQ]Ø8GÌwÏÉô`ð `r4   c                ó@  — | j                  «       }|€t        |«      }|s|S d}dD ]_  }t        j                  |t        j                  ¬«      }|j                  |«      sŒ:|› d|j                  ||«      › �j                  «       c S  |› d|› d|› �j                  «       S )z¶Gemini prompt = persona direction + transcript; a ``{transcript}`` / ``{{transcript}}``
    placeholder is substituted in place, otherwise the transcript is appended under a heading.z©Synthesize speech from the TRANSCRIPT only. Treat AUDIO PROFILE, SCENE, DIRECTOR'S NOTES, and SAMPLE CONTEXT as performance direction; do not speak those sections aloud.)z\{\{\s*transcript\s*\}\}z\{\s*transcript\s*\}r™   z

z

#### TRANSCRIPT
)r+   r›  r�   ÚcompileÚ
IGNORECASEr   rÔ   )rÃ   rš  r¥  r¦  ÚpreambleÚpatternÚcompileds          r2   Ú_compose_gemini_tts_promptr®    s°   € ð —‘“€JØÐÜ4°]ÓCˆÙØÐð	-ð ð Jò WˆÜ—:‘:˜g¬R¯]©]Ô;ˆØ�?‰?˜>Õ*Ø�Z˜t H§L¡L°¸^Ó$LÐ#MÐN×TÑTÓVÒVðWð ˆZ�t˜NÐ+Ð+@ÀÀÐM×SÑSÓUÐUr4   c                óÊ   — t        | d¬«      }	 t        | |«      j                  di «      j                  d«      }|xs |j	                  dd¬«      dd	 S # t        $ r d}Y Œ'w xY w)
zYBest-effort ``error.message`` from a non-200 Gemini reply, else the first 300 body chars.r£  r'  r†  r˜   Nrf   rg   rh   i,  )ry   r‚   rl   r_   r}   )rX   ru  r˜   s      r2   Ú_gemini_error_detailr°  %  sn   € ä'¨¸ÔE€HðÜ" 8¨XÓ6×:Ñ:¸7ÀBÓG×KÑKÈIÓVˆð ÒF�h—o‘o g°i�oÓ@ÀÀ#ÐFÐFøô ò ØŠðús   �+A ÁA"Á!A"c                ó¶  — t        «       }|j                  dd«      xs |j                  dd«      }|st        d«      ‚t        |d«      }t	        |j                  dt        «      «      j                  «       xs t        }t	        |j                  dt        «      «      j                  «       xs t        }ddl	m
} dd	lm}	  |	|j                  d
«      xs  |d«      xs t        «      }
t        |«      }| }t        ||«      rt!        | |¬«      }t#        |||¬«      }|j%                  d|«      }t'        |«      |kD  rt        dt'        |«      › d|› d�«      ‚dd|igigdgddd|iiidœdœ}ddi}t)        |
«      j*                  dk(  r"	 ddl}t	        |j.                  «      }d|› �|d<   t3        |
› d|› d �||d!|i¬"«      }|j4                  d#k7  r$t7        d$|j4                  › d%t9        |«      › �«      ‚	 t;        |d&¬'«      }|d(   d   d)   d   }t=        d*„ |D «       d«      }|€t7        d+«      ‚|j                  d,«      xs |j                  d-«      xs i j                  d.d/«      }|st7        d1«      ‚tE        tG        tI        jJ                  |«      «      |«      S # t0        $ r d}Y �Œ	w xY w# t>        t@        tB        f$ r}t7        d0|› �«      |‚d}~ww xY w)2zÀGenerate audio via Gemini ``generateContent`` (``responseModalities=["AUDIO"]``). The reply is
    base64 24kHz mono 16-bit PCM, wrapped as WAV and ffmpeg-converted to the requested container.ÚGEMINI_API_KEYÚgeminiÚGOOGLE_API_KEYzIGEMINI_API_KEY not set. Get one at https://aistudio.google.com/app/apikeyr[  rº   r   r  )Únormalize_gemini_base_urlrÊ   ÚGEMINI_BASE_URL)r¥  z?Gemini TTS composed prompt exceeds the provider request limit (z > zˆ chars). Reduce the persona/audio-tag prompt or lower tts.gemini.max_text_length so long-form text is split with enough prompt headroom.ÚpartsrÃ   ÚAUDIOÚvoiceConfigÚprebuiltVoiceConfigÚ	voiceName)ÚresponseModalitiesÚspeechConfig)ÚcontentsÚgenerationConfigr&  r$  z!generativelanguage.googleapis.comNz0.0.0zhermes-agent/zX-Goog-Api-Clientz/models/z:generateContentÚkey)ÚparamséÈ   zGemini TTS API error (HTTP rV  r£  r'  Ú
candidatesrd   c              3  ó2   K  — | ]  }d |v sd|v sŒ|–— Œ y­w)Ú
inlineDataÚinline_dataNre   )r>   Úps     r2   rB   z'_generate_gemini_tts.<locals>.<genexpr>a  s   è ø€ ÒW ¨|¸qÑ/@ÀMÐUVÒDVœ1ÑWùs   ‚�z+Gemini TTS response contained no audio datarÅ  rÆ  rj  rH   z#Gemini TTS response was malformed: z$Gemini TTS returned empty audio data)&r   rI   rJ   r   r*   rl   ÚDEFAULT_GEMINI_TTS_MODELr+   ÚDEFAULT_GEMINI_TTS_VOICEr1  r   Úagent.gemini_native_adapterrµ  ÚDEFAULT_GEMINI_TTS_BASE_URLr›  r¡  r§  r®  Ú_resolve_max_text_lengthrp   r
   rK  Ú
hermes_cliÚ__version__r_   r–   rT  rq   r°  r„   rD   ÚKeyErrorÚ
IndexErrorr  r   r   rƒ  r„  )rÃ   rA   rÄ   ÚoriginrN   rš  r[  rº   r   rµ  rÊ   r¥  Ú
tts_scriptÚprompt_textÚmax_lenr”   rŽ   rÍ  ÚversionrX   rj  r·  Ú
audio_partÚ	audio_b64rŠ  s                            r2   Ú_generate_gemini_ttsrØ  /  s+  € ô ‹Y€FØ×*Ñ*Ð+;¸XÓFò $È&×JfÑJfØ˜(óK$€GáÜÐdÓeÐeÜ˜Z¨Ó2€MÜ�×!Ñ! 'Ô+CÓDÓE×KÑKÓMÒiÔQi€EÜ�×!Ñ! 'Ô+CÓDÓE×KÑKÓMÒiÔQi€EÝ/ÝEÙ(Ø×Ñ˜*Ó%Òh©Ð7HÓ)IÒhÔMhó€Hô 1°Ó?€NØ€JÜ! -°Ô7Ü3°DÈÔXˆ
Ü,Ø�M°.ôB€Kà×-Ñ-¨h¸
ÓC€GÜ
ˆ;Ó˜'Ò!ÜðÜ�KÓ Ð!  W Ið .1ð1ó2ð 	2ð  ¨Ð 5Ð6Ð7Ð8à#* )Ø*Ð-BÀ[ÐRWÐDXÐ,YÐZñ
ñ€Gð Ð1Ð2€GÜ�Ó×"Ñ"Ð&IÒIð	ÛÜ˜*×0Ñ0Ó1ˆGð *7°w°iÐ'@ˆÐ#Ñ$Ü˜X˜J h¨u¨gÐ5EÐFÈÐQXÐbgÐipÐaqÔr€HØ×Ñ˜sÒ"ÜÐ8¸×9MÑ9MÐ8NÈcÔRfÐgoÓRpÐQqÐrÓsÐsðMÜ& x°|ÔDˆØ�\Ñ" 1Ñ% iÑ0°Ñ9ˆÜÑW eÔWÐY]Ó^ˆ
ØÐÜÐLÓMÐMØ—^‘^ LÓ1ÒX°Z·^±^ÀMÓ5RÒXÐVX×]Ñ]Ð^dÐfhÓiˆ	ñ ÜÐAÓBÐBÜÔ/´×0@Ñ0@ÀÓ0KÓLÈkÓZÐZøô# ò 	Ø‹Gð	ûô ”j¤)Ð,ò MÜÐ@ÀÀÐDÓEÈ1ÐLûðMús+   Æ
J Ç6A3J0 ÊJ-Ê,J-Ê0KËKËK)F)r/   r   r0   r'   Úreturnr'   )rA   r*   rÙ  r*   )rK   r*   rL   r*   rM   r*   rÙ  r*   )rX   r   rÙ  r'   )rX   r   rÙ  ÚNone)rX   r   rt   r*   ra   úOptional[int]rÙ  rm   )rX   r   r   rm   rÙ  úDict[str, Any])rX   r   rt   r*   ra   rÛ  rÙ  rÜ  )rA   r*   r‰   rm   rÙ  r*   )r“   r*   r”   rÜ  rŽ   zDict[str, str]r•   r   )rX   r   rÙ  r*   )r°   r*   r±   r*   r²   r*   rt   r*   r³   r*   r´   r(   rÙ  r*   )rÃ   r*   rA   r*   rÄ   rÜ  rÙ  r*   )rÕ   rÜ  rÙ  rÜ  )rÃ   r*   rÙ  r*   )r   r   )rÄ   rÜ  rÙ  r;  )rX  rÜ  rÙ  rÚ  )rš  rÜ  rÙ  r*   )rš  rÜ  r[  r*   rÙ  r'   )rH   )rÃ   r*   r¥  r*   rÙ  r*   r<   )rÃ   r*   rš  rÜ  r¥  zOptional[str]rÙ  r*   )erB  Ú
__future__r   rƒ  r]   r{   r  r�  r�   Údataclassesr   r   Úpathlibr   Útypingr   r   r	   Úurllib.parser
   Útools.tts_tool_deliveryr   r   r   r   r(  r   Ú	getLoggerr®   r¿   râ   rã   Ú%DEFAULT_ELEVENLABS_STREAMING_MODEL_IDrl  rm  ÚDEFAULT_MINIMAX_BASE_URLÚDEFAULT_MINIMAX_CN_BASE_URLr�  r‚  r)  r*  r+  r,  r-  r2  r.  r/  r3  r4  r0  rÈ  rÉ  rË  rŸ  r­   rj   rk   r-   r.   r3   rF   rO   rZ   r`   ry   r‚   r„   r‹   r–   r£   r  r  r¶   rÈ   rÖ   rç   r  r  r©  rs   rª  rÿ   rŸ   r  r	  r  r8  r;  rJ  Ú	frozensetrL  rQ  rY  rv  r‹  r›  r¡  r§  r®  r°  rØ  re   r4   r2   ú<module>rè     s³  ðñõ #ã Û Û Û Û 	Û 	ß (Ý ß &Ñ &Ý !ç \Ó \Ý 0à	ˆ×	Ñ	Ð+Ó	,€à'Ð Ø4Ð Ø6Ð Ø(;Ð %Ø&Ð Ø8Ð Ø=Ð ØBÐ Ø3Ð ØEÐ ØÐ ØÐ ØÐ ØÐ Ø$Ð Ø,Ð ð Ð ØÐ ØÐ Ø12Ð .Ø).Ð &Ø9Ð Ø!Ð ØPÐ Ø!Ð Ø 0Ð Ø 0Ð Ø )Ð â3€Ú6€ô^óSóóeóð SWõ "ó6
ð RVõ dóó_ó	6ðKð ð
 YÐ ðØðØ%(ðØ47ðØCFðØX[ðØdgðàóó"óNó
ðGÐ ðVÐ ð  �R—Z‘ZØˆc�h‰hÐ.Ó/Ð0°
¸3¿8¹8ÐD]Ó;^Ð:_Ð_bÐcØ
�-‰-ôÐ ð $˜Ÿ™Ð$EÈRÏYÉYÔWÐ óó:
!ó6Zñt �$Ô÷%ð %ó ð%ð !9Ð@[Ñ\Ð áÐ)Ð+=Ð>Ó?Ù
Ð'Ð(Ó
)ñ+Ð ó
vó0kó4=óp2ó.ó&ô`ô0Vó&Gô:[r4   