@hienlh/ppm 0.23.5 → 0.23.7

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 (714) hide show
  1. package/CHANGELOG.md +89 -0
  2. package/CLAUDE.md +21 -1
  3. package/Dockerfile.test +8 -1
  4. package/assets/skills/ppm/SKILL.md +1 -1
  5. package/assets/skills/ppm/references/cli-reference.md +4 -4
  6. package/assets/skills/ppm/references/http-api.md +30 -1
  7. package/dist/web/assets/accounts-settings-section-BYWnY9hH.js +1 -0
  8. package/dist/web/assets/accounts-settings-section-BYWnY9hH.js.br +0 -0
  9. package/dist/web/assets/accounts-settings-section-BYWnY9hH.js.gz +0 -0
  10. package/dist/web/assets/{ai-resource-editor-DKcsVDle.js → ai-resource-editor-CY4n_Ccv.js} +1 -1
  11. package/dist/web/assets/ai-resource-editor-CY4n_Ccv.js.br +0 -0
  12. package/dist/web/assets/ai-resource-editor-CY4n_Ccv.js.gz +0 -0
  13. package/dist/web/assets/ai-settings-section-Bs3iUW4j.js +1 -0
  14. package/dist/web/assets/ai-settings-section-Bs3iUW4j.js.br +0 -0
  15. package/dist/web/assets/ai-settings-section-Bs3iUW4j.js.gz +0 -0
  16. package/dist/web/assets/ai-settings-section-DDs11XV4.js +1 -0
  17. package/dist/web/assets/api-client-CJPnCOG-.js +1 -0
  18. package/dist/web/assets/{api-client-c8YOpTlT.js → api-client-D-SMbdiH.js} +1 -1
  19. package/dist/web/assets/api-client-D-SMbdiH.js.br +0 -0
  20. package/dist/web/assets/api-client-D-SMbdiH.js.gz +0 -0
  21. package/dist/web/assets/api-settings-BDkkhFMq.js +1 -0
  22. package/dist/web/assets/{api-settings-BmvNoCbn.js → api-settings-Bv9mLCty.js} +1 -1
  23. package/dist/web/assets/api-settings-Bv9mLCty.js.br +0 -0
  24. package/dist/web/assets/api-settings-Bv9mLCty.js.gz +0 -0
  25. package/dist/web/assets/{api-themes-6fOQJgM9.js → api-themes-3wW-zLzU.js} +1 -1
  26. package/dist/web/assets/appearance-settings-section-C0BoIBmz.js +1 -0
  27. package/dist/web/assets/appearance-settings-section-C0BoIBmz.js.br +0 -0
  28. package/dist/web/assets/appearance-settings-section-C0BoIBmz.js.gz +0 -0
  29. package/dist/web/assets/apps-panel-DXAFsveZ.js +1 -0
  30. package/dist/web/assets/apps-panel-DXAFsveZ.js.br +0 -0
  31. package/dist/web/assets/apps-panel-DXAFsveZ.js.gz +0 -0
  32. package/dist/web/assets/{audio-preview-vaG2cB-k.js → audio-preview-BfES4Cx5.js} +1 -1
  33. package/dist/web/assets/audio-preview-BfES4Cx5.js.br +0 -0
  34. package/dist/web/assets/audio-preview-BfES4Cx5.js.gz +0 -0
  35. package/dist/web/assets/branch-review-tab-CA8hPSX9.js +1 -0
  36. package/dist/web/assets/branch-review-tab-CA8hPSX9.js.br +0 -0
  37. package/dist/web/assets/branch-review-tab-CA8hPSX9.js.gz +0 -0
  38. package/dist/web/assets/{button-Ci9EUgqd.js → button-DeAyLH9U.js} +1 -1
  39. package/dist/web/assets/button-DeAyLH9U.js.br +0 -0
  40. package/dist/web/assets/button-DeAyLH9U.js.gz +0 -0
  41. package/dist/web/assets/{chat-preparation-cache-BSIQGiWx.js → chat-preparation-cache-CcCd2g7A.js} +1 -1
  42. package/dist/web/assets/chat-preparation-cache-CcCd2g7A.js.br +0 -0
  43. package/dist/web/assets/chat-preparation-cache-CcCd2g7A.js.gz +0 -0
  44. package/dist/web/assets/chat-tab-BWi_bUzA.js +1 -0
  45. package/dist/web/assets/chat-tab-BWi_bUzA.js.br +0 -0
  46. package/dist/web/assets/chat-tab-BWi_bUzA.js.gz +0 -0
  47. package/dist/web/assets/chat-tab-BvJhIaVE.js +15 -0
  48. package/dist/web/assets/chat-tab-BvJhIaVE.js.br +0 -0
  49. package/dist/web/assets/chat-tab-BvJhIaVE.js.gz +0 -0
  50. package/dist/web/assets/code-editor-OJUdLVnn.js +7 -0
  51. package/dist/web/assets/code-editor-OJUdLVnn.js.br +0 -0
  52. package/dist/web/assets/code-editor-OJUdLVnn.js.gz +0 -0
  53. package/dist/web/assets/codex-reset-credit-button-Dgxy_VNp.js +1 -0
  54. package/dist/web/assets/codex-reset-credit-button-Dgxy_VNp.js.br +0 -0
  55. package/dist/web/assets/codex-reset-credit-button-Dgxy_VNp.js.gz +0 -0
  56. package/dist/web/assets/{conflict-editor-qMGJH0Bx.js → conflict-editor-BpKW_vbL.js} +1 -1
  57. package/dist/web/assets/conflict-editor-BpKW_vbL.js.br +0 -0
  58. package/dist/web/assets/conflict-editor-BpKW_vbL.js.gz +0 -0
  59. package/dist/web/assets/context-menu-7OX80HDB.js +1 -0
  60. package/dist/web/assets/context-menu-7OX80HDB.js.br +0 -0
  61. package/dist/web/assets/context-menu-7OX80HDB.js.gz +0 -0
  62. package/dist/web/assets/{csv-preview-D2I742dl.js → csv-preview-COYdTABa.js} +1 -1
  63. package/dist/web/assets/csv-preview-COYdTABa.js.br +0 -0
  64. package/dist/web/assets/csv-preview-COYdTABa.js.gz +0 -0
  65. package/dist/web/assets/{data-grid-overlay-editor-CQRVKr7y.js → data-grid-overlay-editor-CeZoduke.js} +1 -1
  66. package/dist/web/assets/data-grid-overlay-editor-CeZoduke.js.br +0 -0
  67. package/dist/web/assets/data-grid-overlay-editor-CeZoduke.js.gz +0 -0
  68. package/dist/web/assets/{database-viewer-Bz4LjgIa.js → database-viewer-BQcBqCKm.js} +1 -1
  69. package/dist/web/assets/database-viewer-BQcBqCKm.js.br +0 -0
  70. package/dist/web/assets/database-viewer-BQcBqCKm.js.gz +0 -0
  71. package/dist/web/assets/{design-export-client-ChMcMoqW.js → design-export-client-OrnGCSwu.js} +1 -1
  72. package/dist/web/assets/design-export-client-OrnGCSwu.js.br +0 -0
  73. package/dist/web/assets/design-export-client-OrnGCSwu.js.gz +0 -0
  74. package/dist/web/assets/{design-responsive-dialog-DNBhJJLf.js → design-responsive-dialog-vJjQrC4n.js} +1 -1
  75. package/dist/web/assets/design-responsive-dialog-vJjQrC4n.js.br +0 -0
  76. package/dist/web/assets/design-responsive-dialog-vJjQrC4n.js.gz +0 -0
  77. package/dist/web/assets/design-tab-BbmFk38H.js +33 -0
  78. package/dist/web/assets/design-tab-BbmFk38H.js.br +0 -0
  79. package/dist/web/assets/design-tab-BbmFk38H.js.gz +0 -0
  80. package/dist/web/assets/{designs-sidebar-panel-CapP1yXq.js → designs-sidebar-panel-D2kXwB8B.js} +1 -1
  81. package/dist/web/assets/designs-sidebar-panel-D2kXwB8B.js.br +0 -0
  82. package/dist/web/assets/designs-sidebar-panel-D2kXwB8B.js.gz +0 -0
  83. package/dist/web/assets/dialog-Bocc0Fgb.js +1 -0
  84. package/dist/web/assets/dialog-Bocc0Fgb.js.br +0 -0
  85. package/dist/web/assets/dialog-Bocc0Fgb.js.gz +0 -0
  86. package/dist/web/assets/{diff-viewer-CdXi7cZN.js → diff-viewer-Bj4DT6Mj.js} +1 -1
  87. package/dist/web/assets/diff-viewer-Bj4DT6Mj.js.br +0 -0
  88. package/dist/web/assets/diff-viewer-Bj4DT6Mj.js.gz +0 -0
  89. package/dist/web/assets/{docx-preview-C9XdKEj1.js → docx-preview-C2QqNGRE.js} +1 -1
  90. package/dist/web/assets/docx-preview-C2QqNGRE.js.br +0 -0
  91. package/dist/web/assets/docx-preview-C2QqNGRE.js.gz +0 -0
  92. package/dist/web/assets/editor-language-service-COqB2tuv.js +1 -0
  93. package/dist/web/assets/editor-language-service-COqB2tuv.js.br +3 -0
  94. package/dist/web/assets/editor-language-service-COqB2tuv.js.gz +0 -0
  95. package/dist/web/assets/explorer-body-DGrYajDN.js +2 -0
  96. package/dist/web/assets/explorer-body-DGrYajDN.js.br +0 -0
  97. package/dist/web/assets/explorer-body-DGrYajDN.js.gz +0 -0
  98. package/dist/web/assets/explorer-window-content-DLzkODTP.js +1 -0
  99. package/dist/web/assets/explorer-window-content-DLzkODTP.js.br +0 -0
  100. package/dist/web/assets/explorer-window-content-DLzkODTP.js.gz +0 -0
  101. package/dist/web/assets/{extension-manager-section-B2nZzJ2b.js → extension-manager-section-Bu0qcB2i.js} +1 -1
  102. package/dist/web/assets/extension-manager-section-Bu0qcB2i.js.br +0 -0
  103. package/dist/web/assets/extension-manager-section-Bu0qcB2i.js.gz +0 -0
  104. package/dist/web/assets/{extension-webview-BGoDxkdF.js → extension-webview-G_WJ0N52.js} +1 -1
  105. package/dist/web/assets/extension-webview-G_WJ0N52.js.br +0 -0
  106. package/dist/web/assets/extension-webview-G_WJ0N52.js.gz +0 -0
  107. package/dist/web/assets/{file-icons-gx_FBOXY.js → file-icons-l7fNOmdS.js} +1 -1
  108. package/dist/web/assets/file-icons-l7fNOmdS.js.br +0 -0
  109. package/dist/web/assets/file-icons-l7fNOmdS.js.gz +0 -0
  110. package/dist/web/assets/{file-store-D9KE0kQC.js → file-store-B0e7sLag.js} +1 -1
  111. package/dist/web/assets/file-store-B0e7sLag.js.br +0 -0
  112. package/dist/web/assets/file-store-B0e7sLag.js.gz +0 -0
  113. package/dist/web/assets/{files-settings-section-DC3OzzOl.js → files-settings-section-ChZ_CynX.js} +1 -1
  114. package/dist/web/assets/files-settings-section-ChZ_CynX.js.br +0 -0
  115. package/dist/web/assets/files-settings-section-ChZ_CynX.js.gz +0 -0
  116. package/dist/web/assets/format-bytes-__396eCN.js +1 -0
  117. package/dist/web/assets/{format-file-meta-mQwA6SuY.js → format-file-meta-o1XBuoKS.js} +1 -1
  118. package/dist/web/assets/format-file-meta-o1XBuoKS.js.br +0 -0
  119. package/dist/web/assets/format-file-meta-o1XBuoKS.js.gz +0 -0
  120. package/dist/web/assets/{fs-api-DL36slbd.js → fs-api-CeHKwx95.js} +1 -1
  121. package/dist/web/assets/fs-api-CeHKwx95.js.br +0 -0
  122. package/dist/web/assets/fs-api-CeHKwx95.js.gz +0 -0
  123. package/dist/web/assets/{general-settings-section-i41W43ER.js → general-settings-section-MSvDEbFa.js} +1 -1
  124. package/dist/web/assets/general-settings-section-MSvDEbFa.js.br +0 -0
  125. package/dist/web/assets/general-settings-section-MSvDEbFa.js.gz +0 -0
  126. package/dist/web/assets/{git-log-panel-DHzPIkJg.js → git-log-panel-gw5_a6j3.js} +1 -1
  127. package/dist/web/assets/git-log-panel-gw5_a6j3.js.br +0 -0
  128. package/dist/web/assets/git-log-panel-gw5_a6j3.js.gz +0 -0
  129. package/dist/web/assets/{git-repo-store-DSypNj19.js → git-repo-store-BpPnah5l.js} +1 -1
  130. package/dist/web/assets/git-repo-store-BpPnah5l.js.br +0 -0
  131. package/dist/web/assets/git-repo-store-BpPnah5l.js.gz +0 -0
  132. package/dist/web/assets/{glide-data-grid-Dj4vrDvj.js → glide-data-grid-Db2Cl26B.js} +5 -5
  133. package/dist/web/assets/glide-data-grid-Db2Cl26B.js.br +0 -0
  134. package/dist/web/assets/glide-data-grid-Db2Cl26B.js.gz +0 -0
  135. package/dist/web/assets/group-chat-tab-B4etmYTR.js +1 -0
  136. package/dist/web/assets/group-chat-tab-B4etmYTR.js.br +0 -0
  137. package/dist/web/assets/group-chat-tab-B4etmYTR.js.gz +0 -0
  138. package/dist/web/assets/{image-preview-CGdZrmLo.js → image-preview-CjNhpfWw.js} +1 -1
  139. package/dist/web/assets/index-CtAvmybi.js +52 -0
  140. package/dist/web/assets/index-CtAvmybi.js.br +0 -0
  141. package/dist/web/assets/index-CtAvmybi.js.gz +0 -0
  142. package/dist/web/assets/index-DeCJasyy.css +1 -0
  143. package/dist/web/assets/index-DeCJasyy.css.br +0 -0
  144. package/dist/web/assets/index-DeCJasyy.css.gz +0 -0
  145. package/dist/web/assets/{jira-watcher-section-BJ9edGEP.js → jira-watcher-section-CKSI1Alo.js} +1 -1
  146. package/dist/web/assets/keybindings-store-C4_yyU4u.js +1 -0
  147. package/dist/web/assets/{keyboard-shortcuts-section-CxdGSNGr.js → keyboard-shortcuts-section-CEaVUc9a.js} +1 -1
  148. package/dist/web/assets/keyboard-shortcuts-section-CEaVUc9a.js.br +0 -0
  149. package/dist/web/assets/keyboard-shortcuts-section-CEaVUc9a.js.gz +0 -0
  150. package/dist/web/assets/language-servers-section-ePtEpnDc.js +2 -0
  151. package/dist/web/assets/language-servers-section-ePtEpnDc.js.br +0 -0
  152. package/dist/web/assets/language-servers-section-ePtEpnDc.js.gz +0 -0
  153. package/dist/web/assets/lsp-client-XzmR3Brr.js +1 -0
  154. package/dist/web/assets/lsp-client-XzmR3Brr.js.br +0 -0
  155. package/dist/web/assets/lsp-client-XzmR3Brr.js.gz +0 -0
  156. package/dist/web/assets/markdown-renderer-CTtDap-l.js +1 -0
  157. package/dist/web/assets/{markdown-renderer-ok96IgnS.js → markdown-renderer-D05fAr57.js} +2 -2
  158. package/dist/web/assets/markdown-renderer-D05fAr57.js.br +0 -0
  159. package/dist/web/assets/markdown-renderer-D05fAr57.js.gz +0 -0
  160. package/dist/web/assets/{media-url-CzUJrREv.js → media-url-C6NumuN5.js} +1 -1
  161. package/dist/web/assets/metric-chart-canvas-DHJe0VER.js +1 -0
  162. package/dist/web/assets/metric-chart-canvas-DHJe0VER.js.br +0 -0
  163. package/dist/web/assets/metric-chart-canvas-DHJe0VER.js.gz +0 -0
  164. package/dist/web/assets/{mobile-bottom-sheet-CuNi2FRv.js → mobile-bottom-sheet-D4UyOatB.js} +1 -1
  165. package/dist/web/assets/mobile-bottom-sheet-D4UyOatB.js.br +0 -0
  166. package/dist/web/assets/mobile-bottom-sheet-D4UyOatB.js.gz +0 -0
  167. package/dist/web/assets/mobile-explorer-sheet-CcfGdGL8.js +1 -0
  168. package/dist/web/assets/mobile-explorer-sheet-CcfGdGL8.js.br +0 -0
  169. package/dist/web/assets/mobile-explorer-sheet-CcfGdGL8.js.gz +0 -0
  170. package/dist/web/assets/{new-design-dialog-Drkjb_LI.js → new-design-dialog-BgmQopJM.js} +1 -1
  171. package/dist/web/assets/new-design-dialog-BgmQopJM.js.br +0 -0
  172. package/dist/web/assets/new-design-dialog-BgmQopJM.js.gz +0 -0
  173. package/dist/web/assets/notification-store-q5QBklKA.js +1 -0
  174. package/dist/web/assets/{notifications-settings-section-C05WYqcE.js → notifications-settings-section-BBJ0r9OS.js} +1 -1
  175. package/dist/web/assets/notifications-settings-section-BBJ0r9OS.js.br +0 -0
  176. package/dist/web/assets/notifications-settings-section-BBJ0r9OS.js.gz +0 -0
  177. package/dist/web/assets/{onboarding-entry-CmUqv1kl.js → onboarding-entry-BYOYswsi.js} +1 -1
  178. package/dist/web/assets/onboarding-entry-BYOYswsi.js.br +0 -0
  179. package/dist/web/assets/onboarding-entry-BYOYswsi.js.gz +0 -0
  180. package/dist/web/assets/{onboarding-quick-orientation-DIhWv1CN.js → onboarding-quick-orientation-DPHYFMbA.js} +1 -1
  181. package/dist/web/assets/onboarding-quick-orientation-DPHYFMbA.js.br +0 -0
  182. package/dist/web/assets/onboarding-quick-orientation-DPHYFMbA.js.gz +0 -0
  183. package/dist/web/assets/overview-panel-pkPs44Tv.js +1 -0
  184. package/dist/web/assets/overview-panel-pkPs44Tv.js.br +0 -0
  185. package/dist/web/assets/overview-panel-pkPs44Tv.js.gz +0 -0
  186. package/dist/web/assets/{pdf-preview-qdXmMkOR.js → pdf-preview-c-L_kDAs.js} +1 -1
  187. package/dist/web/assets/pdf-preview-c-L_kDAs.js.br +0 -0
  188. package/dist/web/assets/pdf-preview-c-L_kDAs.js.gz +0 -0
  189. package/dist/web/assets/performance-panel-yPrq0DJV.js +3 -0
  190. package/dist/web/assets/performance-panel-yPrq0DJV.js.br +0 -0
  191. package/dist/web/assets/performance-panel-yPrq0DJV.js.gz +0 -0
  192. package/dist/web/assets/{postgres-viewer-Xvlun_n5.js → postgres-viewer-CnwDCMNd.js} +1 -1
  193. package/dist/web/assets/postgres-viewer-CnwDCMNd.js.br +0 -0
  194. package/dist/web/assets/postgres-viewer-CnwDCMNd.js.gz +0 -0
  195. package/dist/web/assets/{ppmbot-settings-section-C8PFlvaq.js → ppmbot-settings-section-BDXoSIDp.js} +1 -1
  196. package/dist/web/assets/ppmbot-settings-section-BDXoSIDp.js.br +0 -0
  197. package/dist/web/assets/ppmbot-settings-section-BDXoSIDp.js.gz +0 -0
  198. package/dist/web/assets/{pptx-export-CG6MRNok.js → pptx-export-D0RDY48h.js} +4 -4
  199. package/dist/web/assets/pptx-export-D0RDY48h.js.br +0 -0
  200. package/dist/web/assets/pptx-export-D0RDY48h.js.gz +0 -0
  201. package/dist/web/assets/{problems-panel-CFYO0Ro3.js → problems-panel-BgY8oyo9.js} +1 -1
  202. package/dist/web/assets/problems-panel-BgY8oyo9.js.br +0 -0
  203. package/dist/web/assets/problems-panel-BgY8oyo9.js.gz +0 -0
  204. package/dist/web/assets/process-row-format-CaaMcHzn.js +1 -0
  205. package/dist/web/assets/process-table-BOwDtXuG.js +1 -0
  206. package/dist/web/assets/process-table-BOwDtXuG.js.br +0 -0
  207. package/dist/web/assets/process-table-BOwDtXuG.js.gz +0 -0
  208. package/dist/web/assets/{project-framework-store-XxFXcUpb.js → project-framework-store-UDEMu28U.js} +1 -1
  209. package/dist/web/assets/{project-store-C5gJXkvb.js → project-store-DGa31y5B.js} +1 -1
  210. package/dist/web/assets/project-store-DGa31y5B.js.br +0 -0
  211. package/dist/web/assets/project-store-DGa31y5B.js.gz +0 -0
  212. package/dist/web/assets/{proxy-settings-section-BcHIEANE.js → proxy-settings-section-Db6Kc6xG.js} +1 -1
  213. package/dist/web/assets/proxy-settings-section-Db6Kc6xG.js.br +0 -0
  214. package/dist/web/assets/proxy-settings-section-Db6Kc6xG.js.gz +0 -0
  215. package/dist/web/assets/{query-audit-section-UKG_smyt.js → query-audit-section-C0PAXhfT.js} +1 -1
  216. package/dist/web/assets/query-audit-section-C0PAXhfT.js.br +0 -0
  217. package/dist/web/assets/query-audit-section-C0PAXhfT.js.gz +0 -0
  218. package/dist/web/assets/{remote-desktop-clipboard-notice-BGsp0edA.js → remote-desktop-clipboard-notice-DOVtobj_.js} +1 -1
  219. package/dist/web/assets/remote-desktop-clipboard-notice-DOVtobj_.js.br +0 -0
  220. package/dist/web/assets/remote-desktop-clipboard-notice-DOVtobj_.js.gz +0 -0
  221. package/dist/web/assets/remote-desktop-mobile-sheet-DXlU3msM.js +2 -0
  222. package/dist/web/assets/remote-desktop-mobile-sheet-DXlU3msM.js.br +0 -0
  223. package/dist/web/assets/remote-desktop-mobile-sheet-DXlU3msM.js.gz +0 -0
  224. package/dist/web/assets/remote-desktop-mobile-view-ClV4YTLU.js +1 -0
  225. package/dist/web/assets/remote-desktop-mobile-view-ClV4YTLU.js.br +0 -0
  226. package/dist/web/assets/remote-desktop-mobile-view-ClV4YTLU.js.gz +0 -0
  227. package/dist/web/assets/{remote-desktop-readiness-gate-CsZCCRJI.js → remote-desktop-readiness-gate-BsfoJzdc.js} +1 -1
  228. package/dist/web/assets/remote-desktop-readiness-gate-BsfoJzdc.js.br +0 -0
  229. package/dist/web/assets/remote-desktop-readiness-gate-BsfoJzdc.js.gz +0 -0
  230. package/dist/web/assets/remote-desktop-window-content-kDaXl1_Q.js +1 -0
  231. package/dist/web/assets/remote-desktop-window-content-kDaXl1_Q.js.br +0 -0
  232. package/dist/web/assets/remote-desktop-window-content-kDaXl1_Q.js.gz +0 -0
  233. package/dist/web/assets/{schedules-settings-section-Ci0O2Ng6.js → schedules-settings-section-CvbjQM8z.js} +1 -1
  234. package/dist/web/assets/schedules-settings-section-CvbjQM8z.js.br +0 -0
  235. package/dist/web/assets/schedules-settings-section-CvbjQM8z.js.gz +0 -0
  236. package/dist/web/assets/{scroll-area-XonvWYn_.js → scroll-area-sjOeAfoD.js} +1 -1
  237. package/dist/web/assets/scroll-area-sjOeAfoD.js.br +0 -0
  238. package/dist/web/assets/scroll-area-sjOeAfoD.js.gz +0 -0
  239. package/dist/web/assets/{separator-sQj04Ari.js → separator-9A3PCG1t.js} +1 -1
  240. package/dist/web/assets/services-panel-CimW47P8.js +1 -0
  241. package/dist/web/assets/services-panel-CimW47P8.js.br +0 -0
  242. package/dist/web/assets/services-panel-CimW47P8.js.gz +0 -0
  243. package/dist/web/assets/settings-body-BTXNtpWL.js +2 -0
  244. package/dist/web/assets/settings-body-BTXNtpWL.js.br +0 -0
  245. package/dist/web/assets/settings-body-BTXNtpWL.js.gz +0 -0
  246. package/dist/web/assets/settings-store-DvftLqzy.js +2 -0
  247. package/dist/web/assets/settings-store-DvftLqzy.js.br +0 -0
  248. package/dist/web/assets/settings-store-DvftLqzy.js.gz +0 -0
  249. package/dist/web/assets/settings-tab-CGhaRXjs.js +1 -0
  250. package/dist/web/assets/settings-window-content--Uyg_Psr.js +1 -0
  251. package/dist/web/assets/sortable-header-DUW9T1Hz.js +1 -0
  252. package/dist/web/assets/sortable-header-DUW9T1Hz.js.br +0 -0
  253. package/dist/web/assets/sortable-header-DUW9T1Hz.js.gz +0 -0
  254. package/dist/web/assets/{sql-query-editor-4iCGE4h2.js → sql-query-editor-Dn-cgDrW.js} +1 -1
  255. package/dist/web/assets/sql-query-editor-Dn-cgDrW.js.br +0 -0
  256. package/dist/web/assets/sql-query-editor-Dn-cgDrW.js.gz +0 -0
  257. package/dist/web/assets/{sqlite-viewer-CK6DulYk.js → sqlite-viewer-B0NfaMjq.js} +1 -1
  258. package/dist/web/assets/sqlite-viewer-B0NfaMjq.js.br +0 -0
  259. package/dist/web/assets/sqlite-viewer-B0NfaMjq.js.gz +0 -0
  260. package/dist/web/assets/system-monitor-body-CxCfRQFb.js +2 -0
  261. package/dist/web/assets/system-monitor-body-CxCfRQFb.js.br +0 -0
  262. package/dist/web/assets/system-monitor-body-CxCfRQFb.js.gz +0 -0
  263. package/dist/web/assets/system-monitor-tab-Cb3EZUdp.js +1 -0
  264. package/dist/web/assets/system-monitor-window-content-51CA-2PH.js +1 -0
  265. package/dist/web/assets/{tab-host-window-content-CWBaWKjA.js → tab-host-window-content-CSrcmKNG.js} +1 -1
  266. package/dist/web/assets/tab-host-window-content-CSrcmKNG.js.br +0 -0
  267. package/dist/web/assets/tab-host-window-content-CSrcmKNG.js.gz +0 -0
  268. package/dist/web/assets/{team-member-sheet-Br6mrxrw.js → team-member-sheet-D4X6nh-x.js} +2 -2
  269. package/dist/web/assets/team-member-sheet-D4X6nh-x.js.br +0 -0
  270. package/dist/web/assets/team-member-sheet-D4X6nh-x.js.gz +0 -0
  271. package/dist/web/assets/{team-member-window-content-CwCy7ZWf.js → team-member-window-content-BxkbGVIL.js} +1 -1
  272. package/dist/web/assets/team-member-window-content-BxkbGVIL.js.br +0 -0
  273. package/dist/web/assets/team-member-window-content-BxkbGVIL.js.gz +0 -0
  274. package/dist/web/assets/{terminal-tab-BW14RpCb.js → terminal-tab-BYo34IqU.js} +3 -3
  275. package/dist/web/assets/terminal-tab-BYo34IqU.js.br +0 -0
  276. package/dist/web/assets/terminal-tab-BYo34IqU.js.gz +0 -0
  277. package/dist/web/assets/{tool-cards-CgOBEUnb.js → tool-cards-DvXjOped.js} +4 -4
  278. package/dist/web/assets/tool-cards-DvXjOped.js.br +0 -0
  279. package/dist/web/assets/tool-cards-DvXjOped.js.gz +0 -0
  280. package/dist/web/assets/{use-blob-url-CmavyEP8.js → use-blob-url-CISBWKG5.js} +1 -1
  281. package/dist/web/assets/use-inline-blame-Br6mheS4.js +16 -0
  282. package/dist/web/assets/use-inline-blame-Br6mheS4.js.br +0 -0
  283. package/dist/web/assets/use-inline-blame-Br6mheS4.js.gz +0 -0
  284. package/dist/web/assets/use-lsp-BpJmvQ0n.js +6 -0
  285. package/dist/web/assets/use-lsp-BpJmvQ0n.js.br +0 -0
  286. package/dist/web/assets/use-lsp-BpJmvQ0n.js.gz +0 -0
  287. package/dist/web/assets/{use-monaco-theme-rH6epJYA.js → use-monaco-theme-UGOzyIhv.js} +1 -1
  288. package/dist/web/assets/use-process-kill-CyiiUD1E.js +1 -0
  289. package/dist/web/assets/use-process-kill-CyiiUD1E.js.br +0 -0
  290. package/dist/web/assets/use-process-kill-CyiiUD1E.js.gz +0 -0
  291. package/dist/web/assets/{use-websocket-QwURkjpV.js → use-websocket-Dpl21cHG.js} +1 -1
  292. package/dist/web/assets/{vendor-ui-BHh12_0v.js → vendor-ui-P9Ym7hCv.js} +1 -1
  293. package/dist/web/assets/vendor-ui-P9Ym7hCv.js.br +0 -0
  294. package/dist/web/assets/vendor-ui-P9Ym7hCv.js.gz +0 -0
  295. package/dist/web/assets/video-preview-D6Jw-IZK.js +1 -0
  296. package/dist/web/assets/video-preview-D6Jw-IZK.js.br +0 -0
  297. package/dist/web/assets/video-preview-D6Jw-IZK.js.gz +0 -0
  298. package/dist/web/assets/voice-settings-section-CcHQDYzN.js +1 -0
  299. package/dist/web/assets/voice-settings-section-CcHQDYzN.js.br +0 -0
  300. package/dist/web/assets/voice-settings-section-CcHQDYzN.js.gz +0 -0
  301. package/dist/web/assets/ws-auth-CqI8-aoA.js +1 -0
  302. package/dist/web/index.html +20 -20
  303. package/dist/web/index.html.br +0 -0
  304. package/dist/web/index.html.gz +0 -0
  305. package/dist/web/sw.js +1 -1
  306. package/dist/web/sw.js.br +0 -0
  307. package/dist/web/sw.js.gz +0 -0
  308. package/docs/deployment-guide.md +23 -0
  309. package/package.json +1 -1
  310. package/release-from-worktree.sh +224 -0
  311. package/src/cli/commands/config-cmd.ts +12 -0
  312. package/src/providers/claude-agent-sdk.ts +65 -2
  313. package/src/providers/codex-app-server/codex-jsonrpc-client.ts +16 -1
  314. package/src/providers/codex-app-server/codex-provider.ts +39 -7
  315. package/src/providers/codex-app-server/codex-reset-credit.ts +49 -0
  316. package/src/providers/provider-probe.ts +63 -0
  317. package/src/providers/registry.ts +109 -29
  318. package/src/server/index.ts +9 -0
  319. package/src/server/middleware/auth.ts +5 -1
  320. package/src/server/routes/codex-accounts.ts +14 -0
  321. package/src/server/routes/cross-origin-guard.ts +20 -0
  322. package/src/server/routes/git.ts +40 -4
  323. package/src/server/routes/lsp.ts +97 -4
  324. package/src/server/routes/resources.ts +72 -9
  325. package/src/server/routes/settings.ts +19 -1
  326. package/src/server/routes/speech.ts +66 -0
  327. package/src/server/routes/system-services.ts +76 -0
  328. package/src/server/routes/tunnel.ts +33 -1
  329. package/src/server/ws/chat.ts +74 -3
  330. package/src/services/codex-account-login.ts +26 -2
  331. package/src/services/codex-reset-credit.service.ts +83 -0
  332. package/src/services/compaction-savings.ts +127 -0
  333. package/src/services/db.service.ts +123 -8
  334. package/src/services/edge-forwarder.ts +191 -191
  335. package/src/services/fs-ops/fs-ops-trash.service.ts +22 -9
  336. package/src/services/git-refs/for-each-ref.ts +118 -0
  337. package/src/services/git.service.ts +25 -2
  338. package/src/services/host-info/spawn-runner.ts +48 -4
  339. package/src/services/jsonl-transcript-parser.ts +7 -42
  340. package/src/services/lsp/lsp-install.ts +289 -0
  341. package/src/services/lsp/lsp-manager.ts +160 -29
  342. package/src/services/lsp/server-registry.ts +120 -4
  343. package/src/services/named-tunnel/named-tunnel-config.ts +8 -2
  344. package/src/services/named-tunnel/named-tunnel-setup.service.ts +4 -0
  345. package/src/services/read-lines.ts +54 -0
  346. package/src/services/speech-to-text/whisper-catalog.ts +142 -0
  347. package/src/services/speech-to-text/whisper-download.ts +113 -0
  348. package/src/services/speech-to-text/whisper-hallucinations.ts +51 -0
  349. package/src/services/speech-to-text/whisper-install.service.ts +247 -0
  350. package/src/services/speech-to-text/whisper-paths.ts +62 -0
  351. package/src/services/speech-to-text/whisper-transcribe.service.ts +117 -0
  352. package/src/services/supervisor.ts +94 -11
  353. package/src/services/system-metrics/cpu-details-linux.ts +252 -0
  354. package/src/services/system-metrics/cpu-memory-collector.ts +140 -18
  355. package/src/services/system-metrics/device-collector-linux.ts +31 -0
  356. package/src/services/system-metrics/device-collector-types.ts +40 -0
  357. package/src/services/system-metrics/disk-devices-linux.ts +156 -0
  358. package/src/services/system-metrics/disk-inventory-linux.ts +150 -0
  359. package/src/services/system-metrics/fans-linux.ts +51 -0
  360. package/src/services/system-metrics/gpu-api-versions.ts +120 -0
  361. package/src/services/system-metrics/gpu-devices-linux.ts +370 -0
  362. package/src/services/system-metrics/gpu-fdinfo-linux.ts +253 -0
  363. package/src/services/system-metrics/hardware-inventory.ts +50 -0
  364. package/src/services/system-metrics/linux-fs.ts +43 -0
  365. package/src/services/system-metrics/memory-darwin.ts +91 -0
  366. package/src/services/system-metrics/memory-linux.ts +156 -0
  367. package/src/services/system-metrics/net-devices-linux.ts +114 -0
  368. package/src/services/system-metrics/net-inventory-linux.ts +100 -0
  369. package/src/services/system-metrics/partitions-linux.ts +158 -0
  370. package/src/services/system-metrics/process-collector-linux.ts +58 -6
  371. package/src/services/system-metrics/process-collector-types.ts +8 -1
  372. package/src/services/system-metrics/process-details-darwin.ts +166 -0
  373. package/src/services/system-metrics/process-details-linux.ts +150 -0
  374. package/src/services/system-metrics/process-grouping.ts +2 -1
  375. package/src/services/system-metrics/process-rows-builder.ts +2 -0
  376. package/src/services/system-metrics/process-swap-linux.ts +37 -0
  377. package/src/services/system-metrics/signal-executor.ts +84 -0
  378. package/src/services/system-metrics/signal-request-handler.ts +92 -0
  379. package/src/services/system-metrics/system-metrics-platform.ts +30 -4
  380. package/src/services/system-metrics/system-metrics-tick.ts +73 -4
  381. package/src/services/system-metrics/system-metrics.service.ts +87 -2
  382. package/src/services/system-metrics/udev-db.ts +40 -0
  383. package/src/services/system-services/app-cgroup-linux.ts +115 -0
  384. package/src/services/system-services/app-icon-service.ts +31 -0
  385. package/src/services/system-services/app-icons-linux.ts +124 -0
  386. package/src/services/system-services/apps-linux.ts +174 -0
  387. package/src/services/system-services/desktop-entry.ts +103 -0
  388. package/src/services/system-services/service-guard.ts +124 -0
  389. package/src/services/system-services/systemd-collector.ts +203 -0
  390. package/src/services/system-services/systemd-parse.ts +162 -0
  391. package/src/services/windows-process-tree.ts +351 -351
  392. package/src/shared/prompt-cache-idle.ts +197 -0
  393. package/src/shared/turn-usage.ts +85 -1
  394. package/src/shared/usage-extra.ts +19 -0
  395. package/src/types/chat.ts +29 -0
  396. package/src/types/config.ts +14 -0
  397. package/src/types/git.ts +41 -0
  398. package/src/types/system-hardware.ts +137 -0
  399. package/src/types/system-metrics.ts +231 -2
  400. package/src/types/system-services.ts +73 -0
  401. package/src/web/components/branch-review/branch-review-tab.tsx +20 -20
  402. package/src/web/components/branch-review/branch-review-tree-row.tsx +1 -13
  403. package/src/web/components/chat/chat-tab.tsx +3 -0
  404. package/src/web/components/chat/codex-usage-panel.tsx +4 -0
  405. package/src/web/components/chat/compaction-divider.tsx +48 -0
  406. package/src/web/components/chat/idle-cache-notice.tsx +67 -0
  407. package/src/web/components/chat/message-input.tsx +48 -13
  408. package/src/web/components/chat/message-list.tsx +15 -0
  409. package/src/web/components/chat/prompt-cache-chip.tsx +74 -0
  410. package/src/web/components/editor/code-editor.tsx +1 -0
  411. package/src/web/components/editor/editor-language-service.tsx +11 -3
  412. package/src/web/components/editor/lsp-status.tsx +115 -13
  413. package/src/web/components/git/branch-picker.tsx +419 -0
  414. package/src/web/components/git/branch-select.tsx +34 -0
  415. package/src/web/components/git/create-worktree-dialog.tsx +17 -16
  416. package/src/web/components/git/git-repo-picker.tsx +28 -40
  417. package/src/web/components/layout/status-bar.tsx +42 -19
  418. package/src/web/components/settings/accounts/account-card.tsx +10 -2
  419. package/src/web/components/settings/accounts/account-usage-extras.tsx +3 -2
  420. package/src/web/components/settings/accounts/codex-accounts-section.tsx +3 -1
  421. package/src/web/components/settings/accounts/codex-reset-credit-button.tsx +120 -0
  422. package/src/web/components/settings/ai-settings-section.tsx +67 -3
  423. package/src/web/components/settings/appearance-settings-section.tsx +2 -28
  424. package/src/web/components/settings/language-servers-section.tsx +362 -0
  425. package/src/web/components/settings/settings-categories.ts +8 -3
  426. package/src/web/components/settings/settings-section-content.tsx +2 -0
  427. package/src/web/components/settings/voice-settings-section.tsx +283 -0
  428. package/src/web/components/system/apps/app-row.tsx +110 -0
  429. package/src/web/components/system/apps/app-rows.ts +140 -0
  430. package/src/web/components/system/apps/apps-panel.tsx +129 -0
  431. package/src/web/components/system/metric-chart-canvas.tsx +79 -3
  432. package/src/web/components/system/overview-cards/card-shell.tsx +54 -0
  433. package/src/web/components/system/overview-cards/cpu-card.tsx +11 -6
  434. package/src/web/components/system/overview-cards/disk-card.tsx +11 -6
  435. package/src/web/components/system/overview-cards/gpu-card.tsx +16 -6
  436. package/src/web/components/system/overview-cards/mem-card.tsx +11 -6
  437. package/src/web/components/system/overview-cards/net-card.tsx +11 -6
  438. package/src/web/components/system/overview-device-target.ts +69 -0
  439. package/src/web/components/system/overview-panel.tsx +15 -1
  440. package/src/web/components/system/performance/cpu-core-grid.tsx +74 -0
  441. package/src/web/components/system/performance/cpu-detail.tsx +220 -0
  442. package/src/web/components/system/performance/detail-parts.tsx +149 -0
  443. package/src/web/components/system/performance/device-list.ts +139 -0
  444. package/src/web/components/system/performance/disk-detail.tsx +64 -0
  445. package/src/web/components/system/performance/fans-detail.tsx +35 -0
  446. package/src/web/components/system/performance/gpu-detail.tsx +116 -0
  447. package/src/web/components/system/performance/memory-detail.tsx +109 -0
  448. package/src/web/components/system/performance/nic-detail.tsx +55 -0
  449. package/src/web/components/system/performance/partition-list.tsx +79 -0
  450. package/src/web/components/system/performance/performance-panel.tsx +206 -0
  451. package/src/web/components/system/performance/use-hardware-inventory.ts +48 -0
  452. package/src/web/components/system/process-columns-grid.ts +5 -3
  453. package/src/web/components/system/process-details-dialog.tsx +116 -0
  454. package/src/web/components/system/process-group-row.tsx +6 -1
  455. package/src/web/components/system/process-row-format.ts +6 -0
  456. package/src/web/components/system/process-row-menu.tsx +72 -0
  457. package/src/web/components/system/process-row.tsx +7 -1
  458. package/src/web/components/system/process-table-model.ts +1 -1
  459. package/src/web/components/system/process-table-sort.ts +8 -4
  460. package/src/web/components/system/process-table-toolbar.tsx +10 -2
  461. package/src/web/components/system/process-table-totals.ts +3 -0
  462. package/src/web/components/system/process-table.tsx +25 -2
  463. package/src/web/components/system/services/service-action-confirm.tsx +100 -0
  464. package/src/web/components/system/services/service-columns.ts +103 -0
  465. package/src/web/components/system/services/service-details-sheet.tsx +97 -0
  466. package/src/web/components/system/services/service-resources.ts +105 -0
  467. package/src/web/components/system/services/service-row.tsx +146 -0
  468. package/src/web/components/system/services/service-rows.ts +92 -0
  469. package/src/web/components/system/services/service-sort.ts +90 -0
  470. package/src/web/components/system/services/services-header.tsx +51 -0
  471. package/src/web/components/system/services/services-panel.tsx +207 -0
  472. package/src/web/components/system/services/use-services.ts +92 -0
  473. package/src/web/components/system/sortable-header.tsx +13 -8
  474. package/src/web/components/system/sysmon-preferences.tsx +85 -0
  475. package/src/web/components/system/system-monitor-body.tsx +101 -43
  476. package/src/web/components/system/system-monitor-window-content.tsx +2 -3
  477. package/src/web/components/system/use-process-signal.ts +87 -0
  478. package/src/web/components/tunnels/public-tunnel-switch.tsx +82 -0
  479. package/src/web/components/tunnels/tunnel-manager-tab.tsx +4 -0
  480. package/src/web/components/ui/dialog.tsx +14 -1
  481. package/src/web/components/ui/search-select.tsx +279 -0
  482. package/src/web/components/ui/start-ellipsis.tsx +18 -0
  483. package/src/web/hooks/use-chat.ts +28 -0
  484. package/src/web/hooks/use-global-keybindings.ts +7 -5
  485. package/src/web/hooks/use-lsp.ts +23 -2
  486. package/src/web/hooks/use-minute-clock.ts +20 -0
  487. package/src/web/hooks/use-whisper-voice-input.ts +113 -0
  488. package/src/web/lib/api-tunnels.ts +19 -0
  489. package/src/web/lib/branch-select-items.ts +29 -0
  490. package/src/web/lib/cpu-graph-mode.ts +90 -0
  491. package/src/web/lib/format-bytes.ts +14 -0
  492. package/src/web/lib/git-ref-picker.ts +120 -0
  493. package/src/web/lib/lsp/lsp-client.ts +32 -0
  494. package/src/web/lib/search-select-rows.ts +55 -0
  495. package/src/web/lib/temperature.ts +27 -0
  496. package/src/web/lib/voice-wav.ts +69 -0
  497. package/src/web/stores/git-status-store.ts +31 -17
  498. package/src/web/stores/keybindings-store.ts +14 -1
  499. package/src/web/stores/settings-store.ts +65 -0
  500. package/src/web/styles/globals.css +11 -0
  501. package/dist/web/assets/accounts-settings-section-CgG5P3Jm.js +0 -1
  502. package/dist/web/assets/accounts-settings-section-CgG5P3Jm.js.br +0 -0
  503. package/dist/web/assets/accounts-settings-section-CgG5P3Jm.js.gz +0 -0
  504. package/dist/web/assets/ai-resource-editor-DKcsVDle.js.br +0 -0
  505. package/dist/web/assets/ai-resource-editor-DKcsVDle.js.gz +0 -0
  506. package/dist/web/assets/ai-settings-section-D7zJ-hCO.js +0 -1
  507. package/dist/web/assets/ai-settings-section-D7zJ-hCO.js.br +0 -0
  508. package/dist/web/assets/ai-settings-section-D7zJ-hCO.js.gz +0 -0
  509. package/dist/web/assets/ai-settings-section-OPqC2bYG.js +0 -1
  510. package/dist/web/assets/api-client-BgedDTvo.js +0 -1
  511. package/dist/web/assets/api-client-c8YOpTlT.js.br +0 -0
  512. package/dist/web/assets/api-client-c8YOpTlT.js.gz +0 -0
  513. package/dist/web/assets/api-settings-BmvNoCbn.js.br +0 -0
  514. package/dist/web/assets/api-settings-BmvNoCbn.js.gz +0 -0
  515. package/dist/web/assets/api-settings-Bti1-Zn3.js +0 -1
  516. package/dist/web/assets/appearance-settings-section-DL466x83.js +0 -1
  517. package/dist/web/assets/appearance-settings-section-DL466x83.js.br +0 -0
  518. package/dist/web/assets/appearance-settings-section-DL466x83.js.gz +0 -0
  519. package/dist/web/assets/audio-preview-vaG2cB-k.js.br +0 -0
  520. package/dist/web/assets/audio-preview-vaG2cB-k.js.gz +0 -0
  521. package/dist/web/assets/branch-review-tab-Dag86n_R.js +0 -1
  522. package/dist/web/assets/branch-review-tab-Dag86n_R.js.br +0 -0
  523. package/dist/web/assets/branch-review-tab-Dag86n_R.js.gz +0 -0
  524. package/dist/web/assets/button-Ci9EUgqd.js.br +0 -0
  525. package/dist/web/assets/button-Ci9EUgqd.js.gz +0 -0
  526. package/dist/web/assets/chat-preparation-cache-BSIQGiWx.js.br +0 -0
  527. package/dist/web/assets/chat-preparation-cache-BSIQGiWx.js.gz +0 -0
  528. package/dist/web/assets/chat-tab-CcYZLXls.js +0 -15
  529. package/dist/web/assets/chat-tab-CcYZLXls.js.br +0 -0
  530. package/dist/web/assets/chat-tab-CcYZLXls.js.gz +0 -0
  531. package/dist/web/assets/chat-tab-QFDhzzBZ.js +0 -1
  532. package/dist/web/assets/chat-tab-QFDhzzBZ.js.br +0 -0
  533. package/dist/web/assets/chat-tab-QFDhzzBZ.js.gz +0 -0
  534. package/dist/web/assets/code-editor-K-IN8VwJ.js +0 -7
  535. package/dist/web/assets/code-editor-K-IN8VwJ.js.br +0 -0
  536. package/dist/web/assets/code-editor-K-IN8VwJ.js.gz +0 -0
  537. package/dist/web/assets/codex-sign-in-again-dialog-C8JvblLG.js +0 -1
  538. package/dist/web/assets/codex-sign-in-again-dialog-C8JvblLG.js.br +0 -0
  539. package/dist/web/assets/codex-sign-in-again-dialog-C8JvblLG.js.gz +0 -0
  540. package/dist/web/assets/conflict-editor-qMGJH0Bx.js.br +0 -0
  541. package/dist/web/assets/conflict-editor-qMGJH0Bx.js.gz +0 -0
  542. package/dist/web/assets/context-menu-CjYTq8DI.js +0 -1
  543. package/dist/web/assets/context-menu-CjYTq8DI.js.br +0 -0
  544. package/dist/web/assets/context-menu-CjYTq8DI.js.gz +0 -0
  545. package/dist/web/assets/csv-preview-D2I742dl.js.br +0 -0
  546. package/dist/web/assets/csv-preview-D2I742dl.js.gz +0 -0
  547. package/dist/web/assets/data-grid-overlay-editor-CQRVKr7y.js.br +0 -0
  548. package/dist/web/assets/data-grid-overlay-editor-CQRVKr7y.js.gz +0 -0
  549. package/dist/web/assets/database-viewer-Bz4LjgIa.js.br +0 -0
  550. package/dist/web/assets/database-viewer-Bz4LjgIa.js.gz +0 -0
  551. package/dist/web/assets/design-export-client-ChMcMoqW.js.br +0 -0
  552. package/dist/web/assets/design-export-client-ChMcMoqW.js.gz +0 -0
  553. package/dist/web/assets/design-responsive-dialog-DNBhJJLf.js.br +0 -0
  554. package/dist/web/assets/design-responsive-dialog-DNBhJJLf.js.gz +0 -0
  555. package/dist/web/assets/design-tab-C987MtMR.js +0 -33
  556. package/dist/web/assets/design-tab-C987MtMR.js.br +0 -0
  557. package/dist/web/assets/design-tab-C987MtMR.js.gz +0 -0
  558. package/dist/web/assets/designs-sidebar-panel-CapP1yXq.js.br +0 -0
  559. package/dist/web/assets/designs-sidebar-panel-CapP1yXq.js.gz +0 -0
  560. package/dist/web/assets/dialog-B8clVkyi.js +0 -1
  561. package/dist/web/assets/dialog-B8clVkyi.js.br +0 -0
  562. package/dist/web/assets/dialog-B8clVkyi.js.gz +0 -0
  563. package/dist/web/assets/diff-viewer-CdXi7cZN.js.br +0 -0
  564. package/dist/web/assets/diff-viewer-CdXi7cZN.js.gz +0 -0
  565. package/dist/web/assets/docx-preview-C9XdKEj1.js.br +0 -0
  566. package/dist/web/assets/docx-preview-C9XdKEj1.js.gz +0 -0
  567. package/dist/web/assets/editor-language-service-Zle_PZV8.js +0 -1
  568. package/dist/web/assets/editor-language-service-Zle_PZV8.js.br +0 -0
  569. package/dist/web/assets/editor-language-service-Zle_PZV8.js.gz +0 -0
  570. package/dist/web/assets/explorer-body-DHMQR1Rk.js +0 -2
  571. package/dist/web/assets/explorer-body-DHMQR1Rk.js.br +0 -0
  572. package/dist/web/assets/explorer-body-DHMQR1Rk.js.gz +0 -0
  573. package/dist/web/assets/explorer-window-content-Df40nQBk.js +0 -1
  574. package/dist/web/assets/explorer-window-content-Df40nQBk.js.br +0 -0
  575. package/dist/web/assets/explorer-window-content-Df40nQBk.js.gz +0 -0
  576. package/dist/web/assets/extension-manager-section-B2nZzJ2b.js.br +0 -0
  577. package/dist/web/assets/extension-manager-section-B2nZzJ2b.js.gz +0 -0
  578. package/dist/web/assets/extension-webview-BGoDxkdF.js.br +0 -0
  579. package/dist/web/assets/extension-webview-BGoDxkdF.js.gz +0 -0
  580. package/dist/web/assets/file-icons-gx_FBOXY.js.br +0 -0
  581. package/dist/web/assets/file-icons-gx_FBOXY.js.gz +0 -0
  582. package/dist/web/assets/file-store-D9KE0kQC.js.br +0 -0
  583. package/dist/web/assets/file-store-D9KE0kQC.js.gz +0 -0
  584. package/dist/web/assets/files-settings-section-DC3OzzOl.js.br +0 -0
  585. package/dist/web/assets/files-settings-section-DC3OzzOl.js.gz +0 -0
  586. package/dist/web/assets/format-bytes-DmSHAKFe.js +0 -1
  587. package/dist/web/assets/format-file-meta-mQwA6SuY.js.br +0 -0
  588. package/dist/web/assets/format-file-meta-mQwA6SuY.js.gz +0 -0
  589. package/dist/web/assets/fs-api-DL36slbd.js.br +0 -0
  590. package/dist/web/assets/fs-api-DL36slbd.js.gz +0 -0
  591. package/dist/web/assets/general-settings-section-i41W43ER.js.br +0 -0
  592. package/dist/web/assets/general-settings-section-i41W43ER.js.gz +0 -0
  593. package/dist/web/assets/git-log-panel-DHzPIkJg.js.br +0 -0
  594. package/dist/web/assets/git-log-panel-DHzPIkJg.js.gz +0 -0
  595. package/dist/web/assets/git-repo-store-DSypNj19.js.br +0 -0
  596. package/dist/web/assets/git-repo-store-DSypNj19.js.gz +0 -0
  597. package/dist/web/assets/glide-data-grid-Dj4vrDvj.js.br +0 -0
  598. package/dist/web/assets/glide-data-grid-Dj4vrDvj.js.gz +0 -0
  599. package/dist/web/assets/group-chat-tab-DfwZb-fI.js +0 -1
  600. package/dist/web/assets/group-chat-tab-DfwZb-fI.js.br +0 -0
  601. package/dist/web/assets/group-chat-tab-DfwZb-fI.js.gz +0 -0
  602. package/dist/web/assets/index-DMA-So69.css +0 -1
  603. package/dist/web/assets/index-DMA-So69.css.br +0 -0
  604. package/dist/web/assets/index-DMA-So69.css.gz +0 -0
  605. package/dist/web/assets/index-jG9mLs-J.js +0 -52
  606. package/dist/web/assets/index-jG9mLs-J.js.br +0 -0
  607. package/dist/web/assets/index-jG9mLs-J.js.gz +0 -0
  608. package/dist/web/assets/keybindings-store-BlapkC6O.js +0 -1
  609. package/dist/web/assets/keyboard-shortcuts-section-CxdGSNGr.js.br +0 -0
  610. package/dist/web/assets/keyboard-shortcuts-section-CxdGSNGr.js.gz +0 -0
  611. package/dist/web/assets/markdown-renderer-DJ9EVU1B.js +0 -1
  612. package/dist/web/assets/markdown-renderer-ok96IgnS.js.br +0 -0
  613. package/dist/web/assets/markdown-renderer-ok96IgnS.js.gz +0 -0
  614. package/dist/web/assets/mobile-bottom-sheet-CuNi2FRv.js.br +0 -0
  615. package/dist/web/assets/mobile-bottom-sheet-CuNi2FRv.js.gz +0 -0
  616. package/dist/web/assets/mobile-explorer-sheet-Cc03LUKy.js +0 -1
  617. package/dist/web/assets/mobile-explorer-sheet-Cc03LUKy.js.br +0 -0
  618. package/dist/web/assets/mobile-explorer-sheet-Cc03LUKy.js.gz +0 -0
  619. package/dist/web/assets/new-design-dialog-Drkjb_LI.js.br +0 -0
  620. package/dist/web/assets/new-design-dialog-Drkjb_LI.js.gz +0 -0
  621. package/dist/web/assets/notification-store-DCyxho0O.js +0 -1
  622. package/dist/web/assets/notifications-settings-section-C05WYqcE.js.br +0 -0
  623. package/dist/web/assets/notifications-settings-section-C05WYqcE.js.gz +0 -0
  624. package/dist/web/assets/onboarding-entry-CmUqv1kl.js.br +0 -0
  625. package/dist/web/assets/onboarding-entry-CmUqv1kl.js.gz +0 -0
  626. package/dist/web/assets/onboarding-quick-orientation-DIhWv1CN.js.br +0 -0
  627. package/dist/web/assets/onboarding-quick-orientation-DIhWv1CN.js.gz +0 -0
  628. package/dist/web/assets/overview-panel-BZAW_nag.js +0 -1
  629. package/dist/web/assets/overview-panel-BZAW_nag.js.br +0 -0
  630. package/dist/web/assets/overview-panel-BZAW_nag.js.gz +0 -0
  631. package/dist/web/assets/pdf-preview-qdXmMkOR.js.br +0 -0
  632. package/dist/web/assets/pdf-preview-qdXmMkOR.js.gz +0 -0
  633. package/dist/web/assets/postgres-viewer-Xvlun_n5.js.br +0 -0
  634. package/dist/web/assets/postgres-viewer-Xvlun_n5.js.gz +0 -0
  635. package/dist/web/assets/ppmbot-settings-section-C8PFlvaq.js.br +0 -0
  636. package/dist/web/assets/ppmbot-settings-section-C8PFlvaq.js.gz +0 -0
  637. package/dist/web/assets/pptx-export-CG6MRNok.js.br +0 -0
  638. package/dist/web/assets/pptx-export-CG6MRNok.js.gz +0 -0
  639. package/dist/web/assets/problems-panel-CFYO0Ro3.js.br +0 -0
  640. package/dist/web/assets/problems-panel-CFYO0Ro3.js.gz +0 -0
  641. package/dist/web/assets/process-table-BVeRguFg.js +0 -1
  642. package/dist/web/assets/process-table-BVeRguFg.js.br +0 -0
  643. package/dist/web/assets/process-table-BVeRguFg.js.gz +0 -0
  644. package/dist/web/assets/project-store-C5gJXkvb.js.br +0 -0
  645. package/dist/web/assets/project-store-C5gJXkvb.js.gz +0 -0
  646. package/dist/web/assets/proxy-settings-section-BcHIEANE.js.br +0 -0
  647. package/dist/web/assets/proxy-settings-section-BcHIEANE.js.gz +0 -0
  648. package/dist/web/assets/query-audit-section-UKG_smyt.js.br +0 -0
  649. package/dist/web/assets/query-audit-section-UKG_smyt.js.gz +0 -0
  650. package/dist/web/assets/remote-desktop-clipboard-notice-BGsp0edA.js.br +0 -0
  651. package/dist/web/assets/remote-desktop-clipboard-notice-BGsp0edA.js.gz +0 -0
  652. package/dist/web/assets/remote-desktop-mobile-sheet-DxkmF8qb.js +0 -2
  653. package/dist/web/assets/remote-desktop-mobile-sheet-DxkmF8qb.js.br +0 -0
  654. package/dist/web/assets/remote-desktop-mobile-sheet-DxkmF8qb.js.gz +0 -0
  655. package/dist/web/assets/remote-desktop-mobile-view-DMD0M9Jh.js +0 -1
  656. package/dist/web/assets/remote-desktop-mobile-view-DMD0M9Jh.js.br +0 -0
  657. package/dist/web/assets/remote-desktop-mobile-view-DMD0M9Jh.js.gz +0 -0
  658. package/dist/web/assets/remote-desktop-readiness-gate-CsZCCRJI.js.br +0 -0
  659. package/dist/web/assets/remote-desktop-readiness-gate-CsZCCRJI.js.gz +0 -0
  660. package/dist/web/assets/remote-desktop-window-content-DrHw_vwY.js +0 -1
  661. package/dist/web/assets/remote-desktop-window-content-DrHw_vwY.js.br +0 -0
  662. package/dist/web/assets/remote-desktop-window-content-DrHw_vwY.js.gz +0 -0
  663. package/dist/web/assets/schedules-settings-section-Ci0O2Ng6.js.br +0 -0
  664. package/dist/web/assets/schedules-settings-section-Ci0O2Ng6.js.gz +0 -0
  665. package/dist/web/assets/scroll-area-XonvWYn_.js.br +0 -0
  666. package/dist/web/assets/scroll-area-XonvWYn_.js.gz +0 -0
  667. package/dist/web/assets/settings-body-B6JGOIYb.js +0 -2
  668. package/dist/web/assets/settings-body-B6JGOIYb.js.br +0 -0
  669. package/dist/web/assets/settings-body-B6JGOIYb.js.gz +0 -0
  670. package/dist/web/assets/settings-store-Br5c1efC.js +0 -2
  671. package/dist/web/assets/settings-store-Br5c1efC.js.br +0 -0
  672. package/dist/web/assets/settings-store-Br5c1efC.js.gz +0 -0
  673. package/dist/web/assets/settings-tab-CIQM4fNE.js +0 -1
  674. package/dist/web/assets/settings-window-content-BGNNz-E5.js +0 -1
  675. package/dist/web/assets/sql-query-editor-4iCGE4h2.js.br +0 -3
  676. package/dist/web/assets/sql-query-editor-4iCGE4h2.js.gz +0 -0
  677. package/dist/web/assets/sqlite-viewer-CK6DulYk.js.br +0 -0
  678. package/dist/web/assets/sqlite-viewer-CK6DulYk.js.gz +0 -0
  679. package/dist/web/assets/system-monitor-body-J9JtvAWV.js +0 -2
  680. package/dist/web/assets/system-monitor-body-J9JtvAWV.js.br +0 -0
  681. package/dist/web/assets/system-monitor-body-J9JtvAWV.js.gz +0 -0
  682. package/dist/web/assets/system-monitor-tab-DjBeRE81.js +0 -1
  683. package/dist/web/assets/system-monitor-window-content-BT7-ugFx.js +0 -1
  684. package/dist/web/assets/tab-host-window-content-CWBaWKjA.js.br +0 -0
  685. package/dist/web/assets/tab-host-window-content-CWBaWKjA.js.gz +0 -0
  686. package/dist/web/assets/team-member-sheet-Br6mrxrw.js.br +0 -0
  687. package/dist/web/assets/team-member-sheet-Br6mrxrw.js.gz +0 -0
  688. package/dist/web/assets/team-member-window-content-CwCy7ZWf.js.br +0 -0
  689. package/dist/web/assets/team-member-window-content-CwCy7ZWf.js.gz +0 -0
  690. package/dist/web/assets/terminal-tab-BW14RpCb.js.br +0 -0
  691. package/dist/web/assets/terminal-tab-BW14RpCb.js.gz +0 -0
  692. package/dist/web/assets/tool-cards-CgOBEUnb.js.br +0 -0
  693. package/dist/web/assets/tool-cards-CgOBEUnb.js.gz +0 -0
  694. package/dist/web/assets/use-inline-blame-Bzjfru4n.js +0 -16
  695. package/dist/web/assets/use-inline-blame-Bzjfru4n.js.br +0 -0
  696. package/dist/web/assets/use-inline-blame-Bzjfru4n.js.gz +0 -0
  697. package/dist/web/assets/use-lsp-hGdjL2hV.js +0 -6
  698. package/dist/web/assets/use-lsp-hGdjL2hV.js.br +0 -0
  699. package/dist/web/assets/use-lsp-hGdjL2hV.js.gz +0 -0
  700. package/dist/web/assets/vendor-ui-BHh12_0v.js.br +0 -0
  701. package/dist/web/assets/vendor-ui-BHh12_0v.js.gz +0 -0
  702. package/dist/web/assets/video-preview-P9T-ZVdN.js +0 -1
  703. package/dist/web/assets/video-preview-P9T-ZVdN.js.br +0 -0
  704. package/dist/web/assets/video-preview-P9T-ZVdN.js.gz +0 -0
  705. package/dist/web/assets/ws-auth-kXgsX2Js.js +0 -1
  706. package/packages/vscode-compat/node_modules/.bin/tsc.bunx +0 -0
  707. package/packages/vscode-compat/node_modules/.bin/tsc.exe +0 -0
  708. package/packages/vscode-compat/node_modules/.bin/tsserver.bunx +0 -0
  709. package/packages/vscode-compat/node_modules/.bin/tsserver.exe +0 -0
  710. /package/dist/web/assets/{__vite-browser-external-BpSQWxcq.js → __vite-browser-external-BILfYaAs.js} +0 -0
  711. /package/dist/web/assets/{run-in-terminal-HIdNgYim.js → run-in-terminal-2pSiup8e.js} +0 -0
  712. /package/dist/web/assets/{vendor-xterm-DLDtzLib.js → vendor-xterm-DF1JTfsy.js} +0 -0
  713. /package/dist/web/assets/{vendor-xterm-DLDtzLib.js.br → vendor-xterm-DF1JTfsy.js.br} +0 -0
  714. /package/dist/web/assets/{vendor-xterm-DLDtzLib.js.gz → vendor-xterm-DF1JTfsy.js.gz} +0 -0
