@marimo-team/islands 0.25.3-dev2 → 0.25.3-dev200

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (690) hide show
  1. package/dist/{ConnectedDataExplorerComponent-CNSxdKyJ.js → ConnectedDataExplorerComponent-BsWiIPFk.js} +22 -20
  2. package/dist/{ErrorBoundary-DWEpirf3.js → ErrorBoundary-UWARECs-.js} +19 -19
  3. package/dist/{abnfDiagram-VCTEODGH-DQDjNXt3.js → abnfDiagram-VCTEODGH-I2x4Yu25.js} +2 -2
  4. package/dist/any-language-editor-BVFHDDQ3.js +75 -0
  5. package/dist/{architectureDiagram-5GKGNRK7-Nmls7Wxn.js → architectureDiagram-5GKGNRK7-1bSQMKzK.js} +1 -1
  6. package/dist/{arrays-CN1djC4k.js → arrays-DoQ-AILx.js} +15 -27
  7. package/dist/assets/__vite-browser-external-BCJsx8QS.js +1 -0
  8. package/dist/assets/worker-DodjWT_Z.js +113 -0
  9. package/dist/{button-CvjkwdSk.js → button-BQRdqQi1.js} +199 -192
  10. package/dist/{capabilities-CQ5IjhzL.js → capabilities-C2QUNRXi.js} +2 -2
  11. package/dist/{chat-ui-BDpymeoe.js → chat-ui-DXDoSuS4.js} +667 -667
  12. package/dist/{check-EDwSwP89.js → check-C9Mp9eCK.js} +1 -1
  13. package/dist/{chunk-IMKFNOWR-CoIFEo-1.js → chunk-IMKFNOWR-fsCGAJ9G.js} +1 -1
  14. package/dist/{chunk-SHT3W25Y-lHiGx3ZC.js → chunk-SHT3W25Y-D2STW4hj.js} +1 -1
  15. package/dist/{chunk-SVP7TREG-BvsHIrY_.js → chunk-SVP7TREG-CiY7cQG-.js} +1 -1
  16. package/dist/{chunk-TICWLB2K-BC8YIm_n.js → chunk-TICWLB2K-C_t5RBp9.js} +1 -1
  17. package/dist/{chunk-YOKDWASO-DPZk8vhS.js → chunk-YOKDWASO-DKplTrBY.js} +20 -20
  18. package/dist/{classDiagram-ZZMXUADV-Bt98lkkv.js → classDiagram-ZZMXUADV-B2JvZAP4.js} +2 -2
  19. package/dist/{classDiagram-v2-VYDZK3BY-D9bfbcC3.js → classDiagram-v2-VYDZK3BY-L8VsZG5A.js} +2 -2
  20. package/dist/{code-visibility-CLNfgCjd.js → code-visibility-33fxfX1p.js} +45 -49
  21. package/dist/{common-fyD_6mT2.js → common-D09oJJ8Z.js} +7354 -6884
  22. package/dist/{copy-icon-Ft7t9bqz.js → copy-icon-De584pZ4.js} +3 -3
  23. package/dist/{cynefinDiagram-5FMLGOSQ-CgWra7wt.js → cynefinDiagram-5FMLGOSQ-DdllC264.js} +1 -1
  24. package/dist/{dagre-GXQ25YYZ-CFZ8-35c.js → dagre-GXQ25YYZ-BaWHw4_f.js} +1 -1
  25. package/dist/{data-grid-overlay-editor-BmqASKep.js → data-grid-overlay-editor-lGsInXfR.js} +5 -5
  26. package/dist/{data-grid-types-BH_r7g7l.js → data-grid-types-0PJ-9N5n.js} +1 -1
  27. package/dist/{diagram-S7CK7UJ4-lCNQrW7d.js → diagram-S7CK7UJ4-pFt-tUDe.js} +1 -1
  28. package/dist/{diagram-UQ7AKVKN-CQPQ6pP_.js → diagram-UQ7AKVKN-DqGJiBp4.js} +1 -1
  29. package/dist/{diagram-VX7I27RA-Cf3b0llz.js → diagram-VX7I27RA-Dr-yzMjf.js} +1 -1
  30. package/dist/{diagram-Z3DM3KII-Bt4QLrpn.js → diagram-Z3DM3KII-8xzJzv-w.js} +1 -1
  31. package/dist/{dialog-CEBFZNyc.js → dialog-DVRfQuhD.js} +25 -25
  32. package/dist/{dist-F8Ep36rk.js → dist-B1M0bGO3.js} +1 -1
  33. package/dist/{dist-D6d86eNJ.js → dist-BA13RJj5.js} +1 -1
  34. package/dist/{dist-Bvs24R_E.js → dist-BJtmSgcE.js} +48 -48
  35. package/dist/{dist-CN_BeG2I.js → dist-Ba2VIn1K.js} +53 -53
  36. package/dist/{dist-PXYI_yuP.js → dist-Bj4bmwUm.js} +12 -12
  37. package/dist/{dist-DoE4XJBC.js → dist-BmS-ZGjl.js} +8626 -8626
  38. package/dist/{dist-BorMD-uX.js → dist-Bzogh7CW.js} +87 -87
  39. package/dist/{dist-CN8zI-XC.js → dist-CThPVKaP.js} +1385 -1382
  40. package/dist/{dist-DiDibOYr.js → dist-CTi5FTiV.js} +87 -87
  41. package/dist/{dist-diIx5qJW.js → dist-Ck_C32ye.js} +2 -2
  42. package/dist/{dist-BLfKmR-l.js → dist-D1fnFp1J.js} +1 -1
  43. package/dist/{dist-OR1OnN-y.js → dist-D3x9__Fu.js} +46 -46
  44. package/dist/{dist-BMQf5zIS.js → dist-D7mrh5sO.js} +36 -36
  45. package/dist/{dist-CSJ0MDRw.js → dist-D9Q3xjiP.js} +1 -1
  46. package/dist/{dist-BuaRHxOc.js → dist-DP60Ubh8.js} +2 -2
  47. package/dist/{dist-CSbh1PNP.js → dist-DTv9KkpW.js} +12 -12
  48. package/dist/{dist-D-wwqlzJ.js → dist-DVVwOfrD.js} +109 -109
  49. package/dist/{dist-C8fAKSH1.js → dist-DYXM73-k.js} +36 -36
  50. package/dist/{dist-DBtSl3sf.js → dist-DjeybPOb.js} +1 -1
  51. package/dist/{dist-CrSP_H1M.js → dist-DtGn9N4h.js} +197 -197
  52. package/dist/{dist-CLdpGQVr.js → dist-KN80qWCP.js} +2 -2
  53. package/dist/{dist-DpBpA_n1.js → dist-Lm-D-Vr6.js} +3 -3
  54. package/dist/{dist-Cg7gzw-a.js → dist-O0qFpEJh.js} +56 -56
  55. package/dist/{dist-CkTTIdBe.js → dist-OUle2RT7.js} +207 -207
  56. package/dist/{dist-BK4Oj99o.js → dist-T5rh6JvL.js} +1 -1
  57. package/dist/{dropdown-menu-CP_qCYHC.js → dropdown-menu-NlnsmNA6.js} +1481 -1433
  58. package/dist/{ebnfDiagram-PWID7BFC-D3NAyPFY.js → ebnfDiagram-PWID7BFC-Br04Wy-E.js} +2 -2
  59. package/dist/{erDiagram-RLTQ6QDP-Tlu09_Nm.js → erDiagram-RLTQ6QDP-D5-XVgvv.js} +1 -1
  60. package/dist/{error-banner-Da600cwz.js → error-banner-DxJ3s8YO.js} +89 -84
  61. package/dist/{cells-C8iCYvLU.js → error-entries-C2Ux0Fjt.js} +7970 -8605
  62. package/dist/{esm-D2gTsXEV.js → esm-Bbw_Njjx.js} +575 -575
  63. package/dist/{esm-AMFssoNp.js → esm-mDQNEFe_.js} +354 -354
  64. package/dist/feedback-button-B0CMhVv7.js +374 -0
  65. package/dist/{flowDiagram-HODETNUW-CAYbpJmV.js → flowDiagram-HODETNUW-CVl2kREF.js} +2 -2
  66. package/dist/{formats-BGh2thRc.js → formats-BCYthwyc.js} +3 -3
  67. package/dist/{ganttDiagram-EL5Y4UJY-BQT16JSc.js → ganttDiagram-EL5Y4UJY-Dh_4cBJZ.js} +2 -2
  68. package/dist/{glide-data-editor-BkjP14aq.js → glide-data-editor-CL535A5q.js} +370 -368
  69. package/dist/{glide-utils-DJyqh0EM.js → glide-utils-D98laidb.js} +16 -16
  70. package/dist/{globals-BN2O0F8N.js → globals-Bsr6T2yD.js} +3 -3
  71. package/dist/{highlighted-body-KPVGNVTW-zwjq21tf.js → highlighted-body-KPVGNVTW-3Ziwfz-V.js} +2 -2
  72. package/dist/{html-to-image-CZY1pIZH.js → html-to-image-CkH7vdBZ.js} +478 -381
  73. package/dist/{infoDiagram-27XIBGKW-XrDxhr0x.js → infoDiagram-27XIBGKW-BJ4vNcZE.js} +1 -1
  74. package/dist/{ishikawaDiagram-5VMMS53U-CD1muzov.js → ishikawaDiagram-5VMMS53U-B_Jy1Dsm.js} +1 -1
  75. package/dist/{kanban-definition-UXKFOSKX-Dg9W142_.js → kanban-definition-UXKFOSKX-C6MkS9vw.js} +1 -1
  76. package/dist/{label-BDKF3Afc.js → label-Qvw1E97W.js} +3 -3
  77. package/dist/{linear-Cnaq3Tfb.js → linear-DWERh7eI.js} +121 -73
  78. package/dist/{loader-BQOfjTIJ.js → loader-DOVB0Syl.js} +12 -12
  79. package/dist/main.js +9706 -7708
  80. package/dist/{mermaid-CiAXjLpA.js → mermaid-Bh918qrq.js} +52 -52
  81. package/dist/mermaid-HWGCJPDP-Du3-HPQA.js +2 -0
  82. package/dist/{mindmap-definition-YA3MSWOX-DgCidgYJ.js → mindmap-definition-YA3MSWOX-BP3ZTuir.js} +1 -1
  83. package/dist/{number-overlay-editor-BEBWJnbL.js → number-overlay-editor-CzbkG4E2.js} +3 -3
  84. package/dist/{objects-CzUgoMIF.js → objects-DCmMvZtn.js} +1 -3
  85. package/dist/{once-BtE-wKRL.js → once-NnpX_HnX.js} +1 -1
  86. package/dist/{pegDiagram-XKGWAZYB-coOYYKB6.js → pegDiagram-XKGWAZYB-nNGOQtnt.js} +2 -2
  87. package/dist/{pieDiagram-E7YTZNPT-BnXTc3bj.js → pieDiagram-E7YTZNPT-CpRz5BZz.js} +1 -1
  88. package/dist/precisionRound-DhAzeRcm.js +49 -0
  89. package/dist/{process-output-e4jj9Ijt.js → process-output-OujAtFW4.js} +4 -4
  90. package/dist/{quadrantDiagram-AXDQQJYC-Ccw0xMjN.js → quadrantDiagram-AXDQQJYC-Blrm7V7_.js} +1 -1
  91. package/dist/{railroadDiagram-O6MQD6OU-B28-u83n.js → railroadDiagram-O6MQD6OU-BqOEN4I0.js} +2 -2
  92. package/dist/{react-vega-BED0DjiB.js → react-vega-C4T9Rb_w.js} +12284 -12270
  93. package/dist/{requirementDiagram-BXWQKSXE-CdYCTMu0.js → requirementDiagram-BXWQKSXE-CEfg6vu9.js} +1 -1
  94. package/dist/{reveal-component-DK69bOki.js → reveal-component-CbEK0sNX.js} +733 -710
  95. package/dist/{select-BButFi-d.js → select-2KOiReNY.js} +536 -457
  96. package/dist/{sequenceDiagram-WJ2MYXX4-CM3aRAe_.js → sequenceDiagram-WJ2MYXX4-IOmpQcOi.js} +1 -1
  97. package/dist/{spec-BwarBpUJ.js → spec-Dkp64vVQ.js} +41 -11
  98. package/dist/{stateDiagram-D77RDMKH-DOZUMVj8.js → stateDiagram-D77RDMKH-tgU-EY9_.js} +2 -2
  99. package/dist/{stateDiagram-v2-MP3YSRHH-CISYxma6.js → stateDiagram-v2-MP3YSRHH-BofhG6q1.js} +2 -2
  100. package/dist/style.css +1 -1
  101. package/dist/{swimlanes-42K2YHIH-BkSppxp8.js → swimlanes-42K2YHIH-DW4vWDBd.js} +1 -1
  102. package/dist/{swimlanesDiagram-VR7AAH4N-c8G5pGxC.js → swimlanesDiagram-VR7AAH4N-BJcrqUJr.js} +2 -2
  103. package/dist/{swiper-component-DKntyn8p.js → swiper-component-BVfnhbnt.js} +2 -2
  104. package/dist/{time-BieKwdYS.js → time-BaMbJs4z.js} +18 -18
  105. package/dist/{timeline-definition-24CTP7MA-CaMQayqK.js → timeline-definition-24CTP7MA-D_QU3NGs.js} +1 -1
  106. package/dist/{toDate-BNJf01u1.js → toDate-BNDEXbfV.js} +77 -74
  107. package/dist/{toast-B9UMEi8u.js → toast-B5t9o6s_.js} +219 -201
  108. package/dist/{tooltip-BO1REbqs.js → tooltip-s4zZxwKe.js} +325 -301
  109. package/dist/{use-restore-focus-BEM7sFWl.js → use-restore-focus-BgDTd2tc.js} +1482 -1433
  110. package/dist/{useAsyncData-Deh5kszT.js → useAsyncData-ASDni9vH.js} +15 -14
  111. package/dist/{useDateFormatter-D8XruNGG.js → useDateFormatter-D3Tkfzej.js} +2 -2
  112. package/dist/{useDeepCompareMemoize-DXwzRINI.js → useDeepCompareMemoize-B1Ogyf53.js} +1 -1
  113. package/dist/{useIframeCapabilities-DBETvvPl.js → useIframeCapabilities-6a_yDNXp.js} +1 -1
  114. package/dist/{useLifecycle-j7D9uD1o.js → useLifecycle-Bfpa2m7k.js} +28 -25
  115. package/dist/{useTheme-CRnjkku0.js → useTheme-5TwyOh3B.js} +522 -314
  116. package/dist/{vega-component-DG29TAB7.js → vega-component-BHS9UOtC.js} +158 -158
  117. package/dist/{vega-embed-container-BNHE18G9.js → vega-embed-container--LYZqguO.js} +2 -2
  118. package/dist/{vega-loader.browser-DNST6uVf.js → vega-loader.browser-B9Pz0EGP.js} +298 -507
  119. package/dist/{vennDiagram-4TSXK5OY-CF8pfaK3.js → vennDiagram-4TSXK5OY-YFYsNIAh.js} +1 -1
  120. package/dist/{wardleyDiagram-VM6X3IG4-dGPu39d-.js → wardleyDiagram-VM6X3IG4-i_n8mAWC.js} +1 -1
  121. package/dist/{xychartDiagram-S5SC5T6Z-CP6-9q56.js → xychartDiagram-S5SC5T6Z-BYGN95wW.js} +2 -2
  122. package/package.json +16 -16
  123. package/src/__mocks__/document.tsx +63 -0
  124. package/src/__mocks__/notebook.ts +3 -4
  125. package/src/__mocks__/partial.ts +26 -0
  126. package/src/__mocks__/requests.ts +0 -3
  127. package/src/__tests__/fixtures/{pair-preview.ts → pair-config.ts} +3 -2
  128. package/src/__tests__/main.test.tsx +24 -1
  129. package/src/__tests__/module-entry.test.ts +44 -0
  130. package/src/__tests__/mount.test.ts +9 -9
  131. package/src/__tests__/{host-imports.test.ts → replica-imports.test.ts} +12 -11
  132. package/src/components/ai/__tests__/ai-model-dropdown.test.tsx +63 -0
  133. package/src/components/ai/ai-model-dropdown.tsx +11 -6
  134. package/src/components/app-config/ai-config.tsx +7 -2
  135. package/src/components/app-config/app-config-form.tsx +5 -9
  136. package/src/components/app-config/user-config-form.tsx +35 -0
  137. package/src/components/chat/__tests__/message-queue.test.tsx +17 -0
  138. package/src/components/chat/__tests__/notebook-access-selector.test.tsx +64 -0
  139. package/src/components/chat/acp/__tests__/session-tabs.test.tsx +43 -0
  140. package/src/components/chat/acp/__tests__/state.test.ts +2 -2
  141. package/src/components/chat/acp/blocks.tsx +3 -2
  142. package/src/components/chat/acp/session-tabs.tsx +8 -3
  143. package/src/components/chat/chat-components.tsx +2 -0
  144. package/src/components/chat/chat-panel.tsx +20 -101
  145. package/src/components/chat/chat-utils.ts +4 -8
  146. package/src/components/chat/notebook-access-selector.stories.tsx +22 -0
  147. package/src/components/chat/notebook-access-selector.tsx +100 -0
  148. package/src/components/data-table/TableBottomBar.tsx +4 -1
  149. package/src/components/data-table/TableTopBar.tsx +2 -0
  150. package/src/components/data-table/__tests__/chart-spec-model.test.ts +195 -195
  151. package/src/components/data-table/__tests__/column-explorer.test.tsx +27 -1
  152. package/src/components/data-table/__tests__/columns.test.tsx +105 -0
  153. package/src/components/data-table/__tests__/context-menu-interaction.test.tsx +130 -0
  154. package/src/components/data-table/__tests__/context-menu.test.ts +176 -0
  155. package/src/components/data-table/__tests__/data-table.test.tsx +1 -0
  156. package/src/components/data-table/__tests__/date-filter-inputs.test.tsx +24 -1
  157. package/src/components/data-table/__tests__/date-popover.test.tsx +72 -0
  158. package/src/components/data-table/__tests__/export-actions.test.tsx +434 -6
  159. package/src/components/data-table/__tests__/keyboard-selection.test.tsx +188 -0
  160. package/src/components/data-table/__tests__/pagination.test.tsx +28 -1
  161. package/src/components/data-table/__tests__/search-highlight.test.tsx +109 -0
  162. package/src/components/data-table/__tests__/url-detector.test.tsx +74 -0
  163. package/src/components/data-table/cell-selection/feature.ts +2 -2
  164. package/src/components/data-table/cell-selection/types.ts +2 -2
  165. package/src/components/data-table/charts/__tests__/chart-panel.test.tsx +74 -1
  166. package/src/components/data-table/charts/__tests__/spec-snapshot.test.ts +20 -20
  167. package/src/components/data-table/charts/__tests__/spec.test.ts +78 -52
  168. package/src/components/data-table/charts/__tests__/storage.test.ts +4 -1
  169. package/src/components/data-table/charts/chart-spec/spec.ts +68 -43
  170. package/src/components/data-table/charts/charts.tsx +40 -30
  171. package/src/components/data-table/charts/storage.ts +16 -5
  172. package/src/components/data-table/column-explorer-panel/column-explorer.tsx +1 -1
  173. package/src/components/data-table/column-summary/chart-spec-model.tsx +23 -16
  174. package/src/components/data-table/column-summary/column-summary.tsx +2 -4
  175. package/src/components/data-table/column-visibility-dropdown.tsx +8 -13
  176. package/src/components/data-table/columns.tsx +45 -46
  177. package/src/components/data-table/context-menu.tsx +161 -46
  178. package/src/components/data-table/data-table.tsx +17 -1
  179. package/src/components/data-table/date-filter-inputs.tsx +15 -42
  180. package/src/components/data-table/date-popover.tsx +6 -4
  181. package/src/components/data-table/export-actions.tsx +267 -163
  182. package/src/components/data-table/pagination.tsx +44 -33
  183. package/src/components/data-table/range-focus/atoms.ts +4 -6
  184. package/src/components/data-table/range-focus/use-cell-range-selection.ts +65 -38
  185. package/src/components/data-table/range-focus/use-scroll-into-view.ts +21 -2
  186. package/src/components/data-table/renderers.tsx +16 -7
  187. package/src/components/data-table/row-viewer-panel/__tests__/row-viewer.test.tsx +24 -1
  188. package/src/components/data-table/row-viewer-panel/row-viewer.tsx +4 -4
  189. package/src/components/data-table/schemas.ts +14 -36
  190. package/src/components/data-table/search-highlight.tsx +79 -0
  191. package/src/components/data-table/types.ts +1 -0
  192. package/src/components/data-table/url-detector.tsx +49 -9
  193. package/src/components/data-table/utils.ts +18 -0
  194. package/src/components/datasources/__tests__/column-actions.test.tsx +97 -0
  195. package/src/components/datasources/__tests__/column-preview.test.tsx +96 -5
  196. package/src/components/datasources/__tests__/datasources-interactions.test.tsx +181 -0
  197. package/src/components/datasources/__tests__/table-list.test.tsx +118 -0
  198. package/src/components/datasources/__tests__/utils.test.ts +57 -6
  199. package/src/components/datasources/column-preview.tsx +17 -12
  200. package/src/components/datasources/datasources.tsx +56 -43
  201. package/src/components/datasources/utils.ts +32 -23
  202. package/src/components/debugger/debugger-code.tsx +5 -0
  203. package/src/components/dependency-graph/custom-node.tsx +1 -1
  204. package/src/components/dependency-graph/dependency-graph-tree.tsx +8 -8
  205. package/src/components/dependency-graph/elements.ts +24 -21
  206. package/src/components/dependency-graph/minimap-content.tsx +13 -19
  207. package/src/components/dependency-graph/panels.tsx +4 -2
  208. package/src/components/dependency-graph/utils/__tests__/layout.test.ts +18 -11
  209. package/src/components/editor/Output.tsx +9 -2
  210. package/src/components/editor/SortableCell.tsx +1 -3
  211. package/src/components/editor/__tests__/Output.test.tsx +50 -32
  212. package/src/components/editor/__tests__/agent-toast.test.tsx +58 -0
  213. package/src/components/editor/__tests__/data-attributes.test.tsx +28 -14
  214. package/src/components/editor/__tests__/dynamic-favicon.test.tsx +111 -18
  215. package/src/components/editor/__tests__/output-persistence.test.tsx +6 -2
  216. package/src/components/editor/__tests__/package-alert.test.tsx +22 -1
  217. package/src/components/editor/actions/__tests__/name-cell-input.test.tsx +69 -0
  218. package/src/components/editor/actions/__tests__/pair-with-agent-commands.test.ts +80 -252
  219. package/src/components/editor/actions/__tests__/pair-with-agent-modal.test.tsx +218 -40
  220. package/src/components/editor/actions/__tests__/pair-with-agent.test.tsx +2 -6
  221. package/src/components/editor/actions/name-cell-input.tsx +4 -3
  222. package/src/components/editor/actions/pair-with-agent-commands.ts +44 -53
  223. package/src/components/editor/actions/pair-with-agent-modal.tsx +101 -38
  224. package/src/components/editor/actions/useCellActionButton.tsx +26 -31
  225. package/src/components/editor/actions/useConfigActions.tsx +3 -4
  226. package/src/components/editor/actions/useNotebookActions.tsx +19 -23
  227. package/src/components/editor/actions/useRestartKernel.tsx +1 -1
  228. package/src/components/editor/actions/useSetCodeVisibility.ts +11 -12
  229. package/src/components/editor/actions/useSetOutputsExpanded.ts +14 -19
  230. package/src/components/editor/agent-toast.ts +15 -0
  231. package/src/components/editor/ai/add-cell-with-ai.tsx +3 -3
  232. package/src/components/editor/ai/ai-completion-editor.tsx +1 -0
  233. package/src/components/editor/alerts/__tests__/connection-notice.test.tsx +1 -1
  234. package/src/components/editor/alerts/connection-notice.tsx +1 -1
  235. package/src/components/editor/alerts/startup-logs-alert.tsx +1 -0
  236. package/src/components/editor/alerts/stdin-blocking-alert.tsx +1 -1
  237. package/src/components/editor/app-container.tsx +1 -1
  238. package/src/components/editor/boundary/__tests__/ErrorBoundary.test.tsx +1 -1
  239. package/src/components/editor/cell/CreateCellButton.tsx +15 -21
  240. package/src/components/editor/cell/DeleteButton.tsx +3 -2
  241. package/src/components/editor/cell/RunButton.tsx +2 -2
  242. package/src/components/editor/cell/StagedAICell.tsx +10 -2
  243. package/src/components/editor/cell/StopButton.tsx +2 -2
  244. package/src/components/editor/cell/__tests__/StagedAICell.test.tsx +3 -1
  245. package/src/components/editor/cell/__tests__/useShouldShowInterrupt.test.ts +39 -0
  246. package/src/components/editor/cell/cell-actions.tsx +12 -1
  247. package/src/components/editor/cell/code/__tests__/language-toggle.test.tsx +54 -0
  248. package/src/components/editor/cell/code/cell-editor.tsx +36 -43
  249. package/src/components/editor/cell/code/language-toggle.tsx +8 -7
  250. package/src/components/editor/cell/collapse.tsx +11 -4
  251. package/src/components/editor/cell/useAddCell.ts +4 -8
  252. package/src/components/editor/cell/useDeleteCell.tsx +10 -36
  253. package/src/components/editor/cell/useRunCells.ts +2 -5
  254. package/src/components/editor/cell/useShouldShowInterrupt.ts +2 -12
  255. package/src/components/editor/cell/useSplitCell.tsx +10 -6
  256. package/src/components/editor/chrome/components/__tests__/feedback-button.test.tsx +1 -1
  257. package/src/components/editor/chrome/components/feedback-button.tsx +2 -8
  258. package/src/components/editor/chrome/panels/__tests__/packages-panel.test.tsx +31 -2
  259. package/src/components/editor/chrome/panels/__tests__/runtime-details.test.tsx +1 -1
  260. package/src/components/editor/chrome/panels/__tests__/sandbox-recovery.test.tsx +1 -1
  261. package/src/components/editor/chrome/panels/cache-panel.tsx +1 -0
  262. package/src/components/editor/chrome/panels/dependency-graph-panel.tsx +1 -1
  263. package/src/components/editor/chrome/panels/error-panel.tsx +1 -0
  264. package/src/components/editor/chrome/panels/logs-panel.tsx +2 -1
  265. package/src/components/editor/chrome/panels/outline/__tests__/outline-keyboard.test.tsx +84 -0
  266. package/src/components/editor/chrome/panels/outline/floating-outline.tsx +39 -14
  267. package/src/components/editor/chrome/panels/outline/useActiveOutline.tsx +3 -2
  268. package/src/components/editor/chrome/panels/packages-panel.tsx +4 -7
  269. package/src/components/editor/chrome/panels/secrets-panel.tsx +1 -0
  270. package/src/components/editor/chrome/panels/session-panel.tsx +1 -1
  271. package/src/components/editor/chrome/panels/snippets-panel.tsx +10 -12
  272. package/src/components/editor/chrome/panels/variable-panel.tsx +1 -5
  273. package/src/components/editor/chrome/wrapper/__tests__/attachment-status.test.tsx +363 -0
  274. package/src/components/editor/chrome/wrapper/__tests__/document-sync-status.test.tsx +92 -0
  275. package/src/components/editor/chrome/wrapper/__tests__/pending-ai-cells.test.tsx +61 -2
  276. package/src/components/editor/chrome/wrapper/footer-item.tsx +32 -24
  277. package/src/components/editor/chrome/wrapper/footer-items/attachment-status.tsx +237 -0
  278. package/src/components/editor/chrome/wrapper/footer-items/backend-status.tsx +1 -1
  279. package/src/components/editor/chrome/wrapper/footer-items/document-sync-status.tsx +54 -0
  280. package/src/components/editor/chrome/wrapper/footer-items/lsp-status.tsx +1 -1
  281. package/src/components/editor/chrome/wrapper/footer-items/machine-stats.tsx +1 -1
  282. package/src/components/editor/chrome/wrapper/footer-items/runtime-settings.tsx +1 -7
  283. package/src/components/editor/chrome/wrapper/footer.tsx +4 -0
  284. package/src/components/editor/chrome/wrapper/minimap-state.ts +1 -1
  285. package/src/components/editor/chrome/wrapper/pending-ai-cells.tsx +12 -2
  286. package/src/components/editor/chrome/wrapper/storage.ts +1 -1
  287. package/src/components/editor/columns/__tests__/cell-column.test.tsx +1 -1
  288. package/src/components/editor/columns/cell-column.tsx +1 -1
  289. package/src/components/editor/columns/sortable-column.tsx +2 -2
  290. package/src/components/editor/connections/components.tsx +5 -10
  291. package/src/components/editor/controls/Controls.tsx +4 -4
  292. package/src/components/editor/controls/__tests__/command-palette.test.tsx +53 -0
  293. package/src/components/editor/controls/__tests__/keyboard-shortcuts.test.tsx +61 -0
  294. package/src/components/editor/controls/__tests__/notebook-menu-dropdown.test.tsx +10 -4
  295. package/src/components/editor/controls/command-palette.tsx +22 -10
  296. package/src/components/editor/controls/keyboard-shortcuts.tsx +14 -5
  297. package/src/components/editor/documentation.css +34 -11
  298. package/src/components/editor/dynamic-favicon.tsx +21 -40
  299. package/src/components/editor/errors/__tests__/send-error-report-button.test.tsx +536 -0
  300. package/src/components/editor/errors/auto-fix.tsx +4 -8
  301. package/src/components/editor/errors/send-error-report-button.tsx +66 -0
  302. package/src/components/editor/file-tree/__tests__/file-explorer-interactions.test.tsx +6 -0
  303. package/src/components/editor/file-tree/__tests__/file-explorer-navigation.test.tsx +47 -0
  304. package/src/components/editor/file-tree/__tests__/use-file-search.test.tsx +91 -0
  305. package/src/components/editor/file-tree/file-explorer.tsx +48 -15
  306. package/src/components/editor/file-tree/file-name-input.tsx +1 -0
  307. package/src/components/editor/file-tree/file-viewer.tsx +4 -2
  308. package/src/components/editor/file-tree/use-file-search.ts +35 -21
  309. package/src/components/editor/header/__tests__/status.test.tsx +5 -3
  310. package/src/components/editor/header/app-header.tsx +1 -1
  311. package/src/components/editor/header/status.tsx +40 -20
  312. package/src/components/editor/links/__tests__/cell-link.test.tsx +148 -0
  313. package/src/components/editor/links/cell-link-list.tsx +1 -1
  314. package/src/components/editor/links/cell-link.tsx +17 -7
  315. package/src/components/editor/navigation/__tests__/clipboard.test.ts +60 -38
  316. package/src/components/editor/navigation/__tests__/navigation.test.ts +108 -85
  317. package/src/components/editor/navigation/__tests__/selection.test.ts +43 -21
  318. package/src/components/editor/navigation/clipboard.ts +17 -14
  319. package/src/components/editor/navigation/focus-utils.ts +23 -4
  320. package/src/components/editor/navigation/multi-cell-action-toolbar.tsx +17 -33
  321. package/src/components/editor/navigation/navigation.ts +71 -70
  322. package/src/components/editor/navigation/selection.ts +30 -29
  323. package/src/components/editor/notebook-banner.tsx +1 -0
  324. package/src/components/editor/notebook-cell.tsx +29 -31
  325. package/src/components/editor/output/MarimoErrorOutput.tsx +23 -6
  326. package/src/components/editor/output/MarimoTracebackOutput.tsx +54 -37
  327. package/src/components/editor/output/Outputs.css +8 -0
  328. package/src/components/editor/output/__tests__/ansi-reduce.test.ts +18 -0
  329. package/src/components/editor/output/__tests__/traceback.test.tsx +27 -1
  330. package/src/components/editor/output/ansi-reduce.ts +36 -17
  331. package/src/components/editor/output/console/ConsoleOutput.tsx +19 -25
  332. package/src/components/editor/output/console/__tests__/ConsoleOutput.test.tsx +125 -69
  333. package/src/components/editor/package-alert.tsx +14 -7
  334. package/src/components/editor/renderers/cell-array.tsx +22 -33
  335. package/src/components/editor/renderers/grid-layout/grid-layout.tsx +12 -6
  336. package/src/components/editor/renderers/slides-layout/__tests__/plugin.test.ts +0 -1
  337. package/src/components/editor/renderers/slides-layout/slides-layout.tsx +1 -1
  338. package/src/components/editor/renderers/vertical-layout/__tests__/useFocusFirstEditor.test.ts +4 -4
  339. package/src/components/editor/renderers/vertical-layout/sidebar/toggle.tsx +7 -1
  340. package/src/components/editor/renderers/vertical-layout/useFocusFirstEditor.ts +1 -1
  341. package/src/components/editor/renderers/vertical-layout/vertical-layout.tsx +1 -1
  342. package/src/components/editor/stdin-blocking-alert.tsx +1 -1
  343. package/src/components/home/components.tsx +17 -31
  344. package/src/components/icons/__tests__/large-spinner.test.tsx +39 -0
  345. package/src/components/icons/large-spinner.tsx +3 -14
  346. package/src/components/icons/spinner.tsx +1 -1
  347. package/src/components/markdown/markdown-renderer.tsx +4 -8
  348. package/src/components/mcp/mcp-status-indicator.tsx +1 -1
  349. package/src/components/pages/__tests__/home-page.test.tsx +116 -0
  350. package/src/components/pages/edit-page.tsx +19 -17
  351. package/src/components/pages/home-page.tsx +164 -91
  352. package/src/components/scratchpad/scratchpad.test.tsx +97 -0
  353. package/src/components/scratchpad/scratchpad.tsx +20 -11
  354. package/src/components/slides/__tests__/minimap-actions.test.tsx +22 -29
  355. package/src/components/slides/__tests__/minimap.test.ts +38 -19
  356. package/src/components/slides/__tests__/slide-scroll-hint.test.tsx +37 -0
  357. package/src/components/slides/minimap.tsx +17 -12
  358. package/src/components/slides/reveal-component.tsx +58 -26
  359. package/src/components/slides/reveal-slides.css +5 -4
  360. package/src/components/slides/slide-cell-view.tsx +4 -5
  361. package/src/components/slides/slide-form.tsx +1 -0
  362. package/src/components/slides/slide-scroll-hint.tsx +3 -1
  363. package/src/components/sort/SortableCellsProvider.tsx +8 -25
  364. package/src/components/tracing/tracing-keyboard.test.tsx +85 -0
  365. package/src/components/tracing/tracing.tsx +46 -42
  366. package/src/components/ui/__tests__/draggable-popover.test.tsx +24 -0
  367. package/src/components/ui/__tests__/range-slider.test.tsx +165 -0
  368. package/src/components/ui/alert-dialog.tsx +1 -1
  369. package/src/components/ui/draggable-popover.tsx +24 -2
  370. package/src/components/ui/range-slider.tsx +22 -9
  371. package/src/core/MarimoApp.tsx +1 -1
  372. package/src/core/ai/__tests__/staged-cells.test.ts +27 -26
  373. package/src/core/ai/context/providers/__tests__/cell-output.test.ts +8 -12
  374. package/src/core/ai/context/providers/cell-output.ts +2 -2
  375. package/src/core/ai/context/providers/datasource.ts +6 -2
  376. package/src/core/ai/staged-cells.ts +15 -18
  377. package/src/core/ai/tools/__tests__/edit-notebook-tool.test.ts +40 -88
  378. package/src/core/ai/tools/__tests__/registry.test.ts +17 -0
  379. package/src/core/ai/tools/base.ts +18 -15
  380. package/src/core/ai/tools/edit-notebook-tool.ts +86 -80
  381. package/src/core/ai/tools/registry.ts +13 -10
  382. package/src/core/ai/tools/sample-tool.ts +6 -7
  383. package/src/core/cells/__tests__/__snapshots__/cells.test.ts.snap +4 -37
  384. package/src/core/cells/__tests__/actions.test.ts +624 -35
  385. package/src/core/cells/__tests__/add-missing-import.test.ts +7 -8
  386. package/src/core/cells/__tests__/arrange.test.ts +432 -0
  387. package/src/core/cells/__tests__/cell.test.ts +39 -0
  388. package/src/core/cells/__tests__/cells.test.ts +256 -2477
  389. package/src/core/cells/__tests__/collapseConsoleOutputs.test.ts +54 -0
  390. package/src/core/cells/__tests__/document.test.ts +341 -0
  391. package/src/core/cells/__tests__/editor.test.ts +57 -0
  392. package/src/core/cells/__tests__/error-report.test.ts +139 -0
  393. package/src/core/cells/__tests__/flush-document.test.ts +40 -0
  394. package/src/core/cells/__tests__/harness.ts +106 -0
  395. package/src/core/cells/__tests__/layout.test.ts +177 -0
  396. package/src/core/cells/__tests__/notebook-outline.test.ts +120 -0
  397. package/src/core/cells/__tests__/outputs.test.tsx +71 -53
  398. package/src/core/cells/__tests__/session.test.ts +493 -210
  399. package/src/core/cells/__tests__/utils.test.ts +9 -108
  400. package/src/core/cells/__tests__/with-document-save.test.ts +67 -0
  401. package/src/core/cells/actions.ts +636 -6
  402. package/src/core/cells/add-missing-import.ts +47 -43
  403. package/src/core/cells/arrange.ts +529 -0
  404. package/src/core/cells/cell.ts +14 -3
  405. package/src/core/cells/cells.ts +120 -1337
  406. package/src/core/cells/columns.ts +38 -0
  407. package/src/core/cells/document.ts +289 -0
  408. package/src/core/cells/edit.ts +30 -0
  409. package/src/core/cells/editor.ts +82 -0
  410. package/src/core/cells/error-report.ts +63 -0
  411. package/src/core/cells/layout.ts +221 -0
  412. package/src/core/cells/outputs.ts +12 -28
  413. package/src/core/cells/pending-delete-service.ts +3 -7
  414. package/src/core/cells/session.ts +104 -54
  415. package/src/core/cells/types.ts +22 -6
  416. package/src/core/cells/utils.ts +10 -8
  417. package/src/core/codemirror/__tests__/setup.test.ts +29 -29
  418. package/src/core/codemirror/ai/__tests__/resources.test.ts +117 -0
  419. package/src/core/codemirror/ai/resources.ts +1 -1
  420. package/src/core/codemirror/cells/__tests__/extensions.test.ts +42 -1
  421. package/src/core/codemirror/cells/extensions.ts +27 -9
  422. package/src/core/codemirror/cells/state.ts +1 -1
  423. package/src/core/codemirror/copilot/__tests__/getCodes.test.ts +6 -7
  424. package/src/core/codemirror/copilot/getCodes.ts +2 -2
  425. package/src/core/codemirror/format.ts +6 -5
  426. package/src/core/codemirror/keymaps/vim.ts +4 -8
  427. package/src/core/codemirror/language/__tests__/sql.test.ts +22 -20
  428. package/src/core/codemirror/language/__tests__/utils.test.ts +187 -15
  429. package/src/core/codemirror/language/cell-code.ts +114 -0
  430. package/src/core/codemirror/language/extension.ts +52 -35
  431. package/src/core/codemirror/language/languages/markdown.ts +8 -6
  432. package/src/core/codemirror/language/languages/python.ts +16 -10
  433. package/src/core/codemirror/language/languages/sql/sql.ts +16 -24
  434. package/src/core/codemirror/language/panel/panel.tsx +1 -0
  435. package/src/core/codemirror/language/types.ts +7 -7
  436. package/src/core/codemirror/language/utils.ts +9 -39
  437. package/src/core/codemirror/lsp/__tests__/notebook-lsp.test.ts +1 -2
  438. package/src/core/codemirror/lsp/notebook-lsp.ts +6 -5
  439. package/src/core/codemirror/lsp/utils.ts +1 -1
  440. package/src/core/codemirror/readonly/__tests__/extension.test.ts +1 -1
  441. package/src/core/codemirror/readonly/extension.ts +2 -2
  442. package/src/core/codemirror/rtc/extension.ts +24 -13
  443. package/src/core/codemirror/rtc/loro/awareness.ts +34 -19
  444. package/src/core/codemirror/rtc/loro/sync.ts +1 -0
  445. package/src/core/codemirror/utils.ts +1 -0
  446. package/src/core/config/__tests__/app-config.test.ts +64 -0
  447. package/src/core/config/__tests__/config-schema.test.ts +13 -6
  448. package/src/core/config/config-schema.ts +13 -3
  449. package/src/core/config/config.ts +26 -12
  450. package/src/core/config/pair.ts +5 -3
  451. package/src/core/datasets/__tests__/data-source-discovery.test.ts +5 -5
  452. package/src/core/datasets/data-source-discovery.ts +4 -6
  453. package/src/core/documentation/doc-lookup.ts +1 -1
  454. package/src/core/edit-app.tsx +21 -28
  455. package/src/core/errors/error-entries.ts +4 -1
  456. package/src/core/export/hooks.ts +1 -1
  457. package/src/core/export/layout.ts +2 -2
  458. package/src/core/hotkeys/actions.ts +2 -4
  459. package/src/core/islands/__tests__/bootstrap.test.ts +69 -17
  460. package/src/core/islands/__tests__/bridge.test.ts +72 -25
  461. package/src/core/islands/bootstrap.ts +46 -53
  462. package/src/core/islands/bridge.ts +74 -23
  463. package/src/core/islands/components/__tests__/IslandControls.test.tsx +7 -5
  464. package/src/core/islands/components/web-components.tsx +1 -1
  465. package/src/core/islands/worker/__tests__/controller.test.ts +62 -4
  466. package/src/core/islands/worker/controller.ts +4 -10
  467. package/src/core/islands/worker/worker.tsx +33 -33
  468. package/src/core/kernel/__tests__/RuntimeState.test.ts +1 -1
  469. package/src/core/kernel/__tests__/handlers.test.ts +7 -153
  470. package/src/core/kernel/handlers.ts +19 -72
  471. package/src/core/meta/__tests__/code-visibility.test.tsx +78 -70
  472. package/src/core/meta/code-visibility.ts +18 -9
  473. package/src/core/network/__tests__/connection.test.ts +1 -1
  474. package/src/core/network/__tests__/requests-lazy.test.ts +1 -3
  475. package/src/core/network/connection-notice.ts +1 -1
  476. package/src/core/network/connection.ts +5 -3
  477. package/src/core/network/requests-lazy.ts +1 -4
  478. package/src/core/network/requests-network.ts +0 -25
  479. package/src/core/network/requests-static.ts +0 -3
  480. package/src/core/network/requests-toasting.tsx +0 -3
  481. package/src/core/network/types.ts +0 -12
  482. package/src/core/network/useConnectionNotice.ts +8 -2
  483. package/src/core/notebook/__tests__/operations.test.ts +51 -0
  484. package/src/core/notebook/attachments.ts +38 -0
  485. package/src/core/notebook/document/__tests__/codemirror.test.ts +586 -0
  486. package/src/core/notebook/document/__tests__/draft.test.ts +363 -0
  487. package/src/core/notebook/document/__tests__/fixtures.ts +92 -0
  488. package/src/core/notebook/document/__tests__/hold.test.ts +88 -0
  489. package/src/core/notebook/document/__tests__/hooks.test.tsx +391 -0
  490. package/src/core/notebook/document/__tests__/lifecycle-scenarios.test.ts +61 -0
  491. package/src/core/notebook/document/__tests__/model.test.ts +247 -0
  492. package/src/core/notebook/document/__tests__/protocol-fixtures.ts +38 -0
  493. package/src/core/notebook/document/__tests__/recovery-scenarios.test.ts +230 -0
  494. package/src/core/notebook/document/__tests__/scenario-fixture.ts +43 -0
  495. package/src/core/notebook/document/__tests__/scenarios.test.ts +205 -0
  496. package/src/core/notebook/document/__tests__/state.test.ts +459 -0
  497. package/src/core/notebook/document/__tests__/submission.test.ts +203 -0
  498. package/src/core/notebook/document/__tests__/test-host.test.ts +92 -0
  499. package/src/core/notebook/document/__tests__/test-host.ts +247 -0
  500. package/src/core/notebook/document/__tests__/test-notebook.ts +149 -0
  501. package/src/core/notebook/document/__tests__/user.ts +61 -0
  502. package/src/core/notebook/document/codemirror.ts +216 -0
  503. package/src/core/notebook/document/draft.ts +502 -0
  504. package/src/core/notebook/document/hooks.tsx +118 -0
  505. package/src/core/notebook/document/index.ts +24 -0
  506. package/src/core/notebook/document/model.ts +105 -0
  507. package/src/core/notebook/document/select.ts +41 -0
  508. package/src/core/notebook/document/state.ts +378 -0
  509. package/src/core/notebook/document/sync.ts +418 -0
  510. package/src/core/notebook/index.ts +19 -0
  511. package/src/core/notebook/operations.ts +30 -0
  512. package/src/core/notebook/replica/AGENTS.md +11 -0
  513. package/src/core/notebook/replica/__tests__/attachments.test.ts +56 -0
  514. package/src/core/notebook/replica/__tests__/document.test.ts +126 -0
  515. package/src/core/notebook/replica/__tests__/fixtures.ts +79 -0
  516. package/src/core/notebook/replica/__tests__/replica.test.ts +550 -0
  517. package/src/core/notebook/replica/backend.ts +19 -0
  518. package/src/core/{websocket/types.ts → notebook/replica/connection.ts} +10 -15
  519. package/src/core/notebook/replica/index.ts +13 -0
  520. package/src/core/notebook/replica/replica.ts +286 -0
  521. package/src/core/notebook/replica/resources/attachments.ts +22 -0
  522. package/src/core/notebook/replica/resources/document.ts +101 -0
  523. package/src/core/packages/__tests__/useSandboxController.test.tsx +1 -1
  524. package/src/core/packages/useSandboxController.ts +1 -1
  525. package/src/core/run-app.tsx +48 -51
  526. package/src/core/runtime/__tests__/adapter.test.ts +1 -1
  527. package/src/core/runtime/__tests__/createWsUrl.test.ts +77 -7
  528. package/src/core/runtime/__tests__/runtime.test.ts +33 -15
  529. package/src/core/runtime/adapter.ts +1 -1
  530. package/src/core/runtime/config.ts +2 -2
  531. package/src/core/runtime/runtime.ts +39 -30
  532. package/src/core/saving/__tests__/state.test.ts +111 -0
  533. package/src/core/saving/__tests__/useAutoSave.test.tsx +67 -0
  534. package/src/core/saving/filename.ts +1 -1
  535. package/src/core/saving/save-component.tsx +28 -36
  536. package/src/core/saving/state.ts +38 -39
  537. package/src/core/saving/useAutoSave.ts +17 -53
  538. package/src/core/session/__tests__/backend.test.ts +236 -0
  539. package/src/core/session/__tests__/useNotebookReplica.hook.test.tsx +184 -0
  540. package/src/core/{websocket/__tests__/useMarimoKernelConnection.hook.test.tsx → session/__tests__/useNotebookSession.hook.test.tsx} +252 -185
  541. package/src/core/session/active-notebook.ts +22 -0
  542. package/src/core/session/backend.ts +123 -0
  543. package/src/core/session/embedded.ts +7 -0
  544. package/src/core/session/types.ts +17 -0
  545. package/src/core/session/useNotebookReplica.ts +74 -0
  546. package/src/core/{websocket/useMarimoKernelConnection.tsx → session/useNotebookSession.tsx} +120 -273
  547. package/src/core/state/__tests__/jotai.test.tsx +108 -0
  548. package/src/core/state/jotai.ts +1 -1
  549. package/src/core/static/__tests__/files.test.ts +38 -10
  550. package/src/core/static/files.ts +2 -0
  551. package/src/core/{websocket/__tests__/useMarimoKernelConnection.test.ts → transports/__tests__/connection-state.test.ts} +16 -30
  552. package/src/core/transports/__tests__/server.test.ts +408 -0
  553. package/src/core/transports/__tests__/static.test.ts +306 -0
  554. package/src/core/transports/__tests__/wasm.test.ts +166 -0
  555. package/src/core/transports/connection-state.ts +63 -0
  556. package/src/core/transports/server.ts +152 -0
  557. package/src/core/transports/static.ts +166 -0
  558. package/src/core/transports/wasm.ts +97 -0
  559. package/src/core/wasm/__tests__/bridge.test.ts +214 -50
  560. package/src/core/wasm/__tests__/worker.test.ts +187 -0
  561. package/src/core/wasm/bridge.ts +75 -69
  562. package/src/core/wasm/rpc.ts +15 -3
  563. package/src/core/wasm/store.ts +3 -3
  564. package/src/core/wasm/worker/bootstrap.ts +55 -51
  565. package/src/core/wasm/worker/getMarimoWheel.ts +1 -1
  566. package/src/core/wasm/worker/save-worker.ts +9 -10
  567. package/src/core/wasm/worker/types.ts +29 -18
  568. package/src/core/wasm/worker/worker.ts +88 -44
  569. package/src/css/globals.css +66 -22
  570. package/src/hooks/__tests__/useAsyncData.test.tsx +148 -0
  571. package/src/hooks/__tests__/useDebounce.test.tsx +51 -0
  572. package/src/hooks/__tests__/useDeepCompareMemoize.test.tsx +39 -0
  573. package/src/hooks/__tests__/useDelayElapsed.test.tsx +28 -0
  574. package/src/hooks/__tests__/useInternalStateWithSync.test.tsx +20 -0
  575. package/src/hooks/__tests__/useScript.test.tsx +77 -0
  576. package/src/hooks/__tests__/useStateForKey.test.tsx +257 -0
  577. package/src/hooks/useAsyncData.ts +3 -3
  578. package/src/hooks/useDataSourceDiscovery.ts +6 -4
  579. package/src/hooks/useDebounce.ts +6 -10
  580. package/src/hooks/useDeepCompareMemoize.ts +1 -1
  581. package/src/hooks/useDelayElapsed.ts +14 -10
  582. package/src/hooks/useElapsedTime.ts +3 -3
  583. package/src/hooks/useEventListener.ts +1 -2
  584. package/src/hooks/useInputHistory.ts +4 -7
  585. package/src/hooks/useInternalStateWithSync.ts +6 -6
  586. package/src/hooks/useResizeObserver.ts +4 -7
  587. package/src/hooks/useScript.ts +67 -70
  588. package/src/hooks/useStateForKey.ts +93 -0
  589. package/src/mount.tsx +23 -14
  590. package/src/plugins/__tests__/plugin-object-schemas.test.ts +104 -0
  591. package/src/plugins/core/registerReactComponent.tsx +1 -1
  592. package/src/plugins/impl/CodeEditorPlugin.tsx +1 -1
  593. package/src/plugins/impl/DataEditorPlugin.tsx +1 -1
  594. package/src/plugins/impl/DataTablePlugin.tsx +69 -37
  595. package/src/plugins/impl/DropdownPlugin.tsx +2 -6
  596. package/src/plugins/impl/FileBrowserPlugin.tsx +4 -16
  597. package/src/plugins/impl/FormPlugin.tsx +1 -1
  598. package/src/plugins/impl/RangeSliderPlugin.tsx +16 -2
  599. package/src/plugins/impl/RefreshPlugin.tsx +1 -0
  600. package/src/plugins/impl/SliderPlugin.tsx +6 -8
  601. package/src/plugins/impl/__tests__/DataTablePlugin.test.tsx +471 -1
  602. package/src/plugins/impl/__tests__/FileBrowserPlugin.test.tsx +45 -0
  603. package/src/plugins/impl/__tests__/RangeSliderPlugin.test.tsx +109 -0
  604. package/src/plugins/impl/__tests__/SliderPlugin.test.tsx +24 -3
  605. package/src/plugins/impl/anywidget/__tests__/registry.test.ts +153 -0
  606. package/src/plugins/impl/anywidget/__tests__/widget-binding.test.ts +241 -2
  607. package/src/plugins/impl/anywidget/model.ts +3 -1
  608. package/src/plugins/impl/anywidget/registry.ts +18 -14
  609. package/src/plugins/impl/anywidget/runtime.ts +21 -9
  610. package/src/plugins/impl/anywidget/widget-binding.ts +160 -82
  611. package/src/plugins/impl/chat/__tests__/chat-prompts.test.tsx +93 -0
  612. package/src/plugins/impl/chat/chat-ui.tsx +14 -11
  613. package/src/plugins/impl/code/any-language-editor.tsx +2 -2
  614. package/src/plugins/impl/data-editor/glide-data-editor.tsx +8 -5
  615. package/src/plugins/impl/data-editor/glide-utils.ts +3 -1
  616. package/src/plugins/impl/data-explorer/ConnectedDataExplorerComponent.tsx +1 -1
  617. package/src/plugins/impl/data-explorer/components/column-summary.tsx +4 -2
  618. package/src/plugins/impl/data-explorer/state/reducer.ts +1 -1
  619. package/src/plugins/impl/data-frames/DataFramePlugin.tsx +1 -2
  620. package/src/plugins/impl/data-frames/__tests__/sidebar.test.tsx +160 -0
  621. package/src/plugins/impl/data-frames/forms/__tests__/__snapshots__/form.test.tsx.snap +66 -66
  622. package/src/plugins/impl/data-frames/panel.tsx +43 -16
  623. package/src/plugins/impl/mpl-interactive/MplInteractivePlugin.tsx +5 -3
  624. package/src/plugins/impl/panel/PanelPlugin.tsx +16 -17
  625. package/src/plugins/impl/panel/__tests__/utils.test.ts +39 -1
  626. package/src/plugins/impl/panel/utils.ts +17 -0
  627. package/src/plugins/impl/plotly/PlotlyPlugin.tsx +2 -5
  628. package/src/plugins/impl/plotly/selection.ts +25 -19
  629. package/src/plugins/impl/vega/VegaPlugin.tsx +2 -3
  630. package/src/plugins/impl/vega/make-selectable.ts +4 -7
  631. package/src/plugins/layout/RoutesPlugin.tsx +1 -1
  632. package/src/stories/__tests__/editor-story.test.tsx +33 -0
  633. package/src/stories/button.stories.tsx +1 -0
  634. package/src/stories/cell.stories.tsx +2 -5
  635. package/src/stories/data-table.stories.tsx +31 -0
  636. package/src/stories/editor.stories.tsx +24 -17
  637. package/src/stories/form-wrapper.stories.tsx +2 -2
  638. package/src/stories/layout/vertical/one-column.stories.tsx +2 -5
  639. package/src/stories/runtime-story.tsx +23 -17
  640. package/src/stories/select.stories.tsx +2 -2
  641. package/src/stories/switchable-multi-select.stories.tsx +1 -1
  642. package/src/utils/__tests__/arrays.test.ts +35 -0
  643. package/src/utils/__tests__/batch-requests.test.ts +3 -3
  644. package/src/utils/__tests__/{createReducer.test.ts → createReducer.test.tsx} +29 -0
  645. package/src/utils/__tests__/dates.test.ts +116 -0
  646. package/src/utils/__tests__/numbers.test.ts +105 -1
  647. package/src/utils/__tests__/objects.test.ts +21 -0
  648. package/src/utils/arrays.ts +11 -2
  649. package/src/utils/blob.ts +1 -1
  650. package/src/utils/createReducer.ts +53 -26
  651. package/src/utils/dates.ts +94 -0
  652. package/src/utils/maps.ts +0 -3
  653. package/src/utils/numbers.ts +79 -18
  654. package/src/utils/objects.ts +4 -9
  655. package/src/utils/once.ts +19 -19
  656. package/src/utils/tracer.ts +9 -5
  657. package/src/utils/zod-utils.ts +1 -3
  658. package/dist/any-language-editor-B9REGlD9.js +0 -76
  659. package/dist/assets/__vite-browser-external-BXYkiFsk.js +0 -1
  660. package/dist/assets/worker-HPY9fbhz.js +0 -114
  661. package/dist/error-entries-CzoYkIQZ.js +0 -56
  662. package/dist/feedback-button-fND8YT59.js +0 -380
  663. package/dist/mermaid-HWGCJPDP-ByCsZnYF.js +0 -2
  664. package/dist/precisionRound-DMIVQrt2.js +0 -97
  665. package/src/components/editor/navigation/__tests__/state.test.ts +0 -81
  666. package/src/components/editor/navigation/state.ts +0 -65
  667. package/src/core/ai/tools/__tests__/run-cells-tool.test.ts +0 -656
  668. package/src/core/ai/tools/run-cells-tool.ts +0 -303
  669. package/src/core/cells/__tests__/apply-transaction.test.ts +0 -991
  670. package/src/core/cells/__tests__/document-changes.test.ts +0 -1140
  671. package/src/core/cells/__tests__/document-roundtrip.test.ts +0 -392
  672. package/src/core/cells/document-changes.ts +0 -944
  673. package/src/core/host/AGENTS.md +0 -6
  674. package/src/core/host/__tests__/protocol.test.ts +0 -214
  675. package/src/core/host/protocol.ts +0 -1943
  676. package/src/core/state/__tests__/jotai.test.ts +0 -25
  677. package/src/core/wasm/worker/message-buffer.ts +0 -33
  678. package/src/core/websocket/__tests__/useWebSocket.test.ts +0 -49
  679. package/src/core/websocket/transports/__tests__/basic.test.ts +0 -275
  680. package/src/core/websocket/transports/__tests__/sse.test.ts +0 -338
  681. package/src/core/websocket/transports/__tests__/transport.test.ts +0 -308
  682. package/src/core/websocket/transports/__tests__/ws.test.ts +0 -125
  683. package/src/core/websocket/transports/basic.ts +0 -102
  684. package/src/core/websocket/transports/sse.ts +0 -308
  685. package/src/core/websocket/transports/transport.ts +0 -61
  686. package/src/core/websocket/transports/ws.ts +0 -98
  687. package/src/core/websocket/useWebSocket.tsx +0 -88
  688. package/src/utils/__tests__/id-tree.test.ts +0 -2145
  689. package/src/utils/id-tree.tsx +0 -1134
  690. /package/src/core/{websocket → session}/connection-utils.ts +0 -0
