+
    lHàjîæ  ã                   óè  a € R¨ t†0 t R t^ RIt^ RIt^ RIt^ RIHt ^ RIHt ^ RI	t	^ RI
t
^ RIt^ RIHt ^ RIHtHtHtHtHtHt ^ RIHt ^ RIt^ RIHt Rs] ^ k Rs] ^k R R	 lt^ R
IHt ^ RIH t  ^ RI!H"t" ^ RI#H$t%H&t'H(t)H*t+H,t-H.t/ ^ RI0H1t1H2t2H3t3H4t4H5t5H6t6H7t7 ]	Pp                  ! ]94      t:] ! RRR7      t;RR/R R llt<R©R R llt=]=! RR]>4      t?]?f   Rt?Rªt@R R ltAR R ltB]B! 4       tC]! ]CRR7      tDR  tER! R" ltFR# R$ ltGR%tHR& R' ltIR( R) ltJR* R+ ltKR, tLR- R. ltMR«R/ R0 lltNR©R1 R2 lltOR¬tPR3tQR­tRR®tSR4 R5 ltTR6 R7 ltUR8 tVR]RRRR93R: R; lltW]X! 0 R¯m4      tY]X! 0 R°m4      tZR±R< R= llt[R> R? lt\R@ RA lt]RB RC lt^RD RE lt_R©RF RG llt`RH RI lta ! RJ RK]b4      tc ! RL RM]4      tdRN RO lteRP RQ ltfRR RS ltgR²RT RU llthRVR/RW RX lltiRY RZ ltjR³tk]kR[3R´Rµ3tl]k]l^ ,          ^,          3R¶]SR^33tmR_R`]l3RaRb]m3/tnRc Rd ltoR©Re Rf lltpRg Rh ltqR·Ri Rj lltrRk Rl ltsRm Rn ltt^ RoIuHvtvHwtw RpRqRrRsRtRuRvRwR\RuRxRrRy/RzRuRxRrR{/R|RuR}R~RuR/R€^R�^RrR‚//RƒR\Rz.//txR„ R… ltyR† R‡ ltz]vPö                  ! RqRˆ]x]z]tR‰RŠR‹7       RŒR�RŽR�R�R‘R’R�R“R�R”R•R–R•/t|Rªt}R¬t~R— R˜ ltR™ Rš lt€R©R› Rœ llt�R� Rž lt‚R²RŸ R  lltƒRpR¡RrR¢RtRuRvRwR]RuRxRrR£/RzRuRxRrR¤//RƒR]Rz.//t„R¥ R¦ lt…]vPö                  ! R¡Ra]„]…]sR‰R§R‹7       R# )¸a[  Vision tools: ``vision_analyze`` (image) and ``video_analyze``.

Images resolve through :mod:`tools.image_source`, are normalized to a provider-supported format
(:mod:`tools.vision_tools_image_prep`), then either attach natively to a vision-capable main
model (multimodal tool-result envelope) or are described by the auxiliary vision LLM router.
N)ÚThreadPoolExecutor)ÚBytesIO)ÚPath)ÚAnyÚ	AwaitableÚCallableÚDictÚ
NamedTupleÚOptional)Úurlparse)Úmake_user_dirc                ó   € V ^8„  d   QhRR/# )é   ÚreturnN© )Úformats   "Ú7/home/ubuntu/.hermes/hermes-agent/tools/vision_tools.pyÚ__annotate__r      s   € ÷ iñ i ñ ió    c                  óž   € \         e	   \        f=   ^ RIHp  \         ;'       g    V P                   s \        ;'       g    V P                  sR # R # )N)Úauxiliary_client)Úasync_call_llmÚextract_content_or_reasoningÚagentr   )Ú_auxs    r   Ú_load_auxiliary_clientr      s>   € äÒÔ!=Ò!EÝ2Ü'×>Ð>¨4×+>Ñ+>ˆÜ'C×'hÐ'hÀt×GhÑGhÒ$ñ "Fr   )Úget_hermes_dir)ÚDebugSession)Úcheck_website_access)Únative_turn_duplicateÚrecord_embedÚrelease_embedÚrepeat_refusalÚresolve_repeat_capÚresolve_embed_target_bytes)Ú&_VISION_MAX_VALIDATED_AGGREGATE_PIXELSÚ!_VISION_MAX_VALIDATED_FRAME_COUNTÚ_crop_image_regionÚ_determine_mime_typeÚ_image_exceeds_dimensionÚ_normalize_to_supported_imageÚ _validate_raster_image_decodableÚvision_toolsÚVISION_TOOLS_DEBUG)Úenv_varÚdefaultc                ó$   € V ^8„  d   QhR\         /# )r   Úkeys©Ústr)r   s   "r   r   r   >   s   € ÷ ñ œ#ñ r   c                ó^   €  ^ RI HpHp V! V! 4       R.VO5RV / #   \         d    T u # i ; i)zQ``auxiliary.<keys...>`` from config.yaml; ``default`` when config is unavailable.)Úcfg_getÚload_configÚ	auxiliaryr/   )Úhermes_cli.configr5   r6   Ú	Exception)r/   r1   r5   r6   s   $*  r   Ú_cfg_auxiliaryr:   >   s7   € ðß:Ù‘{“} kÐJ°DÒJÀ'ÑJÐJøÜô ØŠðús   ‚ œ,«,c                ó0   € V ^8„  d   QhR\         R\         /# )r   r.   Úkeyr2   )r   s   "r   r   r   G   s   € ÷ 
Nñ 
N¤#ð 
N¬Cñ 
Nr   c                ó®   aa€ VV3R lpT! \         P                  ! V R4      P                  4       ;'       g    R4      pVe   V# V! \        RV4      4      # )uº   Env var â†’ ``auxiliary.vision.<key>`` â†’ None. Values that fail ``cast`` or fall below
``minimum`` are skipped in favor of the next source (a cap can never be disabled by a bad value).c                 ód   <€  S! V 4      pSe   TS8¼  d   T# R #   \         \        3 d     R # i ; i©N)Ú	TypeErrorÚ
ValueError)ÚrawÚvalÚcastÚminimums   & €€r   Ú_acceptÚ%_read_vision_setting.<locals>._acceptJ   sA   ø€ ð	Ù�s“)ˆCð ’o¨°¬ˆsÐA¸TÐAøô œ:Ð&ô 	Úð	ús   ƒ š/®/Ú NÚvision)ÚosÚgetenvÚstripr:   )r.   r<   rD   rE   rF   rC   s   &&ff  r   Ú_read_vision_settingrM   G   sL   ù€ öBñ ”"—)’)˜G RÓ(×.Ñ.Ó0×8Ð8°DÓ
9€CØ’/ˆ3ÐM¡w¬~¸hÈÓ/LÓ'MÐMr   ÚHERMES_VISION_DOWNLOAD_TIMEOUTÚdownload_timeoutg      >@c                ó$   € V ^8„  d   QhR\         /# ©r   r   ©Úint)r   s   "r   r   r   c   s   € ÷ +ñ +œ3ñ +r   c                 óÖ   €  \        ^\        \        P                  ! ^ 4      4      4      #   \        \
        3 d-    \        ^\        P                  ! 4       ;'       g    ^4      u # i ; i)zKUsable CPU count (``sched_getaffinity`` honors cpuset pinning), at least 1.)ÚmaxÚlenrJ   Úsched_getaffinityÚAttributeErrorÚOSErrorÚ	cpu_countr   r   r   Ú_detect_host_cpusr[   c   sS   € ð+Ü�1”cœ"×.Ò.¨qÓ1Ó2Ó3Ð3øÜœGÐ$ô +Ü�1”b—l’l“n×)Ð)¨Ó*Ò*ð+ús   ‚(+ «2A(ÁA(Á'A(c                ó$   € V ^8„  d   QhR\         /# rQ   rR   )r   s   "r   r   r   k   s   € ÷ &ñ &¤Sñ &r   c                 óP   € \        RR\        ^R7      p T ;'       g    \        4       # )ud   HERMES_VISION_MAX_CONCURRENCY â†’ ``auxiliary.vision.max_concurrency`` â†’ host cores (< 1 ignored).ÚHERMES_VISION_MAX_CONCURRENCYÚmax_concurrency)rE   )rM   rS   r[   )rC   s    r   Ú_resolve_vision_cpu_workersr`   k   s(   € ä
Ð>Ð@QÔSVÐ`aÔ
b€CØ×%Ð%Ô#Ó%Ð%r   zvision-encode)Úmax_workersÚthread_name_prefixc              �  ó¤   "  € ^ RI p\        P                  ! 4       pVP                  \        VP
                  ! V .VO5/ VB 4      G Rj  x€L
 #  L5i)zZRun a sync encode/resize callable on the bounded vision CPU executor (never the LLM call).N)Ú	functoolsÚasyncioÚget_running_loopÚrun_in_executorÚ_vision_cpu_executorÚpartial)ÚfnÚargsÚkwargsrd   Úloops   &*,  r   Ú_run_encode_on_cpu_executorrn   x   sG   é € ãÜ×#Ò#Ó%€DØ×%Ñ%Ô&:¸I×<MÒ<MÈbÐ<bÐSWÒ<bÐ[aÑ<bÓc×cÐcÑcùs   ‚AAÁ	AÁ
Ac                ó0   € V ^8„  d   QhR\         R\        /# )r   Úurlr   ©r3   Úbool)r   s   "r   r   r      s   € ÷ (ñ (¬ð (´ñ (r   c              ƒ  óÎ   "  € \        V \        4      '       d3   V P                  R4      '       d   \        V 4      P                  '       g   R# ^ RIHp V! V 4      G Rj  x€L
 #  L5i)zlHTTP(S) shape check (scheme, netloc; extension-less CDN URLs pass) + SSRF guard with DNS
off the event loop.F)Úasync_is_safe_urlN)úhttp://úhttps://)Ú
isinstancer3   Ú
startswithr   ÚnetlocÚtools.url_safetyrt   )rp   rt   s   & r   Ú_validate_image_url_asyncr{      sL   é € ô �sœC× Ò  S§^¡^Ð4K×%LÒ%LÔQYÐZ]ÓQ^×Qe×QeÐQeÙÝ2Ù" 3Ó'×'Ð'Ñ'ùs   ‚AA%ÁA#ÁA%c                ó0   € V ^8„  d   QhR\         R\        /# ©r   Úerrorr   ©r9   rr   )r   s   "r   r   r   ˆ   s   € ÷ ñ ¬	ð ´dñ r   c                óþ   € \        V \        \        34      '       d   R# \        V \        P                  4      '       d?   V P
                  P                  pVR8H  ;'       g    RTu;8*  ;'       d    R8  Mu '       * # R# )z¹Transient failures only: 429, 5xx, transport errors and anything unclassified. Fail-fast on
other 4xx, PermissionError (policy/SSRF block) and ValueError (too large / blocked redirect).Fi­  i�  iô  T)rw   ÚPermissionErrorrA   ÚhttpxÚHTTPStatusErrorÚresponseÚstatus_code)r~   Ústatuss   & r   Ú_is_retryable_download_errorr‡   ˆ   s`   € ô �%œ/¬:Ð6×7Ò7ÙÜ�%œ×.Ñ.×/Ò/Ø—‘×+Ñ+ˆØ˜‰}×7Ð7 C¨6×$7Ô$7°CÔ$7Ô 7Ð7Ùr   zoMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36c                ó$   € V ^8„  d   QhR\         /# rQ   ©rr   )r   s   "r   r   r   ™   s   € ÷ ñ œ$ñ r   c                 óT   €  ^ RI Hp  \        V ! 4       4      #   \         d     R# i ; i)ac  True when a package manager (NixOS) owns this install's modes.

Mirrors the check ``hermes_cli.config._secure_dir`` makes internally, read
here so the *creation* mode honours the same carve-out as reconciliation.
Import is local and failure means "not managed": an unimportable config
module is the single-user source-install case, where 0700 is correct.
©Ú
is_managedF)r8   rŒ   rr   r9   r‹   s    r   Ú_managed_installr�   ™   s)   € ðÝ0ä‘J“LÓ!Ð!øÜô Úðús   ‚ ˜'¦'c                ó<   € V ^8„  d   QhR\         R\         R\        /# )r   Únew_subpathÚold_namer   )r3   r   )r   s   "r   r   r   ©   s!   € ÷ 9ñ 9¤3ð 9´#ð 9¼$ñ 9r   c                ó   € \        W4      p\        4       '       d   VP                  RRR7       V# \        VRRRR7        ^ RIHp V! V4       V#   \         d"   p\        P                  RT4        Rp?T# Rp?ii ; i)uy	  Resolve a Hermes media-cache dir, creating it owner-only (0700).

