+
    lHàj<  ã            
       óð   € R t ^ RIt^ RIt^ RIt^ RIHtHtHt ]P                  ! R4      t	Rt
RtRtRtRtR R	 ltR
 R ltRR/R R lltR tR R ltR^ R^ RRRRRR/R R lltRtRtR R ltR R ltR# ) ab  Background-process launch path: ``terminal(background=true)`` spawns a tracked
process via the process registry (Popen locally, ``env.execute`` in a sandbox),
stamps gateway routing metadata for completion / watch-pattern notifications and
returns the JSON result. Lazy ``tools.terminal_tool`` imports keep the origin's
monkeypatch points authoritative.
N)ÚAnyÚListÚOptionalztools.terminal_toolu  background=true without notify_on_complete=true means this process runs SILENTLY â€” you will not be told when it exits. If this is a bounded task (test suite, build, CI poller, deploy, anything with a defined end), you almost certainly wanted notify_on_complete=true so the system pings you on exit. Re-launch with notify_on_complete=true, or call process(action='poll') / process(action='wait') yourself to learn the outcome. Only ignore this hint for genuine long-lived processes that never exit (servers, watchers, daemons).uU  This looks like a homebrewed CI poller built from `gh pr view --json statusCheckRollup` and/or `gh pr checks | jq`. That shape has burned us repeatedly in hermes-agent dev work (PRs #31329, #31448, #31695, #31709, #31745, #32264, #33131) â€” stdout buffering kills output capture, jq null-key edge cases silently exit the loop, conclusion-vs-status field confusion exits early with bogus all-green verdicts, TTY-only summary banners never appear when piped. Use the canonical snippets in the green-ci-policy skill instead: the exit-code-driven `gh pr checks $PR >/dev/null` (rc 0 = green, 8 = pending, else fail) for exit-on-first-fail behavior, or the column-2 awk-on-tabs poller (`awk -F"\t" "$2==\"pending\""`) for sharded matrices. Load skill_view(name='github/hermes-agent-dev', file_path='references/green-ci-policy.md') for the verbatim snippets. If you must roll a custom loop with rich structured output, write each tick to a known file (`tee -a $TMPDIR/ci.log`) and rely on `process(action='log')` to read THAT file â€” do not rely on background-process stdout capture for line-buffered shell loops.z¼Ran in the background (the trailing & was converted to background=true; Hermes tracks the process). Do NOT re-run it. Use process_manage (poll/log/wait/kill, session_id above) to check it.u\  notify_on_complete / watch_patterns are not available in this session â€” it cannot receive an async completion after the turn ends (a one-shot runner such as `hermes -z`, a cron job, a Kanban worker, or a stateless HTTP endpoint). The process is running in the background; retrieve its result with process(action='poll') or process(action='wait').c                ó0   € V ^8„  d   QhR\         R\        /# )é   ÚcommandÚreturn)ÚstrÚbool)Úformats   "ÚC/home/ubuntu/.hermes/hermes-agent/tools/terminal_tool_background.pyÚ__annotate__r   M   s   € ÷ Añ A¬Cð A´Dñ Aó    c                 ó–   € R V 9   ;'       g    RV 9   pRV 9   ;'       g    RV 9   ;'       g    RV 9   pRV 9   ;'       g    T;'       d    T# )z
gh pr viewzgh pr checksz jq z| jqz$(jqÚstatusCheckRollup© )r   Úhas_ghÚhas_jqs   &  r   Ú_looks_like_homebrew_ci_pollerr   M   sX   € Ø˜WÑ$×AÐA¨¸'Ñ(A€FØ�wÑ×HÐH &¨GÑ"3×HÐH°vÀÑ7H€Fà 'Ñ)×@Ð@¨f×.?Ð.?¸Ð@r   c                ó   € V ^8„  d   QhRR/# ©r   r   Nr   )r   s   "r   r   r   T   s   € ÷ >ñ >¸Tñ >r   c           	     ó|   € V! RR4      pV'       g   R# W n         \         F  w  r4\        WV! VR4      4       K  	  R# )zƒCopy the spawning chat's routing metadata onto the process session so
completion / watch notifications reach the right chat/thread.ÚHERMES_SESSION_PLATFORMÚ N)Úwatcher_platformÚ_ROUTING_FIELDSÚsetattr)Úproc_sessionÚget_session_envÚplatformÚattrÚvars   &&   r   Ú_stamp_gateway_routingr"   T   s:   € ñ Ð8¸"Ó=€HßÙØ$,Ô!ß$‰	ˆÜ�¡O°C¸Ó$<Ö=ó %r   Úpersist_on_releaseFc                ó$   € V ^8„  d   QhR\         /# )r   r#   )r
   )r   s   "r   r   r   _   s   € ÷ =ñ =Ü;?ñ=r   c       	   	      óÔ   € \        Y4TT;'       g    TVV	R 7      p
