§
    ‰eîiÏr  ã                  óž  — U d Z ddlmZ ddlZddlZddlZddlZddlZddlZddl	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 ddlmZmZ ddlmZ ddlmZmZmZmZmZmZmZmZ 	 ddl Z n# e!$ r dZ Y nw xY wdd	l"m#Z#  ej$        e%¦  «        Z&d
Z'dZ(dZ) e*¦   «         Z+de,d<    ej-        ¦   «         Z. ej-        ¦   «         Z/e G d„ d¦  «        ¦   «         Z0ddœdJd„Z1dKd„Z2dLd„Z3dMd„Z4dNd&„Z5h d'£Z6dOd+„Z7dPd-„Z8dQd/„Z9dRd1„Z:dSd3„Z;dTd4„Z<dUd6„Z=dVd8„Z>edWd:„¦   «         Z?dXd;„Z@dYd<„ZAdZd=„ZBd[d>„ZCd?ZDd@e,dA<   d\dB„ZEd]dD„ZFd^dE„ZGd_dG„ZHd`dH„ZIdadI„ZJdS )bu#  
Shell-script hooks bridge.

Reads the ``hooks:`` block from ``cli-config.yaml``, prompts the user for
consent on first use of each ``(event, command)`` pair, and registers
callbacks on the existing plugin hook manager so every existing
``invoke_hook()`` site dispatches to the configured shell scripts â€” with
zero changes to call sites.

Design notes
------------
* Python plugins and shell hooks compose naturally: both flow through
  :func:`hermes_cli.plugins.invoke_hook` and its aggregators.  Python
  plugins are registered first (via ``discover_and_load()``) so their
  block decisions win ties over shell-hook blocks.
* Subprocess execution uses ``shlex.split(os.path.expanduser(command))``
  with ``shell=False`` â€” no shell injection footguns.  Users that need
  pipes/redirection wrap their logic in a script.
* First-use consent is gated by the allowlist under
  ``~/.hermes/shell-hooks-allowlist.json``.  Non-TTY callers must pass
  ``accept_hooks=True`` (resolved from ``--accept-hooks``,
  ``HERMES_ACCEPT_HOOKS``, or ``hooks_auto_accept: true`` in config)
  for registration to succeed without a prompt.
* Registration is idempotent â€” safe to invoke from both the CLI entry
  point (``hermes_cli/main.py``) and the gateway entry point
  (``gateway/run.py``).

Wire protocol
-------------
**stdin** (JSON, piped to the script)::

    {
        "hook_event_name": "pre_tool_call",
        "tool_name":       "terminal",
        "tool_input":      {"command": "rm -rf /"},
        "session_id":      "sess_abc123",
        "cwd":             "/home/user/project",
        "extra":           {...}   # event-specific kwargs
    }

**stdout** (JSON, optional â€” anything else is ignored)::

    # Block a pre_tool_call (either shape accepted; normalised internally):
    {"decision": "block", "reason":  "Forbidden command"}   # Claude-Code-style
    {"action":   "block", "message": "Forbidden command"}   # Hermes-canonical

    # Inject context for pre_llm_call:
    {"context": "Today is Friday"}

    # Silent no-op:
    <empty or any non-matching JSON object>
é    )ÚannotationsN)Úcontextmanager)Ú	dataclassÚfield)ÚdatetimeÚtimezone)ÚPath)ÚAnyÚCallableÚDictÚIteratorÚListÚOptionalÚSetÚTuple)Úget_hermes_homeé<   i,  zshell-hooks-allowlist.jsonz#Set[Tuple[str, Optional[str], str]]Ú_registeredc                  óx   — e Zd ZU dZded<   ded<   dZded<   eZded	<    edd
¬¦  «        Z	ded<   dd„Z
dd„ZdS )ÚShellHookSpeczAParsed and validated representation of a single ``hooks:`` entry.ÚstrÚeventÚcommandNúOptional[str]ÚmatcherÚintÚtimeoutF)ÚdefaultÚreprzOptional[re.Pattern]Úcompiled_matcherÚreturnÚNonec                ó\  — t          | j        t          ¦  «        r$| j                             ¦   «         }|r|nd | _        | j        rf	 t	          j        | j        ¦  «        | _        d S # t          j        $ r3}t           	                    d| j        |¦  «         d | _        Y d }~d S d }~ww xY wd S )NuF   shell hook matcher %r is invalid (%s) â€” treating as literal equality)
Ú
isinstancer   r   ÚstripÚreÚcompiler    ÚerrorÚloggerÚwarning)ÚselfÚstrippedÚexcs      ú3/home/div/.hermes/hermes-agent/agent/shell_hooks.pyÚ__post_init__zShellHookSpec.__post_init__r   sÍ   € õ �d”l¥CÑ(Ô(ð 	:Ø”|×)Ò)Ñ+Ô+ˆHØ'/Ð9˜8˜8°TˆDŒLØŒ<ð 	-ð-Ý(*¬
°4´<Ñ(@Ô(@�Ô%Ð%Ð%øÝ”8ð -ð -ð -Ý—’ð'Ø(,¬°cñô ð ð )-�Ô%Ð%Ð%Ð%Ð%Ð%Ð%øøøøð-øøøð	-ð 	-s   ÁA' Á'B)Á6(B$Â$B)Ú	tool_nameÚboolc                óx   — | j         sdS |€dS | j        �| j                             |¦  «        d uS || j         k    S )NTF)r   r    Ú	fullmatch)r+   r0   s     r.   Úmatches_toolzShellHookSpec.matches_toolƒ   sP   € ØŒ|ð 	Ø�4ØÐØ�5ØÔ Ð,ØÔ(×2Ò2°9Ñ=Ô=ÀTÐIÐIð ˜DœLÒ(Ð(ó    ©r!   r"   )r0   r   r!   r1   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ú__annotations__r   ÚDEFAULT_TIMEOUT_SECONDSr   r   r    r/   r4   © r5   r.   r   r   h   s™   € € € € € € àKÐKà€J€J�JØ€L€L�LØ!€GÐ!Ð!Ð!Ñ!Ø*€GÐ*Ð*Ð*Ñ*Ø-2¨U¸4ÀeÐ-LÑ-LÔ-LÐÐLÐLÐLÑLð-ð -ð -ð -ð"	)ð 	)ð 	)ð 	)ð 	)ð 	)r5   r   F©Úaccept_hooksÚcfgúOptional[Dict[str, Any]]r?   r1   r!   úList[ShellHookSpec]c          	     óÎ  — t          | t          ¦  «        sg S t          | |¦  «        }t          |                      d¦  «        ¦  «        }|sg S g }ddlm}  |¦   «         }|D �]�}|j        |j        |j	        f}t          5  |t          v r	 ddd¦  «         Œ5t          |j        |j	        ¦  «        }	ddd¦  «         n# 1 swxY w Y   |	sCt          |j        |j	        |¬¦  «        s't                               d|j        |j	        ¦  «         Œ«t          5  |t          v r	 ddd¦  «         ŒÉ|j                             |j        g ¦  «                             t'          |¦  «        ¦  «         t                               |¦  «         |                     |¦  «         t                               d|j        |j	        |j        |j        ¦  «         ddd¦  «         n# 1 swxY w Y   �Œƒ|S )u*  Register every configured shell hook on the plugin manager.

    ``cfg`` is the full parsed config dict (``hermes_cli.config.load_config``
    output).  The ``hooks:`` key is read out of it.  Missing, empty, or
    non-dict ``hooks`` is treated as zero configured hooks.

    ``accept_hooks=True`` skips the TTY consent prompt â€” the caller is
    promising that the user has opted in via a flag, env var, or config
    setting.  ``HERMES_ACCEPT_HOOKS=1`` and ``hooks_auto_accept: true`` are
    also honored inside this function so either CLI or gateway call sites
    pick them up.

    Returns the list of :class:`ShellHookSpec` entries that ended up wired
    up on the plugin manager.  Skipped entries (unknown events, malformed,
    not allowlisted, already registered) are logged but not returned.
    Úhooksr   )Úget_plugin_managerNr>   u    shell hook for %s (%s) not allowlisted â€” skipped. Use --accept-hooks / HERMES_ACCEPT_HOOKS=1 / hooks_auto_accept: true, or approve at the TTY prompt next run.z9shell hook registered: %s -> %s (matcher=%s, timeout=%ds))r$   ÚdictÚ_resolve_effective_acceptÚ_parse_hooks_blockÚgetÚhermes_cli.pluginsrE   r   r   r   Ú_registered_lockr   Ú_is_allowlistedÚ_prompt_and_recordr)   r*   Ú_hooksÚ
setdefaultÚappendÚ_make_callbackÚaddÚinfor   )
r@   r?   Úeffective_acceptÚspecsÚ
registeredrE   ÚmanagerÚspecÚkeyÚalready_allowlisteds
             r.   Úregister_from_configr[   “   sÆ  € õ* �c�4Ñ Ô ð Øˆ	å0°°lÑCÔCÐå˜sŸwšw wÑ/Ô/Ñ0Ô0€EØð Øˆ	à&(€Jð 6Ð5Ð5Ð5Ð5Ð5à Ð Ñ"Ô"€Gð ð ñ ˆØŒz˜4œ<¨¬Ð6ˆÝð 	Lð 	LØ•kÐ!Ð!Øð	Lð 	Lð 	Lñ 	Lô 	Lð 	Lð 	Lõ #2°$´*¸d¼lÑ"KÔ"KÐð	Lð 	Lð 	Lñ 	Lô 	Lð 	Lð 	Lð 	Lð 	Lð 	Lð 	Løøøð 	Lð 	Lð 	Lð 	Lð
 #ð 	Ý%Ø”
˜DœLÐ7Gðñ ô ð 
õ —’ð'ð ”J ¤ñô ð ð åð 		ð 		Ø•kÐ!Ð!Øð		ð 		ð 		ñ 		ô 		ð 		ð 		ð ŒN×%Ò% d¤j°"Ñ5Ô5×<Ò<½^ÈDÑ=QÔ=QÑRÔRÐRÝ�OŠO˜CÑ Ô Ð Ø×Ò˜dÑ#Ô#Ð#Ý�KŠKØKØ”
˜DœL¨$¬,¸¼ñô ð ð		ð 		ð 		ñ 		ô 		ð 		ð 		ð 		ð 		ð 		ð 		øøøð 		ð 		ð 		ð 		ùð Ðs1   Â B=ÂB=Â=C	ÃC	ÄGÄ+B!GÇG	ÇG	c                ót   — t          | t          ¦  «        sg S t          |                      d¦  «        ¦  «        S )zˆReturn the parsed ``ShellHookSpec`` entries from config without
    registering anything.  Used by ``hermes hooks list`` and ``doctor``.rD   )r$   rF   rH   rI   )r@   s    r.   Úiter_configured_hooksr]   Þ   s5   € õ �c�4Ñ Ô ð Øˆ	Ý˜cŸgšg gÑ.Ô.Ñ/Ô/Ð/r5   r"   c                 óx   — t           5  t                               ¦   «          ddd¦  «         dS # 1 swxY w Y   dS )z-Clear the idempotence set.  Test-only helper.N)rK   r   Úclearr=   r5   r.   Úreset_for_testsr`   æ   s~   € å	ð ð Ý×ÒÑÔÐðð ð ñ ô ð ð ð ð ð ð ð øøøð ð ð ð ð ð s   ˆ/¯3¶3Ú	hooks_cfgr
   c           
     óš  — ddl m} t          | t          ¦  «        sg S g }|                      ¦   «         D �]\  }}||vr‡t          j        t          |¦  «        |dd¬¦  «        }|r#t           	                    d||d         ¦  «         n<t           	                    d|d 
                    t          |¦  «        ¦  «        ¦  «         Œ‘|€Œ”t          |t          ¦  «        s/t           	                    d
|t          |¦  «        j        ¦  «         ŒØt          |¦  «        D ]-\  }}t!          |||¦  «        }|�|                     |¦  «         Œ.�Œ|S )uÉ   Normalise the ``hooks:`` dict into a flat list of ``ShellHookSpec``.

    Malformed entries warn-and-skip â€” we never raise from config parsing
    because a broken hook must not crash the agent.
    r   )ÚVALID_HOOKSé   g333333ã?)ÚnÚcutoffu;   unknown hook event %r in hooks: config â€” did you mean %r?z2unknown hook event %r in hooks: config (valid: %s)z, Nz3hooks.%s must be a list of hook definitions; got %s)rJ   rc   r$   rF   ÚitemsÚdifflibÚget_close_matchesr   r)   r*   ÚjoinÚsortedÚlistÚtyper7   Ú	enumerateÚ_parse_single_entryrP   )	ra   rc   rU   Ú
event_nameÚentriesÚ
suggestionÚiÚrawrX   s	            r.   rH   rH   ð   s‚  € ð /Ð.Ð.Ð.Ð.Ð.å�i¥Ñ&Ô&ð Øˆ	à!#€Eà(ŸšÑ0Ô0ð #ñ #Ñˆ
�GØ˜[Ð(Ð(Ý Ô2Ý�J‘” °¸#ðñ ô ˆJð ð 	Ý—’ØQØ 
¨1¤ñô ð ð õ
 —’ØHØ §	¢	­&°Ñ*=Ô*=Ñ >Ô >ñô ð ð àˆ?Øå˜'¥4Ñ(Ô(ð 	Ý�NŠNØEØ�D ™MœMÔ2ñô ð ð å Ñ(Ô(ð 	#ð 	#‰FˆAˆsÝ& z°1°cÑ:Ô:ˆDØÐØ—’˜TÑ"Ô"Ð"øñ	#ð
 €Lr5   r   r   Úindexr   rt   úOptional[ShellHookSpec]c                ó  — t          |t          ¦  «        s1t                               d| |t	          |¦  «        j        ¦  «         d S |                     d¦  «        }t          |t          ¦  «        r|                     ¦   «         st                               d| |¦  «         d S |                     d¦  «        }|�3t          |t          ¦  «        st                               d| |¦  «         d }|�$| dvr t                               d| ||| ¦  «         d }|                     dt          ¦  «        }	 t          |¦  «        }nA# t          t          f$ r- t                               d	| ||t          ¦  «         t          }Y nw xY w|d