A downloaded image or video is as sensitive as whatever the user pointed
the agent at â€” a private attachment, an internal screenshot, a document
scan. Created with a bare ``mkdir(parents=True, exist_ok=True)`` these
inherited the umask and landed 0755, readable by every other local
account. ``HERMES_HOME`` is 0700 by default so default-config exposure is
narrow; the concrete scenario is the documented ``HERMES_HOME_MODE=0701``
hatch (letting nginx/caddy traverse to a served subdirectory), where a
0755 child really is world-readable.

The mode is passed to ``mkdir`` so it is set *at creation*, leaving no
window where the directory sits world-readable before a follow-up chmod.
Policy is then reconciled through ``hermes_cli.config._secure_dir`` â€” the
house helper â€” rather than a hand-rolled chmod, which is what keeps this
correct off a single-user desktop: managed/NixOS installs are skipped,
``HERMES_HOME_MODE`` stays honoured, and ``HERMES_UID``/``HERMES_GID``
ownership is applied so a root-created dir does not lock out uid-mapped
Docker workers (#34107).

The managed/NixOS carve-out applies to **creation as well as
reconciliation**. ``cache/vision`` and ``cache/video`` are not among the
directories the NixOS module's ``systemd.tmpfiles`` rules pre-create, so
they are made lazily at runtime; a hardcoded 0700 here would be the only
thing setting their mode and would silently override a design that pins
``stateDir/.hermes`` to ``2770`` and runs the gateway with ``UMask =
"0007"`` so "interactive users in the hermes group can read/write"
gateway-created state. On such a host the gateway and a hostUsers CLI
share one ``$HERMES_HOME``, so a 0700 cache created by whichever ran
first makes vision fail with EACCES for the other. Skipping the explicit
mode there lets the inherited setgid + umask land 2770, matching
``ensure_hermes_home``'s managed branch and its ``logs/curator``
lazy-mkdir precedent.

Running it unconditionally also heals a directory an older Hermes left at
0755. That retroactive tighten is safe *here* because this is
Hermes-private scratch that the same user re-reads in the same call â€”
there is no user-shared content to strand. Note ``parents=True`` applies
the mode to the leaf only, so an intermediate ``cache/`` keeps its default
mode; it is shared with other subsystems and holds only directory names.
T©ÚparentsÚexist_okiÀ  )r“   r”   Úmode)Ú_secure_dirz#vision: cache dir chmod skipped: %sN)	r   r�   Úmkdirr   r8   r–   r9   ÚloggerÚdebug)r�   r�   Ú	cache_dirr–   Úexcs   &&   r   Ú_secure_cache_dirrœ   ©   s…   € ôT ˜{Ó5€IÜ×Òð 	�‰ ¨tˆÔ4ØÐô �) T°D¸uÕEðAÝ1á�IÔð Ðøô ô AÜ�‰Ð:¸C×@Ð@ØÐûðAús   ÁA ÁA=ÁA8Á8A=c                ó4   € V ^8„  d   QhR\         R\        RR/# )r   ÚpathÚdatar   N)r   Úbytes)r   s   "r   r   r   å   s!   € ÷ ñ œtð ¬5ð °Tñ r   c                óž  € \         P                  \         P                  ,          \         P                  ,          p \         P                  ! \        V 4      VR4      p\         P                  ! TR4      ;_uu_ 4       pTP                  T4       RRR4       R#   \         d    T P                  T4        R# i ; i  + '       g   i     R# ; i)u@  Write ``data`` to ``path`` with owner-only (0600) permissions.

``Path.write_bytes`` lands 0644 under a default umask. The enclosing cache
dir is 0700, so this matters only under ``HERMES_HOME_MODE=0701`` â€” but
``tools.computer_use.tool`` already writes private captures into this
very directory, and one directory with two file-mode conventions is the
kind of inconsistency that rots. POSIX mode bits are advisory on Windows
(``os.chmod`` there only toggles the read-only flag), so on an ``os.open``
failure this degrades to a plain write rather than failing the download.
i€  NÚwb)
rJ   ÚO_WRONLYÚO_CREATÚO_TRUNCÚopenr3   rY   Úwrite_bytesÚfdopenÚwrite)rž   rŸ   ÚflagsÚfdÚhandles   &&   r   Ú_write_private_bytesr­   å   s‘   € ô �K‰Kœ"Ÿ*™*Õ$¤r§z¡zÕ1€EðÜ�WŠW”S˜“Y  uÓ-ˆô 
�Š�2�t×	Ô	 Ø�‰�TÔ÷ 
Ñ	øô ô Ø×Ñ˜ÔÚðú÷ 
×	Ð	ús   ¼!B Á<B;ÂB8Â7B8Â;C	c              ƒ  óŽ   "  € ^ RI HpHp V! V 4      pV'       d'   V! V4      G Rj  x€L
 '       g   \        RV 24      hR# R#  L5i)z¤Re-validate each redirect target (a public URL 302ing to 169.254.169.254 would otherwise
bypass the pre-flight check). Async because httpx.AsyncClient awaits hooks.)rt   Úredirect_target_from_responseNz.Blocked redirect to private/internal address: )rz   rt   r¯   rA   )r„   rt   r¯   Úredirect_urls   &   r   Ú_ssrf_redirect_guardr±   ú   sD   é € ÷ RÙ0°Ó:€LßÑ"3°LÓ"A×AÖAÜÐIÈ,ÈÐXÓYÐYñ B�|ÑAùs   ‚$A¦A§	A±Ac                ó„   € V ^8„  d   QhR\         R\        R\        R\         R\         R\        R\        R\        R	\        /	# )
r   rp   ÚdestinationÚmax_retriesÚmedia_labelÚacceptÚ	max_bytesÚtimeoutÚ	retry_allr   )r3   r   rS   Úfloatrr   )r   s   "r   r   r     sj   € ÷ Mmñ MmÜ	ðMmÜðMmÜ.1ðMmäðMmä!ðMmä.1ðMmä<AðMmäNRðMmäW[ñMmr   c             ƒ  óF  "  € ^ RI Hp ^ RIHp	 VP                  P                  RRR7       Rp
\        V4       EFÎ  p \        V 4      pV'       d   \        VR,          4      hV	! VRR\        ./R7      ;_uu_4       GRj  x€L
 qÝP                  R	V R
\        RV/R7      ;_uu_4       GRj  x€L
 pVP                  4        VP                  P                  R4      p V'       d   \        V4      MRpVe   VV8”  d   \!        V RV RV R24      h\        \#        VP$                  4      4      pV'       d   \        VR,          4      hVP'                  RVP(                   R\*        P,                  ! 4       P.                   R24      p^ p VP1                  R4      ;_uu_ 4       pVP3                  4         Rj  x€L
  pV'       g   K  V\5        V4      ,          pVV8”  d   \!        V RV RV R24      hVP7                  V4       KT  	  V
e   V
h\M        RVPO                  4        RV R24      h EL± ELˆ  \          d    Rp ELUi ; i L‘D’ RRR4       M  + '       g   i     M; iT! TT4       ML  \8         d?     TP;                  RR7       h   \<         d    \>        PA                  RTRR7        h i ; ii ; iRRR4      GRj  x€L 
  M  + GRj  x€L 
 '       g   i     M; iRRR4      GRj  x€L 
  M  + GRj  x€L 
 '       g   i     M; iTu #   \8         dò   pTp
Y²^,
          8¼  g   T'       gS   \C        T4      '       gB   \>        PE                  RY;^,           \#        T4      R,          RR7       T'       g   h  Rp? EKŠ  ^T^,           ,          p\>        PG                  RY;^,           T\#        T4      R,          4       T'       g   \>        PG                  RT4       \H        PJ                  ! T4      G Rj  x€L 
   Rp?EKà  Rp?ii ; i5i)u¾   SSRF-safe streaming download with exponential backoff (2s/4s/8s). ``retry_all=False`` (images)
retries only :func:`_is_retryable_download_error` errors â€” a 404/403 never succeeds on retry.)Úatomic_replace)Úcreate_ssrf_safe_async_clientTr’   NÚmessager„   )r¸   Úfollow_redirectsÚevent_hooksÚGETz
User-AgentÚAccept)Úheaderszcontent-lengthz too large (z bytes, max Ú)Ú.z.tmpr¢   ©Ú
missing_okz%Could not delete partial download: %s©Úexc_infoz*%s download failed after %s attempt(s): %sºNéd   Nz&%s download failed (attempt %s/%s): %s:Né2   NzRetrying in %ss...Ú
_download_z3 exited retry loop without attempting (max_retries=)(Úutilsr¼   rz   r½   Úparentr—   Úranger   r�   r±   ÚstreamÚ_DOWNLOAD_USER_AGENTÚraise_for_statusrÃ   ÚgetrS   rA   r3   rp   Ú	with_nameÚnameÚuuidÚuuid4Úhexr¦   Úaiter_bytesrV   r©   r9   ÚunlinkrY   r˜   r™   r‡   r~   Úwarningre   ÚsleepÚRuntimeErrorÚlower)rp   r³   r´   rµ   r¶   r·   r¸   r¹   r¼   r½   Ú
last_errorÚattemptÚblockedÚclientr„   ÚclÚdeclared_sizeÚtmp_destinationÚbytes_writtenÚfÚchunkÚeÚ	wait_times   &&&$$$$$               r   Ú_download_mediarì     sÌ  é € õ
 %Ý>Ø×Ñ×Ñ T°DÐÔ9Ø€JÜ˜×%ˆð>	+Ü*¨3Ó/ˆGßÜ% g¨iÕ&8Ó9Ð9ñ 5Ø°$ÀZÔRfÐQgÐDh÷÷ õ àŸ™Ø�s \Ô3GÈÐSYÐ$Zð '÷ ÷ ô àØ×)Ñ)Ô+ð ×%Ñ%×)Ñ)Ð*:Ó;�ð)ß/1¤C¨¤G°t�Mð !Ò,°ÀÔ1JÜ$¨ }°LÀÀÈ|Ð\eÐ[fÐfgÐ%hÓiÐiÜ.¬s°8·<±<Ó/@ÓA�ßÜ)¨'°)Õ*<Ó=Ð=ð #.×"7Ñ"7¸!¸K×<LÑ<LÐ;MÈQÌtÏzÊzË|×O_ÑO_ÐN`Ð`dÐ8eÓ"f�Ø !�ðØ(×-Ñ-¨d×3Ô3°qØ+3×+?Ñ+?Ô+A÷ +ð + %ß#(Ù (Ø)¬S°«ZÕ7˜MØ,¨yÔ8Ü&0Ø'2 m°<À¸ÈlÐ[dÐZeÐefÐ$gó'"ð !"ð ŸG™G EžNñS &ðB ÒØÐÜ
Ø
�[×&Ñ&Ó(Ð)Ð)\Ð]hÐ\iÐijÐkómð mòwòøô "ô )Ø$(“Mð)úñ+Ñ+A÷ 4×3×3Ð3úñ # ?°KÕ@øÜ ô ðnØ'×.Ñ.¸$Ð.Ô?ð øô #ô nÜŸ™Ð%LÈoÐhl˜ÕmØðnúðú÷C÷ ÷ ÷ ÷ ò ú÷÷ ÷ ÷ ÷ ò úðR ÒøÜô 	+ØˆJØ¨�/Ô)·)ÔD`Ðab×DcÒDcÜ—‘ÐIØ(°A­+´s¸1³v¸dµ|Èdð ô Tç ØßØ˜g¨�kÕ*ˆIÜ�N‰NÐCØ&°!­°[Ä#ÀaÃ&ÈÅ+ôOçÜ—‘Ð3°YÔ?Ü—-’- 	Ó*×*×*Ð*ûð	+üsƒ  ‚;P!¾AL"ÂH2
ÂL"Â(LÂ-H5Â.LÂ1,KÃH8
Ã3BKÆI6
Æ%IÆ6IÆ:IÆ;IÆ>AIÈ
(P!È2L"È5LÈ8I	ÉKÉI	É	KÉIÉIÉ	I6
ÉI)É$I6
É5KÉ6J?ÊJÊJ?Ê#J;Ê8J?Ê:J;Ê;J?Ê?KËLËK
ËLËK-ËKË
K-Ë&K-Ë(LË0L"Ë;K>Ë<L"ÌLÌLÌ	
LÌLÌ	L"ÌP!Ì"PÌ-PÍA
PÎP!ÎA6PÐPÐPÐP!ÐPÐP!c                óH   € V ^8„  d   QhR\         R\        R\        R\        /# )r   Ú	image_urlr³   r´   r   )r3   r   rS   )r   s   "r   r   r   S  s/   € ÷ añ a¤Sð a´tð aÌ#ð aÔVZñ ar   c              ƒ  óR   "  € \        WVRR\        \        RR7      G Rj  x€L
 #  L5i)zCDownload an image with SSRF protection and error-class-aware retry.ÚImagezimage/*,*/*;q=0.8F©rµ   r¶   r·   r¸   r¹   N)rì   Ú_VISION_MAX_DOWNLOAD_BYTESÚ_VISION_DOWNLOAD_TIMEOUT)rî   r³   r´   s   &&&r   Ú_download_imagerô   S  s4   é € ä Ø ØÐ$7Ü,Ô6NÐZ_ôa÷ að añ aùs   ‚' %¡'c                óR   € V ^8„  d   QhR\         R\        \        ,          R\        /# )r   Ú
image_pathÚ	mime_typer   ©r   r
   r3   )r   s   "r   r   r   [  s+   € ÷ ]ñ ]¬$ð ]¼8ÄC½=ð ]ÔTWñ ]r   c                óž   € T;'       g    \        V 4      pRV R\        P                  ! V P                  4       4      P	                  R4       2# )zK``data:<mime>;base64,...`` for a file (MIME from extension when not given).údata:ú;base64,Úascii)r(   Úbase64Ú	b64encodeÚ
