diff options
Diffstat (limited to 'packages/cli/src/services/CommandService.ts')
| -rw-r--r-- | packages/cli/src/services/CommandService.ts | 36 |
1 files changed, 28 insertions, 8 deletions
diff --git a/packages/cli/src/services/CommandService.ts b/packages/cli/src/services/CommandService.ts index ef4f4d14..78e4817b 100644 --- a/packages/cli/src/services/CommandService.ts +++ b/packages/cli/src/services/CommandService.ts @@ -30,13 +30,17 @@ export class CommandService { * * This factory method orchestrates the entire command loading process. It * runs all provided loaders in parallel, aggregates their results, handles - * name conflicts by letting the last-loaded command win, and then returns a + * name conflicts for extension commands by renaming them, and then returns a * fully constructed `CommandService` instance. * + * Conflict resolution: + * - Extension commands that conflict with existing commands are renamed to + * `extensionName.commandName` + * - Non-extension commands (built-in, user, project) override earlier commands + * with the same name based on loader order + * * @param loaders An array of objects that conform to the `ICommandLoader` - * interface. The order of loaders is significant: if multiple loaders - * provide a command with the same name, the command from the loader that - * appears later in the array will take precedence. + * interface. Built-in commands should come first, followed by FileCommandLoader. * @param signal An AbortSignal to cancel the loading process. * @returns A promise that resolves to a new, fully initialized `CommandService` instance. */ @@ -57,12 +61,28 @@ export class CommandService { } } - // De-duplicate commands using a Map. The last one found with a given name wins. - // This creates a natural override system based on the order of the loaders - // passed to the constructor. const commandMap = new Map<string, SlashCommand>(); for (const cmd of allCommands) { - commandMap.set(cmd.name, cmd); + let finalName = cmd.name; + + // Extension commands get renamed if they conflict with existing commands + if (cmd.extensionName && commandMap.has(cmd.name)) { + let renamedName = `${cmd.extensionName}.${cmd.name}`; + let suffix = 1; + + // Keep trying until we find a name that doesn't conflict + while (commandMap.has(renamedName)) { + renamedName = `${cmd.extensionName}.${cmd.name}${suffix}`; + suffix++; + } + + finalName = renamedName; + } + + commandMap.set(finalName, { + ...cmd, + name: finalName, + }); } const finalCommands = Object.freeze(Array.from(commandMap.values())); |
