+
    „WÝjl"  ã                  ó„  a € 0 t $ R t^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIH	t	 ^ RI
Ht ^ RIHtHtHt ^ RIHt ^ RIHt ]P(                  ! R4      t]! 0 Rm4      t]P(                  ! R	4      tRt/ tR
]R&   ]P8                  ! 4       tR R ltR R ltR R lt R R lt!R R lt"R R lt#]	R R l4       t$ ! R R4      t%R# )z]Plugin-owned durable state and namespaced settings helpers (split out of hermes_cli.plugins).)ÚannotationsN)Úcontextmanager)ÚPath)ÚAnyÚDictÚMapping)Úget_hermes_home)Ú_portable_skill_namespacez!^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$z#^[A-Za-z0-9][A-Za-z0-9_.:-]{0,127}$zdict[str, threading.RLock]Ú_PLUGIN_STATE_LOCKSc               ó    € V ^8„  d   QhRRRR/# )é   ÚkeyÚstrÚreturnútuple[str, ...]© )Úformats   "ÚLC:\Users\johnn\AppData\Local\hermes\hermes-agent\hermes_cli\plugins_state.pyÚ__annotate__r      s   € ÷ ñ  3ð ¨?ñ ó    c                ó¤  € \        V \        4      '       g   \        R4      h\        V P	                  R4      4      pV '       * ;'       g9    RV 9   ;'       g,    RV 9   ;'       g    V^ ,          P                  4       \        9   pV'       g;   \        ;QJ d    R V 4       F  '       d   K   RM	  RM! R V 4       4      '       g   \        R4      hV# )	z×Validate/split a plugin-relative settings key; global paths, traversal, and core roots are rejected
before any config read.

