@hienlh/ppm 0.23.6 → 0.23.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (701) hide show
  1. package/CHANGELOG.md +84 -0
  2. package/CLAUDE.md +21 -1
  3. package/Dockerfile.test +8 -1
  4. package/assets/skills/ppm/SKILL.md +1 -1
  5. package/assets/skills/ppm/references/cli-reference.md +4 -4
  6. package/assets/skills/ppm/references/http-api.md +29 -1
  7. package/dist/web/assets/accounts-settings-section-BYWnY9hH.js +1 -0
  8. package/dist/web/assets/accounts-settings-section-BYWnY9hH.js.br +0 -0
  9. package/dist/web/assets/accounts-settings-section-BYWnY9hH.js.gz +0 -0
  10. package/dist/web/assets/{ai-resource-editor-Dn_wB-o5.js → ai-resource-editor-CY4n_Ccv.js} +1 -1
  11. package/dist/web/assets/ai-resource-editor-CY4n_Ccv.js.br +0 -0
  12. package/dist/web/assets/ai-resource-editor-CY4n_Ccv.js.gz +0 -0
  13. package/dist/web/assets/ai-settings-section-Bs3iUW4j.js +1 -0
  14. package/dist/web/assets/ai-settings-section-Bs3iUW4j.js.br +0 -0
  15. package/dist/web/assets/ai-settings-section-Bs3iUW4j.js.gz +0 -0
  16. package/dist/web/assets/ai-settings-section-DDs11XV4.js +1 -0
  17. package/dist/web/assets/api-client-CJPnCOG-.js +1 -0
  18. package/dist/web/assets/{api-client-c8YOpTlT.js → api-client-D-SMbdiH.js} +1 -1
  19. package/dist/web/assets/api-client-D-SMbdiH.js.br +0 -0
  20. package/dist/web/assets/api-client-D-SMbdiH.js.gz +0 -0
  21. package/dist/web/assets/api-settings-BDkkhFMq.js +1 -0
  22. package/dist/web/assets/{api-settings-BmvNoCbn.js → api-settings-Bv9mLCty.js} +1 -1
  23. package/dist/web/assets/api-settings-Bv9mLCty.js.br +0 -0
  24. package/dist/web/assets/api-settings-Bv9mLCty.js.gz +0 -0
  25. package/dist/web/assets/{api-themes-6fOQJgM9.js → api-themes-3wW-zLzU.js} +1 -1
  26. package/dist/web/assets/appearance-settings-section-C0BoIBmz.js +1 -0
  27. package/dist/web/assets/appearance-settings-section-C0BoIBmz.js.br +0 -0
  28. package/dist/web/assets/appearance-settings-section-C0BoIBmz.js.gz +0 -0
  29. package/dist/web/assets/apps-panel-DXAFsveZ.js +1 -0
  30. package/dist/web/assets/apps-panel-DXAFsveZ.js.br +0 -0
  31. package/dist/web/assets/apps-panel-DXAFsveZ.js.gz +0 -0
  32. package/dist/web/assets/{audio-preview-vaG2cB-k.js → audio-preview-BfES4Cx5.js} +1 -1
  33. package/dist/web/assets/audio-preview-BfES4Cx5.js.br +0 -0
  34. package/dist/web/assets/audio-preview-BfES4Cx5.js.gz +0 -0
  35. package/dist/web/assets/branch-review-tab-CA8hPSX9.js +1 -0
  36. package/dist/web/assets/branch-review-tab-CA8hPSX9.js.br +0 -0
  37. package/dist/web/assets/branch-review-tab-CA8hPSX9.js.gz +0 -0
  38. package/dist/web/assets/{button-Ci9EUgqd.js → button-DeAyLH9U.js} +1 -1
  39. package/dist/web/assets/button-DeAyLH9U.js.br +0 -0
  40. package/dist/web/assets/button-DeAyLH9U.js.gz +0 -0
  41. package/dist/web/assets/{chat-preparation-cache-BSIQGiWx.js → chat-preparation-cache-CcCd2g7A.js} +1 -1
  42. package/dist/web/assets/chat-preparation-cache-CcCd2g7A.js.br +0 -0
  43. package/dist/web/assets/chat-preparation-cache-CcCd2g7A.js.gz +0 -0
  44. package/dist/web/assets/chat-tab-BWi_bUzA.js +1 -0
  45. package/dist/web/assets/chat-tab-BWi_bUzA.js.br +0 -0
  46. package/dist/web/assets/chat-tab-BWi_bUzA.js.gz +0 -0
  47. package/dist/web/assets/chat-tab-BvJhIaVE.js +15 -0
  48. package/dist/web/assets/chat-tab-BvJhIaVE.js.br +0 -0
  49. package/dist/web/assets/chat-tab-BvJhIaVE.js.gz +0 -0
  50. package/dist/web/assets/code-editor-OJUdLVnn.js +7 -0
  51. package/dist/web/assets/code-editor-OJUdLVnn.js.br +0 -0
  52. package/dist/web/assets/code-editor-OJUdLVnn.js.gz +0 -0
  53. package/dist/web/assets/codex-reset-credit-button-Dgxy_VNp.js +1 -0
  54. package/dist/web/assets/codex-reset-credit-button-Dgxy_VNp.js.br +0 -0
  55. package/dist/web/assets/codex-reset-credit-button-Dgxy_VNp.js.gz +0 -0
  56. package/dist/web/assets/{conflict-editor-BA3y-qSH.js → conflict-editor-BpKW_vbL.js} +1 -1
  57. package/dist/web/assets/conflict-editor-BpKW_vbL.js.br +0 -0
  58. package/dist/web/assets/conflict-editor-BpKW_vbL.js.gz +0 -0
  59. package/dist/web/assets/context-menu-7OX80HDB.js +1 -0
  60. package/dist/web/assets/context-menu-7OX80HDB.js.br +0 -0
  61. package/dist/web/assets/context-menu-7OX80HDB.js.gz +0 -0
  62. package/dist/web/assets/{csv-preview-BioxkrQF.js → csv-preview-COYdTABa.js} +1 -1
  63. package/dist/web/assets/csv-preview-COYdTABa.js.br +0 -0
  64. package/dist/web/assets/csv-preview-COYdTABa.js.gz +0 -0
  65. package/dist/web/assets/{data-grid-overlay-editor-CQRVKr7y.js → data-grid-overlay-editor-CeZoduke.js} +1 -1
  66. package/dist/web/assets/data-grid-overlay-editor-CeZoduke.js.br +0 -0
  67. package/dist/web/assets/data-grid-overlay-editor-CeZoduke.js.gz +0 -0
  68. package/dist/web/assets/{database-viewer-BSoJ0E6p.js → database-viewer-BQcBqCKm.js} +1 -1
  69. package/dist/web/assets/database-viewer-BQcBqCKm.js.br +0 -0
  70. package/dist/web/assets/database-viewer-BQcBqCKm.js.gz +0 -0
  71. package/dist/web/assets/{design-export-client-ChMcMoqW.js → design-export-client-OrnGCSwu.js} +1 -1
  72. package/dist/web/assets/design-export-client-OrnGCSwu.js.br +0 -0
  73. package/dist/web/assets/design-export-client-OrnGCSwu.js.gz +0 -0
  74. package/dist/web/assets/{design-responsive-dialog-DNBhJJLf.js → design-responsive-dialog-vJjQrC4n.js} +1 -1
  75. package/dist/web/assets/design-responsive-dialog-vJjQrC4n.js.br +0 -0
  76. package/dist/web/assets/design-responsive-dialog-vJjQrC4n.js.gz +0 -0
  77. package/dist/web/assets/design-tab-BbmFk38H.js +33 -0
  78. package/dist/web/assets/design-tab-BbmFk38H.js.br +0 -0
  79. package/dist/web/assets/design-tab-BbmFk38H.js.gz +0 -0
  80. package/dist/web/assets/{designs-sidebar-panel-DHh5QsH9.js → designs-sidebar-panel-D2kXwB8B.js} +1 -1
  81. package/dist/web/assets/designs-sidebar-panel-D2kXwB8B.js.br +0 -0
  82. package/dist/web/assets/designs-sidebar-panel-D2kXwB8B.js.gz +0 -0
  83. package/dist/web/assets/dialog-Bocc0Fgb.js +1 -0
  84. package/dist/web/assets/dialog-Bocc0Fgb.js.br +0 -0
  85. package/dist/web/assets/dialog-Bocc0Fgb.js.gz +0 -0
  86. package/dist/web/assets/{diff-viewer-lctWoSmG.js → diff-viewer-Bj4DT6Mj.js} +1 -1
  87. package/dist/web/assets/diff-viewer-Bj4DT6Mj.js.br +0 -0
  88. package/dist/web/assets/diff-viewer-Bj4DT6Mj.js.gz +0 -0
  89. package/dist/web/assets/{docx-preview-C9XdKEj1.js → docx-preview-C2QqNGRE.js} +1 -1
  90. package/dist/web/assets/docx-preview-C2QqNGRE.js.br +0 -0
  91. package/dist/web/assets/docx-preview-C2QqNGRE.js.gz +0 -0
  92. package/dist/web/assets/editor-language-service-COqB2tuv.js +1 -0
  93. package/dist/web/assets/editor-language-service-COqB2tuv.js.br +3 -0
  94. package/dist/web/assets/editor-language-service-COqB2tuv.js.gz +0 -0
  95. package/dist/web/assets/explorer-body-DGrYajDN.js +2 -0
  96. package/dist/web/assets/explorer-body-DGrYajDN.js.br +0 -0
  97. package/dist/web/assets/explorer-body-DGrYajDN.js.gz +0 -0
  98. package/dist/web/assets/explorer-window-content-DLzkODTP.js +1 -0
  99. package/dist/web/assets/explorer-window-content-DLzkODTP.js.br +0 -0
  100. package/dist/web/assets/explorer-window-content-DLzkODTP.js.gz +0 -0
  101. package/dist/web/assets/{extension-manager-section-rbkXsZVR.js → extension-manager-section-Bu0qcB2i.js} +1 -1
  102. package/dist/web/assets/extension-manager-section-Bu0qcB2i.js.br +0 -0
  103. package/dist/web/assets/extension-manager-section-Bu0qcB2i.js.gz +0 -0
  104. package/dist/web/assets/{extension-webview-uPO0WgCq.js → extension-webview-G_WJ0N52.js} +1 -1
  105. package/dist/web/assets/extension-webview-G_WJ0N52.js.br +0 -0
  106. package/dist/web/assets/extension-webview-G_WJ0N52.js.gz +0 -0
  107. package/dist/web/assets/{file-icons-gx_FBOXY.js → file-icons-l7fNOmdS.js} +1 -1
  108. package/dist/web/assets/file-icons-l7fNOmdS.js.br +0 -0
  109. package/dist/web/assets/file-icons-l7fNOmdS.js.gz +0 -0
  110. package/dist/web/assets/{file-store-D9KE0kQC.js → file-store-B0e7sLag.js} +1 -1
  111. package/dist/web/assets/file-store-B0e7sLag.js.br +0 -0
  112. package/dist/web/assets/file-store-B0e7sLag.js.gz +0 -0
  113. package/dist/web/assets/{files-settings-section-CT7mDb0L.js → files-settings-section-ChZ_CynX.js} +1 -1
  114. package/dist/web/assets/files-settings-section-ChZ_CynX.js.br +0 -0
  115. package/dist/web/assets/files-settings-section-ChZ_CynX.js.gz +0 -0
  116. package/dist/web/assets/format-bytes-__396eCN.js +1 -0
  117. package/dist/web/assets/{format-file-meta-mQwA6SuY.js → format-file-meta-o1XBuoKS.js} +1 -1
  118. package/dist/web/assets/format-file-meta-o1XBuoKS.js.br +0 -0
  119. package/dist/web/assets/format-file-meta-o1XBuoKS.js.gz +0 -0
  120. package/dist/web/assets/{fs-api-DL36slbd.js → fs-api-CeHKwx95.js} +1 -1
  121. package/dist/web/assets/fs-api-CeHKwx95.js.br +0 -0
  122. package/dist/web/assets/fs-api-CeHKwx95.js.gz +0 -0
  123. package/dist/web/assets/{general-settings-section-DANPfMRN.js → general-settings-section-MSvDEbFa.js} +1 -1
  124. package/dist/web/assets/general-settings-section-MSvDEbFa.js.br +0 -0
  125. package/dist/web/assets/general-settings-section-MSvDEbFa.js.gz +0 -0
  126. package/dist/web/assets/{git-log-panel-BJPkLiEw.js → git-log-panel-gw5_a6j3.js} +1 -1
  127. package/dist/web/assets/git-log-panel-gw5_a6j3.js.br +0 -0
  128. package/dist/web/assets/git-log-panel-gw5_a6j3.js.gz +0 -0
  129. package/dist/web/assets/{git-repo-store-DSypNj19.js → git-repo-store-BpPnah5l.js} +1 -1
  130. package/dist/web/assets/git-repo-store-BpPnah5l.js.br +0 -0
  131. package/dist/web/assets/git-repo-store-BpPnah5l.js.gz +0 -0
  132. package/dist/web/assets/{glide-data-grid-R4PcAntf.js → glide-data-grid-Db2Cl26B.js} +5 -5
  133. package/dist/web/assets/glide-data-grid-Db2Cl26B.js.br +0 -0
  134. package/dist/web/assets/glide-data-grid-Db2Cl26B.js.gz +0 -0
  135. package/dist/web/assets/group-chat-tab-B4etmYTR.js +1 -0
  136. package/dist/web/assets/group-chat-tab-B4etmYTR.js.br +0 -0
  137. package/dist/web/assets/group-chat-tab-B4etmYTR.js.gz +0 -0
  138. package/dist/web/assets/{image-preview-CGdZrmLo.js → image-preview-CjNhpfWw.js} +1 -1
  139. package/dist/web/assets/index-CtAvmybi.js +52 -0
  140. package/dist/web/assets/index-CtAvmybi.js.br +0 -0
  141. package/dist/web/assets/index-CtAvmybi.js.gz +0 -0
  142. package/dist/web/assets/index-DeCJasyy.css +1 -0
  143. package/dist/web/assets/index-DeCJasyy.css.br +0 -0
  144. package/dist/web/assets/index-DeCJasyy.css.gz +0 -0
  145. package/dist/web/assets/{jira-watcher-section-DHRoyWcG.js → jira-watcher-section-CKSI1Alo.js} +1 -1
  146. package/dist/web/assets/keybindings-store-C4_yyU4u.js +1 -0
  147. package/dist/web/assets/{keyboard-shortcuts-section-BKej4mUf.js → keyboard-shortcuts-section-CEaVUc9a.js} +1 -1
  148. package/dist/web/assets/keyboard-shortcuts-section-CEaVUc9a.js.br +0 -0
  149. package/dist/web/assets/keyboard-shortcuts-section-CEaVUc9a.js.gz +0 -0
  150. package/dist/web/assets/language-servers-section-ePtEpnDc.js +2 -0
  151. package/dist/web/assets/language-servers-section-ePtEpnDc.js.br +0 -0
  152. package/dist/web/assets/language-servers-section-ePtEpnDc.js.gz +0 -0
  153. package/dist/web/assets/lsp-client-XzmR3Brr.js +1 -0
  154. package/dist/web/assets/lsp-client-XzmR3Brr.js.br +0 -0
  155. package/dist/web/assets/lsp-client-XzmR3Brr.js.gz +0 -0
  156. package/dist/web/assets/markdown-renderer-CTtDap-l.js +1 -0
  157. package/dist/web/assets/{markdown-renderer-BHtYqkYZ.js → markdown-renderer-D05fAr57.js} +2 -2
  158. package/dist/web/assets/markdown-renderer-D05fAr57.js.br +0 -0
  159. package/dist/web/assets/markdown-renderer-D05fAr57.js.gz +0 -0
  160. package/dist/web/assets/{media-url-CzUJrREv.js → media-url-C6NumuN5.js} +1 -1
  161. package/dist/web/assets/metric-chart-canvas-DHJe0VER.js +1 -0
  162. package/dist/web/assets/metric-chart-canvas-DHJe0VER.js.br +0 -0
  163. package/dist/web/assets/metric-chart-canvas-DHJe0VER.js.gz +0 -0
  164. package/dist/web/assets/{mobile-bottom-sheet-CuNi2FRv.js → mobile-bottom-sheet-D4UyOatB.js} +1 -1
  165. package/dist/web/assets/mobile-bottom-sheet-D4UyOatB.js.br +0 -0
  166. package/dist/web/assets/mobile-bottom-sheet-D4UyOatB.js.gz +0 -0
  167. package/dist/web/assets/mobile-explorer-sheet-CcfGdGL8.js +1 -0
  168. package/dist/web/assets/mobile-explorer-sheet-CcfGdGL8.js.br +0 -0
  169. package/dist/web/assets/mobile-explorer-sheet-CcfGdGL8.js.gz +0 -0
  170. package/dist/web/assets/{new-design-dialog-DS_XrpTG.js → new-design-dialog-BgmQopJM.js} +1 -1
  171. package/dist/web/assets/new-design-dialog-BgmQopJM.js.br +0 -0
  172. package/dist/web/assets/new-design-dialog-BgmQopJM.js.gz +0 -0
  173. package/dist/web/assets/notification-store-q5QBklKA.js +1 -0
  174. package/dist/web/assets/{notifications-settings-section-C05WYqcE.js → notifications-settings-section-BBJ0r9OS.js} +1 -1
  175. package/dist/web/assets/notifications-settings-section-BBJ0r9OS.js.br +0 -0
  176. package/dist/web/assets/notifications-settings-section-BBJ0r9OS.js.gz +0 -0
  177. package/dist/web/assets/{onboarding-entry-CmUqv1kl.js → onboarding-entry-BYOYswsi.js} +1 -1
  178. package/dist/web/assets/onboarding-entry-BYOYswsi.js.br +0 -0
  179. package/dist/web/assets/onboarding-entry-BYOYswsi.js.gz +0 -0
  180. package/dist/web/assets/{onboarding-quick-orientation-DIhWv1CN.js → onboarding-quick-orientation-DPHYFMbA.js} +1 -1
  181. package/dist/web/assets/onboarding-quick-orientation-DPHYFMbA.js.br +0 -0
  182. package/dist/web/assets/onboarding-quick-orientation-DPHYFMbA.js.gz +0 -0
  183. package/dist/web/assets/overview-panel-pkPs44Tv.js +1 -0
  184. package/dist/web/assets/overview-panel-pkPs44Tv.js.br +0 -0
  185. package/dist/web/assets/overview-panel-pkPs44Tv.js.gz +0 -0
  186. package/dist/web/assets/{pdf-preview-qdXmMkOR.js → pdf-preview-c-L_kDAs.js} +1 -1
  187. package/dist/web/assets/pdf-preview-c-L_kDAs.js.br +0 -0
  188. package/dist/web/assets/pdf-preview-c-L_kDAs.js.gz +0 -0
  189. package/dist/web/assets/performance-panel-yPrq0DJV.js +3 -0
  190. package/dist/web/assets/performance-panel-yPrq0DJV.js.br +0 -0
  191. package/dist/web/assets/performance-panel-yPrq0DJV.js.gz +0 -0
  192. package/dist/web/assets/{postgres-viewer-Xvlun_n5.js → postgres-viewer-CnwDCMNd.js} +1 -1
  193. package/dist/web/assets/postgres-viewer-CnwDCMNd.js.br +0 -0
  194. package/dist/web/assets/postgres-viewer-CnwDCMNd.js.gz +0 -0
  195. package/dist/web/assets/{ppmbot-settings-section-D8AES1BA.js → ppmbot-settings-section-BDXoSIDp.js} +1 -1
  196. package/dist/web/assets/ppmbot-settings-section-BDXoSIDp.js.br +0 -0
  197. package/dist/web/assets/ppmbot-settings-section-BDXoSIDp.js.gz +0 -0
  198. package/dist/web/assets/{pptx-export-CG6MRNok.js → pptx-export-D0RDY48h.js} +4 -4
  199. package/dist/web/assets/pptx-export-D0RDY48h.js.br +0 -0
  200. package/dist/web/assets/pptx-export-D0RDY48h.js.gz +0 -0
  201. package/dist/web/assets/{problems-panel-DTBG4beI.js → problems-panel-BgY8oyo9.js} +1 -1
  202. package/dist/web/assets/problems-panel-BgY8oyo9.js.br +0 -0
  203. package/dist/web/assets/problems-panel-BgY8oyo9.js.gz +0 -0
  204. package/dist/web/assets/process-row-format-CaaMcHzn.js +1 -0
  205. package/dist/web/assets/process-table-BOwDtXuG.js +1 -0
  206. package/dist/web/assets/process-table-BOwDtXuG.js.br +0 -0
  207. package/dist/web/assets/process-table-BOwDtXuG.js.gz +0 -0
  208. package/dist/web/assets/{project-framework-store-XxFXcUpb.js → project-framework-store-UDEMu28U.js} +1 -1
  209. package/dist/web/assets/{project-store-C5gJXkvb.js → project-store-DGa31y5B.js} +1 -1
  210. package/dist/web/assets/project-store-DGa31y5B.js.br +0 -0
  211. package/dist/web/assets/project-store-DGa31y5B.js.gz +0 -0
  212. package/dist/web/assets/{proxy-settings-section-CqtmbeRj.js → proxy-settings-section-Db6Kc6xG.js} +1 -1
  213. package/dist/web/assets/proxy-settings-section-Db6Kc6xG.js.br +0 -0
  214. package/dist/web/assets/proxy-settings-section-Db6Kc6xG.js.gz +0 -0
  215. package/dist/web/assets/{query-audit-section-UKG_smyt.js → query-audit-section-C0PAXhfT.js} +1 -1
  216. package/dist/web/assets/query-audit-section-C0PAXhfT.js.br +0 -0
  217. package/dist/web/assets/query-audit-section-C0PAXhfT.js.gz +0 -0
  218. package/dist/web/assets/{remote-desktop-clipboard-notice-Djt6cpNL.js → remote-desktop-clipboard-notice-DOVtobj_.js} +1 -1
  219. package/dist/web/assets/remote-desktop-clipboard-notice-DOVtobj_.js.br +0 -0
  220. package/dist/web/assets/remote-desktop-clipboard-notice-DOVtobj_.js.gz +0 -0
  221. package/dist/web/assets/remote-desktop-mobile-sheet-DXlU3msM.js +2 -0
  222. package/dist/web/assets/remote-desktop-mobile-sheet-DXlU3msM.js.br +0 -0
  223. package/dist/web/assets/remote-desktop-mobile-sheet-DXlU3msM.js.gz +0 -0
  224. package/dist/web/assets/remote-desktop-mobile-view-ClV4YTLU.js +1 -0
  225. package/dist/web/assets/remote-desktop-mobile-view-ClV4YTLU.js.br +0 -0
  226. package/dist/web/assets/remote-desktop-mobile-view-ClV4YTLU.js.gz +0 -0
  227. package/dist/web/assets/{remote-desktop-readiness-gate-DNJF8TcF.js → remote-desktop-readiness-gate-BsfoJzdc.js} +1 -1
  228. package/dist/web/assets/remote-desktop-readiness-gate-BsfoJzdc.js.br +0 -0
  229. package/dist/web/assets/remote-desktop-readiness-gate-BsfoJzdc.js.gz +0 -0
  230. package/dist/web/assets/remote-desktop-window-content-kDaXl1_Q.js +1 -0
  231. package/dist/web/assets/remote-desktop-window-content-kDaXl1_Q.js.br +0 -0
  232. package/dist/web/assets/remote-desktop-window-content-kDaXl1_Q.js.gz +0 -0
  233. package/dist/web/assets/{schedules-settings-section-BKoPovy2.js → schedules-settings-section-CvbjQM8z.js} +1 -1
  234. package/dist/web/assets/schedules-settings-section-CvbjQM8z.js.br +0 -0
  235. package/dist/web/assets/schedules-settings-section-CvbjQM8z.js.gz +0 -0
  236. package/dist/web/assets/{scroll-area-XonvWYn_.js → scroll-area-sjOeAfoD.js} +1 -1
  237. package/dist/web/assets/scroll-area-sjOeAfoD.js.br +0 -0
  238. package/dist/web/assets/scroll-area-sjOeAfoD.js.gz +0 -0
  239. package/dist/web/assets/{separator-sQj04Ari.js → separator-9A3PCG1t.js} +1 -1
  240. package/dist/web/assets/services-panel-CimW47P8.js +1 -0
  241. package/dist/web/assets/services-panel-CimW47P8.js.br +0 -0
  242. package/dist/web/assets/services-panel-CimW47P8.js.gz +0 -0
  243. package/dist/web/assets/settings-body-BTXNtpWL.js +2 -0
  244. package/dist/web/assets/settings-body-BTXNtpWL.js.br +0 -0
  245. package/dist/web/assets/settings-body-BTXNtpWL.js.gz +0 -0
  246. package/dist/web/assets/settings-store-DvftLqzy.js +2 -0
  247. package/dist/web/assets/settings-store-DvftLqzy.js.br +0 -0
  248. package/dist/web/assets/settings-store-DvftLqzy.js.gz +0 -0
  249. package/dist/web/assets/settings-tab-CGhaRXjs.js +1 -0
  250. package/dist/web/assets/settings-window-content--Uyg_Psr.js +1 -0
  251. package/dist/web/assets/sortable-header-DUW9T1Hz.js +1 -0
  252. package/dist/web/assets/sortable-header-DUW9T1Hz.js.br +0 -0
  253. package/dist/web/assets/sortable-header-DUW9T1Hz.js.gz +0 -0
  254. package/dist/web/assets/{sql-query-editor-BjIMi9Wk.js → sql-query-editor-Dn-cgDrW.js} +1 -1
  255. package/dist/web/assets/sql-query-editor-Dn-cgDrW.js.br +0 -0
  256. package/dist/web/assets/sql-query-editor-Dn-cgDrW.js.gz +0 -0
  257. package/dist/web/assets/{sqlite-viewer-BNcA6Irq.js → sqlite-viewer-B0NfaMjq.js} +1 -1
  258. package/dist/web/assets/sqlite-viewer-B0NfaMjq.js.br +0 -0
  259. package/dist/web/assets/sqlite-viewer-B0NfaMjq.js.gz +0 -0
  260. package/dist/web/assets/system-monitor-body-CxCfRQFb.js +2 -0
  261. package/dist/web/assets/system-monitor-body-CxCfRQFb.js.br +0 -0
  262. package/dist/web/assets/system-monitor-body-CxCfRQFb.js.gz +0 -0
  263. package/dist/web/assets/system-monitor-tab-Cb3EZUdp.js +1 -0
  264. package/dist/web/assets/system-monitor-window-content-51CA-2PH.js +1 -0
  265. package/dist/web/assets/{tab-host-window-content-CIRGNCvi.js → tab-host-window-content-CSrcmKNG.js} +1 -1
  266. package/dist/web/assets/tab-host-window-content-CSrcmKNG.js.br +0 -0
  267. package/dist/web/assets/tab-host-window-content-CSrcmKNG.js.gz +0 -0
  268. package/dist/web/assets/{team-member-sheet-CwXpLi3X.js → team-member-sheet-D4X6nh-x.js} +2 -2
  269. package/dist/web/assets/team-member-sheet-D4X6nh-x.js.br +0 -0
  270. package/dist/web/assets/team-member-sheet-D4X6nh-x.js.gz +0 -0
  271. package/dist/web/assets/{team-member-window-content-4swiiDz7.js → team-member-window-content-BxkbGVIL.js} +1 -1
  272. package/dist/web/assets/team-member-window-content-BxkbGVIL.js.br +0 -0
  273. package/dist/web/assets/team-member-window-content-BxkbGVIL.js.gz +0 -0
  274. package/dist/web/assets/{terminal-tab-BGcdtMMT.js → terminal-tab-BYo34IqU.js} +3 -3
  275. package/dist/web/assets/terminal-tab-BYo34IqU.js.br +0 -0
  276. package/dist/web/assets/terminal-tab-BYo34IqU.js.gz +0 -0
  277. package/dist/web/assets/{tool-cards-D0-krtA2.js → tool-cards-DvXjOped.js} +4 -4
  278. package/dist/web/assets/tool-cards-DvXjOped.js.br +0 -0
  279. package/dist/web/assets/tool-cards-DvXjOped.js.gz +0 -0
  280. package/dist/web/assets/{use-blob-url-CmavyEP8.js → use-blob-url-CISBWKG5.js} +1 -1
  281. package/dist/web/assets/use-inline-blame-Br6mheS4.js +16 -0
  282. package/dist/web/assets/use-inline-blame-Br6mheS4.js.br +0 -0
  283. package/dist/web/assets/use-inline-blame-Br6mheS4.js.gz +0 -0
  284. package/dist/web/assets/use-lsp-BpJmvQ0n.js +6 -0
  285. package/dist/web/assets/use-lsp-BpJmvQ0n.js.br +0 -0
  286. package/dist/web/assets/use-lsp-BpJmvQ0n.js.gz +0 -0
  287. package/dist/web/assets/{use-monaco-theme-C88KphGx.js → use-monaco-theme-UGOzyIhv.js} +1 -1
  288. package/dist/web/assets/use-process-kill-CyiiUD1E.js +1 -0
  289. package/dist/web/assets/use-process-kill-CyiiUD1E.js.br +0 -0
  290. package/dist/web/assets/use-process-kill-CyiiUD1E.js.gz +0 -0
  291. package/dist/web/assets/{use-websocket-Chk9guIU.js → use-websocket-Dpl21cHG.js} +1 -1
  292. package/dist/web/assets/{vendor-ui-BHh12_0v.js → vendor-ui-P9Ym7hCv.js} +1 -1
  293. package/dist/web/assets/vendor-ui-P9Ym7hCv.js.br +0 -0
  294. package/dist/web/assets/vendor-ui-P9Ym7hCv.js.gz +0 -0
  295. package/dist/web/assets/video-preview-D6Jw-IZK.js +1 -0
  296. package/dist/web/assets/video-preview-D6Jw-IZK.js.br +0 -0
  297. package/dist/web/assets/video-preview-D6Jw-IZK.js.gz +0 -0
  298. package/dist/web/assets/voice-settings-section-CcHQDYzN.js +1 -0
  299. package/dist/web/assets/voice-settings-section-CcHQDYzN.js.br +0 -0
  300. package/dist/web/assets/voice-settings-section-CcHQDYzN.js.gz +0 -0
  301. package/dist/web/assets/ws-auth-CqI8-aoA.js +1 -0
  302. package/dist/web/index.html +20 -20
  303. package/dist/web/index.html.br +0 -0
  304. package/dist/web/index.html.gz +0 -0
  305. package/dist/web/sw.js +1 -1
  306. package/dist/web/sw.js.br +0 -0
  307. package/dist/web/sw.js.gz +0 -0
  308. package/docs/deployment-guide.md +23 -0
  309. package/package.json +1 -1
  310. package/release-from-worktree.sh +224 -0
  311. package/src/cli/commands/config-cmd.ts +12 -0
  312. package/src/providers/claude-agent-sdk.ts +65 -2
  313. package/src/providers/codex-app-server/codex-jsonrpc-client.ts +16 -1
  314. package/src/providers/codex-app-server/codex-provider.ts +39 -7
  315. package/src/providers/provider-probe.ts +63 -0
  316. package/src/providers/registry.ts +109 -29
  317. package/src/server/index.ts +9 -0
  318. package/src/server/middleware/auth.ts +5 -1
  319. package/src/server/routes/cross-origin-guard.ts +20 -0
  320. package/src/server/routes/git.ts +40 -4
  321. package/src/server/routes/lsp.ts +97 -4
  322. package/src/server/routes/resources.ts +72 -9
  323. package/src/server/routes/settings.ts +19 -1
  324. package/src/server/routes/speech.ts +66 -0
  325. package/src/server/routes/system-services.ts +76 -0
  326. package/src/server/routes/tunnel.ts +33 -1
  327. package/src/server/ws/chat.ts +74 -3
  328. package/src/services/codex-account-login.ts +26 -2
  329. package/src/services/codex-reset-credit.service.ts +16 -3
  330. package/src/services/compaction-savings.ts +127 -0
  331. package/src/services/db.service.ts +123 -8
  332. package/src/services/fs-ops/fs-ops-trash.service.ts +22 -9
  333. package/src/services/git-refs/for-each-ref.ts +118 -0
  334. package/src/services/git.service.ts +25 -2
  335. package/src/services/host-info/spawn-runner.ts +48 -4
  336. package/src/services/jsonl-transcript-parser.ts +7 -42
  337. package/src/services/lsp/lsp-install.ts +289 -0
  338. package/src/services/lsp/lsp-manager.ts +160 -29
  339. package/src/services/lsp/server-registry.ts +120 -4
  340. package/src/services/named-tunnel/named-tunnel-config.ts +8 -2
  341. package/src/services/named-tunnel/named-tunnel-setup.service.ts +4 -0
  342. package/src/services/read-lines.ts +54 -0
  343. package/src/services/speech-to-text/whisper-catalog.ts +142 -0
  344. package/src/services/speech-to-text/whisper-download.ts +113 -0
  345. package/src/services/speech-to-text/whisper-hallucinations.ts +51 -0
  346. package/src/services/speech-to-text/whisper-install.service.ts +247 -0
  347. package/src/services/speech-to-text/whisper-paths.ts +62 -0
  348. package/src/services/speech-to-text/whisper-transcribe.service.ts +117 -0
  349. package/src/services/supervisor.ts +94 -11
  350. package/src/services/system-metrics/cpu-details-linux.ts +252 -0
  351. package/src/services/system-metrics/cpu-memory-collector.ts +140 -18
  352. package/src/services/system-metrics/device-collector-linux.ts +31 -0
  353. package/src/services/system-metrics/device-collector-types.ts +40 -0
  354. package/src/services/system-metrics/disk-devices-linux.ts +156 -0
  355. package/src/services/system-metrics/disk-inventory-linux.ts +150 -0
  356. package/src/services/system-metrics/fans-linux.ts +51 -0
  357. package/src/services/system-metrics/gpu-api-versions.ts +120 -0
  358. package/src/services/system-metrics/gpu-devices-linux.ts +370 -0
  359. package/src/services/system-metrics/gpu-fdinfo-linux.ts +253 -0
  360. package/src/services/system-metrics/hardware-inventory.ts +50 -0
  361. package/src/services/system-metrics/linux-fs.ts +43 -0
  362. package/src/services/system-metrics/memory-darwin.ts +91 -0
  363. package/src/services/system-metrics/memory-linux.ts +156 -0
  364. package/src/services/system-metrics/net-devices-linux.ts +114 -0
  365. package/src/services/system-metrics/net-inventory-linux.ts +100 -0
  366. package/src/services/system-metrics/partitions-linux.ts +158 -0
  367. package/src/services/system-metrics/process-collector-linux.ts +58 -6
  368. package/src/services/system-metrics/process-collector-types.ts +8 -1
  369. package/src/services/system-metrics/process-details-darwin.ts +166 -0
  370. package/src/services/system-metrics/process-details-linux.ts +150 -0
  371. package/src/services/system-metrics/process-grouping.ts +2 -1
  372. package/src/services/system-metrics/process-rows-builder.ts +2 -0
  373. package/src/services/system-metrics/process-swap-linux.ts +37 -0
  374. package/src/services/system-metrics/signal-executor.ts +84 -0
  375. package/src/services/system-metrics/signal-request-handler.ts +92 -0
  376. package/src/services/system-metrics/system-metrics-platform.ts +30 -4
  377. package/src/services/system-metrics/system-metrics-tick.ts +73 -4
  378. package/src/services/system-metrics/system-metrics.service.ts +87 -2
  379. package/src/services/system-metrics/udev-db.ts +40 -0
  380. package/src/services/system-services/app-cgroup-linux.ts +115 -0
  381. package/src/services/system-services/app-icon-service.ts +31 -0
  382. package/src/services/system-services/app-icons-linux.ts +124 -0
  383. package/src/services/system-services/apps-linux.ts +174 -0
  384. package/src/services/system-services/desktop-entry.ts +103 -0
  385. package/src/services/system-services/service-guard.ts +124 -0
  386. package/src/services/system-services/systemd-collector.ts +203 -0
  387. package/src/services/system-services/systemd-parse.ts +162 -0
  388. package/src/shared/prompt-cache-idle.ts +197 -0
  389. package/src/shared/turn-usage.ts +85 -1
  390. package/src/types/chat.ts +27 -0
  391. package/src/types/config.ts +14 -0
  392. package/src/types/git.ts +41 -0
  393. package/src/types/system-hardware.ts +137 -0
  394. package/src/types/system-metrics.ts +231 -2
  395. package/src/types/system-services.ts +73 -0
  396. package/src/web/components/branch-review/branch-review-tab.tsx +20 -20
  397. package/src/web/components/branch-review/branch-review-tree-row.tsx +1 -13
  398. package/src/web/components/chat/chat-tab.tsx +3 -0
  399. package/src/web/components/chat/compaction-divider.tsx +48 -0
  400. package/src/web/components/chat/idle-cache-notice.tsx +67 -0
  401. package/src/web/components/chat/message-input.tsx +48 -13
  402. package/src/web/components/chat/message-list.tsx +15 -0
  403. package/src/web/components/chat/prompt-cache-chip.tsx +74 -0
  404. package/src/web/components/editor/code-editor.tsx +1 -0
  405. package/src/web/components/editor/editor-language-service.tsx +11 -3
  406. package/src/web/components/editor/lsp-status.tsx +115 -13
  407. package/src/web/components/git/branch-picker.tsx +419 -0
  408. package/src/web/components/git/branch-select.tsx +34 -0
  409. package/src/web/components/git/create-worktree-dialog.tsx +17 -16
  410. package/src/web/components/git/git-repo-picker.tsx +28 -40
  411. package/src/web/components/layout/status-bar.tsx +42 -19
  412. package/src/web/components/settings/accounts/account-card.tsx +5 -1
  413. package/src/web/components/settings/ai-settings-section.tsx +67 -3
  414. package/src/web/components/settings/appearance-settings-section.tsx +2 -28
  415. package/src/web/components/settings/language-servers-section.tsx +362 -0
  416. package/src/web/components/settings/settings-categories.ts +8 -3
  417. package/src/web/components/settings/settings-section-content.tsx +2 -0
  418. package/src/web/components/settings/voice-settings-section.tsx +283 -0
  419. package/src/web/components/system/apps/app-row.tsx +110 -0
  420. package/src/web/components/system/apps/app-rows.ts +140 -0
  421. package/src/web/components/system/apps/apps-panel.tsx +129 -0
  422. package/src/web/components/system/metric-chart-canvas.tsx +79 -3
  423. package/src/web/components/system/overview-cards/card-shell.tsx +54 -0
  424. package/src/web/components/system/overview-cards/cpu-card.tsx +11 -6
  425. package/src/web/components/system/overview-cards/disk-card.tsx +11 -6
  426. package/src/web/components/system/overview-cards/gpu-card.tsx +16 -6
  427. package/src/web/components/system/overview-cards/mem-card.tsx +11 -6
  428. package/src/web/components/system/overview-cards/net-card.tsx +11 -6
  429. package/src/web/components/system/overview-device-target.ts +69 -0
  430. package/src/web/components/system/overview-panel.tsx +15 -1
  431. package/src/web/components/system/performance/cpu-core-grid.tsx +74 -0
  432. package/src/web/components/system/performance/cpu-detail.tsx +220 -0
  433. package/src/web/components/system/performance/detail-parts.tsx +149 -0
  434. package/src/web/components/system/performance/device-list.ts +139 -0
  435. package/src/web/components/system/performance/disk-detail.tsx +64 -0
  436. package/src/web/components/system/performance/fans-detail.tsx +35 -0
  437. package/src/web/components/system/performance/gpu-detail.tsx +116 -0
  438. package/src/web/components/system/performance/memory-detail.tsx +109 -0
  439. package/src/web/components/system/performance/nic-detail.tsx +55 -0
  440. package/src/web/components/system/performance/partition-list.tsx +79 -0
  441. package/src/web/components/system/performance/performance-panel.tsx +206 -0
  442. package/src/web/components/system/performance/use-hardware-inventory.ts +48 -0
  443. package/src/web/components/system/process-columns-grid.ts +5 -3
  444. package/src/web/components/system/process-details-dialog.tsx +116 -0
  445. package/src/web/components/system/process-group-row.tsx +6 -1
  446. package/src/web/components/system/process-row-format.ts +6 -0
  447. package/src/web/components/system/process-row-menu.tsx +72 -0
  448. package/src/web/components/system/process-row.tsx +7 -1
  449. package/src/web/components/system/process-table-model.ts +1 -1
  450. package/src/web/components/system/process-table-sort.ts +8 -4
  451. package/src/web/components/system/process-table-toolbar.tsx +10 -2
  452. package/src/web/components/system/process-table-totals.ts +3 -0
  453. package/src/web/components/system/process-table.tsx +25 -2
  454. package/src/web/components/system/services/service-action-confirm.tsx +100 -0
  455. package/src/web/components/system/services/service-columns.ts +103 -0
  456. package/src/web/components/system/services/service-details-sheet.tsx +97 -0
  457. package/src/web/components/system/services/service-resources.ts +105 -0
  458. package/src/web/components/system/services/service-row.tsx +146 -0
  459. package/src/web/components/system/services/service-rows.ts +92 -0
  460. package/src/web/components/system/services/service-sort.ts +90 -0
  461. package/src/web/components/system/services/services-header.tsx +51 -0
  462. package/src/web/components/system/services/services-panel.tsx +207 -0
  463. package/src/web/components/system/services/use-services.ts +92 -0
  464. package/src/web/components/system/sortable-header.tsx +13 -8
  465. package/src/web/components/system/sysmon-preferences.tsx +85 -0
  466. package/src/web/components/system/system-monitor-body.tsx +101 -43
  467. package/src/web/components/system/system-monitor-window-content.tsx +2 -3
  468. package/src/web/components/system/use-process-signal.ts +87 -0
  469. package/src/web/components/tunnels/public-tunnel-switch.tsx +82 -0
  470. package/src/web/components/tunnels/tunnel-manager-tab.tsx +4 -0
  471. package/src/web/components/ui/dialog.tsx +14 -1
  472. package/src/web/components/ui/search-select.tsx +279 -0
  473. package/src/web/components/ui/start-ellipsis.tsx +18 -0
  474. package/src/web/hooks/use-chat.ts +28 -0
  475. package/src/web/hooks/use-global-keybindings.ts +7 -5
  476. package/src/web/hooks/use-lsp.ts +23 -2
  477. package/src/web/hooks/use-minute-clock.ts +20 -0
  478. package/src/web/hooks/use-whisper-voice-input.ts +113 -0
  479. package/src/web/lib/api-tunnels.ts +19 -0
  480. package/src/web/lib/branch-select-items.ts +29 -0
  481. package/src/web/lib/cpu-graph-mode.ts +90 -0
  482. package/src/web/lib/format-bytes.ts +14 -0
  483. package/src/web/lib/git-ref-picker.ts +120 -0
  484. package/src/web/lib/lsp/lsp-client.ts +32 -0
  485. package/src/web/lib/search-select-rows.ts +55 -0
  486. package/src/web/lib/temperature.ts +27 -0
  487. package/src/web/lib/voice-wav.ts +69 -0
  488. package/src/web/stores/git-status-store.ts +31 -17
  489. package/src/web/stores/keybindings-store.ts +14 -1
  490. package/src/web/stores/settings-store.ts +65 -0
  491. package/src/web/styles/globals.css +11 -0
  492. package/dist/web/assets/accounts-settings-section-DUVO32SQ.js +0 -1
  493. package/dist/web/assets/accounts-settings-section-DUVO32SQ.js.br +0 -0
  494. package/dist/web/assets/accounts-settings-section-DUVO32SQ.js.gz +0 -0
  495. package/dist/web/assets/ai-resource-editor-Dn_wB-o5.js.br +0 -0
  496. package/dist/web/assets/ai-resource-editor-Dn_wB-o5.js.gz +0 -0
  497. package/dist/web/assets/ai-settings-section-CEbW8jRy.js +0 -1
  498. package/dist/web/assets/ai-settings-section-CEbW8jRy.js.br +0 -0
  499. package/dist/web/assets/ai-settings-section-CEbW8jRy.js.gz +0 -0
  500. package/dist/web/assets/ai-settings-section-D-mwEYFZ.js +0 -1
  501. package/dist/web/assets/api-client-BgedDTvo.js +0 -1
  502. package/dist/web/assets/api-client-c8YOpTlT.js.br +0 -0
  503. package/dist/web/assets/api-client-c8YOpTlT.js.gz +0 -0
  504. package/dist/web/assets/api-settings-BmvNoCbn.js.br +0 -0
  505. package/dist/web/assets/api-settings-BmvNoCbn.js.gz +0 -0
  506. package/dist/web/assets/api-settings-Bti1-Zn3.js +0 -1
  507. package/dist/web/assets/appearance-settings-section-tw6TpFb6.js +0 -1
  508. package/dist/web/assets/appearance-settings-section-tw6TpFb6.js.br +0 -0
  509. package/dist/web/assets/appearance-settings-section-tw6TpFb6.js.gz +0 -0
  510. package/dist/web/assets/audio-preview-vaG2cB-k.js.br +0 -0
  511. package/dist/web/assets/audio-preview-vaG2cB-k.js.gz +0 -0
  512. package/dist/web/assets/branch-review-tab-MBuMWp_i.js +0 -1
  513. package/dist/web/assets/branch-review-tab-MBuMWp_i.js.br +0 -0
  514. package/dist/web/assets/branch-review-tab-MBuMWp_i.js.gz +0 -0
  515. package/dist/web/assets/button-Ci9EUgqd.js.br +0 -0
  516. package/dist/web/assets/button-Ci9EUgqd.js.gz +0 -0
  517. package/dist/web/assets/chat-preparation-cache-BSIQGiWx.js.br +0 -0
  518. package/dist/web/assets/chat-preparation-cache-BSIQGiWx.js.gz +0 -0
  519. package/dist/web/assets/chat-tab-DVvnqhw6.js +0 -1
  520. package/dist/web/assets/chat-tab-DVvnqhw6.js.br +0 -0
  521. package/dist/web/assets/chat-tab-DVvnqhw6.js.gz +0 -0
  522. package/dist/web/assets/chat-tab-DaEHva22.js +0 -15
  523. package/dist/web/assets/chat-tab-DaEHva22.js.br +0 -0
  524. package/dist/web/assets/chat-tab-DaEHva22.js.gz +0 -0
  525. package/dist/web/assets/code-editor-Bu9lhTVp.js +0 -7
  526. package/dist/web/assets/code-editor-Bu9lhTVp.js.br +0 -0
  527. package/dist/web/assets/code-editor-Bu9lhTVp.js.gz +0 -0
  528. package/dist/web/assets/codex-reset-credit-button-CbmE5mRX.js +0 -1
  529. package/dist/web/assets/codex-reset-credit-button-CbmE5mRX.js.br +0 -0
  530. package/dist/web/assets/codex-reset-credit-button-CbmE5mRX.js.gz +0 -0
  531. package/dist/web/assets/conflict-editor-BA3y-qSH.js.br +0 -0
  532. package/dist/web/assets/conflict-editor-BA3y-qSH.js.gz +0 -0
  533. package/dist/web/assets/context-menu-CjYTq8DI.js +0 -1
  534. package/dist/web/assets/context-menu-CjYTq8DI.js.br +0 -0
  535. package/dist/web/assets/context-menu-CjYTq8DI.js.gz +0 -0
  536. package/dist/web/assets/csv-preview-BioxkrQF.js.br +0 -0
  537. package/dist/web/assets/csv-preview-BioxkrQF.js.gz +0 -0
  538. package/dist/web/assets/data-grid-overlay-editor-CQRVKr7y.js.br +0 -0
  539. package/dist/web/assets/data-grid-overlay-editor-CQRVKr7y.js.gz +0 -0
  540. package/dist/web/assets/database-viewer-BSoJ0E6p.js.br +0 -0
  541. package/dist/web/assets/database-viewer-BSoJ0E6p.js.gz +0 -0
  542. package/dist/web/assets/design-export-client-ChMcMoqW.js.br +0 -0
  543. package/dist/web/assets/design-export-client-ChMcMoqW.js.gz +0 -0
  544. package/dist/web/assets/design-responsive-dialog-DNBhJJLf.js.br +0 -0
  545. package/dist/web/assets/design-responsive-dialog-DNBhJJLf.js.gz +0 -0
  546. package/dist/web/assets/design-tab-iU2CviE3.js +0 -33
  547. package/dist/web/assets/design-tab-iU2CviE3.js.br +0 -0
  548. package/dist/web/assets/design-tab-iU2CviE3.js.gz +0 -0
  549. package/dist/web/assets/designs-sidebar-panel-DHh5QsH9.js.br +0 -0
  550. package/dist/web/assets/designs-sidebar-panel-DHh5QsH9.js.gz +0 -0
  551. package/dist/web/assets/dialog-B8clVkyi.js +0 -1
  552. package/dist/web/assets/dialog-B8clVkyi.js.br +0 -0
  553. package/dist/web/assets/dialog-B8clVkyi.js.gz +0 -0
  554. package/dist/web/assets/diff-viewer-lctWoSmG.js.br +0 -0
  555. package/dist/web/assets/diff-viewer-lctWoSmG.js.gz +0 -0
  556. package/dist/web/assets/docx-preview-C9XdKEj1.js.br +0 -0
  557. package/dist/web/assets/docx-preview-C9XdKEj1.js.gz +0 -0
  558. package/dist/web/assets/editor-language-service-fPG56hQO.js +0 -1
  559. package/dist/web/assets/editor-language-service-fPG56hQO.js.br +0 -0
  560. package/dist/web/assets/editor-language-service-fPG56hQO.js.gz +0 -0
  561. package/dist/web/assets/explorer-body-BgF7FsxI.js +0 -2
  562. package/dist/web/assets/explorer-body-BgF7FsxI.js.br +0 -0
  563. package/dist/web/assets/explorer-body-BgF7FsxI.js.gz +0 -0
  564. package/dist/web/assets/explorer-window-content-C21w_7lf.js +0 -1
  565. package/dist/web/assets/explorer-window-content-C21w_7lf.js.br +0 -0
  566. package/dist/web/assets/explorer-window-content-C21w_7lf.js.gz +0 -0
  567. package/dist/web/assets/extension-manager-section-rbkXsZVR.js.br +0 -0
  568. package/dist/web/assets/extension-manager-section-rbkXsZVR.js.gz +0 -0
  569. package/dist/web/assets/extension-webview-uPO0WgCq.js.br +0 -0
  570. package/dist/web/assets/extension-webview-uPO0WgCq.js.gz +0 -0
  571. package/dist/web/assets/file-icons-gx_FBOXY.js.br +0 -0
  572. package/dist/web/assets/file-icons-gx_FBOXY.js.gz +0 -0
  573. package/dist/web/assets/file-store-D9KE0kQC.js.br +0 -0
  574. package/dist/web/assets/file-store-D9KE0kQC.js.gz +0 -0
  575. package/dist/web/assets/files-settings-section-CT7mDb0L.js.br +0 -0
  576. package/dist/web/assets/files-settings-section-CT7mDb0L.js.gz +0 -0
  577. package/dist/web/assets/format-bytes-DmSHAKFe.js +0 -1
  578. package/dist/web/assets/format-file-meta-mQwA6SuY.js.br +0 -0
  579. package/dist/web/assets/format-file-meta-mQwA6SuY.js.gz +0 -0
  580. package/dist/web/assets/fs-api-DL36slbd.js.br +0 -0
  581. package/dist/web/assets/fs-api-DL36slbd.js.gz +0 -0
  582. package/dist/web/assets/general-settings-section-DANPfMRN.js.br +0 -0
  583. package/dist/web/assets/general-settings-section-DANPfMRN.js.gz +0 -0
  584. package/dist/web/assets/git-log-panel-BJPkLiEw.js.br +0 -0
  585. package/dist/web/assets/git-log-panel-BJPkLiEw.js.gz +0 -0
  586. package/dist/web/assets/git-repo-store-DSypNj19.js.br +0 -0
  587. package/dist/web/assets/git-repo-store-DSypNj19.js.gz +0 -0
  588. package/dist/web/assets/glide-data-grid-R4PcAntf.js.br +0 -0
  589. package/dist/web/assets/glide-data-grid-R4PcAntf.js.gz +0 -0
  590. package/dist/web/assets/group-chat-tab-BXMdo8w9.js +0 -1
  591. package/dist/web/assets/group-chat-tab-BXMdo8w9.js.br +0 -0
  592. package/dist/web/assets/group-chat-tab-BXMdo8w9.js.gz +0 -0
  593. package/dist/web/assets/index-C8nGqkKN.js +0 -52
  594. package/dist/web/assets/index-C8nGqkKN.js.br +0 -0
  595. package/dist/web/assets/index-C8nGqkKN.js.gz +0 -0
  596. package/dist/web/assets/index-DvClbTQx.css +0 -1
  597. package/dist/web/assets/index-DvClbTQx.css.br +0 -0
  598. package/dist/web/assets/index-DvClbTQx.css.gz +0 -0
  599. package/dist/web/assets/keybindings-store-BGKlQQAv.js +0 -1
  600. package/dist/web/assets/keyboard-shortcuts-section-BKej4mUf.js.br +0 -0
  601. package/dist/web/assets/keyboard-shortcuts-section-BKej4mUf.js.gz +0 -0
  602. package/dist/web/assets/markdown-renderer-BHtYqkYZ.js.br +0 -0
  603. package/dist/web/assets/markdown-renderer-BHtYqkYZ.js.gz +0 -0
  604. package/dist/web/assets/markdown-renderer-vDNuKjel.js +0 -1
  605. package/dist/web/assets/mobile-bottom-sheet-CuNi2FRv.js.br +0 -0
  606. package/dist/web/assets/mobile-bottom-sheet-CuNi2FRv.js.gz +0 -0
  607. package/dist/web/assets/mobile-explorer-sheet-DtvxS7-r.js +0 -1
  608. package/dist/web/assets/mobile-explorer-sheet-DtvxS7-r.js.br +0 -0
  609. package/dist/web/assets/mobile-explorer-sheet-DtvxS7-r.js.gz +0 -0
  610. package/dist/web/assets/new-design-dialog-DS_XrpTG.js.br +0 -0
  611. package/dist/web/assets/new-design-dialog-DS_XrpTG.js.gz +0 -0
  612. package/dist/web/assets/notification-store-Dnnj20Ky.js +0 -1
  613. package/dist/web/assets/notifications-settings-section-C05WYqcE.js.br +0 -0
  614. package/dist/web/assets/notifications-settings-section-C05WYqcE.js.gz +0 -0
  615. package/dist/web/assets/onboarding-entry-CmUqv1kl.js.br +0 -0
  616. package/dist/web/assets/onboarding-entry-CmUqv1kl.js.gz +0 -0
  617. package/dist/web/assets/onboarding-quick-orientation-DIhWv1CN.js.br +0 -0
  618. package/dist/web/assets/onboarding-quick-orientation-DIhWv1CN.js.gz +0 -0
  619. package/dist/web/assets/overview-panel-BZAW_nag.js +0 -1
  620. package/dist/web/assets/overview-panel-BZAW_nag.js.br +0 -0
  621. package/dist/web/assets/overview-panel-BZAW_nag.js.gz +0 -0
  622. package/dist/web/assets/pdf-preview-qdXmMkOR.js.br +0 -0
  623. package/dist/web/assets/pdf-preview-qdXmMkOR.js.gz +0 -0
  624. package/dist/web/assets/postgres-viewer-Xvlun_n5.js.br +0 -0
  625. package/dist/web/assets/postgres-viewer-Xvlun_n5.js.gz +0 -0
  626. package/dist/web/assets/ppmbot-settings-section-D8AES1BA.js.br +0 -0
  627. package/dist/web/assets/ppmbot-settings-section-D8AES1BA.js.gz +0 -0
  628. package/dist/web/assets/pptx-export-CG6MRNok.js.br +0 -0
  629. package/dist/web/assets/pptx-export-CG6MRNok.js.gz +0 -0
  630. package/dist/web/assets/problems-panel-DTBG4beI.js.br +0 -0
  631. package/dist/web/assets/problems-panel-DTBG4beI.js.gz +0 -0
  632. package/dist/web/assets/process-table-D_gR2XA6.js +0 -1
  633. package/dist/web/assets/process-table-D_gR2XA6.js.br +0 -0
  634. package/dist/web/assets/process-table-D_gR2XA6.js.gz +0 -0
  635. package/dist/web/assets/project-store-C5gJXkvb.js.br +0 -0
  636. package/dist/web/assets/project-store-C5gJXkvb.js.gz +0 -0
  637. package/dist/web/assets/proxy-settings-section-CqtmbeRj.js.br +0 -0
  638. package/dist/web/assets/proxy-settings-section-CqtmbeRj.js.gz +0 -0
  639. package/dist/web/assets/query-audit-section-UKG_smyt.js.br +0 -0
  640. package/dist/web/assets/query-audit-section-UKG_smyt.js.gz +0 -0
  641. package/dist/web/assets/remote-desktop-clipboard-notice-Djt6cpNL.js.br +0 -0
  642. package/dist/web/assets/remote-desktop-clipboard-notice-Djt6cpNL.js.gz +0 -0
  643. package/dist/web/assets/remote-desktop-mobile-sheet-BQxhJUkm.js +0 -2
  644. package/dist/web/assets/remote-desktop-mobile-sheet-BQxhJUkm.js.br +0 -0
  645. package/dist/web/assets/remote-desktop-mobile-sheet-BQxhJUkm.js.gz +0 -0
  646. package/dist/web/assets/remote-desktop-mobile-view-DGnT8RY7.js +0 -1
  647. package/dist/web/assets/remote-desktop-mobile-view-DGnT8RY7.js.br +0 -0
  648. package/dist/web/assets/remote-desktop-mobile-view-DGnT8RY7.js.gz +0 -0
  649. package/dist/web/assets/remote-desktop-readiness-gate-DNJF8TcF.js.br +0 -0
  650. package/dist/web/assets/remote-desktop-readiness-gate-DNJF8TcF.js.gz +0 -0
  651. package/dist/web/assets/remote-desktop-window-content-Ds0DKmM0.js +0 -1
  652. package/dist/web/assets/remote-desktop-window-content-Ds0DKmM0.js.br +0 -0
  653. package/dist/web/assets/remote-desktop-window-content-Ds0DKmM0.js.gz +0 -0
  654. package/dist/web/assets/schedules-settings-section-BKoPovy2.js.br +0 -0
  655. package/dist/web/assets/schedules-settings-section-BKoPovy2.js.gz +0 -0
  656. package/dist/web/assets/scroll-area-XonvWYn_.js.br +0 -0
  657. package/dist/web/assets/scroll-area-XonvWYn_.js.gz +0 -0
  658. package/dist/web/assets/settings-body-k2qPgRFe.js +0 -2
  659. package/dist/web/assets/settings-body-k2qPgRFe.js.br +0 -0
  660. package/dist/web/assets/settings-body-k2qPgRFe.js.gz +0 -0
  661. package/dist/web/assets/settings-store-Br5c1efC.js +0 -2
  662. package/dist/web/assets/settings-store-Br5c1efC.js.br +0 -0
  663. package/dist/web/assets/settings-store-Br5c1efC.js.gz +0 -0
  664. package/dist/web/assets/settings-tab-Bb23VdBu.js +0 -1
  665. package/dist/web/assets/settings-window-content-ClarWusz.js +0 -1
  666. package/dist/web/assets/sql-query-editor-BjIMi9Wk.js.br +0 -0
  667. package/dist/web/assets/sql-query-editor-BjIMi9Wk.js.gz +0 -0
  668. package/dist/web/assets/sqlite-viewer-BNcA6Irq.js.br +0 -0
  669. package/dist/web/assets/sqlite-viewer-BNcA6Irq.js.gz +0 -0
  670. package/dist/web/assets/system-monitor-body-D0T3ggt2.js +0 -2
  671. package/dist/web/assets/system-monitor-body-D0T3ggt2.js.br +0 -0
  672. package/dist/web/assets/system-monitor-body-D0T3ggt2.js.gz +0 -0
  673. package/dist/web/assets/system-monitor-tab-I1Igmoey.js +0 -1
  674. package/dist/web/assets/system-monitor-window-content-C5SeUv1H.js +0 -1
  675. package/dist/web/assets/tab-host-window-content-CIRGNCvi.js.br +0 -0
  676. package/dist/web/assets/tab-host-window-content-CIRGNCvi.js.gz +0 -0
  677. package/dist/web/assets/team-member-sheet-CwXpLi3X.js.br +0 -0
  678. package/dist/web/assets/team-member-sheet-CwXpLi3X.js.gz +0 -0
  679. package/dist/web/assets/team-member-window-content-4swiiDz7.js.br +0 -0
  680. package/dist/web/assets/team-member-window-content-4swiiDz7.js.gz +0 -0
  681. package/dist/web/assets/terminal-tab-BGcdtMMT.js.br +0 -0
  682. package/dist/web/assets/terminal-tab-BGcdtMMT.js.gz +0 -0
  683. package/dist/web/assets/tool-cards-D0-krtA2.js.br +0 -0
  684. package/dist/web/assets/tool-cards-D0-krtA2.js.gz +0 -0
  685. package/dist/web/assets/use-inline-blame-pKaXyGU-.js +0 -16
  686. package/dist/web/assets/use-inline-blame-pKaXyGU-.js.br +0 -0
  687. package/dist/web/assets/use-inline-blame-pKaXyGU-.js.gz +0 -0
  688. package/dist/web/assets/use-lsp-71azTXQz.js +0 -6
  689. package/dist/web/assets/use-lsp-71azTXQz.js.br +0 -0
  690. package/dist/web/assets/use-lsp-71azTXQz.js.gz +0 -0
  691. package/dist/web/assets/vendor-ui-BHh12_0v.js.br +0 -0
  692. package/dist/web/assets/vendor-ui-BHh12_0v.js.gz +0 -0
  693. package/dist/web/assets/video-preview-DxEX-uGo.js +0 -1
  694. package/dist/web/assets/video-preview-DxEX-uGo.js.br +0 -0
  695. package/dist/web/assets/video-preview-DxEX-uGo.js.gz +0 -0
  696. package/dist/web/assets/ws-auth-kXgsX2Js.js +0 -1
  697. /package/dist/web/assets/{__vite-browser-external-BpSQWxcq.js → __vite-browser-external-BILfYaAs.js} +0 -0
  698. /package/dist/web/assets/{run-in-terminal-HIdNgYim.js → run-in-terminal-2pSiup8e.js} +0 -0
  699. /package/dist/web/assets/{vendor-xterm-DLDtzLib.js → vendor-xterm-DF1JTfsy.js} +0 -0
  700. /package/dist/web/assets/{vendor-xterm-DLDtzLib.js.br → vendor-xterm-DF1JTfsy.js.br} +0 -0
  701. /package/dist/web/assets/{vendor-xterm-DLDtzLib.js.gz → vendor-xterm-DF1JTfsy.js.gz} +0 -0
