Ë
    áß²jÙ-  ã                   ó\   — d Z ddlZddlZddlmZ  ej
                  d«      Z G d„ d«      Zy)a<  User-facing status / warning / notice plumbing for ``AIAgent``.

Safe printing, quiet-mode gating, deduped context-overflow warnings, and the buffered retry
chatter that is shown only when every retry/fallback is exhausted.
Extracted from ``run_agent.py``; every method resolves through ``AIAgent``'s MRO unchanged.
é    N)ÚActivityProvenanceÚ	run_agentc                   ó‚  — e Zd ZdZddœdefd„Zdddœdedefd„Zd	efd
„Zd	efd„Zde	de	d	dfd„Z
de	de	de	d	dfd„Zd	efd„Zde	d	dfd„Zde	d	dfd„Zde	d	dfd„Zde	deded	dfd„Zdeded	dfd„Zd+d„Zd+d„Zde	d	dfd „Zd!e	d	dfd"„Zd!e	d	dfd#„Zde	de	d	dfd$„Zde	d	dfd%„Zde	d	dfd&„Zde	d	dfd'„Zd+d(„Zd+d)„Zd+d*„Zy),ÚStatusOutputMixinzRStatus/warning/notice emission and retry-chatter buffering (see module docstring).F)Ú
diagnosticr   c                ó¦   — t        | dd«      ry|r| j                  «       sy	  | j                  xs t        |i |¤Ž y# t        t
        f$ r Y yw xY w)z²Print that swallows broken pipes / closed stdout (headless stdout can vanish mid-session);
        routes through ``self._print_fn`` so the CLI can inject an ANSI-aware renderer.Ú_mute_notification_replyFN)ÚgetattrÚ_warning_presentation_enabledÚ	_print_fnÚprintÚOSErrorÚ
ValueError)Úselfr   ÚargsÚkwargss       ú8/home/ubuntu/.hermes/hermes-agent/agent/status_output.pyÚ_safe_printzStatusOutputMixin._safe_print   sY   € ô �4Ð3°UÔ;ØÙ˜d×@Ñ@ÔBØð	Ø$ˆT�^‰^Ò$œu tÐ6¨vÓ6øÜœÐ$ò 	Ùð	ús   £> ¾AÁA)Úforcer   r   c                óÄ   — t        | dd«      ry|r| j                  «       sy|s)t        | dd«      s0| j                  «       r| j                  r | j                  |i |¤Ž yyy)uÐ   Verbose print â€” suppressed while tokens are streaming (allowed during tool execution) and after
        the main response; ``force=True`` bypasses both. ``suppress_status_output`` (``hermes chat -q``) wins.Úsuppress_status_outputFNÚ_mute_post_response)r
   r   Ú_has_stream_consumersÚ_executing_toolsr   )r   r   r   r   r   s        r   Ú_vprintzStatusOutputMixin._vprint   so   € ô �4Ð1°5Ô9ØÙ˜d×@Ñ@ÔBØÙœ Ð'<¸eÔDÈ×IcÑIcÔIeÐnr÷  oDò  oDØˆD×Ñ˜dÐ- fÓ-ð oDÐDó    Úreturnc                 ó    — | j                   �y	 t        t        j                  j	                  «       «      S # t
        t        t        f$ r Y yw xY w)z©True when quiet-mode spinner output has a safe sink (``_print_fn`` or a real TTY); a raw spinner
        on a non-TTY stdout can corrupt protocol streams (ACP JSON-RPC).TF)r   ÚboolÚsysÚstdoutÚisattyÚAttributeErrorr   r   ©r   s    r   Ú_should_start_quiet_spinnerz-StatusOutputMixin._should_start_quiet_spinner)   sG   € ð �>‰>Ð%Øð	ÜœŸ
™
×)Ñ)Ó+Ó,Ð,øÜ¤
¬GÐ4ò 	Ùð	ús   �&6 ¶AÁAc                 óx   — t        | dd«      ry| j                  xr | j                   xr t        | dd«      dk(  S )a.  True when quiet-mode tool summaries should print directly (CLI, no callback owns rendering);
        ``suppress_status_output`` always wins so ``[tool]``/``[done]`` never land in captured stdout.

        ``suppress_status_output`` (the strict machine-readable mode used by ``hermes chat -Q``) always
        wins: those flows neutralize the rendering callbacks, and without this gate the "no callback owns
        rendering" fallback would print ``[tool]``/``[done]`` spinner lines into the captured stdout it
        exists to keep clean (#93220).
        r   FÚplatformÚ Úcli)r
   Ú
