@marimo-team/frontend 0.25.3-dev40 → 0.25.3-dev44

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 (100) hide show
  1. package/dist/assets/{CellStatus-BGIWF94J.js → CellStatus-BpOBz-8m.js} +1 -1
  2. package/dist/assets/{ErrorBoundary-hliG40Pk.js → ErrorBoundary-DmXl4Nre.js} +2 -2
  3. package/dist/assets/{JsonOutput-9tmC-p6h.js → JsonOutput-DsMCKg5f.js} +2 -2
  4. package/dist/assets/{MarimoErrorOutput-BaHdbtck.js → MarimoErrorOutput-DVjK8RgY.js} +1 -1
  5. package/dist/assets/{RenderHTML-B1FzB5NY.js → RenderHTML-BFaztTR0.js} +1 -1
  6. package/dist/assets/{RunButton-DpGokdF1.js → RunButton-B44xE_d5.js} +1 -1
  7. package/dist/assets/{add-cell-with-ai-BYWG0iKO.js → add-cell-with-ai-CkjslziO.js} +1 -1
  8. package/dist/assets/{add-connection-dialog-BWbUVPJk.js → add-connection-dialog-CWLLVKju.js} +1 -1
  9. package/dist/assets/{agent-panel-DKNiQrAl.js → agent-panel-DVUZ4l17.js} +1 -1
  10. package/dist/assets/{ai-model-dropdown-CIg9eu47.js → ai-model-dropdown-F3mm17Wa.js} +1 -1
  11. package/dist/assets/{app-config-button-BvkL2eSY.js → app-config-button-D0uDs5nC.js} +1 -1
  12. package/dist/assets/{blob-BQfLiwKr.js → blob-BSfsdCNF.js} +1 -1
  13. package/dist/assets/{cell-editor-BKKUv4d5.js → cell-editor-BXMAe73i.js} +1 -1
  14. package/dist/assets/{cell-link-B_QkRkm-.js → cell-link-DFPHORAO.js} +1 -1
  15. package/dist/assets/{cells-CdH98VSn.js → cells-BdgzY0of.js} +1 -1
  16. package/dist/assets/{chat-display-CNbRSebo.js → chat-display-BrcwdhKJ.js} +1 -1
  17. package/dist/assets/{chat-panel-HbEKDf0c.js → chat-panel-C__3iSyI.js} +1 -1
  18. package/dist/assets/{chat-ui-BwMev8Bf.js → chat-ui-NlBK3kK6.js} +1 -1
  19. package/dist/assets/{code-visibility-sQ37CBNo.js → code-visibility-Cs-Vv3jV.js} +1 -1
  20. package/dist/assets/{column-preview-CsEBzIUE.js → column-preview-D-MQXrz3.js} +1 -1
  21. package/dist/assets/{command-palette-BzZ86pUz.js → command-palette-BbCoQAH7.js} +1 -1
  22. package/dist/assets/{common-S2v8dsEy.js → common-BcEY1yDS.js} +1 -1
  23. package/dist/assets/{components-D-TnFWjo.js → components-lkCfd2vy.js} +1 -1
  24. package/dist/assets/{config-CYsbZpwa.js → config-BwHT0yGp.js} +2 -2
  25. package/dist/assets/{config-BoBwH7CU.js → config-DXjnAwtL.js} +1 -1
  26. package/dist/assets/{datasource-BA7YF4eo.js → datasource-dKk3JHSQ.js} +1 -1
  27. package/dist/assets/{dependency-graph-panel-DsjI61Qa.js → dependency-graph-panel-BaisS9Zt.js} +1 -1
  28. package/dist/assets/{documentation-panel-hk3IdeXy.js → documentation-panel-CpSUoM8r.js} +1 -1
  29. package/dist/assets/{download-CCZkq0y4.js → download-RV4i1fWI.js} +1 -1
  30. package/dist/assets/{edit-page-BgS6tjth.js → edit-page-OQUBqPxV.js} +4 -4
  31. package/dist/assets/{error-entries-BVXrGOTZ.js → error-entries-CJS0gOId.js} +1 -1
  32. package/dist/assets/{error-panel-DYethUUR.js → error-panel-BxCKpZtN.js} +1 -1
  33. package/dist/assets/feedback-button-BLvwvndE.js +1 -0
  34. package/dist/assets/{feedback-button-DaNc3uJa.js → feedback-button-DYjae3_b.js} +1 -1
  35. package/dist/assets/{file-explorer-panel-CqnzSSYc.js → file-explorer-panel-Cg48iuPg.js} +1 -1
  36. package/dist/assets/{file-name-input-D4AvwZV9.js → file-name-input-BpfSzvEB.js} +1 -1
  37. package/dist/assets/{floating-outline-CTy-Iakk.js → floating-outline-CrWdiNQ2.js} +1 -1
  38. package/dist/assets/{gallery-page-ByjlvM6k.js → gallery-page-W_b-XWq6.js} +1 -1
  39. package/dist/assets/{glide-data-editor-CABBj2b0.js → glide-data-editor-C_bIL30J.js} +1 -1
  40. package/dist/assets/{home-page-DejRSjeJ.js → home-page-D1teQDdF.js} +1 -1
  41. package/dist/assets/{hooks-BJgCcVXZ.js → hooks-B2jmXrjG.js} +1 -1
  42. package/dist/assets/{index-PDJQd7X6.js → index-CnvKSoR0.js} +5 -5
  43. package/dist/assets/index-evFWHKmM.css +2 -0
  44. package/dist/assets/{layout-Ct0rjb-5.js → layout-Ckm5arvO.js} +3 -3
  45. package/dist/assets/{logs-panel-TyeqEvOY.js → logs-panel-DVSgfMgv.js} +1 -1
  46. package/dist/assets/{markdown-renderer-BFyD6Jhs.js → markdown-renderer-DX2O5YiE.js} +1 -1
  47. package/dist/assets/{name-cell-input-D-0VF3qd.js → name-cell-input-DL1i8Mj0.js} +1 -1
  48. package/dist/assets/{outline-panel-DMTjk2WC.js → outline-panel-DPKPT2eg.js} +1 -1
  49. package/dist/assets/{packages-panel-DrT69k9L.js → packages-panel-CZZwD9YV.js} +1 -1
  50. package/dist/assets/{panel-accordion-state-Ban6j---.js → panel-accordion-state-C7vvsYz1.js} +1 -1
  51. package/dist/assets/panels-B2HvGLkD.js +4 -0
  52. package/dist/assets/{process-output-DzpQYlpY.js → process-output-BKhybJBb.js} +1 -1
  53. package/dist/assets/{readonly-code-display-Cyn3k5TX.js → readonly-code-display-9QrSm_7D.js} +1 -1
  54. package/dist/assets/{readonly-python-code-DrXDDAnA.js → readonly-python-code-BLotL3XP.js} +1 -1
  55. package/dist/assets/{reveal-component-_lKImPWP.js → reveal-component-CxQ9fVAB.js} +1 -1
  56. package/dist/assets/{run-page-7UNg--Rj.js → run-page-DtWhVRu3.js} +1 -1
  57. package/dist/assets/{runtime-details-state-CKOKhMhv.js → runtime-details-state-B25uM-Ps.js} +1 -1
  58. package/dist/assets/{scratchpad-panel-C7h4MgqN.js → scratchpad-panel-DsqDHGr7.js} +1 -1
  59. package/dist/assets/{session-panel-CLiWXc5y.js → session-panel-CjJ0nwoT.js} +1 -1
  60. package/dist/assets/{snippets-panel-Wrqaorxa.js → snippets-panel-IxIxfxNc.js} +1 -1
  61. package/dist/assets/{state-TVREh4u4.js → state-BHuYDaxs.js} +1 -1
  62. package/dist/assets/{state-_uXVmwuN.js → state-CVgqwwCU.js} +1 -1
  63. package/dist/assets/{terminal-Dp5gyJ7l.js → terminal-CjvCrRrA.js} +1 -1
  64. package/dist/assets/{tracing-fUNLyKuj.js → tracing-V5zejPsw.js} +1 -1
  65. package/dist/assets/{tracing-panel-Cx4OqOoP.js → tracing-panel-DLS3iwK6.js} +2 -2
  66. package/dist/assets/{tree-actions-B1vsdenY.js → tree-actions-Be_mzC1C.js} +1 -1
  67. package/dist/assets/{useAddCell-DZ-50qEG.js → useAddCell-DK79W1vA.js} +1 -1
  68. package/dist/assets/{useBoolean-5g-bBaYF.js → useBoolean-j0qHaJxu.js} +1 -1
  69. package/dist/assets/{useCellActionButton-DINnRstv.js → useCellActionButton-Cw9Ob12j.js} +1 -1
  70. package/dist/assets/{useDeleteCell-CREJXVNp.js → useDeleteCell-BNqX6PPu.js} +1 -1
  71. package/dist/assets/{useDependencyPanelTab-Cw5VT16Q.js → useDependencyPanelTab-GnTnqKJo.js} +1 -1
  72. package/dist/assets/{useInstallPackage-Cw0dVELh.js → useInstallPackage-CVItDn1e.js} +1 -1
  73. package/dist/assets/{useNotebookActions-B4av4mLc.js → useNotebookActions-BTkKQpGk.js} +1 -1
  74. package/dist/assets/{useRunCells-BHBMk9zW.js → useRunCells-DP09DHT6.js} +1 -1
  75. package/dist/assets/{useSplitCell-DAgwZV0q.js → useSplitCell-IfumZ4sm.js} +1 -1
  76. package/dist/assets/{vega-component-pQE2mKc1.js → vega-component-CMn031HF.js} +1 -1
  77. package/dist/index.html +25 -25
  78. package/package.json +2 -4
  79. package/src/__tests__/host-imports.test.ts +1 -0
  80. package/src/components/data-table/__tests__/export-actions.test.tsx +88 -0
  81. package/src/components/data-table/export-actions.tsx +71 -45
  82. package/src/core/attachments/state.ts +2 -2
  83. package/src/core/host/AGENTS.md +6 -2
  84. package/src/core/host/__tests__/attachments.test.ts +9 -10
  85. package/src/core/host/__tests__/document.test.ts +18 -16
  86. package/src/core/host/__tests__/events.test.ts +5 -2
  87. package/src/core/host/__tests__/fixtures.ts +6 -4
  88. package/src/core/host/events.ts +18 -2
  89. package/src/core/host/notebook-client.ts +46 -13
  90. package/src/core/host/resources/attachments.ts +3 -3
  91. package/src/core/host/resources/document.ts +3 -3
  92. package/src/core/websocket/__tests__/useNotebookSession.hook.test.tsx +1 -1
  93. package/dist/assets/feedback-button-DDzObtF2.js +0 -1
  94. package/dist/assets/index-ChfDZJzP.css +0 -2
  95. package/dist/assets/panels-BLYQRkEc.js +0 -4
  96. package/src/core/host/__tests__/protocol.test.ts +0 -229
  97. package/src/core/host/__tests__/stream.test.ts +0 -209
  98. package/src/core/host/protocol.ts +0 -1948
  99. package/src/core/host/resources/resource.ts +0 -47
  100. package/src/core/host/stream.ts +0 -211
