Ë
    ãß²jÔQ  ã                  óÊ  — d Z ddlmZ ddl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  ej                  d«      Zd#d„Zd$d„Zd	d
dœd%d„Z eh d£«      Z eh d£«      Zd&d„Zd'd„Zd(d„Zd)d„Zd*d„ZdZdZdZd+d„Zd,d„Zd-d„Z d.d„Z!d/d„Z" ejF                  «       Z$ ejJ                  «       Z& ejJ                  «       Z'd„ Z(d0d„Z)d1d„Z*d2d„Z+d3d „Z,	 	 	 	 	 	 	 	 d4d!„Z-d5d6d"„Z.y)7zmSubagent result post-processing: summary budget/spill, tool-trace summaries, lifecycle hooks and cost rollup.é    )ÚannotationsN)ÚAnyÚDictÚListÚOptional)ÚurlsplitÚ
urlunsplitztools.delegate_toolc                óê   — | €yt        | t        «      r| S t        | t        «      rdj                  d„ | D «       «      S t        | t        «      rt        j                  | dt        ¬«      S t        | «      S )z‰Stable text for tool-result content. Some OpenAI-compatible paths return
    content-block lists; observability must never crash on them.Ú Ú
c              3  óò   K  — | ]o  }t        |t        «      r$t        |j                  d «      t        «      r|d    n6t        |t        «      rt	        j
                  |dt        ¬«      n
t        |«      –— Œq y­w)ÚtextF©Úensure_asciiÚdefaultN)Ú
isinstanceÚdictÚgetÚstrÚjsonÚdumps)Ú.0Úitems     ú@/home/ubuntu/.hermes/hermes-agent/tools/delegate_tool_results.pyú	<genexpr>z*_stringify_tool_content.<locals>.<genexpr>   sa   è ø€ ò 
ð ô ' t¬TÔ2´zÀ$Ç(Á(È6ÓBRÔTWÔ7XˆD�ŠLÜFPÐQUÔW[ÔF\”—‘˜D¨u¼cÕBÜ�T“óñ
ùs   ‚A5A7Fr   )r   r   ÚlistÚjoinr   r   r   )Úcontents    r   Ú_stringify_tool_contentr      sn   € ð €ØÜ�'œ3ÔØˆÜ�'œ4Ô Ø�y‰yñ 
ð  ô	
ó 
ð 	
ô �'œ4Ô Ü�z‰z˜'°¼sÔCÐCÜˆw‹<Ðó    c                ó
  — t        | «      } | sy| j                  «       j                  d«      rt	 t        j                  | «      }t        |t        «      rN|j                  d«      s<t        |j                  d«      xs d«      j                  «       j                  «       dv ry| j                  «       r/| j                  «       d	   j                  «       j                  «       nd}|j                  d
«      S # t
        $ r d}Y Œ½w xY w)zíConservative error detector for tool-result previews: structured JSON with
    an ``error`` key or an error/failed ``status``, or a first line starting with a
    classic error marker. (Substring "error" alone painted normal output red.)F)ú{ú[NÚerrorÚstatusr   >   r$   ÚfailedÚfailureÚtimeoutTr   )zerror:zfailed:z
traceback z
exception:)r   ÚlstripÚ
startswithr   ÚloadsÚ	Exceptionr   r   r   r   ÚstripÚlowerÚ
splitlines)r   ÚparsedÚfirsts      r   Ú_looks_like_error_outputr2      sß   € ô & gÓ.€GÙØØ‡~�~Ó×"Ñ" :Ô.ð	Ü—Z‘Z Ó(ˆFô �fœdÔ#Ø�J‰J�wÔ¤3 v§z¡z°(Ó';Ò'A¸rÓ#B×#HÑ#HÓ#J×#PÑ#PÓ#RÐVÑ#àØ7>×7IÑ7IÔ7KˆG×ÑÓ  Ñ#×)Ñ)Ó+×1Ñ1Ô3ÐQS€EØ×ÑÐMÓNÐNøô ò 	ØŠFð	ús   ¯C4 Ã4DÄDé   i@  )Úmax_entriesÚ	max_charsc               ó  — t        | t        «      r| j                  d«      nd}t        |t        «      sg S |D ��ci c]†  }t        |t        «      rt|j                  d«      dk(  r`|j                  d«      xs g D ]H  }|j                  d«      r5|d   t	        |j                  d«      xs i j                  d«      xs d	«      “ŒJ Œˆ }}}g }t        |«      D ]›  }t        |«      |k\  r n‹t        |t        «      r|j                  d«      d	k7  rŒ8t        |j                  d
«      xs d«      }|j                  |j                  d«      xs dd	«      }	|j                  |	|d| t        |«      dœ«       Œ� |j                  «        |S c c}}w )aj  Last N tool-call results ``{tool, preview, is_error}`` from a child's conversation (the overlay's "Output"
    section), chronological order. Content blocks are flattened first so a block-wrapped "Error: ..." is still
    flagged; line structure is preserved (capped at ``max_chars``) so the overlay shows real output rather than a
    whitespace-collapsed blob.ÚmessagesNÚroleÚ	assistantÚ
