@hienlh/ppm 0.23.5 → 0.23.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (714) hide show
  1. package/CHANGELOG.md +89 -0
  2. package/CLAUDE.md +21 -1
  3. package/Dockerfile.test +8 -1
  4. package/assets/skills/ppm/SKILL.md +1 -1
  5. package/assets/skills/ppm/references/cli-reference.md +4 -4
  6. package/assets/skills/ppm/references/http-api.md +30 -1
  7. package/dist/web/assets/accounts-settings-section-BYWnY9hH.js +1 -0
  8. package/dist/web/assets/accounts-settings-section-BYWnY9hH.js.br +0 -0
  9. package/dist/web/assets/accounts-settings-section-BYWnY9hH.js.gz +0 -0
  10. package/dist/web/assets/{ai-resource-editor-DKcsVDle.js → ai-resource-editor-CY4n_Ccv.js} +1 -1
  11. package/dist/web/assets/ai-resource-editor-CY4n_Ccv.js.br +0 -0
  12. package/dist/web/assets/ai-resource-editor-CY4n_Ccv.js.gz +0 -0
  13. package/dist/web/assets/ai-settings-section-Bs3iUW4j.js +1 -0
  14. package/dist/web/assets/ai-settings-section-Bs3iUW4j.js.br +0 -0
  15. package/dist/web/assets/ai-settings-section-Bs3iUW4j.js.gz +0 -0
  16. package/dist/web/assets/ai-settings-section-DDs11XV4.js +1 -0
  17. package/dist/web/assets/api-client-CJPnCOG-.js +1 -0
  18. package/dist/web/assets/{api-client-c8YOpTlT.js → api-client-D-SMbdiH.js} +1 -1
  19. package/dist/web/assets/api-client-D-SMbdiH.js.br +0 -0
  20. package/dist/web/assets/api-client-D-SMbdiH.js.gz +0 -0
  21. package/dist/web/assets/api-settings-BDkkhFMq.js +1 -0
  22. package/dist/web/assets/{api-settings-BmvNoCbn.js → api-settings-Bv9mLCty.js} +1 -1
  23. package/dist/web/assets/api-settings-Bv9mLCty.js.br +0 -0
  24. package/dist/web/assets/api-settings-Bv9mLCty.js.gz +0 -0
  25. package/dist/web/assets/{api-themes-6fOQJgM9.js → api-themes-3wW-zLzU.js} +1 -1
  26. package/dist/web/assets/appearance-settings-section-C0BoIBmz.js +1 -0
  27. package/dist/web/assets/appearance-settings-section-C0BoIBmz.js.br +0 -0
  28. package/dist/web/assets/appearance-settings-section-C0BoIBmz.js.gz +0 -0
  29. package/dist/web/assets/apps-panel-DXAFsveZ.js +1 -0
  30. package/dist/web/assets/apps-panel-DXAFsveZ.js.br +0 -0
  31. package/dist/web/assets/apps-panel-DXAFsveZ.js.gz +0 -0
  32. package/dist/web/assets/{audio-preview-vaG2cB-k.js → audio-preview-BfES4Cx5.js} +1 -1
  33. package/dist/web/assets/audio-preview-BfES4Cx5.js.br +0 -0
  34. package/dist/web/assets/audio-preview-BfES4Cx5.js.gz +0 -0
  35. package/dist/web/assets/branch-review-tab-CA8hPSX9.js +1 -0
  36. package/dist/web/assets/branch-review-tab-CA8hPSX9.js.br +0 -0
  37. package/dist/web/assets/branch-review-tab-CA8hPSX9.js.gz +0 -0
  38. package/dist/web/assets/{button-Ci9EUgqd.js → button-DeAyLH9U.js} +1 -1
  39. package/dist/web/assets/button-DeAyLH9U.js.br +0 -0
  40. package/dist/web/assets/button-DeAyLH9U.js.gz +0 -0
  41. package/dist/web/assets/{chat-preparation-cache-BSIQGiWx.js → chat-preparation-cache-CcCd2g7A.js} +1 -1
  42. package/dist/web/assets/chat-preparation-cache-CcCd2g7A.js.br +0 -0
  43. package/dist/web/assets/chat-preparation-cache-CcCd2g7A.js.gz +0 -0
  44. package/dist/web/assets/chat-tab-BWi_bUzA.js +1 -0
  45. package/dist/web/assets/chat-tab-BWi_bUzA.js.br +0 -0
  46. package/dist/web/assets/chat-tab-BWi_bUzA.js.gz +0 -0
  47. package/dist/web/assets/chat-tab-BvJhIaVE.js +15 -0
  48. package/dist/web/assets/chat-tab-BvJhIaVE.js.br +0 -0
  49. package/dist/web/assets/chat-tab-BvJhIaVE.js.gz +0 -0
  50. package/dist/web/assets/code-editor-OJUdLVnn.js +7 -0
  51. package/dist/web/assets/code-editor-OJUdLVnn.js.br +0 -0
  52. package/dist/web/assets/code-editor-OJUdLVnn.js.gz +0 -0
  53. package/dist/web/assets/codex-reset-credit-button-Dgxy_VNp.js +1 -0
  54. package/dist/web/assets/codex-reset-credit-button-Dgxy_VNp.js.br +0 -0
  55. package/dist/web/assets/codex-reset-credit-button-Dgxy_VNp.js.gz +0 -0
  56. package/dist/web/assets/{conflict-editor-qMGJH0Bx.js → conflict-editor-BpKW_vbL.js} +1 -1
  57. package/dist/web/assets/conflict-editor-BpKW_vbL.js.br +0 -0
  58. package/dist/web/assets/conflict-editor-BpKW_vbL.js.gz +0 -0
  59. package/dist/web/assets/context-menu-7OX80HDB.js +1 -0
  60. package/dist/web/assets/context-menu-7OX80HDB.js.br +0 -0
  61. package/dist/web/assets/context-menu-7OX80HDB.js.gz +0 -0
  62. package/dist/web/assets/{csv-preview-D2I742dl.js → csv-preview-COYdTABa.js} +1 -1
  63. package/dist/web/assets/csv-preview-COYdTABa.js.br +0 -0
  64. package/dist/web/assets/csv-preview-COYdTABa.js.gz +0 -0
  65. package/dist/web/assets/{data-grid-overlay-editor-CQRVKr7y.js → data-grid-overlay-editor-CeZoduke.js} +1 -1
  66. package/dist/web/assets/data-grid-overlay-editor-CeZoduke.js.br +0 -0
  67. package/dist/web/assets/data-grid-overlay-editor-CeZoduke.js.gz +0 -0
  68. package/dist/web/assets/{database-viewer-Bz4LjgIa.js → database-viewer-BQcBqCKm.js} +1 -1
  69. package/dist/web/assets/database-viewer-BQcBqCKm.js.br +0 -0
  70. package/dist/web/assets/database-viewer-BQcBqCKm.js.gz +0 -0
  71. package/dist/web/assets/{design-export-client-ChMcMoqW.js → design-export-client-OrnGCSwu.js} +1 -1
  72. package/dist/web/assets/design-export-client-OrnGCSwu.js.br +0 -0
  73. package/dist/web/assets/design-export-client-OrnGCSwu.js.gz +0 -0
  74. package/dist/web/assets/{design-responsive-dialog-DNBhJJLf.js → design-responsive-dialog-vJjQrC4n.js} +1 -1
  75. package/dist/web/assets/design-responsive-dialog-vJjQrC4n.js.br +0 -0
  76. package/dist/web/assets/design-responsive-dialog-vJjQrC4n.js.gz +0 -0
  77. package/dist/web/assets/design-tab-BbmFk38H.js +33 -0
  78. package/dist/web/assets/design-tab-BbmFk38H.js.br +0 -0
  79. package/dist/web/assets/design-tab-BbmFk38H.js.gz +0 -0
  80. package/dist/web/assets/{designs-sidebar-panel-CapP1yXq.js → designs-sidebar-panel-D2kXwB8B.js} +1 -1
  81. package/dist/web/assets/designs-sidebar-panel-D2kXwB8B.js.br +0 -0
  82. package/dist/web/assets/designs-sidebar-panel-D2kXwB8B.js.gz +0 -0
  83. package/dist/web/assets/dialog-Bocc0Fgb.js +1 -0
  84. package/dist/web/assets/dialog-Bocc0Fgb.js.br +0 -0
  85. package/dist/web/assets/dialog-Bocc0Fgb.js.gz +0 -0
  86. package/dist/web/assets/{diff-viewer-CdXi7cZN.js → diff-viewer-Bj4DT6Mj.js} +1 -1
  87. package/dist/web/assets/diff-viewer-Bj4DT6Mj.js.br +0 -0
  88. package/dist/web/assets/diff-viewer-Bj4DT6Mj.js.gz +0 -0
  89. package/dist/web/assets/{docx-preview-C9XdKEj1.js → docx-preview-C2QqNGRE.js} +1 -1
  90. package/dist/web/assets/docx-preview-C2QqNGRE.js.br +0 -0
  91. package/dist/web/assets/docx-preview-C2QqNGRE.js.gz +0 -0
  92. package/dist/web/assets/editor-language-service-COqB2tuv.js +1 -0
  93. package/dist/web/assets/editor-language-service-COqB2tuv.js.br +3 -0
  94. package/dist/web/assets/editor-language-service-COqB2tuv.js.gz +0 -0
  95. package/dist/web/assets/explorer-body-DGrYajDN.js +2 -0
  96. package/dist/web/assets/explorer-body-DGrYajDN.js.br +0 -0
  97. package/dist/web/assets/explorer-body-DGrYajDN.js.gz +0 -0
  98. package/dist/web/assets/explorer-window-content-DLzkODTP.js +1 -0
  99. package/dist/web/assets/explorer-window-content-DLzkODTP.js.br +0 -0
  100. package/dist/web/assets/explorer-window-content-DLzkODTP.js.gz +0 -0
  101. package/dist/web/assets/{extension-manager-section-B2nZzJ2b.js → extension-manager-section-Bu0qcB2i.js} +1 -1
  102. package/dist/web/assets/extension-manager-section-Bu0qcB2i.js.br +0 -0
  103. package/dist/web/assets/extension-manager-section-Bu0qcB2i.js.gz +0 -0
  104. package/dist/web/assets/{extension-webview-BGoDxkdF.js → extension-webview-G_WJ0N52.js} +1 -1
  105. package/dist/web/assets/extension-webview-G_WJ0N52.js.br +0 -0
  106. package/dist/web/assets/extension-webview-G_WJ0N52.js.gz +0 -0
  107. package/dist/web/assets/{file-icons-gx_FBOXY.js → file-icons-l7fNOmdS.js} +1 -1
  108. package/dist/web/assets/file-icons-l7fNOmdS.js.br +0 -0
  109. package/dist/web/assets/file-icons-l7fNOmdS.js.gz +0 -0
  110. package/dist/web/assets/{file-store-D9KE0kQC.js → file-store-B0e7sLag.js} +1 -1
  111. package/dist/web/assets/file-store-B0e7sLag.js.br +0 -0
  112. package/dist/web/assets/file-store-B0e7sLag.js.gz +0 -0
  113. package/dist/web/assets/{files-settings-section-DC3OzzOl.js → files-settings-section-ChZ_CynX.js} +1 -1
  114. package/dist/web/assets/files-settings-section-ChZ_CynX.js.br +0 -0
  115. package/dist/web/assets/files-settings-section-ChZ_CynX.js.gz +0 -0
  116. package/dist/web/assets/format-bytes-__396eCN.js +1 -0
  117. package/dist/web/assets/{format-file-meta-mQwA6SuY.js → format-file-meta-o1XBuoKS.js} +1 -1
  118. package/dist/web/assets/format-file-meta-o1XBuoKS.js.br +0 -0
  119. package/dist/web/assets/format-file-meta-o1XBuoKS.js.gz +0 -0
  120. package/dist/web/assets/{fs-api-DL36slbd.js → fs-api-CeHKwx95.js} +1 -1
  121. package/dist/web/assets/fs-api-CeHKwx95.js.br +0 -0
  122. package/dist/web/assets/fs-api-CeHKwx95.js.gz +0 -0
  123. package/dist/web/assets/{general-settings-section-i41W43ER.js → general-settings-section-MSvDEbFa.js} +1 -1
  124. package/dist/web/assets/general-settings-section-MSvDEbFa.js.br +0 -0
  125. package/dist/web/assets/general-settings-section-MSvDEbFa.js.gz +0 -0
  126. package/dist/web/assets/{git-log-panel-DHzPIkJg.js → git-log-panel-gw5_a6j3.js} +1 -1
  127. package/dist/web/assets/git-log-panel-gw5_a6j3.js.br +0 -0
  128. package/dist/web/assets/git-log-panel-gw5_a6j3.js.gz +0 -0
  129. package/dist/web/assets/{git-repo-store-DSypNj19.js → git-repo-store-BpPnah5l.js} +1 -1
  130. package/dist/web/assets/git-repo-store-BpPnah5l.js.br +0 -0
  131. package/dist/web/assets/git-repo-store-BpPnah5l.js.gz +0 -0
  132. package/dist/web/assets/{glide-data-grid-Dj4vrDvj.js → glide-data-grid-Db2Cl26B.js} +5 -5
  133. package/dist/web/assets/glide-data-grid-Db2Cl26B.js.br +0 -0
  134. package/dist/web/assets/glide-data-grid-Db2Cl26B.js.gz +0 -0
  135. package/dist/web/assets/group-chat-tab-B4etmYTR.js +1 -0
  136. package/dist/web/assets/group-chat-tab-B4etmYTR.js.br +0 -0
  137. package/dist/web/assets/group-chat-tab-B4etmYTR.js.gz +0 -0
  138. package/dist/web/assets/{image-preview-CGdZrmLo.js → image-preview-CjNhpfWw.js} +1 -1
  139. package/dist/web/assets/index-CtAvmybi.js +52 -0
  140. package/dist/web/assets/index-CtAvmybi.js.br +0 -0
  141. package/dist/web/assets/index-CtAvmybi.js.gz +0 -0
  142. package/dist/web/assets/index-DeCJasyy.css +1 -0
  143. package/dist/web/assets/index-DeCJasyy.css.br +0 -0
  144. package/dist/web/assets/index-DeCJasyy.css.gz +0 -0
  145. package/dist/web/assets/{jira-watcher-section-BJ9edGEP.js → jira-watcher-section-CKSI1Alo.js} +1 -1
  146. package/dist/web/assets/keybindings-store-C4_yyU4u.js +1 -0
  147. package/dist/web/assets/{keyboard-shortcuts-section-CxdGSNGr.js → keyboard-shortcuts-section-CEaVUc9a.js} +1 -1
  148. package/dist/web/assets/keyboard-shortcuts-section-CEaVUc9a.js.br +0 -0
  149. package/dist/web/assets/keyboard-shortcuts-section-CEaVUc9a.js.gz +0 -0
  150. package/dist/web/assets/language-servers-section-ePtEpnDc.js +2 -0
  151. package/dist/web/assets/language-servers-section-ePtEpnDc.js.br +0 -0
  152. package/dist/web/assets/language-servers-section-ePtEpnDc.js.gz +0 -0
  153. package/dist/web/assets/lsp-client-XzmR3Brr.js +1 -0
  154. package/dist/web/assets/lsp-client-XzmR3Brr.js.br +0 -0
  155. package/dist/web/assets/lsp-client-XzmR3Brr.js.gz +0 -0
  156. package/dist/web/assets/markdown-renderer-CTtDap-l.js +1 -0
  157. package/dist/web/assets/{markdown-renderer-ok96IgnS.js → markdown-renderer-D05fAr57.js} +2 -2
  158. package/dist/web/assets/markdown-renderer-D05fAr57.js.br +0 -0
  159. package/dist/web/assets/markdown-renderer-D05fAr57.js.gz +0 -0
  160. package/dist/web/assets/{media-url-CzUJrREv.js → media-url-C6NumuN5.js} +1 -1
  161. package/dist/web/assets/metric-chart-canvas-DHJe0VER.js +1 -0
  162. package/dist/web/assets/metric-chart-canvas-DHJe0VER.js.br +0 -0
  163. package/dist/web/assets/metric-chart-canvas-DHJe0VER.js.gz +0 -0
  164. package/dist/web/assets/{mobile-bottom-sheet-CuNi2FRv.js → mobile-bottom-sheet-D4UyOatB.js} +1 -1
  165. package/dist/web/assets/mobile-bottom-sheet-D4UyOatB.js.br +0 -0
  166. package/dist/web/assets/mobile-bottom-sheet-D4UyOatB.js.gz +0 -0
  167. package/dist/web/assets/mobile-explorer-sheet-CcfGdGL8.js +1 -0
  168. package/dist/web/assets/mobile-explorer-sheet-CcfGdGL8.js.br +0 -0
  169. package/dist/web/assets/mobile-explorer-sheet-CcfGdGL8.js.gz +0 -0
  170. package/dist/web/assets/{new-design-dialog-Drkjb_LI.js → new-design-dialog-BgmQopJM.js} +1 -1
  171. package/dist/web/assets/new-design-dialog-BgmQopJM.js.br +0 -0
  172. package/dist/web/assets/new-design-dialog-BgmQopJM.js.gz +0 -0
  173. package/dist/web/assets/notification-store-q5QBklKA.js +1 -0
  174. package/dist/web/assets/{notifications-settings-section-C05WYqcE.js → notifications-settings-section-BBJ0r9OS.js} +1 -1
  175. package/dist/web/assets/notifications-settings-section-BBJ0r9OS.js.br +0 -0
  176. package/dist/web/assets/notifications-settings-section-BBJ0r9OS.js.gz +0 -0
  177. package/dist/web/assets/{onboarding-entry-CmUqv1kl.js → onboarding-entry-BYOYswsi.js} +1 -1
  178. package/dist/web/assets/onboarding-entry-BYOYswsi.js.br +0 -0
  179. package/dist/web/assets/onboarding-entry-BYOYswsi.js.gz +0 -0
  180. package/dist/web/assets/{onboarding-quick-orientation-DIhWv1CN.js → onboarding-quick-orientation-DPHYFMbA.js} +1 -1
  181. package/dist/web/assets/onboarding-quick-orientation-DPHYFMbA.js.br +0 -0
  182. package/dist/web/assets/onboarding-quick-orientation-DPHYFMbA.js.gz +0 -0
  183. package/dist/web/assets/overview-panel-pkPs44Tv.js +1 -0
  184. package/dist/web/assets/overview-panel-pkPs44Tv.js.br +0 -0
  185. package/dist/web/assets/overview-panel-pkPs44Tv.js.gz +0 -0
  186. package/dist/web/assets/{pdf-preview-qdXmMkOR.js → pdf-preview-c-L_kDAs.js} +1 -1
  187. package/dist/web/assets/pdf-preview-c-L_kDAs.js.br +0 -0
  188. package/dist/web/assets/pdf-preview-c-L_kDAs.js.gz +0 -0
  189. package/dist/web/assets/performance-panel-yPrq0DJV.js +3 -0
  190. package/dist/web/assets/performance-panel-yPrq0DJV.js.br +0 -0
  191. package/dist/web/assets/performance-panel-yPrq0DJV.js.gz +0 -0
  192. package/dist/web/assets/{postgres-viewer-Xvlun_n5.js → postgres-viewer-CnwDCMNd.js} +1 -1
  193. package/dist/web/assets/postgres-viewer-CnwDCMNd.js.br +0 -0
  194. package/dist/web/assets/postgres-viewer-CnwDCMNd.js.gz +0 -0
  195. package/dist/web/assets/{ppmbot-settings-section-C8PFlvaq.js → ppmbot-settings-section-BDXoSIDp.js} +1 -1
  196. package/dist/web/assets/ppmbot-settings-section-BDXoSIDp.js.br +0 -0
  197. package/dist/web/assets/ppmbot-settings-section-BDXoSIDp.js.gz +0 -0
  198. package/dist/web/assets/{pptx-export-CG6MRNok.js → pptx-export-D0RDY48h.js} +4 -4
  199. package/dist/web/assets/pptx-export-D0RDY48h.js.br +0 -0
  200. package/dist/web/assets/pptx-export-D0RDY48h.js.gz +0 -0
  201. package/dist/web/assets/{problems-panel-CFYO0Ro3.js → problems-panel-BgY8oyo9.js} +1 -1
  202. package/dist/web/assets/problems-panel-BgY8oyo9.js.br +0 -0
  203. package/dist/web/assets/problems-panel-BgY8oyo9.js.gz +0 -0
  204. package/dist/web/assets/process-row-format-CaaMcHzn.js +1 -0
  205. package/dist/web/assets/process-table-BOwDtXuG.js +1 -0
  206. package/dist/web/assets/process-table-BOwDtXuG.js.br +0 -0
  207. package/dist/web/assets/process-table-BOwDtXuG.js.gz +0 -0
  208. package/dist/web/assets/{project-framework-store-XxFXcUpb.js → project-framework-store-UDEMu28U.js} +1 -1
  209. package/dist/web/assets/{project-store-C5gJXkvb.js → project-store-DGa31y5B.js} +1 -1
  210. package/dist/web/assets/project-store-DGa31y5B.js.br +0 -0
  211. package/dist/web/assets/project-store-DGa31y5B.js.gz +0 -0
  212. package/dist/web/assets/{proxy-settings-section-BcHIEANE.js → proxy-settings-section-Db6Kc6xG.js} +1 -1
  213. package/dist/web/assets/proxy-settings-section-Db6Kc6xG.js.br +0 -0
  214. package/dist/web/assets/proxy-settings-section-Db6Kc6xG.js.gz +0 -0
  215. package/dist/web/assets/{query-audit-section-UKG_smyt.js → query-audit-section-C0PAXhfT.js} +1 -1
  216. package/dist/web/assets/query-audit-section-C0PAXhfT.js.br +0 -0
  217. package/dist/web/assets/query-audit-section-C0PAXhfT.js.gz +0 -0
  218. package/dist/web/assets/{remote-desktop-clipboard-notice-BGsp0edA.js → remote-desktop-clipboard-notice-DOVtobj_.js} +1 -1
  219. package/dist/web/assets/remote-desktop-clipboard-notice-DOVtobj_.js.br +0 -0
  220. package/dist/web/assets/remote-desktop-clipboard-notice-DOVtobj_.js.gz +0 -0
  221. package/dist/web/assets/remote-desktop-mobile-sheet-DXlU3msM.js +2 -0
  222. package/dist/web/assets/remote-desktop-mobile-sheet-DXlU3msM.js.br +0 -0
  223. package/dist/web/assets/remote-desktop-mobile-sheet-DXlU3msM.js.gz +0 -0
  224. package/dist/web/assets/remote-desktop-mobile-view-ClV4YTLU.js +1 -0
  225. package/dist/web/assets/remote-desktop-mobile-view-ClV4YTLU.js.br +0 -0
  226. package/dist/web/assets/remote-desktop-mobile-view-ClV4YTLU.js.gz +0 -0
  227. package/dist/web/assets/{remote-desktop-readiness-gate-CsZCCRJI.js → remote-desktop-readiness-gate-BsfoJzdc.js} +1 -1
  228. package/dist/web/assets/remote-desktop-readiness-gate-BsfoJzdc.js.br +0 -0
  229. package/dist/web/assets/remote-desktop-readiness-gate-BsfoJzdc.js.gz +0 -0
  230. package/dist/web/assets/remote-desktop-window-content-kDaXl1_Q.js +1 -0
  231. package/dist/web/assets/remote-desktop-window-content-kDaXl1_Q.js.br +0 -0
  232. package/dist/web/assets/remote-desktop-window-content-kDaXl1_Q.js.gz +0 -0
  233. package/dist/web/assets/{schedules-settings-section-Ci0O2Ng6.js → schedules-settings-section-CvbjQM8z.js} +1 -1
  234. package/dist/web/assets/schedules-settings-section-CvbjQM8z.js.br +0 -0
  235. package/dist/web/assets/schedules-settings-section-CvbjQM8z.js.gz +0 -0
  236. package/dist/web/assets/{scroll-area-XonvWYn_.js → scroll-area-sjOeAfoD.js} +1 -1
  237. package/dist/web/assets/scroll-area-sjOeAfoD.js.br +0 -0
  238. package/dist/web/assets/scroll-area-sjOeAfoD.js.gz +0 -0
  239. package/dist/web/assets/{separator-sQj04Ari.js → separator-9A3PCG1t.js} +1 -1
  240. package/dist/web/assets/services-panel-CimW47P8.js +1 -0
  241. package/dist/web/assets/services-panel-CimW47P8.js.br +0 -0
  242. package/dist/web/assets/services-panel-CimW47P8.js.gz +0 -0
  243. package/dist/web/assets/settings-body-BTXNtpWL.js +2 -0
  244. package/dist/web/assets/settings-body-BTXNtpWL.js.br +0 -0
  245. package/dist/web/assets/settings-body-BTXNtpWL.js.gz +0 -0
  246. package/dist/web/assets/settings-store-DvftLqzy.js +2 -0
  247. package/dist/web/assets/settings-store-DvftLqzy.js.br +0 -0
  248. package/dist/web/assets/settings-store-DvftLqzy.js.gz +0 -0
  249. package/dist/web/assets/settings-tab-CGhaRXjs.js +1 -0
  250. package/dist/web/assets/settings-window-content--Uyg_Psr.js +1 -0
  251. package/dist/web/assets/sortable-header-DUW9T1Hz.js +1 -0
  252. package/dist/web/assets/sortable-header-DUW9T1Hz.js.br +0 -0
  253. package/dist/web/assets/sortable-header-DUW9T1Hz.js.gz +0 -0
  254. package/dist/web/assets/{sql-query-editor-4iCGE4h2.js → sql-query-editor-Dn-cgDrW.js} +1 -1
  255. package/dist/web/assets/sql-query-editor-Dn-cgDrW.js.br +0 -0
  256. package/dist/web/assets/sql-query-editor-Dn-cgDrW.js.gz +0 -0
  257. package/dist/web/assets/{sqlite-viewer-CK6DulYk.js → sqlite-viewer-B0NfaMjq.js} +1 -1
  258. package/dist/web/assets/sqlite-viewer-B0NfaMjq.js.br +0 -0
  259. package/dist/web/assets/sqlite-viewer-B0NfaMjq.js.gz +0 -0
  260. package/dist/web/assets/system-monitor-body-CxCfRQFb.js +2 -0
  261. package/dist/web/assets/system-monitor-body-CxCfRQFb.js.br +0 -0
  262. package/dist/web/assets/system-monitor-body-CxCfRQFb.js.gz +0 -0
  263. package/dist/web/assets/system-monitor-tab-Cb3EZUdp.js +1 -0
  264. package/dist/web/assets/system-monitor-window-content-51CA-2PH.js +1 -0
  265. package/dist/web/assets/{tab-host-window-content-CWBaWKjA.js → tab-host-window-content-CSrcmKNG.js} +1 -1
  266. package/dist/web/assets/tab-host-window-content-CSrcmKNG.js.br +0 -0
  267. package/dist/web/assets/tab-host-window-content-CSrcmKNG.js.gz +0 -0
  268. package/dist/web/assets/{team-member-sheet-Br6mrxrw.js → team-member-sheet-D4X6nh-x.js} +2 -2
  269. package/dist/web/assets/team-member-sheet-D4X6nh-x.js.br +0 -0
  270. package/dist/web/assets/team-member-sheet-D4X6nh-x.js.gz +0 -0
  271. package/dist/web/assets/{team-member-window-content-CwCy7ZWf.js → team-member-window-content-BxkbGVIL.js} +1 -1
  272. package/dist/web/assets/team-member-window-content-BxkbGVIL.js.br +0 -0
  273. package/dist/web/assets/team-member-window-content-BxkbGVIL.js.gz +0 -0
  274. package/dist/web/assets/{terminal-tab-BW14RpCb.js → terminal-tab-BYo34IqU.js} +3 -3
  275. package/dist/web/assets/terminal-tab-BYo34IqU.js.br +0 -0
  276. package/dist/web/assets/terminal-tab-BYo34IqU.js.gz +0 -0
  277. package/dist/web/assets/{tool-cards-CgOBEUnb.js → tool-cards-DvXjOped.js} +4 -4
  278. package/dist/web/assets/tool-cards-DvXjOped.js.br +0 -0
  279. package/dist/web/assets/tool-cards-DvXjOped.js.gz +0 -0
  280. package/dist/web/assets/{use-blob-url-CmavyEP8.js → use-blob-url-CISBWKG5.js} +1 -1
  281. package/dist/web/assets/use-inline-blame-Br6mheS4.js +16 -0
  282. package/dist/web/assets/use-inline-blame-Br6mheS4.js.br +0 -0
  283. package/dist/web/assets/use-inline-blame-Br6mheS4.js.gz +0 -0
  284. package/dist/web/assets/use-lsp-BpJmvQ0n.js +6 -0
  285. package/dist/web/assets/use-lsp-BpJmvQ0n.js.br +0 -0
  286. package/dist/web/assets/use-lsp-BpJmvQ0n.js.gz +0 -0
  287. package/dist/web/assets/{use-monaco-theme-rH6epJYA.js → use-monaco-theme-UGOzyIhv.js} +1 -1
  288. package/dist/web/assets/use-process-kill-CyiiUD1E.js +1 -0
  289. package/dist/web/assets/use-process-kill-CyiiUD1E.js.br +0 -0
  290. package/dist/web/assets/use-process-kill-CyiiUD1E.js.gz +0 -0
  291. package/dist/web/assets/{use-websocket-QwURkjpV.js → use-websocket-Dpl21cHG.js} +1 -1
  292. package/dist/web/assets/{vendor-ui-BHh12_0v.js → vendor-ui-P9Ym7hCv.js} +1 -1
  293. package/dist/web/assets/vendor-ui-P9Ym7hCv.js.br +0 -0
  294. package/dist/web/assets/vendor-ui-P9Ym7hCv.js.gz +0 -0
  295. package/dist/web/assets/video-preview-D6Jw-IZK.js +1 -0
  296. package/dist/web/assets/video-preview-D6Jw-IZK.js.br +0 -0
  297. package/dist/web/assets/video-preview-D6Jw-IZK.js.gz +0 -0
  298. package/dist/web/assets/voice-settings-section-CcHQDYzN.js +1 -0
  299. package/dist/web/assets/voice-settings-section-CcHQDYzN.js.br +0 -0
  300. package/dist/web/assets/voice-settings-section-CcHQDYzN.js.gz +0 -0
  301. package/dist/web/assets/ws-auth-CqI8-aoA.js +1 -0
  302. package/dist/web/index.html +20 -20
  303. package/dist/web/index.html.br +0 -0
  304. package/dist/web/index.html.gz +0 -0
  305. package/dist/web/sw.js +1 -1
  306. package/dist/web/sw.js.br +0 -0
  307. package/dist/web/sw.js.gz +0 -0
  308. package/docs/deployment-guide.md +23 -0
  309. package/package.json +1 -1
  310. package/release-from-worktree.sh +224 -0
  311. package/src/cli/commands/config-cmd.ts +12 -0
  312. package/src/providers/claude-agent-sdk.ts +65 -2
  313. package/src/providers/codex-app-server/codex-jsonrpc-client.ts +16 -1
  314. package/src/providers/codex-app-server/codex-provider.ts +39 -7
  315. package/src/providers/codex-app-server/codex-reset-credit.ts +49 -0
  316. package/src/providers/provider-probe.ts +63 -0
  317. package/src/providers/registry.ts +109 -29
  318. package/src/server/index.ts +9 -0
  319. package/src/server/middleware/auth.ts +5 -1
  320. package/src/server/routes/codex-accounts.ts +14 -0
  321. package/src/server/routes/cross-origin-guard.ts +20 -0
  322. package/src/server/routes/git.ts +40 -4
  323. package/src/server/routes/lsp.ts +97 -4
  324. package/src/server/routes/resources.ts +72 -9
  325. package/src/server/routes/settings.ts +19 -1
  326. package/src/server/routes/speech.ts +66 -0
  327. package/src/server/routes/system-services.ts +76 -0
  328. package/src/server/routes/tunnel.ts +33 -1
  329. package/src/server/ws/chat.ts +74 -3
  330. package/src/services/codex-account-login.ts +26 -2
  331. package/src/services/codex-reset-credit.service.ts +83 -0
  332. package/src/services/compaction-savings.ts +127 -0
  333. package/src/services/db.service.ts +123 -8
  334. package/src/services/edge-forwarder.ts +191 -191
  335. package/src/services/fs-ops/fs-ops-trash.service.ts +22 -9
  336. package/src/services/git-refs/for-each-ref.ts +118 -0
  337. package/src/services/git.service.ts +25 -2
  338. package/src/services/host-info/spawn-runner.ts +48 -4
  339. package/src/services/jsonl-transcript-parser.ts +7 -42
  340. package/src/services/lsp/lsp-install.ts +289 -0
  341. package/src/services/lsp/lsp-manager.ts +160 -29
  342. package/src/services/lsp/server-registry.ts +120 -4
  343. package/src/services/named-tunnel/named-tunnel-config.ts +8 -2
  344. package/src/services/named-tunnel/named-tunnel-setup.service.ts +4 -0
  345. package/src/services/read-lines.ts +54 -0
  346. package/src/services/speech-to-text/whisper-catalog.ts +142 -0
  347. package/src/services/speech-to-text/whisper-download.ts +113 -0
  348. package/src/services/speech-to-text/whisper-hallucinations.ts +51 -0
  349. package/src/services/speech-to-text/whisper-install.service.ts +247 -0
  350. package/src/services/speech-to-text/whisper-paths.ts +62 -0
  351. package/src/services/speech-to-text/whisper-transcribe.service.ts +117 -0
  352. package/src/services/supervisor.ts +94 -11
  353. package/src/services/system-metrics/cpu-details-linux.ts +252 -0
  354. package/src/services/system-metrics/cpu-memory-collector.ts +140 -18
  355. package/src/services/system-metrics/device-collector-linux.ts +31 -0
  356. package/src/services/system-metrics/device-collector-types.ts +40 -0
  357. package/src/services/system-metrics/disk-devices-linux.ts +156 -0
  358. package/src/services/system-metrics/disk-inventory-linux.ts +150 -0
  359. package/src/services/system-metrics/fans-linux.ts +51 -0
  360. package/src/services/system-metrics/gpu-api-versions.ts +120 -0
  361. package/src/services/system-metrics/gpu-devices-linux.ts +370 -0
  362. package/src/services/system-metrics/gpu-fdinfo-linux.ts +253 -0
  363. package/src/services/system-metrics/hardware-inventory.ts +50 -0
  364. package/src/services/system-metrics/linux-fs.ts +43 -0
  365. package/src/services/system-metrics/memory-darwin.ts +91 -0
  366. package/src/services/system-metrics/memory-linux.ts +156 -0
  367. package/src/services/system-metrics/net-devices-linux.ts +114 -0
  368. package/src/services/system-metrics/net-inventory-linux.ts +100 -0
  369. package/src/services/system-metrics/partitions-linux.ts +158 -0
  370. package/src/services/system-metrics/process-collector-linux.ts +58 -6
  371. package/src/services/system-metrics/process-collector-types.ts +8 -1
  372. package/src/services/system-metrics/process-details-darwin.ts +166 -0
  373. package/src/services/system-metrics/process-details-linux.ts +150 -0
  374. package/src/services/system-metrics/process-grouping.ts +2 -1
  375. package/src/services/system-metrics/process-rows-builder.ts +2 -0
  376. package/src/services/system-metrics/process-swap-linux.ts +37 -0
  377. package/src/services/system-metrics/signal-executor.ts +84 -0
  378. package/src/services/system-metrics/signal-request-handler.ts +92 -0
  379. package/src/services/system-metrics/system-metrics-platform.ts +30 -4
  380. package/src/services/system-metrics/system-metrics-tick.ts +73 -4
  381. package/src/services/system-metrics/system-metrics.service.ts +87 -2
  382. package/src/services/system-metrics/udev-db.ts +40 -0
  383. package/src/services/system-services/app-cgroup-linux.ts +115 -0
  384. package/src/services/system-services/app-icon-service.ts +31 -0
  385. package/src/services/system-services/app-icons-linux.ts +124 -0
  386. package/src/services/system-services/apps-linux.ts +174 -0
  387. package/src/services/system-services/desktop-entry.ts +103 -0
  388. package/src/services/system-services/service-guard.ts +124 -0
  389. package/src/services/system-services/systemd-collector.ts +203 -0
  390. package/src/services/system-services/systemd-parse.ts +162 -0
  391. package/src/services/windows-process-tree.ts +351 -351
  392. package/src/shared/prompt-cache-idle.ts +197 -0
  393. package/src/shared/turn-usage.ts +85 -1
  394. package/src/shared/usage-extra.ts +19 -0
  395. package/src/types/chat.ts +29 -0
  396. package/src/types/config.ts +14 -0
  397. package/src/types/git.ts +41 -0
  398. package/src/types/system-hardware.ts +137 -0
  399. package/src/types/system-metrics.ts +231 -2
  400. package/src/types/system-services.ts +73 -0
  401. package/src/web/components/branch-review/branch-review-tab.tsx +20 -20
  402. package/src/web/components/branch-review/branch-review-tree-row.tsx +1 -13
  403. package/src/web/components/chat/chat-tab.tsx +3 -0
  404. package/src/web/components/chat/codex-usage-panel.tsx +4 -0
  405. package/src/web/components/chat/compaction-divider.tsx +48 -0
  406. package/src/web/components/chat/idle-cache-notice.tsx +67 -0
  407. package/src/web/components/chat/message-input.tsx +48 -13
  408. package/src/web/components/chat/message-list.tsx +15 -0
  409. package/src/web/components/chat/prompt-cache-chip.tsx +74 -0
  410. package/src/web/components/editor/code-editor.tsx +1 -0
  411. package/src/web/components/editor/editor-language-service.tsx +11 -3
  412. package/src/web/components/editor/lsp-status.tsx +115 -13
  413. package/src/web/components/git/branch-picker.tsx +419 -0
  414. package/src/web/components/git/branch-select.tsx +34 -0
  415. package/src/web/components/git/create-worktree-dialog.tsx +17 -16
  416. package/src/web/components/git/git-repo-picker.tsx +28 -40
  417. package/src/web/components/layout/status-bar.tsx +42 -19
  418. package/src/web/components/settings/accounts/account-card.tsx +10 -2
  419. package/src/web/components/settings/accounts/account-usage-extras.tsx +3 -2
  420. package/src/web/components/settings/accounts/codex-accounts-section.tsx +3 -1
  421. package/src/web/components/settings/accounts/codex-reset-credit-button.tsx +120 -0
  422. package/src/web/components/settings/ai-settings-section.tsx +67 -3
  423. package/src/web/components/settings/appearance-settings-section.tsx +2 -28
  424. package/src/web/components/settings/language-servers-section.tsx +362 -0
  425. package/src/web/components/settings/settings-categories.ts +8 -3
  426. package/src/web/components/settings/settings-section-content.tsx +2 -0
  427. package/src/web/components/settings/voice-settings-section.tsx +283 -0
  428. package/src/web/components/system/apps/app-row.tsx +110 -0
  429. package/src/web/components/system/apps/app-rows.ts +140 -0
  430. package/src/web/components/system/apps/apps-panel.tsx +129 -0
  431. package/src/web/components/system/metric-chart-canvas.tsx +79 -3
  432. package/src/web/components/system/overview-cards/card-shell.tsx +54 -0
  433. package/src/web/components/system/overview-cards/cpu-card.tsx +11 -6
  434. package/src/web/components/system/overview-cards/disk-card.tsx +11 -6
  435. package/src/web/components/system/overview-cards/gpu-card.tsx +16 -6
  436. package/src/web/components/system/overview-cards/mem-card.tsx +11 -6
  437. package/src/web/components/system/overview-cards/net-card.tsx +11 -6
  438. package/src/web/components/system/overview-device-target.ts +69 -0
  439. package/src/web/components/system/overview-panel.tsx +15 -1
  440. package/src/web/components/system/performance/cpu-core-grid.tsx +74 -0
  441. package/src/web/components/system/performance/cpu-detail.tsx +220 -0
  442. package/src/web/components/system/performance/detail-parts.tsx +149 -0
  443. package/src/web/components/system/performance/device-list.ts +139 -0
  444. package/src/web/components/system/performance/disk-detail.tsx +64 -0
  445. package/src/web/components/system/performance/fans-detail.tsx +35 -0
  446. package/src/web/components/system/performance/gpu-detail.tsx +116 -0
  447. package/src/web/components/system/performance/memory-detail.tsx +109 -0
  448. package/src/web/components/system/performance/nic-detail.tsx +55 -0
  449. package/src/web/components/system/performance/partition-list.tsx +79 -0
  450. package/src/web/components/system/performance/performance-panel.tsx +206 -0
  451. package/src/web/components/system/performance/use-hardware-inventory.ts +48 -0
  452. package/src/web/components/system/process-columns-grid.ts +5 -3
  453. package/src/web/components/system/process-details-dialog.tsx +116 -0
  454. package/src/web/components/system/process-group-row.tsx +6 -1
  455. package/src/web/components/system/process-row-format.ts +6 -0
  456. package/src/web/components/system/process-row-menu.tsx +72 -0
  457. package/src/web/components/system/process-row.tsx +7 -1
  458. package/src/web/components/system/process-table-model.ts +1 -1
  459. package/src/web/components/system/process-table-sort.ts +8 -4
  460. package/src/web/components/system/process-table-toolbar.tsx +10 -2
  461. package/src/web/components/system/process-table-totals.ts +3 -0
  462. package/src/web/components/system/process-table.tsx +25 -2
  463. package/src/web/components/system/services/service-action-confirm.tsx +100 -0
  464. package/src/web/components/system/services/service-columns.ts +103 -0
  465. package/src/web/components/system/services/service-details-sheet.tsx +97 -0
  466. package/src/web/components/system/services/service-resources.ts +105 -0
  467. package/src/web/components/system/services/service-row.tsx +146 -0
  468. package/src/web/components/system/services/service-rows.ts +92 -0
  469. package/src/web/components/system/services/service-sort.ts +90 -0
  470. package/src/web/components/system/services/services-header.tsx +51 -0
  471. package/src/web/components/system/services/services-panel.tsx +207 -0
  472. package/src/web/components/system/services/use-services.ts +92 -0
  473. package/src/web/components/system/sortable-header.tsx +13 -8
  474. package/src/web/components/system/sysmon-preferences.tsx +85 -0
  475. package/src/web/components/system/system-monitor-body.tsx +101 -43
  476. package/src/web/components/system/system-monitor-window-content.tsx +2 -3
  477. package/src/web/components/system/use-process-signal.ts +87 -0
  478. package/src/web/components/tunnels/public-tunnel-switch.tsx +82 -0
  479. package/src/web/components/tunnels/tunnel-manager-tab.tsx +4 -0
  480. package/src/web/components/ui/dialog.tsx +14 -1
  481. package/src/web/components/ui/search-select.tsx +279 -0
  482. package/src/web/components/ui/start-ellipsis.tsx +18 -0
  483. package/src/web/hooks/use-chat.ts +28 -0
  484. package/src/web/hooks/use-global-keybindings.ts +7 -5
  485. package/src/web/hooks/use-lsp.ts +23 -2
  486. package/src/web/hooks/use-minute-clock.ts +20 -0
  487. package/src/web/hooks/use-whisper-voice-input.ts +113 -0
  488. package/src/web/lib/api-tunnels.ts +19 -0
  489. package/src/web/lib/branch-select-items.ts +29 -0
  490. package/src/web/lib/cpu-graph-mode.ts +90 -0
  491. package/src/web/lib/format-bytes.ts +14 -0
  492. package/src/web/lib/git-ref-picker.ts +120 -0
  493. package/src/web/lib/lsp/lsp-client.ts +32 -0
  494. package/src/web/lib/search-select-rows.ts +55 -0
  495. package/src/web/lib/temperature.ts +27 -0
  496. package/src/web/lib/voice-wav.ts +69 -0
  497. package/src/web/stores/git-status-store.ts +31 -17
  498. package/src/web/stores/keybindings-store.ts +14 -1
  499. package/src/web/stores/settings-store.ts +65 -0
  500. package/src/web/styles/globals.css +11 -0
  501. package/dist/web/assets/accounts-settings-section-CgG5P3Jm.js +0 -1
  502. package/dist/web/assets/accounts-settings-section-CgG5P3Jm.js.br +0 -0
  503. package/dist/web/assets/accounts-settings-section-CgG5P3Jm.js.gz +0 -0
  504. package/dist/web/assets/ai-resource-editor-DKcsVDle.js.br +0 -0
  505. package/dist/web/assets/ai-resource-editor-DKcsVDle.js.gz +0 -0
  506. package/dist/web/assets/ai-settings-section-D7zJ-hCO.js +0 -1
  507. package/dist/web/assets/ai-settings-section-D7zJ-hCO.js.br +0 -0
  508. package/dist/web/assets/ai-settings-section-D7zJ-hCO.js.gz +0 -0
  509. package/dist/web/assets/ai-settings-section-OPqC2bYG.js +0 -1
  510. package/dist/web/assets/api-client-BgedDTvo.js +0 -1
  511. package/dist/web/assets/api-client-c8YOpTlT.js.br +0 -0
  512. package/dist/web/assets/api-client-c8YOpTlT.js.gz +0 -0
  513. package/dist/web/assets/api-settings-BmvNoCbn.js.br +0 -0
  514. package/dist/web/assets/api-settings-BmvNoCbn.js.gz +0 -0
  515. package/dist/web/assets/api-settings-Bti1-Zn3.js +0 -1
  516. package/dist/web/assets/appearance-settings-section-DL466x83.js +0 -1
  517. package/dist/web/assets/appearance-settings-section-DL466x83.js.br +0 -0
  518. package/dist/web/assets/appearance-settings-section-DL466x83.js.gz +0 -0
  519. package/dist/web/assets/audio-preview-vaG2cB-k.js.br +0 -0
  520. package/dist/web/assets/audio-preview-vaG2cB-k.js.gz +0 -0
  521. package/dist/web/assets/branch-review-tab-Dag86n_R.js +0 -1
  522. package/dist/web/assets/branch-review-tab-Dag86n_R.js.br +0 -0
  523. package/dist/web/assets/branch-review-tab-Dag86n_R.js.gz +0 -0
  524. package/dist/web/assets/button-Ci9EUgqd.js.br +0 -0
  525. package/dist/web/assets/button-Ci9EUgqd.js.gz +0 -0
  526. package/dist/web/assets/chat-preparation-cache-BSIQGiWx.js.br +0 -0
  527. package/dist/web/assets/chat-preparation-cache-BSIQGiWx.js.gz +0 -0
  528. package/dist/web/assets/chat-tab-CcYZLXls.js +0 -15
  529. package/dist/web/assets/chat-tab-CcYZLXls.js.br +0 -0
  530. package/dist/web/assets/chat-tab-CcYZLXls.js.gz +0 -0
  531. package/dist/web/assets/chat-tab-QFDhzzBZ.js +0 -1
  532. package/dist/web/assets/chat-tab-QFDhzzBZ.js.br +0 -0
  533. package/dist/web/assets/chat-tab-QFDhzzBZ.js.gz +0 -0
  534. package/dist/web/assets/code-editor-K-IN8VwJ.js +0 -7
  535. package/dist/web/assets/code-editor-K-IN8VwJ.js.br +0 -0
  536. package/dist/web/assets/code-editor-K-IN8VwJ.js.gz +0 -0
  537. package/dist/web/assets/codex-sign-in-again-dialog-C8JvblLG.js +0 -1
  538. package/dist/web/assets/codex-sign-in-again-dialog-C8JvblLG.js.br +0 -0
  539. package/dist/web/assets/codex-sign-in-again-dialog-C8JvblLG.js.gz +0 -0
  540. package/dist/web/assets/conflict-editor-qMGJH0Bx.js.br +0 -0
  541. package/dist/web/assets/conflict-editor-qMGJH0Bx.js.gz +0 -0
  542. package/dist/web/assets/context-menu-CjYTq8DI.js +0 -1
  543. package/dist/web/assets/context-menu-CjYTq8DI.js.br +0 -0
  544. package/dist/web/assets/context-menu-CjYTq8DI.js.gz +0 -0
  545. package/dist/web/assets/csv-preview-D2I742dl.js.br +0 -0
  546. package/dist/web/assets/csv-preview-D2I742dl.js.gz +0 -0
  547. package/dist/web/assets/data-grid-overlay-editor-CQRVKr7y.js.br +0 -0
  548. package/dist/web/assets/data-grid-overlay-editor-CQRVKr7y.js.gz +0 -0
  549. package/dist/web/assets/database-viewer-Bz4LjgIa.js.br +0 -0
  550. package/dist/web/assets/database-viewer-Bz4LjgIa.js.gz +0 -0
  551. package/dist/web/assets/design-export-client-ChMcMoqW.js.br +0 -0
  552. package/dist/web/assets/design-export-client-ChMcMoqW.js.gz +0 -0
  553. package/dist/web/assets/design-responsive-dialog-DNBhJJLf.js.br +0 -0
  554. package/dist/web/assets/design-responsive-dialog-DNBhJJLf.js.gz +0 -0
  555. package/dist/web/assets/design-tab-C987MtMR.js +0 -33
  556. package/dist/web/assets/design-tab-C987MtMR.js.br +0 -0
  557. package/dist/web/assets/design-tab-C987MtMR.js.gz +0 -0
  558. package/dist/web/assets/designs-sidebar-panel-CapP1yXq.js.br +0 -0
  559. package/dist/web/assets/designs-sidebar-panel-CapP1yXq.js.gz +0 -0
  560. package/dist/web/assets/dialog-B8clVkyi.js +0 -1
  561. package/dist/web/assets/dialog-B8clVkyi.js.br +0 -0
  562. package/dist/web/assets/dialog-B8clVkyi.js.gz +0 -0
  563. package/dist/web/assets/diff-viewer-CdXi7cZN.js.br +0 -0
  564. package/dist/web/assets/diff-viewer-CdXi7cZN.js.gz +0 -0
  565. package/dist/web/assets/docx-preview-C9XdKEj1.js.br +0 -0
  566. package/dist/web/assets/docx-preview-C9XdKEj1.js.gz +0 -0
  567. package/dist/web/assets/editor-language-service-Zle_PZV8.js +0 -1
  568. package/dist/web/assets/editor-language-service-Zle_PZV8.js.br +0 -0
  569. package/dist/web/assets/editor-language-service-Zle_PZV8.js.gz +0 -0
  570. package/dist/web/assets/explorer-body-DHMQR1Rk.js +0 -2
  571. package/dist/web/assets/explorer-body-DHMQR1Rk.js.br +0 -0
  572. package/dist/web/assets/explorer-body-DHMQR1Rk.js.gz +0 -0
  573. package/dist/web/assets/explorer-window-content-Df40nQBk.js +0 -1
  574. package/dist/web/assets/explorer-window-content-Df40nQBk.js.br +0 -0
  575. package/dist/web/assets/explorer-window-content-Df40nQBk.js.gz +0 -0
  576. package/dist/web/assets/extension-manager-section-B2nZzJ2b.js.br +0 -0
  577. package/dist/web/assets/extension-manager-section-B2nZzJ2b.js.gz +0 -0
  578. package/dist/web/assets/extension-webview-BGoDxkdF.js.br +0 -0
  579. package/dist/web/assets/extension-webview-BGoDxkdF.js.gz +0 -0
  580. package/dist/web/assets/file-icons-gx_FBOXY.js.br +0 -0
  581. package/dist/web/assets/file-icons-gx_FBOXY.js.gz +0 -0
  582. package/dist/web/assets/file-store-D9KE0kQC.js.br +0 -0
  583. package/dist/web/assets/file-store-D9KE0kQC.js.gz +0 -0
  584. package/dist/web/assets/files-settings-section-DC3OzzOl.js.br +0 -0
  585. package/dist/web/assets/files-settings-section-DC3OzzOl.js.gz +0 -0
  586. package/dist/web/assets/format-bytes-DmSHAKFe.js +0 -1
  587. package/dist/web/assets/format-file-meta-mQwA6SuY.js.br +0 -0
  588. package/dist/web/assets/format-file-meta-mQwA6SuY.js.gz +0 -0
  589. package/dist/web/assets/fs-api-DL36slbd.js.br +0 -0
  590. package/dist/web/assets/fs-api-DL36slbd.js.gz +0 -0
  591. package/dist/web/assets/general-settings-section-i41W43ER.js.br +0 -0
  592. package/dist/web/assets/general-settings-section-i41W43ER.js.gz +0 -0
  593. package/dist/web/assets/git-log-panel-DHzPIkJg.js.br +0 -0
  594. package/dist/web/assets/git-log-panel-DHzPIkJg.js.gz +0 -0
  595. package/dist/web/assets/git-repo-store-DSypNj19.js.br +0 -0
  596. package/dist/web/assets/git-repo-store-DSypNj19.js.gz +0 -0
  597. package/dist/web/assets/glide-data-grid-Dj4vrDvj.js.br +0 -0
  598. package/dist/web/assets/glide-data-grid-Dj4vrDvj.js.gz +0 -0
  599. package/dist/web/assets/group-chat-tab-DfwZb-fI.js +0 -1
  600. package/dist/web/assets/group-chat-tab-DfwZb-fI.js.br +0 -0
  601. package/dist/web/assets/group-chat-tab-DfwZb-fI.js.gz +0 -0
  602. package/dist/web/assets/index-DMA-So69.css +0 -1
  603. package/dist/web/assets/index-DMA-So69.css.br +0 -0
  604. package/dist/web/assets/index-DMA-So69.css.gz +0 -0
  605. package/dist/web/assets/index-jG9mLs-J.js +0 -52
  606. package/dist/web/assets/index-jG9mLs-J.js.br +0 -0
  607. package/dist/web/assets/index-jG9mLs-J.js.gz +0 -0
  608. package/dist/web/assets/keybindings-store-BlapkC6O.js +0 -1
  609. package/dist/web/assets/keyboard-shortcuts-section-CxdGSNGr.js.br +0 -0
  610. package/dist/web/assets/keyboard-shortcuts-section-CxdGSNGr.js.gz +0 -0
  611. package/dist/web/assets/markdown-renderer-DJ9EVU1B.js +0 -1
  612. package/dist/web/assets/markdown-renderer-ok96IgnS.js.br +0 -0
  613. package/dist/web/assets/markdown-renderer-ok96IgnS.js.gz +0 -0
  614. package/dist/web/assets/mobile-bottom-sheet-CuNi2FRv.js.br +0 -0
  615. package/dist/web/assets/mobile-bottom-sheet-CuNi2FRv.js.gz +0 -0
  616. package/dist/web/assets/mobile-explorer-sheet-Cc03LUKy.js +0 -1
  617. package/dist/web/assets/mobile-explorer-sheet-Cc03LUKy.js.br +0 -0
  618. package/dist/web/assets/mobile-explorer-sheet-Cc03LUKy.js.gz +0 -0
  619. package/dist/web/assets/new-design-dialog-Drkjb_LI.js.br +0 -0
  620. package/dist/web/assets/new-design-dialog-Drkjb_LI.js.gz +0 -0
  621. package/dist/web/assets/notification-store-DCyxho0O.js +0 -1
  622. package/dist/web/assets/notifications-settings-section-C05WYqcE.js.br +0 -0
  623. package/dist/web/assets/notifications-settings-section-C05WYqcE.js.gz +0 -0
  624. package/dist/web/assets/onboarding-entry-CmUqv1kl.js.br +0 -0
  625. package/dist/web/assets/onboarding-entry-CmUqv1kl.js.gz +0 -0
  626. package/dist/web/assets/onboarding-quick-orientation-DIhWv1CN.js.br +0 -0
  627. package/dist/web/assets/onboarding-quick-orientation-DIhWv1CN.js.gz +0 -0
  628. package/dist/web/assets/overview-panel-BZAW_nag.js +0 -1
  629. package/dist/web/assets/overview-panel-BZAW_nag.js.br +0 -0
  630. package/dist/web/assets/overview-panel-BZAW_nag.js.gz +0 -0
  631. package/dist/web/assets/pdf-preview-qdXmMkOR.js.br +0 -0
  632. package/dist/web/assets/pdf-preview-qdXmMkOR.js.gz +0 -0
  633. package/dist/web/assets/postgres-viewer-Xvlun_n5.js.br +0 -0
  634. package/dist/web/assets/postgres-viewer-Xvlun_n5.js.gz +0 -0
  635. package/dist/web/assets/ppmbot-settings-section-C8PFlvaq.js.br +0 -0
  636. package/dist/web/assets/ppmbot-settings-section-C8PFlvaq.js.gz +0 -0
  637. package/dist/web/assets/pptx-export-CG6MRNok.js.br +0 -0
  638. package/dist/web/assets/pptx-export-CG6MRNok.js.gz +0 -0
  639. package/dist/web/assets/problems-panel-CFYO0Ro3.js.br +0 -0
  640. package/dist/web/assets/problems-panel-CFYO0Ro3.js.gz +0 -0
  641. package/dist/web/assets/process-table-BVeRguFg.js +0 -1
  642. package/dist/web/assets/process-table-BVeRguFg.js.br +0 -0
  643. package/dist/web/assets/process-table-BVeRguFg.js.gz +0 -0
  644. package/dist/web/assets/project-store-C5gJXkvb.js.br +0 -0
  645. package/dist/web/assets/project-store-C5gJXkvb.js.gz +0 -0
  646. package/dist/web/assets/proxy-settings-section-BcHIEANE.js.br +0 -0
  647. package/dist/web/assets/proxy-settings-section-BcHIEANE.js.gz +0 -0
  648. package/dist/web/assets/query-audit-section-UKG_smyt.js.br +0 -0
  649. package/dist/web/assets/query-audit-section-UKG_smyt.js.gz +0 -0
  650. package/dist/web/assets/remote-desktop-clipboard-notice-BGsp0edA.js.br +0 -0
  651. package/dist/web/assets/remote-desktop-clipboard-notice-BGsp0edA.js.gz +0 -0
  652. package/dist/web/assets/remote-desktop-mobile-sheet-DxkmF8qb.js +0 -2
  653. package/dist/web/assets/remote-desktop-mobile-sheet-DxkmF8qb.js.br +0 -0
  654. package/dist/web/assets/remote-desktop-mobile-sheet-DxkmF8qb.js.gz +0 -0
  655. package/dist/web/assets/remote-desktop-mobile-view-DMD0M9Jh.js +0 -1
  656. package/dist/web/assets/remote-desktop-mobile-view-DMD0M9Jh.js.br +0 -0
  657. package/dist/web/assets/remote-desktop-mobile-view-DMD0M9Jh.js.gz +0 -0
  658. package/dist/web/assets/remote-desktop-readiness-gate-CsZCCRJI.js.br +0 -0
  659. package/dist/web/assets/remote-desktop-readiness-gate-CsZCCRJI.js.gz +0 -0
  660. package/dist/web/assets/remote-desktop-window-content-DrHw_vwY.js +0 -1
  661. package/dist/web/assets/remote-desktop-window-content-DrHw_vwY.js.br +0 -0
  662. package/dist/web/assets/remote-desktop-window-content-DrHw_vwY.js.gz +0 -0
  663. package/dist/web/assets/schedules-settings-section-Ci0O2Ng6.js.br +0 -0
  664. package/dist/web/assets/schedules-settings-section-Ci0O2Ng6.js.gz +0 -0
  665. package/dist/web/assets/scroll-area-XonvWYn_.js.br +0 -0
  666. package/dist/web/assets/scroll-area-XonvWYn_.js.gz +0 -0
  667. package/dist/web/assets/settings-body-B6JGOIYb.js +0 -2
  668. package/dist/web/assets/settings-body-B6JGOIYb.js.br +0 -0
  669. package/dist/web/assets/settings-body-B6JGOIYb.js.gz +0 -0
  670. package/dist/web/assets/settings-store-Br5c1efC.js +0 -2
  671. package/dist/web/assets/settings-store-Br5c1efC.js.br +0 -0
  672. package/dist/web/assets/settings-store-Br5c1efC.js.gz +0 -0
  673. package/dist/web/assets/settings-tab-CIQM4fNE.js +0 -1
  674. package/dist/web/assets/settings-window-content-BGNNz-E5.js +0 -1
  675. package/dist/web/assets/sql-query-editor-4iCGE4h2.js.br +0 -3
  676. package/dist/web/assets/sql-query-editor-4iCGE4h2.js.gz +0 -0
  677. package/dist/web/assets/sqlite-viewer-CK6DulYk.js.br +0 -0
  678. package/dist/web/assets/sqlite-viewer-CK6DulYk.js.gz +0 -0
  679. package/dist/web/assets/system-monitor-body-J9JtvAWV.js +0 -2
  680. package/dist/web/assets/system-monitor-body-J9JtvAWV.js.br +0 -0
  681. package/dist/web/assets/system-monitor-body-J9JtvAWV.js.gz +0 -0
  682. package/dist/web/assets/system-monitor-tab-DjBeRE81.js +0 -1
  683. package/dist/web/assets/system-monitor-window-content-BT7-ugFx.js +0 -1
  684. package/dist/web/assets/tab-host-window-content-CWBaWKjA.js.br +0 -0
  685. package/dist/web/assets/tab-host-window-content-CWBaWKjA.js.gz +0 -0
  686. package/dist/web/assets/team-member-sheet-Br6mrxrw.js.br +0 -0
  687. package/dist/web/assets/team-member-sheet-Br6mrxrw.js.gz +0 -0
  688. package/dist/web/assets/team-member-window-content-CwCy7ZWf.js.br +0 -0
  689. package/dist/web/assets/team-member-window-content-CwCy7ZWf.js.gz +0 -0
  690. package/dist/web/assets/terminal-tab-BW14RpCb.js.br +0 -0
  691. package/dist/web/assets/terminal-tab-BW14RpCb.js.gz +0 -0
  692. package/dist/web/assets/tool-cards-CgOBEUnb.js.br +0 -0
  693. package/dist/web/assets/tool-cards-CgOBEUnb.js.gz +0 -0
  694. package/dist/web/assets/use-inline-blame-Bzjfru4n.js +0 -16
  695. package/dist/web/assets/use-inline-blame-Bzjfru4n.js.br +0 -0
  696. package/dist/web/assets/use-inline-blame-Bzjfru4n.js.gz +0 -0
  697. package/dist/web/assets/use-lsp-hGdjL2hV.js +0 -6
  698. package/dist/web/assets/use-lsp-hGdjL2hV.js.br +0 -0
  699. package/dist/web/assets/use-lsp-hGdjL2hV.js.gz +0 -0
  700. package/dist/web/assets/vendor-ui-BHh12_0v.js.br +0 -0
  701. package/dist/web/assets/vendor-ui-BHh12_0v.js.gz +0 -0
  702. package/dist/web/assets/video-preview-P9T-ZVdN.js +0 -1
  703. package/dist/web/assets/video-preview-P9T-ZVdN.js.br +0 -0
  704. package/dist/web/assets/video-preview-P9T-ZVdN.js.gz +0 -0
  705. package/dist/web/assets/ws-auth-kXgsX2Js.js +0 -1
  706. package/packages/vscode-compat/node_modules/.bin/tsc.bunx +0 -0
  707. package/packages/vscode-compat/node_modules/.bin/tsc.exe +0 -0
  708. package/packages/vscode-compat/node_modules/.bin/tsserver.bunx +0 -0
  709. package/packages/vscode-compat/node_modules/.bin/tsserver.exe +0 -0
  710. /package/dist/web/assets/{__vite-browser-external-BpSQWxcq.js → __vite-browser-external-BILfYaAs.js} +0 -0
  711. /package/dist/web/assets/{run-in-terminal-HIdNgYim.js → run-in-terminal-2pSiup8e.js} +0 -0
  712. /package/dist/web/assets/{vendor-xterm-DLDtzLib.js → vendor-xterm-DF1JTfsy.js} +0 -0
  713. /package/dist/web/assets/{vendor-xterm-DLDtzLib.js.br → vendor-xterm-DF1JTfsy.js.br} +0 -0
  714. /package/dist/web/assets/{vendor-xterm-DLDtzLib.js.gz → vendor-xterm-DF1JTfsy.js.gz} +0 -0
