mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-01 15:15:09 +00:00
Thread the canonical outbound session key into plugin message_sending and message_sent hook contexts, and align native command redirect routed delivery with the agent runtime session key. This lets plugins correlate agent_end with outbound delivery hooks without seeing missing or divergent session keys. Verification: - gh pr checks 73706 --repo openclaw/openclaw --watch=false - Real behavior proof: https://github.com/openclaw/openclaw/actions/runs/26526635074/job/78131933497 Thanks @zeroaltitude. Co-authored-by: Edward Abrams <zeroaltitude@gmail.com>
132 lines
4.1 KiB
TypeScript
132 lines
4.1 KiB
TypeScript
import type { DiagnosticTraceContext } from "../infra/diagnostic-trace-context.js";
|
|
import type { PluginConversationBinding } from "./conversation-binding.types.js";
|
|
|
|
export type PluginHookMessageContext = {
|
|
channelId: string;
|
|
accountId?: string;
|
|
conversationId?: string;
|
|
/**
|
|
* Canonical session key for this conversation — the same value the agent
|
|
* runtime sees as `params.sessionKey` for the run that produced the
|
|
* outbound payload, and the same value `agent_end`/`llm_input`/`llm_output`
|
|
* fire with. Plugins correlating per-turn state across `agent_end` and
|
|
* `message_sending` rely on this equality.
|
|
*
|
|
* For inbound message hooks (`inbound_claim` etc.), this is the canonical
|
|
* session for the inbound conversation as resolved by `resolveSessionKey`
|
|
* / `deriveInboundMessageHookContext`.
|
|
*
|
|
* For outbound delivery hooks (`message_sending` and `message_sent`),
|
|
* this mirrors `OutboundSessionContext.key` from the dispatch path when
|
|
* delivery has a session attached. When the outbound path has no
|
|
* resolvable session (e.g. internal smoke runs without
|
|
* `OutboundSessionContext`), this field is omitted; plugins must treat
|
|
* it as optional.
|
|
*/
|
|
sessionKey?: string;
|
|
/**
|
|
* Per-turn run identifier (UUID), unique to one end-to-end agent turn:
|
|
* stable across all LLM-call iterations, retry attempts (compaction,
|
|
* empty-response, planning-only, etc.), and multi-payload reply chunks
|
|
* within that turn; distinct for each new inbound user message and for
|
|
* each cron/heartbeat/followup-triggered run.
|
|
*
|
|
* Generated once in `agent-runner-execution.ts`/`followup-runner.ts` via
|
|
* `crypto.randomUUID()`. Currently populated for inbound message hooks
|
|
* (`inbound_claim`, `message_received`) and for agent-runtime hooks that
|
|
* already receive the run id (e.g. `agent_end`, `llm_input`, `llm_output`).
|
|
* It is **not yet** plumbed through the outbound delivery path, so
|
|
* plugins observing `message_sending` / `message_sent` should not rely
|
|
* on `runId` to correlate against `agent_end`; use `sessionKey` for
|
|
* outbound→inbound correlation today (with the caveat that it cannot
|
|
* disambiguate concurrent turns in the same session).
|
|
*/
|
|
runId?: string;
|
|
messageId?: string;
|
|
senderId?: string;
|
|
trace?: DiagnosticTraceContext;
|
|
traceId?: string;
|
|
spanId?: string;
|
|
parentSpanId?: string;
|
|
callDepth?: number;
|
|
};
|
|
|
|
export type PluginHookInboundClaimContext = PluginHookMessageContext & {
|
|
parentConversationId?: string;
|
|
senderId?: string;
|
|
messageId?: string;
|
|
pluginBinding?: PluginConversationBinding;
|
|
};
|
|
|
|
export type PluginHookInboundClaimEvent = {
|
|
content: string;
|
|
body?: string;
|
|
bodyForAgent?: string;
|
|
transcript?: string;
|
|
timestamp?: number;
|
|
channel: string;
|
|
accountId?: string;
|
|
conversationId?: string;
|
|
parentConversationId?: string;
|
|
senderId?: string;
|
|
senderName?: string;
|
|
senderUsername?: string;
|
|
threadId?: string | number;
|
|
messageId?: string;
|
|
sessionKey?: string;
|
|
runId?: string;
|
|
trace?: DiagnosticTraceContext;
|
|
traceId?: string;
|
|
spanId?: string;
|
|
parentSpanId?: string;
|
|
isGroup: boolean;
|
|
commandAuthorized?: boolean;
|
|
wasMentioned?: boolean;
|
|
metadata?: Record<string, unknown>;
|
|
};
|
|
|
|
export type PluginHookMessageReceivedEvent = {
|
|
from: string;
|
|
content: string;
|
|
timestamp?: number;
|
|
threadId?: string | number;
|
|
messageId?: string;
|
|
senderId?: string;
|
|
sessionKey?: string;
|
|
runId?: string;
|
|
trace?: DiagnosticTraceContext;
|
|
traceId?: string;
|
|
spanId?: string;
|
|
parentSpanId?: string;
|
|
metadata?: Record<string, unknown>;
|
|
};
|
|
|
|
export type PluginHookMessageSendingEvent = {
|
|
to: string;
|
|
content: string;
|
|
replyToId?: string | number;
|
|
threadId?: string | number;
|
|
metadata?: Record<string, unknown>;
|
|
};
|
|
|
|
export type PluginHookMessageSendingResult = {
|
|
content?: string;
|
|
cancel?: boolean;
|
|
cancelReason?: string;
|
|
metadata?: Record<string, unknown>;
|
|
};
|
|
|
|
export type PluginHookMessageSentEvent = {
|
|
to: string;
|
|
content: string;
|
|
success: boolean;
|
|
messageId?: string;
|
|
sessionKey?: string;
|
|
runId?: string;
|
|
trace?: DiagnosticTraceContext;
|
|
traceId?: string;
|
|
spanId?: string;
|
|
parentSpanId?: string;
|
|
error?: string;
|
|
};
|