Ë
    ãß²j.3  ã                   óP  — d Z ddlZddlmZmZmZmZ h d£ZdZdZ	dZ
dZd	Zd
ddddœZddhZ G d„ d«      Z	 	 d4deeeeef         dedee   defd„Zdefd„Zdddddddd id d!d"œd g d#¢d$œd d%d"œd&œg d'¢d(œd)œd*d+dd,œd-œg d(œd.œZdd/lmZmZ  ej0                  dd0eed1„ d2¬3«       y)5af  Todo tool: in-memory, revisioned task list for multi-step work. State lives on the
AIAgent (one per session), is re-injected after context compression, and every write bumps
a monotonic revision so UI clients can reject stale updates. One ``todo_list`` tool: pass
``todos`` to write, omit to read; every call returns the full list. No system-prompt mutation.é    N)ÚAnyÚDictÚListÚOptional>   ÚpendingÚ	cancelledÚ	completedÚin_progressi   é   i Ð u   â€¦ [truncated]z@[Your active task list was preserved across context compression]z[x]z[>]z[ ]z[~])r	   r
   r   r   r   r
   c            
       ó  — e Zd ZdZd„ Zdeeeef      deeeef      fd„Z	ddeeeef      de
deeeef      fd„Zdeeeef      ddfd	„Zdeeeef      fd
„Zde
fd„Zdeeef   fd„Zddœdeeeef      dedeeeef      fd„Zdee   fd„Zededefd„«       Zedeeef   deeef   fd„«       Zedeeeef      ddfd„«       Zedeeeef      deeeef      fd„«       Zedeeeef      deeeef      fd„«       Zy)Ú	TodoStoreu‘   In-memory todo list, one per AIAgent. List position is priority; items are
    ``{id, content, status, parent?}`` â€” ``parent`` nests a subtask.c                 ó    — g | _         d| _        y )Nr   )Ú_itemsÚ	_revision©Úselfs    ú4/home/ubuntu/.hermes/hermes-agent/tools/todo_tool.pyÚ__init__zTodoStore.__init__   s   € Ø,.ˆŒØˆ�ó    ÚtodosÚreturnc                 ó†   — | j                  | j                  |«      D �cg c]  }| j                  |«      ‘Œ c}«      S c c}w )z@Validate, dedupe and order a whole new list (replace / restore).)Ú_normalize_orderÚ_dedupe_by_idÚ	_validate)r   r   Úts      r   Ú_fresh_itemszTodoStore._fresh_items"   s6   € à×$Ñ$À×ASÑASÐTYÓAZÖ%[¸A d§n¡n°QÕ&7Ò%[Ó\Ð\ùÒ%[s   Ÿ>Úmergec                 ó:  — | j                  «       }|r| j                  |«       n| j                  |«      | _        | j                  t        d…= | j                  | j                  «       | j                  |k7  r| xj                  dz  c_        | j                  «       S )zOReplace the list (default) or merge by id; returns the full list after writing.Né   )ÚreadÚ_merger   r   ÚMAX_TODO_ITEMSÚ_sanitize_parentsr   )r   r   r   Úbefores       r   ÚwritezTodoStore.write&   st   € à—‘“ˆÙØ�K‰K˜Õà×+Ñ+¨EÓ2ˆDŒKØ�K‰Kœ™Ð(Ø×Ñ˜tŸ{™{Ô+Ø�;‰;˜&Ò Ø�NŠN˜aÑ�NØ�y‰y‹{Ðr   Nc                 ó   — | j                   D �ci c]  }|d   |“Œ
 }}| j                  |«      D �]e  }t        |j                  dd«      «      j	                  «       }|sŒ0|j                  |«      }|€5| j                  |«      }|||d   <   | j                   j                  |«       Œx|j                  d«      r.| j                  t        |d   «      j	                  «       «      |d<   |j                  d«      r]t        |d   «      j	                  «       j                  «       t        v r-t        |d   «      j	                  «       j                  «       |d<   d|v s�Œ+t        |d   xs d«      j	                  «       }|r||d<   �ŒT|j                  dd«       �Œh | j                   D �ci c]  }|d   |j                  |d   |«      “Œ }	}| j                  t        |	j                  «       «      «      | _         yc c}w c c}w )zOUpdate existing items only in the fields provided; append new ones (validated).ÚidÚ NÚcontentÚstatusÚparent)r   r   ÚstrÚgetÚstripr   ÚappendÚ_cap_contentÚlowerÚVALID_STATUSESÚpopr   ÚlistÚvalues)
