test: optimize redundant suites for faster runtime

This commit is contained in:
Peter Steinberger
2026-02-23 13:57:34 +00:00
parent 5196565f19
commit 3f03cdea56
7 changed files with 288 additions and 309 deletions

View File

@@ -2,6 +2,10 @@ import type { PluginRuntime } from "openclaw/plugin-sdk";
import { beforeEach, describe, expect, it, vi } from "vitest"; import { beforeEach, describe, expect, it, vi } from "vitest";
import { setMSTeamsRuntime } from "./runtime.js"; import { setMSTeamsRuntime } from "./runtime.js";
vi.mock("openclaw/plugin-sdk", () => ({
isPrivateIpAddress: () => false,
}));
/** Mock DNS resolver that always returns a public IP (for anti-SSRF validation in tests). */ /** Mock DNS resolver that always returns a public IP (for anti-SSRF validation in tests). */
const publicResolveFn = async () => ({ address: "13.107.136.10" }); const publicResolveFn = async () => ({ address: "13.107.136.10" });

View File

@@ -234,16 +234,11 @@ describe("trigger handling", () => {
}); });
}); });
it("drops top-level restricted commands for unauthorized senders", async () => { it("enforces top-level command auth but keeps inline text for unauthorized senders", async () => {
await withTempHome(async (home) => { await withTempHome(async (home) => {
for (const command of ["/status", "/whoami"] as const) { for (const command of ["/status", "/whoami"] as const) {
await expectUnauthorizedCommandDropped(home, command); await expectUnauthorizedCommandDropped(home, command);
} }
});
});
it("keeps inline commands for unauthorized senders", async () => {
await withTempHome(async (home) => {
for (const command of ["/status", "/help"] as const) { for (const command of ["/status", "/help"] as const) {
const runEmbeddedPiAgentMock = mockEmbeddedOk(); const runEmbeddedPiAgentMock = mockEmbeddedOk();
const res = await runInlineUnauthorizedCommand({ const res = await runInlineUnauthorizedCommand({
@@ -305,109 +300,115 @@ describe("trigger handling", () => {
}); });
}); });
it("rejects elevated toggles when disabled", async () => { it("enforces elevated toggles across enabled and mention scenarios", async () => {
await withTempHome(async (home) => { await withTempHome(async (home) => {
const cfg = makeWhatsAppElevatedCfg(home, { elevatedEnabled: false }); const isolateStore = (cfg: ReturnType<typeof makeWhatsAppElevatedCfg>, label: string) => {
cfg.session = { ...cfg.session, store: join(home, `${label}.sessions.json`) };
return cfg;
};
const res = await getReplyFromConfig( {
{ const cfg = isolateStore(makeWhatsAppElevatedCfg(home, { elevatedEnabled: false }), "off");
Body: "/elevated on", const res = await getReplyFromConfig(
From: "+1000", {
To: "+2000", Body: "/elevated on",
Provider: "whatsapp", From: "+1000",
SenderE164: "+1000", To: "+2000",
}, Provider: "whatsapp",
{}, SenderE164: "+1000",
cfg, },
); {},
const text = Array.isArray(res) ? res[0]?.text : res?.text; cfg,
expect(text).toContain("tools.elevated.enabled"); );
const text = Array.isArray(res) ? res[0]?.text : res?.text;
expect(text).toContain("tools.elevated.enabled");
const storeRaw = await fs.readFile(requireSessionStorePath(cfg), "utf-8"); const storeRaw = await fs.readFile(requireSessionStorePath(cfg), "utf-8");
const store = JSON.parse(storeRaw) as Record<string, { elevatedLevel?: string }>; const store = JSON.parse(storeRaw) as Record<string, { elevatedLevel?: string }>;
expect(store[MAIN_SESSION_KEY]?.elevatedLevel).toBeUndefined(); expect(store[MAIN_SESSION_KEY]?.elevatedLevel).toBeUndefined();
}); }
});
it("allows elevated off in groups without mention", async () => { {
await withTempHome(async (home) => { const cfg = isolateStore(
const cfg = makeWhatsAppElevatedCfg(home, { requireMentionInGroups: false }); makeWhatsAppElevatedCfg(home, { requireMentionInGroups: false }),
"group-off",
);
const res = await getReplyFromConfig(
{
Body: "/elevated off",
From: "whatsapp:group:123@g.us",
To: "whatsapp:+2000",
Provider: "whatsapp",
SenderE164: "+1000",
CommandAuthorized: true,
ChatType: "group",
WasMentioned: false,
},
{},
cfg,
);
const text = Array.isArray(res) ? res[0]?.text : res?.text;
expect(text).toContain("Elevated mode disabled.");
const store = await readSessionStore(cfg);
expect(store["agent:main:whatsapp:group:123@g.us"]?.elevatedLevel).toBe("off");
}
const res = await getReplyFromConfig( {
{ const cfg = isolateStore(
Body: "/elevated off", makeWhatsAppElevatedCfg(home, { requireMentionInGroups: true }),
From: "whatsapp:group:123@g.us", "group-on",
To: "whatsapp:+2000", );
Provider: "whatsapp", const res = await getReplyFromConfig(
SenderE164: "+1000", {
CommandAuthorized: true, Body: "/elevated on",
ChatType: "group", From: "whatsapp:group:123@g.us",
WasMentioned: false, To: "whatsapp:+2000",
}, Provider: "whatsapp",
{}, SenderE164: "+1000",
cfg, CommandAuthorized: true,
); ChatType: "group",
const text = Array.isArray(res) ? res[0]?.text : res?.text; WasMentioned: true,
expect(text).toContain("Elevated mode disabled."); },
{},
cfg,
);
const text = Array.isArray(res) ? res[0]?.text : res?.text;
expect(text).toContain("Elevated mode set to ask");
const store = await readSessionStore(cfg);
expect(store["agent:main:whatsapp:group:123@g.us"]?.elevatedLevel).toBe("on");
}
const store = await readSessionStore(cfg); {
expect(store["agent:main:whatsapp:group:123@g.us"]?.elevatedLevel).toBe("off"); const cfg = isolateStore(
}); makeWhatsAppElevatedCfg(home, { requireMentionInGroups: false }),
}); "group-ignore",
);
it("allows elevated directive in groups when mentioned", async () => { const runEmbeddedPiAgentMock = getRunEmbeddedPiAgentMock();
await withTempHome(async (home) => { runEmbeddedPiAgentMock.mockClear();
const cfg = makeWhatsAppElevatedCfg(home, { requireMentionInGroups: true }); runEmbeddedPiAgentMock.mockResolvedValue({
payloads: [{ text: "ok" }],
const res = await getReplyFromConfig( meta: {
{ durationMs: 1,
Body: "/elevated on", agentMeta: { sessionId: "s", provider: "p", model: "m" },
From: "whatsapp:group:123@g.us", },
To: "whatsapp:+2000", });
Provider: "whatsapp", const res = await getReplyFromConfig(
SenderE164: "+1000", {
CommandAuthorized: true, Body: "/elevated on",
ChatType: "group", From: "whatsapp:group:123@g.us",
WasMentioned: true, To: "whatsapp:+2000",
}, Provider: "whatsapp",
{}, SenderE164: "+1000",
cfg, ChatType: "group",
); WasMentioned: false,
const text = Array.isArray(res) ? res[0]?.text : res?.text; },
expect(text).toContain("Elevated mode set to ask"); {},
cfg,
const store = await readSessionStore(cfg); );
expect(store["agent:main:whatsapp:group:123@g.us"]?.elevatedLevel).toBe("on"); const text = Array.isArray(res) ? res[0]?.text : res?.text;
}); expect(text).toBeUndefined();
}); expect(runEmbeddedPiAgentMock).not.toHaveBeenCalled();
}
it("ignores elevated directive in groups when not mentioned", async () => {
await withTempHome(async (home) => {
getRunEmbeddedPiAgentMock().mockResolvedValue({
payloads: [{ text: "ok" }],
meta: {
durationMs: 1,
agentMeta: { sessionId: "s", provider: "p", model: "m" },
},
});
const cfg = makeWhatsAppElevatedCfg(home, { requireMentionInGroups: false });
const res = await getReplyFromConfig(
{
Body: "/elevated on",
From: "whatsapp:group:123@g.us",
To: "whatsapp:+2000",
Provider: "whatsapp",
SenderE164: "+1000",
ChatType: "group",
WasMentioned: false,
},
{},
cfg,
);
const text = Array.isArray(res) ? res[0]?.text : res?.text;
expect(text).toBeUndefined();
expect(getRunEmbeddedPiAgentMock()).not.toHaveBeenCalled();
}); });
}); });
@@ -439,56 +440,57 @@ describe("trigger handling", () => {
}); });
}); });
it("uses tools.elevated.allowFrom.discord for elevated approval", async () => { it("handles discord elevated allowlist and override behavior", async () => {
await withTempHome(async (home) => { await withTempHome(async (home) => {
const cfg = makeCfg(home); {
cfg.tools = { elevated: { allowFrom: { discord: ["123"] } } }; const cfg = makeCfg(home);
cfg.session = { ...cfg.session, store: join(home, "discord-allow.sessions.json") };
cfg.tools = { elevated: { allowFrom: { discord: ["123"] } } };
const res = await getReplyFromConfig( const res = await getReplyFromConfig(
{ {
Body: "/elevated on", Body: "/elevated on",
From: "discord:123", From: "discord:123",
To: "user:123", To: "user:123",
Provider: "discord", Provider: "discord",
SenderName: "Peter Steinberger", SenderName: "Peter Steinberger",
SenderUsername: "steipete", SenderUsername: "steipete",
SenderTag: "steipete", SenderTag: "steipete",
CommandAuthorized: true, CommandAuthorized: true,
}, },
{}, {},
cfg, cfg,
); );
const text = Array.isArray(res) ? res[0]?.text : res?.text; const text = Array.isArray(res) ? res[0]?.text : res?.text;
expect(text).toContain("Elevated mode set to ask"); expect(text).toContain("Elevated mode set to ask");
const store = await readSessionStore(cfg);
expect(store[MAIN_SESSION_KEY]?.elevatedLevel).toBe("on");
}
const store = await readSessionStore(cfg); {
expect(store[MAIN_SESSION_KEY]?.elevatedLevel).toBe("on"); const cfg = makeCfg(home);
}); cfg.session = { ...cfg.session, store: join(home, "discord-deny.sessions.json") };
}); cfg.tools = {
elevated: {
allowFrom: { discord: [] },
},
};
it("treats explicit discord elevated allowlist as override", async () => { const res = await getReplyFromConfig(
await withTempHome(async (home) => { {
const cfg = makeCfg(home); Body: "/elevated on",
cfg.tools = { From: "discord:123",
elevated: { To: "user:123",
allowFrom: { discord: [] }, Provider: "discord",
}, SenderName: "steipete",
}; },
{},
const res = await getReplyFromConfig( cfg,
{ );
Body: "/elevated on", const text = Array.isArray(res) ? res[0]?.text : res?.text;
From: "discord:123", expect(text).toContain("tools.elevated.allowFrom.discord");
To: "user:123", expect(getRunEmbeddedPiAgentMock()).not.toHaveBeenCalled();
Provider: "discord", }
SenderName: "steipete",
},
{},
cfg,
);
const text = Array.isArray(res) ? res[0]?.text : res?.text;
expect(text).toContain("tools.elevated.allowFrom.discord");
expect(getRunEmbeddedPiAgentMock()).not.toHaveBeenCalled();
}); });
}); });

View File

@@ -30,10 +30,6 @@ import {
} from "../media/input-files.js"; } from "../media/input-files.js";
import { defaultRuntime } from "../runtime.js"; import { defaultRuntime } from "../runtime.js";
import { resolveAssistantStreamDeltaText } from "./agent-event-assistant-text.js"; import { resolveAssistantStreamDeltaText } from "./agent-event-assistant-text.js";
import {
buildAgentMessageFromConversationEntries,
type ConversationEntry,
} from "./agent-prompt.js";
import type { AuthRateLimiter } from "./auth-rate-limit.js"; import type { AuthRateLimiter } from "./auth-rate-limit.js";
import type { ResolvedGatewayAuth } from "./auth.js"; import type { ResolvedGatewayAuth } from "./auth.js";
import { sendJson, setSseHeaders, writeDone } from "./http-common.js"; import { sendJson, setSseHeaders, writeDone } from "./http-common.js";
@@ -41,14 +37,13 @@ import { handleGatewayPostJsonEndpoint } from "./http-endpoint-helpers.js";
import { resolveAgentIdForRequest, resolveSessionKey } from "./http-utils.js"; import { resolveAgentIdForRequest, resolveSessionKey } from "./http-utils.js";
import { import {
CreateResponseBodySchema, CreateResponseBodySchema,
type ContentPart,
type CreateResponseBody, type CreateResponseBody,
type ItemParam,
type OutputItem, type OutputItem,
type ResponseResource, type ResponseResource,
type StreamingEvent, type StreamingEvent,
type Usage, type Usage,
} from "./open-responses.schema.js"; } from "./open-responses.schema.js";
import { buildAgentPrompt } from "./openresponses-prompt.js";
type OpenResponsesHttpOptions = { type OpenResponsesHttpOptions = {
auth: ResolvedGatewayAuth; auth: ResolvedGatewayAuth;
@@ -67,24 +62,6 @@ function writeSseEvent(res: ServerResponse, event: StreamingEvent) {
res.write(`data: ${JSON.stringify(event)}\n\n`); res.write(`data: ${JSON.stringify(event)}\n\n`);
} }
function extractTextContent(content: string | ContentPart[]): string {
if (typeof content === "string") {
return content;
}
return content
.map((part) => {
if (part.type === "input_text") {
return part.text;
}
if (part.type === "output_text") {
return part.text;
}
return "";
})
.filter(Boolean)
.join("\n");
}
type ResolvedResponsesLimits = { type ResolvedResponsesLimits = {
maxBodyBytes: number; maxBodyBytes: number;
maxUrlParts: number; maxUrlParts: number;
@@ -172,52 +149,7 @@ function applyToolChoice(params: {
return { tools }; return { tools };
} }
export function buildAgentPrompt(input: string | ItemParam[]): { export { buildAgentPrompt } from "./openresponses-prompt.js";
message: string;
extraSystemPrompt?: string;
} {
if (typeof input === "string") {
return { message: input };
}
const systemParts: string[] = [];
const conversationEntries: ConversationEntry[] = [];
for (const item of input) {
if (item.type === "message") {
const content = extractTextContent(item.content).trim();
if (!content) {
continue;
}
if (item.role === "system" || item.role === "developer") {
systemParts.push(content);
continue;
}
const normalizedRole = item.role === "assistant" ? "assistant" : "user";
const sender = normalizedRole === "assistant" ? "Assistant" : "User";
conversationEntries.push({
role: normalizedRole,
entry: { sender, body: content },
});
} else if (item.type === "function_call_output") {
conversationEntries.push({
role: "tool",
entry: { sender: `Tool:${item.call_id}`, body: item.output },
});
}
// Skip reasoning and item_reference for prompt building (Phase 1)
}
const message = buildAgentMessageFromConversationEntries(conversationEntries);
return {
message,
extraSystemPrompt: systemParts.length > 0 ? systemParts.join("\n\n") : undefined,
};
}
function resolveOpenResponsesSessionKey(params: { function resolveOpenResponsesSessionKey(params: {
req: IncomingMessage; req: IncomingMessage;

View File

@@ -12,7 +12,7 @@ let InputFileContentPartSchema: typeof import("./open-responses.schema.js").Inpu
let ToolDefinitionSchema: typeof import("./open-responses.schema.js").ToolDefinitionSchema; let ToolDefinitionSchema: typeof import("./open-responses.schema.js").ToolDefinitionSchema;
let CreateResponseBodySchema: typeof import("./open-responses.schema.js").CreateResponseBodySchema; let CreateResponseBodySchema: typeof import("./open-responses.schema.js").CreateResponseBodySchema;
let OutputItemSchema: typeof import("./open-responses.schema.js").OutputItemSchema; let OutputItemSchema: typeof import("./open-responses.schema.js").OutputItemSchema;
let buildAgentPrompt: typeof import("./openresponses-http.js").buildAgentPrompt; let buildAgentPrompt: typeof import("./openresponses-prompt.js").buildAgentPrompt;
describe("OpenResponses Feature Parity", () => { describe("OpenResponses Feature Parity", () => {
beforeAll(async () => { beforeAll(async () => {
@@ -23,7 +23,7 @@ describe("OpenResponses Feature Parity", () => {
CreateResponseBodySchema, CreateResponseBodySchema,
OutputItemSchema, OutputItemSchema,
} = await import("./open-responses.schema.js")); } = await import("./open-responses.schema.js"));
({ buildAgentPrompt } = await import("./openresponses-http.js")); ({ buildAgentPrompt } = await import("./openresponses-prompt.js"));
}); });
describe("Schema Validation", () => { describe("Schema Validation", () => {

View File

@@ -0,0 +1,70 @@
import {
buildAgentMessageFromConversationEntries,
type ConversationEntry,
} from "./agent-prompt.js";
import type { ContentPart, ItemParam } from "./open-responses.schema.js";
function extractTextContent(content: string | ContentPart[]): string {
if (typeof content === "string") {
return content;
}
return content
.map((part) => {
if (part.type === "input_text") {
return part.text;
}
if (part.type === "output_text") {
return part.text;
}
return "";
})
.filter(Boolean)
.join("\n");
}
export function buildAgentPrompt(input: string | ItemParam[]): {
message: string;
extraSystemPrompt?: string;
} {
if (typeof input === "string") {
return { message: input };
}
const systemParts: string[] = [];
const conversationEntries: ConversationEntry[] = [];
for (const item of input) {
if (item.type === "message") {
const content = extractTextContent(item.content).trim();
if (!content) {
continue;
}
if (item.role === "system" || item.role === "developer") {
systemParts.push(content);
continue;
}
const normalizedRole = item.role === "assistant" ? "assistant" : "user";
const sender = normalizedRole === "assistant" ? "Assistant" : "User";
conversationEntries.push({
role: normalizedRole,
entry: { sender, body: content },
});
} else if (item.type === "function_call_output") {
conversationEntries.push({
role: "tool",
entry: { sender: `Tool:${item.call_id}`, body: item.output },
});
}
// Skip reasoning and item_reference for prompt building (Phase 1)
}
const message = buildAgentMessageFromConversationEntries(conversationEntries);
return {
message,
extraSystemPrompt: systemParts.length > 0 ? systemParts.join("\n\n") : undefined,
};
}

View File

@@ -209,6 +209,65 @@ describe("telegram inbound media", () => {
fetchSpy.mockRestore(); fetchSpy.mockRestore();
}); });
it("captures pin and venue location payload fields", async () => {
const { handler, replySpy } = await createBotHandler();
const cases = [
{
message: {
chat: { id: 42, type: "private" as const },
message_id: 5,
caption: "Meet here",
date: 1736380800,
location: {
latitude: 48.858844,
longitude: 2.294351,
horizontal_accuracy: 12,
},
},
assert: (payload: Record<string, unknown>) => {
expect(payload.Body).toContain("Meet here");
expect(payload.Body).toContain("48.858844");
expect(payload.LocationLat).toBe(48.858844);
expect(payload.LocationLon).toBe(2.294351);
expect(payload.LocationSource).toBe("pin");
expect(payload.LocationIsLive).toBe(false);
},
},
{
message: {
chat: { id: 42, type: "private" as const },
message_id: 6,
date: 1736380800,
venue: {
title: "Eiffel Tower",
address: "Champ de Mars, Paris",
location: { latitude: 48.858844, longitude: 2.294351 },
},
},
assert: (payload: Record<string, unknown>) => {
expect(payload.Body).toContain("Eiffel Tower");
expect(payload.LocationName).toBe("Eiffel Tower");
expect(payload.LocationAddress).toBe("Champ de Mars, Paris");
expect(payload.LocationSource).toBe("place");
},
},
] as const;
for (const testCase of cases) {
replySpy.mockClear();
await handler({
message: testCase.message,
me: { username: "openclaw_bot" },
getFile: async () => ({ file_path: "unused" }),
});
expect(replySpy).toHaveBeenCalledTimes(1);
const payload = replySpy.mock.calls[0][0] as Record<string, unknown>;
testCase.assert(payload);
}
});
}); });
describe("telegram media groups", () => { describe("telegram media groups", () => {

View File

@@ -1,88 +0,0 @@
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { onSpy } from "./bot.media.e2e-harness.js";
let handler: (ctx: Record<string, unknown>) => Promise<void>;
let replySpy: ReturnType<typeof vi.fn>;
beforeAll(async () => {
const { createTelegramBot } = await import("./bot.js");
const replyModule = await import("../auto-reply/reply.js");
replySpy = (replyModule as unknown as { __replySpy: ReturnType<typeof vi.fn> }).__replySpy;
onSpy.mockClear();
createTelegramBot({ token: "tok" });
const registeredHandler = onSpy.mock.calls.find((call) => call[0] === "message")?.[1] as (
ctx: Record<string, unknown>,
) => Promise<void>;
expect(registeredHandler).toBeDefined();
handler = registeredHandler;
});
beforeEach(() => {
replySpy.mockClear();
});
function expectSingleReplyPayload(replySpy: ReturnType<typeof vi.fn>) {
expect(replySpy).toHaveBeenCalledTimes(1);
return replySpy.mock.calls[0][0] as Record<string, unknown>;
}
describe("telegram inbound media", () => {
const _INBOUND_MEDIA_TEST_TIMEOUT_MS = process.platform === "win32" ? 30_000 : 20_000;
it(
"includes location text and ctx fields for pins",
async () => {
await handler({
message: {
chat: { id: 42, type: "private" },
message_id: 5,
caption: "Meet here",
date: 1736380800,
location: {
latitude: 48.858844,
longitude: 2.294351,
horizontal_accuracy: 12,
},
},
me: { username: "openclaw_bot" },
getFile: async () => ({ file_path: "unused" }),
});
const payload = expectSingleReplyPayload(replySpy);
expect(payload.Body).toContain("Meet here");
expect(payload.Body).toContain("48.858844");
expect(payload.LocationLat).toBe(48.858844);
expect(payload.LocationLon).toBe(2.294351);
expect(payload.LocationSource).toBe("pin");
expect(payload.LocationIsLive).toBe(false);
},
_INBOUND_MEDIA_TEST_TIMEOUT_MS,
);
it(
"captures venue fields for named places",
async () => {
await handler({
message: {
chat: { id: 42, type: "private" },
message_id: 6,
date: 1736380800,
venue: {
title: "Eiffel Tower",
address: "Champ de Mars, Paris",
location: { latitude: 48.858844, longitude: 2.294351 },
},
},
me: { username: "openclaw_bot" },
getFile: async () => ({ file_path: "unused" }),
});
const payload = expectSingleReplyPayload(replySpy);
expect(payload.Body).toContain("Eiffel Tower");
expect(payload.LocationName).toBe("Eiffel Tower");
expect(payload.LocationAddress).toBe("Champ de Mars, Paris");
expect(payload.LocationSource).toBe("place");
},
_INBOUND_MEDIA_TEST_TIMEOUT_MS,
);
});