claude-code-workflow 7.2.10 → 7.2.12
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/agents/cli-planning-agent.md +3 -0
- package/.claude/agents/debug-explore-agent.md +1 -0
- package/.claude/agents/tdd-developer.md +1 -0
- package/.claude/agents/team-worker.md +1 -1
- package/.claude/agents/test-action-planning-agent.md +3 -0
- package/.claude/agents/test-context-search-agent.md +1 -0
- package/.claude/agents/test-fix-agent.md +3 -0
- package/.claude/commands/workflow/analyze-with-file.md +108 -54
- package/.claude/commands/workflow-tune.md +811 -0
- package/.claude/skills/review-code/SKILL.md +2 -0
- package/.claude/skills/review-cycle/SKILL.md +4 -0
- package/.claude/skills/skill-simplify/phases/02-optimize.md +4 -0
- package/.claude/skills/spec-generator/phases/05-epics-stories.md +4 -0
- package/.claude/skills/team-arch-opt/specs/team-config.json +5 -5
- package/.claude/skills/team-frontend-debug/roles/analyzer/role.md +3 -2
- package/.claude/skills/team-perf-opt/roles/coordinator/commands/monitor.md +1 -1
- package/.claude/skills/team-perf-opt/specs/team-config.json +5 -5
- package/.claude/skills/team-quality-assurance/roles/executor/role.md +2 -1
- package/.claude/skills/team-review/roles/reviewer/role.md +2 -1
- package/.claude/skills/team-tech-debt/roles/scanner/role.md +2 -1
- package/.claude/skills/team-testing/roles/executor/role.md +2 -1
- package/.claude/skills/team-testing/roles/generator/role.md +2 -1
- package/.claude/skills/team-ultra-analyze/roles/explorer/role.md +2 -1
- package/.claude/skills/team-ux-improve/specs/team-config.json +6 -6
- package/.claude/skills/workflow-execute/phases/06-review.md +4 -4
- package/.claude/skills/workflow-lite-execute/SKILL.md +106 -14
- package/.claude/skills/workflow-lite-plan/SKILL.md +34 -72
- package/.claude/skills/workflow-lite-test-review/SKILL.md +41 -26
- package/.claude/skills/workflow-plan/phases/05-plan-verify.md +4 -0
- package/.claude/skills/workflow-tdd-plan/phases/02-context-gathering.md +1 -0
- package/.claude/skills/workflow-tdd-plan/phases/05-tdd-task-generation.md +2 -1
- package/.claude/skills/workflow-test-fix/phases/02-test-context-gather.md +1 -0
- package/.claude/skills/workflow-test-fix/phases/05-test-cycle-execute.md +2 -1
- package/.codex/skills/analyze-with-file/SKILL.md +2 -0
- package/.codex/skills/debug-with-file/SKILL.md +4 -0
- package/.codex/skills/issue-discover/SKILL.md +1 -0
- package/.codex/skills/review-cycle/phases/02-parallel-review.md +3 -0
- package/.codex/skills/team-designer/agents/validation-reporter.md +186 -0
- package/.codex/skills/team-iterdev/agents/gc-controller.md +193 -0
- package/.codex/skills/team-iterdev/agents/task-analyzer.md +206 -0
- package/.codex/skills/team-lifecycle-v4/agents/quality-gate.md +165 -0
- package/.codex/skills/team-lifecycle-v4/agents/requirement-clarifier.md +163 -0
- package/.codex/skills/team-lifecycle-v4/agents/supervisor.md +182 -0
- package/.codex/skills/team-uidesign/agents/completion-handler.md +177 -0
- package/.codex/skills/team-uidesign/agents/gc-loop-handler.md +162 -0
- package/.codex/skills/workflow-test-fix-cycle/phases/01-test-fix-gen.md +4 -0
- package/.codex/skills/workflow-test-fix-cycle/phases/02-test-cycle-execute.md +2 -0
- package/ccw/dist/commands/spec.d.ts.map +1 -1
- package/ccw/dist/commands/spec.js +9 -4
- package/ccw/dist/commands/spec.js.map +1 -1
- package/ccw/dist/core/routes/codexlens-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/codexlens-routes.js +3 -1
- package/ccw/dist/core/routes/codexlens-routes.js.map +1 -1
- package/ccw/dist/tools/spec-index-builder.d.ts +8 -4
- package/ccw/dist/tools/spec-index-builder.d.ts.map +1 -1
- package/ccw/dist/tools/spec-index-builder.js +8 -4
- package/ccw/dist/tools/spec-index-builder.js.map +1 -1
- package/ccw/dist/tools/spec-init.d.ts +1 -1
- package/ccw/dist/tools/spec-init.d.ts.map +1 -1
- package/ccw/dist/tools/spec-init.js +127 -0
- package/ccw/dist/tools/spec-init.js.map +1 -1
- package/ccw/dist/tools/spec-loader.d.ts.map +1 -1
- package/ccw/dist/tools/spec-loader.js +2 -1
- package/ccw/dist/tools/spec-loader.js.map +1 -1
- package/ccw/frontend/dist/assets/{AlertDialog-gTMl4gSG.js → AlertDialog-BW9jiZ-p.js} +2 -2
- package/ccw/frontend/dist/assets/{AlertDialog-gTMl4gSG.js.map → AlertDialog-BW9jiZ-p.js.map} +1 -1
- package/ccw/frontend/dist/assets/{AnalysisPage-Bc4p4SvJ.js → AnalysisPage-ds-w_nVO.js} +2 -2
- package/ccw/frontend/dist/assets/{AnalysisPage-Bc4p4SvJ.js.map → AnalysisPage-ds-w_nVO.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ApiSettingsPage-CVK108u2.js → ApiSettingsPage-DlCbXxTz.js} +2 -2
- package/ccw/frontend/dist/assets/{ApiSettingsPage-CVK108u2.js.map → ApiSettingsPage-DlCbXxTz.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CliModeToggle-34Sjwl05.js → CliModeToggle-Dq3nL4fF.js} +2 -2
- package/ccw/frontend/dist/assets/{CliModeToggle-34Sjwl05.js.map → CliModeToggle-Dq3nL4fF.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CliSessionSharePage-bJZAYI38.js → CliSessionSharePage-BNDkEE4u.js} +2 -2
- package/ccw/frontend/dist/assets/{CliSessionSharePage-bJZAYI38.js.map → CliSessionSharePage-BNDkEE4u.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CliViewerPage-VYnQGjxU.js → CliViewerPage-ChM-uNx_.js} +2 -2
- package/ccw/frontend/dist/assets/{CliViewerPage-VYnQGjxU.js.map → CliViewerPage-ChM-uNx_.js.map} +1 -1
- package/ccw/frontend/dist/assets/CodexLensPage-DOcsYNQk.js +2 -0
- package/ccw/frontend/dist/assets/CodexLensPage-DOcsYNQk.js.map +1 -0
- package/ccw/frontend/dist/assets/{Collapsible-B_xd1Qbg.js → Collapsible-CRNbykXN.js} +2 -2
- package/ccw/frontend/dist/assets/{Collapsible-B_xd1Qbg.js.map → Collapsible-CRNbykXN.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CommandsManagerPage-Bjx1bPbH.js → CommandsManagerPage-C2JWcemF.js} +2 -2
- package/ccw/frontend/dist/assets/{CommandsManagerPage-Bjx1bPbH.js.map → CommandsManagerPage-C2JWcemF.js.map} +1 -1
- package/ccw/frontend/dist/assets/{DeepWikiPage-EgHsHvAH.js → DeepWikiPage-CvleOtJy.js} +2 -2
- package/ccw/frontend/dist/assets/{DeepWikiPage-EgHsHvAH.js.map → DeepWikiPage-CvleOtJy.js.map} +1 -1
- package/ccw/frontend/dist/assets/{EndpointsPage-CuwpbCzK.js → EndpointsPage-CMOWQG64.js} +2 -2
- package/ccw/frontend/dist/assets/{EndpointsPage-CuwpbCzK.js.map → EndpointsPage-CMOWQG64.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ExplorerPage-cvlx0Zw0.js → ExplorerPage-DaFPRlNo.js} +2 -2
- package/ccw/frontend/dist/assets/{ExplorerPage-cvlx0Zw0.js.map → ExplorerPage-DaFPRlNo.js.map} +1 -1
- package/ccw/frontend/dist/assets/{FixSessionPage-C74-MPza.js → FixSessionPage-CC4p04Az.js} +2 -2
- package/ccw/frontend/dist/assets/{FixSessionPage-C74-MPza.js.map → FixSessionPage-CC4p04Az.js.map} +1 -1
- package/ccw/frontend/dist/assets/{FloatingFileBrowser-x_-6y_n2.js → FloatingFileBrowser-DROn1xZ5.js} +2 -2
- package/ccw/frontend/dist/assets/{FloatingFileBrowser-x_-6y_n2.js.map → FloatingFileBrowser-DROn1xZ5.js.map} +1 -1
- package/ccw/frontend/dist/assets/{FloatingPanel-BGwmbJR1.js → FloatingPanel-CmL_yhDv.js} +2 -2
- package/ccw/frontend/dist/assets/{FloatingPanel-BGwmbJR1.js.map → FloatingPanel-CmL_yhDv.js.map} +1 -1
- package/ccw/frontend/dist/assets/{GraphExplorerPage-Bg5-aQxi.js → GraphExplorerPage-DCV5ybKE.js} +2 -2
- package/ccw/frontend/dist/assets/{GraphExplorerPage-Bg5-aQxi.js.map → GraphExplorerPage-DCV5ybKE.js.map} +1 -1
- package/ccw/frontend/dist/assets/{HistoryPage-C00fh0HE.js → HistoryPage-D0fYQZgc.js} +2 -2
- package/ccw/frontend/dist/assets/{HistoryPage-C00fh0HE.js.map → HistoryPage-D0fYQZgc.js.map} +1 -1
- package/ccw/frontend/dist/assets/{HookManagerPage-CtVTB_ae.js → HookManagerPage-D2FuJfsM.js} +2 -2
- package/ccw/frontend/dist/assets/{HookManagerPage-CtVTB_ae.js.map → HookManagerPage-D2FuJfsM.js.map} +1 -1
- package/ccw/frontend/dist/assets/{InstallationsPage-CYuMQDbC.js → InstallationsPage-tjklillZ.js} +2 -2
- package/ccw/frontend/dist/assets/{InstallationsPage-CYuMQDbC.js.map → InstallationsPage-tjklillZ.js.map} +1 -1
- package/ccw/frontend/dist/assets/{IssueHubPage-T_VSvUMh.js → IssueHubPage-E4JVrhO1.js} +2 -2
- package/ccw/frontend/dist/assets/{IssueHubPage-T_VSvUMh.js.map → IssueHubPage-E4JVrhO1.js.map} +1 -1
- package/ccw/frontend/dist/assets/{LiteTasksPage-DmcgvIvi.js → LiteTasksPage-aJuRoyLt.js} +2 -2
- package/ccw/frontend/dist/assets/{LiteTasksPage-DmcgvIvi.js.map → LiteTasksPage-aJuRoyLt.js.map} +1 -1
- package/ccw/frontend/dist/assets/{McpManagerPage-C_a7QSKz.js → McpManagerPage-BJeuWJv1.js} +2 -2
- package/ccw/frontend/dist/assets/{McpManagerPage-C_a7QSKz.js.map → McpManagerPage-BJeuWJv1.js.map} +1 -1
- package/ccw/frontend/dist/assets/{MemoryPage-CWKmXY5k.js → MemoryPage-BI4FAXhs.js} +2 -2
- package/ccw/frontend/dist/assets/{MemoryPage-CWKmXY5k.js.map → MemoryPage-BI4FAXhs.js.map} +1 -1
- package/ccw/frontend/dist/assets/{NotFoundPage-B1duXK6r.js → NotFoundPage-DD2svchp.js} +2 -2
- package/ccw/frontend/dist/assets/{NotFoundPage-B1duXK6r.js.map → NotFoundPage-DD2svchp.js.map} +1 -1
- package/ccw/frontend/dist/assets/{OrchestratorPage-Ib9TM6HE.js → OrchestratorPage-FC__7yYa.js} +2 -2
- package/ccw/frontend/dist/assets/{OrchestratorPage-Ib9TM6HE.js.map → OrchestratorPage-FC__7yYa.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ProjectOverviewPage-sXSWMbF8.js → ProjectOverviewPage-DBB_-FzV.js} +2 -2
- package/ccw/frontend/dist/assets/{ProjectOverviewPage-sXSWMbF8.js.map → ProjectOverviewPage-DBB_-FzV.js.map} +1 -1
- package/ccw/frontend/dist/assets/{PromptHistoryPage-B6jaqG12.js → PromptHistoryPage-BwOAvCH8.js} +2 -2
- package/ccw/frontend/dist/assets/{PromptHistoryPage-B6jaqG12.js.map → PromptHistoryPage-BwOAvCH8.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ReviewSessionPage-D5qJyr3s.js → ReviewSessionPage-Dd1-g_gp.js} +2 -2
- package/ccw/frontend/dist/assets/{ReviewSessionPage-D5qJyr3s.js.map → ReviewSessionPage-Dd1-g_gp.js.map} +1 -1
- package/ccw/frontend/dist/assets/{RulesManagerPage-DyawK8QE.js → RulesManagerPage-B3RGdsKD.js} +2 -2
- package/ccw/frontend/dist/assets/{RulesManagerPage-DyawK8QE.js.map → RulesManagerPage-B3RGdsKD.js.map} +1 -1
- package/ccw/frontend/dist/assets/{SessionDetailPage-Cym_RvC9.js → SessionDetailPage-DM-W5R8K.js} +2 -2
- package/ccw/frontend/dist/assets/{SessionDetailPage-Cym_RvC9.js.map → SessionDetailPage-DM-W5R8K.js.map} +1 -1
- package/ccw/frontend/dist/assets/{SessionsPage-Dkc1Hv8W.js → SessionsPage-BVz1KCc7.js} +2 -2
- package/ccw/frontend/dist/assets/{SessionsPage-Dkc1Hv8W.js.map → SessionsPage-BVz1KCc7.js.map} +1 -1
- package/ccw/frontend/dist/assets/{SettingsPage-Rik9cUIj.js → SettingsPage-ComW7EZS.js} +4 -4
- package/ccw/frontend/dist/assets/{SettingsPage-Rik9cUIj.js.map → SettingsPage-ComW7EZS.js.map} +1 -1
- package/ccw/frontend/dist/assets/{SkillsManagerPage-BGDWYAyI.js → SkillsManagerPage-CKom9XwV.js} +2 -2
- package/ccw/frontend/dist/assets/{SkillsManagerPage-BGDWYAyI.js.map → SkillsManagerPage-CKom9XwV.js.map} +1 -1
- package/ccw/frontend/dist/assets/{SpecsSettingsPage-CTiA1DMP.js → SpecsSettingsPage-DQz7WP2s.js} +2 -2
- package/ccw/frontend/dist/assets/{SpecsSettingsPage-CTiA1DMP.js.map → SpecsSettingsPage-DQz7WP2s.js.map} +1 -1
- package/ccw/frontend/dist/assets/{Switch-BgAFC-Wk.js → Switch-BPMdND9H.js} +2 -2
- package/ccw/frontend/dist/assets/{Switch-BgAFC-Wk.js.map → Switch-BPMdND9H.js.map} +1 -1
- package/ccw/frontend/dist/assets/{TabsNavigation-drSnu5jn.js → TabsNavigation-qqt70VYL.js} +2 -2
- package/ccw/frontend/dist/assets/{TabsNavigation-drSnu5jn.js.map → TabsNavigation-qqt70VYL.js.map} +1 -1
- package/ccw/frontend/dist/assets/{TaskDrawer-ePC__6-P.js → TaskDrawer-BqK_qiHX.js} +2 -2
- package/ccw/frontend/dist/assets/{TaskDrawer-ePC__6-P.js.map → TaskDrawer-BqK_qiHX.js.map} +1 -1
- package/ccw/frontend/dist/assets/{TeamPage-C6bdFWn8.js → TeamPage-u5_i0Rgh.js} +2 -2
- package/ccw/frontend/dist/assets/{TeamPage-C6bdFWn8.js.map → TeamPage-u5_i0Rgh.js.map} +1 -1
- package/ccw/frontend/dist/assets/{TerminalDashboardPage-Zofi_DZM.js → TerminalDashboardPage-rUtC9e40.js} +2 -2
- package/ccw/frontend/dist/assets/{TerminalDashboardPage-Zofi_DZM.js.map → TerminalDashboardPage-rUtC9e40.js.map} +1 -1
- package/ccw/frontend/dist/assets/{archive-Bza1KlB9.js → archive-C3u8YNQF.js} +2 -2
- package/ccw/frontend/dist/assets/{archive-Bza1KlB9.js.map → archive-C3u8YNQF.js.map} +1 -1
- package/ccw/frontend/dist/assets/{archive-restore-CpsDm-cG.js → archive-restore-DfQ998g5.js} +2 -2
- package/ccw/frontend/dist/assets/{archive-restore-CpsDm-cG.js.map → archive-restore-DfQ998g5.js.map} +1 -1
- package/ccw/frontend/dist/assets/{arrow-right-CibG_LVO.js → arrow-right-BshJM9Po.js} +2 -2
- package/ccw/frontend/dist/assets/{arrow-right-CibG_LVO.js.map → arrow-right-BshJM9Po.js.map} +1 -1
- package/ccw/frontend/dist/assets/{bookmark-plus-BheO8EgG.js → bookmark-plus-D03qJyOZ.js} +2 -2
- package/ccw/frontend/dist/assets/{bookmark-plus-BheO8EgG.js.map → bookmark-plus-D03qJyOZ.js.map} +1 -1
- package/ccw/frontend/dist/assets/{bot-BlhM0Nl0.js → bot-CyzWuwq0.js} +2 -2
- package/ccw/frontend/dist/assets/{bot-BlhM0Nl0.js.map → bot-CyzWuwq0.js.map} +1 -1
- package/ccw/frontend/dist/assets/{braces-Dqjg_eCO.js → braces-BPgtyjsG.js} +2 -2
- package/ccw/frontend/dist/assets/{braces-Dqjg_eCO.js.map → braces-BPgtyjsG.js.map} +1 -1
- package/ccw/frontend/dist/assets/{circle-stop-DYZSLYU0.js → circle-stop-Dix1AOmw.js} +2 -2
- package/ccw/frontend/dist/assets/{circle-stop-DYZSLYU0.js.map → circle-stop-Dix1AOmw.js.map} +1 -1
- package/ccw/frontend/dist/assets/{cpu-DWCyAOAv.js → cpu-CCQ4Q0Zh.js} +2 -2
- package/ccw/frontend/dist/assets/{cpu-DWCyAOAv.js.map → cpu-CCQ4Q0Zh.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ellipsis-vertical-DIyoSEHx.js → ellipsis-vertical-BpTysg-Y.js} +2 -2
- package/ccw/frontend/dist/assets/{ellipsis-vertical-DIyoSEHx.js.map → ellipsis-vertical-BpTysg-Y.js.map} +1 -1
- package/ccw/frontend/dist/assets/{eye-DUy7aLEx.js → eye-DGY1rAZs.js} +2 -2
- package/ccw/frontend/dist/assets/{eye-DUy7aLEx.js.map → eye-DGY1rAZs.js.map} +1 -1
- package/ccw/frontend/dist/assets/{eye-off-CGRUVRDR.js → eye-off-D8t3JfWG.js} +2 -2
- package/ccw/frontend/dist/assets/{eye-off-CGRUVRDR.js.map → eye-off-D8t3JfWG.js.map} +1 -1
- package/ccw/frontend/dist/assets/{file-json-BxLBtU9d.js → file-json-BAdJb0n8.js} +2 -2
- package/ccw/frontend/dist/assets/{file-json-BxLBtU9d.js.map → file-json-BAdJb0n8.js.map} +1 -1
- package/ccw/frontend/dist/assets/{file-text-BoHsW2es.js → file-text-DrJFiOUB.js} +2 -2
- package/ccw/frontend/dist/assets/{file-text-BoHsW2es.js.map → file-text-DrJFiOUB.js.map} +1 -1
- package/ccw/frontend/dist/assets/{filter-B4vOqP6B.js → filter-CKqzYbz7.js} +2 -2
- package/ccw/frontend/dist/assets/{filter-B4vOqP6B.js.map → filter-CKqzYbz7.js.map} +1 -1
- package/ccw/frontend/dist/assets/{folder-BKhwCNFG.js → folder-CV8511y9.js} +2 -2
- package/ccw/frontend/dist/assets/{folder-BKhwCNFG.js.map → folder-CV8511y9.js.map} +1 -1
- package/ccw/frontend/dist/assets/{gauge-Dgf64gkT.js → gauge-XKvmu_uU.js} +2 -2
- package/ccw/frontend/dist/assets/{gauge-Dgf64gkT.js.map → gauge-XKvmu_uU.js.map} +1 -1
- package/ccw/frontend/dist/assets/{globe-Cus_S6Ux.js → globe-C56cDUzX.js} +2 -2
- package/ccw/frontend/dist/assets/{globe-Cus_S6Ux.js.map → globe-C56cDUzX.js.map} +1 -1
- package/ccw/frontend/dist/assets/{grid-3x3-DM08hpAN.js → grid-3x3-Bya-suFW.js} +2 -2
- package/ccw/frontend/dist/assets/{grid-3x3-DM08hpAN.js.map → grid-3x3-Bya-suFW.js.map} +1 -1
- package/ccw/frontend/dist/assets/{hard-drive-eCtll84F.js → hard-drive-CmuTZpsB.js} +2 -2
- package/ccw/frontend/dist/assets/{hard-drive-eCtll84F.js.map → hard-drive-CmuTZpsB.js.map} +1 -1
- package/ccw/frontend/dist/assets/{hash-Bd1RD285.js → hash-CRPT_tJQ.js} +2 -2
- package/ccw/frontend/dist/assets/{hash-Bd1RD285.js.map → hash-CRPT_tJQ.js.map} +1 -1
- package/ccw/frontend/dist/assets/{history-eyyCQA6b.js → history-C1pJZQCL.js} +2 -2
- package/ccw/frontend/dist/assets/{history-eyyCQA6b.js.map → history-C1pJZQCL.js.map} +1 -1
- package/ccw/frontend/dist/assets/{index-ZnmWxcZg.js → index-B6TpijCe.js} +2 -2
- package/ccw/frontend/dist/assets/{index-ZnmWxcZg.js.map → index-B6TpijCe.js.map} +1 -1
- package/ccw/frontend/dist/assets/{index-b2C0iFd1.js → index-Bcq-7r6F.js} +2 -2
- package/ccw/frontend/dist/assets/{index-b2C0iFd1.js.map → index-Bcq-7r6F.js.map} +1 -1
- package/ccw/frontend/dist/assets/{index-Cs2ShCCy.js → index-CI8-rBff.js} +2 -2
- package/ccw/frontend/dist/assets/{index-Cs2ShCCy.js.map → index-CI8-rBff.js.map} +1 -1
- package/ccw/frontend/dist/assets/{index-CY6Lueph.js → index-Dmt9OiEf.js} +2 -2
- package/ccw/frontend/dist/assets/{index-CY6Lueph.js.map → index-Dmt9OiEf.js.map} +1 -1
- package/ccw/frontend/dist/assets/{index-DfeBbFXo.js → index-anSMmEF8.js} +2 -2
- package/ccw/frontend/dist/assets/{index-DfeBbFXo.js.map → index-anSMmEF8.js.map} +1 -1
- package/ccw/frontend/dist/assets/{index-B6I7GQC5.js → index-dWT2M6Ef.js} +4 -4
- package/ccw/frontend/dist/assets/{index-B6I7GQC5.js.map → index-dWT2M6Ef.js.map} +1 -1
- package/ccw/frontend/dist/assets/{layout-grid-ChrTrCby.js → layout-grid-TSO0BFQE.js} +2 -2
- package/ccw/frontend/dist/assets/{layout-grid-ChrTrCby.js.map → layout-grid-TSO0BFQE.js.map} +1 -1
- package/ccw/frontend/dist/assets/{lightbulb-CvXiTlzN.js → lightbulb-Caj6fIQD.js} +2 -2
- package/ccw/frontend/dist/assets/{lightbulb-CvXiTlzN.js.map → lightbulb-Caj6fIQD.js.map} +1 -1
- package/ccw/frontend/dist/assets/{link-2-W0Nl17ec.js → link-2-DE9lMxa-.js} +2 -2
- package/ccw/frontend/dist/assets/{link-2-W0Nl17ec.js.map → link-2-DE9lMxa-.js.map} +1 -1
- package/ccw/frontend/dist/assets/{link-CL4JmoHb.js → link-BZtPgLW0.js} +2 -2
- package/ccw/frontend/dist/assets/{link-CL4JmoHb.js.map → link-BZtPgLW0.js.map} +1 -1
- package/ccw/frontend/dist/assets/{list-CDmYFcio.js → list-DubWyY-U.js} +2 -2
- package/ccw/frontend/dist/assets/{list-CDmYFcio.js.map → list-DubWyY-U.js.map} +1 -1
- package/ccw/frontend/dist/assets/{map-pin-0Mfsw_3d.js → map-pin-DwN_48AF.js} +2 -2
- package/ccw/frontend/dist/assets/{map-pin-0Mfsw_3d.js.map → map-pin-DwN_48AF.js.map} +1 -1
- package/ccw/frontend/dist/assets/{messages-square-C6h08ple.js → messages-square-bjxvaiM9.js} +2 -2
- package/ccw/frontend/dist/assets/{messages-square-C6h08ple.js.map → messages-square-bjxvaiM9.js.map} +1 -1
- package/ccw/frontend/dist/assets/{minimize-2-Cbu2yRzi.js → minimize-2-CGfBKD_V.js} +2 -2
- package/ccw/frontend/dist/assets/{minimize-2-Cbu2yRzi.js.map → minimize-2-CGfBKD_V.js.map} +1 -1
- package/ccw/frontend/dist/assets/{package-CoLVUZGJ.js → package-nzWY6ilt.js} +2 -2
- package/ccw/frontend/dist/assets/{package-CoLVUZGJ.js.map → package-nzWY6ilt.js.map} +1 -1
- package/ccw/frontend/dist/assets/{plug-BYTYqsw1.js → plug-CiLce49C.js} +2 -2
- package/ccw/frontend/dist/assets/{plug-BYTYqsw1.js.map → plug-CiLce49C.js.map} +1 -1
- package/ccw/frontend/dist/assets/{power-DmIojFl-.js → power-CFLmB-U9.js} +2 -2
- package/ccw/frontend/dist/assets/{power-DmIojFl-.js.map → power-CFLmB-U9.js.map} +1 -1
- package/ccw/frontend/dist/assets/{save-BFa03OnG.js → save-DuO6OF0C.js} +2 -2
- package/ccw/frontend/dist/assets/{save-BFa03OnG.js.map → save-DuO6OF0C.js.map} +1 -1
- package/ccw/frontend/dist/assets/{send-Vet3sN4J.js → send-CZk9p0mM.js} +2 -2
- package/ccw/frontend/dist/assets/{send-Vet3sN4J.js.map → send-CZk9p0mM.js.map} +1 -1
- package/ccw/frontend/dist/assets/{square-check-big-B9nzZRfE.js → square-check-big-BY_1YQQg.js} +2 -2
- package/ccw/frontend/dist/assets/{square-check-big-B9nzZRfE.js.map → square-check-big-BY_1YQQg.js.map} +1 -1
- package/ccw/frontend/dist/assets/{square-pen-C7K13x4Z.js → square-pen-CnZgm6g-.js} +2 -2
- package/ccw/frontend/dist/assets/{square-pen-C7K13x4Z.js.map → square-pen-CnZgm6g-.js.map} +1 -1
- package/ccw/frontend/dist/assets/{star-BCQHcnSe.js → star-Cn1F0qy7.js} +2 -2
- package/ccw/frontend/dist/assets/{star-BCQHcnSe.js.map → star-Cn1F0qy7.js.map} +1 -1
- package/ccw/frontend/dist/assets/{style-CJsrp48L.js → style-Dxs1iXCV.js} +2 -2
- package/ccw/frontend/dist/assets/{style-CJsrp48L.js.map → style-Dxs1iXCV.js.map} +1 -1
- package/ccw/frontend/dist/assets/{target-CBzCJCB1.js → target-Bz1fLRKH.js} +2 -2
- package/ccw/frontend/dist/assets/{target-CBzCJCB1.js.map → target-Bz1fLRKH.js.map} +1 -1
- package/ccw/frontend/dist/assets/{test-tube-BYTc5mvQ.js → test-tube-C6qCYlDr.js} +2 -2
- package/ccw/frontend/dist/assets/{test-tube-BYTc5mvQ.js.map → test-tube-C6qCYlDr.js.map} +1 -1
- package/ccw/frontend/dist/assets/{upload-DzyQj7ib.js → upload-C71kd4Qs.js} +2 -2
- package/ccw/frontend/dist/assets/{upload-DzyQj7ib.js.map → upload-C71kd4Qs.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useApiSettings-CFPww7gU.js → useApiSettings-CqP2BAJ7.js} +2 -2
- package/ccw/frontend/dist/assets/{useApiSettings-CFPww7gU.js.map → useApiSettings-CqP2BAJ7.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useCli-ByL_a5CD.js → useCli-PCoPoVeM.js} +2 -2
- package/ccw/frontend/dist/assets/{useCli-ByL_a5CD.js.map → useCli-PCoPoVeM.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useCommands-BvKIoOzB.js → useCommands-3OfPQPw4.js} +2 -2
- package/ccw/frontend/dist/assets/{useCommands-BvKIoOzB.js.map → useCommands-3OfPQPw4.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useDebounce-CmKmoP7n.js → useDebounce-bXiFhQx9.js} +2 -2
- package/ccw/frontend/dist/assets/{useDebounce-CmKmoP7n.js.map → useDebounce-bXiFhQx9.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useFileExplorer-G5UoArCU.js → useFileExplorer-DEyUm46_.js} +2 -2
- package/ccw/frontend/dist/assets/{useFileExplorer-G5UoArCU.js.map → useFileExplorer-DEyUm46_.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useLocale-D2iHK44M.js → useLocale-sXTrdxcJ.js} +2 -2
- package/ccw/frontend/dist/assets/{useLocale-D2iHK44M.js.map → useLocale-sXTrdxcJ.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useSkills-CYU4zqhm.js → useSkills-D0W0kXYm.js} +3 -3
- package/ccw/frontend/dist/assets/{useSkills-CYU4zqhm.js.map → useSkills-D0W0kXYm.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useSystemSettings-JznNpij7.js → useSystemSettings-DZ-8lZsG.js} +2 -2
- package/ccw/frontend/dist/assets/{useSystemSettings-JznNpij7.js.map → useSystemSettings-DZ-8lZsG.js.map} +1 -1
- package/ccw/frontend/dist/assets/{wand-sparkles-DqS0VCeN.js → wand-sparkles-83GmAYuw.js} +2 -2
- package/ccw/frontend/dist/assets/{wand-sparkles-DqS0VCeN.js.map → wand-sparkles-83GmAYuw.js.map} +1 -1
- package/ccw/frontend/dist/index.html +1 -1
- package/package.json +1 -1
- package/.claude/commands/ddd/auto.md +0 -359
- package/.claude/commands/ddd/doc-generate.md +0 -222
- package/.claude/commands/ddd/doc-refresh.md +0 -218
- package/.claude/commands/ddd/execute.md +0 -416
- package/.claude/commands/ddd/index-build.md +0 -212
- package/.claude/commands/ddd/plan.md +0 -611
- package/.claude/commands/ddd/scan.md +0 -365
- package/.claude/commands/ddd/sync.md +0 -353
- package/.claude/commands/ddd/update.md +0 -160
- package/.claude/commands/idaw/add.md +0 -287
- package/.claude/commands/idaw/resume.md +0 -442
- package/.claude/commands/idaw/run-coordinate.md +0 -648
- package/.claude/commands/idaw/run.md +0 -539
- package/.claude/commands/idaw/status.md +0 -182
- package/.claude/skills/team-arch-opt/role-specs/analyzer.md +0 -80
- package/.claude/skills/team-arch-opt/role-specs/designer.md +0 -118
- package/.claude/skills/team-arch-opt/role-specs/refactorer.md +0 -106
- package/.claude/skills/team-arch-opt/role-specs/reviewer.md +0 -116
- package/.claude/skills/team-arch-opt/role-specs/validator.md +0 -117
- package/.claude/skills/team-brainstorm/role-specs/challenger.md +0 -63
- package/.claude/skills/team-brainstorm/role-specs/evaluator.md +0 -58
- package/.claude/skills/team-brainstorm/role-specs/ideator.md +0 -71
- package/.claude/skills/team-brainstorm/role-specs/synthesizer.md +0 -59
- package/.claude/skills/team-frontend/role-specs/analyst.md +0 -91
- package/.claude/skills/team-frontend/role-specs/architect.md +0 -85
- package/.claude/skills/team-frontend/role-specs/developer.md +0 -92
- package/.claude/skills/team-frontend/role-specs/qa.md +0 -78
- package/.claude/skills/team-issue/role-specs/explorer.md +0 -95
- package/.claude/skills/team-issue/role-specs/implementer.md +0 -89
- package/.claude/skills/team-issue/role-specs/integrator.md +0 -86
- package/.claude/skills/team-issue/role-specs/planner.md +0 -83
- package/.claude/skills/team-issue/role-specs/reviewer.md +0 -89
- package/.claude/skills/team-iterdev/role-specs/architect.md +0 -64
- package/.claude/skills/team-iterdev/role-specs/developer.md +0 -73
- package/.claude/skills/team-iterdev/role-specs/reviewer.md +0 -65
- package/.claude/skills/team-iterdev/role-specs/tester.md +0 -87
- package/.claude/skills/team-perf-opt/role-specs/benchmarker.md +0 -110
- package/.claude/skills/team-perf-opt/role-specs/optimizer.md +0 -102
- package/.claude/skills/team-perf-opt/role-specs/profiler.md +0 -73
- package/.claude/skills/team-perf-opt/role-specs/reviewer.md +0 -91
- package/.claude/skills/team-perf-opt/role-specs/strategist.md +0 -114
- package/.claude/skills/team-planex/role-specs/executor.md +0 -90
- package/.claude/skills/team-planex/role-specs/planner.md +0 -110
- package/.claude/skills/team-quality-assurance/role-specs/analyst.md +0 -79
- package/.claude/skills/team-quality-assurance/role-specs/executor.md +0 -64
- package/.claude/skills/team-quality-assurance/role-specs/generator.md +0 -67
- package/.claude/skills/team-quality-assurance/role-specs/scout.md +0 -66
- package/.claude/skills/team-quality-assurance/role-specs/strategist.md +0 -70
- package/.claude/skills/team-review/role-specs/fixer.md +0 -75
- package/.claude/skills/team-review/role-specs/reviewer.md +0 -66
- package/.claude/skills/team-review/role-specs/scanner.md +0 -70
- package/.claude/skills/team-roadmap-dev/role-specs/executor.md +0 -71
- package/.claude/skills/team-roadmap-dev/role-specs/planner.md +0 -77
- package/.claude/skills/team-roadmap-dev/role-specs/verifier.md +0 -73
- package/.claude/skills/team-tech-debt/role-specs/assessor.md +0 -70
- package/.claude/skills/team-tech-debt/role-specs/executor.md +0 -80
- package/.claude/skills/team-tech-debt/role-specs/planner.md +0 -71
- package/.claude/skills/team-tech-debt/role-specs/scanner.md +0 -85
- package/.claude/skills/team-tech-debt/role-specs/validator.md +0 -83
- package/.claude/skills/team-testing/role-specs/analyst.md +0 -94
- package/.claude/skills/team-testing/role-specs/executor.md +0 -97
- package/.claude/skills/team-testing/role-specs/generator.md +0 -96
- package/.claude/skills/team-testing/role-specs/strategist.md +0 -82
- package/.claude/skills/team-uidesign/role-specs/designer.md +0 -72
- package/.claude/skills/team-uidesign/role-specs/implementer.md +0 -74
- package/.claude/skills/team-uidesign/role-specs/researcher.md +0 -84
- package/.claude/skills/team-uidesign/role-specs/reviewer.md +0 -70
- package/.claude/skills/team-ux-improve/role-specs/designer.md +0 -191
- package/.claude/skills/team-ux-improve/role-specs/diagnoser.md +0 -110
- package/.claude/skills/team-ux-improve/role-specs/explorer.md +0 -109
- package/.claude/skills/team-ux-improve/role-specs/implementer.md +0 -164
- package/.claude/skills/team-ux-improve/role-specs/scanner.md +0 -117
- package/.claude/skills/team-ux-improve/role-specs/tester.md +0 -163
- package/ccw/frontend/dist/assets/CodexLensPage-My6DnfN6.js +0 -2
- package/ccw/frontend/dist/assets/CodexLensPage-My6DnfN6.js.map +0 -1
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
prefix: SCAN
|
|
3
|
-
inner_loop: false
|
|
4
|
-
message_types:
|
|
5
|
-
success: scan_complete
|
|
6
|
-
error: error
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# UI Scanner
|
|
10
|
-
|
|
11
|
-
Scan UI components to identify interaction issues: unresponsive buttons, missing feedback mechanisms, state not refreshing.
|
|
12
|
-
|
|
13
|
-
## Phase 2: Context Loading
|
|
14
|
-
|
|
15
|
-
| Input | Source | Required |
|
|
16
|
-
|-------|--------|----------|
|
|
17
|
-
| Project path | Task description CONTEXT | Yes |
|
|
18
|
-
| Framework | Task description CONTEXT | Yes |
|
|
19
|
-
| Scan scope | Task description CONSTRAINTS | Yes |
|
|
20
|
-
|
|
21
|
-
1. Extract session path and project path from task description
|
|
22
|
-
2. Detect framework from project structure:
|
|
23
|
-
|
|
24
|
-
| Signal | Framework |
|
|
25
|
-
|--------|-----------|
|
|
26
|
-
| package.json has "react" | React |
|
|
27
|
-
| package.json has "vue" | Vue |
|
|
28
|
-
| *.tsx files present | React |
|
|
29
|
-
| *.vue files present | Vue |
|
|
30
|
-
|
|
31
|
-
3. Build file pattern list for scanning:
|
|
32
|
-
- React: `**/*.tsx`, `**/*.jsx`, `**/use*.ts`
|
|
33
|
-
- Vue: `**/*.vue`, `**/composables/*.ts`
|
|
34
|
-
|
|
35
|
-
### Wisdom Input
|
|
36
|
-
|
|
37
|
-
1. Read `<session>/wisdom/anti-patterns/common-ux-pitfalls.md` if available
|
|
38
|
-
2. Use anti-patterns to identify known UX issues during scanning
|
|
39
|
-
3. Check `<session>/wisdom/patterns/ui-feedback.md` for expected feedback patterns
|
|
40
|
-
|
|
41
|
-
### Complex Analysis (use CLI)
|
|
42
|
-
|
|
43
|
-
For large projects with many components:
|
|
44
|
-
|
|
45
|
-
```
|
|
46
|
-
Bash(`ccw cli -p "PURPOSE: Discover all UI components with user interactions
|
|
47
|
-
CONTEXT: @<project-path>/**/*.tsx @<project-path>/**/*.vue
|
|
48
|
-
EXPECTED: Component list with interaction types (click, submit, input, select)
|
|
49
|
-
CONSTRAINTS: Focus on interactive components only" --tool gemini --mode analysis`)
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
## Phase 3: Component Scanning
|
|
53
|
-
|
|
54
|
-
Scan strategy:
|
|
55
|
-
|
|
56
|
-
| Category | Detection Pattern | Severity |
|
|
57
|
-
|----------|-------------------|----------|
|
|
58
|
-
| Unresponsive actions | onClick/\@click without async handling or error catching | High |
|
|
59
|
-
| Missing loading state | Form submit without isLoading/loading ref | High |
|
|
60
|
-
| State not refreshing | Array.splice/push without reactive reassignment | High |
|
|
61
|
-
| Missing error feedback | try/catch without error state or user notification | Medium |
|
|
62
|
-
| Missing success feedback | API call without success confirmation | Medium |
|
|
63
|
-
| No empty state | Data list without empty state placeholder | Low |
|
|
64
|
-
| Input without validation | Form input without validation rules | Low |
|
|
65
|
-
| Missing file selector | Text input for file/folder path without picker | Medium |
|
|
66
|
-
|
|
67
|
-
For each component file:
|
|
68
|
-
1. Read file content
|
|
69
|
-
2. Scan for interaction patterns using Grep
|
|
70
|
-
3. Check for feedback mechanisms (loading, error, success states)
|
|
71
|
-
4. Check state update patterns (mutation vs reactive)
|
|
72
|
-
5. Record issues with file:line references
|
|
73
|
-
|
|
74
|
-
## Phase 4: Issue Report Generation
|
|
75
|
-
|
|
76
|
-
1. Classify issues by severity (High/Medium/Low)
|
|
77
|
-
2. Group by category (unresponsive, missing feedback, state issues, input UX)
|
|
78
|
-
3. Generate structured report:
|
|
79
|
-
|
|
80
|
-
```markdown
|
|
81
|
-
# UI Scan Report
|
|
82
|
-
|
|
83
|
-
## Summary
|
|
84
|
-
- Total issues: <count>
|
|
85
|
-
- High: <count> | Medium: <count> | Low: <count>
|
|
86
|
-
|
|
87
|
-
## Issues
|
|
88
|
-
|
|
89
|
-
### High Severity
|
|
90
|
-
| # | File:Line | Component | Issue | Category |
|
|
91
|
-
|---|-----------|-----------|-------|----------|
|
|
92
|
-
| 1 | src/components/Upload.tsx:45 | UploadForm | No loading state on submit | Missing feedback |
|
|
93
|
-
|
|
94
|
-
### Medium Severity
|
|
95
|
-
...
|
|
96
|
-
|
|
97
|
-
### Low Severity
|
|
98
|
-
...
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
4. Write report to `<session>/artifacts/scan-report.md`
|
|
102
|
-
5. Share state via team_msg:
|
|
103
|
-
```
|
|
104
|
-
team_msg(operation="log", session_id=<session-id>, from="scanner",
|
|
105
|
-
type="state_update", data={
|
|
106
|
-
total_issues: <count>,
|
|
107
|
-
high: <count>, medium: <count>, low: <count>,
|
|
108
|
-
categories: [<category-list>],
|
|
109
|
-
scanned_files: <count>
|
|
110
|
-
})
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
### Wisdom Contribution
|
|
114
|
-
|
|
115
|
-
If novel UX issues discovered that aren't in anti-patterns:
|
|
116
|
-
1. Write findings to `<session>/wisdom/contributions/scanner-issues-<timestamp>.md`
|
|
117
|
-
2. Format: Issue description, detection criteria, affected components
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
prefix: TEST
|
|
3
|
-
inner_loop: false
|
|
4
|
-
message_types:
|
|
5
|
-
success: test_complete
|
|
6
|
-
error: error
|
|
7
|
-
fix: fix_required
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
# Test Engineer
|
|
11
|
-
|
|
12
|
-
Generate and run tests to verify fixes (loading states, error handling, state updates).
|
|
13
|
-
|
|
14
|
-
## Phase 2: Environment Detection
|
|
15
|
-
|
|
16
|
-
1. Detect test framework from project files:
|
|
17
|
-
|
|
18
|
-
| Signal | Framework |
|
|
19
|
-
|--------|-----------|
|
|
20
|
-
| package.json has "jest" | Jest |
|
|
21
|
-
| package.json has "vitest" | Vitest |
|
|
22
|
-
| package.json has "@testing-library/react" | React Testing Library |
|
|
23
|
-
| package.json has "@vue/test-utils" | Vue Test Utils |
|
|
24
|
-
|
|
25
|
-
2. Get changed files from implementer state:
|
|
26
|
-
```
|
|
27
|
-
team_msg(operation="get_state", session_id=<session-id>, role="implementer")
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
3. Load test strategy from design guide
|
|
31
|
-
|
|
32
|
-
### Wisdom Input
|
|
33
|
-
|
|
34
|
-
1. Read `<session>/wisdom/anti-patterns/common-ux-pitfalls.md` for common issues to test
|
|
35
|
-
2. Read `<session>/wisdom/patterns/ui-feedback.md` for expected feedback behaviors to verify
|
|
36
|
-
3. Use wisdom to design comprehensive test cases covering known edge cases
|
|
37
|
-
|
|
38
|
-
## Phase 3: Test Generation & Execution
|
|
39
|
-
|
|
40
|
-
### Test Generation
|
|
41
|
-
|
|
42
|
-
For each modified file, generate test cases:
|
|
43
|
-
|
|
44
|
-
**React Example**:
|
|
45
|
-
```typescript
|
|
46
|
-
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
|
47
|
-
import Upload from '../Upload';
|
|
48
|
-
|
|
49
|
-
describe('Upload Component', () => {
|
|
50
|
-
it('shows loading state during upload', async () => {
|
|
51
|
-
global.fetch = vi.fn(() => Promise.resolve({ ok: true }));
|
|
52
|
-
|
|
53
|
-
render(<Upload />);
|
|
54
|
-
const uploadButton = screen.getByRole('button', { name: /upload/i });
|
|
55
|
-
|
|
56
|
-
fireEvent.click(uploadButton);
|
|
57
|
-
|
|
58
|
-
// Check loading state
|
|
59
|
-
await waitFor(() => {
|
|
60
|
-
expect(screen.getByText(/uploading.../i)).toBeInTheDocument();
|
|
61
|
-
expect(uploadButton).toBeDisabled();
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
// Check normal state restored
|
|
65
|
-
await waitFor(() => {
|
|
66
|
-
expect(uploadButton).not.toBeDisabled();
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it('displays error message on failure', async () => {
|
|
71
|
-
global.fetch = vi.fn(() => Promise.reject(new Error('Upload failed')));
|
|
72
|
-
|
|
73
|
-
render(<Upload />);
|
|
74
|
-
fireEvent.click(screen.getByRole('button', { name: /upload/i }));
|
|
75
|
-
|
|
76
|
-
await waitFor(() => {
|
|
77
|
-
expect(screen.getByText(/upload failed/i)).toBeInTheDocument();
|
|
78
|
-
});
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
### Test Execution
|
|
84
|
-
|
|
85
|
-
Iterative test-fix cycle (max 5 iterations):
|
|
86
|
-
|
|
87
|
-
1. Run tests: `npm test` or `npm run test:unit`
|
|
88
|
-
2. Parse results -> calculate pass rate
|
|
89
|
-
3. If pass rate >= 95% -> exit (success)
|
|
90
|
-
4. If pass rate < 95% and iterations < 5:
|
|
91
|
-
- Analyze failures
|
|
92
|
-
- Use CLI to generate fixes:
|
|
93
|
-
```
|
|
94
|
-
Bash(`ccw cli -p "PURPOSE: Fix test failures
|
|
95
|
-
CONTEXT: @<test-file> @<source-file>
|
|
96
|
-
EXPECTED: Fixed code that passes tests
|
|
97
|
-
CONSTRAINTS: Maintain existing functionality" --tool gemini --mode write`)
|
|
98
|
-
```
|
|
99
|
-
- Increment iteration counter
|
|
100
|
-
- Loop to step 1
|
|
101
|
-
5. If iterations >= 5 -> send fix_required message
|
|
102
|
-
|
|
103
|
-
## Phase 4: Test Report
|
|
104
|
-
|
|
105
|
-
### Wisdom Contribution
|
|
106
|
-
|
|
107
|
-
If new edge cases or test patterns discovered:
|
|
108
|
-
1. Write test findings to `<session>/wisdom/contributions/tester-edge-cases-<timestamp>.md`
|
|
109
|
-
2. Format: Edge case description, test scenario, expected behavior, actual behavior
|
|
110
|
-
|
|
111
|
-
Generate test report:
|
|
112
|
-
|
|
113
|
-
```markdown
|
|
114
|
-
# Test Report
|
|
115
|
-
|
|
116
|
-
## Summary
|
|
117
|
-
- Total tests: <count>
|
|
118
|
-
- Passed: <count>
|
|
119
|
-
- Failed: <count>
|
|
120
|
-
- Pass rate: <percentage>%
|
|
121
|
-
- Fix iterations: <count>
|
|
122
|
-
|
|
123
|
-
## Test Results
|
|
124
|
-
|
|
125
|
-
### Passed Tests
|
|
126
|
-
- ✅ Upload Component > shows loading state during upload
|
|
127
|
-
- ✅ Upload Component > displays error message on failure
|
|
128
|
-
|
|
129
|
-
### Failed Tests
|
|
130
|
-
- ❌ Form Component > validates input before submit
|
|
131
|
-
- Error: Expected validation message not found
|
|
132
|
-
|
|
133
|
-
## Coverage
|
|
134
|
-
- Statements: 85%
|
|
135
|
-
- Branches: 78%
|
|
136
|
-
- Functions: 90%
|
|
137
|
-
- Lines: 84%
|
|
138
|
-
|
|
139
|
-
## Remaining Issues
|
|
140
|
-
- Form validation test failing (needs manual review)
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
Write report to `<session>/artifacts/test-report.md`
|
|
144
|
-
|
|
145
|
-
Share state via team_msg:
|
|
146
|
-
```
|
|
147
|
-
team_msg(operation="log", session_id=<session-id>, from="tester",
|
|
148
|
-
type="state_update", data={
|
|
149
|
-
total_tests: <count>,
|
|
150
|
-
passed: <count>,
|
|
151
|
-
failed: <count>,
|
|
152
|
-
pass_rate: <percentage>,
|
|
153
|
-
fix_iterations: <count>
|
|
154
|
-
})
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
If pass rate < 95%, send fix_required message:
|
|
158
|
-
```
|
|
159
|
-
SendMessage({
|
|
160
|
-
to: "coordinator",
|
|
161
|
-
message: "[tester] Test validation incomplete. Pass rate: <percentage>%. Manual review needed."
|
|
162
|
-
})
|
|
163
|
-
```
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{ab as M,aF as A,aH as I,ga as b,u as C,r as j,a9 as z,aa as W,j as e,B as w,C as _,ai as O,aj as L,e as h,bq as V,am as Z,R as Y,a as S,N as y,an as T,dh as $,dg as G,T as J,I as X,a7 as ee,cJ as se,b as ne}from"./index-B6I7GQC5.js";import{T as te}from"./TabsNavigation-drSnu5jn.js";import{S as ae}from"./save-BFa03OnG.js";import{E as le}from"./eye-off-CGRUVRDR.js";import{E as ie}from"./eye-DUy7aLEx.js";const N={all:["codexLens"],models:()=>[...N.all,"models"],indexStatus:s=>[...N.all,"indexStatus",s],env:()=>[...N.all,"env"],mcpConfig:()=>[...N.all,"mcpConfig"]};function de(){return M({queryKey:N.models(),queryFn:()=>b("/api/codexlens/models").then(s=>s.models),staleTime:3e4})}function ce(){const s=A(),n=I({mutationFn:t=>b("/api/codexlens/models/download",{method:"POST",body:JSON.stringify({name:t})}),onSuccess:()=>{s.invalidateQueries({queryKey:N.models()})}});return{downloadModel:n.mutateAsync,isDownloading:n.isPending,error:n.error}}function oe(){const s=A(),n=I({mutationFn:t=>b("/api/codexlens/models/delete",{method:"POST",body:JSON.stringify({name:t})}),onSuccess:()=>{s.invalidateQueries({queryKey:N.models()})}});return{deleteModel:n.mutateAsync,isDeleting:n.isPending,error:n.error}}function re(s){return M({queryKey:N.indexStatus(s),queryFn:()=>b(`/api/codexlens/index/status?projectPath=${encodeURIComponent(s)}`).then(n=>n.status),enabled:!!s,staleTime:1e4})}function me(){const s=I({mutationFn:n=>b("/api/codexlens/index/sync",{method:"POST",body:JSON.stringify({projectPath:n})})});return{syncIndex:s.mutateAsync,isSyncing:s.isPending,error:s.error}}function xe(){const s=I({mutationFn:n=>b("/api/codexlens/index/rebuild",{method:"POST",body:JSON.stringify({projectPath:n})})});return{rebuildIndex:s.mutateAsync,isRebuilding:s.isPending,error:s.error}}function K(){return M({queryKey:N.env(),queryFn:()=>b("/api/codexlens/env").then(s=>({values:s.env??{},defaults:s.defaults??{}})),staleTime:6e4})}function ue(){const s=A(),n=I({mutationFn:t=>b("/api/codexlens/env",{method:"POST",body:JSON.stringify({env:t})}),onSuccess:()=>{s.invalidateQueries({queryKey:N.env()}),s.invalidateQueries({queryKey:N.mcpConfig()})}});return{saveEnv:n.mutateAsync,isSaving:n.isPending,error:n.error}}function Ee(){return M({queryKey:N.mcpConfig(),queryFn:()=>b("/api/codexlens/mcp-config").then(s=>s.config),staleTime:3e4})}function pe(){const{formatMessage:s}=C(),{data:n,isLoading:t,isError:i,refetch:o}=Ee(),{data:l}=K(),[x,u]=j.useState(!1),[r,a]=j.useState(!1),[c,E]=j.useState(null),p=z(W),D=async g=>{a(!0),E(null);try{const v=n==null?void 0:n.mcpServers,P=v&&typeof v=="object"?v.codexlens:void 0;if(!P||typeof P!="object")throw new Error(s({id:"codexlens.mcp.noConfig"}));const F=P;if(g==="project"){if(!p)throw new Error(s({id:"codexlens.mcp.installError"}));await $("codexlens",F,p)}else await G("codexlens",F);E({ok:!0,msg:s({id:"codexlens.mcp.installSuccess"})})}catch(v){E({ok:!1,msg:v.message})}finally{a(!1)}},k=!!(l!=null&&l.values.CODEXLENS_EMBED_API_URL),R=k?"API":"Local fastembed",m=n?JSON.stringify(n,null,2):"",f=()=>{navigator.clipboard.writeText(m).then(()=>{u(!0),setTimeout(()=>u(!1),2e3)})},d=()=>{o()};return e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("span",{className:"text-sm text-muted-foreground",children:[s({id:"codexlens.mcp.embedMode"}),":"]}),e.jsx(w,{variant:k?"success":"secondary",children:R})]}),e.jsxs(_,{children:[e.jsx(O,{className:"pb-3",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx(L,{className:"text-base",children:s({id:"codexlens.mcp.configTitle"})}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs(h,{variant:"outline",size:"sm",onClick:f,disabled:!m||t,children:[x?e.jsx(V,{className:"w-4 h-4 mr-1"}):e.jsx(Z,{className:"w-4 h-4 mr-1"}),s(x?{id:"codexlens.mcp.copied"}:{id:"codexlens.mcp.copy"})]}),e.jsxs(h,{variant:"outline",size:"sm",onClick:d,disabled:t,children:[e.jsx(Y,{className:`w-4 h-4 mr-1 ${t?"animate-spin":""}`}),s({id:"codexlens.mcp.regenerate"})]})]})]})}),e.jsxs(S,{children:[t&&e.jsx("p",{className:"text-sm text-muted-foreground",children:s({id:"codexlens.mcp.loading"})}),i&&e.jsx("p",{className:"text-sm text-destructive",children:s({id:"codexlens.mcp.error"})}),!t&&!i&&e.jsx("pre",{className:"bg-muted rounded-md p-4 text-xs overflow-auto max-h-96 font-mono",children:m||s({id:"codexlens.mcp.noConfig"})})]})]}),e.jsxs(_,{children:[e.jsxs(O,{className:"pb-3",children:[e.jsx(L,{className:"text-base",children:s({id:"codexlens.mcp.quickInstallTitle"})}),e.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:s({id:"codexlens.mcp.quickInstallDesc"})})]}),e.jsxs(S,{className:"space-y-3",children:[e.jsxs("div",{className:"flex gap-2 flex-wrap",children:[e.jsxs(h,{variant:"outline",size:"sm",onClick:()=>D("project"),disabled:r||!p,children:[r?e.jsx(y,{className:"w-4 h-4 mr-1 animate-spin"}):e.jsx(T,{className:"w-4 h-4 mr-1"}),s(r?{id:"codexlens.mcp.installing"}:{id:"codexlens.mcp.installProject"})]}),e.jsxs(h,{variant:"outline",size:"sm",onClick:()=>D("global"),disabled:r,children:[r?e.jsx(y,{className:"w-4 h-4 mr-1 animate-spin"}):e.jsx(T,{className:"w-4 h-4 mr-1"}),s(r?{id:"codexlens.mcp.installing"}:{id:"codexlens.mcp.installGlobal"})]})]}),c&&e.jsx("p",{className:`text-sm ${c.ok?"text-success":"text-destructive"}`,children:c.msg})]})]}),e.jsxs(_,{children:[e.jsx(O,{className:"pb-3",children:e.jsx(L,{className:"text-base",children:s({id:"codexlens.mcp.installTitle"})})}),e.jsx(S,{children:e.jsxs("ol",{className:"list-decimal list-inside space-y-2 text-sm text-muted-foreground",children:[e.jsx("li",{children:s({id:"codexlens.mcp.installSteps.step1"})}),e.jsx("li",{children:s({id:"codexlens.mcp.installSteps.step2"})}),e.jsx("li",{children:s({id:"codexlens.mcp.installSteps.step3"})}),e.jsx("li",{children:s({id:"codexlens.mcp.installSteps.step4"})}),e.jsx("li",{children:s({id:"codexlens.mcp.installSteps.step5"})})]})})]})]})}function he(){const{formatMessage:s}=C(),{data:n,isLoading:t,isError:i}=de(),{data:o}=K(),{downloadModel:l,isDownloading:x}=ce(),{deleteModel:u,isDeleting:r}=oe(),a=!!(o!=null&&o.values.CODEXLENS_EMBED_API_URL),c=a?"API":"Local fastembed",E=n??[];return e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-2 p-3 rounded-md bg-muted text-sm",children:[e.jsxs("span",{className:"text-muted-foreground",children:[s({id:"codexlens.models.embedMode"}),":"]}),e.jsx(w,{variant:a?"success":"secondary",children:c})]}),t&&e.jsxs("div",{className:"flex items-center gap-2 text-sm text-muted-foreground p-4",children:[e.jsx(y,{className:"w-4 h-4 animate-spin"}),s({id:"codexlens.models.loading"})]}),i&&e.jsx("p",{className:"text-sm text-destructive p-4",children:s({id:"codexlens.models.error"})}),!t&&!i&&E.length===0&&e.jsx("p",{className:"text-sm text-muted-foreground p-4",children:s({id:"codexlens.models.noModels"})}),!t&&!i&&E.length>0&&e.jsx(_,{children:e.jsx(S,{className:"p-0",children:e.jsx("div",{className:"divide-y divide-border",children:E.map(p=>e.jsxs("div",{className:"flex items-center justify-between px-4 py-3",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("span",{className:"text-sm font-medium",children:p.name}),e.jsx(w,{variant:p.installed?"success":"secondary",children:p.installed?s({id:"codexlens.models.installed"}):s({id:"codexlens.models.notInstalled"})})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs(h,{variant:"outline",size:"sm",onClick:()=>l(p.name),disabled:x,children:[x?e.jsx(y,{className:"w-4 h-4 animate-spin"}):e.jsx(T,{className:"w-4 h-4"}),e.jsx("span",{className:"ml-1",children:s({id:"codexlens.models.download"})})]}),e.jsxs(h,{variant:"outline",size:"sm",onClick:()=>u(p.name),disabled:!p.installed||r,children:[r?e.jsx(y,{className:"w-4 h-4 animate-spin"}):e.jsx(J,{className:"w-4 h-4"}),e.jsx("span",{className:"ml-1",children:s({id:"codexlens.models.delete"})})]})]})]},p.name))})})})]})}function Ne({projectPath:s}){const{formatMessage:n}=C(),t=A(),{data:i,isLoading:o,isError:l}=re(s),{syncIndex:x,isSyncing:u}=me(),{rebuildIndex:r,isRebuilding:a}=xe(),c=i,E=()=>{t.invalidateQueries({queryKey:N.indexStatus(s)})};return e.jsxs(_,{children:[e.jsx(O,{className:"pb-3",children:e.jsx(L,{className:"text-sm font-medium truncate",children:s})}),e.jsxs(S,{className:"space-y-4",children:[o&&e.jsxs("div",{className:"flex items-center gap-2 text-sm text-muted-foreground",children:[e.jsx(y,{className:"w-4 h-4 animate-spin"}),n({id:"codexlens.index.loading"})]}),l&&e.jsx("p",{className:"text-sm text-destructive",children:n({id:"codexlens.index.error"})}),!o&&!l&&c&&e.jsxs("div",{className:"grid grid-cols-3 gap-3",children:[e.jsxs("div",{className:"text-center",children:[e.jsx("p",{className:"text-lg font-semibold",children:c.files_tracked??0}),e.jsx("p",{className:"text-xs text-muted-foreground",children:n({id:"codexlens.index.filesTracked"})})]}),e.jsxs("div",{className:"text-center",children:[e.jsx("p",{className:"text-lg font-semibold",children:c.total_chunks??0}),e.jsx("p",{className:"text-xs text-muted-foreground",children:n({id:"codexlens.index.totalChunks"})})]}),e.jsxs("div",{className:"text-center",children:[e.jsx("p",{className:"text-lg font-semibold",children:c.deleted_chunks??0}),e.jsx("p",{className:"text-xs text-muted-foreground",children:n({id:"codexlens.index.deletedChunks"})})]})]}),e.jsxs("div",{className:"flex gap-2 flex-wrap",children:[e.jsxs(h,{variant:"outline",size:"sm",onClick:()=>x(s),disabled:u,children:[u?e.jsx(y,{className:"w-4 h-4 animate-spin mr-1"}):null,n({id:"codexlens.index.sync"})]}),e.jsxs(h,{variant:"outline",size:"sm",onClick:()=>r(s),disabled:a,children:[a?e.jsx(y,{className:"w-4 h-4 animate-spin mr-1"}):null,n({id:"codexlens.index.rebuild"})]}),e.jsxs(h,{variant:"outline",size:"sm",onClick:E,children:[e.jsx(Y,{className:"w-4 h-4 mr-1"}),n({id:"codexlens.index.refresh"})]})]})]})]})}function fe(){const{formatMessage:s}=C(),n=z(W),[t,i]=j.useState([]),[o,l]=j.useState("");j.useEffect(()=>{n&&i(a=>a.includes(n)?a:[n,...a])},[n]);const x=()=>{const a=o.trim();a&&!t.includes(a)&&i(c=>[...c,a]),l("")},u=a=>{i(c=>c.filter(E=>E!==a))},r=a=>{a.key==="Enter"&&x()};return e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex gap-2",children:[e.jsx(X,{placeholder:s({id:"codexlens.index.pathPlaceholder"}),value:o,onChange:a=>l(a.target.value),onKeyDown:r,className:"flex-1"}),e.jsxs(h,{onClick:x,disabled:!o.trim(),children:[e.jsx(ee,{className:"w-4 h-4 mr-1"}),s({id:"codexlens.index.add"})]})]}),t.length===0&&e.jsx("p",{className:"text-sm text-muted-foreground",children:s({id:"codexlens.index.empty"})}),t.map(a=>e.jsxs("div",{className:"relative",children:[e.jsx(h,{variant:"ghost",size:"sm",className:"absolute top-2 right-2 z-10 h-7 w-7 p-0",onClick:()=>u(a),title:s({id:"codexlens.index.removeProject"}),children:e.jsx(J,{className:"w-4 h-4 text-muted-foreground"})}),e.jsx(Ne,{projectPath:a})]},a))]})}const Q=[{title:"embed",fields:[{key:"CODEXLENS_EMBED_API_URL",label:"Embed API URL"},{key:"CODEXLENS_EMBED_API_KEY",label:"Embed API Key",sensitive:!0},{key:"CODEXLENS_EMBED_API_MODEL",label:"Embed API Model"},{key:"CODEXLENS_EMBED_DIM",label:"Embed Dimension"},{key:"CODEXLENS_EMBED_API_ENDPOINTS",label:"Embed API Endpoints",sensitive:!0},{key:"CODEXLENS_EMBED_BATCH_SIZE",label:"Embed Batch Size"},{key:"CODEXLENS_EMBED_API_CONCURRENCY",label:"Embed API Concurrency"}]},{title:"reranker",fields:[{key:"CODEXLENS_RERANKER_API_URL",label:"Reranker API URL"},{key:"CODEXLENS_RERANKER_API_KEY",label:"Reranker API Key",sensitive:!0},{key:"CODEXLENS_RERANKER_API_MODEL",label:"Reranker API Model"}]},{title:"performance",fields:[{key:"CODEXLENS_BINARY_TOP_K",label:"Binary Top K"},{key:"CODEXLENS_ANN_TOP_K",label:"ANN Top K"},{key:"CODEXLENS_FTS_TOP_K",label:"FTS Top K"},{key:"CODEXLENS_FUSION_K",label:"Fusion K"},{key:"CODEXLENS_RERANKER_TOP_K",label:"Reranker Top K"},{key:"CODEXLENS_RERANKER_BATCH_SIZE",label:"Reranker Batch Size"}]},{title:"index",fields:[{key:"CODEXLENS_DB_PATH",label:"DB Path"},{key:"CODEXLENS_INDEX_WORKERS",label:"Index Workers"},{key:"CODEXLENS_CODE_AWARE_CHUNKING",label:"Code Aware Chunking"},{key:"CODEXLENS_MAX_FILE_SIZE",label:"Max File Size"},{key:"CODEXLENS_HNSW_EF",label:"HNSW EF"},{key:"CODEXLENS_HNSW_M",label:"HNSW M"}]}],je=new Set(["CODEXLENS_EMBED_API_URL","CODEXLENS_EMBED_API_KEY","CODEXLENS_EMBED_API_ENDPOINTS","CODEXLENS_EMBED_API_CONCURRENCY"]),q={CODEXLENS_EMBED_API_MODEL:"text-embedding-3-small",CODEXLENS_EMBED_DIM:"1536",CODEXLENS_EMBED_BATCH_SIZE:"64",CODEXLENS_EMBED_API_CONCURRENCY:"4",CODEXLENS_BINARY_TOP_K:"200",CODEXLENS_ANN_TOP_K:"50",CODEXLENS_FTS_TOP_K:"50",CODEXLENS_FUSION_K:"60",CODEXLENS_RERANKER_TOP_K:"20",CODEXLENS_RERANKER_BATCH_SIZE:"32",CODEXLENS_INDEX_WORKERS:"2",CODEXLENS_CODE_AWARE_CHUNKING:"true",CODEXLENS_MAX_FILE_SIZE:"1000000",CODEXLENS_HNSW_EF:"150",CODEXLENS_HNSW_M:"32"},B=Q.flatMap(s=>s.fields.map(n=>n.key));function U(){return Object.fromEntries(B.map(s=>[s,""]))}function H(s,n){return Object.fromEntries(B.map(t=>[t,s[t]??n[t]??""]))}function ge({value:s,onChange:n,id:t}){const[i,o]=j.useState(!1);return e.jsxs("div",{className:"relative",children:[e.jsx(X,{id:t,type:i?"text":"password",value:s,onChange:l=>n(l.target.value),className:"pr-10"}),e.jsx("button",{type:"button",className:"absolute inset-y-0 right-2 flex items-center text-muted-foreground hover:text-foreground",onClick:()=>o(l=>!l),tabIndex:-1,children:i?e.jsx(le,{className:"w-4 h-4"}):e.jsx(ie,{className:"w-4 h-4"})})]})}function be(){const{formatMessage:s}=C(),{data:n,isLoading:t}=K(),{saveEnv:i,isSaving:o}=ue(),[l,x]=j.useState("local"),[u,r]=j.useState(U),a=(n==null?void 0:n.values)??{},c={...q,...(n==null?void 0:n.defaults)??{}},E=H(a,c);j.useEffect(()=>{if(n){const m={...q,...n.defaults??{}},f=n.values??{};r(H(f,m)),f.CODEXLENS_EMBED_API_URL&&x("api")}},[n]);const p=B.some(m=>u[m]!==(E[m]??"")),D=(m,f)=>{r(d=>({...d,[m]:f}))},k=async()=>{const m=Object.fromEntries(Object.entries(u).flatMap(([f,d])=>{const g=d.trim(),v=c[f]??"";return!g||g===v?[]:[[f,g]]}));await i(m)},R=()=>{r(U())};return t?e.jsx("p",{className:"text-sm text-muted-foreground p-4",children:s({id:"codexlens.env.loading"})}):e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("span",{className:"text-sm font-medium",children:[s({id:"codexlens.env.mode"}),":"]}),e.jsxs("div",{className:"flex rounded-md border border-border overflow-hidden",children:[e.jsx("button",{type:"button",onClick:()=>x("local"),className:`px-3 py-1.5 text-sm transition-colors ${l==="local"?"bg-primary text-primary-foreground":"bg-background text-muted-foreground hover:bg-muted"}`,children:s({id:"codexlens.env.localMode"})}),e.jsx("button",{type:"button",onClick:()=>x("api"),className:`px-3 py-1.5 text-sm transition-colors ${l==="api"?"bg-primary text-primary-foreground":"bg-background text-muted-foreground hover:bg-muted"}`,children:s({id:"codexlens.env.apiMode"})})]}),e.jsx("span",{className:"text-xs text-muted-foreground",children:s(l==="local"?{id:"codexlens.env.localModeDesc"}:{id:"codexlens.env.apiModeDesc"})})]}),Q.map(m=>{const f=l==="local"?m.fields.filter(d=>!je.has(d.key)):m.fields;return f.length===0?null:e.jsxs(_,{children:[e.jsx(O,{className:"pb-3",children:e.jsx(L,{className:"text-base",children:s({id:`codexlens.env.sections.${m.title}`})})}),e.jsx(S,{className:"space-y-3",children:f.map(d=>e.jsxs("div",{className:"grid grid-cols-3 gap-3 items-center",children:[e.jsx("label",{htmlFor:d.key,className:"text-sm text-muted-foreground col-span-1",children:d.label}),e.jsx("div",{className:"col-span-2",children:d.sensitive?e.jsx(ge,{id:d.key,value:u[d.key]??"",onChange:g=>D(d.key,g)}):e.jsx(X,{id:d.key,value:u[d.key]??"",placeholder:c[d.key]??"",onChange:g=>D(d.key,g.target.value)})})]},d.key))})]},m.title)}),e.jsxs("div",{className:"flex justify-between pt-2",children:[e.jsxs(h,{variant:"outline",onClick:R,children:[e.jsx(se,{className:"w-4 h-4 mr-2"}),s({id:"codexlens.env.clearForm"})]}),e.jsxs(h,{onClick:k,disabled:!p||o,children:[e.jsx(ae,{className:"w-4 h-4 mr-2"}),s(o?{id:"codexlens.env.saving"}:{id:"codexlens.env.save"})]})]})]})}function De(){const{formatMessage:s}=C(),[n,t]=j.useState("mcp");return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{children:[e.jsxs("h1",{className:"text-2xl font-bold text-foreground flex items-center gap-2",children:[e.jsx(ne,{className:"w-6 h-6 text-primary"}),s({id:"codexlens.page.title"})]}),e.jsx("p",{className:"text-muted-foreground mt-1",children:s({id:"codexlens.page.description"})})]}),e.jsx(te,{value:n,onValueChange:i=>t(i),tabs:[{value:"mcp",label:s({id:"codexlens.tabs.mcp"})},{value:"models",label:s({id:"codexlens.tabs.models"})},{value:"index",label:s({id:"codexlens.tabs.index"})},{value:"env",label:s({id:"codexlens.tabs.env"})}]}),e.jsxs("div",{className:"mt-4",children:[n==="mcp"&&e.jsx(pe,{}),n==="models"&&e.jsx(he,{}),n==="index"&&e.jsx(fe,{}),n==="env"&&e.jsx(be,{})]})]})}export{De as CodexLensPage,De as default};
|
|
2
|
-
//# sourceMappingURL=CodexLensPage-My6DnfN6.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"CodexLensPage-My6DnfN6.js","sources":["../../src/hooks/useCodexLens.ts","../../src/components/codexlens/McpConfigTab.tsx","../../src/components/codexlens/ModelManagerTab.tsx","../../src/components/codexlens/IndexManagerTab.tsx","../../src/components/codexlens/EnvSettingsTab.tsx","../../src/pages/CodexLensPage.tsx"],"sourcesContent":["// ========================================\n// useCodexLens Hook\n// ========================================\n// TanStack Query hooks for CodexLens v2 API management\n\nimport { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';\nimport { fetchApi } from '@/lib/api';\n\n// ========================================\n// Domain types (exported for component use)\n// ========================================\n\nexport interface ModelEntry {\n name: string;\n installed: boolean;\n type?: string;\n cache_path?: string;\n}\n\nexport interface IndexStatusData {\n status?: string;\n files_tracked?: number;\n total_chunks?: number;\n deleted_chunks?: number;\n db_path?: string;\n}\n\nexport type McpConfigData = Record<string, unknown>;\nexport interface CodexLensEnvData {\n values: Record<string, string>;\n defaults: Record<string, string>;\n}\n\n// Internal API response wrappers\ninterface ModelsResponse { success: boolean; models: ModelEntry[] }\ninterface IndexStatusResponse { success: boolean; status: IndexStatusData }\ninterface EnvResponse {\n success: boolean;\n env: Record<string, string>;\n defaults?: Record<string, string>;\n}\ninterface McpConfigResponse { success: boolean; config: McpConfigData }\n\n// ========================================\n// Query Key Factory\n// ========================================\n\nexport const codexLensKeys = {\n all: ['codexLens'] as const,\n models: () => [...codexLensKeys.all, 'models'] as const,\n indexStatus: (path: string) => [...codexLensKeys.all, 'indexStatus', path] as const,\n env: () => [...codexLensKeys.all, 'env'] as const,\n mcpConfig: () => [...codexLensKeys.all, 'mcpConfig'] as const,\n};\n\n// ========================================\n// Models Hooks\n// ========================================\n\nexport function useCodexLensModels() {\n return useQuery({\n queryKey: codexLensKeys.models(),\n queryFn: () => fetchApi<ModelsResponse>('/api/codexlens/models').then(r => r.models),\n staleTime: 30_000,\n });\n}\n\nexport function useDownloadModel() {\n const queryClient = useQueryClient();\n\n const mutation = useMutation({\n mutationFn: (modelName: string) =>\n fetchApi<{ success: boolean }>('/api/codexlens/models/download', {\n method: 'POST',\n body: JSON.stringify({ name: modelName }),\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: codexLensKeys.models() });\n },\n });\n\n return {\n downloadModel: mutation.mutateAsync,\n isDownloading: mutation.isPending,\n error: mutation.error,\n };\n}\n\nexport function useDeleteModel() {\n const queryClient = useQueryClient();\n\n const mutation = useMutation({\n mutationFn: (modelName: string) =>\n fetchApi<{ success: boolean }>('/api/codexlens/models/delete', {\n method: 'POST',\n body: JSON.stringify({ name: modelName }),\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: codexLensKeys.models() });\n },\n });\n\n return {\n deleteModel: mutation.mutateAsync,\n isDeleting: mutation.isPending,\n error: mutation.error,\n };\n}\n\n// ========================================\n// Index Hooks\n// ========================================\n\nexport function useIndexStatus(projectPath: string) {\n return useQuery({\n queryKey: codexLensKeys.indexStatus(projectPath),\n queryFn: () =>\n fetchApi<IndexStatusResponse>(\n `/api/codexlens/index/status?projectPath=${encodeURIComponent(projectPath)}`\n ).then(r => r.status),\n enabled: !!projectPath,\n staleTime: 10_000,\n });\n}\n\nexport function useSyncIndex() {\n const mutation = useMutation({\n mutationFn: (projectPath: string) =>\n fetchApi<{ success: boolean }>('/api/codexlens/index/sync', {\n method: 'POST',\n body: JSON.stringify({ projectPath }),\n }),\n });\n\n return {\n syncIndex: mutation.mutateAsync,\n isSyncing: mutation.isPending,\n error: mutation.error,\n };\n}\n\nexport function useRebuildIndex() {\n const mutation = useMutation({\n mutationFn: (projectPath: string) =>\n fetchApi<{ success: boolean }>('/api/codexlens/index/rebuild', {\n method: 'POST',\n body: JSON.stringify({ projectPath }),\n }),\n });\n\n return {\n rebuildIndex: mutation.mutateAsync,\n isRebuilding: mutation.isPending,\n error: mutation.error,\n };\n}\n\n// ========================================\n// Env Hooks\n// ========================================\n\nexport function useCodexLensEnv() {\n return useQuery({\n queryKey: codexLensKeys.env(),\n queryFn: () =>\n fetchApi<EnvResponse>('/api/codexlens/env').then((r): CodexLensEnvData => ({\n values: r.env ?? {},\n defaults: r.defaults ?? {},\n })),\n staleTime: 60_000,\n });\n}\n\nexport function useSaveCodexLensEnv() {\n const queryClient = useQueryClient();\n\n const mutation = useMutation({\n mutationFn: (env: Record<string, string>) =>\n fetchApi<{ success: boolean }>('/api/codexlens/env', {\n method: 'POST',\n body: JSON.stringify({ env }),\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: codexLensKeys.env() });\n queryClient.invalidateQueries({ queryKey: codexLensKeys.mcpConfig() });\n },\n });\n\n return {\n saveEnv: mutation.mutateAsync,\n isSaving: mutation.isPending,\n error: mutation.error,\n };\n}\n\n// ========================================\n// MCP Config Hooks\n// ========================================\n\nexport function useCodexLensMcpConfig() {\n return useQuery({\n queryKey: codexLensKeys.mcpConfig(),\n queryFn: () => fetchApi<McpConfigResponse>('/api/codexlens/mcp-config').then(r => r.config),\n staleTime: 30_000,\n });\n}\n","// ========================================\r\n// McpConfigTab Component\r\n// ========================================\r\n// Read-only MCP config JSON display with copy-to-clipboard and regenerate\r\n\r\nimport { useState } from 'react';\r\nimport { useIntl } from 'react-intl';\r\nimport { Copy, RefreshCw, Check, Download, Loader2 } from 'lucide-react';\nimport { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/Card';\nimport { Button } from '@/components/ui/Button';\nimport { Badge } from '@/components/ui/Badge';\nimport { useCodexLensMcpConfig, useCodexLensEnv } from '@/hooks/useCodexLens';\nimport { addGlobalMcpServer, copyMcpServerToProject } from '@/lib/api';\nimport { useWorkflowStore, selectProjectPath } from '@/stores/workflowStore';\n\r\nexport function McpConfigTab() {\r\n const { formatMessage } = useIntl();\r\n const { data: mcpConfig, isLoading, isError, refetch } = useCodexLensMcpConfig();\r\n const { data: envData } = useCodexLensEnv();\r\n const [copied, setCopied] = useState(false);\r\n const [installing, setInstalling] = useState(false);\r\n const [installResult, setInstallResult] = useState<{ ok: boolean; msg: string } | null>(null);\r\n const projectPath = useWorkflowStore(selectProjectPath);\r\n\r\n const handleInstall = async (scope: 'global' | 'project') => {\n setInstalling(true);\n setInstallResult(null);\n try {\n const mcpServers = mcpConfig?.['mcpServers'];\n const serverConfig = mcpServers && typeof mcpServers === 'object'\n ? (mcpServers as Record<string, unknown>).codexlens\n : undefined;\n\n if (!serverConfig || typeof serverConfig !== 'object') {\n throw new Error(formatMessage({ id: 'codexlens.mcp.noConfig' }));\n }\n\n const typedConfig = serverConfig as {\n command: string;\n args?: string[];\n env?: Record<string, string>;\n type?: string;\n };\n\n if (scope === 'project') {\n if (!projectPath) {\n throw new Error(formatMessage({ id: 'codexlens.mcp.installError' }));\n }\n await copyMcpServerToProject('codexlens', typedConfig, projectPath);\n } else {\n await addGlobalMcpServer('codexlens', typedConfig);\n }\n\n setInstallResult({\n ok: true,\n msg: formatMessage({ id: 'codexlens.mcp.installSuccess' }),\n });\n } catch (err) {\n setInstallResult({ ok: false, msg: (err as Error).message });\n } finally {\n setInstalling(false);\n }\n };\n\n const hasApiUrl = !!(envData?.values.CODEXLENS_EMBED_API_URL);\n const embedMode = hasApiUrl ? 'API' : 'Local fastembed';\r\n\r\n const configJson = mcpConfig ? JSON.stringify(mcpConfig, null, 2) : '';\r\n\r\n const handleCopy = () => {\r\n navigator.clipboard.writeText(configJson).then(() => {\r\n setCopied(true);\r\n setTimeout(() => setCopied(false), 2000);\r\n });\r\n };\r\n\r\n const handleRegenerate = () => {\r\n refetch();\r\n };\r\n\r\n return (\r\n <div className=\"space-y-4\">\r\n {/* Embed mode badge */}\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-sm text-muted-foreground\">{formatMessage({ id: 'codexlens.mcp.embedMode' })}:</span>\r\n <Badge variant={hasApiUrl ? 'success' : 'secondary'}>\r\n {embedMode}\r\n </Badge>\r\n </div>\r\n\r\n {/* Config JSON block */}\r\n <Card>\r\n <CardHeader className=\"pb-3\">\r\n <div className=\"flex items-center justify-between\">\r\n <CardTitle className=\"text-base\">{formatMessage({ id: 'codexlens.mcp.configTitle' })}</CardTitle>\r\n <div className=\"flex gap-2\">\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n onClick={handleCopy}\r\n disabled={!configJson || isLoading}\r\n >\r\n {copied ? <Check className=\"w-4 h-4 mr-1\" /> : <Copy className=\"w-4 h-4 mr-1\" />}\r\n {copied ? formatMessage({ id: 'codexlens.mcp.copied' }) : formatMessage({ id: 'codexlens.mcp.copy' })}\r\n </Button>\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n onClick={handleRegenerate}\r\n disabled={isLoading}\r\n >\r\n <RefreshCw className={`w-4 h-4 mr-1 ${isLoading ? 'animate-spin' : ''}`} />\r\n {formatMessage({ id: 'codexlens.mcp.regenerate' })}\r\n </Button>\r\n </div>\r\n </div>\r\n </CardHeader>\r\n <CardContent>\r\n {isLoading && (\r\n <p className=\"text-sm text-muted-foreground\">{formatMessage({ id: 'codexlens.mcp.loading' })}</p>\r\n )}\r\n {isError && (\r\n <p className=\"text-sm text-destructive\">{formatMessage({ id: 'codexlens.mcp.error' })}</p>\r\n )}\r\n {!isLoading && !isError && (\r\n <pre className=\"bg-muted rounded-md p-4 text-xs overflow-auto max-h-96 font-mono\">\r\n {configJson || formatMessage({ id: 'codexlens.mcp.noConfig' })}\r\n </pre>\r\n )}\r\n </CardContent>\r\n </Card>\r\n\r\n {/* Quick Install */}\r\n <Card>\r\n <CardHeader className=\"pb-3\">\r\n <CardTitle className=\"text-base\">{formatMessage({ id: 'codexlens.mcp.quickInstallTitle' })}</CardTitle>\r\n <p className=\"text-xs text-muted-foreground mt-1\">{formatMessage({ id: 'codexlens.mcp.quickInstallDesc' })}</p>\r\n </CardHeader>\r\n <CardContent className=\"space-y-3\">\r\n <div className=\"flex gap-2 flex-wrap\">\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n onClick={() => handleInstall('project')}\r\n disabled={installing || !projectPath}\r\n >\r\n {installing ? <Loader2 className=\"w-4 h-4 mr-1 animate-spin\" /> : <Download className=\"w-4 h-4 mr-1\" />}\r\n {installing ? formatMessage({ id: 'codexlens.mcp.installing' }) : formatMessage({ id: 'codexlens.mcp.installProject' })}\r\n </Button>\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n onClick={() => handleInstall('global')}\r\n disabled={installing}\r\n >\r\n {installing ? <Loader2 className=\"w-4 h-4 mr-1 animate-spin\" /> : <Download className=\"w-4 h-4 mr-1\" />}\r\n {installing ? formatMessage({ id: 'codexlens.mcp.installing' }) : formatMessage({ id: 'codexlens.mcp.installGlobal' })}\r\n </Button>\r\n </div>\r\n {installResult && (\r\n <p className={`text-sm ${installResult.ok ? 'text-success' : 'text-destructive'}`}>\r\n {installResult.msg}\r\n </p>\r\n )}\r\n </CardContent>\r\n </Card>\r\n\r\n {/* Installation instructions */}\r\n <Card>\r\n <CardHeader className=\"pb-3\">\r\n <CardTitle className=\"text-base\">{formatMessage({ id: 'codexlens.mcp.installTitle' })}</CardTitle>\r\n </CardHeader>\r\n <CardContent>\r\n <ol className=\"list-decimal list-inside space-y-2 text-sm text-muted-foreground\">\r\n <li>{formatMessage({ id: 'codexlens.mcp.installSteps.step1' })}</li>\r\n <li>{formatMessage({ id: 'codexlens.mcp.installSteps.step2' })}</li>\r\n <li>{formatMessage({ id: 'codexlens.mcp.installSteps.step3' })}</li>\r\n <li>{formatMessage({ id: 'codexlens.mcp.installSteps.step4' })}</li>\r\n <li>{formatMessage({ id: 'codexlens.mcp.installSteps.step5' })}</li>\r\n </ol>\r\n </CardContent>\r\n </Card>\r\n </div>\r\n );\r\n}\r\n","// ========================================\r\n// ModelManagerTab Component\r\n// ========================================\r\n// Model list with download/delete actions and embed mode banner\r\n\r\nimport { useIntl } from 'react-intl';\r\nimport { Download, Trash2, Loader2 } from 'lucide-react';\r\nimport { Card, CardContent } from '@/components/ui/Card';\r\nimport { Button } from '@/components/ui/Button';\r\nimport { Badge } from '@/components/ui/Badge';\r\nimport {\r\n useCodexLensModels,\r\n useDownloadModel,\r\n useDeleteModel,\r\n useCodexLensEnv,\r\n type ModelEntry,\r\n} from '@/hooks/useCodexLens';\r\n\r\nexport function ModelManagerTab() {\r\n const { formatMessage } = useIntl();\r\n const { data: modelsData, isLoading, isError } = useCodexLensModels();\r\n const { data: envData } = useCodexLensEnv();\r\n const { downloadModel, isDownloading } = useDownloadModel();\r\n const { deleteModel, isDeleting } = useDeleteModel();\r\n\r\n const hasApiUrl = !!(envData?.values.CODEXLENS_EMBED_API_URL);\n const embedMode = hasApiUrl ? 'API' : 'Local fastembed';\r\n\r\n const models: ModelEntry[] = modelsData ?? [];\r\n\r\n return (\r\n <div className=\"space-y-4\">\r\n {/* Embed mode banner */}\r\n <div className=\"flex items-center gap-2 p-3 rounded-md bg-muted text-sm\">\r\n <span className=\"text-muted-foreground\">{formatMessage({ id: 'codexlens.models.embedMode' })}:</span>\r\n <Badge variant={hasApiUrl ? 'success' : 'secondary'}>{embedMode}</Badge>\r\n </div>\r\n\r\n {/* Loading / Error states */}\r\n {isLoading && (\r\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground p-4\">\r\n <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n {formatMessage({ id: 'codexlens.models.loading' })}\r\n </div>\r\n )}\r\n\r\n {isError && (\r\n <p className=\"text-sm text-destructive p-4\">{formatMessage({ id: 'codexlens.models.error' })}</p>\r\n )}\r\n\r\n {/* Model list */}\r\n {!isLoading && !isError && models.length === 0 && (\r\n <p className=\"text-sm text-muted-foreground p-4\">{formatMessage({ id: 'codexlens.models.noModels' })}</p>\r\n )}\r\n\r\n {!isLoading && !isError && models.length > 0 && (\r\n <Card>\r\n <CardContent className=\"p-0\">\r\n <div className=\"divide-y divide-border\">\r\n {models.map((model) => (\r\n <div\r\n key={model.name}\r\n className=\"flex items-center justify-between px-4 py-3\"\r\n >\r\n <div className=\"flex items-center gap-3\">\r\n <span className=\"text-sm font-medium\">{model.name}</span>\r\n <Badge variant={model.installed ? 'success' : 'secondary'}>\r\n {model.installed\r\n ? formatMessage({ id: 'codexlens.models.installed' })\r\n : formatMessage({ id: 'codexlens.models.notInstalled' })}\r\n </Badge>\r\n </div>\r\n <div className=\"flex gap-2\">\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n onClick={() => downloadModel(model.name)}\r\n disabled={isDownloading}\r\n >\r\n {isDownloading ? (\r\n <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n ) : (\r\n <Download className=\"w-4 h-4\" />\r\n )}\r\n <span className=\"ml-1\">{formatMessage({ id: 'codexlens.models.download' })}</span>\r\n </Button>\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n onClick={() => deleteModel(model.name)}\r\n disabled={!model.installed || isDeleting}\r\n >\r\n {isDeleting ? (\r\n <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n ) : (\r\n <Trash2 className=\"w-4 h-4\" />\r\n )}\r\n <span className=\"ml-1\">{formatMessage({ id: 'codexlens.models.delete' })}</span>\r\n </Button>\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n </CardContent>\r\n </Card>\r\n )}\r\n </div>\r\n );\r\n}\r\n","// ========================================\r\n// IndexManagerTab Component\r\n// ========================================\r\n// Project path input, index status display, and sync/rebuild actions\r\n\r\nimport { useState, useEffect } from 'react';\r\nimport { useIntl } from 'react-intl';\r\nimport { Plus, Trash2, RefreshCw, Loader2 } from 'lucide-react';\r\nimport { useQueryClient } from '@tanstack/react-query';\r\nimport { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/Card';\r\nimport { Button } from '@/components/ui/Button';\r\nimport { Input } from '@/components/ui/Input';\r\nimport { useIndexStatus, useSyncIndex, useRebuildIndex, codexLensKeys, type IndexStatusData } from '@/hooks/useCodexLens';\r\nimport { useWorkflowStore, selectProjectPath } from '@/stores/workflowStore';\r\n\r\ninterface ProjectStatusCardProps {\r\n projectPath: string;\r\n}\r\n\r\nfunction ProjectStatusCard({ projectPath }: ProjectStatusCardProps) {\r\n const { formatMessage } = useIntl();\r\n const queryClient = useQueryClient();\r\n const { data: statusData, isLoading, isError } = useIndexStatus(projectPath);\r\n const { syncIndex, isSyncing } = useSyncIndex();\r\n const { rebuildIndex, isRebuilding } = useRebuildIndex();\r\n\r\n const status: IndexStatusData | undefined = statusData;\r\n\r\n const handleRefresh = () => {\r\n queryClient.invalidateQueries({ queryKey: codexLensKeys.indexStatus(projectPath) });\r\n };\r\n\r\n return (\r\n <Card>\r\n <CardHeader className=\"pb-3\">\r\n <CardTitle className=\"text-sm font-medium truncate\">{projectPath}</CardTitle>\r\n </CardHeader>\r\n <CardContent className=\"space-y-4\">\r\n {/* Status stats */}\r\n {isLoading && (\r\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\r\n <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n {formatMessage({ id: 'codexlens.index.loading' })}\r\n </div>\r\n )}\r\n {isError && (\r\n <p className=\"text-sm text-destructive\">{formatMessage({ id: 'codexlens.index.error' })}</p>\r\n )}\r\n {!isLoading && !isError && status && (\r\n <div className=\"grid grid-cols-3 gap-3\">\r\n <div className=\"text-center\">\r\n <p className=\"text-lg font-semibold\">{status.files_tracked ?? 0}</p>\r\n <p className=\"text-xs text-muted-foreground\">{formatMessage({ id: 'codexlens.index.filesTracked' })}</p>\r\n </div>\r\n <div className=\"text-center\">\r\n <p className=\"text-lg font-semibold\">{status.total_chunks ?? 0}</p>\r\n <p className=\"text-xs text-muted-foreground\">{formatMessage({ id: 'codexlens.index.totalChunks' })}</p>\r\n </div>\r\n <div className=\"text-center\">\r\n <p className=\"text-lg font-semibold\">{status.deleted_chunks ?? 0}</p>\r\n <p className=\"text-xs text-muted-foreground\">{formatMessage({ id: 'codexlens.index.deletedChunks' })}</p>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Action buttons */}\r\n <div className=\"flex gap-2 flex-wrap\">\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n onClick={() => syncIndex(projectPath)}\r\n disabled={isSyncing}\r\n >\r\n {isSyncing ? <Loader2 className=\"w-4 h-4 animate-spin mr-1\" /> : null}\r\n {formatMessage({ id: 'codexlens.index.sync' })}\r\n </Button>\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n onClick={() => rebuildIndex(projectPath)}\r\n disabled={isRebuilding}\r\n >\r\n {isRebuilding ? <Loader2 className=\"w-4 h-4 animate-spin mr-1\" /> : null}\r\n {formatMessage({ id: 'codexlens.index.rebuild' })}\r\n </Button>\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n onClick={handleRefresh}\r\n >\r\n <RefreshCw className=\"w-4 h-4 mr-1\" />\r\n {formatMessage({ id: 'codexlens.index.refresh' })}\r\n </Button>\r\n </div>\r\n </CardContent>\r\n </Card>\r\n );\r\n}\r\n\r\nexport function IndexManagerTab() {\r\n const { formatMessage } = useIntl();\r\n const currentWorkspacePath = useWorkflowStore(selectProjectPath);\r\n const [paths, setPaths] = useState<string[]>([]);\r\n const [inputValue, setInputValue] = useState('');\r\n\r\n // Auto-add current workspace path on mount and when workspace changes\r\n useEffect(() => {\r\n if (currentWorkspacePath) {\r\n setPaths((prev) => {\r\n if (prev.includes(currentWorkspacePath)) return prev;\r\n return [currentWorkspacePath, ...prev];\r\n });\r\n }\r\n }, [currentWorkspacePath]);\r\n\r\n const handleAdd = () => {\r\n const trimmed = inputValue.trim();\r\n if (trimmed && !paths.includes(trimmed)) {\r\n setPaths((prev) => [...prev, trimmed]);\r\n }\r\n setInputValue('');\r\n };\r\n\r\n const handleRemove = (path: string) => {\r\n setPaths((prev) => prev.filter((p) => p !== path));\r\n };\r\n\r\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\r\n if (e.key === 'Enter') {\r\n handleAdd();\r\n }\r\n };\r\n\r\n return (\r\n <div className=\"space-y-4\">\r\n {/* Add project path */}\r\n <div className=\"flex gap-2\">\r\n <Input\r\n placeholder={formatMessage({ id: 'codexlens.index.pathPlaceholder' })}\r\n value={inputValue}\r\n onChange={(e) => setInputValue(e.target.value)}\r\n onKeyDown={handleKeyDown}\r\n className=\"flex-1\"\r\n />\r\n <Button onClick={handleAdd} disabled={!inputValue.trim()}>\r\n <Plus className=\"w-4 h-4 mr-1\" />\r\n {formatMessage({ id: 'codexlens.index.add' })}\r\n </Button>\r\n </div>\r\n\r\n {paths.length === 0 && (\r\n <p className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'codexlens.index.empty' })}\r\n </p>\r\n )}\r\n\r\n {/* Project status cards */}\r\n {paths.map((path) => (\r\n <div key={path} className=\"relative\">\r\n <Button\r\n variant=\"ghost\"\r\n size=\"sm\"\r\n className=\"absolute top-2 right-2 z-10 h-7 w-7 p-0\"\r\n onClick={() => handleRemove(path)}\r\n title={formatMessage({ id: 'codexlens.index.removeProject' })}\r\n >\r\n <Trash2 className=\"w-4 h-4 text-muted-foreground\" />\r\n </Button>\r\n <ProjectStatusCard projectPath={path} />\r\n </div>\r\n ))}\r\n </div>\r\n );\r\n}\r\n","// ========================================\r\n// EnvSettingsTab Component\r\n// ========================================\r\n// Grouped env var form with save/reset actions\r\n\r\nimport { useState, useEffect } from 'react';\r\nimport { useIntl } from 'react-intl';\r\nimport { Eye, EyeOff, Save, RotateCcw } from 'lucide-react';\r\nimport { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/Card';\r\nimport { Button } from '@/components/ui/Button';\r\nimport { Input } from '@/components/ui/Input';\r\nimport { useCodexLensEnv, useSaveCodexLensEnv } from '@/hooks/useCodexLens';\r\n\r\ntype EmbedMode = 'local' | 'api';\r\n\r\n// ========================================\r\n// ENV group definitions\r\n// ========================================\r\n\r\ninterface EnvField {\r\n key: string;\r\n label: string;\r\n sensitive?: boolean;\r\n}\r\n\r\ninterface EnvGroup {\r\n title: string;\r\n fields: EnvField[];\r\n}\r\n\r\nconst ENV_GROUPS: EnvGroup[] = [\r\n {\r\n title: 'embed',\r\n fields: [\r\n { key: 'CODEXLENS_EMBED_API_URL', label: 'Embed API URL' },\r\n { key: 'CODEXLENS_EMBED_API_KEY', label: 'Embed API Key', sensitive: true },\r\n { key: 'CODEXLENS_EMBED_API_MODEL', label: 'Embed API Model' },\r\n { key: 'CODEXLENS_EMBED_DIM', label: 'Embed Dimension' },\r\n { key: 'CODEXLENS_EMBED_API_ENDPOINTS', label: 'Embed API Endpoints', sensitive: true },\r\n { key: 'CODEXLENS_EMBED_BATCH_SIZE', label: 'Embed Batch Size' },\r\n { key: 'CODEXLENS_EMBED_API_CONCURRENCY', label: 'Embed API Concurrency' },\r\n ],\r\n },\r\n {\r\n title: 'reranker',\r\n fields: [\r\n { key: 'CODEXLENS_RERANKER_API_URL', label: 'Reranker API URL' },\r\n { key: 'CODEXLENS_RERANKER_API_KEY', label: 'Reranker API Key', sensitive: true },\r\n { key: 'CODEXLENS_RERANKER_API_MODEL', label: 'Reranker API Model' },\r\n ],\r\n },\r\n {\r\n title: 'performance',\r\n fields: [\r\n { key: 'CODEXLENS_BINARY_TOP_K', label: 'Binary Top K' },\r\n { key: 'CODEXLENS_ANN_TOP_K', label: 'ANN Top K' },\r\n { key: 'CODEXLENS_FTS_TOP_K', label: 'FTS Top K' },\r\n { key: 'CODEXLENS_FUSION_K', label: 'Fusion K' },\r\n { key: 'CODEXLENS_RERANKER_TOP_K', label: 'Reranker Top K' },\r\n { key: 'CODEXLENS_RERANKER_BATCH_SIZE', label: 'Reranker Batch Size' },\r\n ],\r\n },\r\n {\r\n title: 'index',\r\n fields: [\r\n { key: 'CODEXLENS_DB_PATH', label: 'DB Path' },\r\n { key: 'CODEXLENS_INDEX_WORKERS', label: 'Index Workers' },\r\n { key: 'CODEXLENS_CODE_AWARE_CHUNKING', label: 'Code Aware Chunking' },\r\n { key: 'CODEXLENS_MAX_FILE_SIZE', label: 'Max File Size' },\r\n { key: 'CODEXLENS_HNSW_EF', label: 'HNSW EF' },\r\n { key: 'CODEXLENS_HNSW_M', label: 'HNSW M' },\r\n ],\r\n },\r\n];\r\n\r\n// Fields that are only relevant in API mode\r\nconst API_ONLY_KEYS = new Set([\r\n 'CODEXLENS_EMBED_API_URL',\r\n 'CODEXLENS_EMBED_API_KEY',\r\n 'CODEXLENS_EMBED_API_ENDPOINTS',\r\n 'CODEXLENS_EMBED_API_CONCURRENCY',\r\n]);\r\n\r\n// Default placeholder values\r\nconst FIELD_DEFAULTS: Record<string, string> = {\n CODEXLENS_EMBED_API_MODEL: 'text-embedding-3-small',\n CODEXLENS_EMBED_DIM: '1536',\n CODEXLENS_EMBED_BATCH_SIZE: '64',\n CODEXLENS_EMBED_API_CONCURRENCY: '4',\n CODEXLENS_BINARY_TOP_K: '200',\n CODEXLENS_ANN_TOP_K: '50',\n CODEXLENS_FTS_TOP_K: '50',\n CODEXLENS_FUSION_K: '60',\n CODEXLENS_RERANKER_TOP_K: '20',\n CODEXLENS_RERANKER_BATCH_SIZE: '32',\n CODEXLENS_INDEX_WORKERS: '2',\n CODEXLENS_CODE_AWARE_CHUNKING: 'true',\n CODEXLENS_MAX_FILE_SIZE: '1000000',\n CODEXLENS_HNSW_EF: '150',\n CODEXLENS_HNSW_M: '32',\n};\n\r\n// Collect all keys\r\nconst ALL_KEYS = ENV_GROUPS.flatMap((g) => g.fields.map((f) => f.key));\r\n\r\nfunction buildEmptyEnv(): Record<string, string> {\n return Object.fromEntries(ALL_KEYS.map((k) => [k, '']));\n}\n\nfunction buildEffectiveEnv(\n values: Record<string, string>,\n defaults: Record<string, string>,\n): Record<string, string> {\n return Object.fromEntries(\n ALL_KEYS.map((key) => [key, values[key] ?? defaults[key] ?? '']),\n );\n}\n\r\n// ========================================\r\n// Sensitive field with show/hide toggle\r\n// ========================================\r\n\r\ninterface SensitiveInputProps {\r\n value: string;\r\n onChange: (v: string) => void;\r\n id: string;\r\n}\r\n\r\nfunction SensitiveInput({ value, onChange, id }: SensitiveInputProps) {\r\n const [show, setShow] = useState(false);\r\n return (\r\n <div className=\"relative\">\r\n <Input\r\n id={id}\r\n type={show ? 'text' : 'password'}\r\n value={value}\r\n onChange={(e) => onChange(e.target.value)}\r\n className=\"pr-10\"\r\n />\r\n <button\r\n type=\"button\"\r\n className=\"absolute inset-y-0 right-2 flex items-center text-muted-foreground hover:text-foreground\"\r\n onClick={() => setShow((s) => !s)}\r\n tabIndex={-1}\r\n >\r\n {show ? <EyeOff className=\"w-4 h-4\" /> : <Eye className=\"w-4 h-4\" />}\r\n </button>\r\n </div>\r\n );\r\n}\r\n\r\n// ========================================\r\n// Main component\r\n// ========================================\r\n\r\nexport function EnvSettingsTab() {\n const { formatMessage } = useIntl();\n const { data: envData, isLoading } = useCodexLensEnv();\n const { saveEnv, isSaving } = useSaveCodexLensEnv();\n\n const [embedMode, setEmbedMode] = useState<EmbedMode>('local');\n const [localEnv, setLocalEnv] = useState<Record<string, string>>(buildEmptyEnv);\n\n const serverValues = envData?.values ?? {};\n const serverDefaults = { ...FIELD_DEFAULTS, ...(envData?.defaults ?? {}) };\n const serverRecord = buildEffectiveEnv(serverValues, serverDefaults);\n\n // Sync server state into local when loaded and detect embed mode\n useEffect(() => {\n if (envData) {\n const nextDefaults = { ...FIELD_DEFAULTS, ...(envData.defaults ?? {}) };\n const nextValues = envData.values ?? {};\n setLocalEnv(buildEffectiveEnv(nextValues, nextDefaults));\n // Auto-detect mode from saved env\n if (nextValues.CODEXLENS_EMBED_API_URL) {\n setEmbedMode('api');\n }\n }\n }, [envData]);\n\n const isDirty = ALL_KEYS.some((k) => localEnv[k] !== (serverRecord[k] ?? ''));\n\r\n const handleChange = (key: string, value: string) => {\r\n setLocalEnv((prev) => ({ ...prev, [key]: value }));\r\n };\n\n const handleSave = async () => {\n const payload = Object.fromEntries(\n Object.entries(localEnv).flatMap(([key, value]) => {\n const trimmed = value.trim();\n const defaultValue = serverDefaults[key] ?? '';\n if (!trimmed || trimmed === defaultValue) {\n return [];\n }\n return [[key, trimmed]];\n }),\n );\n await saveEnv(payload);\n };\n\r\n const handleReset = () => {\r\n setLocalEnv(buildEmptyEnv());\r\n };\r\n\r\n if (isLoading) {\r\n return <p className=\"text-sm text-muted-foreground p-4\">{formatMessage({ id: 'codexlens.env.loading' })}</p>;\r\n }\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Mode toggle */}\r\n <div className=\"flex items-center gap-3\">\r\n <span className=\"text-sm font-medium\">{formatMessage({ id: 'codexlens.env.mode' })}:</span>\r\n <div className=\"flex rounded-md border border-border overflow-hidden\">\r\n <button\r\n type=\"button\"\r\n onClick={() => setEmbedMode('local')}\r\n className={`px-3 py-1.5 text-sm transition-colors ${\r\n embedMode === 'local'\r\n ? 'bg-primary text-primary-foreground'\r\n : 'bg-background text-muted-foreground hover:bg-muted'\r\n }`}\r\n >\r\n {formatMessage({ id: 'codexlens.env.localMode' })}\r\n </button>\r\n <button\r\n type=\"button\"\r\n onClick={() => setEmbedMode('api')}\r\n className={`px-3 py-1.5 text-sm transition-colors ${\r\n embedMode === 'api'\r\n ? 'bg-primary text-primary-foreground'\r\n : 'bg-background text-muted-foreground hover:bg-muted'\r\n }`}\r\n >\r\n {formatMessage({ id: 'codexlens.env.apiMode' })}\r\n </button>\r\n </div>\r\n <span className=\"text-xs text-muted-foreground\">\r\n {embedMode === 'local'\r\n ? formatMessage({ id: 'codexlens.env.localModeDesc' })\r\n : formatMessage({ id: 'codexlens.env.apiModeDesc' })}\r\n </span>\r\n </div>\r\n\r\n {ENV_GROUPS.map((group) => {\r\n // In local mode, filter out API-only fields from embed group\r\n const visibleFields = embedMode === 'local'\r\n ? group.fields.filter((f) => !API_ONLY_KEYS.has(f.key))\r\n : group.fields;\r\n if (visibleFields.length === 0) return null;\r\n return (\r\n <Card key={group.title}>\r\n <CardHeader className=\"pb-3\">\r\n <CardTitle className=\"text-base\">{formatMessage({ id: `codexlens.env.sections.${group.title}` })}</CardTitle>\r\n </CardHeader>\r\n <CardContent className=\"space-y-3\">\r\n {visibleFields.map((field) => (\r\n <div key={field.key} className=\"grid grid-cols-3 gap-3 items-center\">\r\n <label\r\n htmlFor={field.key}\r\n className=\"text-sm text-muted-foreground col-span-1\"\r\n >\r\n {field.label}\r\n </label>\r\n <div className=\"col-span-2\">\r\n {field.sensitive ? (\r\n <SensitiveInput\r\n id={field.key}\r\n value={localEnv[field.key] ?? ''}\r\n onChange={(v) => handleChange(field.key, v)}\r\n />\r\n ) : (\r\n <Input\n id={field.key}\n value={localEnv[field.key] ?? ''}\n placeholder={serverDefaults[field.key] ?? ''}\n onChange={(e) => handleChange(field.key, e.target.value)}\n />\n )}\n </div>\r\n </div>\r\n ))}\r\n </CardContent>\r\n </Card>\r\n );\r\n })}\r\n\r\n {/* Action buttons */}\r\n <div className=\"flex justify-between pt-2\">\r\n <Button variant=\"outline\" onClick={handleReset}>\r\n <RotateCcw className=\"w-4 h-4 mr-2\" />\r\n {formatMessage({ id: 'codexlens.env.clearForm' })}\r\n </Button>\r\n <Button onClick={handleSave} disabled={!isDirty || isSaving}>\r\n <Save className=\"w-4 h-4 mr-2\" />\r\n {isSaving ? formatMessage({ id: 'codexlens.env.saving' }) : formatMessage({ id: 'codexlens.env.save' })}\r\n </Button>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","// ========================================\r\n// CodexLens Page\r\n// ========================================\r\n// Main page for CodexLens v2 management: MCP config, models, index, env\r\n\r\nimport { useState } from 'react';\r\nimport { useIntl } from 'react-intl';\r\nimport { Search } from 'lucide-react';\r\nimport { TabsNavigation } from '@/components/ui/TabsNavigation';\r\nimport { McpConfigTab } from '@/components/codexlens/McpConfigTab';\r\nimport { ModelManagerTab } from '@/components/codexlens/ModelManagerTab';\r\nimport { IndexManagerTab } from '@/components/codexlens/IndexManagerTab';\r\nimport { EnvSettingsTab } from '@/components/codexlens/EnvSettingsTab';\r\n\r\ntype TabType = 'mcp' | 'models' | 'index' | 'env';\r\n\r\nexport function CodexLensPage() {\r\n const { formatMessage } = useIntl();\r\n const [activeTab, setActiveTab] = useState<TabType>('mcp');\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Page Header */}\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-foreground flex items-center gap-2\">\r\n <Search className=\"w-6 h-6 text-primary\" />\r\n {formatMessage({ id: 'codexlens.page.title' })}\r\n </h1>\r\n <p className=\"text-muted-foreground mt-1\">\r\n {formatMessage({ id: 'codexlens.page.description' })}\r\n </p>\r\n </div>\r\n\r\n {/* Tab Navigation */}\r\n <TabsNavigation\r\n value={activeTab}\r\n onValueChange={(v) => setActiveTab(v as TabType)}\r\n tabs={[\r\n { value: 'mcp', label: formatMessage({ id: 'codexlens.tabs.mcp' }) },\r\n { value: 'models', label: formatMessage({ id: 'codexlens.tabs.models' }) },\r\n { value: 'index', label: formatMessage({ id: 'codexlens.tabs.index' }) },\r\n { value: 'env', label: formatMessage({ id: 'codexlens.tabs.env' }) },\r\n ]}\r\n />\r\n\r\n {/* Tab Content */}\r\n <div className=\"mt-4\">\r\n {activeTab === 'mcp' && <McpConfigTab />}\r\n {activeTab === 'models' && <ModelManagerTab />}\r\n {activeTab === 'index' && <IndexManagerTab />}\r\n {activeTab === 'env' && <EnvSettingsTab />}\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\nexport default CodexLensPage;\r\n"],"names":["codexLensKeys","path","useCodexLensModels","useQuery","fetchApi","r","useDownloadModel","queryClient","useQueryClient","mutation","useMutation","modelName","useDeleteModel","useIndexStatus","projectPath","useSyncIndex","useRebuildIndex","useCodexLensEnv","useSaveCodexLensEnv","env","useCodexLensMcpConfig","McpConfigTab","formatMessage","useIntl","mcpConfig","isLoading","isError","refetch","envData","copied","setCopied","useState","installing","setInstalling","installResult","setInstallResult","useWorkflowStore","selectProjectPath","handleInstall","scope","mcpServers","serverConfig","typedConfig","copyMcpServerToProject","addGlobalMcpServer","err","hasApiUrl","embedMode","configJson","handleCopy","handleRegenerate","jsxs","Badge","Card","jsx","CardHeader","CardTitle","Button","Check","Copy","RefreshCw","CardContent","Loader2","Download","ModelManagerTab","modelsData","downloadModel","isDownloading","deleteModel","isDeleting","models","model","Trash2","ProjectStatusCard","statusData","syncIndex","isSyncing","rebuildIndex","isRebuilding","status","handleRefresh","IndexManagerTab","currentWorkspacePath","paths","setPaths","inputValue","setInputValue","useEffect","prev","handleAdd","trimmed","handleRemove","p","handleKeyDown","e","Input","Plus","ENV_GROUPS","API_ONLY_KEYS","FIELD_DEFAULTS","ALL_KEYS","g","f","buildEmptyEnv","k","buildEffectiveEnv","values","defaults","key","SensitiveInput","value","onChange","id","show","setShow","s","EyeOff","Eye","EnvSettingsTab","saveEnv","isSaving","setEmbedMode","localEnv","setLocalEnv","serverValues","serverDefaults","serverRecord","nextDefaults","nextValues","isDirty","handleChange","handleSave","payload","defaultValue","handleReset","group","visibleFields","field","v","RotateCcw","Save","CodexLensPage","activeTab","setActiveTab","Search","TabsNavigation"],"mappings":"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"}
|