r   r   ÚitemÚexistingr   Úitem_idÚcurÚ	validatedr,   Úrebuilts
             r   r"   zTodoStore._merge3   s¿  € à15·±Ö=¨�D˜‘J Ñ$Ð=ˆÐ=Ø×#Ñ# EÓ*ó 	,ˆAÜ˜!Ÿ%™%  b›/Ó*×0Ñ0Ó2ˆGÙØØ—,‘,˜wÓ'ˆCØˆ{Ø ŸN™N¨1Ó-�	Ø,5�˜ 4™Ñ)Ø—‘×"Ñ" 9Ô-ØØ�u‰u�YÔØ!%×!2Ñ!2´3°q¸±|Ó3D×3JÑ3JÓ3LÓ!M��I‘Ø�u‰u�XŒ¤3 q¨¡{Ó#3×#9Ñ#9Ó#;×#AÑ#AÓ#CÄ~Ñ#UÜ # A h¡KÓ 0× 6Ñ 6Ó 8× >Ñ >Ó @��H‘Ø˜1‹}Ü˜Q˜x™[Ò.¨BÓ/×5Ñ5Ó7�ÙØ$*�C˜“Mà—G‘G˜H dÖ+ð'	,ð* KOÏ+É+ÖVÀ$�4˜‘:˜xŸ|™|¨D°©J¸Ó=Ñ=ÐVˆÐVØ×+Ñ+¬D°·±Ó1AÓ,BÓCˆ�ùò/ >ùò, Ws   �G6Æ& G;c                 ó\   — | j                   D �cg c]  }|j                  «       ‘Œ c}S c c}w ©N)r   Úcopy)r   r7   s     r   r!   zTodoStore.readN   s    € Ø(,¯©Ö4 �—	‘	•Ò4Ð4ùÒ4s   �)c                 ó,   — t        | j                  «      S r>   )Úboolr   r   s    r   Ú	has_itemszTodoStore.has_itemsQ   s   € Ü�D—K‘KÓ Ð r   c                 ó<   — | j                  «       | j                  dœS )z,Full state clients can reconcile atomically.)r   Úrevision)r!   r   r   s    r   ÚsnapshotzTodoStore.snapshotT   s   € àŸ™›°$·.±.ÑAÐAr   r   )rD   rD   c                óð   — | j                  |«      dt         | _        	 t        dt	        |xs d«      «      | _        | j                  «       S # t        t        f$ r d| _        Y | j                  «       S w xY w)z@Restore a trusted snapshot without manufacturing a new revision.Nr   )	r   r#   r   ÚmaxÚintr   Ú	TypeErrorÚ
ValueErrorr!   )r   r   rD   s      r   ÚrestorezTodoStore.restoreX   sn   € à×'Ñ'¨Ó.¨´Ð?ˆŒð	Ü  ¤C¨ª°AÓ$6Ó7ˆDŒNð �y‰y‹{Ðøô œ:Ð&ò 	ØˆD�NØ�y‰y‹{Ðð	ús   ŸA ÁA5Á4A5c                 óÂ  ‡‡— | j                   syi Š| j                   D ]8  }|j                  d«      sŒ‰j                  |d   g «      j                  |«       Œ: dt        t
        t
        f   dt        dt        t
           dt        fˆˆfd„Št        g}| j                   D ]  }|j                  d«      rŒ ‰|d|«       Œ  t        |«      d	kD  rd
j                  |«      S dS )u4  Render the list for post-compression injection, or None if nothing active. Only
        pending/in_progress items are injected â€” finished ones make the model re-do work after
        compression. A parent is kept (with its real status marker) when any descendant is
        active so subtasks keep context.Nr,   r7   ÚdepthÚoutr   c                 ó2  •— g }d}‰j                  | d   g «      D ]  }| ‰	||dz   |«      z  }Œ | d   t        v xs |}|rVt        j                  | d   d«      }|j                  d|z  › d|› d| d   › d	| d
   › d| d   › d�
