diffity 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1081 -0
- package/dist/ui/assets/abap-BdImnpbu.js +1 -0
- package/dist/ui/assets/actionscript-3-CoDkCxhg.js +1 -0
- package/dist/ui/assets/ada-bCR0ucgS.js +1 -0
- package/dist/ui/assets/andromeeda-C4gqWexZ.js +1 -0
- package/dist/ui/assets/angular-html-DA-rfuFy.js +1 -0
- package/dist/ui/assets/angular-ts-BrjP3tb8.js +1 -0
- package/dist/ui/assets/apache-Pmp26Uib.js +1 -0
- package/dist/ui/assets/apex-D8_7TLub.js +1 -0
- package/dist/ui/assets/apl-CORt7UWP.js +1 -0
- package/dist/ui/assets/applescript-Co6uUVPk.js +1 -0
- package/dist/ui/assets/ara-BRHolxvo.js +1 -0
- package/dist/ui/assets/asciidoc-Ve4PFQV2.js +1 -0
- package/dist/ui/assets/asm-D_Q5rh1f.js +1 -0
- package/dist/ui/assets/astro-HNnZUWAn.js +1 -0
- package/dist/ui/assets/aurora-x-D-2ljcwZ.js +1 -0
- package/dist/ui/assets/awk-DMzUqQB5.js +1 -0
- package/dist/ui/assets/ayu-dark-DYE7WIF3.js +1 -0
- package/dist/ui/assets/ayu-light-BA47KaF1.js +1 -0
- package/dist/ui/assets/ayu-mirage-32ctXXKs.js +1 -0
- package/dist/ui/assets/ballerina-BFfxhgS-.js +1 -0
- package/dist/ui/assets/bat-BkioyH1T.js +1 -0
- package/dist/ui/assets/beancount-k_qm7-4y.js +1 -0
- package/dist/ui/assets/berry-uYugtg8r.js +1 -0
- package/dist/ui/assets/bibtex-CHM0blh-.js +1 -0
- package/dist/ui/assets/bicep-Bmn6On1c.js +1 -0
- package/dist/ui/assets/bird2-BIv1doCn.js +1 -0
- package/dist/ui/assets/blade-BjGOyj-B.js +1 -0
- package/dist/ui/assets/bsl-BO_Y6i37.js +1 -0
- package/dist/ui/assets/c-BIGW1oBm.js +1 -0
- package/dist/ui/assets/c3-eo99z4R2.js +1 -0
- package/dist/ui/assets/cadence-Bv_4Rxtq.js +1 -0
- package/dist/ui/assets/cairo-KRGpt6FW.js +1 -0
- package/dist/ui/assets/catppuccin-frappe-DFWUc33u.js +1 -0
- package/dist/ui/assets/catppuccin-latte-C9dUb6Cb.js +1 -0
- package/dist/ui/assets/catppuccin-macchiato-DQyhUUbL.js +1 -0
- package/dist/ui/assets/catppuccin-mocha-D87Tk5Gz.js +1 -0
- package/dist/ui/assets/clarity-D53aC0YG.js +1 -0
- package/dist/ui/assets/clojure-P80f7IUj.js +1 -0
- package/dist/ui/assets/cmake-D1j8_8rp.js +1 -0
- package/dist/ui/assets/cobol-nBiQ_Alo.js +1 -0
- package/dist/ui/assets/codeowners-Bp6g37R7.js +1 -0
- package/dist/ui/assets/codeql-DsOJ9woJ.js +1 -0
- package/dist/ui/assets/coffee-Ch7k5sss.js +1 -0
- package/dist/ui/assets/common-lisp-Cg-RD9OK.js +1 -0
- package/dist/ui/assets/coq-DkFqJrB1.js +1 -0
- package/dist/ui/assets/cpp-CofmeUqb.js +1 -0
- package/dist/ui/assets/crystal-DNxU26gB.js +1 -0
- package/dist/ui/assets/csharp-COcwbKMJ.js +1 -0
- package/dist/ui/assets/css-CLj8gQPS.js +1 -0
- package/dist/ui/assets/csv-fuZLfV_i.js +1 -0
- package/dist/ui/assets/cue-D82EKSYY.js +1 -0
- package/dist/ui/assets/cypher-COkxafJQ.js +1 -0
- package/dist/ui/assets/d-85-TOEBH.js +1 -0
- package/dist/ui/assets/dark-plus-C3mMm8J8.js +1 -0
- package/dist/ui/assets/dart-bE4Kk8sk.js +1 -0
- package/dist/ui/assets/dax-CEL-wOlO.js +1 -0
- package/dist/ui/assets/desktop-BmXAJ9_W.js +1 -0
- package/dist/ui/assets/diff-D97Zzqfu.js +1 -0
- package/dist/ui/assets/docker-BcOcwvcX.js +1 -0
- package/dist/ui/assets/dotenv-Da5cRb03.js +1 -0
- package/dist/ui/assets/dracula-BzJJZx-M.js +1 -0
- package/dist/ui/assets/dracula-soft-BXkSAIEj.js +1 -0
- package/dist/ui/assets/dream-maker-BtqSS_iP.js +1 -0
- package/dist/ui/assets/edge-FbVlp4U3.js +1 -0
- package/dist/ui/assets/elixir-CkH2-t6x.js +1 -0
- package/dist/ui/assets/elm-DbKCFpqz.js +1 -0
- package/dist/ui/assets/emacs-lisp-CXvaQtF9.js +1 -0
- package/dist/ui/assets/erb-BYCe7drp.js +1 -0
- package/dist/ui/assets/erlang-DsQrWhSR.js +1 -0
- package/dist/ui/assets/everforest-dark-BgDCqdQA.js +1 -0
- package/dist/ui/assets/everforest-light-C8M2exoo.js +1 -0
- package/dist/ui/assets/fennel-BYunw83y.js +1 -0
- package/dist/ui/assets/fish-BvzEVeQv.js +1 -0
- package/dist/ui/assets/fluent-C4IJs8-o.js +1 -0
- package/dist/ui/assets/fortran-fixed-form-CkoXwp7k.js +1 -0
- package/dist/ui/assets/fortran-free-form-BxgE0vQu.js +1 -0
- package/dist/ui/assets/fsharp-CXgrBDvD.js +1 -0
- package/dist/ui/assets/gdresource-BOOCDP_w.js +1 -0
- package/dist/ui/assets/gdscript-C5YyOfLZ.js +1 -0
- package/dist/ui/assets/gdshader-DkwncUOv.js +1 -0
- package/dist/ui/assets/genie-D0YGMca9.js +1 -0
- package/dist/ui/assets/gherkin-DyxjwDmM.js +1 -0
- package/dist/ui/assets/git-commit-F4YmCXRG.js +1 -0
- package/dist/ui/assets/git-rebase-r7XF79zn.js +1 -0
- package/dist/ui/assets/github-dark-DHJKELXO.js +1 -0
- package/dist/ui/assets/github-dark-default-Cuk6v7N8.js +1 -0
- package/dist/ui/assets/github-dark-dimmed-DH5Ifo-i.js +1 -0
- package/dist/ui/assets/github-dark-high-contrast-E3gJ1_iC.js +1 -0
- package/dist/ui/assets/github-light-DAi9KRSo.js +1 -0
- package/dist/ui/assets/github-light-default-D7oLnXFd.js +1 -0
- package/dist/ui/assets/github-light-high-contrast-BfjtVDDH.js +1 -0
- package/dist/ui/assets/gleam-BspZqrRM.js +1 -0
- package/dist/ui/assets/glimmer-js-ByusRIyA.js +1 -0
- package/dist/ui/assets/glimmer-ts-BfAWNZQY.js +1 -0
- package/dist/ui/assets/glsl-DplSGwfg.js +1 -0
- package/dist/ui/assets/gn-n2N0HUVH.js +1 -0
- package/dist/ui/assets/gnuplot-DdkO51Og.js +1 -0
- package/dist/ui/assets/go-C27-OAKa.js +1 -0
- package/dist/ui/assets/graphql-ChdNCCLP.js +1 -0
- package/dist/ui/assets/groovy-gcz8RCvz.js +1 -0
- package/dist/ui/assets/gruvbox-dark-hard-CFHQjOhq.js +1 -0
- package/dist/ui/assets/gruvbox-dark-medium-GsRaNv29.js +1 -0
- package/dist/ui/assets/gruvbox-dark-soft-CVdnzihN.js +1 -0
- package/dist/ui/assets/gruvbox-light-hard-CH1njM8p.js +1 -0
- package/dist/ui/assets/gruvbox-light-medium-DRw_LuNl.js +1 -0
- package/dist/ui/assets/gruvbox-light-soft-hJgmCMqR.js +1 -0
- package/dist/ui/assets/hack-i7_Ulhet.js +1 -0
- package/dist/ui/assets/haml-D5jkg6IW.js +1 -0
- package/dist/ui/assets/handlebars-BpdQsYii.js +1 -0
- package/dist/ui/assets/haskell-Df6bDoY_.js +1 -0
- package/dist/ui/assets/haxe-CzTSHFRz.js +1 -0
- package/dist/ui/assets/hcl-BWvSN4gD.js +1 -0
- package/dist/ui/assets/hjson-D5-asLiD.js +1 -0
- package/dist/ui/assets/hlsl-D3lLCCz7.js +1 -0
- package/dist/ui/assets/horizon-BUw7H-hv.js +1 -0
- package/dist/ui/assets/horizon-bright-CUuTKBJd.js +1 -0
- package/dist/ui/assets/houston-DnULxvSX.js +1 -0
- package/dist/ui/assets/html-derivative-DlHx6ybY.js +1 -0
- package/dist/ui/assets/html-pp8916En.js +1 -0
- package/dist/ui/assets/http-jrhK8wxY.js +1 -0
- package/dist/ui/assets/hurl-irOxFIW8.js +1 -0
- package/dist/ui/assets/hxml-Bvhsp5Yf.js +1 -0
- package/dist/ui/assets/hy-DFXneXwc.js +1 -0
- package/dist/ui/assets/imba-DGztddWO.js +1 -0
- package/dist/ui/assets/index-B2RHRT_g.css +1 -0
- package/dist/ui/assets/index-BUq0B-nJ.js +198 -0
- package/dist/ui/assets/ini-BEwlwnbL.js +1 -0
- package/dist/ui/assets/java-CylS5w8V.js +1 -0
- package/dist/ui/assets/javascript-wDzz0qaB.js +1 -0
- package/dist/ui/assets/jinja-f2NsQr07.js +1 -0
- package/dist/ui/assets/jison-wvAkD_A8.js +1 -0
- package/dist/ui/assets/json-Cp-IABpG.js +1 -0
- package/dist/ui/assets/json5-C9tS-k6U.js +1 -0
- package/dist/ui/assets/jsonc-Des-eS-w.js +1 -0
- package/dist/ui/assets/jsonl-DcaNXYhu.js +1 -0
- package/dist/ui/assets/jsonnet-DFQXde-d.js +1 -0
- package/dist/ui/assets/jssm-C2t-YnRu.js +1 -0
- package/dist/ui/assets/jsx-g9-lgVsj.js +1 -0
- package/dist/ui/assets/julia-CxzCAyBv.js +1 -0
- package/dist/ui/assets/just-VxiPbLrw.js +1 -0
- package/dist/ui/assets/kanagawa-dragon-CkXjmgJE.js +1 -0
- package/dist/ui/assets/kanagawa-lotus-CfQXZHmo.js +1 -0
- package/dist/ui/assets/kanagawa-wave-DWedfzmr.js +1 -0
- package/dist/ui/assets/kdl-DV7GczEv.js +1 -0
- package/dist/ui/assets/kotlin-BdnUsdx6.js +1 -0
- package/dist/ui/assets/kusto-wEQ09or8.js +1 -0
- package/dist/ui/assets/laserwave-DUszq2jm.js +1 -0
- package/dist/ui/assets/latex-CWtU0Tv5.js +1 -0
- package/dist/ui/assets/lean-BZvkOJ9d.js +1 -0
- package/dist/ui/assets/less-B1dDrJ26.js +1 -0
- package/dist/ui/assets/light-plus-B7mTdjB0.js +1 -0
- package/dist/ui/assets/liquid-C0sCDyMI.js +1 -0
- package/dist/ui/assets/llvm-DjAJT7YJ.js +1 -0
- package/dist/ui/assets/log-2UxHyX5q.js +1 -0
- package/dist/ui/assets/logo-BtOb2qkB.js +1 -0
- package/dist/ui/assets/lua-BaeVxFsk.js +1 -0
- package/dist/ui/assets/luau-C-HG3fhB.js +1 -0
- package/dist/ui/assets/make-CHLpvVh8.js +1 -0
- package/dist/ui/assets/markdown-Cvjx9yec.js +1 -0
- package/dist/ui/assets/marko-DjSrsDqO.js +1 -0
- package/dist/ui/assets/material-theme-D5KoaKCx.js +1 -0
- package/dist/ui/assets/material-theme-darker-BfHTSMKl.js +1 -0
- package/dist/ui/assets/material-theme-lighter-B0m2ddpp.js +1 -0
- package/dist/ui/assets/material-theme-ocean-CyktbL80.js +1 -0
- package/dist/ui/assets/material-theme-palenight-Csfq5Kiy.js +1 -0
- package/dist/ui/assets/matlab-D7o27uSR.js +1 -0
- package/dist/ui/assets/mdc-DTYItulj.js +1 -0
- package/dist/ui/assets/mdx-Cmh6b_Ma.js +1 -0
- package/dist/ui/assets/mermaid-mWjccvbQ.js +1 -0
- package/dist/ui/assets/min-dark-CafNBF8u.js +1 -0
- package/dist/ui/assets/min-light-CTRr51gU.js +1 -0
- package/dist/ui/assets/mipsasm-CKIfxQSi.js +1 -0
- package/dist/ui/assets/mojo-rZm6bMo-.js +1 -0
- package/dist/ui/assets/monokai-D4h5O-jR.js +1 -0
- package/dist/ui/assets/moonbit-_H4v1dQx.js +1 -0
- package/dist/ui/assets/move-IF9eRakj.js +1 -0
- package/dist/ui/assets/narrat-DRg8JJMk.js +1 -0
- package/dist/ui/assets/nextflow-C-mBbutL.js +1 -0
- package/dist/ui/assets/nextflow-groovy-vE_lwT2v.js +1 -0
- package/dist/ui/assets/nginx-BpAMiNFr.js +1 -0
- package/dist/ui/assets/night-owl-C39BiMTA.js +1 -0
- package/dist/ui/assets/night-owl-light-CMTm3GFP.js +1 -0
- package/dist/ui/assets/nim-BIad80T-.js +1 -0
- package/dist/ui/assets/nix-CwoSXNpI.js +1 -0
- package/dist/ui/assets/nord-Ddv68eIx.js +1 -0
- package/dist/ui/assets/nushell-Cz2AlsmD.js +1 -0
- package/dist/ui/assets/objective-c-DXmwc3jG.js +1 -0
- package/dist/ui/assets/objective-cpp-CLxacb5B.js +1 -0
- package/dist/ui/assets/ocaml-C0hk2d4L.js +1 -0
- package/dist/ui/assets/odin-BBf5iR-q.js +1 -0
- package/dist/ui/assets/one-dark-pro-DVMEJ2y_.js +1 -0
- package/dist/ui/assets/one-light-C3Wv6jpd.js +1 -0
- package/dist/ui/assets/openscad-C4EeE6gA.js +1 -0
- package/dist/ui/assets/pascal-D93ZcfNL.js +1 -0
- package/dist/ui/assets/perl-NvoQZIq0.js +1 -0
- package/dist/ui/assets/php-R6g_5hLQ.js +1 -0
- package/dist/ui/assets/pkl-u5AG7uiY.js +1 -0
- package/dist/ui/assets/plastic-3e1v2bzS.js +1 -0
- package/dist/ui/assets/plsql-ChMvpjG-.js +1 -0
- package/dist/ui/assets/po-BTJTHyun.js +1 -0
- package/dist/ui/assets/poimandres-CS3Unz2-.js +1 -0
- package/dist/ui/assets/polar-C0HS_06l.js +1 -0
- package/dist/ui/assets/postcss-CXtECtnM.js +1 -0
- package/dist/ui/assets/powerquery-CEu0bR-o.js +1 -0
- package/dist/ui/assets/powershell-Dpen1YoG.js +1 -0
- package/dist/ui/assets/prisma-Dd19v3D-.js +1 -0
- package/dist/ui/assets/prolog-CbFg5uaA.js +1 -0
- package/dist/ui/assets/proto-C7zT0LnQ.js +1 -0
- package/dist/ui/assets/pug-DKIMFp6K.js +1 -0
- package/dist/ui/assets/puppet-BMWR74SV.js +1 -0
- package/dist/ui/assets/purescript-CklMAg4u.js +1 -0
- package/dist/ui/assets/python-B6aJPvgy.js +1 -0
- package/dist/ui/assets/qml-3beO22l8.js +1 -0
- package/dist/ui/assets/qmldir-C8lEn-DE.js +1 -0
- package/dist/ui/assets/qss-IeuSbFQv.js +1 -0
- package/dist/ui/assets/r-Dspwwk_N.js +1 -0
- package/dist/ui/assets/racket-BqYA7rlc.js +1 -0
- package/dist/ui/assets/raku-DXvB9xmW.js +1 -0
- package/dist/ui/assets/razor-BDqjjVU7.js +1 -0
- package/dist/ui/assets/red-bN70gL4F.js +1 -0
- package/dist/ui/assets/reg-C-SQnVFl.js +1 -0
- package/dist/ui/assets/regexp-CDVJQ6XC.js +1 -0
- package/dist/ui/assets/rel-C3B-1QV4.js +1 -0
- package/dist/ui/assets/riscv-BM1_JUlF.js +1 -0
- package/dist/ui/assets/ron-D8l8udqQ.js +1 -0
- package/dist/ui/assets/rose-pine-dawn-DHQR4-dF.js +1 -0
- package/dist/ui/assets/rose-pine-moon-D4_iv3hh.js +1 -0
- package/dist/ui/assets/rose-pine-qdsjHGoJ.js +1 -0
- package/dist/ui/assets/rosmsg-BJDFO7_C.js +1 -0
- package/dist/ui/assets/rst-CRjBmOyv.js +1 -0
- package/dist/ui/assets/ruby-Wjq7vjNf.js +1 -0
- package/dist/ui/assets/rust-B1yitclQ.js +1 -0
- package/dist/ui/assets/sas-cz2c8ADy.js +1 -0
- package/dist/ui/assets/sass-Cj5Yp3dK.js +1 -0
- package/dist/ui/assets/scala-C151Ov-r.js +1 -0
- package/dist/ui/assets/scheme-C98Dy4si.js +1 -0
- package/dist/ui/assets/scss-D5BDwBP9.js +1 -0
- package/dist/ui/assets/sdbl-DVxCFoDh.js +1 -0
- package/dist/ui/assets/shaderlab-Dg9Lc6iA.js +1 -0
- package/dist/ui/assets/shellscript-Yzrsuije.js +1 -0
- package/dist/ui/assets/shellsession-BADoaaVG.js +1 -0
- package/dist/ui/assets/slack-dark-BthQWCQV.js +1 -0
- package/dist/ui/assets/slack-ochin-DqwNpetd.js +1 -0
- package/dist/ui/assets/smalltalk-BERRCDM3.js +1 -0
- package/dist/ui/assets/snazzy-light-Bw305WKR.js +1 -0
- package/dist/ui/assets/solarized-dark-DXbdFlpD.js +1 -0
- package/dist/ui/assets/solarized-light-L9t79GZl.js +1 -0
- package/dist/ui/assets/solidity-rGO070M0.js +1 -0
- package/dist/ui/assets/soy-8wufbnw4.js +1 -0
- package/dist/ui/assets/sparql-rVzFXLq3.js +1 -0
- package/dist/ui/assets/splunk-BtCnVYZw.js +1 -0
- package/dist/ui/assets/sql-BLtJtn59.js +1 -0
- package/dist/ui/assets/ssh-config-_ykCGR6B.js +1 -0
- package/dist/ui/assets/stata-BH5u7GGu.js +1 -0
- package/dist/ui/assets/stylus-BEDo0Tqx.js +1 -0
- package/dist/ui/assets/surrealql-Bq5Q-fJD.js +1 -0
- package/dist/ui/assets/svelte-Cy7k_4gC.js +1 -0
- package/dist/ui/assets/swift-D82vCrfD.js +1 -0
- package/dist/ui/assets/synthwave-84-CbfX1IO0.js +1 -0
- package/dist/ui/assets/system-verilog-CnnmHF94.js +1 -0
- package/dist/ui/assets/systemd-4A_iFExJ.js +1 -0
- package/dist/ui/assets/talonscript-CkByrt1z.js +1 -0
- package/dist/ui/assets/tasl-QIJgUcNo.js +1 -0
- package/dist/ui/assets/tcl-dwOrl1Do.js +1 -0
- package/dist/ui/assets/templ-DhtptRzy.js +1 -0
- package/dist/ui/assets/terraform-BETggiCN.js +1 -0
- package/dist/ui/assets/tex-idrVyKtj.js +1 -0
- package/dist/ui/assets/tokyo-night-hegEt444.js +1 -0
- package/dist/ui/assets/toml-vGWfd6FD.js +1 -0
- package/dist/ui/assets/ts-tags-DQrlYJgV.js +1 -0
- package/dist/ui/assets/tsv-B_m7g4N7.js +1 -0
- package/dist/ui/assets/tsx-COt5Ahok.js +1 -0
- package/dist/ui/assets/turtle-BsS91CYL.js +1 -0
- package/dist/ui/assets/twig-xg9kU7Mw.js +1 -0
- package/dist/ui/assets/typescript-BPQ3VLAy.js +1 -0
- package/dist/ui/assets/typespec-CAFt9gP4.js +1 -0
- package/dist/ui/assets/typst-DHCkPAjA.js +1 -0
- package/dist/ui/assets/v-BcVCzyr7.js +1 -0
- package/dist/ui/assets/vala-CsfeWuGM.js +1 -0
- package/dist/ui/assets/vb-D17OF-Vu.js +1 -0
- package/dist/ui/assets/verilog-BQ8w6xss.js +1 -0
- package/dist/ui/assets/vesper-DU1UobuO.js +1 -0
- package/dist/ui/assets/vhdl-CeAyd5Ju.js +1 -0
- package/dist/ui/assets/viml-CJc9bBzg.js +1 -0
- package/dist/ui/assets/vitesse-black-Bkuqu6BP.js +1 -0
- package/dist/ui/assets/vitesse-dark-D0r3Knsf.js +1 -0
- package/dist/ui/assets/vitesse-light-CVO1_9PV.js +1 -0
- package/dist/ui/assets/vue-D2xRrEX4.js +1 -0
- package/dist/ui/assets/vue-html-AaS7Mt5G.js +1 -0
- package/dist/ui/assets/vue-vine-BoDAl6tE.js +1 -0
- package/dist/ui/assets/vyper-CDx5xZoG.js +1 -0
- package/dist/ui/assets/wasm-CG6Dc4jp.js +1 -0
- package/dist/ui/assets/wasm-MzD3tlZU.js +1 -0
- package/dist/ui/assets/wenyan-BV7otONQ.js +1 -0
- package/dist/ui/assets/wgsl-Dx-B1_4e.js +1 -0
- package/dist/ui/assets/wikitext-BhOHFoWU.js +1 -0
- package/dist/ui/assets/wit-5i3qLPDT.js +1 -0
- package/dist/ui/assets/wolfram-lXgVvXCa.js +1 -0
- package/dist/ui/assets/xml-sdJ4AIDG.js +1 -0
- package/dist/ui/assets/xsl-CtQFsRM5.js +1 -0
- package/dist/ui/assets/yaml-Buea-lGh.js +1 -0
- package/dist/ui/assets/zenscript-DVFEvuxE.js +1 -0
- package/dist/ui/assets/zig-VOosw3JB.js +1 -0
- package/{packages → dist}/ui/index.html +2 -1
- package/package.json +39 -20
- package/.claude/settings.local.json +0 -11
- package/LICENSE +0 -21
- package/README.md +0 -71
- package/development.md +0 -156
- package/packages/cli/build.js +0 -38
- package/packages/cli/package.json +0 -51
- package/packages/cli/src/agent.ts +0 -187
- package/packages/cli/src/db.ts +0 -58
- package/packages/cli/src/index.ts +0 -196
- package/packages/cli/src/review-routes.ts +0 -150
- package/packages/cli/src/server.ts +0 -370
- package/packages/cli/src/session.ts +0 -48
- package/packages/cli/src/threads.ts +0 -238
- package/packages/cli/tsconfig.json +0 -13
- package/packages/git/package.json +0 -24
- package/packages/git/src/commits.ts +0 -28
- package/packages/git/src/diff.ts +0 -97
- package/packages/git/src/exec.ts +0 -35
- package/packages/git/src/index.ts +0 -5
- package/packages/git/src/repo.ts +0 -63
- package/packages/git/src/status.ts +0 -9
- package/packages/git/src/types.ts +0 -12
- package/packages/git/tsconfig.json +0 -9
- package/packages/parser/package.json +0 -26
- package/packages/parser/src/index.ts +0 -12
- package/packages/parser/src/parse.ts +0 -299
- package/packages/parser/src/types.ts +0 -52
- package/packages/parser/src/word-diff.ts +0 -155
- package/packages/parser/tests/fixtures/binary-deleted.diff +0 -4
- package/packages/parser/tests/fixtures/binary-file.diff +0 -4
- package/packages/parser/tests/fixtures/binary-modified.diff +0 -3
- package/packages/parser/tests/fixtures/copied-file.diff +0 -12
- package/packages/parser/tests/fixtures/deleted-file.diff +0 -9
- package/packages/parser/tests/fixtures/empty.diff +0 -0
- package/packages/parser/tests/fixtures/hunk-with-context.diff +0 -12
- package/packages/parser/tests/fixtures/mode-change-with-content.diff +0 -10
- package/packages/parser/tests/fixtures/mode-change.diff +0 -3
- package/packages/parser/tests/fixtures/multi-file.diff +0 -22
- package/packages/parser/tests/fixtures/new-file.diff +0 -9
- package/packages/parser/tests/fixtures/no-newline.diff +0 -10
- package/packages/parser/tests/fixtures/renamed-file.diff +0 -12
- package/packages/parser/tests/fixtures/single-file-additions.diff +0 -11
- package/packages/parser/tests/fixtures/single-file-deletions.diff +0 -11
- package/packages/parser/tests/fixtures/single-file-mixed.diff +0 -15
- package/packages/parser/tests/fixtures/single-file-multi-hunk.diff +0 -22
- package/packages/parser/tests/fixtures/spaces-in-path.diff +0 -9
- package/packages/parser/tests/fixtures/submodule.diff +0 -7
- package/packages/parser/tests/fixtures/unicode-content.diff +0 -11
- package/packages/parser/tests/parse.test.ts +0 -312
- package/packages/parser/tests/word-diff-integration.test.ts +0 -52
- package/packages/parser/tests/word-diff.test.ts +0 -121
- package/packages/parser/tsconfig.json +0 -10
- package/packages/skills/diffity-resolve/SKILL.md +0 -55
- package/packages/skills/diffity-review/SKILL.md +0 -74
- package/packages/skills/diffity-start/SKILL.md +0 -25
- package/packages/ui/package.json +0 -35
- package/packages/ui/src/app.tsx +0 -14
- package/packages/ui/src/components/comment-bubble.tsx +0 -78
- package/packages/ui/src/components/comment-form-row.tsx +0 -58
- package/packages/ui/src/components/comment-form.tsx +0 -78
- package/packages/ui/src/components/comment-line-number.tsx +0 -60
- package/packages/ui/src/components/comment-thread.tsx +0 -209
- package/packages/ui/src/components/commit-list.tsx +0 -100
- package/packages/ui/src/components/dashboard.tsx +0 -84
- package/packages/ui/src/components/diff-line.tsx +0 -90
- package/packages/ui/src/components/diff-page.tsx +0 -332
- package/packages/ui/src/components/diff-stats.tsx +0 -20
- package/packages/ui/src/components/diff-view.tsx +0 -278
- package/packages/ui/src/components/expand-row.tsx +0 -45
- package/packages/ui/src/components/file-block.tsx +0 -536
- package/packages/ui/src/components/file-tree-item.tsx +0 -84
- package/packages/ui/src/components/file-tree.tsx +0 -72
- package/packages/ui/src/components/general-comments.tsx +0 -174
- package/packages/ui/src/components/hunk-block-split.tsx +0 -357
- package/packages/ui/src/components/hunk-block.tsx +0 -161
- package/packages/ui/src/components/hunk-header.tsx +0 -144
- package/packages/ui/src/components/hunk-with-gap.tsx +0 -113
- package/packages/ui/src/components/icons/arrow-down-icon.tsx +0 -7
- package/packages/ui/src/components/icons/arrow-up-icon.tsx +0 -7
- package/packages/ui/src/components/icons/check-circle-icon.tsx +0 -8
- package/packages/ui/src/components/icons/check-icon.tsx +0 -9
- package/packages/ui/src/components/icons/chevron-down-icon.tsx +0 -11
- package/packages/ui/src/components/icons/chevron-icon.tsx +0 -20
- package/packages/ui/src/components/icons/chevron-up-down-icon.tsx +0 -7
- package/packages/ui/src/components/icons/chevron-up-icon.tsx +0 -11
- package/packages/ui/src/components/icons/comment-icon.tsx +0 -9
- package/packages/ui/src/components/icons/copy-icon.tsx +0 -10
- package/packages/ui/src/components/icons/eye-icon.tsx +0 -10
- package/packages/ui/src/components/icons/eye-off-icon.tsx +0 -12
- package/packages/ui/src/components/icons/file-icon.tsx +0 -7
- package/packages/ui/src/components/icons/folder-icon.tsx +0 -19
- package/packages/ui/src/components/icons/git-branch-icon.tsx +0 -13
- package/packages/ui/src/components/icons/keyboard-icon.tsx +0 -13
- package/packages/ui/src/components/icons/moon-icon.tsx +0 -9
- package/packages/ui/src/components/icons/plus-icon.tsx +0 -9
- package/packages/ui/src/components/icons/search-icon.tsx +0 -10
- package/packages/ui/src/components/icons/sidebar-icon.tsx +0 -10
- package/packages/ui/src/components/icons/spinner.tsx +0 -7
- package/packages/ui/src/components/icons/split-view-icon.tsx +0 -10
- package/packages/ui/src/components/icons/sun-icon.tsx +0 -17
- package/packages/ui/src/components/icons/trash-icon.tsx +0 -11
- package/packages/ui/src/components/icons/undo-icon.tsx +0 -9
- package/packages/ui/src/components/icons/unified-view-icon.tsx +0 -12
- package/packages/ui/src/components/icons/x-icon.tsx +0 -10
- package/packages/ui/src/components/line-number-cell.tsx +0 -18
- package/packages/ui/src/components/markdown-content.tsx +0 -139
- package/packages/ui/src/components/orphaned-threads.tsx +0 -80
- package/packages/ui/src/components/overview-file-list.tsx +0 -57
- package/packages/ui/src/components/render-expansion-rows.tsx +0 -47
- package/packages/ui/src/components/shortcut-modal.tsx +0 -93
- package/packages/ui/src/components/sidebar.tsx +0 -80
- package/packages/ui/src/components/skeleton.tsx +0 -9
- package/packages/ui/src/components/stale-diff-banner.tsx +0 -21
- package/packages/ui/src/components/summary-bar.tsx +0 -39
- package/packages/ui/src/components/toolbar.tsx +0 -246
- package/packages/ui/src/components/ui/badge.tsx +0 -17
- package/packages/ui/src/components/ui/confirm-dialog.tsx +0 -52
- package/packages/ui/src/components/ui/icon-button.tsx +0 -23
- package/packages/ui/src/components/ui/status-badge.tsx +0 -57
- package/packages/ui/src/components/ui/thread-badge.tsx +0 -35
- package/packages/ui/src/components/word-diff.tsx +0 -126
- package/packages/ui/src/hooks/use-comment-actions.ts +0 -97
- package/packages/ui/src/hooks/use-commits.ts +0 -12
- package/packages/ui/src/hooks/use-copy.ts +0 -18
- package/packages/ui/src/hooks/use-diff-staleness.ts +0 -58
- package/packages/ui/src/hooks/use-diff.ts +0 -12
- package/packages/ui/src/hooks/use-highlighter.ts +0 -190
- package/packages/ui/src/hooks/use-info.ts +0 -12
- package/packages/ui/src/hooks/use-keyboard.ts +0 -55
- package/packages/ui/src/hooks/use-line-selection.ts +0 -157
- package/packages/ui/src/hooks/use-overview.ts +0 -12
- package/packages/ui/src/hooks/use-review-threads.ts +0 -12
- package/packages/ui/src/hooks/use-search-params.ts +0 -26
- package/packages/ui/src/hooks/use-theme.ts +0 -34
- package/packages/ui/src/hooks/use-thread-navigation.ts +0 -43
- package/packages/ui/src/lib/api.ts +0 -232
- package/packages/ui/src/lib/cn.ts +0 -6
- package/packages/ui/src/lib/context-expansion.ts +0 -122
- package/packages/ui/src/lib/diff-utils.ts +0 -268
- package/packages/ui/src/lib/dom-utils.ts +0 -13
- package/packages/ui/src/lib/file-tree.ts +0 -122
- package/packages/ui/src/lib/query-client.ts +0 -10
- package/packages/ui/src/lib/render-content.tsx +0 -23
- package/packages/ui/src/lib/syntax-token.ts +0 -4
- package/packages/ui/src/main.tsx +0 -14
- package/packages/ui/src/queries/commits.ts +0 -9
- package/packages/ui/src/queries/diff.ts +0 -9
- package/packages/ui/src/queries/file.ts +0 -10
- package/packages/ui/src/queries/info.ts +0 -9
- package/packages/ui/src/queries/overview.ts +0 -9
- package/packages/ui/src/styles/app.css +0 -178
- package/packages/ui/src/types/comment.ts +0 -61
- package/packages/ui/src/vite-env.d.ts +0 -1
- package/packages/ui/tests/context-expansion.test.ts +0 -279
- package/packages/ui/tests/diff-utils.test.ts +0 -409
- package/packages/ui/tsconfig.json +0 -14
- package/packages/ui/vite.config.ts +0 -23
- package/scripts/build-skills.ts +0 -26
- package/scripts/build.ts +0 -15
- package/scripts/dev.ts +0 -32
- package/scripts/lib/transformers/claude-code.ts +0 -11
- package/scripts/lib/transformers/codex.ts +0 -17
- package/scripts/lib/transformers/cursor.ts +0 -17
- package/scripts/lib/transformers/index.ts +0 -3
- package/scripts/lib/utils.ts +0 -70
- package/scripts/link-dev.ts +0 -54
- package/skills/diffity-resolve/SKILL.md +0 -55
- package/skills/diffity-review/SKILL.md +0 -74
- package/skills/diffity-start/SKILL.md +0 -27
- package/tsconfig.json +0 -22
- /package/{packages/ui/public → dist/ui}/brand.svg +0 -0
- /package/{packages/ui/public → dist/ui}/favicon.svg +0 -0
|
@@ -1,312 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { readFileSync } from 'node:fs';
|
|
3
|
-
import { resolve, dirname } from 'node:path';
|
|
4
|
-
import { fileURLToPath } from 'node:url';
|
|
5
|
-
import { parseDiff } from '../src/parse.js';
|
|
6
|
-
|
|
7
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
-
const fixture = (name: string) =>
|
|
9
|
-
readFileSync(resolve(__dirname, './fixtures', name), 'utf-8');
|
|
10
|
-
|
|
11
|
-
describe('parseDiff', () => {
|
|
12
|
-
describe('basic formats', () => {
|
|
13
|
-
it('parses single file with additions only', () => {
|
|
14
|
-
const result = parseDiff(fixture('single-file-additions.diff'));
|
|
15
|
-
|
|
16
|
-
expect(result.files).toHaveLength(1);
|
|
17
|
-
expect(result.files[0].oldPath).toBe('hello.ts');
|
|
18
|
-
expect(result.files[0].newPath).toBe('hello.ts');
|
|
19
|
-
expect(result.files[0].status).toBe('modified');
|
|
20
|
-
expect(result.files[0].hunks).toHaveLength(1);
|
|
21
|
-
|
|
22
|
-
const hunk = result.files[0].hunks[0];
|
|
23
|
-
expect(hunk.oldStart).toBe(1);
|
|
24
|
-
expect(hunk.oldCount).toBe(3);
|
|
25
|
-
expect(hunk.newStart).toBe(1);
|
|
26
|
-
expect(hunk.newCount).toBe(6);
|
|
27
|
-
|
|
28
|
-
const addLines = hunk.lines.filter(l => l.type === 'add');
|
|
29
|
-
expect(addLines).toHaveLength(3);
|
|
30
|
-
expect(addLines[0].content).toBe("const name = 'world';");
|
|
31
|
-
expect(addLines[0].newLineNumber).toBe(2);
|
|
32
|
-
expect(addLines[0].oldLineNumber).toBeNull();
|
|
33
|
-
|
|
34
|
-
const contextLines = hunk.lines.filter(l => l.type === 'context');
|
|
35
|
-
expect(contextLines).toHaveLength(3);
|
|
36
|
-
expect(contextLines[0].oldLineNumber).toBe(1);
|
|
37
|
-
expect(contextLines[0].newLineNumber).toBe(1);
|
|
38
|
-
|
|
39
|
-
expect(result.files[0].additions).toBe(3);
|
|
40
|
-
expect(result.files[0].deletions).toBe(0);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('parses single file with deletions', () => {
|
|
44
|
-
const result = parseDiff(fixture('single-file-deletions.diff'));
|
|
45
|
-
|
|
46
|
-
expect(result.files).toHaveLength(1);
|
|
47
|
-
const hunk = result.files[0].hunks[0];
|
|
48
|
-
const delLines = hunk.lines.filter(l => l.type === 'delete');
|
|
49
|
-
expect(delLines).toHaveLength(3);
|
|
50
|
-
expect(delLines[0].content).toBe(" console.log('adding', a, b);");
|
|
51
|
-
expect(delLines[0].oldLineNumber).toBe(2);
|
|
52
|
-
expect(delLines[0].newLineNumber).toBeNull();
|
|
53
|
-
|
|
54
|
-
expect(result.files[0].additions).toBe(1);
|
|
55
|
-
expect(result.files[0].deletions).toBe(3);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it('parses single file with mixed changes', () => {
|
|
59
|
-
const result = parseDiff(fixture('single-file-mixed.diff'));
|
|
60
|
-
|
|
61
|
-
expect(result.files).toHaveLength(1);
|
|
62
|
-
const hunk = result.files[0].hunks[0];
|
|
63
|
-
|
|
64
|
-
expect(hunk.lines.filter(l => l.type === 'add')).toHaveLength(3);
|
|
65
|
-
expect(hunk.lines.filter(l => l.type === 'delete')).toHaveLength(2);
|
|
66
|
-
expect(hunk.lines.filter(l => l.type === 'context')).toHaveLength(5);
|
|
67
|
-
|
|
68
|
-
expect(result.files[0].additions).toBe(3);
|
|
69
|
-
expect(result.files[0].deletions).toBe(2);
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it('parses single file with multiple hunks', () => {
|
|
73
|
-
const result = parseDiff(fixture('single-file-multi-hunk.diff'));
|
|
74
|
-
|
|
75
|
-
expect(result.files).toHaveLength(1);
|
|
76
|
-
expect(result.files[0].hunks).toHaveLength(2);
|
|
77
|
-
|
|
78
|
-
expect(result.files[0].hunks[0].oldStart).toBe(1);
|
|
79
|
-
expect(result.files[0].hunks[0].newStart).toBe(1);
|
|
80
|
-
expect(result.files[0].hunks[1].oldStart).toBe(20);
|
|
81
|
-
expect(result.files[0].hunks[1].newStart).toBe(20);
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
it('parses multiple files', () => {
|
|
85
|
-
const result = parseDiff(fixture('multi-file.diff'));
|
|
86
|
-
|
|
87
|
-
expect(result.files).toHaveLength(2);
|
|
88
|
-
expect(result.files[0].newPath).toBe('index.ts');
|
|
89
|
-
expect(result.files[1].newPath).toBe('runner.ts');
|
|
90
|
-
|
|
91
|
-
expect(result.stats.filesChanged).toBe(2);
|
|
92
|
-
expect(result.stats.totalAdditions).toBe(
|
|
93
|
-
result.files[0].additions + result.files[1].additions
|
|
94
|
-
);
|
|
95
|
-
expect(result.stats.totalDeletions).toBe(
|
|
96
|
-
result.files[0].deletions + result.files[1].deletions
|
|
97
|
-
);
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
it('parses empty diff', () => {
|
|
101
|
-
const result = parseDiff(fixture('empty.diff'));
|
|
102
|
-
|
|
103
|
-
expect(result.files).toHaveLength(0);
|
|
104
|
-
expect(result.stats.filesChanged).toBe(0);
|
|
105
|
-
expect(result.stats.totalAdditions).toBe(0);
|
|
106
|
-
expect(result.stats.totalDeletions).toBe(0);
|
|
107
|
-
});
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
describe('hunk header parsing', () => {
|
|
111
|
-
it('parses standard hunk header', () => {
|
|
112
|
-
const result = parseDiff(fixture('single-file-additions.diff'));
|
|
113
|
-
const hunk = result.files[0].hunks[0];
|
|
114
|
-
|
|
115
|
-
expect(hunk.oldStart).toBe(1);
|
|
116
|
-
expect(hunk.oldCount).toBe(3);
|
|
117
|
-
expect(hunk.newStart).toBe(1);
|
|
118
|
-
expect(hunk.newCount).toBe(6);
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
it('parses hunk header with function context', () => {
|
|
122
|
-
const result = parseDiff(fixture('hunk-with-context.diff'));
|
|
123
|
-
const hunk = result.files[0].hunks[0];
|
|
124
|
-
|
|
125
|
-
expect(hunk.oldStart).toBe(10);
|
|
126
|
-
expect(hunk.oldCount).toBe(5);
|
|
127
|
-
expect(hunk.newStart).toBe(10);
|
|
128
|
-
expect(hunk.newCount).toBe(7);
|
|
129
|
-
expect(hunk.context).toBe('function processData() {');
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
it('parses new file hunk header with 0,0', () => {
|
|
133
|
-
const result = parseDiff(fixture('new-file.diff'));
|
|
134
|
-
const hunk = result.files[0].hunks[0];
|
|
135
|
-
|
|
136
|
-
expect(hunk.oldStart).toBe(0);
|
|
137
|
-
expect(hunk.oldCount).toBe(0);
|
|
138
|
-
expect(hunk.newStart).toBe(1);
|
|
139
|
-
expect(hunk.newCount).toBe(3);
|
|
140
|
-
});
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
describe('line number assignment', () => {
|
|
144
|
-
it('assigns correct line numbers to context lines', () => {
|
|
145
|
-
const result = parseDiff(fixture('single-file-additions.diff'));
|
|
146
|
-
const contextLines = result.files[0].hunks[0].lines.filter(
|
|
147
|
-
l => l.type === 'context'
|
|
148
|
-
);
|
|
149
|
-
|
|
150
|
-
expect(contextLines[0].oldLineNumber).toBe(1);
|
|
151
|
-
expect(contextLines[0].newLineNumber).toBe(1);
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
it('assigns correct line numbers to addition lines', () => {
|
|
155
|
-
const result = parseDiff(fixture('single-file-additions.diff'));
|
|
156
|
-
const addLines = result.files[0].hunks[0].lines.filter(
|
|
157
|
-
l => l.type === 'add'
|
|
158
|
-
);
|
|
159
|
-
|
|
160
|
-
expect(addLines[0].oldLineNumber).toBeNull();
|
|
161
|
-
expect(addLines[0].newLineNumber).toBe(2);
|
|
162
|
-
expect(addLines[1].newLineNumber).toBe(3);
|
|
163
|
-
expect(addLines[2].newLineNumber).toBe(4);
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
it('assigns correct line numbers to deletion lines', () => {
|
|
167
|
-
const result = parseDiff(fixture('single-file-deletions.diff'));
|
|
168
|
-
const delLines = result.files[0].hunks[0].lines.filter(
|
|
169
|
-
l => l.type === 'delete'
|
|
170
|
-
);
|
|
171
|
-
|
|
172
|
-
expect(delLines[0].newLineNumber).toBeNull();
|
|
173
|
-
expect(delLines[0].oldLineNumber).toBe(2);
|
|
174
|
-
expect(delLines[1].oldLineNumber).toBe(3);
|
|
175
|
-
expect(delLines[2].oldLineNumber).toBe(4);
|
|
176
|
-
});
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
describe('file status detection', () => {
|
|
180
|
-
it('detects new files', () => {
|
|
181
|
-
const result = parseDiff(fixture('new-file.diff'));
|
|
182
|
-
|
|
183
|
-
expect(result.files[0].status).toBe('added');
|
|
184
|
-
expect(result.files[0].oldPath).toBe('/dev/null');
|
|
185
|
-
expect(result.files[0].newPath).toBe('newfile.ts');
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
it('detects deleted files', () => {
|
|
189
|
-
const result = parseDiff(fixture('deleted-file.diff'));
|
|
190
|
-
|
|
191
|
-
expect(result.files[0].status).toBe('deleted');
|
|
192
|
-
expect(result.files[0].oldPath).toBe('old-file.ts');
|
|
193
|
-
expect(result.files[0].newPath).toBe('/dev/null');
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
it('detects renamed files', () => {
|
|
197
|
-
const result = parseDiff(fixture('renamed-file.diff'));
|
|
198
|
-
|
|
199
|
-
expect(result.files[0].status).toBe('renamed');
|
|
200
|
-
expect(result.files[0].oldPath).toBe('old-name.ts');
|
|
201
|
-
expect(result.files[0].newPath).toBe('new-name.ts');
|
|
202
|
-
expect(result.files[0].similarityIndex).toBe(85);
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
it('detects copied files', () => {
|
|
206
|
-
const result = parseDiff(fixture('copied-file.diff'));
|
|
207
|
-
|
|
208
|
-
expect(result.files[0].status).toBe('copied');
|
|
209
|
-
expect(result.files[0].oldPath).toBe('original.ts');
|
|
210
|
-
expect(result.files[0].newPath).toBe('copy.ts');
|
|
211
|
-
expect(result.files[0].similarityIndex).toBe(90);
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
it('detects mode-only changes', () => {
|
|
215
|
-
const result = parseDiff(fixture('mode-change.diff'));
|
|
216
|
-
|
|
217
|
-
expect(result.files[0].status).toBe('modified');
|
|
218
|
-
expect(result.files[0].oldMode).toBe('100644');
|
|
219
|
-
expect(result.files[0].newMode).toBe('100755');
|
|
220
|
-
expect(result.files[0].hunks).toHaveLength(0);
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
it('detects mode change with content', () => {
|
|
224
|
-
const result = parseDiff(fixture('mode-change-with-content.diff'));
|
|
225
|
-
|
|
226
|
-
expect(result.files[0].oldMode).toBe('100644');
|
|
227
|
-
expect(result.files[0].newMode).toBe('100755');
|
|
228
|
-
expect(result.files[0].hunks).toHaveLength(1);
|
|
229
|
-
expect(result.files[0].additions).toBe(1);
|
|
230
|
-
});
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
describe('edge cases', () => {
|
|
234
|
-
it('handles no newline at end of file', () => {
|
|
235
|
-
const result = parseDiff(fixture('no-newline.diff'));
|
|
236
|
-
const lines = result.files[0].hunks[0].lines;
|
|
237
|
-
const lastContext = lines.filter(l => l.type === 'context').pop();
|
|
238
|
-
|
|
239
|
-
expect(lastContext?.noNewline).toBe(true);
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
it('handles binary files (new)', () => {
|
|
243
|
-
const result = parseDiff(fixture('binary-file.diff'));
|
|
244
|
-
|
|
245
|
-
expect(result.files[0].isBinary).toBe(true);
|
|
246
|
-
expect(result.files[0].status).toBe('added');
|
|
247
|
-
expect(result.files[0].hunks).toHaveLength(0);
|
|
248
|
-
expect(result.files[0].additions).toBe(0);
|
|
249
|
-
expect(result.files[0].deletions).toBe(0);
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
it('handles binary files (modified)', () => {
|
|
253
|
-
const result = parseDiff(fixture('binary-modified.diff'));
|
|
254
|
-
|
|
255
|
-
expect(result.files[0].isBinary).toBe(true);
|
|
256
|
-
expect(result.files[0].status).toBe('modified');
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
it('handles binary files (deleted)', () => {
|
|
260
|
-
const result = parseDiff(fixture('binary-deleted.diff'));
|
|
261
|
-
|
|
262
|
-
expect(result.files[0].isBinary).toBe(true);
|
|
263
|
-
expect(result.files[0].status).toBe('deleted');
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
it('handles files with spaces in path', () => {
|
|
267
|
-
const result = parseDiff(fixture('spaces-in-path.diff'));
|
|
268
|
-
|
|
269
|
-
expect(result.files[0].oldPath).toBe('my folder/my file.ts');
|
|
270
|
-
expect(result.files[0].newPath).toBe('my folder/my file.ts');
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
it('handles unicode content', () => {
|
|
274
|
-
const result = parseDiff(fixture('unicode-content.diff'));
|
|
275
|
-
|
|
276
|
-
expect(result.files).toHaveLength(1);
|
|
277
|
-
const addLine = result.files[0].hunks[0].lines.find(l => l.type === 'add' && l.content.includes('emoji'));
|
|
278
|
-
expect(addLine).toBeDefined();
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
it('handles submodule changes', () => {
|
|
282
|
-
const result = parseDiff(fixture('submodule.diff'));
|
|
283
|
-
|
|
284
|
-
expect(result.files).toHaveLength(1);
|
|
285
|
-
expect(result.files[0].newPath).toBe('vendor/lib');
|
|
286
|
-
});
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
describe('stats computation', () => {
|
|
290
|
-
it('computes per-file stats', () => {
|
|
291
|
-
const result = parseDiff(fixture('single-file-mixed.diff'));
|
|
292
|
-
|
|
293
|
-
expect(result.files[0].additions).toBe(3);
|
|
294
|
-
expect(result.files[0].deletions).toBe(2);
|
|
295
|
-
});
|
|
296
|
-
|
|
297
|
-
it('computes total stats across files', () => {
|
|
298
|
-
const result = parseDiff(fixture('multi-file.diff'));
|
|
299
|
-
|
|
300
|
-
expect(result.stats.filesChanged).toBe(2);
|
|
301
|
-
expect(result.stats.totalAdditions).toBeGreaterThan(0);
|
|
302
|
-
expect(result.stats.totalDeletions).toBeGreaterThan(0);
|
|
303
|
-
});
|
|
304
|
-
|
|
305
|
-
it('binary files report 0 additions/deletions', () => {
|
|
306
|
-
const result = parseDiff(fixture('binary-file.diff'));
|
|
307
|
-
|
|
308
|
-
expect(result.files[0].additions).toBe(0);
|
|
309
|
-
expect(result.files[0].deletions).toBe(0);
|
|
310
|
-
});
|
|
311
|
-
});
|
|
312
|
-
});
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { readFileSync } from 'node:fs';
|
|
3
|
-
import { resolve, dirname } from 'node:path';
|
|
4
|
-
import { fileURLToPath } from 'node:url';
|
|
5
|
-
import { parseDiff } from '../src/index.js';
|
|
6
|
-
|
|
7
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
-
const fixture = (name: string) =>
|
|
9
|
-
readFileSync(resolve(__dirname, './fixtures', name), 'utf-8');
|
|
10
|
-
|
|
11
|
-
describe('word diff integration', () => {
|
|
12
|
-
it('attaches word diff to paired delete+add lines', () => {
|
|
13
|
-
const result = parseDiff(fixture('single-file-deletions.diff'));
|
|
14
|
-
const hunk = result.files[0].hunks[0];
|
|
15
|
-
|
|
16
|
-
const delLines = hunk.lines.filter(l => l.type === 'delete');
|
|
17
|
-
const addLines = hunk.lines.filter(l => l.type === 'add');
|
|
18
|
-
|
|
19
|
-
expect(delLines[0].wordDiff).toBeDefined();
|
|
20
|
-
expect(addLines[0].wordDiff).toBeDefined();
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('does not attach word diff to pure additions', () => {
|
|
24
|
-
const result = parseDiff(fixture('single-file-additions.diff'));
|
|
25
|
-
const hunk = result.files[0].hunks[0];
|
|
26
|
-
const addLines = hunk.lines.filter(l => l.type === 'add');
|
|
27
|
-
|
|
28
|
-
for (const line of addLines) {
|
|
29
|
-
expect(line.wordDiff).toBeUndefined();
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it('pairs consecutive delete+add sequences for word diff', () => {
|
|
34
|
-
const result = parseDiff(fixture('single-file-mixed.diff'));
|
|
35
|
-
const hunk = result.files[0].hunks[0];
|
|
36
|
-
|
|
37
|
-
const lines = hunk.lines;
|
|
38
|
-
const portDel = lines.find(
|
|
39
|
-
l => l.type === 'delete' && l.content.includes('3000')
|
|
40
|
-
);
|
|
41
|
-
const portAdd = lines.find(
|
|
42
|
-
l => l.type === 'add' && l.content.includes('8080')
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
expect(portDel?.wordDiff).toBeDefined();
|
|
46
|
-
expect(portAdd?.wordDiff).toBeDefined();
|
|
47
|
-
|
|
48
|
-
const portDelSegments = portDel!.wordDiff!;
|
|
49
|
-
const hasDelete = portDelSegments.some(s => s.type === 'delete');
|
|
50
|
-
expect(hasDelete).toBe(true);
|
|
51
|
-
});
|
|
52
|
-
});
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { computeWordDiff } from '../src/word-diff.js';
|
|
3
|
-
|
|
4
|
-
describe('computeWordDiff', () => {
|
|
5
|
-
it('returns equal segment for identical lines', () => {
|
|
6
|
-
const result = computeWordDiff('hello world', 'hello world');
|
|
7
|
-
|
|
8
|
-
expect(result).toEqual([{ text: 'hello world', type: 'equal' }]);
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
it('detects single word change', () => {
|
|
12
|
-
const result = computeWordDiff('const x = 5;', 'const x = 10;');
|
|
13
|
-
|
|
14
|
-
expect(result).toEqual([
|
|
15
|
-
{ text: 'const x = ', type: 'equal' },
|
|
16
|
-
{ text: '5', type: 'delete' },
|
|
17
|
-
{ text: '10', type: 'insert' },
|
|
18
|
-
{ text: ';', type: 'equal' },
|
|
19
|
-
]);
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it('detects word added at end', () => {
|
|
23
|
-
const result = computeWordDiff('hello', 'hello world');
|
|
24
|
-
|
|
25
|
-
expect(result).toEqual([
|
|
26
|
-
{ text: 'hello', type: 'equal' },
|
|
27
|
-
{ text: ' world', type: 'insert' },
|
|
28
|
-
]);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it('detects word deleted from beginning', () => {
|
|
32
|
-
const result = computeWordDiff('const x = 1;', 'x = 1;');
|
|
33
|
-
|
|
34
|
-
expect(result).toEqual([
|
|
35
|
-
{ text: 'const ', type: 'delete' },
|
|
36
|
-
{ text: 'x = 1;', type: 'equal' },
|
|
37
|
-
]);
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it('detects multiple word changes', () => {
|
|
41
|
-
const result = computeWordDiff(
|
|
42
|
-
'import { foo } from "bar";',
|
|
43
|
-
'import { baz } from "qux";'
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
expect(result).toEqual([
|
|
47
|
-
{ text: 'import { ', type: 'equal' },
|
|
48
|
-
{ text: 'foo', type: 'delete' },
|
|
49
|
-
{ text: 'baz', type: 'insert' },
|
|
50
|
-
{ text: ' } from "', type: 'equal' },
|
|
51
|
-
{ text: 'bar', type: 'delete' },
|
|
52
|
-
{ text: 'qux', type: 'insert' },
|
|
53
|
-
{ text: '";', type: 'equal' },
|
|
54
|
-
]);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it('handles entirely different lines', () => {
|
|
58
|
-
const result = computeWordDiff('abc', 'xyz');
|
|
59
|
-
|
|
60
|
-
expect(result).toEqual([
|
|
61
|
-
{ text: 'abc', type: 'delete' },
|
|
62
|
-
{ text: 'xyz', type: 'insert' },
|
|
63
|
-
]);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it('handles empty old line', () => {
|
|
67
|
-
const result = computeWordDiff('', 'hello');
|
|
68
|
-
|
|
69
|
-
expect(result).toEqual([{ text: 'hello', type: 'insert' }]);
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it('handles empty new line', () => {
|
|
73
|
-
const result = computeWordDiff('hello', '');
|
|
74
|
-
|
|
75
|
-
expect(result).toEqual([{ text: 'hello', type: 'delete' }]);
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
it('handles indentation change', () => {
|
|
79
|
-
const result = computeWordDiff(' return x;', ' return x;');
|
|
80
|
-
|
|
81
|
-
expect(result).toEqual([
|
|
82
|
-
{ text: ' ', type: 'delete' },
|
|
83
|
-
{ text: ' ', type: 'insert' },
|
|
84
|
-
{ text: 'return x;', type: 'equal' },
|
|
85
|
-
]);
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
it('handles case change', () => {
|
|
89
|
-
const result = computeWordDiff('Foo', 'foo');
|
|
90
|
-
|
|
91
|
-
expect(result).toEqual([
|
|
92
|
-
{ text: 'Foo', type: 'delete' },
|
|
93
|
-
{ text: 'foo', type: 'insert' },
|
|
94
|
-
]);
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
it('handles string content change', () => {
|
|
98
|
-
const result = computeWordDiff(
|
|
99
|
-
'const msg = "hello";',
|
|
100
|
-
'const msg = "world";'
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
expect(result).toEqual([
|
|
104
|
-
{ text: 'const msg = "', type: 'equal' },
|
|
105
|
-
{ text: 'hello', type: 'delete' },
|
|
106
|
-
{ text: 'world', type: 'insert' },
|
|
107
|
-
{ text: '";', type: 'equal' },
|
|
108
|
-
]);
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
it('handles whitespace-only change between words', () => {
|
|
112
|
-
const result = computeWordDiff('a b', 'a b');
|
|
113
|
-
|
|
114
|
-
expect(result).toEqual([
|
|
115
|
-
{ text: 'a', type: 'equal' },
|
|
116
|
-
{ text: ' ', type: 'delete' },
|
|
117
|
-
{ text: ' ', type: 'insert' },
|
|
118
|
-
{ text: 'b', type: 'equal' },
|
|
119
|
-
]);
|
|
120
|
-
});
|
|
121
|
-
});
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: diffity-resolve
|
|
3
|
-
description: Read open review comments and resolve them by making code fixes
|
|
4
|
-
user-invocable: true
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Diffity Resolve Skill
|
|
8
|
-
|
|
9
|
-
You are reading open review comments and resolving them by making the requested code changes.
|
|
10
|
-
|
|
11
|
-
## Arguments
|
|
12
|
-
|
|
13
|
-
- `thread-id` (optional): Resolve a specific thread by ID instead of all open threads. Example: `/diffity-resolve abc123`
|
|
14
|
-
|
|
15
|
-
## CLI Reference
|
|
16
|
-
|
|
17
|
-
```
|
|
18
|
-
{{binary}} agent list [--status open|resolved|dismissed] [--json]
|
|
19
|
-
{{binary}} agent comment --file <path> --line <n> [--end-line <n>] [--side new|old] --body "<text>"
|
|
20
|
-
{{binary}} agent general-comment --body "<text>"
|
|
21
|
-
{{binary}} agent resolve <id> [--summary "<text>"]
|
|
22
|
-
{{binary}} agent dismiss <id> [--reason "<text>"]
|
|
23
|
-
{{binary}} agent reply <id> --body "<text>"
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
- `--file`, `--line`, `--body` are required for `comment`
|
|
27
|
-
- `--end-line` defaults to `--line` (single-line comment)
|
|
28
|
-
- `--side` defaults to `new`
|
|
29
|
-
- `general-comment` creates a diff-level comment not tied to any file or line
|
|
30
|
-
- `<id>` accepts full UUID or 8-char prefix
|
|
31
|
-
|
|
32
|
-
## Prerequisites
|
|
33
|
-
|
|
34
|
-
1. Check that `{{binary}}` is available: run `which {{binary}}`. If not found, {{install_hint}}.
|
|
35
|
-
2. Check that a review session exists: run `cat .diffity/current-session`. If the file doesn't exist or is stale, tell the user to start diffity first.
|
|
36
|
-
|
|
37
|
-
## Instructions
|
|
38
|
-
|
|
39
|
-
1. List open comment threads with full details:
|
|
40
|
-
```
|
|
41
|
-
{{binary}} agent list --status open --json
|
|
42
|
-
```
|
|
43
|
-
If a `thread-id` argument was provided, filter to just that thread. The JSON output includes the full comment body, file path, line numbers, and side for each thread.
|
|
44
|
-
2. If there are no open threads, tell the user there's nothing to resolve.
|
|
45
|
-
3. For each open thread:
|
|
46
|
-
a. **Skip** general comments (filePath `__general__`) — these are summaries, not actionable code changes.
|
|
47
|
-
b. **Skip** threads tagged `[question]` or `[nit]` — these don't require code changes. Tell the user you skipped them and why.
|
|
48
|
-
c. Read the comment body from the JSON output and understand what change is requested.
|
|
49
|
-
d. Read the relevant source file to understand the full context around the commented lines, then make the requested code change using the Edit tool.
|
|
50
|
-
e. After making the change, resolve the thread with a summary:
|
|
51
|
-
```
|
|
52
|
-
{{binary}} agent resolve <thread-id> --summary "Fixed: <brief description of what was changed>"
|
|
53
|
-
```
|
|
54
|
-
4. After resolving all applicable threads, run `{{binary}} agent list` to confirm status.
|
|
55
|
-
5. Tell the user to check the browser — resolved status will appear within 2 seconds via polling.
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: diffity-review
|
|
3
|
-
description: Review current diff and leave comments using diffity agent commands
|
|
4
|
-
user-invocable: true
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Diffity Review Skill
|
|
8
|
-
|
|
9
|
-
You are reviewing a diff and leaving inline comments using the `{{binary}} agent` CLI.
|
|
10
|
-
|
|
11
|
-
## Arguments
|
|
12
|
-
|
|
13
|
-
- `focus` (optional): Focus the review on a specific area. One of: `security`, `performance`, `naming`, `errors`, `types`, `logic`. If omitted, review everything.
|
|
14
|
-
|
|
15
|
-
## CLI Reference
|
|
16
|
-
|
|
17
|
-
```
|
|
18
|
-
{{binary}} agent list [--status open|resolved|dismissed] [--json]
|
|
19
|
-
{{binary}} agent comment --file <path> --line <n> [--end-line <n>] [--side new|old] --body "<text>"
|
|
20
|
-
{{binary}} agent general-comment --body "<text>"
|
|
21
|
-
{{binary}} agent resolve <id> [--summary "<text>"]
|
|
22
|
-
{{binary}} agent dismiss <id> [--reason "<text>"]
|
|
23
|
-
{{binary}} agent reply <id> --body "<text>"
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
- `--file`, `--line`, `--body` are required for `comment`
|
|
27
|
-
- `--end-line` defaults to `--line` (single-line comment)
|
|
28
|
-
- `--side` defaults to `new`
|
|
29
|
-
- `general-comment` creates a diff-level comment not tied to any file or line
|
|
30
|
-
- `<id>` accepts full UUID or 8-char prefix
|
|
31
|
-
|
|
32
|
-
## Prerequisites
|
|
33
|
-
|
|
34
|
-
1. Check that `{{binary}}` is available: run `which {{binary}}`. If not found, {{install_hint}}.
|
|
35
|
-
2. Check that a review session exists: run `cat .diffity/current-session`. If the file doesn't exist or is stale, tell the user to start diffity first (e.g. `{{binary}}`).
|
|
36
|
-
|
|
37
|
-
## Instructions
|
|
38
|
-
|
|
39
|
-
1. Read the current diff using `git diff`. Check `.diffity/current-session` to determine which ref is active.
|
|
40
|
-
2. For each changed file, read the **entire file** (not just the diff hunks) to understand the full context. This prevents false positives from missing surrounding code.
|
|
41
|
-
3. Analyze the code changes thoroughly. If a `focus` argument was provided, concentrate on that area. Otherwise look for:
|
|
42
|
-
- Bugs, logic errors, off-by-one errors
|
|
43
|
-
- Security issues (injection, XSS, auth bypass)
|
|
44
|
-
- Performance problems
|
|
45
|
-
- Missing error handling at system boundaries
|
|
46
|
-
- Race conditions
|
|
47
|
-
- API contract violations
|
|
48
|
-
- Unclear or misleading naming
|
|
49
|
-
4. **Only comment on code that was changed in the diff.** Do not flag pre-existing issues in unchanged code — this is a review of the diff, not an audit of the entire file. The only exception is if a change in the diff introduces a bug in combination with existing code.
|
|
50
|
-
5. **Prioritize signal over volume.** A clean diff should get a clean review. Do not manufacture findings to appear thorough. If a diff with 5 changed lines only has 1 real issue, leave 1 comment.
|
|
51
|
-
6. **Do not repeat the same issue across files.** If the same pattern appears in multiple places, leave one inline comment on the first occurrence and mention it in the general summary instead of commenting on every instance.
|
|
52
|
-
7. Categorize each finding with a severity prefix in the comment body:
|
|
53
|
-
- `[must-fix]` — Bugs, security issues, data loss risks. These must be addressed.
|
|
54
|
-
- `[suggestion]` — Improvements that would meaningfully improve the code.
|
|
55
|
-
- `[nit]` — Style or preference. Fine to ignore.
|
|
56
|
-
- `[question]` — Something unclear that needs clarification from the author.
|
|
57
|
-
8. For each finding, leave a comment using:
|
|
58
|
-
```
|
|
59
|
-
{{binary}} agent comment --file <path> --line <n> [--end-line <n>] [--side new] --body "<comment>"
|
|
60
|
-
```
|
|
61
|
-
- Use `--side new` (default) for comments on added/modified code
|
|
62
|
-
- Use `--side old` for comments on removed code
|
|
63
|
-
- Use `--end-line` when the issue spans multiple lines
|
|
64
|
-
- Be specific and actionable in your comments
|
|
65
|
-
9. After leaving all inline comments, write a general comment that summarizes your overall assessment of the diff. This should cover:
|
|
66
|
-
- Overall quality verdict (e.g. "Looks good with minor issues" or "Needs significant changes before merging")
|
|
67
|
-
- Cross-cutting concerns that don't belong on any single line (architecture, naming consistency across files, missing tests, etc.)
|
|
68
|
-
- A count of findings by severity (e.g. "2 must-fix, 3 suggestions, 1 nit")
|
|
69
|
-
```
|
|
70
|
-
{{binary}} agent general-comment --body "<overall review summary>"
|
|
71
|
-
```
|
|
72
|
-
If there are no inline findings, still leave a general comment with your assessment (e.g. "Clean diff — no issues found").
|
|
73
|
-
10. Run `{{binary}} agent list` to confirm all comments were created.
|
|
74
|
-
11. Tell the user to check the browser — comments will appear within 2 seconds via polling.
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: diffity-start
|
|
3
|
-
description: Start the diffity diff viewer server for the current working tree or staged changes
|
|
4
|
-
user-invocable: true
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Diffity Start Skill
|
|
8
|
-
|
|
9
|
-
You are starting the diffity diff viewer so the user can see their changes in the browser.
|
|
10
|
-
|
|
11
|
-
## Instructions
|
|
12
|
-
|
|
13
|
-
1. Check that `{{binary}}` is available: run `which {{binary}}`. If not found, {{install_hint}}.
|
|
14
|
-
2. Start the server using the Bash tool with `run_in_background: true`:
|
|
15
|
-
- Command: `{{binary}}`
|
|
16
|
-
- Do NOT use `&` or `--quiet` — let the Bash tool handle backgrounding
|
|
17
|
-
- The browser will open automatically and the session is auto-created on startup
|
|
18
|
-
4. Wait 2 seconds, then verify the session exists by checking that `.diffity/current-session` file is present.
|
|
19
|
-
5. Tell the user diffity is running and show them what they can do next. Keep it short — don't show session IDs, hashes, or other internals. Example:
|
|
20
|
-
|
|
21
|
-
> Diffity is running — check your browser.
|
|
22
|
-
>
|
|
23
|
-
> Here's what you can do:
|
|
24
|
-
> - **{{slash}}review** — get a code review on your changes
|
|
25
|
-
> - **{{slash}}resolve** — fix issues from review comments
|