feat(plugins): carry the delivery target on stream observer payloads - #90367
feat(plugins): carry the delivery target on stream observer payloads#90367CocaKova wants to merge 1 commit into
Conversation
Reviewed by reviewer-e (AI automated review). Well-reasoned payload extension: routing streamed tokens to the right conversation genuinely is a different question than which stored history a turn extends, and Nit (non-blocking): hermes_cli/plugins.py:170 — the base-payload field list is now hand-maintained prose in the hook registry comment, duplicated against |
The stream observer hooks identify a turn by session_id, which answers which stored history it extends — not which conversation it is being delivered to. One gateway serves many chats concurrently, so a plugin that mirrors a turn's tokens somewhere per-chat (a second client, a protocol bridge, a web view) has no way to route them, and ends up needing core patches to recover an identity the agent already holds. _stream_hook_base_payload now carries chat_id, chat_type and thread_id alongside surface, so the target is (surface, chat_id) — the same pair the gateway keys a chat on. The values come from the _chat_id/_chat_type/ _thread_id attributes agent_init already sets for gateway sessions; defensive getattr with "" defaults, so a CLI turn reports no chat rather than omitting the keys and making consumers guess. on_interim_message is folded onto the same base payload: a consumer routing deltas by chat should not find the identity present there and missing on interim messages. That also picks up turn_id and iteration, which it was building by hand. Payload and target semantics are documented at _stream_hook_base_payload; the VALID_HOOKS comment points there rather than duplicating the field list. Real consumer is a standalone gateway side-channel plugin that streams a turn into the Matrix room it came from; without the target it cannot tell two rooms apart. Tests: 2 added, 14 passing in tests/run_agent/test_plugin_stream_hooks.py
b6196e8 to
d29d869
Compare
|
Addressed the nit in d29d869: the VALID_HOOKS comment no longer enumerates the base payload fields — it points at |
The gap
on_stream_start/on_stream_delta/on_stream_end/on_interim_messageidentify a turn bysession_id. That answers which stored history does this extend — not which conversation is this being delivered to.One gateway serves many chats at once. A plugin that mirrors a turn's tokens somewhere per-chat — a second client, a protocol bridge, a web view — receives every delta of every concurrent turn with no way to tell them apart, and has to patch core to recover an identity the agent is already holding.
The change
_stream_hook_base_payload()gainschat_id,chat_typeandthread_idnext to the existingsurface, so the delivery target is(surface, chat_id)— the same pair the gateway keys a chat on._chat_id/_chat_type/_thread_idattributesagent_initalready sets for gateway sessions. Nothing new is plumbed.getattrwith""defaults: a CLI turn reports no chat rather than omitting the keys and making consumers guess.on_interim_messageis folded onto the same base payload instead of hand-building its half of it. A consumer routing deltas by chat should not find the identity present on its deltas and missing on its interim messages; it also picks upturn_idanditerationfor free.VALID_HOOKScomment block.Observer-only, off the token path, no behaviour change for anything that ignores the new keys.
Consumer
A standalone gateway side-channel plugin that streams a turn into the Matrix room it came from, so a phone client can render tokens live without the homeserver taking an
m.replaceedit per tick. Without the target it cannot tell two rooms apart. It ships separately, per the plugin policy.Relationship to #90077
Independent and adjacent — that one adds
usagetoon_stream_end, this one adds the target to the shared base payload. They touch the same file and the same test module, so whichever lands second will want a trivial rebase. Together they are what lets that plugin stop being a core patch.Tests
2 added, 14 passing in
tests/run_agent/test_plugin_stream_hooks.py.tests/hermes_cli/test_plugins.pyalso green (64 passing).(Supersedes #90310 — identical commit, reopened from a correctly-named branch. Renaming the head branch on the fork closed the original.)