新增完整的 channels 限界上下文模块,包含契约层、领域核心层、应用服务、管道编排、插件体系、基础设施组合根等全层级代码,新增飞书与微信 iLink 渠道插件基础结构,补充各类 DTO、端口协议与领域服务实现。
113 lines
3.9 KiB
Python
113 lines
3.9 KiB
Python
"""入站 DTO。
|
||
|
||
定义入站管道入口的命令与结果值对象,包括入站消息命令与入站结果。所有
|
||
DTO 均为 ``dataclass(frozen=True)``,仅依赖标准库与契约层内部类型,用于
|
||
渠道适配器向核心层传递原始事件并返回 ACK 决策。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from dataclasses import dataclass, field
|
||
|
||
from yuxi.channels.contract.dtos.channel import ChannelType
|
||
from yuxi.channels.contract.dtos.command import CommandResponse
|
||
from yuxi.channels.contract.dtos.common import RawEvent
|
||
from yuxi.channels.contract.errors import ValidationError
|
||
|
||
|
||
@dataclass(frozen=True)
|
||
class InboundMessageCmd:
|
||
"""入站消息命令。
|
||
|
||
由入站端口方法引用,封装渠道适配器接收到的原始事件,携带渠道类型、
|
||
账户 ID、原始事件与可选追踪 ID,作为入站管道的统一输入。
|
||
|
||
字段:
|
||
channel_type: 渠道类型。
|
||
account_id: 渠道账户 ID。
|
||
raw_event: 原始事件。
|
||
trace_id: 追踪 ID(可选)。
|
||
"""
|
||
|
||
channel_type: ChannelType
|
||
account_id: str
|
||
raw_event: RawEvent
|
||
trace_id: str | None = None
|
||
|
||
def __post_init__(self) -> None:
|
||
"""校验必填字段非空。
|
||
|
||
``account_id`` 必须非空,在构造时即抛出 ``ValidationError``,
|
||
adapter 不再做该校验(INV-8)。
|
||
"""
|
||
if not self.account_id:
|
||
raise ValidationError("account_id", "must not be empty")
|
||
|
||
|
||
@dataclass(frozen=True)
|
||
class InboundResult:
|
||
"""入站结果。
|
||
|
||
描述入站管道处理后的 ACK 决策与后续 Agent 运行信息,用于适配器按
|
||
决策向渠道侧返回确认或保持静默。
|
||
|
||
字段:
|
||
ack_decision: ACK 决策(ack | nack | pending)。
|
||
agent_run_id: 关联的 Agent 运行 ID(可选)。
|
||
is_silent: 是否静默处理(默认 False)。
|
||
error: NACK 错误消息(FR-24 显式 NACK,与 ACK 互斥,仅
|
||
``ack_decision="nack"`` 时填充)。
|
||
command_response: 命令响应(FR-15)。命令命中且需回显时由
|
||
command-check 阶段填充,供 reply 阶段向渠道侧回送命令响应内容;
|
||
非命令路径或静默命令为 None。
|
||
error_code: 错误码(用例服务捕获异常时填充,默认空字符串)。
|
||
trace_id: 追踪 ID(用例服务捕获异常时填充,默认空字符串)。
|
||
"""
|
||
|
||
ack_decision: str
|
||
agent_run_id: str | None = None
|
||
is_silent: bool = False
|
||
error: str | None = None
|
||
command_response: CommandResponse | None = None
|
||
error_code: str = ""
|
||
trace_id: str = ""
|
||
|
||
|
||
@dataclass(frozen=True)
|
||
class ReceiveInboundCmd:
|
||
"""Webhook 入站接收命令。
|
||
|
||
供 ``InboundMessagePort.receiveWebhook`` 调用,封装 webhook 路由解析
|
||
后的原始事件负载与请求头。与 ``InboundMessageCmd`` 的差异:不要求
|
||
``account_id``,账户身份解析下沉入站管道,由 webhook 适配器仅传递
|
||
渠道类型、原始事件字符串与请求头(FR-01)。
|
||
|
||
字段:
|
||
channel_type: 渠道类型。
|
||
raw_event: 原始事件负载字符串(webhook body 原文)。
|
||
headers: 请求头(含签名、时间戳等,默认空 dict)。
|
||
"""
|
||
|
||
channel_type: ChannelType
|
||
raw_event: str
|
||
headers: dict[str, str] = field(default_factory=dict)
|
||
|
||
def __post_init__(self) -> None:
|
||
"""校验必填字段非空。
|
||
|
||
``channel_type`` 不可为 ``None``,``raw_event`` 必须为非空字符串;
|
||
违规抛 ``ValidationError``,与同文件 ``InboundMessageCmd`` 风格一致
|
||
(INV-7 异常协议一致性)。
|
||
"""
|
||
if self.channel_type is None:
|
||
raise ValidationError("channel_type", "must not be None")
|
||
if not self.raw_event:
|
||
raise ValidationError("raw_event", "must be a non-empty string")
|
||
|
||
|
||
__all__ = [
|
||
"InboundMessageCmd",
|
||
"InboundResult",
|
||
"ReceiveInboundCmd",
|
||
]
|