ForcePilot/backend/package/yuxi/channels/application/context/outbound_context.py

135 lines
5.2 KiB
Python
Raw Normal View History

"""出站管道上下文。
定义出站管道的可变局部上下文 ``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 | adminoutbox-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
# ---- 会话定位字段 ----
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`` 成功后置 Truetyping-stop 阶段据此
# 决定是否调用 ``stopTypingIndicator`` 释放输入指示资源。
typing_started: bool = False
streaming_completed: StreamingCompleted | 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