Add support for /extensions config command (#17895)

This commit is contained in:
christine betts
2026-02-05 11:04:24 -05:00
committed by GitHub
parent e3b8490edf
commit ee58e1e3c1
8 changed files with 908 additions and 211 deletions

View File

@@ -32,6 +32,10 @@ import { SettingScope } from '../../config/settings.js';
import { McpServerEnablementManager } from '../../config/mcp/mcpServerEnablement.js';
import { theme } from '../semantic-colors.js';
import { stat } from 'node:fs/promises';
import { ExtensionSettingScope } from '../../config/extensions/extensionSettings.js';
import { type ConfigLogger } from '../../commands/extensions/utils.js';
import { ConfigExtensionDialog } from '../components/ConfigExtensionDialog.js';
import React from 'react';
function showMessageIfNoExtensions(
context: CommandContext,
@@ -583,6 +587,77 @@ async function uninstallAction(context: CommandContext, args: string) {
}
}
async function configAction(context: CommandContext, args: string) {
const parts = args.trim().split(/\s+/).filter(Boolean);
let scope = ExtensionSettingScope.USER;
const scopeEqIndex = parts.findIndex((p) => p.startsWith('--scope='));
if (scopeEqIndex > -1) {
const scopeVal = parts[scopeEqIndex].split('=')[1];
if (scopeVal === 'workspace') {
scope = ExtensionSettingScope.WORKSPACE;
} else if (scopeVal === 'user') {
scope = ExtensionSettingScope.USER;
}
parts.splice(scopeEqIndex, 1);
} else {
const scopeIndex = parts.indexOf('--scope');
if (scopeIndex > -1) {
const scopeVal = parts[scopeIndex + 1];
if (scopeVal === 'workspace' || scopeVal === 'user') {
scope =
scopeVal === 'workspace'
? ExtensionSettingScope.WORKSPACE
: ExtensionSettingScope.USER;
parts.splice(scopeIndex, 2);
}
}
}
const otherArgs = parts;
const name = otherArgs[0];
const setting = otherArgs[1];
if (name) {
if (name.includes('/') || name.includes('\\') || name.includes('..')) {
context.ui.addItem({
type: MessageType.ERROR,
text: 'Invalid extension name. Names cannot contain path separators or "..".',
});
return;
}
}
const extensionManager = context.services.config?.getExtensionLoader();
if (!(extensionManager instanceof ExtensionManager)) {
debugLogger.error(
`Cannot ${context.invocation?.name} extensions in this environment`,
);
return;
}
const logger: ConfigLogger = {
log: (message: string) => {
context.ui.addItem({ type: MessageType.INFO, text: message.trim() });
},
error: (message: string) =>
context.ui.addItem({ type: MessageType.ERROR, text: message }),
};
return {
type: 'custom_dialog' as const,
component: React.createElement(ConfigExtensionDialog, {
extensionManager,
onClose: () => context.ui.removeComponent(),
extensionName: name,
settingKey: setting,
scope,
configureAll: !name && !setting,
loggerAdapter: logger,
}),
};
}
/**
* Exported for testing.
*/
@@ -701,6 +776,14 @@ const restartCommand: SlashCommand = {
completion: completeExtensions,
};
const configCommand: SlashCommand = {
name: 'config',
description: 'Configure extension settings',
kind: CommandKind.BUILT_IN,
autoExecute: false,
action: configAction,
};
export function extensionsCommand(
enableExtensionReloading?: boolean,
): SlashCommand {
@@ -711,6 +794,7 @@ export function extensionsCommand(
installCommand,
uninstallCommand,
linkCommand,
configCommand,
]
: [];
return {