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,308 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* Help Routes Module
|
|
4
|
+
* Handles all Help-related API endpoints for command guide and CodexLens docs
|
|
5
|
+
*/
|
|
6
|
+
import type { IncomingMessage, ServerResponse } from 'http';
|
|
7
|
+
import { readFileSync, existsSync, watch } from 'fs';
|
|
8
|
+
import { join } from 'path';
|
|
9
|
+
import { homedir } from 'os';
|
|
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
|
+
// ========== In-Memory Cache ==========
|
|
22
|
+
interface CacheEntry {
|
|
23
|
+
data: any;
|
|
24
|
+
timestamp: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const cache = new Map<string, CacheEntry>();
|
|
28
|
+
const CACHE_TTL = 300000; // 5 minutes
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Get cached data or load from file
|
|
32
|
+
*/
|
|
33
|
+
function getCachedData(key: string, filePath: string): any {
|
|
34
|
+
const now = Date.now();
|
|
35
|
+
const cached = cache.get(key);
|
|
36
|
+
|
|
37
|
+
// Return cached data if valid
|
|
38
|
+
if (cached && (now - cached.timestamp) < CACHE_TTL) {
|
|
39
|
+
return cached.data;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Load fresh data
|
|
43
|
+
try {
|
|
44
|
+
if (!existsSync(filePath)) {
|
|
45
|
+
console.error(`Help data file not found: ${filePath}`);
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const content = readFileSync(filePath, 'utf8');
|
|
50
|
+
const data = JSON.parse(content);
|
|
51
|
+
|
|
52
|
+
// Update cache
|
|
53
|
+
cache.set(key, { data, timestamp: now });
|
|
54
|
+
|
|
55
|
+
return data;
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error(`Failed to load help data from ${filePath}:`, error);
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Invalidate cache for a specific key
|
|
64
|
+
*/
|
|
65
|
+
function invalidateCache(key: string): void {
|
|
66
|
+
cache.delete(key);
|
|
67
|
+
console.log(`Cache invalidated: ${key}`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// ========== File Watchers ==========
|
|
71
|
+
let watchersInitialized = false;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Initialize file watchers for JSON indexes
|
|
75
|
+
*/
|
|
76
|
+
function initializeFileWatchers(): void {
|
|
77
|
+
if (watchersInitialized) return;
|
|
78
|
+
|
|
79
|
+
const indexDir = join(homedir(), '.claude', 'skills', 'command-guide', 'index');
|
|
80
|
+
|
|
81
|
+
if (!existsSync(indexDir)) {
|
|
82
|
+
console.warn(`Command guide index directory not found: ${indexDir}`);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
// Watch all JSON files in index directory
|
|
88
|
+
const watcher = watch(indexDir, { recursive: false }, (eventType, filename) => {
|
|
89
|
+
if (!filename || !filename.endsWith('.json')) return;
|
|
90
|
+
|
|
91
|
+
console.log(`File change detected: ${filename} (${eventType})`);
|
|
92
|
+
|
|
93
|
+
// Invalidate relevant cache entries
|
|
94
|
+
if (filename === 'all-commands.json') {
|
|
95
|
+
invalidateCache('all-commands');
|
|
96
|
+
} else if (filename === 'command-relationships.json') {
|
|
97
|
+
invalidateCache('command-relationships');
|
|
98
|
+
} else if (filename === 'by-category.json') {
|
|
99
|
+
invalidateCache('by-category');
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
watchersInitialized = true;
|
|
104
|
+
console.log(`File watchers initialized for: ${indexDir}`);
|
|
105
|
+
} catch (error) {
|
|
106
|
+
console.error('Failed to initialize file watchers:', error);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// ========== Helper Functions ==========
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Filter commands by search query
|
|
114
|
+
*/
|
|
115
|
+
function filterCommands(commands: any[], query: string): any[] {
|
|
116
|
+
if (!query) return commands;
|
|
117
|
+
|
|
118
|
+
const lowerQuery = query.toLowerCase();
|
|
119
|
+
return commands.filter(cmd =>
|
|
120
|
+
cmd.name?.toLowerCase().includes(lowerQuery) ||
|
|
121
|
+
cmd.command?.toLowerCase().includes(lowerQuery) ||
|
|
122
|
+
cmd.description?.toLowerCase().includes(lowerQuery) ||
|
|
123
|
+
cmd.category?.toLowerCase().includes(lowerQuery)
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Group commands by category with subcategories
|
|
129
|
+
*/
|
|
130
|
+
function groupCommandsByCategory(commands: any[]): any {
|
|
131
|
+
const grouped: any = {};
|
|
132
|
+
|
|
133
|
+
for (const cmd of commands) {
|
|
134
|
+
const category = cmd.category || 'general';
|
|
135
|
+
const subcategory = cmd.subcategory || null;
|
|
136
|
+
|
|
137
|
+
if (!grouped[category]) {
|
|
138
|
+
grouped[category] = {
|
|
139
|
+
name: category,
|
|
140
|
+
commands: [],
|
|
141
|
+
subcategories: {}
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (subcategory) {
|
|
146
|
+
if (!grouped[category].subcategories[subcategory]) {
|
|
147
|
+
grouped[category].subcategories[subcategory] = [];
|
|
148
|
+
}
|
|
149
|
+
grouped[category].subcategories[subcategory].push(cmd);
|
|
150
|
+
} else {
|
|
151
|
+
grouped[category].commands.push(cmd);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return grouped;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// ========== API Routes ==========
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Handle Help routes
|
|
162
|
+
* @returns true if route was handled, false otherwise
|
|
163
|
+
*/
|
|
164
|
+
export async function handleHelpRoutes(ctx: RouteContext): Promise<boolean> {
|
|
165
|
+
const { pathname, url, req, res } = ctx;
|
|
166
|
+
|
|
167
|
+
// Initialize file watchers on first request
|
|
168
|
+
initializeFileWatchers();
|
|
169
|
+
|
|
170
|
+
const indexDir = join(homedir(), '.claude', 'skills', 'command-guide', 'index');
|
|
171
|
+
|
|
172
|
+
// API: Get all commands with optional search
|
|
173
|
+
if (pathname === '/api/help/commands') {
|
|
174
|
+
const searchQuery = url.searchParams.get('q') || '';
|
|
175
|
+
const filePath = join(indexDir, 'all-commands.json');
|
|
176
|
+
|
|
177
|
+
let commands = getCachedData('all-commands', filePath);
|
|
178
|
+
|
|
179
|
+
if (!commands) {
|
|
180
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
181
|
+
res.end(JSON.stringify({ error: 'Commands data not found' }));
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Filter by search query if provided
|
|
186
|
+
if (searchQuery) {
|
|
187
|
+
commands = filterCommands(commands, searchQuery);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Group by category
|
|
191
|
+
const grouped = groupCommandsByCategory(commands);
|
|
192
|
+
|
|
193
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
194
|
+
res.end(JSON.stringify({
|
|
195
|
+
commands: commands,
|
|
196
|
+
grouped: grouped,
|
|
197
|
+
total: commands.length
|
|
198
|
+
}));
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// API: Get workflow command relationships
|
|
203
|
+
if (pathname === '/api/help/workflows') {
|
|
204
|
+
const filePath = join(indexDir, 'command-relationships.json');
|
|
205
|
+
const relationships = getCachedData('command-relationships', filePath);
|
|
206
|
+
|
|
207
|
+
if (!relationships) {
|
|
208
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
209
|
+
res.end(JSON.stringify({ error: 'Workflow relationships not found' }));
|
|
210
|
+
return true;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
214
|
+
res.end(JSON.stringify(relationships));
|
|
215
|
+
return true;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// API: Get commands by category
|
|
219
|
+
if (pathname === '/api/help/commands/by-category') {
|
|
220
|
+
const filePath = join(indexDir, 'by-category.json');
|
|
221
|
+
const byCategory = getCachedData('by-category', filePath);
|
|
222
|
+
|
|
223
|
+
if (!byCategory) {
|
|
224
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
225
|
+
res.end(JSON.stringify({ error: 'Category data not found' }));
|
|
226
|
+
return true;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
230
|
+
res.end(JSON.stringify(byCategory));
|
|
231
|
+
return true;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// API: Get CodexLens documentation metadata
|
|
235
|
+
if (pathname === '/api/help/codexlens') {
|
|
236
|
+
// Return CodexLens quick-start guide data
|
|
237
|
+
const codexLensData = {
|
|
238
|
+
title: 'CodexLens Quick Start',
|
|
239
|
+
description: 'Fast code indexing and semantic search for large codebases',
|
|
240
|
+
sections: [
|
|
241
|
+
{
|
|
242
|
+
title: 'Key Concepts',
|
|
243
|
+
items: [
|
|
244
|
+
{
|
|
245
|
+
name: 'Indexing',
|
|
246
|
+
description: 'CodexLens builds a semantic index of your codebase for fast retrieval',
|
|
247
|
+
command: 'codex_lens(action="init", path=".")'
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
name: 'Search Modes',
|
|
251
|
+
description: 'Text search for exact matches, semantic search for concept-based queries',
|
|
252
|
+
command: 'codex_lens(action="search", query="authentication logic", mode="semantic")'
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
name: 'Symbol Navigation',
|
|
256
|
+
description: 'Extract and navigate code symbols (functions, classes, interfaces)',
|
|
257
|
+
command: 'codex_lens(action="symbol", file="path/to/file.py")'
|
|
258
|
+
}
|
|
259
|
+
]
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
title: 'Common Commands',
|
|
263
|
+
items: [
|
|
264
|
+
{
|
|
265
|
+
name: 'Initialize Index',
|
|
266
|
+
command: 'codex_lens(action="init", path=".")',
|
|
267
|
+
description: 'Index the current directory'
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
name: 'Text Search',
|
|
271
|
+
command: 'codex_lens(action="search", query="function name", path=".")',
|
|
272
|
+
description: 'Search for exact text matches'
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
name: 'Semantic Search',
|
|
276
|
+
command: 'codex_lens(action="search", query="user authentication", mode="semantic")',
|
|
277
|
+
description: 'Search by concept or meaning'
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
name: 'Check Status',
|
|
281
|
+
command: 'codex_lens(action="status")',
|
|
282
|
+
description: 'View indexing status for all projects'
|
|
283
|
+
}
|
|
284
|
+
]
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
title: 'Best Practices',
|
|
288
|
+
items: [
|
|
289
|
+
{ description: 'Index large codebases (>500 files) for optimal performance' },
|
|
290
|
+
{ description: 'Use semantic search for exploratory tasks' },
|
|
291
|
+
{ description: 'Combine with smart_search for medium-sized projects' },
|
|
292
|
+
{ description: 'Re-index after major code changes' }
|
|
293
|
+
]
|
|
294
|
+
}
|
|
295
|
+
],
|
|
296
|
+
links: [
|
|
297
|
+
{ text: 'Full Documentation', url: 'https://github.com/yourusername/codex-lens' },
|
|
298
|
+
{ text: 'Tool Selection Guide', url: '/.claude/rules/tool-selection.md' }
|
|
299
|
+
]
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
303
|
+
res.end(JSON.stringify(codexLensData));
|
|
304
|
+
return true;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
return false;
|
|
308
|
+
}
|
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* Hooks Routes Module
|
|
4
|
+
* Handles all hooks-related API endpoints
|
|
5
|
+
*/
|
|
6
|
+
import type { IncomingMessage, ServerResponse } from 'http';
|
|
7
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
|
|
8
|
+
import { join, dirname } from 'path';
|
|
9
|
+
import { homedir } from 'os';
|
|
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
|
+
extractSessionIdFromPath: (filePath: string) => string | null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// ========================================
|
|
23
|
+
// Helper Functions
|
|
24
|
+
// ========================================
|
|
25
|
+
|
|
26
|
+
const GLOBAL_SETTINGS_PATH = join(homedir(), '.claude', 'settings.json');
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Get project settings path
|
|
30
|
+
* @param {string} projectPath
|
|
31
|
+
* @returns {string}
|
|
32
|
+
*/
|
|
33
|
+
function getProjectSettingsPath(projectPath) {
|
|
34
|
+
const normalizedPath = projectPath.replace(/\//g, '\\').replace(/^\\([a-zA-Z])\\/, '$1:\\');
|
|
35
|
+
return join(normalizedPath, '.claude', 'settings.json');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Read settings file safely
|
|
40
|
+
* @param {string} filePath
|
|
41
|
+
* @returns {Object}
|
|
42
|
+
*/
|
|
43
|
+
function readSettingsFile(filePath) {
|
|
44
|
+
try {
|
|
45
|
+
if (!existsSync(filePath)) {
|
|
46
|
+
return {};
|
|
47
|
+
}
|
|
48
|
+
const content = readFileSync(filePath, 'utf8');
|
|
49
|
+
return JSON.parse(content);
|
|
50
|
+
} catch (error: unknown) {
|
|
51
|
+
console.error(`Error reading settings file ${filePath}:`, error);
|
|
52
|
+
return {};
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Get hooks configuration from global and project settings
|
|
58
|
+
* @param {string} projectPath
|
|
59
|
+
* @returns {Object}
|
|
60
|
+
*/
|
|
61
|
+
function getHooksConfig(projectPath) {
|
|
62
|
+
const globalSettings = readSettingsFile(GLOBAL_SETTINGS_PATH);
|
|
63
|
+
const projectSettingsPath = projectPath ? getProjectSettingsPath(projectPath) : null;
|
|
64
|
+
const projectSettings = projectSettingsPath ? readSettingsFile(projectSettingsPath) : {};
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
global: {
|
|
68
|
+
path: GLOBAL_SETTINGS_PATH,
|
|
69
|
+
hooks: globalSettings.hooks || {}
|
|
70
|
+
},
|
|
71
|
+
project: {
|
|
72
|
+
path: projectSettingsPath,
|
|
73
|
+
hooks: projectSettings.hooks || {}
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Save a hook to settings file
|
|
80
|
+
* @param {string} projectPath
|
|
81
|
+
* @param {string} scope - 'global' or 'project'
|
|
82
|
+
* @param {string} event - Hook event type
|
|
83
|
+
* @param {Object} hookData - Hook configuration
|
|
84
|
+
* @returns {Object}
|
|
85
|
+
*/
|
|
86
|
+
function saveHookToSettings(projectPath, scope, event, hookData) {
|
|
87
|
+
try {
|
|
88
|
+
const filePath = scope === 'global' ? GLOBAL_SETTINGS_PATH : getProjectSettingsPath(projectPath);
|
|
89
|
+
const settings = readSettingsFile(filePath);
|
|
90
|
+
|
|
91
|
+
// Ensure hooks object exists
|
|
92
|
+
if (!settings.hooks) {
|
|
93
|
+
settings.hooks = {};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Ensure the event array exists
|
|
97
|
+
if (!settings.hooks[event]) {
|
|
98
|
+
settings.hooks[event] = [];
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Ensure it's an array
|
|
102
|
+
if (!Array.isArray(settings.hooks[event])) {
|
|
103
|
+
settings.hooks[event] = [settings.hooks[event]];
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Check if we're replacing an existing hook
|
|
107
|
+
if (hookData.replaceIndex !== undefined) {
|
|
108
|
+
const index = hookData.replaceIndex;
|
|
109
|
+
delete hookData.replaceIndex;
|
|
110
|
+
if (index >= 0 && index < settings.hooks[event].length) {
|
|
111
|
+
settings.hooks[event][index] = hookData;
|
|
112
|
+
}
|
|
113
|
+
} else {
|
|
114
|
+
// Add new hook
|
|
115
|
+
settings.hooks[event].push(hookData);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Ensure directory exists and write file
|
|
119
|
+
const dirPath = dirname(filePath);
|
|
120
|
+
if (!existsSync(dirPath)) {
|
|
121
|
+
mkdirSync(dirPath, { recursive: true });
|
|
122
|
+
}
|
|
123
|
+
writeFileSync(filePath, JSON.stringify(settings, null, 2), 'utf8');
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
success: true,
|
|
127
|
+
event,
|
|
128
|
+
hookData
|
|
129
|
+
};
|
|
130
|
+
} catch (error: unknown) {
|
|
131
|
+
console.error('Error saving hook:', error);
|
|
132
|
+
return { error: (error as Error).message };
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Delete a hook from settings file
|
|
138
|
+
* @param {string} projectPath
|
|
139
|
+
* @param {string} scope - 'global' or 'project'
|
|
140
|
+
* @param {string} event - Hook event type
|
|
141
|
+
* @param {number} hookIndex - Index of hook to delete
|
|
142
|
+
* @returns {Object}
|
|
143
|
+
*/
|
|
144
|
+
function deleteHookFromSettings(projectPath, scope, event, hookIndex) {
|
|
145
|
+
try {
|
|
146
|
+
const filePath = scope === 'global' ? GLOBAL_SETTINGS_PATH : getProjectSettingsPath(projectPath);
|
|
147
|
+
const settings = readSettingsFile(filePath);
|
|
148
|
+
|
|
149
|
+
if (!settings.hooks || !settings.hooks[event]) {
|
|
150
|
+
return { error: 'Hook not found' };
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Ensure it's an array
|
|
154
|
+
if (!Array.isArray(settings.hooks[event])) {
|
|
155
|
+
settings.hooks[event] = [settings.hooks[event]];
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (hookIndex < 0 || hookIndex >= settings.hooks[event].length) {
|
|
159
|
+
return { error: 'Invalid hook index' };
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Remove the hook
|
|
163
|
+
settings.hooks[event].splice(hookIndex, 1);
|
|
164
|
+
|
|
165
|
+
// Remove empty event arrays
|
|
166
|
+
if (settings.hooks[event].length === 0) {
|
|
167
|
+
delete settings.hooks[event];
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
writeFileSync(filePath, JSON.stringify(settings, null, 2), 'utf8');
|
|
171
|
+
|
|
172
|
+
return {
|
|
173
|
+
success: true,
|
|
174
|
+
event,
|
|
175
|
+
hookIndex
|
|
176
|
+
};
|
|
177
|
+
} catch (error: unknown) {
|
|
178
|
+
console.error('Error deleting hook:', error);
|
|
179
|
+
return { error: (error as Error).message };
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// ========================================
|
|
184
|
+
// Session State Tracking (for progressive disclosure)
|
|
185
|
+
// ========================================
|
|
186
|
+
|
|
187
|
+
// Track sessions that have received startup context
|
|
188
|
+
// Key: sessionId, Value: timestamp of first context load
|
|
189
|
+
const sessionContextState = new Map<string, {
|
|
190
|
+
firstLoad: string;
|
|
191
|
+
loadCount: number;
|
|
192
|
+
lastPrompt?: string;
|
|
193
|
+
}>();
|
|
194
|
+
|
|
195
|
+
// Cleanup old sessions (older than 24 hours)
|
|
196
|
+
function cleanupOldSessions() {
|
|
197
|
+
const cutoff = Date.now() - 24 * 60 * 60 * 1000;
|
|
198
|
+
for (const [sessionId, state] of sessionContextState.entries()) {
|
|
199
|
+
if (new Date(state.firstLoad).getTime() < cutoff) {
|
|
200
|
+
sessionContextState.delete(sessionId);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Run cleanup every hour
|
|
206
|
+
setInterval(cleanupOldSessions, 60 * 60 * 1000);
|
|
207
|
+
|
|
208
|
+
// ========================================
|
|
209
|
+
// Route Handler
|
|
210
|
+
// ========================================
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Handle hooks routes
|
|
214
|
+
* @returns true if route was handled, false otherwise
|
|
215
|
+
*/
|
|
216
|
+
export async function handleHooksRoutes(ctx: RouteContext): Promise<boolean> {
|
|
217
|
+
const { pathname, url, req, res, initialPath, handlePostRequest, broadcastToClients, extractSessionIdFromPath } = ctx;
|
|
218
|
+
|
|
219
|
+
// API: Hook endpoint for Claude Code notifications
|
|
220
|
+
if (pathname === '/api/hook' && req.method === 'POST') {
|
|
221
|
+
handlePostRequest(req, res, async (body) => {
|
|
222
|
+
const { type, filePath, sessionId, ...extraData } = body;
|
|
223
|
+
|
|
224
|
+
// Determine session ID from file path if not provided
|
|
225
|
+
let resolvedSessionId = sessionId;
|
|
226
|
+
if (!resolvedSessionId && filePath) {
|
|
227
|
+
resolvedSessionId = extractSessionIdFromPath(filePath);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Handle context hooks (session-start, context)
|
|
231
|
+
if (type === 'session-start' || type === 'context') {
|
|
232
|
+
try {
|
|
233
|
+
const projectPath = url.searchParams.get('path') || initialPath;
|
|
234
|
+
const { SessionClusteringService } = await import('../session-clustering-service.js');
|
|
235
|
+
const clusteringService = new SessionClusteringService(projectPath);
|
|
236
|
+
|
|
237
|
+
const format = url.searchParams.get('format') || 'markdown';
|
|
238
|
+
|
|
239
|
+
// Pass type and prompt to getProgressiveIndex
|
|
240
|
+
// session-start: returns recent sessions by time
|
|
241
|
+
// context: returns intent-matched sessions based on prompt
|
|
242
|
+
const index = await clusteringService.getProgressiveIndex({
|
|
243
|
+
type: type as 'session-start' | 'context',
|
|
244
|
+
sessionId: resolvedSessionId,
|
|
245
|
+
prompt: extraData.prompt // Pass user prompt for intent matching
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
// Return context directly
|
|
249
|
+
return {
|
|
250
|
+
success: true,
|
|
251
|
+
type: 'context',
|
|
252
|
+
format,
|
|
253
|
+
content: index,
|
|
254
|
+
sessionId: resolvedSessionId
|
|
255
|
+
};
|
|
256
|
+
} catch (error) {
|
|
257
|
+
console.error('[Hooks] Failed to generate context:', error);
|
|
258
|
+
// Return empty content on failure (fail silently)
|
|
259
|
+
return {
|
|
260
|
+
success: true,
|
|
261
|
+
type: 'context',
|
|
262
|
+
format: 'markdown',
|
|
263
|
+
content: '',
|
|
264
|
+
sessionId: resolvedSessionId,
|
|
265
|
+
error: (error as Error).message
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Broadcast to all connected WebSocket clients
|
|
271
|
+
const notification = {
|
|
272
|
+
type: type || 'session_updated',
|
|
273
|
+
payload: {
|
|
274
|
+
sessionId: resolvedSessionId,
|
|
275
|
+
filePath: filePath,
|
|
276
|
+
timestamp: new Date().toISOString(),
|
|
277
|
+
...extraData // Pass through toolName, status, result, params, error, etc.
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
broadcastToClients(notification);
|
|
282
|
+
|
|
283
|
+
return { success: true, notification };
|
|
284
|
+
});
|
|
285
|
+
return true;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// API: Unified Session Context endpoint (Progressive Disclosure)
|
|
289
|
+
// Automatically detects first prompt vs subsequent prompts
|
|
290
|
+
// - First prompt: returns cluster-based session overview
|
|
291
|
+
// - Subsequent prompts: returns intent-matched sessions based on prompt
|
|
292
|
+
if (pathname === '/api/hook/session-context' && req.method === 'POST') {
|
|
293
|
+
handlePostRequest(req, res, async (body) => {
|
|
294
|
+
const { sessionId, prompt } = body as { sessionId?: string; prompt?: string };
|
|
295
|
+
|
|
296
|
+
if (!sessionId) {
|
|
297
|
+
return {
|
|
298
|
+
success: true,
|
|
299
|
+
content: '',
|
|
300
|
+
error: 'sessionId is required'
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
try {
|
|
305
|
+
const projectPath = url.searchParams.get('path') || initialPath;
|
|
306
|
+
const { SessionClusteringService } = await import('../session-clustering-service.js');
|
|
307
|
+
const clusteringService = new SessionClusteringService(projectPath);
|
|
308
|
+
|
|
309
|
+
// Check if this is the first prompt for this session
|
|
310
|
+
const existingState = sessionContextState.get(sessionId);
|
|
311
|
+
const isFirstPrompt = !existingState;
|
|
312
|
+
|
|
313
|
+
// Update session state
|
|
314
|
+
if (isFirstPrompt) {
|
|
315
|
+
sessionContextState.set(sessionId, {
|
|
316
|
+
firstLoad: new Date().toISOString(),
|
|
317
|
+
loadCount: 1,
|
|
318
|
+
lastPrompt: prompt
|
|
319
|
+
});
|
|
320
|
+
} else {
|
|
321
|
+
existingState.loadCount++;
|
|
322
|
+
existingState.lastPrompt = prompt;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// Determine which type of context to return
|
|
326
|
+
let contextType: 'session-start' | 'context';
|
|
327
|
+
let content: string;
|
|
328
|
+
|
|
329
|
+
if (isFirstPrompt) {
|
|
330
|
+
// First prompt: return session overview with clusters
|
|
331
|
+
contextType = 'session-start';
|
|
332
|
+
content = await clusteringService.getProgressiveIndex({
|
|
333
|
+
type: 'session-start',
|
|
334
|
+
sessionId
|
|
335
|
+
});
|
|
336
|
+
} else if (prompt && prompt.trim().length > 0) {
|
|
337
|
+
// Subsequent prompts with content: return intent-matched sessions
|
|
338
|
+
contextType = 'context';
|
|
339
|
+
content = await clusteringService.getProgressiveIndex({
|
|
340
|
+
type: 'context',
|
|
341
|
+
sessionId,
|
|
342
|
+
prompt
|
|
343
|
+
});
|
|
344
|
+
} else {
|
|
345
|
+
// Subsequent prompts without content: return minimal context
|
|
346
|
+
contextType = 'context';
|
|
347
|
+
content = ''; // No context needed for empty prompts
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
return {
|
|
351
|
+
success: true,
|
|
352
|
+
type: contextType,
|
|
353
|
+
isFirstPrompt,
|
|
354
|
+
loadCount: sessionContextState.get(sessionId)?.loadCount || 1,
|
|
355
|
+
content,
|
|
356
|
+
sessionId
|
|
357
|
+
};
|
|
358
|
+
} catch (error) {
|
|
359
|
+
console.error('[Hooks] Failed to generate session context:', error);
|
|
360
|
+
return {
|
|
361
|
+
success: true,
|
|
362
|
+
content: '',
|
|
363
|
+
sessionId,
|
|
364
|
+
error: (error as Error).message
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
return true;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// API: Get hooks configuration
|
|
372
|
+
if (pathname === '/api/hooks' && req.method === 'GET') {
|
|
373
|
+
const projectPathParam = url.searchParams.get('path');
|
|
374
|
+
const hooksData = getHooksConfig(projectPathParam);
|
|
375
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
376
|
+
res.end(JSON.stringify(hooksData));
|
|
377
|
+
return true;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// API: Save hook
|
|
381
|
+
if (pathname === '/api/hooks' && req.method === 'POST') {
|
|
382
|
+
handlePostRequest(req, res, async (body) => {
|
|
383
|
+
const { projectPath, scope, event, hookData } = body;
|
|
384
|
+
if (!scope || !event || !hookData) {
|
|
385
|
+
return { error: 'scope, event, and hookData are required', status: 400 };
|
|
386
|
+
}
|
|
387
|
+
return saveHookToSettings(projectPath, scope, event, hookData);
|
|
388
|
+
});
|
|
389
|
+
return true;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// API: Delete hook
|
|
393
|
+
if (pathname === '/api/hooks' && req.method === 'DELETE') {
|
|
394
|
+
handlePostRequest(req, res, async (body) => {
|
|
395
|
+
const { projectPath, scope, event, hookIndex } = body;
|
|
396
|
+
if (!scope || !event || hookIndex === undefined) {
|
|
397
|
+
return { error: 'scope, event, and hookIndex are required', status: 400 };
|
|
398
|
+
}
|
|
399
|
+
return deleteHookFromSettings(projectPath, scope, event, hookIndex);
|
|
400
|
+
});
|
|
401
|
+
return true;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
return false;
|
|
405
|
+
}
|