ForcePilot/backend/package/yuxi/channels/contract/dtos/admin.py

84 lines
3.1 KiB
Python
Raw Normal View History

"""管理员消息 DTO。
定义管理员消息发送的命令与结果值对象包括管理员发送命令与发送结果
所有 DTO 均为 ``dataclass(frozen=True)``仅依赖标准库与契约层内部类型
用于管理员向目标会话或用户批量发送消息并聚合失败与跳过详情集合字段
使用 tuple 以保证 frozen dataclass 的不可变语义
"""
from __future__ import annotations
from dataclasses import dataclass
from typing import Literal
from yuxi.channels.contract.dtos.common import (
FailureDetail,
MessageContent,
Operator,
SkipDetail,
)
from yuxi.channels.contract.errors import ValidationError
@dataclass(frozen=True)
class AdminSendCmd:
"""管理员发送命令FR-19
由管理员消息端口方法引用描述管理员向目标会话或用户发送消息的请求
携带目标内容会话策略幂等键与操作人支持复用 / 新建 / 临时
三种会话策略
字段
target: 目标会话或用户
content: 消息内容
conversation_policy: 会话策略reuse | reuse-or-create | new
idempotency_key: 幂等键
operator: 操作人审计用
target_type: 目标类型session_id peer_id默认 session_id
"""
target: str
content: MessageContent
conversation_policy: Literal["reuse", "reuse-or-create", "new"]
idempotency_key: str
operator: Operator
target_type: Literal["session_id", "peer_id"] = "session_id"
def __post_init__(self) -> None:
"""校验必填字段非空FR-19
``target`` ``idempotency_key`` 必须非空在构造时即抛出
``ValidationError``adapter 不再做该校验INV-8
``conversation_policy`` 的合法值校验由 ``AdminMessageService``
统一执行``_CONVERSATION_POLICIES``DTO 层不重复校验避免
service 层默认值回退``or _DEFAULT_CONVERSATION_POLICY``
冲突
``target_type`` 默认 ``"session_id"``按会话 ID 触达
``"peer_id"`` 表示按对端 ID 触达需配合 ``channel_type`` /
``account_id`` 路由信息 ``_resolveTarget`` 解析
"""
if not self.target:
raise ValidationError("target", "must not be empty")
if not self.idempotency_key:
raise ValidationError("idempotency_key", "must not be empty")
@dataclass(frozen=True)
class AdminSendResult:
"""管理员发送结果FR-19
描述管理员批量发送消息的执行结果聚合成功消息 ID失败详情与跳过
详情用于结果汇报与重试策略决策集合字段使用 tuple 以保证不可变
字段
message_ids: 成功发送的消息 ID 列表
failures: 失败详情列表默认空 tuple
skipped: 跳过详情列表默认空 tuple
"""
message_ids: tuple[str, ...]
failures: tuple[FailureDetail, ...] = ()
skipped: tuple[SkipDetail, ...] = ()