«       |j	                  |«       |S )NFr(   r    r+   z[?]z  z- Ú z. r*   z (ú))r.   Ú_ACTIVE_STATUSESÚ_STATUS_MARKERSr0   Úextend)
r7   rM   rN   Ú	kid_linesÚhas_active_kidÚkidÚkeepÚmarkerÚchildrenÚrenders
           €€r   r[   z.TodoStore.format_for_injection.<locals>.renderm   sÆ   ø€ Ø#%ˆIØ"ˆNØ—|‘| D¨¡J°Ó3ò D�Ø¡&¨¨e°a©i¸Ó"CÑC‘ðDà˜‘>Ô%5Ð5ÒG¸ˆDÙÜ(×,Ñ,¨T°(©^¸UÓC�Ø—
‘
˜d U™l˜^¨2¨f¨X°Q°t¸D±z°lÀ"Ø" 9™oÐ.¨b°°h±Ð0@ÀðCô Dà—
‘
˜9Ô%ØˆKr   r   r    Ú
)r   r.   Ú
setdefaultr0   r   r-   rH   r   rA   ÚTODO_INJECTION_HEADERÚlenÚjoin)r   r7   ÚlinesrZ   r[   s      @@r   Úformat_for_injectionzTodoStore.format_for_injectiona   sÖ   ù€ ð
 �{Š{ØØ46ˆØ—K‘Kò 	EˆDØ�x‰x˜Õ!Ø×#Ñ# D¨¡N°BÓ7×>Ñ>¸tÕDð	Eð	œœc¤3˜h™ð 	´ð 	¼$¼s¹)ð 	Ìö 	ô 'Ð'ˆØ—K‘Kò 	'ˆDØ—8‘8˜HÕ%Ù�t˜Q Õ&ð	'ô $' u£:°¢>ˆt�y‰y˜ÓÐ;°tÐ;r   r*   c                 ój   — t        | «      t        kD  r | dt        t        t        «      z
   t        z   S | S )zSTruncate to MAX_TODO_CONTENT_CHARS keeping the head (the actionable part) + marker.N)r_   ÚMAX_TODO_CONTENT_CHARSÚ_TRUNCATION_MARKER)r*   s    r   r1   zTodoStore._cap_content€   s6   € ô ˆw‹<Ô0Ò0ØÐLÔ2´SÔ9KÓ5LÑLÐMÔPbÑbÐbØˆr   r7   c                 ó
  — t        | t        «      sddddœS t        | j                  dd«      «      j	                  «       xs d}t        | j                  dd«      «      j	                  «       }t        | j                  dd«      «      j	                  «       j                  «       }||rt        j                  |«      nd	|t        v r|nddœ}t        | j                  d
«      xs d«      j	                  «       }|r
||k7  r||d
<   |S )zUNormalize one item to ``{id, content, status, parent?}`` (placeholders when missing).ú?z(invalid item)r   ©r(   r*   r+   r(   r)   r*   r+   z(no description)r,   )	Ú
isinstanceÚdictr-   r.   r/   r2   r   r1   r3   )r7   r9   r*   r+   Úresultr,   s         r   r   zTodoStore._validate‡   sê   € ô ˜$¤Ô%ØÐ*:ÀiÑPÐPÜ�d—h‘h˜t RÓ(Ó)×/Ñ/Ó1Ò8°SˆÜ�d—h‘h˜y¨"Ó-Ó.×4Ñ4Ó6ˆÜ�T—X‘X˜h¨	Ó2Ó3×9Ñ9Ó;×AÑAÓCˆØÙ@GœY×3Ñ3°GÔ<ÐM_Ø&,´Ñ&>™FÀIñOˆô �T—X‘X˜hÓ'Ò-¨2Ó.×4Ñ4Ó6ˆÙ�f Ò'Ø%ˆF�8ÑØˆr   Úitemsc                 ól  — | D �ci c]  }|d   |“Œ
 }}| D ].  }|j                  d«      sŒ|d   |vsŒ|j                  dd«       Œ0 | D ]d  }|d   h|}}|j                  d«      sŒ|d   |v r|j                  dd«       Œ7|j                  |d   «       ||d      }|j                  d«      rŒHŒf yc c}w )zNDrop dangling parent refs and break cycles in place (such items become roots).r(   r,   N)r.   r4   Úadd)rl   r7   Úby_idÚseenÚnodes        r   r$   zTodoStore._sanitize_parents—   sÎ   € ð /4Ö4 d��d‘˜TÑ!Ð4ˆÐ4Øò 	)ˆDØ�x‰x˜Õ! d¨8¡n¸EÒ&AØ—‘˜ 4Õ(ð	)ð ò 	-ˆDØ˜t™*˜ t�$ˆDØ—(‘(˜8Õ$Ø˜‘> TÑ)Ø—H‘H˜X tÔ,ØØ—‘˜˜h™Ô(Ø˜T (™^Ñ,�ð —(‘(˜8Ö$ñ	-ùò	 5s   …B1c                 ó  — i }t        | «      D ]L  \  }}t        |t        «      r)t        |j	                  dd«      «      j                  «       nd|› �}|||xs d<   ŒN t        |j                  «       «      D �cg c]  }| |   ‘Œ	 c}S c c}w )zDCollapse duplicate ids, keeping the last occurrence in its position.r(   r)   Ú
__invalid_rg   )Ú	enumerateri   rj   r-   r.   r/   Úsortedr6   )r   Ú
last_indexÚir7   Úkeys        r   r   zTodoStore._dedupe_by_id§   sŠ   € ð &(ˆ
Ü  Ó'ò 	'‰GˆAˆtÜ5?ÀÄdÔ5K”#�d—h‘h˜t RÓ(Ó)×/Ñ/Ô1ÐS]Ð^_Ð]`ÐQaˆCØ%&ˆJ�s’z˜cÒ"ð	'ô #)¨×):Ñ):Ó)<Ó"=Ö>˜Q��a“Ò>Ð>ùÒ>s   Á8Bc                 ó  — | D �cg c]  }|d   ‘Œ	 }}t        d„ | D «       «      sd|vr| S |j                  d«      }d|d| vr| S | j                  «       }|j                  |j                  d«      |j	                  |«      «       |S c c}w )u£   Lift the in_progress step ahead of any earlier pending placeholder. Nested lists
        keep authored order â€” reordering would tear a subtask from its siblings.r+   c              3   ó>   K  — | ]  }|j                  d «      –— Œ y­w)r,   N)r.   )Ú.0r7   s     r   ú	<genexpr>z-TodoStore._normalize_order.<locals>.<genexpr>µ   s   è ø€ Ò4 dˆt�x‰x˜×!Ñ4ùs   ‚r
   r   N)ÚanyÚindexr?   Úinsertr4   )rl   r7   ÚstatusesÚactive_indexÚ
normalizeds        r   r   zTodoStore._normalize_order°   s�   € ð 05Ö5 t�D˜“NÐ5ˆÐ5ÜÑ4¨eÔ4Ô4¸ÈXÑ8UØˆLØ—~‘~ mÓ4ˆØ˜H ] lÐ3Ñ3ØˆLØ—Z‘Z“\ˆ
Ø×Ñ˜(Ÿ.™.¨Ó3°Z·^±^ÀLÓ5QÔRØÐùò 6s   …B)F)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r-   r   r   rA   r&   r"   r!   rB   rE   rK   r   rb   Ústaticmethodr1   r   r$   r   r   © r   r   r   r      s  „ ñJòð] $ t¨C°¨H¡~Ñ"6ð ]¸4ÀÀSÈ#ÀXÁÑ;Oó ]ñ˜4  S¨# X¡Ñ/ð ¸ð ÈÈdÐSVÐX[ÐS[ÉnÑI]ó ðD˜D  c¨3 h¡Ñ0ð D°Tó Dð65�d˜4  S ™>Ñ*ó 5ð!˜4ó !ðB˜$˜s C˜x™.ó Bð GHò ˜T $ s¨C x¡.Ñ1ð Àð ÈDÐQUÐVYÐ[^ÐV^ÑQ_ÑL`ó ð< h¨s¡mó <ð> ð˜cð  cò ó ðð ð˜˜S #˜X™ð ¨4°°S°©>ò ó ðð ð-  d¨3°¨8¡nÑ!5ð -¸$ò -ó ð-ð ð?˜T $ s¨C x¡.Ñ1ð ?°d¸4ÀÀSÀ¹>Ñ6Jò ?ó ð?ð ð  T¨#¨s¨(¡^Ñ 4ð ¸¸dÀ3ÈÀ8¹nÑ9Mò ó ñr   r   Fr   r   Ústorer   c                 ó  ‡— |€t        d«      S | €|j                  «       }nit        | t        «      r	 t	        j
                  | «      } t        | t        «      s!t        dt        | «      j                  › �«      S |j                  | |«      }dt        |«      i}dD ]  Št        ˆfd„|D «       «      |‰<   Œ t	        j                  ||j                  «       d   |dœd	¬