package/dist/index.html CHANGED
@@ -66,7 +66,7 @@
66
66
  <marimo-server-token data-token="{{ server_token }}" hidden></marimo-server-token>
67
67
  <!-- /TODO -->
68
68
  <title>{{ title }}</title>
69
- <script type="module" crossorigin src="./assets/index-PDJQd7X6.js"></script>
69
+ <script type="module" crossorigin src="./assets/index-CnvKSoR0.js"></script>
70
70
  <link rel="modulepreload" crossorigin href="./assets/rolldown-runtime-B0Z9INg1.js">
71
71
  <link rel="modulepreload" crossorigin href="./assets/react-DVplv7_D.js">
72
72
  <link rel="modulepreload" crossorigin href="./assets/compiler-runtime-BrajqUja.js">
@@ -79,7 +79,7 @@
79
79
  <link rel="modulepreload" crossorigin href="./assets/utils-B4K466FK.js">
80
80
  <link rel="modulepreload" crossorigin href="./assets/session-B8Y-GJnS.js">
81
81
  <link rel="modulepreload" crossorigin href="./assets/Deferred-CrTnjj37.js">
82
- <link rel="modulepreload" crossorigin href="./assets/config-CYsbZpwa.js">
82
+ <link rel="modulepreload" crossorigin href="./assets/config-BwHT0yGp.js">
83
83
  <link rel="modulepreload" crossorigin href="./assets/isObject-BCaOs5rp.js">