@@ -0,0 +1,127 @@
1
+ /**
2
+ * What each compaction in a transcript cost and saved.
3
+ *
4
+ * Compaction is the largest single thing that happens to a chat and the only one the
5
+ * transcript records without the UI ever saying so: a session silently loses most of
6
+ * its history, the next turn's prefix collapses, and the only visible trace is a long
7
+ * summary message. This reads the figures back out so the divider above that summary
8
+ * can state them.
9
+ *
10
+ * The link between a boundary and the message it introduces is `parentUuid`. Claude
11
+ * Code writes the `compact_boundary` record with `parentUuid: null` — it is the root
12
+ * of the post-compaction segment — and the summary immediately after it carries the
13
+ * boundary's uuid as its parent. Keying the result by that summary's uuid is what
14
+ * lets both message readers stamp it on without either of them knowing the layout,
15
+ * since `parseSessionMessage` already uses the record uuid as `ChatMessage.id`.
16
+ */
17
+
18
+ import { existsSync } from "node:fs";
19
+ import type { CompactionInfo } from "../types/chat.ts";
20
+ import { readLines } from "./read-lines.ts";
21
+
22
+ /**
23
+ * Cheap test for the only two lines per compaction worth parsing.
24
+ *
25
+ * A transcript reaches tens of megabytes and `JSON.parse` on every line of one is the
26
+ * dominant cost of reading it at all — but a compaction leaves two records in a file
27
+ * that holds thousands, so a substring check keeps this a scan rather than a parse.
28
+ */
29
+ const BOUNDARY_MARKER = '"compact_boundary"';
30
+
31
+ /**
32
+ * Map of compact-summary message uuid → that compaction's figures.
33
+ *
34
+ * Answers an empty map for a missing or unreadable file: a transcript that cannot be
35
+ * read still has messages worth showing, and a divider is not worth failing a history
36
+ * load over.
37
+ */
38
+ export async function readCompactions(jsonlPath: string): Promise<Map<string, CompactionInfo>> {
39
+ const byMessageId = new Map<string, CompactionInfo>();
40
+ if (!existsSync(jsonlPath)) return byMessageId;
41
+
42
+ // The boundary is read one line before the summary that claims it, so it waits here
43
+ // until a record names it as parent. Held rather than assumed adjacent: the pairing
44
+ // is by uuid, so a record written between the two cannot mis-attach the figures.
45
+ let pending: { uuid: string; info: CompactionInfo } | null = null;
46
+
47
+ try {
48
+ for await (const line of readLines(jsonlPath)) {
49
+ if (line.includes(BOUNDARY_MARKER)) {
50
+ const info = parseBoundary(line);
51
+ pending = info ? { uuid: info.uuid, info: info.compaction } : null;
52
+ continue;
53
+ }
54
+ if (!pending) continue;
55
+ // Only lines that could be the child are parsed — the uuid of the boundary is a
56
+ // full uuid, so this substring test has no realistic false positive.
57
+ if (!line.includes(pending.uuid)) continue;
58
+ const child = parseChild(line);
59
+ if (child?.parentUuid === pending.uuid) {
60
+ byMessageId.set(child.uuid, pending.info);
61
+ pending = null;
62
+ }
63
+ }
64
+ } catch {
65
+ // Truncated or mid-write — keep whatever pairs were already complete.
66
+ }
67
+ return byMessageId;
68
+ }
69
+
70
+ /** The boundary's own uuid and figures, or null when the record is not one we can use. */
71
+ function parseBoundary(line: string): { uuid: string; compaction: CompactionInfo } | null {
72
+ let entry: any;
73
+ try {
74
+ entry = JSON.parse(line);
75
+ } catch {
76
+ return null;
77
+ }
78
+ if (entry?.type !== "system" || entry.subtype !== "compact_boundary") return null;
79
+ const meta = entry.compactMetadata;
80
+ if (typeof entry.uuid !== "string" || !meta) return null;
81
+
82
+ const preTokens = numberOr(meta.preTokens, 0);
83
+ const postTokens = numberOr(meta.postTokens, 0);
84
+ // A boundary with no `preTokens` is a record shape this cannot describe — a zero
85
+ // saving would render as a confident "saved 0", which is worse than no divider.
86
+ if (preTokens <= 0) return null;
87
+
88
+ return {
89
+ uuid: entry.uuid,
90
+ compaction: {
91
+ trigger: meta.trigger === "manual" ? "manual" : "auto",
92
+ preTokens,
93
+ postTokens,
94
+ // Clamped: `postTokens` is absent on older records, and a summary that somehow
95
+ // measured larger than its input must not report a negative saving.
96
+ savedTokens: Math.max(0, preTokens - postTokens),
97
+ ...(typeof meta.durationMs === "number" ? { durationMs: meta.durationMs } : {}),
98
+ },
99
+ };
100
+ }
101
+
102
+ /** The uuid/parentUuid pair of a candidate child record. */
103
+ function parseChild(line: string): { uuid: string; parentUuid: string } | null {
104
+ try {
105
+ const entry = JSON.parse(line);
106
+ if (typeof entry?.uuid !== "string" || typeof entry.parentUuid !== "string") return null;
107
+ return { uuid: entry.uuid, parentUuid: entry.parentUuid };
108
+ } catch {
109
+ return null;
110
+ }
111
+ }
112
+
113
+ function numberOr(value: unknown, fallback: number): number {
114
+ return typeof value === "number" && Number.isFinite(value) ? value : fallback;
115
+ }
116
+
117
+ /** Stamp each compaction onto the message that opens its segment. */
118
+ export function applyCompactions(
119
+ messages: { id: string; compaction?: CompactionInfo }[],
120
+ byMessageId: Map<string, CompactionInfo>,
121
+ ): void {
122
+ if (byMessageId.size === 0) return;
123
+ for (const msg of messages) {
124
+ const info = byMessageId.get(msg.id);
125
+ if (info) msg.compaction = info;
126
+ }
127
+ }
@@ -8,7 +8,7 @@ import { backupDbSync } from "./db-backup/db-backup-sync.ts";
8
8
  import { CODEX_DEFAULT_MODEL } from "../types/config.ts";
