Get started
Rencana refaktor penyajian kanal
Status
Diimplementasikan untuk permukaan agen bersama, CLI, kapabilitas plugin, dan pengiriman keluar:
ReplyPayload.presentationmembawa UI pesan semantik.ReplyPayload.delivery.pinmembawa permintaan penyematan pesan yang telah dikirim.- Tindakan pesan bersama mengekspos
presentation,delivery, danpin, bukancomponents,blocks,buttons, ataucardbawaan penyedia. - Inti merender atau menurunkan kemampuan presentasi secara otomatis melalui kapabilitas keluar yang dideklarasikan plugin.
- Perender Discord, Slack, Telegram, Mattermost, MS Teams, dan Feishu menggunakan kontrak generik.
- Kode bidang kontrol kanal Discord tidak lagi mengimpor kontainer UI berbasis Carbon.
Dokumentasi kanonis kini berada di Presentasi pesan. Pertahankan rencana ini sebagai konteks implementasi historis; perbarui panduan kanonis untuk perubahan perilaku kontrak, perender, atau fallback.
Masalah
UI kanal saat ini terbagi ke dalam beberapa permukaan yang tidak kompatibel:
- Inti memiliki hook perender lintas konteks berbentuk Discord melalui
buildCrossContextComponents. channel.tsDiscord dapat mengimpor UI Carbon bawaan melaluiDiscordUiContainer, yang menarik dependensi UI runtime ke bidang kontrol plugin kanal.- Agen dan CLI mengekspos jalur pintas payload bawaan seperti
componentsDiscord,blocksSlack,buttonsTelegram atau Mattermost, sertacardTeams atau Feishu. ReplyPayload.channelDatamembawa petunjuk transportasi sekaligus amplop UI bawaan.- Model
interactivegenerik tersedia, tetapi lebih terbatas daripada tata letak yang lebih kaya yang sudah digunakan oleh Discord, Slack, Teams, Feishu, LINE, Telegram, dan Mattermost.
Hal ini membuat inti mengetahui bentuk UI bawaan, melemahkan pemuatan lambat runtime plugin, dan memberi agen terlalu banyak cara khusus penyedia untuk mengekspresikan maksud pesan yang sama.
Tujuan
- Inti menentukan presentasi semantik terbaik untuk suatu pesan berdasarkan kapabilitas yang dideklarasikan.
- Ekstensi mendeklarasikan kapabilitas dan merender presentasi semantik menjadi payload transportasi bawaan.
- UI Kontrol Web tetap terpisah dari UI obrolan bawaan.
- Payload kanal bawaan tidak diekspos melalui permukaan pesan agen bersama atau CLI.
- Fitur presentasi yang tidak didukung otomatis diturunkan ke representasi teks terbaik.
- Perilaku pengiriman seperti menyematkan pesan yang telah dikirim merupakan metadata pengiriman generik, bukan presentasi.
Bukan tujuan
- Tidak ada shim kompatibilitas mundur untuk
buildCrossContextComponents. - Tidak ada jalur pintas bawaan publik untuk
components,blocks,buttons, ataucard. - Tidak ada impor pustaka UI bawaan kanal oleh inti.
- Tidak ada celah SDK khusus penyedia untuk kanal yang dibundel.
Model target
Tambahkan bidang presentation milik inti ke ReplyPayload.
type MessagePresentationTone = "neutral" | "info" | "success" | "warning" | "danger"; type MessagePresentation = { tone?: MessagePresentationTone; 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[] }; type MessagePresentationButton = { label: string; value?: string; url?: string; style?: "primary" | "secondary" | "success" | "danger";}; type MessagePresentationOption = { label: string; value: string;};interactive menjadi subset dari presentation selama migrasi:
- Blok teks
interactivedipetakan kepresentation.blocks[].type = "text". - Blok tombol
interactivedipetakan kepresentation.blocks[].type = "buttons". - Blok pilihan
interactivedipetakan kepresentation.blocks[].type = "select".
Skema agen eksternal dan CLI kini menggunakan presentation; interactive tetap menjadi pembantu penguraian/perenderan lama internal untuk produsen balasan yang ada.
API publik yang ditujukan bagi produsen memperlakukan interactive sebagai usang. Dukungan runtime
tetap tersedia agar pembantu persetujuan yang ada dan plugin lama terus
berfungsi sementara kode baru menghasilkan presentation.
Metadata pengiriman
Tambahkan bidang delivery milik inti untuk perilaku pengiriman yang bukan UI.
type ReplyPayloadDelivery = { pin?: | boolean | { enabled: boolean; notify?: boolean; required?: boolean; };};Semantik:
delivery.pin = trueberarti menyematkan pesan pertama yang berhasil dikirim.notifysecara default bernilaifalse.requiredsecara default bernilaifalse; kanal yang tidak didukung atau kegagalan penyematan otomatis diturunkan dengan melanjutkan pengiriman.- Tindakan pesan manual
pin,unpin, danlist-pinstetap tersedia untuk pesan yang sudah ada.
Pengikatan topik ACP Telegram saat ini harus dipindahkan dari channelData.telegram.pin = true ke delivery.pin = true.
Kontrak kapabilitas runtime
Tambahkan hook perenderan presentasi dan pengiriman ke adaptor keluar runtime, bukan ke plugin kanal bidang kontrol.
type ChannelPresentationCapabilities = { supported: boolean; buttons?: boolean; selects?: boolean; context?: boolean; divider?: boolean; tones?: MessagePresentationTone[]; limits?: { actions?: { maxActions?: number; maxActionsPerRow?: number; maxRows?: number; maxLabelLength?: number; maxValueBytes?: number; supportsStyles?: boolean; supportsDisabled?: boolean; supportsLayoutHints?: boolean; }; selects?: { maxOptions?: number; maxLabelLength?: number; maxValueBytes?: number; }; text?: { maxLength?: number; encoding?: "characters" | "utf8-bytes" | "utf16-units"; markdownDialect?: "plain" | "markdown" | "html" | "slack-mrkdwn" | "discord-markdown"; supportsEdit?: boolean; }; };}; type ChannelDeliveryCapabilities = { pinSentMessage?: boolean;}; type ChannelOutboundAdapter = { presentationCapabilities?: ChannelPresentationCapabilities; renderPresentation?: (params: { payload: ReplyPayload; presentation: MessagePresentation; ctx: ChannelOutboundSendContext; }) => ReplyPayload | null; deliveryCapabilities?: ChannelDeliveryCapabilities; pinDeliveredMessage?: (params: { cfg: OpenClawConfig; accountId?: string | null; to: string; threadId?: string | number | null; messageId: string; notify: boolean; }) => Promise<void>;};Perilaku inti:
- Menentukan kanal target dan adaptor runtime.
- Meminta kapabilitas presentasi.
- Menurunkan blok yang tidak didukung dan menerapkan batas kapabilitas generik sebelum perenderan.
- Memanggil
renderPresentation. - Jika tidak ada perender, mengonversi presentasi menjadi fallback teks.
- Setelah pengiriman berhasil, memanggil
pinDeliveredMessageketikadelivery.pindiminta dan didukung.
Pemetaan kanal
Discord:
- Merender
presentationmenjadi komponen v2 dan kontainer Carbon dalam modul khusus runtime. - Mempertahankan pembantu warna aksen dalam modul ringan.
- Menghapus impor
DiscordUiContainerdari kode bidang kontrol plugin kanal.
Slack:
- Merender
presentationmenjadi Block Kit. - Menghapus input
blocksagen dan CLI.
Telegram:
- Merender teks, konteks, dan pemisah sebagai teks.
- Merender tindakan dan pilihan sebagai papan ketik inline ketika dikonfigurasi dan diizinkan untuk permukaan target.
- Menggunakan fallback teks ketika tombol inline dinonaktifkan.
- Memindahkan penyematan topik ACP ke
delivery.pin.
Mattermost:
- Merender tindakan sebagai tombol interaktif ketika dikonfigurasi.
- Merender blok lain sebagai fallback teks.
MS Teams:
- Merender
presentationmenjadi Adaptive Cards. - Mempertahankan tindakan manual sematkan/batalkan sematan/daftar sematan.
- Secara opsional mengimplementasikan
pinDeliveredMessagejika dukungan Graph dapat diandalkan untuk percakapan target.
Feishu:
- Merender
presentationmenjadi kartu interaktif. - Mempertahankan tindakan manual sematkan/batalkan sematan/daftar sematan.
- Secara opsional mengimplementasikan
pinDeliveredMessageuntuk menyematkan pesan terkirim jika perilaku API dapat diandalkan.
LINE:
- Merender
presentationmenjadi pesan Flex atau templat jika memungkinkan. - Menggunakan fallback teks untuk blok yang tidak didukung.
- Menghapus payload UI LINE dari
channelData.
Kanal sederhana atau terbatas:
- Mengonversi presentasi menjadi teks dengan pemformatan konservatif.
Langkah refaktor
- Terapkan kembali perbaikan rilis Discord yang memisahkan
ui-colors.tsdari UI berbasis Carbon dan menghapusDiscordUiContainerdariextensions/discord/src/channel.ts. - Tambahkan
presentationdandeliverykeReplyPayload, normalisasi payload keluar, ringkasan pengiriman, dan payload hook. - Tambahkan skema
MessagePresentationdan pembantu pengurai dalam subjalur SDK/runtime yang sempit. - Ganti kapabilitas pesan
buttons,cards,components, danblocksdengan kapabilitas presentasi semantik. - Tambahkan hook adaptor keluar runtime untuk perenderan presentasi dan penyematan pengiriman.
- Ganti konstruksi komponen lintas konteks dengan
buildCrossContextPresentation. - Hapus
src/infra/outbound/channel-adapters.tsdan hapusbuildCrossContextComponentsdari tipe plugin kanal. - Ubah
maybeApplyCrossContextMarkeragar melampirkanpresentation, bukan parameter bawaan. - Perbarui jalur pengiriman dispatch plugin agar hanya menggunakan presentasi semantik dan metadata pengiriman.
- Hapus parameter payload bawaan agen dan CLI:
components,blocks,buttons, dancard. - Hapus pembantu SDK yang membuat skema alat pesan bawaan, dan ganti dengan pembantu skema presentasi.
- Hapus amplop UI/bawaan dari
channelData; pertahankan hanya metadata transportasi hingga setiap bidang yang tersisa ditinjau. - Migrasikan perender Discord, Slack, Telegram, Mattermost, MS Teams, Feishu, dan LINE.
- Perbarui dokumentasi untuk CLI pesan, halaman kanal, SDK plugin, dan buku resep kapabilitas.
- Jalankan pembuatan profil sebaran impor untuk Discord dan titik masuk kanal yang terdampak.
Langkah 1-11 dan 13-14 diimplementasikan dalam refaktor ini untuk kontrak agen bersama, CLI, kapabilitas plugin, dan adaptor keluar. Langkah 12 masih memerlukan tahap pembersihan internal yang lebih mendalam untuk amplop transportasi channelData privat penyedia. Langkah 15 tetap menjadi validasi tindak lanjut jika kita menginginkan angka sebaran impor terukur di luar gerbang tipe/pengujian.
Pengujian
Tambahkan atau perbarui:
- Pengujian normalisasi presentasi.
- Pengujian penurunan otomatis presentasi untuk blok yang tidak didukung.
- Pengujian penanda lintas konteks untuk dispatch plugin dan jalur pengiriman inti.
- Pengujian matriks perender kanal untuk Discord, Slack, Telegram, Mattermost, MS Teams, Feishu, LINE, dan fallback teks.
- Pengujian skema alat pesan yang membuktikan bidang bawaan telah dihapus.
- Pengujian CLI yang membuktikan flag bawaan telah dihapus.
- Regresi kelambatan impor titik masuk Discord yang mencakup Carbon.
- Pengujian penyematan pengiriman yang mencakup Telegram dan fallback generik.
Pertanyaan terbuka
- Apakah
delivery.pinharus diimplementasikan untuk Discord, Slack, MS Teams, dan Feishu pada tahap pertama, atau hanya Telegram terlebih dahulu? - Apakah
deliverypada akhirnya harus mencakup bidang yang ada sepertireplyToId,replyToCurrent,silent, danaudioAsVoice, atau tetap berfokus pada perilaku setelah pengiriman? - Apakah presentasi harus mendukung gambar atau referensi berkas secara langsung, atau media sebaiknya tetap terpisah dari tata letak UI untuk saat ini?