[2/2] feat(eve): observe channel deliveries as session history - #3023
Open
Lukavyi wants to merge 3 commits into
Open
[2/2] feat(eve): observe channel deliveries as session history#3023Lukavyi wants to merge 3 commits into
Lukavyi wants to merge 3 commits into
Conversation
Contributor
|
@Lukavyi is attempting to deploy a commit to the Vercel Team on Vercel. A member of the Team first needs to authorize it. |
Lukavyi
force-pushed
the
telegram-observe-group-messages
branch
from
September 4, 2026 08:09
5a78fd5 to
330c225
Compare
Telegram group and supergroup inbound messages keyed the session to the bot message being replied to, or to the mention itself. Every fresh mention therefore started a new session with one message of context, while private chats already keep one continuous session per chat. Groups now key to the chat plus forum topic, the same way private chats do. Mentions, replies to bot messages, callback queries, and outbound sends all resume that session. The message_thread_id that non-forum supergroups stamp on replies is a reply chain, not a topic, and does not split the session. Proactive targets can still pin a thread through conversationId. Related to vercel#874 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015P6RBuagWTMzBmJLCiYKW9 Signed-off-by: Taras Lukavyi <lukavyi@me.com>
…orm prompt is pending A reply to a bot message went through respond() with only the synthetic telegram_reply:<id> response. When that id was not a registered freeform prompt, the adapter resolved nothing, returned undefined, and the session re-parked without a turn, so the reply was dropped. The initial channel sent the text as message on the same delivery; vercel#1597 replaced that with respond() and lost it. With chat-wide group sessions a reply to the bot is the natural follow-up, so carry the text as message again: the adapter still resolves a pending freeform answer first and otherwise runs the text as a normal turn. Pass state and title so a reply can start a session with a usable chat id when none owns the address. Also correct the TelegramReceiveTarget docstring: conversationId pins a caller-selected id that inbound messages never route to, and initialMessage no longer starts a separate thread in groups. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015P6RBuagWTMzBmJLCiYKW9 Signed-off-by: Taras Lukavyi <lukavyi@me.com>
A group bot only ever sees the messages that address it, so even with one session per chat it cannot follow the conversation that happens between mentions. Slack has threadContext for this; Telegram had nothing. Add observe: true to channel deliveries. An observed delivery appends its message and context to the session as history without running a turn: eve buffers it on the parked or active session, never steers, never starts a session, and folds the buffered messages in arrival order into the next delivery that does run a turn. The observed backlog is capped at 256 payloads, oldest dropped first. Task deliveries settle on their own and leave observed history waiting for a channel turn. The Telegram channel exposes it as observe on the onMessage result and exports isTelegramBotMentioned so hosts can gate on it. Related to vercel#874 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015P6RBuagWTMzBmJLCiYKW9 Signed-off-by: Taras Lukavyi <lukavyi@me.com>
Lukavyi
force-pushed
the
telegram-observe-group-messages
branch
from
September 4, 2026 08:10
330c225 to
98a3ecb
Compare
Lukavyi
marked this pull request as ready for review
September 4, 2026 08:18
This was referenced Sep 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A group bot only ever sees the messages that address it. Even with one session per chat (#3020), it cannot follow the conversation that happens between mentions, so "@bot, what do you think about what U1 just said?" has nothing to work with. Slack has
threadContextfor this; Telegram had no equivalent, and the dispatch gate drops unaddressed messages before they reach a session (#874, second half).This adds
observe: trueto channel deliveries, a channel-agnostic primitive:messageandcontextto the session as history without running a turn. eve buffers it on the session, parked or mid-turn, and folds the buffered messages in arrival order into the next delivery that does run a turn, so the model sees them as part of that turn's input (this rides on the coalescing fixed in coalesceDeliverPayloads silently drops earlier messages in a batched delivery (last-key-wins for message/context) #897).turnPolicyis not applied) and never starts a session: with no owner for the address it throwsRuntimeNoActiveSessionError, which the Telegram channel logs at debug and drops.observeon theonMessageresult.isTelegramBotMentionedis now exported so a customonMessagecan gate on it; the docs carry the four-line example. Telegram only delivers unaddressed group messages with privacy mode off or the bot as admin, noted in the docs rather than enforced.SendPayloadgains a field, so the channel extension contract moves to epoch 18 (structurally backward compatible, epoch 17 retained).We have run this shape as a
patchedDependenciespatch in production on two group bots since July; the acceptance scenario from #874 (untagged question, later a mention, answer with that context) passes there.Related to #874, #897, #223 (Slack: the same
observegate would let a SlackonMessagefollow a thread without mentions).Validation
New coverage:
coalesceDeliverPayloadskeepsobserveonly when every payload was observed;bufferObservedDeliverybuffers observe-only deliveries, leaves addressed ones to the caller, and drops the oldest past the cap; a parked session stays parked on observed deliveries and coalesces them ahead of the next addressed one; buffered observed deliveries alone do not wake it; a task delivery runs without them; the turn receiver buffers observed deliveries without steering or forwarding; the Telegram channel delivers anobserveresult as history with the<telegram_context>block and a mention without it.Checklist
CONTRIBUTING.mdevepackagegit commit --signoff)🤖 Generated with Claude Code
https://claude.ai/code/session_015P6RBuagWTMzBmJLCiYKW9