Files
clawdbot/src/auto-reply/commands-registry.test.ts
2026-01-18 11:01:16 +00:00

154 lines
4.9 KiB
TypeScript

import { afterEach, beforeEach, describe, expect, it } from "vitest";
import {
buildCommandText,
getCommandDetection,
listChatCommands,
listChatCommandsForConfig,
listNativeCommandSpecs,
listNativeCommandSpecsForConfig,
normalizeCommandBody,
shouldHandleTextCommands,
} from "./commands-registry.js";
import { setActivePluginRegistry } from "../plugins/runtime.js";
import { createTestRegistry } from "../test-utils/channel-plugins.js";
beforeEach(() => {
setActivePluginRegistry(createTestRegistry([]));
});
afterEach(() => {
setActivePluginRegistry(createTestRegistry([]));
});
describe("commands registry", () => {
it("builds command text with args", () => {
expect(buildCommandText("status")).toBe("/status");
expect(buildCommandText("model", "gpt-5")).toBe("/model gpt-5");
});
it("exposes native specs", () => {
const specs = listNativeCommandSpecs();
expect(specs.find((spec) => spec.name === "help")).toBeTruthy();
expect(specs.find((spec) => spec.name === "stop")).toBeTruthy();
expect(specs.find((spec) => spec.name === "whoami")).toBeTruthy();
expect(specs.find((spec) => spec.name === "compact")).toBeFalsy();
});
it("filters commands based on config flags", () => {
const disabled = listChatCommandsForConfig({
commands: { config: false, debug: false },
});
expect(disabled.find((spec) => spec.key === "config")).toBeFalsy();
expect(disabled.find((spec) => spec.key === "debug")).toBeFalsy();
const enabled = listChatCommandsForConfig({
commands: { config: true, debug: true },
});
expect(enabled.find((spec) => spec.key === "config")).toBeTruthy();
expect(enabled.find((spec) => spec.key === "debug")).toBeTruthy();
const nativeDisabled = listNativeCommandSpecsForConfig({
commands: { config: false, debug: false, native: true },
});
expect(nativeDisabled.find((spec) => spec.name === "config")).toBeFalsy();
expect(nativeDisabled.find((spec) => spec.name === "debug")).toBeFalsy();
});
it("appends skill commands when provided", () => {
const skillCommands = [
{
name: "demo_skill",
skillName: "demo-skill",
description: "Demo skill",
},
];
const commands = listChatCommandsForConfig(
{
commands: { config: false, debug: false },
},
{ skillCommands },
);
expect(commands.find((spec) => spec.nativeName === "demo_skill")).toBeTruthy();
const native = listNativeCommandSpecsForConfig(
{ commands: { config: false, debug: false, native: true } },
{ skillCommands },
);
expect(native.find((spec) => spec.name === "demo_skill")).toBeTruthy();
});
it("detects known text commands", () => {
const detection = getCommandDetection();
expect(detection.exact.has("/commands")).toBe(true);
expect(detection.exact.has("/compact")).toBe(true);
expect(detection.exact.has("/whoami")).toBe(true);
expect(detection.exact.has("/id")).toBe(true);
for (const command of listChatCommands()) {
for (const alias of command.textAliases) {
expect(detection.exact.has(alias.toLowerCase())).toBe(true);
expect(detection.regex.test(alias)).toBe(true);
expect(detection.regex.test(`${alias}:`)).toBe(true);
if (command.acceptsArgs) {
expect(detection.regex.test(`${alias} list`)).toBe(true);
expect(detection.regex.test(`${alias}: list`)).toBe(true);
} else {
expect(detection.regex.test(`${alias} list`)).toBe(false);
expect(detection.regex.test(`${alias}: list`)).toBe(false);
}
}
}
expect(detection.regex.test("try /status")).toBe(false);
});
it("respects text command gating", () => {
const cfg = { commands: { text: false } };
expect(
shouldHandleTextCommands({
cfg,
surface: "discord",
commandSource: "text",
}),
).toBe(false);
expect(
shouldHandleTextCommands({
cfg,
surface: "whatsapp",
commandSource: "text",
}),
).toBe(true);
expect(
shouldHandleTextCommands({
cfg,
surface: "discord",
commandSource: "native",
}),
).toBe(true);
});
it("normalizes telegram-style command mentions for the current bot", () => {
expect(normalizeCommandBody("/help@clawdbot", { botUsername: "clawdbot" })).toBe("/help");
expect(
normalizeCommandBody("/help@clawdbot args", {
botUsername: "clawdbot",
}),
).toBe("/help args");
expect(
normalizeCommandBody("/help@clawdbot: args", {
botUsername: "clawdbot",
}),
).toBe("/help args");
});
it("keeps telegram-style command mentions for other bots", () => {
expect(normalizeCommandBody("/help@otherbot", { botUsername: "clawdbot" })).toBe(
"/help@otherbot",
);
});
it("normalizes dock command aliases", () => {
expect(normalizeCommandBody("/dock_telegram")).toBe("/dock-telegram");
});
});