将语义化消息展示与各 channel 原生 UI 渲染器解耦。该计划已在共享 agent、CLI、插件能力和出站投递面实现,此文件保留为历史实现上下文。

问题背景

原有 channel UI 分散在多个不兼容的面:

  • Core 通过 buildCrossContextComponents 持有 Discord 形状的跨上下文渲染钩子
  • Discord channel.ts 可导入原生 Carbon UI(DiscordUiContainer),将运行时 UI 依赖拉入 channel 插件控制平面
  • Agent 和 CLI 暴露原生 payload 逃生舱(Discord components、Slack blocks、Telegram buttons、Teams/Feishu card)
  • ReplyPayload.channelData 同时承载传输提示和原生 UI 信封

这导致 core 感知原生 UI 形状,削弱插件运行时懒加载,给 agent 提供了过多 provider 特定的表达方式。

目标模型

在 ReplyPayload 中添加 core 拥有的 presentation 字段:

type MessagePresentation = {
  tone?: "neutral" | "info" | "success" | "warning" | "danger";
  title?: string;
  blocks: MessagePresentationBlock[];
};
 
type MessagePresentationBlock =
  | { type: "text"; text: string }
  | { type: "context"; text: string }
  | { type: "divider" }
  | { type: "buttons"; buttons: MessagePresentationButton[] }
  | { type: "select"; placeholder?: string; options: MessagePresentationOption[] };

delivery 字段承载发送行为(非 UI):

type ReplyPayloadDelivery = {
  pin?: boolean | { enabled: boolean; notify?: boolean; required?: boolean };
};

运行时能力合约

展示和投递渲染钩子添加到运行时出站适配器,而非控制平面 channel 插件:

  • presentationCapabilities:声明支持的 block 类型
  • renderPresentation:将语义展示渲染为原生 transport payload
  • deliveryCapabilities:声明是否支持 pin 已发送消息
  • pinDeliveredMessage:执行 pin 操作

Core 行为:解析目标 channel → 查询展示能力 → 降级不支持的 block → 调用 renderPresentation → 无渲染器时转为文本 fallback → 发送成功后执行 pin。

各 Channel 映射

Channel渲染方式
Discordcomponents v2 + Carbon containers(仅运行时模块)
SlackBlock Kit
Telegram文本/context/divider 为文本,actions/select 为 inline keyboard
Mattermost交互按钮(已配置时)
MS TeamsAdaptive Cards
Feishu交互卡片
LINEFlex 或模板消息,不支持时降级为文本

已实现内容

  • ReplyPayload.presentation 承载语义消息 UI
  • ReplyPayload.delivery.pin 承载 pin 请求
  • Discord、Slack、Telegram、Mattermost、MS Teams、Feishu 渲染器消费通用合约
  • Discord channel 控制平面代码不再导入 Carbon UI 容器

相关页面