Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
a96f8ed
feat: Add support for handling `message_deleted` and `message_changed…
mlenczewski-tidio May 22, 2026
9f14e48
chore: cleanup
mlenczewski-tidio May 22, 2026
5354dbb
feat: Add lifecycle callbacks for message update and delete with Slac…
mlenczewski-tidio May 22, 2026
f1284e3
feat: Handle `tombstone` messages and improve hidden message update h…
mlenczewski-tidio May 22, 2026
ee2944e
chore: prepare chat packages for git installs
mlenczewski-tidio May 25, 2026
0af12f3
fix: integrate lifecycle callbacks with upstream test tooling and mak…
mlenczewski-tidio Jul 8, 2026
176f4ac
chore: drop the git-install prepare scripts
dancer Aug 5, 2026
88d3839
fix(chat): scope and self-filter message lifecycle dispatch
dancer Aug 5, 2026
11b30d2
refactor(slack): derive message-event thread ids in one place
dancer Aug 5, 2026
f8f9ec7
test(slack): use the shared mock helpers instead of shadowing them
dancer Aug 5, 2026
aa1eb14
test(slack): assert message, edit, and delete share a thread id
dancer Aug 5, 2026
f731d7d
fix(chat): drop the unpassed context param and document the delete shape
dancer Aug 5, 2026
2e8df24
docs: add message edit and delete events to the feature matrix
dancer Aug 5, 2026
5f9823d
docs: document onMessageUpdated and onMessageDeleted
dancer Aug 5, 2026
51ad33a
feat(chat): forward the pre-edit message to onMessageUpdated
dancer Aug 5, 2026
036d441
revert(slack): stop interpreting the undocumented tombstone subtype
dancer Aug 5, 2026
3082628
fix(slack): ignore message_changed when nothing actually changed
dancer Aug 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/legal-ways-reply.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@chat-adapter/slack": minor
"chat": minor
---

Add message update and delete lifecycle callbacks, with Slack message_changed and message_deleted dispatch support.
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/community/baileys.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ features:
addReactions: yes
removeReactions: yes
typingIndicator: yes
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages: yes
ephemeralMessages: no
userLookup: yes
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/community/blooio.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ features:
status: yes
label: Tapbacks
typingIndicator: yes
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages: yes
ephemeralMessages: no
userLookup:
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/community/mattermost.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ features:
addReactions: yes
removeReactions: yes
typingIndicator: yes
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages: yes
ephemeralMessages: yes
userLookup: yes
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/community/qq.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ features:
addReactions: no
removeReactions: no
typingIndicator: no
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages: yes
ephemeralMessages: no
userLookup: no
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/community/webex.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ features:
addReactions: no
removeReactions: no
typingIndicator: no
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages: yes
ephemeralMessages: no
userLookup: yes
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/community/wecom.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ features:
addReactions: no
removeReactions: no
typingIndicator: no
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages: yes
ephemeralMessages: no
userLookup: no
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/community/weixin.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ features:
addReactions: no
removeReactions: no
typingIndicator: yes
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages: yes
ephemeralMessages: no
userLookup: no
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/community/zaileys.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ features:
addReactions: yes
removeReactions: yes
typingIndicator: yes
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages: yes
ephemeralMessages: no
userLookup: yes
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/community/zalo.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ features:
addReactions: no
removeReactions: no
typingIndicator: yes
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages: yes
ephemeralMessages: no
userLookup: no
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/official/discord.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ features:
addReactions: yes
removeReactions: yes
typingIndicator: yes
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages: yes
ephemeralMessages: no
userLookup: yes
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/official/gchat.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ features:
status: yes
label: Workspace Events
typingIndicator: no
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages:
status: yes
label: Requires delegation
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/official/github.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ features:
status: partial
label: ""
typingIndicator: no
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages: no
ephemeralMessages: no
userLookup: yes
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/official/linear.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ features:
typingIndicator:
status: partial
label: Agent sessions
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages: no
ephemeralMessages: no
userLookup: yes
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/official/messenger.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ features:
addReactions: no
removeReactions: no
typingIndicator: yes
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages: yes
ephemeralMessages: no
customApiEndpoint: yes
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/official/slack.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ features:
addReactions: yes
removeReactions: yes
typingIndicator: yes
messageUpdatedEvents: yes
messageDeletedEvents: yes
directMessages: yes
ephemeralMessages:
status: yes
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/official/teams.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ features:
addReactions: yes
removeReactions: yes
typingIndicator: yes
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages: yes
ephemeralMessages:
status: yes
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/official/telegram.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ features:
addReactions: yes
removeReactions: yes
typingIndicator: yes
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages: yes
ephemeralMessages: no
userLookup:
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/official/twilio.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ features:
addReactions: no
removeReactions: no
typingIndicator: no
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages: yes
ephemeralMessages: no
customApiEndpoint: yes
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/official/web.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ features:
addReactions: no
removeReactions: no
typingIndicator: no
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages: yes
ephemeralMessages: no
customApiEndpoint: yes
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/official/whatsapp.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ features:
addReactions: yes
removeReactions: yes
typingIndicator: yes
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages: yes
ephemeralMessages: no
customApiEndpoint: yes
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/official/x.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ features:
status: partial
label: Likes only
typingIndicator: no
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages: yes
ephemeralMessages: no
customApiEndpoint: yes
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/official/xchat.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ features:
addReactions: yes
removeReactions: yes
typingIndicator: yes
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages: yes
ephemeralMessages: no
customApiEndpoint:
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/vendor-official/agentphone.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ features:
label: iMessage only
removeReactions: no
typingIndicator: no
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages: yes
ephemeralMessages: no
userLookup: no
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/vendor-official/dial.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ features:
typingIndicator:
status: partial
label: iMessage numbers only; silently ignored on SMS
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages: yes
ephemeralMessages: no
userLookup: no
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/vendor-official/kapso.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ features:
addReactions: yes
removeReactions: yes
typingIndicator: no
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages: yes
ephemeralMessages: no
userLookup: no
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/vendor-official/lark.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ features:
addReactions: yes
removeReactions: yes
typingIndicator: no
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages: yes
ephemeralMessages: no
userLookup: no
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/vendor-official/linq.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ features:
typingIndicator:
status: partial
label: DMs only
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages: yes
ephemeralMessages: no
userLookup: no
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/vendor-official/liveblocks.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ features:
status: yes
label: Unicode emoji
typingIndicator: no
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages: no
ephemeralMessages: no
userLookup:
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/vendor-official/matrix.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ features:
addReactions: yes
removeReactions: yes
typingIndicator: yes
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages: yes
ephemeralMessages: no
userLookup: yes
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/vendor-official/novu.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ features:
addReactions: yes
removeReactions: no
typingIndicator: no
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages:
status: partial
label: Inbound only (no openDM in v1)
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/vendor-official/photon.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ features:
typingIndicator:
status: partial
label: Remote only
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages: yes
ephemeralMessages: no
userLookup: no
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/vendor-official/resend.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ features:
addReactions: no
removeReactions: no
typingIndicator: no
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages: yes
ephemeralMessages: no
userLookup: no
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/vendor-official/sendblue.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ features:
typingIndicator:
status: partial
label: 1:1 only
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages: yes
ephemeralMessages: no
userLookup:
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/adapters/vendor-official/zernio.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ features:
typingIndicator:
status: partial
label: FB, Telegram
messageUpdatedEvents: no
messageDeletedEvents: no
directMessages: yes
ephemeralMessages: no
userLookup: yes
Expand Down
54 changes: 54 additions & 0 deletions apps/docs/content/docs/handling-events.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,60 @@ bot.onReaction(["bookmark"], async (event) => {
});
```

