@hienlh/ppm 0.20.10 → 0.21.0

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 (982) hide show
  1. package/CHANGELOG.md +108 -0
  2. package/CLAUDE.md +42 -1
  3. package/LICENSE +5 -0
  4. package/THIRD-PARTY-NOTICES.md +83 -0
  5. package/assets/skills/ppm/SKILL.md +1 -1
  6. package/assets/skills/ppm/references/cli-reference.md +4 -4
  7. package/assets/skills/ppm/references/http-api.md +1 -1
  8. package/bun.lock +38 -7
  9. package/dist/web/assets/KaTeX_Size3-Regular-gV2CO0n9.woff2 +0 -0
  10. package/dist/web/assets/accounts-settings-section-BuxD9zH3.js +1 -0
  11. package/dist/web/assets/ai-resource-editor-F09pf8Hd.js +1 -0
  12. package/dist/web/assets/ai-settings-section-Dd9tOUp0.js +1 -0
  13. package/dist/web/assets/ai-settings-section-FrU2X8Fu.js +1 -0
  14. package/dist/web/assets/{angular-html-D4qjt-75.js → angular-html-DkR4iCth.js} +1 -1
  15. package/dist/web/assets/{angular-ts-DvLn04T8.js → angular-ts-DcyL4Chx.js} +1 -1
  16. package/dist/web/assets/api-client-BUCo1lms.js +1 -0
  17. package/dist/web/assets/{api-client-DCzgxFNY.js → api-client-bfB7cXRM.js} +1 -1
  18. package/dist/web/assets/{api-settings-t5xLrBkQ.js → api-settings-BcNjZIvG.js} +1 -1
  19. package/dist/web/assets/{api-themes-CJmyQeMk.js → api-themes-DBfyVUtX.js} +1 -1
  20. package/dist/web/assets/{apl-DQOoPzqd.js → apl-BVlrVtjt.js} +1 -1
  21. package/dist/web/assets/appearance-settings-section-whgnq3ss.js +1 -0
  22. package/dist/web/assets/architecture-PBZL5I3N-5K0wEkAn.js +1 -0
  23. package/dist/web/assets/{astro-C2zFJ1Er.js → astro-MjJlozLj.js} +1 -1
  24. package/dist/web/assets/audio-preview-Bc54GCAV.js +1 -0
  25. package/dist/web/assets/{blade-CBD8sEa1.js → blade-DnJWi1fz.js} +1 -1
  26. package/dist/web/assets/{bsl-bs2JpeTQ.js → bsl-DCmJxSIz.js} +1 -1
  27. package/dist/web/assets/{button-DHI8IY_N.js → button-VW4QGKCn.js} +1 -1
  28. package/dist/web/assets/{cairo-DT2g4i_6.js → cairo-C8dDenub.js} +1 -1
  29. package/dist/web/assets/chat-tab-Cr6_KSGO.js +15 -0
  30. package/dist/web/assets/{cobol-B2rp6LA1.js → cobol-DPx_nifl.js} +1 -1
  31. package/dist/web/assets/code-editor-DfmlGamv.js +7 -0
  32. package/dist/web/assets/codex-daily-guard-CfybHv_c.js +1 -0
  33. package/dist/web/assets/{coffee-D5ShQC08.js → coffee-DvFzqhgN.js} +1 -1
  34. package/dist/web/assets/conflict-editor-DenQUOT2.js +19 -0
  35. package/dist/web/assets/context-menu-DOODKZdF.js +1 -0
  36. package/dist/web/assets/{cpp-BmKOH-E0.js → cpp-BLJN0umi.js} +1 -1
  37. package/dist/web/assets/{createLucideIcon-CLMdC3Kl.js → createLucideIcon-DoiEKeJ_.js} +1 -1
  38. package/dist/web/assets/{crystal-B7u_ZTpu.js → crystal-BXR-9fGw.js} +1 -1
  39. package/dist/web/assets/csv-preview-CClrJOuR.js +2 -0
  40. package/dist/web/assets/{data-grid-overlay-editor-DJWgclot.js → data-grid-overlay-editor-D4fhcMfT.js} +1 -1
  41. package/dist/web/assets/{data-grid-types-Uu77aFvI.js → data-grid-types-OgUxMLdQ.js} +1 -1
  42. package/dist/web/assets/database-viewer-DItjm8wB.js +1 -0
  43. package/dist/web/assets/dialog-DQTn55Mt.js +1 -0
  44. package/dist/web/assets/diff-viewer-BpNj7pN9.js +4 -0
  45. package/dist/web/assets/{dist-BTdRgQig.js → dist-CrBOCtCW.js} +1 -1
  46. package/dist/web/assets/docx-preview-DYBkiUaE.js +12 -0
  47. package/dist/web/assets/{edge--MpXROh5.js → edge-rWOlCmXT.js} +1 -1
  48. package/dist/web/assets/{edit-diff-preview-ESj6hMoD.js → edit-diff-preview-COtmo54G.js} +3 -3
  49. package/dist/web/assets/editor-font-BDrdiGf1.js +1 -0
  50. package/dist/web/assets/editor-language-service-DxkZ51E5.js +1 -0
  51. package/dist/web/assets/{elixir-DL8mOfzH.js → elixir-E7Y82okW.js} +1 -1
  52. package/dist/web/assets/{elm-eVlzIFEZ.js → elm-DTPGbc-w.js} +1 -1
  53. package/dist/web/assets/{erb-BgvaH9l0.js → erb-DHqLHrE6.js} +1 -1
  54. package/dist/web/assets/{erlang-CEf8Sfhs.js → erlang-Byg0nNiV.js} +1 -1
  55. package/dist/web/assets/{esm-C5xqy163.js → esm-D_DmOM7n.js} +2 -2
  56. package/dist/web/assets/explorer-body-D-5z464e.js +2 -0
  57. package/dist/web/assets/explorer-window-content-7-1wuRul.js +1 -0
  58. package/dist/web/assets/extension-manager-section-BhwB6nqr.js +1 -0
  59. package/dist/web/assets/extension-webview-DI4VL2tJ.js +12 -0
  60. package/dist/web/assets/file-icons-EzPL0q-k.js +1 -0
  61. package/dist/web/assets/file-icons.generated-CfaJuvZu.css +1 -0
  62. package/dist/web/assets/file-store-DMABxOkV.js +1 -0
  63. package/dist/web/assets/files-settings-section-CZzABuKz.js +1 -0
  64. package/dist/web/assets/format-file-meta-DOpzJJhS.js +1 -0
  65. package/dist/web/assets/{fortran-fixed-form-yAUsSjab.js → fortran-fixed-form-CY1n0Xf6.js} +1 -1
  66. package/dist/web/assets/{fsharp-BEWvY_ZR.js → fsharp-_vEDSCJz.js} +1 -1
  67. package/dist/web/assets/{gdresource-CYZFZ057.js → gdresource-B6XT0wAC.js} +1 -1
  68. package/dist/web/assets/geist-cyrillic-ext-wght-italic-BYAq_K0C.woff2 +0 -0
  69. package/dist/web/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
  70. package/dist/web/assets/geist-cyrillic-wght-italic-Da0gXVk3.woff2 +0 -0
  71. package/dist/web/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
  72. package/dist/web/assets/geist-latin-ext-wght-italic-XgKbg5n7.woff2 +0 -0
  73. package/dist/web/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
  74. package/dist/web/assets/geist-latin-wght-italic-dTnRTFFJ.woff2 +0 -0
  75. package/dist/web/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
  76. package/dist/web/assets/geist-vietnamese-wght-italic-0fly6zkB.woff2 +0 -0
  77. package/dist/web/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
  78. package/dist/web/assets/general-settings-section-BcxwiZ0X.js +1 -0
  79. package/dist/web/assets/{git-commit-DedchUJ6.js → git-commit-Wk9ovq59.js} +1 -1
  80. package/dist/web/assets/git-log-panel-CRN4JVOx.js +1 -0
  81. package/dist/web/assets/{git-rebase-DPvHNzQr.js → git-rebase-DSarGPvK.js} +1 -1
  82. package/dist/web/assets/git-repo-store-Dy69YCHN.js +1 -0
  83. package/dist/web/assets/gitGraph-HDMCJU4V-DkVT2MAM.js +1 -0
  84. package/dist/web/assets/glide-data-grid-BvgAqSUr.js +141 -0
  85. package/dist/web/assets/{glimmer-js-B4hPYBMX.js → glimmer-js-CkYI35_P.js} +1 -1
  86. package/dist/web/assets/{glimmer-ts-C0WfcQnO.js → glimmer-ts-BqmIZcds.js} +1 -1
  87. package/dist/web/assets/{glsl-DHW88hTv.js → glsl-Be-yBCF5.js} +1 -1
  88. package/dist/web/assets/{graphql-CEvXbo6e.js → graphql-a5DrENHY.js} +1 -1
  89. package/dist/web/assets/group-chat-tab-DFa5mAx5.js +1 -0
  90. package/dist/web/assets/{hack-lKfhn1vw.js → hack-BLAg20aD.js} +1 -1
  91. package/dist/web/assets/{haml-AjKlANaB.js → haml-Dj6bGOQH.js} +1 -1
  92. package/dist/web/assets/{handlebars-B8fZzj2G.js → handlebars-dmEa36Oh.js} +1 -1
  93. package/dist/web/assets/{html-derivative-VZmoMdQD.js → html-derivative-lLi3-RNT.js} +1 -1
  94. package/dist/web/assets/{html-H_S3FJMj.js → html-yacZYzSE.js} +1 -1
  95. package/dist/web/assets/{http-DBxROFKc.js → http-1KaxcE4e.js} +1 -1
  96. package/dist/web/assets/{hurl-Hf7XWQHN.js → hurl-ST-dEEZR.js} +1 -1
  97. package/dist/web/assets/{hxml-BRhRKwSo.js → hxml-CpDtuq__.js} +1 -1
  98. package/dist/web/assets/icons-DQjqk0lJ.js +1 -0
  99. package/dist/web/assets/image-preview-CJVxL0uH.js +1 -0
  100. package/dist/web/assets/index-D7DbXD3G.css +1 -0
  101. package/dist/web/assets/index-ZtfxZOyb.js +52 -0
  102. package/dist/web/assets/info-3K5VOQVL-BBsmKGzA.js +1 -0
  103. package/dist/web/assets/input-D-dR8RI6.js +1 -0
  104. package/dist/web/assets/{jinja-D3jMH0jG.js → jinja-Cjw-evAn.js} +1 -1
  105. package/dist/web/assets/{jira-watcher-section-DZvWeUAW.js → jira-watcher-section-DIC1yIV3.js} +1 -1
  106. package/dist/web/assets/{jison-CZtpkLiY.js → jison-DfATMYoY.js} +1 -1
  107. package/dist/web/assets/{julia-DwFjOpos.js → julia-DDCaxiqT.js} +1 -1
  108. package/dist/web/assets/{just-BEfj8dHN.js → just-CJL529u6.js} +1 -1
  109. package/dist/web/assets/keybindings-store-tVfhPANS.js +1 -0
  110. package/dist/web/assets/keyboard-shortcuts-section-BW03P3AF.js +1 -0
  111. package/dist/web/assets/{latex-C6Rb_zGG.js → latex-Zc4EpLpW.js} +1 -1
  112. package/dist/web/assets/{lib-CFTK00ux.js → lib-BVwmtv2i.js} +1 -1
  113. package/dist/web/assets/{liquid-DTVs9cD3.js → liquid-B_6KMNYS.js} +1 -1
  114. package/dist/web/assets/{lua-C1zfiqhG.js → lua-BtS2idK7.js} +1 -1
  115. package/dist/web/assets/markdown-renderer-CvL1pWeK.js +3 -0
  116. package/dist/web/assets/markdown-renderer-sJNNVhlS.js +1 -0
  117. package/dist/web/assets/{marko-_hrXozl2.js → marko-Wk6LBnck.js} +1 -1
  118. package/dist/web/assets/{mdc-AX9XWu8K.js → mdc-cRaXBrzL.js} +1 -1
  119. package/dist/web/assets/{media-url-D43IHXnP.js → media-url-DL8OCGGg.js} +1 -1
  120. package/dist/web/assets/{mobile-bottom-sheet-GSto0_0m.js → mobile-bottom-sheet-CoUauvLF.js} +1 -1
  121. package/dist/web/assets/mobile-explorer-sheet-CZ0HZ2E_.js +1 -0
  122. package/dist/web/assets/monaco-dotenv-language-BDYnKcnr.js +1 -0
  123. package/dist/web/assets/monaspace-argon-latin-400-italic-DHf095HZ.woff2 +0 -0
  124. package/dist/web/assets/monaspace-argon-latin-400-italic-DZMiIHEH.woff +0 -0
  125. package/dist/web/assets/monaspace-argon-latin-400-normal-DZUN4ACH.woff +0 -0
  126. package/dist/web/assets/monaspace-argon-latin-400-normal-RS-2TGNg.woff2 +0 -0
  127. package/dist/web/assets/monaspace-argon-latin-700-normal-4y--rLW1.woff +0 -0
  128. package/dist/web/assets/monaspace-argon-latin-700-normal-D9kWRRK5.woff2 +0 -0
  129. package/dist/web/assets/monaspace-krypton-latin-400-italic-BoBCEexI.woff2 +0 -0
  130. package/dist/web/assets/monaspace-krypton-latin-400-italic-LWEicbvC.woff +0 -0
  131. package/dist/web/assets/monaspace-krypton-latin-400-normal-D9XlxC9R.woff +0 -0
  132. package/dist/web/assets/monaspace-krypton-latin-400-normal-DsuVXUab.woff2 +0 -0
  133. package/dist/web/assets/nerd-symbols-codicons-DSvMY_FK.woff2 +0 -0
  134. package/dist/web/assets/nerd-symbols-devicons-BBab8P54.woff2 +0 -0
  135. package/dist/web/assets/nerd-symbols-font-awesome-BzNW1pRA.woff2 +0 -0
  136. package/dist/web/assets/nerd-symbols-font-awesome-ext-D30e--UY.woff2 +0 -0
  137. package/dist/web/assets/nerd-symbols-font-awesome-legacy-D_qekXx9.woff2 +0 -0
  138. package/dist/web/assets/nerd-symbols-font-logos-gdu3INfy.woff2 +0 -0
  139. package/dist/web/assets/nerd-symbols-iec-power-Cw6TNeDf.woff2 +0 -0
  140. package/dist/web/assets/nerd-symbols-material-l-CXi9Ay.woff2 +0 -0
  141. package/dist/web/assets/nerd-symbols-misc-BaVfdyeB.woff2 +0 -0
  142. package/dist/web/assets/nerd-symbols-octicons-CJLTTzKm.woff2 +0 -0
  143. package/dist/web/assets/nerd-symbols-pomicons-D7T3Ya3H.woff2 +0 -0
  144. package/dist/web/assets/nerd-symbols-powerline-Cgg0sdGS.woff2 +0 -0
  145. package/dist/web/assets/nerd-symbols-seti-DYiUFq6z.woff2 +0 -0
  146. package/dist/web/assets/nerd-symbols-weather-D4Jrp5XD.woff2 +0 -0
  147. package/dist/web/assets/{nextflow-xJ5dkaQ2.js → nextflow-Bos2wvDV.js} +1 -1
  148. package/dist/web/assets/{nginx-BfbjvmIV.js → nginx-DMlOwzdr.js} +1 -1
  149. package/dist/web/assets/{nim-KrUnNSwZ.js → nim-D2dZQA88.js} +1 -1
  150. package/dist/web/assets/notification-store-BZbsPnW0.js +1 -0
  151. package/dist/web/assets/notifications-settings-section-DPUROMw-.js +1 -0
  152. package/dist/web/assets/{number-overlay-editor-CGZ1ObrN.js → number-overlay-editor-DZ2i_Bnb.js} +1 -1
  153. package/dist/web/assets/{overview-panel-Ni1Wqr3E.js → overview-panel-R146OIom.js} +1 -1
  154. package/dist/web/assets/packet-RMMSAZCW-DwmYPOlx.js +1 -0
  155. package/dist/web/assets/panel-store-BVLBRn6M.js +1 -0
  156. package/dist/web/assets/pdf-preview-BWUPGLp6.js +1 -0
  157. package/dist/web/assets/{perl-DAexWIeo.js → perl-C5-Z6fPn.js} +1 -1
  158. package/dist/web/assets/{php-DXc7GdU9.js → php-BXNNhkMH.js} +1 -1
  159. package/dist/web/assets/pie-UPGHQEXC-D0oogIFi.js +1 -0
  160. package/dist/web/assets/portal-container-context-BarKmT4S.js +1 -0
  161. package/dist/web/assets/{postgres-viewer-DmbVhmJ8.js → postgres-viewer-CjOvaruz.js} +3 -3
  162. package/dist/web/assets/ppmbot-settings-section-DrvWh8l8.js +1 -0
  163. package/dist/web/assets/problems-panel-B7BWVhdy.js +1 -0
  164. package/dist/web/assets/process-table-BRMS1MrX.js +1 -0
  165. package/dist/web/assets/{project-store-DCDLF-x3.js → project-store-BhMbVln3.js} +1 -1
  166. package/dist/web/assets/proxy-settings-section-Bv0Ny-Yy.js +1 -0
  167. package/dist/web/assets/{pug-CHds8FDl.js → pug-C1zf1yWy.js} +1 -1
  168. package/dist/web/assets/{qml-DBt6oNnU.js → qml-OW58jGpD.js} +1 -1
  169. package/dist/web/assets/query-audit-section-BcHJZcVC.js +1 -0
  170. package/dist/web/assets/radar-KQ55EAFF-CQIJOQGa.js +1 -0
  171. package/dist/web/assets/{razor-DVDe2z8Z.js → razor-DzjSaobM.js} +1 -1
  172. package/dist/web/assets/{react-Bf5xrFLG.js → react-Bghu0NUO.js} +1 -1
  173. package/dist/web/assets/remote-desktop-mobile-sheet-ByjaeZKX.js +2 -0
  174. package/dist/web/assets/remote-desktop-mobile-view-D13mtr9F.js +1 -0
  175. package/dist/web/assets/remote-desktop-readiness-gate-BTzss2wX.js +1 -0
  176. package/dist/web/assets/remote-desktop-window-content-CbqTCaC6.js +1 -0
  177. package/dist/web/assets/{rst-s3rP0H8p.js → rst-RfuihOUW.js} +1 -1
  178. package/dist/web/assets/{ruby-sRcfbjlr.js → ruby-CNO3pli1.js} +1 -1
  179. package/dist/web/assets/{run-in-terminal-Yt_lq4T9.js → run-in-terminal-Cb_hVU8x.js} +1 -1
  180. package/dist/web/assets/{sas-CuyZeQJw.js → sas-DZY5BtXx.js} +1 -1
  181. package/dist/web/assets/schedules-settings-section-DO8xAOVj.js +1 -0
  182. package/dist/web/assets/scroll-area-LtNV8g5o.js +1 -0
  183. package/dist/web/assets/{scss-B9m4FneT.js → scss--4g-REcN.js} +1 -1
  184. package/dist/web/assets/{send-to-chat-01eMNs3j.js → send-to-chat-Cnpru1M0.js} +1 -1
  185. package/dist/web/assets/separator-Cds1yxy8.js +1 -0
  186. package/dist/web/assets/settings-body-Rnu-FcX-.js +2 -0
  187. package/dist/web/assets/settings-store-DZPgPtEA.js +2 -0
  188. package/dist/web/assets/settings-tab-C6PHxs0Z.js +1 -0
  189. package/dist/web/assets/settings-window-content-CQ4gT2qj.js +1 -0
  190. package/dist/web/assets/{shaderlab-BuCltaXx.js → shaderlab-Cu4sBiVn.js} +1 -1
  191. package/dist/web/assets/{shellsession-DG_WIFRW.js → shellsession-DWzJfEv7.js} +1 -1
  192. package/dist/web/assets/{soy-CKNCwmqR.js → soy-BnqE-5Ff.js} +1 -1
  193. package/dist/web/assets/{sparql-BEH92-9e.js → sparql-Ctg__NhZ.js} +1 -1
  194. package/dist/web/assets/{sql-query-editor-BTMEy88p.js → sql-query-editor-D9k19T_M.js} +1 -1
  195. package/dist/web/assets/sqlite-viewer-DoV9hnWJ.js +1 -0
  196. package/dist/web/assets/{stata-Bt5IUWCl.js → stata-Qk2h66XW.js} +1 -1
  197. package/dist/web/assets/{streaming-store-Dw3ZR1E4.js → streaming-store-uDu3PoN1.js} +1 -1
  198. package/dist/web/assets/{surrealql-B5M94PT2.js → surrealql-8QEX7EfH.js} +1 -1
  199. package/dist/web/assets/{svelte-BqLoF5fB.js → svelte-D_mubC5-.js} +1 -1
  200. package/dist/web/assets/system-monitor-body-2vQ1kMxE.js +2 -0
  201. package/dist/web/assets/system-monitor-tab-krAcvwF7.js +1 -0
  202. package/dist/web/assets/system-monitor-window-content-qXLcicFM.js +1 -0
  203. package/dist/web/assets/tab-host-window-content-7fPZNEni.js +1 -0
  204. package/dist/web/assets/{tab-store-Dsk4jnlN.js → tab-store-DGJGnbwv.js} +1 -1
  205. package/dist/web/assets/team-member-sheet-2FnRmk1a.js +2 -0
  206. package/dist/web/assets/team-member-window-content-BgvJFypM.js +1 -0
  207. package/dist/web/assets/{templ-BxGWIwYz.js → templ-C1jV0fsO.js} +1 -1
  208. package/dist/web/assets/terminal-tab-Cs0sGljx.js +3 -0
  209. package/dist/web/assets/{tex-B9CPrNBA.js → tex-D_StFXy_.js} +1 -1
  210. package/dist/web/assets/tool-cards-DU_S2o51.js +9 -0
  211. package/dist/web/assets/treemap-KZPCXAKY-BhEtjljr.js +1 -0
  212. package/dist/web/assets/{ts-tags-CObhnP_s.js → ts-tags-B5m47rEm.js} +1 -1
  213. package/dist/web/assets/{twig-ZcDaz0E8.js → twig-C_br6GIl.js} +1 -1
  214. package/dist/web/assets/{use-blob-url-D-NnFGAr.js → use-blob-url-C-SGi_Hb.js} +1 -1
  215. package/dist/web/assets/use-inline-blame-B4trxGcR.js +16 -0
  216. package/dist/web/assets/{use-is-mobile-BsqeOLv4.js → use-is-mobile-BQ9Bv5Ga.js} +1 -1
  217. package/dist/web/assets/use-lsp-CV0vzILO.js +6 -0
  218. package/dist/web/assets/use-monaco-theme-DBqbWjWX.js +1 -0
  219. package/dist/web/assets/use-open-team-member-DENsjp0s.js +1 -0
  220. package/dist/web/assets/use-remote-desktop-display-choice-BK_f787P.js +1 -0
  221. package/dist/web/assets/{use-visual-viewport-hdC_hRtB.js → use-visual-viewport-CbwnktSG.js} +1 -1
  222. package/dist/web/assets/{use-websocket-CUKjQFAl.js → use-websocket-LgXiX1qN.js} +1 -1
  223. package/dist/web/assets/vendor-markdown-CuWCHIVb.js +291 -0
  224. package/dist/web/assets/{vendor-mermaid-BoRFiriK.js → vendor-mermaid-Cbig5zA6.js} +1 -1
  225. package/dist/web/assets/{vendor-ui-D1NQnrtd.js → vendor-ui-BBdkypKW.js} +1 -1
  226. package/dist/web/assets/video-preview-BDNwumbW.js +1 -0
  227. package/dist/web/assets/{vue-TgfQfAF8.js → vue-DQwCnLdr.js} +1 -1
  228. package/dist/web/assets/{vue-html-DbAh9aHW.js → vue-html-T_EoGpPJ.js} +1 -1
  229. package/dist/web/assets/{vue-vine-DQ8US6vO.js → vue-vine-DmxLqX50.js} +1 -1
  230. package/dist/web/assets/{window-pip-registry-DfPfSFQg.js → window-pip-registry-3l4hoxuD.js} +1 -1
  231. package/dist/web/assets/{window-store-BSXqIkwB.js → window-store-UC1jJeLM.js} +1 -1
  232. package/dist/web/assets/ws-auth-DEAJiGCR.js +1 -0
  233. package/dist/web/assets/{xml-CXzUNYMl.js → xml-Bs6Bw8is.js} +1 -1
  234. package/dist/web/assets/{xsl-CdnFww1s.js → xsl-f5ZNhRCc.js} +1 -1
  235. package/dist/web/index.html +107 -73
  236. package/dist/web/sw.js +1 -1
  237. package/docs/project-roadmap.md +2 -0
  238. package/licenses/Apache-2.0.txt +73 -0
  239. package/licenses/CC-BY-4.0.txt +156 -0
  240. package/licenses/MIT.txt +18 -0
  241. package/licenses/OFL-1.1.txt +43 -0
  242. package/licenses/Unlicense.txt +10 -0
  243. package/package.json +14 -7
  244. package/packages/ext-git-graph/src/blame-view.ts +4 -5
  245. package/packages/ext-git-graph/src/commit-detail-escaping.test.ts +205 -0
  246. package/packages/ext-git-graph/src/commit-detail-file-cap.test.ts +65 -0
  247. package/packages/ext-git-graph/src/commit-message-html.test.ts +214 -0
  248. package/packages/ext-git-graph/src/commit-message-html.ts +190 -0
  249. package/packages/ext-git-graph/src/commit-request-generation.test.ts +57 -0
  250. package/packages/ext-git-graph/src/compare-view.ts +4 -5
  251. package/packages/ext-git-graph/src/extension.ts +148 -36
  252. package/packages/ext-git-graph/src/file-history-view.ts +4 -5
  253. package/packages/ext-git-graph/src/log-args.test.ts +57 -0
  254. package/packages/ext-git-graph/src/ppm-api.ts +39 -6
  255. package/packages/ext-git-graph/src/project-scope.test.ts +77 -0
  256. package/packages/ext-git-graph/src/project-scope.ts +69 -0
  257. package/packages/ext-git-graph/src/shortstat-parser.test.ts +53 -0
  258. package/packages/ext-git-graph/src/shortstat-parser.ts +45 -0
  259. package/packages/ext-git-graph/src/types.ts +2 -0
  260. package/packages/ext-git-graph/src/webview-html.test.ts +407 -0
  261. package/packages/ext-git-graph/src/webview-html.ts +631 -108
  262. package/packages/ext-git-graph/src/webview-shell.test.ts +63 -0
  263. package/packages/ext-git-graph/src/webview-shell.ts +48 -7
  264. package/packages/vscode-compat/node_modules/.bin/tsc.bunx +0 -0
  265. package/packages/vscode-compat/node_modules/.bin/tsc.exe +0 -0
  266. package/packages/vscode-compat/node_modules/.bin/tsserver.bunx +0 -0
  267. package/packages/vscode-compat/node_modules/.bin/tsserver.exe +0 -0
  268. package/scripts/check-ppm-dir-usage.sh +0 -0
  269. package/scripts/copy-monaco.ts +63 -0
  270. package/scripts/gen-file-icons.ts +485 -0
  271. package/scripts/gen-nerd-font.ts +311 -0
  272. package/scripts/gen-product-icons.ts +442 -0
  273. package/scripts/install.sh +0 -0
  274. package/scripts/monaco-staging.ts +32 -0
  275. package/scripts/precompress-web.ts +77 -0
  276. package/scripts/release.sh +0 -0
  277. package/scripts/third-party-notices.ts +160 -0
  278. package/scripts/vite-monaco-dev-assets.ts +63 -0
  279. package/src/providers/claude-agent-sdk.ts +32 -2
  280. package/src/server/index.ts +17 -0
  281. package/src/server/routes/chat.ts +16 -6
  282. package/src/server/routes/git.ts +113 -1
  283. package/src/server/routes/lsp.ts +58 -0
  284. package/src/server/routes/project-scoped.ts +2 -0
  285. package/src/server/routes/static-encoding.ts +73 -0
  286. package/src/server/routes/static-fallback.ts +51 -0
  287. package/src/server/routes/static.ts +41 -5
  288. package/src/server/ws/lsp.ts +433 -0
  289. package/src/services/chat-search.service.ts +211 -26
  290. package/src/services/edge-forwarder.ts +191 -191
  291. package/src/services/fs-ops/fs-real-path.ts +23 -0
  292. package/src/services/git-blame/commit-line-diff.ts +124 -0
  293. package/src/services/git-blame/git-blame.service.ts +96 -1
  294. package/src/services/git-repos/git-repo-discovery.ts +152 -0
  295. package/src/services/lsp/lsp-capabilities.ts +160 -0
  296. package/src/services/lsp/lsp-manager.ts +442 -0
  297. package/src/services/lsp/lsp-protocol.ts +170 -0
  298. package/src/services/lsp/lsp-session.ts +466 -0
  299. package/src/services/lsp/server-registry.ts +401 -0
  300. package/src/services/search-index-db.service.ts +10 -2
  301. package/src/services/windows-process-tree.ts +351 -351
  302. package/src/shared/blame.ts +51 -0
  303. package/src/shared/lsp-uri.ts +108 -0
  304. package/src/web/app.tsx +6 -0
  305. package/src/web/components/ai-resources/ai-resource-editor.tsx +1 -1
  306. package/src/web/components/ai-resources/ai-resources-panel.tsx +1 -1
  307. package/src/web/components/ai-resources/mcp-group.tsx +1 -1
  308. package/src/web/components/ai-resources/new-resource-menu.tsx +1 -1
  309. package/src/web/components/ai-resources/resource-visuals.tsx +1 -1
  310. package/src/web/components/auth/login-screen.tsx +1 -1
  311. package/src/web/components/auth/support-dialog.tsx +1 -1
  312. package/src/web/components/chat/attachment-chips.tsx +113 -5
  313. package/src/web/components/chat/background-command-bar.tsx +1 -1
  314. package/src/web/components/chat/background-output-panel.tsx +1 -1
  315. package/src/web/components/chat/change-edit-list.tsx +1 -1
  316. package/src/web/components/chat/change-file-row.tsx +1 -1
  317. package/src/web/components/chat/chat-history-bar.tsx +2 -2
  318. package/src/web/components/chat/chat-history-panel.tsx +1 -1
  319. package/src/web/components/chat/chat-placeholder.tsx +1 -1
  320. package/src/web/components/chat/chat-scroll-nav.tsx +1 -1
  321. package/src/web/components/chat/chat-tab.tsx +1 -1
  322. package/src/web/components/chat/chat-toolbar-overflow-menu.tsx +1 -1
  323. package/src/web/components/chat/chat-welcome.tsx +1 -1
  324. package/src/web/components/chat/codex-usage-panel.tsx +1 -1
  325. package/src/web/components/chat/file-picker.tsx +1 -1
  326. package/src/web/components/chat/image-preview-states.tsx +1 -1
  327. package/src/web/components/chat/message-action-bar.tsx +1 -1
  328. package/src/web/components/chat/message-input.tsx +1 -1
  329. package/src/web/components/chat/message-list.tsx +1 -1
  330. package/src/web/components/chat/mode-selector.tsx +1 -1
  331. package/src/web/components/chat/model-selector.tsx +1 -1
  332. package/src/web/components/chat/model-thinking-selector.tsx +1 -1
  333. package/src/web/components/chat/pre-compact-button.tsx +1 -1
  334. package/src/web/components/chat/provider-selector.tsx +1 -1
  335. package/src/web/components/chat/send-message-card.tsx +1 -1
  336. package/src/web/components/chat/session-context-menu.tsx +1 -1
  337. package/src/web/components/chat/session-debug-dialog.tsx +1 -1
  338. package/src/web/components/chat/session-history-list.tsx +1 -1
  339. package/src/web/components/chat/session-list-panel.tsx +1 -1
  340. package/src/web/components/chat/session-picker.tsx +1 -1
  341. package/src/web/components/chat/slash-command-picker.tsx +1 -1
  342. package/src/web/components/chat/task-tracker.tsx +1 -1
  343. package/src/web/components/chat/team-activity-panel.tsx +1 -1
  344. package/src/web/components/chat/team-member-activity-row.tsx +1 -1
  345. package/src/web/components/chat/team-member-list.tsx +1 -1
  346. package/src/web/components/chat/team-member-sheet.tsx +1 -1
  347. package/src/web/components/chat/team-member-window-content.tsx +1 -1
  348. package/src/web/components/chat/team-working-bar.tsx +1 -1
  349. package/src/web/components/chat/tool-cards.tsx +2 -2
  350. package/src/web/components/chat/turn-change-sheet.tsx +1 -1
  351. package/src/web/components/chat/turn-change-tray.tsx +1 -1
  352. package/src/web/components/chat/turn-cost-warning.tsx +1 -1
  353. package/src/web/components/chat/usage-badge.tsx +1 -1
  354. package/src/web/components/chat/usage-panel-shell.tsx +1 -1
  355. package/src/web/components/chat/version-switcher.tsx +1 -1
  356. package/src/web/components/database/connection-import-export.tsx +1 -1
  357. package/src/web/components/database/connection-list.tsx +1 -1
  358. package/src/web/components/database/connection-row.tsx +1 -1
  359. package/src/web/components/database/database-sidebar.tsx +1 -1
  360. package/src/web/components/database/database-viewer.tsx +1 -1
  361. package/src/web/components/database/export-button.tsx +1 -1
  362. package/src/web/components/database/glide-context-menu.tsx +1 -1
  363. package/src/web/components/database/glide-data-grid.tsx +1 -1
  364. package/src/web/components/database/glide-data-preview-panel.tsx +2 -2
  365. package/src/web/components/database/glide-grid-pagination.tsx +1 -1
  366. package/src/web/components/database/glide-grid-toolbar.tsx +1 -1
  367. package/src/web/components/database/glide-header-menu.tsx +1 -1
  368. package/src/web/components/database/glide-save-bar.tsx +1 -1
  369. package/src/web/components/database/schema-table-tree.tsx +1 -1
  370. package/src/web/components/editor/audio-preview.tsx +1 -1
  371. package/src/web/components/editor/code-editor.tsx +167 -21
  372. package/src/web/components/editor/compare-picker.tsx +1 -1
  373. package/src/web/components/editor/conflict-editor.tsx +15 -6
  374. package/src/web/components/editor/csv-preview.tsx +1 -1
  375. package/src/web/components/editor/diff-viewer.tsx +59 -37
  376. package/src/web/components/editor/docx-preview.tsx +1 -1
  377. package/src/web/components/editor/editor-breadcrumb-external.tsx +1 -1
  378. package/src/web/components/editor/editor-breadcrumb.tsx +1 -1
  379. package/src/web/components/editor/editor-language-picker.tsx +3 -1
  380. package/src/web/components/editor/editor-language-service.tsx +77 -0
  381. package/src/web/components/editor/editor-mobile-toolbar.tsx +13 -2
  382. package/src/web/components/editor/editor-placeholder.tsx +1 -1
  383. package/src/web/components/editor/editor-toolbar.tsx +1 -1
  384. package/src/web/components/editor/image-preview.tsx +1 -1
  385. package/src/web/components/editor/lsp-status.tsx +241 -0
  386. package/src/web/components/editor/pdf-preview.tsx +1 -1
  387. package/src/web/components/editor/video-player/video-player-controls.tsx +1 -1
  388. package/src/web/components/editor/video-player/video-player.tsx +1 -1
  389. package/src/web/components/editor/video-player/video-settings-menu.tsx +1 -1
  390. package/src/web/components/editor/video-preview.tsx +1 -1
  391. package/src/web/components/explorer/file-tree.tsx +1 -1
  392. package/src/web/components/explorer/inline-tree-input.tsx +1 -1
  393. package/src/web/components/explorer/search-panel.tsx +3 -2
  394. package/src/web/components/explorer/tree-node-context-menu.tsx +1 -1
  395. package/src/web/components/explorer/tree-node.tsx +5 -12
  396. package/src/web/components/extensions/extension-quickpick.tsx +1 -1
  397. package/src/web/components/extensions/extension-tree-view.tsx +1 -1
  398. package/src/web/components/extensions/extension-webview.tsx +53 -20
  399. package/src/web/components/extensions/webview-theme.ts +121 -0
  400. package/src/web/components/floating-window/pip/pip-caption-button.tsx +1 -1
  401. package/src/web/components/git/create-worktree-dialog.tsx +5 -3
  402. package/src/web/components/git/git-log-panel.tsx +4 -2
  403. package/src/web/components/git/git-placeholder.tsx +1 -1
  404. package/src/web/components/git/git-ref-badge.tsx +1 -1
  405. package/src/web/components/git/git-repo-picker.tsx +145 -0
  406. package/src/web/components/git/git-status-panel.tsx +231 -250
  407. package/src/web/components/git/git-worktree-panel.tsx +6 -4
  408. package/src/web/components/git/hunk-stage-dialog.tsx +5 -3
  409. package/src/web/components/group-chat/group-chat-tab.tsx +1 -1
  410. package/src/web/components/group-chat/group-create-dialog.tsx +1 -1
  411. package/src/web/components/group-chat/group-full-transcript-view.tsx +1 -1
  412. package/src/web/components/group-chat/group-list.tsx +1 -1
  413. package/src/web/components/group-chat/group-member-edit-dialog.tsx +1 -1
  414. package/src/web/components/group-chat/group-member-roster.tsx +1 -1
  415. package/src/web/components/group-chat/group-message-item.tsx +1 -1
  416. package/src/web/components/group-chat/group-transcript-messages.tsx +1 -1
  417. package/src/web/components/jira/jira-config-form.tsx +1 -1
  418. package/src/web/components/jira/jira-filter-builder.tsx +1 -1
  419. package/src/web/components/jira/jira-panel.tsx +1 -1
  420. package/src/web/components/jira/jira-results-panel.tsx +1 -1
  421. package/src/web/components/jira/jira-ticket-card.tsx +1 -1
  422. package/src/web/components/jira/jira-ticket-detail.tsx +1 -1
  423. package/src/web/components/jira/jira-watcher-form.tsx +1 -1
  424. package/src/web/components/jira/jira-watcher-list.tsx +1 -1
  425. package/src/web/components/layout/add-project-form.tsx +1 -1
  426. package/src/web/components/layout/cloud-alias-row.tsx +1 -1
  427. package/src/web/components/layout/cloud-share-named-tunnel-row.tsx +1 -1
  428. package/src/web/components/layout/cloud-share-popover.tsx +1 -1
  429. package/src/web/components/layout/command-palette-filter-chips.tsx +1 -1
  430. package/src/web/components/layout/command-palette.tsx +46 -8
  431. package/src/web/components/layout/dock-header.tsx +4 -4
  432. package/src/web/components/layout/dock-panel.tsx +3 -3
  433. package/src/web/components/layout/draggable-tab.tsx +20 -3
  434. package/src/web/components/layout/editor-panel.tsx +1 -1
  435. package/src/web/components/layout/mobile-drawer-tab-bar.tsx +10 -1
  436. package/src/web/components/layout/mobile-drawer.tsx +1 -1
  437. package/src/web/components/layout/mobile-nav.tsx +3 -3
  438. package/src/web/components/layout/mobile-tab-switcher-sheet.tsx +13 -4
  439. package/src/web/components/layout/nav-section-rail.tsx +1 -1
  440. package/src/web/components/layout/notification-bell-popover.tsx +1 -1
  441. package/src/web/components/layout/panel-layout.tsx +1 -1
  442. package/src/web/components/layout/project-bottom-sheet.tsx +4 -1
  443. package/src/web/components/layout/project-sort.ts +1 -1
  444. package/src/web/components/layout/project-switcher.tsx +1 -1
  445. package/src/web/components/layout/reparenting-tab.tsx +1 -1
  446. package/src/web/components/layout/sidebar.tsx +1 -1
  447. package/src/web/components/layout/status-bar.tsx +4 -1
  448. package/src/web/components/layout/tab-bar.tsx +9 -23
  449. package/src/web/components/layout/tab-content.tsx +6 -1
  450. package/src/web/components/layout/tab-pool.tsx +1 -0
  451. package/src/web/components/layout/tab-pop-out-menu-item.tsx +1 -1
  452. package/src/web/components/layout/upgrade-button.tsx +1 -1
  453. package/src/web/components/layout/wake-lock-indicator.tsx +1 -1
  454. package/src/web/components/os-explorer/explorer-body.tsx +1 -1
  455. package/src/web/components/os-explorer/explorer-breadcrumb.tsx +1 -1
  456. package/src/web/components/os-explorer/explorer-sidebar.tsx +1 -1
  457. package/src/web/components/os-explorer/explorer-sort-menu.tsx +1 -1
  458. package/src/web/components/os-explorer/explorer-toolbar.tsx +1 -1
  459. package/src/web/components/os-explorer/icons/file-type-icon-map.ts +10 -94
  460. package/src/web/components/os-explorer/icons/file-type-icon.tsx +17 -13
  461. package/src/web/components/os-explorer/mobile/mobile-bottom-toolbar.tsx +1 -1
  462. package/src/web/components/os-explorer/mobile/mobile-explorer-top-bar.tsx +1 -1
  463. package/src/web/components/os-explorer/mobile/mobile-more-sheet.tsx +1 -1
  464. package/src/web/components/os-explorer/mobile/mobile-places-sheet.tsx +1 -1
  465. package/src/web/components/os-explorer/mobile/mobile-places-strip.tsx +1 -1
  466. package/src/web/components/os-explorer/properties-dialog.tsx +1 -1
  467. package/src/web/components/os-explorer/skins/macos-window-chrome.tsx +1 -1
  468. package/src/web/components/os-explorer/skins/windows-window-chrome.tsx +1 -1
  469. package/src/web/components/os-explorer/upload/upload-batch-card.tsx +1 -1
  470. package/src/web/components/os-explorer/upload/upload-batch-row.tsx +1 -1
  471. package/src/web/components/os-explorer/use-coarse-long-press.ts +8 -0
  472. package/src/web/components/os-explorer/views/column-view-mobile.tsx +1 -1
  473. package/src/web/components/os-explorer/views/icons-view-tile.tsx +1 -1
  474. package/src/web/components/os-explorer/views/list-row.tsx +1 -1
  475. package/src/web/components/os-explorer/views/list-view.tsx +1 -1
  476. package/src/web/components/postgres/postgres-viewer.tsx +1 -1
  477. package/src/web/components/problems/problems-panel.tsx +230 -0
  478. package/src/web/components/problems/problems-status.tsx +53 -0
  479. package/src/web/components/projects/dir-suggest.tsx +1 -1
  480. package/src/web/components/projects/project-list.tsx +1 -1
  481. package/src/web/components/remote-desktop/remote-desktop-mobile-toolbar.tsx +1 -1
  482. package/src/web/components/remote-desktop/remote-desktop-mobile-view.tsx +1 -1
  483. package/src/web/components/remote-desktop/remote-desktop-readiness-gate.tsx +1 -1
  484. package/src/web/components/remote-desktop/remote-desktop-warning-gate.tsx +1 -1
  485. package/src/web/components/remote-desktop/remote-desktop-window-content.tsx +1 -1
  486. package/src/web/components/root-error-boundary.tsx +116 -0
  487. package/src/web/components/settings/accounts/account-add-dialog.tsx +1 -1
  488. package/src/web/components/settings/accounts/account-card.tsx +1 -1
  489. package/src/web/components/settings/accounts/account-export-dialog.tsx +1 -1
  490. package/src/web/components/settings/accounts/account-export-simulation.tsx +1 -1
  491. package/src/web/components/settings/accounts/account-import-dialog.tsx +1 -1
  492. package/src/web/components/settings/accounts/account-profile-panel.tsx +1 -1
  493. package/src/web/components/settings/accounts/account-rotation-settings.tsx +1 -1
  494. package/src/web/components/settings/accounts/account-token-test-dialog.tsx +1 -1
  495. package/src/web/components/settings/accounts/account-usage-pattern-chart.tsx +1 -1
  496. package/src/web/components/settings/accounts/accounts-pane-header.tsx +1 -1
  497. package/src/web/components/settings/accounts/accounts-settings-section.tsx +1 -1
  498. package/src/web/components/settings/accounts/claude-accounts-section.tsx +9 -1
  499. package/src/web/components/settings/accounts/codex-accounts-section.tsx +10 -1
  500. package/src/web/components/settings/accounts/codex-add-account-dialog.tsx +1 -1
  501. package/src/web/components/settings/accounts/codex-backup-dialog.tsx +1 -1
  502. package/src/web/components/settings/ai-settings-section.tsx +1 -1
  503. package/src/web/components/settings/appearance-settings-section.tsx +56 -1
  504. package/src/web/components/settings/change-password-section.tsx +1 -1
  505. package/src/web/components/settings/extension-manager-section.tsx +1 -1
  506. package/src/web/components/settings/general-settings-section.tsx +1 -1
  507. package/src/web/components/settings/glob-list-editor.tsx +1 -1
  508. package/src/web/components/settings/keyboard-shortcuts-section.tsx +1 -1
  509. package/src/web/components/settings/mcp-server-dialog.tsx +1 -1
  510. package/src/web/components/settings/notifications-settings-section.tsx +1 -1
  511. package/src/web/components/settings/ppmbot-settings-section.tsx +1 -1
  512. package/src/web/components/settings/proxy-settings-section.tsx +1 -1
  513. package/src/web/components/settings/proxy-test-section.tsx +1 -1
  514. package/src/web/components/settings/query-audit-section.tsx +1 -1
  515. package/src/web/components/settings/schedules/schedule-row.tsx +1 -1
  516. package/src/web/components/settings/schedules/schedules-settings-section.tsx +1 -1
  517. package/src/web/components/settings/settings-body.tsx +1 -1
  518. package/src/web/components/settings/settings-categories.ts +14 -3
  519. package/src/web/components/settings/settings-category-list.tsx +1 -1
  520. package/src/web/components/settings/settings-section-content.tsx +1 -1
  521. package/src/web/components/settings/tag-settings-section.tsx +1 -1
  522. package/src/web/components/settings/theme-grid.tsx +1 -1
  523. package/src/web/components/settings/theme-manager-section.tsx +1 -1
  524. package/src/web/components/settings/theme-picker.tsx +1 -1
  525. package/src/web/components/shared/bug-report-popup.tsx +1 -1
  526. package/src/web/components/shared/connection-lost-overlay.tsx +1 -1
  527. package/src/web/components/shared/diagram-overlay.tsx +1 -1
  528. package/src/web/components/shared/image-overlay.tsx +1 -1
  529. package/src/web/components/shared/theme-mode-menu.tsx +1 -1
  530. package/src/web/components/sqlite/sqlite-data-grid.tsx +1 -1
  531. package/src/web/components/sqlite/sqlite-table-list.tsx +1 -1
  532. package/src/web/components/sqlite/sqlite-viewer.tsx +1 -1
  533. package/src/web/components/system/process-group-row.tsx +1 -1
  534. package/src/web/components/system/process-row.tsx +1 -1
  535. package/src/web/components/system/process-table-toolbar.tsx +1 -1
  536. package/src/web/components/system/resource-status-bar.tsx +1 -1
  537. package/src/web/components/system/sortable-header.tsx +1 -1
  538. package/src/web/components/system/system-monitor-body.tsx +1 -1
  539. package/src/web/components/terminal/terminal-finish-login.tsx +1 -1
  540. package/src/web/components/terminal/terminal-links-sheet.tsx +1 -1
  541. package/src/web/components/terminal/terminal-mobile-toolbar.tsx +1 -1
  542. package/src/web/components/terminal/terminal-placeholder.tsx +1 -1
  543. package/src/web/components/terminal/terminal-tab.tsx +1 -1
  544. package/src/web/components/tunnels/named-tunnel/named-tunnel-login-step.tsx +1 -1
  545. package/src/web/components/tunnels/named-tunnel/named-tunnel-section.tsx +1 -1
  546. package/src/web/components/tunnels/named-tunnel/named-tunnel-setup-content.tsx +1 -1
  547. package/src/web/components/tunnels/named-tunnel/named-tunnel-setup-popup.tsx +1 -1
  548. package/src/web/components/tunnels/tunnel-manager-tab.tsx +1 -1
  549. package/src/web/components/ui/accordion.tsx +1 -1
  550. package/src/web/components/ui/adaptive-context-menu.tsx +9 -2
  551. package/src/web/components/ui/browse-button.tsx +1 -1
  552. package/src/web/components/ui/context-menu.tsx +1 -1
  553. package/src/web/components/ui/dialog.tsx +1 -1
  554. package/src/web/components/ui/dropdown-menu.tsx +1 -1
  555. package/src/web/components/ui/file-browser-picker.tsx +4 -6
  556. package/src/web/components/ui/select.tsx +1 -1
  557. package/src/web/components/ui/sidebar-header.tsx +1 -1
  558. package/src/web/components/ui/sonner.tsx +1 -1
  559. package/src/web/hooks/use-git-repo.ts +124 -0
  560. package/src/web/hooks/use-global-keybindings.ts +11 -6
  561. package/src/web/hooks/use-inline-blame.ts +161 -11
  562. package/src/web/hooks/use-is-touch-only.ts +46 -0
  563. package/src/web/hooks/use-lsp.ts +182 -0
  564. package/src/web/hooks/use-terminal.ts +60 -2
  565. package/src/web/hooks/use-touch-tab-drag.ts +18 -2
  566. package/src/web/hooks/use-url-sync.ts +15 -1
  567. package/src/web/index.html +74 -0
  568. package/src/web/lib/blame-hover-commands.ts +82 -0
  569. package/src/web/lib/blame-hover.ts +199 -0
  570. package/src/web/lib/chunk-recovery.ts +113 -0
  571. package/src/web/lib/editor-font.ts +70 -0
  572. package/src/web/lib/ext-command-dispatch.ts +24 -0
  573. package/src/web/lib/file-icons.generated.ts +408 -0
  574. package/src/web/lib/file-icons.tsx +192 -0
  575. package/src/web/lib/fluent-icon.tsx +62 -0
  576. package/src/web/lib/git-file-tree.ts +83 -0
  577. package/src/web/lib/git-repo-scope.ts +157 -0
  578. package/src/web/lib/icons.generated.tsx +428 -0
  579. package/src/web/lib/icons.ts +17 -0
  580. package/src/web/lib/lsp/lsp-client.ts +321 -0
  581. package/src/web/lib/lsp/lsp-documents.ts +39 -0
  582. package/src/web/lib/lsp/lsp-monaco.ts +214 -0
  583. package/src/web/lib/lsp/lsp-navigation.ts +129 -0
  584. package/src/web/lib/lsp/lsp-responses.ts +244 -0
  585. package/src/web/lib/lsp/lsp-semantic-tokens.ts +180 -0
  586. package/src/web/lib/lsp/lsp-shadow-models.ts +254 -0
  587. package/src/web/lib/lsp/monaco-builtin-typescript.ts +149 -0
  588. package/src/web/lib/lsp/register-providers.ts +458 -0
  589. package/src/web/lib/monaco-diff-language.ts +62 -0
  590. package/src/web/lib/monaco-dotenv-language.ts +134 -0
  591. package/src/web/lib/sidebar-tabs/tab-registry.ts +11 -2
  592. package/src/web/lib/tab-type-icons.ts +32 -4
  593. package/src/web/main.tsx +30 -1
  594. package/src/web/stores/git-repo-store.ts +117 -0
  595. package/src/web/stores/git-status-store.ts +10 -7
  596. package/src/web/stores/keybindings-store.ts +1 -0
  597. package/src/web/stores/panel-utils.ts +5 -2
  598. package/src/web/stores/problems-store.ts +116 -0
  599. package/src/web/stores/settings-store.ts +40 -0
  600. package/src/web/stores/tab-store.ts +2 -1
  601. package/src/web/stores/window-panel-persistence.ts +1 -0
  602. package/src/web/styles/file-icons.generated.css +1007 -0
  603. package/src/web/styles/fonts/nerd-symbols-codicons.woff2 +0 -0
  604. package/src/web/styles/fonts/nerd-symbols-devicons.woff2 +0 -0
  605. package/src/web/styles/fonts/nerd-symbols-font-awesome-ext.woff2 +0 -0
  606. package/src/web/styles/fonts/nerd-symbols-font-awesome-legacy.woff2 +0 -0
  607. package/src/web/styles/fonts/nerd-symbols-font-awesome.woff2 +0 -0
  608. package/src/web/styles/fonts/nerd-symbols-font-logos.woff2 +0 -0
  609. package/src/web/styles/fonts/nerd-symbols-iec-power.woff2 +0 -0
  610. package/src/web/styles/fonts/nerd-symbols-material.woff2 +0 -0
  611. package/src/web/styles/fonts/nerd-symbols-misc.woff2 +0 -0
  612. package/src/web/styles/fonts/nerd-symbols-octicons.woff2 +0 -0
  613. package/src/web/styles/fonts/nerd-symbols-pomicons.woff2 +0 -0
  614. package/src/web/styles/fonts/nerd-symbols-powerline.woff2 +0 -0
  615. package/src/web/styles/fonts/nerd-symbols-seti.woff2 +0 -0
  616. package/src/web/styles/fonts/nerd-symbols-weather.woff2 +0 -0
  617. package/src/web/styles/globals.css +30 -3
  618. package/src/web/styles/nerd-font.generated.css +153 -0
  619. package/src/web/sw.ts +69 -2
  620. package/src/web/theme/adapters/monaco-adapter.ts +20 -1
  621. package/src/web/theme/diff-token-rules.ts +34 -0
  622. package/src/web/theme/semantic-token-rules.ts +103 -0
  623. package/src/web/theme/theme-mode-options.ts +1 -1
  624. package/vite.config.ts +24 -7
  625. package/dist/web/assets/accounts-settings-section-DC2A6FhQ.js +0 -1
  626. package/dist/web/assets/ai-resource-editor-DDhuy_AR.js +0 -1
  627. package/dist/web/assets/ai-settings-section-J9Rbs26g.js +0 -1
  628. package/dist/web/assets/ai-settings-section-OrhLykA2.js +0 -1
  629. package/dist/web/assets/api-client-PMwZQ4iC.js +0 -1
  630. package/dist/web/assets/appearance-settings-section-BQ1dH29t.js +0 -1
  631. package/dist/web/assets/architecture-PBZL5I3N-D55g5j-p.js +0 -1
  632. package/dist/web/assets/arrow-left-y44wEZrw.js +0 -1
  633. package/dist/web/assets/arrow-right-SQ8KJIvE.js +0 -1
  634. package/dist/web/assets/audio-preview-CAVqEwDi.js +0 -1
  635. package/dist/web/assets/bot-BNu2OM_S.js +0 -1
  636. package/dist/web/assets/brain-BsjvCk4k.js +0 -1
  637. package/dist/web/assets/calendar-clock-Zydwzvp7.js +0 -1
  638. package/dist/web/assets/chat-tab-D2le8LxY.js +0 -15
  639. package/dist/web/assets/check-DczxQ5UD.js +0 -1
  640. package/dist/web/assets/chevron-down-BCt_kn-R.js +0 -1
  641. package/dist/web/assets/chevron-right-Lt-y9H_e.js +0 -1
  642. package/dist/web/assets/chevron-up-CRl1AF4q.js +0 -1
  643. package/dist/web/assets/circle-D4vp8Yky.js +0 -1
  644. package/dist/web/assets/circle-question-mark-BGbDcz7E.js +0 -1
  645. package/dist/web/assets/clock-BBIE-uf3.js +0 -1
  646. package/dist/web/assets/code-CvgQViOi.js +0 -1
  647. package/dist/web/assets/code-editor-D-8oqMBM.js +0 -7
  648. package/dist/web/assets/codex-daily-guard-h4ZpEemV.js +0 -1
  649. package/dist/web/assets/conflict-editor-B0Mj8pYR.js +0 -19
  650. package/dist/web/assets/context-menu-I07Ld1Yr.js +0 -1
  651. package/dist/web/assets/copy-Bqr2VxN5.js +0 -1
  652. package/dist/web/assets/csv-preview-Ds2oCW6U.js +0 -2
  653. package/dist/web/assets/database-BHxcoKlT.js +0 -1
  654. package/dist/web/assets/database-viewer-CiwQ6spt.js +0 -1
  655. package/dist/web/assets/diff-viewer-BomFSnpH.js +0 -4
  656. package/dist/web/assets/docx-preview-PsyMM8SN.js +0 -12
  657. package/dist/web/assets/download-hiDsGuxx.js +0 -1
  658. package/dist/web/assets/explorer-body-CExMoOiW.js +0 -2
  659. package/dist/web/assets/explorer-window-content-Hy9kB6Q7.js +0 -1
  660. package/dist/web/assets/extension-manager-section-DMb56aut.js +0 -1
  661. package/dist/web/assets/extension-webview-CQB0Uvdo.js +0 -3
  662. package/dist/web/assets/eye-DYS5JBeU.js +0 -1
  663. package/dist/web/assets/eye-off-YWCuob9F.js +0 -1
  664. package/dist/web/assets/file-exclamation-point-DpdJqj9-.js +0 -1
  665. package/dist/web/assets/files-settings-section-CVHPO3N9.js +0 -1
  666. package/dist/web/assets/flask-conical-BUxpYe-g.js +0 -1
  667. package/dist/web/assets/folder-symlink-DKTEop0L.js +0 -1
  668. package/dist/web/assets/general-settings-section-CWYR9F5y.js +0 -1
  669. package/dist/web/assets/git-log-panel-DYLF-XSq.js +0 -1
  670. package/dist/web/assets/gitGraph-HDMCJU4V-At-P8hlA.js +0 -1
  671. package/dist/web/assets/glide-data-grid-BxFN-Z6F.js +0 -141
  672. package/dist/web/assets/group-chat-tab-Ch6OGMKj.js +0 -1
  673. package/dist/web/assets/hand-BomFk_WG.js +0 -1
  674. package/dist/web/assets/image-preview-DjT5Xb2L.js +0 -1
  675. package/dist/web/assets/index-BfDJvjH9.js +0 -52
  676. package/dist/web/assets/index-Di9nVG3y.css +0 -2
  677. package/dist/web/assets/info-3K5VOQVL-btSsuixb.js +0 -1
  678. package/dist/web/assets/key-round-BhkPzOjZ.js +0 -1
  679. package/dist/web/assets/keybindings-store-CNqxSJxv.js +0 -1
  680. package/dist/web/assets/keyboard-IQMXPNIE.js +0 -1
  681. package/dist/web/assets/keyboard-shortcuts-section-DAFNxA49.js +0 -1
  682. package/dist/web/assets/loader-circle-Bm-Dq_wA.js +0 -1
  683. package/dist/web/assets/markdown-renderer-BSiaxWjE.js +0 -1
  684. package/dist/web/assets/markdown-renderer-CMNnYOPG.js +0 -3
  685. package/dist/web/assets/mobile-explorer-sheet-BMg4Q9Bm.js +0 -1
  686. package/dist/web/assets/monitor-DEoVYSPl.js +0 -1
  687. package/dist/web/assets/notification-store-CRlOB9I9.js +0 -1
  688. package/dist/web/assets/notifications-settings-section-Cci_OOHx.js +0 -1
  689. package/dist/web/assets/packet-RMMSAZCW-B20_sIFd.js +0 -1
  690. package/dist/web/assets/panel-store-BcgZsiXU.js +0 -1
  691. package/dist/web/assets/pdf-preview-C28MEOND.js +0 -1
  692. package/dist/web/assets/pie-UPGHQEXC-nzfJdXCC.js +0 -1
  693. package/dist/web/assets/portal-container-context-DO44JpXO.js +0 -1
  694. package/dist/web/assets/power-BMdSjXYW.js +0 -1
  695. package/dist/web/assets/ppmbot-settings-section-Cef8FSS6.js +0 -1
  696. package/dist/web/assets/process-table-BfixzY3r.js +0 -1
  697. package/dist/web/assets/proxy-settings-section-BlLWfinY.js +0 -1
  698. package/dist/web/assets/query-audit-section-qnSL15x8.js +0 -1
  699. package/dist/web/assets/radar-KQ55EAFF-CS4sHKD5.js +0 -1
  700. package/dist/web/assets/remote-desktop-mobile-sheet-CG6h4OL2.js +0 -2
  701. package/dist/web/assets/remote-desktop-mobile-view-D__2WLV5.js +0 -1
  702. package/dist/web/assets/remote-desktop-readiness-gate-rL48PCUH.js +0 -1
  703. package/dist/web/assets/remote-desktop-window-content-DlGUCbxq.js +0 -1
  704. package/dist/web/assets/save-CIuK3QI4.js +0 -1
  705. package/dist/web/assets/schedules-settings-section-BUqf3KTd.js +0 -1
  706. package/dist/web/assets/send-DQz3yIWM.js +0 -1
  707. package/dist/web/assets/separator-CE0YEyaB.js +0 -1
  708. package/dist/web/assets/settings-body-Baw2komX.js +0 -2
  709. package/dist/web/assets/settings-store-CuQlVCIe.js +0 -2
  710. package/dist/web/assets/settings-tab-DCW-3C38.js +0 -1
  711. package/dist/web/assets/settings-window-content-CVxOGqPV.js +0 -1
  712. package/dist/web/assets/shield-check-46EViZ6-.js +0 -1
  713. package/dist/web/assets/shield-off-Dx5mw3le.js +0 -1
  714. package/dist/web/assets/sparkles-Bay_CedB.js +0 -1
  715. package/dist/web/assets/sqlite-viewer-BWLSC3VJ.js +0 -1
  716. package/dist/web/assets/system-monitor-body-BqPyB0CY.js +0 -2
  717. package/dist/web/assets/system-monitor-tab-BXRvCThe.js +0 -1
  718. package/dist/web/assets/system-monitor-window-content-CvvwXkmW.js +0 -1
  719. package/dist/web/assets/tab-host-window-content-23IR3qzu.js +0 -1
  720. package/dist/web/assets/table-BbD_HNPU.js +0 -1
  721. package/dist/web/assets/team-member-sheet-BXJtrQAB.js +0 -2
  722. package/dist/web/assets/team-member-window-content-CBWnzwZ1.js +0 -1
  723. package/dist/web/assets/terminal-tab-uNw7Yvwg.js +0 -3
  724. package/dist/web/assets/text-wrap-97GXZlav.js +0 -1
  725. package/dist/web/assets/tool-cards-CjirOQfx.js +0 -9
  726. package/dist/web/assets/treemap-KZPCXAKY-BBrhTPZk.js +0 -1
  727. package/dist/web/assets/use-coarse-long-press-CynaAB7m.js +0 -1
  728. package/dist/web/assets/use-inline-blame-BLPCADZ8.js +0 -8
  729. package/dist/web/assets/use-monaco-theme-D2ETCHji.js +0 -1
  730. package/dist/web/assets/use-open-team-member-BlUqTp-l.js +0 -1
  731. package/dist/web/assets/use-remote-desktop-display-choice-B4O11KIj.js +0 -1
  732. package/dist/web/assets/vendor-markdown-3-bej77C.js +0 -291
  733. package/dist/web/assets/video-preview-BlD1DNP8.js +0 -1
  734. package/dist/web/assets/ws-auth-ZB8jvzhM.js +0 -1
  735. package/dist/web/assets/x-TEI-uJYo.js +0 -1
  736. package/dist/web/monacoeditorwork/css.worker.bundle.js +0 -54268
  737. package/dist/web/monacoeditorwork/editor.worker.bundle.js +0 -14316
  738. package/dist/web/monacoeditorwork/html.worker.bundle.js +0 -30452
  739. package/dist/web/monacoeditorwork/json.worker.bundle.js +0 -22095
  740. package/dist/web/monacoeditorwork/ts.worker.bundle.js +0 -225957
  741. package/src/web/components/explorer/file-icon-map.ts +0 -69
  742. /package/dist/web/assets/{abap-Dbc91hEB.js → abap-tkptwpsK.js} +0 -0
  743. /package/dist/web/assets/{actionscript-3-C14d4O5M.js → actionscript-3-Di9TMGwg.js} +0 -0
  744. /package/dist/web/assets/{ada-n8mPGtZF.js → ada-CB9F079D.js} +0 -0
  745. /package/dist/web/assets/{andromeeda-DAKL0TFq.js → andromeeda-Dcl8jpb7.js} +0 -0
  746. /package/dist/web/assets/{apache-BDCV8YqE.js → apache-D0Nk0qsH.js} +0 -0
  747. /package/dist/web/assets/{apex-BphlFNA_.js → apex-mQIoWncD.js} +0 -0
  748. /package/dist/web/assets/{applescript-F2pJar76.js → applescript-C6ljbcsI.js} +0 -0
  749. /package/dist/web/assets/{apply-theme-Abd1TNqE.js → apply-theme-BwIMNXyX.js} +0 -0
  750. /package/dist/web/assets/{ara-B32t5JRb.js → ara-WFqRPGPe.js} +0 -0
  751. /package/dist/web/assets/{asciidoc-DenFyKu-.js → asciidoc-bNd8w4nf.js} +0 -0
  752. /package/dist/web/assets/{asm-D5mJz41u.js → asm-BQ1_F580.js} +0 -0
  753. /package/dist/web/assets/{aurora-x-CUyAXiXM.js → aurora-x-Ciqs_Dbu.js} +0 -0
  754. /package/dist/web/assets/{awk-CUwaf-l-.js → awk-GCR-6KZV.js} +0 -0
  755. /package/dist/web/assets/{ayu-dark-Cgg8W7cK.js → ayu-dark-DxJXuj99.js} +0 -0
  756. /package/dist/web/assets/{ayu-light-B1c04Bhg.js → ayu-light-jvSyJWDV.js} +0 -0
  757. /package/dist/web/assets/{ayu-mirage-CdWbuzp5.js → ayu-mirage-Cg3BPO6H.js} +0 -0
  758. /package/dist/web/assets/{ballerina-B2-GPRG0.js → ballerina-BPz4CrX6.js} +0 -0
  759. /package/dist/web/assets/{bat-Nss7Yr-0.js → bat-CSTs2hIG.js} +0 -0
  760. /package/dist/web/assets/{beancount-CgaWuvpQ.js → beancount-DMateAZX.js} +0 -0
  761. /package/dist/web/assets/{berry-DCFF4Zj1.js → berry-9lXg0GRM.js} +0 -0
  762. /package/dist/web/assets/{bibtex-BPNI-Gig.js → bibtex-DIbqmvFg.js} +0 -0
  763. /package/dist/web/assets/{bicep-qCj6DX1x.js → bicep-02WGsoJ8.js} +0 -0
  764. /package/dist/web/assets/{bird2-DYDjG-B_.js → bird2-BY0tbu3k.js} +0 -0
  765. /package/dist/web/assets/{c-CZV8SiOL.js → c-jMBX_9Je.js} +0 -0
  766. /package/dist/web/assets/{c3-BG7R2A4x.js → c3-B8JVbNjW.js} +0 -0
  767. /package/dist/web/assets/{cadence-BuiQVST4.js → cadence-DUIf1tvL.js} +0 -0
  768. /package/dist/web/assets/{can-open-in-ppm-DU5MH6XF.js → can-open-in-ppm-DGEc0s4P.js} +0 -0
  769. /package/dist/web/assets/{catppuccin-frappe-C-nwrEbb.js → catppuccin-frappe-FhUCVxex.js} +0 -0
  770. /package/dist/web/assets/{catppuccin-latte-nRLBO6vg.js → catppuccin-latte-CzfrtmgL.js} +0 -0
  771. /package/dist/web/assets/{catppuccin-macchiato-42eAAqCw.js → catppuccin-macchiato-6xL0lOtj.js} +0 -0
  772. /package/dist/web/assets/{catppuccin-mocha-4lH0_4tX.js → catppuccin-mocha-D39-xS3P.js} +0 -0
  773. /package/dist/web/assets/{clarity-BCPLN5zJ.js → clarity-D8TeGvoT.js} +0 -0
  774. /package/dist/web/assets/{clojure-Btb509Z6.js → clojure-Dx_acSX7.js} +0 -0
  775. /package/dist/web/assets/{cmake-CGLZgJL3.js → cmake-CyeYPq8o.js} +0 -0
  776. /package/dist/web/assets/{codeowners-Dgqmdm5J.js → codeowners-DrTI0lmI.js} +0 -0
  777. /package/dist/web/assets/{codeql-DDUO6ZHS.js → codeql-CPkFxVW-.js} +0 -0
  778. /package/dist/web/assets/{common-lisp-DlhZ-mM8.js → common-lisp-B0k-3LTj.js} +0 -0
  779. /package/dist/web/assets/{coq-CVz-5qYC.js → coq-uygpo7to.js} +0 -0
  780. /package/dist/web/assets/{csharp-CXL6GcvM.js → csharp-DKUYGfSp.js} +0 -0
  781. /package/dist/web/assets/{css-CthwUm0E.js → css-DoOUp7v4.js} +0 -0
  782. /package/dist/web/assets/{csv-Bsal3rDr.js → csv-B3YE13gi.js} +0 -0
  783. /package/dist/web/assets/{csv-parser-iow1WWML.js → csv-parser-DXePqmXe.js} +0 -0
  784. /package/dist/web/assets/{cue-D2bSqa4C.js → cue-DViO2wvn.js} +0 -0
  785. /package/dist/web/assets/{cypher-u-EM8HmU.js → cypher-4BMCIW5N.js} +0 -0
  786. /package/dist/web/assets/{d-BFVkgfjO.js → d-BT_sTHas.js} +0 -0
  787. /package/dist/web/assets/{dark-plus-BXlM9uFB.js → dark-plus-DVVXu-1N.js} +0 -0
  788. /package/dist/web/assets/{dart-Hxx4mUdp.js → dart-DHz6f6_6.js} +0 -0
  789. /package/dist/web/assets/{dax-DQwsaFe_.js → dax-ChYCjweK.js} +0 -0
  790. /package/dist/web/assets/{desktop-CAHGHZLk.js → desktop-D6Lt4p04.js} +0 -0
  791. /package/dist/web/assets/{diff-CAbIXu6l.js → diff-D8TDe4hP.js} +0 -0
  792. /package/dist/web/assets/{dist-C_bG2Tku.js → dist-DOTlFQJA.js} +0 -0
  793. /package/dist/web/assets/{docker-51FhFKmM.js → docker-Bsp0YbPx.js} +0 -0
  794. /package/dist/web/assets/{dotenv-C4fc3fLK.js → dotenv-B_7giSY_.js} +0 -0
  795. /package/dist/web/assets/{dracula-CTtuacPO.js → dracula-TrQL2iB5.js} +0 -0
  796. /package/dist/web/assets/{dracula-soft-B-95hu1J.js → dracula-soft-n2XOlgh-.js} +0 -0
  797. /package/dist/web/assets/{dream-maker-Di3hAOzX.js → dream-maker-CdIEdhpT.js} +0 -0
  798. /package/dist/web/assets/{emacs-lisp-C6btr6QV.js → emacs-lisp-CSbixs6u.js} +0 -0
  799. /package/dist/web/assets/{everforest-dark-CDQGzEiq.js → everforest-dark-BuZahZYp.js} +0 -0
  800. /package/dist/web/assets/{everforest-light-DRZC8v3w.js → everforest-light-DPH53z5H.js} +0 -0
  801. /package/dist/web/assets/{fennel-BZz92X8f.js → fennel-B1-K_hlJ.js} +0 -0
  802. /package/dist/web/assets/{fish-qpLXUfGf.js → fish-Cy12Dbua.js} +0 -0
  803. /package/dist/web/assets/{fluent-B3F6P-xc.js → fluent-B_82ys8E.js} +0 -0
  804. /package/dist/web/assets/{format-bytes-B9Dbme9a.js → format-bytes-D5sBgIqU.js} +0 -0
  805. /package/dist/web/assets/{fortran-free-form-DjGQrmKa.js → fortran-free-form-BRQdNzZF.js} +0 -0
  806. /package/dist/web/assets/{gdscript-DToF1duE.js → gdscript-XBDmLUm9.js} +0 -0
  807. /package/dist/web/assets/{gdshader-FZCS76-j.js → gdshader-DhVfB3u4.js} +0 -0
  808. /package/dist/web/assets/{genie-CN3-FS9S.js → genie-X3K29Y49.js} +0 -0
  809. /package/dist/web/assets/{gherkin-DT66zHzt.js → gherkin-DKIx-6cX.js} +0 -0
  810. /package/dist/web/assets/{github-dark-5S2AJM2m.js → github-dark-Bf7zdp5s.js} +0 -0
  811. /package/dist/web/assets/{github-dark-default-DNEUWmc8.js → github-dark-default-DqsBBV11.js} +0 -0
  812. /package/dist/web/assets/{github-dark-dimmed-BVgm_raB.js → github-dark-dimmed-X2gqRz6w.js} +0 -0
  813. /package/dist/web/assets/{github-dark-high-contrast-Dai8qNkr.js → github-dark-high-contrast-Z7tvbGX4.js} +0 -0
  814. /package/dist/web/assets/{github-light-C49nlhDa.js → github-light-BKxt-7zZ.js} +0 -0
  815. /package/dist/web/assets/{github-light-default-BLQcyxQl.js → github-light-default-B0liF4d4.js} +0 -0
  816. /package/dist/web/assets/{github-light-high-contrast-BH3u_hMd.js → github-light-high-contrast-F4encJwr.js} +0 -0
  817. /package/dist/web/assets/{gleam-G2907CEQ.js → gleam-Pz2bHgBB.js} +0 -0
  818. /package/dist/web/assets/{gn-fxgN7J9Q.js → gn-CgmdNsPU.js} +0 -0
  819. /package/dist/web/assets/{gnuplot-a1TK_67n.js → gnuplot-qLNF5yZ9.js} +0 -0
  820. /package/dist/web/assets/{go-DLqnNJpz.js → go-CSDUNhE7.js} +0 -0
  821. /package/dist/web/assets/{groovy-D8U-plxc.js → groovy-B3NEnOHF.js} +0 -0
  822. /package/dist/web/assets/{gruvbox-dark-hard-DRYdA7rg.js → gruvbox-dark-hard-DcoftiUX.js} +0 -0
  823. /package/dist/web/assets/{gruvbox-dark-medium-CJgayBQH.js → gruvbox-dark-medium-D1wVSuD8.js} +0 -0
  824. /package/dist/web/assets/{gruvbox-dark-soft-spQNOlQ2.js → gruvbox-dark-soft-DWpunymH.js} +0 -0
  825. /package/dist/web/assets/{gruvbox-light-hard-FoElS0Wo.js → gruvbox-light-hard-rHMvyUdS.js} +0 -0
  826. /package/dist/web/assets/{gruvbox-light-medium-9E1Brisc.js → gruvbox-light-medium-3O2KiXO7.js} +0 -0
  827. /package/dist/web/assets/{gruvbox-light-soft-Coyp7RRB.js → gruvbox-light-soft-lNlXJPwH.js} +0 -0
  828. /package/dist/web/assets/{haskell-D1twJpgj.js → haskell-aaG3aC0h.js} +0 -0
  829. /package/dist/web/assets/{haxe-CppquubK.js → haxe-CPcHhUDd.js} +0 -0
  830. /package/dist/web/assets/{hcl-BWfTkyhR.js → hcl-CMQNlR_4.js} +0 -0
  831. /package/dist/web/assets/{hjson-fgd7F6t5.js → hjson-DeuklPFj.js} +0 -0
  832. /package/dist/web/assets/{hlsl-Ua1j-4aZ.js → hlsl-BI3hlsaM.js} +0 -0
  833. /package/dist/web/assets/{horizon-CTFgrxGb.js → horizon-C7-gOcjs.js} +0 -0
  834. /package/dist/web/assets/{horizon-bright-C4eTVZPB.js → horizon-bright-Cxt9bRW7.js} +0 -0
  835. /package/dist/web/assets/{houston-BeYbWPdk.js → houston-DbF2G7iD.js} +0 -0
  836. /package/dist/web/assets/{hy-BposFX9Q.js → hy-DRG6Hs2I.js} +0 -0
  837. /package/dist/web/assets/{image-gallery-COea0nSk.js → image-gallery-CObzTisL.js} +0 -0
  838. /package/dist/web/assets/{imba-D11-b73t.js → imba-CxKv_2TW.js} +0 -0
  839. /package/dist/web/assets/{ini-BCYCXf0w.js → ini-BiHsyCdO.js} +0 -0
  840. /package/dist/web/assets/{java-BqKIPPzY.js → java-D3RZzgDB.js} +0 -0
  841. /package/dist/web/assets/{javascript-CxvTx_wu.js → javascript-4FmSqG-T.js} +0 -0
  842. /package/dist/web/assets/{json-DiknJGdj.js → json-CjB236_E.js} +0 -0
  843. /package/dist/web/assets/{json5--8nFeehk.js → json5-bkfO-Rco.js} +0 -0
  844. /package/dist/web/assets/{jsonc-BFcq-Nx-.js → jsonc-BwaTeLyv.js} +0 -0
  845. /package/dist/web/assets/{jsonl-DKItgfTA.js → jsonl-CfxNSwGd.js} +0 -0
  846. /package/dist/web/assets/{jsonnet-sNz5wf7H.js → jsonnet-CQETCYrp.js} +0 -0
  847. /package/dist/web/assets/{jssm-BALAIF_E.js → jssm-D5o3Zzdz.js} +0 -0
  848. /package/dist/web/assets/{jsx-fXHHDCVl.js → jsx-BAMILPLo.js} +0 -0
  849. /package/dist/web/assets/{kanagawa-dragon-nywk9qzg.js → kanagawa-dragon-BhGVxu3R.js} +0 -0
  850. /package/dist/web/assets/{kanagawa-lotus-BmYPLC4f.js → kanagawa-lotus-FH4Y59ro.js} +0 -0
  851. /package/dist/web/assets/{kanagawa-wave-624mOWgc.js → kanagawa-wave-eilvP9MB.js} +0 -0
  852. /package/dist/web/assets/{kdl-DT8Argim.js → kdl-BQ-yvXUK.js} +0 -0
  853. /package/dist/web/assets/{kotlin-BvUjvPz2.js → kotlin-BuCx0-VT.js} +0 -0
  854. /package/dist/web/assets/{kusto-B0PONVdx.js → kusto-DAN_n_Cy.js} +0 -0
  855. /package/dist/web/assets/{laserwave-ByV7LuzT.js → laserwave-Cq2BlxrT.js} +0 -0
  856. /package/dist/web/assets/{lean-DQtq2qQC.js → lean-Dhq7uXKw.js} +0 -0
  857. /package/dist/web/assets/{less-DZeD4ccP.js → less-CxaMQb8j.js} +0 -0
  858. /package/dist/web/assets/{libesm-CcPYXCKp.js → libesm-DdtEjhIi.js} +0 -0
  859. /package/dist/web/assets/{light-plus-BCaKDxvd.js → light-plus-B4sMAend.js} +0 -0
  860. /package/dist/web/assets/{llvm-Dzok661y.js → llvm-DQ6-B_6Y.js} +0 -0
  861. /package/dist/web/assets/{log-C32HpwgI.js → log-Bb_vqvu7.js} +0 -0
  862. /package/dist/web/assets/{logo-Dtjk3XHO.js → logo-BzfYv3A_.js} +0 -0
  863. /package/dist/web/assets/{luau-BMbN7IqN.js → luau-BnAeNR77.js} +0 -0
  864. /package/dist/web/assets/{make-DIVSnx7D.js → make-B6IFuxpC.js} +0 -0
  865. /package/dist/web/assets/{markdown-B1JzcsJb.js → markdown-Z0xi77Fn.js} +0 -0
  866. /package/dist/web/assets/{material-theme-XMfEph9O.js → material-theme-1scy1SYn.js} +0 -0
  867. /package/dist/web/assets/{material-theme-darker-CRGzh4Ox.js → material-theme-darker-G-JykXQP.js} +0 -0
  868. /package/dist/web/assets/{material-theme-lighter-D6esgP3h.js → material-theme-lighter-BtKkCMVq.js} +0 -0
  869. /package/dist/web/assets/{material-theme-ocean-CGbfRrFG.js → material-theme-ocean-irrDC89L.js} +0 -0
  870. /package/dist/web/assets/{material-theme-palenight-DFW4xdPI.js → material-theme-palenight-Eq5_K4LM.js} +0 -0
  871. /package/dist/web/assets/{matlab-Zpc8hvmI.js → matlab-BE3oCXZC.js} +0 -0
  872. /package/dist/web/assets/{mdx-DLlDpnjI.js → mdx-DYiuFTGw.js} +0 -0
  873. /package/dist/web/assets/{mermaid-q_sEDHYr.js → mermaid-DVlaEvtw.js} +0 -0
  874. /package/dist/web/assets/{min-dark-DUklXai3.js → min-dark-DSkeTpQa.js} +0 -0
  875. /package/dist/web/assets/{min-light-Ps7CV3R0.js → min-light-CFv2Q0uF.js} +0 -0
  876. /package/dist/web/assets/{mipsasm-anKs0TGD.js → mipsasm-CiAFuZQ2.js} +0 -0
  877. /package/dist/web/assets/{mojo-CWTvit9D.js → mojo-ARshcaSQ.js} +0 -0
  878. /package/dist/web/assets/{monokai-DOSMe3B9.js → monokai-CPTV-SOg.js} +0 -0
  879. /package/dist/web/assets/{moonbit-zOAryA05.js → moonbit-D57B0dZr.js} +0 -0
  880. /package/dist/web/assets/{move-CA6YZdSC.js → move-qgy3G_o9.js} +0 -0
  881. /package/dist/web/assets/{narrat-CyMxkfZJ.js → narrat-CZ3rC-oc.js} +0 -0
  882. /package/dist/web/assets/{nextflow-groovy-D5beSS3L.js → nextflow-groovy-BxxIOcI4.js} +0 -0
  883. /package/dist/web/assets/{night-owl-3ALu1K6e.js → night-owl-B1ryGCda.js} +0 -0
  884. /package/dist/web/assets/{night-owl-light-_NLbQQrl.js → night-owl-light-BZvNnvMF.js} +0 -0
  885. /package/dist/web/assets/{nix-C_KqthNc.js → nix-BVBQi8yv.js} +0 -0
  886. /package/dist/web/assets/{nord-VG8J_Wfy.js → nord-3NXw613h.js} +0 -0
  887. /package/dist/web/assets/{nushell-Dx7K7YNI.js → nushell-BMOLRalb.js} +0 -0
  888. /package/dist/web/assets/{objective-c-DrEbGERB.js → objective-c-AxruEUgh.js} +0 -0
  889. /package/dist/web/assets/{objective-cpp-DpiXqKhj.js → objective-cpp-cFT0qRsD.js} +0 -0
  890. /package/dist/web/assets/{ocaml-G6x51MAm.js → ocaml-_8JH6O8J.js} +0 -0
  891. /package/dist/web/assets/{odin-tK6CU-OU.js → odin-nwYvR0O6.js} +0 -0
  892. /package/dist/web/assets/{one-dark-pro-581te-yF.js → one-dark-pro-C1LaYJaH.js} +0 -0
  893. /package/dist/web/assets/{one-light-DpYva-U1.js → one-light-B7rMc__c.js} +0 -0
  894. /package/dist/web/assets/{openscad-C7LYrrI4.js → openscad-Cwes8bKO.js} +0 -0
  895. /package/dist/web/assets/{pascal-ChqM3eJD.js → pascal-DMt-6tdZ.js} +0 -0
  896. /package/dist/web/assets/{pkl-BlIRJsyQ.js → pkl-QBTyYQmB.js} +0 -0
  897. /package/dist/web/assets/{plastic-DxceXlOD.js → plastic-BTSUp8Fk.js} +0 -0
  898. /package/dist/web/assets/{plsql-CVikvjWK.js → plsql-DQv3IFXP.js} +0 -0
  899. /package/dist/web/assets/{po-BN9bpeJD.js → po-CNwZx4tW.js} +0 -0
  900. /package/dist/web/assets/{poimandres-NeQA7ZSh.js → poimandres-8Os7Qequ.js} +0 -0
  901. /package/dist/web/assets/{polar-DtRx-uzO.js → polar-b4yK8oD8.js} +0 -0
  902. /package/dist/web/assets/{postcss-EDnOs84S.js → postcss-sFctwpxx.js} +0 -0
  903. /package/dist/web/assets/{powerquery-mc-bbl3v.js → powerquery-Cg_WrtuN.js} +0 -0
  904. /package/dist/web/assets/{powershell-ZqZF93a-.js → powershell-C7Ifz95h.js} +0 -0
  905. /package/dist/web/assets/{prisma-vhORN1Sx.js → prisma-Z52HUJzQ.js} +0 -0
  906. /package/dist/web/assets/{prolog-DfIbN_m8.js → prolog-DLqW-zR1.js} +0 -0
  907. /package/dist/web/assets/{proto-BHcnh-Db.js → proto-BOIzxCCJ.js} +0 -0
  908. /package/dist/web/assets/{puppet-oLpQOx2h.js → puppet-De7TjZIf.js} +0 -0
  909. /package/dist/web/assets/{purescript-HbM4Dt8M.js → purescript-R76ou1WT.js} +0 -0
  910. /package/dist/web/assets/{python-Dlxo2z6Q.js → python-Dprm0tNP.js} +0 -0
  911. /package/dist/web/assets/{qmldir-B5ox9idu.js → qmldir-Clp_jpNw.js} +0 -0
  912. /package/dist/web/assets/{qss-CyegwBrl.js → qss-eQPYYzSo.js} +0 -0
  913. /package/dist/web/assets/{r-CxE2X3lg.js → r-CCcRHIf5.js} +0 -0
  914. /package/dist/web/assets/{racket-CpguQMOj.js → racket-CzE472yp.js} +0 -0
  915. /package/dist/web/assets/{raku-DDf8ASYE.js → raku-DQwXrTSi.js} +0 -0
  916. /package/dist/web/assets/{red-C634f6x3.js → red-KCS6wyop.js} +0 -0
  917. /package/dist/web/assets/{reg-4gnm7BOP.js → reg-CcrAddUh.js} +0 -0
  918. /package/dist/web/assets/{regexp-Cs-hPAru.js → regexp-DDbud-Ri.js} +0 -0
  919. /package/dist/web/assets/{rel-CrGcWbwM.js → rel-99GDgaHp.js} +0 -0
  920. /package/dist/web/assets/{resolve-theme-Dm8ehbOv.js → resolve-theme-CW2niGV2.js} +0 -0
  921. /package/dist/web/assets/{riscv-B2P26ROS.js → riscv-Dm2eNv0R.js} +0 -0
  922. /package/dist/web/assets/{ron-DDHGmvxW.js → ron-CzFt0ygH.js} +0 -0
  923. /package/dist/web/assets/{rose-pine-CUYRoYal.js → rose-pine-Ck6lCrCP.js} +0 -0
  924. /package/dist/web/assets/{rose-pine-dawn-C9JfuUh8.js → rose-pine-dawn-vtALRJNj.js} +0 -0
  925. /package/dist/web/assets/{rose-pine-moon-CrYHzRJm.js → rose-pine-moon-DPto8qXw.js} +0 -0
  926. /package/dist/web/assets/{rosmsg-iqzz1U38.js → rosmsg-NtS6429H.js} +0 -0
  927. /package/dist/web/assets/{rust-DVeWF3Is.js → rust-BjIXvF9h.js} +0 -0
  928. /package/dist/web/assets/{sass-CbVwBbUd.js → sass-CQ23wf5E.js} +0 -0
  929. /package/dist/web/assets/{scala-gZhcvPGv.js → scala-LfKLM143.js} +0 -0
  930. /package/dist/web/assets/{scheme-Z-DWgvmB.js → scheme-D3SLBXlF.js} +0 -0
  931. /package/dist/web/assets/{sdbl-wn_BtpSz.js → sdbl-ODRd2rGN.js} +0 -0
  932. /package/dist/web/assets/{shellscript-C09f889h.js → shellscript-3KB1G_oA.js} +0 -0
  933. /package/dist/web/assets/{slack-dark-D63Fbr3l.js → slack-dark-DTtyWmIy.js} +0 -0
  934. /package/dist/web/assets/{slack-ochin--Yu-v0r6.js → slack-ochin-Bu0PApk3.js} +0 -0
  935. /package/dist/web/assets/{smalltalk-LQDcL_tW.js → smalltalk-haMT-Sbe.js} +0 -0
  936. /package/dist/web/assets/{snazzy-light-bo9fX83t.js → snazzy-light-DXJzefE9.js} +0 -0
  937. /package/dist/web/assets/{solarized-dark-zSs85XH6.js → solarized-dark-B6LyYa18.js} +0 -0
  938. /package/dist/web/assets/{solarized-light-B6Q4CXBt.js → solarized-light-QLADebkv.js} +0 -0
  939. /package/dist/web/assets/{solidity-uUJPOjGx.js → solidity-mzfq1aDc.js} +0 -0
  940. /package/dist/web/assets/{splunk-C6oWgmrC.js → splunk-CyH4RWBp.js} +0 -0
  941. /package/dist/web/assets/{sql-DyUvXbLi.js → sql-CWVlT5D3.js} +0 -0
  942. /package/dist/web/assets/{ssh-config-62Vrd_7v.js → ssh-config-DNvQJ1Qx.js} +0 -0
  943. /package/dist/web/assets/{stylus-CmLQe7Fq.js → stylus-ByQQdtmf.js} +0 -0
  944. /package/dist/web/assets/{swift-DJwuT1eZ.js → swift-D1cpY4ow.js} +0 -0
  945. /package/dist/web/assets/{synthwave-84-CEeyTLD7.js → synthwave-84-BDF_-QiW.js} +0 -0
  946. /package/dist/web/assets/{system-verilog-DMqtAclw.js → system-verilog-BYrkMydC.js} +0 -0
  947. /package/dist/web/assets/{systemd-XnScP_8M.js → systemd-CQm3zyK0.js} +0 -0
  948. /package/dist/web/assets/{talonscript-CDoODzml.js → talonscript-DMW5CzE1.js} +0 -0
  949. /package/dist/web/assets/{tasl-DycI0-Tf.js → tasl-BhFzMCr2.js} +0 -0
  950. /package/dist/web/assets/{tcl-Dt8iP0sw.js → tcl-D7VEAF-9.js} +0 -0
  951. /package/dist/web/assets/{terraform-DXzABgqQ.js → terraform-DdT5A0Vy.js} +0 -0
  952. /package/dist/web/assets/{tokyo-night-DHB1Yc-3.js → tokyo-night-WGLMM6Q9.js} +0 -0
  953. /package/dist/web/assets/{toml-BkejsZF3.js → toml-CZ7ipXHZ.js} +0 -0
  954. /package/dist/web/assets/{tsv-ClmhsiiR.js → tsv-B1zVvoTr.js} +0 -0
  955. /package/dist/web/assets/{tsx-Cp-c_JHF.js → tsx-D4HwRUBq.js} +0 -0
  956. /package/dist/web/assets/{turtle-BbwC417u.js → turtle-B4r8KEJH.js} +0 -0
  957. /package/dist/web/assets/{typescript-DbwnrRKJ.js → typescript-BnHhxMtp.js} +0 -0
  958. /package/dist/web/assets/{typespec-DLL0LoZj.js → typespec-DP2q46GT.js} +0 -0
  959. /package/dist/web/assets/{typst-BmEouVT1.js → typst-DFsD_yaD.js} +0 -0
  960. /package/dist/web/assets/{utils-CwNUra6_.js → utils-Bmf_8h7Y.js} +0 -0
  961. /package/dist/web/assets/{v-C5rFgF81.js → v-Bji8hSVT.js} +0 -0
  962. /package/dist/web/assets/{vala-rBXMujLw.js → vala-D3TIgGmU.js} +0 -0
  963. /package/dist/web/assets/{vb-mxG_YZv2.js → vb-DvcxFS2q.js} +0 -0
  964. /package/dist/web/assets/{vendor-xterm-BtjgHRUe.js → vendor-xterm-BqPDsE9b.js} +0 -0
  965. /package/dist/web/assets/{verilog-uQ-oJRKp.js → verilog-Dy7cF35d.js} +0 -0
  966. /package/dist/web/assets/{vesper-SO5Hw_2X.js → vesper-BzjwUv9J.js} +0 -0
  967. /package/dist/web/assets/{vhdl-8IeO85hx.js → vhdl-DuFnFNmW.js} +0 -0
  968. /package/dist/web/assets/{viml-De-Hm57y.js → viml-yAPgKlbz.js} +0 -0
  969. /package/dist/web/assets/{vitesse-black-BVm23GJE.js → vitesse-black-oSSQdyIZ.js} +0 -0
  970. /package/dist/web/assets/{vitesse-dark-CR0XeT-h.js → vitesse-dark-BZxwPihB.js} +0 -0
  971. /package/dist/web/assets/{vitesse-light-CXIFICUA.js → vitesse-light-uIigycvt.js} +0 -0
  972. /package/dist/web/assets/{vyper-dUuvAUFJ.js → vyper-CX3NAxm5.js} +0 -0
  973. /package/dist/web/assets/{wasm-DbLMmiW0.js → wasm-6mEOOvVa.js} +0 -0
  974. /package/dist/web/assets/{wasm-D5Vd7qV1.js → wasm-D9td37qO.js} +0 -0
  975. /package/dist/web/assets/{wenyan-BafBYCBu.js → wenyan-lwNIHgk6.js} +0 -0
  976. /package/dist/web/assets/{wgsl-DY5sHamz.js → wgsl-DQAzCfog.js} +0 -0
  977. /package/dist/web/assets/{wikitext-QkQQVra5.js → wikitext-DTXmt5NE.js} +0 -0
  978. /package/dist/web/assets/{wit-BZjaDTy9.js → wit-Bdw_7WDH.js} +0 -0
  979. /package/dist/web/assets/{wolfram-vrjPFD7R.js → wolfram-DqyHDZ07.js} +0 -0
  980. /package/dist/web/assets/{yaml-D1as76NB.js → yaml-CPXhdByd.js} +0 -0
  981. /package/dist/web/assets/{zenscript-D31myxQh.js → zenscript-6s_i5zek.js} +0 -0
  982. /package/dist/web/assets/{zig-BbLb6ieN.js → zig-B2htezJ_.js} +0 -0