@@ -6,11 +6,10 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
6
6
  import { Mocks } from "@/__mocks__/common";
7
7
  import { cellId } from "@/__tests__/branded";
8
8
  import { parseOutline } from "@/core/dom/outline";
9
- import { MultiColumn, visibleForTesting } from "@/utils/id-tree";
10
9
  import { invariant } from "@/utils/invariant";
11
10
  import { Logger } from "@/utils/Logger";
12
11
  import { SETUP_CELL_ID } from "../ids";
13
- import { notebookStateFromSession } from "../session";
12
+ import { readExport } from "../session";
14
13
 
15
14
  // Mock dependencies
16
15
  vi.mock("@/utils/Logger", () => ({ Logger: Mocks.quietLogger() }));
@@ -25,10 +24,16 @@ type NotebookCell = api.Notebook["NotebookV1"]["cells"][0];
25
24
  // Test constants
26
25
  const CELL_1 = cellId("cell-1");
27
26
 
28
- describe("notebookStateFromSession", () => {
27
+ /** The snapshot's record of a cell. */
28
+ function cellIn(result: ReturnType<typeof readExport>, id: string) {
29
+ const cell = result.snapshot?.cells.find((cell) => cell.id === id);
30
+ invariant(cell, `no cell ${id}`);
31
+ return cell;
32
+ }
33
+
34
+ describe("readExport", () => {
29
35
  beforeEach(() => {
30
36
  vi.clearAllMocks();
31
- visibleForTesting.reset();
32
37
  });
33
38
 
34
39
  // Test data factories
@@ -46,10 +51,17 @@ describe("notebookStateFromSession", () => {
46
51
 
47
52
  const createNotebookCell = (
48
53
  id: string,
49
- code: string | null = null,
50
- name: string | null = null,
51
- config: NotebookCell["config"] | null = null,
52
- code_hash: string | null = null,
54
+ {
55
+ code = null,
56
+ name = null,
57
+ config = null,
58
+ code_hash = null,
59
+ }: {
60
+ code?: string | null;
61
+ name?: string | null;
62
+ config?: NotebookCell["config"] | null;
63
+ code_hash?: string | null;
64
+ } = {},
53
65
  ): NotebookCell => ({
54
66
  id,
55
67
  code,
@@ -81,72 +93,113 @@ describe("notebookStateFromSession", () => {
81
93
 
82
94
  describe("validation", () => {
83
95
  it("logs error for both session and notebook null/undefined", () => {
84
- const result = notebookStateFromSession(null, null);
85
- expect(result).toBeNull();
96
+ const result = readExport({
97
+ session: null,
98
+ notebook: null,
99
+ filename: null,
100
+ appConfig: {},
101
+ });
102
+ expect(result.snapshot).toBeNull();
86
103
  });
87
104
 
88
105
  it("logs error when session and notebook have different cells", () => {
89
106
  const session = createSession([createSessionCell("cell-1")]);
90
- const notebook = createNotebook([createNotebookCell("cell-2")]);
107
+ const notebook = createNotebook([createNotebookCell("cell-2", {})]);
91
108
 
92
- const result = notebookStateFromSession(session, notebook);
109
+ const result = readExport({
110
+ session: session,
111
+ notebook: notebook,
112
+ filename: null,
113
+ appConfig: {},
114
+ });
93
115
 
94
116
  expect(Logger.warn).toHaveBeenCalledWith(
95
117
  "Session and notebook have different cells, attempted merge.",
96
118
  );
97
119
  // Should have the same cell structure as notebook
98
- expect(result).not.toBeNull();
99
- invariant(result, "result is null");
100
- expect(result.cellIds.inOrderIds).toEqual(
101
- MultiColumn.from([["cell-2"]]).inOrderIds,
102
- );
120
+ invariant(result.snapshot, "no snapshot");
121
+ expect(result.snapshot.document.order).toEqual(["cell-2"]);
103
122
  });
104
123
  });
105
124
 
106
125
  describe("null/undefined inputs", () => {
107
126
  it("returns null when both session and notebook are null", () => {
108
- const result = notebookStateFromSession(null, null);
109
- expect(result).toBeNull();
127
+ const result = readExport({
128
+ session: null,
129
+ notebook: null,
130
+ filename: null,
131
+ appConfig: {},
132
+ });
133
+ expect(result.snapshot).toBeNull();
110
134
  });
111
135
 
112
136
  it("returns null when both session and notebook are undefined", () => {
113
- const result = notebookStateFromSession(undefined, undefined);
114
- expect(result).toBeNull();
137
+ const result = readExport({
138
+ session: undefined,
139
+ notebook: undefined,
140
+ filename: null,
141
+ appConfig: {},
142
+ });
143
+ expect(result.snapshot).toBeNull();
115
144
  });
116
145
 
117
146
  it("returns null when session is null and notebook is undefined", () => {
118
- const result = notebookStateFromSession(null, undefined);
119
- expect(result).toBeNull();
147
+ const result = readExport({
148
+ session: null,
149
+ notebook: undefined,
150
+ filename: null,
151
+ appConfig: {},
152
+ });
153
+ expect(result.snapshot).toBeNull();
120
154
  });
121
155
  });
122
156
 
123
157
  describe("session only scenarios", () => {
124
158
  it("creates state from session with single cell", () => {
125
159
  const session = createSession([createSessionCell("cell-1")]);
126
- const result = notebookStateFromSession(session, null);
160
+ const result = readExport({
161
+ session: session,
162
+ notebook: null,
163
+ filename: null,
164
+ appConfig: {},
165
+ });
127
166
 
128
- expect(result).not.toBeNull();
129
- invariant(result, "result is null");
130
- expect(result.cellIds.inOrderIds).toEqual(
131
- MultiColumn.from([[CELL_1]]).inOrderIds,
132
- );
133
- expect(result.cellData[CELL_1].code).toBe("");
167
+ invariant(result.snapshot, "no snapshot");
168
+ expect(result.snapshot.document.order).toEqual([CELL_1]);
169
+ // The session knows outputs, not source; the host withholds it as null.
170
+ expect(cellIn(result, CELL_1).code).toBeNull();
134
171
  expect(result.cellRuntime[CELL_1]).toBeDefined();
135
172
  });
136
173
 
174
+ it("carries the page's filename and app config into the snapshot", () => {
175
+ const session = createSession([createSessionCell("cell-1")]);
176
+ const result = readExport({
177
+ session,
178
+ notebook: null,
179
+ filename: "notebook.py",
180
+ appConfig: { width: "full" },
181
+ });
182
+
183
+ invariant(result.snapshot, "no snapshot");
184
+ expect(result.snapshot.notebook.name).toBe("notebook.py");
185
+ expect(result.snapshot.document.app_config).toEqual({ width: "full" });
186
+ });
187
+
137
188
  it("creates state from session with multiple cells", () => {
138
189
  const session = createSession([
139
190
  createSessionCell("cell-1"),
140
191
  createSessionCell("cell-2"),
141
192
  ]);
142
- const result = notebookStateFromSession(session, null);
193
+ const result = readExport({
194
+ session: session,
195
+ notebook: null,
196
+ filename: null,
197
+ appConfig: {},
198
+ });
143
199
 
144
- expect(result).not.toBeNull();
145
- invariant(result, "result is null");
146
- expect(result.cellIds.inOrderIds).toEqual(
147
- MultiColumn.from([["cell-1", "cell-2"]]).inOrderIds,
148
- );
149
- expect(Object.keys((result as any).cellData)).toEqual([
200
+ invariant(result.snapshot, "no snapshot");
201
+ expect(result.snapshot.document.order).toEqual(["cell-1", "cell-2"]);
202
+ expect(result.snapshot.cells.map((cell) => cell.id)).toEqual([
150
203
  "cell-1",
151
204
  "cell-2",
152
205
  ]);
@@ -166,16 +219,23 @@ describe("notebookStateFromSession", () => {
166
219
  const session = createSession([
167
220
  createSessionCell("cell-1", [errorOutput]),
168
221
  ]);
169
- const result = notebookStateFromSession(session, null);
222
+ const result = readExport({
223
+ session: session,
224
+ notebook: null,
225
+ filename: null,
226
+ appConfig: {},
227
+ });
170
228
 
171
- expect(result).not.toBeNull();
172
- invariant(result, "result is null");
229
+ invariant(result.snapshot, "no snapshot");
173
230
  expect(result.cellRuntime[CELL_1].output).toEqual({
174
231
  channel: "marimo-error",
175
232
  data: [
176
233
  {
177
- type: "unknown",
234
+ type: "exception",
235
+ exception_type: "ValueError",
178
236
  msg: "Something went wrong",
237
+ raising_cell: null,
238
+ traceback: "Traceback line 1",
179
239
  },
180
240
  ],
181
241
  mimetype: "application/vnd.marimo+error",
@@ -183,6 +243,57 @@ describe("notebookStateFromSession", () => {
183
243
  });
184
244
  });
185
245
 
246
+ it("restores matching code from the session", () => {
247
+ const code = "raise ValueError('cached failure')";
248
+ const session = createSession([
249
+ createSessionCell(
250
+ "cell-1",
251
+ [
252
+ {
253
+ type: "error",
254
+ ename: "ValueError",
255
+ evalue: "cached failure",
256
+ traceback: ["Traceback\n", "ValueError: cached failure"],
257
+ code,
258
+ },
259
+ ],
260
+ [
261
+ {
262
+ type: "stream",
263
+ name: "stderr",
264
+ text: "ValueError: cached <failure>",
265
+ mimetype: "application/vnd.marimo+traceback",
266
+ traceback_format: "text",
267
+ code,
268
+ },
269
+ ],
270
+ ),
271
+ ]);
272
+ const state = readExport({
273
+ session: session,
274
+ notebook: null,
275
+ filename: null,
276
+ appConfig: {},
277
+ });
278
+ invariant(state.snapshot, "no snapshot");
279
+ expect(state.cellRuntime[CELL_1].output).toMatchObject({
280
+ code,
281
+ data: [
282
+ {
283
+ type: "exception",
284
+ exception_type: "ValueError",
285
+ msg: "cached failure",
286
+ traceback: "Traceback\nValueError: cached failure",
287
+ },
288
+ ],
289
+ });
290
+ expect(state.cellRuntime[CELL_1].consoleOutputs[0].code).toBe(code);
291
+ expect(state.cellRuntime[CELL_1].consoleOutputs[0]).toMatchObject({
292
+ traceback_format: "text",
293
+ data: "ValueError: cached <failure>",
294
+ });
295
+ });
296
+
186
297
  it("handles data output in session cell", () => {
187
298
  const dataOutput = {
188
299
  type: "data" as const,
@@ -193,10 +304,14 @@ describe("notebookStateFromSession", () => {
193
304
  const session = createSession([
194
305
  createSessionCell("cell-1", [dataOutput]),
195
306
  ]);
196
- const result = notebookStateFromSession(session, null);
307
+ const result = readExport({
308
+ session: session,
309
+ notebook: null,
310
+ filename: null,
311
+ appConfig: {},
312
+ });
197
313
 
198
- expect(result).not.toBeNull();
199
- invariant(result, "result is null");
314
+ invariant(result.snapshot, "no snapshot");
200
315
  expect(result.cellRuntime[CELL_1].output).toEqual({
201
316
  channel: "output",
202
317
  data: "Hello World",
@@ -223,10 +338,14 @@ describe("notebookStateFromSession", () => {
223
338
  const session = createSession([
224
339
  createSessionCell("cell-1", [], consoleOutputs),
225
340
  ]);
226
- const result = notebookStateFromSession(session, null);
341
+ const result = readExport({
342
+ session: session,
343
+ notebook: null,
344
+ filename: null,
345
+ appConfig: {},
346
+ });
227
347
 
228
- expect(result).not.toBeNull();
229
- invariant(result, "result is null");
348
+ invariant(result.snapshot, "no snapshot");
230
349
  expect(result.cellRuntime[CELL_1].consoleOutputs).toEqual([
231
350
  {
232
351
  channel: "stdout",
@@ -254,7 +373,12 @@ describe("notebookStateFromSession", () => {
254
373
  const session = createSession([
255
374
  createSessionCell("cell-1", [dataOutput]),
256
375
  ]);
257
- const result = notebookStateFromSession(session, null);
376
+ const result = readExport({
377
+ session: session,
378
+ notebook: null,
379
+ filename: null,
380
+ appConfig: {},
381
+ });
258
382
 
259
383
  expect(parseOutline).toHaveBeenCalledWith({
260
384
  channel: "output",
@@ -262,16 +386,21 @@ describe("notebookStateFromSession", () => {
262
386
  mimetype: "text/html",
263
387
  timestamp: 0,
264
388
  });
265
- invariant(result, "result is null");
389
+ invariant(result.snapshot, "no snapshot");
266
390
  expect(result.cellRuntime[CELL_1].outline).toBe(mockOutline);
267
391
  });
268
392
 
269
393
  it("sets outline to null when no output exists", () => {
270
394
  const session = createSession([createSessionCell("cell-1")]);
271
- const result = notebookStateFromSession(session, null);
395
+ const result = readExport({
396
+ session: session,
397
+ notebook: null,
398
+ filename: null,
399
+ appConfig: {},
400
+ });
272
401
 
273
402
  expect(parseOutline).not.toHaveBeenCalled();
274
- invariant(result, "result is null");
403
+ invariant(result.snapshot, "no snapshot");
275
404
  expect(result.cellRuntime[CELL_1].outline).toBeNull();
276
405
  });
277
406
  });
@@ -279,46 +408,59 @@ describe("notebookStateFromSession", () => {
279
408
  describe("notebook only scenarios", () => {
280
409
  it("creates state from notebook with single cell", () => {
281
410
  const notebook = createNotebook([
282
- createNotebookCell("cell-1", "print('hello')", "my_cell"),
411
+ createNotebookCell("cell-1", {
412
+ code: "print('hello')",
413
+ name: "my_cell",
414
+ }),
283
415
  ]);
284
- const result = notebookStateFromSession(null, notebook);
416
+ const result = readExport({
417
+ session: null,
418
+ notebook: notebook,
419
+ filename: null,
420
+ appConfig: {},
421
+ });
285
422
 
286
- expect(result).not.toBeNull();
287
- invariant(result, "result is null");
288
- expect(result.cellIds.inOrderIds).toEqual(
289
- MultiColumn.from([[CELL_1]]).inOrderIds,
290
- );
291
- expect(result.cellData[CELL_1]).toEqual({
292
- id: "cell-1",
423
+ invariant(result.snapshot, "no snapshot");
424
+ expect(result.snapshot.document.order).toEqual([CELL_1]);
425
+ expect(cellIn(result, CELL_1)).toEqual({
426
+ id: CELL_1,
427
+ notebook_id: "embedded",
293
428
  name: "my_cell",
294
429
  code: "print('hello')",
295
- edited: false,
296
- lastCodeRun: null,
297
- lastExecutionTime: null,
298
430
  config: {
299
431
  hide_code: false,
300
432
  disabled: false,
301
433
  column: null,
302
434
  expand_output: false,
303
435
  },
304
- serializedEditorState: null,
436
+ etag: `embedded:${CELL_1}`,
437
+ code_hash: `embedded:${CELL_1}:code`,
438
+ version: 1,
305
439
  });
306
440
  });
307
441
 
308
442
  it("creates state from notebook with custom config", () => {
309
443
  const notebook = createNotebook([
310
- createNotebookCell("cell-1", "code", "name", {
311
- hide_code: true,
312
- disabled: true,
313
- column: 1,
314
- expand_output: true,
444
+ createNotebookCell("cell-1", {
445
+ code: "code",
446
+ name: "name",
447
+ config: {
448
+ hide_code: true,
449
+ disabled: true,
450
+ column: 1,
451
+ expand_output: true,
452
+ },
315
453
  }),
316
454
  ]);
317
- const result = notebookStateFromSession(null, notebook);
455
+ const result = readExport({
456
+ session: null,
457
+ notebook: notebook,
458
+ filename: null,
459
+ appConfig: {},
460
+ });
318
461
 
319
- expect(result).not.toBeNull();
320
- invariant(result, "result is null");
321
- expect(result.cellData[CELL_1].config).toEqual({
462
+ invariant(result.snapshot, "no snapshot");
463
+ expect(cellIn(result, CELL_1).config).toEqual({
322
464
  hide_code: true,
323
465
  disabled: true,
324
466
  column: 1,
@@ -339,24 +481,28 @@ describe("notebookStateFromSession", () => {
339
481
  },
340
482
  };
341
483
  const notebook = createNotebook([notebookCell]);
342
- const result = notebookStateFromSession(null, notebook);
484
+ const result = readExport({
485
+ session: null,
486
+ notebook: notebook,
487
+ filename: null,
488
+ appConfig: {},
489
+ });
343
490
 
344
- expect(result).not.toBeNull();
345
- invariant(result, "result is null");
346
- expect(result.cellData[CELL_1]).toEqual({
347
- id: "cell-1",
348
- name: "",
349
- code: "",
350
- edited: false,
351
- lastCodeRun: null,
352
- lastExecutionTime: null,
491
+ invariant(result.snapshot, "no snapshot");
492
+ expect(cellIn(result, CELL_1)).toEqual({
493
+ id: CELL_1,
494
+ notebook_id: "embedded",
495
+ name: "_",
496
+ code: null,
353
497
  config: {
354
498
  hide_code: false,
355
499
  disabled: false,
356
500
  column: null,
357
501
  expand_output: false,
358
502
  },
359
- serializedEditorState: null,
503
+ etag: `embedded:${CELL_1}`,
504
+ code_hash: `embedded:${CELL_1}:code`,
505
+ version: 1,
360
506
  });
361
507
  });
362
508
 
@@ -373,27 +519,29 @@ describe("notebookStateFromSession", () => {
373
519
  },
374
520
  };
375
521
  const notebook = createNotebook([notebookCell as any]);
376
- const result = notebookStateFromSession(null, notebook);
522
+ const result = readExport({
523
+ session: null,
524
+ notebook: notebook,
525
+ filename: null,
526
+ appConfig: {},
527
+ });
377
528
 
378
- expect(result).not.toBeNull();
379
- invariant(result, "result is null");
380
- expect(result.cellIds.inOrderIds).toEqual(
381
- MultiColumn.from([[SETUP_CELL_ID]]).inOrderIds,
382
- );
383
- expect(result.cellData[SETUP_CELL_ID]).toEqual({
529
+ invariant(result.snapshot, "no snapshot");
530
+ expect(result.snapshot.document.order).toEqual([SETUP_CELL_ID]);
531
+ expect(cellIn(result, SETUP_CELL_ID)).toEqual({
384
532
  id: SETUP_CELL_ID,
533
+ notebook_id: "embedded",
385
534
  name: "setup",
386
535
  code: "import marimo as mo",
387
- edited: false,
388
- lastCodeRun: null,
389
- lastExecutionTime: null,
390
536
  config: {
391
537
  hide_code: false,
392
538
  disabled: false,
393
539
  column: null,
394
540
  expand_output: false,
395
541
  },
396
- serializedEditorState: null,
542
+ etag: `embedded:${SETUP_CELL_ID}`,
543
+ code_hash: `embedded:${SETUP_CELL_ID}:code`,
544
+ version: 1,
397
545
  });
398
546
  });
399
547
  });
@@ -415,26 +563,33 @@ describe("notebookStateFromSession", () => {
415
563
  ),
416
564
  ]);
417
565
  const notebook = createNotebook([
418
- createNotebookCell("cell-1", "print('hello')", "my_cell"),
566
+ createNotebookCell("cell-1", {
567
+ code: "print('hello')",
568
+ name: "my_cell",
569
+ }),
419
570
  ]);
420
- const result = notebookStateFromSession(session, notebook);
571
+ const result = readExport({
572
+ session: session,
573
+ notebook: notebook,
574
+ filename: null,
575
+ appConfig: {},
576
+ });
421
577
 
422
- expect(result).not.toBeNull();
423
- invariant(result, "result is null");
424
- expect(result.cellData[CELL_1]).toEqual({
425
- id: "cell-1",
578
+ invariant(result.snapshot, "no snapshot");
579
+ expect(cellIn(result, CELL_1)).toEqual({
580
+ id: CELL_1,
581
+ notebook_id: "embedded",
426
582
  name: "my_cell",
427
583
  code: "print('hello')",
428
- edited: false,
429
- lastCodeRun: null,
430
- lastExecutionTime: null,
431
584
  config: {
432
585
  hide_code: false,
433
586
  disabled: false,
434
587
  column: null,
435
588
  expand_output: false,
436
589
  },
437
- serializedEditorState: null,
590
+ etag: `embedded:${CELL_1}`,
591
+ code_hash: `embedded:${CELL_1}:code`,
592
+ version: 1,
438
593
  });
439
594
  // Null result means no output.
440
595
  expect(result.cellRuntime[CELL_1].consoleOutputs).toEqual([]);
@@ -446,17 +601,19 @@ describe("notebookStateFromSession", () => {
446
601
  createSessionCell("cell-2"),
447
602
  ]);
448
603
  const notebook = createNotebook([
449
- createNotebookCell("cell-2"),
450
- createNotebookCell("cell-1"),
604
+ createNotebookCell("cell-2", {}),
605
+ createNotebookCell("cell-1", {}),
451
606
  ]);
452
607
 
453
- const result = notebookStateFromSession(session, notebook);
608
+ const result = readExport({
609
+ session: session,
610
+ notebook: notebook,
611
+ filename: null,
612
+ appConfig: {},
613
+ });
454
614
 
455
- expect(result).not.toBeNull();
456
- invariant(result, "result is null");
457
- expect(result.cellIds.inOrderIds).toEqual(
458
- MultiColumn.from([["cell-2", "cell-1"]]).inOrderIds,
459
- );
615
+ invariant(result.snapshot, "no snapshot");
616
+ expect(result.snapshot.document.order).toEqual(["cell-2", "cell-1"]);
460
617
  });
461
618
 
462
619
  it("creates state when session and notebook have identical cell arrays", () => {
@@ -465,52 +622,73 @@ describe("notebookStateFromSession", () => {
465
622
  createSessionCell("cell-2"),
466
623
  ]);
467
624
  const notebook = createNotebook([
468
- createNotebookCell("cell-1"),
469
- createNotebookCell("cell-2"),
625
+ createNotebookCell("cell-1", {}),
626
+ createNotebookCell("cell-2", {}),
470
627
  ]);
471
628
 
472
- const result = notebookStateFromSession(session, notebook);
629
+ const result = readExport({
630
+ session: session,
631
+ notebook: notebook,
632
+ filename: null,
633
+ appConfig: {},
634
+ });
473
635
 
474
636
  expect(Logger.error).not.toHaveBeenCalled();
475
- expect(result).not.toBeNull();
476
- invariant(result, "result is null");
477
- expect(result.cellIds.inOrderIds).toEqual(
478
- MultiColumn.from([["cell-1", "cell-2"]]).inOrderIds,
479
- );
637
+ invariant(result.snapshot, "no snapshot");
638
+ expect(result.snapshot.document.order).toEqual(["cell-1", "cell-2"]);
480
639
  });
481
640
  });
482
641
 
483
642
  describe("empty cells scenarios", () => {
484
643
  it("warns and returns null when session has empty cells array", () => {
485
644
  const session = createSession([]);
486
- const result = notebookStateFromSession(session, null);
645
+ const result = readExport({
646
+ session: session,
647
+ notebook: null,
648
+ filename: null,
649
+ appConfig: {},
650
+ });
487
651
 
488
- expect(result).toBeNull();
652
+ expect(result.snapshot).toBeNull();
489
653
  });
490
654
 
491
655
  it("warns and returns null when notebook has empty cells array", () => {
492
656
  const notebook = createNotebook([]);
493
- const result = notebookStateFromSession(null, notebook);
657
+ const result = readExport({
658
+ session: null,
659
+ notebook: notebook,
660
+ filename: null,
661
+ appConfig: {},
662
+ });
494
663
 
495
- expect(result).toBeNull();
664
+ expect(result.snapshot).toBeNull();
496
665
  });
497
666
 
498
667
  it("warns and returns null when both have empty cells arrays", () => {
499
668
  const session = createSession([]);
500
669
  const notebook = createNotebook([]);
501
- const result = notebookStateFromSession(session, notebook);
670
+ const result = readExport({
671
+ session: session,
672
+ notebook: notebook,
673
+ filename: null,
674
+ appConfig: {},
675
+ });
502
676
 
503
- expect(result).toBeNull();
677
+ expect(result.snapshot).toBeNull();
504
678
  });
505
679
  });
506
680
 
507
681
  describe("edge cases", () => {
508
682
  it("handles session cell with no outputs", () => {
509
683
  const session = createSession([createSessionCell("cell-1", [])]);
510
- const result = notebookStateFromSession(session, null);
684
+ const result = readExport({
685
+ session: session,
686
+ notebook: null,
687
+ filename: null,
688
+ appConfig: {},
689
+ });
511
690
 
512
- expect(result).not.toBeNull();
513
- invariant(result, "result is null");
691
+ invariant(result.snapshot, "no snapshot");
514
692
  expect(result.cellRuntime[CELL_1].output).toBeNull();
515
693
  expect(result.cellRuntime[CELL_1].consoleOutputs).toEqual([]);
516
694
  expect(result.cellRuntime[CELL_1].outline).toBeNull();
@@ -518,10 +696,14 @@ describe("notebookStateFromSession", () => {
518
696
 
519
697
  it("handles session cell with empty console array", () => {
520
698
  const session = createSession([createSessionCell("cell-1", [], [])]);
521
- const result = notebookStateFromSession(session, null);
699
+ const result = readExport({
700
+ session: session,
701
+ notebook: null,
702
+ filename: null,
703
+ appConfig: {},
704
+ });
522
705
 
523
- expect(result).not.toBeNull();
524
- invariant(result, "result is null");
706
+ invariant(result.snapshot, "no snapshot");
525
707
  expect(result.cellRuntime[CELL_1].consoleOutputs).toEqual([]);
526
708
  });
527
709
 
@@ -531,10 +713,14 @@ describe("notebookStateFromSession", () => {
531
713
  { type: "data" as const, data: { "text/plain": "Second" } },
532
714
  ];
533
715
  const session = createSession([createSessionCell("cell-1", outputs)]);
534
- const result = notebookStateFromSession(session, null);
716
+ const result = readExport({
717
+ session: session,
718
+ notebook: null,
719
+ filename: null,
720
+ appConfig: {},
721
+ });
535
722
 
536
- expect(result).not.toBeNull();
537
- invariant(result, "result is null");
723
+ invariant(result.snapshot, "no snapshot");
538
724
  expect(result.cellRuntime[CELL_1].output).toEqual({
539
725
  channel: "output",
540
726
  data: "First",
@@ -554,10 +740,14 @@ describe("notebookStateFromSession", () => {
554
740
  const session = createSession([
555
741
  createSessionCell("cell-1", [dataOutput]),
556
742
  ]);
557
- const result = notebookStateFromSession(session, null);
743
+ const result = readExport({
744
+ session: session,
745
+ notebook: null,
746
+ filename: null,
747
+ appConfig: {},
748
+ });
558
749
 
559
- expect(result).not.toBeNull();
560
- invariant(result, "result is null");
750
+ invariant(result.snapshot, "no snapshot");
561
751
  expect(result.cellRuntime[CELL_1].output).toEqual({
562
752
  channel: "output",
563
753
  data: "Plain text",
@@ -574,10 +764,14 @@ describe("notebookStateFromSession", () => {
574
764
  const session = createSession([
575
765
  createSessionCell("cell-1", [dataOutput]),
576
766
  ]);
577
- const result = notebookStateFromSession(session, null);
767
+ const result = readExport({
768
+ session: session,
769
+ notebook: null,
770
+ filename: null,
771
+ appConfig: {},
772
+ });
578
773
 
579
- expect(result).not.toBeNull();
580
- invariant(result, "result is null");
774
+ invariant(result.snapshot, "no snapshot");
581
775
  expect(result.cellRuntime[CELL_1].output).toEqual({
582
776
  channel: "output",
583
777
  data: undefined,
@@ -588,22 +782,29 @@ describe("notebookStateFromSession", () => {
588
782
 
589
783
  it("returns correct structure with all expected properties", () => {
590
784
  const session = createSession([createSessionCell("cell-1")]);
591
- const result = notebookStateFromSession(session, null);
592
-
593
- expect(result).not.toBeNull();
594
- invariant(result, "result is null");
595
- expect(result).toHaveProperty("cellIds");
596
- expect(result).toHaveProperty("cellData");
597
- expect(result).toHaveProperty("cellRuntime");
598
- expect(result).toHaveProperty("cellHandles");
599
- expect(result).toHaveProperty("history");
600
- expect(result).toHaveProperty("scrollKey");
601
- expect(result).toHaveProperty("cellLogs");
602
-
603
- expect(result.cellHandles).toEqual({});
604
- expect(result.history).toEqual([]);
605
- expect(result.scrollKey).toBeNull();
606
- expect(result.cellLogs).toEqual([]);
785
+ const result = readExport({
786
+ session: session,
787
+ notebook: null,
788
+ filename: null,
789
+ appConfig: {},
790
+ });
791
+
792
+ invariant(result.snapshot, "no snapshot");
793
+ expect(result.snapshot.notebook).toEqual({
794
+ id: "embedded",
795
+ project_id: "embedded",
796
+ path: null,
797
+ name: "",
798
+ updated_at: null,
799
+ });
800
+ expect(result.snapshot.document).toMatchObject({
801
+ notebook_id: "embedded",
802
+ order: result.snapshot.cells.map((cell) => cell.id),
803
+ version: 1,
804
+ });
805
+ expect(Object.keys(result.cellRuntime)).toEqual(
806
+ result.snapshot.document.order,
807
+ );
607
808
  });
608
809
  });
609
810
 
@@ -620,12 +821,42 @@ describe("notebookStateFromSession", () => {
620
821
  };
621
822
  // Create notebook cells with code values 'a' through 'f'
622
823
  const notebookCells = [
623
- createNotebookCell("cell-a", "a", null, null, hashes.a),
624
- createNotebookCell("cell-b", "b", null, null, hashes.b),
625
- createNotebookCell("cell-c", "c", null, null, hashes.c),
626
- createNotebookCell("cell-d", "d", null, null, hashes.d),
627
- createNotebookCell("cell-e", "e", null, null, hashes.e),
628
- createNotebookCell("cell-f", "f", null, null, hashes.f),
824
+ createNotebookCell("cell-a", {
825
+ code: "a",
826
+ name: null,
827
+ config: null,
828
+ code_hash: hashes.a,
829
+ }),
830
+ createNotebookCell("cell-b", {
831
+ code: "b",
832
+ name: null,
833
+ config: null,
834
+ code_hash: hashes.b,
835
+ }),
836
+ createNotebookCell("cell-c", {
837
+ code: "c",
838
+ name: null,
839
+ config: null,
840
+ code_hash: hashes.c,
841
+ }),
842
+ createNotebookCell("cell-d", {
843
+ code: "d",
844
+ name: null,
845
+ config: null,
846
+ code_hash: hashes.d,
847
+ }),
848
+ createNotebookCell("cell-e", {
849
+ code: "e",
850
+ name: null,
851
+ config: null,
852
+ code_hash: hashes.e,
853
+ }),
854
+ createNotebookCell("cell-f", {
855
+ code: "f",
856
+ name: null,
857
+ config: null,
858
+ code_hash: hashes.f,
859
+ }),
629
860
  ];
630
861
  // Create session cells with matching code_hashes
631
862
  const sessionCells = [
@@ -668,19 +899,26 @@ describe("notebookStateFromSession", () => {
668
899
  ];
669
900
  const session = createSession(sessionCells);
670
901
  const notebook = createNotebook(notebookCells);
671
- const result = notebookStateFromSession(session, notebook);
672
- expect(result).not.toBeNull();
673
- invariant(result, "result is null");
902
+ const result = readExport({
903
+ session: session,
904
+ notebook: notebook,
905
+ filename: null,
906
+ appConfig: {},
907
+ });
908
+ invariant(result.snapshot, "no snapshot");
674
909
  // Should have all cell IDs in order
675
- expect(result.cellIds.inOrderIds).toEqual(
676
- MultiColumn.from([
677
- ["cell-a", "cell-b", "cell-c", "cell-d", "cell-e", "cell-f"],
678
- ]).inOrderIds,
679
- );
910
+ expect(result.snapshot.document.order).toEqual([
911
+ "cell-a",
912
+ "cell-b",
913
+ "cell-c",
914
+ "cell-d",
915
+ "cell-e",
916
+ "cell-f",
917
+ ]);
680
918
  // Should have correct code and output for each cell
681
919
  for (const code of ["a", "b", "c", "d", "e", "f"]) {
682
920
  const cid = cellId(`cell-${code}`);
683
- expect(result.cellData[cid].code).toBe(code);
921
+ expect(cellIn(result, cid).code).toBe(code);
684
922
  expect(result.cellRuntime[cid].output).toEqual({
685
923
  channel: "output",
686
924
  data: `${code.toUpperCase()}!`,
@@ -738,32 +976,64 @@ describe("notebookStateFromSession", () => {
738
976
 
739
977
  // Notebook has cells with code 'a', 'c', 'z', 'e', 'g'
740
978
  const notebookCells = [
741
- createNotebookCell("cell-a", "a", null, null, hashes.a),
742
- createNotebookCell("cell-c", "c", null, null, hashes.c),
743
- createNotebookCell("cell-z", "z", null, null, hashes.z),
744
- createNotebookCell("cell-e", "e", null, null, hashes.e),
745
- createNotebookCell("cell-g", "g", null, null, hashes.g),
979
+ createNotebookCell("cell-a", {
980
+ code: "a",
981
+ name: null,
982
+ config: null,
983
+ code_hash: hashes.a,
984
+ }),
985
+ createNotebookCell("cell-c", {
986
+ code: "c",
987
+ name: null,
988
+ config: null,
989
+ code_hash: hashes.c,
990
+ }),
991
+ createNotebookCell("cell-z", {
992
+ code: "z",
993
+ name: null,
994
+ config: null,
995
+ code_hash: hashes.z,
996
+ }),
997
+ createNotebookCell("cell-e", {
998
+ code: "e",
999
+ name: null,
1000
+ config: null,
1001
+ code_hash: hashes.e,
1002
+ }),
1003
+ createNotebookCell("cell-g", {
1004
+ code: "g",
1005
+ name: null,
1006
+ config: null,
1007
+ code_hash: hashes.g,
1008
+ }),
746
1009
  ];
747
1010
 
748
1011
  const session = createSession(sessionCells);
749
1012
  const notebook = createNotebook(notebookCells);
750
- const result = notebookStateFromSession(session, notebook);
1013
+ const result = readExport({
1014
+ session: session,
1015
+ notebook: notebook,
1016
+ filename: null,
1017
+ appConfig: {},
1018
+ });
751
1019
 
752
- expect(result).not.toBeNull();
753
- invariant(result, "result is null");
1020
+ invariant(result.snapshot, "no snapshot");
754
1021
 
755
1022
  // Should have notebook cell IDs in order (notebook is canonical)
756
- expect(result.cellIds.inOrderIds).toEqual(
757
- MultiColumn.from([["cell-a", "cell-c", "cell-z", "cell-e", "cell-g"]])
758
- .inOrderIds,
759
- );
1023
+ expect(result.snapshot.document.order).toEqual([
1024
+ "cell-a",
1025
+ "cell-c",
1026
+ "cell-z",
1027
+ "cell-e",
1028
+ "cell-g",
1029
+ ]);
760
1030
 
761
1031
  // Should have correct code for each cell
762
- expect(result.cellData[cellId("cell-a")].code).toBe("a");
763
- expect(result.cellData[cellId("cell-c")].code).toBe("c");
764
- expect(result.cellData[cellId("cell-z")].code).toBe("z");
765
- expect(result.cellData[cellId("cell-e")].code).toBe("e");
766
- expect(result.cellData[cellId("cell-g")].code).toBe("g");
1032
+ expect(cellIn(result, "cell-a").code).toBe("a");
1033
+ expect(cellIn(result, "cell-c").code).toBe("c");
1034
+ expect(cellIn(result, "cell-z").code).toBe("z");
1035
+ expect(cellIn(result, "cell-e").code).toBe("e");
1036
+ expect(cellIn(result, "cell-g").code).toBe("g");
767
1037
 
768
1038
  // Should have session outputs for matching cells (a, c, e)
769
1039
  expect(result.cellRuntime[cellId("cell-a")].output).toEqual({
@@ -859,35 +1129,48 @@ describe("notebookStateFromSession", () => {
859
1129
 
860
1130
  // Notebook has cells: cell-1 (1 / 0, no hash), cell-2 (mo.md("Hello"), hash=moMd), cell-3 (slider, hash=slider)
861
1131
  const notebookCells = [
862
- createNotebookCell("cell-1", "1 / 0", null, null, null), // no hash
863
- createNotebookCell("cell-2", 'mo.md("Hello")', null, null, hashes.moMd),
864
- createNotebookCell(
865
- "cell-3",
866
- "x = mo.ui.slider(0, 10)",
867
- null,
868
- null,
869
- hashes.slider,
870
- ),
1132
+ createNotebookCell("cell-1", {
1133
+ code: "1 / 0",
1134
+ name: null,
1135
+ config: null,
1136
+ code_hash: null,
1137
+ }), // no hash
1138
+ createNotebookCell("cell-2", {
1139
+ code: 'mo.md("Hello")',
1140
+ name: null,
1141
+ config: null,
1142
+ code_hash: hashes.moMd,
1143
+ }),
1144
+ createNotebookCell("cell-3", {
1145
+ code: "x = mo.ui.slider(0, 10)",
1146
+ name: null,
1147
+ config: null,
1148
+ code_hash: hashes.slider,
1149
+ }),
871
1150
  ];
872
1151
 
873
1152
  const session = createSession(sessionCells);
874
1153
  const notebook = createNotebook(notebookCells);
875
- const result = notebookStateFromSession(session, notebook);
1154
+ const result = readExport({
1155
+ session: session,
1156
+ notebook: notebook,
1157
+ filename: null,
1158
+ appConfig: {},
1159
+ });
876
1160
 
877
- expect(result).not.toBeNull();
878
- invariant(result, "result is null");
1161
+ invariant(result.snapshot, "no snapshot");
879
1162
 
880
1163
  // Should have notebook cell IDs in order (notebook is canonical)
881
- expect(result.cellIds.inOrderIds).toEqual(
882
- MultiColumn.from([["cell-1", "cell-2", "cell-3"]]).inOrderIds,
883
- );
1164
+ expect(result.snapshot.document.order).toEqual([
1165
+ "cell-1",
1166
+ "cell-2",
1167
+ "cell-3",
1168
+ ]);
884
1169
 
885
1170
  // Should have correct code from notebook
886
- expect(result.cellData[cellId("cell-1")].code).toBe("1 / 0");
887
- expect(result.cellData[cellId("cell-2")].code).toBe('mo.md("Hello")');
888
- expect(result.cellData[cellId("cell-3")].code).toBe(
889
- "x = mo.ui.slider(0, 10)",
890
- );
1171
+ expect(cellIn(result, "cell-1").code).toBe("1 / 0");
1172
+ expect(cellIn(result, "cell-2").code).toBe('mo.md("Hello")');
1173
+ expect(cellIn(result, "cell-3").code).toBe("x = mo.ui.slider(0, 10)");
891
1174
 
892
1175
  // cell-1: No matching session cell (hash is null), gets stub session cell
893
1176
  expect(result.cellRuntime[cellId("cell-1")].output).toBeNull();