tool_callsÚidÚfunctionÚnameÚtoolr   r   Útool_call_id)r>   ÚpreviewÚis_error)r   r   r   r   r   ÚreversedÚlenr   Úappendr2   Úreverse)
Úresultr4   r5   r7   ÚmsgÚtcÚname_by_call_idÚtailr   Ú	tool_names
             r   Ú_extract_output_tailrL   2   sr  € ô
 *4°F¼DÔ)Aˆv�z‰z˜*Ô%Àt€HÜ�h¤Ô%Øˆ	ð ÷àœz¨#¬tÔ4¸¿¹À»ÈKÒ9WØ—'‘'˜,Ó'Ò-¨2òð °·±¸´ð 	ˆ4‰”#�r—v‘v˜jÓ)Ò/¨R×4Ñ4°VÓ<ÒFÀÓGÑGðØð€Oñ ð
 "$€DÜ˜Ó!ò xˆÜˆt‹9˜Ò#ÙÜ˜#œtÔ$¨¯©°«¸6Ò(AØÜ)¨#¯'©'°)Ó*<Ò*BÀÓCˆØ#×'Ñ'¨¯©°Ó(?Ò(EÀ2ÀvÓNˆ	Ø�‰˜Y°7¸:¸IÐ3FÔTlÐmtÓTuÑvÕwðxð 	‡L�L„NØ€Kùós   »BF>   ÚcwdÚdstÚsrcÚurlÚpathÚurlsÚendpointÚnew_pathÚold_pathÚ	directoryÚ	file_pathÚsource_pathÚtarget_pathÚdestination_path>   rP   rR   rS   c                óà  ‡ — t        |t        «      r$ˆ fd„|dd D «       D �cg c]  }|€Œ|‘Œ	 }}|xs dS t        |t        «      r|sy|dd }‰ t        v r„	 t	        |«      }|j
                  rj|j                  r^|j                  }|syd|v rd|› d�n|}|j                  �|› d|j                  › �n|}t        |j
                  ||j                  ddf«      S |S |S c c}w # t        $ r Y yw xY w)	z<Keep bounded side-effect targets while dropping URL secrets.c              3  ó6   •K  — | ]  }t        ‰|«      –— Œ y ­w)N)Ú_sanitize_tool_target)r   r   Úkeys     €r   r   z(_sanitize_tool_target.<locals>.<genexpr>T   s   øè ø€ Ò$]È$Ô%:¸3À×%EÑ$]ùs   ƒNé   i   ú:r#   ú]r   )r   r   r   Ú_TOOL_INPUT_URL_KEYSr   ÚschemeÚnetlocÚhostnameÚportr	   rQ   Ú