@@ -10,6 +10,7 @@ import { resolveTheme as resolvePpmTheme } from "@/theme/resolve-theme";
10
10
  import { getCurrentAppliedTheme, THEME_CHANGE_EVENT } from "@/theme/apply-theme";
11
11
  import { onHostResize } from "@/components/floating-window/pip/pip-resize-signal";
12
12
  import type { PpmTheme } from "@/theme/types";
13
+ import { TERMINAL_FONT_FAMILY } from "@/lib/editor-font";
13
14
 
14
15
  /** Current active PpmTheme → xterm ITheme (prefers the live applied theme). */
15
16
  function currentXtermTheme(): ITheme {
@@ -347,9 +348,25 @@ export function useTerminal(
347
348
  fontSize: 13,
348
349
  scrollback: 50000,
349
350
  // Explicit terminal-grade stack: the WebGL renderer builds its glyph
350
- // atlas via ctx.font and cannot resolve CSS var() values.
351
- fontFamily: "Consolas, 'Cascadia Mono', Menlo, 'DejaVu Sans Mono', 'Courier New', monospace",
351
+ // atlas via ctx.font and cannot resolve CSS var() values. Its own stack
352
+ // rather than the editor's, because a prompt needs the powerline and
353
+ // devicon glyphs only a patched Nerd Font has.
354
+ fontFamily: TERMINAL_FONT_FAMILY,
352
355
  theme: currentXtermTheme(),
356
+ // The two ends of an ANSI palette collapse into the background, and a
357
+ // prompt cannot know which way round the terminal is. On PPM's light
358
+ // themes `white` is #e9edf5 against a #f3f7ff background — 1.09:1, i.e.
359
+ // invisible — and on the dark ones `black` is 1.10:1. oh-my-posh writes
360
+ // its second prompt line in plain SGR 37, which is correct on the dark
361
+ // terminal it was designed for and disappeared entirely here.
362
+ //
363
+ // Repainting those palette slots is the wrong fix: the same `white` is
364
+ // also the text *on* a coloured powerline segment, where it is right.
365
+ // xterm adjusts the foreground per cell against that cell's real
366
+ // background instead, which leaves every segment untouched and only
367
+ // rescues the text that had nothing behind it. 4.5 is WCAG AA, and the
368
+ // value VS Code ships as its own default.
369
+ minimumContrastRatio: 4.5,
353
370
  });
