
    4wiD              
          d Z ddlZddlZddlZddlmZ ddlmZ ddlZddl	Zddl
Z
ddlmZ ddlmZ ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZ ddlmZ  ej         e eej!                  d            ej"        e#          Z$ G d d          Z%de%fdZ& e&            Z' e            Z(dZ)de*de*de+e*ef         fdZ,edefd            Z- eddde-          Z.ej/        pej0        1                    dd           Z2 ej3        d!ej4        pd"e2 e5ej/                  #          Z6ej7        8                    e.e6eegd$%           e.1                    d&          de+e*e*f         fd'            Z9e.1                    d(          de+e*ef         fd)            Z: G d* d+e          Z;e.<                    d,          d-e;de+e*ef         fd.            Z=e.1                    d/          d8de*d1e>de+e*ef         fd2            Z?e.<                    d3          de*d4e5de+e*e*f         fd5            Z@d9d6ZAe#d7k    r eA             dS dS ):u   FastAPI 主入口。    N)asynccontextmanager)Any)FastAPI)	BaseModel)settings)BaseGateway)NapCatGateway)TelegramGateway)ContextManager)inngest_client)handle_im_message)command_guardrailz4%(asctime)s - %(name)s - %(levelname)s - %(message)s)levelformatc                   R    e Zd ZdZddZdeddfdZddZded	ed
eddfdZ	ddZ
dS )GatewayManageru   多通道网关管理器。returnNc                 "    i | _         g | _        d S )N)gateways_tasks)selfs    */root/projects/qq-shell/src/butler/main.py__init__zGatewayManager.__init__"   s    0202    gatewayc                 $    || j         |j        <   dS )u   注册网关。N)r   name)r   r   s     r   registerzGatewayManager.register&   s    &-gl###r   c                 8  K   | j                                         D ]}\  }}|                    | j                   t	          j        |                                          }| j                            |           t          
                    d| d           ~dS )u   启动所有网关。	Gateway 'z	' startedN)r   items
