Files
dev/third_party/pi/packages/tui/test/autocomplete-skill-slash.test.ts
alexion 6081e3e325 chore(vendor): import pi 1.3.0
Imported as a linear vendor commit so forge rebases do not replay the upstream root tree.

git-subtree-dir: third_party/pi

git-subtree-split: 71023aec1546d6d677a65669c5665c0927ce0dd0
2026-10-15 17:58:48 -04:00

99 lines
3.5 KiB
TypeScript

import assert from "node:assert";
import { describe, it } from "node:test";
import { CombinedAutocompleteProvider } from "../src/autocomplete.ts";
describe("CombinedAutocompleteProvider slash-command filter", () => {
const commands = [
{ name: "skill:deep-research", description: "Multi-agent deep research" },
{ name: "skill:research-idea", description: "Refine a raw idea into a falsifiable seed" },
{ name: "skill:to-sidecar", description: "Route work to a sidecar" },
{ name: "skill:brainstorm", description: "Generate ideas" },
{ name: "model", description: "Select the active model" },
];
async function suggestionsFor(prefix: string): Promise<string[]> {
const provider = new CombinedAutocompleteProvider(commands, process.cwd());
const line = `/${prefix}`;
const result = await provider.getSuggestions([line], 0, line.length, {
signal: new AbortController().signal,
});
assert.ok(result, `expected suggestions for "/${prefix}"`);
return result.items.map((item) => item.value);
}
it("ranks skill:research-idea first for query 'idea'", async () => {
const items = await suggestionsFor("idea");
assert.equal(items[0], "skill:research-idea");
assert.ok(items.indexOf("skill:deep-research") > items.indexOf("skill:research-idea"));
});
it("keeps ordinary slash commands matching", async () => {
const items = await suggestionsFor("mod");
assert.ok(items.includes("model"));
});
it("completes commands after leading whitespace and preserves it", async () => {
const provider = new CombinedAutocompleteProvider([{ name: "model" }], process.cwd());
for (const [line, expected] of [
[" /", " /model "],
[" /mod", " /model "],
["\t/mod", "\t/model "],
] as const) {
const result = await provider.getSuggestions([line], 0, line.length, {
signal: new AbortController().signal,
});
assert.ok(result);
assert.equal(result.prefix, line.trimStart());
assert.deepStrictEqual(
result.items.map((item) => item.value),
["model"],
);
const applied = provider.applyCompletion([line], 0, line.length, result.items[0]!, result.prefix);
assert.equal(applied.lines[0], expected);
assert.equal(applied.cursorCol, expected.length);
}
});
it("completes command arguments after leading whitespace", async () => {
const provider = new CombinedAutocompleteProvider(
[
{
name: "model",
getArgumentCompletions: (prefix: string) => {
assert.equal(prefix, "son");
return [{ value: "sonnet", label: "sonnet" }];
},
},
],
process.cwd(),
);
const line = " /model son";
const result = await provider.getSuggestions([line], 0, line.length, {
signal: new AbortController().signal,
});
assert.ok(result);
assert.equal(result.prefix, "son");
const applied = provider.applyCompletion([line], 0, line.length, result.items[0]!, result.prefix);
assert.equal(applied.lines[0], " /model sonnet");
});
it("keeps explicit skill: queries working", async () => {
const items = await suggestionsFor("skill:side");
assert.ok(items.includes("skill:to-sidecar"));
});
// Regression test for #9944.
it("lists skills while typing the skill prefix", async () => {
const items = await suggestionsFor("skill");
assert.deepStrictEqual(
items.filter((item) => item.startsWith("skill:")),
commands.filter((command) => command.name.startsWith("skill:")).map((command) => command.name),
);
});
it("keeps fuzzy skill-prefix shorthand working", async () => {
const items = await suggestionsFor("skbra");
assert.ok(items.includes("skill:brainstorm"));
});
});