Ë
    áß²jvâ  ã            
       ób  — d 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 ddl	m
ZmZmZ ddlmZ ddlmZmZ  ej*                  d«      Zd	Zd
ZdZdZdefd„Zdefd„Zdd„ fdd„ fdd„ fdd„ fdd„ fdd„ fdd„ fdd„ fd d!„ ff	Zd"d#œd$ed%eddfd&„Z d'ed(edefd)„Z!d*e"d+e"d,e"d-e"ddf
d.„Z# G d/„ d0«      Z$y)1a  Tool-resource teardown, wire-client lifecycle and credential refresh for ``AIAgent``.

``ClientLifecycleMixin`` owns task cleanup, the shared primary client, per-request client caches
(owner-thread close vs stranger-thread abort), credential rotation and route-derived headers.
é    N)Úsuppress)ÚAnyÚOptional)ÚforwardÚforward_staticÚ	lazy_attr)Úget_provider_request_timeout)Úbase_url_host_matchesÚ	env_floatÚ	run_agentz0.14.1Ú_request_client_cacheÚ_request_anthropic_client_cacheuU    â€” no sockets found; in-flight request may keep running until the provider finishesÚreturnc                  ó   — ddl m}  dd| › �iS )z<User-Agent RouterMint needs to avoid Cloudflare 1010 blocks.r   )Ú__version__ú
User-AgentzHermesAgent/)Ú
hermes_clir   )Ú_HERMES_VERSIONs    ú;/home/ubuntu/.hermes/hermes-agent/agent/client_lifecycle.pyÚ_routermint_headersr      s   € å9Ø˜L¨Ð(9Ð:Ð;Ð;ó    c                  óŒ   — dd l } dt        › d| j                  «       j                  «       › d| j	                  «       › d�}|d|ddœS )	Nr   z	QwenCode/z (z; ú)Úenablez
qwen-oauth)r   zX-DashScope-CacheControlzX-DashScope-UserAgentzX-DashScope-AuthType)ÚplatformÚ_QWEN_CODE_VERSIONÚsystemÚlowerÚmachine)Ú_platÚ_uas     r   Ú_qwen_portal_headersr"      sN   € ÛØÔ(Ð)¨¨E¯L©L«N×,@Ñ,@Ó,BÐ+CÀ2ÀeÇmÁmÃoÐEVÐVWÐ
X€Cà°xÐZ]Ø ,ñð r   zopenrouter.aic                 ó$   —  t        dd«      «       S )Núagent.auxiliary_clientÚbuild_or_headers©Ú
_lazy_attr©ÚselfÚurls     r   ú<lambda>r+   *   s   € Ð(`¬
Ð3KÐM_Ó(`Ó(b€ r   zai-gateway.vercel.shc                 ó,   — t        t        dd«      «      S ©Nr$   Ú_AI_GATEWAY_HEADERS©Údictr'   r(   s     r   r+   r+   +   s   € ¬t´JÐ?WÐYnÓ4oÓ/p€ r   zintegrate.api.nvidia.comc                 ó&   —  t        dd«      |«      S )Nr$   Úbuild_nvidia_nim_headersr&   r(   s     r   r+   r+   ,   s   € Ð3s´:Ð>VÐXrÓ3sÐtwÓ3x€ r   zapi.routermint.comc                 ó   — t        «       S ©N)r   r(   s     r   r+   r+   -   s
   € Ô-@Ó-B€ r   úgithubcopilot.comc                 ó$   —  t        dd«      «       S )Nzhermes_cli.modelsÚcopilot_default_headersr&   r(   s     r   r+   r+   .   s   € Ð,f¬JÐ7JÐLeÓ,fÓ,h€ r   zapi.kimi.comc                 ó,   — t        t        dd«      «      S r-   r/   r(   s     r   r+   r+   /   s   € ¤t¬JÐ7OÐQfÓ,gÓ'h€ r   zportal.qwen.aic                 ó   — t        «       S r4   )r"   r(   s     r   r+   r+   0   s
   € Ô)=Ó)?€ r   zchatgpt.comc                 ó^   —  t        dd«      | j                  j                  dd«      |¬«      S )Nzagent.codex_headersÚcodex_cloudflare_headersÚapi_keyÚ )Úbase_url)r'   Ú_client_kwargsÚgetr(   s     r   r+   r+   1   s/   € Ð&c¤jÐ1FÐHbÓ&cØ×Ñ×Ñ 	¨2Ó.¸ô'>€ r   zx.aic                 ó$   —  t        dd«      «       S )Nztools.xai_httpÚhermes_xai_default_headersr&   r(   s     r   r+   r+   4   s   € ÐYœzÐ*:Ð<XÓYÓ[€ r   F)Úin_useÚcacherC   c                ó,   — d | d<   d | d<   d| d<   || d<   y )NÚclientÚkeyFÚpoisonedrC   © )rD   rC   s     r   Ú_reset_slotrJ   8   s'   € Ø€Eˆ(�OØ€Eˆ%�LØ€Eˆ*ÑØ€Eˆ(‚Or   r<   r>   c                 ó    — t        t        | t        «      xr4 | j                  «       xr" t        |t        «      xr |j                  «       «      S r4   )ÚboolÚ
isinstanceÚstrÚstrip©r<   r>   s     r   Ú_valid_credential_pairrQ   ?   s;   € Ü”
˜7¤CÓ(Òo¨W¯]©]«_ÒoÄÈHÔVYÓAZÒoÐ_g×_mÑ_mÓ_oÓpÐpr   Úfb_providerÚfb_modelÚfb_base_urlÚfb_api_modec                 ó”  — t        ||«      }|dk(  r|dv rddlm}  || ||«       yt        |«      j	                  d«      }t        |«      r|n|j                  }	|dk(  rxddlm}
 dd	l	m
}m} |d
k(  }|	xs |r |t        | dd«      ¬«      ndxs d}|x| _        | _        || _         |
|||¬«      | _         ||||¬«      | _        di c| _        | _        y|	| _        || _        t        |dd«      xs t        |dd«      }|	|dœ| _        |rt'        |«      | j$                  d<   |�"|| j$                  d<   | j)                  d¬«       yy)z_Install the fallback client(s) in place, honoring request_timeout_seconds (None = SDK default).Úbedrock©Úanthropic_messagesÚbedrock_converser   )Úbind_bedrock_runtimeNÚ_api_key_providerrY   ©Úbuild_anthropic_client)Úresolve_anthropic_tokenÚanthropic_route_is_oauthÚ	anthropicÚmodel©rb   r=   ©Útimeout©ÚproviderÚ_custom_headersÚdefault_headersrP   re   Úfallback_timeout_apply©Úreason)r	   Úagent.bedrock_adapterr[   Úvarsr@   Úcallabler<   Úagent.anthropic_adapterr^   Úagent.anthropic_credentialsr_   r`   ÚgetattrÚ_anthropic_api_keyÚ_anthropic_base_urlÚ_anthropic_clientÚ_is_anthropic_oauthrF   r?   r0   Ú_replace_primary_openai_client)ÚagentÚ	fb_clientrR   rS   rT   rU   re   r[   Úkey_providerÚ
credentialr^   r_   r`   Úis_anthropicÚeffective_keyÚ
fb_headerss                   r   Ú_swap_fallback_clientsr   C   st  € ä*¨;¸ÓA€GØ�iÒ KÐ3]Ñ$]å>Ù˜U K°Ô=Øä˜	“?×&Ñ&Ð':Ó;€LÜ!)¨,Ô!7‘¸Y×=NÑ=N€JØÐ*Ò*ÝBßaØ" kÑ1ˆØ"ò  EÑgsÑ'>ÄWÈUÐT[Ð]aÓEbÕ'cÐy}ò  Eð  CEˆØ3@Ð@ˆŒ˜Ô0Ø$/ˆÔ!Ù"8¸ÈÐ]dÔ"eˆÔÙ$<¸[È-ÐbmÔ$nˆÔ!Ø-1°2Ð*ˆŒ�eÔ*ØØ€E„MØ€E„Lô ˜Ð$5°tÓ<ÒkÄÈ	ÐSdÐfjÓ@k€JØ'1¸{ÑK€EÔÙÜ26°zÓ2Bˆ×ÑÐ.Ñ/ØÐØ*1ˆ×Ñ˜YÑ'à×,Ñ,Ð4LÐ,ÕMð r   c            	       ó  — e Zd Zdeddfd„Zdefd„Zdefd„Zdej                  fd„Z	e
dedefd	„«       Ze
dVd
dœdededefd„«       Z edd«      Z edd«      Z edd«      Z edd«      Z edd«      Zdedededdfd„Zdededdfd„Zdedefd„Zdedefd„Zdedefd„Ze
dedefd„«       Z edd h«      Zd!edefd"„Z d!ed#ede!fd$„Z"d!eded#eddfd%„Z#d!edededefd&„Z$d!ede!fd'„Z%d!edededdfd(„Z&dd)œdede'e   defd*„Z(dededdfd+„Z)deddfd,„Z*dededdfd-„Z+de!fd.„Z,d/ededefd0„Z-d/edefd1„Z.d#e!defd2„Z/dedefd3„Z0dededdfd4„Z1deddfd5„Z2dededdfd6„Z3dWd7„Z4d8edededefd9„Z5d
d:œd;edefd<„Z6d
dd=œd;ed>edz  defd?„Z7d@Z8defdA„Z9de'e!   fdB„Z:d8ededCedefdD„Z;defdE„Z<defdF„Z=d/edGededefdH„Z>defdI„Z?defdJ„Z@defdK„ZAd
dLœdedMeddfdN„ZBdWdO„ZCdefdP„ZDdQeddfdR„ZEddSœdedefdT„ZFdWdU„ZGy)XÚClientLifecycleMixinÚtask_idr   Nc                 ó~   ‡ ‡‡‡— ddl m}mŠmŠ d	ˆ fd„}d	ˆfd„}d	ˆ ˆfd„}|ˆˆfd„ˆˆfd„||fD ]
  } ||«       Œ y)
zRRelease task resources without treating a shared environment as process ownership.r   )Ú_quietlyÚcleanup_browserÚ
cleanup_vmNc                  ó¦   •— ddl m}  t        ‰dd«      }| j                  «       D ]*  }|d   |v sŒ|d   dk(  sŒ| j	                  |d   d	d
¬«       Œ, y )Nr   )Úprocess_registryÚ_process_owner_task_idsrI   Úowner_task_idÚstatusÚrunningÚ
session_idÚagent_closeT)ÚsourceÚconsume_output)Útools.process_registryrˆ   rr   Úlist_sessionsÚkill_process)rˆ   ÚownersÚprocessr)   s      €r   Úkill_processeszBClientLifecycleMixin._close_task_resources.<locals>.kill_processesl   sh   ø€ Ý?ô ˜TÐ#<¸bÓAˆFØ+×9Ñ9Ó;ò �Ø˜?Ñ+¨vÒ5¸'À(Ñ:KÈyÓ:XØ$×1Ñ1Ø Ñ-°mÐTXð 2õ ñr   c                  ó"   •— ddl m}   | ‰«       y )Nr   )Úrelease_computer_use_session)Útools.computer_use.toolr˜   )r˜   r‚   s    €r   Úrelease_computer_usezHClientLifecycleMixin._close_task_resources.<locals>.release_computer_usew   s   ø€ ÝLÙ(¨Õ1r   c                  óX   •— ddl m}  t        ‰dd«      D ]  }|sŒ|‰k7  sŒ | |«       Œ y )Nr   )Úclear_file_ops_cacher‰   rI   )Útools.file_toolsrœ   rr   )rœ   Úownerr)   r‚   s     €€r   Úforget_file_statezEClientLifecycleMixin._close_task_resources.<locals>.forget_file_state{   s3   ø€ õ >Ü  Ð'@À"ÓEò 0�Ú˜U gÓ-Ù(¨Õ/ñ0r   c                  ó   •—  ‰ ‰«      S r4   rI   )r†   r‚   s   €€r   r+   z<ClientLifecycleMixin._close_task_resources.<locals>.<lambda>„   s   ø€ ©Z¸Ó-@€ r   c                  ó   •—  ‰ ‰«      S r4   rI   )r…   r‚   s   €€r   r+   z<ClientLifecycleMixin._close_task_resources.<locals>.<lambda>„   s   ø€ É/ÐZaÓJb€ r   ©r   N)r   r„   r…   r†   )	r)   r‚   r„   r–   rš   rŸ   Ústepr…   r†   s	   ``     @@r   Ú_close_task_resourcesz*ClientLifecycleMixin._close_task_resourcesh   sA   û€ çCÑCõ		õ	2ö	0ð $Ô%@ÔBbØ)Ð+<ð>ò 	ˆDá�T�Nñ	r   c                 ó¶   — t        j                  «       }d|j                  › d|j                  › dt	        | dd«      › dt	        | dd«      › dt	        | d	d«      › �
S )
Nzthread=ú:z
 provider=rg   Úunknownz
 base_url=r>   ú model=rb   )Ú	threadingÚcurrent_threadÚnameÚidentrr   )r)   Úthreads     r   Ú_client_log_contextz(ClientLifecycleMixin._client_log_contextˆ   sh   € Ü×)Ñ)Ó+ˆà�f—k‘k�] ! F§L¡L >°¼GÀDÈ*ÐV_Ó<`Ð;að bÜ  j°)Ó<Ð=¸WÄWÈTÐSZÐ\eÓEfÐDgðið	
