Skip to content

Restart Kernel is unreachable from the UI on Deepnote notebooks #471

Description

@tkislan

Restart Kernel works on Deepnote notebooks but nothing in the UI surfaces it: no toolbar button, and the Command Palette entry is disabled. Interrupt, by contrast, is available and — as of #358 — works end to end. This asks to give Restart the same treatment.

This is a pre-existing gap, not something a specific PR broke. The deepnote.restartkernel* contributions are inherited from vscode-jupyter and scoped to notebookType == 'jupyter-notebook'; when the deepnote notebook type was added in c35f414 (feat(block-execution): use deepnote kernel in venv, #16) none of them were extended to it.

Three independent gates, all of which currently block it

1. Menu when clauses

Every entry requires jupyter-notebook or the Interactive Window, so none renders for a .deepnote file.

Menu package.json when
notebook/toolbar :1071 notebookKernel =~ /^ms-toolsai.jupyter\// && notebookType == 'jupyter-notebook' && notebookType != 'deepnote' && isWorkspaceTrusted && deepnote.kernel.isjupyter
editor/title :990 notebookKernel =~ /^ms-toolsai.jupyter\// && notebookType == 'jupyter-notebook' && isWorkspaceTrusted && deepnote.notebookeditor.canrestartNotebookkernel && config.notebook.globalToolbar != true
interactive/toolbar :1157 interactive window only
commandPalette :1420 (deepnote.ispythonorinteractiveactive || deepnote.isnativeactive) && isWorkspaceTrusted

deepnote.restartkernelandrunallcells (:692) and deepnote.restartkernelandrunuptoselectedcell (:699) have no menu entries at all.

The notebookType != 'deepnote' clause on the toolbar entry is a no-op and is not what hides the button — notebookType is a single string, so == 'jupyter-notebook' already excludes Deepnote. c35f414 appended && notebookType != 'deepnote' uniformly to every jupyter-notebook menu entry in the file (restart, openVariableView, openOutlineView, continueEditSessionInCodespace, notebookeditor.export, replayPylanceLogStep, selectPrecedentCells, selectDependentCells), all of which already carried the == 'jupyter-notebook' conjunct. Worth stating so this isn't read as reverting a deliberate exclusion — there wasn't one.

2. Command enablement

Even reached from the palette, the command is disabled (package.json:681-690):

isWorkspaceTrusted && (deepnote.interactive.canRestartNotebookKernel
  || (notebookKernel =~ /^ms-toolsai.jupyter\// && deepnote.notebookeditor.canrestartNotebookkernel))

3. canrestartNotebookkernel is hardwired false for Deepnote

src/standalone/context/activeEditorContext.ts:147-162 only resolves a kernel for JupyterNotebookView, so both keys fall to the else:

private updateContextOfActiveNotebookKernel(activeEditor?: NotebookEditor) {
    const kernel =
        activeEditor && activeEditor.notebook.notebookType === JupyterNotebookView
            ? this.kernelProvider.get(activeEditor.notebook)
            : undefined;
    if (kernel) {
        ...
        this.canRestartNotebookKernelContext.set(!!canStart).catch(noop);
        const canInterrupt = kernel.status === 'busy';
        this.canInterruptNotebookKernelContext.set(!!canInterrupt).catch(noop);
    } else {
        this.canRestartNotebookKernelContext.set(false).catch(noop);
        this.canInterruptNotebookKernelContext.set(false).catch(noop);
    }

A menu entry alone will not be enough; this method has to learn about deepnote too.

deepnote.kernel.isjupyter is fine — updateSelectedKernelContext (:185-197) already tests isDeepnoteNotebook(document). It depended on controllerRegistration.getSelected(), which returned undefined for every Deepnote notebook until 4ebf56c, so that branch was dead; it works now.

Why this is an omission rather than a policy

  • Deepnote notebooks already restart kernels programmatically — IntegrationKernelRestartHandler calls await kernel.restart() (src/notebooks/deepnote/integrations/integrationKernelRestartHandler.ts:99) whenever integration credentials change, so nothing about the venv/toolkit setup forbids a restart.
  • The command path is in working order: restartKernelImpl and interruptKernel share NotebookCommandListener.wrapKernelMethod, whose getSelected failure (No kernel associated with the notebook, thrown on every Deepnote notebook) was fixed in 4ebf56c and removed outright in af2a832. Interrupt through that path is verified against the built extension by the agent-block Stop E2E; Restart shares it but is not exercised by any test.
  • Interrupt is visible only because it is not a contribution: VS Code renders it from NotebookController.supportsInterrupt, which follows from the interruptHandler set at src/notebooks/controllers/vscodeNotebookController.ts:229. It was never in scope for the c35f414 sweep, which is why one of the pair ended up reachable and the other did not.

Suggested fix

  1. A notebook/toolbar entry for Deepnote alongside the existing one:
{
    "command": "deepnote.restartkernel",
    "group": "navigation/execute@5",
    "when": "notebookType == 'deepnote' && isWorkspaceTrusted && deepnote.notebookeditor.canrestartNotebookkernel"
}
  1. Widen updateContextOfActiveNotebookKernel to resolve the kernel for Deepnote notebooks as well, so canrestartNotebookkernel reflects reality (isDeepnoteNotebook already exists in src/platform/common/utils.ts).

  2. Relax the command enablement so the notebookKernel =~ /^ms-toolsai.jupyter\// arm is not the only path to a truthy value, and add a commandPalette predicate covering notebookType == 'deepnote'.

  3. Decide whether restartkernelandrunallcells / restartkernelandrunuptoselectedcell should be surfaced too, or stay palette-only.

To verify while implementing

  • Does notebookKernel =~ /^ms-toolsai.jupyter\// match anything in this fork? The publisher is Deepnote (package.json), not ms-toolsai, and VS Code derives notebookKernel from the controller id. If it never matches, that arm of the enablement is dead for jupyter-notebook files too and the fix is broader than this issue. Not verified here.
  • What should Restart mean for a Deepnote kernel? kernel.restart() restarts the kernel inside the venv; it does not restart the deepnote-toolkit server (DeepnoteServerStarter). Confirm that is the intended semantics before exposing a button.

Testing

There is no test for Restart on any notebook type today. Whatever lands should come with an E2E in the shape of the Stop test in test/e2e/suite/agentBlock.e2e.test.ts — click the real toolbar button, then assert the kernel actually restarted rather than that the command resolved.

Related, deliberately out of scope

  • Five other upstream toolbar buttons are hidden from Deepnote notebooks by the same == 'jupyter-notebook' scoping: openVariableView, openOutlineView, continueEditSessionInCodespace, notebookeditor.export, replayPylanceLogStep. Each needs its own decision; this issue only asks about Restart.
  • package.json:1109, :1114, :1119 (run-by-line cell toolbar) use unquoted notebookType != deepnote where the rest of the file quotes it, and unlike the restart entry they have no notebookType == 'jupyter-notebook' conjunct backing them up — so there the clause is load-bearing. Whether VS Code's when-clause parser treats the unquoted form identically has not been checked.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions