+
    lHàj  ã                  óæ   € R t ^ RIHt ^ RIt^ RIt^ RIHtHtHtH	t	 ^ RI
HtHtHtHt ^ RIHt ]P"                  ! R4      tRRR	R
/R R lltR R ltR R ltR R ltR R ltR R ltR R ltR# )aa  Plugin-registered TTS providers for ``tools.tts_tool``: routes ``tts.provider: <name>`` values
that are neither built-in nor ``type: command`` to a plugin :class:`agent.tts_provider.TTSProvider`.
Discovery goes through ``hermes_cli.plugins._ensure_plugins_discovered`` (imported lazily so the
tool module stays importable without the plugin machinery).
)ÚannotationsN)ÚAnyÚDictÚOptionalÚTuple)ÚBUILTIN_TTS_PROVIDERSÚ!DEFAULT_COMMAND_TTS_OUTPUT_FORMATÚ_get_named_provider_configÚ_is_command_provider_config)ÚNOUS_MANAGED_PROVIDERztools.tts_toolÚdiscoverTÚretryFc               ó$   € V ^8„  d   QhRRRRRR/# )é   ÚkeyÚstrr   Úboolr   © )Úformats   "Ú;/home/ubuntu/.hermes/hermes-agent/tools/tts_tool_plugins.pyÚ__annotate__r      s!   € ÷ ñ  ð °4ð Àtñ ó    c               ó†   € ^ RI Hp V'       d   ^ RIHp V! 4        V! V 4      pVf   V'       d   X! RR7       V! V 4      pV# )u  The registered ``TTSProvider`` named *key*, or None. ``discover`` runs plugin discovery first;
``retry`` re-discovers with ``force=True`` on a miss (a long-lived session may predate the
plugin's install). Raises on registry/discovery failure â€” callers decide if fatal.)Úget_provider)Ú_ensure_plugins_discoveredT)Úforce)Úagent.tts_registryr   Úhermes_cli.pluginsr   )r   r   r   r   r   Úplugin_providers   &$$   r   Ú_lookup_plugin_providerr      s=   € õ 0ßÝAÙ"Ô$Ù" 3Ó'€OØÒ§5Ù"¨Õ.Ù& sÓ+ˆØÐr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úproviderr   Ú
tts_configúdict[str, Any]ÚreturnúOptional[str]r   )r   s   "r   r   r   $   s!   € ÷ ñ  ð °ð ÀMñ r   c                óÎ   € T ;'       g    RP                  4       P                  4       pV'       d   V\        9   g   V\        8X  d   R# \	        \        W4      4      '       d   R# V# )z½Normalized *provider* when a plugin may service it, else None: built-in names never reach the
registry and a same-named ``type: command`` provider wins (config is more local than a plugin).Ú N)ÚlowerÚstripr   r   r
   r	   )r!   r"   r   s   && r   Ú_plugin_route_keyr*   $   sP   € ð �>ˆ>�r×
 Ñ
 Ó
"×
(Ñ
(Ó
*€Cß�#Ô.Ô.°#Ô9NÔ2NÙÜ"Ô#=¸jÓ#N×OÒOÙØ€Jr   c               ó    € V ^8„  d   QhRRRR/# )r   r"   r#   r$   r   )r   s   "r   r   r   /   s   € ÷ Pñ P ^ð P¸ñ Pr   c           
     óz  € \        V \        4      '       d   T M/ pVP                  R4      VP                  R4      VP                  R4      rCpR\        V\        4      '       d   V'       d   TMRR\        V\        4      '       d   V'       d   TMRR\        V\        \
        34      '       d   \        V4      /# R/# )z®``voice`` / ``model`` / ``speed`` for a plugin call (None = provider default). Shared by
``synthesize`` and the streaming path so a streamed reply keeps the configured voice.ÚvoiceÚmodelÚspeedN)Ú
isinstanceÚdictÚgetr   ÚintÚfloat)r"   Úcfgr-   r.   r/   s   &    r   Ú_plugin_voice_kwargsr6   /   s›   € ô # :¬t×4Ò4‰*¸"€CØŸ'™' 'Ó*¨C¯G©G°GÓ,<¸c¿g¹gÀgÓ>N�%€EØœj¨´×4Ò4¿‘UÀDØœj¨´×4Ò4¿‘UÀDØ¤Z°¼¼U°|×%DÒ%D”U˜5“\ðPð PàJNðPð Pr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r!   r   r"   r#   r$   zOptional[tuple[Any, int]]r   )r   s   "r   r   r   9   s"   € ÷ ñ ¨Sð ¸nð ÐQjñ r   c                óø  € \        W4      pVf   R#  \        V4      pVe)   VP                  '       d   VP                  4       '       g   R# VP                  p\        T\        4      '       g@   \        T\        \        34      '       d$   \        P                  ! T4      '       d   T^8  d   \        P                  RY$4       R# T\        T4      3#   \
         d    \        P                  RTRR7        R# i ; i)up  ``(plugin, sample_rate)`` when the plugin servicing *provider* opted into raw-PCM streaming.