read_bytesÚdecode)rö   r÷   Úmimes   && r   Ú_image_to_base64_data_urlr  [  sI   € à×8Ð8Ô,¨ZÓ8€DØ�4�&˜¤×!1Ò!1°*×2GÑ2GÓ2IÓ!J×!QÑ!QÐRYÓ!ZÐ [Ð\Ð\r   i   c                ó0   € V ^8„  d   QhR\         R\        /# r}   r   )r   s   "r   r   r   x  s   € ÷ añ a¤	ð a¬dñ ar   c                óÖ   a€ \        V 4      P                  4       o\        ;QJ d*    V3R l\        R,            4       F  '       g   K   R# 	  R# ! V3R l\        R,            4       4      # )z;Detect if an API error is related to image or payload size.c              3   ó,   <"  € T F	  qS9   x € K  	  R # 5ir?   r   ©Ú.0ÚhintÚerr_strs   & €r   Ú	<genexpr>Ú'_is_image_size_error.<locals>.<genexpr>{  s   øé € Ð`Ñ+_ 4�wŽÓ+_ùó   ƒTF)rî   Úinvalid_request)r3   rß   ÚanyÚ_SIZE_ERROR_HINTS)r~   r	  s   &@r   Ú_is_image_size_errorr  x  sL   ø€ ä�%‹j×ÑÓ €Gß‹3Ô`Ô+<Ð?_Ö+_Ó`�3Œ3Ð`Š3Ð`ˆ3Ô`Ô+<Ð?_Ö+_Ó`Ó`Ð`r   c                ó~   € V ^8„  d   QhR\         \        ,          R\         \        ,          R\         \        ,          /# )r   Ú
scale_infoÚcrop_offsetr   )r
   Údictr3   )r   s   "r   r   r   ~  s0   € ÷ .ñ .¤(¬4¥.ð .¼xÌ½~ð .ÔRZÔ[^ÕR_ñ .r   c                óª  € . pV '       d‚   V R,          V R,          rCV R,          V R,          reV'       d	   W5,          MRV'       d	   WF,          MRr‡VR VR 8X  d   RVR 2M	RVR R	VR 2p	VP                  R
V RV RV RV RV	 R24       V'       d'   VP                  RVR,           RVR,           R24       V'       d   RP                  V4      # R# )z^Coordinate-mapping disclosure for downscale and/or region crop; ``None`` when neither applied.Ú
orig_widthÚorig_heightÚ	new_widthÚ
new_heightg      ð?z.2fzany coordinates you report by z any x coordinates you report by z and any y coordinates by zImage downscaled from Úxz to z for vision; multiply z# to map back to the original image.zUAnalysis was performed on a cropped region of the original image starting at offset (ú, Úyua   ); coordinates are relative to that crop origin â€” add the offset to map back to the full image.Ú N)ÚappendÚjoin)
r  r  ÚpartsÚowÚohÚnwÚnhÚfxÚfyÚaxess
   &&        r   Ú_build_scale_noter(  ~  s  € à€EßØ˜LÕ)¨:°mÕ+DˆBØ˜KÕ(¨*°\Õ*BˆBß�"–' S·r¨B®G¸sˆBØ@BÀ3¸xÈrÐRUÈhÔ=WÐ0°°C°Ñ9Ø7¸¸3°xÐ?YÐZ\Ð]`ÐYaÐbð 	à�‰Ð-¨b¨T°°2°$°d¸2¸$¸aÀ¸tð D!Ø!% Ð&IðKô 	LçØ�‰ð)Ø)4°SÕ)9Ð(:¸"Ø˜3ÕÐ ð !GðHô	I÷
 $ˆ3�8‰8�E‹?Ð-¨Ð-r   c                 óˆ   €  ^ RI Hp  V #   \         d-     ^ RIHp T! R4       ^ RI Hp   T #   \
         d      R# i ; ii ; i)zâReturn ``PIL.Image`` or None (Pillow is a lazy-installable soft dependency). ``prompt=False``:
a blocking input() deadlocks the CLI where prompt_toolkit owns stdin; the install is already
gated by security.allow_lazy_installs.)rð   )Úensure_importrI   N)ÚPILrð   ÚImportErrorÚpmr*  r9   )rð   r*  s     r   Ú_import_pillow_for_resizer.  ’  sR   € ðÝð €Løô ô ð
	õ
 )á˜(Ô#Þ!ð €Løô ô 	Ûð	úðús   ‚
 ŠA–-­=¸A¼=½AFc                ó®   € V ^8„  d   QhR\         R\        \        ,          R\        R\        \        ,          R\        \        ,          R\
        R\        /# )r   rö   r÷   Úmax_base64_bytesÚmax_dimensionÚ	scale_outÚ
force_jpegr   )r   r
   r3   rS   r  rr   )r   s   "r   r   r   §  s]   € ÷ Vñ V¬ð V¼(Ä3½-ð VÜ03ðVä-5´c­]ðVô *2´$­ðVô +/ð	Vô <?ñ	Vr   c           	     óÌ  a aaaa€ S P                  4       P                  pV^,          ^,          ^d,           pRoWr8:  d6   Ve   \        S V4      '       g    \        S SR7      o\	        S4      V8:  d   S# R VV V3R llp\        4       p	V	f   \        P                  R4       V! 4       # \        P                  RVR,          VR,          VR,          V4       S;'       g    \        S 4      R8H  ;'       d    V'       * p
V
'       d   RMRw  r¼ V	P                  S 4      pT
'       g#   TP                  R9  d   TP                  R	4      pT
'       d   RMRpTP                  TP                  3;opRpR
 TT3R llp\        ^4       EFO  pT^ 8”  Ed2   \!        \#        TP                  R,          4      ^@4      \!        \#        TP                  R,          4      ^@4      ppT^@8X  dJ   TP                  ^ 8”  d9   \!        \#        TP                  ^@TP                  ,          ,          4      ^@4      pMOT^@8X  dI   TP                  ^ 8”  d8   \!        \#        TP                  ^@TP                  ,          ,          4      ^@4      pTT3T8X  d    EMQTP%                  TT3T	P&                  4      pTT3p\        P                  RTTT4       TRJ ;'       g$    \!        TP                  TP                  4      T8*  pT FÝ  p\)        4       pTP*                  ! T3RT/Tf   / MRT/B  RT R\,        P.                  ! TP1                  4       4      P3                  R4       2p\	        T4      T8:  g   Ku  T'       g   K  \        P                  R\	        T4      R,          TTP                  TP                  4       T! TP                  TP                  4       Tu u # 	  EKR  	  Tf   T! 4       # \        P5                  RTR,          \	        T4      R,          4       T! TP                  TP                  4       T#   \         d(   p\        P                  RT4       T! 4       u Rp?# Rp?ii ; i)u-  Base64 data URL, progressively downscaled with Pillow while over budget.

Halves dimensions (aspect-preserving, 64px floor) up to 4 times; JPEG also walks a
quality ladder (85/70/50) per step. Without Pillow, or if it still doesn't fit, returns
the best attempt (or raw bytes) and lets the caller apply the size check.
``max_dimension``: force a downscale above this long edge even when bytes fit
(Anthropic's 8000px cap is independent of bytes). ``force_jpeg``: re-encode PNG as JPEG
when resizing â€” halving PNG dimensions destroys text legibility on dense screenshots.

Args: max_dimension: If set, images whose longest side exceeds this pixel count are forcibly downscaled
even if they're under the byte budget. Anthropic enforces an 8000 px per-side cap independently of the 5
MB byte cap. force_jpeg: Re-encode as JPEG even for PNG input when a resize is needed. History-reuse
embeds (#92699) opt in so a text-heavy screenshot keeps its readable resolution and shrinks via JPEG
quality instead. Images already under both caps are returned unchanged (still PNG).
N©r÷   c                ó$   € V ^8„  d   QhR\         /# rQ   r2   )r   s   "r   r   Ú._resize_image_for_vision.<locals>.__annotate__Å  s   € ÷ Vñ V”#ñ Vr   c                  ó2   <€ S ;'       g    \        SSR 7      # )r5  )r  )Údata_urlrö   r÷   s   €€€r   Ú_rawÚ&_resize_image_for_vision.<locals>._rawÅ  s   ø€ Ø×UÐUÔ4°ZÈ9ÔUÐUr   u;   Pillow not installed â€” cannot auto-resize oversized imagezcImage file is %.1f MB (estimated base64 %.1f MB, limit %.1f MB, max_dimension=%s), auto-resizing...ú	image/pngz)Pillow cannot open image for resizing: %sÚRGBc                ó4   € V ^8„  d   QhR\         R\         RR/# )r   ÚwÚhr   NrR   )r   s   "r   r   r7  Þ  s&   € ÷ kñ kœð k¤ð k¨ñ kr   c                 ól   <€ Se/   W3S8w  d%   SP                  S^ ,          S^,          WR7       R # R # R # )N)r  r  r  r  )Úupdate)r?  r@  Ú	orig_dimsr2  s   &&€€r   Ú_record_scaleÚ/_resize_image_for_vision.<locals>._record_scaleÞ  s8   ø€ ØÒ  a V¨yÔ%8Ø×Ñ¨	°!­À)ÈAÅ,ÐZ[ÐÖjñ &9Ñ r   g      à?zResized to %dx%d (attempt %d)r   Úqualityrú   rû   rü   z4Auto-resized image fits: %.1f MB (quality=%s, %dx%d)z=Auto-resize could not fit image under %.1f MB (best: %.1f MB)é   )ÚPNGr<  )ÚJPEGz
image/jpeg>   ÚLr=  r?   )éU   éF   rÌ   )ÚstatÚst_sizer)   r  rV   r.  r˜   Úinfor(   r¦   r9   r•   ÚconvertÚwidthÚheightrÐ   rU   rS   ÚresizeÚLANCZOSr   Úsaverý   rþ   Úgetvaluer   rÜ   )rö   r÷   r0  r1  r2  r3  Ú	file_sizeÚestimated_b64r:  rð   Úis_pngÚ
pil_formatÚout_mimeÚimgr›   Úquality_stepsÚ	prev_dimsÚ	candidaterD  rá   Únew_wÚnew_hÚdims_okÚqÚbufr9  rC  s   ff&&f&                   @@r   Ú_resize_image_for_visionre  §  s“  ü€ ð( —‘Ó!×)Ñ)€IØ •] qÕ(¨3Õ.€MØ€HØÔ(ØÒ!Ô&>¸zÈ=×&YÒ&Yä,¨ZÀ9ÔMˆÜˆx‹=Ð,Ô,ØˆO÷Vò Vä%Ó'€EØ‚}Ü�‰ÐQÔRÙ‹vˆÜ
‡K�KÐuØ˜[Õ)¨=¸KÕ+HØ  KÕ0°-ôAð ×;Ð;Ô/°
Ó;ÀÑK×^Ð^ÐT^ÔP^€Fß39Ñ/Ð?UÑ€JðØ�j‰j˜Ó$ˆ÷ �c—h‘h lÔ2Ø�k‰k˜%Ó ˆß%‘G¨<€MØ ŸY™Y¨¯
©
Ð3Ð3€I�	Ø€I÷kñ kô ˜—8ˆØ�Q�;äœs 3§9¡9¨s¥?Ó3°RÓ8¼#¼cÀ#Ç*Á*ÈsÕBRÓ>SÐUWÓ:X�5ˆEØ˜Œ{˜sŸy™y¨1œ}ÜœC §
¡
¨b°3·9±9­nÕ =Ó>ÀÓC‘Ø˜"” §¡¨a¤ÜœC §	¡	¨R°#·*±*­_Õ =Ó>ÀÓC�Ø�uˆ~ Ô*ÚØ—*‘*˜e U˜^¨U¯]©]Ó;ˆCØ ˜ˆIÜ�K‰KÐ7¸ÀÀwÔOØ 4Ð'×VÐV¬3¨s¯y©y¸#¿*¹*Ó+EÈÑ+VˆÛˆAÜ“)ˆCØ�HŠH�SÑU ÐU°a²i±ÀiÐQRÀ^ÒUØ ˜z¨´&×2BÒ2BÀ3Ç<Á<Ã>Ó2R×2YÑ2YÐZaÓ2bÐ1cÐdˆIÜ�9‹~Ð!1Ö1·g±gÜ—‘ÐRÜ 	›N¨kÕ:¸A¸s¿y¹yÈ#Ï*É*ôVá˜cŸi™i¨¯©Ô4Ø Ô ô ñ ð. ÒÙ‹vˆÜ
‡N�NÐRØ# {Õ3´S¸³^À{Õ5SôUá�#—)‘)˜SŸZ™ZÔ(ØÐøôU ô Ü�‰Ð?ÀÔEÙ‹v�ûðús   ÄP1 Ð1Q#Ð<QÑQ#ÑQ#c                ó<   € V ^8„  d   QhR\         R\         R\        /# ©r   ÚproviderÚmodelr   rq   )r   s   "r   r   r     s!   € ÷ ñ ¬#ð ´cð Ä4ñ r   c                óD   €  ^ RI Hp V! W4      #   \         d     R# i ; i)uv  Hard veto: the provider's ``ProviderProfile`` declares
``supports_vision_tool_messages=False`` â€” images are accepted in user
messages but list-type tool-result content is rejected with 400
(xiaomi/MiMo "text is not set"). ``supports_vision`` alone must not
override this, or the multimodal tool-result envelope 400s every turn
and the image never enters context (#89981).
)Ú)routed_model_rejects_vision_tool_messagesF)Ú	providersrk  r9   )rh  ri  rk  s   && r   Ú_profile_rejects_tool_mediarm    s'   € ðÝGÙ8¸ÓIÐIøÜô Úðús   ‚ �žc                ó<   € V ^8„  d   QhR\         R\         R\        /# rg  rq   )r   s   "r   r   r     s!   € ÷ ñ ¬cð ¼#ð Ä$ñ r   c                ó:  a€ \        V \        4      '       d   V P                  4       P                  4       MRpV'       d   \	        W!4      '       d   R# V\
        9   d   R# V\        9   dq   \        V\        4      '       d   VP                  4       P                  4       MRo\        ;QJ d    V3R lR 4       F  '       g   K   R# 	  R# ! V3R lR 4       4      #  ^ RIH	p V! V4      pVRJ;'       d    \        VP                  4      #   \         d     R# i ; i)a  Whether provider+model accepts image content inside a tool-result message. Unknown
