@marimo-team/islands 0.24.3-dev5 → 0.24.3-dev52

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 (384) hide show
  1. package/dist/{ConnectedDataExplorerComponent-C9OF_75w.js → ConnectedDataExplorerComponent-KVhjDMSe.js} +1066 -1066
  2. package/dist/ErrorBoundary-Bfp74qVG.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-BajL8aoc.js +1 -0
  12. package/dist/assets/worker-BemUy60C.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-BhNoIBSU.js → cells-BSgNCBZ8.js} +6740 -10126
  18. package/dist/{channel-CyiYUzJv.js → channel-B5XnTarr.js} +1 -1
  19. package/dist/chat-ui-CygzVJ9s.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-qtEE1_Zi.js +138 -0
  46. package/dist/{common-xHoep60C.js → common-BmP252R5.js} +8839 -12646
  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-DtaTjDfe.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-iJn-Nryx.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-D_YQdd5e.js +380 -0
  99. package/dist/flowDiagram-HODETNUW-6dMdB8pR.js +16 -0
  100. package/dist/{formats-CJMVUfb3.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-CV4eSJ7N.js} +2143 -1910
  105. package/dist/{glide-utils-NShAPPtn.js → glide-utils-B3rUT5PI.js} +15 -15
  106. package/dist/globals-DdrpcXQY.js +19 -0
  107. package/dist/highlighted-body-KPVGNVTW-Ad3MKZ18.js +38 -0
  108. package/dist/html-to-image-kpuRfdfZ.js +3253 -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 +8105 -13485
  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-DXWRr4gK.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-CpK6fX_C.js → process-output-DFe2tVIY.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-DwuC-61O.js → reveal-component-DLxDt6wQ.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-D-Rx3ux5.js → toDate-WXg1yLcI.js} +10 -9
  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-CPehZbUb.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__/requests.ts +7 -0
  185. package/src/__tests__/__snapshots__/CellStatus.test.tsx.snap +12 -12
  186. package/src/__tests__/fixtures/pair-preview.ts +19 -0
  187. package/src/__tests__/mount.test.ts +18 -0
  188. package/src/components/chat/acp/__tests__/agent-panel.test.tsx +270 -0
  189. package/src/components/chat/acp/agent-panel.tsx +45 -44
  190. package/src/components/data-table/column-explorer-panel/column-explorer.tsx +2 -6
  191. package/src/components/data-table/column-summary/chart-spec-model.tsx +1 -1
  192. package/src/components/data-table/columns.tsx +64 -67
  193. package/src/components/editor/RecoveryButton.tsx +1 -0
  194. package/src/components/editor/__tests__/dynamic-favicon.test.tsx +36 -2
  195. package/src/components/editor/actions/__tests__/pair-with-agent-commands.test.ts +115 -0
  196. package/src/components/editor/actions/__tests__/pair-with-agent-modal.test.tsx +218 -0
  197. package/src/components/editor/actions/pair-with-agent-commands.ts +46 -9
  198. package/src/components/editor/actions/pair-with-agent-modal.tsx +49 -23
  199. package/src/components/editor/ai/add-cell-with-ai.tsx +1 -0
  200. package/src/components/editor/ai/ai-completion-editor.tsx +3 -1
  201. package/src/components/editor/alerts/connecting-alert.tsx +1 -66
  202. package/src/components/editor/alerts/connection-notice.tsx +140 -0
  203. package/src/components/editor/app-container.tsx +9 -3
  204. package/src/components/editor/boundary/ErrorBoundary.tsx +38 -16
  205. package/src/components/editor/boundary/__tests__/ErrorBoundary.test.tsx +311 -0
  206. package/src/components/editor/cell/code/__tests__/rtc-editor-config.test.ts +50 -0
  207. package/src/components/editor/cell/code/cell-editor.tsx +41 -42
  208. package/src/components/editor/chrome/components/__tests__/feedback-button.test.tsx +94 -0
  209. package/src/components/editor/chrome/components/feedback-button.tsx +63 -42
  210. package/src/components/editor/chrome/panels/__tests__/packages-panel.test.tsx +114 -7
  211. package/src/components/editor/chrome/panels/__tests__/sandbox-recovery.test.tsx +165 -0
  212. package/src/components/editor/chrome/panels/packages-panel.tsx +93 -166
  213. package/src/components/editor/chrome/panels/sandbox-controller.tsx +106 -0
  214. package/src/components/editor/chrome/panels/sandbox-panel.tsx +173 -0
  215. package/src/components/editor/chrome/wrapper/footer-items/backend-status.tsx +3 -1
  216. package/src/components/editor/code/__tests__/readonly-diff.test.tsx +65 -0
  217. package/src/components/editor/code/readonly-diff.tsx +1 -1
  218. package/src/components/editor/connections/database/__tests__/__snapshots__/as-code.test.ts.snap +98 -98
  219. package/src/components/editor/connections/database/__tests__/as-code.test.ts +11 -5
  220. package/src/components/editor/dynamic-favicon.tsx +17 -10
  221. package/src/components/editor/file-tree/__tests__/tree-actions.test.tsx +54 -0
  222. package/src/components/editor/file-tree/tree-actions.tsx +11 -14
  223. package/src/components/editor/header/__tests__/status.test.tsx +8 -20
  224. package/src/components/editor/header/filename-input.tsx +2 -0
  225. package/src/components/editor/header/status.tsx +5 -3
  226. package/src/components/editor/notebook-cell.tsx +4 -2
  227. package/src/components/editor/output/JsonOutput.tsx +182 -632
  228. package/src/components/editor/output/Outputs.css +50 -17
  229. package/src/components/editor/output/__tests__/JsonOutput-interactions.test.tsx +254 -0
  230. package/src/components/editor/output/__tests__/JsonOutput-mimetype.test.tsx +41 -46
  231. package/src/components/editor/output/__tests__/{json-output.test.ts → json-output-formatting.test.ts} +113 -75
  232. package/src/components/editor/output/__tests__/json-output-pagination.test.ts +252 -0
  233. package/src/components/editor/output/json-output/formatting.ts +167 -0
  234. package/src/components/editor/output/json-output/pagination.ts +155 -0
  235. package/src/components/editor/output/json-output/renderers.tsx +196 -0
  236. package/src/components/editor/output/json-output/themes.ts +52 -0
  237. package/src/components/editor/renderers/cell-array.tsx +1 -5
  238. package/src/components/home/components.tsx +17 -0
  239. package/src/components/pages/gallery-page.tsx +2 -4
  240. package/src/components/pages/home-page.tsx +2 -4
  241. package/src/components/slides/slide-form.tsx +1 -0
  242. package/src/components/slides/slide-notes-editor.tsx +1 -0
  243. package/src/components/terminal/terminal.tsx +4 -4
  244. package/src/components/tracing/tracing-spec.ts +1 -1
  245. package/src/components/ui/table.tsx +1 -1
  246. package/src/components/ui/use-toast.ts +8 -0
  247. package/src/core/MarimoApp.tsx +0 -2
  248. package/src/core/cells/__tests__/__snapshots__/cells.test.ts.snap +259 -259
  249. package/src/core/cells/__tests__/cell.test.ts +61 -0
  250. package/src/core/cells/__tests__/cells.test.ts +37 -37
  251. package/src/core/cells/cell.ts +9 -1
  252. package/src/core/cells/pending-delete-service.ts +12 -16
  253. package/src/core/codemirror/language/__tests__/sql.test.ts +70 -2
  254. package/src/core/codemirror/language/languages/sql/sql.ts +16 -1
  255. package/src/core/codemirror/rtc/extension.ts +5 -2
  256. package/src/core/config/pair.ts +19 -0
  257. package/src/core/datasets/__tests__/data-source.test.ts +2 -0
  258. package/src/core/datasets/data-source-connections.ts +15 -10
  259. package/src/core/edit-app.tsx +8 -5
  260. package/src/core/errors/state.ts +1 -2
  261. package/src/core/islands/__tests__/parse.test.ts +140 -7
  262. package/src/core/islands/bootstrap.ts +1 -0
  263. package/src/core/islands/bridge.ts +3 -0
  264. package/src/core/islands/parse.ts +20 -0
  265. package/src/core/network/connection-notice.ts +84 -0
  266. package/src/core/network/requests-lazy.ts +3 -0
  267. package/src/core/network/requests-network.ts +12 -0
  268. package/src/core/network/requests-static.ts +3 -0
  269. package/src/core/network/requests-toasting.tsx +3 -0
  270. package/src/core/network/resolve.ts +2 -1
  271. package/src/core/network/types.ts +7 -0
  272. package/src/core/packages/__tests__/usePackageAction.test.tsx +129 -0
  273. package/src/core/packages/__tests__/useSandboxController.test.tsx +165 -0
  274. package/src/core/packages/package-data.ts +35 -0
  275. package/src/core/packages/sandbox-state.ts +15 -0
  276. package/src/core/packages/toast-components.tsx +11 -0
  277. package/src/core/packages/useInstallPackage.ts +1 -1
  278. package/src/core/packages/usePackageAction.ts +51 -0
  279. package/src/core/packages/usePackageDependencies.ts +22 -0
  280. package/src/core/packages/useSandboxController.ts +188 -0
  281. package/src/core/run-app.tsx +2 -0
  282. package/src/core/runtime/__tests__/runtime.test.ts +11 -0
  283. package/src/core/runtime/runtime.ts +7 -2
  284. package/src/core/wasm/bridge.ts +11 -0
  285. package/src/core/websocket/__tests__/useMarimoKernelConnection.hook.test.tsx +212 -2
  286. package/src/core/websocket/transports/transport.ts +1 -1
  287. package/src/core/websocket/transports/ws.ts +1 -1
  288. package/src/core/websocket/types.ts +11 -1
  289. package/src/core/websocket/useMarimoKernelConnection.tsx +43 -8
  290. package/src/css/app/Cell.css +2 -0
  291. package/src/hooks/useDebounce.ts +2 -0
  292. package/src/mount.tsx +3 -0
  293. package/src/plugins/core/BadPlugin.tsx +3 -14
  294. package/src/plugins/core/RenderHTML.tsx +22 -2
  295. package/src/plugins/core/__test__/RenderHTML.test.ts +187 -0
  296. package/src/plugins/core/registerReactComponent.tsx +0 -1
  297. package/src/plugins/impl/FormPlugin.tsx +2 -0
  298. package/src/plugins/impl/MatrixPlugin.tsx +2 -0
  299. package/src/plugins/impl/RangeSliderPlugin.tsx +2 -0
  300. package/src/plugins/impl/SliderPlugin.tsx +2 -0
  301. package/src/plugins/impl/data-editor/__tests__/glide-data-editor.test.tsx +23 -18
  302. package/src/plugins/impl/data-frames/panel.tsx +1 -0
  303. package/src/plugins/impl/image-comparison/ImageComparisonComponent.tsx +1 -1
  304. package/src/plugins/impl/image-comparison/__tests__/ImageComparisonComponent.test.tsx +15 -0
  305. package/src/plugins/layout/AccordionPlugin.tsx +7 -2
  306. package/src/plugins/layout/JsonOutputPlugin.tsx +7 -10
  307. package/src/plugins/layout/__test__/AccordionPlugin.test.tsx +66 -0
  308. package/src/stories/sandbox.stories.tsx +308 -0
  309. package/dist/ErrorBoundary-CR-ZQN_c.js +0 -125
  310. package/dist/_baseMerge-Dv8bBloN.js +0 -73
  311. package/dist/_initCloneObject---vediN2.js +0 -95
  312. package/dist/arc-DOVLrCPd.js +0 -82
  313. package/dist/architecture-TIHT7OUA-MiJpPpQW.js +0 -3
  314. package/dist/array-CApNbSU9.js +0 -6
  315. package/dist/assets/__vite-browser-external-BdKGjRZ4.js +0 -1
  316. package/dist/assets/worker-DlIBfp9S.js +0 -98
  317. package/dist/blockDiagram-VBNYF7ZC-Bc--I65C.js +0 -3158
  318. package/dist/chat-ui-DjTMZRVP.js +0 -8455
  319. package/dist/chunk-3NCLNEKW-BIp_lB_4.js +0 -14
  320. package/dist/chunk-5FCAYU7R-C_HO9A1J.js +0 -23
  321. package/dist/chunk-5HE753X5-Bixm_MV-.js +0 -38
  322. package/dist/chunk-5JV3BV7I-CH5J3iZY.js +0 -54
  323. package/dist/chunk-5TONJI2A-DG6gDiSS.js +0 -62
  324. package/dist/chunk-7BUUIJ7U-5afmIPeo.js +0 -82
  325. package/dist/chunk-BIQX33UG-7TMBUf89.js +0 -23
  326. package/dist/chunk-CQNSW5MT-Cnqqsxt-.js +0 -38
  327. package/dist/chunk-CYSBUYHQ-BAbymFHR.js +0 -23
  328. package/dist/chunk-EMLP6XTP-Bsz-QL77.js +0 -23
  329. package/dist/chunk-J7OUQ5F2-CM_meqZH.js +0 -57
  330. package/dist/chunk-JG7HCLWE-DUnCDgPk.js +0 -62
  331. package/dist/chunk-MOZMSUNE-BG6IHvzT.js +0 -35
  332. package/dist/chunk-OSBZ3O6U-CYwj_bvR.js +0 -23
  333. package/dist/chunk-QBLGF6JB-B4vJ4j8J.js +0 -23
  334. package/dist/chunk-QR6OTTB3-D4wH2ldi.js +0 -3738
  335. package/dist/chunk-R7FJI6CG-Blf8FcmZ.js +0 -64
  336. package/dist/chunk-RYQCIY6F-BWbIlBIH.js +0 -241
  337. package/dist/chunk-U6XO7XAA-COw445DS.js +0 -63
  338. package/dist/chunk-UBXNYLIW-BHigVU4H.js +0 -32
  339. package/dist/chunk-YOTPTUD7-Dn044Q_d.js +0 -30
  340. package/dist/chunk-ZIRB5QZD-BR4TMfOa.js +0 -1153
  341. package/dist/classDiagram-JCYQIIEL-DmXSLxe_.js +0 -30
  342. package/dist/classDiagram-v2-OCEON4UE-CooqVexA.js +0 -30
  343. package/dist/click-outside-container-D_URcm3D.js +0 -167
  344. package/dist/code-block-37QAKDTI-CQrzBOr-.js +0 -107
  345. package/dist/copy-CD7S58CY.js +0 -141
  346. package/dist/cynefin-VYW2F7L2-CeHAxOEX.js +0 -3
  347. package/dist/dagre-VZM6K2ZE-CJggWPTJ.js +0 -328
  348. package/dist/dist-3_o3T78I.js +0 -1360
  349. package/dist/dist-ABQjhuek.js +0 -64
  350. package/dist/dist-CO5R6VMi.js +0 -538
  351. package/dist/dropdown-menu-DhCfcscX.js +0 -5858
  352. package/dist/emotion-is-prop-valid.esm-M57VsT8j.js +0 -14
  353. package/dist/error-banner-CsXbEEjo.js +0 -611
  354. package/dist/eventmodeling-45OFAUF4-B_lWZ-Pd.js +0 -3
  355. package/dist/flowDiagram-UKHOOZJN-g1AmrZzM.js +0 -17
  356. package/dist/gitGraph-TEB2WS4Q-Dj-eXUph.js +0 -3
  357. package/dist/info-DKCQHKI2-Bhb-pe2e.js +0 -3
  358. package/dist/line-CuKjIQa1.js +0 -34
  359. package/dist/map-BJpOfPlL.js +0 -149
  360. package/dist/math-BXtKgYah.js +0 -10
  361. package/dist/mermaid-4DMBBIKO-Ddp9TgNp.js +0 -2
  362. package/dist/mermaid-Bi23Ibnw.js +0 -1173
  363. package/dist/mermaid-parser.core-Din9FvSi.js +0 -99
  364. package/dist/packet-7NZHBO7P-fbkIIyKE.js +0 -3
  365. package/dist/path-BNHuHZP8.js +0 -87
  366. package/dist/pie-RZYD4A2V-CLRIsxY1.js +0 -3
  367. package/dist/purify.es-CB-YO1Hn.js +0 -774
  368. package/dist/radar-I7S5WNFK-BGzCbgXu.js +0 -3
  369. package/dist/railroad-3IZDKUUU-CvQIIcuU.js +0 -3
  370. package/dist/railroad-abnf-AHOZXSZD-CMwtlNtu.js +0 -3
  371. package/dist/railroad-ebnf-EBAXGLYW-n1QUOAsh.js +0 -3
  372. package/dist/railroad-peg-LSFZ7HO6-PjnrpmCs.js +0 -3
  373. package/dist/schemas-DzK6U94N.js +0 -6057
  374. package/dist/stateDiagram-v2-UEYNNEHI-BTRUs8Il.js +0 -30
  375. package/dist/step-CKczO72Q.js +0 -670
  376. package/dist/swimlanesDiagram-ULZ7WXOC-NBmgBl9G.js +0 -31
  377. package/dist/timer-DpDyj9G0.js +0 -596
  378. package/dist/tooltip-Dt77sBeT.js +0 -390
  379. package/dist/treeView-QDETBFTQ-DU8LwHuf.js +0 -3
  380. package/dist/treemap-6X3UGDF4-DUk4-k_O.js +0 -3
  381. package/dist/useTheme-CVJ0UOf2.js +0 -841
  382. package/dist/vega-loader.browser-DEggZzni.js +0 -1083
  383. package/dist/wardley-OPB4EBWU-Db-AaGas.js +0 -3
  384. package/src/components/editor/output/EmotionCacheProvider.tsx +0 -32
