@marimo-team/frontend 0.23.16-dev5 → 0.23.16-dev51

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 (704) hide show
  1. package/dist/assets/{CellStatus-BalYv0pK.js → CellStatus-DciB5rbr.js} +1 -1
  2. package/dist/assets/{ConnectedDataExplorerComponent-DI7mV-Gw.js → ConnectedDataExplorerComponent-CXp99aFw.js} +1 -1
  3. package/dist/assets/{ErrorBoundary-C7_5jjWi.js → ErrorBoundary-DzTD8LVq.js} +1 -1
  4. package/dist/assets/{ImperativeModal-BIavOiUv.js → ImperativeModal-fY-ZfT0b.js} +1 -1
  5. package/dist/assets/JsonOutput-BM3vve9F.js +53 -0
  6. package/dist/assets/LazyAnyLanguageCodeMirror-DPOEues4.js +2 -0
  7. package/dist/assets/{MarimoErrorOutput-DO2k2fA5.js → MarimoErrorOutput-Bh0y53Du.js} +4 -4
  8. package/dist/assets/{RSPContexts-CgC81f0I.js → RSPContexts-WiCgGm__.js} +1 -1
  9. package/dist/assets/RenderHTML-B9jx7Dsm.js +1 -0
  10. package/dist/assets/{RunButton-BKRupqr7.js → RunButton-DMtHbFuA.js} +1 -1
  11. package/dist/assets/{add-cell-with-ai-CEZtaZCK.js → add-cell-with-ai-BcRYriMM.js} +35 -35
  12. package/dist/assets/add-connection-dialog-syjRSNPT.js +178 -0
  13. package/dist/assets/{agent-panel-CHB6t7Zy.js → agent-panel-B31W_VwU.js} +5 -5
  14. package/dist/assets/ai-model-dropdown-B3D05oQh.js +5 -0
  15. package/dist/assets/{alert-dialog-BXegNC0I.js → alert-dialog-Bb8Lz8ko.js} +1 -1
  16. package/dist/assets/{any-language-editor-DCpZRrpx.js → any-language-editor-BDvoKhJM.js} +1 -1
  17. package/dist/assets/apl-B-7blH-b.js +1 -0
  18. package/dist/assets/app-config-button-D_mjovwU.js +1 -0
  19. package/dist/assets/{arc-CfUZAQDm.js → arc-CezuXhk_.js} +1 -1
  20. package/dist/assets/{architecture-7HQA4BMR-Bvqj37EA.js → architecture-7HQA4BMR-Dy7zkjw8.js} +1 -1
  21. package/dist/assets/{architectureDiagram-VXUJARFQ-sx_yisiZ.js → architectureDiagram-VXUJARFQ-BmOSh2SW.js} +1 -1
  22. package/dist/assets/asciiarmor-D3K8amZ9.js +1 -0
  23. package/dist/assets/asn1-UGGn98tp.js +1 -0
  24. package/dist/assets/blob-BJREJiQp.js +1 -0
  25. package/dist/assets/{blockDiagram-VD42YOAC-KexI-fgH.js → blockDiagram-VD42YOAC-DHO0ifdn.js} +1 -1
  26. package/dist/assets/brainfuck-B4y4U3tg.js +1 -0
  27. package/dist/assets/{button-eIihcbUw.js → button-DDGiD1NW.js} +1 -1
  28. package/dist/assets/{c4Diagram-YG6GDRKO-d8NrlxRF.js → c4Diagram-YG6GDRKO-ByToYMes.js} +1 -1
  29. package/dist/assets/{cache-panel-wllSTlbM.js → cache-panel-Bvnkzrzd.js} +1 -1
  30. package/dist/assets/{capabilities-B09j1Eor.js → capabilities-DoEg0XwL.js} +1 -1
  31. package/dist/assets/{cell-editor-B5JVq7_q.js → cell-editor-BOhZHoLm.js} +17 -17
  32. package/dist/assets/cell-link-DqNEv3f9.js +1 -0
  33. package/dist/assets/cells-Jr-5Pc9f.js +235 -0
  34. package/dist/assets/channel-hYe4T32r.js +1 -0
  35. package/dist/assets/{chat-display-BG08ltQ3.js → chat-display-Djy1Jt6b.js} +1 -1
  36. package/dist/assets/{chat-panel-P2CzCtXJ.js → chat-panel-B2nYSE_l.js} +4 -4
  37. package/dist/assets/{chat-ui-fAJZAoTD.js → chat-ui-DlG0En7w.js} +4 -4
  38. package/dist/assets/{chunk-4BX2VUAB-fhh1HlXH.js → chunk-4BX2VUAB-BsEakQWN.js} +1 -1
  39. package/dist/assets/chunk-55IACEB6-DkGbQmsa.js +1 -0
  40. package/dist/assets/{chunk-5FQGJX7Z-Cp0LZT-a.js → chunk-5FQGJX7Z-BEbM01OT.js} +2 -2
  41. package/dist/assets/{chunk-ABZYJK2D-BtK4zInQ.js → chunk-ABZYJK2D-CCNXe-E2.js} +3 -3
  42. package/dist/assets/{chunk-ATLVNIR6-YZDenslF.js → chunk-ATLVNIR6-yY0weiRB.js} +1 -1
  43. package/dist/assets/{chunk-B4BG7PRW-DYIZwDbt.js → chunk-B4BG7PRW-DtjHcIBO.js} +1 -1
  44. package/dist/assets/{chunk-CVBHYZKI-CIyHeK0Q.js → chunk-CVBHYZKI-D1ar3Zzb.js} +1 -1
  45. package/dist/assets/{chunk-DI55MBZ5-TodwBGEN.js → chunk-DI55MBZ5-BxB9Lmc6.js} +1 -1
  46. package/dist/assets/{chunk-EXTU4WIE-C76bF1UD.js → chunk-EXTU4WIE-Do43HMrz.js} +1 -1
  47. package/dist/assets/{chunk-FMBD7UC4-Yq65IDPA.js → chunk-FMBD7UC4-FWkYBdS7.js} +1 -1
  48. package/dist/assets/{chunk-HN2XXSSU-CcbN4n6W.js → chunk-HN2XXSSU-nVY6M8Me.js} +1 -1
  49. package/dist/assets/{chunk-JA3XYJ7Z-CPXEu7AX.js → chunk-JA3XYJ7Z-52dYwyoT.js} +1 -1
  50. package/dist/assets/{chunk-JZLCHNYA-D8q1z6Py.js → chunk-JZLCHNYA-BHSouLxk.js} +1 -1
  51. package/dist/assets/{chunk-MI3HLSF2-bmomnexd.js → chunk-MI3HLSF2-BwgHEi3_.js} +1 -1
  52. package/dist/assets/{chunk-N4CR4FBY-BhsjB2qn.js → chunk-N4CR4FBY-BkAnRh0J.js} +2 -2
  53. package/dist/assets/{chunk-QN33PNHL-ngvPqyQ0.js → chunk-QN33PNHL-DWzHlkYI.js} +1 -1
  54. package/dist/assets/{chunk-QXUST7PY-C4c0Sjmn.js → chunk-QXUST7PY-CjtWgrZg.js} +1 -1
  55. package/dist/assets/{chunk-QZHKN3VN-CkbwBDOS.js → chunk-QZHKN3VN-CmAwpNoC.js} +1 -1
  56. package/dist/assets/{chunk-S3R3BYOJ-Bt2NnquF.js → chunk-S3R3BYOJ-DcZAYEft.js} +1 -1
  57. package/dist/assets/{chunk-TZMSLE5B-Dysko1OC.js → chunk-TZMSLE5B-D2-o8-XQ.js} +1 -1
  58. package/dist/assets/classDiagram-2ON5EDUG-DapsPtpH.js +1 -0
  59. package/dist/assets/classDiagram-v2-WZHVMYZB-Oa2f7U6n.js +1 -0
  60. package/dist/assets/{clike-DKPr2D1_.js → clike-BAN6KopO.js} +1 -1
  61. package/dist/assets/clojure-BAZ-ejkG.js +1 -0
  62. package/dist/assets/cmake-jWn0xN9y.js +1 -0
  63. package/dist/assets/cobol-XqY9jaWP.js +1 -0
  64. package/dist/assets/{code-block-37QAKDTI-DlENujeV.js → code-block-37QAKDTI-DdMTHZGu.js} +1 -1
  65. package/dist/assets/coffeescript-DI1jfZHX.js +1 -0
  66. package/dist/assets/{column-preview-Dne1dIt0.js → column-preview-BUHlI5va.js} +1 -1
  67. package/dist/assets/{command-CAJLPEBq.js → command-Dqxie4gq.js} +1 -1
  68. package/dist/assets/{command-palette-iOCqUIs1.js → command-palette-rEJmXCZM.js} +1 -1
  69. package/dist/assets/{common-CD6Mj8n6.js → common-CZc3fQI4.js} +1 -1
  70. package/dist/assets/commonlisp-UKb01OlU.js +1 -0
  71. package/dist/assets/components-GAYCj6Mx.js +1 -0
  72. package/dist/assets/config-B-Q7J_6d.js +1 -0
  73. package/dist/assets/{config-COUOIPEq.js → config-BJVx3eBW.js} +1 -1
  74. package/dist/assets/{copy-BtTOqPTS.js → copy-Bxb1_Gtw.js} +1 -1
  75. package/dist/assets/{copy-icon-C2pG0ZNK.js → copy-icon-neDQUo4Q.js} +1 -1
  76. package/dist/assets/{cose-bilkent-S5V4N54A-BlMw4-M9.js → cose-bilkent-S5V4N54A-B4-5phSs.js} +1 -1
  77. package/dist/assets/{createReducer-C7kZ8zEe.js → createReducer-DGx5Af-C.js} +1 -1
  78. package/dist/assets/crystal-DOvjTBWA.js +1 -0
  79. package/dist/assets/{css-DsUcFZz8.js → css-DWLxGm3Z.js} +1 -1
  80. package/dist/assets/cypher-CLDhu2ae.js +1 -0
  81. package/dist/assets/d-C0ecUZk9.js +1 -0
  82. package/dist/assets/{dagre-6UL2VRFP-kJ4x17JK.js → dagre-6UL2VRFP-2XhH1Ri-.js} +1 -1
  83. package/dist/assets/{data-grid-overlay-editor-DbobQcVo.js → data-grid-overlay-editor-B4LrPNw9.js} +1 -1
  84. package/dist/assets/{datasource-ySAiC9gr.js → datasource-AWkkAeiS.js} +2 -2
  85. package/dist/assets/{dates-D-kIKDYA.js → dates-C2LWzsCZ.js} +1 -1
  86. package/dist/assets/{dependency-graph-panel-BF23EwcD.js → dependency-graph-panel-wcqTPq6b.js} +3 -3
  87. package/dist/assets/{diagram-PSM6KHXK-d-5aQNHk.js → diagram-PSM6KHXK-CAqt0euW.js} +1 -1
  88. package/dist/assets/{diagram-QEK2KX5R-CO-PXq75.js → diagram-QEK2KX5R-D5cgX3Vp.js} +1 -1
  89. package/dist/assets/{diagram-S2PKOQOG-Dv7pcvYC.js → diagram-S2PKOQOG-ibWavdR5.js} +1 -1
  90. package/dist/assets/{dialog-D1DEsRZ2.js → dialog-BCVepWLJ.js} +1 -1
  91. package/dist/assets/diff-657cCCVc.js +1 -0
  92. package/dist/assets/{dist-CRrIf3gB.js → dist-7L5iW3e_.js} +1 -1
  93. package/dist/assets/{dist-ByVeMWkr.js → dist-BLN8PNJV.js} +1 -1
  94. package/dist/assets/{dist-R1kU4nzJ.js → dist-Bcpo9599.js} +1 -1
  95. package/dist/assets/{dist-DQNaXfK1.js → dist-BrZHhdmA.js} +1 -1
  96. package/dist/assets/dist-C00gHjPp.js +1 -0
  97. package/dist/assets/{dist-0QUuSoRx.js → dist-C4El4p_-.js} +1 -1
  98. package/dist/assets/{dist-BsphJPAV.js → dist-CIYjZ11d.js} +1 -1
  99. package/dist/assets/{dist-Du-wcJyR.js → dist-COTjOJlM.js} +1 -1
  100. package/dist/assets/dist-CWNfBqYo.js +1 -0
  101. package/dist/assets/dist-Cck3fpDq.js +1 -0
  102. package/dist/assets/dist-CiVShZKM.js +2 -0
  103. package/dist/assets/{dist-CECF_J8y.js → dist-DIQO2yAn.js} +1 -1
  104. package/dist/assets/{dist-BMOD2Pyh.js → dist-DabFEfar.js} +1 -1
  105. package/dist/assets/dist-f5euh_Pv.js +1 -0
  106. package/dist/assets/{dist-CDUl-YL4.js → dist-ryTWanRP.js} +1 -1
  107. package/dist/assets/{dist-6c4zOh78.js → dist-sg9T7Ulw.js} +1 -1
  108. package/dist/assets/{dist-sPfKr-vH.js → dist-wSuqFvon.js} +1 -1
  109. package/dist/assets/{dockerfile-C2PznFWk.js → dockerfile-kqVBOcIP.js} +1 -1
  110. package/dist/assets/{documentation-panel-e9Fi9R7e.js → documentation-panel-Eu8MIkoU.js} +1 -1
  111. package/dist/assets/download-CQ7iZFJL.js +9 -0
  112. package/dist/assets/{dropdown-menu-BFZLnWeO.js → dropdown-menu-dHmZR8bI.js} +1 -1
  113. package/dist/assets/dtd-DSiK7Qgi.js +1 -0
  114. package/dist/assets/dylan-07d5-7Q9.js +1 -0
  115. package/dist/assets/ecl-CSTUHiwq.js +1 -0
  116. package/dist/assets/{edit-page-7X3HYey7.js → edit-page-Cw7nN6HC.js} +6 -6
  117. package/dist/assets/eiffel-DR99GcsM.js +1 -0
  118. package/dist/assets/elm-Cmh0iW6J.js +1 -0
  119. package/dist/assets/{erDiagram-Q2GNP2WA-BQ8HfnRu.js → erDiagram-Q2GNP2WA-BaY7iomT.js} +1 -1
  120. package/dist/assets/erlang-CS9Yc6UC.js +1 -0
  121. package/dist/assets/{error-banner-B6eIlxzg.js → error-banner-BSxEOIn2.js} +1 -1
  122. package/dist/assets/error-entries-Cr8uVukN.js +8 -0
  123. package/dist/assets/{error-panel-DdsUL6b7.js → error-panel-BZzr0PA1.js} +1 -1
  124. package/dist/assets/{es-1D83cgiu.js → es-gYgfF8y5.js} +1 -1
  125. package/dist/assets/{esm-BL7jQmzn.js → esm-B30N1GS0.js} +1 -1
  126. package/dist/assets/{esm-Cmv0Nuxi.js → esm-DqItXpGT.js} +1 -1
  127. package/dist/assets/{factor-DMrXrOH8.js → factor-D96xahcJ.js} +1 -1
  128. package/dist/assets/factor-DjB27Lcf.js +1 -0
  129. package/dist/assets/{field-BeZbVzXA.js → field-BsxD35VE.js} +1 -1
  130. package/dist/assets/file-explorer-panel-C1W7g_Wp.js +26 -0
  131. package/dist/assets/{file-icons-Cb54mIL8.js → file-icons-BAqZR08W.js} +1 -1
  132. package/dist/assets/{file-name-input-BWFcK1ey.js → file-name-input-0MiZVw5r.js} +1 -1
  133. package/dist/assets/{fileToBase64-C2Yy-YXq.js → fileToBase64-Dgfa7TRQ.js} +1 -1
  134. package/dist/assets/floating-outline-C6g75zrP.js +1 -0
  135. package/dist/assets/{flowDiagram-NV44I4VS-xBOzhlfg.js → flowDiagram-NV44I4VS-C_6PGGE6.js} +1 -1
  136. package/dist/assets/focus-C0HXXg3V.js +1 -0
  137. package/dist/assets/form-C051zAev.js +1 -0
  138. package/dist/assets/{form-B6BkSCJb.js → form-DT44Rmhp.js} +2 -2
  139. package/dist/assets/{formats-ClEFGPy-.js → formats-DzmLpc9A.js} +1 -1
  140. package/dist/assets/{formatting-B_41gSF5.js → formatting-DQX9QUSf.js} +1 -1
  141. package/dist/assets/forth-UwTUu7NY.js +1 -0
  142. package/dist/assets/fortran-cptiB4gJ.js +1 -0
  143. package/dist/assets/{fullscreen-dUjPYOmm.js → fullscreen-CTDqNQr6.js} +1 -1
  144. package/dist/assets/{gallery-page-CWQQAYpa.js → gallery-page-CL1y8LXc.js} +1 -1
  145. package/dist/assets/{ganttDiagram-JELNMOA3-D2O_k-Zg.js → ganttDiagram-JELNMOA3-CJFyE5hs.js} +1 -1
  146. package/dist/assets/gas-ajMbd9Us.js +1 -0
  147. package/dist/assets/gherkin-ClYkalzE.js +1 -0
  148. package/dist/assets/{gitGraph-G5XIXVHT-8HJwNcdU.js → gitGraph-G5XIXVHT-BP96QVP9.js} +1 -1
  149. package/dist/assets/{gitGraphDiagram-V2S2FVAM-Nk4Ll9GY.js → gitGraphDiagram-V2S2FVAM-CGQPWKR8.js} +1 -1
  150. package/dist/assets/{glide-data-editor-lMARFWHS.js → glide-data-editor-Badziq3Y.js} +4 -4
  151. package/dist/assets/groovy-BY-gt7AW.js +1 -0
  152. package/dist/assets/haskell-D1BeJ7SR.js +1 -0
  153. package/dist/assets/haxe-QOq5WFXx.js +1 -0
  154. package/dist/assets/home-page-CJz9IHZ2.js +4 -0
  155. package/dist/assets/{html-to-image-CwmX28T9.js → html-to-image-CfjhKLA4.js} +2 -2
  156. package/dist/assets/idl-3-UcEGx7.js +1 -0
  157. package/dist/assets/index-CrEgp1mR.js +38 -0
  158. package/dist/assets/index-D6Dp_PFj.css +2 -0
  159. package/dist/assets/{info-VBDWY6EO-rfe3WPvd.js → info-VBDWY6EO-B7aeNYNu.js} +1 -1
  160. package/dist/assets/infoDiagram-HS3SLOUP-BT7ISZ3J.js +2 -0
  161. package/dist/assets/{input-CqrUjynb.js → input-JxFwu-3G.js} +1 -1
  162. package/dist/assets/javascript-CorD44JN.js +1 -0
  163. package/dist/assets/{journeyDiagram-XKPGCS4Q-D61FGivn.js → journeyDiagram-XKPGCS4Q-DhyWkFu7.js} +1 -1
  164. package/dist/assets/julia-BYqTtTAl.js +1 -0
  165. package/dist/assets/{kanban-definition-3W4ZIXB7-Bnv0X0Tu.js → kanban-definition-3W4ZIXB7-B2A0FPA_.js} +1 -1
  166. package/dist/assets/katex-BnxSCReZ.js +1 -0
  167. package/dist/assets/kiosk-mode-CWGEgpon.js +1 -0
  168. package/dist/assets/{label-BElwWzf0.js → label-CqjrpwRC.js} +1 -1
  169. package/dist/assets/{layout-CUlZijwG.js → layout-D4bpsgVD.js} +5 -5
  170. package/dist/assets/{line-DNm2phYo.js → line-1dURhxkp.js} +1 -1
  171. package/dist/assets/{linear-CTQqNbVX.js → linear-gmSPLe7o.js} +1 -1
  172. package/dist/assets/{links-CToBjIIj.js → links-CiT7FeSM.js} +1 -1
  173. package/dist/assets/livescript-qYgfNnNE.js +1 -0
  174. package/dist/assets/logs-panel-CsaY3O1m.js +1 -0
  175. package/dist/assets/{loro_wasm_bg-Duqr-kJ2.js → loro_wasm_bg-DWuCVDfB.js} +1 -1
  176. package/dist/assets/lua-BCqCjdfz.js +1 -0
  177. package/dist/assets/{markdown-renderer-QvXG0CRk.js → markdown-renderer-BgqeO4JR.js} +3 -3
  178. package/dist/assets/mathematica-XKwMfn0d.js +1 -0
  179. package/dist/assets/mbox-BnkeOnif.js +1 -0
  180. package/dist/assets/{menu-items-DbSLBfXR.js → menu-items-CCi6aOPm.js} +1 -1
  181. package/dist/assets/{mermaid-4DMBBIKO-CDGmT6YQ.js → mermaid-4DMBBIKO-DxfSuOnE.js} +1 -1
  182. package/dist/assets/{mermaid-Bh0flEIb.js → mermaid-Dfx05w1B.js} +3 -3
  183. package/dist/assets/{mermaid-parser.core-Dz2GMGqQ.js → mermaid-parser.core-OagDSIIt.js} +2 -2
  184. package/dist/assets/{mhchem-CIWniJp4.js → mhchem-Dka9kRKN.js} +1 -1
  185. package/dist/assets/{mindmap-definition-VGOIOE7T-C-YaKmEU.js → mindmap-definition-VGOIOE7T-torqqISZ.js} +1 -1
  186. package/dist/assets/mirc-ipoElhai.js +1 -0
  187. package/dist/assets/mllike-DmouQ5Dp.js +1 -0
  188. package/dist/assets/modelica-BtmmVsUf.js +1 -0
  189. package/dist/assets/mscgen-BHZmHZgz.js +1 -0
  190. package/dist/assets/mumps-oKfoFTl_.js +1 -0
  191. package/dist/assets/{name-cell-input-C6cukQ9k.js → name-cell-input-DcU8Rfrz.js} +1 -1
  192. package/dist/assets/node-sql-parser-Dpr10aqR.js +68 -0
  193. package/dist/assets/nsis-DDOPnuAW.js +1 -0
  194. package/dist/assets/{nsis-Ccvd1gbp.js → nsis-gzbsJ5t0.js} +1 -1
  195. package/dist/assets/ntriples-Dsyl_sOF.js +1 -0
  196. package/dist/assets/{number-overlay-editor-BQ9P6yP7.js → number-overlay-editor-DlQjqV32.js} +1 -1
  197. package/dist/assets/{numbers-CeeaFKqu.js → numbers-rmawRqQP.js} +1 -1
  198. package/dist/assets/octave-CI5RGMPa.js +1 -0
  199. package/dist/assets/{ordinal-DyTNGK17.js → ordinal-W4TcDjiJ.js} +1 -1
  200. package/dist/assets/{outline-panel-BPlg9_CE.js → outline-panel-D-CHPZQM.js} +1 -1
  201. package/dist/assets/oz-D01pKAWx.js +1 -0
  202. package/dist/assets/{packages-panel-BzQF60rG.js → packages-panel-dq7QVZl1.js} +1 -1
  203. package/dist/assets/{packet-DYOGHKS2-DTVloLa7.js → packet-DYOGHKS2-B2FlK_cc.js} +1 -1
  204. package/dist/assets/pair-with-agent-modal-D2vO1D8g.js +4 -0
  205. package/dist/assets/panels-DWoniKhE.js +4 -0
  206. package/dist/assets/pascal-DGXfnIFD.js +1 -0
  207. package/dist/assets/perl-gZ7qIkF-.js +1 -0
  208. package/dist/assets/{pie-VRWISCQL-Bmght6JF.js → pie-VRWISCQL-rtCNhZhm.js} +1 -1
  209. package/dist/assets/{pieDiagram-ADFJNKIX-DlFYL0BN.js → pieDiagram-ADFJNKIX-vSo1I9sb.js} +1 -1
  210. package/dist/assets/pig-Cb90ayl-.js +1 -0
  211. package/dist/assets/{popover-DrHQ3KEt.js → popover-Bcz1Zikb.js} +1 -1
  212. package/dist/assets/powershell-_YxddSL3.js +1 -0
  213. package/dist/assets/process-output-NbwnUu05.js +1 -0
  214. package/dist/assets/properties-sU50dmvt.js +1 -0
  215. package/dist/assets/protobuf-DFdF-yfo.js +1 -0
  216. package/dist/assets/{pug-BtXi5KiX.js → pug-CfBtO6QD.js} +1 -1
  217. package/dist/assets/pug-DwUB-C24.js +1 -0
  218. package/dist/assets/puppet-DtKzwiZ6.js +1 -0
  219. package/dist/assets/python-BMLOKYmk.js +1 -0
  220. package/dist/assets/q-BF1zXMdP.js +1 -0
  221. package/dist/assets/{quadrantDiagram-AYHSOK5B-BpJug2BH.js → quadrantDiagram-AYHSOK5B-DonUSsuk.js} +1 -1
  222. package/dist/assets/r-BQiKhVSI.js +1 -0
  223. package/dist/assets/{radar-ZZBFDIW7-CYwWzRgW.js → radar-ZZBFDIW7-CRVupj1O.js} +1 -1
  224. package/dist/assets/{radio-group-CLBjGkt5.js → radio-group-rhQpGwU-.js} +1 -1
  225. package/dist/assets/{react-vega-TNCk_eWj.js → react-vega-Bd66vLSZ.js} +1 -1
  226. package/dist/assets/{readonly-code-display-D63oRtBP.js → readonly-code-display-CVY2f7EZ.js} +1 -1
  227. package/dist/assets/{readonly-python-code-CW_G5e4E.js → readonly-python-code-Q_1Y3VyZ.js} +1 -1
  228. package/dist/assets/{renderShortcut-BZLr8D7H.js → renderShortcut-Bl8_FVn8.js} +1 -1
  229. package/dist/assets/{requirementDiagram-UZGBJVZJ-Bd-1eny8.js → requirementDiagram-UZGBJVZJ-D8rJ1Dg-.js} +1 -1
  230. package/dist/assets/{reveal-component-BLMTmd8T.js → reveal-component-CedpDwM8.js} +60 -60
  231. package/dist/assets/rpm-v7UTuaHo.js +1 -0
  232. package/dist/assets/ruby-Cw43FpG3.js +1 -0
  233. package/dist/assets/{run-page-B6pgDYEJ.js → run-page-CGoux5cj.js} +1 -1
  234. package/dist/assets/{runs-D51Xwrsk.js → runs-CZN8py6x.js} +1 -1
  235. package/dist/assets/{sankeyDiagram-TZEHDZUN-CDWAE6GV.js → sankeyDiagram-TZEHDZUN-Bufh177s.js} +1 -1
  236. package/dist/assets/sas-BIKscqlp.js +1 -0
  237. package/dist/assets/scheme-CGic3hSV.js +1 -0
  238. package/dist/assets/scratchpad-panel-BLuF25yR.js +1 -0
  239. package/dist/assets/{scroll-to-bottom-button-Cgr10kaJ.js → scroll-to-bottom-button-C8yfT4wq.js} +1 -1
  240. package/dist/assets/{secrets-panel-Cc5KDBk6.js → secrets-panel-4Qy7R-wy.js} +1 -1
  241. package/dist/assets/{select-B5TFNjmU.js → select-BP75_5jJ.js} +1 -1
  242. package/dist/assets/{sequenceDiagram-WL72ISMW-B6hjDGBF.js → sequenceDiagram-WL72ISMW-DOsQdDD2.js} +1 -1
  243. package/dist/assets/{session-CEFnN9Cq.js → session-BmukRjSi.js} +1 -1
  244. package/dist/assets/session-panel-OIot3eyB.js +1 -0
  245. package/dist/assets/{share-CYpcX4N4.js → share-852X_cqy.js} +1 -1
  246. package/dist/assets/shell-DAh545tm.js +1 -0
  247. package/dist/assets/sieve-bGkng63-.js +1 -0
  248. package/dist/assets/{skeleton-D3QPxqWC.js → skeleton-BRvjFlRu.js} +1 -1
  249. package/dist/assets/slides-DkEgzTJB.css +1 -0
  250. package/dist/assets/smalltalk-fIw53lm8.js +1 -0
  251. package/dist/assets/{snippets-panel-CXpGflMO.js → snippets-panel-YFyH2hUM.js} +1 -1
  252. package/dist/assets/sparql-CHbJrAY_.js +1 -0
  253. package/dist/assets/{spec-CzqcmYQk.js → spec-C7opZZRp.js} +1 -1
  254. package/dist/assets/{src-CIOdyciO.js → src-BSYB0gI9.js} +1 -1
  255. package/dist/assets/state-DB_fxbhn.js +3 -0
  256. package/dist/assets/{state-WBgc7MiA.js → state-DDag0B_B.js} +1 -1
  257. package/dist/assets/{state-BvdK8eiw.js → state-DFeun9PF.js} +1 -1
  258. package/dist/assets/{state-DBzEQtWz.js → state-bHyw5u3R.js} +1 -1
  259. package/dist/assets/{stateDiagram-FKZM4ZOC-Bzv6j99z.js → stateDiagram-FKZM4ZOC-z2ks4r_9.js} +1 -1
  260. package/dist/assets/stateDiagram-v2-4FDKWEC3-BApjXiT0.js +1 -0
  261. package/dist/assets/{step-CDlhJj9-.js → step-DIOVHicC.js} +1 -1
  262. package/dist/assets/{strings-Djnbwmfl.js → strings--BknHX9C.js} +1 -1
  263. package/dist/assets/stylus-3Q5WfXqT.js +1 -0
  264. package/dist/assets/swift-MKxc2knl.js +1 -0
  265. package/dist/assets/{swiper-component-DInvCxhI.js → swiper-component-C0ieyDzn.js} +1 -1
  266. package/dist/assets/switch-OVajJBPR.js +1 -0
  267. package/dist/assets/tcl-D3fKhQc_.js +1 -0
  268. package/dist/assets/{terminal-D3IQBBYo.js → terminal-D4sGJYRn.js} +1 -1
  269. package/dist/assets/textarea-DZB2bzVL.js +1 -0
  270. package/dist/assets/textile-Bi_LEJQ3.js +1 -0
  271. package/dist/assets/{time-BuRlxEhE.js → time-NXrJfoDM.js} +1 -1
  272. package/dist/assets/{timeline-definition-IT6M3QCI-DXwdU1og.js → timeline-definition-IT6M3QCI-BRuA290T.js} +1 -1
  273. package/dist/assets/toml-Dt-PBqwt.js +1 -0
  274. package/dist/assets/{tooltip-CFX4fYHU.js → tooltip-4bZlU7jl.js} +1 -1
  275. package/dist/assets/{tooltip-HLb6RxVp.js → tooltip-B7U4xkIN.js} +1 -1
  276. package/dist/assets/{tracing-CKn3gWHw.js → tracing-CDMM1BB2.js} +1 -1
  277. package/dist/assets/{tracing-panel-BU-o_LCd.js → tracing-panel-BH5Zbvl9.js} +2 -2
  278. package/dist/assets/{tree-actions-CsC2XmGo.js → tree-actions-DDveUIHK.js} +1 -1
  279. package/dist/assets/{treemap-GDKQZRPO-4Cm6HMmj.js → treemap-GDKQZRPO-DIzBBPQD.js} +1 -1
  280. package/dist/assets/troff-BSU-rxoD.js +1 -0
  281. package/dist/assets/ttcn-BmLjonVM.js +1 -0
  282. package/dist/assets/ttcn-cfg-TPTcP0Eh.js +1 -0
  283. package/dist/assets/turtle-HafmShQq.js +1 -0
  284. package/dist/assets/{useBoolean-D89u30n-.js → useBoolean-CFj86iac.js} +1 -1
  285. package/dist/assets/useCellActionButton-D5ix_g2a.js +1 -0
  286. package/dist/assets/{useDeleteCell-EPH4kcG7.js → useDeleteCell-BIopCngo.js} +1 -1
  287. package/dist/assets/{useDependencyPanelTab-CZnK7N2L.js → useDependencyPanelTab-snM337f9.js} +1 -1
  288. package/dist/assets/useEventListener-C0195JsF.js +1 -0
  289. package/dist/assets/{useHotkey-DIuRH8Wu.js → useHotkey-DLZvrRZT.js} +1 -1
  290. package/dist/assets/{useIframeCapabilities-Ccb4fvKc.js → useIframeCapabilities-j6fR_dBA.js} +1 -1
  291. package/dist/assets/{useInstallPackage-BRbUAUFn.js → useInstallPackage-WiYBwhUO.js} +1 -1
  292. package/dist/assets/{useInterval-CC0vKpWm.js → useInterval-Be6s6idX.js} +1 -1
  293. package/dist/assets/useNotebookActions-CsZfWFKy.js +12 -0
  294. package/dist/assets/{useRunCells-CSSF_mJ0.js → useRunCells-CF_V8X2K.js} +1 -1
  295. package/dist/assets/{useSplitCell-9Qz93yPZ.js → useSplitCell-BTmKY1CU.js} +1 -1
  296. package/dist/assets/{useTheme-KXqAyDPC.js → useTheme-Bxv9B31g.js} +1 -1
  297. package/dist/assets/{utils-Z80SV4_d.js → utils-BWBBpCkT.js} +1 -1
  298. package/dist/assets/vb-CUif5uGR.js +1 -0
  299. package/dist/assets/vbscript-DWVPFl59.js +1 -0
  300. package/dist/assets/{vega-component-Cie3ag_T.js → vega-component-BYd6AACD.js} +1 -1
  301. package/dist/assets/{vega-embed-container-hDAVOOba.js → vega-embed-container-CRADa99b.js} +1 -1
  302. package/dist/assets/velocity-BJl8UzB4.js +1 -0
  303. package/dist/assets/verilog-B4LUPYXy.js +1 -0
  304. package/dist/assets/vhdl-C91h3ipk.js +1 -0
  305. package/dist/assets/webidl-DOay1zbU.js +1 -0
  306. package/dist/assets/write-secret-modal-D-p66LIx.js +2 -0
  307. package/dist/assets/xquery-Cez7jD_4.js +1 -0
  308. package/dist/assets/{xychartDiagram-PRI3JC2R-Cb0exSKs.js → xychartDiagram-PRI3JC2R-BX6ICxcN.js} +1 -1
  309. package/dist/assets/yacas-CSQEXB_S.js +1 -0
  310. package/dist/assets/z80-CJbYj7Wr.js +1 -0
  311. package/dist/index.html +74 -73
  312. package/package.json +3 -4
  313. package/src/__mocks__/requests.ts +45 -4
  314. package/src/components/data-table/__tests__/__snapshots__/chart-spec-model.test.ts.snap +174 -21
  315. package/src/components/data-table/__tests__/chart-spec-model.test.ts +102 -1
  316. package/src/components/data-table/column-summary/chart-spec-model.tsx +163 -103
  317. package/src/components/data-table/column-summary/legacy-chart-spec.ts +15 -7
  318. package/src/components/data-table/column-summary/utils.ts +26 -7
  319. package/src/components/data-table/types.ts +1 -1
  320. package/src/components/editor/__tests__/viewer-banner.test.tsx +14 -0
  321. package/src/components/editor/actions/__tests__/pair-with-agent-commands.test.ts +99 -18
  322. package/src/components/editor/actions/__tests__/pdf-export.test.ts +32 -13
  323. package/src/components/editor/actions/pair-with-agent-commands.ts +21 -10
  324. package/src/components/editor/actions/pair-with-agent-modal.tsx +2 -2
  325. package/src/components/editor/actions/pdf-export.ts +11 -14
  326. package/src/components/editor/actions/useNotebookActions.tsx +18 -18
  327. package/src/components/editor/cell/code/__tests__/cell-editor-activity-lifecycle.test.ts +250 -0
  328. package/src/components/editor/cell/code/cell-editor.tsx +13 -7
  329. package/src/components/editor/chrome/panels/__tests__/logs-panel.test.tsx +25 -0
  330. package/src/components/editor/chrome/panels/logs-panel.tsx +12 -2
  331. package/src/components/editor/chrome/panels/write-secret-modal.tsx +40 -12
  332. package/src/components/editor/connections/__tests__/json-credentials.test.ts +114 -0
  333. package/src/components/editor/connections/__tests__/paths.test.ts +39 -0
  334. package/src/components/editor/connections/components.tsx +6 -2
  335. package/src/components/editor/connections/database/__tests__/__snapshots__/as-code.test.ts.snap +21 -5
  336. package/src/components/editor/connections/database/__tests__/as-code.test.ts +17 -0
  337. package/src/components/editor/connections/database/as-code.ts +16 -2
  338. package/src/components/editor/connections/database/schemas.ts +6 -5
  339. package/src/components/editor/connections/form-renderers.tsx +99 -1
  340. package/src/components/editor/connections/json-credentials.ts +57 -0
  341. package/src/components/editor/connections/paths.ts +21 -0
  342. package/src/components/editor/connections/secret-combobox.tsx +41 -20
  343. package/src/components/editor/connections/storage/__tests__/__snapshots__/as-code.test.ts.snap +88 -2
  344. package/src/components/editor/connections/storage/__tests__/as-code.test.ts +128 -8
  345. package/src/components/editor/connections/storage/as-code.ts +79 -36
  346. package/src/components/editor/connections/storage/schemas.ts +85 -44
  347. package/src/components/editor/file-tree/__tests__/renderers.test.ts +31 -0
  348. package/src/components/editor/file-tree/file-viewer.tsx +11 -7
  349. package/src/components/editor/file-tree/renderers.tsx +21 -0
  350. package/src/components/editor/renderers/vertical-layout/vertical-layout.tsx +1 -1
  351. package/src/components/editor/viewer-banner.tsx +6 -1
  352. package/src/components/forms/options.ts +2 -1
  353. package/src/components/slides/__tests__/cell-output-block.test.tsx +40 -0
  354. package/src/components/slides/__tests__/slide-cell-view.test.tsx +33 -0
  355. package/src/components/slides/__tests__/slide-scroll-hint.test.tsx +198 -0
  356. package/src/components/slides/reveal-component.tsx +25 -19
  357. package/src/components/slides/slide-cell-view.tsx +1 -1
  358. package/src/components/slides/slide-scroll-hint.tsx +161 -0
  359. package/src/components/slides/slides.css +4 -2
  360. package/src/components/static-html/share-modal.tsx +1 -1
  361. package/src/components/ui/input.tsx +1 -1
  362. package/src/core/ai/context/providers/file.ts +8 -29
  363. package/src/core/cells/__tests__/cells.test.ts +12 -2
  364. package/src/core/cells/__tests__/logs.test.ts +5 -5
  365. package/src/core/cells/cells.ts +17 -4
  366. package/src/core/cells/document-changes.ts +1 -0
  367. package/src/core/cells/logs.ts +14 -4
  368. package/src/core/codemirror/copilot/__tests__/language-server.test.ts +396 -100
  369. package/src/core/codemirror/copilot/__tests__/transport.test.ts +128 -540
  370. package/src/core/codemirror/copilot/language-server.ts +182 -70
  371. package/src/core/codemirror/copilot/transport.ts +15 -207
  372. package/src/core/codemirror/copilot/types.ts +9 -2
  373. package/src/core/codemirror/find-replace/__tests__/navigate.test.ts +42 -30
  374. package/src/core/codemirror/find-replace/navigate.ts +2 -0
  375. package/src/core/codemirror/go-to-definition/__tests__/commands.test.ts +24 -3
  376. package/src/core/codemirror/go-to-definition/commands.ts +3 -0
  377. package/src/core/codemirror/keymaps/__tests__/keymaps.test.ts +31 -2
  378. package/src/core/codemirror/keymaps/keymaps.ts +12 -0
  379. package/src/core/codemirror/language/__tests__/sql.test.ts +443 -61
  380. package/src/core/codemirror/language/languages/python.ts +23 -11
  381. package/src/core/codemirror/language/languages/sql/completion-store.ts +5 -1
  382. package/src/core/codemirror/language/languages/sql/sql.ts +210 -3
  383. package/src/core/codemirror/lsp/__tests__/federated-lsp.test.ts +161 -0
  384. package/src/core/codemirror/lsp/__tests__/log-messages.test.ts +53 -0
  385. package/src/core/codemirror/lsp/__tests__/normalize-markdown-math.test.ts +25 -0
  386. package/src/core/codemirror/lsp/__tests__/notebook-lsp.test.ts +598 -156
  387. package/src/core/codemirror/lsp/__tests__/transports.test.ts +112 -0
  388. package/src/core/codemirror/lsp/federated-lsp.ts +76 -23
  389. package/src/core/codemirror/lsp/log-messages.ts +37 -0
  390. package/src/core/codemirror/lsp/normalize-markdown-math.ts +8 -4
  391. package/src/core/codemirror/lsp/notebook-lsp.ts +220 -56
  392. package/src/core/codemirror/lsp/transports.ts +8 -1
  393. package/src/core/codemirror/lsp/types.ts +68 -8
  394. package/src/core/codemirror/lsp/utils.ts +14 -0
  395. package/src/core/codemirror/utils.ts +28 -0
  396. package/src/core/edit-app.tsx +1 -2
  397. package/src/core/export/__tests__/hooks.test.ts +2 -4
  398. package/src/core/export/hooks.ts +4 -3
  399. package/src/core/hotkeys/hotkeys.ts +0 -2
  400. package/src/core/islands/__tests__/bridge.test.ts +107 -0
  401. package/src/core/islands/bridge.ts +16 -0
  402. package/src/core/lsp/__tests__/transport.test.ts +509 -337
  403. package/src/core/lsp/transport.ts +304 -132
  404. package/src/core/mode.ts +10 -0
  405. package/src/core/network/__tests__/api.test.ts +42 -0
  406. package/src/core/network/__tests__/connection.test.ts +45 -0
  407. package/src/core/network/__tests__/requests-lazy.test.ts +32 -1
  408. package/src/core/network/__tests__/requests-network.test.ts +21 -0
  409. package/src/core/network/api.ts +27 -0
  410. package/src/core/network/connection.ts +15 -0
  411. package/src/core/network/requests-lazy.ts +1 -0
  412. package/src/core/network/requests-network.ts +14 -8
  413. package/src/core/network/requests-static.ts +1 -0
  414. package/src/core/network/requests-toasting.tsx +1 -0
  415. package/src/core/network/types.ts +22 -6
  416. package/src/core/rtc/state.ts +9 -0
  417. package/src/core/static/download-html.ts +5 -14
  418. package/src/core/wasm/bridge.ts +4 -2
  419. package/src/core/wasm/worker/types.ts +5 -2
  420. package/src/css/app/codemirror.css +16 -2
  421. package/src/plugins/impl/FormPlugin.tsx +1 -1
  422. package/src/plugins/impl/__tests__/FormPlugin.test.tsx +162 -0
  423. package/src/stories/log-viewer.stories.tsx +12 -6
  424. package/src/utils/__tests__/blob.test.ts +27 -1
  425. package/src/utils/__tests__/download.test.tsx +44 -4
  426. package/src/utils/blob.ts +24 -1
  427. package/src/utils/download.ts +14 -15
  428. package/dist/assets/JsonOutput-CkCD-FgM.js +0 -53
  429. package/dist/assets/LazyAnyLanguageCodeMirror-sVm_hz8A.js +0 -2
  430. package/dist/assets/RenderHTML-BCvU9dYz.js +0 -1
  431. package/dist/assets/add-connection-dialog-B-jCRNTN.js +0 -170
  432. package/dist/assets/ai-model-dropdown-DXgLphFa.js +0 -5
  433. package/dist/assets/apl-DTwRFDps.js +0 -1
  434. package/dist/assets/app-config-button-NrM9ywXA.js +0 -1
  435. package/dist/assets/asciiarmor-CiqkDK0s.js +0 -1
  436. package/dist/assets/asn1-RTvH5MEs.js +0 -1
  437. package/dist/assets/blob-C3EfaMOb.js +0 -1
  438. package/dist/assets/brainfuck-szH_VGzd.js +0 -1
  439. package/dist/assets/cell-link-DqBkyAFe.js +0 -1
  440. package/dist/assets/cells-Cf7bHHq3.js +0 -229
  441. package/dist/assets/channel-D-k8o3T1.js +0 -1
  442. package/dist/assets/chunk-55IACEB6-xhaY4LU6.js +0 -1
  443. package/dist/assets/classDiagram-2ON5EDUG-C-rIg7EQ.js +0 -1
  444. package/dist/assets/classDiagram-v2-WZHVMYZB-MBAsRLae.js +0 -1
  445. package/dist/assets/clojure-CyEbLmch.js +0 -1
  446. package/dist/assets/cmake-Dk8f7QuI.js +0 -1
  447. package/dist/assets/cobol-BJJRqW1D.js +0 -1
  448. package/dist/assets/coffeescript-BDuWJ9WO.js +0 -1
  449. package/dist/assets/commonlisp-CVHm2VSp.js +0 -1
  450. package/dist/assets/components-BH6gDVv6.js +0 -1
  451. package/dist/assets/config-BbOTTCYY.js +0 -1
  452. package/dist/assets/crystal-C2Fgr79A.js +0 -1
  453. package/dist/assets/cypher-CUlCm6vR.js +0 -1
  454. package/dist/assets/d-4ANEHA6q.js +0 -1
  455. package/dist/assets/diff-C-W-5V8L.js +0 -1
  456. package/dist/assets/dist-BCMBu0rO.js +0 -2
  457. package/dist/assets/dist-CCAhuqF-.js +0 -1
  458. package/dist/assets/dist-DGhK0kPE.js +0 -1
  459. package/dist/assets/dist-SVDIDTM2.js +0 -1
  460. package/dist/assets/dist-xSLg7wNV.js +0 -1
  461. package/dist/assets/download-BomYt3nl.js +0 -9
  462. package/dist/assets/dtd-D9h-tL8G.js +0 -1
  463. package/dist/assets/dylan-D3MC56xy.js +0 -1
  464. package/dist/assets/ecl-B6UC4tME.js +0 -1
  465. package/dist/assets/eiffel-CjvEov4k.js +0 -1
  466. package/dist/assets/elm-DvSbvRWe.js +0 -1
  467. package/dist/assets/erlang-DJYaGXyq.js +0 -1
  468. package/dist/assets/error-entries-Birw-8VX.js +0 -8
  469. package/dist/assets/factor-CUQCrkTo.js +0 -1
  470. package/dist/assets/file-explorer-panel-Ntq1-VbF.js +0 -26
  471. package/dist/assets/floating-outline-wz-WSRgP.js +0 -1
  472. package/dist/assets/focus-DiEyfiAG.js +0 -1
  473. package/dist/assets/forth-D9xegiCO.js +0 -1
  474. package/dist/assets/fortran-B0Oe0U8s.js +0 -1
  475. package/dist/assets/gas-jLjj-PIq.js +0 -1
  476. package/dist/assets/gherkin-3Ig8Crit.js +0 -1
  477. package/dist/assets/groovy-NKpNVJ-n.js +0 -1
  478. package/dist/assets/haskell-OPE4bAjk.js +0 -1
  479. package/dist/assets/haxe-DEAZF8L3.js +0 -1
  480. package/dist/assets/home-page-DJ4jJsZj.js +0 -4
  481. package/dist/assets/idl-BM6265Xl.js +0 -1
  482. package/dist/assets/index-A71LAt6h.css +0 -2
  483. package/dist/assets/index-CMZzy-dF.js +0 -38
  484. package/dist/assets/infoDiagram-HS3SLOUP-DQnMjKYJ.js +0 -2
  485. package/dist/assets/javascript-CZ9vDpAy.js +0 -1
  486. package/dist/assets/julia-BrY9TQnt.js +0 -1
  487. package/dist/assets/katex-C-lfa1AM.js +0 -1
  488. package/dist/assets/kiosk-mode-ABm3oYgq.js +0 -1
  489. package/dist/assets/livescript-CNahkUp5.js +0 -1
  490. package/dist/assets/logs-panel-iFV4ZJ9b.js +0 -1
  491. package/dist/assets/lua-Skr4TVu_.js +0 -1
  492. package/dist/assets/mathematica-BXxhrpeY.js +0 -1
  493. package/dist/assets/mbox-BRrQCVe9.js +0 -1
  494. package/dist/assets/mirc-CffYPE4R.js +0 -1
  495. package/dist/assets/mllike-C1DLZhEI.js +0 -1
  496. package/dist/assets/modelica-CvAyRRNV.js +0 -1
  497. package/dist/assets/mscgen-uMZWtMZv.js +0 -1
  498. package/dist/assets/mumps-DFJehEx7.js +0 -1
  499. package/dist/assets/node-sql-parser-BWgUjcfV.js +0 -68
  500. package/dist/assets/nsis-BVI9YULz.js +0 -1
  501. package/dist/assets/ntriples-Bcdh7b2H.js +0 -1
  502. package/dist/assets/octave-CdAKz6YS.js +0 -1
  503. package/dist/assets/oz-DSySeR-W.js +0 -1
  504. package/dist/assets/pair-with-agent-modal-CKOYwOYw.js +0 -4
  505. package/dist/assets/panels-Dj45fW-v.js +0 -4
  506. package/dist/assets/pascal-DefziIUN.js +0 -1
  507. package/dist/assets/perl-BOOloBPk.js +0 -1
  508. package/dist/assets/pig-f0nBb-5x.js +0 -1
  509. package/dist/assets/powershell-DToQjbK9.js +0 -1
  510. package/dist/assets/process-output-BEhIGfkO.js +0 -1
  511. package/dist/assets/properties-BRob-nyj.js +0 -1
  512. package/dist/assets/protobuf-DZyC6051.js +0 -1
  513. package/dist/assets/pug-pVoM8FRt.js +0 -1
  514. package/dist/assets/puppet-9fuYG07F.js +0 -1
  515. package/dist/assets/python-_Mr8fyXP.js +0 -1
  516. package/dist/assets/q-D73s4Y77.js +0 -1
  517. package/dist/assets/r-BOEjz92e.js +0 -1
  518. package/dist/assets/rpm-LpXWTM5t.js +0 -1
  519. package/dist/assets/ruby-DodgSDfF.js +0 -1
  520. package/dist/assets/sas-D9KCtUmL.js +0 -1
  521. package/dist/assets/scheme-p8UJxmJw.js +0 -1
  522. package/dist/assets/scratchpad-panel-B0mEqBNk.js +0 -1
  523. package/dist/assets/session-panel-Y0Oon0sD.js +0 -1
  524. package/dist/assets/shell-BWdqyqwL.js +0 -1
  525. package/dist/assets/sieve-CLwJmtiQ.js +0 -1
  526. package/dist/assets/slides-MCbMDtlY.css +0 -1
  527. package/dist/assets/smalltalk-D3KV-Qah.js +0 -1
  528. package/dist/assets/sparql-D9Jz2mBw.js +0 -1
  529. package/dist/assets/state-BZQc7xxL.js +0 -3
  530. package/dist/assets/stateDiagram-v2-4FDKWEC3-CA1l0rNa.js +0 -1
  531. package/dist/assets/stylus-ClN4l_XO.js +0 -1
  532. package/dist/assets/swift-Dvd_9xBv.js +0 -1
  533. package/dist/assets/switch-CvweaCXq.js +0 -1
  534. package/dist/assets/tcl-DR2p8cyi.js +0 -1
  535. package/dist/assets/textarea-CpFfEUet.js +0 -1
  536. package/dist/assets/textile-D6S27_J2.js +0 -1
  537. package/dist/assets/toml-B-YuQ2Id.js +0 -1
  538. package/dist/assets/troff-HSk8AoRF.js +0 -1
  539. package/dist/assets/ttcn-CehzlVdx.js +0 -1
  540. package/dist/assets/ttcn-cfg-CLEPwk1s.js +0 -1
  541. package/dist/assets/turtle-DQLHkbOu.js +0 -1
  542. package/dist/assets/useCellActionButton-CRfIEVB5.js +0 -1
  543. package/dist/assets/useEventListener-B_w3A283.js +0 -1
  544. package/dist/assets/useNotebookActions-DTXAoukG.js +0 -12
  545. package/dist/assets/vb-o1EHrS4z.js +0 -1
  546. package/dist/assets/vbscript-BS8yUFpf.js +0 -1
  547. package/dist/assets/velocity-u_oGPFaA.js +0 -1
  548. package/dist/assets/verilog-CSmDH7su.js +0 -1
  549. package/dist/assets/vhdl-BCaWLcjw.js +0 -1
  550. package/dist/assets/webidl-Bf6dokXM.js +0 -1
  551. package/dist/assets/write-secret-modal-DEEn7sZV.js +0 -1
  552. package/dist/assets/xquery-Di0kkiXg.js +0 -1
  553. package/dist/assets/yacas-DB8tPtyp.js +0 -1
  554. package/dist/assets/z80-DFUvlWxk.js +0 -1
  555. /package/dist/assets/{ImageComparisonComponent-Cz3xVDLH.js → ImageComparisonComponent-HnxpPJnM.js} +0 -0
  556. /package/dist/assets/{Inputs-B8-VCb_j.js → Inputs-BhvqLBkk.js} +0 -0
  557. /package/dist/assets/{Plot-X2G47XHf.js → Plot-Df7XX6zz.js} +0 -0
  558. /package/dist/assets/{apl-DVqFAlEd.js → apl-CPlG1HX3.js} +0 -0
  559. /package/dist/assets/{array-Ddg9CgJT.js → array-DkMvCrqF.js} +0 -0
  560. /package/dist/assets/{asciiarmor-B45BhOLj.js → asciiarmor-DV_pcocJ.js} +0 -0
  561. /package/dist/assets/{asn1-C4T2ctU6.js → asn1-DPxWcGvG.js} +0 -0
  562. /package/dist/assets/{asterisk-9U_4Kgke.js → asterisk-Di-nanOd.js} +0 -0
  563. /package/dist/assets/{azure-nN8APleF.js → azure-BjL5s4-w.js} +0 -0
  564. /package/dist/assets/{brainfuck-kVh8Eud4.js → brainfuck-CGDdBVNO.js} +0 -0
  565. /package/dist/assets/{card-VUBaYDpT.js → card-DIbLM4TA.js} +0 -0
  566. /package/dist/assets/{chunk-4F5CHEZ2-ClSh5rxG.js → chunk-4F5CHEZ2-yOSqdjGN.js} +0 -0
  567. /package/dist/assets/{chunk-B2363JML-cit0ouFv.js → chunk-B2363JML-BqlxcdFI.js} +0 -0
  568. /package/dist/assets/{chunk-DR5Q36YT-Bsu9Glc0.js → chunk-DR5Q36YT-9bsCT1tL.js} +0 -0
  569. /package/dist/assets/{chunk-FRFDVMJY--Re1QfFE.js → chunk-FRFDVMJY-DW58IWII.js} +0 -0
  570. /package/dist/assets/{chunk-PL6DKKU2-CAwRAr-p.js → chunk-PL6DKKU2-CiPkyomE.js} +0 -0
  571. /package/dist/assets/{chunk-SJTYNZTY-G1spWesO.js → chunk-SJTYNZTY-UJLIXgY2.js} +0 -0
  572. /package/dist/assets/{chunk-TQ3KTPDO-DBwra5xv.js → chunk-TQ3KTPDO-DQFcRP5c.js} +0 -0
  573. /package/dist/assets/{chunk-UMXZTB3W-A5RvYDPE.js → chunk-UMXZTB3W-cibob28z.js} +0 -0
  574. /package/dist/assets/{clear-button-DQtvx6eq.js → clear-button-Bsxh4lx1.js} +0 -0
  575. /package/dist/assets/{click-outside-container-CrWZsAF5.js → click-outside-container-LfSB2_ne.js} +0 -0
  576. /package/dist/assets/{clike-O0gwXilc.js → clike-D91DrsBh.js} +0 -0
  577. /package/dist/assets/{clojure-CsbMWxp9.js → clojure-B0eb_-2q.js} +0 -0
  578. /package/dist/assets/{cmake-FpJvOdyj.js → cmake-COzUvjiS.js} +0 -0
  579. /package/dist/assets/{cobol-Duxbpsru.js → cobol-DW4FSnmb.js} +0 -0
  580. /package/dist/assets/{coffeescript-D-Unz9IP.js → coffeescript-CommR2mv.js} +0 -0
  581. /package/dist/assets/{colors-C_0lIznd.js → colors-CyQT5OPu.js} +0 -0
  582. /package/dist/assets/{common-keywords-PqH2GDfH.js → common-keywords-Bk-0jOKl.js} +0 -0
  583. /package/dist/assets/{commonlisp-_nR12oc7.js → commonlisp-FR_N9RJL.js} +0 -0
  584. /package/dist/assets/{crystal-dj3W4b1A.js → crystal-CAN7bz25.js} +0 -0
  585. /package/dist/assets/{css-0BG6A_BC.js → css-DmLg8a0m.js} +0 -0
  586. /package/dist/assets/{cypher-CKPokaoH.js → cypher-BzSJn05x.js} +0 -0
  587. /package/dist/assets/{cytoscape.esm-DzUNSF80.js → cytoscape.esm-CVhOSlMZ.js} +0 -0
  588. /package/dist/assets/{d-BrbqzVa2.js → d-UpmnByGo.js} +0 -0
  589. /package/dist/assets/{diff-BmdR9FsO.js → diff-DRpitNo9.js} +0 -0
  590. /package/dist/assets/{dist-CM-lWxt3.js → dist-1DJkf78n.js} +0 -0
  591. /package/dist/assets/{dist-ByK00N0T.js → dist-6KRysbQA.js} +0 -0
  592. /package/dist/assets/{dist-98K4fusX.js → dist-8H9kNP92.js} +0 -0
  593. /package/dist/assets/{dist-OgwOt8T2.js → dist-8lZYHUSx.js} +0 -0
  594. /package/dist/assets/{dist-DNGKAtWk.js → dist-B4sFEC9P.js} +0 -0
  595. /package/dist/assets/{dist-BaKJ0-Tb.js → dist-B5BlmbY-.js} +0 -0
  596. /package/dist/assets/{dist-CpbbK4-I.js → dist-BDUj3vkc.js} +0 -0
  597. /package/dist/assets/{dist-3N7-WLqi.js → dist-C13NfWpP.js} +0 -0
  598. /package/dist/assets/{dist-DokId-qM.js → dist-C3XTRycV.js} +0 -0
  599. /package/dist/assets/{dist-56ul6-mm.js → dist-C6uSSUmH.js} +0 -0
  600. /package/dist/assets/{dist-D5ToCtv8.js → dist-CDFlR-dv.js} +0 -0
  601. /package/dist/assets/{dist-DzAAhYcW.js → dist-CaADT3TK.js} +0 -0
  602. /package/dist/assets/{dist-B8g3pNYJ.js → dist-CbTMGxEf.js} +0 -0
  603. /package/dist/assets/{dist-O5-NiN3f.js → dist-CjpCHqUI.js} +0 -0
  604. /package/dist/assets/{dist-D9sE1udr.js → dist-D0BTeZL0.js} +0 -0
  605. /package/dist/assets/{dist-DrtRBAn8.js → dist-DE4Vb9tO.js} +0 -0
  606. /package/dist/assets/{dist-D35OyUMQ.js → dist-DYsXEge_.js} +0 -0
  607. /package/dist/assets/{dist-C5kf6g-d.js → dist-lCLEUACp.js} +0 -0
  608. /package/dist/assets/{dtd-DbCXDVgi.js → dtd-CQV9N2ok.js} +0 -0
  609. /package/dist/assets/{duckdb-keywords-mPlR0SxW.js → duckdb-keywords-CqO5LWsh.js} +0 -0
  610. /package/dist/assets/{dylan-CLLzL2Js.js → dylan-Bp98yT5y.js} +0 -0
  611. /package/dist/assets/{ebnf-Cnws41cu.js → ebnf-DoGvzVmX.js} +0 -0
  612. /package/dist/assets/{ecl-BC7x2nzk.js → ecl-BgtQ3zu5.js} +0 -0
  613. /package/dist/assets/{eiffel-CDU836rz.js → eiffel-Cu14O7Gi.js} +0 -0
  614. /package/dist/assets/{elm-D-_bXARs.js → elm-Dp1dn40k.js} +0 -0
  615. /package/dist/assets/{empty-state-CqJvEFRk.js → empty-state-yX2_pzkH.js} +0 -0
  616. /package/dist/assets/{erlang-CwDZk2zM.js → erlang-DdogJjdp.js} +0 -0
  617. /package/dist/assets/{esm-D6WfbcL3.js → esm-DZILy413.js} +0 -0
  618. /package/dist/assets/{fcl-CwkPc-_9.js → fcl-CTs4ROWI.js} +0 -0
  619. /package/dist/assets/{forth-D6FsO_8x.js → forth-Dd0r86IP.js} +0 -0
  620. /package/dist/assets/{fortran-D4BMbIkG.js → fortran-4qvtlW4z.js} +0 -0
  621. /package/dist/assets/{gas-JFjzcgdY.js → gas-DqwqZHXy.js} +0 -0
  622. /package/dist/assets/{gherkin-Cyu-qGaF.js → gherkin-DMxJEDh5.js} +0 -0
  623. /package/dist/assets/{github-_JH-0hIO.js → github-kTVN-x1m.js} +0 -0
  624. /package/dist/assets/{groovy-CZaE9eN-.js → groovy-DA_MxBua.js} +0 -0
  625. /package/dist/assets/{haskell-Dc6o0IGr.js → haskell-B_hi8VEK.js} +0 -0
  626. /package/dist/assets/{haxe-Bsf0tzqs.js → haxe-D-I6YeRN.js} +0 -0
  627. /package/dist/assets/{http-BQNSD-HR.js → http-Ci3E2pzn.js} +0 -0
  628. /package/dist/assets/{idl-1W91kQ8_.js → idl-CteRrHSs.js} +0 -0
  629. /package/dist/assets/{init-nx27Zb9l.js → init-CYoUL2Ak.js} +0 -0
  630. /package/dist/assets/{javascript-BZ81-2rO.js → javascript-Cq9DsvSW.js} +0 -0
  631. /package/dist/assets/{julia-BZOsq0r_.js → julia-bHGj6eLp.js} +0 -0
  632. /package/dist/assets/{katex-CvZ3kCGk.js → katex-BKFLE8En.js} +0 -0
  633. /package/dist/assets/{livescript-CNZfmikk.js → livescript-C72YlTeO.js} +0 -0
  634. /package/dist/assets/{loro_wasm_bg-RNUly1SE.js → loro_wasm_bg-aCH66ryB.js} +0 -0
  635. /package/dist/assets/{lua-DXGRliwd.js → lua-DAtJrHXr.js} +0 -0
  636. /package/dist/assets/{marimo-icons-C_nFooxr.js → marimo-icons-Bq_N9GGs.js} +0 -0
  637. /package/dist/assets/{math-CLO4uoaP.js → math-D6WZfqI3.js} +0 -0
  638. /package/dist/assets/{mathematica-BoUj8M7D.js → mathematica-DGp7b8Lx.js} +0 -0
  639. /package/dist/assets/{mbox-DLVP8LAe.js → mbox-C35KjfEV.js} +0 -0
  640. /package/dist/assets/{mirc-kI4d5fMu.js → mirc-BRCHEPv1.js} +0 -0
  641. /package/dist/assets/{mllike-CD9vBc_2.js → mllike-D7ajla-U.js} +0 -0
  642. /package/dist/assets/{modelica-DgfsLJuF.js → modelica-0RGVL4ie.js} +0 -0
  643. /package/dist/assets/{mscgen-B1HDwshJ.js → mscgen-C7Ohs4Tl.js} +0 -0
  644. /package/dist/assets/{multi-icon-nrKPWjDU.js → multi-icon-C2ijLyOs.js} +0 -0
  645. /package/dist/assets/{mumps-D_-b9TZD.js → mumps-Cgag5Xef.js} +0 -0
  646. /package/dist/assets/{nginx-Cm282mo8.js → nginx-k5GTB7o1.js} +0 -0
  647. /package/dist/assets/{ntriples-COX9JFZ8.js → ntriples-oQv5c69K.js} +0 -0
  648. /package/dist/assets/{octave-BejycR79.js → octave-BMTXs4lo.js} +0 -0
  649. /package/dist/assets/{oz-CFFivrGn.js → oz-CuHYwo8r.js} +0 -0
  650. /package/dist/assets/{panel-context-CH75ubGG.js → panel-context-CmeYEpWr.js} +0 -0
  651. /package/dist/assets/{pascal-B_p9jkCs.js → pascal-eFKoVV2p.js} +0 -0
  652. /package/dist/assets/{path-Bz_hIzg5.js → path-BcLO3NWe.js} +0 -0
  653. /package/dist/assets/{pathUtils-Bfcp5m-a.js → pathUtils-BbJtW9Mp.js} +0 -0
  654. /package/dist/assets/{perl-C-SFBTly.js → perl-B1OqOW8w.js} +0 -0
  655. /package/dist/assets/{pig-BhxDMp2k.js → pig-gIrBDx27.js} +0 -0
  656. /package/dist/assets/{powershell-c59M-9N2.js → powershell-3fQF2XND.js} +0 -0
  657. /package/dist/assets/{properties-D1JNwCKy.js → properties-D4HHpZmU.js} +0 -0
  658. /package/dist/assets/{protobuf-DQS7ex8R.js → protobuf-DFSTKR0L.js} +0 -0
  659. /package/dist/assets/{puppet-DaQvhvew.js → puppet-BAISgXk9.js} +0 -0
  660. /package/dist/assets/{python-XHl3eRTS.js → python-mPctBCbA.js} +0 -0
  661. /package/dist/assets/{q-DppnoRE3.js → q-CYeV5Dbb.js} +0 -0
  662. /package/dist/assets/{r-D8-F_FWj.js → r-Ds4UrjIV.js} +0 -0
  663. /package/dist/assets/{request-registry-DHocQ_4I.js → request-registry-CEkYnwgr.js} +0 -0
  664. /package/dist/assets/{requests-DYeT4CEe.js → requests-CIR84T8A.js} +0 -0
  665. /package/dist/assets/{rpm-CegJhNNO.js → rpm-DV5-r6dM.js} +0 -0
  666. /package/dist/assets/{ruby-YMIxufV1.js → ruby-B9qrycrI.js} +0 -0
  667. /package/dist/assets/{sas-wTtX9UIQ.js → sas-Cd7L1ZOe.js} +0 -0
  668. /package/dist/assets/{scheme-BGenom3k.js → scheme-L6Kva-Kc.js} +0 -0
  669. /package/dist/assets/{semaphore-DtBYRzWS.js → semaphore-YOr3WMiw.js} +0 -0
  670. /package/dist/assets/{shell-Bu1sLaiP.js → shell-Ck42V1Kn.js} +0 -0
  671. /package/dist/assets/{sieve-ffe6rUQh.js → sieve-DfSJcUfS.js} +0 -0
  672. /package/dist/assets/{simple-mode-DBSzUJLA.js → simple-mode-CfoR0Lvg.js} +0 -0
  673. /package/dist/assets/{smalltalk-NU5EGjHp.js → smalltalk-CT418Iph.js} +0 -0
  674. /package/dist/assets/{solr-ptw1yIqO.js → solr-DfAVBX8L.js} +0 -0
  675. /package/dist/assets/{sparql-uqVktnwO.js → sparql-BlJ_cLEt.js} +0 -0
  676. /package/dist/assets/{spreadsheet-VEzeu_mb.js → spreadsheet-Qy1VjLDU.js} +0 -0
  677. /package/dist/assets/{sql-tYjnWETe.js → sql-BAkD7JGK.js} +0 -0
  678. /package/dist/assets/{src-BshXgZd4.js → src-Dlf0iGaF.js} +0 -0
  679. /package/dist/assets/{stylus-B2E6Ulaz.js → stylus-92qIiGm1.js} +0 -0
  680. /package/dist/assets/{swift-Rmnn7ATv.js → swift-gZzicbJu.js} +0 -0
  681. /package/dist/assets/{tcl-ZPWCn2nn.js → tcl-CtgoBYkk.js} +0 -0
  682. /package/dist/assets/{textile-uhA33kFk.js → textile-Du3RzJ2D.js} +0 -0
  683. /package/dist/assets/{tiddlywiki-CPkGLyXH.js → tiddlywiki-CL3W3RpP.js} +0 -0
  684. /package/dist/assets/{tiki-BtjLo8OF.js → tiki-2L3jCwab.js} +0 -0
  685. /package/dist/assets/{timer-VYMLXPue.js → timer-DLLzXmjF.js} +0 -0
  686. /package/dist/assets/{toml-BFZv2Mv7.js → toml-HcF44TVB.js} +0 -0
  687. /package/dist/assets/{treemap-Bca0xNNq.js → treemap-BdaAyoGw.js} +0 -0
  688. /package/dist/assets/{troff-B5eayHop.js → troff-xbwT4huN.js} +0 -0
  689. /package/dist/assets/{ttcn-cfg-CfbkL3Q_.js → ttcn-cfg-jWDg1i50.js} +0 -0
  690. /package/dist/assets/{ttcn-BM0Yp8NY.js → ttcn-phKysj_0.js} +0 -0
  691. /package/dist/assets/{turtle-DvetLxrv.js → turtle-CPC48wcy.js} +0 -0
  692. /package/dist/assets/{types-Da7lA5YC.js → types-C7hjolXC.js} +0 -0
  693. /package/dist/assets/{use-vega-container-remeasure-CbKTb_jy.js → use-vega-container-remeasure-0GBen_rR.js} +0 -0
  694. /package/dist/assets/{vb-i5Z8scch.js → vb-BTubZ2rB.js} +0 -0
  695. /package/dist/assets/{vbscript-BiPYgIyi.js → vbscript-B52mDFWM.js} +0 -0
  696. /package/dist/assets/{velocity-Dw3R3YoX.js → velocity-BO3M1iFD.js} +0 -0
  697. /package/dist/assets/{verilog-B8FhJcX6.js → verilog-CBz90JJu.js} +0 -0
  698. /package/dist/assets/{vhdl-BqPEoXdJ.js → vhdl-CeQ1lGlV.js} +0 -0
  699. /package/dist/assets/{web-vitals-CwE0GGzl.js → web-vitals-Q0-_CtWm.js} +0 -0
  700. /package/dist/assets/{webidl-mMO-qW5Q.js → webidl-CRtF5pmu.js} +0 -0
  701. /package/dist/assets/{ws-BmTnbVEi.js → ws-CNqquaud.js} +0 -0
  702. /package/dist/assets/{xquery-DvqNwq7L.js → xquery-CFnbrHav.js} +0 -0
  703. /package/dist/assets/{yacas-Dku9Z6Kf.js → yacas-KIC_JO6M.js} +0 -0
  704. /package/dist/assets/{z80-DvazU5Tr.js → z80-kGpw5_me.js} +0 -0