354
371
 
355
372
  const fitAddon = new FitAddon();
@@ -382,6 +399,23 @@ export function useTerminal(
382
399
  termRef.current = term;
383
400
  fitRef.current = fitAddon;
384
401
 
402
+ // A webfont that is still in flight is not in the stack yet: xterm measures
403
+ // the cell and bakes the glyph atlas from ctx.font at open(), so a terminal
404
+ // opened during the first paint would keep whatever fallback was resolved
405
+ // then, for the rest of the session. Re-measuring once the face lands is
406
+ // the whole fix; the atlas is rebuilt from the new metrics by fit().
407
+ let fontsSettled = false;
408
+ document.fonts.ready.then(() => {
409
+ if (fontsSettled || termRef.current !== term) return;
410
+ fontsSettled = true;
411
+ try {
412
+ term.options.fontFamily = TERMINAL_FONT_FAMILY;
413
+ fitAddon.fit();
414
+ } catch {
415
+ // A terminal disposed between the promise and here; nothing to redraw.
416
+ }
417
+ });
418
+
385
419
  // Wire input to WS + track command boundaries
386
420
  term.onData((data) => {
387
421
  // When user presses Enter, mark next row as command output start
@@ -452,8 +486,32 @@ export function useTerminal(
452
486
  window.addEventListener(THEME_CHANGE_EVENT, onThemeChange);
453
487
  const unsubTheme = () => window.removeEventListener(THEME_CHANGE_EVENT, onThemeChange);
454
488
 
489
+ // The icon faces are fetched on demand — a `unicode-range` face is not
490
+ // requested until something lays out a character inside it, which for a
491
+ // prompt's Private Use Area glyphs is the first time the prompt is drawn.
492
+ // That is long after `document.fonts.ready` above has resolved, so the
493
+ // one-shot re-measure cannot see it.
494
+ //
495
+ // And nothing else redraws: measured in Chromium, a canvas `fillText` does
496
+ // start the fetch, but the glyph it painted is tofu and the canvas never
497
+ // repaints itself — ink stayed identical after the face finished loading
498
+ // and only tripled on a redraw. So the atlas the WebGL and canvas renderers
499
+ // baked has to be thrown away by hand, or the prompt is tofu for the rest
500
+ // of the session with the right font sitting loaded in the page.
501
+ const onFontLoaded = () => {
502
+ if (termRef.current !== term) return;
503
+ try {
504
+ term.clearTextureAtlas();
505
+ term.refresh(0, term.rows - 1);
506
+ } catch {
507
+ // Disposed between the event and here; nothing left to redraw.
508
+ }
509
+ };
510
+ document.fonts.addEventListener("loadingdone", onFontLoaded);
511
+
455
512
  return () => {
456
513
  unsubTheme();
514
+ document.fonts.removeEventListener("loadingdone", onFontLoaded);
457
515
  unsubHostResize();
458
516
  if (fitTimer) clearTimeout(fitTimer);
459
517
  resizeObserver.disconnect();
@@ -1,4 +1,4 @@
1
- import { useCallback, useRef, useSyncExternalStore } from "react";
1
+ import { useCallback, useEffect, useRef, useSyncExternalStore } from "react";
2
2
  import { setDragging, clearDragging, type DragPayload } from "./use-tab-drag";
3
3
  import { usePanelStore } from "@/stores/panel-store";
4
4
  import { findPanelPosition, maxColumns, MAX_ROWS } from "@/stores/panel-utils";
@@ -186,5 +186,21 @@ export function useTouchTabDrag(panelId: string) {
186
186
  if (timer.current) { clearTimeout(timer.current); timer.current = null; }
187
187
  }, []);
188
188
 
189
- return { handleTouchStart, handleTouchMove, handleTouchEnd };
189
+ /**
190
+ * The *pre-arm* timer's cancel. There is already a document-level
191
+ * `touchcancel` above, but it belongs to a drag that has begun and is only
192
+ * registered once `beginDrag` has run — it says nothing about the 200ms
193
+ * window before that. And that window is exactly where the problem is: a
194
+ * scroll fires `touchcancel` and then delivers no further `touchmove` or
195
+ * `touchend` to the tab, so the `MOVE_PX` tolerance never sees the moves it
196
+ * would have measured and the drag begins under a finger that was scrolling.
197
+ */
198
+ const handleTouchCancel = useCallback(() => {
199
+ if (timer.current) { clearTimeout(timer.current); timer.current = null; }
200
+ origin.current = null;
201
+ }, []);
202
+
203
+ useEffect(() => () => { if (timer.current) clearTimeout(timer.current); }, []);
204
+
205
+ return { handleTouchStart, handleTouchMove, handleTouchEnd, handleTouchCancel };
190
206
  }
@@ -25,6 +25,20 @@ const VALID_TAB_TYPES: TabType[] = [
25
25
  // Parse URL → state
26
26
  // ---------------------------------------------------------------------------
27
27
 
28
+ /**
29
+ * `decodeURIComponent` throws `URIError` on a percent that is not an escape —
30
+ * a hand-edited address, a truncated share link, a `%` in a branch name that
31
+ * was never encoded. Thrown from here it reaches the root and unmounts the app,
32
+ * so a mistyped URL would blank the page instead of just not resolving to a tab.
33
+ */
34
+ function decodePathSegment(segment: string): string {
35
+ try {
36
+ return decodeURIComponent(segment);
37
+ } catch {
38
+ return segment;
39
+ }
40
+ }
41
+
28
42
  /**
29
43
  * Parse the current URL to extract project name and tab info.
30
44
  * Format: /project/{name}/{tabType}/{...identifier}
@@ -37,7 +51,7 @@ export function parseUrlState(): UrlState {
37
51
  const match = path.match(/^\/project\/([^/]+)(?:\/([^/]+)(\/.*)?)?/);
38
52
  if (!match) return { projectName: null, tabType: null, tabIdentifier: null, openChat };
39
53
 
40
- const projectName = decodeURIComponent(match[1]!);
54
+ const projectName = decodePathSegment(match[1]!);
41
55
  const rawType = match[2] ?? null;
42
56
  const rawIdentifier = match[3] ? match[3].slice(1) : null; // strip leading /
43
57
 
@@ -48,6 +48,80 @@
48
48
  <div id="portal" style="position: fixed; left: 0; top: 0; z-index: 9999;" /></div>
49
49
  <div id="root"></div>
50
50
  <script type="module" src="./main.tsx"></script>
51
+ <!-- Boot watchdog: the last resort, and the only code that can still run.
52
+ The entry's module graph is ~39 separately-hashed chunks, and if any one
53
+ of them 404s — an upgrade replaced dist/web, or a stale index.html is
54
+ still naming last week's hashes — the entry module never executes. No
55
+ React, no error boundary, no listener: `#root` stays empty and the page
56
+ shows nothing but the body's background. That is the white screen, and
57
+ nothing bundled can report it, because nothing bundled ran. Hence
58
+ inline, dependency-free, and gated on the flag main.tsx sets: a boundary
59
+ inside React already covers the case where the entry *did* run. -->
60
+ <script>
61
+ (function () {
62
+ var KEY = "ppm:boot-retry";
63
+ // Every cache, not just this app's: the stale index.html that named the
64
+ // missing hashes comes from the service worker's *precache*, which is
65
+ // workbox's to name. It repopulates itself on the next activation.
66
+ function purge() {
67
+ if (!window.caches) return Promise.resolve();
68
+ return caches
69
+ .keys()
70
+ .then(function (names) { return Promise.all(names.map(function (n) { return caches.delete(n); })); })
71
+ .catch(function () {});
72
+ }
73
+ function panic() {
74
+ // The wrapper carries its own background: if the stylesheet was one of
75
+ // the chunks that went missing, `var(--bg)` on <body> resolves to
76
+ // nothing and dark-mode text would be white on white.
77
+ document.getElementById("root").innerHTML =
78
+ '<div style="min-height:100dvh;display:flex;align-items:center;justify-content:center;padding:24px;' +
79
+ 'background:var(--bg-solid,#0a0e17);color:var(--text,#eaeefb);font:16px/1.5 system-ui,sans-serif">' +
80
+ '<div role="alert" style="width:100%;max-width:440px;background:var(--panel,#141820);' +
81
+ 'border:1px solid var(--border,rgba(255,255,255,0.12));border-radius:18px;padding:24px">' +
82
+ '<h1 style="margin:0;font-size:18px;font-weight:600">PPM could not finish loading</h1>' +
83
+ '<p style="margin:12px 0 0;color:var(--text-2,#9aa6c2)">Part of the app is missing from the server, ' +
84
+ 'which usually means it was replaced by an upgrade. Reloading fetches the current version.</p>' +
85
+ '<button id="ppm-boot-retry" type="button" style="min-height:44px;width:100%;margin-top:20px;' +
86
+ 'padding:0 20px;border:0;border-radius:12px;background:var(--accent,#5b8cff);' +
87
+ 'color:var(--accent-fg,#fff);font:inherit;font-weight:600;cursor:pointer">Reload</button>' +
88
+ "</div></div>";
89
+ document.getElementById("ppm-boot-retry").onclick = function () {
90
+ try { sessionStorage.removeItem(KEY); } catch (e) {}
91
+ purge().then(function () { location.reload(); });
92
+ };
93
+ }
94
+ function check() {
95
+ // Module scripts execute before `load`, so a flag still unset here is
96
+ // never going to be set — this cannot misfire on a slow boot.
97
+ //
98
+ // A boot that worked also clears the key. The silent retry is meant to
99
+ // be one per *incident*, and the key was only ever written: after one
100
+ // upgrade healed itself, a second upgrade in the same tab session went
101
+ // straight to the panic card without trying the reload that would have
102
+ // fixed it — on a long-lived tab, which is exactly the tab this is for.
103
+ if (window.__ppmEntryRan) {
104
+ try { sessionStorage.removeItem(KEY); } catch (e) {}
105
+ return;
106
+ }
107
+ var retried;
108
+ try {
109
+ retried = sessionStorage.getItem(KEY) === "1";
110
+ sessionStorage.setItem(KEY, "1");
111
+ } catch (e) {
112
+ // No storage means no way to count attempts, and an uncounted
113
+ // reload is a loop. Go straight to the message.
114
+ retried = true;
115
+ }
116
+ // One silent attempt first: index.html is served `no-cache`, so a
117
+ // reload with this origin's caches dropped is exactly how a tab
118
+ // holding an upgraded-away chunk list heals itself.
119
+ if (!retried) { purge().then(function () { location.reload(); }); return; }
120
+ panic();
121
+ }
122
+ window.addEventListener("load", function () { setTimeout(check, 4000); });
123
+ })();
124
+ </script>
51
125
  <!-- Eruda: mobile console for debugging. Activate with ?debug in URL -->
52
126
  <script>
53
127
  if (/debug=true|debug(&|$)/.test(location.search)) {
@@ -0,0 +1,82 @@
1
+ /**
2
+ * The commands behind the blame hover's buttons.
3
+ *
4
+ * A Monaco hover can only contain markdown, so a button is a `command:` link
5
+ * and there has to be something registered under that id for it to reach. These
6
+ * are registered on the standalone `CommandsRegistry`, which is global to the
7
+ * page — hence the idempotence, and hence ids namespaced under `ppm.blame.`.
8
+ *
9
+ * Three of the four hand off to the Git Graph extension, which already has the
10
+ * views: `ext:command:execute` is the same event core UI uses elsewhere
11
+ * (`git-status-panel.tsx`), and `git-graph.blame` and `git-graph.fileHistory`
12
+ * already accept a file path as their second argument.
13
+ *
14
+ * Every handler re-checks its arguments even though `buildBlameHoverMarkdown`
15
+ * is the only thing that writes these links, and even though the hover's trust
16
+ * is narrowed so a commit message cannot forge one. The registry is global: any
17
+ * other markdown on the page could name these ids.
18
+ */
19
+ import type * as MonacoType from "monaco-editor";
20
+ import { toast } from "sonner";
21
+ import { copyToClipboard } from "./clipboard";
22
+
23
+ let registered = false;
24
+
25
+ /** Dispatch an extension command the way the rest of the app does. */
26
+ function runExtensionCommand(command: string, args: unknown[]): void {
27
+ window.dispatchEvent(new CustomEvent("ext:command:execute", { detail: { command, args } }));
28
+ }
29
+
30
+ function asHash(value: unknown): string | null {
31
+ return typeof value === "string" && /^[0-9a-f]{7,40}$/.test(value) ? value : null;
32
+ }
33
+
34
+ function asPath(value: unknown): string | null {
35
+ return typeof value === "string" && value.length > 0 ? value : null;
36
+ }
37
+
38
+ /**
39
+ * Both paths are required. An extension view command reads a falsy first
40
+ * argument as "resolve the project yourself", which for a hover that named a
41
+ * specific file would silently open some other project's history.
42
+ */
43
+ function runForFile(command: string, projectPath: unknown, filePath: unknown): void {
44
+ const root = asPath(projectPath);
45
+ const path = asPath(filePath);
46
+ if (!root || !path) return;
47
+ runExtensionCommand(command, [root, path]);
48
+ }
49
+
50
+ export function registerBlameHoverCommands(monaco: typeof MonacoType): void {
51
+ if (registered) return;
52
+ registered = true;
53
+
54
+ monaco.editor.registerCommand("ppm.blame.copySha", (_accessor, hash: unknown) => {
55
+ const sha = asHash(hash);
56
+ if (!sha) return;
57
+ // The full hash, not the abbreviation the link shows: an abbreviation is
58
+ // for reading, and what you paste into a command has to be unambiguous.
59
+ void copyToClipboard(sha).then((ok) => {
60
+ toast[ok ? "success" : "error"](ok ? `Copied ${sha.slice(0, 7)}` : "Could not copy");
61
+ });
62
+ });
63
+
64
+ monaco.editor.registerCommand("ppm.blame.fileHistory", (_accessor, projectPath: unknown, filePath: unknown) => {
65
+ runForFile("git-graph.fileHistory", projectPath, filePath);
66
+ });
67
+
68
+ monaco.editor.registerCommand("ppm.blame.blameFile", (_accessor, projectPath: unknown, filePath: unknown) => {
69
+ runForFile("git-graph.blame", projectPath, filePath);
70
+ });
71
+
72
+ monaco.editor.registerCommand("ppm.blame.showInGraph", (_accessor, projectPath: unknown) => {
73
+ const root = asPath(projectPath);
74
+ if (!root) return;
75
+ runExtensionCommand("git-graph.view", [root]);
76
+ });
77
+ }
78
+
79
+ /** Test seam. */
80
+ export function _resetBlameHoverCommands(): void {
81
+ registered = false;
82
+ }
@@ -0,0 +1,199 @@
1
+ /**
2
+ * The markdown behind the editor's blame hover — GitLens' hover, rebuilt.
3
+ *
4
+ * Monaco's hover renders a markdown string and nothing else, so everything the
5
+ * hover shows has to survive being written as markdown: the avatar is a data-URI
6
+ * image, the buttons are `command:` links, and the diff is a fenced block.
7
+ *
8
+ * Three things about that are load-bearing and were each verified against a real
9
+ * Monaco 0.55.1 rather than assumed:
10
+ *
11
+ * - `command:` links are stripped unless the string is trusted, and a trusted
12
+ * string with `isTrusted: true` allows *every* registered command. This one
13
+ * carries a commit message, and anyone who can land a commit can put
14
+ * `[click](command:whatever)` in one — so the trust is narrowed to the four
15
+ * commands here via `enabledCommands`, and the message is escaped on top.
16
+ * - `supportHtml` stays off. The avatar is `![](data:image/svg+xml,…)`, which
17
+ * renders inline at its own intrinsic size, so no `<img width>` is needed and
18
+ * no HTML from a commit message can render at all.
19
+ * - a ```diff block is only coloured because `monaco-diff-language.ts`
20
+ * registers the language Monaco lacks.
21
+ */
22
+ import type * as MonacoType from "monaco-editor";
23
+ import {
24
+ formatAbsoluteTime,
25
+ formatRelativeTime,
26
+ isUncommittedHash,
27
+ type BlameCommitInfo,
28
+ type BlameLineDetail,
29
+ } from "../../shared/blame";
30
+
31
+ /** The commands the hover's links may run. Nothing else, whatever a message says. */
32
+ export const BLAME_HOVER_COMMANDS = [
33
+ "ppm.blame.copySha",
34
+ "ppm.blame.fileHistory",
35
+ "ppm.blame.blameFile",
36
+ "ppm.blame.showInGraph",
37
+ ] as const;
38
+
39
+ /** How much of a sha to show. Git's own default abbreviation. */
40
+ const SHORT_SHA = 7;
41
+
42
+ /**
43
+ * Escape the markdown a commit message or an author name would otherwise be
44
+ * read as. The character set is VS Code's own `escapeMarkdownSyntaxTokens`.
45
+ *
46
+ * `[` and `]` are the ones that matter most: without them a message reading
47
+ * `[click](command:…)` becomes a button in the hover.
48
+ *
49
+ * `<` and `>` are added to VS Code's set because the renderer does not leave an
50
+ * unknown tag alone — it strips the tag and keeps the text inside, so a message
51
+ * mentioning `<script>alert(1)</script>` displayed as `alert(1)`. Not a script
52
+ * that runs, but a commit message rewritten in the one view whose job is to
53
+ * show it verbatim. A backslash escape rather than an entity: `&lt;` would come
54
+ * back out literally, since `&` is not escaped here.
55
+ *
56
+ * Newlines are left alone; the message's own line breaks are wanted.
57
+ */
58
+ export function escapeMarkdown(text: string): string {
59
+ return text.replace(/[\\`*_{}[\]()#+\-!<>]/g, (c) => `\\${c}`);
60
+ }
61
+
62
+ /** Initials for the avatar: first letters of the first and last word. */
63
+ export function authorInitials(author: string): string {
64
+ const words = author.trim().split(/\s+/).filter(Boolean);
65
+ if (words.length === 0) return "?";
66
+ const first = words[0]![0]!;
67
+ const last = words.length > 1 ? words[words.length - 1]![0]! : "";
68
+ return (first + last).toUpperCase();
69
+ }
70
+
71
+ /**
72
+ * A stable colour per author, from VS Code's chart palette.
73
+ *
74
+ * Deliberately not a gravatar. Fetching one would send a hash of the
75
+ * committer's email to a third party on every hover, which a self-hosted tool
76
+ * must not do silently — the same reason the git graph's author chips are
77
+ * initials.
78
+ */
79
+ const AVATAR_COLOURS = ["4E79A7", "F28E2B", "E15759", "76B7B2", "59A14F", "AF7AA1", "9C755F", "B07AA1"];
80
+
81
+ export function authorColour(author: string): string {
82
+ let hash = 0;
83
+ for (let i = 0; i < author.length; i++) hash = (hash * 31 + author.charCodeAt(i)) | 0;
84
+ return AVATAR_COLOURS[Math.abs(hash) % AVATAR_COLOURS.length]!;
85
+ }
86
+
87
+ /**
88
+ * The avatar as an inline SVG data URI, sized 16×16 so it needs no HTML
89
+ * attributes to sit on the same line as the name.
90
+ *
91
+ * `charset=utf-8` matters: initials can be non-ASCII, and without it the
92
+ * browser decodes the percent-escapes as latin-1 and draws mojibake.
93
+ */
94
+ export function avatarDataUri(author: string): string {
95
+ const svg =
96
+ `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">` +
97
+ `<circle cx="8" cy="8" r="8" fill="#${authorColour(author)}"/>` +
98
+ `<text x="8" y="11.5" font-family="sans-serif" font-size="7" font-weight="700" ` +
99
+ `fill="#ffffff" text-anchor="middle">${escapeXml(authorInitials(author))}</text></svg>`;
100
+ return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;
101
+ }
102
+
103
+ function escapeXml(text: string): string {
104
+ return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
105
+ }
106
+
107
+ /** `command:id?["arg","arg"]`, percent-encoded as the opener expects. */
108
+ function commandUri(command: (typeof BLAME_HOVER_COMMANDS)[number], args: unknown[]): string {
109
+ return `command:${command}?${encodeURIComponent(JSON.stringify(args))}`;
110
+ }
111
+
112
+ export interface BlameHoverOptions {
113
+ commit: BlameCommitInfo;
114
+ /** Null while the `git show` is still in flight, or when it found nothing. */
115
+ detail: BlameLineDetail | null;
116
+ /** Project-relative path of the open file, for the action links. */
117
+ filePath: string;
118
+ /** Absolute path of the project, which is what the git-graph commands take. */
119
+ projectPath?: string;
120
+ /** Parameter rather than the clock, so the wording is testable. */
121
+ now?: number;
122
+ }
123
+
124
+ /**
125
+ * The hover for a committed line.
126
+ *
127
+ * Returns null for an uncommitted line: there is no commit to describe, and the
128
+ * annotation already says "You, uncommitted changes".
129
+ */
130
+ export function buildBlameHoverMarkdown(options: BlameHoverOptions): MonacoType.IMarkdownString | null {
131
+ const { commit, detail, filePath, projectPath, now = Date.now() } = options;
132
+ if (isUncommittedHash(commit.hash)) return null;
133
+
134
+ const author = commit.author || "Unknown";
135
+ const shortSha = commit.hash.slice(0, SHORT_SHA);
136
+ const lines: string[] = [];
137
+
138
+ // Row 1: avatar, author, and both readings of the date — "9 months ago" is
139
+ // what you want to know, the exact date is what you need to go looking.
140
+ const when = commit.authorTime > 0
141
+ ? `${formatRelativeTime(commit.authorTime * 1000, now)} (${formatAbsoluteTime(commit.authorTime * 1000)})`
142
+ : "";
143
+ lines.push(`![](${avatarDataUri(author)}) **${escapeMarkdown(author)}**${when ? ` &nbsp;$(history) ${escapeMarkdown(when)}` : ""}`);
144
+
145
+ // Row 2: the whole message, not just the summary the annotation shows.
146
+ const message = detail?.message || commit.summary;
147
+ if (message) {
148
+ lines.push("");
149
+ // A blank line inside the message would end the markdown paragraph and
150
+ // leave the body unindented; two trailing spaces make each line its own.
151
+ lines.push(escapeMarkdown(message).split("\n").join(" \n"));
152
+ }
153
+
154
+ // A rule between sections, as GitLens has. It must be preceded by a blank
155
+ // line: `text` then `---` on the next line is a setext heading in markdown,
156
+ // which would turn the last line of the commit message into a title.
157
+ const RULE = ["", "---", ""];
158
+
159
+ // Row 3: the sha, and the things PPM can actually do with it.
160
+ const actions = [
161
+ `[$(git-commit) ${shortSha}](${commandUri("ppm.blame.copySha", [commit.hash])} "Copy commit hash")`,
162
+ ];
163
+ // The Git Graph views are addressed by absolute project path. Without one the
164
+ // links would dispatch an empty first argument, which the extension reads as
165
+ // "resolve the project yourself" — so it might open a *different* project's
166
+ // history. Better to not offer the button.
167
+ if (projectPath) {
168
+ actions.push(
169
+ `[$(history) File History](${commandUri("ppm.blame.fileHistory", [projectPath, filePath])} "Open the file's history")`,
170
+ `[$(users) Blame](${commandUri("ppm.blame.blameFile", [projectPath, filePath])} "Open the blame view")`,
171
+ `[$(git-branch) Graph](${commandUri("ppm.blame.showInGraph", [projectPath])} "Open the commit graph")`,
172
+ );
173
+ }
174
+ lines.push(...RULE);
175
+ lines.push(actions.join(" &nbsp; "));
176
+
177
+ // Row 4: what this commit did to this line.
178
+ const diff = [...(detail?.removed ?? []).map((l) => `-${l}`), ...(detail?.added ?? []).map((l) => `+${l}`)];
179
+ if (diff.length > 0) {
180
+ lines.push(...RULE);
181
+ lines.push("```diff");
182
+ lines.push(...diff);
183
+ lines.push("```");
184
+ lines.push("");
185
+ // GitLens' wording, and the distinction is worth keeping: a line that only
186
+ // ever appeared in this commit reads differently from one it rewrote.
187
+ const verb = (detail?.removed.length ?? 0) === 0 ? "added in" : "in";
188
+ lines.push(`Changes ${verb} \`${shortSha}\``);
189
+ }
190
+
191
+ return {
192
+ value: lines.join("\n"),
193
+ // Narrowed on purpose. `true` here would let a commit message's own
194
+ // `command:` link run anything registered, and a commit message is not
195
+ // ours. See the module comment.
196
+ isTrusted: { enabledCommands: [...BLAME_HOVER_COMMANDS] },
197
+ supportThemeIcons: true,
198
+ };
199
+ }
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Recovery for the one failure that empties the screen instead of reporting an
3
+ * error: a lazy chunk the running app asks for and cannot get.
4
+ *
5
+ * The chain, reproduced end to end. An upgrade replaces `dist/web` and Vite's
6
+ * `emptyOutDir` deletes the previous content hashes, so a tab that has been open
7
+ * across the upgrade asks for a chunk that is no longer on disk. `static.ts`
8
+ * used to answer that with the app shell — `200 text/html` — which a module load
9
+ * refuses on its strict MIME check; it now answers 404, but a 404 is still a
10
+ * rejected `import()`, which is a throw inside `React.lazy`. A throw with no
11
+ * boundary above it unmounts the whole tree: `#root` empties and the page is
12
+ * left showing nothing but the body's background.
13
+ *
14
+ * The service worker made it *permanent*. `CacheFirst` on `/assets/` had stored
15
+ * that `text/html` under the chunk's own URL, and content-hashed assets are
16
+ * never revalidated — so restoring the file on the server changed nothing and
17
+ * only `caches.delete("ppm-assets")` recovered the tab. `sw.ts` now refuses to
18
+ * store or serve HTML for an asset, but an install that already holds a poisoned
19
+ * entry has to be cleaned from the page, which is what this does before
20
+ * reloading.
21
+ *
22
+ * Reloading is allowed once per tab. A second failure means the chunk is
23
+ * genuinely unavailable, and a page that reloads itself forever is worse than
24
+ * one that says what happened.
25
+ */
26
+
27
+ const RELOAD_KEY = "ppm:chunk-reload";
28
+
29
+ /**
30
+ * Set once a recovery reload is on its way, and read by the `beforeunload`
31
+ * guard in `app.tsx`.
32
+ *
33
+ * That guard is unconditional while authenticated — it exists to catch a stray
34
+ * Ctrl+W — and `beforeunload` cannot tell who asked for the navigation. So the
35
+ * automatic recovery put a "Leave site?" dialog in front of the one reload the
36
+ * user never chose and cannot act on knowledgeably: the tab is already showing
37
+ * a broken app. Declining it leaves them there.
38
+ */
39
+ let recoveryReloadPending = false;
40
+
41
+ export function isRecoveryReloadPending(): boolean {
42
+ return recoveryReloadPending;
43
+ }
44
+
45
+ /**
46
+ * The wordings browsers use when a dynamic import does not produce a module.
47
+ * Chrome, Firefox and Safari each phrase it differently, and the MIME refusal
48
+ * is phrased differently again from a plain network failure.
49
+ */
50
+ const CHUNK_ERROR =
51
+ /dynamically imported module|importing a module script failed|failed to load module script|error loading chunk|expected a javascript(-or-wasm)? module script/i;
52
+
53
+ export function isChunkLoadError(error: unknown): boolean {
54
+ if (!error) return false;
55
+ const message = error instanceof Error ? `${error.name}: ${error.message}` : String(error);
56
+ return CHUNK_ERROR.test(message);
57
+ }
58
+
59
+ /** Drop the caches this app owns, so the next load asks the server again. */
60
+ export async function purgeAssetCaches(): Promise<void> {
61
+ if (typeof caches === "undefined") return;
62
+ try {
63
+ const names = await caches.keys();
64
+ await Promise.all(names.filter((n) => n.startsWith("ppm-")).map((n) => caches.delete(n)));
65
+ } catch {
66
+ // A browser in private mode can refuse the Cache API outright. Reloading
67
+ // without the purge is still the right next move.
68
+ }
69
+ }
70
+
71
+ /** Purge and reload unconditionally — the button in the error boundary. */
72
+ export async function purgeAndReload(): Promise<void> {
73
+ try {
74
+ sessionStorage.removeItem(RELOAD_KEY);
75
+ } catch {
76
+ // Nothing to clear; the reload below is what matters.
77
+ }
78
+ recoveryReloadPending = true;
79
+ await purgeAssetCaches();
80
+ window.location.reload();
81
+ }
82
+
83
+ /**
84
+ * Purge and reload at most once per tab. Returns whether a reload was started,
85
+ * so a caller can tell "recovering" from "this is as good as it gets".
86
+ */
87
+ export function reloadOnceForChunkError(): boolean {
88
+ let already: boolean;
89
+ try {
90
+ already = sessionStorage.getItem(RELOAD_KEY) === "1";
91
+ sessionStorage.setItem(RELOAD_KEY, "1");
92
+ } catch {
93
+ // No storage means no way to count attempts, and an uncounted auto-reload
94
+ // is an infinite loop. Leave it to the boundary's button.
95
+ return false;
96
+ }
97
+ if (already) return false;
98
+ recoveryReloadPending = true;
99
+ void purgeAssetCaches().then(() => window.location.reload());
100
+ return true;
101
+ }
102
+
103
+ export function installChunkErrorRecovery(): void {
104
+ // Vite's preload helper dispatches this when a chunk, or one of the chunks it
105
+ // preloads, cannot be fetched. It is deliberately *not* `preventDefault`ed:
106
+ // cancelling the event makes the helper resolve with `undefined` rather than
107
+ // rethrow, and `React.lazy` then fails reading `.default` of undefined — an
108
+ // error that says nothing about what actually happened. The reload normally
109
+ // wins the race; when it does not, the boundary catches the real throw.
110
+ window.addEventListener("vite:preloadError", () => {
111
+ reloadOnceForChunkError();
112
+ });
113
+ }