The public API accepts only relative keys (``endpoint`` or ``retry.policy``). See #64227.
z,Expected a plugin-relative config key stringÚ.Ú/Ú\c              3  óL   "  € T F  p\         P                  V4      x € K  	  R # 5i©N)Ú_PLUGIN_SETTING_SEGMENT_REÚ	fullmatch)Ú.0Úsegments   & r   Ú	<genexpr>Ú,_plugin_relative_segments.<locals>.<genexpr>"   s!   é € Ð`ÑW_ÈGÔ4×>Ñ>¸w×GÐGÓW_ùs   ‚"$FTzƒExpected a plugin-relative config key such as 'endpoint' or 'retry.policy'; global, cross-plugin, and traversal paths are forbidden)Ú
isinstancer   Ú
ValueErrorÚtupleÚsplitÚlowerÚ_PLUGIN_SETTING_RESERVED_ROOTSÚall)r   ÚsegmentsÚinvalids   &  r   Ú_plugin_relative_segmentsr+      s¨   € ô �cœ3×ÒÜÐGÓHÐHÜ�S—Y‘Y˜s“^Ó$€HØŒg×kÐk˜ ™×kÐk t¨s¡{×kÐk°h¸qµk×6GÑ6GÓ6IÔMkÑ6k€Gß—c“cÑ`ÑW_Ó`—c—c’cÑ`ÑW_Ó`×`Ò`ÜðVó
ð 	
ð €Or   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   ÚrootÚobjectr)   r   Údefaultr   r   r   )r   s   "r   r   r   *   s)   € ÷ ñ ˜vð °ð È3ð ÐSVñ r   c                ól   € T pV F+  p\        V\        4      '       d   WC9  d   Vu # W4,          pK-  	  V# )zIWalk ``segments`` through nested mappings; ``default`` on the first miss.)r"   r   )r-   r)   r/   Úcurrentr   s   &&&  r   Ú_nested_plugin_valuer2   *   s7   € à€GÛˆÜ˜'¤7×+Ò+¨wÔ/EØŠNØÕ"Šñ ð €Nr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r)   r   Úvaluer   r   údict[str, Any]r   )r   s   "r   r   r   4   s!   € ÷ ñ  _ð ¸Sð À^ñ r   c                ó4   € Tp\        V 4       F  pW2/pK  	  V# )z;Wrap ``value`` in nested single-key dicts, outermost first.)Úreversed)r)   r4   Únestedr   s   &&  r   Ú_nested_plugin_mappingr9   4   s#   € à€FÜ˜HÖ%ˆØÐ"Šñ &à€Mr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úconfigr.   Ú	plugin_idr   r   zMapping[str, Any] | Noner   )r   s   "r   r   r   <   s"   € ÷ 9ñ 9 6ð 9°cð 9Ð>Vñ 9r   c                óV   € \        V RRV3R4      p\        V\        4      '       d   V# R# )z<``plugins.entries.<plugin_id>`` as a mapping, else ``None``.ÚpluginsÚentriesN)r2   r"   r   )r;   r<   Úentrys   && r   Ú_plugin_settings_entryrA   <   s.   € ä  ¨)°YÀ	Ð)JÈDÓQ€EÜ˜u¤g×.Ò.ˆ5Ð8°DÐ8r   c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   r<   r   r)   r   r4   r   r   ÚNoner   )r   s   "r   r   r   B   s/   € ÷ Xñ X 3ð X°/ð XÈ#ð XÐRVñ Xr   c           
     ó>  € ^ RI Hp ^ RI Hp VP                  4       '       d   \	        R4      hRRV R.VO5pRP                  V4      pVP                  V4      '       d   \	        RV: R	24      h\        VR
,          \        W4      4      p\        VP                  4       4      ;_uu_ 4        VP                  ;_uu_ 4        VP                  4        VP                  Wu0RR7       RRR4       RRR4       R#   + '       g   i     L; i  + '       g   i     R# ; i)a²  Atomically write one value under ``plugins.entries.<plugin_id>.settings``.

THE writer for plugin settings: ``PluginContext.set_config`` (the plugin itself) and the
Desktop/TUI ``plugins.manage settings`` action both land here so managed-install and
administrator-managed-key refusals, the cross-process lock and the fail-closed raw read
are enforced once. ``segments`` must already be validated by :func:`_plugin_relative_segments`.
)r;   )Úmanaged_scopez6Plugin settings cannot be changed in a managed installr>   r?   Úsettingsr   zPlugin setting z is administrator-managed:Né   NT)Úpreserve_keysÚmerge_existingN)Ú
hermes_clir;   rE   Ú
is_managedÚPermissionErrorÚjoinÚis_key_managedr9   Ú_locked_plugin_stateÚget_config_pathÚ_CONFIG_LOCKÚread_user_config_rawÚsave_config)r<   r)   r4   Ú
config_modrE   Ú	full_pathÚdotted_pathÚpartials   &&&     r   Úsave_plugin_settingrX   B   sä   € õ 0Ý(à×Ñ×ÒÜÐVÓWÐWØ˜I y°*ÐH¸xÑH€IØ—(‘(˜9Ó%€KØ×#Ñ# K×0Ò0Ü °©Ð>WÐXÓYÐYÜ$ Y¨r¥]Ô4JÈ8Ó4[Ó\€Gô 
˜j×8Ñ8Ó:×	;Õ	;¸Z×=T×=TÓ=Tð 	×'Ñ'Ô)Ø×Ñ˜w°kÐRVÐÔW÷	 >U×	;Ñ	;×=T×=Tú×	;×	;Ð	;ús$   Â,DÃ%C8	Ã&DÃ8DÄDÄD	c               ó$   € V ^8„  d   QhRRRRRR/# )r   r<   r   Úskill_namespacer   r   )r   s   "r   r   r   ]   s!   € ÷ 0ñ 0 cð 0¸Cð 0ÀCñ 0r   c                ó´   € T;'       g    T pT;'       d    VP                  R4      pV'       d    \        P                  ! RV4      '       d   V# \        V4      # )zïReturn one Windows-safe directory component for plugin-owned data. Portable Agent Plugins already
receive this exact PLUGIN_DATA path; otherwise the fixed prefix avoids Windows reserved device names and
the digest prevents fold collisions.zagent-plugin-z[A-Za-z0-9][A-Za-z0-9_-]{0,191})Ú
startswithÚrer   r	   )r<   rZ   Ú	candidateÚportables   &&  r   Ú_plugin_data_namespacer`   ]   sN   € ð  ×,Ð, 9€IØ×HÐH 9×#7Ñ#7¸Ó#H€Hß”B—L’LÐ!CÀY×OÒOØÐÜ$ YÓ/Ð/r   c               ó   € V ^8„  d   QhRR/# )r   Úpathr   r   )r   s   "r   r   r   i   s   € ÷ @ñ @˜tñ @r   c              #  ó¨  "  € V P                  RV P                   R24      p\        ;_uu_ 4        \        P	                  \        VP                  RR7      4      \        P                  ! 4       4      pRRR4       X;_uu_ 4        VP                  P                  RRR7       \        VR4      ;_uu_ 4       p\        P                  R	8X  dˆ   ^ RIpVP                  ^ \        P                  4      ^ 8X  d"   VP!                  R
4       VP#                  4        VP                  ^ 4       VP%                  VP'                  4       VP(                  ^4       M.^ RIpVP-                  VP'                  4       VP.                  4        Rx € \        P                  R	8X  d>   VP                  ^ 4       XP%                  VP'                  4       VP0                  ^4       M+XP-                  VP'                  4       VP2                  4        RRR4       RRR4       R#   + '       g   i     EL¬; i  \        P                  R	8X  d>   TP                  ^ 4       XP%                  TP'                  4       TP0                  ^4       i XP-                  TP'                  4       TP2                  4       i ; i  + '       g   i     L¯; i  + '       g   i     R# ; i5i)z¤Serialize state read-modify-write across threads/processes (fcntl / msvcrt). The lock lives in a
sibling file because atomic replacement changes the target's inode.r   z.lockF)ÚstrictNT)ÚparentsÚexist_okza+bÚntó    )Ú	with_nameÚnameÚ_PLUGIN_STATE_LOCKS_GUARDr
   Ú
