
    sj.                        U 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 ddlmZ ddlmZ ddlmZmZmZ  ej        e          Zi ae
ee
ee	f         f         ed<   daee         ed	<   daee         ed
<    ej                    Z  ej!        d          Z" ej!        d          Z#dZ$dZ%dZ&dZ'dZ(dZ)dZ* ej!         ej+        e$          dz             Z,e$dz   Z-dZ.de/dedefdZ0de	dee         fdZ1d?de	dedee         fdZ2d edee         fd!Z3d edee         fd"Z4dee         fd#Z5defd$Z6d@d%ed&edz  de7e8ee	f         edz  ef         dz  fd'Z9d(e8ee	f         de/e         ddfd)Z:	 	 	 dAd(e8ee	f         d+edz  d,ed-ed.ed/edz  defd0Z;de
ee
ee	f         f         fd1Z<de
ee
ee	f         f         fd2Z=de
ee	f         fd3Z>d4edee         fd5Z?	 	 	 dBd6ed-ed&edz  d.edee         f
d7Z@d8ZAd9ede7e/e         ef         fd:ZB	 	 dCd;e/e         d-ed&edz  dee7ee/e         e/e         f                  fd<ZC	 d@d=e/e         d&edz  de7ee/e         e/e         f         fd>ZDdS )DzShared slash command helpers for skills.

Shared between CLI (cli.py) and gateway (gateway/run.py) so both surfaces
can invoke skills via /skill-name commands.
    N)Path)AnyDictOptional)display_hermes_home)register_stable_prefix)expand_inline_shellload_skills_configsubstitute_template_vars_skill_commands_skill_commands_platform_skill_commands_homez
[^a-z0-9-]z-{2,}z%[IMPORTANT: The user has invoked the z(The full skill content is loaded below.]zPThe user has provided the following instruction alongside the skill invocation: z

[Runtime note:z skill bundle,z
User instruction: z

[Loaded as part of the z	"([^"]*)"%partsinstructionreturnc                     d                     |           dz   t          z   }|                     t           |            |S )u  Append the instruction line to ``parts``; return the stable prefix.

    Shared by every builder that ends a static skill scaffold with the
    caller-supplied volatile instruction (single-skill invocations, cron job
    prompts). The returned prefix ends exactly at the instruction marker, so
    registering it with ``agent.prompt_cache_boundary`` lets the Anthropic
    cache planner put a breakpoint on the scaffold instead of caching the
    whole message as one atomic block (#81867). Keeping construction in one
    place guarantees the registered prefix stays a byte-prefix of the built
    message — the invariant the request-time split depends on.
    
)join_SINGLE_SKILL_INSTRUCTIONappend)r   r   stable_prefixs      8/home/agent/.hermes/hermes-agent/agent/skill_commands.pyappend_user_instructionr   P   sD     IIe$$t+.GGM	LL-<{<<===    contentc                     t          | t                    sdS |                     t                    s| S t          | v rt          |           S t          | v rt          |           S dS )u(  Recover the user's instruction from a slash-skill-expanded turn.

    Returns:
        - The original string unchanged when it is NOT skill scaffolding
          (a normal user message passes straight through).
        - The extracted user instruction when the scaffolding carried one.
        - ``None`` when the content is skill scaffolding with no user
          instruction (i.e. a bare ``/skill`` invocation). Callers that feed
          memory providers should skip the turn in that case — there is no
          user content worth storing.
    N)
