ForcePilot/backend/package/yuxi/channels/contract/dtos/outbound.py
Kris 53e067aa4b feat: 多渠道网关核心功能迭代
包含以下变更:
1. 重构微信WOC账户模型,移除固定DEFAULT_ACCOUNT
2. 新增路由绑定管理、目录搜索导出能力
3. 扩展消息查询与出站管理过滤条件
4. 新增SSE事件广播、敏感字段/配置作用域注册表
5. 新增审计日志与配对过期定时任务
6. 优化会话处理与参数校验逻辑
7. 修复sender_id校验与outbox序列化问题
2026-07-07 16:20:40 +08:00

332 lines
10 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""出站 DTO。
定义出站管道的富消息与最终输出值对象,包括富消息按钮、富消息选项、
富消息、富消息字段、出站负载、格式化消息、可信消息与最终消息。
所有 DTO 均为 ``dataclass(frozen=True)``,仅依赖标准库与契约层内部
类型,用于出站消息的格式化、可信注入与最终投递。集合字段使用 tuple
以保证 frozen dataclass 的不可变语义。
"""
from __future__ import annotations
from dataclasses import dataclass
from typing import Any
from yuxi.channels.contract.dtos.common import Attachment, MessageFormat
from yuxi.channels.contract.errors import ValidationError
@dataclass(frozen=True)
class RichMessageButton:
"""富消息按钮。
描述富消息中的可点击按钮,由适配器按渠道协议渲染为对应交互元素。
字段:
label: 按钮显示文本。
action: 按钮动作标识。
value: 按钮动作携带的值(可选)。
"""
label: str
action: str
value: str | None = None
@dataclass(frozen=True)
class RichMessageOption:
"""富消息选项。
描述富消息中的可选项,用于下拉 / 列表类交互组件。
字段:
label: 选项显示文本。
value: 选项值。
"""
label: str
value: str
@dataclass(frozen=True)
class RichMessageSelect:
"""富消息下拉选择器组件。
字段:
name: 表单字段名。
label: 显示标签。
options: 可选项列表。
placeholder: 占位文本,可选。
default_value: 默认值,可选。
"""
name: str
label: str
options: tuple[RichMessageOption, ...]
placeholder: str | None = None
default_value: str | None = None
@dataclass(frozen=True)
class RichMessageDatePicker:
"""富消息日期选择器组件。
字段:
name: 表单字段名。
label: 显示标签。
placeholder: 占位文本,可选。
default_value: 默认日期ISO 格式),可选。
min_date: 最小可选日期ISO 格式),可选。
max_date: 最大可选日期ISO 格式),可选。
"""
name: str
label: str
placeholder: str | None = None
default_value: str | None = None
min_date: str | None = None
max_date: str | None = None
@dataclass(frozen=True)
class RichMessageCheckbox:
"""富消息复选框组件。
字段:
name: 表单字段名。
label: 显示标签。
options: 可选项列表。
default_values: 默认选中值列表。
"""
name: str
label: str
options: tuple[RichMessageOption, ...]
default_values: tuple[str, ...] = ()
@dataclass(frozen=True)
class RichMessageInput:
"""富消息输入框组件。
字段:
name: 表单字段名。
label: 显示标签。
placeholder: 占位文本,可选。
default_value: 默认值,可选。
max_length: 最大输入长度,可选。
input_type: 输入类型text/number/email 等),默认 text。
"""
name: str
label: str
placeholder: str | None = None
default_value: str | None = None
max_length: int | None = None
input_type: str = "text"
@dataclass(frozen=True)
class RichMessage:
"""富消息。
描述结构化的富消息内容,包括标题、正文、描述、图片、视频与交互元素
(按钮 / 选项),由适配器按渠道协议渲染。集合字段使用 tuple 以
保证不可变。
字段:
text: 正文文本。
title: 标题(可选)。
description: 描述(可选)。
image_url: 图片 URL可选向后兼容
video_url: 视频 URL可选FR-50
attachments: 多附件列表承载多图、文件等FR-50
buttons: 按钮列表(默认空 tuple
options: 选项列表(默认空 tuple
metadata: 渠道侧元数据(可选)。
selects: 下拉选择器组件列表。
date_pickers: 日期选择器组件列表。
checkboxes: 复选框组件列表。
inputs: 输入框组件列表。
"""
text: str
title: str | None = None
description: str | None = None
image_url: str | None = None
video_url: str | None = None
attachments: tuple[Attachment, ...] = ()
buttons: tuple[RichMessageButton, ...] = ()
options: tuple[RichMessageOption, ...] = ()
metadata: dict[str, Any] | None = None
selects: tuple[RichMessageSelect, ...] = ()
date_pickers: tuple[RichMessageDatePicker, ...] = ()
checkboxes: tuple[RichMessageCheckbox, ...] = ()
inputs: tuple[RichMessageInput, ...] = ()
@dataclass(frozen=True)
class RichMessageFields:
"""富消息字段。
包装富消息与其回退格式,用于出站负载携带富消息渲染信息,当渠道
不支持富消息时按回退格式渲染。
字段:
rich_message: 富消息内容。
fallback_format: 回退格式(默认 MARKDOWN
"""
rich_message: RichMessage
fallback_format: MessageFormat = MessageFormat.MARKDOWN
@dataclass(frozen=True)
class OutboundPayload:
"""出站负载。
描述出站管道的统一负载,关联 Agent 运行 ID携带流式分块、可选的
富消息字段与附件列表,用于驱动出站消息的格式化与投递。
字段:
agent_run_id: 关联的 Agent 运行 ID。
stream_chunks: 流式分块列表(默认空 tuple
rich_message_fields: 富消息字段(可选)。
attachments: 附件列表(默认空 tupleFR-51
"""
agent_run_id: str | None = None
stream_chunks: tuple[str, ...] = ()
rich_message_fields: RichMessageFields | None = None
attachments: tuple[Attachment, ...] = ()
@dataclass(frozen=True)
class FormattedMessage:
"""格式化消息。
描述经格式化后的消息内容,携带文本、格式、可选的富消息与附件列表,
用于适配器按渠道协议渲染最终消息。
字段:
content: 消息文本内容。
format: 消息格式(默认 TEXT
rich_message: 渲染后的渠道原生富消息对象(可选,由
RichMessageAdapter.renderRichMessage 产生,类型由具体适配器
决定)。
attachments: 附件列表(默认空 tupleFR-51
"""
content: str
format: MessageFormat = MessageFormat.TEXT
rich_message: Any = None
attachments: tuple[Attachment, ...] = ()
@dataclass(frozen=True)
class TrustedMessage:
"""可信消息。
描述经服务端强制注入发送者身份与所有者标记的消息,用于可信注入
边界FR-25确保渠道侧无法伪造发送者。
字段:
content: 消息文本内容。
sender_id: 发送者 ID服务端强制注入
is_owner: 是否为会话所有者(服务端强制注入,默认 False
rich_message: 渲染后的渠道原生富消息对象(可选,从
FormattedMessage 透传FR-08
"""
content: str
sender_id: str
is_owner: bool = False
rich_message: Any = None
def __post_init__(self) -> None:
"""校验必填字段非空。
``content`` 与 ``sender_id`` 必须非空,在构造时即抛出
``ValidationError``,避免空消息内容或空发送者身份传播到渠道
适配器INV-8
"""
if not self.content:
raise ValidationError("content", "must not be empty")
if not self.sender_id:
raise ValidationError("sender_id", "must not be empty")
@dataclass(frozen=True)
class FinalMessage:
"""最终消息。
描述出站管道最终投递至渠道适配器的消息,携带文本、发送者 ID 与
可选前缀,前缀用于所有者标记等场景。
字段:
content: 消息文本内容。
sender_id: 发送者 ID。
prefix: 前缀(可选,如所有者标记)。
rich_message: 渲染后的渠道原生富消息对象(可选,从
TrustedMessage 透传FR-08
"""
content: str
sender_id: str
prefix: str | None = None
rich_message: Any = None
def __post_init__(self) -> None:
"""校验必填字段非空。
``content`` 与 ``sender_id`` 必须非空,在构造时即抛出
``ValidationError``,避免空消息内容或空发送者身份投递到渠道
INV-8
"""
if not self.content:
raise ValidationError("content", "must not be empty")
if not self.sender_id:
raise ValidationError("sender_id", "must not be empty")
@dataclass(frozen=True)
class BatchSendItem:
"""批量发送单条结果。
描述 ``OutboundAdapter.batchSendMessages`` 单条投递结果,与
``MultiPartReceipt`` 区别:``MultiPartReceipt`` 描述**同一条**逻辑
消息拆分为多个分片的回执,``BatchSendItem`` 描述**同一负载**投递到
多个 peer 的逐条结果。
字段:
peer_id: 接收目标 ID。
channel_msg_id: 渠道侧消息 ID成功时非空失败时为空字符串
success: 是否投递成功。
error: 失败时的错误信息(可选,成功时为 ``None``)。
"""
peer_id: str
channel_msg_id: str
success: bool
error: str | None = None
@dataclass(frozen=True)
class BatchSendResult:
"""批量发送结果。
描述 ``OutboundAdapter.batchSendMessages`` 的聚合结果,包含逐条结果
与汇总统计。集合字段使用 tuple 以保证 frozen dataclass 的不可变语义。
字段:
total: 总投递目标数。
succeeded: 成功的目标 ID 元组。
failed: 失败条目元组(含目标 ID 与错误信息)。
items: 逐条结果元组(含成功与失败)。
"""
total: int
succeeded: tuple[str, ...]
failed: tuple[BatchSendItem, ...]
items: tuple[BatchSendItem, ...]