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
- A
notebook/toolbar entry for Deepnote alongside the existing one:
-
Widen updateContextOfActiveNotebookKernel to resolve the kernel for Deepnote notebooks as well, so canrestartNotebookkernel reflects reality (isDeepnoteNotebook already exists in src/platform/common/utils.ts).
-
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'.
-
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.
Restart Kernelworks 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 tonotebookType == 'jupyter-notebook'; when thedeepnotenotebook 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
whenclausesEvery entry requires
jupyter-notebookor the Interactive Window, so none renders for a.deepnotefile.package.jsonwhennotebook/toolbar:1071notebookKernel =~ /^ms-toolsai.jupyter\// && notebookType == 'jupyter-notebook' && notebookType != 'deepnote' && isWorkspaceTrusted && deepnote.kernel.isjupytereditor/title:990notebookKernel =~ /^ms-toolsai.jupyter\// && notebookType == 'jupyter-notebook' && isWorkspaceTrusted && deepnote.notebookeditor.canrestartNotebookkernel && config.notebook.globalToolbar != trueinteractive/toolbar:1157commandPalette:1420(deepnote.ispythonorinteractiveactive || deepnote.isnativeactive) && isWorkspaceTrusteddeepnote.restartkernelandrunallcells(:692) anddeepnote.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 —notebookTypeis a single string, so== 'jupyter-notebook'already excludes Deepnote. c35f414 appended&& notebookType != 'deepnote'uniformly to everyjupyter-notebookmenu 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
enablementEven reached from the palette, the command is disabled (
package.json:681-690):3.
canrestartNotebookkernelis hardwired false for Deepnotesrc/standalone/context/activeEditorContext.ts:147-162only resolves a kernel forJupyterNotebookView, so both keys fall to theelse:A menu entry alone will not be enough; this method has to learn about
deepnotetoo.deepnote.kernel.isjupyteris fine —updateSelectedKernelContext(:185-197) already testsisDeepnoteNotebook(document). It depended oncontrollerRegistration.getSelected(), which returnedundefinedfor every Deepnote notebook until 4ebf56c, so that branch was dead; it works now.Why this is an omission rather than a policy
IntegrationKernelRestartHandlercallsawait kernel.restart()(src/notebooks/deepnote/integrations/integrationKernelRestartHandler.ts:99) whenever integration credentials change, so nothing about the venv/toolkit setup forbids a restart.restartKernelImplandinterruptKernelshareNotebookCommandListener.wrapKernelMethod, whosegetSelectedfailure (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.NotebookController.supportsInterrupt, which follows from theinterruptHandlerset atsrc/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
notebook/toolbarentry for Deepnote alongside the existing one:{ "command": "deepnote.restartkernel", "group": "navigation/execute@5", "when": "notebookType == 'deepnote' && isWorkspaceTrusted && deepnote.notebookeditor.canrestartNotebookkernel" }Widen
updateContextOfActiveNotebookKernelto resolve the kernel for Deepnote notebooks as well, socanrestartNotebookkernelreflects reality (isDeepnoteNotebookalready exists insrc/platform/common/utils.ts).Relax the command
enablementso thenotebookKernel =~ /^ms-toolsai.jupyter\//arm is not the only path to a truthy value, and add acommandPalettepredicate coveringnotebookType == 'deepnote'.Decide whether
restartkernelandrunallcells/restartkernelandrunuptoselectedcellshould be surfaced too, or stay palette-only.To verify while implementing
notebookKernel =~ /^ms-toolsai.jupyter\//match anything in this fork? ThepublisherisDeepnote(package.json), notms-toolsai, and VS Code derivesnotebookKernelfrom the controller id. If it never matches, that arm of theenablementis dead forjupyter-notebookfiles too and the fix is broader than this issue. Not verified here.kernel.restart()restarts the kernel inside the venv; it does not restart thedeepnote-toolkitserver (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
== '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 unquotednotebookType != deepnotewhere the rest of the file quotes it, and unlike the restart entry they have nonotebookType == '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.