fix(outbound): thread sessionKey into message_sending hook context#19
Closed
zeroaltitude wants to merge 1 commit intomainfrom
Closed
fix(outbound): thread sessionKey into message_sending hook context#19zeroaltitude wants to merge 1 commit intomainfrom
zeroaltitude wants to merge 1 commit intomainfrom
Conversation
The outbound delivery path in applyMessageSendingHook constructed a
PluginHookMessageContext containing only { channelId, accountId,
conversationId } and dropped the sessionKey that the surrounding
deliverOutboundPayloads scope already had as
sessionKeyForInternalHooks. Plugins receiving message_sending therefore
saw ctx.sessionKey === undefined for every reply.
This breaks any plugin that needs to correlate a per-turn signal
emitted in agent_end with the matching outbound delivery in
message_sending. The concrete observed regression is the
openclaw-provenance developer-mode taint footer: agent_end populates a
finalTaintBySession map keyed by sessionKey, and message_sending looks
it up by sessionKey before appending the footer. With the key missing
on the message_sending side, the lookup always returned undefined and
no footer was ever appended.
PluginHookMessageContext already declares sessionKey?: string and the
auto-reply dispatch path in src/auto-reply/dispatch.ts already
threads it through deriveInboundMessageHookContext +
toPluginMessageContext. This change brings deliver.ts in line.
- applyMessageSendingHook now takes an optional sessionKey and forwards
it on the runMessageSending context.
- The single caller in deliverOutboundPayloads passes
sessionKeyForInternalHooks, which is already resolved earlier in the
function from params.mirror?.sessionKey ?? params.session?.key.
- Two new unit tests cover the present-and-absent cases.
Closes the deliver.ts side of the agent_end → message_sending
correlation gap. No behavior change for plugins that don't read
ctx.sessionKey.
Owner
Author
|
Re-targeted upstream as openclaw#73706. |
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.
What
Thread
sessionKeyinto thePluginHookMessageContextpassed torunMessageSendingfrom the outbound delivery path.Why
applyMessageSendingHookinsrc/infra/outbound/deliver.tsconstructed the hook context with only{ channelId, accountId, conversationId }and dropped thesessionKeythatdeliverOutboundPayloadsalready had in scope assessionKeyForInternalHooks(resolved at line 950 fromparams.mirror?.sessionKey ?? params.session?.key).PluginHookMessageContextalready declaressessionKey?: string, and the inboundauto-reply/dispatch.tspath already populates it viaderiveInboundMessageHookContext→toPluginMessageContext. This brings the outbound deliver path in line with the type contract and the inbound dispatch path.Concrete regression observed
openclaw-provenancecorrelates a per-turn signal across two hooks:agent_endwrites tofinalTaintBySession.set(sessionKey, …)so the developer-mode footer payload survives until delivery.message_sendingdoesfinalTaintBySession.get(sessionKey)and appends the footer to outbound content.With
sessionKeymissing on themessage_sendingside, the handler fell back to"unknown"and the lookup always missed, so the developer-mode taint trajectory footer never appeared on outbound replies. Confirmed in the live gateway log onintegration:agent_endfires per turn butfinalTaintBySession.getreturnsundefinedin everymessage_sendinginvocation.Change
applyMessageSendingHookaccepts an optionalsessionKey.deliverOutboundPayloadspassessessionKeyForInternalHooks.deliver.test.tscover the present-and-absent cases.Tests
pnpm test src/infra/outbound/deliver.test.ts→ 55/55 passing (53 prior + 2 new).Risk
Low. Additive only — the field is optional in the type, no plugins currently rely on it being absent. The inbound dispatch path was already passing
sessionKey; this aligns the outbound path with that existing behavior.