@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.
- package/.release-run.sh +5 -0
- package/CHANGELOG.md +21 -0
- package/CLAUDE.md +4 -0
- package/assets/skills/ppm/SKILL.md +1 -1
- package/assets/skills/ppm/references/http-api.md +16 -2
- package/bun.lock +3 -0
- package/dist/web/assets/{ai-resource-editor-DL011EDu.js → ai-resource-editor-BLYgg033.js} +1 -1
- package/dist/web/assets/{angular-html-D4YJUMLP.js → angular-html-jfMqUuRd.js} +1 -1
- package/dist/web/assets/{angular-ts-CUvq2h3X.js → angular-ts-wytn9PMm.js} +1 -1
- package/dist/web/assets/{api-client-COQtP-dB.js → api-client-B9OFv3nY.js} +1 -1
- package/dist/web/assets/api-client-CKo60P6G.js +1 -0
- package/dist/web/assets/{api-settings-Do0Z0IRN.js → api-settings-DGhshDRg.js} +1 -1
- package/dist/web/assets/api-settings-fdkhqLSF.js +1 -0
- package/dist/web/assets/{api-themes-DXi8sz-9.js → api-themes-okiyhhp9.js} +1 -1
- package/dist/web/assets/{apl-DSANFLx0.js → apl-i-ahKx6O.js} +1 -1
- package/dist/web/assets/architecture-PBZL5I3N-B4J2-O8Q.js +1 -0
- package/dist/web/assets/{astro-CXIotiNS.js → astro-DVBCJfG6.js} +1 -1
- package/dist/web/assets/{audio-preview-H16VO99g.js → audio-preview-y8XpCNrh.js} +1 -1
- package/dist/web/assets/{blade-BvrP2gPd.js → blade-BHlL8SqU.js} +1 -1
- package/dist/web/assets/{bsl-CGf6Xuyu.js → bsl-D-UOfR1F.js} +1 -1
- package/dist/web/assets/{cairo-BboZ9qIf.js → cairo-Bn6rucli.js} +1 -1
- package/dist/web/assets/can-open-in-ppm-BzVXoV-d.js +1 -0
- package/dist/web/assets/chat-tab-BcR-3_6R.js +13 -0
- package/dist/web/assets/clock-B1CPBp2g.js +1 -0
- package/dist/web/assets/{cobol-D39V6ukp.js → cobol-Byn9FYKu.js} +1 -1
- package/dist/web/assets/code-editor-CJ8g7dqm.js +10 -0
- package/dist/web/assets/{coffee-DTtK7kKi.js → coffee-DjBl4gm-.js} +1 -1
- package/dist/web/assets/{conflict-editor-B_wAb0Kb.js → conflict-editor-BP7JFZzG.js} +3 -3
- package/dist/web/assets/context-menu-BSE5yuMG.js +1 -0
- package/dist/web/assets/copy-Su9m2utd.js +1 -0
- package/dist/web/assets/{cpp-CnU9hfBq.js → cpp-CKzic-3E.js} +1 -1
- package/dist/web/assets/{crystal-DMjCL--0.js → crystal-Bkg-Ly_g.js} +1 -1
- package/dist/web/assets/csv-preview-xAwUDNat.js +2 -0
- package/dist/web/assets/{data-grid-overlay-editor-Bdc80TJ1.js → data-grid-overlay-editor-DMTCHIG9.js} +1 -1
- package/dist/web/assets/{database-viewer-awmnuDCt.js → database-viewer-BVLWYPa4.js} +1 -1
- package/dist/web/assets/dialog-D__LRQTn.js +1 -0
- package/dist/web/assets/diff-viewer-BheSOHfl.js +4 -0
- package/dist/web/assets/{docx-preview-DDw3duw9.js → docx-preview-CGlMqltP.js} +1 -1
- package/dist/web/assets/{edge-CTom35R_.js → edge-DVbZnd3Y.js} +1 -1
- package/dist/web/assets/{edit-diff-preview-D1TEK7Jz.js → edit-diff-preview-ClJAJwlL.js} +1 -1
- package/dist/web/assets/{elixir-BAX9HSOu.js → elixir-Dwi8Wu7W.js} +1 -1
- package/dist/web/assets/{elm-CpD28xsW.js → elm-DtIv-HXJ.js} +1 -1
- package/dist/web/assets/{erb-DHX2IIEs.js → erb-D3HEDz1x.js} +1 -1
- package/dist/web/assets/{erlang-B_etLcPG.js → erlang-2MjTCzGz.js} +1 -1
- package/dist/web/assets/{esm-PmlN1RTs.js → esm-BfqDE09P.js} +1 -1
- package/dist/web/assets/explorer-body-DE5339g9.js +2 -0
- package/dist/web/assets/explorer-window-content-BrTHAoXM.js +1 -0
- package/dist/web/assets/{extension-webview-DkTI51P3.js → extension-webview-DRq1tWC1.js} +1 -1
- package/dist/web/assets/{fortran-fixed-form-CpR0cN7O.js → fortran-fixed-form-BLyAtyPM.js} +1 -1
- package/dist/web/assets/{fsharp-DxITxZW5.js → fsharp-Bxbn_gbr.js} +1 -1
- package/dist/web/assets/{gdresource-DJ7IvROZ.js → gdresource-sFMY4D2Q.js} +1 -1
- package/dist/web/assets/{git-commit-sQznNP43.js → git-commit-BzB9Lio5.js} +1 -1
- package/dist/web/assets/git-log-panel-pjyOjchU.js +1 -0
- package/dist/web/assets/{git-rebase-DkHvejAR.js → git-rebase-CKSVd848.js} +1 -1
- package/dist/web/assets/gitGraph-HDMCJU4V-CtQ3yXN-.js +1 -0
- package/dist/web/assets/{glide-data-grid-Bpgp72Hg.js → glide-data-grid-LX3N4SsJ.js} +9 -9
- package/dist/web/assets/{glimmer-js-BwJnDfL-.js → glimmer-js-BY8aExAJ.js} +1 -1
- package/dist/web/assets/{glimmer-ts-Coz155XK.js → glimmer-ts-Bak54dBX.js} +1 -1
- package/dist/web/assets/{glsl-BED7ZmUZ.js → glsl-nR2eaJQe.js} +1 -1
- package/dist/web/assets/{graphql-B_KyE6oz.js → graphql-CGPPFAU6.js} +1 -1
- package/dist/web/assets/group-chat-tab-CVQfptkT.js +1 -0
- package/dist/web/assets/{hack-sxywdIAQ.js → hack-CXIMX-Ol.js} +1 -1
- package/dist/web/assets/{haml-Dts9JlPU.js → haml-tPY-9Pfm.js} +1 -1
- package/dist/web/assets/{handlebars-C9HXIMtj.js → handlebars-BuW1LT7T.js} +1 -1
- package/dist/web/assets/{html-2p0RvXi4.js → html-bgVcwZ-t.js} +1 -1
- package/dist/web/assets/{html-derivative-BiTPuOba.js → html-derivative-D6-IxTgn.js} +1 -1
- package/dist/web/assets/{http-CHd2gYPf.js → http-CJ1zyB-h.js} +1 -1
- package/dist/web/assets/{hurl-boMPgDm9.js → hurl-CmoT7l3T.js} +1 -1
- package/dist/web/assets/{hxml-BQvjiuBt.js → hxml-CztOsL8o.js} +1 -1
- package/dist/web/assets/{image-preview-Dwg0EuJ2.js → image-preview-BDySmiim.js} +1 -1
- package/dist/web/assets/index-XoDY9bc0.js +52 -0
- package/dist/web/assets/index-YCTraslE.css +2 -0
- package/dist/web/assets/info-3K5VOQVL-Cg0mIJn9.js +1 -0
- package/dist/web/assets/{jinja-B-zKiwlp.js → jinja-B1pq3jJq.js} +1 -1
- package/dist/web/assets/{jison-C2vJYjbJ.js → jison-D8B5pCwA.js} +1 -1
- package/dist/web/assets/{julia-DJ8MrQPA.js → julia-D0K3bwpU.js} +1 -1
- package/dist/web/assets/{just-BvQHq7VE.js → just-B9Jlddu-.js} +1 -1
- package/dist/web/assets/keybindings-store-BE1jVUZW.js +1 -0
- package/dist/web/assets/{latex-ChNeshUC.js → latex-BPJSSE6j.js} +1 -1
- package/dist/web/assets/{liquid-KNJEBOwW.js → liquid-lv10fo4U.js} +1 -1
- package/dist/web/assets/{lua-D8NNsLbC.js → lua-PNuaIBEF.js} +1 -1
- package/dist/web/assets/{markdown-renderer-C7dlPs2S.js → markdown-renderer-B8Kz5rvP.js} +3 -3
- package/dist/web/assets/markdown-renderer-Btync7yg.js +1 -0
- package/dist/web/assets/{marko-HGo5Qtz4.js → marko-Du3frD6X.js} +1 -1
- package/dist/web/assets/{mdc-omkodQB5.js → mdc-BeDVcFRl.js} +1 -1
- package/dist/web/assets/mobile-bottom-sheet-CzRXE6mY.js +1 -0
- package/dist/web/assets/mobile-explorer-sheet-CDU8xriw.js +1 -0
- package/dist/web/assets/{nextflow-Adq02pv-.js → nextflow-DkcXP71s.js} +1 -1
- package/dist/web/assets/{nginx-ByvWruGD.js → nginx-C5n8N_bt.js} +1 -1
- package/dist/web/assets/{nim-BrMojX4O.js → nim-CIhyfs-A.js} +1 -1
- package/dist/web/assets/notification-store-Bi7VHAy4.js +1 -0
- package/dist/web/assets/{number-overlay-editor-CunvWJnN.js → number-overlay-editor-B8P26qGC.js} +1 -1
- package/dist/web/assets/packet-RMMSAZCW-D79vAFR_.js +1 -0
- package/dist/web/assets/{panel-store-CpKvXNnm.js → panel-store-gbNJvZB_.js} +1 -1
- package/dist/web/assets/{pdf-preview-CEWYMxdp.js → pdf-preview-CtZWvujY.js} +1 -1
- package/dist/web/assets/{perl-Bd_0l-b4.js → perl-Cf31sZYE.js} +1 -1
- package/dist/web/assets/{php-D-DLTnWJ.js → php-Dzl_MDIW.js} +1 -1
- package/dist/web/assets/pie-UPGHQEXC-DYUOH68U.js +1 -0
- package/dist/web/assets/{postgres-viewer-D7PggslU.js → postgres-viewer-fqMUi0xS.js} +3 -3
- package/dist/web/assets/{project-store-D0ALup9Z.js → project-store-D1D1MN03.js} +1 -1
- package/dist/web/assets/{pug-D2aO-l2T.js → pug-CxSYHrB3.js} +1 -1
- package/dist/web/assets/{qml-CyQVzNXS.js → qml-DlEjGhwN.js} +1 -1
- package/dist/web/assets/radar-KQ55EAFF-B1eznNtd.js +1 -0
- package/dist/web/assets/{razor-8tvJXsO3.js → razor-KVt5uW14.js} +1 -1
- package/dist/web/assets/{rst-C4AZyQQl.js → rst-D5BwNTnw.js} +1 -1
- package/dist/web/assets/{ruby-O_z2NTLY.js → ruby-D5fejQwd.js} +1 -1
- package/dist/web/assets/{sas-BtnF4zaV.js → sas-Bj7B1CB2.js} +1 -1
- package/dist/web/assets/{scss-GAyp5euH.js → scss-BB0CUoCL.js} +1 -1
- package/dist/web/assets/settings-store-Bm7uL8VA.js +2 -0
- package/dist/web/assets/settings-tab-DxtBG0DW.js +1 -0
- package/dist/web/assets/{shaderlab-nM5YZwa5.js → shaderlab-BdjEZUMc.js} +1 -1
- package/dist/web/assets/{shellsession-D2OCI4Gv.js → shellsession-Bp1OA1rR.js} +1 -1
- package/dist/web/assets/{soy-DrLNhqfp.js → soy-DlYz3wsC.js} +1 -1
- package/dist/web/assets/sparkles-BvJ1EGWd.js +1 -0
- package/dist/web/assets/{sparql-CsM6F2Yv.js → sparql-CdfII5Jd.js} +1 -1
- package/dist/web/assets/{sql-query-editor-ZnKcxCyj.js → sql-query-editor-D2UxRvG7.js} +1 -1
- package/dist/web/assets/sqlite-viewer-CTBwzT-r.js +1 -0
- package/dist/web/assets/{stata-Bk3cgfXJ.js → stata-BvUA6GUW.js} +1 -1
- package/dist/web/assets/{surrealql-Dkz0DPK8.js → surrealql--DLNbTyI.js} +1 -1
- package/dist/web/assets/{svelte-23si1KV5.js → svelte-CBfSsG4n.js} +1 -1
- package/dist/web/assets/{system-monitor-tab-Ck3REHUg.js → system-monitor-tab-Bscf6tzK.js} +1 -1
- package/dist/web/assets/{tab-store-BQmDVh9c.js → tab-store-DnNnaAcE.js} +1 -1
- package/dist/web/assets/{templ-CPxlP4vF.js → templ-Dv8zpKZW.js} +1 -1
- package/dist/web/assets/{terminal-tab-D6tYDFSF.js → terminal-tab-CTKU5gaF.js} +3 -3
- package/dist/web/assets/{tex-ugJpgYPc.js → tex-CsrOiqh1.js} +1 -1
- package/dist/web/assets/tool-cards-xstpayaW.js +7 -0
- package/dist/web/assets/treemap-KZPCXAKY-SeI2TxLs.js +1 -0
- package/dist/web/assets/{ts-tags-BovP9TMu.js → ts-tags-3T98k4EJ.js} +1 -1
- package/dist/web/assets/{twig-B7VUm2Ca.js → twig-u6QZ45FH.js} +1 -1
- package/dist/web/assets/{use-blob-url-B3YovXF6.js → use-blob-url-BLRmhlZI.js} +1 -1
- package/dist/web/assets/{use-monaco-theme-wKbyNwIn.js → use-monaco-theme-DxYstgYa.js} +1 -1
- package/dist/web/assets/{vendor-mermaid-CYOBtZtD.js → vendor-mermaid-C977xNeE.js} +1 -1
- package/dist/web/assets/{vendor-ui-DMRGWRuc.js → vendor-ui-CXJtBULr.js} +1 -1
- package/dist/web/assets/{video-preview-DwrfenNA.js → video-preview-cfaoRxG3.js} +1 -1
- package/dist/web/assets/{vue-m75pWowk.js → vue-CxIsxtwn.js} +1 -1
- package/dist/web/assets/{vue-html-odHs7IMn.js → vue-html-BGL5qnuH.js} +1 -1
- package/dist/web/assets/{vue-vine-BbBB3V_G.js → vue-vine-DHPh_gMr.js} +1 -1
- package/dist/web/assets/{xml-BHzIcDWI.js → xml-C-vM2m7J.js} +1 -1
- package/dist/web/assets/{xsl-DTLhN7uu.js → xsl-DvTXNwuO.js} +1 -1
- package/dist/web/index.html +26 -23
- package/dist/web/sw.js +1 -1
- package/docs/codebase-summary.md +10 -1
- package/docs/design-guidelines.md +31 -0
- package/docs/project-roadmap.md +10 -0
- package/docs/system-architecture.md +59 -0
- package/package.json +2 -1
- package/src/providers/claude-agent-sdk.ts +6 -0
- package/src/server/index.ts +8 -0
- package/src/server/routes/files.ts +2 -2
- package/src/server/routes/fs-browse.ts +99 -74
- package/src/server/routes/fs-ops.ts +118 -0
- package/src/server/routes/fs-sqlite.ts +129 -0
- package/src/server/routes/host-info.ts +17 -0
- package/src/server/routes/settings.ts +2 -0
- package/src/services/download-token.service.ts +21 -5
- package/src/services/file.service.ts +8 -12
- package/src/services/fs-browse.service.ts +104 -161
- package/src/services/fs-ops/fs-content-disposition.ts +17 -0
- package/src/services/fs-ops/fs-core-ops.ts +149 -0
- package/src/services/fs-ops/fs-error-response.ts +24 -0
- package/src/services/fs-ops/fs-git-init.service.ts +23 -0
- package/src/services/fs-ops/fs-hidden-names.ts +17 -0
- package/src/services/fs-ops/fs-list-files.service.ts +68 -0
- package/src/services/fs-ops/fs-ops-copy-move.service.ts +60 -0
- package/src/services/fs-ops/fs-ops-mutate.service.ts +59 -0
- package/src/services/fs-ops/fs-ops-read-write.service.ts +70 -0
- package/src/services/fs-ops/fs-ops-stat.service.ts +109 -0
- package/src/services/fs-ops/fs-ops-trash.service.ts +111 -0
- package/src/services/fs-ops/fs-real-path.ts +44 -0
- package/src/services/fs-ops/sql-row-reader.ts +26 -0
- package/src/services/fs-ops/sql-statement-guard.ts +63 -0
- package/src/services/fs-path-guard.service.ts +196 -0
- package/src/services/host-info/apple-bookmark-decoder.ts +97 -0
- package/src/services/host-info/apple-plist-xml-parser.ts +107 -0
- package/src/services/host-info/concurrency-limit.ts +20 -0
- package/src/services/host-info/host-drives.ts +190 -0
- package/src/services/host-info/host-info.service.ts +171 -0
- package/src/services/host-info/host-known-folders.ts +180 -0
- package/src/services/host-info/pinned-linux-bookmarks.ts +89 -0
- package/src/services/host-info/pinned-macos-finder-favorites.ts +175 -0
- package/src/services/host-info/pinned-windows-quick-access.ts +87 -0
- package/src/services/host-info/spawn-runner.ts +41 -0
- package/src/services/jsonl-transcript-parser.ts +6 -0
- package/src/services/sqlite-types.ts +26 -0
- package/src/services/sqlite.service.ts +38 -29
- package/src/services/subagent-transcript-merger.ts +144 -0
- package/src/types/system.ts +50 -0
- package/src/web/app.tsx +19 -3
- package/src/web/components/editor/code-editor.tsx +3 -9
- package/src/web/components/explorer/file-tree.tsx +103 -21
- package/src/web/components/explorer/tree-node-context-menu.tsx +6 -1
- package/src/web/components/explorer/tree-node.tsx +34 -93
- package/src/web/components/explorer/use-file-upload-drag.ts +14 -9
- package/src/web/components/explorer/use-tree-row-dnd.ts +206 -0
- package/src/web/components/floating-window/default-window-chrome.tsx +71 -0
- package/src/web/components/floating-window/floating-window.tsx +167 -0
- package/src/web/components/floating-window/use-window-drag.ts +28 -0
- package/src/web/components/floating-window/use-window-gesture-context.ts +44 -0
- package/src/web/components/floating-window/use-window-keyboard.ts +55 -0
- package/src/web/components/floating-window/use-window-resize.ts +30 -0
- package/src/web/components/floating-window/window-chrome-contract.ts +38 -0
- package/src/web/components/floating-window/window-content-registry.ts +51 -0
- package/src/web/components/floating-window/window-geometry.ts +121 -0
- package/src/web/components/floating-window/window-layer.tsx +92 -0
- package/src/web/components/floating-window/window-persistence.ts +104 -0
- package/src/web/components/floating-window/window-resize-handles.tsx +81 -0
- package/src/web/components/floating-window/window-store-types.ts +20 -0
- package/src/web/components/floating-window/window-store.ts +192 -0
- package/src/web/components/layout/command-palette.tsx +10 -0
- package/src/web/components/layout/mobile-drawer.tsx +11 -2
- package/src/web/components/layout/nav-section-rail.tsx +7 -1
- package/src/web/components/os-explorer/actions/explorer-actions-clipboard.ts +186 -0
- package/src/web/components/os-explorer/actions/explorer-actions-mutate.ts +109 -0
- package/src/web/components/os-explorer/actions/explorer-actions-open.ts +67 -0
- package/src/web/components/os-explorer/actions/explorer-actions-transfer-helpers.ts +35 -0
- package/src/web/components/os-explorer/actions/use-explorer-actions.ts +205 -0
- package/src/web/components/os-explorer/can-open-in-ppm.ts +89 -0
- package/src/web/components/os-explorer/dnd/drag-depth-counter.ts +36 -0
- package/src/web/components/os-explorer/dnd/drag-ghost.ts +44 -0
- package/src/web/components/os-explorer/dnd/drop-target-decision.ts +46 -0
- package/src/web/components/os-explorer/dnd/drop-target-style.ts +7 -0
- package/src/web/components/os-explorer/dnd/entry-drag-payload.ts +115 -0
- package/src/web/components/os-explorer/dnd/entry-drag-state.ts +35 -0
- package/src/web/components/os-explorer/dnd/entry-drop-executor.ts +43 -0
- package/src/web/components/os-explorer/dnd/use-drag-auto-scroll.ts +70 -0
- package/src/web/components/os-explorer/dnd/use-drop-transfer.tsx +82 -0
- package/src/web/components/os-explorer/dnd/use-entry-drag-source.ts +73 -0
- package/src/web/components/os-explorer/dnd/use-entry-drop-target.ts +150 -0
- package/src/web/components/os-explorer/dnd/use-entry-row-dnd.ts +66 -0
- package/src/web/components/os-explorer/dnd/use-path-drop-target.ts +30 -0
- package/src/web/components/os-explorer/explorer-body.tsx +153 -0
- package/src/web/components/os-explorer/explorer-breadcrumb.tsx +108 -0
- package/src/web/components/os-explorer/explorer-context-menu.tsx +131 -0
- package/src/web/components/os-explorer/explorer-dialogs.tsx +103 -0
- package/src/web/components/os-explorer/explorer-modal-shell.tsx +60 -0
- package/src/web/components/os-explorer/explorer-pins-store.ts +63 -0
- package/src/web/components/os-explorer/explorer-sidebar.tsx +198 -0
- package/src/web/components/os-explorer/explorer-sort-menu.tsx +68 -0
- package/src/web/components/os-explorer/explorer-status-bar.tsx +35 -0
- package/src/web/components/os-explorer/explorer-store.ts +179 -0
- package/src/web/components/os-explorer/explorer-toolbar.tsx +139 -0
- package/src/web/components/os-explorer/explorer-window-content.tsx +36 -0
- package/src/web/components/os-explorer/format-file-meta.ts +74 -0
- package/src/web/components/os-explorer/icons/file-type-icon-map.ts +106 -0
- package/src/web/components/os-explorer/icons/file-type-icon.tsx +56 -0
- package/src/web/components/os-explorer/icons/thumbnail-fetch-semaphore.ts +44 -0
- package/src/web/components/os-explorer/icons/thumbnail-image.tsx +124 -0
- package/src/web/components/os-explorer/mobile/mobile-bottom-toolbar.tsx +102 -0
- package/src/web/components/os-explorer/mobile/mobile-explorer-sheet.tsx +61 -0
- package/src/web/components/os-explorer/mobile/mobile-explorer-top-bar.tsx +41 -0
- package/src/web/components/os-explorer/mobile/mobile-more-sheet.tsx +117 -0
- package/src/web/components/os-explorer/mobile/mobile-places-sheet.tsx +120 -0
- package/src/web/components/os-explorer/mobile/mobile-places-strip.tsx +109 -0
- package/src/web/components/os-explorer/mobile/mobile-tap-action.ts +19 -0
- package/src/web/components/os-explorer/mobile/use-mobile-row-tap.ts +50 -0
- package/src/web/components/os-explorer/open-explorer.ts +35 -0
- package/src/web/components/os-explorer/properties-dialog.tsx +99 -0
- package/src/web/components/os-explorer/skins/explorer-skin-chrome.tsx +17 -0
- package/src/web/components/os-explorer/skins/folder-icon-macos.tsx +42 -0
- package/src/web/components/os-explorer/skins/folder-icon-windows.tsx +25 -0
- package/src/web/components/os-explorer/skins/macos-skin.ts +14 -0
- package/src/web/components/os-explorer/skins/macos-window-chrome.tsx +69 -0
- package/src/web/components/os-explorer/skins/skin-types.ts +40 -0
- package/src/web/components/os-explorer/skins/skins.css +25 -0
- package/src/web/components/os-explorer/skins/use-explorer-skin.ts +21 -0
- package/src/web/components/os-explorer/skins/windows-skin.ts +11 -0
- package/src/web/components/os-explorer/skins/windows-window-chrome.tsx +56 -0
- package/src/web/components/os-explorer/sort-and-filter-entries.ts +52 -0
- package/src/web/components/os-explorer/sort-options.ts +29 -0
- package/src/web/components/os-explorer/toolbar-icon-button.ts +18 -0
- package/src/web/components/os-explorer/use-coarse-long-press.ts +97 -0
- package/src/web/components/os-explorer/use-explorer-keyboard.ts +124 -0
- package/src/web/components/os-explorer/use-explorer-navigation.ts +155 -0
- package/src/web/components/os-explorer/use-explorer-open-state.ts +67 -0
- package/src/web/components/os-explorer/use-host-info.ts +85 -0
- package/src/web/components/os-explorer/views/column-row.tsx +126 -0
- package/src/web/components/os-explorer/views/column-view-column.tsx +112 -0
- package/src/web/components/os-explorer/views/column-view-mobile.tsx +98 -0
- package/src/web/components/os-explorer/views/column-view-preview.tsx +70 -0
- package/src/web/components/os-explorer/views/column-view.tsx +204 -0
- package/src/web/components/os-explorer/views/compose-interactive-row-props.ts +77 -0
- package/src/web/components/os-explorer/views/explorer-view-registry.tsx +55 -0
- package/src/web/components/os-explorer/views/icons-view-tile.tsx +158 -0
- package/src/web/components/os-explorer/views/icons-view.tsx +188 -0
- package/src/web/components/os-explorer/views/inline-name-input.tsx +60 -0
- package/src/web/components/os-explorer/views/list-row.tsx +162 -0
- package/src/web/components/os-explorer/views/list-view.tsx +177 -0
- package/src/web/components/os-explorer/views/use-column-view-state.ts +158 -0
- package/src/web/components/os-explorer/views/use-entry-selection.ts +178 -0
- package/src/web/components/settings/settings-tab.tsx +29 -2
- package/src/web/components/sqlite/sqlite-viewer.tsx +5 -2
- package/src/web/components/sqlite/use-sqlite.ts +7 -2
- package/src/web/components/ui/adaptive-context-menu.tsx +57 -1
- package/src/web/components/ui/file-browser-picker.tsx +1 -18
- package/src/web/hooks/use-chat.ts +22 -4
- package/src/web/lib/file-download.ts +6 -4
- package/src/web/lib/fs-api.ts +185 -0
- package/src/web/stores/file-store.ts +38 -1
- package/src/web/stores/settings-store.ts +14 -0
- package/src/web/styles/globals.css +1 -0
- package/dist/web/assets/api-client-RtNXvS0P.js +0 -1
- package/dist/web/assets/api-settings-De--HNHp.js +0 -1
- package/dist/web/assets/architecture-PBZL5I3N-DVRYSsQn.js +0 -1
- package/dist/web/assets/chat-tab-D2nZCpAo.js +0 -13
- package/dist/web/assets/code-editor-DqQy2Qm8.js +0 -10
- package/dist/web/assets/context-menu-DIiZdfbE.js +0 -1
- package/dist/web/assets/csv-preview-BL0I3CKz.js +0 -2
- package/dist/web/assets/dialog-HHdNInEH.js +0 -1
- package/dist/web/assets/diff-viewer-_yQtutHR.js +0 -4
- package/dist/web/assets/git-log-panel-NkghB_rO.js +0 -1
- package/dist/web/assets/gitGraph-HDMCJU4V-CutkUNY_.js +0 -1
- package/dist/web/assets/group-chat-tab-CQOVBmVp.js +0 -1
- package/dist/web/assets/index-CJ0Wp_rW.js +0 -50
- package/dist/web/assets/index-CVJmlKhp.css +0 -2
- package/dist/web/assets/info-3K5VOQVL-BpNjgbj9.js +0 -1
- package/dist/web/assets/keybindings-store-ClNYe9vD.js +0 -1
- package/dist/web/assets/markdown-renderer-CwpP5Ola.js +0 -1
- package/dist/web/assets/notification-store-DwAhNzTy.js +0 -1
- package/dist/web/assets/packet-RMMSAZCW-D5IUZ66-.js +0 -1
- package/dist/web/assets/pie-UPGHQEXC-CM29eKDR.js +0 -1
- package/dist/web/assets/radar-KQ55EAFF-QtJGaSGt.js +0 -1
- package/dist/web/assets/settings-store-B3LfpCPa.js +0 -2
- package/dist/web/assets/settings-tab-CeSJQIfF.js +0 -1
- package/dist/web/assets/sparkles-B3DmG8PJ.js +0 -1
- package/dist/web/assets/sqlite-viewer-8fk_wut8.js +0 -1
- package/dist/web/assets/tool-cards-C3ka1Y7I.js +0 -7
- package/dist/web/assets/treemap-KZPCXAKY-CjUqpVnS.js +0 -1
- /package/dist/web/assets/{abap-BM5PMK0-.js → abap-C1K0-wzc.js} +0 -0
- /package/dist/web/assets/{actionscript-3-CML-MTNy.js → actionscript-3-CJhQVjLA.js} +0 -0
- /package/dist/web/assets/{ada-DzO1tMqV.js → ada-Bt8r9fME.js} +0 -0
- /package/dist/web/assets/{andromeeda-C3nkvRhj.js → andromeeda-DF1I8qi3.js} +0 -0
- /package/dist/web/assets/{apache-Dg7oWQbs.js → apache-CnlleE6P.js} +0 -0
- /package/dist/web/assets/{apex-3O2170Ju.js → apex-j0C6Xmk6.js} +0 -0
- /package/dist/web/assets/{applescript-5AlzBqQO.js → applescript-DO7AnO8U.js} +0 -0
- /package/dist/web/assets/{apply-theme-BSJDABU3.js → apply-theme-CMQXnUAa.js} +0 -0
- /package/dist/web/assets/{ara-BGtOX5Hn.js → ara-i83AydZj.js} +0 -0
- /package/dist/web/assets/{asciidoc-CIsC4kkq.js → asciidoc-DbBA6-sF.js} +0 -0
- /package/dist/web/assets/{asm-p1-PUkh3.js → asm-B5S47Rgr.js} +0 -0
- /package/dist/web/assets/{aurora-x-BPgGL50S.js → aurora-x-De_IaSKw.js} +0 -0
- /package/dist/web/assets/{awk-Cj93pRL8.js → awk-CfyLHXqS.js} +0 -0
- /package/dist/web/assets/{ayu-dark-C50MYKhw.js → ayu-dark-DTLdZ1Si.js} +0 -0
- /package/dist/web/assets/{ayu-light-DyIp0Idy.js → ayu-light-DTOfkzhu.js} +0 -0
- /package/dist/web/assets/{ayu-mirage-BAdm8pKU.js → ayu-mirage-DsAECCMv.js} +0 -0
- /package/dist/web/assets/{ballerina-DUO9mwyV.js → ballerina-CumGp9A7.js} +0 -0
- /package/dist/web/assets/{bat-Cg8hlSct.js → bat-Ca2SBbYN.js} +0 -0
- /package/dist/web/assets/{beancount-f8f3BBqB.js → beancount-CqyXBwwF.js} +0 -0
- /package/dist/web/assets/{berry-BqVQYZZr.js → berry-yl-kJr_H.js} +0 -0
- /package/dist/web/assets/{bibtex-C_q8ygAM.js → bibtex-DoFFszjV.js} +0 -0
- /package/dist/web/assets/{bicep-DWS-2uWR.js → bicep-CWPi4nfK.js} +0 -0
- /package/dist/web/assets/{bird2-C0pvipi_.js → bird2-DXew-ut0.js} +0 -0
- /package/dist/web/assets/{bot-E9mcVZnr.js → bot-BHXjpQ7x.js} +0 -0
- /package/dist/web/assets/{c-BQFvJ6Ux.js → c-clbySDvd.js} +0 -0
- /package/dist/web/assets/{c3-Da53KeG6.js → c3-B65jvSM1.js} +0 -0
- /package/dist/web/assets/{cadence-B5X2vWm3.js → cadence-Cm8tQTHN.js} +0 -0
- /package/dist/web/assets/{catppuccin-frappe-Dm3rVY3b.js → catppuccin-frappe-DLeGslh_.js} +0 -0
- /package/dist/web/assets/{catppuccin-latte-ZxS-ga_K.js → catppuccin-latte-CR5GeHws.js} +0 -0
- /package/dist/web/assets/{catppuccin-macchiato-B0bAzXh0.js → catppuccin-macchiato-p-XgjxhP.js} +0 -0
- /package/dist/web/assets/{catppuccin-mocha-BeMC5hqi.js → catppuccin-mocha-B8QOAZLl.js} +0 -0
- /package/dist/web/assets/{chevron-right-DeUue2aK.js → chevron-right-CtcHmZg9.js} +0 -0
- /package/dist/web/assets/{circle-question-mark-PaJgx-3d.js → circle-question-mark-EVgisosn.js} +0 -0
- /package/dist/web/assets/{clarity-BRdirlsw.js → clarity-DPulbvKH.js} +0 -0
- /package/dist/web/assets/{clojure-pSLH-KQp.js → clojure-DFuWS20u.js} +0 -0
- /package/dist/web/assets/{cmake-DsZu4U4F.js → cmake-DejCqcu4.js} +0 -0
- /package/dist/web/assets/{code-TekEnDFM.js → code-Dupqw5Fr.js} +0 -0
- /package/dist/web/assets/{codeowners-CtkKTnsH.js → codeowners-BwAyqWIH.js} +0 -0
- /package/dist/web/assets/{codeql-BpP1PDrj.js → codeql-DgSwFjqI.js} +0 -0
- /package/dist/web/assets/{common-lisp-BX1XgHTt.js → common-lisp-CxIVJCtf.js} +0 -0
- /package/dist/web/assets/{coq-D2bX6-8g.js → coq-DLSjSnmf.js} +0 -0
- /package/dist/web/assets/{csharp-DcR97P0D.js → csharp-C1HHzXBp.js} +0 -0
- /package/dist/web/assets/{css-CIjciIIk.js → css-VXsMY--y.js} +0 -0
- /package/dist/web/assets/{csv-DW48Z5d-.js → csv-BEbcJdHz.js} +0 -0
- /package/dist/web/assets/{csv-parser-DVHBcvuE.js → csv-parser-DHvoTjMF.js} +0 -0
- /package/dist/web/assets/{cue-Byh1xHko.js → cue-BkDnFqUD.js} +0 -0
- /package/dist/web/assets/{cypher-TVlMMWma.js → cypher-1cMqojSQ.js} +0 -0
- /package/dist/web/assets/{d-CxaScvxf.js → d-BnYjRXtH.js} +0 -0
- /package/dist/web/assets/{dark-plus-sn-FFTT1.js → dark-plus-XfbaH7kZ.js} +0 -0
- /package/dist/web/assets/{dart-BmpakMe-.js → dart-Ca7s-8hK.js} +0 -0
- /package/dist/web/assets/{data-grid-types-BuMHLKXV.js → data-grid-types-DP-ZexEN.js} +0 -0
- /package/dist/web/assets/{database-COYAMZaw.js → database-Dj0DxgtX.js} +0 -0
- /package/dist/web/assets/{dax-B1aRUMXT.js → dax-CmuOw-mY.js} +0 -0
- /package/dist/web/assets/{desktop-C6lD62ar.js → desktop-C2gJ6Ovb.js} +0 -0
- /package/dist/web/assets/{diff-CupGmT1a.js → diff-BCEo1Ej7.js} +0 -0
- /package/dist/web/assets/{dist-Bi4gRyhr.js → dist-CipvJy9w.js} +0 -0
- /package/dist/web/assets/{dist-m_oJqIDk.js → dist-D__U4ZJz.js} +0 -0
- /package/dist/web/assets/{docker-DjDr3TJF.js → docker-DN2jlyAh.js} +0 -0
- /package/dist/web/assets/{dotenv-QeT1SLTv.js → dotenv-NExMY2kS.js} +0 -0
- /package/dist/web/assets/{dracula-yI5kpKp5.js → dracula-B9lbE01y.js} +0 -0
- /package/dist/web/assets/{dracula-soft-CYF6cJce.js → dracula-soft-CMBBfKF_.js} +0 -0
- /package/dist/web/assets/{dream-maker-TBDKiHrV.js → dream-maker-DEyDwFsd.js} +0 -0
- /package/dist/web/assets/{emacs-lisp-B7aZTnJ_.js → emacs-lisp-D_qP2zS6.js} +0 -0
- /package/dist/web/assets/{everforest-dark-CN77B1NJ.js → everforest-dark-DbHa2U-p.js} +0 -0
- /package/dist/web/assets/{everforest-light-CyFxGMIs.js → everforest-light-BISkJchP.js} +0 -0
- /package/dist/web/assets/{fennel-C6ktGUzp.js → fennel-6B22SfJR.js} +0 -0
- /package/dist/web/assets/{file-exclamation-point-DBEC-Kst.js → file-exclamation-point-D-ZORzYB.js} +0 -0
- /package/dist/web/assets/{fish-Vr62C2vP.js → fish-CubIIvJD.js} +0 -0
- /package/dist/web/assets/{fluent-CH3IJUki.js → fluent-DF55zQ09.js} +0 -0
- /package/dist/web/assets/{fortran-free-form-BN7VmmxZ.js → fortran-free-form-DvOu8jAt.js} +0 -0
- /package/dist/web/assets/{gdscript-BYdRNu_P.js → gdscript-DCPxdLpq.js} +0 -0
- /package/dist/web/assets/{gdshader-C2XOq90k.js → gdshader-CTZ381FO.js} +0 -0
- /package/dist/web/assets/{genie-B4hkIXNU.js → genie-C_QDtvgU.js} +0 -0
- /package/dist/web/assets/{gherkin-CW9NH2DW.js → gherkin-BcvK42tF.js} +0 -0
- /package/dist/web/assets/{github-dark-BWCf99kM.js → github-dark-C9afs_4w.js} +0 -0
- /package/dist/web/assets/{github-dark-default-DZ1m_6OP.js → github-dark-default-CKGVrl3Z.js} +0 -0
- /package/dist/web/assets/{github-dark-dimmed-CUXSQ8bS.js → github-dark-dimmed-C3dQZ_LC.js} +0 -0
- /package/dist/web/assets/{github-dark-high-contrast-B6BvU8H-.js → github-dark-high-contrast-DW78QukY.js} +0 -0
- /package/dist/web/assets/{github-light-Ch-E92cy.js → github-light-BnP2dznS.js} +0 -0
- /package/dist/web/assets/{github-light-default-CKFslV7i.js → github-light-default-C2fPZzPG.js} +0 -0
- /package/dist/web/assets/{github-light-high-contrast-DiJVeRlZ.js → github-light-high-contrast-BzIuUFR2.js} +0 -0
- /package/dist/web/assets/{gleam-D4dP7V5M.js → gleam-BpeKwEIO.js} +0 -0
- /package/dist/web/assets/{gn-DuO2D2eW.js → gn-nUb_Mit0.js} +0 -0
- /package/dist/web/assets/{gnuplot-Df_8pFbI.js → gnuplot-D7I0v20p.js} +0 -0
- /package/dist/web/assets/{go-BL16cMJO.js → go-D7Qqska7.js} +0 -0
- /package/dist/web/assets/{groovy-rfHeCRqy.js → groovy-DS-pne5-.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-hard-CLbDN-E3.js → gruvbox-dark-hard-C0W01fsq.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-medium-Df0L0qje.js → gruvbox-dark-medium-Bqo6fQbg.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-soft-DV6TAcen.js → gruvbox-dark-soft-D-XSM_fu.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-hard-CWXUzp9b.js → gruvbox-light-hard-IVAwMJRl.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-medium-BOHMe1-7.js → gruvbox-light-medium-38ATiG7i.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-soft-DrrS2sdV.js → gruvbox-light-soft-DnZr3c_0.js} +0 -0
- /package/dist/web/assets/{haskell-DybKb9uW.js → haskell-uQcywkDH.js} +0 -0
- /package/dist/web/assets/{haxe-DLRwZxmt.js → haxe-c6bI4_GT.js} +0 -0
- /package/dist/web/assets/{hcl-CusCzwOk.js → hcl-CQXTiEXq.js} +0 -0
- /package/dist/web/assets/{hjson-BygWIJ-3.js → hjson-ChETf2bz.js} +0 -0
- /package/dist/web/assets/{hlsl-DCKvuEyZ.js → hlsl-BMC4JGoE.js} +0 -0
- /package/dist/web/assets/{horizon-DSOVAzyH.js → horizon-BusFlhLW.js} +0 -0
- /package/dist/web/assets/{horizon-bright-DKfVjGj_.js → horizon-bright-2oD0Mz7W.js} +0 -0
- /package/dist/web/assets/{houston-Ddm8AgpV.js → houston-DdbbjqFg.js} +0 -0
- /package/dist/web/assets/{hy-DzZa6alE.js → hy-D_SOuqw9.js} +0 -0
- /package/dist/web/assets/{image-gallery-CObzTisL.js → image-gallery-BWFpZAAP.js} +0 -0
- /package/dist/web/assets/{imba-aiXalPnK.js → imba-BxLOHO5I.js} +0 -0
- /package/dist/web/assets/{ini-CAvrVa5R.js → ini-ox-CFcg0.js} +0 -0
- /package/dist/web/assets/{java-PRMSQp24.js → java-Bzo8yIal.js} +0 -0
- /package/dist/web/assets/{javascript-DQR6GQKs.js → javascript-DHuz9VXn.js} +0 -0
- /package/dist/web/assets/{json-uWUKqOxq.js → json-0_y80FD5.js} +0 -0
- /package/dist/web/assets/{json5-R_LXJXL0.js → json5-CEQ50pGM.js} +0 -0
- /package/dist/web/assets/{jsonc-tC5zvrPO.js → jsonc-CfrLEAKA.js} +0 -0
- /package/dist/web/assets/{jsonl-BAwnWh7U.js → jsonl-fKbrANC2.js} +0 -0
- /package/dist/web/assets/{jsonnet-CPj4HCRm.js → jsonnet-DKbkPaQ2.js} +0 -0
- /package/dist/web/assets/{jssm-B7HswxOM.js → jssm-Dxxx1Hqu.js} +0 -0
- /package/dist/web/assets/{jsx-z4TGELE1.js → jsx-DlJL-Oj3.js} +0 -0
- /package/dist/web/assets/{kanagawa-dragon-BpeLlraV.js → kanagawa-dragon-CwN4SV1c.js} +0 -0
- /package/dist/web/assets/{kanagawa-lotus-CLnIPAGs.js → kanagawa-lotus-BHltayiE.js} +0 -0
- /package/dist/web/assets/{kanagawa-wave-BglPniBb.js → kanagawa-wave-D-KXPjw6.js} +0 -0
- /package/dist/web/assets/{kdl-B6blIqLq.js → kdl-DvtoJdFo.js} +0 -0
- /package/dist/web/assets/{kotlin-DVAEYiwY.js → kotlin-CTS4MLcx.js} +0 -0
- /package/dist/web/assets/{kusto-Ba87977j.js → kusto-HtSE_sKm.js} +0 -0
- /package/dist/web/assets/{laserwave-C-NuzoMp.js → laserwave-DaXZG9ge.js} +0 -0
- /package/dist/web/assets/{lean-CJ_KLkrJ.js → lean-BYtGUfWx.js} +0 -0
- /package/dist/web/assets/{less-Dfn9YC_2.js → less-BoxmU_Mk.js} +0 -0
- /package/dist/web/assets/{lib-DTaN9riD.js → lib-Bpbn00xM.js} +0 -0
- /package/dist/web/assets/{libesm-DdtEjhIi.js → libesm-tR4XlhMj.js} +0 -0
- /package/dist/web/assets/{light-plus-B3BLlguG.js → light-plus-Bt5CyUuo.js} +0 -0
- /package/dist/web/assets/{llvm-6UDP3NQb.js → llvm-CSdk9q9V.js} +0 -0
- /package/dist/web/assets/{log-QW3dqr1D.js → log-B-kp_3CL.js} +0 -0
- /package/dist/web/assets/{logo-DUinJheI.js → logo-DdIsXFDO.js} +0 -0
- /package/dist/web/assets/{luau-B1vcBzl8.js → luau-DUBpLlzQ.js} +0 -0
- /package/dist/web/assets/{make-CqNL10gS.js → make-B3JVjoW_.js} +0 -0
- /package/dist/web/assets/{markdown-BQNMNiYS.js → markdown-Seon0vHs.js} +0 -0
- /package/dist/web/assets/{material-theme-rbV8EefR.js → material-theme-Nq-ChX1P.js} +0 -0
- /package/dist/web/assets/{material-theme-darker-BZrskvoo.js → material-theme-darker-CPV4ayXJ.js} +0 -0
- /package/dist/web/assets/{material-theme-lighter-B0CBBjBw.js → material-theme-lighter-0kyjYqEd.js} +0 -0
- /package/dist/web/assets/{material-theme-ocean-CX_CHnQq.js → material-theme-ocean-DGpAp5co.js} +0 -0
- /package/dist/web/assets/{material-theme-palenight-ztiOCPbw.js → material-theme-palenight-B0AUn0NG.js} +0 -0
- /package/dist/web/assets/{matlab-tHQDNC9G.js → matlab-C2waytxs.js} +0 -0
- /package/dist/web/assets/{mdx-D4kZ6c6G.js → mdx-DAis6R6I.js} +0 -0
- /package/dist/web/assets/{mermaid-DlR4U4Pe.js → mermaid-_rnT2YGD.js} +0 -0
- /package/dist/web/assets/{min-dark-BX-xHAD2.js → min-dark-BSSjchUB.js} +0 -0
- /package/dist/web/assets/{min-light-Bxw0_Gqq.js → min-light-DomAFQsa.js} +0 -0
- /package/dist/web/assets/{mipsasm-DYyZAum-.js → mipsasm-bBgtvPyG.js} +0 -0
- /package/dist/web/assets/{mojo-q9wuEYKR.js → mojo-Cp9BayW0.js} +0 -0
- /package/dist/web/assets/{monokai-D9vrJ8JM.js → monokai-CL_9gbmn.js} +0 -0
- /package/dist/web/assets/{moonbit-C9roWxMb.js → moonbit-BS_fcr-P.js} +0 -0
- /package/dist/web/assets/{move-BvhjG2ic.js → move-C79AH45U.js} +0 -0
- /package/dist/web/assets/{narrat-BXGbPwG3.js → narrat-CJ5s3BDf.js} +0 -0
- /package/dist/web/assets/{nextflow-groovy-CMy5-Z4k.js → nextflow-groovy-ZHa4JrPJ.js} +0 -0
- /package/dist/web/assets/{night-owl-CBQBcbmw.js → night-owl-Jkf9zFQK.js} +0 -0
- /package/dist/web/assets/{night-owl-light-CC-brflp.js → night-owl-light-DRPeaG5J.js} +0 -0
- /package/dist/web/assets/{nix-B9EAdptu.js → nix-D2Jet9DN.js} +0 -0
- /package/dist/web/assets/{nord-DxASd4qG.js → nord-CREVs22j.js} +0 -0
- /package/dist/web/assets/{nushell-BsY59i7N.js → nushell-CAiDi_mR.js} +0 -0
- /package/dist/web/assets/{objective-c-CoeQAcnP.js → objective-c-CVkmJkC1.js} +0 -0
- /package/dist/web/assets/{objective-cpp-BysdFvND.js → objective-cpp-DIKDO1Ly.js} +0 -0
- /package/dist/web/assets/{ocaml-CrtQYMMK.js → ocaml-R9qtGQhs.js} +0 -0
- /package/dist/web/assets/{odin-B8pz4gIL.js → odin-DTYNQqVr.js} +0 -0
- /package/dist/web/assets/{one-dark-pro-3sSHqoqQ.js → one-dark-pro-BSLWUJn5.js} +0 -0
- /package/dist/web/assets/{one-light-LUZAvT8g.js → one-light-DbkRXG3t.js} +0 -0
- /package/dist/web/assets/{openscad-DcKia-sV.js → openscad-BlPcSnmT.js} +0 -0
- /package/dist/web/assets/{pascal-zM5SlmgF.js → pascal-B1Y46ZZB.js} +0 -0
- /package/dist/web/assets/{pkl-C_r_zLLt.js → pkl-BhJSJbFv.js} +0 -0
- /package/dist/web/assets/{plastic-B3cRtgKD.js → plastic-BzxsCTpi.js} +0 -0
- /package/dist/web/assets/{plsql-BzyjheXU.js → plsql-DBba7dyP.js} +0 -0
- /package/dist/web/assets/{plus-DcuJuDC3.js → plus-Dm36mgLh.js} +0 -0
- /package/dist/web/assets/{po-Dz4OaDNi.js → po-BvgLlnNo.js} +0 -0
- /package/dist/web/assets/{poimandres-BBbtYwmR.js → poimandres-DUaI_1JP.js} +0 -0
- /package/dist/web/assets/{polar-Che1XC2Z.js → polar-C7uILwJn.js} +0 -0
- /package/dist/web/assets/{postcss-DouzwG4F.js → postcss-BgJlpFdw.js} +0 -0
- /package/dist/web/assets/{powerquery-YOdcTZmd.js → powerquery-Dn1MIpZu.js} +0 -0
- /package/dist/web/assets/{powershell-8ojzYH34.js → powershell-Bo-DYzOS.js} +0 -0
- /package/dist/web/assets/{prisma-DCmjceML.js → prisma-CTLs5IdT.js} +0 -0
- /package/dist/web/assets/{prolog-ByNNz2pB.js → prolog-QRGun3eG.js} +0 -0
- /package/dist/web/assets/{proto-DWMt6Qu1.js → proto-B7PI7apn.js} +0 -0
- /package/dist/web/assets/{puppet-osfKyZp4.js → puppet-CBq0tLrP.js} +0 -0
- /package/dist/web/assets/{purescript-ClIblkvh.js → purescript-DFewOQb2.js} +0 -0
- /package/dist/web/assets/{python-Ctyr4faP.js → python-iWuxKXvT.js} +0 -0
- /package/dist/web/assets/{qmldir-CbNgyhnI.js → qmldir-cXiW3AsF.js} +0 -0
- /package/dist/web/assets/{qss-LbRHzb21.js → qss-DASwAbBL.js} +0 -0
- /package/dist/web/assets/{r-Dvfjp0wc.js → r-TU2eaIPw.js} +0 -0
- /package/dist/web/assets/{racket-DI8v8nzD.js → racket-SkRKqrLY.js} +0 -0
- /package/dist/web/assets/{raku-CX1q9GW0.js → raku-D31lthkZ.js} +0 -0
- /package/dist/web/assets/{react-8hrD3-kv.js → react-DjdYfcEe.js} +0 -0
- /package/dist/web/assets/{red-CSz3QEOw.js → red-CTcQZevb.js} +0 -0
- /package/dist/web/assets/{reg-FMjhUQE-.js → reg-D8YAsTGf.js} +0 -0
- /package/dist/web/assets/{regexp-CCSe1Fc4.js → regexp-CD2uvAWx.js} +0 -0
- /package/dist/web/assets/{rel-Ce0UO-OB.js → rel-CAaI-1fg.js} +0 -0
- /package/dist/web/assets/{resolve-theme-B9Mgd5GG.js → resolve-theme-B0eotaPq.js} +0 -0
- /package/dist/web/assets/{riscv-BFZrdZtB.js → riscv-DR-hJVIj.js} +0 -0
- /package/dist/web/assets/{ron-D0t4kvJG.js → ron-CuUCJ0n4.js} +0 -0
- /package/dist/web/assets/{rose-pine-HzwmOzHM.js → rose-pine-aFHxW48i.js} +0 -0
- /package/dist/web/assets/{rose-pine-dawn-CSp9xAF9.js → rose-pine-dawn-Bqz2sBRY.js} +0 -0
- /package/dist/web/assets/{rose-pine-moon-Cnzr2Cw0.js → rose-pine-moon-wqyh0an4.js} +0 -0
- /package/dist/web/assets/{rosmsg-DEJ8Snbv.js → rosmsg-CI1ywimO.js} +0 -0
- /package/dist/web/assets/{rust-2jBzrC0l.js → rust-p7Imk4G_.js} +0 -0
- /package/dist/web/assets/{sass-DD75Izu_.js → sass-C8JfaqCV.js} +0 -0
- /package/dist/web/assets/{save-BM4p9_9n.js → save-ignW_jk2.js} +0 -0
- /package/dist/web/assets/{scala-DpBKROIu.js → scala-DNxCW1By.js} +0 -0
- /package/dist/web/assets/{scheme-DM2jzwUK.js → scheme-BYuUPJoL.js} +0 -0
- /package/dist/web/assets/{sdbl-C34Cg6e7.js → sdbl-DbPeJPUr.js} +0 -0
- /package/dist/web/assets/{shellscript-DxfzKSgU.js → shellscript-DMiHlR3q.js} +0 -0
- /package/dist/web/assets/{shield-check-C3qYSU8a.js → shield-check-BSA9P3nI.js} +0 -0
- /package/dist/web/assets/{shield-off-D5tU7gQT.js → shield-off-Cb9J9x_n.js} +0 -0
- /package/dist/web/assets/{slack-dark-DIIV3bpD.js → slack-dark-C4xGcQXI.js} +0 -0
- /package/dist/web/assets/{slack-ochin-BTkxWjEP.js → slack-ochin-BzgRt_wm.js} +0 -0
- /package/dist/web/assets/{smalltalk-Bm0qg6SA.js → smalltalk-LDeL9PYH.js} +0 -0
- /package/dist/web/assets/{snazzy-light-ClAuuhn4.js → snazzy-light-CXE7a5j_.js} +0 -0
- /package/dist/web/assets/{solarized-dark-93sEWmYT.js → solarized-dark-DgUhY74x.js} +0 -0
- /package/dist/web/assets/{solarized-light-C74FvgcO.js → solarized-light-DD9C-H-9.js} +0 -0
- /package/dist/web/assets/{solidity-H9fSjkQP.js → solidity-CAbDB4D4.js} +0 -0
- /package/dist/web/assets/{splunk-CDTN2iAG.js → splunk-kQREPfIc.js} +0 -0
- /package/dist/web/assets/{sql-CoqObhgo.js → sql-CBzeNAD8.js} +0 -0
- /package/dist/web/assets/{ssh-config-C3Wv6qRp.js → ssh-config-L1euxrsM.js} +0 -0
- /package/dist/web/assets/{stylus-D0uTFXCy.js → stylus-DvBnYniP.js} +0 -0
- /package/dist/web/assets/{swift-DtMMgvRI.js → swift-DF5NDQp6.js} +0 -0
- /package/dist/web/assets/{synthwave-84-DAroyZBu.js → synthwave-84-DbBhB_Hq.js} +0 -0
- /package/dist/web/assets/{system-verilog-Bj7X_lq4.js → system-verilog-D8s2ZW_k.js} +0 -0
- /package/dist/web/assets/{systemd-CH8ApCUs.js → systemd-a5-XZJsG.js} +0 -0
- /package/dist/web/assets/{table-Di8pv2Y_.js → table-4P8kS7sg.js} +0 -0
- /package/dist/web/assets/{talonscript-70lVC3cw.js → talonscript-BLa0URTW.js} +0 -0
- /package/dist/web/assets/{tasl-WQR8VslV.js → tasl-DIoV4XcC.js} +0 -0
- /package/dist/web/assets/{tcl-caTR_frn.js → tcl-ztYAdXfQ.js} +0 -0
- /package/dist/web/assets/{terraform-CVRZ4SZ4.js → terraform-DvpCCiOZ.js} +0 -0
- /package/dist/web/assets/{tokyo-night-CDyT1jCI.js → tokyo-night-BkHlYUv0.js} +0 -0
- /package/dist/web/assets/{toml-B7D2mIDU.js → toml-acIrxos6.js} +0 -0
- /package/dist/web/assets/{tsv-2kdn5dqL.js → tsv-BJB5EVCT.js} +0 -0
- /package/dist/web/assets/{tsx-DJfG3fzg.js → tsx-B1MmXGT3.js} +0 -0
- /package/dist/web/assets/{turtle-DaQac_UT.js → turtle-DFceTiqd.js} +0 -0
- /package/dist/web/assets/{typescript-BLfAIchl.js → typescript-Dz9wU5Y1.js} +0 -0
- /package/dist/web/assets/{typespec-ymBaOi_c.js → typespec-CPuYZijj.js} +0 -0
- /package/dist/web/assets/{typst-DkvUYMT-.js → typst-CfsCIYv8.js} +0 -0
- /package/dist/web/assets/{use-is-mobile-BcuCjH19.js → use-is-mobile-K1a38BwI.js} +0 -0
- /package/dist/web/assets/{utils-E0yyGxXt.js → utils-B9H0d3Fh.js} +0 -0
- /package/dist/web/assets/{v-D4997FGs.js → v-CGo0jcXA.js} +0 -0
- /package/dist/web/assets/{vala-AFg9DmKE.js → vala-AsSR0hrb.js} +0 -0
- /package/dist/web/assets/{vb-DNUJ9fOP.js → vb-C7tvbXv1.js} +0 -0
- /package/dist/web/assets/{vendor-xterm-QDr0jvpJ.js → vendor-xterm-ClRVIJ-k.js} +0 -0
- /package/dist/web/assets/{verilog-BrnAQ3tF.js → verilog--a33ND-p.js} +0 -0
- /package/dist/web/assets/{vesper-DCZnFmY0.js → vesper-B_Z0h4pn.js} +0 -0
- /package/dist/web/assets/{vhdl-DoK4PjhE.js → vhdl-CWL5dZPN.js} +0 -0
- /package/dist/web/assets/{viml-D6EKG66q.js → viml-BglmT14Y.js} +0 -0
- /package/dist/web/assets/{vitesse-black-C6KILWdF.js → vitesse-black-RKFsSqQI.js} +0 -0
- /package/dist/web/assets/{vitesse-dark-BuSr6OT5.js → vitesse-dark-D7zDWNmc.js} +0 -0
- /package/dist/web/assets/{vitesse-light-M-eYyOoe.js → vitesse-light-MAp87W5b.js} +0 -0
- /package/dist/web/assets/{vyper-CwSN64Jn.js → vyper-CgCBYg1G.js} +0 -0
- /package/dist/web/assets/{wasm-BhQEkzil.js → wasm-BOG7ZeTT.js} +0 -0
- /package/dist/web/assets/{wasm-CVlf9Jwb.js → wasm-Bd258nS1.js} +0 -0
- /package/dist/web/assets/{wenyan-BC7irgM3.js → wenyan-DpShPKXZ.js} +0 -0
- /package/dist/web/assets/{wgsl-W-3UHMDO.js → wgsl-BakcCblK.js} +0 -0
- /package/dist/web/assets/{wikitext-T1DoFcm8.js → wikitext-NroRWVAO.js} +0 -0
- /package/dist/web/assets/{wit-DIrx_eCI.js → wit-B5CM2pg6.js} +0 -0
- /package/dist/web/assets/{wolfram-Cza4b443.js → wolfram-7MTFBJpR.js} +0 -0
- /package/dist/web/assets/{x-BsFLg-T8.js → x-BtzqXv1z.js} +0 -0
- /package/dist/web/assets/{yaml-DOZ10aZe.js → yaml-Bwr01G2K.js} +0 -0
- /package/dist/web/assets/{zenscript-DDAXkseY.js → zenscript-Dj8GATvi.js} +0 -0
- /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
|
-
|
|
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
|
-
|
|
21
|
-
|
|
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
|
-
/**
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
/**
|
|
126
|
-
|
|
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
|
|
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 {
|
|
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
|
-
|
|
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
|
}
|