
    FjH                        d Z ddlmZ ddlZddlZddlmZmZmZm	Z	 ddl
mZmZmZmZmZmZmZmZmZmZmZmZ d ZdddZdddZddZddZg dZdS )u@  System-prompt assembly for :class:`AIAgent`.

The agent's system prompt is built once per session and reused across all
turns — only context compression triggers a rebuild.  This keeps the
upstream prefix cache warm.  See ``hermes-agent-dev``'s
``references/system-prompt-invariant.md`` for the invariants and
``references/self-improvement-loop.md`` for how the background-review
fork inherits the cached prompt verbatim.

Three tiers are joined with ``\n\n``:

* ``stable``   — identity (SOUL.md or DEFAULT_AGENT_IDENTITY), tool
  guidance, computer-use guidance, nous subscription block, tool-use
  enforcement guidance + per-model operational guidance, skills prompt,
  alibaba model-name workaround, environment hints, platform hints.
* ``context``  — caller-supplied ``system_message`` plus context files
  (AGENTS.md / .cursorrules / etc.) discovered under ``TERMINAL_CWD``.
* ``volatile`` — memory snapshot, USER.md profile, external memory
  provider block, timestamp/session/model/provider line.

Pure helpers that read the agent's state.  AIAgent keeps thin forwarders.
    )annotationsN)AnyDictListOptional)DEFAULT_AGENT_IDENTITY!GOOGLE_MODEL_OPERATIONAL_GUIDANCEHERMES_AGENT_HELP_GUIDANCEKANBAN_GUIDANCEMEMORY_GUIDANCEOPENAI_MODEL_EXECUTION_GUIDANCEPLATFORM_HINTSSESSION_SEARCH_GUIDANCESKILLS_GUIDANCETASK_COMPLETION_GUIDANCETOOL_USE_ENFORCEMENT_GUIDANCETOOL_USE_ENFORCEMENT_MODELSc                     ddl } | S )a  Lazy reference to the ``run_agent`` module.

    Helpers like ``load_soul_md``, ``build_environment_hints``,
    ``build_context_files_prompt``, ``build_nous_subscription_prompt``,
    ``build_skills_system_prompt`` and ``get_toolset_for_tool`` are
    imported into ``run_agent``'s namespace.  Many tests
    ``patch("run_agent.load_soul_md", ...)``; if we imported them
    directly here those patches would not reach us.  Looking them up
    through ``run_agent`` on every call preserves the patch contract.
    r   N	run_agentr   s    2/usr/local/lib/hermes-agent/agent/system_prompt.py_rar   .   s         agentr   system_messageOptional[str]returnDict[str, str]c                j   "# t                      "g }d} j        s j        s-"                                }|r|                    |           d}|s|                    t
                     |                    t                     t           dd          r! j        r|                    t                     g }d j        v r|                    t                     d j        v r|                    t                     d j        v r|                    t                     t           dd          }|r|                    |           n%|#d	 j        v r|                    t                     |r(|                    d
                    |                     d j        v rddlm} |                    |           "                     j                  }|r|                    |            j        rs j        }	d}
|	du s+t'          |	t(                    r|	                                dv rd}
n|	du s+t'          |	t(                    r|	                                dv rd}
nt'          |	t,                    r7 j        pd                                #t1          #fd|	D                       }
n; j        pd                                #t1          #fdt2          D                       }
|
r}|                    t4                      j        pd                                }d|v sd|v r|                    t6                     d|v sd|v sd|v r|                    t8                     t1           fddD                       }|r:d "fd j        D             D             }"                     j        |          }nd}|r|                    |            j        dk    rQd j        v r  j                            d          d         n j        }|                    d | d! j         d"           "                                 }|r|                    |           t           d#d          r9	 dd$l!m"}  |            }|r|                    |           n# tF          $ r Y nw xY w	 dd%l$m%}  |            }n# tF          $ r d&}Y nw xY w|d&k    r|                    d'           n|                    d(| d)| d*            j&        pd                                '                                }|tP          v r!|                    tP          |                    nR|rP	 dd+l)m*} |+                    |          }|r!|j,        r|                    |j,                   n# tF          $ r Y nw xY wg }||                    |            j        sDt[          j.        d,          pd}"/                    ||-          }|r|                    |           g } j0        rp j1        r1 j0        2                    d          }|r|                    |            j3        r1 j0        2                    d.          }|r|                    |            j4        rB	  j4        5                                }|r|                    |           n# tF          $ r Y nw xY wdd/l6m7}  |            } d0| 8                    d1           }! j9        r j:        r|!d2 j:         z  }! j        r|!d3 j         z  }! j        r|!d4 j         z  }!|                    |!           d5                    d6 |D                       d5                    d7 |D                       d5                    d8 |D                       d9S ):u  Assemble the system prompt as three ordered parts.

    Returns a dict with three keys:
      * ``stable``   — identity, tool guidance, skills prompt,
        environment hints, platform hints, model-family operational
        guidance.
      * ``context``  — context files (AGENTS.md, .cursorrules, etc.)
        and caller-supplied system_message.
      * ``volatile`` — memory snapshot, user profile, external
        memory provider block, timestamp line.

    Joined into a single string by :func:`build_system_prompt` and
    cached on ``agent._cached_system_prompt`` for the lifetime of the
    AIAgent.  Hermes never re-renders parts of this string mid-
    session — that's the only way to keep upstream prompt caches
    warm across turns.
    FT_task_completion_guidancememorysession_searchskill_manage_kanban_worker_guidanceNkanban_show computer_user   )COMPUTER_USE_GUIDANCE>   onyestruealways>   noofffalsenever c              3  n   K   | ]/}t          |t                    |                                v V  0d S N)
