"""入站管道上下文。 定义入站管道的可变局部上下文 ``InboundContext``,携带请求从 receive 到 reply 各阶段产生的状态。上下文为 ``@dataclass``(不 frozen),阶段直接修改字段以 推进管道状态。 """ from __future__ import annotations from dataclasses import dataclass from typing import TYPE_CHECKING, Any from yuxi.channels.contract.dtos.ack import AckPolicy from yuxi.channels.contract.dtos.agent_run import ( AgentRoutingDecision, ChannelContextNote, ChannelFormatSpec, ) from yuxi.channels.contract.dtos.channel import ( ChannelSession, ChannelType, UserIdentity, ) from yuxi.channels.contract.dtos.command import CommandResult from yuxi.channels.contract.dtos.common import ( MessageContent, RawEvent, ) from yuxi.channels.contract.dtos.mention import ( InboundMentionFact, MentionContext, MentionDecision, ) from yuxi.channels.contract.dtos.pairing import DmDecision from yuxi.channels.contract.dtos.route import RouteBinding from yuxi.channels.contract.dtos.service_account import ServiceAccount from yuxi.channels.contract.dtos.status import EventType from yuxi.channels.contract.errors import Error if TYPE_CHECKING: from yuxi.channels.contract.ports.driven.transaction_port import TransactionContext @dataclass class InboundContext: """入站管道可变局部上下文。 携带入站请求从 receive 到 reply 各阶段产生的状态,阶段按顺序填充字段。 字段按阶段分组,便于追溯状态来源。 事务边界(§10.1):``tx`` 字段由 ``InboundMessageService`` 在管道 执行前通过 ``TransactionPort.begin()`` 开启,session-resolve 阶段的 ``resolveConversation`` 与 ``saveChannelSession`` 写操作共享此事务 上下文,确保会话解析与渠道会话保存原子提交。 命名等价说明(6-P2-01):``trace_id`` 与 Agent 层 ``turn_id`` 为同一 概念的不同命名,均标识一次请求/会话回合的链路追踪 ID。本上下文 ``trace_id`` 字段即等价于 ``turn_id``。 """ # ---- 基础字段(receive 阶段) ---- trace_id: str request_id: str channel_type: ChannelType account_id: str raw_event: RawEvent # 运行来源(如 "channel" / "admin"),用于 Agent 上下文注入区分来源(FR-10) source: str = "channel" # 渠道插件清单 ID,由 receive 阶段填充 plugin_id: str | None = None # ---- signature-verify 阶段字段 ---- # Webhook 签名是否已验证通过,由 signature-verify 阶段填充。 # 适配器未实现验签时保持 False(跳过验签),验签通过时置 True。 signature_verified: bool = False # ---- 事务上下文(由 InboundMessageService 注入,session_resolve_stage 共享)---- tx: TransactionContext | None = None # ---- classify 阶段字段 ---- event_type: EventType | None = None ref_channel_msg_id: str | None = None status_payload: dict[str, Any] | None = None peer_id: str | None = None chat_type: str | None = None # 话题 ID(FR-10),由 classify 阶段从原始事件提取,不支持话题的渠道为 None topic_id: str | None = None message_content: MessageContent | None = None mention_context: MentionContext | None = None mention_fact: InboundMentionFact | None = None # Agent 路由决策(FR-AgentCollab),由 classify 阶段从 mention_context # 构造,供下游 RouteStage 决定路由目标。None 表示无 Agent 提及。 agent_routing_decision: AgentRoutingDecision | None = None # ---- security 阶段字段 ---- dm_decision: DmDecision | None = None pairing_id: str | None = None # 是否为管理员用户(FR-15),由 security 阶段根据账户级 admin_users 配置 # 判定,供 command-check 阶段校验 ADMIN 权限命令(/allowlist、/approve 等)。 is_admin: bool = False # 是否为渠道访客 channel_guest 身份,由 identity-resolve 阶段判定,标识当前 # 请求来自未绑定服务账号的访客,供下游阶段决策鉴权与降级策略。 is_guest: bool = False # ---- command-check 阶段字段 ---- command: CommandResult | None = None is_silent: bool = False mention_decision: MentionDecision | None = None # ---- identity-resolve 阶段字段 ---- unified_identity: UserIdentity | None = None # 渠道账户绑定的服务账号,由 service-account-resolve 阶段填充,携带服务账号 # uid 作为 Agent 执行的鉴权主体,满足会话归属与用户存在性校验。 service_account: ServiceAccount | None = None # ---- session-resolve 阶段字段 ---- channel_session: ChannelSession | None = None conversation_id: str | None = None # ---- fence 代际字段(agent-run-enqueue 阶段写入,FR-23) ---- fence_generation: int | None = None # ---- route 阶段字段 ---- route_binding: RouteBinding | None = None current_uid: str | None = None # ---- agent-run-enqueue 阶段字段 ---- agent_run_id: str | None = None # ---- reply 阶段字段(FR-24 分阶段 ACK) ---- # ACK 决策结果:ack | nack | pending ack_decision: str = "pending" # 解析后的 ACK 策略(reply 阶段解析:插件声明 → 配置 → 默认值) ack_policy: AckPolicy | None = None # 幂等键(基于渠道类型 + 账户 ID + 原始事件负载哈希,跨重试稳定) ack_idempotency_key: str | None = None # 是否已 ACK(幂等检查标记,避免重复 ACK 副作用) acked: bool = False # 是否已 NACK(与 ACK 互斥,避免 ACK/NACK 同时生效) nacked: bool = False # ---- 出站投递错误字段 ---- # 出站消息投递失败时的错误信息(FR-24)。reply 阶段向渠道侧投递出站 # 消息失败时填充,用于上层决策重试或降级;投递成功或未触发投递时为 None。 outbound_error: str | None = None # ---- 降级标志字段 ---- degraded: bool = False degraded_reason: Error | None = None # ---- 可观测性字段(BP-10) ---- # 渠道格式规范(包含 supported_formats),由上下文富化逻辑写入,供管道 # 日志(_logStageExecution)输出可观测性信息。 channel_format_spec: ChannelFormatSpec | None = None # 渠道上下文注记(来自 channel_context_provider),由上下文富化逻辑写入, # 供管道日志(_logStageExecution)输出可观测性信息。 channel_context_note: ChannelContextNote | None = None