
    i3A                        d Z ddlZddlmZmZmZmZ ddlmZm	Z	 ddZ
dddded	ee         d
ee         dee         dz  deeee         gef                  dee         fdZ	 ddddded	ee         d
ededz  dedz  defdZded	ee         d
ededef
dZ	 dddded	ee         dedededz  f
dZded	ee         dededz  fdZ	 dded	ee         d
ee         dee         deeee         gef                  dee         fdZdS )zShared curses-based UI components for Hermes CLI.

Used by `hermes tools` and `hermes skills` for interactive checklists.
Provides a curses multi-select with keyboard navigation, plus a
text-based numbered fallback for terminals without curses support.
    N)CallableListOptionalSet)Colorscolorreturnc                      	 t           j                                        sdS ddl} |                     t           j        | j                   dS # t          $ r Y dS w xY w)u  Flush any stray bytes from the stdin input buffer.

    Must be called after ``curses.wrapper()`` (or any terminal-mode library
    like simple_term_menu) returns, **before** the next ``input()`` /
    ``getpass.getpass()`` call.  ``curses.endwin()`` restores the terminal
    but does NOT drain the OS input buffer — leftover escape-sequence bytes
    (from arrow keys, terminal mode-switch responses, or rapid keypresses)
    remain buffered and silently get consumed by the next ``input()`` call,
    corrupting user data (e.g. writing ``^[^[`` into .env files).

    On non-TTY stdin (piped, redirected) or Windows, this is a no-op.
    Nr   )sysstdinisattytermiostcflushTCIFLUSH	Exception)r   s    9/home/ubuntu/.hermes/hermes-agent/hermes_cli/curses_ui.pyflush_stdinr      sl    y!! 	F	7#344444   s   A )A 
AA)cancel_returns	status_fntitleitemsselectedr   r   c                f    t          |          t          j                                        sS 	 ddlt          |          dg fd}                    |           t                       d         d         nS # t          $ r t           |          cY S w xY w)a  Curses multi-select checklist. Returns set of selected indices.

    Args:
        title: Header line displayed above the checklist.
        items: Display labels for each row.
        selected: Indices that start checked (pre-selected).
        cancel_returns: Returned on ESC/q. Defaults to the original *selected*.
        status_fn: Optional callback ``f(chosen_indices) -> str`` whose return
            value is rendered on the bottom row of the terminal.  Use this for
            live aggregate info (e.g. estimated token counts).
    Nr   c           
                              d                                           rw                                                                                      dj        d                               dj        d                               ddd           d}d}	 |                                  |                                 \  }}rdnd}	 j	        }                                r|
                    d          z  }|                     dd|dz
  |           |                     ddd|dz
  j                   n# j        $ r Y nw xY w|dz
  |z
  }||k     r|}n|||z   k    r||z
  dz   }t          t          |t!          t#                    ||z                                 D ]\  }}	|dz   }
|
|dz
  |z
  k    r n|	v rd	nd
}|	|k    rdnd
}d
| d| d|	          }j        }|	|k    r3j	        }                                r|
                    d          z  }	 |                     |
d||dz
  |           # j        $ r Y w xY wr	            }|rxt'          d|t#          |          z
  dz
            }j        }                                r|
                    d          z  }|                     |dz
  ||||z
  dz
  |           n# j        $ r Y nw xY w|                                  |                                 }|j        t/          d          fv r|dz
  t#                    z  }n|j        t/          d          fv r|dz   t#                    z  }nd|t/          d
          k    r                    |h           n:|j        ddfv rt7                    d<   d S |dt/          d          fv rd<   d S <)Nr               Tu:     ↑↓ navigate  SPACE toggle  ENTER confirm  ESC cancelu   ✓    →z [z] kj
         q)curs_set