r   c                 ó>   — dt        | dd «      › dt        | dd «      › �S )Nz	provider=rg   r¨   rb   )rr   ©r)   s    r   Ú_anthropic_log_contextz+ClientLifecycleMixin._anthropic_log_context�   s+   € Øœ7 4¨°TÓ:Ð;¸7Ä7È4ÐQXÐZ^ÓC_ÐB`ÐaÐar   c                 óf   — t        | dd «      €t        j                  «       | _        | j                  S )NÚ_client_lock)rr   r©   ÚRLockr³   r°   s    r   Ú_openai_client_lockz(ClientLifecycleMixin._openai_client_lock’   s,   € Ü�4˜¨Ó.Ð6Ü )§¡Ó 1ˆDÔØ× Ñ Ð r   rF   c                 óÐ   — ddl m} t        | |«      ryt        | dd«      }|�t	        |«      r |«       ryt        |«      ryt        | dd«      }|�t        t        |dd«      «      S y)a„  Check if an OpenAI client is closed.

        Handles both property and method forms of is_closed:
        - httpx.Client.is_closed is a bool property
        - openai.OpenAI.is_closed is a method returning bool

        Prior bug: getattr(client, "is_closed", False) returned the bound method,
        which is always truthy, causing unnecessary client recreation on every call.
        r   ©ÚMockFÚ	is_closedNTÚ_client)Úunittest.mockr¸   rM   rr   ro   rL   )rF   r¸   Úis_closed_attrÚhttp_clients       r   Ú_is_openai_client_closedz-ClientLifecycleMixin._is_openai_client_closed—   so   € õ 	'ä�f˜dÔ#Øä  ¨°dÓ;ˆØÐ%ä˜Ô'Ù!Ô#ØÜ�nÔ%Øä˜f i°Ó6ˆØÐ"Üœ ¨[¸%Ó@ÓAÐAØr   T©Úverifyr>   rÀ   c                ó"   — ddl m}  || |¬«      S )z@Build the shared OpenAI httpx client used by main and aux paths.r   )Úbuild_keepalive_http_clientr¿   )Úagent.process_bootstraprÂ   )r>   rÀ   rÂ   s      r   Ú_build_keepalive_http_clientz1ClientLifecycleMixin._build_keepalive_http_clientµ   s   € õ 	HÙ*¨8¸FÔCÐCr   zagent.agent_runtime_helpersÚcreate_openai_clientÚforce_close_tcp_socketsÚcleanup_dead_connectionszagent.codex_runtimeÚrun_codex_streamÚrecover_with_credential_poolrl   Úsharedc                óþ   — |€y | j                  «       }| j                  |«      }	 |j                  «        t        j	                  d||||«       y # t
        $ r#}t        j                  d||||«       Y d }~y d }~ww xY w)Nz<OpenAI client closed (%s, shared=%s, tcp_force_closed=%d) %sz6OpenAI client close failed (%s, shared=%s) %s error=%s)r®   Ú_force_close_tcp_socketsÚcloseÚloggerÚinfoÚ	ExceptionÚdebug)r)   rF   rl   rÊ   ÚctxÚforce_closedÚexcs          r   Ú_close_openai_clientz)ClientLifecycleMixin._close_openai_clientÁ   s~   € Øˆ>ØØ×&Ñ&Ó(ˆà×4Ñ4°VÓ<ˆð	mØ�L‰LŒNÜ�K‰KÐVÐX^Ð`fÐhtÐvyÕzøÜò 	mÜ�L‰LÐQÐSYÐ[aÐcfÐhk×lÑlûð	mús   ¦)A Á	A<ÁA7Á7A<c                óò   — |€y	 | j                  |«      }t        j                  d||| j                  «       «       y# t        $ r0}t        j                  d|| j                  «       |«       Y d}~yd}~ww xY w)u|  Ownership-safe retirement of a replaced shared OpenAI client: ``shutdown()`` sockets only, FDs to GC.

        ``close()`` releases FDs from the calling thread while other threads may still hold the fd in an SSL BIO;
        a recycled fd then gets a TLS record written into an unrelated file (SQLite-header corruption).

        The shared primary client has no single owning thread â€” worker threads from stale-killed attempts
        may still be unwinding their SSL BIOs, and the codex-direct / MoA paths stream on the shared client
        itself. If we release an FD while another thread's SSL layer still caches the raw integer fd, the
        kernel can recycle it into an unrelated ``open()`` (e.g. ``kanban.db``) and the unwinding TLS flush
        then writes an application-data record into that file â€” the SQLite-header corruption documented in
        #29507/#70773.
        NzPShared OpenAI client retired (%s, tcp_shutdown=%d, fd_release=deferred_to_gc) %sz3Shared OpenAI client retire failed (%s) %s error=%s)rÌ   rÎ   rÏ   r®   rÐ   rÑ   )r)   rF   rl   Úshutdown_countrÔ   s        r   Ú_retire_shared_openai_clientz1ClientLifecycleMixin._retire_shared_openai_clientÍ   sw   € ð ˆ>Øð	yØ!×:Ñ:¸6ÓBˆNÜ�K‰KØbØ˜¨×(@Ñ(@Ó(Bõøô ò 	yÜ�L‰LÐNÐPVÐX\×XpÑXpÓXrÐtw×xÑxûð	yús   …7= ½	A6Á&A1Á1A6c                óZ  — d}	 t        | dd«      }|�|| j                  |«      z  }t
        | j                  dft        | j                  dffD ]B  \  }}}	 | j                  «       5  t        | |d«      }|r|d   nd}ddd«       �
 |||¬	«       ŒD 	 t        t        | dd«      dd«      }	t        |	«      r |	«        	 t        | dd«      }
t        |
«      r |
|«       t        j                  d||| j                  «       «       |S # t        $ r t        j	                  dd¬«       Y �Œw xY w# 1 sw Y   Œ²xY w# t        $ r t        j	                  d
|d¬«       Y �Œw xY w# t        $ r t        j	                  dd¬«       Y ŒÆw xY w# t        $ r t        j	                  dd¬«       Y ŒËw xY w)aê  FD-safe transport drain for an abandoned (timed-out) worker; returns sockets shut down.

        The worker may be blocked in an OpenSSL read; hard-closing from the timeout thread releases FDs under a
        live BIO (native corruption / SIGSEGV). Only ``shutdown()`` so the read sees EOF and the worker closes itself.

        See #94248.
        A delegation deadline abandons this agent's daemon worker while it may still be blocked inside an
        in-flight OpenSSL ``read`` (Codex Responses stream, httpx request). This helper only ``shutdown()``s
        pooled sockets (safe from any thread), settling blocked reads with EOF/EPIPE so the worker can
        unwind and run the real close from its own thread. See #70773, #94248.
        r   rF   Nz2Abandoned-worker drain: shared client sweep failedT©Úexc_infoÚrequestra   rk   z.Abandoned-worker drain: %s client abort failedÚ_codex_sessionÚrequest_interruptz.Abandoned-worker drain: codex interrupt failedÚ_active_request_abortz3Abandoned-worker drain: active request abort failedz[Abandoned-worker transports drained (%s, tcp_shutdown=%d, fd_release=deferred_to_worker) %s)rr   rÌ   rÐ   rÎ   rÑ   Ú_OPENAI_SLOTÚ_abort_request_openai_clientÚ_ANTHROPIC_SLOTÚ_abort_request_anthropic_clientrµ   ro   rÏ   r®   )r)   rl   ÚdrainedrF   Ú	slot_attrÚabortÚlabelrD   ÚcachedrÞ   Úabort_actives              r   Ú#_drain_transports_after_abandonmentz8ClientLifecycleMixin._drain_transports_after_abandonmentå   sÞ  € ð ˆð	^Ü˜T 8¨TÓ2ˆFØÐ!Ø˜4×8Ñ8¸Ó@Ñ@�ô ˜4×<Ñ<¸iÐHÜ˜d×BÑBÀKÐPð(