ValueError)	r^   Úvaluer   ÚcleanedÚboundedr0   re   Úhostrd   s	   `        r   r]   r]   Q   s  ø€ ä�%œÔÛ$]ÐRWÐX[ÐY[ÐR\Ô$]Ör˜DÐaeÑaq’4ÐrˆÐrØŠ˜$ÐÜ�eœSÔ!©ØØ�E�Tˆl€GØ
Ô"Ñ"ð	Ü˜gÓ&ˆFØ�}Š} §¢Ø!Ÿ?™?�ÙØð +.°©/˜˜8˜* A‘¸x�Ø4:·K±KÐ4K˜D˜6  6§;¡; -Ñ0ÐQU�Ü! 6§=¡=°&¸&¿+¹+ÀrÈ2Ð"NÓOÐOð €Nˆ7€Nùò) søô$ ò 	Ùð	ús#   ¢CªCÁ1C! Â	AC! Ã!	C-Ã,C-c                ó¦   — i }| j                  «       D ];  \  }}t        |«      j                  «       }|t        v sŒ(t	        ||«      }|€Œ7|||<   Œ= |S )zNKeep only known side-effect target keys, each sanitized (URL secrets dropped).)Úitemsr   r.   Ú_TOOL_INPUT_TARGET_KEYSr]   )ÚmappingÚtargetsÚraw_keyrh   r^   ri   s         r   Ú_sanitize_targetsrr   j   s]   € à €GØ!Ÿ-™-›/ò '‰ˆ�Ü�'‹l× Ñ Ó"ˆØÔ)Ò)Ü+¨C°Ó7ˆGØÑ"Ø&�˜’ð'ð €Nr    c                ó®   — t        | t        «      r| dd D �cg c]  }t        |«      dd ‘Œ c}ng t        |t        «      rt	        |«      dœS i dœS c c}w )zT``{argument_keys, targets}`` with bounded, sanitized contents (empty on bad shapes).Né@   é€   )Úargument_keysrp   )r   r   r   r   rr   )Úkeysrp   r^   s      r   Ú_input_summaryrx   u   s]   € ô CMÈTÔSWÔBX°D¸¸"°IÖ>¨Sœ#˜c›( 4 Cš.Ó>Ð^`Ü1;¸GÄTÔ1JÔ$ WÓ-ñð àPRñð ùÚ>s   ˜Ac                óð   — 	 t        | t        «      rt        j                  | «      nd}t        |t        «      st        g i «      S t        t        d„ |D «       «      |«      S # t        t
        f$ r d}Y ŒKw xY w)zFSummarize argument names and side-effect targets without raw payloads.Nc              3  ó8   K  — | ]  }t        |«      d d –— Œ y ­w)Nru   )r   )r   r^   s     r   r   z,_summarize_tool_arguments.<locals>.<genexpr>„   s   è ø€ Ò B°C¤ S£¨$¨3¤Ñ Bùs   ‚)	r   r   r   r+   Ú	TypeErrorrg   r   rx   Úsorted)Ú	argumentsr0   s     r   Ú_summarize_tool_argumentsr~   |   sl   € ðÜ*4°YÄÔ*D”—‘˜IÔ&È$ˆô �fœdÔ#Ü˜b "Ó%Ð%Üœ&Ñ B¸6Ô BÓBÀFÓKÐKøô	 ”zÐ"ò ØŠðús   ‚'A! Á!A5Á4A5c           
     óì  — t        | t        «      sg S dd„}g }| D ]Ö  }t        |t        «      sŒt        |j	                  d«      xs d«      j                  «       }|j	                  d«      }t        |t        «      r|ni }|j                  t        |j	                  d«      xs d«      dd t        |j	                  d«      |j	                  d	«      «       ||d
«       ||d«      |dv r|nddœ«       ŒØ |S )zXDetached, metadata-only tool history for lifecycle hooks (input summaries re-sanitized).c                ó    — | j                  |d«      }t        |t        t        f«      r%t        |t        «      st        dt        |«      «      S dS )Nr   )r   r   ÚintÚfloatÚboolÚmax)r   r^   rh   s      r   Ú_byte_countz5_subagent_stop_tool_call_history.<locals>._byte_count‹   sA   € Ø—‘˜˜aÓ ˆÜ%/°¼¼U°|Ô%DÌZÐX]Ô_cÔMdŒs�1”c˜%“jÓ!ÐkÐjkÐkr    r%   ÚunknownÚinput_summaryr>   Né   rv   rp   Ú
args_bytesÚresult_bytes>   Úokr$   )rK   Ú
tool_inputÚinput_bytesÚoutput_bytesr%   )r^   r   Úreturnr�   )r   r   r   r   r   r.   rD   rx   )Ú
tool_tracer…   Úhistoryr   r%   Úsummarys         r   Ú _subagent_stop_tool_call_historyr“   †   sì   € ä�j¤$Ô'Øˆ	ólð %'€GØò ˆÜ˜$¤Ô%ØÜ�T—X‘X˜hÓ'Ò4¨9Ó5×;Ñ;Ó=ˆØ—(‘(˜?Ó+ˆÜ'¨´Ô6‘'¸BˆØ�‰Ü˜TŸX™X fÓ-Ò:°Ó;¸D¸SÐAÜ(¨¯©°_Ó)EÀwÇ{Á{ÐS\ÓG]Ó^Ù& t¨\Ó:ÉKÐX\Ð^lÓLmØ &¨/Ñ 9‘f¸yñ	
õ 	ðð €Nr    iÀ]  ç      à?iÐ  c                óF  — 	 ddl m} ddl} |dd«      }|j                  dd¬«       |d| › d	|j                  j	                  «       j                  d
«      › d�z  }ddlm}  |||d¬«       t        |«      S # t        $ r }t        j                  d|«       Y d}~yd}~ww xY w)u%  Write the full summary under ``cache/delegation`` (mounted read-only into remote backends via
    ``credential_files._CACHE_DIRS``, so the parent's terminal/``read_file`` can page it on any backend). Absolute
    path, or None on failure â€” the trimmed head+tail is still returned regardless.r   )Úget_hermes_dirNzcache/delegationÚdelegation_cacheT)ÚparentsÚexist_okzsubagent-summary-Ú-z%Y%m%d_%H%M%S_%fz.txt)Úwrite_text_exclusiveF)Úprivatez,Failed to spill subagent summary to file: %s)Úhermes_constantsr–   ÚdatetimeÚmkdirÚnowÚstrftimeÚtools.spill_safetyr›   r   r,   ÚloggerÚdebug)Ú
