@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
@@ -0,0 +1,356 @@
1
+ /* Copyright 2024 Marimo. All rights reserved. */
2
+
3
+ import { renderHook } from "@testing-library/react";
4
+ import { getDefaultStore } from "jotai";
5
+ import { beforeEach, describe, expect, it, vi } from "vitest";
6
+ import { CellId } from "@/core/cells/ids";
7
+ import { updateEditorCodeFromPython } from "../../codemirror/language/utils";
8
+ import {
9
+ stagedAICellsAtom,
10
+ useStagedCells,
11
+ visibleForTesting,
12
+ } from "../staged-cells";
13
+
14
+ const { createActions, reducer, initialState } = visibleForTesting;
15
+
16
+ // Mock the dependencies
17
+ const mockCreateNewCell = vi.fn();
18
+ const mockUpdateCellEditor = vi.fn();
19
+ const mockDeleteCellCallback = vi.fn();
20
+
21
+ // Mock cell handle with editor view
22
+ const mockCellHandle = {
23
+ current: {
24
+ editorViewOrNull: {
25
+ dispatch: vi.fn(),
26
+ },
27
+ },
28
+ };
29
+
30
+ vi.mock("../../cells/cells", () => ({
31
+ useCellActions: () => ({
32
+ createNewCell: mockCreateNewCell,
33
+ updateCellEditor: mockUpdateCellEditor,
34
+ }),
35
+ cellHandleAtom: vi.fn(() => ({
36
+ read: vi.fn(() => mockCellHandle),
37
+ })),
38
+ }));
39
+
40
+ vi.mock("@/components/editor/cell/useDeleteCell", () => ({
41
+ useDeleteCellCallback: () => mockDeleteCellCallback,
42
+ }));
43
+
44
+ vi.mock("../../codemirror/language/utils", () => ({
45
+ updateEditorCodeFromPython: vi.fn(),
46
+ }));
47
+
48
+ // Mock CellId.create
49
+ vi.mock("@/core/cells/ids", () => ({
50
+ CellId: {
51
+ create: vi.fn(),
52
+ },
53
+ }));
54
+
55
+ describe("staged-cells", () => {
56
+ let store: ReturnType<typeof getDefaultStore>;
57
+ let cellId1: CellId;
58
+ let cellId2: CellId;
59
+
60
+ beforeEach(() => {
61
+ store = getDefaultStore();
62
+ cellId1 = "cell-1" as CellId;
63
+ cellId2 = "cell-2" as CellId;
64
+
65
+ // Reset mocks
66
+ vi.clearAllMocks();
67
+
68
+ // Reset the atom state
69
+ store.set(stagedAICellsAtom, new Set<CellId>());
70
+ });
71
+
72
+ describe("reducer and actions", () => {
73
+ it("should initialize with empty map", () => {
74
+ const state = initialState();
75
+ expect(state).toEqual(new Set());
76
+ });
77
+
78
+ it("should add cell IDs", () => {
79
+ let state = initialState();
80
+ state = reducer(state, {
81
+ type: "addStagedCell",
82
+ payload: { cellId: cellId1 },
83
+ });
84
+ state = reducer(state, {
85
+ type: "addStagedCell",
86
+ payload: { cellId: cellId2 },
87
+ });
88
+
89
+ expect(state.has(cellId1)).toBe(true);
90
+ expect(state.has(cellId2)).toBe(true);
91
+ });
92
+
93
+ it("should remove cell IDs", () => {
94
+ const state = new Set([cellId1, cellId2]);
95
+ const newState = reducer(state, {
96
+ type: "removeStagedCell",
97
+ payload: cellId1,
98
+ });
99
+
100
+ expect(newState.has(cellId1)).toBe(false);
101
+ expect(newState.has(cellId2)).toBe(true);
102
+ });
103
+
104
+ it("should clear all cell IDs", () => {
105
+ const state = new Set([cellId1, cellId2]);
106
+ const newState = reducer(state, {
107
+ type: "clearStagedCells",
108
+ payload: undefined,
109
+ });
110
+
111
+ expect(newState).toEqual(new Set());
112
+ });
113
+
114
+ it("should not mutate original state", () => {
115
+ const state = new Set([cellId1]);
116
+ const originalSize = state.size;
117
+
118
+ reducer(state, {
119
+ type: "addStagedCell",
120
+ payload: { cellId: cellId2 },
121
+ });
122
+
123
+ expect(state.size).toBe(originalSize);
124
+ expect(state.has(cellId1)).toBe(true);
125
+ expect(state.has(cellId2)).toBe(false);
126
+ });
127
+
128
+ it("should create action functions", () => {
129
+ const mockDispatch = vi.fn();
130
+ const actions = createActions(mockDispatch);
131
+
132
+ expect(typeof actions.addStagedCell).toBe("function");
133
+ expect(typeof actions.removeStagedCell).toBe("function");
134
+ expect(typeof actions.clearStagedCells).toBe("function");
135
+ });
136
+
137
+ it("should initialize atom with empty map", () => {
138
+ const state = store.get(stagedAICellsAtom);
139
+ expect(state).toEqual(new Set());
140
+ });
141
+ });
142
+
143
+ describe("useStagedCells hook", () => {
144
+ it("should create a staged cell with code", () => {
145
+ const { result } = renderHook(() => useStagedCells(store));
146
+ const testCode = "print('hello world')";
147
+
148
+ // Mock CellId.create to return a predictable ID
149
+ const mockCellId = "mock-cell-id" as CellId;
150
+ vi.mocked(CellId.create).mockReturnValue(mockCellId);
151
+
152
+ const returnedCellId = result.current.createStagedCell(testCode);
153
+
154
+ expect(returnedCellId).toBe(mockCellId);
155
+ expect(mockCreateNewCell).toHaveBeenCalledWith({
156
+ cellId: "__end__",
157
+ code: testCode,
158
+ before: false,
159
+ newCellId: mockCellId,
160
+ });
161
+ });
162
+
163
+ it("should delete a staged cell", () => {
164
+ const { result } = renderHook(() => useStagedCells(store));
165
+ const testCellId = "test-cell-id" as CellId;
166
+
167
+ result.current.deleteStagedCell(testCellId);
168
+
169
+ expect(mockDeleteCellCallback).toHaveBeenCalledWith({
170
+ cellId: testCellId,
171
+ });
172
+ });
173
+
174
+ it("should delete all staged cells when none exist", () => {
175
+ const { result } = renderHook(() => useStagedCells(store));
176
+
177
+ // Should not throw when no cells exist
178
+ expect(() => result.current.deleteAllStagedCells()).not.toThrow();
179
+ expect(mockDeleteCellCallback).not.toHaveBeenCalled();
180
+ });
181
+
182
+ it("should delete all staged cells when cells exist", () => {
183
+ // First set the atom state before rendering the hook
184
+ store.set(stagedAICellsAtom, new Set([cellId1, cellId2]));
185
+
186
+ const { result } = renderHook(() => useStagedCells(store));
187
+ result.current.deleteAllStagedCells();
188
+
189
+ expect(mockDeleteCellCallback).toHaveBeenCalledTimes(2);
190
+ expect(mockDeleteCellCallback).toHaveBeenCalledWith({ cellId: cellId1 });
191
+ expect(mockDeleteCellCallback).toHaveBeenCalledWith({ cellId: cellId2 });
192
+
193
+ // Verify cells were cleared from the atom
194
+ const state = store.get(stagedAICellsAtom);
195
+ expect(state).toEqual(new Set());
196
+ });
197
+ });
198
+
199
+ it("should add staged cell", () => {
200
+ const { result } = renderHook(() => useStagedCells(store));
201
+
202
+ result.current.addStagedCell({ cellId: cellId1 });
203
+
204
+ // Check that the cell was added to the atom
205
+ const state = store.get(stagedAICellsAtom);
206
+ expect(state.has(cellId1)).toBe(true);
207
+ });
208
+
209
+ it("should remove staged cell", () => {
210
+ const { result } = renderHook(() => useStagedCells(store));
211
+
212
+ // First add cells
213
+ result.current.addStagedCell({ cellId: cellId1 });
214
+ result.current.addStagedCell({ cellId: cellId2 });
215
+
216
+ // Then remove one
217
+ result.current.removeStagedCell(cellId1);
218
+
219
+ // Check that only the remaining cell is in the map
220
+ const state = store.get(stagedAICellsAtom);
221
+ expect(state.has(cellId1)).toBe(false);
222
+ expect(state.has(cellId2)).toBe(true);
223
+ });
224
+
225
+ it("should clear all staged cells", () => {
226
+ const { result } = renderHook(() => useStagedCells(store));
227
+
228
+ // First add some cells
229
+ result.current.addStagedCell({ cellId: cellId1 });
230
+ result.current.addStagedCell({ cellId: cellId2 });
231
+
232
+ // Then clear all
233
+ result.current.clearStagedCells();
234
+
235
+ // Check that no cells remain
236
+ const state = store.get(stagedAICellsAtom);
237
+ expect(state).toEqual(new Set());
238
+ });
239
+
240
+ it("should handle multiple operations correctly", () => {
241
+ const { result } = renderHook(() => useStagedCells(store));
242
+
243
+ // Create a staged cell
244
+ const mockCellId = "mock-cell-id" as CellId;
245
+ vi.mocked(CellId.create).mockReturnValue(mockCellId);
246
+
247
+ const createdCellId = result.current.createStagedCell("test code");
248
+
249
+ // Verify it was created and added
250
+ expect(createdCellId).toBe(mockCellId);
251
+ expect(mockCreateNewCell).toHaveBeenCalled();
252
+
253
+ let state = store.get(stagedAICellsAtom);
254
+ expect(state.has(mockCellId)).toBe(true);
255
+
256
+ // Delete the staged cell
257
+ result.current.deleteStagedCell(mockCellId);
258
+ expect(mockDeleteCellCallback).toHaveBeenCalledWith({
259
+ cellId: mockCellId,
260
+ });
261
+
262
+ // Verify it was removed from staged cells
263
+ state = store.get(stagedAICellsAtom);
264
+ expect(state.has(mockCellId)).toBe(false);
265
+ });
266
+ });
267
+
268
+ describe("onStream", () => {
269
+ let store: ReturnType<typeof getDefaultStore>;
270
+ beforeEach(() => {
271
+ store = getDefaultStore();
272
+ });
273
+
274
+ it("should create a cell creation stream", () => {
275
+ const { result } = renderHook(() => useStagedCells(store));
276
+ result.current.onStream({ type: "text-start", id: "test-id" });
277
+
278
+ // No cell or cell update should have been called
279
+ expect(mockCreateNewCell).not.toHaveBeenCalled();
280
+ expect(mockUpdateCellEditor).not.toHaveBeenCalled();
281
+ });
282
+
283
+ it("should not create cells when text-delta is received and no stream has been created", () => {
284
+ const { result } = renderHook(() => useStagedCells(store));
285
+ result.current.onStream({
286
+ type: "text-delta",
287
+ id: "test-id",
288
+ delta: "test-delta",
289
+ });
290
+
291
+ // No cell or cell update should have been called
292
+ expect(mockCreateNewCell).not.toHaveBeenCalled();
293
+ expect(mockUpdateCellEditor).not.toHaveBeenCalled();
294
+ });
295
+
296
+ it("should create cells when text-delta is received and a stream has been created", () => {
297
+ const { result } = renderHook(() => useStagedCells(store));
298
+ result.current.onStream({ type: "text-start", id: "test-id" });
299
+
300
+ // Mock CellId.create to return a predictable ID
301
+ const mockCellId = "mock-cell-id" as CellId;
302
+ vi.mocked(CellId.create).mockReturnValue(mockCellId);
303
+
304
+ result.current.onStream({
305
+ type: "text-delta",
306
+ id: "test-id",
307
+ delta: "some code",
308
+ });
309
+
310
+ expect(mockCreateNewCell).toHaveBeenCalledWith({
311
+ cellId: "__end__",
312
+ code: "some code",
313
+ before: false,
314
+ newCellId: "mock-cell-id",
315
+ });
316
+ });
317
+
318
+ it("should handle delta chunks", () => {
319
+ const { result } = renderHook(() => useStagedCells(store));
320
+ result.current.onStream({ type: "text-start", id: "test-id" });
321
+
322
+ const mockCellId = "mock-cell-id" as CellId;
323
+ vi.mocked(CellId.create).mockReturnValue(mockCellId);
324
+
325
+ result.current.onStream({
326
+ type: "text-delta",
327
+ id: "test-id",
328
+ delta: "``",
329
+ });
330
+
331
+ expect(mockCreateNewCell).toHaveBeenCalledWith({
332
+ cellId: "__end__",
333
+ code: "``",
334
+ before: false,
335
+ newCellId: "mock-cell-id",
336
+ });
337
+
338
+ result.current.onStream({
339
+ type: "text-delta",
340
+ id: "test-id",
341
+ delta: "```python\nsome code",
342
+ });
343
+
344
+ // Now the cell is recognized and only some code is seen
345
+ expect(vi.mocked(updateEditorCodeFromPython)).toHaveBeenCalledWith(
346
+ mockCellHandle.current.editorViewOrNull,
347
+ "some code",
348
+ );
349
+
350
+ result.current.onStream({
351
+ type: "text-delta",
352
+ id: "test-id",
353
+ delta: "\n```",
354
+ });
355
+ });
356
+ });
@@ -101,11 +101,13 @@ class AttachmentContextProvider extends AIContextProvider<MockContextItem> {
101
101
  readonly mentionPrefix = "@";
102
102
  readonly contextType = "attachment";
103
103
 
104
- constructor(
105
- private items: MockContextItem[] = [],
106
- private attachments: FileUIPart[] = [],
107
- ) {
104
+ private items: MockContextItem[];
105
+ private attachments: FileUIPart[];
106
+
107
+ constructor(items: MockContextItem[] = [], attachments: FileUIPart[] = []) {
108
108
  super();
109
+ this.items = items;
110
+ this.attachments = attachments;
109
111
  }
110
112
 
111
113
  getItems(): MockContextItem[] {
@@ -86,9 +86,10 @@ export class CellOutputContextProvider extends AIContextProvider<CellOutputConte
86
86
  readonly title = "Cell Outputs";
87
87
  readonly mentionPrefix = "@";
88
88
  readonly contextType = "cell-output";
89
-
90
- constructor(private store: JotaiStore) {
89
+ private store: JotaiStore;
90
+ constructor(store: JotaiStore) {
91
91
  super();
92
+ this.store = store;
92
93
  }
93
94
 
94
95
  getItems(): CellOutputContextItem[] {
@@ -64,9 +64,11 @@ export class ErrorContextProvider extends AIContextProvider<ErrorContextItem> {
64
64
  readonly title = "Errors";
65
65
  readonly mentionPrefix = "@";
66
66
  readonly contextType = "error";
67
+ private store: JotaiStore;
67
68
 
68
- constructor(private store: JotaiStore) {
69
+ constructor(store: JotaiStore) {
69
70
  super();
71
+ this.store = store;
70
72
  }
71
73
 
72
74
  getItems(): ErrorContextItem[] {
@@ -43,11 +43,16 @@ export class FileContextProvider extends AIContextProvider<FileContextItem> {
43
43
  readonly mentionPrefix = "#";
44
44
  readonly contextType = "file";
45
45
 
46
+ private apiRequests: EditRequests & RunRequests;
47
+ private config: FileSearchConfig;
48
+
46
49
  constructor(
47
- private apiRequests: EditRequests & RunRequests,
48
- private config: FileSearchConfig = DEFAULT_FILE_SEARCH_CONFIG,
50
+ apiRequests: EditRequests & RunRequests,
51
+ config: FileSearchConfig = DEFAULT_FILE_SEARCH_CONFIG,
49
52
  ) {
50
53
  super();
54
+ this.apiRequests = apiRequests;
55
+ this.config = config;
51
56
  }
52
57
 
53
58
  /**
@@ -17,9 +17,10 @@ export class TableContextProvider extends AIContextProvider<TableContextItem> {
17
17
  readonly title = "Tables";
18
18
  readonly mentionPrefix = "@";
19
19
  readonly contextType = "data";
20
-
21
- constructor(private tablesMap: DatasetTablesMap) {
20
+ private tablesMap: DatasetTablesMap;
21
+ constructor(tablesMap: DatasetTablesMap) {
22
22
  super();
23
+ this.tablesMap = tablesMap;
23
24
  }
24
25
 
25
26
  getItems(): TableContextItem[] {
@@ -20,11 +20,13 @@ export class VariableContextProvider extends AIContextProvider<VariableContextIt
20
20
  readonly mentionPrefix = "@";
21
21
  readonly contextType = "variable";
22
22
 
23
- constructor(
24
- private variables: Variables,
25
- private tablesMap: DatasetTablesMap,
26
- ) {
23
+ private variables: Variables;
24
+ private tablesMap: DatasetTablesMap;
25
+
26
+ constructor(variables: Variables, tablesMap: DatasetTablesMap) {
27
27
  super();
28
+ this.variables = variables;
29
+ this.tablesMap = tablesMap;
28
30
  }
29
31
 
30
32
  getItems(): VariableContextItem[] {
@@ -0,0 +1,208 @@
1
+ /* Copyright 2024 Marimo. All rights reserved. */
2
+
3
+ import type { UIMessageChunk } from "ai";
4
+ import { useRef } from "react";
5
+ import {
6
+ type AiCompletion,
7
+ codeToCells,
8
+ } from "@/components/editor/ai/completion-utils";
9
+ import { useDeleteCellCallback } from "@/components/editor/cell/useDeleteCell";
10
+ import { CellId } from "@/core/cells/ids";
11
+ import { createReducerAndAtoms } from "@/utils/createReducer";
12
+ import { Logger } from "@/utils/Logger";
13
+ import { cellHandleAtom, useCellActions } from "../cells/cells";
14
+ import type { LanguageAdapterType } from "../codemirror/language/types";
15
+ import { updateEditorCodeFromPython } from "../codemirror/language/utils";
16
+ import type { JotaiStore } from "../state/jotai";
17
+
18
+ /**
19
+ * Cells that are staged for AI completion
20
+ * They function similarly to cells in the notebook, but they can be deleted or accepted by the user.
21
+ * We only track one set of staged cells at a time.
22
+ */
23
+
24
+ const initialState = (): Set<CellId> => {
25
+ return new Set();
26
+ };
27
+
28
+ const {
29
+ valueAtom: stagedAICellsAtom,
30
+ useActions: useStagedAICellsActions,
31
+ createActions,
32
+ reducer,
33
+ } = createReducerAndAtoms(initialState, {
34
+ addStagedCell: (state, action: { cellId: CellId }) => {
35
+ const { cellId } = action;
36
+ return new Set([...state, cellId]);
37
+ },
38
+ removeStagedCell: (state, cellId: CellId) => {
39
+ return new Set([...state].filter((id) => id !== cellId));
40
+ },
41
+ clearStagedCells: () => {
42
+ return initialState();
43
+ },
44
+ });
45
+
46
+ interface UpdateStagedCellAction {
47
+ cellId: CellId;
48
+ code: string;
49
+ language?: LanguageAdapterType;
50
+ }
51
+
52
+ /**
53
+ * Helper functions to create and delete staged cells.
54
+ */
55
+ export function useStagedCells(store: JotaiStore) {
56
+ const { addStagedCell, removeStagedCell, clearStagedCells } =
57
+ useStagedAICellsActions();
58
+ const { createNewCell } = useCellActions();
59
+ const deleteCellCallback = useDeleteCellCallback();
60
+
61
+ const cellCreationStream = useRef<CellCreationStream | null>(null);
62
+
63
+ const createStagedCell = (code: string): CellId => {
64
+ const newCellId = CellId.create();
65
+ addStagedCell({ cellId: newCellId });
66
+ createNewCell({
67
+ cellId: "__end__",
68
+ code,
69
+ before: false,
70
+ newCellId: newCellId,
71
+ });
72
+ return newCellId;
73
+ };
74
+
75
+ const updateStagedCell = (opts: UpdateStagedCellAction) => {
76
+ const { cellId, code } = opts;
77
+ const stagedAICells = store.get(stagedAICellsAtom);
78
+
79
+ if (!stagedAICells.has(cellId)) {
80
+ Logger.error("Staged cell not found", { cellId });
81
+ return;
82
+ }
83
+
84
+ const cellHandle = store.get(cellHandleAtom(cellId));
85
+ const editorView = cellHandle?.current?.editorViewOrNull;
86
+ if (!editorView) {
87
+ Logger.error("Editor for this cell not found", { cellId });
88
+ return;
89
+ }
90
+ // TODO: Update the language
91
+ updateEditorCodeFromPython(editorView, code);
92
+ };
93
+
94
+ // Delete a staged cell and the corresponding cell in the notebook.
95
+ const deleteStagedCell = (cellId: CellId) => {
96
+ removeStagedCell(cellId);
97
+ deleteCellCallback({ cellId });
98
+ };
99
+
100
+ // Delete all staged cells and the corresponding cells in the notebook.
101
+ const deleteAllStagedCells = () => {
102
+ const stagedAICells = store.get(stagedAICellsAtom);
103
+ for (const cellId of stagedAICells) {
104
+ deleteCellCallback({ cellId });
105
+ }
106
+ clearStagedCells();
107
+ };
108
+
109
+ const onStream = (chunk: UIMessageChunk) => {
110
+ switch (chunk.type) {
111
+ case "text-start":
112
+ // Create stream
113
+ cellCreationStream.current = new CellCreationStream(
114
+ createStagedCell,
115
+ updateStagedCell,
116
+ );
117
+ break;
118
+ case "text-delta":
119
+ if (!cellCreationStream.current) {
120
+ Logger.error("Cell creation stream not found");
121
+ return;
122
+ }
123
+ cellCreationStream.current.stream(chunk);
124
+ break;
125
+ case "text-end":
126
+ case "finish":
127
+ if (!cellCreationStream.current) {
128
+ Logger.error("Cell creation stream not found");
129
+ return;
130
+ }
131
+ cellCreationStream.current.stop();
132
+ break;
133
+ default:
134
+ Logger.error("Unknown chunk type", { chunk });
135
+ }
136
+ };
137
+
138
+ return {
139
+ createStagedCell,
140
+ updateStagedCell,
141
+ addStagedCell,
142
+ removeStagedCell,
143
+ clearStagedCells,
144
+ deleteStagedCell,
145
+ deleteAllStagedCells,
146
+ onStream,
147
+ };
148
+ }
149
+
150
+ export { stagedAICellsAtom };
151
+ export const visibleForTesting = {
152
+ createActions,
153
+ reducer,
154
+ initialState,
155
+ useStagedAICellsActions,
156
+ };
157
+
158
+ type TextDeltaChunk = Extract<UIMessageChunk, { type: "text-delta" }>;
159
+
160
+ interface CreatedCell {
161
+ cellId: CellId;
162
+ cell: AiCompletion;
163
+ }
164
+
165
+ class CellCreationStream {
166
+ private createdCells: CreatedCell[] = [];
167
+ private buffer = "";
168
+
169
+ private onCreateCell: (code: string) => CellId;
170
+ private onUpdateCell: (opts: UpdateStagedCellAction) => void;
171
+
172
+ constructor(
173
+ onCreateCell: (code: string) => CellId,
174
+ onUpdateCell: (opts: UpdateStagedCellAction) => void,
175
+ ) {
176
+ this.onCreateCell = onCreateCell;
177
+ this.onUpdateCell = onUpdateCell;
178
+ }
179
+
180
+ stream(chunk: TextDeltaChunk) {
181
+ const delta = chunk.delta;
182
+ this.buffer += delta;
183
+ const completionCells = codeToCells(this.buffer);
184
+
185
+ // As incoming chunks are appended to the buffer,
186
+ // we parse the buffer into cells and determine which parts correspond to which cell.
187
+ // For each parsed cell, we either update an existing staged cell or create a new one.
188
+ for (const [idx, cell] of completionCells.entries()) {
189
+ if (idx < this.createdCells.length) {
190
+ const existingCell = this.createdCells[idx];
191
+ this.createdCells[idx] = { ...existingCell, cell };
192
+ this.onUpdateCell({
193
+ cellId: existingCell.cellId,
194
+ code: cell.code,
195
+ language: cell.language,
196
+ });
197
+ } else {
198
+ const newCellId = this.onCreateCell(cell.code);
199
+ this.createdCells.push({ cellId: newCellId, cell });
200
+ }
201
+ }
202
+ }
203
+
204
+ stop() {
205
+ // Clear all state
206
+ this.buffer = "";
207
+ }
208
+ }
@@ -1623,7 +1623,7 @@ const cellDataAtom = atomFamily((cellId: CellId) =>
1623
1623
  const cellRuntimeAtom = atomFamily((cellId: CellId) =>
1624
1624
  atom((get) => get(notebookAtom).cellRuntime[cellId]),
1625
1625
  );
1626
- const cellHandleAtom = atomFamily((cellId: CellId) =>
1626
+ export const cellHandleAtom = atomFamily((cellId: CellId) =>
1627
1627
  atom((get) => get(notebookAtom).cellHandles[cellId]),
1628
1628
  );
1629
1629
  /**
@@ -102,7 +102,7 @@ export function formatLogTimestamp(timestamp: number): string {
102
102
  try {
103
103
  // parse from UTC
104
104
  const date = fromUnixTime(timestamp);
105
- return date.toLocaleTimeString("en-US", {
105
+ return date.toLocaleTimeString(undefined, {
106
106
  hour12: true,
107
107
  hour: "numeric",
108
108
  minute: "numeric",
@@ -91,8 +91,10 @@ const HighlightMargin = 250;
91
91
  export const searchHighlighter = ViewPlugin.fromClass(
92
92
  class {
93
93
  decorations: DecorationSet;
94
+ readonly view: EditorView;
94
95
 
95
- constructor(readonly view: EditorView) {
96
+ constructor(view: EditorView) {
97
+ this.view = view;
96
98
  this.decorations = this.highlight(view.state.field(searchState));
97
99
  }
98
100