providers are False (caller falls back to aux-LLM text) unless their ``ProviderProfile``
declares ``supports_vision``; ``supports_vision_tool_messages=False`` is a hard veto.rH   FTc              3   ó,   <"  € T F	  qS9   x € K  	  R # 5ir?   r   )r  ÚtagÚms   & €r   r
  Ú2_supports_media_in_tool_results.<locals>.<genexpr>'  s   øé € ÐVÑ'U ˜!–8Ó'Uùr  )Úget_provider_profileN)zgemini-3zgemini-pro-3zgemini-flash-3)rw   r3   rL   rß   rm  Ú_TOOL_RESULT_MEDIA_PROVIDERSÚ_GEMINI_PROVIDERSr  rl  rt  rr   Úsupports_visionr9   )rh  ri  Úprt  Úprofilerr  s   &&   @r   Ú_supports_media_in_tool_resultsrz    sÝ   ø€ ô %/¨x¼×$=Ò$=ˆ�‰Ó×ÑÔ À2€AßÔ+¨A×5Ò5ÙØÔ(Ô(ÙØÔÔÜ%/°´s×%;Ò%;ˆE�K‰K‹M×ÑÔ!Àˆß‹sÔVÑ'UÓV�sŒsÐVŠsÐVˆsÔVÑ'UÓVÓVÐVðÝ2Ù& qÓ)ˆØ˜dÐ"×DÐD¤t¨G×,CÑ,CÓ'DÐDøÜô Úðús   ÃD Ã5D ÄDÄDc          	      ó€   € V ^8„  d   QhR\         R\         R\        \        \         \        3,          ,          R\        /# ©r   rh  ri  Úcfgr   ©r3   r
   r  r   rr   )r   s   "r   r   r   0  s=   € ÷ 
Añ 
A¬#ð 
A´cð 
AÄÌÌcÔSVÈhÍÕ@Xð 
AÔ]añ 
Ar   c                óp   € \        W4      '       d   R# \        W4      '       d   R# ^ RIHp V! WV4      RJ # )uš  One gate for both native lanes â€” the ``vision_analyze`` fast path and the ``computer_use`` capture route
(#115248): the profile's ``supports_vision_tool_messages=False`` veto first, then either the provider's tool
results are known to carry media or the per-model capability lookup (config override â†’ catalog incl. the
profile's ``model_capabilities`` â†’ local probes) attests the model as vision-capable.FT)Ú_lookup_supports_vision)rm  rz  Úagent.image_routingr€  )rh  ri  r}  r€  s   &&& r   Ú_accepts_tool_result_imagesr‚  0  s5   € ô
 # 8×3Ò3ÙÜ& x×7Ò7ÙÝ;Ù" 8°CÓ8¸DÐ@Ð@r   c          	      ó€   € V ^8„  d   QhR\         R\         R\        \        \         \        3,          ,          R\        /# r|  r~  )r   s   "r   r   r   =  s=   € ÷ {ñ {¬ð {´Sð {¼xÌÌSÔRUÈXÍÕ?Wð {Ô\`ñ {r   c                óN   € ^ RI Hp V! WV4      R8H  ;'       d    \        WV4      # )a‡  THE gate for every tool that can hand the main model pixels (``vision_analyze``, browser and
``computer_use`` screenshots, MCP ``ImageContent``): image routing resolves to ``native``
(``agent.image_input_mode``, an explicit ``auxiliary.vision`` backend, the catalog) AND the
route accepts images inside tool results. One predicate, so the lane never depends on which
tool produced the image.)Údecide_image_input_modeÚnative)r�  r…  r‚  )rh  ri  r}  r…  s   &&& r   Ú_native_tool_result_imagesr‡  =  s+   € õ <Ù" 8°CÓ8¸HÑD×zÐzÔIdÐemÐvyÓIzÐzr   c                ó$   € V ^8„  d   QhR\         /# rQ   r‰   )r   s   "r   r   r   G  s   € ÷ ñ ¬Tñ r   c                 ó¶   €  ^ RI Hp Hp ^ RIHp \        V ! 4       V! 4       V! 4       4      #   \         d"   p\        P                  RT4        Rp?R# Rp?ii ; i)uT   :func:`_native_tool_result_images` for the active main model; any failure â†’ False.)Ú_read_main_providerÚ_read_main_model)r6   z(Native vision fast-path check failed: %sNF)	Úagent.auxiliary_clientrŠ  r‹  r8   r6   r‡  r9   r˜   r™   )rŠ  r‹  r6   r›   s       r   Ú#_should_use_native_vision_fast_pathr�  G  sJ   € ðßPÝ1Ü)Ñ*=Ó*?ÑAQÓASÑU`ÓUbÓcÐcøÜô Ü�‰Ð?ÀÔEÝûðús   ‚), ¬A·AÁAc                ó˜   € V ^8„  d   QhR\         R\         R\         R\        R\        \         ,          R\        \         \        3,          /# )r   rî   ÚquestionÚimage_data_urlÚimage_size_bytesÚ
scale_noter   )r3   rS   r
   r  r   )r   s   "r   r   r   R  sR   € ÷ gñ gÜðgÜ!ðgÜ36ðgÜJMðgäœ•ðgô 
Œ#Œsˆ(…^ñgr   c                ó  € Rp\        V\        4      '       d1   VP                  4       '       d   VRVP                  4        2,          pV'       d   VRV 2,          pRRRRRRV/RR	R	R
V//.RRVR,          R R2RR	V R,          RVRR//# )z½Multimodal tool-result envelope. The text part is intentionally minimal (the model already
has the question); ``text_summary`` is the fallback for providers without multimodal tool results.ul   Image loaded into your context â€” you can see it natively now. Use your built-in vision to answer the user.z

Question: z