ò 	eÑ#ˆI�u˜eðeØ×-Ñ-Ó/ñ @Ü# D¨)°TÓ:�EÙ05˜U 8š_¸4�F÷@ð Ð%Ù˜&¨Õ0øð	eð	ZÜ '¬°Ð6FÈÓ(MÐObÐdhÓ iÐÜÐ)Ô*Ù!Ô#ð	_Ü" 4Ð)@À$ÓGˆLÜ˜Ô%Ù˜VÔ$ô 	�‰ØiØ�G˜T×5Ñ5Ó7ô	
ð ˆøôE ò 	^Ü�L‰LÐMÐX\ˆL×]ð	^ú÷@ð @ûô
 ò eÜ—‘ÐMÈuÐ_c�×dðeûô ò 	ZÜ�L‰LÐIÐTXˆLÖYð	Zûô ò 	_Ü�L‰LÐNÐY]ˆLÖ^ð	_ús_   „#D ÁD9Á%D-Á<D9Â*E! Â> F Ä D*Ä)D*Ä-D6	Ä2D9Ä9!EÅEÅ! FÆFÆ F*Æ)F*c                óü  — | j                  «       5  t        | dd «      }	 t        | dd«      xs dj                  «       j                  «       dk(  rddlm}  || | j                  «      }n| j                  | j                  |d¬«      }|| _        d d d «       | j                  d|› �¬«       y# t        $ r8}t        j                  d	|| j                  «       |«       Y d }~d d d «       y
d }~ww xY w# 1 sw Y   ŒdxY w)NrF   rg   r=   Úmoar   )Úbuild_moa_facadeT©rl   rÊ   z8Failed to rebuild shared primary client (%s) %s error=%sFúreplace:rk   )rµ   rr   rO   r   Úagent.moa_looprí   rb   Ú_create_openai_clientr?   rÐ   rÎ   Úwarningr®   rF   rØ   )r)   rl   Ú
old_clientrí   Ú
new_clientrÔ   s         r   rw   z3ClientLifecycleMixin._replace_primary_openai_client  sú   € Ø×%Ñ%Ó'ñ 	%Ü   x°Ó6ˆJðä˜D *¨bÓ1Ò7°R×>Ñ>Ó@×FÑFÓHÈEÒQÝ?Ù!1°$¸¿
¹
Ó!C‘Jà!%×!;Ñ!;¸D×<OÑ<OÐX^ÐgkÐ!;Ó!l�Jð %ˆDŒK÷	%ð* 	×)Ñ)¨*¸xÈÀxÐ=PÐ)ÔQØøô ò Ü—‘ØNÐPVÐX\×XpÑXpÓXrÐtwôó ÷	%ð 	%ûðú÷	%ð 	%ús5   ‘C2 A(B.ÂC2Â.	C/Â7&C*ÃC2Ã*C/Ã/C2Ã2C;c                óð  — | j                  «       5  t        | dd «      }|�| j                  |«      s|cd d d «       S 	 | j                  | j                  |d¬«      }|| _
        d d d «       t        j                  d|| j                  «       «       | j                  d|› �d¬«       S # t
        $ r7}t        j                  d|| j                  «       |«       t        d«      |‚d }~ww xY w# 1 sw Y   ŒŠxY w)NrF   Trî   z8Failed to recreate closed OpenAI client (%s) %s error=%sz'Failed to recreate closed OpenAI clientzBDetected closed shared OpenAI client; recreated before use (%s) %srï   )rµ   rr   r¾   rñ   r?   rÐ   rÎ   rò   r®   ÚRuntimeErrorrF   rÕ   )r)   rl   rF   rô   rÔ   s        r   Ú_ensure_primary_openai_clientz2ClientLifecycleMixin._ensure_primary_openai_client4  s	  € Ø×%Ñ%Ó'ñ 	%Ü˜T 8¨TÓ2ˆFØÐ!¨$×*GÑ*GÈÔ*OØ÷	%ñ 	%ðWØ!×7Ñ7¸×8KÑ8KÐTZÐcgÐ7Óh�
ð %ˆDŒK÷	%ô 	�‰ØPÐRXÐZ^×ZrÑZrÓZtô	
ð 	×!Ñ! &°8¸F¸8Ð1DÈTÐ!ÔRØÐøô ò WÜ—‘ØNÐPVÐX\×XpÑXpÓXrÐtwôô #Ð#LÓMÐSVÐVûð	Wú÷	%ð 	%ús.   ‘"C,¾B)ÁC,Â)	C)Â22C$Ã$C)Ã)C,Ã,C5Ú
api_kwargsc                 óv   ‡ ‡— t        ‰ t        «      sydt        dt        fˆfd„Št	        ˆˆ fd„dD «       «      S )zfTrue when the outbound request still has native image parts (Chat ``messages`` / Responses ``input``).FÚvaluer   c                 óÞ   •— t        | t        «      r7| j                  d«      dv xs" t        ˆfd„| j	                  «       D «       «      S t        | t
        «      xr t        ˆfd„| D «       «      S )NÚtype>   Ú	image_urlÚinput_imagec              3   ó.   •K  — | ]  } ‰|«      –— Œ y ­wr4   rI   ©Ú.0ÚvÚ_contains_images     €r   ú	<genexpr>z]ClientLifecycleMixin._api_kwargs_have_image_parts.<locals>._contains_image.<locals>.<genexpr>O  s   øè ø€ ò PØ+,‘O A×&ñPùó   ƒc              3   ó.   •K  — | ]  } ‰|«      –— Œ y ­wr4   rI   r   s     €r   r  z]ClientLifecycleMixin._api_kwargs_have_image_parts.<locals>._contains_image.<locals>.<genexpr>R  s   øè ø€ Ò2UÈ!±?À1×3EÑ2Uùr  )rM   r0   r@   ÚanyÚvaluesÚlist)rú   r  s    €r   r  zJClientLifecycleMixin._api_kwargs_have_image_parts.<locals>._contains_imageM  se   ø€ Ü˜%¤Ô&Ø—y‘y Ó(Ð,HÐHò ÌCó PØ05·±³ôPó Mð ô ˜e¤TÓ*ÒU¬sÓ2UÈuÔ2UÓ/UÐUr   c              3   ó€   •K  — | ]5  }t        ‰j                  |«      t        «      r‰|   D ]  } ‰|«      –— Œ Œ7 y ­wr4   )rM   r@   r	  )r  ÚfieldÚitemr  rø   s      €€r   r  zDClientLifecycleMixin._api_kwargs_have_image_parts.<locals>.<genexpr>S  sK   øè ø€ ò 
àÜ˜*Ÿ.™.¨Ó/´Ô6Ø" 5Ñ)ò	
ð ñ ˜D×!ð
Ø!ñ
ùs   ƒ;>)ÚmessagesÚinput)rM   r0   r   rL   r  )rø   r  s   `@r   Ú_api_kwargs_have_image_partsz1ClientLifecycleMixin._api_kwargs_have_image_partsG  sD   ù€ ô ˜*¤dÔ+Øð	V¤3ð 	V¬4õ 	Vô ô 
à.ô
ó 
ð 	
r   Úrequest_completeÚstream_request_completerå   c                 óX   — t        | |d «      }|€t        | |i x}«       t        |«       |S r4   )rr   ÚsetattrrJ   )r)   rå   rD   s      r   Ú_request_slotz"ClientLifecycleMixin._request_slotb  s2   € Ü˜˜i¨Ó.ˆØˆ=Ü�D˜)¨b [ UÔ1Ü˜ÔØˆr   rG   c                 ó  — | j                  «       5  | j                  |«      }|d   }|�|d   r
	 ddd«       y|d   s+|d   |k(  r#| j                  |«      sd|d<   |dfcddd«       S t        |«       d|fcddd«       S # 1 sw Y   yxY w)zDReturn ``(reusable_client, stale_client)``; at most one is non-None.rF   NrC   )NNrH   rG   T)rµ   r  r¾   rJ   )r)   rå   rG   rD   rè   s        r   Ú_checkout_request_slotz+ClientLifecycleMixin._checkout_request_sloti  s¢   € à×%Ñ%Ó'ñ 	 Ø×&Ñ& yÓ1ˆEØ˜8‘_ˆFØˆ~  x¢Ø!÷		 ð 	 ð
 ˜Ò$¨¨u©¸Ò)<ÀT×EbÑEbÐciÔEjØ"&��h‘Ø˜t�|÷	 ñ 	 ô ˜ÔØ˜�<÷	 ÷ 	 ò 	 ús   ‘B¹&BÁ)BÂB
c                 ó¤   — | j                  «       5  | j                  |«      }|d   €|j                  ||dd¬«       d d d «       y # 1 sw Y   y xY w)NrF   FT)rF   rG   rH   rC   )rµ   r  Úupdate)r)   rå   rF   rG   rD   s        r   Ú_store_request_slotz(ClientLifecycleMixin._store_request_slotx  sU   € Ø×%Ñ%Ó'ñ 	RØ×&Ñ& yÓ1ˆEØ�X‰Ð&Ø—‘ F°¸eÈD�ÔQ÷	R÷ 	Rñ 	Rús   ‘,AÁAc                 óØ   — | j                  «       5  | j                  |«      }|d   |u r-|| j                  v r|d   sd|d<   	 ddd«       yt        |«       ddd«       y# 1 sw Y   yxY w)zUOwner-thread release; True when the client stays cached (clean finish, not poisoned).rF   rH   FrC   NT)rµ   r  Ú_REQUEST_CLIENT_REUSE_REASONSrJ   )r)   rå   rF   rl   rD   s        r   Ú_release_request_slotz*ClientLifecycleMixin._release_request_slot  sy   € à×%Ñ%Ó'ñ 	#Ø×&Ñ& yÓ1ˆEØ�X‰ &Ñ(Ø˜T×?Ñ?Ñ?ÈÈjÒHYØ&+�E˜(‘OØ÷	#ð 	#ô ˜EÔ"÷	#ð ÷	#ð ús   ‘2A ÁA Á A)c                 óÂ   — | j                  «       5  t        | |d«      }|r|d   t        |d   «      fnd\  }}|�t        |«       ddd«       ||fS # 1 sw Y   fS xY w)z=Teardown: empty the slot and return ``(client, was_in_use)``.NrF   rC   )NF)rµ   rr   rL   rJ   )r)   rå   rD   rF   rC   s        r   Ú_take_request_slotz'ClientLifecycleMixin._take_request_slotŠ  sr   € à×%Ñ%Ó'ñ 	#Ü˜D )¨TÓ2ˆEÙIN˜e H™o¬t°E¸(±OÓ/DÑEÐTa‰NˆF�FØÐ Ü˜EÔ"÷		#ð
 �vˆ~Ð÷	#ð
 �vˆ~Ðús   ‘5AÁAc          	      óV  — |€y|t         k(  }|rdnd}|r| j                  «       n| j                  «       }| j                  «       5  | j	                  |«      }|d   |u rd|d<   ddd«       	 t        t        t        |«      dd«      «      r|j                  «        y| j                  |«      }|dk(  rt        j                  nt        j                  }	 |	d	|||||dk(  rt        «       yd
«       y# 1 sw Y   ŒŽxY w# t        $ r#}
t        j                  d||||
«       Y d}
~
yd}
~
ww xY w)aR  Cross-thread abort (interrupt loop, stale detector): ``shutdown(SHUT_RDWR)`` without releasing FDs.

        ``close()`` from a non-owning thread races the live SSL BIO and corrupts unrelated FDs; shutdown unblocks
        the owner's recv/send so it closes from its own context. The slot is poisoned so the pool is never reused.
        NÚ	AnthropicÚOpenAIrF   TrH   Úcancelr   z^%s client aborted (%s, shared=False, tcp_force_closed=%d, deferred_close=stranger_thread) %s%sr=   z5%s client abort failed (%s, shared=False) %s error=%s)râ   r±   r®   rµ   r  ro   rr   rü   r"  rÌ   rÎ   rò   rÏ   Ú_NO_SOCKETS_SUFFIXrÐ   rÑ   )r)   rå   rF   rl   ra   rç   ÚcontextrD   r×   Ú_logrÔ   s              r   Ú_abort_request_slot_clientz/ClientLifecycleMixin._abort_request_slot_client“  s&  € ð ˆ>ØØ¤Ñ0ˆ	Ù(‘¨hˆÙ3<�$×-Ñ-Ô/À$×BZÑBZÓB\ˆØ×%Ñ%Ó'ñ 	)Ø×&Ñ& yÓ1ˆEØ�X‰ &Ñ(Ø$(��jÑ!÷	)ð	oäœ¤ V£¨h¸Ó=Ô>Ø—‘”ØØ!×:Ñ:¸6ÓBˆNð &4°qÒ%8”6—>’>¼f¿k¹kˆDÙØpØ�v˜~¨wÈnÐ`aÒNaÔ8Jõàgiõ÷!	)ð 	)ûô( ò 	oÜ�L‰LÐPÐRWÐY_ÐahÐjm×nÑnûð	oús1   ÁC0Á,/C< ÂAC< Ã)C< Ã0C9Ã<	D(ÄD#Ä#D()rø   c          	      óÖ  — ddl m} | j                  |¬«      }| j                  dk(  st	        ||«      r|S | j                  «       5  t        | j                  «      }d d d «       dd<   t        t        |j                  dd«      «      d«      }|r(| j                  |xs i «      rdd	lm}  |d
d
¬«      |d<   | j                  t        |«      \  }}	|�|S |	�| j!                  |	d|› �d¬«       | j#                  ||d¬«      }
|j%                  «       D ��ci c]#  \  }}|t	        |t        «      rt        |«      n|“Œ% }}}| j'                  t        |
|«       |
S # 1 sw Y   ŒþxY wc c}}w )Nr   r·   rk   rì   Úmax_retriesr>   r=   r5   )Úcopilot_request_headersT)Úis_agent_turnÚ	is_visionri   úreuse_evict:Frî   )r»   r¸   r÷   rg   rM   rµ   r0   r?   r
   rN   r@   r  Úhermes_cli.copilot_authr)  r  rà   rÕ   rñ   Úitemsr  )r)   rl   rø   r¸   Úprimary_clientÚrequest_kwargsÚ
is_copilotr)  rè   ÚstalerF   Úkr  Úsnapshots                 r   Ú_create_request_openai_clientz2ClientLifecycleMixin._create_request_openai_clientµ  sg  € Ý&Ø×;Ñ;À6Ð;ÓJˆØ�=‰=˜EÒ!¤Z°ÀÔ%EØ!Ð!Ø×%Ñ%Ó'ñ 	7Ü! $×"5Ñ"5Ó6ˆN÷	7ð )*ˆ�}Ñ%Ü*¬3¨~×/AÑ/AÀ*ÈbÓ/QÓ+RÐTgÓhˆ
Ù˜$×;Ñ;¸JÒ<LÈ"ÔMÝGÙ0GÐVZÐfjÔ0kˆNÐ,Ñ-Ø×3Ñ3´LÀ.ÓQ‰ˆ�ØÐØˆMØÐØ×%Ñ% e°lÀ6À(Ð4KÐTYÐ%ÔZØ×+Ñ+¨NÀ6ÐRWÐ+ÓXˆàIW×I]ÑI]ÓI_×`ÁÀÀA�A¤*¨Q´Ô"5”t˜A”w¸1Ñ<Ð`ˆÑ`Ø× Ñ ¤¨v°xÔ@Øˆ÷%	7ð 	7üó  as   ÁEÄ(E%ÅE"c                ó\   — | j                  t        ||«      s| j                  ||d¬«       y y )NFrî   )r  rà   rÕ   ©r)   rF   rl   s      r   Ú_close_request_openai_clientz1ClientLifecycleMixin._close_request_openai_clientÎ  s/   € Ø×)Ñ)¬,¸ÀÔGØ×%Ñ% f°VÀEÐ%ÕJð Hr   c                ó”   — | j                  t        «      \  }}|€y|r| j                  ||› d�¬«       y| j                  ||d¬«       y)z?Teardown hook: really close the cached per-request wire client.NÚ
_in_flightrk   Frî   )r  rà   rá   rÕ   ©r)   rl   rF   rC   s       r   Ú#_close_cached_request_openai_clientz8ClientLifecycleMixin._close_cached_request_openai_clientÒ  sR   € à×0Ñ0´Ó>‰ˆ�Øˆ>ØÙð ×-Ñ-¨fÀ¸xÀzÐ=RÐ-ÕSà×%Ñ% f°VÀEÐ%ÕJr   c                ó4   — | j                  t        ||¬«       y ©Nrk   )r&  rà   r7  s      r   rá   z1ClientLifecycleMixin._abort_request_openai_clientÞ  s   € Ø×'Ñ'¬°fÀVÐ'ÕLr   c                 óä   — t        | dd«      dk(  rdt        | dd«      xs dfS d| j                  t        | dd«      t        | j                  | j                  «      t        t        | dd	«      «      fS )
zeCache key over everything forcing a fresh client: credential, base URL/region, timeout, 1M-beta flag.rg   NrW   Ú_bedrock_regionz	us-east-1Údirectrt   Ú_oauth_1m_beta_disabledF)rr   rs   r	   rg   rb   rL   r°   s    r   Ú_request_anthropic_client_keyz2ClientLifecycleMixin._request_anthropic_client_keyá  su   € ä�4˜ TÓ*¨iÒ7Øœw tÐ->ÀÓLÒ[ÐP[Ð\Ð\à�d×-Ñ-¬w°tÐ=RÐTXÓ/YÜ(¨¯©¸¿
¹
ÓCÄTÌ'ÐRVÐXqÐsxÓJyÓEzð
ð 	
r   Útokenc                 ó`   — ddl m}  |||t        | j                  | j                  «      ¬«      S )z[Native Anthropic client for ``token``/``base_url`` with the provider/model request timeout.r   r]   rd   )rp   r^   r	   rg   rb   )r)   rD  r>   r^   s       r   Ú_build_direct_anthropic_clientz3ClientLifecycleMixin._build_direct_anthropic_clientê  s*   € åBÙ% e¨XÔ?[Ð\`×\iÑ\iÐko×kuÑkuÓ?vÔwÐwr   c                 óN   — ddl m}  |t        | dd«      || j                  ¬«      S )zoOAuth flag only on native Anthropic routes; third-party Anthropic-protocol endpoints must not trip OAuth paths.r   )r`   rt   Nrf   )rq   r`   rr   rg   )r)   rD  r`   s      r   Ú_anthropic_oauth_flagz*ClientLifecycleMixin._anthropic_oauth_flagï  s&   € åHÙ'¬°Ð6KÈTÓ(RÐTYÐdh×dqÑdqÔrÐrr   c                 óh   — ddl m}m} |d   dk(  r ||d   «      S  ||d   |d   |d   |d   ¬«      S )	Nr   )Úbuild_anthropic_bedrock_clientr^   rW   é   é   é   é   )re   Údrop_context_1m_beta)rp   rJ  r^   )r)   rG   rJ  r^   s       r   Ú_build_anthropic_client_for_keyz4ClientLifecycleMixin._build_anthropic_client_for_keyô  sD   € ßbØˆq‰6�YÒÙ1°#°a±&Ó9Ð9Ù% c¨!¡f¨c°!©f¸cÀ!¹fÐ[^Ð_`Ñ[aÔbÐbr   c                óh  — | j                   dk(  r| j                  «        | j                  «       }| j                  t        |«      \  }}|�|S |�| j                  |d|› �¬«       | j                  |«      }t        j                  d|| j                  «       «       | j                  t        ||«       |S )u<  Build (or reuse) a request-local Anthropic client for one in-flight call.

        The watchdog must never ``close()`` a client a worker is still reading (fd recycled under a live SSL BIO â†’
        TLS record in a SQLite header); per-request clients let the stranger ``shutdown()`` while the owner closes.
        rY   r,  rk   z6Anthropic request client created (%s, shared=False) %s)Úapi_modeÚ)_try_refresh_anthropic_client_credentialsrC  r  râ   Ú_close_request_anthropic_clientrP  rÎ   rÑ   r±   r  )r)   rl   rG   rè   r2  rF   s         r   Ú _create_request_anthropic_clientz5ClientLifecycleMixin._create_request_anthropic_clientú  s®   € ð �=‰=Ð0Ò0Ø×:Ñ:Ô<Ø×0Ñ0Ó2ˆØ×3Ñ3´OÀSÓI‰ˆ�ØÐØˆMØÐØ×0Ñ0°ÀÈfÈXÐ?VÐ0ÔWØ×5Ñ5°cÓ:ˆÜ�‰ÐMÈvÐW[×WrÑWrÓWtÔuØ× Ñ ¤°&¸#Ô>Øˆr   c                ó>  — |�| j                  t        ||«      ry	 | j                  |«       |j                  «        t        j                  d|| j                  «       «       y# t        $ r0}t        j                  d|| j                  «       |«       Y d}~yd}~ww xY w)zmOwner-thread close: clean finish keeps the pool warm; otherwise force-close sockets (CLOSE-WAIT) + SDK close.Nz-Anthropic client closed (%s, shared=False) %sz<Anthropic client close failed (%s, shared=False) %s error=%s)	r  râ   rÌ   rÍ   rÎ   rÏ   r±   rÐ   rÑ   )r)   rF   rl   rÔ   s       r   rT  z4ClientLifecycleMixin._close_request_anthropic_client  s‰   € àˆ>˜T×7Ñ7¼ÈÐQWÔXØð	Ø×)Ñ)¨&Ô1Ø�L‰LŒNÜ�K‰KÐGÈÐQU×QlÑQlÓQnÕoøÜò 	Ü�L‰LØNÐPVÐX\×XsÑXsÓXuÐwz÷ñ ûð	ús   œAA# Á#	BÁ,&BÂBc                óö   — | j                  t        «      \  }}|€y|r| j                  ||› d�¬«       yt        t        «      5  | j                  |«       |j                  «        ddd«       y# 1 sw Y   yxY w)zDTeardown hook: really close the cached per-request Anthropic client.Nr:  rk   )r  râ   rã   r   rÐ   rÌ   rÍ   r;  s       r   Ú&_close_cached_request_anthropic_clientz;ClientLifecycleMixin._close_cached_request_anthropic_client  sr   € à×0Ñ0´ÓA‰ˆ�Øˆ>ØÙØ×0Ñ0°À6À(È*Ð@UÐ0ÔVØÜ”iÓ ñ 	Ø×)Ñ)¨&Ô1Ø�L‰LŒN÷	÷ 	ñ 	ús   Á"A/Á/A8c                ó4   — | j                  t        ||¬«       y r>  )r&  râ   r7  s      r   rã   z4ClientLifecycleMixin._abort_request_anthropic_client&  s   € Ø×'Ñ'¬¸ÈÐ'ÕOr   c                 óh   — | j                   | j                  d<   | j                  | j                  d<   y)zPMirror ``self.api_key`` / ``self.base_url`` into the OpenAI-style client kwargs.r<   r>   N)r<   r?   r>   r°   s    r   Ú_sync_client_kwargs_credentialsz4ClientLifecycleMixin._sync_client_kwargs_credentials*  s*   € à)-¯©ˆ×Ñ˜IÑ&Ø*.¯-©-ˆ×Ñ˜JÒ'r   r<   c                óº   — |j                  «       |j                  «       j                  d«      c| _        | _        | j	                  «        | j                  |¬«      S )zTApply a fresh key/base_url to the OpenAI-style kwargs and rebuild the shared client.ú/rk   )rO   Úrstripr<   r>   r[  rw   )r)   r<   r>   rl   s       r   Ú_adopt_openai_credentialsz.ClientLifecycleMixin._adopt_openai_credentials/  sJ   € à&-§m¡m£o°x·~±~Ó7G×7NÑ7NÈsÓ7SÐ#ˆŒ�d”mØ×,Ñ,Ô.Ø×2Ñ2¸&Ð2ÓAÐAr   )Úforcer`  c                ó¢  — | j                   dk7  s| j                  dvry	 ddlm} | j                  dk(  r|j                  n|j
                  } |d¬«      }t        |j                  d	«      xs d
