





















@@ -0,0 +1,53 @@
1+import { describe, expect, it } from "vitest";
2+3+import { parseSlashCommandOrNull } from "./commands-slash-parse.js";
4+5+describe("parseSlashCommandOrNull", () => {
6+const opts = { invalidMessage: "invalid" };
7+8+it("returns null when the input doesn't start with the slash prefix", () => {
9+expect(parseSlashCommandOrNull("hello world", "/config", opts)).toBeNull();
10+});
11+12+it("parses action + args when the input has a clean word boundary", () => {
13+const result = parseSlashCommandOrNull("/config show enabled", "/config", opts);
14+expect(result).toEqual({ ok: true, action: "show", args: "enabled" });
15+});
16+17+it("returns the default action on an empty body", () => {
18+const result = parseSlashCommandOrNull("/config", "/config", { ...opts, defaultAction: "show" });
19+expect(result).toEqual({ ok: true, action: "show", args: "" });
20+});
21+22+describe("regression: #84572 — prefix match must require a word boundary", () => {
23+// Previously, `/config-check <args>` matched the `/config` handler
24+// via a naive `startsWith` and surfaced as an invalid action, blocking
25+// any skill whose name shared a prefix with a built-in command.
26+it("does not match a longer command name with a hyphen tail (`/config-check`)", () => {
27+expect(parseSlashCommandOrNull("/config-check arg1 arg2", "/config", opts)).toBeNull();
28+});
29+30+it("does not match a longer command name with no whitespace after prefix", () => {
31+expect(parseSlashCommandOrNull("/configfoo", "/config", opts)).toBeNull();
32+});
33+34+it("does not match when prefix sits in the middle of a longer word", () => {
35+// /modelsy should not be captured by /models
36+expect(parseSlashCommandOrNull("/modelsy", "/models", opts)).toBeNull();
37+});
38+39+it("still matches when the boundary is a colon (`/config:json`)", () => {
40+// Some clients allow `cmd:subkey` to pass through to the action parser
41+// when there's no whitespace — the boundary character is still a
42+// separator and not an alpha continuation.
43+const result = parseSlashCommandOrNull("/config:json", "/config", opts);
44+expect(result).not.toBeNull();
45+expect(result?.ok).toBe(true);
46+});
47+48+it("still matches the exact prefix with leading whitespace", () => {
49+const result = parseSlashCommandOrNull(" /config show ", "/config", opts);
50+expect(result).toEqual({ ok: true, action: "show", args: "" });
51+});
52+});
53+});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。