@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
@@ -28,7 +28,9 @@ import { BottomSheet } from "@/components/ui/mobile-bottom-sheet";
28
28
  import { GitRepoBar, GitRepoChoice, GitNoRepo } from "@/components/git/git-repo-picker";
29
29
  import { FileIcon } from "@/lib/file-icons";
30
30
  import { buildTree, compactTree } from "@/lib/git-file-tree";
31
- import { StartEllipsis, TreeRow } from "./branch-review-tree-row";
31
+ import { TreeRow } from "./branch-review-tree-row";
32
+ import { StartEllipsis } from "@/components/ui/start-ellipsis";
33
+ import { BranchSelect } from "@/components/git/branch-select";
32
34
  import {
33
35
  Check, ChevronDown, ChevronRight, FileText, Loader2, RefreshCw, ListChecks, ArrowRight,
34
36
  } from "@/lib/icons";
@@ -246,30 +248,28 @@ export function BranchReviewTab({ metadata }: BranchReviewTabProps) {
246
248
  )}
247
249
 
248
250
  {/*
249
- Native selects rather than the shadcn one: a repository can have
250
- hundreds of branches, and the OS picker is both scrollable and a far
251
- better touch target than a rendered popover on a phone.
251
+ A searchable picker rather than a native `<select>`: the list is the
252
+ whole problem here — hundreds of branches, all sharing a prefix — and a
253
+ native picker cannot be filtered. See `branch-select.tsx`.
252
254
  */}
253
255
  <div className="flex items-center gap-2 px-2 py-1.5 border-b border-border shrink-0 flex-wrap">
254
- <select
256
+ <BranchSelect
255
257
  value={base}
256
- onChange={(e) => setBase(e.target.value)}
257
- aria-label="Base branch"
258
- data-testid="branch-review-base"
259
- className="h-7 max-w-[38%] rounded-md border border-border bg-panel px-2 text-xs min-w-0"
260
- >
261
- {branches.map((b) => <option key={b.name} value={b.name}>{b.name}</option>)}
262
- </select>
258
+ branches={branches}
259
+ onChange={setBase}
260
+ label="Base branch"
261
+ testId="branch-review-base"
262
+ className="max-w-[38%]"
263
+ />
263
264
  <ArrowRight className="size-3.5 text-text-3 shrink-0" />
264
- <select
265
+ <BranchSelect
265
266
  value={head}
266
- onChange={(e) => setHead(e.target.value)}
267
- aria-label="Branch to review"
268
- data-testid="branch-review-head"
269
- className="h-7 max-w-[38%] rounded-md border border-border bg-panel px-2 text-xs min-w-0"
270
- >
271
- {branches.map((b) => <option key={b.name} value={b.name}>{b.name}</option>)}
272
- </select>
267
+ branches={branches}
268
+ onChange={setHead}
269
+ label="Branch to review"
270
+ testId="branch-review-head"
271
+ className="max-w-[38%]"
272
+ />
273
273
 
274
274
  <div className="ml-auto flex items-center gap-2">
275
275
  <span className="text-xs text-text-2 tabular-nums" data-testid="branch-review-progress">
@@ -18,6 +18,7 @@ import { Check, ChevronDown, ChevronRight } from "@/lib/icons";
18
18
  import { FileIcon } from "@/lib/file-icons";
19
19
  import { isReviewed, type ReviewState } from "@/lib/branch-review-state";
20
20
  import type { TreeNode } from "@/lib/git-file-tree";
21
+ import { StartEllipsis } from "@/components/ui/start-ellipsis";
21
22
  import type { BranchDiffFile } from "../../../types/git";
22
23
 