«      j                  «       }t        | j                  xs d
«      j                  «       }|r(|r&||k7  r!t        j                  d| j                  «       y	  ||¬«      }|j                  d	«      |j                  d«      }
}	t        |	|
«      sy|r4|	j                  «       |k(  r!t        j                  d| j                  «       y| j                  |	|
| j                  › d�¬«      S # t        $ r+}t        j                  d| j                  |«       Y d }~yd }~ww xY w# t        $ r+}t        j                  d| j                  |«       Y d }~yd }~ww xY w)NÚcodex_responses>   ú	xai-oauthúopenai-codexFr   ©Úauthrd  )Úrefresh_if_expiringz%s singleton read failed: %sr<   r=   z«%s singleton tokens differ from the active api_key; skipping singleton force-refresh to avoid silent account swap. Reactive credential rotation should go through the pool.)Úforce_refreshz %s credential refresh failed: %sr>   zM%s credential refresh returned the same token; refresh likely failed silentlyÚ_credential_refreshrk   )rR  rg   r   rf  Ú!resolve_codex_runtime_credentialsÚ%resolve_xai_oauth_runtime_credentialsrÐ   rÎ   rÑ   rN   r@   rO   r<   rQ   r_  )r)   r`  Ú_authÚresolveÚsingleton_nowrÔ   Úsingleton_keyÚold_keyÚcredsr<   r>   s              r   Ú%_try_refresh_codex_client_credentialsz:ClientLifecycleMixin._try_refresh_codex_client_credentials5  sš  € Ø�=‰=Ð-Ò-°·±ÐFcÑ1cØð		Ý0à;?¿=¹=ÈNÒ;Z�×7Ò7Ø×@Ñ@ð ñ $¸Ô>ˆMô ˜M×-Ñ-¨iÓ8Ò>¸BÓ?×EÑEÓGˆÜ�d—l‘lÒ( bÓ)×/Ñ/Ó1ˆÙ™W¨¸'Ò)AÜ�L‰Lð`Øae×anÑanôð ð	Ù¨%Ô0ˆEð "ŸI™I iÓ0°%·)±)¸JÓ2G�ˆÜ% g¨xÔ8Øá�w—}‘}“¨'Ò1Ü�L‰LÐhÐjn×jwÑjwÔxØØ×-Ñ-¨g°xÈ4Ï=É=È/ÐYlÐHmÐ-ÓnÐnøô/ ò 	Ü�L‰LÐ7¸¿¹ÈÔLÜûð	ûô ò 	Ü�L‰LÐ;¸T¿]¹]ÈCÔPÜûð	ús/    6E# Ã	F Å#	FÅ,!FÆFÆ	GÆ#!G	Ç	G©r`  Úrequire_accountrt  c                ó®  — | j                   dk7  s| j                  dvry	 ddlm} t	        dd«      } |||| j
                  xs d ¬«      }|j                  d
«      |j                  d«      }}t        ||«      syt        |«      j                  «       t        | j
                  xs d«      j                  «       k(  r`t        |«      j                  «       j                  d«      t        | j                  xs d«      j                  «       j                  d«      k(  ry|�O	 ddlm}	  |	t        |«      «      j                  d«      }
t        |
xs d«      |k7  rt        j#                  d«       y| j                  dk(  rn|j                  «       |j                  «       j                  d«      c| _        | _        | j
                  | j                  c| _        | _        | j)                  «        y| j*                  j-                  dd «       | j/                  ||d¬«      S # t        $ r }t        j                  d	|«       Y d }~yd }~ww xY w# t        $ r d }
Y �Œw xY w)NÚnous)Úchat_completionsrY   Fr   )Ú resolve_nous_runtime_credentialsÚHERMES_NOUS_TIMEOUT_SECONDSé   )Útimeout_secondsrh  Ústale_access_tokenz"Nous credential refresh failed: %sr<   r>   r=   r]  ©Ú_decode_jwt_claimsÚsubz†Nous pre-expiry adoption skipped: the store's key belongs to a different account than the one in hand; keeping the current credential.rY   Tri   Únous_credential_refreshrk   )rg   rR  Úhermes_cli.authrx  r   r<   rÐ   rÎ   rÑ   r@   rQ   rN   rO   r^  r>   Úhermes_cli.auth_constantsr~  rÏ   rs   rt   Ú_rebuild_anthropic_clientr?   Úpopr_  )r)   r`  rt  rx  re   rq  rÔ   r<   r>   r~  Únew_accounts              r   Ú$_try_refresh_nous_client_credentialsz9ClientLifecycleMixin._try_refresh_nous_client_credentialsZ  s  € à�=‰=˜FÒ" d§m¡mÐ;eÑ&eØð
	ÝHÜÐ =¸rÓBˆGñ 5Ø '°uÐQU×Q]ÑQ]ÒQeÐaeôˆEð "ŸI™I iÓ0°%·)±)¸JÓ2G�ˆÜ% g¨xÔ8ØÜ�‹L×ÑÓ ¤C¨¯©Ò(:¸Ó$;×$AÑ$AÓ$CÒCÜ˜“M×'Ñ'Ó)×0Ñ0°Ó5¼¸T¿]¹]Ò=PÈbÓ9Q×9WÑ9WÓ9Y×9`Ñ9`ÐadÓ9eÒeØØÐ&ð#ÝHÙ0´°W³Ó>×BÑBÀ5ÓI�ô �;Ò$ "Ó%¨Ò8Ü—‘ðLôð Ø�=‰=Ð0Ò0Ø*1¯-©-«/¸8¿>¹>Ó;K×;RÑ;RÐSVÓ;WÐ'ˆDŒL˜$œ-Ø@DÇÁÈdÏmÉmÐ=ˆDÔ# TÔ%=Ø×*Ñ*Ô,Øà×Ñ×ÑÐ 1°4Ô8Ø×-Ñ-¨g°xÐHaÐ-ÓbÐbøô9 ò 	Ü�L‰LÐ=¸sÔCÜûð	ûô ò #Ø"“ð#ús)    +H Ä&I È	IÈ"H=È=IÉIÉIé´   c                 ó„  — t        | dd«      dk7  st        | dd«      sy	 ddlm}  || j                  «      }|j                  d	«      |j                  d
«      }}|r:t        |t        t        f«      r$|t        j                  «       z
  | j                  kD  ry| j                  dt        |«      ¬«      S # t        $ r Y yw xY w)a<  Swap in a fresh Nous agent key BEFORE the one in hand expires, so the request never 401s.

        The agent key is a JWT; its ``exp`` is read locally (no network). Inside the skew the store
        is re-read under the auth-store lock: the keepalive thread normally holds a fresh key already
        (adopt, no POST), otherwise ONE refresh runs and every peer adopts its result. Before this,
        every agent in a process learned about the hourly expiry from its own 401, all in the same
        minute (620 in one 200-subagent run), and the pool benched the sole credential for all of
        them. Returns True when a new key was adopted.

        Identity guard: the replacement must belong to the SAME account (``sub`` claim) as the key
        in hand. The store holds the logged-in singleton; an agent running on an explicitly supplied
        or pool-selected key for a different account must never be silently moved onto it (that
        changes who is billed). When either side lacks a ``sub`` nothing is adopted here; the
        reactive 401 path is unchanged.
        rg   r=   rv  r<   NFr   r}  Úexpr  rs  )rr   r‚  r~  r<   rÐ   r@   rM   ÚintÚfloatÚtimeÚ_NOUS_KEY_ADOPT_SKEW_Sr†  rN   )r)   r~  Úclaimsr‰  Úaccounts        r   Ú_adopt_nous_key_before_expiryz2ClientLifecycleMixin._adopt_nous_key_before_expiryˆ  s´   € ô  �4˜ RÓ(¨FÒ2¼'À$È	ÐSWÔ:XØð	ÝDÙ'¨¯©Ó5ˆFð —z‘z %Ó(¨&¯*©*°UÓ*;ˆWˆÙœj¨¬s´E¨lÔ;¸sÄTÇYÁYÃ[Ñ?PÐSW×SnÑSnÒ?nØØ×8Ñ8¸uÔVYÐZaÓVbÐ8ÓcÐcøô ò 	Ùð	ús    B3 Â3	B?Â>B?c                 ó®  ‡— 	 ddl mŠ ddlm} |j                  | j                  «      }|�rIt        |dd«      dk(  �r8t        |dd	«      �r*t        d
„ ˆfd„|j                  D «       D «       d«      }|sy|j                  }|r% ‰|«      j                  «       j                  d«      nd}|j                  xs dj                  «       j                  d«      }|xs |}| j                  dk(  r*ddlm} ddlm}	m}
  |	 |
