@marimo-team/islands 0.24.3-dev9 → 0.25.1-dev1

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 (440) hide show
  1. package/dist/{ConnectedDataExplorerComponent-C9OF_75w.js → ConnectedDataExplorerComponent-KVhjDMSe.js} +1066 -1066
  2. package/dist/ErrorBoundary-pXXIvlr3.js +200 -0
  3. package/dist/{ImageComparisonComponent-2a9TMMm2.js → ImageComparisonComponent-Dlm5aWnH.js} +4 -4
  4. package/dist/{Plot-C-9MQeGP.js → Plot-CTyjbQDT.js} +21032 -20666
  5. package/dist/_baseMerge-BiGRwuqv.js +165 -0
  6. package/dist/{abnfDiagram-N423BO3Z-CQKwzX8t.js → abnfDiagram-VCTEODGH-CpN0FRda.js} +17 -18
  7. package/dist/{any-language-editor-DmQ7dyCx.js → any-language-editor-CycIVIeP.js} +17 -17
  8. package/dist/arc-7ra3iNdN.js +81 -0
  9. package/dist/architecture-7GRP2DOG-BWLylgiA.js +3 -0
  10. package/dist/{architectureDiagram-T3A2C74G-CncrDpfa.js → architectureDiagram-5GKGNRK7-DDyj5SRB.js} +25 -25
  11. package/dist/assets/__vite-browser-external-C9iR87Zl.js +1 -0
  12. package/dist/assets/worker-D7hWi02M.js +109 -0
  13. package/dist/blockDiagram-I7D4REHJ-BbXEXJRu.js +1922 -0
  14. package/dist/{button-CKBkqR9J.js → button-DdXAm8iz.js} +5 -5
  15. package/dist/{c4Diagram-5PPSVZJV-DarUk3Yq.js → c4Diagram-7LVT6UL2-DcLsbQmR.js} +696 -668
  16. package/dist/{capabilities-CMBBJTcc.js → capabilities-B3ce_GNu.js} +1 -1
  17. package/dist/{html-to-image-BtFMe_Nq.js → cells-DYIkSxs6.js} +6757 -10137
  18. package/dist/{channel-CyiYUzJv.js → channel-B5XnTarr.js} +1 -1
  19. package/dist/chat-ui-BXj3uYjy.js +5786 -0
  20. package/dist/{check-CHig47QV.js → check-B7cIK6gb.js} +1 -1
  21. package/dist/{chunk-2Q5K7J3B-BMuJl2jB.js → chunk-2Q5K7J3B-BMkUkeuy.js} +2 -2
  22. package/dist/chunk-4HAMMTFA-D2qv8E0X.js +4188 -0
  23. package/dist/{chunk-5VM5RSS4-Bcq0ftdy.js → chunk-5VM5RSS4-DKsmPCL6.js} +2 -2
  24. package/dist/{chunk-NSK5VX7P-CDTMcJB0.js → chunk-75Z2AOVW-5_HsvXwr.js} +23 -23
  25. package/dist/{chunk-I66GZJ75-BqyTCAPf.js → chunk-DU6HZSFF-BUgAHvnM.js} +21 -4
  26. package/dist/{chunk-2GRJ4B5K-DgO8Qudq.js → chunk-F27PBJKO-DHmYWZXr.js} +4 -4
  27. package/dist/{chunk-KEIR6QF5-C4KX3XYh.js → chunk-FOHPRMQF-BpYR8RqP.js} +4 -4
  28. package/dist/{chunk-WRU74C26-BpWsbiDK.js → chunk-GMAD6QVW-Czynz8aA.js} +486 -258
  29. package/dist/chunk-GVQU2GXP-yQEdulRS.js +37 -0
  30. package/dist/{chunk-5RXB4S5H-tLNUVDdO.js → chunk-IMKFNOWR-BfwTebD0.js} +11 -11
  31. package/dist/{chunk-JWPE2WC7-BJwjGUnF.js → chunk-JWPE2WC7-DJvv1t8U.js} +2 -2
  32. package/dist/chunk-L3NEJ4N5-DwRWnDDK.js +245 -0
  33. package/dist/{chunk-7Z6QIM7H-Dc18hFxH.js → chunk-OSK3NFVY-BBKU_Ign.js} +222 -144
  34. package/dist/{chunk-W5SLKNZC-DLnvpEtV.js → chunk-P2QGCYS3-C0iGU29N.js} +20 -20
  35. package/dist/{chunk-KBJHAD2P-BuqWqkcW.js → chunk-POPQ4Y6H-BCbS3Ozc.js} +4 -4
  36. package/dist/{chunk-4I5QYGJK-DpytHuZQ.js → chunk-PWAF6VOD-CTFCL0jI.js} +4 -4
  37. package/dist/{chunk-JQJVKLGR-CgqCwe8E.js → chunk-SHT3W25Y-BspJEJ5H.js} +109 -63
  38. package/dist/{chunk-6Q2QTUOP-DmTcEBMn.js → chunk-SVP7TREG-DX3rFNTe.js} +5 -5
  39. package/dist/{chunk-GF5L2VYU-B0wgCQgS.js → chunk-TICWLB2K-fVF7Uujg.js} +13 -13
  40. package/dist/{chunk-XXDRQBXY-D73H4IN0.js → chunk-XXDRQBXY-Dnl5VBqG.js} +3 -3
  41. package/dist/{chunk-Y2CYZVJY-DoegUj_e.js → chunk-Y2CYZVJY-DKKS1VyV.js} +1 -1
  42. package/dist/{chunk-5FQGJX7Z-B85XCPv6.js → chunk-YOKDWASO-DrWbKnxA.js} +6925 -5460
  43. package/dist/classDiagram-ZZMXUADV-Fe-V14Sc.js +30 -0
  44. package/dist/classDiagram-v2-VYDZK3BY-xTDg7lOs.js +30 -0
  45. package/dist/code-visibility-BC_yF09p.js +138 -0
  46. package/dist/{common-Cv-4hMa0.js → common-Dv227ygK.js} +8838 -12645
  47. package/dist/{compiler-runtime-CAH9RLw2.js → compiler-runtime-Cj8ZWiNS.js} +2 -2
  48. package/dist/copy-icon-CLdENY__.js +190 -0
  49. package/dist/{cose-bilkent-JH36ORCC-FUWHkXFX.js → cose-bilkent-JH36ORCC-_LyRKVqm.js} +2 -2
  50. package/dist/cubic-OaEBhQPK.js +1404 -0
  51. package/dist/cynefin-OW5HDTMX-obq-i80l.js +3 -0
  52. package/dist/{cynefinDiagram-MW4NZA55-BXSFK93J.js → cynefinDiagram-5FMLGOSQ-CFQrqzSX.js} +10 -10
  53. package/dist/{dagre-CGyalH38.js → dagre-BGSfXNEb.js} +678 -537
  54. package/dist/dagre-GXQ25YYZ-xHNAUTyG.js +425 -0
  55. package/dist/{data-grid-overlay-editor-DZM4BAaI.js → data-grid-overlay-editor-B-I2K7z3.js} +8 -9
  56. package/dist/{data-grid-types-BnZwWG8z.js → data-grid-types-BucVmDDp.js} +1 -1
  57. package/dist/{defaultLocale-DKaU_opG.js → defaultLocale-JI_lnoCe.js} +1 -1
  58. package/dist/{diagram-7IWD3JNH-BjfzDNvj.js → diagram-S7CK7UJ4-Bt1rPbAx.js} +40 -39
  59. package/dist/{diagram-UB23O5K3-DDg-7wLA.js → diagram-UQ7AKVKN-D1sq5FoZ.js} +10 -10
  60. package/dist/{diagram-B4RE2ZJO-CKccR9eE.js → diagram-VSXAHHWV-BKpmG23x.js} +10 -10
  61. package/dist/{diagram-Q27KOJAE-Zhz01ss7.js → diagram-VX7I27RA-BMwGFVD6.js} +21 -21
  62. package/dist/{diagram-LBJQPF4R-CJ-bOruh.js → diagram-Z3DM3KII--KLDR9Pl.js} +10 -10
  63. package/dist/dialog-CgNq6y9-.js +94 -0
  64. package/dist/{dist-dAqZAPcF.js → dist-1HDa70oE.js} +3 -3
  65. package/dist/{dist-Re9sOPOx.js → dist-9x1ZRe-e.js} +2 -2
  66. package/dist/{dist-DEeLqRlU.js → dist-B1vYLK28.js} +1 -1
  67. package/dist/{dist-C5Bn52W4.js → dist-B8D7McG3.js} +3 -3
  68. package/dist/{dist-_XvgytiS.js → dist-BHCHt1NI.js} +1 -1
  69. package/dist/{dist-CRjAdnqF.js → dist-BRxfaJgs.js} +3 -3
  70. package/dist/{dist-Byj2bV8o.js → dist-BVGtK7Ht.js} +1 -1
  71. package/dist/{dist-BIN5LKyE.js → dist-BaHjhkpZ.js} +2 -2
  72. package/dist/{dist-DVFbIwc5.js → dist-BtKIs9N-.js} +1 -1
  73. package/dist/{dist-BrQGcfQ9.js → dist-C2KzV-vf.js} +2 -2
  74. package/dist/{dist-DJFiGP2k.js → dist-C2wDlYdD.js} +2 -2
  75. package/dist/{dist-BVRM2y1P.js → dist-C8xMLVYi.js} +2 -2
  76. package/dist/dist-CMh_W4y4.js +538 -0
  77. package/dist/{extends-BPB6_lTK.js → dist-CO1AwwG_.js} +516 -561
  78. package/dist/{dist-BzN60Z2s.js → dist-CPGxfVGX.js} +1 -1
  79. package/dist/{dist-C7v-9nUK.js → dist-Cm3iAFMD.js} +3 -3
  80. package/dist/{dist-CGAxEiaM.js → dist-Cs2FijYk.js} +2 -2
  81. package/dist/{dist-hXd65f0_.js → dist-D1PpnuZB.js} +1 -1
  82. package/dist/{dist-VdvbxG72.js → dist-DHOTQar0.js} +1 -1
  83. package/dist/{dist-DcgzXCfy.js → dist-DPcEtqmG.js} +2 -2
  84. package/dist/{dist-D4Z_qdP4.js → dist-Df0wKI0F.js} +1 -1
  85. package/dist/{dist-qhLI-SHd.js → dist-DszxuxS1.js} +2 -2
  86. package/dist/{dist-BEmkrGoQ.js → dist-Kxgjxakw.js} +1 -1
  87. package/dist/{dist-BbSMhhD2.js → dist-KzZ7WELx.js} +2 -2
  88. package/dist/{dist-jWUab2d1.js → dist-lA1Cttkb.js} +1 -1
  89. package/dist/dropdown-menu-CZgjYSAh.js +4502 -0
  90. package/dist/{ebnfDiagram-BXEA7PRR-Dm75pCAS.js → ebnfDiagram-PWID7BFC-WnG4cvSQ.js} +17 -18
  91. package/dist/{erDiagram-JOGREHBK-rVDG3VSQ.js → erDiagram-RLTQ6QDP-DhzKiYHc.js} +1037 -798
  92. package/dist/error-banner-B94dcDmP.js +391 -0
  93. package/dist/error-entries-C0NsUqXl.js +56 -0
  94. package/dist/{esm-CR1nhb1c.js → esm-BElI3qKH.js} +22 -22
  95. package/dist/{esm-C1d0g6Bv.js → esm-G4Fhsgng.js} +51 -37
  96. package/dist/{esm-CesmlDrs.js → esm-h8f7-1CJ.js} +423 -423
  97. package/dist/eventmodeling-NTZA5JFV-D7nP7Uyu.js +3 -0
  98. package/dist/feedback-button-D2hUXe09.js +380 -0
  99. package/dist/flowDiagram-HODETNUW-6dMdB8pR.js +16 -0
  100. package/dist/{formats-CslNOKy0.js → formats-BR5iGb4s.js} +8 -8
  101. package/dist/{ganttDiagram-PKOTCBZU-9D-LXF6P.js → ganttDiagram-EL5Y4UJY-DbzEBLbl.js} +15 -15
  102. package/dist/gitGraph-4MIJSDKK-Dy9uQXGh.js +3 -0
  103. package/dist/{gitGraphDiagram-DS77QQ5N-BfpsXTLf.js → gitGraphDiagram-WWUBYQGX-BMf0iKi1.js} +10 -10
  104. package/dist/{glide-data-editor-sPZ8fUFn.js → glide-data-editor-B851uguN.js} +2143 -1910
  105. package/dist/{glide-utils-NShAPPtn.js → glide-utils-B3rUT5PI.js} +15 -15
  106. package/dist/globals-CmijFoIU.js +19 -0
  107. package/dist/highlighted-body-KPVGNVTW-Ad3MKZ18.js +38 -0
  108. package/dist/html-to-image-CeYYvQNb.js +3272 -0
  109. package/dist/info-A6RAGUB7-DKoayiHY.js +3 -0
  110. package/dist/{infoDiagram-6WML65LV-DqCTXHVy.js → infoDiagram-27XIBGKW-BagtCX_5.js} +7 -7
  111. package/dist/{ishikawaDiagram-WSZJBQD7-BCUYmZ1v.js → ishikawaDiagram-5VMMS53U-DByDehYy.js} +8 -8
  112. package/dist/{journeyDiagram-NVQOT4AX-BXB6M4zN.js → journeyDiagram-3NMN7TZE-D2LcKDUO.js} +8 -8
  113. package/dist/{jsx-runtime-CpoKNRgu.js → jsx-runtime-DgDPJV9S.js} +1 -1
  114. package/dist/{kanban-definition-27J2QSJJ-CGRhrDUX.js → kanban-definition-UXKFOSKX-BxwkbBI_.js} +29 -29
  115. package/dist/katex-DFBiSucW.js +21840 -0
  116. package/dist/{label-lwzzBHUW.js → label-BJ49YTvk.js} +6 -6
  117. package/dist/{linear-D5r_1YqD.js → linear-Cnaq3Tfb.js} +4 -4
  118. package/dist/{loader-VZ__bv4g.js → loader-D2W4oM-3.js} +15 -15
  119. package/dist/main.js +8113 -13475
  120. package/dist/mermaid-DPNuhemn.js +3084 -0
  121. package/dist/mermaid-HWGCJPDP-DYCzSILp.js +2 -0
  122. package/dist/mermaid-parser.core-DxuSfYwJ.js +638 -0
  123. package/dist/{mhchem-BjwrxcV-.js → mhchem-DWCF06w9.js} +1 -1
  124. package/dist/{micromark-factory-space-DruVGzeG.js → micromark-factory-space-DGxAzmw8.js} +2 -2
  125. package/dist/{mindmap-definition-FAOFIHXS-C9gRhzZq.js → mindmap-definition-YA3MSWOX-Cgvojw3y.js} +17 -17
  126. package/dist/{node-sql-parser-DesT1xNw.js → node-sql-parser-BiZOJ-FS.js} +0 -3
  127. package/dist/{number-overlay-editor-De2CabLL.js → number-overlay-editor-BtdoxWiD.js} +5 -5
  128. package/dist/objectWithoutPropertiesLoose-BRDcTsfB.js +23 -0
  129. package/dist/packet-AYTQ26CC-Yw7ajchJ.js +3 -0
  130. package/dist/{pegDiagram-VL7TDLO6-Df9IUjMD.js → pegDiagram-XKGWAZYB-DahHhYyN.js} +19 -20
  131. package/dist/{pick-SnHlmIBN.js → pick-CJeoxYOS.js} +1 -1
  132. package/dist/pie-WAS4IAKB-BKdKOAkL.js +3 -0
  133. package/dist/{pieDiagram-7S7Q4E2Y-BmRzQ8ZP.js → pieDiagram-E7YTZNPT-CCtX0oCK.js} +29 -31
  134. package/dist/{process-output-CPy0YKUe.js → process-output-BCTjlyuH.js} +7 -6
  135. package/dist/purify.es-DgKyQviY.js +805 -0
  136. package/dist/{quadrantDiagram-CIZ2JOQS-wFBvWcxS.js → quadrantDiagram-AXDQQJYC-DftINo6g.js} +5 -5
  137. package/dist/radar-RG4KPBEZ-ScR_D_Ts.js +3 -0
  138. package/dist/railroad-74A4TZTK-DQvPSdo5.js +3 -0
  139. package/dist/railroad-abnf-HS5TGJTU-CsJQG2O8.js +3 -0
  140. package/dist/railroad-ebnf-LZEXJU2U-BgEobkSn.js +3 -0
  141. package/dist/railroad-peg-WCYAUIDC-DjLAjofI.js +3 -0
  142. package/dist/{railroadDiagram-AXF67PYL-DxbIatiN.js → railroadDiagram-O6MQD6OU-Du5NsPUb.js} +17 -18
  143. package/dist/{react-dom-C94wmq5w.js → react-dom-BUgJ-ab_.js} +3 -3
  144. package/dist/{react-DMWcHin-.js → react-ofJbxM4x.js} +2 -2
  145. package/dist/{react-vega-DSD5aT7_.js → react-vega-5AcMW8gG.js} +10012 -9369
  146. package/dist/{requirementDiagram-LRYGKXZP-X_x-Y713.js → requirementDiagram-BXWQKSXE-0pmmxL6_.js} +20 -19
  147. package/dist/{reveal-component-CVsYlb9J.js → reveal-component-DQq7NUGJ.js} +1303 -1237
  148. package/dist/{sankeyDiagram-W5VNT64P-BYJALbbm.js → sankeyDiagram-P5KCCOFB-CDKR5TJH.js} +4 -4
  149. package/dist/{select-3qHpFKF9.js → select-C6plhmZr.js} +317 -562
  150. package/dist/{sequenceDiagram-SI44F4Z6-BiPBe3Sv.js → sequenceDiagram-WJ2MYXX4-DB-ChWwU.js} +11 -11
  151. package/dist/{sizeCapture-X5ZJPWSS-BKLDeh5H.js → sizeCapture-INFHLROL-Dx5SpkQF.js} +2 -2
  152. package/dist/{spec-CutWdqo3.js → spec-CAYwFeV6.js} +4 -4
  153. package/dist/{src-C31ngt98.js → src-CA_m4ONl.js} +298 -303
  154. package/dist/{stateDiagram-OKZ733FA-B7QyNBxH.js → stateDiagram-D77RDMKH-orN6AwMx.js} +19 -20
  155. package/dist/stateDiagram-v2-MP3YSRHH-o05_rJN8.js +30 -0
  156. package/dist/style.css +2 -2
  157. package/dist/{swimlanes-SLNWSIFB-B4f8VP3b.js → swimlanes-42K2YHIH-BkSDcqDT.js} +1501 -1591
  158. package/dist/swimlanesDiagram-VR7AAH4N-D_nFQfRc.js +30 -0
  159. package/dist/{swiper-component-C90YjhaV.js → swiper-component-IOUowglM.js} +39 -26
  160. package/dist/{time-aWGfjN8x.js → time-BieKwdYS.js} +42 -42
  161. package/dist/{timeline-definition-Z64GVDOM-Dacq_5lr.js → timeline-definition-24CTP7MA-BuqJUIRZ.js} +7 -7
  162. package/dist/{toDate-CpXBeDq0.js → toDate-WXg1yLcI.js} +7 -7
  163. package/dist/toast-DvY70eFX.js +1834 -0
  164. package/dist/tooltip-qB8NlSqV.js +1742 -0
  165. package/dist/treeView-Q6P3EWNA-DuRV97YF.js +3 -0
  166. package/dist/treemap-WGGIJYW6-AsLq-uwC.js +3 -0
  167. package/dist/use-restore-focus-D5D9xEjZ.js +5946 -0
  168. package/dist/{use-vega-container-remeasure-DUW4tRxq.js → use-vega-container-remeasure-4DwJbPWu.js} +2 -2
  169. package/dist/{useAsyncData-CH6-CgJF.js → useAsyncData-BD6AStMt.js} +3 -3
  170. package/dist/{useDateFormatter-Cp9Jdxls.js → useDateFormatter-BRTPsUK7.js} +8 -8
  171. package/dist/{useDeepCompareMemoize-JC87C_jO.js → useDeepCompareMemoize-D_HNdyvI.js} +2 -2
  172. package/dist/{useIframeCapabilities-De3C-9b4.js → useIframeCapabilities-CVtNkI3Y.js} +2 -2
  173. package/dist/{useLifecycle-B4RGlyf0.js → useLifecycle-DPgiiwwU.js} +6 -6
  174. package/dist/useNumberFormatter-BfDpa21j.js +251 -0
  175. package/dist/useTheme-DzXmYZ5V.js +904 -0
  176. package/dist/{vega-component-ovBXgp91.js → vega-component-D0QXopU8.js} +34 -34
  177. package/dist/{vega-embed-container-TJ5z5dZw.js → vega-embed-container-CbnTccZi.js} +6 -6
  178. package/dist/vega-loader.browser-D95WfUcj.js +1139 -0
  179. package/dist/{vennDiagram-T6HMQDX7-D-Rcq3Iu.js → vennDiagram-4TSXK5OY-CTUlJ2PK.js} +9 -9
  180. package/dist/wardley-WFR3VGLG-Na-tFhQJ.js +3 -0
  181. package/dist/{wardleyDiagram-T6FBY63Y-Z-Og7_Wd.js → wardleyDiagram-VM6X3IG4-3evLUb0M.js} +10 -10
  182. package/dist/{xychartDiagram-ELKLHX3M-BDJ2dITA.js → xychartDiagram-S5SC5T6Z-DL2E3K8-.js} +248 -139
  183. package/package.json +54 -57
  184. package/src/__mocks__/notebook.ts +1 -0
  185. package/src/__mocks__/requests.ts +7 -0
  186. package/src/__tests__/__snapshots__/CellStatus.test.tsx.snap +12 -12
  187. package/src/__tests__/fixtures/pair-preview.ts +19 -0
  188. package/src/__tests__/mount.test.ts +18 -0
  189. package/src/components/app-config/optional-features.tsx +6 -0
  190. package/src/components/chat/acp/__tests__/agent-panel-initialization.test.tsx +394 -0
  191. package/src/components/chat/acp/__tests__/agent-panel.test.tsx +272 -0
  192. package/src/components/chat/acp/__tests__/state.test.ts +2 -2
  193. package/src/components/chat/acp/agent-panel.tsx +115 -74
  194. package/src/components/chat/acp/state.ts +1 -1
  195. package/src/components/data-table/__tests__/filters.test.ts +21 -21
  196. package/src/components/data-table/charts/__tests__/spec.test.ts +5 -10
  197. package/src/components/data-table/column-explorer-panel/column-explorer.tsx +2 -6
  198. package/src/components/data-table/column-summary/chart-spec-model.tsx +1 -1
  199. package/src/components/data-table/columns.tsx +64 -67
  200. package/src/components/editor/RecoveryButton.tsx +1 -0
  201. package/src/components/editor/__tests__/dynamic-favicon.test.tsx +36 -2
  202. package/src/components/editor/actions/__tests__/pair-with-agent-commands.test.ts +115 -0
  203. package/src/components/editor/actions/__tests__/pair-with-agent-modal.test.tsx +218 -0
  204. package/src/components/editor/actions/pair-with-agent-commands.ts +46 -9
  205. package/src/components/editor/actions/pair-with-agent-modal.tsx +49 -23
  206. package/src/components/editor/ai/add-cell-with-ai.tsx +1 -0
  207. package/src/components/editor/ai/ai-completion-editor.tsx +3 -1
  208. package/src/components/editor/alerts/__tests__/connection-notice.test.tsx +186 -0
  209. package/src/components/editor/alerts/__tests__/startup-progress.test.tsx +185 -0
  210. package/src/components/editor/alerts/connecting-alert.tsx +1 -66
  211. package/src/components/editor/alerts/connection-notice.tsx +186 -0
  212. package/src/components/editor/alerts/startup-output.tsx +173 -0
  213. package/src/components/editor/alerts/startup-progress.tsx +204 -0
  214. package/src/components/editor/app-container.tsx +9 -3
  215. package/src/components/editor/boundary/ErrorBoundary.tsx +38 -16
  216. package/src/components/editor/boundary/__tests__/ErrorBoundary.test.tsx +311 -0
  217. package/src/components/editor/cell/__tests__/toolbar.test.tsx +73 -0
  218. package/src/components/editor/cell/code/__tests__/rtc-editor-config.test.ts +50 -0
  219. package/src/components/editor/cell/code/cell-editor.tsx +41 -42
  220. package/src/components/editor/cell/toolbar.tsx +11 -0
  221. package/src/components/editor/chrome/components/__tests__/feedback-button.test.tsx +94 -0
  222. package/src/components/editor/chrome/components/feedback-button.tsx +63 -42
  223. package/src/components/editor/chrome/panels/__tests__/packages-panel.test.tsx +164 -8
  224. package/src/components/editor/chrome/panels/__tests__/sandbox-details.test.tsx +358 -0
  225. package/src/components/editor/chrome/panels/__tests__/sandbox-recovery.test.tsx +168 -0
  226. package/src/components/editor/chrome/panels/packages-panel.tsx +113 -175
  227. package/src/components/editor/chrome/panels/sandbox-controller.tsx +106 -0
  228. package/src/components/editor/chrome/panels/sandbox-details-state.ts +38 -0
  229. package/src/components/editor/chrome/panels/sandbox-panel.tsx +230 -0
  230. package/src/components/editor/chrome/panels/sandbox-toggle.tsx +52 -0
  231. package/src/components/editor/chrome/wrapper/app-chrome.tsx +7 -0
  232. package/src/components/editor/chrome/wrapper/footer-items/backend-status.tsx +3 -1
  233. package/src/components/editor/code/__tests__/readonly-diff.test.tsx +65 -0
  234. package/src/components/editor/code/readonly-diff.tsx +1 -1
  235. package/src/components/editor/connections/database/__tests__/__snapshots__/as-code.test.ts.snap +98 -98
  236. package/src/components/editor/connections/database/__tests__/as-code.test.ts +11 -5
  237. package/src/components/editor/dynamic-favicon.tsx +17 -10
  238. package/src/components/editor/file-tree/__tests__/file-explorer-navigation.test.tsx +13 -11
  239. package/src/components/editor/file-tree/__tests__/tree-actions.test.tsx +54 -0
  240. package/src/components/editor/file-tree/tree-actions.tsx +11 -14
  241. package/src/components/editor/header/__tests__/status.test.tsx +8 -20
  242. package/src/components/editor/header/filename-input.tsx +2 -0
  243. package/src/components/editor/header/status.tsx +5 -3
  244. package/src/components/editor/navigation/clipboard.ts +1 -0
  245. package/src/components/editor/notebook-cell.tsx +4 -2
  246. package/src/components/editor/output/JsonOutput.tsx +182 -632
  247. package/src/components/editor/output/Outputs.css +49 -17
  248. package/src/components/editor/output/__tests__/JsonOutput-interactions.test.tsx +254 -0
  249. package/src/components/editor/output/__tests__/JsonOutput-mimetype.test.tsx +41 -46
  250. package/src/components/editor/output/__tests__/{json-output.test.ts → json-output-formatting.test.ts} +113 -75
  251. package/src/components/editor/output/__tests__/json-output-pagination.test.ts +252 -0
  252. package/src/components/editor/output/json-output/formatting.ts +167 -0
  253. package/src/components/editor/output/json-output/pagination.ts +155 -0
  254. package/src/components/editor/output/json-output/renderers.tsx +196 -0
  255. package/src/components/editor/output/json-output/themes.ts +52 -0
  256. package/src/components/editor/package-alert.tsx +112 -66
  257. package/src/components/editor/renderers/cell-array.tsx +1 -5
  258. package/src/components/editor/renderers/slides-layout/__tests__/plugin.test.ts +3 -7
  259. package/src/components/slides/slide-form.tsx +1 -0
  260. package/src/components/slides/slide-notes-editor.tsx +1 -0
  261. package/src/components/tracing/tracing-spec.ts +1 -1
  262. package/src/components/ui/__tests__/badge.test.ts +6 -4
  263. package/src/components/ui/use-toast.ts +8 -0
  264. package/src/core/MarimoApp.tsx +0 -2
  265. package/src/core/ai/context/providers/__tests__/error.test.ts +16 -22
  266. package/src/core/alerts/__tests__/environment.test.ts +183 -0
  267. package/src/core/alerts/__tests__/state.test.tsx +240 -0
  268. package/src/core/alerts/environment.ts +57 -0
  269. package/src/core/alerts/state.ts +155 -99
  270. package/src/core/cells/__tests__/__snapshots__/cells.test.ts.snap +296 -259
  271. package/src/core/cells/__tests__/apply-transaction.test.ts +34 -0
  272. package/src/core/cells/__tests__/cell.test.ts +61 -0
  273. package/src/core/cells/__tests__/cells.test.ts +182 -37
  274. package/src/core/cells/__tests__/document-changes.test.ts +39 -1
  275. package/src/core/cells/__tests__/outputs.test.tsx +117 -0
  276. package/src/core/cells/__tests__/pending-delete-service.test.tsx +4 -3
  277. package/src/core/cells/__tests__/session.test.ts +7 -0
  278. package/src/core/cells/cell.ts +9 -1
  279. package/src/core/cells/cells.ts +13 -18
  280. package/src/core/cells/document-changes.ts +11 -1
  281. package/src/core/cells/outputs.ts +66 -9
  282. package/src/core/cells/pending-delete-service.ts +12 -16
  283. package/src/core/cells/session.ts +2 -0
  284. package/src/core/cells/types.ts +2 -0
  285. package/src/core/codemirror/find-replace/__tests__/navigate.test.ts +8 -16
  286. package/src/core/codemirror/language/__tests__/sql.test.ts +70 -2
  287. package/src/core/codemirror/language/embedded/__tests__/embedded-python.test.ts +4 -8
  288. package/src/core/codemirror/language/languages/sql/sql.ts +16 -1
  289. package/src/core/codemirror/rtc/extension.ts +5 -2
  290. package/src/core/config/pair.ts +19 -0
  291. package/src/core/datasets/__tests__/data-source.test.ts +2 -0
  292. package/src/core/datasets/data-source-connections.ts +15 -10
  293. package/src/core/edit-app.tsx +8 -5
  294. package/src/core/errors/state.ts +1 -2
  295. package/src/core/export/__tests__/hooks.test.ts +1 -6
  296. package/src/core/islands/bootstrap.ts +3 -1
  297. package/src/core/islands/bridge.ts +3 -0
  298. package/src/core/islands/worker-factory.ts +2 -12
  299. package/src/core/kernel/messages.ts +2 -2
  300. package/src/core/network/__tests__/requests-network.test.ts +4 -3
  301. package/src/core/network/connection-notice.ts +117 -0
  302. package/src/core/network/connection.ts +19 -0
  303. package/src/core/network/requests-lazy.ts +3 -0
  304. package/src/core/network/requests-network.ts +12 -0
  305. package/src/core/network/requests-static.ts +3 -0
  306. package/src/core/network/requests-toasting.tsx +3 -0
  307. package/src/core/network/resolve.ts +2 -1
  308. package/src/core/network/types.ts +7 -0
  309. package/src/core/network/useConnectionNotice.ts +53 -0
  310. package/src/core/packages/__tests__/usePackageAction.test.tsx +129 -0
  311. package/src/core/packages/__tests__/useSandboxController.test.tsx +246 -0
  312. package/src/core/packages/package-data.ts +35 -0
  313. package/src/core/packages/sandbox-state.ts +67 -0
  314. package/src/core/packages/toast-components.tsx +11 -0
  315. package/src/core/packages/useInstallPackage.ts +1 -1
  316. package/src/core/packages/usePackageAction.ts +51 -0
  317. package/src/core/packages/usePackageDependencies.ts +22 -0
  318. package/src/core/packages/useSandboxController.ts +208 -0
  319. package/src/core/run-app.tsx +2 -0
  320. package/src/core/static/__tests__/files.test.ts +12 -30
  321. package/src/core/wasm/__tests__/bootstrap.test.ts +63 -0
  322. package/src/core/wasm/__tests__/bridge.test.ts +13 -4
  323. package/src/core/wasm/__tests__/fs.test.ts +22 -0
  324. package/src/core/wasm/__tests__/runtime-config.test.ts +65 -0
  325. package/src/core/wasm/bridge.ts +35 -23
  326. package/src/core/wasm/rpc.ts +2 -0
  327. package/src/core/wasm/runtime-config.ts +31 -0
  328. package/src/core/wasm/worker/bootstrap.ts +21 -11
  329. package/src/core/wasm/worker/constants.ts +1 -0
  330. package/src/core/wasm/worker/fs.ts +4 -0
  331. package/src/core/wasm/worker/getController.ts +3 -1
  332. package/src/core/wasm/worker/save-worker.ts +10 -9
  333. package/src/core/wasm/worker/types.ts +6 -4
  334. package/src/core/wasm/worker/worker.ts +9 -9
  335. package/src/core/websocket/__tests__/useMarimoKernelConnection.hook.test.tsx +404 -3
  336. package/src/core/websocket/__tests__/useMarimoKernelConnection.test.ts +8 -6
  337. package/src/core/websocket/transports/transport.ts +1 -1
  338. package/src/core/websocket/transports/ws.ts +1 -1
  339. package/src/core/websocket/types.ts +11 -1
  340. package/src/core/websocket/useMarimoKernelConnection.tsx +63 -16
  341. package/src/hooks/useDebounce.ts +2 -0
  342. package/src/mount.tsx +3 -0
  343. package/src/plugins/core/BadPlugin.tsx +3 -14
  344. package/src/plugins/core/RenderHTML.tsx +22 -2
  345. package/src/plugins/core/__test__/RenderHTML.test.ts +187 -0
  346. package/src/plugins/core/registerReactComponent.tsx +0 -1
  347. package/src/plugins/impl/FileBrowserPlugin.tsx +10 -4
  348. package/src/plugins/impl/FormPlugin.tsx +2 -0
  349. package/src/plugins/impl/MatrixPlugin.tsx +2 -0
  350. package/src/plugins/impl/RangeSliderPlugin.tsx +2 -0
  351. package/src/plugins/impl/SliderPlugin.tsx +2 -0
  352. package/src/plugins/impl/__tests__/FileBrowserPlugin.test.tsx +50 -1
  353. package/src/plugins/impl/data-editor/__tests__/glide-data-editor.test.tsx +23 -18
  354. package/src/plugins/impl/data-frames/panel.tsx +1 -0
  355. package/src/plugins/impl/image-comparison/ImageComparisonComponent.tsx +1 -1
  356. package/src/plugins/impl/image-comparison/__tests__/ImageComparisonComponent.test.tsx +15 -0
  357. package/src/plugins/impl/vega/__tests__/make-selectable.test.ts +42 -48
  358. package/src/plugins/layout/AccordionPlugin.tsx +7 -2
  359. package/src/plugins/layout/JsonOutputPlugin.tsx +7 -10
  360. package/src/plugins/layout/__test__/AccordionPlugin.test.tsx +66 -0
  361. package/src/stories/sandbox.stories.tsx +488 -0
  362. package/src/utils/__tests__/path.test.ts +6 -5
  363. package/src/utils/__tests__/worker.test.ts +81 -0
  364. package/src/utils/worker.ts +22 -0
  365. package/dist/ErrorBoundary-CR-ZQN_c.js +0 -125
  366. package/dist/_baseMerge-Dv8bBloN.js +0 -73
  367. package/dist/_initCloneObject---vediN2.js +0 -95
  368. package/dist/arc-DOVLrCPd.js +0 -82
  369. package/dist/architecture-TIHT7OUA-MiJpPpQW.js +0 -3
  370. package/dist/array-CApNbSU9.js +0 -6
  371. package/dist/assets/__vite-browser-external-BdKGjRZ4.js +0 -1
  372. package/dist/assets/worker-DlIBfp9S.js +0 -98
  373. package/dist/blockDiagram-VBNYF7ZC-Bc--I65C.js +0 -3158
  374. package/dist/chat-ui-BSwr409J.js +0 -8455
  375. package/dist/chunk-3NCLNEKW-BIp_lB_4.js +0 -14
  376. package/dist/chunk-5FCAYU7R-C_HO9A1J.js +0 -23
  377. package/dist/chunk-5HE753X5-Bixm_MV-.js +0 -38
  378. package/dist/chunk-5JV3BV7I-CH5J3iZY.js +0 -54
  379. package/dist/chunk-5TONJI2A-DG6gDiSS.js +0 -62
  380. package/dist/chunk-7BUUIJ7U-5afmIPeo.js +0 -82
  381. package/dist/chunk-BIQX33UG-7TMBUf89.js +0 -23
  382. package/dist/chunk-CQNSW5MT-Cnqqsxt-.js +0 -38
  383. package/dist/chunk-CYSBUYHQ-BAbymFHR.js +0 -23
  384. package/dist/chunk-EMLP6XTP-Bsz-QL77.js +0 -23
  385. package/dist/chunk-J7OUQ5F2-CM_meqZH.js +0 -57
  386. package/dist/chunk-JG7HCLWE-DUnCDgPk.js +0 -62
  387. package/dist/chunk-MOZMSUNE-BG6IHvzT.js +0 -35
  388. package/dist/chunk-OSBZ3O6U-CYwj_bvR.js +0 -23
  389. package/dist/chunk-QBLGF6JB-B4vJ4j8J.js +0 -23
  390. package/dist/chunk-QR6OTTB3-D4wH2ldi.js +0 -3738
  391. package/dist/chunk-R7FJI6CG-Blf8FcmZ.js +0 -64
  392. package/dist/chunk-RYQCIY6F-BWbIlBIH.js +0 -241
  393. package/dist/chunk-U6XO7XAA-COw445DS.js +0 -63
  394. package/dist/chunk-UBXNYLIW-BHigVU4H.js +0 -32
  395. package/dist/chunk-YOTPTUD7-Dn044Q_d.js +0 -30
  396. package/dist/chunk-ZIRB5QZD-BR4TMfOa.js +0 -1153
  397. package/dist/classDiagram-JCYQIIEL-DmXSLxe_.js +0 -30
  398. package/dist/classDiagram-v2-OCEON4UE-CooqVexA.js +0 -30
  399. package/dist/click-outside-container-D_URcm3D.js +0 -167
  400. package/dist/code-block-37QAKDTI-CQrzBOr-.js +0 -107
  401. package/dist/copy-CD7S58CY.js +0 -141
  402. package/dist/cynefin-VYW2F7L2-CeHAxOEX.js +0 -3
  403. package/dist/dagre-VZM6K2ZE-CJggWPTJ.js +0 -328
  404. package/dist/dist-3_o3T78I.js +0 -1360
  405. package/dist/dist-ABQjhuek.js +0 -64
  406. package/dist/dist-CO5R6VMi.js +0 -538
  407. package/dist/dropdown-menu-DhCfcscX.js +0 -5858
  408. package/dist/emotion-is-prop-valid.esm-M57VsT8j.js +0 -14
  409. package/dist/error-banner-CsXbEEjo.js +0 -611
  410. package/dist/eventmodeling-45OFAUF4-B_lWZ-Pd.js +0 -3
  411. package/dist/flowDiagram-UKHOOZJN-g1AmrZzM.js +0 -17
  412. package/dist/gitGraph-TEB2WS4Q-Dj-eXUph.js +0 -3
  413. package/dist/info-DKCQHKI2-Bhb-pe2e.js +0 -3
  414. package/dist/line-CuKjIQa1.js +0 -34
  415. package/dist/map-BJpOfPlL.js +0 -149
  416. package/dist/math-BXtKgYah.js +0 -10
  417. package/dist/mermaid-4DMBBIKO-Ddp9TgNp.js +0 -2
  418. package/dist/mermaid-Bi23Ibnw.js +0 -1173
  419. package/dist/mermaid-parser.core-Din9FvSi.js +0 -99
  420. package/dist/packet-7NZHBO7P-fbkIIyKE.js +0 -3
  421. package/dist/path-BNHuHZP8.js +0 -87
  422. package/dist/pie-RZYD4A2V-CLRIsxY1.js +0 -3
  423. package/dist/purify.es-CB-YO1Hn.js +0 -774
  424. package/dist/radar-I7S5WNFK-BGzCbgXu.js +0 -3
  425. package/dist/railroad-3IZDKUUU-CvQIIcuU.js +0 -3
  426. package/dist/railroad-abnf-AHOZXSZD-CMwtlNtu.js +0 -3
  427. package/dist/railroad-ebnf-EBAXGLYW-n1QUOAsh.js +0 -3
  428. package/dist/railroad-peg-LSFZ7HO6-PjnrpmCs.js +0 -3
  429. package/dist/schemas-DzK6U94N.js +0 -6057
  430. package/dist/stateDiagram-v2-UEYNNEHI-BTRUs8Il.js +0 -30
  431. package/dist/step-CKczO72Q.js +0 -670
  432. package/dist/swimlanesDiagram-ULZ7WXOC-NBmgBl9G.js +0 -31
  433. package/dist/timer-DpDyj9G0.js +0 -596
  434. package/dist/tooltip-Dt77sBeT.js +0 -390
  435. package/dist/treeView-QDETBFTQ-DU8LwHuf.js +0 -3
  436. package/dist/treemap-6X3UGDF4-DUk4-k_O.js +0 -3
  437. package/dist/useTheme-CVJ0UOf2.js +0 -841
  438. package/dist/vega-loader.browser-DEggZzni.js +0 -1083
  439. package/dist/wardley-OPB4EBWU-Db-AaGas.js +0 -3
  440. package/src/components/editor/output/EmotionCacheProvider.tsx +0 -32