Opt-in = ``streams_pcm`` truthy AND ``stream_sample_rate`` a finite number >= 1 Hz AND
``is_available()`` â€” read once per resolve, so per-profile state (key present, user opted out)
belongs there. A bad rate is refused loudly: PCM played at a guessed rate garbles speech.
Nz+plugin TTS streaming lookup failed for '%s'T)Úexc_infozpTTS provider '%s' sets streams_pcm without a valid stream_sample_rate (%r); using per-sentence synthesis instead)r*   r   Ústreams_pcmÚis_availableÚstream_sample_rateÚ	ExceptionÚloggerÚdebugr0   r   r3   r4   ÚmathÚisfiniteÚwarning)r!   r"   r   ÚpluginÚrates   &&   r   Ú_plugin_pcm_streaming_providerrE   9   s×   € ô ˜HÓ
1€CØ
‚{ÙðÜ(¨Ó-ˆØŠ> ×!3×!3Ð!3¸6×;NÑ;N×;PÒ;PÙØ×(Ñ(ˆô �$œ×Ò¤Z°´s¼E°l×%CÒ%CÌ4Ï=Ê=ÐY]×K^ÒK^ÐbfÐijÔbjÜ�‰ð >Ø?Bô	JáØ”3�t“9ÐÐøô ô Ü�‰ÐBÀCÐRVˆÔWÚðús   “ C ´C ÁC Ã#C9Ã8C9c          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )	r   Útextr   Úoutput_pathr!   r"   r#   r$   r%   r   )r   s   "r   r   r   R   s8   € ÷ Lñ L sð L¸ð LÈð LÐYgð LÐlyñ Lr   c                óô  € \        W#4      pVf   R#  \        VRR7      pTf   R# \        T\        4      '       d   TM/ P                  R\        4      p\        P                  RT4       TP                  ! Y3RT'       d   \        T4      P                  4       MR/\        T4      B p\        T\        4      '       d   T'       d   T# T#   \         d"   p\        P	                  RT4        Rp?R# Rp?ii ; i)	aø  Route to a plugin-registered TTS provider; None means "fall through".

Invariants re-checked here so a caller refactor can't break them: built-in names never reach
the registry; a same-named ``type: command`` provider wins; only an exact registered name
dispatches. Plugin exceptions propagate to ``text_to_speech_tool``'s error envelope.

Resolution invariants enforced here (matches issue #30398):
1. The caller is responsible for the elif chain that handles ``edge``/``openai``/etc.; this function
explicitly rejects those names defensively. 2. 3. Plugin dispatch fires only when ``provider`` matches a
registered :class:`TTSProvider` whose ``name`` equals the configured value. Unknown names return None
(caller falls through to Edge default). See #17843.
NT)r   z2tts plugin dispatch skipped (discovery failed): %sÚoutput_formatz2Generating speech with plugin TTS provider '%s'...r   Úmp3)r*   r   r=   r>   r?   r0   r1   r2   r   ÚinfoÚ
synthesizer   r(   r6   )	rG   rH   r!   r"   r   r   ÚexcÚfmtÚwrittens	   &&&&     r   Ú_dispatch_to_plugin_providerrQ   R   sÝ   € ô ˜HÓ
1€CØ
‚{ÙðÜ1°#¸TÔBˆð ÒÙÜ# J´×5Ò5‰:¸2×
BÑ
BØÔ:ó<€Cä
‡K�KÐDÀcÔJØ×(Ò(Øñjß69¤# c£(§.¡.Ô"2¸uðjÜH\Ð]gÓHhñj€Gä  ¬#×.Ò.·7ˆ7ÐKÀÐKøô ô Ü�‰ÐIÈ3ÔOÝûðús   “C ÃC7ÃC2Ã2C7c               ó    € V ^8„  d   QhRRRR/# ©r   r!   r   r$   r   r   )r   s   "r   r   r   q   s   € ÷ 
ñ 
°3ð 
¸4ñ 
r   c                ó8  € T ;'       g    RP                  4       P                  4       pV'       d   V\        9   d   R#  \        VRR7      pVRJ;'       d    \	        VP
                  4      #   \         d"   p\        P                  RY4        Rp?R# Rp?ii ; i)z`True when the registered plugin provider opts into voice-bubble delivery (any failure -> False).r'   F)r   Nz5tts plugin voice_compatible check failed for '%s': %s)	r(   r)   r   r   r   Úvoice_compatibler=   r>   r?   )r!   r   r   rN   s   &   r   Ú$_plugin_provider_is_voice_compatiblerV   q   s~   € à�>ˆ>�r×
 Ñ
 Ó
"×
(Ñ
(Ó
*€Cß�#Ô.Ô.ÙðÜ1°#ÀÔFˆØ dÐ*×UÐU¬t°O×4TÑ4TÓ/UÐUøÜô Ü�‰ÐLÈcÔWÝûðús   ¿A- ÁA- Á-BÁ8BÂBc               ó    € V ^8„  d   QhRRRR/# rS   r   )r   s   "r   r   r   ~   s   € ÷ ñ ¨Cð °Dñ r   c                ó„   €  \        V 4      p\        T;'       d    VP                  4       4      #   \         d     R# i ; i)zh``check_fn`` leg for plugin names: discovered provider reports ``is_available()``; any failure is False.F)r   r   r;   r=   )r!   rC   s   & r   Ú_plugin_provider_is_availablerY   ~   s?   € ðÜ(¨Ó2ˆÜ�F×4Ð4˜v×2Ñ2Ó4Ó5Ð5øÜô Úðús   ‚0 ›0 °?¾?)Ú__doc__Ú
__future__r   Úloggingr@   Útypingr   r   r   r   Útools.tts_command_providerr   r   r	   r
   Útools.tool_backend_helpersr   Ú	getLoggerr>   r   r*   r6   rE   rQ   rV   rY   r   r   r   Ú<module>ra      sn   ðñõ #ã Û ß -Ó -÷!ó !õ =à	×	Ò	Ð+Ó	,€ð¸$ð Èe÷ õõPõõ2Lõ>
÷r   