本次提交包含多类代码优化: 1. 修复多处单行代码换行格式,统一代码排版 2. 为外部系统模块新增快捷菜单配置 3. 优化前端API请求参数命名一致性 4. 补充媒体下载超限错误码与领域异常类 5. 完善仓储层更新逻辑,支持显式清空字段 6. 优化部分测试用例与工具函数代码结构 7. 为微信插件白名单缓存增加过期时间
180 lines
7.5 KiB
Python
180 lines
7.5 KiB
Python
"""出站管道上下文。
|
||
|
||
定义出站管道的可变局部上下文 ``OutboundContext``,携带请求从 sse-consume 到
|
||
deliver 各阶段产生的状态。上下文为 ``@dataclass``(不 frozen),阶段直接
|
||
修改字段以推进管道状态。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from dataclasses import dataclass, field
|
||
from typing import Any
|
||
|
||
from yuxi.channels.contract.dtos.capability import (
|
||
CapabilityResult,
|
||
ChannelCapabilities,
|
||
)
|
||
from yuxi.channels.contract.dtos.channel import ChannelType
|
||
from yuxi.channels.contract.dtos.common import Attachment
|
||
from yuxi.channels.contract.dtos.fence import FenceGeneration
|
||
from yuxi.channels.contract.dtos.outbound import (
|
||
FinalMessage,
|
||
FormattedMessage,
|
||
OutboundPayload,
|
||
RichMessage,
|
||
TrustedMessage,
|
||
)
|
||
from yuxi.channels.contract.dtos.outbox import MultiPartReceipt, OutboxEntry, OutboxId
|
||
from yuxi.channels.contract.dtos.streaming import StreamingCompleted
|
||
from yuxi.channels.contract.dtos.truncation import TruncationResult
|
||
from yuxi.channels.contract.errors import Error
|
||
|
||
|
||
@dataclass(frozen=True)
|
||
class FanOutTarget:
|
||
"""fan-out 扇出目标(M13)。
|
||
|
||
描述一次 fan-out 投递中单个目标的渠道定位信息,由上游阶段(如
|
||
``AdminMessageService``)按 target 列表解析后填充到
|
||
``OutboundContext.fan_out_entries``,供 outbox-persist 阶段批量构造
|
||
``SaveOutboxEntryCmd`` 在单事务内保存。
|
||
|
||
字段:
|
||
channel_type: 目标渠道类型。
|
||
account_id: 目标渠道账户业务 ID。
|
||
channel_session_id: 目标渠道会话 ID(可选)。
|
||
"""
|
||
|
||
channel_type: ChannelType
|
||
account_id: str
|
||
channel_session_id: str | None = None
|
||
|
||
|
||
@dataclass
|
||
class OutboundContext:
|
||
"""出站管道可变局部上下文。
|
||
|
||
携带出站请求从 sse-consume 到 deliver 各阶段产生的状态,阶段按顺序填充
|
||
字段。字段按阶段分组,便于追溯状态来源。
|
||
"""
|
||
|
||
# ---- 基础字段 ----
|
||
trace_id: str
|
||
request_id: str
|
||
channel_type: ChannelType
|
||
account_id: str
|
||
channel_session_id: str
|
||
agent_run_id: str
|
||
delivery_mode: str
|
||
trusted_sender_id: str
|
||
is_owner: bool = False
|
||
# 消息发送者角色(user | assistant | admin),outbox-persist 阶段据此
|
||
# 设置 Message 表 role 字段,管理员消息为 "admin"(FR-19)
|
||
sender_role: str = "assistant"
|
||
# 持久化策略(required | best_effort | none),由上游阶段(如
|
||
# AdminMessageService)按消息类型设置,outbox-persist 阶段据此决定
|
||
# 持久化行为(FR-22)。为 None 时回退到配置 durability_policy_default。
|
||
durability_policy: str | None = None
|
||
# 出站投递幂等键(可选)。跨重试稳定,供 deliver 阶段调用适配器
|
||
# ``sendMessage`` / ``sendMessageContinuation`` 时传入,实现渠道侧去重。
|
||
idempotency_key: str | None = None
|
||
# fan-out 批次 ID(可选)。标识同一次 fan-out 产生的一组出站请求,
|
||
# 由 AdminMessageService 在 fan-out 时填充,outbox-persist 阶段据此
|
||
# 写入 OutboxEntry.fan_out_batch_id,供 M8 outbox 重试保序使用。
|
||
fan_out_batch_id: str | None = None
|
||
# fan-out 批次内序号(可选)。标识同批次内的投递顺序,由
|
||
# AdminMessageService 在 fan-out 时按目标遍历顺序填充,供 M8 重试保序
|
||
# 按序号恢复原始顺序。
|
||
fan_out_seq: int | None = None
|
||
|
||
# ---- 会话定位字段 ----
|
||
conversation_id: str | None = None
|
||
peer_id: str | None = None
|
||
message_id: str | None = None
|
||
channel_capabilities: ChannelCapabilities | None = None
|
||
|
||
# ---- trusted-inject 阶段请求上下文字段(FR-25) ----
|
||
# gateway_client_info 与 is_dry_run 由上游从实际请求上下文提取后填充,
|
||
# trusted-inject 阶段透传给 TrustedMessageGuard.buildContext,避免领域
|
||
# 服务硬编码(FR-25)。
|
||
gateway_client_info: dict[str, Any] | None = None
|
||
is_dry_run: bool = False
|
||
|
||
# ---- sse-consume 阶段字段 ----
|
||
stream_chunks: list[str] = field(default_factory=list)
|
||
chunk_results: list[Any] = field(default_factory=list)
|
||
|
||
# ---- load-build 阶段输入字段 ----
|
||
# 富消息源数据(FR-08),由上游阶段(如 AdminMessageService)填充,
|
||
# load-build 阶段将其包装为 RichMessageFields 装入 OutboundPayload。
|
||
rich_message: RichMessage | None = None
|
||
# 附件列表(FR-19),由上游阶段(如 AdminMessageService)填充,
|
||
# load-build / format 阶段据此装入出站负载供适配器渲染。
|
||
attachments: tuple[Attachment, ...] = ()
|
||
|
||
# ---- fence-check 阶段输入字段(FR-23,由入站管道捕获并透传) ----
|
||
fence_inbound_generation: int | None = None
|
||
|
||
# ---- fence-check 阶段字段 ----
|
||
fence_generation: FenceGeneration | None = None
|
||
fence_visible: bool = False
|
||
# 待标记可见的 fence 代际(可选)。由上游阶段填充,fence-check 阶段据此
|
||
# 将指定代际标记为可见,用于降级投递等场景的代际可见性控制。
|
||
generation_to_mark_visible: int | None = None
|
||
|
||
# ---- load-build 阶段字段 ----
|
||
outbound_payload: OutboundPayload | None = None
|
||
|
||
# ---- capability-verify 阶段字段 ----
|
||
capability_result: CapabilityResult | None = None
|
||
# 富消息能力校验结果(FR-08 增强),声明+证明双层校验。
|
||
rich_message_capability_result: CapabilityResult | None = None
|
||
|
||
# ---- format 阶段字段 ----
|
||
formatted_message: FormattedMessage | None = None
|
||
|
||
# ---- trusted-inject 阶段字段 ----
|
||
trusted_message: TrustedMessage | None = None
|
||
|
||
# ---- prefix 阶段字段 ----
|
||
final_message: FinalMessage | None = None
|
||
|
||
# ---- streaming 阶段字段 ----
|
||
streaming_started: bool = False
|
||
# 输入指示是否已启动(FR-13)。typing-indicator 阶段调用
|
||
# ``startTypingIndicator`` 成功后置 True,typing-stop 阶段据此
|
||
# 决定是否调用 ``stopTypingIndicator`` 释放输入指示资源。
|
||
typing_started: bool = False
|
||
streaming_completed: StreamingCompleted | None = None
|
||
# 流式中断时分片序号(可选)。流式投递被中断时记录已发送分片序号,
|
||
# 供 ``sendMessageContinuation`` 续发定位续发起点。
|
||
stream_aborted_at_chunk: int | None = None
|
||
|
||
# ---- truncation-check 阶段字段 ----
|
||
truncation_detected: bool = False
|
||
truncation_info: TruncationResult | None = None
|
||
|
||
# ---- outbox-persist 阶段字段 ----
|
||
outbox_entry: OutboxEntry | None = None
|
||
|
||
# ---- deliver 阶段字段 ----
|
||
delivered: bool = False
|
||
channel_msg_id: str | None = None
|
||
# 多部分消息回执列表(FR-22 多部分模型)。适配器实现 ``sendMessageMultiPart``
|
||
# 时由 deliver 阶段填充,``channel_msg_id`` 取首分片 ``platform_msg_id``。
|
||
# 单分片投递(``sendMessage``)时为 None。部分失败时仅含成功分片,由
|
||
# 下游阶段据长度判定部分失败。
|
||
multi_part_receipts: list[MultiPartReceipt] | None = None
|
||
|
||
# ---- 降级标志字段 ----
|
||
degraded: bool = False
|
||
degraded_reason: Error | None = None
|
||
|
||
# ---- fan-out 扇出字段(M13)----
|
||
# 由上游阶段(如 AdminMessageService)填充,outbox-persist 阶段据此
|
||
# 走批量保存路径(单事务保存所有 OutboxEntry)。is_fan_out 为 False
|
||
# 或 fan_out_entries 为 None 时走原单条保存路径。
|
||
is_fan_out: bool = False
|
||
fan_out_entries: list[FanOutTarget] | None = None
|
||
fan_out_outbox_ids: list[OutboxId] | None = None
|