isinstancestr
startswith_SKILL_INVOCATION_PREFIX_BUNDLE_MARKER _extract_bundle_user_instruction_SINGLE_SKILL_MARKER&_extract_single_skill_user_instruction)r   s    r   +extract_user_instruction_from_skill_messager'   a   sn     gs## t677   /888w&&5g>>>4r       — 	separatorc                    t          | t                    r|                     t                    sdS t                              |           }|r|                    d          nd                                }|                    d          r|nd| }t          |           }|rY|| urU|	                    t                    d         }d                    |	                                          }|r|r| | | n|S |r|ndS )u   Render a slash-skill-expanded turn the way the user typed it.

    The expanded message embeds the whole skill body, so any surface that
    summarizes a user turn from its raw content — session titles, sidebar
    previews, the ``/rewind`` picker — otherwise shows the skill's own prose
    as if the user had written it. That is how a skill's opening line ends up
    as a session title.

    Returns ``"/work — fix the title leak"``, or ``"/work"`` for a bare
    invocation, or ``None`` when *content* is not skill scaffolding (the
    caller should then summarize it as an ordinary message).

    *separator* joins the command and the instruction. Previews use the
    default em dash; pass ``" "`` for the literal invocation the user typed,
    which is what chat transcripts render.
    N    /r    )r   r    r!   r"   _SKILL_NAME_REmatchgroupstripr'   splitSKILL_EXCERPT_JOINTr   )r   r)   r0   namelabelr   s         r   describe_skill_invocationr7   |   s   " gs## 7+=+=>V+W+W t  ))E#+EKKNNN2244D OOC((8DDj$jjE=gFFK O{'11 "''(;<<Q?hh{002233 	O9=Ne5Y5555;N"55d"r   messagec                    |                      t                    }|dk     rd S | |t          t                    z   d          }|                    t                    }|dk    r
|d |         }|                                }|pd S Nr   )rfindr   lenfind_RUNTIME_NOTEr2   )r8   
marker_idxr   runtime_idxs       r   r&   r&      s     899JA~~t*s+D'E'EEFFGK""=11Ka!,;,/##%%K$r   c                    |                      t                    }|dk     rd S | |t          t                    z   d          }|                     t                    }|dk    r
|d |         }|                                }|pd S r:   )r=   _BUNDLE_USER_INSTRUCTIONr<   _BUNDLE_FIRST_SKILL_BLOCKr2   )r8   r?   r   first_skill_idxs       r   r$   r$      s     677JA~~t*s+C'D'DDEEFK!&&'@AAO!!"2?"23##%%K$r   c                      	 ddl m}  t          j        d          p
 | d          }n$# t          $ r t          j        d          }Y nw xY w|pdS )a  Return the current platform scope used for disabled-skill filtering.

    Used to detect when the active platform has shifted so
    :func:`get_skill_commands` can drop a stale cache that was populated
    for a different platform's ``skills.platform_disabled`` view (#14536).

    Resolves from (in order) ``HERMES_PLATFORM`` env var and
    ``HERMES_SESSION_PLATFORM`` from the gateway session context. Returns
    ``None`` when no platform scope is active (e.g. classic CLI, RL
    rollouts, standalone scripts).
    r   )get_session_envHERMES_PLATFORMHERMES_SESSION_PLATFORMN)gateway.session_contextrF   osgetenv	Exception)rF   resolved_platforms     r    _resolve_skill_commands_platformrN      s    9;;;;;; I'(( :899 	  9 9 9I&7889$$s   %( A	A	c                  <    ddl m}  t           |                       S )a  Return the effective Hermes home the skill scan should be scoped to.

    A gateway session can switch between profiles that each carry their own
    ``skills.external_dirs`` (via ``set_hermes_home_override``), but the
    module-level scan only tracked ``_resolve_skill_commands_platform()``.
    Switching profiles without a platform change left the previous profile's
    skill list cached, so ``get_skill_commands()`` reported a cache miss for
    skills that only exist under the new profile (#88023).
    r   get_hermes_home)hermes_constantsrQ   r    rP   s    r   _resolve_skill_commands_homerS      s,     100000  !!!r   skill_identifiertask_idc                 B   | pd                                 }|sdS 	 ddlm}m} ddlm}  ||          }t          j         |||d                    }n# t          $ r Y dS w xY w|	                    d          sdS t          |	                    d	          p|          }t          |	                    d
          pd          }	d}
