@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.
Files changed (325) hide show
  1. package/dist/assets/ConnectedDataExplorerComponent-CNLoZkWr.js +19 -0
  2. package/dist/assets/{ImageComparisonComponent-CEXMKKA4.js → ImageComparisonComponent-SX7fDaTK.js} +1 -1
  3. package/dist/assets/{VegaLite-Bt14Ds9k.js → VegaLite-MJUW3b7C.js} +6 -6
  4. package/dist/assets/_baseEach-9_logFrf.js +1 -0
  5. package/dist/assets/_baseMap-NzEbKt5c.js +1 -0
  6. package/dist/assets/_baseUniq-C5LFcyNC.js +1 -0
  7. package/dist/assets/_createAggregator-ZRm2b6Zm.js +1 -0
  8. package/dist/assets/agent-panel-BBd11wNX.js +287 -0
  9. package/dist/assets/agent-panel-D92Mfy1i.css +1 -0
  10. package/dist/assets/{any-language-editor-DiwNT6zp.js → any-language-editor-DwAaEQfS.js} +1 -1
  11. package/dist/assets/architectureDiagram-W76B3OCA-BJmVXUoW.js +36 -0
  12. package/dist/assets/{between-horizontal-start-FyewyCGn.js → between-horizontal-start-KiwU-a3C.js} +1 -1
  13. package/dist/assets/{blockDiagram-QIGZ2CNN-BrOkAf_c.js → blockDiagram-QIGZ2CNN-DzxZjE7B.js} +1 -1
  14. package/dist/assets/{c4Diagram-FPNF74CW-BHPzDxE2.js → c4Diagram-FPNF74CW-DjmldG_J.js} +5 -5
  15. package/dist/assets/channel-DHcKBVM4.js +1 -0
  16. package/dist/assets/chat-panel-DgJZr0eS.js +3 -0
  17. package/dist/assets/{chunk-4BX2VUAB-DLxaCNYh.js → chunk-4BX2VUAB-EUTQThiZ.js} +1 -1
  18. package/dist/assets/{chunk-55IACEB6-DdzvO3HR.js → chunk-55IACEB6-DZAiDJxy.js} +1 -1
  19. package/dist/assets/{chunk-FMBD7UC4-R5o-nSiG.js → chunk-FMBD7UC4-Bd0Czs-J.js} +1 -1
  20. package/dist/assets/{chunk-K7UQS3LO-DxaMrGgG.js → chunk-K7UQS3LO-DEKMIknX.js} +1 -1
  21. package/dist/assets/{chunk-QN33PNHL-DqS9-FYm.js → chunk-QN33PNHL-E0jwHU_n.js} +1 -1
  22. package/dist/assets/{chunk-QZHKN3VN-BZ-TzajS.js → chunk-QZHKN3VN-BzaIHJbq.js} +1 -1
  23. package/dist/assets/{chunk-TVAH2DTR-BsgP2dyv.js → chunk-TVAH2DTR-CZFYvqnm.js} +1 -1
  24. package/dist/assets/{chunk-TZMSLE5B-D-h3ahXI.js → chunk-TZMSLE5B-BNqnFjtv.js} +1 -1
  25. package/dist/assets/{circle-play-CQtRZ-rT.js → circle-play-D3J_mYrF.js} +1 -1
  26. package/dist/assets/classDiagram-KNZD7YFC-D-xwLnlX.js +1 -0
  27. package/dist/assets/classDiagram-v2-RKCZMP56-D-xwLnlX.js +1 -0
  28. package/dist/assets/{clear-button-BY6Z_ViL.js → clear-button-ifzRuAR3.js} +1 -1
  29. package/dist/assets/clone-CSxIll62.js +1 -0
  30. package/dist/assets/command-palette-D2fdVSET.js +1 -0
  31. package/dist/assets/common-Ku-cF_2J.js +1 -0
  32. package/dist/assets/{compile-Ct_jzdKr.js → compile-BgZlHW1c.js} +1 -1
  33. package/dist/assets/cose-bilkent-S5V4N54A-CVM83SqK.js +1 -0
  34. package/dist/assets/dagre-5GWH7T2D-ouQPkxT3.js +4 -0
  35. package/dist/assets/{data-grid-overlay-editor-BN_wulc3.js → data-grid-overlay-editor-B47j5GJJ.js} +1 -1
  36. package/dist/assets/datasources-panel-Bt41Zir-.js +1 -0
  37. package/dist/assets/{dependency-graph-panel-BOmSCZf7.js → dependency-graph-panel-CZC_B7pK.js} +4 -4
  38. package/dist/assets/diagram-N5W7TBWH-CQ817ZdR.js +24 -0
  39. package/dist/assets/diagram-QEK2KX5R-DOK_psUO.js +43 -0
  40. package/dist/assets/diagram-S2PKOQOG-CVljmOW8.js +24 -0
  41. package/dist/assets/{documentation-panel-BxjJO_Gw.js → documentation-panel-C7yIvGg1.js} +1 -1
  42. package/dist/assets/edit-page-CyTMQV2u.js +129 -0
  43. package/dist/assets/{ellipsis-vertical-UHbmjI2n.js → ellipsis-vertical-C7FjlUsY.js} +1 -1
  44. package/dist/assets/{empty-state-BIBXzY_0.js → empty-state-DIOGM_CU.js} +1 -1
  45. package/dist/assets/{erDiagram-AWTI2OKA-E84mAle_.js → erDiagram-AWTI2OKA-DYu8cEdc.js} +1 -1
  46. package/dist/assets/{error-panel-MEvQ6K7h.js → error-panel-Ddb8RkFG.js} +1 -1
  47. package/dist/assets/file-explorer-panel-Oy9DbyFP.js +1 -0
  48. package/dist/assets/{flowDiagram-PVAE7QVJ-DfbIRSAW.js → flowDiagram-PVAE7QVJ-CmvW5iTb.js} +1 -1
  49. package/dist/assets/{ganttDiagram-OWAHRB6G-DR4HZ1z_.js → ganttDiagram-OWAHRB6G-BaKQlCaT.js} +4 -4
  50. package/dist/assets/gitGraphDiagram-NY62KEGX-CWO24eP6.js +65 -0
  51. package/dist/assets/{glide-data-editor-nNmo1lPq.js → glide-data-editor-CNDLEJ9a.js} +11 -11
  52. package/dist/assets/graph-BZKTtxsc.js +1 -0
  53. package/dist/assets/home-page-Bvwppn9N.js +9 -0
  54. package/dist/assets/{index-VPWqq2Pg.js → index-0XOUPdwT.js} +1 -1
  55. package/dist/assets/{index-uacyUula.js → index-BH7f3aiU.js} +1 -1
  56. package/dist/assets/{index-Dt9UWeWn.js → index-BJVyzkx5.js} +1 -1
  57. package/dist/assets/{index-BAH034Ue.js → index-B_d_JZGI.js} +1 -1
  58. package/dist/assets/{index-CB2pnVQG.js → index-BgXbBA39.js} +1 -1
  59. package/dist/assets/{index-B8llrTSo.js → index-Brf2DwUM.js} +1 -1
  60. package/dist/assets/{index-BLu5CX6z.js → index-CXrWwFX6.js} +1 -1
  61. package/dist/assets/{index-DyLSuOH1.js → index-CZaurnA9.js} +1 -1
  62. package/dist/assets/{index-BFSnz7iM.js → index-CerjupfZ.js} +1 -1
  63. package/dist/assets/{index-B7yXbrLa.js → index-D-tZfElD.js} +1 -1
  64. package/dist/assets/{index-c6If577Q.js → index-D3PqGupX.js} +1 -1
  65. package/dist/assets/{index-CSgxTUzD.js → index-DCkzth56.js} +1 -1
  66. package/dist/assets/{index-DWOaniGT.js → index-DFrGFNW1.js} +1 -1
  67. package/dist/assets/{index-CPN7TRA1.js → index-DZhOPkOB.js} +1 -1
  68. package/dist/assets/index-DadI618h.css +1 -0
  69. package/dist/assets/{index-DqzMPAC8.js → index-DkntzpX4.js} +2 -2
  70. package/dist/assets/{index-B1_GXGaP.js → index-DmgwT3sx.js} +1 -1
  71. package/dist/assets/index-PmY0x4Zd.js +578 -0
  72. package/dist/assets/{index-Bq516OmX.js → index-WXJFkQHg.js} +1 -1
  73. package/dist/assets/{index-DSU75csX.js → index-qE8lHQ-N.js} +1 -1
  74. package/dist/assets/{index-DMomwMcN.js → index-zrSUQXha.js} +1 -1
  75. package/dist/assets/infoDiagram-STP46IZ2-CAuVVehw.js +2 -0
  76. package/dist/assets/isEmpty-D1t7Gran.js +1 -0
  77. package/dist/assets/{journeyDiagram-BIP6EPQ6-BBiFyygf.js → journeyDiagram-BIP6EPQ6-D4Rp6H_h.js} +1 -1
  78. package/dist/assets/{kanban-definition-6OIFK2YF-DhgA6Nt6.js → kanban-definition-6OIFK2YF-DFt9DftA.js} +4 -4
  79. package/dist/assets/layout-D8WXi2_g.js +1 -0
  80. package/dist/assets/linear-BwY8e5hA.js +1 -0
  81. package/dist/assets/links-4B6ldZ5P.js +7 -0
  82. package/dist/assets/{logs-panel-B9SmTZAW.js → logs-panel-Dxiyt7dO.js} +1 -1
  83. package/dist/assets/{agent-panel-DpQ6muj-.css → markdown-renderer-ClyzDMmG.css} +1 -1
  84. package/dist/assets/markdown-renderer-VDu-NBKB.js +263 -0
  85. package/dist/assets/mermaid-B-O-Puyi.js +1 -0
  86. package/dist/assets/{mermaid.core-4nVOEVX3.js → mermaid.core-BFFCqfOn.js} +41 -41
  87. package/dist/assets/min-DtVSfYKl.js +1 -0
  88. package/dist/assets/{mindmap-definition-Q6HEUPPD-CVLQNn1q.js → mindmap-definition-Q6HEUPPD-kyvIY8Dg.js} +2 -2
  89. package/dist/assets/{number-overlay-editor-CzRzXLcd.js → number-overlay-editor-GjLB2UK4.js} +1 -1
  90. package/dist/assets/outline-panel-CMJjOoN7.js +1 -0
  91. package/dist/assets/packages-panel-nfXB-bKW.js +1 -0
  92. package/dist/assets/{pieDiagram-ADFJNKIX-C5IQ5DBZ.js → pieDiagram-ADFJNKIX-D8JFQcWR.js} +3 -3
  93. package/dist/assets/{quadrantDiagram-LMRXKWRM-CFXFnQxx.js → quadrantDiagram-LMRXKWRM-Nf8GzxXG.js} +1 -1
  94. package/dist/assets/{react-plotly-mzdv02_Y.js → react-plotly-CnW9p7ZA.js} +1 -1
  95. package/dist/assets/{requirementDiagram-4UW4RH46-D9bPC89T.js → requirementDiagram-4UW4RH46-CCUxF8BZ.js} +1 -1
  96. package/dist/assets/run-page-Bl4p3AbZ.js +1 -0
  97. package/dist/assets/sankeyDiagram-GR3RE2ED-Sr8kDwP1.js +10 -0
  98. package/dist/assets/scratchpad-panel-Ja1Mu-W3.js +1 -0
  99. package/dist/assets/secrets-panel-B-3fcSyP.js +1 -0
  100. package/dist/assets/{sequenceDiagram-C3RYC4MD-6N7_hY4k.js → sequenceDiagram-C3RYC4MD-CBJ152Q3.js} +4 -4
  101. package/dist/assets/{slides-component-DMjQomc3.css → slides-component-C-LoGC1U.css} +1 -1
  102. package/dist/assets/{slides-component-EcjC8sDK.js → slides-component-DGtsVP5o.js} +1 -1
  103. package/dist/assets/snippets-panel-ClNnwKBM.js +1 -0
  104. package/dist/assets/sortBy-D47H6Vyl.js +1 -0
  105. package/dist/assets/state-B_RCHTH5.js +1 -0
  106. package/dist/assets/stateDiagram-KXAO66HF-BlBFSAZr.js +1 -0
  107. package/dist/assets/stateDiagram-v2-UMBNRL4Z-DbA-iToo.js +1 -0
  108. package/dist/assets/storage-BNcWOH3-.js +26 -0
  109. package/dist/assets/terminal-CATzv5Hd.js +10 -0
  110. package/dist/assets/time-CsYqILfB.js +1 -0
  111. package/dist/assets/{timeline-definition-XQNQX7LJ-BEaynAiY.js → timeline-definition-XQNQX7LJ-CGrhjuAs.js} +1 -1
  112. package/dist/assets/tracing-DUbJtOyq.js +2 -0
  113. package/dist/assets/{tracing-panel-BmuHLPrY.js → tracing-panel-DmzqPUtc.js} +2 -2
  114. package/dist/assets/{trash-UBqfK4mR.js → trash-rxdjLzkf.js} +1 -1
  115. package/dist/assets/{tree-XiEycetl.js → tree-C2Ul1h1C.js} +1 -1
  116. package/dist/assets/{treemap-75Q7IDZK-CnuVFbBG.js → treemap-75Q7IDZK-N9hyUpyj.js} +20 -20
  117. package/dist/assets/{ts-tags-CloPe9IY.js → ts-tags-DxCDHihD.js} +1 -1
  118. package/dist/assets/variable-panel-BbgupOdG.js +1 -0
  119. package/dist/assets/{vega-component-DsTH4tuX.js → vega-component-CR_MHOBT.js} +1 -1
  120. package/dist/assets/worker-fHbtoWvT.js +1 -0
  121. package/dist/assets/{xychartDiagram-6GGTOJPD-Dcz3O-A3.js → xychartDiagram-6GGTOJPD-jdLZsMb2.js} +1 -1
  122. package/dist/index.html +2 -2
  123. package/package.json +10 -5
  124. package/src/__tests__/mocks.ts +43 -0
  125. package/src/components/app-config/user-config-form.tsx +78 -1
  126. package/src/components/chat/acp/__tests__/__snapshots__/prompt.test.ts.snap +116 -65
  127. package/src/components/chat/acp/__tests__/atoms.test.ts +1 -1
  128. package/src/components/chat/acp/__tests__/context-utils.test.ts +222 -0
  129. package/src/components/chat/acp/__tests__/prompt.test.ts +1 -1
  130. package/src/components/chat/acp/__tests__/state.test.ts +38 -42
  131. package/src/components/chat/acp/agent-docs.tsx +33 -6
  132. package/src/components/chat/acp/agent-panel.css +0 -18
  133. package/src/components/chat/acp/agent-panel.tsx +394 -72
  134. package/src/components/chat/acp/agent-selector.tsx +7 -1
  135. package/src/components/chat/acp/blocks.tsx +40 -10
  136. package/src/components/chat/acp/common.tsx +10 -2
  137. package/src/components/chat/acp/context-utils.ts +127 -0
  138. package/src/components/chat/acp/prompt.ts +96 -53
  139. package/src/components/chat/acp/state.ts +1 -1
  140. package/src/components/chat/acp/types.ts +8 -0
  141. package/src/components/chat/chat-panel.tsx +28 -89
  142. package/src/components/chat/chat-utils.ts +127 -1
  143. package/src/components/chat/markdown-renderer.css +39 -0
  144. package/src/components/chat/markdown-renderer.tsx +12 -47
  145. package/src/components/chat/tool-call-accordion.tsx +148 -26
  146. package/src/components/data-table/SearchBar.tsx +8 -7
  147. package/src/components/data-table/__tests__/column_formatting.test.ts +50 -35
  148. package/src/components/data-table/__tests__/data-table.test.tsx +39 -1
  149. package/src/components/data-table/cell-hover-template/feature.ts +14 -0
  150. package/src/components/data-table/cell-hover-template/types.ts +11 -0
  151. package/src/components/data-table/charts/components/form-fields.tsx +41 -37
  152. package/src/components/data-table/charts/forms/common-chart.tsx +2 -2
  153. package/src/components/data-table/column-explorer-panel/column-explorer.tsx +5 -2
  154. package/src/components/data-table/column-formatting/feature.ts +62 -29
  155. package/src/components/data-table/column-formatting/types.ts +1 -0
  156. package/src/components/data-table/column-header.tsx +3 -1
  157. package/src/components/data-table/column-summary/chart-spec-model.tsx +24 -7
  158. package/src/components/data-table/column-summary/column-summary.tsx +18 -9
  159. package/src/components/data-table/columns.tsx +42 -18
  160. package/src/components/data-table/data-table.tsx +10 -2
  161. package/src/components/data-table/date-popover.tsx +85 -75
  162. package/src/components/data-table/filter-pills.tsx +14 -9
  163. package/src/components/data-table/header-items.tsx +5 -1
  164. package/src/components/data-table/pagination.tsx +20 -13
  165. package/src/components/data-table/renderers.tsx +28 -0
  166. package/src/components/data-table/row-viewer-panel/row-viewer.tsx +10 -8
  167. package/src/components/datasources/column-preview.tsx +6 -2
  168. package/src/components/datasources/datasources.tsx +8 -12
  169. package/src/components/editor/Cell.tsx +6 -0
  170. package/src/components/editor/actions/name-cell-input.tsx +6 -1
  171. package/src/components/editor/actions/useCellActionButton.tsx +3 -1
  172. package/src/components/editor/ai/__tests__/completion-utils.test.ts +178 -1
  173. package/src/components/editor/ai/add-cell-with-ai.tsx +68 -66
  174. package/src/components/editor/ai/ai-completion-editor.tsx +29 -26
  175. package/src/components/editor/ai/completion-handlers.tsx +44 -6
  176. package/src/components/editor/ai/completion-utils.ts +92 -0
  177. package/src/components/editor/ai/transport/chat-transport.tsx +39 -0
  178. package/src/components/editor/cell/CellStatus.tsx +23 -20
  179. package/src/components/editor/cell/CreateCellButton.tsx +3 -4
  180. package/src/components/editor/cell/StagedAICell.tsx +51 -0
  181. package/src/components/editor/cell/cell-actions.tsx +2 -1
  182. package/src/components/editor/cell/code/language-toggle.tsx +3 -4
  183. package/src/components/editor/chrome/wrapper/footer-items/machine-stats.tsx +39 -28
  184. package/src/components/editor/controls/notebook-menu-dropdown.tsx +4 -2
  185. package/src/components/editor/file-tree/requesting-tree.tsx +14 -8
  186. package/src/components/editor/renderers/CellArray.tsx +3 -4
  187. package/src/components/editor/renderers/slides-layout/slides-layout.tsx +3 -3
  188. package/src/components/editor/renderers/slides-layout/types.ts +1 -0
  189. package/src/components/pages/home-page.tsx +4 -1
  190. package/src/components/slides/slides-component.tsx +1 -1
  191. package/src/components/slides/slides.css +6 -0
  192. package/src/components/terminal/__tests__/state.test.ts +207 -0
  193. package/src/components/terminal/hooks.ts +41 -0
  194. package/src/components/terminal/state.ts +75 -0
  195. package/src/components/terminal/terminal.tsx +334 -13
  196. package/src/components/terminal/theme.tsx +57 -0
  197. package/src/components/tracing/tracing-spec.ts +5 -4
  198. package/src/components/ui/range-slider.tsx +4 -2
  199. package/src/components/ui/slider.tsx +3 -1
  200. package/src/components/variables/variables-table.tsx +3 -0
  201. package/src/core/MarimoApp.tsx +9 -6
  202. package/src/core/ai/__tests__/staged-cells.test.ts +356 -0
  203. package/src/core/ai/context/__tests__/registry.test.ts +6 -4
  204. package/src/core/ai/context/providers/cell-output.ts +3 -2
  205. package/src/core/ai/context/providers/error.ts +3 -1
  206. package/src/core/ai/context/providers/file.ts +7 -2
  207. package/src/core/ai/context/providers/tables.ts +3 -2
  208. package/src/core/ai/context/providers/variable.ts +6 -4
  209. package/src/core/ai/staged-cells.ts +208 -0
  210. package/src/core/cells/cells.ts +1 -1
  211. package/src/core/cells/logs.ts +1 -1
  212. package/src/core/codemirror/find-replace/search-highlight.ts +3 -1
  213. package/src/core/codemirror/language/LanguageAdapters.ts +9 -3
  214. package/src/core/codemirror/lsp/federated-lsp.ts +1 -1
  215. package/src/core/codemirror/lsp/notebook-lsp.ts +8 -2
  216. package/src/core/codemirror/readonly/__tests__/extension.test.ts +1 -1
  217. package/src/core/codemirror/rtc/loro/awareness.ts +52 -17
  218. package/src/core/codemirror/rtc/loro/sync.ts +12 -4
  219. package/src/core/config/config-schema.ts +1 -0
  220. package/src/core/config/config.ts +4 -0
  221. package/src/core/hotkeys/hotkeys.ts +8 -4
  222. package/src/core/i18n/__tests__/locale-provider.test.tsx +176 -0
  223. package/src/core/i18n/locale-provider.tsx +35 -0
  224. package/src/core/i18n/with-locale.tsx +12 -0
  225. package/src/core/islands/components/web-components.tsx +13 -10
  226. package/src/core/islands/main.ts +2 -2
  227. package/src/core/kernel/RuntimeState.ts +4 -1
  228. package/src/core/kernel/messages.ts +8 -12
  229. package/src/core/network/DeferredRequestRegistry.ts +16 -4
  230. package/src/core/runtime/runtime.ts +5 -4
  231. package/src/core/saving/__tests__/filename.test.ts +37 -0
  232. package/src/core/static/__tests__/download-html.test.ts +43 -1
  233. package/src/core/wasm/bridge.ts +5 -1
  234. package/src/core/wasm/store.ts +4 -1
  235. package/src/core/wasm/worker/message-buffer.ts +3 -2
  236. package/src/core/websocket/types.ts +22 -16
  237. package/src/core/websocket/useMarimoWebSocket.tsx +2 -2
  238. package/src/css/app/Cell.css +11 -0
  239. package/src/hooks/useFormatting.ts +97 -0
  240. package/src/hooks/useTimer.ts +8 -5
  241. package/src/plugins/core/RenderHTML.tsx +36 -2
  242. package/src/plugins/core/__test__/RenderHTML.test.ts +72 -0
  243. package/src/plugins/core/registerReactComponent.tsx +44 -10
  244. package/src/plugins/impl/DataTablePlugin.tsx +4 -0
  245. package/src/plugins/impl/FileBrowserPlugin.tsx +8 -2
  246. package/src/plugins/impl/RangeSliderPlugin.tsx +5 -3
  247. package/src/plugins/impl/SliderPlugin.tsx +3 -1
  248. package/src/plugins/impl/anywidget/model.ts +16 -5
  249. package/src/plugins/impl/data-editor/types.ts +7 -5
  250. package/src/plugins/impl/data-explorer/components/column-summary.tsx +20 -13
  251. package/src/plugins/impl/panel/utils.ts +6 -4
  252. package/src/plugins/layout/OutlinePlugin.tsx +69 -0
  253. package/src/plugins/layout/StatPlugin.tsx +4 -1
  254. package/src/plugins/plugins.ts +2 -0
  255. package/src/stories/cell.stories.tsx +1 -1
  256. package/src/stories/layout/vertical/one-column.stories.tsx +1 -1
  257. package/src/utils/__tests__/cell-urls.test.ts +29 -0
  258. package/src/utils/__tests__/dates.test.ts +45 -24
  259. package/src/utils/__tests__/filenames.test.ts +18 -0
  260. package/src/utils/__tests__/numbers.test.ts +42 -30
  261. package/src/utils/__tests__/once.test.ts +187 -0
  262. package/src/utils/__tests__/path.test.ts +38 -0
  263. package/src/utils/__tests__/urls.test.ts +56 -1
  264. package/src/utils/dates.ts +15 -10
  265. package/src/utils/edit-distance.ts +8 -6
  266. package/src/utils/errors.ts +9 -0
  267. package/src/utils/id-tree.tsx +21 -10
  268. package/src/utils/localStorage.ts +13 -4
  269. package/src/utils/numbers.ts +11 -11
  270. package/src/utils/once.ts +32 -0
  271. package/src/utils/paths.ts +4 -1
  272. package/src/utils/pluralize.ts +12 -5
  273. package/src/utils/python-poet/poet.ts +30 -15
  274. package/src/utils/time.ts +5 -1
  275. package/dist/assets/ConnectedDataExplorerComponent-Cn5-l2X1.js +0 -19
  276. package/dist/assets/_baseEach-C1FLm7WW.js +0 -1
  277. package/dist/assets/_baseMap-DBVArUYD.js +0 -1
  278. package/dist/assets/_baseUniq-Dk7ZPJ3N.js +0 -1
  279. package/dist/assets/_createAggregator-Bn38fDd3.js +0 -1
  280. package/dist/assets/agent-panel-COUYnuIK.js +0 -475
  281. package/dist/assets/architectureDiagram-W76B3OCA-DBzWQKKu.js +0 -36
  282. package/dist/assets/channel-CjhbjOv4.js +0 -1
  283. package/dist/assets/chat-panel-BPXKoTnZ.js +0 -7
  284. package/dist/assets/chat-panel-Brrs_eeH.css +0 -1
  285. package/dist/assets/classDiagram-KNZD7YFC-DHs5cFzy.js +0 -1
  286. package/dist/assets/classDiagram-v2-RKCZMP56-DHs5cFzy.js +0 -1
  287. package/dist/assets/clone-DM1YNjEn.js +0 -1
  288. package/dist/assets/command-palette-S0bzQp7v.js +0 -1
  289. package/dist/assets/common-B8U9k2Ly.js +0 -1
  290. package/dist/assets/cose-bilkent-S5V4N54A-wz1Sfx7j.js +0 -1
  291. package/dist/assets/dagre-5GWH7T2D-BfpcVBgq.js +0 -4
  292. package/dist/assets/datasources-panel-DfuURLJw.js +0 -1
  293. package/dist/assets/diagram-N5W7TBWH-Bf0oqqQh.js +0 -24
  294. package/dist/assets/diagram-QEK2KX5R-ZTc3qikh.js +0 -43
  295. package/dist/assets/diagram-S2PKOQOG-tLScBy7Z.js +0 -24
  296. package/dist/assets/edit-page-DJ8kJZ9w.js +0 -129
  297. package/dist/assets/file-explorer-panel-CzNUJ63G.js +0 -1
  298. package/dist/assets/gitGraphDiagram-NY62KEGX-C1t6QtVa.js +0 -65
  299. package/dist/assets/graph-CssCVWIq.js +0 -1
  300. package/dist/assets/home-page-9eW6qida.js +0 -9
  301. package/dist/assets/index-CknhX2Vy.css +0 -1
  302. package/dist/assets/index-DcCIe7np.js +0 -28
  303. package/dist/assets/index-OC46250R.js +0 -570
  304. package/dist/assets/infoDiagram-STP46IZ2-CwiAoz9f.js +0 -2
  305. package/dist/assets/layout-DpQrxGW-.js +0 -1
  306. package/dist/assets/linear-NsreOeBF.js +0 -1
  307. package/dist/assets/links-CbvGxbsJ.js +0 -7
  308. package/dist/assets/mermaid-DSt0r6IQ.js +0 -1
  309. package/dist/assets/min-D259kI3t.js +0 -1
  310. package/dist/assets/outline-panel-uvsS-YEQ.js +0 -1
  311. package/dist/assets/packages-panel-xMz9W2hW.js +0 -1
  312. package/dist/assets/run-page-Bb68qdhQ.js +0 -1
  313. package/dist/assets/sankeyDiagram-GR3RE2ED-BSJOau8E.js +0 -10
  314. package/dist/assets/scratchpad-panel-BF4BO-U4.js +0 -1
  315. package/dist/assets/secrets-panel-CdIX44dQ.js +0 -1
  316. package/dist/assets/snippets-panel-Dco9h0rb.js +0 -1
  317. package/dist/assets/sortBy-aLGA-PGK.js +0 -1
  318. package/dist/assets/stateDiagram-KXAO66HF-Bd68WT3b.js +0 -1
  319. package/dist/assets/stateDiagram-v2-UMBNRL4Z-BXz_GSwb.js +0 -1
  320. package/dist/assets/storage-CGlP4lCF.js +0 -26
  321. package/dist/assets/terminal-CxkHubcu.js +0 -9
  322. package/dist/assets/time-D2nr1UgQ.js +0 -1
  323. package/dist/assets/tracing-kTqHxa7q.js +0 -2
  324. package/dist/assets/variable-panel-noTnH-AQ.js +0 -1
  325. 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 { PromptInput } from "@/components/editor/ai/add-cell-with-ai";
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
- ReadTextFileResponse,
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
- <div className="flex flex-col h-full">
176
- <AgentPanelHeader
177
- connectionState={connectionState}
178
- currentAgentId={currentAgentId}
179
- onConnect={onConnect}
180
- onDisconnect={onDisconnect}
181
- hasActiveSession={false}
182
- />
183
- <SessionTabs />
184
- <div className="flex-1 flex items-center justify-center p-6">
185
- <div className="max-w-md w-full space-y-6">
186
- <PanelEmptyState
187
- title="No Agent Sessions"
188
- description="Create a new session to start a conversation"
189
- action={<AgentSelector className="border-y-1 rounded" />}
190
- icon={<BotMessageSquareIcon />}
191
- />
192
- {connectionState.status === "disconnected" && (
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
- </div>
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
- <div
264
- className={cn(
265
- "px-3 py-2 border-t bg-background flex-shrink-0 min-h-[80px]",
266
- (isLoading || !activeSessionId) && "opacity-50 pointer-events-none",
267
- )}
268
- >
269
- <PromptInput
270
- value={promptValue}
271
- onChange={isLoading ? Functions.NOOP : onPromptValueChange}
272
- onSubmit={onPromptSubmit}
273
- onClose={Functions.NOOP}
274
- placeholder={isLoading ? "Processing..." : "Ask your AI agent..."}
275
- className={isLoading ? "opacity-50 pointer-events-none" : ""}
276
- maxHeight="120px"
277
- />
278
- </div>
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: unknown) => void;
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): Promise<ReadTextFileResponse> => {
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): Promise<WriteTextFileResponse> => {
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(() => null);
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 as RequestPermissionResponse);
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)}