claude-code-workflow 6.3.18 → 6.3.19
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 +8 -5
- package/.claude/agents/action-planning-agent.md +26 -2
- package/.claude/agents/code-developer.md +132 -43
- package/.claude/agents/debug-explore-agent.md +434 -0
- package/.claude/agents/test-fix-agent.md +14 -0
- package/.claude/commands/issue/discover.md +41 -0
- package/.claude/commands/issue/execute.md +200 -19
- package/.claude/commands/issue/new.md +1 -1
- package/.claude/commands/issue/plan.md +6 -1
- package/.claude/commands/issue/queue.md +94 -39
- package/.claude/commands/memory/swagger-docs.md +773 -0
- package/.claude/commands/workflow/brainstorm/auto-parallel.md +21 -21
- package/.claude/commands/workflow/execute.md +54 -34
- package/.claude/commands/workflow/lite-execute.md +48 -164
- package/.claude/commands/workflow/lite-fix.md +4 -4
- package/.claude/commands/workflow/lite-plan.md +5 -5
- package/.claude/commands/workflow/plan.md +27 -27
- package/.claude/commands/workflow/review.md +42 -17
- package/.claude/commands/workflow/tdd-plan.md +25 -25
- package/.claude/commands/workflow/test-fix-gen.md +10 -10
- package/.claude/commands/workflow/test-gen.md +14 -14
- package/.claude/commands/workflow/ui-design/explore-auto.md +21 -21
- package/.claude/commands/workflow/ui-design/imitate-auto.md +24 -24
- package/.claude/skills/_shared/SKILL-DESIGN-SPEC.md +693 -0
- package/.claude/skills/ccw/SKILL.md +462 -0
- package/.claude/skills/ccw/index/command-capabilities.json +127 -0
- package/.claude/skills/ccw/index/intent-rules.json +136 -0
- package/.claude/skills/ccw/index/workflow-chains.json +451 -0
- package/.claude/skills/ccw/phases/actions/bugfix.md +218 -0
- package/.claude/skills/ccw/phases/actions/coupled.md +194 -0
- package/.claude/skills/ccw/phases/actions/docs.md +93 -0
- package/.claude/skills/ccw/phases/actions/full.md +154 -0
- package/.claude/skills/ccw/phases/actions/issue.md +201 -0
- package/.claude/skills/ccw/phases/actions/rapid.md +104 -0
- package/.claude/skills/ccw/phases/actions/review-fix.md +84 -0
- package/.claude/skills/ccw/phases/actions/tdd.md +66 -0
- package/.claude/skills/ccw/phases/actions/ui.md +79 -0
- package/.claude/skills/ccw/phases/orchestrator.md +435 -0
- package/.claude/skills/ccw/specs/intent-classification.md +336 -0
- package/.claude/skills/ccw-help/SKILL.md +177 -0
- package/.claude/skills/ccw-help/index/all-agents.json +82 -0
- package/.claude/skills/{command-guide → ccw-help}/index/all-commands.json +183 -73
- package/.claude/skills/{command-guide → ccw-help}/index/by-category.json +187 -73
- package/.claude/skills/{command-guide → ccw-help}/index/by-use-case.json +295 -185
- package/.claude/skills/{command-guide → ccw-help}/index/command-relationships.json +19 -166
- package/.claude/skills/{command-guide → ccw-help}/index/essential-commands.json +10 -10
- package/.claude/skills/ccw-help/scripts/analyze_commands.py +337 -0
- package/.claude/skills/code-reviewer/README.md +340 -0
- package/.claude/skills/code-reviewer/SKILL.md +308 -0
- package/.claude/skills/code-reviewer/phases/01-code-discovery.md +246 -0
- package/.claude/skills/code-reviewer/phases/02-security-analysis.md +442 -0
- package/.claude/skills/code-reviewer/phases/03-best-practices-review.md +36 -0
- package/.claude/skills/code-reviewer/phases/04-report-generation.md +278 -0
- package/.claude/skills/code-reviewer/specs/best-practices-requirements.md +346 -0
- package/.claude/skills/code-reviewer/specs/quality-standards.md +252 -0
- package/.claude/skills/code-reviewer/specs/security-requirements.md +243 -0
- package/.claude/skills/code-reviewer/templates/best-practice-finding.md +234 -0
- package/.claude/skills/code-reviewer/templates/report-template.md +316 -0
- package/.claude/skills/code-reviewer/templates/security-finding.md +161 -0
- package/.claude/skills/skill-generator/SKILL.md +187 -0
- package/.claude/skills/skill-generator/phases/01-requirements-discovery.md +239 -0
- package/.claude/skills/skill-generator/phases/02-structure-generation.md +207 -0
- package/.claude/skills/skill-generator/phases/03-phase-generation.md +802 -0
- package/.claude/skills/skill-generator/phases/04-specs-templates.md +328 -0
- package/.claude/skills/skill-generator/phases/05-validation.md +334 -0
- package/.claude/skills/skill-generator/specs/cli-integration.md +448 -0
- package/.claude/skills/skill-generator/specs/execution-modes.md +396 -0
- package/.claude/skills/skill-generator/specs/scripting-integration.md +265 -0
- package/.claude/skills/skill-generator/specs/skill-requirements.md +466 -0
- package/.claude/skills/skill-generator/templates/autonomous-action.md +517 -0
- package/.claude/skills/skill-generator/templates/autonomous-orchestrator.md +276 -0
- package/.claude/skills/skill-generator/templates/code-analysis-action.md +503 -0
- package/.claude/skills/skill-generator/templates/llm-action.md +355 -0
- package/.claude/skills/skill-generator/templates/script-bash.md +277 -0
- package/.claude/skills/skill-generator/templates/script-python.md +198 -0
- package/.claude/skills/skill-generator/templates/sequential-phase.md +441 -0
- package/.claude/skills/skill-generator/templates/skill-md.md +156 -0
- package/.claude/workflows/chinese-response.md +15 -28
- package/.claude/workflows/cli-templates/prompts/documentation/swagger-api.txt +266 -0
- package/.claude/workflows/cli-tools-usage.md +221 -177
- package/.claude/workflows/windows-platform.md +13 -10
- package/.codex/prompts/issue-execute.md +305 -82
- package/.codex/prompts/issue-queue.md +22 -0
- package/.codex/prompts/lite-execute.md +36 -11
- package/README.md +309 -305
- package/ccw/README.md +10 -4
- package/ccw/dist/cli.d.ts.map +1 -1
- package/ccw/dist/cli.js +4 -1
- package/ccw/dist/cli.js.map +1 -1
- package/ccw/dist/commands/cli.d.ts.map +1 -1
- package/ccw/dist/commands/cli.js +131 -34
- package/ccw/dist/commands/cli.js.map +1 -1
- package/ccw/dist/commands/issue.d.ts +152 -0
- package/ccw/dist/commands/issue.d.ts.map +1 -1
- package/ccw/dist/commands/issue.js +550 -85
- package/ccw/dist/commands/issue.js.map +1 -1
- package/ccw/dist/commands/serve.d.ts +1 -0
- package/ccw/dist/commands/serve.d.ts.map +1 -1
- package/ccw/dist/commands/serve.js +12 -5
- package/ccw/dist/commands/serve.js.map +1 -1
- package/ccw/dist/commands/stop.d.ts.map +1 -1
- package/ccw/dist/commands/stop.js +29 -5
- package/ccw/dist/commands/stop.js.map +1 -1
- package/ccw/dist/commands/tool.d.ts.map +1 -1
- package/ccw/dist/commands/tool.js +19 -2
- package/ccw/dist/commands/tool.js.map +1 -1
- package/ccw/dist/commands/view.d.ts +1 -0
- package/ccw/dist/commands/view.d.ts.map +1 -1
- package/ccw/dist/commands/view.js +10 -3
- package/ccw/dist/commands/view.js.map +1 -1
- package/ccw/dist/config/cli-settings-manager.d.ts +86 -0
- package/ccw/dist/config/cli-settings-manager.d.ts.map +1 -0
- package/ccw/dist/config/cli-settings-manager.js +392 -0
- package/ccw/dist/config/cli-settings-manager.js.map +1 -0
- package/ccw/dist/config/litellm-api-config-manager.d.ts +71 -5
- package/ccw/dist/config/litellm-api-config-manager.d.ts.map +1 -1
- package/ccw/dist/config/litellm-api-config-manager.js +290 -20
- package/ccw/dist/config/litellm-api-config-manager.js.map +1 -1
- package/ccw/dist/core/auth/csrf-manager.d.ts +18 -0
- package/ccw/dist/core/auth/csrf-manager.d.ts.map +1 -0
- package/ccw/dist/core/auth/csrf-manager.js +80 -0
- package/ccw/dist/core/auth/csrf-manager.js.map +1 -0
- package/ccw/dist/core/auth/csrf-middleware.d.ts +8 -0
- package/ccw/dist/core/auth/csrf-middleware.d.ts.map +1 -0
- package/ccw/dist/core/auth/csrf-middleware.js +141 -0
- package/ccw/dist/core/auth/csrf-middleware.js.map +1 -0
- package/ccw/dist/core/auth/middleware.d.ts +15 -0
- package/ccw/dist/core/auth/middleware.d.ts.map +1 -0
- package/ccw/dist/core/auth/middleware.js +76 -0
- package/ccw/dist/core/auth/middleware.js.map +1 -0
- package/ccw/dist/core/auth/token-manager.d.ts +41 -0
- package/ccw/dist/core/auth/token-manager.d.ts.map +1 -0
- package/ccw/dist/core/auth/token-manager.js +171 -0
- package/ccw/dist/core/auth/token-manager.js.map +1 -0
- package/ccw/dist/core/cache-manager.d.ts +6 -6
- package/ccw/dist/core/cache-manager.d.ts.map +1 -1
- package/ccw/dist/core/cache-manager.js +70 -48
- package/ccw/dist/core/cache-manager.js.map +1 -1
- package/ccw/dist/core/claude-freshness.d.ts.map +1 -1
- package/ccw/dist/core/claude-freshness.js +23 -3
- package/ccw/dist/core/claude-freshness.js.map +1 -1
- package/ccw/dist/core/core-memory-store.d.ts.map +1 -1
- package/ccw/dist/core/core-memory-store.js +2 -1
- package/ccw/dist/core/core-memory-store.js.map +1 -1
- package/ccw/dist/core/cors.d.ts +3 -0
- package/ccw/dist/core/cors.d.ts.map +1 -0
- package/ccw/dist/core/cors.js +10 -0
- package/ccw/dist/core/cors.js.map +1 -0
- package/ccw/dist/core/dashboard-generator-patch.js +0 -1
- package/ccw/dist/core/dashboard-generator-patch.js.map +1 -1
- package/ccw/dist/core/dashboard-generator.d.ts.map +1 -1
- package/ccw/dist/core/dashboard-generator.js +417 -416
- package/ccw/dist/core/dashboard-generator.js.map +1 -1
- package/ccw/dist/core/data-aggregator.js +2 -2
- package/ccw/dist/core/data-aggregator.js.map +1 -1
- package/ccw/dist/core/lite-scanner.d.ts +1 -1
- package/ccw/dist/core/lite-scanner.d.ts.map +1 -1
- package/ccw/dist/core/lite-scanner.js +130 -127
- package/ccw/dist/core/lite-scanner.js.map +1 -1
- package/ccw/dist/core/routes/auth-routes.d.ts +12 -0
- package/ccw/dist/core/routes/auth-routes.d.ts.map +1 -0
- package/ccw/dist/core/routes/auth-routes.js +80 -0
- package/ccw/dist/core/routes/auth-routes.js.map +1 -0
- package/ccw/dist/core/routes/ccw-routes.d.ts +1 -14
- package/ccw/dist/core/routes/ccw-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/ccw-routes.js +9 -4
- package/ccw/dist/core/routes/ccw-routes.js.map +1 -1
- package/ccw/dist/core/routes/claude-routes.d.ts +1 -14
- package/ccw/dist/core/routes/claude-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/claude-routes.js +98 -39
- package/ccw/dist/core/routes/claude-routes.js.map +1 -1
- package/ccw/dist/core/routes/cli-routes.d.ts +14 -12
- package/ccw/dist/core/routes/cli-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/cli-routes.js +122 -43
- package/ccw/dist/core/routes/cli-routes.js.map +1 -1
- package/ccw/dist/core/routes/cli-settings-routes.d.ts +11 -0
- package/ccw/dist/core/routes/cli-settings-routes.d.ts.map +1 -0
- package/ccw/dist/core/routes/cli-settings-routes.js +204 -0
- package/ccw/dist/core/routes/cli-settings-routes.js.map +1 -0
- package/ccw/dist/core/routes/codexlens/config-handlers.d.ts +6 -0
- package/ccw/dist/core/routes/codexlens/config-handlers.d.ts.map +1 -0
- package/ccw/dist/core/routes/codexlens/config-handlers.js +1195 -0
- package/ccw/dist/core/routes/codexlens/config-handlers.js.map +1 -0
- package/ccw/dist/core/routes/codexlens/index-handlers.d.ts +10 -0
- package/ccw/dist/core/routes/codexlens/index-handlers.d.ts.map +1 -0
- package/ccw/dist/core/routes/codexlens/index-handlers.js +322 -0
- package/ccw/dist/core/routes/codexlens/index-handlers.js.map +1 -0
- package/ccw/dist/core/routes/codexlens/semantic-handlers.d.ts +6 -0
- package/ccw/dist/core/routes/codexlens/semantic-handlers.d.ts.map +1 -0
- package/ccw/dist/core/routes/codexlens/semantic-handlers.js +865 -0
- package/ccw/dist/core/routes/codexlens/semantic-handlers.js.map +1 -0
- package/ccw/dist/core/routes/codexlens/utils.d.ts +23 -0
- package/ccw/dist/core/routes/codexlens/utils.d.ts.map +1 -0
- package/ccw/dist/core/routes/codexlens/utils.js +85 -0
- package/ccw/dist/core/routes/codexlens/utils.js.map +1 -0
- package/ccw/dist/core/routes/codexlens/watcher-handlers.d.ts +13 -0
- package/ccw/dist/core/routes/codexlens/watcher-handlers.d.ts.map +1 -0
- package/ccw/dist/core/routes/codexlens/watcher-handlers.js +235 -0
- package/ccw/dist/core/routes/codexlens/watcher-handlers.js.map +1 -0
- package/ccw/dist/core/routes/codexlens-routes.d.ts +2 -11
- package/ccw/dist/core/routes/codexlens-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/codexlens-routes.js +10 -981
- package/ccw/dist/core/routes/codexlens-routes.js.map +1 -1
- package/ccw/dist/core/routes/discovery-routes.d.ts +1 -35
- package/ccw/dist/core/routes/discovery-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/discovery-routes.js +25 -0
- package/ccw/dist/core/routes/discovery-routes.js.map +1 -1
- package/ccw/dist/core/routes/files-routes.d.ts +1 -14
- package/ccw/dist/core/routes/files-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/files-routes.js +57 -14
- package/ccw/dist/core/routes/files-routes.js.map +1 -1
- package/ccw/dist/core/routes/graph-routes.d.ts +1 -14
- package/ccw/dist/core/routes/graph-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/graph-routes.js +36 -37
- package/ccw/dist/core/routes/graph-routes.js.map +1 -1
- package/ccw/dist/core/routes/help-routes.d.ts +1 -14
- package/ccw/dist/core/routes/help-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/help-routes.js +5 -0
- package/ccw/dist/core/routes/help-routes.js.map +1 -1
- package/ccw/dist/core/routes/hooks-routes.d.ts +4 -14
- package/ccw/dist/core/routes/hooks-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/hooks-routes.js +43 -21
- package/ccw/dist/core/routes/hooks-routes.js.map +1 -1
- package/ccw/dist/core/routes/issue-routes.d.ts +1 -34
- package/ccw/dist/core/routes/issue-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/issue-routes.js +24 -0
- package/ccw/dist/core/routes/issue-routes.js.map +1 -1
- package/ccw/dist/core/routes/litellm-api-routes.d.ts +1 -14
- package/ccw/dist/core/routes/litellm-api-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/litellm-api-routes.js +505 -48
- package/ccw/dist/core/routes/litellm-api-routes.js.map +1 -1
- package/ccw/dist/core/routes/litellm-routes.d.ts +1 -14
- package/ccw/dist/core/routes/litellm-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/litellm-routes.js +28 -11
- package/ccw/dist/core/routes/litellm-routes.js.map +1 -1
- package/ccw/dist/core/routes/mcp-routes.d.ts +1 -14
- package/ccw/dist/core/routes/mcp-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/mcp-routes.js +99 -30
- package/ccw/dist/core/routes/mcp-routes.js.map +1 -1
- package/ccw/dist/core/routes/mcp-templates-db.d.ts.map +1 -1
- package/ccw/dist/core/routes/mcp-templates-db.js +30 -31
- package/ccw/dist/core/routes/mcp-templates-db.js.map +1 -1
- package/ccw/dist/core/routes/memory-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/memory-routes.js +74 -24
- package/ccw/dist/core/routes/memory-routes.js.map +1 -1
- package/ccw/dist/core/routes/nav-status-routes.d.ts +3 -0
- package/ccw/dist/core/routes/nav-status-routes.d.ts.map +1 -0
- package/ccw/dist/core/routes/nav-status-routes.js +217 -0
- package/ccw/dist/core/routes/nav-status-routes.js.map +1 -0
- package/ccw/dist/core/routes/rules-routes.d.ts +1 -14
- package/ccw/dist/core/routes/rules-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/rules-routes.js +481 -58
- package/ccw/dist/core/routes/rules-routes.js.map +1 -1
- package/ccw/dist/core/routes/session-routes.d.ts +1 -14
- package/ccw/dist/core/routes/session-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/session-routes.js +15 -3
- package/ccw/dist/core/routes/session-routes.js.map +1 -1
- package/ccw/dist/core/routes/skills-routes.d.ts +1 -14
- package/ccw/dist/core/routes/skills-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/skills-routes.js +394 -112
- package/ccw/dist/core/routes/skills-routes.js.map +1 -1
- package/ccw/dist/core/routes/status-routes.d.ts +1 -14
- package/ccw/dist/core/routes/status-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/status-routes.js +4 -0
- package/ccw/dist/core/routes/status-routes.js.map +1 -1
- package/ccw/dist/core/routes/system-routes.d.ts +4 -10
- package/ccw/dist/core/routes/system-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/system-routes.js +6 -4
- package/ccw/dist/core/routes/system-routes.js.map +1 -1
- package/ccw/dist/core/routes/types.d.ts +19 -0
- package/ccw/dist/core/routes/types.d.ts.map +1 -0
- package/ccw/dist/core/routes/types.js +2 -0
- package/ccw/dist/core/routes/types.js.map +1 -0
- package/ccw/dist/core/server.d.ts.map +1 -1
- package/ccw/dist/core/server.js +201 -29
- package/ccw/dist/core/server.js.map +1 -1
- package/ccw/dist/core/services/api-key-tester.d.ts +31 -0
- package/ccw/dist/core/services/api-key-tester.d.ts.map +1 -0
- package/ccw/dist/core/services/api-key-tester.js +106 -0
- package/ccw/dist/core/services/api-key-tester.js.map +1 -0
- package/ccw/dist/core/services/health-check-service.d.ts +82 -0
- package/ccw/dist/core/services/health-check-service.d.ts.map +1 -0
- package/ccw/dist/core/services/health-check-service.js +271 -0
- package/ccw/dist/core/services/health-check-service.js.map +1 -0
- package/ccw/dist/core/websocket.d.ts +9 -7
- package/ccw/dist/core/websocket.d.ts.map +1 -1
- package/ccw/dist/core/websocket.js +9 -4
- package/ccw/dist/core/websocket.js.map +1 -1
- package/ccw/dist/tools/claude-cli-tools.d.ts +152 -28
- package/ccw/dist/tools/claude-cli-tools.d.ts.map +1 -1
- package/ccw/dist/tools/claude-cli-tools.js +490 -100
- package/ccw/dist/tools/claude-cli-tools.js.map +1 -1
- package/ccw/dist/tools/cli-config-manager.d.ts +24 -8
- package/ccw/dist/tools/cli-config-manager.d.ts.map +1 -1
- package/ccw/dist/tools/cli-config-manager.js +76 -156
- package/ccw/dist/tools/cli-config-manager.js.map +1 -1
- package/ccw/dist/tools/cli-executor-core.d.ts +85 -0
- package/ccw/dist/tools/cli-executor-core.d.ts.map +1 -0
- package/ccw/dist/tools/cli-executor-core.js +1310 -0
- package/ccw/dist/tools/cli-executor-core.js.map +1 -0
- package/ccw/dist/tools/cli-executor-state.d.ts +241 -0
- package/ccw/dist/tools/cli-executor-state.d.ts.map +1 -0
- package/ccw/dist/tools/cli-executor-state.js +392 -0
- package/ccw/dist/tools/cli-executor-state.js.map +1 -0
- package/ccw/dist/tools/cli-executor-utils.d.ts +36 -0
- package/ccw/dist/tools/cli-executor-utils.d.ts.map +1 -0
- package/ccw/dist/tools/cli-executor-utils.js +298 -0
- package/ccw/dist/tools/cli-executor-utils.js.map +1 -0
- package/ccw/dist/tools/cli-executor.d.ts +3 -377
- package/ccw/dist/tools/cli-executor.d.ts.map +1 -1
- package/ccw/dist/tools/cli-executor.js +3 -1884
- package/ccw/dist/tools/cli-executor.js.map +1 -1
- package/ccw/dist/tools/cli-history-store.d.ts +2 -0
- package/ccw/dist/tools/cli-history-store.d.ts.map +1 -1
- package/ccw/dist/tools/cli-history-store.js.map +1 -1
- package/ccw/dist/tools/cli-output-converter.d.ts +192 -0
- package/ccw/dist/tools/cli-output-converter.d.ts.map +1 -0
- package/ccw/dist/tools/cli-output-converter.js +1047 -0
- package/ccw/dist/tools/cli-output-converter.js.map +1 -0
- package/ccw/dist/tools/cli-prompt-builder.d.ts +113 -0
- package/ccw/dist/tools/cli-prompt-builder.d.ts.map +1 -0
- package/ccw/dist/tools/cli-prompt-builder.js +363 -0
- package/ccw/dist/tools/cli-prompt-builder.js.map +1 -0
- package/ccw/dist/tools/codex-lens.d.ts +15 -1
- package/ccw/dist/tools/codex-lens.d.ts.map +1 -1
- package/ccw/dist/tools/codex-lens.js +289 -55
- package/ccw/dist/tools/codex-lens.js.map +1 -1
- package/ccw/dist/tools/detect-changed-modules.d.ts.map +1 -1
- package/ccw/dist/tools/detect-changed-modules.js +22 -4
- package/ccw/dist/tools/detect-changed-modules.js.map +1 -1
- package/ccw/dist/tools/index.d.ts.map +1 -1
- package/ccw/dist/tools/index.js +2 -0
- package/ccw/dist/tools/index.js.map +1 -1
- package/ccw/dist/tools/litellm-client.d.ts.map +1 -1
- package/ccw/dist/tools/litellm-client.js +10 -4
- package/ccw/dist/tools/litellm-client.js.map +1 -1
- package/ccw/dist/tools/litellm-executor.d.ts +2 -4
- package/ccw/dist/tools/litellm-executor.d.ts.map +1 -1
- package/ccw/dist/tools/litellm-executor.js +39 -8
- package/ccw/dist/tools/litellm-executor.js.map +1 -1
- package/ccw/dist/tools/native-session-discovery.d.ts +2 -0
- package/ccw/dist/tools/native-session-discovery.d.ts.map +1 -1
- package/ccw/dist/tools/native-session-discovery.js +197 -1
- package/ccw/dist/tools/native-session-discovery.js.map +1 -1
- package/ccw/dist/tools/session-manager.d.ts.map +1 -1
- package/ccw/dist/tools/session-manager.js +79 -0
- package/ccw/dist/tools/session-manager.js.map +1 -1
- package/ccw/dist/tools/skill-context-loader.d.ts +15 -0
- package/ccw/dist/tools/skill-context-loader.d.ts.map +1 -0
- package/ccw/dist/tools/skill-context-loader.js +198 -0
- package/ccw/dist/tools/skill-context-loader.js.map +1 -0
- package/ccw/dist/tools/smart-search.d.ts +8 -3
- package/ccw/dist/tools/smart-search.d.ts.map +1 -1
- package/ccw/dist/tools/smart-search.js +378 -75
- package/ccw/dist/tools/smart-search.js.map +1 -1
- package/ccw/dist/types/cli-settings.d.ts +86 -0
- package/ccw/dist/types/cli-settings.d.ts.map +1 -0
- package/ccw/dist/types/cli-settings.js +54 -0
- package/ccw/dist/types/cli-settings.js.map +1 -0
- package/ccw/dist/types/litellm-api-config.d.ts +40 -1
- package/ccw/dist/types/litellm-api-config.d.ts.map +1 -1
- package/ccw/dist/utils/exec-constants.d.ts +25 -0
- package/ccw/dist/utils/exec-constants.d.ts.map +1 -0
- package/ccw/dist/utils/exec-constants.js +25 -0
- package/ccw/dist/utils/exec-constants.js.map +1 -0
- package/ccw/dist/utils/path-resolver.d.ts +1 -0
- package/ccw/dist/utils/path-resolver.d.ts.map +1 -1
- package/ccw/dist/utils/path-resolver.js +48 -3
- package/ccw/dist/utils/path-resolver.js.map +1 -1
- package/ccw/dist/utils/path-validator.d.ts.map +1 -1
- package/ccw/dist/utils/path-validator.js +25 -6
- package/ccw/dist/utils/path-validator.js.map +1 -1
- package/ccw/dist/utils/python-utils.d.ts.map +1 -1
- package/ccw/dist/utils/python-utils.js +27 -7
- package/ccw/dist/utils/python-utils.js.map +1 -1
- package/ccw/dist/utils/shell-escape.d.ts +8 -0
- package/ccw/dist/utils/shell-escape.d.ts.map +1 -0
- package/ccw/dist/utils/shell-escape.js +24 -0
- package/ccw/dist/utils/shell-escape.js.map +1 -0
- package/ccw/dist/utils/uv-manager.d.ts +167 -0
- package/ccw/dist/utils/uv-manager.d.ts.map +1 -0
- package/ccw/dist/utils/uv-manager.js +644 -0
- package/ccw/dist/utils/uv-manager.js.map +1 -0
- package/ccw/src/cli.ts +4 -1
- package/ccw/src/commands/cli.ts +132 -34
- package/ccw/src/commands/issue.ts +605 -91
- package/ccw/src/commands/serve.ts +15 -5
- package/ccw/src/commands/stop.ts +32 -5
- package/ccw/src/commands/tool.ts +17 -2
- package/ccw/src/commands/view.ts +13 -3
- package/ccw/src/config/cli-settings-manager.ts +460 -0
- package/ccw/src/config/litellm-api-config-manager.ts +392 -57
- package/ccw/src/core/auth/csrf-manager.ts +104 -0
- package/ccw/src/core/auth/csrf-middleware.ts +159 -0
- package/ccw/src/core/auth/middleware.ts +94 -0
- package/ccw/src/core/auth/token-manager.ts +219 -0
- package/ccw/src/core/cache-manager.ts +64 -52
- package/ccw/src/core/claude-freshness.ts +26 -6
- package/ccw/src/core/core-memory-store.ts +2 -1
- package/ccw/src/core/cors.ts +10 -0
- package/ccw/src/core/dashboard-generator-patch.ts +47 -48
- package/ccw/src/core/dashboard-generator.ts +797 -744
- package/ccw/src/core/data-aggregator.ts +667 -667
- package/ccw/src/core/lite-scanner.ts +156 -140
- package/ccw/src/core/routes/auth-routes.ts +98 -0
- package/ccw/src/core/routes/ccw-routes.ts +10 -20
- package/ccw/src/core/routes/claude-routes.ts +101 -51
- package/ccw/src/core/routes/cli-routes.ts +152 -55
- package/ccw/src/core/routes/cli-settings-routes.ts +232 -0
- package/ccw/src/core/routes/codexlens/README.md +37 -0
- package/ccw/src/core/routes/codexlens/config-handlers.ts +1269 -0
- package/ccw/src/core/routes/codexlens/index-handlers.ts +354 -0
- package/ccw/src/core/routes/codexlens/semantic-handlers.ts +931 -0
- package/ccw/src/core/routes/codexlens/utils.ts +96 -0
- package/ccw/src/core/routes/codexlens/watcher-handlers.ts +265 -0
- package/ccw/src/core/routes/codexlens-routes.ts +11 -1044
- package/ccw/src/core/routes/discovery-routes.ts +1 -12
- package/ccw/src/core/routes/files-routes.ts +112 -40
- package/ccw/src/core/routes/graph-routes.ts +39 -46
- package/ccw/src/core/routes/help-routes.ts +2 -12
- package/ccw/src/core/routes/hooks-routes.ts +83 -44
- package/ccw/src/core/routes/issue-routes.ts +1 -12
- package/ccw/src/core/routes/litellm-api-routes.ts +566 -60
- package/ccw/src/core/routes/litellm-routes.ts +35 -27
- package/ccw/src/core/routes/mcp-routes.ts +157 -60
- package/ccw/src/core/routes/mcp-routes.ts.backup +549 -550
- package/ccw/src/core/routes/mcp-templates-db.ts +267 -268
- package/ccw/src/core/routes/memory-routes.ts +76 -22
- package/ccw/src/core/routes/nav-status-routes.ts +231 -0
- package/ccw/src/core/routes/rules-routes.ts +600 -81
- package/ccw/src/core/routes/session-routes.ts +28 -22
- package/ccw/src/core/routes/skills-routes.ts +452 -132
- package/ccw/src/core/routes/status-routes.ts +1 -12
- package/ccw/src/core/routes/system-routes.ts +15 -22
- package/ccw/src/core/routes/types.ts +25 -0
- package/ccw/src/core/server.ts +651 -468
- package/ccw/src/core/services/api-key-tester.ts +137 -0
- package/ccw/src/core/services/health-check-service.ts +340 -0
- package/ccw/src/core/websocket.ts +20 -12
- package/ccw/src/templates/dashboard-css/01-base.css +109 -0
- package/ccw/src/templates/dashboard-css/10-cli-status.css +202 -0
- package/ccw/src/templates/dashboard-css/21-cli-toolmgmt.css +308 -0
- package/ccw/src/templates/dashboard-css/30-core-memory.css +20 -0
- package/ccw/src/templates/dashboard-css/31-api-settings.css +751 -14
- package/ccw/src/templates/dashboard-css/33-cli-stream-viewer.css +230 -2
- package/ccw/src/templates/dashboard-js/api.js +5 -0
- package/ccw/src/templates/dashboard-js/components/cli-status.js +279 -107
- package/ccw/src/templates/dashboard-js/components/cli-stream-viewer.js +262 -20
- package/ccw/src/templates/dashboard-js/components/hook-manager.js +105 -5
- package/ccw/src/templates/dashboard-js/components/mcp-manager.js +317 -0
- package/ccw/src/templates/dashboard-js/components/navigation.js +45 -0
- package/ccw/src/templates/dashboard-js/components/notifications.js +128 -0
- package/ccw/src/templates/dashboard-js/i18n.js +4438 -3983
- package/ccw/src/templates/dashboard-js/main.js +71 -0
- package/ccw/src/templates/dashboard-js/services.js +289 -0
- package/ccw/src/templates/dashboard-js/views/api-settings.js +5613 -3361
- package/ccw/src/templates/dashboard-js/views/claude-manager.js +1 -7
- package/ccw/src/templates/dashboard-js/views/cli-manager.js +581 -87
- package/ccw/src/templates/dashboard-js/views/codexlens-manager.js +6091 -1965
- package/ccw/src/templates/dashboard-js/views/core-memory.js +129 -20
- package/ccw/src/templates/dashboard-js/views/hook-manager.js +17 -3
- package/ccw/src/templates/dashboard-js/views/mcp-manager.js +63 -0
- package/ccw/src/templates/dashboard-js/views/project-overview.js +182 -37
- package/ccw/src/templates/dashboard-js/views/rules-manager.js +26 -3
- package/ccw/src/templates/dashboard-js/views/skills-manager.js +2 -42
- package/ccw/src/templates/dashboard.html +6 -0
- package/ccw/src/tools/README.md +29 -0
- package/ccw/src/tools/claude-cli-tools.ts +640 -125
- package/ccw/src/tools/cli-config-manager.ts +102 -172
- package/ccw/src/tools/cli-executor-core.ts +1533 -0
- package/ccw/src/tools/cli-executor-state.ts +560 -0
- package/ccw/src/tools/cli-executor-utils.ts +349 -0
- package/ccw/src/tools/cli-executor.ts +3 -2309
- package/ccw/src/tools/cli-history-store.ts +2 -0
- package/ccw/src/tools/cli-output-converter.ts +1237 -0
- package/ccw/src/tools/cli-prompt-builder.ts +487 -0
- package/ccw/src/tools/codex-lens.ts +324 -59
- package/ccw/src/tools/detect-changed-modules.ts +24 -6
- package/ccw/src/tools/index.ts +2 -0
- package/ccw/src/tools/litellm-client.ts +10 -4
- package/ccw/src/tools/litellm-executor.ts +146 -114
- package/ccw/src/tools/native-session-discovery.ts +209 -1
- package/ccw/src/tools/session-manager.ts +88 -0
- package/ccw/src/tools/skill-context-loader.ts +213 -0
- package/ccw/src/tools/smart-search.ts +427 -76
- package/ccw/src/types/cli-settings.ts +137 -0
- package/ccw/src/types/litellm-api-config.ts +55 -1
- package/ccw/src/utils/exec-constants.ts +24 -0
- package/ccw/src/utils/path-resolver.ts +49 -3
- package/ccw/src/utils/path-validator.ts +28 -6
- package/ccw/src/utils/python-utils.ts +140 -121
- package/ccw/src/utils/shell-escape.ts +30 -0
- package/ccw/src/utils/uv-manager.ts +796 -0
- package/ccw-litellm/src/ccw_litellm/__pycache__/__init__.cpython-310.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/__pycache__/__init__.cpython-312.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/clients/__pycache__/__init__.cpython-310.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/clients/__pycache__/__init__.cpython-312.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/clients/__pycache__/litellm_embedder.cpython-310.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/clients/__pycache__/litellm_embedder.cpython-312.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/clients/__pycache__/litellm_embedder.cpython-313.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/clients/__pycache__/litellm_llm.cpython-310.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/clients/__pycache__/litellm_llm.cpython-312.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/clients/__pycache__/litellm_llm.cpython-313.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/clients/litellm_embedder.py +270 -251
- package/ccw-litellm/src/ccw_litellm/clients/litellm_llm.py +33 -0
- package/ccw-litellm/src/ccw_litellm/config/__pycache__/__init__.cpython-310.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/config/__pycache__/__init__.cpython-312.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/config/__pycache__/loader.cpython-310.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/config/__pycache__/loader.cpython-312.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/config/__pycache__/loader.cpython-313.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/config/__pycache__/models.cpython-310.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/config/__pycache__/models.cpython-312.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/config/__pycache__/models.cpython-313.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/config/loader.py +343 -316
- package/ccw-litellm/src/ccw_litellm/config/models.py +162 -130
- package/ccw-litellm/src/ccw_litellm/interfaces/__pycache__/__init__.cpython-310.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/interfaces/__pycache__/__init__.cpython-312.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/interfaces/__pycache__/embedder.cpython-310.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/interfaces/__pycache__/embedder.cpython-312.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/interfaces/__pycache__/llm.cpython-310.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/interfaces/__pycache__/llm.cpython-312.pyc +0 -0
- package/codex-lens/pyproject.toml +43 -0
- package/codex-lens/src/codexlens/__pycache__/__init__.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/__pycache__/__init__.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/__pycache__/__main__.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/__pycache__/__main__.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/__pycache__/config.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/__pycache__/config.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/__pycache__/config.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/__pycache__/entities.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/__pycache__/entities.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/__pycache__/entities.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/__pycache__/env_config.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/__pycache__/env_config.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/__pycache__/env_config.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/__pycache__/errors.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/__pycache__/errors.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/cli/__pycache__/__init__.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/cli/__pycache__/__init__.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/cli/__pycache__/commands.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/cli/__pycache__/commands.cpython-312.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-310.pyc +0 -0
- package/codex-lens/src/codexlens/cli/__pycache__/embedding_manager.cpython-312.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-310.pyc +0 -0
- package/codex-lens/src/codexlens/cli/__pycache__/model_manager.cpython-312.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-310.pyc +0 -0
- package/codex-lens/src/codexlens/cli/__pycache__/output.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/cli/commands.py +4416 -2295
- package/codex-lens/src/codexlens/cli/embedding_manager.py +767 -14
- package/codex-lens/src/codexlens/cli/model_manager.py +676 -0
- package/codex-lens/src/codexlens/config.py +321 -12
- package/codex-lens/src/codexlens/entities.py +4 -1
- package/codex-lens/src/codexlens/env_config.py +298 -0
- package/codex-lens/src/codexlens/indexing/__init__.py +23 -1
- package/codex-lens/src/codexlens/indexing/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/indexing/__pycache__/embedding.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/embedding.py +582 -0
- package/codex-lens/src/codexlens/indexing/symbol_extractor.py +62 -28
- package/codex-lens/src/codexlens/parsers/__pycache__/__init__.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/parsers/__pycache__/__init__.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/parsers/__pycache__/factory.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/parsers/__pycache__/factory.cpython-312.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-310.pyc +0 -0
- package/codex-lens/src/codexlens/parsers/__pycache__/tokenizer.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/parsers/__pycache__/treesitter_parser.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/parsers/__pycache__/treesitter_parser.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/parsers/__pycache__/treesitter_parser.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/parsers/factory.py +139 -10
- package/codex-lens/src/codexlens/parsers/treesitter_parser.py +487 -13
- package/codex-lens/src/codexlens/search/__pycache__/__init__.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/search/__pycache__/__init__.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/search/__pycache__/binary_searcher.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/search/__pycache__/chain_search.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/search/__pycache__/chain_search.cpython-312.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__/graph_expander.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/search/__pycache__/hybrid_search.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/search/__pycache__/hybrid_search.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/search/__pycache__/hybrid_search.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/search/__pycache__/ranking.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/search/__pycache__/ranking.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/search/__pycache__/ranking.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/search/binary_searcher.py +277 -0
- package/codex-lens/src/codexlens/search/chain_search.py +1642 -8
- package/codex-lens/src/codexlens/search/enrichment.py +21 -0
- package/codex-lens/src/codexlens/search/graph_expander.py +264 -0
- package/codex-lens/src/codexlens/search/hybrid_search.py +772 -37
- package/codex-lens/src/codexlens/search/ranking.py +347 -8
- package/codex-lens/src/codexlens/semantic/SPLADE_IMPLEMENTATION.md +225 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/__init__.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/__init__.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/ann_index.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/ann_index.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/ann_index.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/base.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/base.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/chunker.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/chunker.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/embedder.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/embedder.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/factory.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/factory.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/factory.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/gpu_support.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/gpu_support.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/gpu_support.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/litellm_embedder.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/litellm_embedder.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/litellm_embedder.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/reranker.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/splade_encoder.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/splade_encoder.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/splade_encoder.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/vector_store.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/vector_store.cpython-312.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 +654 -0
- package/codex-lens/src/codexlens/semantic/factory.py +63 -3
- package/codex-lens/src/codexlens/semantic/gpu_support.py +19 -2
- package/codex-lens/src/codexlens/semantic/litellm_embedder.py +144 -144
- package/codex-lens/src/codexlens/semantic/reranker/__init__.py +25 -0
- package/codex-lens/src/codexlens/semantic/reranker/__pycache__/__init__.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/reranker/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/reranker/__pycache__/api_reranker.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/reranker/__pycache__/api_reranker.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/reranker/__pycache__/base.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/reranker/__pycache__/base.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/reranker/__pycache__/factory.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/reranker/__pycache__/factory.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/reranker/__pycache__/fastembed_reranker.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/reranker/__pycache__/fastembed_reranker.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/reranker/__pycache__/legacy.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/reranker/__pycache__/legacy.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/reranker/__pycache__/litellm_reranker.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/reranker/__pycache__/onnx_reranker.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/reranker/__pycache__/onnx_reranker.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/reranker/api_reranker.py +403 -0
- package/codex-lens/src/codexlens/semantic/reranker/base.py +46 -0
- package/codex-lens/src/codexlens/semantic/reranker/factory.py +159 -0
- package/codex-lens/src/codexlens/semantic/reranker/fastembed_reranker.py +257 -0
- package/codex-lens/src/codexlens/semantic/reranker/legacy.py +91 -0
- package/codex-lens/src/codexlens/semantic/reranker/litellm_reranker.py +214 -0
- package/codex-lens/src/codexlens/semantic/reranker/onnx_reranker.py +268 -0
- package/codex-lens/src/codexlens/semantic/splade_encoder.py +567 -0
- package/codex-lens/src/codexlens/semantic/vector_store.py +472 -352
- package/codex-lens/src/codexlens/storage/__init__.py +3 -0
- package/codex-lens/src/codexlens/storage/__pycache__/__init__.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/__init__.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/dir_index.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/dir_index.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/dir_index.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/global_index.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/global_index.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/index_tree.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/index_tree.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/index_tree.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/merkle_tree.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/path_mapper.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/path_mapper.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/registry.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/registry.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/splade_index.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/splade_index.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/splade_index.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/sqlite_store.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/sqlite_store.cpython-312.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-310.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/sqlite_utils.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/vector_meta_store.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/vector_meta_store.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/vector_meta_store.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/dir_index.py +310 -12
- package/codex-lens/src/codexlens/storage/index_tree.py +194 -23
- package/codex-lens/src/codexlens/storage/merkle_tree.py +136 -0
- package/codex-lens/src/codexlens/storage/migrations/__pycache__/__init__.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/storage/migrations/__pycache__/__init__.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_006_enhance_relationships.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_007_add_graph_neighbors.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_007_add_graph_neighbors.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_007_add_graph_neighbors.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_008_add_merkle_hashes.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_009_add_splade.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_010_add_multi_vector_chunks.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/migrations/migration_006_enhance_relationships.py +37 -0
- package/codex-lens/src/codexlens/storage/migrations/migration_007_add_graph_neighbors.py +47 -0
- package/codex-lens/src/codexlens/storage/migrations/migration_008_add_merkle_hashes.py +81 -0
- package/codex-lens/src/codexlens/storage/migrations/migration_009_add_splade.py +103 -0
- package/codex-lens/src/codexlens/storage/migrations/migration_010_add_multi_vector_chunks.py +162 -0
- package/codex-lens/src/codexlens/storage/splade_index.py +578 -0
- package/codex-lens/src/codexlens/storage/sqlite_store.py +508 -184
- package/codex-lens/src/codexlens/storage/vector_meta_store.py +415 -0
- package/codex-lens/src/codexlens/watcher/__init__.py +17 -0
- package/codex-lens/src/codexlens/watcher/__pycache__/__init__.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/watcher/__pycache__/__init__.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/watcher/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/watcher/__pycache__/events.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/watcher/__pycache__/events.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/watcher/__pycache__/events.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/watcher/__pycache__/file_watcher.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/watcher/__pycache__/file_watcher.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/watcher/__pycache__/file_watcher.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/watcher/__pycache__/incremental_indexer.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/watcher/__pycache__/incremental_indexer.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/watcher/__pycache__/incremental_indexer.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/watcher/__pycache__/manager.cpython-310.pyc +0 -0
- package/codex-lens/src/codexlens/watcher/__pycache__/manager.cpython-312.pyc +0 -0
- package/codex-lens/src/codexlens/watcher/__pycache__/manager.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/watcher/events.py +82 -0
- package/codex-lens/src/codexlens/watcher/file_watcher.py +347 -0
- package/codex-lens/src/codexlens/watcher/incremental_indexer.py +369 -0
- package/codex-lens/src/codexlens/watcher/manager.py +255 -0
- package/package.json +4 -1
- package/.claude/commands/workflow/docs/analyze.md +0 -1467
- package/.claude/commands/workflow/docs/copyright.md +0 -1265
- package/.claude/skills/command-guide/SKILL.md +0 -388
- package/.claude/skills/command-guide/UPDATE-GUIDELINE.md +0 -592
- package/.claude/skills/command-guide/guides/cli-tools-guide.md +0 -410
- package/.claude/skills/command-guide/guides/examples.md +0 -537
- package/.claude/skills/command-guide/guides/getting-started.md +0 -242
- package/.claude/skills/command-guide/guides/implementation-details.md +0 -1010
- package/.claude/skills/command-guide/guides/index-structure.md +0 -326
- package/.claude/skills/command-guide/guides/troubleshooting.md +0 -92
- package/.claude/skills/command-guide/guides/ui-design-workflow-guide.md +0 -316
- package/.claude/skills/command-guide/guides/workflow-patterns.md +0 -662
- package/.claude/skills/command-guide/reference/agents/action-planning-agent.md +0 -855
- package/.claude/skills/command-guide/reference/agents/cli-execution-agent.md +0 -267
- package/.claude/skills/command-guide/reference/agents/cli-explore-agent.md +0 -182
- package/.claude/skills/command-guide/reference/agents/cli-lite-planning-agent.md +0 -446
- package/.claude/skills/command-guide/reference/agents/cli-planning-agent.md +0 -558
- package/.claude/skills/command-guide/reference/agents/code-developer.md +0 -311
- package/.claude/skills/command-guide/reference/agents/conceptual-planning-agent.md +0 -308
- package/.claude/skills/command-guide/reference/agents/context-search-agent.md +0 -581
- package/.claude/skills/command-guide/reference/agents/doc-generator.md +0 -330
- package/.claude/skills/command-guide/reference/agents/memory-bridge.md +0 -94
- package/.claude/skills/command-guide/reference/agents/test-context-search-agent.md +0 -400
- package/.claude/skills/command-guide/reference/agents/test-fix-agent.md +0 -344
- package/.claude/skills/command-guide/reference/agents/ui-design-agent.md +0 -593
- package/.claude/skills/command-guide/reference/agents/universal-executor.md +0 -131
- package/.claude/skills/command-guide/reference/commands/cli/cli-init.md +0 -440
- package/.claude/skills/command-guide/reference/commands/enhance-prompt.md +0 -93
- package/.claude/skills/command-guide/reference/commands/memory/code-map-memory.md +0 -687
- package/.claude/skills/command-guide/reference/commands/memory/docs-full-cli.md +0 -471
- package/.claude/skills/command-guide/reference/commands/memory/docs-related-cli.md +0 -386
- package/.claude/skills/command-guide/reference/commands/memory/docs.md +0 -616
- package/.claude/skills/command-guide/reference/commands/memory/load-skill-memory.md +0 -182
- package/.claude/skills/command-guide/reference/commands/memory/load.md +0 -240
- package/.claude/skills/command-guide/reference/commands/memory/skill-memory.md +0 -525
- package/.claude/skills/command-guide/reference/commands/memory/style-skill-memory.md +0 -396
- package/.claude/skills/command-guide/reference/commands/memory/tech-research.md +0 -314
- package/.claude/skills/command-guide/reference/commands/memory/update-full.md +0 -332
- package/.claude/skills/command-guide/reference/commands/memory/update-related.md +0 -332
- package/.claude/skills/command-guide/reference/commands/memory/workflow-skill-memory.md +0 -517
- package/.claude/skills/command-guide/reference/commands/task/breakdown.md +0 -204
- package/.claude/skills/command-guide/reference/commands/task/create.md +0 -152
- package/.claude/skills/command-guide/reference/commands/task/execute.md +0 -270
- package/.claude/skills/command-guide/reference/commands/task/replan.md +0 -437
- package/.claude/skills/command-guide/reference/commands/version.md +0 -254
- package/.claude/skills/command-guide/reference/commands/workflow/action-plan-verify.md +0 -447
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/api-designer.md +0 -585
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/artifacts.md +0 -452
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/auto-parallel.md +0 -443
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/data-architect.md +0 -220
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/product-manager.md +0 -200
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/product-owner.md +0 -200
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/scrum-master.md +0 -200
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/subject-matter-expert.md +0 -200
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/synthesis.md +0 -398
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/system-architect.md +0 -387
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/ui-designer.md +0 -221
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/ux-expert.md +0 -221
- package/.claude/skills/command-guide/reference/commands/workflow/execute.md +0 -465
- package/.claude/skills/command-guide/reference/commands/workflow/init.md +0 -164
- package/.claude/skills/command-guide/reference/commands/workflow/lite-execute.md +0 -748
- package/.claude/skills/command-guide/reference/commands/workflow/lite-fix.md +0 -664
- package/.claude/skills/command-guide/reference/commands/workflow/lite-plan.md +0 -645
- package/.claude/skills/command-guide/reference/commands/workflow/plan.md +0 -551
- package/.claude/skills/command-guide/reference/commands/workflow/replan.md +0 -515
- package/.claude/skills/command-guide/reference/commands/workflow/review-fix.md +0 -606
- package/.claude/skills/command-guide/reference/commands/workflow/review-module-cycle.md +0 -765
- package/.claude/skills/command-guide/reference/commands/workflow/review-session-cycle.md +0 -776
- package/.claude/skills/command-guide/reference/commands/workflow/review.md +0 -298
- package/.claude/skills/command-guide/reference/commands/workflow/session/complete.md +0 -547
- package/.claude/skills/command-guide/reference/commands/workflow/session/list.md +0 -114
- package/.claude/skills/command-guide/reference/commands/workflow/session/resume.md +0 -77
- package/.claude/skills/command-guide/reference/commands/workflow/session/start.md +0 -257
- package/.claude/skills/command-guide/reference/commands/workflow/tdd-plan.md +0 -460
- package/.claude/skills/command-guide/reference/commands/workflow/tdd-verify.md +0 -400
- package/.claude/skills/command-guide/reference/commands/workflow/test-cycle-execute.md +0 -498
- package/.claude/skills/command-guide/reference/commands/workflow/test-fix-gen.md +0 -699
- package/.claude/skills/command-guide/reference/commands/workflow/test-gen.md +0 -529
- package/.claude/skills/command-guide/reference/commands/workflow/tools/conflict-resolution.md +0 -766
- package/.claude/skills/command-guide/reference/commands/workflow/tools/context-gather.md +0 -433
- package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-agent.md +0 -487
- package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-tdd.md +0 -518
- package/.claude/skills/command-guide/reference/commands/workflow/tools/tdd-coverage-analysis.md +0 -309
- package/.claude/skills/command-guide/reference/commands/workflow/tools/test-concept-enhanced.md +0 -163
- package/.claude/skills/command-guide/reference/commands/workflow/tools/test-context-gather.md +0 -232
- package/.claude/skills/command-guide/reference/commands/workflow/tools/test-task-generate.md +0 -254
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/animation-extract.md +0 -1150
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/codify-style.md +0 -652
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/design-sync.md +0 -454
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/explore-auto.md +0 -678
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/generate.md +0 -504
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/imitate-auto.md +0 -745
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/import-from-code.md +0 -537
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/layout-extract.md +0 -788
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/reference-page-generator.md +0 -356
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/style-extract.md +0 -773
- package/.claude/skills/command-guide/scripts/analyze_commands.py +0 -502
- package/.claude/skills/command-guide/scripts/update-index.sh +0 -130
- package/.claude/skills/command-guide/templates/issue-bug.md +0 -104
- package/.claude/skills/command-guide/templates/issue-diagnosis.md +0 -275
- package/.claude/skills/command-guide/templates/issue-feature.md +0 -97
- package/.claude/skills/command-guide/templates/issue-question.md +0 -141
|
@@ -1,22 +1,66 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
1
|
/**
|
|
3
2
|
* Skills Routes Module
|
|
4
3
|
* Handles all Skills-related API endpoints
|
|
5
4
|
*/
|
|
6
|
-
import type { IncomingMessage, ServerResponse } from 'http';
|
|
7
5
|
import { readFileSync, existsSync, readdirSync, statSync, unlinkSync, promises as fsPromises } from 'fs';
|
|
8
6
|
import { join } from 'path';
|
|
9
7
|
import { homedir } from 'os';
|
|
10
8
|
import { executeCliTool } from '../../tools/cli-executor.js';
|
|
9
|
+
import { SmartContentFormatter } from '../../tools/cli-output-converter.js';
|
|
10
|
+
import { validatePath as validateAllowedPath } from '../../utils/path-validator.js';
|
|
11
|
+
import type { RouteContext } from './types.js';
|
|
12
|
+
|
|
13
|
+
type SkillLocation = 'project' | 'user';
|
|
14
|
+
|
|
15
|
+
interface ParsedSkillFrontmatter {
|
|
16
|
+
name: string;
|
|
17
|
+
description: string;
|
|
18
|
+
version: string | null;
|
|
19
|
+
allowedTools: string[];
|
|
20
|
+
content: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface SkillSummary {
|
|
24
|
+
name: string;
|
|
25
|
+
folderName: string;
|
|
26
|
+
description: string;
|
|
27
|
+
version: string | null;
|
|
28
|
+
allowedTools: string[];
|
|
29
|
+
location: SkillLocation;
|
|
30
|
+
path: string;
|
|
31
|
+
supportingFiles: string[];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface SkillsConfig {
|
|
35
|
+
projectSkills: SkillSummary[];
|
|
36
|
+
userSkills: SkillSummary[];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
interface SkillInfo {
|
|
40
|
+
name: string;
|
|
41
|
+
description: string;
|
|
42
|
+
version: string | null;
|
|
43
|
+
allowedTools: string[];
|
|
44
|
+
supportingFiles: string[];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
type SkillFolderValidation =
|
|
48
|
+
| { valid: true; errors: string[]; skillInfo: SkillInfo }
|
|
49
|
+
| { valid: false; errors: string[]; skillInfo: null };
|
|
50
|
+
|
|
51
|
+
type GenerationType = 'description' | 'template';
|
|
11
52
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
53
|
+
interface GenerationParams {
|
|
54
|
+
generationType: GenerationType;
|
|
55
|
+
description?: string;
|
|
56
|
+
skillName: string;
|
|
57
|
+
location: SkillLocation;
|
|
58
|
+
projectPath: string;
|
|
59
|
+
broadcastToClients?: (data: unknown) => void;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
63
|
+
return typeof value === 'object' && value !== null;
|
|
20
64
|
}
|
|
21
65
|
|
|
22
66
|
// ========== Skills Helper Functions ==========
|
|
@@ -26,8 +70,8 @@ export interface RouteContext {
|
|
|
26
70
|
* @param {string} content - Skill file content
|
|
27
71
|
* @returns {Object} Parsed frontmatter and content
|
|
28
72
|
*/
|
|
29
|
-
function parseSkillFrontmatter(content) {
|
|
30
|
-
const result = {
|
|
73
|
+
function parseSkillFrontmatter(content: string): ParsedSkillFrontmatter {
|
|
74
|
+
const result: ParsedSkillFrontmatter = {
|
|
31
75
|
name: '',
|
|
32
76
|
description: '',
|
|
33
77
|
version: null,
|
|
@@ -58,7 +102,11 @@ function parseSkillFrontmatter(content) {
|
|
|
58
102
|
result.version = value.replace(/^["']|["']$/g, '');
|
|
59
103
|
} else if (key === 'allowed-tools' || key === 'allowedtools') {
|
|
60
104
|
// Parse as comma-separated or YAML array
|
|
61
|
-
result.allowedTools = value
|
|
105
|
+
result.allowedTools = value
|
|
106
|
+
.replace(/^\[|\]$/g, '')
|
|
107
|
+
.split(',')
|
|
108
|
+
.map((tool) => tool.trim())
|
|
109
|
+
.filter(Boolean);
|
|
62
110
|
}
|
|
63
111
|
}
|
|
64
112
|
}
|
|
@@ -75,8 +123,8 @@ function parseSkillFrontmatter(content) {
|
|
|
75
123
|
* @param {string} skillDir
|
|
76
124
|
* @returns {string[]}
|
|
77
125
|
*/
|
|
78
|
-
function getSupportingFiles(skillDir) {
|
|
79
|
-
const files = [];
|
|
126
|
+
function getSupportingFiles(skillDir: string): string[] {
|
|
127
|
+
const files: string[] = [];
|
|
80
128
|
try {
|
|
81
129
|
const entries = readdirSync(skillDir, { withFileTypes: true });
|
|
82
130
|
for (const entry of entries) {
|
|
@@ -99,8 +147,8 @@ function getSupportingFiles(skillDir) {
|
|
|
99
147
|
* @param {string} projectPath
|
|
100
148
|
* @returns {Object}
|
|
101
149
|
*/
|
|
102
|
-
function getSkillsConfig(projectPath) {
|
|
103
|
-
const result = {
|
|
150
|
+
function getSkillsConfig(projectPath: string): SkillsConfig {
|
|
151
|
+
const result: SkillsConfig = {
|
|
104
152
|
projectSkills: [],
|
|
105
153
|
userSkills: []
|
|
106
154
|
};
|
|
@@ -179,17 +227,44 @@ function getSkillsConfig(projectPath) {
|
|
|
179
227
|
* @param {string} projectPath
|
|
180
228
|
* @returns {Object}
|
|
181
229
|
*/
|
|
182
|
-
function getSkillDetail(skillName, location, projectPath) {
|
|
230
|
+
async function getSkillDetail(skillName: string, location: SkillLocation, projectPath: string, initialPath: string) {
|
|
183
231
|
try {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
232
|
+
if (skillName.includes('/') || skillName.includes('\\')) {
|
|
233
|
+
return { error: 'Access denied', status: 403 };
|
|
234
|
+
}
|
|
235
|
+
if (skillName.includes('..')) {
|
|
236
|
+
return { error: 'Invalid skill name', status: 400 };
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
let baseDir;
|
|
240
|
+
if (location === 'project') {
|
|
241
|
+
try {
|
|
242
|
+
const validatedProjectPath = await validateAllowedPath(projectPath, { mustExist: true, allowedDirectories: [initialPath] });
|
|
243
|
+
baseDir = join(validatedProjectPath, '.claude', 'skills');
|
|
244
|
+
} catch (err) {
|
|
245
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
246
|
+
const status = message.includes('Access denied') ? 403 : 400;
|
|
247
|
+
console.error(`[Skills] Project path validation failed: ${message}`);
|
|
248
|
+
return { error: status === 403 ? 'Access denied' : 'Invalid path', status };
|
|
249
|
+
}
|
|
250
|
+
} else {
|
|
251
|
+
baseDir = join(homedir(), '.claude', 'skills');
|
|
252
|
+
}
|
|
187
253
|
|
|
188
254
|
const skillDir = join(baseDir, skillName);
|
|
189
|
-
const
|
|
255
|
+
const skillMdCandidate = join(skillDir, 'SKILL.md');
|
|
190
256
|
|
|
191
|
-
|
|
192
|
-
|
|
257
|
+
let skillMdPath;
|
|
258
|
+
try {
|
|
259
|
+
skillMdPath = await validateAllowedPath(skillMdCandidate, { mustExist: true, allowedDirectories: [skillDir] });
|
|
260
|
+
} catch (err) {
|
|
261
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
262
|
+
if (message.includes('File not found')) {
|
|
263
|
+
return { error: 'Skill not found', status: 404 };
|
|
264
|
+
}
|
|
265
|
+
const status = message.includes('Access denied') ? 403 : 400;
|
|
266
|
+
console.error(`[Skills] Path validation failed: ${message}`);
|
|
267
|
+
return { error: status === 403 ? 'Access denied' : 'Invalid path', status };
|
|
193
268
|
}
|
|
194
269
|
|
|
195
270
|
const content = readFileSync(skillMdPath, 'utf8');
|
|
@@ -210,7 +285,7 @@ function getSkillDetail(skillName, location, projectPath) {
|
|
|
210
285
|
}
|
|
211
286
|
};
|
|
212
287
|
} catch (error) {
|
|
213
|
-
return { error: (error as Error).message };
|
|
288
|
+
return { error: (error as Error).message, status: 500 };
|
|
214
289
|
}
|
|
215
290
|
}
|
|
216
291
|
|
|
@@ -221,38 +296,50 @@ function getSkillDetail(skillName, location, projectPath) {
|
|
|
221
296
|
* @param {string} projectPath
|
|
222
297
|
* @returns {Object}
|
|
223
298
|
*/
|
|
224
|
-
function deleteSkill(skillName, location, projectPath) {
|
|
299
|
+
async function deleteSkill(skillName: string, location: SkillLocation, projectPath: string, initialPath: string) {
|
|
225
300
|
try {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
301
|
+
if (skillName.includes('/') || skillName.includes('\\')) {
|
|
302
|
+
return { error: 'Access denied', status: 403 };
|
|
303
|
+
}
|
|
304
|
+
if (skillName.includes('..')) {
|
|
305
|
+
return { error: 'Invalid skill name', status: 400 };
|
|
306
|
+
}
|
|
231
307
|
|
|
232
|
-
|
|
233
|
-
|
|
308
|
+
let baseDir;
|
|
309
|
+
if (location === 'project') {
|
|
310
|
+
try {
|
|
311
|
+
const validatedProjectPath = await validateAllowedPath(projectPath, { mustExist: true, allowedDirectories: [initialPath] });
|
|
312
|
+
baseDir = join(validatedProjectPath, '.claude', 'skills');
|
|
313
|
+
} catch (err) {
|
|
314
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
315
|
+
const status = message.includes('Access denied') ? 403 : 400;
|
|
316
|
+
console.error(`[Skills] Project path validation failed: ${message}`);
|
|
317
|
+
return { error: status === 403 ? 'Access denied' : 'Invalid path', status };
|
|
318
|
+
}
|
|
319
|
+
} else {
|
|
320
|
+
baseDir = join(homedir(), '.claude', 'skills');
|
|
234
321
|
}
|
|
235
322
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
}
|
|
246
|
-
});
|
|
247
|
-
fsPromises.rmdir(dirPath);
|
|
323
|
+
const skillDirCandidate = join(baseDir, skillName);
|
|
324
|
+
|
|
325
|
+
let skillDir;
|
|
326
|
+
try {
|
|
327
|
+
skillDir = await validateAllowedPath(skillDirCandidate, { mustExist: true, allowedDirectories: [baseDir] });
|
|
328
|
+
} catch (err) {
|
|
329
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
330
|
+
if (message.includes('File not found')) {
|
|
331
|
+
return { error: 'Skill not found', status: 404 };
|
|
248
332
|
}
|
|
249
|
-
|
|
333
|
+
const status = message.includes('Access denied') ? 403 : 400;
|
|
334
|
+
console.error(`[Skills] Path validation failed: ${message}`);
|
|
335
|
+
return { error: status === 403 ? 'Access denied' : 'Invalid path', status };
|
|
336
|
+
}
|
|
250
337
|
|
|
251
|
-
|
|
338
|
+
await fsPromises.rm(skillDir, { recursive: true, force: true });
|
|
252
339
|
|
|
253
340
|
return { success: true, skillName, location };
|
|
254
341
|
} catch (error) {
|
|
255
|
-
return { error: (error as Error).message };
|
|
342
|
+
return { error: (error as Error).message, status: 500 };
|
|
256
343
|
}
|
|
257
344
|
}
|
|
258
345
|
|
|
@@ -261,8 +348,8 @@ function deleteSkill(skillName, location, projectPath) {
|
|
|
261
348
|
* @param {string} folderPath - Path to skill folder
|
|
262
349
|
* @returns {Object} Validation result with skill info
|
|
263
350
|
*/
|
|
264
|
-
function validateSkillFolder(folderPath) {
|
|
265
|
-
const errors = [];
|
|
351
|
+
function validateSkillFolder(folderPath: string): SkillFolderValidation {
|
|
352
|
+
const errors: string[] = [];
|
|
266
353
|
|
|
267
354
|
// Check if folder exists
|
|
268
355
|
if (!existsSync(folderPath)) {
|
|
@@ -327,7 +414,7 @@ function validateSkillFolder(folderPath) {
|
|
|
327
414
|
* @param {string} source - Source directory path
|
|
328
415
|
* @param {string} target - Target directory path
|
|
329
416
|
*/
|
|
330
|
-
async function copyDirectoryRecursive(source, target) {
|
|
417
|
+
async function copyDirectoryRecursive(source: string, target: string): Promise<void> {
|
|
331
418
|
await fsPromises.mkdir(target, { recursive: true });
|
|
332
419
|
|
|
333
420
|
const entries = await fsPromises.readdir(source, { withFileTypes: true });
|
|
@@ -352,7 +439,7 @@ async function copyDirectoryRecursive(source, target) {
|
|
|
352
439
|
* @param {string} customName - Optional custom name for skill
|
|
353
440
|
* @returns {Object}
|
|
354
441
|
*/
|
|
355
|
-
async function importSkill(sourcePath, location, projectPath, customName) {
|
|
442
|
+
async function importSkill(sourcePath: string, location: SkillLocation, projectPath: string, customName?: string) {
|
|
356
443
|
try {
|
|
357
444
|
// Validate source folder
|
|
358
445
|
const validation = validateSkillFolder(sourcePath);
|
|
@@ -371,6 +458,9 @@ async function importSkill(sourcePath, location, projectPath, customName) {
|
|
|
371
458
|
|
|
372
459
|
// Determine target folder name
|
|
373
460
|
const skillName = customName || validation.skillInfo.name;
|
|
461
|
+
if (skillName.includes('/') || skillName.includes('\\') || skillName.includes('..')) {
|
|
462
|
+
return { error: 'Invalid skill name', status: 400 };
|
|
463
|
+
}
|
|
374
464
|
const targetPath = join(baseDir, skillName);
|
|
375
465
|
|
|
376
466
|
// Check if already exists
|
|
@@ -400,9 +490,13 @@ async function importSkill(sourcePath, location, projectPath, customName) {
|
|
|
400
490
|
* @param {string} params.skillName - Name for the skill
|
|
401
491
|
* @param {string} params.location - 'project' or 'user'
|
|
402
492
|
* @param {string} params.projectPath - Project root path
|
|
493
|
+
* @param {Function} params.broadcastToClients - WebSocket broadcast function
|
|
403
494
|
* @returns {Object}
|
|
404
495
|
*/
|
|
405
|
-
async function generateSkillViaCLI({ generationType, description, skillName, location, projectPath }) {
|
|
496
|
+
async function generateSkillViaCLI({ generationType, description, skillName, location, projectPath, broadcastToClients }: GenerationParams) {
|
|
497
|
+
// Generate unique execution ID for tracking
|
|
498
|
+
const executionId = `skill-gen-${skillName}-${Date.now()}`;
|
|
499
|
+
|
|
406
500
|
try {
|
|
407
501
|
// Validate inputs
|
|
408
502
|
if (!skillName) {
|
|
@@ -429,50 +523,107 @@ async function generateSkillViaCLI({ generationType, description, skillName, loc
|
|
|
429
523
|
await fsPromises.mkdir(baseDir, { recursive: true });
|
|
430
524
|
}
|
|
431
525
|
|
|
432
|
-
// Build
|
|
526
|
+
// Build structured skill parameters for /skill-generator
|
|
433
527
|
const targetLocationDisplay = location === 'project'
|
|
434
528
|
? '.claude/skills/'
|
|
435
529
|
: '~/.claude/skills/';
|
|
436
530
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
531
|
+
// Structured fields from user input
|
|
532
|
+
const skillParams = {
|
|
533
|
+
skill_name: skillName,
|
|
534
|
+
description: description || 'Generate a basic skill template',
|
|
535
|
+
target_location: targetLocationDisplay,
|
|
536
|
+
target_path: targetPath,
|
|
537
|
+
location_type: location // 'project' | 'user'
|
|
538
|
+
};
|
|
539
|
+
|
|
540
|
+
// Prompt that invokes /skill-generator skill with structured parameters
|
|
541
|
+
const prompt = `/skill-generator
|
|
542
|
+
|
|
543
|
+
## Skill Parameters (Structured Input)
|
|
544
|
+
|
|
545
|
+
\`\`\`json
|
|
546
|
+
${JSON.stringify(skillParams, null, 2)}
|
|
547
|
+
\`\`\`
|
|
548
|
+
|
|
549
|
+
## User Request
|
|
550
|
+
|
|
551
|
+
Create a new Claude Code skill with the following specifications:
|
|
552
|
+
|
|
553
|
+
- **Skill Name**: ${skillName}
|
|
554
|
+
- **Description**: ${description || 'Generate a basic skill template'}
|
|
555
|
+
- **Target Location**: ${targetLocationDisplay}${skillName}
|
|
556
|
+
- **Location Type**: ${location === 'project' ? 'Project-level (.claude/skills/)' : 'User-level (~/.claude/skills/)'}
|
|
557
|
+
|
|
558
|
+
## Instructions
|
|
559
|
+
|
|
560
|
+
1. Use the skill-generator to create a complete skill structure
|
|
561
|
+
2. Generate SKILL.md with proper frontmatter (name, description, version, allowed-tools)
|
|
562
|
+
3. Create necessary supporting files (phases, specs, templates as needed)
|
|
563
|
+
4. Follow Claude Code skill design patterns and best practices
|
|
564
|
+
5. Output all files to: ${targetPath}`;
|
|
565
|
+
|
|
566
|
+
// Broadcast CLI_EXECUTION_STARTED event
|
|
567
|
+
if (broadcastToClients) {
|
|
568
|
+
broadcastToClients({
|
|
569
|
+
type: 'CLI_EXECUTION_STARTED',
|
|
570
|
+
payload: {
|
|
571
|
+
executionId,
|
|
572
|
+
tool: 'claude',
|
|
573
|
+
mode: 'write',
|
|
574
|
+
category: 'internal',
|
|
575
|
+
context: 'skill-generation',
|
|
576
|
+
skillName
|
|
577
|
+
}
|
|
578
|
+
});
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
// Create onOutput callback for real-time streaming
|
|
582
|
+
const onOutput = broadcastToClients
|
|
583
|
+
? (unit: import('../../tools/cli-output-converter.js').CliOutputUnit) => {
|
|
584
|
+
// CliOutputUnit handler: use SmartContentFormatter for intelligent formatting (never returns null)
|
|
585
|
+
const content = SmartContentFormatter.format(unit.content, unit.type);
|
|
586
|
+
broadcastToClients({
|
|
587
|
+
type: 'CLI_OUTPUT',
|
|
588
|
+
payload: {
|
|
589
|
+
executionId,
|
|
590
|
+
chunkType: unit.type,
|
|
591
|
+
data: content
|
|
592
|
+
}
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
: undefined;
|
|
460
596
|
|
|
461
597
|
// Execute CLI tool (Claude) with write mode
|
|
598
|
+
const startTime = Date.now();
|
|
462
599
|
const result = await executeCliTool({
|
|
463
600
|
tool: 'claude',
|
|
464
601
|
prompt,
|
|
465
602
|
mode: 'write',
|
|
466
603
|
cd: baseDir,
|
|
467
604
|
timeout: 600000, // 10 minutes
|
|
468
|
-
category: 'internal'
|
|
469
|
-
|
|
605
|
+
category: 'internal',
|
|
606
|
+
id: executionId
|
|
607
|
+
}, onOutput);
|
|
608
|
+
|
|
609
|
+
// Broadcast CLI_EXECUTION_COMPLETED event
|
|
610
|
+
if (broadcastToClients) {
|
|
611
|
+
broadcastToClients({
|
|
612
|
+
type: 'CLI_EXECUTION_COMPLETED',
|
|
613
|
+
payload: {
|
|
614
|
+
executionId,
|
|
615
|
+
success: result.success,
|
|
616
|
+
status: result.execution?.status || (result.success ? 'success' : 'error'),
|
|
617
|
+
duration_ms: Date.now() - startTime
|
|
618
|
+
}
|
|
619
|
+
});
|
|
620
|
+
}
|
|
470
621
|
|
|
471
622
|
// Check if execution was successful
|
|
472
623
|
if (!result.success) {
|
|
473
624
|
return {
|
|
474
625
|
error: `CLI generation failed: ${result.stderr || 'Unknown error'}`,
|
|
475
|
-
stdout: result.stdout,
|
|
626
|
+
stdout: result.parsedOutput || result.stdout,
|
|
476
627
|
stderr: result.stderr
|
|
477
628
|
};
|
|
478
629
|
}
|
|
@@ -482,7 +633,7 @@ REQUIREMENTS:
|
|
|
482
633
|
if (!validation.valid) {
|
|
483
634
|
return {
|
|
484
635
|
error: `Generated skill is invalid: ${validation.errors.join(', ')}`,
|
|
485
|
-
stdout: result.stdout,
|
|
636
|
+
stdout: result.parsedOutput || result.stdout,
|
|
486
637
|
stderr: result.stderr
|
|
487
638
|
};
|
|
488
639
|
}
|
|
@@ -492,7 +643,7 @@ REQUIREMENTS:
|
|
|
492
643
|
skillName: validation.skillInfo.name,
|
|
493
644
|
location,
|
|
494
645
|
path: targetPath,
|
|
495
|
-
stdout: result.stdout,
|
|
646
|
+
stdout: result.parsedOutput || result.stdout,
|
|
496
647
|
stderr: result.stderr
|
|
497
648
|
};
|
|
498
649
|
} catch (error) {
|
|
@@ -507,14 +658,24 @@ REQUIREMENTS:
|
|
|
507
658
|
* @returns true if route was handled, false otherwise
|
|
508
659
|
*/
|
|
509
660
|
export async function handleSkillsRoutes(ctx: RouteContext): Promise<boolean> {
|
|
510
|
-
const { pathname, url, req, res, initialPath, handlePostRequest } = ctx;
|
|
661
|
+
const { pathname, url, req, res, initialPath, handlePostRequest, broadcastToClients } = ctx;
|
|
511
662
|
|
|
512
663
|
// API: Get all skills (project and user)
|
|
513
664
|
if (pathname === '/api/skills') {
|
|
514
665
|
const projectPathParam = url.searchParams.get('path') || initialPath;
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
666
|
+
|
|
667
|
+
try {
|
|
668
|
+
const validatedProjectPath = await validateAllowedPath(projectPathParam, { mustExist: true, allowedDirectories: [initialPath] });
|
|
669
|
+
const skillsData = getSkillsConfig(validatedProjectPath);
|
|
670
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
671
|
+
res.end(JSON.stringify(skillsData));
|
|
672
|
+
} catch (err) {
|
|
673
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
674
|
+
const status = message.includes('Access denied') ? 403 : 400;
|
|
675
|
+
console.error(`[Skills] Project path validation failed: ${message}`);
|
|
676
|
+
res.writeHead(status, { 'Content-Type': 'application/json' });
|
|
677
|
+
res.end(JSON.stringify({ error: status === 403 ? 'Access denied' : 'Invalid path', projectSkills: [], userSkills: [] }));
|
|
678
|
+
}
|
|
518
679
|
return true;
|
|
519
680
|
}
|
|
520
681
|
|
|
@@ -526,18 +687,46 @@ export async function handleSkillsRoutes(ctx: RouteContext): Promise<boolean> {
|
|
|
526
687
|
const location = url.searchParams.get('location') || 'project';
|
|
527
688
|
const projectPathParam = url.searchParams.get('path') || initialPath;
|
|
528
689
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
690
|
+
if (skillName.includes('/') || skillName.includes('\\') || skillName.includes('..')) {
|
|
691
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
692
|
+
res.end(JSON.stringify({ error: 'Invalid skill name' }));
|
|
693
|
+
return true;
|
|
694
|
+
}
|
|
532
695
|
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
696
|
+
let baseDir: string;
|
|
697
|
+
if (location === 'project') {
|
|
698
|
+
try {
|
|
699
|
+
const validatedProjectPath = await validateAllowedPath(projectPathParam, { mustExist: true, allowedDirectories: [initialPath] });
|
|
700
|
+
baseDir = join(validatedProjectPath, '.claude', 'skills');
|
|
701
|
+
} catch (err) {
|
|
702
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
703
|
+
const status = message.includes('Access denied') ? 403 : 400;
|
|
704
|
+
console.error(`[Skills] Project path validation failed: ${message}`);
|
|
705
|
+
res.writeHead(status, { 'Content-Type': 'application/json' });
|
|
706
|
+
res.end(JSON.stringify({ error: status === 403 ? 'Access denied' : 'Invalid path' }));
|
|
707
|
+
return true;
|
|
708
|
+
}
|
|
709
|
+
} else {
|
|
710
|
+
baseDir = join(homedir(), '.claude', 'skills');
|
|
711
|
+
}
|
|
536
712
|
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
713
|
+
const skillRoot = join(baseDir, skillName);
|
|
714
|
+
const requestedDir = subPath ? join(skillRoot, subPath) : skillRoot;
|
|
715
|
+
|
|
716
|
+
let dirPath: string;
|
|
717
|
+
try {
|
|
718
|
+
dirPath = await validateAllowedPath(requestedDir, { mustExist: true, allowedDirectories: [skillRoot] });
|
|
719
|
+
} catch (err) {
|
|
720
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
721
|
+
if (message.includes('File not found')) {
|
|
722
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
723
|
+
res.end(JSON.stringify({ error: 'Directory not found' }));
|
|
724
|
+
return true;
|
|
725
|
+
}
|
|
726
|
+
const status = message.includes('Access denied') ? 403 : 400;
|
|
727
|
+
console.error(`[Skills] Path validation failed: ${message}`);
|
|
728
|
+
res.writeHead(status, { 'Content-Type': 'application/json' });
|
|
729
|
+
res.end(JSON.stringify({ error: status === 403 ? 'Access denied' : 'Invalid path' }));
|
|
541
730
|
return true;
|
|
542
731
|
}
|
|
543
732
|
|
|
@@ -585,16 +774,46 @@ export async function handleSkillsRoutes(ctx: RouteContext): Promise<boolean> {
|
|
|
585
774
|
return true;
|
|
586
775
|
}
|
|
587
776
|
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
777
|
+
if (skillName.includes('/') || skillName.includes('\\') || skillName.includes('..')) {
|
|
778
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
779
|
+
res.end(JSON.stringify({ error: 'Invalid skill name' }));
|
|
780
|
+
return true;
|
|
781
|
+
}
|
|
591
782
|
|
|
592
|
-
|
|
783
|
+
let baseDir: string;
|
|
784
|
+
if (location === 'project') {
|
|
785
|
+
try {
|
|
786
|
+
const validatedProjectPath = await validateAllowedPath(projectPathParam, { mustExist: true, allowedDirectories: [initialPath] });
|
|
787
|
+
baseDir = join(validatedProjectPath, '.claude', 'skills');
|
|
788
|
+
} catch (err) {
|
|
789
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
790
|
+
const status = message.includes('Access denied') ? 403 : 400;
|
|
791
|
+
console.error(`[Skills] Project path validation failed: ${message}`);
|
|
792
|
+
res.writeHead(status, { 'Content-Type': 'application/json' });
|
|
793
|
+
res.end(JSON.stringify({ error: status === 403 ? 'Access denied' : 'Invalid path' }));
|
|
794
|
+
return true;
|
|
795
|
+
}
|
|
796
|
+
} else {
|
|
797
|
+
baseDir = join(homedir(), '.claude', 'skills');
|
|
798
|
+
}
|
|
593
799
|
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
800
|
+
const skillRoot = join(baseDir, skillName);
|
|
801
|
+
const requestedFile = join(skillRoot, fileName);
|
|
802
|
+
|
|
803
|
+
let filePath: string;
|
|
804
|
+
try {
|
|
805
|
+
filePath = await validateAllowedPath(requestedFile, { mustExist: true, allowedDirectories: [skillRoot] });
|
|
806
|
+
} catch (err) {
|
|
807
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
808
|
+
if (message.includes('File not found')) {
|
|
809
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
810
|
+
res.end(JSON.stringify({ error: 'File not found' }));
|
|
811
|
+
return true;
|
|
812
|
+
}
|
|
813
|
+
const status = message.includes('Access denied') ? 403 : 400;
|
|
814
|
+
console.error(`[Skills] Path validation failed: ${message}`);
|
|
815
|
+
res.writeHead(status, { 'Content-Type': 'application/json' });
|
|
816
|
+
res.end(JSON.stringify({ error: status === 403 ? 'Access denied' : 'Invalid path' }));
|
|
598
817
|
return true;
|
|
599
818
|
}
|
|
600
819
|
|
|
@@ -621,25 +840,54 @@ export async function handleSkillsRoutes(ctx: RouteContext): Promise<boolean> {
|
|
|
621
840
|
const skillName = decodeURIComponent(pathParts[3]);
|
|
622
841
|
|
|
623
842
|
handlePostRequest(req, res, async (body) => {
|
|
624
|
-
|
|
843
|
+
if (!isRecord(body)) {
|
|
844
|
+
return { error: 'Invalid request body', status: 400 };
|
|
845
|
+
}
|
|
625
846
|
|
|
626
|
-
|
|
847
|
+
const fileName = body.fileName;
|
|
848
|
+
const content = body.content;
|
|
849
|
+
const location: SkillLocation = body.location === 'project' ? 'project' : 'user';
|
|
850
|
+
const projectPathParam = typeof body.projectPath === 'string' ? body.projectPath : undefined;
|
|
851
|
+
|
|
852
|
+
if (typeof fileName !== 'string' || !fileName) {
|
|
627
853
|
return { error: 'fileName is required' };
|
|
628
854
|
}
|
|
629
855
|
|
|
630
|
-
if (content
|
|
856
|
+
if (typeof content !== 'string') {
|
|
631
857
|
return { error: 'content is required' };
|
|
632
858
|
}
|
|
633
859
|
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
860
|
+
if (skillName.includes('/') || skillName.includes('\\') || skillName.includes('..')) {
|
|
861
|
+
return { error: 'Invalid skill name', status: 400 };
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
let baseDir: string;
|
|
865
|
+
if (location === 'project') {
|
|
866
|
+
try {
|
|
867
|
+
const projectRoot = projectPathParam || initialPath;
|
|
868
|
+
const validatedProjectPath = await validateAllowedPath(projectRoot, { mustExist: true, allowedDirectories: [initialPath] });
|
|
869
|
+
baseDir = join(validatedProjectPath, '.claude', 'skills');
|
|
870
|
+
} catch (err) {
|
|
871
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
872
|
+
const status = message.includes('Access denied') ? 403 : 400;
|
|
873
|
+
console.error(`[Skills] Project path validation failed: ${message}`);
|
|
874
|
+
return { error: status === 403 ? 'Access denied' : 'Invalid path', status };
|
|
875
|
+
}
|
|
876
|
+
} else {
|
|
877
|
+
baseDir = join(homedir(), '.claude', 'skills');
|
|
878
|
+
}
|
|
637
879
|
|
|
638
|
-
const
|
|
880
|
+
const skillRoot = join(baseDir, skillName);
|
|
881
|
+
const requestedFile = join(skillRoot, fileName);
|
|
639
882
|
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
883
|
+
let filePath: string;
|
|
884
|
+
try {
|
|
885
|
+
filePath = await validateAllowedPath(requestedFile, { allowedDirectories: [skillRoot] });
|
|
886
|
+
} catch (err) {
|
|
887
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
888
|
+
const status = message.includes('Access denied') ? 403 : 400;
|
|
889
|
+
console.error(`[Skills] Path validation failed: ${message}`);
|
|
890
|
+
return { error: status === 403 ? 'Access denied' : 'Invalid path', status };
|
|
643
891
|
}
|
|
644
892
|
|
|
645
893
|
try {
|
|
@@ -656,25 +904,43 @@ export async function handleSkillsRoutes(ctx: RouteContext): Promise<boolean> {
|
|
|
656
904
|
if (pathname.startsWith('/api/skills/') && req.method === 'GET' &&
|
|
657
905
|
!pathname.endsWith('/skills/') && !pathname.endsWith('/dir') && !pathname.endsWith('/file')) {
|
|
658
906
|
const skillName = decodeURIComponent(pathname.replace('/api/skills/', ''));
|
|
659
|
-
const
|
|
907
|
+
const locationParam = url.searchParams.get('location');
|
|
908
|
+
const location: SkillLocation = locationParam === 'user' ? 'user' : 'project';
|
|
660
909
|
const projectPathParam = url.searchParams.get('path') || initialPath;
|
|
661
|
-
const skillDetail = getSkillDetail(skillName, location, projectPathParam);
|
|
910
|
+
const skillDetail = await getSkillDetail(skillName, location, projectPathParam, initialPath);
|
|
662
911
|
if (skillDetail.error) {
|
|
663
|
-
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
664
|
-
res.end(JSON.stringify(skillDetail));
|
|
665
|
-
|
|
666
|
-
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
667
|
-
res.end(JSON.stringify(skillDetail));
|
|
912
|
+
res.writeHead(skillDetail.status || 404, { 'Content-Type': 'application/json' });
|
|
913
|
+
res.end(JSON.stringify({ error: skillDetail.error }));
|
|
914
|
+
return true;
|
|
668
915
|
}
|
|
916
|
+
|
|
917
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
918
|
+
res.end(JSON.stringify(skillDetail));
|
|
669
919
|
return true;
|
|
670
920
|
}
|
|
671
921
|
|
|
672
922
|
// API: Delete skill
|
|
673
923
|
if (pathname.startsWith('/api/skills/') && req.method === 'DELETE') {
|
|
674
924
|
const skillName = decodeURIComponent(pathname.replace('/api/skills/', ''));
|
|
925
|
+
if (skillName.includes('/') || skillName.includes('\\')) {
|
|
926
|
+
res.writeHead(403, { 'Content-Type': 'application/json' });
|
|
927
|
+
res.end(JSON.stringify({ error: 'Access denied' }));
|
|
928
|
+
return true;
|
|
929
|
+
}
|
|
930
|
+
if (skillName.includes('..')) {
|
|
931
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
932
|
+
res.end(JSON.stringify({ error: 'Invalid skill name' }));
|
|
933
|
+
return true;
|
|
934
|
+
}
|
|
675
935
|
handlePostRequest(req, res, async (body) => {
|
|
676
|
-
|
|
677
|
-
|
|
936
|
+
if (!isRecord(body)) {
|
|
937
|
+
return { error: 'Invalid request body', status: 400 };
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
const location: SkillLocation = body.location === 'project' ? 'project' : 'user';
|
|
941
|
+
const projectPathParam = typeof body.projectPath === 'string' ? body.projectPath : undefined;
|
|
942
|
+
|
|
943
|
+
return deleteSkill(skillName, location, projectPathParam || initialPath, initialPath);
|
|
678
944
|
});
|
|
679
945
|
return true;
|
|
680
946
|
}
|
|
@@ -682,11 +948,24 @@ export async function handleSkillsRoutes(ctx: RouteContext): Promise<boolean> {
|
|
|
682
948
|
// API: Validate skill import
|
|
683
949
|
if (pathname === '/api/skills/validate-import' && req.method === 'POST') {
|
|
684
950
|
handlePostRequest(req, res, async (body) => {
|
|
685
|
-
|
|
686
|
-
if (!sourcePath) {
|
|
951
|
+
if (!isRecord(body)) {
|
|
687
952
|
return { valid: false, errors: ['Source path is required'], skillInfo: null };
|
|
688
953
|
}
|
|
689
|
-
|
|
954
|
+
|
|
955
|
+
const sourcePath = body.sourcePath;
|
|
956
|
+
if (typeof sourcePath !== 'string' || !sourcePath.trim()) {
|
|
957
|
+
return { valid: false, errors: ['Source path is required'], skillInfo: null };
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
try {
|
|
961
|
+
const validatedSourcePath = await validateAllowedPath(sourcePath, { mustExist: true });
|
|
962
|
+
return validateSkillFolder(validatedSourcePath);
|
|
963
|
+
} catch (err) {
|
|
964
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
965
|
+
const status = message.includes('Access denied') ? 403 : 400;
|
|
966
|
+
console.error(`[Skills] Path validation failed: ${message}`);
|
|
967
|
+
return { error: status === 403 ? 'Access denied' : 'Invalid path', status };
|
|
968
|
+
}
|
|
690
969
|
});
|
|
691
970
|
return true;
|
|
692
971
|
}
|
|
@@ -694,37 +973,78 @@ export async function handleSkillsRoutes(ctx: RouteContext): Promise<boolean> {
|
|
|
694
973
|
// API: Create/Import skill
|
|
695
974
|
if (pathname === '/api/skills/create' && req.method === 'POST') {
|
|
696
975
|
handlePostRequest(req, res, async (body) => {
|
|
697
|
-
|
|
976
|
+
if (!isRecord(body)) {
|
|
977
|
+
return { error: 'Invalid request body', status: 400 };
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
const mode = body.mode;
|
|
981
|
+
const locationValue = body.location;
|
|
982
|
+
const sourcePath = typeof body.sourcePath === 'string' ? body.sourcePath : undefined;
|
|
983
|
+
const skillName = typeof body.skillName === 'string' ? body.skillName : undefined;
|
|
984
|
+
const description = typeof body.description === 'string' ? body.description : undefined;
|
|
985
|
+
const generationType = typeof body.generationType === 'string' ? body.generationType : undefined;
|
|
986
|
+
const projectPathParam = typeof body.projectPath === 'string' ? body.projectPath : undefined;
|
|
698
987
|
|
|
699
|
-
if (!mode) {
|
|
988
|
+
if (typeof mode !== 'string' || !mode) {
|
|
700
989
|
return { error: 'Mode is required (import or cli-generate)' };
|
|
701
990
|
}
|
|
702
991
|
|
|
703
|
-
if (
|
|
992
|
+
if (locationValue !== 'project' && locationValue !== 'user') {
|
|
704
993
|
return { error: 'Location is required (project or user)' };
|
|
705
994
|
}
|
|
706
995
|
|
|
996
|
+
const location: SkillLocation = locationValue;
|
|
707
997
|
const projectPath = projectPathParam || initialPath;
|
|
708
998
|
|
|
999
|
+
let validatedProjectPath = projectPath;
|
|
1000
|
+
if (location === 'project') {
|
|
1001
|
+
try {
|
|
1002
|
+
validatedProjectPath = await validateAllowedPath(projectPath, { mustExist: true, allowedDirectories: [initialPath] });
|
|
1003
|
+
} catch (err) {
|
|
1004
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1005
|
+
const status = message.includes('Access denied') ? 403 : 400;
|
|
1006
|
+
console.error(`[Skills] Project path validation failed: ${message}`);
|
|
1007
|
+
return { error: status === 403 ? 'Access denied' : 'Invalid path', status };
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
|
|
709
1011
|
if (mode === 'import') {
|
|
710
1012
|
// Import mode: copy existing skill folder
|
|
711
1013
|
if (!sourcePath) {
|
|
712
1014
|
return { error: 'Source path is required for import mode' };
|
|
713
1015
|
}
|
|
714
1016
|
|
|
715
|
-
|
|
1017
|
+
if (skillName && (skillName.includes('/') || skillName.includes('\\') || skillName.includes('..'))) {
|
|
1018
|
+
return { error: 'Invalid skill name', status: 400 };
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
let validatedSourcePath;
|
|
1022
|
+
try {
|
|
1023
|
+
validatedSourcePath = await validateAllowedPath(sourcePath, { mustExist: true });
|
|
1024
|
+
} catch (err) {
|
|
1025
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1026
|
+
const status = message.includes('Access denied') ? 403 : 400;
|
|
1027
|
+
console.error(`[Skills] Path validation failed: ${message}`);
|
|
1028
|
+
return { error: status === 403 ? 'Access denied' : 'Invalid path', status };
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
return await importSkill(validatedSourcePath, location, validatedProjectPath, skillName);
|
|
716
1032
|
} else if (mode === 'cli-generate') {
|
|
717
1033
|
// CLI generate mode: use Claude to generate skill
|
|
718
1034
|
if (!skillName) {
|
|
719
1035
|
return { error: 'Skill name is required for CLI generation mode' };
|
|
720
1036
|
}
|
|
1037
|
+
if (skillName.includes('/') || skillName.includes('\\') || skillName.includes('..')) {
|
|
1038
|
+
return { error: 'Invalid skill name', status: 400 };
|
|
1039
|
+
}
|
|
721
1040
|
|
|
722
1041
|
return await generateSkillViaCLI({
|
|
723
|
-
generationType: generationType
|
|
1042
|
+
generationType: generationType === 'template' ? 'template' : 'description',
|
|
724
1043
|
description,
|
|
725
1044
|
skillName,
|
|
726
1045
|
location,
|
|
727
|
-
projectPath
|
|
1046
|
+
projectPath: validatedProjectPath,
|
|
1047
|
+
broadcastToClients
|
|
728
1048
|
});
|
|
729
1049
|
} else {
|
|
730
1050
|
return { error: 'Invalid mode. Must be "import" or "cli-generate"' };
|