Skip to content

think: messenger burst concurrency silently drops the messages it skipped #2312

Closed

Description

@harryy2510

Describe the bug

ThinkMessengerRuntime.createChat() builds its Chat with the burst concurrency strategy. The Chat SDK documents that strategy as:

'burst' — wait once before the first handler, then process the latest message with context.skipped containing earlier burst messages

So burst deliberately delivers only the newest message of a run and hands the earlier ones to the handler through MessageContext.skipped. Think's three handlers drop that argument:

chat.onDirectMessage(async (thread, message) => { ... });
chat.onNewMention(async (thread, message) => { ... });
chat.onSubscribedMessage(async (thread, message) => { ... });

The result is silent data loss on ordinary chat behaviour. The same applies to queue, which also reports through context.skipped.

To Reproduce

  1. Configure a Think agent with any messenger (the runtime hardcodes burst, so no extra setup is needed).
  2. From one user, send three quick lines inside the 600ms burst window:
summarize the thread
for me
and keep it short
  1. The model receives only and keep it short. The first two lines are discarded and never reach it.

Attachments are lost the same way: sending a photo and then "what is this?" inside the window reaches the model as a bare question with no image.

Expected behavior

The messages the concurrency strategy folded into this run are the sender's own words for this turn, not prior history. They should reach the model along with the message being answered, in the order they were sent, with their attachments.

Version: @cloudflare/think@0.19.0 (reproduces on main)

Additional context

I have a branch ready that:

  • adds skipped?: readonly ChatMessage[] to ChatSdkMessengerEventInput, oldest first
  • passes context?.skipped through from all three handlers
  • has defaultChatSdkEvent prepend the skipped text and attachments to the answered message, then run self-mention resolution over the combined text so a mention on a skipped line still resolves

A custom toEvent receives the same input and can fold them differently, or ignore the field to keep today's behaviour.

main...harryy2510:agents:fix/think-messenger-burst-skipped

Includes two tests (text folded oldest-first with self-mention resolution; attachments from a skipped message landing on the event) and a minor changeset, since it adds a field to a public input type. Validated with Node 24 / pnpm 11.9.0: full packages/think suite (45 files, 938 tests) passing, tsgo clean, oxlint 0/0, oxfmt --check clean, pnpm run build and pnpm run check:exports green.

I opened this as an issue because pull requests from forks appear to be disabled on this repo. Happy to submit it as a PR instead if that changes.

Metadata

Metadata

Assignees

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