- Primitive inti seharusnya terima dan kirim, bukan balas.
- Balasan hanyalah relasi pada pesan outbound.
- Turn adalah kemudahan pemrosesan inbound, bukan pemilik pengiriman.
- Pengiriman harus berbasis konteks:
begin, render, pratinjau atau stream, kirim final, commit, gagal. - Penerimaan juga harus berbasis konteks: normalisasi, dedupe, route, catat, dispatch, ack platform, gagal.
- SDK Plugin publik harus diringkas menjadi satu surface channel-outbound kecil.
Masalah
Stack channel saat ini tumbuh dari beberapa kebutuhan lokal yang valid:- Adapter inbound sederhana menggunakan
runtime.channel.inbound.run. - Adapter kaya menggunakan
runtime.channel.inbound.runPreparedReply. - Helper legacy menggunakan
dispatchInboundReplyWithBase,recordInboundSessionAndDispatchReply, helper payload balasan, chunking balasan, referensi balasan, dan helper runtime outbound. - Streaming pratinjau berada di dispatcher khusus channel.
- Durability pengiriman final sedang ditambahkan di sekitar path payload balasan yang ada.
Sasaran
- Satu lifecycle inti untuk semua path terima dan kirim pesan channel.
- Pengiriman final yang durable secara default dalam lifecycle pesan baru setelah adapter mendeklarasikan perilaku replay-safe.
- Semantik pratinjau, edit, stream, finalisasi, retry, pemulihan, dan receipt bersama.
- Surface SDK Plugin kecil yang dapat dipelajari dan dipelihara Plugin pihak ketiga.
- Kompatibilitas untuk pemanggil kompatibilitas balasan inbound yang ada selama migrasi.
- Titik ekstensi yang jelas untuk kapabilitas channel baru.
- Tidak ada cabang khusus platform di inti.
- Tidak ada pesan channel token-delta. Streaming channel tetap berupa pratinjau pesan, edit, append, atau pengiriman blok yang selesai.
- Metadata asal OpenClaw terstruktur untuk output operasional/sistem agar kegagalan Gateway yang terlihat tidak masuk kembali ke ruang bersama yang mengaktifkan bot sebagai prompt baru.
Bukan sasaran
- Jangan paksa setiap channel yang ada ke pengiriman pesan durable pada fase pertama.
- Jangan paksa setiap channel ke perilaku transport native yang sama.
- Jangan ajarkan inti tentang topik Telegram, stream native Slack, redaksi Matrix, kartu Feishu, suara QQ, atau aktivitas Teams.
- Jangan publikasikan semua helper migrasi internal sebagai API SDK stabil.
- Jangan buat retry me-replay operasi platform non-idempoten yang sudah selesai.
Model referensi
Vercel Chat memiliki model mental publik yang baik:ChatThreadChannelMessage- metode adapter seperti
postMessage,editMessage,deleteMessage,stream,startTyping, dan pengambilan riwayat - adapter state untuk dedupe, lock, antrean, dan persistensi
- Intent pengiriman outbound yang durable sebelum panggilan transport langsung.
- Konteks pengiriman eksplisit dengan begin, commit, dan fail.
- Konteks penerimaan yang mengetahui kebijakan ack platform.
- Receipt yang bertahan melewati restart dan dapat menggerakkan edit, hapus, pemulihan, dan penekanan duplikat.
- SDK publik yang lebih kecil. Plugin bundled dapat menggunakan helper runtime internal, tetapi Plugin pihak ketiga sebaiknya melihat satu API pesan yang koheren.
- Perilaku khusus agen: sesi, transkrip, streaming blok, progres tool, approval, direktif media, balasan senyap, dan riwayat mention grup.
thread.post() tidak cukup untuk OpenClaw. Promise itu menyembunyikan
batas transaksi yang memutuskan apakah pengiriman dapat dipulihkan.
Model inti
Domain baru sebaiknya berada di bawah namespace inti internal sepertisrc/channels/message/*.
Domain ini memiliki empat konsep:
receive memiliki lifecycle inbound.
send memiliki lifecycle outbound.
live memiliki state pratinjau, edit, progres, dan stream.
state memiliki penyimpanan intent durable, receipt, idempotensi, pemulihan, lock, dan
dedupe.
Istilah pesan
Pesan
Pesan yang dinormalisasi bersifat netral platform:Target
Target menjelaskan tempat pesan berada:Relasi
Balasan adalah relasi, bukan root API:Asal
Asal menjelaskan siapa yang menghasilkan pesan dan bagaimana OpenClaw harus memperlakukan echo dari pesan itu. Ini terpisah dari relasi: sebuah pesan dapat berupa balasan kepada pengguna dan tetap merupakan output operasional yang berasal dari OpenClaw.allowBots diaktifkan.
Receipt
Receipt adalah first-class:Konteks penerimaan
Penerimaan sebaiknya bukan panggilan helper telanjang. Inti membutuhkan konteks yang mengetahui dedupe, routing, pencatatan sesi, dan kebijakan ack platform.- Ack transport: memberi tahu Webhook atau socket platform bahwa OpenClaw menerima envelope event. Beberapa platform memerlukan ini sebelum dispatch.
- Ack offset polling: memajukan cursor agar event yang sama tidak diambil lagi. Ini tidak boleh maju melewati pekerjaan yang tidak dapat dipulihkan.
- Ack record inbound: mengonfirmasi OpenClaw mempersistensikan metadata inbound yang cukup untuk dedupe dan me-route redelivery.
- Receipt yang terlihat pengguna: perilaku baca/status/typing opsional; tidak pernah menjadi batas durability.
ReceiveAckPolicy hanya mengontrol acknowledgment transport atau polling. Ini tidak boleh
digunakan kembali untuk read receipt atau reaksi status.
Sebelum otorisasi bot, penerimaan harus menerapkan kebijakan echo OpenClaw bersama
ketika channel dapat mendecode metadata asal pesan:
allowBots normal.
Kebijakan ack bersifat eksplisit:
getUpdates upstream Telegram masih dikontrol oleh
library polling, jadi langkah lebih dalam yang tersisa adalah sumber polling yang sepenuhnya durable
jika kita membutuhkan redelivery tingkat platform di luar watermark restart
OpenClaw. Platform Webhook mungkin membutuhkan ack HTTP langsung, tetapi tetap membutuhkan
dedupe inbound dan intent pengiriman outbound yang durable karena Webhook dapat redeliver.
Konteks pengiriman
Pengiriman juga berbasis konteks:unknown_after_send, bukan diputar ulang
secara membuta. Channel tanpa rekonsiliasi boleh memilih pemutaran ulang at-least-once
hanya jika pesan terlihat duplikat adalah tradeoff yang dapat diterima dan
terdokumentasi untuk channel dan relasi tersebut. Bridge rekonsiliasi SDK saat ini
mengharuskan adapter mendeklarasikan reconcileUnknownSend, lalu meminta
durableFinal.reconcileUnknownSend untuk mengklasifikasikan entri tak dikenal sebagai
sent, not_sent, atau unresolved; hanya not_sent yang mengizinkan pemutaran ulang,
dan entri yang belum terselesaikan tetap terminal atau hanya mencoba ulang pemeriksaan
rekonsiliasi.
Kebijakan durabilitas harus eksplisit:
required berarti core harus gagal tertutup ketika tidak dapat menulis intent durable.
best_effort dapat meneruskan ketika persistensi tidak tersedia. disabled mempertahankan
perilaku kirim langsung lama. Selama migrasi, wrapper lama dan helper kompatibilitas
publik default ke disabled; semuanya tidak boleh menyimpulkan required dari fakta
bahwa sebuah channel memiliki adapter outbound generik.
Konteks kirim juga memiliki efek pascakirim lokal channel. Migrasi tidak aman
jika pengiriman durable melewati perilaku lokal yang sebelumnya terpasang pada
jalur kirim langsung channel. Contohnya mencakup cache penekanan self-echo,
penanda partisipasi thread, anchor edit native, rendering tanda tangan model,
dan penjaga duplikat khusus platform. Efek tersebut harus dipindahkan ke
adapter kirim, adapter render, atau hook konteks-kirim bernama sebelum channel
tersebut dapat mengaktifkan pengiriman final generik durable.
Helper kirim harus mengembalikan tanda terima sepenuhnya ke pemanggilnya. Wrapper
durable tidak dapat menelan id pesan atau mengganti hasil pengiriman channel dengan
undefined; dispatcher buffered menggunakan id tersebut untuk anchor thread, edit
berikutnya, finalisasi pratinjau, dan penekanan duplikat.
Pengiriman fallback beroperasi pada batch, bukan payload tunggal. Penulisan ulang
silent-reply, fallback media, fallback kartu, dan proyeksi chunk semuanya dapat
menghasilkan lebih dari satu pesan yang dapat dikirim, jadi konteks kirim harus
mengirim seluruh batch yang diproyeksikan atau mendokumentasikan secara eksplisit
mengapa hanya satu payload yang valid.
unknown_after_send sampai adapter
merekonsiliasinya.
Konteks live
Perilaku pratinjau, edit, progres, dan stream harus menjadi satu lifecycle opt-in.- Telegram mengirim plus mengedit pratinjau, dengan final segar setelah usia pratinjau usang.
- Discord mengirim plus mengedit pratinjau, membatalkan pada media/error/balasan eksplisit.
- Slack stream native atau pratinjau draf bergantung pada bentuk thread.
- Finalisasi posting draf Mattermost.
- Finalisasi event draf Matrix atau redaksi saat tidak cocok.
- Stream progres native Teams.
- Stream QQ Bot atau fallback terakumulasi.
Permukaan adapter
Target SDK publik harus berupa satu subpath:origin.decode mengembalikan metadata asal OpenClaw. Adapter terima
memasok fakta platform seperti penulis bot dan bentuk room; core memiliki keputusan
drop dan pengurutan sehingga channel tidak mengimplementasikan ulang filter teks.
Adapter asal:
MessageOrigin. Channel hanya menerjemahkannya ke dan dari metadata
transport native. Slack memetakannya ke chat.postMessage({ metadata }) dan
message.metadata inbound; Matrix dapat memetakannya ke konten event tambahan; channel
tanpa metadata native dapat menggunakan registri tanda terima/outbound ketika itu
merupakan pendekatan terbaik yang tersedia.
Kapabilitas:
Pengurangan SDK publik
Permukaan publik baru harus menyerap atau menghentikan area konseptual ini:reply-runtimereply-dispatch-runtimereply-referencereply-chunkingreply-payloadinbound-reply-dispatchchannel-reply-pipeline- sebagian besar penggunaan publik
outbound-runtime - helper lifecycle stream draf ad hoc
plugin-sdk/channel-outbound setelah tersedia.
Hubungan dengan inbound channel
runtime.channel.inbound.* adalah bridge runtime selama migrasi.
Itu harus menjadi adapter kompatibilitas:
channel.inbound.runPreparedReply juga harus tetap ada pada awalnya:
channel.turn lama telah dihapus. Pemanggil runtime menggunakan
channel.inbound.*; dokumentasi channel dan subpath SDK menggunakan nomina inbound/message.
Guardrail kompatibilitas
Selama migrasi, pengiriman durable generik bersifat opt-in untuk channel apa pun yang callback pengiriman yang ada memiliki efek samping selain “kirim payload ini”. Entry point lama non-durable secara default:channel.inbound.rundandispatchChannelInboundReplymenggunakan callback pengiriman channel kecuali channel tersebut secara eksplisit memasok objek kebijakan/opsi durable yang telah diaudit.channel.inbound.runPreparedReplytetap dimiliki channel sampai dispatcher yang disiapkan secara eksplisit memanggil konteks kirim.- Helper kompatibilitas publik seperti
recordInboundSessionAndDispatchReply,dispatchInboundReplyWithBase, dan helper direct-DM tidak pernah menyuntikkan pengiriman durable generik sebelum callbackdeliverataureplyyang disediakan pemanggil.
durable: undefined berarti “tidak durable”. Jalur
durable diaktifkan hanya oleh nilai kebijakan/opsi yang eksplisit. durable: false dapat tetap sebagai ejaan kompatibilitas, tetapi implementasi seharusnya tidak
mengharuskan setiap channel yang belum dimigrasikan menambahkannya.
Kode bridge saat ini harus menjaga keputusan durabilitas tetap eksplisit:
- Pengiriman final durabel mengembalikan status terdiskriminasi.
handled_visibledanhandled_no_sendbersifat terminal;unsupporteddannot_applicabledapat kembali ke pengiriman milik kanal;failedmeneruskan kegagalan pengiriman. - Pengiriman final durabel generik dibatasi oleh kapabilitas adapter seperti pengiriman senyap, pelestarian target balasan, pelestarian kutipan native, dan hook pengiriman pesan. Paritas yang hilang harus memilih pengiriman milik kanal, bukan pengiriman generik yang mengubah perilaku yang terlihat pengguna.
- Pengiriman durabel berbasis antrean mengekspos referensi niat pengiriman.
Field sesi
pendingFinalDelivery*yang ada dapat membawa id niat selama transisi; keadaan akhir adalah penyimpananMessageSendIntent, bukan teks balasan beku ditambah field konteks ad hoc.
- Adapter pengiriman generik menjalankan perilaku rendering dan transport yang sama dengan jalur langsung lama.
- Efek samping lokal setelah pengiriman dipertahankan melalui konteks pengiriman.
- Adapter mengembalikan tanda terima atau hasil pengiriman dengan semua id pesan platform.
- Jalur dispatcher yang disiapkan memanggil konteks pengiriman baru atau tetap didokumentasikan sebagai di luar jaminan durabel.
- Pengiriman fallback menangani setiap payload yang diproyeksikan, bukan hanya yang pertama.
- Pengiriman fallback durabel mencatat seluruh array payload yang diproyeksikan sebagai satu niat atau rencana batch yang dapat diputar ulang.
- Pengiriman monitor iMessage mencatat pesan terkirim dalam cache gema setelah pengiriman berhasil. Pengiriman final durabel tetap harus mengisi cache itu; jika tidak, OpenClaw dapat menelan ulang balasan finalnya sendiri sebagai pesan pengguna masuk.
- Tlon menambahkan tanda tangan model opsional dan mencatat thread yang diikuti setelah balasan grup. Pengiriman durabel generik tidak boleh melewati efek tersebut; pindahkan efek itu ke adapter render/kirim/finalisasi Tlon atau pertahankan Tlon pada jalur milik kanal.
- Discord dan dispatcher lain yang disiapkan sudah memiliki perilaku pengiriman langsung dan pratinjau. Mereka tidak tercakup oleh jaminan durabel giliran yang dirakit sampai dispatcher yang disiapkan secara eksplisit merutekan final melalui konteks pengiriman.
- Pengiriman fallback senyap Telegram harus mengirimkan seluruh array payload yang diproyeksikan. Pintasan satu payload dapat menjatuhkan payload fallback tambahan setelah proyeksi.
- LINE, Zalo, Nostr, dan jalur rakitan/helper lain yang ada mungkin memiliki penanganan token balasan, proxy media, cache pesan terkirim, pembersihan loading/status, atau target khusus callback. Mereka tetap berada pada pengiriman milik kanal sampai semantik tersebut direpresentasikan oleh adapter pengiriman dan diverifikasi oleh pengujian.
- Helper DM langsung dapat memiliki callback balasan yang merupakan satu-satunya
target transport yang benar. Outbound generik tidak boleh menebak dari
OriginatingToatauTodan melewati callback tersebut. - Output kegagalan Gateway OpenClaw harus tetap terlihat oleh manusia, tetapi
gema ruang yang ditandai sebagai dibuat bot harus dibuang sebelum otorisasi
allowBots. Kanal tidak boleh mengimplementasikan ini dengan filter prefiks teks terlihat kecuali sebagai langkah darurat singkat; kontrak durabelnya adalah metadata asal terstruktur.
Penyimpanan internal
Antrean durabel harus menyimpan niat pengiriman pesan, bukan payload balasan.Kelas kegagalan
Adapter kanal mengklasifikasikan kegagalan transport ke dalam kategori tertutup:- Coba ulang
transientdanrate_limit. - Jangan coba ulang
invalid_payloadkecuali ada fallback render. - Jangan coba ulang
authataupermissionsampai konfigurasi berubah. - Untuk
not_found, biarkan finalisasi live kembali dari edit ke pengiriman baru ketika kanal menyatakan itu aman. - Untuk
conflict, gunakan aturan tanda terima/idempotensi untuk memutuskan apakah pesan sudah ada. - Error apa pun setelah adapter mungkin telah menyelesaikan I/O platform tetapi
sebelum commit tanda terima menjadi
unknown_after_sendkecuali adapter dapat membuktikan operasi platform tidak terjadi.
Pemetaan kanal
| Channel | Migrasi target |
|---|---|
| Telegram | Menerima kebijakan ack ditambah pengiriman akhir yang persisten. Adaptor langsung memiliki pengiriman ditambah pratinjau edit, pengiriman akhir pratinjau basi, topik, pelewatan pratinjau balasan-kutipan, fallback media, dan penanganan retry-after. |
| Discord | Adaptor kirim membungkus pengiriman muatan persisten yang ada. Adaptor langsung memiliki edit draf, draf progres, pembatalan pratinjau media/kesalahan, pelestarian target balasan, dan tanda terima id pesan. Audit gema kegagalan gateway yang ditulis bot di ruang bersama; gunakan registri keluar atau padanan native lain jika Discord tidak dapat membawa metadata asal pada pesan normal. |
| Slack | Adaptor kirim menangani posting chat normal. Adaptor langsung memilih stream native saat bentuk thread mendukungnya, jika tidak memakai pratinjau draf. Tanda terima mempertahankan timestamp thread. Adaptor asal memetakan kegagalan gateway OpenClaw ke Slack chat.postMessage.metadata dan membuang gema ruang-bot bertag sebelum otorisasi allowBots. |
| Adaptor kirim memiliki pengiriman teks/media dengan intent akhir persisten. Adaptor terima menangani mention grup dan identitas pengirim. Langsung dapat tetap tidak ada sampai WhatsApp memiliki transport yang dapat diedit. | |
| Matrix | Adaptor langsung memiliki edit event draf, finalisasi, redaksi, batasan media terenkripsi, dan fallback ketidakcocokan target balasan. Adaptor terima memiliki hidrasi event terenkripsi dan deduplikasi. Adaptor asal sebaiknya mengenkode asal kegagalan gateway OpenClaw ke konten event Matrix dan membuang gema ruang bot terkonfigurasi sebelum penanganan allowBots. |
| Mattermost | Adaptor langsung memiliki satu posting draf, pelipatan progres/tool, finalisasi di tempat, dan fallback pengiriman baru. |
| Microsoft Teams | Adaptor langsung memiliki progres native dan perilaku stream blok. Adaptor kirim memiliki aktivitas dan tanda terima lampiran/kartu. |
| Feishu | Adaptor render memiliki rendering teks/kartu/raw. Adaptor langsung memiliki kartu streaming dan penekanan final duplikat. Adaptor kirim memiliki komentar, sesi topik, media, dan penekanan suara. |
| QQ Bot | Adaptor langsung memiliki streaming C2C, timeout akumulator, dan fallback pengiriman akhir. Adaptor render memiliki tag media dan teks-sebagai-suara. |
| Signal | Adaptor terima sederhana ditambah adaptor kirim. Tidak ada adaptor langsung kecuali signal-cli menambahkan dukungan edit yang andal. |
| iMessage | Adaptor terima sederhana ditambah adaptor kirim. Pengiriman iMessage harus mempertahankan pengisian cache gema monitor sebelum final persisten dapat melewati pengiriman monitor. |
| Google Chat | Adaptor terima sederhana ditambah adaptor kirim dengan relasi thread dipetakan ke space dan id thread. Audit perilaku ruang allowBots=true untuk gema kegagalan gateway OpenClaw bertag. |
| LINE | Adaptor terima sederhana ditambah adaptor kirim dengan batasan token balasan dimodelkan sebagai kapabilitas target/relasi. |
| Nextcloud Talk | Bridge terima SDK ditambah adaptor kirim. |
| IRC | Adaptor terima sederhana ditambah adaptor kirim, tanpa tanda terima edit persisten. |
| Nostr | Adaptor terima ditambah adaptor kirim untuk DM terenkripsi; tanda terima adalah id event. |
| QA Channel | Adaptor uji-kontrak untuk perilaku terima, kirim, langsung, coba ulang, dan pemulihan. |
| Synology Chat | Adaptor terima sederhana ditambah adaptor kirim. |
| Tlon | Adaptor kirim harus mempertahankan rendering tanda tangan model dan pelacakan thread yang diikuti sebelum pengiriman akhir persisten generik diaktifkan. |
| Twitch | Adaptor terima sederhana ditambah adaptor kirim dengan klasifikasi batas laju. |
| Zalo | Adaptor terima sederhana ditambah adaptor kirim. |
| Zalo Personal | Adaptor terima sederhana ditambah adaptor kirim. |
Rencana migrasi
Fase 1: Domain Pesan Internal
- Tambahkan tipe
src/channels/message/*untuk pesan, target, relasi, asal, tanda terima, kapabilitas, intent persisten, konteks terima, konteks kirim, konteks langsung, dan kelas kegagalan. - Tambahkan
origin?: MessageOriginke tipe muatan bridge migrasi yang digunakan oleh pengiriman balasan saat ini, lalu pindahkan field tersebut keChannelMessagedan tipe pesan yang dirender saat refactor menggantikan muatan balasan. - Pertahankan ini tetap internal sampai adaptor dan pengujian membuktikan bentuknya.
- Tambahkan pengujian unit murni untuk transisi status dan serialisasi.
Fase 2: Core Kirim Persisten
- Pindahkan antrean keluar yang ada dari persistensi muatan-balasan ke intent pengiriman pesan persisten.
- Izinkan intent kirim persisten membawa array muatan terproyeksi atau rencana batch, bukan hanya satu muatan balasan.
- Pertahankan perilaku pemulihan antrean saat ini melalui konversi kompatibilitas.
- Buat
deliverOutboundPayloadsmemanggilmessages.send. - Jadikan persistensi pengiriman akhir sebagai default dan gagal tertutup saat intent persisten tidak dapat ditulis dalam siklus hidup pesan baru, setelah adaptor mendeklarasikan keamanan pemutaran ulang. Jalur kompatibilitas runner masuk dan SDK yang ada tetap menggunakan kirim langsung secara default selama fase ini.
- Catat tanda terima secara konsisten.
- Kembalikan tanda terima dan hasil pengiriman ke pemanggil dispatcher asli, alih-alih memperlakukan kirim persisten sebagai efek samping terminal.
- Persistenkan asal pesan melalui intent kirim persisten sehingga pemulihan, pemutaran ulang, dan pengiriman terpotong mempertahankan provenance operasional OpenClaw.
Fase 3: Bridge Masuk Channel
- Implementasikan ulang
channel.inbound.rundandispatchChannelInboundReplydi atasmessages.receivedanmessages.send. - Pertahankan tipe fakta saat ini tetap stabil.
- Pertahankan perilaku legacy secara default. Channel giliran-terakit menjadi persisten hanya saat adaptornya secara eksplisit ikut serta dengan kebijakan persistensi yang aman untuk pemutaran ulang.
- Pertahankan
durable: falsesebagai escape hatch kompatibilitas untuk jalur yang memfinalisasi edit native dan belum dapat diputar ulang dengan aman, tetapi jangan bergantung pada markerfalseuntuk melindungi channel yang belum dimigrasikan. - Defaultkan persistensi giliran-terakit hanya dalam siklus hidup pesan baru, setelah pemetaan channel membuktikan jalur kirim generik mempertahankan semantik pengiriman channel lama.
Fase 4: Bridge Dispatcher Siap
- Ganti
deliverDurableInboundReplyPayloaddengan jembatan konteks kirim. - Pertahankan helper lama sebagai wrapper.
- Port Telegram, WhatsApp, Slack, Signal, iMessage, dan Discord lebih dulu karena semuanya sudah memiliki pekerjaan final tahan lama atau jalur kirim yang lebih sederhana.
- Perlakukan setiap dispatcher yang disiapkan sebagai belum tercakup sampai secara eksplisit ikut serta dalam konteks kirim. Dokumentasi dan entri changelog harus menyebut “giliran channel yang dirakit” atau menamai jalur channel yang dimigrasikan, bukan mengklaim semua balasan final otomatis.
- Pertahankan perilaku
recordInboundSessionAndDispatchReply, helper direct-DM, dan helper kompatibilitas publik serupa. Semuanya dapat mengekspos ikut-serta konteks kirim eksplisit nanti, tetapi tidak boleh otomatis mencoba pengiriman tahan lama generik sebelum callback pengiriman milik pemanggil.
Fase 5: Siklus Hidup Live Terpadu
- Bangun
messages.livedengan dua adapter pembuktian:- Telegram untuk kirim plus edit plus pengiriman final kedaluwarsa.
- Matrix untuk finalisasi draf plus fallback redaksi.
- Lalu migrasikan Discord, Slack, Mattermost, Teams, QQ Bot, dan Feishu.
- Hapus kode finalisasi pratinjau yang terduplikasi hanya setelah setiap channel memiliki uji paritas.
Fase 6: SDK Publik
- Tambahkan
openclaw/plugin-sdk/channel-outbound. - Dokumentasikan sebagai API Plugin channel yang disarankan.
- Perbarui ekspor paket, inventaris entrypoint, baseline API yang dihasilkan, dan dokumentasi SDK Plugin.
- Sertakan
MessageOrigin, hook enkode/dekode origin, dan predikat bersamashouldDropOpenClawEchodi permukaan SDK channel-outbound. - Pertahankan wrapper kompatibilitas untuk subpath lama.
- Tandai helper SDK bernama reply sebagai usang dalam dokumentasi setelah Plugin bundel dimigrasikan.
Fase 7: Semua Pengirim
Pindahkan semua produser outbound non-reply kemessages.send:
- notifikasi cron dan heartbeat
- penyelesaian tugas
- hasil hook
- prompt persetujuan dan hasil persetujuan
- pengiriman alat pesan
- pengumuman penyelesaian subagent
- pengiriman CLI atau Control UI eksplisit
- jalur otomatisasi/broadcast
Fase 8: Hapus Kompatibilitas Bernama Turn
- Pertahankan wrapper bernama inbound/message sebagai jendela kompatibilitas.
- Terbitkan catatan migrasi.
- Jalankan uji kompatibilitas SDK Plugin terhadap impor lama.
- Hapus atau sembunyikan helper internal lama hanya setelah tidak ada Plugin bundel yang membutuhkannya dan kontrak pihak ketiga memiliki pengganti yang stabil.
Rencana uji
Uji unit:- Serialisasi dan pemulihan intent kirim tahan lama.
- Penggunaan ulang kunci idempotensi dan penekanan duplikat.
- Commit tanda terima dan lewati replay.
- Pemulihan
unknown_after_sendyang melakukan rekonsiliasi sebelum replay saat adapter mendukung rekonsiliasi. - Kebijakan klasifikasi kegagalan.
- Pengurutan kebijakan ack terima.
- Pemetaan relasi untuk pengiriman reply, followup, system, dan broadcast.
- Factory origin kegagalan Gateway dan predikat
shouldDropOpenClawEcho. - Preservasi origin melalui normalisasi payload, chunking, serialisasi antrean tahan lama, dan pemulihan.
- Adapter sederhana
channel.inbound.runtetap mencatat dan mengirim. - Pengiriman assembled-event lama tidak menjadi tahan lama kecuali channel secara eksplisit ikut serta.
- Jembatan
channel.inbound.runPreparedReplytetap mencatat dan memfinalisasi. - Helper kompatibilitas publik memanggil callback pengiriman milik pemanggil secara default dan tidak melakukan generic-send sebelum callback tersebut.
- Pengiriman fallback tahan lama me-replay seluruh array payload terproyeksi setelah restart dan tidak dapat membiarkan payload berikutnya tidak tercatat setelah crash awal.
- Pengiriman assembled-event tahan lama mengembalikan ID pesan platform ke dispatcher yang di-buffer.
- Hook pengiriman kustom tetap mengembalikan ID pesan platform saat pengiriman tahan lama dinonaktifkan atau tidak tersedia.
- Balasan final bertahan dari restart antara penyelesaian assistant dan pengiriman platform.
- Draf pratinjau difinalisasi di tempat saat diizinkan.
- Draf pratinjau dibatalkan atau direduksi saat ketidakcocokan media/error/reply-target memerlukan pengiriman normal.
- Streaming blok dan streaming pratinjau tidak sama-sama mengirim teks yang sama.
- Media yang di-stream lebih awal tidak diduplikasi dalam pengiriman final.
- Balasan topik Telegram dengan ack polling ditunda sampai watermark selesai aman milik konteks terima.
- Pemulihan polling Telegram untuk pembaruan yang diterima-tetapi-belum-terkirim dicakup oleh model offset selesai-aman yang dipersistenkan.
- Pratinjau Telegram yang kedaluwarsa mengirim final baru dan membersihkan pratinjau.
- Fallback senyap Telegram mengirim setiap payload fallback terproyeksi.
- Daya tahan fallback senyap Telegram mencatat seluruh array fallback terproyeksi secara atomik, bukan satu intent tahan lama payload tunggal per iterasi loop.
- Pembatalan pratinjau Discord pada media/error/reply eksplisit.
- Final dispatcher yang disiapkan Discord dirutekan melalui konteks kirim sebelum dokumentasi atau changelog mengklaim daya tahan final-reply Discord.
- Pengiriman final tahan lama iMessage mengisi cache echo pesan-terkirim monitor.
- Jalur pengiriman lama LINE, Zalo, dan Nostr tidak dilewati oleh kirim tahan lama generik sampai uji paritas adapternya ada.
- Pengiriman callback Direct-DM/Nostr tetap otoritatif kecuali secara eksplisit dimigrasikan ke target pesan lengkap dan adapter kirim yang aman replay.
- Pesan kegagalan Gateway OpenClaw bertag Slack tetap terlihat outbound, echo
bot-room bertag dibuang sebelum
allowBots, dan pesan bot tanpa tag dengan teks terlihat yang sama tetap mengikuti otorisasi bot normal. - Fallback stream native Slack ke pratinjau draf di DM tingkat atas.
- Finalisasi pratinjau Matrix dan fallback redaksi.
- Echo room kegagalan Gateway OpenClaw bertag Matrix dari akun bot yang dikonfigurasi
dibuang sebelum penanganan
allowBots. - Audit kaskade kegagalan Gateway ruang bersama Discord dan Google Chat mencakup
mode
allowBotssebelum mengklaim perlindungan generik di sana. - Finalisasi draf Mattermost dan fallback kirim-baru.
- Finalisasi progres native Teams.
- Penekanan final duplikat Feishu.
- Fallback timeout akumulator QQ Bot.
- Pengiriman final tahan lama Tlon mempertahankan rendering tanda tangan model dan pelacakan thread yang diikuti.
- Pengiriman final tahan lama sederhana WhatsApp, Signal, iMessage, Google Chat, LINE, IRC, Nostr, Nextcloud Talk, Synology Chat, Tlon, Twitch, Zalo, dan Zalo Personal.
- File Vitest tertarget selama pengembangan.
pnpm check:changeddi Testbox untuk seluruh permukaan yang berubah.pnpm checkyang lebih luas di Testbox sebelum mendaratkan refactor lengkap atau setelah perubahan SDK/ekspor publik.- Smoke live atau qa-channel untuk setidaknya satu channel berkemampuan edit dan satu channel sederhana hanya-kirim sebelum menghapus wrapper kompatibilitas.
Pertanyaan terbuka
- Apakah Telegram pada akhirnya harus mengganti sumber runner grammY dengan sumber polling yang sepenuhnya tahan lama yang dapat mengontrol pengiriman ulang tingkat platform, bukan hanya watermark restart yang dipersistenkan OpenClaw.
- Apakah status pratinjau live tahan lama harus disimpan dalam record antrean yang sama dengan intent kirim final atau dalam penyimpanan status live saudara.
- Berapa lama wrapper kompatibilitas tetap didokumentasikan setelah
plugin-sdk/channel-outbounddikirim. - Apakah Plugin pihak ketiga harus mengimplementasikan adapter terima secara langsung atau hanya
menyediakan hook normalize/send/live melalui
defineChannelMessageAdapter. - Field tanda terima mana yang aman diekspos di SDK publik versus status runtime internal.
- Apakah efek samping seperti cache self-echo dan penanda thread-yang-diikuti harus dimodelkan sebagai hook konteks kirim, langkah finalize milik adapter, atau subscriber tanda terima.
- Channel mana yang memiliki metadata origin native, mana yang membutuhkan registry outbound yang dipersistenkan, dan mana yang tidak dapat menawarkan penekanan echo lintas-bot yang andal.
Kriteria penerimaan
- Setiap channel pesan bundel mengirim output final yang terlihat melalui
messages.send. - Setiap channel pesan inbound masuk melalui
messages.receiveatau wrapper kompatibilitas terdokumentasi. - Setiap channel pratinjau/edit/stream menggunakan
messages.liveuntuk status draf dan finalisasi. channel.inboundhanya wrapper.- Helper SDK bernama reply adalah ekspor kompatibilitas, bukan jalur yang disarankan.
- Pemulihan tahan lama dapat me-replay pengiriman final yang tertunda setelah restart tanpa kehilangan respons final atau menduplikasi pengiriman yang sudah di-commit; pengiriman dengan hasil platform yang tidak diketahui direkonsiliasi sebelum replay atau didokumentasikan sebagai setidaknya-sekali untuk adapter tersebut.
- Pengiriman final tahan lama gagal tertutup saat intent tahan lama tidak dapat ditulis, kecuali pemanggil secara eksplisit memilih mode non-tahan-lama yang terdokumentasi.
- Helper kompatibilitas SDK lama default ke pengiriman langsung milik channel; kirim tahan lama generik hanya ikut-serta eksplisit.
- Tanda terima mempertahankan semua ID pesan platform untuk pengiriman multi-bagian dan ID primer untuk kemudahan threading/edit.
- Wrapper tahan lama mempertahankan efek samping lokal channel sebelum mengganti callback pengiriman langsung.
- Dispatcher yang disiapkan tidak dihitung sebagai tahan lama sampai jalur pengiriman finalnya secara eksplisit menggunakan konteks kirim.
- Pengiriman fallback menangani setiap payload terproyeksi.
- Pengiriman fallback tahan lama mencatat setiap payload terproyeksi dalam satu intent atau rencana batch yang dapat di-replay.
- Output kegagalan Gateway yang berasal dari OpenClaw terlihat oleh manusia tetapi echo room bertag yang ditulis bot dibuang sebelum otorisasi bot pada channel yang menyatakan dukungan untuk kontrak origin.
- Dokumentasi menjelaskan kirim, terima, live, status, tanda terima, relasi, kebijakan kegagalan, migrasi, dan cakupan uji.