Skip to content

feat(chatbook): add Convert to Chatbook for ordinary notebooks - #508

Merged
mbektas merged 2 commits into
plmbr:mainfrom
pjdoland:feat/504-convert-to-chatbook
Sep 29, 2026
Merged

mbektas merged 2 commits into
plmbr:mainfrom
pjdoland:feat/504-convert-to-chatbook

Conversation

@pjdoland

@pjdoland pjdoland commented Sep 28, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

This adds the reverse of Export as code notebook: a way to turn an existing notebook into a Chatbook, as requested in #504. Ordinary notebooks get a Convert to Chatbook toolbar button and a Convert notebook to Chatbook palette command. Both write a Chatbook copy beside the original and open it. Every code cell arrives as a Cd cell, ready to switch to natural language.

Solution

What the copy contains

  • The copy is named <stem>-chatbook.ipynb, numbered when that name is taken, following the export's -python naming. It uses the export's collision-safe save, which is now shared as saveNotebookCopy.
  • It is built from what is in the editor, so unsaved changes are included. The original is not changed.
  • Code cells get nbi.chatbook = {mode: 'code', origin: 'code', codeSource, generatedCode} and run exactly as written.
  • Everything else is kept: outputs, execution counts, cell ids and tags, attachments, markdown and raw cells, and other notebook metadata. Only the kernelspec and language_info change to Chatbook's. When the source names its kernel, the name is recorded under nbi.chatbook.sourceKernel.

English descriptions

  • Conversion sends nothing to a model.
  • The existing path generates a cell's one-line English description on its first successful run, and the dialog discloses this.
  • A description the cell already carries is kept only when its metadata ties it to that exact code. That is the case for a Chatbook that was exported and is converted back, so its prompts survive the round trip.
  • Natural-language cells of a Chatbook whose kernel was switched away are left as natural language, provided they have run and have not been edited since.

Language check

  • The Chatbook execution kernel is one setting shared by every Chatbook, so conversion compares the notebook's language with it first.
  • Same language: the notebook converts, with a note when its kernel differs.
  • Unknown language: the notebook converts, with a note naming the kernel it will run on.
  • Different language (an R notebook while the backend is Python): the dialog explains why the notebook can't be converted yet and, when a suitable kernel is installed, offers Open Chatbook settings. It never changes that setting itself, because the change would also affect the user's existing Chatbooks.

Visibility

  • The button shows only on loaded, non-Chatbook notebooks, and only while Chatbook is enabled.
  • It is re-checked when the kernelspec metadata changes, so a notebook switched to or from the Chatbook kernel updates correctly.
  • The icon is the Chatbook kernel's own glyph (VscChatSparkle, MIT).

Testing

  • tests/ts/chatbook.test.ts: the conversion contract. It covers:
    • what is kept;
    • when a description survives, including after a failed refresh, an edited prompt, and code edited after generation;
    • a Chatbook → export → Chatbook round trip;
    • mode switching on converted cells;
    • naming;
    • language normalization;
    • the fit matrix.
  • tests/ts/chatbook-convert.test.ts: drives convertNotebookToChatbook with a fake Contents service. It checks that a taken name is numbered rather than overwritten, the source is not modified, and no summarize call or fetch happens.
  • tests/ts/chatbook-toolbar-convert.test.ts: covers button visibility, every dialog branch (convert, cancel, unknown language, blocked with and without an installed kernel), one conversion at a time, and a failed save.
  • The new guards were mutation-checked: removing any one of them fails a test.
  • pytest tests/ -q (2233 passed), jlpm tsc --noEmit, jlpm lint:check, jlpm jest (53 suites, 614 tests).
  • Checked in a running JupyterLab 4.6:
    • Converted a Python notebook with outputs and tags. The copy opened on the Chatbook kernel with Cd badges and its outputs, and the saved metadata matched the above.
    • Converting again produced -chatbook-1 with the "Created Chatbook copy" toast.
    • Running a converted cell generated its description.
    • An R notebook was blocked, and Open Chatbook settings opened the Chatbook tab.
    • The button stayed hidden on the Chatbook tabs.
    • No console errors.

Risks / follow-ups

  • Existing export behavior noticed while testing, unchanged here, filed as Export as code notebook drops the code of a Cd cell switched to natural language #509. A Cd cell switched to NL and not re-run exports as a comment of its English, so its code does not reach the exported notebook.
  • Natural-language cells of a kernel-switched Chatbook that were never run, or were edited since their last run, carry nothing that distinguishes them from code, so they convert as code. The docs recommend switching such a Chatbook back to the Chatbook kernel instead.
  • Possible later additions, if they seem worthwhile:
    • a file-browser context-menu entry;
    • a per-notebook backend kernel (the recorded sourceKernel would feed it);
    • generating English on convert, off by default;
    • an admin policy for code summaries.
  • The button is inserted after the existing Chatbook buttons, so like them it relies on the cellType toolbar item being present.

Screenshots

Closes #504

Chatbook could export a Chatbook as a code notebook but had no way back,
so an existing notebook could only become a Chatbook by copying cells by
hand. Ordinary notebooks now get a toolbar button and a palette command
that write a Chatbook copy beside the original (<stem>-chatbook.ipynb,
numbered when taken) and open it.

Every code cell becomes a Chatbook code cell that runs exactly as
written; outputs, execution counts, attachments, markdown and other
metadata are kept, and the original is not changed. An English
description is kept only when the cell's metadata ties it to that exact
code, so a Chatbook exported and converted back keeps its prompts.

Conversion sends nothing to a model. The first successful run of each
cell generates its description, as for any code cell, and the dialog says
so.

The Chatbook execution kernel is one setting shared by every Chatbook, so
a notebook in a different language is not converted and the dialog
points to that setting instead of changing it. The source kernel name is
recorded under nbi.chatbook.sourceKernel.

The export's collision-safe save is shared with conversion through
saveNotebookCopy.
- Leave the run natural-language cells of a Chatbook whose kernel was
  switched as they are. They hold a prompt, not code, and converting them
  made English into code cells. Exported natural-language cells hold
  code or a comment and still convert.
- Keep a prior English description only when it still describes the
  code: not after a failed refresh (summaryError), and through the
  prompt-hash path only for a cell still in natural-language mode.
- Compare languages the way the backend kernel list does (py is Python,
  an empty kernelspec language falls back to language_info), sharing
  one helper with normalizeNotebookLanguage.
- Show the button only once the file has loaded, re-check it when the
  kernelspec metadata or the Chatbook config changes, and never on a
  notebook when Chatbook is off.
- Allow one conversion at a time, open the copy without a redundant
  kernel argument, and report a failed open without losing the toast.
- Rewrite the dialogs: the language dialog names the language, says what
  to do next and that the setting affects every Chatbook, and closes
  with a cancel button; the confirm dialog says where the copy goes and
  when code is sent to the model. Use sentence case for the command.
- Correct the docs on what metadata is kept and when a description is
  generated.
- Test the toolbar entry point: visibility, every dialog branch, the
  one-at-a-time guard and a failed save, plus a Chatbook to export to
  Chatbook round trip.
@mbektas
mbektas merged commit 54bc87f into plmbr:main Sep 29, 2026
5 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add convert to Chatbook feature

2 participants