2026-07-02 03:22:12 +08:00
|
|
|
|
"""AgentRun DTO。
|
|
|
|
|
|
|
|
|
|
|
|
定义 Agent 运行端口的命令与上下文值对象,包括 Agent 运行 ID、渠道格式
|
|
|
|
|
|
规格、Agent 运行上下文、渠道上下文注记与 Agent 运行命令。所有 DTO 均为
|
|
|
|
|
|
``dataclass(frozen=True)``,仅依赖标准库与契约层内部类型,用于 Agent
|
|
|
|
|
|
运行的命令传递与渠道上下文注入(FR-10 / FR-11)。集合字段使用 tuple 以
|
|
|
|
|
|
保证 frozen dataclass 的不可变语义。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
|
|
from dataclasses import dataclass
|
2026-07-03 19:18:13 +08:00
|
|
|
|
from typing import Literal
|
2026-07-02 03:22:12 +08:00
|
|
|
|
|
|
|
|
|
|
from yuxi.channels.contract.dtos.channel import ChannelType, UserIdentity
|
|
|
|
|
|
from yuxi.channels.contract.dtos.command import CommandResult
|
|
|
|
|
|
from yuxi.channels.contract.dtos.common import MessageContent, MessageFormat
|
|
|
|
|
|
from yuxi.channels.contract.dtos.mention import MentionTarget
|
2026-07-03 19:18:13 +08:00
|
|
|
|
from yuxi.channels.contract.dtos.pairing import DmDecision
|
2026-07-02 03:22:12 +08:00
|
|
|
|
from yuxi.channels.contract.dtos.tools import ChannelTool
|
|
|
|
|
|
from yuxi.channels.contract.errors import ValidationError
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
|
|
|
|
class AgentRunId:
|
|
|
|
|
|
"""Agent 运行 ID。
|
|
|
|
|
|
|
|
|
|
|
|
标识一次 Agent 运行的唯一 ID,用于关联 Agent 执行链路与出站消息。
|
|
|
|
|
|
|
|
|
|
|
|
字段:
|
|
|
|
|
|
value: Agent 运行 ID 字符串。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
value: str
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
|
|
|
|
class ChannelFormatSpec:
|
|
|
|
|
|
"""渠道格式规格。
|
|
|
|
|
|
|
|
|
|
|
|
描述渠道支持的消息格式规格,包括格式说明与支持的格式列表,用于
|
|
|
|
|
|
Agent 上下文注入以指导消息渲染。集合字段使用 tuple 以保证不可变。
|
|
|
|
|
|
|
|
|
|
|
|
字段:
|
|
|
|
|
|
format_description: 格式说明。
|
|
|
|
|
|
supported_formats: 支持的格式列表(默认空 tuple)。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
format_description: str
|
|
|
|
|
|
supported_formats: tuple[MessageFormat, ...] = ()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
|
|
|
|
class ChannelContextNote:
|
|
|
|
|
|
"""渠道上下文注记。
|
|
|
|
|
|
|
|
|
|
|
|
描述渠道上下文的注记信息,包括系统提示附录与上下文备注,用于 Agent
|
|
|
|
|
|
上下文注入以补充渠道特定信息。
|
|
|
|
|
|
|
|
|
|
|
|
字段:
|
|
|
|
|
|
system_prompt_appendix: 系统提示附录。
|
|
|
|
|
|
context_remark: 上下文备注(可选)。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
system_prompt_appendix: str
|
|
|
|
|
|
context_remark: str | None = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
|
|
|
|
class AgentRunContext:
|
|
|
|
|
|
"""Agent 运行上下文。
|
|
|
|
|
|
|
|
|
|
|
|
描述 Agent 运行的渠道上下文,包括渠道类型、账户 ID、对端 ID、群组 ID、
|
|
|
|
|
|
话题 ID、发送者 ID、渠道格式规格、渠道上下文注记、渠道工具列表、统一
|
|
|
|
|
|
用户身份、DM 安全决策与配对 ID,用于 Agent 上下文注入(FR-10)与渠道
|
|
|
|
|
|
工具注册(FR-11)。
|
|
|
|
|
|
|
|
|
|
|
|
渠道字段均为可选(默认空),以支持非渠道来源(如直接 API 调用)构造
|
|
|
|
|
|
上下文(FR-10)。``agent_id`` 由 ``AgentRunEnqueueStage`` 从
|
|
|
|
|
|
``route_binding.agent_binding`` 提取,携带路由解析出的 Agent slug,
|
|
|
|
|
|
供 ``AgentRunAdapter`` 传递给 ``create_agent_run_view`` 创建运行。
|
|
|
|
|
|
``channel_context_note`` 由 ``AgentRunEnqueueStage`` 调用插件方法
|
|
|
|
|
|
(``buildAgentContextNote``)生成,携带渠道特定的系统提示附录与上下文
|
|
|
|
|
|
备注。``channel_tools`` 由 ``AgentRunEnqueueStage`` 读取
|
|
|
|
|
|
``agent_tools_enabled`` 开关后调用插件方法(``getChannelTools``)填充,
|
|
|
|
|
|
携带渠道原生工具声明,供 Agent 运行时合并到可用工具列表(FR-11)。
|
|
|
|
|
|
``unified_identity`` 由 ``identity_resolve_stage`` 解析得到,携带
|
|
|
|
|
|
统一用户身份信息,用于 Agent 上下文注入身份维度。``dm_decision`` 与
|
|
|
|
|
|
``pairing_id`` 由 ``security_stage`` 产出,分别携带 DM 安全决策结果
|
|
|
|
|
|
与在 ``pending_pairing`` 决策下生成的配对标识,供 Agent 运行感知 DM
|
|
|
|
|
|
安全处置状态。
|
|
|
|
|
|
|
|
|
|
|
|
字段:
|
|
|
|
|
|
agent_id: Agent slug(默认空串),由路由绑定解析,用于创建 Agent 运行。
|
|
|
|
|
|
channel_type: 渠道类型(可选,默认 None)。
|
|
|
|
|
|
channel_account_id: 渠道账户 ID(默认空串)。
|
|
|
|
|
|
channel_peer_id: 对端 ID(默认空串)。
|
|
|
|
|
|
channel_group_id: 群组 ID(可选)。
|
|
|
|
|
|
channel_topic_id: 话题 ID(可选)。
|
|
|
|
|
|
channel_sender_id: 发送者 ID(可选)。
|
|
|
|
|
|
channel_format_spec: 渠道格式规格(可选)。
|
|
|
|
|
|
channel_context_note: 渠道上下文注记(可选,由插件方法生成)。
|
|
|
|
|
|
channel_tools: 渠道工具列表(默认空 tuple,由插件方法 ``getChannelTools``
|
|
|
|
|
|
生成,FR-11)。非渠道来源或开关关闭时为空 tuple,不合并任何
|
|
|
|
|
|
渠道工具。
|
|
|
|
|
|
unified_identity: 统一用户身份(可选,默认 None),来源
|
|
|
|
|
|
``identity_resolve_stage`` 解析结果,携带用户在渠道侧或外部
|
|
|
|
|
|
身份系统的身份信息,用于 Agent 上下文注入身份维度。
|
2026-07-03 19:18:13 +08:00
|
|
|
|
service_user_uid: 服务用户 UID(deprecated,默认空串,后续迭代移除)。
|
|
|
|
|
|
channel_user_identity: 渠道用户身份(可选,默认 None),
|
|
|
|
|
|
``unified_identity`` 的替代字段。
|
2026-07-02 03:22:12 +08:00
|
|
|
|
dm_decision: DM 安全决策(可选,默认 None),来源
|
|
|
|
|
|
``security_stage`` 决策结果,携带 DM 消息处置决策(allow /
|
|
|
|
|
|
deny / pending_pairing / whitelist),供 Agent 运行感知 DM
|
|
|
|
|
|
安全处置状态。
|
|
|
|
|
|
pairing_id: 配对 ID(可选,默认 None),来源 ``security_stage``
|
|
|
|
|
|
在 ``pending_pairing`` 决策下生成的配对标识,用于关联后续配对
|
|
|
|
|
|
审批流程与审计。
|
|
|
|
|
|
|
|
|
|
|
|
多 Agent 协作链路字段(默认 None 表示非协作场景):``parent_run_id``
|
|
|
|
|
|
标识父 AgentRun(委派发起方);``delegated_by_agent_id`` 标识委派发起的
|
|
|
|
|
|
Agent slug;``collaboration_id`` 关联同一协作链路的多个 AgentRun。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
agent_id: str = ""
|
|
|
|
|
|
channel_type: ChannelType | None = None
|
|
|
|
|
|
channel_account_id: str = ""
|
|
|
|
|
|
channel_peer_id: str = ""
|
|
|
|
|
|
channel_group_id: str | None = None
|
|
|
|
|
|
channel_topic_id: str | None = None
|
|
|
|
|
|
channel_sender_id: str | None = None
|
|
|
|
|
|
channel_format_spec: ChannelFormatSpec | None = None
|
|
|
|
|
|
channel_context_note: ChannelContextNote | None = None
|
|
|
|
|
|
channel_tools: tuple[ChannelTool, ...] = ()
|
2026-07-03 19:18:13 +08:00
|
|
|
|
unified_identity: UserIdentity | None = None # deprecated: 后续迭代移除,使用 channel_user_identity 替代
|
|
|
|
|
|
service_user_uid: str = ""
|
|
|
|
|
|
channel_user_identity: UserIdentity | None = None
|
2026-07-02 03:22:12 +08:00
|
|
|
|
dm_decision: DmDecision | None = None
|
|
|
|
|
|
pairing_id: str | None = None
|
|
|
|
|
|
parent_run_id: str | None = None
|
|
|
|
|
|
delegated_by_agent_id: str | None = None
|
|
|
|
|
|
collaboration_id: str | None = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
|
|
|
|
class AgentRunCmd:
|
2026-07-03 19:18:13 +08:00
|
|
|
|
"""Agent 运行命令(FR-10 / FR-15)。
|
2026-07-02 03:22:12 +08:00
|
|
|
|
|
|
|
|
|
|
由 Agent 运行端口方法引用,描述一次 Agent 运行请求,携带会话 ID、
|
|
|
|
|
|
消息内容、上下文与追踪 ID,用于驱动 Agent 执行。
|
|
|
|
|
|
|
|
|
|
|
|
字段:
|
|
|
|
|
|
conversation_id: 会话 ID。
|
|
|
|
|
|
message_content: 消息内容。
|
|
|
|
|
|
context: Agent 运行上下文(可选)。
|
|
|
|
|
|
trace_id: 追踪 ID(可选)。
|
|
|
|
|
|
source: 运行来源(如 "channel" / "api" / "admin" / "delegation"),用于 Agent
|
|
|
|
|
|
上下文注入区分来源(FR-10,可选,默认空串)。
|
|
|
|
|
|
command_result: 非静默命令执行结果(可选,FR-15),作为上下文
|
|
|
|
|
|
注入 Agent 运行,供 Agent 感知命令执行结果。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
conversation_id: str
|
|
|
|
|
|
message_content: MessageContent
|
|
|
|
|
|
context: AgentRunContext | None = None
|
|
|
|
|
|
trace_id: str | None = None
|
2026-07-03 19:18:13 +08:00
|
|
|
|
source: Literal["channel", "api", "admin", "delegation"] = ""
|
2026-07-02 03:22:12 +08:00
|
|
|
|
command_result: CommandResult | None = None
|
|
|
|
|
|
|
|
|
|
|
|
def __post_init__(self) -> None:
|
|
|
|
|
|
"""校验必填字段非空。
|
|
|
|
|
|
|
|
|
|
|
|
``conversation_id`` 与 ``message_content.text`` 必须非空,
|
|
|
|
|
|
在构造时即抛出 ``ValidationError``,adapter 不再做该校验(INV-8 /
|
|
|
|
|
|
§7.3 端口契约前置条件)。
|
|
|
|
|
|
"""
|
|
|
|
|
|
if not self.conversation_id:
|
|
|
|
|
|
raise ValidationError("conversation_id", "must not be empty")
|
|
|
|
|
|
if not self.message_content.text:
|
|
|
|
|
|
raise ValidationError("message_content", "must not be empty")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
|
|
|
|
class AgentRoutingDecision:
|
|
|
|
|
|
"""Agent 路由决策。
|
|
|
|
|
|
|
|
|
|
|
|
描述入站消息中识别到的 Agent 路由决策,由 ClassifyStage 在
|
|
|
|
|
|
mention_context.target_agent_ids 非空时构造,供下游 RouteStage
|
|
|
|
|
|
决定路由目标(多 Agent 协作)。
|
|
|
|
|
|
|
|
|
|
|
|
字段:
|
|
|
|
|
|
target_agent_id: 目标 Agent ID(必填)。
|
|
|
|
|
|
source: 触发路由的 MentionTarget(可选,默认 None)。
|
|
|
|
|
|
collaboration_id: 协作链路 ID(可选,默认 None)。
|
|
|
|
|
|
is_handoff: 是否为 Agent 移交(默认 False)。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
target_agent_id: str
|
|
|
|
|
|
source: MentionTarget | None = None
|
|
|
|
|
|
collaboration_id: str | None = None
|
|
|
|
|
|
is_handoff: bool = False
|
|
|
|
|
|
|
|
|
|
|
|
def __post_init__(self) -> None:
|
|
|
|
|
|
"""校验必填字段非空。"""
|
|
|
|
|
|
if not self.target_agent_id:
|
|
|
|
|
|
raise ValidationError("target_agent_id", "must not be empty")
|