quiet_modeÚtool_progress_callbackr$   s    r   Ú _should_emit_quiet_tool_messagesz2StatusOutputMixin._should_emit_quiet_tool_messages3   sB   € ô �4Ð1°5Ô9ØØ�‰Òm t×'BÑ'BÐ#BÒmÄwÈtÐU_ÐacÓGdÐhmÑGmÐmr   ÚnameÚoriginNc                ó€   — t        | |d«      }|r	  ||Ž  yy# t        $ r t        j                  d||d¬«       Y yw xY w)uh   Invoke ``self.<name>(*args)`` if set, swallowing errors â€” a driver callback must never break the loop.Nz%s error in %sT)Úexc_info)r
   Ú	ExceptionÚloggerÚdebug)r   r-   r.   r   Úcbs        r   Ú_call_callbackz StatusOutputMixin._call_callback@   sM   € ä�T˜4 Ó&ˆÙðLÙ�D’	ð øô ò LÜ—‘Ð-¨t°VÀd�ÖKðLús   ‘ ˜"=¼=ÚkindÚmessagec                óÎ   — ddl m} 	  |||«      r| j                  «       r!| j                  | j                  › |› �d¬«       | j                  d|||¬«       y# t
        $ r Y Œ!w xY w)zkPrint to the CLI (``_vprint(force=True)``) and forward to ``status_callback(kind, message)``. Never raises.r   )Úis_warning_statusT©r   Ústatus_callback©r.   N)Úgateway.warning_notificationsr9   r   r   Ú
log_prefixr1   r5   )r   r6   r7   r.   r9   s        r   Ú_emit_status_kindz#StatusOutputMixin._emit_status_kindI   sk   € åCð	Ù$ T¨7Ô3°t×7YÑ7YÔ7[Ø—‘ §¡Ð0°°	Ð:À$�ÔGð 	×ÑÐ-¨t°WÀVÐÕLøô ò 	Ùð	ús   ˆ:A Á	A$Á#A$c                 ó‚   — ddl m} 	  |t        | dt        | dd«      «      t        | dd «      «      S # t        $ r Y yw xY w)Nr   )Úwarning_notifications_enabledÚ_notification_platformr'   r)   Ú_notification_configT)r=   rA   r
   r1   )r   rA   s     r   r   z/StatusOutputMixin._warning_presentation_enabledS   sO   € ÝOð	Ù0Ü˜Ð6¼ÀÀjÐRWÓ8XÓYÜ˜Ð4°dÓ;óð øô ò 	áð	ús   ˆ)2 ²	>½>c                 ó>   — ddl m} | j                   ||«      «       y)zGA diagnostic on the lifecycle rail, without changing legacy formatting.r   ©ÚDiagnosticTextN)r=   rF   Ú_emit_status©r   r7   rF   s      r   Ú_emit_diagnostic_statusz)StatusOutputMixin._emit_diagnostic_status^   s   € å@Ø×Ñ™.¨Ó1Õ2r   c                 ó,   — | j                  d|d¬«       y)zDEmit a lifecycle status message (CLI + gateway ``status_callback``).Ú	lifecyclerG   r<   N©r?   ©r   r7   s     r   rG   zStatusOutputMixin._emit_statusc   s   € à×Ñ˜{¨G¸NÐÕKr   c                 ó,   — | j                  d|d¬«       y)zdEmit a user-visible warning for degraded side paths where the turn continues but the user must know.ÚwarnÚ_emit_warningr<   NrL   rM   s     r   rP   zStatusOutputMixin._emit_warningg   s   € à×Ñ˜v w°ÐÕGr   ÚreasonÚpreflight_tokensÚthreshold_tokensc                 ó  — |xs dj                  dd«      d   }d|f}t        | dd«      |k(  ry|| _        ddlm} |d	v r%| j                  d
|› d�t        j                  ¬«       | j                  |j                  |||¬«      «       y)uÖ   Warn (deduped on the block *kind* â€” ``cooldown`` / ``ineffective`` â€” not the countdown string;
        cleared by ``_clear_context_overflow_warn``) when context is over the threshold but compression is blocked.Úunknownú:é   r   Úctx_overflow_blockedÚ_last_ctx_overflow_warnN)Ú)CONTEXT_OVERFLOW_BLOCKED_WARNING_TEMPLATE)ÚcooldownÚineffectivezcompression blocked (ú))Ú
