@marimo-team/frontend 0.15.4 → 0.16.0-dev96986
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/ConnectedDataExplorerComponent-CNLoZkWr.js +19 -0
- package/dist/assets/{ImageComparisonComponent-CEXMKKA4.js → ImageComparisonComponent-SX7fDaTK.js} +1 -1
- package/dist/assets/{VegaLite-Bt14Ds9k.js → VegaLite-MJUW3b7C.js} +6 -6
- package/dist/assets/_baseEach-9_logFrf.js +1 -0
- package/dist/assets/_baseMap-NzEbKt5c.js +1 -0
- package/dist/assets/_baseUniq-C5LFcyNC.js +1 -0
- package/dist/assets/_createAggregator-ZRm2b6Zm.js +1 -0
- package/dist/assets/agent-panel-BBd11wNX.js +287 -0
- package/dist/assets/agent-panel-D92Mfy1i.css +1 -0
- package/dist/assets/{any-language-editor-DiwNT6zp.js → any-language-editor-DwAaEQfS.js} +1 -1
- package/dist/assets/architectureDiagram-W76B3OCA-BJmVXUoW.js +36 -0
- package/dist/assets/{between-horizontal-start-FyewyCGn.js → between-horizontal-start-KiwU-a3C.js} +1 -1
- package/dist/assets/{blockDiagram-QIGZ2CNN-BrOkAf_c.js → blockDiagram-QIGZ2CNN-DzxZjE7B.js} +1 -1
- package/dist/assets/{c4Diagram-FPNF74CW-BHPzDxE2.js → c4Diagram-FPNF74CW-DjmldG_J.js} +5 -5
- package/dist/assets/channel-DHcKBVM4.js +1 -0
- package/dist/assets/chat-panel-DgJZr0eS.js +3 -0
- package/dist/assets/{chunk-4BX2VUAB-DLxaCNYh.js → chunk-4BX2VUAB-EUTQThiZ.js} +1 -1
- package/dist/assets/{chunk-55IACEB6-DdzvO3HR.js → chunk-55IACEB6-DZAiDJxy.js} +1 -1
- package/dist/assets/{chunk-FMBD7UC4-R5o-nSiG.js → chunk-FMBD7UC4-Bd0Czs-J.js} +1 -1
- package/dist/assets/{chunk-K7UQS3LO-DxaMrGgG.js → chunk-K7UQS3LO-DEKMIknX.js} +1 -1
- package/dist/assets/{chunk-QN33PNHL-DqS9-FYm.js → chunk-QN33PNHL-E0jwHU_n.js} +1 -1
- package/dist/assets/{chunk-QZHKN3VN-BZ-TzajS.js → chunk-QZHKN3VN-BzaIHJbq.js} +1 -1
- package/dist/assets/{chunk-TVAH2DTR-BsgP2dyv.js → chunk-TVAH2DTR-CZFYvqnm.js} +1 -1
- package/dist/assets/{chunk-TZMSLE5B-D-h3ahXI.js → chunk-TZMSLE5B-BNqnFjtv.js} +1 -1
- package/dist/assets/{circle-play-CQtRZ-rT.js → circle-play-D3J_mYrF.js} +1 -1
- package/dist/assets/classDiagram-KNZD7YFC-D-xwLnlX.js +1 -0
- package/dist/assets/classDiagram-v2-RKCZMP56-D-xwLnlX.js +1 -0
- package/dist/assets/{clear-button-BY6Z_ViL.js → clear-button-ifzRuAR3.js} +1 -1
- package/dist/assets/clone-CSxIll62.js +1 -0
- package/dist/assets/command-palette-D2fdVSET.js +1 -0
- package/dist/assets/common-Ku-cF_2J.js +1 -0
- package/dist/assets/{compile-Ct_jzdKr.js → compile-BgZlHW1c.js} +1 -1
- package/dist/assets/cose-bilkent-S5V4N54A-CVM83SqK.js +1 -0
- package/dist/assets/dagre-5GWH7T2D-ouQPkxT3.js +4 -0
- package/dist/assets/{data-grid-overlay-editor-BN_wulc3.js → data-grid-overlay-editor-B47j5GJJ.js} +1 -1
- package/dist/assets/datasources-panel-Bt41Zir-.js +1 -0
- package/dist/assets/{dependency-graph-panel-BOmSCZf7.js → dependency-graph-panel-CZC_B7pK.js} +4 -4
- package/dist/assets/diagram-N5W7TBWH-CQ817ZdR.js +24 -0
- package/dist/assets/diagram-QEK2KX5R-DOK_psUO.js +43 -0
- package/dist/assets/diagram-S2PKOQOG-CVljmOW8.js +24 -0
- package/dist/assets/{documentation-panel-BxjJO_Gw.js → documentation-panel-C7yIvGg1.js} +1 -1
- package/dist/assets/edit-page-CyTMQV2u.js +129 -0
- package/dist/assets/{ellipsis-vertical-UHbmjI2n.js → ellipsis-vertical-C7FjlUsY.js} +1 -1
- package/dist/assets/{empty-state-BIBXzY_0.js → empty-state-DIOGM_CU.js} +1 -1
- package/dist/assets/{erDiagram-AWTI2OKA-E84mAle_.js → erDiagram-AWTI2OKA-DYu8cEdc.js} +1 -1
- package/dist/assets/{error-panel-MEvQ6K7h.js → error-panel-Ddb8RkFG.js} +1 -1
- package/dist/assets/file-explorer-panel-Oy9DbyFP.js +1 -0
- package/dist/assets/{flowDiagram-PVAE7QVJ-DfbIRSAW.js → flowDiagram-PVAE7QVJ-CmvW5iTb.js} +1 -1
- package/dist/assets/{ganttDiagram-OWAHRB6G-DR4HZ1z_.js → ganttDiagram-OWAHRB6G-BaKQlCaT.js} +4 -4
- package/dist/assets/gitGraphDiagram-NY62KEGX-CWO24eP6.js +65 -0
- package/dist/assets/{glide-data-editor-nNmo1lPq.js → glide-data-editor-CNDLEJ9a.js} +11 -11
- package/dist/assets/graph-BZKTtxsc.js +1 -0
- package/dist/assets/home-page-Bvwppn9N.js +9 -0
- package/dist/assets/{index-VPWqq2Pg.js → index-0XOUPdwT.js} +1 -1
- package/dist/assets/{index-uacyUula.js → index-BH7f3aiU.js} +1 -1
- package/dist/assets/{index-Dt9UWeWn.js → index-BJVyzkx5.js} +1 -1
- package/dist/assets/{index-BAH034Ue.js → index-B_d_JZGI.js} +1 -1
- package/dist/assets/{index-CB2pnVQG.js → index-BgXbBA39.js} +1 -1
- package/dist/assets/{index-B8llrTSo.js → index-Brf2DwUM.js} +1 -1
- package/dist/assets/{index-BLu5CX6z.js → index-CXrWwFX6.js} +1 -1
- package/dist/assets/{index-DyLSuOH1.js → index-CZaurnA9.js} +1 -1
- package/dist/assets/{index-BFSnz7iM.js → index-CerjupfZ.js} +1 -1
- package/dist/assets/{index-B7yXbrLa.js → index-D-tZfElD.js} +1 -1
- package/dist/assets/{index-c6If577Q.js → index-D3PqGupX.js} +1 -1
- package/dist/assets/{index-CSgxTUzD.js → index-DCkzth56.js} +1 -1
- package/dist/assets/{index-DWOaniGT.js → index-DFrGFNW1.js} +1 -1
- package/dist/assets/{index-CPN7TRA1.js → index-DZhOPkOB.js} +1 -1
- package/dist/assets/index-DadI618h.css +1 -0
- package/dist/assets/{index-DqzMPAC8.js → index-DkntzpX4.js} +2 -2
- package/dist/assets/{index-B1_GXGaP.js → index-DmgwT3sx.js} +1 -1
- package/dist/assets/index-PmY0x4Zd.js +578 -0
- package/dist/assets/{index-Bq516OmX.js → index-WXJFkQHg.js} +1 -1
- package/dist/assets/{index-DSU75csX.js → index-qE8lHQ-N.js} +1 -1
- package/dist/assets/{index-DMomwMcN.js → index-zrSUQXha.js} +1 -1
- package/dist/assets/infoDiagram-STP46IZ2-CAuVVehw.js +2 -0
- package/dist/assets/isEmpty-D1t7Gran.js +1 -0
- package/dist/assets/{journeyDiagram-BIP6EPQ6-BBiFyygf.js → journeyDiagram-BIP6EPQ6-D4Rp6H_h.js} +1 -1
- package/dist/assets/{kanban-definition-6OIFK2YF-DhgA6Nt6.js → kanban-definition-6OIFK2YF-DFt9DftA.js} +4 -4
- package/dist/assets/layout-D8WXi2_g.js +1 -0
- package/dist/assets/linear-BwY8e5hA.js +1 -0
- package/dist/assets/links-4B6ldZ5P.js +7 -0
- package/dist/assets/{logs-panel-B9SmTZAW.js → logs-panel-Dxiyt7dO.js} +1 -1
- package/dist/assets/{agent-panel-DpQ6muj-.css → markdown-renderer-ClyzDMmG.css} +1 -1
- package/dist/assets/markdown-renderer-VDu-NBKB.js +263 -0
- package/dist/assets/mermaid-B-O-Puyi.js +1 -0
- package/dist/assets/{mermaid.core-4nVOEVX3.js → mermaid.core-BFFCqfOn.js} +41 -41
- package/dist/assets/min-DtVSfYKl.js +1 -0
- package/dist/assets/{mindmap-definition-Q6HEUPPD-CVLQNn1q.js → mindmap-definition-Q6HEUPPD-kyvIY8Dg.js} +2 -2
- package/dist/assets/{number-overlay-editor-CzRzXLcd.js → number-overlay-editor-GjLB2UK4.js} +1 -1
- package/dist/assets/outline-panel-CMJjOoN7.js +1 -0
- package/dist/assets/packages-panel-nfXB-bKW.js +1 -0
- package/dist/assets/{pieDiagram-ADFJNKIX-C5IQ5DBZ.js → pieDiagram-ADFJNKIX-D8JFQcWR.js} +3 -3
- package/dist/assets/{quadrantDiagram-LMRXKWRM-CFXFnQxx.js → quadrantDiagram-LMRXKWRM-Nf8GzxXG.js} +1 -1
- package/dist/assets/{react-plotly-mzdv02_Y.js → react-plotly-CnW9p7ZA.js} +1 -1
- package/dist/assets/{requirementDiagram-4UW4RH46-D9bPC89T.js → requirementDiagram-4UW4RH46-CCUxF8BZ.js} +1 -1
- package/dist/assets/run-page-Bl4p3AbZ.js +1 -0
- package/dist/assets/sankeyDiagram-GR3RE2ED-Sr8kDwP1.js +10 -0
- package/dist/assets/scratchpad-panel-Ja1Mu-W3.js +1 -0
- package/dist/assets/secrets-panel-B-3fcSyP.js +1 -0
- package/dist/assets/{sequenceDiagram-C3RYC4MD-6N7_hY4k.js → sequenceDiagram-C3RYC4MD-CBJ152Q3.js} +4 -4
- package/dist/assets/{slides-component-DMjQomc3.css → slides-component-C-LoGC1U.css} +1 -1
- package/dist/assets/{slides-component-EcjC8sDK.js → slides-component-DGtsVP5o.js} +1 -1
- package/dist/assets/snippets-panel-ClNnwKBM.js +1 -0
- package/dist/assets/sortBy-D47H6Vyl.js +1 -0
- package/dist/assets/state-B_RCHTH5.js +1 -0
- package/dist/assets/stateDiagram-KXAO66HF-BlBFSAZr.js +1 -0
- package/dist/assets/stateDiagram-v2-UMBNRL4Z-DbA-iToo.js +1 -0
- package/dist/assets/storage-BNcWOH3-.js +26 -0
- package/dist/assets/terminal-CATzv5Hd.js +10 -0
- package/dist/assets/time-CsYqILfB.js +1 -0
- package/dist/assets/{timeline-definition-XQNQX7LJ-BEaynAiY.js → timeline-definition-XQNQX7LJ-CGrhjuAs.js} +1 -1
- package/dist/assets/tracing-DUbJtOyq.js +2 -0
- package/dist/assets/{tracing-panel-BmuHLPrY.js → tracing-panel-DmzqPUtc.js} +2 -2
- package/dist/assets/{trash-UBqfK4mR.js → trash-rxdjLzkf.js} +1 -1
- package/dist/assets/{tree-XiEycetl.js → tree-C2Ul1h1C.js} +1 -1
- package/dist/assets/{treemap-75Q7IDZK-CnuVFbBG.js → treemap-75Q7IDZK-N9hyUpyj.js} +20 -20
- package/dist/assets/{ts-tags-CloPe9IY.js → ts-tags-DxCDHihD.js} +1 -1
- package/dist/assets/variable-panel-BbgupOdG.js +1 -0
- package/dist/assets/{vega-component-DsTH4tuX.js → vega-component-CR_MHOBT.js} +1 -1
- package/dist/assets/worker-fHbtoWvT.js +1 -0
- package/dist/assets/{xychartDiagram-6GGTOJPD-Dcz3O-A3.js → xychartDiagram-6GGTOJPD-jdLZsMb2.js} +1 -1
- package/dist/index.html +2 -2
- package/package.json +10 -5
- package/src/__tests__/mocks.ts +43 -0
- package/src/components/app-config/user-config-form.tsx +78 -1
- package/src/components/chat/acp/__tests__/__snapshots__/prompt.test.ts.snap +116 -65
- package/src/components/chat/acp/__tests__/atoms.test.ts +1 -1
- package/src/components/chat/acp/__tests__/context-utils.test.ts +222 -0
- package/src/components/chat/acp/__tests__/prompt.test.ts +1 -1
- package/src/components/chat/acp/__tests__/state.test.ts +38 -42
- package/src/components/chat/acp/agent-docs.tsx +33 -6
- package/src/components/chat/acp/agent-panel.css +0 -18
- package/src/components/chat/acp/agent-panel.tsx +394 -72
- package/src/components/chat/acp/agent-selector.tsx +7 -1
- package/src/components/chat/acp/blocks.tsx +40 -10
- package/src/components/chat/acp/common.tsx +10 -2
- package/src/components/chat/acp/context-utils.ts +127 -0
- package/src/components/chat/acp/prompt.ts +96 -53
- package/src/components/chat/acp/state.ts +1 -1
- package/src/components/chat/acp/types.ts +8 -0
- package/src/components/chat/chat-panel.tsx +28 -89
- package/src/components/chat/chat-utils.ts +127 -1
- package/src/components/chat/markdown-renderer.css +39 -0
- package/src/components/chat/markdown-renderer.tsx +12 -47
- package/src/components/chat/tool-call-accordion.tsx +148 -26
- package/src/components/data-table/SearchBar.tsx +8 -7
- package/src/components/data-table/__tests__/column_formatting.test.ts +50 -35
- package/src/components/data-table/__tests__/data-table.test.tsx +39 -1
- package/src/components/data-table/cell-hover-template/feature.ts +14 -0
- package/src/components/data-table/cell-hover-template/types.ts +11 -0
- package/src/components/data-table/charts/components/form-fields.tsx +41 -37
- package/src/components/data-table/charts/forms/common-chart.tsx +2 -2
- package/src/components/data-table/column-explorer-panel/column-explorer.tsx +5 -2
- package/src/components/data-table/column-formatting/feature.ts +62 -29
- package/src/components/data-table/column-formatting/types.ts +1 -0
- package/src/components/data-table/column-header.tsx +3 -1
- package/src/components/data-table/column-summary/chart-spec-model.tsx +24 -7
- package/src/components/data-table/column-summary/column-summary.tsx +18 -9
- package/src/components/data-table/columns.tsx +42 -18
- package/src/components/data-table/data-table.tsx +10 -2
- package/src/components/data-table/date-popover.tsx +85 -75
- package/src/components/data-table/filter-pills.tsx +14 -9
- package/src/components/data-table/header-items.tsx +5 -1
- package/src/components/data-table/pagination.tsx +20 -13
- package/src/components/data-table/renderers.tsx +28 -0
- package/src/components/data-table/row-viewer-panel/row-viewer.tsx +10 -8
- package/src/components/datasources/column-preview.tsx +6 -2
- package/src/components/datasources/datasources.tsx +8 -12
- package/src/components/editor/Cell.tsx +6 -0
- package/src/components/editor/actions/name-cell-input.tsx +6 -1
- package/src/components/editor/actions/useCellActionButton.tsx +3 -1
- package/src/components/editor/ai/__tests__/completion-utils.test.ts +178 -1
- package/src/components/editor/ai/add-cell-with-ai.tsx +68 -66
- package/src/components/editor/ai/ai-completion-editor.tsx +29 -26
- package/src/components/editor/ai/completion-handlers.tsx +44 -6
- package/src/components/editor/ai/completion-utils.ts +92 -0
- package/src/components/editor/ai/transport/chat-transport.tsx +39 -0
- package/src/components/editor/cell/CellStatus.tsx +23 -20
- package/src/components/editor/cell/CreateCellButton.tsx +3 -4
- package/src/components/editor/cell/StagedAICell.tsx +51 -0
- package/src/components/editor/cell/cell-actions.tsx +2 -1
- package/src/components/editor/cell/code/language-toggle.tsx +3 -4
- package/src/components/editor/chrome/wrapper/footer-items/machine-stats.tsx +39 -28
- package/src/components/editor/controls/notebook-menu-dropdown.tsx +4 -2
- package/src/components/editor/file-tree/requesting-tree.tsx +14 -8
- package/src/components/editor/renderers/CellArray.tsx +3 -4
- package/src/components/editor/renderers/slides-layout/slides-layout.tsx +3 -3
- package/src/components/editor/renderers/slides-layout/types.ts +1 -0
- package/src/components/pages/home-page.tsx +4 -1
- package/src/components/slides/slides-component.tsx +1 -1
- package/src/components/slides/slides.css +6 -0
- package/src/components/terminal/__tests__/state.test.ts +207 -0
- package/src/components/terminal/hooks.ts +41 -0
- package/src/components/terminal/state.ts +75 -0
- package/src/components/terminal/terminal.tsx +334 -13
- package/src/components/terminal/theme.tsx +57 -0
- package/src/components/tracing/tracing-spec.ts +5 -4
- package/src/components/ui/range-slider.tsx +4 -2
- package/src/components/ui/slider.tsx +3 -1
- package/src/components/variables/variables-table.tsx +3 -0
- package/src/core/MarimoApp.tsx +9 -6
- package/src/core/ai/__tests__/staged-cells.test.ts +356 -0
- package/src/core/ai/context/__tests__/registry.test.ts +6 -4
- package/src/core/ai/context/providers/cell-output.ts +3 -2
- package/src/core/ai/context/providers/error.ts +3 -1
- package/src/core/ai/context/providers/file.ts +7 -2
- package/src/core/ai/context/providers/tables.ts +3 -2
- package/src/core/ai/context/providers/variable.ts +6 -4
- package/src/core/ai/staged-cells.ts +208 -0
- package/src/core/cells/cells.ts +1 -1
- package/src/core/cells/logs.ts +1 -1
- package/src/core/codemirror/find-replace/search-highlight.ts +3 -1
- package/src/core/codemirror/language/LanguageAdapters.ts +9 -3
- package/src/core/codemirror/lsp/federated-lsp.ts +1 -1
- package/src/core/codemirror/lsp/notebook-lsp.ts +8 -2
- package/src/core/codemirror/readonly/__tests__/extension.test.ts +1 -1
- package/src/core/codemirror/rtc/loro/awareness.ts +52 -17
- package/src/core/codemirror/rtc/loro/sync.ts +12 -4
- package/src/core/config/config-schema.ts +1 -0
- package/src/core/config/config.ts +4 -0
- package/src/core/hotkeys/hotkeys.ts +8 -4
- package/src/core/i18n/__tests__/locale-provider.test.tsx +176 -0
- package/src/core/i18n/locale-provider.tsx +35 -0
- package/src/core/i18n/with-locale.tsx +12 -0
- package/src/core/islands/components/web-components.tsx +13 -10
- package/src/core/islands/main.ts +2 -2
- package/src/core/kernel/RuntimeState.ts +4 -1
- package/src/core/kernel/messages.ts +8 -12
- package/src/core/network/DeferredRequestRegistry.ts +16 -4
- package/src/core/runtime/runtime.ts +5 -4
- package/src/core/saving/__tests__/filename.test.ts +37 -0
- package/src/core/static/__tests__/download-html.test.ts +43 -1
- package/src/core/wasm/bridge.ts +5 -1
- package/src/core/wasm/store.ts +4 -1
- package/src/core/wasm/worker/message-buffer.ts +3 -2
- package/src/core/websocket/types.ts +22 -16
- package/src/core/websocket/useMarimoWebSocket.tsx +2 -2
- package/src/css/app/Cell.css +11 -0
- package/src/hooks/useFormatting.ts +97 -0
- package/src/hooks/useTimer.ts +8 -5
- package/src/plugins/core/RenderHTML.tsx +36 -2
- package/src/plugins/core/__test__/RenderHTML.test.ts +72 -0
- package/src/plugins/core/registerReactComponent.tsx +44 -10
- package/src/plugins/impl/DataTablePlugin.tsx +4 -0
- package/src/plugins/impl/FileBrowserPlugin.tsx +8 -2
- package/src/plugins/impl/RangeSliderPlugin.tsx +5 -3
- package/src/plugins/impl/SliderPlugin.tsx +3 -1
- package/src/plugins/impl/anywidget/model.ts +16 -5
- package/src/plugins/impl/data-editor/types.ts +7 -5
- package/src/plugins/impl/data-explorer/components/column-summary.tsx +20 -13
- package/src/plugins/impl/panel/utils.ts +6 -4
- package/src/plugins/layout/OutlinePlugin.tsx +69 -0
- package/src/plugins/layout/StatPlugin.tsx +4 -1
- package/src/plugins/plugins.ts +2 -0
- package/src/stories/cell.stories.tsx +1 -1
- package/src/stories/layout/vertical/one-column.stories.tsx +1 -1
- package/src/utils/__tests__/cell-urls.test.ts +29 -0
- package/src/utils/__tests__/dates.test.ts +45 -24
- package/src/utils/__tests__/filenames.test.ts +18 -0
- package/src/utils/__tests__/numbers.test.ts +42 -30
- package/src/utils/__tests__/once.test.ts +187 -0
- package/src/utils/__tests__/path.test.ts +38 -0
- package/src/utils/__tests__/urls.test.ts +56 -1
- package/src/utils/dates.ts +15 -10
- package/src/utils/edit-distance.ts +8 -6
- package/src/utils/errors.ts +9 -0
- package/src/utils/id-tree.tsx +21 -10
- package/src/utils/localStorage.ts +13 -4
- package/src/utils/numbers.ts +11 -11
- package/src/utils/once.ts +32 -0
- package/src/utils/paths.ts +4 -1
- package/src/utils/pluralize.ts +12 -5
- package/src/utils/python-poet/poet.ts +30 -15
- package/src/utils/time.ts +5 -1
- package/dist/assets/ConnectedDataExplorerComponent-Cn5-l2X1.js +0 -19
- package/dist/assets/_baseEach-C1FLm7WW.js +0 -1
- package/dist/assets/_baseMap-DBVArUYD.js +0 -1
- package/dist/assets/_baseUniq-Dk7ZPJ3N.js +0 -1
- package/dist/assets/_createAggregator-Bn38fDd3.js +0 -1
- package/dist/assets/agent-panel-COUYnuIK.js +0 -475
- package/dist/assets/architectureDiagram-W76B3OCA-DBzWQKKu.js +0 -36
- package/dist/assets/channel-CjhbjOv4.js +0 -1
- package/dist/assets/chat-panel-BPXKoTnZ.js +0 -7
- package/dist/assets/chat-panel-Brrs_eeH.css +0 -1
- package/dist/assets/classDiagram-KNZD7YFC-DHs5cFzy.js +0 -1
- package/dist/assets/classDiagram-v2-RKCZMP56-DHs5cFzy.js +0 -1
- package/dist/assets/clone-DM1YNjEn.js +0 -1
- package/dist/assets/command-palette-S0bzQp7v.js +0 -1
- package/dist/assets/common-B8U9k2Ly.js +0 -1
- package/dist/assets/cose-bilkent-S5V4N54A-wz1Sfx7j.js +0 -1
- package/dist/assets/dagre-5GWH7T2D-BfpcVBgq.js +0 -4
- package/dist/assets/datasources-panel-DfuURLJw.js +0 -1
- package/dist/assets/diagram-N5W7TBWH-Bf0oqqQh.js +0 -24
- package/dist/assets/diagram-QEK2KX5R-ZTc3qikh.js +0 -43
- package/dist/assets/diagram-S2PKOQOG-tLScBy7Z.js +0 -24
- package/dist/assets/edit-page-DJ8kJZ9w.js +0 -129
- package/dist/assets/file-explorer-panel-CzNUJ63G.js +0 -1
- package/dist/assets/gitGraphDiagram-NY62KEGX-C1t6QtVa.js +0 -65
- package/dist/assets/graph-CssCVWIq.js +0 -1
- package/dist/assets/home-page-9eW6qida.js +0 -9
- package/dist/assets/index-CknhX2Vy.css +0 -1
- package/dist/assets/index-DcCIe7np.js +0 -28
- package/dist/assets/index-OC46250R.js +0 -570
- package/dist/assets/infoDiagram-STP46IZ2-CwiAoz9f.js +0 -2
- package/dist/assets/layout-DpQrxGW-.js +0 -1
- package/dist/assets/linear-NsreOeBF.js +0 -1
- package/dist/assets/links-CbvGxbsJ.js +0 -7
- package/dist/assets/mermaid-DSt0r6IQ.js +0 -1
- package/dist/assets/min-D259kI3t.js +0 -1
- package/dist/assets/outline-panel-uvsS-YEQ.js +0 -1
- package/dist/assets/packages-panel-xMz9W2hW.js +0 -1
- package/dist/assets/run-page-Bb68qdhQ.js +0 -1
- package/dist/assets/sankeyDiagram-GR3RE2ED-BSJOau8E.js +0 -10
- package/dist/assets/scratchpad-panel-BF4BO-U4.js +0 -1
- package/dist/assets/secrets-panel-CdIX44dQ.js +0 -1
- package/dist/assets/snippets-panel-Dco9h0rb.js +0 -1
- package/dist/assets/sortBy-aLGA-PGK.js +0 -1
- package/dist/assets/stateDiagram-KXAO66HF-Bd68WT3b.js +0 -1
- package/dist/assets/stateDiagram-v2-UMBNRL4Z-BXz_GSwb.js +0 -1
- package/dist/assets/storage-CGlP4lCF.js +0 -26
- package/dist/assets/terminal-CxkHubcu.js +0 -9
- package/dist/assets/time-D2nr1UgQ.js +0 -1
- package/dist/assets/tracing-kTqHxa7q.js +0 -2
- package/dist/assets/variable-panel-noTnH-AQ.js +0 -1
- package/dist/assets/worker-X5rxzQGQ.js +0 -1
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
SquareIcon,
|
|
19
19
|
} from "lucide-react";
|
|
20
20
|
import { memo, useEffect, useMemo, useRef, useState } from "react";
|
|
21
|
+
import { useLocale } from "react-aria";
|
|
21
22
|
import useEvent from "react-use-event-hook";
|
|
22
23
|
import { Button } from "@/components/ui/button";
|
|
23
24
|
import {
|
|
@@ -48,7 +49,6 @@ import { DEFAULT_AI_MODEL } from "@/core/config/config-schema";
|
|
|
48
49
|
import { FeatureFlagged } from "@/core/config/feature-flag";
|
|
49
50
|
import { useRequestClient } from "@/core/network/requests";
|
|
50
51
|
import { useRuntimeManager } from "@/core/runtime/config";
|
|
51
|
-
import type { ChatMessage } from "@/plugins/impl/chat/types";
|
|
52
52
|
import { ErrorBanner } from "@/plugins/impl/common/error-banner";
|
|
53
53
|
import { cn } from "@/utils/cn";
|
|
54
54
|
import { timeAgo } from "@/utils/dates";
|
|
@@ -59,7 +59,6 @@ import { PromptInput } from "../editor/ai/add-cell-with-ai";
|
|
|
59
59
|
import {
|
|
60
60
|
addContextCompletion,
|
|
61
61
|
CONTEXT_TRIGGER,
|
|
62
|
-
getAICompletionBodyWithAttachments,
|
|
63
62
|
} from "../editor/ai/completion-utils";
|
|
64
63
|
import { PanelEmptyState } from "../editor/chrome/panels/empty-state";
|
|
65
64
|
import { CopyClipboardIcon } from "../icons/copy-icon";
|
|
@@ -68,8 +67,11 @@ import { Tooltip, TooltipProvider } from "../ui/tooltip";
|
|
|
68
67
|
import { toast } from "../ui/use-toast";
|
|
69
68
|
import { AttachmentRenderer, FileAttachmentPill } from "./chat-components";
|
|
70
69
|
import {
|
|
70
|
+
buildCompletionRequestBody,
|
|
71
71
|
convertToFileUIPart,
|
|
72
72
|
generateChatTitle,
|
|
73
|
+
handleToolCall,
|
|
74
|
+
hasPendingToolCalls,
|
|
73
75
|
isLastMessageReasoning,
|
|
74
76
|
} from "./chat-utils";
|
|
75
77
|
import { MarkdownRenderer } from "./markdown-renderer";
|
|
@@ -102,6 +104,7 @@ const ChatHeader: React.FC<ChatHeaderProps> = ({
|
|
|
102
104
|
}) => {
|
|
103
105
|
const { handleClick } = useOpenSettingsToTab();
|
|
104
106
|
const chatState = useAtomValue(chatStateAtom);
|
|
107
|
+
const { locale } = useLocale();
|
|
105
108
|
const chats = useMemo(() => {
|
|
106
109
|
return [...chatState.chats.values()].sort(
|
|
107
110
|
(a, b) => b.updatedAt - a.updatedAt,
|
|
@@ -158,7 +161,7 @@ const ChatHeader: React.FC<ChatHeaderProps> = ({
|
|
|
158
161
|
>
|
|
159
162
|
<div className="font-medium">{chat.title}</div>
|
|
160
163
|
<div className="text-sm text-muted-foreground">
|
|
161
|
-
{timeAgo(chat.updatedAt)}
|
|
164
|
+
{timeAgo(chat.updatedAt, locale)}
|
|
162
165
|
</div>
|
|
163
166
|
</button>
|
|
164
167
|
))}
|
|
@@ -233,7 +236,9 @@ const ChatMessageDisplay: React.FC<ChatMessageProps> = memo(
|
|
|
233
236
|
index={i}
|
|
234
237
|
toolName={part.type}
|
|
235
238
|
result={part.output}
|
|
239
|
+
className="my-2"
|
|
236
240
|
state={part.state}
|
|
241
|
+
input={part.input}
|
|
237
242
|
/>
|
|
238
243
|
);
|
|
239
244
|
}
|
|
@@ -265,6 +270,8 @@ const ChatMessageDisplay: React.FC<ChatMessageProps> = memo(
|
|
|
265
270
|
toolName={part.type}
|
|
266
271
|
result={part.output}
|
|
267
272
|
state={part.state}
|
|
273
|
+
input={part.input}
|
|
274
|
+
className="my-2"
|
|
268
275
|
/>
|
|
269
276
|
);
|
|
270
277
|
|
|
@@ -282,10 +289,11 @@ const ChatMessageDisplay: React.FC<ChatMessageProps> = memo(
|
|
|
282
289
|
Logger.error("Unhandled part type:", part.type);
|
|
283
290
|
try {
|
|
284
291
|
return (
|
|
285
|
-
<
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
292
|
+
<div className="text-xs text-muted-foreground" key={i}>
|
|
293
|
+
<MarkdownRenderer
|
|
294
|
+
content={JSON.stringify(part, null, 2)}
|
|
295
|
+
/>
|
|
296
|
+
</div>
|
|
289
297
|
);
|
|
290
298
|
} catch (error) {
|
|
291
299
|
Logger.error("Error rendering part:", part.type, error);
|
|
@@ -429,7 +437,7 @@ const ChatInputFooter: React.FC<ChatInputFooterProps> = memo(
|
|
|
429
437
|
</>
|
|
430
438
|
)}
|
|
431
439
|
|
|
432
|
-
<Tooltip content="Submit">
|
|
440
|
+
<Tooltip content={isLoading ? "Stop" : "Submit"}>
|
|
433
441
|
<Button
|
|
434
442
|
variant="text"
|
|
435
443
|
size="sm"
|
|
@@ -565,80 +573,20 @@ const ChatPanelBody = () => {
|
|
|
565
573
|
id: chatId,
|
|
566
574
|
} = useChat({
|
|
567
575
|
id: activeChatId,
|
|
568
|
-
|
|
569
|
-
sendAutomaticallyWhen: ({ messages }) => {
|
|
570
|
-
if (messages.length === 0) {
|
|
571
|
-
return false;
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
const lastMessage = messages[messages.length - 1];
|
|
575
|
-
const parts = lastMessage.parts;
|
|
576
|
-
|
|
577
|
-
if (parts.length === 0) {
|
|
578
|
-
return false;
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
// Only auto-send if the last message is an assistant message
|
|
582
|
-
// Because assistant messages are the ones that can have tool calls
|
|
583
|
-
if (lastMessage.role !== "assistant") {
|
|
584
|
-
return false;
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
const toolParts = parts.filter((part) =>
|
|
588
|
-
part.type.startsWith("tool-"),
|
|
589
|
-
) as ToolUIPart[];
|
|
590
|
-
|
|
591
|
-
const hasCompletedToolCalls = toolParts.some(
|
|
592
|
-
(part) => part.state === "output-available",
|
|
593
|
-
);
|
|
594
|
-
|
|
595
|
-
// Check if the last part has any text content
|
|
596
|
-
const lastPart = parts[parts.length - 1];
|
|
597
|
-
const hasTextContent =
|
|
598
|
-
lastPart.type === "text" && lastPart.text?.trim().length > 0;
|
|
599
|
-
|
|
600
|
-
// Only auto-send if we have completed tool calls and there is no reply yet
|
|
601
|
-
return hasCompletedToolCalls && !hasTextContent;
|
|
602
|
-
},
|
|
576
|
+
sendAutomaticallyWhen: ({ messages }) => hasPendingToolCalls(messages),
|
|
603
577
|
messages: activeChat?.messages || [], // initial messages
|
|
604
578
|
transport: new DefaultChatTransport({
|
|
605
579
|
api: runtimeManager.getAiURL("chat").toString(),
|
|
606
580
|
headers: runtimeManager.headers(),
|
|
607
581
|
prepareSendMessagesRequest: async (options) => {
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
.map((part) => (part.type === "text" ? part.text : ""))
|
|
612
|
-
.join("\n");
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
const input = toContent(options.messages.flatMap((m) => m.parts));
|
|
616
|
-
const completionBody = await getAICompletionBodyWithAttachments({
|
|
617
|
-
input,
|
|
618
|
-
});
|
|
619
|
-
|
|
620
|
-
// Map from UIMessage to our ChatMessage type
|
|
621
|
-
// If it's the last message, add the attachments from the completion body
|
|
622
|
-
function mapMessage(m: UIMessage, isLastMessage: boolean): ChatMessage {
|
|
623
|
-
const parts = m.parts;
|
|
624
|
-
if (isLastMessage) {
|
|
625
|
-
parts.push(...completionBody.attachments);
|
|
626
|
-
}
|
|
627
|
-
return {
|
|
628
|
-
role: m.role,
|
|
629
|
-
content: toContent(m.parts),
|
|
630
|
-
parts: parts,
|
|
631
|
-
};
|
|
632
|
-
}
|
|
582
|
+
const completionBody = await buildCompletionRequestBody(
|
|
583
|
+
options.messages,
|
|
584
|
+
);
|
|
633
585
|
|
|
634
586
|
return {
|
|
635
587
|
body: {
|
|
636
588
|
...options,
|
|
637
|
-
...completionBody
|
|
638
|
-
messages: options.messages.map((m, idx) => ({
|
|
639
|
-
...m,
|
|
640
|
-
...mapMessage(m, idx === options.messages.length - 1),
|
|
641
|
-
})),
|
|
589
|
+
...completionBody,
|
|
642
590
|
},
|
|
643
591
|
};
|
|
644
592
|
},
|
|
@@ -653,24 +601,15 @@ const ChatPanelBody = () => {
|
|
|
653
601
|
});
|
|
654
602
|
},
|
|
655
603
|
onToolCall: async ({ toolCall }) => {
|
|
656
|
-
|
|
657
|
-
|
|
604
|
+
await handleToolCall({
|
|
605
|
+
invokeAiTool,
|
|
606
|
+
addToolResult,
|
|
607
|
+
toolCall: {
|
|
658
608
|
toolName: toolCall.toolName,
|
|
659
|
-
arguments: toolCall.input as Record<string, never>,
|
|
660
|
-
});
|
|
661
|
-
addToolResult({
|
|
662
|
-
tool: toolCall.toolName,
|
|
663
609
|
toolCallId: toolCall.toolCallId,
|
|
664
|
-
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
Logger.error("Tool call failed:", error);
|
|
668
|
-
addToolResult({
|
|
669
|
-
tool: toolCall.toolName,
|
|
670
|
-
toolCallId: toolCall.toolCallId,
|
|
671
|
-
output: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
672
|
-
});
|
|
673
|
-
}
|
|
610
|
+
input: toolCall.input as Record<string, never>,
|
|
611
|
+
},
|
|
612
|
+
});
|
|
674
613
|
},
|
|
675
614
|
onError: (error) => {
|
|
676
615
|
Logger.error("An error occurred:", error);
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
/* Copyright 2024 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type { components } from "@marimo-team/marimo-api";
|
|
4
|
+
import type { FileUIPart, ToolUIPart, UIMessage } from "ai";
|
|
5
|
+
import type {
|
|
6
|
+
InvokeAiToolRequest,
|
|
7
|
+
InvokeAiToolResponse,
|
|
8
|
+
} from "@/core/network/types";
|
|
9
|
+
import type { ChatMessage } from "@/plugins/impl/chat/types";
|
|
4
10
|
import { blobToString } from "@/utils/fileToBase64";
|
|
11
|
+
import { Logger } from "@/utils/Logger";
|
|
12
|
+
import { getAICompletionBodyWithAttachments } from "../editor/ai/completion-utils";
|
|
5
13
|
|
|
6
14
|
export function generateChatTitle(message: string): string {
|
|
7
15
|
return message.length > 50 ? `${message.slice(0, 50)}...` : message;
|
|
@@ -48,3 +56,121 @@ export function isLastMessageReasoning(messages: UIMessage[]): boolean {
|
|
|
48
56
|
const lastPart = parts[parts.length - 1];
|
|
49
57
|
return lastPart.type === "reasoning";
|
|
50
58
|
}
|
|
59
|
+
|
|
60
|
+
function stringifyTextParts(parts: UIMessage["parts"]): string {
|
|
61
|
+
return parts
|
|
62
|
+
.map((part) => (part.type === "text" ? part.text : ""))
|
|
63
|
+
.join("\n");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export async function buildCompletionRequestBody(
|
|
67
|
+
messages: UIMessage[],
|
|
68
|
+
): Promise<{
|
|
69
|
+
messages: ChatMessage[];
|
|
70
|
+
context?: (null | components["schemas"]["AiCompletionContext"]) | undefined;
|
|
71
|
+
includeOtherCode: string;
|
|
72
|
+
selectedText?: string | null | undefined;
|
|
73
|
+
}> {
|
|
74
|
+
const input = stringifyTextParts(messages.flatMap((m) => m.parts));
|
|
75
|
+
const completionBody = await getAICompletionBodyWithAttachments({ input });
|
|
76
|
+
|
|
77
|
+
// Map from UIMessage to our ChatMessage type
|
|
78
|
+
// If it's the last message, add the attachments from the completion body
|
|
79
|
+
function toChatMessage(message: UIMessage, isLast: boolean): ChatMessage {
|
|
80
|
+
// Clone parts to avoid mutating the original message
|
|
81
|
+
const parts = [...message.parts];
|
|
82
|
+
if (isLast) {
|
|
83
|
+
parts.push(...completionBody.attachments);
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
role: message.role,
|
|
87
|
+
content: stringifyTextParts(message.parts), // This is no longer used in the backend
|
|
88
|
+
parts,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
...completionBody.body,
|
|
94
|
+
messages: messages.map((m, idx) =>
|
|
95
|
+
toChatMessage(m, idx === messages.length - 1),
|
|
96
|
+
),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
interface AddToolResult {
|
|
101
|
+
tool: string;
|
|
102
|
+
toolCallId: string;
|
|
103
|
+
output: unknown;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export async function handleToolCall({
|
|
107
|
+
invokeAiTool,
|
|
108
|
+
addToolResult,
|
|
109
|
+
toolCall,
|
|
110
|
+
}: {
|
|
111
|
+
invokeAiTool: (request: InvokeAiToolRequest) => Promise<InvokeAiToolResponse>;
|
|
112
|
+
addToolResult: (result: AddToolResult) => Promise<void>;
|
|
113
|
+
toolCall: {
|
|
114
|
+
toolName: string;
|
|
115
|
+
toolCallId: string;
|
|
116
|
+
input: Record<string, never>;
|
|
117
|
+
};
|
|
118
|
+
}) {
|
|
119
|
+
try {
|
|
120
|
+
const response = await invokeAiTool({
|
|
121
|
+
toolName: toolCall.toolName,
|
|
122
|
+
arguments: toolCall.input,
|
|
123
|
+
});
|
|
124
|
+
addToolResult({
|
|
125
|
+
tool: toolCall.toolName,
|
|
126
|
+
toolCallId: toolCall.toolCallId,
|
|
127
|
+
output: response.result || response.error,
|
|
128
|
+
});
|
|
129
|
+
} catch (error) {
|
|
130
|
+
Logger.error("Tool call failed:", error);
|
|
131
|
+
addToolResult({
|
|
132
|
+
tool: toolCall.toolName,
|
|
133
|
+
toolCallId: toolCall.toolCallId,
|
|
134
|
+
output: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Checks if we should send a message automatically based on the messages.
|
|
141
|
+
* We only want to send a message if we have completed tool calls and there is no reply yet.
|
|
142
|
+
*/
|
|
143
|
+
export function hasPendingToolCalls(messages: UIMessage[]): boolean {
|
|
144
|
+
if (messages.length === 0) {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const lastMessage = messages[messages.length - 1];
|
|
149
|
+
const parts = lastMessage.parts;
|
|
150
|
+
|
|
151
|
+
if (parts.length === 0) {
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Only auto-send if the last message is an assistant message
|
|
156
|
+
// Because assistant messages are the ones that can have tool calls
|
|
157
|
+
if (lastMessage.role !== "assistant") {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const toolParts = parts.filter((part) =>
|
|
162
|
+
part.type.startsWith("tool-"),
|
|
163
|
+
) as ToolUIPart[];
|
|
164
|
+
|
|
165
|
+
const hasCompletedToolCalls = toolParts.some(
|
|
166
|
+
(part) => part.state === "output-available",
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
// Check if the last part has any text content
|
|
170
|
+
const lastPart = parts[parts.length - 1];
|
|
171
|
+
const hasTextContent =
|
|
172
|
+
lastPart.type === "text" && lastPart.text?.trim().length > 0;
|
|
173
|
+
|
|
174
|
+
// Only auto-send if we have completed tool calls and there is no reply yet
|
|
175
|
+
return hasCompletedToolCalls && !hasTextContent;
|
|
176
|
+
}
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
+
@source "../../../node_modules/streamdown/dist/index.js";
|
|
2
|
+
|
|
1
3
|
.mo-markdown-renderer {
|
|
4
|
+
/* Make headers a bit smaller */
|
|
5
|
+
--text-2xl: 1rem;
|
|
6
|
+
--text-3xl: 1.2rem;
|
|
7
|
+
|
|
2
8
|
h1,
|
|
3
9
|
h2,
|
|
4
10
|
h3,
|
|
@@ -12,4 +18,37 @@
|
|
|
12
18
|
margin-top: 8px;
|
|
13
19
|
margin-bottom: 12px;
|
|
14
20
|
}
|
|
21
|
+
|
|
22
|
+
pre {
|
|
23
|
+
width: 100%;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
[data-code-block-container="true"] {
|
|
27
|
+
margin-top: 0 !important;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
[data-code-block-header="true"] {
|
|
31
|
+
padding: 4px !important;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
code {
|
|
35
|
+
font-size: inherit !important;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
li.task-list-item {
|
|
39
|
+
list-style-type: none;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
li {
|
|
43
|
+
padding-left: 6px;
|
|
44
|
+
|
|
45
|
+
> input {
|
|
46
|
+
margin-right: 6px;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
ul,
|
|
51
|
+
ol {
|
|
52
|
+
padding-left: 10px;
|
|
53
|
+
}
|
|
15
54
|
}
|
|
@@ -3,10 +3,8 @@
|
|
|
3
3
|
import { EditorView } from "@codemirror/view";
|
|
4
4
|
import { useAtomValue } from "jotai";
|
|
5
5
|
import { BetweenHorizontalStartIcon } from "lucide-react";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import Markdown, { type Components } from "react-markdown";
|
|
9
|
-
import remarkGfm from "remark-gfm";
|
|
6
|
+
import { memo, Suspense, useState } from "react";
|
|
7
|
+
import { Streamdown, type StreamdownProps } from "streamdown";
|
|
10
8
|
import { Button, type ButtonProps } from "@/components/ui/button";
|
|
11
9
|
import { maybeAddMarimoImport } from "@/core/cells/add-missing-import";
|
|
12
10
|
import { useCellActions } from "@/core/cells/cells";
|
|
@@ -116,9 +114,9 @@ const CodeBlock = ({ code, language }: CodeBlockProps) => {
|
|
|
116
114
|
const { theme } = useTheme();
|
|
117
115
|
const [value, setValue] = useState(code);
|
|
118
116
|
|
|
119
|
-
|
|
117
|
+
if (value !== code) {
|
|
120
118
|
setValue(code);
|
|
121
|
-
}
|
|
119
|
+
}
|
|
122
120
|
|
|
123
121
|
const handleCopyCode = async () => {
|
|
124
122
|
await copyToClipboard(value);
|
|
@@ -152,18 +150,13 @@ const CodeBlock = ({ code, language }: CodeBlockProps) => {
|
|
|
152
150
|
const CopyButton: React.FC<ButtonProps> = ({ onClick, ...props }) => {
|
|
153
151
|
const [copied, setCopied] = useState(false);
|
|
154
152
|
|
|
155
|
-
useEffect(() => {
|
|
156
|
-
if (copied) {
|
|
157
|
-
setTimeout(() => setCopied(false), 1000);
|
|
158
|
-
}
|
|
159
|
-
}, [copied]);
|
|
160
|
-
|
|
161
153
|
return (
|
|
162
154
|
<Button
|
|
163
155
|
{...props}
|
|
164
156
|
onClick={(e) => {
|
|
165
157
|
onClick?.(e);
|
|
166
158
|
setCopied(true);
|
|
159
|
+
setTimeout(() => setCopied(false), 1000);
|
|
167
160
|
}}
|
|
168
161
|
>
|
|
169
162
|
{copied ? "Copied" : "Copy"}
|
|
@@ -171,14 +164,17 @@ const CopyButton: React.FC<ButtonProps> = ({ onClick, ...props }) => {
|
|
|
171
164
|
);
|
|
172
165
|
};
|
|
173
166
|
|
|
167
|
+
type Components = StreamdownProps["components"];
|
|
168
|
+
|
|
174
169
|
const COMPONENTS: Components = {
|
|
175
170
|
code: ({ children, className }) => {
|
|
176
171
|
const language = className?.replace("language-", "");
|
|
177
172
|
if (language && typeof children === "string") {
|
|
173
|
+
const code = children.trim();
|
|
178
174
|
return (
|
|
179
175
|
<div>
|
|
180
176
|
<div className="text-xs text-muted-foreground pl-1">{language}</div>
|
|
181
|
-
<CodeBlock code={
|
|
177
|
+
<CodeBlock code={code} language={language} />
|
|
182
178
|
</div>
|
|
183
179
|
);
|
|
184
180
|
}
|
|
@@ -186,42 +182,11 @@ const COMPONENTS: Components = {
|
|
|
186
182
|
},
|
|
187
183
|
};
|
|
188
184
|
|
|
189
|
-
function parseMarkdownIntoBlocks(markdown: string): string[] {
|
|
190
|
-
const tokens = marked.lexer(markdown);
|
|
191
|
-
return tokens.map((token) => token.raw);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
const PLUGINS = [remarkGfm];
|
|
195
|
-
|
|
196
|
-
const MemoizedMarkdownBlock = memo(
|
|
197
|
-
({ content }: { content: string }) => {
|
|
198
|
-
return (
|
|
199
|
-
<Markdown
|
|
200
|
-
components={COMPONENTS}
|
|
201
|
-
remarkPlugins={PLUGINS}
|
|
202
|
-
className="mo-markdown-renderer prose dark:prose-invert max-w-none prose-pre:pl-0"
|
|
203
|
-
>
|
|
204
|
-
{content}
|
|
205
|
-
</Markdown>
|
|
206
|
-
);
|
|
207
|
-
},
|
|
208
|
-
(prevProps, nextProps) => prevProps.content === nextProps.content,
|
|
209
|
-
);
|
|
210
|
-
|
|
211
|
-
MemoizedMarkdownBlock.displayName = "MemoizedMarkdownBlock";
|
|
212
|
-
|
|
213
185
|
export const MarkdownRenderer = memo(({ content }: { content: string }) => {
|
|
214
|
-
const blocks = useMemo(() => parseMarkdownIntoBlocks(content), [content]);
|
|
215
|
-
|
|
216
186
|
return (
|
|
217
|
-
|
|
218
|
-
{
|
|
219
|
-
|
|
220
|
-
content={block}
|
|
221
|
-
key={`markdown-block-${index}`}
|
|
222
|
-
/>
|
|
223
|
-
))}
|
|
224
|
-
</>
|
|
187
|
+
<Streamdown components={COMPONENTS} className="mo-markdown-renderer">
|
|
188
|
+
{content}
|
|
189
|
+
</Streamdown>
|
|
225
190
|
);
|
|
226
191
|
});
|
|
227
192
|
MarkdownRenderer.displayName = "MarkdownRenderer";
|