@aiderdesk/aiderdesk 0.61.1 → 0.64.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/out/renderer/assets/{_baseUniq-BPF2Herp.js → _baseUniq-C6Q8LpuQ.js} +1 -1
- package/out/renderer/assets/abap-B7h4dtBh.js +7 -0
- package/out/renderer/assets/actionscript-3-DtnkuHN2.js +7 -0
- package/out/renderer/assets/ada-BZS802Se.js +7 -0
- package/out/renderer/assets/andromeeda-C847lm7Z.js +4 -0
- package/out/renderer/assets/angular-html-BYG42TJr.js +42 -0
- package/out/renderer/assets/angular-ts-BftcHvZ6.js +29 -0
- package/out/renderer/assets/apache-D4roVlsU.js +7 -0
- package/out/renderer/assets/apex-B-mI3Md2.js +7 -0
- package/out/renderer/assets/apl-CGZawg-A.js +18 -0
- package/out/renderer/assets/applescript-C43Knf0G.js +7 -0
- package/out/renderer/assets/ara-DRBH84ND.js +7 -0
- package/out/renderer/assets/{arc-DfPLteHF.js → arc-DoIK-bD2.js} +1 -1
- package/out/renderer/assets/{architectureDiagram-Q4EWVU46-Bw0u-sSH.js → architectureDiagram-Q4EWVU46-B8_dgBXp.js} +5 -5
- package/out/renderer/assets/asciidoc-CT8_dLUs.js +7 -0
- package/out/renderer/assets/asm-3tg4MVib.js +7 -0
- package/out/renderer/assets/astro-BxdWOZvM.js +19 -0
- package/out/renderer/assets/aurora-x-wJ4-eM2h.js +4 -0
- package/out/renderer/assets/awk-ChreaG-G.js +7 -0
- package/out/renderer/assets/ayu-dark-rtpbXCNg.js +4 -0
- package/out/renderer/assets/ayu-light-BCZDSyV8.js +4 -0
- package/out/renderer/assets/ayu-mirage-BVoH71sA.js +4 -0
- package/out/renderer/assets/ballerina-B0yt0TYU.js +7 -0
- package/out/renderer/assets/bat-BzNgQIA7.js +7 -0
- package/out/renderer/assets/beancount-aZWrE5WV.js +7 -0
- package/out/renderer/assets/berry--Qc8OslH.js +7 -0
- package/out/renderer/assets/bibtex-BLeFwAes.js +7 -0
- package/out/renderer/assets/bicep-DbBeGdXQ.js +7 -0
- package/out/renderer/assets/bird2-aXhIUHPg.js +7 -0
- package/out/renderer/assets/blade-BbH7YAUi.js +22 -0
- package/out/renderer/assets/{blockDiagram-DXYQGD6D-CkfB9if8.js → blockDiagram-DXYQGD6D-BDOvGPDN.js} +6 -6
- package/out/renderer/assets/bsl-DwPS0BId.js +9 -0
- package/out/renderer/assets/c-C4VtT7JA.js +7 -0
- package/out/renderer/assets/c3-CWHczQMq.js +7 -0
- package/out/renderer/assets/{c4Diagram-AHTNJAMY-DweK9Liz.js → c4Diagram-AHTNJAMY-1ABZnJ2v.js} +2 -2
- package/out/renderer/assets/cadence-S_NtR5Dy.js +7 -0
- package/out/renderer/assets/cairo-BtYx2aM5.js +9 -0
- package/out/renderer/assets/catppuccin-frappe-C21OPQfC.js +4 -0
- package/out/renderer/assets/catppuccin-latte-0ZtXlsrX.js +4 -0
- package/out/renderer/assets/catppuccin-macchiato-BD_FR4sl.js +4 -0
- package/out/renderer/assets/catppuccin-mocha-C653csR5.js +4 -0
- package/out/renderer/assets/{channel-C5wwrRof.js → channel-Cr_H2zdE.js} +1 -1
- package/out/renderer/assets/{chunk-4BX2VUAB-0KM14cFd.js → chunk-4BX2VUAB-d88VZY9C.js} +1 -1
- package/out/renderer/assets/{chunk-4TB4RGXK-CmVtCVL4.js → chunk-4TB4RGXK-DLcMuHVI.js} +5 -5
- package/out/renderer/assets/{chunk-55IACEB6-BzVYZvBM.js → chunk-55IACEB6-BO1oJBQV.js} +1 -1
- package/out/renderer/assets/{chunk-EDXVE4YY-BryQl5Kv.js → chunk-EDXVE4YY-Dt80V_EG.js} +1 -1
- package/out/renderer/assets/{chunk-FMBD7UC4-CRiLea_e.js → chunk-FMBD7UC4-D5MNbIWZ.js} +1 -1
- package/out/renderer/assets/{chunk-OYMX7WX6-Cpi4N3NO.js → chunk-OYMX7WX6-DBFhtMcs.js} +3 -3
- package/out/renderer/assets/{chunk-QZHKN3VN-BT8kABWC.js → chunk-QZHKN3VN-Bxwt_pyh.js} +1 -1
- package/out/renderer/assets/{chunk-YZCP3GAM-OLZV_Sef.js → chunk-YZCP3GAM-gAcMGuhT.js} +1 -1
- package/out/renderer/assets/clarity-D2ViJC0i.js +7 -0
- package/out/renderer/assets/{classDiagram-6PBFFD2Q-VdE6G90i.js → classDiagram-6PBFFD2Q-B7lgamMP.js} +6 -6
- package/out/renderer/assets/{classDiagram-v2-HSJHXN6E-VdE6G90i.js → classDiagram-v2-HSJHXN6E-B7lgamMP.js} +6 -6
- package/out/renderer/assets/clojure-C_G4_w5x.js +7 -0
- package/out/renderer/assets/{clone-DwQZ86nS.js → clone-DKkqtIT8.js} +1 -1
- package/out/renderer/assets/cmake-CDfQILeU.js +7 -0
- package/out/renderer/assets/cobol-B8r1pfPr.js +13 -0
- package/out/renderer/assets/codeowners-awy7PWCD.js +7 -0
- package/out/renderer/assets/codeql-lfK8ppuq.js +7 -0
- package/out/renderer/assets/coffee-XLjtuEYs.js +9 -0
- package/out/renderer/assets/common-lisp-DAq1kaby.js +7 -0
- package/out/renderer/assets/coq-l_JvzFJl.js +7 -0
- package/out/renderer/assets/{cose-bilkent-S5V4N54A-BEcAKM9H.js → cose-bilkent-S5V4N54A-BZNBIG2x.js} +1 -1
- package/out/renderer/assets/cpp-zh2ePAE_.js +22 -0
- package/out/renderer/assets/crystal-BqBRy7Ec.js +19 -0
- package/out/renderer/assets/csharp-DxX_6tHh.js +7 -0
- package/out/renderer/assets/css-BtVcDqlU.js +7 -0
- package/out/renderer/assets/csv-Ba84L8e5.js +7 -0
- package/out/renderer/assets/cue-BFSVLV6N.js +7 -0
- package/out/renderer/assets/cypher-DbUmWIxC.js +7 -0
- package/out/renderer/assets/d-9qSZPw74.js +7 -0
- package/out/renderer/assets/{dagre-KV5264BT-BcFQYL1M.js → dagre-KV5264BT-C3hXUNb-.js} +6 -6
- package/out/renderer/assets/dark-plus-DmZ1Dzd4.js +4 -0
- package/out/renderer/assets/dart-CCSsOg9l.js +7 -0
- package/out/renderer/assets/dax-CvsmLV-B.js +7 -0
- package/out/renderer/assets/desktop-_xiGZ9X1.js +7 -0
- package/out/renderer/assets/{diagram-5BDNPKRD-GrUNdC1u.js → diagram-5BDNPKRD-DNh45EqP.js} +6 -6
- package/out/renderer/assets/{diagram-G4DWMVQ6-CG4S-ov5.js → diagram-G4DWMVQ6-8lhqJfPk.js} +6 -6
- package/out/renderer/assets/{diagram-MMDJMWI5-9ogY3MRC.js → diagram-MMDJMWI5-BcI1Ek4N.js} +5 -5
- package/out/renderer/assets/{diagram-TYMM5635-Ck7mI1bS.js → diagram-TYMM5635-DuHcW-s7.js} +5 -5
- package/out/renderer/assets/diff-BEdzuHlE.js +7 -0
- package/out/renderer/assets/docker-CUaLOm2I.js +7 -0
- package/out/renderer/assets/dotenv-Bb4iNxXK.js +7 -0
- package/out/renderer/assets/dracula-B8-AVrwI.js +4 -0
- package/out/renderer/assets/dracula-soft-BHeefow7.js +4 -0
- package/out/renderer/assets/dream-maker-CNLQpoF-.js +7 -0
- package/out/renderer/assets/edge-CnHxQ_FD.js +15 -0
- package/out/renderer/assets/elixir-B_LIBv5J.js +11 -0
- package/out/renderer/assets/elm-BlO7pcFp.js +10 -0
- package/out/renderer/assets/emacs-lisp-4gdXY_g3.js +7 -0
- package/out/renderer/assets/{erDiagram-SMLLAGMA-Dvf_c-7M.js → erDiagram-SMLLAGMA-I6Q9HYdF.js} +4 -4
- package/out/renderer/assets/erb-Bzn22wO6.js +28 -0
- package/out/renderer/assets/erlang-Ch5kuXHm.js +9 -0
- package/out/renderer/assets/everforest-dark-Cg1xdODP.js +4 -0
- package/out/renderer/assets/everforest-light-BmTD3bxe.js +4 -0
- package/out/renderer/assets/fennel-BTELNkeT.js +7 -0
- package/out/renderer/assets/fish-kGF2-4SL.js +7 -0
- package/out/renderer/assets/{flowDiagram-DWJPFMVM-CPDjOXYp.js → flowDiagram-DWJPFMVM-BzRjtX5C.js} +6 -6
- package/out/renderer/assets/fluent-YyC28MRr.js +7 -0
- package/out/renderer/assets/fortran-fixed-form-CpmOyvS5.js +9 -0
- package/out/renderer/assets/fortran-free-form-5X94ETMi.js +7 -0
- package/out/renderer/assets/fsharp-5vtGqRR9.js +9 -0
- package/out/renderer/assets/{ganttDiagram-T4ZO3ILL-B4dJrK-3.js → ganttDiagram-T4ZO3ILL-DVkem_IA.js} +1 -1
- package/out/renderer/assets/gdresource-B5TLWiFO.js +11 -0
- package/out/renderer/assets/gdscript-CNW3Aj-d.js +7 -0
- package/out/renderer/assets/gdshader-BEzE4j_3.js +7 -0
- package/out/renderer/assets/genie-BvhtM5Ga.js +7 -0
- package/out/renderer/assets/gherkin-xCNF9gh8.js +7 -0
- package/out/renderer/assets/git-commit-PP9xCApN.js +9 -0
- package/out/renderer/assets/git-rebase-D-XQSvDj.js +9 -0
- package/out/renderer/assets/{gitGraphDiagram-UUTBAWPF-De2eCfMN.js → gitGraphDiagram-UUTBAWPF-BYpvdMpK.js} +6 -6
- package/out/renderer/assets/github-dark-O22yVQaY.js +4 -0
- package/out/renderer/assets/github-dark-default-DB2Hkvqn.js +4 -0
- package/out/renderer/assets/github-dark-dimmed-CMZ_OfqC.js +4 -0
- package/out/renderer/assets/github-dark-high-contrast-DmxWVmCU.js +4 -0
- package/out/renderer/assets/github-light-BTbR9xVK.js +4 -0
- package/out/renderer/assets/github-light-default-DWEonwFe.js +4 -0
- package/out/renderer/assets/github-light-high-contrast-WJ_cPDts.js +4 -0
- package/out/renderer/assets/gleam-LmNxrMsN.js +7 -0
- package/out/renderer/assets/glimmer-js-h2QNNiD7.js +15 -0
- package/out/renderer/assets/glimmer-ts-Bk3uX6Ae.js +15 -0
- package/out/renderer/assets/glsl-CGsiYPcu.js +9 -0
- package/out/renderer/assets/gn-OUMx7fqt.js +7 -0
- package/out/renderer/assets/gnuplot-tV8vezdE.js +7 -0
- package/out/renderer/assets/go-DRMr3iML.js +7 -0
- package/out/renderer/assets/{graph-BFn23kR_.js → graph-CAtr5PoG.js} +2 -2
- package/out/renderer/assets/graphql-CwmtR1ib.js +15 -0
- package/out/renderer/assets/groovy-Bn4MhXgW.js +7 -0
- package/out/renderer/assets/gruvbox-dark-hard-DVsRsETr.js +4 -0
- package/out/renderer/assets/gruvbox-dark-medium-B5JBrQdg.js +4 -0
- package/out/renderer/assets/gruvbox-dark-soft-Db-YOqRx.js +4 -0
- package/out/renderer/assets/gruvbox-light-hard-CXzJt7DI.js +4 -0
- package/out/renderer/assets/gruvbox-light-medium-B89RAI1Y.js +4 -0
- package/out/renderer/assets/gruvbox-light-soft-Cs0hTZYv.js +4 -0
- package/out/renderer/assets/hack-BTX3ICIE.js +13 -0
- package/out/renderer/assets/haml-DrIklt7F.js +11 -0
- package/out/renderer/assets/handlebars-yWFGGD2R.js +15 -0
- package/out/renderer/assets/haskell-CzPS7wjM.js +7 -0
- package/out/renderer/assets/haxe-BpobLYM9.js +7 -0
- package/out/renderer/assets/hcl-axoq0Ycu.js +7 -0
- package/out/renderer/assets/hjson-I7LcauIB.js +7 -0
- package/out/renderer/assets/hlsl-TRzjajlb.js +7 -0
- package/out/renderer/assets/horizon-DWzh3z5C.js +4 -0
- package/out/renderer/assets/horizon-bright-C1AFkPsv.js +4 -0
- package/out/renderer/assets/houston-CF_ws8Cq.js +4 -0
- package/out/renderer/assets/html-GC16tDh9.js +11 -0
- package/out/renderer/assets/html-derivative-HU9p64q4.js +11 -0
- package/out/renderer/assets/http-DjsOm9E4.js +20 -0
- package/out/renderer/assets/hurl-Am2cDU4f.js +18 -0
- package/out/renderer/assets/hxml-Jle7oGdm.js +9 -0
- package/out/renderer/assets/hy-B1k9U6S8.js +7 -0
- package/out/renderer/assets/imba-C4923lSV.js +7 -0
- package/out/renderer/assets/{index-BL-57WPa.js → index-CNL53LoL.js} +33672 -11520
- package/out/renderer/assets/{index-BkntVzTm.css → index-Duw36zwk.css} +209 -24
- package/out/renderer/assets/{infoDiagram-42DDH7IO-BIt9B6mQ.js → infoDiagram-42DDH7IO-BcmBthOY.js} +4 -4
- package/out/renderer/assets/ini-B84Ha1bx.js +7 -0
- package/out/renderer/assets/{ishikawaDiagram-UXIWVN3A-CXZs0KGV.js → ishikawaDiagram-UXIWVN3A-moTWny-V.js} +1 -1
- package/out/renderer/assets/java-BfXh-0uJ.js +7 -0
- package/out/renderer/assets/javascript-BsAkV7mL.js +7 -0
- package/out/renderer/assets/jinja-FkIlHBgj.js +16 -0
- package/out/renderer/assets/jison-BkdOIOd4.js +9 -0
- package/out/renderer/assets/{journeyDiagram-VCZTEJTY-B-EXuj5b.js → journeyDiagram-VCZTEJTY-DOW8zaZt.js} +4 -4
- package/out/renderer/assets/json-TjWBGEk1.js +7 -0
- package/out/renderer/assets/json5-DCGCKrmX.js +7 -0
- package/out/renderer/assets/jsonc-DLVLp8id.js +7 -0
- package/out/renderer/assets/jsonl-B-R_pDGg.js +7 -0
- package/out/renderer/assets/jsonnet-Cs8BnnC6.js +7 -0
- package/out/renderer/assets/jssm-DDuANZ2u.js +7 -0
- package/out/renderer/assets/jsx-BPmvoin2.js +7 -0
- package/out/renderer/assets/julia-CU_UwNb8.js +20 -0
- package/out/renderer/assets/just-tGFryTtU.js +34 -0
- package/out/renderer/assets/kanagawa-dragon-DU8n2NNT.js +4 -0
- package/out/renderer/assets/kanagawa-lotus-Byd0CDet.js +4 -0
- package/out/renderer/assets/kanagawa-wave-DExoagcR.js +4 -0
- package/out/renderer/assets/{kanban-definition-6JOO6SKY-ByvN0qaD.js → kanban-definition-6JOO6SKY-DpJjTob4.js} +2 -2
- package/out/renderer/assets/kdl-DzNQTDs7.js +7 -0
- package/out/renderer/assets/kotlin-BM2ZNTMh.js +7 -0
- package/out/renderer/assets/kusto-dtpuxMFE.js +7 -0
- package/out/renderer/assets/laserwave-DF03wMlf.js +4 -0
- package/out/renderer/assets/latex-B0gTO9uZ.js +10 -0
- package/out/renderer/assets/{layout-BpybWUv6.js → layout-BvH51Ui9.js} +4 -4
- package/out/renderer/assets/lean-CTow-IzD.js +7 -0
- package/out/renderer/assets/less-BAzLMJNR.js +7 -0
- package/out/renderer/assets/light-plus-DS08Xg5J.js +4 -0
- package/out/renderer/assets/liquid-QmJ_LYTW.js +15 -0
- package/out/renderer/assets/llvm-CTKcAHbb.js +7 -0
- package/out/renderer/assets/log-BF22rfM9.js +7 -0
- package/out/renderer/assets/logo-D9l7oEJ8.js +7 -0
- package/out/renderer/assets/lua-BVbbqwZC.js +9 -0
- package/out/renderer/assets/luau-CdZ6BoEa.js +7 -0
- package/out/renderer/assets/make-DLtqaK4D.js +7 -0
- package/out/renderer/assets/markdown-F_EULe_G.js +7 -0
- package/out/renderer/assets/marko-BAWrmNIa.js +15 -0
- package/out/renderer/assets/material-theme-B8B2U48Q.js +4 -0
- package/out/renderer/assets/material-theme-darker-BV0iY_T3.js +4 -0
- package/out/renderer/assets/material-theme-lighter-DrzybSTF.js +4 -0
- package/out/renderer/assets/material-theme-ocean-BRPLVReX.js +4 -0
- package/out/renderer/assets/material-theme-palenight-DSJwsR_D.js +4 -0
- package/out/renderer/assets/matlab-7XHduepk.js +7 -0
- package/out/renderer/assets/mdc-Ca0ft0PS.js +16 -0
- package/out/renderer/assets/mdx-D5wExp-O.js +7 -0
- package/out/renderer/assets/mermaid-z_1ejSlp.js +7 -0
- package/out/renderer/assets/{min-DB8ixvoT.js → min-CowxrbD6.js} +2 -2
- package/out/renderer/assets/min-dark-BNaN9fWk.js +4 -0
- package/out/renderer/assets/min-light-CMrjentn.js +4 -0
- package/out/renderer/assets/{mindmap-definition-QFDTVHPH-Do-I-At8.js → mindmap-definition-QFDTVHPH-DggFFNHq.js} +3 -3
- package/out/renderer/assets/mipsasm-BQyyUrpa.js +7 -0
- package/out/renderer/assets/mojo-ByCRDvCf.js +7 -0
- package/out/renderer/assets/monokai-DelygWXa.js +4 -0
- package/out/renderer/assets/moonbit-CqjK87KZ.js +7 -0
- package/out/renderer/assets/move-DhTNmxqC.js +7 -0
- package/out/renderer/assets/narrat-CLjGcbCy.js +7 -0
- package/out/renderer/assets/nextflow-B166B-y1.js +9 -0
- package/out/renderer/assets/nextflow-groovy-BOO9s0iq.js +7 -0
- package/out/renderer/assets/nginx-BFAkI5_-.js +10 -0
- package/out/renderer/assets/night-owl-DSS199ra.js +4 -0
- package/out/renderer/assets/night-owl-light-gC6E-Eh2.js +4 -0
- package/out/renderer/assets/nim-B3PAIZ4D.js +22 -0
- package/out/renderer/assets/nix-ByWcmvXF.js +12 -0
- package/out/renderer/assets/nord-CvDbBq5M.js +4 -0
- package/out/renderer/assets/nushell-DB8ZUEbK.js +7 -0
- package/out/renderer/assets/objective-c-BRoNQF42.js +7 -0
- package/out/renderer/assets/objective-cpp-DEoN9Fe5.js +7 -0
- package/out/renderer/assets/ocaml-B1kfGk9Y.js +7 -0
- package/out/renderer/assets/odin-CNQ56Ay2.js +7 -0
- package/out/renderer/assets/one-dark-pro-CsMf0BoJ.js +4 -0
- package/out/renderer/assets/one-light-B0cTzZyr.js +4 -0
- package/out/renderer/assets/openscad-C_m7ehZF.js +7 -0
- package/out/renderer/assets/pascal-CU8Kjkr_.js +7 -0
- package/out/renderer/assets/perl-HITCDkgu.js +18 -0
- package/out/renderer/assets/php-C2HieitX.js +20 -0
- package/out/renderer/assets/{pieDiagram-DEJITSTG-Cnpf6Gt6.js → pieDiagram-DEJITSTG-BED4dnMF.js} +6 -6
- package/out/renderer/assets/pierre-dark-DADY5eR0.js +4 -0
- package/out/renderer/assets/pierre-light-DUjirxKp.js +4 -0
- package/out/renderer/assets/pkl-BsByaYax.js +7 -0
- package/out/renderer/assets/plastic-BjwMpBc0.js +4 -0
- package/out/renderer/assets/plsql-B3Na24V4.js +7 -0
- package/out/renderer/assets/po-BajfNjc5.js +7 -0
- package/out/renderer/assets/poimandres-ChWyhPrn.js +4 -0
- package/out/renderer/assets/polar-BB-dlxnO.js +7 -0
- package/out/renderer/assets/postcss-kj1IbjVd.js +7 -0
- package/out/renderer/assets/powerquery-B-e1fO-k.js +7 -0
- package/out/renderer/assets/powershell-BcMVbGpk.js +7 -0
- package/out/renderer/assets/prisma-bmxcSDxq.js +7 -0
- package/out/renderer/assets/prolog-BT9GCzqD.js +7 -0
- package/out/renderer/assets/proto-Ds-m32NR.js +7 -0
- package/out/renderer/assets/pug-BwQB43qN.js +13 -0
- package/out/renderer/assets/puppet-N15G4Usj.js +7 -0
- package/out/renderer/assets/purescript-DrwsEYNH.js +7 -0
- package/out/renderer/assets/python-CrdIx4PZ.js +7 -0
- package/out/renderer/assets/qml-jtL8okyu.js +9 -0
- package/out/renderer/assets/qmldir-DuMSk0Oz.js +7 -0
- package/out/renderer/assets/qss-BFrB6p4y.js +7 -0
- package/out/renderer/assets/{quadrantDiagram-34T5L4WZ-VcOb1qLd.js → quadrantDiagram-34T5L4WZ-RpQ3qNU5.js} +1 -1
- package/out/renderer/assets/r-Dpdc-Kyk.js +7 -0
- package/out/renderer/assets/racket-DbA06HL7.js +7 -0
- package/out/renderer/assets/raku-6v-Y17bs.js +7 -0
- package/out/renderer/assets/razor-gBXW6YBJ.js +13 -0
- package/out/renderer/assets/red-DByOl5N0.js +4 -0
- package/out/renderer/assets/reg-CULnG2WX.js +7 -0
- package/out/renderer/assets/regexp-BxWeO75u.js +7 -0
- package/out/renderer/assets/rel-CHRwzjd4.js +7 -0
- package/out/renderer/assets/{requirementDiagram-MS252O5E-VJs9Hpaw.js → requirementDiagram-MS252O5E-VQt4zBMB.js} +3 -3
- package/out/renderer/assets/riscv-BNQ9cVpw.js +7 -0
- package/out/renderer/assets/ron-CUEPaFZU.js +7 -0
- package/out/renderer/assets/rose-pine-B-kZ4Z9q.js +4 -0
- package/out/renderer/assets/rose-pine-dawn-efeVGdSI.js +4 -0
- package/out/renderer/assets/rose-pine-moon-DmodZNzl.js +4 -0
- package/out/renderer/assets/rosmsg-Bfahr6vb.js +7 -0
- package/out/renderer/assets/rst-by6KAwTb.js +37 -0
- package/out/renderer/assets/ruby-C13Bjepi.js +37 -0
- package/out/renderer/assets/rust-CMNYZh5a.js +7 -0
- package/out/renderer/assets/{sankeyDiagram-XADWPNL6-BoXxgLvi.js → sankeyDiagram-XADWPNL6-DywR7qAk.js} +1 -1
- package/out/renderer/assets/sas-BLBgC3TA.js +9 -0
- package/out/renderer/assets/sass-BheygBdF.js +7 -0
- package/out/renderer/assets/scala-B-_7vFVn.js +7 -0
- package/out/renderer/assets/scheme-BSHdPinv.js +7 -0
- package/out/renderer/assets/scss-Dq-LbI_c.js +9 -0
- package/out/renderer/assets/sdbl-BBUhycGU.js +7 -0
- package/out/renderer/assets/{sequenceDiagram-FGHM5R23-b69hQjSp.js → sequenceDiagram-FGHM5R23-CVPfZD4e.js} +3 -3
- package/out/renderer/assets/shaderlab-C07uO3dL.js +9 -0
- package/out/renderer/assets/shellscript-CQ8MXh-D.js +7 -0
- package/out/renderer/assets/shellsession-CkeTp4M1.js +9 -0
- package/out/renderer/assets/slack-dark-BEe10hxO.js +4 -0
- package/out/renderer/assets/slack-ochin-BKmu9pBc.js +4 -0
- package/out/renderer/assets/smalltalk-qxcGy4fT.js +7 -0
- package/out/renderer/assets/snazzy-light-Dcvd-ZyI.js +4 -0
- package/out/renderer/assets/solarized-dark-BBl5y5sR.js +4 -0
- package/out/renderer/assets/solarized-light-DW9b_AY8.js +4 -0
- package/out/renderer/assets/solidity-CSTQ0FCC.js +7 -0
- package/out/renderer/assets/soy-BHaHgMUy.js +11 -0
- package/out/renderer/assets/sparql-DswowMAp.js +9 -0
- package/out/renderer/assets/splunk-DcGJXIDa.js +7 -0
- package/out/renderer/assets/sql-DzUuSofg.js +7 -0
- package/out/renderer/assets/ssh-config-Bk_I5wDR.js +7 -0
- package/out/renderer/assets/stata-Dl7wDdBE.js +9 -0
- package/out/renderer/assets/{stateDiagram-FHFEXIEX-BK7E-REm.js → stateDiagram-FHFEXIEX-BrH8Q8ZG.js} +8 -8
- package/out/renderer/assets/{stateDiagram-v2-QKLJ7IA2-Cd2wfCQu.js → stateDiagram-v2-QKLJ7IA2-BTWk2K0H.js} +4 -4
- package/out/renderer/assets/stylus-DXFa_2Jl.js +7 -0
- package/out/renderer/assets/surrealql-Bs3vUeKA.js +9 -0
- package/out/renderer/assets/svelte-fC0HkEkx.js +15 -0
- package/out/renderer/assets/swift-Cohr-WZC.js +7 -0
- package/out/renderer/assets/synthwave-84-CoUef9sh.js +4 -0
- package/out/renderer/assets/system-verilog-BcESSvRn.js +7 -0
- package/out/renderer/assets/systemd-DJPFjU02.js +7 -0
- package/out/renderer/assets/talonscript-CEEMXJTH.js +7 -0
- package/out/renderer/assets/tasl-DfOr2qHi.js +7 -0
- package/out/renderer/assets/tcl-CTsc4-t7.js +7 -0
- package/out/renderer/assets/templ-CSEiQwNm.js +13 -0
- package/out/renderer/assets/terraform-CeztUfUr.js +7 -0
- package/out/renderer/assets/tex-CGVqF8nD.js +9 -0
- package/out/renderer/assets/{timeline-definition-GMOUNBTQ-Bl-MTfK5.js → timeline-definition-GMOUNBTQ-DwDUCrTb.js} +2 -2
- package/out/renderer/assets/tokyo-night-DjtLpAEY.js +4 -0
- package/out/renderer/assets/toml-vHPzWDj6.js +7 -0
- package/out/renderer/assets/ts-tags-cG2hZuda.js +54 -0
- package/out/renderer/assets/tsv-ChRVFvMy.js +7 -0
- package/out/renderer/assets/tsx-CmGGo4Hm.js +7 -0
- package/out/renderer/assets/turtle-BnC7StHY.js +7 -0
- package/out/renderer/assets/twig-CwEEYIBf.js +36 -0
- package/out/renderer/assets/typescript-CP6ECzON.js +7 -0
- package/out/renderer/assets/typespec-CkDVVIcK.js +7 -0
- package/out/renderer/assets/typst-XYLFxYau.js +7 -0
- package/out/renderer/assets/v-BSYXvR4g.js +7 -0
- package/out/renderer/assets/vala-qJa5rry9.js +7 -0
- package/out/renderer/assets/vb-Bzg9rspf.js +7 -0
- package/out/renderer/assets/{vennDiagram-DHZGUBPP-DNmr1k2L.js → vennDiagram-DHZGUBPP-Bjvr7yGM.js} +1 -1
- package/out/renderer/assets/verilog-CCb_iTfF.js +7 -0
- package/out/renderer/assets/vesper-4Q1cEwPL.js +4 -0
- package/out/renderer/assets/vhdl-DMqk4T2s.js +7 -0
- package/out/renderer/assets/viml--FINbfoq.js +7 -0
- package/out/renderer/assets/vitesse-black-BqNLki8b.js +4 -0
- package/out/renderer/assets/vitesse-dark-jJ32WhwH.js +4 -0
- package/out/renderer/assets/vitesse-light-476zM4e6.js +4 -0
- package/out/renderer/assets/vue-K-7Ga-y8.js +40 -0
- package/out/renderer/assets/vue-html-DhreShjd.js +9 -0
- package/out/renderer/assets/vue-vine-rMIwOpFf.js +19 -0
- package/out/renderer/assets/vyper-DP4whl13.js +7 -0
- package/out/renderer/assets/{wardley-RL74JXVD-DTbxPMj9.js → wardley-RL74JXVD-Bo-sW7uQ.js} +3 -3
- package/out/renderer/assets/{wardleyDiagram-NUSXRM2D-BWw08wtD.js → wardleyDiagram-NUSXRM2D-DRW_1PCJ.js} +5 -5
- package/out/renderer/assets/wasm-BBh6f151.js +7 -0
- package/out/renderer/assets/wasm-DDgzZJey.js +10 -0
- package/out/renderer/assets/wenyan-BdqozpMZ.js +7 -0
- package/out/renderer/assets/wgsl-Vo-hHVWH.js +7 -0
- package/out/renderer/assets/wikitext-BDjE6pmL.js +7 -0
- package/out/renderer/assets/wit-C_nQzOkY.js +7 -0
- package/out/renderer/assets/wolfram-CRmjUoI4.js +7 -0
- package/out/renderer/assets/xml-BMzZeaqs.js +9 -0
- package/out/renderer/assets/xsl-CnwVr_6q.js +10 -0
- package/out/renderer/assets/{xychartDiagram-5P7HB3ND-EEYPnLDT.js → xychartDiagram-5P7HB3ND-Ds-qS4nC.js} +1 -1
- package/out/renderer/assets/yaml-B_vW5iTY.js +7 -0
- package/out/renderer/assets/zenscript-DFINJL6j.js +7 -0
- package/out/renderer/assets/zig-CS4FMAZp.js +7 -0
- package/out/renderer/index.html +2 -2
- package/out/resources/connector/connector.py +9 -6
- package/out/resources/mcp-server/aider-desk-mcp-server.js +16 -1
- package/out/resources/prompts/code-change-requests.hbs +21 -0
- package/out/resources/skills/extension-creator/SKILL.md +25 -0
- package/out/resources/skills/extension-creator/references/config-components.md +6 -6
- package/out/resources/skills/extension-creator/references/extension-interface.md +66 -0
- package/out/runner.js +1650 -409
- package/package.json +12 -10
- package/patches/@ai-sdk+deepseek+1.0.37.patch +150 -0
- package/out/resources/prompts/code-inline-request.hbs +0 -16
- /package/patches/{ai+5.0.167.patch → ai+5.0.179.patch} +0 -0
package/out/runner.js
CHANGED
|
@@ -31,12 +31,8 @@ const node_sqlite = require("node:sqlite");
|
|
|
31
31
|
const path = require("path");
|
|
32
32
|
const os = require("os");
|
|
33
33
|
const http = require("http");
|
|
34
|
-
const undici = require("undici");
|
|
35
|
-
const uuid = require("uuid");
|
|
36
|
-
const ai = require("ai");
|
|
37
34
|
const gpt4o = require("gpt-tokenizer/model/gpt-4o");
|
|
38
35
|
const istextorbinary = require("istextorbinary");
|
|
39
|
-
const fileType = require("file-type");
|
|
40
36
|
const child_process = require("child_process");
|
|
41
37
|
const treeKill = require("tree-kill");
|
|
42
38
|
const glob = require("glob");
|
|
@@ -51,7 +47,7 @@ const filenamifyImport = require("filenamify");
|
|
|
51
47
|
const slugify = require("slugify");
|
|
52
48
|
const Turndown = require("turndown");
|
|
53
49
|
const cheerio = require("cheerio");
|
|
54
|
-
const
|
|
50
|
+
const uuid = require("uuid");
|
|
55
51
|
const index_js = require("@modelcontextprotocol/sdk/client/index.js");
|
|
56
52
|
const stdio_js = require("@modelcontextprotocol/sdk/client/stdio.js");
|
|
57
53
|
const streamableHttp_js = require("@modelcontextprotocol/sdk/client/streamableHttp.js");
|
|
@@ -62,8 +58,13 @@ const express = require("express");
|
|
|
62
58
|
const cors = require("cors");
|
|
63
59
|
const cloudflared = require("cloudflared");
|
|
64
60
|
const socket_io = require("socket.io");
|
|
61
|
+
const yamlFrontMatter = require("yaml-front-matter");
|
|
65
62
|
const debounce = require("lodash/debounce.js");
|
|
66
63
|
const crypto = require("crypto");
|
|
64
|
+
const undici = require("undici");
|
|
65
|
+
const globalAgent = require("global-agent");
|
|
66
|
+
const ai = require("ai");
|
|
67
|
+
const fileType = require("file-type");
|
|
67
68
|
const anthropic = require("@ai-sdk/anthropic");
|
|
68
69
|
const azure = require("@ai-sdk/azure");
|
|
69
70
|
const clientBedrock = require("@aws-sdk/client-bedrock");
|
|
@@ -78,6 +79,7 @@ const genai = require("@google/genai");
|
|
|
78
79
|
const openaiCompatible = require("@ai-sdk/openai-compatible");
|
|
79
80
|
const groq = require("@ai-sdk/groq");
|
|
80
81
|
const alibaba = require("@ai-sdk/alibaba");
|
|
82
|
+
const mistral = require("@ai-sdk/mistral");
|
|
81
83
|
const ollamaAiProviderV2 = require("ollama-ai-provider-v2");
|
|
82
84
|
const openai = require("@ai-sdk/openai");
|
|
83
85
|
const aiSdkProvider = require("@openrouter/ai-sdk-provider");
|
|
@@ -241,6 +243,7 @@ const WorktreeSchema = zod.z.object({
|
|
|
241
243
|
path: zod.z.string(),
|
|
242
244
|
baseBranch: zod.z.string().optional(),
|
|
243
245
|
baseCommit: zod.z.string().optional(),
|
|
246
|
+
branch: zod.z.string().optional(),
|
|
244
247
|
prunable: zod.z.boolean().optional()
|
|
245
248
|
});
|
|
246
249
|
const MergeStateSchema = zod.z.object({
|
|
@@ -297,7 +300,10 @@ const ProjectSettingsSchema = zod.z.object({
|
|
|
297
300
|
contextCompactingThreshold: zod.z.number().optional(),
|
|
298
301
|
weakModelLocked: zod.z.boolean().optional(),
|
|
299
302
|
autoApproveLocked: zod.z.boolean().optional(),
|
|
300
|
-
updatedFilesGroupMode: zod.z.enum(["grouped", "flat"]).default("flat")
|
|
303
|
+
updatedFilesGroupMode: zod.z.enum(["grouped", "flat"]).default("flat"),
|
|
304
|
+
disabledRuleFiles: zod.z.array(zod.z.string()).default([]),
|
|
305
|
+
contextSidebarSectionsOrder: zod.z.array(zod.z.string()).default([]),
|
|
306
|
+
contextSidebarSectionsHidden: zod.z.array(zod.z.string()).default([])
|
|
301
307
|
});
|
|
302
308
|
var ToolApprovalState = /* @__PURE__ */ ((ToolApprovalState2) => {
|
|
303
309
|
ToolApprovalState2["Always"] = "always";
|
|
@@ -481,19 +487,22 @@ const parseUsageReport = (model, report) => {
|
|
|
481
487
|
};
|
|
482
488
|
const normalizeBaseDir = (baseDir, os2 = process.platform === "win32" ? OS.Windows : process.platform === "darwin" ? OS.MacOS : OS.Linux) => {
|
|
483
489
|
if (os2 === OS.Windows) {
|
|
484
|
-
return baseDir.toLowerCase();
|
|
490
|
+
return baseDir.toLowerCase().replace(/\\+$/, "");
|
|
485
491
|
} else {
|
|
486
492
|
const wslPrefix = "\\\\wsl.localhost\\";
|
|
487
493
|
if (baseDir.startsWith(wslPrefix)) {
|
|
488
494
|
const thirdBackslashIndex = baseDir.indexOf("\\", wslPrefix.length);
|
|
489
495
|
if (thirdBackslashIndex !== -1) {
|
|
490
496
|
const actualPath = baseDir.substring(thirdBackslashIndex + 1);
|
|
491
|
-
return "/" + actualPath.replace(/\\/g, "/");
|
|
497
|
+
return ("/" + actualPath.replace(/\\/g, "/")).replace(/\/+$/, "");
|
|
492
498
|
}
|
|
493
499
|
}
|
|
494
|
-
return baseDir;
|
|
500
|
+
return baseDir.replace(/\/+$/, "");
|
|
495
501
|
}
|
|
496
502
|
};
|
|
503
|
+
const compareBaseDirs$1 = (baseDir1, baseDir2, os2) => {
|
|
504
|
+
return normalizeBaseDir(baseDir1, os2) === normalizeBaseDir(baseDir2, os2);
|
|
505
|
+
};
|
|
497
506
|
const fileExists = async (fileName) => {
|
|
498
507
|
return await fs.stat(fileName).catch(() => null) !== null;
|
|
499
508
|
};
|
|
@@ -810,6 +819,7 @@ const POSTHOG_HOST = "https://eu.i.posthog.com";
|
|
|
810
819
|
process.env.AIDER_DESK_HEADLESS === "true";
|
|
811
820
|
const AUTH_USERNAME = process.env.AIDER_DESK_USERNAME;
|
|
812
821
|
const AUTH_PASSWORD = process.env.AIDER_DESK_PASSWORD;
|
|
822
|
+
const CORS_ALLOWED_ORIGINS = process.env.AIDER_DESK_CORS_ALLOWED_ORIGINS;
|
|
813
823
|
const PROBE_BINARY_PATH = path.join(
|
|
814
824
|
RESOURCES_DIR,
|
|
815
825
|
process.platform === "win32" ? "win" : process.platform === "darwin" ? "macos" : "linux",
|
|
@@ -1432,6 +1442,7 @@ const search = async (options) => {
|
|
|
1432
1442
|
args.push(`${flag} ${String(value)}`);
|
|
1433
1443
|
}
|
|
1434
1444
|
}
|
|
1445
|
+
args.push("--");
|
|
1435
1446
|
args.push(`"${options.query}"`);
|
|
1436
1447
|
if (options.path) {
|
|
1437
1448
|
args.push(`"${options.path}"`);
|
|
@@ -1462,6 +1473,7 @@ const AVAILABLE_PROVIDERS = [
|
|
|
1462
1473
|
"litellm",
|
|
1463
1474
|
"lmstudio",
|
|
1464
1475
|
"minimax",
|
|
1476
|
+
"mistral",
|
|
1465
1477
|
"ollama",
|
|
1466
1478
|
"openai",
|
|
1467
1479
|
"openai-compatible",
|
|
@@ -1506,24 +1518,28 @@ const isRequestyProvider = (provider) => provider.name === "requesty";
|
|
|
1506
1518
|
const isOpenCodeProvider = (provider) => provider.name === "opencode";
|
|
1507
1519
|
const isZaiPlanProvider = (provider) => provider.name === "zai-plan";
|
|
1508
1520
|
const isMinimaxProvider = (provider) => provider.name === "minimax";
|
|
1521
|
+
const isMistralProvider = (provider) => provider.name === "mistral";
|
|
1509
1522
|
const isSyntheticProvider = (provider) => provider.name === "synthetic";
|
|
1510
|
-
const DEFAULT_MODEL_TEMPERATURE = 0;
|
|
1511
1523
|
const DEFAULT_PROVIDER_MODELS = {
|
|
1512
1524
|
"alibaba-plan": "qwen3-coder-plus",
|
|
1513
1525
|
anthropic: "claude-sonnet-4-6",
|
|
1526
|
+
auggie: "gpt-5-4",
|
|
1527
|
+
bedrock: "global.anthropic.claude-sonnet-4-6",
|
|
1514
1528
|
cerebras: "qwen-3-235b-a22b-instruct-2507",
|
|
1515
1529
|
"claude-agent-sdk": "sonnet",
|
|
1516
|
-
deepseek: "deepseek-
|
|
1530
|
+
deepseek: "deepseek-v4-pro",
|
|
1517
1531
|
gemini: "gemini-pro-latest",
|
|
1518
|
-
"gemini-cli": "gemini-2.5-
|
|
1532
|
+
"gemini-cli": "gemini-2.5-pro",
|
|
1519
1533
|
groq: "moonshotai/kimi-k2-instruct-0905",
|
|
1534
|
+
"kimi-plan": "k2p6",
|
|
1520
1535
|
openai: "gpt-5.4",
|
|
1521
1536
|
openrouter: "anthropic/claude-sonnet-4.6",
|
|
1522
1537
|
opencode: "claude-sonnet-4-6",
|
|
1523
1538
|
requesty: "anthropic/claude-sonnet-4-6",
|
|
1524
1539
|
synthetic: "hf:zai-org/GLM-4.7",
|
|
1525
|
-
"zai-plan": "glm-5",
|
|
1526
|
-
minimax: "MiniMax-M2"
|
|
1540
|
+
"zai-plan": "glm-5.1",
|
|
1541
|
+
minimax: "MiniMax-M2.7",
|
|
1542
|
+
mistral: "mistral-large-latest"
|
|
1527
1543
|
};
|
|
1528
1544
|
const DEFAULT_AIDER_MAIN_MODEL = `anthropic/${DEFAULT_PROVIDER_MODELS.anthropic}`;
|
|
1529
1545
|
const DEFAULT_AGENT_PROFILE_ID = "default";
|
|
@@ -1835,7 +1851,8 @@ const getDefaultProviderParams = (providerName) => {
|
|
|
1835
1851
|
case "deepseek":
|
|
1836
1852
|
provider = {
|
|
1837
1853
|
name: "deepseek",
|
|
1838
|
-
apiKey: ""
|
|
1854
|
+
apiKey: "",
|
|
1855
|
+
thinkingEnabled: true
|
|
1839
1856
|
};
|
|
1840
1857
|
break;
|
|
1841
1858
|
case "bedrock":
|
|
@@ -1920,6 +1937,12 @@ const getDefaultProviderParams = (providerName) => {
|
|
|
1920
1937
|
apiKey: ""
|
|
1921
1938
|
};
|
|
1922
1939
|
break;
|
|
1940
|
+
case "mistral":
|
|
1941
|
+
provider = {
|
|
1942
|
+
name: "mistral",
|
|
1943
|
+
apiKey: ""
|
|
1944
|
+
};
|
|
1945
|
+
break;
|
|
1923
1946
|
case "gemini-cli":
|
|
1924
1947
|
provider = {
|
|
1925
1948
|
name: "gemini-cli",
|
|
@@ -2181,7 +2204,8 @@ const readApiKeyFromConfFile = (filePath, envVarName) => {
|
|
|
2181
2204
|
CEREBRAS_API_KEY: ["cerebras"],
|
|
2182
2205
|
OPENCODE_API_KEY: ["opencode"],
|
|
2183
2206
|
REQUESTY_API_KEY: ["requesty"],
|
|
2184
|
-
SYNTHETIC_API_KEY: ["synthetic"]
|
|
2207
|
+
SYNTHETIC_API_KEY: ["synthetic"],
|
|
2208
|
+
MISTRAL_API_KEY: ["mistral"]
|
|
2185
2209
|
};
|
|
2186
2210
|
const providerNames = envVarToProviderName[envVarName] || [envVarName.replace(/_API_KEY$/, "").toLowerCase()];
|
|
2187
2211
|
const apiKeys = Array.isArray(apiKeyValue) ? apiKeyValue : [apiKeyValue];
|
|
@@ -2347,7 +2371,10 @@ const getDefaultProjectSettings = (store, providerModels, baseDir, defaultAgentP
|
|
|
2347
2371
|
currentMode: "agent",
|
|
2348
2372
|
agentProfileId: defaultAgentProfileId,
|
|
2349
2373
|
autoApproveLocked: false,
|
|
2350
|
-
updatedFilesGroupMode: "flat"
|
|
2374
|
+
updatedFilesGroupMode: "flat",
|
|
2375
|
+
disabledRuleFiles: [],
|
|
2376
|
+
contextSidebarSectionsOrder: [],
|
|
2377
|
+
contextSidebarSectionsHidden: []
|
|
2351
2378
|
};
|
|
2352
2379
|
};
|
|
2353
2380
|
const filenamify = filenamifyImport.default;
|
|
@@ -3034,19 +3061,16 @@ const scrapeWeb = async (url, timeout = 6e4, abortSignal, format = "markdown") =
|
|
|
3034
3061
|
const scraper = new WebScraper();
|
|
3035
3062
|
return await scraper.scrape(url, timeout, abortSignal, format);
|
|
3036
3063
|
};
|
|
3037
|
-
const
|
|
3038
|
-
const
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
}
|
|
3048
|
-
});
|
|
3049
|
-
return newLock;
|
|
3064
|
+
const THINKING_RESPONSE_STAR_TAG = "---\n► **THINKING**\n";
|
|
3065
|
+
const ANSWER_RESPONSE_START_TAG = "---\n► **ANSWER**\n";
|
|
3066
|
+
const extractPromptContextFromToolResult = (toolResult) => {
|
|
3067
|
+
if (toolResult && typeof toolResult === "object" && "promptContext" in toolResult) {
|
|
3068
|
+
return toolResult.promptContext;
|
|
3069
|
+
}
|
|
3070
|
+
return void 0;
|
|
3071
|
+
};
|
|
3072
|
+
const findLastUserMessage = (messages) => {
|
|
3073
|
+
return [...messages].reverse().find((msg) => msg.role === MessageRole.User);
|
|
3050
3074
|
};
|
|
3051
3075
|
const expandTilde = (filePath) => {
|
|
3052
3076
|
if (filePath.startsWith("~/") || filePath === "~") {
|
|
@@ -3054,11 +3078,25 @@ const expandTilde = (filePath) => {
|
|
|
3054
3078
|
}
|
|
3055
3079
|
return filePath;
|
|
3056
3080
|
};
|
|
3057
|
-
const readFileContent = async (absolutePath, withLines = false, lineOffset = 0, lineLimit = 1e3) => {
|
|
3081
|
+
const readFileContent = async (absolutePath, withLines = false, lineOffset = 0, lineLimit = 1e3, sizeLimit = 0.05 * lineLimit) => {
|
|
3058
3082
|
const fileContentBuffer = await fs.readFile(absolutePath);
|
|
3059
3083
|
if (istextorbinary.isBinary(absolutePath, fileContentBuffer)) {
|
|
3060
3084
|
throw new Error("Binary files cannot be read.");
|
|
3061
3085
|
}
|
|
3086
|
+
const fileSizeKB = fileContentBuffer.length / 1024;
|
|
3087
|
+
if (fileSizeKB > sizeLimit) {
|
|
3088
|
+
const truncatedBytes = fileContentBuffer.subarray(0, Math.floor(sizeLimit * 1024));
|
|
3089
|
+
const truncatedContent = truncatedBytes.toString("utf8");
|
|
3090
|
+
const truncatedLines = truncatedContent.split("\n");
|
|
3091
|
+
if (withLines) {
|
|
3092
|
+
return truncatedLines.map((line, index) => `${index + 1}|${line}`).join("\n") + `
|
|
3093
|
+
|
|
3094
|
+
File size limit (${sizeLimit.toFixed(1)} KB) exceeded. Use shell commands (e.g., head, tail, grep) to read specific parts.`;
|
|
3095
|
+
}
|
|
3096
|
+
return truncatedContent + `
|
|
3097
|
+
|
|
3098
|
+
File size limit (${sizeLimit.toFixed(1)} KB) exceeded. Use shell commands (e.g., head, tail, grep) to read specific parts.`;
|
|
3099
|
+
}
|
|
3062
3100
|
const fileContent = fileContentBuffer.toString("utf8");
|
|
3063
3101
|
const lines = fileContent.split("\n");
|
|
3064
3102
|
const totalLines = lines.length;
|
|
@@ -3074,6 +3112,42 @@ const readFileContent = async (absolutePath, withLines = false, lineOffset = 0,
|
|
|
3074
3112
|
}
|
|
3075
3113
|
return limitedLines.join("\n");
|
|
3076
3114
|
};
|
|
3115
|
+
const truncateToolResult = async (content, maxLines = 1e3, maxSizeKB = 50) => {
|
|
3116
|
+
const lines = content.split("\n");
|
|
3117
|
+
const sizeBytes = Buffer.byteLength(content, "utf8");
|
|
3118
|
+
const sizeKB = sizeBytes / 1024;
|
|
3119
|
+
if (lines.length <= maxLines && sizeKB <= maxSizeKB) {
|
|
3120
|
+
return content;
|
|
3121
|
+
}
|
|
3122
|
+
const id = Date.now().toString(36) + Math.random().toString(36).substring(2, 8);
|
|
3123
|
+
const tmpFileName = `aider-desk-tool-result-${id}.txt`;
|
|
3124
|
+
const tmpFilePath = path.join(os.tmpdir(), tmpFileName);
|
|
3125
|
+
await fs.writeFile(tmpFilePath, content, "utf8");
|
|
3126
|
+
const previewLines = lines.slice(0, maxLines);
|
|
3127
|
+
const reasons = [];
|
|
3128
|
+
if (lines.length > maxLines) {
|
|
3129
|
+
reasons.push(`${lines.length} lines exceeded limit of ${maxLines}`);
|
|
3130
|
+
}
|
|
3131
|
+
if (sizeKB > maxSizeKB) {
|
|
3132
|
+
reasons.push(`${sizeKB.toFixed(1)} KB exceeded limit of ${maxSizeKB} KB`);
|
|
3133
|
+
}
|
|
3134
|
+
return previewLines.join("\n") + `
|
|
3135
|
+
... Content truncated (${reasons.join(", ")}). Full content saved to ${tmpFilePath}.`;
|
|
3136
|
+
};
|
|
3137
|
+
const fileLocks = /* @__PURE__ */ new Map();
|
|
3138
|
+
const withFileLock = (filePath, operation) => {
|
|
3139
|
+
logger.debug("Acquiring file lock:", { filePath });
|
|
3140
|
+
const currentLock = fileLocks.get(filePath) || Promise.resolve();
|
|
3141
|
+
const newLock = currentLock.then(operation, operation);
|
|
3142
|
+
fileLocks.set(filePath, newLock);
|
|
3143
|
+
newLock.finally(() => {
|
|
3144
|
+
if (fileLocks.get(filePath) === newLock) {
|
|
3145
|
+
logger.debug("Releasing file lock:", { filePath });
|
|
3146
|
+
fileLocks.delete(filePath);
|
|
3147
|
+
}
|
|
3148
|
+
});
|
|
3149
|
+
return newLock;
|
|
3150
|
+
};
|
|
3077
3151
|
const createPowerToolset = (task, profile, promptContext, abortSignal) => {
|
|
3078
3152
|
const approvalManager = new ApprovalManager(task, profile);
|
|
3079
3153
|
const fileEditTool = ai.tool({
|
|
@@ -3392,10 +3466,10 @@ Do not use escape characters \\ in the string like \\n or \\" and others. Do not
|
|
|
3392
3466
|
encoding: "utf8",
|
|
3393
3467
|
signal: abortSignal
|
|
3394
3468
|
});
|
|
3395
|
-
const
|
|
3469
|
+
const lines2 = fileContent.split("\n");
|
|
3396
3470
|
const relativeFilePath = path.relative(task.getTaskDir(), absoluteFilePath);
|
|
3397
|
-
for (let index = 0; index <
|
|
3398
|
-
const line =
|
|
3471
|
+
for (let index = 0; index < lines2.length; index++) {
|
|
3472
|
+
const line = lines2[index];
|
|
3399
3473
|
if (searchRegex.test(line)) {
|
|
3400
3474
|
if (results.length >= maxResults) {
|
|
3401
3475
|
break;
|
|
@@ -3407,8 +3481,8 @@ Do not use escape characters \\ in the string like \\n or \\" and others. Do not
|
|
|
3407
3481
|
};
|
|
3408
3482
|
if (contextLines > 0) {
|
|
3409
3483
|
const start = Math.max(0, index - contextLines);
|
|
3410
|
-
const end = Math.min(
|
|
3411
|
-
matchResult.context =
|
|
3484
|
+
const end = Math.min(lines2.length - 1, index + contextLines);
|
|
3485
|
+
matchResult.context = lines2.slice(start, end + 1);
|
|
3412
3486
|
}
|
|
3413
3487
|
results.push(matchResult);
|
|
3414
3488
|
}
|
|
@@ -3417,7 +3491,40 @@ Do not use escape characters \\ in the string like \\n or \\" and others. Do not
|
|
|
3417
3491
|
if (results.length === 0) {
|
|
3418
3492
|
return `No matches found for pattern '${searchTerm}' in files matching '${filePattern}'.`;
|
|
3419
3493
|
}
|
|
3420
|
-
|
|
3494
|
+
const grouped = {};
|
|
3495
|
+
for (const r of results) {
|
|
3496
|
+
if (!grouped[r.filePath]) {
|
|
3497
|
+
grouped[r.filePath] = [];
|
|
3498
|
+
}
|
|
3499
|
+
grouped[r.filePath].push(r);
|
|
3500
|
+
}
|
|
3501
|
+
const lines = [];
|
|
3502
|
+
lines.push(`## Grep Results: \`${searchTerm}\` in \`${filePattern}\` (${results.length} matches)`);
|
|
3503
|
+
lines.push("");
|
|
3504
|
+
for (const [filePath, matches] of Object.entries(grouped)) {
|
|
3505
|
+
lines.push(`### ${filePath} (${matches.length} ${matches.length === 1 ? "match" : "matches"})`);
|
|
3506
|
+
for (const match of matches) {
|
|
3507
|
+
const escapedContent = match.lineContent.replace(/`/g, "\\`");
|
|
3508
|
+
lines.push(`- **L${match.lineNumber}:** \`${escapedContent}\``);
|
|
3509
|
+
if (match.context && match.context.length > 0) {
|
|
3510
|
+
lines.push(" ```");
|
|
3511
|
+
for (const ctxLine of match.context) {
|
|
3512
|
+
lines.push(` ${ctxLine}`);
|
|
3513
|
+
}
|
|
3514
|
+
lines.push(" ```");
|
|
3515
|
+
}
|
|
3516
|
+
}
|
|
3517
|
+
lines.push("");
|
|
3518
|
+
}
|
|
3519
|
+
const notices = [];
|
|
3520
|
+
if (results.length >= maxResults) {
|
|
3521
|
+
notices.push(`${maxResults} matches limit reached. Use maxResults=${maxResults * 2} for more, or refine pattern`);
|
|
3522
|
+
}
|
|
3523
|
+
if (notices.length > 0) {
|
|
3524
|
+
lines.push("---");
|
|
3525
|
+
lines.push(`[${notices.join(". ")}]`);
|
|
3526
|
+
}
|
|
3527
|
+
return lines.join("\n");
|
|
3421
3528
|
} catch (error) {
|
|
3422
3529
|
if (isAbortError(error)) {
|
|
3423
3530
|
return "Operation was cancelled by user.";
|
|
@@ -3491,24 +3598,26 @@ Timeout: ${timeout}ms`;
|
|
|
3491
3598
|
abortSignal?.removeEventListener("abort", abortListener);
|
|
3492
3599
|
}
|
|
3493
3600
|
};
|
|
3494
|
-
const resolveWithResult = () => {
|
|
3601
|
+
const resolveWithResult = async () => {
|
|
3495
3602
|
if (isResolved) {
|
|
3496
3603
|
return;
|
|
3497
3604
|
}
|
|
3498
3605
|
isResolved = true;
|
|
3499
3606
|
cleanup();
|
|
3500
|
-
|
|
3607
|
+
const truncatedStdout = await truncateToolResult(stdout);
|
|
3608
|
+
const truncatedStderr = await truncateToolResult(stderr);
|
|
3609
|
+
resolve({ stdout: truncatedStdout, stderr: truncatedStderr, exitCode });
|
|
3501
3610
|
};
|
|
3502
3611
|
abortListener = () => {
|
|
3503
3612
|
if (isResolved) {
|
|
3504
3613
|
return;
|
|
3505
3614
|
}
|
|
3506
3615
|
if (childProcess?.pid) {
|
|
3507
|
-
treeKill(childProcess.pid, "
|
|
3616
|
+
treeKill(childProcess.pid, "SIGKILL");
|
|
3508
3617
|
}
|
|
3509
3618
|
stderr = "Operation was cancelled by user.";
|
|
3510
3619
|
exitCode = 130;
|
|
3511
|
-
resolveWithResult();
|
|
3620
|
+
void resolveWithResult();
|
|
3512
3621
|
};
|
|
3513
3622
|
abortSignal?.addEventListener("abort", abortListener);
|
|
3514
3623
|
try {
|
|
@@ -3525,13 +3634,16 @@ Timeout: ${timeout}ms`;
|
|
|
3525
3634
|
return;
|
|
3526
3635
|
}
|
|
3527
3636
|
if (childProcess?.pid) {
|
|
3528
|
-
treeKill(childProcess.pid, "
|
|
3637
|
+
treeKill(childProcess.pid, "SIGKILL");
|
|
3529
3638
|
}
|
|
3530
3639
|
stderr = `Error: Command timed out after ${timeout}ms. Consider increasing the timeout parameter.`;
|
|
3531
3640
|
exitCode = 124;
|
|
3532
|
-
resolveWithResult();
|
|
3641
|
+
void resolveWithResult();
|
|
3533
3642
|
}, timeout);
|
|
3534
3643
|
childProcess.stdout?.on("data", (data) => {
|
|
3644
|
+
if (isResolved) {
|
|
3645
|
+
return;
|
|
3646
|
+
}
|
|
3535
3647
|
const chunk = data.toString("utf-8");
|
|
3536
3648
|
stdout += chunk;
|
|
3537
3649
|
task.addToolMessage(
|
|
@@ -3548,6 +3660,9 @@ Timeout: ${timeout}ms`;
|
|
|
3548
3660
|
);
|
|
3549
3661
|
});
|
|
3550
3662
|
childProcess.stderr?.on("data", (data) => {
|
|
3663
|
+
if (isResolved) {
|
|
3664
|
+
return;
|
|
3665
|
+
}
|
|
3551
3666
|
const chunk = data.toString("utf-8");
|
|
3552
3667
|
stderr += chunk;
|
|
3553
3668
|
task.addToolMessage(
|
|
@@ -3567,7 +3682,7 @@ Timeout: ${timeout}ms`;
|
|
|
3567
3682
|
if (!isResolved) {
|
|
3568
3683
|
stderr = error.message;
|
|
3569
3684
|
exitCode = 1;
|
|
3570
|
-
resolveWithResult();
|
|
3685
|
+
void resolveWithResult();
|
|
3571
3686
|
}
|
|
3572
3687
|
});
|
|
3573
3688
|
childProcess.on("exit", (code, signal) => {
|
|
@@ -3579,14 +3694,14 @@ Timeout: ${timeout}ms`;
|
|
|
3579
3694
|
} else {
|
|
3580
3695
|
exitCode = 1;
|
|
3581
3696
|
}
|
|
3582
|
-
resolveWithResult();
|
|
3697
|
+
void resolveWithResult();
|
|
3583
3698
|
}
|
|
3584
3699
|
});
|
|
3585
3700
|
} catch (error) {
|
|
3586
3701
|
if (!isResolved) {
|
|
3587
3702
|
stderr = error instanceof Error ? error.message : String(error);
|
|
3588
3703
|
exitCode = 1;
|
|
3589
|
-
resolveWithResult();
|
|
3704
|
+
void resolveWithResult();
|
|
3590
3705
|
}
|
|
3591
3706
|
}
|
|
3592
3707
|
});
|
|
@@ -4059,7 +4174,8 @@ Parent Task ID: ${parentTaskId || "none (top-level task)"}` : ""}`;
|
|
|
4059
4174
|
const newTask = await task.getProject().createNewTask({
|
|
4060
4175
|
parentId: parentTaskId || null,
|
|
4061
4176
|
name: name || "",
|
|
4062
|
-
autoApprove
|
|
4177
|
+
autoApprove,
|
|
4178
|
+
workingMode: worktree ? "worktree" : "local"
|
|
4063
4179
|
});
|
|
4064
4180
|
const updates = {};
|
|
4065
4181
|
if (agentProfileId) {
|
|
@@ -4071,9 +4187,6 @@ Parent Task ID: ${parentTaskId || "none (top-level task)"}` : ""}`;
|
|
|
4071
4187
|
updates.model = modelParts.join("/");
|
|
4072
4188
|
updates.mainModel = modelId;
|
|
4073
4189
|
}
|
|
4074
|
-
if (worktree) {
|
|
4075
|
-
updates.workingMode = "worktree";
|
|
4076
|
-
}
|
|
4077
4190
|
const taskInstance = task.getProject().getTask(newTask.id);
|
|
4078
4191
|
if (!taskInstance) {
|
|
4079
4192
|
throw new Error(`Failed to get task instance for newly created task ${newTask.id}`);
|
|
@@ -4685,64 +4798,6 @@ New content: "${content}"`;
|
|
|
4685
4798
|
}
|
|
4686
4799
|
return filteredTools;
|
|
4687
4800
|
};
|
|
4688
|
-
const SKILLS_DIR_NAME = "skills";
|
|
4689
|
-
const SKILL_MARKDOWN_FILE = "SKILL.md";
|
|
4690
|
-
const parseSkillFrontMatter = (markdown) => {
|
|
4691
|
-
const parsed = yamlFrontMatter.loadFront(markdown);
|
|
4692
|
-
const name = typeof parsed.name === "string" ? parsed.name : void 0;
|
|
4693
|
-
const description = typeof parsed.description === "string" ? parsed.description : void 0;
|
|
4694
|
-
if (!name || !description) {
|
|
4695
|
-
return null;
|
|
4696
|
-
}
|
|
4697
|
-
return { name, description };
|
|
4698
|
-
};
|
|
4699
|
-
const safeReadDir = async (dirPath) => {
|
|
4700
|
-
try {
|
|
4701
|
-
return await fs.readdir(dirPath);
|
|
4702
|
-
} catch {
|
|
4703
|
-
return [];
|
|
4704
|
-
}
|
|
4705
|
-
};
|
|
4706
|
-
const safeStat = async (filePath) => {
|
|
4707
|
-
try {
|
|
4708
|
-
return await fs.stat(filePath);
|
|
4709
|
-
} catch {
|
|
4710
|
-
return null;
|
|
4711
|
-
}
|
|
4712
|
-
};
|
|
4713
|
-
const loadSkillsFromDir = async (skillsRootDir, location) => {
|
|
4714
|
-
const entries = await safeReadDir(skillsRootDir);
|
|
4715
|
-
const skills = [];
|
|
4716
|
-
for (const entry of entries) {
|
|
4717
|
-
const dirPath = path.join(skillsRootDir, entry);
|
|
4718
|
-
const stat = await safeStat(dirPath);
|
|
4719
|
-
if (!stat?.isDirectory()) {
|
|
4720
|
-
continue;
|
|
4721
|
-
}
|
|
4722
|
-
const skillMdPath = path.join(dirPath, SKILL_MARKDOWN_FILE);
|
|
4723
|
-
const skillMdStat = await safeStat(skillMdPath);
|
|
4724
|
-
if (!skillMdStat?.isFile()) {
|
|
4725
|
-
continue;
|
|
4726
|
-
}
|
|
4727
|
-
let markdown;
|
|
4728
|
-
try {
|
|
4729
|
-
markdown = await fs.readFile(skillMdPath, "utf8");
|
|
4730
|
-
} catch {
|
|
4731
|
-
continue;
|
|
4732
|
-
}
|
|
4733
|
-
const parsed = parseSkillFrontMatter(markdown);
|
|
4734
|
-
if (!parsed) {
|
|
4735
|
-
continue;
|
|
4736
|
-
}
|
|
4737
|
-
skills.push({
|
|
4738
|
-
name: parsed.name,
|
|
4739
|
-
description: parsed.description,
|
|
4740
|
-
location,
|
|
4741
|
-
dirPath
|
|
4742
|
-
});
|
|
4743
|
-
}
|
|
4744
|
-
return skills;
|
|
4745
|
-
};
|
|
4746
4801
|
const getActivateSkillDescription = (skills) => {
|
|
4747
4802
|
const instructions = 'Execute a skill within the main conversation\n\n<skills_instructions>\nWhen users ask you to perform tasks, check if any of the available skills below can help complete the task more effectively. Skills provide specialized capabilities and domain knowledge.\n\nHow to invoke:\n- Use this tool with the skill name only (no arguments)\n- Example: {"skill": "pdf"}\n\nImportant:\n- When a skill is relevant, you must invoke this tool IMMEDIATELY as your first action\n- NEVER just announce or mention a skill in your text response without actually calling this tool\n- Only use skills listed in <available_skills> below\n- Do not invoke a skill that is already running\n</skills_instructions>';
|
|
4748
4803
|
const availableSkills = skills.map((skill) => {
|
|
@@ -4766,15 +4821,10 @@ ${availableSkills}
|
|
|
4766
4821
|
};
|
|
4767
4822
|
const createSkillsToolset = async (task, profile, promptContext) => {
|
|
4768
4823
|
const approvalManager = new ApprovalManager(task, profile);
|
|
4824
|
+
const skillManager = task.getSkillManager();
|
|
4769
4825
|
const generateActivateSkillDescription = async () => {
|
|
4770
|
-
const
|
|
4771
|
-
|
|
4772
|
-
const [globalSkills, projectSkills, builtinSkills] = await Promise.all([
|
|
4773
|
-
loadSkillsFromDir(globalSkillsDir, "global"),
|
|
4774
|
-
loadSkillsFromDir(projectSkillsDir, "project"),
|
|
4775
|
-
loadSkillsFromDir(AIDER_DESK_BUILTIN_SKILLS_DIR, "builtin")
|
|
4776
|
-
]);
|
|
4777
|
-
return getActivateSkillDescription([...projectSkills, ...globalSkills, ...builtinSkills]);
|
|
4826
|
+
const skills = await skillManager.loadAllSkills();
|
|
4827
|
+
return getActivateSkillDescription(skills);
|
|
4778
4828
|
};
|
|
4779
4829
|
const activateSkillTool = ai.tool({
|
|
4780
4830
|
description: await generateActivateSkillDescription(),
|
|
@@ -4792,30 +4842,21 @@ const createSkillsToolset = async (task, profile, promptContext) => {
|
|
|
4792
4842
|
if (!isApproved) {
|
|
4793
4843
|
return `Activating skill denied by user. Reason: ${userInput}`;
|
|
4794
4844
|
}
|
|
4795
|
-
const
|
|
4796
|
-
const projectSkillsDir = path.join(task.getProjectDir(), AIDER_DESK_DIR, SKILLS_DIR_NAME);
|
|
4797
|
-
const [globalSkills, projectSkills, builtinSkills] = await Promise.all([
|
|
4798
|
-
loadSkillsFromDir(globalSkillsDir, "global"),
|
|
4799
|
-
loadSkillsFromDir(projectSkillsDir, "project"),
|
|
4800
|
-
loadSkillsFromDir(AIDER_DESK_BUILTIN_SKILLS_DIR, "builtin")
|
|
4801
|
-
]);
|
|
4802
|
-
const allSkills = [...projectSkills, ...globalSkills, ...builtinSkills];
|
|
4845
|
+
const allSkills = await skillManager.loadAllSkills();
|
|
4803
4846
|
const requested = allSkills.find((s) => s.name === skill);
|
|
4804
4847
|
if (!requested) {
|
|
4805
4848
|
const available = allSkills.map((s) => s.name).join(", ");
|
|
4806
4849
|
return `Skill '${skill}' not found. Available skills: ${available || "(none)"}.`;
|
|
4807
4850
|
}
|
|
4808
|
-
const
|
|
4809
|
-
|
|
4810
|
-
|
|
4811
|
-
content = await fs.readFile(skillMdPath, "utf8");
|
|
4812
|
-
} catch {
|
|
4813
|
-
return `Failed to read skill content from ${skillMdPath}.`;
|
|
4851
|
+
const content = await skillManager.getSkillContent(skill);
|
|
4852
|
+
if (!content) {
|
|
4853
|
+
return `Skill '${requested.name}' has no content or dirPath.`;
|
|
4814
4854
|
}
|
|
4855
|
+
const dirInfo = requested.dirPath ? `
|
|
4856
|
+
Skill directory is ${requested.dirPath} - use it as parent directory for relative paths mentioned in the skill description.` : "";
|
|
4815
4857
|
return `${content}
|
|
4816
4858
|
|
|
4817
|
-
Skill '${requested.name}' activated
|
|
4818
|
-
Skill directory is ${requested.dirPath} - use it as parent directory for relative paths mentioned in the skill description.`;
|
|
4859
|
+
Skill '${requested.name}' activated.${dirInfo}`;
|
|
4819
4860
|
}
|
|
4820
4861
|
});
|
|
4821
4862
|
const allTools = {
|
|
@@ -5252,17 +5293,6 @@ class McpManager {
|
|
|
5252
5293
|
}
|
|
5253
5294
|
}
|
|
5254
5295
|
}
|
|
5255
|
-
const THINKING_RESPONSE_STAR_TAG = "---\n► **THINKING**\n";
|
|
5256
|
-
const ANSWER_RESPONSE_START_TAG = "---\n► **ANSWER**\n";
|
|
5257
|
-
const extractPromptContextFromToolResult = (toolResult) => {
|
|
5258
|
-
if (toolResult && typeof toolResult === "object" && "promptContext" in toolResult) {
|
|
5259
|
-
return toolResult.promptContext;
|
|
5260
|
-
}
|
|
5261
|
-
return void 0;
|
|
5262
|
-
};
|
|
5263
|
-
const findLastUserMessage = (messages) => {
|
|
5264
|
-
return [...messages].reverse().find((msg) => msg.role === MessageRole.User);
|
|
5265
|
-
};
|
|
5266
5296
|
const extractReasoningMiddleware = function extractReasoningMiddleware2({
|
|
5267
5297
|
tagName,
|
|
5268
5298
|
separator = "\n"
|
|
@@ -5905,16 +5935,6 @@ const removeDuplicateToolCalls = (messages) => {
|
|
|
5905
5935
|
}
|
|
5906
5936
|
return newMessages;
|
|
5907
5937
|
};
|
|
5908
|
-
undici.setGlobalDispatcher(
|
|
5909
|
-
new undici.Agent({
|
|
5910
|
-
headersTimeout: 30 * 60 * 1e3,
|
|
5911
|
-
// 30 minutes
|
|
5912
|
-
bodyTimeout: 30 * 60 * 1e3,
|
|
5913
|
-
// 30 minutes
|
|
5914
|
-
connectTimeout: 30 * 1e3
|
|
5915
|
-
// 30 seconds
|
|
5916
|
-
})
|
|
5917
|
-
);
|
|
5918
5938
|
const MAX_RETRIES = 3;
|
|
5919
5939
|
class Agent {
|
|
5920
5940
|
constructor(store, agentProfileManager, mcpManager, modelManager, telemetryManager, memoryManager, promptsManager, extensionManager) {
|
|
@@ -6242,6 +6262,9 @@ ${fileList}`
|
|
|
6242
6262
|
options.abortSignal = abortSignal;
|
|
6243
6263
|
}
|
|
6244
6264
|
const result = await toolDef.execute(effectiveInput, options);
|
|
6265
|
+
if (options.abortSignal?.aborted) {
|
|
6266
|
+
return result;
|
|
6267
|
+
}
|
|
6245
6268
|
const toolFinishedExtensionResult = await this.extensionManager.dispatchEvent(
|
|
6246
6269
|
"onToolFinished",
|
|
6247
6270
|
{ toolName, input: effectiveInput, output: result },
|
|
@@ -6291,6 +6314,14 @@ ${fileList}`
|
|
|
6291
6314
|
}
|
|
6292
6315
|
);
|
|
6293
6316
|
logger.debug(`Tool ${toolDef.name} returned response`, { response });
|
|
6317
|
+
if (response && typeof response === "object" && "content" in response && Array.isArray(response.content)) {
|
|
6318
|
+
for (let i = 0; i < response.content.length; i++) {
|
|
6319
|
+
const part = response.content[i];
|
|
6320
|
+
if (part && typeof part === "object" && part.type === "text" && typeof part.text === "string") {
|
|
6321
|
+
part.text = await truncateToolResult(part.text);
|
|
6322
|
+
}
|
|
6323
|
+
}
|
|
6324
|
+
}
|
|
6294
6325
|
this.lastToolCallTime = Date.now();
|
|
6295
6326
|
return response;
|
|
6296
6327
|
} catch (error) {
|
|
@@ -6471,7 +6502,7 @@ ${fileList}`
|
|
|
6471
6502
|
this.abortControllers.set(controllerId, newController);
|
|
6472
6503
|
}
|
|
6473
6504
|
const effectiveAbortSignal = abortSignal || (controllerId ? this.abortControllers.get(controllerId)?.signal : void 0);
|
|
6474
|
-
const cacheControl = this.modelManager.getCacheControl(
|
|
6505
|
+
const cacheControl = this.modelManager.getCacheControl(provider, modelName);
|
|
6475
6506
|
const providerOptions = this.modelManager.getProviderOptions(provider, modelName);
|
|
6476
6507
|
const providerParameters = this.modelManager.getProviderParameters(provider, modelName);
|
|
6477
6508
|
const firstUserMessage = contextMessages.length > 0 ? contextMessages[0] : null;
|
|
@@ -6727,6 +6758,9 @@ ${fileList}`
|
|
|
6727
6758
|
responseMessageIndex = 0;
|
|
6728
6759
|
hasReasoning = false;
|
|
6729
6760
|
streamingMessageIds.clear();
|
|
6761
|
+
if (responseMessages.length > 0) {
|
|
6762
|
+
retryCount = 0;
|
|
6763
|
+
}
|
|
6730
6764
|
};
|
|
6731
6765
|
const extensionStepStartedResult = await this.extensionManager.dispatchEvent(
|
|
6732
6766
|
"onAgentStepStarted",
|
|
@@ -7171,6 +7205,7 @@ ${fileList}`
|
|
|
7171
7205
|
}
|
|
7172
7206
|
const settings = this.store.getSettings();
|
|
7173
7207
|
const model = await this.modelManager.createLlm(provider, modelName, settings, projectDir, void 0, systemPrompt, void 0);
|
|
7208
|
+
const cacheControl = this.modelManager.getCacheControl(provider, modelName);
|
|
7174
7209
|
const providerOptions = this.modelManager.getProviderOptions(provider, modelName);
|
|
7175
7210
|
const providerParameters = this.modelManager.getProviderParameters(provider, modelName);
|
|
7176
7211
|
const controllerId = uuid.v4();
|
|
@@ -7195,7 +7230,7 @@ ${fileList}`
|
|
|
7195
7230
|
const result = await ai.generateText({
|
|
7196
7231
|
model,
|
|
7197
7232
|
system: systemPrompt,
|
|
7198
|
-
messages: await optimizeMessages(messages),
|
|
7233
|
+
messages: await optimizeMessages(messages, cacheControl),
|
|
7199
7234
|
abortSignal: effectiveAbortSignal,
|
|
7200
7235
|
providerOptions,
|
|
7201
7236
|
...providerParameters
|
|
@@ -7226,7 +7261,7 @@ ${fileList}`
|
|
|
7226
7261
|
const messages = await this.prepareMessages(task, profile, await task.getContextMessages(), await task.getContextFiles());
|
|
7227
7262
|
const toolSet = await this.getAvailableTools(task, "agent", profile, provider, profile.model);
|
|
7228
7263
|
const systemPrompt = await this.promptsManager.getSystemPrompt(this.store.getSettings(), task, profile);
|
|
7229
|
-
const cacheControl = this.modelManager.getCacheControl(
|
|
7264
|
+
const cacheControl = this.modelManager.getCacheControl(provider, profile.model);
|
|
7230
7265
|
const lastUserIndex = messages.map((m) => m.role).lastIndexOf("user");
|
|
7231
7266
|
const userRequestMessageIndex = lastUserIndex >= 0 ? lastUserIndex : 0;
|
|
7232
7267
|
const optimizedMessages = await optimizeMessages(
|
|
@@ -8460,9 +8495,10 @@ const UpdateOpenProjectsOrderSchema = zod.z.object({
|
|
|
8460
8495
|
const LoadInputHistorySchema = zod.z.object({
|
|
8461
8496
|
projectDir: zod.z.string().min(1, "Project directory is required")
|
|
8462
8497
|
});
|
|
8463
|
-
const
|
|
8498
|
+
const RedoUserPromptSchema = zod.z.object({
|
|
8464
8499
|
projectDir: zod.z.string().min(1, "Project directory is required"),
|
|
8465
8500
|
taskId: zod.z.string().min(1, "Task id is required"),
|
|
8501
|
+
messageId: zod.z.string().min(1, "Message id is required"),
|
|
8466
8502
|
mode: zod.z.string().min(1, "Mode is required"),
|
|
8467
8503
|
updatedPrompt: zod.z.string().optional()
|
|
8468
8504
|
});
|
|
@@ -8571,12 +8607,15 @@ const HandoffConversationSchema = zod.z.object({
|
|
|
8571
8607
|
taskId: zod.z.string().min(1, "Task id is required"),
|
|
8572
8608
|
focus: zod.z.string().optional()
|
|
8573
8609
|
});
|
|
8574
|
-
const
|
|
8575
|
-
projectDir: zod.z.string().min(1, "Project directory is required"),
|
|
8576
|
-
taskId: zod.z.string().min(1, "Task id is required"),
|
|
8610
|
+
const ChangeRequestItemSchema = zod.z.object({
|
|
8577
8611
|
filename: zod.z.string().min(1, "Filename is required"),
|
|
8578
8612
|
lineNumber: zod.z.number().int().min(1, "Line number is required"),
|
|
8579
|
-
userComment: zod.z.string().min(1, "User comment is required")
|
|
8613
|
+
userComment: zod.z.string().min(1, "User comment is required")
|
|
8614
|
+
});
|
|
8615
|
+
const RunCodeChangeRequestsSchema = zod.z.object({
|
|
8616
|
+
projectDir: zod.z.string().min(1, "Project directory is required"),
|
|
8617
|
+
taskId: zod.z.string().min(1, "Task id is required"),
|
|
8618
|
+
requests: zod.z.array(ChangeRequestItemSchema).min(1, "At least one request is required"),
|
|
8580
8619
|
createNewTask: zod.z.boolean().optional()
|
|
8581
8620
|
});
|
|
8582
8621
|
const ScrapeWebSchema = zod.z.object({
|
|
@@ -8592,6 +8631,11 @@ const MergeWorktreeToMainSchema = zod.z.object({
|
|
|
8592
8631
|
targetBranch: zod.z.string().optional(),
|
|
8593
8632
|
commitMessage: zod.z.string().optional()
|
|
8594
8633
|
});
|
|
8634
|
+
const MergeAndSwitchToLocalSchema = zod.z.object({
|
|
8635
|
+
projectDir: zod.z.string().min(1, "Project directory is required"),
|
|
8636
|
+
taskId: zod.z.string().min(1, "Task id is required"),
|
|
8637
|
+
targetBranch: zod.z.string().optional()
|
|
8638
|
+
});
|
|
8595
8639
|
const ApplyUncommittedChangesSchema = zod.z.object({
|
|
8596
8640
|
projectDir: zod.z.string().min(1, "Project directory is required"),
|
|
8597
8641
|
taskId: zod.z.string().min(1, "Task id is required"),
|
|
@@ -8608,6 +8652,7 @@ const RestoreFileSchema = zod.z.object({
|
|
|
8608
8652
|
});
|
|
8609
8653
|
const ReadFileSchema = zod.z.object({
|
|
8610
8654
|
projectDir: zod.z.string().min(1, "Project directory is required"),
|
|
8655
|
+
taskId: zod.z.string().min(1, "Task id is required"),
|
|
8611
8656
|
filePath: zod.z.string().min(1, "File path is required")
|
|
8612
8657
|
});
|
|
8613
8658
|
const GenerateCommitMessageSchema = zod.z.object({
|
|
@@ -8645,6 +8690,11 @@ const ResolveWorktreeConflictsWithAgentSchema = zod.z.object({
|
|
|
8645
8690
|
projectDir: zod.z.string().min(1, "Project directory is required"),
|
|
8646
8691
|
taskId: zod.z.string().min(1, "Task id is required")
|
|
8647
8692
|
});
|
|
8693
|
+
const RenameWorktreeBranchSchema = zod.z.object({
|
|
8694
|
+
projectDir: zod.z.string().min(1, "Project directory is required"),
|
|
8695
|
+
taskId: zod.z.string().min(1, "Task id is required"),
|
|
8696
|
+
newBranchName: zod.z.string().min(1, "New branch name is required")
|
|
8697
|
+
});
|
|
8648
8698
|
class ProjectApi extends BaseApi {
|
|
8649
8699
|
constructor(eventsHandler) {
|
|
8650
8700
|
super();
|
|
@@ -8673,13 +8723,13 @@ class ProjectApi extends BaseApi {
|
|
|
8673
8723
|
router.post(
|
|
8674
8724
|
"/project/redo-prompt",
|
|
8675
8725
|
this.handleRequest(async (req, res) => {
|
|
8676
|
-
const parsed = this.validateRequest(
|
|
8726
|
+
const parsed = this.validateRequest(RedoUserPromptSchema, req.body, res);
|
|
8677
8727
|
if (!parsed) {
|
|
8678
8728
|
return;
|
|
8679
8729
|
}
|
|
8680
|
-
const { projectDir, taskId, mode, updatedPrompt } = parsed;
|
|
8681
|
-
await this.eventsHandler.
|
|
8682
|
-
res.status(200).json({ message: "Redo
|
|
8730
|
+
const { projectDir, taskId, messageId, mode, updatedPrompt } = parsed;
|
|
8731
|
+
await this.eventsHandler.redoUserPrompt(projectDir, taskId, messageId, mode, updatedPrompt);
|
|
8732
|
+
res.status(200).json({ message: "Redo user prompt initiated" });
|
|
8683
8733
|
})
|
|
8684
8734
|
);
|
|
8685
8735
|
router.post(
|
|
@@ -8976,15 +9026,15 @@ class ProjectApi extends BaseApi {
|
|
|
8976
9026
|
})
|
|
8977
9027
|
);
|
|
8978
9028
|
router.post(
|
|
8979
|
-
"/project/run-code-
|
|
9029
|
+
"/project/run-code-change-requests",
|
|
8980
9030
|
this.handleRequest(async (req, res) => {
|
|
8981
|
-
const parsed = this.validateRequest(
|
|
9031
|
+
const parsed = this.validateRequest(RunCodeChangeRequestsSchema, req.body, res);
|
|
8982
9032
|
if (!parsed) {
|
|
8983
9033
|
return;
|
|
8984
9034
|
}
|
|
8985
|
-
const { projectDir, taskId,
|
|
8986
|
-
await this.eventsHandler.
|
|
8987
|
-
res.status(200).json({ message: "Code
|
|
9035
|
+
const { projectDir, taskId, requests, createNewTask } = parsed;
|
|
9036
|
+
await this.eventsHandler.runCodeChangeRequests(projectDir, taskId, requests, createNewTask);
|
|
9037
|
+
res.status(200).json({ message: "Code change requests initiated" });
|
|
8988
9038
|
})
|
|
8989
9039
|
);
|
|
8990
9040
|
router.post(
|
|
@@ -9011,6 +9061,18 @@ class ProjectApi extends BaseApi {
|
|
|
9011
9061
|
res.status(200).json({ message: "Worktree merged" });
|
|
9012
9062
|
})
|
|
9013
9063
|
);
|
|
9064
|
+
router.post(
|
|
9065
|
+
"/project/worktree/merge-and-switch-to-local",
|
|
9066
|
+
this.handleRequest(async (req, res) => {
|
|
9067
|
+
const parsed = this.validateRequest(MergeAndSwitchToLocalSchema, req.body, res);
|
|
9068
|
+
if (!parsed) {
|
|
9069
|
+
return;
|
|
9070
|
+
}
|
|
9071
|
+
const { projectDir, taskId, targetBranch } = parsed;
|
|
9072
|
+
await this.eventsHandler.mergeAndSwitchToLocal(projectDir, taskId, targetBranch);
|
|
9073
|
+
res.status(200).json({ message: "Worktree merged and switched to local" });
|
|
9074
|
+
})
|
|
9075
|
+
);
|
|
9014
9076
|
router.post(
|
|
9015
9077
|
"/project/worktree/apply-uncommitted",
|
|
9016
9078
|
this.handleRequest(async (req, res) => {
|
|
@@ -9054,8 +9116,8 @@ class ProjectApi extends BaseApi {
|
|
|
9054
9116
|
if (!parsed) {
|
|
9055
9117
|
return;
|
|
9056
9118
|
}
|
|
9057
|
-
const { projectDir, filePath } = parsed;
|
|
9058
|
-
const content = await this.eventsHandler.readFile(projectDir, filePath);
|
|
9119
|
+
const { projectDir, taskId, filePath } = parsed;
|
|
9120
|
+
const content = await this.eventsHandler.readFile(projectDir, taskId, filePath);
|
|
9059
9121
|
res.status(200).json({ content });
|
|
9060
9122
|
})
|
|
9061
9123
|
);
|
|
@@ -9155,6 +9217,18 @@ class ProjectApi extends BaseApi {
|
|
|
9155
9217
|
res.status(200).json({ message: "Conflicts resolved" });
|
|
9156
9218
|
})
|
|
9157
9219
|
);
|
|
9220
|
+
router.post(
|
|
9221
|
+
"/project/worktree/rename-branch",
|
|
9222
|
+
this.handleRequest(async (req, res) => {
|
|
9223
|
+
const parsed = this.validateRequest(RenameWorktreeBranchSchema, req.body, res);
|
|
9224
|
+
if (!parsed) {
|
|
9225
|
+
return;
|
|
9226
|
+
}
|
|
9227
|
+
const { projectDir, taskId, newBranchName } = parsed;
|
|
9228
|
+
await this.eventsHandler.renameWorktreeBranch(projectDir, taskId, newBranchName);
|
|
9229
|
+
res.status(200).json({ message: "Branch renamed" });
|
|
9230
|
+
})
|
|
9231
|
+
);
|
|
9158
9232
|
router.post(
|
|
9159
9233
|
"/project/update-order",
|
|
9160
9234
|
this.handleRequest(async (req, res) => {
|
|
@@ -9488,9 +9562,10 @@ const GetSystemLogsSchema = zod.z.object({
|
|
|
9488
9562
|
levels: zod.z.array(zod.z.string()).optional()
|
|
9489
9563
|
});
|
|
9490
9564
|
class SystemApi extends BaseApi {
|
|
9491
|
-
constructor(eventsHandler) {
|
|
9565
|
+
constructor(eventsHandler, pythonInstaller) {
|
|
9492
9566
|
super();
|
|
9493
9567
|
this.eventsHandler = eventsHandler;
|
|
9568
|
+
this.pythonInstaller = pythonInstaller;
|
|
9494
9569
|
}
|
|
9495
9570
|
registerRoutes(router) {
|
|
9496
9571
|
router.get(
|
|
@@ -9524,6 +9599,13 @@ class SystemApi extends BaseApi {
|
|
|
9524
9599
|
res.status(200).json({ success: true });
|
|
9525
9600
|
})
|
|
9526
9601
|
);
|
|
9602
|
+
router.get(
|
|
9603
|
+
"/system/aider-connector-status",
|
|
9604
|
+
this.handleRequest(async (_req, res) => {
|
|
9605
|
+
const status = this.pythonInstaller.getStatus();
|
|
9606
|
+
res.status(200).json(status);
|
|
9607
|
+
})
|
|
9608
|
+
);
|
|
9527
9609
|
}
|
|
9528
9610
|
}
|
|
9529
9611
|
const GetTodosSchema = zod.z.object({
|
|
@@ -10100,13 +10182,88 @@ class ExtensionsApi extends BaseApi {
|
|
|
10100
10182
|
);
|
|
10101
10183
|
}
|
|
10102
10184
|
}
|
|
10185
|
+
const GetSkillsSchema = zod.z.object({
|
|
10186
|
+
projectDir: zod.z.string().min(1, "Project directory is required"),
|
|
10187
|
+
taskId: zod.z.string().min(1, "Task ID is required")
|
|
10188
|
+
});
|
|
10189
|
+
const ActivateSkillSchema = zod.z.object({
|
|
10190
|
+
projectDir: zod.z.string().min(1, "Project directory is required"),
|
|
10191
|
+
taskId: zod.z.string().min(1, "Task ID is required"),
|
|
10192
|
+
skillName: zod.z.string().min(1, "Skill name is required")
|
|
10193
|
+
});
|
|
10194
|
+
class SkillsApi extends BaseApi {
|
|
10195
|
+
constructor(eventsHandler) {
|
|
10196
|
+
super();
|
|
10197
|
+
this.eventsHandler = eventsHandler;
|
|
10198
|
+
}
|
|
10199
|
+
registerRoutes(router) {
|
|
10200
|
+
router.get(
|
|
10201
|
+
"/skills",
|
|
10202
|
+
this.handleRequest(async (req, res) => {
|
|
10203
|
+
const parsed = this.validateRequest(GetSkillsSchema, req.query, res);
|
|
10204
|
+
if (!parsed) {
|
|
10205
|
+
return;
|
|
10206
|
+
}
|
|
10207
|
+
const { projectDir, taskId } = parsed;
|
|
10208
|
+
const skills = await this.eventsHandler.getSkills(projectDir, taskId);
|
|
10209
|
+
res.status(200).json(skills);
|
|
10210
|
+
})
|
|
10211
|
+
);
|
|
10212
|
+
router.post(
|
|
10213
|
+
"/skills/activate",
|
|
10214
|
+
this.handleRequest(async (req, res) => {
|
|
10215
|
+
const parsed = this.validateRequest(ActivateSkillSchema, req.body, res);
|
|
10216
|
+
if (!parsed) {
|
|
10217
|
+
return;
|
|
10218
|
+
}
|
|
10219
|
+
const { projectDir, taskId, skillName } = parsed;
|
|
10220
|
+
await this.eventsHandler.activateSkill(projectDir, taskId, skillName);
|
|
10221
|
+
res.status(200).json({ success: true });
|
|
10222
|
+
})
|
|
10223
|
+
);
|
|
10224
|
+
router.post(
|
|
10225
|
+
"/skills/deactivate",
|
|
10226
|
+
this.handleRequest(async (req, res) => {
|
|
10227
|
+
const parsed = this.validateRequest(ActivateSkillSchema, req.body, res);
|
|
10228
|
+
if (!parsed) {
|
|
10229
|
+
return;
|
|
10230
|
+
}
|
|
10231
|
+
const { projectDir, taskId, skillName } = parsed;
|
|
10232
|
+
await this.eventsHandler.deactivateSkill(projectDir, taskId, skillName);
|
|
10233
|
+
res.status(200).json({ success: true });
|
|
10234
|
+
})
|
|
10235
|
+
);
|
|
10236
|
+
}
|
|
10237
|
+
}
|
|
10238
|
+
const createCorsOriginValidator = (store) => (origin, callback) => {
|
|
10239
|
+
if (CORS_ALLOWED_ORIGINS) {
|
|
10240
|
+
const origins = CORS_ALLOWED_ORIGINS.split(",").map((o) => o.trim()).filter(Boolean);
|
|
10241
|
+
if (!origin || origins.includes(origin)) {
|
|
10242
|
+
callback(null, true);
|
|
10243
|
+
} else {
|
|
10244
|
+
callback(null, false);
|
|
10245
|
+
}
|
|
10246
|
+
return;
|
|
10247
|
+
}
|
|
10248
|
+
const corsSettings = store.getSettings().server.cors;
|
|
10249
|
+
if (!corsSettings.enabled || corsSettings.origins.length === 0) {
|
|
10250
|
+
callback(null, false);
|
|
10251
|
+
return;
|
|
10252
|
+
}
|
|
10253
|
+
if (!origin || corsSettings.origins.includes(origin)) {
|
|
10254
|
+
callback(null, true);
|
|
10255
|
+
} else {
|
|
10256
|
+
callback(null, false);
|
|
10257
|
+
}
|
|
10258
|
+
};
|
|
10103
10259
|
const REQUEST_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
10104
10260
|
class ServerController {
|
|
10105
|
-
constructor(server, projectManager, eventsHandler, store) {
|
|
10261
|
+
constructor(server, projectManager, eventsHandler, store, pythonInstaller) {
|
|
10106
10262
|
this.server = server;
|
|
10107
10263
|
this.projectManager = projectManager;
|
|
10108
10264
|
this.eventsHandler = eventsHandler;
|
|
10109
10265
|
this.store = store;
|
|
10266
|
+
this.pythonInstaller = pythonInstaller;
|
|
10110
10267
|
this.init();
|
|
10111
10268
|
}
|
|
10112
10269
|
app = express();
|
|
@@ -10162,7 +10319,7 @@ class ServerController {
|
|
|
10162
10319
|
new ProjectApi(this.eventsHandler).registerRoutes(apiRouter);
|
|
10163
10320
|
new CommandsApi(this.eventsHandler).registerRoutes(apiRouter);
|
|
10164
10321
|
new UsageApi(this.eventsHandler).registerRoutes(apiRouter);
|
|
10165
|
-
new SystemApi(this.eventsHandler).registerRoutes(apiRouter);
|
|
10322
|
+
new SystemApi(this.eventsHandler, this.pythonInstaller).registerRoutes(apiRouter);
|
|
10166
10323
|
new TodoApi(this.eventsHandler).registerRoutes(apiRouter);
|
|
10167
10324
|
new McpApi(this.eventsHandler).registerRoutes(apiRouter);
|
|
10168
10325
|
new ProvidersApi(this.eventsHandler).registerRoutes(apiRouter);
|
|
@@ -10171,11 +10328,15 @@ class ServerController {
|
|
|
10171
10328
|
new VoiceApi(this.eventsHandler).registerRoutes(apiRouter);
|
|
10172
10329
|
new TerminalApi(this.eventsHandler).registerRoutes(apiRouter);
|
|
10173
10330
|
new ExtensionsApi(this.eventsHandler).registerRoutes(apiRouter);
|
|
10331
|
+
new SkillsApi(this.eventsHandler).registerRoutes(apiRouter);
|
|
10174
10332
|
this.app.use("/api", apiRouter);
|
|
10175
10333
|
}
|
|
10334
|
+
setupCors() {
|
|
10335
|
+
this.app.use(cors({ origin: createCorsOriginValidator(this.store) }));
|
|
10336
|
+
}
|
|
10176
10337
|
init() {
|
|
10177
10338
|
this.app.use(express.json({ limit: "50mb" }));
|
|
10178
|
-
this.
|
|
10339
|
+
this.setupCors();
|
|
10179
10340
|
this.app.use(this.serverGuardMiddleware.bind(this));
|
|
10180
10341
|
this.app.use(this.timeoutMiddleware.bind(this));
|
|
10181
10342
|
this.app.use(this.basicAuthMiddleware.bind(this));
|
|
@@ -10442,9 +10603,10 @@ const isUnsubscribeEventsMessage = (message) => {
|
|
|
10442
10603
|
return message.action === "unsubscribe-events";
|
|
10443
10604
|
};
|
|
10444
10605
|
class ConnectorManager {
|
|
10445
|
-
constructor(httpServer, projectManager, eventManager) {
|
|
10606
|
+
constructor(httpServer, projectManager, eventManager, store) {
|
|
10446
10607
|
this.projectManager = projectManager;
|
|
10447
10608
|
this.eventManager = eventManager;
|
|
10609
|
+
this.store = store;
|
|
10448
10610
|
this.init(httpServer);
|
|
10449
10611
|
}
|
|
10450
10612
|
io = null;
|
|
@@ -10452,7 +10614,7 @@ class ConnectorManager {
|
|
|
10452
10614
|
init(httpServer) {
|
|
10453
10615
|
this.io = new socket_io.Server(httpServer, {
|
|
10454
10616
|
cors: {
|
|
10455
|
-
origin:
|
|
10617
|
+
origin: createCorsOriginValidator(this.store),
|
|
10456
10618
|
methods: ["GET", "POST"]
|
|
10457
10619
|
},
|
|
10458
10620
|
pingTimeout: 6e5,
|
|
@@ -11286,6 +11448,15 @@ class ContextManager {
|
|
|
11286
11448
|
}
|
|
11287
11449
|
return this.removeByToolCallId(messageId);
|
|
11288
11450
|
}
|
|
11451
|
+
removeMessagesByIds(ids) {
|
|
11452
|
+
for (const id of ids) {
|
|
11453
|
+
const index = this.messages.findIndex((msg) => msg.id === id);
|
|
11454
|
+
if (index !== -1) {
|
|
11455
|
+
this.messages.splice(index, 1);
|
|
11456
|
+
}
|
|
11457
|
+
}
|
|
11458
|
+
this.autosave();
|
|
11459
|
+
}
|
|
11289
11460
|
removeMessageByIndex(index, messageId) {
|
|
11290
11461
|
const removedIds = [];
|
|
11291
11462
|
removedIds.push(messageId);
|
|
@@ -11415,16 +11586,17 @@ class ContextManager {
|
|
|
11415
11586
|
}
|
|
11416
11587
|
this.autosave();
|
|
11417
11588
|
}
|
|
11418
|
-
|
|
11419
|
-
const
|
|
11420
|
-
if (
|
|
11421
|
-
logger.warn("No user message found to remove up to.", {
|
|
11422
|
-
taskId: this.taskId
|
|
11589
|
+
removeMessagesUpToUserMessage(messageId) {
|
|
11590
|
+
const userMessageIndex = this.messages.findIndex((msg) => msg.id === messageId && msg.role === MessageRole.User);
|
|
11591
|
+
if (userMessageIndex === -1) {
|
|
11592
|
+
logger.warn("No user message found with the given ID to remove up to.", {
|
|
11593
|
+
taskId: this.taskId,
|
|
11594
|
+
messageId
|
|
11423
11595
|
});
|
|
11424
11596
|
return [];
|
|
11425
11597
|
}
|
|
11426
|
-
const removedMessages = this.messages.splice(
|
|
11427
|
-
logger.debug(`Task ${this.taskId}: Removed ${removedMessages.length} messages up to
|
|
11598
|
+
const removedMessages = this.messages.splice(userMessageIndex);
|
|
11599
|
+
logger.debug(`Task ${this.taskId}: Removed ${removedMessages.length} messages up to user message ${messageId}. Total messages: ${this.messages.length}`);
|
|
11428
11600
|
this.autosave();
|
|
11429
11601
|
return removedMessages;
|
|
11430
11602
|
}
|
|
@@ -12078,6 +12250,82 @@ ${JSON.stringify(part.output.value, null, 2)}
|
|
|
12078
12250
|
return removedIds;
|
|
12079
12251
|
}
|
|
12080
12252
|
}
|
|
12253
|
+
const PROXY_ENV_VAR_NAMES = ["HTTP_PROXY", "HTTPS_PROXY", "ALL_PROXY", "http_proxy", "https_proxy", "all_proxy"];
|
|
12254
|
+
const getProxyEnvVars = (settings) => {
|
|
12255
|
+
if (settings.proxy?.enabled && settings.proxy?.url) {
|
|
12256
|
+
const url = settings.proxy.url;
|
|
12257
|
+
return {
|
|
12258
|
+
HTTP_PROXY: url,
|
|
12259
|
+
HTTPS_PROXY: url,
|
|
12260
|
+
ALL_PROXY: url,
|
|
12261
|
+
http_proxy: url,
|
|
12262
|
+
https_proxy: url,
|
|
12263
|
+
all_proxy: url
|
|
12264
|
+
};
|
|
12265
|
+
}
|
|
12266
|
+
return Object.fromEntries(PROXY_ENV_VAR_NAMES.map((key) => [key, ""]));
|
|
12267
|
+
};
|
|
12268
|
+
class ProxyManager {
|
|
12269
|
+
currentUrl = null;
|
|
12270
|
+
/**
|
|
12271
|
+
* Initialize proxy from settings. Called once during app startup (first in managers init).
|
|
12272
|
+
*/
|
|
12273
|
+
init(settings) {
|
|
12274
|
+
globalAgent.bootstrap();
|
|
12275
|
+
if (settings.proxy?.enabled && settings.proxy?.url) {
|
|
12276
|
+
this.applyProxy(settings.proxy.url);
|
|
12277
|
+
} else {
|
|
12278
|
+
this.clearProxy();
|
|
12279
|
+
}
|
|
12280
|
+
}
|
|
12281
|
+
/**
|
|
12282
|
+
* React to settings changes. Called on every saveSettings().
|
|
12283
|
+
* Re-initializes the proxy if the config changed.
|
|
12284
|
+
*/
|
|
12285
|
+
settingsChanged(oldSettings, newSettings) {
|
|
12286
|
+
const oldProxy = oldSettings.proxy;
|
|
12287
|
+
const newProxy = newSettings.proxy;
|
|
12288
|
+
if (oldProxy?.enabled !== newProxy?.enabled || oldProxy?.url !== newProxy?.url) {
|
|
12289
|
+
if (newProxy?.enabled && newProxy?.url) {
|
|
12290
|
+
logger.info(`[ProxyManager] Applying proxy: ${newProxy.url}`);
|
|
12291
|
+
this.applyProxy(newProxy.url);
|
|
12292
|
+
} else if (this.currentUrl !== null) {
|
|
12293
|
+
logger.info("[ProxyManager] Clearing proxy");
|
|
12294
|
+
this.clearProxy();
|
|
12295
|
+
}
|
|
12296
|
+
}
|
|
12297
|
+
}
|
|
12298
|
+
applyProxy(url) {
|
|
12299
|
+
try {
|
|
12300
|
+
global.GLOBAL_AGENT.HTTP_PROXY = url;
|
|
12301
|
+
const proxyAgent = new undici.ProxyAgent(url);
|
|
12302
|
+
undici.setGlobalDispatcher(proxyAgent);
|
|
12303
|
+
this.currentUrl = url;
|
|
12304
|
+
logger.info(`[ProxyManager] Proxy initialized: ${url}`);
|
|
12305
|
+
} catch (error) {
|
|
12306
|
+
logger.error("[ProxyManager] Failed to initialize proxy", { error: error instanceof Error ? error.message : String(error) });
|
|
12307
|
+
}
|
|
12308
|
+
}
|
|
12309
|
+
clearProxy() {
|
|
12310
|
+
try {
|
|
12311
|
+
global.GLOBAL_AGENT.HTTP_PROXY = void 0;
|
|
12312
|
+
undici.setGlobalDispatcher(
|
|
12313
|
+
new undici.Agent({
|
|
12314
|
+
headersTimeout: 30 * 60 * 1e3,
|
|
12315
|
+
// 30 minutes
|
|
12316
|
+
bodyTimeout: 30 * 60 * 1e3,
|
|
12317
|
+
// 30 minutes
|
|
12318
|
+
connectTimeout: 30 * 1e3
|
|
12319
|
+
// 30 seconds
|
|
12320
|
+
})
|
|
12321
|
+
);
|
|
12322
|
+
this.currentUrl = null;
|
|
12323
|
+
logger.info("[ProxyManager] Proxy cleared");
|
|
12324
|
+
} catch (error) {
|
|
12325
|
+
logger.error("[ProxyManager] Failed to clear proxy", { error: error instanceof Error ? error.message : String(error) });
|
|
12326
|
+
}
|
|
12327
|
+
}
|
|
12328
|
+
}
|
|
12081
12329
|
class AiderManager {
|
|
12082
12330
|
constructor(task, store, modelManager, eventManager, getConnectors, pythonInstaller) {
|
|
12083
12331
|
this.task = task;
|
|
@@ -12186,11 +12434,13 @@ class AiderManager {
|
|
|
12186
12434
|
taskId: this.task.taskId,
|
|
12187
12435
|
args
|
|
12188
12436
|
});
|
|
12437
|
+
const proxyEnvVars = getProxyEnvVars(settings);
|
|
12189
12438
|
const env = {
|
|
12190
12439
|
...process.env,
|
|
12191
12440
|
...environmentVariables,
|
|
12192
12441
|
...envFromMain,
|
|
12193
12442
|
...envFromWeak,
|
|
12443
|
+
...proxyEnvVars,
|
|
12194
12444
|
PYTHONPATH: AIDER_DESK_CONNECTOR_DIR,
|
|
12195
12445
|
PYTHONUTF8: process.env.AIDER_DESK_OMIT_PYTHONUTF8 ? void 0 : "1",
|
|
12196
12446
|
BASE_DIR: this.task.getProjectDir(),
|
|
@@ -12486,6 +12736,156 @@ class AiderManager {
|
|
|
12486
12736
|
connectors.filter((connector) => connector.listenTo.includes("update-env-vars")).forEach((connector) => connector.sendUpdateEnvVarsMessage(environmentVariables));
|
|
12487
12737
|
}
|
|
12488
12738
|
}
|
|
12739
|
+
const SKILLS_DIR_NAME = "skills";
|
|
12740
|
+
const SKILL_MARKDOWN_FILE = "SKILL.md";
|
|
12741
|
+
const TOOL_NAME = `${SKILLS_TOOL_GROUP_NAME}${TOOL_GROUP_NAME_SEPARATOR}${SKILLS_TOOL_ACTIVATE_SKILL}`;
|
|
12742
|
+
const parseSkillFrontMatter = (markdown) => {
|
|
12743
|
+
const parsed = yamlFrontMatter.loadFront(markdown);
|
|
12744
|
+
const name = typeof parsed.name === "string" ? parsed.name : void 0;
|
|
12745
|
+
const description = typeof parsed.description === "string" ? parsed.description : void 0;
|
|
12746
|
+
if (!name || !description) {
|
|
12747
|
+
return null;
|
|
12748
|
+
}
|
|
12749
|
+
return { name, description };
|
|
12750
|
+
};
|
|
12751
|
+
const safeReadDir = async (dirPath) => {
|
|
12752
|
+
try {
|
|
12753
|
+
return await fs.readdir(dirPath);
|
|
12754
|
+
} catch {
|
|
12755
|
+
return [];
|
|
12756
|
+
}
|
|
12757
|
+
};
|
|
12758
|
+
const safeStat = async (filePath) => {
|
|
12759
|
+
try {
|
|
12760
|
+
return await fs.stat(filePath);
|
|
12761
|
+
} catch {
|
|
12762
|
+
return null;
|
|
12763
|
+
}
|
|
12764
|
+
};
|
|
12765
|
+
const loadSkillsFromDir = async (skillsRootDir, location) => {
|
|
12766
|
+
const entries = await safeReadDir(skillsRootDir);
|
|
12767
|
+
const skills = [];
|
|
12768
|
+
for (const entry of entries) {
|
|
12769
|
+
const dirPath = path.join(skillsRootDir, entry);
|
|
12770
|
+
const stat = await safeStat(dirPath);
|
|
12771
|
+
if (!stat?.isDirectory()) {
|
|
12772
|
+
continue;
|
|
12773
|
+
}
|
|
12774
|
+
const skillMdPath = path.join(dirPath, SKILL_MARKDOWN_FILE);
|
|
12775
|
+
const skillMdStat = await safeStat(skillMdPath);
|
|
12776
|
+
if (!skillMdStat?.isFile()) {
|
|
12777
|
+
continue;
|
|
12778
|
+
}
|
|
12779
|
+
let markdown;
|
|
12780
|
+
try {
|
|
12781
|
+
markdown = await fs.readFile(skillMdPath, "utf8");
|
|
12782
|
+
} catch {
|
|
12783
|
+
continue;
|
|
12784
|
+
}
|
|
12785
|
+
const parsed = parseSkillFrontMatter(markdown);
|
|
12786
|
+
if (!parsed) {
|
|
12787
|
+
continue;
|
|
12788
|
+
}
|
|
12789
|
+
skills.push({
|
|
12790
|
+
name: parsed.name,
|
|
12791
|
+
description: parsed.description,
|
|
12792
|
+
location,
|
|
12793
|
+
dirPath
|
|
12794
|
+
});
|
|
12795
|
+
}
|
|
12796
|
+
return skills;
|
|
12797
|
+
};
|
|
12798
|
+
class SkillManager {
|
|
12799
|
+
extensionManager;
|
|
12800
|
+
projectDir;
|
|
12801
|
+
constructor(projectDir, extensionManager) {
|
|
12802
|
+
this.projectDir = projectDir;
|
|
12803
|
+
this.extensionManager = extensionManager;
|
|
12804
|
+
}
|
|
12805
|
+
async loadAllSkills() {
|
|
12806
|
+
const globalSkillsDir = path.join(os.homedir(), AIDER_DESK_DIR, SKILLS_DIR_NAME);
|
|
12807
|
+
const projectSkillsDir = path.join(this.projectDir, AIDER_DESK_DIR, SKILLS_DIR_NAME);
|
|
12808
|
+
const extensionSkills = this.extensionManager ? this.extensionManager.getSkills({ baseDir: this.projectDir }, { getTaskDir: () => this.projectDir }) : [];
|
|
12809
|
+
const [globalSkills, projectSkills, builtinSkills] = await Promise.all([
|
|
12810
|
+
loadSkillsFromDir(globalSkillsDir, "global"),
|
|
12811
|
+
loadSkillsFromDir(projectSkillsDir, "project"),
|
|
12812
|
+
loadSkillsFromDir(AIDER_DESK_BUILTIN_SKILLS_DIR, "builtin")
|
|
12813
|
+
]);
|
|
12814
|
+
return [...projectSkills, ...globalSkills, ...builtinSkills, ...extensionSkills];
|
|
12815
|
+
}
|
|
12816
|
+
async getSkills(contextMessages) {
|
|
12817
|
+
const skills = await this.loadAllSkills();
|
|
12818
|
+
const activatedSkillNames = contextMessages ? this.getActivatedSkillNames(contextMessages) : /* @__PURE__ */ new Set();
|
|
12819
|
+
return skills.map((skill) => ({
|
|
12820
|
+
...skill,
|
|
12821
|
+
activated: activatedSkillNames.has(skill.name)
|
|
12822
|
+
}));
|
|
12823
|
+
}
|
|
12824
|
+
async getSkillContent(skillName) {
|
|
12825
|
+
const skills = await this.loadAllSkills();
|
|
12826
|
+
const skill = skills.find((s) => s.name === skillName);
|
|
12827
|
+
if (!skill) {
|
|
12828
|
+
return null;
|
|
12829
|
+
}
|
|
12830
|
+
if (skill.content) {
|
|
12831
|
+
return skill.content;
|
|
12832
|
+
}
|
|
12833
|
+
if (skill.dirPath) {
|
|
12834
|
+
const skillMdPath = path.join(skill.dirPath, SKILL_MARKDOWN_FILE);
|
|
12835
|
+
try {
|
|
12836
|
+
return await fs.readFile(skillMdPath, "utf8");
|
|
12837
|
+
} catch {
|
|
12838
|
+
return null;
|
|
12839
|
+
}
|
|
12840
|
+
}
|
|
12841
|
+
return null;
|
|
12842
|
+
}
|
|
12843
|
+
getActivatedSkillNames(contextMessages) {
|
|
12844
|
+
const activatedNames = /* @__PURE__ */ new Set();
|
|
12845
|
+
for (const message of contextMessages) {
|
|
12846
|
+
if (message.role === "assistant" && Array.isArray(message.content)) {
|
|
12847
|
+
for (const part of message.content) {
|
|
12848
|
+
if (part.type === "tool-call" && part.toolName === TOOL_NAME && part.input?.skill) {
|
|
12849
|
+
activatedNames.add(part.input.skill);
|
|
12850
|
+
}
|
|
12851
|
+
}
|
|
12852
|
+
}
|
|
12853
|
+
}
|
|
12854
|
+
return activatedNames;
|
|
12855
|
+
}
|
|
12856
|
+
buildActivateSkillMessages(skillName, content) {
|
|
12857
|
+
const toolCallId = uuid.v4();
|
|
12858
|
+
const assistantMessage = {
|
|
12859
|
+
id: uuid.v4(),
|
|
12860
|
+
role: "assistant",
|
|
12861
|
+
content: [
|
|
12862
|
+
{
|
|
12863
|
+
type: "text",
|
|
12864
|
+
text: "User requested the skill activation."
|
|
12865
|
+
},
|
|
12866
|
+
{
|
|
12867
|
+
type: "tool-call",
|
|
12868
|
+
toolCallId,
|
|
12869
|
+
toolName: TOOL_NAME,
|
|
12870
|
+
input: { skill: skillName }
|
|
12871
|
+
}
|
|
12872
|
+
]
|
|
12873
|
+
};
|
|
12874
|
+
const toolMessage = {
|
|
12875
|
+
id: uuid.v4(),
|
|
12876
|
+
role: "tool",
|
|
12877
|
+
content: [
|
|
12878
|
+
{
|
|
12879
|
+
type: "tool-result",
|
|
12880
|
+
toolCallId,
|
|
12881
|
+
toolName: TOOL_NAME,
|
|
12882
|
+
output: { type: "text", value: content }
|
|
12883
|
+
}
|
|
12884
|
+
]
|
|
12885
|
+
};
|
|
12886
|
+
return [assistantMessage, toolMessage];
|
|
12887
|
+
}
|
|
12888
|
+
}
|
|
12489
12889
|
class GitError extends Error {
|
|
12490
12890
|
name = "GitError";
|
|
12491
12891
|
gitCommands;
|
|
@@ -12563,7 +12963,7 @@ class WorktreeManager {
|
|
|
12563
12963
|
await execWithShellPath('git commit -m "Initial commit" --allow-empty', { cwd: projectPath });
|
|
12564
12964
|
}
|
|
12565
12965
|
let baseCommit;
|
|
12566
|
-
let
|
|
12966
|
+
let newBranchName;
|
|
12567
12967
|
const baseRef = baseBranch;
|
|
12568
12968
|
if (branch) {
|
|
12569
12969
|
let branchExists = false;
|
|
@@ -12577,7 +12977,7 @@ class WorktreeManager {
|
|
|
12577
12977
|
baseCommit = (await execWithShellPath(`git rev-parse ${branch}`, {
|
|
12578
12978
|
cwd: projectPath
|
|
12579
12979
|
})).stdout.trim();
|
|
12580
|
-
|
|
12980
|
+
newBranchName = branch;
|
|
12581
12981
|
} else {
|
|
12582
12982
|
if (baseBranch !== "HEAD") {
|
|
12583
12983
|
try {
|
|
@@ -12590,7 +12990,7 @@ class WorktreeManager {
|
|
|
12590
12990
|
cwd: projectPath
|
|
12591
12991
|
})).stdout.trim();
|
|
12592
12992
|
await execWithShellPath(`git worktree add -b ${branch} "${worktreePath}" ${baseRef}`, { cwd: projectPath });
|
|
12593
|
-
|
|
12993
|
+
newBranchName = branch;
|
|
12594
12994
|
}
|
|
12595
12995
|
} else {
|
|
12596
12996
|
await execWithShellPath(`git worktree add "${worktreePath}" ${baseRef}`, { cwd: projectPath });
|
|
@@ -12599,25 +12999,38 @@ class WorktreeManager {
|
|
|
12599
12999
|
})).stdout.trim();
|
|
12600
13000
|
if (baseRef === "HEAD") {
|
|
12601
13001
|
try {
|
|
12602
|
-
|
|
13002
|
+
newBranchName = (await execWithShellPath("git rev-parse --abbrev-ref HEAD", {
|
|
12603
13003
|
cwd: projectPath
|
|
12604
13004
|
})).stdout.trim();
|
|
12605
|
-
if (
|
|
12606
|
-
|
|
13005
|
+
if (newBranchName === "HEAD") {
|
|
13006
|
+
newBranchName = "DETACHED HEAD";
|
|
12607
13007
|
}
|
|
12608
13008
|
} catch {
|
|
12609
|
-
|
|
13009
|
+
newBranchName = "DETACHED HEAD";
|
|
12610
13010
|
}
|
|
12611
13011
|
} else {
|
|
12612
|
-
|
|
13012
|
+
newBranchName = `${baseRef} (DETACHED)`;
|
|
12613
13013
|
}
|
|
12614
13014
|
logger.info(`Worktree created in DETACHED HEAD mode from commit: ${baseCommit}`);
|
|
12615
13015
|
}
|
|
13016
|
+
let resolvedBaseBranch;
|
|
13017
|
+
if (baseRef === "HEAD") {
|
|
13018
|
+
try {
|
|
13019
|
+
const result = await execWithShellPath("git rev-parse --abbrev-ref HEAD", { cwd: projectPath });
|
|
13020
|
+
const headBranch = result.stdout.trim();
|
|
13021
|
+
resolvedBaseBranch = headBranch !== "HEAD" ? headBranch : void 0;
|
|
13022
|
+
} catch {
|
|
13023
|
+
resolvedBaseBranch = void 0;
|
|
13024
|
+
}
|
|
13025
|
+
} else {
|
|
13026
|
+
resolvedBaseBranch = baseRef;
|
|
13027
|
+
}
|
|
12616
13028
|
logger.info(`Worktree created successfully at: ${worktreePath}`);
|
|
12617
13029
|
return {
|
|
12618
13030
|
path: worktreePath,
|
|
12619
13031
|
baseCommit,
|
|
12620
|
-
baseBranch:
|
|
13032
|
+
baseBranch: resolvedBaseBranch,
|
|
13033
|
+
branch: newBranchName
|
|
12621
13034
|
};
|
|
12622
13035
|
} catch (error) {
|
|
12623
13036
|
logger.error("Failed to create worktree:", error);
|
|
@@ -12625,6 +13038,29 @@ class WorktreeManager {
|
|
|
12625
13038
|
}
|
|
12626
13039
|
});
|
|
12627
13040
|
}
|
|
13041
|
+
async renameBranch(projectPath, oldBranch, newBranch) {
|
|
13042
|
+
try {
|
|
13043
|
+
const finalBranchName = await this.findUniqueBranchName(projectPath, newBranch);
|
|
13044
|
+
await execWithShellPath(`git branch -m ${oldBranch} ${finalBranchName}`, { cwd: projectPath });
|
|
13045
|
+
logger.info(`Renamed branch: ${oldBranch} -> ${finalBranchName}`);
|
|
13046
|
+
return finalBranchName;
|
|
13047
|
+
} catch (error) {
|
|
13048
|
+
logger.warn(`Failed to rename branch ${oldBranch} to ${newBranch}:`, error);
|
|
13049
|
+
return newBranch;
|
|
13050
|
+
}
|
|
13051
|
+
}
|
|
13052
|
+
async findUniqueBranchName(projectPath, baseName) {
|
|
13053
|
+
const existingBranches = await this.listBranches(projectPath);
|
|
13054
|
+
const branchNames = new Set(existingBranches.map((b) => b.name));
|
|
13055
|
+
if (!branchNames.has(baseName)) {
|
|
13056
|
+
return baseName;
|
|
13057
|
+
}
|
|
13058
|
+
let suffix = 2;
|
|
13059
|
+
while (branchNames.has(`${baseName}-${suffix}`)) {
|
|
13060
|
+
suffix++;
|
|
13061
|
+
}
|
|
13062
|
+
return `${baseName}-${suffix}`;
|
|
13063
|
+
}
|
|
12628
13064
|
async createSymlinks(projectPath, worktreePath, folderNames) {
|
|
12629
13065
|
if (folderNames.length === 0) {
|
|
12630
13066
|
logger.debug("No symlink folders configured, skipping symlink creation");
|
|
@@ -12678,14 +13114,14 @@ class WorktreeManager {
|
|
|
12678
13114
|
return await withLock(`worktree-remove-${projectDir}-${worktree.path}`, async () => {
|
|
12679
13115
|
try {
|
|
12680
13116
|
await execWithShellPath(`git worktree remove "${worktree.path}" --force`, { cwd: projectDir });
|
|
12681
|
-
if (worktree.
|
|
13117
|
+
if (worktree.branch) {
|
|
12682
13118
|
try {
|
|
12683
|
-
await execWithShellPath(`git branch -D ${worktree.
|
|
13119
|
+
await execWithShellPath(`git branch -D ${worktree.branch}`, {
|
|
12684
13120
|
cwd: projectDir
|
|
12685
13121
|
});
|
|
12686
|
-
logger.info(`Deleted task branch: ${worktree.
|
|
13122
|
+
logger.info(`Deleted task branch: ${worktree.branch}`);
|
|
12687
13123
|
} catch (error) {
|
|
12688
|
-
logger.debug(`Could not delete branch ${worktree.
|
|
13124
|
+
logger.debug(`Could not delete branch ${worktree.branch}:`, error);
|
|
12689
13125
|
}
|
|
12690
13126
|
}
|
|
12691
13127
|
} catch (error) {
|
|
@@ -12712,12 +13148,12 @@ class WorktreeManager {
|
|
|
12712
13148
|
...currentWorktree
|
|
12713
13149
|
});
|
|
12714
13150
|
}
|
|
12715
|
-
currentWorktree = { path: line.substring(9),
|
|
13151
|
+
currentWorktree = { path: line.substring(9), branch: "" };
|
|
12716
13152
|
} else if (line.startsWith("branch ")) {
|
|
12717
13153
|
currentWorktree = {
|
|
12718
13154
|
...currentWorktree || {},
|
|
12719
13155
|
path: currentWorktree ? currentWorktree.path : "",
|
|
12720
|
-
|
|
13156
|
+
branch: line.substring(7).replace("refs/heads/", "")
|
|
12721
13157
|
};
|
|
12722
13158
|
} else if (line.startsWith("HEAD ")) {
|
|
12723
13159
|
currentWorktree = {
|
|
@@ -12729,7 +13165,7 @@ class WorktreeManager {
|
|
|
12729
13165
|
currentWorktree = {
|
|
12730
13166
|
...currentWorktree || {},
|
|
12731
13167
|
path: currentWorktree ? currentWorktree.path : "",
|
|
12732
|
-
|
|
13168
|
+
branch: void 0
|
|
12733
13169
|
};
|
|
12734
13170
|
} else if (line.startsWith("prunable")) {
|
|
12735
13171
|
currentWorktree = {
|
|
@@ -12758,7 +13194,7 @@ class WorktreeManager {
|
|
|
12758
13194
|
cwd: projectPath
|
|
12759
13195
|
});
|
|
12760
13196
|
const worktrees = await this.listWorktrees(projectPath);
|
|
12761
|
-
const worktreeBranches = new Set(worktrees.map((w) => w.
|
|
13197
|
+
const worktreeBranches = new Set(worktrees.map((w) => w.branch));
|
|
12762
13198
|
const branches = [];
|
|
12763
13199
|
const lines = branchOutput.split("\n").filter((line) => line.trim());
|
|
12764
13200
|
for (const line of lines) {
|
|
@@ -12812,6 +13248,22 @@ class WorktreeManager {
|
|
|
12812
13248
|
logger.warn("getEffectiveMainBranch is deprecated, use getProjectMainBranch instead");
|
|
12813
13249
|
return await this.getProjectMainBranch(project.path);
|
|
12814
13250
|
}
|
|
13251
|
+
async getHeadCommit(worktreePath) {
|
|
13252
|
+
try {
|
|
13253
|
+
const { stdout } = await execWithShellPath("git rev-parse HEAD", { cwd: worktreePath });
|
|
13254
|
+
return stdout.trim();
|
|
13255
|
+
} catch {
|
|
13256
|
+
return void 0;
|
|
13257
|
+
}
|
|
13258
|
+
}
|
|
13259
|
+
async getBranchesContainingCommit(projectPath, commit) {
|
|
13260
|
+
try {
|
|
13261
|
+
const { stdout } = await execWithShellPath(`git branch --contains ${commit} --format='%(refname:short)'`, { cwd: projectPath });
|
|
13262
|
+
return stdout.trim().split("\n").map((b) => b.trim()).filter((b) => b);
|
|
13263
|
+
} catch {
|
|
13264
|
+
return [];
|
|
13265
|
+
}
|
|
13266
|
+
}
|
|
12815
13267
|
async hasChangesToRebase(worktreePath, mainBranch) {
|
|
12816
13268
|
try {
|
|
12817
13269
|
let stdout = "0";
|
|
@@ -12893,7 +13345,7 @@ class WorktreeManager {
|
|
|
12893
13345
|
};
|
|
12894
13346
|
}
|
|
12895
13347
|
}
|
|
12896
|
-
async rebaseMainIntoWorktree(worktreePath, mainBranch) {
|
|
13348
|
+
async rebaseMainIntoWorktree(worktreePath, mainBranch, baseCommit) {
|
|
12897
13349
|
return await withLock(`git-rebase-${worktreePath}`, async () => {
|
|
12898
13350
|
const executedCommands = [];
|
|
12899
13351
|
let lastOutput = "";
|
|
@@ -12905,14 +13357,14 @@ class WorktreeManager {
|
|
|
12905
13357
|
const addCommand = "git add -A";
|
|
12906
13358
|
executedCommands.push(`${addCommand} (in ${worktreePath})`);
|
|
12907
13359
|
await execWithShellPath(addCommand, { cwd: worktreePath });
|
|
12908
|
-
const commitCommand = `git commit -m "TEMP_UNCOMMITTED_${Date.now()}"`;
|
|
13360
|
+
const commitCommand = `git commit --no-verify -m "TEMP_UNCOMMITTED_${Date.now()}"`;
|
|
12909
13361
|
executedCommands.push(`${commitCommand} (in ${worktreePath})`);
|
|
12910
13362
|
await execWithShellPath(commitCommand, {
|
|
12911
13363
|
cwd: worktreePath
|
|
12912
13364
|
});
|
|
12913
13365
|
logger.info("Created temporary commit for uncommitted changes");
|
|
12914
13366
|
}
|
|
12915
|
-
const command = `git rebase ${mainBranch}`;
|
|
13367
|
+
const command = baseCommit ? `git rebase --onto ${mainBranch} ${baseCommit}` : `git rebase ${mainBranch}`;
|
|
12916
13368
|
executedCommands.push(`${command} (in ${worktreePath})`);
|
|
12917
13369
|
const rebaseResult = await execWithShellPath(command, {
|
|
12918
13370
|
cwd: worktreePath
|
|
@@ -12987,7 +13439,7 @@ class WorktreeManager {
|
|
|
12987
13439
|
}
|
|
12988
13440
|
});
|
|
12989
13441
|
}
|
|
12990
|
-
async squashAndMergeWorktreeToMain(projectPath, worktreePath, mainBranch, commitMessage) {
|
|
13442
|
+
async squashAndMergeWorktreeToMain(projectPath, worktreePath, mainBranch, commitMessage, baseCommit) {
|
|
12991
13443
|
const executedCommands = [];
|
|
12992
13444
|
let lastOutput = "";
|
|
12993
13445
|
try {
|
|
@@ -13003,8 +13455,8 @@ class WorktreeManager {
|
|
|
13003
13455
|
if (!commits.trim()) {
|
|
13004
13456
|
return;
|
|
13005
13457
|
}
|
|
13006
|
-
command = `git rebase ${mainBranch}`;
|
|
13007
|
-
executedCommands.push(
|
|
13458
|
+
command = baseCommit ? `git rebase --onto ${mainBranch} ${baseCommit}` : `git rebase ${mainBranch}`;
|
|
13459
|
+
executedCommands.push(`${command} (in ${worktreePath})`);
|
|
13008
13460
|
try {
|
|
13009
13461
|
const rebaseWorktreeResult = await execWithShellPath(command, {
|
|
13010
13462
|
cwd: worktreePath
|
|
@@ -13313,10 +13765,12 @@ Git output: ${err.stderr || err.stdout || err.message}`
|
|
|
13313
13765
|
*/
|
|
13314
13766
|
async hasUncommittedChanges(path2) {
|
|
13315
13767
|
try {
|
|
13316
|
-
const { stdout } = await execWithShellPath("git status --porcelain=v1", {
|
|
13768
|
+
const { stdout } = await execWithShellPath("git status --porcelain=v1 -z", {
|
|
13317
13769
|
cwd: path2
|
|
13318
13770
|
});
|
|
13319
|
-
|
|
13771
|
+
const filePaths = this.parseGitStatusEntries(stdout);
|
|
13772
|
+
const realChanges = filePaths.filter((filePath) => !this.isSymlinkPath(path2, filePath));
|
|
13773
|
+
return realChanges.length > 0;
|
|
13320
13774
|
} catch (error) {
|
|
13321
13775
|
logger.error("Failed to check for uncommitted changes:", error);
|
|
13322
13776
|
return false;
|
|
@@ -13408,7 +13862,7 @@ Git output: ${err.stderr || err.stdout || err.message}`
|
|
|
13408
13862
|
* Merge worktree to main branch with uncommitted changes support
|
|
13409
13863
|
* Returns MergeState for potential revert
|
|
13410
13864
|
*/
|
|
13411
|
-
async mergeWorktreeToMainWithUncommitted(projectPath, taskId, worktreePath, squash, commitMessage, targetBranch, symlinkFolders = []) {
|
|
13865
|
+
async mergeWorktreeToMainWithUncommitted(projectPath, taskId, worktreePath, squash, commitMessage, targetBranch, symlinkFolders = [], baseCommit) {
|
|
13412
13866
|
return await withLock(`git-merge-worktree-${worktreePath}`, async () => {
|
|
13413
13867
|
const timestamp = Date.now();
|
|
13414
13868
|
const worktreeStashId = `worktree-${taskId.length > 24 ? taskId.substring(24) : taskId}-merge-${timestamp}`;
|
|
@@ -13436,7 +13890,7 @@ Git output: ${err.stderr || err.stdout || err.message}`
|
|
|
13436
13890
|
if (!commitMessage) {
|
|
13437
13891
|
throw new Error("Commit message is required for squash merge");
|
|
13438
13892
|
}
|
|
13439
|
-
await this.squashAndMergeWorktreeToMain(projectPath, worktreePath, mainBranch, commitMessage);
|
|
13893
|
+
await this.squashAndMergeWorktreeToMain(projectPath, worktreePath, mainBranch, commitMessage, baseCommit);
|
|
13440
13894
|
} else {
|
|
13441
13895
|
await this.mergeWorktreeToMain(projectPath, worktreePath, mainBranch);
|
|
13442
13896
|
}
|
|
@@ -13490,10 +13944,15 @@ Git output: ${err.stderr || err.stdout || err.message}`
|
|
|
13490
13944
|
* Check if worktree has uncommitted changes or unmerged commits
|
|
13491
13945
|
* Returns information about unsaved work in the worktree
|
|
13492
13946
|
*/
|
|
13493
|
-
async checkWorktreeForUnmergedWork(projectPath, worktreePath, targetBranch) {
|
|
13947
|
+
async checkWorktreeForUnmergedWork(projectPath, worktreePath, targetBranch, symlinkFolders = []) {
|
|
13494
13948
|
try {
|
|
13495
|
-
const hasUncommittedChanges = await this.hasUncommittedChanges(worktreePath);
|
|
13496
13949
|
const { files: uncommittedFiles } = await this.getUncommittedFiles(worktreePath);
|
|
13950
|
+
const filteredUncommittedFiles = uncommittedFiles.filter((file) => {
|
|
13951
|
+
const pathPart = file.replace(/^..\s*/, "").trim();
|
|
13952
|
+
const normalizedPath = pathPart.replace(/\\/g, "/");
|
|
13953
|
+
return !symlinkFolders.some((folder) => normalizedPath.startsWith(`${folder}/`) || normalizedPath === folder);
|
|
13954
|
+
});
|
|
13955
|
+
const actualHasUncommittedChanges = filteredUncommittedFiles.length > 0;
|
|
13497
13956
|
const effectiveTargetBranch = targetBranch || await this.getProjectMainBranch(projectPath);
|
|
13498
13957
|
let unmergedCommitCount = 0;
|
|
13499
13958
|
let unmergedCommits = [];
|
|
@@ -13507,11 +13966,11 @@ Git output: ${err.stderr || err.stdout || err.message}`
|
|
|
13507
13966
|
}
|
|
13508
13967
|
const hasUnmergedCommits = unmergedCommitCount > 0;
|
|
13509
13968
|
return {
|
|
13510
|
-
hasUncommittedChanges,
|
|
13969
|
+
hasUncommittedChanges: actualHasUncommittedChanges,
|
|
13511
13970
|
hasUnmergedCommits,
|
|
13512
13971
|
unmergedCommitCount,
|
|
13513
13972
|
unmergedCommits,
|
|
13514
|
-
uncommittedFiles
|
|
13973
|
+
uncommittedFiles: filteredUncommittedFiles
|
|
13515
13974
|
};
|
|
13516
13975
|
} catch (error) {
|
|
13517
13976
|
logger.error("Failed to check worktree for unmerged work:", error);
|
|
@@ -13536,12 +13995,25 @@ Git output: ${err.stderr || err.stdout || err.message}`
|
|
|
13536
13995
|
const { stdout } = await execWithShellPath("git status --porcelain=v1 -z", {
|
|
13537
13996
|
cwd: worktreePath
|
|
13538
13997
|
});
|
|
13539
|
-
const
|
|
13998
|
+
const filePaths = this.parseGitStatusEntries(stdout);
|
|
13999
|
+
const files = filePaths.filter((filePath) => !this.isSymlinkPath(worktreePath, filePath));
|
|
13540
14000
|
return {
|
|
13541
14001
|
count: files.length,
|
|
13542
14002
|
files: Array.from(new Set(files))
|
|
13543
14003
|
};
|
|
13544
14004
|
}
|
|
14005
|
+
parseGitStatusEntries(stdout) {
|
|
14006
|
+
return stdout.split("\0").map((entry) => entry.substring(3).trim()).filter((filePath) => filePath.length > 0);
|
|
14007
|
+
}
|
|
14008
|
+
isSymlinkPath(cwd, filePath) {
|
|
14009
|
+
try {
|
|
14010
|
+
const fullPath = path.join(cwd, filePath);
|
|
14011
|
+
const stat = fs$1.lstatSync(fullPath);
|
|
14012
|
+
return stat.isSymbolicLink();
|
|
14013
|
+
} catch {
|
|
14014
|
+
return false;
|
|
14015
|
+
}
|
|
14016
|
+
}
|
|
13545
14017
|
/**
|
|
13546
14018
|
* Get updated files with per-commit and uncommitted diffs.
|
|
13547
14019
|
*
|
|
@@ -13553,13 +14025,17 @@ Git output: ${err.stderr || err.stdout || err.message}`
|
|
|
13553
14025
|
*/
|
|
13554
14026
|
async getUpdatedFiles(worktreePath, workingMode, mainBranch, groupMode = UpdatedFilesGroupMode.Grouped) {
|
|
13555
14027
|
try {
|
|
14028
|
+
let files;
|
|
13556
14029
|
if (workingMode === "worktree" && mainBranch) {
|
|
13557
14030
|
if (groupMode === UpdatedFilesGroupMode.Flat) {
|
|
13558
|
-
|
|
14031
|
+
files = await this.getWorktreeFlatUpdatedFiles(worktreePath, mainBranch);
|
|
14032
|
+
} else {
|
|
14033
|
+
files = await this.getWorktreeUpdatedFiles(worktreePath, mainBranch);
|
|
13559
14034
|
}
|
|
13560
|
-
|
|
14035
|
+
} else {
|
|
14036
|
+
files = await this.getNonWorktreeUpdatedFiles(worktreePath);
|
|
13561
14037
|
}
|
|
13562
|
-
return await this.
|
|
14038
|
+
return await this.markConflictingFiles(worktreePath, files);
|
|
13563
14039
|
} catch (error) {
|
|
13564
14040
|
logger.warn("Failed to get updated files:", error);
|
|
13565
14041
|
return [];
|
|
@@ -13799,6 +14275,20 @@ Git output: ${err.stderr || err.stdout || err.message}`
|
|
|
13799
14275
|
}
|
|
13800
14276
|
return fileDiffs;
|
|
13801
14277
|
}
|
|
14278
|
+
async markConflictingFiles(worktreePath, files) {
|
|
14279
|
+
try {
|
|
14280
|
+
const { stdout } = await execWithShellPath("git diff --name-only --diff-filter=U", { cwd: worktreePath });
|
|
14281
|
+
const unmergedFiles = new Set(
|
|
14282
|
+
stdout.split("\n").map((l) => l.trim()).filter((l) => l.length > 0)
|
|
14283
|
+
);
|
|
14284
|
+
if (unmergedFiles.size === 0) {
|
|
14285
|
+
return files;
|
|
14286
|
+
}
|
|
14287
|
+
return files.map((f) => unmergedFiles.has(f.path) ? { ...f, hasConflicts: true } : f);
|
|
14288
|
+
} catch {
|
|
14289
|
+
return files;
|
|
14290
|
+
}
|
|
14291
|
+
}
|
|
13802
14292
|
async restoreFile(worktreePath, filePath) {
|
|
13803
14293
|
try {
|
|
13804
14294
|
logger.info(`Restoring file: ${filePath}`, { worktreePath });
|
|
@@ -14166,6 +14656,7 @@ class Task {
|
|
|
14166
14656
|
};
|
|
14167
14657
|
this.taskDataPath = path.join(this.project.baseDir, AIDER_DESK_TASKS_DIR, this.taskId, "settings.json");
|
|
14168
14658
|
this.contextManager = new ContextManager(this, this.taskId);
|
|
14659
|
+
this.skillManager = new SkillManager(project.baseDir, extensionManager);
|
|
14169
14660
|
this.agent = new Agent(
|
|
14170
14661
|
this.store,
|
|
14171
14662
|
this.agentProfileManager,
|
|
@@ -14211,6 +14702,7 @@ class Task {
|
|
|
14211
14702
|
contextManager;
|
|
14212
14703
|
agent;
|
|
14213
14704
|
aiderManager;
|
|
14705
|
+
skillManager;
|
|
14214
14706
|
task;
|
|
14215
14707
|
async getTaskAgentProfile() {
|
|
14216
14708
|
let agentProfileId = this.task.agentProfileId;
|
|
@@ -14264,10 +14756,56 @@ class Task {
|
|
|
14264
14756
|
* Generate a branch name from task name (first 7 words, separated by '-')
|
|
14265
14757
|
*/
|
|
14266
14758
|
generateBranchName() {
|
|
14759
|
+
const settings = this.store.getSettings();
|
|
14760
|
+
const branchPrefix = settings.taskSettings.worktreeBranchPrefix || WORKTREE_BRANCH_PREFIX;
|
|
14267
14761
|
const words = this.task.name.toLowerCase().replace(/[^a-z0-9\s-]/g, "").split(/\s+/).filter((word) => word.length > 0).slice(0, 7);
|
|
14268
14762
|
const branchName = words.join("-");
|
|
14269
14763
|
const cleanBranchName = branchName.replace(/^[.-]+/, "").replace(/-+/g, "-").replace(/-$/, "");
|
|
14270
|
-
|
|
14764
|
+
const fallbackId = /^[0-9a-f]{8}-/i.test(this.taskId) ? this.taskId.split("-")[0] : this.taskId;
|
|
14765
|
+
return `${branchPrefix}${cleanBranchName || fallbackId}`;
|
|
14766
|
+
}
|
|
14767
|
+
async renameWorktreeBranchIfNeeded() {
|
|
14768
|
+
if (this.task.workingMode !== "worktree" || !this.task.worktree?.branch) {
|
|
14769
|
+
return;
|
|
14770
|
+
}
|
|
14771
|
+
const settings = this.store.getSettings();
|
|
14772
|
+
if (!settings.taskSettings.renameBranchOnNameGeneration) {
|
|
14773
|
+
return;
|
|
14774
|
+
}
|
|
14775
|
+
const oldBranch = this.task.worktree.branch;
|
|
14776
|
+
const newBranch = this.generateBranchName();
|
|
14777
|
+
if (oldBranch === newBranch) {
|
|
14778
|
+
return;
|
|
14779
|
+
}
|
|
14780
|
+
await this.renameWorktreeBranch(newBranch);
|
|
14781
|
+
}
|
|
14782
|
+
/**
|
|
14783
|
+
* @deprecated This migration ensures older task data has the `branch` field
|
|
14784
|
+
* and `baseBranch` stores the branch the worktree was created from.
|
|
14785
|
+
* Can be removed once all users have migrated past v0.64.0.
|
|
14786
|
+
*/
|
|
14787
|
+
async migrateWorktreeData() {
|
|
14788
|
+
if (!this.task.worktree || this.task.worktree.branch) {
|
|
14789
|
+
return;
|
|
14790
|
+
}
|
|
14791
|
+
const currentBranch = this.task.worktree.baseBranch;
|
|
14792
|
+
this.task.worktree.branch = currentBranch;
|
|
14793
|
+
let resolvedBase = "";
|
|
14794
|
+
if (this.task.worktree.baseCommit) {
|
|
14795
|
+
const branches = await this.worktreeManager.getBranchesContainingCommit(this.project.baseDir, this.task.worktree.baseCommit);
|
|
14796
|
+
if (branches.length === 1) {
|
|
14797
|
+
resolvedBase = branches[0];
|
|
14798
|
+
}
|
|
14799
|
+
}
|
|
14800
|
+
if (!resolvedBase) {
|
|
14801
|
+
try {
|
|
14802
|
+
resolvedBase = await this.worktreeManager.getProjectMainBranch(this.project.baseDir);
|
|
14803
|
+
} catch {
|
|
14804
|
+
resolvedBase = "";
|
|
14805
|
+
}
|
|
14806
|
+
}
|
|
14807
|
+
this.task.worktree.baseBranch = resolvedBase || void 0;
|
|
14808
|
+
await this.saveTask({ worktree: this.task.worktree });
|
|
14271
14809
|
}
|
|
14272
14810
|
isInternal() {
|
|
14273
14811
|
return this.taskId === INTERNAL_TASK_ID;
|
|
@@ -14343,14 +14881,18 @@ class Task {
|
|
|
14343
14881
|
worktreePath: this.task.worktree.path
|
|
14344
14882
|
});
|
|
14345
14883
|
} else {
|
|
14346
|
-
|
|
14347
|
-
this.task.worktree = await this.worktreeManager.createWorktree(this.project.baseDir, this.taskId, branchName);
|
|
14884
|
+
await this.initWorktree();
|
|
14348
14885
|
void this.sendUpdatedFilesUpdated();
|
|
14886
|
+
void this.sendWorktreeIntegrationStatusUpdated();
|
|
14349
14887
|
}
|
|
14350
14888
|
} else if (workingMode === "local") {
|
|
14351
14889
|
if (existingWorktree) {
|
|
14352
|
-
|
|
14890
|
+
const isShared = this.project.isWorktreeSharedWithOtherTasks(existingWorktree.path, this.taskId);
|
|
14891
|
+
if (!isShared) {
|
|
14892
|
+
await this.worktreeManager.removeWorktree(this.project.baseDir, existingWorktree);
|
|
14893
|
+
}
|
|
14353
14894
|
void this.sendUpdatedFilesUpdated();
|
|
14895
|
+
void this.sendWorktreeIntegrationStatusUpdated();
|
|
14354
14896
|
}
|
|
14355
14897
|
} else {
|
|
14356
14898
|
logger.debug("Empty workingMode, setting to local", {
|
|
@@ -14367,6 +14909,7 @@ class Task {
|
|
|
14367
14909
|
this.task.workingMode = "local";
|
|
14368
14910
|
}
|
|
14369
14911
|
}
|
|
14912
|
+
await this.migrateWorktreeData();
|
|
14370
14913
|
if (await fileExists(this.getTaskDir())) {
|
|
14371
14914
|
this.git = simpleGit.simpleGit(this.getTaskDir());
|
|
14372
14915
|
}
|
|
@@ -14741,7 +15284,9 @@ class Task {
|
|
|
14741
15284
|
await this.saveTask({
|
|
14742
15285
|
name: this.task.name || this.getTaskNameFromPrompt(prompt || ""),
|
|
14743
15286
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
14744
|
-
state: DefaultTaskState.InProgress
|
|
15287
|
+
state: DefaultTaskState.InProgress,
|
|
15288
|
+
provider: this.task.provider || profile.provider,
|
|
15289
|
+
model: this.task.model || profile.model
|
|
14745
15290
|
});
|
|
14746
15291
|
const agentMessages = await this.agent.runAgent(this, profile, prompt, mode, promptContext, contextMessages, contextFiles, systemPrompt);
|
|
14747
15292
|
if (agentMessages.length > 0) {
|
|
@@ -14752,6 +15297,7 @@ class Task {
|
|
|
14752
15297
|
void this.sendRequestContextInfo();
|
|
14753
15298
|
void this.sendWorktreeIntegrationStatusUpdated();
|
|
14754
15299
|
void this.sendUpdatedFilesUpdated();
|
|
15300
|
+
void this.sendSkillsUpdated();
|
|
14755
15301
|
this.resolveAgentRunPromises();
|
|
14756
15302
|
if (waitForCurrentAgentToFinish) {
|
|
14757
15303
|
await this.runNextQueuedPrompt();
|
|
@@ -14782,14 +15328,11 @@ class Task {
|
|
|
14782
15328
|
const settings = this.store.getSettings();
|
|
14783
15329
|
if (settings.taskSettings.autoGenerateTaskName) {
|
|
14784
15330
|
this.generateTaskNameInBackground(prompt).then((taskName) => {
|
|
14785
|
-
|
|
14786
|
-
|
|
14787
|
-
} else {
|
|
14788
|
-
void this.saveTask({ name: fallbackName });
|
|
14789
|
-
}
|
|
15331
|
+
const newName = taskName || fallbackName;
|
|
15332
|
+
void this.saveTask({ name: newName }).then(() => this.renameWorktreeBranchIfNeeded());
|
|
14790
15333
|
}).catch((error) => {
|
|
14791
15334
|
logger.warn("Failed to generate task name:", error);
|
|
14792
|
-
void this.saveTask({ name: fallbackName });
|
|
15335
|
+
void this.saveTask({ name: fallbackName }).then(() => this.renameWorktreeBranchIfNeeded());
|
|
14793
15336
|
});
|
|
14794
15337
|
return "<<generating>>";
|
|
14795
15338
|
} else {
|
|
@@ -15565,10 +16108,10 @@ ${contentText}</agent-response>`;
|
|
|
15565
16108
|
return contextFiles;
|
|
15566
16109
|
}
|
|
15567
16110
|
const profile = await this.getTaskAgentProfile();
|
|
15568
|
-
const ruleFiles = await this.getRuleFilesAsContextFiles(profile || void 0);
|
|
16111
|
+
const ruleFiles = await this.getRuleFilesAsContextFiles(profile || void 0, true);
|
|
15569
16112
|
return [...contextFiles, ...ruleFiles];
|
|
15570
16113
|
}
|
|
15571
|
-
async getRuleFilesAsContextFiles(profile) {
|
|
16114
|
+
async getRuleFilesAsContextFiles(profile, includeDisabled = false) {
|
|
15572
16115
|
const ruleFiles = [];
|
|
15573
16116
|
const homeDir = os.homedir();
|
|
15574
16117
|
if (await fileExists(AIDER_DESK_GLOBAL_RULES_DIR)) {
|
|
@@ -15639,7 +16182,8 @@ ${contentText}</agent-response>`;
|
|
|
15639
16182
|
}
|
|
15640
16183
|
}
|
|
15641
16184
|
const extensionResult = await this.extensionManager.dispatchEvent("onRuleFilesRetrieved", { files: ruleFiles }, this.project, this);
|
|
15642
|
-
|
|
16185
|
+
const disabledRuleFiles = this.project.getProjectSettings().disabledRuleFiles ?? [];
|
|
16186
|
+
return includeDisabled ? extensionResult.files : extensionResult.files.filter((f) => !disabledRuleFiles.includes(f.path));
|
|
15643
16187
|
}
|
|
15644
16188
|
getRepoMap() {
|
|
15645
16189
|
return this.aiderManager.getRepoMap();
|
|
@@ -15668,6 +16212,92 @@ ${contentText}</agent-response>`;
|
|
|
15668
16212
|
getContextMessages() {
|
|
15669
16213
|
return this.contextManager.getContextMessages();
|
|
15670
16214
|
}
|
|
16215
|
+
getSkillManager() {
|
|
16216
|
+
return this.skillManager;
|
|
16217
|
+
}
|
|
16218
|
+
async getSkills() {
|
|
16219
|
+
const contextMessages = await this.contextManager.getContextMessages();
|
|
16220
|
+
return this.skillManager.getSkills(contextMessages);
|
|
16221
|
+
}
|
|
16222
|
+
async activateSkill(skillName) {
|
|
16223
|
+
const contextMessages = await this.contextManager.getContextMessages();
|
|
16224
|
+
const activatedNames = this.skillManager.getActivatedSkillNames(contextMessages);
|
|
16225
|
+
if (activatedNames.has(skillName)) {
|
|
16226
|
+
logger.debug("Skill already activated, skipping", { skillName });
|
|
16227
|
+
return;
|
|
16228
|
+
}
|
|
16229
|
+
const content = await this.skillManager.getSkillContent(skillName);
|
|
16230
|
+
if (!content) {
|
|
16231
|
+
throw new Error(`Skill '${skillName}' not found`);
|
|
16232
|
+
}
|
|
16233
|
+
const [assistantMessage, toolMessage] = this.skillManager.buildActivateSkillMessages(skillName, content);
|
|
16234
|
+
this.contextManager.addContextMessage(assistantMessage);
|
|
16235
|
+
this.contextManager.addContextMessage(toolMessage);
|
|
16236
|
+
await this.processResponseMessage(
|
|
16237
|
+
{
|
|
16238
|
+
id: assistantMessage.id,
|
|
16239
|
+
action: "response",
|
|
16240
|
+
content: "User requested the skill activation.",
|
|
16241
|
+
finished: true
|
|
16242
|
+
},
|
|
16243
|
+
false
|
|
16244
|
+
);
|
|
16245
|
+
const toolCallId = toolMessage.content[0].toolCallId;
|
|
16246
|
+
this.addToolMessage(
|
|
16247
|
+
toolCallId,
|
|
16248
|
+
SKILLS_TOOL_GROUP_NAME,
|
|
16249
|
+
SKILLS_TOOL_ACTIVATE_SKILL,
|
|
16250
|
+
{ skill: skillName },
|
|
16251
|
+
JSON.stringify(content),
|
|
16252
|
+
void 0,
|
|
16253
|
+
void 0,
|
|
16254
|
+
false,
|
|
16255
|
+
true
|
|
16256
|
+
);
|
|
16257
|
+
await this.updateContextInfo();
|
|
16258
|
+
}
|
|
16259
|
+
async deactivateSkill(skillName) {
|
|
16260
|
+
const contextMessages = await this.contextManager.getContextMessages();
|
|
16261
|
+
const toolName = `${SKILLS_TOOL_GROUP_NAME}${TOOL_GROUP_NAME_SEPARATOR}${SKILLS_TOOL_ACTIVATE_SKILL}`;
|
|
16262
|
+
for (let i = contextMessages.length - 1; i >= 0; i--) {
|
|
16263
|
+
const message = contextMessages[i];
|
|
16264
|
+
if (message.role === "assistant" && Array.isArray(message.content)) {
|
|
16265
|
+
const toolCallPart = message.content.find(
|
|
16266
|
+
(part) => part.type === "tool-call" && part.toolName === toolName && part.input?.skill === skillName
|
|
16267
|
+
);
|
|
16268
|
+
if (!toolCallPart || toolCallPart.type !== "tool-call") {
|
|
16269
|
+
continue;
|
|
16270
|
+
}
|
|
16271
|
+
const toolCallId = toolCallPart.toolCallId;
|
|
16272
|
+
const toolMessage = contextMessages.find(
|
|
16273
|
+
(msg) => msg.role === "tool" && Array.isArray(msg.content) && msg.content.some((part) => part.type === "tool-result" && part.toolCallId === toolCallId)
|
|
16274
|
+
);
|
|
16275
|
+
const removedIds = [];
|
|
16276
|
+
const idsToRemoveFromContext = [];
|
|
16277
|
+
if (toolMessage) {
|
|
16278
|
+
removedIds.push(toolMessage.id);
|
|
16279
|
+
removedIds.push(toolCallId);
|
|
16280
|
+
idsToRemoveFromContext.push(toolMessage.id);
|
|
16281
|
+
}
|
|
16282
|
+
const otherToolCalls = message.content.filter((part) => part.type === "tool-call" && part !== toolCallPart);
|
|
16283
|
+
if (otherToolCalls.length > 0) {
|
|
16284
|
+
this.contextManager.removeMessageById(toolCallId);
|
|
16285
|
+
} else {
|
|
16286
|
+
removedIds.push(message.id);
|
|
16287
|
+
idsToRemoveFromContext.push(message.id);
|
|
16288
|
+
this.contextManager.removeMessagesByIds(idsToRemoveFromContext);
|
|
16289
|
+
}
|
|
16290
|
+
if (removedIds.length > 0) {
|
|
16291
|
+
await this.reloadConnectorMessages();
|
|
16292
|
+
await this.updateContextInfo();
|
|
16293
|
+
void this.sendSkillsUpdated();
|
|
16294
|
+
}
|
|
16295
|
+
return removedIds;
|
|
16296
|
+
}
|
|
16297
|
+
}
|
|
16298
|
+
logger.debug(`No activation found for skill '${skillName}' to deactivate.`);
|
|
16299
|
+
return [];
|
|
16300
|
+
}
|
|
15671
16301
|
async addRoleContextMessage(role, content, usageReport) {
|
|
15672
16302
|
logger.debug("Adding role message to session:", {
|
|
15673
16303
|
baseDir: this.project.baseDir,
|
|
@@ -15948,12 +16578,18 @@ ${contentText}</agent-response>`;
|
|
|
15948
16578
|
const removedIds = this.contextManager.removeMessageById(messageId);
|
|
15949
16579
|
await this.reloadConnectorMessages();
|
|
15950
16580
|
await this.updateContextInfo();
|
|
16581
|
+
if (removedIds.length > 0) {
|
|
16582
|
+
void this.sendSkillsUpdated();
|
|
16583
|
+
}
|
|
15951
16584
|
return removedIds;
|
|
15952
16585
|
}
|
|
15953
16586
|
async removeMessagesUpTo(messageId) {
|
|
15954
16587
|
const removedIds = this.contextManager.removeMessagesAfter(messageId);
|
|
15955
16588
|
await this.reloadConnectorMessages();
|
|
15956
16589
|
await this.updateContextInfo();
|
|
16590
|
+
if (removedIds.length > 0) {
|
|
16591
|
+
void this.sendSkillsUpdated();
|
|
16592
|
+
}
|
|
15957
16593
|
return removedIds;
|
|
15958
16594
|
}
|
|
15959
16595
|
sendTaskMessageRemoved(messageIds) {
|
|
@@ -15961,26 +16597,27 @@ ${contentText}</agent-response>`;
|
|
|
15961
16597
|
this.eventManager.sendTaskMessageRemoved(this.project.baseDir, this.taskId, messageIds);
|
|
15962
16598
|
}
|
|
15963
16599
|
}
|
|
15964
|
-
async
|
|
15965
|
-
logger.info("Redoing
|
|
16600
|
+
async redoUserPrompt(messageId, mode, updatedPrompt) {
|
|
16601
|
+
logger.info("Redoing user prompt:", {
|
|
15966
16602
|
baseDir: this.project.baseDir,
|
|
16603
|
+
messageId,
|
|
15967
16604
|
mode,
|
|
15968
16605
|
hasUpdatedPrompt: !!updatedPrompt
|
|
15969
16606
|
});
|
|
15970
|
-
const removedMessages = this.contextManager.
|
|
15971
|
-
const
|
|
15972
|
-
if (!
|
|
15973
|
-
logger.warn("Could not find
|
|
16607
|
+
const removedMessages = this.contextManager.removeMessagesUpToUserMessage(messageId);
|
|
16608
|
+
const originalUserMessage = removedMessages[0];
|
|
16609
|
+
if (!originalUserMessage || originalUserMessage.role !== MessageRole.User) {
|
|
16610
|
+
logger.warn("Could not find the specified user message to redo.", { messageId });
|
|
15974
16611
|
return;
|
|
15975
16612
|
}
|
|
15976
|
-
const promptToRun = updatedPrompt ??
|
|
16613
|
+
const promptToRun = updatedPrompt ?? originalUserMessage.content;
|
|
15977
16614
|
if (promptToRun) {
|
|
15978
16615
|
logger.info("Found message content to run, reloading and re-running prompt.", {
|
|
15979
16616
|
remainingMessagesCount: (await this.contextManager.getContextMessages()).length
|
|
15980
16617
|
});
|
|
15981
|
-
this.sendTaskMessageRemoved(removedMessages.slice(
|
|
16618
|
+
this.sendTaskMessageRemoved(removedMessages.slice(1).map((msg) => msg.id));
|
|
15982
16619
|
await this.updateContextInfo();
|
|
15983
|
-
void this.runPrompt(promptToRun, mode, false,
|
|
16620
|
+
void this.runPrompt(promptToRun, mode, false, originalUserMessage.id);
|
|
15984
16621
|
} else {
|
|
15985
16622
|
logger.warn("Could not find a previous user message to redo or an updated prompt to run.");
|
|
15986
16623
|
}
|
|
@@ -16007,7 +16644,7 @@ ${contentText}</agent-response>`;
|
|
|
16007
16644
|
if (lastMessage && lastMessage.role === MessageRole.User) {
|
|
16008
16645
|
logger.info("Last message is from user, redoing prompt");
|
|
16009
16646
|
this.addLogMessage("loading", "Resuming task...");
|
|
16010
|
-
void this.
|
|
16647
|
+
void this.redoUserPrompt(lastMessage.id, mode);
|
|
16011
16648
|
} else {
|
|
16012
16649
|
logger.info("Last message is not from user, sending Continue prompt");
|
|
16013
16650
|
void this.runPrompt("Continue", mode, false);
|
|
@@ -16320,12 +16957,16 @@ ${contentText}</agent-response>`;
|
|
|
16320
16957
|
const aiderWatchFilesChanged = oldSettings.aider.watchFiles !== newSettings?.aider.watchFiles;
|
|
16321
16958
|
const aiderCachingEnabledChanged = oldSettings.aider.cachingEnabled !== newSettings?.aider.cachingEnabled;
|
|
16322
16959
|
const aiderConfirmBeforeEditChanged = oldSettings.aider.confirmBeforeEdit !== newSettings?.aider.confirmBeforeEdit;
|
|
16960
|
+
const proxyChanged = oldSettings.proxy?.enabled !== newSettings.proxy?.enabled || oldSettings.proxy?.url !== newSettings.proxy?.url;
|
|
16323
16961
|
if ((aiderOptionsChanged || aiderAutoCommitsChanged || aiderWatchFilesChanged || aiderCachingEnabledChanged || aiderConfirmBeforeEditChanged) && await this.shouldStartAider()) {
|
|
16324
16962
|
logger.debug("Aider options changed, restarting Aider.");
|
|
16325
16963
|
void this.aiderManager.start(true);
|
|
16326
|
-
} else if (aiderEnvVarsChanged) {
|
|
16964
|
+
} else if (aiderEnvVarsChanged || proxyChanged) {
|
|
16327
16965
|
logger.debug("Aider environment variables changed, updating connectors.");
|
|
16328
|
-
const updatedEnvironmentVariables =
|
|
16966
|
+
const updatedEnvironmentVariables = {
|
|
16967
|
+
...getEnvironmentVariablesForAider(newSettings, this.project.baseDir),
|
|
16968
|
+
...getProxyEnvVars(newSettings)
|
|
16969
|
+
};
|
|
16329
16970
|
this.sendUpdateEnvVars(updatedEnvironmentVariables);
|
|
16330
16971
|
}
|
|
16331
16972
|
}
|
|
@@ -16335,9 +16976,13 @@ ${contentText}</agent-response>`;
|
|
|
16335
16976
|
async projectSettingsChanged(oldSettings, newSettings) {
|
|
16336
16977
|
const modeChanged = oldSettings.currentMode !== newSettings.currentMode;
|
|
16337
16978
|
const agentProfileIdChanged = oldSettings.agentProfileId !== newSettings.agentProfileId;
|
|
16338
|
-
|
|
16979
|
+
const disabledRulesChanged = JSON.stringify(oldSettings.disabledRuleFiles) !== JSON.stringify(newSettings.disabledRuleFiles);
|
|
16980
|
+
if (agentProfileIdChanged || modeChanged || disabledRulesChanged) {
|
|
16339
16981
|
void this.sendContextFilesUpdated();
|
|
16340
16982
|
}
|
|
16983
|
+
if (disabledRulesChanged) {
|
|
16984
|
+
void this.updateAgentEstimatedTokens();
|
|
16985
|
+
}
|
|
16341
16986
|
}
|
|
16342
16987
|
sendUpdateEnvVars(environmentVariables) {
|
|
16343
16988
|
this.aiderManager.sendUpdateEnvVars(environmentVariables);
|
|
@@ -16614,6 +17259,18 @@ ${error.stderr}`,
|
|
|
16614
17259
|
});
|
|
16615
17260
|
this.eventManager.sendUpdatedFilesUpdated(this.project.baseDir, this.taskId, updatedFiles);
|
|
16616
17261
|
}
|
|
17262
|
+
async sendSkillsUpdated() {
|
|
17263
|
+
const skills = await this.getSkills();
|
|
17264
|
+
this.eventManager.sendSkillsUpdated(this.project.baseDir, this.taskId, skills);
|
|
17265
|
+
}
|
|
17266
|
+
async initWorktree() {
|
|
17267
|
+
const branchName = this.generateBranchName();
|
|
17268
|
+
this.task.worktree = await this.worktreeManager.createWorktree(this.project.baseDir, this.taskId, branchName);
|
|
17269
|
+
const settings = this.store.getSettings();
|
|
17270
|
+
if (settings.taskSettings.worktreeSymlinkFolders && settings.taskSettings.worktreeSymlinkFolders.length > 0) {
|
|
17271
|
+
await this.worktreeManager.createSymlinks(this.project.baseDir, this.task.worktree.path, settings.taskSettings.worktreeSymlinkFolders);
|
|
17272
|
+
}
|
|
17273
|
+
}
|
|
16617
17274
|
async applyWorkingMode(mode) {
|
|
16618
17275
|
logger.info("Applying workingMode configuration", {
|
|
16619
17276
|
baseDir: this.project.baseDir,
|
|
@@ -16624,17 +17281,15 @@ ${error.stderr}`,
|
|
|
16624
17281
|
const currentWorktree = await this.worktreeManager.getTaskWorktree(this.project.baseDir, this.taskId);
|
|
16625
17282
|
if (mode === "worktree") {
|
|
16626
17283
|
if (!currentWorktree) {
|
|
16627
|
-
|
|
16628
|
-
this.task.worktree = await this.worktreeManager.createWorktree(this.project.baseDir, this.taskId, branchName);
|
|
16629
|
-
const settings = this.store.getSettings();
|
|
16630
|
-
if (settings.taskSettings.worktreeSymlinkFolders && settings.taskSettings.worktreeSymlinkFolders.length > 0) {
|
|
16631
|
-
await this.worktreeManager.createSymlinks(this.project.baseDir, this.task.worktree.path, settings.taskSettings.worktreeSymlinkFolders);
|
|
16632
|
-
}
|
|
17284
|
+
await this.initWorktree();
|
|
16633
17285
|
}
|
|
16634
17286
|
this.task.workingMode = mode;
|
|
16635
17287
|
} else if (mode === "local") {
|
|
16636
17288
|
if (currentWorktree) {
|
|
16637
|
-
|
|
17289
|
+
const isShared = this.project.isWorktreeSharedWithOtherTasks(currentWorktree.path, this.taskId);
|
|
17290
|
+
if (!isShared) {
|
|
17291
|
+
await this.worktreeManager.removeWorktree(this.project.baseDir, currentWorktree);
|
|
17292
|
+
}
|
|
16638
17293
|
}
|
|
16639
17294
|
this.task.worktree = void 0;
|
|
16640
17295
|
this.task.lastMergeState = void 0;
|
|
@@ -16706,7 +17361,8 @@ Only answer with the commit message, nothing else.`,
|
|
|
16706
17361
|
squash,
|
|
16707
17362
|
effectiveCommitMessage || this.task.name || `Task ${this.taskId} changes`,
|
|
16708
17363
|
targetBranch,
|
|
16709
|
-
symlinkFolders
|
|
17364
|
+
symlinkFolders,
|
|
17365
|
+
this.task.worktree.baseCommit
|
|
16710
17366
|
);
|
|
16711
17367
|
await this.saveTask({ lastMergeState: mergeState });
|
|
16712
17368
|
this.addLogMessage(
|
|
@@ -16728,6 +17384,47 @@ Only answer with the commit message, nothing else.`,
|
|
|
16728
17384
|
await this.sendUpdatedFilesUpdated();
|
|
16729
17385
|
await this.sendWorktreeIntegrationStatusUpdated();
|
|
16730
17386
|
}
|
|
17387
|
+
async mergeAndSwitchToLocal(targetBranch) {
|
|
17388
|
+
if (!this.task.worktree) {
|
|
17389
|
+
throw new Error("No worktree exists for this task");
|
|
17390
|
+
}
|
|
17391
|
+
logger.info("Merging worktree and switching to local mode", {
|
|
17392
|
+
baseDir: this.project.baseDir,
|
|
17393
|
+
taskId: this.taskId
|
|
17394
|
+
});
|
|
17395
|
+
await this.waitForCurrentPromptToFinish();
|
|
17396
|
+
try {
|
|
17397
|
+
const effectiveTargetBranch = targetBranch || await this.worktreeManager.getProjectMainBranch(this.project.baseDir);
|
|
17398
|
+
this.addLogMessage("loading", `Merging worktree to ${effectiveTargetBranch} branch and switching to local mode...`);
|
|
17399
|
+
const settings = this.store.getSettings();
|
|
17400
|
+
const symlinkFolders = settings.taskSettings.worktreeSymlinkFolders || [];
|
|
17401
|
+
const mergeState = await this.worktreeManager.mergeWorktreeToMainWithUncommitted(
|
|
17402
|
+
this.project.baseDir,
|
|
17403
|
+
this.task.id,
|
|
17404
|
+
this.task.worktree.path,
|
|
17405
|
+
false,
|
|
17406
|
+
this.task.name || `Task ${this.taskId} changes`,
|
|
17407
|
+
targetBranch,
|
|
17408
|
+
symlinkFolders
|
|
17409
|
+
);
|
|
17410
|
+
await this.saveTask({ lastMergeState: mergeState });
|
|
17411
|
+
this.addLogMessage("info", `Successfully merged worktree to ${effectiveTargetBranch} branch`, true);
|
|
17412
|
+
await this.updateTask({ workingMode: "local" });
|
|
17413
|
+
} catch (error) {
|
|
17414
|
+
logger.error("Failed to merge worktree and switch to local:", { error });
|
|
17415
|
+
const isConflict = error instanceof GitError && (error.gitOutput?.toLowerCase().includes("resolve all conflicts") || error.message?.toLowerCase().includes("conflicts must be resolved first") || error.gitOutput?.toLowerCase().includes("conflicts must be resolved first"));
|
|
17416
|
+
this.addLogMessage(
|
|
17417
|
+
"error",
|
|
17418
|
+
isConflict ? "worktree.mergeConflicts" : error instanceof GitError ? error.getErrorDetails() : `Failed to merge worktree: ${error instanceof Error ? error.message : String(error)}`,
|
|
17419
|
+
true,
|
|
17420
|
+
void 0,
|
|
17421
|
+
isConflict ? ["rebase-worktree"] : void 0
|
|
17422
|
+
);
|
|
17423
|
+
await this.sendUpdatedFilesUpdated();
|
|
17424
|
+
await this.sendWorktreeIntegrationStatusUpdated();
|
|
17425
|
+
throw error;
|
|
17426
|
+
}
|
|
17427
|
+
}
|
|
16731
17428
|
async applyUncommittedChanges(targetBranch) {
|
|
16732
17429
|
if (!this.task.worktree) {
|
|
16733
17430
|
throw new Error("No worktree exists for this task");
|
|
@@ -16857,10 +17554,18 @@ ${diff}
|
|
|
16857
17554
|
taskId: this.taskId,
|
|
16858
17555
|
amend
|
|
16859
17556
|
});
|
|
17557
|
+
const beforeResult = await this.extensionManager.dispatchEvent("onBeforeCommit", { message, amend }, this.project, this);
|
|
17558
|
+
if (beforeResult.blocked) {
|
|
17559
|
+
logger.debug("Commit blocked by extension");
|
|
17560
|
+
return;
|
|
17561
|
+
}
|
|
17562
|
+
message = beforeResult.message;
|
|
17563
|
+
amend = beforeResult.amend;
|
|
16860
17564
|
const taskDir = this.getTaskDir();
|
|
16861
17565
|
await this.worktreeManager.commitChanges(taskDir, message, amend);
|
|
16862
17566
|
await this.sendUpdatedFilesUpdated();
|
|
16863
17567
|
await this.sendWorktreeIntegrationStatusUpdated();
|
|
17568
|
+
await this.extensionManager.dispatchEvent("onAfterCommit", { message, amend }, this.project, this);
|
|
16864
17569
|
}
|
|
16865
17570
|
async getWorktreeIntegrationStatus(targetBranch) {
|
|
16866
17571
|
if (!this.task.worktree) {
|
|
@@ -16868,12 +17573,16 @@ ${diff}
|
|
|
16868
17573
|
}
|
|
16869
17574
|
const effectiveTargetBranch = targetBranch || await this.worktreeManager.getProjectMainBranch(this.project.baseDir);
|
|
16870
17575
|
const worktreePath = this.task.worktree.path;
|
|
17576
|
+
const settings = this.store.getSettings();
|
|
17577
|
+
const symlinkFolders = settings.taskSettings.worktreeSymlinkFolders || [];
|
|
16871
17578
|
const [unmergedWork, predictedConflicts, rebaseState] = await Promise.all([
|
|
16872
|
-
this.worktreeManager.checkWorktreeForUnmergedWork(this.project.baseDir, worktreePath, effectiveTargetBranch),
|
|
17579
|
+
this.worktreeManager.checkWorktreeForUnmergedWork(this.project.baseDir, worktreePath, effectiveTargetBranch, symlinkFolders),
|
|
16873
17580
|
this.worktreeManager.checkForRebaseConflicts(worktreePath, effectiveTargetBranch),
|
|
16874
17581
|
this.worktreeManager.getRebaseState(worktreePath)
|
|
16875
17582
|
]);
|
|
16876
17583
|
return {
|
|
17584
|
+
currentBranch: this.task.worktree.branch || "",
|
|
17585
|
+
baseBranch: this.task.worktree.baseBranch || "",
|
|
16877
17586
|
targetBranch: effectiveTargetBranch,
|
|
16878
17587
|
aheadCommits: {
|
|
16879
17588
|
count: unmergedWork.unmergedCommitCount,
|
|
@@ -16900,22 +17609,24 @@ ${diff}
|
|
|
16900
17609
|
await this.waitForCurrentPromptToFinish();
|
|
16901
17610
|
try {
|
|
16902
17611
|
this.addLogMessage("loading", `Rebasing worktree from ${effectiveFromBranch}...`);
|
|
16903
|
-
const { success, error } = await this.worktreeManager.rebaseMainIntoWorktree(this.task.worktree.path, effectiveFromBranch);
|
|
17612
|
+
const { success, error } = await this.worktreeManager.rebaseMainIntoWorktree(this.task.worktree.path, effectiveFromBranch, this.task.worktree.baseCommit);
|
|
16904
17613
|
if (success) {
|
|
17614
|
+
const newHead = await this.worktreeManager.getHeadCommit(this.task.worktree.path);
|
|
17615
|
+
if (newHead) {
|
|
17616
|
+
await this.saveTask({ worktree: { ...this.task.worktree, baseCommit: newHead, baseBranch: effectiveFromBranch } });
|
|
17617
|
+
}
|
|
16905
17618
|
this.addLogMessage("info", "Worktree rebased successfully", true);
|
|
16906
17619
|
return;
|
|
16907
17620
|
}
|
|
16908
17621
|
if (error) {
|
|
17622
|
+
this.addLogMessage("loading", void 0, true);
|
|
16909
17623
|
const isConflict = error.gitOutput?.includes("Resolve all conflicts");
|
|
16910
|
-
|
|
16911
|
-
"error",
|
|
16912
|
-
|
|
16913
|
-
true,
|
|
16914
|
-
void 0,
|
|
16915
|
-
isConflict ? ["abort-rebase", "resolve-conflicts-with-agent"] : void 0
|
|
16916
|
-
);
|
|
17624
|
+
if (!isConflict) {
|
|
17625
|
+
this.addLogMessage("error", error.getErrorDetails(), true);
|
|
17626
|
+
}
|
|
16917
17627
|
}
|
|
16918
17628
|
} catch (error) {
|
|
17629
|
+
this.addLogMessage("loading", void 0, true);
|
|
16919
17630
|
logger.error("Failed to rebase worktree:", {
|
|
16920
17631
|
error: error instanceof Error ? error.message : String(error)
|
|
16921
17632
|
});
|
|
@@ -16944,11 +17655,26 @@ ${diff}
|
|
|
16944
17655
|
await this.sendUpdatedFilesUpdated();
|
|
16945
17656
|
await this.sendWorktreeIntegrationStatusUpdated();
|
|
16946
17657
|
}
|
|
17658
|
+
async renameWorktreeBranch(newBranchName) {
|
|
17659
|
+
if (!this.task.worktree) {
|
|
17660
|
+
throw new Error("No worktree exists for this task");
|
|
17661
|
+
}
|
|
17662
|
+
const oldBranchName = this.task.worktree.branch;
|
|
17663
|
+
if (!oldBranchName) {
|
|
17664
|
+
throw new Error("Cannot determine current branch name");
|
|
17665
|
+
}
|
|
17666
|
+
const actualBranchName = await this.worktreeManager.renameBranch(this.project.baseDir, oldBranchName, newBranchName);
|
|
17667
|
+
this.task.worktree.branch = actualBranchName;
|
|
17668
|
+
await this.saveTask({ worktree: this.task.worktree });
|
|
17669
|
+
void this.sendWorktreeIntegrationStatusUpdated();
|
|
17670
|
+
}
|
|
16947
17671
|
async executeConflictResolution(directoryPath, directoryName) {
|
|
16948
17672
|
const activeProfile = await this.getTaskAgentProfile();
|
|
16949
17673
|
if (!activeProfile) {
|
|
16950
17674
|
throw new Error("No active agent profile found");
|
|
16951
17675
|
}
|
|
17676
|
+
const previousTaskState = this.task.state;
|
|
17677
|
+
await this.saveTask({ state: DefaultTaskState.InProgress });
|
|
16952
17678
|
try {
|
|
16953
17679
|
this.addLogMessage("loading", `Resolving conflicts in ${directoryName}...`);
|
|
16954
17680
|
const files = await this.worktreeManager.listConflictedFiles(directoryPath);
|
|
@@ -17033,13 +17759,8 @@ ${diff}
|
|
|
17033
17759
|
}
|
|
17034
17760
|
});
|
|
17035
17761
|
await Promise.all(resolutionPromises);
|
|
17036
|
-
if (interruptedCount
|
|
17037
|
-
this.addLogMessage("
|
|
17038
|
-
} else if (interruptedCount < files.length) {
|
|
17039
|
-
this.addLogMessage("warning", "Some conflicts were resolved, but some were interrupted. You can continue the rebase.", true, void 0, [
|
|
17040
|
-
"continue-rebase",
|
|
17041
|
-
"abort-rebase"
|
|
17042
|
-
]);
|
|
17762
|
+
if (interruptedCount > 0 && interruptedCount < files.length) {
|
|
17763
|
+
this.addLogMessage("warning", "Some conflicts were resolved, but some were interrupted. You can continue the rebase.", true, void 0, []);
|
|
17043
17764
|
}
|
|
17044
17765
|
} catch (error) {
|
|
17045
17766
|
logger.error("Failed to resolve conflicts with agent:", error);
|
|
@@ -17048,6 +17769,8 @@ ${diff}
|
|
|
17048
17769
|
error instanceof GitError ? error.getErrorDetails() : `Failed to resolve conflicts with agent: ${error instanceof Error ? error.message : String(error)}`,
|
|
17049
17770
|
true
|
|
17050
17771
|
);
|
|
17772
|
+
} finally {
|
|
17773
|
+
await this.saveTask({ state: previousTaskState });
|
|
17051
17774
|
}
|
|
17052
17775
|
await this.sendWorktreeIntegrationStatusUpdated();
|
|
17053
17776
|
}
|
|
@@ -17084,17 +17807,17 @@ ${diff}
|
|
|
17084
17807
|
this.addLogMessage("loading", "Continuing rebase...");
|
|
17085
17808
|
await this.worktreeManager.continueRebase(this.task.worktree.path);
|
|
17086
17809
|
await this.saveTask({ lastMergeState: void 0 });
|
|
17087
|
-
this.addLogMessage("info", "Rebase
|
|
17810
|
+
this.addLogMessage("info", "Rebase completed", true);
|
|
17088
17811
|
} catch (error) {
|
|
17089
17812
|
logger.error("Failed to continue rebase:", error);
|
|
17090
17813
|
const isConflict = error instanceof GitError && error.gitOutput?.includes("Resolve all conflicts manually");
|
|
17091
|
-
|
|
17092
|
-
|
|
17093
|
-
|
|
17094
|
-
|
|
17095
|
-
|
|
17096
|
-
|
|
17097
|
-
|
|
17814
|
+
if (!isConflict) {
|
|
17815
|
+
this.addLogMessage(
|
|
17816
|
+
"error",
|
|
17817
|
+
error instanceof GitError ? error.getErrorDetails() : `Failed to continue rebase: ${error instanceof Error ? error.message : String(error)}`,
|
|
17818
|
+
true
|
|
17819
|
+
);
|
|
17820
|
+
}
|
|
17098
17821
|
}
|
|
17099
17822
|
await this.sendUpdatedFilesUpdated();
|
|
17100
17823
|
await this.sendWorktreeIntegrationStatusUpdated();
|
|
@@ -17158,50 +17881,53 @@ ${diff}
|
|
|
17158
17881
|
async generateText(modelId, systemPrompt, prompt) {
|
|
17159
17882
|
return this.agent.generateText(modelId, systemPrompt, prompt, this.getProjectDir());
|
|
17160
17883
|
}
|
|
17161
|
-
async
|
|
17162
|
-
const filePath = path.isAbsolute(filename) ? filename : path.join(this.getTaskDir(), filename);
|
|
17163
|
-
const fileExtension = path.extname(filename).slice(1) || "";
|
|
17164
|
-
let contextLines = [];
|
|
17165
|
-
try {
|
|
17166
|
-
const fileContent = await fs.readFile(filePath, "utf-8");
|
|
17167
|
-
const lines = fileContent.split("\n");
|
|
17168
|
-
const startLine = Math.max(0, lineNumber - contextSize - 1);
|
|
17169
|
-
const endLine = Math.min(lines.length, lineNumber + contextSize);
|
|
17170
|
-
contextLines = lines.slice(startLine, endLine).map((content, index) => ({
|
|
17171
|
-
lineNumber: startLine + index + 1,
|
|
17172
|
-
content
|
|
17173
|
-
}));
|
|
17174
|
-
} catch (error) {
|
|
17175
|
-
logger.warn("Failed to read file for context extraction", {
|
|
17176
|
-
filePath,
|
|
17177
|
-
error
|
|
17178
|
-
});
|
|
17179
|
-
}
|
|
17180
|
-
const prompt = await this.promptsManager.getCodeInlineRequestPrompt(this, {
|
|
17181
|
-
filename,
|
|
17182
|
-
lineNumber,
|
|
17183
|
-
fileExtension,
|
|
17184
|
-
contextLines,
|
|
17185
|
-
userComment
|
|
17186
|
-
});
|
|
17884
|
+
async runCodeChangeRequests(requests, contextSize = 5, createNewTask) {
|
|
17187
17885
|
const mode = this.getCurrentMode();
|
|
17886
|
+
const promptRequests = await Promise.all(
|
|
17887
|
+
requests.map(async (request) => {
|
|
17888
|
+
const filePath = path.isAbsolute(request.filename) ? request.filename : path.join(this.getTaskDir(), request.filename);
|
|
17889
|
+
const fileExtension = path.extname(request.filename).slice(1) || "";
|
|
17890
|
+
let contextLines = [];
|
|
17891
|
+
try {
|
|
17892
|
+
const fileContent = await fs.readFile(filePath, "utf-8");
|
|
17893
|
+
const lines = fileContent.split("\n");
|
|
17894
|
+
const startLine = Math.max(0, request.lineNumber - contextSize - 1);
|
|
17895
|
+
const endLine = Math.min(lines.length, request.lineNumber + contextSize);
|
|
17896
|
+
contextLines = lines.slice(startLine, endLine).map((content, index) => ({
|
|
17897
|
+
lineNumber: startLine + index + 1,
|
|
17898
|
+
content
|
|
17899
|
+
}));
|
|
17900
|
+
} catch (error) {
|
|
17901
|
+
logger.warn("Failed to read file for context extraction", {
|
|
17902
|
+
filePath,
|
|
17903
|
+
error
|
|
17904
|
+
});
|
|
17905
|
+
}
|
|
17906
|
+
return {
|
|
17907
|
+
filename: request.filename,
|
|
17908
|
+
lineNumber: request.lineNumber,
|
|
17909
|
+
fileExtension,
|
|
17910
|
+
contextLines,
|
|
17911
|
+
userComment: request.userComment
|
|
17912
|
+
};
|
|
17913
|
+
})
|
|
17914
|
+
);
|
|
17915
|
+
const prompt = await this.promptsManager.getCodeChangeRequestsPrompt(this, {
|
|
17916
|
+
requests: promptRequests
|
|
17917
|
+
});
|
|
17188
17918
|
if (!createNewTask) {
|
|
17919
|
+
const uniqueFiles = [...new Set(requests.map((r) => r.filename))];
|
|
17189
17920
|
if (AIDER_MODES.includes(mode)) {
|
|
17190
|
-
|
|
17191
|
-
path: filename
|
|
17192
|
-
}
|
|
17921
|
+
for (const filename of uniqueFiles) {
|
|
17922
|
+
await this.addFiles({ path: filename });
|
|
17923
|
+
}
|
|
17193
17924
|
}
|
|
17194
17925
|
void this.runPrompt(prompt, mode, false);
|
|
17195
17926
|
return;
|
|
17196
17927
|
}
|
|
17197
|
-
|
|
17198
|
-
baseDir: this.project.baseDir,
|
|
17199
|
-
taskId: INTERNAL_TASK_ID,
|
|
17200
|
-
level: "loading",
|
|
17201
|
-
message: "Creating task for inline code request..."
|
|
17202
|
-
});
|
|
17928
|
+
const taskName = requests.length === 1 ? `${requests[0].filename}:${requests[0].lineNumber}` : `${requests.length} change requests`;
|
|
17203
17929
|
const newTaskData = await this.project.createNewTask({
|
|
17204
|
-
name:
|
|
17930
|
+
name: taskName,
|
|
17205
17931
|
sendEvent: false,
|
|
17206
17932
|
autoApprove: true,
|
|
17207
17933
|
activate: true,
|
|
@@ -17215,9 +17941,10 @@ ${diff}
|
|
|
17215
17941
|
}
|
|
17216
17942
|
await newTask.init();
|
|
17217
17943
|
if (AIDER_MODES.includes(mode)) {
|
|
17218
|
-
|
|
17219
|
-
|
|
17220
|
-
|
|
17944
|
+
const uniqueFiles = [...new Set(requests.map((r) => r.filename))];
|
|
17945
|
+
for (const filename of uniqueFiles) {
|
|
17946
|
+
await newTask.addFiles({ path: filename });
|
|
17947
|
+
}
|
|
17221
17948
|
}
|
|
17222
17949
|
this.eventManager.sendTaskCreated(newTask.task, true);
|
|
17223
17950
|
void newTask.runPrompt(prompt, mode, false);
|
|
@@ -17379,6 +18106,9 @@ class Project {
|
|
|
17379
18106
|
if (!parentTask) {
|
|
17380
18107
|
throw new Error(`Parent task with id ${normalizedParams.parentId} not found`);
|
|
17381
18108
|
}
|
|
18109
|
+
if (!parentTask.task.createdAt) {
|
|
18110
|
+
await parentTask.saveTask();
|
|
18111
|
+
}
|
|
17382
18112
|
}
|
|
17383
18113
|
const sourceTask = parentTask || this.getMostRecentTask();
|
|
17384
18114
|
const defaultWorkingMode = this.store.getSettings().taskSettings.defaultWorkingMode || "local";
|
|
@@ -17603,6 +18333,17 @@ class Project {
|
|
|
17603
18333
|
getAgentProfiles() {
|
|
17604
18334
|
return this.agentProfileManager.getProjectProfiles(this);
|
|
17605
18335
|
}
|
|
18336
|
+
/**
|
|
18337
|
+
* Checks if any other task (excluding the specified taskId) uses the given worktree path.
|
|
18338
|
+
*/
|
|
18339
|
+
isWorktreeSharedWithOtherTasks(worktreePath, excludeTaskId) {
|
|
18340
|
+
for (const [id, task] of this.tasks.entries()) {
|
|
18341
|
+
if (id !== excludeTaskId && task.task.worktree?.path === worktreePath) {
|
|
18342
|
+
return true;
|
|
18343
|
+
}
|
|
18344
|
+
}
|
|
18345
|
+
return false;
|
|
18346
|
+
}
|
|
17606
18347
|
async deleteTaskInternal(taskId) {
|
|
17607
18348
|
const taskDir = path.join(this.baseDir, ".aider-desk", "tasks", taskId);
|
|
17608
18349
|
const task = this.tasks.get(taskId);
|
|
@@ -17611,6 +18352,19 @@ class Project {
|
|
|
17611
18352
|
this.tasks.delete(taskId);
|
|
17612
18353
|
this.eventManager.sendTaskDeleted(task.task);
|
|
17613
18354
|
}
|
|
18355
|
+
const taskData = task?.task;
|
|
18356
|
+
if (taskData?.worktree && !this.isWorktreeSharedWithOtherTasks(taskData.worktree.path, taskId)) {
|
|
18357
|
+
try {
|
|
18358
|
+
await this.worktreeManager.removeWorktree(this.baseDir, taskData.worktree);
|
|
18359
|
+
} catch (error) {
|
|
18360
|
+
logger.warn("Failed to remove worktree during task deletion", {
|
|
18361
|
+
baseDir: this.baseDir,
|
|
18362
|
+
taskId,
|
|
18363
|
+
worktreePath: taskData.worktree.path,
|
|
18364
|
+
error: error instanceof Error ? error.message : String(error)
|
|
18365
|
+
});
|
|
18366
|
+
}
|
|
18367
|
+
}
|
|
17614
18368
|
await fs.rm(taskDir, { recursive: true, force: true });
|
|
17615
18369
|
}
|
|
17616
18370
|
async deleteTask(taskId) {
|
|
@@ -17645,8 +18399,12 @@ class Project {
|
|
|
17645
18399
|
if (!sourceTask) {
|
|
17646
18400
|
throw new Error(`Task with id ${taskId} not found`);
|
|
17647
18401
|
}
|
|
18402
|
+
const hasWorktree = sourceTask.task.worktree && sourceTask.task.workingMode === "worktree";
|
|
17648
18403
|
const newTask = await this.prepareTask(void 0, {
|
|
17649
18404
|
...sourceTask.task,
|
|
18405
|
+
// When the source task has a worktree, make the duplicate a subtask
|
|
18406
|
+
// so both tasks sharing the same worktree are clearly related
|
|
18407
|
+
...hasWorktree ? { parentId: sourceTask.task.parentId || taskId } : {},
|
|
17650
18408
|
state: sourceTask.task.state === DefaultTaskState.InProgress ? DefaultTaskState.Todo : sourceTask.task.state
|
|
17651
18409
|
});
|
|
17652
18410
|
await newTask.init();
|
|
@@ -17858,6 +18616,15 @@ class EventManager {
|
|
|
17858
18616
|
this.sendToWindows("updated-files-updated", data);
|
|
17859
18617
|
this.broadcastToEventConnectors("updated-files-updated", data);
|
|
17860
18618
|
}
|
|
18619
|
+
sendSkillsUpdated(baseDir, taskId, skills) {
|
|
18620
|
+
const data = {
|
|
18621
|
+
baseDir,
|
|
18622
|
+
taskId,
|
|
18623
|
+
skills
|
|
18624
|
+
};
|
|
18625
|
+
this.sendToWindows("skills-updated", data);
|
|
18626
|
+
this.broadcastToEventConnectors("skills-updated", data);
|
|
18627
|
+
}
|
|
17861
18628
|
// Response events
|
|
17862
18629
|
sendResponseChunk(data) {
|
|
17863
18630
|
this.sendToWindows("response-chunk", data);
|
|
@@ -18361,8 +19128,7 @@ const loadAnthropicCompatibleModels = async (profile, settings) => {
|
|
|
18361
19128
|
const models = data.data?.map((model) => {
|
|
18362
19129
|
return {
|
|
18363
19130
|
id: model.id,
|
|
18364
|
-
providerId: profile.id
|
|
18365
|
-
temperature: DEFAULT_MODEL_TEMPERATURE
|
|
19131
|
+
providerId: profile.id
|
|
18366
19132
|
};
|
|
18367
19133
|
}) || [];
|
|
18368
19134
|
logger.info(`Loaded ${models.length} Anthropic-compatible models for profile ${profile.id}`);
|
|
@@ -18475,6 +19241,11 @@ const AUGGIE_MODELS = [
|
|
|
18475
19241
|
maxInputTokens: 2e5,
|
|
18476
19242
|
maxOutputTokensLimit: 32768
|
|
18477
19243
|
},
|
|
19244
|
+
{
|
|
19245
|
+
id: "claude-opus-4-7",
|
|
19246
|
+
maxInputTokens: 2e5,
|
|
19247
|
+
maxOutputTokensLimit: 32768
|
|
19248
|
+
},
|
|
18478
19249
|
{ id: "gpt-5-1", maxInputTokens: 2e5, maxOutputTokensLimit: 16384 },
|
|
18479
19250
|
{ id: "gpt-5-2", maxInputTokens: 2e5, maxOutputTokensLimit: 16384 },
|
|
18480
19251
|
{ id: "gpt-5-4", maxInputTokens: 2e5, maxOutputTokensLimit: 16384 }
|
|
@@ -18786,8 +19557,7 @@ const loadBedrockModels = async (profile, settings) => {
|
|
|
18786
19557
|
if (response.authorizationStatus === "AUTHORIZED" && response.entitlementAvailability === "AVAILABLE" && response.regionAvailability === "AVAILABLE") {
|
|
18787
19558
|
availableModels.push({
|
|
18788
19559
|
id: inferenceProfile.inferenceProfileId,
|
|
18789
|
-
providerId: profile.id
|
|
18790
|
-
temperature: DEFAULT_MODEL_TEMPERATURE
|
|
19560
|
+
providerId: profile.id
|
|
18791
19561
|
});
|
|
18792
19562
|
logger.debug(`Profile ${inferenceProfile.inferenceProfileId} with model ${modelId} is available and authorized`);
|
|
18793
19563
|
} else {
|
|
@@ -18941,8 +19711,7 @@ const loadCerebrasModels = async (profile, settings) => {
|
|
|
18941
19711
|
return {
|
|
18942
19712
|
id: model.id,
|
|
18943
19713
|
providerId: profile.id,
|
|
18944
|
-
maxInputTokens: model.max_context_length
|
|
18945
|
-
temperature: DEFAULT_MODEL_TEMPERATURE
|
|
19714
|
+
maxInputTokens: model.max_context_length
|
|
18946
19715
|
};
|
|
18947
19716
|
}) || [];
|
|
18948
19717
|
logger.info(`Loaded ${models.length} Cerebras models for profile ${profile.id}`);
|
|
@@ -19212,8 +19981,7 @@ const loadDeepseekModels = async (profile, settings) => {
|
|
|
19212
19981
|
const models = data.data?.map((m) => {
|
|
19213
19982
|
return {
|
|
19214
19983
|
id: m.id,
|
|
19215
|
-
providerId: profile.id
|
|
19216
|
-
temperature: DEFAULT_MODEL_TEMPERATURE
|
|
19984
|
+
providerId: profile.id
|
|
19217
19985
|
};
|
|
19218
19986
|
}) || [];
|
|
19219
19987
|
logger.info(`Loaded ${models.length} DeepSeek models for profile ${profile.id}`);
|
|
@@ -19257,6 +20025,34 @@ const createDeepseekLlm = (profile, model, settings, projectDir) => {
|
|
|
19257
20025
|
});
|
|
19258
20026
|
return deepseekProvider(model.id);
|
|
19259
20027
|
};
|
|
20028
|
+
const getDeepseekProviderOptions = (llmProvider, model) => {
|
|
20029
|
+
if (!isDeepseekProvider(llmProvider)) {
|
|
20030
|
+
return void 0;
|
|
20031
|
+
}
|
|
20032
|
+
const providerOverrides = model.providerOverrides;
|
|
20033
|
+
const thinkingEnabled = providerOverrides?.thinkingEnabled ?? llmProvider.thinkingEnabled ?? true;
|
|
20034
|
+
const reasoningEffort = providerOverrides?.reasoningEffort ?? llmProvider.reasoningEffort ?? "high";
|
|
20035
|
+
return {
|
|
20036
|
+
deepseek: {
|
|
20037
|
+
thinking: { type: thinkingEnabled ? "enabled" : "disabled" },
|
|
20038
|
+
...thinkingEnabled && { reasoningEffort }
|
|
20039
|
+
}
|
|
20040
|
+
};
|
|
20041
|
+
};
|
|
20042
|
+
const getDeepseekProviderParameters = (llmProvider, model) => {
|
|
20043
|
+
if (!isDeepseekProvider(llmProvider)) {
|
|
20044
|
+
return {};
|
|
20045
|
+
}
|
|
20046
|
+
const providerOverrides = model.providerOverrides;
|
|
20047
|
+
const thinkingEnabled = providerOverrides?.thinkingEnabled ?? llmProvider.thinkingEnabled ?? true;
|
|
20048
|
+
if (thinkingEnabled) {
|
|
20049
|
+
return {
|
|
20050
|
+
temperature: void 0,
|
|
20051
|
+
topP: void 0
|
|
20052
|
+
};
|
|
20053
|
+
}
|
|
20054
|
+
return {};
|
|
20055
|
+
};
|
|
19260
20056
|
const deepseekProviderStrategy = {
|
|
19261
20057
|
// Core LLM functions
|
|
19262
20058
|
createLlm: createDeepseekLlm,
|
|
@@ -19265,7 +20061,9 @@ const deepseekProviderStrategy = {
|
|
|
19265
20061
|
loadModels: loadDeepseekModels,
|
|
19266
20062
|
hasEnvVars: hasDeepseekEnvVars,
|
|
19267
20063
|
getAiderMapping: getDeepseekAiderMapping,
|
|
19268
|
-
getModelInfo: getDefaultModelInfo
|
|
20064
|
+
getModelInfo: getDefaultModelInfo,
|
|
20065
|
+
getProviderOptions: getDeepseekProviderOptions,
|
|
20066
|
+
getProviderParameters: getDeepseekProviderParameters
|
|
19269
20067
|
};
|
|
19270
20068
|
const loadGeminiModels = async (profile, settings) => {
|
|
19271
20069
|
if (!isGeminiProvider(profile.provider)) {
|
|
@@ -19619,8 +20417,7 @@ const loadGpustackModels = async (profile, settings) => {
|
|
|
19619
20417
|
id: model.name,
|
|
19620
20418
|
providerId: profile.id,
|
|
19621
20419
|
// Extract max_model_len from meta if available
|
|
19622
|
-
maxInputTokens: model.meta?.max_model_len
|
|
19623
|
-
temperature: DEFAULT_MODEL_TEMPERATURE
|
|
20420
|
+
maxInputTokens: model.meta?.max_model_len
|
|
19624
20421
|
};
|
|
19625
20422
|
}) || [];
|
|
19626
20423
|
logger.info(`Loaded ${models.length} GPUStack models for profile ${profile.id}`);
|
|
@@ -19740,8 +20537,7 @@ const loadGroqModels = async (profile, settings) => {
|
|
|
19740
20537
|
const models = data.data?.map((model) => {
|
|
19741
20538
|
return {
|
|
19742
20539
|
id: model.id,
|
|
19743
|
-
providerId: profile.id
|
|
19744
|
-
temperature: DEFAULT_MODEL_TEMPERATURE
|
|
20540
|
+
providerId: profile.id
|
|
19745
20541
|
};
|
|
19746
20542
|
}) || [];
|
|
19747
20543
|
logger.info(`Loaded ${models.length} Groq models for profile ${profile.id}`);
|
|
@@ -19892,7 +20688,6 @@ const alibabaPlanProviderStrategy = {
|
|
|
19892
20688
|
getProviderOptions: getAlibabaPlanProviderOptions
|
|
19893
20689
|
};
|
|
19894
20690
|
const KIMI_PLAN_BASE_URL = "https://api.kimi.com/coding/v1";
|
|
19895
|
-
const KIMI_PLAN_MODEL_ID = "k2p5";
|
|
19896
20691
|
const loadKimiPlanModels = async (profile, settings) => {
|
|
19897
20692
|
if (!isKimiPlanProvider(profile.provider)) {
|
|
19898
20693
|
return { models: [], success: false };
|
|
@@ -19906,7 +20701,19 @@ const loadKimiPlanModels = async (profile, settings) => {
|
|
|
19906
20701
|
}
|
|
19907
20702
|
const models = [
|
|
19908
20703
|
{
|
|
19909
|
-
id:
|
|
20704
|
+
id: "kimi-k2-thinking",
|
|
20705
|
+
providerId: profile.id,
|
|
20706
|
+
maxInputTokens: 262144,
|
|
20707
|
+
maxOutputTokensLimit: 32768
|
|
20708
|
+
},
|
|
20709
|
+
{
|
|
20710
|
+
id: "k2p5",
|
|
20711
|
+
providerId: profile.id,
|
|
20712
|
+
maxInputTokens: 262144,
|
|
20713
|
+
maxOutputTokensLimit: 32768
|
|
20714
|
+
},
|
|
20715
|
+
{
|
|
20716
|
+
id: "k2p6",
|
|
19910
20717
|
providerId: profile.id,
|
|
19911
20718
|
maxInputTokens: 262144,
|
|
19912
20719
|
maxOutputTokensLimit: 32768
|
|
@@ -20129,8 +20936,7 @@ const loadLmStudioModels = async (profile, settings) => {
|
|
|
20129
20936
|
return {
|
|
20130
20937
|
id: model.id,
|
|
20131
20938
|
providerId: profile.id,
|
|
20132
|
-
maxInputTokens: model.max_context_length
|
|
20133
|
-
temperature: DEFAULT_MODEL_TEMPERATURE
|
|
20939
|
+
maxInputTokens: model.max_context_length
|
|
20134
20940
|
};
|
|
20135
20941
|
}) || [];
|
|
20136
20942
|
logger.info(`Loaded ${models.length} LM Studio models from ${effectiveBaseUrl} for profile ${profile.id}`);
|
|
@@ -20210,7 +21016,63 @@ const loadMinimaxModels = async (profile) => {
|
|
|
20210
21016
|
}
|
|
20211
21017
|
const hardcodedModels = [
|
|
20212
21018
|
{
|
|
20213
|
-
id: "MiniMax-M2",
|
|
21019
|
+
id: "MiniMax-M2.7",
|
|
21020
|
+
providerId: profile.id,
|
|
21021
|
+
maxInputTokens: 204800,
|
|
21022
|
+
maxOutputTokensLimit: 131072,
|
|
21023
|
+
inputCostPerToken: 3e-7,
|
|
21024
|
+
// 0.3 per 1M tokens
|
|
21025
|
+
outputCostPerToken: 12e-7,
|
|
21026
|
+
// 1.2 per 1M tokens
|
|
21027
|
+
cacheReadInputTokenCost: 6e-8,
|
|
21028
|
+
// 0.06 per 1M tokens
|
|
21029
|
+
cacheWriteInputTokenCost: 375e-9
|
|
21030
|
+
// 0.375 per 1M tokens
|
|
21031
|
+
},
|
|
21032
|
+
{
|
|
21033
|
+
id: "MiniMax-M2.7-highspeed",
|
|
21034
|
+
providerId: profile.id,
|
|
21035
|
+
maxInputTokens: 204800,
|
|
21036
|
+
maxOutputTokensLimit: 131072,
|
|
21037
|
+
inputCostPerToken: 6e-7,
|
|
21038
|
+
// 0.6 per 1M tokens
|
|
21039
|
+
outputCostPerToken: 24e-7,
|
|
21040
|
+
// 2.4 per 1M tokens
|
|
21041
|
+
cacheReadInputTokenCost: 6e-8,
|
|
21042
|
+
// 0.06 per 1M tokens
|
|
21043
|
+
cacheWriteInputTokenCost: 375e-9
|
|
21044
|
+
// 0.375 per 1M tokens
|
|
21045
|
+
},
|
|
21046
|
+
{
|
|
21047
|
+
id: "MiniMax-M2.5",
|
|
21048
|
+
providerId: profile.id,
|
|
21049
|
+
maxInputTokens: 204800,
|
|
21050
|
+
maxOutputTokensLimit: 131072,
|
|
21051
|
+
inputCostPerToken: 3e-7,
|
|
21052
|
+
// 0.3 per 1M tokens
|
|
21053
|
+
outputCostPerToken: 12e-7,
|
|
21054
|
+
// 1.2 per 1M tokens
|
|
21055
|
+
cacheReadInputTokenCost: 3e-8,
|
|
21056
|
+
// 0.03 per 1M tokens
|
|
21057
|
+
cacheWriteInputTokenCost: 375e-9
|
|
21058
|
+
// 0.375 per 1M tokens
|
|
21059
|
+
},
|
|
21060
|
+
{
|
|
21061
|
+
id: "MiniMax-M2.5-highspeed",
|
|
21062
|
+
providerId: profile.id,
|
|
21063
|
+
maxInputTokens: 204800,
|
|
21064
|
+
maxOutputTokensLimit: 131072,
|
|
21065
|
+
inputCostPerToken: 6e-7,
|
|
21066
|
+
// 0.6 per 1M tokens
|
|
21067
|
+
outputCostPerToken: 24e-7,
|
|
21068
|
+
// 2.4 per 1M tokens
|
|
21069
|
+
cacheReadInputTokenCost: 3e-8,
|
|
21070
|
+
// 0.03 per 1M tokens
|
|
21071
|
+
cacheWriteInputTokenCost: 375e-9
|
|
21072
|
+
// 0.375 per 1M tokens
|
|
21073
|
+
},
|
|
21074
|
+
{
|
|
21075
|
+
id: "MiniMax-M2.1",
|
|
20214
21076
|
providerId: profile.id,
|
|
20215
21077
|
maxInputTokens: 204800,
|
|
20216
21078
|
maxOutputTokensLimit: 131072,
|
|
@@ -20220,12 +21082,25 @@ const loadMinimaxModels = async (profile) => {
|
|
|
20220
21082
|
// 1.2 per 1M tokens
|
|
20221
21083
|
cacheReadInputTokenCost: 3e-8,
|
|
20222
21084
|
// 0.03 per 1M tokens
|
|
20223
|
-
cacheWriteInputTokenCost:
|
|
20224
|
-
// 0.
|
|
20225
|
-
|
|
21085
|
+
cacheWriteInputTokenCost: 375e-9
|
|
21086
|
+
// 0.375 per 1M tokens
|
|
21087
|
+
},
|
|
21088
|
+
{
|
|
21089
|
+
id: "MiniMax-M2.1-highspeed",
|
|
21090
|
+
providerId: profile.id,
|
|
21091
|
+
maxInputTokens: 204800,
|
|
21092
|
+
maxOutputTokensLimit: 131072,
|
|
21093
|
+
inputCostPerToken: 6e-7,
|
|
21094
|
+
// 0.6 per 1M tokens
|
|
21095
|
+
outputCostPerToken: 24e-7,
|
|
21096
|
+
// 2.4 per 1M tokens
|
|
21097
|
+
cacheReadInputTokenCost: 3e-8,
|
|
21098
|
+
// 0.03 per 1M tokens
|
|
21099
|
+
cacheWriteInputTokenCost: 375e-9
|
|
21100
|
+
// 0.375 per 1M tokens
|
|
20226
21101
|
},
|
|
20227
21102
|
{
|
|
20228
|
-
id: "MiniMax-M2
|
|
21103
|
+
id: "MiniMax-M2",
|
|
20229
21104
|
providerId: profile.id,
|
|
20230
21105
|
maxInputTokens: 204800,
|
|
20231
21106
|
maxOutputTokensLimit: 131072,
|
|
@@ -20235,9 +21110,8 @@ const loadMinimaxModels = async (profile) => {
|
|
|
20235
21110
|
// 1.2 per 1M tokens
|
|
20236
21111
|
cacheReadInputTokenCost: 3e-8,
|
|
20237
21112
|
// 0.03 per 1M tokens
|
|
20238
|
-
cacheWriteInputTokenCost:
|
|
20239
|
-
// 0.
|
|
20240
|
-
temperature: 0.5
|
|
21113
|
+
cacheWriteInputTokenCost: 375e-9
|
|
21114
|
+
// 0.375 per 1M tokens
|
|
20241
21115
|
}
|
|
20242
21116
|
];
|
|
20243
21117
|
return { models: hardcodedModels, success: true };
|
|
@@ -20333,6 +21207,90 @@ const minimaxProviderStrategy = {
|
|
|
20333
21207
|
// Configuration helpers
|
|
20334
21208
|
getCacheControl: getMinimaxCacheControl
|
|
20335
21209
|
};
|
|
21210
|
+
const loadMistralModels = async (profile, settings) => {
|
|
21211
|
+
if (!isMistralProvider(profile.provider)) {
|
|
21212
|
+
return { models: [], success: false };
|
|
21213
|
+
}
|
|
21214
|
+
const provider = profile.provider;
|
|
21215
|
+
const apiKey = provider.apiKey || "";
|
|
21216
|
+
const apiKeyEnv = getEffectiveEnvironmentVariable("MISTRAL_API_KEY", settings);
|
|
21217
|
+
const effectiveApiKey = apiKey || apiKeyEnv?.value || "";
|
|
21218
|
+
if (!effectiveApiKey) {
|
|
21219
|
+
const errorMsg = "Mistral API key is required. Please set it in Providers settings or via MISTRAL_API_KEY environment variable.";
|
|
21220
|
+
logger.debug(errorMsg);
|
|
21221
|
+
return { models: [], success: false };
|
|
21222
|
+
}
|
|
21223
|
+
try {
|
|
21224
|
+
const response = await fetch("https://api.mistral.ai/v1/models", {
|
|
21225
|
+
headers: { Authorization: `Bearer ${effectiveApiKey}` }
|
|
21226
|
+
});
|
|
21227
|
+
if (!response.ok) {
|
|
21228
|
+
const errorMsg = `Mistral models API response failed: ${response.status} ${response.statusText} ${await response.text()}`;
|
|
21229
|
+
logger.error(errorMsg, {
|
|
21230
|
+
status: response.status,
|
|
21231
|
+
statusText: response.statusText
|
|
21232
|
+
});
|
|
21233
|
+
return { models: [], success: false, error: errorMsg };
|
|
21234
|
+
}
|
|
21235
|
+
const data = await response.json();
|
|
21236
|
+
const models = data.data?.map((model) => {
|
|
21237
|
+
return {
|
|
21238
|
+
id: model.id,
|
|
21239
|
+
providerId: profile.id,
|
|
21240
|
+
temperature: 0.7
|
|
21241
|
+
};
|
|
21242
|
+
}) || [];
|
|
21243
|
+
logger.info(`Loaded ${models.length} Mistral models for profile ${profile.id}`);
|
|
21244
|
+
return { models, success: true };
|
|
21245
|
+
} catch (error) {
|
|
21246
|
+
const errorMsg = typeof error === "string" ? error : error instanceof Error ? error.message : "Unknown error loading Mistral models";
|
|
21247
|
+
logger.error("Error loading Mistral models:", error);
|
|
21248
|
+
return { models: [], success: false, error: errorMsg };
|
|
21249
|
+
}
|
|
21250
|
+
};
|
|
21251
|
+
const hasMistralEnvVars = (settings) => {
|
|
21252
|
+
return !!getEffectiveEnvironmentVariable("MISTRAL_API_KEY", settings, void 0)?.value;
|
|
21253
|
+
};
|
|
21254
|
+
const getMistralAiderMapping = (provider, modelId) => {
|
|
21255
|
+
const mistralProvider = provider.provider;
|
|
21256
|
+
const envVars = {};
|
|
21257
|
+
if (mistralProvider.apiKey) {
|
|
21258
|
+
envVars.MISTRAL_API_KEY = mistralProvider.apiKey;
|
|
21259
|
+
}
|
|
21260
|
+
return {
|
|
21261
|
+
modelName: `mistral/${modelId}`,
|
|
21262
|
+
environmentVariables: envVars
|
|
21263
|
+
};
|
|
21264
|
+
};
|
|
21265
|
+
const createMistralLlm = (profile, model, settings, projectDir) => {
|
|
21266
|
+
const provider = profile.provider;
|
|
21267
|
+
let apiKey = provider.apiKey;
|
|
21268
|
+
if (!apiKey) {
|
|
21269
|
+
const effectiveVar = getEffectiveEnvironmentVariable("MISTRAL_API_KEY", settings, projectDir);
|
|
21270
|
+
if (effectiveVar) {
|
|
21271
|
+
apiKey = effectiveVar.value;
|
|
21272
|
+
logger.debug(`Loaded MISTRAL_API_KEY from ${effectiveVar.source}`);
|
|
21273
|
+
}
|
|
21274
|
+
}
|
|
21275
|
+
if (!apiKey) {
|
|
21276
|
+
throw new Error("Mistral API key is required in Providers settings or Aider environment variables (MISTRAL_API_KEY)");
|
|
21277
|
+
}
|
|
21278
|
+
const mistralProvider = mistral.createMistral({
|
|
21279
|
+
apiKey,
|
|
21280
|
+
headers: profile.headers
|
|
21281
|
+
});
|
|
21282
|
+
return mistralProvider(model.id);
|
|
21283
|
+
};
|
|
21284
|
+
const mistralProviderStrategy = {
|
|
21285
|
+
// Core LLM functions
|
|
21286
|
+
createLlm: createMistralLlm,
|
|
21287
|
+
getUsageReport: getDefaultUsageReport,
|
|
21288
|
+
// Model discovery functions
|
|
21289
|
+
loadModels: loadMistralModels,
|
|
21290
|
+
hasEnvVars: hasMistralEnvVars,
|
|
21291
|
+
getAiderMapping: getMistralAiderMapping,
|
|
21292
|
+
getModelInfo: getDefaultModelInfo
|
|
21293
|
+
};
|
|
20336
21294
|
const loadOllamaModels = async (profile, settings) => {
|
|
20337
21295
|
if (!isOllamaProvider(profile.provider)) {
|
|
20338
21296
|
return { models: [], success: false };
|
|
@@ -20359,8 +21317,7 @@ const loadOllamaModels = async (profile, settings) => {
|
|
|
20359
21317
|
const models = data?.models?.map((m) => {
|
|
20360
21318
|
return {
|
|
20361
21319
|
id: m.name,
|
|
20362
|
-
providerId: profile.id
|
|
20363
|
-
temperature: DEFAULT_MODEL_TEMPERATURE
|
|
21320
|
+
providerId: profile.id
|
|
20364
21321
|
};
|
|
20365
21322
|
}) || [];
|
|
20366
21323
|
logger.info(`Loaded ${models.length} Ollama models from ${effectiveBaseUrl} for profile ${profile.id}`);
|
|
@@ -20698,8 +21655,7 @@ const loadOpenaiCompatibleModels = async (profile, settings) => {
|
|
|
20698
21655
|
const models = data.data?.map((model) => {
|
|
20699
21656
|
return {
|
|
20700
21657
|
id: model.id,
|
|
20701
|
-
providerId: profile.id
|
|
20702
|
-
temperature: DEFAULT_MODEL_TEMPERATURE
|
|
21658
|
+
providerId: profile.id
|
|
20703
21659
|
};
|
|
20704
21660
|
}) || [];
|
|
20705
21661
|
logger.info(`Loaded ${models.length} OpenAI-compatible models for profile ${profile.id}`);
|
|
@@ -20818,7 +21774,7 @@ const getDefaultModelTemperature$2 = (modelId) => {
|
|
|
20818
21774
|
if (modelId.includes("glm-")) {
|
|
20819
21775
|
return 0.7;
|
|
20820
21776
|
}
|
|
20821
|
-
return
|
|
21777
|
+
return void 0;
|
|
20822
21778
|
};
|
|
20823
21779
|
const loadOpencodeModels = async (profile, settings) => {
|
|
20824
21780
|
if (!isOpenCodeProvider(profile.provider)) {
|
|
@@ -20949,7 +21905,7 @@ const getDefaultModelTemperature$1 = (modelId) => {
|
|
|
20949
21905
|
if (modelId.includes("qwen")) {
|
|
20950
21906
|
return 0.55;
|
|
20951
21907
|
}
|
|
20952
|
-
return
|
|
21908
|
+
return void 0;
|
|
20953
21909
|
};
|
|
20954
21910
|
const loadOpenrouterModels = async (profile, settings) => {
|
|
20955
21911
|
if (!isOpenRouterProvider(profile.provider)) {
|
|
@@ -21074,9 +22030,9 @@ const getOpenRouterUsageReport = (task, provider, model, usage, providerMetadata
|
|
|
21074
22030
|
agentTotalCost: task.task.agentTotalCost + messageCost
|
|
21075
22031
|
};
|
|
21076
22032
|
};
|
|
21077
|
-
const getOpenRouterCacheControl = (
|
|
22033
|
+
const getOpenRouterCacheControl = (llmProvider, model) => {
|
|
21078
22034
|
if (isOpenRouterProvider(llmProvider)) {
|
|
21079
|
-
if (
|
|
22035
|
+
if (model.id?.startsWith("anthropic/")) {
|
|
21080
22036
|
return {
|
|
21081
22037
|
providerOptions: {
|
|
21082
22038
|
openrouter: {
|
|
@@ -21113,7 +22069,7 @@ const getDefaultModelTemperature = (modelId) => {
|
|
|
21113
22069
|
if (modelId.includes("qwen")) {
|
|
21114
22070
|
return 0.55;
|
|
21115
22071
|
}
|
|
21116
|
-
return
|
|
22072
|
+
return void 0;
|
|
21117
22073
|
};
|
|
21118
22074
|
const loadRequestyModels = async (profile, settings) => {
|
|
21119
22075
|
if (!isRequestyProvider(profile.provider)) {
|
|
@@ -21265,9 +22221,9 @@ const normalizeRequestyMessages = (_provider, model, messages) => {
|
|
|
21265
22221
|
}
|
|
21266
22222
|
return messages;
|
|
21267
22223
|
};
|
|
21268
|
-
const getRequestyCacheControl = (
|
|
22224
|
+
const getRequestyCacheControl = (llmProvider, model) => {
|
|
21269
22225
|
if (isRequestyProvider(llmProvider) && !llmProvider.useAutoCache) {
|
|
21270
|
-
if (
|
|
22226
|
+
if (model.id?.startsWith("anthropic/")) {
|
|
21271
22227
|
return {
|
|
21272
22228
|
providerOptions: {
|
|
21273
22229
|
requesty: {
|
|
@@ -21317,8 +22273,7 @@ const loadSyntheticModels = async (profile, settings) => {
|
|
|
21317
22273
|
const models = data.data?.map((model) => {
|
|
21318
22274
|
return {
|
|
21319
22275
|
id: model.id,
|
|
21320
|
-
providerId: profile.id
|
|
21321
|
-
temperature: DEFAULT_MODEL_TEMPERATURE
|
|
22276
|
+
providerId: profile.id
|
|
21322
22277
|
};
|
|
21323
22278
|
}) || [];
|
|
21324
22279
|
logger.info(`Loaded ${models.length} Synthetic models for profile ${profile.id}`);
|
|
@@ -21657,6 +22612,8 @@ const zaiPlanProviderStrategy = {
|
|
|
21657
22612
|
};
|
|
21658
22613
|
const MODELS_META_URL = "https://models.dev/api.json";
|
|
21659
22614
|
const MODELS_FILE = path.join(AIDER_DESK_DATA_DIR, "models.json");
|
|
22615
|
+
const PROVIDER_MODELS_CACHE_FILE = path.join(AIDER_DESK_CACHE_DIR, "provider-models.json");
|
|
22616
|
+
const PROVIDER_MODELS_CACHE_VERSION = 1;
|
|
21660
22617
|
class ModelManager {
|
|
21661
22618
|
constructor(store, eventManager) {
|
|
21662
22619
|
this.store = store;
|
|
@@ -21687,6 +22644,7 @@ class ModelManager {
|
|
|
21687
22644
|
litellm: litellmProviderStrategy,
|
|
21688
22645
|
lmstudio: lmStudioProviderStrategy,
|
|
21689
22646
|
minimax: minimaxProviderStrategy,
|
|
22647
|
+
mistral: mistralProviderStrategy,
|
|
21690
22648
|
ollama: ollamaProviderStrategy,
|
|
21691
22649
|
openai: openaiProviderStrategy,
|
|
21692
22650
|
"openai-compatible": openaiCompatibleProviderStrategy,
|
|
@@ -21704,9 +22662,20 @@ class ModelManager {
|
|
|
21704
22662
|
this.updateEnvVarsProviders();
|
|
21705
22663
|
await this.loadModelsInfo();
|
|
21706
22664
|
await this.loadModelOverrides();
|
|
21707
|
-
await this.
|
|
22665
|
+
const cacheLoaded = await this.loadProviderModelsFromCache();
|
|
22666
|
+
if (cacheLoaded) {
|
|
22667
|
+
this.eventManager.sendProviderModelsUpdated({
|
|
22668
|
+
models: Object.values(this.providerModels).flat(),
|
|
22669
|
+
loading: true,
|
|
22670
|
+
errors: this.providerErrors
|
|
22671
|
+
});
|
|
22672
|
+
this.loadProviderModelsInBackground(this.getProviders().filter((p) => !p.disabled));
|
|
22673
|
+
} else {
|
|
22674
|
+
await this.loadProviderModels(this.getProviders().filter((p) => !p.disabled));
|
|
22675
|
+
}
|
|
21708
22676
|
logger.info("ModelInfoManager initialized successfully.", {
|
|
21709
|
-
modelCount: Object.keys(this.modelsInfo).length
|
|
22677
|
+
modelCount: Object.keys(this.modelsInfo).length,
|
|
22678
|
+
cacheLoaded
|
|
21710
22679
|
});
|
|
21711
22680
|
} catch (error) {
|
|
21712
22681
|
logger.error("Error initializing ModelInfoManager:", error);
|
|
@@ -21753,6 +22722,44 @@ class ModelManager {
|
|
|
21753
22722
|
await freshDataPromise;
|
|
21754
22723
|
}
|
|
21755
22724
|
}
|
|
22725
|
+
async loadProviderModelsFromCache() {
|
|
22726
|
+
try {
|
|
22727
|
+
const cacheData = await fs$1.promises.readFile(PROVIDER_MODELS_CACHE_FILE, "utf-8");
|
|
22728
|
+
const cache = JSON.parse(cacheData);
|
|
22729
|
+
if (cache.version !== PROVIDER_MODELS_CACHE_VERSION) {
|
|
22730
|
+
logger.info("Provider models cache version mismatch, ignoring cache");
|
|
22731
|
+
return false;
|
|
22732
|
+
}
|
|
22733
|
+
this.providerModels = cache.providerModels;
|
|
22734
|
+
this.providerErrors = cache.providerErrors;
|
|
22735
|
+
logger.info("Loaded provider models from cache", {
|
|
22736
|
+
providerCount: Object.keys(cache.providerModels).length
|
|
22737
|
+
});
|
|
22738
|
+
return true;
|
|
22739
|
+
} catch {
|
|
22740
|
+
logger.info("Provider models cache not found or invalid");
|
|
22741
|
+
return false;
|
|
22742
|
+
}
|
|
22743
|
+
}
|
|
22744
|
+
async saveProviderModelsToCache() {
|
|
22745
|
+
try {
|
|
22746
|
+
const cache = {
|
|
22747
|
+
version: PROVIDER_MODELS_CACHE_VERSION,
|
|
22748
|
+
providerModels: this.providerModels,
|
|
22749
|
+
providerErrors: this.providerErrors
|
|
22750
|
+
};
|
|
22751
|
+
await fs$1.promises.mkdir(AIDER_DESK_CACHE_DIR, { recursive: true });
|
|
22752
|
+
await fs$1.promises.writeFile(PROVIDER_MODELS_CACHE_FILE, JSON.stringify(cache));
|
|
22753
|
+
logger.info("Saved provider models to cache");
|
|
22754
|
+
} catch (error) {
|
|
22755
|
+
logger.error("Failed to save provider models to cache:", error);
|
|
22756
|
+
}
|
|
22757
|
+
}
|
|
22758
|
+
loadProviderModelsInBackground(providers) {
|
|
22759
|
+
this.loadProviderModels(providers).catch((error) => {
|
|
22760
|
+
logger.error("Background loading of provider models failed:", error);
|
|
22761
|
+
});
|
|
22762
|
+
}
|
|
21756
22763
|
processModelsMeta(data) {
|
|
21757
22764
|
for (const providerId in data) {
|
|
21758
22765
|
const providerData = data[providerId];
|
|
@@ -21795,6 +22802,21 @@ class ModelManager {
|
|
|
21795
22802
|
}
|
|
21796
22803
|
return Array.from(changed);
|
|
21797
22804
|
}
|
|
22805
|
+
async loadModelsWithRetry(strategy, profile, retryCount = 3) {
|
|
22806
|
+
let lastResponse;
|
|
22807
|
+
for (let attempt = 0; attempt <= retryCount; attempt++) {
|
|
22808
|
+
if (attempt > 0) {
|
|
22809
|
+
const delayMs = Math.pow(2, attempt - 1) * 1e3;
|
|
22810
|
+
logger.info(`Retrying load models for provider profile ${profile.id} in ${delayMs}ms (attempt ${attempt + 1}/${retryCount + 1})`);
|
|
22811
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
22812
|
+
}
|
|
22813
|
+
lastResponse = await strategy.loadModels(profile, this.store.getSettings());
|
|
22814
|
+
if (lastResponse.success) {
|
|
22815
|
+
return lastResponse;
|
|
22816
|
+
}
|
|
22817
|
+
}
|
|
22818
|
+
return lastResponse;
|
|
22819
|
+
}
|
|
21798
22820
|
async providersChanged(oldProviders, newProviders) {
|
|
21799
22821
|
await this.initPromise;
|
|
21800
22822
|
const removedProviders = oldProviders.filter((p) => !newProviders.find((np) => np.id === p.id));
|
|
@@ -21836,7 +22858,7 @@ class ModelManager {
|
|
|
21836
22858
|
continue;
|
|
21837
22859
|
}
|
|
21838
22860
|
let providerModels = [];
|
|
21839
|
-
const response = await
|
|
22861
|
+
const response = await this.loadModelsWithRetry(strategy, profile);
|
|
21840
22862
|
delete this.providerErrors[profile.id];
|
|
21841
22863
|
if (response.success) {
|
|
21842
22864
|
providerModels.push(...response.models);
|
|
@@ -21865,6 +22887,7 @@ class ModelManager {
|
|
|
21865
22887
|
errors: this.providerErrors
|
|
21866
22888
|
});
|
|
21867
22889
|
this.eventManager.sendSettingsUpdated(this.store.getSettings());
|
|
22890
|
+
await this.saveProviderModelsToCache();
|
|
21868
22891
|
}
|
|
21869
22892
|
enrichWithModelInfo(models, profile, strategy) {
|
|
21870
22893
|
const enrichedModels = [...models];
|
|
@@ -22132,12 +23155,22 @@ class ModelManager {
|
|
|
22132
23155
|
}
|
|
22133
23156
|
return strategy.getUsageReport(task, provider, modelObj, usage, providerMetadata);
|
|
22134
23157
|
}
|
|
22135
|
-
getCacheControl(
|
|
23158
|
+
getCacheControl(provider, modelId) {
|
|
23159
|
+
const llmProvider = provider.provider;
|
|
22136
23160
|
const strategy = this.providerRegistry[llmProvider.name];
|
|
22137
23161
|
if (!strategy?.getCacheControl) {
|
|
22138
23162
|
return void 0;
|
|
22139
23163
|
}
|
|
22140
|
-
|
|
23164
|
+
const models = this.providerModels[provider.id] || [];
|
|
23165
|
+
const modelObj = models.find((m) => m.id === modelId);
|
|
23166
|
+
if (!modelObj) {
|
|
23167
|
+
const fallbackModel = {
|
|
23168
|
+
id: modelId,
|
|
23169
|
+
providerId: provider.id
|
|
23170
|
+
};
|
|
23171
|
+
return strategy.getCacheControl(llmProvider, fallbackModel);
|
|
23172
|
+
}
|
|
23173
|
+
return strategy.getCacheControl(llmProvider, modelObj);
|
|
22141
23174
|
}
|
|
22142
23175
|
isStreamingDisabled(provider, modelId) {
|
|
22143
23176
|
const llmProvider = provider.provider;
|
|
@@ -22271,7 +23304,7 @@ class ModelManager {
|
|
|
22271
23304
|
getProviderOptions: provider.strategy.getProviderOptions ? (_provider, model) => provider.strategy.getProviderOptions(model) : void 0,
|
|
22272
23305
|
getProviderTools: provider.strategy.getProviderTools ? (_provider, model) => provider.strategy.getProviderTools(model) : void 0,
|
|
22273
23306
|
getProviderParameters: provider.strategy.getProviderParameters ? (_provider, model) => provider.strategy.getProviderParameters(model) : void 0,
|
|
22274
|
-
getCacheControl: provider.strategy.getCacheControl ? (
|
|
23307
|
+
getCacheControl: provider.strategy.getCacheControl ? (_provider, model) => provider.strategy.getCacheControl(model) : void 0,
|
|
22275
23308
|
hasEnvVars: () => false,
|
|
22276
23309
|
getAiderMapping: provider.strategy.getAiderMapping ? provider.strategy.getAiderMapping : (_provider, modelId) => ({
|
|
22277
23310
|
modelName: modelId,
|
|
@@ -23171,12 +24204,13 @@ class MemoryManager {
|
|
|
23171
24204
|
*/
|
|
23172
24205
|
async storeMemory(projectId, taskId, type, content) {
|
|
23173
24206
|
if (!await this.waitForInit() || !this.isMemoryEnabled() || !this.db) {
|
|
23174
|
-
return;
|
|
24207
|
+
return "";
|
|
23175
24208
|
}
|
|
23176
24209
|
try {
|
|
23177
24210
|
const embedding = await this.getEmbedding(content);
|
|
24211
|
+
const id = uuid.v4();
|
|
23178
24212
|
const memoryWithVector = {
|
|
23179
|
-
id
|
|
24213
|
+
id,
|
|
23180
24214
|
type,
|
|
23181
24215
|
content,
|
|
23182
24216
|
taskid: taskId,
|
|
@@ -23196,8 +24230,10 @@ class MemoryManager {
|
|
|
23196
24230
|
taskId: memoryWithVector.taskid,
|
|
23197
24231
|
content: memoryWithVector.content.substring(0, 100)
|
|
23198
24232
|
});
|
|
24233
|
+
return id;
|
|
23199
24234
|
} catch (error) {
|
|
23200
24235
|
logger.error("Failed to store memory:", error);
|
|
24236
|
+
return "";
|
|
23201
24237
|
}
|
|
23202
24238
|
}
|
|
23203
24239
|
/**
|
|
@@ -23353,6 +24389,16 @@ class MemoryManager {
|
|
|
23353
24389
|
isMemoryEnabled() {
|
|
23354
24390
|
return this.isInitialized && this.store.getSettings().memory.enabled || false;
|
|
23355
24391
|
}
|
|
24392
|
+
setMemoryEnabled(enabled) {
|
|
24393
|
+
const settings = this.store.getSettings();
|
|
24394
|
+
this.store.saveSettings({
|
|
24395
|
+
...settings,
|
|
24396
|
+
memory: {
|
|
24397
|
+
...settings.memory,
|
|
24398
|
+
enabled
|
|
24399
|
+
}
|
|
24400
|
+
});
|
|
24401
|
+
}
|
|
23356
24402
|
}
|
|
23357
24403
|
const AIDER_DESK_EXTENSIONS_REPO_URL = "https://github.com/hotovo/aider-desk/tree/main/packages/extensions/extensions/";
|
|
23358
24404
|
const baseJitiOptions = {
|
|
@@ -23517,8 +24563,16 @@ class TaskContextImpl {
|
|
|
23517
24563
|
async loadContextMessages(messages) {
|
|
23518
24564
|
await this.task.loadContextMessages(messages);
|
|
23519
24565
|
}
|
|
24566
|
+
async redoUserPrompt(messageId, mode, updatedPrompt) {
|
|
24567
|
+
await this.task.redoUserPrompt(messageId, mode || "agent", updatedPrompt);
|
|
24568
|
+
}
|
|
23520
24569
|
async redoLastUserPrompt(mode, updatedPrompt) {
|
|
23521
|
-
await this.task.
|
|
24570
|
+
const messages = await this.task.getContextMessages();
|
|
24571
|
+
const lastUserMessage = messages.findLast((msg) => msg.role === "user");
|
|
24572
|
+
if (!lastUserMessage) {
|
|
24573
|
+
return;
|
|
24574
|
+
}
|
|
24575
|
+
await this.task.redoUserPrompt(lastUserMessage.id, mode || "agent", updatedPrompt);
|
|
23522
24576
|
}
|
|
23523
24577
|
async removeMessagesUpTo(messageId) {
|
|
23524
24578
|
await this.task.removeMessagesUpTo(messageId);
|
|
@@ -23721,15 +24775,20 @@ class ProjectContextImpl {
|
|
|
23721
24775
|
}
|
|
23722
24776
|
}
|
|
23723
24777
|
class ExtensionContextImpl {
|
|
23724
|
-
constructor(extensionId, extensionName, store, modelManager, eventManager, project, task) {
|
|
24778
|
+
constructor(extensionId, extensionName, store, modelManager, eventManager, memoryManager, project, task) {
|
|
23725
24779
|
this.extensionId = extensionId;
|
|
23726
24780
|
this.extensionName = extensionName;
|
|
23727
24781
|
this.store = store;
|
|
23728
24782
|
this.modelManager = modelManager;
|
|
23729
24783
|
this.eventManager = eventManager;
|
|
24784
|
+
this.memoryManager = memoryManager;
|
|
23730
24785
|
this.project = project;
|
|
23731
24786
|
this.task = task;
|
|
24787
|
+
this.taskContext = this.task ? new TaskContextImpl(this.task) : null;
|
|
24788
|
+
this.projectContext = this.project ? new ProjectContextImpl(this.project) : null;
|
|
23732
24789
|
}
|
|
24790
|
+
taskContext;
|
|
24791
|
+
projectContext;
|
|
23733
24792
|
log(message, type = "info") {
|
|
23734
24793
|
const logFn = logger[type];
|
|
23735
24794
|
logFn(`[Extension:${this.extensionName}] ${message}`);
|
|
@@ -23738,13 +24797,13 @@ class ExtensionContextImpl {
|
|
|
23738
24797
|
return this.project?.baseDir ?? "";
|
|
23739
24798
|
}
|
|
23740
24799
|
getTaskContext() {
|
|
23741
|
-
return this.
|
|
24800
|
+
return this.taskContext;
|
|
23742
24801
|
}
|
|
23743
24802
|
getProjectContext() {
|
|
23744
|
-
if (!this.
|
|
24803
|
+
if (!this.projectContext) {
|
|
23745
24804
|
throw new Error("Project context not available");
|
|
23746
24805
|
}
|
|
23747
|
-
return
|
|
24806
|
+
return this.projectContext;
|
|
23748
24807
|
}
|
|
23749
24808
|
async getModelConfigs() {
|
|
23750
24809
|
if (!this.modelManager) {
|
|
@@ -23843,6 +24902,12 @@ class ExtensionContextImpl {
|
|
|
23843
24902
|
return false;
|
|
23844
24903
|
}
|
|
23845
24904
|
}
|
|
24905
|
+
getMemoryContext() {
|
|
24906
|
+
if (!this.memoryManager) {
|
|
24907
|
+
throw new Error("MemoryManager not available");
|
|
24908
|
+
}
|
|
24909
|
+
return this.memoryManager;
|
|
24910
|
+
}
|
|
23846
24911
|
}
|
|
23847
24912
|
const CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
23848
24913
|
class ExtensionFetcher {
|
|
@@ -24142,11 +25207,12 @@ class ExtensionFetcher {
|
|
|
24142
25207
|
}
|
|
24143
25208
|
}
|
|
24144
25209
|
class ExtensionManager {
|
|
24145
|
-
constructor(store, modelManager, eventManager, telemetryManager, registry = new ExtensionRegistry()) {
|
|
25210
|
+
constructor(store, modelManager, eventManager, telemetryManager, memoryManager, registry = new ExtensionRegistry()) {
|
|
24146
25211
|
this.store = store;
|
|
24147
25212
|
this.modelManager = modelManager;
|
|
24148
25213
|
this.eventManager = eventManager;
|
|
24149
25214
|
this.telemetryManager = telemetryManager;
|
|
25215
|
+
this.memoryManager = memoryManager;
|
|
24150
25216
|
this.registry = registry;
|
|
24151
25217
|
this.loader = new ExtensionLoader();
|
|
24152
25218
|
this.fetcher = new ExtensionFetcher();
|
|
@@ -24171,7 +25237,7 @@ class ExtensionManager {
|
|
|
24171
25237
|
filterEnabledExtensions(extensions) {
|
|
24172
25238
|
const settings = this.store.getSettings();
|
|
24173
25239
|
const disabledExtensions = settings.extensions?.disabled || [];
|
|
24174
|
-
return extensions.filter((ext) => !disabledExtensions.includes(ext.
|
|
25240
|
+
return extensions.filter((ext) => !disabledExtensions.includes(ext.filePath));
|
|
24175
25241
|
}
|
|
24176
25242
|
/**
|
|
24177
25243
|
* Handle settings changes. Detects when extensions with UI components
|
|
@@ -24189,7 +25255,7 @@ class ExtensionManager {
|
|
|
24189
25255
|
const changedExtensions = [...newlyDisabled, ...newlyEnabled];
|
|
24190
25256
|
if (changedExtensions.length > 0) {
|
|
24191
25257
|
const allExtensions = this.registry.getExtensions();
|
|
24192
|
-
const hasUIComponentsChange = allExtensions.some((ext) => changedExtensions.includes(ext.
|
|
25258
|
+
const hasUIComponentsChange = allExtensions.some((ext) => changedExtensions.includes(ext.filePath) && ext.instance.getUIComponents !== void 0);
|
|
24193
25259
|
if (hasUIComponentsChange) {
|
|
24194
25260
|
logger.debug("[Extensions] Extensions with UI components changed, triggering UI refresh");
|
|
24195
25261
|
this.eventManager.sendExtensionUIRefresh({ reloadComponents: true });
|
|
@@ -24217,6 +25283,7 @@ class ExtensionManager {
|
|
|
24217
25283
|
this.registry.clear();
|
|
24218
25284
|
await this.loadExtensionsForDir(AIDER_DESK_GLOBAL_EXTENSIONS_DIR);
|
|
24219
25285
|
this.initialized = true;
|
|
25286
|
+
this.migrateDisabledExtensions();
|
|
24220
25287
|
await this.startHotReloadWatcher();
|
|
24221
25288
|
this.captureExtensionsTelemetry();
|
|
24222
25289
|
this.preloadAvailableExtensions().catch((error) => {
|
|
@@ -24253,7 +25320,7 @@ class ExtensionManager {
|
|
|
24253
25320
|
return true;
|
|
24254
25321
|
}
|
|
24255
25322
|
try {
|
|
24256
|
-
const context = new ExtensionContextImpl(loaded.id, metadata.name, this.store, this.modelManager, this.eventManager,
|
|
25323
|
+
const context = new ExtensionContextImpl(loaded.id, metadata.name, this.store, this.modelManager, this.eventManager, this.memoryManager, project);
|
|
24257
25324
|
await instance.onLoad(context);
|
|
24258
25325
|
this.registry.setInitialized(filePath, true);
|
|
24259
25326
|
this.eventManager.sendExtensionUIRefresh({
|
|
@@ -24347,13 +25414,51 @@ class ExtensionManager {
|
|
|
24347
25414
|
isInitialized() {
|
|
24348
25415
|
return this.initialized;
|
|
24349
25416
|
}
|
|
25417
|
+
/**
|
|
25418
|
+
* @deprecated Migration helper: converts old name-based disabled list to filePath-based.
|
|
25419
|
+
* Will be removed in a future version.
|
|
25420
|
+
*/
|
|
25421
|
+
migrateDisabledExtensions() {
|
|
25422
|
+
const settings = this.store.getSettings();
|
|
25423
|
+
const disabled = settings.extensions?.disabled;
|
|
25424
|
+
if (!disabled || disabled.length === 0) {
|
|
25425
|
+
return;
|
|
25426
|
+
}
|
|
25427
|
+
const allExtensions = this.registry.getExtensions();
|
|
25428
|
+
const filePaths = new Set(allExtensions.map((ext) => ext.filePath));
|
|
25429
|
+
const migrated = [];
|
|
25430
|
+
let changed = false;
|
|
25431
|
+
for (const item of disabled) {
|
|
25432
|
+
if (filePaths.has(item)) {
|
|
25433
|
+
migrated.push(item);
|
|
25434
|
+
} else {
|
|
25435
|
+
const match = allExtensions.find((ext) => ext.metadata.name === item);
|
|
25436
|
+
if (match) {
|
|
25437
|
+
migrated.push(match.filePath);
|
|
25438
|
+
changed = true;
|
|
25439
|
+
} else {
|
|
25440
|
+
migrated.push(item);
|
|
25441
|
+
}
|
|
25442
|
+
}
|
|
25443
|
+
}
|
|
25444
|
+
if (changed) {
|
|
25445
|
+
logger.info("[Extensions] Migrated disabled extensions from name-based to filePath-based identifiers");
|
|
25446
|
+
this.store.saveSettings({
|
|
25447
|
+
...settings,
|
|
25448
|
+
extensions: {
|
|
25449
|
+
...settings.extensions,
|
|
25450
|
+
disabled: migrated
|
|
25451
|
+
}
|
|
25452
|
+
});
|
|
25453
|
+
}
|
|
25454
|
+
}
|
|
24350
25455
|
captureExtensionsTelemetry() {
|
|
24351
25456
|
const allExtensions = this.registry.getExtensions();
|
|
24352
25457
|
const settings = this.store.getSettings();
|
|
24353
25458
|
const disabledExtensions = settings.extensions?.disabled || [];
|
|
24354
25459
|
const globalExtensions = allExtensions.filter((ext) => !ext.projectDir).length;
|
|
24355
25460
|
const projectExtensions = allExtensions.filter((ext) => ext.projectDir).length;
|
|
24356
|
-
const enabledCount = allExtensions.filter((ext) => !disabledExtensions.includes(ext.
|
|
25461
|
+
const enabledCount = allExtensions.filter((ext) => !disabledExtensions.includes(ext.filePath)).length;
|
|
24357
25462
|
this.telemetryManager.captureExtensionsLoaded(allExtensions.length, globalExtensions, projectExtensions, enabledCount, disabledExtensions.length);
|
|
24358
25463
|
}
|
|
24359
25464
|
async dispose() {
|
|
@@ -24588,7 +25693,16 @@ class ExtensionManager {
|
|
|
24588
25693
|
continue;
|
|
24589
25694
|
}
|
|
24590
25695
|
try {
|
|
24591
|
-
const context = new ExtensionContextImpl(
|
|
25696
|
+
const context = new ExtensionContextImpl(
|
|
25697
|
+
loaded.id,
|
|
25698
|
+
metadata.name,
|
|
25699
|
+
this.store,
|
|
25700
|
+
this.modelManager,
|
|
25701
|
+
this.eventManager,
|
|
25702
|
+
this.memoryManager,
|
|
25703
|
+
task.project,
|
|
25704
|
+
task
|
|
25705
|
+
);
|
|
24592
25706
|
const tools = instance.getTools(context, mode, profile);
|
|
24593
25707
|
if (!Array.isArray(tools)) {
|
|
24594
25708
|
logger.error(`[Extensions] Extension '${metadata.name}' getTools() did not return an array`);
|
|
@@ -24628,7 +25742,16 @@ class ExtensionManager {
|
|
|
24628
25742
|
const registeredTools = this.getTools(task, mode, profile);
|
|
24629
25743
|
for (const { extensionId, extensionName, tool } of registeredTools) {
|
|
24630
25744
|
const toolId = tool.name;
|
|
24631
|
-
const context = new ExtensionContextImpl(
|
|
25745
|
+
const context = new ExtensionContextImpl(
|
|
25746
|
+
extensionId,
|
|
25747
|
+
extensionName,
|
|
25748
|
+
this.store,
|
|
25749
|
+
this.modelManager,
|
|
25750
|
+
this.eventManager,
|
|
25751
|
+
this.memoryManager,
|
|
25752
|
+
task.project,
|
|
25753
|
+
task
|
|
25754
|
+
);
|
|
24632
25755
|
if (profile.toolApprovals?.[toolId] === ToolApprovalState.Never) {
|
|
24633
25756
|
logger.debug(`[Extensions] Skipping tool '${tool.name}' (marked as Never approved)`);
|
|
24634
25757
|
continue;
|
|
@@ -24709,7 +25832,7 @@ class ExtensionManager {
|
|
|
24709
25832
|
continue;
|
|
24710
25833
|
}
|
|
24711
25834
|
try {
|
|
24712
|
-
const context = new ExtensionContextImpl(loaded.id, metadata.name, this.store, this.modelManager, this.eventManager,
|
|
25835
|
+
const context = new ExtensionContextImpl(loaded.id, metadata.name, this.store, this.modelManager, this.eventManager, this.memoryManager, project);
|
|
24713
25836
|
const commands = instance.getCommands(context);
|
|
24714
25837
|
if (!Array.isArray(commands)) {
|
|
24715
25838
|
logger.error(`[Extensions] Extension '${metadata.name}' getCommands() did not return an array`);
|
|
@@ -24743,7 +25866,7 @@ class ExtensionManager {
|
|
|
24743
25866
|
continue;
|
|
24744
25867
|
}
|
|
24745
25868
|
try {
|
|
24746
|
-
const context = new ExtensionContextImpl(loaded.id, metadata.name, this.store, this.modelManager, this.eventManager,
|
|
25869
|
+
const context = new ExtensionContextImpl(loaded.id, metadata.name, this.store, this.modelManager, this.eventManager, this.memoryManager, project);
|
|
24747
25870
|
const agents = instance.getAgents(context);
|
|
24748
25871
|
if (!Array.isArray(agents)) {
|
|
24749
25872
|
logger.error(`[Extensions] Extension '${metadata.name}' getAgents() did not return an array`);
|
|
@@ -24783,7 +25906,7 @@ class ExtensionManager {
|
|
|
24783
25906
|
continue;
|
|
24784
25907
|
}
|
|
24785
25908
|
try {
|
|
24786
|
-
const context = new ExtensionContextImpl(loaded.id, metadata.name, this.store, this.modelManager, this.eventManager,
|
|
25909
|
+
const context = new ExtensionContextImpl(loaded.id, metadata.name, this.store, this.modelManager, this.eventManager, this.memoryManager, project);
|
|
24787
25910
|
const modes = instance.getModes(context);
|
|
24788
25911
|
if (!Array.isArray(modes)) {
|
|
24789
25912
|
logger.error(`[Extensions] Extension '${metadata.name}' getModes() did not return an array`);
|
|
@@ -24836,7 +25959,7 @@ class ExtensionManager {
|
|
|
24836
25959
|
continue;
|
|
24837
25960
|
}
|
|
24838
25961
|
try {
|
|
24839
|
-
const context = new ExtensionContextImpl(loaded.id, metadata.name, this.store, this.modelManager, this.eventManager,
|
|
25962
|
+
const context = new ExtensionContextImpl(loaded.id, metadata.name, this.store, this.modelManager, this.eventManager, this.memoryManager, project);
|
|
24840
25963
|
const providers = instance.getProviders(context);
|
|
24841
25964
|
if (!Array.isArray(providers)) {
|
|
24842
25965
|
logger.error(`[Extensions] Extension '${metadata.name}' getProviders() did not return an array`);
|
|
@@ -24859,6 +25982,42 @@ class ExtensionManager {
|
|
|
24859
25982
|
}
|
|
24860
25983
|
return collectedProviders;
|
|
24861
25984
|
}
|
|
25985
|
+
getSkills(project, task) {
|
|
25986
|
+
const collectedSkills = [];
|
|
25987
|
+
const allExtensions = this.registry.getExtensions(project.baseDir);
|
|
25988
|
+
const extensions = this.filterEnabledExtensions(allExtensions);
|
|
25989
|
+
for (const loaded of extensions) {
|
|
25990
|
+
const { instance, metadata } = loaded;
|
|
25991
|
+
if (!instance.getSkills) {
|
|
25992
|
+
continue;
|
|
25993
|
+
}
|
|
25994
|
+
try {
|
|
25995
|
+
const context = new ExtensionContextImpl(loaded.id, metadata.name, this.store, this.modelManager, this.eventManager, this.memoryManager, project, task);
|
|
25996
|
+
const skills = instance.getSkills(context);
|
|
25997
|
+
if (!Array.isArray(skills)) {
|
|
25998
|
+
logger.error(`[Extensions] Extension '${metadata.name}' getSkills() did not return an array`);
|
|
25999
|
+
continue;
|
|
26000
|
+
}
|
|
26001
|
+
for (const skill of skills) {
|
|
26002
|
+
if (!skill.name || !skill.description) {
|
|
26003
|
+
logger.error(`[Extensions] Invalid skill from extension '${metadata.name}': missing name or description`);
|
|
26004
|
+
continue;
|
|
26005
|
+
}
|
|
26006
|
+
if (!skill.dirPath && !skill.content) {
|
|
26007
|
+
logger.error(`[Extensions] Invalid skill from extension '${metadata.name}': must have dirPath or content`);
|
|
26008
|
+
continue;
|
|
26009
|
+
}
|
|
26010
|
+
collectedSkills.push({
|
|
26011
|
+
...skill,
|
|
26012
|
+
location: "extension"
|
|
26013
|
+
});
|
|
26014
|
+
}
|
|
26015
|
+
} catch (error) {
|
|
26016
|
+
logger.error(`[Extensions] Failed to get skills from extension '${metadata.name}':`, error);
|
|
26017
|
+
}
|
|
26018
|
+
}
|
|
26019
|
+
return collectedSkills;
|
|
26020
|
+
}
|
|
24862
26021
|
getUIComponents(project, task) {
|
|
24863
26022
|
const collectedComponents = [];
|
|
24864
26023
|
const allExtensions = this.registry.getExtensions(project?.baseDir);
|
|
@@ -24872,7 +26031,7 @@ class ExtensionManager {
|
|
|
24872
26031
|
continue;
|
|
24873
26032
|
}
|
|
24874
26033
|
try {
|
|
24875
|
-
const context = new ExtensionContextImpl(loaded.id, metadata.name, this.store, this.modelManager, this.eventManager, project, task);
|
|
26034
|
+
const context = new ExtensionContextImpl(loaded.id, metadata.name, this.store, this.modelManager, this.eventManager, this.memoryManager, project, task);
|
|
24876
26035
|
const components = instance.getUIComponents(context);
|
|
24877
26036
|
if (!Array.isArray(components)) {
|
|
24878
26037
|
logger.error(`[Extensions] Extension '${metadata.name}' getUIComponents() did not return an array`);
|
|
@@ -24906,7 +26065,7 @@ class ExtensionManager {
|
|
|
24906
26065
|
return false;
|
|
24907
26066
|
}
|
|
24908
26067
|
try {
|
|
24909
|
-
const context = new ExtensionContextImpl(loadedExt.id, loadedExt.metadata.name, this.store, this.modelManager, this.eventManager);
|
|
26068
|
+
const context = new ExtensionContextImpl(loadedExt.id, loadedExt.metadata.name, this.store, this.modelManager, this.eventManager, this.memoryManager);
|
|
24910
26069
|
const jsx = instance.getConfigComponent(context);
|
|
24911
26070
|
return typeof jsx === "string" && jsx.length > 0;
|
|
24912
26071
|
} catch {
|
|
@@ -24930,7 +26089,7 @@ class ExtensionManager {
|
|
|
24930
26089
|
}
|
|
24931
26090
|
try {
|
|
24932
26091
|
logger.debug(`[Extensions] Getting UI extension data from '${id}' for component '${componentId}'`);
|
|
24933
|
-
const context = new ExtensionContextImpl(id, metadata.name, this.store, this.modelManager, this.eventManager, project, task);
|
|
26092
|
+
const context = new ExtensionContextImpl(id, metadata.name, this.store, this.modelManager, this.eventManager, this.memoryManager, project, task);
|
|
24934
26093
|
return await instance.getUIExtensionData(componentId, context);
|
|
24935
26094
|
} catch (error) {
|
|
24936
26095
|
logger.error(`[Extensions] Failed to get UI extension data from '${id}' for component '${componentId}':`, error);
|
|
@@ -24956,7 +26115,7 @@ class ExtensionManager {
|
|
|
24956
26115
|
}
|
|
24957
26116
|
try {
|
|
24958
26117
|
logger.debug(`[Extensions] Executing UI extension action '${action}' from '${id}' for component '${componentId}'`);
|
|
24959
|
-
const context = new ExtensionContextImpl(id, metadata.name, this.store, this.modelManager, this.eventManager, project, task);
|
|
26118
|
+
const context = new ExtensionContextImpl(id, metadata.name, this.store, this.modelManager, this.eventManager, this.memoryManager, project, task);
|
|
24960
26119
|
return await instance.executeUIExtensionAction(componentId, action, args, context);
|
|
24961
26120
|
} catch (error) {
|
|
24962
26121
|
logger.error(`[Extensions] Failed to execute UI extension action '${action}' from '${id}' for component '${componentId}':`, error);
|
|
@@ -24979,7 +26138,15 @@ class ExtensionManager {
|
|
|
24979
26138
|
return null;
|
|
24980
26139
|
}
|
|
24981
26140
|
try {
|
|
24982
|
-
const context = new ExtensionContextImpl(
|
|
26141
|
+
const context = new ExtensionContextImpl(
|
|
26142
|
+
loaded.id,
|
|
26143
|
+
loaded.metadata.name,
|
|
26144
|
+
this.store,
|
|
26145
|
+
this.modelManager,
|
|
26146
|
+
this.eventManager,
|
|
26147
|
+
this.memoryManager,
|
|
26148
|
+
project
|
|
26149
|
+
);
|
|
24983
26150
|
const jsx = loaded.instance.getConfigComponent(context);
|
|
24984
26151
|
if (typeof jsx !== "string" || jsx.length === 0) {
|
|
24985
26152
|
return null;
|
|
@@ -25007,7 +26174,15 @@ class ExtensionManager {
|
|
|
25007
26174
|
return null;
|
|
25008
26175
|
}
|
|
25009
26176
|
try {
|
|
25010
|
-
const context = new ExtensionContextImpl(
|
|
26177
|
+
const context = new ExtensionContextImpl(
|
|
26178
|
+
loaded.id,
|
|
26179
|
+
loaded.metadata.name,
|
|
26180
|
+
this.store,
|
|
26181
|
+
this.modelManager,
|
|
26182
|
+
this.eventManager,
|
|
26183
|
+
this.memoryManager,
|
|
26184
|
+
project
|
|
26185
|
+
);
|
|
25011
26186
|
return await loaded.instance.getConfigData(context);
|
|
25012
26187
|
} catch (error) {
|
|
25013
26188
|
logger.error(`[Extensions] Failed to get config data from extension '${extensionId}':`, error);
|
|
@@ -25031,7 +26206,15 @@ class ExtensionManager {
|
|
|
25031
26206
|
return null;
|
|
25032
26207
|
}
|
|
25033
26208
|
try {
|
|
25034
|
-
const context = new ExtensionContextImpl(
|
|
26209
|
+
const context = new ExtensionContextImpl(
|
|
26210
|
+
loaded.id,
|
|
26211
|
+
loaded.metadata.name,
|
|
26212
|
+
this.store,
|
|
26213
|
+
this.modelManager,
|
|
26214
|
+
this.eventManager,
|
|
26215
|
+
this.memoryManager,
|
|
26216
|
+
project
|
|
26217
|
+
);
|
|
25035
26218
|
return await loaded.instance.saveConfigData(configData, context);
|
|
25036
26219
|
} catch (error) {
|
|
25037
26220
|
logger.error(`[Extensions] Failed to save config data for extension '${extensionId}':`, error);
|
|
@@ -25064,7 +26247,7 @@ class ExtensionManager {
|
|
|
25064
26247
|
continue;
|
|
25065
26248
|
}
|
|
25066
26249
|
try {
|
|
25067
|
-
const context = new ExtensionContextImpl(loaded.id, metadata.name, this.store, this.modelManager, this.eventManager,
|
|
26250
|
+
const context = new ExtensionContextImpl(loaded.id, metadata.name, this.store, this.modelManager, this.eventManager, this.memoryManager);
|
|
25068
26251
|
const agents = instance.getAgents(context);
|
|
25069
26252
|
if (!Array.isArray(agents)) {
|
|
25070
26253
|
continue;
|
|
@@ -25100,7 +26283,7 @@ class ExtensionManager {
|
|
|
25100
26283
|
}
|
|
25101
26284
|
const { extensionId, extensionName, command } = registered;
|
|
25102
26285
|
try {
|
|
25103
|
-
const context = new ExtensionContextImpl(extensionId, extensionName, this.store, this.modelManager, this.eventManager, project, task);
|
|
26286
|
+
const context = new ExtensionContextImpl(extensionId, extensionName, this.store, this.modelManager, this.eventManager, this.memoryManager, project, task);
|
|
25104
26287
|
logger.debug(`[Extensions] Executing command '${commandName}' from extension '${extensionName}'`);
|
|
25105
26288
|
await command.execute(args, context);
|
|
25106
26289
|
logger.debug(`[Extensions] Command '${commandName}' executed successfully`);
|
|
@@ -25275,6 +26458,15 @@ class ExtensionManager {
|
|
|
25275
26458
|
throw new Error("Invalid GitHub repository URL");
|
|
25276
26459
|
}
|
|
25277
26460
|
await this.unloadExtensionsForDir(targetDir);
|
|
26461
|
+
const parsedExistingPath = path.parse(existingExtension.filePath);
|
|
26462
|
+
const existingIsFolder = parsedExistingPath.name === "index";
|
|
26463
|
+
if (extension.type === "folder" && !existingIsFolder) {
|
|
26464
|
+
await fs.unlink(existingExtension.filePath);
|
|
26465
|
+
logger.debug(`[Extensions] Removed old single-file extension: ${existingExtension.filePath}`);
|
|
26466
|
+
} else if (extension.type === "single" && existingIsFolder) {
|
|
26467
|
+
await fs.rm(parsedExistingPath.dir, { recursive: true, force: true });
|
|
26468
|
+
logger.debug(`[Extensions] Removed old folder extension: ${parsedExistingPath.dir}`);
|
|
26469
|
+
}
|
|
25278
26470
|
if (extension.type === "single" && extension.file) {
|
|
25279
26471
|
const url = `${githubRawBase}/${extension.file}`;
|
|
25280
26472
|
const response = await fetch(url);
|
|
@@ -25338,7 +26530,7 @@ class ExtensionManager {
|
|
|
25338
26530
|
}
|
|
25339
26531
|
logger.debug(`[Extensions] Dispatching event '${String(eventName)}' to extension '${metadata.name}'`);
|
|
25340
26532
|
try {
|
|
25341
|
-
const context = new ExtensionContextImpl(loaded.id, metadata.name, this.store, this.modelManager, this.eventManager, project, task);
|
|
26533
|
+
const context = new ExtensionContextImpl(loaded.id, metadata.name, this.store, this.modelManager, this.eventManager, this.memoryManager, project, task);
|
|
25342
26534
|
const result = await handler.call(instance, currentEvent, context);
|
|
25343
26535
|
if (result && typeof result === "object") {
|
|
25344
26536
|
const partialEvent = result;
|
|
@@ -25361,13 +26553,13 @@ class ExtensionManager {
|
|
|
25361
26553
|
* @returns Sorted array of extensions
|
|
25362
26554
|
*/
|
|
25363
26555
|
sortExtensionsForDispatch(extensions, projectDir) {
|
|
25364
|
-
const
|
|
26556
|
+
const global2 = extensions.filter((e) => !e.projectDir);
|
|
25365
26557
|
const projectSpecific = extensions.filter((e) => e.projectDir === projectDir);
|
|
25366
|
-
return [...
|
|
26558
|
+
return [...global2, ...projectSpecific];
|
|
25367
26559
|
}
|
|
25368
26560
|
}
|
|
25369
26561
|
class EventsHandler {
|
|
25370
|
-
constructor(projectManager, store, mcpManager, versionsManager, modelManager, telemetryManager, dataManager, terminalManager, cloudflareTunnelManager, eventManager, agentProfileManager, memoryManager, extensionManager, windowManager) {
|
|
26562
|
+
constructor(projectManager, store, mcpManager, versionsManager, modelManager, telemetryManager, dataManager, terminalManager, cloudflareTunnelManager, eventManager, agentProfileManager, memoryManager, extensionManager, proxyManager, windowManager) {
|
|
25371
26563
|
this.projectManager = projectManager;
|
|
25372
26564
|
this.store = store;
|
|
25373
26565
|
this.mcpManager = mcpManager;
|
|
@@ -25381,6 +26573,7 @@ class EventsHandler {
|
|
|
25381
26573
|
this.agentProfileManager = agentProfileManager;
|
|
25382
26574
|
this.memoryManager = memoryManager;
|
|
25383
26575
|
this.extensionManager = extensionManager;
|
|
26576
|
+
this.proxyManager = proxyManager;
|
|
25384
26577
|
this.windowManager = windowManager;
|
|
25385
26578
|
}
|
|
25386
26579
|
loadSettings() {
|
|
@@ -25389,6 +26582,7 @@ class EventsHandler {
|
|
|
25389
26582
|
async saveSettings(newSettings) {
|
|
25390
26583
|
const oldSettings = this.store.getSettings();
|
|
25391
26584
|
this.store.saveSettings(newSettings);
|
|
26585
|
+
this.proxyManager.settingsChanged(oldSettings, newSettings);
|
|
25392
26586
|
void this.projectManager.settingsChanged(oldSettings, newSettings);
|
|
25393
26587
|
this.telemetryManager.settingsChanged(oldSettings, newSettings);
|
|
25394
26588
|
void this.memoryManager.settingsChanged(oldSettings, newSettings);
|
|
@@ -25443,7 +26637,7 @@ class EventsHandler {
|
|
|
25443
26637
|
}
|
|
25444
26638
|
async addOpenProject(baseDir) {
|
|
25445
26639
|
const projects = this.store.getOpenProjects();
|
|
25446
|
-
const existingProject = projects.find((p) =>
|
|
26640
|
+
const existingProject = projects.find((p) => compareBaseDirs$1(p.baseDir, baseDir));
|
|
25447
26641
|
if (!existingProject) {
|
|
25448
26642
|
logger.info("EventsHandler: addOpenProject", { baseDir });
|
|
25449
26643
|
const providerModels = await this.modelManager.getProviderModels();
|
|
@@ -25460,7 +26654,7 @@ class EventsHandler {
|
|
|
25460
26654
|
}
|
|
25461
26655
|
removeOpenProject(baseDir) {
|
|
25462
26656
|
const projects = this.store.getOpenProjects();
|
|
25463
|
-
const updatedProjects = projects.filter((project) =>
|
|
26657
|
+
const updatedProjects = projects.filter((project) => !compareBaseDirs$1(project.baseDir, baseDir));
|
|
25464
26658
|
if (updatedProjects.length > 0) {
|
|
25465
26659
|
if (!updatedProjects.some((p) => p.active)) {
|
|
25466
26660
|
updatedProjects[updatedProjects.length - 1].active = true;
|
|
@@ -25510,8 +26704,8 @@ class EventsHandler {
|
|
|
25510
26704
|
const removedIds = await this.projectManager.getProject(baseDir).getTask(taskId)?.removeMessagesUpTo(messageId) ?? [];
|
|
25511
26705
|
this.eventManager.sendTaskMessageRemoved(baseDir, taskId, removedIds);
|
|
25512
26706
|
}
|
|
25513
|
-
async
|
|
25514
|
-
void this.projectManager.getProject(baseDir).getTask(taskId)?.
|
|
26707
|
+
async redoUserPrompt(baseDir, taskId, messageId, mode, updatedPrompt) {
|
|
26708
|
+
void this.projectManager.getProject(baseDir).getTask(taskId)?.redoUserPrompt(messageId, mode, updatedPrompt);
|
|
25515
26709
|
}
|
|
25516
26710
|
async resumeTask(baseDir, taskId) {
|
|
25517
26711
|
void this.projectManager.getProject(baseDir).getTask(taskId)?.resumeTask();
|
|
@@ -25530,8 +26724,8 @@ class EventsHandler {
|
|
|
25530
26724
|
const mode = this.store.getProjectSettings(baseDir).currentMode || "agent";
|
|
25531
26725
|
await task.handoffConversation(mode, focus);
|
|
25532
26726
|
}
|
|
25533
|
-
async
|
|
25534
|
-
await this.projectManager.getProject(baseDir).getTask(taskId)?.
|
|
26727
|
+
async runCodeChangeRequests(baseDir, taskId, requests, createNewTask) {
|
|
26728
|
+
await this.projectManager.getProject(baseDir).getTask(taskId)?.runCodeChangeRequests(requests, 5, createNewTask);
|
|
25535
26729
|
}
|
|
25536
26730
|
async loadInputHistory(baseDir) {
|
|
25537
26731
|
return await this.projectManager.getProject(baseDir).loadInputHistory();
|
|
@@ -25740,6 +26934,13 @@ class EventsHandler {
|
|
|
25740
26934
|
}
|
|
25741
26935
|
await task.mergeWorktreeToMain(squash, targetBranch, commitMessage);
|
|
25742
26936
|
}
|
|
26937
|
+
async mergeAndSwitchToLocal(baseDir, taskId, targetBranch) {
|
|
26938
|
+
const task = this.projectManager.getProject(baseDir).getTask(taskId);
|
|
26939
|
+
if (!task) {
|
|
26940
|
+
throw new Error(`Task ${taskId} not found`);
|
|
26941
|
+
}
|
|
26942
|
+
await task.mergeAndSwitchToLocal(targetBranch);
|
|
26943
|
+
}
|
|
25743
26944
|
async applyUncommittedChanges(baseDir, taskId, targetBranch) {
|
|
25744
26945
|
const task = this.projectManager.getProject(baseDir).getTask(taskId);
|
|
25745
26946
|
if (!task) {
|
|
@@ -25761,8 +26962,9 @@ class EventsHandler {
|
|
|
25761
26962
|
}
|
|
25762
26963
|
await task.restoreFile(filePath);
|
|
25763
26964
|
}
|
|
25764
|
-
async readFile(baseDir, filePath) {
|
|
25765
|
-
const
|
|
26965
|
+
async readFile(baseDir, taskId, filePath) {
|
|
26966
|
+
const task = this.projectManager.getProject(baseDir).getTask(taskId);
|
|
26967
|
+
const absolutePath = path.isAbsolute(filePath) ? filePath : task ? await task.resolveContextFilePath(filePath) ?? path.join(baseDir, filePath) : path.join(baseDir, filePath);
|
|
25766
26968
|
const fileContentBuffer = await fs.readFile(absolutePath);
|
|
25767
26969
|
if (istextorbinary.isBinary(filePath, fileContentBuffer)) {
|
|
25768
26970
|
throw new Error("Cannot read binary file");
|
|
@@ -25821,6 +27023,13 @@ class EventsHandler {
|
|
|
25821
27023
|
}
|
|
25822
27024
|
await task.resolveConflictsWithAgent();
|
|
25823
27025
|
}
|
|
27026
|
+
async renameWorktreeBranch(baseDir, taskId, newBranchName) {
|
|
27027
|
+
const task = this.projectManager.getProject(baseDir).getTask(taskId);
|
|
27028
|
+
if (!task) {
|
|
27029
|
+
throw new Error(`Task ${taskId} not found`);
|
|
27030
|
+
}
|
|
27031
|
+
await task.renameWorktreeBranch(newBranchName);
|
|
27032
|
+
}
|
|
25824
27033
|
async scrapeWeb(baseDir, taskId, url, filePath) {
|
|
25825
27034
|
const content = await scrapeWeb(url);
|
|
25826
27035
|
const project = this.projectManager.getProject(baseDir);
|
|
@@ -26099,6 +27308,17 @@ ${error instanceof Error ? error.message : String(error)}`);
|
|
|
26099
27308
|
async initProjectRulesFile(baseDir, taskId, args) {
|
|
26100
27309
|
return this.projectManager.getProject(baseDir).getTask(taskId)?.initProjectAgentsFile(args);
|
|
26101
27310
|
}
|
|
27311
|
+
async getSkills(baseDir, taskId) {
|
|
27312
|
+
return await this.projectManager.getProject(baseDir).getTask(taskId)?.getSkills() || [];
|
|
27313
|
+
}
|
|
27314
|
+
async activateSkill(baseDir, taskId, skillName) {
|
|
27315
|
+
await this.projectManager.getProject(baseDir).getTask(taskId)?.activateSkill(skillName);
|
|
27316
|
+
void this.projectManager.getProject(baseDir).getTask(taskId)?.sendSkillsUpdated();
|
|
27317
|
+
}
|
|
27318
|
+
async deactivateSkill(baseDir, taskId, skillName) {
|
|
27319
|
+
const removedIds = await this.projectManager.getProject(baseDir).getTask(taskId)?.deactivateSkill(skillName) ?? [];
|
|
27320
|
+
this.eventManager.sendTaskMessageRemoved(baseDir, taskId, removedIds);
|
|
27321
|
+
}
|
|
26102
27322
|
async enableServer(username, password) {
|
|
26103
27323
|
const currentSettings = this.store.getSettings();
|
|
26104
27324
|
const updatedSettings = {
|
|
@@ -26387,7 +27607,7 @@ class PromptsManager {
|
|
|
26387
27607
|
"conflict-resolution-system",
|
|
26388
27608
|
"update-task-state",
|
|
26389
27609
|
"handoff",
|
|
26390
|
-
"code-
|
|
27610
|
+
"code-change-requests"
|
|
26391
27611
|
];
|
|
26392
27612
|
}
|
|
26393
27613
|
async loadGlobalTemplateSource(name) {
|
|
@@ -26594,6 +27814,7 @@ class PromptsManager {
|
|
|
26594
27814
|
};
|
|
26595
27815
|
getRulesContent = async (task, agentProfile) => {
|
|
26596
27816
|
const ruleFiles = await task.getRuleFilesAsContextFiles(agentProfile);
|
|
27817
|
+
logger.debug("Rule files for prompt content:", { ruleFiles });
|
|
26597
27818
|
const ruleFilesContent = await Promise.all(
|
|
26598
27819
|
ruleFiles.map(async (file) => {
|
|
26599
27820
|
try {
|
|
@@ -26664,8 +27885,8 @@ ${content}
|
|
|
26664
27885
|
};
|
|
26665
27886
|
return await this.render("handoff", data, task.getProjectDir(), task);
|
|
26666
27887
|
};
|
|
26667
|
-
|
|
26668
|
-
return await this.render("code-
|
|
27888
|
+
getCodeChangeRequestsPrompt = async (task, data) => {
|
|
27889
|
+
return await this.render("code-change-requests", data, task.getProjectDir(), task);
|
|
26669
27890
|
};
|
|
26670
27891
|
}
|
|
26671
27892
|
const execAsync = util.promisify(child_process.exec);
|
|
@@ -26925,6 +28146,8 @@ class PythonDependenciesInstaller {
|
|
|
26925
28146
|
}
|
|
26926
28147
|
}
|
|
26927
28148
|
const initManagers = async (store, windowManager) => {
|
|
28149
|
+
const proxyManager = new ProxyManager();
|
|
28150
|
+
proxyManager.init(store.getSettings());
|
|
26928
28151
|
const telemetryManager = new TelemetryManager(store);
|
|
26929
28152
|
telemetryManager.init().catch((error) => {
|
|
26930
28153
|
logger.error("[Telemetry] Telemetry initialization failed, continuing without analytics:", error);
|
|
@@ -26943,7 +28166,7 @@ const initManagers = async (store, windowManager) => {
|
|
|
26943
28166
|
memoryManager.init().catch((error) => {
|
|
26944
28167
|
logger.error("[Memory] Memory system initialization failed, continuing without memories:", error);
|
|
26945
28168
|
});
|
|
26946
|
-
const extensionManager = new ExtensionManager(store, modelManager, eventManager, telemetryManager);
|
|
28169
|
+
const extensionManager = new ExtensionManager(store, modelManager, eventManager, telemetryManager, memoryManager);
|
|
26947
28170
|
extensionManager.init().catch((error) => {
|
|
26948
28171
|
logger.error("[Extensions] Extension system initialization failed, continuing without extensions:", error);
|
|
26949
28172
|
});
|
|
@@ -26988,10 +28211,11 @@ const initManagers = async (store, windowManager) => {
|
|
|
26988
28211
|
agentProfileManager,
|
|
26989
28212
|
memoryManager,
|
|
26990
28213
|
extensionManager,
|
|
28214
|
+
proxyManager,
|
|
26991
28215
|
windowManager
|
|
26992
28216
|
);
|
|
26993
|
-
const serverController = new ServerController(httpServer, projectManager, eventsHandler, store);
|
|
26994
|
-
const connectorManager = new ConnectorManager(httpServer, projectManager, eventManager);
|
|
28217
|
+
const serverController = new ServerController(httpServer, projectManager, eventsHandler, store, pythonInstaller);
|
|
28218
|
+
const connectorManager = new ConnectorManager(httpServer, projectManager, eventManager, store);
|
|
26995
28219
|
httpServer.listen(SERVER_PORT);
|
|
26996
28220
|
logger.info(`AiderDesk headless server listening on http://localhost:${SERVER_PORT}`);
|
|
26997
28221
|
let cleanedUp = false;
|
|
@@ -27579,6 +28803,10 @@ const DEFAULT_SETTINGS = {
|
|
|
27579
28803
|
enabled: false,
|
|
27580
28804
|
username: "",
|
|
27581
28805
|
password: ""
|
|
28806
|
+
},
|
|
28807
|
+
cors: {
|
|
28808
|
+
enabled: false,
|
|
28809
|
+
origins: []
|
|
27582
28810
|
}
|
|
27583
28811
|
},
|
|
27584
28812
|
memory: {
|
|
@@ -27594,11 +28822,17 @@ const DEFAULT_SETTINGS = {
|
|
|
27594
28822
|
worktreeSymlinkFolders: ["node_modules", "vendor", "__pycache__", ".venv", "venv"],
|
|
27595
28823
|
contextCompactingThreshold: 0,
|
|
27596
28824
|
contextCompactionType: ContextCompactionType.Compact,
|
|
27597
|
-
defaultWorkingMode: "local"
|
|
28825
|
+
defaultWorkingMode: "local",
|
|
28826
|
+
worktreeBranchPrefix: "aider-desk/task/",
|
|
28827
|
+
renameBranchOnNameGeneration: true
|
|
27598
28828
|
},
|
|
27599
28829
|
extensions: {
|
|
27600
28830
|
repositories: [AIDER_DESK_EXTENSIONS_REPO_URL],
|
|
27601
28831
|
disabled: []
|
|
28832
|
+
},
|
|
28833
|
+
proxy: {
|
|
28834
|
+
enabled: false,
|
|
28835
|
+
url: ""
|
|
27602
28836
|
}
|
|
27603
28837
|
};
|
|
27604
28838
|
const compareBaseDirs = (baseDir1, baseDir2) => {
|
|
@@ -27654,7 +28888,14 @@ class Store {
|
|
|
27654
28888
|
}
|
|
27655
28889
|
},
|
|
27656
28890
|
mcpServers: settings.mcpServers || DEFAULT_SETTINGS.mcpServers,
|
|
27657
|
-
server:
|
|
28891
|
+
server: {
|
|
28892
|
+
...DEFAULT_SETTINGS.server,
|
|
28893
|
+
...settings.server,
|
|
28894
|
+
cors: {
|
|
28895
|
+
...DEFAULT_SETTINGS.server.cors,
|
|
28896
|
+
...settings.server?.cors
|
|
28897
|
+
}
|
|
28898
|
+
},
|
|
27658
28899
|
memory: {
|
|
27659
28900
|
...DEFAULT_SETTINGS.memory,
|
|
27660
28901
|
...settings?.memory
|