has_colorsstart_coloruse_default_colors	init_pairCOLOR_GREENCOLOR_YELLOWcleargetmaxyxA_BOLD
color_pairaddnstrA_DIMerror	enumeraterangeminlenA_NORMALmaxrefreshgetchKEY_UPordKEY_DOWNsymmetric_difference_update	KEY_ENTERset)stdscrcursorscroll_offsetmax_ymax_xfooter_rowshattrvisible_rowsdraw_iiycheckarrowlineattrstatus_textsxsattrkeyr   chosencursesr   result_holderr   r   s                      r   _drawzcurses_checklist.<locals>._drawC   s   OOA  "" +""$$$))+++  F$6;;;  F$7<<<  Ar***FMK%00u $-3aa!"ME((** 6!2!21!5!55NN1a	5AAANN1T	6<   
 |   D  %qy;6M))$*MM}|;;;$*\$9A$=M!*-SZZ9U)V)VWW" "  IFA 
AEAI333%&&[[EEcE%&&[[EEcE;u;;;;q;;D!?DF{{%}!,,.. 9 F$5$5a$8$88Dq!T519dCCCC!<     
&/i&7&7& ^!$QK0@0@(@1(D!E!EB$*LE%0022 > %):):1)=)= ="NN519b+urzTU~W\]]]!<       llnn6=#c((333$qjCJJ6FFV_c#hh777$qjCJJ6FFCHH__66x@@@@V-r2666'*6{{M!$FRSN**'5M!$FWKs8   A0E
 

EE3I
II#BK) )
K65K6)	rC   r   r   r   rX   wrapperr   r   _numbered_fallback)	r   r   r   r   r   rZ   rW   rX   rY   s	   `` `` @@@r   curses_checklistr]   #   s   & X 9 bUX#fV	 V	 V	 V	 V	 V	 V	 V	 V	 V	 V	p 	u#0#3#?}Q^S U U U!%.)TTTTTUs   AB B0/B0)r   descriptionr^   c                \    t           j                                        sS g |r|                                	 ddldg fd}                    |           t                       d         d         nS # t          $ r t                     cY S w xY w)a  Curses single-select radio list. Returns the selected index.

    Args:
        title: Header line displayed above the list.
        items: Display labels for each row.
        selected: Index that starts selected (pre-selected).
        cancel_returns: Returned on ESC/q. Defaults to the original *selected*.
        description: Optional multi-line text shown between the title and
            the item list.  Useful for context that should survive the
            curses screen clear.
    Nr   c           
                              d                                           r`                                                                                      dj        d                               dj        d           }d}	 |                                  |                                 \  }}d}	 j	        }                                r|
                    d          z  }|                     |d|dz
  |           |dz  }D ]3}||dz
  k    r n'|                     |d||dz
  j                   |dz  }4|                     |dd|dz
  j                   |dz  }n# j        $ r Y nw xY w|dz   }||z
  dz
  }	||k     r|}n|||	z   k    r||	z
  dz   }t          t!          |t#          t%                    ||	z                                 D ]\  }
}|
|z   }||dz
  k    r n|k    rdnd}||k    rd	nd
}d
| d| d|          }j        }||k    r3j	        }                                r|
                    d          z  }	 |                     |d||dz
  |           # j        $ r Y w xY w|                                  |                                 }|j        t-          d          fv r|dz
  t%                    z  }ni|j        t-          d          fv r|dz   t%                    z  }n;|t-          d
          j        ddfv r|d<   d S |dt-          d          fv rd<   d S )Nr   r   r   r   Tu1     ↑↓ navigate  ENTER/SPACE select  ESC cancelu   ●u   ○r!   r    z (z) r"   r#   r$   r%   r&   r'   )r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   r:   r4   r5   r6   r7   r8   r9   r<   r=   r>   r?   r@   rB   )rD   rE   rF   rG   rH   rowrJ   dlineitems_startrK   rL   rM   rN   radiorP   rQ   rR   rV   r   rX   
desc_linesr   rY   r   r   s                     r   rZ   zcurses_radiolist.<locals>._draw   s   OOA  "" =""$$$))+++  F$6;;;  F$7<<<FME%00u"ME((** 6!2!21!5!55NN35%!)UCCC1HC ", ! !%!)++!EsAueaiQQQqNNQQ	6<  
 1HCC|   D "Ag${2Q6M))$*MM}|;;;$*\$9A$=M!*-SZZ9U)V)VWW" "  IFA ,AEAI~~()XHH8E()VHHE;u;;;;q;;D!?DF{{%}!,,.. 9 F$5$5a$8$88Dq!T519dCCCC!<       llnn6=#c((333$qjCJJ6FFV_c#hh777$qjCJJ6FFSXXv'7R@@@'-M!$FRSN**'5M!$FKEs%   >B0E/ /
E<;E<I99
JJ)	r   r   r   
splitlinesrX   r[   r   r   _radio_numbered_fallback)	r   r   r   r   r^   rZ   rX   re   rY   s	   ````  @@@r   curses_radiolistrh      s   & !9 J . ++--
ZP#fO	 O	 O	 O	 O	 O	 O	 O	 O	 O	 O	b 	u#0#3#?}Q^S P P P'uhOOOOOPs   AB B+*B+c           	         t          t          d|  t          j                             t          t          dt          j                             t          |          D ]C\  }}||k    rt          dt          j                  nd}t          d| d|dz   dd	|            Dt                       	 t          t          d
|dz    dt          j                                                            }|s|S t          |          dz
  }d|cxk    rt          |          k     rn n|S |S # t          t          t          f$ r |cY S w xY w)z1Text-based numbered fallback for radio selection.
  z&  Select by number, Enter to confirm.
u   (●)u   (○)  r    r   >2. z  Choice [default ]: r   )printr   r   YELLOWDIMr6   GREENinputstripintr9   
ValueErrorKeyboardInterruptEOFError)	r   r   r   r   rM   labelmarkervalidxs	            r   rg   rg     si    
%u
.
.///	%96:
F
FGGGe$$ 1 1545MMz6<000z/6//AE/////0000	GGG	E@x!|@@@&*MMNNTTVV 	O#hhl    c%jj     J)84   s   4AD+ 80D+ )D+ +EECancel)cancel_labeldefault_indexr~   c                    t           j                                        sdS 	 ddldgt	          |          |gz   t          |          } fd}                    |           t                       d         d         |k    rdS d         S # t          $ r6 t	          |          |gz   t          |          }t           |          cY S w xY w)zCurses single-select menu. Returns selected index or None on cancel.

    Works inside prompt_toolkit because curses.wrapper() restores the terminal
    safely, unlike simple_term_menu which conflicts with /dev/tty.
    Nr   c           
                              d                                           r`                                                                                      dj        d                               dj        d           t          t                    dz
            }d}	 | 	                                 | 
                                \  }}	 j        }                                r|                    d          z  }|                     dd|dz
  |           |                     ddd|dz
  j                   n# j        $ r Y nw xY w|dz
  }||k     r|}n|||z   k    r||z
  dz   }t!          t#          |t          t                    ||z                                 D ]\  }}|dz   }	|	|dz
  k    r n||k    rdnd	}
