Files
zhenxun_bot/zhenxun/services/ai/run/ui.py
T

85 lines
3.0 KiB
Python
Raw Normal View History

from __future__ import annotations
from typing import Any
from nonebot_plugin_alconna import UniMessage
from zhenxun.services.ai.core.stream_events import ToolStreamChunkEvent, UserCustomEvent
from zhenxun.utils.message import MessageUtils
from zhenxun.utils.platform import PlatformUtils
from .context import RunContext
class UIController:
"""前端 UI 富交互流式控制器 (按需生成模式)"""
def __init__(self, context: RunContext):
self.context = context
@property
def tool_name(self) -> str:
"""从上下文中动态获取当前调用的工具名"""
return getattr(self.context.call, "tool_name", "UnknownTool")
async def send_text(self, text: str, status: str = "running") -> None:
"""向前端流式反馈执行进度文本"""
await self.context.run.emit(
ToolStreamChunkEvent(
tool_name=self.tool_name, content=text, metadata={"status": status}
)
)
async def send_image(self, image: bytes | str) -> None:
"""向前端发送富文本图片气泡(字节流或 URL)"""
display_msg = UniMessage()
if isinstance(image, bytes):
display_msg = display_msg.image(raw=image)
else:
display_msg = display_msg.image(url=image)
await self.context.run.emit(UserCustomEvent(display=display_msg))
async def send_display(self, display: Any) -> None:
"""向前端发送任意展示载体"""
if display is not None:
await self.context.run.emit(UserCustomEvent(display=display))
@staticmethod
async def handle_control_flow_exit_display(
e: BaseException, context: RunContext | None, reply_to: bool = False
) -> None:
"""统一处理 ControlFlowExit 异常带来的 UI 反馈逻辑"""
from zhenxun.services.ai.core.exceptions import ControlFlowExit
if not isinstance(e, ControlFlowExit):
return
display_msg = getattr(e, "display", None) or getattr(e, "display_content", None)
if not display_msg:
return
try:
bot = context.get_bot() if context else None
event = context.get_event() if context else None
if bot:
msg_to_send = (
display_msg
if isinstance(display_msg, UniMessage)
else MessageUtils.build_message(str(display_msg))
)
if event:
await msg_to_send.send(event, bot=bot, reply_to=reply_to)
elif context:
target = PlatformUtils.get_target(
user_id=context.get_user_id(), group_id=context.get_group_id()
)
if target:
await msg_to_send.send(target=target, bot=bot)
else:
await MessageUtils.build_message(str(display_msg)).send(
reply_to=reply_to
)
except Exception:
pass