@@ -16,14 +16,20 @@
16
16
  */
17
17
  import { stat } from "node:fs/promises";
18
18
  import path from "node:path";
19
+ import { resolveBunPath } from "../autostart-generator.ts";
20
+ import { canInstall, lspInstallDir, rustupServerPath } from "./lsp-install.ts";
19
21
  import { LspSession, type LspSessionState } from "./lsp-session.ts";
20
22
  import {
21
23
  LANGUAGE_SERVERS,
22
24
  ancestorDirs,
23
25
  bundledServerEntry,
24
26
  candidateCommandPaths,
27
+ installedBinaryPath,
28
+ installedServerEntry,
25
29
  lspLanguageForPath,
30
+ serversSharingInstall,
26
31
  type LanguageServerDefinition,
32
+ type LanguageServerInstall,
27
33
  } from "./server-registry.ts";
28
34
 
29
35
  /** How long a session with no subscribers is kept before being shut down. */
@@ -52,10 +58,34 @@ export type LspUnavailableReason = "no-language" | "not-installed" | "failed";
52
58
  export interface LspUnavailable {
53
59
  reason: LspUnavailableReason;
54
60
  /** The server that would have served it, when one is known. */
55
- server?: { id: string; displayName: string; installHint: string };
61
+ server?: {
62
+ id: string;
63
+ displayName: string;
64
+ installHint: string;
65
+ installable: boolean;
66
+ /** What the button would use, so the editor can say what pressing it does. */
67
+ installWith?: "bun" | "go" | "rustup";
68
+ };
56
69
  message: string;
57
70
  }
