@hienlh/ppm 0.21.0 → 0.22.1

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 (620) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/CLAUDE.md +29 -4
  3. package/THIRD-PARTY-NOTICES.md +1 -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 +1 -1
  7. package/bun.lock +16 -1
  8. package/dist/web/assets/accounts-settings-section-D3BylchP.js +1 -0
  9. package/dist/web/assets/{ai-resource-editor-F09pf8Hd.js → ai-resource-editor-BLPcnhTM.js} +1 -1
  10. package/dist/web/assets/ai-settings-section-BtR7rF-T.js +1 -0
  11. package/dist/web/assets/ai-settings-section-r9JctHNM.js +1 -0
  12. package/dist/web/assets/{angular-html-DkR4iCth.js → angular-html-G66FNlyn.js} +1 -1
  13. package/dist/web/assets/{angular-ts-DcyL4Chx.js → angular-ts-B-PnUMyt.js} +1 -1
  14. package/dist/web/assets/{api-client-bfB7cXRM.js → api-client-C1ZwRL4Y.js} +1 -1
  15. package/dist/web/assets/api-client-pQL53cDQ.js +1 -0
  16. package/dist/web/assets/{api-settings-BcNjZIvG.js → api-settings-_7Q-ULxp.js} +1 -1
  17. package/dist/web/assets/{api-themes-DBfyVUtX.js → api-themes-DRAERo4Q.js} +1 -1
  18. package/dist/web/assets/{apl-BVlrVtjt.js → apl-BmDqqwE8.js} +1 -1
  19. package/dist/web/assets/{appearance-settings-section-whgnq3ss.js → appearance-settings-section-CiMdk3sb.js} +1 -1
  20. package/dist/web/assets/architecture-PBZL5I3N-Dx6nBEKT.js +1 -0
  21. package/dist/web/assets/{astro-MjJlozLj.js → astro-BfwMNfxr.js} +1 -1
  22. package/dist/web/assets/{audio-preview-Bc54GCAV.js → audio-preview-DsYvgKqj.js} +1 -1
  23. package/dist/web/assets/{blade-DnJWi1fz.js → blade-BsFV4pnN.js} +1 -1
  24. package/dist/web/assets/branch-review-tab-B1pFjlKM.js +1 -0
  25. package/dist/web/assets/{bsl-DCmJxSIz.js → bsl-Cw9Outng.js} +1 -1
  26. package/dist/web/assets/{button-VW4QGKCn.js → button-B9CTrsEf.js} +1 -1
  27. package/dist/web/assets/{cairo-C8dDenub.js → cairo-DOK5Wqnd.js} +1 -1
  28. package/dist/web/assets/chat-tab-DZagX06m.js +15 -0
  29. package/dist/web/assets/{cobol-DPx_nifl.js → cobol-DRaRy4FK.js} +1 -1
  30. package/dist/web/assets/code-editor-BJhOEsnZ.js +7 -0
  31. package/dist/web/assets/{codex-daily-guard-CfybHv_c.js → codex-daily-guard-CaCQJ4r_.js} +1 -1
  32. package/dist/web/assets/{coffee-DvFzqhgN.js → coffee-DvXuBmEJ.js} +1 -1
  33. package/dist/web/assets/{conflict-editor-DenQUOT2.js → conflict-editor-B7u_p49h.js} +3 -3
  34. package/dist/web/assets/context-menu-C6pIsf83.js +1 -0
  35. package/dist/web/assets/{cpp-BLJN0umi.js → cpp-zCmm8rKA.js} +1 -1
  36. package/dist/web/assets/{crystal-BXR-9fGw.js → crystal-CdQx6lB6.js} +1 -1
  37. package/dist/web/assets/{csv-preview-CClrJOuR.js → csv-preview-CttjJU1e.js} +1 -1
  38. package/dist/web/assets/{data-grid-overlay-editor-D4fhcMfT.js → data-grid-overlay-editor-6xUCeLHh.js} +1 -1
  39. package/dist/web/assets/{database-viewer-DItjm8wB.js → database-viewer-Ca4HxIfx.js} +1 -1
  40. package/dist/web/assets/{dialog-DQTn55Mt.js → dialog-B84_DJQ8.js} +1 -1
  41. package/dist/web/assets/diff-viewer-9-XjLIwa.js +4 -0
  42. package/dist/web/assets/{docx-preview-DYBkiUaE.js → docx-preview-CXuk-emm.js} +1 -1
  43. package/dist/web/assets/{edge-rWOlCmXT.js → edge-E8QLt7oi.js} +1 -1
  44. package/dist/web/assets/{edit-diff-preview-COtmo54G.js → edit-diff-preview-BGGGecVw.js} +1 -1
  45. package/dist/web/assets/{editor-language-service-DxkZ51E5.js → editor-language-service-D0DuEOs_.js} +1 -1
  46. package/dist/web/assets/{elixir-E7Y82okW.js → elixir-DPb_-72P.js} +1 -1
  47. package/dist/web/assets/{elm-DTPGbc-w.js → elm-BMzJY5b0.js} +1 -1
  48. package/dist/web/assets/{erb-DHqLHrE6.js → erb-AABQNtMK.js} +1 -1
  49. package/dist/web/assets/{erlang-Byg0nNiV.js → erlang-CEIKOkfP.js} +1 -1
  50. package/dist/web/assets/{esm-D_DmOM7n.js → esm-B9RVMpwV.js} +1 -1
  51. package/dist/web/assets/explorer-body-VdCBqcZu.js +2 -0
  52. package/dist/web/assets/explorer-window-content-BIsbl7Th.js +1 -0
  53. package/dist/web/assets/extension-manager-section-HkY7geS5.js +1 -0
  54. package/dist/web/assets/{extension-webview-DI4VL2tJ.js → extension-webview-DZG8YHX9.js} +1 -1
  55. package/dist/web/assets/file-icons-BXdvggK2.js +1 -0
  56. package/dist/web/assets/file-icons.generated-BtBErEwb.css +1 -0
  57. package/dist/web/assets/file-store-ojgMXgAw.js +1 -0
  58. package/dist/web/assets/files-settings-section-qnRtkX05.js +1 -0
  59. package/dist/web/assets/{format-file-meta-DOpzJJhS.js → format-file-meta-C77h04cZ.js} +1 -1
  60. package/dist/web/assets/{fortran-fixed-form-CY1n0Xf6.js → fortran-fixed-form-CrXvLHyi.js} +1 -1
  61. package/dist/web/assets/{fsharp-_vEDSCJz.js → fsharp-DCI4qAz_.js} +1 -1
  62. package/dist/web/assets/{gdresource-B6XT0wAC.js → gdresource-Vb2kO1MG.js} +1 -1
  63. package/dist/web/assets/{general-settings-section-BcxwiZ0X.js → general-settings-section-BAFSZmCE.js} +1 -1
  64. package/dist/web/assets/{git-commit-Wk9ovq59.js → git-commit-BMI_OWn-.js} +1 -1
  65. package/dist/web/assets/git-log-panel-2sGpfEla.js +1 -0
  66. package/dist/web/assets/{git-rebase-DSarGPvK.js → git-rebase-D-d_2iqZ.js} +1 -1
  67. package/dist/web/assets/{git-repo-store-Dy69YCHN.js → git-repo-store-88Z8v-pF.js} +1 -1
  68. package/dist/web/assets/gitGraph-HDMCJU4V-C6qRruHI.js +1 -0
  69. package/dist/web/assets/{glide-data-grid-BvgAqSUr.js → glide-data-grid-f0hyITiF.js} +7 -7
  70. package/dist/web/assets/{glimmer-js-CkYI35_P.js → glimmer-js-BmNNiR0Z.js} +1 -1
  71. package/dist/web/assets/{glimmer-ts-BqmIZcds.js → glimmer-ts-DQE2Ufha.js} +1 -1
  72. package/dist/web/assets/{glsl-Be-yBCF5.js → glsl-BcIDsxRJ.js} +1 -1
  73. package/dist/web/assets/{graphql-a5DrENHY.js → graphql-DGKSLmGH.js} +1 -1
  74. package/dist/web/assets/group-chat-tab-Ck6sk7yY.js +1 -0
  75. package/dist/web/assets/{hack-BLAg20aD.js → hack-YiC8bEIb.js} +1 -1
  76. package/dist/web/assets/{haml-Dj6bGOQH.js → haml-DjblxAsz.js} +1 -1
  77. package/dist/web/assets/{handlebars-dmEa36Oh.js → handlebars-BQepOXaU.js} +1 -1
  78. package/dist/web/assets/{html-yacZYzSE.js → html-Cayj_2GP.js} +1 -1
  79. package/dist/web/assets/{html-derivative-lLi3-RNT.js → html-derivative-Weq79bL6.js} +1 -1
  80. package/dist/web/assets/{http-1KaxcE4e.js → http-BeLfdGdz.js} +1 -1
  81. package/dist/web/assets/{hurl-ST-dEEZR.js → hurl-D9rypCLK.js} +1 -1
  82. package/dist/web/assets/{hxml-CpDtuq__.js → hxml-clG8mmSH.js} +1 -1
  83. package/dist/web/assets/{image-preview-CJVxL0uH.js → image-preview-CzCc4_Do.js} +1 -1
  84. package/dist/web/assets/image-preview-geometry-9lgeLYB3.js +1 -0
  85. package/dist/web/assets/index-BH99TIE0.css +1 -0
  86. package/dist/web/assets/index-CEZVxM4G.js +52 -0
  87. package/dist/web/assets/info-3K5VOQVL-BOSpdwlz.js +1 -0
  88. package/dist/web/assets/{jinja-Cjw-evAn.js → jinja-BShBWfs5.js} +1 -1
  89. package/dist/web/assets/{jira-watcher-section-DIC1yIV3.js → jira-watcher-section-CeLmhvu1.js} +1 -1
  90. package/dist/web/assets/{jison-DfATMYoY.js → jison-dN2Nf_Dr.js} +1 -1
  91. package/dist/web/assets/{julia-DDCaxiqT.js → julia-5U0vR-uJ.js} +1 -1
  92. package/dist/web/assets/{just-CJL529u6.js → just-BMppVRy6.js} +1 -1
  93. package/dist/web/assets/keybindings-store-C_3ChOEf.js +1 -0
  94. package/dist/web/assets/{keyboard-shortcuts-section-BW03P3AF.js → keyboard-shortcuts-section-PVz6kuh2.js} +1 -1
  95. package/dist/web/assets/{latex-Zc4EpLpW.js → latex-DSSOKjis.js} +1 -1
  96. package/dist/web/assets/{liquid-B_6KMNYS.js → liquid-C24dKoyI.js} +1 -1
  97. package/dist/web/assets/{lua-BtS2idK7.js → lua-DNOsnyhn.js} +1 -1
  98. package/dist/web/assets/{markdown-renderer-CvL1pWeK.js → markdown-renderer-C140Ijk0.js} +3 -3
  99. package/dist/web/assets/markdown-renderer-Dz7-DYUg.js +1 -0
  100. package/dist/web/assets/{marko-Wk6LBnck.js → marko-26MHO_Q9.js} +1 -1
  101. package/dist/web/assets/{mdc-cRaXBrzL.js → mdc-Dhw9mGrC.js} +1 -1
  102. package/dist/web/assets/{media-url-DL8OCGGg.js → media-url-yfqHpPz0.js} +1 -1
  103. package/dist/web/assets/{mobile-bottom-sheet-CoUauvLF.js → mobile-bottom-sheet-C3TniEP-.js} +1 -1
  104. package/dist/web/assets/mobile-explorer-sheet-CUG_owdf.js +1 -0
  105. package/dist/web/assets/{nextflow-Bos2wvDV.js → nextflow-xH4oJTex.js} +1 -1
  106. package/dist/web/assets/{nginx-DMlOwzdr.js → nginx-CMz4w0M8.js} +1 -1
  107. package/dist/web/assets/{nim-D2dZQA88.js → nim-D8FnIYsx.js} +1 -1
  108. package/dist/web/assets/notification-store-6vib1ISy.js +1 -0
  109. package/dist/web/assets/{notifications-settings-section-DPUROMw-.js → notifications-settings-section-DqlPDfNX.js} +1 -1
  110. package/dist/web/assets/{number-overlay-editor-DZ2i_Bnb.js → number-overlay-editor-CRGwULhR.js} +1 -1
  111. package/dist/web/assets/{overview-panel-R146OIom.js → overview-panel-Di-3aV9p.js} +1 -1
  112. package/dist/web/assets/packet-RMMSAZCW-BGIE1QdU.js +1 -0
  113. package/dist/web/assets/panel-store-CboGJAwh.js +1 -0
  114. package/dist/web/assets/{pdf-preview-BWUPGLp6.js → pdf-preview-CmBI6E7d.js} +1 -1
  115. package/dist/web/assets/{perl-C5-Z6fPn.js → perl-D9iNWYwb.js} +1 -1
  116. package/dist/web/assets/{php-BXNNhkMH.js → php-Bw3Qo0Zv.js} +1 -1
  117. package/dist/web/assets/pie-UPGHQEXC-Dg-QTbXX.js +1 -0
  118. package/dist/web/assets/{postgres-viewer-CjOvaruz.js → postgres-viewer-8ZAqEALv.js} +3 -3
  119. package/dist/web/assets/{ppmbot-settings-section-DrvWh8l8.js → ppmbot-settings-section-Cji-Mil-.js} +1 -1
  120. package/dist/web/assets/problems-panel-a6_hrWvl.js +1 -0
  121. package/dist/web/assets/{process-table-BRMS1MrX.js → process-table-CiIqlOIK.js} +1 -1
  122. package/dist/web/assets/project-framework-store-B70Q3dNM.js +1 -0
  123. package/dist/web/assets/project-store-B87hLRSk.js +1 -0
  124. package/dist/web/assets/{proxy-settings-section-Bv0Ny-Yy.js → proxy-settings-section-BjI4IFgp.js} +1 -1
  125. package/dist/web/assets/{pug-C1zf1yWy.js → pug-fT5JC6Vm.js} +1 -1
  126. package/dist/web/assets/{qml-OW58jGpD.js → qml-P_wEDB1w.js} +1 -1
  127. package/dist/web/assets/{query-audit-section-BcHJZcVC.js → query-audit-section-By6qyqdB.js} +1 -1
  128. package/dist/web/assets/radar-KQ55EAFF-DZ6IVu2s.js +1 -0
  129. package/dist/web/assets/{razor-DzjSaobM.js → razor-Drrt2_Ph.js} +1 -1
  130. package/dist/web/assets/remote-desktop-clipboard-notice-eXYvwgx7.js +1 -0
  131. package/dist/web/assets/remote-desktop-mobile-sheet-Doh-fci-.js +2 -0
  132. package/dist/web/assets/remote-desktop-mobile-view-Dt8Akc3p.js +1 -0
  133. package/dist/web/assets/{remote-desktop-readiness-gate-BTzss2wX.js → remote-desktop-readiness-gate-t83fqbID.js} +1 -1
  134. package/dist/web/assets/remote-desktop-window-content-CguhZMmx.js +1 -0
  135. package/dist/web/assets/{rst-RfuihOUW.js → rst-Dr2mW4-h.js} +1 -1
  136. package/dist/web/assets/{ruby-CNO3pli1.js → ruby-C6EpUsTY.js} +1 -1
  137. package/dist/web/assets/{run-in-terminal-Cb_hVU8x.js → run-in-terminal-CdefEe_R.js} +1 -1
  138. package/dist/web/assets/{sas-DZY5BtXx.js → sas-D8ZEeP6v.js} +1 -1
  139. package/dist/web/assets/{schedules-settings-section-DO8xAOVj.js → schedules-settings-section-BVkpW5ms.js} +1 -1
  140. package/dist/web/assets/{scroll-area-LtNV8g5o.js → scroll-area-BzeiOd-B.js} +1 -1
  141. package/dist/web/assets/{scss--4g-REcN.js → scss-ITL7jQ1f.js} +1 -1
  142. package/dist/web/assets/{send-to-chat-Cnpru1M0.js → send-to-chat-F207yH3u.js} +1 -1
  143. package/dist/web/assets/{separator-Cds1yxy8.js → separator-TRMsJUYe.js} +1 -1
  144. package/dist/web/assets/settings-body-CoIxYAh6.js +2 -0
  145. package/dist/web/assets/settings-store-krC6bc79.js +2 -0
  146. package/dist/web/assets/settings-tab-7DKVUTbM.js +1 -0
  147. package/dist/web/assets/settings-window-content-3_39TeX-.js +1 -0
  148. package/dist/web/assets/{shaderlab-Cu4sBiVn.js → shaderlab-mW-IIlhk.js} +1 -1
  149. package/dist/web/assets/{shellsession-DWzJfEv7.js → shellsession-DhNl5STt.js} +1 -1
  150. package/dist/web/assets/{soy-BnqE-5Ff.js → soy-SdY0Qjtr.js} +1 -1
  151. package/dist/web/assets/{sparql-Ctg__NhZ.js → sparql-ftqZo2i-.js} +1 -1
  152. package/dist/web/assets/{sql-query-editor-D9k19T_M.js → sql-query-editor-CQB7Yp7U.js} +1 -1
  153. package/dist/web/assets/{sqlite-viewer-DoV9hnWJ.js → sqlite-viewer-Bd7rjr1D.js} +1 -1
  154. package/dist/web/assets/{stata-Qk2h66XW.js → stata-Bj7Yjb4b.js} +1 -1
  155. package/dist/web/assets/{surrealql-8QEX7EfH.js → surrealql-CLhYGAfB.js} +1 -1
  156. package/dist/web/assets/{svelte-D_mubC5-.js → svelte-DTAlRHhK.js} +1 -1
  157. package/dist/web/assets/system-monitor-body-DsRXeMyU.js +2 -0
  158. package/dist/web/assets/system-monitor-tab-DdSZgux3.js +1 -0
  159. package/dist/web/assets/{system-monitor-window-content-qXLcicFM.js → system-monitor-window-content-ClPo4-El.js} +1 -1
  160. package/dist/web/assets/{tab-host-window-content-7fPZNEni.js → tab-host-window-content-d2TAD4PU.js} +1 -1
  161. package/dist/web/assets/{tab-store-DGJGnbwv.js → tab-store-OJa1GPCq.js} +1 -1
  162. package/dist/web/assets/team-member-sheet-7d2Qp-ie.js +2 -0
  163. package/dist/web/assets/{team-member-window-content-BgvJFypM.js → team-member-window-content-Bctg2gmg.js} +1 -1
  164. package/dist/web/assets/{templ-C1jV0fsO.js → templ-BMfhACxb.js} +1 -1
  165. package/dist/web/assets/{terminal-tab-Cs0sGljx.js → terminal-tab-0HQic25V.js} +3 -3
  166. package/dist/web/assets/{tex-D_StFXy_.js → tex-BcssM-QA.js} +1 -1
  167. package/dist/web/assets/tool-cards-CmLLRACd.js +9 -0
  168. package/dist/web/assets/treemap-KZPCXAKY-CE30wCXa.js +1 -0
  169. package/dist/web/assets/{ts-tags-B5m47rEm.js → ts-tags-CrR5IYI8.js} +1 -1
  170. package/dist/web/assets/{twig-C_br6GIl.js → twig-DchfUmyI.js} +1 -1
  171. package/dist/web/assets/{use-blob-url-C-SGi_Hb.js → use-blob-url-CPtCcY3i.js} +1 -1
  172. package/dist/web/assets/{use-inline-blame-B4trxGcR.js → use-inline-blame-sDMjcz1-.js} +3 -3
  173. package/dist/web/assets/{use-lsp-CV0vzILO.js → use-lsp-CBgID-EU.js} +1 -1
  174. package/dist/web/assets/{use-monaco-theme-DBqbWjWX.js → use-monaco-theme-gvhJ_jZh.js} +1 -1
  175. package/dist/web/assets/{use-open-team-member-DENsjp0s.js → use-open-team-member-C3mrUzIC.js} +1 -1
  176. package/dist/web/assets/{use-websocket-LgXiX1qN.js → use-websocket-C9wlRliB.js} +1 -1
  177. package/dist/web/assets/{vendor-mermaid-Cbig5zA6.js → vendor-mermaid-BitiXJlL.js} +1 -1
  178. package/dist/web/assets/{vendor-ui-BBdkypKW.js → vendor-ui-DmZ-Mb-H.js} +1 -1
  179. package/dist/web/assets/video-preview-CSDK5j6H.js +1 -0
  180. package/dist/web/assets/{vue-DQwCnLdr.js → vue-1EL6Pw1h.js} +1 -1
  181. package/dist/web/assets/{vue-html-T_EoGpPJ.js → vue-html-BPQNwPC6.js} +1 -1
  182. package/dist/web/assets/{vue-vine-DmxLqX50.js → vue-vine-Bb_dsWLt.js} +1 -1
  183. package/dist/web/assets/{window-pip-registry-3l4hoxuD.js → window-pip-registry-yD6esSju.js} +1 -1
  184. package/dist/web/assets/ws-auth-CEYVQ8NH.js +1 -0
  185. package/dist/web/assets/{xml-Bs6Bw8is.js → xml-dxkLNA0K.js} +1 -1
  186. package/dist/web/assets/{xsl-f5ZNhRCc.js → xsl-Bw2adwrl.js} +1 -1
  187. package/dist/web/index.html +27 -26
  188. package/dist/web/sw.js +1 -1
  189. package/docs/architecture/ai-chat-and-providers.md +9 -0
  190. package/docs/architecture/plugins-and-tracing.md +285 -0
  191. package/docs/lessons-learned.md +31 -0
  192. package/docs/system-architecture.md +1 -0
  193. package/package.json +2 -1
  194. package/packages/ext-git-graph/src/compare-diff-base.test.ts +173 -0
  195. package/packages/ext-git-graph/src/compare-view.ts +22 -3
  196. package/packages/ext-git-graph/src/extension.ts +6 -0
  197. package/packages/ext-git-graph/src/types.ts +19 -0
  198. package/packages/ext-git-graph/src/webview-html.test.ts +159 -1
  199. package/packages/ext-git-graph/src/webview-html.ts +344 -26
  200. package/scripts/gen-file-icons.ts +493 -242
  201. package/src/providers/claude-agent-sdk.ts +42 -1
  202. package/src/providers/codex-app-server/codex-history.ts +77 -23
  203. package/src/server/index.ts +42 -7
  204. package/src/server/routes/chat.ts +15 -11
  205. package/src/server/routes/git.ts +83 -3
  206. package/src/server/routes/remote-desktop.ts +7 -2
  207. package/src/server/ws/global.ts +1 -1
  208. package/src/server/ws/remote-desktop.ts +12 -5
  209. package/src/services/binary-content.ts +25 -0
  210. package/src/services/chat-search.service.ts +1 -1
  211. package/src/services/chat.service.ts +9 -0
  212. package/src/services/edge-forwarder.ts +191 -191
  213. package/src/services/event-loop-lag.ts +208 -0
  214. package/src/services/file-lines.ts +114 -0
  215. package/src/services/file-watcher/recreated-dir-poller.ts +108 -6
  216. package/src/services/file-watcher/watch-tree.ts +131 -10
  217. package/src/services/file-watcher.service.ts +73 -23
  218. package/src/services/git-branch-diff/branch-diff-parse.ts +151 -0
  219. package/src/services/git-branch-diff/branch-diff.service.ts +79 -0
  220. package/src/services/git-hunks/git-hunks.service.ts +26 -11
  221. package/src/services/git-hunks/unified-diff.ts +15 -1
  222. package/src/services/git.service.ts +74 -24
  223. package/src/services/jsonl-transcript-parser.ts +138 -6
  224. package/src/services/log-rotate.ts +142 -0
  225. package/src/services/media-transcode/ffmpeg-capabilities.ts +72 -2
  226. package/src/services/remote-desktop/remote-desktop-audio.ts +193 -0
  227. package/src/services/remote-desktop/remote-desktop-capture-input.ts +87 -14
  228. package/src/services/remote-desktop/remote-desktop-capture.ts +40 -7
  229. package/src/services/remote-desktop/remote-desktop-clipboard.ts +166 -0
  230. package/src/services/remote-desktop/remote-desktop-displays.ts +77 -1
  231. package/src/services/remote-desktop/remote-desktop-encoder-args.ts +25 -6
  232. package/src/services/remote-desktop/remote-desktop-evdev-key-map.ts +69 -0
  233. package/src/services/remote-desktop/remote-desktop-input-linux.ts +253 -0
  234. package/src/services/remote-desktop/remote-desktop-input-uinput.ts +242 -0
  235. package/src/services/remote-desktop/remote-desktop-input.ts +40 -8
  236. package/src/services/remote-desktop/remote-desktop-linux-session.ts +146 -0
  237. package/src/services/remote-desktop/remote-desktop-ogg-opus.ts +144 -0
  238. package/src/services/remote-desktop/remote-desktop-privacy.ts +163 -0
  239. package/src/services/remote-desktop/remote-desktop-quality.ts +138 -0
  240. package/src/services/remote-desktop/remote-desktop-requirements.ts +158 -5
  241. package/src/services/remote-desktop/remote-desktop-resolution.ts +302 -0
  242. package/src/services/remote-desktop/remote-desktop-session.ts +523 -21
  243. package/src/services/remote-desktop/remote-desktop-x11.ts +250 -0
  244. package/src/services/supervisor.ts +47 -4
  245. package/src/services/windows-process-tree.ts +351 -351
  246. package/src/shared/codex-daily-guard.ts +12 -5
  247. package/src/shared/remote-desktop-custom-quality.ts +117 -0
  248. package/src/shared/remote-desktop-quality.ts +127 -0
  249. package/src/types/chat.ts +4 -0
  250. package/src/types/git.ts +52 -0
  251. package/src/web/components/branch-review/branch-review-tab.tsx +360 -0
  252. package/src/web/components/branch-review/branch-review-tree-row.tsx +138 -0
  253. package/src/web/components/chat/attachment-chips.tsx +30 -6
  254. package/src/web/components/chat/chat-tab.tsx +12 -1
  255. package/src/web/components/chat/message-events.tsx +273 -0
  256. package/src/web/components/chat/message-list.tsx +107 -861
  257. package/src/web/components/chat/message-markdown.tsx +34 -0
  258. package/src/web/components/chat/message-media.tsx +174 -0
  259. package/src/web/components/chat/message-user-bubble.tsx +399 -0
  260. package/src/web/components/chat/provider-selector.tsx +30 -22
  261. package/src/web/components/chat/session-history-list.tsx +2 -2
  262. package/src/web/components/chat/session-list-panel.tsx +3 -2
  263. package/src/web/components/editor/binary-diff-view.tsx +212 -0
  264. package/src/web/components/editor/diff-viewer.tsx +76 -3
  265. package/src/web/components/explorer/file-tree.tsx +235 -134
  266. package/src/web/components/explorer/flatten-visible-tree.ts +35 -40
  267. package/src/web/components/explorer/tree-node.tsx +69 -69
  268. package/src/web/components/explorer/use-tree-row-dnd.ts +3 -4
  269. package/src/web/components/extensions/extension-tree-view.tsx +4 -11
  270. package/src/web/components/git/git-status-panel.tsx +25 -0
  271. package/src/web/components/layout/command-palette.tsx +2 -18
  272. package/src/web/components/layout/draggable-tab.tsx +4 -2
  273. package/src/web/components/layout/nav-section-rail.tsx +12 -3
  274. package/src/web/components/layout/status-bar.tsx +10 -6
  275. package/src/web/components/layout/tab-content.tsx +5 -0
  276. package/src/web/components/layout/tab-pool.tsx +1 -0
  277. package/src/web/components/layout/upgrade-button.tsx +5 -1
  278. package/src/web/components/remote-desktop/remote-desktop-clipboard-client.ts +67 -0
  279. package/src/web/components/remote-desktop/remote-desktop-clipboard-notice.tsx +127 -0
  280. package/src/web/components/remote-desktop/remote-desktop-codec-labels.ts +28 -0
  281. package/src/web/components/remote-desktop/remote-desktop-custom-quality-dialog.tsx +144 -0
  282. package/src/web/components/remote-desktop/remote-desktop-mobile-key-bar.tsx +13 -2
  283. package/src/web/components/remote-desktop/remote-desktop-mobile-settings.tsx +232 -0
  284. package/src/web/components/remote-desktop/remote-desktop-mobile-toolbar.tsx +21 -8
  285. package/src/web/components/remote-desktop/remote-desktop-mobile-view.tsx +82 -3
  286. package/src/web/components/remote-desktop/remote-desktop-recording.ts +76 -0
  287. package/src/web/components/remote-desktop/remote-desktop-resolution-list.ts +100 -0
  288. package/src/web/components/remote-desktop/remote-desktop-toolbar.tsx +497 -0
  289. package/src/web/components/remote-desktop/remote-desktop-view-style.ts +145 -0
  290. package/src/web/components/remote-desktop/remote-desktop-window-content.tsx +126 -35
  291. package/src/web/components/remote-desktop/use-h264-canvas-decoder.ts +11 -0
  292. package/src/web/components/remote-desktop/use-opus-audio-player.ts +148 -0
  293. package/src/web/components/remote-desktop/use-remote-desktop-connection.ts +284 -1
  294. package/src/web/components/remote-desktop/use-remote-desktop-readiness.ts +75 -1
  295. package/src/web/components/remote-desktop/use-remote-desktop-recorder.ts +103 -0
  296. package/src/web/components/remote-desktop/use-remote-desktop-virtual-keyboard.ts +19 -2
  297. package/src/web/components/remote-desktop/use-remote-input-capture.ts +39 -3
  298. package/src/web/components/settings/accounts/account-card.tsx +2 -2
  299. package/src/web/components/settings/accounts/codex-accounts-section.tsx +4 -4
  300. package/src/web/components/settings/extension-manager-section.tsx +8 -1
  301. package/src/web/components/settings/theme-picker.tsx +2 -1
  302. package/src/web/components/ui/tooltip.tsx +15 -2
  303. package/src/web/lib/branch-review-state.ts +175 -0
  304. package/src/web/lib/extension-icons.ts +70 -0
  305. package/src/web/lib/file-icon-name.ts +62 -0
  306. package/src/web/lib/file-icons.generated.ts +3287 -25
  307. package/src/web/lib/file-icons.tsx +71 -73
  308. package/src/web/lib/flatten-expansions.ts +18 -5
  309. package/src/web/lib/message-ordinals.ts +23 -0
  310. package/src/web/lib/provider-logos.tsx +143 -0
  311. package/src/web/lib/tab-type-icons.ts +25 -0
  312. package/src/web/stores/file-store.ts +73 -35
  313. package/src/web/stores/panel-utils.ts +5 -0
  314. package/src/web/stores/project-framework-store.ts +82 -0
  315. package/src/web/stores/project-store.ts +7 -1
  316. package/src/web/stores/settings-store.ts +128 -0
  317. package/src/web/stores/tab-store.ts +1 -0
  318. package/src/web/stores/window-panel-persistence.ts +1 -0
  319. package/src/web/styles/file-icons.generated.css +3282 -234
  320. package/src/web/styles/globals.css +26 -0
  321. package/dist/web/assets/accounts-settings-section-BuxD9zH3.js +0 -1
  322. package/dist/web/assets/ai-settings-section-Dd9tOUp0.js +0 -1
  323. package/dist/web/assets/ai-settings-section-FrU2X8Fu.js +0 -1
  324. package/dist/web/assets/api-client-BUCo1lms.js +0 -1
  325. package/dist/web/assets/architecture-PBZL5I3N-5K0wEkAn.js +0 -1
  326. package/dist/web/assets/chat-tab-Cr6_KSGO.js +0 -15
  327. package/dist/web/assets/code-editor-DfmlGamv.js +0 -7
  328. package/dist/web/assets/context-menu-DOODKZdF.js +0 -1
  329. package/dist/web/assets/diff-viewer-BpNj7pN9.js +0 -4
  330. package/dist/web/assets/explorer-body-D-5z464e.js +0 -2
  331. package/dist/web/assets/explorer-window-content-7-1wuRul.js +0 -1
  332. package/dist/web/assets/extension-manager-section-BhwB6nqr.js +0 -1
  333. package/dist/web/assets/file-icons-EzPL0q-k.js +0 -1
  334. package/dist/web/assets/file-icons.generated-CfaJuvZu.css +0 -1
  335. package/dist/web/assets/file-store-DMABxOkV.js +0 -1
  336. package/dist/web/assets/files-settings-section-CZzABuKz.js +0 -1
  337. package/dist/web/assets/git-log-panel-CRN4JVOx.js +0 -1
  338. package/dist/web/assets/gitGraph-HDMCJU4V-DkVT2MAM.js +0 -1
  339. package/dist/web/assets/group-chat-tab-DFa5mAx5.js +0 -1
  340. package/dist/web/assets/index-D7DbXD3G.css +0 -1
  341. package/dist/web/assets/index-ZtfxZOyb.js +0 -52
  342. package/dist/web/assets/info-3K5VOQVL-BBsmKGzA.js +0 -1
  343. package/dist/web/assets/keybindings-store-tVfhPANS.js +0 -1
  344. package/dist/web/assets/markdown-renderer-sJNNVhlS.js +0 -1
  345. package/dist/web/assets/mobile-explorer-sheet-CZ0HZ2E_.js +0 -1
  346. package/dist/web/assets/notification-store-BZbsPnW0.js +0 -1
  347. package/dist/web/assets/packet-RMMSAZCW-DwmYPOlx.js +0 -1
  348. package/dist/web/assets/panel-store-BVLBRn6M.js +0 -1
  349. package/dist/web/assets/pie-UPGHQEXC-D0oogIFi.js +0 -1
  350. package/dist/web/assets/problems-panel-B7BWVhdy.js +0 -1
  351. package/dist/web/assets/project-store-BhMbVln3.js +0 -1
  352. package/dist/web/assets/radar-KQ55EAFF-CQIJOQGa.js +0 -1
  353. package/dist/web/assets/remote-desktop-mobile-sheet-ByjaeZKX.js +0 -2
  354. package/dist/web/assets/remote-desktop-mobile-view-D13mtr9F.js +0 -1
  355. package/dist/web/assets/remote-desktop-window-content-CbqTCaC6.js +0 -1
  356. package/dist/web/assets/settings-body-Rnu-FcX-.js +0 -2
  357. package/dist/web/assets/settings-store-DZPgPtEA.js +0 -2
  358. package/dist/web/assets/settings-tab-C6PHxs0Z.js +0 -1
  359. package/dist/web/assets/settings-window-content-CQ4gT2qj.js +0 -1
  360. package/dist/web/assets/system-monitor-body-2vQ1kMxE.js +0 -2
  361. package/dist/web/assets/system-monitor-tab-krAcvwF7.js +0 -1
  362. package/dist/web/assets/team-member-sheet-2FnRmk1a.js +0 -2
  363. package/dist/web/assets/tool-cards-DU_S2o51.js +0 -9
  364. package/dist/web/assets/treemap-KZPCXAKY-BhEtjljr.js +0 -1
  365. package/dist/web/assets/use-remote-desktop-display-choice-BK_f787P.js +0 -1
  366. package/dist/web/assets/video-preview-BDNwumbW.js +0 -1
  367. package/dist/web/assets/ws-auth-DEAJiGCR.js +0 -1
  368. package/packages/vscode-compat/node_modules/.bin/tsc.bunx +0 -0
  369. package/packages/vscode-compat/node_modules/.bin/tsc.exe +0 -0
  370. package/packages/vscode-compat/node_modules/.bin/tsserver.bunx +0 -0
  371. package/packages/vscode-compat/node_modules/.bin/tsserver.exe +0 -0
  372. /package/dist/web/assets/{abap-tkptwpsK.js → abap-IN2yINdN.js} +0 -0
  373. /package/dist/web/assets/{actionscript-3-Di9TMGwg.js → actionscript-3-C_t772eR.js} +0 -0
  374. /package/dist/web/assets/{ada-CB9F079D.js → ada-DPme3emm.js} +0 -0
  375. /package/dist/web/assets/{andromeeda-Dcl8jpb7.js → andromeeda-DSV4i4mZ.js} +0 -0
  376. /package/dist/web/assets/{apache-D0Nk0qsH.js → apache-CWr8s8I8.js} +0 -0
  377. /package/dist/web/assets/{apex-mQIoWncD.js → apex-Z20JnDF5.js} +0 -0
  378. /package/dist/web/assets/{applescript-C6ljbcsI.js → applescript-BKNPu3ga.js} +0 -0
  379. /package/dist/web/assets/{apply-theme-BwIMNXyX.js → apply-theme-CbR31K6I.js} +0 -0
  380. /package/dist/web/assets/{ara-WFqRPGPe.js → ara-hWdY3O96.js} +0 -0
  381. /package/dist/web/assets/{asciidoc-bNd8w4nf.js → asciidoc-eynhq496.js} +0 -0
  382. /package/dist/web/assets/{asm-BQ1_F580.js → asm-Bu02Kq4P.js} +0 -0
  383. /package/dist/web/assets/{aurora-x-Ciqs_Dbu.js → aurora-x-BHBGXbIZ.js} +0 -0
  384. /package/dist/web/assets/{awk-GCR-6KZV.js → awk-B4ojezyv.js} +0 -0
  385. /package/dist/web/assets/{ayu-dark-DxJXuj99.js → ayu-dark-D0GQzFi9.js} +0 -0
  386. /package/dist/web/assets/{ayu-light-jvSyJWDV.js → ayu-light-BVYb5Yn8.js} +0 -0
  387. /package/dist/web/assets/{ayu-mirage-Cg3BPO6H.js → ayu-mirage-BGFW6oNb.js} +0 -0
  388. /package/dist/web/assets/{ballerina-BPz4CrX6.js → ballerina-B6Og3IKT.js} +0 -0
  389. /package/dist/web/assets/{bat-CSTs2hIG.js → bat-D8YFILfx.js} +0 -0
  390. /package/dist/web/assets/{beancount-DMateAZX.js → beancount-BjlbBBuX.js} +0 -0
  391. /package/dist/web/assets/{berry-9lXg0GRM.js → berry-Cz1ygeoj.js} +0 -0
  392. /package/dist/web/assets/{bibtex-DIbqmvFg.js → bibtex-CVkJceJh.js} +0 -0
  393. /package/dist/web/assets/{bicep-02WGsoJ8.js → bicep-DrhYI5GX.js} +0 -0
  394. /package/dist/web/assets/{bird2-BY0tbu3k.js → bird2-BV-KJtmc.js} +0 -0
  395. /package/dist/web/assets/{c-jMBX_9Je.js → c-CuLlvxbG.js} +0 -0
  396. /package/dist/web/assets/{c3-B8JVbNjW.js → c3-CI7-1CJ0.js} +0 -0
  397. /package/dist/web/assets/{cadence-DUIf1tvL.js → cadence-DjxhNP3Q.js} +0 -0
  398. /package/dist/web/assets/{can-open-in-ppm-DGEc0s4P.js → can-open-in-ppm-cv5--yHX.js} +0 -0
  399. /package/dist/web/assets/{catppuccin-frappe-FhUCVxex.js → catppuccin-frappe-CEozpJRh.js} +0 -0
  400. /package/dist/web/assets/{catppuccin-latte-CzfrtmgL.js → catppuccin-latte-C4sXQFMc.js} +0 -0
  401. /package/dist/web/assets/{catppuccin-macchiato-6xL0lOtj.js → catppuccin-macchiato-Ci-fDhXy.js} +0 -0
  402. /package/dist/web/assets/{catppuccin-mocha-D39-xS3P.js → catppuccin-mocha-CH7YXw8d.js} +0 -0
  403. /package/dist/web/assets/{clarity-D8TeGvoT.js → clarity-BWrJ7UmT.js} +0 -0
  404. /package/dist/web/assets/{clojure-Dx_acSX7.js → clojure-C94fh2hb.js} +0 -0
  405. /package/dist/web/assets/{cmake-CyeYPq8o.js → cmake-CtvCkMsG.js} +0 -0
  406. /package/dist/web/assets/{codeowners-DrTI0lmI.js → codeowners-CJnubqzH.js} +0 -0
  407. /package/dist/web/assets/{codeql-CPkFxVW-.js → codeql-BOoP5HY2.js} +0 -0
  408. /package/dist/web/assets/{common-lisp-B0k-3LTj.js → common-lisp-B9nlMFJd.js} +0 -0
  409. /package/dist/web/assets/{coq-uygpo7to.js → coq-CgzIQiSH.js} +0 -0
  410. /package/dist/web/assets/{csharp-DKUYGfSp.js → csharp-4xAIx3jw.js} +0 -0
  411. /package/dist/web/assets/{css-DoOUp7v4.js → css-D4YoLYGn.js} +0 -0
  412. /package/dist/web/assets/{csv-B3YE13gi.js → csv-C2v-ZakW.js} +0 -0
  413. /package/dist/web/assets/{csv-parser-DXePqmXe.js → csv-parser-_oDBUkwQ.js} +0 -0
  414. /package/dist/web/assets/{cue-DViO2wvn.js → cue-Bbznh_an.js} +0 -0
  415. /package/dist/web/assets/{cypher-4BMCIW5N.js → cypher-BKhVEARF.js} +0 -0
  416. /package/dist/web/assets/{d-BT_sTHas.js → d-D6IhWopl.js} +0 -0
  417. /package/dist/web/assets/{dark-plus-DVVXu-1N.js → dark-plus-xAWu790O.js} +0 -0
  418. /package/dist/web/assets/{dart-DHz6f6_6.js → dart-Bj6S9O1j.js} +0 -0
  419. /package/dist/web/assets/{data-grid-types-OgUxMLdQ.js → data-grid-types-C5bthITf.js} +0 -0
  420. /package/dist/web/assets/{dax-ChYCjweK.js → dax-CF2zvaqq.js} +0 -0
  421. /package/dist/web/assets/{desktop-D6Lt4p04.js → desktop-CnmyxMKE.js} +0 -0
  422. /package/dist/web/assets/{diff-D8TDe4hP.js → diff-Qi8WuJsI.js} +0 -0
  423. /package/dist/web/assets/{dist-DOTlFQJA.js → dist-Bjseolz4.js} +0 -0
  424. /package/dist/web/assets/{dist-CrBOCtCW.js → dist-Czq7BUMy.js} +0 -0
  425. /package/dist/web/assets/{docker-Bsp0YbPx.js → docker-vLbbNP5d.js} +0 -0
  426. /package/dist/web/assets/{dotenv-B_7giSY_.js → dotenv-DJMvvNzn.js} +0 -0
  427. /package/dist/web/assets/{dracula-TrQL2iB5.js → dracula-CtAh2rhB.js} +0 -0
  428. /package/dist/web/assets/{dracula-soft-n2XOlgh-.js → dracula-soft-CXtuAAf6.js} +0 -0
  429. /package/dist/web/assets/{dream-maker-CdIEdhpT.js → dream-maker-D5YQyK49.js} +0 -0
  430. /package/dist/web/assets/{editor-font-BDrdiGf1.js → editor-font-ClTC9gaD.js} +0 -0
  431. /package/dist/web/assets/{emacs-lisp-CSbixs6u.js → emacs-lisp-CGTjbiqF.js} +0 -0
  432. /package/dist/web/assets/{everforest-dark-BuZahZYp.js → everforest-dark-D59p7vAQ.js} +0 -0
  433. /package/dist/web/assets/{everforest-light-DPH53z5H.js → everforest-light-B3Qtud3V.js} +0 -0
  434. /package/dist/web/assets/{fennel-B1-K_hlJ.js → fennel-BCyHNUwf.js} +0 -0
  435. /package/dist/web/assets/{fish-Cy12Dbua.js → fish-DDDlLV2G.js} +0 -0
  436. /package/dist/web/assets/{fluent-B_82ys8E.js → fluent-By54R9tl.js} +0 -0
  437. /package/dist/web/assets/{format-bytes-D5sBgIqU.js → format-bytes-D1AQyUCt.js} +0 -0
  438. /package/dist/web/assets/{fortran-free-form-BRQdNzZF.js → fortran-free-form-tP8mRym_.js} +0 -0
  439. /package/dist/web/assets/{gdscript-XBDmLUm9.js → gdscript-nHC2z6Te.js} +0 -0
  440. /package/dist/web/assets/{gdshader-DhVfB3u4.js → gdshader-K-cSmPlW.js} +0 -0
  441. /package/dist/web/assets/{genie-X3K29Y49.js → genie-BAcRhvEe.js} +0 -0
  442. /package/dist/web/assets/{gherkin-DKIx-6cX.js → gherkin-CcifxMLb.js} +0 -0
  443. /package/dist/web/assets/{github-dark-Bf7zdp5s.js → github-dark-67KKlMdB.js} +0 -0
  444. /package/dist/web/assets/{github-dark-default-DqsBBV11.js → github-dark-default-tja8pidR.js} +0 -0
  445. /package/dist/web/assets/{github-dark-dimmed-X2gqRz6w.js → github-dark-dimmed-CtjhYQtx.js} +0 -0
  446. /package/dist/web/assets/{github-dark-high-contrast-Z7tvbGX4.js → github-dark-high-contrast-Bf-LPFgn.js} +0 -0
  447. /package/dist/web/assets/{github-light-BKxt-7zZ.js → github-light-CbJxE7n3.js} +0 -0
  448. /package/dist/web/assets/{github-light-default-B0liF4d4.js → github-light-default-DRQmdHxt.js} +0 -0
  449. /package/dist/web/assets/{github-light-high-contrast-F4encJwr.js → github-light-high-contrast-CJkDgTeM.js} +0 -0
  450. /package/dist/web/assets/{gleam-Pz2bHgBB.js → gleam-D4LCl2ri.js} +0 -0
  451. /package/dist/web/assets/{gn-CgmdNsPU.js → gn-COY8zZmC.js} +0 -0
  452. /package/dist/web/assets/{gnuplot-qLNF5yZ9.js → gnuplot-ROk1VitR.js} +0 -0
  453. /package/dist/web/assets/{go-CSDUNhE7.js → go-H30c3p0C.js} +0 -0
  454. /package/dist/web/assets/{groovy-B3NEnOHF.js → groovy-DBLCaelV.js} +0 -0
  455. /package/dist/web/assets/{gruvbox-dark-hard-DcoftiUX.js → gruvbox-dark-hard-DJy4irps.js} +0 -0
  456. /package/dist/web/assets/{gruvbox-dark-medium-D1wVSuD8.js → gruvbox-dark-medium-Dhfw1QTO.js} +0 -0
  457. /package/dist/web/assets/{gruvbox-dark-soft-DWpunymH.js → gruvbox-dark-soft-BncJU-8w.js} +0 -0
  458. /package/dist/web/assets/{gruvbox-light-hard-rHMvyUdS.js → gruvbox-light-hard-Cq12_YvM.js} +0 -0
  459. /package/dist/web/assets/{gruvbox-light-medium-3O2KiXO7.js → gruvbox-light-medium-DqVja5_v.js} +0 -0
  460. /package/dist/web/assets/{gruvbox-light-soft-lNlXJPwH.js → gruvbox-light-soft-IvwhveGF.js} +0 -0
  461. /package/dist/web/assets/{haskell-aaG3aC0h.js → haskell-DA1JV-MC.js} +0 -0
  462. /package/dist/web/assets/{haxe-CPcHhUDd.js → haxe-V9RTRc5E.js} +0 -0
  463. /package/dist/web/assets/{hcl-CMQNlR_4.js → hcl-hr1lyZ10.js} +0 -0
  464. /package/dist/web/assets/{hjson-DeuklPFj.js → hjson-D3vW3i7X.js} +0 -0
  465. /package/dist/web/assets/{hlsl-BI3hlsaM.js → hlsl-BB85gfJT.js} +0 -0
  466. /package/dist/web/assets/{horizon-C7-gOcjs.js → horizon-DU8OOnj8.js} +0 -0
  467. /package/dist/web/assets/{horizon-bright-Cxt9bRW7.js → horizon-bright-DNMUclW6.js} +0 -0
  468. /package/dist/web/assets/{houston-DbF2G7iD.js → houston-DAiZKf6T.js} +0 -0
  469. /package/dist/web/assets/{hy-DRG6Hs2I.js → hy-C6Zv0LMe.js} +0 -0
  470. /package/dist/web/assets/{image-gallery-CObzTisL.js → image-gallery-CGvlv8zR.js} +0 -0
  471. /package/dist/web/assets/{imba-CxKv_2TW.js → imba-Didnp6Y-.js} +0 -0
  472. /package/dist/web/assets/{ini-BiHsyCdO.js → ini-m0T7q4gQ.js} +0 -0
  473. /package/dist/web/assets/{input-D-dR8RI6.js → input-C7Q8FxeL.js} +0 -0
  474. /package/dist/web/assets/{java-D3RZzgDB.js → java-Buy07jGn.js} +0 -0
  475. /package/dist/web/assets/{javascript-4FmSqG-T.js → javascript-Cjq3CbRL.js} +0 -0
  476. /package/dist/web/assets/{json-CjB236_E.js → json-BSVu8IqD.js} +0 -0
  477. /package/dist/web/assets/{json5-bkfO-Rco.js → json5-NN_Vb7e6.js} +0 -0
  478. /package/dist/web/assets/{jsonc-BwaTeLyv.js → jsonc-BdyZhBUw.js} +0 -0
  479. /package/dist/web/assets/{jsonl-CfxNSwGd.js → jsonl-BsDSNvwi.js} +0 -0
  480. /package/dist/web/assets/{jsonnet-CQETCYrp.js → jsonnet-Gm963F-U.js} +0 -0
  481. /package/dist/web/assets/{jssm-D5o3Zzdz.js → jssm-Ds3bKWgJ.js} +0 -0
  482. /package/dist/web/assets/{jsx-BAMILPLo.js → jsx-BT5mW58X.js} +0 -0
  483. /package/dist/web/assets/{kanagawa-dragon-BhGVxu3R.js → kanagawa-dragon-BvNvf7xd.js} +0 -0
  484. /package/dist/web/assets/{kanagawa-lotus-FH4Y59ro.js → kanagawa-lotus-CuSiliSn.js} +0 -0
  485. /package/dist/web/assets/{kanagawa-wave-eilvP9MB.js → kanagawa-wave-C6g-d6jT.js} +0 -0
  486. /package/dist/web/assets/{kdl-BQ-yvXUK.js → kdl-Bx4kZef-.js} +0 -0
  487. /package/dist/web/assets/{kotlin-BuCx0-VT.js → kotlin-qvaVvCcm.js} +0 -0
  488. /package/dist/web/assets/{kusto-DAN_n_Cy.js → kusto-BPLyNCN6.js} +0 -0
  489. /package/dist/web/assets/{laserwave-Cq2BlxrT.js → laserwave-Sf8ZEhWP.js} +0 -0
  490. /package/dist/web/assets/{lean-Dhq7uXKw.js → lean-DGe6uqgk.js} +0 -0
  491. /package/dist/web/assets/{less-CxaMQb8j.js → less-CqM85x-9.js} +0 -0
  492. /package/dist/web/assets/{lib-BVwmtv2i.js → lib-CD6pOS4u.js} +0 -0
  493. /package/dist/web/assets/{libesm-DdtEjhIi.js → libesm-CPh1Av0r.js} +0 -0
  494. /package/dist/web/assets/{light-plus-B4sMAend.js → light-plus-DBtKwhFA.js} +0 -0
  495. /package/dist/web/assets/{llvm-DQ6-B_6Y.js → llvm-Dpbq3gky.js} +0 -0
  496. /package/dist/web/assets/{log-Bb_vqvu7.js → log-qKMcPm9S.js} +0 -0
  497. /package/dist/web/assets/{logo-BzfYv3A_.js → logo-DFo7i5KH.js} +0 -0
  498. /package/dist/web/assets/{luau-BnAeNR77.js → luau-DGlqWFyL.js} +0 -0
  499. /package/dist/web/assets/{make-B6IFuxpC.js → make-CixdvUQe.js} +0 -0
  500. /package/dist/web/assets/{markdown-Z0xi77Fn.js → markdown-CmRnbngE.js} +0 -0
  501. /package/dist/web/assets/{material-theme-1scy1SYn.js → material-theme-WDUbafB-.js} +0 -0
  502. /package/dist/web/assets/{material-theme-darker-G-JykXQP.js → material-theme-darker-u8y2xpOk.js} +0 -0
  503. /package/dist/web/assets/{material-theme-lighter-BtKkCMVq.js → material-theme-lighter-cyQZK3Tg.js} +0 -0
  504. /package/dist/web/assets/{material-theme-ocean-irrDC89L.js → material-theme-ocean-LBAVvw7k.js} +0 -0
  505. /package/dist/web/assets/{material-theme-palenight-Eq5_K4LM.js → material-theme-palenight-BJqhBxL0.js} +0 -0
  506. /package/dist/web/assets/{matlab-BE3oCXZC.js → matlab-B38sOJee.js} +0 -0
  507. /package/dist/web/assets/{mdx-DYiuFTGw.js → mdx-C8QrE_IW.js} +0 -0
  508. /package/dist/web/assets/{mermaid-DVlaEvtw.js → mermaid-BQ-eeU8A.js} +0 -0
  509. /package/dist/web/assets/{min-dark-DSkeTpQa.js → min-dark-D4gNa5tv.js} +0 -0
  510. /package/dist/web/assets/{min-light-CFv2Q0uF.js → min-light-Dfbhn_PL.js} +0 -0
  511. /package/dist/web/assets/{mipsasm-CiAFuZQ2.js → mipsasm-bLOhJkdm.js} +0 -0
  512. /package/dist/web/assets/{mojo-ARshcaSQ.js → mojo-B0BCOMQW.js} +0 -0
  513. /package/dist/web/assets/{monaco-dotenv-language-BDYnKcnr.js → monaco-dotenv-language-uB-wok6C.js} +0 -0
  514. /package/dist/web/assets/{monokai-CPTV-SOg.js → monokai-Bdw_07OM.js} +0 -0
  515. /package/dist/web/assets/{moonbit-D57B0dZr.js → moonbit-BFdGaeuk.js} +0 -0
  516. /package/dist/web/assets/{move-qgy3G_o9.js → move-CyXQFGPM.js} +0 -0
  517. /package/dist/web/assets/{narrat-CZ3rC-oc.js → narrat-9DvTD3_3.js} +0 -0
  518. /package/dist/web/assets/{nextflow-groovy-BxxIOcI4.js → nextflow-groovy-C4VY3kNY.js} +0 -0
  519. /package/dist/web/assets/{night-owl-B1ryGCda.js → night-owl-feYm66V0.js} +0 -0
  520. /package/dist/web/assets/{night-owl-light-BZvNnvMF.js → night-owl-light-DALqFjvx.js} +0 -0
  521. /package/dist/web/assets/{nix-BVBQi8yv.js → nix-C1kPA9Sw.js} +0 -0
  522. /package/dist/web/assets/{nord-3NXw613h.js → nord-1dvrj1Al.js} +0 -0
  523. /package/dist/web/assets/{nushell-BMOLRalb.js → nushell-DSQ_9Uqj.js} +0 -0
  524. /package/dist/web/assets/{objective-c-AxruEUgh.js → objective-c-Dhcn5ZK8.js} +0 -0
  525. /package/dist/web/assets/{objective-cpp-cFT0qRsD.js → objective-cpp-CGVYCSrp.js} +0 -0
  526. /package/dist/web/assets/{ocaml-_8JH6O8J.js → ocaml-rxXW21An.js} +0 -0
  527. /package/dist/web/assets/{odin-nwYvR0O6.js → odin-ClSJX2DE.js} +0 -0
  528. /package/dist/web/assets/{one-dark-pro-C1LaYJaH.js → one-dark-pro-3gbWDfFW.js} +0 -0
  529. /package/dist/web/assets/{one-light-B7rMc__c.js → one-light-C2q5ZZAw.js} +0 -0
  530. /package/dist/web/assets/{openscad-Cwes8bKO.js → openscad-eHXeafBl.js} +0 -0
  531. /package/dist/web/assets/{pascal-DMt-6tdZ.js → pascal-kKha3Txs.js} +0 -0
  532. /package/dist/web/assets/{pkl-QBTyYQmB.js → pkl-CTiPytg-.js} +0 -0
  533. /package/dist/web/assets/{plastic-BTSUp8Fk.js → plastic-D1Ygezi4.js} +0 -0
  534. /package/dist/web/assets/{plsql-DQv3IFXP.js → plsql-D_gbgZIr.js} +0 -0
  535. /package/dist/web/assets/{po-CNwZx4tW.js → po-BkhbDUnq.js} +0 -0
  536. /package/dist/web/assets/{poimandres-8Os7Qequ.js → poimandres-Do6NywrA.js} +0 -0
  537. /package/dist/web/assets/{polar-b4yK8oD8.js → polar-B3B23wca.js} +0 -0
  538. /package/dist/web/assets/{postcss-sFctwpxx.js → postcss-Dv_YBvWd.js} +0 -0
  539. /package/dist/web/assets/{powerquery-Cg_WrtuN.js → powerquery-fKJWI-Sh.js} +0 -0
  540. /package/dist/web/assets/{powershell-C7Ifz95h.js → powershell-B4Y7KIgx.js} +0 -0
  541. /package/dist/web/assets/{prisma-Z52HUJzQ.js → prisma-J--XdTXX.js} +0 -0
  542. /package/dist/web/assets/{prolog-DLqW-zR1.js → prolog-BBTg4Vb3.js} +0 -0
  543. /package/dist/web/assets/{proto-BOIzxCCJ.js → proto-DWlum3T8.js} +0 -0
  544. /package/dist/web/assets/{puppet-De7TjZIf.js → puppet-ZiUfc9JV.js} +0 -0
  545. /package/dist/web/assets/{purescript-R76ou1WT.js → purescript-CmT8SCHB.js} +0 -0
  546. /package/dist/web/assets/{python-Dprm0tNP.js → python-BURpj-fq.js} +0 -0
  547. /package/dist/web/assets/{qmldir-Clp_jpNw.js → qmldir-CpaiJywQ.js} +0 -0
  548. /package/dist/web/assets/{qss-eQPYYzSo.js → qss-C-zdz0i5.js} +0 -0
  549. /package/dist/web/assets/{r-CCcRHIf5.js → r-K56BeS-s.js} +0 -0
  550. /package/dist/web/assets/{racket-CzE472yp.js → racket-gkn6Z_Jw.js} +0 -0
  551. /package/dist/web/assets/{raku-DQwXrTSi.js → raku-C0ZBuKlx.js} +0 -0
  552. /package/dist/web/assets/{red-KCS6wyop.js → red-BWZ6x-3p.js} +0 -0
  553. /package/dist/web/assets/{reg-CcrAddUh.js → reg-Dt_EsyGR.js} +0 -0
  554. /package/dist/web/assets/{regexp-DDbud-Ri.js → regexp-CT6BLG2C.js} +0 -0
  555. /package/dist/web/assets/{rel-99GDgaHp.js → rel-MJ2LcyzJ.js} +0 -0
  556. /package/dist/web/assets/{resolve-theme-CW2niGV2.js → resolve-theme-B_ukrg_8.js} +0 -0
  557. /package/dist/web/assets/{riscv-Dm2eNv0R.js → riscv-BZYWzMAA.js} +0 -0
  558. /package/dist/web/assets/{ron-CzFt0ygH.js → ron-CLbwHWMn.js} +0 -0
  559. /package/dist/web/assets/{rose-pine-Ck6lCrCP.js → rose-pine-BPiI_daR.js} +0 -0
  560. /package/dist/web/assets/{rose-pine-dawn-vtALRJNj.js → rose-pine-dawn-BjkJc7dW.js} +0 -0
  561. /package/dist/web/assets/{rose-pine-moon-DPto8qXw.js → rose-pine-moon-BQSxkt7g.js} +0 -0
  562. /package/dist/web/assets/{rosmsg-NtS6429H.js → rosmsg-yt4151pJ.js} +0 -0
  563. /package/dist/web/assets/{rust-BjIXvF9h.js → rust-1dAcengL.js} +0 -0
  564. /package/dist/web/assets/{sass-CQ23wf5E.js → sass-DUgtQJsg.js} +0 -0
  565. /package/dist/web/assets/{scala-LfKLM143.js → scala-CxoGYpS0.js} +0 -0
  566. /package/dist/web/assets/{scheme-D3SLBXlF.js → scheme-B2K3u9e3.js} +0 -0
  567. /package/dist/web/assets/{sdbl-ODRd2rGN.js → sdbl-C0Ygk0n6.js} +0 -0
  568. /package/dist/web/assets/{shellscript-3KB1G_oA.js → shellscript-C2CvhqMk.js} +0 -0
  569. /package/dist/web/assets/{slack-dark-DTtyWmIy.js → slack-dark-DYdgzRGj.js} +0 -0
  570. /package/dist/web/assets/{slack-ochin-Bu0PApk3.js → slack-ochin-X-WD0WCg.js} +0 -0
  571. /package/dist/web/assets/{smalltalk-haMT-Sbe.js → smalltalk-Dp7g_zb9.js} +0 -0
  572. /package/dist/web/assets/{snazzy-light-DXJzefE9.js → snazzy-light-DWHWr-a6.js} +0 -0
  573. /package/dist/web/assets/{solarized-dark-B6LyYa18.js → solarized-dark-CxdLsjvb.js} +0 -0
  574. /package/dist/web/assets/{solarized-light-QLADebkv.js → solarized-light-Cz9rAvG5.js} +0 -0
  575. /package/dist/web/assets/{solidity-mzfq1aDc.js → solidity-D33gHHdn.js} +0 -0
  576. /package/dist/web/assets/{splunk-CyH4RWBp.js → splunk-BFbOroYw.js} +0 -0
  577. /package/dist/web/assets/{sql-CWVlT5D3.js → sql-ChpxvmdY.js} +0 -0
  578. /package/dist/web/assets/{ssh-config-DNvQJ1Qx.js → ssh-config-CUuSQ6JG.js} +0 -0
  579. /package/dist/web/assets/{streaming-store-uDu3PoN1.js → streaming-store-BYukdB56.js} +0 -0
  580. /package/dist/web/assets/{stylus-ByQQdtmf.js → stylus-DDihP0_W.js} +0 -0
  581. /package/dist/web/assets/{swift-D1cpY4ow.js → swift-XoalUn4x.js} +0 -0
  582. /package/dist/web/assets/{synthwave-84-BDF_-QiW.js → synthwave-84-DjkG0Bff.js} +0 -0
  583. /package/dist/web/assets/{system-verilog-BYrkMydC.js → system-verilog-f_pLKMYd.js} +0 -0
  584. /package/dist/web/assets/{systemd-CQm3zyK0.js → systemd-DjDcLfxp.js} +0 -0
  585. /package/dist/web/assets/{talonscript-DMW5CzE1.js → talonscript-BpUzYcDl.js} +0 -0
  586. /package/dist/web/assets/{tasl-BhFzMCr2.js → tasl-DP-cUbg8.js} +0 -0
  587. /package/dist/web/assets/{tcl-D7VEAF-9.js → tcl-BHoy-dfE.js} +0 -0
  588. /package/dist/web/assets/{terraform-DdT5A0Vy.js → terraform-vCVxN25B.js} +0 -0
  589. /package/dist/web/assets/{tokyo-night-WGLMM6Q9.js → tokyo-night-D0u4xZba.js} +0 -0
  590. /package/dist/web/assets/{toml-CZ7ipXHZ.js → toml-BS8D0__A.js} +0 -0
  591. /package/dist/web/assets/{tsv-B1zVvoTr.js → tsv-DCb-NQh3.js} +0 -0
  592. /package/dist/web/assets/{tsx-D4HwRUBq.js → tsx-DF8YeRgG.js} +0 -0
  593. /package/dist/web/assets/{turtle-B4r8KEJH.js → turtle-Bhx1GlIy.js} +0 -0
  594. /package/dist/web/assets/{typescript-BnHhxMtp.js → typescript-CAVD2Wb6.js} +0 -0
  595. /package/dist/web/assets/{typespec-DP2q46GT.js → typespec-D7mchdY_.js} +0 -0
  596. /package/dist/web/assets/{typst-DFsD_yaD.js → typst-CeXzq6Yw.js} +0 -0
  597. /package/dist/web/assets/{use-is-mobile-BQ9Bv5Ga.js → use-is-mobile-TkcwP1Gx.js} +0 -0
  598. /package/dist/web/assets/{use-visual-viewport-CbwnktSG.js → use-visual-viewport-Lp878uzs.js} +0 -0
  599. /package/dist/web/assets/{v-Bji8hSVT.js → v-DhzO54je.js} +0 -0
  600. /package/dist/web/assets/{vala-D3TIgGmU.js → vala-Dw_RAk3E.js} +0 -0
  601. /package/dist/web/assets/{vb-DvcxFS2q.js → vb-CiXdNh2Y.js} +0 -0
  602. /package/dist/web/assets/{vendor-xterm-BqPDsE9b.js → vendor-xterm-BHEY6Ctu.js} +0 -0
  603. /package/dist/web/assets/{verilog-Dy7cF35d.js → verilog-fITdxqwV.js} +0 -0
  604. /package/dist/web/assets/{vesper-BzjwUv9J.js → vesper-B1wm_At7.js} +0 -0
  605. /package/dist/web/assets/{vhdl-DuFnFNmW.js → vhdl-ebHjqKp9.js} +0 -0
  606. /package/dist/web/assets/{viml-yAPgKlbz.js → viml-Dgmnoxoo.js} +0 -0
  607. /package/dist/web/assets/{vitesse-black-oSSQdyIZ.js → vitesse-black-BZ5gMb7l.js} +0 -0
  608. /package/dist/web/assets/{vitesse-dark-BZxwPihB.js → vitesse-dark-Lij7kkOt.js} +0 -0
  609. /package/dist/web/assets/{vitesse-light-uIigycvt.js → vitesse-light-DW6Wq7VC.js} +0 -0
  610. /package/dist/web/assets/{vyper-CX3NAxm5.js → vyper-6FxDnVNg.js} +0 -0
  611. /package/dist/web/assets/{wasm-6mEOOvVa.js → wasm-BDxaNPCj.js} +0 -0
  612. /package/dist/web/assets/{wasm-D9td37qO.js → wasm-DKhAtzfe.js} +0 -0
  613. /package/dist/web/assets/{wenyan-lwNIHgk6.js → wenyan-C0k0DYG_.js} +0 -0
  614. /package/dist/web/assets/{wgsl-DQAzCfog.js → wgsl-Y2zagbdn.js} +0 -0
  615. /package/dist/web/assets/{wikitext-DTXmt5NE.js → wikitext-C4QGWzkY.js} +0 -0
  616. /package/dist/web/assets/{wit-Bdw_7WDH.js → wit-CQESzjHy.js} +0 -0
  617. /package/dist/web/assets/{wolfram-DqyHDZ07.js → wolfram-B-ia69Ia.js} +0 -0
  618. /package/dist/web/assets/{yaml-CPXhdByd.js → yaml-CEYYTQPm.js} +0 -0
  619. /package/dist/web/assets/{zenscript-6s_i5zek.js → zenscript-BggWXIeJ.js} +0 -0
  620. /package/dist/web/assets/{zig-B2htezJ_.js → zig-CbaUfBQe.js} +0 -0
