Skip to content

feat(messaging): manage an app's conversations: mute, rules, block, allow again (#1109) - #1120

Merged
DoodleBears merged 1 commit into
mainfrom
claude/1109-conversation-list
Oct 7, 2026
Merged

DoodleBears merged 1 commit into
mainfrom
claude/1109-conversation-list

Conversation

@DoodleBears

Copy link
Copy Markdown
Contributor

Requested by Vain · project thread

Closes #1109 · part of #1107 · ADR-0142

Before: an app's Conversations list in Edit identity was read-only. Every new DM or @mention was admitted with no limit, and nothing could mute, tune or shut out one conversation.

After: the list sorts conversations into Waiting, Active, Muted and Blocked, each with row actions. Mute keeps messages in the Inbox without waking the Bot. Rules edits one group's collection and wake. Block asks for confirmation and keeps the conversation out, even after a restart or after unbinding and rebinding. Allow again starts fresh from the next message with no backfill. A new New conversations setting chooses Admit automatically or Ask me first. New conversations past 20 per hour or 500 active per app wait, and the row says why.

How

  • Storage (gen 62).
    • messaging_conversation_blocks is keyed by Bot, app fingerprint, conversation kind and ID, so a block survives unbind and rebind.
    • messaging_held_conversations keeps metadata only: name, first and last seen, a capped count and the reason. It holds at most 200 rows per app, pruning the oldest.
    • Revoked explicit receive grants with no live replacement migrate into blocks.
  • Intake (inbound.ts). For a conversation that has no entry yet:
    • If it is blocked, the message is acknowledged and nothing is admitted.
    • In ask mode, or past the bounds, it is held and no Source Event is created.
    • Otherwise an implicit entry is created as before.
    • On a muted entry, both wake columns become silent, and the runtime neither wakes the Bot nor steers on it.
  • Commands (outbound.ts conversation(), bridge messagingConversation).
    • mute is checked against a separate preferenceRevision, so the grant revision that fences the Outbox is untouched.
    • block bumps the revision, ends unstarted intents as grant-revoked, aborts in-flight file attempts and writes the block.
    • block-held blocks a waiting conversation.
    • allow (from held or blocked) creates a fresh implicit entry with receiveAfter = now and refuses when the app is at 500 active entries.
    • Stale revisions refuse with conversation-stale.
  • Client. The new ExternalConversations component reuses GroupReceptionSettings for Rules and confirms Block inline. The New conversations combobox (hidden for WeChat) saves through the identity update.
  • Docs. The External identities guide (zh/en) gets a new conversations section and a new list image. CHANGELOG zh/en are updated.

Screenshots

From a real Host with the simulated Lark provider and the real model. All variants, zh/en and light/dark: https://github.com/BotHarness/BotHarness/tree/claude/1109-conversation-list/docs/assets/pr/1109-conversation-list

zh light en dark
Four groups
Block confirm
Rules

Tests

  • messaging-default-traffic.test.ts covers:
    • A blocked group stays out in auto mode, after a restart and after unbind and rebind. Allow again admits only new messages.
    • A stale block is refused, and the old reply route is revoked.
    • A muted entry is admitted with wake_mode = silent and no run, and it can still be answered. Unmute wakes again.
    • Ask mode holds a conversation with no Source Event until it is allowed. Blocking a held conversation keeps it out.
    • The 21st new conversation in an hour waits with hourly-limit.
  • messaging-conversation-list-migration.test.ts checks the gen-62 upgrade.
  • external-conversations.test.ts checks the groups and that Block needs a confirmation. It also checks that every action sends the right revision-checked command.
  • Core messaging: 20 files and 208 tests pass. Client: 120 files and 890 tests pass. tsc, lint and oxfmt are clean.
  • human-dm-steer.test.ts › folds many short pending… times out in this container on a clean main too, so it is not caused by this change.

Real Host (DSH 0.2.0-rc.1, OpenCode Go model, simulated Lark provider):

  • A blocked group got no reply.
  • A muted DM was admitted as silent with no run.
  • In ask mode, a new group and a new DM waited, with no message text stored.
  • Allowing the group got a real reply in 3 s.
  • After Allow again, the blocked group was answered.
  • Messages sent while blocked or waiting were not backfilled.