@@ -0,0 +1,218 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import {
4
+ act,
5
+ fireEvent,
6
+ render,
7
+ screen,
8
+ waitFor,
9
+ within,
10
+ } from "@testing-library/react";
11
+ import { Provider } from "jotai";
12
+ import type React from "react";
13
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
14
+ import { PAIR_PREVIEW } from "@/__tests__/fixtures/pair-preview";
15
+ import { Dialog } from "@/components/ui/dialog";
16
+ import { TooltipProvider } from "@/components/ui/tooltip";
17
+ import { pairPreviewAtom } from "@/core/config/pair";
18
+ import { getSessionId } from "@/core/kernel/session";
19
+ import { filenameAtom } from "@/core/saving/file-state";
20
+ import {
21
+ DEFAULT_RUNTIME_CONFIG,
22
+ runtimeConfigAtom,
23
+ } from "@/core/runtime/config";
24
+ import { store } from "@/core/state/jotai";
25
+ import { PairWithAgentModal } from "../pair-with-agent-modal";
26
+ import { copyToClipboard } from "@/utils/copy";
27
+
28
+ vi.mock("@/utils/copy", () => ({
29
+ copyToClipboard: vi.fn().mockResolvedValue(undefined),
30
+ }));
31
+
32
+ function wrapper({ children }: { children: React.ReactNode }) {
33
+ return (
34
+ <Provider store={store}>
35
+ <TooltipProvider>
36
+ <Dialog open={true}>{children}</Dialog>
37
+ </TooltipProvider>
38
+ </Provider>
39
+ );
40
+ }
41
+
42
+ describe("PairWithAgentModal", () => {
43
+ beforeEach(() => {
44
+ vi.clearAllMocks();
45
+ store.set(pairPreviewAtom, PAIR_PREVIEW);
46
+ store.set(filenameAtom, "/project/my notebook.py");
47
+ store.set(runtimeConfigAtom, {
48
+ ...DEFAULT_RUNTIME_CONFIG,
49
+ url: "http://localhost:8000",
50
+ });
51
+ window.history.replaceState({}, "", "/?file=notebook.py");
52
+ vi.stubGlobal(
53
+ "fetch",
54
+ vi.fn().mockResolvedValue(new Response(JSON.stringify({ token: null }))),
55
+ );
56
+ });
57
+
58
+ afterEach(() => {
59
+ store.set(pairPreviewAtom, undefined);
60
+ store.set(filenameAtom, null);
61
+ vi.unstubAllGlobals();
62
+ });
63
+
64
+ it.each(["Claude", "Codex", "OpenCode", "Prompt"])(
65
+ "omits skill installation and includes the current session in %s preview",
66
+ async (tab) => {
67
+ await act(async () => {
68
+ render(<PairWithAgentModal onClose={vi.fn()} />, { wrapper });
69
+ });
70
+ fireEvent.mouseDown(screen.getByRole("tab", { name: tab }), {
71
+ button: 0,
72
+ ctrlKey: false,
73
+ });
74
+
75
+ const panel = screen.getByRole("tabpanel");
76
+ expect(within(panel).queryAllByText(/skill/i)).toEqual([]);
77
+ expect(panel).toHaveTextContent(getSessionId());
78
+ expect(panel).toHaveTextContent(
79
+ tab === "Prompt" ? "File: notebook.py" : "--file notebook.py",
80
+ );
81
+ expect(panel).not.toHaveTextContent("/project/my notebook.py");
82
+ expect(panel).toHaveTextContent(
83
+ tab === "Prompt" ? "1. Copy this prompt" : "1. Run in your terminal",
84
+ );
85
+ },
86
+ );
87
+
88
+ it.each(["Claude", "Codex", "OpenCode", "Prompt"])(
89
+ "includes the known notebook file in %s preview when the URL has no file",
90
+ async (tab) => {
91
+ window.history.replaceState({}, "", "/");
92
+ await act(async () => {
93
+ render(<PairWithAgentModal onClose={vi.fn()} />, { wrapper });
94
+ });
95
+ fireEvent.mouseDown(screen.getByRole("tab", { name: tab }), {
96
+ button: 0,
97
+ ctrlKey: false,
98
+ });
99
+
100
+ const panel = screen.getByRole("tabpanel");
101
+ const fileHint =
102
+ tab === "Prompt"
103
+ ? "File: /project/my notebook.py"
104
+ : "--file '/project/my notebook.py'";
105
+ expect(panel).toHaveTextContent(fileHint);
106
+ fireEvent.click(
107
+ within(panel).getByRole("button", {
108
+ name: tab === "Prompt" ? "Copy prompt" : "Copy command",
109
+ }),
110
+ );
111
+ await waitFor(() => expect(copyToClipboard).toHaveBeenCalledOnce());
112
+ expect(vi.mocked(copyToClipboard).mock.calls[0][0]).toContain(fileHint);
113
+ },
114
+ );
115
+
116
+ it.each([null, ""])(
117
+ "omits the file when the URL and notebook filename are absent (%s)",
118
+ async (filename) => {
119
+ window.history.replaceState({}, "", "/");
120
+ store.set(filenameAtom, filename);
121
+ await act(async () => {
122
+ render(<PairWithAgentModal onClose={vi.fn()} />, { wrapper });
123
+ });
124
+ expect(screen.getByRole("tabpanel")).not.toHaveTextContent("--file");
125
+ fireEvent.mouseDown(screen.getByRole("tab", { name: "Prompt" }), {
126
+ button: 0,
127
+ ctrlKey: false,
128
+ });
129
+ expect(screen.getByRole("tabpanel")).not.toHaveTextContent("File:");
130
+ },
131
+ );
132
+
133
+ it.each(["Claude", "Codex", "OpenCode", "Prompt"])(
134
+ "preserves the %s skill flow without preview configuration",
135
+ async (tab) => {
136
+ store.set(pairPreviewAtom, undefined);
137
+ window.history.replaceState({}, "", "/");
138
+ await act(async () => {
139
+ render(<PairWithAgentModal onClose={vi.fn()} />, { wrapper });
140
+ });
141
+ fireEvent.mouseDown(screen.getByRole("tab", { name: tab }), {
142
+ button: 0,
143
+ ctrlKey: false,
144
+ });
145
+
146
+ const panel = screen.getByRole("tabpanel");
147
+ expect(
148
+ within(panel).getByText("npx skills add marimo-team/marimo-pair"),
149
+ ).toBeVisible();
150
+ expect(panel).not.toHaveTextContent(getSessionId());
151
+ expect(panel).not.toHaveTextContent("MARIMO_PAIR_NEXT");
152
+ expect(panel).not.toHaveTextContent("/project/my notebook.py");
153
+ expect(panel).toHaveTextContent(
154
+ tab === "Prompt" ? "2. Copy this prompt" : "2. Run in your terminal",
155
+ );
156
+ },
157
+ );
158
+
159
+ it.each([true, false])(
160
+ "masks the raw token but copies it intact (preview=%s)",
161
+ async (preview) => {
162
+ store.set(pairPreviewAtom, preview ? PAIR_PREVIEW : undefined);
163
+ vi.mocked(fetch).mockResolvedValue(
164
+ new Response(JSON.stringify({ token: "secret-token" })),
165
+ );
166
+ await act(async () => {
167
+ render(<PairWithAgentModal onClose={vi.fn()} />, { wrapper });
168
+ });
169
+ fireEvent.mouseDown(screen.getByRole("tab", { name: "Prompt" }), {
170
+ button: 0,
171
+ ctrlKey: false,
172
+ });
173
+
174
+ const panel = screen.getByRole("tabpanel");
175
+ expect(panel).toHaveTextContent("********oken");
176
+ expect(panel).not.toHaveTextContent("secret-token");
177
+ fireEvent.click(
178
+ within(panel).getByRole("button", { name: "Copy prompt" }),
179
+ );
180
+ await waitFor(() => expect(copyToClipboard).toHaveBeenCalledOnce());
181
+ expect(vi.mocked(copyToClipboard).mock.calls[0][0]).toContain(
182
+ preview ? "export MARIMO_TOKEN=secret-token" : "--token secret-token",
183
+ );
184
+ expect(vi.mocked(copyToClipboard).mock.calls[0][0]).not.toContain(
185
+ "********oken",
186
+ );
187
+ },
188
+ );
189
+
190
+ it("copies a preview terminal command without the token and lets the user copy the token separately", async () => {
191
+ vi.mocked(fetch).mockResolvedValue(
192
+ new Response(JSON.stringify({ token: "secret-token" })),
193
+ );
194
+ await act(async () => {
195
+ render(<PairWithAgentModal onClose={vi.fn()} />, { wrapper });
196
+ });
197
+
198
+ const panel = screen.getByRole("tabpanel");
199
+ expect(panel).toHaveTextContent("2. Paste when prompted for a token");
200
+ expect(panel).not.toHaveTextContent("secret-token");
201
+ fireEvent.click(
202
+ within(panel).getByRole("button", { name: "Copy command" }),
203
+ );
204
+ await waitFor(() =>
205
+ expect(copyToClipboard).toHaveBeenCalledWith(
206
+ String.raw`claude "$(MARIMO_PAIR_NEXT=1 uv run marimo pair prompt \
207
+ --url http://localhost:8000/ \
208
+ --file notebook.py \
209
+ --session ${getSessionId()} \
210
+ --with-token)"`,
211
+ ),
212
+ );
213
+ fireEvent.click(within(panel).getByRole("button", { name: "Copy token" }));
214
+ await waitFor(() =>
215
+ expect(copyToClipboard).toHaveBeenLastCalledWith("secret-token"),
216
+ );
217
+ });
218
+ });
@@ -3,6 +3,7 @@
3
3
  import { assertNever } from "@/utils/assertNever";