@@ -0,0 +1,250 @@
1
+ /**
2
+ * One shared Xlib connection for the X11 capture/input paths, over `bun:ffi` — no helper
3
+ * binary, matching `remote-desktop-input-win32.ts` (user32) and `-darwin.ts` (CoreGraphics).
4
+ *
5
+ * Two things here exist to keep a desktop problem from becoming a PPM problem:
6
+ *
7
+ * 1. **Xlib's default I/O error handler calls `exit()`.** If the X server goes away — a
8
+ * logout, a GPU driver reset, `systemctl restart sddm` — libX11 prints `XIO: fatal IO
9
+ * error` and terminates the *calling process*, which here is the whole PPM server: every
10
+ * project, terminal and chat session dies because someone logged out of the desktop. Both
11
+ * handlers are therefore replaced (`XSetIOErrorHandler` returns instead of falling through,
12
+ * and libX11 ≥ 1.7's `XSetIOErrorExitHandler` cancels the exit that otherwise happens even
13
+ * when the first one returns). Protocol errors (`BadWindow` from a monitor unplugged
14
+ * mid-enumeration) go to a no-op `XSetErrorHandler` rather than the default's stderr spew.
15
+ * The callbacks are held in module scope: a GC'd `JSCallback` would leave Xlib calling a
16
+ * freed trampoline, which is a segfault rather than the crash it was installed to prevent.
17
+ *
18
+ * On libX11 **1.6** that protection is only half there, and the code says so rather than
19
+ * assuming otherwise: the third handler does not exist before 1.7 (2021), so an I/O error
20
+ * still reaches the `exit()` the second handler returns into. It is loaded from its own
21
+ * dlopen table for that reason — `bun:ffi`'s `dlopen` throws on the *first* missing symbol
22
+ * and hands back none of the others, so one optional function in the main table would take
23
+ * capture, input, privacy mode and monitor enumeration down together on every host older
24
+ * than that (Ubuntu 20.04 ships 1.6.9).
25
+ *
26
+ * 2. **A connection that took an I/O error is not reusable.** There is no safe call left on it,
27
+ * not even `XCloseDisplay`, so it is dropped un-closed (a few KB, once per X server
28
+ * lifetime) and the next caller opens a fresh one.
29
+ *
30
+ * libXtst and libXrandr are optional: a host can have Xlib but no XTEST extension (input goes
31
+ * view-only) or no libXrandr (one whole-screen display instead of per-monitor). Neither is a
32
+ * reason to fail capture, so both load into `null` rather than throwing.
33
+ */
34
+ import { resetLinuxSession, type LinuxSession } from "./remote-desktop-linux-session.ts";
35
+
36
+ type Ffi = typeof import("bun:ffi");
37
+ /** Xlib pointer/handle as bun:ffi hands it back. */
38
+ type Ptr = number | bigint;
39
+
40
+ const X11_SYMBOLS = {
41
+ XOpenDisplay: { args: ["cstring"], returns: "ptr" },
42
+ XDefaultRootWindow: { args: ["ptr"], returns: "u64" },
43
+ XDefaultScreen: { args: ["ptr"], returns: "i32" },
44
+ XDisplayWidth: { args: ["ptr", "i32"], returns: "i32" },
45
+ XDisplayHeight: { args: ["ptr", "i32"], returns: "i32" },
46
+ XFlush: { args: ["ptr"], returns: "i32" },
47
+ XSync: { args: ["ptr", "i32"], returns: "i32" },
48
+ XGetAtomName: { args: ["ptr", "u64"], returns: "ptr" },
49
+ XFree: { args: ["ptr"], returns: "i32" },
50
+ XStringToKeysym: { args: ["cstring"], returns: "u64" },
51
+ XKeysymToKeycode: { args: ["ptr", "u64"], returns: "u8" },
52
+ XDisplayKeycodes: { args: ["ptr", "ptr", "ptr"], returns: "i32" },
53
+ XGetKeyboardMapping: { args: ["ptr", "u8", "i32", "ptr"], returns: "ptr" },
54
+ XChangeKeyboardMapping: { args: ["ptr", "i32", "i32", "ptr", "i32"], returns: "i32" },
55
+ XQueryPointer: { args: ["ptr", "u64", "ptr", "ptr", "ptr", "ptr", "ptr", "ptr", "ptr"], returns: "i32" },
56
+ // Privacy mode: an X grab with `owner_events = False` routes every local key and button to
57
+ // the grabbing client, which simply drops them. Paired with `XTestGrabControl` below, which
58
+ // is what keeps the *remote* session's injected events working through that grab.
59
+ XGrabKeyboard: { args: ["ptr", "u64", "i32", "i32", "i32", "u64"], returns: "i32" },
60
+ XGrabPointer: { args: ["ptr", "u64", "i32", "u32", "i32", "i32", "u64", "u64", "u64"], returns: "i32" },
61
+ XUngrabKeyboard: { args: ["ptr", "u64"], returns: "i32" },
62
+ XUngrabPointer: { args: ["ptr", "u64"], returns: "i32" },
63
+ XSetErrorHandler: { args: ["ptr"], returns: "ptr" },
64
+ XSetIOErrorHandler: { args: ["ptr"], returns: "ptr" },
65
+ } as const;
66
+
67
+ /** libX11 ≥ 1.7 only, which is why it is a table of its own rather than one more line above.
68
+ * Exported so a test can assert the split still holds: moving this key back into
69
+ * `X11_SYMBOLS` is a one-line change that costs every pre-1.7 host its input. */
70
+ export const X11_EXIT_SYMBOLS = {
71
+ XSetIOErrorExitHandler: { args: ["ptr", "ptr", "ptr"], returns: "void" },
72
+ } as const;
73
+
74
+ const XTST_SYMBOLS = {
75
+ XTestQueryExtension: { args: ["ptr", "ptr", "ptr", "ptr", "ptr"], returns: "i32" },
76
+ XTestFakeMotionEvent: { args: ["ptr", "i32", "i32", "i32", "u64"], returns: "i32" },
77
+ XTestFakeButtonEvent: { args: ["ptr", "u32", "i32", "u64"], returns: "i32" },
78
+ XTestFakeKeyEvent: { args: ["ptr", "u32", "i32", "u64"], returns: "i32" },
79
+ /** Makes this client's XTEST events *impervious to grabs* — the one call that lets privacy
80
+ * mode hold a keyboard/pointer grab without also blocking the remote session's own input. */
81
+ XTestGrabControl: { args: ["ptr", "i32"], returns: "i32" },
82
+ } as const;
83
+
84
+ const XRANDR_SYMBOLS = {
85
+ XRRGetMonitors: { args: ["ptr", "u64", "i32", "ptr"], returns: "ptr" },
86
+ XRRFreeMonitors: { args: ["ptr"], returns: "void" },
87
+ // Resolution switching. `…Current` rather than `XRRGetScreenResources`: the latter re-polls
88
+ // every output over DDC, which takes tens of milliseconds and can wake a sleeping monitor.
89
+ XRRGetScreenResourcesCurrent: { args: ["ptr", "u64"], returns: "ptr" },
90
+ XRRFreeScreenResources: { args: ["ptr"], returns: "void" },
91
+ XRRGetOutputInfo: { args: ["ptr", "ptr", "u64"], returns: "ptr" },
92
+ XRRFreeOutputInfo: { args: ["ptr"], returns: "void" },
93
+ XRRGetCrtcInfo: { args: ["ptr", "ptr", "u64"], returns: "ptr" },
94
+ XRRFreeCrtcInfo: { args: ["ptr"], returns: "void" },
95
+ XRRSetCrtcConfig: {
96
+ args: ["ptr", "ptr", "u64", "u64", "i32", "i32", "u64", "u16", "ptr", "i32"],
97
+ returns: "i32",
98
+ },
99
+ XRRSetScreenSize: { args: ["ptr", "u64", "i32", "i32", "i32", "i32"], returns: "void" },
100
+ } as const;
101
+
102
+ /** DPMS lives in libXext, not libX11. Used to turn the host's monitor off for privacy mode
103
+ * while leaving the framebuffer — and therefore the capture — alone. */
104
+ const DPMS_SYMBOLS = {
105
+ DPMSQueryExtension: { args: ["ptr", "ptr", "ptr"], returns: "i32" },
106
+ DPMSCapable: { args: ["ptr"], returns: "i32" },
107
+ DPMSEnable: { args: ["ptr"], returns: "i32" },
108
+ DPMSForceLevel: { args: ["ptr", "u16"], returns: "i32" },
109
+ DPMSInfo: { args: ["ptr", "ptr", "ptr"], returns: "i32" },
110
+ } as const;
111
+
112
+ /* eslint-disable @typescript-eslint/no-explicit-any -- dlopen's symbol types are per-call */
113
+ type X11Lib = { [K in keyof typeof X11_SYMBOLS]: any };
114
+ type X11ExitLib = { [K in keyof typeof X11_EXIT_SYMBOLS]: any };
115
+ type XtstLib = { [K in keyof typeof XTST_SYMBOLS]: any };
116
+ type XrandrLib = { [K in keyof typeof XRANDR_SYMBOLS]: any };
117
+ type DpmsLib = { [K in keyof typeof DPMS_SYMBOLS]: any };
118
+ /* eslint-enable @typescript-eslint/no-explicit-any */
119
+
120
+ export interface X11Connection {
121
+ ffi: Ffi;
122
+ x11: X11Lib;
123
+ /** null when the host has no libXtst — capture works, input does not. */
124
+ xtst: XtstLib | null;
125
+ /** null when the host has no libXrandr — one whole-screen display instead of per-monitor. */
126
+ xrandr: XrandrLib | null;
127
+ /** null when the host has no libXext, or its X server has no DPMS extension — privacy mode
128
+ * then blocks local input without blanking the monitor. */
129
+ dpms: DpmsLib | null;
130
+ dpy: Ptr;
131
+ root: bigint;
132
+ screen: number;
133
+ /** XTEST is present AND usable on this connection. */
134
+ hasXTest: boolean;
135
+ /** Which display this was opened against, so a later session change cannot reuse it. */
136
+ display: string;
137
+ }
138
+
139
+ let ffiModule: Ffi | null = null;
140
+ let connection: X11Connection | null = null;
141
+ /** Kept forever: Xlib holds raw pointers to these trampolines for the process lifetime. Named
142
+ * rather than an array, because the one read outside `installErrorHandlers` used to be
143
+ * `liveCallbacks[2]` — a fourth handler would have handed the wrong trampoline to Xlib, with
144
+ * a wrong signature, and nothing to say so until it was called. */
145
+ let errorCallbacks: { onError: Trampoline; onIoError: Trampoline; onIoExit: Trampoline } | null = null;
146
+ let connectionLost = false;
147
+
148
+ /** One `JSCallback`, whose `.ptr` is the address Xlib keeps for the process lifetime. */
149
+ type Trampoline = InstanceType<Ffi["JSCallback"]>;
150
+
151
+ function tryDlopen<T>(ffi: Ffi, names: string[], symbols: object): T | null {
152
+ for (const name of names) {
153
+ try { return ffi.dlopen(name, symbols as never).symbols as T; } catch { /* try the next soname */ }
154
+ }
155
+ return null;
156
+ }
157
+
158
+ /** Replace the three handlers that would otherwise print to stderr or kill the process. */
159
+ function installErrorHandlers(ffi: Ffi, x11: X11Lib): void {
160
+ if (errorCallbacks) return;
161
+ const { JSCallback } = ffi;
162
+
163
+ // Protocol error (BadWindow/BadMatch): return 0, the same as the default handler minus stderr.
164
+ const onError = new JSCallback(() => 0, { args: ["ptr", "ptr"], returns: "i32" });
165
+ // I/O error: server gone. Mark dead and return — libX11 would otherwise fall through to exit.
166
+ const onIoError = new JSCallback(() => { connectionLost = true; return 0; }, { args: ["ptr"], returns: "i32" });
167
+ // The exit that happens anyway once the handler above returns. Cancelled by doing nothing.
168
+ const onIoExit = new JSCallback(() => { connectionLost = true; }, { args: ["ptr", "ptr"], returns: "void" });
169
+
170
+ x11.XSetErrorHandler(onError.ptr);
171
+ x11.XSetIOErrorHandler(onIoError.ptr);
172
+ // Written last, and this is the whole of the "installed" flag: the old boolean was set
173
+ // *before* the two calls above, so anything that read it in between was told the process was
174
+ // protected while the default handlers were still in place.
175
+ errorCallbacks = { onError, onIoError, onIoExit };
176
+ }
177
+
178
+ /** The shared connection for `session`, or null when Xlib is missing or the server refuses us
179
+ * (no `$DISPLAY` server running, an auth cookie we cannot read). */
180
+ export async function getX11(session: LinuxSession): Promise<X11Connection | null> {
181
+ if (session.kind !== "x11") return null;
182
+ if (connectionLost) { connection = null; connectionLost = false; }
183
+ // Matched on the display, not merely on there being a connection. The session is re-probed
184
+ // periodically now, so it can name a different display on a still-live server — a second
185
+ // seat, a nested Xephyr, `:0` becoming `:1`. Handing back the old `Display*` then sends
186
+ // every keystroke and click into the display nobody is looking at, silently and for good:
187
+ // nothing errors, because the old server is still there.
188
+ // Dropped rather than closed, the way `resetX11` and the module header already decide: Xlib's
189
+ // I/O error handler can `exit()` the server process, so `XCloseDisplay` is never called here.
190
+ if (connection && connection.display !== session.display) connection = null;
191
+ if (connection) return connection;
192
+
193
+ if (!ffiModule) ffiModule = await import("bun:ffi");
194
+ const ffi = ffiModule;
195
+ const x11 = tryDlopen<X11Lib>(ffi, ["libX11.so.6", "libX11.so"], X11_SYMBOLS);
196
+ if (!x11) return null;
197
+ // Same library, second `dlopen`: null here means libX11 1.6, not a missing libX11.
198
+ const x11Exit = tryDlopen<X11ExitLib>(ffi, ["libX11.so.6", "libX11.so"], X11_EXIT_SYMBOLS);
199
+ installErrorHandlers(ffi, x11);
200
+
201
+ const dpy = x11.XOpenDisplay(Buffer.from(`${session.display}\0`));
202
+ if (!dpy) return null;
203
+
204
+ const xtst = tryDlopen<XtstLib>(ffi, ["libXtst.so.6", "libXtst.so"], XTST_SYMBOLS);
205
+ const xrandr = tryDlopen<XrandrLib>(ffi, ["libXrandr.so.2", "libXrandr.so"], XRANDR_SYMBOLS);
206
+ const xext = tryDlopen<DpmsLib>(ffi, ["libXext.so.6", "libXext.so"], DPMS_SYMBOLS);
207
+
208
+ let hasXTest = false;
209
+ if (xtst) {
210
+ const out = new Int32Array(1);
211
+ hasXTest = xtst.XTestQueryExtension(dpy, ffi.ptr(out), ffi.ptr(out), ffi.ptr(out), ffi.ptr(out)) !== 0;
212
+ }
213
+
214
+ // The exit handler needs the Display, so it is installed after the connection exists — and
215
+ // only where the symbol resolved. The guard was on whether a *callback* existed, which is
216
+ // always true and says nothing about whether libX11 has the function to pass it to.
217
+ if (x11Exit && errorCallbacks) x11Exit.XSetIOErrorExitHandler(dpy, errorCallbacks.onIoExit.ptr, null);
218
+
219
+ // libXext being present is not enough: a server can be built without the DPMS extension, and
220
+ // `DPMSForceLevel` against one of those is a no-op that returns success.
221
+ let dpms: DpmsLib | null = null;
222
+ if (xext) {
223
+ const out = new Int32Array(2);
224
+ const present = xext.DPMSQueryExtension(dpy, ffi.ptr(out), ffi.ptr(out.subarray(1))) !== 0;
225
+ if (present && xext.DPMSCapable(dpy) !== 0) dpms = xext;
226
+ }
227
+
228
+ connection = {
229
+ ffi, x11, xtst, xrandr, dpms, dpy,
230
+ root: BigInt(x11.XDefaultRootWindow(dpy)),
231
+ screen: x11.XDefaultScreen(dpy),
232
+ hasXTest,
233
+ display: session.display,
234
+ };
235
+ return connection;
236
+ }
237
+
238
+ /** `bun:ffi` types every address as a branded `Pointer`, but walking a C array means doing
239
+ * arithmetic on a plain number. One cast, here, instead of at every struct field. */
240
+ export function asPointer(address: number): import("bun:ffi").Pointer {
241
+ return address as unknown as import("bun:ffi").Pointer;
242
+ }
243
+
244
+ /** Drop the cached connection (tests, and after a session change) and, with it, the memoized
245
+ * session it was opened against. */
246
+ export function resetX11(): void {
247
+ connection = null;
248
+ connectionLost = false;
249
+ resetLinuxSession();
250
+ }
@@ -11,6 +11,7 @@ import {
11
11
  unlinkSync, statSync,
12
12
  } from "node:fs";