Merge risk

Human verification

  1. Bind a real Lark app, @mention it in a group, open Edit identity and Block the group. The next mention gets no reply. Restart, unbind and rebind: still no reply. Then Allow again: the next mention is answered.
  2. Mute a DM. New DMs appear in the Inbox without waking the Bot.
  3. Switch New conversations to Ask me first and DM from another account. It waits under Waiting. Allow it, and the next DM is answered.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WXjBatxGTRyRSxZYeJpqgH


Generated by Claude Code

…llow again (#1109)

The app's Conversations list in Edit identity sorts entries into Waiting,
Active, Muted and Blocked. Mute admits silently, Rules reuses the group
reception editor, Block revokes the entry, cancels unsent replies and
writes a durable block per Bot, app fingerprint and conversation that
survives restart and rebind; Allow again creates a fresh entry with no
backfill. New conversations can be admitted automatically or held for
the user, and new entries are bounded to 20 per hour and 500 active per
app with at most 200 held.

Issue: #1109
Agent-Task: claude-code/cloud/session_01WXjBatxGTRyRSxZYeJpqgH
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WXjBatxGTRyRSxZYeJpqgH
@coderabbitai

coderabbitai Bot commented Oct 7, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 54 seconds.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: e0c6e9ba-2af6-4e91-88dc-f132f97121fc
📥 Commits

Reviewing files that changed from the base of the PR and between 8297ef4 and c4b1da6.

📒 Files selected for processing (43)
  • CHANGELOG.md
  • CHANGELOG.zh.md
  • apps/docs/public/guides/channel-sidebar/19b-app-conversations-en.webp
  • apps/docs/public/guides/channel-sidebar/19b-app-conversations-zh.webp
  • apps/docs/public/guides/channel-sidebar/19c-app-conversations-en.webp
  • apps/docs/public/guides/channel-sidebar/19c-app-conversations-zh.webp
  • docs/assets/pr/1109-conversation-list/README.md
  • docs/assets/pr/1109-conversation-list/block-confirm-en-dark.webp
  • docs/assets/pr/1109-conversation-list/block-confirm-en-light.webp
  • docs/assets/pr/1109-conversation-list/block-confirm-zh-dark.webp
  • docs/assets/pr/1109-conversation-list/block-confirm-zh-light.webp
  • docs/assets/pr/1109-conversation-list/conversations-en-dark.webp
  • docs/assets/pr/1109-conversation-list/conversations-en-light.webp
  • docs/assets/pr/1109-conversation-list/conversations-zh-dark.webp
  • docs/assets/pr/1109-conversation-list/conversations-zh-light.webp
  • docs/assets/pr/1109-conversation-list/rules-en-dark.webp
  • docs/assets/pr/1109-conversation-list/rules-en-light.webp
  • docs/assets/pr/1109-conversation-list/rules-zh-dark.webp
  • docs/assets/pr/1109-conversation-list/rules-zh-light.webp
  • docs/channel-sidebar/external-identities.md
  • docs/channel-sidebar/external-identities.zh.md
  • packages/client/src/client/actions.ts
  • packages/client/src/client/bridge.ts
  • packages/client/src/client/external-conversations.tsx
  • packages/client/src/client/external-entries.tsx
  • packages/client/src/client/external-identity-list.tsx
  • packages/client/src/client/locale.ts
  • packages/client/src/client/messaging-grant.tsx
  • packages/client/src/client/styles.ts
  • packages/client/test/bot-sidebar.test.ts
  • packages/client/test/external-conversations.test.ts
  • packages/client/test/external-identity-list.test.ts
  • packages/core/src/bridge/methods.ts
  • packages/core/src/bridge/rpc.ts
  • packages/core/src/database/schema-plan.ts
  • packages/core/src/messaging/conversations.ts
  • packages/core/src/messaging/inbound.ts
  • packages/core/src/messaging/outbound.ts
  • packages/core/src/runtime/bot-runtime.ts
  • packages/core/test/bridge-rpc.test.ts
  • packages/core/test/messaging-conversation-list-migration.test.ts
  • packages/core/test/messaging-default-traffic.test.ts
  • packages/core/test/plugin.test.ts
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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.

Conversation list: mute, rules, block that sticks, allow again

2 participants