task_indexr’   r–   Ú_dtÚ	cache_dirrQ   r›   Úexcs           r   Ú_spill_summary_to_filer©   ¨   s�   € ðÝ3ÛÙ"Ð#5Ð7IÓJˆ	Ø�‰ ¨tˆÔ4ØÐ.¨z¨l¸!¸C¿L¹L×<LÑ<LÓ<N×<WÑ<WÐXjÓ<kÐ;lÐlpÐqÑqˆÝ;ñ 	˜T 7°EÕ:Ü�4‹yÐøÜò Ü�‰ÐCÀSÔIÜûðús   ‚A4A7 Á7	B Â BÂB c           
     ót  — t        | «      }t        |dz  «      }||z
  }| d| | | d }}|j                  d«      }||dz  kD  r|d| }|j                  d«      }d|cxk  r|dz  k  rn n||dz   d }t	        || «      }	|	rddlm}
  |
|	«      }	dd	d
t        |«      d›dt        |«      d›d|d›d�g}|	rH|j                  d|	› �«       |j                  d|	› d|j                  t        d«      «      dz   › d�«       n|j                  d«       |j                  d«       |dz   |z   dj                  |«      z   |	fS )a3  ``(model_text, spill_path)`` for one over-budget summary: a ~75% head / ~25% tail window snapped to line
    boundaries (so the opening AND the closing outcomes/files-changed/issues both survive), the full text spilled
    to disk, and a footer giving the exact ``read_file offset=`` for the omitted middle.g      è?Nr   r”   r   é   )Úto_agent_visible_cache_pathr   uE   â”€â”€â”€â”€â”€â”€â”€â”€ [SUMMARY TRUNCATED] â”€â”€â”€â”€â”€â”€â”€â”€zShowing ú,z chars (head) + z chars (tail) of u:    total â€” trimmed to protect the parent's context window.zFull subagent output saved to: z,To read the omitted middle: read_file path="z	" offset=é
   é   zV limit=200  (the file is the complete summary; raise/lower offset to page through it).zWFull output could not be stored to disk; the head+tail above is all that was preserved.uo   â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€u+   

[... middle omitted â€” see footer ...]

)rC   r�   ÚrfindÚfindr©   Útools.credential_filesr¬   rD   ÚcountÚchrr   )r’   Úcapr¥   Úoriginal_lenÚhead_budgetÚtail_budgetÚheadrJ   ÚnlÚ
spill_pathr¬   Úfooter_liness               r   Ú_trim_summary_with_footerr½   »   sˆ  € ô �w“<€LÜ�c˜D‘j“/€KØ˜Ñ#€KØ˜˜+Ð&¨°°°Ð(>ˆ$€DØ	�‰�DÓ	€BØ	ˆK˜#ÑÒØ�C�RˆyˆØ	�‰�4‹€BØˆBÔ"�˜sÑ"Õ"Ø�B˜‘F�Gˆ}ˆä'¨
°GÓ<€JÙåFÙ0°Ó<ˆ
à
Ð;Ø
”3�t“9˜Q�-Ð/´°D³	¸!¨}ð =Ø˜1ÐÐWð	Yð€Lñ
 à×ÑÐ=¸j¸\ÐJÔKØ×ÑØ:¸:¸,ð GØ—j‘j¤ R£Ó)¨AÑ-Ð.ð /?ð@õ	
