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,455 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage Manager - Centralized storage management for CCW
|
|
3
|
+
* Provides info, cleanup, and configuration for ~/.ccw/ storage
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { existsSync, readdirSync, statSync, rmSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
7
|
+
import { join, resolve } from 'path';
|
|
8
|
+
import { homedir } from 'os';
|
|
9
|
+
import { createRequire } from 'module';
|
|
10
|
+
import { StoragePaths, CCW_HOME, getProjectId } from '../config/storage-paths.js';
|
|
11
|
+
|
|
12
|
+
// Create require for loading CJS modules in ESM context
|
|
13
|
+
const require = createRequire(import.meta.url);
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Storage statistics for a single project
|
|
17
|
+
*/
|
|
18
|
+
export interface ProjectStorageStats {
|
|
19
|
+
projectId: string;
|
|
20
|
+
totalSize: number;
|
|
21
|
+
cliHistory: { exists: boolean; size: number; recordCount?: number };
|
|
22
|
+
memory: { exists: boolean; size: number };
|
|
23
|
+
cache: { exists: boolean; size: number };
|
|
24
|
+
config: { exists: boolean; size: number };
|
|
25
|
+
lastModified: Date | null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Global storage statistics
|
|
30
|
+
*/
|
|
31
|
+
export interface StorageStats {
|
|
32
|
+
rootPath: string;
|
|
33
|
+
totalSize: number;
|
|
34
|
+
globalDb: { exists: boolean; size: number };
|
|
35
|
+
projects: ProjectStorageStats[];
|
|
36
|
+
projectCount: number;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Storage configuration
|
|
41
|
+
*/
|
|
42
|
+
export interface StorageConfig {
|
|
43
|
+
dataDir: string;
|
|
44
|
+
isCustom: boolean;
|
|
45
|
+
envVar: string | undefined;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Calculate directory size recursively
|
|
50
|
+
*/
|
|
51
|
+
function getDirSize(dirPath: string): number {
|
|
52
|
+
if (!existsSync(dirPath)) return 0;
|
|
53
|
+
|
|
54
|
+
let totalSize = 0;
|
|
55
|
+
try {
|
|
56
|
+
const entries = readdirSync(dirPath, { withFileTypes: true });
|
|
57
|
+
for (const entry of entries) {
|
|
58
|
+
const fullPath = join(dirPath, entry.name);
|
|
59
|
+
if (entry.isDirectory()) {
|
|
60
|
+
totalSize += getDirSize(fullPath);
|
|
61
|
+
} else {
|
|
62
|
+
try {
|
|
63
|
+
totalSize += statSync(fullPath).size;
|
|
64
|
+
} catch {
|
|
65
|
+
// Skip files we can't read
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
} catch {
|
|
70
|
+
// Skip directories we can't read
|
|
71
|
+
}
|
|
72
|
+
return totalSize;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Get file size safely
|
|
77
|
+
*/
|
|
78
|
+
function getFileSize(filePath: string): number {
|
|
79
|
+
try {
|
|
80
|
+
return existsSync(filePath) ? statSync(filePath).size : 0;
|
|
81
|
+
} catch {
|
|
82
|
+
return 0;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Get latest modification time in a directory
|
|
88
|
+
*/
|
|
89
|
+
function getLatestModTime(dirPath: string): Date | null {
|
|
90
|
+
if (!existsSync(dirPath)) return null;
|
|
91
|
+
|
|
92
|
+
let latest: Date | null = null;
|
|
93
|
+
try {
|
|
94
|
+
const entries = readdirSync(dirPath, { withFileTypes: true });
|
|
95
|
+
for (const entry of entries) {
|
|
96
|
+
const fullPath = join(dirPath, entry.name);
|
|
97
|
+
try {
|
|
98
|
+
const stat = statSync(fullPath);
|
|
99
|
+
const mtime = stat.mtime;
|
|
100
|
+
if (!latest || mtime > latest) {
|
|
101
|
+
latest = mtime;
|
|
102
|
+
}
|
|
103
|
+
if (entry.isDirectory()) {
|
|
104
|
+
const subLatest = getLatestModTime(fullPath);
|
|
105
|
+
if (subLatest && (!latest || subLatest > latest)) {
|
|
106
|
+
latest = subLatest;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
} catch {
|
|
110
|
+
// Skip files we can't read
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
} catch {
|
|
114
|
+
// Skip directories we can't read
|
|
115
|
+
}
|
|
116
|
+
return latest;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Get record count from SQLite database
|
|
121
|
+
*/
|
|
122
|
+
function getDbRecordCount(dbPath: string, tableName: string): number {
|
|
123
|
+
if (!existsSync(dbPath)) return 0;
|
|
124
|
+
try {
|
|
125
|
+
// Dynamic import to handle ESM module
|
|
126
|
+
const Database = require('better-sqlite3');
|
|
127
|
+
const db = new Database(dbPath, { readonly: true, fileMustExist: true });
|
|
128
|
+
const stmt = db.prepare(`SELECT COUNT(*) as count FROM ${tableName}`);
|
|
129
|
+
const result = stmt.get() as { count: number };
|
|
130
|
+
db.close();
|
|
131
|
+
return result?.count ?? 0;
|
|
132
|
+
} catch (err) {
|
|
133
|
+
// Debug: enable to see actual error
|
|
134
|
+
if (process.env.DEBUG) console.error(`[Storage] Failed to get record count from ${dbPath}: ${err}`);
|
|
135
|
+
return 0;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Check if a directory is a project data directory
|
|
141
|
+
* A project data directory contains at least one of: cli-history, memory, cache, config
|
|
142
|
+
*/
|
|
143
|
+
function isProjectDataDirectory(dirPath: string): boolean {
|
|
144
|
+
const dataMarkers = ['cli-history', 'memory', 'cache', 'config'];
|
|
145
|
+
return dataMarkers.some(marker => existsSync(join(dirPath, marker)));
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Get storage statistics for a specific project by path
|
|
150
|
+
* @param projectId - Project ID (can be hierarchical like "parent/child")
|
|
151
|
+
* @param projectDir - Actual directory path in storage
|
|
152
|
+
*/
|
|
153
|
+
function getProjectStats(projectId: string, projectDir: string): ProjectStorageStats {
|
|
154
|
+
const cliHistoryDir = join(projectDir, 'cli-history');
|
|
155
|
+
const memoryDir = join(projectDir, 'memory');
|
|
156
|
+
const cacheDir = join(projectDir, 'cache');
|
|
157
|
+
const configDir = join(projectDir, 'config');
|
|
158
|
+
|
|
159
|
+
const cliHistorySize = getDirSize(cliHistoryDir);
|
|
160
|
+
const memorySize = getDirSize(memoryDir);
|
|
161
|
+
const cacheSize = getDirSize(cacheDir);
|
|
162
|
+
const configSize = getDirSize(configDir);
|
|
163
|
+
|
|
164
|
+
let recordCount: number | undefined;
|
|
165
|
+
const historyDb = join(cliHistoryDir, 'history.db');
|
|
166
|
+
if (existsSync(historyDb)) {
|
|
167
|
+
recordCount = getDbRecordCount(historyDb, 'conversations');
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return {
|
|
171
|
+
projectId,
|
|
172
|
+
totalSize: cliHistorySize + memorySize + cacheSize + configSize,
|
|
173
|
+
cliHistory: {
|
|
174
|
+
exists: existsSync(cliHistoryDir),
|
|
175
|
+
size: cliHistorySize,
|
|
176
|
+
recordCount
|
|
177
|
+
},
|
|
178
|
+
memory: {
|
|
179
|
+
exists: existsSync(memoryDir),
|
|
180
|
+
size: memorySize
|
|
181
|
+
},
|
|
182
|
+
cache: {
|
|
183
|
+
exists: existsSync(cacheDir),
|
|
184
|
+
size: cacheSize
|
|
185
|
+
},
|
|
186
|
+
config: {
|
|
187
|
+
exists: existsSync(configDir),
|
|
188
|
+
size: configSize
|
|
189
|
+
},
|
|
190
|
+
lastModified: getLatestModTime(projectDir)
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Get storage statistics for a specific project by ID (legacy)
|
|
196
|
+
*/
|
|
197
|
+
export function getProjectStorageStats(projectId: string): ProjectStorageStats {
|
|
198
|
+
const paths = StoragePaths.projectById(projectId);
|
|
199
|
+
return getProjectStats(projectId, paths.root);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Recursively scan project directory for hierarchical structure
|
|
204
|
+
* @param basePath - Base directory to scan
|
|
205
|
+
* @param relativePath - Relative path from projects root
|
|
206
|
+
* @param results - Array to accumulate results
|
|
207
|
+
*/
|
|
208
|
+
function scanProjectDirectory(
|
|
209
|
+
basePath: string,
|
|
210
|
+
relativePath: string,
|
|
211
|
+
results: ProjectStorageStats[]
|
|
212
|
+
): void {
|
|
213
|
+
if (!existsSync(basePath)) return;
|
|
214
|
+
|
|
215
|
+
try {
|
|
216
|
+
const entries = readdirSync(basePath, { withFileTypes: true });
|
|
217
|
+
|
|
218
|
+
for (const entry of entries) {
|
|
219
|
+
if (!entry.isDirectory()) continue;
|
|
220
|
+
|
|
221
|
+
const fullPath = join(basePath, entry.name);
|
|
222
|
+
const currentRelPath = relativePath ? `${relativePath}/${entry.name}` : entry.name;
|
|
223
|
+
|
|
224
|
+
// Check if this is a project data directory
|
|
225
|
+
if (isProjectDataDirectory(fullPath)) {
|
|
226
|
+
const projectId = currentRelPath;
|
|
227
|
+
const stats = getProjectStats(projectId, fullPath);
|
|
228
|
+
results.push(stats);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Recursively scan subdirectories (excluding data directories)
|
|
232
|
+
const dataDirs = ['cli-history', 'memory', 'cache', 'config'];
|
|
233
|
+
if (!dataDirs.includes(entry.name)) {
|
|
234
|
+
scanProjectDirectory(fullPath, currentRelPath, results);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
} catch (err) {
|
|
238
|
+
// Ignore read errors
|
|
239
|
+
if (process.env.DEBUG) console.error(`[Storage] Failed to scan ${basePath}: ${err}`);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Get all storage statistics
|
|
245
|
+
* Supports hierarchical project structure
|
|
246
|
+
*/
|
|
247
|
+
export function getStorageStats(): StorageStats {
|
|
248
|
+
const rootPath = CCW_HOME;
|
|
249
|
+
const projectsDir = join(rootPath, 'projects');
|
|
250
|
+
|
|
251
|
+
// Global database
|
|
252
|
+
const mcpTemplatesPath = StoragePaths.global.mcpTemplates();
|
|
253
|
+
const globalDbSize = getFileSize(mcpTemplatesPath);
|
|
254
|
+
|
|
255
|
+
// Projects - use recursive scanning for hierarchical structure
|
|
256
|
+
const projects: ProjectStorageStats[] = [];
|
|
257
|
+
if (existsSync(projectsDir)) {
|
|
258
|
+
scanProjectDirectory(projectsDir, '', projects);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Sort by last modified (most recent first)
|
|
262
|
+
projects.sort((a, b) => {
|
|
263
|
+
if (!a.lastModified && !b.lastModified) return 0;
|
|
264
|
+
if (!a.lastModified) return 1;
|
|
265
|
+
if (!b.lastModified) return -1;
|
|
266
|
+
return b.lastModified.getTime() - a.lastModified.getTime();
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
const totalProjectSize = projects.reduce((sum, p) => sum + p.totalSize, 0);
|
|
270
|
+
|
|
271
|
+
return {
|
|
272
|
+
rootPath,
|
|
273
|
+
totalSize: globalDbSize + totalProjectSize,
|
|
274
|
+
globalDb: {
|
|
275
|
+
exists: existsSync(mcpTemplatesPath),
|
|
276
|
+
size: globalDbSize
|
|
277
|
+
},
|
|
278
|
+
projects,
|
|
279
|
+
projectCount: projects.length
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Get current storage configuration
|
|
285
|
+
*/
|
|
286
|
+
export function getStorageConfig(): StorageConfig {
|
|
287
|
+
const envVar = process.env.CCW_DATA_DIR;
|
|
288
|
+
return {
|
|
289
|
+
dataDir: CCW_HOME,
|
|
290
|
+
isCustom: !!envVar,
|
|
291
|
+
envVar
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Format bytes to human readable string
|
|
297
|
+
*/
|
|
298
|
+
export function formatBytes(bytes: number): string {
|
|
299
|
+
if (bytes === 0) return '0 B';
|
|
300
|
+
const k = 1024;
|
|
301
|
+
const sizes = ['B', 'KB', 'MB', 'GB'];
|
|
302
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
303
|
+
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Format date to relative time
|
|
308
|
+
*/
|
|
309
|
+
export function formatTimeAgo(date: Date | null): string {
|
|
310
|
+
if (!date) return 'Never';
|
|
311
|
+
|
|
312
|
+
const now = new Date();
|
|
313
|
+
const diffMs = now.getTime() - date.getTime();
|
|
314
|
+
const diffMins = Math.floor(diffMs / 60000);
|
|
315
|
+
const diffHours = Math.floor(diffMins / 60);
|
|
316
|
+
const diffDays = Math.floor(diffHours / 24);
|
|
317
|
+
|
|
318
|
+
if (diffMins < 1) return 'Just now';
|
|
319
|
+
if (diffMins < 60) return `${diffMins}m ago`;
|
|
320
|
+
if (diffHours < 24) return `${diffHours}h ago`;
|
|
321
|
+
if (diffDays < 30) return `${diffDays}d ago`;
|
|
322
|
+
return date.toLocaleDateString();
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Clean storage for a specific project
|
|
327
|
+
*/
|
|
328
|
+
export function cleanProjectStorage(projectId: string, options: {
|
|
329
|
+
cliHistory?: boolean;
|
|
330
|
+
memory?: boolean;
|
|
331
|
+
cache?: boolean;
|
|
332
|
+
config?: boolean;
|
|
333
|
+
all?: boolean;
|
|
334
|
+
} = { all: true }): { success: boolean; freedBytes: number; errors: string[] } {
|
|
335
|
+
const paths = StoragePaths.projectById(projectId);
|
|
336
|
+
let freedBytes = 0;
|
|
337
|
+
const errors: string[] = [];
|
|
338
|
+
|
|
339
|
+
const shouldClean = (type: keyof typeof options) => options.all || options[type];
|
|
340
|
+
|
|
341
|
+
const cleanDir = (dirPath: string, name: string) => {
|
|
342
|
+
if (existsSync(dirPath)) {
|
|
343
|
+
try {
|
|
344
|
+
const size = getDirSize(dirPath);
|
|
345
|
+
rmSync(dirPath, { recursive: true, force: true });
|
|
346
|
+
freedBytes += size;
|
|
347
|
+
} catch (err) {
|
|
348
|
+
errors.push(`Failed to clean ${name}: ${err}`);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
if (shouldClean('cliHistory')) cleanDir(paths.cliHistory, 'CLI history');
|
|
354
|
+
if (shouldClean('memory')) cleanDir(paths.memory, 'Memory store');
|
|
355
|
+
if (shouldClean('cache')) cleanDir(paths.cache, 'Cache');
|
|
356
|
+
if (shouldClean('config')) cleanDir(paths.config, 'Config');
|
|
357
|
+
|
|
358
|
+
// Remove project directory if empty
|
|
359
|
+
if (existsSync(paths.root)) {
|
|
360
|
+
try {
|
|
361
|
+
const remaining = readdirSync(paths.root);
|
|
362
|
+
if (remaining.length === 0) {
|
|
363
|
+
rmSync(paths.root, { recursive: true, force: true });
|
|
364
|
+
}
|
|
365
|
+
} catch {
|
|
366
|
+
// Ignore cleanup errors
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
return { success: errors.length === 0, freedBytes, errors };
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Clean all storage
|
|
375
|
+
*/
|
|
376
|
+
export function cleanAllStorage(options: {
|
|
377
|
+
cliHistory?: boolean;
|
|
378
|
+
memory?: boolean;
|
|
379
|
+
cache?: boolean;
|
|
380
|
+
config?: boolean;
|
|
381
|
+
globalDb?: boolean;
|
|
382
|
+
all?: boolean;
|
|
383
|
+
} = { all: true }): { success: boolean; freedBytes: number; projectsCleaned: number; errors: string[] } {
|
|
384
|
+
const stats = getStorageStats();
|
|
385
|
+
let freedBytes = 0;
|
|
386
|
+
let projectsCleaned = 0;
|
|
387
|
+
const errors: string[] = [];
|
|
388
|
+
|
|
389
|
+
// Clean projects
|
|
390
|
+
for (const project of stats.projects) {
|
|
391
|
+
const result = cleanProjectStorage(project.projectId, options);
|
|
392
|
+
freedBytes += result.freedBytes;
|
|
393
|
+
if (result.errors.length === 0) {
|
|
394
|
+
projectsCleaned++;
|
|
395
|
+
}
|
|
396
|
+
errors.push(...result.errors);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// Clean global database if requested
|
|
400
|
+
if (options.all || options.globalDb) {
|
|
401
|
+
const mcpPath = StoragePaths.global.mcpTemplates();
|
|
402
|
+
if (existsSync(mcpPath)) {
|
|
403
|
+
try {
|
|
404
|
+
const size = getFileSize(mcpPath);
|
|
405
|
+
rmSync(mcpPath, { force: true });
|
|
406
|
+
freedBytes += size;
|
|
407
|
+
} catch (err) {
|
|
408
|
+
errors.push(`Failed to clean global database: ${err}`);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
return { success: errors.length === 0, freedBytes, projectsCleaned, errors };
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Get project ID from project path
|
|
418
|
+
*/
|
|
419
|
+
export function resolveProjectId(projectPath: string): string {
|
|
420
|
+
return getProjectId(resolve(projectPath));
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Check if a project ID exists in storage
|
|
425
|
+
*/
|
|
426
|
+
export function projectExists(projectId: string): boolean {
|
|
427
|
+
const paths = StoragePaths.projectById(projectId);
|
|
428
|
+
return existsSync(paths.root);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Get storage location instructions for changing it
|
|
433
|
+
*/
|
|
434
|
+
export function getStorageLocationInstructions(): string {
|
|
435
|
+
return `
|
|
436
|
+
To change the CCW storage location, set the CCW_DATA_DIR environment variable:
|
|
437
|
+
|
|
438
|
+
Windows (PowerShell):
|
|
439
|
+
$env:CCW_DATA_DIR = "D:\\custom\\ccw-data"
|
|
440
|
+
|
|
441
|
+
Windows (Command Prompt):
|
|
442
|
+
set CCW_DATA_DIR=D:\\custom\\ccw-data
|
|
443
|
+
|
|
444
|
+
Linux/macOS:
|
|
445
|
+
export CCW_DATA_DIR="/custom/ccw-data"
|
|
446
|
+
|
|
447
|
+
Permanent (add to shell profile):
|
|
448
|
+
echo 'export CCW_DATA_DIR="/custom/ccw-data"' >> ~/.bashrc
|
|
449
|
+
|
|
450
|
+
Note: Existing data will NOT be migrated automatically.
|
|
451
|
+
To migrate, manually copy the contents of the old directory to the new location.
|
|
452
|
+
|
|
453
|
+
Current location: ${CCW_HOME}
|
|
454
|
+
`;
|
|
455
|
+
}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Write File Tool - Create or overwrite files
|
|
3
|
+
*
|
|
4
|
+
* Features:
|
|
5
|
+
* - Create new files or overwrite existing
|
|
6
|
+
* - Auto-create parent directories
|
|
7
|
+
* - Support for text content with proper encoding
|
|
8
|
+
* - Optional backup before overwrite
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { z } from 'zod';
|
|
12
|
+
import type { ToolSchema, ToolResult } from '../types/tool.js';
|
|
13
|
+
import { writeFileSync, readFileSync, existsSync, mkdirSync, renameSync, statSync } from 'fs';
|
|
14
|
+
import { resolve, isAbsolute, dirname, basename } from 'path';
|
|
15
|
+
import { validatePath } from '../utils/path-validator.js';
|
|
16
|
+
|
|
17
|
+
// Define Zod schema for validation
|
|
18
|
+
const ParamsSchema = z.object({
|
|
19
|
+
path: z.string().min(1, 'Path is required'),
|
|
20
|
+
content: z.string(),
|
|
21
|
+
createDirectories: z.boolean().default(true),
|
|
22
|
+
backup: z.boolean().default(false),
|
|
23
|
+
encoding: z.enum(['utf8', 'utf-8', 'ascii', 'latin1', 'binary', 'hex', 'base64']).default('utf8'),
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
type Params = z.infer<typeof ParamsSchema>;
|
|
27
|
+
|
|
28
|
+
// Compact result for output
|
|
29
|
+
interface WriteResult {
|
|
30
|
+
path: string;
|
|
31
|
+
bytes: number;
|
|
32
|
+
message: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Ensure parent directory exists
|
|
37
|
+
* @param filePath - Path to file
|
|
38
|
+
*/
|
|
39
|
+
function ensureDir(filePath: string): void {
|
|
40
|
+
const dir = dirname(filePath);
|
|
41
|
+
if (!existsSync(dir)) {
|
|
42
|
+
mkdirSync(dir, { recursive: true });
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Create backup of existing file
|
|
48
|
+
* @param filePath - Path to file
|
|
49
|
+
* @returns Backup path or null if no backup created
|
|
50
|
+
*/
|
|
51
|
+
function createBackup(filePath: string): string | null {
|
|
52
|
+
if (!existsSync(filePath)) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const dir = dirname(filePath);
|
|
57
|
+
const name = basename(filePath);
|
|
58
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
59
|
+
const backupPath = resolve(dir, `.${name}.${timestamp}.bak`);
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
const content = readFileSync(filePath);
|
|
63
|
+
writeFileSync(backupPath, content);
|
|
64
|
+
return backupPath;
|
|
65
|
+
} catch (error) {
|
|
66
|
+
throw new Error(`Failed to create backup: ${(error as Error).message}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Verify file write operation completed successfully
|
|
72
|
+
* @param filePath - Path to written file
|
|
73
|
+
* @param expectedBytes - Expected file size in bytes
|
|
74
|
+
* @param encoding - File encoding used
|
|
75
|
+
* @returns Error message if verification fails, null if successful
|
|
76
|
+
*/
|
|
77
|
+
function verifyFileWrite(filePath: string, expectedBytes: number, encoding: BufferEncoding): string | null {
|
|
78
|
+
// Check 1: File exists
|
|
79
|
+
if (!existsSync(filePath)) {
|
|
80
|
+
return `File verification failed: file does not exist at ${filePath}`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
// Check 2: File size matches expected bytes
|
|
85
|
+
const stats = statSync(filePath);
|
|
86
|
+
if (stats.size !== expectedBytes) {
|
|
87
|
+
return `File verification failed: size mismatch (expected ${expectedBytes}B, actual ${stats.size}B)`;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Check 3: File is readable (for long JSON files)
|
|
91
|
+
const readContent = readFileSync(filePath, { encoding });
|
|
92
|
+
const actualBytes = Buffer.byteLength(readContent, encoding);
|
|
93
|
+
if (actualBytes !== expectedBytes) {
|
|
94
|
+
return `File verification failed: content size mismatch after read (expected ${expectedBytes}B, read ${actualBytes}B)`;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return null; // Verification passed
|
|
98
|
+
} catch (error) {
|
|
99
|
+
return `File verification failed: ${(error as Error).message}`;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Tool schema for MCP
|
|
104
|
+
export const schema: ToolSchema = {
|
|
105
|
+
name: 'write_file',
|
|
106
|
+
description: `Write content to file. Auto-creates parent directories.
|
|
107
|
+
|
|
108
|
+
Usage: write_file(path="file.js", content="code here")
|
|
109
|
+
Options: backup=true (backup before overwrite), createDirectories=false (disable auto-creation), encoding="utf8"`,
|
|
110
|
+
inputSchema: {
|
|
111
|
+
type: 'object',
|
|
112
|
+
properties: {
|
|
113
|
+
path: {
|
|
114
|
+
type: 'string',
|
|
115
|
+
description: 'Path to the file to create or overwrite',
|
|
116
|
+
},
|
|
117
|
+
content: {
|
|
118
|
+
type: 'string',
|
|
119
|
+
description: 'Content to write to the file',
|
|
120
|
+
},
|
|
121
|
+
createDirectories: {
|
|
122
|
+
type: 'boolean',
|
|
123
|
+
description: 'Create parent directories if they do not exist (default: true)',
|
|
124
|
+
default: true,
|
|
125
|
+
},
|
|
126
|
+
backup: {
|
|
127
|
+
type: 'boolean',
|
|
128
|
+
description: 'Create backup of existing file before overwriting (default: false)',
|
|
129
|
+
default: false,
|
|
130
|
+
},
|
|
131
|
+
encoding: {
|
|
132
|
+
type: 'string',
|
|
133
|
+
description: 'File encoding (default: utf8)',
|
|
134
|
+
default: 'utf8',
|
|
135
|
+
enum: ['utf8', 'utf-8', 'ascii', 'latin1', 'binary', 'hex', 'base64'],
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
required: ['path', 'content'],
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
// Handler function
|
|
143
|
+
export async function handler(params: Record<string, unknown>): Promise<ToolResult<WriteResult>> {
|
|
144
|
+
const parsed = ParamsSchema.safeParse(params);
|
|
145
|
+
if (!parsed.success) {
|
|
146
|
+
return { success: false, error: `Invalid params: ${parsed.error.message}` };
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const {
|
|
150
|
+
path: filePath,
|
|
151
|
+
content,
|
|
152
|
+
createDirectories,
|
|
153
|
+
backup,
|
|
154
|
+
encoding,
|
|
155
|
+
} = parsed.data;
|
|
156
|
+
|
|
157
|
+
// Validate and resolve path
|
|
158
|
+
const resolvedPath = await validatePath(filePath);
|
|
159
|
+
const fileExists = existsSync(resolvedPath);
|
|
160
|
+
|
|
161
|
+
// Create parent directories if needed
|
|
162
|
+
if (createDirectories) {
|
|
163
|
+
ensureDir(resolvedPath);
|
|
164
|
+
} else if (!existsSync(dirname(resolvedPath))) {
|
|
165
|
+
return {
|
|
166
|
+
success: false,
|
|
167
|
+
error: `Parent directory does not exist: ${dirname(resolvedPath)}`,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Create backup if requested and file exists
|
|
172
|
+
let backupPath: string | null = null;
|
|
173
|
+
if (backup && fileExists) {
|
|
174
|
+
try {
|
|
175
|
+
backupPath = createBackup(resolvedPath);
|
|
176
|
+
} catch (error) {
|
|
177
|
+
return {
|
|
178
|
+
success: false,
|
|
179
|
+
error: (error as Error).message,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Write file
|
|
185
|
+
try {
|
|
186
|
+
writeFileSync(resolvedPath, content, { encoding });
|
|
187
|
+
const bytes = Buffer.byteLength(content, encoding);
|
|
188
|
+
|
|
189
|
+
// Verify write operation completed successfully
|
|
190
|
+
const verificationError = verifyFileWrite(resolvedPath, bytes, encoding as BufferEncoding);
|
|
191
|
+
if (verificationError) {
|
|
192
|
+
return {
|
|
193
|
+
success: false,
|
|
194
|
+
error: verificationError,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Build compact message
|
|
199
|
+
let message: string;
|
|
200
|
+
if (fileExists) {
|
|
201
|
+
message = backupPath
|
|
202
|
+
? `Overwrote (${bytes}B, backup: ${basename(backupPath)}) - verified`
|
|
203
|
+
: `Overwrote (${bytes}B) - verified`;
|
|
204
|
+
} else {
|
|
205
|
+
message = `Created (${bytes}B) - verified`;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return {
|
|
209
|
+
success: true,
|
|
210
|
+
result: {
|
|
211
|
+
path: resolvedPath,
|
|
212
|
+
bytes,
|
|
213
|
+
message,
|
|
214
|
+
},
|
|
215
|
+
};
|
|
216
|
+
} catch (error) {
|
|
217
|
+
return {
|
|
218
|
+
success: false,
|
|
219
|
+
error: `Failed to write file: ${(error as Error).message}`,
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export type SessionStatus = 'active' | 'paused' | 'completed' | 'archived';
|
|
2
|
+
export type SessionType = 'workflow' | 'review' | 'tdd' | 'test' | 'docs' | 'lite-plan' | 'lite-fix';
|
|
3
|
+
export type ContentType =
|
|
4
|
+
| 'session' | 'plan' | 'task' | 'summary'
|
|
5
|
+
| 'process' | 'chat' | 'brainstorm'
|
|
6
|
+
| 'review-dim' | 'review-iter' | 'review-fix'
|
|
7
|
+
| 'todo' | 'context';
|
|
8
|
+
|
|
9
|
+
export interface SessionMetadata {
|
|
10
|
+
id: string;
|
|
11
|
+
type: SessionType;
|
|
12
|
+
status: SessionStatus;
|
|
13
|
+
description?: string;
|
|
14
|
+
project?: string;
|
|
15
|
+
created: string;
|
|
16
|
+
updated: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface SessionOperationResult {
|
|
20
|
+
success: boolean;
|
|
21
|
+
sessionId?: string;
|
|
22
|
+
path?: string;
|
|
23
|
+
data?: unknown;
|
|
24
|
+
error?: string;
|
|
25
|
+
}
|