mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 13:41:37 +00:00
test: simplify session reset and rawbody coverage
This commit is contained in:
@@ -232,47 +232,35 @@ describe("initSessionState thread forking", () => {
|
||||
});
|
||||
|
||||
describe("initSessionState RawBody", () => {
|
||||
it("triggerBodyNormalized correctly extracts commands when Body contains context but RawBody is clean", async () => {
|
||||
it("uses RawBody for command extraction and reset triggers when Body contains wrapped context", async () => {
|
||||
const root = await makeCaseDir("openclaw-rawbody-");
|
||||
const storePath = path.join(root, "sessions.json");
|
||||
const cfg = { session: { store: storePath } } as OpenClawConfig;
|
||||
|
||||
const groupMessageCtx = {
|
||||
Body: `[Chat messages since your last reply - for context]\n[WhatsApp ...] Someone: hello\n\n[Current message - respond to this]\n[WhatsApp ...] Jake: /status\n[from: Jake McInteer (+6421807830)]`,
|
||||
RawBody: "/status",
|
||||
ChatType: "group",
|
||||
SessionKey: "agent:main:whatsapp:group:g1",
|
||||
};
|
||||
|
||||
const result = await initSessionState({
|
||||
ctx: groupMessageCtx,
|
||||
const statusResult = await initSessionState({
|
||||
ctx: {
|
||||
Body: `[Chat messages since your last reply - for context]\n[WhatsApp ...] Someone: hello\n\n[Current message - respond to this]\n[WhatsApp ...] Jake: /status\n[from: Jake McInteer (+6421807830)]`,
|
||||
RawBody: "/status",
|
||||
ChatType: "group",
|
||||
SessionKey: "agent:main:whatsapp:group:g1",
|
||||
},
|
||||
cfg,
|
||||
commandAuthorized: true,
|
||||
});
|
||||
expect(statusResult.triggerBodyNormalized).toBe("/status");
|
||||
|
||||
expect(result.triggerBodyNormalized).toBe("/status");
|
||||
});
|
||||
|
||||
it("Reset triggers (/new, /reset) work with RawBody", async () => {
|
||||
const root = await makeCaseDir("openclaw-rawbody-reset-");
|
||||
const storePath = path.join(root, "sessions.json");
|
||||
const cfg = { session: { store: storePath } } as OpenClawConfig;
|
||||
|
||||
const groupMessageCtx = {
|
||||
Body: `[Context]\nJake: /new\n[from: Jake]`,
|
||||
RawBody: "/new",
|
||||
ChatType: "group",
|
||||
SessionKey: "agent:main:whatsapp:group:g1",
|
||||
};
|
||||
|
||||
const result = await initSessionState({
|
||||
ctx: groupMessageCtx,
|
||||
const resetResult = await initSessionState({
|
||||
ctx: {
|
||||
Body: `[Context]\nJake: /new\n[from: Jake]`,
|
||||
RawBody: "/new",
|
||||
ChatType: "group",
|
||||
SessionKey: "agent:main:whatsapp:group:g1",
|
||||
},
|
||||
cfg,
|
||||
commandAuthorized: true,
|
||||
});
|
||||
|
||||
expect(result.isNewSession).toBe(true);
|
||||
expect(result.bodyStripped).toBe("");
|
||||
expect(resetResult.isNewSession).toBe(true);
|
||||
expect(resetResult.bodyStripped).toBe("");
|
||||
});
|
||||
|
||||
it("preserves argument casing while still matching reset triggers case-insensitively", async () => {
|
||||
@@ -303,25 +291,6 @@ describe("initSessionState RawBody", () => {
|
||||
expect(result.triggerBodyNormalized).toBe("/NEW KeepThisCase");
|
||||
});
|
||||
|
||||
it("falls back to Body when RawBody is undefined", async () => {
|
||||
const root = await makeCaseDir("openclaw-rawbody-fallback-");
|
||||
const storePath = path.join(root, "sessions.json");
|
||||
const cfg = { session: { store: storePath } } as OpenClawConfig;
|
||||
|
||||
const ctx = {
|
||||
Body: "/status",
|
||||
SessionKey: "agent:main:whatsapp:dm:s1",
|
||||
};
|
||||
|
||||
const result = await initSessionState({
|
||||
ctx,
|
||||
cfg,
|
||||
commandAuthorized: true,
|
||||
});
|
||||
|
||||
expect(result.triggerBodyNormalized).toBe("/status");
|
||||
});
|
||||
|
||||
it("uses the default per-agent sessions store when config store is unset", async () => {
|
||||
const root = await makeCaseDir("openclaw-session-store-default-");
|
||||
const stateDir = path.join(root, ".openclaw");
|
||||
@@ -643,10 +612,10 @@ describe("initSessionState reset triggers in WhatsApp groups", () => {
|
||||
it("applies WhatsApp group reset authorization across sender variants", async () => {
|
||||
const sessionKey = "agent:main:whatsapp:group:120363406150318674@g.us";
|
||||
const existingSessionId = "existing-session-123";
|
||||
const storePath = await createStorePath("openclaw-group-reset");
|
||||
const cases = [
|
||||
{
|
||||
name: "authorized sender",
|
||||
storePrefix: "openclaw-group-reset-",
|
||||
allowFrom: ["+41796666864"],
|
||||
body: `[Chat messages since your last reply - for context]\\n[WhatsApp 120363406150318674@g.us 2026-01-13T07:45Z] Someone: hello\\n\\n[Current message - respond to this]\\n[WhatsApp 120363406150318674@g.us 2026-01-13T07:45Z] Peschiño: /new\\n[from: Peschiño (+41796666864)]`,
|
||||
senderName: "Peschiño",
|
||||
@@ -654,39 +623,8 @@ describe("initSessionState reset triggers in WhatsApp groups", () => {
|
||||
senderId: "41796666864:0@s.whatsapp.net",
|
||||
expectedIsNewSession: true,
|
||||
},
|
||||
{
|
||||
name: "unauthorized sender",
|
||||
storePrefix: "openclaw-group-reset-unauth-",
|
||||
allowFrom: ["+41796666864"],
|
||||
body: `[Context]\\n[WhatsApp ...] OtherPerson: /new\\n[from: OtherPerson (+1555123456)]`,
|
||||
senderName: "OtherPerson",
|
||||
senderE164: "+1555123456",
|
||||
senderId: "1555123456:0@s.whatsapp.net",
|
||||
expectedIsNewSession: false,
|
||||
},
|
||||
{
|
||||
name: "raw body clean while body wrapped",
|
||||
storePrefix: "openclaw-group-rawbody-",
|
||||
allowFrom: ["*"],
|
||||
body: `[WhatsApp 120363406150318674@g.us 2026-01-13T07:45Z] Jake: /new\n[from: Jake (+1222)]`,
|
||||
senderName: undefined,
|
||||
senderE164: "+1222",
|
||||
senderId: undefined,
|
||||
expectedIsNewSession: true,
|
||||
},
|
||||
{
|
||||
name: "LID sender with authorized E164",
|
||||
storePrefix: "openclaw-group-reset-lid-",
|
||||
allowFrom: ["+41796666864"],
|
||||
body: `[WhatsApp 120363406150318674@g.us 2026-01-13T07:45Z] Owner: /new\n[from: Owner (+41796666864)]`,
|
||||
senderName: "Owner",
|
||||
senderE164: "+41796666864",
|
||||
senderId: "123@lid",
|
||||
expectedIsNewSession: true,
|
||||
},
|
||||
{
|
||||
name: "LID sender with unauthorized E164",
|
||||
storePrefix: "openclaw-group-reset-lid-unauth-",
|
||||
allowFrom: ["+41796666864"],
|
||||
body: `[WhatsApp 120363406150318674@g.us 2026-01-13T07:45Z] Other: /new\n[from: Other (+1555123456)]`,
|
||||
senderName: "Other",
|
||||
@@ -697,7 +635,6 @@ describe("initSessionState reset triggers in WhatsApp groups", () => {
|
||||
] as const;
|
||||
|
||||
for (const testCase of cases) {
|
||||
const storePath = await createStorePath(testCase.storePrefix);
|
||||
await seedSessionStore({
|
||||
storePath,
|
||||
sessionKey,
|
||||
@@ -755,57 +692,40 @@ describe("initSessionState reset triggers in Slack channels", () => {
|
||||
|
||||
it("supports mention-prefixed Slack reset commands and preserves args", async () => {
|
||||
const existingSessionId = "existing-session-123";
|
||||
const cases = [
|
||||
{
|
||||
name: "reset command",
|
||||
storePrefix: "openclaw-slack-channel-reset-",
|
||||
sessionKey: "agent:main:slack:channel:c1",
|
||||
body: "<@U123> /reset",
|
||||
expectedBodyStripped: "",
|
||||
const sessionKey = "agent:main:slack:channel:c2";
|
||||
const body = "<@U123> /new take notes";
|
||||
const storePath = await createStorePath("openclaw-slack-channel-new-");
|
||||
await seedSessionStore({
|
||||
storePath,
|
||||
sessionKey,
|
||||
sessionId: existingSessionId,
|
||||
});
|
||||
const cfg = {
|
||||
session: { store: storePath, idleMinutes: 999 },
|
||||
} as OpenClawConfig;
|
||||
|
||||
const result = await initSessionState({
|
||||
ctx: {
|
||||
Body: body,
|
||||
RawBody: body,
|
||||
CommandBody: body,
|
||||
From: "slack:channel:C1",
|
||||
To: "channel:C1",
|
||||
ChatType: "channel",
|
||||
SessionKey: sessionKey,
|
||||
Provider: "slack",
|
||||
Surface: "slack",
|
||||
SenderId: "U123",
|
||||
SenderName: "Owner",
|
||||
},
|
||||
{
|
||||
name: "new command with args",
|
||||
storePrefix: "openclaw-slack-channel-new-",
|
||||
sessionKey: "agent:main:slack:channel:c2",
|
||||
body: "<@U123> /new take notes",
|
||||
expectedBodyStripped: "take notes",
|
||||
},
|
||||
] as const;
|
||||
cfg,
|
||||
commandAuthorized: true,
|
||||
});
|
||||
|
||||
for (const testCase of cases) {
|
||||
const storePath = await createStorePath(testCase.storePrefix);
|
||||
await seedSessionStore({
|
||||
storePath,
|
||||
sessionKey: testCase.sessionKey,
|
||||
sessionId: existingSessionId,
|
||||
});
|
||||
const cfg = {
|
||||
session: { store: storePath, idleMinutes: 999 },
|
||||
} as OpenClawConfig;
|
||||
|
||||
const result = await initSessionState({
|
||||
ctx: {
|
||||
Body: testCase.body,
|
||||
RawBody: testCase.body,
|
||||
CommandBody: testCase.body,
|
||||
From: "slack:channel:C1",
|
||||
To: "channel:C1",
|
||||
ChatType: "channel",
|
||||
SessionKey: testCase.sessionKey,
|
||||
Provider: "slack",
|
||||
Surface: "slack",
|
||||
SenderId: "U123",
|
||||
SenderName: "Owner",
|
||||
},
|
||||
cfg,
|
||||
commandAuthorized: true,
|
||||
});
|
||||
|
||||
expect(result.isNewSession, testCase.name).toBe(true);
|
||||
expect(result.resetTriggered, testCase.name).toBe(true);
|
||||
expect(result.sessionId, testCase.name).not.toBe(existingSessionId);
|
||||
expect(result.bodyStripped, testCase.name).toBe(testCase.expectedBodyStripped);
|
||||
}
|
||||
expect(result.isNewSession).toBe(true);
|
||||
expect(result.resetTriggered).toBe(true);
|
||||
expect(result.sessionId).not.toBe(existingSessionId);
|
||||
expect(result.bodyStripped).toBe("take notes");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -920,150 +840,60 @@ describe("initSessionState preserves behavior overrides across /new and /reset",
|
||||
});
|
||||
}
|
||||
|
||||
it("/new preserves verboseLevel from previous session", async () => {
|
||||
const storePath = await createStorePath("openclaw-reset-verbose-");
|
||||
const sessionKey = "agent:main:telegram:dm:user1";
|
||||
const existingSessionId = "existing-session-verbose";
|
||||
await seedSessionStoreWithOverrides({
|
||||
storePath,
|
||||
sessionKey,
|
||||
sessionId: existingSessionId,
|
||||
overrides: { verboseLevel: "on" },
|
||||
});
|
||||
await fs.writeFile(
|
||||
path.join(path.dirname(storePath), `${existingSessionId}.jsonl`),
|
||||
"",
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
const cfg = {
|
||||
session: { store: storePath, idleMinutes: 999 },
|
||||
} as OpenClawConfig;
|
||||
|
||||
const result = await initSessionState({
|
||||
ctx: {
|
||||
Body: "/new",
|
||||
RawBody: "/new",
|
||||
CommandBody: "/new",
|
||||
From: "user1",
|
||||
To: "bot",
|
||||
ChatType: "direct",
|
||||
SessionKey: sessionKey,
|
||||
Provider: "telegram",
|
||||
Surface: "telegram",
|
||||
it("preserves behavior overrides across /new and /reset", async () => {
|
||||
const storePath = await createStorePath("openclaw-reset-overrides-");
|
||||
const sessionKey = "agent:main:telegram:dm:user-overrides";
|
||||
const existingSessionId = "existing-session-overrides";
|
||||
const overrides = {
|
||||
verboseLevel: "on",
|
||||
thinkingLevel: "high",
|
||||
reasoningLevel: "low",
|
||||
label: "telegram-priority",
|
||||
} as const;
|
||||
const cases = [
|
||||
{
|
||||
name: "new preserves behavior overrides",
|
||||
body: "/new",
|
||||
},
|
||||
cfg,
|
||||
commandAuthorized: true,
|
||||
});
|
||||
|
||||
expect(result.isNewSession).toBe(true);
|
||||
expect(result.resetTriggered).toBe(true);
|
||||
expect(result.sessionId).not.toBe(existingSessionId);
|
||||
expect(result.sessionEntry.verboseLevel).toBe("on");
|
||||
});
|
||||
|
||||
it("/reset preserves thinkingLevel and reasoningLevel from previous session", async () => {
|
||||
const storePath = await createStorePath("openclaw-reset-thinking-");
|
||||
const sessionKey = "agent:main:telegram:dm:user2";
|
||||
const existingSessionId = "existing-session-thinking";
|
||||
await seedSessionStoreWithOverrides({
|
||||
storePath,
|
||||
sessionKey,
|
||||
sessionId: existingSessionId,
|
||||
overrides: { thinkingLevel: "high", reasoningLevel: "low" },
|
||||
});
|
||||
|
||||
const cfg = {
|
||||
session: { store: storePath, idleMinutes: 999 },
|
||||
} as OpenClawConfig;
|
||||
|
||||
const result = await initSessionState({
|
||||
ctx: {
|
||||
Body: "/reset",
|
||||
RawBody: "/reset",
|
||||
CommandBody: "/reset",
|
||||
From: "user2",
|
||||
To: "bot",
|
||||
ChatType: "direct",
|
||||
SessionKey: sessionKey,
|
||||
Provider: "telegram",
|
||||
Surface: "telegram",
|
||||
{
|
||||
name: "reset preserves behavior overrides",
|
||||
body: "/reset",
|
||||
},
|
||||
cfg,
|
||||
commandAuthorized: true,
|
||||
});
|
||||
] as const;
|
||||
|
||||
expect(result.isNewSession).toBe(true);
|
||||
expect(result.resetTriggered).toBe(true);
|
||||
expect(result.sessionId).not.toBe(existingSessionId);
|
||||
expect(result.sessionEntry.thinkingLevel).toBe("high");
|
||||
expect(result.sessionEntry.reasoningLevel).toBe("low");
|
||||
});
|
||||
for (const testCase of cases) {
|
||||
await seedSessionStoreWithOverrides({
|
||||
storePath,
|
||||
sessionKey,
|
||||
sessionId: existingSessionId,
|
||||
overrides: { ...overrides },
|
||||
});
|
||||
|
||||
it("/new preserves session label from previous session", async () => {
|
||||
const storePath = await createStorePath("openclaw-reset-label-");
|
||||
const sessionKey = "agent:main:telegram:dm:user-label";
|
||||
const existingSessionId = "existing-session-label";
|
||||
await seedSessionStoreWithOverrides({
|
||||
storePath,
|
||||
sessionKey,
|
||||
sessionId: existingSessionId,
|
||||
overrides: { label: "telegram-priority" },
|
||||
});
|
||||
const cfg = {
|
||||
session: { store: storePath, idleMinutes: 999 },
|
||||
} as OpenClawConfig;
|
||||
|
||||
const cfg = {
|
||||
session: { store: storePath, idleMinutes: 999 },
|
||||
} as OpenClawConfig;
|
||||
const result = await initSessionState({
|
||||
ctx: {
|
||||
Body: testCase.body,
|
||||
RawBody: testCase.body,
|
||||
CommandBody: testCase.body,
|
||||
From: "user-overrides",
|
||||
To: "bot",
|
||||
ChatType: "direct",
|
||||
SessionKey: sessionKey,
|
||||
Provider: "telegram",
|
||||
Surface: "telegram",
|
||||
},
|
||||
cfg,
|
||||
commandAuthorized: true,
|
||||
});
|
||||
|
||||
const result = await initSessionState({
|
||||
ctx: {
|
||||
Body: "/new",
|
||||
RawBody: "/new",
|
||||
CommandBody: "/new",
|
||||
From: "user-label",
|
||||
To: "bot",
|
||||
ChatType: "direct",
|
||||
SessionKey: sessionKey,
|
||||
Provider: "telegram",
|
||||
Surface: "telegram",
|
||||
},
|
||||
cfg,
|
||||
commandAuthorized: true,
|
||||
});
|
||||
|
||||
expect(result.isNewSession).toBe(true);
|
||||
expect(result.resetTriggered).toBe(true);
|
||||
expect(result.sessionEntry.label).toBe("telegram-priority");
|
||||
});
|
||||
|
||||
it("/new in a new session does not preserve overrides", async () => {
|
||||
const storePath = await createStorePath("openclaw-new-no-preserve-");
|
||||
const sessionKey = "agent:main:telegram:dm:user3";
|
||||
|
||||
const cfg = {
|
||||
session: { store: storePath, idleMinutes: 999 },
|
||||
} as OpenClawConfig;
|
||||
|
||||
const result = await initSessionState({
|
||||
ctx: {
|
||||
Body: "/new",
|
||||
RawBody: "/new",
|
||||
CommandBody: "/new",
|
||||
From: "user3",
|
||||
To: "bot",
|
||||
ChatType: "direct",
|
||||
SessionKey: sessionKey,
|
||||
Provider: "telegram",
|
||||
Surface: "telegram",
|
||||
},
|
||||
cfg,
|
||||
commandAuthorized: true,
|
||||
});
|
||||
|
||||
expect(result.isNewSession).toBe(true);
|
||||
expect(result.resetTriggered).toBe(true);
|
||||
expect(result.sessionEntry.verboseLevel).toBeUndefined();
|
||||
expect(result.sessionEntry.thinkingLevel).toBeUndefined();
|
||||
expect(result.isNewSession, testCase.name).toBe(true);
|
||||
expect(result.resetTriggered, testCase.name).toBe(true);
|
||||
expect(result.sessionId, testCase.name).not.toBe(existingSessionId);
|
||||
expect(result.sessionEntry, testCase.name).toMatchObject(overrides);
|
||||
}
|
||||
});
|
||||
|
||||
it("archives the old session store entry on /new", async () => {
|
||||
|
||||
Reference in New Issue
Block a user