@@ -1,439 +1,611 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
- /* oxlint-disable typescript/no-explicit-any */
3
-
4
- import { WebSocketTransport } from "@open-rpc/client-js";
5
- import { beforeEach, describe, expect, it, vi } from "vitest";
2
+ import type { JSONRPCMessage } from "@marimo-team/codemirror-languageserver";
3
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
6
4
  import { Mocks } from "@/__mocks__/common";
5
+ import { isRecord } from "@/utils/records";
7
6
  import { ReconnectingWebSocketTransport } from "../transport";
8
7
 
9
- // Mock the Logger
10
8
  vi.mock("@/utils/Logger", () => ({
11
9
  Logger: Mocks.logger(),
12
10
  }));
13
11
 
14
- // Mock the WebSocketTransport
15
- vi.mock("@open-rpc/client-js", () => {
16
- const mockWebSocketTransport = vi.fn();
17
- mockWebSocketTransport.prototype.connect = vi.fn();
18
- mockWebSocketTransport.prototype.close = vi.fn();
19
- mockWebSocketTransport.prototype.sendData = vi.fn();
20
-
21
- return {
22
- WebSocketTransport: mockWebSocketTransport,
23
- };
24
- });
12
+ class FakeWebSocket {
13
+ static readonly CONNECTING = 0;
14
+ static readonly OPEN = 1;
15
+ static readonly CLOSING = 2;
16
+ static readonly CLOSED = 3;
17
+ static readonly instances: FakeWebSocket[] = [];
18
+
19
+ readonly sent: string[] = [];
20
+ readonly url: string;
21
+ readonly protocols: string | string[] | undefined;
22
+ readyState = FakeWebSocket.CONNECTING;
23
+ private readonly listeners = new Map<
24
+ string,
25
+ Set<(event: { data?: unknown }) => void>
26
+ >();
27
+
28
+ constructor(url: string, protocols?: string | string[]) {
29
+ this.url = url;
30
+ this.protocols = protocols;
31
+ FakeWebSocket.instances.push(this);
32
+ }
33
+
34
+ addEventListener(
35
+ type: string,
36
+ listener: (event: { data?: unknown }) => void,
37
+ ) {
38
+ const listeners = this.listeners.get(type) ?? new Set();
39
+ listeners.add(listener);
40
+ this.listeners.set(type, listeners);
41
+ }
42
+
43
+ send(frame: string) {
44
+ this.sent.push(frame);
45
+ }
46
+
47
+ close() {
48
+ this.readyState = FakeWebSocket.CLOSED;
49
+ this.emit("close", {});
50
+ }
51
+
52
+ open() {
53
+ this.readyState = FakeWebSocket.OPEN;
54
+ this.emit("open", {});
55
+ }
56
+
57
+ fail() {
58
+ this.emit("error", {});
59
+ }
60
+
61
+ disconnect() {
62
+ this.readyState = FakeWebSocket.CLOSED;
63
+ this.emit("close", {});
64
+ }
65
+
66
+ receive(message: JSONRPCMessage) {
67
+ this.emit("message", { data: JSON.stringify(message) });
68
+ }
69
+
70
+ messages(): JSONRPCMessage[] {
71
+ return this.sent.map((frame) => {
72
+ const message: unknown = JSON.parse(frame);
73
+ if (!isJSONRPCMessage(message)) {
74
+ throw new Error("Fake WebSocket received an invalid JSON-RPC message");
75
+ }
76
+ return message;
77
+ });
78
+ }
79
+
80
+ private emit(type: string, event: { data?: unknown }) {
81
+ for (const listener of this.listeners.get(type) ?? []) {
82
+ listener(event);
83
+ }
84
+ }
85
+ }
86
+
87
+ function isJSONRPCMessage(value: unknown): value is JSONRPCMessage {
88
+ if (!isRecord(value) || value.jsonrpc !== "2.0") {
89
+ return false;
90
+ }
91
+ if (typeof value.method === "string") {
92
+ return true;
93
+ }
94
+ return (
95
+ (typeof value.id === "string" || typeof value.id === "number") &&
96
+ ("result" in value || "error" in value)
97
+ );
98
+ }
99
+
100
+ async function getSocket(index: number): Promise<FakeWebSocket> {
101
+ await vi.waitFor(() => {
102
+ expect(FakeWebSocket.instances.length).toBeGreaterThan(index);
103
+ });
104
+ return FakeWebSocket.instances[index];
105
+ }
25
106
 
