@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
@@ -8,12 +8,33 @@ export interface MetricSeries {
8
8
  }
9
9
 
10
10
  interface MetricChartCanvasProps {
11
- /** 1-2 series drawn on the same axis. */
11
+ /** Series drawn on the same axis. Overlaid by default; see `stacked`. */
12
12
  series: MetricSeries[];
13
13
  height: number;
14
14
  /** Fixed scale ceiling (e.g. 100 for a percentage axis). Omitted = autoscale to
15
15
  * the max across all series in the visible window. */
16
16
  maxValue?: number;
17
+ /** Mission Center's faint ruled background. Off by default — the Overview cards
18
+ * are 56px tall and a grid in there is noise rather than a reading aid. */
19
+ grid?: boolean;
20
+ /** Stack the series instead of overlaying them: each is drawn on top of the sum
21
+ * of the ones before it, so the top edge is the total. The caller supplies
22
+ * values that already sum to the scale (24 threads each divided by 24), because
23
+ * only the caller knows what the total is supposed to mean. */
24
+ stacked?: boolean;
25
+ }
26
+
27
+ /** Mission Center's ruling: ten columns and five rows, fixed rather than derived
28
+ * from the point count, so the background does not crawl as the window fills. */
29
+ const GRID_COLS = 10;
30
+ const GRID_ROWS = 5;
31
+
32
+ /** The per-column sums a stack reaches, which is what its axis has to fit. */
33
+ function stackedTotals(series: MetricSeries[]): number[] {
34
+ const len = Math.max(0, ...series.map((s) => s.data.length));
35
+ const totals = new Array(len).fill(0);
36
+ for (const s of series) for (let i = 0; i < s.data.length; i++) totals[i] += s.data[i] ?? 0;
37
+ return totals;
17
38
  }
18
39
 