ð 	×ÑÐuÔvØ×Ñ˜
Ô#ØÐCÑCÀdÑJÈTÏYÉYÐWcÓMdÑdÐfpÐpÐpr    c                ó  — t        | dd«      }t        |t        t        f«      r|dkD  rt        |«      S t        | dd«      xs i }t        |t        «      r|j                  d«      nd}t        |t        t        f«      r|dkD  rt        |«      S y)a.  The parent's current prompt size: the aggregator's own last ``prompt_tokens`` (pre-MoA-fold), else
    the last provider usage. ``None`` when no request has completed yet: the caller then applies the
    static ceiling only. Treating "no usage yet" as zero handed a 190K/200K parent a 384K-char budget.Ú_last_prompt_size_tokensNr   Ú_last_turn_usageÚprompt_tokens)Úgetattrr   r�   r‚   r   r   )Úparent_agentÚsizeÚ
last_usageÚuseds       r   Ú_parent_prompt_size_tokensrÇ   á   s€   € ô �<Ð!;¸TÓB€DÜ�$œœe˜Ô%¨$°ª(Ü�4‹yÐÜ˜Ð'9¸4Ó@ÒFÀB€JÜ.8¸ÄTÔ.Jˆ:�>‰>˜/Ô*ÐPT€DÜ�$œœe˜Ô%¨$°ª(Ü�4‹yÐØr    c                ó˜  — 	 t        | dd«      }t        |dd«      }t        |t        «      r|dk  ryt        | «      }|€y|t        |«      z
  t        t        |dd«      xs d«      z
  }|dk  rt        S t        |t
        z  «      t        d|«      z  }t        t        |dz  «      S # t        $ r t        j                  dd	¬
«       Y yw xY w)uì  Per-summary char budget from the parent's *remaining* context headroom (context length âˆ’ the parent's
    current prompt size âˆ’ the compressor's output reserve), a fraction of it split across the batch at ~4
    chars/token. None when the parent's context state is unknown â€” caller then uses the static ceiling only.

    "Current prompt size" is the last API call's ``prompt_tokens`` (``_last_turn_usage``), never
    ``session_prompt_tokens``: that field is the running SUM over every call in the session, so after a
    few hundred calls it exceeds any context window and every summary collapsed to the 2,000-char floor
    (measured: all 1,393 child summaries in one run, each spilled to disk, the orchestrator working from
    the stub).Úcontext_compressorNÚcontext_lengthr   Ú
max_tokensr«   é   z!Summary budget computation failedT©Úexc_info)
rÂ   r   r�   rÇ   Ú_MIN_SUMMARY_CHARSÚ_SUMMARY_HEADROOM_FRACTIONr„   r,   r£   r¤   )rÃ   Ún_summariesÚ
compressorrÊ   Úused_tokensÚheadroom_tokensÚper_summary_tokenss          r   Ú_parent_summary_char_budgetrÖ   ï   sÛ   € ðÜ˜\Ð+?ÀÓFˆ
Ü  Ð-=¸tÓDˆÜ˜.¬#Ô.°.ÀAÒ2EØÜ0°Ó>ˆØÐØØ(¬3¨{Ó+;Ñ;¼cÄ'È*ÐVbÐdeÓBfÒBkÐjkÓ>lÑlˆØ˜aÒÜ%Ð%Ü  Ô3MÑ!MÓNÔRUÐVWÐYdÓReÑeÐÜÔ%Ð'9¸AÑ'=Ó>Ð>øÜò Ü�‰Ð8À4ˆÔHÙðús"   ‚/B& ²B& Á 3B& Á41B& Â& C	ÃC	c           	     ó°  — ddl m} | D �cg c];  }t        |t        «      sŒt        |j	                  d«      t
        «      sŒ4|d   sŒ:|‘Œ= }}|sy	 t         |«       j	                  dt        «      «      }|t        |t        |«      «      fD �cg c]  }|sŒ|dkD  sŒ|‘Œ }}|syt        |«      }|D ]}  }	|	d   }