k     r)t                               d| |t          ¦  «         t          }|t          k    r*t                               d| ||t          ¦  «         t          }t          | |                     ¦   «         ||¬¦  «        S )Nz;hooks.%s[%d] must be a mapping with a 'command' key; got %sr   z3hooks.%s[%d] is missing a non-empty 'command' fieldr   z5hooks.%s[%d].matcher must be a string regex; ignoring©Úpre_tool_callÚpost_tool_callu£   hooks.%s[%d].matcher=%r will be ignored at runtime â€” the matcher field is only honored for pre_tool_call / post_tool_call.  The hook will fire on every %s event.r   z?hooks.%s[%d].timeout must be an int (got %r); using default %dsrd   z3hooks.%s[%d].timeout must be >=1; using default %dsz2hooks.%s[%d].timeout=%ds exceeds max %ds; clamping)r   r   r   r   )r$   rF   r)   r*   rm   r7   rI   r   r%   r<   r   Ú	TypeErrorÚ
ValueErrorÚMAX_TIMEOUT_SECONDSr   )r   ru   rt   r   r   Útimeout_rawr   s          r.   ro   ro      s1  € õ �c�4Ñ Ô ð Ý�ŠØIØ�5�$˜s™)œ)Ô,ñ	
ô 	
ð 	
ð ˆtà�gŠg�iÑ Ô €GÝ�g�sÑ#Ô#ð ¨7¯=ª=©?¬?ð Ý�ŠØAØ�5ñ	
ô 	
ð 	
ð ˆtà�gŠg�iÑ Ô €GØÐ¥:¨gµsÑ#;Ô#;ÐÝ�ŠØCØ�5ñ	
ô 	
ð 	
ð ˆàÐ˜uÐ,OÐOÐOÝ�ŠðEð �5˜' 5ñ		
ô 	
ð 	
ð ˆà—'’'˜)Õ%<Ñ=Ô=€Kð*Ý�kÑ"Ô"ˆˆøÝ•zÐ"ð *ð *ð *Ý�ŠØMØ�5˜+Õ'>ñ	
ô 	
ð 	
õ *ˆˆˆð*øøøð �‚{€{Ý�ŠØAØ�5Õ1ñ	
ô 	
ð 	
õ *ˆàÕ$Ò$Ð$Ý�ŠØ@Ø�5˜'Õ#6ñ	
ô 	
ð 	
õ &ˆåØØ—’‘”ØØð	ñ ô ð s   Ä/D? Ä?;E=Å<E=>   Úargsr0   Ú
session_idÚparent_session_idrX   Ú
stdin_jsonúDict[str, Any]c                ó   — dddddddœ}	 t          j        t          j                             | j        ¦  «        ¦  «        }n)# t          $ r}d| j        ›d|› �|d<   |cY d}~S d}~ww xY w|sd	|d<   |S t          j        ¦   «         }	 t          j
        ||d
| j        d
d¬¦  «        }n�# t          j        $ r1 d
|d<   t          t          j        ¦   «         |z
  d¦  «        |d<   |cY S t          $ r
 d|d<   |cY S t          $ r
 d|d<   |cY S t           $ r}t#          |¦  «        |d<   |cY d}~S d}~ww xY w|j        |d<   |j        pd|d<   |j        pd|d<   t          t          j        ¦   «         |z
  d¦  «        |d<   |S )u¨  Run ``spec.command`` as a subprocess with ``stdin_json`` on stdin.

    Returns a diagnostic dict with the same keys for every outcome
    (``returncode``, ``stdout``, ``stderr``, ``timed_out``,
    ``elapsed_seconds``, ``error``).  This is the single place the
    subprocess is actually invoked â€” both the live callback path
    (:func:`_make_callback`) and the CLI test helper (:func:`run_once`)
    go through it.
    NÚ Fg        )Ú