9
9
  // Must equal the last `PRAGMA user_version` below: the pre-migration snapshot is skipped for
10
10
  // any database already at this version, so a stale value silently drops that backup.
11
- export const CURRENT_SCHEMA_VERSION = 51;
11
+ export const CURRENT_SCHEMA_VERSION = 54;
12
12
 
13
13
  let db: Database | null = null;
14
14
  let dbProfile: string | null = null;
@@ -36,8 +36,7 @@ export function getDb(): Database {
36
36
  const ppmDir = getPpmDir();
37
37
  if (!existsSync(ppmDir)) mkdirSync(ppmDir, { recursive: true });
38
38
  db = new Database(getDbPath());
39
- db.exec("PRAGMA journal_mode = WAL");
40
- db.exec("PRAGMA foreign_keys = ON");
39
+ applyDbPragmas(db);
41
40
  backupBeforeMigrations(db);
42
41
  runMigrations(db);
43
42
  return db;
@@ -68,6 +67,26 @@ function backupBeforeMigrations(database: Database): void {
68
67
  }
69
68
  }
70
69
 
70
+ /**
71
+ * The pragmas every PPM connection to this database needs.
72
+ *
73
+ * `busy_timeout` is the one with a story. SQLite's default is to fail a
74
+ * contended lock INSTANTLY — measured, 0ms to `SQLiteError: database is
75
+ * locked` — and PPM routinely has two processes on this file for a moment: a
76
+ * `systemctl restart` starts the new supervisor while the outgoing server is
77
+ * still committing and checkpointing, which for a 300MB database is over a
78
+ * second. That single throw arrived as an unhandled rejection inside
79
+ * supervisor startup, which then stopped before spawning the edge forwarder —
80
+ * so PPM ran with nothing listening on its public port. 5s rather than the
81
+ * query audit's 2s: one snapshot of this database measures ~1.2s, so the wait
82
+ * has to cover a checkpoint plus whatever writes queued behind it.
83
+ */
84
+ export function applyDbPragmas(database: Database): void {
85
+ database.exec("PRAGMA journal_mode = WAL");
86
+ database.exec("PRAGMA busy_timeout = 5000");
87
+ database.exec("PRAGMA foreign_keys = ON");
88
+ }
89
+
71
90
  /** Close the DB (for graceful shutdown or tests) */
