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
|
@@ -1,852 +1,888 @@
|
|
|
1
|
-
// ============================================
|
|
2
|
-
// EXPLORER VIEW
|
|
3
|
-
// ============================================
|
|
4
|
-
// File tree browser with .gitignore filtering and CLAUDE.md update support
|
|
5
|
-
// Split-panel layout: file tree (left) + preview (right)
|
|
6
|
-
|
|
7
|
-
// Explorer state
|
|
8
|
-
let explorerCurrentPath = null;
|
|
9
|
-
let explorerSelectedFile = null;
|
|
10
|
-
let explorerExpandedDirs = new Set();
|
|
11
|
-
|
|
12
|
-
// Task queue for CLAUDE.md updates
|
|
13
|
-
let updateTaskQueue = [];
|
|
14
|
-
let isTaskQueueVisible = false;
|
|
15
|
-
let isTaskRunning = false;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
*
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
<div class="
|
|
76
|
-
<
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
</div>
|
|
100
|
-
<div class="task-queue-
|
|
101
|
-
<div class="
|
|
102
|
-
<
|
|
103
|
-
<
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
<
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
'
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
'
|
|
235
|
-
'
|
|
236
|
-
'
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
'
|
|
240
|
-
'
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
'
|
|
245
|
-
'
|
|
246
|
-
'
|
|
247
|
-
'
|
|
248
|
-
'
|
|
249
|
-
'
|
|
250
|
-
'
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
'
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
'
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
'
|
|
260
|
-
'
|
|
261
|
-
'
|
|
262
|
-
'
|
|
263
|
-
'
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
'
|
|
268
|
-
'
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
'
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
'
|
|
276
|
-
'
|
|
277
|
-
'
|
|
278
|
-
'
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
'
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
: '<
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
//
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
if
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
<
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
const
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
}
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
1
|
+
// ============================================
|
|
2
|
+
// EXPLORER VIEW
|
|
3
|
+
// ============================================
|
|
4
|
+
// File tree browser with .gitignore filtering and CLAUDE.md update support
|
|
5
|
+
// Split-panel layout: file tree (left) + preview (right)
|
|
6
|
+
|
|
7
|
+
// Explorer state
|
|
8
|
+
let explorerCurrentPath = null;
|
|
9
|
+
let explorerSelectedFile = null;
|
|
10
|
+
let explorerExpandedDirs = new Set();
|
|
11
|
+
|
|
12
|
+
// Task queue for CLAUDE.md updates
|
|
13
|
+
let updateTaskQueue = [];
|
|
14
|
+
let isTaskQueueVisible = false;
|
|
15
|
+
let isTaskRunning = false;
|
|
16
|
+
// Note: defaultCliTool is defined in components/cli-status.js
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Safe base64 encode that handles Unicode characters
|
|
21
|
+
* Returns alphanumeric-only string suitable for HTML IDs
|
|
22
|
+
*/
|
|
23
|
+
function safeBase64Encode(str) {
|
|
24
|
+
try {
|
|
25
|
+
// Encode Unicode string to UTF-8 bytes, then to base64
|
|
26
|
+
const encoded = btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, (_, p1) => String.fromCharCode(parseInt(p1, 16))));
|
|
27
|
+
return encoded.replace(/[^a-zA-Z0-9]/g, '');
|
|
28
|
+
} catch (e) {
|
|
29
|
+
// Fallback: use simple hash if encoding fails
|
|
30
|
+
let hash = 0;
|
|
31
|
+
for (let i = 0; i < str.length; i++) {
|
|
32
|
+
const char = str.charCodeAt(i);
|
|
33
|
+
hash = ((hash << 5) - hash) + char;
|
|
34
|
+
hash = hash & hash;
|
|
35
|
+
}
|
|
36
|
+
return 'path' + Math.abs(hash).toString(36);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Render the Explorer view
|
|
42
|
+
*/
|
|
43
|
+
async function renderExplorer() {
|
|
44
|
+
const container = document.getElementById('mainContent');
|
|
45
|
+
if (!container) return;
|
|
46
|
+
|
|
47
|
+
// Hide stats grid and search
|
|
48
|
+
const statsGrid = document.getElementById('statsGrid');
|
|
49
|
+
const searchInput = document.getElementById('searchInput');
|
|
50
|
+
if (statsGrid) statsGrid.style.display = 'none';
|
|
51
|
+
if (searchInput) searchInput.parentElement.style.display = 'none';
|
|
52
|
+
|
|
53
|
+
// Initialize explorer path to project path
|
|
54
|
+
explorerCurrentPath = projectPath;
|
|
55
|
+
|
|
56
|
+
container.innerHTML = `
|
|
57
|
+
<div class="explorer-container">
|
|
58
|
+
<!-- Left Panel: File Tree -->
|
|
59
|
+
<div class="explorer-tree-panel">
|
|
60
|
+
<div class="explorer-tree-header">
|
|
61
|
+
<div class="explorer-tree-title">
|
|
62
|
+
<i data-lucide="folder-tree" class="explorer-icon"></i>
|
|
63
|
+
<span class="explorer-title-text">${t('explorer.title')}</span>
|
|
64
|
+
</div>
|
|
65
|
+
<button class="explorer-refresh-btn" onclick="refreshExplorerTree()" title="${t('explorer.refresh')}">
|
|
66
|
+
<i data-lucide="refresh-cw" class="w-4 h-4"></i>
|
|
67
|
+
</button>
|
|
68
|
+
</div>
|
|
69
|
+
<div class="explorer-tree-content" id="explorerTreeContent">
|
|
70
|
+
<div class="explorer-loading">${t('explorer.loading')}</div>
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<!-- Right Panel: Preview -->
|
|
75
|
+
<div class="explorer-preview-panel">
|
|
76
|
+
<div class="explorer-preview-header" id="explorerPreviewHeader">
|
|
77
|
+
<span class="preview-filename">${t('explorer.selectFile')}</span>
|
|
78
|
+
</div>
|
|
79
|
+
<div class="explorer-preview-content" id="explorerPreviewContent">
|
|
80
|
+
<div class="explorer-preview-empty">
|
|
81
|
+
<div class="preview-empty-icon"><i data-lucide="file-text" class="w-12 h-12"></i></div>
|
|
82
|
+
<div class="preview-empty-text">${t('explorer.selectFileHint')}</div>
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
|
|
88
|
+
<!-- Floating Action Button -->
|
|
89
|
+
<div class="explorer-fab" onclick="toggleTaskQueue()" title="${t('taskQueue.title')}">
|
|
90
|
+
<span class="fab-icon"><i data-lucide="list-todo" class="w-5 h-5"></i></span>
|
|
91
|
+
<span class="fab-badge" id="fabBadge">0</span>
|
|
92
|
+
</div>
|
|
93
|
+
|
|
94
|
+
<!-- Task Queue Panel -->
|
|
95
|
+
<div class="task-queue-panel" id="taskQueuePanel">
|
|
96
|
+
<div class="task-queue-header">
|
|
97
|
+
<span class="task-queue-title"><i data-lucide="clipboard-list" class="w-4 h-4 inline-block mr-1"></i> ${t('taskQueue.title')}</span>
|
|
98
|
+
<button class="task-queue-close" onclick="toggleTaskQueue()">×</button>
|
|
99
|
+
</div>
|
|
100
|
+
<div class="task-queue-toolbar">
|
|
101
|
+
<div class="queue-cli-selector">
|
|
102
|
+
<label>${t('taskQueue.cli')}</label>
|
|
103
|
+
<select id="queueCliTool" onchange="updateDefaultCliTool(this.value)">
|
|
104
|
+
<option value="gemini">Gemini</option>
|
|
105
|
+
<option value="qwen">Qwen</option>
|
|
106
|
+
<option value="codex">Codex</option>
|
|
107
|
+
<option value="claude">Claude</option>
|
|
108
|
+
</select>
|
|
109
|
+
</div>
|
|
110
|
+
<div class="task-queue-actions">
|
|
111
|
+
<button class="queue-action-btn" onclick="openAddTaskModal()" title="${t('taskQueue.addTask')}">
|
|
112
|
+
<i data-lucide="plus" class="w-4 h-4"></i>
|
|
113
|
+
</button>
|
|
114
|
+
<button class="queue-action-btn queue-start-btn" onclick="startTaskQueue()" id="startQueueBtn" disabled title="${t('taskQueue.startAll')}">
|
|
115
|
+
<i data-lucide="play" class="w-4 h-4"></i>
|
|
116
|
+
</button>
|
|
117
|
+
<button class="queue-action-btn queue-clear-btn" onclick="clearCompletedTasks()" title="${t('taskQueue.clearCompleted')}">
|
|
118
|
+
<i data-lucide="trash-2" class="w-4 h-4"></i>
|
|
119
|
+
</button>
|
|
120
|
+
</div>
|
|
121
|
+
</div>
|
|
122
|
+
<div class="task-queue-list" id="taskQueueList">
|
|
123
|
+
<div class="task-queue-empty">
|
|
124
|
+
<span>${t('taskQueue.noTasks')}</span>
|
|
125
|
+
<p>${t('taskQueue.noTasksHint')}</p>
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
`;
|
|
130
|
+
|
|
131
|
+
// Load initial file tree
|
|
132
|
+
await loadExplorerTree(explorerCurrentPath);
|
|
133
|
+
|
|
134
|
+
// Initialize Lucide icons for dynamically rendered content
|
|
135
|
+
if (typeof lucide !== 'undefined') lucide.createIcons();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Load and render file tree for a directory
|
|
140
|
+
*/
|
|
141
|
+
async function loadExplorerTree(dirPath) {
|
|
142
|
+
const treeContent = document.getElementById('explorerTreeContent');
|
|
143
|
+
if (!treeContent) return;
|
|
144
|
+
|
|
145
|
+
try {
|
|
146
|
+
const response = await fetch(`/api/files?path=${encodeURIComponent(dirPath)}`);
|
|
147
|
+
const data = await response.json();
|
|
148
|
+
|
|
149
|
+
if (data.error) {
|
|
150
|
+
treeContent.innerHTML = `<div class="explorer-error">${escapeHtml(data.error)}</div>`;
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Render root level
|
|
155
|
+
treeContent.innerHTML = renderTreeLevel(data.files, dirPath, 0);
|
|
156
|
+
attachTreeEventListeners();
|
|
157
|
+
|
|
158
|
+
// Initialize Lucide icons for tree items
|
|
159
|
+
if (typeof lucide !== 'undefined') lucide.createIcons();
|
|
160
|
+
|
|
161
|
+
} catch (error) {
|
|
162
|
+
treeContent.innerHTML = `<div class="explorer-error">Failed to load: ${escapeHtml(error.message)}</div>`;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Render a level of the file tree
|
|
168
|
+
*/
|
|
169
|
+
function renderTreeLevel(files, parentPath, depth) {
|
|
170
|
+
if (!files || files.length === 0) {
|
|
171
|
+
return `<div class="tree-empty" style="padding-left: ${depth * 16 + 8}px">${t('explorer.emptyDir')}</div>`;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return files.map(file => {
|
|
175
|
+
const isExpanded = explorerExpandedDirs.has(file.path);
|
|
176
|
+
const isSelected = explorerSelectedFile === file.path;
|
|
177
|
+
|
|
178
|
+
if (file.type === 'directory') {
|
|
179
|
+
const folderIcon = getFolderIcon(file.name, isExpanded, file.hasClaudeMd);
|
|
180
|
+
const chevronIcon = isExpanded ? '<i data-lucide="chevron-down" class="w-3 h-3"></i>' : '<i data-lucide="chevron-right" class="w-3 h-3"></i>';
|
|
181
|
+
return `
|
|
182
|
+
<div class="tree-item tree-folder ${isExpanded ? 'expanded' : ''} ${file.hasClaudeMd ? 'has-claude-md' : ''}" data-path="${escapeHtml(file.path)}" data-type="directory">
|
|
183
|
+
<div class="tree-item-row ${isSelected ? 'selected' : ''}" style="padding-left: ${depth * 16}px">
|
|
184
|
+
<span class="tree-chevron">${chevronIcon}</span>
|
|
185
|
+
<span class="tree-icon">${folderIcon}</span>
|
|
186
|
+
<span class="tree-name">${escapeHtml(file.name)}</span>
|
|
187
|
+
${file.hasClaudeMd ? `
|
|
188
|
+
<span class="claude-md-badge" title="Contains CLAUDE.md documentation">
|
|
189
|
+
<span class="badge-icon"><i data-lucide="file-check" class="w-3 h-3"></i></span>
|
|
190
|
+
<span class="badge-text">DOC</span>
|
|
191
|
+
</span>
|
|
192
|
+
` : ''}
|
|
193
|
+
<div class="tree-folder-actions">
|
|
194
|
+
<button class="tree-update-btn" onclick="event.stopPropagation(); addFolderToQueue('${escapeHtml(file.path)}', 'single-layer')" title="${t('explorer.currentFolderOnly')}">
|
|
195
|
+
<span class="update-icon"><i data-lucide="file" class="w-3.5 h-3.5"></i></span>
|
|
196
|
+
</button>
|
|
197
|
+
<button class="tree-update-btn tree-update-multi" onclick="event.stopPropagation(); addFolderToQueue('${escapeHtml(file.path)}', 'multi-layer')" title="${t('explorer.withSubdirs')}">
|
|
198
|
+
<span class="update-icon"><i data-lucide="folder-tree" class="w-3.5 h-3.5"></i></span>
|
|
199
|
+
</button>
|
|
200
|
+
</div>
|
|
201
|
+
</div>
|
|
202
|
+
<div class="tree-children ${isExpanded ? 'show' : ''}" id="children-${safeBase64Encode(file.path)}">
|
|
203
|
+
${isExpanded ? '' : ''}
|
|
204
|
+
</div>
|
|
205
|
+
</div>
|
|
206
|
+
`;
|
|
207
|
+
} else {
|
|
208
|
+
const ext = file.name.includes('.') ? file.name.split('.').pop().toLowerCase() : '';
|
|
209
|
+
const fileIcon = getFileIcon(ext);
|
|
210
|
+
// Special highlight for CLAUDE.md files
|
|
211
|
+
const isClaudeMd = file.name === 'CLAUDE.md';
|
|
212
|
+
return `
|
|
213
|
+
<div class="tree-item tree-file ${isSelected ? 'selected' : ''} ${isClaudeMd ? 'is-claude-md' : ''}" data-path="${escapeHtml(file.path)}" data-type="file">
|
|
214
|
+
<div class="tree-item-row" style="padding-left: ${depth * 16}px">
|
|
215
|
+
<span class="tree-chevron-spacer"></span>
|
|
216
|
+
<span class="tree-icon">${isClaudeMd ? '<span class="file-icon file-icon-claude"><i data-lucide="bot" class="w-3 h-3"></i></span>' : fileIcon}</span>
|
|
217
|
+
<span class="tree-name">${escapeHtml(file.name)}</span>
|
|
218
|
+
</div>
|
|
219
|
+
</div>
|
|
220
|
+
`;
|
|
221
|
+
}
|
|
222
|
+
}).join('');
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Get file icon based on extension - using colored SVG icons for better distinction
|
|
227
|
+
*/
|
|
228
|
+
function getFileIcon(ext) {
|
|
229
|
+
const iconMap = {
|
|
230
|
+
// JavaScript/TypeScript - distinct colors
|
|
231
|
+
'js': '<span class="file-icon file-icon-js">JS</span>',
|
|
232
|
+
'mjs': '<span class="file-icon file-icon-js">JS</span>',
|
|
233
|
+
'cjs': '<span class="file-icon file-icon-js">JS</span>',
|
|
234
|
+
'jsx': '<span class="file-icon file-icon-jsx">JSX</span>',
|
|
235
|
+
'ts': '<span class="file-icon file-icon-ts">TS</span>',
|
|
236
|
+
'tsx': '<span class="file-icon file-icon-tsx">TSX</span>',
|
|
237
|
+
|
|
238
|
+
// Python
|
|
239
|
+
'py': '<span class="file-icon file-icon-py">PY</span>',
|
|
240
|
+
'pyw': '<span class="file-icon file-icon-py">PY</span>',
|
|
241
|
+
|
|
242
|
+
// Other languages
|
|
243
|
+
'go': '<span class="file-icon file-icon-go">GO</span>',
|
|
244
|
+
'rs': '<span class="file-icon file-icon-rs">RS</span>',
|
|
245
|
+
'java': '<span class="file-icon file-icon-java">JV</span>',
|
|
246
|
+
'rb': '<span class="file-icon file-icon-rb">RB</span>',
|
|
247
|
+
'php': '<span class="file-icon file-icon-php">PHP</span>',
|
|
248
|
+
'c': '<span class="file-icon file-icon-c">C</span>',
|
|
249
|
+
'cpp': '<span class="file-icon file-icon-cpp">C++</span>',
|
|
250
|
+
'h': '<span class="file-icon file-icon-h">H</span>',
|
|
251
|
+
'cs': '<span class="file-icon file-icon-cs">C#</span>',
|
|
252
|
+
'swift': '<span class="file-icon file-icon-swift">SW</span>',
|
|
253
|
+
'kt': '<span class="file-icon file-icon-kt">KT</span>',
|
|
254
|
+
|
|
255
|
+
// Web
|
|
256
|
+
'html': '<span class="file-icon file-icon-html">HTML</span>',
|
|
257
|
+
'htm': '<span class="file-icon file-icon-html">HTML</span>',
|
|
258
|
+
'css': '<span class="file-icon file-icon-css">CSS</span>',
|
|
259
|
+
'scss': '<span class="file-icon file-icon-scss">SCSS</span>',
|
|
260
|
+
'sass': '<span class="file-icon file-icon-scss">SASS</span>',
|
|
261
|
+
'less': '<span class="file-icon file-icon-less">LESS</span>',
|
|
262
|
+
'vue': '<span class="file-icon file-icon-vue">VUE</span>',
|
|
263
|
+
'svelte': '<span class="file-icon file-icon-svelte">SV</span>',
|
|
264
|
+
|
|
265
|
+
// Config/Data
|
|
266
|
+
'json': '<span class="file-icon file-icon-json">{}</span>',
|
|
267
|
+
'yaml': '<span class="file-icon file-icon-yaml">YML</span>',
|
|
268
|
+
'yml': '<span class="file-icon file-icon-yaml">YML</span>',
|
|
269
|
+
'xml': '<span class="file-icon file-icon-xml">XML</span>',
|
|
270
|
+
'toml': '<span class="file-icon file-icon-toml">TML</span>',
|
|
271
|
+
'ini': '<span class="file-icon file-icon-ini">INI</span>',
|
|
272
|
+
'env': '<span class="file-icon file-icon-env">ENV</span>',
|
|
273
|
+
|
|
274
|
+
// Documentation
|
|
275
|
+
'md': '<span class="file-icon file-icon-md">MD</span>',
|
|
276
|
+
'markdown': '<span class="file-icon file-icon-md">MD</span>',
|
|
277
|
+
'txt': '<span class="file-icon file-icon-txt">TXT</span>',
|
|
278
|
+
'log': '<span class="file-icon file-icon-log">LOG</span>',
|
|
279
|
+
|
|
280
|
+
// Shell/Scripts
|
|
281
|
+
'sh': '<span class="file-icon file-icon-sh">SH</span>',
|
|
282
|
+
'bash': '<span class="file-icon file-icon-sh">SH</span>',
|
|
283
|
+
'zsh': '<span class="file-icon file-icon-sh">ZSH</span>',
|
|
284
|
+
'ps1': '<span class="file-icon file-icon-ps1">PS1</span>',
|
|
285
|
+
'bat': '<span class="file-icon file-icon-bat">BAT</span>',
|
|
286
|
+
'cmd': '<span class="file-icon file-icon-bat">CMD</span>',
|
|
287
|
+
|
|
288
|
+
// Database
|
|
289
|
+
'sql': '<span class="file-icon file-icon-sql">SQL</span>',
|
|
290
|
+
'db': '<span class="file-icon file-icon-db">DB</span>',
|
|
291
|
+
|
|
292
|
+
// Docker/Container
|
|
293
|
+
'dockerfile': '<span class="file-icon file-icon-docker"><i data-lucide="container" class="w-3 h-3"></i></span>',
|
|
294
|
+
|
|
295
|
+
// Images
|
|
296
|
+
'png': '<span class="file-icon file-icon-img">IMG</span>',
|
|
297
|
+
'jpg': '<span class="file-icon file-icon-img">IMG</span>',
|
|
298
|
+
'jpeg': '<span class="file-icon file-icon-img">IMG</span>',
|
|
299
|
+
'gif': '<span class="file-icon file-icon-img">GIF</span>',
|
|
300
|
+
'svg': '<span class="file-icon file-icon-svg">SVG</span>',
|
|
301
|
+
'ico': '<span class="file-icon file-icon-img">ICO</span>',
|
|
302
|
+
|
|
303
|
+
// Package
|
|
304
|
+
'lock': '<span class="file-icon file-icon-lock"><i data-lucide="lock" class="w-3 h-3"></i></span>'
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
return iconMap[ext] || '<span class="file-icon file-icon-default"><i data-lucide="file" class="w-3 h-3"></i></span>';
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Get folder icon based on folder name and state
|
|
312
|
+
*/
|
|
313
|
+
function getFolderIcon(name, isExpanded, hasClaudeMd) {
|
|
314
|
+
// Only special icon for .workflow folder
|
|
315
|
+
if (name === '.workflow') {
|
|
316
|
+
return '<i data-lucide="zap" class="w-4 h-4 text-warning"></i>';
|
|
317
|
+
}
|
|
318
|
+
return isExpanded
|
|
319
|
+
? '<i data-lucide="folder-open" class="w-4 h-4 text-warning"></i>'
|
|
320
|
+
: '<i data-lucide="folder" class="w-4 h-4 text-warning"></i>';
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Flag to track if event delegation is already set up
|
|
324
|
+
let explorerEventsDelegated = false;
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Attach event listeners using event delegation (only once on container)
|
|
328
|
+
*/
|
|
329
|
+
function attachTreeEventListeners() {
|
|
330
|
+
const treeContent = document.getElementById('explorerTreeContent');
|
|
331
|
+
if (!treeContent || explorerEventsDelegated) return;
|
|
332
|
+
|
|
333
|
+
explorerEventsDelegated = true;
|
|
334
|
+
|
|
335
|
+
// Use event delegation - single listener on container handles all clicks
|
|
336
|
+
treeContent.addEventListener('click', async (e) => {
|
|
337
|
+
// Check if clicked on folder row (but not on action buttons)
|
|
338
|
+
const folderRow = e.target.closest('.tree-folder > .tree-item-row');
|
|
339
|
+
if (folderRow && !e.target.closest('.tree-folder-actions')) {
|
|
340
|
+
const folder = folderRow.closest('.tree-folder');
|
|
341
|
+
const path = folder.dataset.path;
|
|
342
|
+
await toggleFolderExpand(path, folder);
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// Check if clicked on file
|
|
347
|
+
const fileItem = e.target.closest('.tree-file');
|
|
348
|
+
if (fileItem) {
|
|
349
|
+
const path = fileItem.dataset.path;
|
|
350
|
+
await previewFile(path);
|
|
351
|
+
|
|
352
|
+
// Update selection
|
|
353
|
+
document.querySelectorAll('.tree-item-row.selected, .tree-file.selected').forEach(el => {
|
|
354
|
+
el.classList.remove('selected');
|
|
355
|
+
});
|
|
356
|
+
fileItem.classList.add('selected');
|
|
357
|
+
explorerSelectedFile = path;
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Toggle folder expand/collapse
|
|
363
|
+
*/
|
|
364
|
+
async function toggleFolderExpand(path, folderElement) {
|
|
365
|
+
const isExpanded = explorerExpandedDirs.has(path);
|
|
366
|
+
const childrenContainer = folderElement.querySelector('.tree-children');
|
|
367
|
+
const chevron = folderElement.querySelector('.tree-chevron');
|
|
368
|
+
const folderIcon = folderElement.querySelector('.tree-icon');
|
|
369
|
+
|
|
370
|
+
if (isExpanded) {
|
|
371
|
+
// Collapse
|
|
372
|
+
explorerExpandedDirs.delete(path);
|
|
373
|
+
folderElement.classList.remove('expanded');
|
|
374
|
+
childrenContainer.classList.remove('show');
|
|
375
|
+
// Update chevron and folder icon
|
|
376
|
+
if (chevron) chevron.innerHTML = '<i data-lucide="chevron-right" class="w-3 h-3"></i>';
|
|
377
|
+
if (folderIcon && !folderElement.querySelector('[data-lucide="zap"]')) {
|
|
378
|
+
folderIcon.innerHTML = '<i data-lucide="folder" class="w-4 h-4 text-warning"></i>';
|
|
379
|
+
}
|
|
380
|
+
} else {
|
|
381
|
+
// Expand - load children if not loaded
|
|
382
|
+
explorerExpandedDirs.add(path);
|
|
383
|
+
folderElement.classList.add('expanded');
|
|
384
|
+
childrenContainer.classList.add('show');
|
|
385
|
+
// Update chevron and folder icon
|
|
386
|
+
if (chevron) chevron.innerHTML = '<i data-lucide="chevron-down" class="w-3 h-3"></i>';
|
|
387
|
+
if (folderIcon && !folderElement.querySelector('[data-lucide="zap"]')) {
|
|
388
|
+
folderIcon.innerHTML = '<i data-lucide="folder-open" class="w-4 h-4 text-warning"></i>';
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
if (!childrenContainer.innerHTML.trim()) {
|
|
392
|
+
childrenContainer.innerHTML = '<div class="tree-loading">Loading...</div>';
|
|
393
|
+
|
|
394
|
+
try {
|
|
395
|
+
const response = await fetch(`/api/files?path=${encodeURIComponent(path)}`);
|
|
396
|
+
const data = await response.json();
|
|
397
|
+
|
|
398
|
+
const depth = (path.match(/\//g) || []).length - (explorerCurrentPath.match(/\//g) || []).length + 1;
|
|
399
|
+
childrenContainer.innerHTML = renderTreeLevel(data.files, path, depth);
|
|
400
|
+
} catch (error) {
|
|
401
|
+
childrenContainer.innerHTML = `<div class="tree-error">Failed to load</div>`;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// Reinitialize Lucide icons after DOM changes
|
|
407
|
+
if (typeof lucide !== 'undefined') lucide.createIcons();
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Preview a file in the right panel
|
|
412
|
+
*/
|
|
413
|
+
async function previewFile(filePath) {
|
|
414
|
+
const previewHeader = document.getElementById('explorerPreviewHeader');
|
|
415
|
+
const previewContent = document.getElementById('explorerPreviewContent');
|
|
416
|
+
|
|
417
|
+
const fileName = filePath.split('/').pop();
|
|
418
|
+
const ext = fileName.includes('.') ? fileName.split('.').pop().toLowerCase() : '';
|
|
419
|
+
const isMarkdown = ext === 'md' || ext === 'markdown';
|
|
420
|
+
|
|
421
|
+
// Build header with tabs for markdown files
|
|
422
|
+
previewHeader.innerHTML = `
|
|
423
|
+
<div class="preview-header-left">
|
|
424
|
+
<span class="preview-filename">${escapeHtml(fileName)}</span>
|
|
425
|
+
<span class="preview-path" title="${escapeHtml(filePath)}">${escapeHtml(filePath)}</span>
|
|
426
|
+
</div>
|
|
427
|
+
${isMarkdown ? `
|
|
428
|
+
<div class="preview-header-tabs" id="previewHeaderTabs">
|
|
429
|
+
<button class="preview-tab active" data-tab="rendered" onclick="switchPreviewTab(this, 'rendered')">${t('explorer.preview')}</button>
|
|
430
|
+
<button class="preview-tab" data-tab="source" onclick="switchPreviewTab(this, 'source')">${t('explorer.source')}</button>
|
|
431
|
+
</div>
|
|
432
|
+
` : ''}
|
|
433
|
+
`;
|
|
434
|
+
|
|
435
|
+
previewContent.innerHTML = '<div class="explorer-loading">Loading file...</div>';
|
|
436
|
+
|
|
437
|
+
try {
|
|
438
|
+
const response = await fetch(`/api/file-content?path=${encodeURIComponent(filePath)}`);
|
|
439
|
+
const data = await response.json();
|
|
440
|
+
|
|
441
|
+
if (data.error) {
|
|
442
|
+
previewContent.innerHTML = `<div class="explorer-error">${escapeHtml(data.error)}</div>`;
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
if (data.isMarkdown) {
|
|
447
|
+
// Render markdown with tabs content (tabs are in header)
|
|
448
|
+
const rendered = marked.parse(data.content);
|
|
449
|
+
previewContent.innerHTML = `
|
|
450
|
+
<div class="preview-tab-content rendered show" data-tab="rendered">
|
|
451
|
+
<div class="markdown-preview prose">${rendered}</div>
|
|
452
|
+
</div>
|
|
453
|
+
<div class="preview-tab-content source" data-tab="source">
|
|
454
|
+
<pre><code class="language-markdown">${escapeHtml(data.content)}</code></pre>
|
|
455
|
+
</div>
|
|
456
|
+
`;
|
|
457
|
+
} else {
|
|
458
|
+
// Render code with syntax highlighting
|
|
459
|
+
previewContent.innerHTML = `
|
|
460
|
+
<div class="preview-info">
|
|
461
|
+
<span class="preview-lang">${data.language}</span>
|
|
462
|
+
<span class="preview-lines">${data.lines} ${t('explorer.lines')}</span>
|
|
463
|
+
<span class="preview-size">${formatFileSize(data.size)}</span>
|
|
464
|
+
</div>
|
|
465
|
+
<pre class="preview-code"><code class="language-${data.language}">${escapeHtml(data.content)}</code></pre>
|
|
466
|
+
`;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// Apply syntax highlighting if hljs is available
|
|
470
|
+
if (typeof hljs !== 'undefined') {
|
|
471
|
+
previewContent.querySelectorAll('pre code').forEach(block => {
|
|
472
|
+
hljs.highlightElement(block);
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
} catch (error) {
|
|
477
|
+
previewContent.innerHTML = `<div class="explorer-error">Failed to load: ${escapeHtml(error.message)}</div>`;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Switch preview tab (for markdown files)
|
|
483
|
+
*/
|
|
484
|
+
function switchPreviewTab(btn, tabName) {
|
|
485
|
+
const previewPanel = btn.closest('.explorer-preview-panel');
|
|
486
|
+
const contentArea = previewPanel.querySelector('.explorer-preview-content');
|
|
487
|
+
|
|
488
|
+
// Update tab buttons in header
|
|
489
|
+
previewPanel.querySelectorAll('.preview-tab').forEach(t => t.classList.remove('active'));
|
|
490
|
+
btn.classList.add('active');
|
|
491
|
+
|
|
492
|
+
// Update tab content
|
|
493
|
+
contentArea.querySelectorAll('.preview-tab-content').forEach(c => c.classList.remove('show'));
|
|
494
|
+
contentArea.querySelector(`[data-tab="${tabName}"]`).classList.add('show');
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
/**
|
|
498
|
+
* Format file size
|
|
499
|
+
*/
|
|
500
|
+
function formatFileSize(bytes) {
|
|
501
|
+
if (bytes < 1024) return bytes + ' B';
|
|
502
|
+
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';
|
|
503
|
+
return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* Refresh the explorer tree
|
|
508
|
+
*/
|
|
509
|
+
async function refreshExplorerTree() {
|
|
510
|
+
const btn = document.querySelector('.explorer-refresh-btn');
|
|
511
|
+
if (btn) {
|
|
512
|
+
btn.classList.add('refreshing');
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
explorerExpandedDirs.clear();
|
|
516
|
+
explorerEventsDelegated = false;
|
|
517
|
+
await loadExplorerTree(explorerCurrentPath);
|
|
518
|
+
|
|
519
|
+
if (btn) {
|
|
520
|
+
btn.classList.remove('refreshing');
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* Open Update CLAUDE.md modal
|
|
526
|
+
*/
|
|
527
|
+
function openUpdateClaudeMdModal(folderPath) {
|
|
528
|
+
const modal = document.getElementById('updateClaudeMdModal');
|
|
529
|
+
if (!modal) return;
|
|
530
|
+
|
|
531
|
+
// Set folder path
|
|
532
|
+
document.getElementById('claudeMdTargetPath').textContent = folderPath;
|
|
533
|
+
document.getElementById('claudeMdTargetPath').dataset.path = folderPath;
|
|
534
|
+
|
|
535
|
+
// Reset form
|
|
536
|
+
document.getElementById('claudeMdTool').value = 'gemini';
|
|
537
|
+
document.getElementById('claudeMdStrategy').value = 'single-layer';
|
|
538
|
+
|
|
539
|
+
// Show modal
|
|
540
|
+
modal.classList.remove('hidden');
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* Close Update CLAUDE.md modal
|
|
545
|
+
*/
|
|
546
|
+
function closeUpdateClaudeMdModal() {
|
|
547
|
+
const modal = document.getElementById('updateClaudeMdModal');
|
|
548
|
+
if (modal) {
|
|
549
|
+
modal.classList.add('hidden');
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
/**
|
|
554
|
+
* Execute Update CLAUDE.md
|
|
555
|
+
*/
|
|
556
|
+
async function executeUpdateClaudeMd() {
|
|
557
|
+
const pathEl = document.getElementById('claudeMdTargetPath');
|
|
558
|
+
const toolSelect = document.getElementById('claudeMdTool');
|
|
559
|
+
const strategySelect = document.getElementById('claudeMdStrategy');
|
|
560
|
+
const executeBtn = document.getElementById('claudeMdExecuteBtn');
|
|
561
|
+
const statusEl = document.getElementById('claudeMdStatus');
|
|
562
|
+
|
|
563
|
+
const path = pathEl.dataset.path;
|
|
564
|
+
const tool = toolSelect.value;
|
|
565
|
+
const strategy = strategySelect.value;
|
|
566
|
+
|
|
567
|
+
// Update UI
|
|
568
|
+
executeBtn.disabled = true;
|
|
569
|
+
executeBtn.textContent = 'Updating...';
|
|
570
|
+
statusEl.innerHTML = '<div class="status-running">⏳ Running update...</div>';
|
|
571
|
+
|
|
572
|
+
try {
|
|
573
|
+
const response = await fetch('/api/update-claude-md', {
|
|
574
|
+
method: 'POST',
|
|
575
|
+
headers: { 'Content-Type': 'application/json' },
|
|
576
|
+
body: JSON.stringify({ path, tool, strategy })
|
|
577
|
+
});
|
|
578
|
+
|
|
579
|
+
const result = await response.json();
|
|
580
|
+
|
|
581
|
+
if (result.success) {
|
|
582
|
+
statusEl.innerHTML = `<div class="status-success"><i data-lucide="check-circle" class="w-4 h-4 inline text-success"></i> ${escapeHtml(result.message)}</div>`;
|
|
583
|
+
// Refresh tree to update CLAUDE.md indicators
|
|
584
|
+
await refreshExplorerTree();
|
|
585
|
+
if (typeof lucide !== 'undefined') lucide.createIcons();
|
|
586
|
+
} else {
|
|
587
|
+
statusEl.innerHTML = `<div class="status-error"><i data-lucide="x-circle" class="w-4 h-4 inline text-destructive"></i> ${escapeHtml(result.error || 'Update failed')}</div>`;
|
|
588
|
+
if (typeof lucide !== 'undefined') lucide.createIcons();
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
} catch (error) {
|
|
592
|
+
statusEl.innerHTML = `<div class="status-error"><i data-lucide="x-circle" class="w-4 h-4 inline text-destructive"></i> ${escapeHtml(error.message)}</div>`;
|
|
593
|
+
if (typeof lucide !== 'undefined') lucide.createIcons();
|
|
594
|
+
} finally {
|
|
595
|
+
executeBtn.disabled = false;
|
|
596
|
+
executeBtn.textContent = 'Execute';
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
// ============================================
|
|
601
|
+
// TASK QUEUE FUNCTIONS
|
|
602
|
+
// ============================================
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* Toggle task queue panel visibility
|
|
606
|
+
*/
|
|
607
|
+
function toggleTaskQueue() {
|
|
608
|
+
isTaskQueueVisible = !isTaskQueueVisible;
|
|
609
|
+
const panel = document.getElementById('taskQueuePanel');
|
|
610
|
+
const fab = document.querySelector('.explorer-fab');
|
|
611
|
+
|
|
612
|
+
if (isTaskQueueVisible) {
|
|
613
|
+
panel.classList.add('show');
|
|
614
|
+
fab.classList.add('active');
|
|
615
|
+
} else {
|
|
616
|
+
panel.classList.remove('show');
|
|
617
|
+
fab.classList.remove('active');
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
/**
|
|
622
|
+
* Update default CLI tool
|
|
623
|
+
*/
|
|
624
|
+
function updateDefaultCliTool(tool) {
|
|
625
|
+
defaultCliTool = tool;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
/**
|
|
629
|
+
* Update the FAB badge count
|
|
630
|
+
*/
|
|
631
|
+
function updateFabBadge() {
|
|
632
|
+
const badge = document.getElementById('fabBadge');
|
|
633
|
+
if (badge) {
|
|
634
|
+
const pendingCount = updateTaskQueue.filter(t => t.status === 'pending' || t.status === 'running').length;
|
|
635
|
+
badge.textContent = pendingCount || '';
|
|
636
|
+
badge.style.display = pendingCount > 0 ? 'flex' : 'none';
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
/**
|
|
641
|
+
* Open add task modal
|
|
642
|
+
*/
|
|
643
|
+
function openAddTaskModal() {
|
|
644
|
+
const modal = document.getElementById('updateClaudeMdModal');
|
|
645
|
+
if (!modal) return;
|
|
646
|
+
|
|
647
|
+
// Set default path to current project
|
|
648
|
+
document.getElementById('claudeMdTargetPath').textContent = explorerCurrentPath;
|
|
649
|
+
document.getElementById('claudeMdTargetPath').dataset.path = explorerCurrentPath;
|
|
650
|
+
|
|
651
|
+
// Reset form
|
|
652
|
+
document.getElementById('claudeMdTool').value = 'gemini';
|
|
653
|
+
document.getElementById('claudeMdStrategy').value = 'single-layer';
|
|
654
|
+
document.getElementById('claudeMdStatus').innerHTML = '';
|
|
655
|
+
|
|
656
|
+
// Change button to "Add to Queue"
|
|
657
|
+
const executeBtn = document.getElementById('claudeMdExecuteBtn');
|
|
658
|
+
executeBtn.textContent = 'Add to Queue';
|
|
659
|
+
executeBtn.onclick = addTaskToQueue;
|
|
660
|
+
|
|
661
|
+
modal.classList.remove('hidden');
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
/**
|
|
665
|
+
* Add task to queue from modal
|
|
666
|
+
*/
|
|
667
|
+
function addTaskToQueue() {
|
|
668
|
+
const pathEl = document.getElementById('claudeMdTargetPath');
|
|
669
|
+
const toolSelect = document.getElementById('claudeMdTool');
|
|
670
|
+
const strategySelect = document.getElementById('claudeMdStrategy');
|
|
671
|
+
|
|
672
|
+
const path = pathEl.dataset.path;
|
|
673
|
+
const tool = toolSelect.value;
|
|
674
|
+
const strategy = strategySelect.value;
|
|
675
|
+
|
|
676
|
+
addUpdateTask(path, tool, strategy);
|
|
677
|
+
closeUpdateClaudeMdModal();
|
|
678
|
+
|
|
679
|
+
// Show task queue
|
|
680
|
+
if (!isTaskQueueVisible) {
|
|
681
|
+
toggleTaskQueue();
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
/**
|
|
686
|
+
* Add a task to the update queue
|
|
687
|
+
*/
|
|
688
|
+
function addUpdateTask(path, tool = 'gemini', strategy = 'single-layer') {
|
|
689
|
+
const task = {
|
|
690
|
+
id: Date.now(),
|
|
691
|
+
path,
|
|
692
|
+
tool,
|
|
693
|
+
strategy,
|
|
694
|
+
status: 'pending', // pending, running, completed, failed
|
|
695
|
+
message: '',
|
|
696
|
+
addedAt: new Date().toISOString()
|
|
697
|
+
};
|
|
698
|
+
|
|
699
|
+
updateTaskQueue.push(task);
|
|
700
|
+
renderTaskQueue();
|
|
701
|
+
updateFabBadge();
|
|
702
|
+
|
|
703
|
+
// Enable start button
|
|
704
|
+
document.getElementById('startQueueBtn').disabled = false;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
/**
|
|
708
|
+
* Add task from folder context (right-click or button)
|
|
709
|
+
*/
|
|
710
|
+
function addFolderToQueue(folderPath, strategy = 'single-layer') {
|
|
711
|
+
// Use the sidebar queue instead of floating panel
|
|
712
|
+
if (typeof addUpdateTaskToSidebar === 'function') {
|
|
713
|
+
addUpdateTaskToSidebar(folderPath, defaultCliTool, strategy);
|
|
714
|
+
} else {
|
|
715
|
+
// Fallback to local queue
|
|
716
|
+
addUpdateTask(folderPath, defaultCliTool, strategy);
|
|
717
|
+
|
|
718
|
+
// Show task queue if not visible
|
|
719
|
+
if (!isTaskQueueVisible) {
|
|
720
|
+
toggleTaskQueue();
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
/**
|
|
726
|
+
* Render the task queue list
|
|
727
|
+
*/
|
|
728
|
+
function renderTaskQueue() {
|
|
729
|
+
const listEl = document.getElementById('taskQueueList');
|
|
730
|
+
|
|
731
|
+
if (updateTaskQueue.length === 0) {
|
|
732
|
+
listEl.innerHTML = `
|
|
733
|
+
<div class="task-queue-empty">
|
|
734
|
+
<span>${t('taskQueue.noTasks')}</span>
|
|
735
|
+
<p>${t('taskQueue.noTasksHint')}</p>
|
|
736
|
+
</div>
|
|
737
|
+
`;
|
|
738
|
+
return;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
listEl.innerHTML = updateTaskQueue.map(task => {
|
|
742
|
+
const folderName = task.path.split('/').pop() || task.path;
|
|
743
|
+
const strategyLabel = task.strategy === 'multi-layer'
|
|
744
|
+
? '<i data-lucide="folder-tree" class="w-3 h-3 inline"></i> ' + t('taskQueue.withSubdirs')
|
|
745
|
+
: '<i data-lucide="file" class="w-3 h-3 inline"></i> ' + t('taskQueue.currentOnly');
|
|
746
|
+
const statusIcon = {
|
|
747
|
+
'pending': '<i data-lucide="clock" class="w-4 h-4"></i>',
|
|
748
|
+
'running': '<i data-lucide="loader-2" class="w-4 h-4 animate-spin"></i>',
|
|
749
|
+
'completed': '<i data-lucide="check-circle" class="w-4 h-4 text-success"></i>',
|
|
750
|
+
'failed': '<i data-lucide="x-circle" class="w-4 h-4 text-destructive"></i>'
|
|
751
|
+
}[task.status];
|
|
752
|
+
|
|
753
|
+
return `
|
|
754
|
+
<div class="task-queue-item status-${task.status}" data-task-id="${task.id}">
|
|
755
|
+
<div class="task-item-header">
|
|
756
|
+
<span class="task-status-icon">${statusIcon}</span>
|
|
757
|
+
<span class="task-folder-name" title="${escapeHtml(task.path)}">${escapeHtml(folderName)}</span>
|
|
758
|
+
${task.status === 'pending' ? `
|
|
759
|
+
<button class="task-remove-btn" onclick="removeTask(${task.id})" title="Remove">×</button>
|
|
760
|
+
` : ''}
|
|
761
|
+
</div>
|
|
762
|
+
<div class="task-item-meta">
|
|
763
|
+
<span class="task-strategy">${strategyLabel}</span>
|
|
764
|
+
<span class="task-tool">${task.tool}</span>
|
|
765
|
+
</div>
|
|
766
|
+
${task.message ? `<div class="task-item-message">${escapeHtml(task.message)}</div>` : ''}
|
|
767
|
+
</div>
|
|
768
|
+
`;
|
|
769
|
+
}).join('');
|
|
770
|
+
|
|
771
|
+
// Reinitialize Lucide icons
|
|
772
|
+
if (typeof lucide !== 'undefined') lucide.createIcons();
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
/**
|
|
776
|
+
* Remove a task from queue
|
|
777
|
+
*/
|
|
778
|
+
function removeTask(taskId) {
|
|
779
|
+
updateTaskQueue = updateTaskQueue.filter(t => t.id !== taskId);
|
|
780
|
+
renderTaskQueue();
|
|
781
|
+
updateFabBadge();
|
|
782
|
+
|
|
783
|
+
// Disable start button if no pending tasks
|
|
784
|
+
const hasPending = updateTaskQueue.some(t => t.status === 'pending');
|
|
785
|
+
document.getElementById('startQueueBtn').disabled = !hasPending;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
/**
|
|
789
|
+
* Clear completed/failed tasks
|
|
790
|
+
*/
|
|
791
|
+
function clearCompletedTasks() {
|
|
792
|
+
updateTaskQueue = updateTaskQueue.filter(t => t.status === 'pending' || t.status === 'running');
|
|
793
|
+
renderTaskQueue();
|
|
794
|
+
updateFabBadge();
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
/**
|
|
798
|
+
* Execute a single task asynchronously
|
|
799
|
+
*/
|
|
800
|
+
async function executeTask(task) {
|
|
801
|
+
const folderName = task.path.split('/').pop() || task.path;
|
|
802
|
+
|
|
803
|
+
// Update status to running
|
|
804
|
+
task.status = 'running';
|
|
805
|
+
task.message = t('taskQueue.processing');
|
|
806
|
+
renderTaskQueue();
|
|
807
|
+
|
|
808
|
+
addGlobalNotification('info', `Processing: ${folderName}`, `Strategy: ${task.strategy}, Tool: ${task.tool}`, 'Explorer');
|
|
809
|
+
|
|
810
|
+
try {
|
|
811
|
+
const response = await fetch('/api/update-claude-md', {
|
|
812
|
+
method: 'POST',
|
|
813
|
+
headers: { 'Content-Type': 'application/json' },
|
|
814
|
+
body: JSON.stringify({
|
|
815
|
+
path: task.path,
|
|
816
|
+
tool: task.tool,
|
|
817
|
+
strategy: task.strategy
|
|
818
|
+
})
|
|
819
|
+
});
|
|
820
|
+
|
|
821
|
+
const result = await response.json();
|
|
822
|
+
|
|
823
|
+
if (result.success) {
|
|
824
|
+
task.status = 'completed';
|
|
825
|
+
task.message = t('taskQueue.updated');
|
|
826
|
+
addGlobalNotification('success', `Completed: ${folderName}`, result.message, 'Explorer');
|
|
827
|
+
return { success: true };
|
|
828
|
+
} else {
|
|
829
|
+
task.status = 'failed';
|
|
830
|
+
task.message = result.error || t('taskQueue.failed');
|
|
831
|
+
addGlobalNotification('error', `Failed: ${folderName}`, result.error || 'Unknown error', 'Explorer');
|
|
832
|
+
return { success: false };
|
|
833
|
+
}
|
|
834
|
+
} catch (error) {
|
|
835
|
+
task.status = 'failed';
|
|
836
|
+
task.message = error.message;
|
|
837
|
+
addGlobalNotification('error', `Error: ${folderName}`, error.message, 'Explorer');
|
|
838
|
+
return { success: false };
|
|
839
|
+
} finally {
|
|
840
|
+
renderTaskQueue();
|
|
841
|
+
updateFabBadge();
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
/**
|
|
846
|
+
* Start processing task queue - executes tasks asynchronously in parallel
|
|
847
|
+
*/
|
|
848
|
+
async function startTaskQueue() {
|
|
849
|
+
if (isTaskRunning) return;
|
|
850
|
+
|
|
851
|
+
const pendingTasks = updateTaskQueue.filter(t => t.status === 'pending');
|
|
852
|
+
if (pendingTasks.length === 0) return;
|
|
853
|
+
|
|
854
|
+
isTaskRunning = true;
|
|
855
|
+
document.getElementById('startQueueBtn').disabled = true;
|
|
856
|
+
|
|
857
|
+
addGlobalNotification('info', t('taskQueue.startingTasks', { count: pendingTasks.length }), null, 'Explorer');
|
|
858
|
+
|
|
859
|
+
// Execute all tasks in parallel
|
|
860
|
+
const results = await Promise.all(pendingTasks.map(task => executeTask(task)));
|
|
861
|
+
|
|
862
|
+
const successCount = results.filter(r => r.success).length;
|
|
863
|
+
const failCount = results.filter(r => !r.success).length;
|
|
864
|
+
|
|
865
|
+
isTaskRunning = false;
|
|
866
|
+
|
|
867
|
+
// Summary notification
|
|
868
|
+
addGlobalNotification(
|
|
869
|
+
failCount === 0 ? 'success' : 'warning',
|
|
870
|
+
t('taskQueue.queueCompleted', { success: successCount, failed: failCount }),
|
|
871
|
+
null,
|
|
872
|
+
'Explorer'
|
|
873
|
+
);
|
|
874
|
+
|
|
875
|
+
// Force refresh notification list to ensure all notifications are displayed
|
|
876
|
+
if (typeof renderGlobalNotifications === 'function') {
|
|
877
|
+
renderGlobalNotifications();
|
|
878
|
+
updateGlobalNotifBadge();
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
// Re-enable start button if there are pending tasks
|
|
882
|
+
const hasPending = updateTaskQueue.some(t => t.status === 'pending');
|
|
883
|
+
document.getElementById('startQueueBtn').disabled = !hasPending;
|
|
884
|
+
|
|
885
|
+
// Refresh tree to show updated CLAUDE.md files
|
|
886
|
+
await refreshExplorerTree();
|
|
887
|
+
}
|
|
888
|
+
|