@marimo-team/frontend 0.25.2 → 0.25.3-dev100
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/assets/CellStatus-fK4n2NPc.js +1 -0
- package/dist/assets/{ConnectedDataExplorerComponent-t8fH_TNc.js → ConnectedDataExplorerComponent-Dft8R6l5.js} +1 -1
- package/dist/assets/{ErrorBoundary-Gl5nCA8C.js → ErrorBoundary-CAEGdoFW.js} +2 -2
- package/dist/assets/JsonOutput-CyAKmZDD.js +11 -0
- package/dist/assets/{LazyAnyLanguageCodeMirror-CKcCbG2G.js → LazyAnyLanguageCodeMirror-BPYE76jR.js} +2 -2
- package/dist/assets/MarimoErrorOutput-CgZvP0p0.js +10 -0
- package/dist/assets/{RenderHTML-BbOqmHy3.js → RenderHTML-DQvxDDNS.js} +1 -1
- package/dist/assets/RunButton-BBDnDL6G.js +1 -0
- package/dist/assets/__vite-browser-external-8vDMR0Kk.js +1 -0
- package/dist/assets/__vite-browser-external-mKcnhO20.js +1 -0
- package/dist/assets/{add-cell-with-ai-8UBC0xwR.js → add-cell-with-ai-Clg5FELx.js} +12 -12
- package/dist/assets/{add-connection-dialog-DXQnd6eB.js → add-connection-dialog-BqdWmD-7.js} +2 -2
- package/dist/assets/{agent-panel-D7kMZLG-.js → agent-panel-5RxG5Y82.js} +5 -5
- package/dist/assets/ai-model-dropdown-Bvl1ktQq.js +13 -0
- package/dist/assets/{alert-dialog-BaPGzeOK.js → alert-dialog-C-sWmKva.js} +1 -1
- package/dist/assets/any-language-editor-DUMe1UCk.js +1 -0
- package/dist/assets/{app-config-button-BKEG4x9u.js → app-config-button-0QTeQ2Mv.js} +1 -1
- package/dist/assets/arrays-0R2reF2y.js +1 -0
- package/dist/assets/{blob-D5nfNHOo.js → blob-5VcB8K_t.js} +1 -1
- package/dist/assets/{button-COI-NGrx.js → button-D8gVKwe-.js} +1 -1
- package/dist/assets/{cache-panel-DTY1dqvi.js → cache-panel-BV-c7ed0.js} +1 -1
- package/dist/assets/{capabilities-BJvf-MD4.js → capabilities-Pq1YNPlK.js} +1 -1
- package/dist/assets/cell-editor-Byw5y-oI.js +42 -0
- package/dist/assets/cell-link-C5yYyzuF.js +1 -0
- package/dist/assets/{cells-BRkCaSsh.js → cells-D_11MjVB.js} +60 -60
- package/dist/assets/{chat-display-Dnagy4Nv.js → chat-display-BCR_ySiV.js} +1 -1
- package/dist/assets/chat-panel-RPRvBsaU.js +4 -0
- package/dist/assets/chat-ui-CGviVaRA.js +4 -0
- package/dist/assets/{circle-DXf-VWZG.js → circle-B6D_6D8w.js} +1 -1
- package/dist/assets/code-visibility-DYDagVy7.js +1 -0
- package/dist/assets/coerce-DWjFeXOY.js +1 -0
- package/dist/assets/column-preview-xe533-Cn.js +1 -0
- package/dist/assets/command-palette-BB9bWdWp.js +1 -0
- package/dist/assets/{common-Cu6CDbuw.js → common-CaeItbcI.js} +1 -1
- package/dist/assets/components-CBE8cOLK.js +1 -0
- package/dist/assets/{components-CP_UoFtT.js → components-DCo7mAWO.js} +1 -1
- package/dist/assets/{components-CGw16R_N.js → components-G6frbw0c.js} +1 -1
- package/dist/assets/config-CD1IuZFJ.js +1 -0
- package/dist/assets/config-DMz7oN0r.js +1 -0
- package/dist/assets/config-DpY86_Yq.js +1 -0
- package/dist/assets/{copy-D8O_CYCG.js → copy-KlhazlhB.js} +1 -1
- package/dist/assets/{copy-icon-BIiRXh_3.js → copy-icon-8-a5vovc.js} +1 -1
- package/dist/assets/{createReducer-DgRODTW6.js → createReducer-CaI_Oa0v.js} +1 -1
- package/dist/assets/{datasource-Cq6x_5ML.js → datasource-deuXnlU-.js} +1 -1
- package/dist/assets/{dates-BbFQ2oE4.js → dates-CQMwFko2.js} +1 -1
- package/dist/assets/{dependency-graph-panel--Kgtktcw.js → dependency-graph-panel-CIykLnJe.js} +2 -2
- package/dist/assets/{dist-iaThVDkA.js → dist-jlhMTKo_.js} +1 -1
- package/dist/assets/{documentation-panel-BHmbeznw.js → documentation-panel-2PQ8kQLa.js} +1 -1
- package/dist/assets/{download-DCJXy66H.js → download-dK52bLxZ.js} +1 -1
- package/dist/assets/{dropdown-menu-C1rnl-0o.js → dropdown-menu-DS6umAnH.js} +1 -1
- package/dist/assets/edit-page-DrElzw10.js +9 -0
- package/dist/assets/{error-banner-Cd69vvyX.js → error-banner-B5kzVf_0.js} +1 -1
- package/dist/assets/{error-entries-Dk3VZ-OK.js → error-entries-3GVk2KjS.js} +1 -1
- package/dist/assets/{error-panel-BPRYmC5J.js → error-panel-CzDRGPeC.js} +1 -1
- package/dist/assets/{errors-DCrsa1nH.js → errors-CNsgAw6m.js} +1 -1
- package/dist/assets/{es-Cqst59WX.js → es-N9SHpmG7.js} +1 -1
- package/dist/assets/{feedback-button-Bik2-e33.js → feedback-button-C5NgWpFg.js} +2 -2
- package/dist/assets/feedback-button-CONwLFpw.js +1 -0
- package/dist/assets/file-explorer-panel-B50xDnTZ.js +1 -0
- package/dist/assets/{file-name-input-Cdc-TVqO.js → file-name-input-DqwMSgGU.js} +1 -1
- package/dist/assets/{floating-outline-XD9FAV-f.js → floating-outline-ChmAuvxz.js} +1 -1
- package/dist/assets/{formats-yZ06h1Pl.js → formats-zylfwejq.js} +1 -1
- package/dist/assets/{formatting-BqrP-n49.js → formatting-uom1es4b.js} +1 -1
- package/dist/assets/{fullscreen-B9tHcfpV.js → fullscreen-BWTs8pYZ.js} +1 -1
- package/dist/assets/{gallery-page-Dm6mGwBi.js → gallery-page-CiL8aMS1.js} +1 -1
- package/dist/assets/{ganttDiagram-EL5Y4UJY-2n7Ig5Jm.js → ganttDiagram-EL5Y4UJY-CYqkCfFG.js} +1 -1
- package/dist/assets/{glide-data-editor-J9CAb70d.js → glide-data-editor-CqRclBkp.js} +2 -2
- package/dist/assets/{glide-utils-CIrAxdjv.js → glide-utils-HFqhvWHI.js} +2 -2
- package/dist/assets/home-page-BgZVl4dP.js +1 -0
- package/dist/assets/{hooks-93IwHd2u.js → hooks-DM5n7Osw.js} +1 -1
- package/dist/assets/{html-to-image-DK9Zl1lU.js → html-to-image-D_0rd3_B.js} +1 -1
- package/dist/assets/index-BnhSnwvB.css +2 -0
- package/dist/assets/index-EG2n8Oht.js +30 -0
- package/dist/assets/{input-BoBxR50a.js → input-DmHMEZGh.js} +1 -1
- package/dist/assets/kiosk-mode-DFS6HopF.js +1 -0
- package/dist/assets/layout-BpP8nTjb.js +9 -0
- package/dist/assets/linear-Bma8J3iM.js +1 -0
- package/dist/assets/links-DX2w97N9.js +1 -0
- package/dist/assets/{logs-panel-ABM16htT.js → logs-panel-B5eVAZtH.js} +1 -1
- package/dist/assets/{markdown-renderer-BG3sp2rs.js → markdown-renderer-BWUzqkJM.js} +1 -1
- package/dist/assets/{menu-items-BrwnTgyK.js → menu-items-BgUyNUpu.js} +1 -1
- package/dist/assets/{mermaid-a3xYymTy.js → mermaid-BKXlWk4F.js} +2 -2
- package/dist/assets/{name-cell-input-BgEBmqyL.js → name-cell-input-DXW68gRW.js} +1 -1
- package/dist/assets/numbers-CsZVw3Dc.js +1 -0
- package/dist/assets/{objects-snlMn4yk.js → objects-rLPlQ3X_.js} +1 -1
- package/dist/assets/{once-Haz_uxEL.js → once-6KNTRW0u.js} +1 -1
- package/dist/assets/{outline-panel-DCXQ3_F6.js → outline-panel-DPxJhJ_A.js} +1 -1
- package/dist/assets/{package-data-dv4FBHxR.js → package-data-CKPmBDtg.js} +1 -1
- package/dist/assets/packages-panel-gBE2FWQr.js +1 -0
- package/dist/assets/{panel-accordion-state-C1sdPp0m.js → panel-accordion-state-CCF5Gxnc.js} +1 -1
- package/dist/assets/panels-Dr6qMCvU.js +105 -0
- package/dist/assets/precisionRound-BxlUs8G4.js +1 -0
- package/dist/assets/process-output-Cw9IDcKQ.js +1 -0
- package/dist/assets/{quadrantDiagram-AXDQQJYC-yBhCDI7E.js → quadrantDiagram-AXDQQJYC-D9KH5Zge.js} +1 -1
- package/dist/assets/react-vega-BTNeboR2.js +189 -0
- package/dist/assets/{readonly-code-display-Do50PHI8.js → readonly-code-display-DYcZQ28T.js} +1 -1
- package/dist/assets/{readonly-python-code-DCSMIsTX.js → readonly-python-code-RFuQP50v.js} +1 -1
- package/dist/assets/{renderShortcut-BkVJQ_Zh.js → renderShortcut-rUwGqKgC.js} +1 -1
- package/dist/assets/{requests-lt0JK8Jt.js → requests-BIFR-h4M.js} +1 -1
- package/dist/assets/requests-DuLJN9Tf.js +1 -0
- package/dist/assets/{reveal-component-ltaepAqw.js → reveal-component-yRrDmCQz.js} +37 -37
- package/dist/assets/run-page-B69M4-zE.js +1 -0
- package/dist/assets/{runs-BLp5jezv.js → runs-C49hleBy.js} +1 -1
- package/dist/assets/{runtime-details-state-CSPobEdR.js → runtime-details-state-pobtu6TO.js} +1 -1
- package/dist/assets/{save-worker-BbUSwZRG.js → save-worker-pCkSHhuz.js} +1 -1
- package/dist/assets/{schemas-Dv42wLFq.js → schemas-ChRqMOTL.js} +1 -1
- package/dist/assets/scratchpad-panel-H44_pvb_.js +1 -0
- package/dist/assets/{scroll-to-bottom-button-1FyowpWV.js → scroll-to-bottom-button-CIkON2WJ.js} +1 -1
- package/dist/assets/{secrets-panel-Bctbtkrp.js → secrets-panel-bcfEKxRx.js} +1 -1
- package/dist/assets/{select-DTBn5eTb.js → select-3CVGlYrC.js} +1 -1
- package/dist/assets/{session-DqoWmb7X.js → session-CMLIzZKw.js} +1 -1
- package/dist/assets/session-panel-Bnd1iXkO.js +1 -0
- package/dist/assets/{snippets-panel-Bh1oTw4m.js → snippets-panel-DKApxKx9.js} +1 -1
- package/dist/assets/{spec-BfSBcO5B.js → spec-uCpVvaAR.js} +1 -1
- package/dist/assets/{state-uwRvJLb8.js → state-3mcyTS9q.js} +1 -1
- package/dist/assets/state-B_MCKzBL.js +1 -0
- package/dist/assets/state-Bl9BiY_s.js +3 -0
- package/dist/assets/{state-C3oDoyFe.js → state-C5WAeuTu.js} +1 -1
- package/dist/assets/{state-DxQnC_1I.js → state-Cv2JW3l9.js} +1 -1
- package/dist/assets/{state-XsPO8hNi.js → state-Dv059B3A.js} +1 -1
- package/dist/assets/{strings-B2vv-ENv.js → strings-C25fhMR_.js} +1 -1
- package/dist/assets/{swiper-component-a07domrZ.js → swiper-component-CRGRy5_O.js} +1 -1
- package/dist/assets/{switch-CTaiAjrz.js → switch-DYjBfpNJ.js} +1 -1
- package/dist/assets/{tabs-BuQlZFbt.js → tabs-CY8E4r9U.js} +1 -1
- package/dist/assets/{terminal-Ck_vK-34.js → terminal-Ca-kubKb.js} +1 -1
- package/dist/assets/{time-MgToa8VM.js → time-DswSXBDk.js} +1 -1
- package/dist/assets/{toast-BGzLGnvw.js → toast-Gzxi-le_.js} +1 -1
- package/dist/assets/tooltip-Brya4Ghn.js +61 -0
- package/dist/assets/{tooltip-C9TuY18o.js → tooltip-CkGm8X7m.js} +1 -1
- package/dist/assets/tracing-Clwy4SlW.js +1 -0
- package/dist/assets/tracing-panel-BwjLG_aC.js +2 -0
- package/dist/assets/{tree-actions-GM5E_bUs.js → tree-actions-BZNTQ12N.js} +1 -1
- package/dist/assets/{use-restore-focus-BxEGwIbk.js → use-restore-focus-DdS7Tl0F.js} +1 -1
- package/dist/assets/{useAddCell-GR7eEQrT.js → useAddCell-Cjuqk2YR.js} +1 -1
- package/dist/assets/useAsyncData-qvoPYHtx.js +1 -0
- package/dist/assets/useBoolean-Dd2nWXFJ.js +1 -0
- package/dist/assets/useCellActionButton-MoWLvuGe.js +1 -0
- package/dist/assets/useDebounce-DwTQ_1Pu.js +1 -0
- package/dist/assets/{useDeepCompareMemoize-DFIVN9dn.js → useDeepCompareMemoize-B2DVK2De.js} +1 -1
- package/dist/assets/useDelayElapsed-BlsDT4TV.js +1 -0
- package/dist/assets/{useDeleteCell-2_bMClHd.js → useDeleteCell-BC-MW7d1.js} +1 -1
- package/dist/assets/{useDependencyPanelTab-k3C3M18S.js → useDependencyPanelTab-CZU7i-B3.js} +1 -1
- package/dist/assets/{useEvent-Dfcbgjhg.js → useEvent-BDjgaBtz.js} +1 -1
- package/dist/assets/{useEventListener-D9cftcHj.js → useEventListener-CjDeLqFC.js} +1 -1
- package/dist/assets/{useIframeCapabilities-CwTkczVN.js → useIframeCapabilities-Czr9e4uG.js} +1 -1
- package/dist/assets/{useInstallPackage-iX1eufdl.js → useInstallPackage-wcDq9hYT.js} +1 -1
- package/dist/assets/{useInterval--x3s1VpI.js → useInterval-DJdQmXnq.js} +1 -1
- package/dist/assets/useNotebookActions-wFxVdRXQ.js +1 -0
- package/dist/assets/{useRunCells-B2vUhREg.js → useRunCells-ByaWxoIt.js} +1 -1
- package/dist/assets/{useSplitCell-DEb03htp.js → useSplitCell-YJIystwv.js} +1 -1
- package/dist/assets/useStateForKey-CGMJQT8x.js +1 -0
- package/dist/assets/{useTheme-COhSHkCj.js → useTheme-BAA27lh7.js} +1 -1
- package/dist/assets/{utils-CaQYvazl.js → utils-DfElfBpz.js} +1 -1
- package/dist/assets/vega-component-BeyxAJad.js +1 -0
- package/dist/assets/{vega-embed-container-DJPNkHPb.js → vega-embed-container-DtArSJz1.js} +1 -1
- package/dist/assets/vega-loader.browser-Bu25TKax.js +6 -0
- package/dist/assets/{worker-DTQ7oH2A.js → worker-bSCjCvwz.js} +1 -1
- package/dist/assets/{write-secret-modal-DzKAInL2.js → write-secret-modal-BEx-EUlh.js} +1 -1
- package/dist/assets/{xychartDiagram-S5SC5T6Z-KbGzG6-u.js → xychartDiagram-S5SC5T6Z-CeRnBS5e.js} +1 -1
- package/dist/index.html +80 -79
- package/package.json +8 -5
- package/src/__tests__/fixtures/{pair-preview.ts → pair-config.ts} +3 -2
- package/src/__tests__/host-imports.test.ts +101 -0
- package/src/__tests__/mount.test.ts +8 -8
- 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__/state.test.ts +2 -2
- package/src/components/chat/acp/blocks.tsx +2 -2
- 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/__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__/context-menu.test.ts +176 -0
- package/src/components/data-table/__tests__/date-filter-inputs.test.tsx +24 -1
- package/src/components/data-table/__tests__/date-popover.test.tsx +72 -0
- package/src/components/data-table/__tests__/export-actions.test.tsx +434 -6
- 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__/storage.test.ts +4 -1
- package/src/components/data-table/charts/charts.tsx +35 -25
- 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/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 +161 -46
- package/src/components/data-table/data-table.tsx +7 -1
- package/src/components/data-table/date-filter-inputs.tsx +15 -42
- package/src/components/data-table/date-popover.tsx +6 -4
- package/src/components/data-table/export-actions.tsx +267 -163
- package/src/components/data-table/row-viewer-panel/row-viewer.tsx +2 -2
- package/src/components/data-table/schemas.ts +14 -36
- 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/data-table/utils.ts +18 -0
- package/src/components/datasources/__tests__/column-actions.test.tsx +97 -0
- package/src/components/datasources/__tests__/column-preview.test.tsx +63 -2
- package/src/components/datasources/__tests__/table-list.test.tsx +118 -0
- package/src/components/datasources/column-preview.tsx +8 -2
- package/src/components/datasources/datasources.tsx +47 -35
- package/src/components/debugger/debugger-code.tsx +5 -0
- package/src/components/dependency-graph/panels.tsx +2 -1
- package/src/components/editor/Output.tsx +9 -2
- package/src/components/editor/SortableCell.tsx +1 -3
- package/src/components/editor/__tests__/dynamic-favicon.test.tsx +111 -18
- package/src/components/editor/actions/__tests__/pair-with-agent-commands.test.ts +80 -252
- package/src/components/editor/actions/__tests__/pair-with-agent-modal.test.tsx +210 -34
- package/src/components/editor/actions/pair-with-agent-commands.ts +42 -51
- package/src/components/editor/actions/pair-with-agent-modal.tsx +100 -37
- 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/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/error-panel.tsx +1 -0
- package/src/components/editor/chrome/panels/packages-panel.tsx +4 -7
- package/src/components/editor/chrome/wrapper/__tests__/attachment-status.test.tsx +366 -0
- package/src/components/editor/chrome/wrapper/__tests__/pending-ai-cells.test.tsx +58 -1
- package/src/components/editor/chrome/wrapper/footer-item.tsx +32 -24
- package/src/components/editor/chrome/wrapper/footer-items/attachment-status.tsx +237 -0
- package/src/components/editor/chrome/wrapper/footer-items/runtime-settings.tsx +1 -7
- package/src/components/editor/chrome/wrapper/footer.tsx +2 -0
- 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/command-palette.tsx +22 -10
- package/src/components/editor/dynamic-favicon.tsx +21 -40
- package/src/components/editor/errors/__tests__/send-error-report-button.test.tsx +537 -0
- package/src/components/editor/errors/send-error-report-button.tsx +69 -0
- package/src/components/editor/file-tree/__tests__/file-explorer-interactions.test.tsx +6 -0
- package/src/components/editor/file-tree/__tests__/use-file-search.test.tsx +91 -0
- package/src/components/editor/file-tree/file-explorer.tsx +10 -5
- 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/notebook-banner.tsx +1 -0
- package/src/components/editor/output/MarimoErrorOutput.tsx +21 -5
- package/src/components/editor/output/MarimoTracebackOutput.tsx +37 -22
- package/src/components/editor/output/__tests__/ansi-reduce.test.ts +18 -0
- package/src/components/editor/output/ansi-reduce.ts +12 -0
- package/src/components/editor/output/console/ConsoleOutput.tsx +19 -25
- package/src/components/editor/package-alert.tsx +6 -4
- 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.tsx +2 -2
- 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.tsx +2 -2
- package/src/components/ui/alert-dialog.tsx +1 -1
- package/src/core/ai/context/providers/datasource.ts +6 -2
- package/src/core/attachments/__tests__/toast.test.tsx +58 -0
- package/src/core/attachments/state.ts +18 -0
- package/src/core/attachments/toast.ts +15 -0
- 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 +55 -1
- package/src/core/cells/__tests__/collapseConsoleOutputs.test.ts +54 -0
- package/src/core/cells/__tests__/error-report.test.ts +139 -0
- package/src/core/cells/__tests__/notebook-outline.test.ts +113 -0
- package/src/core/cells/__tests__/session.test.ts +50 -1
- package/src/core/cells/cell.ts +14 -3
- package/src/core/cells/cells.ts +3 -1
- package/src/core/cells/error-report.ts +63 -0
- package/src/core/cells/pending-delete-service.ts +2 -6
- package/src/core/cells/session.ts +29 -2
- package/src/core/cells/types.ts +10 -1
- package/src/core/codemirror/__tests__/setup.test.ts +1 -1
- package/src/core/codemirror/keymaps/vim.ts +2 -6
- package/src/core/codemirror/language/languages/markdown.ts +1 -1
- package/src/core/codemirror/language/languages/python.ts +3 -3
- package/src/core/codemirror/language/panel/panel.tsx +1 -0
- package/src/core/config/pair.ts +5 -3
- 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__/draft.test.ts +322 -0
- package/src/core/document/__tests__/fixtures.ts +92 -0
- package/src/core/document/__tests__/model.test.ts +483 -0
- package/src/core/document/__tests__/state.test.ts +446 -0
- package/src/core/document/__tests__/submission.test.ts +346 -0
- package/src/core/document/draft.ts +472 -0
- package/src/core/document/index.ts +10 -0
- package/src/core/document/model.ts +53 -0
- package/src/core/document/state.ts +401 -0
- package/src/core/document/sync.ts +359 -0
- package/src/core/edit-app.tsx +2 -2
- package/src/core/host/AGENTS.md +16 -0
- 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 +41 -0
- package/src/core/host/__tests__/notebook-client.test.ts +570 -0
- package/src/core/host/connection.ts +42 -0
- package/src/core/host/notebook-client.ts +297 -0
- package/src/core/host/resources/attachments.ts +22 -0
- package/src/core/host/resources/document.ts +101 -0
- package/src/core/hotkeys/actions.ts +2 -4
- 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/run-app.tsx +2 -2
- package/src/core/runtime/__tests__/createWsUrl.test.ts +77 -7
- package/src/core/runtime/__tests__/runtime.test.ts +18 -17
- package/src/core/runtime/runtime.ts +26 -30
- package/src/core/state/__tests__/jotai.test.tsx +108 -0
- package/src/core/state/jotai.ts +1 -1
- package/src/core/static/files.ts +2 -0
- package/src/core/wasm/bridge.ts +2 -10
- package/src/core/wasm/store.ts +3 -3
- package/src/core/wasm/worker/bootstrap.ts +1 -1
- package/src/core/wasm/worker/getMarimoWheel.ts +1 -1
- package/src/core/websocket/__tests__/{useMarimoKernelConnection.test.ts → connection-state.test.ts} +15 -29
- package/src/core/websocket/__tests__/useNotebookClient.hook.test.tsx +223 -0
- package/src/core/websocket/__tests__/{useMarimoKernelConnection.hook.test.tsx → useNotebookSession.hook.test.tsx} +194 -184
- package/src/core/websocket/connection-state.ts +60 -0
- package/src/core/websocket/state.ts +7 -0
- package/src/core/websocket/transports/__tests__/notebook.test.ts +502 -0
- package/src/core/websocket/transports/notebook.ts +213 -0
- package/src/core/websocket/types.ts +9 -39
- package/src/core/websocket/useNotebookClient.ts +89 -0
- package/src/core/websocket/{useMarimoKernelConnection.tsx → useNotebookSession.tsx} +53 -224
- 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 +5 -8
- package/src/hooks/useDeepCompareMemoize.ts +1 -1
- package/src/hooks/useDelayElapsed.ts +14 -10
- package/src/hooks/useElapsedTime.ts +3 -3
- 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 +3 -3
- package/src/plugins/core/registerReactComponent.tsx +1 -1
- package/src/plugins/impl/CodeEditorPlugin.tsx +1 -1
- package/src/plugins/impl/DataTablePlugin.tsx +14 -15
- 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 +0 -1
- package/src/plugins/impl/RefreshPlugin.tsx +1 -0
- package/src/plugins/impl/SliderPlugin.tsx +6 -8
- package/src/plugins/impl/__tests__/DataTablePlugin.test.tsx +201 -1
- package/src/plugins/impl/__tests__/FileBrowserPlugin.test.tsx +45 -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 +12 -10
- 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/state/reducer.ts +1 -1
- package/src/plugins/impl/data-frames/DataFramePlugin.tsx +0 -1
- 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/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__/dates.test.ts +116 -0
- package/src/utils/__tests__/numbers.test.ts +48 -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/dates.ts +94 -0
- package/src/utils/numbers.ts +28 -17
- package/src/utils/objects.ts +3 -7
- package/src/utils/once.ts +19 -19
- package/src/utils/zod-utils.ts +1 -3
- package/dist/assets/CellStatus-BP2mavAq.js +0 -1
- package/dist/assets/JsonOutput-D6HIIsCb.js +0 -11
- package/dist/assets/MarimoErrorOutput-D60XkCny.js +0 -6
- package/dist/assets/RunButton-CK3LhnP5.js +0 -1
- package/dist/assets/__vite-browser-external-CYO_P3S8.js +0 -1
- package/dist/assets/__vite-browser-external-FeDVGZU8.js +0 -1
- package/dist/assets/ai-model-dropdown-B0z6-zhp.js +0 -5
- package/dist/assets/any-language-editor-BLCAD3yx.js +0 -1
- package/dist/assets/api-BeC_VSGv.js +0 -1
- package/dist/assets/arrays-BqUx5USx.js +0 -1
- package/dist/assets/cell-editor-ADVfycpN.js +0 -21
- package/dist/assets/cell-link-LSth_8hT.js +0 -1
- package/dist/assets/chat-panel-DQ6HkWEF.js +0 -4
- package/dist/assets/chat-ui-Df8Vcj6n.js +0 -4
- package/dist/assets/circle-play-CYIb0qT6.js +0 -1
- package/dist/assets/code-visibility-B-_GvwR5.js +0 -1
- package/dist/assets/coerce-CpE6kUdX.js +0 -1
- package/dist/assets/column-preview-Cm2D6vyX.js +0 -1
- package/dist/assets/command-palette-DTSQ7gOC.js +0 -1
- package/dist/assets/components-CXfO-F47.js +0 -1
- package/dist/assets/config-BOKzA3tF.js +0 -1
- package/dist/assets/config-DX8Y2WbJ.js +0 -1
- package/dist/assets/config-VPSq73n8.js +0 -1
- package/dist/assets/edit-page-ChcSgpke.js +0 -9
- package/dist/assets/feedback-button-B2gKC5cn.js +0 -1
- package/dist/assets/file-explorer-panel-BEEK5lcl.js +0 -1
- package/dist/assets/home-page-DMHnsRxm.js +0 -4
- package/dist/assets/index-Bcdzex-3.css +0 -2
- package/dist/assets/index-s-M1OXjs.js +0 -29
- package/dist/assets/kiosk-mode-BZECfg9k.js +0 -1
- package/dist/assets/layout-DmcNEu3P.js +0 -9
- package/dist/assets/linear-0eij_aAG.js +0 -1
- package/dist/assets/link-NuFVR7G9.js +0 -1
- package/dist/assets/links-DkkL9DVa.js +0 -1
- package/dist/assets/numbers-Mk3-CcoU.js +0 -1
- package/dist/assets/packages-panel-BMGOmZkR.js +0 -1
- package/dist/assets/pair-CaQyK6En.js +0 -1
- package/dist/assets/panels-CxVG8-v2.js +0 -4
- package/dist/assets/precisionRound-Bq_nmf5u.js +0 -1
- package/dist/assets/process-output-D0KGq04R.js +0 -1
- package/dist/assets/react-vega-C3rYGtP6.js +0 -189
- package/dist/assets/requests-CgSY1X4a.js +0 -1
- package/dist/assets/run-page-DF3c5cDk.js +0 -1
- package/dist/assets/scratchpad-panel-Dwd6W5PE.js +0 -1
- package/dist/assets/session-panel-VdDhEBa-.js +0 -1
- package/dist/assets/state-BAJYRhmO.js +0 -1
- package/dist/assets/state-_Qai_QyX.js +0 -3
- package/dist/assets/tooltip-mT3CGest.js +0 -61
- package/dist/assets/tracing-Di6pUmX8.js +0 -1
- package/dist/assets/tracing-panel-PeRXHD8_.js +0 -2
- package/dist/assets/useAsyncData-C7aJJz0Y.js +0 -1
- package/dist/assets/useBoolean-BDD6_xQQ.js +0 -1
- package/dist/assets/useCellActionButton-B-9eG5z_.js +0 -1
- package/dist/assets/useDebounce-B_ccBZTp.js +0 -1
- package/dist/assets/useNotebookActions-NHN6A-cN.js +0 -1
- package/dist/assets/vega-component-CnadTgoE.js +0 -1
- package/dist/assets/vega-loader.browser-CLRkNgm7.js +0 -6
- package/dist/assets/ws-BXWY541V.js +0 -22
- package/src/core/state/__tests__/jotai.test.ts +0 -25
- package/src/core/websocket/__tests__/useWebSocket.test.ts +0 -49
- package/src/core/websocket/transports/__tests__/basic.test.ts +0 -275
- package/src/core/websocket/transports/__tests__/sse.test.ts +0 -338
- 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/sse.ts +0 -308
- package/src/core/websocket/transports/transport.ts +0 -61
- package/src/core/websocket/transports/ws.ts +0 -98
- package/src/core/websocket/useWebSocket.tsx +0 -88
|
@@ -201,11 +201,16 @@ export const FileExplorer: React.FC<{
|
|
|
201
201
|
() => filterHiddenTree(data, showHiddenFiles),
|
|
202
202
|
[data, showHiddenFiles],
|
|
203
203
|
);
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
204
|
+
const selectedFolderId = selectedFolder?.id;
|
|
205
|
+
const selectedFolderVisible = React.useMemo(
|
|
206
|
+
() =>
|
|
207
|
+
selectedFolderId === undefined ||
|
|
208
|
+
treeContainsId(visibleData, selectedFolderId),
|
|
209
|
+
[visibleData, selectedFolderId],
|
|
210
|
+
);
|
|
211
|
+
if (!selectedFolderVisible) {
|
|
212
|
+
setSelectedFolder(null);
|
|
213
|
+
}
|
|
209
214
|
const contextValue = React.useMemo<FileExplorerContextValue>(
|
|
210
215
|
() => ({
|
|
211
216
|
tree,
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
SaveIcon,
|
|
10
10
|
} from "lucide-react";
|
|
11
11
|
import type React from "react";
|
|
12
|
-
import { useEffect, useRef, useState } from "react";
|
|
12
|
+
import { useEffect, useLayoutEffect, useRef, useState } from "react";
|
|
13
13
|
import { renderShortcut } from "@/components/shortcuts/renderShortcut";
|
|
14
14
|
import { Alert, AlertDescription } from "@/components/ui/alert";
|
|
15
15
|
import { Button } from "@/components/ui/button";
|
|
@@ -82,7 +82,9 @@ export const FileViewer: React.FC<Props> = ({ file, onOpenNotebook }) => {
|
|
|
82
82
|
// carry no draft to preserve.
|
|
83
83
|
// We use a ref for internalValue so we don't call this effect on each keystroke
|
|
84
84
|
const internalValueRef = useRef<string>(internalValue);
|
|
85
|
-
|
|
85
|
+
useLayoutEffect(() => {
|
|
86
|
+
internalValueRef.current = internalValue;
|
|
87
|
+
}, [internalValue]);
|
|
86
88
|
useEffect(() => {
|
|
87
89
|
return () => {
|
|
88
90
|
if (
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
|
-
import { useCallback, useEffect, useRef, useState } from "react";
|
|
3
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
4
4
|
import { useRequestClient } from "@/core/network/requests";
|
|
5
5
|
import { useDebounce } from "@/hooks/useDebounce";
|
|
6
6
|
import {
|
|
@@ -34,20 +34,29 @@ export function useFileSearch({
|
|
|
34
34
|
}): { state: FileSearchState; refetch: () => void } {
|
|
35
35
|
const { sendSearchFiles } = useRequestClient();
|
|
36
36
|
const debouncedQuery = useDebounce(query, 300);
|
|
37
|
-
|
|
37
|
+
// Nullable so the ref is not built on every render
|
|
38
|
+
const pending = useRef<Promise<void> | null>(null);
|
|
38
39
|
const [revision, setRevision] = useState(0);
|
|
39
40
|
const refetch = useCallback(() => setRevision((value) => value + 1), []);
|
|
40
|
-
const
|
|
41
|
+
const requestIdentity = useMemo(
|
|
42
|
+
() => ({ query, tree, showHiddenFiles, revision, sendSearchFiles }),
|
|
43
|
+
[query, tree, showHiddenFiles, revision, sendSearchFiles],
|
|
44
|
+
);
|
|
45
|
+
const [result, setResult] = useState<{
|
|
46
|
+
requestIdentity: typeof requestIdentity;
|
|
47
|
+
state: FileSearchState;
|
|
48
|
+
}>();
|
|
41
49
|
|
|
42
50
|
useEffect(() => {
|
|
51
|
+
// Read inputs through requestIdentity so it alone drives new requests
|
|
52
|
+
const { query, tree, showHiddenFiles, sendSearchFiles } = requestIdentity;
|
|
43
53
|
let cancelled = false;
|
|
44
54
|
if (!query || query !== debouncedQuery) {
|
|
45
55
|
return;
|
|
46
56
|
}
|
|
47
|
-
setResult({ status: "loading", query });
|
|
48
57
|
// Let the in-flight server scan finish before starting another. Superseded
|
|
49
58
|
// queued queries and remaining roots are skipped, keeping scan work bounded.
|
|
50
|
-
const request = pending.current.then(async () => {
|
|
59
|
+
const request = (pending.current ?? Promise.resolve()).then(async () => {
|
|
51
60
|
const filesByPath = new Map<string, FileTreeNode>();
|
|
52
61
|
let rootLimitReached = false;
|
|
53
62
|
let failedRootCount = 0;
|
|
@@ -88,9 +97,12 @@ export function useFileSearch({
|
|
|
88
97
|
if (!cancelled) {
|
|
89
98
|
if (roots.length > 0 && failedRootCount === roots.length) {
|
|
90
99
|
setResult({
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
100
|
+
requestIdentity,
|
|
101
|
+
state: {
|
|
102
|
+
status: "error",
|
|
103
|
+
query,
|
|
104
|
+
error: new Error("Could not search any root"),
|
|
105
|
+
},
|
|
94
106
|
});
|
|
95
107
|
return;
|
|
96
108
|
}
|
|
@@ -110,33 +122,35 @@ export function useFileSearch({
|
|
|
110
122
|
rank(left) - rank(right) || left.name.localeCompare(right.name),
|
|
111
123
|
);
|
|
112
124
|
setResult({
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
125
|
+
requestIdentity,
|
|
126
|
+
state: {
|
|
127
|
+
status: "success",
|
|
128
|
+
isPartial: failedRootCount > 0,
|
|
129
|
+
query,
|
|
130
|
+
files: sortedFiles.slice(0, RESULT_LIMIT),
|
|
131
|
+
hasMore: rootLimitReached || sortedFiles.length > RESULT_LIMIT,
|
|
132
|
+
},
|
|
118
133
|
});
|
|
119
134
|
}
|
|
120
135
|
});
|
|
121
136
|
pending.current = request.catch((error: unknown) => {
|
|
122
137
|
if (!cancelled) {
|
|
123
|
-
setResult({
|
|
138
|
+
setResult({
|
|
139
|
+
requestIdentity,
|
|
140
|
+
state: { status: "error", query, error },
|
|
141
|
+
});
|
|
124
142
|
}
|
|
125
143
|
});
|
|
126
144
|
return () => {
|
|
127
145
|
cancelled = true;
|
|
128
146
|
};
|
|
129
|
-
}, [
|
|
147
|
+
}, [debouncedQuery, requestIdentity]);
|
|
130
148
|
|
|
131
149
|
if (!query) {
|
|
132
150
|
return { state: { status: "idle" }, refetch };
|
|
133
151
|
}
|
|
134
|
-
if (
|
|
135
|
-
query !== debouncedQuery ||
|
|
136
|
-
result.status === "idle" ||
|
|
137
|
-
result.query !== query
|
|
138
|
-
) {
|
|
152
|
+
if (query !== debouncedQuery || result?.requestIdentity !== requestIdentity) {
|
|
139
153
|
return { state: { status: "loading", query }, refetch };
|
|
140
154
|
}
|
|
141
|
-
return { state: result, refetch };
|
|
155
|
+
return { state: result.state, refetch };
|
|
142
156
|
}
|
|
@@ -21,8 +21,10 @@ import { Button } from "@/components/ui/button";
|
|
|
21
21
|
import { Kbd } from "@/components/ui/kbd";
|
|
22
22
|
import { ExternalLink } from "@/components/ui/links";
|
|
23
23
|
import { Tooltip } from "@/components/ui/tooltip";
|
|
24
|
+
import { buildErrorReport } from "@/core/cells/error-report";
|
|
24
25
|
import type { CellId } from "@/core/cells/ids";
|
|
25
26
|
import { resolvedMarimoConfigAtom } from "@/core/config/config";
|
|
27
|
+
import { viewStateAtom } from "@/core/mode";
|
|
26
28
|
import { renderHTML } from "@/plugins/core/RenderHTML";
|
|
27
29
|
import { splitMangledLocals } from "@/utils/local-variables";
|
|
28
30
|
import type { MarimoError } from "../../../core/kernel/messages";
|
|
@@ -32,6 +34,7 @@ import { openPackageManager } from "../chrome/panels/packages-utils";
|
|
|
32
34
|
import { useChromeActions } from "../chrome/state";
|
|
33
35
|
import { AutoFixButton } from "../errors/auto-fix";
|
|
34
36
|
import { MangledSegments } from "../errors/mangled-local-chip";
|
|
37
|
+
import { SendErrorReportButton } from "../errors/send-error-report-button";
|
|
35
38
|
import { CellLinkError } from "../links/cell-link";
|
|
36
39
|
import { processTextForUrls } from "./console/text-rendering";
|
|
37
40
|
|
|
@@ -93,6 +96,7 @@ const Tip = (props: {
|
|
|
93
96
|
interface Props {
|
|
94
97
|
cellId: CellId | undefined;
|
|
95
98
|
errors: MarimoError[];
|
|
99
|
+
code?: string;
|
|
96
100
|
className?: string;
|
|
97
101
|
}
|
|
98
102
|
|
|
@@ -102,6 +106,7 @@ interface Props {
|
|
|
102
106
|
export const MarimoErrorOutput = ({
|
|
103
107
|
errors,
|
|
104
108
|
cellId,
|
|
109
|
+
code,
|
|
105
110
|
className,
|
|
106
111
|
}: Props): JSX.Element => {
|
|
107
112
|
const chromeActions = useChromeActions();
|
|
@@ -111,6 +116,9 @@ export const MarimoErrorOutput = ({
|
|
|
111
116
|
// only helpful when outputs are displayed above the editor.
|
|
112
117
|
const showConsoleHint =
|
|
113
118
|
useAtomValue(resolvedMarimoConfigAtom).display.cell_output === "above";
|
|
119
|
+
// The editor shows tracebacks in the console area, so the inline copy is
|
|
120
|
+
// for views without a console: published apps and present mode.
|
|
121
|
+
const showInlineTraceback = useAtomValue(viewStateAtom).mode !== "edit";
|
|
114
122
|
|
|
115
123
|
let titleContents: string | null =
|
|
116
124
|
"This cell wasn't run because it has errors";
|
|
@@ -208,7 +216,6 @@ export const MarimoErrorOutput = ({
|
|
|
208
216
|
(e): e is Extract<MarimoError, { type: "sql-error" }> =>
|
|
209
217
|
e.type === "sql-error",
|
|
210
218
|
);
|
|
211
|
-
|
|
212
219
|
const openScratchpad = () => {
|
|
213
220
|
chromeActions.openApplication("scratchpad");
|
|
214
221
|
};
|
|
@@ -558,7 +565,9 @@ export const MarimoErrorOutput = ({
|
|
|
558
565
|
<p className="text-muted-foreground">
|
|
559
566
|
{processTextForUrls(error.msg, `exception-${idx}`)}
|
|
560
567
|
</p>
|
|
561
|
-
{
|
|
568
|
+
{showInlineTraceback &&
|
|
569
|
+
"traceback" in error &&
|
|
570
|
+
error.traceback ? (
|
|
562
571
|
<CollapsibleTraceback traceback={error.traceback} />
|
|
563
572
|
) : (
|
|
564
573
|
showConsoleHint && (
|
|
@@ -572,9 +581,11 @@ export const MarimoErrorOutput = ({
|
|
|
572
581
|
<div>
|
|
573
582
|
{processTextForUrls(error.msg, `exception-${idx}`)}
|
|
574
583
|
<CellLinkError cellId={error.raising_cell} />
|
|
575
|
-
{
|
|
576
|
-
|
|
577
|
-
|
|
584
|
+
{showInlineTraceback &&
|
|
585
|
+
"traceback" in error &&
|
|
586
|
+
error.traceback && (
|
|
587
|
+
<CollapsibleTraceback traceback={error.traceback} />
|
|
588
|
+
)}
|
|
578
589
|
</div>
|
|
579
590
|
)}
|
|
580
591
|
</li>
|
|
@@ -728,6 +739,11 @@ export const MarimoErrorOutput = ({
|
|
|
728
739
|
>
|
|
729
740
|
{title}
|
|
730
741
|
<div className="flex flex-col gap-4">{renderMessages()}</div>
|
|
742
|
+
{cellId && errors.length > 0 && (
|
|
743
|
+
<SendErrorReportButton
|
|
744
|
+
getContent={() => buildErrorReport(cellId, { code, errors })}
|
|
745
|
+
/>
|
|
746
|
+
)}
|
|
731
747
|
</Alert>
|
|
732
748
|
);
|
|
733
749
|
};
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
import { Kbd } from "@/components/ui/kbd";
|
|
23
23
|
import { Tooltip } from "@/components/ui/tooltip";
|
|
24
24
|
import { getCellEditorView } from "@/core/cells/cells";
|
|
25
|
+
import { buildErrorReport } from "@/core/cells/error-report";
|
|
25
26
|
import type { CellId } from "@/core/cells/ids";
|
|
26
27
|
import { SCRATCH_CELL_ID } from "@/core/cells/ids";
|
|
27
28
|
import { toggleBreakpoint } from "@/core/codemirror/cells/debugger-state";
|
|
@@ -34,6 +35,7 @@ import { isWasm } from "@/core/wasm/utils";
|
|
|
34
35
|
import { renderHTML } from "@/plugins/core/RenderHTML";
|
|
35
36
|
import { sanitizeHtml } from "@/plugins/core/sanitize-html";
|
|
36
37
|
import { copyToClipboard } from "@/utils/copy";
|
|
38
|
+
import { parseHtmlContent } from "@/utils/dom";
|
|
37
39
|
import {
|
|
38
40
|
containsMangledLocal,
|
|
39
41
|
splitMangledLocals,
|
|
@@ -46,33 +48,45 @@ import {
|
|
|
46
48
|
import { useOpenAiAssistant } from "../chrome/wrapper/useOpenAiAssistant";
|
|
47
49
|
import { AIFixButton, buildFixInChatPrompt } from "../errors/auto-fix";
|
|
48
50
|
import { MangledSegments } from "../errors/mangled-local-chip";
|
|
51
|
+
import { SendErrorReportButton } from "../errors/send-error-report-button";
|
|
49
52
|
import { CellLinkTraceback } from "../links/cell-link";
|
|
50
53
|
import type { OnRefactorWithAI } from "../Output";
|
|
51
54
|
|
|
52
55
|
interface Props {
|
|
53
56
|
cellId: CellId | undefined;
|
|
54
57
|
traceback: string;
|
|
58
|
+
tracebackFormat?: "html" | "text";
|
|
59
|
+
code?: string;
|
|
55
60
|
onRefactorWithAI?: OnRefactorWithAI;
|
|
56
61
|
}
|
|
57
62
|
|
|
58
|
-
/**
|
|
59
|
-
* List of errors due to violations of Marimo semantics.
|
|
60
|
-
*/
|
|
63
|
+
/** Render a traceback and actions for its captured execution. */
|
|
61
64
|
export const MarimoTracebackOutput = ({
|
|
62
65
|
onRefactorWithAI,
|
|
63
66
|
traceback,
|
|
67
|
+
tracebackFormat = "html",
|
|
64
68
|
cellId,
|
|
69
|
+
code,
|
|
65
70
|
}: Props): JSX.Element => {
|
|
66
|
-
const htmlTraceback =
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
71
|
+
const htmlTraceback =
|
|
72
|
+
tracebackFormat === "text" ? (
|
|
73
|
+
<pre>{traceback}</pre>
|
|
74
|
+
) : (
|
|
75
|
+
renderHTML({
|
|
76
|
+
html: traceback,
|
|
77
|
+
additionalReplacements: [
|
|
78
|
+
replaceTracebackFilenames,
|
|
79
|
+
replaceTracebackPrefix,
|
|
80
|
+
replaceMangledLocal,
|
|
81
|
+
],
|
|
82
|
+
})
|
|
83
|
+
);
|
|
74
84
|
|
|
75
|
-
const
|
|
85
|
+
const textTraceback =
|
|
86
|
+
tracebackFormat === "html"
|
|
87
|
+
? parseHtmlContent(sanitizeHtml(traceback))
|
|
88
|
+
: traceback;
|
|
89
|
+
const lastTracebackLine = lastLine(textTraceback);
|
|
76
90
|
const aiFeaturesEnabled = useAtomValue(aiFeaturesEnabledAtom);
|
|
77
91
|
const openAiAssistant = useOpenAiAssistant();
|
|
78
92
|
|
|
@@ -131,6 +145,13 @@ export const MarimoTracebackOutput = ({
|
|
|
131
145
|
</div>
|
|
132
146
|
)}
|
|
133
147
|
<div className="flex gap-2">
|
|
148
|
+
{cellId && lastTracebackLine && (
|
|
149
|
+
<SendErrorReportButton
|
|
150
|
+
getContent={() =>
|
|
151
|
+
buildErrorReport(cellId, { code, traceback, tracebackFormat })
|
|
152
|
+
}
|
|
153
|
+
/>
|
|
154
|
+
)}
|
|
134
155
|
{showAIFix && (
|
|
135
156
|
<AIFixButton
|
|
136
157
|
tooltip="Fix with AI"
|
|
@@ -186,11 +207,7 @@ export const MarimoTracebackOutput = ({
|
|
|
186
207
|
</DropdownMenuItem>
|
|
187
208
|
<DropdownMenuItem
|
|
188
209
|
onClick={() => {
|
|
189
|
-
|
|
190
|
-
const div = document.createElement("div");
|
|
191
|
-
div.innerHTML = sanitizeHtml(traceback);
|
|
192
|
-
const textContent = div.textContent || "";
|
|
193
|
-
copyToClipboard(textContent);
|
|
210
|
+
copyToClipboard(textTraceback);
|
|
194
211
|
}}
|
|
195
212
|
>
|
|
196
213
|
<CopyIcon className="h-4 w-4 mr-2" />
|
|
@@ -205,9 +222,7 @@ export const MarimoTracebackOutput = ({
|
|
|
205
222
|
};
|
|
206
223
|
|
|
207
224
|
function lastLine(text: string): string {
|
|
208
|
-
const
|
|
209
|
-
el.innerHTML = sanitizeHtml(text);
|
|
210
|
-
const lines = el.textContent?.split("\n").filter(Boolean);
|
|
225
|
+
const lines = text.split("\n").filter(Boolean);
|
|
211
226
|
return lines?.at(-1) || "";
|
|
212
227
|
}
|
|
213
228
|
|
|
@@ -233,7 +248,7 @@ export const replaceTracebackFilenames = (domNode: DOMNode) => {
|
|
|
233
248
|
<Tooltip content={tooltipContent}>
|
|
234
249
|
<button
|
|
235
250
|
type="button"
|
|
236
|
-
className="ml-1 p-1 rounded-sm hover:bg-muted transition-
|
|
251
|
+
className="ml-1 p-1 rounded-sm hover:bg-muted transition-colors inline"
|
|
237
252
|
>
|
|
238
253
|
<BugPlayIcon
|
|
239
254
|
onClick={() => {
|
|
@@ -259,7 +274,7 @@ export const replaceTracebackFilenames = (domNode: DOMNode) => {
|
|
|
259
274
|
return (
|
|
260
275
|
<div
|
|
261
276
|
className="inline-block cursor-pointer text-destructive hover:underline"
|
|
262
|
-
onClick={(
|
|
277
|
+
onClick={() => {
|
|
263
278
|
getRequestClient().openFile({
|
|
264
279
|
path: info.filePath,
|
|
265
280
|
lineNumber: info.lineNumber,
|
|
@@ -7,6 +7,24 @@ import {
|
|
|
7
7
|
TerminalBuffer,
|
|
8
8
|
} from "../ansi-reduce";
|
|
9
9
|
|
|
10
|
+
test("preserves source evidence through stateful output and serialization", () => {
|
|
11
|
+
const output = StatefulOutputMessage.create({
|
|
12
|
+
channel: "stderr",
|
|
13
|
+
mimetype: "application/vnd.marimo+traceback",
|
|
14
|
+
timestamp: 1,
|
|
15
|
+
data: "<pre>ValueError:",
|
|
16
|
+
code: "raise ValueError('failed code')",
|
|
17
|
+
}).appendData(" failed code</pre>");
|
|
18
|
+
expect(output.code).toBe("raise ValueError('failed code')");
|
|
19
|
+
expect(output.toJSON()).toEqual({
|
|
20
|
+
channel: "stderr",
|
|
21
|
+
mimetype: "application/vnd.marimo+traceback",
|
|
22
|
+
timestamp: 1,
|
|
23
|
+
data: "<pre>ValueError: failed code</pre>",
|
|
24
|
+
code: "raise ValueError('failed code')",
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
10
28
|
describe("TerminalBuffer", () => {
|
|
11
29
|
test("writeChar writes single character", () => {
|
|
12
30
|
const buffer = new TerminalBuffer();
|
|
@@ -358,6 +358,7 @@ export class AnsiReducer {
|
|
|
358
358
|
|
|
359
359
|
export type StringOutputMessage = Omit<OutputMessage, "data"> & {
|
|
360
360
|
data: string;
|
|
361
|
+
id?: number;
|
|
361
362
|
};
|
|
362
363
|
|
|
363
364
|
/**
|
|
@@ -368,6 +369,8 @@ export class StatefulOutputMessage implements OutputMessage {
|
|
|
368
369
|
public readonly mimetype: OutputMessage["mimetype"];
|
|
369
370
|
public readonly channel: OutputMessage["channel"];
|
|
370
371
|
public readonly timestamp: OutputMessage["timestamp"];
|
|
372
|
+
public readonly code: OutputMessage["code"];
|
|
373
|
+
public readonly id: StringOutputMessage["id"];
|
|
371
374
|
private ansiReducer = new AnsiReducer();
|
|
372
375
|
private _data: string;
|
|
373
376
|
|
|
@@ -383,6 +386,8 @@ export class StatefulOutputMessage implements OutputMessage {
|
|
|
383
386
|
message.channel,
|
|
384
387
|
message.timestamp,
|
|
385
388
|
ansiReducer,
|
|
389
|
+
message.code,
|
|
390
|
+
message.id,
|
|
386
391
|
);
|
|
387
392
|
}
|
|
388
393
|
|
|
@@ -391,10 +396,14 @@ export class StatefulOutputMessage implements OutputMessage {
|
|
|
391
396
|
channel: OutputMessage["channel"],
|
|
392
397
|
timestamp: OutputMessage["timestamp"],
|
|
393
398
|
ansiReducer: AnsiReducer,
|
|
399
|
+
code: OutputMessage["code"],
|
|
400
|
+
id: StringOutputMessage["id"],
|
|
394
401
|
) {
|
|
395
402
|
this.mimetype = mimetype;
|
|
396
403
|
this.channel = channel;
|
|
397
404
|
this.timestamp = timestamp;
|
|
405
|
+
this.code = code;
|
|
406
|
+
this.id = id;
|
|
398
407
|
this.ansiReducer = ansiReducer;
|
|
399
408
|
this._data = this.ansiReducer.render();
|
|
400
409
|
}
|
|
@@ -406,6 +415,8 @@ export class StatefulOutputMessage implements OutputMessage {
|
|
|
406
415
|
this.channel,
|
|
407
416
|
this.timestamp,
|
|
408
417
|
this.ansiReducer,
|
|
418
|
+
this.code,
|
|
419
|
+
this.id,
|
|
409
420
|
);
|
|
410
421
|
}
|
|
411
422
|
|
|
@@ -415,6 +426,7 @@ export class StatefulOutputMessage implements OutputMessage {
|
|
|
415
426
|
channel: this.channel,
|
|
416
427
|
timestamp: this.timestamp,
|
|
417
428
|
data: this.data,
|
|
429
|
+
...(this.code === undefined ? {} : { code: this.code }),
|
|
418
430
|
};
|
|
419
431
|
}
|
|
420
432
|
}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
ChevronsUpDownIcon,
|
|
7
7
|
WrapTextIcon,
|
|
8
8
|
} from "lucide-react";
|
|
9
|
-
import React, { useEffect, useLayoutEffect,
|
|
9
|
+
import React, { useEffect, useLayoutEffect, useState } from "react";
|
|
10
10
|
import { ToggleButton } from "react-aria-components";
|
|
11
11
|
import { DebuggerControls } from "@/components/debugger/debugger-code";
|
|
12
12
|
import { CopyClipboardIcon } from "@/components/icons/copy-icon";
|
|
@@ -16,8 +16,7 @@ import { Tooltip } from "@/components/ui/tooltip";
|
|
|
16
16
|
import type { CellId } from "@/core/cells/ids";
|
|
17
17
|
import { isInternalCellName } from "@/core/cells/names";
|
|
18
18
|
import { useExpandedConsoleOutput } from "@/core/cells/outputs";
|
|
19
|
-
import type {
|
|
20
|
-
import type { OutputMessage } from "@/core/kernel/messages";
|
|
19
|
+
import type { ConsoleOutputMessage } from "@/core/cells/types";
|
|
21
20
|
import {
|
|
22
21
|
type UseInputHistoryReturn,
|
|
23
22
|
useInputHistory,
|
|
@@ -49,31 +48,21 @@ export const CONSOLE_CLEAR_DEBOUNCE_MS = 200;
|
|
|
49
48
|
*/
|
|
50
49
|
function useDebouncedConsoleOutputs<T>(outputs: T[]): T[] {
|
|
51
50
|
const [debouncedOutputs, setDebouncedOutputs] = useState(outputs);
|
|
52
|
-
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
53
51
|
|
|
54
|
-
// Non-empty outputs: apply immediately
|
|
52
|
+
// Non-empty outputs: apply immediately. Effect cleanup cancels pending clears.
|
|
55
53
|
if (outputs.length > 0 && debouncedOutputs !== outputs) {
|
|
56
|
-
if (timerRef.current !== null) {
|
|
57
|
-
clearTimeout(timerRef.current);
|
|
58
|
-
timerRef.current = null;
|
|
59
|
-
}
|
|
60
54
|
setDebouncedOutputs(outputs);
|
|
61
55
|
}
|
|
62
56
|
|
|
63
57
|
// Empty outputs: delay the clear so new outputs can arrive first
|
|
64
58
|
useEffect(() => {
|
|
65
|
-
if (outputs.length
|
|
66
|
-
|
|
67
|
-
timerRef.current = null;
|
|
68
|
-
setDebouncedOutputs([]);
|
|
69
|
-
}, CONSOLE_CLEAR_DEBOUNCE_MS);
|
|
59
|
+
if (outputs.length > 0) {
|
|
60
|
+
return;
|
|
70
61
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
};
|
|
62
|
+
const timer = setTimeout(() => {
|
|
63
|
+
setDebouncedOutputs([]);
|
|
64
|
+
}, CONSOLE_CLEAR_DEBOUNCE_MS);
|
|
65
|
+
return () => clearTimeout(timer);
|
|
77
66
|
}, [outputs]);
|
|
78
67
|
|
|
79
68
|
return debouncedOutputs;
|
|
@@ -83,7 +72,7 @@ interface Props {
|
|
|
83
72
|
cellId: CellId;
|
|
84
73
|
cellName: string;
|
|
85
74
|
className?: string;
|
|
86
|
-
consoleOutputs:
|
|
75
|
+
consoleOutputs: ConsoleOutputMessage[];
|
|
87
76
|
stale: boolean;
|
|
88
77
|
interrupted: boolean;
|
|
89
78
|
debuggerActive: boolean;
|
|
@@ -251,19 +240,24 @@ const ConsoleOutputInternal = (props: Props): React.ReactNode => {
|
|
|
251
240
|
return null;
|
|
252
241
|
}
|
|
253
242
|
|
|
243
|
+
const originalIdx = consoleOutputs.length - idx - 1;
|
|
244
|
+
// Outputs render in reverse, so the reversed index shifts on every
|
|
245
|
+
// new line. The assigned id survives collapse and truncation. The
|
|
246
|
+
// original position is the fallback for outputs without one.
|
|
247
|
+
const key = output.id ?? `position-${originalIdx}`;
|
|
248
|
+
|
|
254
249
|
if (output.channel === "stdin") {
|
|
255
250
|
invariant(
|
|
256
251
|
typeof output.data === "string",
|
|
257
252
|
"Expected data to be a string",
|
|
258
253
|
);
|
|
259
254
|
|
|
260
|
-
const originalIdx = consoleOutputs.length - idx - 1;
|
|
261
255
|
const isPassword = output.mimetype === "text/password";
|
|
262
256
|
|
|
263
257
|
if (output.response == null && lastStdInputIdx === idx) {
|
|
264
258
|
return (
|
|
265
259
|
<StdInput
|
|
266
|
-
key={
|
|
260
|
+
key={key}
|
|
267
261
|
output={output.data}
|
|
268
262
|
isPdb={isPdb}
|
|
269
263
|
isPassword={isPassword}
|
|
@@ -278,7 +272,7 @@ const ConsoleOutputInternal = (props: Props): React.ReactNode => {
|
|
|
278
272
|
|
|
279
273
|
return (
|
|
280
274
|
<StdInputWithResponse
|
|
281
|
-
key={
|
|
275
|
+
key={key}
|
|
282
276
|
output={output.data}
|
|
283
277
|
response={output.response}
|
|
284
278
|
isPassword={isPassword}
|
|
@@ -288,7 +282,7 @@ const ConsoleOutputInternal = (props: Props): React.ReactNode => {
|
|
|
288
282
|
}
|
|
289
283
|
|
|
290
284
|
return (
|
|
291
|
-
<React.Fragment key={
|
|
285
|
+
<React.Fragment key={key}>
|
|
292
286
|
<OutputRenderer
|
|
293
287
|
cellId={cellId}
|
|
294
288
|
onRefactorWithAI={onRefactorWithAI}
|
|
@@ -158,6 +158,7 @@ export const PackageAlert: React.FC = () => {
|
|
|
158
158
|
<SourceBadge source={packageAlert.source} />
|
|
159
159
|
</span>
|
|
160
160
|
<Button
|
|
161
|
+
aria-label="Dismiss missing packages alert"
|
|
161
162
|
variant="text"
|
|
162
163
|
data-testid="remove-banner-button"
|
|
163
164
|
size="icon"
|
|
@@ -171,12 +172,12 @@ export const PackageAlert: React.FC = () => {
|
|
|
171
172
|
<p>The following packages were not found:</p>
|
|
172
173
|
<table className="list-disc ml-2 mt-1">
|
|
173
174
|
<tbody>
|
|
174
|
-
{packageAlert.packages.map((pkg
|
|
175
|
+
{packageAlert.packages.map((pkg) => {
|
|
175
176
|
const parsed = parsePackageSpecifier(pkg);
|
|
176
177
|
const currentExtras = selectedExtras[pkg] || parsed.extras;
|
|
177
178
|
|
|
178
179
|
return (
|
|
179
|
-
<tr className="font-mono text-sm" key={
|
|
180
|
+
<tr className="font-mono text-sm" key={pkg}>
|
|
180
181
|
<td className="pr-2 py-1 align-middle">
|
|
181
182
|
<BoxIcon size="1rem" />
|
|
182
183
|
</td>
|
|
@@ -270,6 +271,7 @@ export const PackageAlert: React.FC = () => {
|
|
|
270
271
|
<SourceBadge source={packageAlert.source} />
|
|
271
272
|
</span>
|
|
272
273
|
<Button
|
|
274
|
+
aria-label={`Dismiss ${title}`}
|
|
273
275
|
variant="text"
|
|
274
276
|
data-testid="remove-banner-button"
|
|
275
277
|
size="icon"
|
|
@@ -294,7 +296,7 @@ export const PackageAlert: React.FC = () => {
|
|
|
294
296
|
</>
|
|
295
297
|
)}
|
|
296
298
|
<ul className="list-disc ml-2 mt-1">
|
|
297
|
-
{Object.entries(packageAlert.packages).map(([pkg, st]
|
|
299
|
+
{Object.entries(packageAlert.packages).map(([pkg, st]) => (
|
|
298
300
|
<li
|
|
299
301
|
className={cn(
|
|
300
302
|
"flex items-center gap-1 font-mono text-sm",
|
|
@@ -305,7 +307,7 @@ export const PackageAlert: React.FC = () => {
|
|
|
305
307
|
status === "failed" &&
|
|
306
308
|
"text-muted-foreground",
|
|
307
309
|
)}
|
|
308
|
-
key={
|
|
310
|
+
key={pkg}
|
|
309
311
|
>
|
|
310
312
|
<ProgressIcon status={st} />
|
|
311
313
|
{pkg}
|
|
@@ -12,7 +12,13 @@ interface SidebarToggleProps {
|
|
|
12
12
|
export const SidebarToggle = ({ isOpen, toggle }: SidebarToggleProps) => {
|
|
13
13
|
return (
|
|
14
14
|
<div className="invisible lg:visible absolute top-[12px] right-[16px] z-20">
|
|
15
|
-
<Button
|
|
15
|
+
<Button
|
|
16
|
+
aria-label={isOpen ? "Collapse sidebar" : "Expand sidebar"}
|
|
17
|
+
onClick={toggle}
|
|
18
|
+
className="w-10 h-8"
|
|
19
|
+
variant="ghost"
|
|
20
|
+
size="icon"
|
|
21
|
+
>
|
|
16
22
|
<ChevronLeft
|
|
17
23
|
className={cn(
|
|
18
24
|
"h-5 w-5 transition-transform ease-in-out duration-700",
|