19
40
  /** Generalised, filled, multi-series canvas chart for the Overview cards. Fills the
@@ -25,6 +46,8 @@ export const MetricChartCanvas = memo(function MetricChartCanvas({
25
46
  series,
26
47
  height,
27
48
  maxValue,
49
+ grid = false,
50
+ stacked = false,
28
51
  }: MetricChartCanvasProps) {
29
52
  const wrapperRef = useRef<HTMLDivElement>(null);
30
53
  const canvasRef = useRef<HTMLCanvasElement>(null);
@@ -51,6 +74,26 @@ export const MetricChartCanvas = memo(function MetricChartCanvas({
51
74
  const drawH = height - padding * 2;
52
75
  const longest = Math.max(1, ...series.map((s) => s.data.length));
53
76
 
77
+ // Behind everything, so a curve is never cut by a rule.
78
+ if (grid) {
79
+ ctx.strokeStyle = colorOf("var(--color-border)");
80
+ ctx.globalAlpha = 0.5;
81
+ ctx.lineWidth = 1;
82
+ ctx.beginPath();
83
+ for (let c = 1; c < GRID_COLS; c++) {
84
+ const x = Math.round((width / GRID_COLS) * c) + 0.5;
85
+ ctx.moveTo(x, 0);
86
+ ctx.lineTo(x, height);
87
+ }
88
+ for (let r = 1; r < GRID_ROWS; r++) {
89
+ const y = Math.round((height / GRID_ROWS) * r) + 0.5;
90
+ ctx.moveTo(0, y);
91
+ ctx.lineTo(width, y);
92
+ }
93
+ ctx.stroke();
94
+ ctx.globalAlpha = 1;
95
+ }
96
+
54
97
  // A flat baseline when there isn't enough data yet to draw a meaningful line —
55
98
  // a freshly-opened window otherwise shows nothing at all for the first tick.
56
99
  if (longest < 2) {
@@ -63,7 +106,40 @@ export const MetricChartCanvas = memo(function MetricChartCanvas({
63
106
  return;
64
107
  }
65
108
 
66
- const scaleMax = resolveScaleMax(series.flatMap((s) => s.data), maxValue);
109
+ const scaleMax = resolveScaleMax(
110
+ stacked ? stackedTotals(series) : series.flatMap((s) => s.data),
111
+ maxValue,
112
+ );
113
+
114
+ if (stacked) {
115
+ // Each band is the area between the running sum before it and after it, so
116
+ // the visible height of a band IS that series' contribution. Drawn bottom-up
117
+ // with a closed polygon per band rather than one fill per series over a
118
+ // shared baseline, which would hide every series behind the first.
119
+ const below: number[] = new Array(Math.max(0, ...series.map((x) => x.data.length))).fill(0);
120
+ for (const s of series) {
121
+ if (s.data.length < 2) continue;
122
+ const stepX = width / (s.data.length - 1);
123
+ const yOf = (v: number) => padding + drawH - (v / scaleMax) * drawH;
124
+ ctx.beginPath();
125
+ for (let i = 0; i < s.data.length; i++) {
126
+ const top = (below[i] ?? 0) + (s.data[i] ?? 0);
127
+ const p = [i * stepX, yOf(top)] as const;
128
+ if (i === 0) ctx.moveTo(p[0], p[1]);
129
+ else ctx.lineTo(p[0], p[1]);
130
+ }
131
+ for (let i = s.data.length - 1; i >= 0; i--) {
132
+ ctx.lineTo(i * stepX, yOf(below[i] ?? 0));
133
+ }
134
+ ctx.closePath();
135
+ ctx.fillStyle = colorOf(s.color);
136
+ ctx.globalAlpha = 0.75;
137
+ ctx.fill();
138
+ ctx.globalAlpha = 1;
139
+ for (let i = 0; i < s.data.length; i++) below[i] = (below[i] ?? 0) + (s.data[i] ?? 0);
140
+ }
141
+ return;
142
+ }
67
143
 
68
144
  for (const s of series) {
69
145
  if (s.data.length < 2) continue;
@@ -97,7 +173,7 @@ export const MetricChartCanvas = memo(function MetricChartCanvas({
97
173
  }
98
174
  ctx.stroke();
99
175
  }
100
- }, [series, width, height, maxValue]);
176
+ }, [series, width, height, maxValue, grid, stacked]);
101
177
 
102
178
  return (
103
179
  <div ref={wrapperRef} className="w-full min-w-0 overflow-hidden" style={{ height }}>
@@ -0,0 +1,54 @@
1
+ import type { ReactNode } from "react";
2
+ import { cn } from "@/lib/utils";
3
+
4
+ export interface CardShellProps {
5
+ testId: string;
6
+ /** Extra `data-*` the card publishes for tests, e.g. `data-available`. */
7
+ data?: Record<string, string | number | boolean>;
8
+ /** Present when this card has a Performance device to open. A card with no
9
+ * target — a host reporting no drives at all — stays a plain `div`, because a
10
+ * button that does nothing is worse than no button. */
11
+ onOpen?: () => void;
12
+ /** What the button announces. Required with `onOpen`: a button's name is
13
+ * otherwise computed from its contents, which here is the whole card
14
+ * ("CPU 6.9% 12th Gen Intel(R) Core(TM) i9-12900K"). */
15
+ openLabel?: string;
16
+ children: ReactNode;
17
+ }
18
+
19
+ /**
20
+ * The frame every Overview card shares, and the click that opens its Performance
21
+ * page. Extracted because all five cards had a byte-identical wrapper and this
22
+ * adds a conditional element type to each of them.
23
+ *
24
+ * It is one button over the whole card rather than a small "details" affordance
25
+ * in a corner: a 44px target is the mobile floor and the card is the thing the
26
+ * reader is already pointing at. That does mean the heading inside it stops being
27
+ * a navigable heading for a screen reader, which is why the name is given
28
+ * explicitly instead of being read off the contents.
29
+ */
30
+ export function CardShell({ testId, data, onOpen, openLabel, children }: CardShellProps) {
31
+ const frame = "rounded-lg border border-border p-4 space-y-2";
32
+ const attrs = { "data-testid": testId, ...data };
33
+
34
+ if (!onOpen) return <div className={frame} {...attrs}>{children}</div>;
35
+
36
+ return (
37
+ <button
38
+ type="button"
39
+ onClick={onOpen}
40
+ aria-label={openLabel}
41
+ {...attrs}
42
+ className={cn(
43
+ frame,
44
+ // `text-left` because a button centres its content, and `w-full` because
45
+ // it is a grid item that would otherwise shrink to its content.
46
+ "w-full text-left cursor-pointer transition-colors",
47
+ "hover:bg-surface-hover hover:border-primary/40",
48
+ "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary",
49
+ )}
50
+ >
51
+ {children}
52
+ </button>
53
+ );
54
+ }
@@ -1,11 +1,14 @@
1
1
  import { MetricChartCanvas } from "../metric-chart-canvas";