VR8X  d5   V P                  ! RR\        VR4      '       d   VP                  MRRV/V
B # V P                  ! RRV/V
B # ))r   ÚcwdÚtask_idÚowner_task_idÚsession_keyr#   ÚlocalÚenv_varsÚenvNÚuse_ptyr   )ÚdictÚspawn_localÚhasattrr,   Úspawn_via_env)Úprocess_registryr,   Úenv_typer   r&   Úeffective_task_idr'   r)   Úeffective_ptyr#   Úcommons   &$$$$$$$$$ r   Ú_spawnr7   _   s‡   € ä˜'Ð4EØ '× <Ð <Ð+<È+Ø%7ô9€Fð �7ÔØ×+Ò+ñ `Ü '¨¨U× 3Ò 3�S—W’W¸ð`ØGTð`ØX^ñ`ð 	`à×)Ò)Ñ<¨cÐ<°VÑ<Ð<r   c                óÎ   € V'       g   V'       g   W#3# ^ RI HpHp V! 4       '       d   \        W4       W#3# RVR&   \        VR&   \
        P                  RV P                  4       R# )zÚFinite sessions (stateless HTTP, one-shot Kanban workers) can't route a
completion back after the turn ends: drop the flags and tell the agent to
poll. Otherwise stamp gateway routing. Returns (notify, watch_patterns).©Úasync_delivery_supportedr   FÚnotify_on_completeÚnotify_unsupportedzjbackground proc %s: async delivery unsupported on this session; notify_on_complete/watch_patterns disabled)FN)Úgateway.session_contextr:   r   r"   Ú_ASYNC_UNSUPPORTED_NOTEÚloggerÚinfoÚid)r   Úresult_datar;   Úwatch_patternsr:   r   s   &&&&  r   Ú_apply_async_supportrD   j   se   € ÷ §.Ø!Ð1Ð1ßQá×!Ò!Ü˜|Ô=Ø!Ð1Ð1Ø(-€KÐ$Ñ%Ü(?€KÐ$Ñ%Ü
‡K�Kð FØGSÇÁôXàÐr   c                ó   € V ^8„  d   QhRR/# r   r   )r   s   "r   r   r   |   s   € ÷ 6ñ 6ÐQUñ 6r   c           
     óà  € ^Vn         RVP                  R^RVRVP                  /\        RR  UUu/ uF   w  r4VP	                  R4      \        W4      bK"  	  uppCRRR	VP                  /Cp\        \        P                  P                  R
4      RR4      p\        V4      '       d   V! 4       MRpVe   VP                  V4      '       d   R# V P                  P                  V4       R# u uppi )aØ  Gateway mode: register a fast watcher so completion triggers a new
agent turn (CLI mode uses the completion_queue directly).

