@marimo-team/islands 0.23.7-dev7 → 0.23.7-dev70

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 (553) hide show
  1. package/dist/{ConnectedDataExplorerComponent-PmilQqXR.js → ConnectedDataExplorerComponent-2lBNiUv6.js} +14 -14
  2. package/dist/{ErrorBoundary-Da4UeYxT.js → ErrorBoundary-D3wrPNma.js} +1 -1
  3. package/dist/{any-language-editor-BVR0l12r.js → any-language-editor-VWs_7v27.js} +15 -15
  4. package/dist/apl-Bdc61P1y.js +4 -0
  5. package/dist/{arc-CHF8PiiF.js → arc-DfkSnvZm.js} +2 -2
  6. package/dist/{architecture-7HQA4BMR-D0JB_3hE.js → architecture-7HQA4BMR-CS9jOrqM.js} +1 -1
  7. package/dist/{architectureDiagram-VXUJARFQ-BXQEUDtK.js → architectureDiagram-VXUJARFQ-CXVJxFhH.js} +16 -16
  8. package/dist/asciiarmor-DVRHDGzT.js +4 -0
  9. package/dist/asn1-BmuKfkfu.js +4 -0
  10. package/dist/assets/__vite-browser-external-CAdMKBac.js +1 -0
  11. package/dist/assets/worker-CpBbwbQo.js +73 -0
  12. package/dist/{blockDiagram-VD42YOAC-DhJe-Y9i.js → blockDiagram-VD42YOAC-DGDaxR8I.js} +11 -11
  13. package/dist/brainfuck-DPrRpyTV.js +4 -0
  14. package/dist/{button-CA5pI2YF.js → button-Dj4BTre0.js} +5 -0
  15. package/dist/{c4Diagram-YG6GDRKO-9dSfzOFR.js → c4Diagram-YG6GDRKO-C2hc6ne8.js} +5 -5
  16. package/dist/{capabilities-6laDasij.js → capabilities-C9rrYCzf.js} +1 -1
  17. package/dist/{channel-MqYIiKgS.js → channel-BBoIVUrJ.js} +1 -1
  18. package/dist/{chat-ui-B-gbqk_F.js → chat-ui-D3XBept8.js} +626 -234
  19. package/dist/{check-CFM2mVDr.js → check-BcUIXnUT.js} +1 -1
  20. package/dist/{chunk-4BX2VUAB-BwfrWBqN.js → chunk-4BX2VUAB-CzXltWHN.js} +1 -1
  21. package/dist/{chunk-55IACEB6-D8THf2mi.js → chunk-55IACEB6-B-1mjMMC.js} +1 -1
  22. package/dist/{chunk-5FQGJX7Z-CO1e63h_.js → chunk-5FQGJX7Z-BOg95xG5.js} +2 -2
  23. package/dist/{chunk-ABZYJK2D-BrBb_0yY.js → chunk-ABZYJK2D-D0cLy8Bb.js} +2 -2
  24. package/dist/{chunk-ATLVNIR6-D-0XqNah.js → chunk-ATLVNIR6-BXsEjlHF.js} +2 -2
  25. package/dist/{chunk-B4BG7PRW-8iRKvugR.js → chunk-B4BG7PRW-Q1usn6T3.js} +7 -7
  26. package/dist/{chunk-CVBHYZKI-B6xhgaBd.js → chunk-CVBHYZKI-B_c5YBcW.js} +1 -1
  27. package/dist/{chunk-DI55MBZ5-C0_2D4m4.js → chunk-DI55MBZ5-D1qLYNrb.js} +6 -6
  28. package/dist/{chunk-EXTU4WIE-Jiw9ca1u.js → chunk-EXTU4WIE-BKNXdLmD.js} +2 -2
  29. package/dist/{chunk-FMBD7UC4-CHdus51S.js → chunk-FMBD7UC4-Ie8M9q0W.js} +1 -1
  30. package/dist/{chunk-HN2XXSSU-2Vfbq-kU.js → chunk-HN2XXSSU-E3n-Ys7Z.js} +1 -1
  31. package/dist/{chunk-JA3XYJ7Z-6wbaigKe.js → chunk-JA3XYJ7Z-D6c6cOBG.js} +3 -3
  32. package/dist/{chunk-JZLCHNYA-_rfptlUP.js → chunk-JZLCHNYA-BvsPHJmL.js} +6 -6
  33. package/dist/{chunk-MI3HLSF2-Do0-KRc0.js → chunk-MI3HLSF2-CUYEasXO.js} +1 -1
  34. package/dist/{chunk-N4CR4FBY-DIZG9dVD.js → chunk-N4CR4FBY-8ycT-O9a.js} +7 -7
  35. package/dist/{chunk-QN33PNHL-Cc64y40m.js → chunk-QN33PNHL-Bb-eUBW3.js} +2 -2
  36. package/dist/{chunk-QXUST7PY-BDG0-0Or.js → chunk-QXUST7PY-DV8yRwBd.js} +10 -10
  37. package/dist/{chunk-QZHKN3VN-B_Mdb8GC.js → chunk-QZHKN3VN-DRjXVwuJ.js} +1 -1
  38. package/dist/{chunk-S3R3BYOJ-DphMP0FA.js → chunk-S3R3BYOJ-mQeCz5CE.js} +4 -4
  39. package/dist/{chunk-TZMSLE5B-C9LUoYkc.js → chunk-TZMSLE5B-BqW10dHe.js} +3 -3
  40. package/dist/classDiagram-2ON5EDUG--Yh__LHb.js +30 -0
  41. package/dist/classDiagram-v2-WZHVMYZB-BC7X7Xtc.js +30 -0
  42. package/dist/{clike-sBZrGeF8.js → clike-DTxNUn7l.js} +1 -1
  43. package/dist/clojure-DEttQW5T.js +4 -0
  44. package/dist/cmake-jNlx_DaM.js +4 -0
  45. package/dist/cobol-BvvIm5MJ.js +4 -0
  46. package/dist/{code-block-37QAKDTI-0JNwiPGv.js → code-block-37QAKDTI-BsGy1AOJ.js} +1 -1
  47. package/dist/{code-visibility-CiN3Xnfo.js → code-visibility-Ci8Uv-1s.js} +11480 -1992
  48. package/dist/coffeescript-DTpBMyFU.js +4 -0
  49. package/dist/commonlisp-BmmUG8jb.js +4 -0
  50. package/dist/{copy-TGGAUEWp.js → copy-DLf4aN7I.js} +2 -2
  51. package/dist/{cose-bilkent-S5V4N54A-DXHZkJKX.js → cose-bilkent-S5V4N54A-kjoZoid4.js} +2 -2
  52. package/dist/crystal-BxyqmEWC.js +4 -0
  53. package/dist/css-BGoCtuG3.js +4 -0
  54. package/dist/cypher-BmCbdl3u.js +4 -0
  55. package/dist/d-CFrlbjZt.js +4 -0
  56. package/dist/{dagre-6UL2VRFP-tH87fkPA.js → dagre-6UL2VRFP-DRBWoQUw.js} +10 -10
  57. package/dist/{data-grid-overlay-editor-CWUN78-s.js → data-grid-overlay-editor-efe5ZagF.js} +2 -2
  58. package/dist/{diagram-PSM6KHXK-2VjPSCDn.js → diagram-PSM6KHXK-H66ATWP2.js} +18 -18
  59. package/dist/{diagram-QEK2KX5R-CiLmNyta.js → diagram-QEK2KX5R-DItl5Wns.js} +14 -14
  60. package/dist/{diagram-S2PKOQOG-Zha_1CLx.js → diagram-S2PKOQOG-CtuW_ZuL.js} +14 -14
  61. package/dist/diff-D6XwL6P8.js +4 -0
  62. package/dist/{dist-Brkazupz.js → dist--sWVZwjW.js} +1 -1
  63. package/dist/{dist-FN0ZA_8F.js → dist-21ButRCu.js} +1 -1
  64. package/dist/{dist-BetEKbPG.js → dist-B8RaFTRF.js} +1 -1
  65. package/dist/dist-BoHGySTM.js +5 -0
  66. package/dist/dist-ByAz19Qc.js +5 -0
  67. package/dist/dist-C93EysN4.js +5 -0
  68. package/dist/{dist-BHnX0ia_.js → dist-CY-lVor6.js} +1 -1
  69. package/dist/{dist-YP-G7W0f.js → dist-CYDuv4bR.js} +1 -1
  70. package/dist/{dist-CMjD5MQb.js → dist-Cfo5EE2t.js} +1 -1
  71. package/dist/dist-CjivSDvN.js +5 -0
  72. package/dist/dist-Cqwx-MH7.js +5 -0
  73. package/dist/{dist-ESg7xyoD.js → dist-D3ZI9nhS.js} +2 -2
  74. package/dist/{dist-DkC6YEo0.js → dist-DMZNjfX4.js} +1 -1
  75. package/dist/{dist-ChC1BhqM.js → dist-DbpcoFAV.js} +1 -1
  76. package/dist/dist-FUNenbiQ.js +5 -0
  77. package/dist/{dist-BEOU2g1b.js → dist-zhSud5X3.js} +1 -1
  78. package/dist/{dockerfile-COvlVLcE.js → dockerfile-twL37N91.js} +1 -1
  79. package/dist/dtd-Bw0lRN0-.js +4 -0
  80. package/dist/dylan-B55eBHTt.js +4 -0
  81. package/dist/ecl-C8G4p0wn.js +4 -0
  82. package/dist/eiffel-BmH46VJl.js +4 -0
  83. package/dist/elm-DhzeFqkl.js +4 -0
  84. package/dist/{erDiagram-Q2GNP2WA-biHZS05w.js → erDiagram-Q2GNP2WA--19X2kU5.js} +14 -14
  85. package/dist/erlang-CY-wdlsU.js +4 -0
  86. package/dist/{error-banner-DnBPzEWg.js → error-banner-CVkfBUT3.js} +2 -2
  87. package/dist/{esm-Dd1z1auZ.js → esm-CWp0KQeK.js} +1 -1
  88. package/dist/{esm-CYEyrE3Y.js → esm-DjNnlmpf.js} +96 -96
  89. package/dist/{extends-CzJgxo2J.js → extends-vAi97cpa.js} +4 -4
  90. package/dist/{factor-C2GT7jfQ.js → factor-CajWS6mS.js} +1 -1
  91. package/dist/factor-DWkgl0xw.js +4 -0
  92. package/dist/{flowDiagram-NV44I4VS-CWWlUpBR.js → flowDiagram-NV44I4VS-DQmWlo7f.js} +16 -16
  93. package/dist/{formats-CgaK7Gmx.js → formats-Dsy9kkZu.js} +3 -3
  94. package/dist/forth-Cij_ie2t.js +4 -0
  95. package/dist/fortran-Br3X9cfm.js +4 -0
  96. package/dist/{ganttDiagram-JELNMOA3-D7B2c4Z9.js → ganttDiagram-JELNMOA3-BOGXJ8Lk.js} +7 -7
  97. package/dist/gas-DYsGcMN2.js +4 -0
  98. package/dist/gherkin-eVgXQ0fQ.js +4 -0
  99. package/dist/{gitGraph-G5XIXVHT-BdepdFa_.js → gitGraph-G5XIXVHT-DGlbae5m.js} +1 -1
  100. package/dist/{gitGraphDiagram-V2S2FVAM-CtLvNR1S.js → gitGraphDiagram-V2S2FVAM-DjzxfF0P.js} +14 -14
  101. package/dist/{glide-data-editor-CvlvtPWJ.js → glide-data-editor-DucgdjRo.js} +13 -13
  102. package/dist/groovy-_NFHIXG7.js +4 -0
  103. package/dist/haskell-D6xNG_bH.js +4 -0
  104. package/dist/haxe-sU_rzAwn.js +5 -0
  105. package/dist/{html-to-image-hMMPiNe_.js → html-to-image-CpggM7u1.js} +2806 -2547
  106. package/dist/idl-Ds_VbrUx.js +4 -0
  107. package/dist/{info-VBDWY6EO--JNA2rNu.js → info-VBDWY6EO-D2lvLLw5.js} +1 -1
  108. package/dist/{infoDiagram-HS3SLOUP-BbZyOxsP.js → infoDiagram-HS3SLOUP-ChNufFsP.js} +12 -12
  109. package/dist/{input-BAOe64zx.js → input-D4kjoQUB.js} +8 -6
  110. package/dist/javascript-CztfIl0i.js +4 -0
  111. package/dist/{journeyDiagram-XKPGCS4Q-BU2mjjzl.js → journeyDiagram-XKPGCS4Q-BO_O4Ij1.js} +6 -6
  112. package/dist/julia-DDv40QMV.js +4 -0
  113. package/dist/{kanban-definition-3W4ZIXB7-BlmczUuw.js → kanban-definition-3W4ZIXB7-CPpiiiWk.js} +11 -11
  114. package/dist/{katex-qPqrBHZ8.js → katex-9-9QRhxz.js} +1 -1
  115. package/dist/{label-BCWi-Oqu.js → label-BLqV33b1.js} +2 -2
  116. package/dist/{line-BWRi3U3S.js → line-C5s_12ee.js} +3 -3
  117. package/dist/{linear-DnHwODZa.js → linear-2NnK4cxi.js} +2 -2
  118. package/dist/livescript-BEOngLLc.js +4 -0
  119. package/dist/{loader-BvW0-YWZ.js → loader-Dr8Qem8p.js} +1 -1
  120. package/dist/lua-9-7BhQ4Y.js +4 -0
  121. package/dist/main.js +1631 -10231
  122. package/dist/mathematica-DDa0Pfxm.js +4 -0
  123. package/dist/mbox-iO03mmoE.js +4 -0
  124. package/dist/{mermaid-4DMBBIKO-CG1ECj5W.js → mermaid-4DMBBIKO-B7VQMwJx.js} +1 -1
  125. package/dist/{mermaid-CEbzCxCc.js → mermaid-DO-Daq7u.js} +46 -46
  126. package/dist/{mermaid-parser.core-CleJseNW.js → mermaid-parser.core-DreccfmS.js} +7 -7
  127. package/dist/{mhchem-BwoRNwg_.js → mhchem-yiCCuiEF.js} +1 -1
  128. package/dist/{mindmap-definition-VGOIOE7T-CcSYqYP9.js → mindmap-definition-VGOIOE7T-CC1_Vl0f.js} +13 -13
  129. package/dist/mirc-C9z5LT4X.js +4 -0
  130. package/dist/mllike-jGJbdm_C.js +6 -0
  131. package/dist/modelica-DzF7oIEL.js +4 -0
  132. package/dist/mscgen-DB-u125o.js +6 -0
  133. package/dist/mumps-CRTFHhzh.js +4 -0
  134. package/dist/nsis-C4NPTuox.js +4 -0
  135. package/dist/{nsis-B5K1qoyo.js → nsis-ClF3r5Tr.js} +1 -1
  136. package/dist/ntriples-BCOoGph1.js +4 -0
  137. package/dist/{number-overlay-editor-_GnlYFHC.js → number-overlay-editor-CpKi64Fy.js} +1 -1
  138. package/dist/octave-DTwNlazz.js +4 -0
  139. package/dist/{ordinal-2jIulmcR.js → ordinal-B43ZeR68.js} +1 -1
  140. package/dist/oz-DD38AzSz.js +4 -0
  141. package/dist/{packet-DYOGHKS2-CBxXGWNr.js → packet-DYOGHKS2-CmWtF3uO.js} +1 -1
  142. package/dist/pascal-BohSp9jV.js +4 -0
  143. package/dist/perl-f5OutoPM.js +4 -0
  144. package/dist/{pie-VRWISCQL-Bmdnqjip.js → pie-VRWISCQL-B6u8vus8.js} +1 -1
  145. package/dist/{pieDiagram-ADFJNKIX-DNyLF5H2.js → pieDiagram-ADFJNKIX-Di34MOFQ.js} +19 -19
  146. package/dist/pig-Dv7wSmHb.js +4 -0
  147. package/dist/powershell-rYgjKB39.js +4 -0
  148. package/dist/{process-output-Bza_GK7Q.js → process-output-X8TR20AK.js} +30 -25
  149. package/dist/properties-BFUNLRDN.js +4 -0
  150. package/dist/protobuf-B9QJQPPv.js +4 -0
  151. package/dist/{pug-tjbzJCFk.js → pug-B_rby2yb.js} +1 -1
  152. package/dist/pug-DzvWpaMC.js +4 -0
  153. package/dist/puppet-B_K-n_xK.js +4 -0
  154. package/dist/python-CAiFcaA2.js +4 -0
  155. package/dist/q-cLeFIBLK.js +4 -0
  156. package/dist/{quadrantDiagram-AYHSOK5B-rXwjifrj.js → quadrantDiagram-AYHSOK5B-B9kVk1ny.js} +3 -3
  157. package/dist/r-04Y-Wco3.js +4 -0
  158. package/dist/{radar-ZZBFDIW7-BmCWDffL.js → radar-ZZBFDIW7-XAmXSa8s.js} +1 -1
  159. package/dist/{react-vega-B-rkEqtS.js → react-vega-Cavbrg4l.js} +1 -1
  160. package/dist/{react-vega-k9ODWPlI.js → react-vega-Dh6-UKKe.js} +13 -13
  161. package/dist/{requirementDiagram-UZGBJVZJ-DBdrMVbs.js → requirementDiagram-UZGBJVZJ-BxGfGYEx.js} +13 -13
  162. package/dist/reveal-component-CIs-OouT.js +7444 -0
  163. package/dist/rpm-FUdrIia9.js +5 -0
  164. package/dist/ruby-DMjFXuEW.js +4 -0
  165. package/dist/{sankeyDiagram-TZEHDZUN-CxmzalGv.js → sankeyDiagram-TZEHDZUN-D09PBJ-n.js} +4 -4
  166. package/dist/sas-DzHZxjXK.js +4 -0
  167. package/dist/scheme-DxHd_Rb9.js +4 -0
  168. package/dist/semaphore-CNDGTzkX.js +46 -0
  169. package/dist/{sequenceDiagram-WL72ISMW-CVCDsJ9h.js → sequenceDiagram-WL72ISMW-t_Dpemj0.js} +7 -7
  170. package/dist/shell-C8Kwypgf.js +4 -0
  171. package/dist/sieve-DdyqOKXZ.js +4 -0
  172. package/dist/smalltalk-pB7X1D9y.js +4 -0
  173. package/dist/sparql-NhBO6oOa.js +4 -0
  174. package/dist/{spec-DSIuqd3f.js → spec-hVaaZsY5.js} +4 -4
  175. package/dist/{src-BY0BGg6V.js → src-Bf2iLOlr.js} +1 -1
  176. package/dist/{stateDiagram-FKZM4ZOC-D_2djEhW.js → stateDiagram-FKZM4ZOC-B18gTP_j.js} +16 -16
  177. package/dist/stateDiagram-v2-4FDKWEC3-B6e_t14A.js +29 -0
  178. package/dist/{step-DGAGWg3y.js → step-CWipAYTY.js} +1 -1
  179. package/dist/{strings-B_FOH6eV.js → strings-BiIhGaI8.js} +4 -4
  180. package/dist/style.css +1 -1
  181. package/dist/stylus-SfWSnzPv.js +4 -0
  182. package/dist/swift-jRPdq2zR.js +4 -0
  183. package/dist/{swiper-component-KkEVUDd3.js → swiper-component-DlD2GU2g.js} +2 -2
  184. package/dist/tcl-_hpTHGX3.js +4 -0
  185. package/dist/textile-C9h8slqH.js +4 -0
  186. package/dist/{time-CMdrp3hw.js → time-C1SGcFMH.js} +2 -2
  187. package/dist/{timeline-definition-IT6M3QCI-E4NzxCs3.js → timeline-definition-IT6M3QCI-DJnh1ks5.js} +3 -3
  188. package/dist/{toDate-CHtl9vts.js → toDate-CIpC_34u.js} +33 -20
  189. package/dist/toml-DWvtinD4.js +4 -0
  190. package/dist/{tooltip-B0mtKTXm.js → tooltip-DRaMBu06.js} +3 -3
  191. package/dist/{treemap-GDKQZRPO-CoKHPxa7.js → treemap-GDKQZRPO-Du95DV6u.js} +1 -1
  192. package/dist/troff-Dwo_A0y7.js +4 -0
  193. package/dist/ttcn-V--CPFKq.js +4 -0
  194. package/dist/ttcn-cfg-CPSMchTG.js +4 -0
  195. package/dist/turtle-B4rPGBWu.js +4 -0
  196. package/dist/{types-DBtDeUKD.js → types-Dzuoc3LN.js} +1 -1
  197. package/dist/{useAsyncData-B6hCGywC.js → useAsyncData-C56Khv_R.js} +1 -1
  198. package/dist/{useDateFormatter-B3mCQMP3.js → useDateFormatter-B_9k85Ex.js} +2 -2
  199. package/dist/{useDeepCompareMemoize-CmwDuYUH.js → useDeepCompareMemoize-Dt98v2ua.js} +1 -1
  200. package/dist/{useIframeCapabilities-DbdLoEDm.js → useIframeCapabilities-BkYHTrss.js} +1 -1
  201. package/dist/{useLifecycle-CjMjllqy.js → useLifecycle-BF6-z62y.js} +3 -3
  202. package/dist/{useTheme-CByZUW0p.js → useTheme-DykuNHR2.js} +2 -2
  203. package/dist/vb-DaMBBd4j.js +4 -0
  204. package/dist/vbscript-BMJQqcE2.js +4 -0
  205. package/dist/{vega-component-CC8TqWWV.js → vega-component-cSdqoAxe.js} +26 -24
  206. package/dist/velocity-CGq2QRq2.js +4 -0
  207. package/dist/verilog-CUNo8F5u.js +4 -0
  208. package/dist/vhdl-CCzA0msW.js +4 -0
  209. package/dist/webidl-CqIMDIBL.js +4 -0
  210. package/dist/xquery-XC5Kbr-1.js +4 -0
  211. package/dist/{xychartDiagram-PRI3JC2R-CuxTvjw5.js → xychartDiagram-PRI3JC2R-Dk2d_bX0.js} +10 -10
  212. package/dist/yacas-CGOv7Dzy.js +4 -0
  213. package/dist/z80-CXhVmi-f.js +4 -0
  214. package/dist/{zod-BxdsqRPd.js → zod-BWkcDORu.js} +1 -1
  215. package/package.json +3 -3
  216. package/src/components/chat/chat-components.tsx +47 -0
  217. package/src/components/chat/chat-display.tsx +41 -7
  218. package/src/components/chat/chat-panel.tsx +37 -10
  219. package/src/components/chat/chat-utils.ts +42 -20
  220. package/src/components/chat/reasoning-accordion.tsx +14 -3
  221. package/src/components/chat/tool-call/shared.ts +13 -0
  222. package/src/components/chat/tool-call/tool-approval-card.tsx +62 -0
  223. package/src/components/chat/tool-call/tool-args.tsx +26 -0
  224. package/src/components/chat/tool-call/tool-call-view.tsx +99 -0
  225. package/src/components/chat/tool-call/tool-error-card.tsx +81 -0
  226. package/src/components/chat/tool-call/tool-history-row.tsx +153 -0
  227. package/src/components/chat/tool-call/tool-result.tsx +101 -0
  228. package/src/components/data-table/__tests__/column-header.test.ts +3 -1
  229. package/src/components/data-table/__tests__/column-header.test.tsx +308 -0
  230. package/src/components/data-table/__tests__/filter-by-values-picker.test.tsx +112 -0
  231. package/src/components/data-table/__tests__/filter-pill-editor.test.tsx +261 -0
  232. package/src/components/data-table/__tests__/filters.test.ts +196 -49
  233. package/src/components/data-table/charts/components/form-fields.tsx +1 -0
  234. package/src/components/data-table/column-header.tsx +349 -170
  235. package/src/components/data-table/date-filter-inputs.tsx +325 -0
  236. package/src/components/data-table/filter-by-values-picker.tsx +70 -9
  237. package/src/components/data-table/filter-pill-editor.tsx +410 -156
  238. package/src/components/data-table/filter-pills.tsx +69 -54
  239. package/src/components/data-table/filters.ts +218 -101
  240. package/src/components/data-table/header-items.tsx +8 -1
  241. package/src/components/data-table/operator-labels.ts +25 -0
  242. package/src/components/data-table/regex-input.tsx +61 -0
  243. package/src/components/dependency-graph/minimap-content.tsx +14 -3
  244. package/src/components/editor/actions/pair-with-agent-modal.tsx +140 -49
  245. package/src/components/editor/actions/useNotebookActions.tsx +3 -1
  246. package/src/components/editor/app-container.tsx +7 -1
  247. package/src/components/editor/chrome/panels/context-aware-panel/context-aware-panel.tsx +10 -2
  248. package/src/components/editor/chrome/wrapper/app-chrome.tsx +1 -0
  249. package/src/components/editor/chrome/wrapper/footer-items/backend-status.tsx +1 -1
  250. package/src/components/editor/chrome/wrapper/footer.tsx +4 -1
  251. package/src/components/editor/chrome/wrapper/panels.tsx +4 -1
  252. package/src/components/editor/chrome/wrapper/sidebar.tsx +4 -1
  253. package/src/components/editor/controls/Controls.tsx +11 -3
  254. package/src/components/editor/file-tree/file-explorer.tsx +12 -2
  255. package/src/components/editor/file-tree/requesting-tree.tsx +27 -25
  256. package/src/components/editor/file-tree/upload.tsx +23 -24
  257. package/src/components/editor/header/__tests__/status.test.tsx +108 -0
  258. package/src/components/editor/header/status.tsx +44 -10
  259. package/src/components/editor/navigation/__tests__/clipboard.test.ts +106 -0
  260. package/src/components/editor/navigation/__tests__/navigation.test.ts +70 -0
  261. package/src/components/editor/navigation/clipboard.ts +99 -25
  262. package/src/components/editor/navigation/navigation.ts +15 -1
  263. package/src/components/editor/notebook-cell.tsx +3 -0
  264. package/src/components/editor/renderers/slides-layout/__tests__/compute-slide-cells.test.ts +5 -4
  265. package/src/components/editor/renderers/slides-layout/__tests__/plugin.test.ts +55 -15
  266. package/src/components/editor/renderers/slides-layout/plugin.tsx +8 -25
  267. package/src/components/editor/renderers/slides-layout/slides-layout.tsx +18 -5
  268. package/src/components/editor/renderers/slides-layout/types.ts +40 -31
  269. package/src/components/home/components.tsx +6 -0
  270. package/src/components/pages/run-page.tsx +4 -1
  271. package/src/components/slides/__tests__/slide-notes.test.ts +131 -0
  272. package/src/components/slides/reveal-component.tsx +242 -147
  273. package/src/components/slides/slide-notes-editor.tsx +127 -0
  274. package/src/components/slides/slide-notes.ts +64 -0
  275. package/src/components/slides/slides.css +14 -0
  276. package/src/components/ui/combobox.tsx +24 -5
  277. package/src/components/ui/number-field.tsx +2 -0
  278. package/src/core/ai/tools/__tests__/registry.test.ts +10 -12
  279. package/src/core/ai/tools/registry.ts +9 -5
  280. package/src/core/cells/__tests__/cells.test.ts +187 -0
  281. package/src/core/cells/__tests__/pending-cut-service.test.tsx +123 -0
  282. package/src/core/cells/cells.ts +102 -17
  283. package/src/core/cells/document-changes.ts +6 -1
  284. package/src/core/cells/pending-cut-service.ts +55 -0
  285. package/src/core/cells/utils.ts +11 -0
  286. package/src/core/codemirror/cells/extensions.ts +10 -0
  287. package/src/core/codemirror/go-to-definition/__tests__/commands.test.ts +152 -0
  288. package/src/core/codemirror/go-to-definition/__tests__/utils.test.ts +99 -0
  289. package/src/core/codemirror/go-to-definition/commands.ts +382 -22
  290. package/src/core/codemirror/go-to-definition/utils.ts +23 -5
  291. package/src/core/codemirror/markdown/__tests__/commands.test.ts +3 -3
  292. package/src/core/codemirror/markdown/commands.ts +1 -2
  293. package/src/core/edit-app.tsx +3 -2
  294. package/src/core/hotkeys/hotkeys.ts +5 -0
  295. package/src/core/islands/worker/worker.tsx +3 -2
  296. package/src/core/network/requests-network.ts +21 -3
  297. package/src/core/network/types.ts +12 -1
  298. package/src/core/run-app.tsx +2 -1
  299. package/src/core/runtime/__tests__/runtime.test.ts +38 -17
  300. package/src/core/runtime/runtime.ts +57 -34
  301. package/src/core/wasm/__tests__/utils.test.ts +34 -0
  302. package/src/core/wasm/bridge.ts +14 -1
  303. package/src/core/wasm/utils.ts +14 -0
  304. package/src/core/wasm/worker/bootstrap.ts +3 -2
  305. package/src/core/wasm/worker/worker.ts +3 -2
  306. package/src/core/websocket/__tests__/useMarimoKernelConnection.hook.test.tsx +156 -0
  307. package/src/core/websocket/__tests__/useMarimoKernelConnection.test.ts +101 -0
  308. package/src/core/websocket/transports/__tests__/ws.test.ts +125 -0
  309. package/src/core/websocket/transports/basic.ts +1 -1
  310. package/src/core/websocket/transports/ws.ts +96 -0
  311. package/src/core/websocket/useMarimoKernelConnection.tsx +133 -54
  312. package/src/core/websocket/useWebSocket.tsx +3 -15
  313. package/src/css/app/Cell.css +10 -0
  314. package/src/plugins/core/__test__/sanitize.test.ts +30 -0
  315. package/src/plugins/impl/DropdownPlugin.tsx +12 -1
  316. package/src/plugins/impl/MultiselectPlugin.tsx +4 -0
  317. package/src/plugins/impl/SearchableSelect.tsx +11 -1
  318. package/src/plugins/impl/TabsPlugin.tsx +35 -7
  319. package/src/plugins/impl/__tests__/DropdownPlugin.test.tsx +56 -0
  320. package/src/plugins/impl/__tests__/TabsPlugin.test.tsx +154 -0
  321. package/src/plugins/impl/data-frames/forms/__tests__/__snapshots__/form.test.tsx.snap +48 -36
  322. package/src/plugins/impl/data-frames/schema.ts +4 -1
  323. package/src/plugins/impl/vega/resolve-data.ts +8 -1
  324. package/src/utils/__tests__/id-tree.test.ts +71 -0
  325. package/src/utils/__tests__/semaphore.test.ts +218 -0
  326. package/src/utils/fileToBase64.ts +8 -7
  327. package/src/utils/id-tree.tsx +89 -0
  328. package/src/utils/semaphore.ts +88 -0
  329. package/dist/apl-BKoVld9y.js +0 -4
  330. package/dist/asciiarmor-DQrKIjoo.js +0 -4
  331. package/dist/asn1-BZvnj0dq.js +0 -4
  332. package/dist/assets/__vite-browser-external-rrUYDKRl.js +0 -1
  333. package/dist/assets/worker-Bfy15ViQ.js +0 -73
  334. package/dist/brainfuck-D558nlUv.js +0 -4
  335. package/dist/classDiagram-2ON5EDUG-CBHMR6ZU.js +0 -30
  336. package/dist/classDiagram-v2-WZHVMYZB-BsUtUGM_.js +0 -30
  337. package/dist/clojure-Cq8mTSrE.js +0 -4
  338. package/dist/cmake-D8HCovWK.js +0 -4
  339. package/dist/cobol-UolN-9iU.js +0 -4
  340. package/dist/coffeescript-VdNuWrt5.js +0 -4
  341. package/dist/commonlisp-ALX7fpDc.js +0 -4
  342. package/dist/crystal-PbyO9Q_s.js +0 -4
  343. package/dist/css-DFklJkr_.js +0 -4
  344. package/dist/cypher-BifNeYlv.js +0 -4
  345. package/dist/d-BA-JP4PJ.js +0 -4
  346. package/dist/diff-CtkDpav4.js +0 -4
  347. package/dist/dist-BuBwsFva.js +0 -5
  348. package/dist/dist-BzmEQ9u7.js +0 -5
  349. package/dist/dist-Cih01ssx.js +0 -5
  350. package/dist/dist-CqfONiY9.js +0 -5
  351. package/dist/dist-D0iD0Fi9.js +0 -5
  352. package/dist/dist-DtNLXm8d.js +0 -5
  353. package/dist/dtd-DW3_UFEG.js +0 -4
  354. package/dist/dylan-pDhodO2N.js +0 -4
  355. package/dist/ecl-BJT8-YD7.js +0 -4
  356. package/dist/eiffel-Dmns-9vS.js +0 -4
  357. package/dist/elm-Da4sO4Bz.js +0 -4
  358. package/dist/erlang-C-zBsDi7.js +0 -4
  359. package/dist/factor-4xPWlWB5.js +0 -4
  360. package/dist/forth-l-c75zSd.js +0 -4
  361. package/dist/fortran-DIujSODW.js +0 -4
  362. package/dist/gas-CXnG5g_b.js +0 -4
  363. package/dist/gherkin-VPeqd4-X.js +0 -4
  364. package/dist/groovy-CphhZQgg.js +0 -4
  365. package/dist/haskell-CCvlS5Iq.js +0 -4
  366. package/dist/haxe-C_bi66fP.js +0 -5
  367. package/dist/idl-1DcP4Dm8.js +0 -4
  368. package/dist/javascript-DUIGhBvO.js +0 -4
  369. package/dist/julia-Cs2G4PQi.js +0 -4
  370. package/dist/livescript-DMtVFaAN.js +0 -4
  371. package/dist/lua-BAoLtdJg.js +0 -4
  372. package/dist/mathematica-C_NoFtbo.js +0 -4
  373. package/dist/mbox-DcFJFYrH.js +0 -4
  374. package/dist/mirc-71dccf_u.js +0 -4
  375. package/dist/mllike-CWcOFVDq.js +0 -6
  376. package/dist/modelica-Ape2VXxx.js +0 -4
  377. package/dist/mscgen-Cc6TwbSN.js +0 -6
  378. package/dist/mumps-h-ZbdkJ9.js +0 -4
  379. package/dist/nsis-C0p3m7JW.js +0 -4
  380. package/dist/ntriples-c9lEeT5w.js +0 -4
  381. package/dist/octave-DzEgB_74.js +0 -4
  382. package/dist/oz-CAxvHkyQ.js +0 -4
  383. package/dist/pascal-BJzu1sgP.js +0 -4
  384. package/dist/perl--IrOzZ2Z.js +0 -4
  385. package/dist/pig-CiBKKNhC.js +0 -4
  386. package/dist/powershell-KY0j6Qop.js +0 -4
  387. package/dist/properties-BW8q3ziV.js +0 -4
  388. package/dist/protobuf-BGaeuTGV.js +0 -4
  389. package/dist/pug-DjOKK-4J.js +0 -4
  390. package/dist/puppet-DWm2o6zX.js +0 -4
  391. package/dist/python-Bp2gezZy.js +0 -4
  392. package/dist/q-DljPshos.js +0 -4
  393. package/dist/r-BajPMnEu.js +0 -4
  394. package/dist/reveal-component-BCKa3sr-.js +0 -4863
  395. package/dist/rpm-BKx-ZZ62.js +0 -5
  396. package/dist/ruby-DJq_HNKc.js +0 -4
  397. package/dist/sas-WANvpcOU.js +0 -4
  398. package/dist/scheme-CliBbhGF.js +0 -4
  399. package/dist/shell-BwhrNUvM.js +0 -4
  400. package/dist/sieve-BIVePvMp.js +0 -4
  401. package/dist/smalltalk-D6G48JmY.js +0 -4
  402. package/dist/sparql-jjc3BmEP.js +0 -4
  403. package/dist/stateDiagram-v2-4FDKWEC3-Cv9Av10H.js +0 -29
  404. package/dist/stylus-WPBPQ4PE.js +0 -4
  405. package/dist/swift-O1Qy6iCm.js +0 -4
  406. package/dist/tcl-BAFdhvsi.js +0 -4
  407. package/dist/textile-DFuzhNLG.js +0 -4
  408. package/dist/toml-DRSTeely.js +0 -4
  409. package/dist/troff-B_ZjwBW0.js +0 -4
  410. package/dist/ttcn-CAyiB3ic.js +0 -4
  411. package/dist/ttcn-cfg-BS5_BGBJ.js +0 -4
  412. package/dist/turtle-CUBEDy3E.js +0 -4
  413. package/dist/vb-DY9S6-U2.js +0 -4
  414. package/dist/vbscript-gaHC39Jq.js +0 -4
  415. package/dist/velocity-TfCOtJZ_.js +0 -4
  416. package/dist/verilog-c2JOX8mv.js +0 -4
  417. package/dist/vhdl-dHBirRiO.js +0 -4
  418. package/dist/webidl-Bauj-i07.js +0 -4
  419. package/dist/xquery-CtaEAOt8.js +0 -4
  420. package/dist/yacas-BZ85agQP.js +0 -4
  421. package/dist/z80-hCgR-L4U.js +0 -4
  422. package/src/components/chat/tool-call-accordion.tsx +0 -247
  423. /package/dist/{ImageComparisonComponent-DaocPIse.js → ImageComparisonComponent-CNHIsPDj.js} +0 -0
  424. /package/dist/{Plot-PIeIvFnD.js → Plot-4wn-lMVn.js} +0 -0
  425. /package/dist/{apl-Dt8GMXYg.js → apl-BCgCq9iM.js} +0 -0
  426. /package/dist/{array-B-MVxRIF.js → array-tvvEqPy7.js} +0 -0
  427. /package/dist/{asciiarmor-CitDQ85h.js → asciiarmor-BtqU-KJQ.js} +0 -0
  428. /package/dist/{asn1-abrf9SMK.js → asn1-Dmb-dTMx.js} +0 -0
  429. /package/dist/{asterisk-BUZwqih-.js → asterisk-DaVJJDnV.js} +0 -0
  430. /package/dist/{brainfuck-BL-Boof0.js → brainfuck-C1HoZKlE.js} +0 -0
  431. /package/dist/{chunk-4F5CHEZ2-C6tO9vjs.js → chunk-4F5CHEZ2-BZq7Kom7.js} +0 -0
  432. /package/dist/{chunk-B2363JML-Ds8wZXyP.js → chunk-B2363JML-D9-XOau1.js} +0 -0
  433. /package/dist/{chunk-DR5Q36YT-CP69aZS_.js → chunk-DR5Q36YT-BflwErH1.js} +0 -0
  434. /package/dist/{chunk-FRFDVMJY-BgQv1HBE.js → chunk-FRFDVMJY-BSBUAX7r.js} +0 -0
  435. /package/dist/{chunk-PL6DKKU2-DHfTUHy8.js → chunk-PL6DKKU2-B0MTXvyc.js} +0 -0
  436. /package/dist/{chunk-SJTYNZTY-Diciw4sx.js → chunk-SJTYNZTY-CEG4F0pB.js} +0 -0
  437. /package/dist/{chunk-TQ3KTPDO-CQfP9npd.js → chunk-TQ3KTPDO-DiCtqVSi.js} +0 -0
  438. /package/dist/{chunk-UMXZTB3W-MSKeGL7W.js → chunk-UMXZTB3W-97iS1iEl.js} +0 -0
  439. /package/dist/{click-outside-container-BZgN7xS_.js → click-outside-container-BDd67_1U.js} +0 -0
  440. /package/dist/{clike-RWg7anhx.js → clike-CdT0yHjt.js} +0 -0
  441. /package/dist/{clojure-DaojKHow.js → clojure-CdyrCpUv.js} +0 -0
  442. /package/dist/{cmake-DN-_v0XE.js → cmake-BFlPxym7.js} +0 -0
  443. /package/dist/{cobol-C3VpMyux.js → cobol-CcJXewp8.js} +0 -0
  444. /package/dist/{coffeescript-DIkz3Tbt.js → coffeescript-DnKuIKRo.js} +0 -0
  445. /package/dist/{colors-Cn2p_FA3.js → colors-CQAOa8cK.js} +0 -0
  446. /package/dist/{common-keywords-hbLeU7VU.js → common-keywords-FBrXPTcz.js} +0 -0
  447. /package/dist/{commonlisp-CB1boOiP.js → commonlisp-B-kok83Z.js} +0 -0
  448. /package/dist/{crystal-DI2oCml6.js → crystal-FYRYjI1I.js} +0 -0
  449. /package/dist/{css-BdEVwQDV.js → css-B45lc2V3.js} +0 -0
  450. /package/dist/{cypher-BNHToqxU.js → cypher-DZMLyVY_.js} +0 -0
  451. /package/dist/{cytoscape.esm-WbbDoCfu.js → cytoscape.esm-ayF70frT.js} +0 -0
  452. /package/dist/{d-D7we7I1b.js → d-x-VVT4o9.js} +0 -0
  453. /package/dist/{diff-Cia6fzjN.js → diff-Dxe2mpXk.js} +0 -0
  454. /package/dist/{dist-BK-3fF4P.js → dist-B4LJpMEg.js} +0 -0
  455. /package/dist/{dist-CxdUraQr.js → dist-B507mf_I.js} +0 -0
  456. /package/dist/{dist-C89sHDXk.js → dist-BGdYVvOu.js} +0 -0
  457. /package/dist/{dist-DquyVv5H.js → dist-BNyrZfqT.js} +0 -0
  458. /package/dist/{dist-Zn0KNbo9.js → dist-Bc5pmZIw.js} +0 -0
  459. /package/dist/{dist-C-J0pt5p.js → dist-BvCfQQQE.js} +0 -0
  460. /package/dist/{dist-D9r7Cmw7.js → dist-C2ej4eOH.js} +0 -0
  461. /package/dist/{dist-HVuryI1a.js → dist-C34oIrQ9.js} +0 -0
  462. /package/dist/{dist-CGLzXdrt.js → dist-CDFZi-QD.js} +0 -0
  463. /package/dist/{dist-C9fmTOin.js → dist-CYEylvZA.js} +0 -0
  464. /package/dist/{dist-DadjmS-4.js → dist-DJ6zJQZ4.js} +0 -0
  465. /package/dist/{dist-CtCY55Jf.js → dist-Dh3wkoyH.js} +0 -0
  466. /package/dist/{dist-C474qFoq.js → dist-Dhk6FMb0.js} +0 -0
  467. /package/dist/{dist-DZjQ_MBo.js → dist-KnujRhFL.js} +0 -0
  468. /package/dist/{dist-CinA9Enb.js → dist-WdPUFc56.js} +0 -0
  469. /package/dist/{dist-DBLeRrPp.js → dist-t_qL7eB8.js} +0 -0
  470. /package/dist/{dist-CyFFzJTb.js → dist-usPCDYx8.js} +0 -0
  471. /package/dist/{dtd-H4Hubdwp.js → dtd-C9VM_Wfu.js} +0 -0
  472. /package/dist/{duckdb-keywords-CZ_ZTscu.js → duckdb-keywords-CvJhR_Yd.js} +0 -0
  473. /package/dist/{dylan-fVO6rnq3.js → dylan-DTSnEIFO.js} +0 -0
  474. /package/dist/{ebnf-WEXPLEWb.js → ebnf-2D4Ctp3y.js} +0 -0
  475. /package/dist/{ecl-B94VPjNR.js → ecl-N04ptnRK.js} +0 -0
  476. /package/dist/{eiffel-C_R6TusS.js → eiffel-Dd8rpqr_.js} +0 -0
  477. /package/dist/{elm-DzCHbO2g.js → elm-GT2E866W.js} +0 -0
  478. /package/dist/{erlang-BGNkx6JU.js → erlang-Cf0Bp5pY.js} +0 -0
  479. /package/dist/{esm-Bb_hbWan.js → esm-BaaaPNGl.js} +0 -0
  480. /package/dist/{fcl-B_Gv5Jfx.js → fcl-Ccj8Z5Xd.js} +0 -0
  481. /package/dist/{forth-Bybw0cJ7.js → forth-wd_XzGTg.js} +0 -0
  482. /package/dist/{fortran-C6PoCLkI.js → fortran-DcwUTZFe.js} +0 -0
  483. /package/dist/{gas-BBlhenj4.js → gas-DeALIER3.js} +0 -0
  484. /package/dist/{gherkin-NXtNG85X.js → gherkin-CKTqaJNX.js} +0 -0
  485. /package/dist/{groovy-BoFYK9xM.js → groovy-Bwdp_d8D.js} +0 -0
  486. /package/dist/{haskell-BtBdvQ1n.js → haskell-DCdCcPLK.js} +0 -0
  487. /package/dist/{haxe-D--o6dr0.js → haxe-DAyktQWJ.js} +0 -0
  488. /package/dist/{http-Dc2fv19V.js → http-_DVAYWoR.js} +0 -0
  489. /package/dist/{idl-AqTq5l7e.js → idl-CBuZiRYu.js} +0 -0
  490. /package/dist/{init-D-g0ONX1.js → init-uv0kkh4g.js} +0 -0
  491. /package/dist/{javascript-DvwNVye9.js → javascript-DzigE11c.js} +0 -0
  492. /package/dist/{julia-DoKiagZC.js → julia-PwfB-0Cm.js} +0 -0
  493. /package/dist/{katex-B7pMJpE0.js → katex-C_XRmjAP.js} +0 -0
  494. /package/dist/{livescript-DxBZMiWB.js → livescript-BJLz1EbT.js} +0 -0
  495. /package/dist/{lua-DmS_0NTu.js → lua-ZC-XC2jf.js} +0 -0
  496. /package/dist/{math-BYK36kWZ.js → math-DFcdCCU8.js} +0 -0
  497. /package/dist/{mathematica-ChlDFeIC.js → mathematica-DCYMx6qB.js} +0 -0
  498. /package/dist/{mbox-CguZuODr.js → mbox-OxMK_9XI.js} +0 -0
  499. /package/dist/{mirc-CFtY8dqz.js → mirc-nJVyhA0H.js} +0 -0
  500. /package/dist/{mllike-C0EJrEOk.js → mllike-DRO89bsU.js} +0 -0
  501. /package/dist/{modelica-C1kO1nfS.js → modelica-Don3E6ZD.js} +0 -0
  502. /package/dist/{mscgen-DEYdr7AY.js → mscgen-DJfqD3bN.js} +0 -0
  503. /package/dist/{mumps-B3NVJs2V.js → mumps-SjGTvDYL.js} +0 -0
  504. /package/dist/{nginx-ComVAAGN.js → nginx-DasThI7R.js} +0 -0
  505. /package/dist/{node-sql-parser-DNGGJ-Rw.js → node-sql-parser-B8nBD36q.js} +0 -0
  506. /package/dist/{ntriples-DHol9X9H.js → ntriples-CNBKRl3I.js} +0 -0
  507. /package/dist/{octave-CYGz0bfo.js → octave-DdeVHNlx.js} +0 -0
  508. /package/dist/{oz-kPxb2ni5.js → oz-CcKSoNvN.js} +0 -0
  509. /package/dist/{pascal-bZ0yrJKy.js → pascal-6leftwNj.js} +0 -0
  510. /package/dist/{path-Du6n3sOU.js → path-BGaWgPKg.js} +0 -0
  511. /package/dist/{perl-z4hvqyqz.js → perl-BhJIwWzN.js} +0 -0
  512. /package/dist/{pig-DZO8QDF9.js → pig-r-xDHqRf.js} +0 -0
  513. /package/dist/{powershell-BSuaDQEC.js → powershell-D-BELeNi.js} +0 -0
  514. /package/dist/{properties-BXhGLlIx.js → properties-CnuDhbll.js} +0 -0
  515. /package/dist/{protobuf-DM6iybWV.js → protobuf-CO8RBhvX.js} +0 -0
  516. /package/dist/{puppet-Bn05sQT8.js → puppet-NmXHjLy8.js} +0 -0
  517. /package/dist/{python-Cvnhm0g7.js → python-DAQXi720.js} +0 -0
  518. /package/dist/{q-B9V8hzex.js → q-DlikXfV0.js} +0 -0
  519. /package/dist/{r-Cf0gFqmq.js → r-CuohilwT.js} +0 -0
  520. /package/dist/{rpm-D-LMkTV1.js → rpm-0Pjwp0Pb.js} +0 -0
  521. /package/dist/{ruby-DeuPikpK.js → ruby-Dq8NJTDG.js} +0 -0
  522. /package/dist/{sas-C9tjgAo9.js → sas-CuwonyVP.js} +0 -0
  523. /package/dist/{scheme-D1_bUF0G.js → scheme-CYU-RRIf.js} +0 -0
  524. /package/dist/{shell-CJBmnks3.js → shell-COPmX2qE.js} +0 -0
  525. /package/dist/{sieve-1fSV75CF.js → sieve-B_3zyLne.js} +0 -0
  526. /package/dist/{simple-mode-B90Wdavj.js → simple-mode-DSBniks8.js} +0 -0
  527. /package/dist/{smalltalk-sZNPD0HO.js → smalltalk-DRft7iPv.js} +0 -0
  528. /package/dist/{solr-DTkyqJ-Z.js → solr-RZ9uTl59.js} +0 -0
  529. /package/dist/{sparql-oHc1nm77.js → sparql-CN6qj55H.js} +0 -0
  530. /package/dist/{spreadsheet-CER0raqY.js → spreadsheet-BNNUNXA2.js} +0 -0
  531. /package/dist/{sql-ByOoEONQ.js → sql-B4x8IkwU.js} +0 -0
  532. /package/dist/{stylus-KzkX6zRB.js → stylus-Bn_ZjOQ3.js} +0 -0
  533. /package/dist/{swift-DqVxZvKo.js → swift-BLUJhMbz.js} +0 -0
  534. /package/dist/{tcl-BtWSwXfA.js → tcl-C86fxecl.js} +0 -0
  535. /package/dist/{textile-CWDbn9Ql.js → textile-DmHh2rsK.js} +0 -0
  536. /package/dist/{tiddlywiki-Cr9xyOY1.js → tiddlywiki-DI0mF2WJ.js} +0 -0
  537. /package/dist/{tiki-D5JONyfZ.js → tiki-2HU6XLLn.js} +0 -0
  538. /package/dist/{timer-D7JVdX9U.js → timer-YZl28NYN.js} +0 -0
  539. /package/dist/{toml-BfehlgmL.js → toml-GWANRNAD.js} +0 -0
  540. /package/dist/{treemap-qFGzn7xk.js → treemap-D-ka1hvx.js} +0 -0
  541. /package/dist/{troff-BZBk6AAu.js → troff-BHTsomIy.js} +0 -0
  542. /package/dist/{ttcn-DVwvXg0_.js → ttcn-DQuhn5Mn.js} +0 -0
  543. /package/dist/{ttcn-cfg-gjbVLf1L.js → ttcn-cfg-HjFYtdB-.js} +0 -0
  544. /package/dist/{turtle-CgxKXorV.js → turtle-nCay33Nv.js} +0 -0
  545. /package/dist/{vb-B9kSwTdM.js → vb-BG-XlqqJ.js} +0 -0
  546. /package/dist/{vbscript-DrUKSCdb.js → vbscript-B6vyW0-D.js} +0 -0
  547. /package/dist/{velocity-AlMYTnMy.js → velocity-CWegueqO.js} +0 -0
  548. /package/dist/{verilog-DLUaM05j.js → verilog-CzSQm4cG.js} +0 -0
  549. /package/dist/{vhdl-DUJOtSmO.js → vhdl-DqnNVL7r.js} +0 -0
  550. /package/dist/{webidl-CQp4aHk_.js → webidl-DXEUpDWH.js} +0 -0
  551. /package/dist/{xquery-IxkjlwOD.js → xquery-Ba_NB5bD.js} +0 -0
  552. /package/dist/{yacas-Bnctn5w8.js → yacas-HKQU6hyk.js} +0 -0
  553. /package/dist/{z80-DrFwhx53.js → z80-CXkHXLdj.js} +0 -0