@@ -0,0 +1,116 @@
1
+ /** One GPU — Mission Center's GPU page: three graphs (utilisation, video
2
+ * encode/decode, memory usage) over the driver's static facts. Every row here is
3
+ * optional in the contract: a driver that publishes no clock or no power reports
4
+ * nothing rather than zero, so the row shows an em dash. */
5
+ import { formatRam } from "@/lib/format-bytes";
6
+ import { historySpanLabel } from "@/lib/cpu-graph-mode";
7
+ import { formatTemp } from "@/lib/temperature";
8
+ import { useSettingsStore } from "@/stores/settings-store";
9
+ import { CHART_COLORS, DetailChart, DetailHeader, Stat, StatGrid, useSeries } from "./detail-parts";
10
+ import type { GpuInfo } from "../../../../types/system-metrics";
11
+ import type { GpuMetrics, MetricsHistoryPoint } from "../../../../types/system-metrics";
12
+
13
+ function pcie(gen: number | undefined, lanes: number | undefined): string | undefined {
14
+ if (gen === undefined && lanes === undefined) return undefined;
15
+ return `${gen === undefined ? "?" : `Gen ${gen}`} x${lanes ?? "?"}`;
16
+ }
17
+
18
+ export function GpuDetail({
19
+ gpu, info, index, history,
20
+ }: { gpu: GpuMetrics; info?: GpuInfo; index: number; history: readonly MetricsHistoryPoint[] }) {
21
+ const tempUnit = useSettingsStore((s) => s.sysmonTempUnit);
22
+ const pick = (p: MetricsHistoryPoint) =>
23
+ p.system.gpus.find((g) => (gpu.id ? g.id === gpu.id : g.name === gpu.name));
24
+ const util = useSeries(history, (p) => pick(p)?.utilPercent);
25
+ const encode = useSeries(history, (p) => pick(p)?.encodePercent);
26
+ const decode = useSeries(history, (p) => pick(p)?.decodePercent);
27
+ // Dedicated memory where the card has some, its share of system RAM where it
28
+ // does not — the two are never both drawn, because they are the same graph
29
+ // answering "how much memory is this GPU using" from whichever source exists.
30
+ const hasVram = gpu.vramTotalMB > 0;
31
+ const hasShared = !hasVram && gpu.sharedTotalMB !== undefined;
32
+ const memory = useSeries(history, (p) => {
33
+ const g = pick(p);
34
+ return hasVram ? g?.vramUsedMB : g?.sharedUsedMB;
35
+ });
36
+ const memoryTotalMB = hasVram ? gpu.vramTotalMB : gpu.sharedTotalMB ?? 0;
37
+
38
+ const hasVideo = gpu.encodePercent !== undefined || gpu.decodePercent !== undefined;
39
+ // Intel runs one engine for both directions, so there is one series with the
40
+ // combined label rather than a decode line that would always trace the encode.
41
+ const videoShared = info?.encodeDecodeShared === true;
42
+ const span = historySpanLabel(history.map((p) => p.ts));
43
+ const caption = (what: string) => (span ? `${what} ${span}` : what);
44
+
45
+ return (
46
+ <div className="space-y-4" data-testid="sysmon-detail-gpu" data-gpu-id={gpu.id ?? index}>
47
+ <DetailHeader title={`GPU ${index}`} subtitle={gpu.name} value={`${gpu.utilPercent.toFixed(0)}%`} />
48
+
49
+ <DetailChart
50
+ grid
51
+ maxValue={100}
52
+ caption={caption("Utilisation")}
53
+ ceiling="100%"
54
+ series={[{ data: util, color: CHART_COLORS.primary }]}
55
+ />
56
+
57
+ {hasVideo && (
58
+ <DetailChart
59
+ grid
60
+ height={90}
61
+ maxValue={100}
62
+ caption={caption(videoShared ? "Video encode/decode utilisation" : "Video encode and decode utilisation")}
63
+ ceiling="100%"
64
+ legend={videoShared ? undefined : ["Encode", "Decode"]}
65
+ series={videoShared
66
+ ? [{ data: encode, color: CHART_COLORS.secondary }]
67
+ : [
68
+ { data: encode, color: CHART_COLORS.secondary },
69
+ { data: decode, color: CHART_COLORS.error },
70
+ ]}
71
+ />
72
+ )}
73
+
74
+ {(hasVram || hasShared) && (
75
+ <DetailChart
76
+ grid
77
+ height={90}
78
+ maxValue={memoryTotalMB}
79
+ caption={caption(hasVram ? "Video memory usage" : "Memory usage")}
80
+ ceiling={formatRam(memoryTotalMB)}
81
+ series={[{ data: memory, color: CHART_COLORS.success }]}
82
+ />
83
+ )}
84
+
85
+ <StatGrid>
86
+ <Stat label="Video memory" value={hasVram
87
+ ? `${formatRam(gpu.vramUsedMB)} / ${formatRam(gpu.vramTotalMB)}` : undefined} />
88
+ <Stat label={hasVram ? "Shared memory" : "Memory usage"} value={gpu.sharedTotalMB === undefined ? undefined
89
+ : `${formatRam(gpu.sharedUsedMB ?? 0)} / ${formatRam(gpu.sharedTotalMB)}`} />
90
+ <Stat
91
+ label={videoShared ? "Video encode/decode" : "Video encode"}
92
+ value={gpu.encodePercent === undefined ? undefined : `${gpu.encodePercent.toFixed(0)}%`}
93
+ />
94
+ {!videoShared && (
95
+ <Stat label="Video decode" value={gpu.decodePercent === undefined ? undefined
96
+ : `${gpu.decodePercent.toFixed(0)}%`} />
97
+ )}
98
+ <Stat label="Clock" value={gpu.clockMHz === undefined ? undefined
99
+ : `${gpu.clockMHz} MHz${gpu.clockMaxMHz ? ` / ${gpu.clockMaxMHz}` : ""}`} />
100
+ <Stat label="Memory clock" value={gpu.memClockMHz === undefined ? undefined
101
+ : `${gpu.memClockMHz} MHz${gpu.memClockMaxMHz ? ` / ${gpu.memClockMaxMHz}` : ""}`} />
102
+ <Stat label="Power" value={gpu.powerW === undefined ? undefined
103
+ : `${gpu.powerW.toFixed(1)} W${gpu.powerMaxW ? ` / ${gpu.powerMaxW}` : ""}`} />
104
+ <Stat label="Temperature" value={formatTemp(gpu.tempC, tempUnit)} />
105
+ <Stat label="Vendor" value={info?.vendor} />
106
+ <Stat label="Driver" value={info?.driver === undefined ? undefined
107
+ : [info.driver, info.driverVersion].filter(Boolean).join(" ")} />
108
+ <Stat label="OpenGL" value={info?.openglVersion} />
109
+ <Stat label="Vulkan" value={info?.vulkanVersion} />
110
+ <Stat label="PCI bus address" value={gpu.id} />
111
+ <Stat label="PCIe link" value={pcie(info?.pcieGen, info?.pcieLanes)} />
112
+ <Stat label="PCIe maximum" value={pcie(info?.pcieMaxGen, info?.pcieMaxLanes)} />
113
+ </StatGrid>
114
+ </div>
115
+ );
116
+ }
@@ -0,0 +1,109 @@
1
+ /** Memory page — Mission Center's Memory tab: the usage graph, the composition
2
+ * strip whose four parts add up to the total exactly, and the SMBIOS slot table. */
3
+ import { formatBytes, formatRam } from "@/lib/format-bytes";
4
+ import { historySpanLabel } from "@/lib/cpu-graph-mode";
5
+ import { CHART_COLORS, CompositionBar, DetailChart, DetailHeader, Stat, StatGrid, useSeries } from "./detail-parts";
6
+ import type { MemoryInfo } from "../../../../types/system-hardware";
7
+ import type { MemoryMetrics, MetricsHistoryPoint } from "../../../../types/system-metrics";
8
+
9
+ export function MemoryDetail({
10
+ mem, info, history,
11
+ }: { mem: MemoryMetrics; info?: MemoryInfo; history: readonly MetricsHistoryPoint[] }) {
12
+ const used = useSeries(history, (p) => p.system.mem.percent);
13
+ // Percent of the swap that is in use, so the graph shares the utilisation axis
14
+ // with the memory one above it rather than autoscaling to whatever megabyte
15
+ // figure happens to be the window's maximum.
16
+ const swap = useSeries(history, (p) => {
17
+ const total = p.system.mem.swapTotalMB ?? 0;
18
+ return total > 0 ? ((p.system.mem.swapUsedMB ?? 0) / total) * 100 : 0;
19
+ });
20
+ // The four byte figures are produced together or not at all, so one of them
21
+ // being present is enough to know the strip can be drawn.
22
+ const composed = mem.inUseBytes !== undefined;
23
+ const span = historySpanLabel(history.map((p) => p.ts));
24
+ const caption = (what: string) => (span ? `${what} ${span}` : what);
25
+ // A host with swap off gets no swap graph at all: a flat zero line over an
26
+ // axis that does not exist reads as "nothing is swapping", which is a
27
+ // different claim from "there is nowhere to swap to".
28
+ const hasSwap = (mem.swapTotalMB ?? 0) > 0;
29
+
30
+ return (
31
+ <div className="space-y-4" data-testid="sysmon-detail-memory">
32
+ <DetailHeader
33
+ title="Memory"
34
+ subtitle={`${formatRam(mem.usedMB)} of ${formatRam(mem.totalMB)} in use`}
35
+ value={`${mem.percent.toFixed(1)}%`}
36
+ />
37
+ <DetailChart
38
+ grid
39
+ maxValue={100}
40
+ caption={caption("Memory usage")}
41
+ ceiling={formatRam(mem.totalMB)}
42
+ series={[{ data: used, color: CHART_COLORS.primary }]}
43
+ />
44
+
45
+ {hasSwap && (
46
+ <DetailChart
47
+ grid
48
+ height={90}
49
+ maxValue={100}
50
+ caption={caption("Swap usage")}
51
+ ceiling={formatRam(mem.swapTotalMB ?? 0)}
52
+ series={[{ data: swap, color: CHART_COLORS.success }]}
53
+ />
54
+ )}
55
+
56
+ {composed && (
57
+ <div className="space-y-2">
58
+ <CompositionBar segments={[
59
+ { label: "In use", value: mem.inUseBytes ?? 0, color: "var(--color-primary)" },
60
+ { label: "Modified", value: mem.modifiedBytes ?? 0, color: "var(--color-warning)" },
61
+ { label: "Standby", value: mem.standbyBytes ?? 0, color: "var(--color-success)" },
62
+ { label: "Free", value: mem.freeBytes ?? 0, color: "var(--color-border)" },
63
+ ]} />
64
+ <div className="flex flex-wrap gap-x-4 gap-y-1 text-[11px] text-text-subtle">
65
+ <span>In use {formatBytes(mem.inUseBytes ?? 0)}</span>
66
+ <span>Modified {formatBytes(mem.modifiedBytes ?? 0)}</span>
67
+ <span>Standby {formatBytes(mem.standbyBytes ?? 0)}</span>
68
+ <span>Free {formatBytes(mem.freeBytes ?? 0)}</span>
69
+ </div>
70
+ </div>
71
+ )}
72
+
73
+ <StatGrid>
74
+ <Stat label="Available" value={formatRam(mem.availableMB)} />
75
+ <Stat label="Cached" value={mem.cachedMB === undefined ? undefined : formatRam(mem.cachedMB)} />
76
+ <Stat label="Committed" value={mem.committedMB === undefined ? undefined
77
+ : `${formatRam(mem.committedMB)} / ${mem.commitLimitMB === undefined ? "?" : formatRam(mem.commitLimitMB)}`} />
78
+ <Stat label="Swap" value={mem.swapTotalMB === undefined ? undefined
79
+ : `${formatRam(mem.swapUsedMB ?? 0)} / ${formatRam(mem.swapTotalMB)}`} />
80
+ <Stat label="Compressed (zram)" value={mem.zramCompressedMB === undefined ? undefined
81
+ : formatRam(mem.zramCompressedMB)} />
82
+ <Stat label="Savings (zram)" value={mem.zramSavingsMB === undefined ? undefined
83
+ : formatRam(mem.zramSavingsMB)} />
84
+ <Stat label="Slots used" value={info === undefined ? undefined
85
+ : `${info.devices.length}${info.slotsTotal ? ` of ${info.slotsTotal}` : ""}`} />
86
+ <Stat label="Maximum capacity" value={info?.maxCapacityBytes === undefined ? undefined
87
+ : formatBytes(info.maxCapacityBytes)} />
88
+ </StatGrid>
89
+
90
+ {info && info.devices.length > 0 && (
91
+ <div className="space-y-1">
92
+ <h4 className="text-xs font-medium text-text-secondary">Slots</h4>
93
+ <div className="rounded-md border border-border divide-y divide-border">
94
+ {info.devices.map((device) => (
95
+ <div key={device.locator} className="flex items-center justify-between gap-3 px-3 py-2 text-xs">
96
+ <span className="font-medium shrink-0">{device.locator}</span>
97
+ <span className="text-text-subtle truncate">
98
+ {[device.manufacturer, device.ramType, device.formFactor,
99
+ device.speedMts ? `${device.speedMts} MT/s` : null].filter(Boolean).join(" · ")}
100
+ </span>
101
+ <span className="tabular-nums shrink-0">{formatBytes(device.sizeBytes)}</span>
102
+ </div>
103
+ ))}
104
+ </div>
105
+ </div>
106
+ )}
107
+ </div>
108
+ );
109
+ }
@@ -0,0 +1,55 @@
1
+ /** One network interface — Mission Center's per-interface page. */
2
+ import { formatBps, formatBytes } from "@/lib/format-bytes";
3
+ import { CHART_COLORS, DetailChart, DetailHeader, Stat, StatGrid, useSeries } from "./detail-parts";
4
+ import { NIC_KIND_LABELS } from "./device-list";
5
+ import type { NicInfo } from "../../../../types/system-hardware";
6
+ import type { MetricsHistoryPoint, NicMetrics, NicState } from "../../../../types/system-metrics";
7
+
8
+ const STATE_LABELS: Record<NicState, string> = {
9
+ connected: "Connected",
10
+ connecting: "Connecting",
11
+ disconnected: "Disconnected",
12
+ unavailable: "Unavailable",
13
+ unknown: "Unknown",
14
+ };
15
+
16
+ export function NicDetail({
17
+ nic, info, history,
18
+ }: { nic: NicMetrics; info?: NicInfo; history: readonly MetricsHistoryPoint[] }) {
19
+ const pick = (p: MetricsHistoryPoint) => p.system.nics?.find((n) => n.id === nic.id);
20
+ const rx = useSeries(history, (p) => pick(p)?.rxBps);
21
+ const tx = useSeries(history, (p) => pick(p)?.txBps);
22
+
23
+ return (
24
+ <div className="space-y-4" data-testid="sysmon-detail-nic" data-nic-id={nic.id}>
25
+ <DetailHeader
26
+ title={NIC_KIND_LABELS[info?.kind ?? "other"]}
27
+ subtitle={[nic.id, info?.deviceName].filter(Boolean).join(" · ")}
28
+ value={nic.available ? formatBps(nic.rxBps + nic.txBps) : "—"}
29
+ />
30
+ <DetailChart
31
+ legend={["Receive", "Send"]}
32
+ series={[
33
+ { data: rx, color: CHART_COLORS.primary },
34
+ { data: tx, color: CHART_COLORS.secondary },
35
+ ]}
36
+ />
37
+ <StatGrid>
38
+ <Stat label="State" value={STATE_LABELS[nic.state]} />
39
+ <Stat label="Receive" value={nic.available ? formatBps(nic.rxBps) : undefined} />
40
+ <Stat label="Send" value={nic.available ? formatBps(nic.txBps) : undefined} />
41
+ <Stat label="Maximum bitrate" value={nic.linkMbps === undefined ? undefined : `${nic.linkMbps} Mbps`} />
42
+ <Stat label="Total received" value={formatBytes(nic.rxTotal)} />
43
+ <Stat label="Total sent" value={formatBytes(nic.txTotal)} />
44
+ <Stat label="Network name" value={nic.ssid} />
45
+ <Stat label="Signal" value={nic.signalPercent === undefined ? undefined : `${nic.signalPercent}%`} />
46
+ <Stat label="Frequency" value={nic.frequencyMHz === undefined ? undefined
47
+ : `${(nic.frequencyMHz / 1000).toFixed(1)} GHz`} />
48
+ <Stat label="Driver" value={info?.driver} />
49
+ <Stat label="Hardware address" value={info?.mac} />
50
+ <Stat label="IPv4" value={info?.ipv4.join(", ")} title={info?.ipv4.join("\n")} />
51
+ <Stat label="IPv6" value={info?.ipv6.join(", ")} title={info?.ipv6.join("\n")} />
52
+ </StatGrid>
53
+ </div>
54
+ );
55
+ }
@@ -0,0 +1,79 @@
1
+ /**
2
+ * A drive's partitions — Mission Center's Partitions section.
3
+ *
4
+ * One row per partition, not per mount: a partition's usage belongs to its
5
+ * FILESYSTEM, and a btrfs subvolume layout mounts one filesystem at seven places
6
+ * that all report the same figures. Seven identical bars would be noise, so the
7
+ * mount points are listed together above one bar.
8
+ */
9
+ import { formatBytes } from "@/lib/format-bytes";
10
+ import { cn } from "@/lib/utils";
11
+ import type { PartitionInfo } from "../../../../types/system-hardware";
12
+
13
+ /** Above this a bar earns a warning colour — a filesystem this full is a problem
14
+ * worth noticing before it is one. */
15
+ const FULL_PERCENT = 90;
16
+ const BUSY_PERCENT = 75;
17
+
18
+ function barColor(percent: number): string {
19
+ if (percent >= FULL_PERCENT) return "bg-error";
20
+ if (percent >= BUSY_PERCENT) return "bg-warning";
21
+ return "bg-primary";
22
+ }
23
+
24
+ export function PartitionList({ partitions }: { partitions: readonly PartitionInfo[] }) {
25
+ if (partitions.length === 0) return null;
26
+ return (
27
+ <section className="space-y-2" data-testid="sysmon-partitions">
28
+ <h4 className="text-sm font-medium">Partitions</h4>
29
+ <ul className="space-y-2">
30
+ {partitions.map((part) => (
31
+ <PartitionRow key={part.id} part={part} />
32
+ ))}
33
+ </ul>
34
+ </section>
35
+ );
36
+ }
37
+
38
+ function PartitionRow({ part }: { part: PartitionInfo }) {
39
+ // The first mount that answered: every mount of one filesystem reports the
40
+ // same statfs, so there is nothing to choose between them.
41
+ const usage = part.mounts.find((m) => m.usedBytes !== undefined && m.totalBytes);
42
+ const percent = usage ? Math.min(100, (usage.usedBytes! / usage.totalBytes!) * 100) : undefined;
43
+
44
+ return (
45
+ <li className="rounded-md border border-border px-3 py-2 space-y-1.5" data-testid="sysmon-partition">
46
+ <div className="flex items-baseline justify-between gap-3">
47
+ <span className="text-sm font-medium truncate" title={part.devicePath}>{part.devicePath}</span>
48
+ <span className="text-[11px] text-text-subtle shrink-0 tabular-nums">
49
+ {part.filesystem ?? "—"} · {formatBytes(part.sizeBytes)}
50
+ </span>
51
+ </div>
52
+
53
+ {part.mounts.length === 0 ? (
54
+ <p className="text-[11px] text-text-subtle">Not mounted</p>
55
+ ) : (
56
+ <>
57
+ <p className="text-[11px] text-text-subtle truncate" title={part.mounts.map((m) => m.mountPoint).join(", ")}>
58
+ {part.mounts.map((m) => m.mountPoint).join(", ")}
59
+ </p>
60
+ {percent === undefined ? (
61
+ // Mounted but statfs refused. An unreadable filesystem is not an
62
+ // empty one, so it gets no bar rather than a bar at zero.
63
+ <p className="text-[11px] text-text-subtle">Usage unavailable</p>
64
+ ) : (
65
+ <div className="space-y-1">
66
+ <div className="h-1.5 w-full rounded-full bg-surface-hover overflow-hidden">
67
+ <div className={cn("h-full rounded-full", barColor(percent))} style={{ width: `${percent}%` }} />
68
+ </div>
69
+ <div className="flex items-baseline justify-between gap-2 text-[11px] text-text-subtle tabular-nums">
70
+ <span>{formatBytes(usage!.usedBytes!)} of {formatBytes(usage!.totalBytes!)}</span>
71
+ <span>{percent.toFixed(0)}%</span>
72
+ </div>
73
+ </div>
74
+ )}
75
+ </>
76
+ )}
77
+ </li>
78
+ );
79
+ }
@@ -0,0 +1,206 @@
1
+ /**
2
+ * The Performance page — Mission Center's device sidebar plus one detail page.
3
+ *
4
+ * Two presentations from one tree: at `md` and above the sidebar and the detail
5
+ * sit side by side; below it the sidebar IS the page and tapping a device drills
6
+ * into it, because a 200px sidebar beside a detail grid on a phone leaves neither
7
+ * of them usable.
8
+ */
9
+ import { useMemo, type ComponentType } from "react";
10
+ import { Activity, ChevronLeft, ChevronRight, Cpu, HardDrive, Layers, Monitor, Wifi } from "@/lib/icons";
11
+ import { cn } from "@/lib/utils";
12
+ import { useIsMobile } from "@/hooks/use-is-mobile";
13
+ import { buildDeviceList, resolveSelected, type DeviceEntry, type DeviceKind } from "./device-list";
14
+ import { useHardwareInventory } from "./use-hardware-inventory";
15
+ import { CpuDetail } from "./cpu-detail";
16
+ import { MemoryDetail } from "./memory-detail";
17
+ import { DiskDetail } from "./disk-detail";
18
+ import { NicDetail } from "./nic-detail";
19
+ import { GpuDetail } from "./gpu-detail";
20
+ import { FansDetail } from "./fans-detail";
21
+ import type { HardwareInventory } from "../../../../types/system-hardware";
22
+ import type { MetricsHistoryPoint, SystemMetrics } from "../../../../types/system-metrics";
23
+
24
+ const KIND_ICONS: Record<DeviceKind, ComponentType<{ className?: string }>> = {
25
+ cpu: Cpu, memory: Layers, disk: HardDrive, nic: Wifi, gpu: Monitor, fans: Activity,
26
+ };
27
+
28
+ function barColor(percent: number): string {
29
+ if (percent > 80) return "bg-error";
30
+ if (percent > 50) return "bg-warning";
31
+ return "bg-primary";
32
+ }
33
+
34
+ function DeviceRow({
35
+ entry, selected, showChevron, onSelect,
36
+ }: { entry: DeviceEntry; selected: boolean; showChevron: boolean; onSelect: (key: string) => void }) {
37
+ const Icon = KIND_ICONS[entry.kind];
38
+ return (
39
+ <button
40
+ type="button"
41
+ onClick={() => onSelect(entry.key)}
42
+ aria-current={selected}
43
+ data-testid="sysmon-device-row"
44
+ data-device-key={entry.key}
45
+ className={cn(
46
+ "w-full min-h-11 px-3 py-2 flex items-center gap-3 text-left transition-colors",
47
+ selected ? "bg-primary/10 text-text-primary" : "hover:bg-surface-hover",
48
+ )}
49
+ >
50
+ <Icon className="size-4 shrink-0 text-text-subtle" />
51
+ <span className="flex-1 min-w-0">
52
+ <span className="block text-sm truncate">{entry.label}</span>
53
+ <span className="block text-[11px] text-text-subtle truncate" title={entry.sublabel}>
54
+ {entry.sublabel}
55
+ </span>
56
+ {/* No bar at all when the device has no percentage — an empty track would
57
+ read as "measured, and it is zero". */}
58
+ {entry.percent !== null && (
59
+ <span className="mt-1 block h-1 w-full rounded-full bg-surface-hover overflow-hidden">
60
+ <span
61
+ className={cn("block h-full transition-[width]", barColor(entry.percent))}
62
+ style={{ width: `${Math.max(1, Math.min(100, entry.percent))}%` }}
63
+ />
64
+ </span>
65
+ )}
66
+ </span>
67
+ <span className="text-xs tabular-nums text-text-secondary shrink-0">{entry.detail}</span>
68
+ {showChevron && <ChevronRight className="size-4 shrink-0 text-text-subtle" />}
69
+ </button>
70
+ );
71
+ }
72
+
73
+ function DeviceDetail({
74
+ entry, system, inventory, history,
75
+ }: {
76
+ entry: DeviceEntry;
77
+ system: SystemMetrics;
78
+ inventory: HardwareInventory | null;
79
+ history: readonly MetricsHistoryPoint[];
80
+ }) {
81
+ switch (entry.kind) {
82
+ case "cpu":
83
+ return <CpuDetail cpu={system.cpu} info={inventory?.cpu} history={history} processCount={system.processCount} />;
84
+ case "memory":
85
+ return <MemoryDetail mem={system.mem} info={inventory?.memory} history={history} />;
86
+ case "disk": {
87
+ const index = (system.disks ?? []).findIndex((d) => d.id === entry.id);
88
+ const disk = index >= 0 ? system.disks?.[index] : undefined;
89
+ if (!disk) return null;
90
+ return (
91
+ <DiskDetail
92
+ disk={disk}
93
+ index={index}
94
+ info={inventory?.disks.find((d) => d.id === disk.id)}
95
+ history={history}
96
+ />
97
+ );
98
+ }
99
+ case "nic": {
100
+ const nic = (system.nics ?? []).find((n) => n.id === entry.id);
101
+ if (!nic) return null;
102
+ return <NicDetail nic={nic} info={inventory?.nics.find((n) => n.id === nic.id)} history={history} />;
103
+ }
104
+ case "gpu": {
105
+ const index = system.gpus.findIndex((g) => (entry.id ? g.id === entry.id : true));
106
+ const gpu = index >= 0 ? system.gpus[index] : undefined;
107
+ if (!gpu) return null;
108
+ return (
109
+ <GpuDetail
110
+ gpu={gpu}
111
+ index={index}
112
+ info={inventory?.gpus.find((g) => g.id === gpu.id)}
113
+ history={history}
114
+ />
115
+ );
116
+ }
117
+ case "fans":
118
+ return <FansDetail fans={system.fans ?? []} />;
119
+ default:
120
+ return null;
121
+ }
122
+ }
123
+
124
+ export interface PerformancePanelProps {
125
+ system: SystemMetrics;
126
+ history: MetricsHistoryPoint[];
127
+ /** Selected device key, owned by the parent so an Overview card can jump
128
+ * straight to one. `null` means "nothing chosen": the desktop sidebar then
129
+ * falls back to the first entry and the phone shows the device list. */
130
+ device: string | null;
131
+ onDeviceChange: (key: string | null) => void;
132
+ }
133
+
134
+ export function PerformancePanel({
135
+ system, history, device, onDeviceChange,
136
+ }: PerformancePanelProps) {
137
+ const isMobile = useIsMobile();
138
+
139
+ // Derived from the tick rather than from the device list, so the inventory
140
+ // fetch does not depend on the list that depends on the inventory.
141
+ const deviceIds = useMemo(
142
+ () => [
143
+ ...(system.disks ?? []).map((d) => d.id),
144
+ ...(system.nics ?? []).map((n) => n.id),
145
+ ...system.gpus.map((g) => g.id).filter((id): id is string => !!id),
146
+ ].join(","),
147
+ [system.disks, system.nics, system.gpus],
148
+ );
149
+ const inventory = useHardwareInventory(deviceIds);
150
+ const entries = useMemo(() => buildDeviceList(system, inventory), [system, inventory]);
151
+
152
+ // A device that disappears (a drive unplugged) falls back rather than leaving
153
+ // the page blank.
154
+ const selectedKey = resolveSelected(entries, device);
155
+ const selected = entries.find((e) => e.key === selectedKey);
156
+
157
+ const list = (
158
+ <div className="divide-y divide-border" role="list" data-testid="sysmon-device-list">
159
+ {entries.map((entry) => (
160
+ <DeviceRow
161
+ key={entry.key}
162
+ entry={entry}
163
+ selected={!isMobile && entry.key === selectedKey}
164
+ showChevron={isMobile}
165
+ onSelect={onDeviceChange}
166
+ />
167
+ ))}
168
+ </div>
169
+ );
170
+
171
+ if (isMobile) {
172
+ // The phone shows one thing at a time, so a key that resolves to something
173
+ // OTHER than what was asked for goes back to the list rather than drilling
174
+ // into the fallback. On desktop that fallback is harmless — the sidebar is on
175
+ // screen saying which device is current — and here there is nothing to say it.
176
+ if (device === null || !selected || selectedKey !== device) {
177
+ return <div className="h-full overflow-y-auto" data-testid="sysmon-performance">{list}</div>;
178
+ }
179
+ return (
180
+ <div className="h-full flex flex-col" data-testid="sysmon-performance">
181
+ <button
182
+ type="button"
183
+ onClick={() => onDeviceChange(null)}
184
+ className="shrink-0 min-h-11 px-3 flex items-center gap-2 text-sm border-b border-border"
185
+ >
186
+ <ChevronLeft className="size-4" />
187
+ Devices
188
+ </button>
189
+ <div className="flex-1 min-h-0 overflow-y-auto p-4 @container">
190
+ <DeviceDetail entry={selected} system={system} inventory={inventory} history={history} />
191
+ </div>
192
+ </div>
193
+ );
194
+ }
195
+
196
+ return (
197
+ <div className="h-full flex min-h-0" data-testid="sysmon-performance">
198
+ <div className="w-56 shrink-0 border-r border-border overflow-y-auto">{list}</div>
199
+ <div className="flex-1 min-w-0 overflow-y-auto p-4 @container">
200
+ {selected && (
201
+ <DeviceDetail entry={selected} system={system} inventory={inventory} history={history} />
202
+ )}
203
+ </div>
204
+ </div>
205
+ );
206
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Static device facts for the Performance page.
3
+ *
4
+ * Fetched once, then again only when a snapshot names a device id the inventory
5
+ * has never heard of — a USB drive plugged in, an interface created. It is a
6
+ * ~2.8 KB payload of things that do not change tick to tick (models, capacities,
7
+ * MAC addresses, DIMM layout), so putting it on the 2 s stream would be pure
8
+ * waste over a tunnel.
9
+ */
10
+ import { useCallback, useEffect, useRef, useState } from "react";
11
+ import { api } from "@/lib/api-client";
12
+ import type { HardwareInventory } from "../../../../types/system-hardware";
13
+
14
+ /** `deviceIds` is a JOINED string, not an array: an array literal is a fresh
15
+ * identity every render, which would turn the refetch effect into a loop. */
16
+ export function useHardwareInventory(deviceIds: string): HardwareInventory | null {
17
+ const [inventory, setInventory] = useState<HardwareInventory | null>(null);
18
+ const inFlight = useRef(false);
19
+
20
+ const load = useCallback(async () => {
21
+ if (inFlight.current) return;
22
+ inFlight.current = true;
23
+ try {
24
+ setInventory(await api.get<HardwareInventory>("/api/system/hardware"));
25
+ } catch {
26
+ // The pages degrade to the ids the tick already carries rather than
27
+ // showing an error over a whole page of otherwise-live figures.
28
+ } finally {
29
+ inFlight.current = false;
30
+ }
31
+ }, []);
32
+
33
+ useEffect(() => {
34
+ void load();
35
+ }, [load]);
36
+
37
+ useEffect(() => {
38
+ if (!inventory) return;
39
+ const known = new Set<string>([
40
+ ...inventory.disks.map((d) => d.id),
41
+ ...inventory.nics.map((n) => n.id),
42
+ ...inventory.gpus.map((g) => g.id),
43
+ ]);
44
+ if (deviceIds.split(",").filter(Boolean).some((id) => !known.has(id))) void load();
45
+ }, [inventory, deviceIds, load]);
46
+
47
+ return inventory;
48
+ }
@@ -9,7 +9,7 @@
9
9
  import type { CSSProperties } from "react";
10
10
  import type { ProcessColumnAvailability, SortKey } from "../../../types/system-metrics";
11
11
 
12
- export type OptionalColumnKey = "disk" | "gpu" | "net";
12
+ export type OptionalColumnKey = "swap" | "disk" | "gpu" | "net";
13
13
  /** Every column whose width the user can drag. The name column takes the rest. */
14
14
  export type ResizableColumnKey = "cpu" | "ram" | OptionalColumnKey;
15
15
 
@@ -20,13 +20,15 @@ export type ProcessColumnsFlags = ProcessColumnAvailability;
20
20
  /** px overrides from a drag; missing keys fall back to `DEFAULT_COLUMN_WIDTH`. */
21
21
  export type ColumnWidths = Partial<Record<ResizableColumnKey, number>>;
22
22
 
23
- const OPTIONAL_COLUMN_ORDER: OptionalColumnKey[] = ["disk", "gpu", "net"];
23
+ /** Mission Center's own order on both its tables: Memory, Swap, then the rest. */
24
+ const OPTIONAL_COLUMN_ORDER: OptionalColumnKey[] = ["swap", "disk", "gpu", "net"];
24
25
 
25
26
  /** Disk/Net cells show two values ("↓ read ↑ write"); GPU shows one composite
26
27
  * ("12% · 1.1 GB") and fits narrower. */
27
28
  export const DEFAULT_COLUMN_WIDTH: Record<ResizableColumnKey, number> = {
28
29
  cpu: 64,
29
30
  ram: 80,
31
+ swap: 80,
30
32
  disk: 120,
31
33
  gpu: 90,
32
34
  net: 120,
@@ -54,7 +56,7 @@ export interface ProcessGridResult {
54
56
  }
55
57
 
56
58
  function isOptionalColumnKey(key: SortKey): key is OptionalColumnKey {
57
- return key === "disk" || key === "gpu" || key === "net";
59
+ return key === "swap" || key === "disk" || key === "gpu" || key === "net";
58
60
  }
59
61
 
60
62
  export function clampColumnWidth(px: number): number {