mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-12 23:40:45 +00:00
fix(hooks): use resolveAgentIdFromSessionKey in runBeforeReset instead of split(":")[0]
Fixes workspace split-brain in multi-agent setups where /new or /reset
was writing session-memory artifacts into workspace-main instead of the bound agent's workspace (e.g. workspace-navi).
Session keys look like "agent:navi:main" so split(":")[0] returns
"agent" not "navi". resolveAgentIdFromSessionKey already exists and
handles this correctly.
Regression introduced in aec41a588b.
Closes #39816
This commit is contained in:
63
src/auto-reply/reply/commands-core.test.ts
Normal file
63
src/auto-reply/reply/commands-core.test.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { HookRunner } from "../../plugins/hooks.js";
|
||||
import type { HandleCommandsParams } from "./commands-types.js";
|
||||
|
||||
const hookRunnerMocks = vi.hoisted(() => ({
|
||||
hasHooks: vi.fn<HookRunner["hasHooks"]>(),
|
||||
runBeforeReset: vi.fn<HookRunner["runBeforeReset"]>(),
|
||||
}));
|
||||
|
||||
vi.mock("../../plugins/hook-runner-global.js", () => ({
|
||||
getGlobalHookRunner: () =>
|
||||
({
|
||||
hasHooks: hookRunnerMocks.hasHooks,
|
||||
runBeforeReset: hookRunnerMocks.runBeforeReset,
|
||||
}) as unknown as HookRunner,
|
||||
}));
|
||||
|
||||
const { emitResetCommandHooks } = await import("./commands-core.js");
|
||||
|
||||
describe("emitResetCommandHooks", () => {
|
||||
beforeEach(() => {
|
||||
hookRunnerMocks.hasHooks.mockReset();
|
||||
hookRunnerMocks.runBeforeReset.mockReset();
|
||||
hookRunnerMocks.hasHooks.mockImplementation((hookName) => hookName === "before_reset");
|
||||
hookRunnerMocks.runBeforeReset.mockResolvedValue(undefined);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it("passes the bound agent id to before_reset hooks for multi-agent session keys", async () => {
|
||||
const command = {
|
||||
surface: "discord",
|
||||
senderId: "rai",
|
||||
channel: "discord",
|
||||
from: "discord:rai",
|
||||
to: "discord:bot",
|
||||
resetHookTriggered: false,
|
||||
} as HandleCommandsParams["command"];
|
||||
|
||||
await emitResetCommandHooks({
|
||||
action: "new",
|
||||
ctx: {} as HandleCommandsParams["ctx"],
|
||||
cfg: {} as HandleCommandsParams["cfg"],
|
||||
command,
|
||||
sessionKey: "agent:navi:main",
|
||||
previousSessionEntry: {
|
||||
sessionId: "prev-session",
|
||||
} as HandleCommandsParams["previousSessionEntry"],
|
||||
workspaceDir: "/tmp/openclaw-workspace",
|
||||
});
|
||||
|
||||
await vi.waitFor(() => expect(hookRunnerMocks.runBeforeReset).toHaveBeenCalledTimes(1));
|
||||
const [, ctx] = hookRunnerMocks.runBeforeReset.mock.calls[0] ?? [];
|
||||
expect(ctx).toMatchObject({
|
||||
agentId: "navi",
|
||||
sessionKey: "agent:navi:main",
|
||||
sessionId: "prev-session",
|
||||
workspaceDir: "/tmp/openclaw-workspace",
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -3,7 +3,7 @@ import { resetAcpSessionInPlace } from "../../acp/persistent-bindings.js";
|
||||
import { logVerbose } from "../../globals.js";
|
||||
import { createInternalHookEvent, triggerInternalHook } from "../../hooks/internal-hooks.js";
|
||||
import { getGlobalHookRunner } from "../../plugins/hook-runner-global.js";
|
||||
import { isAcpSessionKey } from "../../routing/session-key.js";
|
||||
import { isAcpSessionKey, resolveAgentIdFromSessionKey } from "../../routing/session-key.js";
|
||||
import { resolveSendPolicy } from "../../sessions/send-policy.js";
|
||||
import { shouldHandleTextCommands } from "../commands-registry.js";
|
||||
import { handleAcpCommand } from "./commands-acp.js";
|
||||
@@ -120,7 +120,7 @@ export async function emitResetCommandHooks(params: {
|
||||
await hookRunner.runBeforeReset(
|
||||
{ sessionFile, messages, reason: params.action },
|
||||
{
|
||||
agentId: params.sessionKey?.split(":")[0] ?? "main",
|
||||
agentId: resolveAgentIdFromSessionKey(params.sessionKey),
|
||||
sessionKey: params.sessionKey,
|
||||
sessionId: prevEntry?.sessionId,
|
||||
workspaceDir: params.workspaceDir,
|
||||
|
||||
Reference in New Issue
Block a user