Split delivery pipeline into streaming/silent paths #38

Merged
weiwen merged 1 commit from sandcastle/issue-30 into main 2026-07-06 02:01:10 +08:00
Owner

Summary

Scheduled pushes were running through the same deliver_response pipeline as interactive messages, which sent a placeholder message, started a typing indicator, and streamed live edits — all inappropriate for a background scheduled push.

This PR splits the delivery pipeline into two distinct entry points sharing a common render_final tail:

  • deliver_streaming (interactive path): sends a placeholder immediately, starts a typing indicator, and streams pi snapshots to Telegram on a throttled cadence via MessageView. Renders a final authoritative pass on agent_end. Used by the Telegram message handler.
  • deliver_silent (scheduled path): passes a throwaway snapshot channel to session_manager.send_message (send failures on a dropped receiver are silently ignored, so pi.rs needed no changes), no placeholder, no typing indicator, no live edits. Renders into an empty MessageView so final pages arrive as fresh messages, not edits. Used by delivery_consumer.
  • render_final: extracted shared tail — paginates the result, edits the placeholder or sends fresh pages, attaches source buttons on the last page, or sends a plain error notice on failure.

Key decisions

  • MessageView::empty() was added as the silent-path seed so the existing reconcile logic works without modification — an empty ids vec causes every page to be sent fresh.
  • deliver_response (previously pub) is now two private functions; delivery_consumer is in the same module and needs no re-export.
  • No changes to pi.rs: the snapshot channel send already silently ignored errors on a dropped receiver, so passing a throwaway _rx is safe.

Reviewer checklist

  • Confirm deliver_silent really suppresses the typing indicator and placeholder in a live test or by reading the call sites
  • Confirm render_final correctly handles both a seeded view (streaming path) and an empty view (silent path)
  • Check that dropping _rx immediately after creation in deliver_silent does not race with send_message before the first snapshot would be sent

Closes #30

## Summary Scheduled pushes were running through the same `deliver_response` pipeline as interactive messages, which sent a placeholder message, started a typing indicator, and streamed live edits — all inappropriate for a background scheduled push. This PR splits the delivery pipeline into two distinct entry points sharing a common `render_final` tail: - **`deliver_streaming`** (interactive path): sends a placeholder immediately, starts a typing indicator, and streams `pi` snapshots to Telegram on a throttled cadence via `MessageView`. Renders a final authoritative pass on `agent_end`. Used by the Telegram message handler. - **`deliver_silent`** (scheduled path): passes a throwaway snapshot channel to `session_manager.send_message` (send failures on a dropped receiver are silently ignored, so `pi.rs` needed no changes), no placeholder, no typing indicator, no live edits. Renders into an empty `MessageView` so final pages arrive as fresh messages, not edits. Used by `delivery_consumer`. - **`render_final`**: extracted shared tail — paginates the result, edits the placeholder or sends fresh pages, attaches source buttons on the last page, or sends a plain error notice on failure. ### Key decisions - `MessageView::empty()` was added as the silent-path seed so the existing reconcile logic works without modification — an empty `ids` vec causes every page to be sent fresh. - `deliver_response` (previously `pub`) is now two private functions; `delivery_consumer` is in the same module and needs no re-export. - No changes to `pi.rs`: the snapshot channel send already silently ignored errors on a dropped receiver, so passing a throwaway `_rx` is safe. ### Reviewer checklist - [ ] Confirm `deliver_silent` really suppresses the typing indicator and placeholder in a live test or by reading the call sites - [ ] Confirm `render_final` correctly handles both a seeded view (streaming path) and an empty view (silent path) - [ ] Check that dropping `_rx` immediately after creation in `deliver_silent` does not race with `send_message` before the first snapshot would be sent Closes #30
Author
Owner

don’t use deliver silent. i just don’t want to send typing indicator when preparing the message. delivery_silent stops notifications

don’t use deliver silent. i just don’t want to send typing indicator when preparing the message. delivery_silent stops notifications
Author
Owner

Removed deliver_silent (which skipped sending the placeholder and therefore suppressed notifications). The scheduled path now calls deliver_streaming with typing_indicator=false — it still sends a placeholder immediately (triggering the notification), streams live edits, and renders the final result, but never starts the typing indicator.

Removed deliver_silent (which skipped sending the placeholder and therefore suppressed notifications). The scheduled path now calls deliver_streaming with typing_indicator=false — it still sends a placeholder immediately (triggering the notification), streams live edits, and renders the final result, but never starts the typing indicator.
weiwen force-pushed sandcastle/issue-30 from c954e710fb
Some checks failed
CI / check (pull_request) Has been cancelled
to 6ed7aa5ccb
Some checks failed
CI / check (pull_request) Has been cancelled
2026-07-06 01:43:15 +08:00
Compare
weiwen force-pushed sandcastle/issue-30 from 6ed7aa5ccb
Some checks failed
CI / check (pull_request) Has been cancelled
to c23efdb726
All checks were successful
CI / check (pull_request) Successful in 1m22s
PR Triage — label changes-requested reviews / triage-review (pull_request) Successful in 1s
2026-07-06 01:59:11 +08:00
Compare
weiwen merged commit dac7531122 into main 2026-07-06 02:01:10 +08:00
weiwen deleted branch sandcastle/issue-30 2026-07-06 02:01:10 +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!38
No description provided.