from __future__ import annotations import logging from dataclasses import dataclass, field from yuxi.channel.sdk.actions.names import MessageAction logger = logging.getLogger(__name__) @dataclass class DispatchContext: """动作调度上下文(对齐 OpenClaw ChannelMessageActionContext)。""" channel_type: str action: str params: dict = field(default_factory=dict) account_id: str = "default" requester_sender_id: str | None = None sender_is_owner: bool = False session_key: str | None = None agent_id: str | None = None async def dispatch_message_action(ctx: DispatchContext) -> dict: """统一消息动作调度入口。 执行流程(对齐 OpenClaw dispatchChannelMessageAction): 1. 获取插件 → 失败则返回 2. 获取 actions adapter → 失败则返回 3. 信任发送者检查 → 失败则返回 4. supports_action 检查 → 不支持则返回 5. 执行 """ from yuxi.channel.plugins.registry import ChannelPluginRegistry plugin = ChannelPluginRegistry.get(ctx.channel_type) if plugin is None: return { "success": False, "error": f"渠道 {ctx.channel_type} 未注册", } adapter = getattr(plugin, "actions", None) if adapter is None: return { "success": False, "error": f"渠道 {ctx.channel_type} 未配置 MessageActionRegistry", } if ( adapter.requires_trusted_sender(ctx.action) and not ctx.requester_sender_id ): return { "success": False, "error": f"Action '{ctx.action}' requires trusted sender identity", } if not adapter.supports_action(ctx.action): return { "success": False, "error": f"渠道 {ctx.channel_type} 不支持 action: {ctx.action}", } result = await adapter.execute_action( ctx.action, params=ctx.params, context={ "channel_type": ctx.channel_type, "account_id": ctx.account_id, "requester_sender_id": ctx.requester_sender_id, "sender_is_owner": ctx.sender_is_owner, "session_key": ctx.session_key, "agent_id": ctx.agent_id, }, ) return { "success": result.get("success", False), "message": result.get("error", ""), "data": result if result.get("success") else {}, }