mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-14 02:31:24 +00:00
test: move directive state coverage to pure tests
This commit is contained in:
@@ -4,7 +4,6 @@ import type { OpenClawConfig } from "../config/config.js";
|
||||
import { loadSessionStore } from "../config/sessions.js";
|
||||
import {
|
||||
AUTHORIZED_WHATSAPP_COMMAND,
|
||||
assertElevatedOffStatusReply,
|
||||
installDirectiveBehaviorE2EHooks,
|
||||
makeElevatedDirectiveConfig,
|
||||
makeRestrictedElevatedDisabledConfig,
|
||||
@@ -179,27 +178,6 @@ describe("directive behavior", () => {
|
||||
expect(runEmbeddedPiAgentMock).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
it("persists fast toggles across /status and /fast", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
const storePath = sessionStorePath(home);
|
||||
|
||||
const onText = await runCommand(home, "/fast on");
|
||||
expect(onText).toContain("Fast mode enabled");
|
||||
expect(loadSessionStore(storePath)["agent:main:main"]?.fastMode).toBe(true);
|
||||
|
||||
const statusText = await runCommand(home, "/status");
|
||||
const optionsLine = statusText?.split("\n").find((line) => line.trim().startsWith("⚙️"));
|
||||
expect(optionsLine).toContain("Fast: on");
|
||||
|
||||
const offText = await runCommand(home, "/fast off");
|
||||
expect(offText).toContain("Fast mode disabled");
|
||||
expect(loadSessionStore(storePath)["agent:main:main"]?.fastMode).toBe(false);
|
||||
|
||||
const fastText = await runCommand(home, "/fast");
|
||||
expect(fastText).toContain("Current fast mode: off");
|
||||
expect(runEmbeddedPiAgentMock).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
it("treats /fast status like the no-argument status query", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
const statusText = await runCommand(home, "/fast status", {
|
||||
@@ -217,29 +195,6 @@ describe("directive behavior", () => {
|
||||
expect(runEmbeddedPiAgentMock).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
it("persists elevated toggles across /status and /elevated", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
const storePath = sessionStorePath(home);
|
||||
|
||||
const offStatusText = replyText(await runElevatedCommand(home, "/elevated off\n/status"));
|
||||
expect(offStatusText).toContain("Session: agent:main:main");
|
||||
assertElevatedOffStatusReply(offStatusText);
|
||||
|
||||
const offLevelText = replyText(await runElevatedCommand(home, "/elevated"));
|
||||
expect(offLevelText).toContain("Current elevated level: off");
|
||||
expect(loadSessionStore(storePath)["agent:main:main"]?.elevatedLevel).toBe("off");
|
||||
|
||||
await runElevatedCommand(home, "/elevated on");
|
||||
const onStatusText = replyText(await runElevatedCommand(home, "/status"));
|
||||
const optionsLine = onStatusText?.split("\n").find((line) => line.trim().startsWith("⚙️"));
|
||||
expect(optionsLine).toBeTruthy();
|
||||
expect(optionsLine).toContain("elevated");
|
||||
|
||||
const store = loadSessionStore(storePath);
|
||||
expect(store["agent:main:main"]?.elevatedLevel).toBe("on");
|
||||
expect(runEmbeddedPiAgentMock).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
it("enforces per-agent elevated restrictions and status visibility", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
const deniedRes = await getReplyFromConfig(
|
||||
@@ -258,21 +213,6 @@ describe("directive behavior", () => {
|
||||
const deniedText = replyText(deniedRes);
|
||||
expect(deniedText).toContain("agents.list[].tools.elevated.enabled");
|
||||
|
||||
const statusRes = await getReplyFromConfig(
|
||||
{
|
||||
Body: "/status",
|
||||
From: "+1222",
|
||||
To: "+1222",
|
||||
Provider: "whatsapp",
|
||||
SenderE164: "+1222",
|
||||
SessionKey: "agent:restricted:main",
|
||||
CommandAuthorized: true,
|
||||
},
|
||||
{},
|
||||
makeRestrictedElevatedDisabledConfig(home) as unknown as OpenClawConfig,
|
||||
);
|
||||
const statusText = replyText(statusRes);
|
||||
expect(statusText).not.toContain("elevated");
|
||||
expect(runEmbeddedPiAgentMock).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -376,37 +316,4 @@ describe("directive behavior", () => {
|
||||
expect(runEmbeddedPiAgentMock).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
it("strips inline elevated directives from the user text (does not persist session override)", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
runEmbeddedPiAgentMock.mockResolvedValue({
|
||||
payloads: [{ text: "ok" }],
|
||||
meta: {
|
||||
durationMs: 1,
|
||||
agentMeta: { sessionId: "s", provider: "p", model: "m" },
|
||||
},
|
||||
});
|
||||
const storePath = sessionStorePath(home);
|
||||
|
||||
await getReplyFromConfig(
|
||||
{
|
||||
Body: "hello there /elevated off",
|
||||
From: "+1222",
|
||||
To: "+1222",
|
||||
Provider: "whatsapp",
|
||||
SenderE164: "+1222",
|
||||
},
|
||||
{},
|
||||
makeElevatedDirectiveConfig(home),
|
||||
);
|
||||
|
||||
const store = loadSessionStore(storePath);
|
||||
expect(store["agent:main:main"]?.elevatedLevel).toBeUndefined();
|
||||
|
||||
const calls = runEmbeddedPiAgentMock.mock.calls;
|
||||
expect(calls.length).toBeGreaterThan(0);
|
||||
const call = calls[0]?.[0];
|
||||
expect(call?.prompt).toContain("hello there");
|
||||
expect(call?.prompt).not.toContain("/elevated");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -622,6 +622,14 @@ describe("handleDirectiveOnly model persist behavior (fixes #1435)", () => {
|
||||
expect(result?.text ?? "").not.toContain("failed");
|
||||
});
|
||||
|
||||
it("strips inline elevated directives while keeping user text", () => {
|
||||
const directives = parseInlineDirectives("hello there /elevated off");
|
||||
|
||||
expect(directives.hasElevatedDirective).toBe(true);
|
||||
expect(directives.elevatedLevel).toBe("off");
|
||||
expect(directives.cleaned).toBe("hello there");
|
||||
});
|
||||
|
||||
it("persists thinkingLevel=off (does not clear)", async () => {
|
||||
const directives = parseInlineDirectives("/think off");
|
||||
const sessionEntry = createSessionEntry({ thinkingLevel: "low" });
|
||||
@@ -639,6 +647,81 @@ describe("handleDirectiveOnly model persist behavior (fixes #1435)", () => {
|
||||
expect(sessionStore["agent:main:dm:1"]?.thinkingLevel).toBe("off");
|
||||
});
|
||||
|
||||
it("persists and reports fast-mode directives", async () => {
|
||||
const sessionEntry = createSessionEntry();
|
||||
const sessionStore = { [sessionKey]: sessionEntry };
|
||||
|
||||
const onReply = await handleDirectiveOnly(
|
||||
createHandleParams({
|
||||
directives: parseInlineDirectives("/fast on"),
|
||||
sessionEntry,
|
||||
sessionStore,
|
||||
}),
|
||||
);
|
||||
expect(onReply?.text).toContain("Fast mode enabled");
|
||||
expect(sessionEntry.fastMode).toBe(true);
|
||||
|
||||
const statusReply = await handleDirectiveOnly(
|
||||
createHandleParams({
|
||||
directives: parseInlineDirectives("/fast"),
|
||||
sessionEntry,
|
||||
sessionStore,
|
||||
currentFastMode: sessionEntry.fastMode,
|
||||
}),
|
||||
);
|
||||
expect(statusReply?.text).toContain("Current fast mode: on");
|
||||
|
||||
const offReply = await handleDirectiveOnly(
|
||||
createHandleParams({
|
||||
directives: parseInlineDirectives("/fast off"),
|
||||
sessionEntry,
|
||||
sessionStore,
|
||||
currentFastMode: sessionEntry.fastMode,
|
||||
}),
|
||||
);
|
||||
expect(offReply?.text).toContain("Fast mode disabled");
|
||||
expect(sessionEntry.fastMode).toBe(false);
|
||||
});
|
||||
|
||||
it("persists and reports elevated-mode directives when allowed", async () => {
|
||||
const sessionEntry = createSessionEntry();
|
||||
const sessionStore = { [sessionKey]: sessionEntry };
|
||||
const base = {
|
||||
elevatedAllowed: true,
|
||||
elevatedEnabled: true,
|
||||
sessionEntry,
|
||||
sessionStore,
|
||||
} satisfies Partial<HandleParams>;
|
||||
|
||||
const onReply = await handleDirectiveOnly(
|
||||
createHandleParams({
|
||||
...base,
|
||||
directives: parseInlineDirectives("/elevated on"),
|
||||
}),
|
||||
);
|
||||
expect(onReply?.text).toContain("Elevated mode set to ask");
|
||||
expect(sessionEntry.elevatedLevel).toBe("on");
|
||||
|
||||
const statusReply = await handleDirectiveOnly(
|
||||
createHandleParams({
|
||||
...base,
|
||||
directives: parseInlineDirectives("/elevated"),
|
||||
currentElevatedLevel: sessionEntry.elevatedLevel,
|
||||
}),
|
||||
);
|
||||
expect(statusReply?.text).toContain("Current elevated level: on");
|
||||
|
||||
const offReply = await handleDirectiveOnly(
|
||||
createHandleParams({
|
||||
...base,
|
||||
directives: parseInlineDirectives("/elevated off"),
|
||||
currentElevatedLevel: sessionEntry.elevatedLevel,
|
||||
}),
|
||||
);
|
||||
expect(offReply?.text).toContain("Elevated mode disabled");
|
||||
expect(sessionEntry.elevatedLevel).toBe("off");
|
||||
});
|
||||
|
||||
it("blocks internal operator.write exec persistence in directive-only handling", async () => {
|
||||
const directives = parseInlineDirectives(
|
||||
"/exec host=node security=allowlist ask=always node=worker-1",
|
||||
|
||||
Reference in New Issue
Block a user