
    xjR                    l   d Z ddlmZ ddlZddlZddlZddlmZ ddlm	Z	 ddl
mZmZmZmZ ddlmZ dZd	Zh d
Zh dZh dZh dZ ej        d          Z ej        d          Z ej        d          Z ej        d          Z G d de          Z ed           G d d                      Z ed           G d d                      Z ed           G d d                      Z dJd!Z!dKd%Z"dLd'Z#dMd,Z$dNd0Z%dOd4Z&dd5dPd7Z'dQd:Z(dRd<Z)dSd?Z*dTd@Z+ddAdUdDZ,dVdEZ-dWdGZ.dXdIZ/dS )Ya>  Compatibility helpers for Agent Plugins v1 portable directory packages.

This module validates the versioned portable format locally and translates its
supported components into records consumed by Hermes' existing skill and MCP
runtimes. It deliberately performs no schema fetching and imports no plugin
Python code.
    )annotationsN)	dataclass)Path)AnyDictMappingTuple)	yaml_loadz:https://agent-plugins.org/schemas/1.0.0/plugin.schema.jsonz7https://agent-plugins.org/schemas/1.0.0/mcp.schema.json>
   nameauthorlicenseversionhomepagekeywords
extensions
repositorydescription$schema>   urlr   email>   cwdenvargstypecommand>   r   r   headersz3^(?!.*(?:--|\.\.))[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$z"^(?!.*--)[a-z0-9]+(?:-[a-z0-9]+)*$z\$\{(PLUGIN_ROOT|PLUGIN_DATA)\}z^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$c                      e Zd ZdZdS )AgentPluginErrorz+Fatal portable manifest validation failure.N)__name__
__module____qualname____doc__     </home/agent/.hermes/hermes-agent/hermes_cli/agent_plugins.pyr   r   /   s        5555r$   r   T)frozenc                  $    e Zd ZU ded<   ded<   dS )AgentPluginDiagnosticstrscopemessageNr   r    r!   __annotations__r#   r$   r%   r(   r(   3   s"         JJJLLLLLr$   r(   c                  B    e Zd ZU ded<   ded<   ded<   ded<   ded<   d	S )
AgentPluginSkillr)   r   r   r   rootskill_mdMapping[str, Any]frontmatterNr,   r#   r$   r%   r/   r/   9   sE         IIIJJJNNN""""""r$   r/   c                  j    e Zd ZU ded<   ded<   ded<   ded<   ded<   ded	<   d
ed<   ded<   ded<   dS )AgentPluginPackager)   r   r   r   r   r0   	data_rootr2   manifestzTuple[AgentPluginSkill, ...]skillszMapping[str, Dict[str, Any]]mcp_serversz!Tuple[AgentPluginDiagnostic, ...]diagnosticsNr,   r#   r$   r%   r5   r5   B   sr         IIILLLJJJOOO((((----222222r$   r5   pathr   r0   returnboolc                    	 |                      d                              |                     d                     dS # t          t          t          f$ r Y dS w xY w)NFstrictT)resolverelative_toOSErrorRuntimeError
ValueError)r;   r0   s     r%   _insiderF   O   se    E""..t||4|/H/HIIIt\:.   uus   =A AAlabelr)   dictc                  	 t          j        |                     d                    }n9# t          t          t           j        f$ r}t          | d|           |d }~ww xY wt          |t                    st          | d          |S )Nutf-8encodingz is not valid readable JSON: z must contain a JSON object)	jsonloads	read_textrC   UnicodeErrorJSONDecodeErrorr   
isinstancerH   )r;   rG   valueexcs       r%   _read_json_objectrU   W   s    V
4>>7>;;<<\4#78 V V V%KKcKKLLRUUVeT"" F%DDDEEELs   (+ A!AA!(tuple[dict, list[AgentPluginDiagnostic]]c                   | dz  }t          ||           r|                                st          d          t          |d          }g }t	          t          |          t          z
            D ]=}|                    t          dd|                      |	                    |           >|
                    d          t          k    rt          d          |
                    d          }t          |t                    r7d	t          |          cxk    rd
