ForcePilot/backend/package/yuxi/channels/capabilities.py
Kris 29dac24600 feat(channels): 完成渠道模块多维度功能迭代与优化
本次提交对渠道模块进行了全面升级,包含以下核心改进:
1. 新增二维码登录相关协议方法,完善登录流程
2. 优化配置监听逻辑,增加渠道运行状态前置校验
3. 重构动作注册机制,支持动态注册渠道动作并新增批量操作能力
4. 扩展渠道能力模型,新增广播、文件传输等支持
5. 优化适配器加载路径,新增元宝适配器支持
6. 新增凭证过期检查与告警能力,完善运维监控
7. 重构统计收集器,支持多维度渠道统计数据
8. 优化消息路由策略,新增策略缓存与安全处理逻辑
9. 重构基础适配器,新增凭证管理工具方法
10. 完善状态存储功能,支持凭证数据管理与批量清理
11. 重构渠道管理器,新增配置校验、动态渠道管理、限流能力
12. 优化健康检查与状态上报逻辑,完善审计日志与异常处理
2026-05-14 02:08:36 +08:00

219 lines
6.2 KiB
Python

from __future__ import annotations
from pydantic import BaseModel, Field
class ThreadCapabilities(BaseModel):
supports_native_threads: bool = False
supports_topics: bool = False
supports_reply_chains: bool = False
supports_simulated_threads: bool = False
max_thread_depth: int = 1
supports_history_fetch: bool = False
supports_parent_injection: bool = False
supports_thread_binding: bool = False
history_max_messages: int = 50
history_max_chars: int = 4000
history_ttl_seconds: int = 300
@property
def requires_simulation(self) -> bool:
return not self.supports_native_threads and self.supports_simulated_threads
class TTSVoiceCapabilities(BaseModel):
synthesis_target: str = "voice-note"
transcodes_audio: bool = False
enabled: bool = False
class TTSCapabilities(BaseModel):
voice: TTSVoiceCapabilities = Field(default_factory=TTSVoiceCapabilities)
class ChannelCapabilities(BaseModel):
"""渠道能力声明 — 标准能力标志
BaseChannelAdapter 子类通过声明此模型来告知 Gateway 和前端
该渠道支持哪些功能。Gateway 启动时收集所有渠道的此声明,
通过 get_channel_status() 向客户端广播可用能力集合。
"""
chat_types: list[str] = Field(default_factory=lambda: ["direct"])
delivery_mode: str = "direct"
polls: bool = False
reactions: bool = False
edit: bool = False
unsend: bool = False
reply: bool = False
effects: bool = False
group_management: bool = False
threads: bool = False
thread_caps: ThreadCapabilities = Field(default_factory=ThreadCapabilities)
media: bool = False
max_media_size_mb: int = 100
tts: TTSCapabilities = Field(default_factory=TTSCapabilities)
native_commands: bool = False
block_streaming: bool = False
lane_streaming: bool = False
reasoning_streaming: bool = False
pin: bool = False
unpin: bool = False
list_pins: bool = False
send_ephemeral: bool = False
forward: bool = False
broadcast: bool = False
narrowcast: bool = False
file_transfer: bool = False
vision: bool = False
approval: bool = False
typing: bool = False
text_chunk_limit: int = 4096
supports_markdown: bool = False
supports_streaming: bool = False
streaming_modes: list[str] = Field(default_factory=lambda: ["off"])
def supported_actions(self) -> list[str]:
actions: list[str] = ["send", "reply"]
if self.media:
actions.extend(["send_media", "send_attachment", "download_file", "upload_file"])
if self.edit:
actions.append("edit")
if self.unsend:
actions.extend(["delete", "unsend"])
if self.reactions:
actions.append("react")
if self.pin:
actions.append("pin")
if self.unpin:
actions.append("unpin")
if self.list_pins:
actions.append("list_pins")
if self.polls:
actions.append("create_poll")
if self.threads:
actions.extend(["create_thread", "thread_reply"])
if self.send_ephemeral:
actions.append("send_ephemeral")
if self.group_management:
actions.extend(["kick", "ban", "mute", "add_participant", "remove_participant"])
if getattr(self, "supports_streaming", False):
actions.append("stream")
return actions
CAPS_SIMPLE_TEXT = ChannelCapabilities()
CAPS_FULL_FEATURED = ChannelCapabilities(
chat_types=["direct", "group", "thread"],
polls=True,
reactions=True,
edit=True,
unsend=True,
reply=True,
threads=True,
media=True,
supports_markdown=True,
supports_streaming=True,
streaming_modes=["chunked", "live"],
)
CAPS_GROUP_CHAT_ONLY = ChannelCapabilities(
chat_types=["direct", "group"],
reply=True,
media=True,
group_management=True,
supports_markdown=True,
supports_streaming=True,
streaming_modes=["block"],
)
THREAD_CAPABILITIES: dict[str, ThreadCapabilities] = {
"matrix": ThreadCapabilities(
supports_native_threads=True,
supports_history_fetch=True,
supports_parent_injection=True,
supports_thread_binding=True,
history_max_messages=100,
),
"discord": ThreadCapabilities(
supports_native_threads=True,
supports_history_fetch=True,
supports_thread_binding=True,
history_max_messages=100,
),
"slack": ThreadCapabilities(
supports_native_threads=True,
supports_history_fetch=True,
supports_thread_binding=True,
history_max_messages=50,
),
"feishu": ThreadCapabilities(
supports_native_threads=True,
supports_history_fetch=True,
supports_parent_injection=True,
supports_thread_binding=True,
history_max_messages=100,
),
"telegram": ThreadCapabilities(
supports_topics=True,
supports_history_fetch=True,
supports_thread_binding=True,
),
"whatsapp": ThreadCapabilities(
supports_topics=True,
supports_history_fetch=True,
),
"mattermost": ThreadCapabilities(
supports_reply_chains=True,
supports_history_fetch=True,
supports_thread_binding=True,
),
"irc": ThreadCapabilities(
supports_simulated_threads=True,
supports_history_fetch=False,
history_max_messages=0,
),
"nostr": ThreadCapabilities(
supports_simulated_threads=True,
supports_history_fetch=False,
history_max_messages=0,
),
"qqbot": ThreadCapabilities(
supports_simulated_threads=True,
supports_history_fetch=False,
history_max_messages=0,
),
"twitch": ThreadCapabilities(
supports_simulated_threads=True,
supports_history_fetch=False,
history_max_messages=0,
),
"msteams": ThreadCapabilities(
supports_native_threads=True,
supports_history_fetch=False,
supports_parent_injection=False,
supports_thread_binding=True,
),
"wechat": ThreadCapabilities(
supports_simulated_threads=True,
supports_history_fetch=False,
supports_parent_injection=False,
),
}