本次提交包含多项核心改进: 1. 新增微信公众号插件拉取传输模式配置,完善manifest与manifest加载逻辑 2. 新增运行态状态机与幂等冲突错误体系,补充错误映射与领域错误导出 3. 优化出站与入站上下文,新增幂等键、流式中断标记等字段 4. 完善发件箱仓储与模型,新增失败条目查询、投递原子语义字段 5. 修复签名验证阶段异常捕获逻辑,防御性处理内置NotImplementedError 6. 新增出站预算释放方法,完善机器人循环预算管控 7. 优化出站管道格式阶段,新增消息长度校验逻辑 8. 完善出站打字指示器阶段,新增重复启动防御与状态同步 9. 重构出站标记失败阶段,按源状态分支处理状态转换 10. 新增入站幂等过滤阶段,修复入站路由阶段空指针问题 11. 优化出站恢复扫描器,修复状态机调用与聚合根重建逻辑 12. 完善微信公众号适配器,新增类型校验与异常包装 13. 修复数据库事务回滚逻辑,简化不必要的显式回滚操作
141 lines
5.7 KiB
Python
141 lines
5.7 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
|
||
from yuxi.channels.contract.dtos.streaming import StreamingCompleted
|
||
from yuxi.channels.contract.dtos.truncation import TruncationResult
|
||
from yuxi.channels.contract.errors import Error
|
||
|
||
|
||
@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
|
||
|
||
# ---- 会话定位字段 ----
|
||
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
|
||
|
||
# ---- 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
|