Note: Ú_multimodalTÚcontentÚtypeÚtextrî   rp   Útext_summaryz,Image attached natively for the main model (é   ú.1fz# KB). Answer using built-in vision.ÚmetaºNéÈ   NÚ
size_bytesÚnative_vision)rw   r3   rL   )rî   r�  r�  r‘  r’  Ú	text_parts   &&&&& r   Ú _build_native_vision_tool_resultr¡  R  sÄ   € ð	7ð ô �(œC× Ò  X§^¡^×%5Ò%5Ø�~ h§n¡nÓ&6Ð%7Ð8Õ8ˆ	ßØ�z * Ð.Õ.ˆ	à�tØØ�V˜V YÐ/Ø�[ +°°~Ð/FÐGðIð 	Ø:Ð;KÈdÕ;RÐSVÐ:Wð X,ð ,à�˜i¨�o¨|Ð=MÈÐ`dÐeðgð gr   c                ó>   € V ^8„  d   QhR\         \        ,          RR/# )r   rž   r   N)r
   r   )r   s   "r   r   r   j  s   € ÷ ñ œ(¤4�.ð ¨Tñ r   c                 ó\   € V e    V P                  RR7       R # R #   \         d     R # i ; i)NTrÆ   )rÛ   r9   )rž   s   &r   Ú_unlink_quietlyr¤  j  s4   € ØÒð	Ø�K‰K 4ˆKÖ(ñ øô ô 	Úð	ús   † œ+ª+c                   ó   € ] tR tRtRtRtR# )Ú_ImagePrepErrorir  z=Raised by :func:`_prepare_image`; the message is user-facing.r   N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Ú__static_attributes__r   r   r   r¦  r¦  r  s   † ÝGr   r¦  c                   ó0   a € ] tR tRt o RtV 3R ltRtV tR# )Ú_PreparedImageiv  zHTemp image ready to encode; ``path`` is owned by the caller (delete it).c                óZ   <€ V ^8„  d   Qh/ S[ ;R&   S[S[,          ;R&   S[;R&   S[;R&   # )r   rž   r  rž  r  )r   r
   r3   rS   r  )r   Ú__classdict__s   "€r   r   Ú_PreparedImage.__annotate__v  s9   ø‡ ‚ á
�Jñ ñ ‘3�-Ññ ñ �Oñ	 ñ
 Ñò r   r   N)r§  r¨  r©  rª  r«  Ú__annotate_func__r¬  Ú__classdictcell__)r°  s   @r   r®  r®  v  s   ø‡ € ÙR÷ ƒ r   r®  c          
      ó€   € V ^8„  d   QhR\         R\        \         ,          R\        \        ,          R\        R\        /# )r   rî   Útask_idÚregionÚvalidate_decoder   )r3   r
   Úlistrr   r®  )r   s   "r   r   r   ~  s<   € ÷ (?ñ (?Üð(?Ü%¤c�]ð(?Ü4<¼TµNð(?ÜX\ð(?äñ(?r   c             ƒ  óD  "  € ^ RI HpHpHp  V! W! VR7      4      G Rj  x€L
 p\        RR4      p	T	R\        P                  ! 4        R2,          p
\        P                  ! \        Y§P                  4      G Rj  x€L
  TP                  \        TP                  4      / rÜp \        P                  ! \        Y«4      G Rj  x€L
 w  rëpT'       g   Tf   \	        T;'       g    R4      hYê8w  d(   \!        T
4       Tp
T
P#                  4       P$                  pT'       d6   \'        \(        T
\*        \,        4      G Rj  x€L
 pT'       d   \	        T4      hTes   \        P                  ! \.        Y¢TR	7      G Rj  x€L
 w  pppT'       g   Tf   \	        T;'       g    R
4      h\!        T
4       TTTP#                  4       P$                  rËp
\3        Y«YÍ4      #  EL´  T d   p\	        \        T4      4      ThRp?ii ; i EL‚ EL? LÆ LŒ  \0         d    \!        T
4       h i ; i5i)u^  Resolve â†’ materialize â†’ normalize â†’ (validate) â†’ (crop). Raises ``_ImagePrepError``.
Unsupported formats (SVG, BMP) become PNG BEFORE encoding â€” an unsupported media_type baked
into immutable history would 400 on every resume. The crop runs BEFORE any downscale so the
region keeps the full resolution budget. On error no temp file is left.)ÚImageResolutionErrorÚResolveContextÚresolve_image_source©rµ  Nzcache/visionÚtemp_vision_imagesÚtemp_image_z.imgzImage normalization failed.)Ú
offset_outzRegion crop failed.)Útools.image_sourcerº  r»  r¼  r¦  r3   rœ   r×   rØ   re   Ú	to_threadr­   rŸ   r  rV   r*   r¤  rM  rN  rn   r+   r&   r%   r'   ÚBaseExceptionr®  )rî   rµ  r¶  r·  rº  r»  r¼  Úresolvedr›   Útemp_dirrž   r  rž  r  Únormalized_pathÚnorm_errÚdecode_errorÚcropped_pathÚcropped_mimeÚcrop_errs   &&&$                r   Ú_prepare_imagerÌ  ~  så  é € ÷ ^Ñ]ð1Ù-¨i¸ÐPWÔ9XÓY×Yˆô ! Ð1EÓF€HØ˜¤D§J¢J£L >°Ð6Õ6€DÜ
×
Ò
Ô0°$¿¹Ó
F×FÐFØ$,§M¡M´3°x·}±}Ó3EÀr�k€DðÜ07×0AÒ0AÔB_ÐaeÓ0l×*lÑ'ˆ˜xß�Ò.Ü! (×"KÐ"KÐ.KÓLÐLØÔ"Ü˜DÔ!Ø"ˆDØŸ™›×,Ñ,ˆJßÜ!<Ü0°$Ü1Ô3Yó"[÷ [ˆL÷ Ü% lÓ3Ð3ØÒÜ9@×9JÒ9JÜ" D¸[ô:J÷ 4JÑ0ˆL˜,¨ç˜<Ò/Ü% h×&GÐ&GÐ2GÓHÐHÜ˜DÔ!Ø%1°<À×ARÑARÓAT×A\ÑA\˜
ˆDô ˜$ jÓ>Ð>ò? ZøØô 1Üœc #›hÓ'¨SÐ0ûð1úò Gò +mñ[ñ4Jøô ô Ü˜ÔØðüs°   ‚H ŽG  G¡G ¥AH Á9G;Á:&H Â!H Â?G>Ã  H Ã!;H ÄH Ä:HÄ;H Å/H Å6HÅ7H ÆH Æ/H ÇH ÇG ÇG8ÇG3Ç3G8Ç8H Ç>H ÈH ÈH ÈHÈH c                ó0   € V ^8„  d   QhR\         R\         /# )r   r�  r   r2   )r   s   "r   r   r   ©  s   € ÷ Oñ O¤sð O¬sñ Or   c                 óN   € R \        V 4      R,          R R\        R,          R R2# )z2Image too large for vision API: base64 payload is rš  ú MB (limit ú.0fzs MB) even after resizing. Run `hermes pm repair` to restore Pillow for auto-resize, or compress the image manually.rG  )rV   Ú_MAX_BASE64_BYTES)r�  s   &r   Ú_too_large_messagerÒ  ©  s=   € à
<¼SÀÓ=PÐT_Õ=`ÐadÐ<eð fÜ# {Õ3°CÐ8ð 9Mð	NðOr   c                ó<   € V ^8„  d   QhR\         R\        R\        /# )r   Úpreparedr  r   )r®  r  r3   )r   s   "r   r   r   °  s"   € ÷ ñ ¤^ð Äð ÔTWñ r   c              ‹  óp   "  € \        \        V P                  3RV P                  RV/VB G Rj  x€L
 #  L5i)zNRun :func:`_resize_image_for_vision` on the CPU executor for a prepared image.r÷   r2  N)rn   re  rž   r  )rÔ  r  rl   s   &&,r   Ú_resize_preparedrÖ  °  sA   é € ä,Ü  (§-¡-ñØ;C¿=¹=ðØT^ðØbhñ÷ ð ñ ùs   ‚-6¯4°6c          
      ó€   € V ^8„  d   QhR\         R\         R\        \         ,          R\        \        ,          R\        /# )r   rî   r�  rµ  r¶  r   )r3   r
   r¸  r   )r   s   "r   r   r   ·  s=   € ÷ :+ñ :+Üð:+Ü!ð:+Ü,4´S­Mð:+ÜJRÔSWÍ.ð:+äñ:+r   c              ƒ  óð  "  € \        V \        4      '       d   V P                  4       '       g   \        RRR7      # \	        W4      pVe   V# \        V 4      pVe   V# \        4       ^ 8„  pRpRp ^ RIHp	 V	! 4       '       dC   \        RRR7      V'       d   V'       g   \        V 4       Ve   \        VP                  4       # #  \        WVRR7      G Rj  x€L
 p\        \        TP                  TP                   R	7      G Rj  x€L
 p/ p\#        4       p\        \$        TP                  \&        4      G Rj  x€L
 p\)        T4      T8”  g	   T'       d{   \+        Y|T\&        RR
7      G Rj  x€L
 p\)        T4      \,        8”  dL   \        \/        T4      RR7      T'       d   T'       g   \        T 4       Te   \        TP                  4       # # RpT'       g   \1        T 4       \3        YTTP4                  \7        T;'       g    RTP8                  ;'       g    R4      R7      T'       d   T'       g   \        T 4       Te   \        TP                  4       # #  ELƒ  \         dV   p
\        \        T
4      RR7      u Rp
?
T'       d   T'       g   \        T 4       Te   \        TP                  4       # # Rp
?
ii ; i EL» EL‹ EL[  \:         df   p
\<        P?                  RT
4       \        RT
 2RR7      u Rp
?
T'       d   T'       g   \        T 4       Te   \        TP                  4       # # Rp
?
ii ; i  T'       d   T'       g   \        T 4       Te   \        TP                  4       i i ; i5i)zšFast path for vision-capable main models: a ``_multimodal`` envelope dict on success,
or a JSON error string (the normal tool-result contract) on failure.zimage_url is requiredF©ÚsuccessN©Úis_interruptedÚInterruptedT©r·  r5  )r0  r1  r3  )rî   r�  r�  r‘  r’  z"Native vision fast path failed: %szNative vision failed: ) rw   r3   rL   Ú
tool_errorÚ_native_turn_duplicateÚ_repeat_refusalÚ_resolve_repeat_capÚtools.interruptrÜ  Ú_release_embedr¤  rž   rÌ  r¦  rn   r  r  Ú_resolve_embed_target_bytesr)   Ú_EMBED_MAX_DIMENSIONrV   rÖ  rÑ  rÒ  Ú_record_embedr¡  rž  r(  r  r9   r˜   rÜ   )rî   r�  rµ  r¶  Úalready_nativeÚrefusalÚreservedrÔ  ÚembeddedrÜ  r›   r�  Ú_scale_infoÚembed_target_bytesÚ
_over_dimss   &&&&           r   Ú_vision_analyze_nativerï  ·  sá  é € ô
 �i¤×%Ò%¨Y¯_©_×->Ò->ÜÐ1¸5ÔAÐAÜ+¨IÓ>€NØÒ!ØÐä˜iÓ(€GØÒØˆÜ"Ó$ qÑ(€HØ)-€HØ€Hð)+Ý2Ù×ÒÜ˜m°UÔ;÷D ŸHÜ˜9Ô%àÒÜ˜HŸM™MÕ*ð  ðI	7Ü+¨IÀÐX\Ô]×]ˆHô  ;Ü% x§}¡}ÀÇÁô O÷ Oˆð ˆô 9Ó:ÐÜ6Ü$ h§m¡mÔ5IóK÷ Kˆ
äˆ~ÓÐ!3Ô3·zÜ#3ØØ!3ÔCWÐdhô$j÷ jˆNô �>Ó"Ô%6Ô6Ü!Ô"4°^Ó"DÈeÔT÷ ŸHÜ˜9Ô%àÒÜ˜HŸM™MÕ*ð  ð ˆßÜ˜)Ô$Ü/ØÀ>Ø%×0Ñ0Ü(¨×)<Ð)<¸¸h×>RÑ>R×>ZÐ>ZÐVZÓ[ô]÷ ŸHÜ˜9Ô%àÒÜ˜HŸM™MÕ*ð  òG ^øÜô 	7Üœc #›h°Ô6Ô6÷< ŸHÜ˜9Ô%àÒÜ˜HŸM™MÕ*ð  ûðE	7úòOòKòjøô ô IÜ�‰Ð;¸SÔAÜÐ2°3°%Ð8À%ÔHÔHçŸHÜ˜9Ô%àÒÜ˜HŸM™MÕ*ð  ûðIû÷ ŸHÜ˜9Ô%àÒÜ˜HŸM™MÕ*ð  üs  ‚,M6¯A M6Á0K	 ÂM6Â&M6ÃI ÃIÃI Ã)K	 ÄK Ä2K	 Ä8KÄ9K	 ÅK	 Å+KÅ,-K	 ÆM6Æ!M6Æ)&M6Ç	K	 Ç?K	 ÈK	 È$M6È4&M6ÉI ÉJ=É(J8É=J=É>K	 ÊM6Ê&M6Ê8J=Ê=K	 ËK	 ËK	 Ë	L9Ë%L4Ë9L9Ë:L< Ë>M6Ì&M6Ì4L9Ì9L< Ì<M3Í&M3Í3M6Úmin_timeoutc          
      ó€   € V ^8„  d   QhR\         R\        \        ,          R\        R\        \        ,          R\        /# )r   Úmessagesri  Údefault_timeoutrð  r   )r¸  r
   r3   rº   r  )r   s   "r   r   r   ô  s9   € ÷ 3ñ 3œtð 3¬H´S­Mð 3ÌEð 3Ü"*¬5¥/ð3Ü=Añ3r   c               óR  € TRrT \        R/ R7      ;'       g    / pVP                  R4      e,   \        \        VR,          4      Vf   \        R4      MT4      pVP                  R4      e   \        VR,          4      pRRRT RTRT/T'       d   R	T/C# / C#   \         d     L&i ; i)
zò``async_call_llm`` kwargs with ``auxiliary.vision.timeout`` / ``.temperature`` from config.
Local vision models (llama.cpp, ollama) can take well over 30s, hence generous defaults
(temperature 0.1); ``min_timeout`` lets video enforce a floor.gš™™™™™¹?rI   )r/   r¸   z-infÚtemperatureÚtaskrò  ri  )r:   rÔ   rU   rº   r9   )rò  ri  ró  rð  r¸   rõ  Ú_vision_cfgs   &&&$   r   Ú_aux_call_kwargsrø  ô  sÂ   € ð
 +¨Cˆ[ðÜ$ X°rÔ:×@Ð@¸bˆØ�?‰?˜9Ó%Ò1Üœ% ¨IÕ 6Ó7È+ÒJ]¼¸v¼ÐcnÓoˆGØ�?‰?˜=Ó)Ò5Ü ¨MÕ :Ó;ˆKð �H˜j¨(°MÀ;ÐPYÐ[bð 3ß#(�˜Ðð3ð 3Ø.0ð3ð 3øô ô Ùðús   …A:B ÂB&Â%B&c                óH   € V ^8„  d   QhR\         R\         R\         R\        /# )r   Úuser_promptÚ	part_typer9  r   )r3   r¸  )r   s   "r   r   r     s.   € ÷ dñ d¤ð d´ð dÄð dÌñ dr   c           	     ó&   € RRRRRRV /RWRV//./.# )zJSingle user message: text + one ``image_url``/``video_url`` data-URL part.ÚroleÚuserr•  r–  r—  rp   r   )rú  rû  r9  s   &&&r   Ú_media_messagesrÿ    s<   € à�V˜YØ	�˜ Ð-°¸	ÈuÐV^ÐN_Ð/`ð)bð cð dð dr   zkInsufficient credits or payment required. Please top up your API provider account and try again. Error: {e}rî   Ú	video_urlzbThe video is too large for the API. Try compressing or trimming the video (max ~50 MB). Error: {e}ÚimageÚvision_analyze_toolÚvideoÚvideo_analyze_toolc                óH   € V ^8„  d   QhR\         R\         R\         R\        /# )r   ÚkindÚsourcerú  r   )r3   r  )r   s   "r   r   r   -  s.   € ÷ mñ mœ3ð m¬ð m¼#ð mÌñ mr   c                 óx   € \        V4      ^È8”  d   VR,          R,           MTpRV  R2VRVRV/RRR	R
R^ RW0 R2^ /# )r�  rœ  z...Ú
parametersÚ_urlrú  ri  r~   NrÚ  FÚanalysis_lengthÚ
model_usedÚ_size_bytes)rV   )r  r  rú  ri  Úprompts   &&&& r   Ú_debug_call_datar  -  sa   € Ü*-¨kÓ*:¸SÔ*@ˆ[˜Õ Ö&Àk€Fà˜$˜˜t�} f¨m¸VÀWÈeÐTØ��y %Ð):¸A¸|ÈUÐV\Ð\gÐThÐjkðmð mr   c                ó0   € V ^8„  d   QhR\         R\        /# )r   Úcall_kwargsÚ	empty_log©r  r3   )r   s   "r   r   r   4  s   € ÷ 
ñ 
¬ð 
¼ñ 
r   c              ƒ  óà   "  € \        4        Vf   \        R/ V B G Rj  x€L
 p\        V4      pV'       g2   \        P	                  V4       \        \        R/ V B G Rj  x€L
 4      pV#  LJ L5i)z´Aux vision LLM analysis text, retrying once on empty content (reasoning-only response).