84
84
  <link rel="modulepreload" crossorigin href="./assets/isSymbol-oX0TOjjx.js">
85
85
  <link rel="modulepreload" crossorigin href="./assets/now-Cmx0b_zA.js">
@@ -139,7 +139,7 @@
139
139
  <link rel="modulepreload" crossorigin href="./assets/useTheme-DLtPc-39.js">
140
140
  <link rel="modulepreload" crossorigin href="./assets/useAsyncData-DhhdOGGd.js">
141
141
  <link rel="modulepreload" crossorigin href="./assets/purify.es--06brOip.js">
142
- <link rel="modulepreload" crossorigin href="./assets/cells-CdH98VSn.js">
142
+ <link rel="modulepreload" crossorigin href="./assets/cells-BdgzY0of.js">
143
143
  <link rel="modulepreload" crossorigin href="./assets/coerce-DWjFeXOY.js">
144
144
  <link rel="modulepreload" crossorigin href="./assets/get-DjNf4SIX.js">
145
145
  <link rel="modulepreload" crossorigin href="./assets/_hasPath-BmRQipI0.js">
@@ -147,47 +147,47 @@
147
147
  <link rel="modulepreload" crossorigin href="./assets/_baseSet-Bpdo9AvU.js">
148
148
  <link rel="modulepreload" crossorigin href="./assets/pick-DKIID_Mo.js">
149
149
  <link rel="modulepreload" crossorigin href="./assets/errors-CNsgAw6m.js">
150
- <link rel="modulepreload" crossorigin href="./assets/config-BoBwH7CU.js">
150
+ <link rel="modulepreload" crossorigin href="./assets/config-DXjnAwtL.js">
151
151
  <link rel="modulepreload" crossorigin href="./assets/state-C0irhlOZ.js">
152
152
  <link rel="modulepreload" crossorigin href="./assets/state-DaWgt-rn.js">
153
153
  <link rel="modulepreload" crossorigin href="./assets/LazyAnyLanguageCodeMirror-BPYE76jR.js">
154
154
  <link rel="modulepreload" crossorigin href="./assets/copy-KlhazlhB.js">
155
155
  <link rel="modulepreload" crossorigin href="./assets/micromark-factory-space-D9Dr-k4J.js">
156
156
  <link rel="modulepreload" crossorigin href="./assets/chunk-YOKDWASO-BIpRENEC.js">
157
- <link rel="modulepreload" crossorigin href="./assets/markdown-renderer-BFyD6Jhs.js">
157
+ <link rel="modulepreload" crossorigin href="./assets/markdown-renderer-DX2O5YiE.js">
158
158
  <link rel="modulepreload" crossorigin href="./assets/copy-Djr5m5ac.js">
159
159
  <link rel="modulepreload" crossorigin href="./assets/copy-icon-8-a5vovc.js">
160
- <link rel="modulepreload" crossorigin href="./assets/useRunCells-BHBMk9zW.js">
161
- <link rel="modulepreload" crossorigin href="./assets/RenderHTML-B1FzB5NY.js">
162
- <link rel="modulepreload" crossorigin href="./assets/blob-BQfLiwKr.js">
160
+ <link rel="modulepreload" crossorigin href="./assets/useRunCells-DP09DHT6.js">
161
+ <link rel="modulepreload" crossorigin href="./assets/RenderHTML-BFaztTR0.js">
162
+ <link rel="modulepreload" crossorigin href="./assets/blob-BSfsdCNF.js">
163
163
  <link rel="modulepreload" crossorigin href="./assets/kbd-pdKBv96t.js">
164
- <link rel="modulepreload" crossorigin href="./assets/useInstallPackage-Cw0dVELh.js">
164
+ <link rel="modulepreload" crossorigin href="./assets/useInstallPackage-CVItDn1e.js">
165
165
  <link rel="modulepreload" crossorigin href="./assets/share-BZW3tzEX.js">
166
166
  <link rel="modulepreload" crossorigin href="./assets/events-CbeVJ6OD.js">
167
- <link rel="modulepreload" crossorigin href="./assets/state-TVREh4u4.js">
168
- <link rel="modulepreload" crossorigin href="./assets/ErrorBoundary-hliG40Pk.js">
167
+ <link rel="modulepreload" crossorigin href="./assets/state-BHuYDaxs.js">
168
+ <link rel="modulepreload" crossorigin href="./assets/ErrorBoundary-DmXl4Nre.js">
169
169
  <link rel="modulepreload" crossorigin href="./assets/chevron-right-eAtVhbNZ.js">
170
170
  <link rel="modulepreload" crossorigin href="./assets/dropdown-menu-DS6umAnH.js">
171
171
  <link rel="modulepreload" crossorigin href="./assets/html-to-image-D_0rd3_B.js">
172
- <link rel="modulepreload" crossorigin href="./assets/download-CCZkq0y4.js">
172
+ <link rel="modulepreload" crossorigin href="./assets/download-RV4i1fWI.js">
173
173
  <link rel="modulepreload" crossorigin href="./assets/switch-1h011wlH.js">