t        |
«      |k  rŒt        |
||	j	                  dd«      «      \  }}||	d<   d|	d	<   |r||	d
<   t        j                  d|	j	                  dd«      t        |
«      ||xs d«       Œ yc c}w # t        t        f$ r	 t        }Y ŒÚw xY wc c}w )a0  Trim subagent summaries in-place so a batch can't overflow the parent's context window (full text spilled to
    disk). Per-summary cap = MIN(dynamic headroom budget, static ``delegation.max_summary_chars`` ceiling; 0 =
    disabled); over-cap summaries become head+tail plus a pointer to the spill file.r   )Ú_load_configr’   NÚmax_summary_charsr¥   éÿÿÿÿTÚsummary_truncatedÚsummary_full_pathu9   [subagent-%s] summary trimmed %d â†’ ~%d chars (spill=%s)ú?Únone)Útools.delegate_toolrØ   r   r   r   r   r�   ÚDEFAULT_MAX_SUMMARY_CHARSr{   rg   rÖ   rC   Úminr½   r£   r¤   )ÚresultsrÃ   rØ   ÚrÚ	summariesÚstatic_ceilingÚcÚ
candidatesrµ   Úentryr’   Ú
model_textr»   s                r   Ú_apply_summary_budgetrê   
  sj  € õ 1Ø#Ör�q¤z°!´TÕ':¼zÈ!Ï%É%ÐPYÓJZÔ\_Õ?`ÐefÐgpÓeq’Ðr€IÐrÙØð3Ü™\›^×/Ñ/Ð0CÔE^Ó_Ó`ˆð -Ô.IÈ,ÔX[Ð\eÓXfÓ.gÐhÖx˜ÒlmÐrsÐvwÓrw’!Ðx€JÐxÙØÜ
ˆj‹/€CØò 
ˆØ˜	Ñ"ˆÜˆw‹<˜3ÒØÜ!:¸7ÀCÈÏÉÐS_ÐacÓIdÓ!eÑˆ
�JØ%ˆˆiÑØ%)ˆÐ!Ñ"ÙØ)3ˆEÐ%Ñ&Ü�‰ØGÈÏÉÐS_ÐadÓIeÔgjÐkrÓgsÐuxØÒ ˜&õ	
ñ
ùò søô
 ”zÐ"ò 3Ü2Šð3üâxs:   ‹D3¡D3ÁD3ÁD3Á$D8 ÂEÂEÂEÄ8EÅEc                 óÂ   — ddl m} ddl}t        5  t	        |j
                  «      }	  |di | ¤Ž}||_        	 ddd«       _        |S # ||_        w xY w# 1 sw Y   ŒxY w)zCBuild a child without leaking its resolved toolset into the parent.r   )Ú_build_child_agentN© )rß   rì   Úmodel_toolsÚ_CHILD_CONSTRUCTION_LOCKr   Ú_last_resolved_tool_namesÚ_delegate_saved_tool_names)Úkwargsrì   rî   Úparent_tool_namesÚchilds        r   Ú$_build_child_preserving_parent_toolsrõ   ,  sl   € å6ÛÜ	!ñ FÜ  ×!FÑ!FÓGÐð	FÙ&Ñ0¨Ñ0ˆEà4EˆKÕ1÷Fð (9€EÔ$Ø€Løð 5FˆKÕ1ú÷Fð Fús!   ‘A¨A	°AÁ		AÁAÁAc                ó  — | €t         S t        | dd«      }|�|S t        5  t        | dd«      }|€"t        j                  «       }	 t        | d|«       ddd«       |S # t        $ r t         cY cddd«       S w xY w# 1 sw Y   |S xY w)zRPer-parent lock serializing lifecycle side effects (created once under the guard).NÚ_subagent_finalization_lock)Ú"_PARENT_FINALIZATION_FALLBACK_LOCKrÂ   Ú_PARENT_FINALIZATION_LOCK_GUARDÚ	threadingÚRLockÚsetattrr,   )rÃ   Úlocks     r   Ú_parent_finalization_lockrþ   9  sœ   € àÐÜ1Ð1Ü�<Ð!>ÀÓE€DØÐØˆÜ	(ñ :Ü�|Ð%BÀDÓIˆØˆ<Ü—?‘?Ó$ˆDð:Ü˜Ð&CÀTÔJ÷:ð €Køô ò :Ü9Ñ9÷:ñ :ð:ú÷:ð €Kús)    $A:ÁAÁA7Á+A:Á6A7Á7A:Á:Bc           
     ól  — |rt        |dd «      nd }|sy | D ]Œ  }	 |j                  dd«      }t        |t        «      xr d|cxk  xr t	        |«      k  nc }|j                  |r||   d   nd|j                  dd«      xs dt        |j                  |«      dd«      ¬	«       ŒŽ y # t        $ r Y Œ›w xY w)