## Handling edits and deletes

`onMessageUpdated` fires when a user edits a message, and `onMessageDeleted` when one is removed. Both are lifecycle events: they never route through `onNewMessage`, `onNewMention`, or `onSubscribedMessage`, and the concurrency strategies do not apply to them.

```typescript title="lib/bot.ts" lineNumbers
bot.onMessageUpdated(async (thread, message, previousMessage) => {
await mirror.update(message.id, message.text);
if (previousMessage) {
await audit.record(`"${previousMessage.text}" became "${message.text}"`);
}
});

bot.onMessageDeleted(async (event) => {
await mirror.remove(event.messageId);
});
```

`previousMessage` is the message as it read before the edit, supplied when the platform sends it. Slack does, so you can diff the change rather than only seeing the result. Treat it as optional: a platform that reports edits without the prior text leaves it `undefined`.

The bot's own edits are filtered out, so a streamed reply that renders through post-and-edit does not call `onMessageUpdated` back once per delta.

### Why the two shapes differ

`onMessageUpdated` receives `(thread, message, previousMessage?)` like the other message handlers, because an edit carries a full replacement message.

`onMessageDeleted` receives a single event instead. A delete has no message: platforms usually report only the id of what was removed, and `previousMessage` is best-effort. Use `chat.thread(event.threadId)` when you need a `Thread`, for example to post a notice in the conversation:

```typescript title="lib/bot.ts" lineNumbers
bot.onMessageDeleted(async (event) => {
if (!event.previousMessage) {
return;
}
await chat
.thread(event.threadId)
.post(`A message from ${event.previousMessage.author.userName} was deleted`);
});
```

### MessageDeletedEvent

| Property | Type | Description |
|---|---|---|
| `messageId` | `string` | Platform-native id of the deleted message |
| `threadId` | `string` | Thread the message was in |
| `channelId` | `string` | Channel the message was in |
| `platform` | `string` | Adapter name, e.g. `"slack"` |
| `previousMessage` | `Message \| undefined` | Snapshot, when the platform supplied enough to parse one |
| `deletedAt` | `Date \| undefined` | When the delete happened, when reported |
| `raw` | `unknown` | Platform-specific delete event |

<Callout type="warn">
Only the Slack adapter emits these events today. Registering the handlers on another platform is harmless but nothing will call them. Check the **Message edit events** and **Message delete events** rows on each [adapter page](/adapters) before relying on them.
</Callout>

## Handling interactions

For button clicks, slash commands, and modal forms, see the dedicated guides:
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/lib/adapter-features.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ export const PLATFORM_FEATURE_CATEGORIES: AdapterFeatureCategory[] = [
{ key: "addReactions", label: "Add reactions" },
{ key: "removeReactions", label: "Remove reactions" },
{ key: "typingIndicator", label: "Typing indicator" },
{ key: "messageUpdatedEvents", label: "Message edit events" },
{ key: "messageDeletedEvents", label: "Message delete events" },
{ key: "directMessages", label: "DMs" },
{ key: "ephemeralMessages", label: "Ephemeral messages" },
{ key: "userLookup", label: "User lookup" },
Expand Down
Loading