2026-07-02 03:22:12 +08:00
|
|
|
|
"""命令 DTO。
|
|
|
|
|
|
|
|
|
|
|
|
定义渠道命令注册与执行的不可变值对象,包括命令权限、命令 ID、渠道命令、
|
2026-07-02 18:27:06 +08:00
|
|
|
|
命令响应与命令结果。所有 DTO 均为 ``dataclass(frozen=True)``,依赖
|
|
|
|
|
|
标准库与契约层 ``ValidationError``,用于命令插件注册与命令执行结果回传。
|
2026-07-02 03:22:12 +08:00
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
|
|
from dataclasses import dataclass
|
|
|
|
|
|
from enum import StrEnum
|
2026-07-03 19:18:13 +08:00
|
|
|
|
from typing import Literal
|
2026-07-02 03:22:12 +08:00
|
|
|
|
|
2026-07-03 19:18:13 +08:00
|
|
|
|
from yuxi.channels.contract.errors import ValidationError
|
2026-07-02 18:27:06 +08:00
|
|
|
|
|
2026-07-02 03:22:12 +08:00
|
|
|
|
|
|
|
|
|
|
class CommandPermission(StrEnum):
|
|
|
|
|
|
"""命令权限。
|
|
|
|
|
|
|
|
|
|
|
|
标识渠道命令的可见性与执行权限层级,用于命令注册时声明与执行时校验。
|
|
|
|
|
|
继承 ``str, Enum`` 以支持 JSON 序列化与字符串比较。
|
|
|
|
|
|
|
|
|
|
|
|
取值:
|
|
|
|
|
|
PRIVATE: 仅私聊可用。
|
|
|
|
|
|
GROUP: 仅群聊可用。
|
|
|
|
|
|
ADMIN: 仅管理员可用。
|
|
|
|
|
|
ALL: 所有场景可用。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
PRIVATE = "private"
|
|
|
|
|
|
GROUP = "group"
|
|
|
|
|
|
ADMIN = "admin"
|
|
|
|
|
|
ALL = "all"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
|
|
|
|
class CommandId:
|
|
|
|
|
|
"""命令 ID。
|
|
|
|
|
|
|
|
|
|
|
|
标识一条已注册的渠道命令的全局唯一 ID,用于命令路由与审计关联。
|
|
|
|
|
|
|
|
|
|
|
|
字段:
|
|
|
|
|
|
value: 命令 ID 字符串。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
value: str
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
|
|
|
|
class ChannelCommand:
|
2026-07-03 19:18:13 +08:00
|
|
|
|
"""渠道命令(FR-15)。
|
2026-07-02 03:22:12 +08:00
|
|
|
|
|
|
|
|
|
|
描述渠道命令的元信息,由命令插件声明,用于命令注册、权限校验与帮助
|
|
|
|
|
|
文档生成。
|
|
|
|
|
|
|
|
|
|
|
|
字段:
|
|
|
|
|
|
name: 命令名称。
|
|
|
|
|
|
description: 命令描述。
|
|
|
|
|
|
permission: 命令权限(默认 ALL)。
|
|
|
|
|
|
is_silent: 是否静默执行(不回显响应,默认 False)。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
name: str
|
|
|
|
|
|
description: str
|
|
|
|
|
|
permission: CommandPermission = CommandPermission.ALL
|
|
|
|
|
|
is_silent: bool = False
|
|
|
|
|
|
|
2026-07-02 18:27:06 +08:00
|
|
|
|
def __post_init__(self) -> None:
|
|
|
|
|
|
"""校验必填字段非空。
|
|
|
|
|
|
|
|
|
|
|
|
``name`` 与 ``description`` 必须非空,在构造时即抛出
|
|
|
|
|
|
``ValidationError``,adapter 不再做该校验(INV-8)。
|
|
|
|
|
|
"""
|
|
|
|
|
|
if not self.name:
|
|
|
|
|
|
raise ValidationError("name", "must not be empty")
|
|
|
|
|
|
if not self.description:
|
|
|
|
|
|
raise ValidationError("description", "must not be empty")
|
|
|
|
|
|
|
2026-07-02 03:22:12 +08:00
|
|
|
|
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
|
|
|
|
class CommandResponse:
|
|
|
|
|
|
"""命令响应。
|
|
|
|
|
|
|
|
|
|
|
|
描述命令执行后返回给渠道的内容,支持指定内容类型与回复目标。
|
|
|
|
|
|
|
|
|
|
|
|
字段:
|
|
|
|
|
|
content: 响应内容。
|
|
|
|
|
|
content_type: 内容类型(text | markdown | rich,默认 text)。
|
|
|
|
|
|
target: 回复目标,None 表示原会话。
|
|
|
|
|
|
is_silent: 是否静默(不回显,默认 False)。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
content: str
|
2026-07-03 19:18:13 +08:00
|
|
|
|
content_type: Literal["text", "markdown", "rich"] = "text"
|
2026-07-02 03:22:12 +08:00
|
|
|
|
target: str | None = None
|
|
|
|
|
|
is_silent: bool = False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
|
|
|
|
class CommandResult:
|
|
|
|
|
|
"""命令结果。
|
|
|
|
|
|
|
|
|
|
|
|
描述命令执行的最终结果,携带命令名、是否静默与可选的响应内容,用于
|
|
|
|
|
|
管道下游决策是否回显与审计记录。
|
|
|
|
|
|
|
|
|
|
|
|
字段:
|
|
|
|
|
|
command: 命令名。
|
|
|
|
|
|
is_silent: 是否静默执行(默认 False)。
|
|
|
|
|
|
response: 命令响应(无响应时为 None)。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
command: str
|
|
|
|
|
|
is_silent: bool = False
|
|
|
|
|
|
response: CommandResponse | None = None
|