§
    ‰eîi_K  ã                   ó0  — d Z ddlZddlZddlZddlZddlZddlmZ ddlm	Z	m
Z
mZmZmZ  ej        e¦  «        Zdej        defd„Zdedefd	„Zdd
ee         dee         fd„Z G d„ d¦  «        Z G d„ d¦  «        Z e¦   «         Zdefd„Zddefd„ZdS )aV  Central registry for all hermes-agent tools.

Each tool file calls ``registry.register()`` at module level to declare its
schema, handler, toolset membership, and availability check.  ``model_tools.py``
queries the registry instead of maintaining its own parallel data structures.

Import chain (circular-import safe):
    tools/registry.py  (no imports from model_tools or tool files)
           ^
    tools/*.py  (import from tools.registry at module level)
           ^
    model_tools.py  (imports tools.registry + all tool modules)
           ^
    run_agent.py, cli.py, batch_runner.py, etc.
é    N)ÚPath)ÚCallableÚDictÚListÚOptionalÚSetÚnodeÚreturnc                 ó8  — t          | t          j        ¦  «        rt          | j        t          j        ¦  «        sdS | j        j        }t          |t          j        ¦  «        o9|j        dk    o.t          |j        t          j        ¦  «        o|j        j	        dk    S )zHReturn True when *node* is a ``registry.register(...)`` call expression.FÚregisterÚregistry)
Ú
isinstanceÚastÚExprÚvalueÚCallÚfuncÚ	AttributeÚattrÚNameÚid)r	   r   s     ú0/home/div/.hermes/hermes-agent/tools/registry.pyÚ_is_registry_register_callr      s…   € å�d�CœHÑ%Ô%ð ­Z¸¼
ÅCÄHÑ-MÔ-Mð ØˆuØŒ:Œ?€Då�4�œÑ'Ô'ð 	(ØŒI˜Ò#ð	(å�t”z¥3¤8Ñ,Ô,ð	(ð ŒJŒM˜ZÒ'ð	ó    Úmodule_pathc                 óä   — 	 |                       d¬¦  «        }t          j        |t          | ¦  «        ¬¦  «        }n# t          t
          f$ r Y dS w xY wt          d„ |j        D ¦   «         ¦  «        S )zíReturn True when the module contains a top-level ``registry.register(...)`` call.

    Only inspects module-body statements so that helper modules which happen
    to call ``registry.register()`` inside a function are not picked up.
    zutf-8)Úencoding)ÚfilenameFc              3   ó4   K  — | ]}t          |¦  «        V — Œd S ©N)r   )Ú.0Ústmts     r   ú	<genexpr>z*_module_registers_tools.<locals>.<genexpr>5   s+   è è € ÐFÐF°DÕ)¨$Ñ/Ô/ÐFÐFÐFÐFÐFÐFr   )Ú	read_textr   ÚparseÚstrÚOSErrorÚSyntaxErrorÚanyÚbody)r   ÚsourceÚtrees      r   Ú_module_registers_toolsr-   )   sƒ   € ðØ×&Ò&°Ð&Ñ8Ô8ˆÝŒy˜­#¨kÑ*:Ô*:Ð;Ñ;Ô;ˆˆøÝ•[Ð!ð ð ð Øˆuˆuðøøøõ ÐFÐF¸D¼IÐFÑFÔFÑFÔFÐFs   ‚9< ¼AÁAÚ	tools_dirc                 óž  — | �t          | ¦  «        n*t          t          ¦  «                             ¦   «         j        }d„ t	          |                     d¦  «        ¦  «        D ¦   «         }g }|D ]_}	 t          j        |¦  «         |                     |¦  «         Œ-# t          $ r&}t                               d||¦  «         Y d}~ŒXd}~ww xY w|S )zLImport built-in self-registering tool modules and return their module names.Nc                 óR   — g | ]$}|j         d v¯t          |¦  «        ¯d|j        › �‘Œ%S )>   ú__init__.pyúmcp_tool.pyúregistry.pyztools.)Únamer-   Ústem)r!   Úpaths     r   ú
<listcomp>z*discover_builtin_tools.<locals>.<listcomp>;   sK   € ð ð ð àØŒ9ÐIÐIÐIÝ# DÑ)Ô)ð Jð 	�”ÐÐàIÐIÐIr   z*.pyz#Could not import tool module %s: %s)r   Ú__file__ÚresolveÚparentÚsortedÚglobÚ	importlibÚimport_moduleÚappendÚ	ExceptionÚloggerÚwarning)r.   Ú
tools_pathÚmodule_namesÚimportedÚmod_nameÚes         r   Údiscover_builtin_toolsrH   8   sï   € à$-Ð$9•�i‘”�½tÅH¹~¼~×?UÒ?UÑ?WÔ?WÔ?^€Jðð å˜:Ÿ?š?¨6Ñ2Ô2Ñ3Ô3ðñ ô €Lð €HØ ð Oð Oˆð	OÝÔ# HÑ-Ô-Ð-Ø�OŠO˜HÑ%Ô%Ð%Ð%øÝð 	Oð 	Oð 	OÝ�NŠNÐ@À(ÈAÑNÔNÐNÐNÐNÐNÐNÐNøøøøð	Oøøøà€Os   Á0)BÂ
C
Â$CÃC
c                   ó    — e Zd ZdZdZ	 dd„ZdS )Ú	ToolEntryz&Metadata for a single registered tool.©
r4   ÚtoolsetÚschemaÚhandlerÚcheck_fnÚrequires_envÚis_asyncÚdescriptionÚemojiÚmax_result_size_charsNc                 ó’   — || _         || _        || _        || _        || _        || _        || _        || _        |	| _        |
| _	        d S r    rK   )Úselfr4   rL   rM   rN   rO   rP   rQ   rR   rS   rT   s              r   Ú__init__zToolEntry.__init__U   sS   € ð ˆŒ	ØˆŒØˆŒØˆŒØ ˆŒØ(ˆÔØ ˆŒØ&ˆÔØˆŒ
Ø%:ˆÔ"Ð"Ð"r   r    )Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ú	__slots__rW   © r   r   rJ   rJ   L   s:   € € € € € Ø0Ð0ð€Ið (,ð;ð ;ð ;ð ;ð ;ð ;r   rJ   c                   óò  — e Zd ZdZd„ Zdeee         ee	e
f         f         fd„Zdee         fd„Zdee	e
f         fd„Zde	de
d	z  defd
„Zde	dee         fd„Zdee	         fd„Zde	dee	         fd„Zde	de	dd	fd„Zdee	e	f         fd„Zde	dee	         fd„Z	 	 	 	 	 	 d1de	de	dede
de
dedede	de	deez  d	z  fd„Zde	dd	fd„Zd2dee	         d edee         fd!„Zde	d"ede	fd#„Zd3de	d$eez  d	z  deez  fd%„Z dee	         fd&„Z!de	dee         fd'„Z"de	dee	         fd(„Z#d4de	d$e	de	fd*„Z$dee	e	f         fd+„Z%de	defd,„Z&dee	ef         fd-„Z'dee	ef         fd.„Z(dee	ef         fd/„Z)d2d efd0„Z*d	S )5ÚToolRegistryzISingleton registry that collects tool schemas + handlers from tool files.c                 ó`   — i | _         i | _        i | _        t          j        ¦   «         | _        d S r    )Ú_toolsÚ_toolset_checksÚ_toolset_aliasesÚ	threadingÚRLockÚ_lock©rV   s    r   rW   zToolRegistry.__init__g   s.   € Ø,.ˆŒØ46ˆÔØ02ˆÔõ ”_Ñ&Ô&ˆŒ
ˆ
ˆ
r   r
   c                 ó¸   — | j         5  t          | j                             ¦   «         ¦  «        t	          | j        ¦  «        fcddd¦  «         S # 1 swxY w Y   dS )zBReturn a coherent snapshot of registry entries and toolset checks.N)rf   Úlistra   ÚvaluesÚdictrb   rg   s    r   Ú_snapshot_statezToolRegistry._snapshot_statep   s«   € àŒZð 	Jð 	JÝ˜œ×*Ò*Ñ,Ô,Ñ-Ô-­t°DÔ4HÑ/IÔ/IÐIð	Jð 	Jð 	Jð 	Jñ 	Jô 	Jð 	Jð 	Jð 	Jð 	Jð 	Jð 	Jøøøð 	Jð 	Jð 	Jð 	Jð 	Jð 	Js   ˆ:AÁAÁAc                 ó6   — |                       ¦   «         d         S )z4Return a stable snapshot of registered tool entries.r   ©rl   rg   s    r   Ú_snapshot_entrieszToolRegistry._snapshot_entriesu   ó   € à×#Ò#Ñ%Ô% aÔ(Ð(r   c                 ó6   — |                       ¦   «         d         S )z8Return a stable snapshot of toolset availability checks.é   rn   rg   s    r   Ú_snapshot_toolset_checksz%ToolRegistry._snapshot_toolset_checksy   rp   r   rL   ÚcheckNc                 ó’   — |sdS 	 t           |¦   «         ¦  «        S # t          $ r t                               d|¦  «         Y dS w xY w)zQRun a toolset check, treating missing or failing checks as unavailable/available.Tz,Toolset %s check raised; marking unavailableF)Úboolr@   rA   Údebug©rV   rL   rt   s      r   Ú_evaluate_toolset_checkz$ToolRegistry._evaluate_toolset_check}   s]   € àð 	Ø�4ð	Ý˜˜™œ‘=”=Ð øÝð 	ð 	ð 	Ý�LŠLÐGÈÑQÔQÐQØ�5�5ð	øøøs   † �%AÁAr4   c                 óx   — | j         5  | j                             |¦  «        cddd¦  «         S # 1 swxY w Y   dS )z0Return a registered tool entry by name, or None.N)rf   ra   Úget)rV   r4   s     r   Ú	get_entryzToolRegistry.get_entry‡   s   € àŒZð 	)ð 	)Ø”;—?’? 4Ñ(Ô(ð	)ð 	)ð 	)ð 	)ñ 	)ô 	)ð 	)ð 	)ð 	)ð 	)ð 	)ð 	)øøøð 	)ð 	)ð 	)ð 	)ð 	)ð 	)ó   ˆ/¯3¶3c                 óX   — t          d„ |                      ¦   «         D ¦   «         ¦  «        S )z;Return sorted unique toolset names present in the registry.c                 ó   — h | ]	}|j         ’Œ
S r]   ©rL   ©r!   Úentrys     r   ú	<setcomp>z<ToolRegistry.get_registered_toolset_names.<locals>.<setcomp>Ž   s   € ÐKÐKÐK¨�u”}ÐKÐKÐKr   ©r;   ro   rg   s    r   Úget_registered_toolset_namesz)ToolRegistry.get_registered_toolset_namesŒ   s+   € åÐKÐK°$×2HÒ2HÑ2JÔ2JÐKÑKÔKÑLÔLÐLr   c                 ó^   ‡— t          ˆfd„|                      ¦   «         D ¦   «         ¦  «        S )z:Return sorted tool names registered under a given toolset.c              3   ó<   •K  — | ]}|j         ‰k    ¯|j        V — Œd S r    ©rL   r4   )r!   r‚   rL   s     €r   r#   z:ToolRegistry.get_tool_names_for_toolset.<locals>.<genexpr>’   s>   øè è € ð 
ð 
Ø ØŒ} Ò'Ð'ð ŒJØ'Ð'Ð'Ð'ð
ð 
r   r„   )rV   rL   s    `r   Úget_tool_names_for_toolsetz'ToolRegistry.get_tool_names_for_toolset�   sG   ø€ åð 
ð 
ð 
ð 
Ø$(×$:Ò$:Ñ$<Ô$<ð
ñ 
ô 
ñ 
ô 
ð 	
r   Úaliasc                 óØ   — | j         5  | j                             |¦  «        }|r#||k    rt                               d|||¦  «         || j        |<   ddd¦  «         dS # 1 swxY w Y   dS )z8Register an explicit alias for a canonical toolset name.z4Toolset alias collision: '%s' (%s) overwritten by %sN)rf   rc   r{   rA   rB   )rV   rŠ   rL   Úexistings       r   Úregister_toolset_aliasz#ToolRegistry.register_toolset_alias—   sÅ   € àŒZð 	3ð 	3ØÔ,×0Ò0°Ñ7Ô7ˆHØð ˜H¨Ò/Ð/Ý—’ØJØ˜8 Wñô ð ð ,3ˆDÔ! %Ñ(ð	3ð 	3ð 	3ñ 	3ô 	3ð 	3ð 	3ð 	3ð 	3ð 	3ð 	3ð 	3øøøð 	3ð 	3ð 	3ð 	3ð 	3ð 	3s   ˆA
AÁA#Á&A#c                 ól   — | j         5  t          | j        ¦  «        cddd¦  «         S # 1 swxY w Y   dS )z=Return a snapshot of ``{alias: canonical_toolset}`` mappings.N)rf   rk   rc   rg   s    r   Úget_registered_toolset_aliasesz+ToolRegistry.get_registered_toolset_aliases¢   s|   € àŒZð 	/ð 	/Ý˜Ô-Ñ.Ô.ð	/ð 	/ð 	/ð 	/ñ 	/ô 	/ð 	/ð 	/ð 	/ð 	/ð 	/ð 	/øøøð 	/ð 	/ð 	/ð 	/ð 	/ð 	/s   ˆ)©-°-c                 óx   — | j         5  | j                             |¦  «        cddd¦  «         S # 1 swxY w Y   dS )z8Return the canonical toolset name for an alias, or None.N)rf   rc   r{   )rV   rŠ   s     r   Úget_toolset_alias_targetz%ToolRegistry.get_toolset_alias_target§   s‚   € àŒZð 	4ð 	4ØÔ(×,Ò,¨UÑ3Ô3ð	4ð 	4ð 	4ð 	4ñ 	4ô 	4ð 	4ð 	4ð 	4ð 	4ð 	4ð 	4øøøð 	4ð 	4ð 	4ð 	4ð 	4ð 	4r}   FÚ rM   rN   rO   rP   rQ   rR   rS   rT   c                 ó8  — | j         5  | j                             |¦  «        }|r�|j        |k    r„|j                             d¦  «        o|                     d¦  «        }|r#t
                               d|||j        ¦  «         n0t
                               d|||j        ¦  «         	 ddd¦  «         dS t          ||||||pg ||p|                     dd¦  «        |	|
¬¦
  «
        | j        |<   |r|| j	        vr
|| j	        |<   ddd¦  «         dS # 1 swxY w Y   dS )zARegister a tool.  Called at module-import time by each tool file.zmcp-z8Tool '%s': MCP toolset '%s' overwriting MCP toolset '%s'z˜Tool registration REJECTED: '%s' (toolset '%s') would shadow existing tool from toolset '%s'. Deregister the existing tool first if this is intentional.NrR   r’   rK   )
rf   ra   r{   rL   Ú
startswithrA   rw   ÚerrorrJ   rb   )rV   r4   rL   rM   rN   rO   rP   rQ   rR   rS   rT   rŒ   Úboth_mcps                r   r   zToolRegistry.register°   sÊ  € ð ŒZð %	9ð %	9Ø”{—’ tÑ,Ô,ˆHØð ˜HÔ,°Ò7Ð7ð Ô$×/Ò/°Ñ7Ô7ð 3Ø×*Ò*¨6Ñ2Ô2ð ð ð Ý—L’LØRØ˜g xÔ'7ñô ð ð õ —L’LðFð ˜g xÔ'7ñ	ô ð ð ð/%	9ð %	9ð %	9ñ %	9ô %	9ð %	9ð %	9ð %	9õ0 !*ØØØØØ!Ø)Ð/¨RØ!Ø'ÐH¨6¯:ª:°mÀRÑ+HÔ+HØØ&;ð!ñ !ô !ˆDŒK˜Ñð ð 9˜G¨4Ô+?Ð?Ð?Ø08�Ô$ WÑ-ðK%	9ð %	9ð %	9ñ %	9ô %	9ð %	9ð %	9ð %	9ð %	9ð %	9ð %	9ð %	9øøøð %	9ð %	9ð %	9ð %	9ð %	9ð %	9s   ˆBDÂ4ADÄDÄDc                 óÎ  ‡— | j         5  | j                             |d¦  «        Š‰€	 ddd¦  «         dS t          ˆfd„| j                             ¦   «         D ¦   «         ¦  «        }|sJ| j                             ‰j        d¦  «         ˆfd„| j                             ¦   «         D ¦   «         | _        ddd¦  «         n# 1 swxY w Y   t           
                    d|¦  «         dS )a  Remove a tool from the registry.

        Also cleans up the toolset check if no other tools remain in the
        same toolset.  Used by MCP dynamic tool discovery to nuke-and-repave
        when a server sends ``notifications/tools/list_changed``.
        Nc              3   ó8   •K  — | ]}|j         ‰j         k    V — Œd S r    r€   )r!   rG   r‚   s     €r   r#   z*ToolRegistry.deregister.<locals>.<genexpr>ò   s=   øè è € ð 'ð 'Ø/0�”	˜Uœ]Ò*ð'ð 'ð 'ð 'ð 'ð 'r   c                 ó2   •— i | ]\  }}|‰j         k    ¯||“ŒS r]   r€   )r!   rŠ   Útargetr‚   s      €r   ú
<dictcomp>z+ToolRegistry.deregister.<locals>.<dictcomp>÷   s6   ø€ ð )ð )ð )á%˜˜vØ ¤Ò.Ð.ð ˜6à.Ð.Ð.r   zDeregistered tool: %s)rf   ra   Úpopr)   rj   rb   rL   rc   ÚitemsrA   rw   )rV   r4   Útoolset_still_existsr‚   s      @r   Ú
deregisterzToolRegistry.deregisterå   si  ø€ ð ŒZð 	ð 	Ø”K—O’O D¨$Ñ/Ô/ˆEØˆ}Øð	ð 	ð 	ñ 	ô 	ð 	ð 	ð 	õ $'ð 'ð 'ð 'ð 'Ø48´K×4FÒ4FÑ4HÔ4Hð'ñ 'ô 'ñ $ô $Ð ð (ð ØÔ$×(Ò(¨¬¸Ñ=Ô=Ð=ð)ð )ð )ð )à)-Ô)>×)DÒ)DÑ)FÔ)Fð)ñ )ô )�Ô%ð	ð 	ð 	ñ 	ô 	ð 	ð 	ð 	ð 	ð 	ð 	øøøð 	ð 	ð 	ð 	õ  	�ŠÐ,¨dÑ3Ô3Ð3Ð3Ð3s   ‰B?µA>B?Â?CÃCÚ
tool_namesÚquietc                 ó,  — g }i }d„ |                       ¦   «         D ¦   «         }t          |¦  «        D ]á}|                     |¦  «        }|sŒ|j        r–|j        |vrb	 t	          |                     ¦   «         ¦  «        ||j        <   n7# t
          $ r* d||j        <   |st                               d|¦  «         Y nw xY w||j                 s|st                               d|¦  «         Œ·i |j        ¥d|j	        i¥}| 
                    d|dœ¦  «         Œâ|S )zªReturn OpenAI-format tool schemas for the requested tool names.

        Only tools whose ``check_fn()`` returns True (or have no check_fn)
        are included.
        c                 ó   — i | ]
}|j         |“ŒS r]   ©r4   r�   s     r   r›   z0ToolRegistry.get_definitions.<locals>.<dictcomp>
  s   € ÐSÐSÐS°˜5œ: uÐSÐSÐSr   FzTool %s check raised; skippingz"Tool %s unavailable (check failed)r4   Úfunction)Útyper¥   )ro   r;   r{   rO   rv   r@   rA   rw   rM   r4   r?   )	rV   r    r¡   ÚresultÚcheck_resultsÚentries_by_namer4   r‚   Úschema_with_names	            r   Úget_definitionszToolRegistry.get_definitions  s[  € ð ˆØ.0ˆØSÐS¸$×:PÒ:PÑ:RÔ:RÐSÑSÔSˆÝ˜:Ñ&Ô&ð 	Nð 	NˆDØ#×'Ò'¨Ñ-Ô-ˆEØð ØØŒ~ð Ø”>¨Ð6Ð6ðQÝ8<¸U¿^º^Ñ=MÔ=MÑ8NÔ8N˜ e¤nÑ5Ð5øÝ$ð Qð Qð QØ8=˜ e¤nÑ5Ø$ð QÝ"ŸLšLÐ)IÈ4ÑPÔPÐPøøðQøøøð % U¤^Ô4ð Ø ð QÝŸšÐ%IÈ4ÑPÔPÐPØàC %¤,ÐC°¸¼
ÐCÐCÐØ�MŠM :Ð;KÐLÐLÑMÔMÐMÐMØˆs   Á)BÂ1B;Â:B;Úargsc                 óŠ  — |                       |¦  «        }|st          j        dd|› �i¦  «        S 	 |j        rddlm}  | |j        |fi |¤Ž¦  «        S  |j        |fi |¤ŽS # t          $ rT}t           	                    d||¦  «         t          j        ddt          |¦  «        j        › d|› �i¦  «        cY d}~S d}~ww xY w)	zâExecute a tool handler by name.

        * Async handlers are bridged automatically via ``_run_async()``.
        * All exceptions are caught and returned as ``{"error": "..."}``
          for consistent error format.
        r•   zUnknown tool: r   )Ú
_run_asynczTool %s dispatch error: %szTool execution failed: z: N)r|   ÚjsonÚdumpsrQ   Úmodel_toolsr®   rN   r@   rA   Ú	exceptionr¦   rX   )rV   r4   r¬   Úkwargsr‚   r®   rG   s          r   ÚdispatchzToolRegistry.dispatch$  s  € ð —’˜tÑ$Ô$ˆØð 	BÝ”:˜wÐ(?¸Ð(?Ð(?Ð@ÑAÔAÐAð	\ØŒ~ð AØ2Ð2Ð2Ð2Ð2Ð2Ø!�z - %¤-°Ð"?Ð"?¸Ð"?Ð"?Ñ@Ô@Ð@Ø �5”= Ð0Ð0¨Ð0Ð0Ð0øÝð 	\ð 	\ð 	\Ý×ÒÐ9¸4ÀÑCÔCÐCÝ”:˜wÐ(YÅ$ÀqÁ'Ä'ÔBRÐ(YÐ(YÐVWÐ(YÐ(YÐZÑ[Ô[Ð[Ð[Ð[Ð[Ð[Ð[øøøøð	\øøøs$   ²#A$ ÁA$ Á$
CÁ.A	B=Â7CÂ=CÚdefaultc                 ód   — |                       |¦  «        }|r|j        �|j        S |�|S ddlm} |S )zBReturn per-tool max result size, or *default* (or global default).Nr   )ÚDEFAULT_RESULT_SIZE_CHARS)r|   rT   Útools.budget_configr·   )rV   r4   rµ   r‚   r·   s        r   Úget_max_result_sizez ToolRegistry.get_max_result_size;  sO   € à—’˜tÑ$Ô$ˆØð 	/�UÔ0Ð<ØÔ.Ð.ØÐØˆNØAÐAÐAÐAÐAÐAØ(Ð(r   c                 óX   — t          d„ |                      ¦   «         D ¦   «         ¦  «        S )z0Return sorted list of all registered tool names.c              3   ó$   K  — | ]}|j         V — Œd S r    r¤   r�   s     r   r#   z2ToolRegistry.get_all_tool_names.<locals>.<genexpr>G  s$   è è € ÐGÐG U�e”jÐGÐGÐGÐGÐGÐGr   r„   rg   s    r   Úget_all_tool_nameszToolRegistry.get_all_tool_namesE  s+   € åÐGÐG¨d×.DÒ.DÑ.FÔ.FÐGÑGÔGÑGÔGÐGr   c                 óB   — |                       |¦  «        }|r|j        ndS )uÊ   Return a tool's raw schema dict, bypassing check_fn filtering.

        Useful for token estimation and introspection where availability
        doesn't matter â€” only the schema content does.
        N)r|   rM   ©rV   r4   r‚   s      r   Ú
get_schemazToolRegistry.get_schemaI  s&   € ð —’˜tÑ$Ô$ˆØ$Ð.ˆuŒ|ˆ|¨$Ð.r   c                 óB   — |                       |¦  «        }|r|j        ndS )z.Return the toolset a tool belongs to, or None.N)r|   rL   r¾   s      r   Úget_toolset_for_toolz!ToolRegistry.get_toolset_for_toolR  s$   € à—’˜tÑ$Ô$ˆØ %Ð/ˆuŒ}ˆ}¨4Ð/r   õ   âš¡c                 óP   — |                       |¦  «        }|r|j        r|j        n|S )z3Return the emoji for a tool, or *default* if unset.)r|   rS   )rV   r4   rµ   r‚   s       r   Ú	get_emojizToolRegistry.get_emojiW  s+   € à—’˜tÑ$Ô$ˆØ$ÐA¨¬ÐA�”�¸'ÐBr   c                 ó>   — d„ |                       ¦   «         D ¦   «         S )z?Return ``{tool_name: toolset_name}`` for every registered tool.c                 ó(   — i | ]}|j         |j        “ŒS r]   )r4   rL   r�   s     r   r›   z8ToolRegistry.get_tool_to_toolset_map.<locals>.<dictcomp>^  s   € ÐPÐPÐP¨e�”
˜EœMÐPÐPÐPr   )ro   rg   s    r   Úget_tool_to_toolset_mapz$ToolRegistry.get_tool_to_toolset_map\  s"   € àPÐP°t×7MÒ7MÑ7OÔ7OÐPÑPÔPÐPr   c                 ó    — | j         5  | j                             |¦  «        }ddd¦  «         n# 1 swxY w Y   |                      ||¦  «        S )zÒCheck if a toolset's requirements are met.

        Returns False (rather than crashing) when the check function raises
        an unexpected exception (e.g. network error, missing import, bad config).
        N)rf   rb   r{   ry   rx   s      r   Úis_toolset_availablez!ToolRegistry.is_toolset_available`  s�   € ð ŒZð 	6ð 	6ØÔ(×,Ò,¨WÑ5Ô5ˆEð	6ð 	6ð 	6ñ 	6ô 	6ð 	6ð 	6ð 	6ð 	6ð 	6ð 	6øøøð 	6ð 	6ð 	6ð 	6à×+Ò+¨G°UÑ;Ô;Ð;s   ˆ/¯3¶3c                 ó„   ‡ ‡— ‰                       ¦   «         \  }Št          d„ |D ¦   «         ¦  «        }ˆ ˆfd„|D ¦   «         S )z7Return ``{toolset: available_bool}`` for every toolset.c                 ó   — h | ]	}|j         ’Œ
S r]   r€   r�   s     r   rƒ   z:ToolRegistry.check_toolset_requirements.<locals>.<setcomp>m  s   € Ð>Ð>Ð>¨U˜5œ=Ð>Ð>Ð>r   c           	      ód   •— i | ],}|‰                      |‰                     |¦  «        ¦  «        “Œ-S r]   )ry   r{   )r!   rL   rV   Útoolset_checkss     €€r   r›   z;ToolRegistry.check_toolset_requirements.<locals>.<dictcomp>n  sI   ø€ ð 
ð 
ð 
àð �T×1Ò1°'¸>×;MÒ;MÈgÑ;VÔ;VÑWÔWð
ð 
ð 
r   )rl   r;   )rV   ÚentriesÚtoolsetsrÍ   s   `  @r   Úcheck_toolset_requirementsz'ToolRegistry.check_toolset_requirementsj  sf   øø€ à"&×"6Ò"6Ñ"8Ô"8Ñˆ�ÝÐ>Ð>°gÐ>Ñ>Ô>Ñ?Ô?ˆð
ð 
ð 
ð 
ð 
à#ð
ñ 
ô 
ð 	
r   c                 óŠ  — i }|                       ¦   «         \  }}|D ]¦}|j        }||vr1|                      ||                     |¦  «        ¦  «        g dg dœ||<   ||         d                              |j        ¦  «         |j        r;|j        D ]3}|||         d         vr!||         d                              |¦  «         Œ4Œ§|S )z'Return toolset metadata for UI display.r’   )Ú	availableÚtoolsrR   ÚrequirementsrÓ   rÔ   )rl   rL   ry   r{   r?   r4   rP   )rV   rÏ   rÎ   rÍ   r‚   ÚtsÚenvs          r   Úget_available_toolsetsz#ToolRegistry.get_available_toolsetss  sú   € à$&ˆØ"&×"6Ò"6Ñ"8Ô"8Ñˆ�Øð 	Að 	AˆEØ”ˆBØ˜Ð!Ð!à!%×!=Ò!=Ø˜N×.Ò.¨rÑ2Ô2ñ"ô "ð  Ø#%Ø$&ð ð  �˜‘ð �RŒL˜Ô!×(Ò(¨¬Ñ4Ô4Ð4ØÔ!ð AØ Ô-ð Að A�CØ (¨2¤,¨~Ô">Ð>Ð>Ø  œ ^Ô4×;Ò;¸CÑ@Ô@Ð@øøØˆr   c                 ó€  — i }|                       ¦   «         \  }}|D ]¡}|j        }||vr|g |                     |¦  «        dg dœ||<   |j        ||         d         vr&||         d                              |j        ¦  «         |j        D ]3}|||         d         vr!||         d                              |¦  «         Œ4Œ¢|S )zABuild a TOOLSET_REQUIREMENTS-compatible dict for backward compat.N)r4   Úenv_varsrO   Ú	setup_urlrÓ   rÓ   rÙ   )rl   rL   r{   r4   r?   rP   )rV   r§   rÎ   rÍ   r‚   rÕ   rÖ   s          r   Úget_toolset_requirementsz%ToolRegistry.get_toolset_requirements‰  sò   € à"$ˆØ"&×"6Ò"6Ñ"8Ô"8Ñˆ�Øð 	7ð 	7ˆEØ”ˆBØ˜ÐÐàØ "Ø .× 2Ò 2°2Ñ 6Ô 6Ø!%Øðð ��r‘
ð Œz ¨¤¨GÔ!4Ð4Ð4Ø�r”
˜7Ô#×*Ò*¨5¬:Ñ6Ô6Ð6ØÔ)ð 7ð 7�Ø˜f Rœj¨Ô4Ð4Ð4Ø˜2”J˜zÔ*×1Ò1°#Ñ6Ô6Ð6øð7ð ˆr   c                 ó|  ‡— g }g }t          ¦   «         }|                      ¦   «         \  }}|D ]Œ}|j        Š‰|v rŒ|                     ‰¦  «         |                      ‰|                     ‰¦  «        ¦  «        r|                     ‰¦  «         Œb|                     ‰|j        ˆfd„|D ¦   «         dœ¦  «         Œ�||fS )zDReturn (available_toolsets, unavailable_info) like the old function.c                 ó4   •— g | ]}|j         ‰k    ¯|j        ‘ŒS r]   rˆ   )r!   rG   rÕ   s     €r   r7   z8ToolRegistry.check_tool_availability.<locals>.<listcomp>¯  s"   ø€ ÐIÐIÐI¨¸¼Àbº¸˜aœf¸¸¸r   )r4   rÙ   rÓ   )Úsetrl   rL   Úaddry   r{   r?   rP   )	rV   r¡   rÒ   ÚunavailableÚseenrÎ   rÍ   r‚   rÕ   s	           @r   Úcheck_tool_availabilityz$ToolRegistry.check_tool_availabilityž  sî   ø€ àˆ	ØˆÝ‰uŒuˆØ"&×"6Ò"6Ñ"8Ô"8Ñˆ�Øð 	ð 	ˆEØ”ˆBØ�TˆzˆzØØ�HŠH�R‰LŒLˆLØ×+Ò+¨B°×0BÒ0BÀ2Ñ0FÔ0FÑGÔGð Ø× Ò  Ñ$Ô$Ð$Ð$à×"Ò"ØØ %Ô 2ØIÐIÐIÐI¨gÐIÑIÔIð$ð $ñ ô ð ð ð
 ˜+Ð%Ð%r   )NNFr’   r’   N)Fr    )rÂ   )+rX   rY   rZ   r[   rW   Útupler   rJ   r   r&   r   rl   ro   rs   rv   ry   r   r|   r…   r‰   r�   r�   r‘   rk   ri   ÚintÚfloatr   rŸ   r   r«   r´   r¹   r¼   r¿   rÁ   rÄ   rÇ   rÉ   rÐ   r×   rÛ   râ   r]   r   r   r_   r_   d   s�  € € € € € ØSÐSð'ð 'ð 'ðJ  t¨I¤¸¸SÀ(¸]Ô8KÐ'KÔ!Lð Jð Jð Jð Jð
) 4¨	¤?ð )ð )ð )ð )ð)¨$¨s°H¨}Ô*=ð )ð )ð )ð )ð¨sð ¸8Àd¹?ð Ètð ð ð ð ð)˜cð ) h¨yÔ&9ð )ð )ð )ð )ð
M¨d°3¬ið Mð Mð Mð Mð
°#ð 
¸$¸s¼)ð 
ð 
ð 
ð 
ð	3¨Cð 	3¸#ð 	3À$ð 	3ð 	3ð 	3ð 	3ð/°°S¸#°X´ð /ð /ð /ð /ð
4¨cð 4°h¸s´mð 4ð 4ð 4ð 4ð "Ø!ØØØØ48ð39ð 39àð39ð ð39ð ð	39ð
 ð39ð ð39ð ð39ð ð39ð ð39ð ð39ð  # U™{¨TÑ1ð39ð 39ð 39ð 39ðj4˜sð 4 tð 4ð 4ð 4ð 4ð:ð ¨#¨c¬(ð ¸4ð ÈDÐQUÌJð ð ð ð ðD\˜Sð \¨ð \¸3ð \ð \ð \ð \ð.)ð )¨ð )°c¸E±kÀDÑ6Hð )ÐTWÐZ_ÑT_ð )ð )ð )ð )ðH D¨¤Ið Hð Hð Hð Hð/˜sð / x°¤~ð /ð /ð /ð /ð0¨ð 0°¸#´ð 0ð 0ð 0ð 0ð
Cð C˜cð C¨Cð C¸Cð Cð Cð Cð Cð
Q¨¨c°3¨h¬ð Qð Qð Qð Qð<¨Cð <°Dð <ð <ð <ð <ð
¨D°°d°¬Oð 
ð 
ð 
ð 
ð¨¨S°$¨Y¬ð ð ð ð ð,¨$¨s°D¨y¬/ð ð ð ð ð*&ð &¨Tð &ð &ð &ð &ð &ð &r   r_   c                 ó~   — dt          | ¦  «        i}|r|                     |¦  «         t          j        |d¬¦  «        S )zØReturn a JSON error string for tool handlers.

    >>> tool_error("file not found")
    '{"error": "file not found"}'
    >>> tool_error("bad input", success=False)
    '{"error": "bad input", "success": false}'
    r•   F©Úensure_ascii)r&   Úupdater¯   r°   )ÚmessageÚextrar§   s      r   Ú
tool_errorrì   È  sC   € ð •s˜7‘|”|Ð$€FØð Ø�Š�eÑÔÐÝŒ:�f¨5Ð1Ñ1Ô1Ð1r   c                 ó^   — | �t          j        | d¬¦  «        S t          j        |d¬¦  «        S )a  Return a JSON result string for tool handlers.

    Accepts a dict positional arg *or* keyword arguments (not both):

    >>> tool_result(success=True, count=42)
    '{"success": true, "count": 42}'
    >>> tool_result({"key": "value"})
    '{"key": "value"}'
    NFrç   )r¯   r°   )Údatar³   s     r   Útool_resultrï   Ö  s4   € ð ÐÝŒz˜$¨UÐ3Ñ3Ô3Ð3ÝŒ:�f¨5Ð1Ñ1Ô1Ð1r   r    )r[   r   r=   r¯   Úloggingrd   Úpathlibr   Útypingr   r   r   r   r   Ú	getLoggerrX   rA   ÚASTrv   r   r-   r&   rH   rJ   r_   r   rì   rï   r]   r   r   ú<module>rõ      s¸  ððð ð  €
€
€
Ø Ð Ð Ð Ø €€€Ø €€€Ø Ð Ð Ð Ø Ð Ð Ð Ð Ð Ø 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6à	ˆÔ	˜8Ñ	$Ô	$€ð
 S¤Wð 
°ð 
ð 
ð 
ð 
ðG¨ð G°$ð Gð Gð Gð Gðð  h¨t¤nð ÀÀSÄ	ð ð ð ð ð(;ð ;ð ;ð ;ð ;ñ ;ô ;ð ;ð0M&ð M&ð M&ð M&ð M&ñ M&ô M&ð M&ðb
 ˆ<‰>Œ>€ð&2 Cð 2ð 2ð 2ð 2ð2ð 2¨ð 2ð 2ð 2ð 2ð 2ð 2r   