72
91
  export function closeDb(): void {
73
92
  if (db) { db.close(); db = null; }
@@ -76,8 +95,7 @@ export function closeDb(): void {
76
95
  /** For tests: open an isolated in-memory DB with schema applied */
77
96
  export function openTestDb(): Database {
78
97
  const testDb = new Database(":memory:");
79
- testDb.exec("PRAGMA journal_mode = WAL");
80
- testDb.exec("PRAGMA foreign_keys = ON");
98
+ applyDbPragmas(testDb);
81
99
  runMigrations(testDb);
82
100
  return testDb;
83
101
  }
@@ -1131,10 +1149,33 @@ export function runMigrations(database: Database): void {
1131
1149
  database.exec(`PRAGMA user_version = 48;`);
1132
1150
  }
1133
1151
 
1152
+ // This checkout's prompt-cache work first shipped as migrations 46-48 on turn_usage, before
1153
+ // main used those numbers for accounts (it is 50-52 below now). A database that ran the local
1154
+ // ones sits past 45 without main's columns, so the version gates above skip them for good and
1155
+ // 49 then updates a column that does not exist. Added by schema rather than by version here;
1156
+ // on a database that followed main every statement is a no-op.
1157
+ if (current >= 46 && current < 49) {
1158
+ for (const col of [
1159
+ "granted_at INTEGER",
1160
+ "refresh_expires_at INTEGER",
1161
+ "reauth_required INTEGER NOT NULL DEFAULT 0",
1162
+ "last_refresh_attempt_at INTEGER",
1163
+ ]) {
1164
+ try { database.exec(`ALTER TABLE accounts ADD COLUMN ${col}`); } catch { /* exists */ }
1165
+ }
1166
+ try { database.exec(`ALTER TABLE codex_accounts ADD COLUMN status TEXT NOT NULL DEFAULT 'active'`); } catch { /* exists */ }
1167
+ try { database.exec(`ALTER TABLE codex_accounts ADD COLUMN daily_guard_enabled INTEGER NOT NULL DEFAULT 0`); } catch { /* exists */ }
1168
+ }
1169
+
1134
1170
  if (current < 49) {
1135
1171
  // Daily guard was introduced as an opt-in during development. Ship it enabled so every
1136
1172
  // weekly-only account starts paced; Plus accounts simply do not surface or use it.
1137
- database.exec(`UPDATE codex_accounts SET daily_guard_enabled = 1`);
1173
+ //
1174
+ // Guarded like every statement around it, and for the same reason: the ladder runs against
1175
+ // databases that do not have this table yet. Unguarded, the throw escapes `runMigrations`
1176
+ // and leaves the database half-migrated at whatever version the previous step wrote —
1177
+ // there is no transaction around the ladder to undo it.
1178
+ try { database.exec(`UPDATE codex_accounts SET daily_guard_enabled = 1`); } catch { /* no accounts table yet */ }
1138
1179
  database.exec(`PRAGMA user_version = 49;`);
1139
1180
  }
1140
1181
 
@@ -1155,6 +1196,33 @@ export function runMigrations(database: Database): void {
1155
1196
  try { database.exec("ALTER TABLE claude_limit_snapshots ADD COLUMN extra_json TEXT"); } catch { /* exists */ }
1156
1197
  database.exec(`PRAGMA user_version = 51;`);
1157
1198
  }
1199
+
1200
+ if (current < 52) {
1201
+ // The idle-cache notice had to live entirely in server memory, because nothing on disk
1202
+ // said when a session last cached or how much. `recorded_at` answers the first; this
1203
+ // column answers the second with a figure the summed token columns cannot give —
1204
+ // see `TurnUsage.contextTokens`. Null on every existing row: unmeasured, not zero.
1205
+ try { database.exec("ALTER TABLE turn_usage ADD COLUMN context_tokens INTEGER"); } catch { /* column exists */ }
1206
+ database.exec(`PRAGMA user_version = 52;`);
1207
+ }
1208
+
1209
+ if (current < 53) {
1210
+ // The cache window was inferred from the credential's shape — an `sk-ant-oat` prefix
1211
+ // meaning a subscription and therefore an hour. The API states it outright in
1212
+ // `usage.cache_creation`, and that answer has to outlive the process the way the rest of
1213
+ // the last turn's facts now do. Null on existing rows: unreported, so the guess stands.
1214
+ try { database.exec("ALTER TABLE turn_usage ADD COLUMN cache_ttl_ms INTEGER"); } catch { /* column exists */ }
1215
+ database.exec(`PRAGMA user_version = 53;`);
1216
+ }
1217
+
1218
+ if (current < 54) {
1219
+ // A compaction makes the cached prefix inapplicable rather than stale, and the window in
1220
+ // which that matters is between the compaction and the user's next message — a window a
1221
+ // restart lands inside often enough to be worth surviving. Null on existing rows: no
1222
+ // compaction is known, which is what every turn before this recorded anyway.
1223
+ try { database.exec("ALTER TABLE turn_usage ADD COLUMN compacted_at INTEGER"); } catch { /* column exists */ }
1224
+ database.exec(`PRAGMA user_version = 54;`);
1225
+ }
1158
1226
  }
1159
1227
 
1160
1228
  // ---------------------------------------------------------------------------
@@ -1729,6 +1797,9 @@ export interface TurnUsageRow {
1729
1797
  cold_reason: string | null;
1730
1798
  account_id: string | null;
1731
1799
  account_label: string | null;
1800
+ context_tokens: number | null;
1801
+ cache_ttl_ms: number | null;
1802
+ compacted_at: number | null;
1732
1803
  recorded_at: string;
1733
1804
  }
1734
1805
 
@@ -1745,13 +1816,16 @@ export function insertTurnUsage(record: {
1745
1816
  coldReason?: string;
1746
1817
  accountId?: string;
1747
1818
  accountLabel?: string;
1819
+ contextTokens?: number;
1820
+ cacheTtlMs?: number;
1821
+ compactedAt?: number;
1748
1822
  }): void {
1749
1823
  getDb().query(
1750
1824
  `INSERT INTO turn_usage
1751
1825
  (session_id, model, input_tokens, output_tokens, cache_read_tokens,
1752
1826
  cache_write_tokens, context_window, cost_usd, cold_start, cold_reason,
1753
- account_id, account_label)
1754
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
1827
+ account_id, account_label, context_tokens, cache_ttl_ms, compacted_at)
1828
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
1755
1829
  ).run(
1756
1830
  record.sessionId, record.model ?? null,
1757
1831
  record.inputTokens, record.outputTokens,
@@ -1759,9 +1833,50 @@ export function insertTurnUsage(record: {
1759
1833
  record.contextWindow ?? null, record.costUsd ?? null,
1760
1834
  record.coldStart ? 1 : 0, record.coldReason ?? null,
1761
1835
  record.accountId ?? null, record.accountLabel ?? null,
1836
+ record.contextTokens ?? null, record.cacheTtlMs ?? null, record.compactedAt ?? null,
1762
1837
  );
1763
1838
  }
1764
1839
 
1840
+ /**
1841
+ * When this session last wrote its prompt cache, and what it would cost to write again.
1842
+ *
1843
+ * The idle notice used to be answerable only from the live `SessionEntry`, which is dropped
1844
+ * five minutes after the last tab disconnects — while the cache it describes lives for an
1845
+ * hour. So the notice appeared only for a session left connected and went silent for exactly
1846
+ * the session reopened the next morning, which is the one it exists for. These three columns
1847
+ * are already written on every turn; reading them back is the whole fix.
1848
+ */
1849
+ export function getLastTurnCacheState(sessionId: string): {
1850
+ endedAtMs: number;
1851
+ prefixTokens: number;
1852
+ contextTokens?: number;
1853
+ cacheTtlMs?: number;
1854
+ compactedAt?: number;
1855
+ } | null {
1856
+ const row = getDb().query(
1857
+ `SELECT input_tokens, cache_read_tokens, cache_write_tokens, context_tokens, cache_ttl_ms, compacted_at, recorded_at
1858
+ FROM turn_usage WHERE session_id = ? ORDER BY id DESC LIMIT 1`,
1859
+ ).get(sessionId) as Pick<
1860
+ TurnUsageRow,
1861
+ "input_tokens" | "cache_read_tokens" | "cache_write_tokens" | "context_tokens" | "cache_ttl_ms" | "compacted_at" | "recorded_at"
1862
+ > | null;
1863
+ if (!row?.recorded_at) return null;
1864
+
1865
+ // `datetime('now')` is UTC and writes no zone suffix, which `Date` then reads as LOCAL
1866
+ // time — seven hours adrift in Asia/Saigon, enough to make the idle window come out
1867
+ // negative and silence the notice on precisely the machines it was rebuilt for.
1868
+ const endedAtMs = Date.parse(`${row.recorded_at.replace(" ", "T")}Z`);
1869
+ if (!Number.isFinite(endedAtMs)) return null;
1870
+
1871
+ return {
1872
+ endedAtMs,
1873
+ prefixTokens: row.input_tokens + row.cache_read_tokens + row.cache_write_tokens,
1874
+ ...(row.context_tokens != null && { contextTokens: row.context_tokens }),
1875
+ ...(row.cache_ttl_ms != null && { cacheTtlMs: row.cache_ttl_ms }),
1876
+ ...(row.compacted_at != null && { compactedAt: row.compacted_at }),
1877
+ };
1878
+ }
1879
+
1765
1880
  /** Most recent turns first — the debug dialog shows the tail of a session. */
1766
1881
  export function listTurnUsage(sessionId: string, limit = 30): TurnUsageRow[] {
1767
1882
  return getDb().query(
@@ -47,28 +47,40 @@ function osaLiteral(value: string): string {
47
47
  return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
48
48
  }
49
49
 
50
- function windowsCommand(path: string, isDirectory: boolean): string[] {
50
+ /**
51
+ * How a backend binary is found, replaceable for the same reason `TrashRunner` is.
52
+ *
53
+ * Which tool is present is as much a property of the host as what running it does, and
54
+ * leaving the lookup outside the seam meant a test could fake the run and still be refused
55
+ * before reaching it — on any machine without `gio` or `trash-put`, which includes the
56
+ * container the suite runs in.
57
+ */
58
+ export type TrashLookup = (name: string) => string | null;
59
+
60
+ const defaultLookup: TrashLookup = (name) => Bun.which(name);
61
+
62
+ function windowsCommand(path: string, isDirectory: boolean, which: TrashLookup): string[] {
51
63
  const method = isDirectory ? "DeleteDirectory" : "DeleteFile";
52
64
  const script =
53
65
  "Add-Type -AssemblyName Microsoft.VisualBasic; " +
54
66
  `[Microsoft.VisualBasic.FileIO.FileSystem]::${method}(${psLiteral(path)},'OnlyErrorDialogs','SendToRecycleBin')`;
55
- const shell = Bun.which("powershell") ?? Bun.which("pwsh");
67
+ const shell = which("powershell") ?? which("pwsh");
56
68
  if (!shell) throw noTrash("powershell not found on PATH");
57
69
  return [shell, "-NoProfile", "-NonInteractive", "-Command", script];
58
70
  }
59
71
 
60
72
  /** Paths are always absolute here, so no leading-dash option confusion. */
61
- function posixCommand(path: string): string[] {
73
+ function posixCommand(path: string, which: TrashLookup): string[] {
62
74
  if (process.platform === "darwin") {
63
- const trash = Bun.which("trash");
75
+ const trash = which("trash");
64
76
  if (trash) return [trash, path];
65
- const osascript = Bun.which("osascript");
77
+ const osascript = which("osascript");
66
78
  if (!osascript) throw noTrash("neither trash nor osascript found on PATH");
67
79
  return [osascript, "-e", `tell application "Finder" to delete POSIX file ${osaLiteral(path)}`];
68
80
  }
69
- const gio = Bun.which("gio");
81
+ const gio = which("gio");
70
82
  if (gio) return [gio, "trash", path];
71
- const trashPut = Bun.which("trash-put");
83
+ const trashPut = which("trash-put");
72
84
  if (trashPut) return [trashPut, path];
73
85
  throw noTrash("neither gio nor trash-put found on PATH");
74
86
  }
@@ -85,7 +97,7 @@ async function isDirectoryTarget(path: string): Promise<boolean> {
85
97
 
86
98
  export async function trashPath(
87
99
  path: string,
88
- options?: { run?: TrashRunner },
100
+ options?: { run?: TrashRunner; which?: TrashLookup },
89
101
  ): Promise<{ trashed: true; path: string }> {
90
102
  const target = resolvePath(path);
91
103
  assertAllowed(target);
@@ -94,8 +106,9 @@ export async function trashPath(
94
106
  await assertNotProtected(target);
95
107
  const isDir = await isDirectoryTarget(target);
96
108
 
109
+ const which = options?.which ?? defaultLookup;
97
110
  const cmd =
98
- process.platform === "win32" ? windowsCommand(target, isDir) : posixCommand(target);
111
+ process.platform === "win32" ? windowsCommand(target, isDir, which) : posixCommand(target, which);
99
112
 
100
113
  const run = options?.run ?? spawnRunner;
101
114
  let result: { exitCode: number; stderr: string };
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Every checkout target — local branches, remote-tracking branches and tags —
3
+ * out of a single `git for-each-ref`, with the commit each one points at.
4
+ *
5
+ * The format string is built from the field list rather than written out,
6
+ * because the parser reads fields *positionally*: a field added to one and not
7
+ * the other shifts everything after it, and git answers just as happily either
8
+ * way — the picker would simply show a date where the author belongs, with
9
+ * nothing failing.
10
+ *
11
+ * Six of the twelve fields are the `*`-dereferenced twins of six others, and
12
+ * they are what makes an **annotated** tag readable. `refs/tags/v1` resolves to
13
+ * the tag *object*, not to a commit: its `objectname` is the tag's own hash,
14
+ * it has a tagger rather than an author (so `%(authorname)` and
15
+ * `%(committerdate)` come back empty) and its `contents:subject` is the tag
16
+ * message. A lightweight tag has no such object and leaves every `*` field
17
+ * empty — which is why each pair is resolved as "dereferenced when non-empty,
18
+ * else plain" rather than by asking what kind of ref it is.
19
+ */
20
+ import type { GitRef } from "../../types/git.ts";
21
+
22
+ const FIELDS = [
23
+ "refname",
24
+ "objectname",
25
+ "*objectname",
26
+ "HEAD",
27
+ "upstream:short",
28
+ "upstream:track",
29
+ "authorname",
30
+ "*authorname",
31
+ "committerdate:iso-strict",
32
+ "*committerdate:iso-strict",
33
+ "contents:subject",
34
+ "*contents:subject",
35
+ ] as const;
36
+
37
+ /** NUL between fields, newline between records: no ref name or subject may contain either. */
38
+ export const FOR_EACH_REF_FORMAT = FIELDS.map((f) => `%(${f})`).join("%00");
39
+
40
+ export const FOR_EACH_REF_ARGS = [
41
+ "for-each-ref",
42
+ `--format=${FOR_EACH_REF_FORMAT}`,
43
+ "refs/heads",
44
+ "refs/remotes",
45
+ "refs/tags",
46
+ ];
47
+
48
+ const PREFIX: Record<GitRef["type"], string> = {
49
+ branch: "refs/heads/",
50
+ remote: "refs/remotes/",
51
+ tag: "refs/tags/",
52
+ };
53
+
54
+ /**
55
+ * `%(upstream:track)` as git writes it: `[ahead 1, behind 26]`, either half on
56
+ * its own, `[gone]` when the remote branch was deleted, or empty when the
57
+ * branch has no upstream at all.
58
+ */
59
+ export function parseUpstreamTrack(track: string): Pick<GitRef, "ahead" | "behind" | "gone"> {
60
+ if (track.includes("gone")) return { ahead: 0, behind: 0, gone: true };
61
+ const ahead = /ahead (\d+)/.exec(track);
62
+ const behind = /behind (\d+)/.exec(track);
63
+ return {
64
+ ahead: ahead ? Number(ahead[1]) : 0,
65
+ behind: behind ? Number(behind[1]) : 0,
66
+ gone: false,
67
+ };
68
+ }
69
+
70
+ function refType(refName: string): GitRef["type"] | null {
71
+ for (const [type, prefix] of Object.entries(PREFIX)) {
72
+ if (refName.startsWith(prefix)) return type as GitRef["type"];
73
+ }
74
+ return null;
75
+ }
76
+
77
+ /** Newest commit first. Compared as instants, never as strings: `iso-strict` carries the author's own offset. */
78
+ function newestFirst(a: GitRef, b: GitRef): number {
79
+ const at = Date.parse(a.date);
80
+ const bt = Date.parse(b.date);
81
+ if (Number.isNaN(at) || Number.isNaN(bt)) return a.name.localeCompare(b.name);
82
+ return bt - at;
83
+ }
84
+
85
+ export function parseForEachRef(stdout: string): GitRef[] {
86
+ const refs: GitRef[] = [];
87
+
88
+ for (const line of stdout.split("\n")) {
89
+ if (!line) continue;
90
+ const f = line.split("\0");
91
+ // A short record means a field carried a newline after all. Skipping it
92
+ // loses one row; reading it would silently shift every field of that row.
93
+ if (f.length < FIELDS.length) continue;
94
+
95
+ const refName = f[0]!;
96
+ const type = refType(refName);
97
+ if (!type) continue;
98
+ // `origin/HEAD` is a symbolic pointer at another row of this same list.
99
+ if (type === "remote" && refName.endsWith("/HEAD")) continue;
100
+
101
+ const hash = f[2] || f[1]!;
102
+ refs.push({
103
+ refName,
104
+ name: refName.slice(PREFIX[type].length),
105
+ type,
106
+ current: f[3] === "*",
107
+ hash,
108
+ shortHash: hash.slice(0, 7),
109
+ subject: f[11] || f[10]!,
110
+ author: f[7] || f[6]!,
111
+ date: f[9] || f[8]!,
112
+ upstream: f[4] || null,
113
+ ...parseUpstreamTrack(f[5]!),
114
+ });
115
+ }
116
+
117
+ return refs.sort(newestFirst);
118
+ }
@@ -1,13 +1,16 @@
1
1
  import path from "node:path";
2
2
  import simpleGit, { type SimpleGit } from "simple-git";
3
3
  import { isBinaryContent } from "./binary-content.ts";
4
+ import { FOR_EACH_REF_ARGS, parseForEachRef } from "./git-refs/for-each-ref.ts";
4
5
  import type {
6
+ CheckoutMode,
5
7
  FileFullDiff,
6
8
  GitStatus,
7
9
  GitFileChange,
8
10
  GitCommit,
9
11
  GitBranch,
10
12
  GitGraphData,
13
+ GitRef,
11
14
  GitWorktree,
12
15
  } from "../types/git.ts";
13
16
 
@@ -319,8 +322,28 @@ class GitService {
319
322
  await this.git(projectPath).checkoutBranch(name, from ?? "HEAD");
320
323
  }
321
324
 
322
- async checkout(projectPath: string, ref: string): Promise<void> {
323
- await this.git(projectPath).checkout(ref);
325
+ /**
326
+ * `track` is not a nicety: `git checkout origin/foo` lands on a **detached
327
+ * HEAD**, because the remote-tracking ref is not a branch anyone can commit
328
+ * to. `-t` is what creates the local `foo` that follows it. The picker
329
+ * chooses between the three modes; the service only has to keep them apart.
330
+ */
331
+ async checkout(
332
+ projectPath: string,
333
+ ref: string,
334
+ mode: CheckoutMode = "checkout",
335
+ ): Promise<void> {
336
+ const flags = mode === "detach" ? ["--detach"] : mode === "track" ? ["-t"] : [];
337
+ // `--` or the ref is read as a pathspec when no such ref exists: `git checkout src`
338
+ // in a repository with no branch named `src` restores every unstaged change under
339
+ // that directory, silently and with exit 0. `assertSafeRev` refuses a leading dash
340
+ // and a range, but a plain directory name is a legitimate ref shape.
341
+ await this.git(projectPath).checkout([...flags, ref, "--"]);
342
+ }
343
+
344
+ /** Every local branch, remote-tracking branch and tag, newest commit first. */
345
+ async refs(projectPath: string): Promise<GitRef[]> {
346
+ return parseForEachRef(await this.git(projectPath).raw(FOR_EACH_REF_ARGS));
324
347
  }
325
348
 
326
349
  async deleteBranch(
@@ -13,10 +13,37 @@ export type Runner = (argv: string[], timeoutMs?: number) => Promise<RunResult>;
13
13
 
14
14
  const DEFAULT_TIMEOUT_MS = 5000;
15
15
 
16
- /** Real implementation: argv array only (never string-interpolated into a shell), bounded by timeoutMs. */
16
+ /** Real implementation: argv array only (never string-interpolated into a shell), bounded by timeoutMs.
17
+ *
18
+ * `Bun.spawn` **throws synchronously** when the binary is not on `PATH`
19
+ * ("Executable not found in $PATH"), and for these providers that is a normal
20
+ * condition rather than an error: every one of them shells out to a per-OS tool
21
+ * (`systemctl`, `plutil`, `powershell.exe`, `findmnt`, `xdg-user-dir`,
22
+ * `nvidia-smi`), so on any other OS the binary is simply absent. Left to throw,
23
+ * it escapes the `Promise<RunResult>` this signature promises: the Services page
24
+ * on macOS and Windows answered 500 and showed the exception, instead of the
25
+ * "this host has no service manager" the collector is written to report.
26
+ *
27
+ * So a missing binary is returned as a run that failed — `code: null` with the
28
+ * message on stderr, which is the shape every caller already handles for a
29
+ * non-zero exit. */
30
+ const spawnPiped = (argv: string[]) =>
31
+ Bun.spawn(argv, { stdout: "pipe", stderr: "pipe", stdin: "ignore", windowsHide: true });
32
+
17
33
  export const defaultRunner: Runner = async (argv, timeoutMs = DEFAULT_TIMEOUT_MS) => {
18
- const proc = Bun.spawn(argv, { stdout: "pipe", stderr: "pipe", stdin: "ignore", windowsHide: true });
34
+ // Named via `spawnPiped` rather than `ReturnType<typeof Bun.spawn>`: the bare
35
+ // form loses the option narrowing, and `proc.stdout` widens back to a union
36
+ // with `number` (a raw fd) that `new Response()` will not take.
37
+ let proc: ReturnType<typeof spawnPiped>;
38
+ try {
39
+ proc = spawnPiped(argv);
40
+ } catch (e: any) {
41
+ return { stdout: "", stderr: e?.message ?? String(e), code: null, timedOut: false };
42
+ }
19
43
  let timedOut = false;
44
+ /** Resolves when the timeout fires, so the readers below stop waiting with the process. */
45
+ let giveUp!: () => void;
46
+ const abandoned = new Promise<void>((resolve) => { giveUp = resolve; });
20
47
  const killTimer = setTimeout(() => {
21
48
  timedOut = true;
22
49
  try {
@@ -24,12 +51,29 @@ export const defaultRunner: Runner = async (argv, timeoutMs = DEFAULT_TIMEOUT_MS
24
51
  } catch {
25
52
  // Process already exited between the timer firing and the kill call.
26
53
  }
54
+ giveUp();
27
55
  }, timeoutMs);
28
56
 
57
+ /**
58
+ * The output, or nothing once the run has been given up on.
59
+ *
60
+ * Killing the process does **not** close its pipes. A shell that forks rather than execs
61
+ * leaves a grandchild holding the write end, so draining stdout goes on until *that* exits —
62
+ * measured, `proc.exited` came back at the 150ms timeout while the drain ran the full five
63
+ * seconds, which means `timeoutMs` bounded nothing at all. The pending read is left to settle
64
+ * on its own and discarded rather than cancelled: cancelling a subprocess stream has crashed
65
+ * Bun on Windows before, and there is nothing here worth that risk.
66
+ */
67
+ const readOrAbandon = (stream: ReadableStream<Uint8Array>): Promise<string> =>
68
+ Promise.race([
69
+ new Response(stream).text().catch(() => ""),
70
+ abandoned.then(() => ""),
71
+ ]);
72
+
29
73
  try {
30
74
  const [stdout, stderr, code] = await Promise.all([
31
- new Response(proc.stdout).text(),
32
- new Response(proc.stderr).text(),
75
+ readOrAbandon(proc.stdout),
76
+ readOrAbandon(proc.stderr),
33
77
  proc.exited,
34
78
  ]);
35
79
  return { stdout, stderr, code, timedOut };