将语义化消息展示与 channel 原生 UI 渲染器解耦的重构实现记录。规范文档见 docs/plugins/message-presentation,此文件保留为历史实现上下文。

已实现状态

  • ReplyPayload.presentation 承载语义消息 UI
  • ReplyPayload.delivery.pin 承载已发送消息的 pin 请求
  • 共享消息 actions 暴露 presentation、delivery、pin,而非 provider 原生的 components、blocks、buttons、card
  • Core 通过插件声明的出站能力渲染或自动降级 presentation
  • Discord、Slack、Telegram、Mattermost、MS Teams、Feishu 渲染器消费通用合约
  • Discord channel 控制平面代码不再导入 Carbon UI 容器

核心数据结构

type MessagePresentation = {
  tone?: "neutral" | "info" | "success" | "warning" | "danger";
  title?: string;
  blocks: MessagePresentationBlock[];
};
 
type ReplyPayloadDelivery = {
  pin?: boolean | { enabled: boolean; notify?: boolean; required?: boolean };
};

delivery.pin = true 表示 pin 第一条成功投递的消息;notify 默认 false;required 默认 false(不支持时自动降级继续投递)。

运行时能力合约

type ChannelOutboundAdapter = {
  presentationCapabilities?: ChannelPresentationCapabilities;
  renderPresentation?: (params) => ReplyPayload | null;
  deliveryCapabilities?: ChannelDeliveryCapabilities;
  pinDeliveredMessage?: (params) => Promise<void>;
};

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

各 Channel 渲染映射

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

未完成项

  • Step 12:channelData 中 provider 私有传输信封的深度清理(后续 pass)
  • Step 15:Discord 和受影响 channel 入口点的 import fanout 量化分析

相关页面