feat(telegram): debounce Message Burst into a single turn #52

Merged
weiwen merged 1 commit from sandcastle/issue-51 into main 2026-07-06 23:24:51 +08:00
Owner

Summary

  • Adds a trailing 500 ms per-chat debounce buffer in front of deliver_streaming so Telegram's split-paste fragments (and album photos) are collated into one pi turn instead of each one aborting the previous
  • collect_burst accumulates messages until the channel is quiet for 500 ms; merge_burst joins text parts with \n\n and concatenates images; burst_task spawns (not awaits) deliver_streaming so mid-stream interrupts remain prompt (~500 ms latency) rather than waiting for the entire turn to finish
  • 10 new unit tests covering merge_burst and collect_burst (including tokio time-controlled debounce timer tests); 125 total, 0 failed

Key decisions

  • 500 ms hardcoded: tracks Telegram client timing, not a user preference (per ADR 0005)
  • \n\n join: simpler than 4096-boundary heuristic; revisit if pasted-code mangling proves annoying
  • spawn, not await: burst_task spawns each deliver_streaming call so new bursts can interrupt the in-flight turn within the debounce window

Test plan

  • just check passes (125 tests, 0 failures)
  • merge_burst pure-function table tests: single message, \n\n join, empty-text filter, image concat
  • collect_burst timing tests: channel-close flush, debounce timer fires, timer resets within window

Closes #51

🤖 Generated with Claude Code

## Summary - Adds a trailing 500 ms per-chat debounce buffer in front of `deliver_streaming` so Telegram's split-paste fragments (and album photos) are collated into one pi turn instead of each one aborting the previous - `collect_burst` accumulates messages until the channel is quiet for 500 ms; `merge_burst` joins text parts with `\n\n` and concatenates images; `burst_task` spawns (not awaits) `deliver_streaming` so mid-stream interrupts remain prompt (~500 ms latency) rather than waiting for the entire turn to finish - 10 new unit tests covering `merge_burst` and `collect_burst` (including tokio time-controlled debounce timer tests); 125 total, 0 failed ## Key decisions - **500 ms hardcoded**: tracks Telegram client timing, not a user preference (per ADR 0005) - **`\n\n` join**: simpler than 4096-boundary heuristic; revisit if pasted-code mangling proves annoying - **spawn, not await**: `burst_task` spawns each `deliver_streaming` call so new bursts can interrupt the in-flight turn within the debounce window ## Test plan - [x] `just check` passes (125 tests, 0 failures) - [x] `merge_burst` pure-function table tests: single message, `\n\n` join, empty-text filter, image concat - [x] `collect_burst` timing tests: channel-close flush, debounce timer fires, timer resets within window Closes #51 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(telegram): debounce Message Burst into a single turn (#51)
All checks were successful
CI / check (pull_request) Successful in 1m31s
PR Triage — label changes-requested reviews / triage-review (pull_request) Successful in 1s
e4e7f916f9
Implements a trailing 500 ms per-chat debounce in front of the
interactive delivery path so Telegram's split-paste fragments are
collated into one pi turn rather than each one aborting the last.

Architecture:
- `BurstRegistry` (per-chat `mpsc` sender map) routes incoming messages
  to a long-lived `burst_task` for each chat
- `collect_burst` accumulates messages until the channel is quiet for
  500 ms (trailing debounce), returning them as a slice
- `merge_burst` joins text parts with `\n\n` and concatenates images
- `burst_task` spawns (not awaits) `deliver_streaming` so new bursts
  can arrive and abort the in-flight turn without waiting for streaming
- `handle_message` now sends to the burst buffer instead of calling
  `deliver_streaming` directly; burst task is lazily created on first
  message per chat

Key decisions:
- 500 ms hardcoded (tracks Telegram client timing, not user preference)
- Spawn deliver tasks non-blocking so mid-stream interrupts remain ~500 ms
- `\n\n` join (vs 4096-boundary heuristic): simpler; revisit if pasted
  code mangling proves annoying in practice
- Added `PartialEq` to `ImageContent` for testability

Tests: 10 new unit tests covering `merge_burst` (text join, empty
filter, image concat) and `collect_burst` (channel-close, debounce
timer, timer reset). 125 total, 0 failed.

Closes #51

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
weiwen merged commit 8e19563eff into main 2026-07-06 23:24:51 +08:00
weiwen deleted branch sandcastle/issue-51 2026-07-06 23:24:51 +08:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
weiwen/evie!52
No description provided.