174
174
  <link rel="modulepreload" crossorigin href="./assets/tabs-CY8E4r9U.js">
175
175
  <link rel="modulepreload" crossorigin href="./assets/table-DG7Ap4H4.js">
176
176
  <link rel="modulepreload" crossorigin href="./assets/eye-off-CxVozGAC.js">
177
177
  <link rel="modulepreload" crossorigin href="./assets/refresh-cw-Qw1f8Jhy.js">
178
- <link rel="modulepreload" crossorigin href="./assets/tree-actions-B1vsdenY.js">
178
+ <link rel="modulepreload" crossorigin href="./assets/tree-actions-Be_mzC1C.js">
179
179
  <link rel="modulepreload" crossorigin href="./assets/ellipsis-63DyBLHQ.js">
180
180
  <link rel="modulepreload" crossorigin href="./assets/external-link-UrX9KO36.js">
181
181
  <link rel="modulepreload" crossorigin href="./assets/spinner-DyNE-o8o.js">
182
182
  <link rel="modulepreload" crossorigin href="./assets/message-circle-C3rKm8_a.js">
183
183
  <link rel="modulepreload" crossorigin href="./assets/hat-glasses-C8RhSVii.js">
184
184
  <link rel="modulepreload" crossorigin href="./assets/package-GSoSTiIK.js">
185
- <link rel="modulepreload" crossorigin href="./assets/datasource-BA7YF4eo.js">
186
- <link rel="modulepreload" crossorigin href="./assets/error-entries-BVXrGOTZ.js">
185
+ <link rel="modulepreload" crossorigin href="./assets/datasource-dKk3JHSQ.js">
186
+ <link rel="modulepreload" crossorigin href="./assets/error-entries-CJS0gOId.js">
187
187
  <link rel="modulepreload" crossorigin href="./assets/alert-DTaqCu_d.js">
188
- <link rel="modulepreload" crossorigin href="./assets/state-_uXVmwuN.js">
189
- <link rel="modulepreload" crossorigin href="./assets/cell-link-B_QkRkm-.js">
190
- <link rel="modulepreload" crossorigin href="./assets/MarimoErrorOutput-BaHdbtck.js">
188
+ <link rel="modulepreload" crossorigin href="./assets/state-CVgqwwCU.js">
189
+ <link rel="modulepreload" crossorigin href="./assets/cell-link-DFPHORAO.js">
190
+ <link rel="modulepreload" crossorigin href="./assets/MarimoErrorOutput-DVjK8RgY.js">
191
191
  <link rel="modulepreload" crossorigin href="./assets/useDateFormatter-DA-62E-Y.js">
192
192
  <link rel="modulepreload" crossorigin href="./assets/en-US-Buu61juQ.js">
193
193
  <link rel="modulepreload" crossorigin href="./assets/isValid-q_Ad80ug.js">
@@ -206,13 +206,13 @@
206
206
  <link rel="modulepreload" crossorigin href="./assets/formats-zylfwejq.js">
207
207
  <link rel="modulepreload" crossorigin href="./assets/table-vrvqpuKJ.js">
208
208
  <link rel="modulepreload" crossorigin href="./assets/react-resizable-panels.browser.esm-Dbe0MrFr.js">
209
- <link rel="modulepreload" crossorigin href="./assets/JsonOutput-9tmC-p6h.js">
209
+ <link rel="modulepreload" crossorigin href="./assets/JsonOutput-DsMCKg5f.js">
210
210
  <link rel="modulepreload" crossorigin href="./assets/chart-no-axes-column-C4_v6fQW.js">
211
211
  <link rel="modulepreload" crossorigin href="./assets/square-function-_W_Lo0P4.js">
212
212
  <link rel="modulepreload" crossorigin href="./assets/spec-uCpVvaAR.js">
213
213
  <link rel="modulepreload" crossorigin href="./assets/semaphore-BjoL5P0h.js">
214
214
  <link rel="modulepreload" crossorigin href="./assets/fileToBase64-BgBraYAr.js">
215
- <link rel="modulepreload" crossorigin href="./assets/useBoolean-5g-bBaYF.js">
215
+ <link rel="modulepreload" crossorigin href="./assets/useBoolean-j0qHaJxu.js">
216
216
  <link rel="modulepreload" crossorigin href="./assets/code-xml-SQaZqvcO.js">
217
217
  <link rel="modulepreload" crossorigin href="./assets/file-headphone-Dl35U6h3.js">
218
218
  <link rel="modulepreload" crossorigin href="./assets/file-BPBVl9pl.js">
@@ -220,11 +220,11 @@
220
220
  <link rel="modulepreload" crossorigin href="./assets/file-icons-CdJgUy-I.js">
221
221
  <link rel="modulepreload" crossorigin href="./assets/globe-UdPdIbF7.js">
222
222
  <link rel="modulepreload" crossorigin href="./assets/esm-CI_o7NhW.js">
223
- <link rel="modulepreload" crossorigin href="./assets/useAddCell-DZ-50qEG.js">
224
- <link rel="modulepreload" crossorigin href="./assets/readonly-python-code-DrXDDAnA.js">
223
+ <link rel="modulepreload" crossorigin href="./assets/useAddCell-DK79W1vA.js">
224
+ <link rel="modulepreload" crossorigin href="./assets/readonly-python-code-BLotL3XP.js">
225
225
  <link rel="modulepreload" crossorigin href="./assets/data-grid-types-DgHVN_Zz.js">
226
226
  <link rel="modulepreload" crossorigin href="./assets/glide-utils-HFqhvWHI.js">
227
- <link rel="modulepreload" crossorigin href="./assets/column-preview-CsEBzIUE.js">
227
+ <link rel="modulepreload" crossorigin href="./assets/column-preview-D-MQXrz3.js">
228
228
  <link rel="modulepreload" crossorigin href="./assets/square-BPmgQFnh.js">
229
229
  <link rel="modulepreload" crossorigin href="./assets/triangle-alert-DmIqR8sY.js">