NÚ_memory_managerr¥   rÚ   r   Úgoalr   r’   Ú
session_id)ÚtaskrF   Úchild_session_id)rÂ   r   r   r�   rC   Úon_delegationr,   )râ   Ú	task_listÚchild_by_indexrÃ   Úmemoryrè   r¥   Úin_ranges           r   Ú_notify_memory_managerr
  J  sÄ   € Ù?KŒW�\Ð#4°dÔ;ÐQU€FÙØØò 	ˆð	ØŸ™ <°Ó4ˆJÜ! *¬cÓ2ÒW°q¸JÖ7WÌÈYËÔ7WˆHØ× Ñ Ù6>�Y˜zÑ*¨6Ò2ÀBÈuÏyÉyÐYbÐdfÓOgÒOmÐkmÜ!(¨×);Ñ);¸JÓ)GÈÐWYÓ!Zð !õ ñ		øô ò 	Ùð	ús   ›B	B'Â'	B3Â2B3c                óŠ  — 	 ddl m} d}| D ]ç  }|j                  dd«      }|j                  dd«      }	 |r|t	        |«      z  }|€Œ;	 |j                  |j                  dd«      «      } |d	t        |d
d«      t        |dd«      xs dt        |d
d«      ||j                  d«      |j                  d«      t        |j                  d«      «      t        |j                  d«      xs ddz  «      ¬«	       Œé |S # t        $ r d}Y Œýw xY w# t
        t        f$ r Y ŒÖw xY w# t        $ r t        j                  dd¬«       Y �Œ5w xY w)z›Pop the model-hidden ``_child_role`` / ``_child_cost_usd`` fields from every
    entry, fire ``subagent_stop`` per child, and return the summed child cost.r   )Úinvoke_hookNç        Ú_child_roleÚ_child_cost_usdr¥   rÚ   Úsubagent_stopr  Ú_current_turn_idr   r’   r%   r�   Úduration_secondsiè  )Úparent_session_idÚparent_turn_idr  Ú
child_roleÚchild_summaryÚchild_statusÚtool_call_historyÚduration_msz$subagent_stop hook invocation failedTrÍ   )Úhermes_cli.pluginsr  r,   Úpopr‚   r{   rg   r   rÂ   r“   r�   r£   r¤   )	râ   r  rÃ   r  Úchildren_cost_totalrè   r  Ú
child_costrô   s	            r   Ú_fire_subagent_stop_hooksr  Y  s^  € ðÝAð ÐØò PˆØ—Y‘Y˜}¨dÓ3ˆ
Ø—Y‘YÐ0°#Ó6ˆ
ð	ÙØ#¤u¨ZÓ'8Ñ8Ð#ð ÐØð	PØ"×&Ñ& u§y¡y°¸rÓ'BÓCˆEÙØ´7¸<ÈÐW[Ó3\Ü& |Ð5GÈÓLÒRÐPRÜ!(¨°¸dÓ!CÐPZØ#Ÿi™i¨	Ó2ÀÇÁÈ8ÓATÜ"BÀ5Ç9Á9È\ÓCZÓ"[Ü §¡Ð+=Ó!>Ò!CÀ!ÀtÑ KÓLöðPð, Ðøô3 ò ØŠðûô œ:Ð&ò 	Ùð	ûô ò 	PÜ�L‰LÐ?È$ˆL×Oð	Pús5   ‚C8 ´D	ÁB,DÃ8DÄDÄ	DÄDÄ EÅEc                ó   — |dk  ry	 t        t        | dd«      xs d«      }||z   | _        t        | dd«      dv rd| _        t        | dd	«      d
v rd| _        yy# t
        $ r t        j                  dd¬«       Y yw xY w)zzFold the children's spend into the parent's session cost (source/status
    only set when the parent had none of its own).r  NÚsession_estimated_cost_usdÚsession_cost_sourcerÞ   >   Nr   rÞ   ÚsubagentÚsession_cost_statusr†   >   Nr   r†   Ú	estimatedzSubagent cost rollup failedTrÍ   )r‚   rÂ   r   r!  r#  r,   r£   r¤   )rÃ   r  Úcurrents      r   Ú_rollup_children_costr&  y  s›   € ð ˜cÒ!ØðCÜœ Ð.JÈCÓPÒWÐTWÓXˆØ29Ð<OÑ2OˆÔ/Ü�<Ð!6¸Ó?ÐCUÑUØ/9ˆLÔ,Ü�<Ð!6¸	ÓBÐF[Ñ[Ø/:ˆLÕ,ð \øäò CÜ�‰Ð2¸TˆÖBðCús   ˆAA Á A=Á<A=c           	     óä   — t        |«      5  t        | |«       |D ���ci c]	  \  }}}||“Œ }}}}t        | |||«       t        |t	        | ||«      «       ddd«       yc c}}}w # 1 sw Y   yxY w)z@Apply host-owned summary, memory, hook, and cost contracts once.N)rþ   rê   r
  r&  r  )râ   r  ÚchildrenrÃ   ÚindexÚ_taskrô   r  s           r   Ú_finalize_child_resultsr+  ˆ  s|   € ô
 
