@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,220 @@
1
+ /**
2
+ * CPU page — Mission Center's CPU tab.
3
+ *
4
+ * Two graphs, both of which the right-click menu re-points: the top one between
5
+ * overall utilisation, a grid of one graph per logical processor, and every
6
+ * thread overlaid or stacked; the bottom one between temperature, package power,
7
+ * clock speed and nothing at all. The menu is the feature — an i9's eight P-cores
8
+ * and eight E-cores behave nothing alike, and one averaged line hides that.
9
+ */
10
+ import { useMemo } from "react";
11
+ import { formatBytes } from "@/lib/format-bytes";
12
+ import { formatTemp } from "@/lib/temperature";
13
+ import { useSettingsStore } from "@/stores/settings-store";
14
+ import {
15
+ CPU_BOTTOM_GRAPHS, CPU_BOTTOM_LABELS, CPU_GRAPH_LABELS, CPU_GRAPH_MODES, historySpanLabel,
16
+ } from "@/lib/cpu-graph-mode";
17
+ import {
18
+ ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuRadioGroup, ContextMenuRadioItem,
19
+ ContextMenuSeparator, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger,
20
+ ContextMenuTrigger,
21
+ } from "@/components/ui/adaptive-context-menu";
22
+ import { CpuCoreGrid } from "./cpu-core-grid";
23
+ import { CHART_COLORS, DetailChart, DetailHeader, Stat, StatGrid, useSeries } from "./detail-parts";
24
+ import type { CpuInfo } from "../../../../types/system-hardware";
25
+ import type { CpuMetrics, MetricsHistoryPoint } from "../../../../types/system-metrics";
26
+
27
+ function uptime(seconds: number | undefined): string | undefined {
28
+ if (seconds === undefined) return undefined;
29
+ const d = Math.floor(seconds / 86400);
30
+ const h = Math.floor((seconds % 86400) / 3600);
31
+ const m = Math.floor((seconds % 3600) / 60);
32
+ return d > 0 ? `${d}d ${h}h ${m}m` : `${h}h ${m}m`;
33
+ }
34
+
35
+ const GHZ = (mhz: number | undefined) => (mhz === undefined ? undefined : `${(mhz / 1000).toFixed(2)} GHz`);
36
+
37
+ export function CpuDetail({
38
+ cpu, info, history, processCount,
39
+ }: {
40
+ cpu: CpuMetrics;
41
+ info?: CpuInfo;
42
+ history: readonly MetricsHistoryPoint[];
43
+ processCount?: number;
44
+ }) {
45
+ const tempUnit = useSettingsStore((s) => s.sysmonTempUnit);
46
+ const kernelTimes = useSettingsStore((s) => s.sysmonKernelTimes);
47
+ const setKernelTimes = useSettingsStore((s) => s.setSysmonKernelTimes);
48
+ const mode = useSettingsStore((s) => s.sysmonCpuGraph);
49
+ const setMode = useSettingsStore((s) => s.setSysmonCpuGraph);
50
+ const bottom = useSettingsStore((s) => s.sysmonCpuBottomGraph);
51
+ const setBottom = useSettingsStore((s) => s.setSysmonCpuBottomGraph);
52
+
53
+ const total = useSeries(history, (p) => p.system.cpu.total);
54
+ const kernel = useSeries(history, (p) => p.system.cpu.kernelPercent);
55
+ const tempSeries = useSeries(history, (p) => p.system.cpu.tempC);
56
+ const powerSeries = useSeries(history, (p) => p.system.cpu.powerW);
57
+ const clockSeries = useSeries(history, (p) => p.system.cpu.currentMHz);
58
+
59
+ // The kernel line is a SUBSET of the total and is only drawn where the host
60
+ // reports it — otherwise a flat zero line would read as "no kernel time". The
61
+ // preference can only take it away, never conjure one the host never sent.
62
+ const hasKernel = kernelTimes && cpu.kernelPercent !== undefined;
63
+ const span = historySpanLabel(history.map((p) => p.ts));
64
+ const caption = (what: string) => (span ? `${what} ${span}` : what);
65
+
66
+ // One pass over the window for every thread at once, shared by the overlaid and
67
+ // the stacked mode. Stacked divides by the thread count so the stack's top edge
68
+ // is the machine's overall utilisation rather than 2400%.
69
+ const threads = useMemo(() => {
70
+ const window = history.slice(-200);
71
+ const n = cpu.cores.length;
72
+ const out: number[][] = Array.from({ length: n }, () => []);
73
+ for (const point of window) {
74
+ const values = point.system.cpu.cores;
75
+ for (let i = 0; i < n; i++) out[i]!.push(values[i] ?? 0);
76
+ }
77
+ return out;
78
+ }, [history, cpu.cores.length]);
79
+
80
+ const threadSeries = threads.map((data) => ({ data, color: CHART_COLORS.primary }));
81
+ const stackedSeries = threads.map((data) => ({
82
+ data: data.map((v) => v / Math.max(1, threads.length)),
83
+ color: CHART_COLORS.primary,
84
+ }));
85
+
86
+ const bottomChart = () => {
87
+ if (bottom === "none") return null;
88
+ if (bottom === "temperature") {
89
+ if (cpu.tempC === undefined) return null;
90
+ return (
91
+ <DetailChart
92
+ grid
93
+ height={100}
94
+ caption={caption("Temperature")}
95
+ ceiling={formatTemp(Math.max(...tempSeries, 1), tempUnit)}
96
+ series={[{ data: tempSeries, color: CHART_COLORS.error }]}
97
+ />
98
+ );
99
+ }
100
+ if (bottom === "power") {
101
+ if (cpu.powerW === undefined) return null;
102
+ return (
103
+ <DetailChart
104
+ grid
105
+ height={100}
106
+ caption={caption("Power draw")}
107
+ ceiling={`${Math.max(...powerSeries, 1).toFixed(1)} W`}
108
+ series={[{ data: powerSeries, color: CHART_COLORS.secondary }]}
109
+ />
110
+ );
111
+ }
112
+ if (cpu.currentMHz === undefined) return null;
113
+ return (
114
+ <DetailChart
115
+ grid
116
+ height={100}
117
+ caption={caption("Clock speed")}
118
+ ceiling={GHZ(info?.maxMHz ?? Math.max(...clockSeries, 1))}
119
+ maxValue={info?.maxMHz}
120
+ series={[{ data: clockSeries, color: CHART_COLORS.success }]}
121
+ />
122
+ );
123
+ };
124
+
125
+ return (
126
+ <div className="space-y-4" data-testid="sysmon-detail-cpu">
127
+ <DetailHeader title="CPU" subtitle={info?.name ?? cpu.model} value={`${cpu.total.toFixed(1)}%`} />
128
+
129
+ <ContextMenu>
130
+ <ContextMenuTrigger>
131
+ <div className="space-y-3 select-none" data-testid="sysmon-cpu-graphs">
132
+ {mode === "logical" ? (
133
+ <div className="space-y-1">
134
+ <div className="flex items-baseline justify-between gap-2 text-[11px] text-text-subtle">
135
+ <span className="truncate">{caption("Utilisation")}</span>
136
+ <span className="shrink-0 tabular-nums">100%</span>
137
+ </div>
138
+ <CpuCoreGrid cores={cpu.cores} history={history} />
139
+ </div>
140
+ ) : (
141
+ <DetailChart
142
+ grid
143
+ maxValue={100}
144
+ caption={caption("Utilisation")}
145
+ ceiling="100%"
146
+ stacked={mode === "threads-stacked"}
147
+ legend={mode === "overall" && hasKernel ? ["Utilisation", "Kernel"] : undefined}
148
+ series={
149
+ mode === "threads" ? threadSeries
150
+ : mode === "threads-stacked" ? stackedSeries
151
+ : hasKernel
152
+ ? [{ data: total, color: CHART_COLORS.primary }, { data: kernel, color: CHART_COLORS.secondary }]
153
+ : [{ data: total, color: CHART_COLORS.primary }]
154
+ }
155
+ />
156
+ )}
157
+ {bottomChart()}
158
+ </div>
159
+ </ContextMenuTrigger>
160
+ <ContextMenuContent>
161
+ <ContextMenuSub>
162
+ <ContextMenuSubTrigger>Change top graph to</ContextMenuSubTrigger>
163
+ <ContextMenuSubContent>
164
+ <ContextMenuRadioGroup value={mode} onValueChange={(v) => setMode(v as typeof mode)}>
165
+ {CPU_GRAPH_MODES.map((m) => (
166
+ <ContextMenuRadioItem key={m} value={m} data-testid={`sysmon-cpu-graph-${m}`}>
167
+ {CPU_GRAPH_LABELS[m]}
168
+ </ContextMenuRadioItem>
169
+ ))}
170
+ </ContextMenuRadioGroup>
171
+ </ContextMenuSubContent>
172
+ </ContextMenuSub>
173
+ <ContextMenuSub>
174
+ <ContextMenuSubTrigger>Change bottom graph to</ContextMenuSubTrigger>
175
+ <ContextMenuSubContent>
176
+ <ContextMenuRadioGroup value={bottom} onValueChange={(v) => setBottom(v as typeof bottom)}>
177
+ {CPU_BOTTOM_GRAPHS.map((m) => (
178
+ <ContextMenuRadioItem key={m} value={m} data-testid={`sysmon-cpu-bottom-${m}`}>
179
+ {CPU_BOTTOM_LABELS[m]}
180
+ </ContextMenuRadioItem>
181
+ ))}
182
+ </ContextMenuRadioGroup>
183
+ </ContextMenuSubContent>
184
+ </ContextMenuSub>
185
+ <ContextMenuSeparator />
186
+ {/* A plain item rather than a checkbox one: the same switch is in
187
+ Preferences, and this is the place Mission Center puts it. */}
188
+ <ContextMenuItem
189
+ onSelect={() => setKernelTimes(!kernelTimes)}
190
+ data-testid="sysmon-cpu-kernel-toggle"
191
+ >
192
+ {kernelTimes ? "Hide kernel times" : "Show kernel times"}
193
+ </ContextMenuItem>
194
+ </ContextMenuContent>
195
+ </ContextMenu>
196
+
197
+ <StatGrid>
198
+ <Stat label="Speed" value={GHZ(cpu.currentMHz)} />
199
+ <Stat label="Base speed" value={GHZ(info?.baseMHz)} />
200
+ <Stat label="Max speed" value={GHZ(info?.maxMHz)} />
201
+ <Stat label="Temperature" value={formatTemp(cpu.tempC, tempUnit)} />
202
+ <Stat label="Power" value={cpu.powerW === undefined ? undefined : `${cpu.powerW.toFixed(1)} W`} />
203
+ <Stat label="Processes" value={processCount} />
204
+ <Stat label="Threads running" value={cpu.threadCount} />
205
+ <Stat label="Open handles" value={cpu.handleCount} />
206
+ <Stat label="Up time" value={uptime(cpu.uptimeSec)} />
207
+ <Stat label="Sockets" value={info?.sockets} />
208
+ <Stat label="Cores" value={info?.physicalCores} />
209
+ <Stat label="Logical processors" value={info?.logicalCores ?? cpu.cores.length} />
210
+ <Stat label="Virtualisation" value={info?.isVirtualMachine ? "Running in a VM" : info?.virtualization} />
211
+ <Stat label="L1 cache" value={info?.l1CacheBytes === undefined ? undefined : formatBytes(info.l1CacheBytes)} />
212
+ <Stat label="L2 cache" value={info?.l2CacheBytes === undefined ? undefined : formatBytes(info.l2CacheBytes)} />
213
+ <Stat label="L3 cache" value={info?.l3CacheBytes === undefined ? undefined : formatBytes(info.l3CacheBytes)} />
214
+ <Stat label="Cpufreq driver" value={info?.freqDriver} />
215
+ <Stat label="Governor" value={info?.freqGovernor} />
216
+ <Stat label="Power preference" value={info?.powerPreference} />
217
+ </StatGrid>
218
+ </div>
219
+ );
220
+ }
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Shared furniture for every Performance detail page, so the six of them differ
3
+ * only in which figures they name.
4
+ *
5
+ * The one rule they all obey: a figure this host cannot measure is `undefined` in
6
+ * the contract and renders as an em dash, never as 0. A zero is a claim.
7
+ */
8
+ import { useMemo, type ReactNode } from "react";
9
+ import { cn } from "@/lib/utils";
10
+ import { MetricChartCanvas, type MetricSeries } from "../metric-chart-canvas";
11
+ import type { MetricsHistoryPoint } from "../../../../types/system-metrics";
12
+
13
+ export interface DetailHeaderProps {
14
+ title: string;
15
+ subtitle?: string;
16
+ /** Headline figure, already formatted. */
17
+ value?: string;
18
+ valueClassName?: string;
19
+ }
20
+
21
+ export function DetailHeader({ title, subtitle, value, valueClassName }: DetailHeaderProps) {
22
+ return (
23
+ <div className="flex items-baseline justify-between gap-3">
24
+ <div className="min-w-0">
25
+ <h3 className="text-base font-semibold truncate">{title}</h3>
26
+ {subtitle && <p className="text-xs text-text-subtle truncate" title={subtitle}>{subtitle}</p>}
27
+ </div>
28
+ {value !== undefined && (
29
+ <span className={cn("text-2xl font-semibold tabular-nums shrink-0", valueClassName)}>{value}</span>
30
+ )}
31
+ </div>
32
+ );
33
+ }
34
+
35
+ /** Two columns on a phone, four on a wide window. Driven by the panel's OWN width
36
+ * (`@container`), because a floating window is routinely narrower than the screen. */
37
+ export function StatGrid({ children }: { children: ReactNode }) {
38
+ return <dl className="grid grid-cols-2 @2xl:grid-cols-4 gap-x-4 gap-y-3">{children}</dl>;
39
+ }
40
+
41
+ export interface StatProps {
42
+ label: string;
43
+ /** Undefined renders as an em dash: this host cannot measure it. */
44
+ value?: string | number | null;
45
+ title?: string;
46
+ }
47
+
48
+ export function Stat({ label, value, title }: StatProps) {
49
+ const text = value === undefined || value === null || value === "" ? "—" : String(value);
50
+ return (
51
+ <div className="min-w-0">
52
+ <dt className="text-[11px] text-text-subtle truncate">{label}</dt>
53
+ <dd className="text-sm tabular-nums truncate" title={title ?? text}>{text}</dd>
54
+ </div>
55
+ );
56
+ }
57
+
58
+ export interface DetailChartProps {
59
+ series: MetricSeries[];
60
+ /** Fixed ceiling, e.g. 100 for a percentage axis. Omitted autoscales. */
61
+ maxValue?: number;
62
+ height?: number;
63
+ /** One entry per series, in the same order. */
64
+ legend?: string[];
65
+ /** Mission Center's line above the graph — "Utilisation over 6 minutes". */
66
+ caption?: string;
67
+ /** What the top of the axis means, right-aligned opposite the caption. A graph
68
+ * with no stated ceiling is a shape, not a reading. */
69
+ ceiling?: string;
70
+ grid?: boolean;
71
+ stacked?: boolean;
72
+ }
73
+
74
+ export function DetailChart({
75
+ series, maxValue, height = 120, legend, caption, ceiling, grid, stacked,
76
+ }: DetailChartProps) {
77
+ return (
78
+ <div className="space-y-1">
79
+ {(caption || ceiling) && (
80
+ <div className="flex items-baseline justify-between gap-2 text-[11px] text-text-subtle">
81
+ <span className="truncate">{caption}</span>
82
+ <span className="shrink-0 tabular-nums">{ceiling}</span>
83
+ </div>
84
+ )}
85
+ <MetricChartCanvas
86
+ series={series}
87
+ height={height}
88
+ maxValue={maxValue}
89
+ grid={grid}
90
+ stacked={stacked}
91
+ />
92
+ {legend && legend.length > 0 && (
93
+ <div className="flex flex-wrap gap-x-4 gap-y-1">
94
+ {legend.map((label, i) => (
95
+ <span key={label} className="flex items-center gap-1.5 text-[11px] text-text-subtle">
96
+ <span className="size-2 rounded-full" style={{ background: series[i]?.color }} />
97
+ {label}
98
+ </span>
99
+ ))}
100
+ </div>
101
+ )}
102
+ </div>
103
+ );
104
+ }
105
+
106
+ /**
107
+ * One series out of the history window. `pick` returning undefined for a point
108
+ * contributes 0 rather than a gap — the canvas draws a continuous line, and a
109
+ * device that appeared midway through the window has no earlier readings to draw.
110
+ */
111
+ export function useSeries(
112
+ history: readonly MetricsHistoryPoint[],
113
+ pick: (point: MetricsHistoryPoint) => number | undefined,
114
+ points = 200,
115
+ ): number[] {
116
+ return useMemo(
117
+ () => history.slice(-points).map((p) => pick(p) ?? 0),
118
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- `pick` is written inline at every call site; only the data should retrigger
119
+ [history, points],
120
+ );
121
+ }
122
+
123
+ /** A proportional bar made of labelled segments — Mission Center's memory
124
+ * composition strip. Segments whose values do not add to the total are scaled to
125
+ * whatever they do add to, so the bar is never wider than its track. */
126
+ export function CompositionBar({ segments }: { segments: { label: string; value: number; color: string }[] }) {
127
+ const total = segments.reduce((sum, s) => sum + Math.max(0, s.value), 0);
128
+ if (total <= 0) return null;
129
+ return (
130
+ <div className="flex h-3 w-full overflow-hidden rounded-sm bg-surface-hover" role="img"
131
+ aria-label={segments.map((s) => s.label).join(", ")}>
132
+ {segments.map((s) => (
133
+ <div
134
+ key={s.label}
135
+ className="h-full"
136
+ style={{ width: `${(Math.max(0, s.value) / total) * 100}%`, background: s.color }}
137
+ title={s.label}
138
+ />
139
+ ))}
140
+ </div>
141
+ );
142
+ }
143
+
144
+ export const CHART_COLORS = {
145
+ primary: "var(--color-primary)",
146
+ secondary: "var(--color-warning)",
147
+ success: "var(--color-success)",
148
+ error: "var(--color-error)",
149
+ } as const;
@@ -0,0 +1,139 @@
1
+ /**
2
+ * The Performance page's device sidebar, as data - Mission Center's left column.
3
+ *
4
+ * Pure and React-free so the labelling and the summary figures are unit-tested
5
+ * without mounting anything. Imports are relative rather than through the "@"
6
+ * alias for the same reason: everything under `@/` risks reaching a zustand store,
7
+ * which reads localStorage at module scope and throws under bun:test.
8
+ */
9
+ import type { HardwareInventory, NicInfo, NicKind } from "../../../../types/system-hardware";
10
+ import type { SystemMetrics } from "../../../../types/system-metrics";
11
+ import { formatBps } from "../../../lib/format-bytes";
12
+
13
+ export type DeviceKind = "cpu" | "memory" | "disk" | "nic" | "gpu" | "fans";
14
+
15
+ export interface DeviceEntry {
16
+ /** Stable across ticks: the selection key and the React key. */
17
+ key: string;
18
+ kind: DeviceKind;
19
+ /** Sidebar title: "CPU", "Disk 0", "Ethernet". */
20
+ label: string;
21
+ /** Second line: the model or interface name. Empty when there is nothing to add. */
22
+ sublabel: string;
23
+ /** The metrics id this entry is keyed by (disk/nic/gpu), else null. */
24
+ id: string | null;
25
+ /** Right-hand summary: "12%", "21.0/62.5 GB", "1.2 MB/s". */
26
+ detail: string;
27
+ /** 0-100 for the row's mini bar. Null when the device has no percentage to show,
28
+ * which must render as no bar rather than as an empty one. */
29
+ percent: number | null;
30
+ }
31
+
32
+ /** Mission Center's interface names, in its own wording. */
33
+ export const NIC_KIND_LABELS: Record<NicKind, string> = {
34
+ wired: "Ethernet",
35
+ wireless: "Wi-Fi",
36
+ bluetooth: "Bluetooth",
37
+ bridge: "Bridge",
38
+ docker: "Docker",
39
+ infiniband: "InfiniBand",
40
+ multipass: "Multipass",
41
+ virtual: "Virtual",
42
+ vpn: "VPN",
43
+ other: "Other",
44
+ };
45
+
46
+ const GB = 1024;
47
+ const round = (n: number) => Math.round(n);
48
+
49
+ export function nicLabel(info: NicInfo | undefined): string {
50
+ return NIC_KIND_LABELS[info?.kind ?? "other"];
51
+ }
52
+
53
+ /**
54
+ * A NIC's bar is its share of the negotiated link speed. Null when the link speed
55
+ * is unknown - a tunnel or a virtual interface has no ceiling to be a share of,
56
+ * and a bar drawn against a guessed one is worse than no bar.
57
+ */
58
+ export function nicPercent(rxBps: number, txBps: number, linkMbps: number | undefined): number | null {
59
+ if (!linkMbps || linkMbps <= 0) return null;
60
+ const usedMbps = ((rxBps + txBps) * 8) / 1_000_000;
61
+ return Math.min(100, Math.max(0, (usedMbps / linkMbps) * 100));
62
+ }
63
+
64
+ export function memoryDetail(usedMB: number, totalMB: number): string {
65
+ return `${(usedMB / GB).toFixed(1)}/${(totalMB / GB).toFixed(1)} GB`;
66
+ }
67
+
68
+ /**
69
+ * Every device this host can show, in Mission Center's order: CPU, Memory, then
70
+ * the drives, the interfaces, the GPUs, and fans last.
71
+ *
72
+ * A device the tick did not report is absent rather than listed as zero - the
73
+ * per-device arrays are optional in the contract precisely because a host may not
74
+ * measure them at all.
75
+ */
76
+ export function buildDeviceList(system: SystemMetrics, inventory: HardwareInventory | null): DeviceEntry[] {
77
+ const diskInfo = new Map((inventory?.disks ?? []).map((d) => [d.id, d]));
78
+ const nicInfo = new Map((inventory?.nics ?? []).map((n) => [n.id, n]));
79
+ const entries: DeviceEntry[] = [
80
+ {
81
+ key: "cpu", kind: "cpu", label: "CPU", sublabel: system.cpu.model, id: null,
82
+ detail: `${round(system.cpu.total)}%`, percent: system.cpu.total,
83
+ },
84
+ {
85
+ key: "memory", kind: "memory", label: "Memory",
86
+ sublabel: memoryDetail(system.mem.usedMB, system.mem.totalMB), id: null,
87
+ detail: `${round(system.mem.percent)}%`, percent: system.mem.percent,
88
+ },
89
+ ];
90
+
91
+ (system.disks ?? []).forEach((disk, index) => {
92
+ entries.push({
93
+ key: `disk:${disk.id}`, kind: "disk", label: `Disk ${index}`,
94
+ sublabel: diskInfo.get(disk.id)?.model ?? disk.id, id: disk.id,
95
+ // "Active time" is the figure Mission Center puts in the sidebar, not
96
+ // throughput: a drive at 100% busy moving very little still matters.
97
+ detail: disk.available ? `${round(disk.busyPercent)}%` : "—",
98
+ percent: disk.available ? disk.busyPercent : null,
99
+ });
100
+ });
101
+
102
+ (system.nics ?? []).forEach((nic) => {
103
+ const info = nicInfo.get(nic.id);
104
+ entries.push({
105
+ key: `nic:${nic.id}`, kind: "nic", label: nicLabel(info), sublabel: nic.id, id: nic.id,
106
+ detail: nic.available ? formatBps(nic.rxBps + nic.txBps) : "—",
107
+ percent: nic.available ? nicPercent(nic.rxBps, nic.txBps, nic.linkMbps) : null,
108
+ });
109
+ });
110
+
111
+ system.gpus.forEach((gpu, index) => {
112
+ entries.push({
113
+ key: `gpu:${gpu.id ?? index}`, kind: "gpu", label: `GPU ${index}`,
114
+ sublabel: gpu.name, id: gpu.id ?? null,
115
+ detail: `${round(gpu.utilPercent)}%`, percent: gpu.utilPercent,
116
+ });
117
+ });
118
+
119
+ const fans = system.fans ?? [];
120
+ if (fans.length > 0) {
121
+ const fastest = Math.max(...fans.map((f) => f.rpm));
122
+ entries.push({
123
+ key: "fans", kind: "fans", label: "Fans",
124
+ sublabel: `${fans.length} sensor${fans.length === 1 ? "" : "s"}`, id: null,
125
+ detail: `${fastest} RPM`, percent: null,
126
+ });
127
+ }
128
+
129
+ return entries;
130
+ }
131
+
132
+ /**
133
+ * The entry to show when the previous selection is gone - a USB drive unplugged,
134
+ * an interface removed. Falls back to the CPU, which every host has.
135
+ */
136
+ export function resolveSelected(entries: readonly DeviceEntry[], wanted: string | null): string {
137
+ if (wanted && entries.some((e) => e.key === wanted)) return wanted;
138
+ return entries[0]?.key ?? "cpu";
139
+ }
@@ -0,0 +1,64 @@
1
+ /** One drive — Mission Center's per-disk page: active time, response time and the
2
+ * two transfer rates, over the static facts udev already knows. */
3
+ import { formatBps, formatBytes } from "@/lib/format-bytes";
4
+ import { formatTemp } from "@/lib/temperature";
5
+ import { useSettingsStore } from "@/stores/settings-store";
6
+ import { CHART_COLORS, DetailChart, DetailHeader, Stat, StatGrid, useSeries } from "./detail-parts";
7
+ import { PartitionList } from "./partition-list";
8
+ import type { DiskInfo } from "../../../../types/system-hardware";
9
+ import type { DiskMetrics, MetricsHistoryPoint } from "../../../../types/system-metrics";
10
+
11
+ const KIND_LABELS: Record<string, string> = {
12
+ hdd: "Hard disk", ssd: "SSD", nvme: "NVMe", emmc: "eMMC",
13
+ sd: "SD card", optical: "Optical", thumb: "Removable", unknown: "Unknown",
14
+ };
15
+
16
+ export function DiskDetail({
17
+ disk, info, index, history,
18
+ }: { disk: DiskMetrics; info?: DiskInfo; index: number; history: readonly MetricsHistoryPoint[] }) {
19
+ const tempUnit = useSettingsStore((s) => s.sysmonTempUnit);
20
+ const pick = (p: MetricsHistoryPoint) => p.system.disks?.find((d) => d.id === disk.id);
21
+ const busy = useSeries(history, (p) => pick(p)?.busyPercent);
22
+ const read = useSeries(history, (p) => pick(p)?.readBps);
23
+ const write = useSeries(history, (p) => pick(p)?.writeBps);
24
+
25
+ return (
26
+ <div className="space-y-4" data-testid="sysmon-detail-disk" data-disk-id={disk.id}>
27
+ <DetailHeader
28
+ title={`Disk ${index}`}
29
+ subtitle={info?.model ?? disk.id}
30
+ value={disk.available ? `${disk.busyPercent.toFixed(0)}%` : "—"}
31
+ />
32
+ <div className="space-y-1">
33
+ <p className="text-[11px] text-text-subtle">Active time</p>
34
+ <DetailChart maxValue={100} series={[{ data: busy, color: CHART_COLORS.primary }]} height={90} />
35
+ </div>
36
+ <div className="space-y-1">
37
+ <p className="text-[11px] text-text-subtle">Transfer rate</p>
38
+ <DetailChart
39
+ height={90}
40
+ legend={["Read", "Write"]}
41
+ series={[
42
+ { data: read, color: CHART_COLORS.success },
43
+ { data: write, color: CHART_COLORS.secondary },
44
+ ]}
45
+ />
46
+ </div>
47
+ <StatGrid>
48
+ <Stat label="Read speed" value={disk.available ? formatBps(disk.readBps) : undefined} />
49
+ <Stat label="Write speed" value={disk.available ? formatBps(disk.writeBps) : undefined} />
50
+ <Stat label="Avg. response time" value={disk.available ? `${disk.responseMs.toFixed(2)} ms` : undefined} />
51
+ <Stat label="Temperature" value={formatTemp(disk.tempC, tempUnit)} />
52
+ <Stat label="Total read" value={formatBytes(disk.readTotal)} />
53
+ <Stat label="Total written" value={formatBytes(disk.writeTotal)} />
54
+ <Stat label="Capacity" value={info === undefined ? undefined : formatBytes(info.capacityBytes)} />
55
+ <Stat label="Type" value={info === undefined ? undefined : KIND_LABELS[info.kind] ?? info.kind} />
56
+ <Stat label="System disk" value={info === undefined ? undefined : info.systemDisk ? "Yes" : "No"} />
57
+ <Stat label="Removable" value={info === undefined ? undefined : info.removable ? "Yes" : "No"} />
58
+ <Stat label="Rotation" value={info?.rotationRpm === undefined ? undefined : `${info.rotationRpm} RPM`} />
59
+ <Stat label="Serial" value={info?.serial} />
60
+ </StatGrid>
61
+ <PartitionList partitions={info?.partitions ?? []} />
62
+ </div>
63
+ );
64
+ }
@@ -0,0 +1,35 @@
1
+ /** Fans — Mission Center's Fan page. One row per tachometer, with the duty cycle
2
+ * and the temperature the same chip reports beside it. */
3
+ import { formatTemp } from "@/lib/temperature";
4
+ import { useSettingsStore } from "@/stores/settings-store";
5
+ import { DetailHeader, Stat, StatGrid } from "./detail-parts";
6
+ import type { FanMetrics } from "../../../../types/system-metrics";
7
+
8
+ export function FansDetail({ fans }: { fans: readonly FanMetrics[] }) {
9
+ const tempUnit = useSettingsStore((s) => s.sysmonTempUnit);
10
+ const fastest = fans.length > 0 ? Math.max(...fans.map((f) => f.rpm)) : 0;
11
+ return (
12
+ <div className="space-y-4" data-testid="sysmon-detail-fans" data-fan-count={fans.length}>
13
+ <DetailHeader
14
+ title="Fans"
15
+ subtitle={`${fans.length} sensor${fans.length === 1 ? "" : "s"}`}
16
+ value={`${fastest} RPM`}
17
+ />
18
+ <div className="rounded-md border border-border divide-y divide-border">
19
+ {fans.map((fan) => (
20
+ <div key={fan.id} className="px-3 py-2 space-y-2" data-testid="sysmon-fan-row">
21
+ <div className="flex items-baseline justify-between gap-3">
22
+ <span className="text-sm font-medium truncate" title={fan.id}>{fan.label}</span>
23
+ <span className="text-sm tabular-nums shrink-0">{fan.rpm} RPM</span>
24
+ </div>
25
+ <StatGrid>
26
+ <Stat label="Duty cycle" value={fan.pwmPercent === undefined ? undefined
27
+ : `${fan.pwmPercent.toFixed(0)}%`} />
28
+ <Stat label={fan.tempName ?? "Temperature"} value={formatTemp(fan.tempC, tempUnit)} />
29
+ </StatGrid>
30
+ </div>
31
+ ))}
32
+ </div>
33
+ </div>
34
+ );
35
+ }