``response``: an already-made first call (the image path handles size-error retries itself).Nr   )r   r   r   r˜   rÜ   )r  r  r„   Úanalysiss   &&& r   Ú_call_vision_llmr  4  sa   é € ô ÔØÒÜ'Ñ6¨+Ñ6×6ˆÜ+¨HÓ5€HßÜ�‰�yÔ!Ü/´nÑ6SÀ{Ñ6S×0SÓTˆØ€Oñ 7ñ 1Tùs!   ‚A.ŸA* ?A.ÁA,Á A.Á,A.c                óÄ   € V ^8„  d   QhR\         R\         R\         R\        \         ,          R\        \         \        \        .\
        \        ,          3,          R\         /# )r   r  r  rú  ri  Ústager   )r3   r
   r   r  r¸  r   Útuple)r   s   "r   r   r   A  s^   € ÷ 4hñ 4hÜ
ð4hÜð4hÜ),ð4hÜ5=¼cµ]ð4hä”Sœ$¤Ð%¤y´Õ'7Ð7Õ8ð4hä=@ñ4hr   c           
   ƒ  óè  aaa"  € \         V ,          w  op\        V\        4      '       g   Ve   \        V4      MRp\        WW#4      o. pR VV3R llp ^ RIHp V! 4       '       d`   \        RRR7      V FL  p	V	'       g   K  V	P                  4       '       g   K%   V	P                  4        \        P                  R	V 4       KN  	  # \        P                  RWR,          4       \        P                  RVR,          4       V! VSV4      G Rj  x€L
 w  r¼V'       d   \        V4      M^ p\        P                  RV P                  4       V4       T;'       g    RV  R2pRRRV'       d	   RV RV 2MT/pV'       d   WÎR&   SP!                  RVR7       V! V4      V FL  p	V	'       g   K  V	P                  4       '       g   K%   V	P                  4        \        P                  R	V 4       KN  	  #   \         d%   p
\        P                  R
T
RR7        Rp
?
EK¢  Rp
?
ii ; i EL  \         d$   p
\        P                  R
T
RR7        Rp
?
K¯  Rp
?
ii ; i  \         Ed   pRT  RT: 2p\        P#                  RTRR7       \        T4      P%                  4       o\'        T3R lT 4       RT  R24      pTP)                  YóR7      pTSR &   T! RRR TRT/4      u Rp?T F}  p	T	'       g   K  T	P                  4       '       g   K%   T	P                  4        \        P                  R	T 4       KN    \         d$   p
\        P                  R
T
RR7        Rp
?
Kw  Rp
?
ii ; i	  # Rp?ii ; i  T F}  p	T	'       g   K  T	P                  4       '       g   K%   T	P                  4        \        P                  R	T 4       KN    \         d$   p
\        P                  R
T
RR7        Rp
?
Kw  Rp
?
ii ; i	  i ; i5i)!ud  Aux-LLM analysis skeleton for image/video: interrupt check â†’ ``stage`` â†’ JSON result.

``stage(user_prompt, debug_call_data, temp_paths)`` returns ``(analysis, scale_note)``; temp
files it appends to ``temp_paths`` are deleted in ``finally``. Returns JSON
``{"success": bool, "analysis": str}`` (``analysis`` carries the error explanation on failure).
NrH   c                ó0   € V ^8„  d   QhR\         R\        /# )r   Úresultr   r  )r   s   "r   r   Ú#_run_analysis.<locals>.__annotate__P  s   € ÷ @ñ @”tð @¤ñ @r   c                 óŠ   <€ \         P                  SS4       \         P                  4        \        P                  ! V ^RR7      # )r   F)ÚindentÚensure_ascii)Ú_debugÚlog_callrU  ÚjsonÚdumps)r  Údebug_call_dataÚ	tool_names   &€€r   ÚfinishÚ_run_analysis.<locals>.finishP  s-   ø€ Ü�‰˜	 ?Ô3Ü�‰ŒÜ�zŠz˜&¨¸Ô?Ð?r   rÛ  rÝ  FrÙ  zCleaned up temporary %s filez#Could not delete temporary file: %sTrÈ   zAnalyzing %s: %s:Né<   NzUser prompt: %srÊ   z%%s analysis completed (%s characters)z-There was a problem with the request and the z could not be analyzed.rÚ  r  Ú[z] r’  )rÚ  r  zError analyzing z: z%sc              3   ó°   <"  € T FK  w  r\         ;QJ d    V3R  lV 4       F  '       g   K   RM	  RM! V3R  lV 4       4      '       g   KG  Vx € KM  	  R# 5i)c              3   ó,   <"  € T F	  qS9   x € K  	  R # 5ir?   r   r  s   & €r   r
  Ú*_run_analysis.<locals>.<genexpr>.<genexpr>i  s   øé € Ð/RÉEÀD¸¶ËEùr  TFN)r  )r  ÚhintsÚtplr	  s   &  €r   r
  Ú _run_analysis.<locals>.<genexpr>i  s2   øé € ÐS¡5‘Z�U¯C«CÔ/RÉEÓ/R¯C¯CªCÔ/RÉEÓ/R×,R�SŠS£5ùs   ƒ&A¬AÁ
