@marimo-team/frontend 0.15.5 → 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
|
@@ -1,23 +1,32 @@
|
|
|
1
1
|
/* Copyright 2024 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
|
-
import { useAtom } from "jotai";
|
|
3
|
+
import { useAtom, useAtomValue } from "jotai";
|
|
4
4
|
import { capitalize } from "lodash-es";
|
|
5
5
|
import {
|
|
6
|
+
AtSignIcon,
|
|
6
7
|
BotMessageSquareIcon,
|
|
8
|
+
PaperclipIcon,
|
|
7
9
|
RefreshCwIcon,
|
|
10
|
+
SendIcon,
|
|
11
|
+
SquareIcon,
|
|
8
12
|
StopCircleIcon,
|
|
9
13
|
} from "lucide-react";
|
|
10
|
-
import React, { memo, useEffect, useRef, useState } from "react";
|
|
14
|
+
import React, { memo, useEffect, useMemo, useRef, useState } from "react";
|
|
11
15
|
import useEvent from "react-use-event-hook";
|
|
12
16
|
import { useAcpClient } from "use-acp";
|
|
13
17
|
import {
|
|
14
18
|
ConnectionStatus,
|
|
15
19
|
PermissionRequest,
|
|
16
20
|
} from "@/components/chat/acp/common";
|
|
17
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
type AdditionalCompletions,
|
|
23
|
+
PromptInput,
|
|
24
|
+
} from "@/components/editor/ai/add-cell-with-ai";
|
|
18
25
|
import { PanelEmptyState } from "@/components/editor/chrome/panels/empty-state";
|
|
19
26
|
import { Spinner } from "@/components/icons/spinner";
|
|
20
27
|
import { Button } from "@/components/ui/button";
|
|
28
|
+
import { Input } from "@/components/ui/input";
|
|
29
|
+
import { Tooltip, TooltipProvider } from "@/components/ui/tooltip";
|
|
21
30
|
import { cn } from "@/utils/cn";
|
|
22
31
|
import { Logger } from "@/utils/Logger";
|
|
23
32
|
import { AgentDocs } from "./agent-docs";
|
|
@@ -34,27 +43,50 @@ import {
|
|
|
34
43
|
} from "./state";
|
|
35
44
|
import { AgentThread } from "./thread";
|
|
36
45
|
import "./agent-panel.css";
|
|
46
|
+
import type { Completion } from "@codemirror/autocomplete";
|
|
47
|
+
import type { ReactCodeMirrorRef } from "@uiw/react-codemirror";
|
|
37
48
|
import type {
|
|
38
|
-
|
|
49
|
+
ContentBlock,
|
|
39
50
|
RequestPermissionResponse,
|
|
40
|
-
WriteTextFileResponse,
|
|
41
51
|
} from "@zed-industries/agent-client-protocol";
|
|
52
|
+
import {
|
|
53
|
+
addContextCompletion,
|
|
54
|
+
CONTEXT_TRIGGER,
|
|
55
|
+
} from "@/components/editor/ai/completion-utils";
|
|
56
|
+
import {
|
|
57
|
+
Select,
|
|
58
|
+
SelectContent,
|
|
59
|
+
SelectGroup,
|
|
60
|
+
SelectItem,
|
|
61
|
+
SelectLabel,
|
|
62
|
+
SelectTrigger,
|
|
63
|
+
} from "@/components/ui/select";
|
|
42
64
|
import { toast } from "@/components/ui/use-toast";
|
|
43
65
|
import { useRequestClient } from "@/core/network/requests";
|
|
44
66
|
import { filenameAtom } from "@/core/saving/file-state";
|
|
45
67
|
import { store } from "@/core/state/jotai";
|
|
46
68
|
import { Functions } from "@/utils/functions";
|
|
47
69
|
import { Paths } from "@/utils/paths";
|
|
70
|
+
import { FileAttachmentPill } from "../chat-components";
|
|
71
|
+
import {
|
|
72
|
+
convertFilesToResourceLinks,
|
|
73
|
+
parseContextFromPrompt,
|
|
74
|
+
} from "./context-utils";
|
|
48
75
|
import { getAgentPrompt } from "./prompt";
|
|
49
76
|
import type {
|
|
50
77
|
AgentConnectionState,
|
|
51
78
|
AgentPendingPermission,
|
|
79
|
+
AvailableCommands,
|
|
52
80
|
ExternalAgentSessionId,
|
|
53
81
|
NotificationEvent,
|
|
82
|
+
SessionMode,
|
|
54
83
|
} from "./types";
|
|
55
84
|
|
|
56
85
|
const logger = Logger.get("agents");
|
|
57
86
|
|
|
87
|
+
// File attachment constants
|
|
88
|
+
const SUPPORTED_ATTACHMENT_TYPES = ["image/*", "text/*"];
|
|
89
|
+
|
|
58
90
|
interface AgentTitleProps {
|
|
59
91
|
currentAgentId?: ExternalAgentId;
|
|
60
92
|
}
|
|
@@ -171,35 +203,45 @@ interface EmptyStateProps {
|
|
|
171
203
|
}
|
|
172
204
|
|
|
173
205
|
const EmptyState = memo<EmptyStateProps>(
|
|
174
|
-
({ currentAgentId, connectionState, onConnect, onDisconnect }) =>
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
<
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
<AgentDocs
|
|
194
|
-
className="border-t pt-6"
|
|
195
|
-
title="Connect to an agent"
|
|
196
|
-
description="Start agents by running these commands in your terminal:"
|
|
206
|
+
({ currentAgentId, connectionState, onConnect, onDisconnect }) => {
|
|
207
|
+
const filename = useAtomValue(filenameAtom);
|
|
208
|
+
return (
|
|
209
|
+
<div className="flex flex-col h-full">
|
|
210
|
+
<AgentPanelHeader
|
|
211
|
+
connectionState={connectionState}
|
|
212
|
+
currentAgentId={currentAgentId}
|
|
213
|
+
onConnect={onConnect}
|
|
214
|
+
onDisconnect={onDisconnect}
|
|
215
|
+
hasActiveSession={false}
|
|
216
|
+
/>
|
|
217
|
+
<SessionTabs />
|
|
218
|
+
<div className="flex-1 flex items-center justify-center p-6">
|
|
219
|
+
<div className="max-w-md w-full space-y-6">
|
|
220
|
+
<PanelEmptyState
|
|
221
|
+
title="No Agent Sessions"
|
|
222
|
+
description="Create a new session to start a conversation"
|
|
223
|
+
action={<AgentSelector className="border-y-1 rounded" />}
|
|
224
|
+
icon={<BotMessageSquareIcon />}
|
|
197
225
|
/>
|
|
198
|
-
|
|
226
|
+
{connectionState.status === "disconnected" && (
|
|
227
|
+
<AgentDocs
|
|
228
|
+
className="border-t pt-6"
|
|
229
|
+
title="Connect to an agent"
|
|
230
|
+
description={
|
|
231
|
+
<>
|
|
232
|
+
Start agents by running these commands in your terminal:
|
|
233
|
+
<br />
|
|
234
|
+
Note: This must be in the directory{" "}
|
|
235
|
+
{Paths.dirname(filename ?? "")}
|
|
236
|
+
</>
|
|
237
|
+
}
|
|
238
|
+
/>
|
|
239
|
+
)}
|
|
240
|
+
</div>
|
|
199
241
|
</div>
|
|
200
242
|
</div>
|
|
201
|
-
|
|
202
|
-
|
|
243
|
+
);
|
|
244
|
+
},
|
|
203
245
|
);
|
|
204
246
|
EmptyState.displayName = "EmptyState";
|
|
205
247
|
|
|
@@ -248,8 +290,14 @@ interface PromptAreaProps {
|
|
|
248
290
|
isLoading: boolean;
|
|
249
291
|
activeSessionId: ExternalAgentSessionId | null;
|
|
250
292
|
promptValue: string;
|
|
293
|
+
commands: AvailableCommands | undefined;
|
|
251
294
|
onPromptValueChange: (value: string) => void;
|
|
252
295
|
onPromptSubmit: (e: KeyboardEvent | undefined, prompt: string) => void;
|
|
296
|
+
onAddFiles: (files: File[]) => void;
|
|
297
|
+
onStop: () => void;
|
|
298
|
+
fileInputRef: React.RefObject<HTMLInputElement | null>;
|
|
299
|
+
sessionMode?: SessionMode;
|
|
300
|
+
onModeChange?: (mode: string) => void;
|
|
253
301
|
}
|
|
254
302
|
|
|
255
303
|
const PromptArea = memo<PromptAreaProps>(
|
|
@@ -257,36 +305,191 @@ const PromptArea = memo<PromptAreaProps>(
|
|
|
257
305
|
isLoading,
|
|
258
306
|
activeSessionId,
|
|
259
307
|
promptValue,
|
|
308
|
+
commands,
|
|
260
309
|
onPromptValueChange,
|
|
261
310
|
onPromptSubmit,
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
>
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
311
|
+
onAddFiles,
|
|
312
|
+
onStop,
|
|
313
|
+
fileInputRef,
|
|
314
|
+
sessionMode,
|
|
315
|
+
onModeChange,
|
|
316
|
+
}) => {
|
|
317
|
+
const inputRef = useRef<ReactCodeMirrorRef | null>(null);
|
|
318
|
+
const promptCompletions: AdditionalCompletions | undefined = useMemo(() => {
|
|
319
|
+
if (!commands) {
|
|
320
|
+
return undefined;
|
|
321
|
+
}
|
|
322
|
+
// sentence has to begin with '/' to trigger autocomplete
|
|
323
|
+
return {
|
|
324
|
+
triggerCompletionRegex: /^\/(\w+)?/,
|
|
325
|
+
completions: commands.map(
|
|
326
|
+
(prompt): Completion => ({
|
|
327
|
+
label: `/${prompt.name}`,
|
|
328
|
+
info: prompt.description,
|
|
329
|
+
}),
|
|
330
|
+
),
|
|
331
|
+
};
|
|
332
|
+
}, [commands]);
|
|
333
|
+
|
|
334
|
+
const handleSendClick = useEvent(() => {
|
|
335
|
+
if (promptValue.trim()) {
|
|
336
|
+
onPromptSubmit(undefined, promptValue);
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
const handleAddContext = useEvent(() => {
|
|
341
|
+
// For now, just append @ to the current value
|
|
342
|
+
addContextCompletion(inputRef);
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
return (
|
|
346
|
+
<div className="border-t bg-background flex-shrink-0">
|
|
347
|
+
<div
|
|
348
|
+
className={cn(
|
|
349
|
+
"px-3 py-2 min-h-[80px]",
|
|
350
|
+
(isLoading || !activeSessionId) && "opacity-50 pointer-events-none",
|
|
351
|
+
)}
|
|
352
|
+
>
|
|
353
|
+
<PromptInput
|
|
354
|
+
inputRef={inputRef}
|
|
355
|
+
value={promptValue}
|
|
356
|
+
onChange={isLoading ? Functions.NOOP : onPromptValueChange}
|
|
357
|
+
onSubmit={onPromptSubmit}
|
|
358
|
+
additionalCompletions={promptCompletions}
|
|
359
|
+
onClose={Functions.NOOP}
|
|
360
|
+
onAddFiles={onAddFiles}
|
|
361
|
+
placeholder={
|
|
362
|
+
isLoading
|
|
363
|
+
? "Processing..."
|
|
364
|
+
: `Ask anything, ${CONTEXT_TRIGGER} to include context about tables or dataframes`
|
|
365
|
+
}
|
|
366
|
+
className={isLoading ? "opacity-50 pointer-events-none" : ""}
|
|
367
|
+
maxHeight="120px"
|
|
368
|
+
/>
|
|
369
|
+
</div>
|
|
370
|
+
<TooltipProvider>
|
|
371
|
+
<div className="px-3 py-2 border-t border-border/20 flex flex-row items-center justify-between">
|
|
372
|
+
<div className="flex items-center gap-2">
|
|
373
|
+
{sessionMode && onModeChange && (
|
|
374
|
+
<ModeSelector
|
|
375
|
+
sessionMode={sessionMode}
|
|
376
|
+
onModeChange={onModeChange}
|
|
377
|
+
/>
|
|
378
|
+
)}
|
|
379
|
+
</div>
|
|
380
|
+
<div className="flex flex-row">
|
|
381
|
+
<Tooltip content="Add context">
|
|
382
|
+
<Button variant="text" size="icon" onClick={handleAddContext}>
|
|
383
|
+
<AtSignIcon className="h-3.5 w-3.5" />
|
|
384
|
+
</Button>
|
|
385
|
+
</Tooltip>
|
|
386
|
+
<Tooltip content="Attach a file">
|
|
387
|
+
<Button
|
|
388
|
+
variant="text"
|
|
389
|
+
size="icon"
|
|
390
|
+
className="cursor-pointer"
|
|
391
|
+
onClick={() => fileInputRef.current?.click()}
|
|
392
|
+
title="Attach a file"
|
|
393
|
+
>
|
|
394
|
+
<PaperclipIcon className="h-3.5 w-3.5" />
|
|
395
|
+
</Button>
|
|
396
|
+
</Tooltip>
|
|
397
|
+
<Input
|
|
398
|
+
ref={fileInputRef}
|
|
399
|
+
type="file"
|
|
400
|
+
multiple={true}
|
|
401
|
+
hidden={true}
|
|
402
|
+
onChange={(event) => {
|
|
403
|
+
if (event.target.files) {
|
|
404
|
+
onAddFiles([...event.target.files]);
|
|
405
|
+
}
|
|
406
|
+
}}
|
|
407
|
+
accept={SUPPORTED_ATTACHMENT_TYPES.join(",")}
|
|
408
|
+
/>
|
|
409
|
+
<Tooltip content={isLoading ? "Stop" : "Submit"}>
|
|
410
|
+
<Button
|
|
411
|
+
variant="text"
|
|
412
|
+
size="sm"
|
|
413
|
+
className="h-6 w-6 p-0 hover:bg-muted/30 cursor-pointer"
|
|
414
|
+
onClick={isLoading ? onStop : handleSendClick}
|
|
415
|
+
disabled={isLoading ? false : !promptValue.trim()}
|
|
416
|
+
>
|
|
417
|
+
{isLoading ? (
|
|
418
|
+
<SquareIcon className="h-3 w-3 fill-current" />
|
|
419
|
+
) : (
|
|
420
|
+
<SendIcon className="h-3 w-3" />
|
|
421
|
+
)}
|
|
422
|
+
</Button>
|
|
423
|
+
</Tooltip>
|
|
424
|
+
</div>
|
|
425
|
+
</div>
|
|
426
|
+
</TooltipProvider>
|
|
427
|
+
</div>
|
|
428
|
+
);
|
|
429
|
+
},
|
|
280
430
|
);
|
|
281
431
|
PromptArea.displayName = "PromptArea";
|
|
282
432
|
|
|
433
|
+
interface ModeSelectorProps {
|
|
434
|
+
sessionMode: SessionMode;
|
|
435
|
+
onModeChange: (mode: string) => void;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
const ModeSelector = memo<ModeSelectorProps>(
|
|
439
|
+
({ sessionMode, onModeChange }) => {
|
|
440
|
+
const availableModes = sessionMode?.availableModes || [];
|
|
441
|
+
const currentModeId = sessionMode?.currentModeId;
|
|
442
|
+
if (availableModes.length === 0) {
|
|
443
|
+
return null;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
const modeOptions = availableModes.map((mode) => ({
|
|
447
|
+
value: mode.id,
|
|
448
|
+
label: mode.name,
|
|
449
|
+
subtitle: mode.description ?? "",
|
|
450
|
+
}));
|
|
451
|
+
const currentMode = modeOptions.find((opt) => opt.value === currentModeId);
|
|
452
|
+
|
|
453
|
+
return (
|
|
454
|
+
<Select value={currentModeId} onValueChange={onModeChange}>
|
|
455
|
+
<SelectTrigger className="h-6 text-xs border-border shadow-none! ring-0! bg-muted hover:bg-muted/30 py-0 px-2 gap-1 capitalize">
|
|
456
|
+
{currentMode?.label ?? currentModeId}
|
|
457
|
+
</SelectTrigger>
|
|
458
|
+
<SelectContent>
|
|
459
|
+
<SelectGroup>
|
|
460
|
+
<SelectLabel>Agent Mode</SelectLabel>
|
|
461
|
+
{modeOptions.map((option) => (
|
|
462
|
+
<SelectItem
|
|
463
|
+
key={option.value}
|
|
464
|
+
value={option.value}
|
|
465
|
+
className="text-xs"
|
|
466
|
+
>
|
|
467
|
+
<div className="flex flex-col">
|
|
468
|
+
{option.label}
|
|
469
|
+
{option.subtitle && (
|
|
470
|
+
<div className="text-muted-foreground text-xs pt-1 block">
|
|
471
|
+
{option.subtitle}
|
|
472
|
+
</div>
|
|
473
|
+
)}
|
|
474
|
+
</div>
|
|
475
|
+
</SelectItem>
|
|
476
|
+
))}
|
|
477
|
+
</SelectGroup>
|
|
478
|
+
</SelectContent>
|
|
479
|
+
</Select>
|
|
480
|
+
);
|
|
481
|
+
},
|
|
482
|
+
);
|
|
483
|
+
ModeSelector.displayName = "ModeSelector";
|
|
484
|
+
|
|
283
485
|
interface ChatContentProps {
|
|
284
486
|
hasNotifications: boolean;
|
|
487
|
+
agentId: ExternalAgentId | undefined;
|
|
285
488
|
connectionState: AgentConnectionState;
|
|
286
489
|
sessionId: ExternalAgentSessionId | null;
|
|
287
490
|
notifications: NotificationEvent[];
|
|
288
491
|
pendingPermission: AgentPendingPermission;
|
|
289
|
-
onResolvePermission: (option:
|
|
492
|
+
onResolvePermission: (option: RequestPermissionResponse) => void;
|
|
290
493
|
onRetryConnection?: () => void;
|
|
291
494
|
onRetryLastAction?: () => void;
|
|
292
495
|
onDismissError?: (errorId: string) => void;
|
|
@@ -295,6 +498,7 @@ interface ChatContentProps {
|
|
|
295
498
|
const ChatContent = memo<ChatContentProps>(
|
|
296
499
|
({
|
|
297
500
|
hasNotifications,
|
|
501
|
+
agentId,
|
|
298
502
|
connectionState,
|
|
299
503
|
notifications,
|
|
300
504
|
pendingPermission,
|
|
@@ -306,6 +510,7 @@ const ChatContent = memo<ChatContentProps>(
|
|
|
306
510
|
}) => {
|
|
307
511
|
const [isScrolledToBottom, setIsScrolledToBottom] = useState(true);
|
|
308
512
|
const scrollContainerRef = useRef<HTMLDivElement>(null);
|
|
513
|
+
const isDisconnected = connectionState.status === "disconnected";
|
|
309
514
|
|
|
310
515
|
// Scroll handler to determine if we're at the bottom of the chat
|
|
311
516
|
const handleScroll = useEvent(() => {
|
|
@@ -375,12 +580,30 @@ const ChatContent = memo<ChatContentProps>(
|
|
|
375
580
|
/>
|
|
376
581
|
</div>
|
|
377
582
|
) : (
|
|
378
|
-
<div className="flex items-center justify-center h-full min-h-[200px]">
|
|
583
|
+
<div className="flex items-center justify-center h-full min-h-[200px] flex-col">
|
|
379
584
|
<PanelEmptyState
|
|
380
585
|
title="Waiting for agent"
|
|
381
586
|
description="Your AI agent will appear here when active"
|
|
382
587
|
icon={<BotMessageSquareIcon />}
|
|
383
588
|
/>
|
|
589
|
+
{isDisconnected && agentId && (
|
|
590
|
+
<AgentDocs
|
|
591
|
+
className="border-t pt-6 px-5"
|
|
592
|
+
title="Make sure you're connected to an agent"
|
|
593
|
+
description="Run this command in your terminal:"
|
|
594
|
+
agents={[agentId]}
|
|
595
|
+
/>
|
|
596
|
+
)}
|
|
597
|
+
{isDisconnected && (
|
|
598
|
+
<Button
|
|
599
|
+
variant="outline"
|
|
600
|
+
onClick={onRetryConnection}
|
|
601
|
+
type="button"
|
|
602
|
+
className="mt-4"
|
|
603
|
+
>
|
|
604
|
+
Retry
|
|
605
|
+
</Button>
|
|
606
|
+
)}
|
|
384
607
|
</div>
|
|
385
608
|
)}
|
|
386
609
|
</div>
|
|
@@ -408,6 +631,8 @@ function getCwd() {
|
|
|
408
631
|
const AgentPanel: React.FC = () => {
|
|
409
632
|
const [isLoading, setIsLoading] = useState(false);
|
|
410
633
|
const [promptValue, setPromptValue] = useState("");
|
|
634
|
+
const [files, setFiles] = useState<File[]>();
|
|
635
|
+
const fileInputRef = useRef<HTMLInputElement>(null);
|
|
411
636
|
|
|
412
637
|
const [selectedTab] = useAtom(selectedTabAtom);
|
|
413
638
|
const [sessionState, setSessionState] = useAtom(agentSessionStateAtom);
|
|
@@ -421,7 +646,7 @@ const AgentPanel: React.FC = () => {
|
|
|
421
646
|
const acpClient = useAcpClient({
|
|
422
647
|
wsUrl,
|
|
423
648
|
clientOptions: {
|
|
424
|
-
readTextFile: (request)
|
|
649
|
+
readTextFile: (request) => {
|
|
425
650
|
logger.debug("Agent requesting file read", {
|
|
426
651
|
path: request.path,
|
|
427
652
|
});
|
|
@@ -429,7 +654,7 @@ const AgentPanel: React.FC = () => {
|
|
|
429
654
|
content: response.contents || "",
|
|
430
655
|
}));
|
|
431
656
|
},
|
|
432
|
-
writeTextFile: (request)
|
|
657
|
+
writeTextFile: (request) => {
|
|
433
658
|
logger.debug("Agent requesting file write", {
|
|
434
659
|
path: request.path,
|
|
435
660
|
contentLength: request.content.length,
|
|
@@ -437,7 +662,7 @@ const AgentPanel: React.FC = () => {
|
|
|
437
662
|
return sendUpdateFile({
|
|
438
663
|
path: request.path,
|
|
439
664
|
contents: request.content,
|
|
440
|
-
}).then(() =>
|
|
665
|
+
}).then(() => ({}));
|
|
441
666
|
},
|
|
442
667
|
},
|
|
443
668
|
autoConnect: false, // We'll manage connection manually based on active session
|
|
@@ -449,11 +674,25 @@ const AgentPanel: React.FC = () => {
|
|
|
449
674
|
connectionState,
|
|
450
675
|
notifications,
|
|
451
676
|
pendingPermission,
|
|
677
|
+
availableCommands,
|
|
452
678
|
resolvePermission,
|
|
679
|
+
sessionMode,
|
|
453
680
|
activeSessionId,
|
|
454
681
|
agent,
|
|
455
682
|
} = acpClient;
|
|
456
683
|
|
|
684
|
+
useEffect(() => {
|
|
685
|
+
agent?.initialize({
|
|
686
|
+
protocolVersion: 1,
|
|
687
|
+
clientCapabilities: {
|
|
688
|
+
fs: {
|
|
689
|
+
readTextFile: true,
|
|
690
|
+
writeTextFile: true,
|
|
691
|
+
},
|
|
692
|
+
},
|
|
693
|
+
});
|
|
694
|
+
}, [agent]);
|
|
695
|
+
|
|
457
696
|
// Auto-connect to agent when we have an active session, but only once per session
|
|
458
697
|
useEffect(() => {
|
|
459
698
|
if (wsUrl === NO_WS_SET) {
|
|
@@ -581,6 +820,7 @@ const AgentPanel: React.FC = () => {
|
|
|
581
820
|
});
|
|
582
821
|
setIsLoading(true);
|
|
583
822
|
setPromptValue("");
|
|
823
|
+
setFiles(undefined);
|
|
584
824
|
|
|
585
825
|
// Update session title with first message if it's still the default
|
|
586
826
|
if (selectedTab?.title.startsWith("New ")) {
|
|
@@ -597,26 +837,47 @@ const AgentPanel: React.FC = () => {
|
|
|
597
837
|
return;
|
|
598
838
|
}
|
|
599
839
|
|
|
840
|
+
const promptBlocks: ContentBlock[] = [{ type: "text", text: prompt }];
|
|
841
|
+
|
|
842
|
+
// Parse context from the prompt
|
|
843
|
+
const { contextBlocks, attachmentBlocks } =
|
|
844
|
+
await parseContextFromPrompt(prompt);
|
|
845
|
+
promptBlocks.push(...contextBlocks, ...attachmentBlocks);
|
|
846
|
+
|
|
847
|
+
// Add manually uploaded files as resource links
|
|
848
|
+
if (files && files.length > 0) {
|
|
849
|
+
const fileResourceLinks = await convertFilesToResourceLinks(files);
|
|
850
|
+
promptBlocks.push(...fileResourceLinks);
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
const hasGivenRules = notifications.some(
|
|
854
|
+
(notification) =>
|
|
855
|
+
notification.type === "session_notification" &&
|
|
856
|
+
notification.data.update.sessionUpdate === "user_message_chunk",
|
|
857
|
+
);
|
|
858
|
+
if (!hasGivenRules) {
|
|
859
|
+
promptBlocks.push(
|
|
860
|
+
{
|
|
861
|
+
type: "resource_link",
|
|
862
|
+
uri: filename,
|
|
863
|
+
mimeType: "text/x-python",
|
|
864
|
+
name: filename,
|
|
865
|
+
},
|
|
866
|
+
{
|
|
867
|
+
type: "resource",
|
|
868
|
+
resource: {
|
|
869
|
+
uri: "marimo_rules.md",
|
|
870
|
+
mimeType: "text/markdown",
|
|
871
|
+
text: getAgentPrompt(filename),
|
|
872
|
+
},
|
|
873
|
+
},
|
|
874
|
+
);
|
|
875
|
+
}
|
|
876
|
+
|
|
600
877
|
try {
|
|
601
878
|
await agent.prompt({
|
|
602
879
|
sessionId: activeSessionId,
|
|
603
|
-
prompt:
|
|
604
|
-
{ type: "text", text: prompt },
|
|
605
|
-
{
|
|
606
|
-
type: "resource_link",
|
|
607
|
-
uri: filename,
|
|
608
|
-
mimeType: "text/x-python",
|
|
609
|
-
name: filename,
|
|
610
|
-
},
|
|
611
|
-
{
|
|
612
|
-
type: "resource",
|
|
613
|
-
resource: {
|
|
614
|
-
uri: "marimo_rules.md",
|
|
615
|
-
mimeType: "text/markdown",
|
|
616
|
-
text: getAgentPrompt(filename),
|
|
617
|
-
},
|
|
618
|
-
},
|
|
619
|
-
],
|
|
880
|
+
prompt: promptBlocks,
|
|
620
881
|
});
|
|
621
882
|
} catch (error) {
|
|
622
883
|
logger.error("Failed to send prompt", { error });
|
|
@@ -635,6 +896,21 @@ const AgentPanel: React.FC = () => {
|
|
|
635
896
|
setIsLoading(false);
|
|
636
897
|
});
|
|
637
898
|
|
|
899
|
+
// Handler for adding files
|
|
900
|
+
const handleAddFiles = useEvent((newFiles: File[]) => {
|
|
901
|
+
if (newFiles.length === 0) {
|
|
902
|
+
return;
|
|
903
|
+
}
|
|
904
|
+
setFiles((prev) => [...(prev ?? []), ...newFiles]);
|
|
905
|
+
});
|
|
906
|
+
|
|
907
|
+
// Handler for removing files
|
|
908
|
+
const handleRemoveFile = useEvent((fileToRemove: File) => {
|
|
909
|
+
if (files) {
|
|
910
|
+
setFiles(files.filter((f) => f !== fileToRemove));
|
|
911
|
+
}
|
|
912
|
+
});
|
|
913
|
+
|
|
638
914
|
// Handler for manual connect
|
|
639
915
|
const handleManualConnect = useEvent(() => {
|
|
640
916
|
logger.debug("Manual connect requested", {
|
|
@@ -652,6 +928,33 @@ const AgentPanel: React.FC = () => {
|
|
|
652
928
|
disconnect();
|
|
653
929
|
});
|
|
654
930
|
|
|
931
|
+
const handleModeChange = useEvent((mode: string) => {
|
|
932
|
+
logger.debug("Mode change requested", {
|
|
933
|
+
sessionId: activeSessionId,
|
|
934
|
+
mode,
|
|
935
|
+
});
|
|
936
|
+
if (!agent) {
|
|
937
|
+
toast({
|
|
938
|
+
title: "Agent not connected",
|
|
939
|
+
description: "Please connect to an agent to change the mode",
|
|
940
|
+
variant: "danger",
|
|
941
|
+
});
|
|
942
|
+
return;
|
|
943
|
+
}
|
|
944
|
+
if (!agent.setSessionMode) {
|
|
945
|
+
toast({
|
|
946
|
+
title: "Mode change not supported",
|
|
947
|
+
description: "The agent does not support mode changes",
|
|
948
|
+
variant: "danger",
|
|
949
|
+
});
|
|
950
|
+
return;
|
|
951
|
+
}
|
|
952
|
+
void agent.setSessionMode?.({
|
|
953
|
+
sessionId: activeSessionId as string,
|
|
954
|
+
modeId: mode,
|
|
955
|
+
});
|
|
956
|
+
});
|
|
957
|
+
|
|
655
958
|
const hasNotifications = notifications.length > 0;
|
|
656
959
|
const hasActiveSessions = sessionState.sessions.length > 0;
|
|
657
960
|
|
|
@@ -680,6 +983,7 @@ const AgentPanel: React.FC = () => {
|
|
|
680
983
|
<SessionTabs />
|
|
681
984
|
|
|
682
985
|
<ChatContent
|
|
986
|
+
agentId={selectedTab?.agentId}
|
|
683
987
|
sessionId={activeSessionId}
|
|
684
988
|
hasNotifications={hasNotifications}
|
|
685
989
|
connectionState={connectionState}
|
|
@@ -690,7 +994,7 @@ const AgentPanel: React.FC = () => {
|
|
|
690
994
|
sessionId: activeSessionId,
|
|
691
995
|
option,
|
|
692
996
|
});
|
|
693
|
-
resolvePermission(option
|
|
997
|
+
resolvePermission(option);
|
|
694
998
|
}}
|
|
695
999
|
onRetryConnection={handleManualConnect}
|
|
696
1000
|
/>
|
|
@@ -701,12 +1005,30 @@ const AgentPanel: React.FC = () => {
|
|
|
701
1005
|
onStop={handleStop}
|
|
702
1006
|
/>
|
|
703
1007
|
|
|
1008
|
+
{files && files.length > 0 && (
|
|
1009
|
+
<div className="flex flex-row gap-1 flex-wrap p-3 border-t">
|
|
1010
|
+
{files.map((file) => (
|
|
1011
|
+
<FileAttachmentPill
|
|
1012
|
+
file={file}
|
|
1013
|
+
key={file.name}
|
|
1014
|
+
onRemove={() => handleRemoveFile(file)}
|
|
1015
|
+
/>
|
|
1016
|
+
))}
|
|
1017
|
+
</div>
|
|
1018
|
+
)}
|
|
1019
|
+
|
|
704
1020
|
<PromptArea
|
|
705
1021
|
isLoading={isLoading}
|
|
706
1022
|
activeSessionId={activeSessionId}
|
|
707
1023
|
promptValue={promptValue}
|
|
708
1024
|
onPromptValueChange={setPromptValue}
|
|
709
1025
|
onPromptSubmit={handlePromptSubmit}
|
|
1026
|
+
onAddFiles={handleAddFiles}
|
|
1027
|
+
onStop={handleStop}
|
|
1028
|
+
fileInputRef={fileInputRef}
|
|
1029
|
+
commands={availableCommands}
|
|
1030
|
+
sessionMode={sessionMode}
|
|
1031
|
+
onModeChange={handleModeChange}
|
|
710
1032
|
/>
|
|
711
1033
|
</div>
|
|
712
1034
|
);
|
|
@@ -13,7 +13,9 @@ import {
|
|
|
13
13
|
DropdownMenuSeparator,
|
|
14
14
|
DropdownMenuTrigger,
|
|
15
15
|
} from "@/components/ui/dropdown-menu";
|
|
16
|
+
import { useFilename } from "@/core/saving/filename";
|
|
16
17
|
import { cn } from "@/utils/cn";
|
|
18
|
+
import { Paths } from "@/utils/paths";
|
|
17
19
|
import { AgentDocs } from "./agent-docs";
|
|
18
20
|
import {
|
|
19
21
|
type AgentSession,
|
|
@@ -79,6 +81,7 @@ AgentMenuItem.displayName = "AgentMenuItem";
|
|
|
79
81
|
|
|
80
82
|
export const AgentSelector: React.FC<AgentSelectorProps> = memo(
|
|
81
83
|
({ onSessionCreated, className }) => {
|
|
84
|
+
const filename = useFilename();
|
|
82
85
|
const [sessionState, setSessionState] = useAtom(agentSessionStateAtom);
|
|
83
86
|
const setActiveTab = useSetAtom(selectedTabAtom);
|
|
84
87
|
const [isOpen, setIsOpen] = useState(false);
|
|
@@ -123,7 +126,10 @@ export const AgentSelector: React.FC<AgentSelectorProps> = memo(
|
|
|
123
126
|
<div className="px-2 py-2">
|
|
124
127
|
<div className="text-xs font-medium text-muted-foreground mb-3">
|
|
125
128
|
To start an external agent, run the following command in your
|
|
126
|
-
terminal
|
|
129
|
+
terminal.
|
|
130
|
+
<br />
|
|
131
|
+
Note: This must be in the directory{" "}
|
|
132
|
+
{Paths.dirname(filename ?? "")}
|
|
127
133
|
</div>
|
|
128
134
|
<AgentDocs
|
|
129
135
|
agents={AVAILABLE_AGENTS.map((agent) => agent.id)}
|