Add multi-platform bot support with user-scoped identities#872
Merged
Add multi-platform bot support with user-scoped identities#872
Conversation
Unify Slack, Telegram, WhatsApp, and dashboard chat on the same assistant and inbox upload pipeline, and map platform identities to the correct Midday user so bot actions and uploads run with the right permissions. Made-with: Cursor
Unify the new bot runtime across Slack, Telegram, and WhatsApp while adding notification batching and upload-aware assistant behavior. Made-with: Cursor
Hydrate linked platform identities before each bot response so notification context and user mapping stay consistent across Slack, Telegram, and WhatsApp. Remove duplicate public bot webhook aliases so each provider has a single canonical entry point. Made-with: Cursor
Add the missing createPlatformLinkToken export to the shared API test harness so apps router tests can load the updated db query surface without crashing. Made-with: Cursor
Freeze the runway test clock to the seeded fixture window so the trailing six-month burn rate assertion stays stable as calendar time moves forward. Made-with: Cursor
hasCurrentTeamAccess had side effects (forgetThreadState + posting an error message) that conflicted with handleIncomingMessage's own null fallback. When hydrateResolvedConversationIdentity returned null after the access check, the caller posted a second message and cleared state again. Split hasCurrentTeamAccess into a pure check and a separate notifyTeamAccessRevoked helper so each call site controls its own messaging. Made-with: Cursor
…blue Implements a full Chat SDK adapter backed by the official Sendblue SDK, supporting inbound/outbound messages, attachments, tapback reactions, typing indicators, message history, and number lookups. Wired into the bot runtime with webhook routing, platform identity support, and DB schema. Made-with: Cursor
bot-runtime and slack-oauth-callback tests use their own mock.module calls for @midday/bot, which conflict with the preloaded setup.ts mock environment. Run them in separate bun processes so their module mocks don't collide with the shared preload. Made-with: Cursor
…atterns --path-ignore-patterns glob does not work reliably across bun versions (1.3.10 in CI ignores the flag). List safe router test files explicitly in the preloaded run instead. Made-with: Cursor
- Require mixed alphanumeric in bare link codes to avoid false positives on English words - Use stricter Connect-to-Midday prefix matching instead of naive split - Generate link codes with guaranteed digit+letter mix (customAlphabet) - Remove @midday/bot from jobs package, comment out sendToProviders (migrating to worker) Made-with: Cursor
NEXT_PUBLIC_TELEGRAM_BOT_USERNAME and NEXT_PUBLIC_SENDBLUE_NUMBER were missing from both passThroughEnv and Docker build args, so the connect dialogs for iMessage and Telegram were silently rendering null. Made-with: Cursor
… agent The dashboard chat pre-processed uploads into system prompt summaries but still passed raw data-URL file parts to streamMiddayAssistant. Extract shared stripFileAndImageParts utility and use it in both dashboard and bot paths. Made-with: Cursor
…ing demo - Add isExplicitConnectionAttempt to differentiate "Connect to Midday:" / "/start" messages from ambiguous bare alphanumeric strings, so unlinked users see a helpful prompt instead of an invalid-code error - Remove unused export on resolveFromExistingIdentity (file-private only) - Replace ChatDemoRail with dot-indicator + AnimatePresence transitions - Add tests for bare-code vs explicit-link error paths Made-with: Cursor
Move afterConnect (platform app creation) before createOrUpdatePlatformIdentity so a failed connection (e.g. addWhatsAppConnection returns null) no longer leaves an identity record without a matching app. Also remove unused `identity` param from the afterConnect callback signature. Made-with: Cursor
…l active writer.merge() is non-blocking, so the finally block was calling result.cleanup() (closing the MCP execution client) while the ToolLoopAgent was potentially still making tool calls. The agent's onFinish callback already handles cleanup when it's truly done. Made-with: Cursor
The legacy &body= convention can cause the message body to be silently ignored on some platforms or iOS versions. Made-with: Cursor
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 35d7e48. Configure here.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Unify Slack, Telegram, WhatsApp, and dashboard chat on the same assistant and inbox upload pipeline, and map platform identities to the correct Midday user so bot actions and uploads run with the right permissions.
Note
High Risk
High risk because it rewires Slack/WhatsApp/Telegram/Sendblue webhook handling and Slack OAuth flow, adds new identity/link-token logic, and changes how uploads/messages are processed and attributed to users (permission-sensitive).
Overview
Unifies bot runtime handling across Slack, WhatsApp, Telegram, and Sendblue by introducing a new
registerMiddayBotRuntime()flow that resolves/creates per-userPlatformIdentityrecords, caches thread state, and routes messages into the same assistant + inbox-upload pipeline.Adds link-code onboarding and reconnect logic (token extraction, explicit-vs-implicit connect attempts, welcome/error messaging, team-access checks) plus new tRPC
apps.createPlatformLinkTokento mint link codes for supported providers.Refactors Slack OAuth + webhooks to persist a platform identity on install and store Slack installations via
@midday/botadapters; replaces custom Slack/WhatsApp webhook implementations with thin pass-through routers tobot.webhooks.*, and adds new Telegram/Sendblue webhook routes.Extends chat/assistant behavior by preprocessing uploaded files (dashboard + bot attachments), injecting upload summaries into the system prompt, stripping raw file/image parts from model messages, and tightening attachment fetching to an allowlisted set of HTTPS hosts.
Also updates MCP tracker tools to accept/normalize lenient ISO datetimes, adjusts app OAuth callbacks to type
createApp<...>calls, and adds extensive new router/runtime tests and env template/dashboard env vars for messaging integrations.Reviewed by Cursor Bugbot for commit f03fd54. Bugbot is set up for automated code reviews on this repo. Configure here.