1+ import copy
12import traceback
3+ from sys import maxsize
24
5+ import astrbot .api .message_components as Comp
36from astrbot .api import star
47from astrbot .api .event import AstrMessageEvent , filter
58from astrbot .api .message_components import Image , Plain
69from astrbot .api .provider import LLMResponse , ProviderRequest
710from astrbot .core import logger
11+ from astrbot .core .utils .session_waiter import (
12+ FILTERS ,
13+ USER_SESSIONS ,
14+ SessionController ,
15+ SessionWaiter ,
16+ session_waiter ,
17+ )
818
919from .long_term_memory import LongTermMemory
1020
@@ -18,6 +28,103 @@ def __init__(self, context: star.Context) -> None:
1828 except BaseException as e :
1929 logger .error (f"聊天增强 err: { e } " )
2030
31+ @filter .event_message_type (filter .EventMessageType .ALL , priority = maxsize )
32+ async def handle_session_control_agent (self , event : AstrMessageEvent ) -> None :
33+ """会话控制代理"""
34+ for session_filter in FILTERS :
35+ session_id = session_filter .filter (event )
36+ if session_id in USER_SESSIONS :
37+ await SessionWaiter .trigger (session_id , event )
38+ event .stop_event ()
39+
40+ @filter .event_message_type (filter .EventMessageType .ALL , priority = maxsize - 1 )
41+ async def handle_empty_mention (self , event : AstrMessageEvent ):
42+ """处理只有一个 @ 或仅有唤醒前缀的消息,并等待用户下一条内容。"""
43+ try :
44+ messages = event .get_messages ()
45+ cfg = self .context .get_config (umo = event .unified_msg_origin )
46+ p_settings = cfg ["platform_settings" ]
47+ wake_prefix = cfg .get ("wake_prefix" , [])
48+ if len (messages ) != 1 :
49+ return
50+
51+ is_empty_mention = (
52+ isinstance (messages [0 ], Comp .At )
53+ and str (messages [0 ].qq ) == str (event .get_self_id ())
54+ and p_settings .get ("empty_mention_waiting" , True )
55+ )
56+ is_wake_prefix_only = (
57+ isinstance (messages [0 ], Comp .Plain )
58+ and messages [0 ].text .strip () in wake_prefix
59+ )
60+
61+ if not (is_empty_mention or is_wake_prefix_only ):
62+ return
63+
64+ if p_settings .get ("empty_mention_waiting_need_reply" , True ):
65+ try :
66+ curr_cid = await self .context .conversation_manager .get_curr_conversation_id (
67+ event .unified_msg_origin ,
68+ )
69+ conversation = None
70+
71+ if curr_cid :
72+ conversation = (
73+ await self .context .conversation_manager .get_conversation (
74+ event .unified_msg_origin ,
75+ curr_cid ,
76+ )
77+ )
78+ else :
79+ curr_cid = (
80+ await self .context .conversation_manager .new_conversation (
81+ event .unified_msg_origin ,
82+ platform_id = event .get_platform_id (),
83+ )
84+ )
85+
86+ yield event .request_llm (
87+ prompt = (
88+ "注意,你正在社交媒体上中与用户进行聊天,用户只是通过@来唤醒你,但并未在这条消息中输入内容,他可能会在接下来一条发送他想发送的内容。"
89+ "你友好地询问用户想要聊些什么或者需要什么帮助,回复要符合人设,不要太过机械化。"
90+ "请注意,你仅需要输出要回复用户的内容,不要输出其他任何东西"
91+ ),
92+ session_id = curr_cid ,
93+ contexts = [],
94+ system_prompt = "" ,
95+ conversation = conversation ,
96+ )
97+ except Exception as e :
98+ logger .error (f"LLM response failed: { e !s} " )
99+ yield event .plain_result ("想要问什么呢?😄" )
100+
101+ @session_waiter (60 )
102+ async def empty_mention_waiter (
103+ controller : SessionController ,
104+ event : AstrMessageEvent ,
105+ ) -> None :
106+ if not event .message_str or not event .message_str .strip ():
107+ return
108+ event .message_obj .message .insert (
109+ 0 ,
110+ Comp .At (qq = event .get_self_id (), name = event .get_self_id ()),
111+ )
112+ new_event = copy .copy (event )
113+ self .context .get_event_queue ().put_nowait (new_event )
114+ event .stop_event ()
115+ controller .stop ()
116+
117+ try :
118+ await empty_mention_waiter (event )
119+ except TimeoutError :
120+ pass
121+ except Exception as e :
122+ yield event .plain_result ("发生错误,请联系管理员: " + str (e ))
123+ finally :
124+ event .stop_event ()
125+ except Exception as e :
126+ logger .error ("handle_empty_mention error: " + str (e ))
127+
21128 def ltm_enabled (self , event : AstrMessageEvent ):
22129 ltmse = self .context .get_config (umo = event .unified_msg_origin )[
23130 "provider_ltm_settings"
0 commit comments