provenance)ÚtokensÚ	thresholdrQ   )
Úsplitr
   rY   Úagent.conversation_compressionrZ   Ú_touch_activityr   ÚAGENT_COMPRESSION_COOLDOWNrP   Úformat)r   rQ   rR   rS   Ú
_warn_kindÚ	_warn_keyrZ   s          r   Ú_warn_context_overflow_blockedz0StatusOutputMixin._warn_context_overflow_blockedk   s£   € ð Ò) 	×0Ñ0°°aÓ8¸Ñ;ˆ
Ø+¨ZÐ8ˆ	Ü�4Ð2°DÓ9¸YÒFØØ'0ˆÔ$Ý\ð Ð4Ñ4Ø× Ñ Ð#8¸¸ÀÐ!BÔOa×O|ÑO|Ð Ô}Ø×ÑÐD×KÑKØ#Ð/?Èð Ló 
õ 	r   Úcontext_lengthc                 óp   — d|f}t        | dd«      |k7  r"|| _        | j                  d|d›d|d›d�«       yy)a€  Deduped warning when uncompressed context exceeds the model limit; points the user at /compact.

        When compression is explicitly disabled (compression.enabled: false), long sessions can grow past
        the model context window with no compression to shrink them (#89297). Surface an actionable warning
        so the user knows to run /compact or enable compression.
        Úuncompressed_ctx_overflowrY   Nu   âš ï¸� Session context (~ú,z, tokens) exceeds the model context window (~z‡ tokens) with compression disabled (compression.enabled: false). Use /compact to compress history or enable compression in config.yaml.)r
   rY   rP   )r   rR   ri   rg   s       r   Ú#_warn_uncompressed_context_overflowz5StatusOutputMixin._warn_uncompressed_context_overflow|   s_   € ð 1°.ÐAˆ	Ü�4Ð2°DÓ9¸YÒFØ+4ˆDÔ(Ø×ÑØ+Ð,<¸QÐ+?ð @$Ø$2°1Ð#5ð 65ð6õð Gr   c                 ó   — d| _         y)zTReset the blocked-overflow warning dedup so it can re-fire on the next blocked turn.N)rY   r$   s    r   Ú_clear_context_overflow_warnz.StatusOutputMixin._clear_context_overflow_warn�   s
   € à'+ˆÕ$r   c                 ó,   — | j                  d|d¬«       y)zCFire a structured ``AgentNotice`` to the active driver (TUI / CLI).Únotice_callbackÚ_emit_noticer<   N©r5   )r   Únotices     r   rr   zStatusOutputMixin._emit_notice‘   s   € à×ÑÐ-¨v¸nÐÕMr   Úkeyc                 ó,   — | j                  d|d¬«       y)zEClear a previously-fired sticky notice by ``key`` (e.g. on recovery).Únotice_clear_callbackÚ_emit_notice_clearr<   Nrs   )r   ru   s     r   rx   z$StatusOutputMixin._emit_notice_clear•   s   € à×ÑÐ3°SÐAUÐÕVr   Útextc                 óN   — | j                  |«       | j                  d|d¬«       y)z‘Rewrite the live status line (CLI spinner, TUI ``thinking.delta``, gateway activity)
        so long provider waits are not an anonymous spinner.Úthinking_callbackÚ_emit_wait_noticer<   N)rc   r5   )r   ry   s     r   r|   z#StatusOutputMixin._emit_wait_notice™   s)   € ð 	×Ñ˜TÔ"Ø×ÑÐ/°Ð>QÐÕRr   c                 ó>   — ddl m} | j                   ||«      «       y ©Nr   rE   )r=   rF   r|   )r   ry   rF   s      r   Ú_emit_diagnostic_waitz'StatusOutputMixin._emit_diagnostic_waitŸ   s   € Ý@Ø×Ñ™~¨dÓ3Õ4r   c                 óZ   — t        | dd«      }|€	g x}| _        |j                  ||f«       y)z÷Buffer a retry/fallback line as ``(kind, text)`` until we know whether the turn recovered.

        ``kind`` is ``"status"`` (replays via ``_emit_status``), ``"vprint"`` (``_vprint(force=True)``) or
        ``"warn"`` (``_emit_warning``).
        Ú_retry_status_bufferN)r
   r�   Úappend)r   r6   r7   Úbufs       r   Ú_buffer_retry_messagez'StatusOutputMixin._buffer_retry_message¦   s5   € ô �dÐ2°DÓ9ˆØˆ;Ø.0Ð0ˆC�$Ô+Ø�
‰
�D˜'�?Õ#r   c                 ó(   — | j                  d|«       y )NÚstatus©r„   rM   s     r   Ú_buffer_statusz StatusOutputMixin._buffer_status±   ó   € Ø×"Ñ" 8¨WÕ5r   c                 ó>   — ddl m} | j                   ||«      «       y r~   )r=   rF   rˆ   rH   s      r   Ú_buffer_diagnostic_statusz+StatusOutputMixin._buffer_diagnostic_status´   s   € Ý@Ø×Ñ™N¨7Ó3Õ4r   c                 ó(   — | j                  d|«       y )NÚvprintr‡   rM   s     r   Ú_buffer_vprintz StatusOutputMixin._buffer_vprint¸   r‰   r   c                 óD   — t        | dd«      }|r|j                  «        yy)u=   Drop buffered retry messages â€” call on successful recovery.r�   N)r
   Úclear)r   rƒ   s     r   Ú_clear_status_bufferz&StatusOutputMixin._clear_status_buffer»   s"   € ä�dÐ2°DÓ9ˆÙØ�I‰I�Kð r   c                 ó¨   — t        | dd«      }|syd| _        t        |t        «      r|n|gD ]  }	 | j	                  |«       Œ y# t
        $ r Y Œ#w xY w)a;  Surface the one-shot fallback-switch notice on successful recovery: a provider switch is durable
        state operators must see, unlike the retry chatter ``_clear_status_buffer`` drops. Emitted once, then
        cleared; on terminal failure the buffered switch line is flushed instead (``_flush_status_buffer``).Ú_pending_fallback_noticeN)r
   r“   Ú
isinstanceÚlistrI   r1   )r   rt   Úitems      r   Ú_emit_pending_fallback_noticez/StatusOutputMixin._emit_pending_fallback_noticeÁ   sd   € ô ˜Ð9¸4Ó@ˆÙØà(,ˆÔ%Ü(¨´Ô6‘F¸V¸Hò 	ˆDðØ×,Ñ,¨TÕ2ñ	øô ò áðús   ±AÁ	AÁAc                 óP  — d| _         t        | dd«      }|syt        |«      }|j                  «        | j                  | j
                  dœ}|D ]G  \  }}	 ||v r ||   |«       n1| j                  «       r!| j                  | j                  › |› �d¬«       ŒI y# t        $ r Y ŒVw xY w)uZ   Emit buffered retry messages â€” call on terminal failure so the user sees what was tried.Nr�   )r†   rO   Tr:   )
r“   r
   r•   r�   rG   rP   r   r   r>   r1   )r   rƒ   ÚmessagesÚreplayr6   Úmsgs         r   Ú_flush_status_bufferz&StatusOutputMixin._flush_status_bufferÑ   sµ   € ð )-ˆÔ%Ü�dÐ2°DÓ9ˆÙØä˜“9ˆØ�	‰	ŒØ ×-Ñ-°t×7IÑ7IÑJˆØ!ò 	‰IˆD�#ðØ˜6‘>Ø �F˜4‘L Õ%à×9Ñ9Ô;ØŸ™¨¯©Ð'8¸¸Ð%>Àd˜ÔKøñ	øô ò Ùðús   ÁABÂ	B%Â$B%)r   N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r%   r,   Ústrr5   r?   r   rI   rG   rP   Úintrh   rm   ro   rr   rx   r|   r   r„   rˆ   r‹   rŽ   r‘   r—   rœ   © r   r   r   r      sÂ  „ Ù\à49ò 
¨Tó 
ð ,1ÀUò . Dð .¸dó .ð¨Tó ðn°$ó nðL 3ð L°sð L¸tó LðM cð M°Cð MÀCð MÈDó Mð	¨tó 	ð3¨sð 3°tó 3ð
L Cð L¨Dó LðH Sð H¨Tó Hð°Sð ÈCð Ðcfð Ðkoó ð"ÀCð ÐY\ð Ðaeó ó",óNðW cð W¨dó WðS cð S¨dó Sð5¨#ð 5°$ó 5ð	$¨#ð 	$¸ð 	$Àó 	$ð6 cð 6¨dó 6ð5°ð 5¸ó 5ð6 cð 6¨dó 6óóô r   r   )r    Úloggingr    Úagent.session_activityr   Ú	getLoggerr2   r   r£   r   r   ú<module>r§      s5   ðñó Û 
å 5ð 
ˆ×	Ñ	˜;Ó	'€÷Tò Tr   