Skip to content

feat(chat): add message update and delete lifecycle callbacks - #788

Merged
dancer merged 17 commits into
mainfrom
josh/message-lifecycle-callbacks
Aug 5, 2026
Merged

feat(chat): add message update and delete lifecycle callbacks#788
dancer merged 17 commits into
mainfrom
josh/message-lifecycle-callbacks

Conversation

@dancer

@dancer dancer commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

summary

adds onMessageUpdated and onMessageDeleted, so a bot can react when a message is edited or removed. Slack dispatches both today; other adapters can opt in later

supersedes #549, which was verified there against real Slack webhooks. reopened from a branch in this repo with the original commits preserved and signed

bot.onMessageUpdated(async (thread, message, previousMessage) => {
  await mirror.update(message.id, message.text);
});

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

both are lifecycle events: they never route through onNewMessage, onNewMention, or onSubscribedMessage, and the concurrency strategies do not apply

notes

  • the bot's own edits are filtered. slack sends a message_changed for every chat.update, and post-and-edit streaming calls it once per delta, so without this a single streamed reply would call the handler back repeatedly on its own message
  • previousMessage is forwarded on edits. slack sends the pre-edit message and it was being dropped. an edit handler usually needs the before to know what changed, so it is the optional third argument
  • the two shapes differ deliberately. an edit carries a full replacement message, so it gets (thread, message, previousMessage?). a delete has no message, only the id of what was removed, so it gets an event. use chat.thread(event.threadId) when a delete handler needs one
  • one thread id helper now serves message, edit, and delete, so an edit cannot resolve to a different thread than the message it edits

test plan

core:

  • an edit dispatches to onMessageUpdated and not to the normal message handlers
  • the handler receives the pre-edit message as its third argument
  • the bot's own edits are skipped
  • a delete dispatches with normalized event data
  • both run inside the active conversation, so read tools built in these handlers stay scoped

slack:

  • message_changed dispatches as an update, message_deleted as a delete
  • previous_message is forwarded, and left undefined when slack omits it
  • hidden unfurl updates stay ignored, hidden real edits still dispatch
  • message, edit, and delete resolve to one thread id in a flat DM and in a threaded agent_view DM

verified against a real slack workspace over socket mode: editing and deleting a DM both routed to the same thread id as the original message

mlenczewski-tidio and others added 16 commits August 5, 2026 11:41
…e chat prepare rebuildable

Upstream #674/#675 introduced the shared @chat-adapter/tests factories and
matchers, which the rebased adapter-slack tests now use. The mock ChatInstance
did not stub the fork's processMessageUpdated/processMessageDeleted lifecycle
processors, so the message_changed/message_deleted suites failed with
'this.chat.processMessageUpdated is not a function'. Add both processors to
createMockChatInstance and to the toHaveDispatched handler list.

Also make the chat package's prepare script remove dist before tsup: with a
previous build's dist/jsx-runtime.d.ts present, the dts step resolves the
chat/jsx-runtime export to the built file and fails with TS5055 (cannot
overwrite input file). Upstream never hits this because its build script
always cleans first; prepare (used for git installs) did not.
@dancer
dancer requested a review from a team as a code owner August 5, 2026 11:46
@vercel

vercel Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
chat Ready Ready Preview, v0 Aug 5, 2026 12:15pm
chat-sdk-nextjs-chat Ready Ready Preview Aug 5, 2026 12:15pm

@dancer
dancer merged commit 4ac0455 into main Aug 5, 2026
18 checks passed
@dancer
dancer deleted the josh/message-lifecycle-callbacks branch August 5, 2026 12:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants