@hienlh/ppm 0.23.6 → 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 (701) hide show
  1. package/CHANGELOG.md +84 -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 +29 -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-Dn_wB-o5.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-BA3y-qSH.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-BioxkrQF.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-BSoJ0E6p.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-DHh5QsH9.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-lctWoSmG.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-rbkXsZVR.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-uPO0WgCq.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-CT7mDb0L.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-DANPfMRN.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-BJPkLiEw.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-R4PcAntf.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-DHRoyWcG.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-BKej4mUf.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-BHtYqkYZ.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-DS_XrpTG.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-D8AES1BA.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-DTBG4beI.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-CqtmbeRj.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-Djt6cpNL.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-DNJF8TcF.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-BKoPovy2.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-BjIMi9Wk.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-BNcA6Irq.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-CIRGNCvi.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-CwXpLi3X.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-4swiiDz7.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-BGcdtMMT.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-D0-krtA2.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-C88KphGx.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-Chk9guIU.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/provider-probe.ts +63 -0
  316. package/src/providers/registry.ts +109 -29
  317. package/src/server/index.ts +9 -0
  318. package/src/server/middleware/auth.ts +5 -1
  319. package/src/server/routes/cross-origin-guard.ts +20 -0
  320. package/src/server/routes/git.ts +40 -4
  321. package/src/server/routes/lsp.ts +97 -4
  322. package/src/server/routes/resources.ts +72 -9
  323. package/src/server/routes/settings.ts +19 -1
  324. package/src/server/routes/speech.ts +66 -0
  325. package/src/server/routes/system-services.ts +76 -0
  326. package/src/server/routes/tunnel.ts +33 -1
  327. package/src/server/ws/chat.ts +74 -3
  328. package/src/services/codex-account-login.ts +26 -2
  329. package/src/services/codex-reset-credit.service.ts +16 -3
  330. package/src/services/compaction-savings.ts +127 -0
  331. package/src/services/db.service.ts +123 -8
  332. package/src/services/fs-ops/fs-ops-trash.service.ts +22 -9
  333. package/src/services/git-refs/for-each-ref.ts +118 -0
  334. package/src/services/git.service.ts +25 -2
  335. package/src/services/host-info/spawn-runner.ts +48 -4
  336. package/src/services/jsonl-transcript-parser.ts +7 -42
  337. package/src/services/lsp/lsp-install.ts +289 -0
  338. package/src/services/lsp/lsp-manager.ts +160 -29
  339. package/src/services/lsp/server-registry.ts +120 -4
  340. package/src/services/named-tunnel/named-tunnel-config.ts +8 -2
  341. package/src/services/named-tunnel/named-tunnel-setup.service.ts +4 -0
  342. package/src/services/read-lines.ts +54 -0
  343. package/src/services/speech-to-text/whisper-catalog.ts +142 -0
  344. package/src/services/speech-to-text/whisper-download.ts +113 -0
  345. package/src/services/speech-to-text/whisper-hallucinations.ts +51 -0
  346. package/src/services/speech-to-text/whisper-install.service.ts +247 -0
  347. package/src/services/speech-to-text/whisper-paths.ts +62 -0
  348. package/src/services/speech-to-text/whisper-transcribe.service.ts +117 -0
  349. package/src/services/supervisor.ts +94 -11
  350. package/src/services/system-metrics/cpu-details-linux.ts +252 -0
  351. package/src/services/system-metrics/cpu-memory-collector.ts +140 -18
  352. package/src/services/system-metrics/device-collector-linux.ts +31 -0
  353. package/src/services/system-metrics/device-collector-types.ts +40 -0
  354. package/src/services/system-metrics/disk-devices-linux.ts +156 -0
  355. package/src/services/system-metrics/disk-inventory-linux.ts +150 -0
  356. package/src/services/system-metrics/fans-linux.ts +51 -0
  357. package/src/services/system-metrics/gpu-api-versions.ts +120 -0
  358. package/src/services/system-metrics/gpu-devices-linux.ts +370 -0
  359. package/src/services/system-metrics/gpu-fdinfo-linux.ts +253 -0
  360. package/src/services/system-metrics/hardware-inventory.ts +50 -0
  361. package/src/services/system-metrics/linux-fs.ts +43 -0
  362. package/src/services/system-metrics/memory-darwin.ts +91 -0
  363. package/src/services/system-metrics/memory-linux.ts +156 -0
  364. package/src/services/system-metrics/net-devices-linux.ts +114 -0
  365. package/src/services/system-metrics/net-inventory-linux.ts +100 -0
  366. package/src/services/system-metrics/partitions-linux.ts +158 -0
  367. package/src/services/system-metrics/process-collector-linux.ts +58 -6
  368. package/src/services/system-metrics/process-collector-types.ts +8 -1
  369. package/src/services/system-metrics/process-details-darwin.ts +166 -0
  370. package/src/services/system-metrics/process-details-linux.ts +150 -0
  371. package/src/services/system-metrics/process-grouping.ts +2 -1
  372. package/src/services/system-metrics/process-rows-builder.ts +2 -0
  373. package/src/services/system-metrics/process-swap-linux.ts +37 -0
  374. package/src/services/system-metrics/signal-executor.ts +84 -0
  375. package/src/services/system-metrics/signal-request-handler.ts +92 -0
  376. package/src/services/system-metrics/system-metrics-platform.ts +30 -4
  377. package/src/services/system-metrics/system-metrics-tick.ts +73 -4
  378. package/src/services/system-metrics/system-metrics.service.ts +87 -2
  379. package/src/services/system-metrics/udev-db.ts +40 -0
  380. package/src/services/system-services/app-cgroup-linux.ts +115 -0
  381. package/src/services/system-services/app-icon-service.ts +31 -0
  382. package/src/services/system-services/app-icons-linux.ts +124 -0
  383. package/src/services/system-services/apps-linux.ts +174 -0
  384. package/src/services/system-services/desktop-entry.ts +103 -0
  385. package/src/services/system-services/service-guard.ts +124 -0
  386. package/src/services/system-services/systemd-collector.ts +203 -0
  387. package/src/services/system-services/systemd-parse.ts +162 -0
  388. package/src/shared/prompt-cache-idle.ts +197 -0
  389. package/src/shared/turn-usage.ts +85 -1
  390. package/src/types/chat.ts +27 -0
  391. package/src/types/config.ts +14 -0
  392. package/src/types/git.ts +41 -0
  393. package/src/types/system-hardware.ts +137 -0
  394. package/src/types/system-metrics.ts +231 -2
  395. package/src/types/system-services.ts +73 -0
  396. package/src/web/components/branch-review/branch-review-tab.tsx +20 -20
  397. package/src/web/components/branch-review/branch-review-tree-row.tsx +1 -13
  398. package/src/web/components/chat/chat-tab.tsx +3 -0
  399. package/src/web/components/chat/compaction-divider.tsx +48 -0
  400. package/src/web/components/chat/idle-cache-notice.tsx +67 -0
  401. package/src/web/components/chat/message-input.tsx +48 -13
  402. package/src/web/components/chat/message-list.tsx +15 -0
  403. package/src/web/components/chat/prompt-cache-chip.tsx +74 -0
  404. package/src/web/components/editor/code-editor.tsx +1 -0
  405. package/src/web/components/editor/editor-language-service.tsx +11 -3
  406. package/src/web/components/editor/lsp-status.tsx +115 -13
  407. package/src/web/components/git/branch-picker.tsx +419 -0
  408. package/src/web/components/git/branch-select.tsx +34 -0
  409. package/src/web/components/git/create-worktree-dialog.tsx +17 -16
  410. package/src/web/components/git/git-repo-picker.tsx +28 -40
  411. package/src/web/components/layout/status-bar.tsx +42 -19
  412. package/src/web/components/settings/accounts/account-card.tsx +5 -1
  413. package/src/web/components/settings/ai-settings-section.tsx +67 -3
  414. package/src/web/components/settings/appearance-settings-section.tsx +2 -28
  415. package/src/web/components/settings/language-servers-section.tsx +362 -0
  416. package/src/web/components/settings/settings-categories.ts +8 -3
  417. package/src/web/components/settings/settings-section-content.tsx +2 -0
  418. package/src/web/components/settings/voice-settings-section.tsx +283 -0
  419. package/src/web/components/system/apps/app-row.tsx +110 -0
  420. package/src/web/components/system/apps/app-rows.ts +140 -0
  421. package/src/web/components/system/apps/apps-panel.tsx +129 -0
  422. package/src/web/components/system/metric-chart-canvas.tsx +79 -3
  423. package/src/web/components/system/overview-cards/card-shell.tsx +54 -0
  424. package/src/web/components/system/overview-cards/cpu-card.tsx +11 -6
  425. package/src/web/components/system/overview-cards/disk-card.tsx +11 -6
  426. package/src/web/components/system/overview-cards/gpu-card.tsx +16 -6
  427. package/src/web/components/system/overview-cards/mem-card.tsx +11 -6
  428. package/src/web/components/system/overview-cards/net-card.tsx +11 -6
  429. package/src/web/components/system/overview-device-target.ts +69 -0
  430. package/src/web/components/system/overview-panel.tsx +15 -1
  431. package/src/web/components/system/performance/cpu-core-grid.tsx +74 -0
  432. package/src/web/components/system/performance/cpu-detail.tsx +220 -0
  433. package/src/web/components/system/performance/detail-parts.tsx +149 -0
  434. package/src/web/components/system/performance/device-list.ts +139 -0
  435. package/src/web/components/system/performance/disk-detail.tsx +64 -0
  436. package/src/web/components/system/performance/fans-detail.tsx +35 -0
  437. package/src/web/components/system/performance/gpu-detail.tsx +116 -0
  438. package/src/web/components/system/performance/memory-detail.tsx +109 -0
  439. package/src/web/components/system/performance/nic-detail.tsx +55 -0
  440. package/src/web/components/system/performance/partition-list.tsx +79 -0
  441. package/src/web/components/system/performance/performance-panel.tsx +206 -0
  442. package/src/web/components/system/performance/use-hardware-inventory.ts +48 -0
  443. package/src/web/components/system/process-columns-grid.ts +5 -3
  444. package/src/web/components/system/process-details-dialog.tsx +116 -0
  445. package/src/web/components/system/process-group-row.tsx +6 -1
  446. package/src/web/components/system/process-row-format.ts +6 -0
  447. package/src/web/components/system/process-row-menu.tsx +72 -0
  448. package/src/web/components/system/process-row.tsx +7 -1
  449. package/src/web/components/system/process-table-model.ts +1 -1
  450. package/src/web/components/system/process-table-sort.ts +8 -4
  451. package/src/web/components/system/process-table-toolbar.tsx +10 -2
  452. package/src/web/components/system/process-table-totals.ts +3 -0
  453. package/src/web/components/system/process-table.tsx +25 -2
  454. package/src/web/components/system/services/service-action-confirm.tsx +100 -0
  455. package/src/web/components/system/services/service-columns.ts +103 -0
  456. package/src/web/components/system/services/service-details-sheet.tsx +97 -0
  457. package/src/web/components/system/services/service-resources.ts +105 -0
  458. package/src/web/components/system/services/service-row.tsx +146 -0
  459. package/src/web/components/system/services/service-rows.ts +92 -0
  460. package/src/web/components/system/services/service-sort.ts +90 -0
  461. package/src/web/components/system/services/services-header.tsx +51 -0
  462. package/src/web/components/system/services/services-panel.tsx +207 -0
  463. package/src/web/components/system/services/use-services.ts +92 -0
  464. package/src/web/components/system/sortable-header.tsx +13 -8
  465. package/src/web/components/system/sysmon-preferences.tsx +85 -0
  466. package/src/web/components/system/system-monitor-body.tsx +101 -43
  467. package/src/web/components/system/system-monitor-window-content.tsx +2 -3
  468. package/src/web/components/system/use-process-signal.ts +87 -0
  469. package/src/web/components/tunnels/public-tunnel-switch.tsx +82 -0
  470. package/src/web/components/tunnels/tunnel-manager-tab.tsx +4 -0
  471. package/src/web/components/ui/dialog.tsx +14 -1
  472. package/src/web/components/ui/search-select.tsx +279 -0
  473. package/src/web/components/ui/start-ellipsis.tsx +18 -0
  474. package/src/web/hooks/use-chat.ts +28 -0
  475. package/src/web/hooks/use-global-keybindings.ts +7 -5
  476. package/src/web/hooks/use-lsp.ts +23 -2
  477. package/src/web/hooks/use-minute-clock.ts +20 -0
  478. package/src/web/hooks/use-whisper-voice-input.ts +113 -0
  479. package/src/web/lib/api-tunnels.ts +19 -0
  480. package/src/web/lib/branch-select-items.ts +29 -0
  481. package/src/web/lib/cpu-graph-mode.ts +90 -0
  482. package/src/web/lib/format-bytes.ts +14 -0
  483. package/src/web/lib/git-ref-picker.ts +120 -0
  484. package/src/web/lib/lsp/lsp-client.ts +32 -0
  485. package/src/web/lib/search-select-rows.ts +55 -0
  486. package/src/web/lib/temperature.ts +27 -0
  487. package/src/web/lib/voice-wav.ts +69 -0
  488. package/src/web/stores/git-status-store.ts +31 -17
  489. package/src/web/stores/keybindings-store.ts +14 -1
  490. package/src/web/stores/settings-store.ts +65 -0
  491. package/src/web/styles/globals.css +11 -0
  492. package/dist/web/assets/accounts-settings-section-DUVO32SQ.js +0 -1
  493. package/dist/web/assets/accounts-settings-section-DUVO32SQ.js.br +0 -0
  494. package/dist/web/assets/accounts-settings-section-DUVO32SQ.js.gz +0 -0
  495. package/dist/web/assets/ai-resource-editor-Dn_wB-o5.js.br +0 -0
  496. package/dist/web/assets/ai-resource-editor-Dn_wB-o5.js.gz +0 -0
  497. package/dist/web/assets/ai-settings-section-CEbW8jRy.js +0 -1
  498. package/dist/web/assets/ai-settings-section-CEbW8jRy.js.br +0 -0
  499. package/dist/web/assets/ai-settings-section-CEbW8jRy.js.gz +0 -0
  500. package/dist/web/assets/ai-settings-section-D-mwEYFZ.js +0 -1
  501. package/dist/web/assets/api-client-BgedDTvo.js +0 -1
  502. package/dist/web/assets/api-client-c8YOpTlT.js.br +0 -0
  503. package/dist/web/assets/api-client-c8YOpTlT.js.gz +0 -0
  504. package/dist/web/assets/api-settings-BmvNoCbn.js.br +0 -0
  505. package/dist/web/assets/api-settings-BmvNoCbn.js.gz +0 -0
  506. package/dist/web/assets/api-settings-Bti1-Zn3.js +0 -1
  507. package/dist/web/assets/appearance-settings-section-tw6TpFb6.js +0 -1
  508. package/dist/web/assets/appearance-settings-section-tw6TpFb6.js.br +0 -0
  509. package/dist/web/assets/appearance-settings-section-tw6TpFb6.js.gz +0 -0
  510. package/dist/web/assets/audio-preview-vaG2cB-k.js.br +0 -0
  511. package/dist/web/assets/audio-preview-vaG2cB-k.js.gz +0 -0
  512. package/dist/web/assets/branch-review-tab-MBuMWp_i.js +0 -1
  513. package/dist/web/assets/branch-review-tab-MBuMWp_i.js.br +0 -0
  514. package/dist/web/assets/branch-review-tab-MBuMWp_i.js.gz +0 -0
  515. package/dist/web/assets/button-Ci9EUgqd.js.br +0 -0
  516. package/dist/web/assets/button-Ci9EUgqd.js.gz +0 -0
  517. package/dist/web/assets/chat-preparation-cache-BSIQGiWx.js.br +0 -0
  518. package/dist/web/assets/chat-preparation-cache-BSIQGiWx.js.gz +0 -0
  519. package/dist/web/assets/chat-tab-DVvnqhw6.js +0 -1
  520. package/dist/web/assets/chat-tab-DVvnqhw6.js.br +0 -0
  521. package/dist/web/assets/chat-tab-DVvnqhw6.js.gz +0 -0
  522. package/dist/web/assets/chat-tab-DaEHva22.js +0 -15
  523. package/dist/web/assets/chat-tab-DaEHva22.js.br +0 -0
  524. package/dist/web/assets/chat-tab-DaEHva22.js.gz +0 -0
  525. package/dist/web/assets/code-editor-Bu9lhTVp.js +0 -7
  526. package/dist/web/assets/code-editor-Bu9lhTVp.js.br +0 -0
  527. package/dist/web/assets/code-editor-Bu9lhTVp.js.gz +0 -0
  528. package/dist/web/assets/codex-reset-credit-button-CbmE5mRX.js +0 -1
  529. package/dist/web/assets/codex-reset-credit-button-CbmE5mRX.js.br +0 -0
  530. package/dist/web/assets/codex-reset-credit-button-CbmE5mRX.js.gz +0 -0
  531. package/dist/web/assets/conflict-editor-BA3y-qSH.js.br +0 -0
  532. package/dist/web/assets/conflict-editor-BA3y-qSH.js.gz +0 -0
  533. package/dist/web/assets/context-menu-CjYTq8DI.js +0 -1
  534. package/dist/web/assets/context-menu-CjYTq8DI.js.br +0 -0
  535. package/dist/web/assets/context-menu-CjYTq8DI.js.gz +0 -0
  536. package/dist/web/assets/csv-preview-BioxkrQF.js.br +0 -0
  537. package/dist/web/assets/csv-preview-BioxkrQF.js.gz +0 -0
  538. package/dist/web/assets/data-grid-overlay-editor-CQRVKr7y.js.br +0 -0
  539. package/dist/web/assets/data-grid-overlay-editor-CQRVKr7y.js.gz +0 -0
  540. package/dist/web/assets/database-viewer-BSoJ0E6p.js.br +0 -0
  541. package/dist/web/assets/database-viewer-BSoJ0E6p.js.gz +0 -0
  542. package/dist/web/assets/design-export-client-ChMcMoqW.js.br +0 -0
  543. package/dist/web/assets/design-export-client-ChMcMoqW.js.gz +0 -0
  544. package/dist/web/assets/design-responsive-dialog-DNBhJJLf.js.br +0 -0
  545. package/dist/web/assets/design-responsive-dialog-DNBhJJLf.js.gz +0 -0
  546. package/dist/web/assets/design-tab-iU2CviE3.js +0 -33
  547. package/dist/web/assets/design-tab-iU2CviE3.js.br +0 -0
  548. package/dist/web/assets/design-tab-iU2CviE3.js.gz +0 -0
  549. package/dist/web/assets/designs-sidebar-panel-DHh5QsH9.js.br +0 -0
  550. package/dist/web/assets/designs-sidebar-panel-DHh5QsH9.js.gz +0 -0
  551. package/dist/web/assets/dialog-B8clVkyi.js +0 -1
  552. package/dist/web/assets/dialog-B8clVkyi.js.br +0 -0
  553. package/dist/web/assets/dialog-B8clVkyi.js.gz +0 -0
  554. package/dist/web/assets/diff-viewer-lctWoSmG.js.br +0 -0
  555. package/dist/web/assets/diff-viewer-lctWoSmG.js.gz +0 -0
  556. package/dist/web/assets/docx-preview-C9XdKEj1.js.br +0 -0
  557. package/dist/web/assets/docx-preview-C9XdKEj1.js.gz +0 -0
  558. package/dist/web/assets/editor-language-service-fPG56hQO.js +0 -1
  559. package/dist/web/assets/editor-language-service-fPG56hQO.js.br +0 -0
  560. package/dist/web/assets/editor-language-service-fPG56hQO.js.gz +0 -0
  561. package/dist/web/assets/explorer-body-BgF7FsxI.js +0 -2
  562. package/dist/web/assets/explorer-body-BgF7FsxI.js.br +0 -0
  563. package/dist/web/assets/explorer-body-BgF7FsxI.js.gz +0 -0
  564. package/dist/web/assets/explorer-window-content-C21w_7lf.js +0 -1
  565. package/dist/web/assets/explorer-window-content-C21w_7lf.js.br +0 -0
  566. package/dist/web/assets/explorer-window-content-C21w_7lf.js.gz +0 -0
  567. package/dist/web/assets/extension-manager-section-rbkXsZVR.js.br +0 -0
  568. package/dist/web/assets/extension-manager-section-rbkXsZVR.js.gz +0 -0
  569. package/dist/web/assets/extension-webview-uPO0WgCq.js.br +0 -0
  570. package/dist/web/assets/extension-webview-uPO0WgCq.js.gz +0 -0
  571. package/dist/web/assets/file-icons-gx_FBOXY.js.br +0 -0
  572. package/dist/web/assets/file-icons-gx_FBOXY.js.gz +0 -0
  573. package/dist/web/assets/file-store-D9KE0kQC.js.br +0 -0
  574. package/dist/web/assets/file-store-D9KE0kQC.js.gz +0 -0
  575. package/dist/web/assets/files-settings-section-CT7mDb0L.js.br +0 -0
  576. package/dist/web/assets/files-settings-section-CT7mDb0L.js.gz +0 -0
  577. package/dist/web/assets/format-bytes-DmSHAKFe.js +0 -1
  578. package/dist/web/assets/format-file-meta-mQwA6SuY.js.br +0 -0
  579. package/dist/web/assets/format-file-meta-mQwA6SuY.js.gz +0 -0
  580. package/dist/web/assets/fs-api-DL36slbd.js.br +0 -0
  581. package/dist/web/assets/fs-api-DL36slbd.js.gz +0 -0
  582. package/dist/web/assets/general-settings-section-DANPfMRN.js.br +0 -0
  583. package/dist/web/assets/general-settings-section-DANPfMRN.js.gz +0 -0
  584. package/dist/web/assets/git-log-panel-BJPkLiEw.js.br +0 -0
  585. package/dist/web/assets/git-log-panel-BJPkLiEw.js.gz +0 -0
  586. package/dist/web/assets/git-repo-store-DSypNj19.js.br +0 -0
  587. package/dist/web/assets/git-repo-store-DSypNj19.js.gz +0 -0
  588. package/dist/web/assets/glide-data-grid-R4PcAntf.js.br +0 -0
  589. package/dist/web/assets/glide-data-grid-R4PcAntf.js.gz +0 -0
  590. package/dist/web/assets/group-chat-tab-BXMdo8w9.js +0 -1
  591. package/dist/web/assets/group-chat-tab-BXMdo8w9.js.br +0 -0
  592. package/dist/web/assets/group-chat-tab-BXMdo8w9.js.gz +0 -0
  593. package/dist/web/assets/index-C8nGqkKN.js +0 -52
  594. package/dist/web/assets/index-C8nGqkKN.js.br +0 -0
  595. package/dist/web/assets/index-C8nGqkKN.js.gz +0 -0
  596. package/dist/web/assets/index-DvClbTQx.css +0 -1
  597. package/dist/web/assets/index-DvClbTQx.css.br +0 -0
  598. package/dist/web/assets/index-DvClbTQx.css.gz +0 -0
  599. package/dist/web/assets/keybindings-store-BGKlQQAv.js +0 -1
  600. package/dist/web/assets/keyboard-shortcuts-section-BKej4mUf.js.br +0 -0
  601. package/dist/web/assets/keyboard-shortcuts-section-BKej4mUf.js.gz +0 -0
  602. package/dist/web/assets/markdown-renderer-BHtYqkYZ.js.br +0 -0
  603. package/dist/web/assets/markdown-renderer-BHtYqkYZ.js.gz +0 -0
  604. package/dist/web/assets/markdown-renderer-vDNuKjel.js +0 -1
  605. package/dist/web/assets/mobile-bottom-sheet-CuNi2FRv.js.br +0 -0
  606. package/dist/web/assets/mobile-bottom-sheet-CuNi2FRv.js.gz +0 -0
  607. package/dist/web/assets/mobile-explorer-sheet-DtvxS7-r.js +0 -1
  608. package/dist/web/assets/mobile-explorer-sheet-DtvxS7-r.js.br +0 -0
  609. package/dist/web/assets/mobile-explorer-sheet-DtvxS7-r.js.gz +0 -0
  610. package/dist/web/assets/new-design-dialog-DS_XrpTG.js.br +0 -0
  611. package/dist/web/assets/new-design-dialog-DS_XrpTG.js.gz +0 -0
  612. package/dist/web/assets/notification-store-Dnnj20Ky.js +0 -1
  613. package/dist/web/assets/notifications-settings-section-C05WYqcE.js.br +0 -0
  614. package/dist/web/assets/notifications-settings-section-C05WYqcE.js.gz +0 -0
  615. package/dist/web/assets/onboarding-entry-CmUqv1kl.js.br +0 -0
  616. package/dist/web/assets/onboarding-entry-CmUqv1kl.js.gz +0 -0
  617. package/dist/web/assets/onboarding-quick-orientation-DIhWv1CN.js.br +0 -0
  618. package/dist/web/assets/onboarding-quick-orientation-DIhWv1CN.js.gz +0 -0
  619. package/dist/web/assets/overview-panel-BZAW_nag.js +0 -1
  620. package/dist/web/assets/overview-panel-BZAW_nag.js.br +0 -0
  621. package/dist/web/assets/overview-panel-BZAW_nag.js.gz +0 -0
  622. package/dist/web/assets/pdf-preview-qdXmMkOR.js.br +0 -0
  623. package/dist/web/assets/pdf-preview-qdXmMkOR.js.gz +0 -0
  624. package/dist/web/assets/postgres-viewer-Xvlun_n5.js.br +0 -0
  625. package/dist/web/assets/postgres-viewer-Xvlun_n5.js.gz +0 -0
  626. package/dist/web/assets/ppmbot-settings-section-D8AES1BA.js.br +0 -0
  627. package/dist/web/assets/ppmbot-settings-section-D8AES1BA.js.gz +0 -0
  628. package/dist/web/assets/pptx-export-CG6MRNok.js.br +0 -0
  629. package/dist/web/assets/pptx-export-CG6MRNok.js.gz +0 -0
  630. package/dist/web/assets/problems-panel-DTBG4beI.js.br +0 -0
  631. package/dist/web/assets/problems-panel-DTBG4beI.js.gz +0 -0
  632. package/dist/web/assets/process-table-D_gR2XA6.js +0 -1
  633. package/dist/web/assets/process-table-D_gR2XA6.js.br +0 -0
  634. package/dist/web/assets/process-table-D_gR2XA6.js.gz +0 -0
  635. package/dist/web/assets/project-store-C5gJXkvb.js.br +0 -0
  636. package/dist/web/assets/project-store-C5gJXkvb.js.gz +0 -0
  637. package/dist/web/assets/proxy-settings-section-CqtmbeRj.js.br +0 -0
  638. package/dist/web/assets/proxy-settings-section-CqtmbeRj.js.gz +0 -0
  639. package/dist/web/assets/query-audit-section-UKG_smyt.js.br +0 -0
  640. package/dist/web/assets/query-audit-section-UKG_smyt.js.gz +0 -0
  641. package/dist/web/assets/remote-desktop-clipboard-notice-Djt6cpNL.js.br +0 -0
  642. package/dist/web/assets/remote-desktop-clipboard-notice-Djt6cpNL.js.gz +0 -0
  643. package/dist/web/assets/remote-desktop-mobile-sheet-BQxhJUkm.js +0 -2
  644. package/dist/web/assets/remote-desktop-mobile-sheet-BQxhJUkm.js.br +0 -0
  645. package/dist/web/assets/remote-desktop-mobile-sheet-BQxhJUkm.js.gz +0 -0
  646. package/dist/web/assets/remote-desktop-mobile-view-DGnT8RY7.js +0 -1
  647. package/dist/web/assets/remote-desktop-mobile-view-DGnT8RY7.js.br +0 -0
  648. package/dist/web/assets/remote-desktop-mobile-view-DGnT8RY7.js.gz +0 -0
  649. package/dist/web/assets/remote-desktop-readiness-gate-DNJF8TcF.js.br +0 -0
  650. package/dist/web/assets/remote-desktop-readiness-gate-DNJF8TcF.js.gz +0 -0
  651. package/dist/web/assets/remote-desktop-window-content-Ds0DKmM0.js +0 -1
  652. package/dist/web/assets/remote-desktop-window-content-Ds0DKmM0.js.br +0 -0
  653. package/dist/web/assets/remote-desktop-window-content-Ds0DKmM0.js.gz +0 -0
  654. package/dist/web/assets/schedules-settings-section-BKoPovy2.js.br +0 -0
  655. package/dist/web/assets/schedules-settings-section-BKoPovy2.js.gz +0 -0
  656. package/dist/web/assets/scroll-area-XonvWYn_.js.br +0 -0
  657. package/dist/web/assets/scroll-area-XonvWYn_.js.gz +0 -0
  658. package/dist/web/assets/settings-body-k2qPgRFe.js +0 -2
  659. package/dist/web/assets/settings-body-k2qPgRFe.js.br +0 -0
  660. package/dist/web/assets/settings-body-k2qPgRFe.js.gz +0 -0
  661. package/dist/web/assets/settings-store-Br5c1efC.js +0 -2
  662. package/dist/web/assets/settings-store-Br5c1efC.js.br +0 -0
  663. package/dist/web/assets/settings-store-Br5c1efC.js.gz +0 -0
  664. package/dist/web/assets/settings-tab-Bb23VdBu.js +0 -1
  665. package/dist/web/assets/settings-window-content-ClarWusz.js +0 -1
  666. package/dist/web/assets/sql-query-editor-BjIMi9Wk.js.br +0 -0
  667. package/dist/web/assets/sql-query-editor-BjIMi9Wk.js.gz +0 -0
  668. package/dist/web/assets/sqlite-viewer-BNcA6Irq.js.br +0 -0
  669. package/dist/web/assets/sqlite-viewer-BNcA6Irq.js.gz +0 -0
  670. package/dist/web/assets/system-monitor-body-D0T3ggt2.js +0 -2
  671. package/dist/web/assets/system-monitor-body-D0T3ggt2.js.br +0 -0
  672. package/dist/web/assets/system-monitor-body-D0T3ggt2.js.gz +0 -0
  673. package/dist/web/assets/system-monitor-tab-I1Igmoey.js +0 -1
  674. package/dist/web/assets/system-monitor-window-content-C5SeUv1H.js +0 -1
  675. package/dist/web/assets/tab-host-window-content-CIRGNCvi.js.br +0 -0
  676. package/dist/web/assets/tab-host-window-content-CIRGNCvi.js.gz +0 -0
  677. package/dist/web/assets/team-member-sheet-CwXpLi3X.js.br +0 -0
  678. package/dist/web/assets/team-member-sheet-CwXpLi3X.js.gz +0 -0
  679. package/dist/web/assets/team-member-window-content-4swiiDz7.js.br +0 -0
  680. package/dist/web/assets/team-member-window-content-4swiiDz7.js.gz +0 -0
  681. package/dist/web/assets/terminal-tab-BGcdtMMT.js.br +0 -0
  682. package/dist/web/assets/terminal-tab-BGcdtMMT.js.gz +0 -0
  683. package/dist/web/assets/tool-cards-D0-krtA2.js.br +0 -0
  684. package/dist/web/assets/tool-cards-D0-krtA2.js.gz +0 -0
  685. package/dist/web/assets/use-inline-blame-pKaXyGU-.js +0 -16
  686. package/dist/web/assets/use-inline-blame-pKaXyGU-.js.br +0 -0
  687. package/dist/web/assets/use-inline-blame-pKaXyGU-.js.gz +0 -0
  688. package/dist/web/assets/use-lsp-71azTXQz.js +0 -6
  689. package/dist/web/assets/use-lsp-71azTXQz.js.br +0 -0
  690. package/dist/web/assets/use-lsp-71azTXQz.js.gz +0 -0
  691. package/dist/web/assets/vendor-ui-BHh12_0v.js.br +0 -0
  692. package/dist/web/assets/vendor-ui-BHh12_0v.js.gz +0 -0
  693. package/dist/web/assets/video-preview-DxEX-uGo.js +0 -1
  694. package/dist/web/assets/video-preview-DxEX-uGo.js.br +0 -0
  695. package/dist/web/assets/video-preview-DxEX-uGo.js.gz +0 -0
  696. package/dist/web/assets/ws-auth-kXgsX2Js.js +0 -1
  697. /package/dist/web/assets/{__vite-browser-external-BpSQWxcq.js → __vite-browser-external-BILfYaAs.js} +0 -0
  698. /package/dist/web/assets/{run-in-terminal-HIdNgYim.js → run-in-terminal-2pSiup8e.js} +0 -0
  699. /package/dist/web/assets/{vendor-xterm-DLDtzLib.js → vendor-xterm-DF1JTfsy.js} +0 -0
  700. /package/dist/web/assets/{vendor-xterm-DLDtzLib.js.br → vendor-xterm-DF1JTfsy.js.br} +0 -0
  701. /package/dist/web/assets/{vendor-xterm-DLDtzLib.js.gz → vendor-xterm-DF1JTfsy.js.gz} +0 -0
@@ -0,0 +1,247 @@
1
+ /**
2
+ * Installing Whisper on the host: download the prebuilt whisper.cpp for this
3
+ * platform, the chosen speech model, and the VAD model, then prove the binary
4
+ * actually runs here.
5
+ *
6
+ * That last step is not ceremony. The published Linux build needs glibc 2.34
7
+ * and libstdc++ from GCC 11, so on an older host (Ubuntu 20.04 ships glibc
8
+ * 2.31) every file downloads fine and the binary only fails when someone first
9
+ * speaks into the chat box. Running `--help` once at install time turns that
10
+ * into an install error naming the cause.
11
+ *
12
+ * One model is kept on disk at a time: they are 60–574 MB, and "which one is
13
+ * active" then has no state to drift — it is whichever file is there.
14
+ */
15
+ import { existsSync, mkdirSync, readdirSync, rmSync } from "node:fs";
16
+ import { resolve } from "node:path";
17
+ import {
18
+ DEFAULT_MODEL_ID,
19
+ MACOS_INSTALL_HINT,
20
+ VAD_MODEL,
21
+ WHISPER_MODELS,
22
+ WHISPER_VERSION,
23
+ modelById,
24
+ modelUrl,
25
+ vadModelUrl,
26
+ whisperAssetFor,
27
+ type WhisperAsset,
28
+ } from "./whisper-catalog.ts";
29
+ import { downloadVerified, type FetchFn } from "./whisper-download.ts";
30
+ import {
31
+ findWhisperBinary,
32
+ whisperBinDir,
33
+ whisperDir,
34
+ whisperModelDir,
35
+ whisperTmpDir,
36
+ type WhisperBinary,
37
+ } from "./whisper-paths.ts";
38
+
39
+ export type InstallPhase = "binary" | "model" | "vad" | "verify";
40
+
41
+ export interface InstallJobState {
42
+ modelId: string;
43
+ phase: InstallPhase;
44
+ receivedBytes: number;
45
+ totalBytes: number;
46
+ done: boolean;
47
+ error: string | null;
48
+ }
49
+
50
+ export interface WhisperStatusModel {
51
+ id: string;
52
+ label: string;
53
+ note: string;
54
+ bytes: number;
55
+ }
56
+
57
+ export interface WhisperStatus {
58
+ /** False only when this platform has no prebuilt build AND no binary on the host. */
59
+ installable: boolean;
60
+ /** Manual command for a platform PPM cannot install for (macOS). */
61
+ installHint: string | null;
62
+ binary: WhisperBinary | null;
63
+ version: string;
64
+ /** Model currently on disk, if any. */
65
+ model: WhisperStatusModel | null;
66
+ /** Binary + model + VAD model all present — the mic can use it. */
67
+ ready: boolean;
68
+ models: WhisperStatusModel[];
69
+ install: InstallJobState | null;
70
+ }
71
+
72
+ let currentJob: InstallJobState | null = null;
73
+
74
+ const publicModel = (m: (typeof WHISPER_MODELS)[number]): WhisperStatusModel => ({
75
+ id: m.id,
76
+ label: m.label,
77
+ note: m.note,
78
+ bytes: m.bytes,
79
+ });
80
+
81
+ /** The installed model, found by which catalog file exists on disk. */
82
+ export function installedModel(): (typeof WHISPER_MODELS)[number] | null {
83
+ return WHISPER_MODELS.find((m) => existsSync(resolve(whisperModelDir(), m.file))) ?? null;
84
+ }
85
+
86
+ export function vadModelPath(): string {
87
+ return resolve(whisperModelDir(), VAD_MODEL.file);
88
+ }
89
+
90
+ export function getWhisperStatus(
91
+ platform: NodeJS.Platform = process.platform,
92
+ arch: string = process.arch,
93
+ ): WhisperStatus {
94
+ const binary = findWhisperBinary(platform);
95
+ const model = installedModel();
96
+ const hasAsset = whisperAssetFor(platform, arch) !== null;
97
+
98
+ return {
99
+ installable: hasAsset || binary !== null,
100
+ installHint: !hasAsset && platform === "darwin" ? MACOS_INSTALL_HINT : null,
101
+ binary,
102
+ version: WHISPER_VERSION,
103
+ model: model ? publicModel(model) : null,
104
+ ready: binary !== null && model !== null && existsSync(vadModelPath()),
105
+ models: WHISPER_MODELS.map(publicModel),
106
+ install: currentJob,
107
+ };
108
+ }
109
+
110
+ async function extractArchive(archive: string, asset: WhisperAsset, destDir: string, platform: NodeJS.Platform) {
111
+ const cmd =
112
+ asset.ext === "tar.gz"
113
+ ? ["tar", "-xzf", archive, "-C", destDir]
114
+ : platform === "win32"
115
+ ? // Windows 10+ ships bsdtar as tar.exe, which reads zip.
116
+ ["tar", "-xf", archive, "-C", destDir]
117
+ : ["unzip", "-o", "-q", archive, "-d", destDir];
118
+
119
+ const proc = Bun.spawn({ cmd, stdout: "ignore", stderr: "pipe" });
120
+ const code = await proc.exited;
121
+ if (code !== 0) {
122
+ const stderr = await new Response(proc.stderr).text();
123
+ throw new Error(`extract failed (${cmd[0]} exit ${code}): ${stderr.slice(0, 200)}`);
124
+ }
125
+ }
126
+
127
+ /** Run the binary once so a host that cannot execute it fails here, not mid-sentence. */
128
+ async function verifyBinaryRuns(path: string): Promise<void> {
129
+ let proc;
130
+ try {
131
+ proc = Bun.spawn({ cmd: [path, "--help"], stdout: "ignore", stderr: "pipe", windowsHide: true });
132
+ } catch (e: any) {
133
+ throw new Error(`whisper-cli could not be started: ${e?.message ?? e}`);
134
+ }
135
+ const [code, stderr] = await Promise.all([proc.exited, new Response(proc.stderr).text()]);
136
+ if (code !== 0) {
137
+ const detail = stderr.trim().split("\n")[0] ?? `exit ${code}`;
138
+ throw new Error(`whisper-cli does not run on this host: ${detail}`);
139
+ }
140
+ }
141
+
142
+ /** Keep only the model just installed — the others are hundreds of MB of nothing. */
143
+ function pruneOtherModels(keepFile: string) {
144
+ for (const m of WHISPER_MODELS) {
145
+ if (m.file !== keepFile) rmSync(resolve(whisperModelDir(), m.file), { force: true });
146
+ }
147
+ }
148
+
149
+ async function runInstall(modelId: string, platform: NodeJS.Platform, arch: string, fetchFn?: FetchFn) {
150
+ const model = modelById(modelId);
151
+ if (!model) throw new Error(`unknown model: ${modelId}`);
152
+ const job = currentJob!;
153
+ const progress = (received: number, total: number) => {
154
+ job.receivedBytes = received;
155
+ job.totalBytes = total || 0;
156
+ };
157
+
158
+ mkdirSync(whisperModelDir(), { recursive: true });
159
+
160
+ // A host that already has whisper-cli (Homebrew, distro package) needs models only.
161
+ if (!findWhisperBinary(platform)) {
162
+ const asset = whisperAssetFor(platform, arch);
163
+ if (!asset) throw new Error(`no whisper.cpp build for ${platform}/${arch} — install it manually`);
164
+ job.phase = "binary";
165
+ mkdirSync(whisperBinDir(), { recursive: true });
166
+ mkdirSync(whisperTmpDir(), { recursive: true });
167
+ const archive = resolve(whisperTmpDir(), asset.file);
168
+ await downloadVerified({ url: asset.url, dest: archive, sha256: asset.sha256, onProgress: progress, fetchFn });
169
+ await extractArchive(archive, asset, whisperBinDir(), platform);
170
+ rmSync(archive, { force: true });
171
+ }
172
+
173
+ job.phase = "model";
174
+ progress(0, model.bytes);
175
+ await downloadVerified({
176
+ url: modelUrl(model),
177
+ dest: resolve(whisperModelDir(), model.file),
178
+ sha256: model.sha256,
179
+ onProgress: progress,
180
+ fetchFn,
181
+ });
182
+
183
+ job.phase = "vad";
184
+ progress(0, VAD_MODEL.bytes);
185
+ await downloadVerified({
186
+ url: vadModelUrl(),
187
+ dest: vadModelPath(),
188
+ sha256: VAD_MODEL.sha256,
189
+ onProgress: progress,
190
+ fetchFn,
191
+ });
192
+
193
+ job.phase = "verify";
194
+ const binary = findWhisperBinary(platform);
195
+ if (!binary) throw new Error("whisper-cli missing after install");
196
+ await verifyBinaryRuns(binary.path);
197
+
198
+ pruneOtherModels(model.file);
199
+ }
200
+
201
+ /**
202
+ * Start an install in the background and return immediately — the UI polls
203
+ * `getWhisperStatus()`. One at a time: a second call while a job runs throws.
204
+ */
205
+ export function startWhisperInstall(
206
+ modelId: string = DEFAULT_MODEL_ID,
207
+ opts: { platform?: NodeJS.Platform; arch?: string; fetchFn?: FetchFn } = {},
208
+ ): InstallJobState {
209
+ if (currentJob && !currentJob.done) throw new Error("An install is already running");
210
+ const platform = opts.platform ?? process.platform;
211
+ const arch = opts.arch ?? process.arch;
212
+ if (!modelById(modelId)) throw new Error(`unknown model: ${modelId}`);
213
+
214
+ const job: InstallJobState = {
215
+ modelId,
216
+ phase: "binary",
217
+ receivedBytes: 0,
218
+ totalBytes: 0,
219
+ done: false,
220
+ error: null,
221
+ };
222
+ currentJob = job;
223
+
224
+ runInstall(modelId, platform, arch, opts.fetchFn)
225
+ .then(() => {
226
+ job.done = true;
227
+ })
228
+ .catch((e: any) => {
229
+ job.error = e?.message ?? String(e);
230
+ job.done = true;
231
+ console.error("[whisper] install failed:", job.error);
232
+ });
233
+
234
+ return job;
235
+ }
236
+
237
+ /** Remove everything PPM downloaded. A system-installed whisper-cli is left alone. */
238
+ export function uninstallWhisper(): void {
239
+ if (currentJob && !currentJob.done) throw new Error("An install is running");
240
+ rmSync(whisperDir(), { recursive: true, force: true });
241
+ currentJob = null;
242
+ }
243
+
244
+ /** Test seam: forget any finished job so a suite starts from a clean status. */
245
+ export function _resetWhisperInstallState(): void {
246
+ currentJob = null;
247
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Where the Whisper install lives, and how the binary is found.
3
+ *
4
+ * Everything PPM downloads sits under `<ppm dir>/whisper/` so uninstall is one
5
+ * `rm -rf` and an isolated `PPM_HOME` (tests) never touches a real install.
6
+ */
7
+ import { existsSync, readdirSync } from "node:fs";
8
+ import { resolve } from "node:path";
9
+ import { getPpmDir } from "../ppm-dir.ts";
10
+
11
+ export const whisperDir = () => resolve(getPpmDir(), "whisper");
12
+ export const whisperBinDir = () => resolve(whisperDir(), "bin");
13
+ export const whisperModelDir = () => resolve(whisperDir(), "models");
14
+ export const whisperTmpDir = () => resolve(whisperDir(), "tmp");
15
+
16
+ export const cliName = (platform: NodeJS.Platform = process.platform) =>
17
+ platform === "win32" ? "whisper-cli.exe" : "whisper-cli";
18
+
19
+ /**
20
+ * The extracted archive keeps its own top-level directory — `whisper-bin-ubuntu-x64/`
21
+ * on Linux, `Release/` on Windows — and those names carry the build tag, so the
22
+ * binary is located by looking one level down rather than assumed.
23
+ */
24
+ export function findBundledBinary(platform: NodeJS.Platform = process.platform): string | null {
25
+ const root = whisperBinDir();
26
+ if (!existsSync(root)) return null;
27
+ const name = cliName(platform);
28
+ if (existsSync(resolve(root, name))) return resolve(root, name);
29
+ for (const entry of readdirSync(root, { withFileTypes: true })) {
30
+ if (!entry.isDirectory()) continue;
31
+ const candidate = resolve(root, entry.name, name);
32
+ if (existsSync(candidate)) return candidate;
33
+ }
34
+ return null;
35
+ }
36
+
37
+ /**
38
+ * Homebrew's `whisper.cpp` is how a Mac gets a `whisper-cli` (the release has no
39
+ * macOS CLI to download), and a PPM started by launchd/systemd inherits a PATH
40
+ * that usually has neither Homebrew prefix in it — so both are checked directly
41
+ * rather than trusting `PATH` alone.
42
+ */
43
+ const SYSTEM_PATHS = ["/opt/homebrew/bin/whisper-cli", "/usr/local/bin/whisper-cli", "/usr/bin/whisper-cli"];
44
+
45
+ export function findSystemBinary(): string | null {
46
+ const onPath = Bun.which("whisper-cli");
47
+ if (onPath) return onPath;
48
+ return SYSTEM_PATHS.find((p) => existsSync(p)) ?? null;
49
+ }
50
+
51
+ export interface WhisperBinary {
52
+ path: string;
53
+ /** `bundled` = installed by PPM and removable from Settings; `system` = the host's own. */
54
+ source: "bundled" | "system";
55
+ }
56
+
57
+ export function findWhisperBinary(platform: NodeJS.Platform = process.platform): WhisperBinary | null {
58
+ const bundled = findBundledBinary(platform);
59
+ if (bundled) return { path: bundled, source: "bundled" };
60
+ const system = findSystemBinary();
61
+ return system ? { path: system, source: "system" } : null;
62
+ }
@@ -0,0 +1,117 @@
1
+ /**
2
+ * One transcription = one `whisper-cli` run over a temp WAV.
3
+ *
4
+ * Per-request process rather than a long-lived `whisper-server`, for two
5
+ * reasons: Homebrew's formula builds with `WHISPER_BUILD_SERVER=OFF`, so a Mac
6
+ * has no server binary to talk to; and a resident server holds the model
7
+ * (574 MB) in RAM between sentences that are minutes apart.
8
+ *
9
+ * Runs are serialised. Two at once would each load the model and fight for the
10
+ * same cores, turning two five-second waits into two twelve-second ones.
11
+ */
12
+ import { randomUUID } from "node:crypto";
13
+ import { mkdirSync, rmSync } from "node:fs";
14
+ import { availableParallelism } from "node:os";
15
+ import { resolve } from "node:path";
16
+ import { isInventedLine } from "./whisper-hallucinations.ts";
17
+ import { installedModel, vadModelPath } from "./whisper-install.service.ts";
18
+ import { findWhisperBinary, whisperModelDir, whisperTmpDir } from "./whisper-paths.ts";
19
+
20
+ const TIMEOUT_MS = 180_000;
21
+
22
+ /**
23
+ * whisper.cpp defaults to 4 threads. Measured on a 24-thread i9-12900K with
24
+ * large-v3-turbo over a 10s clip: 4 threads 12.0s, 8 threads 8.1s, 16 threads
25
+ * 5.6s, 24 threads 5.4s — so it is worth raising, and worth capping where the
26
+ * curve flattens instead of taking every core the host has.
27
+ */
28
+ export function threadCount(cpus: number = availableParallelism()): number {
29
+ return Math.max(1, Math.min(16, cpus));
30
+ }
31
+
32
+ /** A non-speech annotation on a line of its own: "[BLANK_AUDIO]", "(nhạc)", "*gunshot*". */
33
+ const ANNOTATION = /^[[(*][^)\]*]*[\])*]$/;
34
+
35
+ /**
36
+ * `-nt` prints text without timestamps, one line per segment. Three kinds of
37
+ * line are not something anyone dictated: an annotation, a line with no letter
38
+ * or digit in it at all (a bare "." is what this model makes of a hum in
39
+ * English), and a sentence it invented out of non-speech — see
40
+ * whisper-hallucinations.ts.
41
+ */
42
+ export function parseWhisperText(stdout: string): string {
43
+ return stdout
44
+ .split("\n")
45
+ .map((line) => line.trim())
46
+ .filter(
47
+ (line) =>
48
+ line.length > 0 &&
49
+ !ANNOTATION.test(line) &&
50
+ /[\p{L}\p{N}]/u.test(line) &&
51
+ !isInventedLine(line),
52
+ )
53
+ .join(" ")
54
+ .replace(/\s+/g, " ")
55
+ .trim();
56
+ }
57
+
58
+ export function whisperArgs(binary: string, wavPath: string, modelPath: string, language: string): string[] {
59
+ return [
60
+ binary,
61
+ "-m", modelPath,
62
+ "-f", wavPath,
63
+ "-l", language,
64
+ "-t", String(threadCount()),
65
+ "-nt",
66
+ "-np",
67
+ // Without VAD, silence is transcribed as an invented sentence — see whisper-catalog.ts.
68
+ "--vad",
69
+ "--vad-model", vadModelPath(),
70
+ ];
71
+ }
72
+
73
+ let queue: Promise<unknown> = Promise.resolve();
74
+
75
+ export interface TranscribeResult {
76
+ text: string;
77
+ /** Wall time of the whisper-cli run, for the UI's "took Ns" and for tuning. */
78
+ ms: number;
79
+ }
80
+
81
+ /** Throws when Whisper is not installed, the run fails, or it outruns the timeout. */
82
+ export async function transcribeWav(wav: Uint8Array, language = "vi"): Promise<TranscribeResult> {
83
+ const run = queue.then(() => runOnce(wav, language));
84
+ // Keep the chain alive after a failure, and never leak the rejection through it.
85
+ queue = run.catch(() => {});
86
+ return run;
87
+ }
88
+
89
+ async function runOnce(wav: Uint8Array, language: string): Promise<TranscribeResult> {
90
+ const binary = findWhisperBinary();
91
+ const model = installedModel();
92
+ if (!binary || !model) throw new Error("Whisper is not installed on this host");
93
+
94
+ mkdirSync(whisperTmpDir(), { recursive: true });
95
+ const wavPath = resolve(whisperTmpDir(), `${randomUUID()}.wav`);
96
+ await Bun.write(wavPath, wav);
97
+
98
+ const started = Date.now();
99
+ try {
100
+ const cmd = whisperArgs(binary.path, wavPath, resolve(whisperModelDir(), model.file), language);
101
+ const proc = Bun.spawn({ cmd, stdout: "pipe", stderr: "pipe", stdin: "ignore", windowsHide: true });
102
+ const timer = setTimeout(() => proc.kill(), TIMEOUT_MS);
103
+ const [stdout, stderr, code] = await Promise.all([
104
+ new Response(proc.stdout).text(),
105
+ new Response(proc.stderr).text(),
106
+ proc.exited,
107
+ ]);
108
+ clearTimeout(timer);
109
+ if (code !== 0) {
110
+ const detail = stderr.trim().split("\n").slice(-1)[0] ?? `exit ${code}`;
111
+ throw new Error(`whisper-cli failed: ${detail}`);
112
+ }
113
+ return { text: parseWhisperText(stdout), ms: Date.now() - started };
114
+ } finally {
115
+ rmSync(wavPath, { force: true });
116
+ }
117
+ }
@@ -20,7 +20,7 @@ import {
20
20
  readAndDeleteCmd, readStatus, updateStatus, writeStatus,
21
21
  STATUS_FILE, PID_FILE,
22
22
  } from "./supervisor-state.ts";