k    rn nt                              |          t          d          dD ]4}||v r.t          ||         t                    st          d| d          5d|v rE|d         }t          |t"                    rt%          d |D                       rt          d          d|v r|d         }t          |t&                    st          d          t          |          t(          z
  }|s+t%          d |                                D                       rt          d          d|v r|d         }	t          |	t&                    s9|                    t          dd                     |	                    d           n:t%          d |	                                D                       rt          d          ||fS )Nzplugin.jsonz9plugin.json must be a regular file within the plugin rootrG   r7   z!ignored unknown top-level field: r   zCplugin.json declares an unsupported or missing Agent Plugins schemar      @   z0plugin.json name does not satisfy v1 constraints)r   r   r   r   r   zplugin.json z must be a stringr   c              3  B   K   | ]}t          |t                     V  d S NrR   r)   .0rS   s     r%   	<genexpr>z%_validate_manifest.<locals>.<genexpr>   s@       1
 1
+0
5#&&&1
 1
 1
 1
 1
 1
r$   z0plugin.json keywords must be an array of stringsr   z$plugin.json author must be an objectc              3  B   K   | ]}t          |t                     V  d S r\   r]   r^   s     r%   r`   z%_validate_manifest.<locals>.<genexpr>   s/      RRj444RRRRRRr$   zFplugin.json author may contain only string name, email, and url fieldsr   z#ignored non-object extensions fieldc              3  B   K   | ]}t          |t                     V  d S r\   )rR   rH   r^   s     r%   r`   z%_validate_manifest.<locals>.<genexpr>   s/      NNZt,,,NNNNNNr$   z6plugin.json extension namespace values must be objects)rF   is_filer   rU   sortedset_PLUGIN_FIELDSappendr(   popgetPLUGIN_SCHEMA_V1rR   r)   len_PLUGIN_NAME_RE	fullmatchlistanyrH   _AUTHOR_FIELDSvalues)
r0   manifest_pathr7   r:   fieldr   r   r   unknownr   s
             r%   _validate_manifestru   a   sL   =(M=$'' \}/D/D/F/F \Z[[[ mDDDH/1KH677  !*.YRW.Y.YZZ	
 	
 	
 	U||I"222Q
 
 	
 <<DtS!!SCII#########$$T**2QRRRP L LHZ%E%E"#J%#J#J#JKKKXJ'(D)) 	WS 1
 1
4<1
 1
 1
 .
 .
 	W ##UVVV8(#&$'' 	K"#IJJJf++. 	cRR&--//RRRRR 	"X   xl+
*d++ 	]% E   
 LL&&&&NN*:K:K:M:MNNNNN 	]"#[\\\[  r$   r3   r2   directory_name
str | Nonec                   |                      d          }t          |t                    r=||k    s7dt          |          cxk    rdk    rn nt                              |          dS |                      d          }t          |t                    rdt          |          cxk    rdk    sn dS d| v rt          | d         t                    sd	S d
| v r;| d
         }t          |t                    rdt          |          cxk    rdk    sn dS d| v rJ| d         }t          |t                    r+t          d |                                D                       rdS d| v rt          | d         t                    sdS d S )Nr   rY   rZ   zBname must match the directory and satisfy Agent Skills constraintsr   i   zAdescription must be a non-empty string of at most 1024 charactersr   zlicense must be a stringcompatibilityi  z5compatibility must be a string of 1 to 500 charactersmetadatac              3  t   K   | ]3\  }}t          |t                     pt          |t                     V  4d S r\   r]   r_   keyrS   s      r%   r`   z+_valid_skill_frontmatter.<locals>.<genexpr>   sY       1
 1
U 3$$$BJuc,B,B(B1
 1
 1
 1
 1
 1
r$   z.metadata must map string keys to string valueszallowed-toolszallowed-tools must be a string)	ri   rR   r)   rk   _SKILL_NAME_RErm   rH   ro   items)r3   rv   r   r   ry   rz   s         r%   _valid_skill_frontmatterr      s    ??6""DtS!!T>!!CII###########D))1SS//-00Kk3'' SqC4D4D/L/L/L/L/L/L/L/LRRK
;y3I3(O(O))+%%#O4--- 	KQ#m:L:L5S5S5S5SPS5S5S5S5SJJ[  z*(D)) 	DS 1
 1
&nn..1
 1
 1
 .
 .
 	D DC+%%jO$c/ /% 0/4r$   r:   list[AgentPluginDiagnostic]tuple[AgentPluginSkill, ...]c                   | dz  }|                                 s|                                sdS t          ||           r|                                s%|                    t          dd                     dS g }	 t          |                                d           }n># t          $ r1}|                    t          dd|                      Y d }~dS d }~ww xY w|D ]i}|dz  }|                                r|                                 s1d|j	         }t          ||           r|
                                s$|                    t          |d	                     	 |                    d
          }	|	                    d          }	|	                    d          st          d          t          j        d|	dd                    }
|
t          d          	 t#          |	d|
                                dz                      }n%# t&          $ r}t          d|           |d }~ww xY wt)          |t*                    st          d          |}nK# t          t,          t          f$ r1}|                    t          |d|                      Y d }~d }~ww xY wt/          ||j	                  }|r%|                    t          ||                     |                    t1          |j	        |d         |                    d          |                    d          t+          |                               kt5          |          S )Nr8   r#   z#skills must be an in-root directoryc                    | j         S r\   )r   )r;   s    r%   <lambda>z"_discover_skills.<locals>.<lambda>   s    $) r$   )r}   zcannot list skills: zSKILL.mdzskill:z'SKILL.md must be a regular in-root filerJ   rK   u   ﻿z---zmissing YAML frontmatterz
\n---\s*\n   zunterminated YAML frontmatterzinvalid YAML frontmatter: z"YAML frontmatter must be an objectzinvalid SKILL.md: r   Tr?   )r   r   r0   r1   r3   )exists
is_symlinkrF   is_dirrg   r(   rd   iterdirrC   r   rc   rO   lstrip
startswithrE   researchr
   start	ExceptionrR   rH   rP   r   r/   rA   tuple)r0   r:   skills_rootr8   childrenrT   childr1   r*   content	end_matchparsedr3   errors                 r%   _discover_skillsr      s    /K (>(>(@(@ r;%% [-?-?-A-A !(,QRR	
 	
 	
 r%'F+--//5K5KLLL   0;WRU;W;WXXYYYrrrrr  (
 (
:%||~~ 	X__%6%6 	%%%x&& 	h.>.>.@.@ 	%e-VWW   	(('(::GnnX..G%%e,, = !;<<<	-==I  !@AAAN"71y/@/@1/D+D#EFF N N N !Cc!C!CDD#MNfd++ G !EFFF KKz2 	 	 	4U<VQT<V<VWWXXXHHHH	 )ejAA 	4UEBBCCCZ'6]]$]//!)))66 --  	
 	
 	
 	
 ==sU   <$B! !
C+&CC%A=I#,HI
H2H--H22)IJ$3&JJ$rS   plugin_rootr6   c                ~    t          |          t          |          dt                              fd|           S )N)PLUGIN_ROOTPLUGIN_DATAc                :    |                      d                   S )NrY   )group)matchreplacementss    r%   r   z_expand.<locals>.<lambda>  s    \%++a..-I r$   )r)   _PLACEHOLDER_REsub)rS   r   r6   r   s      @r%   _expandr      sE    ;''9~~ L IIII5QQQr$   expand_placeholdersr   c               ,   |rt          | ||          n| }|                     d          r|}||dd          z  }ni| dk    s|                     d          r|}t          |          }n<| dk    s|                     d          r|}t          |          }nt          d          |                    d	          }	 |                    |                    d	                     n/# t          t          t          f$ r}t          d
          |d }~ww xY w|S )N./   z${PLUGIN_ROOT}z${PLUGIN_ROOT}/z${PLUGIN_DATA}z${PLUGIN_DATA}/z:path must start with ./, ${PLUGIN_ROOT}, or ${PLUGIN_DATA}Fr?   zpath escapes its resolved root)r   r   r   rE   rA   rB   rC   rD   )	rS   r   r6   r   expandedbase	candidateresolvedrT   s	            r%   _resolve_scoped_pathr     sE    :MWwuk9555RWH 
W8ABB<'			"	"	"e&6&67H&I&I	"NN			"	"	"e&6&67H&I&I	"NN		UVVV   ..HDT\\\778888\:. D D D9::CDOs   ;)C% %D<DDr   objectc                   | dS t          | t                    sdS t                      }|                                 D ]\  }}t          |t                    rMt
                              |          3t          |t                    rd|v sd|v s|                                |v r dS |                    |                                           dS )NTF
)	rR   rH   re   r   r)   _HEADER_NAME_RErm   loweradd)r   seenr   rS   s       r%   _validate_headersr   "  s    tgt$$ uUUD}} 
 
e4%%	((..6eS)) 7u}}u}}zz||t##554r$   r   c                X   ddl m} t          | t                    r| st	          d          	  ||           }n%# t          $ r}t	          d|           |d}~ww xY w|j                                        }|dvrt	          d          |j        |j        t	          d          |j	        rt	          d	          |j
        }|st	          d
          |dk    rNd}|dk    rd}n2ddl}	 |                    |          j        }n# t          $ r d}Y nw xY w|st	          d          | S )up  Validate a portable remote MCP URL per the v1 spec and return it.

    Rules (Agent Plugins v1 §7.2.1): absolute http(s) URL, no user
    information, no fragment; non-loopback endpoints must use HTTPS. HTTP is
    allowed only when the host is exactly ``localhost`` or an IP literal in a
    loopback range. No placeholder or environment expansion is performed.
    r   )urlsplitzurl must be a non-empty stringzurl is not parseable: N>   httphttpsz url scheme must be http or httpsz%url must not contain user informationzurl must not contain a fragmentzurl must have a hostr   F	localhostTznon-loopback url must use https)urllib.parser   rR   r)   rE   schemer   usernamepasswordfragmenthostname	ipaddress
ip_addressis_loopback)r   r   r   rT   r   hostloopbackr   s           r%   _validate_remote_urlr   6  s    &%%%%%c3 ;s ;9:::B# B B B7#7788cAB]  ""F&&&;<<<"fo&A@AAA <:;;;?D 1/000;HH!$//55A ! ! ! ! 	@>???Js'   : 
AAA,D DDconfigDict[str, Any]c                T   t          |           t          z
  rt          d          t          |                     d                    }t          |                     d                    st          d          |dd}|                     d          }|rt          |          |d<   |S )a  Translate a portable ``streamable-http`` entry into native MCP config.

    The returned record targets Hermes' existing URL-based MCP runtime.
    ``strict_redirect_headers`` instructs the runtime to drop the configured
    headers on any cross-origin redirect, which the v1 spec requires for
    portable packages (configured headers must not be forwarded to a
    different origin without explicit user authorization).
    zunknown remote fieldr   r   zinvalid headersT)r   strict_redirect_headers)re   _REMOTE_FIELDSrE   r   ri   r   rH   )r   r   
translatedr   s       r%   _translate_remoter   a  s     6{{^# 1/000
vzz%00
1
1CVZZ	2233 ,*+++#'" "J jj##G . $W
9r$   c                   t          |           t          z
  rt          d          |                     d          }t	          |t
                    r|rd|v rt          d          |                    d          r!t          t          |d                    }nEt          d |D                       rt          d	          d
|v sd|v s|dv rt          d          |}|                     dg           }t	          |t                    rt          d |D                       rt          d          |                     di           }t	          |t                    r+t          d |                                D                       rt          d          d |D             }d|v sd|v rt          d          |                     d          }|}	n5t	          |t
                    st          d          t          |          }	fd|                                D             }
t                    |
d<   t                    |
d<   |fd|D             |
t          |	          dS )Nzunknown stdio fieldr    z,command must be a non-empty executable tokenr   Fr   c              3  >   K   | ]}|                                 V  d S r\   )isspace)r_   	characters     r%   r`   z#_translate_stdio.<locals>.<genexpr>  s.      ::YY  ::::::r$   z)command must contain one executable token/\>   ...z2command must be a bare executable or begin with ./r   c              3  B   K   | ]}t          |t                     V  d S r\   r]   r^   s     r%   r`   z#_translate_stdio.<locals>.<genexpr>  s/      (V(VZs-C-C)C(V(V(V(V(V(Vr$   z args must be an array of stringsr   c              3  t   K   | ]3\  }}t          |t                     pt          |t                     V  4d S r\   r]   r|   s      r%   r`   z#_translate_stdio.<locals>.<genexpr>  sY       ( (C sC   >
5#(>(>$>( ( ( ( ( (r$   z)env must map string keys to string valuesc                Z    h | ](}t           j        d k    r|                                n|)S )nt)osr   upper)r_   r}   s     r%   	<setcomp>z#_translate_stdio.<locals>.<setcomp>  s.    GGGCrw$		CGGGr$   r   r   z(PLUGIN_ROOT and PLUGIN_DATA are reservedr   zcwd must be a stringc                :    i | ]\  }}|t          |          S r#   r   )r_   r}   rS   r6   r   s      r%   
<dictcomp>z$_translate_stdio.<locals>.<dictcomp>  s8       8BUWUK33  r$   c                2    g | ]}t          |          S r#   r   )r_   rS   r6   r   s     r%   
<listcomp>z$_translate_stdio.<locals>.<listcomp>  s%    JJJEY77JJJr$   )r   r   r   r   )re   _STDIO_FIELDSrE   ri   rR   r)   r   r   ro   rn   rH   r   )r   r   r6   r   command_valuer   r   env_keysr   	cwd_valuetranslated_envs    ``        r%   _translate_stdior   z  s    6{{]" 0.///jj##Ggs## I7 If6G6GGHHH$   $)	  
 
 
::':::	:	:  DEEE	47??g.D.DMNNN::fb!!DdD!! =S(V(VQU(V(V(V%V%V =;<<<
**UB

Cc4   FC ( ())++( ( ( % % F DEEEGG3GGGH  MX$=$=CDDD
**U

C
{		S!! F/000(k9EE	    FIiikk  N %($4$4N=!$'	NNN=! JJJJJTJJJ9~~	  r$   )create_datar   Dict[str, Dict[str, Any]]c          
        | dz  }|                                 s|                                si S t          ||           r|                                s%|                    t          dd                     i S 	 t          |d          }nI# t          $ r<}|                    t          dt          |                               i cY d }~S d }~ww xY wt          |          ddhk    r%|                    t          dd                     i S |
                    d          t          k    r%|                    t          dd                     i S |
                    d          }t          |t                    s%|                    t          dd	                     i S i }|                                D ]\  }	}
