diffsplain 0.4.3 → 0.6.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/README.md +17 -12
- package/dist/assets/abap-CLvhMVsD.js +1 -0
- package/dist/assets/actionscript-3--17pq3dv.js +1 -0
- package/dist/assets/ada-C5qYipkI.js +1 -0
- package/dist/assets/andromeeda-vGVdxbeo.js +1 -0
- package/dist/assets/angular-html-vBvPnd6a.js +1 -0
- package/dist/assets/angular-ts-CDzF1Z6a.js +1 -0
- package/dist/assets/apache-U0d_L8uA.js +1 -0
- package/dist/assets/apex-VAyPSnFM.js +1 -0
- package/dist/assets/apl-Bm9bxvP7.js +1 -0
- package/dist/assets/applescript-CCn79oCD.js +1 -0
- package/dist/assets/ara-4CJ0cIlV.js +1 -0
- package/dist/assets/asciidoc-DE70LPWp.js +1 -0
- package/dist/assets/asm-Cmm7eHzH.js +1 -0
- package/dist/assets/astro-RNrNWCYO.js +1 -0
- package/dist/assets/aurora-x-CDeNXAV0.js +1 -0
- package/dist/assets/awk-BWXHIvNe.js +1 -0
- package/dist/assets/ayu-dark-DluEY0Gj.js +1 -0
- package/dist/assets/ayu-light-C3h-C4tm.js +1 -0
- package/dist/assets/ayu-mirage-Bqwy1Gya.js +1 -0
- package/dist/assets/ballerina-B7ZEbQpA.js +1 -0
- package/dist/assets/bat-Bo4NYOV-.js +1 -0
- package/dist/assets/beancount-D-usSTwE.js +1 -0
- package/dist/assets/berry-DKpUyyne.js +1 -0
- package/dist/assets/bibtex-Ci_nEsc7.js +1 -0
- package/dist/assets/bicep-CUHmPFLl.js +1 -0
- package/dist/assets/bird2-C6vDhewU.js +1 -0
- package/dist/assets/blade-On-NBYUv.js +1 -0
- package/dist/assets/bsl-BkkzgIyY.js +1 -0
- package/dist/assets/c-hRmhFgD0.js +1 -0
- package/dist/assets/c3-BFHwR3_K.js +1 -0
- package/dist/assets/cadence-CQ2zXKGN.js +1 -0
- package/dist/assets/cairo-DLTphjLi.js +1 -0
- package/dist/assets/catppuccin-frappe-3VR1Za6u.js +1 -0
- package/dist/assets/catppuccin-latte-DwIHMF0Q.js +1 -0
- package/dist/assets/catppuccin-macchiato-DYnBP6_5.js +1 -0
- package/dist/assets/catppuccin-mocha-DYhrFGRu.js +1 -0
- package/dist/assets/clarity-SemFz856.js +1 -0
- package/dist/assets/clojure-DqKBuwfJ.js +1 -0
- package/dist/assets/cmake-Bj61d0ZC.js +1 -0
- package/dist/assets/cobol-CIqc3k2t.js +1 -0
- package/dist/assets/codeowners-C8r90Shi.js +1 -0
- package/dist/assets/codeql-oeQT6MSM.js +1 -0
- package/dist/assets/coffee-Cd5EyvvS.js +1 -0
- package/dist/assets/common-lisp-Cv5bFMCO.js +1 -0
- package/dist/assets/coq-BrsZFFmf.js +1 -0
- package/dist/assets/cpp-zXFAAp_S.js +1 -0
- package/dist/assets/crystal-DRYY4cSw.js +1 -0
- package/dist/assets/csharp-oqKa8noW.js +1 -0
- package/dist/assets/css-C4op_MsD.js +1 -0
- package/dist/assets/csv-Dx-8-gkx.js +1 -0
- package/dist/assets/cue-CE9AQfxI.js +1 -0
- package/dist/assets/cypher-ClKdZ_lG.js +1 -0
- package/dist/assets/d-qD-0Kul2.js +1 -0
- package/dist/assets/dark-plus-Cs2F2srj.js +1 -0
- package/dist/assets/dart-CnvKMtbv.js +1 -0
- package/dist/assets/dax-BkyTk9wS.js +1 -0
- package/dist/assets/desktop-Dlh5hvp9.js +1 -0
- package/dist/assets/diff-woXpYk--.js +1 -0
- package/dist/assets/docker-IyjqRm3v.js +1 -0
- package/dist/assets/dotenv-_5a1GRtc.js +1 -0
- package/dist/assets/dracula-BHWKrbxM.js +1 -0
- package/dist/assets/dracula-soft-5eyTD99u.js +1 -0
- package/dist/assets/dream-maker-DW3nJb8Q.js +1 -0
- package/dist/assets/edge-d3rJkErf.js +1 -0
- package/dist/assets/elixir-DPqlJhYM.js +1 -0
- package/dist/assets/elm-DgU37I8a.js +1 -0
- package/dist/assets/emacs-lisp-B4R74twV.js +1 -0
- package/dist/assets/erb-CZVB_ntC.js +1 -0
- package/dist/assets/erlang-Cphh6RMH.js +1 -0
- package/dist/assets/everforest-dark-sB-x3p7T.js +1 -0
- package/dist/assets/everforest-light-Df2xbC6M.js +1 -0
- package/dist/assets/fennel-DQxkIbk2.js +1 -0
- package/dist/assets/fish-BJitypiv.js +1 -0
- package/dist/assets/fluent-C03EYrpw.js +1 -0
- package/dist/assets/fortran-fixed-form-DEKoE2YW.js +1 -0
- package/dist/assets/fortran-free-form-CYNrtFtB.js +1 -0
- package/dist/assets/fsharp-D13ZGOAj.js +1 -0
- package/dist/assets/gdresource-C0sCabJj.js +1 -0
- package/dist/assets/gdscript-Cp2uCuqX.js +1 -0
- package/dist/assets/gdshader-CBce3t8t.js +1 -0
- package/dist/assets/genie-CV2tkWYe.js +1 -0
- package/dist/assets/gherkin-DExj1W_8.js +1 -0
- package/dist/assets/git-commit-BSykSTBG.js +1 -0
- package/dist/assets/git-rebase-hUkltHZG.js +1 -0
- package/dist/assets/github-dark-C-LZuMrd.js +1 -0
- package/dist/assets/github-dark-default-DXG-b-1a.js +1 -0
- package/dist/assets/github-dark-dimmed-Bx1FflLF.js +1 -0
- package/dist/assets/github-dark-high-contrast-B_tTalzw.js +1 -0
- package/dist/assets/github-light-EUqPIrTm.js +1 -0
- package/dist/assets/github-light-default-BXViO-2h.js +1 -0
- package/dist/assets/github-light-high-contrast-B68TUdTA.js +1 -0
- package/dist/assets/gleam-CSRkHgEL.js +1 -0
- package/dist/assets/glimmer-js-5XOT9GQ8.js +1 -0
- package/dist/assets/glimmer-ts-DT7D0Kfq.js +1 -0
- package/dist/assets/glsl-Br4_Eh5O.js +1 -0
- package/dist/assets/gn-ilITqXS6.js +1 -0
- package/dist/assets/gnuplot-7GGW24-e.js +1 -0
- package/dist/assets/go-rLFTqkRN.js +1 -0
- package/dist/assets/graphql--BmZ_AYP.js +1 -0
- package/dist/assets/groovy-CacY0gHj.js +1 -0
- package/dist/assets/gruvbox-dark-hard-C820rvS2.js +1 -0
- package/dist/assets/gruvbox-dark-medium-BPjhmG05.js +1 -0
- package/dist/assets/gruvbox-dark-soft-MrdJrrXF.js +1 -0
- package/dist/assets/gruvbox-light-hard-BC_s9l72.js +1 -0
- package/dist/assets/gruvbox-light-medium-BAWPOn9u.js +1 -0
- package/dist/assets/gruvbox-light-soft-BSMLrYjP.js +1 -0
- package/dist/assets/hack-CMdqGDoA.js +1 -0
- package/dist/assets/haml-DLEOHGmg.js +1 -0
- package/dist/assets/handlebars-BfUftoV0.js +1 -0
- package/dist/assets/haskell-D8IpX4py.js +1 -0
- package/dist/assets/haxe-OTjmBuCE.js +1 -0
- package/dist/assets/hcl-Dh228itO.js +1 -0
- package/dist/assets/hjson-CxZEssPk.js +1 -0
- package/dist/assets/hlsl-Cvrh5tZx.js +1 -0
- package/dist/assets/horizon-CE9ld1lL.js +1 -0
- package/dist/assets/horizon-bright-DSNQnXHK.js +1 -0
- package/dist/assets/houston-CsvMBhTu.js +1 -0
- package/dist/assets/html-derivative-D5cZE6C4.js +1 -0
- package/dist/assets/html-uOgx2iYC.js +1 -0
- package/dist/assets/http-cW9c66J_.js +1 -0
- package/dist/assets/hurl-BztURO2n.js +1 -0
- package/dist/assets/hxml-B0Qn7Nwc.js +1 -0
- package/dist/assets/hy-CZbG8q4J.js +1 -0
- package/dist/assets/imba-DsUTQ-LC.js +1 -0
- package/dist/assets/{index-BB6eHlnY.css → index-C2p_1iAk.css} +1 -1
- package/dist/assets/index-DZFM4-3L.js +1568 -0
- package/dist/assets/ini-B5eOa1yu.js +1 -0
- package/dist/assets/java-Cy4mnKaj.js +1 -0
- package/dist/assets/javascript-_Z02t_9Q.js +1 -0
- package/dist/assets/jinja-BppBm5gt.js +1 -0
- package/dist/assets/jison-Dzns436M.js +1 -0
- package/dist/assets/json-BYkfLOry.js +1 -0
- package/dist/assets/json5-BR5RXkoi.js +1 -0
- package/dist/assets/jsonc-CYpm1nAK.js +1 -0
- package/dist/assets/jsonl-CmCQp5Yx.js +1 -0
- package/dist/assets/jsonnet-CJTPZ8u_.js +1 -0
- package/dist/assets/jssm-DXw9l8Rf.js +1 -0
- package/dist/assets/jsx-DtAm8NUb.js +1 -0
- package/dist/assets/julia-CLIMRuh0.js +1 -0
- package/dist/assets/just-DMg47an6.js +1 -0
- package/dist/assets/kanagawa-dragon-CXtmUGW6.js +1 -0
- package/dist/assets/kanagawa-lotus-BN08jTvb.js +1 -0
- package/dist/assets/kanagawa-wave-CTweb8Dz.js +1 -0
- package/dist/assets/kdl-CsD5j6eV.js +1 -0
- package/dist/assets/kotlin-DhhofPvG.js +1 -0
- package/dist/assets/kusto-C7mF5XQf.js +1 -0
- package/dist/assets/laserwave-C_8bwKvT.js +1 -0
- package/dist/assets/latex-D05ztCOx.js +1 -0
- package/dist/assets/lean-CewbzKMR.js +1 -0
- package/dist/assets/less-DVTAwKKz.js +1 -0
- package/dist/assets/light-plus-DVQuIRkW.js +1 -0
- package/dist/assets/liquid-DpImQR4t.js +1 -0
- package/dist/assets/llvm-Cm23YOpf.js +1 -0
- package/dist/assets/log-BNLmms1o.js +1 -0
- package/dist/assets/logo-Cluzi2Zq.js +1 -0
- package/dist/assets/lua--ZHUYQUU.js +1 -0
- package/dist/assets/luau-FMPmPwt6.js +1 -0
- package/dist/assets/make-Dixweg8N.js +1 -0
- package/dist/assets/markdown-BYOwaDjH.js +1 -0
- package/dist/assets/marko-Dh3Xi08i.js +1 -0
- package/dist/assets/material-theme-Bm3Qr25_.js +1 -0
- package/dist/assets/material-theme-darker-2IIEA8gg.js +1 -0
- package/dist/assets/material-theme-lighter-uhdI0v04.js +1 -0
- package/dist/assets/material-theme-ocean-CHQ94UKr.js +1 -0
- package/dist/assets/material-theme-palenight-B5W6OYN7.js +1 -0
- package/dist/assets/matlab-D7qyCx1q.js +1 -0
- package/dist/assets/mdc-Br6Pt78u.js +1 -0
- package/dist/assets/mdx-DQZ5AkYe.js +1 -0
- package/dist/assets/mermaid-Bk4SNUv9.js +1 -0
- package/dist/assets/min-dark-BSWPekZh.js +1 -0
- package/dist/assets/min-light-DDpmG2fV.js +1 -0
- package/dist/assets/mipsasm-BMqwQI7S.js +1 -0
- package/dist/assets/mojo-BgCJLMeH.js +1 -0
- package/dist/assets/monokai-CdkpiU2Y.js +1 -0
- package/dist/assets/moonbit-CaWjb8XO.js +1 -0
- package/dist/assets/move-B1IS1UjX.js +1 -0
- package/dist/assets/narrat-_X_XdTYD.js +1 -0
- package/dist/assets/nextflow-BJtWHP5T.js +1 -0
- package/dist/assets/nextflow-groovy-DJMQeKeT.js +1 -0
- package/dist/assets/nginx-CwSU6U6d.js +1 -0
- package/dist/assets/night-owl-DhmEMT88.js +1 -0
- package/dist/assets/night-owl-light-eJ-hLW7d.js +1 -0
- package/dist/assets/nim-CBbTwyeq.js +1 -0
- package/dist/assets/nix-IvuFDN5E.js +1 -0
- package/dist/assets/nord-Cb4Vim4T.js +1 -0
- package/dist/assets/nushell-DcLAeLz5.js +1 -0
- package/dist/assets/objective-c-D1A_Heim.js +1 -0
- package/dist/assets/objective-cpp-BsSzOQcm.js +1 -0
- package/dist/assets/ocaml-O90oeIOV.js +1 -0
- package/dist/assets/odin-B1RWQWA5.js +1 -0
- package/dist/assets/one-dark-pro-CLwyXe_n.js +1 -0
- package/dist/assets/one-light-D7Lr4KcI.js +1 -0
- package/dist/assets/openscad-BUDT5pXO.js +1 -0
- package/dist/assets/pascal-4ZHwLPI5.js +1 -0
- package/dist/assets/perl-D3jQu3LN.js +1 -0
- package/dist/assets/php-BMeXBzlU.js +1 -0
- package/dist/assets/pierre-dark-CpLgRqie.js +1 -0
- package/dist/assets/pierre-dark-protanopia-deuteranopia-B35FxJx-.js +1 -0
- package/dist/assets/pierre-dark-soft-kZQmAZld.js +1 -0
- package/dist/assets/pierre-dark-tritanopia-CpjhbsIL.js +1 -0
- package/dist/assets/pierre-dark-vibrant-CpQYzh95.js +1 -0
- package/dist/assets/pierre-light-CoaEpmwp.js +1 -0
- package/dist/assets/pierre-light-protanopia-deuteranopia-0fSaH845.js +1 -0
- package/dist/assets/pierre-light-soft-lWLdNTOI.js +1 -0
- package/dist/assets/pierre-light-tritanopia-CEbqgOJL.js +1 -0
- package/dist/assets/pierre-light-vibrant-D80Fkn33.js +1 -0
- package/dist/assets/pkl-ot-7Btpt.js +1 -0
- package/dist/assets/plastic-DQwYfKfQ.js +1 -0
- package/dist/assets/plsql-DGHpHOYJ.js +1 -0
- package/dist/assets/po-BiJDBrnU.js +1 -0
- package/dist/assets/poimandres-DRFjx7u4.js +1 -0
- package/dist/assets/polar-C7UOKdEL.js +1 -0
- package/dist/assets/postcss-BXeXVLqQ.js +1 -0
- package/dist/assets/powerquery-DNMTfnFr.js +1 -0
- package/dist/assets/powershell-DshXNtvi.js +1 -0
- package/dist/assets/prisma-BsRQq5mF.js +1 -0
- package/dist/assets/prolog-iXnhIJG7.js +1 -0
- package/dist/assets/proto-DB4EqR-F.js +1 -0
- package/dist/assets/pug-BGdY1g5E.js +1 -0
- package/dist/assets/puppet-CDv2pdJW.js +1 -0
- package/dist/assets/purescript-9MfHhQsQ.js +1 -0
- package/dist/assets/python-gzcpVVnB.js +1 -0
- package/dist/assets/qml-DsT5biza.js +1 -0
- package/dist/assets/qmldir-DCQb3MpD.js +1 -0
- package/dist/assets/qss-Fe1Jh2GI.js +1 -0
- package/dist/assets/r-CbS9PfN5.js +1 -0
- package/dist/assets/racket-DcIDlBhZ.js +1 -0
- package/dist/assets/raku-B3gFvitq.js +1 -0
- package/dist/assets/razor-Bwm8roHi.js +1 -0
- package/dist/assets/red-CJ3rzSJv.js +1 -0
- package/dist/assets/reg-CRGYupPL.js +1 -0
- package/dist/assets/regexp-Bc_9DyAu.js +1 -0
- package/dist/assets/rel-BtDbiS_P.js +1 -0
- package/dist/assets/riscv-Ckw8ddFX.js +1 -0
- package/dist/assets/ron-VUp2lXgN.js +1 -0
- package/dist/assets/rose-pine-BthvhNj6.js +1 -0
- package/dist/assets/rose-pine-dawn-Dg85fqjY.js +1 -0
- package/dist/assets/rose-pine-moon-hon4tzzS.js +1 -0
- package/dist/assets/rosmsg-CAekHB0j.js +1 -0
- package/dist/assets/rst-Cj1Aii91.js +1 -0
- package/dist/assets/ruby-BPMtFZnc.js +1 -0
- package/dist/assets/rust-Cfkwpbl8.js +1 -0
- package/dist/assets/sas-CoOau1t2.js +1 -0
- package/dist/assets/sass-DXrisJhu.js +1 -0
- package/dist/assets/scala-DKOlJaKm.js +1 -0
- package/dist/assets/scheme-DQCgrYNe.js +1 -0
- package/dist/assets/scss-CvfaI808.js +1 -0
- package/dist/assets/sdbl-bTVj8UrX.js +1 -0
- package/dist/assets/shaderlab-TOUzSsQk.js +1 -0
- package/dist/assets/shellscript-B0C-TdLE.js +1 -0
- package/dist/assets/shellsession-UhmLiqcA.js +1 -0
- package/dist/assets/slack-dark-DnToyrRv.js +1 -0
- package/dist/assets/slack-ochin-B2OO5cIa.js +1 -0
- package/dist/assets/smalltalk-B16xEiuN.js +1 -0
- package/dist/assets/snazzy-light-4G7pJPwS.js +1 -0
- package/dist/assets/solarized-dark-DV17i1UV.js +1 -0
- package/dist/assets/solarized-light-DSh2HLQt.js +1 -0
- package/dist/assets/solidity-CKzVLygQ.js +1 -0
- package/dist/assets/soy-D419u0RL.js +1 -0
- package/dist/assets/sparql-D_iOobhT.js +1 -0
- package/dist/assets/splunk-BC2Px7Mm.js +1 -0
- package/dist/assets/sql-Do9k0rRn.js +1 -0
- package/dist/assets/ssh-config-BgfXC-Er.js +1 -0
- package/dist/assets/stata-x47J6BC4.js +1 -0
- package/dist/assets/stylus-B6D30XZt.js +1 -0
- package/dist/assets/surrealql-BERQ6pHu.js +1 -0
- package/dist/assets/svelte-dRWkyqKW.js +1 -0
- package/dist/assets/swift-DonLKvLd.js +1 -0
- package/dist/assets/synthwave-84-nFMaYfgc.js +1 -0
- package/dist/assets/system-verilog-DJ5XKQeo.js +1 -0
- package/dist/assets/systemd-BxMlprV5.js +1 -0
- package/dist/assets/talonscript-CohzipZa.js +1 -0
- package/dist/assets/tasl-DMoTqEGO.js +1 -0
- package/dist/assets/tcl-CZd0xW_V.js +1 -0
- package/dist/assets/templ-CTq-KoWN.js +1 -0
- package/dist/assets/terraform-DswuEJGm.js +1 -0
- package/dist/assets/tex-CdRGjyYI.js +1 -0
- package/dist/assets/tokyo-night-oM2G3aXe.js +1 -0
- package/dist/assets/toml-CcmNWLt0.js +1 -0
- package/dist/assets/ts-tags-CgaMqyVb.js +1 -0
- package/dist/assets/tsv-sltzmVWM.js +1 -0
- package/dist/assets/tsx-cpBQKcPG.js +1 -0
- package/dist/assets/turtle-ByJddavk.js +1 -0
- package/dist/assets/twig-vbs_PM4-.js +1 -0
- package/dist/assets/typescript-Cc--nwIo.js +1 -0
- package/dist/assets/typespec-BRdr0IET.js +1 -0
- package/dist/assets/typst-DI99ib-x.js +1 -0
- package/dist/assets/v-DETTlOr0.js +1 -0
- package/dist/assets/vala-zf12oZj6.js +1 -0
- package/dist/assets/vb-Djn5o6TS.js +1 -0
- package/dist/assets/verilog-CiiDBU1e.js +1 -0
- package/dist/assets/vesper-DdrHHSXu.js +1 -0
- package/dist/assets/vhdl-BroJfC0k.js +1 -0
- package/dist/assets/viml-DvXPmvsu.js +1 -0
- package/dist/assets/vitesse-black-fwtXNY1n.js +1 -0
- package/dist/assets/vitesse-dark-BZCL-v6S.js +1 -0
- package/dist/assets/vitesse-light-VbXTXTou.js +1 -0
- package/dist/assets/vue-CgHwdBmB.js +1 -0
- package/dist/assets/vue-html-BHfoMw47.js +1 -0
- package/dist/assets/vue-vine-_lVRp_NK.js +1 -0
- package/dist/assets/vyper-CgoNMtux.js +1 -0
- package/dist/assets/wasm-BnjxR4X6.js +1 -0
- package/dist/assets/wasm-ByWQv1Qj.js +1 -0
- package/dist/assets/wenyan-C8pVoKbM.js +1 -0
- package/dist/assets/wgsl-BsKzXJz4.js +1 -0
- package/dist/assets/wikitext-ClFFjSW2.js +1 -0
- package/dist/assets/wit-DdvCle-K.js +1 -0
- package/dist/assets/wolfram-DLL8P-h_.js +1 -0
- package/dist/assets/xml-G4NVmTde.js +1 -0
- package/dist/assets/xsl-s0so2M1i.js +1 -0
- package/dist/assets/yaml-CpsmW05t.js +1 -0
- package/dist/assets/zenscript-BnlCZFoB.js +1 -0
- package/dist/assets/zig-CMLA9XwU.js +1 -0
- package/dist/index.html +2 -2
- package/package.json +52 -23
- package/scripts/access-token.mjs +21 -0
- package/scripts/build-diff-data.mjs +297 -62
- package/scripts/cache.mjs +301 -0
- package/scripts/cli-args.mjs +206 -57
- package/scripts/coding-agents.mjs +279 -162
- package/scripts/dev.mjs +218 -0
- package/scripts/doctor.mjs +265 -46
- package/scripts/generate-summaries.mjs +760 -260
- package/scripts/mock-agent.mjs +165 -0
- package/scripts/present.mjs +394 -85
- package/scripts/presenter-runtime.mjs +148 -0
- package/scripts/serve-built.mjs +343 -71
- package/scripts/summary-path.mjs +24 -7
- package/scripts/support-record.mjs +242 -0
- package/dist/assets/index-D5201POe.js +0 -10
package/scripts/dev.mjs
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawn } from "node:child_process";
|
|
4
|
+
import { once } from "node:events";
|
|
5
|
+
import { existsSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
6
|
+
import { tmpdir } from "node:os";
|
|
7
|
+
import { dirname, join, resolve } from "node:path";
|
|
8
|
+
import { createInterface } from "node:readline";
|
|
9
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
10
|
+
import { stripVTControlCharacters } from "node:util";
|
|
11
|
+
|
|
12
|
+
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
13
|
+
|
|
14
|
+
function childStatus(code, signal) {
|
|
15
|
+
if (code !== null) return code;
|
|
16
|
+
return signal || "unknown";
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function childExitCode(code) {
|
|
20
|
+
return code === null ? 1 : code;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// fallow-ignore-next-line complexity -- this validates the full dev-only command surface.
|
|
24
|
+
export function parseDevelopmentArgs(rawArgs, callerDirectory = process.cwd()) {
|
|
25
|
+
const [mode, ...args] = rawArgs;
|
|
26
|
+
if (!["live", "mock"].includes(mode)) {
|
|
27
|
+
throw new Error('Use "live" or "mock".');
|
|
28
|
+
}
|
|
29
|
+
const values = new Map();
|
|
30
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
31
|
+
const name = args[index];
|
|
32
|
+
if (!["--repo", "--fixture", "--port", "--delay"].includes(name)) {
|
|
33
|
+
throw new Error(`Unknown option: ${name}`);
|
|
34
|
+
}
|
|
35
|
+
const value = args[index + 1];
|
|
36
|
+
if (!value || value.startsWith("--")) throw new Error(`${name} needs a value`);
|
|
37
|
+
if (values.has(name)) throw new Error(`${name} was passed more than once`);
|
|
38
|
+
values.set(name, value);
|
|
39
|
+
index += 1;
|
|
40
|
+
}
|
|
41
|
+
if (mode === "live" && values.has("--fixture")) {
|
|
42
|
+
throw new Error("--fixture is only available in mock mode");
|
|
43
|
+
}
|
|
44
|
+
if (mode === "mock" && values.has("--repo")) {
|
|
45
|
+
throw new Error("--repo is only available in live mode");
|
|
46
|
+
}
|
|
47
|
+
const port = values.get("--port") || "2299";
|
|
48
|
+
if (!/^\d+$/.test(port) || Number(port) > 65_535) {
|
|
49
|
+
throw new Error("--port must be a number from 0 to 65535");
|
|
50
|
+
}
|
|
51
|
+
const delay = values.get("--delay") || "750";
|
|
52
|
+
if (!/^\d+$/.test(delay) || Number(delay) < 10 || Number(delay) > 60_000) {
|
|
53
|
+
throw new Error("--delay must be a number from 10 to 60000");
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
mode,
|
|
57
|
+
port,
|
|
58
|
+
delay,
|
|
59
|
+
repo: resolve(callerDirectory, values.get("--repo") || callerDirectory),
|
|
60
|
+
fixture: resolve(
|
|
61
|
+
callerDirectory,
|
|
62
|
+
values.get("--fixture") || resolve(root, "public/demo-diff-data.json"),
|
|
63
|
+
),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function developmentCommands(options, output) {
|
|
68
|
+
const clientReady = join(dirname(output), "client-ready");
|
|
69
|
+
const watcher =
|
|
70
|
+
options.mode === "live"
|
|
71
|
+
? {
|
|
72
|
+
command: process.execPath,
|
|
73
|
+
args: [
|
|
74
|
+
resolve(root, "scripts/build-diff-data.mjs"),
|
|
75
|
+
"--repo",
|
|
76
|
+
options.repo,
|
|
77
|
+
"--worktree",
|
|
78
|
+
"--watch",
|
|
79
|
+
"--watch-content",
|
|
80
|
+
"--output",
|
|
81
|
+
output,
|
|
82
|
+
],
|
|
83
|
+
}
|
|
84
|
+
: {
|
|
85
|
+
command: process.execPath,
|
|
86
|
+
args: [
|
|
87
|
+
resolve(root, "scripts/mock-agent.mjs"),
|
|
88
|
+
"--fixture",
|
|
89
|
+
options.fixture,
|
|
90
|
+
"--delay",
|
|
91
|
+
options.delay,
|
|
92
|
+
"--start-file",
|
|
93
|
+
join(dirname(output), "page-ready"),
|
|
94
|
+
"--advance-file",
|
|
95
|
+
clientReady,
|
|
96
|
+
"--output",
|
|
97
|
+
output,
|
|
98
|
+
],
|
|
99
|
+
};
|
|
100
|
+
return {
|
|
101
|
+
watcher,
|
|
102
|
+
vite: {
|
|
103
|
+
command: process.execPath,
|
|
104
|
+
args: [
|
|
105
|
+
resolve(root, "node_modules/vite/bin/vite.js"),
|
|
106
|
+
"--host",
|
|
107
|
+
"127.0.0.1",
|
|
108
|
+
"--port",
|
|
109
|
+
options.port,
|
|
110
|
+
],
|
|
111
|
+
env: {
|
|
112
|
+
DIFFSPLAIN_LIVE_OUTPUT: output,
|
|
113
|
+
...(options.mode === "mock"
|
|
114
|
+
? { DIFFSPLAIN_LIVE_ACK: clientReady }
|
|
115
|
+
: {}),
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function isDevelopmentEntry(argument, moduleUrl) {
|
|
122
|
+
return Boolean(argument) && pathToFileURL(resolve(argument)).href === moduleUrl;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export function viteServerUrl(output) {
|
|
126
|
+
return stripVTControlCharacters(output).match(
|
|
127
|
+
/Local:\s+(http:\/\/[^\s]+)/,
|
|
128
|
+
)?.[1];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// fallow-ignore-next-line complexity -- this supervisor owns both child lifecycles.
|
|
132
|
+
async function main() {
|
|
133
|
+
const options = parseDevelopmentArgs(process.argv.slice(2));
|
|
134
|
+
if (!existsSync(options.mode === "live" ? options.repo : options.fixture)) {
|
|
135
|
+
throw new Error(
|
|
136
|
+
options.mode === "live"
|
|
137
|
+
? `Repo does not exist: ${options.repo}`
|
|
138
|
+
: `Fixture does not exist: ${options.fixture}`,
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
const runtimeDirectory = mkdtempSync(join(tmpdir(), "diffsplain-dev-"));
|
|
142
|
+
const output = join(runtimeDirectory, "diff-data.json");
|
|
143
|
+
const { watcher, vite } = developmentCommands(options, output);
|
|
144
|
+
let closing = false;
|
|
145
|
+
let pageReady = false;
|
|
146
|
+
const children = new Set();
|
|
147
|
+
const stop = async (code = 0) => {
|
|
148
|
+
if (closing) return;
|
|
149
|
+
closing = true;
|
|
150
|
+
for (const child of children) {
|
|
151
|
+
if (!child.killed) child.kill("SIGTERM");
|
|
152
|
+
}
|
|
153
|
+
await Promise.all(
|
|
154
|
+
[...children].map((child) =>
|
|
155
|
+
child.exitCode === null ? once(child, "exit") : Promise.resolve(),
|
|
156
|
+
),
|
|
157
|
+
);
|
|
158
|
+
rmSync(runtimeDirectory, { recursive: true, force: true });
|
|
159
|
+
process.exitCode = code;
|
|
160
|
+
};
|
|
161
|
+
process.on("SIGINT", () => void stop());
|
|
162
|
+
process.on("SIGTERM", () => void stop());
|
|
163
|
+
|
|
164
|
+
const watchChild = spawn(watcher.command, watcher.args, {
|
|
165
|
+
cwd: root,
|
|
166
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
167
|
+
});
|
|
168
|
+
children.add(watchChild);
|
|
169
|
+
const viteChild = spawn(vite.command, vite.args, {
|
|
170
|
+
cwd: root,
|
|
171
|
+
env: { ...process.env, ...vite.env },
|
|
172
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
173
|
+
});
|
|
174
|
+
children.add(viteChild);
|
|
175
|
+
for (const [name, child] of [
|
|
176
|
+
["watcher", watchChild],
|
|
177
|
+
["Vite", viteChild],
|
|
178
|
+
]) {
|
|
179
|
+
child.on("error", (error) => {
|
|
180
|
+
if (!closing) {
|
|
181
|
+
console.error(`Could not start ${name}: ${error.message}`);
|
|
182
|
+
void stop(1);
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
child.on("exit", (code, signal) => {
|
|
186
|
+
children.delete(child);
|
|
187
|
+
if (!closing) {
|
|
188
|
+
console.error(`${name} stopped (${childStatus(code, signal)}).`);
|
|
189
|
+
void stop(childExitCode(code));
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
function relayWatcherLine(line) {
|
|
194
|
+
if (line) console.log(`[${options.mode}] ${line}`);
|
|
195
|
+
}
|
|
196
|
+
for (const stream of [watchChild.stdout, watchChild.stderr]) {
|
|
197
|
+
createInterface({ input: stream }).on("line", relayWatcherLine);
|
|
198
|
+
}
|
|
199
|
+
function relayViteLine(line) {
|
|
200
|
+
const url = viteServerUrl(line);
|
|
201
|
+
if (url && !pageReady) {
|
|
202
|
+
pageReady = true;
|
|
203
|
+
writeFileSync(join(runtimeDirectory, "page-ready"), "ready\n");
|
|
204
|
+
console.log(`Diffsplain ${options.mode} ready: ${url}`);
|
|
205
|
+
}
|
|
206
|
+
if (line) console.log(`[vite] ${line}`);
|
|
207
|
+
}
|
|
208
|
+
for (const stream of [viteChild.stdout, viteChild.stderr]) {
|
|
209
|
+
createInterface({ input: stream }).on("line", relayViteLine);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (isDevelopmentEntry(process.argv[1], import.meta.url)) {
|
|
214
|
+
main().catch((error) => {
|
|
215
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
216
|
+
process.exitCode = 1;
|
|
217
|
+
});
|
|
218
|
+
}
|
package/scripts/doctor.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { spawnSync } from 'node:child_process';
|
|
2
2
|
import {
|
|
3
|
+
agentDisabledReason,
|
|
3
4
|
codingAgentBinary,
|
|
4
5
|
codingAgents,
|
|
5
6
|
findCommand,
|
|
@@ -12,6 +13,7 @@ const agentLabels = {
|
|
|
12
13
|
cursor: 'Cursor',
|
|
13
14
|
opencode: 'OpenCode',
|
|
14
15
|
};
|
|
16
|
+
const minimumNodeVersion = [22, 13, 0];
|
|
15
17
|
|
|
16
18
|
function firstLine(value) {
|
|
17
19
|
return value
|
|
@@ -21,99 +23,316 @@ function firstLine(value) {
|
|
|
21
23
|
.find(Boolean);
|
|
22
24
|
}
|
|
23
25
|
|
|
24
|
-
function
|
|
25
|
-
|
|
26
|
+
function commandResult(command, args, env) {
|
|
27
|
+
return spawnSync(command, args, {
|
|
26
28
|
encoding: 'utf8',
|
|
29
|
+
env,
|
|
27
30
|
timeout: 5_000,
|
|
28
31
|
windowsHide: true,
|
|
29
32
|
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function commandVersion(command, env) {
|
|
36
|
+
const result = commandResult(command, ['--version'], env);
|
|
30
37
|
if (result.error || result.status !== 0) return undefined;
|
|
31
38
|
return firstLine(`${result.stdout || ''}\n${result.stderr || ''}`);
|
|
32
39
|
}
|
|
33
40
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
)
|
|
41
|
+
function commandSucceeds(command, args, env) {
|
|
42
|
+
const result = commandResult(command, args, env);
|
|
43
|
+
return !result.error && result.status === 0;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function parseNodeVersion(version) {
|
|
47
|
+
const match = version.match(/^v?(\d+)\.(\d+)\.(\d+)/);
|
|
48
|
+
if (!match) return undefined;
|
|
49
|
+
return match.slice(1).map(Number);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function supportsNodeVersion(version) {
|
|
53
|
+
const current = parseNodeVersion(version);
|
|
54
|
+
if (!current) return false;
|
|
55
|
+
for (const [index, part] of current.entries()) {
|
|
56
|
+
if (part !== minimumNodeVersion[index]) {
|
|
57
|
+
return part > minimumNodeVersion[index];
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function inspectDependency(label, command, { env, platform }) {
|
|
42
64
|
const path = await findCommand(command, { env, platform });
|
|
43
|
-
if (!path)
|
|
65
|
+
if (!path) {
|
|
66
|
+
return { label, command, installed: false, compatible: 'not-checked' };
|
|
67
|
+
}
|
|
68
|
+
const version = commandVersion(path, env);
|
|
44
69
|
return {
|
|
45
70
|
label,
|
|
46
71
|
command,
|
|
47
72
|
installed: true,
|
|
48
73
|
path,
|
|
49
|
-
version
|
|
74
|
+
version,
|
|
75
|
+
compatible: version ? 'not-verified' : 'unknown',
|
|
50
76
|
};
|
|
51
77
|
}
|
|
52
78
|
|
|
53
79
|
function dependencyLine(dependency) {
|
|
54
80
|
const label = dependency.label.padEnd(9);
|
|
81
|
+
if (dependency.disabled) {
|
|
82
|
+
return ` ! ${label} disabled (${dependency.disabled})`;
|
|
83
|
+
}
|
|
55
84
|
if (!dependency.installed) {
|
|
56
85
|
return ` ✗ ${label} not found (${dependency.command})`;
|
|
57
86
|
}
|
|
58
87
|
const mark = dependency.version ? '✓' : '!';
|
|
59
|
-
|
|
60
|
-
return ` ${mark} ${label} ${version} (${dependency.path})`;
|
|
88
|
+
return ` ${mark} ${label} ${dependency.version || 'version unavailable'} (${dependency.path})`;
|
|
61
89
|
}
|
|
62
90
|
|
|
63
|
-
function
|
|
64
|
-
return
|
|
91
|
+
function stateLine(name, value) {
|
|
92
|
+
return ` ${name.padEnd(14)} ${value}`;
|
|
65
93
|
}
|
|
66
94
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
95
|
+
function capabilityLines(name, capability) {
|
|
96
|
+
return [
|
|
97
|
+
` ${name}`,
|
|
98
|
+
stateLine(
|
|
99
|
+
'installed',
|
|
100
|
+
typeof capability.installed === 'boolean'
|
|
101
|
+
? yesNo(capability.installed)
|
|
102
|
+
: capability.installed,
|
|
103
|
+
),
|
|
104
|
+
stateLine('compatible', capability.compatible),
|
|
105
|
+
stateLine('authenticated', capability.authenticated),
|
|
106
|
+
stateLine('smoke test', capability.smokeTest),
|
|
107
|
+
];
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function yesNo(value) {
|
|
111
|
+
return value ? 'yes' : 'no';
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function localSmokeTest(dependency, deep, env) {
|
|
115
|
+
if (!deep) return 'not-run';
|
|
116
|
+
if (!dependency.installed) return 'not-run';
|
|
117
|
+
return commandSucceeds(dependency.path, ['--help'], env)
|
|
118
|
+
? 'passed (local command only)'
|
|
119
|
+
: 'failed (local command only)';
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function providerCapability(agent, deep, env) {
|
|
123
|
+
return {
|
|
124
|
+
installed: agent.installed,
|
|
125
|
+
compatible: agent.compatible,
|
|
126
|
+
authenticated: 'not-checked',
|
|
127
|
+
smokeTest: localSmokeTest(agent, deep, env),
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async function inspectDependencies(env, platform) {
|
|
74
132
|
const [git, gh, ...agents] = await Promise.all([
|
|
75
133
|
inspectDependency('Git', 'git', { env, platform }),
|
|
76
134
|
inspectDependency('gh', 'gh', { env, platform }),
|
|
77
|
-
...codingAgents.map((agent) =>
|
|
78
|
-
|
|
135
|
+
...codingAgents.map((agent) => {
|
|
136
|
+
const disabled = agentDisabledReason(agent);
|
|
137
|
+
if (disabled) {
|
|
138
|
+
return Promise.resolve({
|
|
139
|
+
label: agentLabels[agent],
|
|
140
|
+
command: codingAgentBinary(agent, { env }),
|
|
141
|
+
installed: false,
|
|
142
|
+
compatible: 'no',
|
|
143
|
+
disabled,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
return inspectDependency(
|
|
79
147
|
agentLabels[agent],
|
|
80
148
|
codingAgentBinary(agent, { env }),
|
|
81
149
|
{ env, platform },
|
|
82
|
-
)
|
|
83
|
-
),
|
|
150
|
+
);
|
|
151
|
+
}),
|
|
84
152
|
]);
|
|
85
|
-
|
|
86
|
-
|
|
153
|
+
return { git, gh, agents };
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function coreInstalled(git, nodePath) {
|
|
157
|
+
return git.installed && Boolean(nodePath);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function coreReady(git, nodeSupported) {
|
|
161
|
+
return git.installed && Boolean(git.version) && nodeSupported;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function coreReviewCapability(git, nodeSupported, nodePath, deep, env) {
|
|
165
|
+
const ready = coreReady(git, nodeSupported);
|
|
166
|
+
return {
|
|
167
|
+
installed: coreInstalled(git, nodePath),
|
|
168
|
+
compatible: yesNo(ready),
|
|
169
|
+
authenticated: 'not-required',
|
|
170
|
+
smokeTest: localSmokeTest(git, deep, env),
|
|
171
|
+
ready,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function agentNoteCapabilities(agents, deep, env) {
|
|
176
|
+
return Object.fromEntries(
|
|
177
|
+
codingAgents.map((agent, index) => [
|
|
178
|
+
agent,
|
|
179
|
+
providerCapability(agents[index], deep, env),
|
|
180
|
+
]),
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function authenticationState(gh, env) {
|
|
185
|
+
if (!gh.installed) return 'not-checked';
|
|
186
|
+
return commandSucceeds(gh.path, ['auth', 'status', '--active'], env)
|
|
187
|
+
? 'passed'
|
|
188
|
+
: 'failed';
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function pullRequestCapability(gh, deep, env) {
|
|
192
|
+
return {
|
|
193
|
+
installed: gh.installed,
|
|
194
|
+
compatible: gh.compatible,
|
|
195
|
+
authenticated: authenticationState(gh, env),
|
|
196
|
+
smokeTest: localSmokeTest(gh, deep, env),
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function machineReport({
|
|
201
|
+
deep,
|
|
202
|
+
platform,
|
|
203
|
+
architecture,
|
|
204
|
+
nodeVersion,
|
|
205
|
+
nodePath,
|
|
206
|
+
nodeSupported,
|
|
207
|
+
git,
|
|
208
|
+
gh,
|
|
209
|
+
agents,
|
|
210
|
+
capabilities,
|
|
211
|
+
}) {
|
|
212
|
+
return {
|
|
213
|
+
schemaVersion: 1,
|
|
214
|
+
deep,
|
|
215
|
+
platform: { name: platform, architecture },
|
|
216
|
+
dependencies: {
|
|
217
|
+
node: {
|
|
218
|
+
installed: true,
|
|
219
|
+
version: nodeVersion,
|
|
220
|
+
path: nodePath,
|
|
221
|
+
compatible: nodeSupported ? 'yes' : 'no',
|
|
222
|
+
},
|
|
223
|
+
git,
|
|
224
|
+
gh,
|
|
225
|
+
agents: Object.fromEntries(
|
|
226
|
+
codingAgents.map((agent, index) => [agent, agents[index]]),
|
|
227
|
+
),
|
|
228
|
+
},
|
|
229
|
+
capabilities,
|
|
230
|
+
ready: capabilities.coreReview.ready,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function installedCountLabel(installedAgents) {
|
|
235
|
+
return installedAgents.length
|
|
87
236
|
? `${installedAgents.length} installed`
|
|
88
237
|
: 'none installed';
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function agentCapabilityLines(agent, capabilities) {
|
|
241
|
+
return capabilityLines(
|
|
242
|
+
`Agent notes: ${agentLabels[agent]}`,
|
|
243
|
+
capabilities.agentNotes[agent],
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function appendDoctorNotes(lines, installedAgents, deep) {
|
|
248
|
+
if (!installedAgents.length) {
|
|
249
|
+
lines.push(' No agent is required for a plain local review; use --no-agent.');
|
|
250
|
+
}
|
|
251
|
+
if (!deep) {
|
|
252
|
+
lines.push(
|
|
253
|
+
' Smoke tests were not run. Use doctor --deep for local command checks.',
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function reportText({
|
|
259
|
+
deep,
|
|
260
|
+
platform,
|
|
261
|
+
architecture,
|
|
262
|
+
nodeVersion,
|
|
263
|
+
nodePath,
|
|
264
|
+
git,
|
|
265
|
+
gh,
|
|
266
|
+
agents,
|
|
267
|
+
capabilities,
|
|
268
|
+
}) {
|
|
269
|
+
const installedAgents = agents.filter((agent) => agent.installed);
|
|
89
270
|
const lines = [
|
|
90
271
|
'Diffsplain doctor',
|
|
91
272
|
'',
|
|
92
273
|
'Dependencies',
|
|
93
|
-
|
|
274
|
+
dependencyLine({
|
|
275
|
+
label: 'Node',
|
|
276
|
+
command: 'node',
|
|
277
|
+
installed: true,
|
|
278
|
+
path: nodePath,
|
|
279
|
+
version: nodeVersion,
|
|
280
|
+
}),
|
|
94
281
|
dependencyLine(git),
|
|
95
282
|
dependencyLine(gh),
|
|
96
283
|
'',
|
|
97
|
-
`Coding agents (${
|
|
284
|
+
`Coding agents (${installedCountLabel(installedAgents)})`,
|
|
98
285
|
...agents.map(dependencyLine),
|
|
99
286
|
'',
|
|
100
|
-
'
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
:
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
287
|
+
'Capabilities',
|
|
288
|
+
...capabilityLines('Plain local review', {
|
|
289
|
+
...capabilities.coreReview,
|
|
290
|
+
installed: yesNo(capabilities.coreReview.installed),
|
|
291
|
+
}),
|
|
292
|
+
...codingAgents.flatMap((agent) =>
|
|
293
|
+
agentCapabilityLines(agent, capabilities),
|
|
294
|
+
),
|
|
295
|
+
...capabilityLines('Pull request lookup', {
|
|
296
|
+
...capabilities.pullRequestLookup,
|
|
297
|
+
installed: yesNo(capabilities.pullRequestLookup.installed),
|
|
298
|
+
}),
|
|
110
299
|
` Platform: ${platform} ${architecture}`,
|
|
111
300
|
];
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
301
|
+
appendDoctorNotes(lines, installedAgents, deep);
|
|
302
|
+
return lines.join('\n');
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
export async function doctorReport({
|
|
306
|
+
env = process.env,
|
|
307
|
+
platform = process.platform,
|
|
308
|
+
architecture = process.arch,
|
|
309
|
+
nodeVersion = process.version,
|
|
310
|
+
nodePath = process.execPath,
|
|
311
|
+
deep = false,
|
|
312
|
+
} = {}) {
|
|
313
|
+
const { git, gh, agents } = await inspectDependencies(env, platform);
|
|
314
|
+
const nodeSupported = supportsNodeVersion(nodeVersion);
|
|
315
|
+
const capabilities = {
|
|
316
|
+
coreReview: coreReviewCapability(git, nodeSupported, nodePath, deep, env),
|
|
317
|
+
agentNotes: agentNoteCapabilities(agents, deep, env),
|
|
318
|
+
pullRequestLookup: pullRequestCapability(gh, deep, env),
|
|
319
|
+
};
|
|
320
|
+
const reportOptions = {
|
|
321
|
+
deep,
|
|
322
|
+
platform,
|
|
323
|
+
architecture,
|
|
324
|
+
nodeVersion,
|
|
325
|
+
nodePath,
|
|
326
|
+
nodeSupported,
|
|
327
|
+
git,
|
|
328
|
+
gh,
|
|
329
|
+
agents,
|
|
330
|
+
capabilities,
|
|
331
|
+
};
|
|
332
|
+
const json = machineReport(reportOptions);
|
|
115
333
|
return {
|
|
116
|
-
text:
|
|
117
|
-
|
|
334
|
+
text: reportText(reportOptions),
|
|
335
|
+
json,
|
|
336
|
+
ready: json.ready,
|
|
118
337
|
};
|
|
119
338
|
}
|