230
230
  <link rel="modulepreload" crossorigin href="./assets/prop-types-Djf4O40e.js">
@@ -236,11 +236,11 @@
236
236
  <link rel="modulepreload" crossorigin href="./assets/icons-CiZ_8zS-.js">
237
237
  <link rel="modulepreload" crossorigin href="./assets/useDeepCompareMemoize-DFIVN9dn.js">
238
238
  <link rel="modulepreload" crossorigin href="./assets/pathUtils-DPmlLd-r.js">
239
- <link rel="modulepreload" crossorigin href="./assets/floating-outline-CTy-Iakk.js">
239
+ <link rel="modulepreload" crossorigin href="./assets/floating-outline-CrWdiNQ2.js">
240
240
  <link rel="stylesheet" crossorigin href="./assets/cells-0PFKL3SH.css">
241
241
  <link rel="stylesheet" crossorigin href="./assets/markdown-renderer-DjIHoF9Z.css">
242
242
  <link rel="stylesheet" crossorigin href="./assets/JsonOutput-B0GmlMnR.css">
243
- <link rel="stylesheet" crossorigin href="./assets/index-ChfDZJzP.css">
243
+ <link rel="stylesheet" crossorigin href="./assets/index-evFWHKmM.css">
244
244
  </head>
245
245
  <body>
246
246
  <div id="root"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marimo-team/frontend",
3
- "version": "0.25.3-dev40",
3
+ "version": "0.25.3-dev44",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -57,6 +57,7 @@
57
57
  "@marimo-team/codemirror-mcp": "^0.1.7",
58
58
  "@marimo-team/codemirror-sql": "^0.3.0",
59
59
  "@marimo-team/llm-info": "workspace:*",
60
+ "@marimo-team/client": "workspace:*",
60
61
  "@marimo-team/marimo-api": "workspace:*",
61
62
  "@marimo-team/react-slotz": "^0.2.0",
62
63
  "@marimo-team/smart-cells": "workspace:*",
@@ -185,8 +186,6 @@
185
186
  "storybook": "storybook dev -p 6006",
186
187
  "build-storybook": "storybook build",
187
188
  "sync-katex-css": "node --experimental-strip-types scripts/sync-katex-css.ts",
188
- "codegen": "node --experimental-strip-types scripts/generate-host-protocol.ts",
189
- "codegen:check": "node --experimental-strip-types scripts/generate-host-protocol.ts --check",
190
189
  "doctor": "npx react-doctor@latest"
191
190
  },
