
    )Fj$                         d Z ddlZddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
 G d d      Zd Zedk(  r e        yy)z
Kimi Copilot - PTY wrapper for Kimi Code CLI.

Captures user input and Kimi output, forwarding both to the brain module
for context tracking and side-model analysis.
    Nc                   d    e Zd ZddZed        Zed        Zd Zd Zd Z	d Z
d	 Zd
 Zd Zd Zy)KimiCopilotNc                     |xs dg| _         d | _        d | _        d| _        t	        j
                         | _        t	        j
                         | _        t	        j
                         | _        y )NkimiF)	command	master_fd	child_pidrunningqueueQueueuser_input_queuekimi_output_queuenotification_queue)selfr   s     kimi_copilot.py__init__zKimiCopilot.__init__   sS    *6( !&!& #(++-    c                     t        j                  ddddd      }	 t        j                  | t        j
                  |      }t        j                  d|      dd S # t        $ r Y yw xY w)z.Return (rows, cols) for the given terminal fd.HHHHr   )   P   N   )structpackfcntlioctltermios
TIOCGWINSZOSErrorunpack)fdsxs      r   _get_terminal_sizezKimiCopilot._get_terminal_size$   se     KK1a+	B 2 2A6A }}VQ'++  		s   %A 	A%$A%c                     t        j                  d||dd      }	 t        j                  | t        j
                  |       y# t        $ r Y yw xY w)z#Propagate terminal size to the PTY.r   r   N)r   r   r   r   r   
TIOCSWINSZr   )r!   rowscolsr"   s       r   _set_terminal_sizezKimiCopilot._set_terminal_size.   sG     KKdAq1	KKG..2 		s   %A 	AAc                     | j                  t        j                  j                               \  }}| j                  | j                  | j                  ||       yy)z2Propagate terminal resize events to the child PTY.N)r$   sysstdinfilenor   r)   )r   signumframer'   r(   s        r   _on_window_resizezKimiCopilot._on_window_resize7   sH    ,,SYY-=-=-?@
d>>%##DNND$? &r   c                    t        j                         \  }}|dk(  r-t        j                  | j                  d   | j                         || _        || _        | j                  t        j                  j                               \  }}| j                  |||       ddl}|j                  |j                  | j                         y)z.Fork a PTY and exec the Kimi Code CLI process.r   N)ptyforkosexecvpr   r	   r   r$   r+   r,   r-   r)   signalSIGWINCHr0   )r   pidr   r'   r(   r6   s         r   spawnzKimiCopilot.spawn=   s    Y!8IIdll1ot||4" ,,SYY-=-=-?@
d	46 	foot'='=>r   c                    t        j                  t        j                  j	                               syt        j                  t        j                        }t        j                  t        j                  j	                                |S )z:Switch local terminal to raw mode and return old settings.N)	r4   isattyr+   r,   r-   r   	tcgetattrttysetrawr   old_ttys     r   _set_raw_modezKimiCopilot._set_raw_modeO   sP    yy))+,##CII.

399##%&r   c                     |y t        j                  t        j                  j	                         t         j
                  |       y N)r   	tcsetattrr+   r,   r-   	TCSADRAINr?   s     r   _restore_ttyzKimiCopilot._restore_ttyW   s/    ?#))**,g.?.?Ir   c                 ~   	 	 | j                   j                         }|s|j	                  d      s|dz  }|j                  d      }g }t        |      D ]S  \  }}|t        |      dz
  k(  r|dk(  r|j                  d|        |t        |      dz
  k  sC|j                  d       U dj                  |      }|j	                  d      s|dz  }	 t        j                  t        j                  j                         |j                  dd             # t        j                  $ r Y y	w xY w# t         $ r Y y	w xY w)
a  Flush queued brain notifications to stdout in raw-terminal mode.

        In raw mode ``
`` does not perform a carriage return, so we rewrite
        line endings as ``