2
2
  import { CpuCoreBars } from "../cpu-core-bars";
3
+ import { CardShell } from "./card-shell";
3
4
 
4
5
  export interface CpuCardProps {
5
6
  total: number;
6
7
  cores: number[];
7
8
  model: string;
8
9
  series: number[];
10
+ /** Opens the Performance page on this device. */
11
+ onOpen?: () => void;
9
12
  }
10
13
 
11
14
  function cpuColor(pct: number): string {
@@ -14,12 +17,13 @@ function cpuColor(pct: number): string {
14
17
  return "text-success";
15
18
  }
16
19
 
17
- export function CpuCard({ total, cores, model, series }: CpuCardProps) {
20
+ export function CpuCard({ total, cores, model, series, onOpen }: CpuCardProps) {
18
21
  return (
19
- <div
20
- className="rounded-lg border border-border p-4 space-y-2"
21
- data-testid="sysmon-card-cpu"
22
- data-cpu-total={total}
22
+ <CardShell
23
+ testId="sysmon-card-cpu"
24
+ data={{ "data-cpu-total": total }}
25
+ onOpen={onOpen}
26
+ openLabel="CPU details"
23
27
  >
24
28
  <div className="flex items-baseline justify-between">
25
29
  <h3 className="text-sm font-medium">CPU</h3>
@@ -29,11 +33,12 @@ export function CpuCard({ total, cores, model, series }: CpuCardProps) {
29
33
  series={[{ data: series, color: "var(--color-primary)" }]}
30
34
  height={56}
31
35
  maxValue={100}
36
+ grid
32
37
  />
33
38
  <CpuCoreBars cores={cores} />
34
39
  <p className="text-[11px] text-text-subtle truncate" title={model}>
35
40
  {model}
36
41
  </p>
37
- </div>
42
+ </CardShell>
38
43
  );
39
44
  }
@@ -1,5 +1,6 @@
1
1
  import { formatBps } from "@/lib/format-bytes";
2
2
  import { MetricChartCanvas } from "../metric-chart-canvas";
3
+ import { CardShell } from "./card-shell";
3
4
 
4
5
  export interface DiskCardProps {
5
6
  available: boolean;
@@ -10,14 +11,17 @@ export interface DiskCardProps {
10
11
  /** True while the stream has not yet delivered a second tick — a rate needs two
11
12
  * samples, so `available:false` here is expected, not a missing collector. */
12
13
  measuring?: boolean;
14
+ /** Opens the Performance page on the busiest device of this kind. */
15
+ onOpen?: () => void;
13
16
  }
14
17
 
15
- export function DiskCard({ available, inBps, outBps, readSeries, writeSeries, measuring }: DiskCardProps) {
18
+ export function DiskCard({ available, inBps, outBps, readSeries, writeSeries, measuring, onOpen }: DiskCardProps) {
16
19
  return (
17
- <div
18
- className="rounded-lg border border-border p-4 space-y-2"
19
- data-testid="sysmon-card-disk"
20
- data-available={available}
20
+ <CardShell
21
+ testId="sysmon-card-disk"
22
+ data={{ "data-available": available }}
23
+ onOpen={onOpen}
24
+ openLabel="Disk details"
21
25
  >
22
26
  <h3 className="text-sm font-medium">Disk</h3>
23
27
  {available ? (
@@ -28,6 +32,7 @@ export function DiskCard({ available, inBps, outBps, readSeries, writeSeries, me
28
32
  { data: writeSeries, color: "var(--color-warning)" },
29
33
  ]}
30
34
  height={56}
35
+ grid
31
36
  />
32
37
  <p className="text-[11px] text-text-subtle">
33
38
  Read {formatBps(inBps)} · Write {formatBps(outBps)}
@@ -36,6 +41,6 @@ export function DiskCard({ available, inBps, outBps, readSeries, writeSeries, me
36
41
  ) : (
37
42
  <p className="text-[11px] text-text-subtle">{measuring ? "measuring…" : "n/a"}</p>
38
43
  )}
39
- </div>
44
+ </CardShell>
40
45
  );
41
46
  }
@@ -1,5 +1,6 @@
1
1
  import { formatRam } from "@/lib/format-bytes";
2
2
  import { MetricChartCanvas } from "../metric-chart-canvas";
3
+ import { CardShell } from "./card-shell";
3
4
 
4
5
  export interface GpuCardProps {
5
6
  name: string;
@@ -7,13 +8,15 @@ export interface GpuCardProps {
7
8
  vramUsedMB: number;
8
9
  vramTotalMB: number;
9
10
  series: number[];
11
+ /** Opens the Performance page on this GPU. */
12
+ onOpen?: () => void;
10
13
  }
11
14
 
12
15
  /** One card per GPU. The caller (`overview-panel.tsx`) renders zero of these when
13
16
  * `system.gpus` is empty — hide, never a disabled placeholder card. */
14
- export function GpuCard({ name, utilPercent, vramUsedMB, vramTotalMB, series }: GpuCardProps) {
17
+ export function GpuCard({ name, utilPercent, vramUsedMB, vramTotalMB, series, onOpen }: GpuCardProps) {
15
18
  return (
16
- <div className="rounded-lg border border-border p-4 space-y-2" data-testid="sysmon-card-gpu">
19
+ <CardShell testId="sysmon-card-gpu" onOpen={onOpen} openLabel={`${name} details`}>
17
20
  <div className="flex items-baseline justify-between gap-2">
18
21
  <h3 className="text-sm font-medium truncate" title={name}>
19
22
  {name}
@@ -24,10 +27,17 @@ export function GpuCard({ name, utilPercent, vramUsedMB, vramTotalMB, series }:
24
27
  series={[{ data: series, color: "var(--color-primary)" }]}
25
28
  height={56}
26
29
  maxValue={100}
30
+ grid
27
31
  />
28
- <p className="text-[11px] text-text-subtle">
29
- VRAM {formatRam(vramUsedMB)} / {formatRam(vramTotalMB)}
30
- </p>
31
- </div>
32
+ {/* A total of 0 is the contract's "this device has no dedicated memory" — an
33
+ integrated GPU — not a card with an empty one. Saying "0 MB / 0 MB" states
34
+ a measurement that was never taken, and disagrees with the Performance
35
+ page's GPU detail, which renders the same case as an em dash. */}
36
+ {vramTotalMB > 0 && (
37
+ <p className="text-[11px] text-text-subtle">
38
+ VRAM {formatRam(vramUsedMB)} / {formatRam(vramTotalMB)}
39
+ </p>
40
+ )}
41
+ </CardShell>
32
42
  );
33
43
  }
@@ -1,19 +1,23 @@
1
1
  import { formatRam } from "@/lib/format-bytes";
2
2
  import { MetricChartCanvas } from "../metric-chart-canvas";
3
+ import { CardShell } from "./card-shell";
3
4
 
4
5
  export interface MemCardProps {
5
6
  usedMB: number;
6
7
  totalMB: number;
7
8
  percent: number;
8
9
  series: number[];
10
+ /** Opens the Performance page on this device. */
11
+ onOpen?: () => void;
9
12
  }
10
13
 
11
- export function MemCard({ usedMB, totalMB, percent, series }: MemCardProps) {
14
+ export function MemCard({ usedMB, totalMB, percent, series, onOpen }: MemCardProps) {
12
15
  return (
13
- <div
14
- className="rounded-lg border border-border p-4 space-y-2"
15
- data-testid="sysmon-card-mem"
16
- data-mem-percent={percent}
16
+ <CardShell
17
+ testId="sysmon-card-mem"
18
+ data={{ "data-mem-percent": percent }}
19
+ onOpen={onOpen}
20
+ openLabel="Memory details"
17
21
  >
18
22
  <div className="flex items-baseline justify-between">
19
23
  <h3 className="text-sm font-medium">Memory</h3>
@@ -23,10 +27,11 @@ export function MemCard({ usedMB, totalMB, percent, series }: MemCardProps) {
23
27
  series={[{ data: series, color: "var(--color-primary)" }]}
24
28
  height={56}
25
29
  maxValue={100}
30
+ grid
26
31
  />
27
32
  <p className="text-[11px] text-text-subtle">
28
33
  {formatRam(usedMB)} / {formatRam(totalMB)}
29
34
  </p>
30
- </div>
35
+ </CardShell>
31
36
  );
32
37
  }
@@ -1,5 +1,6 @@
1
1
  import { formatBps } from "@/lib/format-bytes";
2
2
  import { MetricChartCanvas } from "../metric-chart-canvas";
3
+ import { CardShell } from "./card-shell";
3
4
 
4
5
  export interface NetCardProps {
5
6
  available: boolean;
@@ -10,14 +11,17 @@ export interface NetCardProps {
10
11
  /** True while the stream has not yet delivered a second tick — a rate needs two
11
12
  * samples, so `available:false` here is expected, not a missing collector. */
12
13
  measuring?: boolean;
14
+ /** Opens the Performance page on the busiest device of this kind. */
15
+ onOpen?: () => void;
13
16
  }
14
17
 
15
- export function NetCard({ available, inBps, outBps, downSeries, upSeries, measuring }: NetCardProps) {
18
+ export function NetCard({ available, inBps, outBps, downSeries, upSeries, measuring, onOpen }: NetCardProps) {
16
19
  return (
17
- <div
18
- className="rounded-lg border border-border p-4 space-y-2"
19
- data-testid="sysmon-card-net"
20
- data-available={available}
20
+ <CardShell
21
+ testId="sysmon-card-net"
22
+ data={{ "data-available": available }}
23
+ onOpen={onOpen}
24
+ openLabel="Network details"
21
25
  >
22
26
  <h3 className="text-sm font-medium">Network</h3>
23
27
  {available ? (
@@ -28,6 +32,7 @@ export function NetCard({ available, inBps, outBps, downSeries, upSeries, measur
28
32
  { data: upSeries, color: "var(--color-warning)" },
29
33
  ]}
30
34
  height={56}
35
+ grid
31
36
  />
32
37
  <p className="text-[11px] text-text-subtle">
33
38
  Down {formatBps(inBps)} · Up {formatBps(outBps)}
@@ -36,6 +41,6 @@ export function NetCard({ available, inBps, outBps, downSeries, upSeries, measur
36
41
  ) : (
37
42
  <p className="text-[11px] text-text-subtle">{measuring ? "measuring…" : "n/a"}</p>
38
43
  )}
39
- </div>
44
+ </CardShell>
40
45
  );
41
46
  }
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Which Performance device an Overview card opens.
3
+ *
4
+ * Three of the five cards have a 1-to-1 target and need no logic: CPU is `cpu`,
5
+ * Memory is `memory`, and each GPU card already knows its own GPU. The Disk and
6
+ * Network cards are the awkward pair — they show **whole-machine** rates while
7
+ * the Performance sidebar lists every drive and every interface separately (two
8
+ * drives and seven interfaces on an ordinary desktop), so a card click has to
9
+ * choose one.
10
+ *
11
+ * It chooses the busiest, because that is what the reader was looking at: you
12
+ * click a Disk card that says "Write 191 MB/s" to find out which drive is doing
13
+ * it. The cost, accepted deliberately: the destination is not fixed, so the same
14
+ * card can open Disk 1 now and Disk 0 later. The alternative — always the first
15
+ * device — is predictable and usually wrong, since `Disk 0` on this host is an
16
+ * idle Toshiba while the loaded drive is `Disk 1`.
17
+ *
18
+ * Each metric matches the figure its own surface already shows, so the jump never
19
+ * contradicts what was on screen: **active time** for a drive (what the sidebar
20
+ * prints, and Mission Center's choice — a drive at 100% busy moving very little
21
+ * still matters) and **raw throughput** for an interface (what the card prints;
22
+ * normalising by link speed would rank a 100 Mbit NIC at 50% above a 10 Gbit one
23
+ * carrying ten times the traffic).
24
+ *
25
+ * Pure, React-free, relative imports only. The keys are `DeviceEntry.key`
26
+ * strings, so they are coupled to `performance/device-list.ts` by format — which
27
+ * is why the test asserts the key against a real `buildDeviceList` rather than
28
+ * against a literal. A key that matches no entry is not an error anywhere:
29
+ * `resolveSelected` silently falls back to the first entry, so the jump would
30
+ * quietly land on CPU.
31
+ */
32
+ import type { SystemMetrics } from "../../../types/system-metrics";
33
+
34
+ /** Highest-scoring entry, or null when there is nothing to pick from. Ties go to
35
+ * the first, so a wholly idle machine is at least deterministic. */
36
+ function busiest<T>(items: readonly T[], score: (item: T) => number | null): T | null {
37
+ let best: T | null = null;
38
+ let bestScore = -Infinity;
39
+ for (const item of items) {
40
+ const s = score(item);
41
+ if (s === null) continue;
42
+ if (s > bestScore) {
43
+ best = item;
44
+ bestScore = s;
45
+ }
46
+ }
47
+ // Every device unmeasurable (every `available: false`, i.e. the very first
48
+ // tick) still has to go somewhere, so fall back to the first one and let its
49
+ // page render the em dashes honestly.
50
+ return best ?? items[0] ?? null;
51
+ }
52
+
53
+ /** The drive with the most active time. Null when the host reports no drives. */
54
+ export function busiestDiskKey(system: SystemMetrics): string | null {
55
+ const disk = busiest(system.disks ?? [], (d) => (d.available ? d.busyPercent : null));
56
+ return disk ? `disk:${disk.id}` : null;
57
+ }
58
+
59
+ /** The interface carrying the most traffic. Null when the host reports none. */
60
+ export function busiestNicKey(system: SystemMetrics): string | null {
61
+ const nic = busiest(system.nics ?? [], (n) => (n.available ? n.rxBps + n.txBps : null));
62
+ return nic ? `nic:${nic.id}` : null;
63
+ }
64
+
65
+ /** The sidebar key for one GPU, matching `buildDeviceList`'s own fallback to the
66
+ * index for a device with no PCI address. */
67
+ export function gpuKey(id: string | undefined, index: number): string {
68
+ return `gpu:${id ?? index}`;
69
+ }
@@ -5,10 +5,14 @@ import { MemCard } from "./overview-cards/mem-card";
5
5
  import { DiskCard } from "./overview-cards/disk-card";
6
6
  import { NetCard } from "./overview-cards/net-card";
7
7
  import { GpuCard } from "./overview-cards/gpu-card";
8
+ import { busiestDiskKey, busiestNicKey, gpuKey } from "./overview-device-target";
8
9
 
9
10
  export interface OverviewPanelProps {
10
11
  system: SystemMetrics;
11
12
  history: MetricsHistoryPoint[];
13
+ /** Opens the Performance tab on one device. Absent in a read-only render (and
14
+ * then every card stays a plain frame rather than a button that does nothing). */
15
+ onOpenDevice?: (key: string) => void;
12
16
  }
13
17
 
14
18
  const SERIES_POINTS = 200;
@@ -42,12 +46,17 @@ function useOverviewSeries(history: MetricsHistoryPoint[]) {
42
46
  }, [history]);
43
47
  }
44
48
 
45
- export function OverviewPanel({ system, history }: OverviewPanelProps) {
49
+ export function OverviewPanel({ system, history, onOpenDevice }: OverviewPanelProps) {
46
50
  const series = useOverviewSeries(history);
47
51
  // Disk/net rates need a delta between two samples — `available:false` on the very
48
52
  // first frame(s) is the collector doing exactly what it should, not a missing
49
53
  // source, so the card says so instead of the flat, indistinguishable "n/a".
50
54
  const measuring = history.length <= 1;
55
+ // Undefined rather than a no-op handler when there is no device to open, so
56
+ // `CardShell` renders a frame instead of a dead button. Computed per render
57
+ // because the busiest drive and interface change with the tick.
58
+ const open = (key: string | null) =>
59
+ onOpenDevice && key ? () => onOpenDevice(key) : undefined;
51
60
 
52
61
  return (
53
62
  <div
@@ -59,12 +68,14 @@ export function OverviewPanel({ system, history }: OverviewPanelProps) {
59
68
  cores={system.cpu.cores}
60
69
  model={system.cpu.model}
61
70
  series={series.cpu}
71
+ onOpen={open("cpu")}
62
72
  />
63
73
  <MemCard
64
74
  usedMB={system.mem.usedMB}
65
75
  totalMB={system.mem.totalMB}
66
76
  percent={system.mem.percent}
67
77
  series={series.mem}
78
+ onOpen={open("memory")}
68
79
  />
69
80
  <DiskCard
70
81
  available={system.disk.available}
@@ -73,6 +84,7 @@ export function OverviewPanel({ system, history }: OverviewPanelProps) {
73
84
  readSeries={series.diskRead}
74
85
  writeSeries={series.diskWrite}
75
86
  measuring={measuring}
87
+ onOpen={open(busiestDiskKey(system))}
76
88
  />
77
89
  <NetCard
78
90
  available={system.net.available}
@@ -81,6 +93,7 @@ export function OverviewPanel({ system, history }: OverviewPanelProps) {
81
93
  downSeries={series.netDown}
82
94
  upSeries={series.netUp}
83
95
  measuring={measuring}
96
+ onOpen={open(busiestNicKey(system))}
84
97
  />
85
98
  {system.gpus.map((gpu, i) => (
86
99
  <GpuCard
@@ -90,6 +103,7 @@ export function OverviewPanel({ system, history }: OverviewPanelProps) {
90
103
  vramUsedMB={gpu.vramUsedMB}
91
104
  vramTotalMB={gpu.vramTotalMB}
92
105
  series={series.gpuUtil[i] ?? []}
106
+ onOpen={open(gpuKey(gpu.id, i))}
93
107
  />
94
108
  ))}
95
109
  </div>
@@ -0,0 +1,74 @@
1
+ /**
2
+ * One graph per logical processor — Mission Center's "Logical Processors" top
3
+ * graph, which is the view that makes a hybrid part legible: on a 12900K the
4
+ * eight P-cores and their SMT siblings move quite differently from the eight
5
+ * E-cores, and a single overall line says none of that.
6
+ *
7
+ * Each cell draws its OWN history rather than a bar of the current value, so a
8
+ * thread that spiked two seconds ago is still visible — which is the whole point
9
+ * of a graph over a meter.
10
+ */
11
+ import { useRef, useMemo } from "react";
12
+ import { useElementWidth } from "@/hooks/use-element-width";
13
+ import { coreGridLayout } from "@/lib/cpu-graph-mode";
14
+ import { MetricChartCanvas } from "../metric-chart-canvas";
15
+ import { CHART_COLORS } from "./detail-parts";
16
+ import type { MetricsHistoryPoint } from "../../../../types/system-metrics";
17
+
18
+ export interface CpuCoreGridProps {
19
+ /** Current reading per logical processor — the length is what decides the grid. */
20
+ cores: readonly number[];
21
+ history: readonly MetricsHistoryPoint[];
22
+ points?: number;
23
+ /** Total height the grid may use; each row gets an equal share. */
24
+ height?: number;
25
+ }
26
+
27
+ export function CpuCoreGrid({ cores, history, points = 200, height = 260 }: CpuCoreGridProps) {
28
+ const ref = useRef<HTMLDivElement>(null);
29
+ const width = useElementWidth(ref);
30
+ const { cols, rows } = coreGridLayout(cores.length, width);
31
+
32
+ // One pass over the window building every cell's series together, rather than
33
+ // twenty-four separate `.map`s over the same 200 points on every tick.
34
+ const series = useMemo(() => {
35
+ const window = history.slice(-points);
36
+ const out: number[][] = Array.from({ length: cores.length }, () => []);
37
+ for (const point of window) {
38
+ const values = point.system.cpu.cores;
39
+ for (let i = 0; i < out.length; i++) out[i]!.push(values[i] ?? 0);
40
+ }
41
+ return out;
42
+ }, [history, points, cores.length]);
43
+
44
+ if (cores.length === 0) return null;
45
+
46
+ // A cell is short; the ruled background would be denser than the curve, so only
47
+ // the frame is drawn and the grid stays on the full-width graphs.
48
+ const cellHeight = Math.max(28, Math.floor(height / Math.max(1, rows)) - 6);
49
+
50
+ return (
51
+ <div
52
+ ref={ref}
53
+ className="grid gap-1.5"
54
+ style={{ gridTemplateColumns: `repeat(${Math.max(1, cols)}, minmax(0, 1fr))` }}
55
+ data-testid="sysmon-core-grid"
56
+ data-core-count={cores.length}
57
+ data-cols={cols}
58
+ >
59
+ {series.map((data, i) => (
60
+ <div
61
+ key={i}
62
+ className="rounded-sm border border-border/70 overflow-hidden px-0.5"
63
+ title={`CPU ${i}: ${(cores[i] ?? 0).toFixed(0)}%`}
64
+ >
65
+ <MetricChartCanvas
66
+ series={[{ data, color: CHART_COLORS.primary }]}
67
+ height={cellHeight}
68
+ maxValue={100}
69
+ />
70
+ </div>
71
+ ))}
72
+ </div>
73
+ );
74
+ }