4
4
  import { KnownQueryParams } from "@/core/constants";
5
5
  import { shellQuote } from "@/utils/shell";
6
+ import type { PairPreviewConfig } from "@/core/config/pair";
6
7
 
7
8
  export type AgentTab = "claude" | "codex" | "opencode" | "prompt";
8
9
 
@@ -37,8 +38,9 @@ function getFileFlag(file: string | undefined): string {
37
38
  /** Identifies the specific running notebook to pair on. */
38
39
  export interface ConnectionInfo {
39
40
  url: string;
40
- /** The server's file key, when the page URL identifies a notebook. */
41
+ /** The server's file key or notebook filename, when known. */
41
42
  file?: string;
43
+ session?: string;
42
44
  }
43
45
 
44
46
  /**
@@ -47,19 +49,29 @@ export interface ConnectionInfo {
47
49
  */
48
50
  export function getTerminalCommand(
49
51
  agent: Exclude<AgentTab, "prompt">,
50
- { url, file }: ConnectionInfo,
52
+ { url, file, session }: ConnectionInfo,
51
53
  withToken: boolean,
54
+ preview?: PairPreviewConfig,
52
55
  ): string {
53
- const fileFlag = getFileFlag(file);
54
- const tokenFlag = withToken ? " --with-token" : "";
55
- const base = `${getMarimoCommand()} pair prompt --url ${shellQuote(url)}${fileFlag}${tokenFlag}`;
56
+ const command = preview?.command ?? getMarimoCommand();
57
+ const prefix = preview ? "MARIMO_PAIR_NEXT=1 " : "";
58
+ const base = [
59
+ `${prefix}${command} pair prompt`,
60
+ `--url ${shellQuote(url)}`,
61
+ file ? `--file ${shellQuote(file)}` : "",
62
+ preview && session ? `--session ${shellQuote(session)}` : "",
63
+ withToken ? "--with-token" : "",
64
+ preview ? "" : `--${agent}`,
65
+ ]
66
+ .filter(Boolean)
67
+ .join(preview ? " \\\n " : " ");
56
68
  switch (agent) {
57
69
  case "claude":
58
- return `claude "$(${base} --claude)"`;
70
+ return `claude "$(${base})"`;
59
71
  case "codex":
60
- return `codex "$(${base} --codex)"`;
72
+ return `codex "$(${base})"`;
61
73
  case "opencode":
62
- return `opencode --prompt "$(${base} --opencode)"`;
74
+ return `opencode --prompt "$(${base})"`;
63
75
  default:
64
76
  assertNever(agent);
65
77
  }
@@ -71,9 +83,23 @@ export function getTerminalCommand(
71
83
  * an agent behaves the same as the terminal commands.
72
84
  */
73
85
  export function getRawPrompt(
74
- { url, file }: ConnectionInfo,
86
+ { url, file, session }: ConnectionInfo,
75
87
  token: string | null,
88
+ preview?: PairPreviewConfig,
76
89
  ): string {
90
+ if (preview) {
91
+ const { command, templates } = preview;
92
+ return formatPrompt(templates.prompt, {
93
+ command,
94
+ url,
95
+ file: file ? formatPrompt(templates.file, { file }) : "",
96
+ session: session ? formatPrompt(templates.session, { session }) : "",
97
+ authentication: token
98
+ ? formatPrompt(templates.token, { token: shellQuote(token) })
99
+ : "",
100
+ });
101
+ }
102
+
77
103
  const fileFlag = getFileFlag(file);
78
104
  const fileHint = file ? ` (file ${file})` : "";
79
105
  const executeCmd = `execute-code.sh --url ${shellQuote(url)}${fileFlag}`;
@@ -91,6 +117,17 @@ export function getRawPrompt(
91
117
  ].join("\n");
92
118
  }
93
119
 
120
+ function formatPrompt(
121
+ template: string,
122
+ values: Record<string, string>,
123
+ ): string {
124
+ // Replace once so inserted file names or tokens cannot become placeholders.
125
+ return template.replaceAll(
126
+ /\{(\w+)\}/g,
127
+ (placeholder, key: string) => values[key] ?? placeholder,
128
+ );
129
+ }
130
+
94
131
  /** Mask all but the last 4 chars of a token for display. */
95
132
  export function maskToken(token: string): string {
96
133
  if (token.length <= 4) {
@@ -2,6 +2,7 @@
2
2
 
3
3
  import { CheckIcon, CopyIcon } from "lucide-react";
4
4
  import React, { useEffect, useState } from "react";
5
+ import { useAtomValue } from "jotai";
5
6
  import { Button } from "@/components/ui/button";
6
7
  import {
7
8
  DialogContent,
@@ -16,6 +17,9 @@ import { Events } from "@/utils/events";
16
17
  import { Tooltip } from "@/components/ui/tooltip";
17
18
  import { asRemoteURL, useRuntimeManager } from "@/core/runtime/config";
18
19
  import { API } from "@/core/network/api";
20
+ import { pairPreviewAtom } from "@/core/config/pair";
21
+ import { getSessionId } from "@/core/kernel/session";
22
+ import { useFilename } from "@/core/saving/filename";
19
23
  import {
20
24
  AGENT_LABELS,
21
25
  AGENT_TABS,
@@ -49,11 +53,17 @@ export const PairWithAgentModal: React.FC<{
49
53
  }> = ({ onClose }) => {
50
54
  const [activeTab, setActiveTab] = useState<AgentTab>("claude");
51
55
  const runtimeManager = useRuntimeManager();
56
+ const preview = useAtomValue(pairPreviewAtom);
57
+ const filename = useFilename();
58
+ const commandStep = preview ? 1 : 2;
52
59
  const authToken = useAuthToken();
53
60
  const hasToken = Boolean(authToken);
54
61
  const connection: ConnectionInfo = {
55
62
  url: runtimeManager.httpURL.toString(),
56
- file: getFileFromURL(window.location.href),
63
+ file:
64
+ getFileFromURL(window.location.href) ??
65
+ (preview ? filename || undefined : undefined),
66
+ session: preview ? getSessionId() : undefined,
57
67
  };
58
68
 
59
69
  return (
@@ -94,23 +104,34 @@ export const PairWithAgentModal: React.FC<{
94
104
  value={tab}
95
105
  className="mt-4 flex flex-col gap-4"
96
106
  >
97
- <Step
98
- index={1}
99
- title="Install the skill"
100
- hint="Run once per machine."
101
- >
102
- <CommandBlock command={SKILL_INSTALL} />
103
- </Step>
104
- <Step index={2} title="Run in your terminal">
107
+ {!preview && (
108
+ <Step
109
+ index={1}
110
+ title="Install the skill"
111
+ hint="Run once per machine."
112
+ >
113
+ <CommandBlock command={SKILL_INSTALL} />
114
+ </Step>
115
+ )}
116
+ <Step index={commandStep} title="Run in your terminal">
105
117
  <CommandBlock
106
- command={getTerminalCommand(tab, connection, hasToken)}
118
+ command={getTerminalCommand(
119
+ tab,
120
+ connection,
121
+ hasToken,
122
+ preview,
123
+ )}
107
124
  />
108
125
  </Step>
109
126
  {hasToken && authToken && (
110
- <Step index={3} title="Paste when prompted for a token">
127
+ <Step
128
+ index={commandStep + 1}
129
+ title="Paste when prompted for a token"
130
+ >
111
131
  <CommandBlock
112
132
  command={authToken}
113
133
  display={maskToken(authToken)}
134
+ copyLabel="Copy token"
114
135
  />
115
136
  </Step>
116
137
  )}
@@ -118,15 +139,17 @@ export const PairWithAgentModal: React.FC<{
118
139
  ))}
119
140
 
120
141
  <TabsContent value="prompt" className="mt-4 flex flex-col gap-4">
142
+ {!preview && (
143
+ <Step
144
+ index={1}
145
+ title="Make sure the marimo-pair skill is available to your agent"
146
+ hint="Skip if your agent already has it."
147
+ >
148
+ <CommandBlock command={SKILL_INSTALL} />
149
+ </Step>
150
+ )}
121
151
  <Step
122
- index={1}
123
- title="Make sure the marimo-pair skill is available to your agent"
124
- hint="Skip if your agent already has it."
125
- >
126
- <CommandBlock command={SKILL_INSTALL} />
127
- </Step>
128
- <Step
129
- index={2}
152
+ index={commandStep}
130
153
  title="Copy this prompt into your agent"
131
154
  hint={
132
155
  hasToken
@@ -135,10 +158,11 @@ export const PairWithAgentModal: React.FC<{
135
158
  }
136
159
  >
137
160
  <CommandBlock
138
- command={getRawPrompt(connection, authToken)}
161
+ command={getRawPrompt(connection, authToken, preview)}
139
162
  display={getRawPrompt(
140
163
  connection,
141
164
  authToken ? maskToken(authToken) : null,
165
+ preview,
142
166
  )}
143
167
  multiline={true}
144
168
  />
@@ -177,7 +201,8 @@ const CommandBlock: React.FC<{
177
201
  command: string;
178
202
  display?: string;
179
203
  multiline?: boolean;
180
- }> = ({ command, display, multiline = false }) => {
204
+ copyLabel?: string;
205
+ }> = ({ command, display, multiline = false, copyLabel = "Copy command" }) => {
181
206
  const [copied, setCopied] = useState(false);
182
207
 
183
208
  const copy = Events.stopPropagation(async (e) => {
@@ -195,6 +220,7 @@ const CommandBlock: React.FC<{
195
220
  </pre>
196
221
  <Tooltip content="Copied!" open={copied}>
197
222
  <Button
223
+ aria-label="Copy prompt"
198
224
  onClick={copy}
199
225
  size="xs"
200
226
  variant="ghost"
@@ -213,11 +239,11 @@ const CommandBlock: React.FC<{
213
239
 
214
240
  return (
215
241
  <div className="flex items-center gap-2 rounded-md bg-muted px-3 py-2 font-mono text-xs">
216
- <code className="flex-1 select-all wrap-break-word">
242
+ <code className="flex-1 whitespace-pre-wrap select-all wrap-break-word">
217
243
  {display ?? command}
218
244
  </code>
219
245
  <Tooltip content="Copied!" open={copied}>
220
- <Button onClick={copy} size="xs" variant="ghost">
246
+ <Button aria-label={copyLabel} onClick={copy} size="xs" variant="ghost">
221
247
  {copied ? (
222
248
  <CheckIcon size={14} strokeWidth={1.5} />
223
249
  ) : (
@@ -124,6 +124,7 @@ export const AddCellWithAI: React.FC<{
124
124
  );
125
125
  const body = {
126
126
  ...completionBody,
127
+ id: options.id,
127
128
  code: "",
128
129
  prompt: "", // Don't need prompt since we are using messages
129
130
  language: language,
@@ -124,7 +124,9 @@ export const AiCompletionEditor: React.FC<Props> = ({
124
124
  new DefaultChatTransport<CompletionUIMessage>({
125
125
  api: runtimeManager.getAiURL("completion").toString(),
126
126
  headers: () => runtimeManager.headers(),
127
- prepareSendMessagesRequest: ({ body }) => ({ body: body ?? {} }),
127
+ prepareSendMessagesRequest: ({ body, id }) => ({
128
+ body: { ...body, id },
129
+ }),
128
130
  }),
129
131
  [runtimeManager],
130
132
  );
@@ -1,76 +1,11 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
3
  import { useAtomValue } from "jotai";
4
- import { LoadingEllipsis } from "@/components/icons/loading-ellipsis";
5
- import { Spinner } from "@/components/icons/spinner";
6
4
  import { Button } from "@/components/ui/button";
7
- import { DelayMount } from "@/components/utils/delay-mount";
8
- import {
9
- isClosedAtom,
10
- isConnectingAtom,
11
- isNotStartedAtom,
12
- } from "@/core/network/connection";
5
+ import { isNotStartedAtom } from "@/core/network/connection";
13
6
  import { useConnectToRuntime } from "@/core/runtime/config";
14
- import { Banner } from "@/plugins/impl/common/error-banner";
15
- import { Tooltip } from "../../ui/tooltip";
16
7
  import { FloatingAlert } from "./floating-alert";
17
8
 
18
- const SHORT_DELAY_MS = 1000; // 1 second
19
- const LONG_DELAY_MS = 5000; // 5 seconds
20
-
21
- export const ConnectingAlert: React.FC = () => {
22
- const isConnecting = useAtomValue(isConnectingAtom);
23
- const isClosed = useAtomValue(isClosedAtom);
24
-
25
- if (isConnecting) {
26
- const subtleNotification = (
27
- <Tooltip content="Connecting to a marimo runtime">
28
- <div className="flex items-center">
29
- <LoadingEllipsis size={5} className="text-yellow-500" />
30
- </div>
31
- </Tooltip>
32
- );
33
-
34
- const longNotification = (
35
- <Banner
36
- kind="info"
37
- className="flex flex-col rounded py-2 px-4 animate-in slide-in-from-top w-fit"
38
- >
39
- <div className="flex flex-col gap-4 justify-between items-start text-muted-foreground text-base">
40
- <div className="flex items-center gap-2">
41
- <Spinner className="h-4 w-4" />
42
- <p>Connecting to a marimo runtime ...</p>
43
- </div>
44
- </div>
45
- </Banner>
46
- );
47
-
48
- // This waits for 1 second to show the subtle notification, then shows the long notification after 5 seconds.
49
- return (
50
- <DelayMount milliseconds={SHORT_DELAY_MS}>
51
- <div className="m-0 flex items-center min-h-[28px] fixed top-5 left-1/2 transform -translate-x-1/2 z-200">
52
- <DelayMount
53
- milliseconds={LONG_DELAY_MS}
54
- fallback={subtleNotification}
55
- >
56
- {longNotification}
57
- </DelayMount>
58
- </div>
59
- </DelayMount>
60
- );
61
- }
62
-
63
- if (isClosed) {
64
- return (
65
- <FloatingAlert show={isClosed} kind="danger">
66
- <div className="flex items-center gap-2">
67
- <p>Failed to connect.</p>
68
- </div>
69
- </FloatingAlert>
70
- );
71
- }
72
- };
73
-
74
9
  export const NotStartedConnectionAlert: React.FC = () => {
75
10
  const isNotStarted = useAtomValue(isNotStartedAtom);
76
11
  const connectToRuntime = useConnectToRuntime();