returncodeÚstdoutÚstderrÚ	timed_outÚelapsed_secondsr(   zcommand z cannot be parsed: r(   zempty commandT)ÚinputÚcapture_outputr   ÚtextÚshellr‰   é   rŠ   zcommand not foundzcommand not executabler†   r‡   rˆ   )ÚshlexÚsplitÚosÚpathÚ
expanduserr   r|   ÚtimeÚ	monotonicÚ
subprocessÚrunr   ÚTimeoutExpiredÚroundÚFileNotFoundErrorÚPermissionErrorÚ	Exceptionr   r†   r‡   rˆ   )rX   r‚   ÚresultÚargvr-   Út0Úprocs          r.   Ú_spawnr¢   j  s  € ð ØØØØØðð €FðÝŒ{�2œ7×-Ò-¨d¬lÑ;Ô;Ñ<Ô<ˆˆøÝð ð ð ØM T¤\ÐMÐMÈÐMÐMˆˆw‰Øˆˆˆˆˆˆøøøøðøøøð ð Ø)ˆˆw‰Øˆå	ŒÑ	Ô	€BðÝŒ~ØØØØ”LØØð
ñ 
ô 
ˆˆøõ Ô$ð ð ð Ø"ˆˆ{ÑÝ$)­$¬.Ñ*:Ô*:¸RÑ*?ÀÑ$CÔ$CˆÐ Ñ!ØˆˆˆÝð ð ð Ø-ˆˆw‰ØˆˆˆÝð ð ð Ø2ˆˆw‰ØˆˆˆÝð ð ð Ý˜c™(œ(ˆˆw‰Øˆˆˆˆˆˆøøøøðøøøð  œ?€Fˆ<ÑØ”{Ð( b€Fˆ8ÑØ”{Ð( b€Fˆ8ÑÝ %¥d¤nÑ&6Ô&6¸Ñ&;¸QÑ ?Ô ?€FÐÑØ€MsM   ‹6A Á
A(ÁA#ÁA(Á#A(ÂB( Â(=D2Ã'D2Ã9D2Ä	D2ÄD-Ä'D2Ä-D2ú'Callable[..., Optional[Dict[str, Any]]]c                ó\   ‡ — d	ˆ fd„}d‰ j         › d‰ j        › d�|_        |j        |_        |S )
z>Build the closure that ``invoke_hook()`` will call per firing.Úkwargsr
   r!   rA   c            	     óÜ  •— ‰j         dv r*‰                     |                      d¦  «        ¦  «        sd S t          ‰t	          ‰j         | ¦  «        ¦  «        }|d         r/t
                               d‰j         ‰j        |d         ¦  «         d S |d         r/t
                               d|d         ‰j         ‰j        ¦  «         d S |d                              ¦   «         }|r/t
           	                    d	‰j         ‰j        |d d
…         ¦  «         |d         dk    r6t
                               d|d         ‰j         ‰j        |d d
…         ¦  «         t          ‰j         |d         ¦  «        S )Nrx   r0   r(   z+shell hook failed (event=%s command=%s): %sr‰   z6shell hook timed out after %.2fs (event=%s command=%s)rŠ   rˆ   z+shell hook stderr (event=%s command=%s): %si�  r†   r   z5shell hook exited %d (event=%s command=%s); stderr=%sr‡   )r   r4   rI   r¢   Ú_serialize_payloadr)   r*   r   r%   ÚdebugÚ_parse_response)r¥   Úrrˆ   rX   s      €r.   Ú	_callbackz!_make_callback.<locals>._callback§  sp  ø€ àŒ:Ð<Ð<Ð<Ø×$Ò$ V§Z¢Z°Ñ%<Ô%<Ñ=Ô=ð Ø�tå�4Õ+¨D¬J¸Ñ?Ô?Ñ@Ô@ˆàˆWŒ:ð 	Ý�NŠNØ=Ø”
˜DœL¨!¨G¬*ñô ð ð �4Øˆ[Œ>ð 	Ý�NŠNØHØÐ#Ô$ d¤j°$´,ñô ð ð �4à�8”×"Ò"Ñ$Ô$ˆØð 	Ý�LŠLØ=Ø”
˜DœL¨&°°#°¬,ñô ð ð ˆ\Œ?˜aÒÐÝ�NŠNØGØ�,” ¤¨T¬\¸6À$À3À$¼<ñô ð õ ˜tœz¨1¨X¬;Ñ7Ô7Ð7r5   zshell_hook[ú:ú])r¥   r
   r!   rA   )r   r   r7   r9   )rX   r«   s   ` r.   rQ   rQ   ¤  sU   ø€ ð"8ð "8ð "8ð "8ð "8ð "8ðH D t¤zÐCÐC°D´LÐCÐCÐC€IÔØ&Ô/€IÔØÐr5   r¥   c                óä  — d„ |                      ¦   «         D ¦   «         }	 t          t          j        ¦   «         ¦  «        }n# t          $ r d}Y nw xY w| |                     d¦  «        t          |                     d¦  «        t          ¦  «        r|                     d¦  «        nd|                     d¦  «        p|                     d¦  «        pd||dœ}t          j	        |d	t          ¬
¦  «        S )zrRender the stdin JSON payload.  Unserialisable values are
    stringified via ``default=str`` rather than dropped.c                ó,   — i | ]\  }}|t           v¯||“ŒS r=   )Ú_TOP_LEVEL_PAYLOAD_KEYS)Ú.0ÚkÚvs      r.   ú
<dictcomp>z&_serialize_payload.<locals>.<dictcomp>Ó  s)   € ÐRÐRÐR‘t�q˜!°Õ:QÐ1QÐ1Qˆa�Ð1QÐ1QÐ1Qr5   r…   r0   r   Nr€   r�   )Úhook_event_namer0   Ú
tool_inputr€   ÚcwdÚextraF)Úensure_asciir   )
rg   r   r	   r·   ÚOSErrorrI   r$   rF   ÚjsonÚdumps)r   r¥   Úextrasr·   Úpayloads        r.   r§   r§   Ð  sò   € ð SÐR˜vŸ|š|™~œ~ÐRÑRÔR€FðÝ•$”(‘*”*‰oŒoˆˆøÝð ð ð Øˆˆˆðøøøð !Ø—Z’Z Ñ,Ô,Ý,6°v·z²zÀ&Ñ7IÔ7IÍ4Ñ,PÔ,PÐZ�f—j’j Ñ(Ô(Ð(ÐVZØ—j’j Ñ.Ô.ÐW°&·*²*Ð=PÑ2QÔ2QÐWÐUWØØðð €Gõ Œ:�g¨E½3Ð?Ñ?Ô?Ð?s     A ÁAÁAr‡   c                ó   — |pd                      ¦   «         }|sdS 	 t          j        |¦  «        }n:# t          j        $ r( t                               d| |dd…         ¦  «         Y dS w xY wt          |t          ¦  «        sdS | dk    rÄ|                     d¦  «        dk    rH|                     d¦  «        p|                     d	¦  «        pd}t          |t          ¦  «        r|rd|d
œS |                     d¦  «        dk    rH|                     d	¦  «        p|                     d¦  «        pd}t          |t          ¦  «        r|rd|d
œS dS |                     d¦  «        }t          |t          ¦  «        r|                      ¦   «         rd|iS dS )u–  Translate stdout JSON into a Hermes wire-shape dict.

    For ``pre_tool_call`` the Claude-Code-style ``{"decision": "block",
    "reason": "..."}`` payload is translated into the canonical Hermes
    ``{"action": "block", "message": "..."}`` shape expected by
    :func:`hermes_cli.plugins.get_pre_tool_call_block_message`.  This is
    the single most important correctness invariant in this module â€”
    skipping the translation silently breaks every ``pre_tool_call``
    block directive.

    For ``pre_llm_call``, ``{"context": "..."}`` is passed through
    unchanged to match the existing plugin-hook contract.

    Anything else returns ``None``.
    r…   Nz3shell hook stdout was not valid JSON (event=%s): %séÈ   ry   ÚactionÚblockÚmessageÚreason)rÁ   rÃ   ÚdecisionÚcontext)
r%   r»   ÚloadsÚJSONDecodeErrorr)   r*   r$   rF   rI   r   )r   r‡   ÚdatarÃ   rÆ   s        r.   r©   r©   ã  s¾  € ð  ˆl˜×!Ò!Ñ#Ô#€FØð ØˆtðÝŒz˜&Ñ!Ô!ˆˆøÝÔð ð ð Ý�ŠØAØ�6˜$˜3˜$”<ñ	
ô 	
ð 	
ð ˆtˆtðøøøõ �d�DÑ!Ô!ð Øˆtà�ÒÐØ�8Š8�HÑÔ Ò(Ð(Ø—h’h˜yÑ)Ô)ÐE¨T¯XªX°hÑ-?Ô-?ÐEÀ2ˆGÝ˜'¥3Ñ'Ô'ð ?¨Gð ?Ø")°gÐ>Ð>Ð>Ø�8Š8�JÑÔ 7Ò*Ð*Ø—h’h˜xÑ(Ô(ÐE¨D¯HªH°YÑ,?Ô,?ÐEÀ2ˆGÝ˜'¥3Ñ'Ô'ð ?¨Gð ?Ø")°gÐ>Ð>Ð>Øˆtà�hŠh�yÑ!Ô!€GÝ�'�3ÑÔð $ G§M¢M¡O¤Oð $Ø˜7Ð#Ð#àˆ4s   œ1 ±3A(Á'A(r	   c                 ó.   — t          ¦   «         t          z  S )z/Path to the per-user shell-hook allowlist file.)r   ÚALLOWLIST_FILENAMEr=   r5   r.   Úallowlist_pathrÌ     s   € åÑÔÕ1Ñ1Ð1r5   c                 óJ  — 	 t          j        t          ¦   «                              ¦   «         ¦  «        } n&# t          t           j        t          f$ r dg icY S w xY wt          | t          ¦  «        sdg iS |  	                    d¦  «        }t          |t          ¦  «        sg | d<   | S )z<Return the parsed allowlist, or an empty skeleton if absent.Ú	approvals)r»   rÇ   rÌ   Ú	read_textr›   rÈ   rº   r$   rF   rI   rl   )rt   rÎ   s     r.   Úload_allowlistrÐ     s¯   € ð!ÝŒj�Ñ)Ô)×3Ò3Ñ5Ô5Ñ6Ô6ˆˆøÝ�tÔ3µWÐ=ð !ð !ð !Ø˜RÐ Ð Ð Ð ð!øøøå�c�4Ñ Ô ð !Ø˜RÐ Ð Ø—’˜Ñ$Ô$€IÝ�i¥Ñ&Ô&ð ØˆˆKÑØ€Js   ‚25 µ AÁArÉ   c                óp  — t          ¦   «         }	 |j                             dd¬¦  «         t          j        |j        › d�dt          |j        ¦  «        ¬¦  «        \  }}	 t          j        |d¦  «        5 }| 	                    t          j        | dd¬¦  «        ¦  «         d	d	d	¦  «         n# 1 swxY w Y   t          j        ||¦  «         d	S # t          $ r( 	 t          j        |¦  «         n# t          $ r Y nw xY w‚ w xY w# t          $ r'}t                                d
||¦  «         Y d	}~d	S d	}~ww xY w)a;  Atomically persist the allowlist via per-process ``mkstemp`` +
    ``os.replace``.  Cross-process read-modify-write races are handled
    by :func:`_locked_update_approvals` (``fcntl.flock``).  On OSError
    the failure is logged; the in-process hook still registers but
    the approval won't survive across runs.T©ÚparentsÚexist_okú.z.tmp)ÚprefixÚsuffixÚdirÚwé   )ÚindentÚ	sort_keysNzÒFailed to persist shell hook allowlist to %s: %s. The approval is in-memory for this run, but the next startup will re-prompt (or skip registration on non-TTY runs without --accept-hooks / HERMES_ACCEPT_HOOKS).)rÌ   ÚparentÚmkdirÚtempfileÚmkstempÚnamer   r’   ÚfdopenÚwriter»   r¼   Úreplacer�   Úunlinkrº   r)   r*   )rÉ   ÚpÚfdÚtmp_pathÚfhr-   s         r.   Úsave_allowlistrê   ,  sÊ  € õ 	ÑÔ€Að
Ø	Œ�Š˜t¨dˆÑ3Ô3Ð3ÝÔ'Ø”f�<�<�<¨µC¸¼±M´Mð
ñ 
ô 
‰ˆˆHð		Ý”˜2˜sÑ#Ô#ð E rØ—’�œ D°¸dÐCÑCÔCÑDÔDÐDðEð Eð Eñ Eô Eð Eð Eð Eð Eð Eð Eøøøð Eð Eð Eð EåŒJ�x Ñ#Ô#Ð#Ð#Ð#øÝð 	ð 	ð 	ðÝ”	˜(Ñ#Ô#Ð#Ð#øÝð ð ð Ø�ðøøøàð	øøøøõ ð 
ð 
ð 
Ý�ŠðBð ˆsñ	
ô 	
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
øøøøð
øøøsr   �AD Á!C Á6+B-Â!C Â-B1Â1C Â4B1Â5C Ã
DÃC/Ã.DÃ/
C<Ã9DÃ;C<Ã<DÄD Ä
D5ÄD0Ä0D5r   c                ó‚   ‡ ‡— t          ¦   «         }t          ˆˆ fd„|                     dg ¦  «        D ¦   «         ¦  «        S )Nc              3  ó¦   •K  — | ]K}t          |t          ¦  «        o1|                     d ¦  «        ‰k    o|                     d¦  «        ‰k    V — ŒLdS )r   r   N©r$   rF   rI   ©r±   Úer   r   s     €€r.   ú	<genexpr>z"_is_allowlisted.<locals>.<genexpr>N  ss   øè è € ð ð ð õ 	�1•dÑÔð 	(Ø�EŠE�'‰NŒN˜eÒ#ð	(à�EŠE�)ÑÔ Ò'ðð ð ð ð ð r5   rÎ   )rÐ   ÚanyrI   )r   r   rÉ   s   `` r.   rL   rL   L  s\   øø€ ÝÑÔ€DÝð ð ð ð ð ð —’˜+ rÑ*Ô*ð	ñ ô ñ ô ð r5   úIterator[Dict[str, Any]]c               #  óô  K  — t          ¦   «         } | j                             dd¬¦  «         |                      | j        dz   ¦  «        }t
          €Bt          5  t          ¦   «         }|V — t          |¦  «         ddd¦  «         n# 1 swxY w Y   dS t          |d¦  «        5 }t          j
        |                     ¦   «         t
          j        ¦  «         	 t          ¦   «         }|V — t          |¦  «         t          j
        |                     ¦   «         t
          j        ¦  «         n6# t          j
        |                     ¦   «         t
          j        ¦  «         w xY w	 ddd¦  «         dS # 1 swxY w Y   dS )u†  Serialise read-modify-write on the allowlist across processes.

    Holds an exclusive ``flock`` on a sibling lock file for the duration
    of the update so concurrent ``_record_approval``/``revoke`` callers
    cannot clobber each other's changes (the race Codex reproduced with
    20â€“50 simultaneous writers).  Falls back to an in-process lock on
    platforms without ``fcntl``.
    TrÒ   z.lockNza+)rÌ   rÝ   rÞ   Úwith_suffixr×   ÚfcntlÚ_allowlist_write_lockrÐ   rê   ÚopenÚflockÚfilenoÚLOCK_EXÚLOCK_UN)ræ   Ú	lock_pathrÉ   Úlock_fhs       r.   Ú_locked_update_approvalsrþ   V  sÊ  è è € õ 	ÑÔ€AØ„H‡N‚N˜4¨$€NÑ/Ô/Ð/Ø—’˜aœh¨Ñ0Ñ1Ô1€Iå€}Ý"ð 	!ð 	!Ý!Ñ#Ô#ˆDØˆJˆJˆJÝ˜4Ñ Ô Ð ð	!ð 	!ð 	!ñ 	!ô 	!ð 	!ð 	!ð 	!ð 	!ð 	!ð 	!øøøð 	!ð 	!ð 	!ð 	!ð 	ˆå	ˆi˜Ñ	Ô	ð 9 'ÝŒ�G—N’NÑ$Ô$¥e¤mÑ4Ô4Ð4ð	9Ý!Ñ#Ô#ˆDØˆJˆJˆJÝ˜4Ñ Ô Ð åŒK˜ŸšÑ(Ô(­%¬-Ñ8Ô8Ð8Ð8ø�EŒK˜ŸšÑ(Ô(­%¬-Ñ8Ô8Ð8Ð8øøøÐ8ð9ð 9ð 9ñ 9ô 9ð 9ð 9ð 9ð 9ð 9ð 9ð 9øøøð 9ð 9ð 9ð 9ð 9ð 9s<   Á"BÂB
ÂB
Â#2E-Ã!D)Ã72E-Ä)3EÅE-Å-E1Å4E1c               ó´  — |r.t          | |¦  «         t                               d| |¦  «         dS t          j                             ¦   «         sdS t          d| › d|› d�¦  «         	 t          d¦  «                             ¦   «          	                    ¦   «         }n&# t          t          f$ r t          ¦   «          Y dS w xY w|dv rt          | |¦  «         dS dS )	zƒDecide whether to approve an unseen ``(event, command)`` pair.
    Returns ``True`` iff the approval was granted and recorded.
    zDshell hook auto-approved via --accept-hooks / env / config: %s -> %sTFuf   
âš  Hermes is about to register a shell hook that will run a
  command on your behalf.

    Event:   z
    Command: zU

  Commands run with your full user credentials.  Only approve
  commands you trust.zAllow this hook to run? [y/N]: )ÚyÚyes)Ú_record_approvalr)   rS   ÚsysÚstdinÚisattyÚprintr‹   r%   ÚlowerÚEOFErrorÚKeyboardInterrupt)r   r   r?   Úanswers       r.   rM   rM   u  s  € ð ð Ý˜ Ñ(Ô(Ð(Ý�ŠðØ˜wñ	
ô 	
ð 	
ð ˆtåŒ9×ÒÑÔð Øˆuå	ð	!àð	!ð 	!ð  ð	!ð 	!ð 	!ñô ð ðÝÐ8Ñ9Ô9×?Ò?ÑAÔA×GÒGÑIÔIˆˆøÝÕ'Ð(ð ð ð Ý‰ŒˆØˆuˆuðøøøð �ÐÐÝ˜ Ñ(Ô(Ð(Øˆtàˆ5s   Á(3B ÂB?Â>B?c                óì   ‡ ‡— ‰ ‰t          ¦   «         t          ‰¦  «        dœ}t          ¦   «         5 }ˆˆ fd„|                     dg ¦  «        D ¦   «         |gz   |d<   d d d ¦  «         d S # 1 swxY w Y   d S )N)r   r   Úapproved_atÚscript_mtime_at_approvalc                ó¢   •— g | ]K}t          |t          ¦  «        r2|                     d ¦  «        ‰k    r|                     d¦  «        ‰k    °I|‘ŒLS )r   r   rí   rî   s     €€r.   ú
<listcomp>z$_record_approval.<locals>.<listcomp>£  se   ø€ ð 
ð 
ð 
Øå˜1�dÑ#Ô#ð
ð —E’E˜'‘N”N eÒ+Ð+Ø—E’E˜)Ñ$Ô$¨Ò/Ð/ð	 ð 0Ð/Ð/r5   rÎ   )Ú_utc_now_isoÚscript_mtime_isorþ   rI   )r   r   ÚentryrÉ   s   ``  r.   r  r  ›  sã   øø€ àØÝ#‘~”~Ý$4°WÑ$=Ô$=ð	ð €Eõ 
"Ñ	#Ô	#ð  tð
ð 
ð 
ð 
ð 
Ø—x’x ¨RÑ0Ô0ð
ñ 
ô 
ð ˆGñˆˆ[Ñðð ð ñ ô ð ð ð ð ð ð ð øøøð ð ð ð ð ð s   ±+A)Á)A-Á0A-c                 óŒ   — t          j        t          j        ¬¦  «                             ¦   «                              dd¦  «        S )N©Útzú+00:00ÚZ)r   Únowr   ÚutcÚ	isoformaträ   r=   r5   r.   r  r  ­  s3   € ÝŒ<�8œ<Ð(Ñ(Ô(×2Ò2Ñ4Ô4×<Ò<¸XÀsÑKÔKÐKr5   c                ó  ‡ — t          ¦   «         5 }t          |                     dg ¦  «        ¦  «        }ˆ fd„|                     dg ¦  «        D ¦   «         |d<   t          |d         ¦  «        }ddd¦  «         n# 1 swxY w Y   ||z
  S )uý   Remove every allowlist entry matching ``command``.

    Returns the number of entries removed.  Does not unregister any
    callbacks that are already live on the plugin manager in the current
    process â€” restart the CLI / gateway to drop them.
    rÎ   c                óp   •— g | ]2}t          |t          ¦  «        r|                     d ¦  «        ‰k    °0|‘Œ3S )r   rí   )r±   rï   r   s     €r.   r  zrevoke.<locals>.<listcomp>º  sL   ø€ ð 
ð 
ð 
ØÝ˜q¥$Ñ'Ô'ð
à,-¯EªE°)Ñ,<Ô,<ÀÒ,GÐ,Gð Ø,GÐ,GÐ,Gr5   N)rþ   ÚlenrI   )r   rÉ   ÚbeforeÚafters   `   r.   Úrevoker   ±  sÙ   ø€ õ 
"Ñ	#Ô	#ð ' tÝ�T—X’X˜k¨2Ñ.Ô.Ñ/Ô/ˆð
ð 
ð 
ð 
Ø—x’x ¨RÑ0Ô0ð
ñ 
ô 
ˆˆ[Ñõ �D˜Ô%Ñ&Ô&ˆð'ð 'ð 'ñ 'ô 'ð 'ð 'ð 'ð 'ð 'ð 'øøøð 'ð 'ð 'ð 'ð �E‰>Ðs   �AA:Á:A>ÂA>)z.shz.bashz.zshz.fishz.pyz.pywz.rbz.plz.luaz.jsz.mjsz.cjsz.tszTuple[str, ...]Ú_SCRIPT_EXTENSIONSc                ó  — 	 t          j        | ¦  «        }n# t          $ r | cY S w xY w|s| S |D ]2}|                     ¦   «                              t
          ¦  «        r|c S Œ3|D ]}d|v s|                     d¦  «        r|c S Œ |d         S )a4  Return the script path from ``command`` for doctor / drift checks.

    Prefers a token ending in a known script extension, then a token
    containing ``/`` or leading ``~``, then the first token.  Handles
    ``python3 /path/hook.py``, ``/usr/bin/env bash hook.sh``, and the
    common bare-path form.
    ú/Ú~r   )r�   r‘   r|   r  Úendswithr!  Ú
