mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-07 23:21:23 +00:00
refactor(agents): dedupe plugin hooks and test helpers
This commit is contained in:
@@ -37,6 +37,15 @@ function makeEvent(overrides?: Partial<InternalHookEvent>): InternalHookEvent {
|
||||
}
|
||||
|
||||
describe("boot-md handler", () => {
|
||||
function setupTwoAgentBootConfig() {
|
||||
const cfg = { agents: { list: [{ id: "main" }, { id: "ops" }] } };
|
||||
listAgentIds.mockReturnValue(["main", "ops"]);
|
||||
resolveAgentWorkspaceDir.mockImplementation((_cfg: unknown, id: string) =>
|
||||
id === "main" ? MAIN_WORKSPACE_DIR : OPS_WORKSPACE_DIR,
|
||||
);
|
||||
return cfg;
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
logWarn.mockReset();
|
||||
@@ -59,11 +68,7 @@ describe("boot-md handler", () => {
|
||||
});
|
||||
|
||||
it("runs boot for each agent", async () => {
|
||||
const cfg = { agents: { list: [{ id: "main" }, { id: "ops" }] } };
|
||||
listAgentIds.mockReturnValue(["main", "ops"]);
|
||||
resolveAgentWorkspaceDir.mockImplementation((_cfg: unknown, id: string) =>
|
||||
id === "main" ? MAIN_WORKSPACE_DIR : OPS_WORKSPACE_DIR,
|
||||
);
|
||||
const cfg = setupTwoAgentBootConfig();
|
||||
runBootOnce.mockResolvedValue({ status: "ran" });
|
||||
|
||||
await runBootChecklist(makeEvent({ context: { cfg } }));
|
||||
@@ -93,11 +98,7 @@ describe("boot-md handler", () => {
|
||||
});
|
||||
|
||||
it("logs warning details when a per-agent boot run fails", async () => {
|
||||
const cfg = { agents: { list: [{ id: "main" }, { id: "ops" }] } };
|
||||
listAgentIds.mockReturnValue(["main", "ops"]);
|
||||
resolveAgentWorkspaceDir.mockImplementation((_cfg: unknown, id: string) =>
|
||||
id === "main" ? MAIN_WORKSPACE_DIR : OPS_WORKSPACE_DIR,
|
||||
);
|
||||
const cfg = setupTwoAgentBootConfig();
|
||||
runBootOnce
|
||||
.mockResolvedValueOnce({ status: "ran" })
|
||||
.mockResolvedValueOnce({ status: "failed", reason: "agent failed" });
|
||||
|
||||
@@ -114,6 +114,25 @@ function makeSessionMemoryConfig(tempDir: string, messages?: number): OpenClawCo
|
||||
} satisfies OpenClawConfig;
|
||||
}
|
||||
|
||||
async function createSessionMemoryWorkspace(params?: {
|
||||
activeSession?: { name: string; content: string };
|
||||
}): Promise<{ tempDir: string; sessionsDir: string; activeSessionFile?: string }> {
|
||||
const tempDir = await makeTempWorkspace("openclaw-session-memory-");
|
||||
const sessionsDir = path.join(tempDir, "sessions");
|
||||
await fs.mkdir(sessionsDir, { recursive: true });
|
||||
|
||||
if (!params?.activeSession) {
|
||||
return { tempDir, sessionsDir };
|
||||
}
|
||||
|
||||
const activeSessionFile = await writeWorkspaceFile({
|
||||
dir: sessionsDir,
|
||||
name: params.activeSession.name,
|
||||
content: params.activeSession.content,
|
||||
});
|
||||
return { tempDir, sessionsDir, activeSessionFile };
|
||||
}
|
||||
|
||||
describe("session-memory hook", () => {
|
||||
it("skips non-command events", async () => {
|
||||
const tempDir = await makeTempWorkspace("openclaw-session-memory-");
|
||||
@@ -289,14 +308,8 @@ describe("session-memory hook", () => {
|
||||
});
|
||||
|
||||
it("falls back to latest .jsonl.reset.* transcript when active file is empty", async () => {
|
||||
const tempDir = await makeTempWorkspace("openclaw-session-memory-");
|
||||
const sessionsDir = path.join(tempDir, "sessions");
|
||||
await fs.mkdir(sessionsDir, { recursive: true });
|
||||
|
||||
const activeSessionFile = await writeWorkspaceFile({
|
||||
dir: sessionsDir,
|
||||
name: "test-session.jsonl",
|
||||
content: "",
|
||||
const { tempDir, sessionsDir, activeSessionFile } = await createSessionMemoryWorkspace({
|
||||
activeSession: { name: "test-session.jsonl", content: "" },
|
||||
});
|
||||
|
||||
// Simulate /new rotation where useful content is now in .reset.* file
|
||||
@@ -314,7 +327,7 @@ describe("session-memory hook", () => {
|
||||
tempDir,
|
||||
previousSessionEntry: {
|
||||
sessionId: "test-123",
|
||||
sessionFile: activeSessionFile,
|
||||
sessionFile: activeSessionFile!,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -323,9 +336,7 @@ describe("session-memory hook", () => {
|
||||
});
|
||||
|
||||
it("handles reset-path session pointers from previousSessionEntry", async () => {
|
||||
const tempDir = await makeTempWorkspace("openclaw-session-memory-");
|
||||
const sessionsDir = path.join(tempDir, "sessions");
|
||||
await fs.mkdir(sessionsDir, { recursive: true });
|
||||
const { tempDir, sessionsDir } = await createSessionMemoryWorkspace();
|
||||
|
||||
const sessionId = "reset-pointer-session";
|
||||
const resetSessionFile = await writeWorkspaceFile({
|
||||
@@ -352,9 +363,7 @@ describe("session-memory hook", () => {
|
||||
});
|
||||
|
||||
it("recovers transcript when previousSessionEntry.sessionFile is missing", async () => {
|
||||
const tempDir = await makeTempWorkspace("openclaw-session-memory-");
|
||||
const sessionsDir = path.join(tempDir, "sessions");
|
||||
await fs.mkdir(sessionsDir, { recursive: true });
|
||||
const { tempDir, sessionsDir } = await createSessionMemoryWorkspace();
|
||||
|
||||
const sessionId = "missing-session-file";
|
||||
await writeWorkspaceFile({
|
||||
@@ -385,14 +394,8 @@ describe("session-memory hook", () => {
|
||||
});
|
||||
|
||||
it("prefers the newest reset transcript when multiple reset candidates exist", async () => {
|
||||
const tempDir = await makeTempWorkspace("openclaw-session-memory-");
|
||||
const sessionsDir = path.join(tempDir, "sessions");
|
||||
await fs.mkdir(sessionsDir, { recursive: true });
|
||||
|
||||
const activeSessionFile = await writeWorkspaceFile({
|
||||
dir: sessionsDir,
|
||||
name: "test-session.jsonl",
|
||||
content: "",
|
||||
const { tempDir, sessionsDir, activeSessionFile } = await createSessionMemoryWorkspace({
|
||||
activeSession: { name: "test-session.jsonl", content: "" },
|
||||
});
|
||||
|
||||
await writeWorkspaceFile({
|
||||
@@ -416,7 +419,7 @@ describe("session-memory hook", () => {
|
||||
tempDir,
|
||||
previousSessionEntry: {
|
||||
sessionId: "test-123",
|
||||
sessionFile: activeSessionFile,
|
||||
sessionFile: activeSessionFile!,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -425,6 +428,39 @@ describe("session-memory hook", () => {
|
||||
expect(memoryContent).not.toContain("Older rotated transcript");
|
||||
});
|
||||
|
||||
it("prefers active transcript when it is non-empty even with reset candidates", async () => {
|
||||
const { tempDir, sessionsDir, activeSessionFile } = await createSessionMemoryWorkspace({
|
||||
activeSession: {
|
||||
name: "test-session.jsonl",
|
||||
content: createMockSessionContent([
|
||||
{ role: "user", content: "Active transcript message" },
|
||||
{ role: "assistant", content: "Active transcript summary" },
|
||||
]),
|
||||
},
|
||||
});
|
||||
|
||||
await writeWorkspaceFile({
|
||||
dir: sessionsDir,
|
||||
name: "test-session.jsonl.reset.2026-02-16T22-26-34.000Z",
|
||||
content: createMockSessionContent([
|
||||
{ role: "user", content: "Reset fallback message" },
|
||||
{ role: "assistant", content: "Reset fallback summary" },
|
||||
]),
|
||||
});
|
||||
|
||||
const { memoryContent } = await runNewWithPreviousSessionEntry({
|
||||
tempDir,
|
||||
previousSessionEntry: {
|
||||
sessionId: "test-123",
|
||||
sessionFile: activeSessionFile!,
|
||||
},
|
||||
});
|
||||
|
||||
expect(memoryContent).toContain("user: Active transcript message");
|
||||
expect(memoryContent).toContain("assistant: Active transcript summary");
|
||||
expect(memoryContent).not.toContain("Reset fallback message");
|
||||
});
|
||||
|
||||
it("handles empty session files gracefully", async () => {
|
||||
// Should not throw
|
||||
const { files } = await runNewWithPreviousSession({ sessionContent: "" });
|
||||
|
||||
Reference in New Issue
Block a user