claude-code-workflow 7.2.5 → 7.2.7
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/.claude/commands/workflow/analyze-with-file.md +11 -10
- package/.claude/skills/ccw-help/command.json +3 -3
- package/.claude/skills/ccw-help/index/all-commands.json +3 -3
- package/.claude/skills/ccw-help/index/by-category.json +3 -3
- package/.claude/skills/ccw-help/index/by-use-case.json +3 -3
- package/.claude/skills/skill-iter-tune/SKILL.md +382 -0
- package/.claude/skills/skill-iter-tune/phases/01-setup.md +144 -0
- package/.claude/skills/skill-iter-tune/phases/02-execute.md +292 -0
- package/.claude/skills/skill-iter-tune/phases/03-evaluate.md +312 -0
- package/.claude/skills/skill-iter-tune/phases/04-improve.md +186 -0
- package/.claude/skills/skill-iter-tune/phases/05-report.md +166 -0
- package/.claude/skills/skill-iter-tune/specs/evaluation-criteria.md +63 -0
- package/.claude/skills/skill-iter-tune/templates/eval-prompt.md +134 -0
- package/.claude/skills/skill-iter-tune/templates/execute-prompt.md +97 -0
- package/.claude/skills/team-roadmap-dev/SKILL.md +1 -1
- package/.claude/skills/team-roadmap-dev/roles/coordinator/role.md +1 -1
- package/.claude/skills/team-roadmap-dev/specs/team-config.json +1 -1
- package/ccw/dist/commands/install.d.ts.map +1 -1
- package/ccw/dist/commands/install.js +11 -9
- package/ccw/dist/commands/install.js.map +1 -1
- package/ccw/dist/core/routes/codexlens/config-handlers.d.ts.map +1 -1
- package/ccw/dist/core/routes/codexlens/config-handlers.js +4 -0
- package/ccw/dist/core/routes/codexlens/config-handlers.js.map +1 -1
- package/ccw/dist/mcp-server/index.js +85 -8
- package/ccw/dist/mcp-server/index.js.map +1 -1
- package/ccw/dist/tools/cli-executor-core.d.ts.map +1 -1
- package/ccw/dist/tools/cli-executor-core.js +0 -25
- package/ccw/dist/tools/cli-executor-core.js.map +1 -1
- package/ccw/dist/tools/cli-executor-state.d.ts.map +1 -1
- package/ccw/dist/tools/cli-executor-state.js +0 -31
- package/ccw/dist/tools/cli-executor-state.js.map +1 -1
- package/ccw/dist/tools/cli-history-store.d.ts.map +1 -1
- package/ccw/dist/tools/cli-history-store.js +1 -30
- package/ccw/dist/tools/cli-history-store.js.map +1 -1
- package/ccw/dist/tools/smart-search.d.ts +72 -1
- package/ccw/dist/tools/smart-search.d.ts.map +1 -1
- package/ccw/dist/tools/smart-search.js +726 -117
- package/ccw/dist/tools/smart-search.js.map +1 -1
- package/ccw/frontend/dist/assets/{AlertDialog-CFGtc76Y.js → AlertDialog-CSZq4WHZ.js} +2 -2
- package/ccw/frontend/dist/assets/{AlertDialog-CFGtc76Y.js.map → AlertDialog-CSZq4WHZ.js.map} +1 -1
- package/ccw/frontend/dist/assets/{AnalysisPage-Duxia_dG.js → AnalysisPage-DVDvLHqI.js} +2 -2
- package/ccw/frontend/dist/assets/{AnalysisPage-Duxia_dG.js.map → AnalysisPage-DVDvLHqI.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ApiSettingsPage-CU9hesAE.js → ApiSettingsPage-D69j8mI6.js} +2 -2
- package/ccw/frontend/dist/assets/{ApiSettingsPage-CU9hesAE.js.map → ApiSettingsPage-D69j8mI6.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CliModeToggle-DcdOFSvM.js → CliModeToggle-fF9xHeGR.js} +2 -2
- package/ccw/frontend/dist/assets/{CliModeToggle-DcdOFSvM.js.map → CliModeToggle-fF9xHeGR.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CliSessionSharePage-oKN-GRIT.js → CliSessionSharePage-Ce8tOQNx.js} +2 -2
- package/ccw/frontend/dist/assets/{CliSessionSharePage-oKN-GRIT.js.map → CliSessionSharePage-Ce8tOQNx.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CliViewerPage-_wUoHaY-.js → CliViewerPage-Bsp1zmfD.js} +2 -2
- package/ccw/frontend/dist/assets/{CliViewerPage-_wUoHaY-.js.map → CliViewerPage-Bsp1zmfD.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CodexLensManagerPage-ClPNashJ.js → CodexLensManagerPage-DUMzbrr9.js} +9 -9
- package/ccw/frontend/dist/assets/CodexLensManagerPage-DUMzbrr9.js.map +1 -0
- package/ccw/frontend/dist/assets/{Collapsible-Dladh9Eu.js → Collapsible-I5pixbHb.js} +2 -2
- package/ccw/frontend/dist/assets/{Collapsible-Dladh9Eu.js.map → Collapsible-I5pixbHb.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CommandsManagerPage-B6DBb_Ew.js → CommandsManagerPage-BH2xukdx.js} +2 -2
- package/ccw/frontend/dist/assets/{CommandsManagerPage-B6DBb_Ew.js.map → CommandsManagerPage-BH2xukdx.js.map} +1 -1
- package/ccw/frontend/dist/assets/{DeepWikiPage-CDA3xm3R.js → DeepWikiPage-D41ccWzY.js} +2 -2
- package/ccw/frontend/dist/assets/{DeepWikiPage-CDA3xm3R.js.map → DeepWikiPage-D41ccWzY.js.map} +1 -1
- package/ccw/frontend/dist/assets/{EndpointsPage-Bu7iU0Wy.js → EndpointsPage-5a8jfEWN.js} +2 -2
- package/ccw/frontend/dist/assets/{EndpointsPage-Bu7iU0Wy.js.map → EndpointsPage-5a8jfEWN.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ExplorerPage-xim2cboZ.js → ExplorerPage-YCqIOu1v.js} +2 -2
- package/ccw/frontend/dist/assets/{ExplorerPage-xim2cboZ.js.map → ExplorerPage-YCqIOu1v.js.map} +1 -1
- package/ccw/frontend/dist/assets/{FixSessionPage-BTFYoFQF.js → FixSessionPage-wK1s4kbo.js} +2 -2
- package/ccw/frontend/dist/assets/{FixSessionPage-BTFYoFQF.js.map → FixSessionPage-wK1s4kbo.js.map} +1 -1
- package/ccw/frontend/dist/assets/{FloatingFileBrowser-B30ANzTJ.js → FloatingFileBrowser-B1U6uk_5.js} +2 -2
- package/ccw/frontend/dist/assets/{FloatingFileBrowser-B30ANzTJ.js.map → FloatingFileBrowser-B1U6uk_5.js.map} +1 -1
- package/ccw/frontend/dist/assets/{FloatingPanel-Ds84B7Ob.js → FloatingPanel-D51p5jNy.js} +2 -2
- package/ccw/frontend/dist/assets/{FloatingPanel-Ds84B7Ob.js.map → FloatingPanel-D51p5jNy.js.map} +1 -1
- package/ccw/frontend/dist/assets/{GraphExplorerPage-DJ4YnFOQ.js → GraphExplorerPage-DpIWrpWH.js} +2 -2
- package/ccw/frontend/dist/assets/{GraphExplorerPage-DJ4YnFOQ.js.map → GraphExplorerPage-DpIWrpWH.js.map} +1 -1
- package/ccw/frontend/dist/assets/{HistoryPage-rzLVsw11.js → HistoryPage-C09lyJGN.js} +2 -2
- package/ccw/frontend/dist/assets/{HistoryPage-rzLVsw11.js.map → HistoryPage-C09lyJGN.js.map} +1 -1
- package/ccw/frontend/dist/assets/{HookManagerPage-DizO_dCP.js → HookManagerPage-CFBe8F_G.js} +2 -2
- package/ccw/frontend/dist/assets/{HookManagerPage-DizO_dCP.js.map → HookManagerPage-CFBe8F_G.js.map} +1 -1
- package/ccw/frontend/dist/assets/{InstallationsPage-BFamuE4y.js → InstallationsPage-qt7NxnsB.js} +2 -2
- package/ccw/frontend/dist/assets/{InstallationsPage-BFamuE4y.js.map → InstallationsPage-qt7NxnsB.js.map} +1 -1
- package/ccw/frontend/dist/assets/{IssueHubPage-DHwQWuUc.js → IssueHubPage-CHol1-Ap.js} +2 -2
- package/ccw/frontend/dist/assets/{IssueHubPage-DHwQWuUc.js.map → IssueHubPage-CHol1-Ap.js.map} +1 -1
- package/ccw/frontend/dist/assets/{LiteTasksPage-DMDkG7pi.js → LiteTasksPage-jH00SLnZ.js} +2 -2
- package/ccw/frontend/dist/assets/{LiteTasksPage-DMDkG7pi.js.map → LiteTasksPage-jH00SLnZ.js.map} +1 -1
- package/ccw/frontend/dist/assets/{McpManagerPage-CS2v_1OG.js → McpManagerPage-BS-HgeQJ.js} +11 -11
- package/ccw/frontend/dist/assets/McpManagerPage-BS-HgeQJ.js.map +1 -0
- package/ccw/frontend/dist/assets/{MemoryPage-DhYPE-VC.js → MemoryPage-1UahrmRX.js} +2 -2
- package/ccw/frontend/dist/assets/{MemoryPage-DhYPE-VC.js.map → MemoryPage-1UahrmRX.js.map} +1 -1
- package/ccw/frontend/dist/assets/{NotFoundPage-BLmC7-ot.js → NotFoundPage-5FVm_IkS.js} +2 -2
- package/ccw/frontend/dist/assets/{NotFoundPage-BLmC7-ot.js.map → NotFoundPage-5FVm_IkS.js.map} +1 -1
- package/ccw/frontend/dist/assets/{OrchestratorPage-1jzSUFZW.js → OrchestratorPage-ThBG24Gg.js} +2 -2
- package/ccw/frontend/dist/assets/{OrchestratorPage-1jzSUFZW.js.map → OrchestratorPage-ThBG24Gg.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ProjectOverviewPage-gWuAj-Cn.js → ProjectOverviewPage-CrmW0IxI.js} +2 -2
- package/ccw/frontend/dist/assets/{ProjectOverviewPage-gWuAj-Cn.js.map → ProjectOverviewPage-CrmW0IxI.js.map} +1 -1
- package/ccw/frontend/dist/assets/{PromptHistoryPage-q7ySVNHM.js → PromptHistoryPage-1cCGwS3s.js} +2 -2
- package/ccw/frontend/dist/assets/{PromptHistoryPage-q7ySVNHM.js.map → PromptHistoryPage-1cCGwS3s.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ReviewSessionPage-DX1uT_nH.js → ReviewSessionPage-DxiEc9HK.js} +2 -2
- package/ccw/frontend/dist/assets/{ReviewSessionPage-DX1uT_nH.js.map → ReviewSessionPage-DxiEc9HK.js.map} +1 -1
- package/ccw/frontend/dist/assets/{RulesManagerPage-Bg6T5W-W.js → RulesManagerPage-BpplliZF.js} +2 -2
- package/ccw/frontend/dist/assets/{RulesManagerPage-Bg6T5W-W.js.map → RulesManagerPage-BpplliZF.js.map} +1 -1
- package/ccw/frontend/dist/assets/{SessionDetailPage-C_ig6JSh.js → SessionDetailPage-crDIiysh.js} +2 -2
- package/ccw/frontend/dist/assets/{SessionDetailPage-C_ig6JSh.js.map → SessionDetailPage-crDIiysh.js.map} +1 -1
- package/ccw/frontend/dist/assets/{SessionsPage-BENFqFDn.js → SessionsPage-DThweYY8.js} +2 -2
- package/ccw/frontend/dist/assets/{SessionsPage-BENFqFDn.js.map → SessionsPage-DThweYY8.js.map} +1 -1
- package/ccw/frontend/dist/assets/{SettingsPage-2c-oTxfz.js → SettingsPage-OCdOz5-z.js} +4 -4
- package/ccw/frontend/dist/assets/{SettingsPage-2c-oTxfz.js.map → SettingsPage-OCdOz5-z.js.map} +1 -1
- package/ccw/frontend/dist/assets/{SkillsManagerPage-GLo6DXnt.js → SkillsManagerPage-BJd3bK1G.js} +2 -2
- package/ccw/frontend/dist/assets/{SkillsManagerPage-GLo6DXnt.js.map → SkillsManagerPage-BJd3bK1G.js.map} +1 -1
- package/ccw/frontend/dist/assets/{SpecsSettingsPage-CRqMV90p.js → SpecsSettingsPage-BAWL2cpO.js} +2 -2
- package/ccw/frontend/dist/assets/{SpecsSettingsPage-CRqMV90p.js.map → SpecsSettingsPage-BAWL2cpO.js.map} +1 -1
- package/ccw/frontend/dist/assets/{Switch-vlMavMRD.js → Switch-w0I3JCcC.js} +2 -2
- package/ccw/frontend/dist/assets/{Switch-vlMavMRD.js.map → Switch-w0I3JCcC.js.map} +1 -1
- package/ccw/frontend/dist/assets/{TabsNavigation-CLKz7pWP.js → TabsNavigation-jhUge9YV.js} +2 -2
- package/ccw/frontend/dist/assets/{TabsNavigation-CLKz7pWP.js.map → TabsNavigation-jhUge9YV.js.map} +1 -1
- package/ccw/frontend/dist/assets/{TaskDrawer-BAFvNqF8.js → TaskDrawer-APWpZulm.js} +2 -2
- package/ccw/frontend/dist/assets/{TaskDrawer-BAFvNqF8.js.map → TaskDrawer-APWpZulm.js.map} +1 -1
- package/ccw/frontend/dist/assets/{TeamPage-C2IsDkAv.js → TeamPage-8OnLsAfJ.js} +2 -2
- package/ccw/frontend/dist/assets/{TeamPage-C2IsDkAv.js.map → TeamPage-8OnLsAfJ.js.map} +1 -1
- package/ccw/frontend/dist/assets/{TerminalDashboardPage-mgS-iKDm.js → TerminalDashboardPage-Be1hcN4p.js} +2 -2
- package/ccw/frontend/dist/assets/{TerminalDashboardPage-mgS-iKDm.js.map → TerminalDashboardPage-Be1hcN4p.js.map} +1 -1
- package/ccw/frontend/dist/assets/{archive-CxxK_YIp.js → archive-Bo1tC9yo.js} +2 -2
- package/ccw/frontend/dist/assets/{archive-CxxK_YIp.js.map → archive-Bo1tC9yo.js.map} +1 -1
- package/ccw/frontend/dist/assets/{archive-restore-DZsrBaeG.js → archive-restore-DYx41yLJ.js} +2 -2
- package/ccw/frontend/dist/assets/{archive-restore-DZsrBaeG.js.map → archive-restore-DYx41yLJ.js.map} +1 -1
- package/ccw/frontend/dist/assets/{arrow-right-BotRHOhr.js → arrow-right-C6pOqWF1.js} +2 -2
- package/ccw/frontend/dist/assets/{arrow-right-BotRHOhr.js.map → arrow-right-C6pOqWF1.js.map} +1 -1
- package/ccw/frontend/dist/assets/{bookmark-plus-C0MWZ3S9.js → bookmark-plus-4Qpa6hMJ.js} +2 -2
- package/ccw/frontend/dist/assets/{bookmark-plus-C0MWZ3S9.js.map → bookmark-plus-4Qpa6hMJ.js.map} +1 -1
- package/ccw/frontend/dist/assets/{bot-BcHFJXqD.js → bot-HXJTmx8r.js} +2 -2
- package/ccw/frontend/dist/assets/{bot-BcHFJXqD.js.map → bot-HXJTmx8r.js.map} +1 -1
- package/ccw/frontend/dist/assets/{braces-D_p0IZhP.js → braces-Dj2IdY7I.js} +2 -2
- package/ccw/frontend/dist/assets/{braces-D_p0IZhP.js.map → braces-Dj2IdY7I.js.map} +1 -1
- package/ccw/frontend/dist/assets/{circle-stop-Bt634NUt.js → circle-stop-M29TJKHc.js} +2 -2
- package/ccw/frontend/dist/assets/{circle-stop-Bt634NUt.js.map → circle-stop-M29TJKHc.js.map} +1 -1
- package/ccw/frontend/dist/assets/{cpu-DjeGKtvT.js → cpu-DX15mzMT.js} +2 -2
- package/ccw/frontend/dist/assets/{cpu-DjeGKtvT.js.map → cpu-DX15mzMT.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ellipsis-vertical-BmNPuatq.js → ellipsis-vertical-Fs6bysWx.js} +2 -2
- package/ccw/frontend/dist/assets/{ellipsis-vertical-BmNPuatq.js.map → ellipsis-vertical-Fs6bysWx.js.map} +1 -1
- package/ccw/frontend/dist/assets/{eye-B0-xkP67.js → eye-D6BRlJ1r.js} +2 -2
- package/ccw/frontend/dist/assets/{eye-B0-xkP67.js.map → eye-D6BRlJ1r.js.map} +1 -1
- package/ccw/frontend/dist/assets/{eye-off-Bz0Fkli3.js → eye-off-DjbIj5iN.js} +2 -2
- package/ccw/frontend/dist/assets/{eye-off-Bz0Fkli3.js.map → eye-off-DjbIj5iN.js.map} +1 -1
- package/ccw/frontend/dist/assets/{file-json-PUAS4vBm.js → file-json-kg4Lid-H.js} +2 -2
- package/ccw/frontend/dist/assets/{file-json-PUAS4vBm.js.map → file-json-kg4Lid-H.js.map} +1 -1
- package/ccw/frontend/dist/assets/{file-text-BMeW5-Sb.js → file-text-BMy5pXNV.js} +2 -2
- package/ccw/frontend/dist/assets/{file-text-BMeW5-Sb.js.map → file-text-BMy5pXNV.js.map} +1 -1
- package/ccw/frontend/dist/assets/{filter-B4wgMvwi.js → filter-BTN-lUUb.js} +2 -2
- package/ccw/frontend/dist/assets/{filter-B4wgMvwi.js.map → filter-BTN-lUUb.js.map} +1 -1
- package/ccw/frontend/dist/assets/{folder-BSHjjjND.js → folder-ChYtty7V.js} +2 -2
- package/ccw/frontend/dist/assets/{folder-BSHjjjND.js.map → folder-ChYtty7V.js.map} +1 -1
- package/ccw/frontend/dist/assets/{gauge-7VRNEl22.js → gauge-C0VJbjRb.js} +2 -2
- package/ccw/frontend/dist/assets/{gauge-7VRNEl22.js.map → gauge-C0VJbjRb.js.map} +1 -1
- package/ccw/frontend/dist/assets/{globe-PvVHBjbW.js → globe-DbNfDXnv.js} +2 -2
- package/ccw/frontend/dist/assets/{globe-PvVHBjbW.js.map → globe-DbNfDXnv.js.map} +1 -1
- package/ccw/frontend/dist/assets/{grid-3x3-CsmmDlhN.js → grid-3x3-xWcpBNxo.js} +2 -2
- package/ccw/frontend/dist/assets/{grid-3x3-CsmmDlhN.js.map → grid-3x3-xWcpBNxo.js.map} +1 -1
- package/ccw/frontend/dist/assets/{hard-drive-D88EZgTY.js → hard-drive-BTACzgUO.js} +2 -2
- package/ccw/frontend/dist/assets/{hard-drive-D88EZgTY.js.map → hard-drive-BTACzgUO.js.map} +1 -1
- package/ccw/frontend/dist/assets/{hash-CZpNRWqt.js → hash-B0dYlmyB.js} +2 -2
- package/ccw/frontend/dist/assets/{hash-CZpNRWqt.js.map → hash-B0dYlmyB.js.map} +1 -1
- package/ccw/frontend/dist/assets/{history-DxN1mopa.js → history-CRRLu6ck.js} +2 -2
- package/ccw/frontend/dist/assets/{history-DxN1mopa.js.map → history-CRRLu6ck.js.map} +1 -1
- package/ccw/frontend/dist/assets/{index-BzGEkwIf.js → index-BJIIo0B3.js} +2 -2
- package/ccw/frontend/dist/assets/{index-BzGEkwIf.js.map → index-BJIIo0B3.js.map} +1 -1
- package/ccw/frontend/dist/assets/{index-DlcRFzFq.js → index-BP-D3Wv6.js} +2 -2
- package/ccw/frontend/dist/assets/{index-DlcRFzFq.js.map → index-BP-D3Wv6.js.map} +1 -1
- package/ccw/frontend/dist/assets/{index-BUiq2PUK.js → index-B_QzEioU.js} +2 -2
- package/ccw/frontend/dist/assets/{index-BUiq2PUK.js.map → index-B_QzEioU.js.map} +1 -1
- package/ccw/frontend/dist/assets/{index-C04xeBGC.js → index-BpoRYgiq.js} +3 -3
- package/ccw/frontend/dist/assets/{index-C04xeBGC.js.map → index-BpoRYgiq.js.map} +1 -1
- package/ccw/frontend/dist/assets/{index-CIoWWkDn.js → index-CeESlrZb.js} +8 -8
- package/ccw/frontend/dist/assets/{index-CIoWWkDn.js.map → index-CeESlrZb.js.map} +1 -1
- package/ccw/frontend/dist/assets/{index-bSgtHHOF.js → index-DzTbMyaS.js} +4 -4
- package/ccw/frontend/dist/assets/{index-bSgtHHOF.js.map → index-DzTbMyaS.js.map} +1 -1
- package/ccw/frontend/dist/assets/{layout-grid-BZqfuNG0.js → layout-grid-ZN26YcTM.js} +2 -2
- package/ccw/frontend/dist/assets/{layout-grid-BZqfuNG0.js.map → layout-grid-ZN26YcTM.js.map} +1 -1
- package/ccw/frontend/dist/assets/{lightbulb-DqJ4OHRL.js → lightbulb-BHrwx9j6.js} +2 -2
- package/ccw/frontend/dist/assets/{lightbulb-DqJ4OHRL.js.map → lightbulb-BHrwx9j6.js.map} +1 -1
- package/ccw/frontend/dist/assets/{link-2-Bq7fLkC9.js → link-2-zZRu2j4G.js} +2 -2
- package/ccw/frontend/dist/assets/{link-2-Bq7fLkC9.js.map → link-2-zZRu2j4G.js.map} +1 -1
- package/ccw/frontend/dist/assets/{link-dSLYjCIG.js → link-8lz-HgnZ.js} +2 -2
- package/ccw/frontend/dist/assets/{link-dSLYjCIG.js.map → link-8lz-HgnZ.js.map} +1 -1
- package/ccw/frontend/dist/assets/{list-Bm_CnR56.js → list-DlablIjt.js} +2 -2
- package/ccw/frontend/dist/assets/{list-Bm_CnR56.js.map → list-DlablIjt.js.map} +1 -1
- package/ccw/frontend/dist/assets/{map-pin-B5TELa0z.js → map-pin-JAsCUplr.js} +2 -2
- package/ccw/frontend/dist/assets/{map-pin-B5TELa0z.js.map → map-pin-JAsCUplr.js.map} +1 -1
- package/ccw/frontend/dist/assets/{messages-square-B9sWItdK.js → messages-square-D0iSFb2Y.js} +2 -2
- package/ccw/frontend/dist/assets/{messages-square-B9sWItdK.js.map → messages-square-D0iSFb2Y.js.map} +1 -1
- package/ccw/frontend/dist/assets/{minimize-2-Z1MYs_Tp.js → minimize-2-BJmkU9CE.js} +2 -2
- package/ccw/frontend/dist/assets/{minimize-2-Z1MYs_Tp.js.map → minimize-2-BJmkU9CE.js.map} +1 -1
- package/ccw/frontend/dist/assets/{package-EEv4N_Qk.js → package-DYrbBCxk.js} +2 -2
- package/ccw/frontend/dist/assets/{package-EEv4N_Qk.js.map → package-DYrbBCxk.js.map} +1 -1
- package/ccw/frontend/dist/assets/{plug-CEkvvYXh.js → plug-VG7-23M-.js} +2 -2
- package/ccw/frontend/dist/assets/{plug-CEkvvYXh.js.map → plug-VG7-23M-.js.map} +1 -1
- package/ccw/frontend/dist/assets/{power-B6Rod0u_.js → power-zPFYNx7u.js} +2 -2
- package/ccw/frontend/dist/assets/{power-B6Rod0u_.js.map → power-zPFYNx7u.js.map} +1 -1
- package/ccw/frontend/dist/assets/{save-DULWrB2g.js → save-D4XQY9i9.js} +2 -2
- package/ccw/frontend/dist/assets/{save-DULWrB2g.js.map → save-D4XQY9i9.js.map} +1 -1
- package/ccw/frontend/dist/assets/{send-C4z974WG.js → send-ClSnDjj-.js} +2 -2
- package/ccw/frontend/dist/assets/{send-C4z974WG.js.map → send-ClSnDjj-.js.map} +1 -1
- package/ccw/frontend/dist/assets/{square-check-big-CqEEw-V0.js → square-check-big-Bffh_MFc.js} +2 -2
- package/ccw/frontend/dist/assets/{square-check-big-CqEEw-V0.js.map → square-check-big-Bffh_MFc.js.map} +1 -1
- package/ccw/frontend/dist/assets/{square-pen-D-4BrMtQ.js → square-pen-DsOvAvME.js} +2 -2
- package/ccw/frontend/dist/assets/{square-pen-D-4BrMtQ.js.map → square-pen-DsOvAvME.js.map} +1 -1
- package/ccw/frontend/dist/assets/{star-CDVVM69o.js → star-TLJjvoy2.js} +2 -2
- package/ccw/frontend/dist/assets/{star-CDVVM69o.js.map → star-TLJjvoy2.js.map} +1 -1
- package/ccw/frontend/dist/assets/{style-CumJ7XC8.js → style-BXKXgpOY.js} +2 -2
- package/ccw/frontend/dist/assets/{style-CumJ7XC8.js.map → style-BXKXgpOY.js.map} +1 -1
- package/ccw/frontend/dist/assets/{target-Dr9SuV1Y.js → target-FDuAB6SF.js} +2 -2
- package/ccw/frontend/dist/assets/{target-Dr9SuV1Y.js.map → target-FDuAB6SF.js.map} +1 -1
- package/ccw/frontend/dist/assets/{test-tube-DzDRKk8F.js → test-tube-B9vj-Im8.js} +2 -2
- package/ccw/frontend/dist/assets/{test-tube-DzDRKk8F.js.map → test-tube-B9vj-Im8.js.map} +1 -1
- package/ccw/frontend/dist/assets/{upload-CihSmIM7.js → upload-CHgTrVN5.js} +2 -2
- package/ccw/frontend/dist/assets/{upload-CihSmIM7.js.map → upload-CHgTrVN5.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useApiSettings-CevxWX2z.js → useApiSettings-XsHrqf-L.js} +2 -2
- package/ccw/frontend/dist/assets/{useApiSettings-CevxWX2z.js.map → useApiSettings-XsHrqf-L.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useCli-jVaF89uU.js → useCli-DOlWtux5.js} +2 -2
- package/ccw/frontend/dist/assets/{useCli-jVaF89uU.js.map → useCli-DOlWtux5.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useCommands-D4uGmNpF.js → useCommands-DazCajiX.js} +2 -2
- package/ccw/frontend/dist/assets/{useCommands-D4uGmNpF.js.map → useCommands-DazCajiX.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useDebounce-BEYmuZYP.js → useDebounce-Cah-bua6.js} +2 -2
- package/ccw/frontend/dist/assets/{useDebounce-BEYmuZYP.js.map → useDebounce-Cah-bua6.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useFileExplorer-DEv0DVy7.js → useFileExplorer-B9SCPhhl.js} +2 -2
- package/ccw/frontend/dist/assets/{useFileExplorer-DEv0DVy7.js.map → useFileExplorer-B9SCPhhl.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useLocale-BRJreqvl.js → useLocale-CmG6pxZe.js} +2 -2
- package/ccw/frontend/dist/assets/{useLocale-BRJreqvl.js.map → useLocale-CmG6pxZe.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useSkills-lnfeXe9l.js → useSkills-DvEJ0JOv.js} +3 -3
- package/ccw/frontend/dist/assets/{useSkills-lnfeXe9l.js.map → useSkills-DvEJ0JOv.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useSystemSettings-PlxVdbXI.js → useSystemSettings-BDpwSa04.js} +2 -2
- package/ccw/frontend/dist/assets/{useSystemSettings-PlxVdbXI.js.map → useSystemSettings-BDpwSa04.js.map} +1 -1
- package/ccw/frontend/dist/assets/{wand-sparkles-BbqUxeEg.js → wand-sparkles-T2KGCRiy.js} +2 -2
- package/ccw/frontend/dist/assets/{wand-sparkles-BbqUxeEg.js.map → wand-sparkles-T2KGCRiy.js.map} +1 -1
- package/ccw/frontend/dist/index.html +1 -1
- package/codex-lens/src/codexlens/cli/commands.py +12 -1
- package/codex-lens/src/codexlens/config.py +12 -0
- package/codex-lens/src/codexlens/env_config.py +1 -0
- package/package.json +1 -1
- package/ccw/frontend/dist/assets/CodexLensManagerPage-ClPNashJ.js.map +0 -1
- package/ccw/frontend/dist/assets/McpManagerPage-CS2v_1OG.js.map +0 -1
|
@@ -21,13 +21,14 @@ import { z } from 'zod';
|
|
|
21
21
|
import { spawn, execSync } from 'child_process';
|
|
22
22
|
import { existsSync, readFileSync, statSync } from 'fs';
|
|
23
23
|
import { dirname, join, resolve } from 'path';
|
|
24
|
-
import { ensureReady as ensureCodexLensReady, ensureLiteLLMEmbedderReady, executeCodexLens, getVenvPythonPath, } from './codex-lens.js';
|
|
24
|
+
import { ensureReady as ensureCodexLensReady, checkSemanticStatus, ensureLiteLLMEmbedderReady, executeCodexLens, getVenvPythonPath, } from './codex-lens.js';
|
|
25
25
|
import { getProjectRoot } from '../utils/path-validator.js';
|
|
26
26
|
import { getCodexLensDataDir } from '../utils/codexlens-path.js';
|
|
27
27
|
import { EXEC_TIMEOUTS } from '../utils/exec-constants.js';
|
|
28
28
|
import { generateRotationEndpoints } from '../config/litellm-api-config-manager.js';
|
|
29
29
|
// Timing utilities for performance analysis
|
|
30
30
|
const TIMING_ENABLED = process.env.SMART_SEARCH_TIMING === '1' || process.env.DEBUG?.includes('timing');
|
|
31
|
+
const SEARCH_OUTPUT_MODES = ['full', 'files_only', 'count', 'ace'];
|
|
31
32
|
function createTimer() {
|
|
32
33
|
const startTime = performance.now();
|
|
33
34
|
const marks = [];
|
|
@@ -61,7 +62,7 @@ const ParamsSchema = z.object({
|
|
|
61
62
|
query: z.string().optional().describe('Content search query (for action="search")'),
|
|
62
63
|
pattern: z.string().optional().describe('Glob pattern for path matching (for action="find_files")'),
|
|
63
64
|
mode: z.enum(['fuzzy', 'semantic']).default('fuzzy'),
|
|
64
|
-
output_mode: z.enum(
|
|
65
|
+
output_mode: z.enum(SEARCH_OUTPUT_MODES).default('ace'),
|
|
65
66
|
path: z.string().optional(),
|
|
66
67
|
paths: z.array(z.string()).default([]),
|
|
67
68
|
contextLines: z.number().default(0),
|
|
@@ -221,6 +222,7 @@ function readCodexLensSettingsSnapshot() {
|
|
|
221
222
|
return {
|
|
222
223
|
embedding_backend: normalizeEmbeddingBackend(typeof embedding.backend === 'string' ? embedding.backend : undefined),
|
|
223
224
|
embedding_model: typeof embedding.model === 'string' ? embedding.model : undefined,
|
|
225
|
+
embedding_auto_embed_missing: typeof embedding.auto_embed_missing === 'boolean' ? embedding.auto_embed_missing : undefined,
|
|
224
226
|
reranker_enabled: typeof reranker.enabled === 'boolean' ? reranker.enabled : undefined,
|
|
225
227
|
reranker_backend: typeof reranker.backend === 'string' ? reranker.backend : undefined,
|
|
226
228
|
reranker_model: typeof reranker.model === 'string' ? reranker.model : undefined,
|
|
@@ -244,6 +246,13 @@ function stripAnsi(str) {
|
|
|
244
246
|
}
|
|
245
247
|
/** Default maximum content length to return (avoid excessive output) */
|
|
246
248
|
const DEFAULT_MAX_CONTENT_LENGTH = 200;
|
|
249
|
+
const CODEX_LENS_FTS_COMPATIBILITY_PATTERNS = [
|
|
250
|
+
/UsageError:\s*Got unexpected extra arguments?/i,
|
|
251
|
+
/Option ['"]--method['"] does not take a value/i,
|
|
252
|
+
/TyperArgument\.make_metavar\(\) takes 1 positional argument but 2 were given/i,
|
|
253
|
+
];
|
|
254
|
+
let codexLensFtsBackendBroken = false;
|
|
255
|
+
const autoEmbedJobs = new Map();
|
|
247
256
|
/**
|
|
248
257
|
* Truncate content to specified length with ellipsis
|
|
249
258
|
* @param content - The content to truncate
|
|
@@ -348,12 +357,89 @@ function parseCodexLensJsonOutput(output) {
|
|
|
348
357
|
}
|
|
349
358
|
return null;
|
|
350
359
|
}
|
|
360
|
+
function isValidRegexPattern(pattern) {
|
|
361
|
+
try {
|
|
362
|
+
new RegExp(pattern);
|
|
363
|
+
return true;
|
|
364
|
+
}
|
|
365
|
+
catch {
|
|
366
|
+
return false;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
function resolveRipgrepQueryMode(query, regex = true, tokenize = true) {
|
|
370
|
+
const tokens = tokenize ? tokenizeQuery(query) : [query];
|
|
371
|
+
if (!regex) {
|
|
372
|
+
return {
|
|
373
|
+
regex: false,
|
|
374
|
+
tokenize,
|
|
375
|
+
tokens,
|
|
376
|
+
literalFallback: false,
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
const invalidTokens = tokens.filter((token) => token.length > 0 && !isValidRegexPattern(token));
|
|
380
|
+
if (invalidTokens.length === 0) {
|
|
381
|
+
return {
|
|
382
|
+
regex: true,
|
|
383
|
+
tokenize,
|
|
384
|
+
tokens,
|
|
385
|
+
literalFallback: false,
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
const preview = truncateContent(invalidTokens[0], 40);
|
|
389
|
+
return {
|
|
390
|
+
regex: false,
|
|
391
|
+
tokenize,
|
|
392
|
+
tokens,
|
|
393
|
+
literalFallback: true,
|
|
394
|
+
warning: invalidTokens.length === 1
|
|
395
|
+
? `Query token "${preview}" is not a valid regular expression. Falling back to literal ripgrep matching.`
|
|
396
|
+
: 'Query contains invalid regular expression tokens. Falling back to literal ripgrep matching.',
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
function isCodexLensCliCompatibilityError(error) {
|
|
400
|
+
if (!error) {
|
|
401
|
+
return false;
|
|
402
|
+
}
|
|
403
|
+
const cleanError = stripAnsi(error);
|
|
404
|
+
return CODEX_LENS_FTS_COMPATIBILITY_PATTERNS.some((pattern) => pattern.test(cleanError));
|
|
405
|
+
}
|
|
406
|
+
function noteCodexLensFtsCompatibility(error) {
|
|
407
|
+
if (!isCodexLensCliCompatibilityError(error)) {
|
|
408
|
+
return false;
|
|
409
|
+
}
|
|
410
|
+
codexLensFtsBackendBroken = true;
|
|
411
|
+
return true;
|
|
412
|
+
}
|
|
413
|
+
function summarizeBackendError(error) {
|
|
414
|
+
const cleanError = stripAnsi(error || '').trim();
|
|
415
|
+
if (!cleanError) {
|
|
416
|
+
return 'unknown error';
|
|
417
|
+
}
|
|
418
|
+
if (isCodexLensCliCompatibilityError(cleanError)) {
|
|
419
|
+
return 'CodexLens exact search CLI is incompatible with the current Typer/Click runtime';
|
|
420
|
+
}
|
|
421
|
+
const regexSummary = cleanError.match(/error:\s*([^\r\n]+)/i);
|
|
422
|
+
if (/regex parse error/i.test(cleanError) && regexSummary?.[1]) {
|
|
423
|
+
return `invalid regular expression (${regexSummary[1].trim()})`;
|
|
424
|
+
}
|
|
425
|
+
const usageSummary = cleanError.match(/UsageError:\s*([^\r\n]+)/i);
|
|
426
|
+
if (usageSummary?.[1]) {
|
|
427
|
+
return usageSummary[1].trim();
|
|
428
|
+
}
|
|
429
|
+
const firstMeaningfulLine = cleanError
|
|
430
|
+
.split(/\r?\n/)
|
|
431
|
+
.map((line) => line.trim())
|
|
432
|
+
.find((line) => line && !line.startsWith('│') && !line.startsWith('┌') && !line.startsWith('└'));
|
|
433
|
+
return truncateContent(firstMeaningfulLine || cleanError, 180);
|
|
434
|
+
}
|
|
351
435
|
function mapCodexLensSemanticMatches(data, scope, maxContentLength) {
|
|
352
436
|
return filterResultsToTargetFile(data.map((item) => {
|
|
353
437
|
const rawScore = item.score || 0;
|
|
354
438
|
const similarityScore = rawScore > 0 ? 1 / (1 + rawScore) : 1;
|
|
355
439
|
return {
|
|
356
440
|
file: item.path || item.file,
|
|
441
|
+
line: typeof item.line === 'number' ? item.line : undefined,
|
|
442
|
+
column: typeof item.column === 'number' ? item.column : undefined,
|
|
357
443
|
score: similarityScore,
|
|
358
444
|
content: truncateContent(item.content || item.excerpt, maxContentLength),
|
|
359
445
|
symbol: item.symbol || null,
|
|
@@ -399,11 +485,11 @@ function hasCentralizedVectorArtifacts(indexRoot) {
|
|
|
399
485
|
}
|
|
400
486
|
function collectBackendError(errors, backendName, backendResult) {
|
|
401
487
|
if (backendResult.status === 'rejected') {
|
|
402
|
-
errors.push(`${backendName}: ${String(backendResult.reason)}`);
|
|
488
|
+
errors.push(`${backendName}: ${summarizeBackendError(String(backendResult.reason))}`);
|
|
403
489
|
return;
|
|
404
490
|
}
|
|
405
491
|
if (!backendResult.value.success) {
|
|
406
|
-
errors.push(`${backendName}: ${backendResult.value.error
|
|
492
|
+
errors.push(`${backendName}: ${summarizeBackendError(backendResult.value.error)}`);
|
|
407
493
|
}
|
|
408
494
|
}
|
|
409
495
|
function mergeWarnings(...warnings) {
|
|
@@ -412,6 +498,75 @@ function mergeWarnings(...warnings) {
|
|
|
412
498
|
.map((warning) => warning.trim()))];
|
|
413
499
|
return merged.length > 0 ? merged.join(' | ') : undefined;
|
|
414
500
|
}
|
|
501
|
+
function mergeNotes(...notes) {
|
|
502
|
+
const merged = [...new Set(notes
|
|
503
|
+
.filter((note) => typeof note === 'string' && note.trim().length > 0)
|
|
504
|
+
.map((note) => note.trim()))];
|
|
505
|
+
return merged.length > 0 ? merged.join(' | ') : undefined;
|
|
506
|
+
}
|
|
507
|
+
function mergeSuggestions(...groups) {
|
|
508
|
+
const merged = new Map();
|
|
509
|
+
for (const group of groups) {
|
|
510
|
+
for (const suggestion of group ?? []) {
|
|
511
|
+
if (!merged.has(suggestion.command)) {
|
|
512
|
+
merged.set(suggestion.command, suggestion);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
return merged.size > 0 ? [...merged.values()] : undefined;
|
|
517
|
+
}
|
|
518
|
+
function formatSmartSearchCommand(action, pathValue, extraParams = {}) {
|
|
519
|
+
const normalizedPath = pathValue.replace(/\\/g, '/');
|
|
520
|
+
const args = [`action=${JSON.stringify(action)}`, `path=${JSON.stringify(normalizedPath)}`];
|
|
521
|
+
for (const [key, value] of Object.entries(extraParams)) {
|
|
522
|
+
if (value === undefined) {
|
|
523
|
+
continue;
|
|
524
|
+
}
|
|
525
|
+
args.push(`${key}=${JSON.stringify(value)}`);
|
|
526
|
+
}
|
|
527
|
+
return `smart_search(${args.join(', ')})`;
|
|
528
|
+
}
|
|
529
|
+
function isAutoEmbedMissingEnabled(config) {
|
|
530
|
+
return config?.embedding_auto_embed_missing !== false;
|
|
531
|
+
}
|
|
532
|
+
function buildIndexSuggestions(indexStatus, scope) {
|
|
533
|
+
const suggestions = [];
|
|
534
|
+
if (!indexStatus.indexed) {
|
|
535
|
+
suggestions.push({
|
|
536
|
+
title: 'Initialize index',
|
|
537
|
+
command: formatSmartSearchCommand('init', scope.workingDirectory),
|
|
538
|
+
reason: 'No CodexLens index exists for this path yet.',
|
|
539
|
+
});
|
|
540
|
+
suggestions.push({
|
|
541
|
+
title: 'Check index status',
|
|
542
|
+
command: formatSmartSearchCommand('status', scope.workingDirectory),
|
|
543
|
+
reason: 'Verify whether the target path is mapped to the expected CodexLens project root.',
|
|
544
|
+
});
|
|
545
|
+
return suggestions;
|
|
546
|
+
}
|
|
547
|
+
if (!indexStatus.has_embeddings) {
|
|
548
|
+
suggestions.push({
|
|
549
|
+
title: 'Generate embeddings',
|
|
550
|
+
command: formatSmartSearchCommand('embed', scope.workingDirectory),
|
|
551
|
+
reason: 'The index exists, but semantic/vector retrieval is unavailable until embeddings are generated.',
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
else if ((indexStatus.embeddings_coverage_percent ?? 0) < 50) {
|
|
555
|
+
suggestions.push({
|
|
556
|
+
title: 'Rebuild embeddings',
|
|
557
|
+
command: formatSmartSearchCommand('embed', scope.workingDirectory, { force: true }),
|
|
558
|
+
reason: `Embedding coverage is only ${(indexStatus.embeddings_coverage_percent ?? 0).toFixed(1)}%, so semantic search quality is degraded.`,
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
if (indexStatus.warning?.includes('Failed to parse index status')) {
|
|
562
|
+
suggestions.push({
|
|
563
|
+
title: 'Re-check status',
|
|
564
|
+
command: formatSmartSearchCommand('status', scope.workingDirectory),
|
|
565
|
+
reason: 'The index health payload could not be parsed cleanly.',
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
return suggestions.length > 0 ? suggestions : undefined;
|
|
569
|
+
}
|
|
415
570
|
/**
|
|
416
571
|
* Check if CodexLens index exists for current directory
|
|
417
572
|
* @param path - Directory path to check
|
|
@@ -437,12 +592,15 @@ async function checkIndexStatus(path = '.') {
|
|
|
437
592
|
...settingsConfig,
|
|
438
593
|
config_file: configData.config_file,
|
|
439
594
|
index_dir: configData.index_dir,
|
|
440
|
-
embedding_backend: configData.embedding_backend,
|
|
441
|
-
embedding_model: configData.embedding_model,
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
595
|
+
embedding_backend: normalizeEmbeddingBackend(configData.embedding_backend) ?? settingsConfig.embedding_backend,
|
|
596
|
+
embedding_model: typeof configData.embedding_model === 'string' ? configData.embedding_model : settingsConfig.embedding_model,
|
|
597
|
+
embedding_auto_embed_missing: typeof configData.embedding_auto_embed_missing === 'boolean'
|
|
598
|
+
? configData.embedding_auto_embed_missing
|
|
599
|
+
: settingsConfig.embedding_auto_embed_missing,
|
|
600
|
+
reranker_enabled: typeof configData.reranker_enabled === 'boolean' ? configData.reranker_enabled : settingsConfig.reranker_enabled,
|
|
601
|
+
reranker_backend: typeof configData.reranker_backend === 'string' ? configData.reranker_backend : settingsConfig.reranker_backend,
|
|
602
|
+
reranker_model: typeof configData.reranker_model === 'string' ? configData.reranker_model : settingsConfig.reranker_model,
|
|
603
|
+
reranker_top_k: typeof configData.reranker_top_k === 'number' ? configData.reranker_top_k : settingsConfig.reranker_top_k,
|
|
446
604
|
};
|
|
447
605
|
}
|
|
448
606
|
catch {
|
|
@@ -641,6 +799,7 @@ function checkToolAvailability(toolName) {
|
|
|
641
799
|
*/
|
|
642
800
|
function buildRipgrepCommand(params) {
|
|
643
801
|
const { query, paths = ['.'], contextLines = 0, maxResults = 10, includeHidden = false, regex = false, caseSensitive = true, tokenize = true } = params;
|
|
802
|
+
const queryMode = resolveRipgrepQueryMode(query, regex, tokenize);
|
|
644
803
|
const args = [
|
|
645
804
|
'-n',
|
|
646
805
|
'--color=never',
|
|
@@ -663,13 +822,12 @@ function buildRipgrepCommand(params) {
|
|
|
663
822
|
if (includeHidden) {
|
|
664
823
|
args.push('--hidden');
|
|
665
824
|
}
|
|
666
|
-
|
|
667
|
-
const tokens = tokenize ? tokenizeQuery(query) : [query];
|
|
825
|
+
const { tokens } = queryMode;
|
|
668
826
|
if (tokens.length > 1) {
|
|
669
827
|
// Multi-token: use multiple -e patterns (OR matching)
|
|
670
828
|
// Each token is escaped for regex safety unless regex mode is enabled
|
|
671
829
|
for (const token of tokens) {
|
|
672
|
-
if (regex) {
|
|
830
|
+
if (queryMode.regex) {
|
|
673
831
|
args.push('-e', token);
|
|
674
832
|
}
|
|
675
833
|
else {
|
|
@@ -681,7 +839,7 @@ function buildRipgrepCommand(params) {
|
|
|
681
839
|
}
|
|
682
840
|
else {
|
|
683
841
|
// Single token or no tokenization: use original behavior
|
|
684
|
-
if (regex) {
|
|
842
|
+
if (queryMode.regex) {
|
|
685
843
|
args.push('-e', query);
|
|
686
844
|
}
|
|
687
845
|
else {
|
|
@@ -689,7 +847,123 @@ function buildRipgrepCommand(params) {
|
|
|
689
847
|
}
|
|
690
848
|
}
|
|
691
849
|
args.push(...paths);
|
|
692
|
-
return {
|
|
850
|
+
return {
|
|
851
|
+
command: 'rg',
|
|
852
|
+
args,
|
|
853
|
+
tokens,
|
|
854
|
+
warning: queryMode.warning,
|
|
855
|
+
literalFallback: queryMode.literalFallback,
|
|
856
|
+
regex: queryMode.regex,
|
|
857
|
+
};
|
|
858
|
+
}
|
|
859
|
+
function finalizeRipgrepChunk(accumulator) {
|
|
860
|
+
if (!accumulator || accumulator.matchCount === 0 || accumulator.chunkLines.length === 0) {
|
|
861
|
+
return null;
|
|
862
|
+
}
|
|
863
|
+
const firstLine = accumulator.chunkLines[0]?.line ?? accumulator.firstMatchLine ?? 1;
|
|
864
|
+
const lastLine = accumulator.chunkLines[accumulator.chunkLines.length - 1]?.line ?? accumulator.firstMatchLine ?? firstLine;
|
|
865
|
+
return {
|
|
866
|
+
file: accumulator.file,
|
|
867
|
+
line: accumulator.firstMatchLine ?? firstLine,
|
|
868
|
+
endLine: lastLine,
|
|
869
|
+
column: accumulator.firstMatchColumn ?? 1,
|
|
870
|
+
content: accumulator.chunkLines.map((line) => line.text).join('\n').trim(),
|
|
871
|
+
chunkLines: [...accumulator.chunkLines],
|
|
872
|
+
};
|
|
873
|
+
}
|
|
874
|
+
function parseRipgrepJsonResults(stdout, effectiveLimit) {
|
|
875
|
+
const allResults = [];
|
|
876
|
+
const activeChunks = new Map();
|
|
877
|
+
const lines = stdout.split('\n').filter((line) => line.trim());
|
|
878
|
+
let resultLimitReached = false;
|
|
879
|
+
const flushChunk = (file) => {
|
|
880
|
+
const finalized = finalizeRipgrepChunk(activeChunks.get(file));
|
|
881
|
+
activeChunks.delete(file);
|
|
882
|
+
if (!finalized) {
|
|
883
|
+
return;
|
|
884
|
+
}
|
|
885
|
+
allResults.push(finalized);
|
|
886
|
+
if (allResults.length >= effectiveLimit) {
|
|
887
|
+
resultLimitReached = true;
|
|
888
|
+
}
|
|
889
|
+
};
|
|
890
|
+
for (const line of lines) {
|
|
891
|
+
if (resultLimitReached) {
|
|
892
|
+
break;
|
|
893
|
+
}
|
|
894
|
+
try {
|
|
895
|
+
const item = JSON.parse(line);
|
|
896
|
+
if (item.type !== 'match' && item.type !== 'context' && item.type !== 'end') {
|
|
897
|
+
continue;
|
|
898
|
+
}
|
|
899
|
+
const file = item.data?.path?.text;
|
|
900
|
+
if (!file) {
|
|
901
|
+
continue;
|
|
902
|
+
}
|
|
903
|
+
if (item.type === 'end') {
|
|
904
|
+
flushChunk(file);
|
|
905
|
+
continue;
|
|
906
|
+
}
|
|
907
|
+
const lineNumber = typeof item.data?.line_number === 'number' ? item.data.line_number : undefined;
|
|
908
|
+
const rawText = typeof item.data?.lines?.text === 'string'
|
|
909
|
+
? item.data.lines.text.replace(/\r?\n$/, '')
|
|
910
|
+
: '';
|
|
911
|
+
if (lineNumber === undefined) {
|
|
912
|
+
continue;
|
|
913
|
+
}
|
|
914
|
+
let current = activeChunks.get(file);
|
|
915
|
+
const isContiguous = current && current.lastLine !== undefined && lineNumber <= current.lastLine + 1;
|
|
916
|
+
if (!current || !isContiguous) {
|
|
917
|
+
if (current) {
|
|
918
|
+
flushChunk(file);
|
|
919
|
+
if (resultLimitReached) {
|
|
920
|
+
break;
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
current = {
|
|
924
|
+
file,
|
|
925
|
+
chunkLines: [],
|
|
926
|
+
matchCount: 0,
|
|
927
|
+
};
|
|
928
|
+
activeChunks.set(file, current);
|
|
929
|
+
}
|
|
930
|
+
const previousLine = current.chunkLines[current.chunkLines.length - 1];
|
|
931
|
+
const duplicateLine = previousLine && previousLine.line === lineNumber && previousLine.text === rawText;
|
|
932
|
+
if (!duplicateLine) {
|
|
933
|
+
current.chunkLines.push({
|
|
934
|
+
line: lineNumber,
|
|
935
|
+
text: rawText,
|
|
936
|
+
isMatch: item.type === 'match',
|
|
937
|
+
});
|
|
938
|
+
}
|
|
939
|
+
else if (item.type === 'match') {
|
|
940
|
+
previousLine.isMatch = true;
|
|
941
|
+
}
|
|
942
|
+
if (item.type === 'match') {
|
|
943
|
+
current.matchCount += 1;
|
|
944
|
+
if (current.firstMatchLine === undefined) {
|
|
945
|
+
current.firstMatchLine = lineNumber;
|
|
946
|
+
current.firstMatchColumn =
|
|
947
|
+
item.data.submatches && item.data.submatches[0]
|
|
948
|
+
? item.data.submatches[0].start + 1
|
|
949
|
+
: 1;
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
current.lastLine = lineNumber;
|
|
953
|
+
}
|
|
954
|
+
catch {
|
|
955
|
+
continue;
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
if (!resultLimitReached) {
|
|
959
|
+
for (const file of [...activeChunks.keys()]) {
|
|
960
|
+
flushChunk(file);
|
|
961
|
+
if (resultLimitReached) {
|
|
962
|
+
break;
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
return { results: allResults.slice(0, effectiveLimit), resultLimitReached };
|
|
693
967
|
}
|
|
694
968
|
function normalizeEmbeddingBackend(backend) {
|
|
695
969
|
if (!backend) {
|
|
@@ -774,50 +1048,63 @@ function extractEmbedJsonLine(stdout) {
|
|
|
774
1048
|
.filter((line) => !line.startsWith(EMBED_PROGRESS_PREFIX));
|
|
775
1049
|
return [...lines].reverse().find((line) => line.startsWith('{') && line.endsWith('}'));
|
|
776
1050
|
}
|
|
777
|
-
|
|
1051
|
+
function buildEmbeddingPythonCode(params) {
|
|
778
1052
|
const { projectPath, backend, model, force, maxWorkers, endpoints = [] } = params;
|
|
779
|
-
|
|
780
|
-
import json
|
|
781
|
-
import sys
|
|
782
|
-
from pathlib import Path
|
|
783
|
-
from codexlens.storage.
|
|
784
|
-
from codexlens.
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
registry
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
1053
|
+
return `
|
|
1054
|
+
import json
|
|
1055
|
+
import sys
|
|
1056
|
+
from pathlib import Path
|
|
1057
|
+
from codexlens.storage.path_mapper import PathMapper
|
|
1058
|
+
from codexlens.storage.registry import RegistryStore
|
|
1059
|
+
from codexlens.cli.embedding_manager import generate_dense_embeddings_centralized
|
|
1060
|
+
|
|
1061
|
+
target_path = Path(r"__PROJECT_PATH__").expanduser().resolve()
|
|
1062
|
+
backend = __BACKEND__
|
|
1063
|
+
model = __MODEL__
|
|
1064
|
+
force = __FORCE__
|
|
1065
|
+
max_workers = __MAX_WORKERS__
|
|
1066
|
+
endpoints = json.loads(r'''__ENDPOINTS_JSON__''')
|
|
1067
|
+
|
|
1068
|
+
def progress_update(message: str):
|
|
1069
|
+
print("__CCW_EMBED_PROGRESS__" + str(message), flush=True)
|
|
1070
|
+
|
|
1071
|
+
registry = RegistryStore()
|
|
1072
|
+
registry.initialize()
|
|
1073
|
+
try:
|
|
1074
|
+
project = registry.get_project(target_path)
|
|
1075
|
+
index_root = None
|
|
1076
|
+
if project is not None:
|
|
1077
|
+
index_root = Path(project.index_root)
|
|
1078
|
+
else:
|
|
1079
|
+
mapper = PathMapper()
|
|
1080
|
+
index_db = mapper.source_to_index_db(target_path)
|
|
1081
|
+
if index_db.exists():
|
|
1082
|
+
index_root = index_db.parent
|
|
1083
|
+
else:
|
|
1084
|
+
nearest = registry.find_nearest_index(target_path)
|
|
1085
|
+
if nearest is not None:
|
|
1086
|
+
index_root = Path(nearest.index_path).parent
|
|
1087
|
+
|
|
1088
|
+
if index_root is None:
|
|
1089
|
+
print(json.dumps({"success": False, "error": f"No index found for: {target_path}"}), flush=True)
|
|
1090
|
+
sys.exit(1)
|
|
1091
|
+
|
|
1092
|
+
result = generate_dense_embeddings_centralized(
|
|
1093
|
+
index_root,
|
|
1094
|
+
embedding_backend=backend,
|
|
1095
|
+
model_profile=model,
|
|
1096
|
+
force=force,
|
|
1097
|
+
use_gpu=True,
|
|
1098
|
+
max_workers=max_workers,
|
|
1099
|
+
endpoints=endpoints if endpoints else None,
|
|
1100
|
+
progress_callback=progress_update,
|
|
1101
|
+
)
|
|
1102
|
+
|
|
1103
|
+
print(json.dumps(result), flush=True)
|
|
1104
|
+
if not result.get("success"):
|
|
1105
|
+
sys.exit(1)
|
|
1106
|
+
finally:
|
|
1107
|
+
registry.close()
|
|
821
1108
|
`
|
|
822
1109
|
.replace('__PROJECT_PATH__', projectPath.replace(/\\/g, '\\\\'))
|
|
823
1110
|
.replace('__BACKEND__', backend ? JSON.stringify(backend) : 'None')
|
|
@@ -825,6 +1112,90 @@ finally:
|
|
|
825
1112
|
.replace('__FORCE__', force ? 'True' : 'False')
|
|
826
1113
|
.replace('__MAX_WORKERS__', typeof maxWorkers === 'number' ? String(Math.max(1, Math.floor(maxWorkers))) : 'None')
|
|
827
1114
|
.replace('__ENDPOINTS_JSON__', JSON.stringify(endpoints).replace(/\\/g, '\\\\').replace(/'''/g, "\\'\\'\\'"));
|
|
1115
|
+
}
|
|
1116
|
+
function spawnBackgroundEmbeddingsViaPython(params) {
|
|
1117
|
+
const { projectPath, backend, model } = params;
|
|
1118
|
+
try {
|
|
1119
|
+
const child = spawn(getVenvPythonPath(), ['-c', buildEmbeddingPythonCode(params)], {
|
|
1120
|
+
cwd: projectPath,
|
|
1121
|
+
shell: false,
|
|
1122
|
+
detached: true,
|
|
1123
|
+
stdio: 'ignore',
|
|
1124
|
+
windowsHide: true,
|
|
1125
|
+
env: { ...process.env, PYTHONIOENCODING: 'utf-8' },
|
|
1126
|
+
});
|
|
1127
|
+
autoEmbedJobs.set(projectPath, {
|
|
1128
|
+
startedAt: Date.now(),
|
|
1129
|
+
backend,
|
|
1130
|
+
model,
|
|
1131
|
+
});
|
|
1132
|
+
const cleanup = () => {
|
|
1133
|
+
autoEmbedJobs.delete(projectPath);
|
|
1134
|
+
};
|
|
1135
|
+
child.on('error', cleanup);
|
|
1136
|
+
child.on('close', cleanup);
|
|
1137
|
+
child.unref();
|
|
1138
|
+
return { success: true };
|
|
1139
|
+
}
|
|
1140
|
+
catch (error) {
|
|
1141
|
+
return {
|
|
1142
|
+
success: false,
|
|
1143
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1144
|
+
};
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
async function maybeStartBackgroundAutoEmbed(scope, indexStatus) {
|
|
1148
|
+
if (!indexStatus.indexed || indexStatus.has_embeddings) {
|
|
1149
|
+
return {};
|
|
1150
|
+
}
|
|
1151
|
+
if (!isAutoEmbedMissingEnabled(indexStatus.config)) {
|
|
1152
|
+
return {
|
|
1153
|
+
note: 'Automatic embedding warmup is disabled by CODEXLENS_AUTO_EMBED_MISSING=false.',
|
|
1154
|
+
};
|
|
1155
|
+
}
|
|
1156
|
+
if (autoEmbedJobs.has(scope.workingDirectory)) {
|
|
1157
|
+
return {
|
|
1158
|
+
note: 'Background embedding build is already running for this path.',
|
|
1159
|
+
};
|
|
1160
|
+
}
|
|
1161
|
+
const backend = normalizeEmbeddingBackend(indexStatus.config?.embedding_backend) ?? 'fastembed';
|
|
1162
|
+
const model = indexStatus.config?.embedding_model?.trim() || undefined;
|
|
1163
|
+
const semanticStatus = await checkSemanticStatus();
|
|
1164
|
+
if (!semanticStatus.available) {
|
|
1165
|
+
return {
|
|
1166
|
+
warning: 'Automatic embedding warmup skipped because semantic dependencies are not ready.',
|
|
1167
|
+
};
|
|
1168
|
+
}
|
|
1169
|
+
if (backend === 'litellm' && !semanticStatus.litellmAvailable) {
|
|
1170
|
+
return {
|
|
1171
|
+
warning: 'Automatic embedding warmup skipped because the LiteLLM embedder is not ready.',
|
|
1172
|
+
};
|
|
1173
|
+
}
|
|
1174
|
+
const endpoints = resolveEmbeddingEndpoints(backend);
|
|
1175
|
+
const configuredApiMaxWorkers = indexStatus.config?.api_max_workers;
|
|
1176
|
+
const effectiveApiMaxWorkers = typeof configuredApiMaxWorkers === 'number'
|
|
1177
|
+
? Math.max(1, Math.floor(configuredApiMaxWorkers))
|
|
1178
|
+
: resolveApiWorkerCount(undefined, backend, endpoints);
|
|
1179
|
+
const spawned = spawnBackgroundEmbeddingsViaPython({
|
|
1180
|
+
projectPath: scope.workingDirectory,
|
|
1181
|
+
backend,
|
|
1182
|
+
model,
|
|
1183
|
+
force: false,
|
|
1184
|
+
maxWorkers: effectiveApiMaxWorkers,
|
|
1185
|
+
endpoints,
|
|
1186
|
+
});
|
|
1187
|
+
if (!spawned.success) {
|
|
1188
|
+
return {
|
|
1189
|
+
warning: `Automatic embedding warmup could not start: ${spawned.error}`,
|
|
1190
|
+
};
|
|
1191
|
+
}
|
|
1192
|
+
return {
|
|
1193
|
+
note: 'Background embedding build started for this path. Re-run semantic search shortly for vector results.',
|
|
1194
|
+
};
|
|
1195
|
+
}
|
|
1196
|
+
async function executeEmbeddingsViaPython(params) {
|
|
1197
|
+
const { projectPath } = params;
|
|
1198
|
+
const pythonCode = buildEmbeddingPythonCode(params);
|
|
828
1199
|
return await new Promise((resolve) => {
|
|
829
1200
|
const child = spawn(getVenvPythonPath(), ['-c', pythonCode], {
|
|
830
1201
|
cwd: projectPath,
|
|
@@ -1040,6 +1411,7 @@ async function executeStatusAction(params) {
|
|
|
1040
1411
|
// Embedding backend info
|
|
1041
1412
|
const embeddingType = cfg.embedding_backend === 'litellm' ? 'API' : 'Local';
|
|
1042
1413
|
statusParts.push(`Embedding: ${embeddingType} (${cfg.embedding_model || 'default'})`);
|
|
1414
|
+
statusParts.push(`Auto Embed Missing: ${isAutoEmbedMissingEnabled(cfg) ? 'on' : 'off'}`);
|
|
1043
1415
|
if (typeof cfg.api_max_workers === 'number') {
|
|
1044
1416
|
statusParts.push(`API Workers: ${cfg.api_max_workers}`);
|
|
1045
1417
|
}
|
|
@@ -1062,6 +1434,12 @@ async function executeStatusAction(params) {
|
|
|
1062
1434
|
success: true,
|
|
1063
1435
|
status: indexStatus,
|
|
1064
1436
|
message: indexStatus.warning || statusParts.join(' | '),
|
|
1437
|
+
metadata: {
|
|
1438
|
+
action: 'status',
|
|
1439
|
+
path: scope.workingDirectory,
|
|
1440
|
+
warning: indexStatus.warning,
|
|
1441
|
+
suggestions: buildIndexSuggestions(indexStatus, scope),
|
|
1442
|
+
},
|
|
1065
1443
|
};
|
|
1066
1444
|
}
|
|
1067
1445
|
/**
|
|
@@ -1180,7 +1558,7 @@ async function executeWatchAction(params) {
|
|
|
1180
1558
|
* Runs both exact (FTS) and ripgrep searches in parallel, merges and ranks results
|
|
1181
1559
|
*/
|
|
1182
1560
|
async function executeFuzzyMode(params) {
|
|
1183
|
-
const { query, path = '.', maxResults = 5, extraFilesCount = 10, codeOnly = true, withDoc = false, excludeExtensions } = params;
|
|
1561
|
+
const { query, path = '.', maxResults = 5, extraFilesCount = 10, codeOnly = true, withDoc = false, excludeExtensions, regex = true, tokenize = true } = params;
|
|
1184
1562
|
// withDoc overrides codeOnly
|
|
1185
1563
|
const effectiveCodeOnly = withDoc ? false : codeOnly;
|
|
1186
1564
|
if (!query) {
|
|
@@ -1190,12 +1568,34 @@ async function executeFuzzyMode(params) {
|
|
|
1190
1568
|
};
|
|
1191
1569
|
}
|
|
1192
1570
|
const timer = createTimer();
|
|
1571
|
+
const ftsWasBroken = codexLensFtsBackendBroken;
|
|
1572
|
+
const ripgrepQueryMode = resolveRipgrepQueryMode(query, regex, tokenize);
|
|
1573
|
+
const fuzzyWarnings = [];
|
|
1574
|
+
let skipExactReason;
|
|
1575
|
+
if (ripgrepQueryMode.literalFallback) {
|
|
1576
|
+
skipExactReason = 'Skipped CodexLens FTS backend for a literal code-pattern query; using ripgrep literal matching.';
|
|
1577
|
+
}
|
|
1578
|
+
else if (codexLensFtsBackendBroken) {
|
|
1579
|
+
skipExactReason = 'CodexLens FTS backend disabled for this process due to CLI compatibility errors.';
|
|
1580
|
+
}
|
|
1193
1581
|
// Run both searches in parallel
|
|
1194
1582
|
const [ftsResult, ripgrepResult] = await Promise.allSettled([
|
|
1195
|
-
|
|
1583
|
+
skipExactReason
|
|
1584
|
+
? Promise.resolve({ success: false, error: skipExactReason })
|
|
1585
|
+
: executeCodexLensExactMode(params),
|
|
1196
1586
|
executeRipgrepMode(params),
|
|
1197
1587
|
]);
|
|
1198
1588
|
timer.mark('parallel_search');
|
|
1589
|
+
if (!skipExactReason && !ftsWasBroken && codexLensFtsBackendBroken) {
|
|
1590
|
+
fuzzyWarnings.push('CodexLens FTS backend is incompatible with the current CLI runtime. Falling back to ripgrep results.');
|
|
1591
|
+
}
|
|
1592
|
+
if (skipExactReason) {
|
|
1593
|
+
fuzzyWarnings.push(skipExactReason);
|
|
1594
|
+
}
|
|
1595
|
+
if (ripgrepResult.status === 'fulfilled' && ripgrepResult.value.metadata?.warning) {
|
|
1596
|
+
fuzzyWarnings.push(String(ripgrepResult.value.metadata.warning));
|
|
1597
|
+
}
|
|
1598
|
+
const mergedSuggestions = mergeSuggestions(ftsResult.status === 'fulfilled' ? ftsResult.value.metadata?.suggestions : undefined, ripgrepResult.status === 'fulfilled' ? ripgrepResult.value.metadata?.suggestions : undefined);
|
|
1199
1599
|
// Collect results from both sources
|
|
1200
1600
|
const resultsMap = new Map();
|
|
1201
1601
|
// Add FTS results if successful
|
|
@@ -1228,8 +1628,10 @@ async function executeFuzzyMode(params) {
|
|
|
1228
1628
|
const normalizedResults = filteredFusedResults.map((item) => ({
|
|
1229
1629
|
file: item.file || item.path,
|
|
1230
1630
|
line: item.line || 0,
|
|
1631
|
+
endLine: item.endLine || item.line || 0,
|
|
1231
1632
|
column: item.column || 0,
|
|
1232
1633
|
content: item.content || '',
|
|
1634
|
+
chunkLines: Array.isArray(item.chunkLines) ? item.chunkLines : undefined,
|
|
1233
1635
|
score: item.fusion_score || 0,
|
|
1234
1636
|
matchCount: item.matchCount,
|
|
1235
1637
|
matchScore: item.matchScore,
|
|
@@ -1239,16 +1641,21 @@ async function executeFuzzyMode(params) {
|
|
|
1239
1641
|
// Log timing
|
|
1240
1642
|
timer.log();
|
|
1241
1643
|
const timings = timer.getTimings();
|
|
1644
|
+
const usingExactResults = resultsMap.has('exact');
|
|
1242
1645
|
return {
|
|
1243
1646
|
success: true,
|
|
1244
1647
|
results,
|
|
1245
1648
|
extra_files: extra_files.length > 0 ? extra_files : undefined,
|
|
1246
1649
|
metadata: {
|
|
1247
1650
|
mode: 'fuzzy',
|
|
1248
|
-
backend: 'fts+ripgrep',
|
|
1651
|
+
backend: usingExactResults ? 'fts+ripgrep' : 'ripgrep',
|
|
1249
1652
|
count: results.length,
|
|
1250
1653
|
query,
|
|
1251
|
-
note:
|
|
1654
|
+
note: usingExactResults
|
|
1655
|
+
? `Fuzzy search using RRF fusion of FTS and ripgrep (weights: exact=${fusionWeights.exact}, ripgrep=${fusionWeights.ripgrep})`
|
|
1656
|
+
: 'Fuzzy search resolved using ripgrep only.',
|
|
1657
|
+
warning: mergeWarnings(...fuzzyWarnings),
|
|
1658
|
+
suggestions: mergedSuggestions,
|
|
1252
1659
|
timing: TIMING_ENABLED ? timings : undefined,
|
|
1253
1660
|
},
|
|
1254
1661
|
};
|
|
@@ -1289,19 +1696,10 @@ async function executeAutoMode(params) {
|
|
|
1289
1696
|
break;
|
|
1290
1697
|
}
|
|
1291
1698
|
// Add classification metadata
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
result.metadata.embeddings_coverage_percent = indexStatus.embeddings_coverage_percent;
|
|
1297
|
-
result.metadata.index_status = indexStatus.indexed
|
|
1298
|
-
? (indexStatus.has_embeddings ? 'indexed' : 'partial')
|
|
1299
|
-
: 'not_indexed';
|
|
1300
|
-
// Add warning if needed
|
|
1301
|
-
if (indexStatus.warning) {
|
|
1302
|
-
result.metadata.warning = indexStatus.warning;
|
|
1303
|
-
}
|
|
1304
|
-
}
|
|
1699
|
+
result.metadata = enrichMetadataWithIndexStatus(result.metadata, indexStatus, scope);
|
|
1700
|
+
result.metadata.classified_as = classification.mode;
|
|
1701
|
+
result.metadata.confidence = classification.confidence;
|
|
1702
|
+
result.metadata.reasoning = classification.reasoning;
|
|
1305
1703
|
return result;
|
|
1306
1704
|
}
|
|
1307
1705
|
/**
|
|
@@ -1337,9 +1735,10 @@ async function executeRipgrepMode(params) {
|
|
|
1337
1735
|
const args = ['search', query, '--limit', totalToFetch.toString(), '--method', 'fts', '--json'];
|
|
1338
1736
|
const result = await executeCodexLens(args, { cwd: scope.workingDirectory });
|
|
1339
1737
|
if (!result.success) {
|
|
1738
|
+
noteCodexLensFtsCompatibility(result.error);
|
|
1340
1739
|
return {
|
|
1341
1740
|
success: false,
|
|
1342
|
-
error: result.error,
|
|
1741
|
+
error: summarizeBackendError(result.error),
|
|
1343
1742
|
metadata: {
|
|
1344
1743
|
mode: 'ripgrep',
|
|
1345
1744
|
backend: 'codexlens-fallback',
|
|
@@ -1380,7 +1779,7 @@ async function executeRipgrepMode(params) {
|
|
|
1380
1779
|
};
|
|
1381
1780
|
}
|
|
1382
1781
|
// Use ripgrep - request more results to support split
|
|
1383
|
-
const { command, args, tokens } = buildRipgrepCommand({
|
|
1782
|
+
const { command, args, tokens, warning: queryModeWarning } = buildRipgrepCommand({
|
|
1384
1783
|
query,
|
|
1385
1784
|
paths: scope.searchPaths,
|
|
1386
1785
|
contextLines,
|
|
@@ -1405,34 +1804,11 @@ async function executeRipgrepMode(params) {
|
|
|
1405
1804
|
stderr += data.toString();
|
|
1406
1805
|
});
|
|
1407
1806
|
child.on('close', (code) => {
|
|
1408
|
-
const allResults = [];
|
|
1409
|
-
const lines = stdout.split('\n').filter((line) => line.trim());
|
|
1410
1807
|
// Limit total results to prevent memory overflow (--max-count only limits per-file)
|
|
1411
1808
|
const effectiveLimit = totalToFetch > 0 ? totalToFetch : 500;
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
resultLimitReached = true;
|
|
1416
|
-
break;
|
|
1417
|
-
}
|
|
1418
|
-
try {
|
|
1419
|
-
const item = JSON.parse(line);
|
|
1420
|
-
if (item.type === 'match') {
|
|
1421
|
-
const match = {
|
|
1422
|
-
file: item.data.path.text,
|
|
1423
|
-
line: item.data.line_number,
|
|
1424
|
-
column: item.data.submatches && item.data.submatches[0]
|
|
1425
|
-
? item.data.submatches[0].start + 1
|
|
1426
|
-
: 1,
|
|
1427
|
-
content: item.data.lines.text.trim(),
|
|
1428
|
-
};
|
|
1429
|
-
allResults.push(match);
|
|
1430
|
-
}
|
|
1431
|
-
}
|
|
1432
|
-
catch {
|
|
1433
|
-
continue;
|
|
1434
|
-
}
|
|
1435
|
-
}
|
|
1809
|
+
const parsedResults = parseRipgrepJsonResults(stdout, effectiveLimit);
|
|
1810
|
+
const allResults = parsedResults.results;
|
|
1811
|
+
resultLimitReached = parsedResults.resultLimitReached;
|
|
1436
1812
|
// Handle Windows device file errors gracefully (os error 1)
|
|
1437
1813
|
// If we have results despite the error, return them as partial success
|
|
1438
1814
|
const isWindowsDeviceError = stderr.includes('os error 1') || stderr.includes('函数不正确');
|
|
@@ -1446,6 +1822,9 @@ async function executeRipgrepMode(params) {
|
|
|
1446
1822
|
const { results, extra_files } = splitResultsWithExtraFiles(filteredResults, maxResults, extraFilesCount);
|
|
1447
1823
|
// Build warning message for various conditions
|
|
1448
1824
|
const warnings = [];
|
|
1825
|
+
if (queryModeWarning) {
|
|
1826
|
+
warnings.push(queryModeWarning);
|
|
1827
|
+
}
|
|
1449
1828
|
if (resultLimitReached) {
|
|
1450
1829
|
warnings.push(`Result limit reached (${effectiveLimit}). Use a more specific query or increase limit.`);
|
|
1451
1830
|
}
|
|
@@ -1539,15 +1918,17 @@ async function executeCodexLensExactMode(params) {
|
|
|
1539
1918
|
}
|
|
1540
1919
|
const result = await executeCodexLens(args, { cwd: scope.workingDirectory });
|
|
1541
1920
|
if (!result.success) {
|
|
1921
|
+
noteCodexLensFtsCompatibility(result.error);
|
|
1542
1922
|
return {
|
|
1543
1923
|
success: false,
|
|
1544
|
-
error: result.error,
|
|
1924
|
+
error: summarizeBackendError(result.error),
|
|
1545
1925
|
metadata: {
|
|
1546
1926
|
mode: 'exact',
|
|
1547
1927
|
backend: 'codexlens',
|
|
1548
1928
|
count: 0,
|
|
1549
1929
|
query,
|
|
1550
1930
|
warning: mergeWarnings(indexStatus.warning, result.warning),
|
|
1931
|
+
suggestions: buildIndexSuggestions(indexStatus, scope),
|
|
1551
1932
|
},
|
|
1552
1933
|
};
|
|
1553
1934
|
}
|
|
@@ -1611,6 +1992,7 @@ async function executeCodexLensExactMode(params) {
|
|
|
1611
1992
|
warning: mergeWarnings(indexStatus.warning, fuzzyResult.warning),
|
|
1612
1993
|
note: 'No exact matches found, showing fuzzy results',
|
|
1613
1994
|
fallback: 'fuzzy',
|
|
1995
|
+
suggestions: buildIndexSuggestions(indexStatus, scope),
|
|
1614
1996
|
},
|
|
1615
1997
|
};
|
|
1616
1998
|
}
|
|
@@ -1628,6 +2010,7 @@ async function executeCodexLensExactMode(params) {
|
|
|
1628
2010
|
count: results.length,
|
|
1629
2011
|
query,
|
|
1630
2012
|
warning: mergeWarnings(indexStatus.warning, result.warning),
|
|
2013
|
+
suggestions: buildIndexSuggestions(indexStatus, scope),
|
|
1631
2014
|
},
|
|
1632
2015
|
};
|
|
1633
2016
|
}
|
|
@@ -1690,6 +2073,7 @@ async function executeHybridMode(params) {
|
|
|
1690
2073
|
count: 0,
|
|
1691
2074
|
query,
|
|
1692
2075
|
warning: mergeWarnings(indexStatus.warning, result.warning),
|
|
2076
|
+
suggestions: buildIndexSuggestions(indexStatus, scope),
|
|
1693
2077
|
},
|
|
1694
2078
|
};
|
|
1695
2079
|
}
|
|
@@ -1732,6 +2116,7 @@ async function executeHybridMode(params) {
|
|
|
1732
2116
|
count: 0,
|
|
1733
2117
|
query,
|
|
1734
2118
|
warning: mergeWarnings(indexStatus.warning, result.warning, 'Failed to parse JSON output'),
|
|
2119
|
+
suggestions: buildIndexSuggestions(indexStatus, scope),
|
|
1735
2120
|
},
|
|
1736
2121
|
};
|
|
1737
2122
|
}
|
|
@@ -1760,6 +2145,7 @@ async function executeHybridMode(params) {
|
|
|
1760
2145
|
query,
|
|
1761
2146
|
note,
|
|
1762
2147
|
warning: mergeWarnings(indexStatus.warning, result.warning),
|
|
2148
|
+
suggestions: buildIndexSuggestions(indexStatus, scope),
|
|
1763
2149
|
suggested_weights: getRRFWeights(query),
|
|
1764
2150
|
timing: TIMING_ENABLED ? timings : undefined,
|
|
1765
2151
|
},
|
|
@@ -1986,30 +2372,100 @@ function filterDominantBaselineScores(results) {
|
|
|
1986
2372
|
* Reference: codex-lens/src/codexlens/search/ranking.py
|
|
1987
2373
|
* Formula: score(d) = Σ weight_source / (k + rank_source(d))
|
|
1988
2374
|
*/
|
|
2375
|
+
function normalizeFusionSnippet(value) {
|
|
2376
|
+
if (typeof value !== 'string') {
|
|
2377
|
+
return undefined;
|
|
2378
|
+
}
|
|
2379
|
+
const normalized = value.replace(/\s+/g, ' ').trim();
|
|
2380
|
+
return normalized ? normalized.slice(0, 240) : undefined;
|
|
2381
|
+
}
|
|
2382
|
+
function buildFusionIdentity(result) {
|
|
2383
|
+
const path = typeof result?.file === 'string'
|
|
2384
|
+
? result.file
|
|
2385
|
+
: typeof result?.path === 'string'
|
|
2386
|
+
? result.path
|
|
2387
|
+
: undefined;
|
|
2388
|
+
if (!path) {
|
|
2389
|
+
return null;
|
|
2390
|
+
}
|
|
2391
|
+
const line = typeof result?.line === 'number' && Number.isFinite(result.line)
|
|
2392
|
+
? result.line
|
|
2393
|
+
: undefined;
|
|
2394
|
+
const endLine = typeof result?.endLine === 'number' && Number.isFinite(result.endLine)
|
|
2395
|
+
? result.endLine
|
|
2396
|
+
: line;
|
|
2397
|
+
const column = typeof result?.column === 'number' && Number.isFinite(result.column)
|
|
2398
|
+
? result.column
|
|
2399
|
+
: undefined;
|
|
2400
|
+
if (line !== undefined) {
|
|
2401
|
+
return `${path}#L${line}-${endLine ?? line}:C${column ?? 0}`;
|
|
2402
|
+
}
|
|
2403
|
+
const symbol = typeof result?.symbol === 'string' && result.symbol.trim()
|
|
2404
|
+
? result.symbol.trim()
|
|
2405
|
+
: undefined;
|
|
2406
|
+
const snippet = normalizeFusionSnippet(result?.content);
|
|
2407
|
+
if (symbol && snippet) {
|
|
2408
|
+
return `${path}::${symbol}::${snippet}`;
|
|
2409
|
+
}
|
|
2410
|
+
if (snippet) {
|
|
2411
|
+
return `${path}::${snippet}`;
|
|
2412
|
+
}
|
|
2413
|
+
if (symbol) {
|
|
2414
|
+
return `${path}::${symbol}`;
|
|
2415
|
+
}
|
|
2416
|
+
return path;
|
|
2417
|
+
}
|
|
2418
|
+
function scoreFusionRepresentative(result) {
|
|
2419
|
+
let score = 0;
|
|
2420
|
+
if (typeof result?.line === 'number' && Number.isFinite(result.line)) {
|
|
2421
|
+
score += 1000;
|
|
2422
|
+
}
|
|
2423
|
+
if (typeof result?.endLine === 'number' && Number.isFinite(result.endLine)) {
|
|
2424
|
+
score += 250;
|
|
2425
|
+
}
|
|
2426
|
+
if (typeof result?.column === 'number' && Number.isFinite(result.column)) {
|
|
2427
|
+
score += 50;
|
|
2428
|
+
}
|
|
2429
|
+
if (Array.isArray(result?.chunkLines) && result.chunkLines.length > 0) {
|
|
2430
|
+
score += 500 + result.chunkLines.length;
|
|
2431
|
+
}
|
|
2432
|
+
if (typeof result?.symbol === 'string' && result.symbol.trim()) {
|
|
2433
|
+
score += 50;
|
|
2434
|
+
}
|
|
2435
|
+
if (typeof result?.content === 'string') {
|
|
2436
|
+
score += Math.min(result.content.length, 200);
|
|
2437
|
+
}
|
|
2438
|
+
return score;
|
|
2439
|
+
}
|
|
1989
2440
|
function applyRRFFusion(resultsMap, weightsOrQuery, limit, k = 60) {
|
|
1990
2441
|
const weights = typeof weightsOrQuery === 'string' ? getRRFWeights(weightsOrQuery) : weightsOrQuery;
|
|
1991
|
-
const
|
|
2442
|
+
const fusedScores = new Map();
|
|
1992
2443
|
resultsMap.forEach((results, source) => {
|
|
1993
2444
|
const weight = weights[source] || 0;
|
|
1994
2445
|
if (weight === 0 || !results)
|
|
1995
2446
|
return;
|
|
1996
2447
|
results.forEach((result, rank) => {
|
|
1997
|
-
const
|
|
1998
|
-
if (!
|
|
2448
|
+
const identity = buildFusionIdentity(result);
|
|
2449
|
+
if (!identity)
|
|
1999
2450
|
return;
|
|
2000
2451
|
const rrfContribution = weight / (k + rank + 1);
|
|
2001
|
-
|
|
2002
|
-
|
|
2452
|
+
const representativeScore = scoreFusionRepresentative(result);
|
|
2453
|
+
if (!fusedScores.has(identity)) {
|
|
2454
|
+
fusedScores.set(identity, { score: 0, result, sources: [], representativeScore });
|
|
2003
2455
|
}
|
|
2004
|
-
const entry =
|
|
2456
|
+
const entry = fusedScores.get(identity);
|
|
2005
2457
|
entry.score += rrfContribution;
|
|
2458
|
+
if (representativeScore > entry.representativeScore) {
|
|
2459
|
+
entry.result = result;
|
|
2460
|
+
entry.representativeScore = representativeScore;
|
|
2461
|
+
}
|
|
2006
2462
|
if (!entry.sources.includes(source)) {
|
|
2007
2463
|
entry.sources.push(source);
|
|
2008
2464
|
}
|
|
2009
2465
|
});
|
|
2010
2466
|
});
|
|
2011
2467
|
// Sort by fusion score descending
|
|
2012
|
-
return Array.from(
|
|
2468
|
+
return Array.from(fusedScores.values())
|
|
2013
2469
|
.sort((a, b) => b.score - a.score)
|
|
2014
2470
|
.slice(0, limit)
|
|
2015
2471
|
.map(item => ({
|
|
@@ -2206,9 +2662,9 @@ Recommended MCP flow: use **action=\"search\"** for lookups, **action=\"init\"**
|
|
|
2206
2662
|
},
|
|
2207
2663
|
output_mode: {
|
|
2208
2664
|
type: 'string',
|
|
2209
|
-
enum: [
|
|
2210
|
-
description: 'Output format:
|
|
2211
|
-
default: '
|
|
2665
|
+
enum: [...SEARCH_OUTPUT_MODES],
|
|
2666
|
+
description: 'Output format: ace (default, ACE-style grouped code sections + rendered text), full (raw matches), files_only (paths only), count (per-file counts)',
|
|
2667
|
+
default: 'ace',
|
|
2212
2668
|
},
|
|
2213
2669
|
path: {
|
|
2214
2670
|
type: 'string',
|
|
@@ -2540,6 +2996,108 @@ function applyPagination(results, offset, limit) {
|
|
|
2540
2996
|
},
|
|
2541
2997
|
};
|
|
2542
2998
|
}
|
|
2999
|
+
function formatChunkRange(section) {
|
|
3000
|
+
if (section.lines && section.lines.length > 0) {
|
|
3001
|
+
const start = section.lines[0]?.line;
|
|
3002
|
+
const end = section.lines[section.lines.length - 1]?.line;
|
|
3003
|
+
if (typeof start === 'number' && typeof end === 'number' && end > start) {
|
|
3004
|
+
return `${start}-${end}`;
|
|
3005
|
+
}
|
|
3006
|
+
if (typeof start === 'number') {
|
|
3007
|
+
return String(start);
|
|
3008
|
+
}
|
|
3009
|
+
}
|
|
3010
|
+
if (section.line && section.endLine && section.endLine > section.line) {
|
|
3011
|
+
return `${section.line}-${section.endLine}`;
|
|
3012
|
+
}
|
|
3013
|
+
if (section.line) {
|
|
3014
|
+
return String(section.line);
|
|
3015
|
+
}
|
|
3016
|
+
return '?';
|
|
3017
|
+
}
|
|
3018
|
+
function renderAceSnippet(section) {
|
|
3019
|
+
if (section.lines && section.lines.length > 0) {
|
|
3020
|
+
return section.lines.map((line) => {
|
|
3021
|
+
const marker = line.isMatch ? '>' : ' ';
|
|
3022
|
+
return `${marker} ${String(line.line).padStart(4, ' ')} | ${line.text}`;
|
|
3023
|
+
});
|
|
3024
|
+
}
|
|
3025
|
+
return section.snippet.split(/\r?\n/).map((line) => ` ${line}`);
|
|
3026
|
+
}
|
|
3027
|
+
function formatAceLikeOutput(results) {
|
|
3028
|
+
const sections = [];
|
|
3029
|
+
for (const result of results) {
|
|
3030
|
+
const candidate = result;
|
|
3031
|
+
const path = typeof candidate.file === 'string'
|
|
3032
|
+
? candidate.file
|
|
3033
|
+
: typeof candidate.path === 'string'
|
|
3034
|
+
? candidate.path
|
|
3035
|
+
: undefined;
|
|
3036
|
+
if (!path) {
|
|
3037
|
+
continue;
|
|
3038
|
+
}
|
|
3039
|
+
const line = typeof candidate.line === 'number' && candidate.line > 0 ? candidate.line : undefined;
|
|
3040
|
+
const column = typeof candidate.column === 'number' && candidate.column > 0 ? candidate.column : undefined;
|
|
3041
|
+
const score = typeof candidate.score === 'number' ? candidate.score : undefined;
|
|
3042
|
+
const symbol = typeof candidate.symbol === 'string' ? candidate.symbol : null;
|
|
3043
|
+
const rawSnippet = typeof candidate.content === 'string'
|
|
3044
|
+
? candidate.content
|
|
3045
|
+
: typeof candidate.name === 'string'
|
|
3046
|
+
? candidate.name
|
|
3047
|
+
: typeof candidate.type === 'string'
|
|
3048
|
+
? `[${candidate.type}]`
|
|
3049
|
+
: '';
|
|
3050
|
+
sections.push({
|
|
3051
|
+
path,
|
|
3052
|
+
line,
|
|
3053
|
+
endLine: typeof candidate.endLine === 'number' && candidate.endLine >= (line ?? 0) ? candidate.endLine : line,
|
|
3054
|
+
column,
|
|
3055
|
+
score,
|
|
3056
|
+
symbol,
|
|
3057
|
+
snippet: rawSnippet || '[no snippet available]',
|
|
3058
|
+
lines: Array.isArray(candidate.chunkLines) ? candidate.chunkLines : undefined,
|
|
3059
|
+
});
|
|
3060
|
+
}
|
|
3061
|
+
const groupsMap = new Map();
|
|
3062
|
+
for (const section of sections) {
|
|
3063
|
+
if (!groupsMap.has(section.path)) {
|
|
3064
|
+
groupsMap.set(section.path, {
|
|
3065
|
+
path: section.path,
|
|
3066
|
+
sections: [],
|
|
3067
|
+
total_matches: 0,
|
|
3068
|
+
});
|
|
3069
|
+
}
|
|
3070
|
+
const group = groupsMap.get(section.path);
|
|
3071
|
+
group.sections.push(section);
|
|
3072
|
+
group.total_matches += 1;
|
|
3073
|
+
}
|
|
3074
|
+
const groups = [...groupsMap.values()];
|
|
3075
|
+
const textParts = ['The following code sections were retrieved:'];
|
|
3076
|
+
for (const group of groups) {
|
|
3077
|
+
textParts.push('');
|
|
3078
|
+
textParts.push(`Path: ${group.path}`);
|
|
3079
|
+
group.sections.forEach((section, index) => {
|
|
3080
|
+
const chunkLabel = group.sections.length > 1 ? `Chunk ${index + 1}` : 'Chunk';
|
|
3081
|
+
textParts.push(`${chunkLabel}: lines ${formatChunkRange(section)}${section.score !== undefined ? ` | score=${section.score.toFixed(4)}` : ''}`);
|
|
3082
|
+
if (section.symbol) {
|
|
3083
|
+
textParts.push(`Symbol: ${section.symbol}`);
|
|
3084
|
+
}
|
|
3085
|
+
for (const snippetLine of renderAceSnippet(section)) {
|
|
3086
|
+
textParts.push(snippetLine);
|
|
3087
|
+
}
|
|
3088
|
+
if (index < group.sections.length - 1) {
|
|
3089
|
+
textParts.push('');
|
|
3090
|
+
}
|
|
3091
|
+
});
|
|
3092
|
+
}
|
|
3093
|
+
return {
|
|
3094
|
+
format: 'ace',
|
|
3095
|
+
text: textParts.join('\n'),
|
|
3096
|
+
groups,
|
|
3097
|
+
sections,
|
|
3098
|
+
total: sections.length,
|
|
3099
|
+
};
|
|
3100
|
+
}
|
|
2543
3101
|
/**
|
|
2544
3102
|
* Transform results based on output_mode
|
|
2545
3103
|
*/
|
|
@@ -2567,11 +3125,23 @@ function transformOutput(results, outputMode) {
|
|
|
2567
3125
|
total: results.length,
|
|
2568
3126
|
};
|
|
2569
3127
|
}
|
|
3128
|
+
case 'ace':
|
|
3129
|
+
return formatAceLikeOutput(results);
|
|
2570
3130
|
case 'full':
|
|
2571
3131
|
default:
|
|
2572
3132
|
return results;
|
|
2573
3133
|
}
|
|
2574
3134
|
}
|
|
3135
|
+
function enrichMetadataWithIndexStatus(metadata, indexStatus, scope) {
|
|
3136
|
+
const nextMetadata = { ...(metadata ?? {}) };
|
|
3137
|
+
nextMetadata.embeddings_coverage_percent = indexStatus.embeddings_coverage_percent;
|
|
3138
|
+
nextMetadata.index_status = indexStatus.indexed
|
|
3139
|
+
? (indexStatus.has_embeddings ? 'indexed' : 'partial')
|
|
3140
|
+
: 'not_indexed';
|
|
3141
|
+
nextMetadata.warning = mergeWarnings(nextMetadata.warning, indexStatus.warning);
|
|
3142
|
+
nextMetadata.suggestions = mergeSuggestions(nextMetadata.suggestions, buildIndexSuggestions(indexStatus, scope));
|
|
3143
|
+
return nextMetadata;
|
|
3144
|
+
}
|
|
2575
3145
|
// Handler function
|
|
2576
3146
|
export async function handler(params) {
|
|
2577
3147
|
const parsed = ParamsSchema.safeParse(params);
|
|
@@ -2642,11 +3212,19 @@ export async function handler(params) {
|
|
|
2642
3212
|
}
|
|
2643
3213
|
break;
|
|
2644
3214
|
}
|
|
3215
|
+
let autoEmbedNote;
|
|
2645
3216
|
// Transform output based on output_mode (for search actions only)
|
|
2646
3217
|
if (action === 'search' || action === 'search_files') {
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
3218
|
+
const scope = resolveSearchScope(parsed.data.path ?? '.');
|
|
3219
|
+
const indexStatus = await checkIndexStatus(scope.workingDirectory);
|
|
3220
|
+
result.metadata = enrichMetadataWithIndexStatus(result.metadata, indexStatus, scope);
|
|
3221
|
+
const autoEmbedStatus = await maybeStartBackgroundAutoEmbed(scope, indexStatus);
|
|
3222
|
+
autoEmbedNote = autoEmbedStatus.note;
|
|
3223
|
+
result.metadata = {
|
|
3224
|
+
...(result.metadata ?? {}),
|
|
3225
|
+
note: mergeNotes(result.metadata?.note, autoEmbedStatus.note),
|
|
3226
|
+
warning: mergeWarnings(result.metadata?.warning, autoEmbedStatus.warning),
|
|
3227
|
+
};
|
|
2650
3228
|
// Add pagination metadata for search results if not already present
|
|
2651
3229
|
if (result.success && result.results && Array.isArray(result.results)) {
|
|
2652
3230
|
const totalResults = result.results.length;
|
|
@@ -2662,6 +3240,33 @@ export async function handler(params) {
|
|
|
2662
3240
|
};
|
|
2663
3241
|
}
|
|
2664
3242
|
}
|
|
3243
|
+
if (result.success && result.results && output_mode !== 'full') {
|
|
3244
|
+
result.results = transformOutput(result.results, output_mode);
|
|
3245
|
+
if (output_mode === 'ace'
|
|
3246
|
+
&& result.results
|
|
3247
|
+
&& typeof result.results === 'object'
|
|
3248
|
+
&& 'format' in result.results
|
|
3249
|
+
&& result.results.format === 'ace') {
|
|
3250
|
+
const advisoryLines = [];
|
|
3251
|
+
if (result.metadata?.warning) {
|
|
3252
|
+
advisoryLines.push('', 'Warnings:', `- ${result.metadata.warning}`);
|
|
3253
|
+
}
|
|
3254
|
+
if (autoEmbedNote) {
|
|
3255
|
+
advisoryLines.push('', 'Notes:', `- ${autoEmbedNote}`);
|
|
3256
|
+
}
|
|
3257
|
+
if (result.metadata?.suggestions && result.metadata.suggestions.length > 0) {
|
|
3258
|
+
advisoryLines.push('', 'Suggestions:');
|
|
3259
|
+
for (const suggestion of result.metadata.suggestions) {
|
|
3260
|
+
advisoryLines.push(`- ${suggestion.title}: ${suggestion.command}`);
|
|
3261
|
+
advisoryLines.push(` ${suggestion.reason}`);
|
|
3262
|
+
}
|
|
3263
|
+
}
|
|
3264
|
+
const aceResults = result.results;
|
|
3265
|
+
if (advisoryLines.length > 0) {
|
|
3266
|
+
aceResults.text += `\n${advisoryLines.join('\n')}`;
|
|
3267
|
+
}
|
|
3268
|
+
}
|
|
3269
|
+
}
|
|
2665
3270
|
}
|
|
2666
3271
|
// Add deprecation warning if applicable
|
|
2667
3272
|
if (deprecationWarning && result.metadata) {
|
|
@@ -2680,10 +3285,14 @@ export async function handler(params) {
|
|
|
2680
3285
|
* @param onProgress - Optional callback for progress updates
|
|
2681
3286
|
*/
|
|
2682
3287
|
export const __testables = {
|
|
3288
|
+
isCodexLensCliCompatibilityError,
|
|
2683
3289
|
parseCodexLensJsonOutput,
|
|
2684
3290
|
parsePlainTextFileMatches,
|
|
2685
3291
|
hasCentralizedVectorArtifacts,
|
|
3292
|
+
resolveRipgrepQueryMode,
|
|
2686
3293
|
resolveEmbeddingSelection,
|
|
3294
|
+
isAutoEmbedMissingEnabled,
|
|
3295
|
+
buildIndexSuggestions,
|
|
2687
3296
|
};
|
|
2688
3297
|
export async function executeInitWithProgress(params, onProgress) {
|
|
2689
3298
|
const path = params.path || '.';
|