startswith)r   ÚpartsÚparts      r.   Ú_command_script_pathr)  Ê  sÄ   € ðÝ”˜GÑ$Ô$ˆˆøÝð ð ð Øˆˆˆðøøøàð ØˆØð ð ˆØ�:Š:‰<Œ<× Ò Õ!3Ñ4Ô4ð 	ØˆKˆKˆKð	àð ð ˆØ�$ˆ;ˆ;˜$Ÿ/š/¨#Ñ.Ô.ˆ;ØˆKˆKˆKð à�Œ8€Os   ‚ —&¥&Úaccept_hooks_argc                óè   — |rdS t           j                             dd¦  «                             ¦   «                              ¦   «         }|dv rdS |                      dd¦  «        }t          |¦  «        S )a  Combine all three opt-in channels into a single boolean.

    Precedence (any truthy source flips us on):
      1. ``--accept-hooks`` flag (CLI) / explicit argument
      2. ``HERMES_ACCEPT_HOOKS`` env var
      3. ``hooks_auto_accept: true`` in ``cli-config.yaml``
    TÚHERMES_ACCEPT_HOOKSr…   )Ú1Útruer  ÚonÚhooks_auto_acceptF)r’   ÚenvironrI   r%   r  r1   )r@   r*  ÚenvÚcfg_vals       r.   rG   rG   å  sp   € ð ð ØˆtÝ