@@ -0,0 +1,19 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import { atom } from "jotai";
4
+ import { z } from "zod";
5
+
6
+ export const pairPreviewSchema = z.object({
7
+ command: z.string(),
8
+ templates: z.object({
9
+ prompt: z.string(),
10
+ file: z.string(),
11
+ session: z.string(),
12
+ token_file: z.string(),
13
+ token: z.string(),
14
+ }),
15
+ });
16
+
17
+ export type PairPreviewConfig = z.infer<typeof pairPreviewSchema>;
18
+
19
+ export const pairPreviewAtom = atom<PairPreviewConfig | undefined>(undefined);
@@ -106,6 +106,7 @@ describe("data source connections", () => {
106
106
 
107
107
  let newState = addConnection(connections, state);
108
108
  expect(newState.connectionsMap.size).toBe(defaultConnSize + 2);
109
+ newState = { ...newState, latestEngineSelected: connections[0].name };
109
110
 
110
111
  newState = reducer(newState, {
111
112
  type: "removeDataSourceConnection",
@@ -113,6 +114,7 @@ describe("data source connections", () => {
113
114
  });
114
115
  expect(newState.connectionsMap.size).toBe(defaultConnSize + 1);
115
116
  expect(newState.connectionsMap.has("conn2" as ConnectionName)).toBe(true);
117
+ expect(newState.latestEngineSelected).toBeNull();
116
118
  });
117
119
 
118
120
  it("can clear all connections", () => {
@@ -44,7 +44,8 @@ export interface DataSourceConnection extends Omit<
44
44
  export type ConnectionsMap = ReadonlyMap<ConnectionName, DataSourceConnection>;
45
45
 
46
46
  export interface DataSourceState {
47
- latestEngineSelected: ConnectionName;
47
+ // Null permits automatic selection; DuckDB can also be an explicit choice.
48
+ latestEngineSelected: ConnectionName | null;
48
49
  connectionsMap: ConnectionsMap;
49
50
  }
50
51
 
@@ -110,7 +111,7 @@ function tableSchemaPath(sqlTableContext: SQLTableContext): string[] {
110
111
 
111
112
  function initialState(): DataSourceState {
112
113
  return {
113
- latestEngineSelected: DUCKDB_ENGINE,
114
+ latestEngineSelected: null,
114
115
  connectionsMap: initialConnections,
115
116
  };
116
117
  }
@@ -136,6 +137,8 @@ const {
136
137
  // Backend will dedupe by connection name & keep the latest, so we use this as the key
137
138
  const newMap = new Map(connectionsMap);
138
139
  for (const conn of opts.connections) {
140
+ // Refresh insertion order so automatic selection follows discovery recency.
141
+ newMap.delete(conn.name);
139
142
  newMap.set(conn.name, conn);
140
143
  }
141
144
 
@@ -161,16 +164,17 @@ const {
161
164
  }),
162
165
  );
163
166
  return {
164
- // If the latest engine selected is not in the new map, use the default engine
165
- latestEngineSelected: newMap.has(latestEngineSelected)
166
- ? latestEngineSelected
167
- : DUCKDB_ENGINE,
167
+ // Allow automatic selection again when the selected connection disappears.
168
+ latestEngineSelected:
169
+ latestEngineSelected && newMap.has(latestEngineSelected)
170
+ ? latestEngineSelected
171
+ : null,
168
172
  connectionsMap: newMap,
169
173
  };
170
174
  },
171
175
 
172
176
  clearDataSourceConnections: (): DataSourceState => ({
173
- latestEngineSelected: DUCKDB_ENGINE,
177
+ latestEngineSelected: null,
174
178
  connectionsMap: new Map(),
175
179
  }),
176
180
 
@@ -183,9 +187,10 @@ const {
183
187
  const newMap = new Map(connectionsMap);
184
188
  newMap.delete(connectionName);
185
189
  return {
186
- latestEngineSelected: newMap.has(latestEngineSelected)
187
- ? latestEngineSelected
188
- : DUCKDB_ENGINE,
190
+ latestEngineSelected:
191
+ latestEngineSelected && newMap.has(latestEngineSelected)
192
+ ? latestEngineSelected
193
+ : null,
189
194
  connectionsMap: newMap,
190
195
  };
191
196
  },
@@ -9,7 +9,8 @@ import { useAtomValue, useSetAtom } from "jotai";
9
9
  import { useEffect } from "react";
10
10
  import { NotStartedConnectionAlert } from "@/components/editor/alerts/connecting-alert";
11
11
  import { Controls } from "@/components/editor/controls/Controls";
12
- import { AppHeader } from "@/components/editor/header/app-header";
12
+ import { SandboxController } from "@/components/editor/chrome/panels/sandbox-controller";
13
+ import { ConnectionNotice } from "@/components/editor/alerts/connection-notice";
13
14
  import { FilenameForm } from "@/components/editor/header/filename-form";
14
15
  import { MultiCellActionToolbar } from "@/components/editor/navigation/multi-cell-action-toolbar";
15
16
  import { ViewerBanner } from "@/components/editor/viewer-banner";
@@ -158,6 +159,7 @@ export const EditApp: React.FC<AppProps> = ({
158
159
 
159
160
  return (
160
161
  <>
162
+ <SandboxController onReconnect={reconnect} />
161
163
  <AppContainer
162
164
  connection={connection}
163
165
  isRunning={isRunning}
@@ -165,10 +167,9 @@ export const EditApp: React.FC<AppProps> = ({
165
167
  onReconnect={reconnect}
166
168
  >
167
169
  <ViewerBanner />
168
- <AppHeader
169
- connection={connection}
170
+ <div
170
171
  className={cn(
171
- "pt-4 sm:pt-12 pb-2 mb-4 print:hidden z-50",
172
+ "pt-4 sm:pt-12 pb-6 print:hidden z-50",
172
173
  // Keep the header sticky when scrolling horizontally, for column mode
173
174
  "sticky left-0",
174
175
  )}
@@ -178,7 +179,9 @@ export const EditApp: React.FC<AppProps> = ({
178
179
  <FilenameForm filename={filename} />
179
180
  </div>
180
181
  )}
181
- </AppHeader>
182
+ </div>
183
+
184
+ <ConnectionNotice appConfig={appConfig} onRetry={reconnect} />
182
185
 
183
186
  {/* Don't render until we have a single cell. NotStartedConnectionAlert
184
187
  still covers the "no remote runtime started" prompt. */}
@@ -7,8 +7,7 @@ import { generateUUID } from "@/utils/uuid";
7
7
  import type { Banner } from "../kernel/messages";
8
8
 
9
9
  /**
10
- * Atom for storing kernel startup error message.
11
- * When set to a non-null value, shows a modal with the error details.
10
+ * Full startup diagnostics, retained until a new connection attempt or readiness.
12
11
  */
13
12
  export const kernelStartupErrorAtom = atom<string | null>(null);
14
13
 
@@ -552,12 +552,7 @@ describe("useEnrichCellOutputs", () => {
552
552
  // Verify the exact return type structure
553
553
  expect(output).toHaveProperty(cid);
554
554
  const cellOutput = output[cid];
555
- expect(cellOutput).toBeDefined();
556
- expect(Array.isArray(cellOutput)).toBe(true);
557
- if (cellOutput) {
558
- expect(cellOutput[0]).toBe("image/png");
559
- expect(cellOutput[1]).toBe(mockDataUrl);
560
- }
555
+ expect(cellOutput).toEqual(["image/png", mockDataUrl]);
561
556
  });
562
557
  });
563
558
 
@@ -181,7 +181,8 @@ function handleMessage(
181
181
  // Unsupported operations in islands mode
182
182
  case "banner":
183
183
  case "missing-package-alert":
184
- case "installing-package-alert":
184
+ case "environment-operation":
185
+ case "environment-state":
185
186
  case "completion-result":
186
187
  case "reload":
187
188
  case "focus-cell":
@@ -201,6 +202,7 @@ function handleMessage(
201
202
  case "storage-download-ready":
202
203
  case "secret-keys-result":
203
204
  case "startup-logs":
205
+ case "startup-progress":
204
206
  case "interrupted":
205
207
  case "reconnected":
206
208
  case "cache-cleared":
@@ -370,6 +370,9 @@ export class IslandsPyodideBridge implements RunRequests, EditRequests {
370
370
  addPackage = throwNotImplemented;
371
371
  removePackage = throwNotImplemented;
372
372
  getPackageList = throwNotImplemented;
373
+ getSandbox = throwNotImplemented;
374
+ updateManifest = throwNotImplemented;
375
+ syncSandbox = throwNotImplemented;
373
376
  getDependencyTree = throwNotImplemented;
374
377
  getRecentFiles = throwNotImplemented;
375
378
  getWorkspaceFiles = throwNotImplemented;
@@ -1,5 +1,6 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
+ import { createModuleWorker } from "@/utils/worker";
3
4
  import { getMarimoVersion } from "../meta/globals";
4
5
  import workerUrl from "./worker/worker.tsx?worker&url";
5
6
 
@@ -47,20 +48,9 @@ export class DefaultWorkerFactory implements WorkerFactory {
47
48
  * Creates a new Pyodide worker
48
49
  */
49
50
  create(): Worker {
50
- const js = `import ${JSON.stringify(new URL(this.url, import.meta.url))}`;
51
- const blob = new Blob([js], { type: "application/javascript" });
52
- const objURL = URL.createObjectURL(blob);
53
-
54
- const worker = new Worker(objURL, {
55
- type: "module",
56
- /* @vite-ignore */
51
+ return createModuleWorker(new URL(this.url, import.meta.url), {
57
52
  name: this.name,
58
53
  });
59
-
60
- // Blob URL can be revoked once the worker has loaded the script
61
- URL.revokeObjectURL(objURL);
62
-
63
- return worker;
64
54
  }
65
55
 
66
56
  /**
@@ -36,8 +36,8 @@ export type CompletionResultMessage =
36
36
  export type HumanReadableStatus = schemas["HumanReadableStatus"];
37
37
  export type FunctionCallResultMessage =
38
38
  NotificationMessageData<"function-call-result">;
39
- export type PackageInstallationStatus =
40
- schemas["InstallingPackageAlertNotification"]["packages"];
39
+ export type PackageOperationStatus =
40
+ schemas["EnvironmentOperationNotification"]["packages"];
41
41
  export type DataColumnPreview = NotificationMessageData<"data-column-preview">;
42
42
  export type SQLTablePreview = NotificationMessageData<"sql-table-preview">;
43
43
  export type SQLTableListPreview =
@@ -69,9 +69,10 @@ describe("createNetworkRequests", () => {
69
69
  const methodNames = Object.keys(requests);
70
70
 
71
71
  for (const methodName of methodNames) {
72
- if (!ACTIONS[methodName as keyof typeof ACTIONS]) {
73
- expect.fail(`Method ${methodName} has no action defined`);
74
- }
72
+ expect(
73
+ ACTIONS[methodName as keyof typeof ACTIONS],
74
+ `Method ${methodName} has no action defined`,
75
+ ).toBeDefined();
75
76
  }
76
77
  });
77
78
 
@@ -0,0 +1,117 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+ import { atom } from "jotai";
3
+ import { kernelStartupErrorAtom } from "@/core/errors/state";
4
+ import { sandboxAtom, sandboxSyncAtom } from "@/core/packages/sandbox-state";
5
+ import {
6
+ type ConnectionPhase,
7
+ WebSocketClosedReason,
8
+ WebSocketState,
9
+ } from "@/core/websocket/types";
10
+ import { connectionAtom } from "./connection";
11
+
12
+ export interface ConnectionNotice {
13
+ kind: "startup" | "sync" | "connection";
14
+ phase?: ConnectionPhase;
15
+ sandbox: boolean;
16
+ title: string;
17
+ description: string;
18
+ pending: boolean;
19
+ error: string | null;
20
+ }
21
+
22
+ export const connectionNoticeAtom = atom<ConnectionNotice | null>((get) => {
23
+ const connection = get(connectionAtom);
24
+ const backend = get(sandboxAtom)?.backend;
25
+ const sandbox = Boolean(backend);
26
+ const sync = get(sandboxSyncAtom);
27
+ const syncing = sync.kind === "running";
28
+ const restartRequired = sync.kind === "restart-required";
29
+ const syncError =
30
+ sync.kind === "failed"
31
+ ? sync.error
32
+ : sync.kind === "cancelled"
33
+ ? "Sandbox sync was interrupted."
34
+ : restartRequired
35
+ ? sync.reason
36
+ : null;
37
+ if (
38
+ sandbox &&
39
+ (syncing || syncError !== null) &&
40
+ connection.state === WebSocketState.OPEN
41
+ ) {
42
+ return {
43
+ kind: "sync",
44
+ sandbox,
45
+ title: syncing
46
+ ? "Syncing sandbox…"
47
+ : restartRequired
48
+ ? "Sandbox restart required"
49
+ : "Sandbox sync failed",
50
+ description: syncing
51
+ ? "Applying the saved manifest to this notebook’s environment."
52
+ : restartRequired
53
+ ? "Restart the kernel to use the updated environment."
54
+ : "Review the error details, then try again.",
55
+ pending: syncing,
56
+ error: syncError,
57
+ };
58
+ }
59
+ if (connection.state === WebSocketState.CONNECTING) {
60
+ const messages = {
61
+ "preparing-environment": {
62
+ title: "Preparing environment…",
63
+ description:
64
+ "Getting this notebook’s Python environment ready. The first start can take a few minutes.",
65
+ },
66
+ "starting-kernel": {
67
+ title: "Starting kernel…",
68
+ description:
69
+ "The environment is prepared. Waiting for the Python kernel to connect to this notebook.",
70
+ },
71
+ reconnecting: {
72
+ title: "Reconnecting…",
73
+ description:
74
+ "The connection was interrupted. Your notebook and existing outputs stay visible while the kernel reconnects.",
75
+ },
76
+ };
77
+ return {
78
+ kind: connection.phase === "reconnecting" ? "connection" : "startup",
79
+ phase: connection.phase,
80
+ sandbox,
81
+ ...(connection.phase
82
+ ? messages[connection.phase]
83
+ : {
84
+ title: "Connecting…",
85
+ description: "Waiting for the notebook’s kernel to connect.",
86
+ }),
87
+ pending: true,
88
+ error: null,
89
+ };
90
+ }
91
+ if (connection.state === WebSocketState.CLOSED) {
92
+ const startupFailed =
93
+ connection.code === WebSocketClosedReason.KERNEL_STARTUP_ERROR;
94
+ const environmentFailed =
95
+ startupFailed && connection.phase === "preparing-environment";
96
+ return {
97
+ kind: startupFailed ? "startup" : "connection",
98
+ phase: connection.phase,
99
+ sandbox,
100
+ title: environmentFailed
101
+ ? "Sandbox setup failed"
102
+ : startupFailed
103
+ ? "Kernel failed to start"
104
+ : connection.reason,
105
+ description: environmentFailed
106
+ ? "The notebook can’t run yet."
107
+ : startupFailed
108
+ ? "The Python kernel could not start. Check the error details, then try again."
109
+ : "The connection to the notebook’s kernel was lost.",
110
+ pending: false,
111
+ error: startupFailed
112
+ ? (get(kernelStartupErrorAtom) ?? connection.reason)
113
+ : null,
114
+ };
115
+ }
116
+ return null;
117
+ });
@@ -1,5 +1,7 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
  import { atom } from "jotai";
3
+ import { atomWithReducer } from "jotai/utils";
4
+ import type { NotificationMessageData } from "../kernel/messages";
3
5
  import { isNotebookPage } from "../mode";
4
6
  import { waitFor } from "../state/jotai";
5
7
  import { type ConnectionStatus, WebSocketState } from "../websocket/types";
@@ -12,6 +14,23 @@ export const connectionAtom = atom<ConnectionStatus>({
12
14
  state: WebSocketState.NOT_STARTED,
13
15
  });
14
16
 
17
+ type StartupProgress = NotificationMessageData<"startup-progress">;
18
+
19
+ export const startupProgressAtom = atomWithReducer<
20
+ Pick<StartupProgress, "phase" | "logs"> | null,
21
+ StartupProgress | null
22
+ >(null, (previous, update: StartupProgress | null) =>
23
+ update === null
24
+ ? null
25
+ : {
26
+ phase: update.phase,
27
+ logs:
28
+ update.log_mode === "append" && previous?.phase === update.phase
29
+ ? previous.logs + update.logs
30
+ : update.logs,
31
+ },
32
+ );
33
+
15
34
  export function waitForConnectionOpen() {
16
35
  return waitFor(connectionAtom, (value) => {
17
36
  return value.state === WebSocketState.OPEN;
@@ -93,6 +93,9 @@ const ACTIONS: Record<keyof AllRequests, Action> = {
93
93
  saveUserConfig: "throwError",
94
94
  sendShutdown: "throwError",
95
95
  getPackageList: "throwError",
96
+ getSandbox: "serverOnly",
97
+ updateManifest: "serverOnly",
98
+ syncSandbox: "serverOnly",
96
99
  getDependencyTree: "throwError",
97
100
  addPackage: "throwError",
98
101
  removePackage: "throwError",
@@ -532,6 +532,18 @@ export function createNetworkRequests(): EditRequests & RunRequests {
532
532
  })
533
533
  .then(handleResponseReturnNull);
534
534
  },
535
+ getSandbox: (request) =>
536
+ getClient()
537
+ .POST("/api/packages/sandbox", { body: request, params: getParams() })
538
+ .then(handleResponse),
539
+ updateManifest: (request) =>
540
+ getClient()
541
+ .POST("/api/packages/manifest", { body: request, params: getParams() })
542
+ .then(handleResponse),
543
+ syncSandbox: (request) =>
544
+ getClient()
545
+ .POST("/api/packages/sync", { body: request, params: getParams() })
546
+ .then(handleResponse),
535
547
  addPackage: (request) => {
536
548
  return getClient()
537
549
  .POST("/api/packages/add", {
@@ -98,6 +98,9 @@ export function createStaticRequests(): EditRequests & RunRequests {
98
98
  addPackage: throwNotInEditMode,
99
99
  removePackage: throwNotInEditMode,
100
100
  getPackageList: throwNotInEditMode,
101
+ getSandbox: throwNotInEditMode,
102
+ updateManifest: throwNotInEditMode,
103
+ syncSandbox: throwNotInEditMode,
101
104
  getDependencyTree: throwNotInEditMode,
102
105
  listSecretKeys: throwNotInEditMode,
103
106
  writeSecret: throwNotInEditMode,
@@ -79,6 +79,9 @@ export function createErrorToastingRequests(
79
79
  addPackage: "Failed to add package",
80
80
  removePackage: "Failed to remove package",
81
81
  getPackageList: "Failed to get package list",
82
+ getSandbox: "",
83
+ updateManifest: "",
84
+ syncSandbox: "",
82
85
  getDependencyTree: "Failed to get dependency tree",
83
86
  listSecretKeys: "Failed to fetch secrets",
84
87
  writeSecret: "Failed to write secret",
@@ -1,4 +1,5 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
+ import { withPackageInvalidation } from "../packages/package-data";
2
3
  import { getRuntimeManager } from "../runtime/config";
3
4
  import { isStaticNotebook } from "../static/static-state";
4
5
  import { PyodideBridge } from "../wasm/bridge";
@@ -20,5 +21,5 @@ export function resolveRequestClient(): EditRequests & RunRequests {
20
21
  getRuntimeManager(),
21
22
  );
22
23
  }
23
- return createErrorToastingRequests(base);
24
+ return withPackageInvalidation(createErrorToastingRequests(base));
24
25
  }
@@ -69,6 +69,10 @@ export type ListPackagesResponse = schemas["ListPackagesResponse"];
69
69
  export type DependencyTreeResponse = schemas["DependencyTreeResponse"];
70
70
  export type DependencyTreeNode = schemas["DependencyTreeNode"];
71
71
 
72
+ export type SandboxRequest = schemas["SandboxRequest"];
73
+ export type SandboxResponse = schemas["SandboxResponse"];
74
+ export type UpdateManifestRequest = schemas["UpdateManifestRequest"];
75
+ export type SyncSandboxResponse = schemas["SyncSandboxResponse"];
72
76
  export type PackageOperationResponse = schemas["PackageOperationResponse"];
73
77
  export type InstantiateNotebookRequest = schemas["InstantiateNotebookRequest"];
74
78
  export type MarimoConfig = schemas["MarimoConfig"];
@@ -246,6 +250,9 @@ export interface EditRequests {
246
250
  autoExportAsMarkdown: (request: AutoExportAsMarkdownRequest) => Promise<null>;
247
251
  autoExportAsIPYNB: (request: AutoExportAsIPYNBRequest) => Promise<null>;
248
252
  updateCellOutputs: (request: UpdateCellOutputsRequest) => Promise<null>;
253
+ getSandbox: (request: SandboxRequest) => Promise<SandboxResponse>;
254
+ updateManifest: (request: UpdateManifestRequest) => Promise<SandboxResponse>;
255
+ syncSandbox: (request: SandboxRequest) => Promise<SyncSandboxResponse>;
249
256
  // Package requests
250
257
  getPackageList: () => Promise<ListPackagesResponse>;
251
258
  getDependencyTree: () => Promise<DependencyTreeResponse>;
@@ -0,0 +1,53 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+ import { useAtomValue } from "jotai";
3
+ import { useEffect, useState } from "react";
4
+ import { useDelayElapsed } from "@/hooks/useDelayElapsed";
5
+ import { isConnectedAtom } from "./connection";
6
+ import {
7
+ type ConnectionNotice,
8
+ connectionNoticeAtom,
9
+ } from "./connection-notice";
10
+
11
+ export type DisplayConnectionNotice = ConnectionNotice & { ready: boolean };
12
+
13
+ /** Briefly acknowledge completion, but only for setup the user actually saw. */
14
+ export function useConnectionNotice(
15
+ delayMs = 500,
16
+ ): DisplayConnectionNotice | null {
17
+ const notice = useAtomValue(connectionNoticeAtom);
18
+ const connected = useAtomValue(isConnectedAtom);
19
+ const elapsed = useDelayElapsed(notice?.pending ? delayMs : 0);
20
+ const [previous, setPrevious] = useState<ConnectionNotice | null>(null);
21
+
22
+ useEffect(() => {
23
+ if (notice || !connected) {
24
+ setPrevious(elapsed ? notice : null);
25
+ return;
26
+ }
27
+ const timeout = setTimeout(() => setPrevious(null), 1500);
28
+ return () => clearTimeout(timeout);
29
+ }, [notice, connected, elapsed]);
30
+
31
+ if (notice) {
32
+ return elapsed ? { ...notice, ready: false } : null;
33
+ }
34
+ if (
35
+ connected &&
36
+ previous?.pending &&
37
+ previous.sandbox &&
38
+ previous.kind !== "connection"
39
+ ) {
40
+ return {
41
+ ...previous,
42
+ pending: false,
43
+ ready: true,
44
+ title:
45
+ previous.kind === "sync"
46
+ ? "Environment synced"
47
+ : "Your notebook is ready",
48
+ description: "The notebook is ready to run.",
49
+ error: null,
50
+ };
51
+ }
52
+ return null;
53
+ }