«       d«      } ||xs |«      }�n| j                  dv �rddlm} | j                  dk(  r|j(                  n|j*                  } |||j                  |«      j                  d«      }n»| j                  dk(  r«	 ddlm}  |t        | dd«      xs d«      }t/        |xs i j                  d«      xs d«      j                  «       }|r ‰|«      j                  «       nd}|r|syt/        |j                  d«      xs d«      j                  «       j                  d«      x}}ny|sy|||fS # t        $ r Y yw xY w# t        $ r Y yw xY w)z¿Current ``.env``-sourced ``(api_key, base_url, default_base)`` for this provider, or ``None``.

        Covers registry api-key providers and named custom providers with ``key_env``.
        r   )Úget_env_prefer_dotenv)ÚPROVIDER_REGISTRYNÚ	auth_typer=   r<   Úapi_key_env_varsrI   c              3   ó&   K  — | ]	  }|sŒ|–— Œ y ­wr4   rI   )r  r3  s     r   r  z@ClientLifecycleMixin._resolve_env_credentials.<locals>.<genexpr>²  s   è ø€ Òq !ÒopœAÑqùs   ‚Šc              3   óJ   •K  — | ]  } ‰|«      j                  «       –— Œ y ­wr4   )rO   )r  r  r’  s     €r   r  z@ClientLifecycleMixin._resolve_env_credentials.<locals>.<genexpr>²  s    øè ø€ Ò'kÈQÑ(=¸aÓ(@×(FÑ(F×(HÑ'kùs   ƒ #r]  Úactual©Únormalize_actual_base_url)Ú_config_base_url_for_providerÚ_get_model_config)úkimi-codingÚzaire  r�  Úcustom)Ú_get_named_custom_providerÚrequested_providerÚkey_envr>   )Úagent.credential_poolr’  r�  r“  ÚImportErrorr@   rg   rr   Únextr•  Úbase_url_env_varrO   r^  Úinference_base_urlrš  Úhermes_cli.runtime_providerr›  rœ  r   rf  Ú_resolve_kimi_base_urlÚ_resolve_zai_base_urlr   rN   )r)   r“  Úpconfigr<   Úurl_varÚenv_urlÚdefault_baser>   rš  r›  rœ  Úconfigured_baserl  Úresolverr   Úcustom_providerr¢  r’  s                    @r   Ú_resolve_env_credentialsz-ClientLifecycleMixin._resolve_env_credentials¥  s4  ø€ ð
	ÝCÝ9ð $×'Ñ'¨¯©Ó6ˆÚ”w˜w¨°RÓ8¸IÓEÌ'ÐRYÐ[mÐoqÕJräÑqÓ'kÐRY×RjÑRjÔ'kÔqÐsuÓvˆGÙØØ×.Ñ.ˆGÙLSÑ+¨GÓ4×:Ñ:Ó<×CÑCÀCÔHÐY[ˆGØ#×6Ñ6Ò<¸"×CÑCÓE×LÑLÈSÓQˆLØÒ. ,ˆHØ�}‰} Ò(ÝEßhÙ"?Ñ@QÓ@SÐU]Ó"^�Ù4°_Ò5PÈÓQ’Ø—‘Ð"8Ò8Ý4Ø;?¿=¹=ÈMÒ;Y˜5×7Ò7Ð_d×_zÑ_z�Ù# G¨W×-GÑ-GÈÓQ×XÑXÐY\Ó]‘Ø�]‰]˜hÒ&ðÝRñ 9¼ÀÐG[Ð]_Ó9`Ò9fÐdfÓgˆOÜ˜?Ò0¨b×5Ñ5°iÓ@ÒFÀBÓG×MÑMÓOˆGÙ@GÑ+¨GÓ4×:Ñ:Ô<ÈRˆGÙ"©'Øä&)¨/×*=Ñ*=¸jÓ*IÒ*OÈRÓ&P×&VÑ&VÓ&X×&_Ñ&_Ð`cÓ&dÐdˆH‘|àÙØØ˜ ,Ð.Ð.øôM ò 	Ùð	ûô2 ò Ùðús#   ƒH9 ÆI È9	IÉIÉ	IÉIr®  c                 óP  — t        | dd«      }| j                  xs dj                  «       j                  d«      }||k(  xr || j                  k(  }|€>|| j                  k7  xr t        | dd«      duxr t        | dd«      }||k(  xr | xr | S ||f|k7  xr |||d   hv xr | S )z»Adopt only env *edits* (resolved value changed since last look), never drift from ``self.*``:
        pool rotation/failover and a config ``model.base_url`` legitimately move the session.Ú_env_creds_seenNr=   r]  Ú_credential_poolÚ_credential_pool_entry_idr   )rr   r>   rO   r^  r<   )r)   r<   r>   r®  ÚprevÚcurrent_baseÚ	unchangedÚpool_rotateds           r   Ú_should_adopt_env_credentialsz2ClientLifecycleMixin._should_adopt_env_credentialsÕ  sÙ   € ô �tÐ.°Ó5ˆØŸ™Ò+¨×2Ñ2Ó4×;Ñ;¸CÓ@ˆØ Ñ,ÒH°¸D¿L¹LÑ1Hˆ	Øˆ<ð ˜4Ÿ<™<Ñ'ò E¬G°DÐ:LÈdÓ,SÐ[_Ð,_ò EÜ˜DÐ"=¸tÓDð ð   <Ñ/ÒV¸	°MÒVÈ,ÐFVÐVà˜'Ð" dÑ*Òh¨|ÀÈdÐSTÉgÐ?VÐ/VÒhÐ_hÐ[hÐhr   c                 ó(  — | j                   dk7  st        | dd«      ry| j                  «       }|€y|\  }}}| j                  |||«      s
||f| _        yddlm}  || j                  «       ||«      k7  }| j                  | j                  }}t        | j                  «      }	||c| _        | _        | j                  «        | j                  |¬«       | j                  d¬«      sE||c| _        | _        | j                  j                  «        | j                  j                  |	«       y	 dd	lm}
  |
| «       ||f| _        t&        j+                  d| j,                  | j                  «       y# t$        $ r t&        j)                  d
d¬«       Y ŒWw xY w)uÛ  Adopt ``~/.hermes/.env`` credential/base-url edits at the turn boundary (a Settings save updates ``.env``
        but a live worker keeps init-time values). Adoption rule: ``_should_adopt_env_credentials``.

        Covers api-key registry providers and named custom providers with a ``key_env`` (#67935) â€” the
        latter resolve to ``provider="custom"`` with no registry entry, so they are matched through the
        runtime provider's config lookup instead.
        rw  Ú_fallback_activatedFr   ©Únormalize_route_base_url©Úroute_changedÚenv_credential_refreshrk   )Úsync_credential_pool_entry_idz6sync_credential_pool_entry_id after env refresh failedTrÚ   z4Applied updated .env credentials for %s: endpoint %s)rR  rr   r²  r»  r´  Úhermes_cli.route_identityr¿  r>   r<   r0   r?   r[  Ú_reapply_route_client_configrw   Úclearr  Úagent.agent_runtime_helpersrÃ  rÐ   rÎ   rÑ   rÏ   rg   )r)   Úresolvedr<   r>   r®  r¿  rÁ  Úprior_api_keyÚprior_base_urlÚprior_client_kwargsrÃ  s              r   Ú#_try_refresh_env_client_credentialsz8ClientLifecycleMixin._try_refresh_env_client_credentialsæ  s‚  € ð �=‰=Ð.Ò.´'¸$Ð@UÐW\Ô2]ØØ×0Ñ0Ó2ˆØÐØØ*2Ñ'ˆ�˜<Ø×1Ñ1°'¸8À\ÔRØ$,¨gÐ#6ˆDÔ ØÝFÙ0°·±Ó?ÑC[Ð\dÓCeÑeˆØ(,¯©°d·m±m�~ˆÜ" 4×#6Ñ#6Ó7ÐØ&-¨xÐ#ˆŒ�d”mØ×,Ñ,Ô.à×)Ñ)¸Ð)ÔFØ×2Ñ2Ð:RÐ2ÔSà*7¸Ð'ˆDŒL˜$œ-Ø×Ñ×%Ñ%Ô'Ø×Ñ×&Ñ&Ð':Ô;Øð	bÝQÙ)¨$Ô/ð !)¨'Ð2ˆÔÜ�‰ÐJÈDÏMÉMÐ[_×[hÑ[hÔiØøô	 ò 	bÜ�L‰LÐQÐ\`ˆLÖað	bús   Ä+E. Å. FÆFc                 ó0  — | j                   dk7  s| j                  dk7  ry	 ddlm}  |«       \  }}t        ||«      xr | j                  ||d¬	«      }|rt
        j                  d
«       |S # t        $ r }t
        j                  d|«       Y d}~yd}~ww xY w)zjRe-mint the Vertex OAuth2 token (~1h TTL; long sessions 401 on the expired bearer) and rebuild the client.rw  ÚvertexFr   )Úget_vertex_configz$Vertex credential refresh failed: %sNÚvertex_credential_refreshrk   zVertex AI OAuth token refreshed)
rR  rg   Úagent.vertex_adapterrÏ  rÐ   rÎ   rÑ   rQ   r_  rÏ   )r)   rÏ  rD  r>   rÔ   Úoks         r   Ú&_try_refresh_vertex_client_credentialsz;ClientLifecycleMixin._try_refresh_vertex_client_credentials  sš   € à�=‰=Ð.Ò.°$·-±-À8Ò2KØð	Ý>Ù/Ó1‰OˆE�8ô $ E¨8Ó4ò 
¸×9WÑ9WØ�8Ð$?ð :Xó :
ˆñ Ü�K‰KÐ9Ô:Øˆ	øô ò 	Ü�L‰LÐ?ÀÔEÜûð	ús   ¡A, Á,	BÁ5BÂBÚenterprise_base_urlc                óÔ   — || _         |r|j                  d«      | _        | j                  «        | j	                  t        | j                  xs d«      «       | j                  |¬«      S )Nr]  r=   rk   )r<   r^  r>   r[  Ú"_apply_client_headers_for_base_urlrN   rw   )r)   rD  rÔ  rl   s       r   Ú_apply_copilot_tokenz)ClientLifecycleMixin._apply_copilot_token   sZ   € ØˆŒÙØ/×6Ñ6°sÓ;ˆDŒMØ×,Ñ,Ô.Ø×/Ñ/´°D·M±MÒ4GÀRÓ0HÔIØ×2Ñ2¸&Ð2ÓAÐAr   c                 ó4  — | j                  «       sy	 ddlm}m}m}  |«       \  }}t        |t        «      r|j                  «       ndd}}|sy	  ||«        ||«      \  }}	t        |t        «      r"|j                  «       r|j                  «       |	}}| j                  ||d¬	«      }
|
rt        j                  d
|«       |
S # t
        $ r }t        j                  d|«       Y d}~yd}~ww xY w# t
        $ r }t        j                  d|«       Y d}~Œ~d}~ww xY w)a?  Refresh Copilot credentials and rebuild the shared OpenAI client (caller enforces the single-shot guard).

        The raw GitHub token is stable; the short-TTL *exchanged* IDE token is what expires mid-turn (``401 IDE
        token expired``), so force a fresh exchange rather than re-resolving the raw token.
        Fr   ©Úresolve_copilot_tokenÚget_copilot_api_tokenÚevict_cached_exchanged_tokenz%Copilot credential refresh failed: %sNr=   z8Copilot 401 re-exchange failed, using resolved token: %sÚcopilot_credential_refreshrk   z%Copilot credentials refreshed from %s)Ú_is_copilot_providerr-  rÚ  rÛ  rÜ  rÐ   rÎ   rÑ   rM   rN   rO   r×  rÏ   )r)   rÚ  rÛ  rÜ  Ú	new_tokenÚtoken_sourcerÔ   rÔ  Ú	api_tokenÚexchanged_base_urlrÒ  s              r   Ú'_try_refresh_copilot_client_credentialsz<ClientLifecycleMixin._try_refresh_copilot_client_credentials(  s  € ð ×(Ñ(Ô*Øð	ßzÑzÙ&;Ó&=Ñ#ˆI�|ô @JÈ)ÔUXÔ?Y¨)¯/©/Ô*;Ð_aÐdhÐ&ˆ	ÙØð	ZÙ(¨Ô3Ù,AÀ)Ó,LÑ)ˆIÐ)Ü˜)¤SÔ)¨i¯o©oÔ.?Ø1:·±Ó1BÐDVÐ.�	ð ×&Ñ& yÐ2EÐNjÐ&ÓkˆÙÜ�K‰KÐ?ÀÔNØˆ	øô# ò 	Ü�L‰LÐ@À#ÔFÜûð	ûô ò 	ZÜ�L‰LÐSÐUX×YÑYûð	Zús0   “C ÁAC. Ã	C+ÃC&Ã&C+Ã.	DÃ7DÄDc                 ó"  — | j                  «       sy	 ddlm}m}m}  |«       \  }}t        |t        «      r|j                  «       sy|j                  «       } ||«        ||«      \  }}t        |t        «      r|j                  «       sy||k(  r|st        j                  d«       y| j                  |j                  «       |d¬«      }	|	rt        j                  d	|«       |	S # t        $ r }t        j                  d|«       Y d}~yd}~ww xY w)
uV  Force a fresh Copilot token exchange + client rebuild after a 400 (single-shot, caller-guarded).

        Copilot surfaces a stale credential as ``400 model_not_available_for_integrator`` / ``model_not_supported``
        â€” typically a raw ``ghu_`` token cached when the startup exchange degraded (restricted integrator allowlist).
        Fr   rÙ  z,Copilot stale-credential recovery failed: %sNz€Copilot stale-credential recovery: exchange still degraded to raw token; skipping retry (network/exchange endpoint unavailable).Ú!copilot_stale_credential_recoveryrk   zGCopilot credentials re-exchanged after stale-credential 400 (source=%s))rÞ  r-  rÚ  rÛ  rÜ  rM   rN   rO   rÐ   rÎ   rÑ   rò   r×  rÏ   )
r)   rÚ  rÛ  rÜ  Ú	raw_tokenrà  rá  rÔ  rÔ   rÒ  s
             r   Ú%_try_recover_stale_copilot_credentialz:ClientLifecycleMixin._try_recover_stale_copilot_credentialF  sú   € ð ×(Ñ(Ô*Øð	ßzÑzÙ&;Ó&=Ñ#ˆI�|Ü˜i¬Ô-°Y·_±_Ô5FØØ!Ÿ™Ó)ˆIá(¨Ô3Ù-BÀ9Ó-MÑ*ˆIÐ*ô ˜)¤SÔ)°·±Ô1BØà˜	Ò!Ñ*=Ü�N‰Nð;ôð Ø×&Ñ& y§¡Ó'8Ð:MÐVyÐ&ÓzˆÙÜ�K‰KÐaÐcoÔpØˆ	øô ò 	Ü�L‰LÐGÈÔMÜûð	ús   “4C% Á#C% Ã%	DÃ.D	Ä	Dc                 óÞ  — | j                   dk7  s6t        | d«      r*| j                  dk7  st        t	        | dd«      xs dd«      ry	 dd	lm}  || j                  ¬
«      }t        |t        «      r|j                  «       nd}|r|| j                  k(  ryt        t        «      5  | j                   j#                  «        d d d «       	 t	        | dd «      }| j%                  ||«      | _        || j)                  |«      c| _        | _        y# t        $ r }t        j                  d|«       Y d }~yd }~ww xY w# 1 sw Y   ŒyxY w# t        $ r }t        j'                  d|«       Y d }~yd }~ww xY w)NrY   rs   ra   rt   r=   z	azure.comFr   )r_   rc   z'Anthropic credential refresh failed: %sz?Failed to rebuild Anthropic client after credential refresh: %sT)rR  Úhasattrrg   r
   rr   rq   r_   rb   rÐ   rÎ   rÑ   rM   rN   rO   rs   r   ru   rÍ   rF  rò   rH  rv   )r)   r_   rß  rÔ   r>   s        r   rS  z>ClientLifecycleMixin._try_refresh_anthropic_client_credentialsh  sL  € ð �M‰MÐ1Ò1¼ÀÐG[Ô9\Ø�}‰} Ò+Ü$¤W¨TÐ3HÈ"Ó%MÒ%SÐQSÐU`Ôaàð	ÝKÙ/°d·j±jÔAˆIô *4°I¼sÔ)C�I—O‘OÔ%Èˆ	Ù˜I¨×)@Ñ)@Ò@ØÜ”iÓ ñ 	+Ø×"Ñ"×(Ñ(Ô*÷	+ð	Ü˜tÐ%:¸DÓAˆHØ%)×%HÑ%HÈÐT\Ó%]ˆDÔ"ð =FÀt×GaÑGaÐbkÓGlÐ9ˆÔ Ô!9Øøô ò 	Ü�L‰LÐBÀCÔHÜûð	ú÷	+ð 	+ûô
 ò 	Ü�N‰NÐ\Ð^aÔbÜûð	ús<   ÁD Â$D7Ã$E Ä	D4ÄD/Ä/D4Ä7E Å	E,ÅE'Å'E,©Úapply_user_headersrë  c                óB  — t         D ])  \  }}t        ||«      sŒ || |«      | j                  d<    n� | j                  j                  dd «       t	        t
        «      5  ddlm}  || j                  «      }|r2|j                  r&t        |j                  «      x}r|| j                  d<   d d d «       |r| j                  «        | j                  dvr	 ddlm}  || j                  |«       y y # 1 sw Y   ŒExY w# t
        $ r t        j!                  dd¬«       Y y w xY w)	Nri   r   )Úget_provider_profilerX   )Ú4apply_custom_provider_extra_headers_to_client_kwargsz%custom-provider extra_headers skippedTrÚ   )Ú_ROUTE_DEFAULT_HEADERSr
   r?   r„  r   rÐ   Ú	providersrí  rg   ri   r0   Ú_apply_user_default_headersrR  Úhermes_cli.configrî  rÎ   rÑ   )	r)   r>   rë  ÚhostÚbuildrí  ÚprofileÚprofile_headersrî  s	            r   rÖ  z7ClientLifecycleMixin._apply_client_headers_for_base_url†  s  € Ü1ò 	M‰KˆD�%Ü$ X¨tÕ4Ù9>¸tÀXÓ9N�×#Ñ#Ð$5Ñ6Ùð	Mð ×Ñ×#Ñ#Ð$5°tÔ<Üœ)Ó$ñ MÝ:Ù.¨t¯}©}Ó=�Ù˜w×6Ò6ÌtÐT[×TkÑTkÓOlÐ<l¸OÐ<lØ=L�D×'Ñ'Ð(9Ñ:÷	Mñ Ø×,Ñ,Ô.à�=‰=Ð JÑJðUÝbÙDÀT×EXÑEXÐZbÕcð K÷Mð Mûô ò UÜ—‘ÐDÈt�ÖTðUús   ÁAC/ÃC; Ã/C8Ã; DÄDc                 ó”   — | j                   dv ryddlm}  || j                  j	                  d«      «      }|r|| j                  d<   yy)zÙMerge config ``model.default_headers`` onto the OpenAI client (user wins; WAFs rejecting SDK headers).
        Delegates to ``agent.auxiliary_client`` so main and aux clients cannot drift. No-op for Anthropic/Bedrock.rX   Nr   )rñ  ri   )rR  Úagent.auxiliary_clientrñ  r?   r@   )r)   Ú_merge_user_headersÚmergeds      r   rñ  z0ClientLifecycleMixin._apply_user_default_headersŸ  sL   € ð �=‰=ÐFÑFØÝ]Ù$ T×%8Ñ%8×%<Ñ%<Ð=NÓ%OÓPˆÙØ5;ˆD×ÑÐ 1Ò2ð r   c           	      ó¤  — t        |dd«      xs t        |dd«      }t        |dd«      xs t        |dd«      xs | j                  }ddlm}  |t        | d	d«      |«      }|rdd
