feat: Add skill slash commands and fuzzy matching for all commands

- Skills registered as /skill:name commands for quick access
- Toggle via /settings or skills.enableSkillCommands in settings.json
- Fuzzy matching for all slash command autocomplete (type /skbra for /skill:brave-search)
- Moved fuzzy module from coding-agent to tui package for reuse

Closes #630 by @Dwsy (reimplemented with fixes)
This commit is contained in:
Mario Zechner 2026-01-11 17:56:11 +01:00
parent 92486e026c
commit 9655907624
15 changed files with 244 additions and 127 deletions

View file

@ -26,6 +26,7 @@ export interface SettingsConfig {
showImages: boolean;
autoResizeImages: boolean;
blockImages: boolean;
enableSkillCommands: boolean;
steeringMode: "all" | "one-at-a-time";
followUpMode: "all" | "one-at-a-time";
thinkingLevel: ThinkingLevel;
@ -42,6 +43,7 @@ export interface SettingsCallbacks {
onShowImagesChange: (enabled: boolean) => void;
onAutoResizeImagesChange: (enabled: boolean) => void;
onBlockImagesChange: (blocked: boolean) => void;
onEnableSkillCommandsChange: (enabled: boolean) => void;
onSteeringModeChange: (mode: "all" | "one-at-a-time") => void;
onFollowUpModeChange: (mode: "all" | "one-at-a-time") => void;
onThinkingLevelChange: (level: ThinkingLevel) => void;
@ -255,6 +257,16 @@ export class SettingsSelectorComponent extends Container {
values: ["true", "false"],
});
// Skill commands toggle (insert after block-images)
const blockImagesIndex = items.findIndex((item) => item.id === "block-images");
items.splice(blockImagesIndex + 1, 0, {
id: "skill-commands",
label: "Skill commands",
description: "Register skills as /skill:name commands",
currentValue: config.enableSkillCommands ? "true" : "false",
values: ["true", "false"],
});
// Add borders
this.addChild(new DynamicBorder());
@ -276,6 +288,9 @@ export class SettingsSelectorComponent extends Container {
case "block-images":
callbacks.onBlockImagesChange(newValue === "true");
break;
case "skill-commands":
callbacks.onEnableSkillCommandsChange(newValue === "true");
break;
case "steering-mode":
callbacks.onSteeringModeChange(newValue as "all" | "one-at-a-time");
break;