出站会话镜像重构(问题 #1520)

出站会话镜像重构(问题 #1520)

状态

  • 进行中。
  • 核心 + 插件频道路由已更新用于出站镜像。
  • 网关发送现在在省略 sessionKey 时派生目标会话。

背景

出站发送被镜像到当前智能体会话(工具会话键),而不是目标频道会话。入站路由使用频道/对等会话键,因此出站响应落在错误的会话中,并且首次联系的目标通常缺少会话条目。

目标

  • 将出站消息镜像到目标频道会话键。
  • 在出站时创建缺失的会话条目。
  • 保持线程/主题范围与入站会话键对齐。
  • 覆盖核心频道 plus 捆绑的扩展。

实现摘要

  • 新的出站会话路由助手:
    • src/infra/outbound/outbound-session.ts
    • resolveOutboundSessionRoute 使用 buildAgentSessionKey(dmScope + identityLinks)构建目标 sessionKey。
    • ensureOutboundSessionEntry 通过 recordSessionMetaFromInbound 写入最小的 MsgContext
  • runMessageAction(发送)派生目标 sessionKey 并将其传递给 executeSendAction 进行镜像。
  • message-tool 不再直接镜像;它仅从当前会话键解析 agentId。
  • 插件发送路径使用派生的 sessionKey 通过 appendAssistantMessageToSessionTranscript 进行镜像。
  • 网关发送在未提供会话键时派生目标会话键,并确保会话条目。

线程/主题处理

  • Slack:replyTo/threadId -> resolveThreadSessionKeys(后缀)。
  • Discord:threadId/replyTo -> resolveThreadSessionKeys,使用 useSuffix=false 以匹配入站(线程频道 id 已限定会话范围)。
  • Telegram:主题 ID 通过 buildTelegramGroupPeerId 映射到 chatId:topic:<id>

覆盖的扩展

  • Matrix、MS Teams、Mattermost、BlueBubbles、Nextcloud Talk、Zalo、Zalo Personal、Nostr、Tlon。
  • 注意事项:
    • Mattermost 目标现在为 DM 会话键路由剥离 @
    • Zalo Personal 对 1:1 目标使用 DM 对等类型(仅在存在 group: 时使用组)。
    • BlueBubbles 组目标剥离 chat_* 前缀以匹配入站会话键。
    • Slack 自动线程镜像不区分大小写地匹配频道 id。
    • 网关发送在镜像前小写提供的会话键。

决策

  • 网关发送会话派生:如果提供了 sessionKey,则使用它。如果省略,则从目标 + 默认智能体派生 sessionKey 并在那里镜像。
  • 会话条目创建:始终使用 recordSessionMetaFromInbound,并将 Provider/From/To/ChatType/AccountId/Originating* 与入站格式对齐。
  • 目标规范化:出站路由在可用时使用解析的目标(在 resolveChannelTarget 之后)。
  • 会话键大小写:在写入和迁移期间将会话键规范化为小写。

添加/更新的测试

  • src/infra/outbound/outbound-session.test.ts
    • Slack 线程会话键。
    • Telegram 主题会话键。
    • dmScope identityLinks 与 Discord。
  • src/agents/tools/message-tool.test.ts
    • 从会话键派生 agentId(没有 sessionKey 传递)。
  • src/gateway/server-methods/send.test.ts
    • 在省略时派生会话键并创建会话条目。

未解决的问题 / 后续工作

  • 语音呼叫插件使用自定义 voice:<phone> 会话键。这里不标准化出站映射;如果 message-tool 应该支持语音呼叫发送,请添加显式映射。
  • 确认是否有任何外部插件使用捆绑集合之外的非标准 From/To 格式。

涉及的文件

  • src/infra/outbound/outbound-session.ts
  • src/infra/outbound/outbound-send-service.ts
  • src/infra/outbound/message-action-runner.ts
  • src/agents/tools/message-tool.ts
  • src/gateway/server-methods/send.ts
  • 测试在:
    • src/infra/outbound/outbound-session.test.ts
    • src/agents/tools/message-tool.test.ts
    • src/gateway/server-methods/send.test.ts