setdefaultr   ÚresolveÚ	threadingÚRLockÚparentÚmkdirÚopenÚosÚmsvcrtÚseekÚSEEK_ENDÚwriteÚflushÚlockingÚfilenoÚLK_LOCKÚfcntlÚflockÚLOCK_EXÚLK_UNLCKÚLOCK_UN)rb   Ú	lock_pathÚthread_lockÚhandlert   r|   s   &     r   rO   rO   h   sÊ  é € ð —‘  4§9¡9 +¨UÐ3Ó4€Iß	"Ö	"Ü)×4Ñ4´S¸×9JÑ9JÐRWÐ9JÓ9XÓ5YÔ[d×[jÒ[jÓ[lÓmˆ÷ 
#ç	ŠØ×Ñ×Ñ t°dÐÔ;Ü�)˜U×#Ô# vÜ�w‰w˜$ŒÛØ—;‘;˜q¤"§+¡+Ó.°!Ô3Ø—L‘L Ô'Ø—L‘L”NØ—‘˜A”Ø—‘˜vŸ}™}›°·±ÀÕBãØ—‘˜FŸM™M›O¨U¯]©]Ô;ð@Ûä—7‘7˜d”?Ø—K‘K ”NØ—N‘N 6§=¡=£?°F·O±OÀQÕGà—K‘K §¡£°·±Õ?÷% $÷ 
‰÷ 
#×	"Ð	"ûô$ —7‘7˜d”?Ø—K‘K ”NØ—N‘N 6§=¡=£?°F·O±OÀQÕGà—K‘K §¡£°·±Õ?ú÷% $×#ú÷ 
�ˆüsh   ‚.K°AHÁ3KÂ2J>Â7CJ+	ÆH*ÆA=J+	ÈJ>È
KÈH'	È!	KÈ*A>J(Ê(J+	Ê+J;Ê6J>Ê>K	Ë		Kc                  óª   € ] tR t^†tRtRR R llt]R R l4       t]R R l4       t]R R	 l4       t	]
R
 R l4       tR R ltRR R lltR R ltRtR# )ÚPluginStatez?Atomic, quota-bounded JSON key/value state owned by one plugin.c               ó$   € V ^8„  d   QhRRRRRR/# )r   r<   r   rZ   r   rC   r   )r   s   "r   r   ÚPluginState.__annotate__‰   s&   € ÷ Rñ R #ð R¸ð RÀTñ Rr   c                	ó&   € \        W4      V n        R # r   )r`   Ú_data_namespace)Úselfr<   rZ   s   &&&r   Ú__init__ÚPluginState.__init__‰   s   € Ü5°iÓQˆÖr   c               ó   € V ^8„  d   QhRR/# ©r   r   r   r   )r   s   "r   r   r‡   �   s   € ÷ Hñ H˜$ñ Hr   c                óF   € \        4       R,          V P                  ,          # )z@Profile-scoped directory matching portable plugins' PLUGIN_DATA.zplugin-data)r   r‰   ©rŠ   s   &r   Údata_dirÚPluginState.data_dirŒ   s   € ô Ó  =Õ0°4×3GÑ3GÕGÐGr   c               ó   € V ^8„  d   QhRR/# rŽ   r   )r   s   "r   r   r‡   ’   s   € ÷ ,ñ ,�dñ ,r   c                	ó(   € V P                   R ,          # )z
state.json)r‘   r�   s   &r   rb   ÚPluginState.path‘   s   € à�}‰}˜|Õ+Ð+r   c               ó   € V ^8„  d   QhRR/# )r   r   Úintr   )r   s   "r   r   r‡   –   s   € ÷ )ñ )˜Sñ )r   c                	ó   € \         # r   )Ú_PLUGIN_STATE_QUOTA_BYTESr�   s   &r   Úquota_bytesÚPluginState.quota_bytes•   s   € ä(Ð(r   c               ó    € V ^8„  d   QhRRRR/# )r   r   r   r   rC   r   )r   s   "r   r   r‡   š   s   € ÷ ñ ˜3ð  4ñ r   c                	óŒ   € \        V \        4      '       d#   \        P                  V 4      '       d   R V 9   d   \	        R4      hR# )z..zgPlugin state keys must be 1-128 characters using letters, numbers, '_', '-', '.', or ':' (without '..')N)r"   r   Ú_PLUGIN_STATE_KEY_REr   r#   )r   s   &r   Ú_validate_keyÚPluginState._validate_key™   sC   € ä˜#œs×#Ò#Ô+?×+IÑ+IÈ#×+NÒ+NÐRVÐZ]ÔR]Üð@óð ñ S^r   c               ó   € V ^8„  d   QhRR/# )r   r   r5   r   )r   s   "r   r   r‡   ¡   s   € ÷ 
ñ 
 ñ 
r   c                	óŽ  €  \        V P                  R R7      ;_uu_ 4       p\        P                  ! V4      pRRR4       \        X\        4      '       g   \        RT P                   R24      hT#   + '       g   i     LA; i  \         d    / u # \
        \        3 d"   p\        RT P                   RT 24      ThRp?ii ; i)z	utf-8-sig)ÚencodingNzCannot parse plugin state z: z: root must be an object)
rr   rb   ÚjsonÚloadÚFileNotFoundErrorÚOSErrorr#   ÚRuntimeErrorr"   Údict)rŠ   rƒ   ÚdataÚexcs   &   r   Ú_read_unlockedÚPluginState._read_unlocked¡   s¨   € ð	YÜ�d—i‘i¨+×6Õ6¸&Ü—y’y Ó(�÷ 7ô ˜$¤×%Ò%ÜÐ!;¸D¿I¹I¸;ÐF^Ð_Ó`Ð`Øˆ÷ 7×6ûä ô 	ØŠIÜœÐ$ô 	YÜÐ!;¸D¿I¹I¸;ÀbÈÈÐNÓOÐUXÐXûð	Yús?   ‚B ¡A1¸B Á1B	Á<B ÂB ÂCÂCÂ"CÂ#B?Â?CNc               ó$   € V ^8„  d   QhRRRRRR/# )r   r   r   r/   r   r   r   )r   s   "r   r   r‡   ­   s!   € ÷ ;ñ ;�sð ; Sð ;°Cñ ;r   c                óÚ   € V P                  V4       \        V P                  4      ;_uu_ 4        V P                  4       P	                  W4      uuRRR4       #   + '       g   i     R# ; i)z>Read a JSON value, returning *default* when the key is absent.N)rŸ   rO   rb   r¬   Úget)rŠ   r   r/   s   &&&r   r°   ÚPluginState.get­   sE   € à×Ñ˜3ÔÜ! $§)¡)×,Õ,Ø×&Ñ&Ó(×,Ñ,¨SÓ:÷ -×,×,Ó,ús   ¯AÁA*	c               ó$   € V ^8„  d   QhRRRRRR/# )r   r   r   r4   r   r   rC   r   )r   s   "r   r   r‡   ³   s!   € ÷ ;ñ ;�sð ; 3ð ;¨4ñ ;r   c           	     ó  € V P                  V4       \        V P                  4      ;_uu_ 4        V P                  4       pW#V&    \        P
                  ! VR^R7      P                  R4      p\        T4      T P                  8”  d&   \        R\        T4       RT P                   R	24      h^ R
IHp T! T P                  TRR7       RRR4       R#   \        \        3 d   p\        RT: R24      ThRp?ii ; i  + '       g   i     R# ; i)zBAtomically set one JSON value without dropping concurrent updates.F)Úensure_asciiÚindentzutf-8zPlugin state value for z is not JSON-serializableNzPlugin state quota exceeded: z bytes is greater than the z-byte per-plugin quota)Úatomic_json_writei€  )Úmode)rŸ   rO   rb   r¬   r¤   ÚdumpsÚencodeÚ	TypeErrorr#   Úlenrš   Úutilsr¶   )rŠ   r   r4   rª   Úencodedr«   r¶   s   &&&    r   ÚsetÚPluginState.set³   sú   € à×Ñ˜3ÔÜ! $§)¡)×,Õ,Ø×&Ñ&Ó(ˆDØ�‰IðfÜŸ*š* T¸ÀaÔH×OÑOÐPWÓX�ô �7‹|˜d×.Ñ.Ô.Ü Ø3´C¸³L°>ð B Ø $× 0Ñ 0Ð1Ð1GðIóð õ 0Ù˜dŸi™i¨°EÕ:÷ -Ñ,øô
 œzÐ*ô fÜ Ð#:¸3¹'ÐAZÐ![Ó\ÐbeÐeûðfú÷ -×,Ð,ús0   ¯C;Á(CÁ-AC;ÃC8Ã"C3Ã3C8Ã8C;Ã;D	)r‰   )Ú r   )Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__r‹   Úpropertyr‘   rb   rš   ÚstaticmethodrŸ   r¬   r°   r¾   Ú__static_attributes__r   r   r   r…   r…   †   sq   † ÙI÷Rð ôHó ðHð ô,ó ð,ð ô)ó ð)ð ôó ðõ
÷;÷;ñ ;r   r…   >   Úmodelr>   ÚsecurityrF   i    )&Ú__conditional_annotations__rÅ   Ú
__future__r   r¤   rs   r]   rn   Ú
contextlibr   Úpathlibr   Útypingr   r   r   Úhermes_constantsr   Úhermes_cli.plugins_manifestr	   Úcompiler   Ú	frozensetr'   rž   r™   r
   Ú__annotations__ÚLockrk   r+   r2   r9   rA   rX   r`   rO   r…   )rË   s   @r   Ú<module>rÖ      s´   øðÜ cå "ã Û 	Û 	Û Ý %Ý ß %Ñ %å ,Ý AàŸZšZÐ(LÓMÐ Ù!*Ò+WÓ!XÐ Ø—z’zÐ"HÓIÐ Ø,Ð Ø24Ð Ð/Ó 4Ø%ŸNšNÓ,Ð õõ$õõ9õXõ60ð ô@ó ð@÷:=;ó =;r   