192
191
  "peerDependencies": {
@@ -216,7 +215,6 @@
216
215
  "jsdom": "^24.1.3",
217
216
  "msw": "^2.15.0",
218
217
  "npm-run-all2": "^6.2.6",
219
- "orval": "8.40.0",
220
218
  "oxc-transform-react": "0.145.0",
221
219
  "oxfmt": "^0.68.0",
222
220
  "oxlint": "^1.83.0",
@@ -19,6 +19,7 @@ it("enforces host dependencies for runtime and type imports", () => {
19
19
  "src/core/host/allowed.ts": `
20
20
  import { atom } from "jotai/vanilla";
21
21
  import { z } from "zod";
22
+ import * as Protocol from "@marimo-team/client/protocol";
22
23
  import { Logger } from "@/utils/Logger";
23
24
  import type { Document } from "./document";
24
25
  export * from "@/core/host/events";
@@ -914,6 +914,94 @@ describe("ExportActions dialog", () => {
914
914
  expect(within(dialog).queryByRole("group")).not.toBeInTheDocument();
915
915
  });
916
916
 
917
+ it("describes format options with their description and current settings", async () => {
918
+ renderExportActions({
919
+ getExportMetadata: vi.fn().mockResolvedValue(geometryMetadata),
920
+ });
921
+ await openDialog();
922
+ await screen.findByRole("button", { name: "GeoParquet options" });
923
+
924
+ for (const [label, description] of [
925
+ ["CSV", "Comma-separated values Comma · UTF-8"],
926
+ ["TSV", "Best for Excel and Google Sheets UTF-8"],
927
+ ["JSON", "Raw JSON data Escapes non-ASCII"],
928
+ ["GeoParquet", "Parquet with geometry and CRS metadata location"],
929
+ ["GeoJSON", "Geometry in longitude and latitude location"],
930
+ ]) {
931
+ expect(
932
+ screen.getByRole("button", { name: `${label} options` }),
933
+ ).toHaveAccessibleDescription(description);
934
+ }
935
+
936
+ const csvOptions = screen.getByRole("button", { name: "CSV options" });
937
+ fireEvent.click(csvOptions);
938
+ fireEvent.change(screen.getByRole("combobox", { name: "Delimiter" }), {
939
+ target: { value: ";" },
940
+ });
941
+ expect(csvOptions).toHaveAccessibleDescription(
942
+ "Comma-separated values Semicolon · UTF-8",
943
+ );
944
+ fireEvent.click(csvOptions);
945
+ expect(csvOptions).toHaveAccessibleDescription(
946
+ "Comma-separated values Semicolon · UTF-8",
947
+ );
948
+ });
949
+
950
+ it.each([
951
+ ["CSV", "Comma-separated values"],
952
+ ["TSV", "Best for Excel and Google Sheets"],
953
+ ["JSON", "Raw JSON data"],
954
+ ["GeoParquet", "Parquet with geometry and CRS metadata"],
955
+ ["GeoJSON", "Geometry in longitude and latitude"],
956
+ ])(
957
+ "toggles %s options from the row label and description",
958
+ async (label, description) => {
959
+ renderExportActions({
960
+ getExportMetadata: vi.fn().mockResolvedValue(geometryMetadata),
961
+ });
962
+ await openDialog();
963
+ const toggle = await screen.findByRole("button", {
964
+ name: `${label} options`,
965
+ });
966
+
967
+ fireEvent.click(screen.getByText(label));
968
+ expect(toggle).toHaveAttribute("aria-expanded", "true");
969
+ expect(
970
+ screen.getByRole("group", { name: `${label} options` }),
971
+ ).toBeInTheDocument();
972
+
973
+ fireEvent.click(screen.getByText(description));
974
+ expect(toggle).toHaveAttribute("aria-expanded", "false");
975
+ expect(
976
+ screen.queryByRole("group", { name: `${label} options` }),
977
+ ).not.toBeInTheDocument();
978
+ },
979
+ );
980
+
981
+ it("keeps download and copy independent of row expansion", async () => {
982
+ vi.stubGlobal(
983
+ "fetch",
984
+ vi.fn().mockResolvedValue({
985
+ ok: true,
986
+ text: vi.fn().mockResolvedValue("name,value\n"),
987
+ }),
988
+ );
989
+ renderExportActions();
990
+ await openDialog();
991
+ const toggle = screen.getByRole("button", { name: "CSV options" });
992
+
993
+ fireEvent.click(screen.getByRole("button", { name: "Download CSV" }));
994
+ await waitFor(() => expect(downloadByURL).toHaveBeenCalled());
995
+ expect(toggle).toHaveAttribute("aria-expanded", "false");
996
+
997
+ fireEvent.click(screen.getByText("CSV"));
998
+ fireEvent.click(screen.getByRole("button", { name: "Copy CSV" }));
999
+ expect(toggle).toHaveAttribute("aria-expanded", "true");
1000
+ await waitFor(() => {
1001
+ expect(copyToClipboard).toHaveBeenCalledWith("name,value\n");
1002
+ });
1003
+ });
1004
+
917
1005
  it("sends only changed CSV options with a download", async () => {
918
1006
  renderExportActions();
919
1007
  await openDialog();
@@ -761,7 +761,10 @@ export const ExportActions: React.FC<ExportActionProps> = (props) => {
761
761
  const expanded =
762
762
  configurableFormat !== null &&
763
763
  expandedFormat === configurableFormat;
764
+ const FormatHeader = configurableFormat ? "button" : "div";
764
765
  const panelId = `export-options-${option.format}`;
766
+ const descriptionId = `${panelId}-description`;
767
+ const summaryId = `${panelId}-summary`;
765
768
  const rowFailure =
766
769
  failure?.action.format === option.format ? failure : null;
767
770
  const summary =
@@ -802,55 +805,78 @@ export const ExportActions: React.FC<ExportActionProps> = (props) => {
802
805
  data-testid={`export-row-${option.format}`}
803
806
  className={cn(expanded && "bg-muted/40")}
804
807
  >
805
- <div className="grid min-h-[60px] grid-cols-[28px_minmax(0,1fr)_auto] items-center gap-x-1 px-2.5 py-2 hover:bg-accent/50">
806
- {configurableFormat ? (
807
- <Button
808
- type="button"
809
- variant="ghost"
810
- size="icon"
811
- aria-label={`${optionLabel} options`}
812
- aria-expanded={expanded}
813
- aria-controls={panelId}
814
- onClick={() => toggleExpanded(option.format)}
808
+ <div className="grid grid-cols-[minmax(0,1fr)_auto] items-center hover:bg-accent/50">
809
+ <FormatHeader
810
+ type={configurableFormat ? "button" : undefined}
811
+ className={cn(
812
+ "grid min-h-[60px] min-w-0 grid-cols-[28px_minmax(0,1fr)] items-center gap-x-1 py-2 pl-2.5 pr-1 text-left",
813
+ configurableFormat &&
814
+ "cursor-pointer focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-ring",
815
+ )}
816
+ aria-label={
817
+ configurableFormat ? `${optionLabel} options` : undefined
818
+ }
819
+ aria-describedby={
820
+ configurableFormat
821
+ ? [descriptionId, summary && summaryId]
822
+ .filter(Boolean)
823
+ .join(" ")
824
+ : undefined
825
+ }
826
+ aria-expanded={configurableFormat ? expanded : undefined}
827
+ aria-controls={configurableFormat ? panelId : undefined}
828
+ onClick={
829
+ configurableFormat
830
+ ? () => toggleExpanded(option.format)
831
+ : undefined
832
+ }
833
+ >
834
+ <span
835
+ aria-hidden={true}
836
+ className="inline-flex h-6 w-6 items-center justify-center"
815
837
  >
816
- <ChevronRightIcon
817
- className={cn(
818
- "h-4 w-4 text-muted-foreground transition-transform",
819
- expanded && "rotate-90",
820
- )}
838
+ {configurableFormat && (
839
+ <ChevronRightIcon
840
+ className={cn(
841
+ "h-4 w-4 text-muted-foreground transition-transform",
842
+ expanded && "rotate-90",
843
+ )}
844
+ />
845
+ )}
846
+ </span>
847
+ <span className="flex min-w-0 items-center gap-3 pl-1">
848
+ <option.icon
849
+ aria-hidden={true}
850
+ data-testid={`export-format-icon-${option.format}`}
851
+ className="h-4 w-4 shrink-0 text-muted-foreground"
821
852
  />
822
- </Button>
823
- ) : (
824
- <span aria-hidden={true} className="h-6 w-6" />
825
- )}
826
- <div className="flex min-w-0 items-center gap-3 pl-1">
827
- <option.icon
828
- aria-hidden={true}
829
- data-testid={`export-format-icon-${option.format}`}
830
- className="h-4 w-4 shrink-0 text-muted-foreground"
831
- />
832
- <div className="grid min-w-0 gap-1">
833
- <span className="flex min-w-0 items-baseline gap-x-2">
834
- <span className="text-sm font-medium leading-tight">
835
- {optionLabel}
836
- </span>
837
- {summary && (
838
- <span
839
- data-testid={`export-summary-${option.format}`}
840
- className="min-w-0 truncate text-xs text-muted-foreground"
841
- >
842
- {summary}
853
+ <span className="grid min-w-0 gap-1">
854
+ <span className="flex min-w-0 items-baseline gap-x-2">
855
+ <span className="text-sm font-medium leading-tight">
856
+ {optionLabel}
843
857
  </span>
844
- )}
845
- </span>
846
- <span className="text-xs text-muted-foreground leading-tight">
847
- {option.format === "parquet" && hasGeometry
848
- ? "Parquet with geometry and CRS metadata"
849
- : option.description}
858
+ {summary && (
859
+ <span
860
+ id={summaryId}
861
+ data-testid={`export-summary-${option.format}`}
862
+ className="min-w-0 truncate text-xs text-muted-foreground"
863
+ >
864
+ {summary}
865
+ </span>
866
+ )}
867
+ </span>
868
+ <span
869
+ id={descriptionId}
870
+ className="text-xs text-muted-foreground leading-tight"
871
+ >
872
+ {option.format === "parquet" && hasGeometry
873
+ ? "Parquet with geometry and CRS metadata"
874
+ : option.description}
875
+ </span>
850
876
  </span>
851
- </div>
852
- </div>
853
- <div className="flex items-center gap-0.5">
877
+ </span>
878
+ </FormatHeader>
879
+ <div className="flex items-center gap-0.5 pr-2.5">
854
880
  <Tooltip
855
881
  content={
856
882
  option.canDownload
@@ -1,10 +1,10 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
3
  import { atom } from "jotai";
4
- import type { Attachment } from "@/core/host/protocol";
4
+ import type { Attachment } from "@marimo-team/client/protocol";
5
5
  import { notebookClientAtom } from "@/core/websocket/state";
6
6
 
7
- export type { Attachment } from "@/core/host/protocol";
7
+ export type { Attachment } from "@marimo-team/client/protocol";
8
8
 
9
9
  export const agentAttachmentsAtom = atom((get) => {
10
10
  const notebook = get(notebookClientAtom);
@@ -1,7 +1,11 @@
1
1
  # Host core
2
2
 
3
- Production code may import host modules, `jotai/vanilla`, `zod`, and
4
- `@/utils/Logger`. Enforced by `marimo/host-imports`. Tests are exempt.
3
+ Production code may import host modules, `@marimo-team/client`,
4
+ `jotai/vanilla`, `zod`, and `@/utils/Logger`. Enforced by
5
+ `marimo/host-imports`. Tests are exempt.
6
+
7
+ The protocol schemas and types live in `@marimo-team/client/protocol`.
8
+ The native `marimo` event is a marimo extension and is defined in `events.ts`.
5
9
 
6
10
  Define interfaces here and inject application behavior through adapters.
7
11
 
@@ -2,15 +2,15 @@
2
2
 
3
3
  import { describe, expect, it } from "vitest";
4
4
  import { attachments } from "../resources/attachments";
5
- import { createStream } from "../stream";
5
+ import { createReducer } from "@marimo-team/client/reducer";
6
6
  import { fixtureEvents } from "./fixtures";
7
7
 
8
- const stream = createStream({ attachments });
8
+ const reducer = createReducer({ attachments });
9
9
  const snapshot = fixtureEvents("notebook-events.sse");
10
10
  const records = snapshot.flatMap((event) =>
11
11
  event.event === "attachment" ? [event.data.attachment] : [],
12
12
  );
13
- const confirmed = () => snapshot.reduce(stream.reduce, stream.initial);
13
+ const confirmed = () => snapshot.reduce(reducer.reduce, reducer.initial);
14
14
 
15
15
  describe("attachment resource", () => {
16
16
  it("collects snapshot records, replaces by id, and removes attachments", () => {
@@ -18,7 +18,7 @@ describe("attachment resource", () => {
18
18
  expect(state.resources.attachments).toEqual(records);
19
19
  const [browser, agent] = records;
20
20
  const renamed = { ...agent, name: "Renamed agent" };
21
- const updated = stream.reduce(state, {
21
+ const updated = reducer.reduce(state, {
22
22
  event: "attachment",
23
23
  id: "98",
24
24
  data: { attachment: renamed },
@@ -26,13 +26,13 @@ describe("attachment resource", () => {
26
26
  expect(updated.resources.attachments).toEqual([browser, renamed]);
27
27
  expect(state.resources.attachments).toEqual(records);
28
28
 
29
- const removed = stream.reduce(updated, {
29
+ const removed = reducer.reduce(updated, {
30
30
  event: "attachment.removed",
31
31
  id: "99",
32
32
  data: { id: browser.id, time: "2026-10-01T09:30:00Z" },
33
33
  });
34
34
  expect(removed.resources.attachments).toEqual([renamed]);
35
- const repeated = stream.reduce(removed, {
35
+ const repeated = reducer.reduce(removed, {
36
36
  event: "attachment.removed",
37
37
  id: "100",
38
38
  data: { id: browser.id, time: "2026-10-01T09:30:00Z" },
@@ -40,10 +40,9 @@ describe("attachment resource", () => {
40
40
  expect(repeated.resources.attachments).toBe(removed.resources.attachments);
41
41
  });
42
42
 
43
- it("retains records for replay and rebuilds them after reset", () => {
43
+ it("rebuilds records after reset", () => {
44
44
  const state = confirmed();
45
- expect(stream.resume(state)).toBe(state);
46
- const reset = stream.reduce(state, { event: "reset", data: {} });
45
+ const reset = reducer.reduce(state, { event: "reset", data: {} });
47
46
  expect(reset.resources.attachments).toEqual([]);
48
47
  const replacement = snapshot
49
48
  .filter(
@@ -51,7 +50,7 @@ describe("attachment resource", () => {
51
50
  event.event !== "attachment" ||
52
51
  event.data.attachment.id === records[0].id,
53
52
  )
54
- .reduce(stream.reduce, reset);
53
+ .reduce(reducer.reduce, reset);
55
54
  expect(replacement.resources.attachments).toEqual([records[0]]);
56
55
  });
57
56
  });
@@ -1,17 +1,20 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
3
  import { describe, expect, it } from "vitest";
4
- import type { NotebookEvent } from "../events";
4
+ import type * as Protocol from "@marimo-team/client/protocol";
5
5
  import { document } from "../resources/document";
6
- import { createStream } from "../stream";
6
+ import { createReducer } from "@marimo-team/client/reducer";
7
7
  import { fixtureEvents } from "./fixtures";
8
8
 
9
- const stream = createStream({ document });
9
+ const reducer = createReducer({ document });
10
10
  const snapshot = fixtureEvents("notebook-events.sse");
11
11
  const edits = fixtureEvents("edits.sse");
12
12
 
13
- function replay(events: readonly NotebookEvent[], from = stream.initial) {
14
- return events.reduce((state, event) => stream.reduce(state, event), from);
13
+ function replay(
14
+ events: readonly Protocol.EventOutput[],
15
+ from = reducer.initial,
16
+ ) {
17
+ return events.reduce((state, event) => reducer.reduce(state, event), from);
15
18
  }
16
19
 
17
20
  const confirmed = () => replay(snapshot);
@@ -33,12 +36,12 @@ describe("document resource", () => {
33
36
  confirmed(),
34
37
  );
35
38
  expect(current(pending)).toEqual(first);
36
- const changed = stream.reduce(pending, edit);
39
+ const changed = reducer.reduce(pending, edit);
37
40
  expect(current(changed)?.revision).toEqual(edit.data.document);
38
41
  expect([...current(changed)!.cells.keys()].toSorted()).toEqual(
39
42
  edit.data.document.order.toSorted(),
40
43
  );
41
- const saved = current(stream.reduce(changed, save));
44
+ const saved = current(reducer.reduce(changed, save));
42
45
  expect(saved?.revision).toEqual(save.data.document);
43
46
  expect(saved?.cells.get("c3")?.code).toBe("x = 22");
44
47
  expect(saved?.cells.has("k7f2")).toBe(false);
@@ -55,7 +58,7 @@ describe("document resource", () => {
55
58
  order: revision.order.toReversed(),
56
59
  version: revision.version + 1,
57
60
  };
58
- const changed = stream.reduce(state, {
61
+ const changed = reducer.reduce(state, {
59
62
  event: "document",
60
63
  data: { document: reordered },
61
64
  id: "200",
@@ -66,17 +69,17 @@ describe("document resource", () => {
66
69
  });
67
70
 
68
71
  const empty = { ...revision, order: [] };
69
- const opening = stream.reduce(stream.initial, {
72
+ const opening = reducer.reduce(reducer.initial, {
70
73
  event: "document",
71
74
  data: { document: empty },
72
75
  });
73
76
  expect(current(opening)).toBeNull();
74
77
  expect(
75
- current(stream.reduce(opening, { event: "ready", data: {}, id: "0" })),
78
+ current(reducer.reduce(opening, { event: "ready", data: {}, id: "0" })),
76
79
  ).toEqual({ revision: empty, cells: new Map() });
77
80
  expect(
78
81
  current(
79
- stream.reduce(stream.initial, { event: "ready", data: {}, id: "0" }),
82
+ reducer.reduce(reducer.initial, { event: "ready", data: {}, id: "0" }),
80
83
  ),
81
84
  ).toBeNull();
82
85
  });
@@ -89,7 +92,6 @@ describe("document resource", () => {
89
92
  }
90
93
  const partial = replay([cell, removed], state);
91
94
  expect(current(partial)).toBe(current(state));
92
- expect(stream.resume(partial)).toBe(partial);
93
95
  const completed = replay(
94
96
  [published, { event: "ready", data: {}, id: "113" }],
95
97
  partial,
@@ -98,7 +100,7 @@ describe("document resource", () => {
98
100
  });
99
101
 
100
102
  it("removes a notebook without waiting for individual cell removals", () => {
101
- const removed = stream.reduce(confirmed(), {
103
+ const removed = reducer.reduce(confirmed(), {
102
104
  event: "notebook.removed",
103
105
  data: { id: "n1", time: "2026-10-01T09:30:00Z" },
104
106
  id: "200",
@@ -110,15 +112,15 @@ describe("document resource", () => {
110
112
  const state = confirmed();
111
113
  const revision = current(state)!.revision;
112
114
  expect(() =>
113
- stream.reduce(state, {
115
+ reducer.reduce(state, {
114
116
  event: "document",
115
117
  data: { document: { ...revision, order: ["missing"] } },
116
118
  id: "200",
117
119
  }),
118
120
  ).toThrow("Document records do not match");
119
- const partial = stream.reduce(state, edits[0]);
121
+ const partial = reducer.reduce(state, edits[0]);
120
122
  expect(() =>
121
- stream.reduce(partial, { event: "ready", data: {}, id: "200" }),
123
+ reducer.reduce(partial, { event: "ready", data: {}, id: "200" }),
122
124
  ).toThrow("incomplete document update");
123
125
  });
124
126
  });
@@ -1,8 +1,8 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
- import { describe, expect, it } from "vitest";
3
+ import { describe, expect, expectTypeOf, it } from "vitest";
4
4
  import { z } from "zod";
5
- import { parseNotebookEvent } from "../events";
5
+ import { type NotebookEvent, parseNotebookEvent } from "../events";
6
6
 
7
7
  describe("notebook messages", () => {
8
8
  it("normalizes session and host envelopes for native marimo messages", () => {
@@ -10,6 +10,9 @@ describe("notebook messages", () => {
10
10
  op: "variables",
11
11
  variables: [{ name: "x", value: Number.NaN }],
12
12
  };
13
+ expectTypeOf<
14
+ Extract<NotebookEvent, { event: "marimo" }>["data"]["marimo"]
15
+ >().toBeUnknown();
13
16
  const host = { event: "marimo", data: { marimo: notification } };
14
17
  expect(parseNotebookEvent({ data: notification })).toEqual(host);
15
18
  expect(parseNotebookEvent({ ...host, id: "42" })).toEqual({