Files
openclaw/src/agents/openclaw-tools.plugin-context.test.ts
Vincent Koc 0954b6bf5f 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>
2026-03-02 15:11:51 -08:00

51 lines
1.4 KiB
TypeScript

import { describe, expect, it, vi } from "vitest";
const { resolvePluginToolsMock } = vi.hoisted(() => ({
resolvePluginToolsMock: vi.fn((params?: unknown) => {
void params;
return [];
}),
}));
vi.mock("../plugins/tools.js", () => ({
resolvePluginTools: resolvePluginToolsMock,
}));
import { createOpenClawTools } from "./openclaw-tools.js";
describe("createOpenClawTools plugin context", () => {
it("forwards trusted requester sender identity to plugin tool context", () => {
createOpenClawTools({
config: {} as never,
requesterSenderId: "trusted-sender",
senderIsOwner: true,
});
expect(resolvePluginToolsMock).toHaveBeenCalledWith(
expect.objectContaining({
context: expect.objectContaining({
requesterSenderId: "trusted-sender",
senderIsOwner: true,
}),
}),
);
});
it("forwards ephemeral sessionId to plugin tool context", () => {
createOpenClawTools({
config: {} as never,
agentSessionKey: "agent:main:telegram:direct:12345",
sessionId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
});
expect(resolvePluginToolsMock).toHaveBeenCalledWith(
expect.objectContaining({
context: expect.objectContaining({
sessionKey: "agent:main:telegram:direct:12345",
sessionId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
}),
}),
);
});
});