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
|
@@ -17,6 +17,25 @@ except ImportError:
|
|
|
17
17
|
def is_embedding_backend_available(_backend: str): # type: ignore[no-redef]
|
|
18
18
|
return False, "codexlens.semantic not available"
|
|
19
19
|
|
|
20
|
+
try:
|
|
21
|
+
from codexlens.config import VECTORS_META_DB_NAME
|
|
22
|
+
except ImportError:
|
|
23
|
+
VECTORS_META_DB_NAME = "_vectors_meta.db"
|
|
24
|
+
|
|
25
|
+
try:
|
|
26
|
+
from codexlens.search.ranking import get_file_category
|
|
27
|
+
except ImportError:
|
|
28
|
+
def get_file_category(path: str): # type: ignore[no-redef]
|
|
29
|
+
"""Fallback: map common extensions to category."""
|
|
30
|
+
ext = Path(path).suffix.lower()
|
|
31
|
+
code_exts = {".py", ".js", ".jsx", ".ts", ".tsx", ".java", ".go", ".c", ".cpp", ".rs"}
|
|
32
|
+
doc_exts = {".md", ".mdx", ".txt", ".rst"}
|
|
33
|
+
if ext in code_exts:
|
|
34
|
+
return "code"
|
|
35
|
+
elif ext in doc_exts:
|
|
36
|
+
return "doc"
|
|
37
|
+
return None
|
|
38
|
+
|
|
20
39
|
logger = logging.getLogger(__name__)
|
|
21
40
|
|
|
22
41
|
# Embedding batch size - larger values improve throughput on modern hardware
|
|
@@ -24,6 +43,105 @@ logger = logging.getLogger(__name__)
|
|
|
24
43
|
EMBEDDING_BATCH_SIZE = 256
|
|
25
44
|
|
|
26
45
|
|
|
46
|
+
def calculate_dynamic_batch_size(config, embedder) -> int:
|
|
47
|
+
"""Calculate batch size dynamically based on model token capacity.
|
|
48
|
+
|
|
49
|
+
This function computes an optimal batch size by considering:
|
|
50
|
+
- Maximum chunk character size from parsing rules
|
|
51
|
+
- Estimated tokens per chunk (chars / chars_per_token_estimate)
|
|
52
|
+
- Model's maximum token capacity
|
|
53
|
+
- Utilization factor (default 80% to leave headroom)
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
config: Config object with api_batch_size_* settings
|
|
57
|
+
embedder: Embedding model object with max_tokens property
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
Calculated batch size, clamped to [1, api_batch_size_max]
|
|
61
|
+
"""
|
|
62
|
+
# If dynamic calculation is disabled, return static value
|
|
63
|
+
if not getattr(config, 'api_batch_size_dynamic', False):
|
|
64
|
+
return getattr(config, 'api_batch_size', 8)
|
|
65
|
+
|
|
66
|
+
# Get maximum chunk character size from ALL parsing rules (not just default)
|
|
67
|
+
# This ensures we use the worst-case chunk size across all languages
|
|
68
|
+
parsing_rules = getattr(config, 'parsing_rules', {})
|
|
69
|
+
all_max_chunk_chars = [
|
|
70
|
+
rule.get('max_chunk_chars', 0)
|
|
71
|
+
for rule in parsing_rules.values()
|
|
72
|
+
if isinstance(rule, dict)
|
|
73
|
+
]
|
|
74
|
+
max_chunk_chars = max(all_max_chunk_chars) if all_max_chunk_chars else 4000
|
|
75
|
+
if max_chunk_chars <= 0:
|
|
76
|
+
max_chunk_chars = 4000 # Final fallback
|
|
77
|
+
|
|
78
|
+
# Get characters per token estimate
|
|
79
|
+
chars_per_token = getattr(config, 'chars_per_token_estimate', 4)
|
|
80
|
+
if chars_per_token <= 0:
|
|
81
|
+
chars_per_token = 4 # Safe default
|
|
82
|
+
|
|
83
|
+
# Estimate tokens per chunk
|
|
84
|
+
estimated_tokens_per_chunk = max_chunk_chars / chars_per_token
|
|
85
|
+
|
|
86
|
+
# Prevent division by zero
|
|
87
|
+
if estimated_tokens_per_chunk <= 0:
|
|
88
|
+
return getattr(config, 'api_batch_size', 8)
|
|
89
|
+
|
|
90
|
+
# Get model's maximum token capacity
|
|
91
|
+
model_max_tokens = getattr(embedder, 'max_tokens', 8192)
|
|
92
|
+
|
|
93
|
+
# Get utilization factor (default 80%, max 95% to leave safety margin)
|
|
94
|
+
utilization_factor = getattr(config, 'api_batch_size_utilization_factor', 0.8)
|
|
95
|
+
if utilization_factor <= 0 or utilization_factor > 0.95:
|
|
96
|
+
if utilization_factor > 0.95:
|
|
97
|
+
logger.warning(
|
|
98
|
+
"Utilization factor %.2f exceeds safe limit 0.95. "
|
|
99
|
+
"Token estimation is approximate, high values risk API errors. "
|
|
100
|
+
"Clamping to 0.95.",
|
|
101
|
+
utilization_factor
|
|
102
|
+
)
|
|
103
|
+
utilization_factor = 0.95
|
|
104
|
+
else:
|
|
105
|
+
utilization_factor = 0.8
|
|
106
|
+
|
|
107
|
+
# Calculate safe token limit
|
|
108
|
+
safe_token_limit = model_max_tokens * utilization_factor
|
|
109
|
+
|
|
110
|
+
# Calculate dynamic batch size
|
|
111
|
+
dynamic_batch_size = int(safe_token_limit / estimated_tokens_per_chunk)
|
|
112
|
+
|
|
113
|
+
# Get maximum batch size limit
|
|
114
|
+
batch_size_max = getattr(config, 'api_batch_size_max', 2048)
|
|
115
|
+
|
|
116
|
+
# Clamp to [1, batch_size_max]
|
|
117
|
+
result = max(1, min(dynamic_batch_size, batch_size_max))
|
|
118
|
+
|
|
119
|
+
logger.debug(
|
|
120
|
+
"Dynamic batch size calculated: %d (max_chunk_chars=%d, chars_per_token=%d, "
|
|
121
|
+
"model_max_tokens=%d, utilization=%.1f%%, limit=%d)",
|
|
122
|
+
result, max_chunk_chars, chars_per_token, model_max_tokens,
|
|
123
|
+
utilization_factor * 100, batch_size_max
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
return result
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def _build_categories_from_batch(chunk_batch: List[Tuple[Any, str]]) -> List[str]:
|
|
130
|
+
"""Build categories list from chunk batch for index-level category filtering.
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
chunk_batch: List of (chunk, file_path) tuples
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
List of category strings ('code' or 'doc'), defaulting to 'code' for unknown
|
|
137
|
+
"""
|
|
138
|
+
categories = []
|
|
139
|
+
for _, file_path in chunk_batch:
|
|
140
|
+
cat = get_file_category(file_path)
|
|
141
|
+
categories.append(cat if cat else "code") # Default to 'code' for unknown extensions
|
|
142
|
+
return categories
|
|
143
|
+
|
|
144
|
+
|
|
27
145
|
def _cleanup_fastembed_resources() -> None:
|
|
28
146
|
"""Best-effort cleanup for fastembed/ONNX resources (no-op for other backends)."""
|
|
29
147
|
try:
|
|
@@ -33,6 +151,15 @@ def _cleanup_fastembed_resources() -> None:
|
|
|
33
151
|
pass
|
|
34
152
|
|
|
35
153
|
|
|
154
|
+
def _cleanup_splade_resources() -> None:
|
|
155
|
+
"""Release SPLADE encoder ONNX resources."""
|
|
156
|
+
try:
|
|
157
|
+
from codexlens.semantic.splade_encoder import clear_splade_cache
|
|
158
|
+
clear_splade_cache()
|
|
159
|
+
except Exception:
|
|
160
|
+
pass
|
|
161
|
+
|
|
162
|
+
|
|
36
163
|
def _generate_chunks_from_cursor(
|
|
37
164
|
cursor,
|
|
38
165
|
chunker,
|
|
@@ -271,6 +398,7 @@ def generate_embeddings(
|
|
|
271
398
|
endpoints: Optional[List] = None,
|
|
272
399
|
strategy: Optional[str] = None,
|
|
273
400
|
cooldown: Optional[float] = None,
|
|
401
|
+
splade_db_path: Optional[Path] = None,
|
|
274
402
|
) -> Dict[str, any]:
|
|
275
403
|
"""Generate embeddings for an index using memory-efficient batch processing.
|
|
276
404
|
|
|
@@ -300,6 +428,9 @@ def generate_embeddings(
|
|
|
300
428
|
Each dict has keys: model, api_key, api_base, weight.
|
|
301
429
|
strategy: Selection strategy for multi-endpoint mode (round_robin, latency_aware).
|
|
302
430
|
cooldown: Default cooldown seconds for rate-limited endpoints.
|
|
431
|
+
splade_db_path: Optional path to centralized SPLADE database. If None, SPLADE
|
|
432
|
+
is written to index_path (legacy behavior). Use index_root / SPLADE_DB_NAME
|
|
433
|
+
for centralized storage.
|
|
303
434
|
|
|
304
435
|
Returns:
|
|
305
436
|
Result dictionary with generation statistics
|
|
@@ -416,6 +547,14 @@ def generate_embeddings(
|
|
|
416
547
|
progress_callback(f"Using {endpoint_count} API endpoints with {strategy} strategy")
|
|
417
548
|
progress_callback(f"Using model: {embedder.model_name} ({embedder.embedding_dim} dimensions)")
|
|
418
549
|
|
|
550
|
+
# Calculate dynamic batch size based on model capacity
|
|
551
|
+
from codexlens.config import Config
|
|
552
|
+
batch_config = Config.load()
|
|
553
|
+
effective_batch_size = calculate_dynamic_batch_size(batch_config, embedder)
|
|
554
|
+
|
|
555
|
+
if progress_callback and batch_config.api_batch_size_dynamic:
|
|
556
|
+
progress_callback(f"Dynamic batch size: {effective_batch_size} (model max_tokens={getattr(embedder, 'max_tokens', 8192)})")
|
|
557
|
+
|
|
419
558
|
except Exception as e:
|
|
420
559
|
return {
|
|
421
560
|
"success": False,
|
|
@@ -429,7 +568,7 @@ def generate_embeddings(
|
|
|
429
568
|
total_chunks_created = 0
|
|
430
569
|
total_files_processed = 0
|
|
431
570
|
FILE_BATCH_SIZE = 100 # Process 100 files at a time
|
|
432
|
-
#
|
|
571
|
+
# effective_batch_size is calculated above (dynamic or EMBEDDING_BATCH_SIZE fallback)
|
|
433
572
|
|
|
434
573
|
try:
|
|
435
574
|
with VectorStore(index_path) as vector_store:
|
|
@@ -487,7 +626,7 @@ def generate_embeddings(
|
|
|
487
626
|
# Fallback to fixed-size batching for backward compatibility
|
|
488
627
|
def fixed_size_batches():
|
|
489
628
|
while True:
|
|
490
|
-
batch = list(islice(chunk_generator,
|
|
629
|
+
batch = list(islice(chunk_generator, effective_batch_size))
|
|
491
630
|
if not batch:
|
|
492
631
|
break
|
|
493
632
|
yield batch
|
|
@@ -518,7 +657,7 @@ def generate_embeddings(
|
|
|
518
657
|
for attempt in range(max_retries + 1):
|
|
519
658
|
try:
|
|
520
659
|
batch_contents = [chunk.content for chunk, _ in chunk_batch]
|
|
521
|
-
embeddings_numpy = embedder.embed_to_numpy(batch_contents, batch_size=
|
|
660
|
+
embeddings_numpy = embedder.embed_to_numpy(batch_contents, batch_size=effective_batch_size)
|
|
522
661
|
return batch_num, chunk_batch, embeddings_numpy, batch_files, None
|
|
523
662
|
|
|
524
663
|
except Exception as e:
|
|
@@ -566,10 +705,11 @@ def generate_embeddings(
|
|
|
566
705
|
try:
|
|
567
706
|
# Generate embeddings
|
|
568
707
|
batch_contents = [chunk.content for chunk, _ in chunk_batch]
|
|
569
|
-
embeddings_numpy = embedder.embed_to_numpy(batch_contents, batch_size=
|
|
708
|
+
embeddings_numpy = embedder.embed_to_numpy(batch_contents, batch_size=effective_batch_size)
|
|
570
709
|
|
|
571
|
-
# Store embeddings
|
|
572
|
-
|
|
710
|
+
# Store embeddings with category
|
|
711
|
+
categories = _build_categories_from_batch(chunk_batch)
|
|
712
|
+
vector_store.add_chunks_batch_numpy(chunk_batch, embeddings_numpy, categories=categories)
|
|
573
713
|
|
|
574
714
|
files_seen.update(batch_files)
|
|
575
715
|
total_chunks_created += len(chunk_batch)
|
|
@@ -621,7 +761,8 @@ def generate_embeddings(
|
|
|
621
761
|
batch_num, chunk_batch, embeddings_numpy, batch_files, error = f.result()
|
|
622
762
|
if embeddings_numpy is not None and error is None:
|
|
623
763
|
# Write to DB in main thread (no contention)
|
|
624
|
-
|
|
764
|
+
categories = _build_categories_from_batch(chunk_batch)
|
|
765
|
+
vector_store.add_chunks_batch_numpy(chunk_batch, embeddings_numpy, categories=categories)
|
|
625
766
|
total_chunks_created += len(chunk_batch)
|
|
626
767
|
files_seen.update(batch_files)
|
|
627
768
|
total_files_processed = len(files_seen)
|
|
@@ -658,7 +799,8 @@ def generate_embeddings(
|
|
|
658
799
|
try:
|
|
659
800
|
batch_num, chunk_batch, embeddings_numpy, batch_files, error = future.result()
|
|
660
801
|
if embeddings_numpy is not None and error is None:
|
|
661
|
-
|
|
802
|
+
categories = _build_categories_from_batch(chunk_batch)
|
|
803
|
+
vector_store.add_chunks_batch_numpy(chunk_batch, embeddings_numpy, categories=categories)
|
|
662
804
|
total_chunks_created += len(chunk_batch)
|
|
663
805
|
files_seen.update(batch_files)
|
|
664
806
|
total_files_processed = len(files_seen)
|
|
@@ -675,10 +817,97 @@ def generate_embeddings(
|
|
|
675
817
|
if progress_callback:
|
|
676
818
|
progress_callback(f"Finalizing index... Building ANN index for {total_chunks_created} chunks")
|
|
677
819
|
|
|
820
|
+
# --- SPLADE SPARSE ENCODING (after dense embeddings) ---
|
|
821
|
+
# Add SPLADE encoding if enabled in config
|
|
822
|
+
splade_success = False
|
|
823
|
+
splade_error = None
|
|
824
|
+
|
|
825
|
+
try:
|
|
826
|
+
from codexlens.config import Config, SPLADE_DB_NAME
|
|
827
|
+
config = Config.load()
|
|
828
|
+
|
|
829
|
+
if config.enable_splade:
|
|
830
|
+
from codexlens.semantic.splade_encoder import check_splade_available, get_splade_encoder
|
|
831
|
+
from codexlens.storage.splade_index import SpladeIndex
|
|
832
|
+
|
|
833
|
+
ok, err = check_splade_available()
|
|
834
|
+
if ok:
|
|
835
|
+
if progress_callback:
|
|
836
|
+
progress_callback(f"Generating SPLADE sparse vectors for {total_chunks_created} chunks...")
|
|
837
|
+
|
|
838
|
+
# Initialize SPLADE encoder and index
|
|
839
|
+
splade_encoder = get_splade_encoder(use_gpu=use_gpu)
|
|
840
|
+
# Use centralized SPLADE database if provided, otherwise fallback to index_path
|
|
841
|
+
effective_splade_path = splade_db_path if splade_db_path else index_path
|
|
842
|
+
splade_index = SpladeIndex(effective_splade_path)
|
|
843
|
+
splade_index.create_tables()
|
|
844
|
+
|
|
845
|
+
# Retrieve all chunks from database for SPLADE encoding
|
|
846
|
+
with sqlite3.connect(index_path) as conn:
|
|
847
|
+
conn.row_factory = sqlite3.Row
|
|
848
|
+
cursor = conn.execute("SELECT id, content FROM semantic_chunks ORDER BY id")
|
|
849
|
+
|
|
850
|
+
# Batch encode for efficiency
|
|
851
|
+
SPLADE_BATCH_SIZE = 32
|
|
852
|
+
batch_postings = []
|
|
853
|
+
chunk_batch = []
|
|
854
|
+
chunk_ids = []
|
|
855
|
+
|
|
856
|
+
for row in cursor:
|
|
857
|
+
chunk_id = row["id"]
|
|
858
|
+
content = row["content"]
|
|
859
|
+
|
|
860
|
+
chunk_ids.append(chunk_id)
|
|
861
|
+
chunk_batch.append(content)
|
|
862
|
+
|
|
863
|
+
# Process batch when full
|
|
864
|
+
if len(chunk_batch) >= SPLADE_BATCH_SIZE:
|
|
865
|
+
sparse_vecs = splade_encoder.encode_batch(chunk_batch, batch_size=SPLADE_BATCH_SIZE)
|
|
866
|
+
for cid, sparse_vec in zip(chunk_ids, sparse_vecs):
|
|
867
|
+
batch_postings.append((cid, sparse_vec))
|
|
868
|
+
|
|
869
|
+
chunk_batch = []
|
|
870
|
+
chunk_ids = []
|
|
871
|
+
|
|
872
|
+
# Process remaining chunks
|
|
873
|
+
if chunk_batch:
|
|
874
|
+
sparse_vecs = splade_encoder.encode_batch(chunk_batch, batch_size=SPLADE_BATCH_SIZE)
|
|
875
|
+
for cid, sparse_vec in zip(chunk_ids, sparse_vecs):
|
|
876
|
+
batch_postings.append((cid, sparse_vec))
|
|
877
|
+
|
|
878
|
+
# Batch insert all postings
|
|
879
|
+
if batch_postings:
|
|
880
|
+
splade_index.add_postings_batch(batch_postings)
|
|
881
|
+
|
|
882
|
+
# Set metadata
|
|
883
|
+
splade_index.set_metadata(
|
|
884
|
+
model_name=splade_encoder.model_name,
|
|
885
|
+
vocab_size=splade_encoder.vocab_size
|
|
886
|
+
)
|
|
887
|
+
|
|
888
|
+
splade_success = True
|
|
889
|
+
if progress_callback:
|
|
890
|
+
stats = splade_index.get_stats()
|
|
891
|
+
progress_callback(
|
|
892
|
+
f"SPLADE index created: {stats['total_postings']} postings, "
|
|
893
|
+
f"{stats['unique_tokens']} unique tokens"
|
|
894
|
+
)
|
|
895
|
+
else:
|
|
896
|
+
logger.debug("SPLADE not available: %s", err)
|
|
897
|
+
splade_error = f"SPLADE not available: {err}"
|
|
898
|
+
except Exception as e:
|
|
899
|
+
splade_error = str(e)
|
|
900
|
+
logger.warning("SPLADE encoding failed: %s", e)
|
|
901
|
+
|
|
902
|
+
# Report SPLADE status after processing
|
|
903
|
+
if progress_callback and not splade_success and splade_error:
|
|
904
|
+
progress_callback(f"SPLADE index: FAILED - {splade_error}")
|
|
905
|
+
|
|
678
906
|
except Exception as e:
|
|
679
907
|
# Cleanup on error to prevent process hanging
|
|
680
908
|
try:
|
|
681
909
|
_cleanup_fastembed_resources()
|
|
910
|
+
_cleanup_splade_resources()
|
|
682
911
|
gc.collect()
|
|
683
912
|
except Exception:
|
|
684
913
|
pass
|
|
@@ -690,6 +919,7 @@ def generate_embeddings(
|
|
|
690
919
|
# This is critical - without it, ONNX Runtime threads prevent Python from exiting
|
|
691
920
|
try:
|
|
692
921
|
_cleanup_fastembed_resources()
|
|
922
|
+
_cleanup_splade_resources()
|
|
693
923
|
gc.collect()
|
|
694
924
|
except Exception:
|
|
695
925
|
pass
|
|
@@ -709,8 +939,10 @@ def generate_embeddings(
|
|
|
709
939
|
}
|
|
710
940
|
|
|
711
941
|
|
|
712
|
-
def
|
|
713
|
-
"""
|
|
942
|
+
def _discover_index_dbs_internal(index_root: Path) -> List[Path]:
|
|
943
|
+
"""Internal helper to find all _index.db files (no deprecation warning).
|
|
944
|
+
|
|
945
|
+
Used internally by generate_dense_embeddings_centralized.
|
|
714
946
|
|
|
715
947
|
Args:
|
|
716
948
|
index_root: Root directory to scan for _index.db files
|
|
@@ -724,6 +956,30 @@ def discover_all_index_dbs(index_root: Path) -> List[Path]:
|
|
|
724
956
|
return sorted(index_root.rglob("_index.db"))
|
|
725
957
|
|
|
726
958
|
|
|
959
|
+
def discover_all_index_dbs(index_root: Path) -> List[Path]:
|
|
960
|
+
"""Recursively find all _index.db files in an index tree.
|
|
961
|
+
|
|
962
|
+
.. deprecated::
|
|
963
|
+
This function is deprecated. Use centralized indexing with
|
|
964
|
+
``generate_dense_embeddings_centralized`` instead, which handles
|
|
965
|
+
index discovery internally.
|
|
966
|
+
|
|
967
|
+
Args:
|
|
968
|
+
index_root: Root directory to scan for _index.db files
|
|
969
|
+
|
|
970
|
+
Returns:
|
|
971
|
+
Sorted list of paths to _index.db files
|
|
972
|
+
"""
|
|
973
|
+
import warnings
|
|
974
|
+
warnings.warn(
|
|
975
|
+
"discover_all_index_dbs is deprecated. Use centralized indexing with "
|
|
976
|
+
"generate_dense_embeddings_centralized instead.",
|
|
977
|
+
DeprecationWarning,
|
|
978
|
+
stacklevel=2
|
|
979
|
+
)
|
|
980
|
+
return _discover_index_dbs_internal(index_root)
|
|
981
|
+
|
|
982
|
+
|
|
727
983
|
def find_all_indexes(scan_dir: Path) -> List[Path]:
|
|
728
984
|
"""Find all _index.db files in directory tree.
|
|
729
985
|
|
|
@@ -757,6 +1013,11 @@ def generate_embeddings_recursive(
|
|
|
757
1013
|
) -> Dict[str, any]:
|
|
758
1014
|
"""Generate embeddings for all index databases in a project recursively.
|
|
759
1015
|
|
|
1016
|
+
.. deprecated::
|
|
1017
|
+
This function is deprecated. Use ``generate_dense_embeddings_centralized``
|
|
1018
|
+
instead, which creates a single centralized vector index for the entire project
|
|
1019
|
+
rather than per-directory indexes.
|
|
1020
|
+
|
|
760
1021
|
Args:
|
|
761
1022
|
index_root: Root index directory containing _index.db files
|
|
762
1023
|
embedding_backend: Embedding backend to use (fastembed or litellm).
|
|
@@ -782,6 +1043,14 @@ def generate_embeddings_recursive(
|
|
|
782
1043
|
Returns:
|
|
783
1044
|
Aggregated result dictionary with generation statistics
|
|
784
1045
|
"""
|
|
1046
|
+
import warnings
|
|
1047
|
+
warnings.warn(
|
|
1048
|
+
"generate_embeddings_recursive is deprecated. Use "
|
|
1049
|
+
"generate_dense_embeddings_centralized instead for centralized indexing.",
|
|
1050
|
+
DeprecationWarning,
|
|
1051
|
+
stacklevel=2
|
|
1052
|
+
)
|
|
1053
|
+
|
|
785
1054
|
# Get defaults from config if not specified
|
|
786
1055
|
(default_backend, default_model, default_gpu,
|
|
787
1056
|
default_endpoints, default_strategy, default_cooldown) = _get_embedding_defaults()
|
|
@@ -812,8 +1081,8 @@ def generate_embeddings_recursive(
|
|
|
812
1081
|
else:
|
|
813
1082
|
max_workers = 1
|
|
814
1083
|
|
|
815
|
-
# Discover all _index.db files
|
|
816
|
-
index_files =
|
|
1084
|
+
# Discover all _index.db files (using internal helper to avoid double deprecation warning)
|
|
1085
|
+
index_files = _discover_index_dbs_internal(index_root)
|
|
817
1086
|
|
|
818
1087
|
if not index_files:
|
|
819
1088
|
return {
|
|
@@ -824,6 +1093,10 @@ def generate_embeddings_recursive(
|
|
|
824
1093
|
if progress_callback:
|
|
825
1094
|
progress_callback(f"Found {len(index_files)} index databases to process")
|
|
826
1095
|
|
|
1096
|
+
# Calculate centralized SPLADE database path
|
|
1097
|
+
from codexlens.config import SPLADE_DB_NAME
|
|
1098
|
+
splade_db_path = index_root / SPLADE_DB_NAME
|
|
1099
|
+
|
|
827
1100
|
# Process each index database
|
|
828
1101
|
all_results = []
|
|
829
1102
|
total_chunks = 0
|
|
@@ -853,6 +1126,7 @@ def generate_embeddings_recursive(
|
|
|
853
1126
|
endpoints=endpoints,
|
|
854
1127
|
strategy=strategy,
|
|
855
1128
|
cooldown=cooldown,
|
|
1129
|
+
splade_db_path=splade_db_path, # Use centralized SPLADE storage
|
|
856
1130
|
)
|
|
857
1131
|
|
|
858
1132
|
all_results.append({
|
|
@@ -874,6 +1148,7 @@ def generate_embeddings_recursive(
|
|
|
874
1148
|
# Each generate_embeddings() call does its own cleanup, but do a final one to be safe
|
|
875
1149
|
try:
|
|
876
1150
|
_cleanup_fastembed_resources()
|
|
1151
|
+
_cleanup_splade_resources()
|
|
877
1152
|
gc.collect()
|
|
878
1153
|
except Exception:
|
|
879
1154
|
pass
|
|
@@ -893,6 +1168,484 @@ def generate_embeddings_recursive(
|
|
|
893
1168
|
}
|
|
894
1169
|
|
|
895
1170
|
|
|
1171
|
+
def generate_dense_embeddings_centralized(
|
|
1172
|
+
index_root: Path,
|
|
1173
|
+
embedding_backend: Optional[str] = None,
|
|
1174
|
+
model_profile: Optional[str] = None,
|
|
1175
|
+
force: bool = False,
|
|
1176
|
+
chunk_size: int = 2000,
|
|
1177
|
+
overlap: int = 200,
|
|
1178
|
+
progress_callback: Optional[callable] = None,
|
|
1179
|
+
use_gpu: Optional[bool] = None,
|
|
1180
|
+
max_tokens_per_batch: Optional[int] = None,
|
|
1181
|
+
max_workers: Optional[int] = None,
|
|
1182
|
+
endpoints: Optional[List] = None,
|
|
1183
|
+
strategy: Optional[str] = None,
|
|
1184
|
+
cooldown: Optional[float] = None,
|
|
1185
|
+
) -> Dict[str, any]:
|
|
1186
|
+
"""Generate dense embeddings with centralized vector storage.
|
|
1187
|
+
|
|
1188
|
+
This function creates a single HNSW index at the project root instead of
|
|
1189
|
+
per-directory indexes. All chunks from all _index.db files are combined
|
|
1190
|
+
into one central _vectors.hnsw file.
|
|
1191
|
+
|
|
1192
|
+
Target architecture:
|
|
1193
|
+
<index_root>/
|
|
1194
|
+
|-- _vectors.hnsw # Centralized dense vector ANN index
|
|
1195
|
+
|-- _splade.db # Centralized sparse vector index
|
|
1196
|
+
|-- src/
|
|
1197
|
+
|-- _index.db # No longer contains .hnsw file
|
|
1198
|
+
|
|
1199
|
+
Args:
|
|
1200
|
+
index_root: Root index directory containing _index.db files
|
|
1201
|
+
embedding_backend: Embedding backend (fastembed or litellm)
|
|
1202
|
+
model_profile: Model profile or name
|
|
1203
|
+
force: If True, regenerate even if embeddings exist
|
|
1204
|
+
chunk_size: Maximum chunk size in characters
|
|
1205
|
+
overlap: Overlap size in characters
|
|
1206
|
+
progress_callback: Optional callback for progress updates
|
|
1207
|
+
use_gpu: Whether to use GPU acceleration
|
|
1208
|
+
max_tokens_per_batch: Maximum tokens per batch
|
|
1209
|
+
max_workers: Maximum concurrent workers
|
|
1210
|
+
endpoints: Multi-endpoint configurations
|
|
1211
|
+
strategy: Endpoint selection strategy
|
|
1212
|
+
cooldown: Rate-limit cooldown seconds
|
|
1213
|
+
|
|
1214
|
+
Returns:
|
|
1215
|
+
Result dictionary with generation statistics
|
|
1216
|
+
"""
|
|
1217
|
+
from codexlens.config import VECTORS_HNSW_NAME, SPLADE_DB_NAME
|
|
1218
|
+
|
|
1219
|
+
# Get defaults from config if not specified
|
|
1220
|
+
(default_backend, default_model, default_gpu,
|
|
1221
|
+
default_endpoints, default_strategy, default_cooldown) = _get_embedding_defaults()
|
|
1222
|
+
|
|
1223
|
+
if embedding_backend is None:
|
|
1224
|
+
embedding_backend = default_backend
|
|
1225
|
+
if model_profile is None:
|
|
1226
|
+
model_profile = default_model
|
|
1227
|
+
if use_gpu is None:
|
|
1228
|
+
use_gpu = default_gpu
|
|
1229
|
+
if endpoints is None:
|
|
1230
|
+
endpoints = default_endpoints
|
|
1231
|
+
if strategy is None:
|
|
1232
|
+
strategy = default_strategy
|
|
1233
|
+
if cooldown is None:
|
|
1234
|
+
cooldown = default_cooldown
|
|
1235
|
+
|
|
1236
|
+
# Calculate endpoint count for worker scaling
|
|
1237
|
+
endpoint_count = len(endpoints) if endpoints else 1
|
|
1238
|
+
|
|
1239
|
+
if max_workers is None:
|
|
1240
|
+
if embedding_backend == "litellm":
|
|
1241
|
+
if endpoint_count > 1:
|
|
1242
|
+
max_workers = endpoint_count * 2
|
|
1243
|
+
else:
|
|
1244
|
+
max_workers = 4
|
|
1245
|
+
else:
|
|
1246
|
+
max_workers = 1
|
|
1247
|
+
|
|
1248
|
+
backend_available, backend_error = is_embedding_backend_available(embedding_backend)
|
|
1249
|
+
if not backend_available:
|
|
1250
|
+
return {"success": False, "error": backend_error or "Embedding backend not available"}
|
|
1251
|
+
|
|
1252
|
+
# Discover all _index.db files
|
|
1253
|
+
index_files = _discover_index_dbs_internal(index_root)
|
|
1254
|
+
|
|
1255
|
+
if not index_files:
|
|
1256
|
+
return {
|
|
1257
|
+
"success": False,
|
|
1258
|
+
"error": f"No index databases found in {index_root}",
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
if progress_callback:
|
|
1262
|
+
progress_callback(f"Found {len(index_files)} index databases for centralized embedding")
|
|
1263
|
+
|
|
1264
|
+
# Pre-calculate estimated chunk count for HNSW capacity
|
|
1265
|
+
# This avoids expensive resize operations during indexing
|
|
1266
|
+
estimated_total_files = 0
|
|
1267
|
+
for index_path in index_files:
|
|
1268
|
+
try:
|
|
1269
|
+
with sqlite3.connect(index_path) as conn:
|
|
1270
|
+
cursor = conn.execute("SELECT COUNT(*) FROM files")
|
|
1271
|
+
estimated_total_files += cursor.fetchone()[0]
|
|
1272
|
+
except Exception:
|
|
1273
|
+
pass
|
|
1274
|
+
# Heuristic: ~15 chunks per file on average
|
|
1275
|
+
estimated_chunks = max(100000, estimated_total_files * 15)
|
|
1276
|
+
|
|
1277
|
+
if progress_callback:
|
|
1278
|
+
progress_callback(f"Estimated {estimated_total_files} files, ~{estimated_chunks} chunks")
|
|
1279
|
+
|
|
1280
|
+
# Check for existing centralized index
|
|
1281
|
+
central_hnsw_path = index_root / VECTORS_HNSW_NAME
|
|
1282
|
+
if central_hnsw_path.exists() and not force:
|
|
1283
|
+
return {
|
|
1284
|
+
"success": False,
|
|
1285
|
+
"error": f"Centralized vector index already exists at {central_hnsw_path}. Use --force to regenerate.",
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
# Initialize embedder
|
|
1289
|
+
try:
|
|
1290
|
+
from codexlens.semantic.factory import get_embedder as get_embedder_factory
|
|
1291
|
+
from codexlens.semantic.chunker import Chunker, ChunkConfig
|
|
1292
|
+
from codexlens.semantic.ann_index import ANNIndex
|
|
1293
|
+
|
|
1294
|
+
if embedding_backend == "fastembed":
|
|
1295
|
+
embedder = get_embedder_factory(backend="fastembed", profile=model_profile, use_gpu=use_gpu)
|
|
1296
|
+
elif embedding_backend == "litellm":
|
|
1297
|
+
embedder = get_embedder_factory(
|
|
1298
|
+
backend="litellm",
|
|
1299
|
+
model=model_profile,
|
|
1300
|
+
endpoints=endpoints if endpoints else None,
|
|
1301
|
+
strategy=strategy,
|
|
1302
|
+
cooldown=cooldown,
|
|
1303
|
+
)
|
|
1304
|
+
else:
|
|
1305
|
+
return {
|
|
1306
|
+
"success": False,
|
|
1307
|
+
"error": f"Invalid embedding backend: {embedding_backend}",
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
chunker = Chunker(config=ChunkConfig(
|
|
1311
|
+
max_chunk_size=chunk_size,
|
|
1312
|
+
overlap=overlap,
|
|
1313
|
+
skip_token_count=True
|
|
1314
|
+
))
|
|
1315
|
+
|
|
1316
|
+
if progress_callback:
|
|
1317
|
+
if endpoint_count > 1:
|
|
1318
|
+
progress_callback(f"Using {endpoint_count} API endpoints with {strategy} strategy")
|
|
1319
|
+
progress_callback(f"Using model: {embedder.model_name} ({embedder.embedding_dim} dimensions)")
|
|
1320
|
+
|
|
1321
|
+
# Calculate dynamic batch size based on model capacity
|
|
1322
|
+
from codexlens.config import Config
|
|
1323
|
+
batch_config = Config.load()
|
|
1324
|
+
effective_batch_size = calculate_dynamic_batch_size(batch_config, embedder)
|
|
1325
|
+
|
|
1326
|
+
if progress_callback and batch_config.api_batch_size_dynamic:
|
|
1327
|
+
progress_callback(f"Dynamic batch size: {effective_batch_size} (model max_tokens={getattr(embedder, 'max_tokens', 8192)})")
|
|
1328
|
+
|
|
1329
|
+
except Exception as e:
|
|
1330
|
+
return {
|
|
1331
|
+
"success": False,
|
|
1332
|
+
"error": f"Failed to initialize components: {str(e)}",
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
# Create centralized ANN index with pre-calculated capacity
|
|
1336
|
+
# Using estimated_chunks avoids expensive resize operations during indexing
|
|
1337
|
+
central_ann_index = ANNIndex.create_central(
|
|
1338
|
+
index_root=index_root,
|
|
1339
|
+
dim=embedder.embedding_dim,
|
|
1340
|
+
initial_capacity=estimated_chunks,
|
|
1341
|
+
auto_save=False,
|
|
1342
|
+
)
|
|
1343
|
+
|
|
1344
|
+
# Process all index databases
|
|
1345
|
+
start_time = time.time()
|
|
1346
|
+
failed_files = []
|
|
1347
|
+
total_chunks_created = 0
|
|
1348
|
+
total_files_processed = 0
|
|
1349
|
+
all_chunk_ids = []
|
|
1350
|
+
all_embeddings = []
|
|
1351
|
+
|
|
1352
|
+
# Track chunk ID to file_path mapping for metadata
|
|
1353
|
+
chunk_id_to_info: Dict[int, Dict[str, Any]] = {}
|
|
1354
|
+
next_chunk_id = 1
|
|
1355
|
+
# Track current index_path for source_index_db field
|
|
1356
|
+
current_index_path: Optional[str] = None
|
|
1357
|
+
|
|
1358
|
+
for idx, index_path in enumerate(index_files, 1):
|
|
1359
|
+
if progress_callback:
|
|
1360
|
+
try:
|
|
1361
|
+
rel_path = index_path.relative_to(index_root)
|
|
1362
|
+
except ValueError:
|
|
1363
|
+
rel_path = index_path
|
|
1364
|
+
progress_callback(f"Processing {idx}/{len(index_files)}: {rel_path}")
|
|
1365
|
+
|
|
1366
|
+
# Track current index_path for source_index_db
|
|
1367
|
+
current_index_path = str(index_path)
|
|
1368
|
+
|
|
1369
|
+
try:
|
|
1370
|
+
with sqlite3.connect(index_path) as conn:
|
|
1371
|
+
conn.row_factory = sqlite3.Row
|
|
1372
|
+
path_column = _get_path_column(conn)
|
|
1373
|
+
|
|
1374
|
+
# Get files from this index
|
|
1375
|
+
cursor = conn.execute(f"SELECT {path_column}, content, language FROM files")
|
|
1376
|
+
file_rows = cursor.fetchall()
|
|
1377
|
+
|
|
1378
|
+
for file_row in file_rows:
|
|
1379
|
+
file_path = file_row[path_column]
|
|
1380
|
+
content = file_row["content"]
|
|
1381
|
+
language = file_row["language"] or "python"
|
|
1382
|
+
|
|
1383
|
+
try:
|
|
1384
|
+
chunks = chunker.chunk_sliding_window(
|
|
1385
|
+
content,
|
|
1386
|
+
file_path=file_path,
|
|
1387
|
+
language=language
|
|
1388
|
+
)
|
|
1389
|
+
|
|
1390
|
+
if not chunks:
|
|
1391
|
+
continue
|
|
1392
|
+
|
|
1393
|
+
total_files_processed += 1
|
|
1394
|
+
|
|
1395
|
+
# Generate embeddings for this file's chunks
|
|
1396
|
+
batch_contents = [chunk.content for chunk in chunks]
|
|
1397
|
+
embeddings_numpy = embedder.embed_to_numpy(batch_contents, batch_size=effective_batch_size)
|
|
1398
|
+
|
|
1399
|
+
# Assign chunk IDs and store embeddings
|
|
1400
|
+
for i, chunk in enumerate(chunks):
|
|
1401
|
+
chunk_id = next_chunk_id
|
|
1402
|
+
next_chunk_id += 1
|
|
1403
|
+
|
|
1404
|
+
all_chunk_ids.append(chunk_id)
|
|
1405
|
+
all_embeddings.append(embeddings_numpy[i])
|
|
1406
|
+
|
|
1407
|
+
# Store metadata for later retrieval
|
|
1408
|
+
chunk_id_to_info[chunk_id] = {
|
|
1409
|
+
"file_path": file_path,
|
|
1410
|
+
"content": chunk.content,
|
|
1411
|
+
"metadata": chunk.metadata,
|
|
1412
|
+
"category": get_file_category(file_path) or "code",
|
|
1413
|
+
"source_index_db": current_index_path,
|
|
1414
|
+
}
|
|
1415
|
+
total_chunks_created += 1
|
|
1416
|
+
|
|
1417
|
+
except Exception as e:
|
|
1418
|
+
logger.error(f"Failed to process {file_path}: {e}")
|
|
1419
|
+
failed_files.append((file_path, str(e)))
|
|
1420
|
+
|
|
1421
|
+
except Exception as e:
|
|
1422
|
+
logger.error(f"Failed to read index {index_path}: {e}")
|
|
1423
|
+
failed_files.append((str(index_path), str(e)))
|
|
1424
|
+
|
|
1425
|
+
# Add all embeddings to centralized ANN index
|
|
1426
|
+
if all_embeddings:
|
|
1427
|
+
if progress_callback:
|
|
1428
|
+
progress_callback(f"Building centralized ANN index with {len(all_embeddings)} vectors...")
|
|
1429
|
+
|
|
1430
|
+
try:
|
|
1431
|
+
import numpy as np
|
|
1432
|
+
embeddings_matrix = np.vstack(all_embeddings)
|
|
1433
|
+
central_ann_index.add_vectors(all_chunk_ids, embeddings_matrix)
|
|
1434
|
+
central_ann_index.save()
|
|
1435
|
+
|
|
1436
|
+
if progress_callback:
|
|
1437
|
+
progress_callback(f"Saved centralized index to {central_hnsw_path}")
|
|
1438
|
+
|
|
1439
|
+
except Exception as e:
|
|
1440
|
+
return {
|
|
1441
|
+
"success": False,
|
|
1442
|
+
"error": f"Failed to build centralized ANN index: {str(e)}",
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
# Store chunk metadata in a centralized metadata database
|
|
1446
|
+
vectors_meta_path = index_root / VECTORS_META_DB_NAME
|
|
1447
|
+
if chunk_id_to_info:
|
|
1448
|
+
if progress_callback:
|
|
1449
|
+
progress_callback(f"Storing {len(chunk_id_to_info)} chunk metadata records...")
|
|
1450
|
+
|
|
1451
|
+
try:
|
|
1452
|
+
from codexlens.storage.vector_meta_store import VectorMetadataStore
|
|
1453
|
+
|
|
1454
|
+
with VectorMetadataStore(vectors_meta_path) as meta_store:
|
|
1455
|
+
# Convert chunk_id_to_info dict to list of dicts for batch insert
|
|
1456
|
+
chunks_to_store = []
|
|
1457
|
+
for cid, info in chunk_id_to_info.items():
|
|
1458
|
+
metadata = info.get("metadata", {})
|
|
1459
|
+
chunks_to_store.append({
|
|
1460
|
+
"chunk_id": cid,
|
|
1461
|
+
"file_path": info["file_path"],
|
|
1462
|
+
"content": info["content"],
|
|
1463
|
+
"start_line": metadata.get("start_line"),
|
|
1464
|
+
"end_line": metadata.get("end_line"),
|
|
1465
|
+
"category": info.get("category"),
|
|
1466
|
+
"metadata": metadata,
|
|
1467
|
+
"source_index_db": info.get("source_index_db"),
|
|
1468
|
+
})
|
|
1469
|
+
|
|
1470
|
+
meta_store.add_chunks(chunks_to_store)
|
|
1471
|
+
|
|
1472
|
+
if progress_callback:
|
|
1473
|
+
progress_callback(f"Saved metadata to {vectors_meta_path}")
|
|
1474
|
+
|
|
1475
|
+
except Exception as e:
|
|
1476
|
+
logger.warning("Failed to store vector metadata: %s", e)
|
|
1477
|
+
# Non-fatal: continue without centralized metadata
|
|
1478
|
+
|
|
1479
|
+
# --- Binary Vector Generation for Cascade Search (Memory-Mapped) ---
|
|
1480
|
+
binary_success = False
|
|
1481
|
+
binary_count = 0
|
|
1482
|
+
try:
|
|
1483
|
+
from codexlens.config import Config, BINARY_VECTORS_MMAP_NAME
|
|
1484
|
+
config = Config.load()
|
|
1485
|
+
|
|
1486
|
+
if getattr(config, 'enable_binary_cascade', True) and all_embeddings:
|
|
1487
|
+
import numpy as np
|
|
1488
|
+
|
|
1489
|
+
if progress_callback:
|
|
1490
|
+
progress_callback(f"Generating binary vectors for {len(all_embeddings)} chunks...")
|
|
1491
|
+
|
|
1492
|
+
# Binarize dense vectors: sign(x) -> 1 if x > 0, 0 otherwise
|
|
1493
|
+
# Pack into bytes for efficient storage and Hamming distance computation
|
|
1494
|
+
embeddings_matrix = np.vstack(all_embeddings)
|
|
1495
|
+
binary_matrix = (embeddings_matrix > 0).astype(np.uint8)
|
|
1496
|
+
|
|
1497
|
+
# Pack bits into bytes (8 bits per byte) - vectorized for all rows
|
|
1498
|
+
packed_matrix = np.packbits(binary_matrix, axis=1)
|
|
1499
|
+
binary_count = len(packed_matrix)
|
|
1500
|
+
|
|
1501
|
+
# Save as memory-mapped file for efficient loading
|
|
1502
|
+
binary_mmap_path = index_root / BINARY_VECTORS_MMAP_NAME
|
|
1503
|
+
mmap_array = np.memmap(
|
|
1504
|
+
str(binary_mmap_path),
|
|
1505
|
+
dtype=np.uint8,
|
|
1506
|
+
mode='w+',
|
|
1507
|
+
shape=packed_matrix.shape
|
|
1508
|
+
)
|
|
1509
|
+
mmap_array[:] = packed_matrix
|
|
1510
|
+
mmap_array.flush()
|
|
1511
|
+
del mmap_array # Close the memmap
|
|
1512
|
+
|
|
1513
|
+
# Save metadata (shape and chunk_ids) to sidecar JSON
|
|
1514
|
+
import json
|
|
1515
|
+
meta_path = binary_mmap_path.with_suffix('.meta.json')
|
|
1516
|
+
with open(meta_path, 'w') as f:
|
|
1517
|
+
json.dump({
|
|
1518
|
+
'shape': list(packed_matrix.shape),
|
|
1519
|
+
'chunk_ids': all_chunk_ids,
|
|
1520
|
+
'embedding_dim': embeddings_matrix.shape[1],
|
|
1521
|
+
}, f)
|
|
1522
|
+
|
|
1523
|
+
# Also store in DB for backward compatibility
|
|
1524
|
+
from codexlens.storage.vector_meta_store import VectorMetadataStore
|
|
1525
|
+
binary_packed_bytes = [row.tobytes() for row in packed_matrix]
|
|
1526
|
+
with VectorMetadataStore(vectors_meta_path) as meta_store:
|
|
1527
|
+
meta_store.add_binary_vectors(all_chunk_ids, binary_packed_bytes)
|
|
1528
|
+
|
|
1529
|
+
binary_success = True
|
|
1530
|
+
if progress_callback:
|
|
1531
|
+
progress_callback(f"Generated {binary_count} binary vectors ({embeddings_matrix.shape[1]} dims -> {packed_matrix.shape[1]} bytes, mmap: {binary_mmap_path.name})")
|
|
1532
|
+
|
|
1533
|
+
except Exception as e:
|
|
1534
|
+
logger.warning("Binary vector generation failed: %s", e)
|
|
1535
|
+
# Non-fatal: continue without binary vectors
|
|
1536
|
+
|
|
1537
|
+
# --- SPLADE Sparse Index Generation (Centralized) ---
|
|
1538
|
+
splade_success = False
|
|
1539
|
+
splade_chunks_count = 0
|
|
1540
|
+
try:
|
|
1541
|
+
from codexlens.config import Config
|
|
1542
|
+
config = Config.load()
|
|
1543
|
+
|
|
1544
|
+
if config.enable_splade and chunk_id_to_info:
|
|
1545
|
+
from codexlens.semantic.splade_encoder import check_splade_available, get_splade_encoder
|
|
1546
|
+
from codexlens.storage.splade_index import SpladeIndex
|
|
1547
|
+
import json
|
|
1548
|
+
|
|
1549
|
+
ok, err = check_splade_available()
|
|
1550
|
+
if ok:
|
|
1551
|
+
if progress_callback:
|
|
1552
|
+
progress_callback(f"Generating SPLADE sparse vectors for {len(chunk_id_to_info)} chunks...")
|
|
1553
|
+
|
|
1554
|
+
# Initialize SPLADE encoder and index
|
|
1555
|
+
splade_encoder = get_splade_encoder(use_gpu=use_gpu)
|
|
1556
|
+
splade_db_path = index_root / SPLADE_DB_NAME
|
|
1557
|
+
splade_index = SpladeIndex(splade_db_path)
|
|
1558
|
+
splade_index.create_tables()
|
|
1559
|
+
|
|
1560
|
+
# Batch encode for efficiency
|
|
1561
|
+
SPLADE_BATCH_SIZE = 32
|
|
1562
|
+
all_postings = []
|
|
1563
|
+
all_chunk_metadata = []
|
|
1564
|
+
|
|
1565
|
+
# Create batches from chunk_id_to_info
|
|
1566
|
+
chunk_items = list(chunk_id_to_info.items())
|
|
1567
|
+
|
|
1568
|
+
for i in range(0, len(chunk_items), SPLADE_BATCH_SIZE):
|
|
1569
|
+
batch_items = chunk_items[i:i + SPLADE_BATCH_SIZE]
|
|
1570
|
+
chunk_ids = [item[0] for item in batch_items]
|
|
1571
|
+
chunk_contents = [item[1]["content"] for item in batch_items]
|
|
1572
|
+
|
|
1573
|
+
# Generate sparse vectors
|
|
1574
|
+
sparse_vecs = splade_encoder.encode_batch(chunk_contents, batch_size=SPLADE_BATCH_SIZE)
|
|
1575
|
+
for cid, sparse_vec in zip(chunk_ids, sparse_vecs):
|
|
1576
|
+
all_postings.append((cid, sparse_vec))
|
|
1577
|
+
|
|
1578
|
+
if progress_callback and (i + SPLADE_BATCH_SIZE) % 100 == 0:
|
|
1579
|
+
progress_callback(f"SPLADE encoding: {min(i + SPLADE_BATCH_SIZE, len(chunk_items))}/{len(chunk_items)}")
|
|
1580
|
+
|
|
1581
|
+
# Batch insert all postings
|
|
1582
|
+
if all_postings:
|
|
1583
|
+
splade_index.add_postings_batch(all_postings)
|
|
1584
|
+
|
|
1585
|
+
# CRITICAL FIX: Populate splade_chunks table
|
|
1586
|
+
for cid, info in chunk_id_to_info.items():
|
|
1587
|
+
metadata_str = json.dumps(info.get("metadata", {})) if info.get("metadata") else None
|
|
1588
|
+
all_chunk_metadata.append((
|
|
1589
|
+
cid,
|
|
1590
|
+
info["file_path"],
|
|
1591
|
+
info["content"],
|
|
1592
|
+
metadata_str,
|
|
1593
|
+
info.get("source_index_db")
|
|
1594
|
+
))
|
|
1595
|
+
|
|
1596
|
+
if all_chunk_metadata:
|
|
1597
|
+
splade_index.add_chunks_metadata_batch(all_chunk_metadata)
|
|
1598
|
+
splade_chunks_count = len(all_chunk_metadata)
|
|
1599
|
+
|
|
1600
|
+
# Set metadata
|
|
1601
|
+
splade_index.set_metadata(
|
|
1602
|
+
model_name=splade_encoder.model_name,
|
|
1603
|
+
vocab_size=splade_encoder.vocab_size
|
|
1604
|
+
)
|
|
1605
|
+
|
|
1606
|
+
splade_index.close()
|
|
1607
|
+
splade_success = True
|
|
1608
|
+
|
|
1609
|
+
if progress_callback:
|
|
1610
|
+
progress_callback(f"SPLADE index created: {len(all_postings)} postings, {splade_chunks_count} chunks")
|
|
1611
|
+
|
|
1612
|
+
else:
|
|
1613
|
+
if progress_callback:
|
|
1614
|
+
progress_callback(f"SPLADE not available, skipping sparse index: {err}")
|
|
1615
|
+
|
|
1616
|
+
except Exception as e:
|
|
1617
|
+
logger.warning("SPLADE encoding failed: %s", e)
|
|
1618
|
+
if progress_callback:
|
|
1619
|
+
progress_callback(f"SPLADE encoding failed: {e}")
|
|
1620
|
+
|
|
1621
|
+
elapsed_time = time.time() - start_time
|
|
1622
|
+
|
|
1623
|
+
# Cleanup
|
|
1624
|
+
try:
|
|
1625
|
+
_cleanup_fastembed_resources()
|
|
1626
|
+
gc.collect()
|
|
1627
|
+
except Exception:
|
|
1628
|
+
pass
|
|
1629
|
+
|
|
1630
|
+
return {
|
|
1631
|
+
"success": True,
|
|
1632
|
+
"result": {
|
|
1633
|
+
"chunks_created": total_chunks_created,
|
|
1634
|
+
"files_processed": total_files_processed,
|
|
1635
|
+
"files_failed": len(failed_files),
|
|
1636
|
+
"elapsed_time": elapsed_time,
|
|
1637
|
+
"model_profile": model_profile,
|
|
1638
|
+
"model_name": embedder.model_name,
|
|
1639
|
+
"central_index_path": str(central_hnsw_path),
|
|
1640
|
+
"failed_files": failed_files[:5],
|
|
1641
|
+
"splade_success": splade_success,
|
|
1642
|
+
"splade_chunks": splade_chunks_count,
|
|
1643
|
+
"binary_success": binary_success,
|
|
1644
|
+
"binary_count": binary_count,
|
|
1645
|
+
},
|
|
1646
|
+
}
|
|
1647
|
+
|
|
1648
|
+
|
|
896
1649
|
def get_embeddings_status(index_root: Path) -> Dict[str, any]:
|
|
897
1650
|
"""Get comprehensive embeddings coverage status for all indexes.
|
|
898
1651
|
|
|
@@ -902,7 +1655,7 @@ def get_embeddings_status(index_root: Path) -> Dict[str, any]:
|
|
|
902
1655
|
Returns:
|
|
903
1656
|
Aggregated status with coverage statistics, model info, and timestamps
|
|
904
1657
|
"""
|
|
905
|
-
index_files =
|
|
1658
|
+
index_files = _discover_index_dbs_internal(index_root)
|
|
906
1659
|
|
|
907
1660
|
if not index_files:
|
|
908
1661
|
return {
|
|
@@ -1071,7 +1824,7 @@ def scan_for_model_conflicts(
|
|
|
1071
1824
|
- conflicts: List of conflicting index paths with their configs
|
|
1072
1825
|
- indexes_with_embeddings: Count of indexes that have embeddings
|
|
1073
1826
|
"""
|
|
1074
|
-
index_files =
|
|
1827
|
+
index_files = _discover_index_dbs_internal(index_root)
|
|
1075
1828
|
|
|
1076
1829
|
if not index_files:
|
|
1077
1830
|
return {
|