fix(bot): coalesce Telegram-split messages into a single prompt#180
fix(bot): coalesce Telegram-split messages into a single prompt#1808x22b wants to merge 3 commits into
Conversation
Telegram delivers long text (and a single paste) as several consecutive message updates, which the bot dispatched as separate prompts - one agent run per chunk. Buffer plain-text prompts per chat for MESSAGE_MERGE_WINDOW_MS (default 1500; 0 disables). Each new chunk restarts the window; when it elapses, buffered texts are joined and dispatched as one prompt. Commands and active interaction flows (question/task/rename/catalog) are unaffected.
|
@8x22b thanks for the PR! The core idea (debouncing Telegram-split chunks into one prompt) is solid, and the merger logic is nicely tested. A few things before I'd merge:
|
|
Thanks, addressed all five points. Short prompts now go straight through; only messages at least 4000 characters long open the merge window, while short follow-up chunks still join an active buffer. Pending text is flushed before slash commands and photo/document/voice/audio/media-group handling, both background prompt calls catch and log errors, and the README table is fixed. I added coverage for the new paths as well. Build, lint, and the full test suite (1119 tests) pass locally. I also merged the current main branch to resolve the PR conflicts. |
Problem
Telegram delivers long text — and a single paste — as several consecutive message updates (the ~4096-char client split, plus some clients splitting one input into multiple messages). The bot dispatches each update as its own prompt, so one long message becomes several independent agent runs and the conversation breaks.
Fix
Buffer plain-text prompts per chat for a short window (
MESSAGE_MERGE_WINDOW_MS, default1500;0disables). Each new chunk restarts the window; once it elapses with no new chunk, the buffered texts are joined (\n\n) and dispatched as a singlesession.prompt.Only the final plain-text fallback path is buffered. Commands and active interaction flows (question answers, task/model-search/rename input, command/skill arguments) keep being handled immediately and are never buffered.
Because the window restarts on every chunk, messages sent a few seconds apart are still processed independently.
Config
MESSAGE_MERGE_WINDOW_MS15000disables merging and processes every message immediatelyTradeoffs
\n\n. For a 4096-char split this adds one blank line per boundary (negligible in a long prompt); for genuinely separate quick messages it reads as separate paragraphs. Easy to change the separator if a maintainer prefers.Tests
New
tests/bot/handlers/message-merger.test.tscovers: disabled window (immediate), single buffered message, multi-chunk merge with window restart, gap-beyond-window flushes separately, per-chat independence, manualflushPendingPrompt, and latest ctx used on merge. The merger state is also reset intests/helpers/reset-singleton-state.tsso timers can't leak between tests.npm run lint,npm run build,npm test(1095 tests) pass. No OS-specific code.