§
    ÷žyj?  ã                  ó„   — d Z ddlmZ ddlZddlmZmZmZ  eddh¦  «        Z	dZ
dd
„Zdd„Zdd„Zdde
ddœdd„Zg d¢ZdS )u  Turn-end guard for kanban workers.

Kanban workers must end with ``kanban_complete`` or ``kanban_block``. Models
(especially GLM / Qwen families) sometimes narrate the next step
("Let me write the report now") and stop with ``finish_reason=stop`` and no
tool calls. Hermes treats that as a clean exit â†’ ``rc=0`` â†’ dispatcher
``protocol_violation``.

This module is policy-only: when a kanban worker tries to finish without a
terminal board tool, return a bounded synthetic nudge so the conversation
loop continues instead of exiting.
é    )ÚannotationsN)ÚAnyÚIterableÚOptionalÚkanban_completeÚkanban_blocké   ÚreturnÚboolc                 ó  — t           j                             d¦  «        } | �*|                      ¦   «                              ¦   «         dv rdS t           j                             d¦  «        pd                     ¦   «         }t          |¦  «        S )zÍReturn whether the kanban stop-guard is active for this process.

    On when ``HERMES_KANBAN_TASK`` is set (dispatcher-spawned worker), unless
    ``HERMES_KANBAN_STOP_NUDGE`` explicitly disables it.
    ÚHERMES_KANBAN_STOP_NUDGEN>   Ú0ÚnoÚoffÚfalseFÚHERMES_KANBAN_TASKÚ )ÚosÚenvironÚgetÚstripÚlowerr   )ÚenvÚtasks     ú7/home/ragecks/.hermes/hermes-agent/agent/kanban_stop.pyÚkanban_stop_nudge_enabledr      sr   € õ Œ*�.Š.Ð3Ñ
4Ô
4€CØ
€˜3Ÿ9š9™;œ;×,Ò,Ñ.Ô.Ð2MÐMÐMØˆuÝŒJ�NŠNÐ/Ñ0Ô0Ð6°B×=Ò=Ñ?Ô?€DÝ�‰:Œ:Ðó    Útcr   Ústrc                ó¶  — t          | t          ¦  «        rr|                      d¦  «        }t          |t          ¦  «        r$t          |                     d¦  «        pd¦  «        S t          |                      d¦  «        pd¦  «        S t	          | dd ¦  «        }|� t          t	          |dd¦  «        pd¦  «        S t          t	          | dd¦  «        pd¦  «        S )NÚfunctionÚnamer   )Ú
isinstanceÚdictr   r   Úgetattr)r   Úfns     r   Ú_tool_call_namer'   &   sÅ   € Ý�"•dÑÔð )Ø�VŠV�JÑÔˆÝ�b�$ÑÔð 	-Ý�r—v’v˜f‘~”~Ð+¨Ñ,Ô,Ð,Ý�2—6’6˜&‘>”>Ð' RÑ(Ô(Ð(Ý	��Z Ñ	&Ô	&€BØ	€~Ý•7˜2˜v rÑ*Ô*Ð0¨bÑ1Ô1Ð1Ý�w�r˜6 2Ñ&Ô&Ð,¨"Ñ-Ô-Ð-r   ÚmessagesúIterable[dict] | Nonec                óP  — | sdS | D ]ž}t          |t          ¦  «        sŒ|                     d¦  «        }|dk    r5|                     d¦  «        pg D ]}t          |¦  «        t          v r  dS ŒŒh|dk    r0t          |                     d¦  «        pd¦  «        }|t          v r dS ŒŸdS )	zATrue if this conversation already invoked a terminal kanban tool.FÚroleÚ	assistantÚ
tool_callsTÚtoolr"   r   )r#   r$   r   r'   Ú_TERMINAL_KANBAN_TOOLSr   )r(   Úmsgr+   r   r"   s        r   Úsession_called_kanban_terminalr1   2   sÕ   € àð ØˆuØð ð ˆÝ˜#�tÑ$Ô$ð 	ØØ�wŠw�v‰ŒˆØ�;ÒÐØ—g’g˜lÑ+Ô+Ð1¨rð  ð  �Ý" 2Ñ&Ô&Õ*@Ð@Ð@Ø˜4˜4˜4ð Að ð �VŠ^ˆ^Ý�s—w’w˜v‘”Ð,¨"Ñ-Ô-ˆDØÕ-Ð-Ð-Ø�t�tøØˆ5r   )r(   ÚattemptsÚmax_attemptsÚtask_idr2   Úintr3   r4   úOptional[str]c                óÎ   — t          ¦   «         sdS ||k    rdS t          | ¦  «        rdS |p t          j                             d¦  «        pd                     ¦   «         pd}d|› d�S )zÛReturn a synthetic follow-up when a kanban worker exits without a terminal tool.

    Returns ``None`` when the guard should not fire (not a kanban worker,
    already completed/blocked, or nudge budget exhausted).
    Nr   r   z	this taskzj[System: You are a Hermes kanban worker. A plain-text reply is NOT a terminal state for the board.

Task `u!  ` is still `running`. Ending now without a board tool causes a protocol violation (clean exit with no `kanban_complete` / `kanban_block`).

Do this immediately in your next response â€” do not narrate intent:
1. Finish any remaining deliverable (write the required file(s) now).
2. Call `kanban_complete(summary=..., artifacts=[...])` if the work is done, OR `kanban_block(reason=...)` if you are blocked.

Never end a turn with only a promise of future action. Repeated protocol violations will block this task and require manual intervention.])r   r1   r   r   r   r   )r(   r2   r3   r4   Útids        r   Úbuild_kanban_stop_nudger9   E   s‹   € õ %Ñ&Ô&ð ØˆtØ�<ÒÐØˆtÝ% hÑ/Ô/ð ØˆtàÐ@•b”j—n’nÐ%9Ñ:Ô:Ð@¸b×
GÒ
GÑ
IÔ
IÐ
XÈ[€Cð
	Uàð
	Uð 
	Uð 
	Uðr   )r9   r   r1   )r
   r   )r   r   r
   r   )r(   r)   r
   r   )
r(   r)   r2   r5   r3   r5   r4   r6   r
   r6   )Ú__doc__Ú
__future__r   r   Útypingr   r   r   Ú	frozensetr/   Ú_DEFAULT_MAX_ATTEMPTSr   r'   r1   r9   Ú__all__© r   r   ú<module>rA      sæ   ððð ð #Ð "Ð "Ð "Ð "Ð "à 	€	€	€	Ø *Ð *Ð *Ð *Ð *Ð *Ð *Ð *Ð *Ð *ð #˜Ð$5°~Ð#FÑGÔGÐ àÐ ð
ð 
ð 
ð 
ð	.ð 	.ð 	.ð 	.ðð ð ð ð* '+ØØ-Ø!ð ð  ð  ð  ð  ð  ðFð ð €€€r   