@@ -275,14 +275,14 @@ describe("RuntimeManager", () => {
275
275
  });
276
276
  });
277
277
 
278
- describe("isHealthy", () => {
278
+ describe("probeHealth", () => {
279
279
  it("should return true for successful health check", async () => {
280
280
  global.fetch = vi.fn().mockResolvedValue({
281
281
  ok: true,
282
282
  });
283
283
 
284
284
  const runtime = new RuntimeManager(mockConfig);
285
- const result = await runtime.isHealthy();
285
+ const result = await runtime.probeHealth();
286
286
 
287
287
  expect(result).toBe(true);
288
288
  expect(fetch).toHaveBeenCalledWith("https://example.com/health");
@@ -294,7 +294,7 @@ describe("RuntimeManager", () => {
294
294
  });
295
295
 
296
296
  const runtime = new RuntimeManager(mockConfig);
297
- const result = await runtime.isHealthy();
297
+ const result = await runtime.probeHealth();
298
298
 
299
299
  expect(result).toBe(false);
300
300
  });
@@ -304,11 +304,32 @@ describe("RuntimeManager", () => {
304
304
  global.fetch = vi.fn().mockRejectedValue(error);
305
305
 
306
306
  const runtime = new RuntimeManager(mockConfig);
307
- const result = await runtime.isHealthy();
307
+ const result = await runtime.probeHealth();
308
308
 
309
309
  expect(result).toBe(false);
310
310
  });
311
311
 
312
+ it("should not mutate config.url on redirect", async () => {
313
+ global.fetch = vi.fn().mockResolvedValue({
314
+ ok: true,
315
+ redirected: true,
316
+ url: "https://sandbox.example.com/health?some_value=abc123",
317
+ });
318
+
319
+ const runtime = new RuntimeManager(
320
+ {
321
+ ...mockConfig,
322
+ url: "https://backend.example.com/lazy?some_value=abc123",
323
+ },
324
+ true,
325
+ );
326
+ const result = await runtime.probeHealth();
327
+ expect(result).toBe(true);
328
+ expect(runtime.httpURL.hostname).toBe("backend.example.com");
329
+ });
330
+ });
331
+
332
+ describe("reconcileFromHealth", () => {
312
333
  it("should update config.url on redirect, stripping /health from pathname", async () => {
313
334
  global.fetch = vi.fn().mockResolvedValue({
314
335
  ok: true,
@@ -323,7 +344,7 @@ describe("RuntimeManager", () => {
323
344
  },
324
345
  true, // lazy — don't call init() in constructor
325
346
  );
326
- const result = await runtime.isHealthy();
347
+ const result = await runtime.reconcileFromHealth();
327
348
 
328
349
  expect(result).toBe(true);
329
350
  // Should strip /health from pathname but preserve query params
@@ -342,7 +363,7 @@ describe("RuntimeManager", () => {
342
363
  it("should resolve immediately if healthy", async () => {
343
364
  const runtime = new RuntimeManager(mockConfig, true);
344
365
 
345
- vi.spyOn(runtime, "isHealthy").mockResolvedValue(true);
366
+ vi.spyOn(runtime, "reconcileFromHealth").mockResolvedValue(true);
346
367
  runtime.init();
347
368
 
348
369
  await expect(runtime.waitForHealthy()).resolves.toBeUndefined();
@@ -351,7 +372,7 @@ describe("RuntimeManager", () => {
351
372
  it("should retry and eventually succeed", async () => {
352
373
  const runtime = new RuntimeManager(mockConfig, true);
353
374
  const healthySpy = vi
354
- .spyOn(runtime, "isHealthy")
375
+ .spyOn(runtime, "reconcileFromHealth")
355
376
  .mockResolvedValueOnce(false)
356
377
  .mockResolvedValueOnce(false)
357
378
  .mockResolvedValueOnce(true);
@@ -364,7 +385,7 @@ describe("RuntimeManager", () => {
364
385
 
365
386
  it("should throw after max retries", async () => {
366
387
  const runtime = new RuntimeManager(mockConfig, true);
367
- vi.spyOn(runtime, "isHealthy").mockResolvedValue(false);
388
+ vi.spyOn(runtime, "reconcileFromHealth").mockResolvedValue(false);
368
389
  runtime.init({ disableRetryDelay: true });
369
390
 
370
391
  await expect(runtime.waitForHealthy()).rejects.toThrow(
@@ -431,7 +452,7 @@ describe("RuntimeManager", () => {
431
452
  // Mock failed health check
432
453
  global.fetch = vi.fn().mockResolvedValue({ ok: false });
433
454
 
434
- await runtime.isHealthy();
455
+ await runtime.reconcileFromHealth();
435
456
 
436
457
  baseElement = document.querySelector("base");
437
458
  expect(baseElement).toBeNull();
@@ -443,7 +464,7 @@ describe("RuntimeManager", () => {
443
464
  // Mock successful health check
444
465
  global.fetch = vi.fn().mockResolvedValue({ ok: true });
445
466
 
446
- await runtime.isHealthy();
467
+ await runtime.reconcileFromHealth();
447
468
 
448
469
  const baseElement = document.querySelector("base");
449
470
  expect(baseElement).toBeTruthy();
@@ -461,7 +482,7 @@ describe("RuntimeManager", () => {
461
482
  // Mock successful health check
462
483
  global.fetch = vi.fn().mockResolvedValue({ ok: true });
463
484
 
464
- await runtime.isHealthy();
485
+ await runtime.reconcileFromHealth();
465
486
 
466
487
  const baseElement = document.querySelector("base");
467
488
  expect(baseElement).toBe(existingBase); // Should be the same element
@@ -483,7 +504,7 @@ describe("RuntimeManager", () => {
483
504
  // Mock successful health check
484
505
  global.fetch = vi.fn().mockResolvedValue({ ok: true });
485
506
 
486
- await runtime.isHealthy();
507
+ await runtime.reconcileFromHealth();
487
508
 
488
509
  const baseElement = document.querySelector("base");
489
510
  expect(baseElement).toBeTruthy();
@@ -524,11 +545,11 @@ describe("RuntimeManager", () => {
524
545
  });
525
546
 
526
547
  const wsUrl = runtime.getWsURL("test" as SessionId);
527
- const httpUrl = runtime.formatHttpURL(
528
- "api/test",
529
- new URLSearchParams(),
530
- false,
531
- );
548
+ const httpUrl = runtime.formatHttpURL({
549
+ path: "api/test",
550
+ searchParams: new URLSearchParams(),
551
+ restrictToKnownQueryParams: false,
552
+ });
532
553
 
533
554
  // Should preserve base URL query params
534
555
  expect(wsUrl.searchParams.get("base_param")).toBe("existing");
@@ -44,17 +44,22 @@ export class RuntimeManager {
44
44
  return this.httpURL.origin === window.location.origin;
45
45
  }
46
46
 
47
+ private get isServerless(): boolean {
48
+ return isWasm() || isIslands() || isStaticNotebook();
49
+ }
50
+
47
51
  /**
48
52
  * The base URL of the runtime.
49
53
  */
50
- formatHttpURL(
51
- path?: string,
52
- searchParams?: URLSearchParams,
54
+ formatHttpURL({
55
+ path = "",
56
+ searchParams,
53
57
  restrictToKnownQueryParams = true,
54
- ): URL {
55
- if (!path) {
56
- path = "";
57
- }
58
+ }: {
59
+ path?: string;
60
+ searchParams?: URLSearchParams;
61
+ restrictToKnownQueryParams?: boolean;
62
+ }): URL {
58
63
  // URL may be something like "http://localhost:8000?auth=123"
59
64
  const baseUrl = this.httpURL;
60
65
  const currentParams = new URLSearchParams(window.location.search);
@@ -84,11 +89,11 @@ export class RuntimeManager {
84
89
  formatWsURL(path: string, searchParams?: URLSearchParams): URL {
85
90
  // We don't restrict to known query parameters, since mo.query_params()
86
91
  // can accept arbitrary parameters.
87
- const url = this.formatHttpURL(
92
+ const url = this.formatHttpURL({
88
93
  path,
89
94
  searchParams,
90
- /* restrictToKnownQueryParams =*/ false,
91
- );
95
+ restrictToKnownQueryParams: false,
96
+ });
92
97
 
93
98
  // For cross-origin runtimes, pass the auth token as a query parameter.
94
99
  // WebSocket connections cannot send custom headers (no Authorization
@@ -168,45 +173,63 @@ export class RuntimeManager {
168
173
  }
169
174
 
170
175
  getAiURL(path: "completion" | "chat"): URL {
171
- return this.formatHttpURL(`/api/ai/${path}`);
176
+ return this.formatHttpURL({ path: `/api/ai/${path}` });
172
177
  }
173
178
 
174
179
  /**
175
180
  * The URL of the health check endpoint.
176
181
  */
177
182
  healthURL(): URL {
178
- return this.formatHttpURL("/health");
183
+ return this.formatHttpURL({ path: "/health" });
179
184
  }
180
185
 
181
- async isHealthy(): Promise<boolean> {
182
- // Always healthy if WASM, Islands, or a static notebook (no server)
183
- if (isWasm() || isIslands() || isStaticNotebook()) {
184
- return true;
185
- }
186
-
186
+ private async fetchHealth(): Promise<Response | null> {
187
187
  try {
188
- const response = await fetch(this.healthURL().toString());
189
- // If there is a redirect, update the URL in the config
190
- if (response.redirected) {
191
- Logger.debug(`Runtime redirected to ${response.url}`);
192
- // strip /health from the URL, using URL parsing to handle query params
193
- const redirected = new URL(response.url);
194
- redirected.pathname = redirected.pathname.replace(/\/health$/, "");
195
- this.config.url = redirected.toString();
196
- }
197
-
198
- const success = response.ok;
199
- if (success) {
200
- this.setDOMBaseUri(this.config.url);
201
- }
202
- return success;
188
+ return await fetch(this.healthURL().toString());
203
189
  } catch (error) {
204
190
  Logger.error(
205
191
  `Failed to check health: ${error instanceof Error ? error.message : "Unknown error"}`,
206
192
  { cause: error },
207
193
  );
194
+ return null;
195
+ }
196
+ }
197
+
198
+ async reconcileFromHealth(): Promise<boolean> {
199
+ // Always healthy if WASM, Islands, or a static notebook (no server)
200
+ if (this.isServerless) {
201
+ return true;
202
+ }
203
+
204
+ const response = await this.fetchHealth();
205
+
206
+ if (!response) {
208
207
  return false;
209
208
  }
209
+
210
+ if (response.redirected) {
211
+ Logger.debug(`Runtime redirected to ${response.url}`);
212
+ // strip /health from the URL, using URL parsing to handle query params
213
+ const redirected = new URL(response.url);
214
+ redirected.pathname = redirected.pathname.replace(/\/health$/, "");
215
+ this.config.url = redirected.toString();
216
+ }
217
+
218
+ if (response.ok) {
219
+ this.setDOMBaseUri(this.config.url);
220
+ }
221
+
222
+ return response.ok;
223
+ }
224
+
225
+ async probeHealth(): Promise<boolean> {
226
+ // Always healthy if WASM, Islands, or a static notebook (no server)
227
+ if (this.isServerless) {
228
+ return true;
229
+ }
230
+
231
+ const response = await this.fetchHealth();
232
+ return response?.ok ?? false;
210
233
  }
211
234
 
212
235
  /**
@@ -251,7 +274,7 @@ export class RuntimeManager {
251
274
  const growthFactor = 1.2;
252
275
  const maxDelay = 2000;
253
276
 
254
- while (!(await this.isHealthy())) {
277
+ while (!(await this.reconcileFromHealth())) {
255
278
  if (retries >= maxRetries) {
256
279
  Logger.error(`Failed to connect after ${maxRetries} retries`);
257
280
  this.initialHealthyCheck.reject(
@@ -0,0 +1,34 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import { describe, expect, it } from "vitest";
4
+ import { shouldLoadDuckDBPackages } from "../utils";
5
+
6
+ describe("shouldLoadDuckDBPackages", () => {
7
+ it("loads for mo.sql", () => {
8
+ expect(shouldLoadDuckDBPackages('df = mo.sql("SELECT 1")')).toBe(true);
9
+ });
10
+
11
+ it("loads for duckdb imports and usage", () => {
12
+ expect(shouldLoadDuckDBPackages("import duckdb")).toBe(true);
13
+ expect(shouldLoadDuckDBPackages("from duckdb import sql")).toBe(true);
14
+ expect(shouldLoadDuckDBPackages("import pandas, duckdb")).toBe(true);
15
+ expect(shouldLoadDuckDBPackages("rows = duckdb.sql('SELECT 1')")).toBe(
16
+ true,
17
+ );
18
+ });
19
+
20
+ it("loads when package discovery found duckdb", () => {
21
+ expect(
22
+ shouldLoadDuckDBPackages("print('hello')", new Set(["duckdb"])),
23
+ ).toBe(true);
24
+ });
25
+
26
+ it("does not load for incidental duckdb text", () => {
27
+ expect(shouldLoadDuckDBPackages("name = 'duckdb'")).toBe(false);
28
+ expect(shouldLoadDuckDBPackages("# import duckdb")).toBe(false);
29
+ });
30
+
31
+ it("does not load without mo.sql, duckdb usage, or discovery", () => {
32
+ expect(shouldLoadDuckDBPackages("print('hello')")).toBe(false);
33
+ });
34
+ });
@@ -3,6 +3,7 @@
3
3
 
4
4
  import { toast } from "@/components/ui/use-toast";
5
5
  import { userConfigAtom } from "@/core/config/config";
6
+ import { serializeBlob } from "@/utils/blob";
6
7
  import { Deferred } from "@/utils/Deferred";
7
8
  import { throwNotImplemented } from "@/utils/functions";
8
9
  import { Logger } from "@/utils/Logger";
@@ -431,9 +432,21 @@ export class PyodideBridge implements RunRequests, EditRequests {
431
432
  sendCreateFileOrFolder: EditRequests["sendCreateFileOrFolder"] = async (
432
433
  request,
433
434
  ) => {
435
+ // The WASM RPC boundary can only carry JSON, so we base64-encode the
436
+ // file bytes here. The HTTP transport uses multipart/form-data instead.
437
+ let contents: string | null = null;
438
+ if (request.file) {
439
+ const dataUrl = await serializeBlob(request.file);
440
+ contents = dataUrl.split(",")[1] ?? "";
441
+ }
434
442
  const response = await this.rpc.proxy.request.bridge({
435
443
  functionName: "create_file_or_directory",
436
- payload: request,
444
+ payload: {
445
+ path: request.path,
446
+ type: request.type,
447
+ name: request.name,
448
+ contents,
449
+ },
437
450
  });
438
451
  return response as FileCreateResponse;
439
452
  };
@@ -10,3 +10,17 @@ export function isWasm(): boolean {
10
10
  document.querySelector("marimo-wasm") !== null
11
11
  );
12
12
  }
13
+
14
+ const DUCKDB_USAGE_PATTERN =
15
+ /(^|\n)\s*(?:import\s+[^\n#]*\bduckdb\b|from\s+duckdb\b|[^\n#]*\bduckdb\s*\.)/;
16
+
17
+ export function shouldLoadDuckDBPackages(
18
+ code: string,
19
+ foundPackages?: ReadonlySet<string>,
20
+ ): boolean {
21
+ return (
22
+ code.includes("mo.sql") ||
23
+ DUCKDB_USAGE_PATTERN.test(code) ||
24
+ foundPackages?.has("duckdb") === true
25
+ );
26
+ }
@@ -9,6 +9,7 @@ import { WasmFileSystem } from "./fs";
9
9
  import { getMarimoWheel } from "./getMarimoWheel";
10
10
  import { t } from "./tracer";
11
11
  import type { SerializedBridge, WasmController } from "./types";
12
+ import { shouldLoadDuckDBPackages } from "../utils";
12
13
 
13
14
  const MAKE_SNAPSHOT = false;
14
15
 
@@ -163,8 +164,8 @@ export class DefaultWasmController implements WasmController {
163
164
  private async loadNotebookDeps(code: string, foundPackages: Set<string>) {
164
165
  const pyodide = this.requirePyodide;
165
166
 
166
- if (code.includes("mo.sql")) {
167
- // We need pandas and duckdb for mo.sql
167
+ if (shouldLoadDuckDBPackages(code, foundPackages)) {
168
+ // We need pandas and duckdb for mo.sql and for remote duckdb sources
168
169
  code = `import pandas\n${code}`;
169
170
  code = `import duckdb\n${code}`;
170
171
  code = `import sqlglot\n${code}`;
@@ -34,6 +34,7 @@ import type {
34
34
  SerializedBridge,
35
35
  WasmController,
36
36
  } from "./types";
37
+ import { shouldLoadDuckDBPackages } from "../utils";
37
38
 
38
39
  /**
39
40
  * Web worker responsible for running the notebook.
@@ -141,8 +142,8 @@ const requestHandler = createRPCRequestHandler({
141
142
  const span = t.startSpan("loadPackages");
142
143
  await pyodideReadyPromise; // Make sure loading is done
143
144
 
144
- if (code.includes("mo.sql")) {
145
- // Add pandas and duckdb to the code
145
+ if (shouldLoadDuckDBPackages(code)) {
146
+ // Add pandas and duckdb to the code for mo.sql and for remote duckdb sources
146
147
  code = `import pandas\n${code}`;
147
148
  code = `import duckdb\n${code}`;
148
149
  code = `import sqlglot\n${code}`;
@@ -0,0 +1,156 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+ // @vitest-environment jsdom
3
+
4
+ import { act, renderHook } from "@testing-library/react";
5
+ import { createStore, Provider as JotaiProvider } from "jotai";
6
+ import type React from "react";
7
+ import { ErrorBoundary } from "react-error-boundary";
8
+ import { beforeEach, describe, expect, it, vi } from "vitest";
9
+
10
+ vi.mock("@/core/websocket/useWebSocket", async () => {
11
+ const actual =
12
+ await vi.importActual<typeof import("../useWebSocket")>("../useWebSocket");
13
+ return {
14
+ ...actual,
15
+ useConnectionTransport: vi.fn(),
16
+ };
17
+ });
18
+
19
+ vi.mock("@/core/runtime/config", async () => {
20
+ const actual = await vi.importActual<typeof import("@/core/runtime/config")>(
21
+ "@/core/runtime/config",
22
+ );
23
+ return {
24
+ ...actual,
25
+ useRuntimeManager: vi.fn(),
26
+ };
27
+ });
28
+
29
+ import { useRuntimeManager } from "@/core/runtime/config";
30
+ import { connectionAtom } from "../../network/connection";
31
+ import type { SessionId } from "../../kernel/session";
32
+ import { WebSocketClosedReason, WebSocketState } from "../types";
33
+ import { useMarimoKernelConnection } from "../useMarimoKernelConnection";
34
+ import { useConnectionTransport } from "../useWebSocket";
35
+
36
+ interface MockTransport {
37
+ readyState: 0 | 1 | 2 | 3;
38
+ reconnect: ReturnType<typeof vi.fn>;
39
+ close: ReturnType<typeof vi.fn>;
40
+ send: ReturnType<typeof vi.fn>;
41
+ addEventListener: ReturnType<typeof vi.fn>;
42
+ removeEventListener: ReturnType<typeof vi.fn>;
43
+ }
44
+
45
+ function makeTransport(
46
+ readyState: 0 | 1 | 2 | 3 = WebSocket.CLOSED,
47
+ ): MockTransport {
48
+ return {
49
+ readyState,
50
+ reconnect: vi.fn(),
51
+ close: vi.fn(),
52
+ send: vi.fn(),
53
+ addEventListener: vi.fn(),
54
+ removeEventListener: vi.fn(),
55
+ };
56
+ }
57
+
58
+ function makeRuntimeManager(
59
+ reconcileFromHealth = vi.fn().mockResolvedValue(true),
60
+ ) {
61
+ return {
62
+ reconcileFromHealth,
63
+ probeHealth: vi.fn().mockResolvedValue(true),
64
+ getWsURL: () => new URL("ws://localhost/ws"),
65
+ waitForHealthy: vi.fn().mockResolvedValue(undefined),
66
+ isSameOrigin: true,
67
+ };
68
+ }
69
+
70
+ describe("useMarimoKernelConnection.reconnect()", () => {
71
+ let transport: MockTransport;
72
+ let isHealthy: ReturnType<typeof vi.fn>;
73
+ let store: ReturnType<typeof createStore>;
74
+
75
+ beforeEach(() => {
76
+ transport = makeTransport(WebSocket.CLOSED);
77
+ isHealthy = vi.fn().mockResolvedValue(true);
78
+ store = createStore();
79
+ store.set(connectionAtom, {
80
+ state: WebSocketState.CLOSED,
81
+ code: WebSocketClosedReason.KERNEL_DISCONNECTED,
82
+ reason: "kernel not found",
83
+ });
84
+ vi.mocked(useConnectionTransport).mockReturnValue(transport);
85
+ vi.mocked(useRuntimeManager).mockReturnValue(
86
+ makeRuntimeManager(isHealthy) as unknown as ReturnType<
87
+ typeof useRuntimeManager
88
+ >,
89
+ );
90
+ });
91
+
92
+ function renderUseHook() {
93
+ const wrapper: React.FC<React.PropsWithChildren> = ({ children }) => (
94
+ <JotaiProvider store={store}>
95
+ <ErrorBoundary fallback={null}>{children}</ErrorBoundary>
96
+ </JotaiProvider>
97
+ );
98
+ return renderHook(
99
+ () =>
100
+ useMarimoKernelConnection({
101
+ sessionId: "test-session" as SessionId,
102
+ autoInstantiate: false,
103
+ setCells: () => {},
104
+ }),
105
+ { wrapper },
106
+ );
107
+ }
108
+
109
+ it("is a no-op when the transport is already OPEN", async () => {
110
+ transport.readyState = WebSocket.OPEN;
111
+ const { result } = renderUseHook();
112
+ await act(async () => {
113
+ await result.current.reconnect();
114
+ });
115
+ expect(isHealthy).not.toHaveBeenCalled();
116
+ expect(transport.reconnect).not.toHaveBeenCalled();
117
+ });
118
+
119
+ it("is a no-op when the transport is already CONNECTING", async () => {
120
+ transport.readyState = WebSocket.CONNECTING;
121
+ const { result } = renderUseHook();
122
+ await act(async () => {
123
+ await result.current.reconnect();
124
+ });
125
+ expect(isHealthy).not.toHaveBeenCalled();
126
+ expect(transport.reconnect).not.toHaveBeenCalled();
127
+ });
128
+
129
+ it("probes /health and reconnects when the runtime is healthy", async () => {
130
+ isHealthy.mockResolvedValue(true);
131
+ const { result } = renderUseHook();
132
+ await act(async () => {
133
+ await result.current.reconnect();
134
+ });
135
+ expect(isHealthy).toHaveBeenCalledOnce();
136
+ expect(transport.reconnect).toHaveBeenCalledOnce();
137
+ expect(store.get(connectionAtom)).toEqual({
138
+ state: WebSocketState.CONNECTING,
139
+ });
140
+ });
141
+
142
+ it("transitions to CLOSED and does not call ws.reconnect when the probe fails", async () => {
143
+ isHealthy.mockResolvedValue(false);
144
+ const { result } = renderUseHook();
145
+ await act(async () => {
146
+ await result.current.reconnect();
147
+ });
148
+ expect(isHealthy).toHaveBeenCalledOnce();
149
+ expect(transport.reconnect).not.toHaveBeenCalled();
150
+ expect(store.get(connectionAtom)).toEqual({
151
+ state: WebSocketState.CLOSED,
152
+ code: WebSocketClosedReason.KERNEL_DISCONNECTED,
153
+ reason: "kernel not found",
154
+ });
155
+ });
156
+ });
@@ -0,0 +1,101 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import { afterEach, describe, expect, it, vi } from "vitest";
4
+ import { Logger } from "@/utils/Logger";
5
+ import { WebSocketClosedReason, WebSocketState } from "../types";
6
+ import { classifyCloseEvent } from "../useMarimoKernelConnection";
7
+
8
+ function classify(reason: string | undefined) {
9
+ return classifyCloseEvent({ reason });
10
+ }
11
+
12
+ describe("classifyCloseEvent", () => {
13
+ describe("transient closes (default branch)", () => {
14
+ it("retries on empty/undefined reason", () => {
15
+ const decision = classify(undefined);
16
+ expect(decision.kind).toBe("retry");
17
+ expect(decision.status).toEqual({ state: WebSocketState.CONNECTING });
18
+ });
19
+
20
+ it("treats unknown reason strings as transient and logs a warning", () => {
21
+ const logger = vi.spyOn(Logger, "warn").mockImplementation(() => {});
22
+ const decision = classify("something-else");
23
+ expect(decision.kind).toBe("retry");
24
+ expect(logger).toHaveBeenCalled();
25
+ logger.mockRestore();
26
+ });
27
+ });
28
+
29
+ afterEach(() => {
30
+ vi.restoreAllMocks();
31
+ });
32
+
33
+ describe("terminal closes (server-initiated)", () => {
34
+ it("MARIMO_ALREADY_CONNECTED → terminal + closeTransport, with takeover", () => {
35
+ const decision = classify("MARIMO_ALREADY_CONNECTED");
36
+ expect(decision.kind).toBe("terminal");
37
+ expect(decision.status).toMatchObject({
38
+ state: WebSocketState.CLOSED,
39
+ code: WebSocketClosedReason.ALREADY_RUNNING,
40
+ canTakeover: true,
41
+ });
42
+ if (decision.kind === "terminal") {
43
+ expect(decision.closeTransport).toBe(true);
44
+ }
45
+ });
46
+
47
+ it.each([
48
+ "MARIMO_WRONG_KERNEL_ID",
49
+ "MARIMO_NO_FILE_KEY",
50
+ "MARIMO_NO_SESSION_ID",
51
+ "MARIMO_NO_SESSION",
52
+ "MARIMO_SHUTDOWN",
53
+ ])("%s → terminal with KERNEL_DISCONNECTED, closes transport", (reason) => {
54
+ const decision = classify(reason);
55
+ expect(decision.kind).toBe("terminal");
56
+ expect(decision.status).toMatchObject({
57
+ state: WebSocketState.CLOSED,
58
+ code: WebSocketClosedReason.KERNEL_DISCONNECTED,
59
+ });
60
+ if (decision.kind === "terminal") {
61
+ expect(decision.closeTransport).toBe(true);
62
+ }
63
+ });
64
+
65
+ it("MARIMO_MALFORMED_QUERY → terminal but does NOT close transport", () => {
66
+ const decision = classify("MARIMO_MALFORMED_QUERY");
67
+ expect(decision.kind).toBe("terminal");
68
+ expect(decision.status).toMatchObject({
69
+ state: WebSocketState.CLOSED,
70
+ code: WebSocketClosedReason.MALFORMED_QUERY,
71
+ });
72
+ if (decision.kind === "terminal") {
73
+ expect(decision.closeTransport).toBe(false);
74
+ }
75
+ });
76
+
77
+ it("MARIMO_KERNEL_STARTUP_ERROR → terminal + closeTransport", () => {
78
+ const decision = classify("MARIMO_KERNEL_STARTUP_ERROR");
79
+ expect(decision.kind).toBe("terminal");
80
+ expect(decision.status).toMatchObject({
81
+ state: WebSocketState.CLOSED,
82
+ code: WebSocketClosedReason.KERNEL_STARTUP_ERROR,
83
+ });
84
+ if (decision.kind === "terminal") {
85
+ expect(decision.closeTransport).toBe(true);
86
+ }
87
+ });
88
+ });
89
+
90
+ describe("transport exhaustion", () => {
91
+ it("MARIMO_TRANSPORT_EXHAUSTED → gave-up with KERNEL_DISCONNECTED", () => {
92
+ const decision = classify("MARIMO_TRANSPORT_EXHAUSTED");
93
+ expect(decision.kind).toBe("gave-up");
94
+ expect(decision.status).toEqual({
95
+ state: WebSocketState.CLOSED,
96
+ code: WebSocketClosedReason.KERNEL_DISCONNECTED,
97
+ reason: "kernel not found",
98
+ });
99
+ });
100
+ });
101
+ });