Merge pull request #290010 from microsoft/brchen/fix-duplicate-mode-action-registration

Fix duplicate command registration for custom chat modes
This commit is contained in:
Bryan Chen
2026-01-23 15:51:17 -08:00
committed by GitHub

View File

@@ -1127,6 +1127,37 @@ class ChatAgentSettingContribution extends Disposable implements IWorkbenchContr
}
/**
* Given builtin and custom modes, returns only the custom mode IDs that should have actions registered.
* Custom modes whose names conflict with builtin modes are excluded.
* If there are name collisions among custom modes, the later mode in the list wins.
*/
function getCustomModesWithUniqueNames(builtinModes: readonly IChatMode[], customModes: readonly IChatMode[]): Set<string> {
const customModeIds = new Set<string>();
const builtinNames = new Set(builtinModes.map(mode => mode.name.get()));
const customNameToId = new Map<string, string>();
for (const mode of customModes) {
const modeName = mode.name.get();
// Skip custom modes that conflict with builtin mode names
if (builtinNames.has(modeName)) {
continue;
}
// If there is a name collision among custom modes, the later one in the list wins
const existingId = customNameToId.get(modeName);
if (existingId) {
customModeIds.delete(existingId);
}
customNameToId.set(modeName, mode.id);
customModeIds.add(mode.id);
}
return customModeIds;
}
/**
* Workbench contribution to register actions for custom chat modes via events
*/
@@ -1142,28 +1173,19 @@ class ChatAgentActionsContribution extends Disposable implements IWorkbenchContr
super();
this._store.add(this._modeActionDisposables);
// Register actions for existing custom modes
const { custom } = this.chatModeService.getModes();
// Register actions for existing custom modes (avoiding name collisions)
const { builtin, custom } = this.chatModeService.getModes();
const currentModeIds = getCustomModesWithUniqueNames(builtin, custom);
for (const mode of custom) {
this._registerModeAction(mode);
if (currentModeIds.has(mode.id)) {
this._registerModeAction(mode);
}
}
// Listen for custom mode changes by tracking snapshots
this._register(this.chatModeService.onDidChangeChatModes(() => {
const { custom } = this.chatModeService.getModes();
const currentModeIds = new Set<string>();
const currentModeNames = new Map<string, string>();
for (const mode of custom) {
const modeName = mode.name.get();
if (currentModeNames.has(modeName)) {
// If there is a name collision, the later one in the list wins
currentModeIds.delete(currentModeNames.get(modeName)!);
}
currentModeNames.set(modeName, mode.id);
currentModeIds.add(mode.id);
}
const { builtin, custom } = this.chatModeService.getModes();
const currentModeIds = getCustomModesWithUniqueNames(builtin, custom);
// Remove modes that no longer exist and those replaced by modes later in the list with same name
for (const modeId of this._modeActionDisposables.keys()) {