mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-09 18:14:31 +00:00
149 lines
4.0 KiB
TypeScript
149 lines
4.0 KiB
TypeScript
import fs from "node:fs/promises";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
import type { MsgContext } from "../../auto-reply/templating.js";
|
|
import {
|
|
clearSessionStoreCacheForTest,
|
|
loadSessionStore,
|
|
recordSessionMetaFromInbound,
|
|
updateLastRoute,
|
|
} from "../sessions.js";
|
|
|
|
const CANONICAL_KEY = "agent:main:webchat:dm:mixed-user";
|
|
const MIXED_CASE_KEY = "Agent:Main:WebChat:DM:MiXeD-User";
|
|
|
|
function createInboundContext(): MsgContext {
|
|
return {
|
|
Provider: "webchat",
|
|
Surface: "webchat",
|
|
ChatType: "direct",
|
|
From: "WebChat:User-1",
|
|
To: "webchat:agent",
|
|
SessionKey: MIXED_CASE_KEY,
|
|
OriginatingTo: "webchat:user-1",
|
|
};
|
|
}
|
|
|
|
describe("session store key normalization", () => {
|
|
let tempDir = "";
|
|
let storePath = "";
|
|
|
|
beforeEach(async () => {
|
|
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-session-key-normalize-"));
|
|
storePath = path.join(tempDir, "sessions.json");
|
|
await fs.writeFile(storePath, "{}", "utf-8");
|
|
});
|
|
|
|
afterEach(async () => {
|
|
clearSessionStoreCacheForTest();
|
|
if (tempDir) {
|
|
await fs.rm(tempDir, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
it("records inbound metadata under a canonical lowercase key", async () => {
|
|
await recordSessionMetaFromInbound({
|
|
storePath,
|
|
sessionKey: MIXED_CASE_KEY,
|
|
ctx: createInboundContext(),
|
|
});
|
|
|
|
const store = loadSessionStore(storePath, { skipCache: true });
|
|
expect(Object.keys(store)).toEqual([CANONICAL_KEY]);
|
|
expect(store[CANONICAL_KEY]?.origin?.provider).toBe("webchat");
|
|
});
|
|
|
|
it("does not create a duplicate mixed-case key when last route is updated", async () => {
|
|
await recordSessionMetaFromInbound({
|
|
storePath,
|
|
sessionKey: CANONICAL_KEY,
|
|
ctx: createInboundContext(),
|
|
});
|
|
|
|
await updateLastRoute({
|
|
storePath,
|
|
sessionKey: MIXED_CASE_KEY,
|
|
channel: "webchat",
|
|
to: "webchat:user-1",
|
|
});
|
|
|
|
const store = loadSessionStore(storePath, { skipCache: true });
|
|
expect(Object.keys(store)).toEqual([CANONICAL_KEY]);
|
|
expect(store[CANONICAL_KEY]).toEqual(
|
|
expect.objectContaining({
|
|
lastChannel: "webchat",
|
|
lastTo: "webchat:user-1",
|
|
}),
|
|
);
|
|
});
|
|
|
|
it("migrates legacy mixed-case entries to the canonical key on update", async () => {
|
|
await fs.writeFile(
|
|
storePath,
|
|
JSON.stringify(
|
|
{
|
|
[MIXED_CASE_KEY]: {
|
|
sessionId: "legacy-session",
|
|
updatedAt: 1,
|
|
chatType: "direct",
|
|
channel: "webchat",
|
|
},
|
|
},
|
|
null,
|
|
2,
|
|
),
|
|
"utf-8",
|
|
);
|
|
clearSessionStoreCacheForTest();
|
|
|
|
await updateLastRoute({
|
|
storePath,
|
|
sessionKey: CANONICAL_KEY,
|
|
channel: "webchat",
|
|
to: "webchat:user-2",
|
|
});
|
|
|
|
const store = loadSessionStore(storePath, { skipCache: true });
|
|
expect(store[CANONICAL_KEY]?.sessionId).toBe("legacy-session");
|
|
expect(store[MIXED_CASE_KEY]).toBeUndefined();
|
|
});
|
|
|
|
it("preserves updatedAt when recording inbound metadata for an existing session", async () => {
|
|
await fs.writeFile(
|
|
storePath,
|
|
JSON.stringify(
|
|
{
|
|
[CANONICAL_KEY]: {
|
|
sessionId: "existing-session",
|
|
updatedAt: 1111,
|
|
chatType: "direct",
|
|
channel: "webchat",
|
|
origin: {
|
|
provider: "webchat",
|
|
chatType: "direct",
|
|
from: "WebChat:User-1",
|
|
to: "webchat:user-1",
|
|
},
|
|
},
|
|
},
|
|
null,
|
|
2,
|
|
),
|
|
"utf-8",
|
|
);
|
|
clearSessionStoreCacheForTest();
|
|
|
|
await recordSessionMetaFromInbound({
|
|
storePath,
|
|
sessionKey: CANONICAL_KEY,
|
|
ctx: createInboundContext(),
|
|
});
|
|
|
|
const store = loadSessionStore(storePath, { skipCache: true });
|
|
expect(store[CANONICAL_KEY]?.sessionId).toBe("existing-session");
|
|
expect(store[CANONICAL_KEY]?.updatedAt).toBe(1111);
|
|
expect(store[CANONICAL_KEY]?.origin?.provider).toBe("webchat");
|
|
});
|
|
});
|