ステータス
共有エージェント、CLI、Plugin 機能、送信配信サーフェス向けに実装済み:ReplyPayload.presentationが意味的なメッセージ UI を運びます。ReplyPayload.delivery.pinが送信済みメッセージの pin リクエストを運びます。- 共有メッセージアクションは、プロバイダー固有の
components、blocks、buttons、cardではなく、presentation、delivery、pinを公開します。 - コアは、Plugin が宣言した送信機能を通して presentation をレンダリングまたは自動劣化させます。
- Discord、Slack、Telegram、Mattermost、MS Teams、Feishu のレンダラーが汎用契約を消費します。
- Discord のチャンネル control-plane コードは、Carbon ベース UI コンテナをもう import しません。
問題
チャンネル UI は現在、互換性のない複数のサーフェスに分裂しています。- コアは
buildCrossContextComponentsを通じて Discord 形状のクロスコンテキストレンダラーフックを所有しています。 - Discord
channel.tsはDiscordUiContainerを通じてネイティブ Carbon UI を import できるため、ランタイム UI 依存がチャンネル Plugin の control plane に引き込まれます。 - エージェントと CLI は、Discord の
components、Slack のblocks、Telegram や Mattermost のbuttons、Teams や Feishu のcardのようなネイティブペイロードの escape hatch を公開しています。 ReplyPayload.channelDataは transport hint とネイティブ UI envelope の両方を運びます。- 汎用
interactiveモデルは存在しますが、Discord、Slack、Teams、Feishu、LINE、Telegram、Mattermost ですでに使われているより豊かなレイアウトよりも狭いです。
目標
- コアが、宣言された機能からメッセージに最適な意味的 presentation を決定する。
- Extension が機能を宣言し、意味的 presentation をネイティブ transport payload にレンダリングする。
- Web Control UI は、チャットのネイティブ UI とは別のままにする。
- ネイティブチャンネルペイロードは、共有エージェントや CLI メッセージサーフェスから公開しない。
- サポートされない presentation 機能は、自動的に最適なテキスト表現へ劣化する。
- 送信済みメッセージの pin のような配信動作は、presentation ではなく汎用の配信メタデータである。
非目標
buildCrossContextComponents向けの後方互換 shim は作らない。components、blocks、buttons、card向けの公開ネイティブ escape hatch は作らない。- コアからチャンネル固有 UI ライブラリを import しない。
- バンドル済みチャンネル向けのプロバイダー固有 SDK seam は作らない。
ターゲットモデル
コア所有のpresentation フィールドを ReplyPayload に追加します。
interactive は presentation のサブセットになります。
interactivetext block はpresentation.blocks[].type = "text"にマップされます。interactivebuttons block はpresentation.blocks[].type = "buttons"にマップされます。interactiveselect block はpresentation.blocks[].type = "select"にマップされます。
presentation を使います。interactive は既存 reply producer 向けの内部 legacy parser/rendering helper のままです。
配信メタデータ
UI ではない送信動作のために、コア所有のdelivery フィールドを追加します。
delivery.pin = trueは、最初に正常配信されたメッセージを pin することを意味します。notifyのデフォルトはfalse。requiredのデフォルトはfalse。未対応チャンネルや pin 失敗は、配信を続行することで自動劣化します。- 既存メッセージ向けの手動
pin、unpin、list-pinsメッセージアクションは残します。
channelData.telegram.pin = true から delivery.pin = true へ移行すべきです。
ランタイム機能契約
presentation と delivery の render hook を、control-plane チャンネル Plugin ではなく runtime outbound adapter に追加します。- 対象チャンネルと runtime adapter を解決する。
- presentation capabilities を問い合わせる。
- サポートされない block をレンダリング前に劣化させる。
renderPresentationを呼び出す。- renderer が存在しない場合は、presentation をテキストフォールバックへ変換する。
- 配信成功後、
delivery.pinが要求されサポートされている場合はpinDeliveredMessageを呼び出す。
チャンネルマッピング
Discord:presentationを runtime-only module 内で components v2 と Carbon container にレンダリングする。- accent color helper は軽量 module に残す。
- チャンネル Plugin control-plane コードから
DiscordUiContainerの import を除去する。
presentationを Block Kit にレンダリングする。- エージェントと CLI の
blocks入力を削除する。
- text、context、divider をテキストとしてレンダリングする。
- actions と select は、対象サーフェスで設定され許可されている場合、inline keyboard としてレンダリングする。
- inline button が無効な場合はテキストフォールバックを使う。
- ACP topic pinning は
delivery.pinへ移す。
- actions は設定されていれば interactive button としてレンダリングする。
- その他の block はテキストフォールバックとしてレンダリングする。
presentationを Adaptive Cards にレンダリングする。- 手動の pin/unpin/list-pins アクションは維持する。
- 対象 conversation に対して Graph サポートが信頼できるなら、
pinDeliveredMessageを任意実装する。
presentationを interactive cards にレンダリングする。- 手動の pin/unpin/list-pins アクションは維持する。
- API 挙動が信頼できるなら、送信済みメッセージ pinning 用に
pinDeliveredMessageを任意実装する。
presentationを可能な限り Flex または template message にレンダリングする。- サポートされない block はテキストにフォールバックする。
channelDataから LINE UI payload を削除する。
- 保守的な書式で presentation をテキストへ変換する。
リファクタ手順
ui-colors.tsを Carbon ベース UI から分離し、extensions/discord/src/channel.tsからDiscordUiContainerを除去する Discord リリース修正を再適用する。presentationとdeliveryをReplyPayload、送信 payload 正規化、配信サマリー、hook payload に追加する。- 狭い SDK/runtime サブパスに
MessagePresentationschema と parser helper を追加する。 - メッセージ機能の
buttons、cards、components、blocksを意味的 presentation capabilities に置き換える。 - presentation render と delivery pinning のための runtime outbound adapter hook を追加する。
- クロスコンテキスト component 構築を
buildCrossContextPresentationに置き換える。 src/infra/outbound/channel-adapters.tsを削除し、チャンネル Plugin type からbuildCrossContextComponentsを除去する。maybeApplyCrossContextMarkerがネイティブ params ではなくpresentationを付与するよう変更する。- Plugin-dispatch の send path を、意味的 presentation と delivery metadata だけを消費するよう更新する。
- エージェントと CLI のネイティブ payload params:
components、blocks、buttons、cardを削除する。 - ネイティブ message-tool schema を作る SDK helper を削除し、presentation schema helper に置き換える。
channelDataから UI/native envelope を除去する。残る各フィールドをレビューするまでは transport metadata のみを維持する。- Discord、Slack、Telegram、Mattermost、MS Teams、Feishu、LINE のレンダラーを移行する。
- message CLI、channel page、Plugin SDK、capability cookbook のドキュメントを更新する。
- Discord と影響を受けるチャンネル entrypoint の import fanout profiling を実行する。
channelData transport envelope に対する、より深い内部クリーンアップパスとして残っています。手順 15 は、型/テストゲートを超えた定量的な import-fanout 数値が欲しい場合のフォローアップ検証として残っています。
テスト
追加または更新するもの:- Presentation 正規化テスト。
- サポートされない block に対する presentation 自動劣化テスト。
- Plugin dispatch とコア配信経路向けのクロスコンテキスト marker テスト。
- Discord、Slack、Telegram、Mattermost、MS Teams、Feishu、LINE、およびテキストフォールバック向けのチャンネル render matrix テスト。
- ネイティブフィールドが消えたことを証明するメッセージツール schema テスト。
- ネイティブフラグが消えたことを証明する CLI テスト。
- Carbon を対象にした Discord entrypoint import-laziness 回帰テスト。
- Telegram と汎用フォールバックをカバーする delivery pin テスト。
未解決の質問
delivery.pinは最初の段階で Discord、Slack、MS Teams、Feishu にも実装すべきか、それともまず Telegram のみか?deliveryは将来的にreplyToId、replyToCurrent、silent、audioAsVoiceのような既存フィールドも吸収すべきか、それとも post-send 動作に集中したままにすべきか?- Presentation は画像やファイル参照を直接サポートすべきか、それとも今のところメディアは UI レイアウトとは分離したままにすべきか?