You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
All 19 deepnote.add*Block* commands are contributed with no enablement clause, and their handlers never check the active notebook's type — so they appear in the Command Palette for every notebook and will insert a Deepnote-shaped cell into an .ipynb or Interactive Window.
This is a pre-existing gap, not something introduced by a specific PR: on origin/main all 18 pre-existing add-block commands already have enablement: (none) and none of them appear in contributes.menus.commandPalette. deepnote.addAgentBlock (added in #358) simply follows the same pattern. Filing as a sweep rather than patching one command.
Affected commands
All entries below are in package.json under contributes.commands with noenablement key. Handlers all live in src/notebooks/deepnote/deepnoteNotebookCommandListener.ts; ids are declared in src/platform/common/constants.ts:230-248.
Command id
Palette title
package.json
Registration
Handler
deepnote.addAgentBlock
Add Agent Block
package.json:177
:170
addAgentBlock():243
deepnote.addSqlBlock
Add SQL Block
package.json:183
:171
addSqlBlock():305
deepnote.addBigNumberChartBlock
Add Big Number Block
package.json:189
:173
addBigNumberChartBlock():351
deepnote.addChartBlock
Add Chart Block
package.json:195
:175
addChartBlock():394
deepnote.addInputTextBlock
Add Input Text Block
package.json:201
:177
addInputBlock():451
deepnote.addInputTextareaBlock
Add Input Textarea Block
package.json:207
:180
addInputBlock():451
deepnote.addInputSelectBlock
Add Input Select Block
package.json:213
:183
addInputBlock():451
deepnote.addInputSliderBlock
Add Input Slider Block
package.json:219
:186
addInputBlock():451
deepnote.addInputCheckboxBlock
Add Input Checkbox Block
package.json:225
:189
addInputBlock():451
deepnote.addInputDateBlock
Add Input Date Block
package.json:231
:192
addInputBlock():451
deepnote.addInputDateRangeBlock
Add Input Date Range Block
package.json:237
:195
addInputBlock():451
deepnote.addInputFileBlock
Add Input File Block
package.json:243
:198
addInputBlock():451
deepnote.addButtonBlock
Add Button Block
package.json:249
:201
addInputBlock():451
deepnote.addInputBlock
Add Input Block
package.json:255
:204
addInputBlockThroughPicker():537
deepnote.addTextBlock
Add Text Block
package.json:261
:207
addTextBlockThroughPicker():499
deepnote.addTextBlockParagraph
Add Paragraph Block
package.json:267
:225
addTextBlockCommandHandler():582
deepnote.addTextBlockHeading1
Add Heading 1 Block
package.json:273
:210
addTextBlockCommandHandler():582
deepnote.addTextBlockHeading2
Add Heading 2 Block
package.json:279
:215
addTextBlockCommandHandler():582
deepnote.addTextBlockHeading3
Add Heading 3 Block
package.json:285
:220
addTextBlockCommandHandler():582
Supporting facts, all verified on this branch:
grep -c notebookType src/notebooks/deepnote/deepnoteNotebookCommandListener.ts → 0. Every handler starts from window.activeNotebookEditor and inserts unconditionally.
No add-block command has a contributes.menus.commandPalette entry, so none is hidden from the palette.
Only 6 of the 19 are surfaced in the toolbar (notebook/toolbar, package.json:1041, :1046, :1051, :1056, :1061, :1066) — and those entries already carry "when": "notebookType == 'deepnote'". The other 13 are palette-only, so the palette is currently their only entry point and it is ungated.
Symptom
Open any .ipynb (or an Interactive Window) so it is the active notebook editor.
Command Palette → e.g. Deepnote: Add SQL Block.
A cell is inserted into the Jupyter notebook with Deepnote-only metadata (__deepnotePocket, deepnote_variable_name, …) and a Deepnote-specific language/content — sql for SQL blocks, json holding a Vega-Lite or big-number spec for chart blocks, plaintext for the agent block.
The cell is meaningless to the Jupyter kernel and will fail if run. Nothing crashes, and the extension does not corrupt the file.
Persisted damage is small — this is mostly a UX/discoverability bug. VS Code's built-in .ipynb serializer writes only the nested cell.metadata.metadata (plus id / attachments / execution_count) back to disk; top-level extension keys like __deepnotePocket are dropped on save. The same nesting convention is visible in this repo at src/platform/common/utils.ts:437 (getCellMetadata — "metadata property is never optional"). Consequently, reopening the saved .ipynb yields a plain cell with odd content and no Deepnote metadata: what survives is a stray cell, not a Deepnote block. (Not observed end-to-end in a running VS Code; based on the serializer's documented metadata shape and this repo's own handling of it.)
Suggested fix
Add an enablement clause to each of the 19 command contributions, matching the predicate the toolbar menu entries already use:
The notebookType == … form is already established in this file — see package.json:369, :376 and :426 (notebookType == jupyter-notebook && isWorkspaceTrusted && …) for enablement, and :1041–:1066 for the quoted notebookType == 'deepnote' form used by the toolbar menus. Reuse the quoted form for consistency with the sibling menu entries.
enablement greys the command out and blocks palette invocation, which covers the reported symptom on its own. Optionally add a cheap handler-side guard in deepnoteNotebookCommandListener.ts next to the existing if (!editor) checks, so programmatic commands.executeCommand(...) callers get the same answer as the palette:
if(editor.notebook.notebookType!==DEEPNOTE_NOTEBOOK_TYPE){thrownewError(l10n.t('Deepnote blocks can only be added to Deepnote notebooks'));}
Both changes are mechanical and easy to unit-test — the existing suite in deepnoteNotebookCommandListener.unit.test.ts already drives these commands.
The agent block's execution-routing exposure, which is a genuinely sharper case and deserves its own treatment. __deepnotePocket.type === 'agent' is read by isAgentCell (src/notebooks/deepnote/dataConversionUtils.ts:30) inside VSCodeNotebookController.executeQueuedCells (src/notebooks/controllers/vscodeNotebookController.ts:653) — a class instantiated for jupyter-notebook and interactive as well as deepnote (src/notebooks/controllers/controllerRegistration.ts:149, :362). A cell carrying that metadata is routed to executeAgentCellinstead of the kernel, so it changes what "Run cell" does, not just how the cell looks. Palette enablement does not fully close that: the metadata can also arrive in-session by copying a cell from a .deepnote editor and pasting it into an .ipynb (expected from VS Code's cell clipboard carrying metadata; not verified here). Note that metadata loaded from an .ipynb file lands nested under cell.metadata.metadata and therefore would not trigger routing — the exposure is in-session only. Track separately if the routing guard is wanted.
Other ungated Deepnote-category commands (deepnote.newNotebook, deepnote.addNotebookToProject, deepnote.renameProject, the deepnote.environments.* family, …). ~46 Deepnote commands lack enablement in total; those are tree/project commands that error harmlessly rather than mutating an unrelated document, so they are a separate cleanup.
All 19
deepnote.add*Block*commands are contributed with noenablementclause, and their handlers never check the active notebook's type — so they appear in the Command Palette for every notebook and will insert a Deepnote-shaped cell into an.ipynbor Interactive Window.This is a pre-existing gap, not something introduced by a specific PR: on
origin/mainall 18 pre-existing add-block commands already haveenablement: (none)and none of them appear incontributes.menus.commandPalette.deepnote.addAgentBlock(added in #358) simply follows the same pattern. Filing as a sweep rather than patching one command.Affected commands
All entries below are in
package.jsonundercontributes.commandswith noenablementkey. Handlers all live insrc/notebooks/deepnote/deepnoteNotebookCommandListener.ts; ids are declared insrc/platform/common/constants.ts:230-248.package.jsondeepnote.addAgentBlockpackage.json:177:170addAgentBlock():243deepnote.addSqlBlockpackage.json:183:171addSqlBlock():305deepnote.addBigNumberChartBlockpackage.json:189:173addBigNumberChartBlock():351deepnote.addChartBlockpackage.json:195:175addChartBlock():394deepnote.addInputTextBlockpackage.json:201:177addInputBlock():451deepnote.addInputTextareaBlockpackage.json:207:180addInputBlock():451deepnote.addInputSelectBlockpackage.json:213:183addInputBlock():451deepnote.addInputSliderBlockpackage.json:219:186addInputBlock():451deepnote.addInputCheckboxBlockpackage.json:225:189addInputBlock():451deepnote.addInputDateBlockpackage.json:231:192addInputBlock():451deepnote.addInputDateRangeBlockpackage.json:237:195addInputBlock():451deepnote.addInputFileBlockpackage.json:243:198addInputBlock():451deepnote.addButtonBlockpackage.json:249:201addInputBlock():451deepnote.addInputBlockpackage.json:255:204addInputBlockThroughPicker():537deepnote.addTextBlockpackage.json:261:207addTextBlockThroughPicker():499deepnote.addTextBlockParagraphpackage.json:267:225addTextBlockCommandHandler():582deepnote.addTextBlockHeading1package.json:273:210addTextBlockCommandHandler():582deepnote.addTextBlockHeading2package.json:279:215addTextBlockCommandHandler():582deepnote.addTextBlockHeading3package.json:285:220addTextBlockCommandHandler():582Supporting facts, all verified on this branch:
grep -c notebookType src/notebooks/deepnote/deepnoteNotebookCommandListener.ts→0. Every handler starts fromwindow.activeNotebookEditorand inserts unconditionally.contributes.menus.commandPaletteentry, so none is hidden from the palette.notebook/toolbar,package.json:1041,:1046,:1051,:1056,:1061,:1066) — and those entries already carry"when": "notebookType == 'deepnote'". The other 13 are palette-only, so the palette is currently their only entry point and it is ungated.Symptom
.ipynb(or an Interactive Window) so it is the active notebook editor.Deepnote: Add SQL Block.__deepnotePocket,deepnote_variable_name, …) and a Deepnote-specific language/content —sqlfor SQL blocks,jsonholding a Vega-Lite or big-number spec for chart blocks,plaintextfor the agent block.The cell is meaningless to the Jupyter kernel and will fail if run. Nothing crashes, and the extension does not corrupt the file.
Persisted damage is small — this is mostly a UX/discoverability bug. VS Code's built-in
.ipynbserializer writes only the nestedcell.metadata.metadata(plusid/attachments/execution_count) back to disk; top-level extension keys like__deepnotePocketare dropped on save. The same nesting convention is visible in this repo atsrc/platform/common/utils.ts:437(getCellMetadata— "metadata property is never optional"). Consequently, reopening the saved.ipynbyields a plain cell with odd content and no Deepnote metadata: what survives is a stray cell, not a Deepnote block. (Not observed end-to-end in a running VS Code; based on the serializer's documented metadata shape and this repo's own handling of it.)Suggested fix
Add an
enablementclause to each of the 19 command contributions, matching the predicate the toolbar menu entries already use:{ "command": "deepnote.addSqlBlock", "title": "%deepnote.commands.addSqlBlock.title%", "category": "Deepnote", "icon": "$(database)", "enablement": "notebookType == 'deepnote'" }The
notebookType == …form is already established in this file — seepackage.json:369,:376and:426(notebookType == jupyter-notebook && isWorkspaceTrusted && …) for enablement, and:1041–:1066for the quotednotebookType == 'deepnote'form used by the toolbar menus. Reuse the quoted form for consistency with the sibling menu entries.enablementgreys the command out and blocks palette invocation, which covers the reported symptom on its own. Optionally add a cheap handler-side guard indeepnoteNotebookCommandListener.tsnext to the existingif (!editor)checks, so programmaticcommands.executeCommand(...)callers get the same answer as the palette:Both changes are mechanical and easy to unit-test — the existing suite in
deepnoteNotebookCommandListener.unit.test.tsalready drives these commands.Out of scope
__deepnotePocket.type === 'agent'is read byisAgentCell(src/notebooks/deepnote/dataConversionUtils.ts:30) insideVSCodeNotebookController.executeQueuedCells(src/notebooks/controllers/vscodeNotebookController.ts:653) — a class instantiated forjupyter-notebookandinteractiveas well asdeepnote(src/notebooks/controllers/controllerRegistration.ts:149,:362). A cell carrying that metadata is routed toexecuteAgentCellinstead of the kernel, so it changes what "Run cell" does, not just how the cell looks. Palette enablement does not fully close that: the metadata can also arrive in-session by copying a cell from a.deepnoteeditor and pasting it into an.ipynb(expected from VS Code's cell clipboard carrying metadata; not verified here). Note that metadata loaded from an.ipynbfile lands nested undercell.metadata.metadataand therefore would not trigger routing — the exposure is in-session only. Track separately if the routing guard is wanted.deepnote.newNotebook,deepnote.addNotebookToProject,deepnote.renameProject, thedeepnote.environments.*family, …). ~46 Deepnote commands lackenablementin total; those are tree/project commands that error harmlessly rather than mutating an unrelated document, so they are a separate cleanup.