d	|
 d	|          }j        }||k    r3j        }                                r|                    d          z  }	 |                     |	d||dz
  |           # j        $ r Y w xY w|                                  |                                 }|j        t-          d
          fv r|dz
  t                    z  }n[|j        t-          d          fv r|dz   t                    z  }n-|j        ddfv r|d<   d S |dt-          d          fv rd d<   d S U)Nr   r   r   r   Tu.     ↑↓ navigate  ENTER confirm  ESC/q cancelr   r!   r    r"   r#   r$   r%   r&   r'   )r(   r)   r*   r+   r,   r-   r.   r8   r9   r/   r0   r1   r2   r3   r4   r5   r6   r7   r:   r<   r=   r>   r?   r@   rB   )rD   rE   rF   rG   rH   rJ   rK   rL   rM   rN   rP   rQ   rR   rV   	all_itemsrX   r   rY   r   s                 r   rZ   z#curses_single_select.<locals>._drawM  s   OOA  "" =""$$$))+++  F$6;;;  F$7<<<I(:;;FM5%00u"ME((** 6!2!21!5!55NN1a	5AAANN1H	6<   
 |   D  %qyM))$*MM}|;;;$*\$9A$=M!*-S^^]\=Y)Z)Z[[" "  IFA 
AEAI~~%&&[[EEcE5u55y|55D!?DF{{%}!,,.. 9 F$5$5a$8$88Dq!T519dCCCC!<       llnn6=#c((333$qjC	NN:FFV_c#hh777$qjC	NN:FFV-r2666'-M!$FRSN**'+M!$Fk5s%   A0E 
EE#I  
II)
r   r   r   rX   listr9   r[   r   r   _numbered_single_fallback)	r   r   r   r~   
cancel_idxrZ   r   rX   rY   s	   ` `   @@@r   curses_single_selectr   7  s!    9 tQG#fKK<.0	ZZ
?	 ?	 ?	 ?	 ?	 ?	 ?	 ?	 ?	B 	u'M!,<
,J,J4Q G G GKK<.0	ZZ
(	:FFFFFGs   A)B B =CCr   c                    t          d|  d           t          |d          D ]\  }}t          d| d|            t                       	 t          dt          |           d                                          }|sdS t          |          dz
  }d	|cxk    rt          |          k     rn n||k     r|S ||k    rdS n# t          t          t          f$ r Y nw xY wdS )
