66"""
77
88import asyncio
9+ from collections .abc import AsyncGenerator
910from typing import Any
1011
1112from astrbot import logger
@@ -21,11 +22,9 @@ class CLIMessageEvent(AstrMessageEvent):
2122 """CLI消息事件
2223
2324 处理命令行模拟器的消息事件。
25+ Socket模式下收集管道中所有send()调用的消息,在管道完成(finalize)后统一返回。
2426 """
2527
26- # 延迟配置
27- INITIAL_DELAY = 5.0 # 首次发送延迟
28- EXTENDED_DELAY = 10.0 # 后续发送延迟
2928 MAX_BUFFER_SIZE = 100 # 缓冲区最大消息组件数
3029
3130 def __init__ (
@@ -48,29 +47,21 @@ def __init__(
4847 self .output_queue = output_queue
4948 self .response_future = response_future
5049
51- # 多次回复收集
50+ # 多次回复收集(Socket模式)
5251 self .send_buffer = None
53- self ._response_delay_task = None
54- self ._response_delay = self .INITIAL_DELAY
5552
5653 async def send (self , message_chain : MessageChain ) -> dict [str , Any ]:
5754 """发送消息到CLI"""
58- # 调用父类方法以设置 _has_send_oper 标志
59- # 这告诉 ProcessStage 已经有发送操作,避免触发 LLM
6055 await super ().send (message_chain )
6156
62- # Socket模式:收集多次回复
57+ # Socket模式:收集所有回复到buffer,等待finalize()统一返回
6358 if self .response_future is not None and not self .response_future .done ():
64- # 使用 ImageProcessor 预处理图片(避免临时文件被删除)
6559 ImageProcessor .preprocess_chain (message_chain )
6660
67- # 收集多次回复到buffer
6861 if not self .send_buffer :
6962 self .send_buffer = message_chain
70- self ._response_delay = self .INITIAL_DELAY
7163 logger .debug ("[CLI] First send: buffer initialized" )
7264 else :
73- # 检查缓冲区大小限制
7465 current_size = len (self .send_buffer .chain )
7566 new_size = len (message_chain .chain )
7667 if current_size + new_size > self .MAX_BUFFER_SIZE :
@@ -80,47 +71,61 @@ async def send(self, message_chain: MessageChain) -> dict[str, Any]:
8071 new_size ,
8172 self .MAX_BUFFER_SIZE ,
8273 )
83- # 只添加能容纳的部分
8474 available = self .MAX_BUFFER_SIZE - current_size
8575 if available > 0 :
8676 self .send_buffer .chain .extend (message_chain .chain [:available ])
8777 else :
8878 self .send_buffer .chain .extend (message_chain .chain )
89- self ._response_delay = self .EXTENDED_DELAY
9079 logger .debug (
9180 "[CLI] Appended to buffer, total: %d" , len (self .send_buffer .chain )
9281 )
93-
94- # 重置延迟任务
95- if self ._response_delay_task and not self ._response_delay_task .done ():
96- self ._response_delay_task .cancel ()
97-
98- self ._response_delay_task = asyncio .create_task (self ._delayed_response ())
9982 else :
100- # 其他模式 :直接放入输出队列
83+ # 非Socket模式或future已完成 :直接放入输出队列
10184 await self .output_queue .put (message_chain )
10285
10386 return {"success" : True }
10487
88+ async def send_streaming (
89+ self ,
90+ generator : AsyncGenerator [MessageChain , None ],
91+ use_fallback : bool = False ,
92+ ) -> None :
93+ """处理流式LLM响应
94+
95+ CLI不支持真正的流式输出,采用收集后一次性发送的策略。
96+ 与aiocqhttp的非fallback模式一致。
97+ """
98+ buffer = None
99+ async for chain in generator :
100+ if not buffer :
101+ buffer = chain
102+ else :
103+ buffer .chain .extend (chain .chain )
104+
105+ if not buffer :
106+ return
107+
108+ buffer .squash_plain ()
109+ await self .send (buffer )
110+ await super ().send_streaming (generator , use_fallback )
111+
105112 async def reply (self , message_chain : MessageChain ) -> dict [str , Any ]:
106113 """回复消息"""
107114 return await self .send (message_chain )
108115
109- async def _delayed_response (self ) -> None :
110- """延迟响应:收集所有回复后统一返回"""
111- try :
112- await asyncio .sleep (self ._response_delay )
116+ async def finalize (self ) -> None :
117+ """管道完成后调用,将收集的所有回复统一返回给Socket客户端。
113118
114- if self .response_future and not self .response_future .done ():
119+ 由PipelineScheduler.execute()在所有阶段执行完毕后调用。
120+ """
121+ if self .response_future and not self .response_future .done ():
122+ if self .send_buffer :
115123 self .response_future .set_result (self .send_buffer )
116124 logger .debug (
117- "[CLI] Delayed response set, %d components" ,
125+ "[CLI] Pipeline done, response set with %d components" ,
118126 len (self .send_buffer .chain ),
119127 )
120-
121- except asyncio .CancelledError :
122- pass
123- except Exception as e :
124- logger .error ("[CLI] Delayed response error: %s" , e )
125- if self .response_future and not self .response_future .done ():
126- self .response_future .set_exception (e )
128+ else :
129+ # 管道完成但没有任何发送操作(如被白名单/频率限制拦截)
130+ self .response_future .set_result (None )
131+ logger .debug ("[CLI] Pipeline done, no response to send" )
0 commit comments