新增元宝(Yuanbao)渠道的完整适配器实现,包含以下核心模块: - 基础适配器与导出入口 - 协议编解码与WebSocket帧处理 - 会话管理与路由逻辑 - 事件队列与出站消息队列 - 消息格式转换与发送重试 - 安全审计与权限校验 - 配置映射与账户管理 - 视觉分析与工具函数 - 文档生成与设置向导
146 lines
6.0 KiB
Python
146 lines
6.0 KiB
Python
from __future__ import annotations
|
||
|
||
from dataclasses import dataclass, field
|
||
|
||
from yuxi.channels.capabilities import ChannelCapabilities
|
||
from yuxi.channels.meta import ChannelMeta
|
||
|
||
|
||
@dataclass
|
||
class ChannelDocSection:
|
||
title: str
|
||
content: str
|
||
subsections: list[ChannelDocSection] = field(default_factory=list)
|
||
|
||
|
||
YUANBAO_CONFIG_KEYS: dict[str, str] = {
|
||
"app_key": "应用 Key(支持 ${ENV_VAR} 环境变量引用)",
|
||
"app_secret": "应用 Secret(支持 ${ENV_VAR} 环境变量引用)",
|
||
"bot_app_id": "Bot 应用 ID",
|
||
"token": "预签名 Token(跳过自动签名流程)",
|
||
"apiBase": "API 基础域名(顶级)",
|
||
"ws_url": "WebSocket 连接地址",
|
||
"ws_max_reconnect": "WebSocket 最大重连次数",
|
||
"ws_ping_interval": "WebSocket 心跳间隔(秒)",
|
||
"ws_ping_timeout": "WebSocket 心跳超时(秒)",
|
||
"ws_close_timeout": "WebSocket 关闭超时(秒)",
|
||
"ws_auth_timeout": "WebSocket 认证超时(秒)",
|
||
"dm_policy": "DM 策略:open/pairing/allowlist/disabled",
|
||
"allow_from": "DM 白名单(支持 * 通配)",
|
||
"requireMention": "群聊是否需要 @机器人",
|
||
"overflowPolicy": "溢出策略:split/stop",
|
||
"replyToMode": "引用回复模式:off/first/all",
|
||
"outboundQueueStrategy": "出站队列策略:merge-text/immediate",
|
||
"minChars": "merge-text 最小合并字符数",
|
||
"maxChars": "merge-text 最大合并字符数",
|
||
"idleMs": "merge-text 空闲等待毫秒数",
|
||
"mediaMaxMb": "媒体最大大小(MB)",
|
||
"historyLimit": "群聊历史上下文限制",
|
||
"disableBlockStreaming": "禁用块级流式输出",
|
||
"fallbackReply": "回退回复内容",
|
||
"markdownHintEnabled": "启用 Markdown 提示注入",
|
||
"debugBotIds": "调试 Bot ID 列表",
|
||
"defaultAccount": "默认账户 ID",
|
||
"maxConcurrency": "最大并发发送数",
|
||
"routeEnv": "路由环境标识(顶级)",
|
||
"accounts.<id>.appKey": "账户级 App Key",
|
||
"accounts.<id>.appSecret": "账户级 App Secret",
|
||
"accounts.<id>.enabled": "账户启用状态",
|
||
"accounts.<id>.name": "账户名称",
|
||
"accounts.<id>.token": "账户级预签名 Token",
|
||
"accounts.<id>.apiDomain": "账户级 API 域名",
|
||
"accounts.<id>.wsUrl": "账户级 WebSocket 地址",
|
||
"accounts.<id>.logUploadApiUrl": "账户级日志上传 API URL",
|
||
"accounts.<id>.routeEnv": "账户级路由环境标识",
|
||
"groups.<id>.requireMention": "群组级是否需要 @机器人",
|
||
"groups.<id>.enabled": "群组级启用状态",
|
||
}
|
||
|
||
|
||
def generate_channel_docs(
|
||
channel_id: str,
|
||
capabilities: ChannelCapabilities,
|
||
meta: ChannelMeta,
|
||
config_keys: dict[str, str] | None = None,
|
||
) -> str:
|
||
config_keys = config_keys or YUANBAO_CONFIG_KEYS
|
||
lines = [
|
||
f"# {meta.label} ({channel_id})",
|
||
"",
|
||
f"> {meta.blurb}",
|
||
"",
|
||
"## 基本信息",
|
||
"",
|
||
f"- **渠道 ID**: `{channel_id}`",
|
||
f"- **别名**: {', '.join(f'`{a}`' for a in meta.aliases) if meta.aliases else '无'}",
|
||
f"- **支持的聊天类型**: {', '.join(capabilities.chat_types)}",
|
||
f"- **投递模式**: {capabilities.delivery_mode}",
|
||
f"- **排序权重**: {meta.order}",
|
||
"",
|
||
"## 能力矩阵",
|
||
"",
|
||
_capability_table(capabilities),
|
||
"",
|
||
"## 消息类型支持",
|
||
"",
|
||
_message_type_section(capabilities),
|
||
"",
|
||
"## 流式输出",
|
||
"",
|
||
f"- **支持流式输出**: {'是' if capabilities.supports_streaming else '否'}",
|
||
f"- **流式模式**: {', '.join(capabilities.streaming_modes)}",
|
||
f"- **Block Streaming**: {'支持' if capabilities.block_streaming else '不支持'}",
|
||
f"- **Lane Streaming**: {'支持' if capabilities.lane_streaming else '不支持'}",
|
||
f"- **Reasoning Streaming**: {'支持' if capabilities.reasoning_streaming else '不支持'}",
|
||
f"- **Markdown 支持**: {'是' if capabilities.supports_markdown else '否'}",
|
||
f"- **文本分块限制**: {capabilities.text_chunk_limit} 字符",
|
||
f"- **媒体大小限制**: {capabilities.max_media_size_mb} MB",
|
||
]
|
||
|
||
if config_keys:
|
||
lines.extend(["", "## 配置项参考", "", _config_table(config_keys)])
|
||
|
||
return "\n".join(lines)
|
||
|
||
|
||
def _capability_table(caps: ChannelCapabilities) -> str:
|
||
rows = [
|
||
"| 能力 | 状态 |",
|
||
"|------|:--:|",
|
||
f"| 媒体消息 | {'✅' if caps.media else '❌'} |",
|
||
f"| 消息回复 | {'✅' if caps.reply else '❌'} |",
|
||
f"| 消息编辑 | {'✅' if caps.edit else '❌'} |",
|
||
f"| 消息撤回 | {'✅' if caps.unsend else '❌'} |",
|
||
f"| 反应 | {'✅' if caps.reactions else '❌'} |",
|
||
f"| 投票 | {'✅' if caps.polls else '❌'} |",
|
||
f"| 线程 | {'✅' if caps.threads else '❌'} |",
|
||
f"| 群组管理 | {'✅' if caps.group_management else '❌'} |",
|
||
f"| 置顶 | {'✅' if caps.pin else '❌'} |",
|
||
f"| 取消置顶 | {'✅' if caps.unpin else '❌'} |",
|
||
f"| 消息特效 | {'✅' if caps.effects else '❌'} |",
|
||
f"| TTS 语音 | {'✅' if caps.tts.voice.enabled else '❌'} |",
|
||
f"| 原生命令 | {'✅' if caps.native_commands else '❌'} |",
|
||
f"| 阅后即焚 | {'✅' if caps.send_ephemeral else '❌'} |",
|
||
]
|
||
return "\n".join(rows)
|
||
|
||
|
||
def _message_type_section(caps: ChannelCapabilities) -> str:
|
||
return (
|
||
f"- **文本**: 支持\n"
|
||
f"- **媒体(图片/文件/音频/视频/贴纸)**: {'支持' if caps.media else '不支持'}\n"
|
||
f"- **Markdown**: {'支持' if caps.supports_markdown else '不支持'}\n"
|
||
f"- **投票**: {'支持' if caps.polls else '不支持'}\n"
|
||
f"- **TTS**: {'支持' if caps.tts.voice.enabled else '不支持'}"
|
||
)
|
||
|
||
|
||
def _config_table(config_keys: dict[str, str]) -> str:
|
||
rows = [
|
||
"| 配置键 | 说明 |",
|
||
"|--------|------|",
|
||
]
|
||
for key, desc in config_keys.items():
|
||
rows.append(f"| `{key}` | {desc} |")
|
||
return "\n".join(rows)
|