Skip to content

Add multi-platform bot support with user-scoped identities#872

Merged
pontusab merged 43 commits intomainfrom
feature/remote
Apr 7, 2026
Merged

Add multi-platform bot support with user-scoped identities#872
pontusab merged 43 commits intomainfrom
feature/remote

Conversation

@pontusab
Copy link
Copy Markdown
Contributor

@pontusab pontusab commented Apr 1, 2026

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-user PlatformIdentity records, 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.createPlatformLinkToken to mint link codes for supported providers.

Refactors Slack OAuth + webhooks to persist a platform identity on install and store Slack installations via @midday/bot adapters; replaces custom Slack/WhatsApp webhook implementations with thin pass-through routers to bot.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.

pontusab added 15 commits April 5, 2026 10:47
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
pontusab added 4 commits April 6, 2026 14:41
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
pontusab added 2 commits April 6, 2026 16:19
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
pontusab added 4 commits April 6, 2026 16:59
…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
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ 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.

@pontusab pontusab merged commit 4444cd7 into main Apr 7, 2026
12 of 13 checks passed
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.

1 participant