13
13
  import { getPpmDir } from "./ppm-dir.ts";
14
+ import { stdioIsLogFile, consumeStdioIsLogEnv, rotateIfOversized, MAX_LOG_BYTES, STDIO_IS_LOG_ENV } from "./log-rotate.ts";
14
15
  import { isCompiledBinary } from "./autostart-generator.ts";
15
16
  import { cleanupStaleBinaryUpgradeArtifacts } from "./binary-upgrade-swap.ts";
16
17
  import {
@@ -60,6 +61,7 @@ const DB_BACKUP_STALE_WARN_MS = 21_600_000; // 6h — snapshots stopped happenin
60
61
  const SELF_REPLACE_TIMEOUT_MS = 30_000; // 30s to wait for new supervisor
61
62
  const EDGE_PROBE_INTERVAL_MS = 10_000; // the public port is dark while the edge is down — check often
62
63
  const SERVER_PORT_MIRROR_TIMEOUT_MS = 30_000; // how long to wait for the server to publish its port
64
+ const LOG_ROTATE_INTERVAL_MS = 60_000; // how often ppm.log is checked against its cap
63
65
 
64
66
  const logFile = () => resolve(getPpmDir(), "ppm.log");
65
67
  const restartingFlag = () => resolve(getPpmDir(), ".restarting");
@@ -154,12 +156,51 @@ let cloudConnected = false; // tracks whether we've initiated a cloud WS connect
154
156
  let originalArgv: string[] = [];
155
157
 
156
158
  // ─── Logging ───────────────────────────────────────────────────────────
159
+
160
+ /**
161
+ * Whether this process's own stderr already lands in ppm.log.
162
+ *
163
+ * Normally it does not — under systemd stderr is the journal, and the
164
+ * supervisor's lines belong there as well as in the log. But the replacement
165
+ * supervisor of a self-upgrade is spawned with `stdio: ["ignore", newLogFd,
166
+ * newLogFd]`, and from then on every line would be written to the file twice.
167
+ * Resolved once, lazily: fd 2 does not change underneath a running process.
168
+ */
169
+ let stderrIsLogFile: boolean | null = null;
170
+
157
171
  function log(level: string, msg: string) {
158
172
  const ts = new Date().toISOString();
159
173
  const line = `[${ts}] [${level}] [supervisor] ${msg}\n`;
160
174
  try { appendFileSync(logFile(), line); } catch {}
161
- // Always write supervisor logs to stderr so journalctl captures them
162
- try { process.stderr.write(line); } catch {}
175
+ if (stderrIsLogFile === null) {
176
+ stderrIsLogFile = stdioIsLogFile(2, logFile());
177
+ consumeStdioIsLogEnv();
178
+ }
179
+ // Write supervisor logs to stderr so journalctl captures them — unless
180
+ // stderr is the log file itself, where that is the same line again.
181
+ if (!stderrIsLogFile) { try { process.stderr.write(line); } catch {} }
182
+ }
183
+
184
+ let logRotateTimer: ReturnType<typeof setInterval> | null = null;
185
+
186
+ /**
187
+ * Keep ppm.log under its cap. Only the supervisor does this.
188
+ *
189
+ * It is the long-lived owner of the descriptor every child was handed, and two
190
+ * processes truncating one file would race. Deliberately *not* run once at
191
+ * startup: the first rotation of a log that has been left to grow copies the
192
+ * whole of it, and doing that during boot adds to the one stall this work is
193
+ * trying to remove. The first tick is a minute away and nothing is worse for
194
+ * waiting.
195
+ */
196
+ function startLogRotation() {
197
+ if (logRotateTimer) return;
198
+ logRotateTimer = setInterval(() => {
199
+ if (rotateIfOversized(logFile())) {
200
+ log("INFO", `Rotated ppm.log at cap ${Math.round(MAX_LOG_BYTES / 1048576)} MB`);
201
+ }
202
+ }, LOG_ROTATE_INTERVAL_MS);
203
+ logRotateTimer.unref?.();
163
204
  }
164
205
 
165
206
  // ─── Backoff calc ──────────────────────────────────────────────────────
@@ -622,7 +663,8 @@ export async function spawnServer(
622
663
  serverChild = await withProbeSpawnGate(() => Bun.spawn({
623
664
  cmd,
624
665
  stdio: ["ignore", logFd, logFd],
625
- env: process.env,
666
+ // The child cannot work out on Windows that fd 1 is already the log, so it is told.
667
+ env: { ...process.env, [STDIO_IS_LOG_ENV]: "1" },
626
668
  // No visible console window. Critical on Windows after an upgrade: the new
627
669
  // supervisor is spawned consoleless (detached), so without this its console
628
670
  // children — and the Claude SDK grandchildren they spawn — pop blank windows.
@@ -1509,7 +1551,7 @@ async function selfReplace(): Promise<{ success: boolean; error?: string }> {
1509
1551
  const proc = await withProbeSpawnGate(() => nodeSpawn(cmd[0]!, cmd.slice(1), {
1510
1552
  detached: true,
1511
1553
  stdio: ["ignore", newLogFd, newLogFd] as any,
1512
- env: process.env as NodeJS.ProcessEnv,
1554
+ env: { ...process.env, [STDIO_IS_LOG_ENV]: "1" } as NodeJS.ProcessEnv,
1513
1555
  windowsHide: true,
1514
1556
  }));
1515
1557
  const killNewChild = () => { try { if (proc.pid) process.kill(proc.pid); } catch {} };
@@ -1873,6 +1915,7 @@ export async function runSupervisor(opts: {
1873
1915
  originalArgv = [...process.argv];
1874
1916
 
1875
1917
  const logFd = openSync(logFile(), "a");
1918
+ startLogRotation();
1876
1919
  log("INFO", `Supervisor started (PID: ${process.pid}, port: ${opts.port}, share: ${opts.share})`);
1877
1920
 
1878
1921
  // ── Systemd self-heal: if the unit file is stale (e.g. still has