Armed on the live gateway loop right away: the post-turn drain alone leaves a
process that finishes while its launching turn is still running unwatched, and
the chat mute for as long as that turn lasts (#112033). Before the gateway
serves, or while it stops, the descriptor waits in ``pending_watchers`` for the
startup / post-turn drain instead.Ú
session_idÚcheck_intervalr)   r   NÚwatcher_r;   TÚparent_session_idzgateway.runÚ_gateway_runner_reféÿÿÿÿ)Úwatcher_intervalrA   r   r   ÚremoveprefixÚgetattrrJ   ÚsysÚmodulesÚgetÚcallableÚarm_process_watcherÚpending_watchersÚappend)r2   r   r)   r    Ú_ÚwatcherÚ
runner_refÚrunners   &&&     r   Ú_register_completion_watcherr[   |   së   € ð %&€LÔ!à�l—o‘oÐ'7¸¸MÈ;Ø�L×1Ñ1ðô *¨#¨2Ñ.ô0Ù.‰wˆtð ×Ñ˜ZÓ(¬'°,Ó*EÒEÙ.ò0ðð
 	˜dÐ$7¸×9WÑ9Wñ€Gô œŸ™Ÿ™¨Ó7Ð9NÐPTÓU€JÜ% j×1Ò1‰ZŒ\°t€FØÒ˜f×8Ñ8¸×AÒAÙØ×%Ñ%×,Ñ,¨WÖ5ùó0s   ±&C*Úcompletion_output_charsÚheartbeat_secondsÚmounted_hostÚauto_backgroundedc          &      ó–  € V ^8„  d   QhR\         R\        R\         R\         R\        \         ,          R\         R\        \         ,          R\         R	\        R
\        R\        \        \         ,          ,          R\        \         ,          R\
        R\        \         ,          R\
        R\        R\        \         ,          R\        R\         /# )r   r   r,   r3   r4   r'   r)   Úworkdirr&   r5   r;   rC   Úapproval_noter\   Úpty_disabled_reasonr]   r#   r^   r_   r   )r	   r   r   r
   ÚlistÚint)r   s   "r   r   r   ”   sï   € ÷ Uñ UÜðUÜðUÜ),ðUÜADðUÜOWÔX[Í}ðUäðUä'¬�}ðUä36ðUäGKðUô ðUô /7´t¼CµyÕ.AðUô S[Ô[^ÕR_ðUô !ð	Uô
 "¤#�ðUô ðUô ðUô œ3•-ðUô ðUô 	ñUr   c                óÚ  € ^ RI Hp ^ RIHpHpHp T! YgYRVe   TM\        VRR4      VR7      p \        VWV VW4VW�R7
      pRRR	VP                  R
VP                  R^ RR/pV'       d   RVR&   V'       d   VVR&   V'       d   VVR&   V'       d   \        VR&   MV	'       g   V
'       g
   \        VR&   V '       dI   \        V 4      '       d8   VP                  RR4      pV'       d   VR,           \        ,           M\        VR&   \        VVWš4      w  ršV! \!        V	4      V
RR7      w  p
pV'       d'   \"        P%                  RVP                  V4       VVR&   V	'       d„   RVn        RVR&   V'       d   \)        V4      Vn        VP,                  '       d   \/        VVV4       ^ RIHp V! 4       '       d   RVR&   \4        VR&   M+V'       d   VP7                  VV4      VR&   MV'       d   RVR&   V
'       d    \9        V
4      Vn        VP:                  VR&   \<        P>                  ! VRR 7      #   \@         d2   p\<        P>                  ! RRRR"RT! R!T 24      /RR 7      u Rp?# Rp?ii ; i)#a–  Spawn *command* as a tracked background process and return the JSON result.

``auto_backgrounded`` marks a trailing-`&` conversion: the result carries the conversion note
and skips the silent-background hint, whose "re-launch" advice would start a second copy.

