Change:
When we only have a couple of notebook controllers created for a notebook type, without any kernel detection task or kernel source commands, the "Select Another Kernel" should not show.
I have no kernels in the MRU, clicking Select Kernel brings me to this quickpick, and clicking the back button here does nothing--I think it shouldn't be shown in this scenario ! I have the Jupyter extension installed but not the Python extension installed, with the MRU picker enabled, the Select Kernel dropdown spins forever like this: !

Discussion:
class NotebookKernelDetection extends Disposable implements IWorkbenchContribution { private _detectionMap = new Map<string, IDisposable>(); <del> private _localDisposableStore = new DisposableStore(); </del> <ins> private _localDisposableStore = this._register(new DisposableStore()); </ins> constructor( @INotebookKernelService private readonly _notebookKernelService: INotebookKernelService, @IExtensionService private readonly _extensionService: IExtensionService,

const sourceAction = new SourceAction(action, notebook, isPrimary); const stateChangeListener = sourceAction.onDidChangeState(() => { this._onDidChangeSourceActions.fire({ <del> notebook: notebook.uri </del> <ins> notebook: notebook.uri, viewType: notebook.viewType, </ins> }); }); sourceActions.push([sourceAction, stateChangeListener]);

}); info.actions = sourceActions; this._kernelSources.set(id, info); <del> this._onDidChangeSourceActions.fire({ notebook: notebook.uri }); </del> <ins> this._onDidChangeSourceActions.fire({ notebook: notebook.uri, viewType: notebook.viewType }); </ins> }; this._register(sourceMenu.onDidChange(() => {

const providers = this._kernelSourceActionProviders.get(viewType) ?? []; providers.push(provider); this._kernelSourceActionProviders.set(viewType, providers); <ins> this._onDidChangeSourceActions.fire({ viewType: viewType }); </ins> return toDisposable(() => { const providers = this._kernelSourceActionProviders.get(viewType) ?? [];

function isKernelSourceQuickPickItem(item: IQuickPickItem): item is KernelSourceQuickPickItem { return 'command' in item; } <del> type KernelQuickPickItem = IQuickPickItem | InstallExtensionPick | KernelPick | GroupedKernelsPick | SourcePick | KernelSourceQuickPickItem; </del> <ins> function supportAutoRun(item: QuickPickInput<IQuickPickItem>): item is IQuickPickItem { return 'autoRun' in item && !!item.autoRun; } type KernelQuickPickItem = (IQuickPickItem & { autoRun?: boolean }) | InstallExtensionPick | KernelPick | GroupedKernelsPick | SourcePick | KernelSourceQuickPickItem; </ins> const KERNEL_PICKER_UPDATE_DEBOUNCE = 200; export type KernelQuickPickContext =

const quickPick = this._quickInputService.createQuickPick<KernelQuickPickItem>(); const quickPickItems = this._getKernelPickerQuickPickItems(notebook, matchResult, this._notebookKernelService, scopedContextKeyService); <ins> if (quickPickItems.length === 1 && supportAutoRun(quickPickItems[0])) { return await this._handleQuickPick(editor, quickPickItems[0]); } </ins> quickPick.items = quickPickItems; quickPick.canSelectMany = false; quickPick.placeholder = selected

quickPickItems.push(kernel); }); <del> quickPickItems.push({ type: 'separator' }); </del> <ins> const shouldAutoRun = quickPickItems.length === 0; if (quickPickItems.length > 0) { quickPickItems.push({ type: 'separator' }); } </ins> // select another kernel quick pick quickPickItems.push({ id: 'selectAnother', label: localize('selectAnotherKernel.more', "Select Another Kernel..."), <ins> autoRun: shouldAutoRun </ins> }); return quickPickItems;

quickPick.buttons = [this._quickInputService.backButton]; quickPick.show(); <del> const quickPickItems: QuickPickInput<KernelQuickPickItem>[] = []; </del> disposables.add(quickPick.onDidTriggerButton(button => { if (button === this._quickInputService.backButton) { quickPick.hide();

} } })); <del> this._notebookKernelService.getKernelSourceActions2(notebook).then(actions => { quickPick.busy = false; const matchResult = this._getMatchingResult(notebook); const others = matchResult.all.filter(item => item.extension.value !== JUPYTER_EXTENSION_ID); // group controllers by extension for (const group of groupBy(others, (a, b) => a.extension.value === b.extension.value ? 0 : 1)) { const extension = this._extensionService.extensions.find(extension => extension.identifier.value === group[0].extension.value); const source = extension?.description ?? group[0].extension.value; if (group.length > 1) { quickPickItems.push({ label: source, detail: localize('selectKernelFromExtensionDetail', "Kernels: {0}", group.map(kernel => kernel.label).join(', ')), kernels: group }); } else { quickPickItems.push({ label: group[0].label, detail: source, kernel: group[0] }); } } const validActions = actions.filter(action => action.command); quickPickItems.push(...validActions.map(action => { return { id: typeof action.command! === 'string' ? action.command! : action.command!.id, label: action.label, detail: action.detail, description: action.description, command: action.command }; })); const sourceActionCommands = this._notebookKernelService.getSourceActions(notebook, editor.scopedContextKeyService); for (const sourceAction of sourceActionCommands) { const res: SourcePick = { action: sourceAction, picked: false, label: sourceAction.action.label, detail: (sourceAction.action as MenuItemAction)?.item?.source }; quickPickItems.push(res); </del> <ins> this._calculdateKernelSources(editor).then(quickPickItems => { quickPick.items = quickPickItems; if (quickPick.items.length > 0) { quickPick.busy = false; </ins> } <ins> }); disposables.add(Event.debounce<void, void>( Event.any( this._notebookKernelService.onDidChangeSourceActions, this._notebookKernelService.onDidAddKernel, this._notebookKernelService.onDidRemoveKernel ), (last, _current) => last, KERNEL_PICKER_UPDATE_DEBOUNCE )(async () => { quickPick.busy = true; const quickPickItems = await this._calculdateKernelSources(editor); </ins> quickPick.items = quickPickItems; <del> }); </del> <ins> quickPick.busy = false; })); </ins> }).finally(() => { disposables.dispose(); }); } <ins> private async _calculdateKernelSources(editor: IActiveNotebookEditor) { const notebook: NotebookTextModel = editor.textModel; const actions = await this._notebookKernelService.getKernelSourceActions2(notebook); const quickPickItems: QuickPickInput<KernelQuickPickItem>[] = []; const matchResult = this._getMatchingResult(notebook); const others = matchResult.all.filter(item => item.extension.value !== JUPYTER_EXTENSION_ID); // group controllers by extension for (const group of groupBy(others, (a, b) => a.extension.value === b.extension.value ? 0 : 1)) { const extension = this._extensionService.extensions.find(extension => extension.identifier.value === group[0].extension.value); const source = extension?.description ?? group[0].extension.value; if (group.length > 1) { quickPickItems.push({ label: source, detail: localize('selectKernelFromExtensionDetail', "Kernels: {0}", group.map(kernel => kernel.label).join(', ')), kernels: group }); } else { quickPickItems.push({ label: group[0].label, detail: source, kernel: group[0] }); } } const validActions = actions.filter(action => action.command); quickPickItems.push(...validActions.map(action => { return { id: typeof action.command! === 'string' ? action.command! : action.command!.id, label: action.label, detail: action.detail, description: action.description, command: action.command }; })); const sourceActionCommands = this._notebookKernelService.getSourceActions(notebook, editor.scopedContextKeyService); for (const sourceAction of sourceActionCommands) { const res: SourcePick = { action: sourceAction, picked: false, label: sourceAction.action.label, detail: (sourceAction.action as MenuItemAction)?.item?.source }; quickPickItems.push(res); } return quickPickItems; } </ins> private async _selectOneKernel(notebook: NotebookTextModel, source: string, kernels: INotebookKernel[]) { const quickPickItems: QuickPickInput<KernelPick>[] = kernels.map(kernel => toKernelQuickPick(kernel, undefined)); const quickPick = this._quickInputService.createQuickPick<KernelQuickPickItem>();

} export interface INotebookSourceActionChangeEvent { <del> notebook: URI; </del> <ins> notebook?: URI; viewType: string; </ins> } export interface IKernelSourceActionProvider {