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,626 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graph Routes Module
|
|
3
|
+
* Handles graph visualization API endpoints for codex-lens data
|
|
4
|
+
*/
|
|
5
|
+
import type { IncomingMessage, ServerResponse } from 'http';
|
|
6
|
+
import { homedir } from 'os';
|
|
7
|
+
import { join, resolve, normalize } from 'path';
|
|
8
|
+
import { existsSync, readdirSync } from 'fs';
|
|
9
|
+
import Database from 'better-sqlite3';
|
|
10
|
+
|
|
11
|
+
export interface RouteContext {
|
|
12
|
+
pathname: string;
|
|
13
|
+
url: URL;
|
|
14
|
+
req: IncomingMessage;
|
|
15
|
+
res: ServerResponse;
|
|
16
|
+
initialPath: string;
|
|
17
|
+
handlePostRequest: (req: IncomingMessage, res: ServerResponse, handler: (body: unknown) => Promise<any>) => void;
|
|
18
|
+
broadcastToClients: (data: unknown) => void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* PathMapper utility class (simplified from codex-lens Python implementation)
|
|
23
|
+
* Maps source paths to index database paths
|
|
24
|
+
*/
|
|
25
|
+
class PathMapper {
|
|
26
|
+
private indexRoot: string;
|
|
27
|
+
|
|
28
|
+
constructor(indexRoot?: string) {
|
|
29
|
+
this.indexRoot = indexRoot || join(homedir(), '.codexlens', 'indexes');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Normalize path to cross-platform storage format
|
|
34
|
+
* Windows: D:\path\to\dir → D/path/to/dir
|
|
35
|
+
* Unix: /home/user/path → home/user/path
|
|
36
|
+
*/
|
|
37
|
+
normalizePath(sourcePath: string): string {
|
|
38
|
+
const resolved = sourcePath.replace(/\\/g, '/');
|
|
39
|
+
|
|
40
|
+
// Handle Windows paths with drive letters
|
|
41
|
+
if (process.platform === 'win32' && /^[A-Za-z]:/.test(resolved)) {
|
|
42
|
+
const drive = resolved[0]; // D
|
|
43
|
+
const rest = resolved.slice(2); // /path/to/dir
|
|
44
|
+
return `${drive}${rest}`.replace(/^\//, '');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Handle Unix paths - remove leading slash
|
|
48
|
+
return resolved.replace(/^\//, '');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Convert source path to index database path
|
|
53
|
+
*/
|
|
54
|
+
sourceToIndexDb(sourcePath: string): string {
|
|
55
|
+
const normalized = this.normalizePath(sourcePath);
|
|
56
|
+
return join(this.indexRoot, normalized, '_index.db');
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
interface GraphNode {
|
|
61
|
+
id: string;
|
|
62
|
+
name: string;
|
|
63
|
+
type: string;
|
|
64
|
+
file: string;
|
|
65
|
+
line: number;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
interface GraphEdge {
|
|
69
|
+
source: string;
|
|
70
|
+
target: string;
|
|
71
|
+
type: string;
|
|
72
|
+
sourceLine: number;
|
|
73
|
+
sourceFile: string;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
interface ImpactAnalysis {
|
|
77
|
+
directDependents: string[];
|
|
78
|
+
affectedFiles: string[];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Validate and sanitize project path to prevent path traversal attacks
|
|
83
|
+
* @returns sanitized absolute path or null if invalid
|
|
84
|
+
*/
|
|
85
|
+
function validateProjectPath(projectPath: string, initialPath: string): string | null {
|
|
86
|
+
if (!projectPath) {
|
|
87
|
+
return initialPath;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Resolve to absolute path
|
|
91
|
+
const resolved = resolve(projectPath);
|
|
92
|
+
const normalized = normalize(resolved);
|
|
93
|
+
|
|
94
|
+
// Check for path traversal attempts
|
|
95
|
+
if (normalized.includes('..') || normalized !== resolved) {
|
|
96
|
+
console.error(`[Graph] Path traversal attempt blocked: ${projectPath}`);
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Ensure path exists and is a directory
|
|
101
|
+
if (!existsSync(normalized)) {
|
|
102
|
+
console.error(`[Graph] Path does not exist: ${normalized}`);
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return normalized;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Find all _index.db files recursively in a directory
|
|
111
|
+
* @param dir Directory to search
|
|
112
|
+
* @returns Array of absolute paths to _index.db files
|
|
113
|
+
*/
|
|
114
|
+
function findAllIndexDbs(dir: string): string[] {
|
|
115
|
+
const dbs: string[] = [];
|
|
116
|
+
|
|
117
|
+
function traverse(currentDir: string): void {
|
|
118
|
+
const dbPath = join(currentDir, '_index.db');
|
|
119
|
+
if (existsSync(dbPath)) {
|
|
120
|
+
dbs.push(dbPath);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
try {
|
|
124
|
+
const entries = readdirSync(currentDir, { withFileTypes: true });
|
|
125
|
+
for (const entry of entries) {
|
|
126
|
+
if (entry.isDirectory()) {
|
|
127
|
+
traverse(join(currentDir, entry.name));
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
} catch {
|
|
131
|
+
// Silently skip directories we can't read
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
traverse(dir);
|
|
136
|
+
return dbs;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Map codex-lens symbol kinds to graph node types
|
|
141
|
+
* Returns null for non-code symbols (markdown headings, etc.)
|
|
142
|
+
*/
|
|
143
|
+
function mapSymbolKind(kind: string): string | null {
|
|
144
|
+
const kindLower = kind.toLowerCase();
|
|
145
|
+
|
|
146
|
+
// Exclude markdown headings
|
|
147
|
+
if (/^h[1-6]$/.test(kindLower)) {
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const kindMap: Record<string, string> = {
|
|
152
|
+
'function': 'FUNCTION',
|
|
153
|
+
'class': 'CLASS',
|
|
154
|
+
'method': 'METHOD',
|
|
155
|
+
'variable': 'VARIABLE',
|
|
156
|
+
'module': 'MODULE',
|
|
157
|
+
'interface': 'CLASS', // TypeScript interfaces as CLASS
|
|
158
|
+
'type': 'CLASS', // Type aliases as CLASS
|
|
159
|
+
'constant': 'VARIABLE',
|
|
160
|
+
'property': 'VARIABLE',
|
|
161
|
+
'parameter': 'VARIABLE',
|
|
162
|
+
'import': 'MODULE',
|
|
163
|
+
'export': 'MODULE',
|
|
164
|
+
};
|
|
165
|
+
return kindMap[kindLower] || 'VARIABLE';
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Map codex-lens relationship types to graph edge types
|
|
170
|
+
*/
|
|
171
|
+
function mapRelationType(relType: string): string {
|
|
172
|
+
const typeMap: Record<string, string> = {
|
|
173
|
+
'call': 'CALLS',
|
|
174
|
+
'import': 'IMPORTS',
|
|
175
|
+
'inherits': 'INHERITS',
|
|
176
|
+
'uses': 'CALLS', // Fallback uses → CALLS
|
|
177
|
+
};
|
|
178
|
+
return typeMap[relType.toLowerCase()] || 'CALLS';
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Query symbols from all codex-lens databases (hierarchical structure)
|
|
183
|
+
* @param projectPath Root project path
|
|
184
|
+
* @param fileFilter Optional file path filter (supports wildcards)
|
|
185
|
+
* @param moduleFilter Optional module/directory filter
|
|
186
|
+
*/
|
|
187
|
+
async function querySymbols(projectPath: string, fileFilter?: string, moduleFilter?: string): Promise<GraphNode[]> {
|
|
188
|
+
const mapper = new PathMapper();
|
|
189
|
+
const rootDbPath = mapper.sourceToIndexDb(projectPath);
|
|
190
|
+
const indexRoot = rootDbPath.replace(/[\\/]_index\.db$/, '');
|
|
191
|
+
|
|
192
|
+
if (!existsSync(indexRoot)) {
|
|
193
|
+
return [];
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Find all _index.db files recursively
|
|
197
|
+
const dbPaths = findAllIndexDbs(indexRoot);
|
|
198
|
+
|
|
199
|
+
if (dbPaths.length === 0) {
|
|
200
|
+
return [];
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const allNodes: GraphNode[] = [];
|
|
204
|
+
|
|
205
|
+
for (const dbPath of dbPaths) {
|
|
206
|
+
try {
|
|
207
|
+
const db = Database(dbPath, { readonly: true });
|
|
208
|
+
|
|
209
|
+
// Build WHERE clause for filtering
|
|
210
|
+
let whereClause = '';
|
|
211
|
+
const params: string[] = [];
|
|
212
|
+
|
|
213
|
+
if (fileFilter) {
|
|
214
|
+
const sanitized = sanitizeForLike(fileFilter);
|
|
215
|
+
whereClause = 'WHERE f.full_path LIKE ?';
|
|
216
|
+
params.push(`%${sanitized}%`);
|
|
217
|
+
} else if (moduleFilter) {
|
|
218
|
+
const sanitized = sanitizeForLike(moduleFilter);
|
|
219
|
+
whereClause = 'WHERE f.full_path LIKE ?';
|
|
220
|
+
params.push(`${sanitized}%`);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const query = `
|
|
224
|
+
SELECT
|
|
225
|
+
s.id,
|
|
226
|
+
s.name,
|
|
227
|
+
s.kind,
|
|
228
|
+
s.start_line,
|
|
229
|
+
f.full_path as file
|
|
230
|
+
FROM symbols s
|
|
231
|
+
JOIN files f ON s.file_id = f.id
|
|
232
|
+
${whereClause}
|
|
233
|
+
ORDER BY f.full_path, s.start_line
|
|
234
|
+
`;
|
|
235
|
+
|
|
236
|
+
const rows = params.length > 0 ? db.prepare(query).all(...params) : db.prepare(query).all();
|
|
237
|
+
|
|
238
|
+
db.close();
|
|
239
|
+
|
|
240
|
+
// Filter out non-code symbols (markdown headings, etc.)
|
|
241
|
+
rows.forEach((row: any) => {
|
|
242
|
+
const type = mapSymbolKind(row.kind);
|
|
243
|
+
if (type !== null) {
|
|
244
|
+
allNodes.push({
|
|
245
|
+
id: `${row.file}:${row.name}:${row.start_line}`,
|
|
246
|
+
name: row.name,
|
|
247
|
+
type,
|
|
248
|
+
file: row.file,
|
|
249
|
+
line: row.start_line,
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
} catch (err) {
|
|
254
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
255
|
+
console.error(`[Graph] Failed to query symbols from ${dbPath}: ${message}`);
|
|
256
|
+
// Continue with other databases even if one fails
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
return allNodes;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Query code relationships from all codex-lens databases (hierarchical structure)
|
|
265
|
+
* @param projectPath Root project path
|
|
266
|
+
* @param fileFilter Optional file path filter (supports wildcards)
|
|
267
|
+
* @param moduleFilter Optional module/directory filter
|
|
268
|
+
*/
|
|
269
|
+
async function queryRelationships(projectPath: string, fileFilter?: string, moduleFilter?: string): Promise<GraphEdge[]> {
|
|
270
|
+
const mapper = new PathMapper();
|
|
271
|
+
const rootDbPath = mapper.sourceToIndexDb(projectPath);
|
|
272
|
+
const indexRoot = rootDbPath.replace(/[\\/]_index\.db$/, '');
|
|
273
|
+
|
|
274
|
+
if (!existsSync(indexRoot)) {
|
|
275
|
+
return [];
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Find all _index.db files recursively
|
|
279
|
+
const dbPaths = findAllIndexDbs(indexRoot);
|
|
280
|
+
|
|
281
|
+
if (dbPaths.length === 0) {
|
|
282
|
+
return [];
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
const allEdges: GraphEdge[] = [];
|
|
286
|
+
|
|
287
|
+
for (const dbPath of dbPaths) {
|
|
288
|
+
try {
|
|
289
|
+
const db = Database(dbPath, { readonly: true });
|
|
290
|
+
|
|
291
|
+
// Build WHERE clause for filtering
|
|
292
|
+
let whereClause = '';
|
|
293
|
+
const params: string[] = [];
|
|
294
|
+
|
|
295
|
+
if (fileFilter) {
|
|
296
|
+
const sanitized = sanitizeForLike(fileFilter);
|
|
297
|
+
whereClause = 'WHERE f.full_path LIKE ?';
|
|
298
|
+
params.push(`%${sanitized}%`);
|
|
299
|
+
} else if (moduleFilter) {
|
|
300
|
+
const sanitized = sanitizeForLike(moduleFilter);
|
|
301
|
+
whereClause = 'WHERE f.full_path LIKE ?';
|
|
302
|
+
params.push(`${sanitized}%`);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const query = `
|
|
306
|
+
SELECT
|
|
307
|
+
s.name as source_name,
|
|
308
|
+
s.start_line as source_line,
|
|
309
|
+
f.full_path as source_file,
|
|
310
|
+
r.target_qualified_name,
|
|
311
|
+
r.relationship_type,
|
|
312
|
+
r.target_file
|
|
313
|
+
FROM code_relationships r
|
|
314
|
+
JOIN symbols s ON r.source_symbol_id = s.id
|
|
315
|
+
JOIN files f ON s.file_id = f.id
|
|
316
|
+
${whereClause}
|
|
317
|
+
ORDER BY f.full_path, s.start_line
|
|
318
|
+
`;
|
|
319
|
+
|
|
320
|
+
const rows = params.length > 0 ? db.prepare(query).all(...params) : db.prepare(query).all();
|
|
321
|
+
|
|
322
|
+
db.close();
|
|
323
|
+
|
|
324
|
+
allEdges.push(...rows.map((row: any) => ({
|
|
325
|
+
source: `${row.source_file}:${row.source_name}:${row.source_line}`,
|
|
326
|
+
target: row.target_qualified_name,
|
|
327
|
+
type: mapRelationType(row.relationship_type),
|
|
328
|
+
sourceLine: row.source_line,
|
|
329
|
+
sourceFile: row.source_file,
|
|
330
|
+
})));
|
|
331
|
+
} catch (err) {
|
|
332
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
333
|
+
console.error(`[Graph] Failed to query relationships from ${dbPath}: ${message}`);
|
|
334
|
+
// Continue with other databases even if one fails
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
return allEdges;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Sanitize a string for use in SQL LIKE patterns
|
|
343
|
+
* Escapes special characters: %, _, [, ]
|
|
344
|
+
*/
|
|
345
|
+
function sanitizeForLike(input: string): string {
|
|
346
|
+
return input
|
|
347
|
+
.replace(/\[/g, '[[]') // Escape [ first
|
|
348
|
+
.replace(/%/g, '[%]') // Escape %
|
|
349
|
+
.replace(/_/g, '[_]'); // Escape _
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Validate and parse symbol ID format
|
|
354
|
+
* Expected format: file:name:line or just symbolName
|
|
355
|
+
* @returns sanitized symbol name or null if invalid
|
|
356
|
+
*/
|
|
357
|
+
function parseSymbolId(symbolId: string): string | null {
|
|
358
|
+
if (!symbolId || symbolId.length > 500) {
|
|
359
|
+
return null;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Remove any potentially dangerous characters
|
|
363
|
+
const sanitized = symbolId.replace(/[<>'";&|`$\\]/g, '');
|
|
364
|
+
|
|
365
|
+
// Parse the format: file:name:line
|
|
366
|
+
const parts = sanitized.split(':');
|
|
367
|
+
if (parts.length >= 2) {
|
|
368
|
+
// Return the name part (second element)
|
|
369
|
+
const name = parts[1].trim();
|
|
370
|
+
return name.length > 0 ? name : null;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// If no colons, use the whole string as name
|
|
374
|
+
return sanitized.trim() || null;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Perform impact analysis for a symbol
|
|
379
|
+
* Find all symbols that depend on this symbol (direct and transitive)
|
|
380
|
+
*/
|
|
381
|
+
async function analyzeImpact(projectPath: string, symbolId: string): Promise<ImpactAnalysis> {
|
|
382
|
+
const mapper = new PathMapper();
|
|
383
|
+
const dbPath = mapper.sourceToIndexDb(projectPath);
|
|
384
|
+
|
|
385
|
+
if (!existsSync(dbPath)) {
|
|
386
|
+
return { directDependents: [], affectedFiles: [] };
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// Parse and validate symbol ID
|
|
390
|
+
const symbolName = parseSymbolId(symbolId);
|
|
391
|
+
if (!symbolName) {
|
|
392
|
+
console.error(`[Graph] Invalid symbol ID format: ${symbolId}`);
|
|
393
|
+
return { directDependents: [], affectedFiles: [] };
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
try {
|
|
397
|
+
const db = Database(dbPath, { readonly: true });
|
|
398
|
+
|
|
399
|
+
// Sanitize for LIKE query to prevent injection via special characters
|
|
400
|
+
const sanitizedName = sanitizeForLike(symbolName);
|
|
401
|
+
|
|
402
|
+
// Find all symbols that reference this symbol
|
|
403
|
+
const rows = db.prepare(`
|
|
404
|
+
SELECT DISTINCT
|
|
405
|
+
s.name as dependent_name,
|
|
406
|
+
f.full_path as dependent_file,
|
|
407
|
+
s.start_line as dependent_line
|
|
408
|
+
FROM code_relationships r
|
|
409
|
+
JOIN symbols s ON r.source_symbol_id = s.id
|
|
410
|
+
JOIN files f ON s.file_id = f.id
|
|
411
|
+
WHERE r.target_qualified_name LIKE ?
|
|
412
|
+
`).all(`%${sanitizedName}%`);
|
|
413
|
+
|
|
414
|
+
db.close();
|
|
415
|
+
|
|
416
|
+
const directDependents = rows.map((row: any) =>
|
|
417
|
+
`${row.dependent_file}:${row.dependent_name}:${row.dependent_line}`
|
|
418
|
+
);
|
|
419
|
+
|
|
420
|
+
const affectedFiles = [...new Set(rows.map((row: any) => row.dependent_file))];
|
|
421
|
+
|
|
422
|
+
return {
|
|
423
|
+
directDependents,
|
|
424
|
+
affectedFiles,
|
|
425
|
+
};
|
|
426
|
+
} catch (err) {
|
|
427
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
428
|
+
console.error(`[Graph] Failed to analyze impact: ${message}`);
|
|
429
|
+
return { directDependents: [], affectedFiles: [] };
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
/**
|
|
434
|
+
* Handle Graph routes
|
|
435
|
+
* @returns true if route was handled, false otherwise
|
|
436
|
+
*/
|
|
437
|
+
export async function handleGraphRoutes(ctx: RouteContext): Promise<boolean> {
|
|
438
|
+
const { pathname, url, req, res, initialPath } = ctx;
|
|
439
|
+
|
|
440
|
+
// API: Graph Nodes - Get all symbols as graph nodes
|
|
441
|
+
if (pathname === '/api/graph/nodes') {
|
|
442
|
+
const rawPath = url.searchParams.get('path') || initialPath;
|
|
443
|
+
const projectPath = validateProjectPath(rawPath, initialPath);
|
|
444
|
+
const limitStr = url.searchParams.get('limit') || '1000';
|
|
445
|
+
const limit = Math.min(parseInt(limitStr, 10) || 1000, 5000); // Max 5000 nodes
|
|
446
|
+
const fileFilter = url.searchParams.get('file') || undefined;
|
|
447
|
+
const moduleFilter = url.searchParams.get('module') || undefined;
|
|
448
|
+
|
|
449
|
+
if (!projectPath) {
|
|
450
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
451
|
+
res.end(JSON.stringify({ error: 'Invalid project path', nodes: [] }));
|
|
452
|
+
return true;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
try {
|
|
456
|
+
const allNodes = await querySymbols(projectPath, fileFilter, moduleFilter);
|
|
457
|
+
const nodes = allNodes.slice(0, limit);
|
|
458
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
459
|
+
res.end(JSON.stringify({
|
|
460
|
+
nodes,
|
|
461
|
+
total: allNodes.length,
|
|
462
|
+
limit,
|
|
463
|
+
hasMore: allNodes.length > limit,
|
|
464
|
+
filters: { file: fileFilter, module: moduleFilter }
|
|
465
|
+
}));
|
|
466
|
+
} catch (err) {
|
|
467
|
+
console.error(`[Graph] Error fetching nodes:`, err);
|
|
468
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
469
|
+
res.end(JSON.stringify({ error: 'Failed to fetch graph nodes', nodes: [] }));
|
|
470
|
+
}
|
|
471
|
+
return true;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// API: Graph Edges - Get all relationships as graph edges
|
|
475
|
+
if (pathname === '/api/graph/edges') {
|
|
476
|
+
const rawPath = url.searchParams.get('path') || initialPath;
|
|
477
|
+
const projectPath = validateProjectPath(rawPath, initialPath);
|
|
478
|
+
const limitStr = url.searchParams.get('limit') || '2000';
|
|
479
|
+
const limit = Math.min(parseInt(limitStr, 10) || 2000, 10000); // Max 10000 edges
|
|
480
|
+
const fileFilter = url.searchParams.get('file') || undefined;
|
|
481
|
+
const moduleFilter = url.searchParams.get('module') || undefined;
|
|
482
|
+
|
|
483
|
+
if (!projectPath) {
|
|
484
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
485
|
+
res.end(JSON.stringify({ error: 'Invalid project path', edges: [] }));
|
|
486
|
+
return true;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
try {
|
|
490
|
+
const allEdges = await queryRelationships(projectPath, fileFilter, moduleFilter);
|
|
491
|
+
const edges = allEdges.slice(0, limit);
|
|
492
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
493
|
+
res.end(JSON.stringify({
|
|
494
|
+
edges,
|
|
495
|
+
total: allEdges.length,
|
|
496
|
+
limit,
|
|
497
|
+
hasMore: allEdges.length > limit,
|
|
498
|
+
filters: { file: fileFilter, module: moduleFilter }
|
|
499
|
+
}));
|
|
500
|
+
} catch (err) {
|
|
501
|
+
console.error(`[Graph] Error fetching edges:`, err);
|
|
502
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
503
|
+
res.end(JSON.stringify({ error: 'Failed to fetch graph edges', edges: [] }));
|
|
504
|
+
}
|
|
505
|
+
return true;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// API: Get available files and modules for filtering
|
|
509
|
+
if (pathname === '/api/graph/files') {
|
|
510
|
+
const rawPath = url.searchParams.get('path') || initialPath;
|
|
511
|
+
const projectPath = validateProjectPath(rawPath, initialPath);
|
|
512
|
+
|
|
513
|
+
if (!projectPath) {
|
|
514
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
515
|
+
res.end(JSON.stringify({ error: 'Invalid project path', files: [], modules: [] }));
|
|
516
|
+
return true;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
try {
|
|
520
|
+
const mapper = new PathMapper();
|
|
521
|
+
const rootDbPath = mapper.sourceToIndexDb(projectPath);
|
|
522
|
+
const indexRoot = rootDbPath.replace(/[\\/]_index\.db$/, '');
|
|
523
|
+
|
|
524
|
+
if (!existsSync(indexRoot)) {
|
|
525
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
526
|
+
res.end(JSON.stringify({ files: [], modules: [] }));
|
|
527
|
+
return true;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
const dbPaths = findAllIndexDbs(indexRoot);
|
|
531
|
+
const filesSet = new Set<string>();
|
|
532
|
+
const modulesSet = new Set<string>();
|
|
533
|
+
|
|
534
|
+
for (const dbPath of dbPaths) {
|
|
535
|
+
try {
|
|
536
|
+
const db = Database(dbPath, { readonly: true });
|
|
537
|
+
const rows = db.prepare(`SELECT DISTINCT full_path FROM files`).all();
|
|
538
|
+
db.close();
|
|
539
|
+
|
|
540
|
+
rows.forEach((row: any) => {
|
|
541
|
+
const filePath = row.full_path;
|
|
542
|
+
filesSet.add(filePath);
|
|
543
|
+
|
|
544
|
+
// Extract module path (directory)
|
|
545
|
+
const lastSlash = Math.max(filePath.lastIndexOf('/'), filePath.lastIndexOf('\\'));
|
|
546
|
+
if (lastSlash > 0) {
|
|
547
|
+
const modulePath = filePath.substring(0, lastSlash);
|
|
548
|
+
modulesSet.add(modulePath);
|
|
549
|
+
}
|
|
550
|
+
});
|
|
551
|
+
} catch (err) {
|
|
552
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
553
|
+
console.error(`[Graph] Failed to query files from ${dbPath}: ${message}`);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
const files = Array.from(filesSet).sort();
|
|
558
|
+
const modules = Array.from(modulesSet).sort();
|
|
559
|
+
|
|
560
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
561
|
+
res.end(JSON.stringify({ files, modules }));
|
|
562
|
+
} catch (err) {
|
|
563
|
+
console.error(`[Graph] Error fetching files:`, err);
|
|
564
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
565
|
+
res.end(JSON.stringify({ error: 'Failed to fetch files and modules', files: [], modules: [] }));
|
|
566
|
+
}
|
|
567
|
+
return true;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// API: Impact Analysis - Get impact analysis for a symbol
|
|
571
|
+
if (pathname === '/api/graph/impact') {
|
|
572
|
+
const rawPath = url.searchParams.get('path') || initialPath;
|
|
573
|
+
const projectPath = validateProjectPath(rawPath, initialPath);
|
|
574
|
+
const symbolId = url.searchParams.get('symbol');
|
|
575
|
+
|
|
576
|
+
if (!projectPath) {
|
|
577
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
578
|
+
res.end(JSON.stringify({ error: 'Invalid project path', directDependents: [], affectedFiles: [] }));
|
|
579
|
+
return true;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
if (!symbolId) {
|
|
583
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
584
|
+
res.end(JSON.stringify({ error: 'symbol parameter is required', directDependents: [], affectedFiles: [] }));
|
|
585
|
+
return true;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
try {
|
|
589
|
+
const impact = await analyzeImpact(projectPath, symbolId);
|
|
590
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
591
|
+
res.end(JSON.stringify(impact));
|
|
592
|
+
} catch (err) {
|
|
593
|
+
console.error(`[Graph] Error analyzing impact:`, err);
|
|
594
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
595
|
+
res.end(JSON.stringify({
|
|
596
|
+
error: 'Failed to analyze impact',
|
|
597
|
+
directDependents: [],
|
|
598
|
+
affectedFiles: []
|
|
599
|
+
}));
|
|
600
|
+
}
|
|
601
|
+
return true;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// API: Search Process - Get search pipeline visualization data (placeholder)
|
|
605
|
+
if (pathname === '/api/graph/search-process') {
|
|
606
|
+
// This endpoint returns mock data for the search process visualization
|
|
607
|
+
// In a real implementation, this would integrate with codex-lens search pipeline
|
|
608
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
609
|
+
res.end(JSON.stringify({
|
|
610
|
+
stages: [
|
|
611
|
+
{ id: 1, name: 'Query Parsing', duration: 0, status: 'pending' },
|
|
612
|
+
{ id: 2, name: 'Vector Search', duration: 0, status: 'pending' },
|
|
613
|
+
{ id: 3, name: 'Graph Enrichment', duration: 0, status: 'pending' },
|
|
614
|
+
{ id: 4, name: 'Chunk Hierarchy', duration: 0, status: 'pending' },
|
|
615
|
+
{ id: 5, name: 'Result Ranking', duration: 0, status: 'pending' }
|
|
616
|
+
],
|
|
617
|
+
chunks: [],
|
|
618
|
+
callers: [],
|
|
619
|
+
callees: [],
|
|
620
|
+
message: 'Search process visualization requires an active search query'
|
|
621
|
+
}));
|
|
622
|
+
return true;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
return false;
|
|
626
|
+
}
|