grepmind-app 0.1.0-alpha
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/LICENSE +190 -0
- package/dist/context.d.ts +43 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +230 -0
- package/dist/context.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +120 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/secrets.d.ts +21 -0
- package/dist/middleware/secrets.d.ts.map +1 -0
- package/dist/middleware/secrets.js +38 -0
- package/dist/middleware/secrets.js.map +1 -0
- package/dist/routes/code.d.ts +61 -0
- package/dist/routes/code.d.ts.map +1 -0
- package/dist/routes/code.js +974 -0
- package/dist/routes/code.js.map +1 -0
- package/dist/routes/code.test.d.ts +7 -0
- package/dist/routes/code.test.d.ts.map +1 -0
- package/dist/routes/code.test.js +418 -0
- package/dist/routes/code.test.js.map +1 -0
- package/dist/routes/events.d.ts +30 -0
- package/dist/routes/events.d.ts.map +1 -0
- package/dist/routes/events.js +152 -0
- package/dist/routes/events.js.map +1 -0
- package/dist/routes/git.d.ts +47 -0
- package/dist/routes/git.d.ts.map +1 -0
- package/dist/routes/git.js +246 -0
- package/dist/routes/git.js.map +1 -0
- package/dist/routes/index.d.ts +6 -0
- package/dist/routes/index.d.ts.map +1 -0
- package/dist/routes/index.js +6 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/routes/notes.d.ts +38 -0
- package/dist/routes/notes.d.ts.map +1 -0
- package/dist/routes/notes.js +829 -0
- package/dist/routes/notes.js.map +1 -0
- package/dist/routes/project.d.ts +35 -0
- package/dist/routes/project.d.ts.map +1 -0
- package/dist/routes/project.js +675 -0
- package/dist/routes/project.js.map +1 -0
- package/dist/routes/sync-handler.d.ts +46 -0
- package/dist/routes/sync-handler.d.ts.map +1 -0
- package/dist/routes/sync-handler.js +178 -0
- package/dist/routes/sync-handler.js.map +1 -0
- package/dist/routes/sync.d.ts +31 -0
- package/dist/routes/sync.d.ts.map +1 -0
- package/dist/routes/sync.js +329 -0
- package/dist/routes/sync.js.map +1 -0
- package/dist/server.d.ts +28 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +93 -0
- package/dist/server.js.map +1 -0
- package/dist/tesst.d.ts +2 -0
- package/dist/tesst.d.ts.map +1 -0
- package/dist/tesst.js +2 -0
- package/dist/tesst.js.map +1 -0
- package/dist/web/assets/apl-B4CMkyY2.js +2 -0
- package/dist/web/assets/apl-B4CMkyY2.js.map +1 -0
- package/dist/web/assets/asciiarmor-Df11BRmG.js +2 -0
- package/dist/web/assets/asciiarmor-Df11BRmG.js.map +1 -0
- package/dist/web/assets/asn1-EdZsLKOL.js +2 -0
- package/dist/web/assets/asn1-EdZsLKOL.js.map +1 -0
- package/dist/web/assets/asterisk-B-8jnY81.js +2 -0
- package/dist/web/assets/asterisk-B-8jnY81.js.map +1 -0
- package/dist/web/assets/brainfuck-C4LP7Hcl.js +2 -0
- package/dist/web/assets/brainfuck-C4LP7Hcl.js.map +1 -0
- package/dist/web/assets/clike-B9uivgTg.js +2 -0
- package/dist/web/assets/clike-B9uivgTg.js.map +1 -0
- package/dist/web/assets/clojure-BMjYHr_A.js +2 -0
- package/dist/web/assets/clojure-BMjYHr_A.js.map +1 -0
- package/dist/web/assets/cmake-BQqOBYOt.js +2 -0
- package/dist/web/assets/cmake-BQqOBYOt.js.map +1 -0
- package/dist/web/assets/cobol-CWcv1MsR.js +2 -0
- package/dist/web/assets/cobol-CWcv1MsR.js.map +1 -0
- package/dist/web/assets/coffeescript-S37ZYGWr.js +2 -0
- package/dist/web/assets/coffeescript-S37ZYGWr.js.map +1 -0
- package/dist/web/assets/commonlisp-DBKNyK5s.js +2 -0
- package/dist/web/assets/commonlisp-DBKNyK5s.js.map +1 -0
- package/dist/web/assets/crystal-SjHAIU92.js +2 -0
- package/dist/web/assets/crystal-SjHAIU92.js.map +1 -0
- package/dist/web/assets/css-BnMrqG3P.js +2 -0
- package/dist/web/assets/css-BnMrqG3P.js.map +1 -0
- package/dist/web/assets/cypher-C_CwsFkJ.js +2 -0
- package/dist/web/assets/cypher-C_CwsFkJ.js.map +1 -0
- package/dist/web/assets/d-pRatUO7H.js +2 -0
- package/dist/web/assets/d-pRatUO7H.js.map +1 -0
- package/dist/web/assets/diff-DbItnlRl.js +2 -0
- package/dist/web/assets/diff-DbItnlRl.js.map +1 -0
- package/dist/web/assets/dockerfile-BKs6k2Af.js +2 -0
- package/dist/web/assets/dockerfile-BKs6k2Af.js.map +1 -0
- package/dist/web/assets/dtd-DF_7sFjM.js +2 -0
- package/dist/web/assets/dtd-DF_7sFjM.js.map +1 -0
- package/dist/web/assets/dylan-DwRh75JA.js +2 -0
- package/dist/web/assets/dylan-DwRh75JA.js.map +1 -0
- package/dist/web/assets/ebnf-CDyGwa7X.js +2 -0
- package/dist/web/assets/ebnf-CDyGwa7X.js.map +1 -0
- package/dist/web/assets/ecl-Cabwm37j.js +2 -0
- package/dist/web/assets/ecl-Cabwm37j.js.map +1 -0
- package/dist/web/assets/eiffel-CnydiIhH.js +2 -0
- package/dist/web/assets/eiffel-CnydiIhH.js.map +1 -0
- package/dist/web/assets/elm-vLlmbW-K.js +2 -0
- package/dist/web/assets/elm-vLlmbW-K.js.map +1 -0
- package/dist/web/assets/erlang-BNw1qcRV.js +2 -0
- package/dist/web/assets/erlang-BNw1qcRV.js.map +1 -0
- package/dist/web/assets/factor-kuTfRLto.js +2 -0
- package/dist/web/assets/factor-kuTfRLto.js.map +1 -0
- package/dist/web/assets/fcl-Kvtd6kyn.js +2 -0
- package/dist/web/assets/fcl-Kvtd6kyn.js.map +1 -0
- package/dist/web/assets/forth-Ffai-XNe.js +2 -0
- package/dist/web/assets/forth-Ffai-XNe.js.map +1 -0
- package/dist/web/assets/fortran-DYz_wnZ1.js +2 -0
- package/dist/web/assets/fortran-DYz_wnZ1.js.map +1 -0
- package/dist/web/assets/gas-Bneqetm1.js +2 -0
- package/dist/web/assets/gas-Bneqetm1.js.map +1 -0
- package/dist/web/assets/gherkin-heZmZLOM.js +2 -0
- package/dist/web/assets/gherkin-heZmZLOM.js.map +1 -0
- package/dist/web/assets/groovy-D9Dt4D0W.js +2 -0
- package/dist/web/assets/groovy-D9Dt4D0W.js.map +1 -0
- package/dist/web/assets/haskell-BWDZoCOh.js +2 -0
- package/dist/web/assets/haskell-BWDZoCOh.js.map +1 -0
- package/dist/web/assets/haxe-H-WmDvRZ.js +2 -0
- package/dist/web/assets/haxe-H-WmDvRZ.js.map +1 -0
- package/dist/web/assets/http-DBlCnlav.js +2 -0
- package/dist/web/assets/http-DBlCnlav.js.map +1 -0
- package/dist/web/assets/idl-BEugSyMb.js +2 -0
- package/dist/web/assets/idl-BEugSyMb.js.map +1 -0
- package/dist/web/assets/index-6L7rK6RK.js +2 -0
- package/dist/web/assets/index-6L7rK6RK.js.map +1 -0
- package/dist/web/assets/index-B1YTM6Ei.js +2 -0
- package/dist/web/assets/index-B1YTM6Ei.js.map +1 -0
- package/dist/web/assets/index-B7vcMomf.js +509 -0
- package/dist/web/assets/index-B7vcMomf.js.map +1 -0
- package/dist/web/assets/index-BcZ8RTQK.js +2 -0
- package/dist/web/assets/index-BcZ8RTQK.js.map +1 -0
- package/dist/web/assets/index-C7GrfZtu.js +2 -0
- package/dist/web/assets/index-C7GrfZtu.js.map +1 -0
- package/dist/web/assets/index-C7fIfqkz.js +2 -0
- package/dist/web/assets/index-C7fIfqkz.js.map +1 -0
- package/dist/web/assets/index-C9-Eilv-.js +2 -0
- package/dist/web/assets/index-C9-Eilv-.js.map +1 -0
- package/dist/web/assets/index-CC-t7RnM.js +4 -0
- package/dist/web/assets/index-CC-t7RnM.js.map +1 -0
- package/dist/web/assets/index-CLbc4ChH.js +2 -0
- package/dist/web/assets/index-CLbc4ChH.js.map +1 -0
- package/dist/web/assets/index-CMXahjWH.js +2 -0
- package/dist/web/assets/index-CMXahjWH.js.map +1 -0
- package/dist/web/assets/index-CfYzSHJA.css +1 -0
- package/dist/web/assets/index-ClDYe_wE.js +2 -0
- package/dist/web/assets/index-ClDYe_wE.js.map +1 -0
- package/dist/web/assets/index-CxykdbB_.js +2 -0
- package/dist/web/assets/index-CxykdbB_.js.map +1 -0
- package/dist/web/assets/index-D3WXxnT1.js +2 -0
- package/dist/web/assets/index-D3WXxnT1.js.map +1 -0
- package/dist/web/assets/index-D4qNbgAX.js +2 -0
- package/dist/web/assets/index-D4qNbgAX.js.map +1 -0
- package/dist/web/assets/index-DCiUPvZt.js +2 -0
- package/dist/web/assets/index-DCiUPvZt.js.map +1 -0
- package/dist/web/assets/index-DJpCPEwr.js +3 -0
- package/dist/web/assets/index-DJpCPEwr.js.map +1 -0
- package/dist/web/assets/index-EuUS3D16.js +8 -0
- package/dist/web/assets/index-EuUS3D16.js.map +1 -0
- package/dist/web/assets/index-WATjATUO.js +2 -0
- package/dist/web/assets/index-WATjATUO.js.map +1 -0
- package/dist/web/assets/javascript-qCveANmP.js +2 -0
- package/dist/web/assets/javascript-qCveANmP.js.map +1 -0
- package/dist/web/assets/julia-DuME0IfC.js +2 -0
- package/dist/web/assets/julia-DuME0IfC.js.map +1 -0
- package/dist/web/assets/livescript-BwQOo05w.js +2 -0
- package/dist/web/assets/livescript-BwQOo05w.js.map +1 -0
- package/dist/web/assets/lua-BgMRiT3U.js +2 -0
- package/dist/web/assets/lua-BgMRiT3U.js.map +1 -0
- package/dist/web/assets/mathematica-DTrFuWx2.js +2 -0
- package/dist/web/assets/mathematica-DTrFuWx2.js.map +1 -0
- package/dist/web/assets/mbox-CNhZ1qSd.js +2 -0
- package/dist/web/assets/mbox-CNhZ1qSd.js.map +1 -0
- package/dist/web/assets/mirc-CjQqDB4T.js +2 -0
- package/dist/web/assets/mirc-CjQqDB4T.js.map +1 -0
- package/dist/web/assets/mllike-CXdrOF99.js +2 -0
- package/dist/web/assets/mllike-CXdrOF99.js.map +1 -0
- package/dist/web/assets/modelica-Dc1JOy9r.js +2 -0
- package/dist/web/assets/modelica-Dc1JOy9r.js.map +1 -0
- package/dist/web/assets/mscgen-BA5vi2Kp.js +2 -0
- package/dist/web/assets/mscgen-BA5vi2Kp.js.map +1 -0
- package/dist/web/assets/mumps-BT43cFF4.js +2 -0
- package/dist/web/assets/mumps-BT43cFF4.js.map +1 -0
- package/dist/web/assets/nginx-DdIZxoE0.js +2 -0
- package/dist/web/assets/nginx-DdIZxoE0.js.map +1 -0
- package/dist/web/assets/nsis-LdVXkNf5.js +2 -0
- package/dist/web/assets/nsis-LdVXkNf5.js.map +1 -0
- package/dist/web/assets/ntriples-BfvgReVJ.js +2 -0
- package/dist/web/assets/ntriples-BfvgReVJ.js.map +1 -0
- package/dist/web/assets/octave-Ck1zUtKM.js +2 -0
- package/dist/web/assets/octave-Ck1zUtKM.js.map +1 -0
- package/dist/web/assets/oz-BzwKVEFT.js +2 -0
- package/dist/web/assets/oz-BzwKVEFT.js.map +1 -0
- package/dist/web/assets/pascal--L3eBynH.js +2 -0
- package/dist/web/assets/pascal--L3eBynH.js.map +1 -0
- package/dist/web/assets/perl-CdXCOZ3F.js +2 -0
- package/dist/web/assets/perl-CdXCOZ3F.js.map +1 -0
- package/dist/web/assets/pig-CevX1Tat.js +2 -0
- package/dist/web/assets/pig-CevX1Tat.js.map +1 -0
- package/dist/web/assets/powershell-CFHJl5sT.js +2 -0
- package/dist/web/assets/powershell-CFHJl5sT.js.map +1 -0
- package/dist/web/assets/properties-C78fOPTZ.js +2 -0
- package/dist/web/assets/properties-C78fOPTZ.js.map +1 -0
- package/dist/web/assets/protobuf-ChK-085T.js +2 -0
- package/dist/web/assets/protobuf-ChK-085T.js.map +1 -0
- package/dist/web/assets/pug-DukmZTjD.js +2 -0
- package/dist/web/assets/pug-DukmZTjD.js.map +1 -0
- package/dist/web/assets/puppet-DMA9R1ak.js +2 -0
- package/dist/web/assets/puppet-DMA9R1ak.js.map +1 -0
- package/dist/web/assets/python-BuPzkPfP.js +2 -0
- package/dist/web/assets/python-BuPzkPfP.js.map +1 -0
- package/dist/web/assets/q-pXgVlZs6.js +2 -0
- package/dist/web/assets/q-pXgVlZs6.js.map +1 -0
- package/dist/web/assets/r-DUYO_cvP.js +2 -0
- package/dist/web/assets/r-DUYO_cvP.js.map +1 -0
- package/dist/web/assets/rpm-CTu-6PCP.js +2 -0
- package/dist/web/assets/rpm-CTu-6PCP.js.map +1 -0
- package/dist/web/assets/ruby-B2Rjki9n.js +2 -0
- package/dist/web/assets/ruby-B2Rjki9n.js.map +1 -0
- package/dist/web/assets/sas-B4kiWyti.js +2 -0
- package/dist/web/assets/sas-B4kiWyti.js.map +1 -0
- package/dist/web/assets/scheme-C41bIUwD.js +2 -0
- package/dist/web/assets/scheme-C41bIUwD.js.map +1 -0
- package/dist/web/assets/shell-CjFT_Tl9.js +2 -0
- package/dist/web/assets/shell-CjFT_Tl9.js.map +1 -0
- package/dist/web/assets/sieve-C3Gn_uJK.js +2 -0
- package/dist/web/assets/sieve-C3Gn_uJK.js.map +1 -0
- package/dist/web/assets/simple-mode-GW_nhZxv.js +2 -0
- package/dist/web/assets/simple-mode-GW_nhZxv.js.map +1 -0
- package/dist/web/assets/smalltalk-CnHTOXQT.js +2 -0
- package/dist/web/assets/smalltalk-CnHTOXQT.js.map +1 -0
- package/dist/web/assets/solr-DehyRSwq.js +2 -0
- package/dist/web/assets/solr-DehyRSwq.js.map +1 -0
- package/dist/web/assets/sparql-DkYu6x3z.js +2 -0
- package/dist/web/assets/sparql-DkYu6x3z.js.map +1 -0
- package/dist/web/assets/spreadsheet-BCZA_wO0.js +2 -0
- package/dist/web/assets/spreadsheet-BCZA_wO0.js.map +1 -0
- package/dist/web/assets/sql-D0XecflT.js +2 -0
- package/dist/web/assets/sql-D0XecflT.js.map +1 -0
- package/dist/web/assets/stex-C3f8Ysf7.js +2 -0
- package/dist/web/assets/stex-C3f8Ysf7.js.map +1 -0
- package/dist/web/assets/stylus-B533Al4x.js +2 -0
- package/dist/web/assets/stylus-B533Al4x.js.map +1 -0
- package/dist/web/assets/swift-BzpIVaGY.js +2 -0
- package/dist/web/assets/swift-BzpIVaGY.js.map +1 -0
- package/dist/web/assets/tcl-DVfN8rqt.js +2 -0
- package/dist/web/assets/tcl-DVfN8rqt.js.map +1 -0
- package/dist/web/assets/textile-CnDTJFAw.js +2 -0
- package/dist/web/assets/textile-CnDTJFAw.js.map +1 -0
- package/dist/web/assets/tiddlywiki-DO-Gjzrf.js +2 -0
- package/dist/web/assets/tiddlywiki-DO-Gjzrf.js.map +1 -0
- package/dist/web/assets/tiki-DGYXhP31.js +2 -0
- package/dist/web/assets/tiki-DGYXhP31.js.map +1 -0
- package/dist/web/assets/toml-Bm5Em-hy.js +2 -0
- package/dist/web/assets/toml-Bm5Em-hy.js.map +1 -0
- package/dist/web/assets/troff-wAsdV37c.js +2 -0
- package/dist/web/assets/troff-wAsdV37c.js.map +1 -0
- package/dist/web/assets/ttcn-CfJYG6tj.js +2 -0
- package/dist/web/assets/ttcn-CfJYG6tj.js.map +1 -0
- package/dist/web/assets/ttcn-cfg-B9xdYoR4.js +2 -0
- package/dist/web/assets/ttcn-cfg-B9xdYoR4.js.map +1 -0
- package/dist/web/assets/turtle-B1tBg_DP.js +2 -0
- package/dist/web/assets/turtle-B1tBg_DP.js.map +1 -0
- package/dist/web/assets/vb-CmGdzxic.js +2 -0
- package/dist/web/assets/vb-CmGdzxic.js.map +1 -0
- package/dist/web/assets/vbscript-BuJXcnF6.js +2 -0
- package/dist/web/assets/vbscript-BuJXcnF6.js.map +1 -0
- package/dist/web/assets/velocity-D8B20fx6.js +2 -0
- package/dist/web/assets/velocity-D8B20fx6.js.map +1 -0
- package/dist/web/assets/verilog-C6RDOZhf.js +2 -0
- package/dist/web/assets/verilog-C6RDOZhf.js.map +1 -0
- package/dist/web/assets/vhdl-lSbBsy5d.js +2 -0
- package/dist/web/assets/vhdl-lSbBsy5d.js.map +1 -0
- package/dist/web/assets/webidl-ZXfAyPTL.js +2 -0
- package/dist/web/assets/webidl-ZXfAyPTL.js.map +1 -0
- package/dist/web/assets/xquery-CQfU5ijd.js +2 -0
- package/dist/web/assets/xquery-CQfU5ijd.js.map +1 -0
- package/dist/web/assets/yacas-BJ4BC0dw.js +2 -0
- package/dist/web/assets/yacas-BJ4BC0dw.js.map +1 -0
- package/dist/web/assets/z80-Hz9HOZM7.js +2 -0
- package/dist/web/assets/z80-Hz9HOZM7.js.map +1 -0
- package/dist/web/index.html +23 -0
- package/package.json +75 -0
- package/public/.gitkeep +0 -0
- package/public/assets/apl-B4CMkyY2.js +2 -0
- package/public/assets/apl-B4CMkyY2.js.map +1 -0
- package/public/assets/asciiarmor-Df11BRmG.js +2 -0
- package/public/assets/asciiarmor-Df11BRmG.js.map +1 -0
- package/public/assets/asn1-EdZsLKOL.js +2 -0
- package/public/assets/asn1-EdZsLKOL.js.map +1 -0
- package/public/assets/asterisk-B-8jnY81.js +2 -0
- package/public/assets/asterisk-B-8jnY81.js.map +1 -0
- package/public/assets/brainfuck-C4LP7Hcl.js +2 -0
- package/public/assets/brainfuck-C4LP7Hcl.js.map +1 -0
- package/public/assets/clike-B9uivgTg.js +2 -0
- package/public/assets/clike-B9uivgTg.js.map +1 -0
- package/public/assets/clojure-BMjYHr_A.js +2 -0
- package/public/assets/clojure-BMjYHr_A.js.map +1 -0
- package/public/assets/cmake-BQqOBYOt.js +2 -0
- package/public/assets/cmake-BQqOBYOt.js.map +1 -0
- package/public/assets/cobol-CWcv1MsR.js +2 -0
- package/public/assets/cobol-CWcv1MsR.js.map +1 -0
- package/public/assets/coffeescript-S37ZYGWr.js +2 -0
- package/public/assets/coffeescript-S37ZYGWr.js.map +1 -0
- package/public/assets/commonlisp-DBKNyK5s.js +2 -0
- package/public/assets/commonlisp-DBKNyK5s.js.map +1 -0
- package/public/assets/crystal-SjHAIU92.js +2 -0
- package/public/assets/crystal-SjHAIU92.js.map +1 -0
- package/public/assets/css-BnMrqG3P.js +2 -0
- package/public/assets/css-BnMrqG3P.js.map +1 -0
- package/public/assets/cypher-C_CwsFkJ.js +2 -0
- package/public/assets/cypher-C_CwsFkJ.js.map +1 -0
- package/public/assets/d-pRatUO7H.js +2 -0
- package/public/assets/d-pRatUO7H.js.map +1 -0
- package/public/assets/diff-DbItnlRl.js +2 -0
- package/public/assets/diff-DbItnlRl.js.map +1 -0
- package/public/assets/dockerfile-BKs6k2Af.js +2 -0
- package/public/assets/dockerfile-BKs6k2Af.js.map +1 -0
- package/public/assets/dtd-DF_7sFjM.js +2 -0
- package/public/assets/dtd-DF_7sFjM.js.map +1 -0
- package/public/assets/dylan-DwRh75JA.js +2 -0
- package/public/assets/dylan-DwRh75JA.js.map +1 -0
- package/public/assets/ebnf-CDyGwa7X.js +2 -0
- package/public/assets/ebnf-CDyGwa7X.js.map +1 -0
- package/public/assets/ecl-Cabwm37j.js +2 -0
- package/public/assets/ecl-Cabwm37j.js.map +1 -0
- package/public/assets/eiffel-CnydiIhH.js +2 -0
- package/public/assets/eiffel-CnydiIhH.js.map +1 -0
- package/public/assets/elm-vLlmbW-K.js +2 -0
- package/public/assets/elm-vLlmbW-K.js.map +1 -0
- package/public/assets/erlang-BNw1qcRV.js +2 -0
- package/public/assets/erlang-BNw1qcRV.js.map +1 -0
- package/public/assets/factor-kuTfRLto.js +2 -0
- package/public/assets/factor-kuTfRLto.js.map +1 -0
- package/public/assets/fcl-Kvtd6kyn.js +2 -0
- package/public/assets/fcl-Kvtd6kyn.js.map +1 -0
- package/public/assets/forth-Ffai-XNe.js +2 -0
- package/public/assets/forth-Ffai-XNe.js.map +1 -0
- package/public/assets/fortran-DYz_wnZ1.js +2 -0
- package/public/assets/fortran-DYz_wnZ1.js.map +1 -0
- package/public/assets/gas-Bneqetm1.js +2 -0
- package/public/assets/gas-Bneqetm1.js.map +1 -0
- package/public/assets/gherkin-heZmZLOM.js +2 -0
- package/public/assets/gherkin-heZmZLOM.js.map +1 -0
- package/public/assets/groovy-D9Dt4D0W.js +2 -0
- package/public/assets/groovy-D9Dt4D0W.js.map +1 -0
- package/public/assets/haskell-BWDZoCOh.js +2 -0
- package/public/assets/haskell-BWDZoCOh.js.map +1 -0
- package/public/assets/haxe-H-WmDvRZ.js +2 -0
- package/public/assets/haxe-H-WmDvRZ.js.map +1 -0
- package/public/assets/http-DBlCnlav.js +2 -0
- package/public/assets/http-DBlCnlav.js.map +1 -0
- package/public/assets/idl-BEugSyMb.js +2 -0
- package/public/assets/idl-BEugSyMb.js.map +1 -0
- package/public/assets/index-BHi_kGSi.js +8 -0
- package/public/assets/index-BHi_kGSi.js.map +1 -0
- package/public/assets/index-BMLAwwWL.js +2 -0
- package/public/assets/index-BMLAwwWL.js.map +1 -0
- package/public/assets/index-BNSDh5mD.js +2 -0
- package/public/assets/index-BNSDh5mD.js.map +1 -0
- package/public/assets/index-BR0D24wt.js +2 -0
- package/public/assets/index-BR0D24wt.js.map +1 -0
- package/public/assets/index-BdLsiQv5.js +2 -0
- package/public/assets/index-BdLsiQv5.js.map +1 -0
- package/public/assets/index-BjnJos4J.js +2 -0
- package/public/assets/index-BjnJos4J.js.map +1 -0
- package/public/assets/index-CM3gGvbH.js +509 -0
- package/public/assets/index-CM3gGvbH.js.map +1 -0
- package/public/assets/index-CV8De3J9.js +2 -0
- package/public/assets/index-CV8De3J9.js.map +1 -0
- package/public/assets/index-ChuKVzLw.js +2 -0
- package/public/assets/index-ChuKVzLw.js.map +1 -0
- package/public/assets/index-CpfmaE2d.js +2 -0
- package/public/assets/index-CpfmaE2d.js.map +1 -0
- package/public/assets/index-D90_xI0s.js +2 -0
- package/public/assets/index-D90_xI0s.js.map +1 -0
- package/public/assets/index-DR3bJemi.js +4 -0
- package/public/assets/index-DR3bJemi.js.map +1 -0
- package/public/assets/index-DlsEbLHk.css +1 -0
- package/public/assets/index-MR5aWKcm.js +2 -0
- package/public/assets/index-MR5aWKcm.js.map +1 -0
- package/public/assets/index-MrhuDMHQ.js +2 -0
- package/public/assets/index-MrhuDMHQ.js.map +1 -0
- package/public/assets/index-NbLWR4tH.js +2 -0
- package/public/assets/index-NbLWR4tH.js.map +1 -0
- package/public/assets/index-VnBXaSng.js +3 -0
- package/public/assets/index-VnBXaSng.js.map +1 -0
- package/public/assets/index-XEgqkWdk.js +2 -0
- package/public/assets/index-XEgqkWdk.js.map +1 -0
- package/public/assets/index-zHvewZlp.js +2 -0
- package/public/assets/index-zHvewZlp.js.map +1 -0
- package/public/assets/javascript-qCveANmP.js +2 -0
- package/public/assets/javascript-qCveANmP.js.map +1 -0
- package/public/assets/julia-DuME0IfC.js +2 -0
- package/public/assets/julia-DuME0IfC.js.map +1 -0
- package/public/assets/livescript-BwQOo05w.js +2 -0
- package/public/assets/livescript-BwQOo05w.js.map +1 -0
- package/public/assets/lua-BgMRiT3U.js +2 -0
- package/public/assets/lua-BgMRiT3U.js.map +1 -0
- package/public/assets/mathematica-DTrFuWx2.js +2 -0
- package/public/assets/mathematica-DTrFuWx2.js.map +1 -0
- package/public/assets/mbox-CNhZ1qSd.js +2 -0
- package/public/assets/mbox-CNhZ1qSd.js.map +1 -0
- package/public/assets/mirc-CjQqDB4T.js +2 -0
- package/public/assets/mirc-CjQqDB4T.js.map +1 -0
- package/public/assets/mllike-CXdrOF99.js +2 -0
- package/public/assets/mllike-CXdrOF99.js.map +1 -0
- package/public/assets/modelica-Dc1JOy9r.js +2 -0
- package/public/assets/modelica-Dc1JOy9r.js.map +1 -0
- package/public/assets/mscgen-BA5vi2Kp.js +2 -0
- package/public/assets/mscgen-BA5vi2Kp.js.map +1 -0
- package/public/assets/mumps-BT43cFF4.js +2 -0
- package/public/assets/mumps-BT43cFF4.js.map +1 -0
- package/public/assets/nginx-DdIZxoE0.js +2 -0
- package/public/assets/nginx-DdIZxoE0.js.map +1 -0
- package/public/assets/nsis-LdVXkNf5.js +2 -0
- package/public/assets/nsis-LdVXkNf5.js.map +1 -0
- package/public/assets/ntriples-BfvgReVJ.js +2 -0
- package/public/assets/ntriples-BfvgReVJ.js.map +1 -0
- package/public/assets/octave-Ck1zUtKM.js +2 -0
- package/public/assets/octave-Ck1zUtKM.js.map +1 -0
- package/public/assets/oz-BzwKVEFT.js +2 -0
- package/public/assets/oz-BzwKVEFT.js.map +1 -0
- package/public/assets/pascal--L3eBynH.js +2 -0
- package/public/assets/pascal--L3eBynH.js.map +1 -0
- package/public/assets/perl-CdXCOZ3F.js +2 -0
- package/public/assets/perl-CdXCOZ3F.js.map +1 -0
- package/public/assets/pig-CevX1Tat.js +2 -0
- package/public/assets/pig-CevX1Tat.js.map +1 -0
- package/public/assets/powershell-CFHJl5sT.js +2 -0
- package/public/assets/powershell-CFHJl5sT.js.map +1 -0
- package/public/assets/properties-C78fOPTZ.js +2 -0
- package/public/assets/properties-C78fOPTZ.js.map +1 -0
- package/public/assets/protobuf-ChK-085T.js +2 -0
- package/public/assets/protobuf-ChK-085T.js.map +1 -0
- package/public/assets/pug-DukmZTjD.js +2 -0
- package/public/assets/pug-DukmZTjD.js.map +1 -0
- package/public/assets/puppet-DMA9R1ak.js +2 -0
- package/public/assets/puppet-DMA9R1ak.js.map +1 -0
- package/public/assets/python-BuPzkPfP.js +2 -0
- package/public/assets/python-BuPzkPfP.js.map +1 -0
- package/public/assets/q-pXgVlZs6.js +2 -0
- package/public/assets/q-pXgVlZs6.js.map +1 -0
- package/public/assets/r-DUYO_cvP.js +2 -0
- package/public/assets/r-DUYO_cvP.js.map +1 -0
- package/public/assets/rpm-CTu-6PCP.js +2 -0
- package/public/assets/rpm-CTu-6PCP.js.map +1 -0
- package/public/assets/ruby-B2Rjki9n.js +2 -0
- package/public/assets/ruby-B2Rjki9n.js.map +1 -0
- package/public/assets/sas-B4kiWyti.js +2 -0
- package/public/assets/sas-B4kiWyti.js.map +1 -0
- package/public/assets/scheme-C41bIUwD.js +2 -0
- package/public/assets/scheme-C41bIUwD.js.map +1 -0
- package/public/assets/shell-CjFT_Tl9.js +2 -0
- package/public/assets/shell-CjFT_Tl9.js.map +1 -0
- package/public/assets/sieve-C3Gn_uJK.js +2 -0
- package/public/assets/sieve-C3Gn_uJK.js.map +1 -0
- package/public/assets/simple-mode-GW_nhZxv.js +2 -0
- package/public/assets/simple-mode-GW_nhZxv.js.map +1 -0
- package/public/assets/smalltalk-CnHTOXQT.js +2 -0
- package/public/assets/smalltalk-CnHTOXQT.js.map +1 -0
- package/public/assets/solr-DehyRSwq.js +2 -0
- package/public/assets/solr-DehyRSwq.js.map +1 -0
- package/public/assets/sparql-DkYu6x3z.js +2 -0
- package/public/assets/sparql-DkYu6x3z.js.map +1 -0
- package/public/assets/spreadsheet-BCZA_wO0.js +2 -0
- package/public/assets/spreadsheet-BCZA_wO0.js.map +1 -0
- package/public/assets/sql-D0XecflT.js +2 -0
- package/public/assets/sql-D0XecflT.js.map +1 -0
- package/public/assets/stex-C3f8Ysf7.js +2 -0
- package/public/assets/stex-C3f8Ysf7.js.map +1 -0
- package/public/assets/stylus-B533Al4x.js +2 -0
- package/public/assets/stylus-B533Al4x.js.map +1 -0
- package/public/assets/swift-BzpIVaGY.js +2 -0
- package/public/assets/swift-BzpIVaGY.js.map +1 -0
- package/public/assets/tcl-DVfN8rqt.js +2 -0
- package/public/assets/tcl-DVfN8rqt.js.map +1 -0
- package/public/assets/textile-CnDTJFAw.js +2 -0
- package/public/assets/textile-CnDTJFAw.js.map +1 -0
- package/public/assets/tiddlywiki-DO-Gjzrf.js +2 -0
- package/public/assets/tiddlywiki-DO-Gjzrf.js.map +1 -0
- package/public/assets/tiki-DGYXhP31.js +2 -0
- package/public/assets/tiki-DGYXhP31.js.map +1 -0
- package/public/assets/toml-Bm5Em-hy.js +2 -0
- package/public/assets/toml-Bm5Em-hy.js.map +1 -0
- package/public/assets/troff-wAsdV37c.js +2 -0
- package/public/assets/troff-wAsdV37c.js.map +1 -0
- package/public/assets/ttcn-CfJYG6tj.js +2 -0
- package/public/assets/ttcn-CfJYG6tj.js.map +1 -0
- package/public/assets/ttcn-cfg-B9xdYoR4.js +2 -0
- package/public/assets/ttcn-cfg-B9xdYoR4.js.map +1 -0
- package/public/assets/turtle-B1tBg_DP.js +2 -0
- package/public/assets/turtle-B1tBg_DP.js.map +1 -0
- package/public/assets/vb-CmGdzxic.js +2 -0
- package/public/assets/vb-CmGdzxic.js.map +1 -0
- package/public/assets/vbscript-BuJXcnF6.js +2 -0
- package/public/assets/vbscript-BuJXcnF6.js.map +1 -0
- package/public/assets/velocity-D8B20fx6.js +2 -0
- package/public/assets/velocity-D8B20fx6.js.map +1 -0
- package/public/assets/verilog-C6RDOZhf.js +2 -0
- package/public/assets/verilog-C6RDOZhf.js.map +1 -0
- package/public/assets/vhdl-lSbBsy5d.js +2 -0
- package/public/assets/vhdl-lSbBsy5d.js.map +1 -0
- package/public/assets/webidl-ZXfAyPTL.js +2 -0
- package/public/assets/webidl-ZXfAyPTL.js.map +1 -0
- package/public/assets/xquery-CQfU5ijd.js +2 -0
- package/public/assets/xquery-CQfU5ijd.js.map +1 -0
- package/public/assets/yacas-BJ4BC0dw.js +2 -0
- package/public/assets/yacas-BJ4BC0dw.js.map +1 -0
- package/public/assets/z80-Hz9HOZM7.js +2 -0
- package/public/assets/z80-Hz9HOZM7.js.map +1 -0
- package/public/index.html +15 -0
|
@@ -0,0 +1,974 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code API Routes
|
|
3
|
+
*
|
|
4
|
+
* Handles code index operations: search, symbols, files, status, sync.
|
|
5
|
+
* All operations work on the currently active project.
|
|
6
|
+
*/
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import fs from 'node:fs/promises';
|
|
9
|
+
import { glob } from 'glob';
|
|
10
|
+
import { getCurrentProject, requireProjectContext, updateSecretsIfNeeded } from './project.js';
|
|
11
|
+
import { emitEvent } from './events.js';
|
|
12
|
+
import { createSyncHandler } from './sync-handler.js';
|
|
13
|
+
import { isError, getGitInfo } from 'grepmind-core';
|
|
14
|
+
import { validateSecrets } from 'grepmind-config';
|
|
15
|
+
/**
|
|
16
|
+
* Ensure a project is open and code indexing is enabled
|
|
17
|
+
*/
|
|
18
|
+
function requireCodeEnabled(reply) {
|
|
19
|
+
const project = getCurrentProject();
|
|
20
|
+
if (!project) {
|
|
21
|
+
reply.status(400).send({
|
|
22
|
+
error: 'No project open',
|
|
23
|
+
message: 'Open a project first using POST /api/project/open',
|
|
24
|
+
});
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
if (!project.config.code.enabled) {
|
|
28
|
+
reply.status(400).send({
|
|
29
|
+
error: 'Code indexing disabled',
|
|
30
|
+
message: 'Code indexing is not enabled for this project',
|
|
31
|
+
});
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Get code root path for current project
|
|
38
|
+
*/
|
|
39
|
+
function getCodePaths() {
|
|
40
|
+
const project = getCurrentProject();
|
|
41
|
+
if (!project || !project.config.code.enabled)
|
|
42
|
+
return null;
|
|
43
|
+
// Code root is always the project directory
|
|
44
|
+
return [project.path];
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Get primary code path (first from array, or project root).
|
|
48
|
+
* Used for backward compatibility with single-path operations.
|
|
49
|
+
*/
|
|
50
|
+
function getCodePath() {
|
|
51
|
+
const paths = getCodePaths();
|
|
52
|
+
return paths ? paths[0] : null;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Detect language from file extension
|
|
56
|
+
*/
|
|
57
|
+
function detectLanguage(filePath) {
|
|
58
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
59
|
+
const languageMap = {
|
|
60
|
+
'.ts': 'typescript',
|
|
61
|
+
'.tsx': 'typescript',
|
|
62
|
+
'.js': 'javascript',
|
|
63
|
+
'.jsx': 'javascript',
|
|
64
|
+
'.py': 'python',
|
|
65
|
+
'.go': 'go',
|
|
66
|
+
'.rs': 'rust',
|
|
67
|
+
'.java': 'java',
|
|
68
|
+
'.c': 'c',
|
|
69
|
+
'.cpp': 'cpp',
|
|
70
|
+
'.h': 'c',
|
|
71
|
+
'.hpp': 'cpp',
|
|
72
|
+
'.cs': 'csharp',
|
|
73
|
+
'.rb': 'ruby',
|
|
74
|
+
'.php': 'php',
|
|
75
|
+
'.swift': 'swift',
|
|
76
|
+
'.kt': 'kotlin',
|
|
77
|
+
'.scala': 'scala',
|
|
78
|
+
'.vue': 'vue',
|
|
79
|
+
'.svelte': 'svelte',
|
|
80
|
+
'.html': 'html',
|
|
81
|
+
'.css': 'css',
|
|
82
|
+
'.scss': 'scss',
|
|
83
|
+
'.less': 'less',
|
|
84
|
+
'.json': 'json',
|
|
85
|
+
'.yaml': 'yaml',
|
|
86
|
+
'.yml': 'yaml',
|
|
87
|
+
'.toml': 'toml',
|
|
88
|
+
'.md': 'markdown',
|
|
89
|
+
'.sh': 'bash',
|
|
90
|
+
'.bash': 'bash',
|
|
91
|
+
'.zsh': 'zsh',
|
|
92
|
+
'.sql': 'sql',
|
|
93
|
+
'.graphql': 'graphql',
|
|
94
|
+
'.gql': 'graphql',
|
|
95
|
+
};
|
|
96
|
+
return languageMap[ext] || 'unknown';
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Register code routes
|
|
100
|
+
*/
|
|
101
|
+
export async function codeRoutes(app) {
|
|
102
|
+
/**
|
|
103
|
+
* GET /api/code/status
|
|
104
|
+
* Get code index status for current project
|
|
105
|
+
*/
|
|
106
|
+
app.get('/status', async (request, reply) => {
|
|
107
|
+
const project = getCurrentProject();
|
|
108
|
+
if (!project) {
|
|
109
|
+
return reply.status(400).send({
|
|
110
|
+
error: 'No project open',
|
|
111
|
+
message: 'Open a project first using POST /api/project/open',
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
if (!project.config.code.enabled) {
|
|
115
|
+
return reply.send({
|
|
116
|
+
enabled: false,
|
|
117
|
+
totalFiles: 0,
|
|
118
|
+
indexedFiles: 0,
|
|
119
|
+
totalSymbols: 0,
|
|
120
|
+
languages: {},
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
try {
|
|
124
|
+
const context = requireProjectContext();
|
|
125
|
+
const codePath = getCodePath();
|
|
126
|
+
if (!context.codeIndexer) {
|
|
127
|
+
return reply.send({
|
|
128
|
+
enabled: true,
|
|
129
|
+
totalFiles: 0,
|
|
130
|
+
indexedFiles: 0,
|
|
131
|
+
totalSymbols: 0,
|
|
132
|
+
languages: {},
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
// Get actual stats from CodeIndexer
|
|
136
|
+
const stats = await context.codeIndexer.getStats();
|
|
137
|
+
// Get git info for branch awareness
|
|
138
|
+
const gitInfo = codePath ? getGitInfo(codePath) : null;
|
|
139
|
+
// Get overlay info if branch indexer is available
|
|
140
|
+
let overlayInfo = null;
|
|
141
|
+
if (context.codeBranchIndexer) {
|
|
142
|
+
overlayInfo = await context.codeBranchIndexer.getInfo();
|
|
143
|
+
}
|
|
144
|
+
const status = {
|
|
145
|
+
enabled: true,
|
|
146
|
+
totalFiles: stats.totalFiles,
|
|
147
|
+
indexedFiles: stats.totalFiles,
|
|
148
|
+
totalSymbols: stats.totalChunks,
|
|
149
|
+
languages: stats.languages,
|
|
150
|
+
lastSync: undefined,
|
|
151
|
+
lastSyncCommit: undefined,
|
|
152
|
+
branch: gitInfo?.branch || null,
|
|
153
|
+
isMainBranch: gitInfo?.isMainBranch ?? null,
|
|
154
|
+
overlay: overlayInfo,
|
|
155
|
+
};
|
|
156
|
+
return reply.send(status);
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
app.log.error(error);
|
|
160
|
+
return reply.status(500).send({
|
|
161
|
+
error: 'Failed to get status',
|
|
162
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
/**
|
|
167
|
+
* GET /api/code/git-info
|
|
168
|
+
* Get git branch information for current project's code path
|
|
169
|
+
*/
|
|
170
|
+
app.get('/git-info', async (request, reply) => {
|
|
171
|
+
const codePath = getCodePath();
|
|
172
|
+
if (!codePath) {
|
|
173
|
+
return reply.send({
|
|
174
|
+
isGitRepo: false,
|
|
175
|
+
branch: null,
|
|
176
|
+
isMainBranch: null,
|
|
177
|
+
mainBranch: null,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
const gitInfo = getGitInfo(codePath);
|
|
181
|
+
return reply.send({
|
|
182
|
+
isGitRepo: !!gitInfo,
|
|
183
|
+
branch: gitInfo?.branch || null,
|
|
184
|
+
isMainBranch: gitInfo?.isMainBranch ?? null,
|
|
185
|
+
mainBranch: gitInfo?.mainBranch || null,
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
/**
|
|
189
|
+
* GET /api/code/files
|
|
190
|
+
* List all code files with index status
|
|
191
|
+
*/
|
|
192
|
+
app.get('/files', {
|
|
193
|
+
schema: {
|
|
194
|
+
querystring: {
|
|
195
|
+
type: 'object',
|
|
196
|
+
properties: {
|
|
197
|
+
folder: { type: 'string' },
|
|
198
|
+
language: { type: 'string' },
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
}, async (request, reply) => {
|
|
203
|
+
if (!requireCodeEnabled(reply))
|
|
204
|
+
return;
|
|
205
|
+
const { folder, language } = request.query;
|
|
206
|
+
const project = getCurrentProject();
|
|
207
|
+
const codePath = getCodePath();
|
|
208
|
+
const include = project.config.code.include || ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'];
|
|
209
|
+
const exclude = project.config.code.exclude || ['**/node_modules/**', '**/dist/**'];
|
|
210
|
+
try {
|
|
211
|
+
const context = requireProjectContext();
|
|
212
|
+
// Get indexed files for status lookup
|
|
213
|
+
let indexedPaths = new Set();
|
|
214
|
+
if (context.codeIndexer) {
|
|
215
|
+
indexedPaths = await context.codeIndexer.getIndexedFilePaths();
|
|
216
|
+
}
|
|
217
|
+
const codeFiles = [];
|
|
218
|
+
for (const pattern of include) {
|
|
219
|
+
const searchPattern = folder ? `${folder}/${pattern}` : pattern;
|
|
220
|
+
const files = await glob(searchPattern, {
|
|
221
|
+
cwd: codePath,
|
|
222
|
+
nodir: true,
|
|
223
|
+
ignore: exclude,
|
|
224
|
+
});
|
|
225
|
+
for (const file of files) {
|
|
226
|
+
const fullPath = path.join(codePath, file);
|
|
227
|
+
const fileLang = detectLanguage(file);
|
|
228
|
+
// Filter by language if specified
|
|
229
|
+
if (language && fileLang !== language)
|
|
230
|
+
continue;
|
|
231
|
+
const stat = await fs.stat(fullPath);
|
|
232
|
+
codeFiles.push({
|
|
233
|
+
path: fullPath,
|
|
234
|
+
name: path.basename(file),
|
|
235
|
+
relativePath: file,
|
|
236
|
+
language: fileLang,
|
|
237
|
+
indexStatus: indexedPaths.has(file) ? 'indexed' : 'unindexed',
|
|
238
|
+
size: stat.size,
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return reply.send(codeFiles);
|
|
243
|
+
}
|
|
244
|
+
catch (error) {
|
|
245
|
+
app.log.error(error);
|
|
246
|
+
return reply.status(500).send({
|
|
247
|
+
error: 'Failed to list files',
|
|
248
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
/**
|
|
253
|
+
* GET /api/code/file/:path
|
|
254
|
+
* Get details for a specific code file with symbols
|
|
255
|
+
*/
|
|
256
|
+
app.get('/file/*', async (request, reply) => {
|
|
257
|
+
if (!requireCodeEnabled(reply))
|
|
258
|
+
return;
|
|
259
|
+
const filePath = request.params['*'];
|
|
260
|
+
const codePath = getCodePath();
|
|
261
|
+
const fullPath = path.join(codePath, filePath);
|
|
262
|
+
try {
|
|
263
|
+
// Ensure path is within code root
|
|
264
|
+
if (!fullPath.startsWith(codePath)) {
|
|
265
|
+
return reply.status(400).send({
|
|
266
|
+
error: 'Invalid path',
|
|
267
|
+
message: 'Path must be within code root',
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
const stat = await fs.stat(fullPath);
|
|
271
|
+
const content = await fs.readFile(fullPath, 'utf-8');
|
|
272
|
+
// TODO: Get symbols from index
|
|
273
|
+
return reply.send({
|
|
274
|
+
path: fullPath,
|
|
275
|
+
name: path.basename(filePath),
|
|
276
|
+
relativePath: filePath,
|
|
277
|
+
language: detectLanguage(filePath),
|
|
278
|
+
indexStatus: 'unindexed',
|
|
279
|
+
size: stat.size,
|
|
280
|
+
content,
|
|
281
|
+
symbols: [], // TODO: Get from index
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
catch (error) {
|
|
285
|
+
if (error.code === 'ENOENT') {
|
|
286
|
+
return reply.status(404).send({
|
|
287
|
+
error: 'File not found',
|
|
288
|
+
message: `Code file not found: ${filePath}`,
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
app.log.error(error);
|
|
292
|
+
return reply.status(500).send({
|
|
293
|
+
error: 'Failed to get file',
|
|
294
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
/**
|
|
299
|
+
* GET /api/code/search
|
|
300
|
+
* Semantic search in code
|
|
301
|
+
*/
|
|
302
|
+
app.get('/search', {
|
|
303
|
+
schema: {
|
|
304
|
+
querystring: {
|
|
305
|
+
type: 'object',
|
|
306
|
+
required: ['q'],
|
|
307
|
+
properties: {
|
|
308
|
+
q: { type: 'string' },
|
|
309
|
+
limit: { type: 'number', default: 10 },
|
|
310
|
+
threshold: { type: 'number', default: 0.5 },
|
|
311
|
+
language: { type: 'string' },
|
|
312
|
+
symbolType: { type: 'string' },
|
|
313
|
+
path: { type: 'string' },
|
|
314
|
+
mode: { type: 'string', enum: ['hybrid', 'semantic', 'text'], default: 'hybrid' },
|
|
315
|
+
},
|
|
316
|
+
},
|
|
317
|
+
},
|
|
318
|
+
}, async (request, reply) => {
|
|
319
|
+
if (!requireCodeEnabled(reply))
|
|
320
|
+
return;
|
|
321
|
+
const { q, limit = 10, threshold = 0.5, language, symbolType, path: pathFilter, mode = 'hybrid' } = request.query;
|
|
322
|
+
try {
|
|
323
|
+
// Update secrets if changed (e.g., Voyage API key added after project open)
|
|
324
|
+
await updateSecretsIfNeeded(request.secrets || {});
|
|
325
|
+
const context = requireProjectContext();
|
|
326
|
+
if (!context.codeIndexer) {
|
|
327
|
+
return reply.status(400).send({
|
|
328
|
+
error: 'Code indexer not available',
|
|
329
|
+
message: 'Code indexing is not initialized for this project',
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
let searchResults;
|
|
333
|
+
if (mode === 'text') {
|
|
334
|
+
searchResults = await context.codeIndexer.searchFts({
|
|
335
|
+
query: q,
|
|
336
|
+
limit,
|
|
337
|
+
language,
|
|
338
|
+
symbolTypes: symbolType ? [symbolType] : undefined,
|
|
339
|
+
path: pathFilter,
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
else if (mode === 'semantic') {
|
|
343
|
+
searchResults = await context.codeIndexer.search(q, {
|
|
344
|
+
limit,
|
|
345
|
+
threshold,
|
|
346
|
+
language,
|
|
347
|
+
symbolTypes: symbolType ? [symbolType] : undefined,
|
|
348
|
+
path: pathFilter,
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
searchResults = await context.codeIndexer.searchHybrid({
|
|
353
|
+
query: q,
|
|
354
|
+
limit,
|
|
355
|
+
threshold,
|
|
356
|
+
language,
|
|
357
|
+
symbolTypes: symbolType ? [symbolType] : undefined,
|
|
358
|
+
path: pathFilter,
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
if (isError(searchResults)) {
|
|
362
|
+
return reply.status(500).send({
|
|
363
|
+
error: 'Search failed',
|
|
364
|
+
message: searchResults.message,
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
const results = searchResults.map(r => ({
|
|
368
|
+
symbol: {
|
|
369
|
+
id: r.id,
|
|
370
|
+
name: r.symbolName,
|
|
371
|
+
type: r.symbolType,
|
|
372
|
+
path: path.join(getCodePath(), r.path),
|
|
373
|
+
relativePath: r.path,
|
|
374
|
+
signature: r.signature,
|
|
375
|
+
docstring: r.docstring,
|
|
376
|
+
startLine: r.startLine,
|
|
377
|
+
endLine: r.endLine,
|
|
378
|
+
parentSymbol: r.parentSymbol,
|
|
379
|
+
},
|
|
380
|
+
score: r.score,
|
|
381
|
+
content: r.content,
|
|
382
|
+
}));
|
|
383
|
+
return reply.send({
|
|
384
|
+
query: q,
|
|
385
|
+
results,
|
|
386
|
+
total: results.length,
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
catch (error) {
|
|
390
|
+
app.log.error(error);
|
|
391
|
+
return reply.status(500).send({
|
|
392
|
+
error: 'Search failed',
|
|
393
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
});
|
|
397
|
+
/**
|
|
398
|
+
* GET /api/code/symbols
|
|
399
|
+
* Search symbols by name (exact or wildcard)
|
|
400
|
+
*/
|
|
401
|
+
app.get('/symbols', {
|
|
402
|
+
schema: {
|
|
403
|
+
querystring: {
|
|
404
|
+
type: 'object',
|
|
405
|
+
required: ['name'],
|
|
406
|
+
properties: {
|
|
407
|
+
name: { type: 'string' },
|
|
408
|
+
type: { type: 'string' },
|
|
409
|
+
path: { type: 'string' },
|
|
410
|
+
limit: { type: 'number', default: 20 },
|
|
411
|
+
},
|
|
412
|
+
},
|
|
413
|
+
},
|
|
414
|
+
}, async (request, reply) => {
|
|
415
|
+
if (!requireCodeEnabled(reply))
|
|
416
|
+
return;
|
|
417
|
+
const { name, type, path: pathFilter, limit = 20 } = request.query;
|
|
418
|
+
try {
|
|
419
|
+
const context = requireProjectContext();
|
|
420
|
+
if (!context.codeIndexer) {
|
|
421
|
+
return reply.status(400).send({
|
|
422
|
+
error: 'Code indexer not available',
|
|
423
|
+
message: 'Code indexing is not initialized for this project',
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
// Convert absolute path to relative if needed
|
|
427
|
+
const codePath = getCodePath();
|
|
428
|
+
let relativePath = pathFilter;
|
|
429
|
+
if (pathFilter && path.isAbsolute(pathFilter) && pathFilter.startsWith(codePath)) {
|
|
430
|
+
relativePath = path.relative(codePath, pathFilter);
|
|
431
|
+
}
|
|
432
|
+
const searchResults = await context.codeIndexer.findSymbols(name, {
|
|
433
|
+
type,
|
|
434
|
+
path: relativePath,
|
|
435
|
+
limit,
|
|
436
|
+
});
|
|
437
|
+
if (isError(searchResults)) {
|
|
438
|
+
return reply.status(500).send({
|
|
439
|
+
error: 'Symbol search failed',
|
|
440
|
+
message: searchResults.message,
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
const symbols = searchResults.map(r => ({
|
|
444
|
+
id: r.id,
|
|
445
|
+
name: r.symbolName,
|
|
446
|
+
type: r.symbolType,
|
|
447
|
+
path: path.join(codePath, r.path),
|
|
448
|
+
relativePath: r.path,
|
|
449
|
+
signature: r.signature,
|
|
450
|
+
docstring: r.docstring,
|
|
451
|
+
startLine: r.startLine,
|
|
452
|
+
endLine: r.endLine,
|
|
453
|
+
parentSymbol: r.parentSymbol,
|
|
454
|
+
score: r.score,
|
|
455
|
+
}));
|
|
456
|
+
return reply.send({
|
|
457
|
+
name,
|
|
458
|
+
symbols,
|
|
459
|
+
total: symbols.length,
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
catch (error) {
|
|
463
|
+
app.log.error(error);
|
|
464
|
+
return reply.status(500).send({
|
|
465
|
+
error: 'Symbol search failed',
|
|
466
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
});
|
|
470
|
+
/**
|
|
471
|
+
* GET /api/code/graph/refs
|
|
472
|
+
* Find references for a symbol.
|
|
473
|
+
*/
|
|
474
|
+
app.get('/graph/refs', {
|
|
475
|
+
schema: {
|
|
476
|
+
querystring: {
|
|
477
|
+
type: 'object',
|
|
478
|
+
properties: {
|
|
479
|
+
symbolId: { type: 'string' },
|
|
480
|
+
symbolName: { type: 'string' },
|
|
481
|
+
file: { type: 'string' },
|
|
482
|
+
includeImports: { type: 'boolean', default: true },
|
|
483
|
+
limit: { type: 'number', default: 50 },
|
|
484
|
+
},
|
|
485
|
+
},
|
|
486
|
+
},
|
|
487
|
+
}, async (request, reply) => {
|
|
488
|
+
if (!requireCodeEnabled(reply))
|
|
489
|
+
return;
|
|
490
|
+
const { symbolId, symbolName, file, includeImports = true, limit = 50 } = request.query;
|
|
491
|
+
if (!symbolId && !symbolName) {
|
|
492
|
+
return reply.status(400).send({
|
|
493
|
+
error: 'Invalid query',
|
|
494
|
+
message: 'Provide either symbolId or symbolName',
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
try {
|
|
498
|
+
const context = requireProjectContext();
|
|
499
|
+
if (!context.codeIndexer) {
|
|
500
|
+
return reply.status(400).send({
|
|
501
|
+
error: 'Code indexer not available',
|
|
502
|
+
message: 'Code indexing is not initialized for this project',
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
// Convert absolute path to relative if needed
|
|
506
|
+
let relativeFile = file;
|
|
507
|
+
if (file) {
|
|
508
|
+
const codePath = getCodePath();
|
|
509
|
+
if (path.isAbsolute(file) && file.startsWith(codePath)) {
|
|
510
|
+
relativeFile = path.relative(codePath, file);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
const result = await context.codeIndexer.graphRefs({
|
|
514
|
+
symbolId,
|
|
515
|
+
symbolName,
|
|
516
|
+
file: relativeFile,
|
|
517
|
+
includeImports,
|
|
518
|
+
limit,
|
|
519
|
+
});
|
|
520
|
+
if (isError(result)) {
|
|
521
|
+
const statusCode = result.code === 'NOT_FOUND' ? 404 : 500;
|
|
522
|
+
return reply.status(statusCode).send({
|
|
523
|
+
error: result.code,
|
|
524
|
+
message: result.message,
|
|
525
|
+
});
|
|
526
|
+
}
|
|
527
|
+
return reply.send(result);
|
|
528
|
+
}
|
|
529
|
+
catch (error) {
|
|
530
|
+
app.log.error(error);
|
|
531
|
+
return reply.status(500).send({
|
|
532
|
+
error: 'Graph refs failed',
|
|
533
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
});
|
|
537
|
+
/**
|
|
538
|
+
* GET /api/code/graph/calls
|
|
539
|
+
* Build callers/callees graph for a symbol.
|
|
540
|
+
*/
|
|
541
|
+
app.get('/graph/calls', {
|
|
542
|
+
schema: {
|
|
543
|
+
querystring: {
|
|
544
|
+
type: 'object',
|
|
545
|
+
properties: {
|
|
546
|
+
symbolId: { type: 'string' },
|
|
547
|
+
symbolName: { type: 'string' },
|
|
548
|
+
direction: { type: 'string', enum: ['callers', 'callees', 'both'], default: 'both' },
|
|
549
|
+
depth: { type: 'number', default: 2 },
|
|
550
|
+
limit: { type: 'number', default: 50 },
|
|
551
|
+
},
|
|
552
|
+
},
|
|
553
|
+
},
|
|
554
|
+
}, async (request, reply) => {
|
|
555
|
+
if (!requireCodeEnabled(reply))
|
|
556
|
+
return;
|
|
557
|
+
const { symbolId, symbolName, direction = 'both', depth = 2, limit = 50 } = request.query;
|
|
558
|
+
if (!symbolId && !symbolName) {
|
|
559
|
+
return reply.status(400).send({
|
|
560
|
+
error: 'Invalid query',
|
|
561
|
+
message: 'Provide either symbolId or symbolName',
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
try {
|
|
565
|
+
const context = requireProjectContext();
|
|
566
|
+
if (!context.codeIndexer) {
|
|
567
|
+
return reply.status(400).send({
|
|
568
|
+
error: 'Code indexer not available',
|
|
569
|
+
message: 'Code indexing is not initialized for this project',
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
const result = await context.codeIndexer.graphCalls({
|
|
573
|
+
symbolId,
|
|
574
|
+
symbolName,
|
|
575
|
+
direction,
|
|
576
|
+
depth,
|
|
577
|
+
limit,
|
|
578
|
+
});
|
|
579
|
+
if (isError(result)) {
|
|
580
|
+
const statusCode = result.code === 'NOT_FOUND' ? 404 : 500;
|
|
581
|
+
return reply.status(statusCode).send({
|
|
582
|
+
error: result.code,
|
|
583
|
+
message: result.message,
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
return reply.send(result);
|
|
587
|
+
}
|
|
588
|
+
catch (error) {
|
|
589
|
+
app.log.error(error);
|
|
590
|
+
return reply.status(500).send({
|
|
591
|
+
error: 'Graph calls failed',
|
|
592
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
});
|
|
596
|
+
/**
|
|
597
|
+
* GET /api/code/graph/deps
|
|
598
|
+
* Build file dependency graph (imports/importedBy).
|
|
599
|
+
*/
|
|
600
|
+
app.get('/graph/deps', {
|
|
601
|
+
schema: {
|
|
602
|
+
querystring: {
|
|
603
|
+
type: 'object',
|
|
604
|
+
required: ['file'],
|
|
605
|
+
properties: {
|
|
606
|
+
file: { type: 'string' },
|
|
607
|
+
direction: { type: 'string', enum: ['imports', 'importedBy', 'both'], default: 'both' },
|
|
608
|
+
depth: { type: 'number', default: 1 },
|
|
609
|
+
includeExternal: { type: 'boolean', default: false },
|
|
610
|
+
},
|
|
611
|
+
},
|
|
612
|
+
},
|
|
613
|
+
}, async (request, reply) => {
|
|
614
|
+
if (!requireCodeEnabled(reply))
|
|
615
|
+
return;
|
|
616
|
+
const { file, direction = 'both', depth = 1, includeExternal = false } = request.query;
|
|
617
|
+
try {
|
|
618
|
+
const context = requireProjectContext();
|
|
619
|
+
if (!context.codeIndexer) {
|
|
620
|
+
return reply.status(400).send({
|
|
621
|
+
error: 'Code indexer not available',
|
|
622
|
+
message: 'Code indexing is not initialized for this project',
|
|
623
|
+
});
|
|
624
|
+
}
|
|
625
|
+
// Convert absolute path to relative if needed
|
|
626
|
+
const codePath = getCodePath();
|
|
627
|
+
let relativeFile = file;
|
|
628
|
+
if (path.isAbsolute(file) && file.startsWith(codePath)) {
|
|
629
|
+
relativeFile = path.relative(codePath, file);
|
|
630
|
+
}
|
|
631
|
+
const result = await context.codeIndexer.graphDeps({
|
|
632
|
+
file: relativeFile,
|
|
633
|
+
direction,
|
|
634
|
+
depth,
|
|
635
|
+
includeExternal,
|
|
636
|
+
});
|
|
637
|
+
if (isError(result)) {
|
|
638
|
+
const statusCode = result.code === 'NOT_FOUND' ? 404 : 500;
|
|
639
|
+
return reply.status(statusCode).send({
|
|
640
|
+
error: result.code,
|
|
641
|
+
message: result.message,
|
|
642
|
+
});
|
|
643
|
+
}
|
|
644
|
+
return reply.send(result);
|
|
645
|
+
}
|
|
646
|
+
catch (error) {
|
|
647
|
+
app.log.error(error);
|
|
648
|
+
return reply.status(500).send({
|
|
649
|
+
error: 'Graph deps failed',
|
|
650
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
651
|
+
});
|
|
652
|
+
}
|
|
653
|
+
});
|
|
654
|
+
/**
|
|
655
|
+
* GET /api/code/graph/hierarchy
|
|
656
|
+
* Build class/interface hierarchy for a symbol.
|
|
657
|
+
*/
|
|
658
|
+
app.get('/graph/hierarchy', {
|
|
659
|
+
schema: {
|
|
660
|
+
querystring: {
|
|
661
|
+
type: 'object',
|
|
662
|
+
properties: {
|
|
663
|
+
symbolId: { type: 'string' },
|
|
664
|
+
symbolName: { type: 'string' },
|
|
665
|
+
direction: { type: 'string', enum: ['ancestors', 'descendants', 'both'], default: 'both' },
|
|
666
|
+
},
|
|
667
|
+
},
|
|
668
|
+
},
|
|
669
|
+
}, async (request, reply) => {
|
|
670
|
+
if (!requireCodeEnabled(reply))
|
|
671
|
+
return;
|
|
672
|
+
const { symbolId, symbolName, direction = 'both' } = request.query;
|
|
673
|
+
if (!symbolId && !symbolName) {
|
|
674
|
+
return reply.status(400).send({
|
|
675
|
+
error: 'Invalid query',
|
|
676
|
+
message: 'Provide either symbolId or symbolName',
|
|
677
|
+
});
|
|
678
|
+
}
|
|
679
|
+
try {
|
|
680
|
+
const context = requireProjectContext();
|
|
681
|
+
if (!context.codeIndexer) {
|
|
682
|
+
return reply.status(400).send({
|
|
683
|
+
error: 'Code indexer not available',
|
|
684
|
+
message: 'Code indexing is not initialized for this project',
|
|
685
|
+
});
|
|
686
|
+
}
|
|
687
|
+
const result = await context.codeIndexer.graphHierarchy({
|
|
688
|
+
symbolId,
|
|
689
|
+
symbolName,
|
|
690
|
+
direction,
|
|
691
|
+
});
|
|
692
|
+
if (isError(result)) {
|
|
693
|
+
const statusCode = result.code === 'NOT_FOUND' ? 404 : 500;
|
|
694
|
+
return reply.status(statusCode).send({
|
|
695
|
+
error: result.code,
|
|
696
|
+
message: result.message,
|
|
697
|
+
});
|
|
698
|
+
}
|
|
699
|
+
return reply.send(result);
|
|
700
|
+
}
|
|
701
|
+
catch (error) {
|
|
702
|
+
app.log.error(error);
|
|
703
|
+
return reply.status(500).send({
|
|
704
|
+
error: 'Graph hierarchy failed',
|
|
705
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
});
|
|
709
|
+
/**
|
|
710
|
+
* GET /api/code/grep
|
|
711
|
+
* Exact text search in code files
|
|
712
|
+
*/
|
|
713
|
+
app.get('/grep', {
|
|
714
|
+
schema: {
|
|
715
|
+
querystring: {
|
|
716
|
+
type: 'object',
|
|
717
|
+
required: ['pattern'],
|
|
718
|
+
properties: {
|
|
719
|
+
pattern: { type: 'string' },
|
|
720
|
+
regex: { type: 'boolean', default: false },
|
|
721
|
+
caseSensitive: { type: 'boolean', default: false },
|
|
722
|
+
limit: { type: 'number', default: 20 },
|
|
723
|
+
language: { type: 'string' },
|
|
724
|
+
context: { type: 'number', default: 1 },
|
|
725
|
+
},
|
|
726
|
+
},
|
|
727
|
+
},
|
|
728
|
+
}, async (request, reply) => {
|
|
729
|
+
if (!requireCodeEnabled(reply))
|
|
730
|
+
return;
|
|
731
|
+
const { pattern, regex = false, caseSensitive = false, limit = 20, language, context: contextLines = 1 } = request.query;
|
|
732
|
+
try {
|
|
733
|
+
const project = getCurrentProject();
|
|
734
|
+
const codePath = getCodePath();
|
|
735
|
+
const include = project.config.code.include || ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'];
|
|
736
|
+
const exclude = project.config.code.exclude || ['**/node_modules/**', '**/dist/**'];
|
|
737
|
+
// Build regex for search
|
|
738
|
+
let searchRegex;
|
|
739
|
+
try {
|
|
740
|
+
if (regex) {
|
|
741
|
+
searchRegex = new RegExp(pattern, caseSensitive ? 'g' : 'gi');
|
|
742
|
+
}
|
|
743
|
+
else {
|
|
744
|
+
// Escape special regex characters for literal search
|
|
745
|
+
const escaped = pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
746
|
+
searchRegex = new RegExp(escaped, caseSensitive ? 'g' : 'gi');
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
catch {
|
|
750
|
+
return reply.status(400).send({
|
|
751
|
+
error: 'Invalid pattern',
|
|
752
|
+
message: 'Invalid regular expression pattern',
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
const results = [];
|
|
756
|
+
let totalMatches = 0;
|
|
757
|
+
// Search through code files
|
|
758
|
+
for (const includePattern of include) {
|
|
759
|
+
const files = await glob(includePattern, {
|
|
760
|
+
cwd: codePath,
|
|
761
|
+
nodir: true,
|
|
762
|
+
ignore: exclude,
|
|
763
|
+
});
|
|
764
|
+
for (const file of files) {
|
|
765
|
+
if (totalMatches >= limit)
|
|
766
|
+
break;
|
|
767
|
+
const fileLang = detectLanguage(file);
|
|
768
|
+
if (language && fileLang !== language)
|
|
769
|
+
continue;
|
|
770
|
+
const fullPath = path.join(codePath, file);
|
|
771
|
+
const content = await fs.readFile(fullPath, 'utf-8');
|
|
772
|
+
const lines = content.split('\n');
|
|
773
|
+
const fileMatches = [];
|
|
774
|
+
for (let i = 0; i < lines.length; i++) {
|
|
775
|
+
if (totalMatches >= limit)
|
|
776
|
+
break;
|
|
777
|
+
if (searchRegex.test(lines[i])) {
|
|
778
|
+
searchRegex.lastIndex = 0; // Reset regex state
|
|
779
|
+
const contextBefore = [];
|
|
780
|
+
const contextAfter = [];
|
|
781
|
+
// Get context before
|
|
782
|
+
for (let j = Math.max(0, i - contextLines); j < i; j++) {
|
|
783
|
+
contextBefore.push(lines[j]);
|
|
784
|
+
}
|
|
785
|
+
// Get context after
|
|
786
|
+
for (let j = i + 1; j <= Math.min(lines.length - 1, i + contextLines); j++) {
|
|
787
|
+
contextAfter.push(lines[j]);
|
|
788
|
+
}
|
|
789
|
+
fileMatches.push({
|
|
790
|
+
line: i + 1,
|
|
791
|
+
content: lines[i],
|
|
792
|
+
contextBefore,
|
|
793
|
+
contextAfter,
|
|
794
|
+
});
|
|
795
|
+
totalMatches++;
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
if (fileMatches.length > 0) {
|
|
799
|
+
results.push({
|
|
800
|
+
path: fullPath,
|
|
801
|
+
relativePath: file,
|
|
802
|
+
language: fileLang,
|
|
803
|
+
matches: fileMatches,
|
|
804
|
+
});
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
if (totalMatches >= limit)
|
|
808
|
+
break;
|
|
809
|
+
}
|
|
810
|
+
return reply.send({
|
|
811
|
+
pattern,
|
|
812
|
+
results,
|
|
813
|
+
total: totalMatches,
|
|
814
|
+
});
|
|
815
|
+
}
|
|
816
|
+
catch (error) {
|
|
817
|
+
app.log.error(error);
|
|
818
|
+
return reply.status(500).send({
|
|
819
|
+
error: 'Grep failed',
|
|
820
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
821
|
+
});
|
|
822
|
+
}
|
|
823
|
+
});
|
|
824
|
+
/**
|
|
825
|
+
* POST /api/code/sync
|
|
826
|
+
* Trigger code sync using SyncWal for recovery and progress tracking.
|
|
827
|
+
* Supports branch-aware sync: auto-detect mode by default.
|
|
828
|
+
*
|
|
829
|
+
* Mode:
|
|
830
|
+
* - 'auto' (default): overlay on feature branches, full reindex on main
|
|
831
|
+
* - 'reindex': force full reindex (errors on feature branch)
|
|
832
|
+
* - 'overlay': force overlay sync only
|
|
833
|
+
*/
|
|
834
|
+
app.post('/sync', {
|
|
835
|
+
schema: {
|
|
836
|
+
body: {
|
|
837
|
+
type: 'object',
|
|
838
|
+
properties: {
|
|
839
|
+
force: { type: 'boolean', default: false },
|
|
840
|
+
resume: { type: 'boolean', default: false },
|
|
841
|
+
mode: { type: 'string', enum: ['auto', 'reindex', 'overlay'], default: 'auto' },
|
|
842
|
+
},
|
|
843
|
+
},
|
|
844
|
+
},
|
|
845
|
+
}, async (request, reply) => {
|
|
846
|
+
if (!requireCodeEnabled(reply))
|
|
847
|
+
return;
|
|
848
|
+
// Update secrets if changed (e.g., Voyage API key added after project open)
|
|
849
|
+
await updateSecretsIfNeeded(request.secrets || {});
|
|
850
|
+
const codePath = getCodePath();
|
|
851
|
+
const gitInfo = getGitInfo(codePath);
|
|
852
|
+
const mode = request.body?.mode || 'auto';
|
|
853
|
+
// Determine sync mode
|
|
854
|
+
let useOverlay = false;
|
|
855
|
+
if (mode === 'auto') {
|
|
856
|
+
useOverlay = gitInfo ? !gitInfo.isMainBranch : false;
|
|
857
|
+
}
|
|
858
|
+
else if (mode === 'overlay') {
|
|
859
|
+
useOverlay = true;
|
|
860
|
+
}
|
|
861
|
+
const syncMode = useOverlay ? 'overlay' : 'reindex';
|
|
862
|
+
// Extra data for SSE events
|
|
863
|
+
const extraEventData = {
|
|
864
|
+
branch: gitInfo?.branch || null,
|
|
865
|
+
isMainBranch: gitInfo?.isMainBranch ?? null,
|
|
866
|
+
mode: syncMode,
|
|
867
|
+
};
|
|
868
|
+
const handler = createSyncHandler(app, {
|
|
869
|
+
type: 'code',
|
|
870
|
+
isEnabled: (ctx) => !!ctx.codeIndexer,
|
|
871
|
+
notEnabledError: 'Code indexing is not initialized for this project',
|
|
872
|
+
validate: async (ctx, body) => {
|
|
873
|
+
// Check if required secrets are present for the configured provider
|
|
874
|
+
const project = getCurrentProject();
|
|
875
|
+
if (!project)
|
|
876
|
+
return 'No project open';
|
|
877
|
+
const secretsError = validateSecrets(project.config, project.secrets);
|
|
878
|
+
if (secretsError)
|
|
879
|
+
return secretsError;
|
|
880
|
+
// Validate: don't allow reindex on feature branch
|
|
881
|
+
if (mode === 'reindex' && gitInfo && !gitInfo.isMainBranch) {
|
|
882
|
+
return `Cannot use 'reindex' mode on feature branch '${gitInfo.branch}'. Use 'overlay' or 'auto' mode instead.`;
|
|
883
|
+
}
|
|
884
|
+
return null;
|
|
885
|
+
},
|
|
886
|
+
clearIndex: async (ctx) => {
|
|
887
|
+
await ctx.codeIndexer.clear();
|
|
888
|
+
},
|
|
889
|
+
getExtraEventData: () => extraEventData,
|
|
890
|
+
setupCallbacks: (ctx, emitProgress) => {
|
|
891
|
+
// Embedding progress callback - only send phase/current/progress
|
|
892
|
+
ctx.syncWal.onEmbeddingProgress((current, total) => {
|
|
893
|
+
emitProgress({
|
|
894
|
+
phase: 'embedding',
|
|
895
|
+
current: `Embedding batch ${current}/${total}`,
|
|
896
|
+
progress: Math.round((current / total) * 100),
|
|
897
|
+
});
|
|
898
|
+
});
|
|
899
|
+
// Sub-phase progress (graph/tree building)
|
|
900
|
+
ctx.syncWal.onSubPhaseProgress((current, total, subPhase) => {
|
|
901
|
+
const [phase, step] = subPhase.split(':');
|
|
902
|
+
emitProgress({
|
|
903
|
+
phase,
|
|
904
|
+
current: `${step}: ${current}/${total}`,
|
|
905
|
+
progress: total > 0 ? Math.round((current / total) * 100) : 0,
|
|
906
|
+
});
|
|
907
|
+
});
|
|
908
|
+
},
|
|
909
|
+
runSync: async (ctx, recoveryPlan) => {
|
|
910
|
+
if (useOverlay && ctx.codeBranchIndexer) {
|
|
911
|
+
return ctx.codeBranchIndexer.syncOverlay();
|
|
912
|
+
}
|
|
913
|
+
else {
|
|
914
|
+
return ctx.codeIndexer.reindexAllWithSyncWal(recoveryPlan || undefined);
|
|
915
|
+
}
|
|
916
|
+
},
|
|
917
|
+
});
|
|
918
|
+
return handler(request, reply);
|
|
919
|
+
});
|
|
920
|
+
/**
|
|
921
|
+
* POST /api/code/reindex
|
|
922
|
+
* Reindex specific files or folders
|
|
923
|
+
*/
|
|
924
|
+
app.post('/reindex', {
|
|
925
|
+
schema: {
|
|
926
|
+
body: {
|
|
927
|
+
type: 'object',
|
|
928
|
+
required: ['paths'],
|
|
929
|
+
properties: {
|
|
930
|
+
paths: {
|
|
931
|
+
type: 'array',
|
|
932
|
+
items: { type: 'string' },
|
|
933
|
+
},
|
|
934
|
+
},
|
|
935
|
+
},
|
|
936
|
+
},
|
|
937
|
+
}, async (request, reply) => {
|
|
938
|
+
if (!requireCodeEnabled(reply))
|
|
939
|
+
return;
|
|
940
|
+
const { paths } = request.body;
|
|
941
|
+
const project = getCurrentProject();
|
|
942
|
+
try {
|
|
943
|
+
emitEvent({
|
|
944
|
+
type: 'reindex:code:started',
|
|
945
|
+
data: { paths },
|
|
946
|
+
});
|
|
947
|
+
// TODO: Implement actual reindexing
|
|
948
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
949
|
+
emitEvent({
|
|
950
|
+
type: 'reindex:code:completed',
|
|
951
|
+
data: { paths },
|
|
952
|
+
});
|
|
953
|
+
return reply.send({
|
|
954
|
+
success: true,
|
|
955
|
+
message: `Reindexed ${paths.length} paths`,
|
|
956
|
+
});
|
|
957
|
+
}
|
|
958
|
+
catch (error) {
|
|
959
|
+
emitEvent({
|
|
960
|
+
type: 'reindex:code:error',
|
|
961
|
+
data: {
|
|
962
|
+
paths,
|
|
963
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
964
|
+
},
|
|
965
|
+
});
|
|
966
|
+
app.log.error(error);
|
|
967
|
+
return reply.status(500).send({
|
|
968
|
+
error: 'Reindex failed',
|
|
969
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
970
|
+
});
|
|
971
|
+
}
|
|
972
|
+
});
|
|
973
|
+
}
|
|
974
|
+
//# sourceMappingURL=code.js.map
|