23
- import type { ResolvedTunnelConfig, TunnelMode } from "./named-tunnel/named-tunnel-config.ts";
23
+ import { resolveTunnelConfig, type ResolvedTunnelConfig, type TunnelMode } from "./named-tunnel/named-tunnel-config.ts";
24
24
  import { readTunnelConfigFresh, chooseTunnelSpawn } from "./named-tunnel/named-tunnel-runtime.ts";
25
25
  import { waitForLogLine } from "./named-tunnel/named-tunnel-readiness.ts";
26
26
  import { nextNamedRetryDelayMs } from "./named-tunnel/named-tunnel-retry.ts";
@@ -101,6 +101,11 @@ const TUNNEL_REGEN_MIN_INTERVAL_MS = 300_000; // 5min
101
101
  // cache, never `configService` (a separate process, stale here) nor a fresh
102
102
  // async DB read (would reorder the startup adopt/probe-before-spawn race).
103
103
  let namedTunnelMode: ResolvedTunnelConfig | null = null;
104
+ // Effective master switch: the argv flag AND `tunnel.enabled` from config.
105
+ // Module-level rather than a local because the SIGUSR1 and Windows-command
106
+ // handlers close over it before startup reaches the config read, and because
107
+ // `retunnel` flips it live when the user toggles the switch.
108
+ let tunnelSharingEnabled = false;
104
109
  // The mode of the tunnel actually spawned (as opposed to `namedTunnelMode`,
105
110
  // which is merely the persisted intent) — a token failure leaves config=named
106
111
  // but live=quick, and every status write / throttle / restart decision must
@@ -430,6 +435,26 @@ function restartTunnel(port: number) {
430
435
  spawnTunnel(port).catch((e) => log("ERROR", `restartTunnel failed: ${e}`));
431
436
  }
432
437
 
438
+ /**
439
+ * Tear the tunnel down for good because the master switch went off — as opposed
440
+ * to `restartTunnel`, which kills in order to respawn.
441
+ *
442
+ * Bumping the generation is the load-bearing part: the running spawn loop is
443
+ * awaiting its child's `exited` and would otherwise treat the kill as a crash
444
+ * and respawn. The probe needs no stopping — it returns early once there is no
445
+ * `tunnelUrl` and no live process.
446
+ */
447
+ function stopTunnelForDisable(): void {
448
+ tunnelGeneration++;
449
+ cancelNamedRetry();
450
+ namedRetryAttempt = 0;
451
+ if (tunnelChild) { try { tunnelChild.kill(); } catch {} tunnelChild = null; }
452
+ if (adoptedTunnelPid) { try { process.kill(adoptedTunnelPid, "SIGTERM"); } catch {} adoptedTunnelPid = null; }
453
+ tunnelUrl = null;
454
+ tunnelPort = null;
455
+ updateStatus({ shareUrl: null, tunnelPid: null, tunnelPort: null });
456
+ }
457
+
433
458
  // ─── Server shutdown ───────────────────────────────────────────────────
