feat(gateway): Telegram session-picker with inline resume buttons and recap context - #75469
Conversation
… recap context Adds inline choice buttons for Telegram DM session listing with per-session resume recaps showing last user message, assistant response, and age. Improves the mobile session-resume UX by keeping context visible before the user commits to resuming a session. - _format_telegram_sessions_picker: renders numbered context above narrow mobile-safe buttons with per-session latest-user-message excerpts - _format_telegram_resume_recap: adds visible 'Where you left off' context after a picker-triggered resume - _resume_recap_snippet / _resume_recap_age / _latest_user_context helpers - Integration in /sessions command: Telegram DMs get the inline picker path (chat_type=dm guard preserves session ownership boundary) - Adapter patch: pass metadata through send_choice_picker for thread routing - Tests: exercise picker formatting, recap age rendering, and user-context extraction with reply-quotation stripping
teknium1
left a comment
There was a problem hiding this comment.
Thanks for the Telegram DM resume UX improvement. The feature addresses a current gap: main still returns the text session listing at gateway/slash_commands.py:4525-4529.
Problems
- The resume picker is unsafe to reuse through the current generic Telegram picker state. The adapter stores one state object per chat at
plugins/platforms/telegram/adapter.py:5664-5668, but resolvescp:<index>from that current state atplugins/platforms/telegram/adapter.py:5700-5711without checking the callback message id. After a user opens a second/sessionspicker, tapping a button on the first visible message can resume the session at the matching index from the newer picker. - The new tests mock
send_choice_picker(tests/gateway/test_resume_command.py:106-108) and directly invoke the closure, so they do not cover the Telegram callback/state-replacement path.
Suggested changes
- Bind picker state to the sent message id or a callback token and reject stale-message callbacks before invoking the resume closure registered at
gateway/slash_commands.py:4701. - Add a regression test for two pickers in one chat followed by a tap on the first message.
This is an automated hermes-sweeper review.
| ), | ||
| choices=choices, | ||
| session_key=current_entry.session_key, | ||
| on_choice_selected=_resume_from_picker, |
There was a problem hiding this comment.
This registers a session-switching closure in the generic picker, but Telegram keeps only one _choice_picker_state[chat_id]. Its callback handler does not validate state['msg_id'] against the clicked message, so after a second /sessions picker replaces state, a tap on the older visible picker resolves an index from the newer list and can resume the wrong session. Bind state to the picker message/token and reject stale callbacks; add a two-picker regression test.
…s-talk
Previously _choice_picker_state was keyed by chat_id alone, so opening a
second picker in the same chat overwrote the first picker's state. Tapping
a button on the first (still-visible) message would then resolve from the
second picker's indices — a wrong session could resume.
Now keyed as chat_id:message_id, so each picker message carries its own
isolated state. Stale-message callbacks whose state has been cleaned up
receive the 'Picker expired' answer instead of resolving from a newer
picker's closure.
- send_choice_picker: key on f"{chat_id}:{msg.message_id}"
- _handle_choice_picker_callback: resolve state_key from query.message.message_id
- Regression test: two pickers, same chat, verify independent closures
SummaryFive PRs address the Telegram session-navigation UX gap: #33702 and #33725 target a button-based bare Related pull requests
Duplicates#33725 is the empty scoped resubmission of #33702. #43695 and #49038 substantially overlap with #75469 on Telegram inline session selection and are superseded by its current-plugin, DM-scoped, message-bound approach; #33702 is an earlier Suggested consolidationKeep #75469 open with a salvage path: retain its contextual Telegram-DM picker, existing Cross-PR triage: Reviewed 5 pull requests and 0 issues in this complex. Each diff was read against this issue; Assessment working set: 81 kB of PR diffs, 7 kB of issue/PR text, 5 kB of discussion (5 comments), 0 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch. |
What
Adds inline choice buttons for Telegram DM session listing (
/sessionsand/sessions all) with per-session resume recaps showing last user message, assistant response, and age. Improves the mobile session-resume UX by keeping context visible before the user commits to resuming a session.Changes
_format_telegram_sessions_picker— renders numbered context above narrow mobile-safe buttons with per-session latest-user-message excerpts_format_telegram_resume_recap— adds visible 'Where you left off' context after a picker-triggered resume, showing last user question + where the assistant left off_resume_recap_snippet/_resume_recap_age/_latest_user_context— compact helpers for excerpt formatting, relative timestamps, and reply-quotation stripping/sessionscommand — Telegram DMs get the inline picker path (guarded bychat_type == "dm"to preserve the session-ownership boundary; group chats and non-Telegram platforms keep the existing text listing)metadatathroughsend_choice_pickerfor correct thread routingWhy
Currently,
/sessionson Telegram returns a dense text list. In a DM, the user has to copy a session ID and paste it into/resume <id>. The inline picker replaces that with numbered context + tap-to-resume buttons — the same number of taps but with context the user can read before committing.Scope
Telegram DMs only — the
chat_type == "dm"guard keeps session-ownership boundaries intact. Other platforms and group chats are unaffected.