|	                    d          }|rt          |          }
n-|	r+	 |t          |	          j        z  }
n# t          $ r d}
Y nw xY w||
|fS )zOLoad a skill by name/path and return (loaded_payload, skill_dir, display_name).r,   Nr   )
SKILLS_DIR
skill_view)normalize_skill_lookup_nameF)rU   
preprocesssuccessr5   path	skill_dir)r2   tools.skills_toolrW   rX   agent.skill_utilsrY   jsonloadsrL   getr    r   parent)rT   rU   raw_identifierrW   rX   rY   
normalizedloaded_skill
skill_name
skill_pathr]   abs_skill_dirs               r   _load_skill_payloadrj      s   &,"3355N t
<<<<<<<<AAAAAA00@@
zJz7uEEE
 
    tt I&& t\%%f--;<<J\%%f--344JI
 !$$[11M ''			 	"T*%5%5%<<II 	 	 	III	 J..s#   9A 
A$#A$2D
 
DDrf   c                    	 ddl m}m}m} t	          |                     d          p|                     d          pd          }|sdS  ||          \  }} ||          }|sdS  ||          }	|	sdS ddt                       dg}
|	                                D ]3\  }}|rt	          |          nd	}|
                    d
| d|            4|
                    d           |	                    |
           dS # t          $ r Y dS w xY w)ae  Resolve and inject skill-declared config values into the message parts.

    If the loaded skill's frontmatter declares ``metadata.hermes.config``
    entries, their current values (from config.yaml or defaults) are appended
    as a ``[Skill config: ...]`` block so the agent knows the configured values
    without needing to read config.yaml itself.
    r   )extract_skill_config_varsparse_frontmatterresolve_skill_config_valuesraw_contentr   r,   Nz[Skill config (from z/config.yaml):z	(not set)z  z = ])r_   rl   rm   rn   r    rb   r   itemsr   extendrL   )rf   r   rl   rm   rn   ro   frontmatter_config_varsresolvedlineskeyvaluedisplay_vals                 r   _inject_skill_configr{     s   	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 ,**=99^\=M=Mi=X=X^\^__ 	F**;77Q//<< 	F..{;; 	FQ,?,A,AQQQR"..** 	5 	5JC(->#e***;KLL3c33k334444SU   s%   AC= 	C= &C= 5BC= =
D
Dr,   r]   activation_noteuser_instructionruntime_note
session_idc                 J   ddl m} t          |                     d          pd          }t	                      }|                    dd          rt          |||          }|                    dd          r6t          |                    d	d
          pd
          }	t          |||	          }|d|                                g}
|rC|
	                    d           |
	                    d| d           |
	                    d           t          | |
           |                     d          r|
                    ddg           n|                     d          r"|
                    dd| d          dg           nK|                     d          r6|                     d          r!|
                    dd| d          dg           g }|                     d          pi }|                                D ],}t          |t                    r|                    |           -|s|rdD ]}||z  }|                                rt!          |                    d                    D ]a}|                                rK|                                s7t          |                    |                    }|	                    |           b|r|r	 t          |                    |                    }n# t*          $ r
 |j        }Y nw xY w|
	                    d           |
	                    d           |D ] }|
	                    d| d||z              !|
	                    d| d| d           d}|r%|
	                    d           t/          |
|          }|r.|
	                    d           |
	                    d| d           d                    |
          }|D|                    |          r/t5          |          t5          |          k    rt7          |           |S ) z9Format a loaded skill into a user/system message payload.r   )rW   r   r,   template_varsTinline_shellFinline_shell_timeout
   z[Skill directory: rp   zResolve any relative paths in this skill (e.g. `scripts/foo.js`, `templates/config.yaml`) against that directory, then run them with the terminal tool using the absolute path.setup_skippedz[Skill setup note: Required environment setup was skipped. Continue loading the skill and explain any reduced functionality if it matters.]gateway_setup_hintz[Skill setup note: setup_needed
setup_notelinked_files)
references	templatesscriptsassets*z"[This skill has supporting files:]z- z  ->  z)
Load any of these with skill_view(name="zM", file_path="<path>"), or run scripts directly by absolute path (e.g. `node z/scripts/foo.js`).Nz[Runtime note: r   )r^   rW   r    rb   _load_skills_config_substitute_template_varsint_expand_inline_shellr2   r   r{   rr   valuesr   listexistssortedrglobis_file
is_symlinkrelative_to
ValueErrorr5   r   r   r!   r<   r   )rf   r]   r|   r}   r~   r   rW   r   
skills_cfgtimeoutr   
supportingr   entriessubdirsubdir_pathfrelskill_view_targetsfr   r8   s                         r   _build_skill_messager   7  s    -,,,,,,""9--344G
 %&&J~~ot,, L+GY