434
459
  // On Windows the server's Claude SDK grandchildren are node-spawned (the
435
460
  // provider forces `executable: "node"`), so they live OUTSIDE Bun's job
@@ -855,6 +880,14 @@ export async function spawnTunnel(port: number, generation: number = ++tunnelGen
855
880
  // setup, disable, or token rotation since the last spawn must be picked up
856
881
  // before deciding what to spawn next.
857
882
  namedTunnelMode = await readTunnelConfigFresh();
883
+ // The freshest possible view of the master switch, so consult it here rather than
884
+ // relying on all six call sites remembering to. Two of them — the Windows
885
+ // leaked-probe-handle restart and the edge probe's respawns — do not, and a
886
+ // respawn is exactly when a switch flipped since the last spawn should take hold.
887
+ if (!namedTunnelMode.enabled) {
888
+ log("INFO", "Public tunnel is switched off — not spawning cloudflared");
889
+ return;
890
+ }
858
891
 
859
892
  let bin: string;
860
893
  try {
@@ -1206,6 +1239,10 @@ async function probeNamedTunnelHealth(): Promise<boolean> {
1206
1239
  }
1207
1240
 
1208
1241
  function startTunnelProbe() {
1242
+ // Idempotent: a supervisor that booted with the tunnel switched off never
1243
+ // started this, and turning the switch on has to be able to start it then —
1244
+ // without leaving a second interval behind on the boots that did start it.
1245
+ if (tunnelProbeTimer) return;
1209
1246
  tunnelProbeTimer = setInterval(async () => {
1210
1247
  if (shuttingDown || !tunnelUrl) { tunnelFailCount = 0; return; }
1211
1248
  if (!tunnelChild && !adoptedTunnelPid) { tunnelFailCount = 0; return; }
@@ -2049,7 +2086,16 @@ export async function runSupervisor(opts: {
2049
2086
  // restarts the ladder so a later transient failure gets a full budget.
2050
2087
  cancelNamedRetry();
2051
2088
  namedRetryAttempt = 0;
2052
- restartTunnel(_opts.port);
2089
+ // `retunnel` is also how the master switch is applied without a
2090
+ // restart, so it has to be able to mean "stop" and not only "respawn".
2091
+ tunnelSharingEnabled = _opts.share && namedTunnelMode.enabled;
2092
+ if (tunnelSharingEnabled) {
2093
+ startTunnelProbe();
2094
+ restartTunnel(_opts.port);
2095
+ } else {
2096
+ log("INFO", "Tunnel switched off — tearing down the running tunnel");
2097
+ stopTunnelForDisable();
2098
+ }
2053
2099
  // Deliberate fall-through (no return): a bare `ppm restart` sends a
2054
2100
  // bare SIGUSR2 with no command file of its own, and a `retunnel` that
2055
2101
  // happens to still be unclaimed at that instant must not silently
@@ -2091,7 +2137,7 @@ export async function runSupervisor(opts: {
2091
2137
  log("ERROR", `Self-replace failed: ${result.error}, restarting children`);
2092
2138
  spawnServer(serverArgs, logFd);
2093
2139
  // Tunnel was kept alive during selfReplace; only respawn if dead
2094
- if (opts.share && !tunnelChild && !tunnelUrl) spawnTunnel(_opts.port);
2140
+ if (tunnelSharingEnabled && !tunnelChild && !tunnelUrl) spawnTunnel(_opts.port);
2095
2141
  }
2096
2142
  });
2097
2143
 
@@ -2200,7 +2246,16 @@ export async function runSupervisor(opts: {
2200
2246
  tunnelFailCount = 0;
2201
2247
  cancelNamedRetry();
2202
2248
  namedRetryAttempt = 0;
2203
- restartTunnel(_opts.port);
2249
+ // Same dual meaning as the POSIX path: this is how the master switch
2250
+ // is applied live, so it must also be able to mean "stop".
2251
+ tunnelSharingEnabled = _opts.share && cfg.enabled;
2252
+ if (tunnelSharingEnabled) {
2253
+ startTunnelProbe();
2254
+ restartTunnel(_opts.port);
2255
+ } else {
2256
+ log("INFO", "Tunnel switched off — tearing down the running tunnel");
2257
+ stopTunnelForDisable();
2258
+ }
2204
2259
  });
2205
2260
  }
2206
2261
  else if (cmd.action === "upgrade") {
@@ -2209,7 +2264,7 @@ export async function runSupervisor(opts: {
2209
2264
  if (!result.success) {
2210
2265
  log("ERROR", `Self-replace failed: ${result.error}, restarting children`);
2211
2266
  spawnServer(serverArgs, logFd);
2212
- if (opts.share && !tunnelChild && !tunnelUrl) spawnTunnel(_opts.port);
2267
+ if (tunnelSharingEnabled && !tunnelChild && !tunnelUrl) spawnTunnel(_opts.port);
2213
2268
  }
2214
2269
  });
2215
2270
  }
@@ -2229,12 +2284,34 @@ export async function runSupervisor(opts: {
2229
2284
  // tunnel's origin port (public URL continuity), so adoption state must be
2230
2285
  // settled first — the old order raced spawnServer's port selection.
2231
2286
  let tunnelAdopted = false;
2232
- if (opts.share) {
2233
- // Populate the cache BEFORE adoptTunnel/probe — an adopted tunnel skips
2234
- // spawnTunnel entirely for this whole generation, so without this the
2235
- // cache would stay null (adoptTunnel's named-hostname gate always refuses,
2236
- // and the probe can never tell named from quick) until the next spawn.
2287
+ // Populate the cache BEFORE adoptTunnel/probe — an adopted tunnel skips
2288
+ // spawnTunnel entirely for this whole generation, so without this the
2289
+ // cache would stay null (adoptTunnel's named-hostname gate always refuses,
2290
+ // and the probe can never tell named from quick) until the next spawn.
2291
+ // It also carries the master switch, so it is read before the gate rather
2292
+ // than inside it.
2293
+ // This read must not be able to decide whether the edge below gets spawned.
2294
+ // It already did once: a `systemctl restart` brought this process up while
2295
+ // the outgoing one still held the database's write lock, the rejection ended
2296
+ // startup right here, and PPM ran for eight minutes with nothing listening on
2297
+ // its public port — the server child came back on the health check, which has
2298
+ // no equivalent for an edge that was never started in the first place.
2299
+ //
2300
+ // The fallback is sharing OFF, not the resolver's default: an absent config
2301
+ // row means "on" (it predates the master switch), so defaulting would publish
2302
+ // a tunnel for someone who had switched sharing off and whose config merely
2303
+ // could not be read.
2304
+ try {
2237
2305
  namedTunnelMode = await readTunnelConfigFresh();
2306
+ } catch (e) {
2307
+ log("ERROR", `Tunnel config unreadable — continuing with sharing off: ${e}`);
2308
+ namedTunnelMode = resolveTunnelConfig({ enabled: false });
2309
+ }
2310
+ tunnelSharingEnabled = opts.share && namedTunnelMode.enabled;
2311
+ if (opts.share && !tunnelSharingEnabled) {
2312
+ log("INFO", "Tunnel off (tunnel.enabled = false) — no cloudflared will be started");
2313
+ }
2314
+ if (tunnelSharingEnabled) {
2238
2315
  // Defensive — already `false` at module init, but a fresh boot must never
2239
2316
  // start with an inherited restart-once budget "spent".
2240
2317
  namedProbeRestartAttempted = false;
@@ -2250,6 +2327,12 @@ export async function runSupervisor(opts: {
2250
2327
  // Sweep leftover cloudflared orphans (crashed supervisors / pre-fix stale
2251
2328
  // loops) so they don't saturate the network and false-trigger regeneration.
2252
2329
  await reapOrphanedTunnels(tunnelAdopted ? adoptedTunnelPid : null);
2330
+ } else if (opts.share) {
2331
+ // Switched off while a tunnel from an earlier boot is still alive: nothing
2332
+ // adopts or probes it now, so it would go on serving a stale origin with no
2333
+ // supervisor watching it.
2334
+ killStaleTunnel();
2335
+ await reapOrphanedTunnels(null);
2253
2336
  }
2254
2337
 
2255
2338
  // The edge owns the public port, so it must exist before anything else tries
@@ -2298,7 +2381,7 @@ export async function runSupervisor(opts: {
2298
2381
 
2299
2382
  // Spawn server + (fresh) tunnel in parallel
2300
2383
  const promises: Promise<void>[] = [spawnServer(serverArgs, logFd)];
2301
- if (opts.share && !tunnelAdopted) promises.push(spawnTunnel(_opts.port));
2384
+ if (tunnelSharingEnabled && !tunnelAdopted) promises.push(spawnTunnel(_opts.port));
2302
2385
 
2303
2386
  await Promise.all(promises);
2304
2387