d
|	 }t          |	t                    r|	rt          |
t                    s$|                    t          |d                     [|

                    d          }|dk    r	 t          |
| |          }|rj|                    dd           t#          |d                   }	 |                    |           |                    dd           n# t&          $ r Y nw xY w|||	<   # t(          t&          f$ r;}|                    t          |t          |                               Y d }~Ad }~ww xY w|dk    r]	 t+          |
          ||	<   d# t&          $ r;}|                    t          |t          |                               Y d }~d }~ww xY w|dk    rt          |
          t,          z
  s_t          |

                    d          t                    r7|

                    d          r"t/          |

                    d                    s%|                    t          |d                     M|                    t          |d| d                     v|                    t          |d                     |S )Nzmcp.jsonmcpz'mcp.json must be a regular in-root filerX   r   
mcpServersz'mcp.json has an invalid top-level shapez'mcp.json declares an unsupported schemazmcpServers must be an objectzmcp:zinvalid server entryr   stdioT)parentsexist_okr   zstreamable-httpsser   r   zinvalid remote entryz	portable z transport is not supportedzunknown MCP server type)r   r   rF   rc   rg   r(   rU   r   r)   re   ri   MCP_SCHEMA_V1rR   rH   r   r   mkdirr   rB   rE   rC   r   r   r   )r0   r6   r:   r   mcp_pathr   rT   serversr   r   serverr*   server_typetranslated_servercwd_paths                  r%   _discover_mcpr     s    j H?? X%8%8%:%: 	8T"" (*:*:*<*< !%)RSS	
 	
 	
 	"8:>>>   0CAABBB						 6{{y,///!%)RSS	
 	
 	
 	zz)--!%)RSS	
 	
 	
 	jj&&Ggt$$ !%)GHH	
 	
 	
 	,.J .X .Xft$$$ 	D 	