isinstancestrlower.0pmodel_lowers     r   	<genexpr>z,build_system_prompt_parts.<locals>.<genexpr>   sA      [[q
STVYHZHZ[!'')){2[[[[[[r   c              3      K   | ]}|v V  	d S r3    r7   s     r   r;   z,build_system_prompt_parts.<locals>.<genexpr>   s(      PPq!{*PPPPPPr   geminigemmagptcodexgrokc              3  *   K   | ]}|j         v V  d S r3   )valid_tool_names)r8   namer   s     r   r;   z,build_system_prompt_parts.<locals>.<genexpr>   s+      ttd45#99ttttttr   )skills_list
skill_viewr#   c                    h | ]}||S r=   r=   )r8   toolsets     r   	<setcomp>z,build_system_prompt_parts.<locals>.<setcomp>   s0     
 
 
 

 
 
r   c              3  B   K   | ]}                     |          V  d S r3   )get_toolset_for_tool)r8   	tool_name_rs     r   r;   z,build_system_prompt_parts.<locals>.<genexpr>   sB        7@''	22     r   )available_toolsavailable_toolsetsalibaba/z#You are powered by the model named z. The exact model ID is zt. When asked what model you are, always answer based on this information, not on any model name returned by the API._environment_probe)get_environment_probe_line)_resolve_active_profile_namedefaulta6  Active Hermes profile: default. Other profiles (if any) live under ~/.hermes/profiles/<name>/. Each profile has its own skills/, plugins/, cron/, and memories/ that affect a different session than this one. Do not modify another profile's skills/plugins/cron/memories unless the user explicitly directs you to.zActive Hermes profile: z3. This session reads and writes ~/.hermes/profiles/u  /. The default profile's data lives at ~/.hermes/skills/, ~/.hermes/plugins/, ~/.hermes/cron/, ~/.hermes/memories/ — those belong to a different session run from a different shell. Do NOT modify another profile's skills/plugins/cron/memories unless the user explicitly directs you to. The cross-profile write guard will refuse such writes by default; pass cross_profile=True only after explicit direction.)platform_registryTERMINAL_CWD)cwd	skip_souluser)nowzConversation started: z%A, %B %d, %Yz
Session ID: z
Model: z
Provider: 

c              3  j   K   | ].}||                                 |                                 V  /d S r3   stripr8   r9   s     r   r;   z,build_system_prompt_parts.<locals>.<genexpr>V  <      UUaQU17799U		UUUUUUr   c              3  j   K   | ].}||                                 |                                 V  /d S r3   r`   rb   s     r   r;   z,build_system_prompt_parts.<locals>.<genexpr>W  rc   r   c              3  j   K   | ].}||                                 |                                 V  /d S r3   r`   rb   s     r   r;   z,build_system_prompt_parts.<locals>.<genexpr>X  rc   r   )stablecontextvolatile);r   load_soul_identityskip_context_filesload_soul_mdappendr   r
   getattrrD   r   r   r   r   r   joinagent.prompt_builderr(   build_nous_subscription_prompt_tool_use_enforcementr4   r5   r6   listmodelanyr   r   r	   r   build_skills_system_promptprovidersplitbuild_environment_hintstools.env_proberU   	Exceptionagent.file_safetyrV   platformra   r   gateway.platform_registryrX   getplatform_hintosgetenvbuild_context_files_prompt_memory_store_memory_enabledformat_for_system_prompt_user_profile_enabled_memory_managerbuild_system_prompthermes_timer]   strftimepass_session_id
