fix: unify handling of whitespace in streamed message segments and ensure trailing buffers are stripped before sending. (#9029)

* perf(streaming): 将流式消息分段发送的空白过滤逻辑前移至核心方法

- 在 AstrMessageEvent 的 process_buffer 中统一进行 strip 并跳过空段,移除各平台子类的重复处理
- aiocqhttp 平台回退尾部 buffer 直接使用核心逻辑过滤,避免自身再次判断空白
- 简化流式消息发送链路,提升代码可维护性与执行效率

* test(strip-stream): 添加流式消息分段空白过滤的单元测试

- 新增 CollectingMessageEvent 与 CollectingAiocqhttpMessageEvent 辅助类,模拟消息发送与断言
- 覆盖 AstrMessageEvent.process_buffer 对段落前导空白行的 strip 和空段跳过逻辑
- 覆盖 AiocqhttpMessageEvent.send_streaming 回退缓冲区的空白过滤,确保跨平台行为一致

* fix(streaming): 调整流式消息分段发送限速等待位置

- 将限速等待(sleep)从循环末尾移动至消息发送成功后立即执行
- 仅在成功发送文本片段时才进行等待,避免无实际发送时的无谓延迟
- 修复因等待时机不当可能导致的流式消息发送频率异常问题

* test(strip-stream): 添加空白分段时跳过睡眠的单元测试
- 新增测试用例,验证当分段为空时不调用睡眠函数
- 确保处理缓冲区时正确剥离空白字符
- 测试通过验证发送消息的行为

* Delete tests/test_streaming_segment_strip.py

---------

Co-authored-by: Weilong Liao <37870767+Soulter@users.noreply.github.com>
This commit is contained in:
NayukiChiba
2026-06-26 22:11:31 +08:00
committed by GitHub
parent 110cc8736c
commit c93bedf04d
2 changed files with 6 additions and 4 deletions

View File

@@ -269,10 +269,11 @@ class AstrMessageEvent(abc.ABC):
match = re.search(pattern, buffer)
if not match:
break
matched_text = match.group()
await self.send(MessageChain([Plain(matched_text)]))
matched_text = match.group().strip()
if matched_text:
await self.send(MessageChain([Plain(matched_text)]))
await asyncio.sleep(1.5) # 限速
buffer = buffer[match.end() :]
await asyncio.sleep(1.5) # 限速
return buffer
async def send_streaming(

View File

@@ -228,7 +228,8 @@ class AiocqhttpMessageEvent(AstrMessageEvent):
await self.send(MessageChain(chain=[comp]))
await asyncio.sleep(1.5) # 限速
if buffer.strip():
buffer = buffer.strip()
if buffer:
await self.send(MessageChain([Plain(buffer)]))
return await super().send_streaming(generator, use_fallback)