Never inline-polls ``is_interrupted()``: the spawn detaches and returns
exit_code 0 immediately, so the stale-interrupt kill cannot occur here.
©r2   )Ú_redact_terminal_error_textÚ_resolve_command_cwdÚ#_resolve_notification_flag_conflictNÚhost_cwd)ra   Údefault_cwdr)   r3   r^   r,   )	r,   r3   r   r&   r4   r'   r)   r5   r#   ÚoutputzBackground process startedrG   ÚpidÚ	exit_codeÚerrorTr#   ÚapprovalÚpty_noter_   Úhintr   z

)r;   rC   Ú
backgroundzbackground proc %s: %sÚwatch_patterns_ignoredr;   )Úis_delegated_child_contextFÚsubagent_noter]   zGheartbeat needs notify=true delivery, which this session cannot receiveÚheartbeat_ignoredrC   )Úensure_asciiz$Failed to start background process: rL   )!Útools.process_registryr2   Útools.terminal_toolrh   ri   rj   rO   r7   rA   rn   Ú_AUTO_BACKGROUND_NOTEÚ_SILENT_BACKGROUND_HINTr   rR   Ú_HOMEBREW_CI_POLLER_HINTrD   r
   r?   Úwarningr;   re   r\   r   r[   Úagent.delegation_contextrv   Ú_SUBAGENT_NOTIFY_NOTEÚarm_heartbeatrd   rC   ÚjsonÚdumpsÚ	Exception)r   r,   r3   r4   r'   r)   ra   r&   r5   r;   rC   rb   r\   rc   r]   r#   r^   r_   r2   rh   ri   rj   Úeffective_cwdr   rB   ÚexistingÚconflict_noterv   Úes   $$$$$$$$$$$$$$$$$$           r   Úspawn_background_processrŠ   ”   sl  € õ& 8÷ñ ñ )Ø°kØ%1Ò%=‘\Ä7È3ÐPZÐ\`ÓCaØô€Mð
8ÜØ #À'È}Ø/ÈkØ'ô
ˆð
  Ð!=¸|È\Ï_É_Ø˜l×.Ñ.°¸QÀÈðOˆçØ04ˆKÐ,Ñ-ßØ&3ˆK˜
Ñ#ßØ&9ˆK˜
Ñ#ßÜ/DˆKÐ+Ò,ß#¯NÜ"9ˆK˜ÑßÔ5°g×>Ò>Ø"—‘ v¨rÓ2ˆHßS[ 8¨fÕ#4Ô7OÖ#OÜ(@ð ˜Ñô .BØ˜+Ð'9ó.KÑ*Ðá(KÜ#Ð$6Ó7ÈÐcgô)
Ñ%ˆ˜÷ Ü�N‰NÐ3°\·_±_ÀmÔTØ4AˆKÐ0Ñ1ßØ.2ˆLÔ+Ø04ˆKÐ,Ñ-ß&Ü7:Ð;RÓ7S�Ô4Ø×,×,Ð,Ü,Ð-=¸|È[ÔYÝKÙ)×+Ò+Ø49�Ð0Ñ1Ü/D�˜OÒ,ß"ð 4D×3QÑ3QÐR^Ð`qÓ3r�Ð/Ñ0øßØ/xˆKÐ+Ñ,ßÜ*.¨~Ó*>ˆLÔ'Ø,8×,GÑ,GˆKÐ(Ñ)Ü�zŠz˜+°EÔ:Ð:øÜô Ü�zŠzØ�b˜+ rØÑ0Ð3WÐXYÐWZÐ1[Ó\ð
ð ôõ 	ûðúss   ¯AH. Á6H. ÂH. ÂH. Â"H. Â*H. Â;*H. Ã&A8H. ÅH. Å3!H. ÆH. Æ5H. ÇH. Ç*H. Ç76H. È.I*È9&I%ÉI*É%I*a£  You are a subagent: this process's completion notice will NOT reach your parent, and the process is killed when you finish. Before you finish, either wait for it (process_manage wait), kill it, or hand it to your parent with process_manage(action='handoff', session_id=..., data='<purpose>') so the parent receives its completion. For CI watchers prefer returning the fact (PR number, SHA) and letting the parent watch.a>  The user sent a message while this command was running, so it was moved to the background WITHOUT being killed and is still running. You will be notified when it exits (notify_on_complete). Read the user's message and respond to it now; use process(action='poll'|'wait'|'log', session_id=...) to check on this command.c                óŒ   € V ^8„  d   QhR\         R\         R\        \         ,          R\         R\        \         ,          R\         /# )r   r   r3   r&   r4   r'   r)   )r	   r   )r   s   "r   r   r   û   sD   € ÷ ñ ÜðÜ"ðÜ)1´#­ðÜKNðä”c�]ðä),ñr   c                ó<   a aaaa€ VR8w  d   R# R V VVVV3R llpV# )a’  Build the ``yield_handler`` a foreground ``env.execute`` calls when the tool thread is
asked to yield (a user message arrived mid-command). Local backend only: the live Popen
is adopted by the process registry as a notify-on-complete background session and the
partial output is returned to the model right away. Other backends return None (no
adoptable host process) and the foreground wait continues.r*   Nc                ó0   € V ^8„  d   QhR\         R\        /# )r   Úoutput_so_farr   )r	   r.   )r   s   "r   r   Ú1yield_to_background_handler.<locals>.__annotate__  s   € ÷ 