58
71
 
72
+ /**
73
+ * What the editor needs to name a missing server, and to decide whether to offer to install it.
74
+ *
75
+ * `installable` is the host's answer rather than the editor's guess, and it is not the registry's
76
+ * either: `go install` needs a Go on this machine and `rustup component add` needs a rustup, so
77
+ * the same server is installable on one host and a command to copy on the next.
78
+ */
79
+ function serverSummary(definition: LanguageServerDefinition): NonNullable<LspUnavailable["server"]> {
80
+ return {
81
+ id: definition.id,
82
+ displayName: definition.displayName,
83
+ installHint: definition.installHint,
84
+ installable: canInstall(definition),
85
+ installWith: definition.install?.with,
86
+ };
87
+ }
88
+
59
89
  export function isUnavailable(result: LspHandle | LspUnavailable): result is LspUnavailable {
60
90
  return "reason" in result;
61
91
  }
@@ -68,6 +98,33 @@ interface Entry {
68
98
  lastUsed: number;
69
99
  }
70
100
 
101
+ /**
102
+ * The bun that runs a server's entry script.
103
+ *
104
+ * Not `process.execPath`: that is bun only while PPM runs from source. A compiled PPM is its
105
+ * own executable, so spawning it with a script path reaches PPM's *CLI* — the same trap that
106
+ * made a compiled PPM answer `<ppm> x @openai/codex app-server` with "unknown command". `null`
107
+ * on a host with no bun at all, where such a copy cannot be run and must not be called
108
+ * installed.
109
+ */
110
+ function bunRuntime(): string | null {
111
+ try {
112
+ return resolveBunPath();
113
+ } catch {
114
+ return null;
115
+ }
116
+ }
117
+
118
+ /**
119
+ * Where a server was found, in the order `resolveCommand` looks.
120
+ *
121
+ * It exists for the Remove button: PPM may delete what PPM installed and nothing else.
122
+ * `project` is the repository's copy, `path` is one the user installed themselves, and
123
+ * `bundled` is PPM's own dependency — removing any of those would be PPM tidying up after
124
+ * someone else, and for `bundled` it would break the TypeScript server a fresh install has.
125
+ */
126
+ export type ServerOrigin = "project" | "rustup" | "path" | "ppm" | "bundled";
127
+
71
128
  async function exists(candidate: string): Promise<boolean> {
72
129
  try {
73
130
  await stat(candidate);
@@ -107,6 +164,8 @@ export class LspManager {
107
164
  private readonly servers: LanguageServerDefinition[] = LANGUAGE_SERVERS,
108
165
  private readonly idleGraceMs: number = IDLE_GRACE_MS,
109
166
  private readonly maxSessions: number = MAX_SESSIONS,
167
+ /** Called rather than held, so `PPM_HOME` is read when a server is looked for, not at import. */
168
+ private readonly installDir: () => string = lspInstallDir,
110
169
  ) {}
111
170
 
112
171
  onNotification(listener: (key: string, method: string, params: unknown) => void): () => void {
@@ -136,8 +195,8 @@ export class LspManager {
136
195
 
137
196
  let lastMissing: LanguageServerDefinition | null = null;
138
197
  for (const definition of candidates) {
139
- const command = await this.resolveCommand(definition, dirs);
140
- if (!command) {
198
+ const resolved = await this.resolveCommand(definition, dirs);
199
+ if (!resolved) {
141
200
  lastMissing = definition;
142
201
  continue;
143
202
  }
@@ -146,7 +205,7 @@ export class LspManager {
146
205
 
147
206
  this.claim(key);
148
207
  try {
149
- const session = await this.startOrReuse(key, definition, command, rootPath);
208
+ const session = await this.startOrReuse(key, definition, resolved.command, rootPath);
150
209
  // Subscribe *then* trim, so the session this call is about to hand out is never the
151
210
  // one the cap takes away.
152
211
  if (!this.subscribe(key, subscriber)) {
@@ -161,7 +220,7 @@ export class LspManager {
161
220
  } catch (e) {
162
221
  return {
163
222
  reason: "failed",
164
- server: { id: definition.id, displayName: definition.displayName, installHint: definition.installHint },
223
+ server: serverSummary(definition),
165
224
  message: e instanceof Error ? e.message : String(e),
166
225
  };
167
226
  } finally {
@@ -172,7 +231,7 @@ export class LspManager {
172
231
  const missing = lastMissing ?? candidates[0]!;
173
232
  return {
174
233
  reason: "not-installed",
175
- server: { id: missing.id, displayName: missing.displayName, installHint: missing.installHint },
234
+ server: serverSummary(missing),
176
235
  message: `${missing.displayName} is not installed.`,
177
236
  };
178
237
  }
@@ -322,25 +381,51 @@ export class LspManager {
322
381
  *
323
382
  * The project's own copy first, because a repository pinned to TypeScript 4 has to be
324
383
  * analysed by its own server — the same reason VS Code offers "Use Workspace Version".
325
- * Then `PATH`, which is whatever the user deliberately installed. Then the copy PPM ships,
326
- * which is the floor rather than a preference: it is how a fresh install has a working
327
- * TypeScript server with nothing else done, and it must never win over either of the two
328
- * choices someone actually made.
384
+ * Then rustup, which owns its answer completely (below). Then `PATH`, which is whatever the
385
+ * user deliberately installed. Then PPM's own directory: what the Install button put there,
386
+ * and then the copy PPM ships, which is the floor rather than a preference — it is how a
387
+ * fresh install has a working TypeScript server with nothing else done, and it must never win
388
+ * over either of the two choices someone actually made.
329
389
  */
330
- private async resolveCommand(definition: LanguageServerDefinition, dirs: string[]): Promise<string[] | null> {
390
+ private async resolveCommand(
391
+ definition: LanguageServerDefinition,
392
+ dirs: string[],
393
+ ): Promise<{ command: string[]; origin: ServerOrigin } | null> {
331
394
  const candidates = candidateCommandPaths(definition.command, dirs);
332
395
  for (const candidate of candidates.slice(0, -1)) {
333
- if (await exists(candidate)) return [candidate];
396
+ if (await exists(candidate)) return { command: [candidate], origin: "project" };
334
397
  }
398
+ // rust-analyzer is a toolchain component rather than a file PPM owns, so rustup is asked
399
+ // where it is — in the file's own directory, so a repository pinning a toolchain gets that
400
+ // toolchain's server. This has to come *before* PATH, because `~/.cargo/bin/rust-analyzer`
401
+ // is a rustup proxy that exists whether or not the component does: found on PATH it reports
402
+ // an installed server, and spawning it prints "unknown binary" and exits, which is a broken
403
+ // server rather than the missing one the Install button is offered for. Costs nothing for
404
+ // every other server — it answers null on sight of a definition that is not rustup's.
405
+ const fromRustup = await rustupServerPath(definition, dirs[0] ?? process.cwd());
406
+ if (fromRustup) return { command: [fromRustup], origin: "rustup" };
407
+
335
408
  // The last candidate is the bare command, which means PATH.
336
409
  const onPath = Bun.which(definition.command);
337
- if (onPath) return [onPath];
410
+ if (onPath) return { command: [onPath], origin: "path" };
411
+
412
+ // What the Install button built with the host's Go: a real binary in PPM's own directory,
413
+ // spawned as itself.
414
+ const binary = installedBinaryPath(definition, this.installDir());
415
+ if (binary && (await exists(binary))) return { command: [binary], origin: "ppm" };
338
416
 
339
- const bundled = bundledServerEntry(definition);
340
- // Run by the runtime PPM is already using, not through npm's `.bin` shim: that shim is
417
+ // Both of PPM's npm copies are entry scripts rather than npm's `.bin` shims: that shim is
341
418
  // `#!/usr/bin/env node`, and someone who installed PPM with bun may have no node at all —
342
419
  // which fails as exit code 127 at spawn time, long after the server looked installed.
343
- return bundled && (await exists(bundled)) ? [process.execPath, bundled] : null;
420
+ for (const [entry, origin] of [
421
+ [installedServerEntry(definition, this.installDir()), "ppm"],
422
+ [bundledServerEntry(definition), "bundled"],
423
+ ] as const) {
424
+ if (!entry || !(await exists(entry))) continue;
425
+ const runtime = bunRuntime();
426
+ return runtime ? { command: [runtime, entry], origin } : null;
427
+ }
428
+ return null;
344
429
  }
345
430
 
346
431
  /**
@@ -382,24 +467,70 @@ export class LspManager {
382
467
  }
383
468
 
384
469
  /**
385
- * Which of the registered servers this project could actually use.
470
+ * Which of the registered servers could actually be used.
386
471
  *
387
- * Answers the editor's "why is nothing happening" question directly, with the
388
- * install command for anything missing.
472
+ * Answers the editor's "why is nothing happening" question directly, with the install
473
+ * command for anything missing. With no `projectPath` it answers for the *machine* — no
474
+ * project `node_modules/.bin` is consulted — which is what the Settings pane asks, since it
475
+ * is not open on any one project.
389
476
  */
390
- async availability(projectPath: string): Promise<
391
- Array<{ id: string; displayName: string; languages: string[]; installed: boolean; installHint: string }>
477
+ async availability(projectPath?: string): Promise<
478
+ Array<{
479
+ id: string;
480
+ displayName: string;
481
+ languages: string[];
482
+ installed: boolean;
483
+ installHint: string;
484
+ installable: boolean;
485
+ installWith?: LanguageServerInstall["with"];
486
+ origin?: ServerOrigin;
487
+ /** Whether PPM may remove it — that is, whether PPM is what put it there. */
488
+ removable: boolean;
489
+ /** Servers the same removal would also take, because one npm package provides several. */
490
+ alsoRemoves?: string[];
491
+ }>
392
492
  > {
393
- const dirs = [projectPath];
493
+ const dirs = projectPath ? [projectPath] : [];
394
494
  return Promise.all(
395
- this.servers.map(async (definition) => ({
396
- id: definition.id,
397
- displayName: definition.displayName,
398
- languages: definition.languages,
399
- installed: (await this.resolveCommand(definition, dirs)) !== null,
400
- installHint: definition.installHint,
401
- })),
495
+ this.servers.map(async (definition) => {
496
+ const resolved = await this.resolveCommand(definition, dirs);
497
+ const origin = resolved?.origin;
498
+ const removable = origin === "ppm" || origin === "rustup";
499
+ const shared = removable ? serversSharingInstall(definition).map((s) => s.displayName) : [];
500
+ return {
501
+ id: definition.id,
502
+ displayName: definition.displayName,
503
+ languages: definition.languages,
504
+ installed: resolved !== null,
505
+ installHint: definition.installHint,
506
+ installable: canInstall(definition),
507
+ installWith: definition.install?.with,
508
+ origin,
509
+ removable,
510
+ ...(shared.length > 0 ? { alsoRemoves: shared } : {}),
511
+ };
512
+ }),
513
+ );
514
+ }
515
+
516
+ /**
517
+ * Stop this server's idle sessions, for an uninstall that is about to delete it.
518
+ *
519
+ * Only the ones nobody is holding. A session with a subscriber is an editor open on it, and
520
+ * taking that away answers every later request with "the language server is no longer
521
+ * running" until the tab is closed and reopened — the same reason `enforceSessionCap` leaves
522
+ * held sessions alone. One that keeps running is running on files it already opened, which
523
+ * is harmless everywhere except Windows, where it is also what refuses the unlink.
524
+ */
525
+ async stopIdle(serverId: string): Promise<void> {
526
+ const doomed = [...this.entries.entries()].filter(
527
+ ([, entry]) => entry.session.definition.id === serverId && entry.subscribers.size === 0,
402
528
  );
529
+ for (const [key, entry] of doomed) {
530
+ if (entry.idleTimer) clearTimeout(entry.idleTimer);
531
+ this.entries.delete(key);
532
+ }
533
+ await Promise.all(doomed.map(([, entry]) => entry.session.dispose()));
403
534
  }
404
535
 
405
536
  /**
@@ -32,6 +32,14 @@ export interface LanguageServerDefinition {
32
32
  rootMarkers: string[];
33
33
  /** Shown verbatim when the command cannot be found. */
34
34
  installHint: string;
35
+ /**
36
+ * How the Install button installs this server, when PPM can install it at all.
37
+ *
38
+ * Unset for a server that needs a system package manager — `clangd`, `lua-language-server`
39
+ * and `solargraph` mean pacman, apt, brew or a gem, i.e. a password and a choice PPM has no
40
+ * business making. Those keep a command to copy and no button.
41
+ */
42
+ install?: LanguageServerInstall;
35
43
  /**
36
44
  * The npm package PPM depends on for this server, when it ships one.
37
45
  *
@@ -42,6 +50,25 @@ export interface LanguageServerDefinition {
42
50
  initializationOptions?: Record<string, unknown>;
43
51
  }
44
52
 
53
+ /**
54
+ * What the Install button runs.
55
+ *
56
+ * `bun` and `go` both put the server inside PPM's own directory, so nothing the user installed
57
+ * is touched and `rm -rf` is the uninstall. `rustup` is the exception and has to be: a
58
+ * rust-analyzer belongs to a toolchain, and a private copy would be the wrong one as soon as a
59
+ * project pins a different toolchain.
60
+ *
61
+ * PPM never installs the *toolchain*. `go` and `rustup` are offered only where the host
62
+ * already has them — see `canInstall` in `lsp-install.ts`.
63
+ */
64
+ export type LanguageServerInstall =
65
+ /** `bun add <packages>`; the first package provides `command`, the rest are what it needs. */
66
+ | { with: "bun"; packages: string[] }
67
+ /** `go install <module>` with `GOBIN` pointed at PPM's own bin directory. */
68
+ | { with: "go"; module: string }
69
+ /** `rustup component add <component>`, in whichever toolchain the project selects. */
70
+ | { with: "rustup"; component: string };
71
+
45
72
  /**
46
73
  * File extension to LSP language id.
47
74
  *
@@ -110,6 +137,7 @@ export const LANGUAGE_SERVERS: LanguageServerDefinition[] = [
110
137
  // start against it with "provides no tsserver" — which reads like a broken
111
138
  // install rather than the wrong major version.
112
139
  installHint: "bun add -g typescript-language-server typescript@5",
140
+ install: { with: "bun", packages: ["typescript-language-server", "typescript@5"] },
113
141
  // Shipped with PPM, so this one works on a fresh install with nothing else done. The
114
142
  // project's own copy still wins where there is one — a repository pinned to TypeScript 4
115
143
  // has to be analysed by its own server, not by whatever PPM happens to carry.
@@ -153,6 +181,7 @@ export const LANGUAGE_SERVERS: LanguageServerDefinition[] = [
153
181
  args: ["--stdio"],
154
182
  rootMarkers: ["pyproject.toml", "setup.py", "setup.cfg", "requirements.txt", "Pipfile"],
155
183
  installHint: "bun add -g pyright",
184
+ install: { with: "bun", packages: ["pyright"] },
156
185
  },
157
186
  {
158
187
  id: "gopls",
@@ -162,6 +191,9 @@ export const LANGUAGE_SERVERS: LanguageServerDefinition[] = [
162
191
  args: [],
163
192
  rootMarkers: ["go.work", "go.mod"],
164
193
  installHint: "go install golang.org/x/tools/gopls@latest",
194
+ // Built by the host's own Go, into PPM's directory: `GOBIN` is what decides where the
195
+ // binary lands, so `~/go/bin` is left exactly as the user arranged it. 10.6 s here.
196
+ install: { with: "go", module: "golang.org/x/tools/gopls@latest" },
165
197
  },
166
198
  {
167
199
  id: "rust-analyzer",
@@ -171,6 +203,11 @@ export const LANGUAGE_SERVERS: LanguageServerDefinition[] = [
171
203
  args: [],
172
204
  rootMarkers: ["Cargo.toml"],
173
205
  installHint: "rustup component add rust-analyzer",
206
+ // The one server PPM does not keep in its own directory: rust-analyzer belongs to a
207
+ // *toolchain*, and a copy of its own would be the wrong one the moment a project pins a
208
+ // different one. `rustup which` is then both the lookup and the installed-check — it exits
209
+ // non-zero with "unknown binary" when the component is absent, in 3 ms.
210
+ install: { with: "rustup", component: "rust-analyzer" },
174
211
  },
175
212
  {
176
213
  id: "clangd",
@@ -189,6 +226,7 @@ export const LANGUAGE_SERVERS: LanguageServerDefinition[] = [
189
226
  args: ["--stdio"],
190
227
  rootMarkers: ["package.json"],
191
228
  installHint: "bun add -g vscode-langservers-extracted",
229
+ install: { with: "bun", packages: ["vscode-langservers-extracted"] },
192
230
  },
193
231
  {
194
232
  id: "html",
@@ -198,6 +236,7 @@ export const LANGUAGE_SERVERS: LanguageServerDefinition[] = [
198
236
  args: ["--stdio"],
199
237
  rootMarkers: ["package.json"],
200
238
  installHint: "bun add -g vscode-langservers-extracted",
239
+ install: { with: "bun", packages: ["vscode-langservers-extracted"] },
201
240
  },
202
241
  {
203
242
  id: "css",
@@ -207,6 +246,7 @@ export const LANGUAGE_SERVERS: LanguageServerDefinition[] = [
207
246
  args: ["--stdio"],
208
247
  rootMarkers: ["package.json"],
209
248
  installHint: "bun add -g vscode-langservers-extracted",
249
+ install: { with: "bun", packages: ["vscode-langservers-extracted"] },
210
250
  },
211
251
  {
212
252
  id: "yaml",
@@ -216,6 +256,7 @@ export const LANGUAGE_SERVERS: LanguageServerDefinition[] = [
216
256
  args: ["--stdio"],
217
257
  rootMarkers: [],
218
258
  installHint: "bun add -g yaml-language-server",
259
+ install: { with: "bun", packages: ["yaml-language-server"] },
219
260
  },
220
261
  {
221
262
  id: "bash",
@@ -225,6 +266,7 @@ export const LANGUAGE_SERVERS: LanguageServerDefinition[] = [
225
266
  args: ["start"],
226
267
  rootMarkers: [],
227
268
  installHint: "bun add -g bash-language-server",
269
+ install: { with: "bun", packages: ["bash-language-server"] },
228
270
  },
229
271
  {
230
272
  id: "intelephense",
@@ -234,6 +276,7 @@ export const LANGUAGE_SERVERS: LanguageServerDefinition[] = [
234
276
  args: ["--stdio"],
235
277
  rootMarkers: ["composer.json"],
236
278
  installHint: "bun add -g intelephense",
279
+ install: { with: "bun", packages: ["intelephense"] },
237
280
  },
238
281
  {
239
282
  id: "solargraph",
@@ -261,6 +304,7 @@ export const LANGUAGE_SERVERS: LanguageServerDefinition[] = [
261
304
  args: ["--stdio"],
262
305
  rootMarkers: ["package.json"],
263
306
  installHint: "bun add -g @vue/language-server",
307
+ install: { with: "bun", packages: ["@vue/language-server"] },
264
308
  },
265
309
  {
266
310
  id: "svelte",
@@ -270,6 +314,7 @@ export const LANGUAGE_SERVERS: LanguageServerDefinition[] = [
270
314
  args: ["--stdio"],
271
315
  rootMarkers: ["package.json"],
272
316
  installHint: "bun add -g svelte-language-server",
317
+ install: { with: "bun", packages: ["svelte-language-server"] },
273
318
  },
274
319
  ];
275
320
 
@@ -282,6 +327,26 @@ export function serverById(id: string): LanguageServerDefinition | undefined {
282
327
  return LANGUAGE_SERVERS.find((s) => s.id === id);
283
328
  }
284
329
 
330
+ /**
331
+ * The other servers that an uninstall of this one would also take away.
332
+ *
333
+ * One npm package can provide several servers — `vscode-langservers-extracted` is JSON, HTML
334
+ * and CSS at once — so `bun remove` of it removes all three whichever row the button was on.
335
+ * That is not a thing to discover afterwards, so the Settings pane names them before asking.
336
+ * Nothing shares a `go` module or a rustup component, so those answer with nothing.
337
+ */
338
+ export function serversSharingInstall(definition: LanguageServerDefinition): LanguageServerDefinition[] {
339
+ const plan = definition.install;
340
+ if (plan?.with !== "bun") return [];
341
+ const pkg = packageName(plan.packages[0] ?? "");
342
+ return LANGUAGE_SERVERS.filter(
343
+ (s) =>
344
+ s.id !== definition.id &&
345
+ s.install?.with === "bun" &&
346
+ packageName(s.install.packages[0] ?? "") === pkg,
347
+ );
348
+ }
349
+
285
350
  /**
286
351
  * Directories to search, nearest first, from the file's own directory up to and
287
352
  * including the project root.
@@ -386,16 +451,67 @@ export function bundledServerEntry(
386
451
  ): string | null {
387
452
  const pkg = definition.bundledPackage;
388
453
  if (!pkg) return null;
389
- let manifestPath: string;
454
+ try {
455
+ return binEntry(resolve(`${pkg}/package.json`), definition.command);
456
+ } catch {
457
+ return null;
458
+ }
459
+ }
460
+
461
+ /**
462
+ * The entry script of an npm server the Install button put in PPM's own directory.
463
+ *
464
+ * Built as a path *under* `installDir` rather than resolved through `require`: Node resolution
465
+ * climbs out of the directory it starts in, so a stray `~/node_modules` would answer for a
466
+ * package PPM never installed — and whatever answers here is executed.
467
+ */
468
+ export function installedServerEntry(definition: LanguageServerDefinition, installDir: string): string | null {
469
+ if (definition.install?.with !== "bun") return null;
470
+ const spec = definition.install.packages[0];
471
+ if (!spec) return null;
472
+ const pkgDir = path.join(installDir, "node_modules", ...packageName(spec).split("/"));
473
+ return binEntry(path.join(pkgDir, "package.json"), definition.command);
474
+ }
475
+
476
+ /**
477
+ * Where a compiled server the Install button built would be — PPM's own `bin` directory.
478
+ *
479
+ * That is `GOBIN` for the install, so the binary is PPM's to find and to delete, and the
480
+ * user's `~/go/bin` is left as they arranged it. A plain path: whether it exists is the
481
+ * caller's `exists()`, the same as for every other candidate.
482
+ */
483
+ export function installedBinaryPath(
484
+ definition: LanguageServerDefinition,
485
+ installDir: string,
486
+ platform: NodeJS.Platform = process.platform,
487
+ ): string | null {
488
+ if (definition.install?.with !== "go") return null;
489
+ return path.join(installDir, "bin", platform === "win32" ? `${definition.command}.exe` : definition.command);
490
+ }
491
+
492
+ /** `typescript@5` → `typescript`, keeping a scoped package's own leading `@`. */
493
+ export function packageName(spec: string): string {
494
+ const at = spec.indexOf("@", 1);
495
+ return at === -1 ? spec : spec.slice(0, at);
496
+ }
497
+
498
+ /**
499
+ * `bin[command]` from a package manifest, as an absolute path.
500
+ *
501
+ * Both callers want the package's **entry script** and not npm's `.bin` shim: that shim starts
502
+ * `#!/usr/bin/env node`, and someone who installed PPM with bun may have no `node` on the
503
+ * machine at all — measured as exit **127** with `env: 'node': No such file or directory`,
504
+ * after the server had already been reported as installed. The manager runs the entry with bun.
505
+ */
506
+ function binEntry(manifestPath: string, command: string): string | null {
390
507
  let manifest: { bin?: string | Record<string, string> };
391
508
  try {
392
- manifestPath = resolve(`${pkg}/package.json`);
393
509
  manifest = JSON.parse(readFileSync(manifestPath, "utf8")) as typeof manifest;
394
510
  } catch {
395
- return null;
511
+ return null; // not installed, or a manifest we cannot read
396
512
  }
397
513
  // `bin` is either a bare string — the package's own name — or a map of command to path.
398
- const relative = typeof manifest.bin === "string" ? manifest.bin : manifest.bin?.[definition.command];
514
+ const relative = typeof manifest.bin === "string" ? manifest.bin : manifest.bin?.[command];
399
515
  if (!relative) return null;
400
516
  return path.resolve(path.dirname(manifestPath), relative);
401
517
  }
@@ -9,6 +9,8 @@
9
9
  export type TunnelMode = "quick" | "named";
10
10
 
11
11
  export interface ResolvedTunnelConfig {
12
+ /** Master switch — `false` means spawn no tunnel at all, whatever `mode` says. */
13
+ enabled: boolean;
12
14
  mode: TunnelMode;
13
15
  hostname: string | null;
14
16
  tunnelName: string | null;
@@ -18,7 +20,7 @@ export interface ResolvedTunnelConfig {
18
20
  dismissed: boolean;
19
21
  }
20
22
 
21
- const QUICK: Omit<ResolvedTunnelConfig, "dismissed"> = {
23
+ const QUICK: Omit<ResolvedTunnelConfig, "dismissed" | "enabled"> = {
22
24
  mode: "quick", hostname: null, tunnelName: null, token: null, zoneID: null, accountID: null,
23
25
  };
24
26
 
@@ -35,6 +37,9 @@ export function resolveTunnelConfig(raw: unknown): ResolvedTunnelConfig {
35
37
  }
36
38
 
37
39
  const dismissed = obj != null && typeof obj.dismissed === "boolean" ? obj.dismissed : false;
40
+ // Absent means a row older than the master switch, back when the tunnel was
41
+ // unconditional — absent is therefore on, never off.
42
+ const enabled = obj != null && typeof obj.enabled === "boolean" ? obj.enabled : true;
38
43
 
39
44
  // Named mode requires BOTH the stored mode flag AND all four identity fields —
40
45
  // checking fields alone would resurrect a tunnel the user explicitly disabled,
@@ -46,10 +51,11 @@ export function resolveTunnelConfig(raw: unknown): ResolvedTunnelConfig {
46
51
  nonEmptyString(obj.accountID);
47
52
 
48
53
  if (!named || obj == null) {
49
- return { ...QUICK, dismissed };
54
+ return { ...QUICK, enabled, dismissed };
50
55
  }
51
56
 
52
57
  return {
58
+ enabled,
53
59
  mode: "named",
54
60
  hostname: obj.namedTunnelHostname as string,
55
61
  tunnelName: nonEmptyString(obj.namedTunnelName) ? obj.namedTunnelName : null,
@@ -159,6 +159,10 @@ async function runSetupInner(hostname: string): Promise<SetupOutcome> {
159
159
 
160
160
  broadcastGlobalEvent({ type: "tunnel:setup_step", step: "apply", message: "applying configuration" });
161
161
  configService.set("tunnel", {
162
+ // Carry the master switch across rather than defaulting it: configuring a
163
+ // domain is not consent to start sharing, and this write would otherwise
164
+ // silently turn a deliberately-off tunnel back on.
165
+ enabled: configService.get("tunnel").enabled,
162
166
  mode: "named",
163
167
  namedTunnelName: tunnelName,
164
168
  namedTunnelHostname: hostname,
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Streaming line reader for the JSONL transcripts.
3
+ *
4
+ * Its own module because two readers need it — the full message parser and the
5
+ * compaction scan — and having the second import it from the first would make the
6
+ * two files a cycle.
7
+ */
8
+
9
+ /**
10
+ * Yield a file's lines without holding the file in memory.
11
+ *
12
+ * `Bun.file().text()` plus `split("\n")` costs the whole transcript twice over —
13
+ * 277MB resident for a 77MB file, which is what forced a cap low enough to
14
+ * reject real sessions. Peak here is one chunk plus one line.
15
+ *
16
+ * `fromByte` reads a tail window instead of the whole file, for the callers that
17
+ * have to bound what they parse. See `fullParseWindow` in
18
+ * `jsonl-transcript-parser.ts` for why a bound is a window rather than a refusal.
19
+ */
20
+ export async function* readLines(filePath: string, fromByte = 0): AsyncGenerator<string> {
21
+ const decoder = new TextDecoder();
22
+ // Explicit reader rather than `for await` over the stream: the DOM lib's
23
+ // ReadableStream is not typed as async-iterable, and the `finally` is what
24
+ // releases it when a caller breaks early on `beforeUuid`.
25
+ // One byte *before* the offset, so the first line the split produces is
26
+ // always the tail of the record the offset fell inside — the empty string
27
+ // when it fell exactly on a newline. That makes the drop below unconditional
28
+ // instead of a boundary case, and a boundary case here silently costs a whole
29
+ // record rather than a fragment.
30
+ const file = fromByte > 0 ? Bun.file(filePath).slice(fromByte - 1) : Bun.file(filePath);
31
+ const reader = file.stream().getReader();
32
+ // A fragment is not always unparseable — the tail of one record is sometimes
33
+ // a complete smaller document — so it has to go by position rather than be
34
+ // left for `JSON.parse` to reject, or it enters as an invented message.
35
+ let dropPartial = fromByte > 0;
36
+ let buffered = "";
37
+ try {
38
+ while (true) {
39
+ const { done, value } = await reader.read();
40
+ if (done) break;
41
+ buffered += decoder.decode(value, { stream: true });
42
+ const lines = buffered.split("\n");
43
+ buffered = lines.pop() ?? "";
44
+ for (const line of lines) {
45
+ if (dropPartial) { dropPartial = false; continue; }
46
+ yield line;
47
+ }
48
+ }
49
+ } finally {
50
+ reader.releaseLock();
51
+ }
52
+ buffered += decoder.decode();
53
+ if (buffered && !dropPartial) yield buffered;
54
+ }