Az" could not be analyzed. Error: {e})rê   ri  r~   )Ú_ANALYSIS_KINDSrw   r3   r  rã  rÜ  rß  ÚexistsrÛ   r˜   r™   r9   rÜ   rO  rV   Ú
capitalizerB  r~   rß   Únextr   )r  r  rú  ri  r  ÚrulesÚ
temp_pathsr'  rÜ  rž   Úcleanup_errorr  r’  r  r  rê   Ú	error_msgÚtemplater%  r	  r&  s   &&&&&             @@@r   Ú_run_analysisr:  A  sX  úé € ô ' tÕ,Ñ€IˆuÜ�k¤3×'Ò'Ø*5Ò*A”c˜+Ô&ÀrˆÜ& t°[ÓH€OØ€J÷@ñ @ð
 hÝ2Ù×ÒÜ˜m°UÔ;ó. ˆDß‰t˜Ÿ™ŸœðhØ—K‘K”MÜ—L‘LÐ!?ÀÖFò	 ô- 	�‰Ð&¨°S­kÔ:Ü�‰Ð% {°4Õ'8Ô9Ù%*¨;¸ÈÓ%T×TÑˆß+3œ#˜hœ-¸ˆÜ�‰Ð;¸T¿_¹_Ó=NÐP_Ô`Ø×lÐlÐ!NÈtÈfÐTkÐlˆØ˜T :Ïz°°:°,¸bÀÀ
Ñ/KÐ_gÐhˆßØ#-�<Ñ Ø×Ñ t¸_ÐÔMÙ�f‹~ó ˆDß‰t˜Ÿ™ŸœðhØ—K‘K”MÜ—L‘LÐ!?ÀÖFò	 øô
 !ô hÜ—N‘NÐ#HÈ-Ðbf�N×gÓgûðhúò3  Uøô2 !ô hÜ—N‘NÐ#HÈ-Ðbf�N×gÒgûðhûô! õ 	TØ& t f¨B¨q©eÐ4ˆ	Ü�‰�T˜9¨tˆÔ4Ü�a“&—,‘,“.ˆÜÜS¡5ÓSØ;¸D¸6ÐAeÐfóhˆð —?‘? Q�?Ó4ˆØ#,ˆ˜Ñ Ù�y %¨°)¸ZÈÐRÓSÔSãˆDß‰t˜Ÿ™ŸœðhØ—K‘K”MÜ—L‘LÐ!?ÀÖFøÜ ô hÜ—N‘NÐ#HÈ-Ðbf�N×gÒgûðhúò ûð	Tûó ˆDß‰t˜Ÿ™ŸœðhØ—K‘K”MÜ—L‘LÐ!?ÀÖFøÜ ô hÜ—N‘NÐ#HÈ-Ðbf�N×gÒgûðhúò üs;  …AO2ÁI Á5
O2ÂO2Â&G/ÃO2ÃAI ÄH!ÄAI ÅI Å+I Å>I Æ
O2Æ+O2Ç&H$Ç*O2Ç/HÇ:HÈO2ÈHÈO2È!I È$IÈ/IÉO2ÉIÉO2ÉM'É!A8M"ËM'ËM* Ë
O2Ë-O2Ì&L.Ì,O2Ì.MÌ9MÍO2ÍMÍO2Í"M'Í'M* Í*O/Í:O/Î&N;Î9O/Î;O)	ÏO$	ÏO/Ï$O)	Ï)O/Ï/O2c                óš   € V ^8„  d   QhR\         R\         R\         R,          R\        \         ,          R\        \        ,          R\         /# )r   rî   rú  ri  Nrµ  r¶  r   )r3   r
   r¸  )r   s   "r   r   r   x  sP   € ÷ &Nñ &NÜð&NÜ!$ð&NÜ-0°4­Zð&Nä”c�]ð&Nä+3´D­>ð&NäEHñ&Nr   c              ƒ  ó\   a aaa"  € R V VVV3R llp\        RS VSV4      G Rj  x€L
 #  L5i)z°Describe an image (URL, local path, data: URL) with the auxiliary vision LLM. ``user_prompt``
is pre-formatted by the caller. Temp images live under $HERMES_HOME/cache/vision/.c                óH   € V ^8„  d   QhR\         R\        R\        R\        /# ©r   r  r%  r6  r   ©r3   r  r¸  r  )r   s   "r   r   Ú)vision_analyze_tool.<locals>.__annotate__}  s.   € ÷  ^ñ  ^œCð  ^´$ð  ^ÄDð  ^ÌUñ  ^r   c              “   óô  <"  € \        SSSR R7      G Rj  x€L
 pVP                  VP                  4       \        P	                  RVP
                  R,          4       \        P	                  R4       \        \        VP                  VP                  R7      G Rj  x€L
 p\        P	                  R\        V4      R,          4       / p\        V4      \        8”  d<   \        W54      G Rj  x€L
 p\        V4      \        8”  d   \        \        V4      4      hVP
                  VR&   \        V R	V4      p\        P	                  R
4       \        VSR4      p\!        4         \#        R/ VB G Rj  x€L
 p\+        VRV4      G Rj  x€L
 p
T
\-        T;'       g    RVP.                  ;'       g    R4      3#  ELž EL LÏ LM  \$         d«   p	\'        T	4      '       d   \        T4      \(        8”  g   h \        P	                  R\        T4      R,          \(        R,          4       \        Y54      G Rj  x€L 
 pYF^ ,          R,          ^,          R	,          R&   \#        R/ TB G Rj  x€L 
 p Rp	?	LûRp	?	ii ; i Lò5i)FrÞ  NzImage ready (%.1f KB)r™  zConverting image to base64...r5  z#Image converted to base64 (%.1f KB)r‘  rî   z%Processing image with vision model...g      ^@zYAPI rejected image (%.1f MB, likely too large); auto-resizing to ~%.0f MB and retrying...r•  rp   z0Vision LLM returned empty content, retrying oncer   rG  )rÌ  r  rž   r˜   rO  rž  rn   r  r  rV   rÑ  rÖ  rA   rÒ  rÿ  rø  r   r   r9   r  Ú_RESIZE_TARGET_BYTESr  r(  r  )r  r%  r6  rÔ  r�  rì  rò  r  r„   Ú_api_errr  rî   ri  r¶  rµ  s   &&&        €€€€r   r  Ú"vision_analyze_tool.<locals>.stage}  s  øé € Ü'¨	°7¸FÐTYÔZ×ZˆØ×Ñ˜(Ÿ-™-Ô(Ü�‰Ð+¨X×-@Ñ-@À4Õ-GÔHä�‰Ð3Ô4Ü:Ü% x§}¡}ÀÇÁô O÷ Oˆä�‰Ð9¼3¸~Ó;NÐQUÕ;UÔVØˆÜˆ~ÓÔ!2Ô2Ü#3°HÓ#J×JˆNÜ�>Ó"Ô%6Ô6Ü Ô!3°NÓ!CÓDÐDØ.6×.AÑ.AˆÐ*Ñ+Ü" 6¨;¸ÓGˆÜ�‰Ð;Ô<Ü& x°¸Ó>ˆÜÔ ð
	;Ü+Ñ:¨kÑ:×:ˆHô *ØÐKÈXóW÷ WˆàÔ*¨;×+>Ð+>¸$À×@TÑ@T×@\Ð@\ÐX\Ó]Ð]Ð]ò? [ò
Oñ
 Kñ ;øÜô 	;Ü(¨×2Ò2´s¸>Ó7JÔMaÔ7aØÜ�K‰KØkÜ�NÓ# {Õ3Ô5IÈ[Õ5Yô[ô $4°HÓ#J×JÐJˆNØ<J�Q�K˜	Õ" 1Õ% kÕ2°5Ñ9Ü+Ñ:¨kÑ:×:Ð:�Hûð	;úñWùs£   ƒI8–F4—BI8ÂF7ÂAI8Ã*F:Ã+A4I8Å F> Å.F<Å/F> Å3I8ÆI6ÆI8ÆI8Æ,	I8Æ7I8Æ:I8Æ<F> Æ>I3Ç	A&I.È/H2È03I.É#I&É$I.É)I8É.I3É3I8r  N©r:  )rî   rú  ri  rµ  r¶  r  s   f&fff r   r  r  x  s.   ûé € ÷
 ^ó  ^ôB ˜w¨	°;ÀÀuÓM×MÐMÑMùs   †,¥*¦,c                ó$   € V ^8„  d   QhR\         /# rQ   r‰   )r   s   "r   r   r   ¡  s   € ÷ 
ñ 
¤$ñ 
r   c                 óô   a€ ^ RI Hp Ho V ! 4       ;_uu_ 4        \        ;QJ d#    V3R l/ RR/3 4       F  '       g   K   RM	  RM! V3R l/ RR/3 4       4      uuRRR4       #   + '       g   i     R# ; i)uN  True when ``call_llm(task="vision")`` could resolve a client.

Mirrors its fallback chain: explicit ``auxiliary.vision.provider``, then auto (main
provider â†’ openrouter â†’ nous) â€” without the auto step the tool would vanish whenever
the explicit name was unresolvable. Probe mode skips real SDK client construction.

See #31179.
©Úaux_probe_modeÚresolve_vision_provider_clientc              3   óF   <"  € T F  pS! R/ VB ^,          RJx € K  	  R# 5i)é   Nr   r   )r  ÚkwrJ  s   & €r   r
  Ú+check_video_requirements.<locals>.<genexpr>®  s(   øé € ð 
ÙJdÀBÑ*Ñ0¨RÑ0°Õ3¸4Õ?ÓJdùs   ƒ!rh  ÚautoTFN)rŒ  rI  rJ  r  rH  s    @r   Úcheck_video_requirementsrP  ¡  se   ø€ ÷ Vñ 
×	Õ	ß‹sô 
ØKMÐPZÐ\bÐOcÑJdó
�s�sŠsô 
ØKMÐPZÐ\bÐOcÑJdó
ó 
÷ 
×	×	Ó	ús   ™$A&Á A&Á&A7	c                ó$   € V ^8„  d   QhR\         /# rQ   r‰   )r   s   "r   r   r   ³  s   € ÷ Oñ O¤4ñ Or   c                 ó:   € \        4       ;'       g    \        4       # )un  Image gate (``vision_analyze``, ``browser_vision``): an aux vision client OR the native fast
path. Both handlers attach pixels straight to a vision-capable main model, so a main model on a
provider the aux resolver does not know (OAuth, local vLLM) must not hide a working tool (#47149).
``video_analyze`` keeps the aux-only gate â€” its handler has no native path.
)r�  rP  r   r   r   Úcheck_vision_requirementsrS  ³  s   € ô /Ó0×NÐNÔ4LÓ4NÐNr   )Úregistryrß  rÖ   Úvision_analyzeÚdescriptionu‡   Load an image into the conversation so you can see it. Call it any time the user references an image â€” then answer from what you see.r	  r–  ÚobjectÚ
propertiesÚstringz>Image URL (http/https), local file path, or data: URL to load.r�  z)Your question or request about the image.r¶  ÚarrayÚitemsÚintegerÚminItemsÚmaxItemsuä   Optional [x1, y1, x2, y2] crop in ORIGINAL-image pixel coordinates, applied before any downscaling â€” the crop keeps full resolution. Load the full image first, then re-call with a region to zoom into small text or fine detail.Úrequiredc                óR   € V ^8„  d   QhR\         R\         R\        \        ,          /# )r   ÚsectionsÚenv_varsr   )r  r
   r3   )r   s   "r   r   r   é  s*   € ÷ 	Vñ 	V¤Eð 	V´Uð 	V¼xÌ½}ñ 	Vr   c                óè   € V  FS  p\        VR4      pV'       g   K  \        V4      P                  4       '       d   \        V4      P                  4       u #  M	  \        R R V 4        4       R4      # )z~First non-empty ``auxiliary.<section>.model`` from config.yaml, else the first non-empty
env var (legacy override), else None.ri  c              3   ó8   "  € T F  q'       g   K  Vx € K  	  R # 5ir?   r   )r  Úvs   & r   r
  Ú(_configured_aux_model.<locals>.<genexpr>ò  s   é € ÐNÑH�qËA—’ÓHùs   ‚	�
c              3   ól   "  € T F*  p\         P                  ! VR 4      P                  4       x € K,  	  R# 5i)rH   N)rJ   rK   rL   )r  rê   s   & r   r
  rf  ò  s'   é € ÐH¹x¸!œRŸYšY q¨"Ó-×3Ñ3×5Ð5»xùs   ‚24N)r:   r3   rL   r4  )ra  rb  ÚsectionÚ_vmodels   &&  r   Ú_configured_aux_modelrj  é  sd   € ó ˆÜ  ¨'Ó2ˆß‰7Ü�7‹|×!Ñ!×#Ò#Ü˜7“|×)Ñ)Ó+Ò+Ùñ ô ÑNÑH¹xÔHÓNÐPTÓUÐUr   c                ó^   € V ^8„  d   QhR\         \        \        3,          R\        R\        /# ©r   rk   rM  r   )r  r3   r   )r   s   "r   r   r   õ  s.   € ÷ dñ d¤t¬C´¨H¥~ð d¼Sð dÄSñ dr   c              ‹   ó^  "  € V P                  R R4      V P                  RR4      V P                  R4      rCpVP                  R4      p\        4       '       d+   \        P                  R4       \	        W#WTR7      G Rj  x€L
 # RV 2p\        R	R
4      p\        W&WuVR7      G Rj  x€L
 #  L+ L5i)rî   rH   r�  r¶  rµ  z vision_analyze: native fast path)rµ  r¶  Nz]Fully describe and explain everything about this image, then answer the following question:

)rI   )ÚAUXILIARY_VISION_MODEL)rÔ   r�  r˜   rO  rï  rj  r  )rk   rM  rî   r�  r¶  rµ  Úfull_promptri  s   &,      r   Ú_handle_vision_analyzerp  õ  s¬   é € Ø"&§(¡(¨;¸Ó";¸T¿X¹XÀjÐRTÓ=UÐW[×W_ÑW_Ð`hÓWi˜€IØ�f‰f�YÓ€Gô +×,Ò,Ü�‰Ð6Ô7Ü+¨IÈÔ`×`Ð`ð	"Ø"* ð	-ð ô " +Ð/JÓK€EÜ$ Y¸UÐ\bÔc×cÐcñ añ dùs$   ‚A;B-Á=B)Á>&B-Â$B+Â%B-Â+B-rI   Tu   ðŸ‘�ï¸�)rÖ   ÚtoolsetÚschemaÚhandlerÚcheck_fnÚis_asyncÚemojiú.mp4ú	video/mp4z.webmz
video/webmz.movz	video/movz.aviz.mkvz.mpegz
video/mpegz.mpgc                óF   € V ^8„  d   QhR\         R\        \        ,          /# )r   Ú
video_pathr   rø   )r   s   "r   r   r      s   € ÷ <ñ <¬ð <´¼#µñ <r   c                ó\   € \         P                  V P                  P                  4       4      # )z7Video MIME type from extension, or None if unsupported.)Ú_VIDEO_MIME_TYPESrÔ   Úsuffixrß   )rz  s   &r   Ú_detect_video_mime_typer~     s"   € ä× Ñ  ×!2Ñ!2×!8Ñ!8Ó!:Ó;Ð;r   c                ó0   € V ^8„  d   QhR\         R\         /# )r   r}  r   r2   )r   s   "r   r   r   %  s   € ÷ mñ m¤cð m¬cñ mr   c           	      óf   € R V  RRP                  \        \        P                  4       4      4       2# )zUnsupported video format: 'z'. Supported: r  )r  Úsortedr|  r1   )r}  s   &r   Ú_unsupported_video_formatr‚  %  s.   € Ø(¨¨°¸t¿y¹yÌÔPa×PfÑPfÓPhÓIiÓ?jÐ>kÐlÐlr   c                óR   € V ^8„  d   QhR\         R\        \        ,          R\        /# )r   rz  r÷   r   rø   )r   s   "r   r   r   )  s+   € ÷ ]ñ ]¬$ð ]¼8ÄC½=ð ]ÔTWñ ]r   c                 ó²   € T;'       g    \        V 4      ;'       g    R pRV R\        P                  ! V P                  4       4      P	                  R4       2# )rx  rú   rû   rü   )r~  rý   rþ   rÿ   r   )rz  r÷   r  s   && r   Ú_video_to_base64_data_urlr…  )  sQ   € Ø×JÐJÔ/°
Ó;×JÐJ¸{€DØ�4�&˜¤×!1Ò!1°*×2GÑ2GÓ2IÓ!J×!QÑ!QÐRYÓ!ZÐ [Ð\Ð\r   c                ó^   € V ^8„  d   QhR\         R\        \         ,          R\        R\        /# )r   r   rµ  r6  r   )r3   r
   r¸  r   )r   s   "r   r   r   .  s4   € ÷ 1dñ 1d¬ð 1d´h¼sµmð 1dÔQUð 1dÔZ^ñ 1dr   c              ƒ  ó  "  € ^ RI HpHpHpHp V P                  R4      p\        \        P                  P                  V4      4      pT ;'       g    RP                  4       P                  4       p	\        V	4      ;'       d    V	P                  R4      '       * p
V! 4       '       gÐ   V
'       dÈ   \        P                  RV 4       \        V4      P                   P                  4       pV\"        9  d   \%        \'        V4      4      h V! W! VR7      RR7      G Rj  x€L
 p\)        R	R
4      pTR\*        P,                  ! 4        T 2,          p\/        YüP0                  4       TP3                  T4       T# VP5                  4       '       d0   ^ RIHp V! \;        V4      4       \        P                  RV 4       V# \=        V 4      G Rj  x€L
 '       dƒ   \?        V 4      pV'       d   \A        VR,          4      h\)        R	R
4      pVR\*        P,                  ! 4        R2,          pVP3                  V4       \C        W^RR\D        RRR7      G Rj  x€L
  V# \%        R4      h ELE  T d   p\%        RT 24      ThRp?ii ; i L¸ L45i)uv  Local video path for a terminal-backend path, local file, or HTTP(S) URL. Only files created
