mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-25 16:12:13 +00:00
fix(hooks): propagate ephemeral sessionId through embedded tool contexts (#32273)
* fix(plugins): expose ephemeral sessionId in tool contexts for per-conversation isolation The plugin tool context (`OpenClawPluginToolContext`) and tool hook context (`PluginHookToolContext`) only provided `sessionKey`, which is a durable channel identifier that survives /new and /reset. Plugins like mem0 that need per-conversation isolation (e.g. mapping Mem0 `run_id`) had no way to distinguish between conversations, causing session-scoped memories to persist unbounded across resets. Add `sessionId` (ephemeral UUID regenerated on /new and /reset) to: - `OpenClawPluginToolContext` (factory context for plugin tools) - `PluginHookToolContext` (before_tool_call / after_tool_call hooks) - Internal `HookContext` for tool call wrappers Thread the value from the run attempt through createOpenClawCodingTools → createOpenClawTools → resolvePluginTools and through the tool hook wrapper. Closes #31253 Made-with: Cursor * fix(agents): propagate embedded sessionId through tool hook context * test(hooks): cover sessionId in embedded tool hook contexts * docs(changelog): add sessionId hook context follow-up note * test(hooks): avoid toolCallId collision in after_tool_call e2e --------- Co-authored-by: SidQin-cyber <sidqin0410@gmail.com>
This commit is contained in:
@@ -61,6 +61,8 @@ export type OpenClawPluginToolContext = {
|
||||
agentDir?: string;
|
||||
agentId?: string;
|
||||
sessionKey?: string;
|
||||
/** Ephemeral session UUID — regenerated on /new and /reset. Use for per-conversation isolation. */
|
||||
sessionId?: string;
|
||||
messageChannel?: string;
|
||||
agentAccountId?: string;
|
||||
/** Trusted sender id from inbound context (runtime-provided, not tool args). */
|
||||
@@ -482,6 +484,8 @@ export type PluginHookMessageSentEvent = {
|
||||
export type PluginHookToolContext = {
|
||||
agentId?: string;
|
||||
sessionKey?: string;
|
||||
/** Ephemeral session UUID — regenerated on /new and /reset. */
|
||||
sessionId?: string;
|
||||
toolName: string;
|
||||
};
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ vi.mock("../infra/agent-events.js", () => ({
|
||||
function createToolHandlerCtx(params: {
|
||||
runId: string;
|
||||
sessionKey?: string;
|
||||
sessionId?: string;
|
||||
agentId?: string;
|
||||
onBlockReplyFlush?: unknown;
|
||||
}) {
|
||||
@@ -32,6 +33,7 @@ function createToolHandlerCtx(params: {
|
||||
session: { messages: [] },
|
||||
agentId: params.agentId,
|
||||
sessionKey: params.sessionKey,
|
||||
sessionId: params.sessionId,
|
||||
onBlockReplyFlush: params.onBlockReplyFlush,
|
||||
},
|
||||
state: {
|
||||
@@ -83,6 +85,7 @@ describe("after_tool_call hook wiring", () => {
|
||||
runId: "test-run-1",
|
||||
agentId: "main",
|
||||
sessionKey: "test-session",
|
||||
sessionId: "test-ephemeral-session",
|
||||
});
|
||||
|
||||
await handleToolExecutionStart(
|
||||
@@ -90,7 +93,7 @@ describe("after_tool_call hook wiring", () => {
|
||||
{
|
||||
type: "tool_execution_start",
|
||||
toolName: "read",
|
||||
toolCallId: "call-1",
|
||||
toolCallId: "wired-hook-call-1",
|
||||
args: { path: "/tmp/file.txt" },
|
||||
} as never,
|
||||
);
|
||||
@@ -100,7 +103,7 @@ describe("after_tool_call hook wiring", () => {
|
||||
{
|
||||
type: "tool_execution_end",
|
||||
toolName: "read",
|
||||
toolCallId: "call-1",
|
||||
toolCallId: "wired-hook-call-1",
|
||||
isError: false,
|
||||
result: { content: [{ type: "text", text: "file contents" }] },
|
||||
} as never,
|
||||
@@ -115,7 +118,7 @@ describe("after_tool_call hook wiring", () => {
|
||||
| { toolName?: string; params?: unknown; error?: unknown; durationMs?: unknown }
|
||||
| undefined;
|
||||
const context = firstCall?.[1] as
|
||||
| { toolName?: string; agentId?: string; sessionKey?: string }
|
||||
| { toolName?: string; agentId?: string; sessionKey?: string; sessionId?: string }
|
||||
| undefined;
|
||||
expect(event).toBeDefined();
|
||||
expect(context).toBeDefined();
|
||||
@@ -129,6 +132,7 @@ describe("after_tool_call hook wiring", () => {
|
||||
expect(context.toolName).toBe("read");
|
||||
expect(context.agentId).toBe("main");
|
||||
expect(context.sessionKey).toBe("test-session");
|
||||
expect(context.sessionId).toBe("test-ephemeral-session");
|
||||
});
|
||||
|
||||
it("includes error in after_tool_call event on tool failure", async () => {
|
||||
|
||||
Reference in New Issue
Block a user