session_id)$r   r   stable_parts_soul_loaded_soul_contenttool_guidance_kanban_guidancer(   nous_subscription_prompt_enforce_inject_model_lowerhas_skills_toolsavail_toolsetsskills_prompt_model_short
_env_hintsrU   _probe_linerV   active_profileplatform_keyrX   _entrycontext_parts_context_cwdcontext_files_promptvolatile_parts	mem_block
user_block_ext_mem_block_hermes_nowr]   timestamp_linerN   r:   s$   `                                 @@r   build_system_prompt_partsr   =   s	   * 
B !L
 L  u'?  )) 	 ...L 42333 2333 u1488 6U=S 64555 M5)))_---51114555///_---
 u&?FF .-....		!mu7M&M&M_--- 5CHH]33444 ///>>>>>>1222!@@AWXX 64555  E.t
8S 9 9hnn>N>NRq>q>qGG:h#<#<AQAQUtAtAtGG$'' 	Q ;,"3355K[[[[H[[[[[GG !;,"3355KPPPP4OPPPPPG 	E =>>>!K-24466L <''7l+B+B##$EFFF $$<(?(?6\CYCY##$CDDDttttFsttttt 
 
   DIDZ  
 
 
 55!2- 6 
 

  +M*** ~""58EK5G5Gu{((--b11U[:, : :%*[: : :	
 	
 	
 ++--J (J''' u*D11 	BBBBBB4466K 1##K000 	 	 	D	#BBBBBB5577 # # #"#""	
 	
 	
 	
 	)n ) )-;) ) )
	
 
	
 
	
 N(b//117799L~%%N<89999	 	CCCCCC&**<88F :&. :##F$8999 	 	 	D	  "M !^,,,# 	7
 y008D!<<  =  6  6 	7  !5666 !#N 	2  	1+DDXNNI 1%%i000& 	2,EEfMMJ 2%%j111  	"2FFHHN 6%%n555 	 	 	D	 /.....
+--C Ncll?.K.KMMN >!1 >=5+;==={ 43ek333~ :9999.))) KKUU<UUUUUKKUU=UUUUUKKUU>UUUUU  sH   5'R 
R*)R*.R? ?SS#>V" "
V/.V/0[ 
[[r5   c                    t          | |          }d                    d |d         |d         |d         fD                       S )u  Assemble the full system prompt from all layers.

    Called once per session (cached on ``agent._cached_system_prompt``) and
    only rebuilt after context compression events. This ensures the system
    prompt is stable across all turns in a session, maximizing prefix cache
    hits.

    Layers are ordered cache-friendly: stable identity/guidance first,
    then session-stable context files, then per-call volatile content
    (memory, USER profile, timestamp).  The whole string is treated as
    one cached block — Hermes never rebuilds or reinjects parts of it
    mid-session, which is the only way to keep upstream prompt caches
    warm across turns.
    )r   r^   c              3     K   | ]}||V  	d S r3   r=   rb   s     r   r;   z&build_system_prompt.<locals>.<genexpr>l  s(      ^^Q\]^q^^^^^^r   rf   rg   rh   )r   rn   )r   r   partss      r   r   r   \  sL     &eNKKKE;;^^5?E)4DeJFW"X^^^^^^r   Nonec                X    d| _         | j        r| j                                         dS dS )zInvalidate the cached system prompt, forcing a rebuild on the next turn.

    Called after context compression events. Also reloads memory from disk
    so the rebuilt prompt captures any writes from this session.
    N)_cached_system_promptr   load_from_disk)r   s    r   invalidate_system_promptr   o  s<     #'E -**,,,,,- -r   c                    | j         sdS g }| j         D ]T}|d         }|d         |                    dd          |                    di           dd}|                    |           Ut          j        |d	
          S )zFormat tool definitions for the system message in the trajectory format.

    Returns:
        str: JSON string representation of tool definitions
    z[]functionrE   descriptionr1   
parametersN)rE   r   r   requiredF)ensure_ascii)toolsr~   rl   jsondumps)r   formatted_toolstoolfuncformatted_tools        r   format_tools_for_system_messager   z  s     ; t O / /JL88M266((<44	
 
 	~....:oE::::r   )r   r   r   r   r3   )r   r   r   r   r   r   )r   r   r   r   r   r5   )r   r   r   r   )r   r   r   r5   )__doc__
__future__r   r   r   typingr   r   r   r   ro   r   r	   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r   __all__r=   r   r   <module>r      sn   . # " " " " "  				 , , , , , , , , , , , ,                              \ \ \ \ \~_ _ _ _ _&- - - -; ; ; ;0  r   