mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-05-15 17:03:20 +00:00
fix(providers): guard invalid skill command namespaces
Claude plugin ids come from local settings and installed plugin metadata. Invalid ids such as empty strings or @ should not become command namespaces. Skip plugin folders when no safe plugin name can be derived. This prevents malformed slash commands like /:command from reaching the UI. Add regression coverage for empty and @ plugin ids. Keyboard selection in the slash menu should match mouse selection. Only skills are inserted into the composer because they are provider invocations. Built-in and custom commands execute directly and close the menu on success or failure.
This commit is contained in:
@@ -20,9 +20,14 @@ import {
|
||||
|
||||
const getClaudeHomePath = (): string => path.join(os.homedir(), '.claude');
|
||||
|
||||
const getClaudePluginName = (pluginId: string): string => {
|
||||
const [pluginName] = pluginId.split('@');
|
||||
return pluginName || pluginId;
|
||||
const getClaudePluginName = (pluginId: string): string | null => {
|
||||
const normalizedPluginId = pluginId.trim();
|
||||
if (!normalizedPluginId || normalizedPluginId === '@') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const [pluginName] = normalizedPluginId.split('@');
|
||||
return readOptionalString(pluginName) ?? null;
|
||||
};
|
||||
|
||||
const stripMarkdownExtension = (filename: string): string =>
|
||||
@@ -52,7 +57,7 @@ const listChildDirectories = async (directoryPath: string): Promise<string[]> =>
|
||||
const readClaudePluginName = async (
|
||||
installPath: string,
|
||||
pluginId: string,
|
||||
): Promise<string> => {
|
||||
): Promise<string | null> => {
|
||||
try {
|
||||
const pluginConfig = await readJsonConfig(
|
||||
path.join(installPath, '.claude-plugin', 'plugin.json'),
|
||||
@@ -142,6 +147,10 @@ export class ClaudeSkillsProvider extends SkillsProvider {
|
||||
visitedPluginFolders.add(pluginFolderKey);
|
||||
|
||||
const pluginName = await readClaudePluginName(pluginFolder, pluginId);
|
||||
if (!pluginName) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const commandsPath = path.join(pluginFolder, 'commands');
|
||||
if (await pathExistsAsDirectory(commandsPath)) {
|
||||
skills.push(
|
||||
|
||||
Reference in New Issue
Block a user