`` to keep iTerm2 display clean. We also clear
        each line before writing because the child CLI may have left a status
        line (context / help hints) at the bottom of the screen; without
        clearing, Copilot messages get concatenated with that status text.
        
    z[Kz
utf-8ignoreerrorsN)r   
get_nowaitr   Emptyendswithsplit	enumeratelenappendjoinr4   writer+   stdoutr-   encoder   )r   msglinespartsilines         r   _emit_notificationszKimiCopilot._emit_notifications\   s2    --88: <<%t IIdOEE$U+ )4E
Q&42:xv./s5zA~%LL() ''%.C<<'v**,cjjj.RS1  ;; ,  s$   D AD0 D-,D-0	D<;D<c                    | j                         }	 | j                  rt        j                  t        j                  j                         | j                  gg g d      \  }}}t        j                  j                         |v r	 t        j                  t        j                  j                         d      }|snt        j                  | j                  |       |j                  dd      }| j                  j                  |       | j                  |v r	 t        j                  | j                  d      }|sn|t        j                  t        j                  j                         |       | j                  j                  |j                  dd             | j!                          | j                  r| j#                  |       y# t        $ r Y w xY w# t        $ r Y ,w xY w# | j#                  |       w xY w)z:Forward bytes between user stdin/stdout and the child PTY.g?i   rK   rL   rM   N)rA   r
   selectr+   r,   r-   r   r4   readr   rW   decoder   putrX   r   r_   rF   )r   r@   readable_datatexts         r   _forward_loopzKimiCopilot._forward_loop   s   $$&"	',,!'YY%%'8"b#"!Q 99##%1!wwsyy'7'7'94@  HHT^^T2;;wx;@D))--d3>>X-!wwt~~t<  HHSZZ..0$7**..GH= ((*? ,,B g&3 #  #  g&sV   A1G% 2G 6AG%  G 6A=G% 	GG% GG% 	G"G% !G""G% %G8c                     	 ddl m} |T j                  rG	  j                  j                  d       	  j                  j                  d        j                  rGydt        f fd} ||       fd	} j                  r |         j                  r	 	  j                  j                          # t        $ r d}Y w xY w# t        j                  $ r Y w xY w# t        j                  $ r Y w xY w# t        j                  $ r Y nw xY w	 	  j                  j                         }j                  |       n# t        j                  $ r Y yw xY wG)
z2Background thread: feed captured I/O to the brain.r   )BrainNg      ?timeoutrZ   c                 <    j                   j                  |        y rC   )r   rd   )rZ   r   s    r   notify_callbackz0KimiCopilot._brain_loop.<locals>.notify_callback   s    ##'',r   )ro   c                  "   	 j                   j                  d      } j                  |        	 j
                  j                  d      } j                  |        y # t        j                  $ r Y Dw xY w# t        j                  $ r Y y w xY w)Ng?rl   )r   getfeed_user_inputr   rP   r   feed_kimi_output)rh   brainr   s    r   process_one_itemz1KimiCopilot._brain_loop.<locals>.process_one_item   s    ,,000=%%d+--11#1>&&t, ;;  ;; s"   -A -A8 A54A58BB)rt   rk   ImportErrorr
   r   rq   r   rP   r   strrO   rs   )r   rk   ro   ru   rh   rt   s   `    @r   _brain_loopzKimiCopilot._brain_loop   sW   	# =,,))--c-:**..s.; ,, 	- 	- o6	 ll ll %%002 S  	E	 {{  {{ @ ;; --88:&&t,;; 	 sW   B8 C	 C" C; 8CC	CC"C87C8;DD+E EEc                 X   | j                          d| _        t        j                  | j                  d      }|j                          	 | j                          d| _        |j                  d       | j                          | j                  "	 t        j                  | j                  d       y y # t        $ r Y y w xY w# d| _        |j                  d       | j                          | j                  1	 t        j                  | j                  d       w # t        $ r Y w w xY ww xY w)NT)targetdaemonFg      N@rl   r   )r9   r
   	threadingThreadrx   startri   rV   r_   r	   r4   waitpidChildProcessError)r   brain_threads     r   runzKimiCopilot.run   s   

 ''t/?/?M	  DL d+$$&~~)JJt~~q1 * )  !DL d+$$&~~)JJt~~q1(  *sB   
C  B2 2	B>=B>6D)8 DD)	D%"D)$D%%D)rC   )__name__
__module____qualname__r   staticmethodr$   r)   r0   r9   rA   rF   r_   ri   rx   r    r   r   r   r      s\    0 , ,  @?$J
#J%'N8tr   r   c                     dt         j                  v rt         j                  j                  d       ddlm}  dd l}dt         j                  v}|st         j                  j                  d        |        }|j                  |      }t        d|        |rt        d       n
t                	 	 |j                  d       t         j                  dd  xs d	g}t        |
      }|j                          y # t        $ r Y y w xY w)Nz--panelr   )	HintPanelz--no-browser)open_browseru   
[Copilot] 提示面板：u#   [Copilot] 正在打开浏览器...
rI   r   )r   )r+   argvremovecopilot_panelr   timeopenprintsleepKeyboardInterruptr   r   )r   r   r   panelurlr   copilots          r   mainr      s     CHH	"+%SXX5HHOON+jjlj3+C51289G	

1 
 hhqrl&vhG'*GKKM ! 		s   /C7 7	DD__main__)__doc__r   r4   r2   r   ra   r   r+   r   r|   r=   r   r   r   r   r   r   <module>r      sP     	 
    
   
a aH< zF r   