# <Ó	0ñ nÜ˜g |Ô4ØBJ×KÐKÑ+>¨5°%¸˜% ™,ÐKˆÒKÜ˜w¨	°>À<ÔPÜ˜lÔ,EÀgÈ~Ð_kÓ,lÔm÷	nð nùäK÷nð nús   ŒA&ŸA
­)A&ÁA&Á&A/c                ó¾   — ddl m}  || |||«      }|j                  d| «       d|i}t        |gt	        | «      D �cg c]  }ddi‘Œ c}|gz   | ||fg|«       |S c c}w )zFRun one child and apply the same host lifecycle used by delegate_task.r   )Ú_run_single_childr¥   r  r   )rß   r-  Ú
setdefaultr+  Úrange)r¥   r  rô   rÃ   r-  rF   r  Ú_s           r   Ú_run_child_lifecycler1  “  s{   € å5Ù˜z¨4°¸ÓE€FØ
×Ñ�l JÔ/Ø�Dˆ>€DÜ˜V˜H¼UÀ:Ó=NÖ&O¸¨°¢|Ò&OÐSWÐRXÑ&XÐ\fÐhlÐnsÐ[tÐZuð  xDô  EØ€Mùò 'Ps   ¼A
)r   r   r�   r   )r   r   r�   rƒ   )rF   úDict[str, Any]r4   r�   r5   r�   r�   úList[Dict[str, Any]])r^   r   rh   r   r�   r   )ro   r2  r�   r2  )rw   r   rp   r   r�   r2  )r}   r   r�   r2  )r�   r   r�   r3  )r¥   r�   r’   r   r�   zOptional[str])r’   r   rµ   r�   r¥   r�   r�   ztuple[str, Optional[str]])r�   úOptional[int])rÑ   r�   r�   r4  )râ   r3  r�   ÚNone)r�   zthreading.RLock)r�   r5  )r�   r‚   )r  r‚   r�   r5  )râ   r3  r  r3  r(  z%List[tuple[int, Dict[str, Any], Any]]r�   r5  )NN)r¥   r�   r  r   r�   r2  )/Ú__doc__Ú
__future__r   Úloggingr   rú   Útypingr   r   r   r   Úurllib.parser   r	   Ú	getLoggerr£   r   r2   rL   Ú	frozensetrn   rb   r]   rr   rx   r~   r“   rà   rÐ   rÏ   r©   r½   rÇ   rÖ   rê   ÚLockrù   rû   rø   rï   rõ   rþ   r
  r  r&  r+  r1  rí   r    r   ú<module>r>     s2  ðÙ så "ã Û Û ß ,Ó ,ß -à	ˆ×	Ñ	Ð0Ó	1€óó$Oð& HJÐ\`õ ñ2 $ò %ó Ð ñ !Ò!<Ó=Ð óó2	óóLóð4 "Ð ð !Ð ð Ð óó&$qóLóó6
ð< #1 )§.¡.Ó"2Ð Ø%4 Y§_¡_Ó%6Ð "Ø*˜9Ÿ?™?Ó,Ð òóó"óó@Cð	nØ!ð	nØ.Bð	nØNsð	nð 
ó	nõr    