@marimo-team/islands 0.25.3-dev141 → 0.25.3-dev143

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 (472) hide show
  1. package/dist/{ConnectedDataExplorerComponent-CNSxdKyJ.js → ConnectedDataExplorerComponent-BAiSVaHj.js} +17 -15
  2. package/dist/{ErrorBoundary-Cg59O3xL.js → ErrorBoundary-BRBKqg2U.js} +16 -16
  3. package/dist/{abnfDiagram-VCTEODGH-DQDjNXt3.js → abnfDiagram-VCTEODGH-BBHN92-F.js} +2 -2
  4. package/dist/any-language-editor-3E24SnCV.js +75 -0
  5. package/dist/{architectureDiagram-5GKGNRK7-Nmls7Wxn.js → architectureDiagram-5GKGNRK7-C0Rd64qh.js} +1 -1
  6. package/dist/{arrays-CN1djC4k.js → arrays-R6JsImiT.js} +8 -0
  7. package/dist/assets/__vite-browser-external-BgQNn4dS.js +1 -0
  8. package/dist/assets/worker-FKe3RHT4.js +113 -0
  9. package/dist/{button-CvjkwdSk.js → button-BQRdqQi1.js} +199 -192
  10. package/dist/{capabilities-CQ5IjhzL.js → capabilities-CI4xUPsp.js} +2 -2
  11. package/dist/{chat-ui-BDpymeoe.js → chat-ui-CvB8Map3.js} +1195 -1195
  12. package/dist/{check-EDwSwP89.js → check-SpOMoCLP.js} +1 -1
  13. package/dist/{chunk-IMKFNOWR-CoIFEo-1.js → chunk-IMKFNOWR-hJXey5p2.js} +1 -1
  14. package/dist/{chunk-SHT3W25Y-lHiGx3ZC.js → chunk-SHT3W25Y-JMzTmmVW.js} +1 -1
  15. package/dist/{chunk-SVP7TREG-BvsHIrY_.js → chunk-SVP7TREG-BIyoHTXi.js} +1 -1
  16. package/dist/{chunk-TICWLB2K-BC8YIm_n.js → chunk-TICWLB2K-CCzH2Uwa.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-DB1kOPS6.js} +2 -2
  19. package/dist/{classDiagram-v2-VYDZK3BY-D9bfbcC3.js → classDiagram-v2-VYDZK3BY-CPaFL0OB.js} +2 -2
  20. package/dist/{code-visibility-Da3iitn_.js → code-visibility-CAgcNzoX.js} +17 -17
  21. package/dist/{common-C6FHcu5p.js → common-BovIV1xq.js} +6341 -5870
  22. package/dist/{copy-icon-Ft7t9bqz.js → copy-icon-C1trdvVt.js} +3 -3
  23. package/dist/{cynefinDiagram-5FMLGOSQ-CgWra7wt.js → cynefinDiagram-5FMLGOSQ-CF93uliH.js} +1 -1
  24. package/dist/{dagre-GXQ25YYZ-CFZ8-35c.js → dagre-GXQ25YYZ-BBB-_p9D.js} +1 -1
  25. package/dist/{data-grid-overlay-editor-mJt3Pg4S.js → data-grid-overlay-editor-CBsr8Yo0.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-BynCnbyt.js} +1 -1
  28. package/dist/{diagram-UQ7AKVKN-CQPQ6pP_.js → diagram-UQ7AKVKN-svOxikMa.js} +1 -1
  29. package/dist/{diagram-VX7I27RA-Cf3b0llz.js → diagram-VX7I27RA-BVQSnPx0.js} +1 -1
  30. package/dist/{diagram-Z3DM3KII-Bt4QLrpn.js → diagram-Z3DM3KII-nR1J0BH5.js} +1 -1
  31. package/dist/{dialog-CEBFZNyc.js → dialog-DgeqyrEZ.js} +3 -3
  32. package/dist/{dist-DpBpA_n1.js → dist-Lm-D-Vr6.js} +3 -3
  33. package/dist/{dropdown-menu-CP_qCYHC.js → dropdown-menu-GWcGCcxE.js} +1277 -1229
  34. package/dist/{ebnfDiagram-PWID7BFC-D3NAyPFY.js → ebnfDiagram-PWID7BFC-C9tq9-Qo.js} +2 -2
  35. package/dist/{erDiagram-RLTQ6QDP-Tlu09_Nm.js → erDiagram-RLTQ6QDP-BiaeB7Fi.js} +1 -1
  36. package/dist/{error-banner-Da600cwz.js → error-banner-D40pmfQQ.js} +86 -81
  37. package/dist/{cells-C8iCYvLU.js → error-entries-CmFDQ9CA.js} +1718 -1621
  38. package/dist/{feedback-button-DaPwHIdM.js → feedback-button-B_9o6DdV.js} +122 -123
  39. package/dist/{flowDiagram-HODETNUW-CAYbpJmV.js → flowDiagram-HODETNUW-f-sLm87k.js} +2 -2
  40. package/dist/{formats-BGh2thRc.js → formats-CCxaLPNs.js} +3 -3
  41. package/dist/{ganttDiagram-EL5Y4UJY-BQT16JSc.js → ganttDiagram-EL5Y4UJY-Dh_4cBJZ.js} +2 -2
  42. package/dist/{glide-data-editor-Ctz2mH6k.js → glide-data-editor-i7BEAfhs.js} +370 -368
  43. package/dist/{glide-utils-DJyqh0EM.js → glide-utils-Dz_F4pAY.js} +16 -16
  44. package/dist/{globals-EpFoRj_E.js → globals-BDzA_Re9.js} +3 -3
  45. package/dist/{highlighted-body-KPVGNVTW-zwjq21tf.js → highlighted-body-KPVGNVTW-3Ziwfz-V.js} +2 -2
  46. package/dist/{html-to-image-CZY1pIZH.js → html-to-image-BrC8OJcj.js} +634 -597
  47. package/dist/{infoDiagram-27XIBGKW-XrDxhr0x.js → infoDiagram-27XIBGKW-BHrWywBe.js} +1 -1
  48. package/dist/{ishikawaDiagram-5VMMS53U-CD1muzov.js → ishikawaDiagram-5VMMS53U-Da4s0Reg.js} +1 -1
  49. package/dist/{kanban-definition-UXKFOSKX-Dg9W142_.js → kanban-definition-UXKFOSKX-DDf1GVLj.js} +1 -1
  50. package/dist/{label-BDKF3Afc.js → label-D9_-zSg-.js} +3 -3
  51. package/dist/{linear-Cnaq3Tfb.js → linear-DWERh7eI.js} +121 -73
  52. package/dist/{loader-BQOfjTIJ.js → loader-DOVB0Syl.js} +12 -12
  53. package/dist/main.js +7548 -7226
  54. package/dist/{mermaid-CiAXjLpA.js → mermaid-ClwTt7OD.js} +38 -38
  55. package/dist/mermaid-HWGCJPDP-Du3-HPQA.js +2 -0
  56. package/dist/{mindmap-definition-YA3MSWOX-DgCidgYJ.js → mindmap-definition-YA3MSWOX-D60oMZtT.js} +1 -1
  57. package/dist/{number-overlay-editor-CtxrummL.js → number-overlay-editor-D9WjQlOL.js} +3 -3
  58. package/dist/{objects-CzUgoMIF.js → objects-DCmMvZtn.js} +1 -3
  59. package/dist/{once-BtE-wKRL.js → once-eG8Vmvjd.js} +1 -1
  60. package/dist/{pegDiagram-XKGWAZYB-coOYYKB6.js → pegDiagram-XKGWAZYB-B9wFpMga.js} +2 -2
  61. package/dist/{pieDiagram-E7YTZNPT-BnXTc3bj.js → pieDiagram-E7YTZNPT-BZwvMuBT.js} +1 -1
  62. package/dist/precisionRound-DhAzeRcm.js +49 -0
  63. package/dist/{process-output-e4jj9Ijt.js → process-output-Bw-vzyoy.js} +4 -4
  64. package/dist/{quadrantDiagram-AXDQQJYC-Ccw0xMjN.js → quadrantDiagram-AXDQQJYC-Blrm7V7_.js} +1 -1
  65. package/dist/{railroadDiagram-O6MQD6OU-B28-u83n.js → railroadDiagram-O6MQD6OU-DqhZGsN2.js} +2 -2
  66. package/dist/{react-vega-BED0DjiB.js → react-vega-C4T9Rb_w.js} +12284 -12270
  67. package/dist/{requirementDiagram-BXWQKSXE-CdYCTMu0.js → requirementDiagram-BXWQKSXE-CL5dYARV.js} +1 -1
  68. package/dist/{reveal-component-DrIXvR_7.js → reveal-component-BxP2jlPx.js} +14 -14
  69. package/dist/{select-BButFi-d.js → select-CkF_GBxO.js} +537 -458
  70. package/dist/{sequenceDiagram-WJ2MYXX4-CM3aRAe_.js → sequenceDiagram-WJ2MYXX4-BSUCRd2x.js} +1 -1
  71. package/dist/{spec-BwarBpUJ.js → spec-DiSh_qJC.js} +41 -11
  72. package/dist/{stateDiagram-D77RDMKH-DOZUMVj8.js → stateDiagram-D77RDMKH-B-1Hvyb0.js} +2 -2
  73. package/dist/{stateDiagram-v2-MP3YSRHH-CISYxma6.js → stateDiagram-v2-MP3YSRHH--HtiR4yB.js} +2 -2
  74. package/dist/style.css +1 -1
  75. package/dist/{swimlanes-42K2YHIH-BkSppxp8.js → swimlanes-42K2YHIH-Bdfhrd-2.js} +1 -1
  76. package/dist/{swimlanesDiagram-VR7AAH4N-c8G5pGxC.js → swimlanesDiagram-VR7AAH4N-BJIfxSz0.js} +2 -2
  77. package/dist/{swiper-component-DKntyn8p.js → swiper-component-BkCm-kLg.js} +2 -2
  78. package/dist/{time-BieKwdYS.js → time-BaMbJs4z.js} +18 -18
  79. package/dist/{timeline-definition-24CTP7MA-CaMQayqK.js → timeline-definition-24CTP7MA-Cs4EfFD3.js} +1 -1
  80. package/dist/{toDate-BNJf01u1.js → toDate-DGvRHwTk.js} +57 -54
  81. package/dist/{toast-B9UMEi8u.js → toast-Btbve3Lm.js} +231 -213
  82. package/dist/{tooltip-BO1REbqs.js → tooltip-CJ4Rqasp.js} +327 -303
  83. package/dist/{use-restore-focus-BEM7sFWl.js → use-restore-focus-CmGwRNId.js} +1482 -1433
  84. package/dist/{useAsyncData-Deh5kszT.js → useAsyncData-BmVgnMP5.js} +15 -14
  85. package/dist/{useDateFormatter-D8XruNGG.js → useDateFormatter-eCL_SdeG.js} +2 -2
  86. package/dist/{useDeepCompareMemoize-DXwzRINI.js → useDeepCompareMemoize-Ch_AeGu6.js} +1 -1
  87. package/dist/{useIframeCapabilities-DBETvvPl.js → useIframeCapabilities-CSdWn6NP.js} +1 -1
  88. package/dist/{useLifecycle-j7D9uD1o.js → useLifecycle-B5BX921H.js} +3 -3
  89. package/dist/{useTheme-CRnjkku0.js → useTheme-Bq9pi_vz.js} +6 -6
  90. package/dist/{vega-component-DG29TAB7.js → vega-component-BgyZ-COt.js} +147 -147
  91. package/dist/{vega-embed-container-BNHE18G9.js → vega-embed-container--LYZqguO.js} +2 -2
  92. package/dist/{vega-loader.browser-DNST6uVf.js → vega-loader.browser-B9Pz0EGP.js} +298 -507
  93. package/dist/{vennDiagram-4TSXK5OY-CF8pfaK3.js → vennDiagram-4TSXK5OY-DRu0vRjO.js} +1 -1
  94. package/dist/{wardleyDiagram-VM6X3IG4-dGPu39d-.js → wardleyDiagram-VM6X3IG4-DzbDxwDY.js} +1 -1
  95. package/dist/{xychartDiagram-S5SC5T6Z-CP6-9q56.js → xychartDiagram-S5SC5T6Z-CLWj6ZFQ.js} +2 -2
  96. package/package.json +15 -12
  97. package/src/__tests__/fixtures/{pair-preview.ts → pair-config.ts} +3 -2
  98. package/src/__tests__/host-imports.test.ts +101 -0
  99. package/src/__tests__/module-entry.test.ts +32 -0
  100. package/src/__tests__/mount.test.ts +8 -8
  101. package/src/components/ai/__tests__/ai-model-dropdown.test.tsx +63 -0
  102. package/src/components/ai/ai-model-dropdown.tsx +11 -6
  103. package/src/components/app-config/ai-config.tsx +7 -2
  104. package/src/components/chat/__tests__/message-queue.test.tsx +17 -0
  105. package/src/components/chat/acp/__tests__/session-tabs.test.tsx +43 -0
  106. package/src/components/chat/acp/__tests__/state.test.ts +2 -2
  107. package/src/components/chat/acp/blocks.tsx +3 -2
  108. package/src/components/chat/acp/session-tabs.tsx +8 -3
  109. package/src/components/chat/chat-components.tsx +2 -0
  110. package/src/components/chat/chat-panel.tsx +9 -8
  111. package/src/components/chat/chat-utils.ts +4 -8
  112. package/src/components/data-table/TableTopBar.tsx +2 -0
  113. package/src/components/data-table/__tests__/chart-spec-model.test.ts +195 -195
  114. package/src/components/data-table/__tests__/column-explorer.test.tsx +27 -1
  115. package/src/components/data-table/__tests__/columns.test.tsx +105 -0
  116. package/src/components/data-table/__tests__/context-menu-interaction.test.tsx +130 -0
  117. package/src/components/data-table/__tests__/context-menu.test.ts +176 -0
  118. package/src/components/data-table/__tests__/data-table.test.tsx +1 -0
  119. package/src/components/data-table/__tests__/date-filter-inputs.test.tsx +24 -1
  120. package/src/components/data-table/__tests__/date-popover.test.tsx +72 -0
  121. package/src/components/data-table/__tests__/export-actions.test.tsx +434 -6
  122. package/src/components/data-table/__tests__/keyboard-selection.test.tsx +188 -0
  123. package/src/components/data-table/__tests__/search-highlight.test.tsx +109 -0
  124. package/src/components/data-table/__tests__/url-detector.test.tsx +74 -0
  125. package/src/components/data-table/cell-selection/feature.ts +2 -2
  126. package/src/components/data-table/cell-selection/types.ts +2 -2
  127. package/src/components/data-table/charts/__tests__/chart-panel.test.tsx +74 -1
  128. package/src/components/data-table/charts/__tests__/spec-snapshot.test.ts +20 -20
  129. package/src/components/data-table/charts/__tests__/spec.test.ts +78 -52
  130. package/src/components/data-table/charts/__tests__/storage.test.ts +4 -1
  131. package/src/components/data-table/charts/chart-spec/spec.ts +68 -43
  132. package/src/components/data-table/charts/charts.tsx +40 -30
  133. package/src/components/data-table/charts/storage.ts +16 -5
  134. package/src/components/data-table/column-explorer-panel/column-explorer.tsx +1 -1
  135. package/src/components/data-table/column-summary/chart-spec-model.tsx +23 -16
  136. package/src/components/data-table/column-summary/column-summary.tsx +2 -4
  137. package/src/components/data-table/column-visibility-dropdown.tsx +8 -13
  138. package/src/components/data-table/columns.tsx +45 -46
  139. package/src/components/data-table/context-menu.tsx +161 -46
  140. package/src/components/data-table/data-table.tsx +13 -1
  141. package/src/components/data-table/date-filter-inputs.tsx +15 -42
  142. package/src/components/data-table/date-popover.tsx +6 -4
  143. package/src/components/data-table/export-actions.tsx +267 -163
  144. package/src/components/data-table/range-focus/atoms.ts +4 -6
  145. package/src/components/data-table/range-focus/use-cell-range-selection.ts +65 -38
  146. package/src/components/data-table/range-focus/use-scroll-into-view.ts +21 -2
  147. package/src/components/data-table/renderers.tsx +16 -7
  148. package/src/components/data-table/row-viewer-panel/__tests__/row-viewer.test.tsx +24 -1
  149. package/src/components/data-table/row-viewer-panel/row-viewer.tsx +4 -4
  150. package/src/components/data-table/schemas.ts +14 -36
  151. package/src/components/data-table/search-highlight.tsx +79 -0
  152. package/src/components/data-table/types.ts +1 -0
  153. package/src/components/data-table/url-detector.tsx +49 -9
  154. package/src/components/data-table/utils.ts +18 -0
  155. package/src/components/datasources/__tests__/column-actions.test.tsx +97 -0
  156. package/src/components/datasources/__tests__/column-preview.test.tsx +98 -5
  157. package/src/components/datasources/__tests__/datasources-interactions.test.tsx +181 -0
  158. package/src/components/datasources/__tests__/table-list.test.tsx +118 -0
  159. package/src/components/datasources/__tests__/utils.test.ts +57 -6
  160. package/src/components/datasources/column-preview.tsx +13 -4
  161. package/src/components/datasources/datasources.tsx +51 -39
  162. package/src/components/datasources/utils.ts +32 -23
  163. package/src/components/debugger/debugger-code.tsx +5 -0
  164. package/src/components/dependency-graph/dependency-graph-tree.tsx +8 -8
  165. package/src/components/dependency-graph/elements.ts +24 -21
  166. package/src/components/dependency-graph/panels.tsx +2 -1
  167. package/src/components/dependency-graph/utils/__tests__/layout.test.ts +18 -11
  168. package/src/components/editor/Output.tsx +9 -2
  169. package/src/components/editor/SortableCell.tsx +1 -3
  170. package/src/components/editor/__tests__/dynamic-favicon.test.tsx +111 -18
  171. package/src/components/editor/__tests__/package-alert.test.tsx +22 -1
  172. package/src/components/editor/actions/__tests__/pair-with-agent-commands.test.ts +80 -252
  173. package/src/components/editor/actions/__tests__/pair-with-agent-modal.test.tsx +210 -34
  174. package/src/components/editor/actions/pair-with-agent-commands.ts +42 -51
  175. package/src/components/editor/actions/pair-with-agent-modal.tsx +100 -37
  176. package/src/components/editor/ai/add-cell-with-ai.tsx +3 -3
  177. package/src/components/editor/ai/ai-completion-editor.tsx +1 -0
  178. package/src/components/editor/alerts/startup-logs-alert.tsx +1 -0
  179. package/src/components/editor/cell/CreateCellButton.tsx +8 -10
  180. package/src/components/editor/cell/DeleteButton.tsx +1 -0
  181. package/src/components/editor/cell/__tests__/useShouldShowInterrupt.test.ts +39 -0
  182. package/src/components/editor/cell/code/__tests__/language-toggle.test.tsx +54 -0
  183. package/src/components/editor/cell/code/cell-editor.tsx +1 -1
  184. package/src/components/editor/cell/code/language-toggle.tsx +8 -7
  185. package/src/components/editor/cell/collapse.tsx +5 -3
  186. package/src/components/editor/cell/useShouldShowInterrupt.ts +2 -12
  187. package/src/components/editor/chrome/panels/__tests__/packages-panel.test.tsx +30 -1
  188. package/src/components/editor/chrome/panels/cache-panel.tsx +1 -0
  189. package/src/components/editor/chrome/panels/error-panel.tsx +1 -0
  190. package/src/components/editor/chrome/panels/outline/__tests__/outline-keyboard.test.tsx +84 -0
  191. package/src/components/editor/chrome/panels/outline/floating-outline.tsx +39 -14
  192. package/src/components/editor/chrome/panels/outline/useActiveOutline.tsx +3 -2
  193. package/src/components/editor/chrome/panels/packages-panel.tsx +4 -7
  194. package/src/components/editor/chrome/panels/secrets-panel.tsx +1 -0
  195. package/src/components/editor/chrome/panels/snippets-panel.tsx +5 -1
  196. package/src/components/editor/chrome/wrapper/__tests__/attachment-status.test.tsx +366 -0
  197. package/src/components/editor/chrome/wrapper/__tests__/pending-ai-cells.test.tsx +58 -1
  198. package/src/components/editor/chrome/wrapper/footer-item.tsx +32 -24
  199. package/src/components/editor/chrome/wrapper/footer-items/attachment-status.tsx +237 -0
  200. package/src/components/editor/chrome/wrapper/footer-items/runtime-settings.tsx +1 -7
  201. package/src/components/editor/chrome/wrapper/footer.tsx +2 -0
  202. package/src/components/editor/chrome/wrapper/pending-ai-cells.tsx +12 -2
  203. package/src/components/editor/chrome/wrapper/storage.ts +1 -1
  204. package/src/components/editor/connections/components.tsx +1 -1
  205. package/src/components/editor/controls/__tests__/command-palette.test.tsx +53 -0
  206. package/src/components/editor/controls/__tests__/keyboard-shortcuts.test.tsx +61 -0
  207. package/src/components/editor/controls/command-palette.tsx +22 -10
  208. package/src/components/editor/controls/keyboard-shortcuts.tsx +14 -5
  209. package/src/components/editor/dynamic-favicon.tsx +21 -40
  210. package/src/components/editor/errors/__tests__/send-error-report-button.test.tsx +537 -0
  211. package/src/components/editor/errors/send-error-report-button.tsx +69 -0
  212. package/src/components/editor/file-tree/__tests__/file-explorer-interactions.test.tsx +6 -0
  213. package/src/components/editor/file-tree/__tests__/file-explorer-navigation.test.tsx +47 -0
  214. package/src/components/editor/file-tree/__tests__/use-file-search.test.tsx +91 -0
  215. package/src/components/editor/file-tree/file-explorer.tsx +45 -8
  216. package/src/components/editor/file-tree/file-name-input.tsx +1 -0
  217. package/src/components/editor/file-tree/file-viewer.tsx +4 -2
  218. package/src/components/editor/file-tree/use-file-search.ts +35 -21
  219. package/src/components/editor/header/status.tsx +28 -5
  220. package/src/components/editor/links/__tests__/cell-link.test.tsx +146 -0
  221. package/src/components/editor/links/cell-link.tsx +14 -5
  222. package/src/components/editor/navigation/focus-utils.ts +4 -4
  223. package/src/components/editor/notebook-banner.tsx +1 -0
  224. package/src/components/editor/notebook-cell.tsx +11 -2
  225. package/src/components/editor/output/MarimoErrorOutput.tsx +21 -5
  226. package/src/components/editor/output/MarimoTracebackOutput.tsx +54 -37
  227. package/src/components/editor/output/__tests__/ansi-reduce.test.ts +18 -0
  228. package/src/components/editor/output/__tests__/traceback.test.tsx +27 -1
  229. package/src/components/editor/output/ansi-reduce.ts +36 -17
  230. package/src/components/editor/output/console/ConsoleOutput.tsx +19 -25
  231. package/src/components/editor/package-alert.tsx +14 -7
  232. package/src/components/editor/renderers/grid-layout/grid-layout.tsx +12 -6
  233. package/src/components/editor/renderers/vertical-layout/sidebar/toggle.tsx +7 -1
  234. package/src/components/home/components.tsx +17 -31
  235. package/src/components/icons/__tests__/large-spinner.test.tsx +39 -0
  236. package/src/components/icons/large-spinner.tsx +3 -14
  237. package/src/components/icons/spinner.tsx +1 -1
  238. package/src/components/mcp/mcp-status-indicator.tsx +1 -1
  239. package/src/components/pages/__tests__/home-page.test.tsx +116 -0
  240. package/src/components/pages/home-page.tsx +164 -91
  241. package/src/components/scratchpad/scratchpad.test.tsx +95 -0
  242. package/src/components/scratchpad/scratchpad.tsx +16 -3
  243. package/src/components/slides/reveal-component.tsx +4 -2
  244. package/src/components/slides/slide-cell-view.tsx +1 -1
  245. package/src/components/slides/slide-form.tsx +1 -0
  246. package/src/components/tracing/tracing-keyboard.test.tsx +85 -0
  247. package/src/components/tracing/tracing.tsx +45 -41
  248. package/src/components/ui/__tests__/draggable-popover.test.tsx +24 -0
  249. package/src/components/ui/__tests__/range-slider.test.tsx +165 -0
  250. package/src/components/ui/alert-dialog.tsx +1 -1
  251. package/src/components/ui/draggable-popover.tsx +24 -2
  252. package/src/components/ui/range-slider.tsx +22 -9
  253. package/src/core/ai/context/providers/datasource.ts +6 -2
  254. package/src/core/ai/tools/base.ts +16 -7
  255. package/src/core/ai/tools/edit-notebook-tool.ts +47 -45
  256. package/src/core/ai/tools/registry.ts +13 -8
  257. package/src/core/ai/tools/sample-tool.ts +6 -7
  258. package/src/core/attachments/__tests__/toast.test.tsx +58 -0
  259. package/src/core/attachments/state.ts +18 -0
  260. package/src/core/attachments/toast.ts +15 -0
  261. package/src/core/cells/__tests__/__snapshots__/cells.test.ts.snap +4 -0
  262. package/src/core/cells/__tests__/cell.test.ts +39 -0
  263. package/src/core/cells/__tests__/cells.test.ts +55 -1
  264. package/src/core/cells/__tests__/collapseConsoleOutputs.test.ts +54 -0
  265. package/src/core/cells/__tests__/error-report.test.ts +139 -0
  266. package/src/core/cells/__tests__/notebook-outline.test.ts +113 -0
  267. package/src/core/cells/__tests__/session.test.ts +167 -37
  268. package/src/core/cells/cell.ts +14 -3
  269. package/src/core/cells/cells.ts +3 -1
  270. package/src/core/cells/error-report.ts +63 -0
  271. package/src/core/cells/pending-delete-service.ts +2 -6
  272. package/src/core/cells/session.ts +29 -2
  273. package/src/core/cells/types.ts +10 -1
  274. package/src/core/codemirror/__tests__/setup.test.ts +29 -29
  275. package/src/core/codemirror/cells/__tests__/extensions.test.ts +15 -0
  276. package/src/core/codemirror/cells/extensions.ts +7 -3
  277. package/src/core/codemirror/keymaps/vim.ts +2 -6
  278. package/src/core/codemirror/language/__tests__/sql.test.ts +22 -20
  279. package/src/core/codemirror/language/extension.ts +8 -8
  280. package/src/core/codemirror/language/languages/markdown.ts +8 -6
  281. package/src/core/codemirror/language/languages/python.ts +16 -10
  282. package/src/core/codemirror/language/languages/sql/sql.ts +9 -7
  283. package/src/core/codemirror/language/panel/panel.tsx +1 -0
  284. package/src/core/codemirror/language/types.ts +7 -7
  285. package/src/core/codemirror/rtc/extension.ts +24 -12
  286. package/src/core/codemirror/rtc/loro/awareness.ts +34 -19
  287. package/src/core/codemirror/rtc/loro/sync.ts +1 -0
  288. package/src/core/codemirror/utils.ts +1 -0
  289. package/src/core/config/pair.ts +5 -3
  290. package/src/core/datasets/__tests__/data-source-discovery.test.ts +4 -4
  291. package/src/core/datasets/data-source-discovery.ts +4 -6
  292. package/src/core/document/__tests__/codemirror.test.ts +485 -0
  293. package/src/core/document/__tests__/draft.test.ts +322 -0
  294. package/src/core/document/__tests__/fixtures.ts +92 -0
  295. package/src/core/document/__tests__/hooks.test.tsx +386 -0
  296. package/src/core/document/__tests__/lifecycle-scenarios.test.ts +61 -0
  297. package/src/core/document/__tests__/model.test.ts +191 -0
  298. package/src/core/document/__tests__/protocol-fixtures.ts +38 -0
  299. package/src/core/document/__tests__/recovery-scenarios.test.ts +230 -0
  300. package/src/core/document/__tests__/scenario-fixture.ts +43 -0
  301. package/src/core/document/__tests__/scenarios.test.ts +205 -0
  302. package/src/core/document/__tests__/state.test.ts +438 -0
  303. package/src/core/document/__tests__/submission.test.ts +203 -0
  304. package/src/core/document/__tests__/test-host.test.ts +92 -0
  305. package/src/core/document/__tests__/test-host.ts +247 -0
  306. package/src/core/document/__tests__/test-notebook.ts +149 -0
  307. package/src/core/document/__tests__/user.ts +61 -0
  308. package/src/core/document/codemirror.ts +311 -0
  309. package/src/core/document/draft.ts +472 -0
  310. package/src/core/document/hooks.tsx +118 -0
  311. package/src/core/document/index.ts +15 -0
  312. package/src/core/document/model.ts +55 -0
  313. package/src/core/document/select.ts +41 -0
  314. package/src/core/document/state.ts +374 -0
  315. package/src/core/document/sync.ts +369 -0
  316. package/src/core/edit-app.tsx +2 -2
  317. package/src/core/host/AGENTS.md +12 -0
  318. package/src/core/host/__tests__/attachments.test.ts +56 -0
  319. package/src/core/host/__tests__/document.test.ts +126 -0
  320. package/src/core/host/__tests__/fixtures.ts +79 -0
  321. package/src/core/host/__tests__/replica.test.ts +550 -0
  322. package/src/core/host/__tests__/static.test.ts +175 -0
  323. package/src/core/host/__tests__/wasm.test.ts +166 -0
  324. package/src/core/host/backend.ts +19 -0
  325. package/src/core/host/connection.ts +42 -0
  326. package/src/core/host/index.ts +14 -0
  327. package/src/core/host/replica.ts +286 -0
  328. package/src/core/host/resources/attachments.ts +22 -0
  329. package/src/core/host/resources/document.ts +101 -0
  330. package/src/core/host/static.ts +77 -0
  331. package/src/core/host/wasm.ts +97 -0
  332. package/src/core/hotkeys/actions.ts +2 -4
  333. package/src/core/islands/__tests__/bootstrap.test.ts +17 -17
  334. package/src/core/islands/__tests__/bridge.test.ts +31 -26
  335. package/src/core/islands/bootstrap.ts +22 -51
  336. package/src/core/islands/bridge.ts +31 -20
  337. package/src/core/islands/components/__tests__/IslandControls.test.tsx +7 -5
  338. package/src/core/islands/worker/__tests__/controller.test.ts +62 -4
  339. package/src/core/islands/worker/controller.ts +4 -10
  340. package/src/core/islands/worker/worker.tsx +33 -33
  341. package/src/core/kernel/__tests__/RuntimeState.test.ts +1 -1
  342. package/src/core/network/connection.ts +4 -2
  343. package/src/core/network/useConnectionNotice.ts +8 -2
  344. package/src/core/run-app.tsx +2 -2
  345. package/src/core/runtime/__tests__/createWsUrl.test.ts +77 -7
  346. package/src/core/runtime/__tests__/runtime.test.ts +33 -15
  347. package/src/core/runtime/runtime.ts +39 -30
  348. package/src/core/saving/save-component.tsx +12 -3
  349. package/src/core/state/__tests__/jotai.test.tsx +108 -0
  350. package/src/core/state/jotai.ts +1 -1
  351. package/src/core/static/__tests__/files.test.ts +38 -10
  352. package/src/core/static/files.ts +2 -0
  353. package/src/core/wasm/__tests__/bridge.test.ts +213 -50
  354. package/src/core/wasm/__tests__/worker.test.ts +187 -0
  355. package/src/core/wasm/bridge.ts +81 -52
  356. package/src/core/wasm/rpc.ts +15 -3
  357. package/src/core/wasm/store.ts +3 -3
  358. package/src/core/wasm/worker/bootstrap.ts +55 -51
  359. package/src/core/wasm/worker/getMarimoWheel.ts +1 -1
  360. package/src/core/wasm/worker/save-worker.ts +9 -10
  361. package/src/core/wasm/worker/types.ts +29 -18
  362. package/src/core/wasm/worker/worker.ts +97 -44
  363. package/src/core/websocket/__tests__/backend.test.ts +235 -0
  364. package/src/core/websocket/__tests__/{useMarimoKernelConnection.test.ts → connection-state.test.ts} +15 -29
  365. package/src/core/websocket/__tests__/useNotebookReplica.hook.test.tsx +141 -0
  366. package/src/core/websocket/__tests__/{useMarimoKernelConnection.hook.test.tsx → useNotebookSession.hook.test.tsx} +197 -184
  367. package/src/core/websocket/backend.ts +129 -0
  368. package/src/core/websocket/connection-state.ts +60 -0
  369. package/src/core/websocket/state.ts +7 -0
  370. package/src/core/websocket/transports/__tests__/notebook.test.ts +405 -0
  371. package/src/core/websocket/transports/notebook.ts +159 -0
  372. package/src/core/websocket/types.ts +9 -39
  373. package/src/core/websocket/useNotebookReplica.ts +69 -0
  374. package/src/core/websocket/{useMarimoKernelConnection.tsx → useNotebookSession.tsx} +63 -228
  375. package/src/css/globals.css +5 -0
  376. package/src/hooks/__tests__/useAsyncData.test.tsx +148 -0
  377. package/src/hooks/__tests__/useDebounce.test.tsx +51 -0
  378. package/src/hooks/__tests__/useDeepCompareMemoize.test.tsx +39 -0
  379. package/src/hooks/__tests__/useDelayElapsed.test.tsx +28 -0
  380. package/src/hooks/__tests__/useInternalStateWithSync.test.tsx +20 -0
  381. package/src/hooks/__tests__/useScript.test.tsx +77 -0
  382. package/src/hooks/__tests__/useStateForKey.test.tsx +257 -0
  383. package/src/hooks/useAsyncData.ts +3 -3
  384. package/src/hooks/useDataSourceDiscovery.ts +6 -4
  385. package/src/hooks/useDebounce.ts +6 -10
  386. package/src/hooks/useDeepCompareMemoize.ts +1 -1
  387. package/src/hooks/useDelayElapsed.ts +14 -10
  388. package/src/hooks/useElapsedTime.ts +3 -3
  389. package/src/hooks/useEventListener.ts +1 -2
  390. package/src/hooks/useInputHistory.ts +4 -7
  391. package/src/hooks/useInternalStateWithSync.ts +6 -6
  392. package/src/hooks/useResizeObserver.ts +4 -7
  393. package/src/hooks/useScript.ts +67 -70
  394. package/src/hooks/useStateForKey.ts +93 -0
  395. package/src/mount.tsx +3 -3
  396. package/src/plugins/__tests__/plugin-object-schemas.test.ts +104 -0
  397. package/src/plugins/core/registerReactComponent.tsx +1 -1
  398. package/src/plugins/impl/CodeEditorPlugin.tsx +1 -1
  399. package/src/plugins/impl/DataEditorPlugin.tsx +1 -1
  400. package/src/plugins/impl/DataTablePlugin.tsx +29 -33
  401. package/src/plugins/impl/DropdownPlugin.tsx +2 -6
  402. package/src/plugins/impl/FileBrowserPlugin.tsx +4 -16
  403. package/src/plugins/impl/FormPlugin.tsx +1 -1
  404. package/src/plugins/impl/RangeSliderPlugin.tsx +16 -2
  405. package/src/plugins/impl/RefreshPlugin.tsx +1 -0
  406. package/src/plugins/impl/SliderPlugin.tsx +6 -8
  407. package/src/plugins/impl/__tests__/DataTablePlugin.test.tsx +201 -1
  408. package/src/plugins/impl/__tests__/FileBrowserPlugin.test.tsx +45 -0
  409. package/src/plugins/impl/__tests__/RangeSliderPlugin.test.tsx +109 -0
  410. package/src/plugins/impl/__tests__/SliderPlugin.test.tsx +24 -3
  411. package/src/plugins/impl/anywidget/__tests__/registry.test.ts +2 -0
  412. package/src/plugins/impl/anywidget/__tests__/widget-binding.test.ts +241 -2
  413. package/src/plugins/impl/anywidget/runtime.ts +21 -9
  414. package/src/plugins/impl/anywidget/widget-binding.ts +160 -82
  415. package/src/plugins/impl/chat/__tests__/chat-prompts.test.tsx +93 -0
  416. package/src/plugins/impl/chat/chat-ui.tsx +14 -11
  417. package/src/plugins/impl/code/any-language-editor.tsx +2 -2
  418. package/src/plugins/impl/data-editor/glide-data-editor.tsx +8 -5
  419. package/src/plugins/impl/data-editor/glide-utils.ts +3 -1
  420. package/src/plugins/impl/data-explorer/ConnectedDataExplorerComponent.tsx +1 -1
  421. package/src/plugins/impl/data-explorer/components/column-summary.tsx +4 -2
  422. package/src/plugins/impl/data-explorer/state/reducer.ts +1 -1
  423. package/src/plugins/impl/data-frames/DataFramePlugin.tsx +1 -2
  424. package/src/plugins/impl/data-frames/__tests__/sidebar.test.tsx +160 -0
  425. package/src/plugins/impl/data-frames/forms/__tests__/__snapshots__/form.test.tsx.snap +66 -66
  426. package/src/plugins/impl/data-frames/panel.tsx +43 -16
  427. package/src/plugins/impl/mpl-interactive/MplInteractivePlugin.tsx +5 -3
  428. package/src/plugins/impl/panel/PanelPlugin.tsx +16 -17
  429. package/src/plugins/impl/panel/__tests__/utils.test.ts +39 -1
  430. package/src/plugins/impl/panel/utils.ts +17 -0
  431. package/src/plugins/impl/plotly/PlotlyPlugin.tsx +2 -5
  432. package/src/plugins/impl/plotly/selection.ts +25 -19
  433. package/src/plugins/impl/vega/VegaPlugin.tsx +2 -3
  434. package/src/plugins/impl/vega/make-selectable.ts +4 -7
  435. package/src/plugins/layout/RoutesPlugin.tsx +1 -1
  436. package/src/stories/__tests__/editor-story.test.tsx +33 -0
  437. package/src/stories/button.stories.tsx +1 -0
  438. package/src/stories/editor.stories.tsx +24 -17
  439. package/src/stories/form-wrapper.stories.tsx +2 -2
  440. package/src/stories/select.stories.tsx +2 -2
  441. package/src/stories/switchable-multi-select.stories.tsx +1 -1
  442. package/src/utils/__tests__/arrays.test.ts +35 -0
  443. package/src/utils/__tests__/batch-requests.test.ts +3 -3
  444. package/src/utils/__tests__/dates.test.ts +116 -0
  445. package/src/utils/__tests__/numbers.test.ts +105 -1
  446. package/src/utils/__tests__/objects.test.ts +21 -0
  447. package/src/utils/arrays.ts +10 -0
  448. package/src/utils/blob.ts +1 -1
  449. package/src/utils/dates.ts +94 -0
  450. package/src/utils/numbers.ts +79 -18
  451. package/src/utils/objects.ts +3 -7
  452. package/src/utils/once.ts +19 -19
  453. package/src/utils/tracer.ts +9 -5
  454. package/src/utils/zod-utils.ts +1 -3
  455. package/dist/any-language-editor-B9REGlD9.js +0 -76
  456. package/dist/assets/__vite-browser-external-BXYkiFsk.js +0 -1
  457. package/dist/assets/worker-HPY9fbhz.js +0 -114
  458. package/dist/error-entries-CzoYkIQZ.js +0 -56
  459. package/dist/mermaid-HWGCJPDP-ByCsZnYF.js +0 -2
  460. package/dist/precisionRound-DMIVQrt2.js +0 -97
  461. package/src/core/state/__tests__/jotai.test.ts +0 -25
  462. package/src/core/wasm/worker/message-buffer.ts +0 -33
  463. package/src/core/websocket/__tests__/useWebSocket.test.ts +0 -49
  464. package/src/core/websocket/transports/__tests__/basic.test.ts +0 -275
  465. package/src/core/websocket/transports/__tests__/sse.test.ts +0 -338
  466. package/src/core/websocket/transports/__tests__/transport.test.ts +0 -308
  467. package/src/core/websocket/transports/__tests__/ws.test.ts +0 -125
  468. package/src/core/websocket/transports/basic.ts +0 -102
  469. package/src/core/websocket/transports/sse.ts +0 -308
  470. package/src/core/websocket/transports/transport.ts +0 -61
  471. package/src/core/websocket/transports/ws.ts +0 -98
  472. package/src/core/websocket/useWebSocket.tsx +0 -88
@@ -46,10 +46,17 @@ describe("notebookStateFromSession", () => {
46
46
 
47
47
  const createNotebookCell = (
48
48
  id: string,
49
- code: string | null = null,
50
- name: string | null = null,
51
- config: NotebookCell["config"] | null = null,
52
- code_hash: string | null = null,
49
+ {
50
+ code = null,
51
+ name = null,
52
+ config = null,
53
+ code_hash = null,
54
+ }: {
55
+ code?: string | null;
56
+ name?: string | null;
57
+ config?: NotebookCell["config"] | null;
58
+ code_hash?: string | null;
59
+ } = {},
53
60
  ): NotebookCell => ({
54
61
  id,
55
62
  code,
@@ -87,7 +94,7 @@ describe("notebookStateFromSession", () => {
87
94
 
88
95
  it("logs error when session and notebook have different cells", () => {
89
96
  const session = createSession([createSessionCell("cell-1")]);
90
- const notebook = createNotebook([createNotebookCell("cell-2")]);
97
+ const notebook = createNotebook([createNotebookCell("cell-2", {})]);
91
98
 
92
99
  const result = notebookStateFromSession(session, notebook);
93
100
 
@@ -174,8 +181,11 @@ describe("notebookStateFromSession", () => {
174
181
  channel: "marimo-error",
175
182
  data: [
176
183
  {
177
- type: "unknown",
184
+ type: "exception",
185
+ exception_type: "ValueError",
178
186
  msg: "Something went wrong",
187
+ raising_cell: null,
188
+ traceback: "Traceback line 1",
179
189
  },
180
190
  ],
181
191
  mimetype: "application/vnd.marimo+error",
@@ -183,6 +193,52 @@ describe("notebookStateFromSession", () => {
183
193
  });
184
194
  });
185
195
 
196
+ it("restores matching code from the session", () => {
197
+ const code = "raise ValueError('cached failure')";
198
+ const session = createSession([
199
+ createSessionCell(
200
+ "cell-1",
201
+ [
202
+ {
203
+ type: "error",
204
+ ename: "ValueError",
205
+ evalue: "cached failure",
206
+ traceback: ["Traceback\n", "ValueError: cached failure"],
207
+ code,
208
+ },
209
+ ],
210
+ [
211
+ {
212
+ type: "stream",
213
+ name: "stderr",
214
+ text: "ValueError: cached <failure>",
215
+ mimetype: "application/vnd.marimo+traceback",
216
+ traceback_format: "text",
217
+ code,
218
+ },
219
+ ],
220
+ ),
221
+ ]);
222
+ const state = notebookStateFromSession(session, null);
223
+ invariant(state, "state is null");
224
+ expect(state.cellRuntime[CELL_1].output).toMatchObject({
225
+ code,
226
+ data: [
227
+ {
228
+ type: "exception",
229
+ exception_type: "ValueError",
230
+ msg: "cached failure",
231
+ traceback: "Traceback\nValueError: cached failure",
232
+ },
233
+ ],
234
+ });
235
+ expect(state.cellRuntime[CELL_1].consoleOutputs[0].code).toBe(code);
236
+ expect(state.cellRuntime[CELL_1].consoleOutputs[0]).toMatchObject({
237
+ traceback_format: "text",
238
+ data: "ValueError: cached <failure>",
239
+ });
240
+ });
241
+
186
242
  it("handles data output in session cell", () => {
187
243
  const dataOutput = {
188
244
  type: "data" as const,
@@ -279,7 +335,10 @@ describe("notebookStateFromSession", () => {
279
335
  describe("notebook only scenarios", () => {
280
336
  it("creates state from notebook with single cell", () => {
281
337
  const notebook = createNotebook([
282
- createNotebookCell("cell-1", "print('hello')", "my_cell"),
338
+ createNotebookCell("cell-1", {
339
+ code: "print('hello')",
340
+ name: "my_cell",
341
+ }),
283
342
  ]);
284
343
  const result = notebookStateFromSession(null, notebook);
285
344
 
@@ -307,11 +366,15 @@ describe("notebookStateFromSession", () => {
307
366
 
308
367
  it("creates state from notebook with custom config", () => {
309
368
  const notebook = createNotebook([
310
- createNotebookCell("cell-1", "code", "name", {
311
- hide_code: true,
312
- disabled: true,
313
- column: 1,
314
- expand_output: true,
369
+ createNotebookCell("cell-1", {
370
+ code: "code",
371
+ name: "name",
372
+ config: {
373
+ hide_code: true,
374
+ disabled: true,
375
+ column: 1,
376
+ expand_output: true,
377
+ },
315
378
  }),
316
379
  ]);
317
380
  const result = notebookStateFromSession(null, notebook);
@@ -415,7 +478,10 @@ describe("notebookStateFromSession", () => {
415
478
  ),
416
479
  ]);
417
480
  const notebook = createNotebook([
418
- createNotebookCell("cell-1", "print('hello')", "my_cell"),
481
+ createNotebookCell("cell-1", {
482
+ code: "print('hello')",
483
+ name: "my_cell",
484
+ }),
419
485
  ]);
420
486
  const result = notebookStateFromSession(session, notebook);
421
487
 
@@ -446,8 +512,8 @@ describe("notebookStateFromSession", () => {
446
512
  createSessionCell("cell-2"),
447
513
  ]);
448
514
  const notebook = createNotebook([
449
- createNotebookCell("cell-2"),
450
- createNotebookCell("cell-1"),
515
+ createNotebookCell("cell-2", {}),
516
+ createNotebookCell("cell-1", {}),
451
517
  ]);
452
518
 
453
519
  const result = notebookStateFromSession(session, notebook);
@@ -465,8 +531,8 @@ describe("notebookStateFromSession", () => {
465
531
  createSessionCell("cell-2"),
466
532
  ]);
467
533
  const notebook = createNotebook([
468
- createNotebookCell("cell-1"),
469
- createNotebookCell("cell-2"),
534
+ createNotebookCell("cell-1", {}),
535
+ createNotebookCell("cell-2", {}),
470
536
  ]);
471
537
 
472
538
  const result = notebookStateFromSession(session, notebook);
@@ -620,12 +686,42 @@ describe("notebookStateFromSession", () => {
620
686
  };
621
687
  // Create notebook cells with code values 'a' through 'f'
622
688
  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),
689
+ createNotebookCell("cell-a", {
690
+ code: "a",
691
+ name: null,
692
+ config: null,
693
+ code_hash: hashes.a,
694
+ }),
695
+ createNotebookCell("cell-b", {
696
+ code: "b",
697
+ name: null,
698
+ config: null,
699
+ code_hash: hashes.b,
700
+ }),
701
+ createNotebookCell("cell-c", {
702
+ code: "c",
703
+ name: null,
704
+ config: null,
705
+ code_hash: hashes.c,
706
+ }),
707
+ createNotebookCell("cell-d", {
708
+ code: "d",
709
+ name: null,
710
+ config: null,
711
+ code_hash: hashes.d,
712
+ }),
713
+ createNotebookCell("cell-e", {
714
+ code: "e",
715
+ name: null,
716
+ config: null,
717
+ code_hash: hashes.e,
718
+ }),
719
+ createNotebookCell("cell-f", {
720
+ code: "f",
721
+ name: null,
722
+ config: null,
723
+ code_hash: hashes.f,
724
+ }),
629
725
  ];
630
726
  // Create session cells with matching code_hashes
631
727
  const sessionCells = [
@@ -738,11 +834,36 @@ describe("notebookStateFromSession", () => {
738
834
 
739
835
  // Notebook has cells with code 'a', 'c', 'z', 'e', 'g'
740
836
  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),
837
+ createNotebookCell("cell-a", {
838
+ code: "a",
839
+ name: null,
840
+ config: null,
841
+ code_hash: hashes.a,
842
+ }),
843
+ createNotebookCell("cell-c", {
844
+ code: "c",
845
+ name: null,
846
+ config: null,
847
+ code_hash: hashes.c,
848
+ }),
849
+ createNotebookCell("cell-z", {
850
+ code: "z",
851
+ name: null,
852
+ config: null,
853
+ code_hash: hashes.z,
854
+ }),
855
+ createNotebookCell("cell-e", {
856
+ code: "e",
857
+ name: null,
858
+ config: null,
859
+ code_hash: hashes.e,
860
+ }),
861
+ createNotebookCell("cell-g", {
862
+ code: "g",
863
+ name: null,
864
+ config: null,
865
+ code_hash: hashes.g,
866
+ }),
746
867
  ];
747
868
 
748
869
  const session = createSession(sessionCells);
@@ -859,15 +980,24 @@ describe("notebookStateFromSession", () => {
859
980
 
860
981
  // Notebook has cells: cell-1 (1 / 0, no hash), cell-2 (mo.md("Hello"), hash=moMd), cell-3 (slider, hash=slider)
861
982
  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
- ),
983
+ createNotebookCell("cell-1", {
984
+ code: "1 / 0",
985
+ name: null,
986
+ config: null,
987
+ code_hash: null,
988
+ }), // no hash
989
+ createNotebookCell("cell-2", {
990
+ code: 'mo.md("Hello")',
991
+ name: null,
992
+ config: null,
993
+ code_hash: hashes.moMd,
994
+ }),
995
+ createNotebookCell("cell-3", {
996
+ code: "x = mo.ui.slider(0, 10)",
997
+ name: null,
998
+ config: null,
999
+ code_hash: hashes.slider,
1000
+ }),
871
1001
  ];
872
1002
 
873
1003
  const session = createSession(sessionCells);
@@ -7,7 +7,12 @@ import { parseOutline } from "../dom/outline";
7
7
  import type { CellMessage, OutputMessage } from "../kernel/messages";
8
8
  import type { RuntimeState } from "../network/types";
9
9
  import { collapseConsoleOutputs } from "./collapseConsoleOutputs";
10
- import type { CellRuntimeState } from "./types";
10
+ import type { CellRuntimeState, ConsoleOutputMessage } from "./types";
11
+
12
+ // Ids increase with position, so the last output holds the maximum.
13
+ function nextConsoleOutputId(outputs: ConsoleOutputMessage[]): number {
14
+ return (outputs.at(-1)?.id ?? 0) + 1;
15
+ }
11
16
 
12
17
  export function transitionCell(
13
18
  cell: CellRuntimeState,
@@ -133,6 +138,7 @@ export function transitionCell(
133
138
  mimetype: output.mimetype,
134
139
  data: output.data,
135
140
  timestamp: output.timestamp,
141
+ id: output.id,
136
142
  response: output.response ?? "",
137
143
  };
138
144
  }
@@ -146,8 +152,13 @@ export function transitionCell(
146
152
  // messageConsole is an output that needs to be appended to the
147
153
  // existing console outputs.
148
154
  consoleOutputs = Array.isArray(messageConsole)
149
- ? collapseConsoleOutputs(messageConsole)
150
- : collapseConsoleOutputs([...consoleOutputs, messageConsole]);
155
+ ? collapseConsoleOutputs(
156
+ messageConsole.map((output, i) => ({ ...output, id: i + 1 })),
157
+ )
158
+ : collapseConsoleOutputs([
159
+ ...consoleOutputs,
160
+ { ...messageConsole, id: nextConsoleOutputId(consoleOutputs) },
161
+ ]);
151
162
  }
152
163
  nextCell.consoleOutputs = consoleOutputs;
153
164
  // Derive outline from output
@@ -1114,6 +1114,7 @@ const {
1114
1114
  mimetype: stdinOutput.mimetype,
1115
1115
  data: stdinOutput.data,
1116
1116
  timestamp: stdinOutput.timestamp,
1117
+ id: stdinOutput.id,
1117
1118
  // An empty response resolves the prompt without retaining the secret.
1118
1119
  response: stdinOutput.mimetype === "text/password" ? "" : response,
1119
1120
  };
@@ -1761,7 +1762,8 @@ export const cellErrorsAtom = atom((get) => {
1761
1762
  });
1762
1763
 
1763
1764
  export const notebookOutline = atom((get) => {
1764
- const { cellIds, cellRuntime } = get(notebookAtom);
1765
+ const cellIds = get(cellIdsAtom);
1766
+ const cellRuntime = get(cellsRuntimeAtom);
1765
1767
  const outlines = cellIds.inOrderIds.map(
1766
1768
  (cellId) => cellRuntime[cellId].outline,
1767
1769
  );
@@ -0,0 +1,63 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import { describeError } from "@/core/errors/error-entries";
4
+ import type { MarimoError } from "@/core/kernel/messages";
5
+ import { sanitizeHtml } from "@/plugins/core/sanitize-html";
6
+ import { parseHtmlContent } from "@/utils/dom";
7
+ import type { CellId } from "./ids";
8
+
9
+ export interface CellOutputMessage<Output> {
10
+ type: "cell-output";
11
+ cell_id: CellId;
12
+ code?: string;
13
+ output: Output;
14
+ }
15
+
16
+ export interface ErrorMessageOutput {
17
+ type: "error";
18
+ instructions: string;
19
+ message: string;
20
+ traceback?: string;
21
+ }
22
+
23
+ export const ERROR_MESSAGE_INSTRUCTIONS = "Fix this notebook error.";
24
+
25
+ export function buildErrorReport(
26
+ cellId: CellId,
27
+ evidence: { code?: string } & (
28
+ | { errors: MarimoError[] }
29
+ | { traceback: string; tracebackFormat: "html" | "text" }
30
+ ),
31
+ ): CellOutputMessage<ErrorMessageOutput> {
32
+ let message: string;
33
+ let traceback: string;
34
+ if ("errors" in evidence) {
35
+ message = evidence.errors.map(describeError).join("\n");
36
+ traceback = evidence.errors
37
+ .flatMap((error) =>
38
+ "traceback" in error && error.traceback
39
+ ? [parseHtmlContent(sanitizeHtml(error.traceback))]
40
+ : [],
41
+ )
42
+ .join("\n\n");
43
+ } else {
44
+ traceback =
45
+ evidence.tracebackFormat === "html"
46
+ ? parseHtmlContent(sanitizeHtml(evidence.traceback))
47
+ : evidence.traceback;
48
+ message = traceback.split("\n").findLast((line) => line.length > 0) ?? "";
49
+ }
50
+
51
+ // Put repair intent before evidence so it survives prefix truncation.
52
+ return {
53
+ type: "cell-output",
54
+ cell_id: cellId,
55
+ output: {
56
+ type: "error",
57
+ instructions: ERROR_MESSAGE_INSTRUCTIONS,
58
+ message,
59
+ ...(traceback ? { traceback } : {}),
60
+ },
61
+ ...(evidence.code === undefined ? {} : { code: evidence.code }),
62
+ };
63
+ }
@@ -134,12 +134,8 @@ export function usePendingDeleteService() {
134
134
  submit({ cellIds, deleteCell, deleteManyCells, store });
135
135
  },
136
136
  clear,
137
- get idle() {
138
- return entries.size === 0;
139
- },
140
- get shouldConfirmDelete() {
141
- return entries.size > 1;
142
- },
137
+ idle: entries.size === 0,
138
+ shouldConfirmDelete: entries.size > 1,
143
139
  };
144
140
  }
145
141
 
@@ -56,7 +56,7 @@ function mergeSessionAndNotebookCells(
56
56
  return {
57
57
  cellIds,
58
58
  sessionCellData: new Map(
59
- cellIds.map((id, idx) => [id, null] as [CellId, SessionCell | null]),
59
+ cellIds.map((id) => [id, null] as [CellId, SessionCell | null]),
60
60
  ),
61
61
  notebookCellData: new Map(
62
62
  cellIds.map(
@@ -206,8 +206,20 @@ function createCellRuntimeFromSession(
206
206
  channel: "marimo-error",
207
207
  data: [
208
208
  {
209
- type: "unknown",
209
+ type: "exception",
210
+ exception_type: primaryOutput.ename,
210
211
  msg: primaryOutput.evalue,
212
+ raising_cell: null,
213
+ traceback:
214
+ primaryOutput.traceback.length === 0
215
+ ? null
216
+ : primaryOutput.traceback
217
+ .map((line, index, lines) =>
218
+ index < lines.length - 1 && !line.endsWith("\n")
219
+ ? `${line}\n`
220
+ : line,
221
+ )
222
+ .join(""),
211
223
  },
212
224
  ],
213
225
  mimetype: "application/vnd.marimo+error",
@@ -223,6 +235,9 @@ function createCellRuntimeFromSession(
223
235
  timestamp: DEFAULT_TIMESTAMP,
224
236
  };
225
237
  }
238
+ if (runtimeState.output && primaryOutput.code !== undefined) {
239
+ runtimeState.output.code = primaryOutput.code;
240
+ }
226
241
  }
227
242
 
228
243
  const consoleOutputs = sessionCell.console || [];
@@ -237,7 +252,13 @@ function createCellRuntimeFromSession(
237
252
  channel: "media",
238
253
  data: consoleOutput.data,
239
254
  mimetype: consoleOutput.mimetype,
255
+ ...(consoleOutput.traceback_format === undefined
256
+ ? {}
257
+ : { traceback_format: consoleOutput.traceback_format }),
240
258
  timestamp: DEFAULT_TIMESTAMP,
259
+ ...(consoleOutput.code === undefined
260
+ ? {}
261
+ : { code: consoleOutput.code }),
241
262
  };
242
263
  }
243
264
  // Handle StreamOutput (type: "stream")
@@ -245,7 +266,13 @@ function createCellRuntimeFromSession(
245
266
  channel: consoleOutput.name === "stderr" ? "stderr" : "stdout",
246
267
  data: consoleOutput.text,
247
268
  mimetype: consoleOutput.mimetype ?? "text/plain",
269
+ ...(consoleOutput.traceback_format === undefined
270
+ ? {}
271
+ : { traceback_format: consoleOutput.traceback_format }),
248
272
  timestamp: DEFAULT_TIMESTAMP,
273
+ ...(consoleOutput.code === undefined
274
+ ? {}
275
+ : { code: consoleOutput.code }),
249
276
  };
250
277
  }),
251
278
  };
@@ -95,7 +95,7 @@ export interface CellRuntimeState {
95
95
  /** TOC outline */
96
96
  outline: Outline | null;
97
97
  /** messages encoding the cell's console outputs. */
98
- consoleOutputs: WithResponse<OutputMessage>[];
98
+ consoleOutputs: ConsoleOutputMessage[];
99
99
  /** current status of the cell */
100
100
  status: RuntimeState;
101
101
  /** whether the cell has stale inputs*/
@@ -130,3 +130,12 @@ export type WithResponse<T> = T & {
130
130
  */
131
131
  response?: string;
132
132
  };
133
+
134
+ /**
135
+ * A console output as held by the frontend. The id is assigned when the
136
+ * output arrives and never changes, so it can identify the output while
137
+ * neighboring outputs collapse, truncate, or receive a stdin response.
138
+ */
139
+ export type ConsoleOutputMessage = WithResponse<OutputMessage> & {
140
+ id?: number;
141
+ };
@@ -100,7 +100,7 @@ function getDuplicateKeymaps(state: EditorState) {
100
100
  (keymap) => keymap,
101
101
  );
102
102
  const duplicates = Objects.fromEntries(
103
- Object.entries(groupBy).filter(([key, value]) => value.length > 1),
103
+ Object.entries(groupBy).filter(([_key, value]) => value.length > 1),
104
104
  );
105
105
  return duplicates;
106
106
  }
@@ -198,22 +198,22 @@ test("go to definition falls through to lower-priority LSP keymap", () => {
198
198
  test("placeholder adds another extension", () => {
199
199
  const opts = getOpts();
200
200
  const withAI = new PythonLanguageAdapter()
201
- .getExtension(
202
- opts.cellId,
203
- opts.completionConfig,
204
- opts.hotkeys,
205
- "marimo-import",
206
- opts.lspConfig,
207
- )
201
+ .getExtension({
202
+ cellId: opts.cellId,
203
+ completionConfig: opts.completionConfig,
204
+ hotkeys: opts.hotkeys,
205
+ placeholderType: "marimo-import",
206
+ lspConfig: opts.lspConfig,
207
+ })
208
208
  .flat();
209
209
  const withoutAI = new PythonLanguageAdapter()
210
- .getExtension(
211
- opts.cellId,
212
- opts.completionConfig,
213
- opts.hotkeys,
214
- "none",
215
- opts.lspConfig,
216
- )
210
+ .getExtension({
211
+ cellId: opts.cellId,
212
+ completionConfig: opts.completionConfig,
213
+ hotkeys: opts.hotkeys,
214
+ placeholderType: "none",
215
+ lspConfig: opts.lspConfig,
216
+ })
217
217
  .flat();
218
218
  expect(withAI.length - 1).toBe(withoutAI.length);
219
219
  });
@@ -221,22 +221,22 @@ test("placeholder adds another extension", () => {
221
221
  test("ai adds more extensions", () => {
222
222
  const opts = getOpts();
223
223
  const withAI = new PythonLanguageAdapter()
224
- .getExtension(
225
- opts.cellId,
226
- opts.completionConfig,
227
- opts.hotkeys,
228
- "ai",
229
- opts.lspConfig,
230
- )
224
+ .getExtension({
225
+ cellId: opts.cellId,
226
+ completionConfig: opts.completionConfig,
227
+ hotkeys: opts.hotkeys,
228
+ placeholderType: "ai",
229
+ lspConfig: opts.lspConfig,
230
+ })
231
231
  .flat();
232
232
  const withoutAI = new PythonLanguageAdapter()
233
- .getExtension(
234
- opts.cellId,
235
- opts.completionConfig,
236
- opts.hotkeys,
237
- "none",
238
- opts.lspConfig,
239
- )
233
+ .getExtension({
234
+ cellId: opts.cellId,
235
+ completionConfig: opts.completionConfig,
236
+ hotkeys: opts.hotkeys,
237
+ placeholderType: "none",
238
+ lspConfig: opts.lspConfig,
239
+ })
240
240
  .flat();
241
241
  expect(withAI.length - 2).toBe(withoutAI.length);
242
242
  });
@@ -68,6 +68,21 @@ describe("shouldAutorunMarkdownUpdate", () => {
68
68
  ).toBe(false);
69
69
  });
70
70
 
71
+ it("ignores remote transactions while focused", () => {
72
+ const transaction = createTransaction({
73
+ changes: { from: 0, insert: "#" },
74
+ annotations: [Transaction.remote.of(true)],
75
+ });
76
+
77
+ expect(
78
+ shouldAutorunMarkdownUpdate({
79
+ docChanged: transaction.docChanged,
80
+ transactions: [transaction],
81
+ hasFocus: true,
82
+ }),
83
+ ).toBe(false);
84
+ });
85
+
71
86
  it("ignores programmatic doc changes without a user event", () => {
72
87
  const transaction = createTransaction({
73
88
  changes: { from: 0, insert: "#" },
@@ -1,7 +1,7 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
3
  import { closeCompletion, completionStatus } from "@codemirror/autocomplete";
4
- import { type Extension, Prec } from "@codemirror/state";
4
+ import { type Extension, Prec, Transaction } from "@codemirror/state";
5
5
  import {
6
6
  EditorView,
7
7
  type KeyBinding,
@@ -382,8 +382,12 @@ function shouldAutorunMarkdownUpdate({
382
382
  }
383
383
 
384
384
  return transactions.some((tr) => {
385
- // Ignore RTC sync changes to avoid duplicate runs from remote edits.
386
- if (tr.annotation(loroSyncAnnotation) !== undefined) {
385
+ // Ignore remote changes to avoid duplicate runs. The client that made the
386
+ // edit runs it.
387
+ if (
388
+ tr.annotation(Transaction.remote) ||
389
+ tr.annotation(loroSyncAnnotation) !== undefined
390
+ ) {
387
391
  return false;
388
392
  }
389
393
 
@@ -369,7 +369,7 @@ class CodeMirrorVimSync {
369
369
  // We use onIdle to keep the focused editor snappy
370
370
  onIdle(() => {
371
371
  if (!skipBroadcast) {
372
- this.broadcastModeChange(instance, e.mode, e.subMode);
372
+ this.broadcastModeChange(instance, e.mode);
373
373
  }
374
374
  this.isBroadcasting = false;
375
375
  });
@@ -380,11 +380,7 @@ class CodeMirrorVimSync {
380
380
  this.instances.delete(instance);
381
381
  }
382
382
 
383
- public broadcastModeChange(
384
- originInstance: EditorView,
385
- mode: string,
386
- subMode?: string,
387
- ) {
383
+ public broadcastModeChange(originInstance: EditorView, mode: string) {
388
384
  invariant(
389
385
  "exitInsertMode" in Vim,
390
386
  "Vim does not have an exitInsertMode method",