ForcePilot/backend/package/yuxi/channel/sdk/actions/discovery.py
Kris b438af3ba8 feat(channel-sdk): 新增完整的渠道SDK工具链
本提交新增了全渠道SDK核心模块:
1.  异步锁、目标解析、动作调度等基础工具
2.  消息动作注册与统一调度系统
3.  测试套件与契约测试框架
4.  完整的目标解析流水线与工具函数
5.  资源依赖注入与生命周期管理
2026-05-21 10:29:12 +08:00

68 lines
2.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from __future__ import annotations
import logging
from yuxi.channel.plugins.registry import ChannelPluginRegistry
from yuxi.channel.sdk.actions.names import MessageAction
logger = logging.getLogger(__name__)
def list_all_actions() -> set[MessageAction]:
"""列出所有已注册渠道支持的所有 action对齐 OpenClaw listChannelMessageActions"""
actions: set[MessageAction] = {MessageAction.SEND}
for plugin in ChannelPluginRegistry.all():
adapter = getattr(plugin, "actions", None)
if adapter is None:
continue
for action in adapter.list_actions():
actions.add(action)
return actions
def list_channel_actions(channel_type: str) -> list[MessageAction]:
"""列出指定渠道支持的 action 列表。"""
plugin = ChannelPluginRegistry.get(channel_type)
if plugin is None:
return []
adapter = getattr(plugin, "actions", None)
if adapter is None:
return []
return adapter.list_actions()
def get_channel_actions_schema(channel_type: str) -> list[dict]:
"""获取指定渠道的 action schema供 Agent tool 注册使用)。"""
plugin = ChannelPluginRegistry.get(channel_type)
if plugin is None:
return []
adapter = getattr(plugin, "actions", None)
if adapter is None:
return []
return [desc.to_capability() for desc in adapter.describe_actions()]
def build_unified_message_tool_schema() -> dict:
"""构建跨所有渠道的统一 message tool schema对齐 OpenClaw resolveChannelMessageToolSchemaProperties"""
all_actions = list_all_actions()
properties: dict[str, dict] = {}
for channel_type in ChannelPluginRegistry.list_plugins():
schema = get_channel_actions_schema(channel_type)
for action_desc in schema:
action_name = action_desc["action"]
if action_name not in properties:
properties[action_name] = {
"description": action_desc.get("description", ""),
"channels": [channel_type],
"parameters": action_desc.get("parameters", []),
}
else:
properties[action_name]["channels"].append(channel_type)
return {
"name": "message",
"description": "Send or manage messages across channels",
"actions": sorted(all_actions),
"properties": properties,
}