claude-code-workflow 6.1.4 → 6.2.2
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/CLAUDE.md +10 -0
- package/.claude/agents/action-planning-agent.md +857 -778
- package/.claude/agents/cli-execution-agent.md +266 -269
- package/.claude/agents/cli-explore-agent.md +2 -2
- package/.claude/agents/cli-lite-planning-agent.md +142 -92
- package/.claude/agents/cli-planning-agent.md +4 -4
- package/.claude/agents/code-developer.md +7 -6
- package/.claude/agents/conceptual-planning-agent.md +2 -2
- package/.claude/agents/context-search-agent.md +31 -32
- package/.claude/agents/doc-generator.md +4 -4
- package/.claude/agents/memory-bridge.md +93 -93
- package/.claude/agents/test-context-search-agent.md +8 -7
- package/.claude/agents/test-fix-agent.md +7 -6
- package/.claude/commands/clean.md +516 -0
- package/.claude/commands/memory/compact.md +383 -0
- package/.claude/commands/memory/docs-full-cli.md +471 -471
- package/.claude/commands/memory/docs-related-cli.md +386 -386
- package/.claude/commands/memory/docs.md +615 -615
- package/.claude/commands/memory/load.md +5 -5
- package/.claude/commands/memory/tech-research-rules.md +310 -0
- package/.claude/commands/memory/update-full.md +332 -332
- package/.claude/commands/memory/workflow-skill-memory.md +4 -4
- package/.claude/commands/task/create.md +151 -151
- package/.claude/commands/version.md +254 -254
- package/.claude/commands/workflow/brainstorm/api-designer.md +587 -585
- package/.claude/commands/workflow/brainstorm/artifacts.md +1 -0
- package/.claude/commands/workflow/brainstorm/auto-parallel.md +443 -443
- package/.claude/commands/workflow/brainstorm/data-architect.md +220 -220
- package/.claude/commands/workflow/brainstorm/product-manager.md +200 -200
- package/.claude/commands/workflow/brainstorm/product-owner.md +200 -200
- package/.claude/commands/workflow/brainstorm/scrum-master.md +200 -200
- package/.claude/commands/workflow/brainstorm/subject-matter-expert.md +200 -200
- package/.claude/commands/workflow/brainstorm/system-architect.md +389 -387
- package/.claude/commands/workflow/brainstorm/ui-designer.md +221 -221
- package/.claude/commands/workflow/brainstorm/ux-expert.md +221 -221
- package/.claude/commands/workflow/debug.md +321 -0
- package/.claude/commands/workflow/execute.md +13 -0
- package/.claude/commands/workflow/init.md +165 -164
- package/.claude/commands/workflow/lite-execute.md +119 -13
- package/.claude/commands/workflow/lite-fix.md +623 -621
- package/.claude/commands/workflow/lite-plan.md +610 -592
- package/.claude/commands/workflow/plan.md +5 -5
- package/.claude/commands/workflow/review-module-cycle.md +2 -0
- package/.claude/commands/workflow/review-session-cycle.md +2 -0
- package/.claude/commands/workflow/review.md +297 -291
- package/.claude/commands/workflow/session/complete.md +153 -500
- package/.claude/commands/workflow/session/list.md +95 -95
- package/.claude/commands/workflow/session/resume.md +60 -60
- package/.claude/commands/workflow/session/start.md +199 -199
- package/.claude/commands/workflow/tdd-plan.md +3 -3
- package/.claude/commands/workflow/tdd-verify.md +23 -9
- package/.claude/commands/workflow/test-cycle-execute.md +2 -0
- package/.claude/commands/workflow/test-fix-gen.md +699 -699
- package/.claude/commands/workflow/tools/conflict-resolution.md +104 -18
- package/.claude/commands/workflow/tools/context-gather.md +436 -434
- package/.claude/commands/workflow/tools/task-generate-agent.md +490 -291
- package/.claude/commands/workflow/tools/task-generate-tdd.md +18 -10
- package/.claude/commands/workflow/tools/test-concept-enhanced.md +2 -1
- package/.claude/commands/workflow/tools/test-context-gather.md +1 -0
- package/.claude/commands/workflow/tools/test-task-generate.md +1 -0
- package/.claude/commands/workflow/ui-design/import-from-code.md +9 -6
- package/.claude/skills/command-guide/SKILL.md +5 -5
- package/.claude/skills/command-guide/index/all-commands.json +1 -1
- package/.claude/skills/command-guide/index/by-category.json +1 -1
- package/.claude/skills/command-guide/index/by-use-case.json +1 -1
- package/.claude/skills/command-guide/reference/agents/action-planning-agent.md +857 -778
- package/.claude/skills/command-guide/reference/agents/cli-execution-agent.md +266 -269
- package/.claude/skills/command-guide/reference/agents/cli-explore-agent.md +2 -2
- package/.claude/skills/command-guide/reference/agents/cli-lite-planning-agent.md +142 -92
- package/.claude/skills/command-guide/reference/agents/cli-planning-agent.md +4 -4
- package/.claude/skills/command-guide/reference/agents/code-developer.md +7 -6
- package/.claude/skills/command-guide/reference/agents/conceptual-planning-agent.md +2 -2
- package/.claude/skills/command-guide/reference/agents/context-search-agent.md +31 -32
- package/.claude/skills/command-guide/reference/agents/doc-generator.md +4 -4
- package/.claude/skills/command-guide/reference/agents/memory-bridge.md +93 -93
- package/.claude/skills/command-guide/reference/agents/test-context-search-agent.md +8 -7
- package/.claude/skills/command-guide/reference/agents/test-fix-agent.md +7 -6
- package/.claude/skills/command-guide/reference/commands/memory/docs-full-cli.md +471 -471
- package/.claude/skills/command-guide/reference/commands/memory/docs-related-cli.md +386 -386
- package/.claude/skills/command-guide/reference/commands/memory/docs.md +17 -16
- package/.claude/skills/command-guide/reference/commands/memory/load.md +5 -5
- package/.claude/skills/command-guide/reference/commands/memory/tech-research.md +194 -357
- package/.claude/skills/command-guide/reference/commands/memory/update-full.md +332 -332
- package/.claude/skills/command-guide/reference/commands/memory/workflow-skill-memory.md +4 -4
- package/.claude/skills/command-guide/reference/commands/task/create.md +151 -151
- package/.claude/skills/command-guide/reference/commands/version.md +254 -254
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/api-designer.md +585 -585
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/auto-parallel.md +443 -443
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/data-architect.md +220 -220
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/product-manager.md +200 -200
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/product-owner.md +200 -200
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/scrum-master.md +200 -200
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/subject-matter-expert.md +200 -200
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/system-architect.md +387 -387
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/ui-designer.md +221 -221
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/ux-expert.md +221 -221
- package/.claude/skills/command-guide/reference/commands/workflow/execute.md +25 -20
- package/.claude/skills/command-guide/reference/commands/workflow/init.md +164 -164
- package/.claude/skills/command-guide/reference/commands/workflow/lite-execute.md +748 -686
- package/.claude/skills/command-guide/reference/commands/workflow/lite-fix.md +664 -621
- package/.claude/skills/command-guide/reference/commands/workflow/lite-plan.md +645 -592
- package/.claude/skills/command-guide/reference/commands/workflow/plan.md +5 -5
- package/.claude/skills/command-guide/reference/commands/workflow/review.md +25 -18
- package/.claude/skills/command-guide/reference/commands/workflow/session/complete.md +547 -500
- package/.claude/skills/command-guide/reference/commands/workflow/session/list.md +45 -27
- package/.claude/skills/command-guide/reference/commands/workflow/session/resume.md +35 -19
- package/.claude/skills/command-guide/reference/commands/workflow/session/start.md +90 -33
- package/.claude/skills/command-guide/reference/commands/workflow/tdd-plan.md +3 -3
- package/.claude/skills/command-guide/reference/commands/workflow/tdd-verify.md +23 -9
- package/.claude/skills/command-guide/reference/commands/workflow/test-fix-gen.md +699 -699
- package/.claude/skills/command-guide/reference/commands/workflow/tools/conflict-resolution.md +103 -17
- package/.claude/skills/command-guide/reference/commands/workflow/tools/context-gather.md +434 -434
- package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-agent.md +487 -291
- package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-tdd.md +17 -10
- package/.claude/skills/command-guide/reference/commands/workflow/tools/test-concept-enhanced.md +1 -1
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/import-from-code.md +6 -6
- package/.claude/workflows/chinese-response.md +38 -0
- package/.claude/workflows/cli-templates/prompts/rules/rule-api.txt +122 -0
- package/.claude/workflows/cli-templates/prompts/rules/rule-components.txt +122 -0
- package/.claude/workflows/cli-templates/prompts/rules/rule-config.txt +89 -0
- package/.claude/workflows/cli-templates/prompts/rules/rule-core.txt +60 -0
- package/.claude/workflows/cli-templates/prompts/rules/rule-patterns.txt +70 -0
- package/.claude/workflows/cli-templates/prompts/rules/rule-testing.txt +81 -0
- package/.claude/workflows/cli-templates/prompts/rules/tech-rules-agent-prompt.txt +89 -0
- package/.claude/workflows/cli-templates/prompts/workflow/gemini-solution-design.txt +131 -131
- package/.claude/workflows/cli-templates/prompts/workflow/skill-conflict-patterns.txt +5 -9
- package/.claude/workflows/cli-templates/prompts/workflow/skill-lessons-learned.txt +5 -9
- package/.claude/workflows/cli-templates/protocols/analysis-protocol.md +112 -0
- package/.claude/workflows/cli-templates/protocols/write-protocol.md +201 -0
- package/.claude/workflows/cli-templates/schemas/conflict-resolution-schema.json +137 -0
- package/.claude/workflows/cli-templates/schemas/debug-log-json-schema.json +127 -0
- package/.claude/workflows/cli-templates/schemas/fix-plan-json-schema.json +25 -0
- package/.claude/workflows/cli-templates/schemas/plan-json-schema.json +25 -0
- package/.claude/workflows/cli-tools-usage.md +526 -0
- package/{CLAUDE.md → .claude/workflows/coding-philosophy.md} +24 -45
- package/.claude/workflows/context-tools.md +84 -0
- package/.claude/workflows/file-modification.md +64 -0
- package/.claude/workflows/tool-strategy.md +216 -79
- package/.claude/workflows/windows-platform.md +16 -0
- package/.claude/workflows/workflow-architecture.md +942 -942
- package/.codex/AGENTS.md +63 -330
- package/.codex/prompts/debug.md +318 -0
- package/.codex/prompts/execute.md +273 -0
- package/.codex/prompts/lite-execute.md +164 -0
- package/.codex/prompts/lite-plan.md +469 -0
- package/.codex/prompts.zip +0 -0
- package/.gemini/GEMINI.md +25 -164
- package/.qwen/QWEN.md +0 -139
- package/README.md +29 -9
- package/ccw/README.md +30 -6
- package/ccw/bin/ccw-mcp.js +7 -0
- package/ccw/bin/ccw.js +9 -9
- package/ccw/package.json +65 -47
- package/ccw/src/.workflow/.cli-history/history.db +0 -0
- package/ccw/src/.workflow/.cli-history/history.db-shm +0 -0
- package/ccw/src/.workflow/.cli-history/history.db-wal +0 -0
- package/ccw/src/cli.ts +244 -0
- package/ccw/src/commands/cli.ts +740 -0
- package/ccw/src/commands/core-memory.ts +770 -0
- package/ccw/src/commands/hook.ts +315 -0
- package/ccw/src/commands/install.ts +519 -0
- package/ccw/src/commands/{list.js → list.ts} +1 -1
- package/ccw/src/commands/memory.ts +1090 -0
- package/ccw/src/commands/{serve.js → serve.ts} +14 -5
- package/ccw/src/commands/session-path-resolver.ts +372 -0
- package/ccw/src/commands/session.ts +1141 -0
- package/ccw/src/commands/{stop.js → stop.ts} +16 -6
- package/ccw/src/commands/tool.ts +201 -0
- package/ccw/src/commands/{uninstall.js → uninstall.ts} +89 -40
- package/ccw/src/commands/{upgrade.js → upgrade.ts} +68 -23
- package/ccw/src/commands/{view.js → view.ts} +22 -8
- package/ccw/src/config/storage-paths.ts +670 -0
- package/ccw/src/core/cache-manager.ts +294 -0
- package/ccw/src/core/claude-freshness.ts +319 -0
- package/ccw/src/core/core-memory-store.ts +1528 -0
- package/ccw/src/core/{dashboard-generator-patch.js → dashboard-generator-patch.ts} +18 -0
- package/ccw/src/core/{dashboard-generator.js → dashboard-generator.ts} +69 -12
- package/ccw/src/core/data-aggregator.ts +584 -0
- package/ccw/src/core/history-importer.ts +625 -0
- package/ccw/src/core/{lite-scanner.js → lite-scanner-complete.ts} +162 -66
- package/ccw/src/core/lite-scanner.ts +469 -0
- package/ccw/src/core/{manifest.js → manifest.ts} +104 -34
- package/ccw/src/core/memory-embedder-bridge.ts +262 -0
- package/ccw/src/core/memory-store.ts +978 -0
- package/ccw/src/core/routes/ccw-routes.ts +96 -0
- package/ccw/src/core/routes/claude-routes.ts +1183 -0
- package/ccw/src/core/routes/cli-routes.ts +561 -0
- package/ccw/src/core/routes/codexlens-routes.ts +806 -0
- package/ccw/src/core/routes/core-memory-routes.ts +605 -0
- package/ccw/src/core/routes/files-routes.ts +428 -0
- package/ccw/src/core/routes/graph-routes.md +164 -0
- package/ccw/src/core/routes/graph-routes.ts +626 -0
- package/ccw/src/core/routes/help-routes.ts +308 -0
- package/ccw/src/core/routes/hooks-routes.ts +405 -0
- package/ccw/src/core/routes/mcp-routes.ts +1271 -0
- package/ccw/src/core/routes/mcp-routes.ts.backup +550 -0
- package/ccw/src/core/routes/mcp-templates-db.ts +268 -0
- package/ccw/src/core/routes/memory-routes.ts +1206 -0
- package/ccw/src/core/routes/rules-routes.ts +526 -0
- package/ccw/src/core/routes/session-routes.ts +467 -0
- package/ccw/src/core/routes/skills-routes.ts +599 -0
- package/ccw/src/core/routes/status-routes.ts +57 -0
- package/ccw/src/core/routes/system-routes.ts +427 -0
- package/ccw/src/core/server.ts +431 -0
- package/ccw/src/core/session-clustering-service.ts +1258 -0
- package/ccw/src/core/session-scanner.ts +283 -0
- package/ccw/src/core/websocket.ts +190 -0
- package/ccw/src/{index.js → index.ts} +1 -0
- package/ccw/src/mcp-server/index.ts +186 -0
- package/ccw/src/templates/assets/css/github-dark.min.css +10 -0
- package/ccw/src/templates/assets/css/github.min.css +10 -0
- package/ccw/src/templates/assets/js/cytoscape.min.js +32 -0
- package/ccw/src/templates/assets/js/d3.min.js +2 -0
- package/ccw/src/templates/assets/js/highlight.min.js +1244 -0
- package/ccw/src/templates/assets/js/lucide.min.js +12 -0
- package/ccw/src/templates/assets/js/marked.min.js +69 -0
- package/ccw/src/templates/assets/js/tailwind.js +83 -0
- package/ccw/src/templates/dashboard-css/01-base.css +11 -0
- package/ccw/src/templates/dashboard-css/02-session.css +22 -0
- package/ccw/src/templates/dashboard-css/04-lite-tasks.css +10 -0
- package/ccw/src/templates/dashboard-css/06-cards.css +10 -4
- package/ccw/src/templates/dashboard-css/07-managers.css +1178 -7
- package/ccw/src/templates/dashboard-css/09-explorer.css +23 -12
- package/ccw/src/templates/dashboard-css/10-cli-status.css +337 -0
- package/ccw/src/templates/dashboard-css/11-cli-history.css +271 -0
- package/ccw/src/templates/dashboard-css/12-cli-legacy.css +796 -0
- package/ccw/src/templates/dashboard-css/13-cli-ccw.css +199 -0
- package/ccw/src/templates/dashboard-css/14-cli-modals.css +258 -0
- package/ccw/src/templates/dashboard-css/15-cli-endpoints.css +305 -0
- package/ccw/src/templates/dashboard-css/16-cli-session.css +241 -0
- package/ccw/src/templates/dashboard-css/17-cli-conversation.css +283 -0
- package/ccw/src/templates/dashboard-css/18-cli-settings.css +160 -0
- package/ccw/src/templates/dashboard-css/19-cli-native-session.css +496 -0
- package/ccw/src/templates/dashboard-css/20-cli-taskqueue.css +188 -0
- package/ccw/src/templates/dashboard-css/21-cli-toolmgmt.css +310 -0
- package/ccw/src/templates/dashboard-css/22-cli-semantic.css +240 -0
- package/ccw/src/templates/dashboard-css/23-memory.css +2390 -0
- package/ccw/src/templates/dashboard-css/24-prompt-history.css +1089 -0
- package/ccw/src/templates/dashboard-css/25-skills-rules.css +326 -0
- package/ccw/src/templates/dashboard-css/26-claude-manager.css +908 -0
- package/ccw/src/templates/dashboard-css/27-graph-explorer.css +1678 -0
- package/ccw/src/templates/dashboard-css/28-mcp-manager.css +748 -0
- package/ccw/src/templates/dashboard-css/29-help.css +264 -0
- package/ccw/src/templates/dashboard-css/30-core-memory.css +1700 -0
- package/ccw/src/templates/dashboard-js/api.js +162 -142
- package/ccw/src/templates/dashboard-js/components/carousel.js +4 -4
- package/ccw/src/templates/dashboard-js/components/cli-history.js +876 -0
- package/ccw/src/templates/dashboard-js/components/cli-status.js +978 -0
- package/ccw/src/templates/dashboard-js/components/global-notifications.js +508 -219
- package/ccw/src/templates/dashboard-js/components/hook-manager.js +1277 -282
- package/ccw/src/templates/dashboard-js/components/index-manager.js +302 -0
- package/ccw/src/templates/dashboard-js/components/mcp-manager.js +718 -27
- package/ccw/src/templates/dashboard-js/components/modals.js +66 -0
- package/ccw/src/templates/dashboard-js/components/navigation.js +80 -12
- package/ccw/src/templates/dashboard-js/components/notifications.js +758 -194
- package/ccw/src/templates/dashboard-js/components/storage-manager.js +478 -0
- package/ccw/src/templates/dashboard-js/components/tabs-other.js +157 -6
- package/ccw/src/templates/dashboard-js/components/task-queue-sidebar.js +716 -0
- package/ccw/src/templates/dashboard-js/help-i18n.js +272 -0
- package/ccw/src/templates/dashboard-js/i18n.js +2807 -0
- package/ccw/src/templates/dashboard-js/main.js +15 -0
- package/ccw/src/templates/dashboard-js/state.js +243 -42
- package/ccw/src/templates/dashboard-js/utils.js +47 -1
- package/ccw/src/templates/dashboard-js/views/claude-manager.js +912 -0
- package/ccw/src/templates/dashboard-js/views/cli-manager.js +2272 -0
- package/ccw/src/templates/dashboard-js/views/codexlens-manager.js +964 -0
- package/ccw/src/templates/dashboard-js/views/core-memory-clusters.js +503 -0
- package/ccw/src/templates/dashboard-js/views/core-memory.js +782 -0
- package/ccw/src/templates/dashboard-js/views/explorer.js +888 -852
- package/ccw/src/templates/dashboard-js/views/graph-explorer.js +1157 -0
- package/ccw/src/templates/dashboard-js/views/help.js +856 -0
- package/ccw/src/templates/dashboard-js/views/history.js +337 -0
- package/ccw/src/templates/dashboard-js/views/home.js +61 -15
- package/ccw/src/templates/dashboard-js/views/hook-manager.js +311 -43
- package/ccw/src/templates/dashboard-js/views/lite-tasks.js +204 -28
- package/ccw/src/templates/dashboard-js/views/mcp-manager.js +2187 -411
- package/ccw/src/templates/dashboard-js/views/mcp-manager.js.backup +1729 -0
- package/ccw/src/templates/dashboard-js/views/mcp-manager.js.new +928 -0
- package/ccw/src/templates/dashboard-js/views/memory.js +1221 -0
- package/ccw/src/templates/dashboard-js/views/prompt-history.js +713 -0
- package/ccw/src/templates/dashboard-js/views/rules-manager.js +828 -0
- package/ccw/src/templates/dashboard-js/views/session-detail.js +54 -53
- package/ccw/src/templates/dashboard-js/views/skills-manager.js +819 -0
- package/ccw/src/templates/dashboard.html +185 -85
- package/ccw/src/templates/hooks-config-example.json +60 -0
- package/ccw/src/tools/classify-folders.ts +245 -0
- package/ccw/src/tools/cli-config-manager.ts +268 -0
- package/ccw/src/tools/cli-executor.ts +2014 -0
- package/ccw/src/tools/cli-history-store.ts +1195 -0
- package/ccw/src/tools/codex-lens.ts +1141 -0
- package/ccw/src/tools/{convert-tokens-to-css.js → convert-tokens-to-css.ts} +73 -23
- package/ccw/src/tools/core-memory.ts +444 -0
- package/ccw/src/tools/detect-changed-modules.ts +325 -0
- package/ccw/src/tools/{discover-design-files.js → discover-design-files.ts} +74 -24
- package/ccw/src/tools/edit-file.ts +568 -0
- package/ccw/src/tools/{generate-module-docs.js → generate-module-docs.ts} +207 -185
- package/ccw/src/tools/{get-modules-by-depth.js → get-modules-by-depth.ts} +120 -79
- package/ccw/src/tools/index.ts +370 -0
- package/ccw/src/tools/native-session-discovery.ts +795 -0
- package/ccw/src/tools/notifier.ts +129 -0
- package/ccw/src/tools/read-file.ts +410 -0
- package/ccw/src/tools/resume-strategy.ts +345 -0
- package/ccw/src/tools/session-content-parser.ts +619 -0
- package/ccw/src/tools/session-manager.ts +1026 -0
- package/ccw/src/tools/smart-context.ts +228 -0
- package/ccw/src/tools/smart-search.ts +2065 -0
- package/ccw/src/tools/smart-search.ts.backup +1233 -0
- package/ccw/src/tools/storage-manager.ts +455 -0
- package/ccw/src/tools/write-file.ts +222 -0
- package/ccw/src/types/config.ts +11 -0
- package/ccw/src/types/index.ts +3 -0
- package/ccw/src/types/session.ts +25 -0
- package/ccw/src/types/tool.ts +41 -0
- package/ccw/src/utils/{browser-launcher.js → browser-launcher.ts} +10 -8
- package/ccw/src/utils/file-utils.ts +48 -0
- package/ccw/src/utils/{path-resolver.js → path-resolver.ts} +114 -78
- package/ccw/src/utils/path-validator.ts +153 -0
- package/ccw/src/utils/{ui.js → ui.ts} +32 -25
- package/codex-lens/pyproject.toml +48 -0
- package/codex-lens/src/codexlens/.workflow/.cli-history/history.db +0 -0
- package/codex-lens/src/codexlens/__init__.py +28 -0
- package/codex-lens/src/codexlens/__main__.py +14 -0
- package/codex-lens/src/codexlens/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/__pycache__/__main__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/__pycache__/config.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/__pycache__/entities.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/__pycache__/errors.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/cli/__init__.py +27 -0
- package/codex-lens/src/codexlens/cli/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/cli/__pycache__/commands.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/cli/__pycache__/embedding_manager.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/cli/__pycache__/model_manager.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/cli/__pycache__/output.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/cli/commands.py +1931 -0
- package/codex-lens/src/codexlens/cli/embedding_manager.py +620 -0
- package/codex-lens/src/codexlens/cli/model_manager.py +289 -0
- package/codex-lens/src/codexlens/cli/output.py +124 -0
- package/codex-lens/src/codexlens/config.py +201 -0
- package/codex-lens/src/codexlens/entities.py +121 -0
- package/codex-lens/src/codexlens/errors.py +55 -0
- package/codex-lens/src/codexlens/indexing/README.md +77 -0
- package/codex-lens/src/codexlens/indexing/__init__.py +4 -0
- package/codex-lens/src/codexlens/indexing/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/indexing/__pycache__/symbol_extractor.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/indexing/symbol_extractor.py +243 -0
- package/codex-lens/src/codexlens/parsers/__init__.py +8 -0
- package/codex-lens/src/codexlens/parsers/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/parsers/__pycache__/encoding.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/parsers/__pycache__/factory.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/parsers/__pycache__/tokenizer.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/parsers/__pycache__/treesitter_parser.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/parsers/encoding.py +202 -0
- package/codex-lens/src/codexlens/parsers/factory.py +256 -0
- package/codex-lens/src/codexlens/parsers/tokenizer.py +98 -0
- package/codex-lens/src/codexlens/parsers/treesitter_parser.py +335 -0
- package/codex-lens/src/codexlens/search/__init__.py +15 -0
- package/codex-lens/src/codexlens/search/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/search/__pycache__/chain_search.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/search/__pycache__/enrichment.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/search/__pycache__/hybrid_search.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/search/__pycache__/query_parser.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/search/__pycache__/ranking.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/search/chain_search.py +647 -0
- package/codex-lens/src/codexlens/search/enrichment.py +150 -0
- package/codex-lens/src/codexlens/search/hybrid_search.py +313 -0
- package/codex-lens/src/codexlens/search/query_parser.py +242 -0
- package/codex-lens/src/codexlens/search/ranking.py +274 -0
- package/codex-lens/src/codexlens/semantic/__init__.py +39 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/ann_index.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/chunker.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/code_extractor.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/embedder.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/graph_analyzer.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/llm_enhancer.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/vector_store.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/ann_index.py +414 -0
- package/codex-lens/src/codexlens/semantic/chunker.py +448 -0
- package/codex-lens/src/codexlens/semantic/code_extractor.py +274 -0
- package/codex-lens/src/codexlens/semantic/embedder.py +185 -0
- package/codex-lens/src/codexlens/semantic/vector_store.py +955 -0
- package/codex-lens/src/codexlens/storage/__init__.py +29 -0
- package/codex-lens/src/codexlens/storage/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/dir_index.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/file_cache.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/index_tree.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/migration_manager.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/path_mapper.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/registry.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/sqlite_store.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/sqlite_utils.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/dir_index.py +1850 -0
- package/codex-lens/src/codexlens/storage/file_cache.py +32 -0
- package/codex-lens/src/codexlens/storage/index_tree.py +776 -0
- package/codex-lens/src/codexlens/storage/migration_manager.py +154 -0
- package/codex-lens/src/codexlens/storage/migrations/__init__.py +1 -0
- package/codex-lens/src/codexlens/storage/migrations/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_001_normalize_keywords.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_002_add_token_metadata.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_003_code_relationships.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_004_dual_fts.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_005_cleanup_unused_fields.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/migrations/migration_001_normalize_keywords.py +123 -0
- package/codex-lens/src/codexlens/storage/migrations/migration_002_add_token_metadata.py +48 -0
- package/codex-lens/src/codexlens/storage/migrations/migration_004_dual_fts.py +232 -0
- package/codex-lens/src/codexlens/storage/migrations/migration_005_cleanup_unused_fields.py +196 -0
- package/codex-lens/src/codexlens/storage/path_mapper.py +274 -0
- package/codex-lens/src/codexlens/storage/registry.py +670 -0
- package/codex-lens/src/codexlens/storage/sqlite_store.py +576 -0
- package/codex-lens/src/codexlens/storage/sqlite_utils.py +64 -0
- package/package.json +4 -1
- package/.claude/commands/memory/tech-research.md +0 -477
- package/.claude/scripts/classify-folders.sh +0 -39
- package/.claude/scripts/convert_tokens_to_css.sh +0 -229
- package/.claude/scripts/detect_changed_modules.sh +0 -161
- package/.claude/scripts/discover-design-files.sh +0 -87
- package/.claude/scripts/extract-animations.js +0 -243
- package/.claude/scripts/extract-computed-styles.js +0 -118
- package/.claude/scripts/extract-layout-structure.js +0 -411
- package/.claude/scripts/generate_module_docs.sh +0 -717
- package/.claude/scripts/get_modules_by_depth.sh +0 -170
- package/.claude/scripts/ui-generate-preview.sh +0 -395
- package/.claude/scripts/ui-instantiate-prototypes.sh +0 -815
- package/.claude/scripts/update_module_claude.sh +0 -337
- package/.claude/workflows/context-search-strategy.md +0 -77
- package/.claude/workflows/intelligent-tools-strategy.md +0 -662
- package/ccw/src/cli.js +0 -119
- package/ccw/src/commands/install.js +0 -324
- package/ccw/src/commands/tool.js +0 -138
- package/ccw/src/core/data-aggregator.js +0 -409
- package/ccw/src/core/server.js +0 -2063
- package/ccw/src/core/session-scanner.js +0 -235
- package/ccw/src/tools/classify-folders.js +0 -204
- package/ccw/src/tools/detect-changed-modules.js +0 -288
- package/ccw/src/tools/edit-file.js +0 -266
- package/ccw/src/tools/index.js +0 -176
- package/ccw/src/utils/file-utils.js +0 -48
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
"""Model Manager - Manage fastembed models for semantic search."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import os
|
|
5
|
+
import shutil
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Dict, List, Optional
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
from fastembed import TextEmbedding
|
|
11
|
+
FASTEMBED_AVAILABLE = True
|
|
12
|
+
except ImportError:
|
|
13
|
+
FASTEMBED_AVAILABLE = False
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# Model profiles with metadata
|
|
17
|
+
MODEL_PROFILES = {
|
|
18
|
+
"fast": {
|
|
19
|
+
"model_name": "BAAI/bge-small-en-v1.5",
|
|
20
|
+
"dimensions": 384,
|
|
21
|
+
"size_mb": 80,
|
|
22
|
+
"description": "Fast, lightweight, English-optimized",
|
|
23
|
+
"use_case": "Quick prototyping, resource-constrained environments",
|
|
24
|
+
},
|
|
25
|
+
"code": {
|
|
26
|
+
"model_name": "jinaai/jina-embeddings-v2-base-code",
|
|
27
|
+
"dimensions": 768,
|
|
28
|
+
"size_mb": 150,
|
|
29
|
+
"description": "Code-optimized, best for programming languages",
|
|
30
|
+
"use_case": "Open source projects, code semantic search",
|
|
31
|
+
},
|
|
32
|
+
"multilingual": {
|
|
33
|
+
"model_name": "intfloat/multilingual-e5-large",
|
|
34
|
+
"dimensions": 1024,
|
|
35
|
+
"size_mb": 1000,
|
|
36
|
+
"description": "Multilingual + code support",
|
|
37
|
+
"use_case": "Enterprise multilingual projects",
|
|
38
|
+
},
|
|
39
|
+
"balanced": {
|
|
40
|
+
"model_name": "mixedbread-ai/mxbai-embed-large-v1",
|
|
41
|
+
"dimensions": 1024,
|
|
42
|
+
"size_mb": 600,
|
|
43
|
+
"description": "High accuracy, general purpose",
|
|
44
|
+
"use_case": "High-quality semantic search, balanced performance",
|
|
45
|
+
},
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def get_cache_dir() -> Path:
|
|
50
|
+
"""Get fastembed cache directory.
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
Path to cache directory (usually ~/.cache/fastembed or %LOCALAPPDATA%\\Temp\\fastembed_cache)
|
|
54
|
+
"""
|
|
55
|
+
# Check HF_HOME environment variable first
|
|
56
|
+
if "HF_HOME" in os.environ:
|
|
57
|
+
return Path(os.environ["HF_HOME"])
|
|
58
|
+
|
|
59
|
+
# Default cache locations
|
|
60
|
+
if os.name == "nt": # Windows
|
|
61
|
+
cache_dir = Path(os.environ.get("LOCALAPPDATA", Path.home() / "AppData" / "Local")) / "Temp" / "fastembed_cache"
|
|
62
|
+
else: # Unix-like
|
|
63
|
+
cache_dir = Path.home() / ".cache" / "fastembed"
|
|
64
|
+
|
|
65
|
+
return cache_dir
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def list_models() -> Dict[str, any]:
|
|
69
|
+
"""List available model profiles and their installation status.
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
Dictionary with model profiles, installed status, and cache info
|
|
73
|
+
"""
|
|
74
|
+
if not FASTEMBED_AVAILABLE:
|
|
75
|
+
return {
|
|
76
|
+
"success": False,
|
|
77
|
+
"error": "fastembed not installed. Install with: pip install codexlens[semantic]",
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
cache_dir = get_cache_dir()
|
|
81
|
+
cache_exists = cache_dir.exists()
|
|
82
|
+
|
|
83
|
+
models = []
|
|
84
|
+
for profile, info in MODEL_PROFILES.items():
|
|
85
|
+
model_name = info["model_name"]
|
|
86
|
+
|
|
87
|
+
# Check if model is cached
|
|
88
|
+
installed = False
|
|
89
|
+
cache_size_mb = 0
|
|
90
|
+
|
|
91
|
+
if cache_exists:
|
|
92
|
+
# Check for model directory in cache
|
|
93
|
+
model_cache_path = cache_dir / f"models--{model_name.replace('/', '--')}"
|
|
94
|
+
if model_cache_path.exists():
|
|
95
|
+
installed = True
|
|
96
|
+
# Calculate cache size
|
|
97
|
+
total_size = sum(
|
|
98
|
+
f.stat().st_size
|
|
99
|
+
for f in model_cache_path.rglob("*")
|
|
100
|
+
if f.is_file()
|
|
101
|
+
)
|
|
102
|
+
cache_size_mb = round(total_size / (1024 * 1024), 1)
|
|
103
|
+
|
|
104
|
+
models.append({
|
|
105
|
+
"profile": profile,
|
|
106
|
+
"model_name": model_name,
|
|
107
|
+
"dimensions": info["dimensions"],
|
|
108
|
+
"estimated_size_mb": info["size_mb"],
|
|
109
|
+
"actual_size_mb": cache_size_mb if installed else None,
|
|
110
|
+
"description": info["description"],
|
|
111
|
+
"use_case": info["use_case"],
|
|
112
|
+
"installed": installed,
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
return {
|
|
116
|
+
"success": True,
|
|
117
|
+
"result": {
|
|
118
|
+
"models": models,
|
|
119
|
+
"cache_dir": str(cache_dir),
|
|
120
|
+
"cache_exists": cache_exists,
|
|
121
|
+
},
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def download_model(profile: str, progress_callback: Optional[callable] = None) -> Dict[str, any]:
|
|
126
|
+
"""Download a model by profile name.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
profile: Model profile name (fast, code, multilingual, balanced)
|
|
130
|
+
progress_callback: Optional callback function to report progress
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
Result dictionary with success status
|
|
134
|
+
"""
|
|
135
|
+
if not FASTEMBED_AVAILABLE:
|
|
136
|
+
return {
|
|
137
|
+
"success": False,
|
|
138
|
+
"error": "fastembed not installed. Install with: pip install codexlens[semantic]",
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if profile not in MODEL_PROFILES:
|
|
142
|
+
return {
|
|
143
|
+
"success": False,
|
|
144
|
+
"error": f"Unknown profile: {profile}. Available: {', '.join(MODEL_PROFILES.keys())}",
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
model_name = MODEL_PROFILES[profile]["model_name"]
|
|
148
|
+
|
|
149
|
+
try:
|
|
150
|
+
# Download model by instantiating TextEmbedding
|
|
151
|
+
# This will automatically download to cache if not present
|
|
152
|
+
if progress_callback:
|
|
153
|
+
progress_callback(f"Downloading {model_name}...")
|
|
154
|
+
|
|
155
|
+
embedder = TextEmbedding(model_name=model_name)
|
|
156
|
+
|
|
157
|
+
if progress_callback:
|
|
158
|
+
progress_callback(f"Model {model_name} downloaded successfully")
|
|
159
|
+
|
|
160
|
+
# Get cache info
|
|
161
|
+
cache_dir = get_cache_dir()
|
|
162
|
+
model_cache_path = cache_dir / f"models--{model_name.replace('/', '--')}"
|
|
163
|
+
|
|
164
|
+
cache_size = 0
|
|
165
|
+
if model_cache_path.exists():
|
|
166
|
+
total_size = sum(
|
|
167
|
+
f.stat().st_size
|
|
168
|
+
for f in model_cache_path.rglob("*")
|
|
169
|
+
if f.is_file()
|
|
170
|
+
)
|
|
171
|
+
cache_size = round(total_size / (1024 * 1024), 1)
|
|
172
|
+
|
|
173
|
+
return {
|
|
174
|
+
"success": True,
|
|
175
|
+
"result": {
|
|
176
|
+
"profile": profile,
|
|
177
|
+
"model_name": model_name,
|
|
178
|
+
"cache_size_mb": cache_size,
|
|
179
|
+
"cache_path": str(model_cache_path),
|
|
180
|
+
},
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
except Exception as e:
|
|
184
|
+
return {
|
|
185
|
+
"success": False,
|
|
186
|
+
"error": f"Failed to download model: {str(e)}",
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def delete_model(profile: str) -> Dict[str, any]:
|
|
191
|
+
"""Delete a downloaded model from cache.
|
|
192
|
+
|
|
193
|
+
Args:
|
|
194
|
+
profile: Model profile name to delete
|
|
195
|
+
|
|
196
|
+
Returns:
|
|
197
|
+
Result dictionary with success status
|
|
198
|
+
"""
|
|
199
|
+
if profile not in MODEL_PROFILES:
|
|
200
|
+
return {
|
|
201
|
+
"success": False,
|
|
202
|
+
"error": f"Unknown profile: {profile}. Available: {', '.join(MODEL_PROFILES.keys())}",
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
model_name = MODEL_PROFILES[profile]["model_name"]
|
|
206
|
+
cache_dir = get_cache_dir()
|
|
207
|
+
model_cache_path = cache_dir / f"models--{model_name.replace('/', '--')}"
|
|
208
|
+
|
|
209
|
+
if not model_cache_path.exists():
|
|
210
|
+
return {
|
|
211
|
+
"success": False,
|
|
212
|
+
"error": f"Model {profile} ({model_name}) is not installed",
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
try:
|
|
216
|
+
# Calculate size before deletion
|
|
217
|
+
total_size = sum(
|
|
218
|
+
f.stat().st_size
|
|
219
|
+
for f in model_cache_path.rglob("*")
|
|
220
|
+
if f.is_file()
|
|
221
|
+
)
|
|
222
|
+
size_mb = round(total_size / (1024 * 1024), 1)
|
|
223
|
+
|
|
224
|
+
# Delete model directory
|
|
225
|
+
shutil.rmtree(model_cache_path)
|
|
226
|
+
|
|
227
|
+
return {
|
|
228
|
+
"success": True,
|
|
229
|
+
"result": {
|
|
230
|
+
"profile": profile,
|
|
231
|
+
"model_name": model_name,
|
|
232
|
+
"deleted_size_mb": size_mb,
|
|
233
|
+
"cache_path": str(model_cache_path),
|
|
234
|
+
},
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
except Exception as e:
|
|
238
|
+
return {
|
|
239
|
+
"success": False,
|
|
240
|
+
"error": f"Failed to delete model: {str(e)}",
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def get_model_info(profile: str) -> Dict[str, any]:
|
|
245
|
+
"""Get detailed information about a model profile.
|
|
246
|
+
|
|
247
|
+
Args:
|
|
248
|
+
profile: Model profile name
|
|
249
|
+
|
|
250
|
+
Returns:
|
|
251
|
+
Result dictionary with model information
|
|
252
|
+
"""
|
|
253
|
+
if profile not in MODEL_PROFILES:
|
|
254
|
+
return {
|
|
255
|
+
"success": False,
|
|
256
|
+
"error": f"Unknown profile: {profile}. Available: {', '.join(MODEL_PROFILES.keys())}",
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
info = MODEL_PROFILES[profile]
|
|
260
|
+
model_name = info["model_name"]
|
|
261
|
+
|
|
262
|
+
# Check installation status
|
|
263
|
+
cache_dir = get_cache_dir()
|
|
264
|
+
model_cache_path = cache_dir / f"models--{model_name.replace('/', '--')}"
|
|
265
|
+
installed = model_cache_path.exists()
|
|
266
|
+
|
|
267
|
+
cache_size_mb = None
|
|
268
|
+
if installed:
|
|
269
|
+
total_size = sum(
|
|
270
|
+
f.stat().st_size
|
|
271
|
+
for f in model_cache_path.rglob("*")
|
|
272
|
+
if f.is_file()
|
|
273
|
+
)
|
|
274
|
+
cache_size_mb = round(total_size / (1024 * 1024), 1)
|
|
275
|
+
|
|
276
|
+
return {
|
|
277
|
+
"success": True,
|
|
278
|
+
"result": {
|
|
279
|
+
"profile": profile,
|
|
280
|
+
"model_name": model_name,
|
|
281
|
+
"dimensions": info["dimensions"],
|
|
282
|
+
"estimated_size_mb": info["size_mb"],
|
|
283
|
+
"actual_size_mb": cache_size_mb,
|
|
284
|
+
"description": info["description"],
|
|
285
|
+
"use_case": info["use_case"],
|
|
286
|
+
"installed": installed,
|
|
287
|
+
"cache_path": str(model_cache_path) if installed else None,
|
|
288
|
+
},
|
|
289
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"""Rich and JSON output helpers for CodexLens CLI."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import sys
|
|
7
|
+
from dataclasses import asdict, is_dataclass
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Any, Iterable, Mapping, Sequence
|
|
10
|
+
|
|
11
|
+
from rich.console import Console
|
|
12
|
+
from rich.table import Table
|
|
13
|
+
from rich.text import Text
|
|
14
|
+
|
|
15
|
+
from codexlens.entities import SearchResult, Symbol
|
|
16
|
+
|
|
17
|
+
# Force UTF-8 encoding for Windows console to properly display Chinese text
|
|
18
|
+
# Use force_terminal=True and legacy_windows=False to avoid GBK encoding issues
|
|
19
|
+
console = Console(force_terminal=True, legacy_windows=False)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _to_jsonable(value: Any) -> Any:
|
|
23
|
+
if value is None:
|
|
24
|
+
return None
|
|
25
|
+
if hasattr(value, "model_dump"):
|
|
26
|
+
return value.model_dump()
|
|
27
|
+
if is_dataclass(value):
|
|
28
|
+
return asdict(value)
|
|
29
|
+
if isinstance(value, Path):
|
|
30
|
+
return str(value)
|
|
31
|
+
if isinstance(value, Mapping):
|
|
32
|
+
return {k: _to_jsonable(v) for k, v in value.items()}
|
|
33
|
+
if isinstance(value, (list, tuple, set)):
|
|
34
|
+
return [_to_jsonable(v) for v in value]
|
|
35
|
+
return value
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def print_json(*, success: bool, result: Any = None, error: str | None = None) -> None:
|
|
39
|
+
payload: dict[str, Any] = {"success": success}
|
|
40
|
+
if success:
|
|
41
|
+
payload["result"] = _to_jsonable(result)
|
|
42
|
+
else:
|
|
43
|
+
payload["error"] = error or "Unknown error"
|
|
44
|
+
console.print_json(json.dumps(payload, ensure_ascii=False))
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def render_search_results(
|
|
48
|
+
results: Sequence[SearchResult], *, title: str = "Search Results", verbose: bool = False
|
|
49
|
+
) -> None:
|
|
50
|
+
"""Render search results with optional source tags in verbose mode.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
results: Search results to display
|
|
54
|
+
title: Table title
|
|
55
|
+
verbose: If True, show search source tags ([E], [F], [V]) and fusion scores
|
|
56
|
+
"""
|
|
57
|
+
table = Table(title=title, show_lines=False)
|
|
58
|
+
|
|
59
|
+
if verbose:
|
|
60
|
+
# Verbose mode: show source tags
|
|
61
|
+
table.add_column("Source", style="dim", width=6, justify="center")
|
|
62
|
+
|
|
63
|
+
table.add_column("Path", style="cyan", no_wrap=True)
|
|
64
|
+
table.add_column("Score", style="magenta", justify="right")
|
|
65
|
+
table.add_column("Excerpt", style="white")
|
|
66
|
+
|
|
67
|
+
for res in results:
|
|
68
|
+
excerpt = res.excerpt or ""
|
|
69
|
+
score_str = f"{res.score:.3f}"
|
|
70
|
+
|
|
71
|
+
if verbose:
|
|
72
|
+
# Extract search source tag if available
|
|
73
|
+
source = getattr(res, "search_source", None)
|
|
74
|
+
source_tag = ""
|
|
75
|
+
if source == "exact":
|
|
76
|
+
source_tag = "[E]"
|
|
77
|
+
elif source == "fuzzy":
|
|
78
|
+
source_tag = "[F]"
|
|
79
|
+
elif source == "vector":
|
|
80
|
+
source_tag = "[V]"
|
|
81
|
+
elif source == "fusion":
|
|
82
|
+
source_tag = "[RRF]"
|
|
83
|
+
table.add_row(source_tag, res.path, score_str, excerpt)
|
|
84
|
+
else:
|
|
85
|
+
table.add_row(res.path, score_str, excerpt)
|
|
86
|
+
|
|
87
|
+
console.print(table)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def render_symbols(symbols: Sequence[Symbol], *, title: str = "Symbols") -> None:
|
|
91
|
+
table = Table(title=title)
|
|
92
|
+
table.add_column("Name", style="green")
|
|
93
|
+
table.add_column("Kind", style="yellow")
|
|
94
|
+
table.add_column("Range", style="white", justify="right")
|
|
95
|
+
|
|
96
|
+
for sym in symbols:
|
|
97
|
+
start, end = sym.range
|
|
98
|
+
table.add_row(sym.name, sym.kind, f"{start}-{end}")
|
|
99
|
+
|
|
100
|
+
console.print(table)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def render_status(stats: Mapping[str, Any]) -> None:
|
|
104
|
+
table = Table(title="Index Status")
|
|
105
|
+
table.add_column("Metric", style="cyan")
|
|
106
|
+
table.add_column("Value", style="white")
|
|
107
|
+
|
|
108
|
+
for key, value in stats.items():
|
|
109
|
+
if isinstance(value, Mapping):
|
|
110
|
+
value_text = ", ".join(f"{k}:{v}" for k, v in value.items())
|
|
111
|
+
elif isinstance(value, (list, tuple)):
|
|
112
|
+
value_text = ", ".join(str(v) for v in value)
|
|
113
|
+
else:
|
|
114
|
+
value_text = str(value)
|
|
115
|
+
table.add_row(str(key), value_text)
|
|
116
|
+
|
|
117
|
+
console.print(table)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def render_file_inspect(path: str, language: str, symbols: Iterable[Symbol]) -> None:
|
|
121
|
+
header = Text.assemble(("File: ", "bold"), (path, "cyan"), (" Language: ", "bold"), (language, "green"))
|
|
122
|
+
console.print(header)
|
|
123
|
+
render_symbols(list(symbols), title="Discovered Symbols")
|
|
124
|
+
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
"""Configuration system for CodexLens."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
from dataclasses import dataclass, field
|
|
7
|
+
from functools import cached_property
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Any, Dict, List, Optional
|
|
10
|
+
|
|
11
|
+
from .errors import ConfigError
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# Workspace-local directory name
|
|
15
|
+
WORKSPACE_DIR_NAME = ".codexlens"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _default_global_dir() -> Path:
|
|
19
|
+
"""Get global CodexLens data directory."""
|
|
20
|
+
env_override = os.getenv("CODEXLENS_DATA_DIR")
|
|
21
|
+
if env_override:
|
|
22
|
+
return Path(env_override).expanduser().resolve()
|
|
23
|
+
return (Path.home() / ".codexlens").resolve()
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def find_workspace_root(start_path: Path) -> Optional[Path]:
|
|
27
|
+
"""Find the workspace root by looking for .codexlens directory.
|
|
28
|
+
|
|
29
|
+
Searches from start_path upward to find an existing .codexlens directory.
|
|
30
|
+
Returns None if not found.
|
|
31
|
+
"""
|
|
32
|
+
current = start_path.resolve()
|
|
33
|
+
|
|
34
|
+
# Search up to filesystem root
|
|
35
|
+
while current != current.parent:
|
|
36
|
+
workspace_dir = current / WORKSPACE_DIR_NAME
|
|
37
|
+
if workspace_dir.is_dir():
|
|
38
|
+
return current
|
|
39
|
+
current = current.parent
|
|
40
|
+
|
|
41
|
+
# Check root as well
|
|
42
|
+
workspace_dir = current / WORKSPACE_DIR_NAME
|
|
43
|
+
if workspace_dir.is_dir():
|
|
44
|
+
return current
|
|
45
|
+
|
|
46
|
+
return None
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@dataclass
|
|
50
|
+
class Config:
|
|
51
|
+
"""Runtime configuration for CodexLens.
|
|
52
|
+
|
|
53
|
+
- data_dir: Base directory for all persistent CodexLens data.
|
|
54
|
+
- venv_path: Optional virtualenv used for language tooling.
|
|
55
|
+
- supported_languages: Language IDs and their associated file extensions.
|
|
56
|
+
- parsing_rules: Per-language parsing and chunking hints.
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
data_dir: Path = field(default_factory=_default_global_dir)
|
|
60
|
+
venv_path: Path = field(default_factory=lambda: _default_global_dir() / "venv")
|
|
61
|
+
supported_languages: Dict[str, Dict[str, Any]] = field(
|
|
62
|
+
default_factory=lambda: {
|
|
63
|
+
"python": {"extensions": [".py"], "tree_sitter_language": "python"},
|
|
64
|
+
"javascript": {"extensions": [".js", ".jsx"], "tree_sitter_language": "javascript"},
|
|
65
|
+
"typescript": {"extensions": [".ts", ".tsx"], "tree_sitter_language": "typescript"},
|
|
66
|
+
"java": {"extensions": [".java"], "tree_sitter_language": "java"},
|
|
67
|
+
"go": {"extensions": [".go"], "tree_sitter_language": "go"},
|
|
68
|
+
"zig": {"extensions": [".zig"], "tree_sitter_language": "zig"},
|
|
69
|
+
"objective-c": {"extensions": [".m", ".mm"], "tree_sitter_language": "objc"},
|
|
70
|
+
"markdown": {"extensions": [".md", ".mdx"], "tree_sitter_language": None},
|
|
71
|
+
"text": {"extensions": [".txt"], "tree_sitter_language": None},
|
|
72
|
+
}
|
|
73
|
+
)
|
|
74
|
+
parsing_rules: Dict[str, Dict[str, Any]] = field(
|
|
75
|
+
default_factory=lambda: {
|
|
76
|
+
"default": {
|
|
77
|
+
"max_chunk_chars": 4000,
|
|
78
|
+
"max_chunk_lines": 200,
|
|
79
|
+
"overlap_lines": 20,
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
llm_enabled: bool = False
|
|
85
|
+
llm_tool: str = "gemini"
|
|
86
|
+
llm_timeout_ms: int = 300000
|
|
87
|
+
llm_batch_size: int = 5
|
|
88
|
+
|
|
89
|
+
# Hybrid chunker configuration
|
|
90
|
+
hybrid_max_chunk_size: int = 2000 # Max characters per chunk before LLM refinement
|
|
91
|
+
hybrid_llm_refinement: bool = False # Enable LLM-based semantic boundary refinement
|
|
92
|
+
def __post_init__(self) -> None:
|
|
93
|
+
try:
|
|
94
|
+
self.data_dir = self.data_dir.expanduser().resolve()
|
|
95
|
+
self.venv_path = self.venv_path.expanduser().resolve()
|
|
96
|
+
self.data_dir.mkdir(parents=True, exist_ok=True)
|
|
97
|
+
except Exception as exc:
|
|
98
|
+
raise ConfigError(f"Failed to initialize data_dir at {self.data_dir}: {exc}") from exc
|
|
99
|
+
|
|
100
|
+
@cached_property
|
|
101
|
+
def cache_dir(self) -> Path:
|
|
102
|
+
"""Directory for transient caches."""
|
|
103
|
+
return self.data_dir / "cache"
|
|
104
|
+
|
|
105
|
+
@cached_property
|
|
106
|
+
def index_dir(self) -> Path:
|
|
107
|
+
"""Directory where index artifacts are stored."""
|
|
108
|
+
return self.data_dir / "index"
|
|
109
|
+
|
|
110
|
+
@cached_property
|
|
111
|
+
def db_path(self) -> Path:
|
|
112
|
+
"""Default SQLite index path."""
|
|
113
|
+
return self.index_dir / "codexlens.db"
|
|
114
|
+
|
|
115
|
+
def ensure_runtime_dirs(self) -> None:
|
|
116
|
+
"""Create standard runtime directories if missing."""
|
|
117
|
+
for directory in (self.cache_dir, self.index_dir):
|
|
118
|
+
try:
|
|
119
|
+
directory.mkdir(parents=True, exist_ok=True)
|
|
120
|
+
except Exception as exc:
|
|
121
|
+
raise ConfigError(f"Failed to create directory {directory}: {exc}") from exc
|
|
122
|
+
|
|
123
|
+
def language_for_path(self, path: str | Path) -> str | None:
|
|
124
|
+
"""Infer a supported language ID from a file path."""
|
|
125
|
+
extension = Path(path).suffix.lower()
|
|
126
|
+
for language_id, spec in self.supported_languages.items():
|
|
127
|
+
extensions: List[str] = spec.get("extensions", [])
|
|
128
|
+
if extension in extensions:
|
|
129
|
+
return language_id
|
|
130
|
+
return None
|
|
131
|
+
|
|
132
|
+
def rules_for_language(self, language_id: str) -> Dict[str, Any]:
|
|
133
|
+
"""Get parsing rules for a specific language, falling back to defaults."""
|
|
134
|
+
return {**self.parsing_rules.get("default", {}), **self.parsing_rules.get(language_id, {})}
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
@dataclass
|
|
138
|
+
class WorkspaceConfig:
|
|
139
|
+
"""Workspace-local configuration for CodexLens.
|
|
140
|
+
|
|
141
|
+
Stores index data in project/.codexlens/ directory.
|
|
142
|
+
"""
|
|
143
|
+
|
|
144
|
+
workspace_root: Path
|
|
145
|
+
|
|
146
|
+
def __post_init__(self) -> None:
|
|
147
|
+
self.workspace_root = Path(self.workspace_root).resolve()
|
|
148
|
+
|
|
149
|
+
@property
|
|
150
|
+
def codexlens_dir(self) -> Path:
|
|
151
|
+
"""The .codexlens directory in workspace root."""
|
|
152
|
+
return self.workspace_root / WORKSPACE_DIR_NAME
|
|
153
|
+
|
|
154
|
+
@property
|
|
155
|
+
def db_path(self) -> Path:
|
|
156
|
+
"""SQLite index path for this workspace."""
|
|
157
|
+
return self.codexlens_dir / "index.db"
|
|
158
|
+
|
|
159
|
+
@property
|
|
160
|
+
def cache_dir(self) -> Path:
|
|
161
|
+
"""Cache directory for this workspace."""
|
|
162
|
+
return self.codexlens_dir / "cache"
|
|
163
|
+
|
|
164
|
+
def initialize(self) -> None:
|
|
165
|
+
"""Create the .codexlens directory structure."""
|
|
166
|
+
try:
|
|
167
|
+
self.codexlens_dir.mkdir(parents=True, exist_ok=True)
|
|
168
|
+
self.cache_dir.mkdir(parents=True, exist_ok=True)
|
|
169
|
+
|
|
170
|
+
# Create .gitignore to exclude cache but keep index
|
|
171
|
+
gitignore_path = self.codexlens_dir / ".gitignore"
|
|
172
|
+
if not gitignore_path.exists():
|
|
173
|
+
gitignore_path.write_text(
|
|
174
|
+
"# CodexLens workspace data\n"
|
|
175
|
+
"cache/\n"
|
|
176
|
+
"*.log\n"
|
|
177
|
+
)
|
|
178
|
+
except Exception as exc:
|
|
179
|
+
raise ConfigError(f"Failed to initialize workspace at {self.codexlens_dir}: {exc}") from exc
|
|
180
|
+
|
|
181
|
+
def exists(self) -> bool:
|
|
182
|
+
"""Check if workspace is already initialized."""
|
|
183
|
+
return self.codexlens_dir.is_dir() and self.db_path.exists()
|
|
184
|
+
|
|
185
|
+
@classmethod
|
|
186
|
+
def from_path(cls, path: Path) -> Optional["WorkspaceConfig"]:
|
|
187
|
+
"""Create WorkspaceConfig from a path by finding workspace root.
|
|
188
|
+
|
|
189
|
+
Returns None if no workspace found.
|
|
190
|
+
"""
|
|
191
|
+
root = find_workspace_root(path)
|
|
192
|
+
if root is None:
|
|
193
|
+
return None
|
|
194
|
+
return cls(workspace_root=root)
|
|
195
|
+
|
|
196
|
+
@classmethod
|
|
197
|
+
def create_at(cls, path: Path) -> "WorkspaceConfig":
|
|
198
|
+
"""Create a new workspace at the given path."""
|
|
199
|
+
config = cls(workspace_root=path)
|
|
200
|
+
config.initialize()
|
|
201
|
+
return config
|