Œ*�.Š.Ð.°Ñ
3Ô
3×
9Ò
9Ñ
;Ô
;×
AÒ
AÑ
CÔ
C€CØ
Ð(Ð(Ð(ØˆtØ�gŠgÐ)¨5Ñ1Ô1€GÝ�‰=Œ=Ðr5   c                óæ   — t          ¦   «                              dg ¦  «        D ]M}t          |t          ¦  «        r6|                     d¦  «        | k    r|                     d¦  «        |k    r|c S ŒNdS )z2Return the allowlist record for this pair, if any.rÎ   r   r   N)rÐ   rI   r$   rF   )r   r   rï   s      r.   Úallowlist_entry_forr5  ü  st   € åÑÔ×!Ò! +¨rÑ2Ô2ð ð ˆå�q�$ÑÔð	à—’�g‘” %Ò'Ð'Ø—’�iÑ Ô  GÒ+Ð+àˆHˆHˆHøØˆ4r5   r   c                óP  — t          | ¦  «        }|sdS 	 t          j                             |¦  «        }t	          j        t          j                             |¦  «        t          j        ¬¦  «         	                    ¦   «          
                    dd¦  «        S # t          $ r Y dS w xY w)zUISO-8601 mtime of the resolved script path, or ``None`` if the
    script is missing.Nr  r  r  )r)  r’   r“   r”   r   ÚfromtimestampÚgetmtimer   r  r  rä   rº   )r   r“   Úexpandeds      r.   r  r    s¤   € õ   Ñ(Ô(€DØð ØˆtðÝ”7×%Ò% dÑ+Ô+ˆÝÔ%ÝŒG×Ò˜XÑ&Ô&­8¬<ð
ñ 
ô 
ç
Š)‰+Œ+—g’g˜h¨Ñ,Ô,ð	-øõ ð ð ð Øˆtˆtðøøøs   •BB Â
B%Â$B%c                óŠ  — t          | ¦  «        }|sdS t          j                             |¦  «        }t          j                             |¦  «        sdS 	 t          j        | ¦  «        }n# t          $ r Y dS w xY wt          |¦  «        o|d         |k    }|rt          j	        nt          j
        }t          j        ||¦  «        S )u�  Return ``True`` iff ``command`` is runnable as configured.

    For a bare invocation (``/path/hook.sh``) the script itself must be
    executable.  For interpreter-prefixed commands (``python3
    /path/hook.py``, ``/usr/bin/env bash hook.sh``) the script just has
    to be readable â€” the interpreter doesn't care about the ``X_OK``
    bit.  Mirrors what ``_spawn`` would actually do at runtime.Fr   )r)  r’   r“   r”   Úisfiler�   r‘   r|   r1   ÚX_OKÚR_OKÚaccess)r   r“   r9  rŸ   Úis_bare_invocationÚrequireds         r.   Úscript_is_executablerA    sÃ   € õ   Ñ(Ô(€DØð ØˆuÝŒw×!Ò! $Ñ'Ô'€HÝŒ7�>Š>˜(Ñ#Ô#ð ØˆuðÝŒ{˜7Ñ#Ô#ˆˆøÝð ð ð Øˆuˆuðøøøå˜d™œÐ7¨¨Q¬°4ªÐØ,Ð9�rŒwˆwµ"´'€HÝŒ9�X˜xÑ(Ô(Ð(s   ÁA* Á*
A8Á7A8c                óŒ   — t          | j        |¦  «        }t          | |¦  «        }t          | j        |d         ¦  «        |d<   |S )uU  Fire a single shell-hook invocation with a synthetic payload.
    Used by ``hermes hooks test`` and ``hermes hooks doctor``.

    ``kwargs`` is the same dict that :func:`hermes_cli.plugins.invoke_hook`
    would pass at runtime.  It is routed through :func:`_serialize_payload`
    so the synthetic stdin exactly matches what a real hook firing would
    produce â€” otherwise scripts tested via ``hermes hooks test`` could
    diverge silently from production behaviour.

    Returns the :func:`_spawn` diagnostic dict plus a ``parsed`` field
    holding the canonical Hermes-wire-shape response.r‡   Úparsed)r§   r   r¢   r©   )rX   r¥   r‚   rž   s       r.   Úrun_oncerD  .  sD   € õ $ D¤J°Ñ7Ô7€JÝ�D˜*Ñ%Ô%€FÝ& t¤z°6¸(Ô3CÑDÔD€Fˆ8ÑØ€Mr5   )r@   rA   r?   r1   r!   rB   )r@   rA   r!   rB   r6   )ra   r
   r!   rB   )r   r   ru   r   rt   r
   r!   rv   )rX   r   r‚   r   r!   rƒ   )rX   r   r!   r£   )r   r   r¥   rƒ   r!   r   )r   r   r‡   r   r!   rA   )r!   r	   )r!   rƒ   )rÉ   rƒ   r!   r"   )r   r   r   r   r!   r1   )r!   rò   )r   r   r   r   r?   r1   r!   r1   )r   r   r   r   r!   r"   )r!   r   )r   r   r!   r   )r   r   r!   r   )r@   rƒ   r*  r1   r!   r1   )r   r   r   r   r!   rA   )r   r   r!   r   )r   r   r!   r1   )rX   r   r¥   rƒ   r!   rƒ   )Kr:   Ú