23
24
  export const STATUS_COLORS: Record<BranchDiffFile["status"], string> = {
@@ -32,19 +33,6 @@ export const STATUS_COLORS: Record<BranchDiffFile["status"], string> = {
32
33
  /** Indent per nesting level, matching the Source Control tree. */
33
34
  export const TREE_INDENT = 14;
34
35
 
35
- /**
36
- * Ellipsize from the start, so the end of a path — the part that differs —
37
- * survives. Same trick as the Source Control panel: a right-to-left box cuts at
38
- * its left edge, and `<bdi>` keeps the name itself reading left to right.
39
- */
40
- export function StartEllipsis({ children }: { children: string }) {
41
- return (
42
- <span dir="rtl" className="truncate text-left min-w-0 flex-1">
43
- <bdi>{children}</bdi>
44
- </span>
45
- );
46
- }
47
-
48
36
  export interface TreeRowProps {
49
37
  node: TreeNode;
50
38
  depth: number;
@@ -301,6 +301,7 @@ function ChatTabContent({ metadata, tabId, onNewSession, onFork, historyFilter }
301
301
  pendingApproval,
302
302
  contextWindowPct,
303
303
  compactStatus,
304
+ promptCache,
304
305
  mcpNeedsAuth,
305
306
  statusMessage,
306
307
  sessionTitle,
@@ -1027,6 +1028,7 @@ function ChatTabContent({ metadata, tabId, onNewSession, onFork, historyFilter }
1027
1028
  connectingElapsed={connectingElapsed}
1028
1029
  statusMessage={statusMessage}
1029
1030
  compactStatus={compactStatus}
1031
+ promptCache={promptCache}
1030
1032
  projectName={projectName}
1031
1033
  onFork={!isStreaming ? handleFork : undefined}
1032
1034
  onEdit={!isStreaming ? handleEdit : undefined}
@@ -1158,6 +1160,7 @@ function ChatTabContent({ metadata, tabId, onNewSession, onFork, historyFilter }
1158
1160
  onEffortChange={setEffort}
1159
1161
  thinking={thinking}
1160
1162
  onThinkingChange={setThinking}
1163
+ promptCache={promptCache}
1161
1164
  />
1162
1165
  )}
1163
1166
  </div>
@@ -0,0 +1,48 @@
1
+ import { Layers } from "@/lib/icons";
2
+ import type { CompactionInfo } from "../../../types/chat";
3
+ import { fmtTokens } from "../../../shared/turn-usage";
4
+
5
+ /**
6
+ * The rule above a compact summary, saying what that compaction did.
7
+ *
8
+ * Compaction is the largest thing that happens to a chat and the only one with no
9
+ * visible cause: most of the history stops being sent, the next turn's prefix
10
+ * collapses, and all the transcript shows for it is a long summary message that
11
+ * reads like something the assistant chose to write. Naming it — and how much it
12
+ * dropped — is what makes the rest of the conversation legible.
13
+ *
14
+ * Deliberately not interactive. Loading the messages it replaced is already the job
15
+ * of the scroll-to-top expansion right above it, and a second control for the same
16
+ * thing would be two affordances competing over one gesture.
17
+ */
18
+ export function CompactionDivider({ compaction }: { compaction: CompactionInfo }) {
19
+ const { trigger, preTokens, postTokens, savedTokens, durationMs } = compaction;
20
+
21
+ const detail = [
22
+ trigger === "manual" ? "Ran with /compact" : "Ran automatically on a full context window",
23
+ `${fmtTokens(preTokens)} → ${fmtTokens(postTokens)} tokens`,
24
+ ...(durationMs != null ? [`took ${formatDuration(durationMs)}`] : []),
25
+ ].join(" · ");
26
+
27
+ return (
28
+ <div className="flex items-center gap-2 pt-2 text-[11px] text-text-subtle" title={detail}>
29
+ <div className="h-px flex-1 bg-border" />
30
+ <span className="flex shrink-0 items-center gap-1.5">
31
+ <Layers className="size-3.5" />
32
+ {/* `tabular-nums` so the figure does not jitter when a re-read changes it. */}
33
+ <span className="tabular-nums">
34
+ Compacted session · saved {fmtTokens(savedTokens)} tokens
35
+ </span>
36
+ </span>
37
+ <div className="h-px flex-1 bg-border" />
38
+ </div>
39
+ );
40
+ }
41
+
42
+ /** Coarse on purpose: this is a footnote, and a compaction is never sub-second. */
43
+ function formatDuration(ms: number): string {
44
+ const seconds = Math.round(ms / 1000);
45
+ if (seconds < 60) return `${seconds}s`;
46
+ const minutes = Math.floor(seconds / 60);
47
+ return `${minutes}m ${seconds % 60}s`;
48
+ }
@@ -0,0 +1,67 @@
1
+ import { Clock } from "@/lib/icons";
2
+ import { useMinuteClock } from "@/hooks/use-minute-clock";
3
+ import type { PromptCacheState } from "../../../shared/prompt-cache-idle";
4
+ import { idleCacheNotice, formatIdleDuration, formatContextTokens } from "../../../shared/prompt-cache-idle";
5
+
6
+ /**
7
+ * How long the session has been idle, when that has stopped being free.
8
+ *
9
+ * Sits above the composer rather than in the transcript: it describes what the *next*
10
+ * message will cost, not anything that has happened, and the transcript is a record of
11
+ * what did. It disappears on its own the moment a turn starts, because by then the
12
+ * decision it exists to inform has been made.
13
+ *
14
+ * Says one of two things. A compaction replaced the conversation, so the cache holds a prefix
15
+ * that will never be sent again — that is reported without a token figure, because the
16
+ * summary it produced has not been through an API call yet and nothing has measured it.
17
+ * Otherwise the cache simply lapsed, and the transcript still standing is what gets re-sent.
18
+ *
19
+ * Names a token figure only when one was measured. `modelUsage` cannot supply it — the SDK
20
+ * accumulates it across the session and across subagents, which is what once printed "1.0M
21
+ * tokens" against a window of the same size — so the number comes from the turn's last
22
+ * top-level assistant message instead (`TurnUsage.contextTokens`). Turns recorded before PPM
23
+ * measured that carry none, and the sentence has to stand without it.
24
+ *
25
+ * Owns its outer padding so that "no notice" costs no layout: the caller renders this
26
+ * unconditionally, and a wrapper with padding around nothing is a gap above the composer
27
+ * that appears for no reason.
28
+ */
29
+ export function IdleCacheNotice({ promptCache }: { promptCache: PromptCacheState | null }) {
30
+ const notice = idleCacheNotice(promptCache, useMinuteClock());
31
+ if (!notice) return null;
32
+
33
+ return (
34
+ // Same `px-4 pt-4 pb-4` as the approval/thinking block below, so the notice keeps the
35
+ // composer's breathing room instead of sitting on top of it.
36
+ <div className="px-4 pt-4 pb-4 select-none">
37
+ {/* `w-fit` rather than a full-width row: this is one sentence, and a thin bordered
38
+ box stretched across an ultrawide reads as a broken layout. It still falls back
39
+ to the available width — and wraps — on a phone. */}
40
+ <div className="flex w-fit items-start gap-2 rounded-md border border-border bg-surface px-2.5 py-2 text-[11px] text-text-secondary">
41
+ <Clock className="mt-px size-3.5 shrink-0 text-text-subtle" />
42
+ {notice.reason === "compacted" ? (
43
+ <span>
44
+ The conversation was compacted{" "}
45
+ <span className="tabular-nums">{formatIdleDuration(notice.idleMs)}</span> ago, so the
46
+ prompt cache no longer covers it and your next message will re-cache it.
47
+ </span>
48
+ ) : (
49
+ <span>
50
+ Idle <span className="tabular-nums">{formatIdleDuration(notice.idleMs)}</span>. The
51
+ prompt cache has likely expired, so your next message re-sends{" "}
52
+ {notice.contextTokens != null ? (
53
+ <>
54
+ about{" "}
55
+ <span className="tabular-nums">{formatContextTokens(notice.contextTokens)}</span>{" "}
56
+ tokens
57
+ </>
58
+ ) : (
59
+ "the whole transcript"
60
+ )}{" "}
61
+ at full price.
62
+ </span>
63
+ )}
64
+ </div>
65
+ </div>
66
+ );
67
+ }
@@ -3,6 +3,8 @@ import { useProjectStore } from "@/stores/project-store";
3
3
  import { useState, useRef, useCallback, useEffect, memo, type KeyboardEvent, type DragEvent, type ClipboardEvent } from "react";
4
4
  import { ArrowUp, Square, Paperclip, Loader2, Mic, MicOff, Zap, ListOrdered, Clock, Bot, X } from "@/lib/icons";
5
5
  import { useVoiceInput } from "@/hooks/use-voice-input";
6
+ import { useWhisperVoiceInput } from "@/hooks/use-whisper-voice-input";
7
+ import { useSettingsStore } from "@/stores/settings-store";
6
8
  import { api, projectUrl, getAuthToken } from "@/lib/api-client";
7
9
  import { downscaleImage } from "@/lib/image-resize";
8
10
  import { INLINE_IMAGE_LIMITS } from "@/lib/image-resize-limits";
@@ -20,6 +22,8 @@ import type { SlashItem } from "./slash-command-picker";
20
22
  import { fetchSlashItems, clearSlashItemsCache } from "@/lib/slash-items-cache";
21
23
  import type { FileNode } from "../../../types/project";
22
24
  import { useFileStore } from "@/stores/file-store";
25
+ import { PromptCacheChip } from "./prompt-cache-chip";
26
+ import type { PromptCacheState } from "../../../shared/prompt-cache-idle";
23
27
 
24
28
  /**
25
29
  * Base64 payload for an image file, or undefined when it cannot be read.
@@ -136,6 +140,8 @@ interface MessageInputProps {
136
140
  thinking?: boolean;
137
141
  /** Thinking toggle handler */
138
142
  onThinkingChange?: (enabled: boolean) => void;
143
+ /** This session's prompt-cache clock, for the countdown chip */
144
+ promptCache?: PromptCacheState | null;
139
145
  }
140
146
 
141
147
  export const MessageInput = memo(function MessageInput({
@@ -172,6 +178,7 @@ export const MessageInput = memo(function MessageInput({
172
178
  onEffortChange,
173
179
  thinking,
174
180
  onThinkingChange,
181
+ promptCache,
175
182
  configurationPending = false,
176
183
  }: MessageInputProps) {
177
184
  // Uncontrolled textarea: value lives in DOM + ref, not React state.
@@ -248,8 +255,16 @@ export const MessageInput = memo(function MessageInput({
248
255
  [getUserHistory, writeTextareas, getVisibleTextarea],
249
256
  );
250
257
 
251
- // Voice input (Web Speech API)
252
- const voice = useVoiceInput();
258
+ // Voice input. Two engines behind the same button: the browser's own
259
+ // recogniser (text appears as you speak, but Chrome/Edge/Safari only) and
260
+ // Whisper running on the PPM host (any browser, answers once at the end).
261
+ // Settings picks, per device; an engine the device cannot do falls back.
262
+ const voiceEngine = useSettingsStore((s) => s.voiceEngine);
263
+ const browserVoice = useVoiceInput();
264
+ const whisperVoice = useWhisperVoiceInput();
265
+ const useWhisper = voiceEngine === "whisper" && whisperVoice.supported;
266
+ const voice = useWhisper ? whisperVoice : browserVoice;
267
+ const isTranscribing = useWhisper && whisperVoice.isTranscribing;
253
268
  // Store pre-voice text so voice appends to existing input
254
269
  const preVoiceTextRef = useRef("");
255
270
  const voiceResultCb = useCallback((text: string) => {
@@ -268,13 +283,20 @@ export const MessageInput = memo(function MessageInput({
268
283
  }
269
284
  }, [writeTextareas, getVisibleTextarea]);
270
285
  const handleVoiceToggle = useCallback(() => {
286
+ // The shortcut reaches this while Whisper is still working on the last
287
+ // recording, where the button is already disabled.
288
+ if (isTranscribing) return;
271
289
  if (voice.isListening) {
272
290
  voice.stop();
273
291
  } else {
274
292
  preVoiceTextRef.current = valueRef.current.trim();
275
293
  voice.start(voiceResultCb);
276
294
  }
277
- }, [voice.isListening, voice.start, voice.stop, voiceResultCb]);
295
+ }, [voice.isListening, voice.start, voice.stop, voiceResultCb, isTranscribing]);
296
+
297
+ const micLabel = isTranscribing
298
+ ? "Transcribing"
299
+ : voice.isListening ? "Stop voice input" : "Start voice input";
278
300
 
279
301
  // Listen for global keyboard shortcut (Cmd+Shift+V) to toggle voice.
280
302
  // Guarded so that only the focused panel's chat reacts — every chat tab stays
@@ -691,7 +713,13 @@ export const MessageInput = memo(function MessageInput({
691
713
  slashPickerOpenRef.current = false;
692
714
  onFileStateChange?.(false, "");
693
715
  filePickerOpenRef.current = false;
694
- if (voice.isListening) voice.stop();
716
+ // Sending closes the mic. Whisper's recording is dropped rather than
717
+ // transcribed: its text would arrive seconds later, into the box the
718
+ // message just left.
719
+ if (voice.isListening) {
720
+ if (useWhisper) whisperVoice.cancel();
721
+ else voice.stop();
722
+ }
695
723
  onSend(content, readyAttachments, isStreaming ? priority : undefined);
696
724
  writeTextareas("");
697
725
  // Revoke preview URLs
@@ -707,7 +735,8 @@ export const MessageInput = memo(function MessageInput({
707
735
  if (textareaRef.current) textareaRef.current.style.height = "auto";
708
736
  if (mobileTextareaRef.current) mobileTextareaRef.current.style.height = "auto";
709
737
  }
710
- }, [attachments, agentTag, onSend, onSlashStateChange, onFileStateChange, isStreaming, priority, writeTextareas]);
738
+ }, [attachments, agentTag, onSend, onSlashStateChange, onFileStateChange, isStreaming, priority, writeTextareas,
739
+ voice.isListening, voice.stop, whisperVoice.cancel, useWhisper]);
711
740
 
712
741
  const handleSend = useCallback(() => {
713
742
  if (disabled) return;
@@ -933,7 +962,7 @@ export const MessageInput = memo(function MessageInput({
933
962
  {/* Attachment chips (inside container, aligned with input) */}
934
963
  <AttachmentChips attachments={attachments} onRemove={removeAttachment} />
935
964
  {/* Mobile: mode chip + provider selector row */}
936
- <div className="flex items-center gap-1 px-2 pt-2 md:hidden relative">
965
+ <div className="flex flex-wrap items-center gap-1 px-2 pt-2 md:hidden relative">
937
966
  {!configurationPending && <>
938
967
  <ModeChip
939
968
  mode={permissionMode ?? "bypassPermissions"}
@@ -967,6 +996,7 @@ export const MessageInput = memo(function MessageInput({
967
996
  />
968
997
  )}
969
998
  {isStreaming && <PriorityToggle value={priority} onChange={setPriority} />}
999
+ <PromptCacheChip promptCache={promptCache ?? null} />
970
1000
  </div>
971
1001
  {/* Mobile: single row — attach + textarea + mic + send */}
972
1002
  <div className="flex items-end gap-1 md:hidden px-2 py-2">
@@ -996,15 +1026,17 @@ export const MessageInput = memo(function MessageInput({
996
1026
  <button
997
1027
  type="button"
998
1028
  onClick={(e) => { e.stopPropagation(); handleVoiceToggle(); }}
999
- disabled={disabled}
1029
+ disabled={disabled || isTranscribing}
1000
1030
  className={`flex items-center justify-center size-8 shrink-0 rounded-[10px] transition-colors disabled:opacity-50 ${
1001
1031
  voice.isListening
1002
1032
  ? "bg-error text-white animate-pulse"
1003
1033
  : "text-text-3 hover:text-text-primary"
1004
1034
  }`}
1005
- aria-label={voice.isListening ? "Stop voice input" : "Start voice input"}
1035
+ aria-label={micLabel}
1006
1036
  >
1007
- {voice.isListening ? <MicOff className="size-4" /> : <Mic className="size-4" />}
1037
+ {isTranscribing
1038
+ ? <Loader2 className="size-4 animate-spin" />
1039
+ : voice.isListening ? <MicOff className="size-4" /> : <Mic className="size-4" />}
1008
1040
  </button>
1009
1041
  )}
1010
1042
  {showCancel ? (
@@ -1030,7 +1062,7 @@ export const MessageInput = memo(function MessageInput({
1030
1062
  {/* Desktop: chips row (permission + model) then a single input row
1031
1063
  (paperclip | textarea | mic | send) — design PPMWorkspace composer. */}
1032
1064
  <div className="hidden md:block">
1033
- <div className="flex items-center gap-1.5 px-2.5 pt-2.5">
1065
+ <div className="flex flex-wrap items-center gap-1.5 px-2.5 pt-2.5">
1034
1066
  {/* Mode indicator chip */}
1035
1067
  {!configurationPending && <div className="relative">
1036
1068
  <ModeChip
@@ -1066,6 +1098,7 @@ export const MessageInput = memo(function MessageInput({
1066
1098
  />
1067
1099
  )}
1068
1100
  {isStreaming && <PriorityToggle value={priority} onChange={setPriority} />}
1101
+ <PromptCacheChip promptCache={promptCache ?? null} />
1069
1102
  </div>
1070
1103
  <div className="flex items-end gap-2 px-2.5 py-2">
1071
1104
  <button
@@ -1094,15 +1127,17 @@ export const MessageInput = memo(function MessageInput({
1094
1127
  <button
1095
1128
  type="button"
1096
1129
  onClick={(e) => { e.stopPropagation(); handleVoiceToggle(); }}
1097
- disabled={disabled}
1130
+ disabled={disabled || isTranscribing}
1098
1131
  className={`flex items-center justify-center size-[34px] shrink-0 rounded-[10px] transition-colors disabled:opacity-50 ${
1099
1132
  voice.isListening
1100
1133
  ? "bg-error text-white animate-pulse"
1101
1134
  : "text-text-3 hover:text-text-primary hover:bg-surface-elevated"
1102
1135
  }`}
1103
- aria-label={voice.isListening ? "Stop voice input" : "Start voice input"}
1136
+ aria-label={micLabel}
1104
1137
  >
1105
- {voice.isListening ? <MicOff className="size-[17px]" /> : <Mic className="size-[17px]" />}
1138
+ {isTranscribing
1139
+ ? <Loader2 className="size-[17px] animate-spin" />
1140
+ : voice.isListening ? <MicOff className="size-[17px]" /> : <Mic className="size-[17px]" />}
1106
1141
  </button>
1107
1142
  )}
1108
1143
  {showCancel ? (
@@ -18,6 +18,9 @@ import { extractJsonlPath } from "./pre-compact-button";
18
18
  import { MarkdownContent } from "./message-markdown";
19
19
  import { UserBubble } from "./message-user-bubble";
20
20
  import { InterleavedEvents, ThinkingIndicator } from "./message-events";
21
+ import { CompactionDivider } from "./compaction-divider";
22
+ import { IdleCacheNotice } from "./idle-cache-notice";
23
+ import type { PromptCacheState } from "../../../shared/prompt-cache-idle";
21
24
  import { RenderErrorBoundary } from "@/components/shared/markdown-error-boundary";
22
25
 
23
26
  import {
@@ -50,6 +53,8 @@ interface MessageListProps {
50
53
  connectingElapsed?: number;
51
54
  statusMessage?: string | null;
52
55
  compactStatus?: "compacting" | null;
56
+ /** Prompt-cache clock for the idle re-cache notice; null when PPM cannot measure it. */
57
+ promptCache?: PromptCacheState | null;
53
58
  projectName?: string;
54
59
  /** Called when user clicks Fork/Rewind — opens new forked chat tab */
55
60
  onFork?: (userMessage: string, messageId?: string) => void;
@@ -127,6 +132,7 @@ export function MessageList({
127
132
  connectingElapsed,
128
133
  statusMessage,
129
134
  compactStatus,
135
+ promptCache,
130
136
  projectName,
131
137
  onFork,
132
138
  onEdit,
@@ -454,6 +460,10 @@ export function MessageList({
454
460
  data-msg-index={globalIdx}
455
461
  className="px-4 pt-4 select-none"
456
462
  >
463
+ {/* Above the summary rather than beside it: the rule is what marks
464
+ where the conversation was cut, and the summary is the first
465
+ message on the new side of it. */}
466
+ {msg.compaction && <CompactionDivider compaction={msg.compaction} />}
457
467
  <RenderErrorBoundary fallbackContent={msg.content}>
458
468
  <MessageBubble
459
469
  message={msg}
@@ -479,6 +489,11 @@ export function MessageList({
479
489
  </div>
480
490
  );
481
491
  })}
492
+ {/* Idle only: once a turn starts the cache question is already answered, and the
493
+ thinking indicator below owns that space. */}
494
+ {!isStreaming && !pendingApproval && (
495
+ <IdleCacheNotice promptCache={promptCache ?? null} />
496
+ )}
482
497
  {hasTrailing && (
483
498
  <div className="px-4 pt-4 pb-4 space-y-4 select-none">
484
499
  {pendingApproval && (
@@ -0,0 +1,74 @@
1
+ import { Clock } from "@/lib/icons";
2
+ import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
3
+ import { useMinuteClock } from "@/hooks/use-minute-clock";
4
+ import type { PromptCacheState } from "../../../shared/prompt-cache-idle";
5
+ import {
6
+ promptCacheStatus,
7
+ formatCacheCountdown,
8
+ formatIdleDuration,
9
+ formatContextTokens,
10
+ } from "../../../shared/prompt-cache-idle";
11
+
12
+ /**
13
+ * How long this session's prompt cache has left, in the composer's chip row.
14
+ *
15
+ * The banner above the composer only appears once the cache is already gone, which answers
16
+ * "why was that turn expensive" after the fact. This is the same fact while it can still be
17
+ * acted on — a countdown says the next message is cheap *now*, and going red says it is not.
18
+ *
19
+ * Reads as a chip rather than a control because there is nothing to click: the cache's clock
20
+ * is not a setting. Renders nothing at all when PPM has not measured the session, so a chat
21
+ * with no completed turn shows a row unchanged from before.
22
+ *
23
+ * The hover text is the only part that is hover-only, and deliberately so: everything it
24
+ * says is already on screen as the chip's own number and, once expired, as the banner. So
25
+ * touch loses a sentence of phrasing rather than a fact — which is why this needs no tap
26
+ * affordance and stays out of the composer's tab order.
27
+ */
28
+ export function PromptCacheChip({ promptCache }: { promptCache: PromptCacheState | null }) {
29
+ const status = promptCacheStatus(promptCache, useMinuteClock());
30
+ if (status.kind === "unknown") return null;
31
+
32
+ const cold = status.kind === "cold";
33
+ const label = status.kind === "cold"
34
+ ? formatIdleDuration(status.idleMs)
35
+ : formatCacheCountdown(status.remainingMs);
36
+
37
+ let detail: string;
38
+ if (status.kind !== "cold") {
39
+ detail = `Prompt cache warm, about ${label.replace(/m$/, " min")} left.`;
40
+ } else if (status.reason === "compacted") {
41
+ // No token figure here on purpose: what the next message re-caches is the summary the
42
+ // compaction just produced, and no API call has reported its size yet.
43
+ detail = `Prompt cache does not cover the compacted conversation. Compacted ${label} ago, so your next message will re-cache it.`;
44
+ } else {
45
+ detail = `Prompt cache expired ${label} ago. Your next message re-sends ${
46
+ status.contextTokens != null
47
+ ? `about ${formatContextTokens(status.contextTokens)} tokens`
48
+ : "the whole transcript"
49
+ } at full price.`;
50
+ }
51
+
52
+ return (
53
+ <Tooltip>
54
+ <TooltipTrigger asChild>
55
+ <span
56
+ // Same shape as `ModeChip` and `PriorityToggle` beside it; only the colour carries
57
+ // the state, and only once the cache is gone — a countdown still running is not news.
58
+ className={`inline-flex items-center gap-1.5 px-[9px] py-1 rounded-full text-[11.5px] border transition-colors ${
59
+ cold
60
+ ? "text-error border-error/40 bg-error/10"
61
+ : "text-text-2 bg-panel-2 border-border-soft"
62
+ }`}
63
+ >
64
+ <Clock className="size-3" />
65
+ {/* `tabular-nums` so a minute ticking over does not shift the chips beside it. */}
66
+ <span className="tabular-nums">{label}</span>
67
+ </span>
68
+ </TooltipTrigger>
69
+ <TooltipContent side="top" className="max-w-[240px] text-xs">
70
+ {detail}
71
+ </TooltipContent>
72
+ </Tooltip>
73
+ );
74
+ }
@@ -860,6 +860,7 @@ export const CodeEditor = memo(function CodeEditor({ metadata, tabId }: CodeEdit
860
860
  onToggle={setLspEnabled}
861
861
  status={lsp.status}
862
862
  diagnostics={lsp.diagnostics}
863
+ onInstall={lsp.install}
863
864
  />
864
865
  )}
865
866
  <EditorLanguagePicker value={effectiveLanguage} onChange={handleLanguageChange} />
@@ -23,6 +23,14 @@ import { useTabStore } from "@/stores/tab-store";
23
23
  export interface EditorLspState {
24
24
  status: LspDocumentStatus | null;
25
25
  diagnostics: LspDiagnostic[];
26
+ /**
27
+ * Install the server this file has none of.
28
+ *
29
+ * Handed up rather than called from the toolbar directly: the indicator lives on the
30
+ * editor's static path, and one runtime import of the LSP client there would merge this
31
+ * whole chunk back into the editor's — see `editor-lsp-lazy-boundary.test.ts`.
32
+ */
33
+ install?: (serverId: string) => Promise<void>;
26
34
  }
27
35
 
28
36
  const NO_LSP_STATE: EditorLspState = { status: null, diagnostics: [] };
@@ -39,7 +47,7 @@ interface EditorLanguageServiceProps {
39
47
  export function EditorLanguageService({
40
48
  editor, monaco, projectName, filePath, onState,
41
49
  }: EditorLanguageServiceProps) {
42
- const { status, diagnostics } = useLsp({ editor, monaco, projectName, filePath, enabled: true });
50
+ const { status, diagnostics, install } = useLsp({ editor, monaco, projectName, filePath, enabled: true });
43
51
 
44
52
  // F12. Monaco's own binding would swap another file's model into this
45
53
  // editor, leaving the tab titled and dirty-tracked as the old file. Disposed
@@ -64,8 +72,8 @@ export function EditorLanguageService({
64
72
  onStateRef.current = onState;
65
73
 
66
74
  useEffect(() => {
67
- onStateRef.current({ status, diagnostics });
68
- }, [status, diagnostics]);
75
+ onStateRef.current({ status, diagnostics, install });
76
+ }, [status, diagnostics, install]);
69
77
 
70
78
  // The editor keeps drawing whatever it was last told, so a language service
71
79
  // that is going away has to retract its own status.