Skip to content

Social: inbound delivery loses, duplicates or cannot reply to remote messages (PR #2 review) #8

Closed

Description

@Birfy

Context

Review feedback on PR #2 reported that inbound Bot Social messages can be lost, duplicated, or left without a reply route. The code at 7b806c6 still has all of these problems. Related to #5 (social design); this issue tracks the delivery bugs only.

Original feedback

  • @hsliuustc0106 review (permalink), P1 item 5: "pollInbox advances the inbox cursor before delivering the batch; any mid-batch throw (hidden by the timer's .catch(() => {})) permanently skips the failed event and everything after it. A middleware deny is also counted as delivered."
  • Codex inline comment, Advance the inbox cursor only after delivering the batch (permalink), ds-bot/plugins/social/src/social.js L237.
  • Review item 6 + Codex inline Route normal replies back to remote senders (permalink), ds-bot/src/host/hooks.js (orig. L331): inbound remote messages carry no return address, so the normal turn-end reply fails with Unknown Bot undefined and is hidden.
  • Review item 7: inbox cursors are in-memory only. A restart replays retained history, overlapping polls double-deliver, and there is no event-id dedup or single-flight guard.
  • Review P2 "Legacy path": the start_conversation conversation id is never cached, so a file send right after opening a legacy conversation fails.

Where (at 7b806c6)

Proposed fix

  1. Process events one at a time with per-event try/catch, and advance or persist the cursor only after each event is handled. Do not count a deny as delivered (log it or surface it).
  2. Persist cursors per bot (for example under the social state file) and dedup by event id. Add a single-flight guard so polls cannot overlap.
  3. Give remote-origin turns a routable return address (for example a remote source carrying the handle) so turns.js routes the turn-end reply through bot.send to the remote transport. Otherwise, do not mark these turns as request.
  4. Cache conversation_id from start_conversation.

Acceptance criteria

  • A throw while delivering event n does not skip events n+1..; the failed event is retried on the next poll.
  • Restarting the host does not redeliver already-delivered events. Two concurrent polls never deliver the same event twice.
  • A local Bot's ordinary reply to an inbound remote message reaches the remote Bot, with no Unknown Bot undefined.
  • A file send right after a new legacy conversation succeeds.
  • Tests cover each case.

Refs: PR #2 (merged), umbrella #3. Verified against Birfy/FlyBot flybot-plugins tip 7b806c6.

Activity

  1. added a commit that references this issue on Oct 14, 2026
    bdfb5b3
  2. added a commit that references this issue on Oct 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions