@marimo-team/islands 0.25.3-dev14 → 0.25.3-dev140
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.
- package/dist/{ConnectedDataExplorerComponent-CNMliVzw.js → ConnectedDataExplorerComponent-BAiSVaHj.js} +17 -15
- package/dist/{ErrorBoundary-S_edj6VQ.js → ErrorBoundary-CTJ1U1fx.js} +16 -16
- package/dist/{abnfDiagram-VCTEODGH-D-Ez91gV.js → abnfDiagram-VCTEODGH-BBHN92-F.js} +2 -2
- package/dist/any-language-editor-3E24SnCV.js +75 -0
- package/dist/{architectureDiagram-5GKGNRK7-CTpcNtO8.js → architectureDiagram-5GKGNRK7-C0Rd64qh.js} +1 -1
- package/dist/{arrays-CN1djC4k.js → arrays-R6JsImiT.js} +8 -0
- package/dist/assets/__vite-browser-external-BgQNn4dS.js +1 -0
- package/dist/assets/worker-FKe3RHT4.js +113 -0
- package/dist/{button-CvjkwdSk.js → button-BQRdqQi1.js} +199 -192
- package/dist/{capabilities-CQ5IjhzL.js → capabilities-CI4xUPsp.js} +2 -2
- package/dist/{chat-ui-DaHynk8g.js → chat-ui-CvB8Map3.js} +1142 -1141
- package/dist/{check-EDwSwP89.js → check-SpOMoCLP.js} +1 -1
- package/dist/{chunk-IMKFNOWR-DGxi-zeo.js → chunk-IMKFNOWR-hJXey5p2.js} +1 -1
- package/dist/{chunk-SHT3W25Y-CV9J3rAB.js → chunk-SHT3W25Y-JMzTmmVW.js} +1 -1
- package/dist/{chunk-SVP7TREG-BL-9Fqgg.js → chunk-SVP7TREG-BIyoHTXi.js} +1 -1
- package/dist/{chunk-TICWLB2K-Cu_XMjDM.js → chunk-TICWLB2K-CCzH2Uwa.js} +1 -1
- package/dist/{chunk-YOKDWASO-DPZk8vhS.js → chunk-YOKDWASO-DKplTrBY.js} +20 -20
- package/dist/{classDiagram-ZZMXUADV-BXXV13Hq.js → classDiagram-ZZMXUADV-DB1kOPS6.js} +2 -2
- package/dist/{classDiagram-v2-VYDZK3BY-B7FXJ1Cp.js → classDiagram-v2-VYDZK3BY-CPaFL0OB.js} +2 -2
- package/dist/{code-visibility-BBdICLTP.js → code-visibility-C1jZfwPW.js} +6 -6
- package/dist/{common-7r9HNiTn.js → common-CNv_7gvI.js} +6766 -6590
- package/dist/{copy-icon-Ft7t9bqz.js → copy-icon-C1trdvVt.js} +3 -3
- package/dist/{cynefinDiagram-5FMLGOSQ-CH96rwba.js → cynefinDiagram-5FMLGOSQ-CF93uliH.js} +1 -1
- package/dist/{dagre-GXQ25YYZ-BD3PmpFY.js → dagre-GXQ25YYZ-BBB-_p9D.js} +1 -1
- package/dist/{data-grid-overlay-editor-Bz1FTAfW.js → data-grid-overlay-editor-t0t17DPI.js} +5 -5
- package/dist/{data-grid-types-BH_r7g7l.js → data-grid-types-0PJ-9N5n.js} +1 -1
- package/dist/{diagram-S7CK7UJ4-BsSJJldB.js → diagram-S7CK7UJ4-BynCnbyt.js} +1 -1
- package/dist/{diagram-UQ7AKVKN-muQtNZc4.js → diagram-UQ7AKVKN-svOxikMa.js} +1 -1
- package/dist/{diagram-VX7I27RA-CdhuZAqR.js → diagram-VX7I27RA-BVQSnPx0.js} +1 -1
- package/dist/{diagram-Z3DM3KII-BD8mXjOj.js → diagram-Z3DM3KII-nR1J0BH5.js} +1 -1
- package/dist/{dialog-CEBFZNyc.js → dialog-DgeqyrEZ.js} +3 -3
- package/dist/{dist-DpBpA_n1.js → dist-Lm-D-Vr6.js} +3 -3
- package/dist/{dropdown-menu-CP_qCYHC.js → dropdown-menu-GWcGCcxE.js} +1277 -1229
- package/dist/{ebnfDiagram-PWID7BFC-BIN1sweE.js → ebnfDiagram-PWID7BFC-C9tq9-Qo.js} +2 -2
- package/dist/{erDiagram-RLTQ6QDP-Ctp5cfoN.js → erDiagram-RLTQ6QDP-BiaeB7Fi.js} +1 -1
- package/dist/{error-banner-D-WCIiMt.js → error-banner-D40pmfQQ.js} +83 -83
- package/dist/{error-entries-Bv6bZPF3.js → error-entries-CmFDQ9CA.js} +1018 -977
- package/dist/{feedback-button-BAheGhdl.js → feedback-button-JzaiyZZm.js} +23 -23
- package/dist/{flowDiagram-HODETNUW-3EfLrlFb.js → flowDiagram-HODETNUW-f-sLm87k.js} +2 -2
- package/dist/{formats-27CW_UP4.js → formats-CCxaLPNs.js} +3 -3
- package/dist/{ganttDiagram-EL5Y4UJY-BQT16JSc.js → ganttDiagram-EL5Y4UJY-Dh_4cBJZ.js} +2 -2
- package/dist/{glide-data-editor-CAvrTnyB.js → glide-data-editor-B3eq-1SC.js} +370 -368
- package/dist/{glide-utils-DJyqh0EM.js → glide-utils-Dz_F4pAY.js} +16 -16
- package/dist/{globals-C03jB5fY.js → globals-BW8TOLYQ.js} +3 -3
- package/dist/{highlighted-body-KPVGNVTW-zwjq21tf.js → highlighted-body-KPVGNVTW-3Ziwfz-V.js} +2 -2
- package/dist/{html-to-image-Bf8QMGi4.js → html-to-image-BrC8OJcj.js} +632 -595
- package/dist/{infoDiagram-27XIBGKW-DipQoHxl.js → infoDiagram-27XIBGKW-BHrWywBe.js} +1 -1
- package/dist/{ishikawaDiagram-5VMMS53U-DgFMjSGz.js → ishikawaDiagram-5VMMS53U-Da4s0Reg.js} +1 -1
- package/dist/{kanban-definition-UXKFOSKX-w1ACVjgl.js → kanban-definition-UXKFOSKX-DDf1GVLj.js} +1 -1
- package/dist/{label-BDKF3Afc.js → label-D9_-zSg-.js} +3 -3
- package/dist/{linear-Cnaq3Tfb.js → linear-DWERh7eI.js} +121 -73
- package/dist/{loader-BQOfjTIJ.js → loader-DOVB0Syl.js} +12 -12
- package/dist/main.js +7551 -7231
- package/dist/{mermaid-CHo49Yv-.js → mermaid-ClwTt7OD.js} +38 -38
- package/dist/mermaid-HWGCJPDP-Du3-HPQA.js +2 -0
- package/dist/{mindmap-definition-YA3MSWOX-CrT0KSfX.js → mindmap-definition-YA3MSWOX-D60oMZtT.js} +1 -1
- package/dist/{number-overlay-editor-DRF7iVLO.js → number-overlay-editor-DoUnDbPE.js} +3 -3
- package/dist/{objects-CzUgoMIF.js → objects-DCmMvZtn.js} +1 -3
- package/dist/{once-BtE-wKRL.js → once-eG8Vmvjd.js} +1 -1
- package/dist/{pegDiagram-XKGWAZYB-BqvywNJA.js → pegDiagram-XKGWAZYB-B9wFpMga.js} +2 -2
- package/dist/{pieDiagram-E7YTZNPT-BfxJ_XCc.js → pieDiagram-E7YTZNPT-BZwvMuBT.js} +1 -1
- package/dist/precisionRound-DhAzeRcm.js +49 -0
- package/dist/{process-output-BZg56CCb.js → process-output-Bw-vzyoy.js} +5 -5
- package/dist/{quadrantDiagram-AXDQQJYC-Ccw0xMjN.js → quadrantDiagram-AXDQQJYC-Blrm7V7_.js} +1 -1
- package/dist/{railroadDiagram-O6MQD6OU-8vFLVTPu.js → railroadDiagram-O6MQD6OU-DqhZGsN2.js} +2 -2
- package/dist/{react-vega-BED0DjiB.js → react-vega-C4T9Rb_w.js} +12284 -12270
- package/dist/{requirementDiagram-BXWQKSXE-a_MxGvxe.js → requirementDiagram-BXWQKSXE-CL5dYARV.js} +1 -1
- package/dist/{reveal-component-QSvE6jwa.js → reveal-component-ClNn1CDl.js} +14 -14
- package/dist/{select-BButFi-d.js → select-CkF_GBxO.js} +537 -458
- package/dist/{sequenceDiagram-WJ2MYXX4-CXFMnxGh.js → sequenceDiagram-WJ2MYXX4-BSUCRd2x.js} +1 -1
- package/dist/{spec-BwarBpUJ.js → spec-DiSh_qJC.js} +41 -11
- package/dist/{stateDiagram-D77RDMKH-DQeA_CwI.js → stateDiagram-D77RDMKH-B-1Hvyb0.js} +2 -2
- package/dist/{stateDiagram-v2-MP3YSRHH-BxxQucm1.js → stateDiagram-v2-MP3YSRHH--HtiR4yB.js} +2 -2
- package/dist/style.css +1 -1
- package/dist/{swimlanes-42K2YHIH-Do6L-cYg.js → swimlanes-42K2YHIH-Bdfhrd-2.js} +1 -1
- package/dist/{swimlanesDiagram-VR7AAH4N-DUzPvSVU.js → swimlanesDiagram-VR7AAH4N-BJIfxSz0.js} +2 -2
- package/dist/{swiper-component-DKntyn8p.js → swiper-component-BkCm-kLg.js} +2 -2
- package/dist/{time-BieKwdYS.js → time-BaMbJs4z.js} +18 -18
- package/dist/{timeline-definition-24CTP7MA-D3c46WM5.js → timeline-definition-24CTP7MA-Cs4EfFD3.js} +1 -1
- package/dist/{toDate-UtiwmnH2.js → toDate-DGvRHwTk.js} +19 -18
- package/dist/{toast-B9UMEi8u.js → toast-Btbve3Lm.js} +231 -213
- package/dist/{tooltip-BO1REbqs.js → tooltip-CJ4Rqasp.js} +327 -303
- package/dist/{use-restore-focus-BEM7sFWl.js → use-restore-focus-CmGwRNId.js} +1482 -1433
- package/dist/{useAsyncData-Deh5kszT.js → useAsyncData-BmVgnMP5.js} +15 -14
- package/dist/{useDateFormatter-D8XruNGG.js → useDateFormatter-eCL_SdeG.js} +2 -2
- package/dist/{useDeepCompareMemoize-DXwzRINI.js → useDeepCompareMemoize-Ch_AeGu6.js} +1 -1
- package/dist/{useIframeCapabilities-DBETvvPl.js → useIframeCapabilities-CSdWn6NP.js} +1 -1
- package/dist/{useLifecycle-j7D9uD1o.js → useLifecycle-B5BX921H.js} +3 -3
- package/dist/{useTheme-CRnjkku0.js → useTheme-Bq9pi_vz.js} +6 -6
- package/dist/{vega-component-BeF9dfyO.js → vega-component-BgyZ-COt.js} +147 -147
- package/dist/{vega-embed-container-BNHE18G9.js → vega-embed-container--LYZqguO.js} +2 -2
- package/dist/{vega-loader.browser-DNST6uVf.js → vega-loader.browser-B9Pz0EGP.js} +298 -507
- package/dist/{vennDiagram-4TSXK5OY-BSZD8JcZ.js → vennDiagram-4TSXK5OY-DRu0vRjO.js} +1 -1
- package/dist/{wardleyDiagram-VM6X3IG4-48cUWkfA.js → wardleyDiagram-VM6X3IG4-DzbDxwDY.js} +1 -1
- package/dist/{xychartDiagram-S5SC5T6Z-CswYgYeu.js → xychartDiagram-S5SC5T6Z-CLWj6ZFQ.js} +2 -2
- package/package.json +14 -14
- package/src/__tests__/host-imports.test.ts +1 -0
- package/src/__tests__/module-entry.test.ts +32 -0
- package/src/__tests__/mount.test.ts +0 -20
- package/src/components/ai/__tests__/ai-model-dropdown.test.tsx +63 -0
- package/src/components/ai/ai-model-dropdown.tsx +11 -6
- package/src/components/app-config/ai-config.tsx +7 -2
- package/src/components/chat/__tests__/message-queue.test.tsx +17 -0
- package/src/components/chat/acp/__tests__/session-tabs.test.tsx +43 -0
- package/src/components/chat/acp/__tests__/state.test.ts +2 -2
- package/src/components/chat/acp/blocks.tsx +3 -2
- package/src/components/chat/acp/session-tabs.tsx +8 -3
- package/src/components/chat/chat-components.tsx +2 -0
- package/src/components/chat/chat-panel.tsx +9 -8
- package/src/components/chat/chat-utils.ts +4 -8
- package/src/components/data-table/TableTopBar.tsx +2 -0
- package/src/components/data-table/__tests__/chart-spec-model.test.ts +195 -195
- package/src/components/data-table/__tests__/column-explorer.test.tsx +27 -1
- package/src/components/data-table/__tests__/columns.test.tsx +105 -0
- package/src/components/data-table/__tests__/context-menu-interaction.test.tsx +130 -0
- package/src/components/data-table/__tests__/data-table.test.tsx +1 -0
- package/src/components/data-table/__tests__/date-popover.test.tsx +72 -0
- package/src/components/data-table/__tests__/export-actions.test.tsx +105 -0
- package/src/components/data-table/__tests__/keyboard-selection.test.tsx +188 -0
- package/src/components/data-table/__tests__/search-highlight.test.tsx +109 -0
- package/src/components/data-table/__tests__/url-detector.test.tsx +74 -0
- package/src/components/data-table/cell-selection/feature.ts +2 -2
- package/src/components/data-table/cell-selection/types.ts +2 -2
- package/src/components/data-table/charts/__tests__/chart-panel.test.tsx +74 -1
- package/src/components/data-table/charts/__tests__/spec-snapshot.test.ts +20 -20
- package/src/components/data-table/charts/__tests__/spec.test.ts +78 -52
- package/src/components/data-table/charts/__tests__/storage.test.ts +4 -1
- package/src/components/data-table/charts/chart-spec/spec.ts +68 -43
- package/src/components/data-table/charts/charts.tsx +40 -30
- package/src/components/data-table/charts/storage.ts +16 -5
- package/src/components/data-table/column-explorer-panel/column-explorer.tsx +1 -1
- package/src/components/data-table/column-summary/chart-spec-model.tsx +23 -16
- package/src/components/data-table/column-summary/column-summary.tsx +2 -4
- package/src/components/data-table/column-visibility-dropdown.tsx +8 -13
- package/src/components/data-table/columns.tsx +45 -46
- package/src/components/data-table/context-menu.tsx +36 -20
- package/src/components/data-table/data-table.tsx +13 -1
- package/src/components/data-table/date-popover.tsx +6 -4
- package/src/components/data-table/export-actions.tsx +76 -48
- package/src/components/data-table/range-focus/atoms.ts +4 -6
- package/src/components/data-table/range-focus/use-cell-range-selection.ts +65 -38
- package/src/components/data-table/range-focus/use-scroll-into-view.ts +21 -2
- package/src/components/data-table/renderers.tsx +16 -7
- package/src/components/data-table/row-viewer-panel/__tests__/row-viewer.test.tsx +24 -1
- package/src/components/data-table/row-viewer-panel/row-viewer.tsx +4 -4
- package/src/components/data-table/search-highlight.tsx +79 -0
- package/src/components/data-table/types.ts +1 -0
- package/src/components/data-table/url-detector.tsx +49 -9
- package/src/components/datasources/__tests__/column-actions.test.tsx +97 -0
- package/src/components/datasources/__tests__/column-preview.test.tsx +98 -5
- package/src/components/datasources/__tests__/datasources-interactions.test.tsx +181 -0
- package/src/components/datasources/__tests__/table-list.test.tsx +118 -0
- package/src/components/datasources/__tests__/utils.test.ts +57 -6
- package/src/components/datasources/column-preview.tsx +13 -4
- package/src/components/datasources/datasources.tsx +51 -39
- package/src/components/datasources/utils.ts +32 -23
- package/src/components/debugger/debugger-code.tsx +5 -0
- package/src/components/dependency-graph/dependency-graph-tree.tsx +8 -8
- package/src/components/dependency-graph/elements.ts +24 -21
- package/src/components/dependency-graph/panels.tsx +2 -1
- package/src/components/dependency-graph/utils/__tests__/layout.test.ts +18 -11
- package/src/components/editor/SortableCell.tsx +1 -3
- package/src/components/editor/__tests__/dynamic-favicon.test.tsx +111 -18
- package/src/components/editor/__tests__/package-alert.test.tsx +22 -1
- package/src/components/editor/actions/__tests__/pair-with-agent-modal.test.tsx +24 -0
- package/src/components/editor/actions/pair-with-agent-modal.tsx +18 -15
- package/src/components/editor/ai/add-cell-with-ai.tsx +3 -3
- package/src/components/editor/ai/ai-completion-editor.tsx +1 -0
- package/src/components/editor/alerts/startup-logs-alert.tsx +1 -0
- package/src/components/editor/cell/CreateCellButton.tsx +8 -10
- package/src/components/editor/cell/DeleteButton.tsx +1 -0
- package/src/components/editor/cell/__tests__/useShouldShowInterrupt.test.ts +39 -0
- package/src/components/editor/cell/code/__tests__/language-toggle.test.tsx +54 -0
- package/src/components/editor/cell/code/cell-editor.tsx +1 -1
- package/src/components/editor/cell/code/language-toggle.tsx +8 -7
- package/src/components/editor/cell/collapse.tsx +5 -3
- package/src/components/editor/cell/useShouldShowInterrupt.ts +2 -12
- package/src/components/editor/chrome/panels/__tests__/packages-panel.test.tsx +30 -1
- package/src/components/editor/chrome/panels/cache-panel.tsx +1 -0
- package/src/components/editor/chrome/panels/outline/__tests__/outline-keyboard.test.tsx +84 -0
- package/src/components/editor/chrome/panels/outline/floating-outline.tsx +39 -14
- package/src/components/editor/chrome/panels/outline/useActiveOutline.tsx +3 -2
- package/src/components/editor/chrome/panels/packages-panel.tsx +4 -7
- package/src/components/editor/chrome/panels/secrets-panel.tsx +1 -0
- package/src/components/editor/chrome/panels/snippets-panel.tsx +5 -1
- package/src/components/editor/chrome/wrapper/__tests__/attachment-status.test.tsx +12 -18
- package/src/components/editor/chrome/wrapper/__tests__/pending-ai-cells.test.tsx +58 -1
- package/src/components/editor/chrome/wrapper/footer-items/runtime-settings.tsx +1 -7
- package/src/components/editor/chrome/wrapper/pending-ai-cells.tsx +12 -2
- package/src/components/editor/chrome/wrapper/storage.ts +1 -1
- package/src/components/editor/connections/components.tsx +1 -1
- package/src/components/editor/controls/__tests__/command-palette.test.tsx +53 -0
- package/src/components/editor/controls/__tests__/keyboard-shortcuts.test.tsx +61 -0
- package/src/components/editor/controls/command-palette.tsx +22 -10
- package/src/components/editor/controls/keyboard-shortcuts.tsx +14 -5
- package/src/components/editor/dynamic-favicon.tsx +21 -40
- package/src/components/editor/errors/__tests__/send-error-report-button.test.tsx +12 -23
- package/src/components/editor/file-tree/__tests__/file-explorer-interactions.test.tsx +6 -0
- package/src/components/editor/file-tree/__tests__/file-explorer-navigation.test.tsx +47 -0
- package/src/components/editor/file-tree/__tests__/use-file-search.test.tsx +91 -0
- package/src/components/editor/file-tree/file-explorer.tsx +45 -8
- package/src/components/editor/file-tree/file-name-input.tsx +1 -0
- package/src/components/editor/file-tree/file-viewer.tsx +4 -2
- package/src/components/editor/file-tree/use-file-search.ts +35 -21
- package/src/components/editor/header/status.tsx +28 -5
- package/src/components/editor/links/__tests__/cell-link.test.tsx +146 -0
- package/src/components/editor/links/cell-link.tsx +14 -5
- package/src/components/editor/navigation/focus-utils.ts +4 -4
- package/src/components/editor/notebook-banner.tsx +1 -0
- package/src/components/editor/notebook-cell.tsx +11 -2
- package/src/components/editor/output/MarimoTracebackOutput.tsx +19 -17
- package/src/components/editor/output/__tests__/traceback.test.tsx +27 -1
- package/src/components/editor/output/ansi-reduce.ts +33 -20
- package/src/components/editor/output/console/ConsoleOutput.tsx +19 -25
- package/src/components/editor/package-alert.tsx +14 -7
- package/src/components/editor/renderers/grid-layout/grid-layout.tsx +12 -6
- package/src/components/editor/renderers/vertical-layout/sidebar/toggle.tsx +7 -1
- package/src/components/home/components.tsx +17 -31
- package/src/components/icons/__tests__/large-spinner.test.tsx +39 -0
- package/src/components/icons/large-spinner.tsx +3 -14
- package/src/components/icons/spinner.tsx +1 -1
- package/src/components/mcp/mcp-status-indicator.tsx +1 -1
- package/src/components/pages/__tests__/home-page.test.tsx +116 -0
- package/src/components/pages/home-page.tsx +164 -91
- package/src/components/scratchpad/scratchpad.test.tsx +95 -0
- package/src/components/scratchpad/scratchpad.tsx +16 -3
- package/src/components/slides/reveal-component.tsx +4 -2
- package/src/components/slides/slide-cell-view.tsx +1 -1
- package/src/components/slides/slide-form.tsx +1 -0
- package/src/components/tracing/tracing-keyboard.test.tsx +85 -0
- package/src/components/tracing/tracing.tsx +45 -41
- package/src/components/ui/__tests__/draggable-popover.test.tsx +24 -0
- package/src/components/ui/__tests__/range-slider.test.tsx +165 -0
- package/src/components/ui/alert-dialog.tsx +1 -1
- package/src/components/ui/draggable-popover.tsx +24 -2
- package/src/components/ui/range-slider.tsx +22 -9
- package/src/core/ai/context/providers/datasource.ts +6 -2
- package/src/core/ai/tools/base.ts +16 -7
- package/src/core/ai/tools/edit-notebook-tool.ts +47 -45
- package/src/core/ai/tools/registry.ts +13 -8
- package/src/core/ai/tools/sample-tool.ts +6 -7
- package/src/core/attachments/state.ts +5 -8
- package/src/core/cells/__tests__/__snapshots__/cells.test.ts.snap +4 -0
- package/src/core/cells/__tests__/cell.test.ts +39 -0
- package/src/core/cells/__tests__/cells.test.ts +3 -1
- package/src/core/cells/__tests__/collapseConsoleOutputs.test.ts +54 -0
- package/src/core/cells/__tests__/notebook-outline.test.ts +113 -0
- package/src/core/cells/__tests__/session.test.ts +117 -36
- package/src/core/cells/cell.ts +14 -3
- package/src/core/cells/cells.ts +3 -1
- package/src/core/cells/pending-delete-service.ts +2 -6
- package/src/core/cells/session.ts +1 -1
- package/src/core/cells/types.ts +10 -1
- package/src/core/codemirror/__tests__/setup.test.ts +29 -29
- package/src/core/codemirror/cells/__tests__/extensions.test.ts +15 -0
- package/src/core/codemirror/cells/extensions.ts +7 -3
- package/src/core/codemirror/keymaps/vim.ts +2 -6
- package/src/core/codemirror/language/__tests__/sql.test.ts +22 -20
- package/src/core/codemirror/language/extension.ts +8 -8
- package/src/core/codemirror/language/languages/markdown.ts +8 -6
- package/src/core/codemirror/language/languages/python.ts +16 -10
- package/src/core/codemirror/language/languages/sql/sql.ts +9 -7
- package/src/core/codemirror/language/panel/panel.tsx +1 -0
- package/src/core/codemirror/language/types.ts +7 -7
- package/src/core/codemirror/rtc/extension.ts +24 -12
- package/src/core/codemirror/rtc/loro/awareness.ts +34 -19
- package/src/core/codemirror/rtc/loro/sync.ts +1 -0
- package/src/core/codemirror/utils.ts +1 -0
- package/src/core/datasets/__tests__/data-source-discovery.test.ts +4 -4
- package/src/core/datasets/data-source-discovery.ts +4 -6
- package/src/core/document/__tests__/codemirror.test.ts +485 -0
- package/src/core/document/__tests__/draft.test.ts +322 -0
- package/src/core/document/__tests__/fixtures.ts +92 -0
- package/src/core/document/__tests__/hooks.test.tsx +386 -0
- package/src/core/document/__tests__/lifecycle-scenarios.test.ts +61 -0
- package/src/core/document/__tests__/model.test.ts +191 -0
- package/src/core/document/__tests__/protocol-fixtures.ts +38 -0
- package/src/core/document/__tests__/recovery-scenarios.test.ts +230 -0
- package/src/core/document/__tests__/scenario-fixture.ts +43 -0
- package/src/core/document/__tests__/scenarios.test.ts +205 -0
- package/src/core/document/__tests__/state.test.ts +438 -0
- package/src/core/document/__tests__/submission.test.ts +203 -0
- package/src/core/document/__tests__/test-host.test.ts +92 -0
- package/src/core/document/__tests__/test-host.ts +247 -0
- package/src/core/document/__tests__/test-notebook.ts +149 -0
- package/src/core/document/__tests__/user.ts +61 -0
- package/src/core/document/codemirror.ts +311 -0
- package/src/core/document/draft.ts +472 -0
- package/src/core/document/hooks.tsx +118 -0
- package/src/core/document/index.ts +15 -0
- package/src/core/document/model.ts +55 -0
- package/src/core/document/select.ts +41 -0
- package/src/core/document/state.ts +374 -0
- package/src/core/document/sync.ts +369 -0
- package/src/core/host/AGENTS.md +8 -2
- package/src/core/host/__tests__/attachments.test.ts +56 -0
- package/src/core/host/__tests__/document.test.ts +126 -0
- package/src/core/host/__tests__/fixtures.ts +71 -0
- package/src/core/host/__tests__/replica.test.ts +550 -0
- package/src/core/host/__tests__/static.test.ts +169 -0
- package/src/core/host/__tests__/wasm.test.ts +163 -0
- package/src/core/host/backend.ts +19 -0
- package/src/core/host/connection.ts +1 -40
- package/src/core/host/index.ts +14 -0
- package/src/core/host/replica.ts +286 -0
- package/src/core/host/resources/attachments.ts +22 -0
- package/src/core/host/resources/document.ts +101 -0
- package/src/core/host/static.ts +72 -0
- package/src/core/host/wasm.ts +107 -0
- package/src/core/hotkeys/actions.ts +2 -4
- package/src/core/islands/__tests__/bootstrap.test.ts +16 -42
- package/src/core/islands/__tests__/bridge.test.ts +31 -26
- package/src/core/islands/bootstrap.ts +22 -52
- package/src/core/islands/bridge.ts +31 -20
- package/src/core/islands/components/__tests__/IslandControls.test.tsx +7 -5
- package/src/core/islands/worker/__tests__/controller.test.ts +62 -4
- package/src/core/islands/worker/controller.ts +4 -10
- package/src/core/islands/worker/worker.tsx +33 -33
- package/src/core/kernel/__tests__/RuntimeState.test.ts +1 -1
- package/src/core/network/connection.ts +4 -2
- package/src/core/network/useConnectionNotice.ts +8 -2
- package/src/core/runtime/__tests__/createWsUrl.test.ts +77 -7
- package/src/core/runtime/__tests__/runtime.test.ts +32 -58
- package/src/core/runtime/runtime.ts +38 -42
- package/src/core/runtime/types.ts +0 -2
- package/src/core/state/__tests__/jotai.test.tsx +108 -0
- package/src/core/state/jotai.ts +1 -1
- package/src/core/static/__tests__/files.test.ts +38 -10
- package/src/core/static/files.ts +2 -0
- package/src/core/wasm/__tests__/bridge.test.ts +42 -1
- package/src/core/wasm/__tests__/worker.test.ts +182 -0
- package/src/core/wasm/bridge.ts +40 -21
- package/src/core/wasm/rpc.ts +0 -1
- package/src/core/wasm/store.ts +3 -3
- package/src/core/wasm/worker/bootstrap.ts +55 -51
- package/src/core/wasm/worker/getMarimoWheel.ts +1 -1
- package/src/core/wasm/worker/types.ts +23 -14
- package/src/core/wasm/worker/worker.ts +77 -36
- package/src/core/websocket/__tests__/backend.test.ts +228 -0
- package/src/core/websocket/__tests__/connection-state.test.ts +0 -12
- package/src/core/websocket/__tests__/useNotebookReplica.hook.test.tsx +141 -0
- package/src/core/websocket/__tests__/useNotebookSession.hook.test.tsx +154 -428
- package/src/core/websocket/backend.ts +130 -0
- package/src/core/websocket/connection-state.ts +1 -11
- package/src/core/websocket/state.ts +7 -0
- package/src/core/websocket/transports/__tests__/notebook.test.ts +405 -0
- package/src/core/websocket/transports/notebook.ts +159 -0
- package/src/core/websocket/types.ts +2 -2
- package/src/core/websocket/useNotebookReplica.ts +69 -0
- package/src/core/websocket/useNotebookSession.tsx +18 -25
- package/src/css/globals.css +5 -0
- package/src/hooks/__tests__/useAsyncData.test.tsx +148 -0
- package/src/hooks/__tests__/useDebounce.test.tsx +51 -0
- package/src/hooks/__tests__/useDeepCompareMemoize.test.tsx +39 -0
- package/src/hooks/__tests__/useDelayElapsed.test.tsx +28 -0
- package/src/hooks/__tests__/useInternalStateWithSync.test.tsx +20 -0
- package/src/hooks/__tests__/useScript.test.tsx +77 -0
- package/src/hooks/__tests__/useStateForKey.test.tsx +257 -0
- package/src/hooks/useAsyncData.ts +3 -3
- package/src/hooks/useDataSourceDiscovery.ts +6 -4
- package/src/hooks/useDebounce.ts +6 -10
- package/src/hooks/useDeepCompareMemoize.ts +1 -1
- package/src/hooks/useDelayElapsed.ts +14 -10
- package/src/hooks/useElapsedTime.ts +3 -3
- package/src/hooks/useEventListener.ts +1 -2
- package/src/hooks/useInputHistory.ts +4 -7
- package/src/hooks/useInternalStateWithSync.ts +6 -6
- package/src/hooks/useResizeObserver.ts +4 -7
- package/src/hooks/useScript.ts +67 -70
- package/src/hooks/useStateForKey.ts +93 -0
- package/src/mount.tsx +0 -4
- package/src/plugins/__tests__/plugin-object-schemas.test.ts +104 -0
- package/src/plugins/core/registerReactComponent.tsx +1 -1
- package/src/plugins/impl/CodeEditorPlugin.tsx +1 -1
- package/src/plugins/impl/DataEditorPlugin.tsx +1 -1
- package/src/plugins/impl/DataTablePlugin.tsx +29 -33
- package/src/plugins/impl/DropdownPlugin.tsx +2 -6
- package/src/plugins/impl/FileBrowserPlugin.tsx +4 -16
- package/src/plugins/impl/FormPlugin.tsx +1 -1
- package/src/plugins/impl/RangeSliderPlugin.tsx +16 -2
- package/src/plugins/impl/RefreshPlugin.tsx +1 -0
- package/src/plugins/impl/SliderPlugin.tsx +6 -8
- package/src/plugins/impl/__tests__/DataTablePlugin.test.tsx +117 -1
- package/src/plugins/impl/__tests__/FileBrowserPlugin.test.tsx +45 -0
- package/src/plugins/impl/__tests__/RangeSliderPlugin.test.tsx +109 -0
- package/src/plugins/impl/__tests__/SliderPlugin.test.tsx +24 -3
- package/src/plugins/impl/anywidget/__tests__/registry.test.ts +2 -0
- package/src/plugins/impl/anywidget/__tests__/widget-binding.test.ts +241 -2
- package/src/plugins/impl/anywidget/runtime.ts +21 -9
- package/src/plugins/impl/anywidget/widget-binding.ts +160 -82
- package/src/plugins/impl/chat/__tests__/chat-prompts.test.tsx +93 -0
- package/src/plugins/impl/chat/chat-ui.tsx +14 -11
- package/src/plugins/impl/code/any-language-editor.tsx +2 -2
- package/src/plugins/impl/data-editor/glide-data-editor.tsx +8 -5
- package/src/plugins/impl/data-editor/glide-utils.ts +3 -1
- package/src/plugins/impl/data-explorer/ConnectedDataExplorerComponent.tsx +1 -1
- package/src/plugins/impl/data-explorer/components/column-summary.tsx +4 -2
- package/src/plugins/impl/data-explorer/state/reducer.ts +1 -1
- package/src/plugins/impl/data-frames/DataFramePlugin.tsx +1 -2
- package/src/plugins/impl/data-frames/__tests__/sidebar.test.tsx +160 -0
- package/src/plugins/impl/data-frames/forms/__tests__/__snapshots__/form.test.tsx.snap +66 -66
- package/src/plugins/impl/data-frames/panel.tsx +43 -16
- package/src/plugins/impl/mpl-interactive/MplInteractivePlugin.tsx +5 -3
- package/src/plugins/impl/panel/PanelPlugin.tsx +16 -17
- package/src/plugins/impl/panel/__tests__/utils.test.ts +39 -1
- package/src/plugins/impl/panel/utils.ts +17 -0
- package/src/plugins/impl/plotly/PlotlyPlugin.tsx +2 -5
- package/src/plugins/impl/plotly/selection.ts +25 -19
- package/src/plugins/impl/vega/VegaPlugin.tsx +2 -3
- package/src/plugins/impl/vega/make-selectable.ts +4 -7
- package/src/plugins/layout/RoutesPlugin.tsx +1 -1
- package/src/stories/__tests__/editor-story.test.tsx +33 -0
- package/src/stories/button.stories.tsx +1 -0
- package/src/stories/editor.stories.tsx +24 -17
- package/src/stories/form-wrapper.stories.tsx +2 -2
- package/src/stories/select.stories.tsx +2 -2
- package/src/stories/switchable-multi-select.stories.tsx +1 -1
- package/src/utils/__tests__/arrays.test.ts +35 -0
- package/src/utils/__tests__/batch-requests.test.ts +3 -3
- package/src/utils/__tests__/numbers.test.ts +105 -1
- package/src/utils/__tests__/objects.test.ts +21 -0
- package/src/utils/arrays.ts +10 -0
- package/src/utils/blob.ts +1 -1
- package/src/utils/numbers.ts +79 -18
- package/src/utils/objects.ts +3 -7
- package/src/utils/once.ts +19 -19
- package/src/utils/tracer.ts +9 -5
- package/src/utils/zod-utils.ts +1 -3
- package/dist/any-language-editor-DZ_YTVus.js +0 -76
- package/dist/assets/__vite-browser-external-BXYkiFsk.js +0 -1
- package/dist/assets/worker-HPY9fbhz.js +0 -114
- package/dist/mermaid-HWGCJPDP-ByCsZnYF.js +0 -2
- package/dist/precisionRound-DMIVQrt2.js +0 -97
- package/src/core/host/__tests__/events.test.ts +0 -46
- package/src/core/host/__tests__/notebook-client.test.ts +0 -191
- package/src/core/host/__tests__/protocol.test.ts +0 -214
- package/src/core/host/events.ts +0 -60
- package/src/core/host/notebook-client.ts +0 -226
- package/src/core/host/protocol.ts +0 -1943
- package/src/core/state/__tests__/jotai.test.ts +0 -25
- package/src/core/wasm/worker/message-buffer.ts +0 -33
- package/src/core/websocket/__tests__/createConnectionTransport.test.ts +0 -49
- package/src/core/websocket/__tests__/useNotebookClient.hook.test.tsx +0 -140
- package/src/core/websocket/transports/__tests__/basic.test.ts +0 -275
- package/src/core/websocket/transports/__tests__/sse.test.ts +0 -335
- package/src/core/websocket/transports/__tests__/transport.test.ts +0 -308
- package/src/core/websocket/transports/__tests__/ws.test.ts +0 -125
- package/src/core/websocket/transports/basic.ts +0 -102
- package/src/core/websocket/transports/create.ts +0 -31
- package/src/core/websocket/transports/sse.ts +0 -308
- package/src/core/websocket/transports/transport.ts +0 -50
- package/src/core/websocket/transports/ws.ts +0 -98
- package/src/core/websocket/useNotebookClient.ts +0 -80
|
@@ -73,9 +73,11 @@ export class FrontendToolRegistry {
|
|
|
73
73
|
const strError = z.prettifyError(inputResponse.error);
|
|
74
74
|
throw new ToolExecutionError(
|
|
75
75
|
`Tool ${toolName} returned invalid input: ${strError}`,
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
{
|
|
77
|
+
code: "INVALID_ARGUMENTS",
|
|
78
|
+
isRetryable: true,
|
|
79
|
+
suggestedFix: "Please check the arguments and try again.",
|
|
80
|
+
},
|
|
79
81
|
);
|
|
80
82
|
}
|
|
81
83
|
const args = inputResponse.data;
|
|
@@ -110,12 +112,15 @@ export class FrontendToolRegistry {
|
|
|
110
112
|
// Handle unknown/generic errors
|
|
111
113
|
const genericError = new ToolExecutionError(
|
|
112
114
|
error instanceof Error ? error.message : String(error),
|
|
113
|
-
"TOOL_ERROR",
|
|
114
|
-
false,
|
|
115
|
-
"Check the error message and try again with valid arguments.",
|
|
116
115
|
{
|
|
117
|
-
|
|
118
|
-
|
|
116
|
+
code: "TOOL_ERROR",
|
|
117
|
+
isRetryable: false,
|
|
118
|
+
suggestedFix:
|
|
119
|
+
"Check the error message and try again with valid arguments.",
|
|
120
|
+
meta: {
|
|
121
|
+
args: rawArgs,
|
|
122
|
+
errorType: error?.constructor?.name ?? typeof error,
|
|
123
|
+
},
|
|
119
124
|
},
|
|
120
125
|
);
|
|
121
126
|
return {
|
|
@@ -50,13 +50,12 @@ export class TestFrontendTool implements AiTool<Input, Output> {
|
|
|
50
50
|
public async handler({ name }: Input): Promise<Output> {
|
|
51
51
|
// Example: Validate input and throw ToolExecutionError on invalid data
|
|
52
52
|
if (!name.trim()) {
|
|
53
|
-
throw new ToolExecutionError(
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
);
|
|
53
|
+
throw new ToolExecutionError("Name cannot be empty", {
|
|
54
|
+
code: "INVALID_INPUT",
|
|
55
|
+
isRetryable: false,
|
|
56
|
+
suggestedFix: "Please provide a non-empty name",
|
|
57
|
+
meta: { field: "name", received: name },
|
|
58
|
+
});
|
|
60
59
|
}
|
|
61
60
|
|
|
62
61
|
return {
|
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
|
-
import type { components } from "@marimo-team/marimo-api";
|
|
4
3
|
import { atom } from "jotai";
|
|
5
|
-
import {
|
|
4
|
+
import type { Attachment } from "@marimo-team/client/protocol";
|
|
5
|
+
import { notebookReplicaAtom } from "@/core/websocket/state";
|
|
6
6
|
|
|
7
|
-
export type Attachment
|
|
7
|
+
export type { Attachment } from "@marimo-team/client/protocol";
|
|
8
8
|
|
|
9
|
-
export const attachmentsAtom = atom<Attachment[]>([]);
|
|
10
9
|
export const agentAttachmentsAtom = atom((get) => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
return get(attachmentsAtom).filter(
|
|
10
|
+
const notebook = get(notebookReplicaAtom);
|
|
11
|
+
return (notebook ? get(notebook.attachmentsAtom) : []).filter(
|
|
15
12
|
(attachment) => attachment.kind === "agent",
|
|
16
13
|
);
|
|
17
14
|
});
|
|
@@ -139,6 +139,7 @@ exports[`cell reducer > can initialize stdin > second stdin requested 1`] = `
|
|
|
139
139
|
{
|
|
140
140
|
"channel": "stdin",
|
|
141
141
|
"data": "what is your name?",
|
|
142
|
+
"id": 2,
|
|
142
143
|
"mimetype": "text/plain",
|
|
143
144
|
"response": "Marimo!",
|
|
144
145
|
"timestamp": 2,
|
|
@@ -146,6 +147,7 @@ exports[`cell reducer > can initialize stdin > second stdin requested 1`] = `
|
|
|
146
147
|
{
|
|
147
148
|
"channel": "stdin",
|
|
148
149
|
"data": "how old are you?",
|
|
150
|
+
"id": 3,
|
|
149
151
|
"mimetype": "text/plain",
|
|
150
152
|
"timestamp": 3,
|
|
151
153
|
},
|
|
@@ -189,6 +191,7 @@ exports[`cell reducer > can initialize stdin > stdin answered 1`] = `
|
|
|
189
191
|
{
|
|
190
192
|
"channel": "stdin",
|
|
191
193
|
"data": "what is your name?",
|
|
194
|
+
"id": 2,
|
|
192
195
|
"mimetype": "text/plain",
|
|
193
196
|
"response": "Marimo!",
|
|
194
197
|
"timestamp": 2,
|
|
@@ -233,6 +236,7 @@ exports[`cell reducer > can initialize stdin > stdin requested 1`] = `
|
|
|
233
236
|
{
|
|
234
237
|
"channel": "stdin",
|
|
235
238
|
"data": "what is your name?",
|
|
239
|
+
"id": 2,
|
|
236
240
|
"mimetype": "text/plain",
|
|
237
241
|
"timestamp": 2,
|
|
238
242
|
},
|
|
@@ -219,6 +219,45 @@ describe("transitionCell serialization", () => {
|
|
|
219
219
|
});
|
|
220
220
|
});
|
|
221
221
|
|
|
222
|
+
describe("transitionCell console output ids", () => {
|
|
223
|
+
const output = (
|
|
224
|
+
data: string,
|
|
225
|
+
channel: OutputMessage["channel"] = "stdout",
|
|
226
|
+
): OutputMessage => ({
|
|
227
|
+
channel,
|
|
228
|
+
mimetype: "text/plain",
|
|
229
|
+
data,
|
|
230
|
+
timestamp: 0,
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
it("assigns increasing ids to appended outputs", () => {
|
|
234
|
+
let cell = createCellRuntimeState({ status: "running" });
|
|
235
|
+
cell = transitionCell(cell, { console: output("a") } as CellMessage);
|
|
236
|
+
cell = transitionCell(cell, {
|
|
237
|
+
console: output("b", "stderr"),
|
|
238
|
+
} as CellMessage);
|
|
239
|
+
expect(cell.consoleOutputs.map((o) => o.id)).toEqual([1, 2]);
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
it("continues from the surviving maximum after a collapse", () => {
|
|
243
|
+
let cell = createCellRuntimeState({ status: "running" });
|
|
244
|
+
cell = transitionCell(cell, { console: output("a") } as CellMessage);
|
|
245
|
+
cell = transitionCell(cell, { console: output("b") } as CellMessage);
|
|
246
|
+
expect(cell.consoleOutputs.map((o) => o.id)).toEqual([1]);
|
|
247
|
+
cell = transitionCell(cell, {
|
|
248
|
+
console: output("c", "stderr"),
|
|
249
|
+
} as CellMessage);
|
|
250
|
+
expect(cell.consoleOutputs.map((o) => o.id)).toEqual([1, 2]);
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
it("assigns ids when the kernel replaces the whole console", () => {
|
|
254
|
+
const cell = transitionCell(createCellRuntimeState({ status: "running" }), {
|
|
255
|
+
console: [output("a"), output("b", "stderr")],
|
|
256
|
+
} as CellMessage);
|
|
257
|
+
expect(cell.consoleOutputs.map((o) => o.id)).toEqual([1, 2]);
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
|
|
222
261
|
describe("transitionCell stdin resolution", () => {
|
|
223
262
|
describe.each([
|
|
224
263
|
{
|
|
@@ -1579,7 +1579,9 @@ describe("cell reducer", () => {
|
|
|
1579
1579
|
response: secret,
|
|
1580
1580
|
});
|
|
1581
1581
|
|
|
1582
|
-
expect(cells[0].consoleOutputs).toEqual([
|
|
1582
|
+
expect(cells[0].consoleOutputs).toEqual([
|
|
1583
|
+
{ ...prompt, id: 1, response: "" },
|
|
1584
|
+
]);
|
|
1583
1585
|
expect(JSON.stringify(cells[0].consoleOutputs)).not.toContain(secret);
|
|
1584
1586
|
});
|
|
1585
1587
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { describe, expect, it } from "vitest";
|
|
4
4
|
import { StatefulOutputMessage } from "@/components/editor/output/ansi-reduce";
|
|
5
|
+
import type { ConsoleOutputMessage } from "@/core/cells/types";
|
|
5
6
|
import type { OutputMessage } from "@/core/kernel/messages";
|
|
6
7
|
import {
|
|
7
8
|
collapseConsoleOutputs,
|
|
@@ -279,6 +280,59 @@ describe("collapseConsoleOutputs", () => {
|
|
|
279
280
|
expect(result[0].data).toContain("Streaming output truncated");
|
|
280
281
|
});
|
|
281
282
|
|
|
283
|
+
it("keeps the first id when collapsing outputs", () => {
|
|
284
|
+
const consoleOutputs = [
|
|
285
|
+
{
|
|
286
|
+
mimetype: "text/plain",
|
|
287
|
+
channel: "output",
|
|
288
|
+
data: "Hello ",
|
|
289
|
+
timestamp: 0,
|
|
290
|
+
id: 7,
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
mimetype: "text/plain",
|
|
294
|
+
channel: "output",
|
|
295
|
+
data: "World",
|
|
296
|
+
timestamp: 0,
|
|
297
|
+
id: 8,
|
|
298
|
+
},
|
|
299
|
+
] satisfies ConsoleOutputMessage[];
|
|
300
|
+
const result = collapseConsoleOutputs(consoleOutputs);
|
|
301
|
+
expect(result).toHaveLength(1);
|
|
302
|
+
expect(result[0].data).toBe("Hello World");
|
|
303
|
+
expect((result[0] as ConsoleOutputMessage).id).toBe(7);
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
it("keeps ids on outputs that survive truncation", () => {
|
|
307
|
+
const consoleOutputs = [
|
|
308
|
+
{
|
|
309
|
+
mimetype: "text/plain",
|
|
310
|
+
channel: "output",
|
|
311
|
+
data: "one\ntwo",
|
|
312
|
+
timestamp: 0,
|
|
313
|
+
id: 1,
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
mimetype: "text/plain",
|
|
317
|
+
channel: "stderr",
|
|
318
|
+
data: "three\nfour",
|
|
319
|
+
timestamp: 0,
|
|
320
|
+
id: 2,
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
mimetype: "text/plain",
|
|
324
|
+
channel: "output",
|
|
325
|
+
data: "five",
|
|
326
|
+
timestamp: 0,
|
|
327
|
+
id: 3,
|
|
328
|
+
},
|
|
329
|
+
] satisfies ConsoleOutputMessage[];
|
|
330
|
+
const result = collapseConsoleOutputs(consoleOutputs, 3);
|
|
331
|
+
const ids = result.map((output) => (output as ConsoleOutputMessage).id);
|
|
332
|
+
expect(result[0].data).toContain("Streaming output truncated");
|
|
333
|
+
expect(ids).toEqual([undefined, 2, 3]);
|
|
334
|
+
});
|
|
335
|
+
|
|
282
336
|
describe("ANSI escape sequences", () => {
|
|
283
337
|
it("should handle cursor movement with collapse", () => {
|
|
284
338
|
const consoleOutputs: OutputMessage[] = [
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { createStore } from "jotai";
|
|
4
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
5
|
+
import { MockNotebook } from "@/__mocks__/notebook";
|
|
6
|
+
import { cellId } from "@/__tests__/branded";
|
|
7
|
+
import {
|
|
8
|
+
createNotebookActions,
|
|
9
|
+
notebookAtom,
|
|
10
|
+
notebookOutline,
|
|
11
|
+
notebookReducer,
|
|
12
|
+
} from "../cells";
|
|
13
|
+
import { exportedForTesting } from "../document-changes";
|
|
14
|
+
import type { Outline } from "../outline";
|
|
15
|
+
|
|
16
|
+
const first = cellId("first");
|
|
17
|
+
const second = cellId("second");
|
|
18
|
+
const firstOutline: Outline = {
|
|
19
|
+
items: [{ name: "First", level: 1, by: { id: "first" } }],
|
|
20
|
+
};
|
|
21
|
+
const secondOutline: Outline = {
|
|
22
|
+
items: [{ name: "Second", level: 2, by: { id: "second" } }],
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
function setup() {
|
|
26
|
+
const store = createStore();
|
|
27
|
+
store.set(
|
|
28
|
+
notebookAtom,
|
|
29
|
+
MockNotebook.notebookState({
|
|
30
|
+
cellData: { [first]: { code: "x = 1" }, [second]: {} },
|
|
31
|
+
cellRuntime: {
|
|
32
|
+
[first]: { outline: firstOutline },
|
|
33
|
+
[second]: { outline: secondOutline },
|
|
34
|
+
},
|
|
35
|
+
}),
|
|
36
|
+
);
|
|
37
|
+
const actions = createNotebookActions((action) =>
|
|
38
|
+
store.set(notebookAtom, (state) => notebookReducer(state, action)),
|
|
39
|
+
);
|
|
40
|
+
return { store, actions };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
afterEach(() => {
|
|
44
|
+
exportedForTesting.cancelPendingChanges();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe("notebookOutline", () => {
|
|
48
|
+
it("does not notify outline subscribers when cell code changes", () => {
|
|
49
|
+
const { store, actions } = setup();
|
|
50
|
+
const initial = store.get(notebookOutline);
|
|
51
|
+
const listener = vi.fn();
|
|
52
|
+
const unsubscribe = store.sub(notebookOutline, listener);
|
|
53
|
+
|
|
54
|
+
actions.updateCellCode({
|
|
55
|
+
cellId: first,
|
|
56
|
+
code: "x = 2",
|
|
57
|
+
formattingChange: false,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
expect(store.get(notebookOutline)).toBe(initial);
|
|
61
|
+
expect(listener).not.toHaveBeenCalled();
|
|
62
|
+
unsubscribe();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("updates headings when runtime outlines change or are removed", () => {
|
|
66
|
+
const { store } = setup();
|
|
67
|
+
const updated: Outline = {
|
|
68
|
+
items: [{ name: "Updated", level: 1, by: { id: "updated" } }],
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
for (const outline of [updated, null]) {
|
|
72
|
+
store.set(notebookAtom, (state) => ({
|
|
73
|
+
...state,
|
|
74
|
+
cellRuntime: {
|
|
75
|
+
...state.cellRuntime,
|
|
76
|
+
[first]: { ...state.cellRuntime[first], outline },
|
|
77
|
+
},
|
|
78
|
+
}));
|
|
79
|
+
expect(store.get(notebookOutline)).toEqual({
|
|
80
|
+
items: [...(outline?.items ?? []), ...secondOutline.items],
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it("keeps headings in cell order after moving and deleting cells", () => {
|
|
86
|
+
const { store, actions } = setup();
|
|
87
|
+
actions.moveCell({ cellId: second, before: true });
|
|
88
|
+
expect(store.get(notebookOutline)).toEqual({
|
|
89
|
+
items: [...secondOutline.items, ...firstOutline.items],
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
actions.deleteCell({ cellId: second });
|
|
93
|
+
expect(store.get(notebookOutline)).toEqual(firstOutline);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it("notifies subscribers when output is replaced with the same headings", () => {
|
|
97
|
+
const { store } = setup();
|
|
98
|
+
const listener = vi.fn();
|
|
99
|
+
const unsubscribe = store.sub(notebookOutline, listener);
|
|
100
|
+
|
|
101
|
+
store.set(notebookAtom, (state) => ({
|
|
102
|
+
...state,
|
|
103
|
+
cellRuntime: {
|
|
104
|
+
...state.cellRuntime,
|
|
105
|
+
[first]: { ...state.cellRuntime[first], outline: { ...firstOutline } },
|
|
106
|
+
},
|
|
107
|
+
}));
|
|
108
|
+
|
|
109
|
+
// Consumers must reconnect to replacement heading elements in the DOM.
|
|
110
|
+
expect(listener).toHaveBeenCalledOnce();
|
|
111
|
+
unsubscribe();
|
|
112
|
+
});
|
|
113
|
+
});
|
|
@@ -46,10 +46,17 @@ describe("notebookStateFromSession", () => {
|
|
|
46
46
|
|
|
47
47
|
const createNotebookCell = (
|
|
48
48
|
id: string,
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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
|
|
|
@@ -328,7 +335,10 @@ describe("notebookStateFromSession", () => {
|
|
|
328
335
|
describe("notebook only scenarios", () => {
|
|
329
336
|
it("creates state from notebook with single cell", () => {
|
|
330
337
|
const notebook = createNotebook([
|
|
331
|
-
createNotebookCell("cell-1",
|
|
338
|
+
createNotebookCell("cell-1", {
|
|
339
|
+
code: "print('hello')",
|
|
340
|
+
name: "my_cell",
|
|
341
|
+
}),
|
|
332
342
|
]);
|
|
333
343
|
const result = notebookStateFromSession(null, notebook);
|
|
334
344
|
|
|
@@ -356,11 +366,15 @@ describe("notebookStateFromSession", () => {
|
|
|
356
366
|
|
|
357
367
|
it("creates state from notebook with custom config", () => {
|
|
358
368
|
const notebook = createNotebook([
|
|
359
|
-
createNotebookCell("cell-1",
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
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
|
+
},
|
|
364
378
|
}),
|
|
365
379
|
]);
|
|
366
380
|
const result = notebookStateFromSession(null, notebook);
|
|
@@ -464,7 +478,10 @@ describe("notebookStateFromSession", () => {
|
|
|
464
478
|
),
|
|
465
479
|
]);
|
|
466
480
|
const notebook = createNotebook([
|
|
467
|
-
createNotebookCell("cell-1",
|
|
481
|
+
createNotebookCell("cell-1", {
|
|
482
|
+
code: "print('hello')",
|
|
483
|
+
name: "my_cell",
|
|
484
|
+
}),
|
|
468
485
|
]);
|
|
469
486
|
const result = notebookStateFromSession(session, notebook);
|
|
470
487
|
|
|
@@ -495,8 +512,8 @@ describe("notebookStateFromSession", () => {
|
|
|
495
512
|
createSessionCell("cell-2"),
|
|
496
513
|
]);
|
|
497
514
|
const notebook = createNotebook([
|
|
498
|
-
createNotebookCell("cell-2"),
|
|
499
|
-
createNotebookCell("cell-1"),
|
|
515
|
+
createNotebookCell("cell-2", {}),
|
|
516
|
+
createNotebookCell("cell-1", {}),
|
|
500
517
|
]);
|
|
501
518
|
|
|
502
519
|
const result = notebookStateFromSession(session, notebook);
|
|
@@ -514,8 +531,8 @@ describe("notebookStateFromSession", () => {
|
|
|
514
531
|
createSessionCell("cell-2"),
|
|
515
532
|
]);
|
|
516
533
|
const notebook = createNotebook([
|
|
517
|
-
createNotebookCell("cell-1"),
|
|
518
|
-
createNotebookCell("cell-2"),
|
|
534
|
+
createNotebookCell("cell-1", {}),
|
|
535
|
+
createNotebookCell("cell-2", {}),
|
|
519
536
|
]);
|
|
520
537
|
|
|
521
538
|
const result = notebookStateFromSession(session, notebook);
|
|
@@ -669,12 +686,42 @@ describe("notebookStateFromSession", () => {
|
|
|
669
686
|
};
|
|
670
687
|
// Create notebook cells with code values 'a' through 'f'
|
|
671
688
|
const notebookCells = [
|
|
672
|
-
createNotebookCell("cell-a",
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
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
|
+
}),
|
|
678
725
|
];
|
|
679
726
|
// Create session cells with matching code_hashes
|
|
680
727
|
const sessionCells = [
|
|
@@ -787,11 +834,36 @@ describe("notebookStateFromSession", () => {
|
|
|
787
834
|
|
|
788
835
|
// Notebook has cells with code 'a', 'c', 'z', 'e', 'g'
|
|
789
836
|
const notebookCells = [
|
|
790
|
-
createNotebookCell("cell-a",
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
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
|
+
}),
|
|
795
867
|
];
|
|
796
868
|
|
|
797
869
|
const session = createSession(sessionCells);
|
|
@@ -908,15 +980,24 @@ describe("notebookStateFromSession", () => {
|
|
|
908
980
|
|
|
909
981
|
// Notebook has cells: cell-1 (1 / 0, no hash), cell-2 (mo.md("Hello"), hash=moMd), cell-3 (slider, hash=slider)
|
|
910
982
|
const notebookCells = [
|
|
911
|
-
createNotebookCell("cell-1",
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
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
|
+
}),
|
|
920
1001
|
];
|
|
921
1002
|
|
|
922
1003
|
const session = createSession(sessionCells);
|
package/src/core/cells/cell.ts
CHANGED
|
@@ -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(
|
|
150
|
-
|
|
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
|
package/src/core/cells/cells.ts
CHANGED
|
@@ -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
|
|
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
|
);
|
|
@@ -134,12 +134,8 @@ export function usePendingDeleteService() {
|
|
|
134
134
|
submit({ cellIds, deleteCell, deleteManyCells, store });
|
|
135
135
|
},
|
|
136
136
|
clear,
|
|
137
|
-
|
|
138
|
-
|
|
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
|
|
59
|
+
cellIds.map((id) => [id, null] as [CellId, SessionCell | null]),
|
|
60
60
|
),
|
|
61
61
|
notebookCellData: new Map(
|
|
62
62
|
cellIds.map(
|
package/src/core/cells/types.ts
CHANGED
|
@@ -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:
|
|
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
|
+
};
|