__future__r   rh   r»   Úloggingr’   r&   r�   r—   r  rß   Ú	threadingr•   Ú
contextlibr   Údataclassesr   r   r   r   Úpathlibr	   Útypingr
   r   r   r   r   r   r   r   rõ   ÚImportErrorÚhermes_constantsr   Ú	getLoggerr7   r)   r<   r}   rË   Úsetr   r;   ÚLockrK   rö   r   r[   r]   r`   rH   ro   r°   r¢   rQ   r§   r©   rÌ   rÐ   rê   rL   rþ   rM   r  r  r   r!  r)  rG   r5  r  rA  rD  r=   r5   r.   ú<module>rQ     sH  ðð3ð 3ð 3ðj #Ð "Ð "Ð "Ð "Ð "à €€€Ø €€€Ø €€€Ø 	€	€	€	Ø 	€	€	€	Ø €€€Ø Ð Ð Ð Ø 
€
€
€
Ø €€€Ø Ð Ð Ð Ø €€€Ø %Ð %Ð %Ð %Ð %Ð %Ø (Ð (Ð (Ð (Ð (Ð (Ð (Ð (Ø 'Ð 'Ð 'Ð 'Ð 'Ð 'Ð 'Ð 'Ø Ð Ð Ð Ð Ð Ø LÐ LÐ LÐ LÐ LÐ LÐ LÐ LÐ LÐ LÐ LÐ LÐ LÐ LÐ LÐ LÐ LÐ LÐ LÐ LðØ€L€L€L€LøØð ð ð Ø€E€E€Eðøøøð -Ð ,Ð ,Ð ,Ð ,Ð ,à	ˆÔ	˜8Ñ	$Ô	$€àÐ ØÐ Ø1Ð ð 47°3±5´5€Ð 8Ð 8Ð 8Ñ 8Ø!�9”>Ñ#Ô#Ð ð '˜	œÑ(Ô(Ð ð ð#)ð #)ð #)ð #)ð #)ñ #)ô #)ñ „ð#)ðZ ðHð Hð Hð Hð Hð HðV0ð 0ð 0ð 0ðð ð ð ð-ð -ð -ð -ð`@ð @ð @ð @ðN SÐRÐRÐ ð7ð 7ð 7ð 7ðt)ð )ð )ð )ðX@ð @ð @ð @ð&/ð /ð /ð /ðl2ð 2ð 2ð 2ð
ð ð ð ð
ð 
ð 
ð 
ð@ð ð ð ð ð9ð 9ð 9ñ „ð9ð<#ð #ð #ð #ðLð ð ð ð$Lð Lð Lð Lðð ð ð ð"'Ð ð ð ð ñ ðð ð ð ð6ð ð ð ð.	ð 	ð 	ð 	ðð ð ð ð)ð )ð )ð )ð.ð ð ð ð ð s   Á'A, Á,A6Á5A6