@hienlh/ppm 0.17.56 → 0.18.0

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 (583) hide show
  1. package/.release-run.sh +5 -0
  2. package/CHANGELOG.md +21 -0
  3. package/CLAUDE.md +4 -0
  4. package/assets/skills/ppm/SKILL.md +1 -1
  5. package/assets/skills/ppm/references/http-api.md +16 -2
  6. package/bun.lock +3 -0
  7. package/dist/web/assets/{ai-resource-editor-DL011EDu.js → ai-resource-editor-BLYgg033.js} +1 -1
  8. package/dist/web/assets/{angular-html-D4YJUMLP.js → angular-html-jfMqUuRd.js} +1 -1
  9. package/dist/web/assets/{angular-ts-CUvq2h3X.js → angular-ts-wytn9PMm.js} +1 -1
  10. package/dist/web/assets/{api-client-COQtP-dB.js → api-client-B9OFv3nY.js} +1 -1
  11. package/dist/web/assets/api-client-CKo60P6G.js +1 -0
  12. package/dist/web/assets/{api-settings-Do0Z0IRN.js → api-settings-DGhshDRg.js} +1 -1
  13. package/dist/web/assets/api-settings-fdkhqLSF.js +1 -0
  14. package/dist/web/assets/{api-themes-DXi8sz-9.js → api-themes-okiyhhp9.js} +1 -1
  15. package/dist/web/assets/{apl-DSANFLx0.js → apl-i-ahKx6O.js} +1 -1
  16. package/dist/web/assets/architecture-PBZL5I3N-B4J2-O8Q.js +1 -0
  17. package/dist/web/assets/{astro-CXIotiNS.js → astro-DVBCJfG6.js} +1 -1
  18. package/dist/web/assets/{audio-preview-H16VO99g.js → audio-preview-y8XpCNrh.js} +1 -1
  19. package/dist/web/assets/{blade-BvrP2gPd.js → blade-BHlL8SqU.js} +1 -1
  20. package/dist/web/assets/{bsl-CGf6Xuyu.js → bsl-D-UOfR1F.js} +1 -1
  21. package/dist/web/assets/{cairo-BboZ9qIf.js → cairo-Bn6rucli.js} +1 -1
  22. package/dist/web/assets/can-open-in-ppm-BzVXoV-d.js +1 -0
  23. package/dist/web/assets/chat-tab-BcR-3_6R.js +13 -0
  24. package/dist/web/assets/clock-B1CPBp2g.js +1 -0
  25. package/dist/web/assets/{cobol-D39V6ukp.js → cobol-Byn9FYKu.js} +1 -1
  26. package/dist/web/assets/code-editor-CJ8g7dqm.js +10 -0
  27. package/dist/web/assets/{coffee-DTtK7kKi.js → coffee-DjBl4gm-.js} +1 -1
  28. package/dist/web/assets/{conflict-editor-B_wAb0Kb.js → conflict-editor-BP7JFZzG.js} +3 -3
  29. package/dist/web/assets/context-menu-BSE5yuMG.js +1 -0
  30. package/dist/web/assets/copy-Su9m2utd.js +1 -0
  31. package/dist/web/assets/{cpp-CnU9hfBq.js → cpp-CKzic-3E.js} +1 -1
  32. package/dist/web/assets/{crystal-DMjCL--0.js → crystal-Bkg-Ly_g.js} +1 -1
  33. package/dist/web/assets/csv-preview-xAwUDNat.js +2 -0
  34. package/dist/web/assets/{data-grid-overlay-editor-Bdc80TJ1.js → data-grid-overlay-editor-DMTCHIG9.js} +1 -1
  35. package/dist/web/assets/{database-viewer-awmnuDCt.js → database-viewer-BVLWYPa4.js} +1 -1
  36. package/dist/web/assets/dialog-D__LRQTn.js +1 -0
  37. package/dist/web/assets/diff-viewer-BheSOHfl.js +4 -0
  38. package/dist/web/assets/{docx-preview-DDw3duw9.js → docx-preview-CGlMqltP.js} +1 -1
  39. package/dist/web/assets/{edge-CTom35R_.js → edge-DVbZnd3Y.js} +1 -1
  40. package/dist/web/assets/{edit-diff-preview-D1TEK7Jz.js → edit-diff-preview-ClJAJwlL.js} +1 -1
  41. package/dist/web/assets/{elixir-BAX9HSOu.js → elixir-Dwi8Wu7W.js} +1 -1
  42. package/dist/web/assets/{elm-CpD28xsW.js → elm-DtIv-HXJ.js} +1 -1
  43. package/dist/web/assets/{erb-DHX2IIEs.js → erb-D3HEDz1x.js} +1 -1
  44. package/dist/web/assets/{erlang-B_etLcPG.js → erlang-2MjTCzGz.js} +1 -1
  45. package/dist/web/assets/{esm-PmlN1RTs.js → esm-BfqDE09P.js} +1 -1
  46. package/dist/web/assets/explorer-body-DE5339g9.js +2 -0
  47. package/dist/web/assets/explorer-window-content-BrTHAoXM.js +1 -0
  48. package/dist/web/assets/{extension-webview-DkTI51P3.js → extension-webview-DRq1tWC1.js} +1 -1
  49. package/dist/web/assets/{fortran-fixed-form-CpR0cN7O.js → fortran-fixed-form-BLyAtyPM.js} +1 -1
  50. package/dist/web/assets/{fsharp-DxITxZW5.js → fsharp-Bxbn_gbr.js} +1 -1
  51. package/dist/web/assets/{gdresource-DJ7IvROZ.js → gdresource-sFMY4D2Q.js} +1 -1
  52. package/dist/web/assets/{git-commit-sQznNP43.js → git-commit-BzB9Lio5.js} +1 -1
  53. package/dist/web/assets/git-log-panel-pjyOjchU.js +1 -0
  54. package/dist/web/assets/{git-rebase-DkHvejAR.js → git-rebase-CKSVd848.js} +1 -1
  55. package/dist/web/assets/gitGraph-HDMCJU4V-CtQ3yXN-.js +1 -0
  56. package/dist/web/assets/{glide-data-grid-Bpgp72Hg.js → glide-data-grid-LX3N4SsJ.js} +9 -9
  57. package/dist/web/assets/{glimmer-js-BwJnDfL-.js → glimmer-js-BY8aExAJ.js} +1 -1
  58. package/dist/web/assets/{glimmer-ts-Coz155XK.js → glimmer-ts-Bak54dBX.js} +1 -1
  59. package/dist/web/assets/{glsl-BED7ZmUZ.js → glsl-nR2eaJQe.js} +1 -1
  60. package/dist/web/assets/{graphql-B_KyE6oz.js → graphql-CGPPFAU6.js} +1 -1
  61. package/dist/web/assets/group-chat-tab-CVQfptkT.js +1 -0
  62. package/dist/web/assets/{hack-sxywdIAQ.js → hack-CXIMX-Ol.js} +1 -1
  63. package/dist/web/assets/{haml-Dts9JlPU.js → haml-tPY-9Pfm.js} +1 -1
  64. package/dist/web/assets/{handlebars-C9HXIMtj.js → handlebars-BuW1LT7T.js} +1 -1
  65. package/dist/web/assets/{html-2p0RvXi4.js → html-bgVcwZ-t.js} +1 -1
  66. package/dist/web/assets/{html-derivative-BiTPuOba.js → html-derivative-D6-IxTgn.js} +1 -1
  67. package/dist/web/assets/{http-CHd2gYPf.js → http-CJ1zyB-h.js} +1 -1
  68. package/dist/web/assets/{hurl-boMPgDm9.js → hurl-CmoT7l3T.js} +1 -1
  69. package/dist/web/assets/{hxml-BQvjiuBt.js → hxml-CztOsL8o.js} +1 -1
  70. package/dist/web/assets/{image-preview-Dwg0EuJ2.js → image-preview-BDySmiim.js} +1 -1
  71. package/dist/web/assets/index-XoDY9bc0.js +52 -0
  72. package/dist/web/assets/index-YCTraslE.css +2 -0
  73. package/dist/web/assets/info-3K5VOQVL-Cg0mIJn9.js +1 -0
  74. package/dist/web/assets/{jinja-B-zKiwlp.js → jinja-B1pq3jJq.js} +1 -1
  75. package/dist/web/assets/{jison-C2vJYjbJ.js → jison-D8B5pCwA.js} +1 -1
  76. package/dist/web/assets/{julia-DJ8MrQPA.js → julia-D0K3bwpU.js} +1 -1
  77. package/dist/web/assets/{just-BvQHq7VE.js → just-B9Jlddu-.js} +1 -1
  78. package/dist/web/assets/keybindings-store-BE1jVUZW.js +1 -0
  79. package/dist/web/assets/{latex-ChNeshUC.js → latex-BPJSSE6j.js} +1 -1
  80. package/dist/web/assets/{liquid-KNJEBOwW.js → liquid-lv10fo4U.js} +1 -1
  81. package/dist/web/assets/{lua-D8NNsLbC.js → lua-PNuaIBEF.js} +1 -1
  82. package/dist/web/assets/{markdown-renderer-C7dlPs2S.js → markdown-renderer-B8Kz5rvP.js} +3 -3
  83. package/dist/web/assets/markdown-renderer-Btync7yg.js +1 -0
  84. package/dist/web/assets/{marko-HGo5Qtz4.js → marko-Du3frD6X.js} +1 -1
  85. package/dist/web/assets/{mdc-omkodQB5.js → mdc-BeDVcFRl.js} +1 -1
  86. package/dist/web/assets/mobile-bottom-sheet-CzRXE6mY.js +1 -0
  87. package/dist/web/assets/mobile-explorer-sheet-CDU8xriw.js +1 -0
  88. package/dist/web/assets/{nextflow-Adq02pv-.js → nextflow-DkcXP71s.js} +1 -1
  89. package/dist/web/assets/{nginx-ByvWruGD.js → nginx-C5n8N_bt.js} +1 -1
  90. package/dist/web/assets/{nim-BrMojX4O.js → nim-CIhyfs-A.js} +1 -1
  91. package/dist/web/assets/notification-store-Bi7VHAy4.js +1 -0
  92. package/dist/web/assets/{number-overlay-editor-CunvWJnN.js → number-overlay-editor-B8P26qGC.js} +1 -1
  93. package/dist/web/assets/packet-RMMSAZCW-D79vAFR_.js +1 -0
  94. package/dist/web/assets/{panel-store-CpKvXNnm.js → panel-store-gbNJvZB_.js} +1 -1
  95. package/dist/web/assets/{pdf-preview-CEWYMxdp.js → pdf-preview-CtZWvujY.js} +1 -1
  96. package/dist/web/assets/{perl-Bd_0l-b4.js → perl-Cf31sZYE.js} +1 -1
  97. package/dist/web/assets/{php-D-DLTnWJ.js → php-Dzl_MDIW.js} +1 -1
  98. package/dist/web/assets/pie-UPGHQEXC-DYUOH68U.js +1 -0
  99. package/dist/web/assets/{postgres-viewer-D7PggslU.js → postgres-viewer-fqMUi0xS.js} +3 -3
  100. package/dist/web/assets/{project-store-D0ALup9Z.js → project-store-D1D1MN03.js} +1 -1
  101. package/dist/web/assets/{pug-D2aO-l2T.js → pug-CxSYHrB3.js} +1 -1
  102. package/dist/web/assets/{qml-CyQVzNXS.js → qml-DlEjGhwN.js} +1 -1
  103. package/dist/web/assets/radar-KQ55EAFF-B1eznNtd.js +1 -0
  104. package/dist/web/assets/{razor-8tvJXsO3.js → razor-KVt5uW14.js} +1 -1
  105. package/dist/web/assets/{rst-C4AZyQQl.js → rst-D5BwNTnw.js} +1 -1
  106. package/dist/web/assets/{ruby-O_z2NTLY.js → ruby-D5fejQwd.js} +1 -1
  107. package/dist/web/assets/{sas-BtnF4zaV.js → sas-Bj7B1CB2.js} +1 -1
  108. package/dist/web/assets/{scss-GAyp5euH.js → scss-BB0CUoCL.js} +1 -1
  109. package/dist/web/assets/settings-store-Bm7uL8VA.js +2 -0
  110. package/dist/web/assets/settings-tab-DxtBG0DW.js +1 -0
  111. package/dist/web/assets/{shaderlab-nM5YZwa5.js → shaderlab-BdjEZUMc.js} +1 -1
  112. package/dist/web/assets/{shellsession-D2OCI4Gv.js → shellsession-Bp1OA1rR.js} +1 -1
  113. package/dist/web/assets/{soy-DrLNhqfp.js → soy-DlYz3wsC.js} +1 -1
  114. package/dist/web/assets/sparkles-BvJ1EGWd.js +1 -0
  115. package/dist/web/assets/{sparql-CsM6F2Yv.js → sparql-CdfII5Jd.js} +1 -1
  116. package/dist/web/assets/{sql-query-editor-ZnKcxCyj.js → sql-query-editor-D2UxRvG7.js} +1 -1
  117. package/dist/web/assets/sqlite-viewer-CTBwzT-r.js +1 -0
  118. package/dist/web/assets/{stata-Bk3cgfXJ.js → stata-BvUA6GUW.js} +1 -1
  119. package/dist/web/assets/{surrealql-Dkz0DPK8.js → surrealql--DLNbTyI.js} +1 -1
  120. package/dist/web/assets/{svelte-23si1KV5.js → svelte-CBfSsG4n.js} +1 -1
  121. package/dist/web/assets/{system-monitor-tab-Ck3REHUg.js → system-monitor-tab-Bscf6tzK.js} +1 -1
  122. package/dist/web/assets/{tab-store-BQmDVh9c.js → tab-store-DnNnaAcE.js} +1 -1
  123. package/dist/web/assets/{templ-CPxlP4vF.js → templ-Dv8zpKZW.js} +1 -1
  124. package/dist/web/assets/{terminal-tab-D6tYDFSF.js → terminal-tab-CTKU5gaF.js} +3 -3
  125. package/dist/web/assets/{tex-ugJpgYPc.js → tex-CsrOiqh1.js} +1 -1
  126. package/dist/web/assets/tool-cards-xstpayaW.js +7 -0
  127. package/dist/web/assets/treemap-KZPCXAKY-SeI2TxLs.js +1 -0
  128. package/dist/web/assets/{ts-tags-BovP9TMu.js → ts-tags-3T98k4EJ.js} +1 -1
  129. package/dist/web/assets/{twig-B7VUm2Ca.js → twig-u6QZ45FH.js} +1 -1
  130. package/dist/web/assets/{use-blob-url-B3YovXF6.js → use-blob-url-BLRmhlZI.js} +1 -1
  131. package/dist/web/assets/{use-monaco-theme-wKbyNwIn.js → use-monaco-theme-DxYstgYa.js} +1 -1
  132. package/dist/web/assets/{vendor-mermaid-CYOBtZtD.js → vendor-mermaid-C977xNeE.js} +1 -1
  133. package/dist/web/assets/{vendor-ui-DMRGWRuc.js → vendor-ui-CXJtBULr.js} +1 -1
  134. package/dist/web/assets/{video-preview-DwrfenNA.js → video-preview-cfaoRxG3.js} +1 -1
  135. package/dist/web/assets/{vue-m75pWowk.js → vue-CxIsxtwn.js} +1 -1
  136. package/dist/web/assets/{vue-html-odHs7IMn.js → vue-html-BGL5qnuH.js} +1 -1
  137. package/dist/web/assets/{vue-vine-BbBB3V_G.js → vue-vine-DHPh_gMr.js} +1 -1
  138. package/dist/web/assets/{xml-BHzIcDWI.js → xml-C-vM2m7J.js} +1 -1
  139. package/dist/web/assets/{xsl-DTLhN7uu.js → xsl-DvTXNwuO.js} +1 -1
  140. package/dist/web/index.html +26 -23
  141. package/dist/web/sw.js +1 -1
  142. package/docs/codebase-summary.md +10 -1
  143. package/docs/design-guidelines.md +31 -0
  144. package/docs/project-roadmap.md +10 -0
  145. package/docs/system-architecture.md +59 -0
  146. package/package.json +2 -1
  147. package/src/providers/claude-agent-sdk.ts +6 -0
  148. package/src/server/index.ts +8 -0
  149. package/src/server/routes/files.ts +2 -2
  150. package/src/server/routes/fs-browse.ts +99 -74
  151. package/src/server/routes/fs-ops.ts +118 -0
  152. package/src/server/routes/fs-sqlite.ts +129 -0
  153. package/src/server/routes/host-info.ts +17 -0
  154. package/src/server/routes/settings.ts +2 -0
  155. package/src/services/download-token.service.ts +21 -5
  156. package/src/services/file.service.ts +8 -12
  157. package/src/services/fs-browse.service.ts +104 -161
  158. package/src/services/fs-ops/fs-content-disposition.ts +17 -0
  159. package/src/services/fs-ops/fs-core-ops.ts +149 -0
  160. package/src/services/fs-ops/fs-error-response.ts +24 -0
  161. package/src/services/fs-ops/fs-git-init.service.ts +23 -0
  162. package/src/services/fs-ops/fs-hidden-names.ts +17 -0
  163. package/src/services/fs-ops/fs-list-files.service.ts +68 -0
  164. package/src/services/fs-ops/fs-ops-copy-move.service.ts +60 -0
  165. package/src/services/fs-ops/fs-ops-mutate.service.ts +59 -0
  166. package/src/services/fs-ops/fs-ops-read-write.service.ts +70 -0
  167. package/src/services/fs-ops/fs-ops-stat.service.ts +109 -0
  168. package/src/services/fs-ops/fs-ops-trash.service.ts +111 -0
  169. package/src/services/fs-ops/fs-real-path.ts +44 -0
  170. package/src/services/fs-ops/sql-row-reader.ts +26 -0
  171. package/src/services/fs-ops/sql-statement-guard.ts +63 -0
  172. package/src/services/fs-path-guard.service.ts +196 -0
  173. package/src/services/host-info/apple-bookmark-decoder.ts +97 -0
  174. package/src/services/host-info/apple-plist-xml-parser.ts +107 -0
  175. package/src/services/host-info/concurrency-limit.ts +20 -0
  176. package/src/services/host-info/host-drives.ts +190 -0
  177. package/src/services/host-info/host-info.service.ts +171 -0
  178. package/src/services/host-info/host-known-folders.ts +180 -0
  179. package/src/services/host-info/pinned-linux-bookmarks.ts +89 -0
  180. package/src/services/host-info/pinned-macos-finder-favorites.ts +175 -0
  181. package/src/services/host-info/pinned-windows-quick-access.ts +87 -0
  182. package/src/services/host-info/spawn-runner.ts +41 -0
  183. package/src/services/jsonl-transcript-parser.ts +6 -0
  184. package/src/services/sqlite-types.ts +26 -0
  185. package/src/services/sqlite.service.ts +38 -29
  186. package/src/services/subagent-transcript-merger.ts +144 -0
  187. package/src/types/system.ts +50 -0
  188. package/src/web/app.tsx +19 -3
  189. package/src/web/components/editor/code-editor.tsx +3 -9
  190. package/src/web/components/explorer/file-tree.tsx +103 -21
  191. package/src/web/components/explorer/tree-node-context-menu.tsx +6 -1
  192. package/src/web/components/explorer/tree-node.tsx +34 -93
  193. package/src/web/components/explorer/use-file-upload-drag.ts +14 -9
  194. package/src/web/components/explorer/use-tree-row-dnd.ts +206 -0
  195. package/src/web/components/floating-window/default-window-chrome.tsx +71 -0
  196. package/src/web/components/floating-window/floating-window.tsx +167 -0
  197. package/src/web/components/floating-window/use-window-drag.ts +28 -0
  198. package/src/web/components/floating-window/use-window-gesture-context.ts +44 -0
  199. package/src/web/components/floating-window/use-window-keyboard.ts +55 -0
  200. package/src/web/components/floating-window/use-window-resize.ts +30 -0
  201. package/src/web/components/floating-window/window-chrome-contract.ts +38 -0
  202. package/src/web/components/floating-window/window-content-registry.ts +51 -0
  203. package/src/web/components/floating-window/window-geometry.ts +121 -0
  204. package/src/web/components/floating-window/window-layer.tsx +92 -0
  205. package/src/web/components/floating-window/window-persistence.ts +104 -0
  206. package/src/web/components/floating-window/window-resize-handles.tsx +81 -0
  207. package/src/web/components/floating-window/window-store-types.ts +20 -0
  208. package/src/web/components/floating-window/window-store.ts +192 -0
  209. package/src/web/components/layout/command-palette.tsx +10 -0
  210. package/src/web/components/layout/mobile-drawer.tsx +11 -2
  211. package/src/web/components/layout/nav-section-rail.tsx +7 -1
  212. package/src/web/components/os-explorer/actions/explorer-actions-clipboard.ts +186 -0
  213. package/src/web/components/os-explorer/actions/explorer-actions-mutate.ts +109 -0
  214. package/src/web/components/os-explorer/actions/explorer-actions-open.ts +67 -0
  215. package/src/web/components/os-explorer/actions/explorer-actions-transfer-helpers.ts +35 -0
  216. package/src/web/components/os-explorer/actions/use-explorer-actions.ts +205 -0
  217. package/src/web/components/os-explorer/can-open-in-ppm.ts +89 -0
  218. package/src/web/components/os-explorer/dnd/drag-depth-counter.ts +36 -0
  219. package/src/web/components/os-explorer/dnd/drag-ghost.ts +44 -0
  220. package/src/web/components/os-explorer/dnd/drop-target-decision.ts +46 -0
  221. package/src/web/components/os-explorer/dnd/drop-target-style.ts +7 -0
  222. package/src/web/components/os-explorer/dnd/entry-drag-payload.ts +115 -0
  223. package/src/web/components/os-explorer/dnd/entry-drag-state.ts +35 -0
  224. package/src/web/components/os-explorer/dnd/entry-drop-executor.ts +43 -0
  225. package/src/web/components/os-explorer/dnd/use-drag-auto-scroll.ts +70 -0
  226. package/src/web/components/os-explorer/dnd/use-drop-transfer.tsx +82 -0
  227. package/src/web/components/os-explorer/dnd/use-entry-drag-source.ts +73 -0
  228. package/src/web/components/os-explorer/dnd/use-entry-drop-target.ts +150 -0
  229. package/src/web/components/os-explorer/dnd/use-entry-row-dnd.ts +66 -0
  230. package/src/web/components/os-explorer/dnd/use-path-drop-target.ts +30 -0
  231. package/src/web/components/os-explorer/explorer-body.tsx +153 -0
  232. package/src/web/components/os-explorer/explorer-breadcrumb.tsx +108 -0
  233. package/src/web/components/os-explorer/explorer-context-menu.tsx +131 -0
  234. package/src/web/components/os-explorer/explorer-dialogs.tsx +103 -0
  235. package/src/web/components/os-explorer/explorer-modal-shell.tsx +60 -0
  236. package/src/web/components/os-explorer/explorer-pins-store.ts +63 -0
  237. package/src/web/components/os-explorer/explorer-sidebar.tsx +198 -0
  238. package/src/web/components/os-explorer/explorer-sort-menu.tsx +68 -0
  239. package/src/web/components/os-explorer/explorer-status-bar.tsx +35 -0
  240. package/src/web/components/os-explorer/explorer-store.ts +179 -0
  241. package/src/web/components/os-explorer/explorer-toolbar.tsx +139 -0
  242. package/src/web/components/os-explorer/explorer-window-content.tsx +36 -0
  243. package/src/web/components/os-explorer/format-file-meta.ts +74 -0
  244. package/src/web/components/os-explorer/icons/file-type-icon-map.ts +106 -0
  245. package/src/web/components/os-explorer/icons/file-type-icon.tsx +56 -0
  246. package/src/web/components/os-explorer/icons/thumbnail-fetch-semaphore.ts +44 -0
  247. package/src/web/components/os-explorer/icons/thumbnail-image.tsx +124 -0
  248. package/src/web/components/os-explorer/mobile/mobile-bottom-toolbar.tsx +102 -0
  249. package/src/web/components/os-explorer/mobile/mobile-explorer-sheet.tsx +61 -0
  250. package/src/web/components/os-explorer/mobile/mobile-explorer-top-bar.tsx +41 -0
  251. package/src/web/components/os-explorer/mobile/mobile-more-sheet.tsx +117 -0
  252. package/src/web/components/os-explorer/mobile/mobile-places-sheet.tsx +120 -0
  253. package/src/web/components/os-explorer/mobile/mobile-places-strip.tsx +109 -0
  254. package/src/web/components/os-explorer/mobile/mobile-tap-action.ts +19 -0
  255. package/src/web/components/os-explorer/mobile/use-mobile-row-tap.ts +50 -0
  256. package/src/web/components/os-explorer/open-explorer.ts +35 -0
  257. package/src/web/components/os-explorer/properties-dialog.tsx +99 -0
  258. package/src/web/components/os-explorer/skins/explorer-skin-chrome.tsx +17 -0
  259. package/src/web/components/os-explorer/skins/folder-icon-macos.tsx +42 -0
  260. package/src/web/components/os-explorer/skins/folder-icon-windows.tsx +25 -0
  261. package/src/web/components/os-explorer/skins/macos-skin.ts +14 -0
  262. package/src/web/components/os-explorer/skins/macos-window-chrome.tsx +69 -0
  263. package/src/web/components/os-explorer/skins/skin-types.ts +40 -0
  264. package/src/web/components/os-explorer/skins/skins.css +25 -0
  265. package/src/web/components/os-explorer/skins/use-explorer-skin.ts +21 -0
  266. package/src/web/components/os-explorer/skins/windows-skin.ts +11 -0
  267. package/src/web/components/os-explorer/skins/windows-window-chrome.tsx +56 -0
  268. package/src/web/components/os-explorer/sort-and-filter-entries.ts +52 -0
  269. package/src/web/components/os-explorer/sort-options.ts +29 -0
  270. package/src/web/components/os-explorer/toolbar-icon-button.ts +18 -0
  271. package/src/web/components/os-explorer/use-coarse-long-press.ts +97 -0
  272. package/src/web/components/os-explorer/use-explorer-keyboard.ts +124 -0
  273. package/src/web/components/os-explorer/use-explorer-navigation.ts +155 -0
  274. package/src/web/components/os-explorer/use-explorer-open-state.ts +67 -0
  275. package/src/web/components/os-explorer/use-host-info.ts +85 -0
  276. package/src/web/components/os-explorer/views/column-row.tsx +126 -0
  277. package/src/web/components/os-explorer/views/column-view-column.tsx +112 -0
  278. package/src/web/components/os-explorer/views/column-view-mobile.tsx +98 -0
  279. package/src/web/components/os-explorer/views/column-view-preview.tsx +70 -0
  280. package/src/web/components/os-explorer/views/column-view.tsx +204 -0
  281. package/src/web/components/os-explorer/views/compose-interactive-row-props.ts +77 -0
  282. package/src/web/components/os-explorer/views/explorer-view-registry.tsx +55 -0
  283. package/src/web/components/os-explorer/views/icons-view-tile.tsx +158 -0
  284. package/src/web/components/os-explorer/views/icons-view.tsx +188 -0
  285. package/src/web/components/os-explorer/views/inline-name-input.tsx +60 -0
  286. package/src/web/components/os-explorer/views/list-row.tsx +162 -0
  287. package/src/web/components/os-explorer/views/list-view.tsx +177 -0
  288. package/src/web/components/os-explorer/views/use-column-view-state.ts +158 -0
  289. package/src/web/components/os-explorer/views/use-entry-selection.ts +178 -0
  290. package/src/web/components/settings/settings-tab.tsx +29 -2
  291. package/src/web/components/sqlite/sqlite-viewer.tsx +5 -2
  292. package/src/web/components/sqlite/use-sqlite.ts +7 -2
  293. package/src/web/components/ui/adaptive-context-menu.tsx +57 -1
  294. package/src/web/components/ui/file-browser-picker.tsx +1 -18
  295. package/src/web/hooks/use-chat.ts +22 -4
  296. package/src/web/lib/file-download.ts +6 -4
  297. package/src/web/lib/fs-api.ts +185 -0
  298. package/src/web/stores/file-store.ts +38 -1
  299. package/src/web/stores/settings-store.ts +14 -0
  300. package/src/web/styles/globals.css +1 -0
  301. package/dist/web/assets/api-client-RtNXvS0P.js +0 -1
  302. package/dist/web/assets/api-settings-De--HNHp.js +0 -1
  303. package/dist/web/assets/architecture-PBZL5I3N-DVRYSsQn.js +0 -1
  304. package/dist/web/assets/chat-tab-D2nZCpAo.js +0 -13
  305. package/dist/web/assets/code-editor-DqQy2Qm8.js +0 -10
  306. package/dist/web/assets/context-menu-DIiZdfbE.js +0 -1
  307. package/dist/web/assets/csv-preview-BL0I3CKz.js +0 -2
  308. package/dist/web/assets/dialog-HHdNInEH.js +0 -1
  309. package/dist/web/assets/diff-viewer-_yQtutHR.js +0 -4
  310. package/dist/web/assets/git-log-panel-NkghB_rO.js +0 -1
  311. package/dist/web/assets/gitGraph-HDMCJU4V-CutkUNY_.js +0 -1
  312. package/dist/web/assets/group-chat-tab-CQOVBmVp.js +0 -1
  313. package/dist/web/assets/index-CJ0Wp_rW.js +0 -50
  314. package/dist/web/assets/index-CVJmlKhp.css +0 -2
  315. package/dist/web/assets/info-3K5VOQVL-BpNjgbj9.js +0 -1
  316. package/dist/web/assets/keybindings-store-ClNYe9vD.js +0 -1
  317. package/dist/web/assets/markdown-renderer-CwpP5Ola.js +0 -1
  318. package/dist/web/assets/notification-store-DwAhNzTy.js +0 -1
  319. package/dist/web/assets/packet-RMMSAZCW-D5IUZ66-.js +0 -1
  320. package/dist/web/assets/pie-UPGHQEXC-CM29eKDR.js +0 -1
  321. package/dist/web/assets/radar-KQ55EAFF-QtJGaSGt.js +0 -1
  322. package/dist/web/assets/settings-store-B3LfpCPa.js +0 -2
  323. package/dist/web/assets/settings-tab-CeSJQIfF.js +0 -1
  324. package/dist/web/assets/sparkles-B3DmG8PJ.js +0 -1
  325. package/dist/web/assets/sqlite-viewer-8fk_wut8.js +0 -1
  326. package/dist/web/assets/tool-cards-C3ka1Y7I.js +0 -7
  327. package/dist/web/assets/treemap-KZPCXAKY-CjUqpVnS.js +0 -1
  328. /package/dist/web/assets/{abap-BM5PMK0-.js → abap-C1K0-wzc.js} +0 -0
  329. /package/dist/web/assets/{actionscript-3-CML-MTNy.js → actionscript-3-CJhQVjLA.js} +0 -0
  330. /package/dist/web/assets/{ada-DzO1tMqV.js → ada-Bt8r9fME.js} +0 -0
  331. /package/dist/web/assets/{andromeeda-C3nkvRhj.js → andromeeda-DF1I8qi3.js} +0 -0
  332. /package/dist/web/assets/{apache-Dg7oWQbs.js → apache-CnlleE6P.js} +0 -0
  333. /package/dist/web/assets/{apex-3O2170Ju.js → apex-j0C6Xmk6.js} +0 -0
  334. /package/dist/web/assets/{applescript-5AlzBqQO.js → applescript-DO7AnO8U.js} +0 -0
  335. /package/dist/web/assets/{apply-theme-BSJDABU3.js → apply-theme-CMQXnUAa.js} +0 -0
  336. /package/dist/web/assets/{ara-BGtOX5Hn.js → ara-i83AydZj.js} +0 -0
  337. /package/dist/web/assets/{asciidoc-CIsC4kkq.js → asciidoc-DbBA6-sF.js} +0 -0
  338. /package/dist/web/assets/{asm-p1-PUkh3.js → asm-B5S47Rgr.js} +0 -0
  339. /package/dist/web/assets/{aurora-x-BPgGL50S.js → aurora-x-De_IaSKw.js} +0 -0
  340. /package/dist/web/assets/{awk-Cj93pRL8.js → awk-CfyLHXqS.js} +0 -0
  341. /package/dist/web/assets/{ayu-dark-C50MYKhw.js → ayu-dark-DTLdZ1Si.js} +0 -0
  342. /package/dist/web/assets/{ayu-light-DyIp0Idy.js → ayu-light-DTOfkzhu.js} +0 -0
  343. /package/dist/web/assets/{ayu-mirage-BAdm8pKU.js → ayu-mirage-DsAECCMv.js} +0 -0
  344. /package/dist/web/assets/{ballerina-DUO9mwyV.js → ballerina-CumGp9A7.js} +0 -0
  345. /package/dist/web/assets/{bat-Cg8hlSct.js → bat-Ca2SBbYN.js} +0 -0
  346. /package/dist/web/assets/{beancount-f8f3BBqB.js → beancount-CqyXBwwF.js} +0 -0
  347. /package/dist/web/assets/{berry-BqVQYZZr.js → berry-yl-kJr_H.js} +0 -0
  348. /package/dist/web/assets/{bibtex-C_q8ygAM.js → bibtex-DoFFszjV.js} +0 -0
  349. /package/dist/web/assets/{bicep-DWS-2uWR.js → bicep-CWPi4nfK.js} +0 -0
  350. /package/dist/web/assets/{bird2-C0pvipi_.js → bird2-DXew-ut0.js} +0 -0
  351. /package/dist/web/assets/{bot-E9mcVZnr.js → bot-BHXjpQ7x.js} +0 -0
  352. /package/dist/web/assets/{c-BQFvJ6Ux.js → c-clbySDvd.js} +0 -0
  353. /package/dist/web/assets/{c3-Da53KeG6.js → c3-B65jvSM1.js} +0 -0
  354. /package/dist/web/assets/{cadence-B5X2vWm3.js → cadence-Cm8tQTHN.js} +0 -0
  355. /package/dist/web/assets/{catppuccin-frappe-Dm3rVY3b.js → catppuccin-frappe-DLeGslh_.js} +0 -0
  356. /package/dist/web/assets/{catppuccin-latte-ZxS-ga_K.js → catppuccin-latte-CR5GeHws.js} +0 -0
  357. /package/dist/web/assets/{catppuccin-macchiato-B0bAzXh0.js → catppuccin-macchiato-p-XgjxhP.js} +0 -0
  358. /package/dist/web/assets/{catppuccin-mocha-BeMC5hqi.js → catppuccin-mocha-B8QOAZLl.js} +0 -0
  359. /package/dist/web/assets/{chevron-right-DeUue2aK.js → chevron-right-CtcHmZg9.js} +0 -0
  360. /package/dist/web/assets/{circle-question-mark-PaJgx-3d.js → circle-question-mark-EVgisosn.js} +0 -0
  361. /package/dist/web/assets/{clarity-BRdirlsw.js → clarity-DPulbvKH.js} +0 -0
  362. /package/dist/web/assets/{clojure-pSLH-KQp.js → clojure-DFuWS20u.js} +0 -0
  363. /package/dist/web/assets/{cmake-DsZu4U4F.js → cmake-DejCqcu4.js} +0 -0
  364. /package/dist/web/assets/{code-TekEnDFM.js → code-Dupqw5Fr.js} +0 -0
  365. /package/dist/web/assets/{codeowners-CtkKTnsH.js → codeowners-BwAyqWIH.js} +0 -0
  366. /package/dist/web/assets/{codeql-BpP1PDrj.js → codeql-DgSwFjqI.js} +0 -0
  367. /package/dist/web/assets/{common-lisp-BX1XgHTt.js → common-lisp-CxIVJCtf.js} +0 -0
  368. /package/dist/web/assets/{coq-D2bX6-8g.js → coq-DLSjSnmf.js} +0 -0
  369. /package/dist/web/assets/{csharp-DcR97P0D.js → csharp-C1HHzXBp.js} +0 -0
  370. /package/dist/web/assets/{css-CIjciIIk.js → css-VXsMY--y.js} +0 -0
  371. /package/dist/web/assets/{csv-DW48Z5d-.js → csv-BEbcJdHz.js} +0 -0
  372. /package/dist/web/assets/{csv-parser-DVHBcvuE.js → csv-parser-DHvoTjMF.js} +0 -0
  373. /package/dist/web/assets/{cue-Byh1xHko.js → cue-BkDnFqUD.js} +0 -0
  374. /package/dist/web/assets/{cypher-TVlMMWma.js → cypher-1cMqojSQ.js} +0 -0
  375. /package/dist/web/assets/{d-CxaScvxf.js → d-BnYjRXtH.js} +0 -0
  376. /package/dist/web/assets/{dark-plus-sn-FFTT1.js → dark-plus-XfbaH7kZ.js} +0 -0
  377. /package/dist/web/assets/{dart-BmpakMe-.js → dart-Ca7s-8hK.js} +0 -0
  378. /package/dist/web/assets/{data-grid-types-BuMHLKXV.js → data-grid-types-DP-ZexEN.js} +0 -0
  379. /package/dist/web/assets/{database-COYAMZaw.js → database-Dj0DxgtX.js} +0 -0
  380. /package/dist/web/assets/{dax-B1aRUMXT.js → dax-CmuOw-mY.js} +0 -0
  381. /package/dist/web/assets/{desktop-C6lD62ar.js → desktop-C2gJ6Ovb.js} +0 -0
  382. /package/dist/web/assets/{diff-CupGmT1a.js → diff-BCEo1Ej7.js} +0 -0
  383. /package/dist/web/assets/{dist-Bi4gRyhr.js → dist-CipvJy9w.js} +0 -0
  384. /package/dist/web/assets/{dist-m_oJqIDk.js → dist-D__U4ZJz.js} +0 -0
  385. /package/dist/web/assets/{docker-DjDr3TJF.js → docker-DN2jlyAh.js} +0 -0
  386. /package/dist/web/assets/{dotenv-QeT1SLTv.js → dotenv-NExMY2kS.js} +0 -0
  387. /package/dist/web/assets/{dracula-yI5kpKp5.js → dracula-B9lbE01y.js} +0 -0
  388. /package/dist/web/assets/{dracula-soft-CYF6cJce.js → dracula-soft-CMBBfKF_.js} +0 -0
  389. /package/dist/web/assets/{dream-maker-TBDKiHrV.js → dream-maker-DEyDwFsd.js} +0 -0
  390. /package/dist/web/assets/{emacs-lisp-B7aZTnJ_.js → emacs-lisp-D_qP2zS6.js} +0 -0
  391. /package/dist/web/assets/{everforest-dark-CN77B1NJ.js → everforest-dark-DbHa2U-p.js} +0 -0
  392. /package/dist/web/assets/{everforest-light-CyFxGMIs.js → everforest-light-BISkJchP.js} +0 -0
  393. /package/dist/web/assets/{fennel-C6ktGUzp.js → fennel-6B22SfJR.js} +0 -0
  394. /package/dist/web/assets/{file-exclamation-point-DBEC-Kst.js → file-exclamation-point-D-ZORzYB.js} +0 -0
  395. /package/dist/web/assets/{fish-Vr62C2vP.js → fish-CubIIvJD.js} +0 -0
  396. /package/dist/web/assets/{fluent-CH3IJUki.js → fluent-DF55zQ09.js} +0 -0
  397. /package/dist/web/assets/{fortran-free-form-BN7VmmxZ.js → fortran-free-form-DvOu8jAt.js} +0 -0
  398. /package/dist/web/assets/{gdscript-BYdRNu_P.js → gdscript-DCPxdLpq.js} +0 -0
  399. /package/dist/web/assets/{gdshader-C2XOq90k.js → gdshader-CTZ381FO.js} +0 -0
  400. /package/dist/web/assets/{genie-B4hkIXNU.js → genie-C_QDtvgU.js} +0 -0
  401. /package/dist/web/assets/{gherkin-CW9NH2DW.js → gherkin-BcvK42tF.js} +0 -0
  402. /package/dist/web/assets/{github-dark-BWCf99kM.js → github-dark-C9afs_4w.js} +0 -0
  403. /package/dist/web/assets/{github-dark-default-DZ1m_6OP.js → github-dark-default-CKGVrl3Z.js} +0 -0
  404. /package/dist/web/assets/{github-dark-dimmed-CUXSQ8bS.js → github-dark-dimmed-C3dQZ_LC.js} +0 -0
  405. /package/dist/web/assets/{github-dark-high-contrast-B6BvU8H-.js → github-dark-high-contrast-DW78QukY.js} +0 -0
  406. /package/dist/web/assets/{github-light-Ch-E92cy.js → github-light-BnP2dznS.js} +0 -0
  407. /package/dist/web/assets/{github-light-default-CKFslV7i.js → github-light-default-C2fPZzPG.js} +0 -0
  408. /package/dist/web/assets/{github-light-high-contrast-DiJVeRlZ.js → github-light-high-contrast-BzIuUFR2.js} +0 -0
  409. /package/dist/web/assets/{gleam-D4dP7V5M.js → gleam-BpeKwEIO.js} +0 -0
  410. /package/dist/web/assets/{gn-DuO2D2eW.js → gn-nUb_Mit0.js} +0 -0
  411. /package/dist/web/assets/{gnuplot-Df_8pFbI.js → gnuplot-D7I0v20p.js} +0 -0
  412. /package/dist/web/assets/{go-BL16cMJO.js → go-D7Qqska7.js} +0 -0
  413. /package/dist/web/assets/{groovy-rfHeCRqy.js → groovy-DS-pne5-.js} +0 -0
  414. /package/dist/web/assets/{gruvbox-dark-hard-CLbDN-E3.js → gruvbox-dark-hard-C0W01fsq.js} +0 -0
  415. /package/dist/web/assets/{gruvbox-dark-medium-Df0L0qje.js → gruvbox-dark-medium-Bqo6fQbg.js} +0 -0
  416. /package/dist/web/assets/{gruvbox-dark-soft-DV6TAcen.js → gruvbox-dark-soft-D-XSM_fu.js} +0 -0
  417. /package/dist/web/assets/{gruvbox-light-hard-CWXUzp9b.js → gruvbox-light-hard-IVAwMJRl.js} +0 -0
  418. /package/dist/web/assets/{gruvbox-light-medium-BOHMe1-7.js → gruvbox-light-medium-38ATiG7i.js} +0 -0
  419. /package/dist/web/assets/{gruvbox-light-soft-DrrS2sdV.js → gruvbox-light-soft-DnZr3c_0.js} +0 -0
  420. /package/dist/web/assets/{haskell-DybKb9uW.js → haskell-uQcywkDH.js} +0 -0
  421. /package/dist/web/assets/{haxe-DLRwZxmt.js → haxe-c6bI4_GT.js} +0 -0
  422. /package/dist/web/assets/{hcl-CusCzwOk.js → hcl-CQXTiEXq.js} +0 -0
  423. /package/dist/web/assets/{hjson-BygWIJ-3.js → hjson-ChETf2bz.js} +0 -0
  424. /package/dist/web/assets/{hlsl-DCKvuEyZ.js → hlsl-BMC4JGoE.js} +0 -0
  425. /package/dist/web/assets/{horizon-DSOVAzyH.js → horizon-BusFlhLW.js} +0 -0
  426. /package/dist/web/assets/{horizon-bright-DKfVjGj_.js → horizon-bright-2oD0Mz7W.js} +0 -0
  427. /package/dist/web/assets/{houston-Ddm8AgpV.js → houston-DdbbjqFg.js} +0 -0
  428. /package/dist/web/assets/{hy-DzZa6alE.js → hy-D_SOuqw9.js} +0 -0
  429. /package/dist/web/assets/{image-gallery-CObzTisL.js → image-gallery-BWFpZAAP.js} +0 -0
  430. /package/dist/web/assets/{imba-aiXalPnK.js → imba-BxLOHO5I.js} +0 -0
  431. /package/dist/web/assets/{ini-CAvrVa5R.js → ini-ox-CFcg0.js} +0 -0
  432. /package/dist/web/assets/{java-PRMSQp24.js → java-Bzo8yIal.js} +0 -0
  433. /package/dist/web/assets/{javascript-DQR6GQKs.js → javascript-DHuz9VXn.js} +0 -0
  434. /package/dist/web/assets/{json-uWUKqOxq.js → json-0_y80FD5.js} +0 -0
  435. /package/dist/web/assets/{json5-R_LXJXL0.js → json5-CEQ50pGM.js} +0 -0
  436. /package/dist/web/assets/{jsonc-tC5zvrPO.js → jsonc-CfrLEAKA.js} +0 -0
  437. /package/dist/web/assets/{jsonl-BAwnWh7U.js → jsonl-fKbrANC2.js} +0 -0
  438. /package/dist/web/assets/{jsonnet-CPj4HCRm.js → jsonnet-DKbkPaQ2.js} +0 -0
  439. /package/dist/web/assets/{jssm-B7HswxOM.js → jssm-Dxxx1Hqu.js} +0 -0
  440. /package/dist/web/assets/{jsx-z4TGELE1.js → jsx-DlJL-Oj3.js} +0 -0
  441. /package/dist/web/assets/{kanagawa-dragon-BpeLlraV.js → kanagawa-dragon-CwN4SV1c.js} +0 -0
  442. /package/dist/web/assets/{kanagawa-lotus-CLnIPAGs.js → kanagawa-lotus-BHltayiE.js} +0 -0
  443. /package/dist/web/assets/{kanagawa-wave-BglPniBb.js → kanagawa-wave-D-KXPjw6.js} +0 -0
  444. /package/dist/web/assets/{kdl-B6blIqLq.js → kdl-DvtoJdFo.js} +0 -0
  445. /package/dist/web/assets/{kotlin-DVAEYiwY.js → kotlin-CTS4MLcx.js} +0 -0
  446. /package/dist/web/assets/{kusto-Ba87977j.js → kusto-HtSE_sKm.js} +0 -0
  447. /package/dist/web/assets/{laserwave-C-NuzoMp.js → laserwave-DaXZG9ge.js} +0 -0
  448. /package/dist/web/assets/{lean-CJ_KLkrJ.js → lean-BYtGUfWx.js} +0 -0
  449. /package/dist/web/assets/{less-Dfn9YC_2.js → less-BoxmU_Mk.js} +0 -0
  450. /package/dist/web/assets/{lib-DTaN9riD.js → lib-Bpbn00xM.js} +0 -0
  451. /package/dist/web/assets/{libesm-DdtEjhIi.js → libesm-tR4XlhMj.js} +0 -0
  452. /package/dist/web/assets/{light-plus-B3BLlguG.js → light-plus-Bt5CyUuo.js} +0 -0
  453. /package/dist/web/assets/{llvm-6UDP3NQb.js → llvm-CSdk9q9V.js} +0 -0
  454. /package/dist/web/assets/{log-QW3dqr1D.js → log-B-kp_3CL.js} +0 -0
  455. /package/dist/web/assets/{logo-DUinJheI.js → logo-DdIsXFDO.js} +0 -0
  456. /package/dist/web/assets/{luau-B1vcBzl8.js → luau-DUBpLlzQ.js} +0 -0
  457. /package/dist/web/assets/{make-CqNL10gS.js → make-B3JVjoW_.js} +0 -0
  458. /package/dist/web/assets/{markdown-BQNMNiYS.js → markdown-Seon0vHs.js} +0 -0
  459. /package/dist/web/assets/{material-theme-rbV8EefR.js → material-theme-Nq-ChX1P.js} +0 -0
  460. /package/dist/web/assets/{material-theme-darker-BZrskvoo.js → material-theme-darker-CPV4ayXJ.js} +0 -0
  461. /package/dist/web/assets/{material-theme-lighter-B0CBBjBw.js → material-theme-lighter-0kyjYqEd.js} +0 -0
  462. /package/dist/web/assets/{material-theme-ocean-CX_CHnQq.js → material-theme-ocean-DGpAp5co.js} +0 -0
  463. /package/dist/web/assets/{material-theme-palenight-ztiOCPbw.js → material-theme-palenight-B0AUn0NG.js} +0 -0
  464. /package/dist/web/assets/{matlab-tHQDNC9G.js → matlab-C2waytxs.js} +0 -0
  465. /package/dist/web/assets/{mdx-D4kZ6c6G.js → mdx-DAis6R6I.js} +0 -0
  466. /package/dist/web/assets/{mermaid-DlR4U4Pe.js → mermaid-_rnT2YGD.js} +0 -0
  467. /package/dist/web/assets/{min-dark-BX-xHAD2.js → min-dark-BSSjchUB.js} +0 -0
  468. /package/dist/web/assets/{min-light-Bxw0_Gqq.js → min-light-DomAFQsa.js} +0 -0
  469. /package/dist/web/assets/{mipsasm-DYyZAum-.js → mipsasm-bBgtvPyG.js} +0 -0
  470. /package/dist/web/assets/{mojo-q9wuEYKR.js → mojo-Cp9BayW0.js} +0 -0
  471. /package/dist/web/assets/{monokai-D9vrJ8JM.js → monokai-CL_9gbmn.js} +0 -0
  472. /package/dist/web/assets/{moonbit-C9roWxMb.js → moonbit-BS_fcr-P.js} +0 -0
  473. /package/dist/web/assets/{move-BvhjG2ic.js → move-C79AH45U.js} +0 -0
  474. /package/dist/web/assets/{narrat-BXGbPwG3.js → narrat-CJ5s3BDf.js} +0 -0
  475. /package/dist/web/assets/{nextflow-groovy-CMy5-Z4k.js → nextflow-groovy-ZHa4JrPJ.js} +0 -0
  476. /package/dist/web/assets/{night-owl-CBQBcbmw.js → night-owl-Jkf9zFQK.js} +0 -0
  477. /package/dist/web/assets/{night-owl-light-CC-brflp.js → night-owl-light-DRPeaG5J.js} +0 -0
  478. /package/dist/web/assets/{nix-B9EAdptu.js → nix-D2Jet9DN.js} +0 -0
  479. /package/dist/web/assets/{nord-DxASd4qG.js → nord-CREVs22j.js} +0 -0
  480. /package/dist/web/assets/{nushell-BsY59i7N.js → nushell-CAiDi_mR.js} +0 -0
  481. /package/dist/web/assets/{objective-c-CoeQAcnP.js → objective-c-CVkmJkC1.js} +0 -0
  482. /package/dist/web/assets/{objective-cpp-BysdFvND.js → objective-cpp-DIKDO1Ly.js} +0 -0
  483. /package/dist/web/assets/{ocaml-CrtQYMMK.js → ocaml-R9qtGQhs.js} +0 -0
  484. /package/dist/web/assets/{odin-B8pz4gIL.js → odin-DTYNQqVr.js} +0 -0
  485. /package/dist/web/assets/{one-dark-pro-3sSHqoqQ.js → one-dark-pro-BSLWUJn5.js} +0 -0
  486. /package/dist/web/assets/{one-light-LUZAvT8g.js → one-light-DbkRXG3t.js} +0 -0
  487. /package/dist/web/assets/{openscad-DcKia-sV.js → openscad-BlPcSnmT.js} +0 -0
  488. /package/dist/web/assets/{pascal-zM5SlmgF.js → pascal-B1Y46ZZB.js} +0 -0
  489. /package/dist/web/assets/{pkl-C_r_zLLt.js → pkl-BhJSJbFv.js} +0 -0
  490. /package/dist/web/assets/{plastic-B3cRtgKD.js → plastic-BzxsCTpi.js} +0 -0
  491. /package/dist/web/assets/{plsql-BzyjheXU.js → plsql-DBba7dyP.js} +0 -0
  492. /package/dist/web/assets/{plus-DcuJuDC3.js → plus-Dm36mgLh.js} +0 -0
  493. /package/dist/web/assets/{po-Dz4OaDNi.js → po-BvgLlnNo.js} +0 -0
  494. /package/dist/web/assets/{poimandres-BBbtYwmR.js → poimandres-DUaI_1JP.js} +0 -0
  495. /package/dist/web/assets/{polar-Che1XC2Z.js → polar-C7uILwJn.js} +0 -0
  496. /package/dist/web/assets/{postcss-DouzwG4F.js → postcss-BgJlpFdw.js} +0 -0
  497. /package/dist/web/assets/{powerquery-YOdcTZmd.js → powerquery-Dn1MIpZu.js} +0 -0
  498. /package/dist/web/assets/{powershell-8ojzYH34.js → powershell-Bo-DYzOS.js} +0 -0
  499. /package/dist/web/assets/{prisma-DCmjceML.js → prisma-CTLs5IdT.js} +0 -0
  500. /package/dist/web/assets/{prolog-ByNNz2pB.js → prolog-QRGun3eG.js} +0 -0
  501. /package/dist/web/assets/{proto-DWMt6Qu1.js → proto-B7PI7apn.js} +0 -0
  502. /package/dist/web/assets/{puppet-osfKyZp4.js → puppet-CBq0tLrP.js} +0 -0
  503. /package/dist/web/assets/{purescript-ClIblkvh.js → purescript-DFewOQb2.js} +0 -0
  504. /package/dist/web/assets/{python-Ctyr4faP.js → python-iWuxKXvT.js} +0 -0
  505. /package/dist/web/assets/{qmldir-CbNgyhnI.js → qmldir-cXiW3AsF.js} +0 -0
  506. /package/dist/web/assets/{qss-LbRHzb21.js → qss-DASwAbBL.js} +0 -0
  507. /package/dist/web/assets/{r-Dvfjp0wc.js → r-TU2eaIPw.js} +0 -0
  508. /package/dist/web/assets/{racket-DI8v8nzD.js → racket-SkRKqrLY.js} +0 -0
  509. /package/dist/web/assets/{raku-CX1q9GW0.js → raku-D31lthkZ.js} +0 -0
  510. /package/dist/web/assets/{react-8hrD3-kv.js → react-DjdYfcEe.js} +0 -0
  511. /package/dist/web/assets/{red-CSz3QEOw.js → red-CTcQZevb.js} +0 -0
  512. /package/dist/web/assets/{reg-FMjhUQE-.js → reg-D8YAsTGf.js} +0 -0
  513. /package/dist/web/assets/{regexp-CCSe1Fc4.js → regexp-CD2uvAWx.js} +0 -0
  514. /package/dist/web/assets/{rel-Ce0UO-OB.js → rel-CAaI-1fg.js} +0 -0
  515. /package/dist/web/assets/{resolve-theme-B9Mgd5GG.js → resolve-theme-B0eotaPq.js} +0 -0
  516. /package/dist/web/assets/{riscv-BFZrdZtB.js → riscv-DR-hJVIj.js} +0 -0
  517. /package/dist/web/assets/{ron-D0t4kvJG.js → ron-CuUCJ0n4.js} +0 -0
  518. /package/dist/web/assets/{rose-pine-HzwmOzHM.js → rose-pine-aFHxW48i.js} +0 -0
  519. /package/dist/web/assets/{rose-pine-dawn-CSp9xAF9.js → rose-pine-dawn-Bqz2sBRY.js} +0 -0
  520. /package/dist/web/assets/{rose-pine-moon-Cnzr2Cw0.js → rose-pine-moon-wqyh0an4.js} +0 -0
  521. /package/dist/web/assets/{rosmsg-DEJ8Snbv.js → rosmsg-CI1ywimO.js} +0 -0
  522. /package/dist/web/assets/{rust-2jBzrC0l.js → rust-p7Imk4G_.js} +0 -0
  523. /package/dist/web/assets/{sass-DD75Izu_.js → sass-C8JfaqCV.js} +0 -0
  524. /package/dist/web/assets/{save-BM4p9_9n.js → save-ignW_jk2.js} +0 -0
  525. /package/dist/web/assets/{scala-DpBKROIu.js → scala-DNxCW1By.js} +0 -0
  526. /package/dist/web/assets/{scheme-DM2jzwUK.js → scheme-BYuUPJoL.js} +0 -0
  527. /package/dist/web/assets/{sdbl-C34Cg6e7.js → sdbl-DbPeJPUr.js} +0 -0
  528. /package/dist/web/assets/{shellscript-DxfzKSgU.js → shellscript-DMiHlR3q.js} +0 -0
  529. /package/dist/web/assets/{shield-check-C3qYSU8a.js → shield-check-BSA9P3nI.js} +0 -0
  530. /package/dist/web/assets/{shield-off-D5tU7gQT.js → shield-off-Cb9J9x_n.js} +0 -0
  531. /package/dist/web/assets/{slack-dark-DIIV3bpD.js → slack-dark-C4xGcQXI.js} +0 -0
  532. /package/dist/web/assets/{slack-ochin-BTkxWjEP.js → slack-ochin-BzgRt_wm.js} +0 -0
  533. /package/dist/web/assets/{smalltalk-Bm0qg6SA.js → smalltalk-LDeL9PYH.js} +0 -0
  534. /package/dist/web/assets/{snazzy-light-ClAuuhn4.js → snazzy-light-CXE7a5j_.js} +0 -0
  535. /package/dist/web/assets/{solarized-dark-93sEWmYT.js → solarized-dark-DgUhY74x.js} +0 -0
  536. /package/dist/web/assets/{solarized-light-C74FvgcO.js → solarized-light-DD9C-H-9.js} +0 -0
  537. /package/dist/web/assets/{solidity-H9fSjkQP.js → solidity-CAbDB4D4.js} +0 -0
  538. /package/dist/web/assets/{splunk-CDTN2iAG.js → splunk-kQREPfIc.js} +0 -0
  539. /package/dist/web/assets/{sql-CoqObhgo.js → sql-CBzeNAD8.js} +0 -0
  540. /package/dist/web/assets/{ssh-config-C3Wv6qRp.js → ssh-config-L1euxrsM.js} +0 -0
  541. /package/dist/web/assets/{stylus-D0uTFXCy.js → stylus-DvBnYniP.js} +0 -0
  542. /package/dist/web/assets/{swift-DtMMgvRI.js → swift-DF5NDQp6.js} +0 -0
  543. /package/dist/web/assets/{synthwave-84-DAroyZBu.js → synthwave-84-DbBhB_Hq.js} +0 -0
  544. /package/dist/web/assets/{system-verilog-Bj7X_lq4.js → system-verilog-D8s2ZW_k.js} +0 -0
  545. /package/dist/web/assets/{systemd-CH8ApCUs.js → systemd-a5-XZJsG.js} +0 -0
  546. /package/dist/web/assets/{table-Di8pv2Y_.js → table-4P8kS7sg.js} +0 -0
  547. /package/dist/web/assets/{talonscript-70lVC3cw.js → talonscript-BLa0URTW.js} +0 -0
  548. /package/dist/web/assets/{tasl-WQR8VslV.js → tasl-DIoV4XcC.js} +0 -0
  549. /package/dist/web/assets/{tcl-caTR_frn.js → tcl-ztYAdXfQ.js} +0 -0
  550. /package/dist/web/assets/{terraform-CVRZ4SZ4.js → terraform-DvpCCiOZ.js} +0 -0
  551. /package/dist/web/assets/{tokyo-night-CDyT1jCI.js → tokyo-night-BkHlYUv0.js} +0 -0
  552. /package/dist/web/assets/{toml-B7D2mIDU.js → toml-acIrxos6.js} +0 -0
  553. /package/dist/web/assets/{tsv-2kdn5dqL.js → tsv-BJB5EVCT.js} +0 -0
  554. /package/dist/web/assets/{tsx-DJfG3fzg.js → tsx-B1MmXGT3.js} +0 -0
  555. /package/dist/web/assets/{turtle-DaQac_UT.js → turtle-DFceTiqd.js} +0 -0
  556. /package/dist/web/assets/{typescript-BLfAIchl.js → typescript-Dz9wU5Y1.js} +0 -0
  557. /package/dist/web/assets/{typespec-ymBaOi_c.js → typespec-CPuYZijj.js} +0 -0
  558. /package/dist/web/assets/{typst-DkvUYMT-.js → typst-CfsCIYv8.js} +0 -0
  559. /package/dist/web/assets/{use-is-mobile-BcuCjH19.js → use-is-mobile-K1a38BwI.js} +0 -0
  560. /package/dist/web/assets/{utils-E0yyGxXt.js → utils-B9H0d3Fh.js} +0 -0
  561. /package/dist/web/assets/{v-D4997FGs.js → v-CGo0jcXA.js} +0 -0
  562. /package/dist/web/assets/{vala-AFg9DmKE.js → vala-AsSR0hrb.js} +0 -0
  563. /package/dist/web/assets/{vb-DNUJ9fOP.js → vb-C7tvbXv1.js} +0 -0
  564. /package/dist/web/assets/{vendor-xterm-QDr0jvpJ.js → vendor-xterm-ClRVIJ-k.js} +0 -0
  565. /package/dist/web/assets/{verilog-BrnAQ3tF.js → verilog--a33ND-p.js} +0 -0
  566. /package/dist/web/assets/{vesper-DCZnFmY0.js → vesper-B_Z0h4pn.js} +0 -0
  567. /package/dist/web/assets/{vhdl-DoK4PjhE.js → vhdl-CWL5dZPN.js} +0 -0
  568. /package/dist/web/assets/{viml-D6EKG66q.js → viml-BglmT14Y.js} +0 -0
  569. /package/dist/web/assets/{vitesse-black-C6KILWdF.js → vitesse-black-RKFsSqQI.js} +0 -0
  570. /package/dist/web/assets/{vitesse-dark-BuSr6OT5.js → vitesse-dark-D7zDWNmc.js} +0 -0
  571. /package/dist/web/assets/{vitesse-light-M-eYyOoe.js → vitesse-light-MAp87W5b.js} +0 -0
  572. /package/dist/web/assets/{vyper-CwSN64Jn.js → vyper-CgCBYg1G.js} +0 -0
  573. /package/dist/web/assets/{wasm-BhQEkzil.js → wasm-BOG7ZeTT.js} +0 -0
  574. /package/dist/web/assets/{wasm-CVlf9Jwb.js → wasm-Bd258nS1.js} +0 -0
  575. /package/dist/web/assets/{wenyan-BC7irgM3.js → wenyan-DpShPKXZ.js} +0 -0
  576. /package/dist/web/assets/{wgsl-W-3UHMDO.js → wgsl-BakcCblK.js} +0 -0
  577. /package/dist/web/assets/{wikitext-T1DoFcm8.js → wikitext-NroRWVAO.js} +0 -0
  578. /package/dist/web/assets/{wit-DIrx_eCI.js → wit-B5CM2pg6.js} +0 -0
  579. /package/dist/web/assets/{wolfram-Cza4b443.js → wolfram-7MTFBJpR.js} +0 -0
  580. /package/dist/web/assets/{x-BsFLg-T8.js → x-BtzqXv1z.js} +0 -0
  581. /package/dist/web/assets/{yaml-DOZ10aZe.js → yaml-Bwr01G2K.js} +0 -0
  582. /package/dist/web/assets/{zenscript-DDAXkseY.js → zenscript-Dj8GATvi.js} +0 -0
  583. /package/dist/web/assets/{zig-CrzwMpQE.js → zig-LAE-fbS-.js} +0 -0
@@ -0,0 +1,87 @@
1
+ /** Windows Quick Access pinned folders via the Shell COM `Namespace`
2
+ * (`shell:::{679f85cb-...}`), verified live: ~150ms enumeration, and
3
+ * `System.Home.IsPinned` reliably separates pinned entries from "frequent"
4
+ * ones. Shell COM reports `.zip`/`.rar` archives as `IsFolder=true`, so
5
+ * every candidate is re-checked with a real directory stat before it ships. */
6
+ import * as fsp from "node:fs/promises";
7
+ import type { PinnedFolder } from "../../types/system.ts";
8
+ import { defaultRunner, type Runner } from "./spawn-runner.ts";
9
+
10
+ export interface QuickAccessDeps {
11
+ run: Runner;
12
+ isDirectory: (path: string) => Promise<boolean>;
13
+ }
14
+
15
+ const defaultDeps: QuickAccessDeps = {
16
+ run: defaultRunner,
17
+ isDirectory: async (p) => {
18
+ try {
19
+ return (await fsp.stat(p)).isDirectory();
20
+ } catch {
21
+ return false;
22
+ }
23
+ },
24
+ };
25
+
26
+ // `@($result)` forces an array even for 0/1 items — ConvertTo-Json unwraps a
27
+ // single-element pipeline input into a bare object otherwise.
28
+ const QUICK_ACCESS_SCRIPT = `
29
+ $items = (New-Object -ComObject Shell.Application).Namespace('shell:::{679f85cb-0220-4080-b29b-5540cc05aab6}').Items()
30
+ $result = foreach ($i in $items) {
31
+ if ($i.IsFolder) {
32
+ [PSCustomObject]@{ Name = $i.Name; Path = $i.Path; Pinned = $i.ExtendedProperty('System.Home.IsPinned') }
33
+ }
34
+ }
35
+ $arr = @($result)
36
+ $json = $arr | ConvertTo-Json -Compress
37
+ if ($arr.Count -le 1) { $json = '[' + $json + ']' }
38
+ Write-Output $json
39
+ `.trim();
40
+
41
+ interface RawItem {
42
+ Name?: string;
43
+ Path?: string;
44
+ Pinned?: boolean | string | null;
45
+ }
46
+
47
+ function isPinned(v: RawItem["Pinned"]): boolean {
48
+ return v === true || v === "True" || v === "true";
49
+ }
50
+
51
+ /** Read Quick Access pinned folders, appending any failure to the shared `warnings` array (never throws). */
52
+ export async function getWindowsQuickAccessPinned(
53
+ warnings: string[],
54
+ overrides: Partial<QuickAccessDeps> = {},
55
+ ): Promise<PinnedFolder[]> {
56
+ const deps: QuickAccessDeps = { ...defaultDeps, ...overrides };
57
+ try {
58
+ const res = await deps.run(
59
+ ["powershell.exe", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", QUICK_ACCESS_SCRIPT],
60
+ 5000,
61
+ );
62
+ if (res.timedOut || res.code !== 0) {
63
+ warnings.push(`pinned: Quick Access ${res.timedOut ? "timed out" : `exited ${res.code}`}`);
64
+ return [];
65
+ }
66
+
67
+ let raw: RawItem[];
68
+ try {
69
+ const parsed = JSON.parse(res.stdout.trim() || "[]");
70
+ raw = (Array.isArray(parsed) ? parsed : [parsed]).filter((x): x is RawItem => x != null);
71
+ } catch (e) {
72
+ warnings.push(`pinned: Quick Access JSON parse failed (${(e as Error)?.message ?? e})`);
73
+ return [];
74
+ }
75
+
76
+ const pinned: PinnedFolder[] = [];
77
+ for (const item of raw) {
78
+ if (!item.Name || !item.Path || !isPinned(item.Pinned)) continue;
79
+ if (!(await deps.isDirectory(item.Path))) continue; // drops archive-as-folder (.zip/.rar) and stale entries
80
+ pinned.push({ name: item.Name, path: item.Path, source: "quick-access" });
81
+ }
82
+ return pinned;
83
+ } catch (e) {
84
+ warnings.push(`pinned: Quick Access failed (${(e as Error)?.message ?? e})`);
85
+ return [];
86
+ }
87
+ }
@@ -0,0 +1,41 @@
1
+ /** Shared argv-array shell-out for host-info providers. Every provider that
2
+ * needs PowerShell/plutil/findmnt/xdg-user-dir injects a `Runner` so unit
3
+ * tests never spawn a real process — only `defaultRunner` touches `Bun.spawn`. */
4
+ export interface RunResult {
5
+ stdout: string;
6
+ stderr: string;
7
+ /** Process exit code, or null when killed by the timeout. */
8
+ code: number | null;
9
+ timedOut: boolean;
10
+ }
11
+
12
+ export type Runner = (argv: string[], timeoutMs?: number) => Promise<RunResult>;
13
+
14
+ const DEFAULT_TIMEOUT_MS = 5000;
15
+
16
+ /** Real implementation: argv array only (never string-interpolated into a shell), bounded by timeoutMs. */
17
+ export const defaultRunner: Runner = async (argv, timeoutMs = DEFAULT_TIMEOUT_MS) => {
18
+ const proc = Bun.spawn(argv, { stdout: "pipe", stderr: "pipe", stdin: "ignore", windowsHide: true });
19
+ let timedOut = false;
20
+ const killTimer = setTimeout(() => {
21
+ timedOut = true;
22
+ try {
23
+ proc.kill();
24
+ } catch {
25
+ // Process already exited between the timer firing and the kill call.
26
+ }
27
+ }, timeoutMs);
28
+
29
+ try {
30
+ const [stdout, stderr, code] = await Promise.all([
31
+ new Response(proc.stdout).text(),
32
+ new Response(proc.stderr).text(),
33
+ proc.exited,
34
+ ]);
35
+ return { stdout, stderr, code, timedOut };
36
+ } catch (e: any) {
37
+ return { stdout: "", stderr: e?.message ?? String(e), code: null, timedOut };
38
+ } finally {
39
+ clearTimeout(killTimer);
40
+ }
41
+ };
@@ -279,6 +279,12 @@ export async function parseJsonlTranscript(
279
279
  // messages than the Agent tool_use that spawned it.
280
280
  nestChildEventsAcrossMessages(merged);
281
281
 
282
+ // Newer CLIs keep subagent transcripts in <session-dir>/subagents/ instead
283
+ // of inline sidechain lines — merge them back as Agent card children.
284
+ // Lazy import: merger depends on this module (parseSessionMessage).
285
+ const { mergeSubagentChildren } = await import("./subagent-transcript-merger.ts");
286
+ mergeSubagentChildren(filePath.replace(/\.jsonl$/, ""), merged);
287
+
282
288
  return merged.filter(
283
289
  (msg) => msg.content.trim().length > 0 || (msg.events && msg.events.length > 0),
284
290
  );
@@ -0,0 +1,26 @@
1
+ /** Shapes returned by the SQLite viewer service, shared by both of its doors. */
2
+
3
+ export interface TableInfo {
4
+ name: string;
5
+ rowCount: number;
6
+ }
7
+
8
+ export interface ColumnInfo {
9
+ cid: number;
10
+ name: string;
11
+ type: string;
12
+ notnull: boolean;
13
+ pk: boolean;
14
+ dflt_value: string | null;
15
+ fk: { table: string; column: string } | null;
16
+ }
17
+
18
+ export interface QueryResult {
19
+ columns: string[];
20
+ rows: Record<string, unknown>[];
21
+ rowsAffected: number;
22
+ changeType: "select" | "modify";
23
+ executionTimeMs: number;
24
+ /** True when a row cap cut the result short. */
25
+ truncated?: boolean;
26
+ }
@@ -1,29 +1,14 @@
1
1
  import { Database } from "bun:sqlite";
2
2
  import { resolve } from "node:path";
3
3
  import { existsSync } from "node:fs";
4
+ import { isPpmDirPath } from "./fs-path-guard.service.ts";
5
+ import { assertNoAttachStatement } from "./fs-ops/sql-statement-guard.ts";
6
+ import { readRows } from "./fs-ops/sql-row-reader.ts";
4
7
 
5
- export interface TableInfo {
6
- name: string;
7
- rowCount: number;
8
- }
9
-
10
- export interface ColumnInfo {
11
- cid: number;
12
- name: string;
13
- type: string;
14
- notnull: boolean;
15
- pk: boolean;
16
- dflt_value: string | null;
17
- fk: { table: string; column: string } | null;
18
- }
8
+ import type { ColumnInfo, QueryResult, TableInfo } from "./sqlite-types.ts";
19
9
 
20
- export interface QueryResult {
21
- columns: string[];
22
- rows: Record<string, unknown>[];
23
- rowsAffected: number;
24
- changeType: "select" | "modify";
25
- executionTimeMs: number;
26
- }
10
+ // Re-exported so existing importers keep using the service as one entry point.
11
+ export type { ColumnInfo, QueryResult, TableInfo };
27
12
 
28
13
  /** Auto-close idle databases after 5 minutes */
29
14
  const IDLE_TIMEOUT_MS = 5 * 60 * 1000;
@@ -36,12 +21,24 @@ interface CachedDb {
36
21
  class SqliteService {
37
22
  private cache = new Map<string, CachedDb>();
38
23
 
39
- /** Resolve db path — supports both project-relative and absolute paths */
24
+ /**
25
+ * Resolve db path — supports both project-relative and absolute paths.
26
+ *
27
+ * Absolute paths are not probed with `existsSync`: they come from the
28
+ * filesystem door, which can point at a dead network mount and would block
29
+ * the event loop here. That door stats the file asynchronously before
30
+ * calling in, and `open()` refuses to create a missing database, so nothing
31
+ * is silently brought into existence either way.
32
+ */
40
33
  private resolvePath(projectPath: string, dbRelPath: string): string {
41
34
  const isAbsolute = /^(\/|[A-Za-z]:[/\\])/.test(dbRelPath);
42
35
  const abs = isAbsolute ? dbRelPath : resolve(projectPath, dbRelPath);
43
36
  if (!isAbsolute && !abs.startsWith(projectPath)) throw new Error("Access denied: path outside project");
44
- if (!existsSync(abs)) throw new Error(`Database not found: ${dbRelPath}`);
37
+ // The PPM directory holds the config database with provider credentials and
38
+ // the auth token. Absolute paths are accepted here, so this door has to
39
+ // refuse it explicitly or a viewer could read the whole secret store.
40
+ if (isPpmDirPath(resolve(abs))) throw new Error("Access denied: PPM directory is not browsable");
41
+ if (!isAbsolute && !existsSync(abs)) throw new Error(`Database not found: ${dbRelPath}`);
45
42
  return abs;
46
43
  }
47
44
 
@@ -53,7 +50,11 @@ class SqliteService {
53
50
  cached.timer = setTimeout(() => this.close(absPath), IDLE_TIMEOUT_MS);
54
51
  return cached.db;
55
52
  }
56
- const db = new Database(absPath);
53
+ // `create: false` a viewer must never bring a database file into
54
+ // existence, least of all at a path the caller chose. `readwrite` has to
55
+ // be spelled out alongside it: the two flags are passed straight to
56
+ // sqlite3_open_v2, which rejects the combination that omits it.
57
+ const db = new Database(absPath, { readwrite: true, create: false });
57
58
  db.exec("PRAGMA journal_mode = WAL");
58
59
  // SQLite defaults FK enforcement off per connection, which would let the
59
60
  // viewer delete rows other clients reject and leave orphaned children.
@@ -122,8 +123,13 @@ class SqliteService {
122
123
  return { columns, rows, total, page, limit };
123
124
  }
124
125
 
125
- /** Execute arbitrary SQL */
126
- executeQuery(projectPath: string, dbPath: string, sql: string): QueryResult {
126
+ /**
127
+ * Execute arbitrary SQL. `maxRows` caps a SELECT result — a foreign database
128
+ * opened through the filesystem door can be arbitrarily large, and reading
129
+ * every row into memory to answer one request is a denial of service.
130
+ */
131
+ executeQuery(projectPath: string, dbPath: string, sql: string, maxRows?: number): QueryResult {
132
+ assertNoAttachStatement(sql);
127
133
  const abs = this.resolvePath(projectPath, dbPath);
128
134
  const db = this.open(abs);
129
135
  const trimmed = sql.trim().toUpperCase();
@@ -132,11 +138,13 @@ class SqliteService {
132
138
 
133
139
  const start = performance.now();
134
140
  if (isSelect) {
135
- const stmt = db.query(sql);
136
- const rows = stmt.all() as Record<string, unknown>[];
141
+ const { rows, truncated } = readRows(db.query(sql), maxRows);
137
142
  const executionTimeMs = Math.round(performance.now() - start);
138
143
  const columns = rows.length > 0 ? Object.keys(rows[0]!) : [];
139
- return { columns, rows, rowsAffected: 0, changeType: "select", executionTimeMs };
144
+ return {
145
+ columns, rows, rowsAffected: 0, changeType: "select", executionTimeMs,
146
+ ...(truncated ? { truncated: true } : {}),
147
+ };
140
148
  }
141
149
 
142
150
  const result = db.run(sql);
@@ -146,6 +154,7 @@ class SqliteService {
146
154
 
147
155
  /** Execute multi-statement SQL script (no result rows returned) */
148
156
  executeScript(projectPath: string, dbPath: string, sql: string): { executionTimeMs: number } {
157
+ assertNoAttachStatement(sql);
149
158
  const abs = this.resolvePath(projectPath, dbPath);
150
159
  const db = this.open(abs);
151
160
  const start = performance.now();
@@ -0,0 +1,144 @@
1
+ /**
2
+ * SubagentTranscriptMerger — restore Agent/Task card children on reload.
3
+ *
4
+ * Newer Claude Code CLIs no longer write subagent activity into the main
5
+ * session JSONL (no isSidechain lines, no parent_tool_use_id). Instead each
6
+ * agent gets its own transcript at:
7
+ * ~/.claude/projects/<slug>/<sessionId>/subagents/agent-<id>.jsonl
8
+ * with a sibling agent-<id>.meta.json carrying the spawning Agent tool_use id.
9
+ *
10
+ * Without merging these, a reloaded session shows bare Agent cards and the
11
+ * live-streamed children are lost. This module reads the meta files, parses
12
+ * each agent transcript, and attaches its events as the card's children.
13
+ */
14
+
15
+ import { existsSync, readdirSync, readFileSync } from "node:fs";
16
+ import { homedir } from "node:os";
17
+ import { join } from "node:path";
18
+ import type { ChatEvent } from "../types/chat.ts";
19
+ import { parseSessionMessage } from "./jsonl-transcript-parser.ts";
20
+
21
+ /**
22
+ * Locate the per-session directory (…/projects/<slug>/<sessionId>) that holds
23
+ * subagents/. The SDK encodes the cwd by replacing separators + drive colon
24
+ * with "-"; when that drifts (drive-letter case), fall back to scanning
25
+ * project dirs for the session's main JSONL.
26
+ */
27
+ export function resolveSessionDir(sessionId: string, projectPath: string | null | undefined): string | null {
28
+ const home = homedir();
29
+ const projectsRoot = join(home, ".claude", "projects");
30
+ if (projectPath) {
31
+ const encoded = projectPath.replace(/[/\\:]/g, "-");
32
+ const dir = join(projectsRoot, encoded);
33
+ if (existsSync(join(dir, `${sessionId}.jsonl`))) return join(dir, sessionId);
34
+ }
35
+ try {
36
+ for (const entry of readdirSync(projectsRoot)) {
37
+ if (existsSync(join(projectsRoot, entry, `${sessionId}.jsonl`))) {
38
+ return join(projectsRoot, entry, sessionId);
39
+ }
40
+ }
41
+ } catch {
42
+ /* projects root unreadable */
43
+ }
44
+ return null;
45
+ }
46
+
47
+ interface MessageLike {
48
+ content: string;
49
+ events?: ChatEvent[];
50
+ }
51
+
52
+ /** Payload guards — a session can hold dozens of agents with multi-MB transcripts. */
53
+ const MAX_CHILDREN_PER_AGENT = 2000;
54
+ const MAX_CHILD_OUTPUT_CHARS = 50_000;
55
+
56
+ /** Map of Agent-card toolUseId → agent transcript path, from subagents/*.meta.json */
57
+ function indexAgentTranscripts(subagentsDir: string): Map<string, string> {
58
+ const map = new Map<string, string>();
59
+ let entries: string[];
60
+ try {
61
+ entries = readdirSync(subagentsDir);
62
+ } catch {
63
+ return map;
64
+ }
65
+ for (const name of entries) {
66
+ if (!name.endsWith(".meta.json")) continue;
67
+ try {
68
+ const meta = JSON.parse(readFileSync(join(subagentsDir, name), "utf8"));
69
+ const toolUseId = meta?.toolUseId as string | undefined;
70
+ if (!toolUseId) continue;
71
+ const transcript = join(subagentsDir, name.replace(/\.meta\.json$/, ".jsonl"));
72
+ if (existsSync(transcript)) map.set(toolUseId, transcript);
73
+ } catch {
74
+ /* unreadable meta — skip this agent */
75
+ }
76
+ }
77
+ return map;
78
+ }
79
+
80
+ /** Parse one agent transcript into a flat children event list (stream order). */
81
+ function parseAgentTranscript(filePath: string): ChatEvent[] {
82
+ const children: ChatEvent[] = [];
83
+ let text: string;
84
+ try {
85
+ text = readFileSync(filePath, "utf8");
86
+ } catch {
87
+ return children;
88
+ }
89
+ let isFirstUser = true;
90
+ for (const line of text.split("\n")) {
91
+ const trimmed = line.trim();
92
+ if (!trimmed) continue;
93
+ let entry: any;
94
+ try {
95
+ entry = JSON.parse(trimmed);
96
+ } catch {
97
+ continue;
98
+ }
99
+ if (entry.type !== "user" && entry.type !== "assistant") continue;
100
+ if (!entry.message) continue;
101
+ if (children.length >= MAX_CHILDREN_PER_AGENT) break;
102
+ // The first user record is the agent's spawn prompt — the live stream
103
+ // never showed it as a child, so skip it to match the streaming view.
104
+ if (entry.type === "user" && isFirstUser) {
105
+ isFirstUser = false;
106
+ const content = entry.message?.content;
107
+ const hasToolResult = Array.isArray(content) && content.some((b: any) => b?.type === "tool_result");
108
+ if (!hasToolResult) continue;
109
+ }
110
+ const parsed = parseSessionMessage(entry);
111
+ for (const ev of parsed.events ?? []) {
112
+ // Keep single events from ballooning the history payload (agent files
113
+ // can carry multi-MB tool outputs the live stream also showed in full,
114
+ // but 24 agents × full outputs breaks mobile reloads).
115
+ if (ev.type === "tool_result" && typeof ev.output === "string" && ev.output.length > MAX_CHILD_OUTPUT_CHARS) {
116
+ ev.output = ev.output.slice(0, MAX_CHILD_OUTPUT_CHARS) + "\n… [truncated]";
117
+ }
118
+ children.push(ev);
119
+ }
120
+ }
121
+ return children;
122
+ }
123
+
124
+ /**
125
+ * Attach subagent transcript events as children of their Agent/Task cards.
126
+ * `sessionDir` is the per-session directory next to the main JSONL
127
+ * (…/projects/<slug>/<sessionId>). Existing children are replaced — the disk
128
+ * transcript is the complete record, while live-collected children may be a
129
+ * partial overlap. Mutates messages in-place.
130
+ */
131
+ export function mergeSubagentChildren(sessionDir: string, messages: MessageLike[]): void {
132
+ const index = indexAgentTranscripts(join(sessionDir, "subagents"));
133
+ if (index.size === 0) return;
134
+
135
+ for (const msg of messages) {
136
+ for (const ev of msg.events ?? []) {
137
+ if (ev.type !== "tool_use" || (ev.tool !== "Agent" && ev.tool !== "Task") || !ev.toolUseId) continue;
138
+ const transcript = index.get(ev.toolUseId);
139
+ if (!transcript) continue;
140
+ const children = parseAgentTranscript(transcript);
141
+ if (children.length > 0) ev.children = children;
142
+ }
143
+ }
144
+ }
@@ -0,0 +1,50 @@
1
+ /** Server-side host facts the frontend cannot learn on its own: OS, path
2
+ * separator, home dir, drives/volumes, resolved known folders, and the
3
+ * user's OS-pinned folders (Windows Quick Access, Finder Favorites,
4
+ * GTK/KDE bookmarks). Backs `GET /api/system/host`. */
5
+ export interface HostInfo {
6
+ platform: "win32" | "darwin" | "linux";
7
+ sep: "\\" | "/";
8
+ homedir: string;
9
+ hostname: string;
10
+ drives: Drive[];
11
+ knownFolders: KnownFolder[];
12
+ pinned: PinnedFolder[];
13
+ /** Non-fatal provider failures — a failure never becomes a 500, it becomes text here. */
14
+ warnings: string[];
15
+ }
16
+
17
+ export type DriveKind = "fixed" | "removable" | "network" | "unknown";
18
+
19
+ export interface Drive {
20
+ /** Display label for the mount, e.g. "C:" or "Macintosh HD". */
21
+ name: string;
22
+ /** Filesystem path to browse into, e.g. "C:\\" or "/Volumes/External". */
23
+ path: string;
24
+ kind: DriveKind;
25
+ /** Volume label when the OS reports one (Windows CIM `VolumeName`). */
26
+ label?: string;
27
+ }
28
+
29
+ export type KnownFolderKey =
30
+ | "desktop"
31
+ | "documents"
32
+ | "downloads"
33
+ | "pictures"
34
+ | "music"
35
+ | "videos"
36
+ | "icloud";
37
+
38
+ export interface KnownFolder {
39
+ key: KnownFolderKey;
40
+ name: string;
41
+ path: string;
42
+ }
43
+
44
+ export type PinnedSource = "quick-access" | "finder-favorites" | "gtk" | "kde";
45
+
46
+ export interface PinnedFolder {
47
+ name: string;
48
+ path: string;
49
+ source: PinnedSource;
50
+ }
package/src/web/app.tsx CHANGED
@@ -1,10 +1,11 @@
1
- import { useEffect, useState, useCallback, useRef } from "react";
1
+ import { useEffect, useState, useCallback, useRef, lazy, Suspense } from "react";
2
2
  import { Toaster } from "@/components/ui/sonner";
3
3
  import { TooltipProvider } from "@/components/ui/tooltip";
4
4
  import { PanelLayout } from "@/components/layout/panel-layout";
5
5
  import { TabPool } from "@/components/layout/tab-pool";
6
6
  import { Sidebar } from "@/components/layout/sidebar";
7
7
  import { StatusBar } from "@/components/layout/status-bar";
8
+ import { WindowLayer } from "@/components/floating-window/window-layer";
8
9
  import { MobileNav } from "@/components/layout/mobile-nav";
9
10
  import { MobileDrawer } from "@/components/layout/mobile-drawer";
10
11
  import { ProjectBottomSheet } from "@/components/layout/project-bottom-sheet";
@@ -36,6 +37,13 @@ import { useExtensionWs } from "@/hooks/use-extension-ws";
36
37
  import { useIsMobile } from "@/hooks/use-is-mobile";
37
38
  import { cn } from "@/lib/utils";
38
39
 
40
+ // Lazy: the explorer feature (views, actions, skins, icon map) is the same heavy bundle the
41
+ // desktop floating window already keeps out of the initial chunk (see `WINDOW_CONTENT`) —
42
+ // a static import here would pull all of it into every user's boot, mobile or not.
43
+ const MobileExplorerSheet = lazy(() =>
44
+ import("@/components/os-explorer/mobile/mobile-explorer-sheet").then((m) => ({ default: m.MobileExplorerSheet })),
45
+ );
46
+
39
47
  type AuthState = "checking" | "authenticated" | "unauthenticated";
40
48
 
41
49
  export function App() {
@@ -284,8 +292,9 @@ export function App() {
284
292
  {/* Desktop unified nav rail (wordmark + project switcher + section rail + panel) */}
285
293
  <Sidebar />
286
294
 
287
- {/* Content area — keep-alive per project */}
288
- <div className="flex-1 flex flex-col overflow-hidden">
295
+ {/* Content area — keep-alive per project. `relative` is the positioning context
296
+ the floating window layer measures and clamps its windows against. */}
297
+ <div className="relative flex-1 flex flex-col overflow-hidden">
289
298
  {[...mountedProjects].map((projectName) => (
290
299
  <div
291
300
  key={projectName}
@@ -303,6 +312,8 @@ export function App() {
303
312
  {/* Desktop status bar — spans the working area only (not under the sidebar).
304
313
  Self-gated to desktop via `hidden md:flex`. */}
305
314
  <StatusBar />
315
+ {/* Floating windows — desktop only, self-gated; covers the working area. */}
316
+ <WindowLayer />
306
317
  </div>
307
318
  </div>
308
319
 
@@ -331,6 +342,11 @@ export function App() {
331
342
  {/* Compare Files picker (Mod+Alt+D, palette, context menus) — singleton */}
332
343
  <ComparePicker />
333
344
 
345
+ {/* Mobile full-screen file explorer sheet — lazy + self-gated, loads nothing until opened */}
346
+ <Suspense fallback={null}>
347
+ <MobileExplorerSheet />
348
+ </Suspense>
349
+
334
350
  {/* Global bug report popup */}
335
351
  <BugReportPopup />
336
352
 
@@ -19,6 +19,9 @@ import { useConnections, type Connection } from "../database/use-connections";
19
19
  import { GlideDataGrid } from "../database/glide-data-grid";
20
20
  import type { GridColumnSchema } from "../database/glide-grid-types";
21
21
  import type { DbQueryResult } from "../database/use-database";
22
+ // Single source of truth: the explorer decides whether a double-click can open a file at
23
+ // all from these very sets, so they must not be redeclared here.
24
+ import { AUDIO_EXTS, IMAGE_EXTS, SQLITE_EXTS, VIDEO_EXTS } from "@/components/os-explorer/can-open-in-ppm";
22
25
 
23
26
  const MarkdownRenderer = lazy(() =>
24
27
  import("@/components/shared/markdown-renderer").then((m) => ({ default: m.MarkdownRenderer }))
@@ -30,15 +33,6 @@ const VideoPreview = lazy(() => import("./video-preview").then((m) => ({ default
30
33
  const AudioPreview = lazy(() => import("./audio-preview").then((m) => ({ default: m.AudioPreview })));
31
34
  const DocxPreview = lazy(() => import("./docx-preview").then((m) => ({ default: m.DocxPreview })));
32
35
 
33
- /** Image extensions renderable inline */
34
- const IMAGE_EXTS = new Set(["png", "jpg", "jpeg", "gif", "webp", "svg", "ico"]);
35
- /** Video extensions playable inline */
36
- const VIDEO_EXTS = new Set(["mp4", "webm", "mov", "ogg", "avi", "mkv"]);
37
- /** Audio extensions playable inline */
38
- const AUDIO_EXTS = new Set(["mp3", "wav", "flac", "aac", "m4a", "wma"]);
39
- /** SQLite extensions — redirect to sqlite viewer */
40
- const SQLITE_EXTS = new Set(["db", "sqlite", "sqlite3"]);
41
-
42
36
  function getFileExt(filename: string): string {
43
37
  return filename.split(".").pop()?.toLowerCase() ?? "";
44
38
  }