here are appended to ``temp_paths`` â€” never user-provided paths. Terminal-backend reads use the
shared media resolver with ``permitted=("video",)`` â€” the exact pipeline vision_analyze uses
(media-cache host reads, bounded in-sandbox exec-read, credential-read guard, 50MB cap).)rº  r»  Ú_is_local_terminal_backendr¼  zfile://rH   z-Reading video source via terminal backend: %sr½  )Ú	permittedNz,Could not read video from terminal backend: zcache/videoÚtemp_video_filesÚterminal_video_)Úraise_if_read_blockedzUsing local video file: %sr¾   Útemp_video_rw  ÚVideozvideo/*,*/*;q=0.8g      N@Trñ   zKInvalid video source. Provide an HTTP/HTTPS URL or a valid local file path.)ru   rv   rú   )r  )#rÁ  rº  r»  rˆ  r¼  Úremoveprefixr   rJ   rž   Ú
expanduserrL   rß   rr   rx   r˜   rO  r}  r|  rA   r‚  rœ   r×   rØ   r­   rŸ   r  Úis_fileÚagent.file_safetyrŒ  r3   r{   r   r�   rì   Ú_MAX_VIDEO_BASE64_BYTES)r   rµ  r6  rº  r»  rˆ  r¼  r  Ú
local_pathÚloweredÚ	path_liker}  rÄ  r›   rÅ  rž   rŒ  râ   s   &&&               r   Ú_materialize_videor—  .  s5  é € ÷
ó ð ×#Ñ# IÓ.€FÜ”b—g‘g×(Ñ(¨Ó0Ó1€JØ�ˆ˜B×%Ñ%Ó'×-Ñ-Ó/€GÜ�W“×ZÐZ g×&8Ñ&8Ð9YÓ&ZÔ"Z€IÙ%×'Ò'¯IÜ�‰ÐCÀYÔOÜ�f“×$Ñ$×*Ñ*Ó,ˆØÔ*Ô*ÜÔ6°vÓ>Ó?Ð?ð	\Ù1Ø˜>°'Ô:ÀjôR÷ RˆHô % ]Ð4FÓGˆØ˜O¬D¯JªJ«L¨>¸&¸ÐBÕBˆÜ˜T§=¡=Ô1Ø×Ñ˜$ÔØˆØ×Ñ×ÒÝ;Ùœc *›oÔ.Ü�‰Ð0°)Ô<ØÐÜ& yÓ1×1Ö1Ü& yÓ1ˆßÜ! '¨)Õ"4Ó5Ð5ô % ]Ð4FÓGˆØ˜K¬¯
ª
« ~°TÐ:Õ:ˆØ×Ñ˜$ÔäØ˜Q¨GÐ<OÜ-°tÀtôM÷ 	Mð 	Mð ˆÜ
ÐbÓ
cÐcò?Røà#ô 	\ÜÐKÈCÈ5ÐQÓRÐX[Ð[ûð	\úñ 2ñ	Mùs{   ‚A?JÂ#JÂ&JÂ.AJÄI# ÄI ÄI# Ä A*JÆ=JÇJÇ		JÇA;JÉJÉJÉ I# É#I>É*I9É9I>É>JÊJc          
      óx   € V ^8„  d   QhR\         R\         R\         R,          R\        \         ,          R\         /# )r   r   rú  ri  Nrµ  r   )r3   r
   )r   s   "r   r   r   b  sD   € ÷ Nñ NÜðNÜ!$ðNÜ-0°4­ZðNÜIQÔRUÍðNÜbeñNr   c              ƒ  óX   a aa"  € R VVV 3R llp\        RS VSV4      G Rj  x€L
 #  L5i)zEAnalyze a video via multimodal LLM. Returns JSON {success, analysis}.c                óH   € V ^8„  d   QhR\         R\        R\        R\        /# r>  r?  )r   s   "r   r   Ú(video_analyze_tool.<locals>.__annotate__e  s(   € ÷ ñ œCð ´$ð ÄDð ÌUñ r   c              “   ód  <"  € \        SSV4      G R j  x€L
 pVP                  4       P                  pVR,          p\        P	                  RV4       \        V4      pV'       g   \        \        VP                  4      4      hV\        8”  d   \        P                  RV4       \        W6R7      p\        V4      \        8”  d0   \        R\        V4      R,          R R\        R,          R R24      hWAR	&   \        V R
V4      p\        VSRRR7      p	\!        V	R4      G R j  x€L
 p
V
R 3#  EL L5i)NzVideo ready (%.1f MB)u,   Video is %.1f MB â€” may be slow or rejectedr5  z+Video too large for API: base64 payload is rš  rÏ  rÐ  z+ MB). Compress or trim the video and retry.Úvideo_size_bytesr   g     €f@)rð  z#Empty video response, retrying oncerG  )r—  rM  rN  r˜   rO  r~  rA   r‚  r}  Ú_VIDEO_SIZE_WARN_BYTESrÜ   r…  rV   r“  rÿ  rø  r  )r  r%  r6  Útemp_video_pathr�  Úvideo_size_mbÚdetected_mimeÚvideo_data_urlrò  r  r  ri  rµ  r   s   &&&        €€€r   r  Ú!video_analyze_tool.<locals>.stagee  s)  øé € Ü 2°9¸gÀzÓ R×RˆØ*×/Ñ/Ó1×9Ñ9ÐØ(¨KÕ8ˆÜ�‰Ð+¨]Ô;Ü/°Ó@ˆßÜÔ6°×7MÑ7MÓNÓOÐOØÔ4Ô4Ü�N‰NÐIÈ=ÔYÜ2°?Ô\ˆÜˆ~ÓÔ!8Ô8ÜØ=¼cÀ.Ó>QÐU`Õ>aÐbeÐ=fð gÜ1°[ÕAÀ#ÐFð G8ð9ó:ð :ð /?Ð*Ñ+Ü" 6¨;¸ÓGˆÜ& x°¸È5ÔQˆÜ)¨+Ð7\Ó]×]ˆØ˜ˆ~Ðò' Sñ$ ^ùs"   ƒD0”D+•DD0Ä"D.Ä#	D0Ä.D0r  NrE  )r   rú  ri  rµ  r  s   f&ff r   r  r  b  s+   úé € ÷ò ô* ˜w¨	°;ÀÀuÓM×MÐMÑMùs   …*£(¤*Úvideo_analyzeu?  Analyze a video from a URL or local file path using a multimodal AI model. Sends the video to a video-capable model (e.g. Gemini) for understanding. Use this for video files â€” for images, use vision_analyze instead. Supports mp4, webm, mov, avi, mkv, mpeg formats. Note: large videos (>20 MB) may be slow; max ~50 MB.z5Video URL (http/https) or local file path to analyze.zpYour specific question about the video. The AI will describe what happens in the video and answer your question.c                ót   € V ^8„  d   QhR\         \        \        3,          R\        R\        \        ,          /# rl  )r  r3   r   r   )r   s   "r   r   r   —  s2   € ÷ Xñ X¤¤S¬# X¥ð X´cð X¼iÌ½nñ Xr   c                 ó¢   € V P                  R R4      V P                  RR4      r2RV 2p\        RR4      p\        W$WQP                  R4      R7      # )r   rH   r�  z¸Fully describe and explain everything happening in this video, including visual content, motion, audio cues, text overlays, and scene transitions. Then answer the following question:

rµ  r½  )r  rI   )ÚAUXILIARY_VIDEO_MODELrn  )rÔ   rj  r  )rk   rM  r   r�  ro  ri  s   &,    r   Ú_handle_video_analyzer¨  —  sZ   € ØŸ(™( ;°Ó3°T·X±X¸jÈ"Ó5Mˆxð	?à?G¸jð	Jð ô "Ð"5Ð7jÓk€EÜ˜i°eÇVÁVÈIÓEVÔWÐWr   u   ðŸŽ¬c                óh   € V ^8„  d   Qh/ ^ \         9   d
   \        ;R&   ^\         9   d
   \        ;R&   # )r   r   r   )Ú__conditional_annotations__r   )r   s   "r   r   r      s0   € ÷ ñ ÷. Ò ”Ñ ñ/÷0 )Ò (œcÑ (ò1r   r?   i   )é   i  @i  P )z	too largeÚpayloadÚ413Úcontent_too_largeÚrequest_too_largeÚexceedsz
size limit>   ÚnousÚclaudeÚopenaiÚvertexÚbedrockÚ	anthropicÚ
openrouterúopenai-chatúazure-openaiúopenai-codexúgoogle-vertexúanthropic-directúanthropic-vertex>   ÚgeminiÚgoogleúgoogle-geminiúgoogle-vertex-gemini)rH   )NN)Ú402Úinsufficientzpayment requiredÚcreditsÚbilling))údoes not supportznot support imageÚcontent_policyÚ
multimodalúunrecognized request argumentzimage inputzY{model} does not support vision or our request was not accepted by the server. Error: {e}))r  rî   z¼The vision API rejected the image. This can happen when the image is in an unsupported format, corrupted, or still too large after auto-resize. Try a smaller JPEG/PNG and retry. Error: {e}))rÆ  znot support videorÇ  rÈ  rÉ  zvideo inputr   z›The model does not support video analysis or the request was rejected. Ensure you're using a video-capable model (e.g. google/gemini-2.5-flash). Error: {e})NNN)‡rª  r«  rý   re   r#  Úconcurrent.futuresr   Úior   ÚloggingrJ   r×   Úpathlibr   Útypingr   r   r   r   r	   r
   Úurllib.parser   r‚   Úhermes_dir_aclr   r   r   r   Úhermes_constantsr   Útools.debug_helpersr   Útools.website_policyr   Ú!tools.vision_tools_history_budgetr   rà  r    rç  r!   rä  r"   rá  r#   râ  r$   rå  Útools.vision_tools_image_prepr%   r&   r'   r(   r)   r*   r+   Ú	getLoggerr§  r˜   r!  r:   rM   rº   ró   rò   r[   r`   Ú_VISION_CPU_WORKERSrh   rn   r{   r‡   rÒ   r�   rœ   r­   r±   rì   rô   r  rÑ  ræ  rB  r  r  r(  r.  re  Ú	frozensetru  rv  rm  rz  r‚  r‡  r�  r¡  r¤  rA   r¦  r®  rÌ  rÒ  rÖ  rï  rø  rÿ  Ú_BILLING_HINTSÚ_IMAGE_ERROR_RULESÚ_VIDEO_ERROR_RULESr1  r  r  r:  r  rP  rS  Útools.registryrT  rß  ÚVISION_ANALYZE_SCHEMArj  rp  Úregisterr|  r“  rž  r~  r‚  r…  r—  r  ÚVIDEO_ANALYZE_SCHEMAr¨  r   )rª  s   @r   Ú<module>rà     sW  øðöó Û Û Ý 1Ý Û Û 	Û Ý ß G× GÝ !Û Ý (ð €Ó Ø$(Ð Ó (õiõ ,Ý ,Ý 5÷÷ ÷&÷ &ñ &ð 
×	Ò	˜8Ó	$€á	�nÐ.BÔ	C€ð t÷ ÷
Nñ 0Ð0PÐRdÐfkÓlÐ ØÒ#Ø#Ðð .Ð õ+õ&ñ 2Ó3Ð á)Ø#¸ôÐ ò
dõ(õð9ð õõ 9õxò*ZõMm÷`a÷]ð %Ð ð Ð ð 'Ð ðÐ õaõ.ò(ð* KOØ6JØ=AØ:>Ø16÷	Vñ|  )ò *ó  Ð ñ
 Ò[Ó\Ð ÷õõ(
Aõ{õ÷gõ0ôH�jô Hô�Zô õ(?õVOõ÷:+ðz3Ø48÷3õ$dð S€àð6ð7ð+ððÐ ð Ð'¨Õ*¨1Õ-Ð.ð3ð
 ð*ð+ð
Ð ð Ð#Ð%7Ð8ØÐ"Ð$6Ð7ð9€õ
m÷
õ4h÷n&NõR
õ$O÷ 0ð Ðð ð	ð Ø�ØØØ˜ØÐ_ðð Ø˜ØÐJðð Ø˜Ø˜& )Ð,Ø˜AØ˜AØððð
ð. 	�[ *Ð-ð3ð(Ð õV	Võdð" 	× Ò Ø	ØØ Ø"Ø&ØØ
õð ˆKØˆ\Ø
ˆKØ
ˆKØ
ˆKØˆ\Ø
ˆLðÐ ð +Ð Ø)Ð õ<õ
m÷]õ
1d÷hNð8 ˆOØð	?ð Ø�ØØØ˜ØÐVðð Ø˜Øð   Rðð	
ð 	�[ *Ð-ððÐ õ4Xð 	× Ò Ø	ØØØ!Ø%ØØ
÷r   