648P8P 	4U<RSSTTTjj(('!!K$4VT9$M$M! DOOD4O@@@#$5e$<==H	D ,,Y777 !tdCCCC &    $5
4  Z( K K K""#8C#I#IJJJJJJJJK---K#4V#<#<
4   K K K""#8C#I#IJJJJJJJJKE!!Fn,!&**U"3"3S99 zz%(( )I)>)>??	 ""#8@V#W#WXXXX"")LKLLL     4U<UVVWWWWsr   :B 
C1CCC.?J1.JJ1
J(%J1'J((J11K=0K88K=L
M %0MM c                   t          |                               d          }|                                st          d          t	          |          \  }}t          |                              d          }t          ||          }t          |||          }t          |d         |                    dd          |                    dd          ||t          |          ||t          |          		  	        S )
zValidate and translate one installed Agent Plugins v1 package.

    Fatal manifest errors raise :class:`AgentPluginError`. Component and entry
    failures are returned as diagnostics and isolated to their owning scope.
    Tr?   plugin root must be a directoryFr   r    r   )	r   r   r   r0   r6   r7   r8   r9   r:   )r   rA   r   r   ru   r   r   r5   ri   rH   r   )r   r6   r0   r7   r:   resolved_datar8   r9   s           r%   load_agent_pluginr    s     $$D$11D;;== B@AAA.t44HkOO++5+99MdK00Fm[AAKfY++LL33h+&&
 
 
 
r$   .tuple[dict, tuple[AgentPluginDiagnostic, ...]]c                    t          |                               d          }|                                st          d          t	          |          \  }}|t          |          fS )zBValidate only root ``plugin.json`` without discovering components.Tr?   r   )r   rA   r   r   ru   r   )r   r0   r7   r:   s       r%   read_agent_plugin_manifestr  '  sg     $$D$11D;;== B@AAA.t44HkU;''''r$   
raw_configc                $    ddl m}  ||           S )a  Compatibility wrapper for the shared PluginManager MCP probe.

    Directory scanning belongs to :mod:`hermes_cli.plugins` so startup gating
    and full plugin discovery cannot drift apart. Keep this import-compatible
    entry point for callers that used the original helper.
    r   )has_enabled_agent_plugin_mcp)hermes_cli.pluginsr  )r  _probes     r%   r  r  1  s'     JIIIII6*r$   )r;   r   r0   r   r<   r=   )r;   r   rG   r)   r<   rH   )r0   r   r<   rV   )r3   r2   rv   r)   r<   rw   )r0   r   r:   r   r<   r   )rS   r)   r   r   r6   r   r<   r)   )
rS   r)   r   r   r6   r   r   r=   r<   r   )r   r   r<   r=   )r   r   r<   r)   )r   r2   r<   r   )r   r2   r   r   r6   r   r<   r   )
r0   r   r6   r   r:   r   r   r=   r<   r   )r   r   r6   r   r<   r5   )r   r   r<   r  )r  r2   r<   r=   )0r"   
__future__r   rM   r   r   dataclassesr   pathlibr   typingr   r   r   r	   agent.skill_utilsr
   rj   r   rf   rp   r   r   compilerl   r~   r   r   rE   r   r(   r/   r5   rF   rU   ru   r   r   r   r   r   r   r   r   r   r  r  r  r#   r$   r%   <module>r     s|    # " " " " "  				 				 ! ! ! ! ! !       , , , , , , , , , , , , ' ' ' ' ' ' P I   *))999+++"*:  ABB"*?@@"*>??6 6 6 6 6z 6 6 6 $       
 $# # # # # # # # $	3 	3 	3 	3 	3 	3 	3 	3      :! :! :! :!z   D< < < <~R R R R !%     6   (( ( ( (V   27 7 7 7~ U U U U U Up   6( ( ( (
 
 
 
 
 
r$   