KK~~ne,, Djnn%;R@@FBGG&w	7CCb'--//2E  
R6)666777>	
 	
 	
 u---(( 
 ^	
 	
 	
 	
 
		.	/	/ 
Kl3G&HKKK	
 	
 	
 	
 
		.	)	) 
l.>.>|.L.L 
Cl<&@CCC	
 	
 	
 J##N339rL&&(( ' 'gt$$ 	'g&&& /) /F 	/ 	/F#f,K!!## / 1 1# 6 677 / /Ayy{{ /1<<>> /!!--	":":;;"))#... 
i 
	/ #I$9$9*$E$E F F 	/ 	/ 	/ )	/ 	R9::: 	: 	:BLL8b88	B88999999J 9 9$9 9 9	
 	
 	
 M IR 07GHH 8R6|666777iiG W%7%7%F%F 3w<<Z]^kZlZlKlKl}---Ns   "K/ /LLc            	         t                      } t                      }i }	 ddlm}m}m}m}m} ddlm	}m
}	m}
m} ddlm}  |            }t                      }t!           |	                      }t!          |          }|                                r|                    |           |                     |                       |D ]`}||v r |
|          n ||d          }|D ]>}t)          d |j        D                       r"	 |                    d          } ||          \  }} ||          sS ||          s_|                    d	|j        j                  }||v r||v r|                    d
d          }|sa|                                                    d          D ]9}|                                }|r!|                    d          s|dd         } n:|                    |           |                                                    dd                              dd          }t@          !                    d|          }tD          !                    d|                              d          }|s ||          tF          $                    d|||           d| }||v r+tF          $                    d||||         d	                    ||pd| dtK          |          tK          |j                  d||<   /# tL          $ r Y <w xY wbn# tL          $ r Y nw xY wtN          5  |a(| a)|a*ddd           n# 1 swxY w Y   |S )zScan ~/.hermes/skills/ and return a mapping of /command -> skill info.

    Returns:
        Dict mapping "/skill-name" to {name, description, skill_md_path, skill_dir}.
    r   )rW   _parse_frontmatterskill_matches_platformskill_matches_environment_get_disabled_skill_names)get_external_skills_dirsget_project_skills_dirsiter_project_skill_filesiter_skill_index_files)resolve_commandzSKILL.mdc              3      K   | ]}|d v V  	dS )>   .git.hub.github.archiveN ).0parts     r   	<genexpr>z&scan_skill_commands.<locals>.<genexpr>  s(      bb4tFFbbbbbbr   zutf-8)encodingr5   descriptionr,   r   #NP   r.   -rt   zSkill %r generates slash command '/%s' which collides with a core Hermes command; skipping auto-registration. Use '/skill %s' instead.r-   zaSkill %r maps to slash command %s already claimed by %r; keeping the first and skipping this one.zInvoke the z skill)r5   r   skill_md_pathr]   )+rN   rS   r^   rW   r   r   r   r   r_   r   r   r   r   hermes_cli.commandsr   setr   r   r   rr   anyr   	read_textrb   rc   r5   r2   r3   r!   addlowerreplace_SKILL_INVALID_CHARSsub_SKILL_MULTI_HYPHENloggerwarningr    rL   _publish_lockr   r   r   )platformhomecommandsrW   r   r   r   r   r   r   r   r   r   disabled
seen_namesproject_dirsdirs_to_scanscan_dir_iterskill_mdr   rs   bodyr5   r   linecmd_namecmd_keys                               r   scan_skill_commandsr     s    011H'))D +-H_ 	S  	S  	S  	S  	S  	S  	S  	S  	S  	S  	S  	S  	S  	S	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	877777,,..%%
 335566L)) 	,
+++4466777$ I	 I	H |++ )(222++HjAA 
 " C CbbS[Sabbbbb @&00'0BBG(:(:7(C(C%K11+>> !  54[AA ! &??68?3GHHDz)) x'' "-//-"D"DK& &$(JJLL$6$6t$<$< & &D#'::<<D# &DOOC,@,@ &.23B3i %NN4(((  $zz||33C==EEc3OOH377HEEH266sHEEKKCPPH# !  'x00<J !(D	   !
 -(nnG(**N '8G+<V+D  
 ! $'2'P6PD6P6P6P),X%(%9%9	) )HW%% !   HECI	T     
 $ $"#+ #$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ Os   C(L) 	/L8L) 9LL) $L)L) *L.L) /DLL) (L.L) 02L"L) $/LL) 
L#L) "L##L) )
L65L6 MMMc                      t                      } t                      }t          5  t          }t	          |          ot
          | k    o
t          |k    }ddd           n# 1 swxY w Y   |r|S t                      S )a  Return the current skill commands mapping (scan first if empty).

    Rescans when the active platform scope changes (e.g. a gateway
    process serving Telegram and Discord concurrently) so each platform
    sees its own ``skills.platform_disabled`` view (#14536), and when the
    active profile's Hermes home changes (e.g. Desktop switching profiles
    mid-session) so each profile sees its own ``skills.external_dirs`` (#88023).
    N)rN   rS   r   r   boolr   r   r   )current_platformcurrent_homer   is_freshs       r   get_skill_commandsr   &  s     899/11L 
 
 
"NN 5(,<<5$4 	
 
 
 
 
 
 
 
 
 
 
 
 
 
 
      s   -AA!$A!c                  l   dt           t          t           t          t          f         f         dt           t          t          f         fd}  | t                    t	                      } | |          t          t                    t                    z
            }t          t                    t                    z
            }t          t                    t                    z            }fd|D             }fd|D             }|||t                    t          |          dS )u  Re-scan the skills directory and return a diff of what changed.

    Rescans ``~/.hermes/skills/`` and any ``skills.external_dirs`` so the
    slash-command map (``agent.skill_commands._skill_commands``) reflects
    skills added or removed on disk.

    This does NOT invalidate the skills system-prompt cache. Skills are
    called by name via ``/skill-name``, ``skills_list``, or ``skill_view``
    — they don't need to be in the system prompt for the model to use them.
    Keeping the prompt cache intact preserves prefix caching across the
    reload, so a user invoking ``/reload-skills`` pays no cache-reset cost.

    Returns:
        Dict with keys::

            {
              "added":      [{"name": str, "description": str}, ...],
              "removed":    [{"name": str, "description": str}, ...],
              "unchanged":  [skill names present before and after],
              "total":      total skill count after rescan,
              "commands":   total /slash-skill count after rescan,
            }

        ``description`` is the skill's full SKILL.md frontmatter
        ``description:`` field. Note: the system prompt skill index
        truncates this to the first 57 chars; see ``extract_skill_description``.
    cmdsr   c                     i }|                                  D ]6\  }}|                    d          }|pi                     d          pd||<   7|S )Nr-   r   r,   )rq   lstriprb   )r   out	slash_keyinfobares        r   	_snapshotz reload_skills.<locals>._snapshota  s\     #zz|| 	> 	>OIt##C((D((77=2CII
r   c                 &    g | ]}||         d S )r5   r   r   )r   nafters     r   
<listcomp>z!reload_skills.<locals>.<listcomp>t  s%    GGGaaa11GGGr   c                 &    g | ]}||         d S r   r   )r   r   befores     r   r   z!reload_skills.<locals>.<listcomp>w  s%    LLL&)44LLLr   )addedremoved	unchangedtotalr   )r   r    r   r   r   r   r   r<   )	r   new_commandsadded_namesremoved_namesr   r   r   r   r   s	          @@r   reload_skillsr   A  s+   @S$sCx.01 d38n     Y''F '((LIl##EUc&kk122K3v;;U344Ms5zzCKK/00IGGGG;GGGE MLLLmLLLG U%%  r   commandc                 d    | sdS d|                      dd           }|t                      v r|ndS )uV  Resolve a user-typed /command to its canonical skill_cmds key.

    Skills are always stored with hyphens — ``scan_skill_commands`` normalizes
    spaces and underscores to hyphens when building the key. Hyphens and
    underscores are treated interchangeably in user input: this matches
    ``_check_unavailable_skill`` and accommodates Telegram bot-command names
    (which disallow hyphens, so ``/claude-code`` is registered as
    ``/claude_code`` and comes back in the underscored form).

    Returns the matching ``/slug`` key from ``get_skill_commands()`` or
    ``None`` if no match.
    Nr-   rt   r   )r   r   )r   r   s     r   resolve_skill_command_keyr     sG      t-'//#s++--G!3!5!555774?r   r   c                    t                      }|                    |           }|sdS t          |d         |          }|sdS |\  }}}		 ddlm}
  |
|	|           n# t
          $ r Y nw xY wd|	 d}t          ||||||          S )	aE  Build the user message content for a skill slash command invocation.

    Args:
        cmd_key: The command key including leading slash (e.g., "/gif-search").
        user_instruction: Optional text the user typed after the command.

    Returns:
        The formatted message string, or None if the skill wasn't found.
    Nr]   rU   r   bump_use&[IMPORTANT: The user has invoked the "zf" skill, indicating they want you to follow its instructions. The full skill content is loaded below.])r}   r~   r   )r   rb   rj   tools.skill_usager   rL   r   )r   r}   rU   r~   r   
skill_infoloadedrf   r]   rg   r   r|   s               r   build_skill_invocation_messager    s     "##Hg&&J t K!8'JJJF t*0'L)Z......W-----   	S 	S 	S 	S   )!   s   
A 
A+*A+   restc                    g }| pd}t          |          t          dz
  k     r|                                }|                    d          sn|                    dd          }|d         }t          |          dk    r|d         nd}t          |                    d                    }|||v rn2|                    |           |}t          |          t          dz
  k     ||                                fS )u  Consume additional leading ``/skill`` tokens from *rest*.

    *rest* is the text that follows the FIRST matched skill command (the
    caller has already resolved that one). Leading whitespace-delimited
    tokens that start with ``/`` and resolve to installed skill commands are
    consumed, up to ``_MAX_STACKED_SKILLS`` total leading skills (i.e. at
    most ``_MAX_STACKED_SKILLS - 1`` extra keys here). Parsing stops at the
    first token that is not a resolvable skill command — that token and
    everything after it become the user instruction.

    Returns:
        ``(extra_cmd_keys, remaining_instruction)`` where ``extra_cmd_keys``
        are canonical ``/slug`` keys from :func:`get_skill_commands`.
    r,   r+   r-   Nr   )r<   _MAX_STACKED_SKILLSr   r!   r3   r   r   r2   )r  keys	remainingstrippedr   tokentailr   s           r   split_stacked_skill_commandsr    s     D
I
d)))A-
-
-##%%""3'' 	tQ''au::>>uQxxr+ELL,=,=>>?gooG	 d)))A-
-
- """"r   cmd_keysc           	         t                      }g }g }g }t                      }| D ]}|r||v r
|                    |           |                    |          }	|	s)|                    |                    d                     _t          |	d         |          }
|
s)|                    |                    d                     |
\  }}}	 ddlm}  |||           n# t          $ r Y nw xY wd| d}|                    t          ||||                     |                    |           |sd	S d
                    d | D                       }d| dt          |           dddd                    |           g}|r+|                    dd                    |                      |r|                    dd| g           d                    |          }d                    |g|          ||fS )ar  Build the user message for a stacked multi-skill slash invocation.

    Args:
        cmd_keys: Canonical ``/slug`` keys, in the order the user typed them.
        user_instruction: Text remaining after the leading skill commands.

    Returns:
        ``(message, loaded_skill_names, missing_skill_names)`` or ``None``
        when no skill could be loaded at all.
    r-   r]   r   r   r   z1[Loaded as part of the stacked skill invocation "z".]r   Nr.   c              3      K   | ]}||V  	d S Nr   )r   ks     r   r   z9build_stacked_skill_invocation_message.<locals>.<genexpr>6  s'      ..1A.Q......r   r  z " stacked skill bundle, loading zL skills together. Treat every skill below as active guidance for this turn.]r,   zSkills loaded: z, zSkills missing (skipped): zUser instruction: r   

)r   r   r   rb   r   r   rj   r  r   rL   r   r   r<   rr   )r  r}   rU   r   loaded_namesmissingskill_blocksseenr   r  r  rf   r]   rg   r   r|   typedheader_linesheaders                      r   &build_stacked_skill_invocation_messager    s    "##H LG LUUD $( $( 	'T//\\'**
 	NN7>>#..///$Z%<gNNN 	NN7>>#..///.4+i	222222HZ11111 	 	 	D	 P
OOO 	 	 "	  	
 	
 	
 	J'''' t HH.......E	- 	- 	-|$$	- 	- 	- 	3$))L1133L  OM79K9KMMNNN KR!H6F!H!HIJJJYY|$$FKK/,/00,HHs   C!!
C.-C.skill_identifiersc           	         g }g }g }	 ddl m}  |            }n# t          $ r t                      }Y nw xY wt                      }| D ]}|pd                                }	|	r|	|v r|                    |	           t          |	|          }
|
s|                    |	           ]|
\  }}}||v s|	|v r|                    |	           	 ddlm	}  |||           n# t          $ r Y nw xY wd| d}|                    t          ||||                     |                    |           d	                    |          ||fS )
uD  Load one or more skills for session-wide CLI/TUI preloading.

    Returns (prompt_text, loaded_skill_names, missing_identifiers).

    Disabled skills are treated the same as missing ones: this loads via a
    raw identifier straight into ``_load_skill_payload``, bypassing
    ``get_skill_commands()``'s scan-time disabled filter — mirrors the
    bundle-invocation gate (#59156). Without this, ``hermes -s <skill>`` or
    a deployment's ``HERMES_TUI_SKILLS`` env var could force-load a skill an
    operator disabled via ``skills.disabled``/``skills.platform_disabled``.
    r   )get_disabled_skill_namesr,   r   r   z9[IMPORTANT: The user launched this CLI session with the "z~" skill preloaded. Treat its instructions as active guidance for the duration of this session unless the user overrides them.]r  r  )r_   r!  rL   r   r2   r   rj   r   r  r   r   r   )r  rU   prompt_partsr  r  r!  disabled_namesr  rd   
identifierr  rf   r]   rg   r   r|   s                   r   build_preloaded_skills_promptr%  G  s    !L LG>>>>>>1133    UUD+ %( %($*1133
 	Z4//$ZAAA 	NN:&&&.4+i'':+G+GNN:&&&	222222HZ11111 	 	 	D	7
 7 7 7 	
 	 "	  	
 	
 	
 	J'''';;|$$lG;;s    44	C
C*)C*)r(   r  )r,   r,   N)r,   Nr,   )r,   N)E__doc__r`   loggingrJ   re	threadingpathlibr   typingr   r   r   rR   r   agent.prompt_cache_boundaryr   agent.skill_preprocessingr	   r   r
   r   r   r   	getLogger__name__r   r   r    __annotations__r   r   Lockr   compiler   r   r"   r%   r   r>   r#   rB   rC   escaper/   SKILL_SCAFFOLD_SQL_LIKEr4   r   r   r'   r7   r&   r$   rN   rS   tupledictrj   r{   r   r   r   r   r   r  r	  r  r  r%  r   r   r   <module>r7     s
       				 				           & & & & & & & & & & 0 0 0 0 0 0 > > > > > >          
	8	$	$-/c4S>)* / / /*. (3- . . .&* hsm * * * 	  !rz-00  bj** ( C A V  %!1 9  IBI&>??,NOO
 3S8   4 c c    " #    6$# $#s $#s $#RU $# $# $# $#NC HSM    c hsm    %(3- % % % %0"c " " " "%/ %/# %/d
 %/eTXY\^aYaTbdhkodoqtTtNux|N| %/ %/ %/ %/P$tCH~ $d3i $D $ $ $ $V !n nsCx.nd{n n 	n
 n d
n 	n n n nb{T#tCH~"56 { { { {|!Dd38n!45 ! ! ! !6>tCH~ > > > >B@s @x} @ @ @ @* 	, ,,, 4Z, 	,
 c], , , ,z  #s #uT#Y^/D # # # #D OI OI3iOIOI 4ZOI eCcDI-./	OI OI OI OIh A< A<CyA<4ZA< 3S	49$%A< A< A< A< A< A<r   