«      S # t        j                  t        f$ r t        d«      cY S w xY w)zWWrite ``todos`` (replace, or ``merge`` by id) or read when None -> list + summary JSON.zTodoStore not initializedz7todos must be a list of objects, got unparseable stringztodos must be a list, got Útotal©r   r
   r	   r   c              3   ó4   •K  — | ]  }|d    ‰k(  sŒd–— Œ y­w)r+   r    Nrˆ   )r{   rw   r+   s     €r   r|   ztodo_tool.<locals>.<genexpr>Ñ   s   øè ø€ ÒH A°!°H±+ÀÓ2GœaÑHùs   ƒ‘rD   )r   rD   ÚsummaryF)Úensure_ascii)Ú
tool_errorr!   ri   r-   ÚjsonÚloadsÚJSONDecodeErrorrI   r5   Útyperƒ   r&   r_   ÚsumÚdumpsrE   )r   r   r‰   rl   rŽ   r+   s        @r   Ú	todo_toolr—   ¿   s	  ø€ ð €}ÜÐ5Ó6Ð6Ø€}Ø—
‘
“‰ä�eœSÔ!ð]ÜŸ
™
 5Ó)�ô ˜%¤Ô&ÜÐ :¼4À»;×;OÑ;OÐ:PÐQÓRÐRØ—‘˜E 5Ó)ˆØœ˜E›
Ð#€GØFò IˆÜÓH¨ÔHÓHˆ�ŠðIä�:‰: °5·>±>Ó3CÀJÑ3OØ")ñ+Ø9>ô@ð @øô ×(Ñ(¬)Ð4ò ]Ü!Ð"[Ó\Ò\ð]ús   ³C" Ã"$D	ÄD	c                   ó   — y)z;Todo tool has no external requirements -- always available.Trˆ   rˆ   r   r   Úcheck_todo_requirementsr™   Ö   s   € àr   Ú	todo_lista5  Track a task list for multi-step work (3+ steps). Use for complex tasks with 3+ steps or when the user provides multiple tasks. For 'all N items' tasks, enumerate every instance as its own checklist item so none are silently dropped. Call with no parameters to read the current list.
List order is priority. Only ONE item in_progress at a time. Break large phases into subtasks via parent. Mark an item completed only after the work is verified done, never based on intent. If something fails, cancel it and add a revised item. Always returns the full current list.ÚobjectÚarrayzTask items to write.r”   ÚstringzTask description)r”   ÚdescriptionrŒ   )r”   ÚenumzNOptional id of another item, making this a nested subtask. Omit for top-level.)r(   r*   r+   r,   rh   )r”   Ú
propertiesÚrequired)r”   rž   rl   Úbooleanzltrue: update existing items by id, add new ones. false (default): replace the entire list with a fresh plan.)r”   rž   Údefault)r   r   )Únamerž   Ú
parameters)Úregistryr�   Útodoc                 óz   — t        | j                  d«      | j                  dd«      |j                  d«      ¬«      S )Nr   r   Fr‰   )r   r   r‰   )r—   r.   )ÚargsÚkws     r   ú<lambda>r«     s/   € œyØ�h‰h�wÓ t§x¡x°¸Ó'?ÀrÇvÁvÈgÃô X€ r   u   ðŸ“‹)r¤   ÚtoolsetÚschemaÚcheck_fnÚhandlerÚemoji)NFN)r†   r‘   Útypingr   r   r   r   r3   rd   r#   ÚMAX_TODO_RESULT_CHARSre   r^   rS   rR   r   r-   rA   r—   r™   ÚTODO_SCHEMAÚtools.registryr¦   r�   Úregisterrˆ   r   r   ú<module>r¶      sr  ðñbó
 ß ,Ó ,âE€ð Ð Ø€ð  Ð Ø&Ð ð [Ð Ø %°eÈÐ\aÑb€Ø˜}Ð-Ð ÷bñ bðJ KPØ+/ñ@�X˜d 4¨¨S¨¡>Ñ2Ñ3ð @À4ð @Ø˜iÑ(ð@Ø47ó@ð. ó ð ð		6ð ð  Ø5à$ð # Hðð %-Ø+=ñ$ð
 %-Ú$Xñ#ð
 %-Ø+{ñ#ñ#ò" !<ñ'ñð4 "ðRð !ññ5"
ðF ñK&ñ6€÷r 0à €× Ñ Ø	˜f¨[ÐCZñXà
ö	r   