on_message_handle_messageasynciocreate_taskstartr   appendloggerinfor   r   gwtasks       r   	start_allzGatewayManager.start_all*   s      ++-- 	5 	5HD"MM$.///&rxxzz22DKt$$$KK3D3334444		5 	5r   user_idcontentchannelc           
      J  K   t                               d| d| d|dd          d           	 t          ||           d{V }|                    dd          }|rR|| j        v rK| j        |                             ||           d{V  t                               d| d	|            dS dS dS # t          $ rd}t                               d| d
|            || j        v r0| j        |                             |d|            d{V  Y d}~dS Y d}~dS d}~ww xY w)u'   统一消息回调：处理并回复。[z] Message from z: N2   z...reply z] Replied to z] Error handling message: u   处理出错：)r(   r)   _process_messagegetr   send_message	Exceptionerror)r   r.   r/   r0   resultr4   es          r   r#   zGatewayManager._handle_message2   s     LLLLL73B3<LLLMMM		Z+GW========FJJw++E ADM11mG,99'5IIIIIIIII???g??@@@@@A A11  	Z 	Z 	ZLLCWCCCCDDD$-''mG,99'CXUVCXCXYYYYYYYYYYYYYYY ('''''	Zs   A>B4 4
D">ADD"c                    K   | j                                         D ]=\  }}|                                 d{V  t                              d| d           >| j        D ]}|                                 dS )u   停止所有网关。Nr    z	' stopped)r   r!   stopr(   r)   r   cancelr*   s       r   stop_allzGatewayManager.stop_all@   s      ++-- 	5 	5HD"''))OOOOOOOKK3D3334444K 	 	DKKMMMM	 	r   r   N)__name__
__module____qualname____doc__r   r   r   r-   strr#   r@    r   r   r   r      s        %%3 3 3 3. . . . . .5 5 5 5ZS Z3 Z ZQU Z Z Z Z     r   r   r   c                     t                      } t          j        D ]}|dk    rEt          j        r9|                     t          t          j        t          j                             M|dk    r9|                     t          t          j        t          j	                             t                              d|            | S )u!   根据配置构建网关实例。telegram)	bot_tokenallowed_chatsnapcat)ws_urlaccess_tokenzUnknown channel: )r   r   enabled_channelstelegram_bot_tokenr   r
   telegram_allowed_chatsr	   napcat_ws_urlnapcat_tokenr(   warning)mgrr0   s     r   _build_gatewaysrV   I   s    


C, : :j  X%@ LL"5&=         LL-%2      
 NN8w889999Jr   u  Butler-Shell 使用说明：
  !<命令>       原始命令模式，跳过 LLM，直接执行并返回原始输出
                例：!ls -la, !df -h
  /new          新建会话（新 tmux session + 新 LLM 上下文）
  /list         列出所有会话
  /enter <会话>  切换到指定会话（按编号或名称）
  /rename <名称> 重命名当前会话
  /del <会话>    删除指定会话（按编号或名称）
  /clear        清理当前会话的 LLM 对话历史（保留 shell session）
  /help         显示本帮助信息
  其他          自然语言模式，LLM 理解意图并总结输出
                例：查看当前目录, 看下磁盘空间r.   r/   c           	        K   ddl m} ddlm} ddlm}m} ddlm} ddl	m
}  |t          j                  } |            }	t          j        |           sd|  d	d
ddddS |                                dk    rt          dddddS |                                dk    rt                               |           }
|
r
|
j        dz   nd}|
r|
j        nd}|                    | |          }t                               | ||           d| d| d}|r	|d| dz  }|ddd|dS |                                dk    r|t                               |           }
|
0|                    |           }t                               | |          }
t                               |            d|
j         dddd|
j        dS |                                dk    rt                               |           }t                               |           }|sddddddS dg}|D ]N}|j        |k    rdnd}|j        rd|j         dnd}|                    d|j         d |j         | |            Od!                    |          ddd|dS |                                                    d"          r|                                d#d                                         }t                               |           }|sd$dd%dddS d}|D ]4}t=          |j                  |k    s|j        |k    s|j        |k    r|} n5|d&| d'dd%dddS |                    |j                  sd(|j         d)dd%dddS t                                | |j                   d*|j!         dd%d|j        dS |                                                    d+          r|                                d,d                                         }|sd-dd.dddS t                               |           }
|
0|                    |           }t                               | |          }
t           "                    | |
j        |           d/| dd.d|
j        dS |                                                    d0          r5|                                d1d                                         }t                               |           }d}|D ]4}t=          |j                  |k    s|j        |k    s|j        |k    r|} n5|d&| dd2dddS t                               |           }|j        |k    rtG          |          dk    rd3dd2dddS t           $                    | |j                   |%                    |j                   t                               |           }d4|j!         d5| dd2d|dS |                    d6          rP|dd                                         }|sd7d8ddddS t                               | d          }
|
j        r|                    |
j                  s#|                    | |
j                  }||
_        t          j&        r, ||          r! ||          pd9}d:| d;| d<d=|d|
j        dS |'                    |
j        |d>?           tQ          j)        d@           d{V  |*                    |
j                  }|	+                    | |
j        ||ddA                    |dBd         dC||dBd         |
j        dS |                    |           }t                               | |          }
|
j        |k    r||
_        |,                    |          }||j-        k    r=|'                    ||dD?           |*                    |          }dEdF||dBd         |dS |}dD}|.                                rdG|                    |          r|*                    |          dHd         ndi}|/                    |||
j0        I           d{V }tb          2                    dJ| dK| dL           ||k    rd>}|rdM| dNdd|dS t          j&        r' ||          r ||          pd9}d:| d;| d<d=|d|dS |'                    ||d>?           tQ          j)        d@           d{V  |*                    |          }|	+                    | |||ddA                    t           3                    | dO|           t           3                    | dPdQ| dR           d}|.                                rN|4                    ||||
j0        I           d{V }|sdS| dT|dHd          }|
j0        r||
j0        dU         dV<   ndW| dT|dHd          }|dX||dBd         |dS )Yu@   核心消息处理逻辑：命令路由 → 执行 → 总结。r   )TmuxWrapper)SessionMode)is_dangerous_commandget_danger_reason)agentLogSkill)session_prefixu   用户 u    无权限使用此服务unauthorizedr5   )r4   modecommand
raw_output
session_idz/helprb   z/new   N)sequ   已创建新会话: z (#)u   
旧会话 u
    仍保留z/clearu$   已清理 LLM 对话历史 (会话: z/listu*   暂无会话，发送消息或 /new 创建u   会话列表：z *z (z  # 
z/enter    u   暂无会话可切换z/enteru   未找到会话: u"   。发送 /list 查看所有会话u   会话 u    的 tmux session 已不存在u   已切换到会话: z/rename    u   用法: /rename <名称>z/renameu   已重命名会话为: z/del    z/delu<   不能删除唯一活跃会话，请先 /new 创建新会话u   已删除会话: u   ，当前会话: !u   命令不能为空r:   u   潜在危险命令u   ⚠️ 该操作需要确认：u   。将执行 `u   `，确认吗？pending_approvalT)enterg      ?i  i0rawFu   已发送按键到交互程序interactivepwdi)llm_messageszAgent: 'z' -> ''uY   ⚠️ LLM 服务暂时不可用，未能理解指令。请稍后重试。
原始输入: 	llm_erroruser	assistantu   执行了: u   
输出摘要待生成uM   ⚠️ 总结服务暂时不可用，以下是命令原始输出:
执行了 `z`
r/   u   执行了 `nl)5butler.session.wrapperrX   butler.sessionrY   butler.security.guardrailrZ   r[   butler.agentr\   butler.skills.log_skillr^   r   r_   is_user_allowedstrip	HELP_TEXTcontext_managerr7   rf   rd   get_or_create_sessionnew_sessionget_or_createclear_contextlist_sessionsget_active_session_idr   r'   join
startswithrF   session_existsswitch_sessiondisplay_namerename_sessionlendelete_sessionkill_sessionguardrail_enabled	send_keysr$   sleepcapture_panelog_commanddetect_modeINTERACTIVEis_available
understandrs   r(   r)   add_message	summarize) r.   r/   rX   rY   rZ   r[   r\   r^   tmux	log_skillctxnew_seqold_sessionnew_session_idr4   session_namesessions	active_idlinessmarker	name_parttargetmatchednew_name
new_activerb   reasonrc   current_mode
llm_failedcontext_infos                                    r   r6   r6   q   so     222222******QQQQQQQQ""""""000000;h&=>>>D

I #G,, RE7EEE~jl|~  OQ  R  R  	R
 }}'!!"I'Y[kmnnn }}&  !!'**#&-37Q;;A(+5cnn33G3II##G^WEEED~DD'DDD 	<;K;;;;E	fTVftuuu }}(""!!'**;55g>>L!//FFC%%g...QQQQ[dqy  JL  \_  \j  k  k  	k }}'!!"0099#99'BB	 	VIS\ip  AC  SU  V  V  V"# 	J 	JA\Y66TTBF*+&8QVbILLHquHHq|HYHHHIIII5))9`br{||| }}!!),, d$**,,"0099 	B4iT\ln  A  B  B  B 	 	A15zzV##qv'7'71<6;Q;Q <R ?[[[[en  |D  TV  fh  i  i  i""7#566 	gYw'9YYYcl  zB  RT  df  g  g  g&&w0BCCCF0DFFPYfn  A  QX  Qc  d  d  	d }}!!*-- 	X==??122&,,.. 	F7W`pr  CE  F  F  F!!'**;55g>>L!//FFC&&wIII=8==y]fvx  IL  IW  X  X  	X }}!!'** t$**,,"0099 	 	A15zzV##qv'7'71<6;Q;Q <R ?9999Y_oq  BD  E  E  E#99'BB	**s8}}/A/A[en  |B  RT  df  g  g  g&&w0BCCC',---$::7CC
`W-A``T^``js  AG  WY  is  t  t  	t # $
!""+##%% 	w17racsuvvv ++GR88~ 	*T%8%8%H%H 	*55g375KKL)CN % 	*>*>w*G*G 	&&w//G3GFj6jjQXjjj*" !n   	s~wd;;;mC         &&s~66
 	gs~w
5D5@QRRR  '$UVV,.
 
 	
 --g66L

'
'
>
>C
~%%% ##L11L {...|WE:::&&|44
9=]dt~  @E  @F  @F  uG  Wc  d  d  	d GJ 	T=P=PQ]=^=^f4$$\2245599df
 ((,SM](^^^^^^^^8w88g888999 gJ 
{ry{{&
 
 	
 ! 
&:&:7&C&C 
""7++C/CfvffWfff&&
 
 	
 	NN<N555
-

""<00J '<*UdU:KLLL 9996dG6d6d6deee E >oogw
QTQaobbbbbbbb 	E Eel  E  Eq{  }A  }B  }B  rC  E  EE 	4.3CR +=g==*TUU*;==DWJW\W]W]L^nz{{{r   appc                   K   t                               d           t                                           d{V  dW V  t                               d           t                                           d{V  dS )u   应用生命周期管理。zStarting Butler-Shell...NzShutting down Butler-Shell...)r(   r)   gateway_managerr-   r@   )r   s    r   lifespanr   R  s       KK*+++

#
#
%
%%%%%%%%	EEEE
KK/000

"
"
$
$$$$$$$$$$r   zButler-Shellz4Persistent Shell Assistant with Multi-Channel Bridgez0.2.0)titledescriptionversionr   INNGEST_SIGNING_KEYz@signkey-dev-placeholder-1234567890123456789012345678901234567890zbutler-shelldev_key)app_id	event_keysigning_keyis_productionz/api/inngest)
serve_pathz/healthc                     K   ddiS )u   服务存活检查。statusokrG   rG   r   r   healthr   z  s       dr   z/readyc                     K   ddl } 	 |                     ddgdd           d}n# t          $ r d}Y nw xY wd t          j        D             }|rd	nd
||dS )u   服务就绪检查。r   Nr   z-VT)capture_outputcheckFc                     i | ]}|d S )	connectedrG   ).0r   s     r   
<dictcomp>zready.<locals>.<dictcomp>  s    GGGdkGGGr   readydegraded)r   r   channels)
subprocessrunr9   r   r   )r   tmux_okr   s      r   r   r     s       ~d$GGG    HGo.FGGGH %4''*  s   % 44c                   ,    e Zd ZU dZdZeed<   eed<   dS )MockMessageu   Mock 消息请求。test_user_001r.   r/   N)rB   rC   rD   rE   r.   rF   __annotations__rG   r   r   r   r     s/         "GS"""LLLLLr   r   z/api/mock/messagemsgc                 F   K   t          | j        | j                   d{V S )uK   自然语言交互端点：输入自然语言，返回自然语言总结。N)r6   r.   r/   )r   s    r   mock_messager     s.       "#+s{;;;;;;;;;r   z/api/raw-outputrl   limitc                   K   ddl m}  |            }t          d                              |j                  }|                    d| |f          }|                                }|                                 d |D             }| |dS )u-   获取命令的原始输出（从日志）。r   r]   sqlite3zcSELECT command, output, timestamp FROM shell_logs WHERE user_id = ? ORDER BY timestamp DESC LIMIT ?c                 >    g | ]}|d          |d         |d         dS )r   re      )rb   output	timestamprG   )r   rows     r   
<listcomp>z"get_raw_output.<locals>.<listcomp>  s>        Fc!f3q6BB  r   )r.   logs)r~   r^   
__import__connectdb_pathexecutefetchallclose)r.   r   r^   r   conncursorrowsr   s           r   get_raw_outputr     s       100000

Ii  (():;;D\\m	% F ??DJJLLL   D ---r   z/api/approvalapprovedc                 p   K   t          j        t          j        d| |d                     d{V  ddiS )u   处理用户审批响应。zim/approval-responser.   r   )r   dataNr   sent)r   sendinngestEventr   s     r   handle_approvalr     sj       
'$(;;	
 	
 	
         fr   c                  6    t          j        dddd           dS )u   启动服务。zbutler.main:appz0.0.0.0i%  F)hostportreloadN)uvicornr   rG   r   r   mainr     s"    K!	UKKKKKKr   __main__)rl   rA   )BrE   r$   loggingos
contextlibr   typingr   r   inngest.fast_apir   fastapir   pydanticr   butler.configr   butler.gateway.baser   butler.gateway.napcatr	   butler.gateway.telegramr
   butler.session.contextr   butler.workflowsr   butler.workflows.handle_messager   butler.workflows.guardrailr   basicConfiggetattr	log_level	getLoggerrB   r(   r   rV   r   r   r   rF   dictr6   r   r   inngest_signing_keyenvironr7   _signing_keyInngestinngest_event_keybool_dev_clientfast_apiserver   r   r   postr   intr   r   r   rG   r   r   <module>r     s       				 * * * * * *                         " " " " " " + + + + + + / / / / / / 3 3 3 3 3 3 1 1 1 1 1 1 + + + + + + = = = = = = 8 8 8 8 8 8  
''8-
.
.A    
	8	$	$' ' ' ' ' ' ' 'T    * "/## .""	 ^|C ^|# ^|$sCx. ^| ^| ^| ^|B 	% 	% 	% 	% 	% g
F	   + rz~~F0 0 go(5I$x344	      )*	     d38n    
 T#s(^    $    )    
<K <DcN < < < <
 	. .# .c .$sCx. . . . .( /3 $ 4S>    L L L L
 zDFFFFF r   