fix(webui): rank skill autocomplete results

This commit is contained in:
chengyongru
2026-07-28 11:36:10 +08:00
committed by chengyongru
parent ef9e687f19
commit fa5d27696a
2 changed files with 106 additions and 10 deletions
+74
View File
@@ -1506,6 +1506,80 @@ describe("ThreadComposer", () => {
expect(input).toHaveValue(`please use $${skillName} `);
});
it("ranks skill name matches ahead of earlier description matches", () => {
render(
<ThreadComposer
onSend={vi.fn()}
placeholder="Type your message..."
skills={[
{
name: "skill-creator",
description: "Create or update AgentSkills",
source: "builtin",
available: true,
},
{
name: "setup-update",
description: "Configure upgrades",
source: "builtin",
available: true,
},
{
name: "update-setup",
description: "One-time setup wizard",
source: "builtin",
available: true,
},
{
name: "up",
description: "Exact match",
source: "workspace",
available: true,
},
]}
/>,
);
const input = screen.getByLabelText("Message input");
fireEvent.change(input, { target: { value: "$up", selectionStart: 3 } });
const options = within(screen.getByRole("listbox", { name: "Slash commands" }))
.getAllByRole("option");
expect(options.map((option) => option.textContent)).toEqual([
"upExact match",
"update-setupOne-time setup wizard",
"setup-updateConfigure upgrades",
"skill-creatorCreate or update AgentSkills",
]);
});
it("keeps a recently selected skill visible at the top of the blank skill menu", () => {
const skills = Array.from({ length: 9 }, (_, index) => ({
name: `skill-${index}`,
description: `Skill ${index}`,
source: "builtin",
available: true,
}));
render(
<ThreadComposer
onSend={vi.fn()}
placeholder="Type your message..."
skills={skills}
/>,
);
const input = screen.getByLabelText("Message input");
fireEvent.change(input, { target: { value: "$skill-8", selectionStart: 8 } });
fireEvent.keyDown(input, { key: "Tab" });
fireEvent.change(input, { target: { value: "$", selectionStart: 1 } });
const options = within(screen.getByRole("listbox", { name: "Slash commands" }))
.getAllByRole("option");
expect(options).toHaveLength(8);
expect(options[0]).toHaveTextContent("skill-8");
expect(options[0]).toHaveTextContent("Recent");
});
it("shows right-side source badges so users can distinguish CLI apps from MCP servers", () => {
render(
<ThreadComposer