from __future__ import annotations from pydantic import BaseModel, Field 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 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 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] = [] if self.media: actions.append("send_media") if self.edit: actions.append("edit") if self.unsend: actions.append("delete") 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.append("create_thread") if self.send_ephemeral: actions.append("send_ephemeral") if self.group_management: actions.extend(["kick", "ban", "mute"]) 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"], )