Initial support for reloading extensions in the CLI - mcp servers only (#12239)

This commit is contained in:
Jacob MacDonald
2025-10-30 11:05:49 -07:00
committed by GitHub
parent d4cad0cdcc
commit cc081337b7
20 changed files with 437 additions and 107 deletions
+1
View File
@@ -680,6 +680,7 @@ export async function loadCliConfig(
listExtensions: argv.listExtensions || false,
enabledExtensions: argv.extensions,
extensionLoader: extensionManager,
enableExtensionReloading: settings.experimental?.extensionReloading,
blockedMcpServers,
noBrowser: !!process.env['NO_BROWSER'],
summarizeToolOutput: settings.model?.summarizeToolOutput,
+31 -23
View File
@@ -28,6 +28,7 @@ export async function updateExtension(
extensionManager: ExtensionManager,
currentState: ExtensionUpdateState,
dispatchExtensionStateUpdate: (action: ExtensionUpdateAction) => void,
enableExtensionReloading?: boolean,
): Promise<ExtensionUpdateInfo | undefined> {
if (currentState === ExtensionUpdateState.UPDATING) {
return undefined;
@@ -81,7 +82,9 @@ export async function updateExtension(
type: 'SET_STATE',
payload: {
name: extension.name,
state: ExtensionUpdateState.UPDATED_NEEDS_RESTART,
state: enableExtensionReloading
? ExtensionUpdateState.UPDATED
: ExtensionUpdateState.UPDATED_NEEDS_RESTART,
},
});
return {
@@ -109,6 +112,7 @@ export async function updateAllUpdatableExtensions(
extensionsState: Map<string, ExtensionUpdateStatus>,
extensionManager: ExtensionManager,
dispatch: (action: ExtensionUpdateAction) => void,
enableExtensionReloading?: boolean,
): Promise<ExtensionUpdateInfo[]> {
return (
await Promise.all(
@@ -124,6 +128,7 @@ export async function updateAllUpdatableExtensions(
extensionManager,
extensionsState.get(extension.name)!.status,
dispatch,
enableExtensionReloading,
),
),
)
@@ -141,34 +146,37 @@ export async function checkForAllExtensionUpdates(
dispatch: (action: ExtensionUpdateAction) => void,
): Promise<void> {
dispatch({ type: 'BATCH_CHECK_START' });
const promises: Array<Promise<void>> = [];
for (const extension of extensions) {
if (!extension.installMetadata) {
try {
const promises: Array<Promise<void>> = [];
for (const extension of extensions) {
if (!extension.installMetadata) {
dispatch({
type: 'SET_STATE',
payload: {
name: extension.name,
state: ExtensionUpdateState.NOT_UPDATABLE,
},
});
continue;
}
dispatch({
type: 'SET_STATE',
payload: {
name: extension.name,
state: ExtensionUpdateState.NOT_UPDATABLE,
state: ExtensionUpdateState.CHECKING_FOR_UPDATES,
},
});
continue;
promises.push(
checkForExtensionUpdate(extension, extensionManager).then((state) =>
dispatch({
type: 'SET_STATE',
payload: { name: extension.name, state },
}),
),
);
}
dispatch({
type: 'SET_STATE',
payload: {
name: extension.name,
state: ExtensionUpdateState.CHECKING_FOR_UPDATES,
},
});
promises.push(
checkForExtensionUpdate(extension, extensionManager).then((state) =>
dispatch({
type: 'SET_STATE',
payload: { name: extension.name, state },
}),
),
);
await Promise.all(promises);
} finally {
dispatch({ type: 'BATCH_CHECK_END' });
}
await Promise.all(promises);
dispatch({ type: 'BATCH_CHECK_END' });
}
+10
View File
@@ -1075,6 +1075,16 @@ const SETTINGS_SCHEMA = {
description: 'Enable extension management features.',
showInDialog: false,
},
extensionReloading: {
type: 'boolean',
label: 'Extension Reloading',
category: 'Experimental',
requiresRestart: true,
default: false,
description:
'Enables extension loading/unloading within the CLI session.',
showInDialog: false,
},
useModelRouter: {
type: 'boolean',
label: 'Use Model Router',