z/Text-based numbered fallback for single-select.rj   
r   rk   rm   z  Choice [1-rn   Nr   )	ro   r6   rs   r9   rt   ru   rv   rw   rx   )r   r   r   rM   ry   r{   r|   s          r   r   r     s+    




eQ'' ! !51    	GGG
23u::2223399;; 	4#hhl    c%jj     S:%5%5J*4 )84   4s   4C 6C ;C CCc           	      \   t          |          }t          t          d|  t          j                             t          t          dt          j                             	 t          |          D ]A\  }}||v rt          dt          j                  nd}t          d| d|dz   d	d
|            B|r7 ||          }	|	r*t          t          d|	 t          j                             t                       	 t          t          dt          j                            	                                }
|
snut          |
          dz
  }d|cxk    rt          |          k     rn n|                    |h           n# t          t          t          f$ r |cY S w xY wt                       J|S )z8Text-based toggle fallback for terminals without curses.rj   z&  Toggle by number, Enter to confirm.
Tu   [✓]z[ ]rk   r    r   rl   rm   z"  Toggle # (or Enter to confirm): r   )rC   ro   r   r   rp   rq   r6   rr   rs   rt   ru   r9   rA   rv   rw   rx   )r   r   r   r   r   rW   rM   ry   rz   rS   r{   r|   s               r   r\   r\     s    ]]F	%u
.
.///	%96:
F
FGGG!%(( 	5 	5HAu56&[[U7FL111eF3v33A333E334444 	?#)F++K ?e0;00&*==>>>	"BFJOOPPVVXXC c((Q,CC$$$$#e**$$$$$22C5999-x8 	" 	" 	"!!!!	"%( Ms   ;;E= 7AE= =FF)r	   N)r   )N)__doc__r   typingr   r   r   r   hermes_cli.colorsr   r   r   strru   r]   rh   rg   r   r   r\        r   <module>r      s    


 0 0 0 0 0 0 0 0 0 0 0 0 + + + + + + + +   6 '+59}U }U }U}U9}U #h}U
 HtO}U #c(S12}U 	X}U }U }U }UF wP
 "&"wP wP wPwP9wP wP
 $JwP twP 	wP wP wP wPt9  	
 	   : `G
 !`G `G `G`G9`G `G
 `G 	4Z`G `G `G `GF9  	4Z	   : 6:    9  #h  H	 
 #c(S12  	X           r   