@vividcodeai/embeddedcowork 0.0.21 → 0.0.23
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/dist/api-types.js +1 -0
- package/dist/auth/auth-store.js +134 -0
- package/dist/auth/http-auth.js +37 -0
- package/dist/auth/manager.js +140 -0
- package/dist/auth/password-hash.js +32 -0
- package/dist/auth/session-manager.js +17 -0
- package/dist/auth/token-manager.js +27 -0
- package/dist/background-processes/manager.js +576 -0
- package/dist/bin.js +24 -0
- package/dist/clients/connection-manager.js +93 -0
- package/dist/config/location.js +57 -0
- package/dist/config/schema.js +72 -0
- package/dist/events/bus.js +47 -0
- package/dist/filesystem/__tests__/search-cache.test.js +40 -0
- package/dist/filesystem/browser.js +292 -0
- package/dist/filesystem/search-cache.js +43 -0
- package/dist/filesystem/search.js +135 -0
- package/dist/index.js +496 -0
- package/dist/launcher.js +149 -0
- package/dist/loader.js +21 -0
- package/dist/logger.js +109 -0
- package/dist/opencode-config/README.md +32 -0
- package/dist/opencode-config/opencode.jsonc +35 -0
- package/dist/opencode-config/package.json +9 -0
- package/dist/opencode-config/plugin/embeddedcowork.ts +62 -0
- package/dist/opencode-config/plugin/lib/background-process.ts +265 -0
- package/dist/opencode-config/plugin/lib/client.ts +133 -0
- package/dist/opencode-config/plugin/lib/request.ts +214 -0
- package/dist/opencode-config.js +15 -0
- package/dist/opencode-downloader.js +295 -0
- package/dist/opencode-paths.js +167 -0
- package/dist/plugins/channel.js +40 -0
- package/dist/plugins/handlers.js +17 -0
- package/dist/plugins/voice-mode.js +78 -0
- package/dist/releases/dev-release-monitor.js +75 -0
- package/dist/releases/release-monitor.js +107 -0
- package/dist/runtime-paths.js +67 -0
- package/dist/server/__tests__/network-addresses.test.js +68 -0
- package/dist/server/__tests__/remote-proxy.test.js +204 -0
- package/dist/server/http-server.js +998 -0
- package/dist/server/network-addresses.js +114 -0
- package/dist/server/remote-proxy.js +466 -0
- package/dist/server/routes/auth-pages/login.html +135 -0
- package/dist/server/routes/auth-pages/token.html +93 -0
- package/dist/server/routes/auth.js +149 -0
- package/dist/server/routes/background-processes.js +78 -0
- package/dist/server/routes/events.js +66 -0
- package/dist/server/routes/filesystem.js +43 -0
- package/dist/server/routes/meta.js +44 -0
- package/dist/server/routes/opencode-status.js +10 -0
- package/dist/server/routes/plugin.js +70 -0
- package/dist/server/routes/remote-proxy.js +42 -0
- package/dist/server/routes/remote-servers.js +142 -0
- package/dist/server/routes/settings.js +69 -0
- package/dist/server/routes/sidecars.js +46 -0
- package/dist/server/routes/speech.js +63 -0
- package/dist/server/routes/storage.js +52 -0
- package/dist/server/routes/workspaces.js +221 -0
- package/dist/server/routes/worktrees.js +156 -0
- package/dist/server/tls.js +224 -0
- package/dist/settings/binaries.js +37 -0
- package/dist/settings/merge-patch.js +33 -0
- package/dist/settings/migrate.js +238 -0
- package/dist/settings/public-config.js +33 -0
- package/dist/settings/service.js +101 -0
- package/dist/settings/yaml-doc-store.js +96 -0
- package/dist/sidecars/manager.js +193 -0
- package/dist/speech/providers/openai-compatible.js +189 -0
- package/dist/speech/service.js +58 -0
- package/dist/storage/instance-store.js +56 -0
- package/dist/ui/__tests__/remote-ui.test.js +67 -0
- package/dist/ui/remote-ui.js +462 -0
- package/dist/workspaces/__tests__/spawn.test.js +139 -0
- package/dist/workspaces/git-mutations.js +98 -0
- package/dist/workspaces/git-status.js +323 -0
- package/dist/workspaces/git-worktrees.js +216 -0
- package/dist/workspaces/instance-events.js +180 -0
- package/dist/workspaces/manager.js +432 -0
- package/dist/workspaces/opencode-auth.js +16 -0
- package/dist/workspaces/runtime.js +366 -0
- package/dist/workspaces/spawn.js +219 -0
- package/dist/workspaces/worktree-directory.js +74 -0
- package/dist/workspaces/worktree-map.js +116 -0
- package/package.json +3 -12
- package/public/apple-touch-icon-180x180.png +0 -0
- package/public/assets/ChangesTab-C4_zdV74.js +2 -0
- package/public/assets/DiffToolbar-BsUPigM5.js +1 -0
- package/public/assets/EmbeddedCowork-Icon-DSw5nKk7.png +0 -0
- package/public/assets/FilesTab-Drvo30nM.js +2 -0
- package/public/assets/GitChangesTab-BhV6qTfP.js +2 -0
- package/public/assets/SplitFilePanel-BBrs329I.js +1 -0
- package/public/assets/StatusTab-DfYWlTSX.js +1 -0
- package/public/assets/abap-BdImnpbu.js +1 -0
- package/public/assets/actionscript-3-CfeIJUat.js +1 -0
- package/public/assets/ada-bCR0ucgS.js +1 -0
- package/public/assets/andromeeda-C-Jbm3Hp.js +1 -0
- package/public/assets/angular-html-CU67Zn6k.js +1 -0
- package/public/assets/angular-ts-BwZT4LLn.js +1 -0
- package/public/assets/apache-Pmp26Uib.js +1 -0
- package/public/assets/apex-DhZLUxFE.js +1 -0
- package/public/assets/apl-dKokRX4l.js +1 -0
- package/public/assets/applescript-Co6uUVPk.js +1 -0
- package/public/assets/ara-BRHolxvo.js +1 -0
- package/public/assets/asciidoc-Dv7Oe6Be.js +1 -0
- package/public/assets/asm-D_Q5rh1f.js +1 -0
- package/public/assets/astro-CbQHKStN.js +1 -0
- package/public/assets/aurora-x-D-2ljcwZ.js +1 -0
- package/public/assets/awk-DMzUqQB5.js +1 -0
- package/public/assets/ayu-dark-Cv9koXgw.js +1 -0
- package/public/assets/ballerina-BFfxhgS-.js +1 -0
- package/public/assets/bat-BkioyH1T.js +1 -0
- package/public/assets/beancount-k_qm7-4y.js +1 -0
- package/public/assets/berry-D08WgyRC.js +1 -0
- package/public/assets/bibtex-CHM0blh-.js +1 -0
- package/public/assets/bicep-Bmn6On1c.js +1 -0
- package/public/assets/blade-DVc8C-J4.js +1 -0
- package/public/assets/bsl-BO_Y6i37.js +1 -0
- package/public/assets/bundle-full-CAZqmV2E.js +13 -0
- package/public/assets/c-BIGW1oBm.js +1 -0
- package/public/assets/cadence-Bv_4Rxtq.js +1 -0
- package/public/assets/cairo-KRGpt6FW.js +1 -0
- package/public/assets/catppuccin-frappe-DFWUc33u.js +1 -0
- package/public/assets/catppuccin-latte-C9dUb6Cb.js +1 -0
- package/public/assets/catppuccin-macchiato-DQyhUUbL.js +1 -0
- package/public/assets/catppuccin-mocha-D87Tk5Gz.js +1 -0
- package/public/assets/clarity-D53aC0YG.js +1 -0
- package/public/assets/clojure-P80f7IUj.js +1 -0
- package/public/assets/cmake-D1j8_8rp.js +1 -0
- package/public/assets/cobol-nwyudZeR.js +1 -0
- package/public/assets/codeowners-Bp6g37R7.js +1 -0
- package/public/assets/codeql-DsOJ9woJ.js +1 -0
- package/public/assets/coffee-Ch7k5sss.js +1 -0
- package/public/assets/common-lisp-Cg-RD9OK.js +1 -0
- package/public/assets/coq-DkFqJrB1.js +1 -0
- package/public/assets/core-DhEqZVGG.js +1 -0
- package/public/assets/cpp-CofmeUqb.js +1 -0
- package/public/assets/crystal-tKQVLTB8.js +1 -0
- package/public/assets/csharp-CX12Zw3r.js +1 -0
- package/public/assets/css-DPfMkruS.js +1 -0
- package/public/assets/csv-fuZLfV_i.js +1 -0
- package/public/assets/cue-D82EKSYY.js +1 -0
- package/public/assets/cypher-COkxafJQ.js +1 -0
- package/public/assets/d-85-TOEBH.js +1 -0
- package/public/assets/dark-plus-eOWES_5F.js +1 -0
- package/public/assets/dart-CF10PKvl.js +1 -0
- package/public/assets/dax-CEL-wOlO.js +1 -0
- package/public/assets/desktop-BmXAJ9_W.js +1 -0
- package/public/assets/diff-D97Zzqfu.js +1 -0
- package/public/assets/diff-viewer--UIZ5GEn.js +1 -0
- package/public/assets/docker-BcOcwvcX.js +1 -0
- package/public/assets/dotenv-Da5cRb03.js +1 -0
- package/public/assets/dracula-BzJJZx-M.js +1 -0
- package/public/assets/dracula-soft-BXkSAIEj.js +1 -0
- package/public/assets/dream-maker-BtqSS_iP.js +1 -0
- package/public/assets/edge-BkV0erSs.js +1 -0
- package/public/assets/elixir-CDX3lj18.js +1 -0
- package/public/assets/elm-DbKCFpqz.js +1 -0
- package/public/assets/emacs-lisp-C9XAeP06.js +1 -0
- package/public/assets/erb-BOJIQeun.js +1 -0
- package/public/assets/erlang-DsQrWhSR.js +1 -0
- package/public/assets/event-DjZVAIBO.js +1 -0
- package/public/assets/everforest-dark-BgDCqdQA.js +1 -0
- package/public/assets/everforest-light-C8M2exoo.js +1 -0
- package/public/assets/fast-diff-vendor-DgdwVvTQ.js +1 -0
- package/public/assets/fennel-BYunw83y.js +1 -0
- package/public/assets/fish-BvzEVeQv.js +1 -0
- package/public/assets/fluent-C4IJs8-o.js +1 -0
- package/public/assets/fortran-fixed-form-BZjJHVRy.js +1 -0
- package/public/assets/fortran-free-form-D22FLkUw.js +1 -0
- package/public/assets/fsharp-CXgrBDvD.js +1 -0
- package/public/assets/gdresource-B7Tvp0Sc.js +1 -0
- package/public/assets/gdscript-DTMYz4Jt.js +1 -0
- package/public/assets/gdshader-DkwncUOv.js +1 -0
- package/public/assets/genie-D0YGMca9.js +1 -0
- package/public/assets/gherkin-DyxjwDmM.js +1 -0
- package/public/assets/git-commit-F4YmCXRG.js +1 -0
- package/public/assets/git-diff-vendor-CSgooKT_.js +52 -0
- package/public/assets/git-diff-vendor-HAZkIolJ.css +19 -0
- package/public/assets/git-rebase-r7XF79zn.js +1 -0
- package/public/assets/github-dark-DHJKELXO.js +1 -0
- package/public/assets/github-dark-default-Cuk6v7N8.js +1 -0
- package/public/assets/github-dark-dimmed-DH5Ifo-i.js +1 -0
- package/public/assets/github-dark-high-contrast-E3gJ1_iC.js +1 -0
- package/public/assets/github-light-DAi9KRSo.js +1 -0
- package/public/assets/github-light-default-D7oLnXFd.js +1 -0
- package/public/assets/github-light-high-contrast-BfjtVDDH.js +1 -0
- package/public/assets/gleam-BspZqrRM.js +1 -0
- package/public/assets/glimmer-js-Rg0-pVw9.js +1 -0
- package/public/assets/glimmer-ts-U6CK756n.js +1 -0
- package/public/assets/glsl-DplSGwfg.js +1 -0
- package/public/assets/gnuplot-DdkO51Og.js +1 -0
- package/public/assets/go-Dn2_MT6a.js +1 -0
- package/public/assets/graphql-ChdNCCLP.js +1 -0
- package/public/assets/groovy-gcz8RCvz.js +1 -0
- package/public/assets/gruvbox-dark-hard-CFHQjOhq.js +1 -0
- package/public/assets/gruvbox-dark-medium-GsRaNv29.js +1 -0
- package/public/assets/gruvbox-dark-soft-CVdnzihN.js +1 -0
- package/public/assets/gruvbox-light-hard-CH1njM8p.js +1 -0
- package/public/assets/gruvbox-light-medium-DRw_LuNl.js +1 -0
- package/public/assets/gruvbox-light-soft-hJgmCMqR.js +1 -0
- package/public/assets/hack-CaT9iCJl.js +1 -0
- package/public/assets/haml-B8DHNrY2.js +1 -0
- package/public/assets/handlebars-BL8al0AC.js +1 -0
- package/public/assets/haskell-Df6bDoY_.js +1 -0
- package/public/assets/haxe-CzTSHFRz.js +1 -0
- package/public/assets/hcl-BWvSN4gD.js +1 -0
- package/public/assets/highlight-vendor-8FKMu9os.js +10 -0
- package/public/assets/hjson-D5-asLiD.js +1 -0
- package/public/assets/hlsl-D3lLCCz7.js +1 -0
- package/public/assets/houston-DnULxvSX.js +1 -0
- package/public/assets/html-GMplVEZG.js +1 -0
- package/public/assets/html-derivative-BFtXZ54Q.js +1 -0
- package/public/assets/http-jrhK8wxY.js +1 -0
- package/public/assets/hurl-irOxFIW8.js +1 -0
- package/public/assets/hxml-Bvhsp5Yf.js +1 -0
- package/public/assets/hy-DFXneXwc.js +1 -0
- package/public/assets/imba-DGztddWO.js +1 -0
- package/public/assets/index--0EL0_Tu.js +2 -0
- package/public/assets/index-BKMyzTSR.js +1 -0
- package/public/assets/index-BLouhjer.js +1 -0
- package/public/assets/index-CLSJ4cO9.js +1 -0
- package/public/assets/index-CgjnEdBS.js +1 -0
- package/public/assets/index-ChCPoe9m.js +1 -0
- package/public/assets/index-Co-dJ-Xs.js +1 -0
- package/public/assets/index-Ctcq8Rhl.css +1 -0
- package/public/assets/index-Da0V-sLI.js +1 -0
- package/public/assets/index-hOT6sqTO.js +1 -0
- package/public/assets/ini-BEwlwnbL.js +1 -0
- package/public/assets/java-CylS5w8V.js +1 -0
- package/public/assets/javascript-wDzz0qaB.js +1 -0
- package/public/assets/jinja-4LBKfQ-Z.js +1 -0
- package/public/assets/jison-wvAkD_A8.js +1 -0
- package/public/assets/json-Cp-IABpG.js +1 -0
- package/public/assets/json5-C9tS-k6U.js +1 -0
- package/public/assets/jsonc-Des-eS-w.js +1 -0
- package/public/assets/jsonl-DcaNXYhu.js +1 -0
- package/public/assets/jsonnet-DFQXde-d.js +1 -0
- package/public/assets/jssm-C2t-YnRu.js +1 -0
- package/public/assets/jsx-g9-lgVsj.js +1 -0
- package/public/assets/julia-C8NyazO9.js +1 -0
- package/public/assets/kanagawa-dragon-CkXjmgJE.js +1 -0
- package/public/assets/kanagawa-lotus-CfQXZHmo.js +1 -0
- package/public/assets/kanagawa-wave-DWedfzmr.js +1 -0
- package/public/assets/kdl-DV7GczEv.js +1 -0
- package/public/assets/kotlin-BdnUsdx6.js +1 -0
- package/public/assets/kusto-BvAqAH-y.js +1 -0
- package/public/assets/laserwave-DUszq2jm.js +1 -0
- package/public/assets/latex-BUKiar2Z.js +1 -0
- package/public/assets/lean-DP1Csr6i.js +1 -0
- package/public/assets/less-B1dDrJ26.js +1 -0
- package/public/assets/light-plus-B7mTdjB0.js +1 -0
- package/public/assets/liquid-DYVedYrR.js +1 -0
- package/public/assets/llvm-BtvRca6l.js +1 -0
- package/public/assets/loading-CugGjKDZ.css +1 -0
- package/public/assets/loading-CvW03p4Z.js +2 -0
- package/public/assets/log-2UxHyX5q.js +1 -0
- package/public/assets/logo-BtOb2qkB.js +1 -0
- package/public/assets/lua-BbnMAYS6.js +1 -0
- package/public/assets/luau-CXu1NL6O.js +1 -0
- package/public/assets/main-ByuKWHRz.js +53 -0
- package/public/assets/make-CHLpvVh8.js +1 -0
- package/public/assets/markdown-BBFC6uy4.js +58 -0
- package/public/assets/markdown-Cvjx9yec.js +1 -0
- package/public/assets/marko-CPi9NSCl.js +1 -0
- package/public/assets/material-theme-D5KoaKCx.js +1 -0
- package/public/assets/material-theme-darker-BfHTSMKl.js +1 -0
- package/public/assets/material-theme-lighter-B0m2ddpp.js +1 -0
- package/public/assets/material-theme-ocean-CyktbL80.js +1 -0
- package/public/assets/material-theme-palenight-Csfq5Kiy.js +1 -0
- package/public/assets/matlab-D7o27uSR.js +1 -0
- package/public/assets/mdc-DUICxH0z.js +1 -0
- package/public/assets/mdx-Cmh6b_Ma.js +1 -0
- package/public/assets/mermaid-DKYwYmdq.js +1 -0
- package/public/assets/min-dark-CafNBF8u.js +1 -0
- package/public/assets/min-light-CTRr51gU.js +1 -0
- package/public/assets/mipsasm-CKIfxQSi.js +1 -0
- package/public/assets/mojo-1DNp92w6.js +1 -0
- package/public/assets/monaco-viewer-DnczYBfh.js +26 -0
- package/public/assets/monokai-D4h5O-jR.js +1 -0
- package/public/assets/move-Bu9oaDYs.js +1 -0
- package/public/assets/narrat-DRg8JJMk.js +1 -0
- package/public/assets/nextflow-CUEJCptM.js +1 -0
- package/public/assets/nginx-DknmC5AR.js +1 -0
- package/public/assets/night-owl-C39BiMTA.js +1 -0
- package/public/assets/nim-CVrawwO9.js +1 -0
- package/public/assets/nix-BbRYJGeE.js +1 -0
- package/public/assets/nord-Ddv68eIx.js +1 -0
- package/public/assets/nushell-C-sUppwS.js +1 -0
- package/public/assets/objective-c-DXmwc3jG.js +1 -0
- package/public/assets/objective-cpp-CLxacb5B.js +1 -0
- package/public/assets/ocaml-C0hk2d4L.js +1 -0
- package/public/assets/one-dark-pro-DVMEJ2y_.js +1 -0
- package/public/assets/one-light-PoHY5YXO.js +1 -0
- package/public/assets/pascal-D93ZcfNL.js +1 -0
- package/public/assets/perl-C0TMdlhV.js +1 -0
- package/public/assets/php-CDn_0X-4.js +1 -0
- package/public/assets/pkl-u5AG7uiY.js +1 -0
- package/public/assets/plastic-3e1v2bzS.js +1 -0
- package/public/assets/plsql-ChMvpjG-.js +1 -0
- package/public/assets/po-BTJTHyun.js +1 -0
- package/public/assets/poimandres-CS3Unz2-.js +1 -0
- package/public/assets/polar-C0HS_06l.js +1 -0
- package/public/assets/postcss-CXtECtnM.js +1 -0
- package/public/assets/powerquery-CEu0bR-o.js +1 -0
- package/public/assets/powershell-Dpen1YoG.js +1 -0
- package/public/assets/prisma-Dd19v3D-.js +1 -0
- package/public/assets/prolog-CbFg5uaA.js +1 -0
- package/public/assets/proto-DyJlTyXw.js +1 -0
- package/public/assets/pug-CGlum2m_.js +1 -0
- package/public/assets/puppet-BMWR74SV.js +1 -0
- package/public/assets/purescript-CklMAg4u.js +1 -0
- package/public/assets/python-B6aJPvgy.js +1 -0
- package/public/assets/qml-3beO22l8.js +1 -0
- package/public/assets/qmldir-C8lEn-DE.js +1 -0
- package/public/assets/qss-IeuSbFQv.js +1 -0
- package/public/assets/r-DiinP2Uv.js +1 -0
- package/public/assets/racket-BqYA7rlc.js +1 -0
- package/public/assets/raku-DXvB9xmW.js +1 -0
- package/public/assets/razor-WgofotgN.js +1 -0
- package/public/assets/red-bN70gL4F.js +1 -0
- package/public/assets/reg-C-SQnVFl.js +1 -0
- package/public/assets/regexp-CDVJQ6XC.js +1 -0
- package/public/assets/rel-C3B-1QV4.js +1 -0
- package/public/assets/riscv-BM1_JUlF.js +1 -0
- package/public/assets/rose-pine-BHrmToEH.js +1 -0
- package/public/assets/rose-pine-dawn-CnK8MTSM.js +1 -0
- package/public/assets/rose-pine-moon-NleAzG8P.js +1 -0
- package/public/assets/rosmsg-BJDFO7_C.js +1 -0
- package/public/assets/rst-B0xPkSld.js +1 -0
- package/public/assets/ruby-BvKwtOVI.js +1 -0
- package/public/assets/rust-B1yitclQ.js +1 -0
- package/public/assets/sas-cz2c8ADy.js +1 -0
- package/public/assets/sass-Cj5Yp3dK.js +1 -0
- package/public/assets/scala-C151Ov-r.js +1 -0
- package/public/assets/scheme-C98Dy4si.js +1 -0
- package/public/assets/scss-OYdSNvt2.js +1 -0
- package/public/assets/sdbl-DVxCFoDh.js +1 -0
- package/public/assets/shaderlab-Dg9Lc6iA.js +1 -0
- package/public/assets/shellscript-Yzrsuije.js +1 -0
- package/public/assets/shellsession-BADoaaVG.js +1 -0
- package/public/assets/slack-dark-BthQWCQV.js +1 -0
- package/public/assets/slack-ochin-DqwNpetd.js +1 -0
- package/public/assets/smalltalk-BERRCDM3.js +1 -0
- package/public/assets/snazzy-light-Bw305WKR.js +1 -0
- package/public/assets/solarized-dark-DXbdFlpD.js +1 -0
- package/public/assets/solarized-light-L9t79GZl.js +1 -0
- package/public/assets/solidity-BbcW6ACK.js +1 -0
- package/public/assets/soy-Brmx7dQM.js +1 -0
- package/public/assets/sparql-rVzFXLq3.js +1 -0
- package/public/assets/splunk-BtCnVYZw.js +1 -0
- package/public/assets/sql-BLtJtn59.js +1 -0
- package/public/assets/ssh-config-_ykCGR6B.js +1 -0
- package/public/assets/stata-BH5u7GGu.js +1 -0
- package/public/assets/stylus-BEDo0Tqx.js +1 -0
- package/public/assets/svelte-3Dk4HxPD.js +1 -0
- package/public/assets/swift-Dg5xB15N.js +1 -0
- package/public/assets/synthwave-84-CbfX1IO0.js +1 -0
- package/public/assets/system-verilog-CnnmHF94.js +1 -0
- package/public/assets/systemd-4A_iFExJ.js +1 -0
- package/public/assets/talonscript-CkByrt1z.js +1 -0
- package/public/assets/tasl-QIJgUcNo.js +1 -0
- package/public/assets/tcl-dwOrl1Do.js +1 -0
- package/public/assets/templ-W15q3VgB.js +1 -0
- package/public/assets/terraform-BETggiCN.js +1 -0
- package/public/assets/tex-Cppo0RY3.js +1 -0
- package/public/assets/todo-BLpUqy61.js +1 -0
- package/public/assets/tokyo-night-hegEt444.js +1 -0
- package/public/assets/toml-vGWfd6FD.js +1 -0
- package/public/assets/tool-call-B4Xz6FbC.js +60 -0
- package/public/assets/ts-tags-zn1MmPIZ.js +1 -0
- package/public/assets/tsv-B_m7g4N7.js +1 -0
- package/public/assets/tsx-COt5Ahok.js +1 -0
- package/public/assets/turtle-BsS91CYL.js +1 -0
- package/public/assets/twig-CO9l9SDP.js +1 -0
- package/public/assets/typescript-BPQ3VLAy.js +1 -0
- package/public/assets/typespec-Df68jz8_.js +1 -0
- package/public/assets/typst-DHCkPAjA.js +1 -0
- package/public/assets/unified-picker-BrzM_sH6.js +1 -0
- package/public/assets/v-BcVCzyr7.js +1 -0
- package/public/assets/vala-CsfeWuGM.js +1 -0
- package/public/assets/vb-D17OF-Vu.js +1 -0
- package/public/assets/verilog-BQ8w6xss.js +1 -0
- package/public/assets/vesper-DU1UobuO.js +1 -0
- package/public/assets/vhdl-CeAyd5Ju.js +1 -0
- package/public/assets/viml-CJc9bBzg.js +1 -0
- package/public/assets/vitesse-black-Bkuqu6BP.js +1 -0
- package/public/assets/vitesse-dark-D0r3Knsf.js +1 -0
- package/public/assets/vitesse-light-CVO1_9PV.js +1 -0
- package/public/assets/vue-CCoi5OLL.js +1 -0
- package/public/assets/vue-html-DAAvJJDi.js +1 -0
- package/public/assets/vue-vine-_Ih-lPRR.js +1 -0
- package/public/assets/vyper-CDx5xZoG.js +1 -0
- package/public/assets/wasm-CG6Dc4jp.js +1 -0
- package/public/assets/wasm-MzD3tlZU.js +1 -0
- package/public/assets/wenyan-BV7otONQ.js +1 -0
- package/public/assets/wgsl-Dx-B1_4e.js +1 -0
- package/public/assets/wikitext-BhOHFoWU.js +1 -0
- package/public/assets/wit-5i3qLPDT.js +1 -0
- package/public/assets/wolfram-lXgVvXCa.js +1 -0
- package/public/assets/wrap-text-B1i7zgLk.js +1 -0
- package/public/assets/xml-sdJ4AIDG.js +1 -0
- package/public/assets/xsl-CtQFsRM5.js +1 -0
- package/public/assets/yaml-Buea-lGh.js +1 -0
- package/public/assets/zenscript-DVFEvuxE.js +1 -0
- package/public/assets/zig-VOosw3JB.js +1 -0
- package/public/favicon.ico +0 -0
- package/public/index.html +44 -0
- package/public/loading.html +33 -0
- package/public/logo.png +0 -0
- package/public/manifest.webmanifest +1 -0
- package/public/maskable-icon-512x512.png +0 -0
- package/public/monaco/vs/base/browser/ui/codicons/codicon/codicon.ttf +0 -0
- package/public/monaco/vs/base/worker/workerMain.js +31 -0
- package/public/monaco/vs/basic-languages/cpp/cpp.js +10 -0
- package/public/monaco/vs/basic-languages/kotlin/kotlin.js +10 -0
- package/public/monaco/vs/basic-languages/markdown/markdown.js +10 -0
- package/public/monaco/vs/basic-languages/python/python.js +10 -0
- package/public/monaco/vs/editor/editor.main.css +8 -0
- package/public/monaco/vs/editor/editor.main.js +798 -0
- package/public/monaco/vs/language/css/cssMode.js +13 -0
- package/public/monaco/vs/language/css/cssWorker.js +77 -0
- package/public/monaco/vs/language/html/htmlMode.js +13 -0
- package/public/monaco/vs/language/html/htmlWorker.js +454 -0
- package/public/monaco/vs/language/json/jsonMode.js +19 -0
- package/public/monaco/vs/language/json/jsonWorker.js +42 -0
- package/public/monaco/vs/language/typescript/tsMode.js +20 -0
- package/public/monaco/vs/language/typescript/tsWorker.js +51328 -0
- package/public/monaco/vs/loader.js +11 -0
- package/public/monaco.worker.js +7 -0
- package/public/pwa-192x192.png +0 -0
- package/public/pwa-512x512.png +0 -0
- package/public/pwa-64x64.png +0 -0
- package/public/registerSW.js +1 -0
- package/public/sw.js +1 -0
- package/public/ui-version.json +3 -0
- package/public/workbox-60d14903.js +1 -0
- package/bin/cli.js +0 -56
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
import { spawn } from "child_process";
|
|
2
|
+
import { readFile } from "fs/promises";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { normalizeGitWorktreeRelativePath } from "./git-mutations";
|
|
5
|
+
async function readFileAsDiffText(filePath) {
|
|
6
|
+
return readFile(filePath, "utf-8");
|
|
7
|
+
}
|
|
8
|
+
async function readGitBlobAsDiffText(resultPromise, missingOk = false) {
|
|
9
|
+
const result = await resultPromise;
|
|
10
|
+
if (!result.ok) {
|
|
11
|
+
return decodeGitShowResult(result, missingOk);
|
|
12
|
+
}
|
|
13
|
+
return result.stdout;
|
|
14
|
+
}
|
|
15
|
+
function runGit(args, cwd, acceptedExitCodes = [0]) {
|
|
16
|
+
return new Promise((resolve) => {
|
|
17
|
+
const child = spawn("git", args, { cwd, stdio: ["ignore", "pipe", "pipe"] });
|
|
18
|
+
let stdout = "";
|
|
19
|
+
let stderr = "";
|
|
20
|
+
child.stdout?.on("data", (chunk) => {
|
|
21
|
+
stdout += chunk.toString();
|
|
22
|
+
});
|
|
23
|
+
child.stderr?.on("data", (chunk) => {
|
|
24
|
+
stderr += chunk.toString();
|
|
25
|
+
});
|
|
26
|
+
child.once("error", (error) => {
|
|
27
|
+
resolve({ ok: false, error, stdout, stderr });
|
|
28
|
+
});
|
|
29
|
+
child.once("close", (code) => {
|
|
30
|
+
if (acceptedExitCodes.includes(code ?? 0)) {
|
|
31
|
+
resolve({ ok: true, stdout });
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
const error = new Error(stderr.trim() || `git ${args.join(" ")} failed with code ${code}`);
|
|
35
|
+
resolve({ ok: false, error, stdout, stderr });
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
function ensureEntry(map, path) {
|
|
41
|
+
const existing = map.get(path);
|
|
42
|
+
if (existing)
|
|
43
|
+
return existing;
|
|
44
|
+
const next = {
|
|
45
|
+
path,
|
|
46
|
+
originalPath: null,
|
|
47
|
+
stagedStatus: null,
|
|
48
|
+
stagedAdditions: 0,
|
|
49
|
+
stagedDeletions: 0,
|
|
50
|
+
unstagedStatus: null,
|
|
51
|
+
unstagedAdditions: 0,
|
|
52
|
+
unstagedDeletions: 0,
|
|
53
|
+
};
|
|
54
|
+
map.set(path, next);
|
|
55
|
+
return next;
|
|
56
|
+
}
|
|
57
|
+
function normalizeGitStatusPath(value) {
|
|
58
|
+
return value.trim().replace(/\\+/g, "/");
|
|
59
|
+
}
|
|
60
|
+
function parseGitChangeKind(code) {
|
|
61
|
+
const normalized = code.trim().toUpperCase();
|
|
62
|
+
if (!normalized)
|
|
63
|
+
return null;
|
|
64
|
+
if (normalized === "A")
|
|
65
|
+
return "added";
|
|
66
|
+
if (normalized === "M")
|
|
67
|
+
return "modified";
|
|
68
|
+
if (normalized === "D")
|
|
69
|
+
return "deleted";
|
|
70
|
+
if (normalized.startsWith("R"))
|
|
71
|
+
return "renamed";
|
|
72
|
+
if (normalized.startsWith("C"))
|
|
73
|
+
return "copied";
|
|
74
|
+
if (normalized === "U")
|
|
75
|
+
return "unmerged";
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
function applyNameStatusOutput(map, output, target) {
|
|
79
|
+
const tokens = output.split("\0");
|
|
80
|
+
let index = 0;
|
|
81
|
+
while (index < tokens.length) {
|
|
82
|
+
const record = tokens[index++] ?? "";
|
|
83
|
+
if (!record)
|
|
84
|
+
continue;
|
|
85
|
+
const parts = record.split("\t");
|
|
86
|
+
const statusCode = parseGitChangeKind(parts[0] ?? "");
|
|
87
|
+
if (!statusCode)
|
|
88
|
+
continue;
|
|
89
|
+
const inlinePath = parts.slice(1).join("\t");
|
|
90
|
+
const firstPath = inlinePath || tokens[index++] || "";
|
|
91
|
+
const secondPath = statusCode === "renamed" || statusCode === "copied" ? tokens[index++] || "" : "";
|
|
92
|
+
const path = statusCode === "renamed" || statusCode === "copied" ? secondPath || firstPath : firstPath;
|
|
93
|
+
const normalizedPath = normalizeGitStatusPath(path);
|
|
94
|
+
if (!normalizedPath)
|
|
95
|
+
continue;
|
|
96
|
+
const entry = ensureEntry(map, normalizedPath);
|
|
97
|
+
entry[target] = statusCode;
|
|
98
|
+
if (statusCode === "renamed" || statusCode === "copied") {
|
|
99
|
+
const originalPath = normalizeGitStatusPath(firstPath);
|
|
100
|
+
entry.originalPath = originalPath || entry.originalPath || null;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function applyUntrackedOutput(map, output) {
|
|
105
|
+
for (const rawLine of output.split(/\r?\n/)) {
|
|
106
|
+
const path = normalizeGitStatusPath(rawLine);
|
|
107
|
+
if (!path)
|
|
108
|
+
continue;
|
|
109
|
+
ensureEntry(map, path).unstagedStatus = "untracked";
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function parseSingleNumstat(output) {
|
|
113
|
+
for (const rawLine of output.split(/\r?\n/)) {
|
|
114
|
+
const line = rawLine.trim();
|
|
115
|
+
if (!line)
|
|
116
|
+
continue;
|
|
117
|
+
const parts = rawLine.split("\t");
|
|
118
|
+
const isBinary = parts[0] === "-" || parts[1] === "-";
|
|
119
|
+
return {
|
|
120
|
+
additions: isBinary ? 0 : Number.parseInt(parts[0] ?? "0", 10) || 0,
|
|
121
|
+
deletions: isBinary ? 0 : Number.parseInt(parts[1] ?? "0", 10) || 0,
|
|
122
|
+
isBinary,
|
|
123
|
+
found: true,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
return { additions: 0, deletions: 0, isBinary: false, found: false };
|
|
127
|
+
}
|
|
128
|
+
async function getUntrackedFileNumstat(workspaceFolder, relativePath) {
|
|
129
|
+
const absolutePath = path.join(workspaceFolder, relativePath);
|
|
130
|
+
const result = await runGit(["diff", "--numstat", "--no-index", "--", "/dev/null", absolutePath], workspaceFolder, [0, 1]);
|
|
131
|
+
if (!result.ok) {
|
|
132
|
+
throw result.error;
|
|
133
|
+
}
|
|
134
|
+
const parsed = parseSingleNumstat(result.stdout);
|
|
135
|
+
return { additions: parsed.additions, deletions: parsed.deletions };
|
|
136
|
+
}
|
|
137
|
+
async function applyUntrackedFileStats(map, workspaceFolder) {
|
|
138
|
+
const pending = Array.from(map.values())
|
|
139
|
+
.filter((entry) => entry.unstagedStatus === "untracked")
|
|
140
|
+
.map(async (entry) => {
|
|
141
|
+
try {
|
|
142
|
+
const stats = await getUntrackedFileNumstat(workspaceFolder, entry.path);
|
|
143
|
+
entry.unstagedAdditions = stats.additions;
|
|
144
|
+
entry.unstagedDeletions = stats.deletions;
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
entry.unstagedAdditions = 0;
|
|
148
|
+
entry.unstagedDeletions = 0;
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
await Promise.all(pending);
|
|
152
|
+
}
|
|
153
|
+
function applyNumstatOutput(map, output, target) {
|
|
154
|
+
const tokens = output.split("\0");
|
|
155
|
+
let index = 0;
|
|
156
|
+
while (index < tokens.length) {
|
|
157
|
+
const record = tokens[index++] ?? "";
|
|
158
|
+
if (!record)
|
|
159
|
+
continue;
|
|
160
|
+
const parts = record.split("\t");
|
|
161
|
+
if (parts.length < 3)
|
|
162
|
+
continue;
|
|
163
|
+
const additions = parts[0] === "-" ? 0 : Number.parseInt(parts[0] ?? "0", 10);
|
|
164
|
+
const deletions = parts[1] === "-" ? 0 : Number.parseInt(parts[1] ?? "0", 10);
|
|
165
|
+
const inlinePath = parts.slice(2).join("\t");
|
|
166
|
+
const isRenameLike = inlinePath === "";
|
|
167
|
+
const originalPath = isRenameLike ? normalizeGitStatusPath(tokens[index++] ?? "") : null;
|
|
168
|
+
const normalizedPath = normalizeGitStatusPath(isRenameLike ? tokens[index++] ?? "" : inlinePath);
|
|
169
|
+
if (!normalizedPath)
|
|
170
|
+
continue;
|
|
171
|
+
const entry = ensureEntry(map, normalizedPath);
|
|
172
|
+
if (originalPath) {
|
|
173
|
+
entry.originalPath = originalPath;
|
|
174
|
+
}
|
|
175
|
+
if (target === "staged") {
|
|
176
|
+
entry.stagedAdditions = Number.isFinite(additions) ? additions : 0;
|
|
177
|
+
entry.stagedDeletions = Number.isFinite(deletions) ? deletions : 0;
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
entry.unstagedAdditions = Number.isFinite(additions) ? additions : 0;
|
|
181
|
+
entry.unstagedDeletions = Number.isFinite(deletions) ? deletions : 0;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
export async function getWorktreeGitStatus(params) {
|
|
186
|
+
const { workspaceFolder, logger } = params;
|
|
187
|
+
const [stagedResult, unstagedResult, untrackedResult, stagedNumstatResult, unstagedNumstatResult] = await Promise.all([
|
|
188
|
+
runGit(["diff", "--name-status", "-z", "--cached", "--find-renames", "--find-copies"], workspaceFolder),
|
|
189
|
+
runGit(["diff", "--name-status", "-z", "--find-renames", "--find-copies"], workspaceFolder),
|
|
190
|
+
runGit(["ls-files", "--others", "--exclude-standard"], workspaceFolder),
|
|
191
|
+
runGit(["diff", "--numstat", "-z", "--cached", "--find-renames", "--find-copies"], workspaceFolder),
|
|
192
|
+
runGit(["diff", "--numstat", "-z", "--find-renames", "--find-copies"], workspaceFolder),
|
|
193
|
+
]);
|
|
194
|
+
for (const result of [stagedResult, unstagedResult, untrackedResult, stagedNumstatResult, unstagedNumstatResult]) {
|
|
195
|
+
if (!result.ok) {
|
|
196
|
+
logger?.warn?.({ workspaceFolder, err: result.error }, "Failed to read git status for worktree");
|
|
197
|
+
throw result.error;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
const stagedOutput = stagedResult.stdout;
|
|
201
|
+
const unstagedOutput = unstagedResult.stdout;
|
|
202
|
+
const untrackedOutput = untrackedResult.stdout;
|
|
203
|
+
const stagedNumstatOutput = stagedNumstatResult.stdout;
|
|
204
|
+
const unstagedNumstatOutput = unstagedNumstatResult.stdout;
|
|
205
|
+
const entries = new Map();
|
|
206
|
+
applyNameStatusOutput(entries, stagedOutput, "stagedStatus");
|
|
207
|
+
applyNameStatusOutput(entries, unstagedOutput, "unstagedStatus");
|
|
208
|
+
applyUntrackedOutput(entries, untrackedOutput);
|
|
209
|
+
applyNumstatOutput(entries, stagedNumstatOutput, "staged");
|
|
210
|
+
applyNumstatOutput(entries, unstagedNumstatOutput, "unstaged");
|
|
211
|
+
await applyUntrackedFileStats(entries, workspaceFolder);
|
|
212
|
+
return Array.from(entries.values()).sort((a, b) => a.path.localeCompare(b.path));
|
|
213
|
+
}
|
|
214
|
+
function decodeGitShowResult(result, missingOk = false) {
|
|
215
|
+
if (result.ok)
|
|
216
|
+
return result.stdout;
|
|
217
|
+
const message = result.stderr?.trim() || result.error.message || "";
|
|
218
|
+
if (missingOk &&
|
|
219
|
+
(message.includes("exists on disk, but not in") ||
|
|
220
|
+
message.includes("Path '") ||
|
|
221
|
+
message.includes("does not exist") ||
|
|
222
|
+
message.includes("unknown revision or path not in the working tree"))) {
|
|
223
|
+
return "";
|
|
224
|
+
}
|
|
225
|
+
throw result.error;
|
|
226
|
+
}
|
|
227
|
+
async function readGitIndexBlob(workspaceFolder, normalizedPath) {
|
|
228
|
+
return runGit(["cat-file", "-p", `:${normalizedPath}`], workspaceFolder);
|
|
229
|
+
}
|
|
230
|
+
async function getTrackedDiffMetadata(params) {
|
|
231
|
+
const args = ["diff", "--numstat"];
|
|
232
|
+
if (params.scope === "staged") {
|
|
233
|
+
args.push("--cached");
|
|
234
|
+
}
|
|
235
|
+
args.push("--find-renames", "--find-copies", "--");
|
|
236
|
+
args.push(params.normalizedPath);
|
|
237
|
+
if (params.normalizedOriginalPath && params.normalizedOriginalPath !== params.normalizedPath) {
|
|
238
|
+
args.push(params.normalizedOriginalPath);
|
|
239
|
+
}
|
|
240
|
+
const result = await runGit(args, params.workspaceFolder);
|
|
241
|
+
if (!result.ok) {
|
|
242
|
+
throw result.error;
|
|
243
|
+
}
|
|
244
|
+
const parsed = parseSingleNumstat(result.stdout);
|
|
245
|
+
return { isBinary: parsed.isBinary, found: parsed.found };
|
|
246
|
+
}
|
|
247
|
+
async function getUntrackedDiffMetadata(params) {
|
|
248
|
+
const absolutePath = path.join(params.workspaceFolder, params.normalizedPath);
|
|
249
|
+
const result = await runGit(["diff", "--numstat", "--no-index", "--", "/dev/null", absolutePath], params.workspaceFolder, [0, 1]);
|
|
250
|
+
if (!result.ok) {
|
|
251
|
+
throw result.error;
|
|
252
|
+
}
|
|
253
|
+
return { isBinary: parseSingleNumstat(result.stdout).isBinary };
|
|
254
|
+
}
|
|
255
|
+
async function resolveUnstagedBeforePath(params) {
|
|
256
|
+
const currentPathResult = await readGitIndexBlob(params.workspaceFolder, params.normalizedPath);
|
|
257
|
+
if (currentPathResult.ok || !params.normalizedOriginalPath || params.normalizedOriginalPath === params.normalizedPath) {
|
|
258
|
+
return currentPathResult;
|
|
259
|
+
}
|
|
260
|
+
return readGitIndexBlob(params.workspaceFolder, params.normalizedOriginalPath);
|
|
261
|
+
}
|
|
262
|
+
export async function getWorktreeGitDiff(params) {
|
|
263
|
+
const normalizedPath = normalizeGitWorktreeRelativePath(params.path);
|
|
264
|
+
const normalizedOriginalPath = params.originalPath ? normalizeGitWorktreeRelativePath(params.originalPath) : null;
|
|
265
|
+
const trackedMetadata = await getTrackedDiffMetadata({
|
|
266
|
+
workspaceFolder: params.workspaceFolder,
|
|
267
|
+
scope: params.scope,
|
|
268
|
+
normalizedPath,
|
|
269
|
+
normalizedOriginalPath,
|
|
270
|
+
});
|
|
271
|
+
const diffMetadata = params.scope === "unstaged" && !trackedMetadata.found
|
|
272
|
+
? await getUntrackedDiffMetadata({
|
|
273
|
+
workspaceFolder: params.workspaceFolder,
|
|
274
|
+
normalizedPath,
|
|
275
|
+
})
|
|
276
|
+
: trackedMetadata;
|
|
277
|
+
if (diffMetadata.isBinary) {
|
|
278
|
+
return {
|
|
279
|
+
path: normalizedPath,
|
|
280
|
+
originalPath: normalizedOriginalPath,
|
|
281
|
+
scope: params.scope,
|
|
282
|
+
before: "",
|
|
283
|
+
after: "",
|
|
284
|
+
isBinary: true,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
if (params.scope === "staged") {
|
|
288
|
+
const [beforeResult, afterResult] = await Promise.all([
|
|
289
|
+
readGitBlobAsDiffText(runGit(["show", `HEAD:${normalizedOriginalPath ?? normalizedPath}`], params.workspaceFolder), true),
|
|
290
|
+
readGitBlobAsDiffText(readGitIndexBlob(params.workspaceFolder, normalizedPath), true),
|
|
291
|
+
]);
|
|
292
|
+
return {
|
|
293
|
+
path: normalizedPath,
|
|
294
|
+
originalPath: normalizedOriginalPath,
|
|
295
|
+
scope: params.scope,
|
|
296
|
+
before: beforeResult,
|
|
297
|
+
after: afterResult,
|
|
298
|
+
isBinary: false,
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
const indexResult = await resolveUnstagedBeforePath({
|
|
302
|
+
workspaceFolder: params.workspaceFolder,
|
|
303
|
+
normalizedPath,
|
|
304
|
+
normalizedOriginalPath,
|
|
305
|
+
});
|
|
306
|
+
const beforeResult = await readGitBlobAsDiffText(Promise.resolve(indexResult), true);
|
|
307
|
+
let after = beforeResult;
|
|
308
|
+
const fsPath = path.join(params.workspaceFolder, normalizedPath);
|
|
309
|
+
try {
|
|
310
|
+
after = await readFileAsDiffText(fsPath);
|
|
311
|
+
}
|
|
312
|
+
catch {
|
|
313
|
+
after = "";
|
|
314
|
+
}
|
|
315
|
+
return {
|
|
316
|
+
path: normalizedPath,
|
|
317
|
+
originalPath: normalizedOriginalPath,
|
|
318
|
+
scope: params.scope,
|
|
319
|
+
before: beforeResult,
|
|
320
|
+
after,
|
|
321
|
+
isBinary: false,
|
|
322
|
+
};
|
|
323
|
+
}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { spawn } from "child_process";
|
|
3
|
+
import { promises as fsp } from "fs";
|
|
4
|
+
function isGitUnavailableResult(result) {
|
|
5
|
+
return !result.ok && result.error?.code === "ENOENT";
|
|
6
|
+
}
|
|
7
|
+
function runGit(args, cwd) {
|
|
8
|
+
return new Promise((resolve) => {
|
|
9
|
+
const child = spawn("git", args, { cwd, stdio: ["ignore", "pipe", "pipe"] });
|
|
10
|
+
let stdout = "";
|
|
11
|
+
let stderr = "";
|
|
12
|
+
child.stdout?.on("data", (chunk) => {
|
|
13
|
+
stdout += chunk.toString();
|
|
14
|
+
});
|
|
15
|
+
child.stderr?.on("data", (chunk) => {
|
|
16
|
+
stderr += chunk.toString();
|
|
17
|
+
});
|
|
18
|
+
child.once("error", (error) => {
|
|
19
|
+
resolve({ ok: false, error, stdout, stderr });
|
|
20
|
+
});
|
|
21
|
+
child.once("close", (code) => {
|
|
22
|
+
if (code === 0) {
|
|
23
|
+
resolve({ ok: true, stdout });
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
const error = new Error(stderr.trim() || `git ${args.join(" ")} failed with code ${code}`);
|
|
27
|
+
resolve({ ok: false, error, stdout, stderr });
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
export async function resolveRepoRoot(folder, logger) {
|
|
33
|
+
const result = await runGit(["rev-parse", "--show-toplevel"], folder);
|
|
34
|
+
if (isGitUnavailableResult(result)) {
|
|
35
|
+
throw new Error("Git is not installed or not available in PATH");
|
|
36
|
+
}
|
|
37
|
+
if (!result.ok) {
|
|
38
|
+
logger?.debug?.({ folder, err: result.error }, "Folder is not a Git repository; using workspace folder as root");
|
|
39
|
+
return { repoRoot: folder, isGitRepo: false };
|
|
40
|
+
}
|
|
41
|
+
const repoRoot = result.stdout.trim();
|
|
42
|
+
if (!repoRoot) {
|
|
43
|
+
return { repoRoot: folder, isGitRepo: false };
|
|
44
|
+
}
|
|
45
|
+
return { repoRoot, isGitRepo: true };
|
|
46
|
+
}
|
|
47
|
+
export async function isGitAvailable(folder) {
|
|
48
|
+
const result = await runGit(["--version"], folder);
|
|
49
|
+
return result.ok || !isGitUnavailableResult(result);
|
|
50
|
+
}
|
|
51
|
+
function parseWorktreePorcelain(output) {
|
|
52
|
+
const records = [];
|
|
53
|
+
const lines = output.split(/\r?\n/);
|
|
54
|
+
let current = {};
|
|
55
|
+
const flush = () => {
|
|
56
|
+
if (current.worktree) {
|
|
57
|
+
records.push({ worktree: current.worktree, branch: current.branch });
|
|
58
|
+
}
|
|
59
|
+
current = {};
|
|
60
|
+
};
|
|
61
|
+
for (const line of lines) {
|
|
62
|
+
const trimmed = line.trim();
|
|
63
|
+
if (!trimmed) {
|
|
64
|
+
flush();
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
const [key, ...rest] = trimmed.split(" ");
|
|
68
|
+
const value = rest.join(" ").trim();
|
|
69
|
+
if (key === "worktree") {
|
|
70
|
+
current.worktree = value;
|
|
71
|
+
}
|
|
72
|
+
else if (key === "branch") {
|
|
73
|
+
// branch is like refs/heads/foo
|
|
74
|
+
current.branch = value.replace(/^refs\/heads\//, "");
|
|
75
|
+
}
|
|
76
|
+
else if (key === "HEAD") {
|
|
77
|
+
current.head = value;
|
|
78
|
+
}
|
|
79
|
+
else if (key === "detached") {
|
|
80
|
+
current.detached = true;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
flush();
|
|
84
|
+
return records;
|
|
85
|
+
}
|
|
86
|
+
export async function listWorktrees(params) {
|
|
87
|
+
const { repoRoot, workspaceFolder, logger } = params;
|
|
88
|
+
const result = await runGit(["worktree", "list", "--porcelain"], workspaceFolder);
|
|
89
|
+
if (!result.ok) {
|
|
90
|
+
const rootDescriptor = { slug: "root", directory: repoRoot, kind: "root" };
|
|
91
|
+
logger?.debug?.({ repoRoot, err: result.error }, "Failed to list git worktrees; returning root only");
|
|
92
|
+
return [rootDescriptor];
|
|
93
|
+
}
|
|
94
|
+
const records = parseWorktreePorcelain(result.stdout);
|
|
95
|
+
const rootRecord = records.find((record) => path.resolve(record.worktree) === path.resolve(repoRoot));
|
|
96
|
+
const rootDescriptor = {
|
|
97
|
+
slug: "root",
|
|
98
|
+
directory: repoRoot,
|
|
99
|
+
kind: "root",
|
|
100
|
+
branch: rootRecord?.branch,
|
|
101
|
+
};
|
|
102
|
+
const worktrees = [rootDescriptor];
|
|
103
|
+
const seen = new Set(["root"]);
|
|
104
|
+
const normalizeSlug = (record) => {
|
|
105
|
+
const branch = (record.branch ?? "").trim();
|
|
106
|
+
if (branch) {
|
|
107
|
+
return branch;
|
|
108
|
+
}
|
|
109
|
+
const head = (record.head ?? "").trim();
|
|
110
|
+
if (head && /^[0-9a-f]{7,40}$/i.test(head)) {
|
|
111
|
+
return `detached-${head.slice(0, 7)}`;
|
|
112
|
+
}
|
|
113
|
+
// Fallback: stable-ish identifier derived from directory basename.
|
|
114
|
+
const base = path.basename(record.worktree || "");
|
|
115
|
+
return base ? `worktree-${base}` : "worktree";
|
|
116
|
+
};
|
|
117
|
+
for (const record of records) {
|
|
118
|
+
const abs = record.worktree;
|
|
119
|
+
if (!abs || typeof abs !== "string")
|
|
120
|
+
continue;
|
|
121
|
+
// Skip the root record (we always expose it as slug="root").
|
|
122
|
+
if (path.resolve(abs) === path.resolve(repoRoot)) {
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
const slug = normalizeSlug(record);
|
|
126
|
+
if (!slug || slug === "root") {
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (seen.has(slug)) {
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
seen.add(slug);
|
|
133
|
+
worktrees.push({ slug, directory: abs, kind: "worktree", branch: record.branch });
|
|
134
|
+
}
|
|
135
|
+
return worktrees;
|
|
136
|
+
}
|
|
137
|
+
export function isValidWorktreeSlug(slug) {
|
|
138
|
+
if (!slug)
|
|
139
|
+
return false;
|
|
140
|
+
const trimmed = slug.trim();
|
|
141
|
+
if (!trimmed)
|
|
142
|
+
return false;
|
|
143
|
+
if (trimmed.length > 200)
|
|
144
|
+
return false;
|
|
145
|
+
// Disallow control characters; allow branch-like slugs including '/'.
|
|
146
|
+
if (/[\x00-\x1F\x7F]/.test(trimmed))
|
|
147
|
+
return false;
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
export async function createManagedWorktree(params) {
|
|
151
|
+
const { repoRoot, workspaceFolder, logger } = params;
|
|
152
|
+
const branch = params.slug.trim();
|
|
153
|
+
if (!branch || branch === "root" || !isValidWorktreeSlug(branch)) {
|
|
154
|
+
throw new Error("Invalid worktree slug");
|
|
155
|
+
}
|
|
156
|
+
const sanitizeDirName = (input) => {
|
|
157
|
+
const normalized = input
|
|
158
|
+
.trim()
|
|
159
|
+
.replace(/[\\/]+/g, "-")
|
|
160
|
+
.replace(/\s+/g, "-")
|
|
161
|
+
.replace(/[^a-zA-Z0-9_.-]+/g, "-")
|
|
162
|
+
.replace(/-{2,}/g, "-")
|
|
163
|
+
.replace(/^-+|-+$/g, "");
|
|
164
|
+
return normalized || "worktree";
|
|
165
|
+
};
|
|
166
|
+
const worktreesDir = path.join(repoRoot, ".embeddedcowork", "worktrees");
|
|
167
|
+
const targetDir = path.join(worktreesDir, sanitizeDirName(branch));
|
|
168
|
+
await fsp.mkdir(worktreesDir, { recursive: true });
|
|
169
|
+
try {
|
|
170
|
+
const stat = await fsp.stat(targetDir);
|
|
171
|
+
if (stat.isDirectory()) {
|
|
172
|
+
throw new Error("Worktree directory already exists");
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
catch (error) {
|
|
176
|
+
const code = error.code;
|
|
177
|
+
if (code !== "ENOENT") {
|
|
178
|
+
throw error;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
logger?.debug?.({ slug: branch, branch, targetDir }, "Creating managed git worktree");
|
|
182
|
+
// Prefer creating a new branch from HEAD.
|
|
183
|
+
const first = await runGit(["worktree", "add", "-b", branch, targetDir, "HEAD"], workspaceFolder);
|
|
184
|
+
if (first.ok) {
|
|
185
|
+
return { slug: branch, directory: targetDir, branch };
|
|
186
|
+
}
|
|
187
|
+
const message = first.stderr?.toLowerCase() ?? first.error.message.toLowerCase();
|
|
188
|
+
if (message.includes("already exists")) {
|
|
189
|
+
// If the branch already exists, add worktree for that branch.
|
|
190
|
+
const second = await runGit(["worktree", "add", targetDir, branch], workspaceFolder);
|
|
191
|
+
if (second.ok) {
|
|
192
|
+
return { slug: branch, directory: targetDir, branch };
|
|
193
|
+
}
|
|
194
|
+
throw second.error;
|
|
195
|
+
}
|
|
196
|
+
throw first.error;
|
|
197
|
+
}
|
|
198
|
+
export async function removeWorktree(params) {
|
|
199
|
+
const { workspaceFolder, logger } = params;
|
|
200
|
+
const directory = (params.directory ?? "").trim();
|
|
201
|
+
if (!directory) {
|
|
202
|
+
throw new Error("Invalid worktree directory");
|
|
203
|
+
}
|
|
204
|
+
logger?.debug?.({ directory, force: Boolean(params.force) }, "Removing git worktree");
|
|
205
|
+
const args = ["worktree", "remove"];
|
|
206
|
+
if (params.force) {
|
|
207
|
+
args.push("--force");
|
|
208
|
+
}
|
|
209
|
+
args.push(directory);
|
|
210
|
+
const result = await runGit(args, workspaceFolder);
|
|
211
|
+
if (!result.ok) {
|
|
212
|
+
throw result.error;
|
|
213
|
+
}
|
|
214
|
+
// Best-effort cleanup of stale metadata.
|
|
215
|
+
await runGit(["worktree", "prune"], workspaceFolder).catch(() => undefined);
|
|
216
|
+
}
|