lm}  ||«      }t        |t        «      r|j                  d«      n|}ddl	m
}  |t        | d	d«      |t        | dd«      «      s-t        j                  dt        |dd«      | j                  «       y|r-d| _        t        | d«      r| j                   j#                  «        t        |dd«      | _        ddlm}	  |	| j                  «       |	|«      k7  }
| j                  dk(  rˆt+        t,        «      5  | j.                  j1                  «        ddd«       ||c| _        | _        | j7                  || j4                  «      | _        | j9                  |«      | _        ||c| _        | _        y||c| _        | _        | j<                  | j>                  d<   | j                  | j>                  d<   | jA                  |
¬«       | jC                  d¬«       y# 1 sw Y   ŒÅxY w)zÿAdopt *entry* as the live credential. Returns False, changing nothing, when the entry's
        route cannot serve this conversation's model (a conversation's model is never rewritten by a
        rotation; the caller treats a refused swap as "no entry").Úruntime_api_keyNÚaccess_tokenr=   Úruntime_base_urlr>   r   )Úis_actual_routerg   r™  r]  )Úroute_can_serve_modelrb   z6Credential %s skipped: its route cannot serve model %sÚidú?Frw  Ú_transport_cacher¾  rY   Tr<   rÀ  Úcredential_rotationrk   )"rr   r>   Úhermes_cli.providersrÿ  r�  rš  rM   rN   r^  Úhermes_cli.anon_authr   rÎ   rÏ   rb   rR  ré  r  rÆ  r¶  rÄ  r¿  r   rÐ   ru   rÍ   rs   rt   rF  rH  rv   r<   r?   rÅ  rw   )r)   ÚentryÚruntime_keyÚruntime_baserÿ  Úactual_routerš  Ústripped_baser   r¿  rÁ  s              r   Ú_swap_credentialz%ClientLifecycleMixin._swap_credential©  s"  € ô ˜eÐ%6¸Ó=ÒcÄÈÐP^Ð`bÓAcˆÜ˜uÐ&8¸$Ó?ÒtÄ7È5ÐR\Ð^bÓCcÒtÐgk×gtÑgtˆÝ8Ù&¤w¨t°ZÀÓ'DÀlÓSˆÙÝAÙ4°\ÓBˆLÜ4>¸|ÌSÔ4Q˜×+Ñ+¨CÔ0ÐWcˆå>Ù$¤W¨T°:¸tÓ%DÀmÔU\Ð]aÐcjÐlpÓUqÔrÜ�K‰KÐPÔRYÐZ_ÐaeÐgjÓRkÐmq×mwÑmwÔxØÙØ.ˆDŒMÜ�tÐ/Ô0Ø×%Ñ%×+Ñ+Ô-Ü)0°¸¸dÓ)CˆÔ&ÝFÙ0°·±Ó?ÑC[Ð\hÓCiÑiˆØ�=‰=Ð0Ò0Üœ)Ó$ñ /Ø×&Ñ&×,Ñ,Ô.÷/à@KÈ]Ð=ˆDÔ# TÔ%=Ø%)×%HÑ%HÈÐVZ×VnÑVnÓ%oˆDÔ"Ø'+×'AÑ'AÀ+Ó'NˆDÔ$Ø*5°}Ð'ˆDŒL˜$œ-ØØ&1°=Ð#ˆŒ�d”mà)-¯©ˆ×Ñ˜IÑ&Ø*.¯-©-ˆ×Ñ˜JÑ'Ø×)Ñ)¸Ð)ÔFØ×+Ñ+Ð3HÐ+ÔIØ÷/ð /ús   Å'IÉIrÁ  c                ó~  — | j                   j                  dd«       | j                   j                  dd«       	 ddlm}m}m}  || j                   t        | j                  xs d«       | |«       «      «       | j                  | j                  | ¬
«       y# t        $ r t        j                  dd¬	«       Y ŒAw xY w)z×Recompute route-derived client kwargs (TLS material, default headers) for ``self.base_url``.

        Any rebuild that may have moved ``base_url`` must call this or the new endpoint inherits the old config.
        Ú
ssl_verifyNÚssl_ca_certr   )Ú*apply_custom_provider_tls_to_client_kwargsÚget_compatible_custom_providersÚload_config_readonlyr=   z=custom-provider TLS resolution skipped on credential rotationTrÚ   rê  )r?   r„  rò  r  r  r  rN   r>   rÐ   rÎ   rÑ   rÖ  )r)   rÁ  r  r  r  s        r   rÅ  z1ClientLifecycleMixin._reapply_route_client_configÑ  s±   € ð
 	×Ñ×Ñ ¨dÔ3Ø×Ñ×Ñ ¨tÔ4ð	i÷ñ ñ 7Ø×#Ñ#¤S¨¯©Ò)<¸"Ó%=Ñ?^Ñ_sÓ_uÓ?vôð
 	×/Ñ/°·±ÐVcÐRcÐ/Õdøô ò 	iÜ�L‰LÐXÐcgˆLÖhð	iús   ºA B Â B<Â;B<)rF   c                óÚ   — |€| j                   dk(  r| j                  «        ddlm}  ||xs | j                  |t        | dd«      t        t        | dd«      «       | j                  ¬«      S )	NrY   r   )Úcreate_anthropic_messageÚ
log_prefixr=   Ú_disable_streamingF)r  Úprefer_streamÚon_response)rR  rS  rp   r  ru   rr   rL   Ú#_capture_anthropic_response_headers)r)   rø   rF   r  s       r   Ú_anthropic_messages_createz/ClientLifecycleMixin._anthropic_messages_createã  sj   € àˆ>˜dŸm™mÐ/CÒCØ×:Ñ:Ô<åDá'ØÒ,�d×,Ñ,¨jÄWÈTÐS_ÐacÓEdÜ"¤7¨4Ð1EÀuÓ#MÓNÐNØ×@Ñ@ô
ð 	
r   c                 óL   — | j                  | j                  «       «      | _        y)zjRebuild the Anthropic client after an interrupt/stale call (Bedrock SDK for bedrock; honors 1M-beta flag).N)rP  rC  ru   r°   s    r   rƒ  z.ClientLifecycleMixin._rebuild_anthropic_clientð  s   € à!%×!EÑ!EÀd×FhÑFhÓFjÓ!kˆÕr   )r=   r¢   )HÚ__name__Ú
__module__Ú__qualname__rN   r¤   r®   r±   r©   r´   rµ   Ústaticmethodr   rL   r¾   rÄ   Ú_forwardrñ   Ú_forward_staticrÌ   Ú_cleanup_dead_connectionsÚ_run_codex_streamÚ_recover_with_credential_poolrÕ   rØ   rŠ  rê   rw   r÷   r0   r  Ú	frozensetr  r  Útupler  r  r  r  r&  r   r5  r8  r<  rá   rC  rF  rH  rP  rU  rT  rX  rã   r[  r_  rr  r†  r�  r�  r²  r»  rÌ  rÓ  r×  rã  rç  rS  rÖ  rñ  r  rÅ  r  rƒ  rI   r   r   r�   r�   g   s  „ ð¨Sð °Tó ð@
 Só 
ðb¨ó bð! Y§_¡_ó !ð
 ð¨ð °ò ó ðð: ðDÈ$ò D¨sð DÀCð DÐSVò Dó ðDñ
 %Ð%BÐDZÓ[ÐÙ.Ð/LÐNgÓhÐÙ (Ð)FÐHbÓ cÐÙ Ð!6Ð8JÓKÐÙ$,Ð-JÐLjÓ$kÐ!ð
m¨3ð 
m¸3ð 
mÈð 
mÐQUó 
mðy°3ð yÀ3ð yÈ4ó yð04¸Sð 4ÀSó 4ðl¸ð Àó ð2°sð ¸só ð& ð
°ð 
¸$ò 
ó ð
ñ0 %.Ð/AÐC\Ð.]Ó$^Ð!ð sð ¨tó ð °ð  ¸#ð  À%ó  ðR¨Sð R¸#ð RÀCð RÈDó Rð	¨sð 	¸Cð 	Èð 	ÐQUó 	ð¨Cð °Eó ð o°Cð  oÀð  oÐQTð  oÐY]ó  oðD Z^ò °sð ÈÐQUÉð Ðbeó ð2K°3ð KÀ3ð KÈ4ó Kð
K¸Sð 
KÀTó 
KðM°3ð MÀ3ð MÈ4ó Mð
¨uó 
ðx°Cð xÀ3ð xÈ3ó xð
s¨3ð s°4ó sð
c°5ð c¸Só cð¸#ð À#ó ð&°cð Àcð Èdó ð
Àð 
Èó 
ðP°cð PÀcð PÈdó Pó8ð
B°ð BÀð BÐPSð BÐX\ó Bð FJò #o¸dð #oÈdó #oðJ EIÐhlò (c¸Tð (cÐ[^ÐaeÑ[eð (cÐquó (cðX !Ððd¨tó dð:./¨(°5©/ó ./ð`i°Sð iÀCð iÐWZð iÐ_có ið"'°Tó 'ðR¸ó ð"B¨#ð BÀCð BÐTWð BÐ\`ó Bð¸ó ð< °tó  ðD¸4ó ð< _cò U¸3ð UÐW[ð UÐgkó Uó2<ð&¨ó &ðPe¸Tð eÀdó eð$ MQò 
°Tð 
Àcó 
ôlr   r�   )%Ú__doc__Úloggingr©   rŒ  Ú
contextlibr   Útypingr   r   Úagent.lazy_forwardr   r   r   r!  r   r'   Úhermes_cli.timeoutsr	   Úutilsr
   r   Ú	getLoggerrÎ   r   rà   râ   r#  r0   r   r"   rï  rL   rJ   rQ   rN   r   r�   rI   r   r   ú<module>r/     sE  ðñó
 Û Û Ý ß  ç nÑ nÝ <ß 2à	ˆ×	Ñ	˜;Ó	'€ØÐ à&€Ø3€ØlÐ ð<˜Tó <ð˜dó ð ÑbÐcØÑpÐqØÑ!xÐyØÑBÐCØÑhÐiØÑhÐiØÑ?Ð@Øñ >ð ?ð Ñ[Ð\ðÐ ð 05ò �tð ¨ð ¸ó ðq Cð q°3ð q¸4ó qð!N¸#ð !NÈð !NÐ[^ð !NÐmpð !NÐuyó !N÷HKlò Klr   