26
107
  describe("ReconnectingWebSocketTransport", () => {
27
108
  const mockWsUrl = "ws://localhost:8080/lsp";
28
- let mockConnection: any;
29
109
 
30
110
  beforeEach(() => {
31
- vi.clearAllMocks();
32
-
33
- // Create a mock WebSocket connection with readyState
34
- mockConnection = {
35
- readyState: WebSocket.OPEN,
36
- };
37
-
38
- // Mock the WebSocketTransport constructor to set the connection
39
- (WebSocketTransport as any).mockImplementation(function (this: any) {
40
- this.connection = mockConnection;
41
- this.connect = vi.fn().mockResolvedValue(undefined);
42
- this.close = vi.fn();
43
- this.sendData = vi.fn().mockResolvedValue({ result: "success" });
44
- this.subscribe = vi.fn();
45
- this.unsubscribe = vi.fn();
46
- });
111
+ FakeWebSocket.instances.length = 0;
112
+ vi.stubGlobal("WebSocket", FakeWebSocket);
47
113
  });
48
114
 
49
- it("should create a transport with the provided URL function", () => {
50
- const getWsUrl = vi.fn(() => mockWsUrl);
51
- const transport = new ReconnectingWebSocketTransport({ getWsUrl });
52
-
53
- expect(transport).toBeDefined();
54
- expect(getWsUrl).not.toHaveBeenCalled(); // URL function not called until connect
115
+ afterEach(() => {
116
+ vi.unstubAllGlobals();
55
117
  });
56
118
 
57
- it("should connect successfully", async () => {
58
- const getWsUrl = vi.fn(() => mockWsUrl);
59
- const transport = new ReconnectingWebSocketTransport({ getWsUrl });
60
-
61
- await transport.connect();
62
-
63
- expect(getWsUrl).toHaveBeenCalledTimes(1);
64
- expect(WebSocketTransport).toHaveBeenCalledWith(mockWsUrl);
65
- });
66
-
67
- it("should wait for connection before connecting", async () => {
119
+ it("waits for prerequisites and shares concurrent connection attempts", async () => {
120
+ let releaseConnection: (() => void) | undefined;
121
+ const waitForConnection = vi.fn(
122
+ () =>
123
+ new Promise<void>((resolve) => {
124
+ releaseConnection = resolve;
125
+ }),
126
+ );
68
127
  const getWsUrl = vi.fn(() => mockWsUrl);
69
- const waitForConnection = vi.fn().mockResolvedValue(undefined);
70
128
  const transport = new ReconnectingWebSocketTransport({
71
129
  getWsUrl,
72
130
  waitForConnection,
73
131
  });
74
132
 
75
- await transport.connect();
76
-
133
+ const firstConnection = transport.connect();
134
+ const secondConnection = transport.connect();
77
135
  expect(waitForConnection).toHaveBeenCalledTimes(1);
136
+ expect(FakeWebSocket.instances).toHaveLength(0);
137
+
138
+ releaseConnection?.();
139
+ const socket = await getSocket(0);
140
+ socket.open();
141
+ await Promise.all([firstConnection, secondConnection]);
142
+
143
+ expect(socket.url).toBe(mockWsUrl);
78
144
  expect(getWsUrl).toHaveBeenCalledTimes(1);
79
145
  });
80
146
 
81
- it("should reuse the same connection promise if already connecting", async () => {
82
- const getWsUrl = vi.fn(() => mockWsUrl);
83
- const waitForConnection = vi
84
- .fn()
85
- .mockImplementation(
86
- () => new Promise((resolve) => setTimeout(resolve, 100)),
87
- );
147
+ it("forwards messages in both directions and supports unsubscribe", async () => {
88
148
  const transport = new ReconnectingWebSocketTransport({
89
- getWsUrl,
90
- waitForConnection,
149
+ getWsUrl: () => mockWsUrl,
91
150
  });
151
+ const inbound = vi.fn();
152
+ const unsubscribe = transport.onMessage(inbound);
153
+ const connection = transport.connect();
154
+ const socket = await getSocket(0);
155
+ socket.open();
156
+ await connection;
157
+
158
+ const outbound: JSONRPCMessage = {
159
+ jsonrpc: "2.0",
160
+ method: "initialized",
161
+ params: {},
162
+ };
163
+ transport.send(outbound);
164
+ expect(socket.messages()).toEqual([outbound]);
92
165
 
93
- // Start two connections concurrently
94
- const promise1 = transport.connect();
95
- const promise2 = transport.connect();
96
-
97
- await Promise.all([promise1, promise2]);
98
-
99
- // Should only create one delegate
100
- expect(WebSocketTransport).toHaveBeenCalledTimes(1);
101
- expect(waitForConnection).toHaveBeenCalledTimes(1);
102
- });
103
-
104
- it("should send data successfully when connected", async () => {
105
- const getWsUrl = vi.fn(() => mockWsUrl);
106
- const transport = new ReconnectingWebSocketTransport({ getWsUrl });
107
-
108
- await transport.connect();
109
-
110
- const data: any = { method: "test", params: [] };
111
- const result = await transport.sendData(data, 5000);
166
+ const notification: JSONRPCMessage = {
167
+ jsonrpc: "2.0",
168
+ method: "textDocument/publishDiagnostics",
169
+ params: { uri: "file:///test.py", diagnostics: [] },
170
+ };
171
+ socket.receive(notification);
172
+ expect(inbound).toHaveBeenCalledWith(notification);
112
173
 
113
- expect(result).toEqual({ result: "success" });
174
+ unsubscribe();
175
+ socket.receive(notification);
176
+ expect(inbound).toHaveBeenCalledTimes(1);
114
177
  });
115
178
 
116
- it("should reconnect when WebSocket is in CLOSED state", async () => {
117
- const getWsUrl = vi.fn(() => mockWsUrl);
118
- const transport = new ReconnectingWebSocketTransport({ getWsUrl });
179
+ it("restores LSP state before replaying queued requests", async () => {
180
+ const onReconnect = vi.fn(async () => {
181
+ transport.send({
182
+ jsonrpc: "2.0",
183
+ method: "initialized",
184
+ params: {},
185
+ });
186
+ transport.send({
187
+ jsonrpc: "2.0",
188
+ method: "textDocument/didOpen",
189
+ params: { textDocument: { uri: "file:///test.py" } },
190
+ });
191
+ });
192
+ const transport = new ReconnectingWebSocketTransport({
193
+ getWsUrl: () => mockWsUrl,
194
+ onReconnect,
195
+ });
119
196
 
120
- // First connection
121
- await transport.connect();
122
- expect(WebSocketTransport).toHaveBeenCalledTimes(1);
197
+ const initialConnection = transport.connect();
198
+ const firstSocket = await getSocket(0);
199
+ firstSocket.open();
200
+ await initialConnection;
201
+ firstSocket.disconnect();
123
202
 
124
- // Simulate WebSocket closing
125
- mockConnection.readyState = WebSocket.CLOSED;
203
+ transport.send({
204
+ jsonrpc: "2.0",
205
+ method: "textDocument/didChange",
206
+ params: { textDocument: { uri: "file:///test.py", version: 2 } },
207
+ });
208
+ const completionRequest: JSONRPCMessage = {
209
+ jsonrpc: "2.0",
210
+ id: 1,
211
+ method: "textDocument/completion",
212
+ params: { textDocument: { uri: "file:///test.py" } },
213
+ };
214
+ transport.send(completionRequest);
126
215
 
127
- // Send data should trigger reconnection
128
- const data: any = { method: "test", params: [] };
129
- await transport.sendData(data, 5000);
216
+ const secondSocket = await getSocket(1);
217
+ secondSocket.open();
218
+ await vi.waitFor(() => {
219
+ expect(onReconnect).toHaveBeenCalledTimes(1);
220
+ expect(secondSocket.messages()).toHaveLength(3);
221
+ });
130
222
 
131
- // Should have created a new WebSocketTransport
132
- expect(WebSocketTransport).toHaveBeenCalledTimes(2);
223
+ expect(secondSocket.messages()).toEqual([
224
+ {
225
+ jsonrpc: "2.0",
226
+ method: "initialized",
227
+ params: {},
228
+ },
229
+ {
230
+ jsonrpc: "2.0",
231
+ method: "textDocument/didOpen",
232
+ params: { textDocument: { uri: "file:///test.py" } },
233
+ },
234
+ completionRequest,
235
+ ]);
133
236
  });
134
237
 
135
- it("should reconnect when WebSocket is in CLOSING state", async () => {
136
- const getWsUrl = vi.fn(() => mockWsUrl);
137
- const transport = new ReconnectingWebSocketTransport({ getWsUrl });
138
-
139
- // First connection
140
- await transport.connect();
141
- expect(WebSocketTransport).toHaveBeenCalledTimes(1);
142
-
143
- // Simulate WebSocket closing
144
- mockConnection.readyState = WebSocket.CLOSING;
145
-
146
- // Send data should trigger reconnection
147
- const data: any = { method: "test", params: [] };
148
- await transport.sendData(data, 5000);
149
-
150
- // Should have created a new WebSocketTransport
151
- expect(WebSocketTransport).toHaveBeenCalledTimes(2);
152
- });
238
+ it("holds live requests until asynchronous state restoration finishes", async () => {
239
+ let finishRestoration: (() => void) | undefined;
240
+ const restorationGate = new Promise<void>((resolve) => {
241
+ finishRestoration = resolve;
242
+ });
243
+ const onReconnect = vi.fn(async () => {
244
+ transport.send({
245
+ jsonrpc: "2.0",
246
+ id: 10,
247
+ method: "initialize",
248
+ params: {},
249
+ });
250
+ await restorationGate;
251
+ transport.send({
252
+ jsonrpc: "2.0",
253
+ method: "initialized",
254
+ params: {},
255
+ });
256
+ });
257
+ const transport = new ReconnectingWebSocketTransport({
258
+ getWsUrl: () => mockWsUrl,
259
+ onReconnect,
260
+ });
153
261
 
154
- it("should close the transport and prevent reconnection", async () => {
155
- const getWsUrl = vi.fn(() => mockWsUrl);
156
- const transport = new ReconnectingWebSocketTransport({ getWsUrl });
262
+ const initialConnection = transport.connect();
263
+ const firstSocket = await getSocket(0);
264
+ firstSocket.open();
265
+ await initialConnection;
266
+ firstSocket.disconnect();
267
+
268
+ const secondSocket = await getSocket(1);
269
+ secondSocket.open();
270
+ await vi.waitFor(() => {
271
+ expect(secondSocket.messages()).toEqual([
272
+ {
273
+ jsonrpc: "2.0",
274
+ id: 10,
275
+ method: "initialize",
276
+ params: {},
277
+ },
278
+ ]);
279
+ });
157
280
 
158
- await transport.connect();
159
- transport.close();
281
+ const hoverRequest: JSONRPCMessage = {
282
+ jsonrpc: "2.0",
283
+ id: 11,
284
+ method: "textDocument/hover",
285
+ params: { textDocument: { uri: "file:///test.py" } },
286
+ };
287
+ transport.send(hoverRequest);
288
+ expect(secondSocket.messages()).toHaveLength(1);
160
289
 
161
- // Attempting to connect again should throw
162
- await expect(transport.connect()).rejects.toThrow("Transport is closed");
290
+ finishRestoration?.();
291
+ await vi.waitFor(() => {
292
+ expect(secondSocket.messages()).toHaveLength(3);
293
+ });
294
+ expect(secondSocket.messages()).toEqual([
295
+ {
296
+ jsonrpc: "2.0",
297
+ id: 10,
298
+ method: "initialize",
299
+ params: {},
300
+ },
301
+ {
302
+ jsonrpc: "2.0",
303
+ method: "initialized",
304
+ params: {},
305
+ },
306
+ hoverRequest,
307
+ ]);
163
308
  });
164
309
 
165
- it("should close old delegate when creating a new one", async () => {
166
- const getWsUrl = vi.fn(() => mockWsUrl);
167
- const transport = new ReconnectingWebSocketTransport({ getWsUrl });
168
-
169
- // First connection
170
- await transport.connect();
171
- const firstDelegate = (transport as any).delegate;
172
- expect(firstDelegate).toBeDefined();
173
-
174
- // Simulate connection closed
175
- mockConnection.readyState = WebSocket.CLOSED;
176
-
177
- // Reconnect by sending data
178
- const data: any = { method: "test", params: [] };
179
- await transport.sendData(data, 5000);
310
+ it("replays document changes made while state restoration is in flight", async () => {
311
+ let finishRestoration: (() => void) | undefined;
312
+ const restorationGate = new Promise<void>((resolve) => {
313
+ finishRestoration = resolve;
314
+ });
315
+ const onReconnect = vi.fn(async () => {
316
+ transport.send({
317
+ jsonrpc: "2.0",
318
+ method: "textDocument/didOpen",
319
+ params: { textDocument: { uri: "file:///test.py", version: 3 } },
320
+ });
321
+ await restorationGate;
322
+ });
323
+ const transport = new ReconnectingWebSocketTransport({
324
+ getWsUrl: () => mockWsUrl,
325
+ onReconnect,
326
+ });
180
327
 
181
- // Old delegate should have been closed
182
- expect(firstDelegate.close).toHaveBeenCalled();
183
- });
328
+ const initialConnection = transport.connect();
329
+ const firstSocket = await getSocket(0);
330
+ firstSocket.open();
331
+ await initialConnection;
332
+ firstSocket.disconnect();
184
333
 
185
- it("should handle connection failures gracefully", async () => {
186
- const getWsUrl = vi.fn(() => mockWsUrl);
187
- const connectionError = new Error("Connection failed");
334
+ const staleChange: JSONRPCMessage = {
335
+ jsonrpc: "2.0",
336
+ method: "textDocument/didChange",
337
+ params: { textDocument: { uri: "file:///test.py", version: 2 } },
338
+ };
339
+ transport.send(staleChange);
188
340
 
189
- // Mock connect to fail
190
- (WebSocketTransport as any).mockImplementationOnce(function (this: any) {
191
- this.connection = mockConnection;
192
- this.connect = vi.fn().mockRejectedValue(connectionError);
193
- this.close = vi.fn();
194
- this.sendData = vi.fn();
341
+ const secondSocket = await getSocket(1);
342
+ secondSocket.open();
343
+ await vi.waitFor(() => {
344
+ expect(onReconnect).toHaveBeenCalledTimes(1);
195
345
  });
196
346
 
197
- const transport = new ReconnectingWebSocketTransport({ getWsUrl });
198
-
199
- await expect(transport.connect()).rejects.toThrow("Connection failed");
347
+ // The user keeps typing while the resync is still awaiting.
348
+ const liveChange: JSONRPCMessage = {
349
+ jsonrpc: "2.0",
350
+ method: "textDocument/didChange",
351
+ params: { textDocument: { uri: "file:///test.py", version: 4 } },
352
+ };
353
+ transport.send(liveChange);
200
354
 
201
- // Delegate should be cleared after failure
202
- expect((transport as any).delegate).toBeUndefined();
355
+ finishRestoration?.();
356
+ await vi.waitFor(() => {
357
+ expect(secondSocket.messages()).toHaveLength(2);
358
+ });
359
+ expect(secondSocket.messages()).toEqual([
360
+ {
361
+ jsonrpc: "2.0",
362
+ method: "textDocument/didOpen",
363
+ params: { textDocument: { uri: "file:///test.py", version: 3 } },
364
+ },
365
+ liveChange,
366
+ ]);
367
+ expect(secondSocket.messages()).not.toContainEqual(staleChange);
203
368
  });
204
369
 
205
- it("should handle waitForConnection failures", async () => {
206
- const getWsUrl = vi.fn(() => mockWsUrl);
207
- const waitError = new Error("Wait failed");
208
- const waitForConnection = vi.fn().mockRejectedValue(waitError);
209
-
370
+ it("retries failed state restoration without losing queued requests", async () => {
371
+ const onReconnect = vi
372
+ .fn<() => Promise<void>>()
373
+ .mockRejectedValueOnce(new Error("State restoration failed"))
374
+ .mockResolvedValue(undefined);
210
375
  const transport = new ReconnectingWebSocketTransport({
211
- getWsUrl,
212
- waitForConnection,
376
+ getWsUrl: () => mockWsUrl,
377
+ onReconnect,
378
+ retries: 2,
379
+ retryDelayMs: 0,
213
380
  });
214
381
 
215
- await expect(transport.connect()).rejects.toThrow("Wait failed");
216
-
217
- // Should not have created a delegate
218
- expect(WebSocketTransport).not.toHaveBeenCalled();
219
- });
220
-
221
- it("should automatically reconnect on sendData after connection loss", async () => {
222
- const getWsUrl = vi.fn(() => mockWsUrl);
223
- const transport = new ReconnectingWebSocketTransport({ getWsUrl });
224
-
225
- // Don't connect initially
226
- // Simulate WebSocket in closed state (no delegate exists)
227
- expect((transport as any).delegate).toBeUndefined();
382
+ const initialConnection = transport.connect();
383
+ const firstSocket = await getSocket(0);
384
+ firstSocket.open();
385
+ await initialConnection;
386
+ firstSocket.disconnect();
387
+
388
+ const queuedRequest: JSONRPCMessage = {
389
+ jsonrpc: "2.0",
390
+ id: 12,
391
+ method: "textDocument/hover",
392
+ params: { textDocument: { uri: "file:///test.py" } },
393
+ };
394
+ transport.send(queuedRequest);
228
395
 
229
- // Send data should trigger automatic connection
230
- const data: any = { method: "test", params: [] };
231
- await transport.sendData(data, 5000);
396
+ const failedRestorationSocket = await getSocket(1);
397
+ failedRestorationSocket.open();
398
+ const recoveredSocket = await getSocket(2);
399
+ recoveredSocket.open();
232
400
 
233
- expect(WebSocketTransport).toHaveBeenCalledTimes(1);
401
+ await vi.waitFor(() => {
402
+ expect(onReconnect).toHaveBeenCalledTimes(2);
403
+ expect(recoveredSocket.messages()).toEqual([queuedRequest]);
404
+ });
405
+ expect(failedRestorationSocket.messages()).toEqual([]);
234
406
  });
235
407
 
236
- it("should call onReconnect callback after reconnection", async () => {
237
- const getWsUrl = vi.fn(() => mockWsUrl);
238
- const onReconnect = vi.fn().mockResolvedValue(undefined);
408
+ it("abandons a restoration whose socket died instead of waiting for it", async () => {
409
+ // A restoration awaiting a response on a dead socket only settles when the
410
+ // LSP request times out, so recovery must not be chained to it.
411
+ const strandedRestoration = new Promise<void>(() => {
412
+ // never settles
413
+ });
414
+ const onReconnect = vi
415
+ .fn<() => Promise<void>>()
416
+ .mockImplementationOnce(() => strandedRestoration)
417
+ .mockResolvedValue(undefined);
239
418
  const transport = new ReconnectingWebSocketTransport({
240
- getWsUrl,
419
+ getWsUrl: () => mockWsUrl,
241
420
  onReconnect,
242
421
  });
243
422
 
244
- // First connection - callback should not be called
245
- await transport.connect();
246
- expect(onReconnect).not.toHaveBeenCalled();
423
+ const initialConnection = transport.connect();
424
+ const firstSocket = await getSocket(0);
425
+ firstSocket.open();
426
+ await initialConnection;
427
+ firstSocket.disconnect();
247
428
 
248
- // Simulate connection loss
249
- mockConnection.readyState = WebSocket.CLOSED;
429
+ const secondSocket = await getSocket(1);
430
+ secondSocket.open();
431
+ await vi.waitFor(() => {
432
+ expect(onReconnect).toHaveBeenCalledTimes(1);
433
+ });
250
434
 
251
- // Reconnect - callback should be called this time
252
- const data: any = { method: "test", params: [] };
253
- await transport.sendData(data, 5000);
435
+ secondSocket.disconnect();
254
436
 
255
- expect(onReconnect).toHaveBeenCalledTimes(1);
437
+ const thirdSocket = await getSocket(2);
438
+ thirdSocket.open();
439
+ await vi.waitFor(() => {
440
+ expect(onReconnect).toHaveBeenCalledTimes(2);
441
+ });
442
+ expect(thirdSocket.readyState).toBe(FakeWebSocket.OPEN);
256
443
  });
257
444
 
258
- it("should not call onReconnect callback on first connection", async () => {
259
- const getWsUrl = vi.fn(() => mockWsUrl);
260
- const onReconnect = vi.fn().mockResolvedValue(undefined);
445
+ it("keeps the queued backlog when a restoration is abandoned", async () => {
446
+ const strandedRestoration = new Promise<void>(() => {
447
+ // never settles
448
+ });
449
+ const onReconnect = vi
450
+ .fn<() => Promise<void>>()
451
+ .mockImplementationOnce(() => strandedRestoration)
452
+ .mockResolvedValue(undefined);
261
453
  const transport = new ReconnectingWebSocketTransport({
262
- getWsUrl,
454
+ getWsUrl: () => mockWsUrl,
263
455
  onReconnect,
264
456
  });
265
457
 
266
- await transport.connect();
458
+ const initialConnection = transport.connect();
459
+ const firstSocket = await getSocket(0);
460
+ firstSocket.open();
461
+ await initialConnection;
462
+ firstSocket.disconnect();
463
+
464
+ const queuedRequest: JSONRPCMessage = {
465
+ jsonrpc: "2.0",
466
+ id: 21,
467
+ method: "textDocument/hover",
468
+ params: { textDocument: { uri: "file:///test.py" } },
469
+ };
470
+ transport.send(queuedRequest);
267
471
 
268
- expect(onReconnect).not.toHaveBeenCalled();
472
+ const secondSocket = await getSocket(1);
473
+ secondSocket.open();
474
+ await vi.waitFor(() => {
475
+ expect(onReconnect).toHaveBeenCalledTimes(1);
476
+ });
477
+ // The doomed attempt detached the backlog; abandoning it must hand the
478
+ // messages back rather than strand them.
479
+ secondSocket.disconnect();
480
+
481
+ const thirdSocket = await getSocket(2);
482
+ thirdSocket.open();
483
+ await vi.waitFor(() => {
484
+ expect(thirdSocket.messages()).toEqual([queuedRequest]);
485
+ });
269
486
  });
270
487
 
271
- it("should handle onReconnect callback errors gracefully", async () => {
272
- const getWsUrl = vi.fn(() => mockWsUrl);
273
- const reconnectError = new Error("Reconnect callback failed");
274
- const onReconnect = vi.fn().mockRejectedValue(reconnectError);
488
+ it("clears the in-flight backlog when closed during restoration", async () => {
489
+ const strandedRestoration = new Promise<void>(() => {
490
+ // never settles
491
+ });
492
+ const onReconnect = vi.fn<() => Promise<void>>(() => strandedRestoration);
275
493
  const transport = new ReconnectingWebSocketTransport({
276
- getWsUrl,
494
+ getWsUrl: () => mockWsUrl,
277
495
  onReconnect,
278
496
  });
279
497
 
280
- // First connection
281
- await transport.connect();
282
-
283
- // Simulate connection loss
284
- mockConnection.readyState = WebSocket.CLOSED;
285
-
286
- // Reconnect - should propagate the error from onReconnect
287
- const data: any = { method: "test", params: [] };
288
- await expect(transport.sendData(data, 5000)).rejects.toThrow(
289
- "Reconnect callback failed",
290
- );
291
- });
292
-
293
- describe("subscribe", () => {
294
- it("should track subscriptions", () => {
295
- const getWsUrl = vi.fn(() => mockWsUrl);
296
- const transport = new ReconnectingWebSocketTransport({ getWsUrl });
297
-
298
- const handler = vi.fn();
299
- transport.subscribe("notification", handler);
498
+ const initialConnection = transport.connect();
499
+ const firstSocket = await getSocket(0);
500
+ firstSocket.open();
501
+ await initialConnection;
502
+ firstSocket.disconnect();
300
503
 
301
- expect((transport as any).pendingSubscriptions).toHaveLength(1);
302
- expect((transport as any).pendingSubscriptions[0]).toEqual({
303
- event: "notification",
304
- handler,
305
- });
504
+ transport.send({
505
+ jsonrpc: "2.0",
506
+ method: "textDocument/didChange",
507
+ params: {},
306
508
  });
307
509
 
308
- it("should register handler on delegate if it exists", async () => {
309
- const getWsUrl = vi.fn(() => mockWsUrl);
310
- const transport = new ReconnectingWebSocketTransport({ getWsUrl });
311
-
312
- await transport.connect();
313
-
314
- const handler = vi.fn();
315
- transport.subscribe("notification", handler);
316
-
317
- const delegate = (transport as any).delegate;
318
- expect(delegate.subscribe).toHaveBeenCalledWith("notification", handler);
510
+ const secondSocket = await getSocket(1);
511
+ secondSocket.open();
512
+ await vi.waitFor(() => {
513
+ expect(onReconnect).toHaveBeenCalledTimes(1);
319
514
  });
515
+ // Restoration is now stranded and holding the backlog it detached.
516
+ expect(
517
+ (transport as unknown as { inFlightBacklog?: unknown[] }).inFlightBacklog,
518
+ ).toHaveLength(1);
320
519
 
321
- it("should register pending subscriptions when delegate is created", async () => {
322
- const getWsUrl = vi.fn(() => mockWsUrl);
323
- const transport = new ReconnectingWebSocketTransport({ getWsUrl });
324
-
325
- const handler1 = vi.fn();
326
- const handler2 = vi.fn();
327
- transport.subscribe("notification", handler1);
328
- transport.subscribe("response", handler2);
520
+ transport.close();
329
521
 
330
- await transport.connect();
522
+ expect(
523
+ (transport as unknown as { inFlightBacklog?: unknown[] }).inFlightBacklog,
524
+ ).toBeUndefined();
525
+ });
331
526
 
332
- const delegate = (transport as any).delegate;
333
- expect(delegate.subscribe).toHaveBeenCalledWith("notification", handler1);
334
- expect(delegate.subscribe).toHaveBeenCalledWith("response", handler2);
527
+ it("keeps inbound subscriptions active after reconnection", async () => {
528
+ const transport = new ReconnectingWebSocketTransport({
529
+ getWsUrl: () => mockWsUrl,
335
530
  });
531
+ const inbound = vi.fn();
532
+ transport.onMessage(inbound);
533
+ const initialConnection = transport.connect();
534
+ const firstSocket = await getSocket(0);
535
+ firstSocket.open();
536
+ await initialConnection;
537
+
538
+ firstSocket.disconnect();
539
+ const secondSocket = await getSocket(1);
540
+ secondSocket.open();
541
+ const notification: JSONRPCMessage = {
542
+ jsonrpc: "2.0",
543
+ method: "window/logMessage",
544
+ params: { type: 3, message: "reconnected" },
545
+ };
546
+ secondSocket.receive(notification);
336
547
 
337
- it("should re-register subscriptions on reconnection", async () => {
338
- const getWsUrl = vi.fn(() => mockWsUrl);
339
- const transport = new ReconnectingWebSocketTransport({ getWsUrl });
340
-
341
- // Add subscription before connection
342
- const handler = vi.fn();
343
- transport.subscribe("notification", handler);
344
-
345
- // First connection
346
- await transport.connect();
347
- const firstDelegate = (transport as any).delegate;
348
- expect(firstDelegate.subscribe).toHaveBeenCalledWith(
349
- "notification",
350
- handler,
351
- );
352
-
353
- // Clear mock calls
354
- firstDelegate.subscribe.mockClear();
355
-
356
- // Simulate connection loss
357
- mockConnection.readyState = WebSocket.CLOSED;
358
-
359
- // Reconnect by sending data
360
- const data: any = { method: "test", params: [] };
361
- await transport.sendData(data, 5000);
362
-
363
- // New delegate should have been created
364
- const secondDelegate = (transport as any).delegate;
365
- expect(secondDelegate).not.toBe(firstDelegate);
366
-
367
- // Subscription should be re-registered on new delegate
368
- expect(secondDelegate.subscribe).toHaveBeenCalledWith(
369
- "notification",
370
- handler,
371
- );
372
- });
548
+ expect(inbound).toHaveBeenCalledWith(notification);
373
549
  });
374
550
 
375
- describe("unsubscribe", () => {
376
- it("should remove subscription from tracking", () => {
377
- const getWsUrl = vi.fn(() => mockWsUrl);
378
- const transport = new ReconnectingWebSocketTransport({ getWsUrl });
379
-
380
- const handler = vi.fn();
381
- transport.subscribe("notification", handler);
382
- expect((transport as any).pendingSubscriptions).toHaveLength(1);
383
-
384
- transport.unsubscribe("notification", handler);
385
- expect((transport as any).pendingSubscriptions).toHaveLength(0);
551
+ it("retries failed connection attempts", async () => {
552
+ const onConnectionFailure = vi.fn();
553
+ const transport = new ReconnectingWebSocketTransport({
554
+ getWsUrl: () => mockWsUrl,
555
+ retries: 2,
556
+ retryDelayMs: 0,
557
+ onConnectionFailure,
386
558
  });
387
559
 
388
- it("should unregister from delegate if it exists", async () => {
389
- const getWsUrl = vi.fn(() => mockWsUrl);
390
- const transport = new ReconnectingWebSocketTransport({ getWsUrl });
391
-
392
- await transport.connect();
393
-
394
- const handler = vi.fn();
395
- transport.subscribe("notification", handler);
560
+ const connection = transport.connect();
561
+ const firstSocket = await getSocket(0);
562
+ firstSocket.fail();
563
+ const secondSocket = await getSocket(1);
564
+ secondSocket.open();
565
+ await connection;
396
566
 
397
- const delegate = (transport as any).delegate;
398
- delegate.unsubscribe.mockClear();
399
-
400
- transport.unsubscribe("notification", handler);
567
+ expect(secondSocket.readyState).toBe(FakeWebSocket.OPEN);
568
+ expect(onConnectionFailure).not.toHaveBeenCalled();
569
+ });
401
570
 
402
- expect(delegate.unsubscribe).toHaveBeenCalledWith(
403
- "notification",
404
- handler,
405
- );
571
+ it("reports the final connection failure", async () => {
572
+ const onConnectionFailure = vi.fn();
573
+ const transport = new ReconnectingWebSocketTransport({
574
+ getWsUrl: () => mockWsUrl,
575
+ retries: 1,
576
+ onConnectionFailure,
406
577
  });
407
578
 
408
- it("should not re-register unsubscribed handlers on reconnection", async () => {
409
- const getWsUrl = vi.fn(() => mockWsUrl);
410
- const transport = new ReconnectingWebSocketTransport({ getWsUrl });
411
-
412
- const handler1 = vi.fn();
413
- const handler2 = vi.fn();
414
- transport.subscribe("notification", handler1);
415
- transport.subscribe("response", handler2);
416
-
417
- await transport.connect();
418
-
419
- // Unsubscribe handler1
420
- transport.unsubscribe("notification", handler1);
579
+ const connection = transport.connect();
580
+ const socket = await getSocket(0);
581
+ socket.fail();
421
582
 
422
- // Simulate connection loss
423
- mockConnection.readyState = WebSocket.CLOSED;
424
-
425
- // Reconnect by sending data
426
- const data: any = { method: "test", params: [] };
427
- await transport.sendData(data, 5000);
583
+ await expect(connection).rejects.toThrow(
584
+ "WebSocket connection to ws://localhost:8080/lsp failed",
585
+ );
586
+ expect(onConnectionFailure).toHaveBeenCalledWith(
587
+ expect.objectContaining({ message: expect.stringContaining("failed") }),
588
+ );
589
+ });
428
590
 
429
- const newDelegate = (transport as any).delegate;
591
+ it("closes permanently and ignores later sends", async () => {
592
+ const transport = new ReconnectingWebSocketTransport({
593
+ getWsUrl: () => mockWsUrl,
594
+ });
595
+ const connection = transport.connect();
596
+ const socket = await getSocket(0);
597
+ socket.open();
598
+ await connection;
430
599
 
431
- // Only handler2 should be registered on the new delegate
432
- expect(newDelegate.subscribe).not.toHaveBeenCalledWith(
433
- "notification",
434
- handler1,
435
- );
436
- expect(newDelegate.subscribe).toHaveBeenCalledWith("response", handler2);
600
+ transport.close();
601
+ transport.send({
602
+ jsonrpc: "2.0",
603
+ method: "initialized",
604
+ params: {},
437
605
  });
606
+
607
+ expect(socket.messages()).toEqual([]);
608
+ await expect(transport.connect()).rejects.toThrow("Transport is closed");
609
+ expect(FakeWebSocket.instances).toHaveLength(1);
438
610
  });
439
611
  });