ñ 

¤cð 

¬dñ 

r   c           
      óþ   <€ ^ RI Hp TP                  T SSSS;'       g    SSVR7      p\        W#S4       \        P                  RVP                  VP                  4       RVRRRVP                  RVP                  /# )	é    rg   )r   r&   r'   r(   r)   rŽ   z7foreground command yielded to background as %s (pid %s)rm   Ú
returncodeNÚyielded_session_idrn   )rz   r2   Úadopt_localÚ_stamp_routing_if_gatewayr?   r@   rA   rn   )	ÚprocrŽ   r2   Úsessionr   r&   r4   r)   r'   s	   &&  €€€€€r   Ú_handlerÚ-yield_to_background_handler.<locals>._handler  s‡   ø€ Ý;Ø"×.Ñ.Ø˜' sÐ4EØ!×6Ð6Ð%6ÀKØ'ð /ó )ˆô 	"Ð"2¸[ÔIÜ�‰ÐMÈwÏzÉzÐ[b×[fÑ[fÔgà�m \°4Ð9MÈwÏzÉzÐ[`Ðbi×bmÑbmð
ð 	
r   r   )r   r3   r&   r4   r'   r)   r˜   s   d$dddd r   Úyield_to_background_handlerrš   û   s!   ü€ ð �7ÔÙ÷

ô 

ð €Or   c                ó   € V ^8„  d   QhRR/# r   r   )r   s   "r   r   r     s   € ÷ Mñ MÈñ Mr   c                ó˜   € ^ RI HpHp V! 4       '       g
   RVn        R# \	        W4       VP
                  '       d   \        WV4       R# R# )zNRoute the adopted session's completion like a normal notify_on_complete spawn.r9   FN)r=   r:   r   r;   r"   r   r[   )r2   r—   r)   r:   r   s   &&&  r   r•   r•     s=   € çQÙ#×%Ò%Ø%*ˆÔ"ÙÜ˜7Ô4Ø××ÐÜ$Ð%5ÀÖLñ  r   ))Úwatcher_chat_idÚHERMES_SESSION_CHAT_ID)Úwatcher_user_idÚHERMES_SESSION_USER_ID)Úwatcher_user_nameÚHERMES_SESSION_USER_NAME)Úwatcher_thread_idÚHERMES_SESSION_THREAD_ID)Úwatcher_message_idÚHERMES_SESSION_MESSAGE_ID)rJ   ÚHERMES_SESSION_ID)Ú__doc__rƒ   ÚloggingrP   Útypingr   r   r   Ú	getLoggerr?   r}   r~   r|   r>   r   r   r"   r7   rD   r[   rŠ   r�   Ú_YIELDED_NOTErš   r•   r   r   r   Ú<module>r­      sÞ   ðñó Û Û 
ß &Ñ &à	×	Ò	Ð0Ó	1€ðð ð ð ð&ið ð]ð ð
€õAõ>ð=ØBG÷=òõ$6ð0Uð $%ð	Uð ðUð  %ðUð #'ðUð $÷UðrXð ðTð õ÷4Mr   